From 552d33e65cfb6cd07d99e701dc222e50a20df386 Mon Sep 17 00:00:00 2001 From: Eason Date: Tue, 6 Apr 2021 10:55:51 +0800 Subject: [PATCH 1/7] luci-app-zerotier: fix iptables bug Signed-off-by: Tianling Shen --- package/lean/luci-app-zerotier/root/etc/zerotier.start | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/lean/luci-app-zerotier/root/etc/zerotier.start b/package/lean/luci-app-zerotier/root/etc/zerotier.start index 6af1931cae..b43e5f9740 100755 --- a/package/lean/luci-app-zerotier/root/etc/zerotier.start +++ b/package/lean/luci-app-zerotier/root/etc/zerotier.start @@ -22,7 +22,7 @@ echo "${zt0}" > "/tmp/zt.nif" iptables -I FORWARD -i "$i" -j ACCEPT iptables -I FORWARD -o "$i" -j ACCEPT iptables -t nat -I POSTROUTING -o "$i" -j MASQUERADE - ip_segment="$(ip route | grep "dev $i proto" | awk '{print $1}')" + ip_segment="$(ip route | grep "dev $i proto kernel" | awk '{print $1}')" iptables -t nat -I POSTROUTING -s "${ip_segment}" -j MASQUERADE done } From 4b855e35fc7e5b595dca93a18742f430fd33df0e Mon Sep 17 00:00:00 2001 From: AmadeusGhost <42570690+AmadeusGhost@users.noreply.github.com> Date: Wed, 7 Apr 2021 11:26:01 +0800 Subject: [PATCH 2/7] sunxi/h5: set max cpu freq to 1296MHz --- .../025-arm64-dts-allwinner-h5-Add-CPU-OPP-table.patch | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/target/linux/sunxi/patches-4.19/025-arm64-dts-allwinner-h5-Add-CPU-OPP-table.patch b/target/linux/sunxi/patches-4.19/025-arm64-dts-allwinner-h5-Add-CPU-OPP-table.patch index 3e7ef4b978..8e231c0795 100644 --- a/target/linux/sunxi/patches-4.19/025-arm64-dts-allwinner-h5-Add-CPU-OPP-table.patch +++ b/target/linux/sunxi/patches-4.19/025-arm64-dts-allwinner-h5-Add-CPU-OPP-table.patch @@ -31,7 +31,7 @@ new file mode 100644 index 0000000000000..b2657201957eb --- /dev/null +++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-cpu-opp.dtsi -@@ -0,0 +1,91 @@ +@@ -0,0 +1,97 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +// Copyright (C) 2020 Chen-Yu Tsai + @@ -105,6 +105,12 @@ index 0000000000000..b2657201957eb + opp-microvolt = <1300000 1300000 1310000>; + clock-latency-ns = <244144>; /* 8 32k periods */ + }; ++ ++ opp-1296000000 { ++ opp-hz = /bits/ 64 <1296000000>; ++ opp-microvolt = <1300000 1300000 1310000>; ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ }; + }; +}; + From d6dd580d60c4dd39d47f2b72915f8dc5b44346e1 Mon Sep 17 00:00:00 2001 From: AmadeusGhost <42570690+AmadeusGhost@users.noreply.github.com> Date: Thu, 8 Apr 2021 09:28:05 +0800 Subject: [PATCH 3/7] rtl8812au-ac: update to latest git HEAD --- package/kernel/rtl8812au-ac/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/kernel/rtl8812au-ac/Makefile b/package/kernel/rtl8812au-ac/Makefile index 43d834efcc..268d5c82fa 100644 --- a/package/kernel/rtl8812au-ac/Makefile +++ b/package/kernel/rtl8812au-ac/Makefile @@ -16,9 +16,9 @@ PKG_RELEASE:=1 PKG_SOURCE_URL:=https://github.com/aircrack-ng/rtl8812au.git PKG_SOURCE_PROTO:=git -PKG_SOURCE_DATE:=2021-02-03 -PKG_SOURCE_VERSION:=b65dcf4105641716d16f3a6c96507fdd9c1862b4 -PKG_MIRROR_HASH:=5416d4a6e671c6b07f44f35fae54662baef71f448c4be4ade58bf7fc5ca4f192 +PKG_SOURCE_DATE:=2021-03-27 +PKG_SOURCE_VERSION:=c0ce81745eb3471a639f0efd4d556975153c666e +PKG_MIRROR_HASH:=7def015c5b4c089d1376f0d31c64b8d52cd4b3aa94448333edf3682d60f891cf PKG_LICENSE:=GPL-2.0 PKG_LICENSE_FILES:=LICENSE From 6fa070f11ad680ff07386f2e798c1b7806dcf954 Mon Sep 17 00:00:00 2001 From: Beginner <70857188+Beginner-Go@users.noreply.github.com> Date: Fri, 9 Apr 2021 23:29:46 +0800 Subject: [PATCH 4/7] v2ray-core: update to 4.37.2 --- package/lean/v2ray/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/lean/v2ray/Makefile b/package/lean/v2ray/Makefile index ac7bfd1e4c..4a80d149ad 100644 --- a/package/lean/v2ray/Makefile +++ b/package/lean/v2ray/Makefile @@ -9,13 +9,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=v2ray -PKG_VERSION:=4.37.1 +PKG_VERSION:=4.37.2 PKG_RELEASE:=1 PKG_BUILD_DIR:=$(BUILD_DIR)/v2ray-core-$(PKG_VERSION) PKG_SOURCE:=v2ray-core-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/v2fly/v2ray-core/tar.gz/v$(PKG_VERSION)? -PKG_HASH:=45b8e977477e586c5b3d54b2f7f92c013fd7e88a407237b8f9701a350b706aef +PKG_HASH:=ece74b2f0e04d9cd487d1b4d79010f0269b6ee0742aaeb147979e5b97639ffa3 PKG_LICENSE:=MIT PKG_LICENSE_FILES:=LICENSE From cc2d67aa771400c817ee4ff7c1ca0bfa2c280b63 Mon Sep 17 00:00:00 2001 From: lichao0223 Date: Sat, 10 Apr 2021 08:40:02 +0800 Subject: [PATCH 5/7] uugamebooster: Update to 2.10.0 Signed-off-by: Tianling Shen --- package/lean/uugamebooster/Makefile | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/package/lean/uugamebooster/Makefile b/package/lean/uugamebooster/Makefile index 925fc84676..37e53d3de5 100644 --- a/package/lean/uugamebooster/Makefile +++ b/package/lean/uugamebooster/Makefile @@ -12,8 +12,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=uugamebooster -PKG_VERSION:=v2.9.0 -PKG_RELEASE:=7 +PKG_VERSION:=v2.10.0 +PKG_RELEASE:=8 include $(INCLUDE_DIR)/package.mk @@ -31,27 +31,27 @@ endef ifeq ($(ARCH),x86_64) UU_ARCH:=x86_64 - PKG_MD5SUM:=136c6e63745b385ab986df60ff8b2ff0 + PKG_MD5SUM:=a856aebe19b9c663bdc08b257a591b40 endif ifeq ($(ARCH),mipsel) UU_ARCH:=mipsel - PKG_MD5SUM:=7bec7f1df806d511f93e90e677aa830a + PKG_MD5SUM:=90e895012e5a03391a0c0f4759a4422c endif ifeq ($(ARCH),mips) UU_ARCH:=mipsel - PKG_MD5SUM:=7bec7f1df806d511f93e90e677aa830a + PKG_MD5SUM:=90e895012e5a03391a0c0f4759a4422c endif ifeq ($(ARCH),arm) UU_ARCH:=arm - PKG_MD5SUM:=ceefdf84f8ce3e1eb87d22200373900a + PKG_MD5SUM:=acc7e564b1718009cd2d94335ace1bcd endif ifeq ($(ARCH),aarch64) UU_ARCH:=aarch64 - PKG_MD5SUM:=a4c82d58416aa604c143053023aca71d + PKG_MD5SUM:=262cc28ba07d7cf84a3f487ff4fd146c endif PKG_SOURCE_URL:=http://uu.gdl.netease.com/openwrt-$(UU_ARCH)/$(PKG_VERSION)/uu.tar.gz? From 6214af00d090e9ab55566934fb8e10213742926b Mon Sep 17 00:00:00 2001 From: Tianling Shen Date: Sat, 10 Apr 2021 14:26:35 +0800 Subject: [PATCH 6/7] lienol: move packages to `packages` feed Signed-off-by: Tianling Shen --- package/lienol/dns-forwarder/Makefile | 56 -------------- .../dns-forwarder/files/dns-forwarder.config | 6 -- .../dns-forwarder/files/dns-forwarder.init | 46 ------------ package/lienol/dns2socks/Makefile | 57 -------------- package/lienol/ipt2socks/Makefile | 43 ----------- package/lienol/redsocks2/Makefile | 52 ------------- .../lienol/redsocks2/files/redsocks2.template | 33 -------- package/lienol/tcping/Makefile | 40 ---------- .../tcping/patches/001-Restone-staff.patch | 10 --- .../tcping/patches/002-Remove-strip.patch | 13 ---- package/lienol/trojan-go/Makefile | 75 ------------------- package/lienol/trojan-plus/Makefile | 70 ----------------- package/lienol/trojan/Makefile | 68 ----------------- .../patches/001-force-openssl-version.patch | 11 --- 14 files changed, 580 deletions(-) delete mode 100644 package/lienol/dns-forwarder/Makefile delete mode 100644 package/lienol/dns-forwarder/files/dns-forwarder.config delete mode 100755 package/lienol/dns-forwarder/files/dns-forwarder.init delete mode 100644 package/lienol/dns2socks/Makefile delete mode 100644 package/lienol/ipt2socks/Makefile delete mode 100644 package/lienol/redsocks2/Makefile delete mode 100644 package/lienol/redsocks2/files/redsocks2.template delete mode 100644 package/lienol/tcping/Makefile delete mode 100644 package/lienol/tcping/patches/001-Restone-staff.patch delete mode 100644 package/lienol/tcping/patches/002-Remove-strip.patch delete mode 100644 package/lienol/trojan-go/Makefile delete mode 100644 package/lienol/trojan-plus/Makefile delete mode 100644 package/lienol/trojan/Makefile delete mode 100644 package/lienol/trojan/patches/001-force-openssl-version.patch diff --git a/package/lienol/dns-forwarder/Makefile b/package/lienol/dns-forwarder/Makefile deleted file mode 100644 index 95e744f3f8..0000000000 --- a/package/lienol/dns-forwarder/Makefile +++ /dev/null @@ -1,56 +0,0 @@ -# -# Copyright (C) 2015 OpenWrt-dist -# Copyright (C) 2015 Jian Chang -# -# Copyright (C) 2021 ImmortalWrt -# -# -# This is free software, licensed under the GNU General Public License v3. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=dns-forwarder -PKG_VERSION:=1.2.1 -PKG_RELEASE:=2 - -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://github.com/aa65535/hev-dns-forwarder.git -PKG_SOURCE_DATE:=2017-07-21 -PKG_SOURCE_VERSION:=289e8c9c7167200668dff83b1e0cbce258665387 -PKG_MIRROR_HASH:=a06f61c2b87f61cf68517d3b4a23439366f3c806dd736594a814ee0245adca43 - -PKG_LICENSE:=GPLv3 -PKG_LICENSE_FILES:=LICENSE -PKG_MAINTAINER:=Jian Chang - -PKG_BUILD_PARALLEL:=1 - -include $(INCLUDE_DIR)/package.mk - -define Package/dns-forwarder - SECTION:=net - CATEGORY:=Network - TITLE:=Forwarding DNS queries on TCP transport - URL:=https://github.com/aa65535/hev-dns-forwarder -endef - -define Package/dns-forwarder/description - Forwarding DNS queries on TCP transport. -endef - -define Package/dns-forwarder/conffiles -/etc/config/dns-forwarder -endef - -define Package/dns-forwarder/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/hev-dns-forwarder $(1)/usr/bin/dns-forwarder - $(INSTALL_DIR) $(1)/etc/config - $(INSTALL_DATA) ./files/dns-forwarder.config $(1)/etc/config/dns-forwarder - $(INSTALL_DIR) $(1)/etc/init.d - $(INSTALL_BIN) ./files/dns-forwarder.init $(1)/etc/init.d/dns-forwarder -endef - -$(eval $(call BuildPackage,dns-forwarder)) diff --git a/package/lienol/dns-forwarder/files/dns-forwarder.config b/package/lienol/dns-forwarder/files/dns-forwarder.config deleted file mode 100644 index 852fec2870..0000000000 --- a/package/lienol/dns-forwarder/files/dns-forwarder.config +++ /dev/null @@ -1,6 +0,0 @@ - -config dns-forwarder - option enable '0' - option listen_addr '0.0.0.0' - option listen_port '5300' - option dns_servers '8.8.8.8' diff --git a/package/lienol/dns-forwarder/files/dns-forwarder.init b/package/lienol/dns-forwarder/files/dns-forwarder.init deleted file mode 100755 index e6fbb5d3a6..0000000000 --- a/package/lienol/dns-forwarder/files/dns-forwarder.init +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/sh /etc/rc.common -# -# Copyright (C) 2016 Jian Chang -# -# This is free software, licensed under the GNU General Public License v3. -# See /LICENSE for more information. -# - -START=75 - -USE_PROCD=1 - -append_parm() { - local section="$1" - local option="$2" - local switch="$3" - local default="$4" - local _loctmp - config_get _loctmp "$section" "$option" - [ -n "$_loctmp" -o -n "$default" ] || return 0 - procd_append_param command "$switch" "${_loctmp:-$default}" -} - -start_instance() { - local enable - config_get_bool enable $1 enable - [ "$enable" = 1 ] || return 0 - - procd_open_instance - procd_set_param respawn - procd_set_param stderr 1 - procd_set_param command /usr/bin/dns-forwarder - append_parm $1 listen_addr "-b" - append_parm $1 listen_port "-p" - append_parm $1 dns_servers "-s" - procd_close_instance -} - -start_service() { - config_load dns-forwarder - config_foreach start_instance dns-forwarder -} - -service_triggers() { - procd_add_reload_trigger "dns-forwarder" -} diff --git a/package/lienol/dns2socks/Makefile b/package/lienol/dns2socks/Makefile deleted file mode 100644 index 29f1258a22..0000000000 --- a/package/lienol/dns2socks/Makefile +++ /dev/null @@ -1,57 +0,0 @@ -# -# Copyright (C) 2021 ImmortalWrt -# -# -# This is free software, licensed under the GNU General Public License v3. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=dns2socks -PKG_VERSION:=2.1 -PKG_RELEASE:=2 - -PKG_SOURCE:=SourceCode.zip -PKG_SOURCE_URL:=@SF/dns2socks -PKG_SOURCE_DATE:=2020-02-18 -PKG_HASH:=406b5003523577d39da66767adfe54f7af9b701374363729386f32f6a3a995f4 - -PKG_MAINTAINER:=ghostmaker -PKG_LICENSE:=BSD-3-Clause -PKG_LICENSE_FILE:=LICENSE - -include $(INCLUDE_DIR)/package.mk - -define Package/dns2socks - SECTION:=net - CATEGORY:=Network - SUBMENU:=IP Addresses and Names - TITLE:=The utility to resolve DNS requests via a SOCKS5 tunnel. - URL:=http://dns2socks.sourceforge.net/ - MAINTAINER:=ghostmaker - DEPENDS:=+libpthread -endef - -define Package/dns2socks/description - This is a utility to resolve DNS requests via a SOCKS5 tunnel and caches the answers. -endef - -UNZIP_CMD:=unzip -q -d $(PKG_BUILD_DIR) $(DL_DIR)/$(PKG_SOURCE) - -define Build/Compile - $(TARGET_CC) \ - $(TARGET_CFLAGS) \ - $(TARGET_CPPFLAGS) \ - $(FPIC) \ - -o $(PKG_BUILD_DIR)/DNS2SOCKS/dns2socks \ - $(PKG_BUILD_DIR)/DNS2SOCKS/DNS2SOCKS.c \ - $(TARGET_LDFLAGS) -pthread -endef - -define Package/dns2socks/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/DNS2SOCKS/dns2socks $(1)/usr/bin/dns2socks -endef - -$(eval $(call BuildPackage,dns2socks)) diff --git a/package/lienol/ipt2socks/Makefile b/package/lienol/ipt2socks/Makefile deleted file mode 100644 index a7625d5031..0000000000 --- a/package/lienol/ipt2socks/Makefile +++ /dev/null @@ -1,43 +0,0 @@ -# -# Copyright (C) 2021 ImmortalWrt -# -# -# This is free software, licensed under the GNU General Public License v3. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=ipt2socks -PKG_VERSION:=1.1.3 -PKG_RELEASE:=2 - -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz -PKG_SOURCE_URL:=https://codeload.github.com/zfl9/ipt2socks/tar.gz/v$(PKG_VERSION)? -PKG_HASH:=73a2498dc95934c225d358707e7f7d060b5ce81aa45260ada09cbd15207d27d1 - -PKG_BUILD_PARALLEL:=1 -PKG_INSTALL:=1 - -PKG_LICENSE:=AGPL-3.0 -PKG_LICENSE_FILE:=LICENSE - -include $(INCLUDE_DIR)/package.mk - -define Package/ipt2socks - SECTION:=net - CATEGORY:=Network - TITLE:=Utility for converting iptables (REDIRECT/TPROXY) to SOCKS5 - URL:=https://github.com/zfl9/ipt2socks - DEPENDS:=+libpthread -endef - -TARGET_CFLAGS += $(FPIC) -flto -TARGET_LDFLAGS += -flto - -define Package/ipt2socks/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/ipt2socks $(1)/usr/bin -endef - -$(eval $(call BuildPackage,ipt2socks)) diff --git a/package/lienol/redsocks2/Makefile b/package/lienol/redsocks2/Makefile deleted file mode 100644 index 2bbcd8f072..0000000000 --- a/package/lienol/redsocks2/Makefile +++ /dev/null @@ -1,52 +0,0 @@ -# -# Copyright (C) 2021 ImmortalWrt -# -# -# This is free software, licensed under the GNU General Public License v3. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=redsocks2 -PKG_VERSION:=0.67 -PKG_RELEASE:=5 - -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://github.com/semigodking/redsocks.git -PKG_SOURCE_DATE:=2020-05-10 -PKG_SOURCE_VERSION:=d94c245ea47859cda5b4b7373308589206b97bdc -PKG_MIRROR_HASH:=5ca32b2f849af7ebda2cab90bbe286bfd97a69de1a85dac09c8df2fbdd8c947c - -PKG_MAINTAINER:=semigodking -PKG_LICENSE:=Apache-2.0 -PKG_LICENSE_FILE:=LICENSE - -PKG_BUILD_PARALLEL:=1 - -include $(INCLUDE_DIR)/package.mk - -define Package/redsocks2 - SECTION:=net - CATEGORY:=Network - TITLE:=Redirect any TCP connection to a SOCKS or HTTPS proxy server - URL:=https://github.com/semigodking/redsocks - DEPENDS:=+libevent2 +libopenssl -endef - -define Package/redsocks2/description - This is a modified version of original redsocks. - The name is changed to be REDSOCKS2 since this release to distinguish with original redsocks. - This variant is useful for anti-GFW (Great Fire Wall). -endef - -MAKE_VARS += DISABLE_SHADOWSOCKS=true - -define Package/redsocks2/install - $(INSTALL_DIR) $(1)/usr/sbin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/redsocks2 $(1)/usr/sbin - $(INSTALL_DIR) $(1)/etc/redsocks2 - $(INSTALL_DATA) ./files/redsocks2.template $(1)/etc/redsocks2/config.template -endef - -$(eval $(call BuildPackage,redsocks2)) diff --git a/package/lienol/redsocks2/files/redsocks2.template b/package/lienol/redsocks2/files/redsocks2.template deleted file mode 100644 index ba494267e8..0000000000 --- a/package/lienol/redsocks2/files/redsocks2.template +++ /dev/null @@ -1,33 +0,0 @@ -base { - log_debug = off; - redirector = iptables; - reuseport = on; -} -redsocks { - local_ip = 192.168.1.1; - local_port = 1081; - ip = 192.168.1.1; - port = 9050; - type = socks5; // I use socks5 proxy for GFW'ed IP - autoproxy = 1; // I want autoproxy feature enabled on this section. - // timeout is meaningful when 'autoproxy' is non-zero. - // It specified timeout value when trying to connect to destination - // directly. Default is 10 seconds. When it is set to 0, default - // timeout value will be used. - // NOTE: decreasing the timeout value may lead increase of chance for - // normal IP to be misjudged. - timeout = 13; - //type = http-connect; - //login = username; - //password = passwd; -} -tcpdns { - // Transform UDP DNS requests into TCP DNS requests. - // You can also redirect connections to external TCP DNS server to - // REDSOCKS transparent proxy via iptables. - local_ip = 192.168.1.1; // Local server to act as DNS server - local_port = 1053; // UDP port to receive UDP DNS requests - tcpdns1 = 8.8.4.4; // DNS server that supports TCP DNS requests - tcpdns2 = 8.8.8.8; // DNS server that supports TCP DNS requests - timeout = 4; // Timeout value for TCP DNS requests -} diff --git a/package/lienol/tcping/Makefile b/package/lienol/tcping/Makefile deleted file mode 100644 index ff9ab1a42e..0000000000 --- a/package/lienol/tcping/Makefile +++ /dev/null @@ -1,40 +0,0 @@ -# -# Copyright (C) 2021 ImmortalWrt -# -# -# This is free software, licensed under the GNU General Public License v3. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=tcping -PKG_VERSION:=0.3 -PKG_RELEASE:=2 - -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://github.com/Mattraks/tcping.git -PKG_SOURCE_DATE:=2020-11-18 -PKG_SOURCE_VERSION:=de2b709f8c386507678041d11102c671d470fea7 -PKG_MIRROR_HASH:=07359ac47f0da4fb30215e5160f7c0c942f0a4af4e7b2e2d2b4ffd9769823054 - -PKG_LICENSE:=GPL-2.0 -PKG_LICENSE_FILE:=LICENSE - -PKG_BUILD_PARALLEL:=1 - -include $(INCLUDE_DIR)/package.mk - -define Package/tcping - SECTION:=net - CATEGORY:=Network - TITLE:=tcping measures the latency of a tcp-connection - URL:=https://github.com/jlyo/tcping -endef - -define Package/tcping/install - $(INSTALL_DIR) $(1)/usr/sbin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/tcping $(1)/usr/sbin -endef - -$(eval $(call BuildPackage,tcping)) diff --git a/package/lienol/tcping/patches/001-Restone-staff.patch b/package/lienol/tcping/patches/001-Restone-staff.patch deleted file mode 100644 index 36e8f25d1b..0000000000 --- a/package/lienol/tcping/patches/001-Restone-staff.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/main.c -+++ b/main.c -@@ -14,6 +14,7 @@ static volatile int stop = 0; - - void usage(void) - { -+ fprintf(stderr, "tcping, (C) 2003 folkert@vanheusden.com\n\n"); - fprintf(stderr, "Usage\n"); - fprintf(stderr, "tcping [options] \n\n"); - fprintf(stderr, "Options:\n"); diff --git a/package/lienol/tcping/patches/002-Remove-strip.patch b/package/lienol/tcping/patches/002-Remove-strip.patch deleted file mode 100644 index 16881fce8a..0000000000 --- a/package/lienol/tcping/patches/002-Remove-strip.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/Makefile b/Makefile -index 1778ebf..e44119e 100644 ---- a/Makefile -+++ b/Makefile -@@ -9,7 +9,7 @@ all: tcping - - tcping: $(OBJS) - $(CC) $(OBJS) $(LDFLAGS) -o tcping -- strip tcping -+ - - install: tcping - cp tcping $(DESTDIR)/usr/bin diff --git a/package/lienol/trojan-go/Makefile b/package/lienol/trojan-go/Makefile deleted file mode 100644 index b57b08a939..0000000000 --- a/package/lienol/trojan-go/Makefile +++ /dev/null @@ -1,75 +0,0 @@ -# Copyright (C) 2020 Lienol -# -# This is free software, licensed under the GNU General Public License v3. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=trojan-go -PKG_VERSION:=0.8.3 -PKG_RELEASE:=1 - -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz -PKG_SOURCE_URL:=https://codeload.github.com/p4gefau1t/trojan-go/tar.gz/v$(PKG_VERSION)? -PKG_HASH:=dbfb536328327bcbbd310b7289ece47d40dcc6aaf7996b563f0e1041e120fb89 - -PKG_CONFIG_DEPENDS:= \ - CONFIG_TROJAN_GO_COMPRESS_GOPROXY \ - CONFIG_TROJAN_GO_COMPRESS_UPX - -PKG_BUILD_DEPENDS:=golang/host -PKG_BUILD_PARALLEL:=1 -PKG_USE_MIPS16:=0 - -GO_PKG:=github.com/p4gefau1t/trojan-go -GO_PKG_BUILD_PKG:=$$(GO_PKG) - -GO_PKG_TAGS:=full -GO_PKG_LDFLAGS:=-s -w -GO_PKG_LDFLAGS_X:= \ - $(GO_PKG)/constant.Version=$(PKG_VERSION) \ - $(GO_PKG)/constant.Commit=v$(PKG_VERSION) - -include $(INCLUDE_DIR)/package.mk -include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk - -define Package/$(PKG_NAME) - SECTION:=net - CATEGORY:=Network - SUBMENU:=Web Servers/Proxies - DEPENDS:=$$(GO_ARCH_DEPENDS) - TITLE:=An unidentifiable mechanism that helps you bypass GFW. It's compatible with original trojan with experimental features. - URL:=https://github.com/p4gefau1t/trojan-go -endef - -define Package/$(PKG_NAME)/config - -menu "Configuration" - depends on PACKAGE_$(PKG_NAME) - -config TROJAN_GO_COMPRESS_GOPROXY - bool "Compiling with GOPROXY proxy" - default n - -config TROJAN_GO_COMPRESS_UPX - bool "Compress executable files with UPX" - default y - -endmenu - -endef - -ifeq ($(CONFIG_TROJAN_GO_COMPRESS_GOPROXY),y) -export GO111MODULE=on -export GOPROXY=https://goproxy.io -endif - -define Build/Compile - $(call GoPackage/Build/Compile) -ifeq ($(CONFIG_TROJAN_GO_COMPRESS_UPX),y) - $(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DIR)/$(PKG_NAME) -endif -endef - -$(eval $(call GoBinPackage,$(PKG_NAME))) -$(eval $(call BuildPackage,$(PKG_NAME))) diff --git a/package/lienol/trojan-plus/Makefile b/package/lienol/trojan-plus/Makefile deleted file mode 100644 index c394a4fe32..0000000000 --- a/package/lienol/trojan-plus/Makefile +++ /dev/null @@ -1,70 +0,0 @@ -# -# Copyright (C) 2018-2019 wongsyrone -# -# This is free software, licensed under the GNU General Public License v3. -# See /LICENSE for more information. -# -include $(TOPDIR)/rules.mk - -PKG_NAME:=trojan-plus -PKG_VERSION:=10.0.3 -PKG_RELEASE:=2 - -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://github.com/peter-tank/trojan-plus.git -PKG_SOURCE_DATE:=2020-09-06 -PKG_SOURCE_VERSION:=a6394cdd718669b0c7491493a78e61f6f0f899b3 -PKG_MIRROR_HASH:=2d37d09fe6d39d7981116ad387706f58f2b30b74a34e27fc5608f267dacc9208 - -PKG_BUILD_PARALLEL:=1 -PKG_BUILD_DEPENDS:=openssl - -PKG_LICENSE:=GPL-3.0 -PKG_LICENSE_FILE:=LICENSE -PKG_MAINTAINER:=Trojan-Plus-Group - -include $(INCLUDE_DIR)/package.mk -include $(INCLUDE_DIR)/cmake.mk - -TARGET_CXXFLAGS += -Wall -Wextra -TARGET_CXXFLAGS += $(FPIC) - -# LTO -TARGET_CXXFLAGS += -flto -TARGET_LDFLAGS += -flto - -# CXX standard -TARGET_CXXFLAGS += -std=c++11 -TARGET_CXXFLAGS := $(filter-out -O%,$(TARGET_CXXFLAGS)) -O3 -TARGET_CXXFLAGS += -ffunction-sections -fdata-sections -TARGET_LDFLAGS += -Wl,--gc-sections - -CMAKE_OPTIONS += \ - -DENABLE_MYSQL=OFF \ - -DENABLE_NAT=ON \ - -DENABLE_REUSE_PORT=ON \ - -DENABLE_SSL_KEYLOG=ON \ - -DENABLE_TLS13_CIPHERSUITES=ON \ - -DFORCE_TCP_FASTOPEN=OFF \ - -DSYSTEMD_SERVICE=OFF \ - -DOPENSSL_USE_STATIC_LIBS=FALSE \ - -DBoost_DEBUG=ON \ - -DBoost_NO_BOOST_CMAKE=ON - -define Package/trojan-plus - SECTION:=net - CATEGORY:=Network - TITLE:=An unidentifiable mechanism that helps you bypass GFW. It's compatible with original trojan with experimental features. - URL:=https://github.com/Trojan-Plus-Group/trojan-plus - DEPENDS:= \ - +libpthread +libstdcpp +libopenssl \ - +boost +boost-system +boost-program_options -endef - -define Package/trojan-plus/install - $(INSTALL_DIR) $(1)/usr/sbin - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/trojan $(1)/usr/sbin/trojan-plus -endef - -$(eval $(call BuildPackage,trojan-plus)) - diff --git a/package/lienol/trojan/Makefile b/package/lienol/trojan/Makefile deleted file mode 100644 index 4c8bddcbd1..0000000000 --- a/package/lienol/trojan/Makefile +++ /dev/null @@ -1,68 +0,0 @@ -# -# Copyright (C) 2018-2019 wongsyrone -# -# This is free software, licensed under the GNU General Public License v3. -# See /LICENSE for more information. -# -include $(TOPDIR)/rules.mk - -PKG_NAME:=trojan -PKG_VERSION:=1.16.0 -PKG_RELEASE:=2 - -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz -PKG_SOURCE_URL:=https://codeload.github.com/trojan-gfw/trojan/tar.gz/v$(PKG_VERSION)? -PKG_HASH:=86cdb2685bb03a63b62ce06545c41189952f1ec4a0cd9147450312ed70956cbc - -PKG_BUILD_PARALLEL:=1 -PKG_BUILD_DEPENDS:=openssl - -PKG_LICENSE:=GPL-3.0 -PKG_LICENSE_FILE:=LICENSE -PKG_MAINTAINER:=GreaterFire - -include $(INCLUDE_DIR)/package.mk -include $(INCLUDE_DIR)/cmake.mk - -TARGET_CXXFLAGS += -Wall -Wextra -TARGET_CXXFLAGS += $(FPIC) - -# LTO -TARGET_CXXFLAGS += -flto -TARGET_LDFLAGS += -flto - -# CXX standard -TARGET_CXXFLAGS += -std=c++11 -TARGET_CXXFLAGS := $(filter-out -O%,$(TARGET_CXXFLAGS)) -O3 -TARGET_CXXFLAGS += -ffunction-sections -fdata-sections -TARGET_LDFLAGS += -Wl,--gc-sections - -CMAKE_OPTIONS += \ - -DENABLE_MYSQL=OFF \ - -DENABLE_NAT=ON \ - -DENABLE_REUSE_PORT=ON \ - -DENABLE_SSL_KEYLOG=ON \ - -DENABLE_TLS13_CIPHERSUITES=ON \ - -DFORCE_TCP_FASTOPEN=OFF \ - -DSYSTEMD_SERVICE=OFF \ - -DOPENSSL_USE_STATIC_LIBS=FALSE \ - -DBoost_DEBUG=ON \ - -DBoost_NO_BOOST_CMAKE=ON - -define Package/trojan - SECTION:=net - CATEGORY:=Network - TITLE:=An unidentifiable mechanism that helps you bypass GFW - URL:=https://github.com/trojan-gfw/trojan - DEPENDS:= \ - +libpthread +libstdcpp +libopenssl \ - +boost +boost-system +boost-program_options +boost-date_time -endef - -define Package/trojan/install - $(INSTALL_DIR) $(1)/usr/sbin - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/trojan $(1)/usr/sbin/trojan -endef - -$(eval $(call BuildPackage,trojan)) - diff --git a/package/lienol/trojan/patches/001-force-openssl-version.patch b/package/lienol/trojan/patches/001-force-openssl-version.patch deleted file mode 100644 index 7ee8f631cc..0000000000 --- a/package/lienol/trojan/patches/001-force-openssl-version.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -43,7 +43,7 @@ if(MSVC) - add_definitions(-DBOOST_DATE_TIME_NO_LIB) - endif() - --find_package(OpenSSL 1.1.0 REQUIRED) -+find_package(OpenSSL 1.1.1 REQUIRED) - include_directories(${OPENSSL_INCLUDE_DIR}) - target_link_libraries(trojan ${OPENSSL_LIBRARIES}) - if(OPENSSL_VERSION VERSION_GREATER_EQUAL 1.1.1) From f703f8937ccbd707e6637d099f076e5555d79078 Mon Sep 17 00:00:00 2001 From: Tianling Shen Date: Sat, 10 Apr 2021 14:37:37 +0800 Subject: [PATCH 7/7] lienol: move LuCI apps to `luci` feed Signed-off-by: Tianling Shen --- package/lienol/luci-app-brook-server/Makefile | 19 - .../luasrc/controller/brook_server.lua | 72 - .../model/cbi/brook_server/api/brook.lua | 338 - .../luasrc/model/cbi/brook_server/config.lua | 32 - .../luasrc/model/cbi/brook_server/index.lua | 66 - .../luasrc/view/brook_server/brook.htm | 168 - .../luasrc/view/brook_server/log.htm | 31 - .../view/brook_server/users_list_status.htm | 23 - .../luasrc/view/brook_server/users_status.htm | 3 - .../po/zh-cn/brook_server.po | 83 - .../root/etc/config/brook_server | 12 - .../root/etc/init.d/brook_server | 63 - .../etc/uci-defaults/luci-app-brook-server | 21 - .../usr/share/brook_server/firewall.include | 39 - .../lienol/luci-app-fileassistant/Makefile | 14 - .../resources/fileassistant/fb.css | 68 - .../luci-static/resources/fileassistant/fb.js | 288 - .../resources/fileassistant/file-icon.png | Bin 1098 -> 0 bytes .../resources/fileassistant/folder-icon.png | Bin 1292 -> 0 bytes .../resources/fileassistant/link-icon.png | Bin 1622 -> 0 bytes .../luasrc/controller/fileassistant.lua | 230 - .../luasrc/view/fileassistant.htm | 20 - .../Makefile | 16 - .../luasrc/controller/ipsec-server.lua | 24 - .../model/cbi/ipsec-server/settings.lua | 105 - .../luasrc/model/cbi/ipsec-server/users.lua | 18 - .../luasrc/view/ipsec-server/index.htm | 13 - .../luasrc/view/ipsec-server/status.htm | 3 - .../po/zh-cn/ipsec.po | 50 - .../root/etc/config/ipsec | 12 - .../root/etc/init.d/ipsecvpn | 68 - .../luci-app-ipsec-vpnserver-manyusers | 23 - .../root/usr/share/ipsecvpn/firewall.include | 39 - package/lienol/luci-app-nginx-pingos/Makefile | 98 - .../luasrc/controller/pingos.lua | 17 - .../luasrc/model/cbi/pingos.lua | 68 - .../luasrc/view/pingos/status.htm | 52 - .../modules/nginx-client-module/COPYRIGHT | 24 - .../modules/nginx-client-module/config | 19 - .../modules/nginx-client-module/ngx_client.c | 1387 - .../modules/nginx-client-module/ngx_client.h | 165 - .../nginx-client-module/ngx_http_client.c | 1889 - .../nginx-client-module/ngx_http_client.h | 323 - .../modules/nginx-client-module/t/config | 13 - .../modules/nginx-client-module/t/nginx.conf | 57 - .../t/ngx_client_stat_module.c | 148 - .../t/ngx_client_test_module.c | 188 - .../t/ngx_http_client_test_module.c | 203 - .../nginx-client-module/t/tcpserver.go | 41 - .../modules/nginx-multiport-module/COPYRIGHT | 24 - .../modules/nginx-multiport-module/README.md | 181 - .../modules/nginx-multiport-module/config | 31 - .../doc/ngx-http-broadcast-module.md | 77 - .../doc/ngx-stream-zone-module.md | 92 - .../ngx_event_multiport_module.c | 1018 - .../ngx_http_broadcast_module.c | 263 - .../ngx_http_inner_proxy_module.c | 254 - .../nginx-multiport-module/ngx_multiport.h | 53 - .../ngx_multiport_misc.c | 165 - .../ngx_process_slot_module.c | 167 - .../ngx_stream_zone_module.c | 551 - .../ngx_stream_zone_module.h | 39 - .../modules/nginx-multiport-module/t/config | 12 - .../nginx-multiport-module/t/nginx.conf | 71 - .../t/ngx_multiport_test_module.c | 168 - .../t/ngx_stream_zone_test_module.c | 134 - .../nginx-multiport-module/t/ngx_test_macro.h | 41 - .../modules/nginx-rtmp-module/AUTHORS | 9 - .../modules/nginx-rtmp-module/LICENSE | 22 - .../modules/nginx-rtmp-module/config | 169 - .../dash/ngx_rtmp_dash_module.c | 1532 - .../nginx-rtmp-module/dash/ngx_rtmp_mp4.c | 1167 - .../nginx-rtmp-module/dash/ngx_rtmp_mp4.h | 52 - .../hls/ngx_rtmp_hls_module.c | 2713 - .../nginx-rtmp-module/hls/ngx_rtmp_mpegts.c | 558 - .../nginx-rtmp-module/hls/ngx_rtmp_mpegts.h | 58 - .../http/ngx_http_flv_live_module.c | 733 - .../http/ngx_http_set_header.c | 282 - .../http/ngx_http_set_header.h | 11 - .../mpegts/ngx_hls_http_module.c | 1303 - .../mpegts/ngx_hls_live_module.c | 1094 - .../mpegts/ngx_hls_live_module.h | 95 - .../mpegts/ngx_mpegts_gop_module.c | 731 - .../mpegts/ngx_mpegts_gop_module.h | 19 - .../mpegts/ngx_mpegts_http_module.c | 611 - .../mpegts/ngx_mpegts_live_module.c | 1891 - .../mpegts/ngx_mpegts_live_module.h | 29 - .../modules/nginx-rtmp-module/ngx_live.c | 449 - .../modules/nginx-rtmp-module/ngx_live.h | 42 - .../nginx-rtmp-module/ngx_live_record.c | 1307 - .../nginx-rtmp-module/ngx_live_record.h | 59 - .../nginx-rtmp-module/ngx_live_relay.c | 418 - .../nginx-rtmp-module/ngx_live_relay.h | 99 - .../ngx_live_relay_httpflv.c | 637 - .../nginx-rtmp-module/ngx_live_relay_inner.c | 399 - .../nginx-rtmp-module/ngx_live_relay_rtmp.c | 860 - .../nginx-rtmp-module/ngx_live_relay_simple.c | 460 - .../nginx-rtmp-module/ngx_live_relay_static.c | 656 - .../modules/nginx-rtmp-module/ngx_netcall.c | 205 - .../modules/nginx-rtmp-module/ngx_netcall.h | 47 - .../modules/nginx-rtmp-module/ngx_rtmp.c | 1343 - .../modules/nginx-rtmp-module/ngx_rtmp.h | 1022 - .../ngx_rtmp_access_module.c | 482 - .../modules/nginx-rtmp-module/ngx_rtmp_amf.c | 664 - .../modules/nginx-rtmp-module/ngx_rtmp_amf.h | 71 - .../nginx-rtmp-module/ngx_rtmp_bandwidth.c | 26 - .../nginx-rtmp-module/ngx_rtmp_bandwidth.h | 31 - .../nginx-rtmp-module/ngx_rtmp_bitop.c | 63 - .../nginx-rtmp-module/ngx_rtmp_bitop.h | 46 - .../nginx-rtmp-module/ngx_rtmp_cmd_module.c | 1096 - .../nginx-rtmp-module/ngx_rtmp_cmd_module.h | 166 - .../nginx-rtmp-module/ngx_rtmp_codec_module.c | 1376 - .../nginx-rtmp-module/ngx_rtmp_codec_module.h | 85 - .../ngx_rtmp_control_module.c | 922 - .../nginx-rtmp-module/ngx_rtmp_core_module.c | 1203 - .../nginx-rtmp-module/ngx_rtmp_dynamic.c | 999 - .../nginx-rtmp-module/ngx_rtmp_dynamic.h | 36 - .../modules/nginx-rtmp-module/ngx_rtmp_eval.c | 298 - .../modules/nginx-rtmp-module/ngx_rtmp_eval.h | 44 - .../nginx-rtmp-module/ngx_rtmp_exec_module.c | 1551 - .../nginx-rtmp-module/ngx_rtmp_gop_module.c | 734 - .../nginx-rtmp-module/ngx_rtmp_handler.c | 948 - .../nginx-rtmp-module/ngx_rtmp_handshake.c | 641 - .../modules/nginx-rtmp-module/ngx_rtmp_init.c | 787 - .../nginx-rtmp-module/ngx_rtmp_limit_module.c | 205 - .../nginx-rtmp-module/ngx_rtmp_live_module.c | 1108 - .../nginx-rtmp-module/ngx_rtmp_live_module.h | 66 - .../nginx-rtmp-module/ngx_rtmp_log_module.c | 1350 - .../ngx_rtmp_monitor_module.c | 458 - .../ngx_rtmp_monitor_module.h | 20 - .../ngx_rtmp_notify_module.c | 1964 - .../ngx_rtmp_notify_module.h | 19 - .../ngx_rtmp_proxy_protocol.c | 197 - .../ngx_rtmp_proxy_protocol.h | 19 - .../nginx-rtmp-module/ngx_rtmp_receive.c | 464 - .../ngx_rtmp_record_module.c | 1308 - .../ngx_rtmp_record_module.h | 96 - .../modules/nginx-rtmp-module/ngx_rtmp_send.c | 699 - .../ngx_rtmp_shared_module.c | 402 - .../nginx-rtmp-module/ngx_rtmp_stat_module.c | 754 - .../nginx-rtmp-module/ngx_rtmp_streams.h | 19 - .../ngx_rtmp_sys_stat_module.c | 170 - .../nginx-rtmp-module/ngx_rtmp_variables.c | 1578 - .../nginx-rtmp-module/ngx_rtmp_variables.h | 85 - .../nginx-rtmp-module/ngx_rtmp_version.h | 15 - .../modules/nginx-toolkit-module/COPYRIGHT | 24 - .../modules/nginx-toolkit-module/README.md | 37 - .../modules/nginx-toolkit-module/config | 47 - .../doc/ngx-dynamic-conf-module.md | 343 - .../doc/ngx-dynamic-resolver-module.md | 157 - .../doc/ngx-event-resolver-module.md | 126 - .../doc/ngx-event-timer-module.md | 112 - .../nginx-toolkit-module/doc/ngx-map.md | 112 - .../nginx-toolkit-module/doc/ngx-poold.md | 19 - .../nginx-toolkit-module/doc/ngx-rbuf.md | 40 - .../doc/ngx-toolkit-misc.md | 89 - .../nginx-toolkit-module/ngx_dynamic_conf.c | 963 - .../nginx-toolkit-module/ngx_dynamic_conf.h | 84 - .../ngx_dynamic_resolver.c | 700 - .../ngx_dynamic_resolver.h | 75 - .../nginx-toolkit-module/ngx_event_resolver.c | 281 - .../nginx-toolkit-module/ngx_event_resolver.h | 43 - .../ngx_event_timer_module.c | 271 - .../ngx_event_timer_module.h | 42 - .../nginx-toolkit-module/ngx_http_dynamic.c | 1677 - .../nginx-toolkit-module/ngx_http_dynamic.h | 31 - .../ngx_http_trace_module.c | 527 - .../modules/nginx-toolkit-module/ngx_map.c | 327 - .../modules/nginx-toolkit-module/ngx_map.h | 131 - .../modules/nginx-toolkit-module/ngx_poold.c | 190 - .../modules/nginx-toolkit-module/ngx_poold.h | 56 - .../modules/nginx-toolkit-module/ngx_rbuf.c | 292 - .../modules/nginx-toolkit-module/ngx_rbuf.h | 59 - .../modules/nginx-toolkit-module/ngx_timerd.c | 269 - .../modules/nginx-toolkit-module/ngx_timerd.h | 68 - .../nginx-toolkit-module/ngx_toolkit_misc.c | 383 - .../nginx-toolkit-module/ngx_toolkit_misc.h | 126 - .../modules/nginx-toolkit-module/t/config | 32 - .../nginx-toolkit-module/t/dns_install.sh | 7 - .../nginx-toolkit-module/t/md5testfile | 24 - .../modules/nginx-toolkit-module/t/named.conf | 25 - .../modules/nginx-toolkit-module/t/nginx.conf | 94 - .../nginx-toolkit-module/t/nginx_dynamic.conf | 74 - .../t/ngx_dynamic_conf_test_module.c | 200 - .../t/ngx_dynamic_resolver_test_module.c | 193 - .../t/ngx_event_resolver_test_module.c | 150 - .../t/ngx_event_timer_test_module.c | 151 - .../t/ngx_http_dynamic_test_module.c | 300 - .../t/ngx_map_test_module.c | 251 - .../t/ngx_poold_test_module.c | 90 - .../t/ngx_rbuf_test_module.c | 116 - .../nginx-toolkit-module/t/ngx_test_macro.h | 41 - .../t/ngx_timerd_test_module.c | 198 - .../t/ngx_toolkit_misc_test_module.c | 285 - .../nginx-toolkit-module/t/test.com.zone | 14 - .../nginx-toolkit-module/t/test1.com.zone | 14 - .../modules/nginx-ts-module/LICENSE | 22 - .../modules/nginx-ts-module/README.rst | 256 - .../modules/nginx-ts-module/config | 18 - .../nginx-ts-module/src/ngx_http_ts_module.c | 263 - .../src/ngx_stream_ts_module.c | 243 - .../modules/nginx-ts-module/src/ngx_ts_aac.c | 69 - .../modules/nginx-ts-module/src/ngx_ts_aac.h | 30 - .../modules/nginx-ts-module/src/ngx_ts_avc.c | 298 - .../modules/nginx-ts-module/src/ngx_ts_avc.h | 57 - .../modules/nginx-ts-module/src/ngx_ts_dash.c | 1426 - .../modules/nginx-ts-module/src/ngx_ts_dash.h | 134 - .../nginx-ts-module/src/ngx_ts_dash_mp4.c | 1486 - .../modules/nginx-ts-module/src/ngx_ts_hls.c | 1002 - .../modules/nginx-ts-module/src/ngx_ts_hls.h | 75 - .../nginx-ts-module/src/ngx_ts_stream.c | 1496 - .../nginx-ts-module/src/ngx_ts_stream.h | 113 - .../patches/101-feature_test_fix.patch | 116 - .../patches/102-sizeof_test_fix.patch | 27 - .../patches/103-sys_nerr.patch | 12 - .../patches/104-endianness_fix.patch | 21 - .../patches/200-config.patch | 18 - .../patches/201-ignore-invalid-options.patch | 12 - .../luci-app-nginx-pingos/po/zh-cn/pingos.po | 44 - .../root/etc/config/pingos | 11 - .../root/etc/init.d/pingos | 68 - .../root/etc/pingos.template | 209 - .../etc/uci-defaults/luci-app-nginx-pingos | 11 - .../root/resource/conf-template/nginx.conf | 205 - .../root/resource/crossdomain.xml | 4 - .../root/resource/stat.xsl | 355 - package/lienol/luci-app-passwall/Makefile | 168 - .../luasrc/controller/passwall.lua | 401 - .../luasrc/model/cbi/passwall/api/api.lua | 441 - .../luasrc/model/cbi/passwall/api/brook.lua | 152 - .../model/cbi/passwall/api/gen_naiveproxy.lua | 28 - .../cbi/passwall/api/gen_shadowsocks.lua | 46 - .../model/cbi/passwall/api/gen_trojan.lua | 85 - .../model/cbi/passwall/api/gen_xray.lua | 576 - .../model/cbi/passwall/api/gen_xray_proto.lua | 87 - .../luasrc/model/cbi/passwall/api/kcptun.lua | 201 - .../model/cbi/passwall/api/trojan_go.lua | 175 - .../luasrc/model/cbi/passwall/api/xray.lua | 175 - .../luasrc/model/cbi/passwall/client/acl.lua | 103 - .../model/cbi/passwall/client/app_update.lua | 38 - .../model/cbi/passwall/client/auto_switch.lua | 33 - .../model/cbi/passwall/client/global.lua | 386 - .../model/cbi/passwall/client/haproxy.lua | 106 - .../luasrc/model/cbi/passwall/client/log.lua | 8 - .../model/cbi/passwall/client/node_config.lua | 684 - .../model/cbi/passwall/client/node_list.lua | 111 - .../cbi/passwall/client/node_subscribe.lua | 84 - .../model/cbi/passwall/client/other.lua | 131 - .../luasrc/model/cbi/passwall/client/rule.lua | 72 - .../model/cbi/passwall/client/rule_list.lua | 133 - .../model/cbi/passwall/client/shunt_rules.lua | 78 - .../model/cbi/passwall/server/api/app.lua | 174 - .../cbi/passwall/server/api/shadowsocks.lua | 19 - .../model/cbi/passwall/server/api/trojan.lua | 60 - .../model/cbi/passwall/server/api/xray.lua | 233 - .../model/cbi/passwall/server/index.lua | 74 - .../luasrc/model/cbi/passwall/server/user.lua | 611 - .../passwall/app_update/brook_version.htm | 157 - .../passwall/app_update/kcptun_version.htm | 173 - .../passwall/app_update/trojan_go_version.htm | 173 - .../view/passwall/app_update/xray_version.htm | 173 - .../luasrc/view/passwall/global/footer.htm | 147 - .../luasrc/view/passwall/global/status.htm | 357 - .../luasrc/view/passwall/global/status2.htm | 262 - .../luasrc/view/passwall/global/tips.htm | 15 - .../luasrc/view/passwall/haproxy/status.htm | 24 - .../luasrc/view/passwall/log/log.htm | 30 - .../view/passwall/node_list/link_add_node.htm | 105 - .../passwall/node_list/link_share_man.htm | 787 - .../view/passwall/node_list/node_list.htm | 413 - .../view/passwall/rule/rule_version.htm | 80 - .../luasrc/view/passwall/server/log.htm | 34 - .../passwall/server/users_list_status.htm | 38 - .../luci-app-passwall/po/zh-cn/passwall.po | 1229 - .../root/etc/config/passwall | 140 - .../root/etc/config/passwall_server | 4 - .../root/etc/init.d/passwall | 21 - .../root/etc/init.d/passwall_server | 16 - .../root/etc/uci-defaults/luci-app-passwall | 31 - .../root/usr/share/passwall/app.sh | 1429 - .../root/usr/share/passwall/iptables.sh | 849 - .../root/usr/share/passwall/monitor.sh | 91 - .../root/usr/share/passwall/rule_update.lua | 450 - .../usr/share/passwall/rules/adblock.conf | 6105 -- .../root/usr/share/passwall/rules/block_host | 0 .../root/usr/share/passwall/rules/block_ip | 0 .../root/usr/share/passwall/rules/chnlist | 70410 ---------------- .../root/usr/share/passwall/rules/chnroute | 8611 -- .../root/usr/share/passwall/rules/chnroute6 | 1924 - .../root/usr/share/passwall/rules/direct_host | 5 - .../root/usr/share/passwall/rules/direct_ip | 11 - .../root/usr/share/passwall/rules/gfwlist | 5447 -- .../root/usr/share/passwall/rules/proxy_host | 8 - .../root/usr/share/passwall/rules/proxy_ip | 18 - .../root/usr/share/passwall/subscribe.lua | 1001 - .../root/usr/share/passwall/test.sh | 169 - package/lienol/luci-app-pppoe-server/Makefile | 23 - .../luasrc/controller/pppoe-server.lua | 25 - .../luasrc/model/cbi/pppoe-server/online.lua | 36 - .../model/cbi/pppoe-server/settings.lua | 82 - .../luasrc/model/cbi/pppoe-server/users.lua | 28 - .../luasrc/view/pppoe-server/index.htm | 13 - .../luasrc/view/pppoe-server/status.htm | 3 - .../po/zh-cn/pppoe-server.po | 101 - .../root/etc/config/pppoe-server | 21 - .../root/etc/init.d/pppoe-server | 101 - .../etc/uci-defaults/luci-app-pppoe-server | 11 - package/lienol/luci-app-socat/Makefile | 16 - .../luasrc/controller/socat.lua | 19 - .../luasrc/model/cbi/socat/config.lua | 82 - .../luasrc/model/cbi/socat/index.lua | 76 - .../luasrc/view/socat/list_status.htm | 19 - .../luasrc/view/socat/status.htm | 3 - .../lienol/luci-app-socat/po/zh-cn/socat.po | 50 - .../luci-app-socat/root/etc/config/socat | 3 - .../luci-app-socat/root/etc/init.d/socat | 119 - .../root/etc/uci-defaults/luci-app-socat | 19 - .../lienol/luci-app-ssr-libev-server/Makefile | 16 - .../luasrc/controller/ssr_libev_server.lua | 29 - .../model/cbi/ssr_libev_server/config.lua | 65 - .../model/cbi/ssr_libev_server/index.lua | 61 - .../ssr_libev_server/users_list_status.htm | 23 - .../view/ssr_libev_server/users_status.htm | 3 - .../po/zh-cn/ssr_libev_server.po | 65 - .../root/etc/config/ssr_libev_server | 16 - .../root/etc/init.d/ssr_libev_server | 73 - .../uci-defaults/luci-app-ssr-libev-server | 21 - .../share/ssr_libev_server/firewall.include | 40 - .../lienol/luci-app-ssr-mudb-server/Makefile | 16 - .../htdocs/luci-static/resources/vue.min.js | 6 - .../luasrc/controller/ssr_mudb_server.lua | 190 - .../model/cbi/ssr_mudb_server/index.lua | 51 - .../luasrc/view/ssr_mudb_server/status.htm | 26 - .../luasrc/view/ssr_mudb_server/user.htm | 258 - .../luasrc/view/ssr_mudb_server/users.htm | 144 - .../po/zh-cn/ssr_mudb_server.po | 152 - .../root/etc/config/ssr_mudb_server | 4 - .../root/etc/config/ssr_mudb_server.json | 18 - .../root/etc/init.d/ssr_mudb_server | 104 - .../etc/uci-defaults/luci-app-ssr-mudb-server | 21 - .../rpcd/acl.d/luci-app-ssr-mudb-server.json | 11 - .../usr/share/ssr_mudb_server/.travis.yml | 21 - .../root/usr/share/ssr_mudb_server/CHANGES | 342 - .../usr/share/ssr_mudb_server/CONTRIBUTING.md | 29 - .../root/usr/share/ssr_mudb_server/Dockerfile | 31 - .../usr/share/ssr_mudb_server/MANIFEST.in | 3 - .../usr/share/ssr_mudb_server/apiconfig.py | 15 - .../usr/share/ssr_mudb_server/asyncmgr.py | 99 - .../clear_traffic_all_users.sh | 11 - .../usr/share/ssr_mudb_server/config.json | 25 - .../usr/share/ssr_mudb_server/configloader.py | 15 - .../usr/share/ssr_mudb_server/db_transfer.py | 631 - .../usr/share/ssr_mudb_server/firewall.lua | 23 - .../usr/share/ssr_mudb_server/importloader.py | 24 - .../usr/share/ssr_mudb_server/initcfg.bat | 4 - .../root/usr/share/ssr_mudb_server/initcfg.sh | 8 - .../usr/share/ssr_mudb_server/initmudbjson.sh | 24 - .../root/usr/share/ssr_mudb_server/logrun.sh | 7 - .../root/usr/share/ssr_mudb_server/mudb.json | 1 - .../usr/share/ssr_mudb_server/mujson_mgr.py | 358 - .../root/usr/share/ssr_mudb_server/mysql.json | 13 - .../root/usr/share/ssr_mudb_server/run.sh | 7 - .../root/usr/share/ssr_mudb_server/server.py | 66 - .../usr/share/ssr_mudb_server/server_pool.py | 293 - .../root/usr/share/ssr_mudb_server/setup.py | 39 - .../share/ssr_mudb_server/setup_cymysql.sh | 6 - .../ssr_mudb_server/shadowsocks/__init__.py | 18 - .../ssr_mudb_server/shadowsocks/asyncdns.py | 555 - .../ssr_mudb_server/shadowsocks/common.py | 418 - .../shadowsocks/crypto/__init__.py | 18 - .../shadowsocks/crypto/ctypes_libsodium.py | 135 - .../shadowsocks/crypto/ctypes_openssl.py | 188 - .../shadowsocks/crypto/openssl.py | 199 - .../shadowsocks/crypto/rc4_md5.py | 52 - .../shadowsocks/crypto/sodium.py | 140 - .../shadowsocks/crypto/table.py | 181 - .../shadowsocks/crypto/util.py | 139 - .../ssr_mudb_server/shadowsocks/daemon.py | 208 - .../ssr_mudb_server/shadowsocks/encrypt.py | 236 - .../ssr_mudb_server/shadowsocks/eventloop.py | 258 - .../ssr_mudb_server/shadowsocks/local.py | 81 - .../ssr_mudb_server/shadowsocks/logrun.sh | 5 - .../ssr_mudb_server/shadowsocks/lru_cache.py | 179 - .../ssr_mudb_server/shadowsocks/manager.py | 291 - .../share/ssr_mudb_server/shadowsocks/obfs.py | 114 - .../shadowsocks/obfsplugin/__init__.py | 18 - .../shadowsocks/obfsplugin/auth.py | 787 - .../shadowsocks/obfsplugin/auth_chain.py | 692 - .../shadowsocks/obfsplugin/http_simple.py | 314 - .../shadowsocks/obfsplugin/obfs_tls.py | 305 - .../shadowsocks/obfsplugin/plain.py | 104 - .../shadowsocks/obfsplugin/verify.py | 154 - .../shadowsocks/ordereddict.py | 214 - .../share/ssr_mudb_server/shadowsocks/run.sh | 5 - .../ssr_mudb_server/shadowsocks/server.py | 215 - .../ssr_mudb_server/shadowsocks/shell.py | 445 - .../share/ssr_mudb_server/shadowsocks/stop.sh | 4 - .../share/ssr_mudb_server/shadowsocks/tail.sh | 3 - .../ssr_mudb_server/shadowsocks/tcprelay.py | 1476 - .../ssr_mudb_server/shadowsocks/udprelay.py | 656 - .../share/ssr_mudb_server/shadowsocks/user.py | 240 - .../ssr_mudb_server/shadowsocks/version.py | 20 - .../root/usr/share/ssr_mudb_server/stop.sh | 4 - .../usr/share/ssr_mudb_server/switchrule.py | 8 - .../root/usr/share/ssr_mudb_server/tail.sh | 3 - .../share/ssr_mudb_server/tests/aes-cfb1.json | 10 - .../share/ssr_mudb_server/tests/aes-cfb8.json | 10 - .../share/ssr_mudb_server/tests/aes-ctr.json | 10 - .../usr/share/ssr_mudb_server/tests/aes.json | 10 - .../usr/share/ssr_mudb_server/tests/assert.sh | 148 - .../share/ssr_mudb_server/tests/chacha20.json | 10 - .../tests/client-multi-server-ip.json | 10 - .../ssr_mudb_server/tests/coverage_server.py | 45 - .../share/ssr_mudb_server/tests/fastopen.json | 10 - .../tests/ipv6-client-side.json | 10 - .../usr/share/ssr_mudb_server/tests/ipv6.json | 10 - .../share/ssr_mudb_server/tests/jenkins.sh | 82 - .../tests/libsodium/install.sh | 10 - .../ssr_mudb_server/tests/nose_plugin.py | 43 - .../share/ssr_mudb_server/tests/rc4-md5.json | 10 - .../ssr_mudb_server/tests/salsa20-ctr.json | 10 - .../share/ssr_mudb_server/tests/salsa20.json | 10 - .../server-multi-passwd-client-side.json | 8 - .../tests/server-multi-passwd-table.json | 19 - .../tests/server-multi-passwd.json | 17 - .../tests/server-multi-ports.json | 8 - .../share/ssr_mudb_server/tests/setup_tc.sh | 18 - .../ssr_mudb_server/tests/socksify/install.sh | 10 - .../ssr_mudb_server/tests/socksify/socks.conf | 5 - .../share/ssr_mudb_server/tests/table.json | 10 - .../usr/share/ssr_mudb_server/tests/test.py | 158 - .../ssr_mudb_server/tests/test_command.sh | 32 - .../ssr_mudb_server/tests/test_daemon.sh | 43 - .../ssr_mudb_server/tests/test_large_file.sh | 24 - .../ssr_mudb_server/tests/test_udp_src.py | 83 - .../ssr_mudb_server/tests/test_udp_src.sh | 23 - .../share/ssr_mudb_server/tests/workers.json | 10 - .../share/ssr_mudb_server/user-config.json | 25 - .../share/ssr_mudb_server/userapiconfig.py | 15 - .../usr/share/ssr_mudb_server/usermysql.json | 13 - .../usr/share/ssr_mudb_server/utils/README.md | 9 - .../share/ssr_mudb_server/utils/autoban.py | 53 - .../utils/fail2ban/shadowsocks.conf | 5 - package/lienol/luci-app-timecontrol/Makefile | 15 - .../luasrc/controller/timecontrol.lua | 17 - .../luasrc/model/cbi/timecontrol.lua | 57 - .../luasrc/view/timecontrol/index.htm | 12 - .../luasrc/view/timecontrol/timecontrol.htm | 3 - .../po/zh-cn/timecontrol.po | 41 - .../root/etc/config/timecontrol | 3 - .../root/etc/init.d/timecontrol | 80 - .../etc/uci-defaults/luci-app-timecontrol | 19 - package/lienol/luci-app-timewol/Makefile | 17 - .../luasrc/controller/timewol.lua | 16 - .../luasrc/model/cbi/timewol.lua | 37 - .../luasrc/view/timewol/index.htm | 18 - .../luasrc/view/timewol/timewol.htm | 3 - .../luci-app-timewol/po/zh-cn/timewol.po | 2 - .../luci-app-timewol/root/etc/config/timewol | 3 - .../luci-app-timewol/root/etc/init.d/timewol | 74 - .../etc/uci-defaults/luci-app-control-timewol | 11 - .../lienol/luci-app-trojan-server/Makefile | 17 - .../luasrc/controller/trojan_server.lua | 41 - .../api/gen_trojan_config_file.lua | 40 - .../luasrc/model/cbi/trojan_server/config.lua | 54 - .../luasrc/model/cbi/trojan_server/index.lua | 58 - .../luasrc/view/trojan_server/log.htm | 31 - .../view/trojan_server/users_list_status.htm | 23 - .../view/trojan_server/users_status.htm | 3 - .../po/zh-cn/trojan_server.po | 68 - .../root/etc/config/trojan_server | 13 - .../root/etc/init.d/trojan_server | 60 - .../etc/uci-defaults/luci-app-trojan-server | 21 - .../usr/share/trojan_server/firewall.include | 39 - .../lienol/luci-app-webrestriction/Makefile | 17 - .../luasrc/controller/webrestriction.lua | 16 - .../luasrc/model/cbi/webrestriction.lua | 30 - .../luasrc/view/webrestriction/index.htm | 18 - .../view/webrestriction/webrestriction.htm | 3 - .../po/zh-cn/webrestriction.po | 2 - .../root/etc/config/webrestriction | 5 - .../root/etc/init.d/webrestriction | 86 - .../luci-app-control-webrestriction | 11 - package/lienol/luci-app-weburl/Makefile | 18 - .../luasrc/controller/weburl.lua | 16 - .../luasrc/model/cbi/weburl.lua | 36 - .../luasrc/view/weburl/index.htm | 18 - .../luasrc/view/weburl/weburl.htm | 3 - .../lienol/luci-app-weburl/po/zh-cn/weburl.po | 2 - .../luci-app-weburl/root/etc/config/weburl | 22 - .../luci-app-weburl/root/etc/init.d/weburl | 88 - .../etc/uci-defaults/luci-app-control-weburl | 11 - .../lienol/luci-theme-argon-dark-mod/Makefile | 16 - .../luci-static/argon_dark/css/purecss.css | 7 - .../luci-static/argon_dark/css/style.css | 3837 - .../htdocs/luci-static/argon_dark/favicon.ico | Bin 31346 -> 0 bytes .../argon_dark/fonts/TypoGraphica.eot | Bin 33846 -> 0 bytes .../argon_dark/fonts/TypoGraphica.svg | 1191 - .../argon_dark/fonts/TypoGraphica.ttf | Bin 33632 -> 0 bytes .../argon_dark/fonts/TypoGraphica.woff | Bin 17816 -> 0 bytes .../luci-static/argon_dark/fonts/font.eot | Bin 1912 -> 0 bytes .../luci-static/argon_dark/fonts/font.svg | 16 - .../luci-static/argon_dark/fonts/font.ttf | Bin 1748 -> 0 bytes .../luci-static/argon_dark/fonts/font.woff | Bin 1824 -> 0 bytes .../luci-static/argon_dark/fonts/icomoon.eot | Bin 1476 -> 0 bytes .../luci-static/argon_dark/fonts/icomoon.svg | 12 - .../luci-static/argon_dark/fonts/icomoon.ttf | Bin 1312 -> 0 bytes .../luci-static/argon_dark/fonts/icomoon.woff | Bin 1388 -> 0 bytes .../luci-static/argon_dark/fonts/ssr.eot | Bin 7232 -> 0 bytes .../luci-static/argon_dark/fonts/ssr.svg | 25 - .../luci-static/argon_dark/fonts/ssr.ttf | Bin 7084 -> 0 bytes .../luci-static/argon_dark/fonts/ssr.woff | Bin 7160 -> 0 bytes .../htdocs/luci-static/argon_dark/img/bg1.jpg | Bin 169716 -> 0 bytes .../htdocs/luci-static/argon_dark/img/bg2.jpg | Bin 264224 -> 0 bytes .../htdocs/luci-static/argon_dark/img/bg3.jpg | Bin 248828 -> 0 bytes .../luci-static/argon_dark/js/jquery.min.js | 6 - .../luci-static/argon_dark/js/script.js | 288 - .../htdocs/luci-static/argon_dark/logo.png | Bin 7138 -> 0 bytes .../argon_dark_purple/css/purecss.css | 7 - .../argon_dark_purple/css/style.css | 3837 - .../luci-static/argon_dark_purple/favicon.ico | Bin 31346 -> 0 bytes .../argon_dark_purple/fonts/TypoGraphica.eot | Bin 33846 -> 0 bytes .../argon_dark_purple/fonts/TypoGraphica.svg | 1191 - .../argon_dark_purple/fonts/TypoGraphica.ttf | Bin 33632 -> 0 bytes .../argon_dark_purple/fonts/TypoGraphica.woff | Bin 17816 -> 0 bytes .../argon_dark_purple/fonts/font.eot | Bin 1912 -> 0 bytes .../argon_dark_purple/fonts/font.svg | 16 - .../argon_dark_purple/fonts/font.ttf | Bin 1748 -> 0 bytes .../argon_dark_purple/fonts/font.woff | Bin 1824 -> 0 bytes .../argon_dark_purple/fonts/icomoon.eot | Bin 1476 -> 0 bytes .../argon_dark_purple/fonts/icomoon.svg | 12 - .../argon_dark_purple/fonts/icomoon.ttf | Bin 1312 -> 0 bytes .../argon_dark_purple/fonts/icomoon.woff | Bin 1388 -> 0 bytes .../argon_dark_purple/fonts/ssr.eot | Bin 7232 -> 0 bytes .../argon_dark_purple/fonts/ssr.svg | 25 - .../argon_dark_purple/fonts/ssr.ttf | Bin 7084 -> 0 bytes .../argon_dark_purple/fonts/ssr.woff | Bin 7160 -> 0 bytes .../luci-static/argon_dark_purple/img/bg1.jpg | Bin 169716 -> 0 bytes .../luci-static/argon_dark_purple/img/bg2.jpg | Bin 264224 -> 0 bytes .../luci-static/argon_dark_purple/img/bg3.jpg | Bin 248828 -> 0 bytes .../argon_dark_purple/js/jquery.min.js | 6 - .../argon_dark_purple/js/script.js | 288 - .../luci-static/argon_dark_purple/logo.png | Bin 7138 -> 0 bytes .../luasrc/view/themes/argon_dark/footer.htm | 63 - .../luasrc/view/themes/argon_dark/header.htm | 304 - .../view/themes/argon_dark_purple/footer.htm | 63 - .../view/themes/argon_dark_purple/header.htm | 304 - .../uci-defaults/30_luci-theme-argon-dark-mod | 7 - .../luci-theme-argon-light-mod/Makefile | 16 - .../luci-static/argon_light/css/purecss.css | 7 - .../luci-static/argon_light/css/style.css | 3832 - .../luci-static/argon_light/favicon.ico | Bin 31346 -> 0 bytes .../argon_light/fonts/TypoGraphica.eot | Bin 33846 -> 0 bytes .../argon_light/fonts/TypoGraphica.svg | 1191 - .../argon_light/fonts/TypoGraphica.ttf | Bin 33632 -> 0 bytes .../argon_light/fonts/TypoGraphica.woff | Bin 17816 -> 0 bytes .../luci-static/argon_light/fonts/font.eot | Bin 1912 -> 0 bytes .../luci-static/argon_light/fonts/font.svg | 16 - .../luci-static/argon_light/fonts/font.ttf | Bin 1748 -> 0 bytes .../luci-static/argon_light/fonts/font.woff | Bin 1824 -> 0 bytes .../luci-static/argon_light/fonts/icomoon.eot | Bin 1476 -> 0 bytes .../luci-static/argon_light/fonts/icomoon.svg | 12 - .../luci-static/argon_light/fonts/icomoon.ttf | Bin 1312 -> 0 bytes .../argon_light/fonts/icomoon.woff | Bin 1388 -> 0 bytes .../luci-static/argon_light/fonts/ssr.eot | Bin 7232 -> 0 bytes .../luci-static/argon_light/fonts/ssr.svg | 25 - .../luci-static/argon_light/fonts/ssr.ttf | Bin 7084 -> 0 bytes .../luci-static/argon_light/fonts/ssr.woff | Bin 7160 -> 0 bytes .../luci-static/argon_light/img/bg1.jpg | Bin 169716 -> 0 bytes .../luci-static/argon_light/img/bg2.jpg | Bin 264224 -> 0 bytes .../luci-static/argon_light/img/bg3.jpg | Bin 248828 -> 0 bytes .../luci-static/argon_light/js/jquery.min.js | 6 - .../luci-static/argon_light/js/script.js | 288 - .../htdocs/luci-static/argon_light/logo.png | Bin 7138 -> 0 bytes .../argon_light_green/css/purecss.css | 7 - .../argon_light_green/css/style.css | 3837 - .../luci-static/argon_light_green/favicon.ico | Bin 31346 -> 0 bytes .../argon_light_green/fonts/TypoGraphica.eot | Bin 33846 -> 0 bytes .../argon_light_green/fonts/TypoGraphica.svg | 1191 - .../argon_light_green/fonts/TypoGraphica.ttf | Bin 33632 -> 0 bytes .../argon_light_green/fonts/TypoGraphica.woff | Bin 17816 -> 0 bytes .../argon_light_green/fonts/font.eot | Bin 1912 -> 0 bytes .../argon_light_green/fonts/font.svg | 16 - .../argon_light_green/fonts/font.ttf | Bin 1748 -> 0 bytes .../argon_light_green/fonts/font.woff | Bin 1824 -> 0 bytes .../argon_light_green/fonts/icomoon.eot | Bin 1476 -> 0 bytes .../argon_light_green/fonts/icomoon.svg | 12 - .../argon_light_green/fonts/icomoon.ttf | Bin 1312 -> 0 bytes .../argon_light_green/fonts/icomoon.woff | Bin 1388 -> 0 bytes .../argon_light_green/fonts/ssr.eot | Bin 7232 -> 0 bytes .../argon_light_green/fonts/ssr.svg | 25 - .../argon_light_green/fonts/ssr.ttf | Bin 7084 -> 0 bytes .../argon_light_green/fonts/ssr.woff | Bin 7160 -> 0 bytes .../luci-static/argon_light_green/img/bg1.jpg | Bin 169716 -> 0 bytes .../luci-static/argon_light_green/img/bg2.jpg | Bin 264224 -> 0 bytes .../luci-static/argon_light_green/img/bg3.jpg | Bin 248828 -> 0 bytes .../argon_light_green/js/jquery.min.js | 6 - .../argon_light_green/js/script.js | 288 - .../luci-static/argon_light_green/logo.png | Bin 7138 -> 0 bytes .../luasrc/view/themes/argon_light/footer.htm | 63 - .../luasrc/view/themes/argon_light/header.htm | 304 - .../view/themes/argon_light_green/footer.htm | 63 - .../view/themes/argon_light_green/header.htm | 304 - .../30_luci-theme-argon-light-mod | 7 - .../lienol/luci-theme-bootstrap-mod/Makefile | 15 - .../luci-static/bootstrap_blue/cascade.css | 1574 - .../luci-static/bootstrap_blue/favicon.ico | Bin 1150 -> 0 bytes .../luci-static/bootstrap_blue/html5.js | 3 - .../luci-static/bootstrap_blue/mobile.css | 78 - .../luci-static/bootstrap_blue/wifi.png | Bin 21597 -> 0 bytes .../luci-static/bootstrap_mod/cascade.css | 1569 - .../luci-static/bootstrap_mod/favicon.ico | Bin 1150 -> 0 bytes .../htdocs/luci-static/bootstrap_mod/html5.js | 3 - .../luci-static/bootstrap_mod/mobile.css | 78 - .../htdocs/luci-static/bootstrap_mod/wifi.png | Bin 21597 -> 0 bytes .../view/themes/bootstrap_blue/footer.htm | 63 - .../view/themes/bootstrap_blue/header.htm | 220 - .../view/themes/bootstrap_mod/footer.htm | 63 - .../view/themes/bootstrap_mod/header.htm | 220 - .../uci-defaults/30_luci-theme-bootstrap-mod | 8 - 620 files changed, 221717 deletions(-) delete mode 100644 package/lienol/luci-app-brook-server/Makefile delete mode 100644 package/lienol/luci-app-brook-server/luasrc/controller/brook_server.lua delete mode 100644 package/lienol/luci-app-brook-server/luasrc/model/cbi/brook_server/api/brook.lua delete mode 100644 package/lienol/luci-app-brook-server/luasrc/model/cbi/brook_server/config.lua delete mode 100644 package/lienol/luci-app-brook-server/luasrc/model/cbi/brook_server/index.lua delete mode 100644 package/lienol/luci-app-brook-server/luasrc/view/brook_server/brook.htm delete mode 100644 package/lienol/luci-app-brook-server/luasrc/view/brook_server/log.htm delete mode 100644 package/lienol/luci-app-brook-server/luasrc/view/brook_server/users_list_status.htm delete mode 100644 package/lienol/luci-app-brook-server/luasrc/view/brook_server/users_status.htm delete mode 100644 package/lienol/luci-app-brook-server/po/zh-cn/brook_server.po delete mode 100644 package/lienol/luci-app-brook-server/root/etc/config/brook_server delete mode 100755 package/lienol/luci-app-brook-server/root/etc/init.d/brook_server delete mode 100755 package/lienol/luci-app-brook-server/root/etc/uci-defaults/luci-app-brook-server delete mode 100755 package/lienol/luci-app-brook-server/root/usr/share/brook_server/firewall.include delete mode 100644 package/lienol/luci-app-fileassistant/Makefile delete mode 100644 package/lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/fb.css delete mode 100644 package/lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/fb.js delete mode 100644 package/lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/file-icon.png delete mode 100644 package/lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/folder-icon.png delete mode 100644 package/lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/link-icon.png delete mode 100644 package/lienol/luci-app-fileassistant/luasrc/controller/fileassistant.lua delete mode 100644 package/lienol/luci-app-fileassistant/luasrc/view/fileassistant.htm delete mode 100644 package/lienol/luci-app-ipsec-vpnserver-manyusers/Makefile delete mode 100644 package/lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/controller/ipsec-server.lua delete mode 100644 package/lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/model/cbi/ipsec-server/settings.lua delete mode 100644 package/lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/model/cbi/ipsec-server/users.lua delete mode 100644 package/lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/view/ipsec-server/index.htm delete mode 100644 package/lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/view/ipsec-server/status.htm delete mode 100644 package/lienol/luci-app-ipsec-vpnserver-manyusers/po/zh-cn/ipsec.po delete mode 100644 package/lienol/luci-app-ipsec-vpnserver-manyusers/root/etc/config/ipsec delete mode 100755 package/lienol/luci-app-ipsec-vpnserver-manyusers/root/etc/init.d/ipsecvpn delete mode 100755 package/lienol/luci-app-ipsec-vpnserver-manyusers/root/etc/uci-defaults/luci-app-ipsec-vpnserver-manyusers delete mode 100755 package/lienol/luci-app-ipsec-vpnserver-manyusers/root/usr/share/ipsecvpn/firewall.include delete mode 100644 package/lienol/luci-app-nginx-pingos/Makefile delete mode 100644 package/lienol/luci-app-nginx-pingos/luasrc/controller/pingos.lua delete mode 100644 package/lienol/luci-app-nginx-pingos/luasrc/model/cbi/pingos.lua delete mode 100644 package/lienol/luci-app-nginx-pingos/luasrc/view/pingos/status.htm delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/COPYRIGHT delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/config delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/ngx_client.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/ngx_client.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/ngx_http_client.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/ngx_http_client.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/config delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/nginx.conf delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/ngx_client_stat_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/ngx_client_test_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/ngx_http_client_test_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/tcpserver.go delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/COPYRIGHT delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/README.md delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/config delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/doc/ngx-http-broadcast-module.md delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/doc/ngx-stream-zone-module.md delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_event_multiport_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_http_broadcast_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_http_inner_proxy_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_multiport.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_multiport_misc.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_process_slot_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_stream_zone_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_stream_zone_module.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/config delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/nginx.conf delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/ngx_multiport_test_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/ngx_stream_zone_test_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/ngx_test_macro.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/AUTHORS delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/LICENSE delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/config delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/dash/ngx_rtmp_dash_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/dash/ngx_rtmp_mp4.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/dash/ngx_rtmp_mp4.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/hls/ngx_rtmp_hls_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/hls/ngx_rtmp_mpegts.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/hls/ngx_rtmp_mpegts.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/http/ngx_http_flv_live_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/http/ngx_http_set_header.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/http/ngx_http_set_header.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_hls_http_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_hls_live_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_hls_live_module.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_gop_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_gop_module.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_http_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_live_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_live_module.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_record.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_record.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_httpflv.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_inner.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_rtmp.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_simple.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_static.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_netcall.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_netcall.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_access_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_amf.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_amf.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_bandwidth.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_bandwidth.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_bitop.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_bitop.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_cmd_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_cmd_module.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_codec_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_codec_module.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_control_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_core_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_dynamic.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_dynamic.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_eval.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_eval.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_exec_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_gop_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_handler.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_handshake.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_init.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_limit_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_live_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_live_module.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_log_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_monitor_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_monitor_module.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_notify_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_notify_module.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_proxy_protocol.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_proxy_protocol.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_receive.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_record_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_record_module.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_send.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_shared_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_stat_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_streams.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_sys_stat_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_variables.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_variables.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_version.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/COPYRIGHT delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/README.md delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/config delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-dynamic-conf-module.md delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-dynamic-resolver-module.md delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-event-resolver-module.md delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-event-timer-module.md delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-map.md delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-poold.md delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-rbuf.md delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-toolkit-misc.md delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_dynamic_conf.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_dynamic_conf.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_dynamic_resolver.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_dynamic_resolver.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_event_resolver.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_event_resolver.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_event_timer_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_event_timer_module.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_http_dynamic.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_http_dynamic.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_http_trace_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_map.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_map.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_poold.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_poold.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_rbuf.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_rbuf.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_timerd.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_timerd.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_toolkit_misc.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_toolkit_misc.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/config delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/dns_install.sh delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/md5testfile delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/named.conf delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/nginx.conf delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/nginx_dynamic.conf delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_dynamic_conf_test_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_dynamic_resolver_test_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_event_resolver_test_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_event_timer_test_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_http_dynamic_test_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_map_test_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_poold_test_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_rbuf_test_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_test_macro.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_timerd_test_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_toolkit_misc_test_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/test.com.zone delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/test1.com.zone delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/LICENSE delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/README.rst delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/config delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_http_ts_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_stream_ts_module.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_aac.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_aac.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_avc.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_avc.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_dash.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_dash.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_dash_mp4.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_hls.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_hls.h delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_stream.c delete mode 100644 package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_stream.h delete mode 100644 package/lienol/luci-app-nginx-pingos/patches/101-feature_test_fix.patch delete mode 100644 package/lienol/luci-app-nginx-pingos/patches/102-sizeof_test_fix.patch delete mode 100644 package/lienol/luci-app-nginx-pingos/patches/103-sys_nerr.patch delete mode 100644 package/lienol/luci-app-nginx-pingos/patches/104-endianness_fix.patch delete mode 100644 package/lienol/luci-app-nginx-pingos/patches/200-config.patch delete mode 100644 package/lienol/luci-app-nginx-pingos/patches/201-ignore-invalid-options.patch delete mode 100644 package/lienol/luci-app-nginx-pingos/po/zh-cn/pingos.po delete mode 100644 package/lienol/luci-app-nginx-pingos/root/etc/config/pingos delete mode 100755 package/lienol/luci-app-nginx-pingos/root/etc/init.d/pingos delete mode 100644 package/lienol/luci-app-nginx-pingos/root/etc/pingos.template delete mode 100755 package/lienol/luci-app-nginx-pingos/root/etc/uci-defaults/luci-app-nginx-pingos delete mode 100644 package/lienol/luci-app-nginx-pingos/root/resource/conf-template/nginx.conf delete mode 100644 package/lienol/luci-app-nginx-pingos/root/resource/crossdomain.xml delete mode 100644 package/lienol/luci-app-nginx-pingos/root/resource/stat.xsl delete mode 100644 package/lienol/luci-app-passwall/Makefile delete mode 100644 package/lienol/luci-app-passwall/luasrc/controller/passwall.lua delete mode 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/api.lua delete mode 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/brook.lua delete mode 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_naiveproxy.lua delete mode 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_shadowsocks.lua delete mode 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_trojan.lua delete mode 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_xray.lua delete mode 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_xray_proto.lua delete mode 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/kcptun.lua delete mode 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/trojan_go.lua delete mode 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/xray.lua delete mode 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/acl.lua delete mode 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/app_update.lua delete mode 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/auto_switch.lua delete mode 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua delete mode 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/haproxy.lua delete mode 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/log.lua delete mode 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/node_config.lua delete mode 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/node_list.lua delete mode 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe.lua delete mode 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/other.lua delete mode 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/rule.lua delete mode 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/rule_list.lua delete mode 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/shunt_rules.lua delete mode 100755 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/app.lua delete mode 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/shadowsocks.lua delete mode 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/trojan.lua delete mode 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/xray.lua delete mode 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/index.lua delete mode 100644 package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/user.lua delete mode 100644 package/lienol/luci-app-passwall/luasrc/view/passwall/app_update/brook_version.htm delete mode 100644 package/lienol/luci-app-passwall/luasrc/view/passwall/app_update/kcptun_version.htm delete mode 100644 package/lienol/luci-app-passwall/luasrc/view/passwall/app_update/trojan_go_version.htm delete mode 100644 package/lienol/luci-app-passwall/luasrc/view/passwall/app_update/xray_version.htm delete mode 100644 package/lienol/luci-app-passwall/luasrc/view/passwall/global/footer.htm delete mode 100644 package/lienol/luci-app-passwall/luasrc/view/passwall/global/status.htm delete mode 100644 package/lienol/luci-app-passwall/luasrc/view/passwall/global/status2.htm delete mode 100644 package/lienol/luci-app-passwall/luasrc/view/passwall/global/tips.htm delete mode 100644 package/lienol/luci-app-passwall/luasrc/view/passwall/haproxy/status.htm delete mode 100644 package/lienol/luci-app-passwall/luasrc/view/passwall/log/log.htm delete mode 100644 package/lienol/luci-app-passwall/luasrc/view/passwall/node_list/link_add_node.htm delete mode 100644 package/lienol/luci-app-passwall/luasrc/view/passwall/node_list/link_share_man.htm delete mode 100644 package/lienol/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm delete mode 100644 package/lienol/luci-app-passwall/luasrc/view/passwall/rule/rule_version.htm delete mode 100644 package/lienol/luci-app-passwall/luasrc/view/passwall/server/log.htm delete mode 100644 package/lienol/luci-app-passwall/luasrc/view/passwall/server/users_list_status.htm delete mode 100644 package/lienol/luci-app-passwall/po/zh-cn/passwall.po delete mode 100644 package/lienol/luci-app-passwall/root/etc/config/passwall delete mode 100644 package/lienol/luci-app-passwall/root/etc/config/passwall_server delete mode 100755 package/lienol/luci-app-passwall/root/etc/init.d/passwall delete mode 100755 package/lienol/luci-app-passwall/root/etc/init.d/passwall_server delete mode 100755 package/lienol/luci-app-passwall/root/etc/uci-defaults/luci-app-passwall delete mode 100755 package/lienol/luci-app-passwall/root/usr/share/passwall/app.sh delete mode 100755 package/lienol/luci-app-passwall/root/usr/share/passwall/iptables.sh delete mode 100755 package/lienol/luci-app-passwall/root/usr/share/passwall/monitor.sh delete mode 100755 package/lienol/luci-app-passwall/root/usr/share/passwall/rule_update.lua delete mode 100644 package/lienol/luci-app-passwall/root/usr/share/passwall/rules/adblock.conf delete mode 100644 package/lienol/luci-app-passwall/root/usr/share/passwall/rules/block_host delete mode 100644 package/lienol/luci-app-passwall/root/usr/share/passwall/rules/block_ip delete mode 100644 package/lienol/luci-app-passwall/root/usr/share/passwall/rules/chnlist delete mode 100644 package/lienol/luci-app-passwall/root/usr/share/passwall/rules/chnroute delete mode 100644 package/lienol/luci-app-passwall/root/usr/share/passwall/rules/chnroute6 delete mode 100644 package/lienol/luci-app-passwall/root/usr/share/passwall/rules/direct_host delete mode 100644 package/lienol/luci-app-passwall/root/usr/share/passwall/rules/direct_ip delete mode 100644 package/lienol/luci-app-passwall/root/usr/share/passwall/rules/gfwlist delete mode 100644 package/lienol/luci-app-passwall/root/usr/share/passwall/rules/proxy_host delete mode 100644 package/lienol/luci-app-passwall/root/usr/share/passwall/rules/proxy_ip delete mode 100755 package/lienol/luci-app-passwall/root/usr/share/passwall/subscribe.lua delete mode 100755 package/lienol/luci-app-passwall/root/usr/share/passwall/test.sh delete mode 100644 package/lienol/luci-app-pppoe-server/Makefile delete mode 100644 package/lienol/luci-app-pppoe-server/luasrc/controller/pppoe-server.lua delete mode 100644 package/lienol/luci-app-pppoe-server/luasrc/model/cbi/pppoe-server/online.lua delete mode 100644 package/lienol/luci-app-pppoe-server/luasrc/model/cbi/pppoe-server/settings.lua delete mode 100644 package/lienol/luci-app-pppoe-server/luasrc/model/cbi/pppoe-server/users.lua delete mode 100644 package/lienol/luci-app-pppoe-server/luasrc/view/pppoe-server/index.htm delete mode 100644 package/lienol/luci-app-pppoe-server/luasrc/view/pppoe-server/status.htm delete mode 100644 package/lienol/luci-app-pppoe-server/po/zh-cn/pppoe-server.po delete mode 100644 package/lienol/luci-app-pppoe-server/root/etc/config/pppoe-server delete mode 100755 package/lienol/luci-app-pppoe-server/root/etc/init.d/pppoe-server delete mode 100755 package/lienol/luci-app-pppoe-server/root/etc/uci-defaults/luci-app-pppoe-server delete mode 100644 package/lienol/luci-app-socat/Makefile delete mode 100644 package/lienol/luci-app-socat/luasrc/controller/socat.lua delete mode 100644 package/lienol/luci-app-socat/luasrc/model/cbi/socat/config.lua delete mode 100644 package/lienol/luci-app-socat/luasrc/model/cbi/socat/index.lua delete mode 100644 package/lienol/luci-app-socat/luasrc/view/socat/list_status.htm delete mode 100644 package/lienol/luci-app-socat/luasrc/view/socat/status.htm delete mode 100644 package/lienol/luci-app-socat/po/zh-cn/socat.po delete mode 100644 package/lienol/luci-app-socat/root/etc/config/socat delete mode 100755 package/lienol/luci-app-socat/root/etc/init.d/socat delete mode 100755 package/lienol/luci-app-socat/root/etc/uci-defaults/luci-app-socat delete mode 100644 package/lienol/luci-app-ssr-libev-server/Makefile delete mode 100644 package/lienol/luci-app-ssr-libev-server/luasrc/controller/ssr_libev_server.lua delete mode 100644 package/lienol/luci-app-ssr-libev-server/luasrc/model/cbi/ssr_libev_server/config.lua delete mode 100644 package/lienol/luci-app-ssr-libev-server/luasrc/model/cbi/ssr_libev_server/index.lua delete mode 100644 package/lienol/luci-app-ssr-libev-server/luasrc/view/ssr_libev_server/users_list_status.htm delete mode 100644 package/lienol/luci-app-ssr-libev-server/luasrc/view/ssr_libev_server/users_status.htm delete mode 100644 package/lienol/luci-app-ssr-libev-server/po/zh-cn/ssr_libev_server.po delete mode 100644 package/lienol/luci-app-ssr-libev-server/root/etc/config/ssr_libev_server delete mode 100755 package/lienol/luci-app-ssr-libev-server/root/etc/init.d/ssr_libev_server delete mode 100755 package/lienol/luci-app-ssr-libev-server/root/etc/uci-defaults/luci-app-ssr-libev-server delete mode 100755 package/lienol/luci-app-ssr-libev-server/root/usr/share/ssr_libev_server/firewall.include delete mode 100644 package/lienol/luci-app-ssr-mudb-server/Makefile delete mode 100644 package/lienol/luci-app-ssr-mudb-server/htdocs/luci-static/resources/vue.min.js delete mode 100644 package/lienol/luci-app-ssr-mudb-server/luasrc/controller/ssr_mudb_server.lua delete mode 100644 package/lienol/luci-app-ssr-mudb-server/luasrc/model/cbi/ssr_mudb_server/index.lua delete mode 100644 package/lienol/luci-app-ssr-mudb-server/luasrc/view/ssr_mudb_server/status.htm delete mode 100644 package/lienol/luci-app-ssr-mudb-server/luasrc/view/ssr_mudb_server/user.htm delete mode 100644 package/lienol/luci-app-ssr-mudb-server/luasrc/view/ssr_mudb_server/users.htm delete mode 100644 package/lienol/luci-app-ssr-mudb-server/po/zh-cn/ssr_mudb_server.po delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/etc/config/ssr_mudb_server delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/etc/config/ssr_mudb_server.json delete mode 100755 package/lienol/luci-app-ssr-mudb-server/root/etc/init.d/ssr_mudb_server delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/etc/uci-defaults/luci-app-ssr-mudb-server delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/rpcd/acl.d/luci-app-ssr-mudb-server.json delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/.travis.yml delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/CHANGES delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/CONTRIBUTING.md delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/Dockerfile delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/MANIFEST.in delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/apiconfig.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/asyncmgr.py delete mode 100755 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/clear_traffic_all_users.sh delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/config.json delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/configloader.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/db_transfer.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/firewall.lua delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/importloader.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/initcfg.bat delete mode 100755 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/initcfg.sh delete mode 100755 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/initmudbjson.sh delete mode 100755 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/logrun.sh delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/mudb.json delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/mujson_mgr.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/mysql.json delete mode 100755 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/run.sh delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/server.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/server_pool.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/setup.py delete mode 100755 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/setup_cymysql.sh delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/__init__.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/asyncdns.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/common.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/__init__.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/ctypes_libsodium.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/ctypes_openssl.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/openssl.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/rc4_md5.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/sodium.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/table.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/util.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/daemon.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/encrypt.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/eventloop.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/local.py delete mode 100755 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/logrun.sh delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/lru_cache.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/manager.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfs.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/__init__.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/auth.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/auth_chain.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/http_simple.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/obfs_tls.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/plain.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/verify.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/ordereddict.py delete mode 100755 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/run.sh delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/server.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/shell.py delete mode 100755 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/stop.sh delete mode 100755 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/tail.sh delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/tcprelay.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/udprelay.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/user.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/version.py delete mode 100755 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/stop.sh delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/switchrule.py delete mode 100755 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tail.sh delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/aes-cfb1.json delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/aes-cfb8.json delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/aes-ctr.json delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/aes.json delete mode 100755 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/assert.sh delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/chacha20.json delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/client-multi-server-ip.json delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/coverage_server.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/fastopen.json delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/ipv6-client-side.json delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/ipv6.json delete mode 100755 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/jenkins.sh delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/libsodium/install.sh delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/nose_plugin.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/rc4-md5.json delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/salsa20-ctr.json delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/salsa20.json delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/server-multi-passwd-client-side.json delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/server-multi-passwd-table.json delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/server-multi-passwd.json delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/server-multi-ports.json delete mode 100755 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/setup_tc.sh delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/socksify/install.sh delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/socksify/socks.conf delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/table.json delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test.py delete mode 100755 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_command.sh delete mode 100755 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_daemon.sh delete mode 100755 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_large_file.sh delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_udp_src.py delete mode 100755 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_udp_src.sh delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/workers.json delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/user-config.json delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/userapiconfig.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/usermysql.json delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/utils/README.md delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/utils/autoban.py delete mode 100644 package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/utils/fail2ban/shadowsocks.conf delete mode 100644 package/lienol/luci-app-timecontrol/Makefile delete mode 100644 package/lienol/luci-app-timecontrol/luasrc/controller/timecontrol.lua delete mode 100644 package/lienol/luci-app-timecontrol/luasrc/model/cbi/timecontrol.lua delete mode 100644 package/lienol/luci-app-timecontrol/luasrc/view/timecontrol/index.htm delete mode 100644 package/lienol/luci-app-timecontrol/luasrc/view/timecontrol/timecontrol.htm delete mode 100644 package/lienol/luci-app-timecontrol/po/zh-cn/timecontrol.po delete mode 100644 package/lienol/luci-app-timecontrol/root/etc/config/timecontrol delete mode 100755 package/lienol/luci-app-timecontrol/root/etc/init.d/timecontrol delete mode 100755 package/lienol/luci-app-timecontrol/root/etc/uci-defaults/luci-app-timecontrol delete mode 100644 package/lienol/luci-app-timewol/Makefile delete mode 100644 package/lienol/luci-app-timewol/luasrc/controller/timewol.lua delete mode 100644 package/lienol/luci-app-timewol/luasrc/model/cbi/timewol.lua delete mode 100644 package/lienol/luci-app-timewol/luasrc/view/timewol/index.htm delete mode 100644 package/lienol/luci-app-timewol/luasrc/view/timewol/timewol.htm delete mode 100644 package/lienol/luci-app-timewol/po/zh-cn/timewol.po delete mode 100644 package/lienol/luci-app-timewol/root/etc/config/timewol delete mode 100755 package/lienol/luci-app-timewol/root/etc/init.d/timewol delete mode 100755 package/lienol/luci-app-timewol/root/etc/uci-defaults/luci-app-control-timewol delete mode 100644 package/lienol/luci-app-trojan-server/Makefile delete mode 100644 package/lienol/luci-app-trojan-server/luasrc/controller/trojan_server.lua delete mode 100644 package/lienol/luci-app-trojan-server/luasrc/model/cbi/trojan_server/api/gen_trojan_config_file.lua delete mode 100644 package/lienol/luci-app-trojan-server/luasrc/model/cbi/trojan_server/config.lua delete mode 100644 package/lienol/luci-app-trojan-server/luasrc/model/cbi/trojan_server/index.lua delete mode 100644 package/lienol/luci-app-trojan-server/luasrc/view/trojan_server/log.htm delete mode 100644 package/lienol/luci-app-trojan-server/luasrc/view/trojan_server/users_list_status.htm delete mode 100644 package/lienol/luci-app-trojan-server/luasrc/view/trojan_server/users_status.htm delete mode 100644 package/lienol/luci-app-trojan-server/po/zh-cn/trojan_server.po delete mode 100644 package/lienol/luci-app-trojan-server/root/etc/config/trojan_server delete mode 100755 package/lienol/luci-app-trojan-server/root/etc/init.d/trojan_server delete mode 100755 package/lienol/luci-app-trojan-server/root/etc/uci-defaults/luci-app-trojan-server delete mode 100755 package/lienol/luci-app-trojan-server/root/usr/share/trojan_server/firewall.include delete mode 100644 package/lienol/luci-app-webrestriction/Makefile delete mode 100644 package/lienol/luci-app-webrestriction/luasrc/controller/webrestriction.lua delete mode 100644 package/lienol/luci-app-webrestriction/luasrc/model/cbi/webrestriction.lua delete mode 100644 package/lienol/luci-app-webrestriction/luasrc/view/webrestriction/index.htm delete mode 100644 package/lienol/luci-app-webrestriction/luasrc/view/webrestriction/webrestriction.htm delete mode 100644 package/lienol/luci-app-webrestriction/po/zh-cn/webrestriction.po delete mode 100644 package/lienol/luci-app-webrestriction/root/etc/config/webrestriction delete mode 100755 package/lienol/luci-app-webrestriction/root/etc/init.d/webrestriction delete mode 100755 package/lienol/luci-app-webrestriction/root/etc/uci-defaults/luci-app-control-webrestriction delete mode 100644 package/lienol/luci-app-weburl/Makefile delete mode 100644 package/lienol/luci-app-weburl/luasrc/controller/weburl.lua delete mode 100644 package/lienol/luci-app-weburl/luasrc/model/cbi/weburl.lua delete mode 100644 package/lienol/luci-app-weburl/luasrc/view/weburl/index.htm delete mode 100644 package/lienol/luci-app-weburl/luasrc/view/weburl/weburl.htm delete mode 100644 package/lienol/luci-app-weburl/po/zh-cn/weburl.po delete mode 100644 package/lienol/luci-app-weburl/root/etc/config/weburl delete mode 100755 package/lienol/luci-app-weburl/root/etc/init.d/weburl delete mode 100755 package/lienol/luci-app-weburl/root/etc/uci-defaults/luci-app-control-weburl delete mode 100644 package/lienol/luci-theme-argon-dark-mod/Makefile delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/css/purecss.css delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/css/style.css delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/favicon.ico delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/TypoGraphica.eot delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/TypoGraphica.svg delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/TypoGraphica.ttf delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/TypoGraphica.woff delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/font.eot delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/font.svg delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/font.ttf delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/font.woff delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/icomoon.eot delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/icomoon.svg delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/icomoon.ttf delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/icomoon.woff delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/ssr.eot delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/ssr.svg delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/ssr.ttf delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/ssr.woff delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/img/bg1.jpg delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/img/bg2.jpg delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/img/bg3.jpg delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/js/jquery.min.js delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/js/script.js delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/logo.png delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark_purple/css/purecss.css delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark_purple/css/style.css delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark_purple/favicon.ico delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark_purple/fonts/TypoGraphica.eot delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark_purple/fonts/TypoGraphica.svg delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark_purple/fonts/TypoGraphica.ttf delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark_purple/fonts/TypoGraphica.woff delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark_purple/fonts/font.eot delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark_purple/fonts/font.svg delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark_purple/fonts/font.ttf delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark_purple/fonts/font.woff delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark_purple/fonts/icomoon.eot delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark_purple/fonts/icomoon.svg delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark_purple/fonts/icomoon.ttf delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark_purple/fonts/icomoon.woff delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark_purple/fonts/ssr.eot delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark_purple/fonts/ssr.svg delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark_purple/fonts/ssr.ttf delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark_purple/fonts/ssr.woff delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark_purple/img/bg1.jpg delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark_purple/img/bg2.jpg delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark_purple/img/bg3.jpg delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark_purple/js/jquery.min.js delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark_purple/js/script.js delete mode 100644 package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark_purple/logo.png delete mode 100644 package/lienol/luci-theme-argon-dark-mod/luasrc/view/themes/argon_dark/footer.htm delete mode 100644 package/lienol/luci-theme-argon-dark-mod/luasrc/view/themes/argon_dark/header.htm delete mode 100644 package/lienol/luci-theme-argon-dark-mod/luasrc/view/themes/argon_dark_purple/footer.htm delete mode 100644 package/lienol/luci-theme-argon-dark-mod/luasrc/view/themes/argon_dark_purple/header.htm delete mode 100755 package/lienol/luci-theme-argon-dark-mod/root/etc/uci-defaults/30_luci-theme-argon-dark-mod delete mode 100644 package/lienol/luci-theme-argon-light-mod/Makefile delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light/css/purecss.css delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light/css/style.css delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light/favicon.ico delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light/fonts/TypoGraphica.eot delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light/fonts/TypoGraphica.svg delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light/fonts/TypoGraphica.ttf delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light/fonts/TypoGraphica.woff delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light/fonts/font.eot delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light/fonts/font.svg delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light/fonts/font.ttf delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light/fonts/font.woff delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light/fonts/icomoon.eot delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light/fonts/icomoon.svg delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light/fonts/icomoon.ttf delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light/fonts/icomoon.woff delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light/fonts/ssr.eot delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light/fonts/ssr.svg delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light/fonts/ssr.ttf delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light/fonts/ssr.woff delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light/img/bg1.jpg delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light/img/bg2.jpg delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light/img/bg3.jpg delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light/js/jquery.min.js delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light/js/script.js delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light/logo.png delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light_green/css/purecss.css delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light_green/css/style.css delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light_green/favicon.ico delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light_green/fonts/TypoGraphica.eot delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light_green/fonts/TypoGraphica.svg delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light_green/fonts/TypoGraphica.ttf delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light_green/fonts/TypoGraphica.woff delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light_green/fonts/font.eot delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light_green/fonts/font.svg delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light_green/fonts/font.ttf delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light_green/fonts/font.woff delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light_green/fonts/icomoon.eot delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light_green/fonts/icomoon.svg delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light_green/fonts/icomoon.ttf delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light_green/fonts/icomoon.woff delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light_green/fonts/ssr.eot delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light_green/fonts/ssr.svg delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light_green/fonts/ssr.ttf delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light_green/fonts/ssr.woff delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light_green/img/bg1.jpg delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light_green/img/bg2.jpg delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light_green/img/bg3.jpg delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light_green/js/jquery.min.js delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light_green/js/script.js delete mode 100644 package/lienol/luci-theme-argon-light-mod/htdocs/luci-static/argon_light_green/logo.png delete mode 100644 package/lienol/luci-theme-argon-light-mod/luasrc/view/themes/argon_light/footer.htm delete mode 100644 package/lienol/luci-theme-argon-light-mod/luasrc/view/themes/argon_light/header.htm delete mode 100644 package/lienol/luci-theme-argon-light-mod/luasrc/view/themes/argon_light_green/footer.htm delete mode 100644 package/lienol/luci-theme-argon-light-mod/luasrc/view/themes/argon_light_green/header.htm delete mode 100755 package/lienol/luci-theme-argon-light-mod/root/etc/uci-defaults/30_luci-theme-argon-light-mod delete mode 100644 package/lienol/luci-theme-bootstrap-mod/Makefile delete mode 100644 package/lienol/luci-theme-bootstrap-mod/htdocs/luci-static/bootstrap_blue/cascade.css delete mode 100644 package/lienol/luci-theme-bootstrap-mod/htdocs/luci-static/bootstrap_blue/favicon.ico delete mode 100644 package/lienol/luci-theme-bootstrap-mod/htdocs/luci-static/bootstrap_blue/html5.js delete mode 100644 package/lienol/luci-theme-bootstrap-mod/htdocs/luci-static/bootstrap_blue/mobile.css delete mode 100644 package/lienol/luci-theme-bootstrap-mod/htdocs/luci-static/bootstrap_blue/wifi.png delete mode 100644 package/lienol/luci-theme-bootstrap-mod/htdocs/luci-static/bootstrap_mod/cascade.css delete mode 100644 package/lienol/luci-theme-bootstrap-mod/htdocs/luci-static/bootstrap_mod/favicon.ico delete mode 100644 package/lienol/luci-theme-bootstrap-mod/htdocs/luci-static/bootstrap_mod/html5.js delete mode 100644 package/lienol/luci-theme-bootstrap-mod/htdocs/luci-static/bootstrap_mod/mobile.css delete mode 100644 package/lienol/luci-theme-bootstrap-mod/htdocs/luci-static/bootstrap_mod/wifi.png delete mode 100644 package/lienol/luci-theme-bootstrap-mod/luasrc/view/themes/bootstrap_blue/footer.htm delete mode 100644 package/lienol/luci-theme-bootstrap-mod/luasrc/view/themes/bootstrap_blue/header.htm delete mode 100644 package/lienol/luci-theme-bootstrap-mod/luasrc/view/themes/bootstrap_mod/footer.htm delete mode 100644 package/lienol/luci-theme-bootstrap-mod/luasrc/view/themes/bootstrap_mod/header.htm delete mode 100755 package/lienol/luci-theme-bootstrap-mod/root/etc/uci-defaults/30_luci-theme-bootstrap-mod diff --git a/package/lienol/luci-app-brook-server/Makefile b/package/lienol/luci-app-brook-server/Makefile deleted file mode 100644 index 14ba04c393..0000000000 --- a/package/lienol/luci-app-brook-server/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (C) 2019-2020 Lienol -# -# This is free software, licensed under the GNU General Public License v3. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=luci-app-brook-server -LUCI_TITLE:=LuCI support for Brook Server -LUCI_DEPENDS:=+brook -LUCI_PKGARCH:=all -PKG_VERSION:=1 -PKG_RELEASE:=2-20200326 - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature - - diff --git a/package/lienol/luci-app-brook-server/luasrc/controller/brook_server.lua b/package/lienol/luci-app-brook-server/luasrc/controller/brook_server.lua deleted file mode 100644 index 324a35eb55..0000000000 --- a/package/lienol/luci-app-brook-server/luasrc/controller/brook_server.lua +++ /dev/null @@ -1,72 +0,0 @@ --- Copyright 2019 Lienol -module("luci.controller.brook_server", package.seeall) -local http = require "luci.http" -local brook = require "luci.model.cbi.brook_server.api.brook" - -function index() - if not nixio.fs.access("/etc/config/brook_server") then return end - entry({"admin", "vpn"}, firstchild(), "VPN", 45).dependent = false - entry({"admin", "vpn", "brook_server"}, cbi("brook_server/index"), - _("Brook Server"), 3).dependent = true - entry({"admin", "vpn", "brook_server", "config"}, cbi("brook_server/config")).leaf = - true - - entry({"admin", "vpn", "brook_server", "users_status"}, - call("brook_users_status")).leaf = true - entry({"admin", "vpn", "brook_server", "check"}, call("brook_check")).leaf = - true - entry({"admin", "vpn", "brook_server", "update"}, call("brook_update")).leaf = - true - entry({"admin", "vpn", "brook_server", "get_log"}, call("get_log")).leaf = - true - entry({"admin", "vpn", "brook_server", "clear_log"}, call("clear_log")).leaf = - true -end - -local function http_write_json(content) - http.prepare_content("application/json") - http.write_json(content or {code = 1}) -end - -function brook_users_status() - local e = {} - local index = luci.http.formvalue("index") - e.index = index - local protocol = luci.sys.exec("echo -n `uci get brook_server.@user[" .. - index .. "].protocol`") - local port = luci.sys.exec( - "echo -n `uci get brook_server.@user[" .. index .. - "].port`") - - local password = luci.sys.exec("echo -n `uci get brook_server.@user[" .. - index .. "].password`") - e.status = luci.sys.call( - "ps -w | grep -v grep | grep 'brook " .. protocol .. " -l :" .. - port .. " -p " .. password .. "' >/dev/null") == 0 - http_write_json(e) -end - -function brook_check() - local json = brook.to_check("") - http_write_json(json) -end - -function brook_update() - local json = nil - local task = http.formvalue("task") - if task == "move" then - json = brook.to_move(http.formvalue("file")) - else - json = brook.to_download(http.formvalue("url")) - end - - http_write_json(json) -end - -function get_log() - luci.http.write(luci.sys.exec( - "[ -f '/var/log/brook_server/app.log' ] && cat /var/log/brook_server/app.log")) -end - -function clear_log() luci.sys.call("echo '' > /var/log/brook_server/app.log") end - diff --git a/package/lienol/luci-app-brook-server/luasrc/model/cbi/brook_server/api/brook.lua b/package/lienol/luci-app-brook-server/luasrc/model/cbi/brook_server/api/brook.lua deleted file mode 100644 index 6319ef0752..0000000000 --- a/package/lienol/luci-app-brook-server/luasrc/model/cbi/brook_server/api/brook.lua +++ /dev/null @@ -1,338 +0,0 @@ -module("luci.model.cbi.brook_server.api.brook", package.seeall) -local fs = require "nixio.fs" -local sys = require "luci.sys" -local uci = require"luci.model.uci".cursor() -local util = require "luci.util" -local i18n = require "luci.i18n" - -local appname = "brook_server" -local brook_api = - "https://api.github.com/repos/txthinking/brook/releases/latest" - -local wget = "/usr/bin/wget" -local wget_args = { - "--no-check-certificate", "--quiet", "--timeout=100", "--tries=3" -} -local command_timeout = 300 - -local LEDE_BOARD = nil -local DISTRIB_TARGET = nil -local is_armv7 = false - -function uci_get_type(type, config, default) - value = uci:get(appname, "@" .. type .. "[0]", config) or sys.exec( - "echo -n `uci -q get " .. appname .. ".@" .. type .. "[0]." .. - config .. "`") - if (value == nil or value == "") and (default and default ~= "") then - value = default - end - return value -end - -local function _unpack(t, i) - i = i or 1 - if t[i] ~= nil then return t[i], _unpack(t, i + 1) end -end - -local function exec(cmd, args, writer, timeout) - local os = require "os" - local nixio = require "nixio" - - local fdi, fdo = nixio.pipe() - local pid = nixio.fork() - - if pid > 0 then - fdo:close() - - if writer or timeout then - local starttime = os.time() - while true do - if timeout and os.difftime(os.time(), starttime) >= timeout then - nixio.kill(pid, nixio.const.SIGTERM) - return 1 - end - - if writer then - local buffer = fdi:read(2048) - if buffer and #buffer > 0 then - writer(buffer) - end - end - - local wpid, stat, code = nixio.waitpid(pid, "nohang") - - if wpid and stat == "exited" then return code end - - if not writer and timeout then nixio.nanosleep(1) end - end - else - local wpid, stat, code = nixio.waitpid(pid) - return wpid and stat == "exited" and code - end - elseif pid == 0 then - nixio.dup(fdo, nixio.stdout) - fdi:close() - fdo:close() - nixio.exece(cmd, args, nil) - nixio.stdout:close() - os.exit(1) - end -end - -local function compare_versions(ver1, comp, ver2) - local table = table - - local av1 = util.split(ver1, "[%.%-]", nil, true) - local av2 = util.split(ver2, "[%.%-]", nil, true) - - local max = table.getn(av1) - local n2 = table.getn(av2) - if (max < n2) then max = n2 end - - for i = 1, max, 1 do - local s1 = av1[i] or "" - local s2 = av2[i] or "" - - if comp == "~=" and (s1 ~= s2) then return true end - if (comp == "<" or comp == "<=") and (s1 < s2) then return true end - if (comp == ">" or comp == ">=") and (s1 > s2) then return true end - if (s1 ~= s2) then return false end - end - - return not (comp == "<" or comp == ">") -end - -local function auto_get_arch() - local arch = nixio.uname().machine or "" - if fs.access("/usr/lib/os-release") then - LEDE_BOARD = sys.exec( - "echo -n `grep 'LEDE_BOARD' /usr/lib/os-release | awk -F '[\\042\\047]' '{print $2}'`") - end - if fs.access("/etc/openwrt_release") then - DISTRIB_TARGET = sys.exec( - "echo -n `grep 'DISTRIB_TARGET' /etc/openwrt_release | awk -F '[\\042\\047]' '{print $2}'`") - end - - if arch == "mips" then - if LEDE_BOARD and LEDE_BOARD ~= "" then - if string.match(LEDE_BOARD, "ramips") == "ramips" then - arch = "ramips" - else - arch = sys.exec("echo '" .. LEDE_BOARD .. - "' | grep -oE 'ramips|ar71xx'") - end - elseif DISTRIB_TARGET and DISTRIB_TARGET ~= "" then - if string.match(DISTRIB_TARGET, "ramips") == "ramips" then - arch = "ramips" - else - arch = sys.exec("echo '" .. DISTRIB_TARGET .. - "' | grep -oE 'ramips|ar71xx'") - end - end - end - - return util.trim(arch) -end - -local function get_file_info(arch) - local file_tree = "" - local sub_version = "" - - if arch == "x86_64" then - file_tree = "amd64" - elseif arch == "aarch64" then - file_tree = "arm64" - elseif arch == "ramips" then - file_tree = "mipsle" - elseif arch == "ar71xx" then - file_tree = "mips" - elseif arch:match("^i[%d]86$") then - file_tree = "386" - elseif arch:match("^armv[5-8]") then - file_tree = "arm" - sub_version = arch:match("[5-8]") - if LEDE_BOARD and string.match(LEDE_BOARD, "bcm53xx") == "bcm53xx" then - sub_version = "5" - elseif DISTRIB_TARGET and string.match(DISTRIB_TARGET, "bcm53xx") == - "bcm53xx" then - sub_version = "5" - end - sub_version = "5" - end - - return file_tree, sub_version -end - -function get_api_json(url) - local jsonc = require "luci.jsonc" - - local output = {} - -- exec(wget, { "-O-", url, _unpack(wget_args) }, - -- function(chunk) output[#output + 1] = chunk end) - -- local json_content = util.trim(table.concat(output)) - - local json_content = luci.sys.exec(wget .. - " --no-check-certificate --timeout=10 -t 1 -O- " .. - url) - - if json_content == "" then return {} end - - return jsonc.parse(json_content) or {} -end - -function get_brook_file_path() - return uci_get_type("global", "brook_path", "/usr/bin/brook") -end - -function get_brook_version(file) - if file == nil then file = get_brook_file_path() end - - if file and file ~= "" then - if not fs.access(file, "rwx", "rx", "rx") then - fs.chmod(file, 755) - end - - local info = util.trim(sys.exec("%s -v 2>/dev/null" % file)) - - if info ~= "" then - local tb = util.split(info, "%s+", nil, true) - return tb[1] == "Brook" and tb[3] or "" - end - end - - return "" -end - -function to_check(arch) - if not arch or arch == "" then arch = auto_get_arch() end - - local file_tree, sub_version = get_file_info(arch) - - if file_tree == "" then - return { - code = 1, - error = i18n.translate( - "Can't determine ARCH, or ARCH not supported.") - } - end - - file_tree = "_linux_" .. file_tree - if file_tree == "_linux_amd64" then file_tree = "" end - - local json = get_api_json(brook_api) - - if json.tag_name == nil then - return { - code = 1, - error = i18n.translate("Get remote version info failed.") - } - end - - local remote_version = json.tag_name:match("[^v]+") - - local client_file = get_brook_file_path() - - local needs_update = compare_versions(get_brook_version(client_file), "<", - remote_version) - local html_url, download_url - - if needs_update then - html_url = json.html_url - for _, v in ipairs(json.assets) do - if v.name and v.name:match(file_tree .. sub_version) then - download_url = v.browser_download_url - break - end - end - end - - if needs_update and not download_url then - return { - code = 1, - now_version = get_brook_version(client_file), - version = remote_version, - html_url = html_url, - error = i18n.translate( - "New version found, but failed to get new version download url.") - } - end - - return { - code = 0, - update = needs_update, - now_version = get_brook_version(client_file), - version = remote_version, - url = {html = html_url, download = download_url} - } -end - -function to_download(url) - if not url or url == "" then - return {code = 1, error = i18n.translate("Download url is required.")} - end - - sys.call("/bin/rm -f /tmp/brook_download.*") - - local tmp_file = util.trim(util.exec("mktemp -u -t brook_download.XXXXXX")) - - local result = exec(wget, {"-O", tmp_file, url, _unpack(wget_args)}, nil, - command_timeout) == 0 - - if not result then - exec("/bin/rm", {"-f", tmp_file}) - return { - code = 1, - error = i18n.translatef("File download failed or timed out: %s", url) - } - end - - return {code = 0, file = tmp_file} -end - -function to_move(file) - if not file or file == "" or not fs.access(file) then - sys.call("/bin/rm -rf /tmp/brook_download.*") - return {code = 1, error = i18n.translate("Client file is required.")} - end - - local version = get_brook_version(file) - if version == "" then - sys.call("/bin/rm -rf /tmp/brook_download.*") - return { - code = 1, - error = i18n.translate( - "The client file is not suitable for current device.") - } - end - - local client_file = get_brook_file_path() - local client_file_bak - - if fs.access(client_file) then - client_file_bak = client_file .. ".bak" - exec("/bin/mv", {"-f", client_file, client_file_bak}) - end - - local result = exec("/bin/mv", {"-f", file, client_file}, nil, - command_timeout) == 0 - - if not result or not fs.access(client_file) then - sys.call("/bin/rm -rf /tmp/brook_download.*") - if client_file_bak then - exec("/bin/mv", {"-f", client_file_bak, client_file}) - end - return { - code = 1, - error = i18n.translatef("Can't move new file to path: %s", - client_file) - } - end - - exec("/bin/chmod", {"755", client_file}) - - if client_file_bak then exec("/bin/rm", {"-f", client_file_bak}) end - - sys.call("/bin/rm -rf /tmp/brook_download.*") - - return {code = 0} -end diff --git a/package/lienol/luci-app-brook-server/luasrc/model/cbi/brook_server/config.lua b/package/lienol/luci-app-brook-server/luasrc/model/cbi/brook_server/config.lua deleted file mode 100644 index 61ce68c8a3..0000000000 --- a/package/lienol/luci-app-brook-server/luasrc/model/cbi/brook_server/config.lua +++ /dev/null @@ -1,32 +0,0 @@ -local app_name = "brook_server" -local d = require "luci.dispatcher" - -map = Map(app_name, "Brook " .. translate("Server Config")) -map.redirect = d.build_url("admin", "vpn", "brook_server") - -t = map:section(NamedSection, arg[1], "user", "") -t.addremove = false -t.dynamic = false - -enable = t:option(Flag, "enable", translate("Enable")) -enable.default = "1" -enable.rmempty = false - -remarks = t:option(Value, "remarks", translate("Remarks")) -remarks.default = translate("Remarks") -remarks.rmempty = false - -port = t:option(Value, "port", translate("Port")) -port.datatype = "port" -port.rmempty = false - -protocol = t:option(ListValue, "protocol", translate("Protocol"), translate( - "if shadowsocks server mode, fixed method is aes-256-cfb")) -protocol:value("server", translate("Brook")) -protocol:value("ssserver", translate("Shadowsocks")) - -password = t:option(Value, "password", translate("Password")) -password.password = true -password.rmempty = false - -return map diff --git a/package/lienol/luci-app-brook-server/luasrc/model/cbi/brook_server/index.lua b/package/lienol/luci-app-brook-server/luasrc/model/cbi/brook_server/index.lua deleted file mode 100644 index 0a514f7e43..0000000000 --- a/package/lienol/luci-app-brook-server/luasrc/model/cbi/brook_server/index.lua +++ /dev/null @@ -1,66 +0,0 @@ -local i = require "luci.dispatcher" -local e = require "nixio.fs" -local e = require "luci.sys" -local e = luci.model.uci.cursor() -local o = "brook_server" - -m = Map(o, translate("Brook Server")) - -t = m:section(TypedSection, "global", translate("Global Settings")) -t.anonymous = true -t.addremove = false - -e = t:option(Flag, "enable", translate("Enable")) -e.rmempty = false -t:append(Template("brook_server/brook")) - -e = t:option(Value, "brook_path", translate("Brook Path"), - translate( - "if you want to run from memory, change the path, such as /tmp/brook, Then save the application and update it manually.")) -e.default = "/usr/bin/brook" -e.rmempty = false - -t = m:section(TypedSection, "user", translate("Users Manager")) -t.anonymous = true -t.addremove = true -t.template = "cbi/tblsection" -t.extedit = i.build_url("admin", "vpn", o, "config", "%s") -function t.create(t, e) - local e = TypedSection.create(t, e) - luci.http.redirect(i.build_url("admin", "vpn", o, "config", e)) -end -function t.remove(t, a) - t.map.proceed = true - t.map:del(a) - luci.http.redirect(i.build_url("admin", "vpn", o)) -end -e = t:option(Flag, "enable", translate("Enable")) -e.width = "5%" -e.rmempty = false -e = t:option(DummyValue, "status", translate("Status")) -e.template = "brook_server/users_status" -e.value = translate("Collecting data...") -e = t:option(DummyValue, "remarks", translate("Remarks")) -e.width = "20%" -e = t:option(DummyValue, "port", translate("Port")) -e.width = "20%" - -e = t:option(DummyValue, "password", translate("Password")) -e.width = "30%" -e.cfgvalue = function(self, section) - local e = m:get(section, "password") or "" - local t = "" - if type(e) == "table" then - for a = 1, #e do t = t .. e[a] .. "," end - t = string.sub(t, 0, #t - 1) - else - t = e - end - return t -end - -m:append(Template("brook_server/log")) - -m:append(Template("brook_server/users_list_status")) -return m - diff --git a/package/lienol/luci-app-brook-server/luasrc/view/brook_server/brook.htm b/package/lienol/luci-app-brook-server/luasrc/view/brook_server/brook.htm deleted file mode 100644 index 373e65f204..0000000000 --- a/package/lienol/luci-app-brook-server/luasrc/view/brook_server/brook.htm +++ /dev/null @@ -1,168 +0,0 @@ -<% -local brook_path = luci.sys.exec("echo -n `uci get brook_server.@global[0].brook_path`") -local brook_version = luci.sys.exec("[ -f '" .. brook_path .. "' ] && " .. brook_path .. " -v | awk '{print $3}'") -local dsp = require "luci.dispatcher" --%> - - - -
- -
-
- 【 <%=brook_version%>】 - - -
-
-
\ No newline at end of file diff --git a/package/lienol/luci-app-brook-server/luasrc/view/brook_server/log.htm b/package/lienol/luci-app-brook-server/luasrc/view/brook_server/log.htm deleted file mode 100644 index fd2dcdfdb1..0000000000 --- a/package/lienol/luci-app-brook-server/luasrc/view/brook_server/log.htm +++ /dev/null @@ -1,31 +0,0 @@ - -
- - <%:Logs%> - - - -
\ No newline at end of file diff --git a/package/lienol/luci-app-brook-server/luasrc/view/brook_server/users_list_status.htm b/package/lienol/luci-app-brook-server/luasrc/view/brook_server/users_list_status.htm deleted file mode 100644 index b162365bb9..0000000000 --- a/package/lienol/luci-app-brook-server/luasrc/view/brook_server/users_list_status.htm +++ /dev/null @@ -1,23 +0,0 @@ -<% -local dsp = require "luci.dispatcher" --%> - - \ No newline at end of file diff --git a/package/lienol/luci-app-brook-server/luasrc/view/brook_server/users_status.htm b/package/lienol/luci-app-brook-server/luasrc/view/brook_server/users_status.htm deleted file mode 100644 index 69dc5ea382..0000000000 --- a/package/lienol/luci-app-brook-server/luasrc/view/brook_server/users_status.htm +++ /dev/null @@ -1,3 +0,0 @@ -<%+cbi/valueheader%> --- -<%+cbi/valuefooter%> \ No newline at end of file diff --git a/package/lienol/luci-app-brook-server/po/zh-cn/brook_server.po b/package/lienol/luci-app-brook-server/po/zh-cn/brook_server.po deleted file mode 100644 index 1891a2e798..0000000000 --- a/package/lienol/luci-app-brook-server/po/zh-cn/brook_server.po +++ /dev/null @@ -1,83 +0,0 @@ -msgid "Brook Server" -msgstr "Brook 服务器" - -msgid "Global Settings" -msgstr "全局设置" - -msgid "Brook Path" -msgstr "Brook路径" - -msgid "if you want to run from memory, change the path, such as /tmp/brook, Then save the application and update it manually." -msgstr "如果你希望从内存中运行,请更改路径,例如/tmp/brook,然后保存应用后,再手动更新。" - -msgid "Server Config" -msgstr "服务器配置" - -msgid "Users Manager" -msgstr "用户管理" - -msgid "Remarks" -msgstr "备注" - -msgid "Port" -msgstr "端口" - -msgid "Password" -msgstr "密码" - -msgid "Protocol" -msgstr "协议" - -msgid "if shadowsocks server mode, fixed method is aes-256-cfb" -msgid "当shadowsocks服务器模式时,固定的加密为 aes-256-cfb" - -msgid "Logs" -msgstr "日志" - -msgid "Clear logs" -msgstr "清空日志" - -msgid "Can't determine ARCH, or ARCH not supported." -msgstr "无法确认ARCH架构,或是不支持。" - -msgid "Get remote version info failed." -msgstr "获取远程版本信息失败。" - -msgid "New version found, but failed to get new version download url." -msgstr "发现新版本,但未能获得新版本的下载地址。" - -msgid "Download url is required." -msgstr "请指定下载地址。" - -msgid "File download failed or timed out: %s" -msgstr "文件下载失败或超时:%s" - -msgid "File path required." -msgstr "请指定文件路径。" - -msgid "Can't find client in file: %s" -msgstr "无法在文件中找到客户端:%s" - -msgid "Client file is required." -msgstr "请指定客户端文件。" - -msgid "The client file is not suitable for current device." -msgstr "客户端文件不适合当前设备。" - -msgid "Can't move new file to path: %s" -msgstr "无法移动新文件到:%s" - -msgid "Enabled" -msgstr "启用" - -msgid "Status" -msgstr "状态" - -msgid "Current Condition" -msgstr "当前状态" - -msgid "NOT RUNNING" -msgstr "未运行" - -msgid "RUNNING" -msgstr "运行中" \ No newline at end of file diff --git a/package/lienol/luci-app-brook-server/root/etc/config/brook_server b/package/lienol/luci-app-brook-server/root/etc/config/brook_server deleted file mode 100644 index 9ff175b266..0000000000 --- a/package/lienol/luci-app-brook-server/root/etc/config/brook_server +++ /dev/null @@ -1,12 +0,0 @@ - -config global - option enable '0' - option brook_path '/usr/bin/brook' - -config user - option remarks '测试' - option port '12345' - list password 'aaa' - option protocol 'server' - option enable '1' - diff --git a/package/lienol/luci-app-brook-server/root/etc/init.d/brook_server b/package/lienol/luci-app-brook-server/root/etc/init.d/brook_server deleted file mode 100755 index dad3ef15ac..0000000000 --- a/package/lienol/luci-app-brook-server/root/etc/init.d/brook_server +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2019-2020 Lienol - -START=99 - -CONFIG=brook_server -LOG_PATH=/var/log/$CONFIG -LOG_APP_FILE=$LOG_PATH/app.log - -echolog() { - echo -e "$(date "+%Y-%m-%d %H:%M:%S"): $1" >> $LOG_APP_FILE -} - -gen_brook_config_file() { - config_get enable $1 enable - [ "$enable" = "0" ] && return 0 - config_get remarks $1 remarks - config_get port $1 port - config_get protocol $1 protocol - config_get password $1 password - - /usr/bin/brook $protocol -l :$port -p $password >/dev/null 2>&1 & - - is_run=$(ps -w| grep -v grep | grep "brook $protocol -l :$port -p $password") - if [ -z "$is_run" ];then - echolog "$remarks $port Brook 运行失败" - else - echolog "$remarks $port Brook 运行成功" - fi -} - -start_brook_server() { - mkdir -p $LOG_PATH - touch $LOG_APP_FILE - config_foreach gen_brook_config_file "user" - fw3 reload >/dev/null 2>&1 & -} - -stop_brook_server() { - fw3 reload >/dev/null 2>&1 - ps -w | grep "brook server" | grep -v "grep" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 & - ps -w | grep "brook ssserver" | grep -v "grep" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 & - rm -rf $LOG_PATH -} - -start() { - config_load $CONFIG - enable=$(uci -q get $CONFIG.@global[0].enable) - if [ "$enable" = "0" ];then - stop_brook_server - else - start_brook_server - fi -} - -stop() { - stop_brook_server -} - -restart() { - stop - start -} \ No newline at end of file diff --git a/package/lienol/luci-app-brook-server/root/etc/uci-defaults/luci-app-brook-server b/package/lienol/luci-app-brook-server/root/etc/uci-defaults/luci-app-brook-server deleted file mode 100755 index f1f5e014dd..0000000000 --- a/package/lienol/luci-app-brook-server/root/etc/uci-defaults/luci-app-brook-server +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete firewall.brook_server - set firewall.brook_server=include - set firewall.brook_server.type=script - set firewall.brook_server.path=/usr/share/brook_server/firewall.include - set firewall.brook_server.reload=1 -EOF - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@brook_server[-1] - add ucitrack brook_server - set ucitrack.@brook_server[-1].init=brook_server - commit ucitrack -EOF - -chmod a+x /usr/share/brook_server/* >/dev/null 2>&1 - -rm -f /tmp/luci-indexcache -exit 0 diff --git a/package/lienol/luci-app-brook-server/root/usr/share/brook_server/firewall.include b/package/lienol/luci-app-brook-server/root/usr/share/brook_server/firewall.include deleted file mode 100755 index 94b0d18acd..0000000000 --- a/package/lienol/luci-app-brook-server/root/usr/share/brook_server/firewall.include +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/sh - -count=$(iptables -n -L INPUT 2>/dev/null | grep -c "BROOK-SERVER") -if [ -n "$count" ]; then - until [ "$count" = 0 ] - do - rules=$(iptables -n -L INPUT --line-num 2>/dev/null | grep "BROOK-SERVER" | awk '{print $1}') - for rule in $rules - do - iptables -D INPUT $rule 2>/dev/null - break - done - count=$(expr $count - 1) - done -fi - -iptables -F BROOK-SERVER 2>/dev/null && iptables -X BROOK-SERVER 2>/dev/null - -enable=$(uci -q get brook_server.@global[0].enable) -if [ $enable -eq 1 ]; then - iptables -N BROOK-SERVER - iptables -I INPUT -j BROOK-SERVER - - count=$(uci show brook_server | grep "@user" | sed -n '$p' | cut -d '[' -f 2 | cut -d ']' -f 1) - [ -n "$count" ] && [ "$count" -ge 0 ] && { - u_get() { - local ret=$(uci -q get brook_server.@user[$1].$2) - echo ${ret:=$3} - } - for i in $(seq 0 $count); do - enable=$(u_get $i enable 0) - [ $enable -eq 0 ] && continue - remarks=$(u_get $i remarks) - port=$(u_get $i port) - iptables -A BROOK-SERVER -p tcp --dport $port -m comment --comment "$remarks" -j ACCEPT - iptables -A BROOK-SERVER -p udp --dport $port -m comment --comment "$remarks" -j ACCEPT - done - } -fi diff --git a/package/lienol/luci-app-fileassistant/Makefile b/package/lienol/luci-app-fileassistant/Makefile deleted file mode 100644 index f9c2df58f3..0000000000 --- a/package/lienol/luci-app-fileassistant/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# From https://github.com/DarkDean89/luci-app-filebrowser -# From https://github.com/stuarthua/oh-my-openwrt/tree/master/stuart/luci-app-fileassistant -# This is free software, licensed under the Apache License, Version 2.0 . - -include $(TOPDIR)/rules.mk - -LUCI_TITLE:=LuCI support for Fileassistant -LUCI_PKGARCH:=all -PKG_VERSION:=1.0 -PKG_RELEASE:=2 - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature diff --git a/package/lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/fb.css b/package/lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/fb.css deleted file mode 100644 index 96cbbb3fc5..0000000000 --- a/package/lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/fb.css +++ /dev/null @@ -1,68 +0,0 @@ -.fb-container { - margin-top: 1rem; -} -.fb-container .cbi-button { - height: 1.8rem; -} -.fb-container .cbi-input-text { - margin-bottom: 1rem; - width: 100%; -} -.fb-container .panel-title { - padding-bottom: 0; - width: 50%; - border-bottom: none; -} -.fb-container .panel-container { - display: flex; - align-items: center; - justify-content: space-between; - padding-bottom: 1rem; - border-bottom: 1px solid #eee; -} -.fb-container .upload-container { - display: none; - margin: 1rem 0; -} -.fb-container .upload-file { - margin-right: 2rem; -} -.fb-container .cbi-value-field { - text-align: left; -} -.fb-container .parent-icon strong { - margin-left: 1rem; -} -.fb-container td[class$="-icon"] { - cursor: pointer; -} -.fb-container .file-icon, .fb-container .folder-icon, .fb-container .link-icon { - position: relative; -} -.fb-container .file-icon:before, .fb-container .folder-icon:before, .fb-container .link-icon:before { - display: inline-block; - width: 1.5rem; - height: 1.5rem; - content: ''; - background-size: contain; - margin: 0 0.5rem 0 1rem; - vertical-align: middle; -} -.fb-container .file-icon:before { - background-image: url(file-icon.png); -} -.fb-container .folder-icon:before { - background-image: url(folder-icon.png); -} -.fb-container .link-icon:before { - background-image: url(link-icon.png); -} -@media screen and (max-width: 480px) { - .fb-container .upload-file { - width: 14.6rem; - } - .fb-container .cbi-value-owner, - .fb-container .cbi-value-perm { - display: none; - } -} diff --git a/package/lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/fb.js b/package/lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/fb.js deleted file mode 100644 index 2e3addef81..0000000000 --- a/package/lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/fb.js +++ /dev/null @@ -1,288 +0,0 @@ -String.prototype.replaceAll = function(search, replacement) { - var target = this; - return target.replace(new RegExp(search, 'g'), replacement); -}; -(function () { - var iwxhr = new XHR(); - var listElem = document.getElementById("list-content"); - listElem.onclick = handleClick; - var currentPath; - var pathElem = document.getElementById("current-path"); - pathElem.onblur = function () { - update_list(this.value.trim()); - }; - pathElem.onkeyup = function (evt) { - if (evt.keyCode == 13) { - this.blur(); - } - }; - function removePath(filename, isdir) { - var c = confirm('你确定要删除 ' + filename + ' 吗?'); - if (c) { - iwxhr.get('/cgi-bin/luci/admin/nas/fileassistant/delete', - { - path: concatPath(currentPath, filename), - isdir: isdir - }, - function (x, res) { - if (res.ec === 0) { - refresh_list(res.data, currentPath); - } - }); - } - } - - function installPath(filename, isdir) { - if (isdir === "1") { - alert('这是一个目录,请选择 ipk 文件进行安装!'); - return; - } - var isipk = isIPK(filename); - if (isipk === 0) { - alert('只允许安装 ipk 格式的文件!'); - return; - } - var c = confirm('你确定要安装 ' + filename + ' 吗?'); - if (c) { - iwxhr.get('/cgi-bin/luci/admin/nas/fileassistant/install', - { - filepath: concatPath(currentPath, filename), - isdir: isdir - }, - function (x, res) { - if (res.ec === 0) { - location.reload(); - alert('安装成功!'); - } else { - alert('安装失败,请检查文件格式!'); - } - }); - } - } - - function isIPK(filename) { - var index= filename.lastIndexOf("."); - var ext = filename.substr(index+1); - if (ext === 'ipk') { - return 1; - } else { - return 0; - } - } - - function renamePath(filename) { - var newname = prompt('请输入新的文件名:', filename); - if (newname) { - newname = newname.trim(); - if (newname != filename) { - var newpath = concatPath(currentPath, newname); - iwxhr.get('/cgi-bin/luci/admin/nas/fileassistant/rename', - { - filepath: concatPath(currentPath, filename), - newpath: newpath - }, - function (x, res) { - if (res.ec === 0) { - refresh_list(res.data, currentPath); - } - } - ); - } - } - } - - function openpath(filename, dirname) { - dirname = dirname || currentPath; - window.open('/cgi-bin/luci/admin/nas/fileassistant/open?path=' - + encodeURIComponent(dirname) + '&filename=' - + encodeURIComponent(filename)); - } - - function getFileElem(elem) { - if (elem.className.indexOf('-icon') > -1) { - return elem; - } - else if (elem.parentNode.className.indexOf('-icon') > -1) { - return elem.parentNode; - } - } - - function concatPath(path, filename) { - if (path === '/') { - return path + filename; - } - else { - return path.replace(/\/$/, '') + '/' + filename; - } - } - - function handleClick(evt) { - var targetElem = evt.target; - var infoElem; - if (targetElem.className.indexOf('cbi-button-remove') > -1) { - infoElem = targetElem.parentNode.parentNode; - removePath(infoElem.dataset['filename'] , infoElem.dataset['isdir']) - } - else if (targetElem.className.indexOf('cbi-button-install') > -1) { - infoElem = targetElem.parentNode.parentNode; - installPath(infoElem.dataset['filename'] , infoElem.dataset['isdir']) - } - else if (targetElem.className.indexOf('cbi-button-edit') > -1) { - renamePath(targetElem.parentNode.parentNode.dataset['filename']); - } - else if (targetElem = getFileElem(targetElem)) { - if (targetElem.className.indexOf('parent-icon') > -1) { - update_list(currentPath.replace(/\/[^/]+($|\/$)/, '')); - } - else if (targetElem.className.indexOf('file-icon') > -1) { - openpath(targetElem.parentNode.dataset['filename']); - } - else if (targetElem.className.indexOf('link-icon') > -1) { - infoElem = targetElem.parentNode; - var filepath = infoElem.dataset['linktarget']; - if (filepath) { - if (infoElem.dataset['isdir'] === "1") { - update_list(filepath); - } - else { - var lastSlash = filepath.lastIndexOf('/'); - openpath(filepath.substring(lastSlash + 1), filepath.substring(0, lastSlash)); - } - } - } - else if (targetElem.className.indexOf('folder-icon') > -1) { - update_list(concatPath(currentPath, targetElem.parentNode.dataset['filename'])) - } - } - } - function refresh_list(filenames, path) { - var listHtml = ''; - if (path !== '/') { - listHtml += ''; - } - if (filenames) { - for (var i = 0; i < filenames.length; i++) { - var line = filenames[i]; - if (line) { - var f = line.match(/(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+([\S\s]+)/); - var isLink = f[1][0] === 'z' || f[1][0] === 'l' || f[1][0] === 'x'; - var o = { - displayname: f[9], - filename: isLink ? f[9].split(' -> ')[0] : f[9], - perms: f[1], - date: f[7] + ' ' + f[6] + ' ' + f[8], - size: f[5], - owner: f[3], - icon: (f[1][0] === 'd') ? "folder-icon" : (isLink ? "link-icon" : "file-icon") - }; - - var install_btn = ''; - var index= o.filename.lastIndexOf("."); - var ext = o.filename.substr(index+1); - if (ext === 'ipk') { - install_btn = ''; - } - - listHtml += '' - + '' - + '' - + '' - + '' - + '' - + '' - + ''; - } - } - } - listHtml += "
..
' - + '' + o.displayname + '' - + ''+o.owner+''+o.date+''+o.size+''+o.perms+'\ - \ - ' - + install_btn - + '
"; - listElem.innerHTML = listHtml; - } - function update_list(path, opt) { - opt = opt || {}; - path = concatPath(path, ''); - if (currentPath != path) { - iwxhr.get('/cgi-bin/luci/admin/nas/fileassistant/list', - {path: path}, - function (x, res) { - if (res.ec === 0) { - refresh_list(res.data, path); - } - else { - refresh_list([], path); - } - } - ); - if (!opt.popState) { - history.pushState({path: path}, null, '?path=' + path); - } - currentPath = path; - pathElem.value = currentPath; - } - }; - - var uploadToggle = document.getElementById('upload-toggle'); - var uploadContainer = document.getElementById('upload-container'); - var isUploadHide = true; - uploadToggle.onclick = function() { - if (isUploadHide) { - uploadContainer.style.display = 'inline-flex'; - } - else { - uploadContainer.style.display = 'none'; - } - isUploadHide = !isUploadHide; - }; - var uploadBtn = uploadContainer.getElementsByClassName('cbi-input-apply')[0]; - uploadBtn.onclick = function (evt) { - var uploadinput = document.getElementById('upload-file'); - var fullPath = uploadinput.value; - if (!fullPath) { - evt.preventDefault(); - } - else { - var formData = new FormData(); - var startIndex = (fullPath.indexOf('\\') >= 0 ? fullPath.lastIndexOf('\\') : fullPath.lastIndexOf('/')); - formData.append('upload-filename', fullPath.substring(startIndex + 1)); - formData.append('upload-dir', concatPath(currentPath, '')); - formData.append('upload-file', uploadinput.files[0]); - var xhr = new XMLHttpRequest(); - xhr.open("POST", "/cgi-bin/luci/admin/nas/fileassistant/upload", true); - xhr.onload = function() { - if (xhr.status == 200) { - var res = JSON.parse(xhr.responseText); - refresh_list(res.data, currentPath); - uploadinput.value = ''; - } - else { - alert('上传失败,请稍后再试...'); - } - }; - xhr.send(formData); - } - }; - - document.addEventListener('DOMContentLoaded', function(evt) { - var initPath = '/'; - if (/path=([/\w]+)/.test(location.search)) { - initPath = RegExp.$1; - } - update_list(initPath, {popState: true}); - }); - window.addEventListener('popstate', function (evt) { - var path = '/'; - if (evt.state && evt.state.path) { - path = evt.state.path; - } - update_list(path, {popState: true}); - }); - -})(); \ No newline at end of file diff --git a/package/lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/file-icon.png b/package/lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/file-icon.png deleted file mode 100644 index f156dc1c7ce823b64401a62e249a377a52b20518..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1098 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H3?#oinD~={fiXV7C&U%V9R;)t0gq*U=0MX+ zN`m}?85o(ESyC4w|-+%u4`_J-}sTczTlbWZCV@SoVw>LwB4?74P_~>1@e8=wH z&fU=qckC8l&g%8~Z~JzK84Nd5-}BA*yTAO~_e*zul#cA)^xP@%bNkV}@@1=Sm_nnE zsJyDOVK&^ans!Nao=4-k^E=Evcdue#I_C3e(OiQAVx|XrN*fszgEv38bVX+ZBLk<7 zgTLLX>}*a2RcCnDxd+V)Vr>uTRp^EDZ{YS5zRLWD zX+K+oZ^7&}j0wVDUNLYaA7pxy&DgP{)_cNgRs|`Y0}Vb07X9Dsw#Gcb+lVpm)>U4M z$qW{)40rHDoarZKhfLm@t>etnLD$M)VPGsasI53}8!m{U0}y(IC{&iZ7U@Z(z4w(uZ zdD~j}0zR}v9-Sy-)WBcf^Xq4217k{qqRfJRo(bPOX3BrNq`T>@q1(e(-elb6Mw<&;$T^(=;mp diff --git a/package/lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/folder-icon.png b/package/lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/folder-icon.png deleted file mode 100644 index 1370df3ad554fcb4d11aa0a72510dd3011cb816b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1292 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H3?#oinD~={fpJ5CPlzj!I|_zS2>kviS_E`% ze@T#EFaskKGYcy_2PYRdFCV{vkf@Z5tfH!#x`w8fw!Wc}v8kDbjjg?lo4bdnkDq@~ zNLWNlrlO|7@I&aaqIS-d-oqce)9C$^A|5)y?Oio-m(|)^6tj@ffbcxT$swdA#S9dDM(%YwA z=;`}t7X5o_cb4ab+U_%F*2&+yf4uTu`aSv6Ja0aq(Nkn#*l^0gUv=J|pA)vGDNXH| z5%v0TKlc`43d@{VRt#TOUdn344I z@hKL)O`5@Fmn5gzE%#Z_?rWK(J~!oMUO$Ulc&~%n!wIve^Uc&^UG?bc&k5U^ru=(j z@`QzLrH*H?*MqJt41c#ox+Tos!|->br&GfhO@k9=UK}j*vdPWQ;8$FBYF>a>4u(+{}*QfsHlKk>Zp>C@i+ z=-vG8o4>hkyxc=p^WV?EPtm_nYx(`x^Fv|LOMcFc{wo~4#ynGFUisp>jo<(Kx0>Jm zv2ORj?3$<7m1}nIe$U6#pOIMcz^`O^KR5$71pQ;2AX!`B8su&V67Y2Ob6Mw<&;$S{ CYKQCq diff --git a/package/lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/link-icon.png b/package/lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/link-icon.png deleted file mode 100644 index 03cc82cdfabae20c1036959e6244ba5039f74697..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1622 zcmV-c2C4apP) zTWB0r7{`CvG(@YF+Ik_0m)2IR7C|eeQV{DEMU;wAE9isZi=a^9kCznM9+=gj%O9~|iA?Ch8G|LvKX zvojMgeDf4=0GI-r5w@eiYrtSt1E87hgb!HSz5)jOD;Wlz+y%TJx`-UC0475hkrF!y z|EbQ~jx;J63Y}aZx_|<#Gy(i^GIRk&FaiAWLFfXCUp~Y|grgsLkMIX~ z;?`HLNi`mIEI~P-w`uS~5@_sDlIxvK}}VL6M_I9?R1z#|E36NA7Z}R<1N{Sh4(!8SZE_Zv$+?YKISw53yv=Fgxz?YfS}b~!eD<6M zUIvzgC^i9NnF#<`1RT!sqAzf}3!@y@68?A#fUP-Rup1cgJrW8T0e&Wu8Q@D{=g)An zg;9=J!fyf$;||)obvywqt6(s+5mWe0fM_pZ#`C~v zpbp_T8^|u;oGv&BT8Vzz&#)Uq{8MH4XMJzb1n|o+)rEhkwO#LbAWQZYKCXyKonflm z=l{g{FW-EBi)aFPpjY8%_>{l|C`qrw&+sLI2~dJi;b-`ezyv5r=qGj$KYod<9td;+`)+|mA@Ccs=$3co8R zz=fy^A54ID)P)ZwK!(cj!2|%s;e!dFI(*PAfco%3uK*T)3ylI;_-$wtpvv$^sag1- zOMoFP{5fb5z`~yg4FXvB3y``17Je5}7Qn(6kg5O{zK|3Ju<&z`ngAAlPErye_V5=2 zdw{79+n)kH0xl}~9=SFI|p1p)eSSG!gf{{8p~KT1*%U@6r+$1wTuAq@fk!ri&!6BXe@8Ui$d&A4Cm>;pC7 zLmC1Ai~;vjUIJC&LplOLc?r~o4`~Si#U)S~KBOlAiUmAeTUO_>isu&|L!c z;X~R2!2A+e_$^Ww0M1J=*82N5Sor^=<(EK?0c&wz$9jL}ex1=U17tL@@aLdO0HXsY zfO1R#<(L4P>u0=T5&T2kj}++9rF zkmTW&Ey!+=+&13^jILY^9HaXf|B6f!uUrnC6BKs_+0Bi{T;4$TA=?qEz)yt*{s1fq zRAXJ)jQlqAdji$S!@>faz+UXMP|9P#zsR3K(DUg(qYwDLOM&fe9Jn(`rS)I{compN zKBilPRNBTS@;x?vm_@O**oj05{{=dgd%", "/") - path = path:gsub(" ", "\ ") - local success - if isdir then - success = os.execute('rm -r "'..path..'"') - else - success = os.remove(path) - end - list_response(nixio.fs.dirname(path), success) -end - -function fileassistant_rename() - local filepath = luci.http.formvalue("filepath") - local newpath = luci.http.formvalue("newpath") - local success = os.execute('mv "'..filepath..'" "'..newpath..'"') - list_response(nixio.fs.dirname(filepath), success) -end - -function fileassistant_install() - local filepath = luci.http.formvalue("filepath") - local isdir = luci.http.formvalue("isdir") - local ext = filepath:match(".+%.(%w+)$") - filepath = filepath:gsub("<>", "/") - filepath = filepath:gsub(" ", "\ ") - local success - if isdir == "1" then - success = false - elseif ext == "ipk" then - success = installIPK(filepath) - else - success = false - end - list_response(nixio.fs.dirname(filepath), success) -end - -function installIPK(filepath) - luci.sys.exec('opkg --force-depends install "'..filepath..'"') - luci.sys.exec('rm -rf /tmp/luci-*') - return true; -end - -function fileassistant_upload() - local filecontent = luci.http.formvalue("upload-file") - local filename = luci.http.formvalue("upload-filename") - local uploaddir = luci.http.formvalue("upload-dir") - local filepath = uploaddir..filename - - local fp - luci.http.setfilehandler( - function(meta, chunk, eof) - if not fp and meta and meta.name == "upload-file" then - fp = io.open(filepath, "w") - end - if fp and chunk then - fp:write(chunk) - end - if fp and eof then - fp:close() - end - end - ) - - list_response(uploaddir, true) -end - -function scandir(directory) - local i, t, popen = 0, {}, io.popen - - local pfile = popen("ls -lh \""..directory.."\" | egrep '^d' ; ls -lh \""..directory.."\" | egrep -v '^d|^l'") - for fileinfo in pfile:lines() do - i = i + 1 - t[i] = fileinfo - end - pfile:close() - pfile = popen("ls -lh \""..directory.."\" | egrep '^l' ;") - for fileinfo in pfile:lines() do - i = i + 1 - linkindex, _, linkpath = string.find(fileinfo, "->%s+(.+)$") - local finalpath; - if string.sub(linkpath, 1, 1) == "/" then - finalpath = linkpath - else - finalpath = nixio.fs.realpath(directory..linkpath) - end - local linktype; - if not finalpath then - finalpath = linkpath; - linktype = 'x' - elseif nixio.fs.stat(finalpath, "type") == "dir" then - linktype = 'z' - else - linktype = 'l' - end - fileinfo = string.sub(fileinfo, 2, linkindex - 1) - fileinfo = linktype..fileinfo.."-> "..finalpath - t[i] = fileinfo - end - pfile:close() - return t -end - -MIME_TYPES = { - ["txt"] = "text/plain"; - ["conf"] = "text/plain"; - ["ovpn"] = "text/plain"; - ["log"] = "text/plain"; - ["js"] = "text/javascript"; - ["json"] = "application/json"; - ["css"] = "text/css"; - ["htm"] = "text/html"; - ["html"] = "text/html"; - ["patch"] = "text/x-patch"; - ["c"] = "text/x-csrc"; - ["h"] = "text/x-chdr"; - ["o"] = "text/x-object"; - ["ko"] = "text/x-object"; - - ["bmp"] = "image/bmp"; - ["gif"] = "image/gif"; - ["png"] = "image/png"; - ["jpg"] = "image/jpeg"; - ["jpeg"] = "image/jpeg"; - ["svg"] = "image/svg+xml"; - - ["zip"] = "application/zip"; - ["pdf"] = "application/pdf"; - ["xml"] = "application/xml"; - ["xsl"] = "application/xml"; - ["doc"] = "application/msword"; - ["ppt"] = "application/vnd.ms-powerpoint"; - ["xls"] = "application/vnd.ms-excel"; - ["odt"] = "application/vnd.oasis.opendocument.text"; - ["odp"] = "application/vnd.oasis.opendocument.presentation"; - ["pl"] = "application/x-perl"; - ["sh"] = "application/x-shellscript"; - ["php"] = "application/x-php"; - ["deb"] = "application/x-deb"; - ["iso"] = "application/x-cd-image"; - ["tgz"] = "application/x-compressed-tar"; - - ["mp3"] = "audio/mpeg"; - ["ogg"] = "audio/x-vorbis+ogg"; - ["wav"] = "audio/x-wav"; - - ["mpg"] = "video/mpeg"; - ["mpeg"] = "video/mpeg"; - ["avi"] = "video/x-msvideo"; -} - -function to_mime(filename) - if type(filename) == "string" then - local ext = filename:match("[^%.]+$") - - if ext and MIME_TYPES[ext:lower()] then - return MIME_TYPES[ext:lower()] - end - end - - return "application/octet-stream" -end \ No newline at end of file diff --git a/package/lienol/luci-app-fileassistant/luasrc/view/fileassistant.htm b/package/lienol/luci-app-fileassistant/luasrc/view/fileassistant.htm deleted file mode 100644 index 15f069b95a..0000000000 --- a/package/lienol/luci-app-fileassistant/luasrc/view/fileassistant.htm +++ /dev/null @@ -1,20 +0,0 @@ -<%+header%> - - -

文件助手

-
- -
-
文件列表
- -
-
- - -
-
-
- - - -<%+footer%> diff --git a/package/lienol/luci-app-ipsec-vpnserver-manyusers/Makefile b/package/lienol/luci-app-ipsec-vpnserver-manyusers/Makefile deleted file mode 100644 index f3ccff9e1e..0000000000 --- a/package/lienol/luci-app-ipsec-vpnserver-manyusers/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (C) 2018-2020 Lienol -# -# This is free software, licensed under the Apache License, Version 2.0 . -# - -include $(TOPDIR)/rules.mk - -LUCI_TITLE:=LuCI support for IPSec VPN Server -LUCI_DEPENDS:=+strongswan +strongswan-minimal +strongswan-mod-xauth-generic -LUCI_PKGARCH:=all -PKG_VERSION:=1 -PKG_RELEASE:=6-20200402 - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature diff --git a/package/lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/controller/ipsec-server.lua b/package/lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/controller/ipsec-server.lua deleted file mode 100644 index 33c7ec530e..0000000000 --- a/package/lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/controller/ipsec-server.lua +++ /dev/null @@ -1,24 +0,0 @@ --- Copyright 2018-2019 Lienol -module("luci.controller.ipsec-server", package.seeall) - -function index() - if not nixio.fs.access("/etc/config/ipsec") then return end - - entry({"admin", "vpn"}, firstchild(), "VPN", 45).dependent = false - entry({"admin", "vpn", "ipsec-server"}, - alias("admin", "vpn", "ipsec-server", "settings"), - _("IPSec VPN Server"), 49).dependent = false - entry({"admin", "vpn", "ipsec-server", "settings"}, - cbi("ipsec-server/settings"), _("General Settings"), 10).leaf = true - entry({"admin", "vpn", "ipsec-server", "users"}, cbi("ipsec-server/users"), - _("Users Manager"), 20).leaf = true - entry({"admin", "vpn", "ipsec-server", "status"}, call("status")).leaf = - true -end - -function status() - local e = {} - e.status = luci.sys.call("/usr/bin/pgrep ipsec > /dev/null") == 0 - luci.http.prepare_content("application/json") - luci.http.write_json(e) -end diff --git a/package/lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/model/cbi/ipsec-server/settings.lua b/package/lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/model/cbi/ipsec-server/settings.lua deleted file mode 100644 index d2415d527d..0000000000 --- a/package/lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/model/cbi/ipsec-server/settings.lua +++ /dev/null @@ -1,105 +0,0 @@ -local s = require "luci.sys" -local net = require"luci.model.network".init() -local ifaces = s.net:devices() -local m, s, o -mp = Map("ipsec", translate("IPSec VPN Server")) -mp.description = translate( - "IPSec VPN connectivity using the native built-in VPN Client on iOS or Andriod (IKEv1 with PSK and Xauth)") -mp.template = "ipsec-server/index" - -s = mp:section(TypedSection, "service") -s.anonymous = true -o = s:option(DummyValue, "ipsec-server_status", translate("Current Condition")) -o.template = "ipsec-server/status" -enabled = s:option(Flag, "enabled", translate("Enable")) -enabled.default = 0 -enabled.rmempty = false - -clientip = s:option(Value, "clientip", translate("VPN Client IP")) -clientip.datatype = "ip4addr" -clientip.description = translate( - "VPN Client reserved started IP addresses with the same subnet mask") -clientip.optional = false -clientip.rmempty = false - ---[[ -clientdns = s:option(Value, "clientdns", translate("VPN Client DNS")) -clientdns.datatype = "ip4addr" -clientdns.description = translate("DNS using in VPN tunnel.") -clientdns.optional = false -clientdns.rmempty = false -]]-- - -secret = s:option(Value, "secret", translate("Secret Pre-Shared Key")) -secret.password = true - -function mp.on_save(self) - require "luci.model.uci" - require "luci.sys" - - local have_ike_rule = false - local have_ipsec_rule = false - local have_ah_rule = false - local have_esp_rule = false - - luci.model.uci.cursor():foreach('firewall', 'rule', function(section) - if section.name == 'ike' then have_ike_rule = true end - if section.name == 'ipsec' then have_ipsec_rule = true end - if section.name == 'ah' then have_ah_rule = true end - if section.name == 'esp' then have_esp_rule = true end - end) - - if not have_ike_rule then - local cursor = luci.model.uci.cursor() - local ike_rulename = cursor:add('firewall', 'rule') - cursor:tset('firewall', ike_rulename, { - ['name'] = 'ike', - ['target'] = 'ACCEPT', - ['src'] = 'wan', - ['proto'] = 'udp', - ['dest_port'] = 500 - }) - cursor:save('firewall') - cursor:commit('firewall') - end - if not have_ipsec_rule then - local cursor = luci.model.uci.cursor() - local ipsec_rulename = cursor:add('firewall', 'rule') - cursor:tset('firewall', ipsec_rulename, { - ['name'] = 'ipsec', - ['target'] = 'ACCEPT', - ['src'] = 'wan', - ['proto'] = 'udp', - ['dest_port'] = 4500 - }) - cursor:save('firewall') - cursor:commit('firewall') - end - if not have_ah_rule then - local cursor = luci.model.uci.cursor() - local ah_rulename = cursor:add('firewall', 'rule') - cursor:tset('firewall', ah_rulename, { - ['name'] = 'ah', - ['target'] = 'ACCEPT', - ['src'] = 'wan', - ['proto'] = 'ah' - }) - cursor:save('firewall') - cursor:commit('firewall') - end - if not have_esp_rule then - local cursor = luci.model.uci.cursor() - local esp_rulename = cursor:add('firewall', 'rule') - cursor:tset('firewall', esp_rulename, { - ['name'] = 'esp', - ['target'] = 'ACCEPT', - ['src'] = 'wan', - ['proto'] = 'esp' - }) - cursor:save('firewall') - cursor:commit('firewall') - end - -end - -return mp diff --git a/package/lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/model/cbi/ipsec-server/users.lua b/package/lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/model/cbi/ipsec-server/users.lua deleted file mode 100644 index 3477448f17..0000000000 --- a/package/lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/model/cbi/ipsec-server/users.lua +++ /dev/null @@ -1,18 +0,0 @@ -mp = Map("ipsec", translate("IPSec VPN Server")) -mp.description = translate( - "IPSec VPN connectivity using the native built-in VPN Client on iOS or Andriod (IKEv1 with PSK and Xauth)") - -s = mp:section(TypedSection, "users", translate("Users Manager")) -s.addremove = true -s.anonymous = true -s.template = "cbi/tblsection" - -enabled = s:option(Flag, "enabled", translate("Enabled")) -enabled.rmempty = false -username = s:option(Value, "username", translate("User name")) -username.placeholder = translate("User name") -username.rmempty = true -password = s:option(Value, "password", translate("Password")) -password.rmempty = true - -return mp diff --git a/package/lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/view/ipsec-server/index.htm b/package/lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/view/ipsec-server/index.htm deleted file mode 100644 index 017f042c4d..0000000000 --- a/package/lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/view/ipsec-server/index.htm +++ /dev/null @@ -1,13 +0,0 @@ -<% include("cbi/map") %> - diff --git a/package/lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/view/ipsec-server/status.htm b/package/lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/view/ipsec-server/status.htm deleted file mode 100644 index 2c50928a9b..0000000000 --- a/package/lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/view/ipsec-server/status.htm +++ /dev/null @@ -1,3 +0,0 @@ -<%+cbi/valueheader%> -<%=pcdata(self:cfgvalue(section) or self.default or "")%> -<%+cbi/valuefooter%> diff --git a/package/lienol/luci-app-ipsec-vpnserver-manyusers/po/zh-cn/ipsec.po b/package/lienol/luci-app-ipsec-vpnserver-manyusers/po/zh-cn/ipsec.po deleted file mode 100644 index 349daca807..0000000000 --- a/package/lienol/luci-app-ipsec-vpnserver-manyusers/po/zh-cn/ipsec.po +++ /dev/null @@ -1,50 +0,0 @@ -msgid "IPSec VPN Server" -msgstr "IPSec VPN 服务器" - -msgid "IPSec VPN connectivity using the native built-in VPN Client on iOS or Andriod (IKEv1 with PSK and Xauth)" -msgstr "使用iOS 或者 Andriod (IKEv1 with PSK and Xauth) 原生内置 IPSec VPN 客户端进行连接" - -msgid "IPSec VPN Server status" -msgstr "IPSec VPN 服务器运行状态" - -msgid "Current Condition" -msgstr "当前状态" - -msgid "General settings" -msgstr "基本设置" - -msgid "VPN Client IP" -msgstr "VPN客户端地址段" - -msgid "VPN Client reserved started IP addresses with the same subnet mask" -msgstr "VPN客户端获取IP的起始地址,例如 192.168.100.10/24" - -msgid "VPN Client DNS" -msgstr "VPN客户端DNS服务器" - -msgid "DNS using in VPN tunnel." -msgstr "指定VPN客户端的DNS地址。" - -msgid "Secret Pre-Shared Key" -msgstr "PSK密钥" - -msgid "is_nat" -msgstr "NAT转发" - -msgid "Interface" -msgstr "接口" - -msgid "Specify interface forwarding traffic." -msgstr "指定接口转发流量。" - -msgid "Disable from startup" -msgstr "禁止开机启动" - -msgid "Enable on startup" -msgstr "允许开机启动" - -msgid "NOT RUNNING" -msgstr "未运行" - -msgid "RUNNING" -msgstr "运行中" \ No newline at end of file diff --git a/package/lienol/luci-app-ipsec-vpnserver-manyusers/root/etc/config/ipsec b/package/lienol/luci-app-ipsec-vpnserver-manyusers/root/etc/config/ipsec deleted file mode 100644 index d837e09160..0000000000 --- a/package/lienol/luci-app-ipsec-vpnserver-manyusers/root/etc/config/ipsec +++ /dev/null @@ -1,12 +0,0 @@ - -config service 'ipsec' - option enabled '0' - option secret 'ipsec' - option clientip '192.168.100.10/24' - option clientdns '223.5.5.5' - -config users - option enabled '1' - option username 'guest' - option password '123456' - diff --git a/package/lienol/luci-app-ipsec-vpnserver-manyusers/root/etc/init.d/ipsecvpn b/package/lienol/luci-app-ipsec-vpnserver-manyusers/root/etc/init.d/ipsecvpn deleted file mode 100755 index 99aafa6cf4..0000000000 --- a/package/lienol/luci-app-ipsec-vpnserver-manyusers/root/etc/init.d/ipsecvpn +++ /dev/null @@ -1,68 +0,0 @@ -#!/bin/sh /etc/rc.common - -START=99 - -IPSEC_SECRETS_FILE=/etc/ipsec.secrets -IPSEC_CONN_FILE=/etc/ipsec.conf - -setup_login() { - config_get enabled $1 enabled - [ "$enabled" -eq 0 ] && return 0 - config_get username $1 username - config_get password $1 password - [ -n "$username" ] || return 0 - [ -n "$password" ] || return 0 - echo "$username : XAUTH '$password'" >> $IPSEC_SECRETS_FILE -} - -start() { - local vt_enabled=$(uci -q get ipsec.@service[0].enabled) - [ "$vt_enabled" = 0 ] && return 1 - - local vt_clientip=$(uci -q get ipsec.@service[0].clientip) - local vt_clientdns=$(uci -q get ipsec.@service[0].clientdns) - [ -z "$vt_clientdns" ] && local vt_clientdns="8.8.4.4" - local vt_secret=$(uci -q get ipsec.@service[0].secret) - - cat > $IPSEC_CONN_FILE < /etc/ipsec.secrets < /dev/null 2>&1 & - fw3 -q reload 2>&1 & -} - -stop() { - ps -w | grep "/usr/lib/ipsec" | grep -v "grep" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 - fw3 -q reload 2>&1 -} \ No newline at end of file diff --git a/package/lienol/luci-app-ipsec-vpnserver-manyusers/root/etc/uci-defaults/luci-app-ipsec-vpnserver-manyusers b/package/lienol/luci-app-ipsec-vpnserver-manyusers/root/etc/uci-defaults/luci-app-ipsec-vpnserver-manyusers deleted file mode 100755 index 48cd77da84..0000000000 --- a/package/lienol/luci-app-ipsec-vpnserver-manyusers/root/etc/uci-defaults/luci-app-ipsec-vpnserver-manyusers +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete firewall.ipsecvpn - set firewall.ipsecvpn=include - set firewall.ipsecvpn.type=script - set firewall.ipsecvpn.path=/usr/share/ipsecvpn/firewall.include - set firewall.ipsecvpn.reload=1 -EOF - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@ipsec[-1] - add ucitrack ipsec - set ucitrack.@ipsec[-1].init=ipsecvpn - commit ucitrack -EOF - -/etc/init.d/ipsec disable && /etc/init.d/ipsec stop -rm -f /etc/init.d/ipsec -chmod a+x /usr/share/ipsecvpn/* >/dev/null 2>&1 - -rm -rf /tmp/luci-*cache -exit 0 diff --git a/package/lienol/luci-app-ipsec-vpnserver-manyusers/root/usr/share/ipsecvpn/firewall.include b/package/lienol/luci-app-ipsec-vpnserver-manyusers/root/usr/share/ipsecvpn/firewall.include deleted file mode 100755 index 16f017ea2f..0000000000 --- a/package/lienol/luci-app-ipsec-vpnserver-manyusers/root/usr/share/ipsecvpn/firewall.include +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/sh - -iptables -D INPUT -p udp -m multiport --dports 500,4500 -m comment --comment "IPSec VPN Server" -j ACCEPT 2> /dev/null -ipsec_nums=$(iptables -t nat -n -L POSTROUTING 2>/dev/null | grep -c "IPSec VPN Server") -if [ -n "$ipsec_nums" ]; then - until [ "$ipsec_nums" = 0 ] - do - rules=$(iptables -t nat -n -L POSTROUTING --line-num 2>/dev/null | grep "IPSec VPN Server" | awk '{print $1}') - for rule in $rules - do - iptables -t nat -D POSTROUTING $rule 2> /dev/null - break - done - ipsec_nums=$(expr $ipsec_nums - 1) - done -fi -nums=$(iptables -n -L forwarding_rule 2>/dev/null | grep -c "IPSec VPN Server") -if [ -n "$nums" ]; then - until [ "$nums" = 0 ] - do - rules=$(iptables -n -L forwarding_rule --line-num 2>/dev/null | grep "IPSec VPN Server" | awk '{print $1}') - for rule in $rules - do - iptables -D forwarding_rule $rule 2> /dev/null - break - done - nums=$(expr $nums - 1) - done -fi - -enable=$(uci -q get ipsec.ipsec.enabled) -if [ -n "$enable" -a "$enable" == 1 ]; then - clientip=$(uci -q get ipsec.ipsec.clientip) - iptables -t nat -I POSTROUTING -s ${clientip%.*}.0/24 -m comment --comment "IPSec VPN Server" -j MASQUERADE - iptables -I forwarding_rule -s ${clientip%.*}.0/24 -m comment --comment "IPSec VPN Server" -j ACCEPT - iptables -I forwarding_rule -m policy --dir in --pol ipsec --proto esp -m comment --comment "IPSec VPN Server" -j ACCEPT - iptables -I forwarding_rule -m policy --dir out --pol ipsec --proto esp -m comment --comment "IPSec VPN Server" -j ACCEPT - iptables -I INPUT -p udp -m multiport --dports 500,4500 -m comment --comment "IPSec VPN Server" -j ACCEPT -fi diff --git a/package/lienol/luci-app-nginx-pingos/Makefile b/package/lienol/luci-app-nginx-pingos/Makefile deleted file mode 100644 index fbbb5a70c0..0000000000 --- a/package/lienol/luci-app-nginx-pingos/Makefile +++ /dev/null @@ -1,98 +0,0 @@ -# Copyright (C) 2020 Lienol - -include $(TOPDIR)/rules.mk - -PKG_NAME:=luci-app-nginx-pingos -PKG_VERSION:=1.19.6 -PKG_RELEASE:=1 - -PKG_SOURCE:=nginx-$(PKG_VERSION).tar.gz -PKG_SOURCE_URL:=https://nginx.org/download/ -PKG_HASH:=b11195a02b1d3285ddf2987e02c6b6d28df41bb1b1dd25f33542848ef4fc33b5 - -PKG_DIR:=$(BUILD_DIR)/$(PKG_NAME) -PKG_BUILD_DIR:=$(PKG_DIR)/nginx-$(PKG_VERSION) - -PKG_FIXUP:=autoreconf -PKG_BUILD_PARALLEL:=1 -PKG_INSTALL:=1 - -include $(INCLUDE_DIR)/package.mk - -define Package/$(PKG_NAME) - CATEGORY:=LuCI - SUBMENU:=3. Applications - TITLE:=PingOS server - PKGARCH:=all - URL:=https://pingos.io/ - DEPENDS:=+libpcre +libopenssl +zlib +libpthread -endef - -define Package/$(PKG_NAME)/conffiles -endef - -define Build/Prepare - rm -r $(PKG_BUILD_DIR) - mkdir -p $(PKG_BUILD_DIR) - tar -zxvf $(DL_DIR)/$(PKG_SOURCE) -C $(PKG_DIR) - $(CP) -pR ./modules $(PKG_BUILD_DIR)/modules - $(call Build/Prepare/Default,) -endef - -ADDITIONAL_MODULES:= --with-http_ssl_module \ - --add-module=./modules/nginx-rtmp-module \ - --add-module=./modules/nginx-client-module \ - --add-module=./modules/nginx-multiport-module \ - --add-module=./modules/nginx-toolkit-module - -TARGET_CFLAGS += -fvisibility=hidden -ffunction-sections -fdata-sections -DNGX_LUA_NO_BY_LUA_BLOCK -TARGET_LDFLAGS += -Wl,--gc-sections - -CONFIGURE_ARGS += \ - --crossbuild=Linux::$(ARCH) \ - --prefix=/usr \ - --conf-path=/usr/share/pingos/conf/nginx.conf \ - $(ADDITIONAL_MODULES) \ - --error-log-path=/var/etc/pingos/error.log \ - --pid-path=/var/etc/pingos/pingos.pid \ - --lock-path=/var/etc/pingos/pingos.lock \ - --http-log-path=/var/etc/pingos/access.log \ - --http-client-body-temp-path=/var/etc/pingos/lib/body \ - --http-proxy-temp-path=/var/etc/pingos/lib/proxy \ - --with-cc="$(TARGET_CC)" \ - --with-cc-opt="$(TARGET_CPPFLAGS) $(TARGET_CFLAGS)" \ - --with-ld-opt="$(TARGET_LDFLAGS)" \ - --without-http_upstream_zone_module - -define Package/$(PKG_NAME)/install - $(INSTALL_DIR) $(1)/etc - $(INSTALL_CONF) ./root/etc/pingos.template $(1)/etc/pingos.template - - $(INSTALL_DIR) $(1)/etc/config - $(INSTALL_CONF) ./root/etc/config/pingos $(1)/etc/config/pingos - - $(INSTALL_DIR) $(1)/etc/init.d - $(INSTALL_BIN) ./root/etc/init.d/pingos $(1)/etc/init.d/pingos - - $(INSTALL_DIR) $(1)/etc/uci-defaults - $(INSTALL_CONF) ./root/etc/uci-defaults/* $(1)/etc/uci-defaults - - $(INSTALL_DIR) $(1)/usr/share/pingos - cp -pR $(PKG_INSTALL_DIR)/usr/share/pingos/conf $(1)/usr/share/pingos - $(INSTALL_DATA) ./root/resource/conf-template/nginx.conf $(1)/usr/share/pingos/conf/nginx.conf - - cp -pR $(PKG_INSTALL_DIR)/usr/html $(1)/usr/share/pingos/html - $(INSTALL_DATA) ./root/resource/crossdomain.xml $(1)/usr/share/pingos/html/crossdomain.xml - $(INSTALL_DATA) ./root/resource/stat.xsl $(1)/usr/share/pingos/html/stat.xsl - - $(INSTALL_DIR) $(1)/usr/lib/lua/luci - cp -pR ./luasrc/* $(1)/usr/lib/lua/luci/ - - $(INSTALL_DIR) $(1)/usr/lib/lua/luci/i18n - po2lmo ./po/zh-cn/pingos.po $(1)/usr/lib/lua/luci/i18n/pingos.zh-cn.lmo - - $(INSTALL_DIR) $(1)/usr/sbin - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/nginx $(1)/usr/sbin/pingos -endef - -$(eval $(call BuildPackage,$(PKG_NAME))) diff --git a/package/lienol/luci-app-nginx-pingos/luasrc/controller/pingos.lua b/package/lienol/luci-app-nginx-pingos/luasrc/controller/pingos.lua deleted file mode 100644 index 7c7bc99724..0000000000 --- a/package/lienol/luci-app-nginx-pingos/luasrc/controller/pingos.lua +++ /dev/null @@ -1,17 +0,0 @@ --- Copyright 2020 Lienol -module("luci.controller.pingos", package.seeall) - -function index() - if not nixio.fs.access("/etc/config/pingos") then return end - - entry({"admin", "nas"}, firstchild(), "NAS", 44).dependent = false - entry({"admin", "nas", "pingos"}, cbi("pingos"), _("PingOS"), 3).dependent = true - entry({"admin", "nas", "pingos", "status"}, call("act_status")).leaf = true -end - -function act_status() - local e = {} - e.status = luci.sys.call("ps -w | grep pingos | grep nginx | grep -v grep > /dev/null") == 0 - luci.http.prepare_content("application/json") - luci.http.write_json(e) -end diff --git a/package/lienol/luci-app-nginx-pingos/luasrc/model/cbi/pingos.lua b/package/lienol/luci-app-nginx-pingos/luasrc/model/cbi/pingos.lua deleted file mode 100644 index 7f40a72968..0000000000 --- a/package/lienol/luci-app-nginx-pingos/luasrc/model/cbi/pingos.lua +++ /dev/null @@ -1,68 +0,0 @@ -m = Map("pingos", translate("PingOS")) -m:append(Template("pingos/status")) - -s = m:section(TypedSection, "global") -s.anonymous = true -s.addremove = false - -s:tab("global", translate("Global Settings")) -s:tab("template", translate("Edit Template")) - -nginx = s:taboption("template", Value, "_nginx", translatef("Edit the template that is used for generating the %s configuration.", "nginx"), - translatef("This is the content of the file '%s'", "/etc/pingos.template") .. "
" .. - translatef("Values enclosed by pipe symbols ('|') should not be changed. They get their values from the '%s' tab.", translate("Global Settings"))) -nginx.template = "cbi/tvalue" -nginx.rows = 30 - -function nginx.cfgvalue(self, section) - return nixio.fs.readfile("/etc/pingos.template") -end - -function nginx.write(self, section, value) - value = value:gsub("\r\n?", "\n") - nixio.fs.writefile("/etc/pingos.template", value) -end - -o = s:taboption("global", Flag, "enable", translate("Enable")) -o.rmempty = false - -o = s:taboption("global", Flag, "ipv6", translate("Listen IPv6")) -o.rmempty = false - -o = s:taboption("global", Value, "http_port", "HTTP(S)" ..translate("Port")) -o.datatype = "port" -o.default = 8082 -o.rmempty = false - -o = s:taboption("global", Flag, "https", translate("HTTPS")) -o.rmempty = false - -o = s:taboption("global", FileUpload, "certificate", translate("certificate")) -o:depends("https", 1) - -o = s:taboption("global", FileUpload, "key", translate("key")) -o:depends("https", 1) - -o = s:taboption("global", Value, "rtmp_port", "RTMP" ..translate("Port")) -o.datatype = "port" -o.default = 1935 -o.rmempty = false - -o = s:taboption("global", Flag, "hls", translate("HLS")) -o.rmempty = false - -o = s:taboption("global", Flag, "hls2", translate("HLS2")) -o.rmempty = false - -o = s:taboption("global", Flag, "ts_record", "TS " .. translate("Record")) -o.rmempty = false - -o = s:taboption("global", Flag, "flv_record", "FLV " .. translate("Record")) -o.rmempty = false - -o = s:taboption("global", Value, "record_path", translate("Record") .. translate("Path")) -o.default = "/tmp/record" -o:depends("ts_record", 1) -o:depends("flv_record", 1) - -return m diff --git a/package/lienol/luci-app-nginx-pingos/luasrc/view/pingos/status.htm b/package/lienol/luci-app-nginx-pingos/luasrc/view/pingos/status.htm deleted file mode 100644 index d2b1a343b5..0000000000 --- a/package/lienol/luci-app-nginx-pingos/luasrc/view/pingos/status.htm +++ /dev/null @@ -1,52 +0,0 @@ -
- <%:Running Status%> -
-
- -
<%:Collecting data...%>
-
-
- -
- -
    -
  • rtmp rtmp://ip/live/<%:Stream name%>
  • -
  • http(s)-flv http(s)://ip/flv/<%:Stream name%>
  • -
  • hls http(s)://ip/hls/<%:Stream name%>.m3u8
  • -
  • hls+ http(s)://ip/hls2/<%:Stream name%>.m3u8
  • -
  • http(s)-ts http(s)://ip/ts/<%:Stream name%>
  • -
-
-
-
-
- - \ No newline at end of file diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/COPYRIGHT b/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/COPYRIGHT deleted file mode 100644 index 837a6682d6..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/COPYRIGHT +++ /dev/null @@ -1,24 +0,0 @@ -Copyright (C) 2016-2020, by Jie Wu "AlexWoo" . -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -SUCH DAMAGE. - diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/config b/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/config deleted file mode 100644 index 36352b8029..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/config +++ /dev/null @@ -1,19 +0,0 @@ -ngx_addon_name=ngx_client_module - - -CORE_MODULES="$CORE_MODULES \ - ngx_client_module \ - ngx_http_client_module \ - " - -NGX_ADDON_SRCS="$NGX_ADDON_SRCS \ - $ngx_addon_dir/ngx_client.c \ - $ngx_addon_dir/ngx_http_client.c \ - " - -NGX_ADDON_DEPS="$NGX_ADDON_DEPS \ - $ngx_addon_dir/ngx_client.h \ - $ngx_addon_dir/ngx_http_client.h \ - " - -CFLAGS="$CFLAGS -I $ngx_addon_dir" diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/ngx_client.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/ngx_client.c deleted file mode 100644 index e18d4a0273..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/ngx_client.c +++ /dev/null @@ -1,1387 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - * fixed by Ping cczjp89@gmail.com - */ - - -#include -#include "ngx_client.h" -#include "ngx_event_resolver.h" -#include "ngx_dynamic_resolver.h" -#include "ngx_poold.h" -#include "ngx_map.h" -#include "ngx_timerd.h" - - -#define NGX_CLIENT_DISCARD_BUFFER_SIZE 4096 - - -static void *ngx_client_module_create_conf(ngx_cycle_t *cycle); -static char *ngx_client_module_init_conf(ngx_cycle_t *cycle, void *conf); - - -typedef struct ngx_client_pool_s ngx_client_pool_t; - - -struct ngx_client_pool_s { - ngx_map_node_t node; - ngx_queue_t cs_queue; /* client session queue */ - ngx_uint_t qsize; /* client pool size */ - - u_char addr[NGX_SOCKADDR_STRLEN]; - ngx_str_t paddr; - - ngx_client_pool_t *next; /* free pool node */ -}; - - -typedef struct { - ngx_map_t client_pools; /* key is ip:port */ - /* max keepalive client session */ - ngx_uint_t max_idle_client; - ngx_msec_t keepalive; - ngx_msec_t connect_timeout; - ngx_msec_t send_timeout; - size_t postpone_output; - ngx_flag_t dynamic_resolver; - ngx_flag_t tcp_nodelay; - ngx_flag_t tcp_nopush; - - ngx_uint_t idle_connction; /* connection num in pools */ - ngx_uint_t nalloc; - ngx_uint_t nfree; - ngx_client_pool_t *free; /* recycle free pool node */ -} ngx_client_conf_t; - - -static ngx_command_t ngx_client_commands[] = { - - { ngx_string("max_idle_client"), - NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - 0, - offsetof(ngx_client_conf_t, max_idle_client), - NULL }, - - { ngx_string("keepalive"), - NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - 0, - offsetof(ngx_client_conf_t, keepalive), - NULL }, - - { ngx_string("connect_timeout"), - NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - 0, - offsetof(ngx_client_conf_t, connect_timeout), - NULL }, - - { ngx_string("send_timeout"), - NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - 0, - offsetof(ngx_client_conf_t, send_timeout), - NULL }, - - { ngx_string("postpone_output"), - NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - 0, - offsetof(ngx_client_conf_t, postpone_output), - NULL }, - - { ngx_string("dynamic_resolver"), - NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG, - ngx_conf_set_flag_slot, - 0, - offsetof(ngx_client_conf_t, dynamic_resolver), - NULL }, - - { ngx_string("tcp_nodelay"), - NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG, - ngx_conf_set_flag_slot, - 0, - offsetof(ngx_client_conf_t, tcp_nodelay), - NULL }, - - { ngx_string("tcp_nopush"), - NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG, - ngx_conf_set_flag_slot, - 0, - offsetof(ngx_client_conf_t, tcp_nopush), - NULL }, - - ngx_null_command -}; - - -static ngx_core_module_t ngx_client_module_ctx = { - ngx_string("client"), - ngx_client_module_create_conf, - ngx_client_module_init_conf -}; - - -ngx_module_t ngx_client_module = { - NGX_MODULE_V1, - &ngx_client_module_ctx, /* module context */ - ngx_client_commands, /* module directives */ - NGX_CORE_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void * -ngx_client_module_create_conf(ngx_cycle_t *cycle) -{ - ngx_client_conf_t *ccf; - - ccf = ngx_pcalloc(cycle->pool, sizeof(ngx_client_conf_t)); - if (ccf == NULL) { - return NULL; - } - - ngx_map_init(&ccf->client_pools, ngx_map_hash_str, ngx_cmp_str); - - ccf->max_idle_client = NGX_CONF_UNSET_UINT; - ccf->keepalive = NGX_CONF_UNSET_MSEC; - ccf->connect_timeout = NGX_CONF_UNSET_MSEC; - ccf->send_timeout = NGX_CONF_UNSET_MSEC; - ccf->postpone_output = NGX_CONF_UNSET_SIZE; - ccf->dynamic_resolver = NGX_CONF_UNSET; - ccf->tcp_nodelay = NGX_CONF_UNSET; - ccf->tcp_nodelay = NGX_CONF_UNSET; - - return ccf; -} - - -static char * -ngx_client_module_init_conf(ngx_cycle_t *cycle, void *conf) -{ - ngx_client_conf_t *ccf = conf; - - ngx_conf_init_uint_value(ccf->max_idle_client, 1024); - ngx_conf_init_msec_value(ccf->keepalive, 60000); - - ngx_conf_init_msec_value(ccf->connect_timeout, 3000); - ngx_conf_init_msec_value(ccf->send_timeout, 10000); - ngx_conf_init_size_value(ccf->postpone_output, 1460); - ngx_conf_init_value(ccf->dynamic_resolver, 1); - ngx_conf_init_value(ccf->tcp_nodelay, 1); - ngx_conf_init_value(ccf->tcp_nopush, 0); - - return NGX_CONF_OK; -} - - -/* client pool */ -static ngx_client_pool_t * -ngx_client_get_client_pool() -{ - ngx_client_conf_t *ccf; - ngx_client_pool_t *pool; - - ccf = (ngx_client_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_client_module); - - pool = ccf->free; - if (pool == NULL) { - pool = ngx_pcalloc(ngx_cycle->pool, sizeof(ngx_client_pool_t)); - if (pool == NULL) { - return NULL; - } - - ++ccf->nalloc; - } else { - ccf->free = pool->next; - ngx_memzero(pool, sizeof(ngx_client_pool_t)); - - --ccf->nfree; - } - - ngx_queue_init(&pool->cs_queue); - - return pool; -} - - -static void -ngx_client_put_client_pool(ngx_client_pool_t *p) -{ - ngx_client_conf_t *ccf; - - ccf = (ngx_client_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_client_module); - - p->next = ccf->free; - ccf->free = p; - - ++ccf->nfree; -} - - -static ngx_connection_t * -ngx_client_get_connection(struct sockaddr *sockaddr, socklen_t socklen) -{ - ngx_client_conf_t *ccf; - ngx_client_pool_t *pool; - ngx_map_node_t *node; - ngx_queue_t *cq; - ngx_str_t paddr; - u_char addr[NGX_SOCKADDR_STRLEN]; - ngx_connection_t *c; - - ccf = (ngx_client_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_client_module); - -#if (NGX_HAVE_UNIX_DOMAIN) - if (sockaddr->sa_family == AF_UNIX) { // Unix will not reuse - return NULL; - } -#endif - - // get client connection pool for sockaddr - paddr.data = addr; - paddr.len = NGX_SOCKADDR_STRLEN; - paddr.len = ngx_sock_ntop(sockaddr, socklen, paddr.data, paddr.len, 1); - - node = ngx_map_find(&ccf->client_pools, (intptr_t) &paddr); - - if (node == NULL) { // connection pool for addr is empty - return NULL; - } - - // get a idle connection from client connection pool - pool = (ngx_client_pool_t *) node; - cq = ngx_queue_head(&pool->cs_queue); - ngx_queue_remove(cq); - c = (ngx_connection_t *) ((char *) cq - offsetof(ngx_connection_t, queue)); - --ccf->idle_connction; - --pool->qsize; - - // recycle empty pool - if (ngx_queue_empty(&pool->cs_queue)) { - ngx_map_delete(&ccf->client_pools, (intptr_t) &paddr); - ngx_client_put_client_pool(pool); - } - - // init connection - if (c->read->timer_set) { - NGX_DEL_TIMER(c->read, c->number); - } - - if (c->read->posted) { - ngx_delete_posted_event(c->read); - } - - return c; -} - - -static void -ngx_client_keepalive_handler(ngx_event_t *rev) -{ - ngx_client_conf_t *ccf; - ngx_client_pool_t *pool; - ngx_connection_t *c; - ngx_int_t n; - ngx_buf_t b; - u_char buffer[NGX_CLIENT_DISCARD_BUFFER_SIZE]; - - c = rev->data; - - ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0, "client keepalive handler"); - - if (rev->timedout || c->close) { - goto close; - } - - // read and discard data - b.start = buffer; - b.end = buffer + NGX_CLIENT_DISCARD_BUFFER_SIZE; - - for (;;) { - b.pos = b.last = b.start; - - n = c->recv(c, b.last, b.end - b.last); - - if (n == 0 || n == NGX_ERROR) { - ngx_log_error(NGX_LOG_INFO, c->log, ngx_errno, - "server close while client keepalive"); - goto close; - } - - ngx_log_error(NGX_LOG_INFO, c->log, 0, - "server recv data while client keepalive %d", n); - - goto close; - } - -close: - // remove connection from pool - ccf = (ngx_client_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_client_module); - - pool = c->data; - - ngx_queue_remove(&c->queue); - --ccf->idle_connction; - --pool->qsize; - - // recycle empty pool - if (ngx_queue_empty(&pool->cs_queue)) { - ngx_map_delete(&ccf->client_pools, (intptr_t) &pool->paddr); - ngx_client_put_client_pool(pool); - } - - if (c->read->timer_set) { - NGX_DEL_TIMER(c->read, c->number); - } - - if (c->write->timer_set) { - NGX_DEL_TIMER(c->write, c->number); - } - - ngx_close_connection(c); -} - - -static void -ngx_client_reusable_connection(ngx_client_session_t *s) -{ - ngx_client_conf_t *ccf; - ngx_client_pool_t *pool; - ngx_map_node_t *node; - ngx_connection_t *c; - ngx_str_t paddr; - u_char addr[NGX_SOCKADDR_STRLEN]; - - ccf = (ngx_client_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_client_module); - - c = s->connection; - -#if (NGX_HAVE_UNIX_DOMAIN) - if (s->peer.sockaddr->sa_family == AF_UNIX) { // Unix will not reuse - return; - } -#endif - - if (ccf->idle_connction > ccf->keepalive) { - ngx_log_error(NGX_LOG_INFO, c->log, 0, - "too many connections in pool"); - return; - } - - ngx_log_error(NGX_LOG_INFO, &s->log, 0, "client, put connection in pool"); - - c->pool = NULL; - - // get client connection pool for c->sockaddr - paddr.data = addr; - paddr.len = NGX_SOCKADDR_STRLEN; - paddr.len = ngx_sock_ntop(s->peer.sockaddr, s->peer.socklen, - paddr.data, paddr.len, 1); - - node = ngx_map_find(&ccf->client_pools, (intptr_t) &paddr); - pool = (ngx_client_pool_t *) node; - - if (pool == NULL) { // connection pool for addr is empty - pool = ngx_client_get_client_pool(); - if (pool == NULL) { - return; - } - - ngx_memcpy(pool->addr, addr, NGX_SOCKADDR_STRLEN); - pool->paddr.data = pool->addr; - pool->paddr.len = paddr.len; - - pool->node.raw_key = (intptr_t) &pool->paddr; - ngx_map_insert(&ccf->client_pools, &pool->node, 0); - } - - // put connection in connection pool - ngx_queue_insert_head(&pool->cs_queue, &c->queue); - c->data = pool; - ++ccf->idle_connction; - ++pool->qsize; - - c->log = ngx_cycle->log; - c->read->log = ngx_cycle->log; - - // set timer for keepalive time - c->read->handler = ngx_client_keepalive_handler; - NGX_ADD_TIMER(c->read, ccf->keepalive, offsetof(ngx_connection_t, number)); - - if (c->write->timer_set) { - NGX_DEL_TIMER(c->write, c->number); - } - - if (c->write->posted) { - ngx_delete_posted_event(c->write); - } - - if (c->write->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) { - if (ngx_del_event(c->write, NGX_WRITE_EVENT, 0) != NGX_OK) { - if (c->read->timer_set) { - NGX_DEL_TIMER(c->read, c->number); - } - - ngx_close_connection(c); - return; - } - } -} - - -/* client */ - -static u_char * -ngx_client_log_error(ngx_log_t *log, u_char *buf, size_t len) -{ - u_char *p; - ngx_client_session_t *s; - - p = buf; - - if (log->action) { - p = ngx_snprintf(buf, len, " while %s", log->action); - len -= p - buf; - buf = p; - } - - s = log->data; - if (s == NULL) { - return p; - } - - if (s->connection) { - p = ngx_snprintf(buf, len, ", server ip: %V", - &s->connection->addr_text); - len -= p - buf; - buf = p; - } - - p = ngx_snprintf(buf, len, ", server: %V, csession: %p", &s->server, s); - len -= p - buf; - buf = p; - - return p; -} - - -static ngx_int_t -ngx_client_get_peer(ngx_peer_connection_t *pc, void *data) -{ - ngx_connection_t *c; - - c = ngx_client_get_connection(pc->sockaddr, pc->socklen); - if (c == NULL) { // cannot find reusable keepalive connection - return NGX_OK; - } - - c->idle = 0; - c->sent = 0; - c->log = pc->log; - c->read->log = pc->log; - c->write->log = pc->log; - - pc->connection = c; - pc->cached = 1; - - return NGX_DONE; -} - - -static void -ngx_client_free_peer(ngx_peer_connection_t *pc, void *data, - ngx_uint_t state) -{ -} - - -static ngx_int_t -ngx_client_test_connect(ngx_connection_t *c) -{ - int err; - socklen_t len; - -#if (NGX_HAVE_KQUEUE) - - if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { - if (c->write->pending_eof || c->read->pending_eof) { - if (c->write->pending_eof) { - err = c->write->kq_errno; - - } else { - err = c->read->kq_errno; - } - - (void) ngx_connection_error(c, err, - "kevent() reported that connect() failed"); - return NGX_ERROR; - } - - } else -#endif - { - err = 0; - len = sizeof(int); - - /* - * BSDs and Linux return 0 and set a pending error in err - * Solaris returns -1 and sets errno - */ - - if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len) - == -1) - { - err = ngx_socket_errno; - } - - if (err) { - (void) ngx_connection_error(c, err, "connect() failed"); - return NGX_ERROR; - } - } - - return NGX_OK; -} - - -static void -ngx_client_connected(ngx_client_session_t *s) -{ - ngx_event_t *wev; - - if (ngx_client_test_connect(s->connection) != NGX_OK) { - ngx_client_close(s); - return; - } - - s->log.action = NULL; - - ngx_log_debug0(NGX_LOG_DEBUG_CORE, &s->log, 0, - "nginx client connected"); - - wev = s->connection->write; - - if (wev->timedout) { /* rev or wev timedout */ - ngx_log_error(NGX_LOG_ERR, &s->log, NGX_ETIMEDOUT, - "server timed out"); - s->connection->timedout = 1; - - ngx_client_close(s); - - return; - } - - if (wev->timer_set) { - NGX_DEL_TIMER(wev, s->connection->number); - } - - s->connected = 1; - s->peer.tries = 0; - - if (s->client_connected) { - s->client_connected(s); - } -} - - -static void -ngx_client_write_handler(ngx_event_t *ev) -{ - ngx_connection_t *c; - ngx_client_session_t *s; - ngx_int_t n; - - c = ev->data; - s = c->data; - - if (c->destroyed) { - return; - } - - ngx_log_debug0(NGX_LOG_DEBUG_CORE, &s->log, 0, - "nginx client write handler"); - - if (!s->connected) { - ngx_client_connected(s); - - return; - } - - if (s->client_send) { - s->client_send(s); - - return; - } - - /* write data buffered in s->out */ - if (s->out == NULL) { - return; - } - - n = ngx_client_write(s, NULL); - if (n == NGX_ERROR) { - ngx_client_close(s); - } -} - - -static void -ngx_client_read_discarded(ngx_client_session_t *s) -{ - ngx_int_t n; - ngx_buf_t b; - u_char buffer[NGX_CLIENT_DISCARD_BUFFER_SIZE]; - - b.start = buffer; - b.end = buffer + NGX_CLIENT_DISCARD_BUFFER_SIZE; - - for (;;) { - b.pos = b.last = b.start; - - n = ngx_client_read(s, &b); - - if (n == NGX_ERROR || n == 0) { - ngx_log_error(NGX_LOG_ERR, &s->log, ngx_errno, - "nginx client read discard error"); - ngx_client_close(s); - - return; - } - - if (n == NGX_AGAIN) { - return; - } - } -} - - -static void -ngx_client_read_handler(ngx_event_t *ev) -{ - ngx_connection_t *c; - ngx_client_session_t *s; - - c = ev->data; - s = c->data; - - if (c->destroyed) { - return; - } - - ngx_log_debug0(NGX_LOG_DEBUG_CORE, &s->log, 0, - "nginx client read handler"); - - if (!s->connected) { - ngx_client_connected(s); - - return; - } - - if (s->client_recv) { - s->client_recv(s); - } else { - /* read and drop */ - ngx_client_read_discarded(s); - } -} - - -static void -ngx_client_connect_server(void *data, struct sockaddr *sa, socklen_t socklen) -{ - ngx_client_session_t *s; - ngx_connection_t *c; - ngx_int_t rc; - int tcp_nodelay; - - s = data; - - if (sa == NULL) { - ngx_log_error(NGX_LOG_ERR, &s->log, 0, - "nginx client resolver peer %v failed", &s->server); - goto failed; - } - - ngx_inet_set_port(sa, s->port); - - s->peer.sockaddr = ngx_pcalloc(s->pool, sizeof(socklen)); - ngx_memcpy(s->peer.sockaddr, sa, socklen); - s->peer.socklen = socklen; - s->peer.name = &s->server; - - s->log.action = "connecting to server"; - - rc = ngx_event_connect_peer(&s->peer); - if (rc == NGX_ERROR) { - ngx_log_error(NGX_LOG_ERR, &s->log, ngx_errno, - "nginx client connect peer failed"); - goto failed; - } else if (rc == NGX_DECLINED) { - ngx_log_error(NGX_LOG_ERR, &s->log, ngx_errno, - "nginx client connect peer failed"); - goto failed; - } - - if (rc == NGX_DONE) { - ngx_log_error(NGX_LOG_INFO, &s->log, 0, "client, reuse connection"); - } - - // NGX_AGAIN: send syn, wait for syn,ack - // NGX_OK: connect to server - // NGX_DONE: reuse keepalive connection - - s->connection = s->peer.connection; - c = s->connection; - c->pool = s->pool; - c->pool->log = s->peer.log; - - // set tcp_nodelay - if (c->type == SOCK_STREAM && s->tcp_nodelay - && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) - { - ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0, "tcp_nodelay"); - - tcp_nodelay = 1; - - if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, - (const void *) &tcp_nodelay, sizeof(int)) == -1) - { - ngx_connection_error(c, ngx_socket_errno, - "setsockopt(TCP_NODELAY) failed"); - goto failed; - } - - c->tcp_nodelay = NGX_TCP_NODELAY_SET; - } - - // set tcp_nopush - if (!s->tcp_nopush) { - c->tcp_nopush = NGX_TCP_NOPUSH_DISABLED; - } - - c->addr_text.data = ngx_pcalloc(s->pool, NGX_SOCKADDR_STRLEN); - if (c->addr_text.data == NULL) { - goto failed; - } - c->addr_text.len = ngx_sock_ntop(sa, socklen, c->addr_text.data, - NGX_SOCKADDR_STRLEN, 1); - - ngx_log_debug1(NGX_LOG_DEBUG_CORE, &s->log, 0, - "nginx client connect server, rc: %i", rc); - - c->log->connection = c->number; - - c->data = s; - - c->write->handler = ngx_client_write_handler; - c->read->handler = ngx_client_read_handler; - - if (rc == NGX_AGAIN) { - NGX_ADD_TIMER(c->write, s->connect_timeout, - offsetof(ngx_connection_t, number)); - return; - } - - /* NGX_OK */ - - ngx_client_connected(s); - - return; - -failed: - ngx_client_close(s); -} - - -static void -ngx_client_resolver_server(void *data, ngx_resolver_addr_t *addrs, - ngx_uint_t naddrs) -{ - ngx_client_session_t *s; - ngx_uint_t n; - - s = data; - - if (naddrs == 0) { - ngx_log_error(NGX_LOG_ERR, &s->log, ngx_errno, - "nginx client resolver failed"); - ngx_client_close(s); - return; - } - - n = ngx_random() % naddrs; - - ngx_client_connect_server(data, addrs[n].sockaddr, addrs[n].socklen); -} - - -static void -ngx_client_close_connection(ngx_client_session_t *s) -{ - ngx_connection_t *c; - - c = s->connection; - - if (c == NULL || c->destroyed) { - return; - } - - ngx_log_debug0(NGX_LOG_DEBUG_CORE, &s->log, 0, - "nginx client close connection"); - - s->connected = 0; - s->connection = NULL; - c->destroyed = 1; - - if (c->write->timer_set) { - NGX_DEL_TIMER(c->write, c->number); - } - - if (c->read->timer_set) { - NGX_DEL_TIMER(c->read, c->number); - } - - ngx_close_connection(c); -} - - -ngx_client_session_t * -ngx_client_create(ngx_str_t *peer, ngx_str_t *local, ngx_flag_t udp, - ngx_log_t *log) -{ - ngx_client_session_t *s; - ngx_client_conf_t *ccf; - ngx_pool_t *pool; - ngx_int_t rc, n; - u_char *p, *last; - size_t plen; - - ccf = (ngx_client_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_client_module); - - if (peer == NULL || peer->len == 0) { - ngx_log_error(NGX_LOG_ERR, log, 0, "client init, peer is NULL"); - return NULL; - } - - pool = NGX_CREATE_POOL(4096, ngx_cycle->log); - if (pool == NULL) { - return NULL; - } - - s = ngx_pcalloc(pool, sizeof(ngx_client_session_t)); - if (s == NULL) { - goto clear; - } - s->pool = pool; - - /* set log */ - // ci->log.connection not set, should set when connection established - s->log = ngx_cycle->new_log; - s->log.handler = ngx_client_log_error; - s->log.data = s; - s->log.action = "create client"; - - s->log.log_level = NGX_LOG_INFO; - - /* parse peer */ - last = peer->data + peer->len; - -#if (NGX_HAVE_INET6) - if (peer->len && peer->data[0] == '[') { - - p = ngx_strlchr(peer->data, last, ']'); - - if (p == NULL || p == last - 1) { - ngx_log_error(NGX_LOG_ERR, log, 0, - "client init, parse peer %V error", peer); - goto clear; - } - - ++p; - } else -#endif - { - p = ngx_strlchr(peer->data, last, ':'); - if (p == NULL) { - p = last; - } - } - - s->server.len = p - peer->data; - s->server.data = ngx_pcalloc(s->pool, s->server.len); - if (s->server.data == NULL) { - goto clear; - } - ngx_memcpy(s->server.data, peer->data, peer->len); - - if (p != last) { /* has port */ - if (*p != ':') { - ngx_log_error(NGX_LOG_ERR, log, 0, - "client init, parse peer %V error", peer); - goto clear; - } - - ++p; - plen = last - p; - - n = ngx_atoi(p, plen); - if (n < 1 || n > 65535) { - ngx_log_error(NGX_LOG_ERR, log, 0, - "client init, parse peer %V error", peer); - goto clear; - } - s->port = n; - } - - /* parse local */ - if (local && local->len) { - s->peer.local = ngx_pcalloc(s->pool, sizeof(ngx_addr_t)); - if (s->peer.local == NULL) { - goto clear; - } - - rc = ngx_parse_addr_port(s->pool, s->peer.local, peer->data, peer->len); - if (rc != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, log, 0, "invalid local address \"%V\"", - local); - goto clear; - } - - s->peer.local->name.data = ngx_pcalloc(s->pool, sizeof(local->len)); - if (s->peer.local->name.data == NULL) { - goto clear; - } - ngx_memcpy(s->peer.local->name.data, local->data, local->len); - s->peer.local->name.len = local->len; - } - - /* set default */ - s->connect_timeout = ccf->connect_timeout; - s->send_timeout = ccf->send_timeout; - s->postpone_output = ccf->postpone_output; - s->dynamic_resolver = ccf->dynamic_resolver; - s->tcp_nodelay = ccf->tcp_nodelay; - s->tcp_nopush = ccf->tcp_nopush; - - /* set peer */ - s->peer.log = &s->log; - s->peer.get = ngx_client_get_peer; - s->peer.free = ngx_client_free_peer; - s->peer.type = udp ? SOCK_DGRAM : SOCK_STREAM; - s->peer.log_error = NGX_ERROR_INFO; - - return s; - -clear: - NGX_DESTROY_POOL(pool); - - return NULL; -} - - -void -ngx_client_connect(ngx_client_session_t *s) -{ - s->log.action = "resolving"; - - ngx_log_debug1(NGX_LOG_DEBUG_CORE, &s->log, 0, "nginx client connect %V", - &s->server); - - /* start connect */ - if (s->dynamic_resolver) { - ngx_dynamic_resolver_start_resolver(&s->server, - ngx_client_connect_server, s); - } else { - ngx_event_resolver_start_resolver(&s->server, - ngx_client_resolver_server, s); - } -} - - -ngx_int_t -ngx_client_write(ngx_client_session_t *s, ngx_chain_t *out) -{ - off_t size; - ngx_uint_t last, flush, sync; - ngx_chain_t *cl, *ln, **ll, *chain; - ngx_connection_t *c; - ngx_event_t *wev; - - c = s->peer.connection; - wev = c->write; - - if (c->error) { - return NGX_ERROR; - } - - size = 0; - flush = 0; - sync = 0; - last = 0; - ll = &s->out; - - /* find the size, the flush point and the last link of the saved chain */ - - for (cl = s->out; cl; cl = cl->next) { - ll = &cl->next; - - ngx_log_debug7(NGX_LOG_DEBUG_EVENT, &s->log, 0, - "nginx client write, write old buf t:%d f:%d %p, " - "pos %p, size: %z file: %O, size: %O", - cl->buf->temporary, cl->buf->in_file, - cl->buf->start, cl->buf->pos, - cl->buf->last - cl->buf->pos, - cl->buf->file_pos, - cl->buf->file_last - cl->buf->file_pos); - -#if 1 - if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) { - ngx_log_error(NGX_LOG_ALERT, &s->log, 0, - "nginx client write, zero size buf in writer " - "t:%d r:%d f:%d %p %p-%p %p %O-%O", - cl->buf->temporary, - cl->buf->recycled, - cl->buf->in_file, - cl->buf->start, - cl->buf->pos, - cl->buf->last, - cl->buf->file, - cl->buf->file_pos, - cl->buf->file_last); - - ngx_debug_point(); - return NGX_ERROR; - } -#endif - - size += ngx_buf_size(cl->buf); - - if (cl->buf->flush || cl->buf->recycled) { - flush = 1; - } - - if (cl->buf->sync) { - sync = 1; - } - - if (cl->buf->last_buf) { - last = 1; - } - } - - /* add the new chain to the existent one */ - - for (ln = out; ln; ln = ln->next) { - cl = ngx_alloc_chain_link(s->pool); - if (cl == NULL) { - return NGX_ERROR; - } - - cl->buf = ln->buf; - *ll = cl; - ll = &cl->next; - - ngx_log_debug7(NGX_LOG_DEBUG_EVENT, &s->log, 0, - "nginx client write, write new buf t:%d f:%d %p, " - "pos %p, size: %z file: %O, size: %O", - cl->buf->temporary, cl->buf->in_file, - cl->buf->start, cl->buf->pos, - cl->buf->last - cl->buf->pos, - cl->buf->file_pos, - cl->buf->file_last - cl->buf->file_pos); - -#if 1 - if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) { - ngx_log_error(NGX_LOG_ALERT, &s->log, 0, - "nginx client write, zero size buf in writer " - "t:%d r:%d f:%d %p %p-%p %p %O-%O", - cl->buf->temporary, - cl->buf->recycled, - cl->buf->in_file, - cl->buf->start, - cl->buf->pos, - cl->buf->last, - cl->buf->file, - cl->buf->file_pos, - cl->buf->file_last); - - ngx_debug_point(); - return NGX_ERROR; - } -#endif - - size += ngx_buf_size(cl->buf); - - if (cl->buf->flush || cl->buf->recycled) { - flush = 1; - } - - if (cl->buf->sync) { - sync = 1; - } - - if (cl->buf->last_buf) { - last = 1; - } - } - - *ll = NULL; - - ngx_log_debug3(NGX_LOG_DEBUG_HTTP, &s->log, 0, "nginx client write, " - "http write filter: l:%ui f:%ui s:%O", last, flush, size); - - /* - * avoid the output if there are no last buf, no flush point, - * there are the incoming bufs and the size of all bufs - * is smaller than "postpone_output" directive - */ - - if (!last && !flush && out && size < (off_t) s->postpone_output) { - return NGX_OK; - } - - if (size == 0 && !(last && c->need_last_buf)) { - if (last || flush || sync) { - for (cl = s->out; cl; /* void */) { - ln = cl; - cl = cl->next; - ngx_free_chain(s->pool, ln); - } - - s->out = NULL; - - return NGX_OK; - } - - ngx_log_error(NGX_LOG_ALERT, &s->log, 0, - "nginx client write, the output chain is empty"); - - ngx_debug_point(); - - return NGX_ERROR; - } - - chain = c->send_chain(c, s->out, 0); - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, &s->log, 0, - "nginx client write %p", chain); - - if (chain == NGX_CHAIN_ERROR) { - c->error = 1; - ngx_log_error(NGX_LOG_ERR, &s->log, ngx_errno, "write error"); - return NGX_ERROR; - } - - for (cl = s->out; cl && cl != chain; /* void */) { - ln = cl; - cl = cl->next; - ngx_free_chain(s->pool, ln); - } - - s->out = chain; - - if (chain) { - NGX_ADD_TIMER(c->write, s->send_timeout, - offsetof(ngx_connection_t, number)); - if (ngx_handle_write_event(c->write, 0) != NGX_OK) { - return NGX_ERROR; - } - - return NGX_AGAIN; - } - - if (wev->active) { /* if NGX_OK, del write notification */ - if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) != NGX_OK) { - return NGX_ERROR; - } - } - - return NGX_OK; -} - - -ngx_int_t -ngx_client_read(ngx_client_session_t *s, ngx_buf_t *b) -{ - ngx_connection_t *c; - ngx_int_t n; - - if (s == NULL || b == NULL) { - return NGX_ERROR; - } - - if (b->last == b->end) { - return NGX_DECLINED; - } - - c = s->peer.connection; - - n = c->recv(c, b->last, b->end - b->last); - - if (n == 0) { - ngx_log_error(NGX_LOG_ERR, &s->log, ngx_errno, "server closed"); - return 0; - } - - if (n == NGX_ERROR) { - ngx_log_error(NGX_LOG_ERR, &s->log, ngx_errno, "read error"); - return NGX_ERROR; - } - - if (n == NGX_AGAIN) { - if (ngx_handle_read_event(c->read, 0) != NGX_OK) { - return NGX_ERROR; - } - - return NGX_AGAIN; - } - - b->last += n; - s->recv += n; - - return n; -} - - -void -ngx_client_set_keepalive(ngx_client_session_t *s) -{ - ngx_pool_t *pool; - - if (s->closed) { - return; - } - - ngx_log_debug0(NGX_LOG_DEBUG_CORE, &s->log, 0, - "nginx client set keepalive"); - - ngx_client_reusable_connection(s); - - pool = s->pool; - NGX_DESTROY_POOL(pool); -} - - -static void -ngx_client_close_handler(ngx_event_t *ev) -{ - ngx_client_session_t *s; - ngx_pool_t *pool; - ngx_client_closed_pt closed; - - s = ev->data; - - ngx_log_debug0(NGX_LOG_DEBUG_CORE, &s->log, 0, "nginx client close"); - - if (s->client_closed) { - closed = s->client_closed; - s->client_closed = NULL; - - closed(s); - } - - ngx_client_close_connection(s); - - pool = s->pool; - NGX_DESTROY_POOL(pool); /* s alloc from pool */ -} - - -void -ngx_client_close(ngx_client_session_t *s) -{ - ngx_event_t *e; - - if (s->closed) { - return; - } - - s->log.action = "close"; - - s->closed = 1; - - e = &s->close; - e->data = s; - e->handler = ngx_client_close_handler; - e->log = &s->log; - - ngx_post_event(e, &ngx_posted_events); -} - - -ngx_chain_t * -ngx_client_state(ngx_http_request_t *r, unsigned detail) -{ - ngx_client_conf_t *ccf; - ngx_chain_t *cl; - ngx_buf_t *b; - ngx_map_node_t *node; - ngx_client_pool_t *pool; - size_t len, len1; - ngx_uint_t n; - - ccf = (ngx_client_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_client_module); - - len = sizeof("##########ngx client connection pool##########\n") - 1 - + sizeof("ngx_client_pool nalloc node: \n") - 1 + NGX_OFF_T_LEN - + sizeof("ngx_client_pool nfree node: \n") - 1 + NGX_OFF_T_LEN - + sizeof("ngx_client_pool idle connection: \n") - 1 + NGX_OFF_T_LEN; - - len1 = 0; - - /* node for create pool */ - if (detail) { - n = ccf->nalloc - ccf->nfree; - /* " addr:port: qsize\n" */ - len1 = 4 + NGX_SOCKADDR_STRLEN + 2 + NGX_OFF_T_LEN + 1; - len += len1 * n; - } - - cl = ngx_alloc_chain_link(r->pool); - if (cl == NULL) { - return NULL; - } - cl->next = NULL; - - b = ngx_create_temp_buf(r->pool, len); - if (b == NULL) { - return NULL; - } - cl->buf = b; - - b->last = ngx_snprintf(b->last, len, - "##########ngx client connection pool##########\n" - "ngx_client_pool nalloc node: %ui\n" - "ngx_client_pool nfree node: %ui\n" - "ngx_client_pool idle connection: %ui\n", - ccf->nalloc, ccf->nfree, ccf->idle_connction); - - if (detail) { - for (node = ngx_map_begin(&ccf->client_pools); node; - node = ngx_map_next(node)) - { - /* m is first element of ngx_poold_node_t */ - pool = (ngx_client_pool_t *) node; - b->last = ngx_snprintf(b->last, len1, " %V: %ui\n", - &pool->paddr, pool->qsize); - } - } - - return cl; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/ngx_client.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/ngx_client.h deleted file mode 100644 index 7b67b7b81e..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/ngx_client.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#ifndef _NGX_CLIENT_H_INCLUDED_ -#define _NGX_CLIENT_H_INCLUDED_ - - -#include -#include -#include -#include - - -typedef struct ngx_client_session_s ngx_client_session_t; - -typedef void (* ngx_client_connect_pt)(ngx_client_session_t *s); -typedef void (* ngx_client_recv_pt)(ngx_client_session_t *s); -typedef void (* ngx_client_send_pt)(ngx_client_session_t *s); -typedef void (* ngx_client_closed_pt)(ngx_client_session_t *s); - - -struct ngx_client_session_s { - ngx_peer_connection_t peer; - ngx_str_t server; /* server original address */ - in_port_t port; /* server port */ - - ngx_connection_t *connection; - - ngx_pool_t *pool; - ngx_log_t log; - - void *data; /* save ctx for callback */ - - ngx_chain_t *out; /* save data unsend */ - - /* configured part */ - - /* timer for connecting to server */ - ngx_msec_t connect_timeout; - - /* timer for sending buffer full */ - ngx_msec_t send_timeout; - - /* - * data will be postponed until nginx has at least - * postpone_output bytes of data to send - */ - size_t postpone_output; - - /* use dynamic resolver mechanism for resolving domain */ - unsigned dynamic_resolver:1; - - unsigned tcp_nodelay:1; /* TCP_NODELAY */ - unsigned tcp_nopush:1; /* TCP_CORK */ - - /* runtime part */ - - size_t recv; /* client recv bytes */ - - unsigned connected:1; /* client connected to server */ - unsigned closed:1; /* client has been closed */ - - ngx_event_t close; /* for async close */ - - /* callback */ - - ngx_client_connect_pt client_connected; /* connect successd */ - ngx_client_recv_pt client_recv; /* recv msg from peer */ - ngx_client_send_pt client_send; /* send msg to peer */ - ngx_client_closed_pt client_closed; /* finalize connection */ -}; - - -/* - * create a client session - * - * return value: - * return client session for successd, return NULL for failed - * paras: - * peer: server address and port, address could be domain or ip - * local: set if need to bind local address, or set NULL - * udp: set 1, use udp, set 0, use tcp - * log: for logging error when create client session failed - */ -ngx_client_session_t *ngx_client_create(ngx_str_t *peer, ngx_str_t *local, - ngx_flag_t udp, ngx_log_t *log); - - -/* - * connect to client server, should use client session created by - * ngx_client_create. before connect to server, user can set paras in - * configured part. - * - * return value: - * void - * paras: - * s: client session created by ngx_client_create - */ -void ngx_client_connect(ngx_client_session_t *s); - - -/* - * send data to server - * - * return value: - * NGX_ERROR: write error, client session will be closed - * NGX_AGAIN: data not sent completely, it will save in client session out - * NGX_OK: data sent completely - * paras: - * s: client session - * out: data for sending - */ -ngx_int_t ngx_client_write(ngx_client_session_t *s, ngx_chain_t *out); - - -/* - * read data from server - * - * return value: - * NGX_ERROR: read error, client session will be closed - * NGX_DECLINED: buf for receiving data is full - * NGX_AGAIN: no data for reading - * 0: server closed - * >0: bytes read into buffer - * paras: - * s: client session - * b: buffer for receiving data - */ -ngx_int_t ngx_client_read(ngx_client_session_t *s, ngx_buf_t *b); - - -/* - * keepalive client connection, and destroy session - * if use client connect the same ip:port, - * new client session will reuse the connection - * - * return value: - * void - * paras: - * s: client session - */ -void ngx_client_set_keepalive(ngx_client_session_t *s); - - -/* - * close client session - * - * return value: - * void - * paras: - * s: client session - */ -void ngx_client_close(ngx_client_session_t *s); - - -/* - * paras: - * r: http request to query status of client - */ -ngx_chain_t *ngx_client_state(ngx_http_request_t *r, unsigned detail); - - -#endif diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/ngx_http_client.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/ngx_http_client.c deleted file mode 100644 index 3a94803c53..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/ngx_http_client.c +++ /dev/null @@ -1,1889 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include "ngx_http_client.h" -#include "ngx_rbuf.h" -#include "ngx_poold.h" -#include "ngx_map.h" -#include "ngx_timerd.h" - - -static void *ngx_http_client_module_create_conf(ngx_cycle_t *cycle); -static char *ngx_http_client_module_init_conf(ngx_cycle_t *cycle, void *conf); - -/* headers in */ -static ngx_int_t ngx_http_client_process_header_line(ngx_http_request_t *r, - ngx_table_elt_t *h, ngx_uint_t offset); -static ngx_int_t ngx_http_client_process_content_length(ngx_http_request_t *r, - ngx_table_elt_t *h, ngx_uint_t offset); -static ngx_int_t ngx_http_client_process_connection(ngx_http_request_t *r, - ngx_table_elt_t *h, ngx_uint_t offset); -static ngx_int_t - ngx_http_client_process_transfer_encoding(ngx_http_request_t *r, - ngx_table_elt_t *h, ngx_uint_t offset); - -/* headers out */ -static void ngx_http_client_host(ngx_http_request_t *r, ngx_str_t *value); -static void ngx_http_client_user_agent(ngx_http_request_t *r, - ngx_str_t *value); -static void ngx_http_client_connection(ngx_http_request_t *r, ngx_str_t *value); -static void ngx_http_client_accept(ngx_http_request_t *r, ngx_str_t *value); -static void ngx_http_client_date(ngx_http_request_t *r, ngx_str_t *value); - - -/* for http response */ -typedef struct { - ngx_list_t headers; - - ngx_uint_t http_version; - ngx_uint_t status_n; - ngx_str_t status_line; - - ngx_table_elt_t *status; - ngx_table_elt_t *date; - ngx_table_elt_t *server; - ngx_table_elt_t *connection; - - ngx_table_elt_t *expires; - ngx_table_elt_t *etag; - ngx_table_elt_t *x_accel_expires; - ngx_table_elt_t *x_accel_redirect; - ngx_table_elt_t *x_accel_limit_rate; - - ngx_table_elt_t *content_type; - ngx_table_elt_t *content_length; - - ngx_table_elt_t *last_modified; - ngx_table_elt_t *location; - ngx_table_elt_t *accept_ranges; - ngx_table_elt_t *www_authenticate; - ngx_table_elt_t *transfer_encoding; - -#if (NGX_HTTP_GZIP) - ngx_table_elt_t *content_encoding; -#endif - - off_t content_length_n; - - unsigned connection_type:2; - unsigned chunked:1; -} ngx_http_client_headers_in_t; - - -typedef struct { - ngx_map_node_t node; - ngx_str_t key; - ngx_str_t value; -} ngx_http_client_header_out_t; - - -typedef struct { - ngx_array_t headers; /* ngx_http_client_header_out_t */ - ngx_map_t hash; /* find header by header */ -} ngx_http_client_headers_out_t; - - -typedef struct { - ngx_client_session_t *session; - void *request; - - /* Request */ - ngx_request_url_t url; - - /* Response */ - ngx_http_status_t status; - ngx_http_chunked_t chunked; - ngx_int_t length; - - /* bufs */ - ngx_chain_t *in; - ngx_buf_t *buffer; /* status line buf */ - - /* config */ - ngx_msec_t header_timeout; - size_t header_buffer_size; - - /* runtime */ - off_t rbytes; /* read bytes */ - off_t wbytes; /* write bytes */ - - ngx_http_client_headers_in_t headers_in; - ngx_http_client_headers_out_t headers_out; - - ngx_http_client_handler_pt read_handler; - ngx_http_client_handler_pt write_handler; -} ngx_http_client_ctx_t; - - -static ngx_str_t ngx_http_client_method[] = { - ngx_string("GET"), - ngx_string("HEAD"), - ngx_string("POST"), - ngx_string("PUT"), - ngx_string("DELETE"), - ngx_string("MKCOL"), - ngx_string("COPY"), - ngx_string("MOVE"), - ngx_string("OPTIONS"), - ngx_string("PROPFIND"), - ngx_string("PROPPATCH"), - ngx_string("LOCK"), - ngx_string("UNLOCK"), - ngx_string("PATCH"), - ngx_string("TRACE") -}; - - -static ngx_str_t ngx_http_client_version[] = { - ngx_string("HTTP/0.9"), /* not support, will not use */ - ngx_string("HTTP/1.0"), - ngx_string("HTTP/1.1"), - ngx_string("HTTP/2.0") -}; - - -#define NGX_HTTP_CLIENT_CONNECTION_CLOSE 1 -#define NGX_HTTP_CLIENT_CONNECTION_KEEP_ALIVE 2 -#define NGX_HTTP_CLIENT_CONNECTION_UPGRADE 3 - - -typedef void (*ngx_http_client_fill_header_pt)(ngx_http_request_t *r, - ngx_str_t *value); - -typedef struct { - ngx_str_t name; - ngx_http_client_fill_header_pt handler; -} ngx_http_client_fill_header_t; - - -typedef struct { - ngx_hash_t headers_in_hash; - - /* wait for response header timeout */ - ngx_msec_t header_timeout; - size_t header_buffer_size; - size_t body_buffer_size; -} ngx_http_client_conf_t; - - -ngx_http_header_t ngx_http_client_headers_in[] = { - - { ngx_string("Status"), offsetof(ngx_http_client_headers_in_t, status), - ngx_http_client_process_header_line }, - - { ngx_string("Date"), offsetof(ngx_http_client_headers_in_t, date), - ngx_http_client_process_header_line }, - - { ngx_string("Server"), offsetof(ngx_http_client_headers_in_t, server), - ngx_http_client_process_header_line }, - - { ngx_string("Connection"), - offsetof(ngx_http_client_headers_in_t, connection), - ngx_http_client_process_connection }, - - { ngx_string("Expires"), offsetof(ngx_http_client_headers_in_t, expires), - ngx_http_client_process_header_line }, - - { ngx_string("ETag"), offsetof(ngx_http_client_headers_in_t, etag), - ngx_http_client_process_header_line }, - - { ngx_string("X-Accel-Expires"), - offsetof(ngx_http_client_headers_in_t, x_accel_expires), - ngx_http_client_process_header_line }, - - { ngx_string("X-Accel-Redirect"), - offsetof(ngx_http_client_headers_in_t, x_accel_redirect), - ngx_http_client_process_header_line }, - - { ngx_string("X-Accel-Limit-Rate"), - offsetof(ngx_http_client_headers_in_t, x_accel_limit_rate), - ngx_http_client_process_header_line }, - - { ngx_string("Content-Type"), - offsetof(ngx_http_client_headers_in_t, content_type), - ngx_http_client_process_header_line }, - - { ngx_string("Content-Length"), - offsetof(ngx_http_client_headers_in_t, content_length), - ngx_http_client_process_content_length }, - - { ngx_string("Last-Modified"), - offsetof(ngx_http_client_headers_in_t, last_modified), - ngx_http_client_process_header_line }, - - { ngx_string("Location"), offsetof(ngx_http_client_headers_in_t, location), - ngx_http_client_process_header_line }, - - { ngx_string("Accept-Ranges"), - offsetof(ngx_http_client_headers_in_t, accept_ranges), - ngx_http_client_process_header_line }, - - { ngx_string("WWW-Authenticate"), - offsetof(ngx_http_client_headers_in_t, www_authenticate), - ngx_http_client_process_header_line }, - - { ngx_string("Transfer-Encoding"), - offsetof(ngx_http_client_headers_in_t, transfer_encoding), - ngx_http_client_process_transfer_encoding }, - -#if (NGX_HTTP_GZIP) - { ngx_string("Content-Encoding"), - offsetof(ngx_http_client_headers_in_t, content_encoding), - ngx_http_client_process_header_line }, -#endif - - { ngx_null_string, 0, NULL } -}; - - -ngx_http_client_fill_header_t ngx_http_client_default_header[] = { - { ngx_string("Host"), ngx_http_client_host }, - { ngx_string("User-Agent"), ngx_http_client_user_agent }, - { ngx_string("Connection"), ngx_http_client_connection }, - { ngx_string("Accept"), ngx_http_client_accept }, - { ngx_string("Date"), ngx_http_client_date }, - { ngx_null_string, NULL } -}; - - -static ngx_command_t ngx_http_client_commands[] = { - - { ngx_string("header_timeout"), - NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - 0, - offsetof(ngx_http_client_conf_t, header_timeout), - NULL }, - - { ngx_string("header_buffer_size"), - NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - 0, - offsetof(ngx_http_client_conf_t, header_buffer_size), - NULL }, - - { ngx_string("body_buffer_size"), - NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - 0, - offsetof(ngx_http_client_conf_t, body_buffer_size), - NULL }, - - ngx_null_command -}; - - -static ngx_core_module_t ngx_http_client_module_ctx = { - ngx_string("http_client"), - ngx_http_client_module_create_conf, - ngx_http_client_module_init_conf -}; - - -ngx_module_t ngx_http_client_module = { - NGX_MODULE_V1, - &ngx_http_client_module_ctx, /* module context */ - ngx_http_client_commands, /* module directives */ - NGX_CORE_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void * -ngx_http_client_module_create_conf(ngx_cycle_t *cycle) -{ - ngx_http_client_conf_t *hccf; - - hccf = ngx_pcalloc(cycle->pool, sizeof(ngx_http_client_conf_t)); - if (hccf == NULL) { - return NULL; - } - - hccf->header_timeout = NGX_CONF_UNSET_MSEC; - hccf->header_buffer_size = NGX_CONF_UNSET_SIZE; - hccf->body_buffer_size = NGX_CONF_UNSET_SIZE; - - return hccf; -} - - -static char * -ngx_http_client_module_init_conf(ngx_cycle_t *cycle, void *conf) -{ - ngx_http_client_conf_t *hccf = conf; - - ngx_array_t headers_in; - ngx_hash_key_t *hk; - ngx_hash_init_t hash; - ngx_http_header_t *header; - - /* upstream_headers_in_hash */ - - if (ngx_array_init(&headers_in, cycle->pool, 32, sizeof(ngx_hash_key_t)) - != NGX_OK) - { - return NGX_CONF_ERROR; - } - - for (header = ngx_http_client_headers_in; header->name.len; header++) { - hk = ngx_array_push(&headers_in); - if (hk == NULL) { - return NGX_CONF_ERROR; - } - - hk->key = header->name; - hk->key_hash = ngx_hash_key_lc(header->name.data, header->name.len); - hk->value = header; - } - - hash.hash = &hccf->headers_in_hash; - hash.key = ngx_hash_key_lc; - hash.max_size = 512; - hash.bucket_size = ngx_align(64, ngx_cacheline_size); - hash.name = "upstream_headers_in_hash"; - hash.pool = cycle->pool; - hash.temp_pool = NULL; - - if (ngx_hash_init(&hash, headers_in.elts, headers_in.nelts) != NGX_OK) { - return NGX_CONF_ERROR; - } - - ngx_conf_init_msec_value(hccf->header_timeout, 10000); - ngx_conf_init_size_value(hccf->header_buffer_size, ngx_pagesize); - ngx_conf_init_size_value(hccf->body_buffer_size, ngx_pagesize); - - return NGX_CONF_OK; -} - - -static ngx_int_t -ngx_http_client_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, - ngx_uint_t offset) -{ - ngx_table_elt_t **ph; - ngx_http_client_ctx_t *ctx; - - ctx = r->ctx[0]; - - ph = (ngx_table_elt_t **) ((char *) &ctx->headers_in + offset); - - if (*ph == NULL) { - *ph = h; - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_http_client_process_content_length(ngx_http_request_t *r, - ngx_table_elt_t *h, ngx_uint_t offset) -{ - ngx_http_client_ctx_t *ctx; - - ctx = r->ctx[0]; - - if (ctx->headers_in.content_length != NULL) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "duplicate Content-Length header, %V: %V", &h->key, &h->value); - return NGX_ERROR; - } - - ctx->headers_in.content_length = h; - ctx->headers_in.content_length_n = ngx_atoof(h->value.data, h->value.len); - - return NGX_OK; -} - - -static ngx_int_t -ngx_http_client_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h, - ngx_uint_t offset) -{ - ngx_http_client_ctx_t *ctx; - - ctx = r->ctx[0]; - - ctx->headers_in.connection = h; - - if (ngx_strcasestrn(h->value.data, "close", 5)) { - ctx->headers_in.connection_type = NGX_HTTP_CLIENT_CONNECTION_CLOSE; - } else if (ngx_strcasestrn(h->value.data, "keep-alive", 10)) { - ctx->headers_in.connection_type = NGX_HTTP_CLIENT_CONNECTION_KEEP_ALIVE; - } else if (ngx_strcasestrn(h->value.data, "upgrade", 7)) { - ctx->headers_in.connection_type = NGX_HTTP_CLIENT_CONNECTION_UPGRADE; - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_http_client_process_transfer_encoding(ngx_http_request_t *r, - ngx_table_elt_t *h, ngx_uint_t offset) -{ - ngx_http_client_ctx_t *ctx; - - ctx = r->ctx[0]; - - ctx->headers_in.transfer_encoding = h; - - if (ngx_strlcasestrn(h->value.data, h->value.data + h->value.len, - (u_char *) "chunked", 7 - 1) - != NULL) - { - ctx->headers_in.chunked = 1; - } - - return NGX_OK; -} - - -static void -ngx_http_client_host(ngx_http_request_t *r, ngx_str_t *value) -{ - ngx_http_client_ctx_t *ctx; - - ctx = r->ctx[0]; - - value->data = ctx->url.host.data; - value->len = ctx->url.host.len; -} - - -static void -ngx_http_client_user_agent(ngx_http_request_t *r, ngx_str_t *value) -{ - value->data = (u_char *) NGINX_VER; - value->len = sizeof(NGINX_VER) - 1; -} - - -static void -ngx_http_client_connection(ngx_http_request_t *r, ngx_str_t *value) -{ - if (r->http_version < NGX_HTTP_CLIENT_VERSION_11) { - value->data = (u_char *) "close"; - value->len = sizeof("close") - 1; - } else { - value->len = 0; - } -} - - -static void -ngx_http_client_accept(ngx_http_request_t *r, ngx_str_t *value) -{ - value->data = (u_char *) "*/*"; - value->len = sizeof("*/*") - 1; -} - - -static void -ngx_http_client_date(ngx_http_request_t *r, ngx_str_t *value) -{ - value->data = ngx_cached_http_time.data; - value->len = ngx_cached_http_time.len; -} - - -static void -ngx_http_client_free_request(ngx_http_request_t *hcr) -{ - ngx_http_client_ctx_t *ctx; - ngx_client_session_t *s; - ngx_pool_t *pool; - ngx_http_cleanup_t *cln; - - if (hcr->pool == NULL) { - return; - } - - ctx = hcr->ctx[0]; - s = ctx->session; - - if (ctx->request) { - cln = hcr->cleanup; - hcr->cleanup = NULL; - - while (cln) { - if (cln->handler) { - cln->handler(cln->data); - } - - cln = cln->next; - } - } - - if (ctx->in) { - ngx_put_chainbufs(ctx->in); - ctx->in = NULL; - } - - if (s) { - s->client_recv = NULL; - s->client_send = NULL; - s->client_closed = NULL; - s->out = NULL; - } - - pool = hcr->pool; - hcr->pool = NULL; - - NGX_DESTROY_POOL(pool); -} - - -static void -ngx_http_client_close_handler(ngx_client_session_t *s) -{ - ngx_http_request_t *r; - - r = s->data; - - ngx_http_client_free_request(r); -} - - -static void -ngx_http_client_discarded_body(ngx_http_request_t *r) -{ - ngx_http_client_ctx_t *ctx; - ngx_chain_t *cl; - ngx_int_t rc; - - ctx = r->ctx[0]; - - rc = ngx_http_client_read_body(r, &cl); - - if (rc == 0 || rc == NGX_ERROR) { // http client close - ngx_http_client_finalize_request(r, 1); - return; - } - - // if detach, all http response receive, set keepalive - if (rc == NGX_DONE) { - ngx_http_client_finalize_request(r, 0); - return; - } - - // NGX_AGAIN - - if (ctx->in) { // make rbuf recycle immediately - ngx_put_chainbufs(ctx->in); - ctx->in = NULL; - } -} - - -static void -ngx_http_client_read_handler(ngx_client_session_t *s) -{ - ngx_http_request_t *r; - ngx_http_client_ctx_t *ctx; - - r = s->data; - ctx = r->ctx[0]; - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http client, read handler"); - - if (ctx->request && ctx->read_handler) { - ctx->read_handler(ctx->request, r); - } else { - ngx_http_client_discarded_body(r); - } -} - - -static void -ngx_http_client_process_header(ngx_client_session_t *s) -{ - ngx_http_request_t *r; - ngx_http_client_ctx_t *ctx; - ngx_buf_t *b; - ngx_int_t n, rc; - ngx_table_elt_t *h; - ngx_http_header_t *hh; - ngx_http_client_conf_t *hccf; - ngx_event_t *rev; - - hccf = (ngx_http_client_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_http_client_module); - - r = s->data; - ctx = r->ctx[0]; - rev = r->connection->read; - - b = ctx->buffer; - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http client, process header"); - - for (;;) { - - rc = ngx_http_parse_header_line(r, b, 1); - - if (rc == NGX_OK) { - - /* a header line has been parsed successfully */ - - h = ngx_list_push(&ctx->headers_in.headers); - if (h == NULL) { - goto error; - } - - h->hash = r->header_hash; - - h->key.len = r->header_name_end - r->header_name_start; - h->value.len = r->header_end - r->header_start; - - h->key.data = ngx_pnalloc(r->pool, - h->key.len + 1 + h->value.len + 1 + h->key.len); - if (h->key.data == NULL) { - goto error; - } - - h->value.data = h->key.data + h->key.len + 1; - h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1; - - ngx_memcpy(h->key.data, r->header_name_start, h->key.len); - h->key.data[h->key.len] = '\0'; - ngx_memcpy(h->value.data, r->header_start, h->value.len); - h->value.data[h->value.len] = '\0'; - - if (h->key.len == r->lowcase_index) { - ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len); - - } else { - ngx_strlow(h->lowcase_key, h->key.data, h->key.len); - } - - hh = ngx_hash_find(&hccf->headers_in_hash, h->hash, - h->lowcase_key, h->key.len); - - if (hh && hh->handler(r, h, hh->offset) != NGX_OK) { - goto error; - } - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http server header: \"%V: %V\"", &h->key, &h->value); - - continue; - } - - if (rc == NGX_HTTP_PARSE_HEADER_DONE) { - - /* a whole header has been parsed successfully */ - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http server header done"); - - /* - * if no "Server" and "Date" in header line, - * then add the special empty headers - */ - - if (ctx->headers_in.server == NULL) { - h = ngx_list_push(&ctx->headers_in.headers); - if (h == NULL) { - goto error; - } - - h->hash = ngx_hash(ngx_hash(ngx_hash(ngx_hash( - ngx_hash('s', 'e'), 'r'), 'v'), 'e'), 'r'); - - ngx_str_set(&h->key, "Server"); - ngx_str_null(&h->value); - h->lowcase_key = (u_char *) "server"; - } - - if (ctx->headers_in.date == NULL) { - h = ngx_list_push(&ctx->headers_in.headers); - if (h == NULL) { - goto error; - } - - h->hash = ngx_hash(ngx_hash(ngx_hash('d', 'a'), 't'), 'e'); - - ngx_str_set(&h->key, "Date"); - ngx_str_null(&h->value); - h->lowcase_key = (u_char *) "date"; - } - - /* clear content length if response is chunked */ - - if (ctx->headers_in.chunked) { - ctx->headers_in.content_length_n = -1; - } - - ctx->length = ctx->headers_in.content_length_n; - - break; - } - - if (rc == NGX_AGAIN) { - n = ngx_client_read(s, b); - - if (n == NGX_ERROR || n == 0) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno, - "http client, process header read error"); - ngx_http_client_finalize_request(r, 1); - return; - } - - if (n == NGX_AGAIN) { - if (!rev->timer_set) { - NGX_ADD_TIMER(rev, ctx->header_timeout, - offsetof(ngx_connection_t, number)); - } - - if (ngx_handle_read_event(rev, 0) != NGX_OK) { - ngx_http_client_finalize_request(r, 1); - return; - } - - return; - } - - /* NGX_OK */ - ctx->rbytes += n; - - continue; - } - - /* there was error while a header line parsing */ - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "http client, http server sent invalid header"); - - goto error; - } - - s->client_recv = ngx_http_client_read_handler; - - if (rev->timer_set) { - NGX_DEL_TIMER(rev, r->connection->number); - } - - return ngx_http_client_read_handler(s); - -error: - ngx_http_client_finalize_request(r, 1); -} - - -static void -ngx_http_client_process_status_line(ngx_client_session_t *s) -{ - ngx_http_request_t *r; - ngx_http_client_ctx_t *ctx; - ngx_buf_t *b; - ngx_int_t n, rc; - ngx_event_t *rev; - - r = s->data; - ctx = r->ctx[0]; - rev = r->connection->read; - - b = ctx->buffer; - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http client, process status line"); - - for (;;) { - rc = ngx_http_parse_status_line(r, b, &ctx->status); - - if (rc == NGX_AGAIN) { - n = ngx_client_read(s, b); - - if (n == NGX_ERROR || n == 0) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno, - "http client, process status line read error"); - ngx_http_client_finalize_request(r, 1); - return; - } - - if (n == NGX_AGAIN) { - if (!rev->timer_set) { - NGX_ADD_TIMER(rev, ctx->header_timeout, - offsetof(ngx_connection_t, number)); - } - - if (ngx_handle_read_event(rev, 0) != NGX_OK) { - ngx_http_client_finalize_request(r, 1); - return; - } - - return; - } - - /* NGX_OK */ - ctx->rbytes += n; - - continue; - } - - if (rc == NGX_ERROR) { - - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "http client, recv no valid HTTP/1.0 header"); - - r->http_version = NGX_HTTP_VERSION_9; - } - - /* NGX_OK */ - break; - } - - ctx->headers_in.http_version = ctx->status.http_version; - ctx->headers_in.status_n = ctx->status.code; - - ctx->headers_in.status_line.len = ctx->status.end - ctx->status.start; - ctx->headers_in.status_line.data = ngx_pcalloc(r->connection->pool, - ctx->headers_in.status_line.len); - if (ctx->headers_in.status_line.data == NULL) { - ngx_http_client_finalize_request(r, 1); - return; - } - ngx_memcpy(ctx->headers_in.status_line.data, ctx->status.start, - ctx->headers_in.status_line.len); - - s->client_recv = ngx_http_client_process_header; - return ngx_http_client_process_header(s); -} - - -static void -ngx_http_client_wait_response_handler(ngx_client_session_t *s) -{ - ngx_http_request_t *r; - ngx_http_client_ctx_t *ctx; - ngx_buf_t *b; - ngx_connection_t *c; - size_t size; - ngx_int_t n; - ngx_event_t *rev; - - r = s->data; - c = r->connection; - ctx = r->ctx[0]; - size = ctx->header_buffer_size; - rev = s->connection->read; - - b = ctx->buffer; - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http client, process response handler"); - - if (b == NULL) { - b = ngx_create_temp_buf(c->pool, size); - if (b == NULL) { - ngx_http_client_finalize_request(r, 1); - return; - } - - ctx->buffer = b; - } else if (b->start == NULL) { - - b->start = ngx_pcalloc(c->pool, size); - if (b->start == NULL) { - ngx_http_client_finalize_request(r, 1); - return; - } - - b->last = b->pos = b->start; - b->end = b->last + size; - } - - n = ngx_client_read(s, b); - /* - * if NGX_ERROR or no bytes read - * if ngx_client_read return NGX_ERROR, s will reconnect - * if 0, ngx_http_client_wait_response_handler - * will called next read event triggered - */ - if (n == NGX_ERROR || n == 0) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno, - "http client, process response handler read error, rc :%i", n); - ngx_http_client_finalize_request(r, 1); - return; - } - - if (n == NGX_AGAIN) { - if (!rev->timer_set) { - NGX_ADD_TIMER(rev, ctx->header_timeout, - offsetof(ngx_connection_t, number)); - } - - if (ngx_handle_read_event(rev, 0) != NGX_OK) { - ngx_http_client_finalize_request(r, 1); - return; - } - - return; - } - - ctx->rbytes += n; - - s->client_recv = ngx_http_client_process_status_line; - return ngx_http_client_process_status_line(s); -} - - -static ngx_int_t -ngx_http_client_set_url(ngx_http_request_t *r, ngx_str_t *url, ngx_log_t *log) -{ - ngx_http_client_ctx_t *ctx; - ngx_client_session_t *cs; - ngx_int_t rc; - - ctx = r->ctx[0]; - - if (ctx->session) { - ngx_log_error(NGX_LOG_INFO, log, 0, "http client, url has been set"); - return NGX_OK; - } - - r->request_line.data = ngx_pcalloc(r->pool, url->len); - if (r->request_line.data == NULL) { - return NGX_ERROR; - } - ngx_memcpy(r->request_line.data, url->data, url->len); - r->request_line.len = url->len; - - rc = ngx_parse_request_url(&ctx->url, &r->request_line); - if (rc == NGX_ERROR) { - return NGX_ERROR; - } - - /* create session */ - cs = ngx_client_create(&ctx->url.host, NULL, 0, log); - if (cs == NULL) { - return NGX_ERROR; - } - - cs->port = ngx_request_port(&ctx->url.scheme, &ctx->url.port); - - ctx->session = cs; - cs->data = r; - - return NGX_OK; -} - - -static ngx_int_t -ngx_http_client_add_header(ngx_http_request_t *r, ngx_str_t *header, - ngx_str_t *value) -{ - ngx_http_client_ctx_t *ctx; - ngx_http_client_header_out_t *h; - ngx_map_node_t *node; - - ctx = r->ctx[0]; - - node = ngx_map_find(&ctx->headers_out.hash, (intptr_t) header); - if (node) { // header exist - h = (ngx_http_client_header_out_t *) node; - } else { // header not exist - h = ngx_array_push(&ctx->headers_out.headers); - if (h == NULL) { - return NGX_ERROR; - } - ngx_memzero(h, sizeof(ngx_http_client_header_out_t)); - - h->key.data = ngx_pcalloc(r->pool, header->len); - if (h->key.data == NULL) { - return NGX_ERROR; - } - ngx_memcpy(h->key.data, header->data, header->len); - h->key.len = header->len; - - h->node.raw_key = (intptr_t) &h->key; - ngx_map_insert(&ctx->headers_out.hash, &h->node, 1); - } - - if (value->len == 0) { // delete header - h->value.len = 0; - return NGX_OK; - } - - // add or modify header - h->value.data = ngx_pcalloc(r->pool, value->len); - if (h->value.data == NULL) { - return NGX_ERROR; - } - ngx_memcpy(h->value.data, value->data, value->len); - h->value.len = value->len; - - return NGX_OK; -} - - -static ngx_buf_t * -ngx_http_client_create_request_buf(ngx_client_session_t *s) -{ - ngx_http_request_t *r; - ngx_http_client_ctx_t *ctx; - ngx_buf_t *b; - size_t len; - ngx_http_client_header_out_t *h; - ngx_uint_t i; - - r = s->data; - ctx = r->ctx[0]; - - /* Request Line */ - /* method */ - len = ngx_http_client_method[r->method].len + 1; /* "GET " */ - - /* path + args */ - ++len; /* "/" */ - if (ctx->url.path.len) { - /* "path" */ - len += ctx->url.path.len; - } - - if (ctx->url.args.len) { - /* "?args" */ - ++len; - len += ctx->url.args.len; - } - ++len; /* " " */ - - /* version */ - len += sizeof("HTTP/1.x") - 1 + sizeof(CRLF) - 1; - - /* Request Headers */ - /* User set headers */ - h = ctx->headers_out.headers.elts; - for (i = 0; i < ctx->headers_out.headers.nelts; ++i, ++h) { - if (h->value.len == 0) { - continue; - } - - len += h->key.len + sizeof(": ") - 1 + h->value.len + sizeof(CRLF) - 1; - } - - /* Request Headers end */ - len += sizeof(CRLF) - 1; - - /* start fill http request */ - b = ngx_create_temp_buf(r->pool, len); - if (b == NULL) { - return NULL; - } - - /* method */ - b->last = ngx_cpymem(b->last, ngx_http_client_method[r->method].data, - ngx_http_client_method[r->method].len); - *b->last++ = ' '; - - /* path + args */ - *b->last++ = '/'; - if (ctx->url.path.len) { - b->last = ngx_cpymem(b->last, ctx->url.path.data, ctx->url.path.len); - } - - if (ctx->url.args.len) { - *b->last++ = '?'; - b->last = ngx_cpymem(b->last, ctx->url.args.data, ctx->url.args.len); - } - *b->last++ = ' '; - - /* version */ - b->last = ngx_cpymem(b->last, - ngx_http_client_version[r->http_version].data, - ngx_http_client_version[r->http_version].len); - *b->last++ = CR; *b->last++ = LF; - - /* Request Headers */ - h = ctx->headers_out.headers.elts; - for (i = 0; i < ctx->headers_out.headers.nelts; ++i, ++h) { - if (h->value.len == 0) { - continue; - } - - b->last = ngx_cpymem(b->last, h->key.data, h->key.len); - *b->last++ = ':'; *b->last++ = ' '; - b->last = ngx_cpymem(b->last, h->value.data, h->value.len); - *b->last++ = CR; *b->last++ = LF; - } - - /* Request Headers end */ - *b->last++ = CR; *b->last++ = LF; - - return b; -} - - -static void -ngx_http_client_send_header(ngx_client_session_t *s) -{ - ngx_http_request_t *r; - ngx_http_client_ctx_t *ctx; - ngx_buf_t *b; - ngx_chain_t out; - ngx_event_t *rev; - - r = s->data; - ctx = r->ctx[0]; - - r->connection = s->connection; - rev = r->connection->read; - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http client, send header"); - - r->connection = s->peer.connection; - - b = ngx_http_client_create_request_buf(s); - if (b == NULL) { - goto destroy; - } - b->flush = 1; - - out.buf = b; - out.next = NULL; - - /* send http request header */ - ngx_client_write(s, &out); - - /* user defined, for send body function callback */ - if (ctx->request && ctx->write_handler) { - ctx->write_handler(ctx->request, r); - } - - NGX_ADD_TIMER(rev, ctx->header_timeout, offsetof(ngx_connection_t, number)); - - return; - -destroy: - ngx_http_client_finalize_request(r, 1); -} - - -static ngx_int_t -ngx_http_client_body_length(ngx_http_request_t *r, ngx_chain_t *cl) -{ - ngx_http_client_ctx_t *ctx; - ngx_buf_t *buf; - ngx_chain_t **ll; - ngx_int_t len; - - ctx = r->ctx[0]; - - for (ll = &ctx->in; *ll; ll = &(*ll)->next); - - while (cl) { - *ll = cl; - cl = cl->next; - (*ll)->next = NULL; - - if (ctx->length != -1) { - buf = (*ll)->buf; - - len = ngx_min(buf->last - buf->pos, ctx->length); - ctx->length -= len; - - if (ctx->length == 0) { - if (cl || buf->last - buf->pos > len) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "http client, read unexpected data"); - ngx_put_chainbufs(cl); - } - return NGX_DONE; - } - } - - ll = &(*ll)->next; - } - - return NGX_AGAIN; -} - - -static ngx_int_t -ngx_http_client_body_chunked(ngx_http_request_t *r, ngx_chain_t *cl) -{ - ngx_http_client_ctx_t *ctx; - ngx_http_client_conf_t *hccf; - ngx_buf_t *buf, *b; - ngx_chain_t **ll, *ln; - ngx_int_t rc; - size_t len; - - ctx = r->ctx[0]; - hccf = (ngx_http_client_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_http_client_module); - - for (ll = &ctx->in; *ll; ll = &(*ll)->next); - - while (1) { - - b = cl->buf; - rc = ngx_http_parse_chunked(r, b, &ctx->chunked); - - ngx_log_debug7(NGX_LOG_DEBUG_CORE, r->connection->log, 0, - "http client, parse chunked %p %p-%p %p, rc: %d, %O %O", - b->start, b->pos, b->last, b->end, - rc, ctx->chunked.size, ctx->chunked.length); - - if (rc == NGX_OK) { - - /* a chunk has been parsed successfully */ - - while (1) { - if (*ll == NULL) { - *ll = ngx_get_chainbuf(hccf->body_buffer_size, 1); - if (*ll == NULL) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "http client, get chainbuf failed"); - return NGX_ERROR; - } - } - - buf = (*ll)->buf; - - if (b->last - b->pos >= ctx->chunked.size) { - len = ngx_min(buf->end - buf->last, ctx->chunked.size); - } else { - len = ngx_min(buf->end - buf->last, b->last - b->pos); - } - - buf->last = ngx_cpymem(buf->last, b->pos, len); - b->pos += len; - ctx->chunked.size -= len; - - if (buf->last == buf->end) { - ll = &(*ll)->next; - } - - if (b->pos == b->last) { // current cl read over - ln = cl; - cl = cl->next; - ngx_put_chainbuf(ln); - - if (cl == NULL) { - return NGX_AGAIN; - } - - b = cl->buf; - } - - if (ctx->chunked.size == 0) { // current chunk read over - break; - } - } - - ngx_log_debug7(NGX_LOG_DEBUG_CORE, r->connection->log, 0, - "http client, parse done %p %p-%p %p, rc: %d, %O %O", - b->start, b->pos, b->last, b->end, - rc, ctx->chunked.size, ctx->chunked.length); - - continue; - } - - if (rc == NGX_AGAIN) { - ln = cl; - cl = cl->next; - ngx_put_chainbuf(ln); - - if (cl == NULL) { - return NGX_AGAIN; - } - - continue; - } - - if (rc == NGX_DONE) { - if (b->pos != b->last || cl->next) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "http client, read unexpected chunked data"); - } - ngx_put_chainbufs(cl); - - return NGX_DONE; - } - - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "http client, invalid chunked response"); - - return NGX_ERROR; - } -} - - -/* create and set http request */ - -ngx_http_request_t * -ngx_http_client_create(ngx_log_t *log, ngx_uint_t method, ngx_str_t *url, - ngx_keyval_t *headers, ngx_http_client_handler_pt send_body, void *request) -{ - ngx_pool_t *pool; - ngx_http_request_t *r; - ngx_http_client_ctx_t *ctx; - ngx_http_client_conf_t *hccf; - ngx_http_client_fill_header_t *h; - ngx_str_t value; - - hccf = (ngx_http_client_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_http_client_module); - - if (url == NULL) { - ngx_log_error(NGX_LOG_ERR, log, 0, - "url is NULL when create http client"); - return NULL; - } - - pool = NGX_CREATE_POOL(4096, ngx_cycle->log); - if (pool == NULL) { - ngx_log_error(NGX_LOG_ERR, log, 0, - "client create, create pool failed"); - return NULL; - } - - r = ngx_pcalloc(pool, sizeof(ngx_http_request_t)); - if (r == NULL) { - ngx_log_error(NGX_LOG_ERR, log, 0, - "client create, create http request failed"); - goto destroy; - } - r->pool = pool; - r->main = r; - - /* create http client ctx */ - r->ctx = ngx_pcalloc(pool, sizeof(void *) * 1); - if (r->ctx == NULL) { - ngx_log_error(NGX_LOG_ERR, log, 0, - "client create, create http request ctxs failed"); - goto destroy; - } - - ctx = ngx_pcalloc(pool, sizeof(ngx_http_client_ctx_t)); - if (ctx == NULL) { - ngx_log_error(NGX_LOG_ERR, log, 0, - "client create, create http request ctx failed"); - goto destroy; - } - r->ctx[0] = ctx; - - /* set paras for http client */ - r->method = method; - - /* default version HTTP/1.1 */ - r->http_version = NGX_HTTP_CLIENT_VERSION_11; - - /* for send body */ - ctx->request = request; - ctx->write_handler = send_body; - - ctx->header_timeout = hccf->header_timeout; - ctx->header_buffer_size = hccf->header_buffer_size; - - if (ngx_http_client_set_url(r, url, log) == NGX_ERROR) { - ngx_log_error(NGX_LOG_ERR, log, 0, - "client create, set url failed"); - goto destroy; - } - - /* headers_out */ - if (ngx_array_init(&ctx->headers_out.headers, pool, 64, - sizeof(ngx_http_client_header_out_t)) != NGX_OK) - { - ngx_log_error(NGX_LOG_ERR, log, 0, - "client create, init headers out failed"); - goto destroy; - } - - ngx_map_init(&ctx->headers_out.hash, ngx_map_hash_str, ngx_cmp_str); - - h = ngx_http_client_default_header; - while(h->name.len) { - h->handler(r, &value); - if (ngx_http_client_add_header(r, &h->name, &value) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, log, 0, - "client create, set default header %V: %V failed", - &h->name, &value); - goto destroy; - } - ++h; - } - - while (headers && headers->key.len) { - if (ngx_http_client_add_header(r, &headers->key, &headers->value) - != NGX_OK) - { - ngx_log_error(NGX_LOG_ERR, log, 0, - "client create, set user header %V: %V failed", - &h->name, &value); - goto destroy; - } - ++headers; - } - - return r; - -destroy: - NGX_DESTROY_POOL(pool); - - return NULL; -} - - -ngx_http_cleanup_t * -ngx_http_client_cleanup_add(ngx_http_request_t *r, size_t size) -{ - ngx_http_cleanup_t *cln; - - r = r->main; - - cln = ngx_palloc(r->pool, sizeof(ngx_http_cleanup_t)); - if (cln == NULL) { - return NULL; - } - - if (size) { - cln->data = ngx_palloc(r->pool, size); - if (cln->data == NULL) { - return NULL; - } - - } else { - cln->data = NULL; - } - - cln->handler = NULL; - cln->next = r->cleanup; - - r->cleanup = cln; - - return cln; -} - - -void -ngx_http_client_set_read_handler(ngx_http_request_t *r, - ngx_http_client_handler_pt read_handler) -{ - ngx_http_client_ctx_t *ctx; - - ctx = r->ctx[0]; - - ctx->read_handler = read_handler; -} - - -ngx_int_t -ngx_http_client_set_headers(ngx_http_request_t *r, ngx_keyval_t *headers) -{ - while (headers && headers->key.len) { - if (ngx_http_client_add_header(r, &headers->key, &headers->value) - != NGX_OK) - { - return NGX_ERROR; - } - ++headers; - } - - return NGX_OK; -} - - -void -ngx_http_client_set_write_handler(ngx_http_request_t *r, - ngx_http_client_handler_pt write_handler) -{ - ngx_http_client_ctx_t *ctx; - - ctx = r->ctx[0]; - - ctx->write_handler = write_handler; -} - - -void -ngx_http_client_set_version(ngx_http_request_t *r, ngx_uint_t version) -{ - r->http_version = version; -} - - -void -ngx_http_client_setopt(ngx_http_request_t *r, unsigned opt, ngx_uint_t value) -{ - ngx_http_client_ctx_t *ctx; - ngx_client_session_t *s; - - ctx = r->ctx[0]; - s = ctx->session; - - switch (opt) { - case NGX_HTTP_CLIENT_OPT_CONNECT_TIMEOUT: - s->connect_timeout = value; - break; - case NGX_HTTP_CLIENT_OPT_SEND_TIMEOUT: - s->send_timeout = value; - break; - case NGX_HTTP_CLIENT_OPT_POSTPONE_OUTPUT: - s->postpone_output = value; - break; - case NGX_HTTP_CLIENT_OPT_DYNAMIC_RESOLVER: - s->dynamic_resolver = value > 0; - break; - case NGX_HTTP_CLIENT_OPT_TCP_NODELAY: - s->tcp_nodelay = value > 0; - break; - case NGX_HTTP_CLIENT_OPT_TCP_NOPUSH: - s->tcp_nopush = value > 0; - break; - case NGX_HTTP_CLIENT_OPT_HEADER_TIMEOUT: - ctx->header_timeout = value; - break; - default: - ngx_log_error(NGX_LOG_ERR, &s->log, 0, - "try to set unsupported opt %d", opt); - break; - } -} - -/* send http request */ - -ngx_int_t -ngx_http_client_send(ngx_http_request_t *r) -{ - ngx_client_session_t *s; - ngx_http_client_ctx_t *ctx; - - ctx = r->ctx[0]; - s = ctx->session; - - /* init */ - s->client_connected = ngx_http_client_send_header; - s->client_recv = ngx_http_client_wait_response_handler; - s->client_closed = ngx_http_client_close_handler; - - /* - * init ctx->headers_in, headers_in use c->pool, - * reconnect will destroy and reinit ctx->headsers_in - */ - if (ngx_list_init(&ctx->headers_in.headers, r->pool, 20, - sizeof(ngx_table_elt_t)) - != NGX_OK) - { - return NGX_ERROR; - } - ctx->headers_in.content_length_n = -1; - - ngx_client_connect(s); - - return NGX_OK; -} - - -ngx_http_request_t * -ngx_http_client_get(ngx_log_t *log, ngx_str_t *url, ngx_keyval_t *headers, - void *request) -{ - ngx_http_request_t *r; - - r = ngx_http_client_create(log, NGX_HTTP_CLIENT_GET, url, headers, - NULL, request); - if (r == NULL) { - return NULL; - } - - if (ngx_http_client_send(r) == NGX_ERROR) { - return NULL; - } - - return r; -} - - -ngx_http_request_t * -ngx_http_client_head(ngx_log_t *log, ngx_str_t *url, ngx_keyval_t *headers, - void *request) -{ - ngx_http_request_t *r; - - r = ngx_http_client_create(log, NGX_HTTP_CLIENT_HEAD, url, headers, - NULL, request); - if (r == NULL) { - return NULL; - } - - if (ngx_http_client_send(r) == NGX_ERROR) { - return NULL; - } - - return r; -} - - -ngx_http_request_t * -ngx_http_client_post(ngx_log_t *log, ngx_str_t *url, ngx_keyval_t *headers, - ngx_http_client_handler_pt send_body, void *request) -{ - ngx_http_request_t *r; - - r = ngx_http_client_create(log, NGX_HTTP_CLIENT_POST, url, headers, - send_body, request); - if (r == NULL) { - return NULL; - } - - if (ngx_http_client_send(r) == NGX_ERROR) { - return NULL; - } - - return r; -} - - -/* get response */ - -ngx_uint_t -ngx_http_client_http_version(ngx_http_request_t *r) -{ - ngx_http_client_ctx_t *ctx; - - ctx = r->ctx[0]; - - return ctx->headers_in.http_version; -} - - -ngx_uint_t -ngx_http_client_status_code(ngx_http_request_t *r) -{ - ngx_http_client_ctx_t *ctx; - - ctx = r->ctx[0]; - - return ctx->headers_in.status_n; -} - - -ngx_str_t * -ngx_http_client_header_in(ngx_http_request_t *r, ngx_str_t *key) -{ - ngx_http_client_ctx_t *ctx; - ngx_table_elt_t *h; - ngx_list_part_t *part; - ngx_uint_t i; - - ctx = r->ctx[0]; - - part = &ctx->headers_in.headers.part; - h = part->elts; - - for (i = 0; /* void */; ++i) { - - if (i >= part->nelts) { - if (part->next == NULL) { - break; - } - - part = part->next; - h = part->elts; - i = 0; - } - - if (h[i].hash == 0) { - continue; - } - - if (h[i].key.len == key->len - && ngx_strncasecmp(h[i].key.data, key->data, key->len) == 0) - { - return &h[i].value; - } - } - - return NULL; -} - - -ngx_int_t -ngx_http_client_read_body(ngx_http_request_t *r, ngx_chain_t **in) -{ - ngx_client_session_t *s; - ngx_http_client_ctx_t *ctx; - ngx_http_client_conf_t *hccf; - ngx_buf_t *buf; - ngx_int_t n, rc; - ngx_event_t *rev; - ngx_chain_t *cl, **ll, *ln; - - ctx = r->ctx[0]; - s = ctx->session; - rev = r->connection->read; - hccf = (ngx_http_client_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_http_client_module); - - // recycle bufs - while (ctx->in) { - cl = ctx->in; - ctx->in = cl->next; - if (cl->buf->pos != cl->buf->last) { - break; - } - - ngx_put_chainbuf(cl); - } - - cl = NULL; - ll = &cl; - - // part of body will read with header - if (ctx->buffer->last != ctx->buffer->pos) { - ln = ngx_get_chainbuf(hccf->body_buffer_size, 0); - if (ln == NULL) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "http client, alloc chainbuf without buffer failed"); - return NGX_ERROR; - } - buf = ln->buf; - buf->pos = ctx->buffer->pos; - buf->last = ctx->buffer->last; - ctx->buffer->pos = ctx->buffer->last; - - *ll = ln; - ll = &(*ll)->next; - } - - // start read - while (1) { - ln = ngx_get_chainbuf(hccf->body_buffer_size, 1); - if (ln == NULL) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "http client, alloc chainbuf with buffer failed"); - return NGX_ERROR; - } - buf = ln->buf; - - n = ngx_client_read(s, buf); - - if (n == 0) { - ngx_put_chainbuf(ln); - ngx_put_chainbufs(cl); - - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "http client, server close"); - return 0; - } - - if (n == NGX_ERROR) { - ngx_put_chainbuf(ln); - ngx_put_chainbufs(cl); - - ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno, - "http client, server error close"); - return NGX_ERROR; - } - - if (n == NGX_AGAIN) { // all data in socket has been read - ngx_put_chainbuf(ln); - - if (ngx_handle_read_event(rev, 0) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno, - "http client, handle read event error"); - return NGX_ERROR; - } - - break; - } - - *ll = ln; - ll = &(*ll)->next; - ctx->rbytes += n; - } - - if (ctx->headers_in.chunked) { - rc = ngx_http_client_body_chunked(r, cl); - } else { - rc = ngx_http_client_body_length(r, cl); - } - - if (rc == NGX_ERROR) { // parse chunked error - return NGX_ERROR; - } - - *in = ctx->in; - if (rc == NGX_DONE) { // all body has been read - return NGX_DONE; - } - - return NGX_AGAIN; -} - - -off_t -ngx_http_client_rbytes(ngx_http_request_t *r) -{ - ngx_http_client_ctx_t *ctx; - - ctx = r->ctx[0]; - - return ctx->rbytes; -} - - -off_t -ngx_http_client_wbytes(ngx_http_request_t *r) -{ - ngx_http_client_ctx_t *ctx; - - ctx = r->ctx[0]; - - return ctx->wbytes; -} - - -/* end request */ - -void -ngx_http_client_detach(ngx_http_request_t *r) -{ - ngx_http_client_ctx_t *ctx; - - if (r == NULL) { - return; - } - - ctx = r->ctx[0]; - - ctx->request = NULL; - - if (r->connection) { - ngx_post_event(r->connection->read, &ngx_posted_events); - } -} - - -void -ngx_http_client_finalize_request(ngx_http_request_t *r, ngx_flag_t closed) -{ - ngx_http_client_ctx_t *ctx; - ngx_client_session_t *s; - - ctx = r->ctx[0]; - s = ctx->session; - - ngx_http_client_free_request(r); - - if (closed) { - ngx_client_close(s); - } else { - ngx_client_set_keepalive(s); - } -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/ngx_http_client.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/ngx_http_client.h deleted file mode 100644 index d06a620773..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/ngx_http_client.h +++ /dev/null @@ -1,323 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#ifndef _NGX_HTTP_CLIENT_H_INCLUDE_ -#define _NGX_HTTP_CLIENT_H_INCLUDE_ - -#include -#include -#include -#include "ngx_client.h" -#include "ngx_toolkit_misc.h" - - -// http client method -#define NGX_HTTP_CLIENT_GET 0 -#define NGX_HTTP_CLIENT_HEAD 1 -#define NGX_HTTP_CLIENT_POST 2 -#define NGX_HTTP_CLIENT_PUT 3 -#define NGX_HTTP_CLIENT_DELETE 4 -#define NGX_HTTP_CLIENT_MKCOL 5 -#define NGX_HTTP_CLIENT_COPY 6 -#define NGX_HTTP_CLIENT_MOVE 7 -#define NGX_HTTP_CLIENT_OPTIONS 8 -#define NGX_HTTP_CLIENT_PROPFIND 9 -#define NGX_HTTP_CLIENT_PROPPATCH 10 -#define NGX_HTTP_CLIENT_LOCK 11 -#define NGX_HTTP_CLIENT_UNLOCK 12 -#define NGX_HTTP_CLIENT_PATCH 13 -#define NGX_HTTP_CLIENT_TRACE 14 - -// http client version -#define NGX_HTTP_CLIENT_VERSION_9 0 -#define NGX_HTTP_CLIENT_VERSION_10 1 -#define NGX_HTTP_CLIENT_VERSION_11 2 -#define NGX_HTTP_CLIENT_VERSION_20 3 - -// http client opt -#define NGX_HTTP_CLIENT_OPT_CONNECT_TIMEOUT 0 -#define NGX_HTTP_CLIENT_OPT_SEND_TIMEOUT 1 -#define NGX_HTTP_CLIENT_OPT_POSTPONE_OUTPUT 2 -#define NGX_HTTP_CLIENT_OPT_DYNAMIC_RESOLVER 3 -#define NGX_HTTP_CLIENT_OPT_TCP_NODELAY 4 -#define NGX_HTTP_CLIENT_OPT_TCP_NOPUSH 5 -#define NGX_HTTP_CLIENT_OPT_HEADER_TIMEOUT 6 - - -typedef void (* ngx_http_client_handler_pt)(void *r, ngx_http_request_t *hcr); - - -/* create and set http request */ - -/* - * create a http request for sending to server - * - * return value: - * return http request for successd, return NULL for failed - * - * paras: - * log: error in create will use this log - * method: http client method - * url: full request url like "http://test.com/index.html?hello=world" - * headers: http request header for sending - * send_body: callback for sending body - * request: who send http request - */ -ngx_http_request_t *ngx_http_client_create(ngx_log_t *log, - ngx_uint_t method, ngx_str_t *url, ngx_keyval_t *headers, - ngx_http_client_handler_pt send_body, void *request); - -/* - * add cleanup as ngx_http_cleanup_add - */ -ngx_http_cleanup_t *ngx_http_client_cleanup_add(ngx_http_request_t *r, - size_t size); - -/* - * set read handler for http client, should set before send request, - * otherwise body from server will discard - * - * return value: - * void - * - * paras: - * r: http client request - * read_handler: handler for setting - */ -void ngx_http_client_set_read_handler(ngx_http_request_t *r, - ngx_http_client_handler_pt read_handler); - -/* - * set http headers - * - * return value: - * NGX_OK for successd, NGX_ERROR for failed - * - * paras: - * r: http client request - * headers: headers set into r - * if value is not null, will set or modify the header - * if value is null string, will delete the header - */ -ngx_int_t ngx_http_client_set_headers(ngx_http_request_t *r, - ngx_keyval_t *headers); - -/* - * set write handler for http client, if set, - * will use this handler for sending body, - * - * return value: - * void - * - * paras: - * r: http client request - * write_handler: handler for setting - */ -void ngx_http_client_set_write_handler(ngx_http_request_t *r, - ngx_http_client_handler_pt write_handler); - -/* - * set write handler for http client, if set, - * will use this handler for sending body, - * - * return value: - * void - * - * paras: - * r: http client request - * write_handler: handler for setting - */ -void ngx_http_client_set_version(ngx_http_request_t *r, ngx_uint_t version); - -/* - * set http client option - * - * return value: - * void - * - * paras: - * r: http client request - * opt: http client opt - * NGX_HTTP_CLIENT_OPT_CONNECT_TIMEOUT: - * connect server timer - * NGX_HTTP_CLIENT_OPT_SEND_TIMEOUT: - * send data timer when buffer full - * NGX_HTTP_CLIENT_OPT_POSTPONE_OUTPUT: - * size threshold to send - * NGX_HTTP_CLIENT_OPT_DYNAMIC_RESOLVER: - * whether use dynamic resolver to resolv domain - * NGX_HTTP_CLIENT_OPT_TCP_NODELAY: - * whether set TCP_NODELAY - * NGX_HTTP_CLIENT_OPT_TCP_NOPUSH: - * whether set TCP_CORK - * NGX_HTTP_CLIENT_OPT_HEADER_TIMEOUT: - * timer for waiting response header from server - * value: http client opt value want to set - */ -void ngx_http_client_setopt(ngx_http_request_t *r, unsigned opt, - ngx_uint_t value); - -/* send http request */ - -/* - * send http request - * - * return value: - * NGX_OK for successd, NGX_ERROR for failed - * - * paras: - * r: http request for seding, create by ngx_http_client_create - */ -ngx_int_t ngx_http_client_send(ngx_http_request_t *r); - -/* - * create and send http GET request to server - * - * return value: - * return http request for successd, return NULL for failed - * - * paras: - * log: error in create will use this log - * url: full request url like "http://test.com/index.html?hello=world" - * headers: http request header for sending - * request: who send http request - */ -ngx_http_request_t *ngx_http_client_get(ngx_log_t *log, ngx_str_t *url, - ngx_keyval_t *headers, void *request); - -/* - * create and send http HEAD request to server - * - * return value: - * return http request for successd, return NULL for failed - * - * paras: - * log: error in create will use this log - * url: full request url like "http://test.com/index.html?hello=world" - * headers: http request header for sending - * request: who send http request - */ -ngx_http_request_t *ngx_http_client_head(ngx_log_t *log, ngx_str_t *url, - ngx_keyval_t *headers, void *request); - -/* - * create and send http POST request to server - * - * return value: - * return http request for successd, return NULL for failed - * - * paras: - * log: error in create will use this log - * url: full request url like "http://test.com/index.html?hello=world" - * headers: http request header for sending - * send_body: callback for sending body - * request: who send http request - */ -ngx_http_request_t *ngx_http_client_post(ngx_log_t *log, ngx_str_t *url, - ngx_keyval_t *headers, ngx_http_client_handler_pt send_body, void *request); - - -/* get response */ - -/* - * get http response version - * - * return value: - * http response version - * - * paras: - * r: http client request - */ -ngx_uint_t ngx_http_client_http_version(ngx_http_request_t *r); - -/* - * get http response status code - * - * return value: - * http response status code like 200, 500 - * - * paras: - * r: http client request - */ -ngx_uint_t ngx_http_client_status_code(ngx_http_request_t *r); - -/* - * get http response header's value - * - * return value: - * http response header's value - * - * paras: - * r: http client request - * key: http header like "Host", "Content-Type" - */ -ngx_str_t *ngx_http_client_header_in(ngx_http_request_t *r, ngx_str_t *key); - -/* - * read http response body - * - * return value: - * NGX_AGAIN: read part of data - * 0: tcp connection disconnect, need finalize request with 1 - * NGX_ERROR: tcp connection error disconnect, need finalize request with 1 - * NGX_DONE: response body has been read, could finalize request with 0 - * - * paras: - * r: http client request - * in: where read data put - */ -ngx_int_t ngx_http_client_read_body(ngx_http_request_t *r, ngx_chain_t **in); - -/* - * get receive bytes - * - * return value: - * bytes receive from server - * - * paras: - * r: http client request - */ -off_t ngx_http_client_rbytes(ngx_http_request_t *r); - -/* - * get send bytes - * - * return value: - * bytes send to server - * - * paras: - * r: http client request - */ -off_t ngx_http_client_wbytes(ngx_http_request_t *r); - - -/* end request */ - -/* - * detach http client request with it's creator, - * all read and write handler will not be triggered - * - * return value: - * bytes send to server - * - * paras: - * r: http client request - */ -void ngx_http_client_detach(ngx_http_request_t *r); - -/* - * finalize http client request - * - * return value: - * void - * - * paras: - * r: http client request - * closed: set to 1, will close connection to server - * set to 0, will keep connection to server alive - */ -void ngx_http_client_finalize_request(ngx_http_request_t *r, ngx_flag_t closed); - -#endif diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/config b/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/config deleted file mode 100644 index 0ac5274dd2..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/config +++ /dev/null @@ -1,13 +0,0 @@ -ngx_addon_name=ngx_client_test_module - -HTTP_MODULES="$HTTP_MODULES \ - ngx_client_test_module \ - ngx_http_client_test_module \ - ngx_client_stat_module \ - " - -NGX_ADDON_SRCS="$NGX_ADDON_SRCS - $ngx_addon_dir/ngx_client_test_module.c \ - $ngx_addon_dir/ngx_http_client_test_module.c \ - $ngx_addon_dir/ngx_client_stat_module.c \ - " diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/nginx.conf b/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/nginx.conf deleted file mode 100644 index 081f0321de..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/nginx.conf +++ /dev/null @@ -1,57 +0,0 @@ - -user root; -worker_processes 4; - -#error_log logs/error.log; -#error_log logs/error.log notice; -error_log logs/error.log info; - -#pid logs/nginx.pid; - -events { - worker_connections 1024; - resolver 192.168.84.254; - dynamic_refresh_interval 5m; -} - - -http { - include mime.types; - default_type application/octet-stream; - - #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - # '$status $body_bytes_sent "$http_referer" ' - # '"$http_user_agent" "$http_x_forwarded_for"'; - - #access_log logs/access.log main; - - sendfile on; - #tcp_nopush on; - - #keepalive_timeout 0; - keepalive_timeout 65; - - #gzip on; - - server { - listen 80; - server_name localhost; - - location / { - root html; - index index.html index.htm; - } - - location /client_test { - client_test; - } - - location /http_client_test { - http_client_test; - } - - location /client_stat { - client_stat; - } - } -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/ngx_client_stat_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/ngx_client_stat_module.c deleted file mode 100644 index bdfe2d1475..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/ngx_client_stat_module.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include -#include -#include -#include -#include "ngx_client.h" -#include "ngx_rbuf.h" -#include "ngx_poold.h" -#include "ngx_timerd.h" -#include "ngx_event_timer_module.h" -#include "ngx_event_resolver.h" -#include "ngx_dynamic_resolver.h" - - -static char *ngx_client_stat(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); - - -static ngx_command_t ngx_client_stat_commands[] = { - - { ngx_string("client_stat"), - NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, - ngx_client_stat, - NGX_HTTP_LOC_CONF_OFFSET, - 0, - NULL }, - - ngx_null_command -}; - - -static ngx_http_module_t ngx_client_stat_module_ctx = { - NULL, /* preconfiguration */ - NULL, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - NULL, /* create location configuration */ - NULL /* merge location configuration */ -}; - - -ngx_module_t ngx_client_stat_module = { - NGX_MODULE_V1, - &ngx_client_stat_module_ctx, /* module context */ - ngx_client_stat_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static ngx_int_t -ngx_client_stat_handler(ngx_http_request_t *r) -{ - ngx_chain_t **ll, *out; - ngx_buf_t *b; - size_t len; - - r->headers_out.status = NGX_HTTP_OK; - ngx_http_send_header(r); - - ll = &out; - - len = sizeof("--------------------------------------------------\n") - 1 - + sizeof("ngx_worker: ngx_process_slot: pid: \n") - 1 - + 3 * NGX_OFF_T_LEN; - - *ll = ngx_alloc_chain_link(r->pool); - if (*ll == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - (*ll)->next = NULL; - - b = ngx_create_temp_buf(r->pool, len); - if (b == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - (*ll)->buf = b; - - b->last = ngx_snprintf(b->last, len, - "--------------------------------------------------\n" - "ngx_worker: %i ngx_process_slot: %i pid: %i\n", - ngx_worker, ngx_process_slot, ngx_pid); - - if (*ll) { - ll = &(*ll)->next; - } - *ll = ngx_rbuf_state(r, 1); - - if (*ll) { - ll = &(*ll)->next; - } - *ll = ngx_event_timer_state(r); - - if (*ll) { - ll = &(*ll)->next; - } - *ll = ngx_event_resolver_state(r); - - if (*ll) { - ll = &(*ll)->next; - } - *ll = ngx_dynamic_resolver_state(r); - - if (*ll) { - ll = &(*ll)->next; - } - *ll = ngx_poold_state(r, 1); - - if (*ll) { - ll = &(*ll)->next; - } - *ll = ngx_timerd_state(r, 1); - - if (*ll) { - ll = &(*ll)->next; - } - *ll = ngx_client_state(r, 1); - - (*ll)->buf->last_buf = 1; - - return ngx_http_output_filter(r, out); -} - -static char * -ngx_client_stat(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_core_loc_conf_t *clcf; - - clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); - clcf->handler = ngx_client_stat_handler; - - return NGX_CONF_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/ngx_client_test_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/ngx_client_test_module.c deleted file mode 100644 index db6c586e36..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/ngx_client_test_module.c +++ /dev/null @@ -1,188 +0,0 @@ -#include -#include -#include -#include "ngx_client.h" - - -static char *ngx_client_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); - - -static ngx_command_t ngx_client_test_commands[] = { - - { ngx_string("client_test"), - NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, - ngx_client_test, - 0, - 0, - NULL }, - - ngx_null_command -}; - - -static ngx_http_module_t ngx_client_test_module_ctx = { - NULL, /* preconfiguration */ - NULL, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - NULL, /* create location configuration */ - NULL /* merge location configuration */ -}; - - -ngx_module_t ngx_client_test_module = { - NGX_MODULE_V1, - &ngx_client_test_module_ctx, /* module context */ - ngx_client_test_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void -ngx_client_test_connected(ngx_client_session_t *s) -{ - ngx_buf_t *b; - size_t len; - ngx_chain_t out; - ngx_http_request_t *r; - ngx_event_t *wev; - - ngx_log_error(NGX_LOG_ERR, &s->log, 0, "client connected"); - - r = s->data; - wev = s->peer.connection->write; - - len = sizeof("nginx client test\n") - 1; - b = ngx_create_temp_buf(s->pool, len); - - if (b == NULL) { - ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - return; - } - - b->last = ngx_copy(b->last, "nginx client test\n", len); - b->last_buf = 1; - - out.buf = b; - out.next = NULL; - - ngx_client_write(s, &out); - - ngx_handle_write_event(wev, 0); -} - -static void -ngx_client_test_recv(ngx_client_session_t *s) -{ - ngx_buf_t *b; - ngx_int_t n; - ngx_connection_t *c; - ngx_str_t recv; - ngx_http_request_t *r; - - c = s->peer.connection; - r = s->data; - - b = ngx_create_temp_buf(s->pool, 4096); - if (b == NULL) { - ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - return; - } - - n = c->recv(c, b->pos, b->end - b->last); - if (n == NGX_AGAIN) { - ngx_log_error(NGX_LOG_ERR, &s->log, 0, "client recv NGX_AGAIN"); - return; - } - - if (n == NGX_ERROR || n == 0) { - ngx_log_error(NGX_LOG_ERR, &s->log, 0, "client recv NGX_ERROR"); - ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - ngx_client_close(s); - return; - } - - b->last += n; - - recv.data = b->pos; - recv.len = b->last - b->pos; - - ngx_log_error(NGX_LOG_ERR, &s->log, 0, "client recv %d: %V, %z", - n, &recv, recv.len); - - ngx_http_finalize_request(r, NGX_HTTP_FORBIDDEN); - ngx_client_set_keepalive(s); - return; -} - -static void -ngx_client_test_send(ngx_client_session_t *s) -{ - ngx_log_error(NGX_LOG_ERR, &s->log, 0, "client send"); -} - -static void -ngx_client_test_closed(ngx_client_session_t *s) -{ - ngx_log_error(NGX_LOG_ERR, &s->log, 0, "client closed"); -} - -static ngx_int_t -ngx_client_test_handler(ngx_http_request_t *r) -{ - ngx_client_session_t *s; - ngx_str_t echo; - - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "client test handler"); - - if (ngx_http_arg(r, (u_char *) "echo", sizeof("echo") - 1, &echo) - != NGX_OK) - { - return NGX_HTTP_BAD_REQUEST; - } - - s = ngx_client_create(&echo, NULL, 0, r->connection->log); - if (s == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - //ci->dynamic_resolver = 0; - //ci->recvbuf = 4096; - - s->client_connected = ngx_client_test_connected; - s->client_recv = ngx_client_test_recv; - s->client_send = ngx_client_test_send; - s->client_closed = ngx_client_test_closed; - s->data = r; - - ngx_client_connect(s); - - ++r->count; - - return NGX_DONE; -} - - -static char * -ngx_client_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_core_loc_conf_t *clcf; - - clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); - clcf->handler = ngx_client_test_handler; - - return NGX_CONF_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/ngx_http_client_test_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/ngx_http_client_test_module.c deleted file mode 100644 index aacef52d6a..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/ngx_http_client_test_module.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include "ngx_http_client.h" -#include "ngx_rbuf.h" - - -static char *ngx_http_client_test(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); - - -static ngx_command_t ngx_http_client_test_commands[] = { - - { ngx_string("http_client_test"), - NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, - ngx_http_client_test, - 0, - 0, - NULL }, - - ngx_null_command -}; - - -static ngx_http_module_t ngx_http_client_test_module_ctx = { - NULL, /* preconfiguration */ - NULL, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - NULL, /* create location configuration */ - NULL /* merge location configuration */ -}; - - -ngx_module_t ngx_http_client_test_module = { - NGX_MODULE_V1, - &ngx_http_client_test_module_ctx, /* module context */ - ngx_http_client_test_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void -ngx_http_client_test_recv_body(void *request, ngx_http_request_t *hcr) -{ - ngx_http_request_t *r; - ngx_chain_t *cl = NULL; - ngx_chain_t **ll; - ngx_int_t rc; - - r = request; - - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "http client test recv body"); - - rc = ngx_http_client_read_body(hcr, &cl); - - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "http client test recv body, rc %i %i, %O", - rc, ngx_errno, ngx_http_client_rbytes(hcr)); - - if (rc == 0) { - goto done; - } - - if (rc == NGX_ERROR) { - goto done; - } - - if (rc == NGX_DONE) { - for (ll = &cl; (*ll)->next; ll = &(*ll)->next); - - (*ll)->buf->last_buf = 1; - } - - ngx_http_output_filter(r, cl); - - ngx_http_run_posted_requests(r->connection); - - if (rc == NGX_AGAIN) { - return; - } - - if (rc == NGX_DONE) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "all body has been read"); - ngx_http_client_finalize_request(hcr, 0); - } - -done: - ngx_http_finalize_request(r, NGX_OK); -} - -static void -ngx_http_client_test_recv(void *request, ngx_http_request_t *hcr) -{ - ngx_http_request_t *r; - static ngx_str_t content_type = ngx_string("Content-Type"); - static ngx_str_t connection = ngx_string("Connection"); - static ngx_str_t unknown = ngx_string("Unknown"); - ngx_str_t *ct, *con; - - r = request; - - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "http client test recv, connection: %p", hcr->connection); - - r->headers_out.status = 200; - - ngx_http_client_set_read_handler(hcr, ngx_http_client_test_recv_body); - - ngx_http_send_header(r); - - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "status_code: %ui http_version: %ui", - ngx_http_client_status_code(hcr), - ngx_http_client_http_version(hcr)); - - ct = ngx_http_client_header_in(hcr, &content_type); - con = ngx_http_client_header_in(hcr, &connection); - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "Content-Type: %V", ct); - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "Connection: %V", con); - - if (ngx_http_client_header_in(hcr, &unknown) == NULL) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "no header Unknown"); - } - - ngx_http_client_test_recv_body(request, hcr); -} - - -static ngx_int_t -ngx_http_client_test_handler(ngx_http_request_t *r) -{ - ngx_http_request_t *hcr; - static ngx_str_t request_url = ngx_string("http://101.200.241.232/"); - - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "http client test handler"); - - // Default header Host, User-Agent, Connection(below HTTP/1.1), Accept, Date - hcr = ngx_http_client_create(r->connection->log, NGX_HTTP_CLIENT_GET, - &request_url, NULL, NULL, r); - - // add Connection, delete Date, Modify Host, add new header - ngx_str_t value; - - value.data = (u_char *) "World"; - value.len = sizeof("World") - 1; - - ngx_keyval_t headers[] = { - { ngx_string("Host"), ngx_string("www.test.com") }, - { ngx_string("Connection"), ngx_string("upgrade") }, - { ngx_string("Date"), ngx_null_string }, - { ngx_string("Hello"), value }, - { ngx_null_string, ngx_null_string } // must end with null str - }; - ngx_http_client_set_headers(hcr, headers); - - ngx_http_client_set_read_handler(hcr, ngx_http_client_test_recv); - - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "http client test before send"); - - ngx_http_client_send(hcr); - - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "http client test after send"); - -// ngx_http_client_detach(hcr); -// return NGX_HTTP_FORBIDDEN; - - ++r->count; - - return NGX_DONE; -} - - -static char * -ngx_http_client_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_core_loc_conf_t *clcf; - - clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); - clcf->handler = ngx_http_client_test_handler; - - return NGX_CONF_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/tcpserver.go b/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/tcpserver.go deleted file mode 100644 index 2ed5d2d9ee..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/tcpserver.go +++ /dev/null @@ -1,41 +0,0 @@ -package main - -import ( - "fmt" - "net" -) - -func handleConnection(c net.Conn) { - b := make([]byte, 4096) - - for { - n, err := c.Read(b) - if err != nil { - fmt.Print("Read Error ", err) - c.Close() - return - } - - fmt.Print("recv ", n, " data:", string(b)) - - c.Write(b[0:n]) - } -} - -func main() { - ln, err := net.Listen("tcp", ":10000") - if err != nil { - fmt.Print("Listen Error ", err) - return - } - - for { - conn, err := ln.Accept() - if err != nil { - fmt.Print("Accept Error ", err) - continue - } - - go handleConnection(conn) - } -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/COPYRIGHT b/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/COPYRIGHT deleted file mode 100644 index 837a6682d6..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/COPYRIGHT +++ /dev/null @@ -1,24 +0,0 @@ -Copyright (C) 2016-2020, by Jie Wu "AlexWoo" . -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -SUCH DAMAGE. - diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/README.md b/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/README.md deleted file mode 100644 index 6e16a909ec..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/README.md +++ /dev/null @@ -1,181 +0,0 @@ -# Module nginx-multiport-module ---- -## Instructions - -Every worker process can bind own port, user can visit specific worker process by using the port. - -- [ngx-stream-zone-module](doc/ngx-stream-zone-module.md) - - Record stream's owner worker process slot - -- [ngx-http-broadcast-module](doc/ngx-http-broadcast-module.md) - - Broadcast HTTP request to all worker processes when receive HTTP request - -## Directives - -### multi\_listen - - Syntax : multi_listen multiport relationport; - Default : None; - Context : events - -multiport can configured as below: - - address:port - port - unix:path - -when configured with IPv4 or IPv6 port, worker process listen port plus with worker process's slot. For Example, we start four workers, add configured multiport with 9000. worker 0 will listen 9000, worker 1 will listen 9001, worker 2 will listen 9002, worker 3 will listen 9003 - -when configured with unix path, worker will listen path plus with suffix of worker process's slot. For Example, we start four workers, add configured multiport with unix:/tmp/http. worker 0 will listen /tmp/http.0, worker 1 will listen /tmp/http.1, worker 2 will listen /tmp/http.2, worker 3 will listen /tmp/http.3 - - -relationport must configured same as listen directives in http server, rtmp server, stream server or other server - -### inner\_proxy - - Syntax : inner_proxy multiport uri; - Default : None; - Context : http, server, location - -- multiport: configured in multi_listen -- uri: uri for inner_proxy, configured as below - - location /multiport_test/ { - inner_proxy unix:/tmp/http.sock.80 /inner_proxy; - multiport_test; - } - - location /inner_proxy/ { - rewrite ^/inner_proxy/(.*):/(.*) /$2 break; - proxy_pass http://$1:; - } - - As example above, if send subrequest to process whose workerid is 0, the uri will change to /inner_proxy/unix:/tmp/http.sock.80.0:/multiport_test/xxx - - proxy_pass will send current request to process 0 as inner proxy request. - -## API - -- ngx\_multiport\_get\_port - - ngx_int_t ngx_event_multiport_get_port(ngx_pool_t *pool, ngx_str_t *port, ngx_str_t *multiport, ngx_int_t pslot); - - - para: - - pool: pool for port memory alloc - port: process real listen port while process\_slot is pslot - multiport: port configure for processes, format as below: - - port only: port - IPv4: host:port host must be ipaddr of IPv4 or * - IPv6: [host]:port host must be ipaddr of IPv6 - Unix: unix:/path - - pslot: process\_slot, process\_slot of other worker process can get through ngx\_process\_slot\_get\_slot - - - return value: - - NGX\_OK for successd, NGX\_ERROR for failed - -- ngx\_multiport\_get\_slot - - ngx_int_t ngx_multiport_get_slot(ngx_uint_t wpid); - - - para: - - wpid: worker process id, 0 to ccf->worker_processes - 1 - - - return value: - - ngx_process_slot for successd, NGX_ERROR for failed - -- ngx\_http\_inner\_proxy\_request - - ngx_int_t ngx_http_inner_proxy_request(ngx_http_request_t *r, ngx_int_t pslot); - - send a inner proxy request to specific process, must use with directives inner\_proxy - - - paras: - - - r: http request for send inner request to sibling worker - - pslot: sibling worker ngx_process_slot - - - return values: - - - NGX_OK: for successd - - NGX_ERROR: for failed - - NGX_DECLINED: for not configured or send inner proxy to self - -## Build - -cd to NGINX source directory & run this: - - ./configure --add-module=/path/to/nginx-multiport-module/ - make && make install - -## Example - -See t/ngx\_http\_process\_slot\_test\_module.c as reference - -**Build**: - - ./configure --with-debug --with-ipv6 --add-module=/path/to/nginx-multiport-module/t/ --add-module=/path/to/nginx-multiport-module/ --add-module=/path/to/echo-nginx-module/ - - make && make install - -**Configure**: - - worker_processes 4; - - events { - ... - - multi_listen 9000 80; - multi_listen unix:/tmp/http.sock.80 80; - } - - http { - ... - - server { - ... - - location /multiport_test/ { - inner_proxy unix:/tmp/http.sock.80 /inner_proxy; - multiport_test; - } - - location /inner_proxy/ { - rewrite ^/inner_proxy/(.*):/(.*) /$2 break; - proxy_pass http://$1:; - } - } - } - -**Test for API**: - - $ curl http://192.168.84.254/multiport_test/123 - TEST cases 19, 19 pass - -If request send to worker1 to worker3, the request will proxy to worker 0. will get log as below: - - 2017/10/14 20:45:44 [error] 20065#0: *6 multiport test handler, client: 192.168.84.1, server: localhost, request: "GET /multiport_test/123 HTTP/1.1", host: "192.168.84.254:9003" - 2017/10/14 20:45:44 [error] 20065#0: *6 inner proxy return 0, client: 192.168.84.1, server: localhost, request: "GET /multiport_test/123 HTTP/1.1", host: "192.168.84.254:9003" - 2017/10/14 20:45:44 [error] 20062#0: *8 multiport test handler, client: unix:, server: localhost, request: "GET //multiport_test/123 HTTP/1.0", host: "localhost" - -**Test for multiport**: - - curl -v http://127.0.0.1/ - curl -v http://127.0.0.1:9000/ - curl -v http://127.0.0.1:9001/ - curl -v http://127.0.0.1:9002/ - curl -v http://127.0.0.1:9003/ - - curl -v --unix-socket /tmp/http.sock.80.0 http:/ - curl -v --unix-socket /tmp/http.sock.80.1 http:/ - curl -v --unix-socket /tmp/http.sock.80.2 http:/ - curl -v --unix-socket /tmp/http.sock.80.3 http:/ - -Tests will get the same result, for port 9000 will always send to worker process 0, 9001 to worker process 1 and so on diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/config b/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/config deleted file mode 100644 index 36313b330e..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/config +++ /dev/null @@ -1,31 +0,0 @@ -ngx_addon_name=ngx_multiport_module - -EVENT_MODULES="$EVENT_MODULES \ - ngx_event_multiport_module \ - " - -CORE_MODULES="$CORE_MODULES \ - ngx_process_slot_module \ - ngx_stream_zone_module \ - " - -HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES \ - ngx_http_broadcast_module \ - ngx_http_inner_proxy_module \ - " - -NGX_ADDON_SRCS="$NGX_ADDON_SRCS \ - $ngx_addon_dir/ngx_multiport_misc.c \ - $ngx_addon_dir/ngx_event_multiport_module.c \ - $ngx_addon_dir/ngx_process_slot_module.c \ - $ngx_addon_dir/ngx_stream_zone_module.c \ - $ngx_addon_dir/ngx_http_broadcast_module.c \ - $ngx_addon_dir/ngx_http_inner_proxy_module.c \ - " - -NGX_ADDON_DEPS="$NGX_ADDON_DEPS \ - $ngx_addon_dir/ngx_multiport.h \ - $ngx_addon_dir/ngx_stream_zone_module.h \ - " - -CFLAGS="$CFLAGS -I $ngx_addon_dir" diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/doc/ngx-http-broadcast-module.md b/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/doc/ngx-http-broadcast-module.md deleted file mode 100644 index 1c86a5bc95..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/doc/ngx-http-broadcast-module.md +++ /dev/null @@ -1,77 +0,0 @@ -# ngx-http-broadcast-module ---- -## Instructions - -Broadcast HTTP request to all worker processes when receive HTTP request - -## Directives - -### broadcast - - Syntax : broadcast multiport uri; - Default : None; - Context : location - -- multiport is multi_listen port configured in event -- uri is http proxy_pass uri configured as below - - - location /auth_proxy/ { - rewrite ^/auth_proxy/(.*) /auth break; - proxy_pass http://$1:; - } - - -## Build - -cd to NGINX source directory & run this: - - ./configure --add-module=/path/to/nginx-multiport-module/ - make && make install - -## Example - -**Build**: - - ./configure --with-debug --with-ipv6 --add-module=/path/to/nginx-multiport-module/t/ --add-module=/path/to/nginx-multiport-module/ --add-module=/path/to/echo-nginx-module/ - make && make install - -**Configure**: - - events { - ... - multi_listen unix:/tmp/http.sock.80 80; - } - - - http { - ... - - server { - listen 80; - server_name localhost; - - ... - - location / { - broadcast unix:/tmp/http.sock.80 /auth_proxy; - } - - location /auth_proxy/ { - rewrite ^/auth_proxy/(.*) /auth break; - proxy_pass http://$1:; - } - - location /auth { - # return 403; - echo "auth"; - echo $scheme://$host$uri?$args; - } - } - } - -**Test**: - - curl -v 'http://192.168.84.254/aa?a=b&c=d' - -curl will get all response content if worker not return non 200 response \ No newline at end of file diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/doc/ngx-stream-zone-module.md b/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/doc/ngx-stream-zone-module.md deleted file mode 100644 index 9864558bc2..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/doc/ngx-stream-zone-module.md +++ /dev/null @@ -1,92 +0,0 @@ -# ngx-stream-zone-module ---- -## Instructions - -Record stream's owner worker process slot - -## Directives - -### stream\_zone - - Syntax : stream_zone buckets=$nbuckets streams=$nstreams; - Default : None; - Context : main - -nbuckets is hash buckect number, nstreams is max streams system can store - -nbuckets is recommended use a prime number - -## API - -**header file** - -For using this API, You should include the header file as below: - - #include "ngx_stream_zone_module.h" - -**ngx\_stream\_zone\_insert\_stream** - - ngx_int_t ngx_stream_zone_insert_stream(ngx_str_t *name); - -- para: - - name: stream name - -- return value: - - process\_slot for owner of stream, NGX\_ERROR for error - -**ngx\_stream\_zone\_delete\_stream** - - void ngx_stream_zone_delete_stream(ngx_str_t *name); - -- para: - - name: stream name - -**ngx\_stream\_zone\_state** - - ngx_chain_t *ngx_stream_zone_state(ngx_http_request_t *r, ngx_flag_t detail); - -- para: - - - r: http request to query status of rbuf - - detail: print stream detail in log - -- return value: - - chain of stream zone state for returning to http client - -## Build - -cd to NGINX source directory & run this: - - ./configure --add-module=/path/to/nginx-multiport-module/ - make && make install - -## Example - -See t/ngx\_stream\_zone\_test\_module.c as reference - -**Build**: - - ./configure --with-debug --with-ipv6 --add-module=/path/to/nginx-multiport-module/t/ --add-module=/path/to/nginx-multiport-module/ - make && make install - -**Configure**: - - stream_zone buckets=10007 streams=10000; - -**Test**: - - curl -XPOST -v "http://127.0.0.1:9001/stream_zone_test/ab?stream=test" - curl -XPOST -v "http://127.0.0.1:9002/stream_zone_test/ab?stream=test1" - curl -XPOST -v "http://127.0.0.1:9003/stream_zone_test/ab?stream=test2" - - curl -XPOST -v "http://127.0.0.1:9003/stream_zone_test/ab?stream=test" - - curl -XDELETE -v "http://127.0.0.1:9000/stream_zone_test/ab?stream=test3" - curl -XDELETE -v "http://127.0.0.1:9002/stream_zone_test/ab?stream=test1" - curl -XDELETE -v "http://127.0.0.1:9001/stream_zone_test/ab?stream=test2" - - curl -XGET -v "http://127.0.0.1:9001/stream_zone_test/ab" \ No newline at end of file diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_event_multiport_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_event_multiport_module.c deleted file mode 100644 index 0c0e10afde..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_event_multiport_module.c +++ /dev/null @@ -1,1018 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include -#include -#include -#include "ngx_multiport.h" - - -static ngx_int_t ngx_event_multiport_process_init(ngx_cycle_t *cycle); -static void ngx_event_multiport_process_exit(ngx_cycle_t *cycle); - -static void *ngx_event_multiport_create_conf(ngx_cycle_t *cycle); -static char *ngx_event_multiport_init_conf(ngx_cycle_t *cycle, void *conf); - -static char *ngx_event_multiport_listen(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); - - -//multiport_listen listenparas relationport -typedef struct { - ngx_str_t multiport; - ngx_str_t relatedport; - ngx_listening_t listening; -} ngx_event_multiport_listen_t; - -typedef struct { - ngx_array_t *ports; /* array of ngx_event_multiport_listen_t */ -} ngx_event_multiport_conf_t; - - -static ngx_str_t event_multiport_name = ngx_string("event_multiport"); - - -static ngx_command_t ngx_event_multiport_commands[] = { - - { ngx_string("multi_listen"), - NGX_EVENT_CONF|NGX_CONF_TAKE2, - ngx_event_multiport_listen, - 0, - 0, - NULL }, - - ngx_null_command -}; - - -ngx_event_module_t ngx_event_multiport_module_ctx = { - &event_multiport_name, - ngx_event_multiport_create_conf, /* create configuration */ - ngx_event_multiport_init_conf, /* init configuration */ - - { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } -}; - - -/* this module use ngx_cycle->log */ -ngx_module_t ngx_event_multiport_module = { - NGX_MODULE_V1, - &ngx_event_multiport_module_ctx, /* module context */ - ngx_event_multiport_commands, /* module directives */ - NGX_EVENT_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - ngx_event_multiport_process_init, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - ngx_event_multiport_process_exit, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void * -ngx_event_multiport_create_conf(ngx_cycle_t *cycle) -{ - ngx_event_multiport_conf_t *conf; - - conf = ngx_pcalloc(cycle->pool, sizeof(ngx_event_multiport_conf_t)); - if (conf == NULL) { - return NULL; - } - - return conf; -} - -static char * -ngx_event_multiport_init_conf(ngx_cycle_t *cycle, void *conf) -{ - return NGX_CONF_OK; -} - -static char * -ngx_event_multiport_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_event_multiport_conf_t *emcf = conf; - - ngx_str_t *value; - ngx_event_multiport_listen_t *mls; - ngx_url_t u; - - value = cf->args->elts; - - ngx_memzero(&u, sizeof(ngx_url_t)); - - /* check listen base port */ - u.url = value[1]; - u.listen = 1; - u.default_port = 0; - - if (ngx_parse_url(cf->temp_pool, &u) != NGX_OK) { - if (u.err) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "%s in \"%V\" of the \"multi_listen" - " baseport\" directive", - u.err, &u.url); - } - - return NGX_CONF_ERROR; - } - - ngx_memzero(&u, sizeof(ngx_url_t)); - - /* check relation port */ - u.url = value[2]; - u.listen = 1; - u.default_port = 0; - - if (ngx_parse_url(cf->temp_pool, &u) != NGX_OK) { - if (u.err) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "%s in \"%V\" of the \"multi_listen" - " relationport\" directive", - u.err, &u.url); - } - - return NGX_CONF_ERROR; - } - - if (emcf->ports == NULL) { - emcf->ports = ngx_array_create(cf->pool, 4, - sizeof(ngx_event_multiport_listen_t)); - if (emcf->ports == NULL) { - return NGX_CONF_ERROR; - } - } - - mls = ngx_array_push(emcf->ports); - if (mls == NULL) { - return NGX_CONF_ERROR; - } - mls->multiport = value[1]; - mls->relatedport = value[2]; - - return NGX_CONF_OK; -} - - -static ngx_int_t -ngx_event_multiport_init_listening(ngx_cycle_t *cycle, ngx_listening_t *ls, - void *sockaddr, socklen_t socklen, ngx_listening_t *cls) -{ - size_t len; - struct sockaddr *sa; - u_char text[NGX_SOCKADDR_STRLEN]; - - ngx_memzero(ls, sizeof(ngx_listening_t)); - - sa = ngx_palloc(cycle->pool, socklen); - if (sa == NULL) { - return NGX_ERROR; - } - - ngx_memcpy(sa, sockaddr, socklen); - - ls->sockaddr = sa; - ls->socklen = socklen; - - len = ngx_sock_ntop(sa, socklen, text, NGX_SOCKADDR_STRLEN, 1); - ls->addr_text.len = len; - - switch (ls->sockaddr->sa_family) { -#if (NGX_HAVE_INET6) - case AF_INET6: - ls->addr_text_max_len = NGX_INET6_ADDRSTRLEN; - break; -#endif -#if (NGX_HAVE_UNIX_DOMAIN) - case AF_UNIX: - ls->addr_text_max_len = NGX_UNIX_ADDRSTRLEN; - len++; - break; -#endif - case AF_INET: - ls->addr_text_max_len = NGX_INET_ADDRSTRLEN; - break; - default: - ls->addr_text_max_len = NGX_SOCKADDR_STRLEN; - break; - } - - ls->addr_text.data = ngx_pnalloc(cycle->pool, len); - if (ls->addr_text.data == NULL) { - return NGX_ERROR; - } - - ngx_memcpy(ls->addr_text.data, text, len); - -#if (NGX_HAVE_UNIX_DOMAIN) - if (ls->sockaddr->sa_family == AF_UNIX) { - u_char *name = ls->addr_text.data + sizeof("unix:") - 1; - ngx_delete_file(name); - } -#endif - - ls->fd = (ngx_socket_t) -1; - ls->type = SOCK_STREAM; - - ls->backlog = cls->backlog; - ls->rcvbuf = cls->rcvbuf; - ls->sndbuf = cls->sndbuf; - -#if (NGX_HAVE_KEEPALIVE_TUNABLE) - ls->keepidle = cls->keepidle; - ls->keepintvl = cls->keepintvl; - ls->keepcnt = cls->keepcnt; -#endif - - ls->addr_ntop = cls->addr_ntop; - ls->handler = cls->handler; - ls->servers = cls->servers; - ls->worker = ngx_worker; - - ls->log= cls->log; - ls->logp = cls->logp; - - ls->pool_size = cls->pool_size; - ls->post_accept_buffer_size = cls->post_accept_buffer_size; - ls->post_accept_timeout = cls->post_accept_timeout; - -#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) - ls->ipv6only = cls->ipv6only; -#endif - - ls->keepalive = cls->keepalive; - -#if (NGX_HAVE_DEFERRED_ACCEPT) - ls->deferred_accept = cls->deferred_accept; - ls->delete_deferred = cls->delete_deferred; - ls->add_deferred = cls->add_deferred; -#endif - -#ifdef SO_ACCEPTFILTER - ls->accept_filter = cls->accept_filter; -#endif - -#if (NGX_HAVE_SETFIB) - ls->setfib = cls->setfib; -#endif - -#if (NGX_HAVE_TCP_FASTOPEN) - ls->fastopen = cls->fastopen; -#endif - - return NGX_OK; -} - -static ngx_int_t -ngx_event_multiport_open_listening_sock(ngx_cycle_t *cycle, ngx_listening_t *ls) -{ - int reuseaddr; - ngx_uint_t tries, failed; - ngx_err_t err; - ngx_log_t *log; - ngx_socket_t s; - - reuseaddr = 1; -#if (NGX_SUPPRESS_WARN) - failed = 0; -#endif - - log = cycle->log; - - /* TODO: configurable try number */ - - for (tries = 5; tries; tries--) { - failed = 0; - - if (ls->fd != (ngx_socket_t) -1) { - return NGX_OK; - } - - s = ngx_socket(ls->sockaddr->sa_family, ls->type, 0); - - if (s == (ngx_socket_t) -1) { - ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, - "multiport, " ngx_socket_n " %V failed", - &ls->addr_text); - return NGX_ERROR; - } - - if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, - (const void *) &reuseaddr, sizeof(int)) - == -1) - { - ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, - "multiport, setsockopt(SO_REUSEADDR) %V failed", - &ls->addr_text); - - if (ngx_close_socket(s) == -1) { - ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, - "multiport, " ngx_close_socket_n " %V failed", - &ls->addr_text); - } - - return NGX_ERROR; - } - -#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) - - if (ls->sockaddr->sa_family == AF_INET6) { - int ipv6only; - - ipv6only = ls->ipv6only; - - if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, - (const void *) &ipv6only, sizeof(int)) - == -1) - { - ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, - "multiport, setsockopt(IPV6_V6ONLY) %V failed," - " ignored", &ls->addr_text); - } - } -#endif - /* TODO: close on exit */ - - if (!(ngx_event_flags & NGX_USE_IOCP_EVENT)) { - if (ngx_nonblocking(s) == -1) { - ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, - "multiport, " ngx_nonblocking_n " %V failed", - &ls->addr_text); - - if (ngx_close_socket(s) == -1) { - ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, - "multiport, " ngx_close_socket_n " %V failed", - &ls->addr_text); - } - - return NGX_ERROR; - } - } - - ngx_log_debug2(NGX_LOG_DEBUG_CORE, log, 0, - "multiport, bind() %V #%d ", &ls->addr_text, s); - - if (bind(s, ls->sockaddr, ls->socklen) == -1) { - ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, - "multiport, bind() to %V failed", &ls->addr_text); - - if (ngx_close_socket(s) == -1) { - ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, - "multiport, " ngx_close_socket_n " %V failed", - &ls->addr_text); - } - - return NGX_ERROR; - } - -#if (NGX_HAVE_UNIX_DOMAIN) - - if (ls->sockaddr->sa_family == AF_UNIX) { - mode_t mode; - u_char *name; - - name = ls->addr_text.data + sizeof("unix:") - 1; - mode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); - - if (chmod((char *) name, mode) == -1) { - ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, - "multiport, chmod() \"%s\" failed", name); - } - } -#endif - - if (ls->type != SOCK_STREAM) { - ls->fd = s; - continue; - } - - if (listen(s, ls->backlog) == -1) { - err = ngx_socket_errno; - - /* - * on OpenVZ after suspend/resume EADDRINUSE - * may be returned by listen() instead of bind(), see - * https://bugzilla.openvz.org/show_bug.cgi?id=2470 - */ - - if (ngx_close_socket(s) == -1) { - ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, - "multiport, " ngx_close_socket_n " %V failed", - &ls->addr_text); - } - - if (err != NGX_EADDRINUSE) { - ngx_log_error(NGX_LOG_EMERG, log, err, - "multiport, listen() to %V, backlog %d failed", - &ls->addr_text, ls->backlog); - return NGX_ERROR; - } - - failed = 1; - } - - ls->listen = 1; - ls->fd = s; - - if (!failed) { - break; - } - - /* TODO: delay configurable */ - - ngx_log_error(NGX_LOG_NOTICE, log, 0, - "multiport, try again to bind() after 500ms"); - - ngx_msleep(500); - } - - if (failed) { - ngx_log_error(NGX_LOG_EMERG, log, 0, - "multiport, still could not bind()"); - return NGX_ERROR; - } - - return NGX_OK; -} - -static ngx_int_t -ngx_event_multiport_configure_listening_socket(ngx_cycle_t *cycle, - ngx_listening_t *ls) -{ - int value; - -#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) - struct accept_filter_arg af; -#endif - - ls->log = *ls->logp; - - if (ls->rcvbuf != -1) { - if (setsockopt(ls->fd, SOL_SOCKET, SO_RCVBUF, - (const void *) &ls->rcvbuf, sizeof(int)) - == -1) - { - ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, - "multiport, setsockopt(SO_RCVBUF, %d) %V failed," - " ignored", ls->rcvbuf, &ls->addr_text); - } - } - - if (ls->sndbuf != -1) { - if (setsockopt(ls->fd, SOL_SOCKET, SO_SNDBUF, - (const void *) &ls->sndbuf, sizeof(int)) - == -1) - { - ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, - "multiport, setsockopt(SO_SNDBUF, %d) %V failed," - " ignored", ls->sndbuf, &ls->addr_text); - } - } - - if (ls->keepalive) { - value = (ls->keepalive == 1) ? 1 : 0; - - if (setsockopt(ls->fd, SOL_SOCKET, SO_KEEPALIVE, - (const void *) &value, sizeof(int)) - == -1) - { - ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, - "multiport, setsockopt(SO_KEEPALIVE, %d) %V failed," - " ignored", value, &ls->addr_text); - } - } - -#if (NGX_HAVE_KEEPALIVE_TUNABLE) - - if (ls->keepidle) { - value = ls->keepidle; - -#if (NGX_KEEPALIVE_FACTOR) - value *= NGX_KEEPALIVE_FACTOR; -#endif - - if (setsockopt(ls->fd, IPPROTO_TCP, TCP_KEEPIDLE, - (const void *) &value, sizeof(int)) - == -1) - { - ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, - "multiport, setsockopt(TCP_KEEPIDLE, %d) %V failed," - " ignored", value, &ls->addr_text); - } - } - - if (ls->keepintvl) { - value = ls->keepintvl; - -#if (NGX_KEEPALIVE_FACTOR) - value *= NGX_KEEPALIVE_FACTOR; -#endif - - if (setsockopt(ls->fd, IPPROTO_TCP, TCP_KEEPINTVL, - (const void *) &value, sizeof(int)) - == -1) - { - ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, - "multiport, setsockopt(TCP_KEEPINTVL, %d) %V failed," - " ignored", value, &ls->addr_text); - } - } - - if (ls->keepcnt) { - if (setsockopt(ls->fd, IPPROTO_TCP, TCP_KEEPCNT, - (const void *) &ls->keepcnt, sizeof(int)) - == -1) - { - ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, - "multiport, setsockopt(TCP_KEEPCNT, %d) %V failed," - " ignored", ls->keepcnt, &ls->addr_text); - } - } - -#endif - -#if (NGX_HAVE_SETFIB) - if (ls->setfib != -1) { - if (setsockopt(ls->fd, SOL_SOCKET, SO_SETFIB, - (const void *) &ls->setfib, sizeof(int)) - == -1) - { - ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, - "multiport, setsockopt(SO_SETFIB, %d) %V failed," - " ignored", ls->setfib, &ls->addr_text); - } - } -#endif - -#if (NGX_HAVE_TCP_FASTOPEN) - if (ls->fastopen != -1) { - if (setsockopt(ls->fd, IPPROTO_TCP, TCP_FASTOPEN, - (const void *) &ls->fastopen, sizeof(int)) - == -1) - { - ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, - "multiport, setsockopt(TCP_FASTOPEN, %d) %V failed," - " ignored", ls->fastopen, &ls->addr_text); - } - } -#endif - - if (ls->listen) { - - /* change backlog via listen() */ - - if (listen(ls->fd, ls->backlog) == -1) { - ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, - "multiport, listen() to %V, backlog %d failed", - &ls->addr_text, ls->backlog); - return NGX_ERROR; - } - } - - /* - * setting deferred mode should be last operation on socket, - * because code may prematurely continue cycle on failure - */ - -#if (NGX_HAVE_DEFERRED_ACCEPT) - -#ifdef SO_ACCEPTFILTER - - if (ls->delete_deferred) { - if (setsockopt(ls->fd, SOL_SOCKET, SO_ACCEPTFILTER, NULL, 0) - == -1) - { - ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, - "multiport, setsockopt(SO_ACCEPTFILTER, NULL) " - "for %V failed, ignored", &ls->addr_text); - - if (ls->accept_filter) { - ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, - "multiport, could not change the accept filter " - "to \"%s\" for %V, ignored", - ls->accept_filter, &ls->addr_text); - } - - continue; - } - - ls->deferred_accept = 0; - } - - if (ls->add_deferred) { - ngx_memzero(&af, sizeof(struct accept_filter_arg)); - (void) ngx_cpystrn((u_char *) af.af_name, - (u_char *) ls->accept_filter, 16); - - if (setsockopt(ls->fd, SOL_SOCKET, SO_ACCEPTFILTER, - &af, sizeof(struct accept_filter_arg)) - == -1) - { - ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, - "multiport, setsockopt(SO_ACCEPTFILTER, \"%s\") " - "for %V failed, ignored", - ls->accept_filter, &ls->addr_text); - continue; - } - - ls->deferred_accept = 1; - } - -#endif - -#ifdef TCP_DEFER_ACCEPT - - if (ls->add_deferred || ls->delete_deferred) { - - if (ls->add_deferred) { - /* - * There is no way to find out how long a connection was - * in queue (and a connection may bypass deferred queue at all - * if syncookies were used), hence we use 1 second timeout - * here. - */ - value = 1; - - } else { - value = 0; - } - - if (setsockopt(ls->fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, - &value, sizeof(int)) - == -1) - { - ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, - "multiport, setsockopt(TCP_DEFER_ACCEPT, %d)" - " for %V failed, ignored", value, &ls->addr_text); - - return NGX_ERROR; - } - } - - if (ls->add_deferred) { - ls->deferred_accept = 1; - } - -#endif - -#endif /* NGX_HAVE_DEFERRED_ACCEPT */ - -#if (NGX_HAVE_IP_RECVDSTADDR) - - if (ls->wildcard - && ls->type == SOCK_DGRAM - && ls->sockaddr->sa_family == AF_INET) - { - value = 1; - - if (setsockopt(ls->fd, IPPROTO_IP, IP_RECVDSTADDR, - (const void *) &value, sizeof(int)) - == -1) - { - ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, - "multiport, setsockopt(IP_RECVDSTADDR) " - "for %V failed, ignored", &ls->addr_text); - } - } - -#elif (NGX_HAVE_IP_PKTINFO) - - if (ls->wildcard - && ls->type == SOCK_DGRAM - && ls->sockaddr->sa_family == AF_INET) - { - value = 1; - - if (setsockopt(ls->fd, IPPROTO_IP, IP_PKTINFO, - (const void *) &value, sizeof(int)) - == -1) - { - ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, - "multiport, setsockopt(IP_PKTINFO) " - "for %V failed, ignored", &ls->addr_text); - } - } - -#endif - -#if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO) - - if (ls->wildcard - && ls->type == SOCK_DGRAM - && ls->sockaddr->sa_family == AF_INET6) - { - value = 1; - - if (setsockopt(ls->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, - (const void *) &value, sizeof(int)) - == -1) - { - ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, - "multiport, setsockopt(IPV6_RECVPKTINFO) " - "for %V failed, ignored", &ls->addr_text); - } - } - -#endif - - return NGX_OK; -} - -static void -ngx_event_multiport_close_listening_sock(ngx_cycle_t *cycle, - ngx_listening_t *ls) -{ - ngx_connection_t *c; - - c = ls->connection; - - if (c) { - if (c->read->active) { - if (ngx_event_flags & NGX_USE_EPOLL_EVENT) { - - /* - * it seems that Linux-2.6.x OpenVZ sends events - * for closed shared listening sockets unless - * the events was explicitly deleted - */ - - ngx_del_event(c->read, NGX_READ_EVENT, 0); - - } else { - ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT); - } - } - - ngx_free_connection(c); - - c->fd = (ngx_socket_t) -1; - } - - ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0, - "multiport, close listening %V #%d", &ls->addr_text, ls->fd); - - if (ngx_close_socket(ls->fd) == -1) { - ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, - "multiport, ", ngx_close_socket_n " %V failed", - &ls->addr_text); - } - -#if (NGX_HAVE_UNIX_DOMAIN) - - if (ls->sockaddr->sa_family == AF_UNIX - && ngx_process == NGX_PROCESS_WORKER) - { - u_char *name = ls->addr_text.data + sizeof("unix:") - 1; - - if (ngx_delete_file(name) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, - "multiport, " ngx_delete_file_n " %s failed", name); - } - } - -#endif - - ls->fd = (ngx_socket_t) -1; -} - -static ngx_listening_t * -ngx_event_multiport_find_relation_port(ngx_cycle_t *cycle, ngx_str_t *str) -{ - ngx_url_t u; - ngx_listening_t *ls; - ngx_uint_t i; - - ngx_memzero(&u, sizeof(ngx_url_t)); - - u.url = *str; - u.listen = 1; - u.default_port = 0; - - if (ngx_parse_url(cycle->pool, &u) != NGX_OK) { - if (u.err) { - ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, - "multiport, relation port err: %V", str); - } - - return NULL; - } - - ls = cycle->listening.elts; - - for (i = 0; i < cycle->listening.nelts; ++i) { - - if (ls[i].socklen == u.socklen - && ngx_memcmp(ls[i].sockaddr, &u.sockaddr, u.socklen) == 0) - { - return &ls[i]; - } - } - - ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, - "multiport, can not find relation port: %V", str); - return NULL; -} - -static ngx_int_t -ngx_event_multiport_set_port(ngx_cycle_t *cycle, - ngx_event_multiport_listen_t *mls, ngx_listening_t *ls) -{ - ngx_str_t port; - ngx_int_t rc; - ngx_url_t u; - - ngx_memzero(&port, sizeof(ngx_str_t)); - - rc = ngx_multiport_get_port(cycle->pool, &port, &mls->multiport, - ngx_process_slot); - if (rc == NGX_ERROR) { - ngx_log_error(NGX_LOG_ERR, cycle->log, 0, - "multiport, get multiport error"); - return NGX_ERROR; - } - - ngx_memzero(&u, sizeof(ngx_url_t)); - u.url = port; - u.listen = 1; - u.default_port = 0; - - if (ngx_parse_url(cycle->pool, &u) != NGX_OK) { - if (u.err) { - ngx_log_error(NGX_LOG_ERR, cycle->log, 0, - "multiport, %s in \"%V\" when set port", u.err, &u.url); - } - - return NGX_ERROR; - } - - /* init multiport listening */ - if (ngx_event_multiport_init_listening(cycle, &mls->listening, - (struct sockaddr *) &u.sockaddr, u.socklen, ls) != NGX_OK) - { - ngx_log_error(NGX_LOG_ERR, cycle->log, 0, - "multiport, init listening error: %V", &mls->multiport); - return NGX_ERROR; - } - - /* open multiport listening */ - if (ngx_event_multiport_open_listening_sock(cycle, &mls->listening) - != NGX_OK) - { - ngx_log_error(NGX_LOG_ERR, cycle->log, 0, - "multiport, open listening error: %V", &mls->multiport); - return NGX_ERROR; - } - - /* config multiport listening */ - if (ngx_event_multiport_configure_listening_socket(cycle, - &mls->listening) != NGX_OK) - { - return NGX_ERROR; - } - - return NGX_OK; -} - -static ngx_int_t -ngx_event_multiport_enable_accept_event(ngx_cycle_t *cycle, ngx_listening_t *ls) -{ - ngx_connection_t *c; - ngx_event_t *rev; - - c = ngx_get_connection(ls->fd, ngx_cycle->log); - - if (c == NULL) { - return NGX_ERROR; - } - - c->type = ls->type; - c->log = &ls->log; - - c->listening = ls; - ls->connection = c; - - rev = c->read; - - rev->log = c->log; - rev->accept = 1; - -#if (NGX_HAVE_DEFERRED_ACCEPT) - rev->deferred_accept = ls->deferred_accept; -#endif - -#if (NGX_WIN32) - - if (ngx_event_flags & NGX_USE_IOCP_EVENT) { - ngx_iocp_conf_t *iocpcf; - - rev->handler = ngx_event_acceptex; - - if (ngx_add_event(rev, 0, NGX_IOCP_ACCEPT) == NGX_ERROR) { - return NGX_ERROR; - } - - ls->log.handler = ngx_acceptex_log_error; - - iocpcf = ngx_event_get_conf(cycle->conf_ctx, ngx_iocp_module); - if (ngx_event_post_acceptex(ls, iocpcf->post_acceptex) - == NGX_ERROR) - { - return NGX_ERROR; - } - - } else { - rev->handler = ngx_event_accept; - - if (ngx_use_accept_mutex) { - return NGX_OK; - } - - if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) { - return NGX_ERROR; - } - } - -#else - - rev->handler = (c->type == SOCK_STREAM)? ngx_event_accept - : ngx_event_recvmsg; - - if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) { - return NGX_ERROR; - } - -#endif - - return NGX_OK; -} - -static ngx_int_t -ngx_event_multiport_process_init(ngx_cycle_t *cycle) -{ - ngx_event_multiport_conf_t *emcf; - ngx_event_multiport_listen_t *mls; - ngx_listening_t *rls; - ngx_uint_t i; - - if (ngx_process != NGX_PROCESS_WORKER) { - return NGX_OK; - } - - emcf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_multiport_module); - if (emcf->ports == NULL) { - return NGX_OK; - } - - mls = emcf->ports->elts; - for (i = 0; i < emcf->ports->nelts; ++i) { - /* find relation listening in cycle->listening */ - rls = ngx_event_multiport_find_relation_port(cycle, - &mls[i].relatedport); - if (rls == NULL) { - return NGX_ERROR; - } - - /* set process port with relation port */ - if (ngx_event_multiport_set_port(cycle, &mls[i], rls) != NGX_OK) { - return NGX_ERROR; - } - - /* enable accept */ - if (ngx_event_multiport_enable_accept_event(cycle, &mls[i].listening) - != NGX_OK) - { - ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, - "multiport, enable accept failed"); - return NGX_ERROR; - } - } - - return NGX_OK; -} - -static void -ngx_event_multiport_process_exit(ngx_cycle_t *cycle) -{ - ngx_event_multiport_conf_t *emcf; - ngx_event_multiport_listen_t *mls; - ngx_uint_t i; - - if (ngx_process != NGX_PROCESS_WORKER) { - return; - } - - emcf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_multiport_module); - if (emcf->ports == NULL) { - return; - } - - mls = emcf->ports->elts; - - for (i = 0; i < emcf->ports->nelts; ++i) { - ngx_event_multiport_close_listening_sock(cycle, &mls[i].listening); - } -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_http_broadcast_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_http_broadcast_module.c deleted file mode 100644 index 5bce05f1f4..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_http_broadcast_module.c +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include -#include -#include -#include "ngx_multiport.h" - - -typedef struct { - ngx_str_t multiport; - ngx_str_t uri; -} ngx_http_broadcast_conf_t; - -typedef struct { - ngx_int_t workerid; - ngx_http_request_t *sr; -} ngx_http_broadcast_ctx_t; - - -static ngx_int_t ngx_http_broadcast_filter_init(ngx_conf_t *cf); - -static void *ngx_http_broadcast_create_conf(ngx_conf_t *cf); -static char *ngx_http_broadcast_merge_conf(ngx_conf_t *cf, - void *parent, void *child); -static char *ngx_http_broadcast(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); - - -static ngx_command_t ngx_http_broadcast_commands[] = { - - { ngx_string("broadcast"), - NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2, - ngx_http_broadcast, - NGX_HTTP_LOC_CONF_OFFSET, - 0, - NULL }, - - ngx_null_command -}; - - -static ngx_http_module_t ngx_http_broadcast_module_ctx = { - NULL, /* preconfiguration */ - ngx_http_broadcast_filter_init, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - ngx_http_broadcast_create_conf, /* create location configuration */ - ngx_http_broadcast_merge_conf /* merge location configuration */ -}; - - -ngx_module_t ngx_http_broadcast_module = { - NGX_MODULE_V1, - &ngx_http_broadcast_module_ctx, /* module context */ - ngx_http_broadcast_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static ngx_http_output_header_filter_pt ngx_http_next_header_filter; -static ngx_http_output_body_filter_pt ngx_http_next_body_filter; - - -static void * -ngx_http_broadcast_create_conf(ngx_conf_t *cf) -{ - ngx_http_broadcast_conf_t *conf; - - conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_broadcast_conf_t)); - if (conf == NULL) { - return NULL; - } - - return conf; -} - -static char * -ngx_http_broadcast_merge_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_http_broadcast_conf_t *prev = parent; - ngx_http_broadcast_conf_t *conf = child; - - ngx_conf_merge_str_value(conf->multiport, prev->multiport, ""); - ngx_conf_merge_str_value(conf->uri, prev->uri, ""); - - return NGX_CONF_OK; -} - -static char * -ngx_http_broadcast(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_broadcast_conf_t *hbcf; - ngx_str_t *value; - - hbcf = conf; - - if (hbcf->multiport.data != NULL) { - return "is duplicate"; - } - - value = cf->args->elts; - - hbcf->multiport = value[1]; - hbcf->uri = value[2]; - - return NGX_CONF_OK; -} - - -static ngx_int_t -ngx_http_broadcast_header_filter(ngx_http_request_t *r) -{ - ngx_http_broadcast_conf_t *hbcf; - - hbcf = ngx_http_get_module_loc_conf(r, ngx_http_broadcast_module); - - if (hbcf == NULL || hbcf->multiport.len == 0) { /* not configured */ - goto next; - } - - ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "broadcast header filter, r:%p r->main:%p, %ui, %O", - r, r->main, r->headers_out.status, r->headers_out.content_length_n); - - r->headers_out.status = NGX_HTTP_OK; - ngx_http_clear_content_length(r); - ngx_http_clear_accept_ranges(r); - -next: - return ngx_http_next_header_filter(r); -} - - -static ngx_int_t -ngx_http_broadcast_send_subrequest(ngx_http_request_t *r, ngx_int_t pslot) -{ - ngx_http_broadcast_conf_t *hbcf; - ngx_str_t uri; - ngx_str_t port; - ngx_http_request_t *sr; - ngx_int_t rc; - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "broadcast send subrequest to %i", pslot); - - hbcf = ngx_http_get_module_loc_conf(r, ngx_http_broadcast_module); - - if (ngx_multiport_get_port(r->pool, &port, &hbcf->multiport, pslot) - == NGX_ERROR) - { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "broadcast get port error, %V %i", &hbcf->multiport, pslot); - return NGX_ERROR; - } - - uri.len = hbcf->uri.len + 1 + port.len; - uri.data = ngx_pcalloc(r->pool, uri.len); - ngx_snprintf(uri.data, uri.len, "%V/%V", &hbcf->uri, &port); - - rc = ngx_http_subrequest(r, &uri, &r->args, &sr, NULL, 0); - sr->method = r->method; - sr->method_name = r->method_name; - - return rc; -} - -static ngx_int_t -ngx_http_broadcast_body_filter(ngx_http_request_t *r, ngx_chain_t *in) -{ - ngx_http_broadcast_conf_t *hbcf; - ngx_http_broadcast_ctx_t *ctx; - ngx_core_conf_t *ccf; - ngx_int_t rc; - ngx_buf_t *b; - ngx_chain_t cl; - - hbcf = ngx_http_get_module_loc_conf(r->main, ngx_http_broadcast_module); - - if (hbcf == NULL || hbcf->multiport.len == 0) { /* not configured */ - return ngx_http_next_body_filter(r, in); - } - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "broadcast body filter, r:%p r->main:%p", r, r->main); - - if (r != r->main) { /* send subrequest */ - if (r->headers_out.status != NGX_HTTP_OK) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "broadcast subrequest send non 200 response: %i", - r->headers_out.status); - return NGX_OK; - } - - return ngx_http_next_body_filter(r, in); - } - - ctx = ngx_http_get_module_ctx(r, ngx_http_broadcast_module); - - if (ctx == NULL) { - ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_broadcast_ctx_t)); - if (ctx == NULL) { - return NGX_ERROR; - } - - ngx_http_set_ctx(r, ctx, ngx_http_broadcast_module); - } - - /* send to all process */ - - ccf = (ngx_core_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_core_module); - - while (ctx->workerid < ccf->worker_processes) { - - rc = ngx_http_broadcast_send_subrequest(r, - ngx_multiport_get_slot(ctx->workerid)); - ++ctx->workerid; - - return rc; - } - - b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); - - if (b == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - b->last_buf = 1; - - cl.buf = b; - cl.next = NULL; - - return ngx_http_next_body_filter(r, &cl); -} - - -static ngx_int_t -ngx_http_broadcast_filter_init(ngx_conf_t *cf) -{ - ngx_http_next_header_filter = ngx_http_top_header_filter; - ngx_http_top_header_filter = ngx_http_broadcast_header_filter; - - ngx_http_next_body_filter = ngx_http_top_body_filter; - ngx_http_top_body_filter = ngx_http_broadcast_body_filter; - - return NGX_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_http_inner_proxy_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_http_inner_proxy_module.c deleted file mode 100644 index 2991b0e218..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_http_inner_proxy_module.c +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include -#include -#include -#include "ngx_multiport.h" - - -typedef struct { - ngx_str_t multiport; - ngx_str_t uri; -} ngx_http_inner_proxy_conf_t; - -typedef struct { - ngx_str_t port; - ngx_flag_t last; -} ngx_http_inner_proxy_ctx_t; - - -static ngx_int_t ngx_http_inner_proxy_filter_init(ngx_conf_t *cf); - -static void *ngx_http_inner_proxy_create_conf(ngx_conf_t *cf); -static char *ngx_http_inner_proxy_merge_conf(ngx_conf_t *cf, - void *parent, void *child); -static char *ngx_http_inner_proxy(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); - - -static ngx_command_t ngx_http_inner_proxy_commands[] = { - - { ngx_string("inner_proxy"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2, - ngx_http_inner_proxy, - NGX_HTTP_LOC_CONF_OFFSET, - 0, - NULL }, - - ngx_null_command -}; - - -static ngx_http_module_t ngx_http_inner_proxy_module_ctx = { - NULL, /* preconfiguration */ - ngx_http_inner_proxy_filter_init, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - ngx_http_inner_proxy_create_conf, /* create location configuration */ - ngx_http_inner_proxy_merge_conf /* merge location configuration */ -}; - - -ngx_module_t ngx_http_inner_proxy_module = { - NGX_MODULE_V1, - &ngx_http_inner_proxy_module_ctx, /* module context */ - ngx_http_inner_proxy_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static ngx_http_output_header_filter_pt ngx_http_next_header_filter; -static ngx_http_output_body_filter_pt ngx_http_next_body_filter; - - -static void * -ngx_http_inner_proxy_create_conf(ngx_conf_t *cf) -{ - ngx_http_inner_proxy_conf_t *conf; - - conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_inner_proxy_conf_t)); - if (conf == NULL) { - return NULL; - } - - return conf; -} - -static char * -ngx_http_inner_proxy_merge_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_http_inner_proxy_conf_t *prev = parent; - ngx_http_inner_proxy_conf_t *conf = child; - - ngx_conf_merge_str_value(conf->multiport, prev->multiport, ""); - ngx_conf_merge_str_value(conf->uri, prev->uri, ""); - - return NGX_CONF_OK; -} - -static char * -ngx_http_inner_proxy(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_inner_proxy_conf_t *hipcf; - ngx_str_t *value; - - hipcf = conf; - - if (hipcf->multiport.data != NULL) { - return "is duplicate"; - } - - value = cf->args->elts; - - hipcf->multiport = value[1]; - hipcf->uri = value[2]; - - return NGX_CONF_OK; -} - - -static ngx_int_t -ngx_http_inner_proxy_header_filter(ngx_http_request_t *r) -{ - ngx_http_inner_proxy_ctx_t *ctx; - - ctx = ngx_http_get_module_ctx(r->main, ngx_http_inner_proxy_module); - - if (ctx == NULL) { /* not configured */ - return ngx_http_next_header_filter(r); - } - - if (r == r->main) { - return NGX_OK; - } - - r->main->headers_out = r->headers_out; - - return ngx_http_next_header_filter(r->main); -} - - -static ngx_int_t -ngx_http_inner_proxy_body_filter(ngx_http_request_t *r, ngx_chain_t *in) -{ - ngx_http_inner_proxy_ctx_t *ctx; - ngx_chain_t *cl, l; - ngx_buf_t *b; - - ctx = ngx_http_get_module_ctx(r->main, ngx_http_inner_proxy_module); - - if (ctx == NULL) { /* not configured */ - return ngx_http_next_body_filter(r, in); - } - - if (r == r->main) { - if (ctx->last == 0) { - return NGX_OK; - } - - b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); - - if (b == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - b->last_buf = 1; - - l.buf = b; - l.next = NULL; - - return ngx_http_next_body_filter(r, &l); - } - - for (cl = in; cl; cl = cl->next) { - if (cl->buf->last_in_chain) { - ctx->last = 1; - } - } - - return ngx_http_next_body_filter(r, in); -} - - -static ngx_int_t -ngx_http_inner_proxy_filter_init(ngx_conf_t *cf) -{ - ngx_http_next_header_filter = ngx_http_top_header_filter; - ngx_http_top_header_filter = ngx_http_inner_proxy_header_filter; - - ngx_http_next_body_filter = ngx_http_top_body_filter; - ngx_http_top_body_filter = ngx_http_inner_proxy_body_filter; - - return NGX_OK; -} - - -ngx_int_t -ngx_http_inner_proxy_request(ngx_http_request_t *r, ngx_int_t pslot) -{ - ngx_http_inner_proxy_conf_t *hipcf; - ngx_http_inner_proxy_ctx_t *ctx; - ngx_http_request_t *sr; - ngx_str_t uri; - ngx_int_t rc; - - hipcf = ngx_http_get_module_loc_conf(r, ngx_http_inner_proxy_module); - - if (hipcf == NULL || hipcf->multiport.len == 0) { /* not configured */ - return NGX_DECLINED; - } - - if (pslot == ngx_process_slot) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "inner proxy send request to self: %i", ngx_process_slot); - return NGX_DECLINED; - } - - ctx = ngx_http_get_module_ctx(r, ngx_http_inner_proxy_module); - if (ctx) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "inner proxy has been called in this request"); - return NGX_ERROR; - } - - ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_inner_proxy_ctx_t)); - if (ctx == NULL) { - return NGX_ERROR; - } - ngx_http_set_ctx(r, ctx, ngx_http_inner_proxy_module); - - if (ngx_multiport_get_port(r->pool, &ctx->port, &hipcf->multiport, pslot) - == NGX_ERROR) - { - return NGX_ERROR; - } - - uri.len = hipcf->uri.len + 1 + ctx->port.len + 2 + r->uri.len; - uri.data = ngx_pcalloc(r->pool, uri.len); - ngx_snprintf(uri.data, uri.len, "%V/%V:/%V", - &hipcf->uri, &ctx->port, &r->uri); - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "inner proxy send request to %V", &ctx->port); - rc = ngx_http_subrequest(r, &uri, &r->args, &sr, NULL, 0); - sr->method = r->method; - sr->method_name = r->method_name; - - return rc; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_multiport.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_multiport.h deleted file mode 100644 index d3fc86bec0..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_multiport.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#ifndef _NGX_MULTIPORT_H_INCLUDED_ -#define _NGX_MULTIPORT_H_INCLUDED_ - - -#include -#include -#include - - -/* - * return value: - * NGX_OK for success, NGX_ERROR for failed - * paras: - * pool: pool for port memory alloc - * port: process real listen port while process_slot is pslot - * multiport: port configure for processes, format as below: - * port only: port - * IPv4: host:port host must be ipaddr of IPv4 or * - * IPv6: [host]:port host must be ipaddr of IPv6 - * Unix: unix:/path - * pslot: process_slot - */ -ngx_int_t ngx_multiport_get_port(ngx_pool_t *pool, ngx_str_t *port, - ngx_str_t *multiport, ngx_int_t pslot); - - -/* - * return value: - * ngx_process_slot for successd, NGX_ERROR for failed - * paras: - * wpid: worker process id, 0 to ccf->worker_processes - 1 - */ -ngx_int_t ngx_multiport_get_slot(ngx_uint_t wpid); - - -/* - * return value: - * NGX_OK : for successd - * NGX_ERROR : for failed - * NGX_DECLINED: for not configured or send inner proxy to self - * paras: - * r : http request for send inner request to sibling worker - * pslot: sibling worker ngx_process_slot - */ -ngx_int_t ngx_http_inner_proxy_request(ngx_http_request_t *r, ngx_int_t pslot); - - -#endif diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_multiport_misc.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_multiport_misc.c deleted file mode 100644 index 98ec0eb5c4..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_multiport_misc.c +++ /dev/null @@ -1,165 +0,0 @@ -#include -#include - - -static ngx_int_t -ngx_multiport_get_port_unix(ngx_pool_t *pool, ngx_str_t *port, - ngx_str_t *multiport, ngx_int_t pslot) -{ -#if (NGX_HAVE_UNIX_DOMAIN) - u_char *p; - size_t len; - - len = multiport->len + 5; /* unix:/path -> unix:/path.127\0 */ - port->data = ngx_pcalloc(pool, len); - if (port->data == NULL) { - return NGX_ERROR; - } - - p = ngx_snprintf(port->data, len, "%V.%i", multiport, pslot); - *p = 0; - port->len = p - port->data; - - return NGX_OK; -#else - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, - "the unix domain sockets not support"); - return NGX_ERROR; -#endif -} - -static ngx_int_t -ngx_multiport_get_port_inet6(ngx_pool_t *pool, ngx_str_t *port, - ngx_str_t *multiport, ngx_int_t pslot) -{ -#if (NGX_HAVE_INET6) - u_char *p, *last; - ngx_str_t addr; - size_t len; - ngx_int_t n; - - last = multiport->data + multiport->len; - p = ngx_strlchr(multiport->data, last, ']'); - - if (p == NULL) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "invalid INET6 host"); - return NGX_ERROR; - } - - ++p; - if (p == last || *p != ':') { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "no INET6 port"); - return NGX_ERROR; - } - - ++p; - addr.data = multiport->data; - addr.len = p - multiport->data; - - len = last - p; - n = ngx_atoi(p, len); - - /* 65408 + 127 = 65535, pslot in [0, 127] */ - if (n < 1 || n + pslot > 65408) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "invalid INET6 port"); - return NGX_ERROR; - } - n += pslot; - - len = multiport->len + 3; /* [::]:1 -> [::]:128\0 */ - port->data = ngx_pcalloc(pool, len); - if (port->data == NULL) { - return NGX_ERROR; - } - - p = port->data; - p = ngx_snprintf(p, len, "%V%i", &addr, n); - port->len = p - port->data; - - return NGX_OK; -#else - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, - "the INET6 sockets not support"); - return NGX_ERROR; -#endif -} - -static ngx_int_t -ngx_multiport_get_port_inet(ngx_pool_t *pool, ngx_str_t *port, - ngx_str_t *multiport, ngx_int_t pslot) -{ - u_char *p, *last; - ngx_str_t addr; - size_t len; - ngx_int_t n; - - last = multiport->data + multiport->len; - p = ngx_strlchr(multiport->data, last, ':'); - - if (p == NULL) { /* port */ - p = multiport->data; - addr.len = 0; - } else { /* host:port */ - ++p; - if (p == last) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "no port"); - return NGX_ERROR; - } - - addr.data = multiport->data; - addr.len = p - multiport->data; - } - - len = last - p; - n = ngx_atoi(p, len); - - /* 65408 + 127 = 65535, pslot in [0, 127] */ - if (n < 1 || n + pslot > 65408) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "invalid port"); - return NGX_ERROR; - } - n += pslot; - - len = multiport->len + 3; /* 127.0.0.1:1 -> 127.0.0.1:128\0 */ - port->data = ngx_pcalloc(pool, len); - if (port->data == NULL) { - return NGX_ERROR; - } - - p = port->data; - if (addr.len == 0) { - p = ngx_snprintf(p, len, "%i", n); - } else { - p = ngx_snprintf(p, len, "%V%i", &addr, n); - } - port->len = p - port->data; - - return NGX_OK; -} - -ngx_int_t -ngx_multiport_get_port(ngx_pool_t *pool, ngx_str_t *port, - ngx_str_t *multiport, ngx_int_t pslot) -{ - u_char *p; - size_t len; - - p = multiport->data; - len = multiport->len; - - if (pslot < 0 || pslot > 127) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "invalid pslot: %i", - pslot); - return NGX_ERROR; - } - - if (len >= 5 && ngx_strncasecmp(p, (u_char *) "unix:", 5) == 0) { - return ngx_multiport_get_port_unix(pool, port, multiport, pslot); - } - - if (len && p[0] == '[') { - return ngx_multiport_get_port_inet6(pool, port, multiport, pslot); - } - - return ngx_multiport_get_port_inet(pool, port, multiport, pslot); -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_process_slot_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_process_slot_module.c deleted file mode 100644 index 201281b50c..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_process_slot_module.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include -#include - - -static ngx_int_t ngx_process_slot_module_init(ngx_cycle_t *cycle); -static ngx_int_t ngx_process_slot_process_init(ngx_cycle_t *cycle); -static void ngx_process_slot_process_exit(ngx_cycle_t *cycle); - -static void *ngx_process_slot_module_create_conf(ngx_cycle_t *cycle); -static char *ngx_process_slot_module_init_conf(ngx_cycle_t *cycle, void *conf); - - -#define MAX_PROCESSES 128 - -typedef struct { - ngx_atomic_int_t process_slot[MAX_PROCESSES]; -} ngx_process_slot_ctx_t; - -typedef struct { - ngx_process_slot_ctx_t *ctx; -} ngx_process_slot_conf_t; - - -static ngx_command_t ngx_process_slot_commands[] = { - - ngx_null_command -}; - - -static ngx_core_module_t ngx_process_slot_module_ctx = { - ngx_string("process_slot"), - ngx_process_slot_module_create_conf, - ngx_process_slot_module_init_conf -}; - - -ngx_module_t ngx_process_slot_module = { - NGX_MODULE_V1, - &ngx_process_slot_module_ctx, /* module context */ - ngx_process_slot_commands, /* module directives */ - NGX_CORE_MODULE, /* module type */ - NULL, /* init master */ - ngx_process_slot_module_init, /* init module */ - ngx_process_slot_process_init, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - ngx_process_slot_process_exit, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void * -ngx_process_slot_module_create_conf(ngx_cycle_t *cycle) -{ - ngx_process_slot_conf_t *pscf; - - pscf = ngx_palloc(cycle->pool, sizeof(ngx_process_slot_conf_t)); - if (pscf == NULL) { - return NULL; - } - - return pscf; -} - -static char * -ngx_process_slot_module_init_conf(ngx_cycle_t *cycle, void *conf) -{ - return NGX_CONF_OK; -} - -static ngx_int_t -ngx_process_slot_module_init(ngx_cycle_t *cycle) -{ - ngx_process_slot_conf_t *pscf; - ngx_shm_t shm; - ngx_uint_t i; - - pscf = (ngx_process_slot_conf_t *) ngx_get_conf(cycle->conf_ctx, - ngx_process_slot_module); - - shm.size = sizeof(ngx_process_slot_ctx_t); - shm.name.len = sizeof("process_slot_zone") - 1; - shm.name.data = (u_char *) "process_slot_zone"; - shm.log = cycle->log; - - if (ngx_shm_alloc(&shm) != NGX_OK) { - return NGX_ERROR; - } - - pscf->ctx = (ngx_process_slot_ctx_t *) shm.addr; - - for (i = 0; i < MAX_PROCESSES; ++i) { - pscf->ctx->process_slot[i] = -1; - } - - return NGX_OK; -} - -static ngx_int_t -ngx_process_slot_process_init(ngx_cycle_t *cycle) -{ - ngx_process_slot_conf_t *pscf; - ngx_process_slot_ctx_t *ctx; - - if (ngx_process != NGX_PROCESS_WORKER) { - return NGX_OK; - } - - pscf = (ngx_process_slot_conf_t *) ngx_get_conf(cycle->conf_ctx, - ngx_process_slot_module); - ctx = pscf->ctx; - - for (;;) { - if (ngx_atomic_cmp_set((ngx_atomic_t *) &ctx->process_slot[ngx_worker], - (ngx_atomic_uint_t)ctx->process_slot[ngx_worker], ngx_process_slot)) - { - break; - } - } - - return NGX_OK; -} - -static void -ngx_process_slot_process_exit(ngx_cycle_t *cycle) -{ - ngx_process_slot_conf_t *pscf; - ngx_process_slot_ctx_t *ctx; - - if (ngx_process != NGX_PROCESS_WORKER) { - return; - } - - pscf = (ngx_process_slot_conf_t *) ngx_get_conf(cycle->conf_ctx, - ngx_process_slot_module); - ctx = pscf->ctx; - - ngx_atomic_cmp_set((ngx_atomic_t *) &ctx->process_slot[ngx_worker], - (ngx_atomic_uint_t)ngx_process_slot, -1); -} - -ngx_int_t -ngx_multiport_get_slot(ngx_uint_t wpid) -{ - ngx_process_slot_conf_t *pscf; - ngx_process_slot_ctx_t *ctx; - ngx_core_conf_t *ccf; - - ccf = (ngx_core_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_core_module); - - if (wpid >= (ngx_uint_t)ccf->worker_processes) { - return -1; - } - - pscf = (ngx_process_slot_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_process_slot_module); - ctx = pscf->ctx; - - return ctx->process_slot[wpid]; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_stream_zone_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_stream_zone_module.c deleted file mode 100644 index 94c2df679a..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_stream_zone_module.c +++ /dev/null @@ -1,551 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include -#include -#include - -typedef struct ngx_stream_zone_hash_s ngx_stream_zone_hash_t; -typedef struct ngx_stream_zone_node_s ngx_stream_zone_node_t; -typedef struct ngx_stream_zone_conf_s ngx_stream_zone_conf_t; - -static ngx_int_t -ngx_stream_zone_init_process(ngx_cycle_t *cycle); -static void -ngx_stream_zone_exit_process(ngx_cycle_t *cycle); -static void * -ngx_stream_zone_create_conf(ngx_cycle_t *cf); -static char * -ngx_stream_zone_init_conf(ngx_cycle_t *cycle, void *conf); -static char * -ngx_stream_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -static char * -ngx_stream_zone_shm_init(ngx_shm_t *shm, ngx_stream_zone_conf_t *szcf, - ngx_cycle_t *cycle); - - -#define NAME_LEN 1024 - -static ngx_str_t stream_zone_key = ngx_string("stream_zone"); - -struct ngx_stream_zone_node_s { - u_char name[NAME_LEN]; - ngx_int_t slot; /* process slot */ - ngx_int_t idx; - ngx_int_t next; /* idx of stream node */ -}; - -struct ngx_stream_zone_hash_s { - ngx_shmtx_t mutex; - ngx_shmtx_sh_t lock; - ngx_int_t node; /* idx of stream node */ -}; - -struct ngx_stream_zone_conf_s { - ngx_int_t nbuckets; - ngx_int_t nstreams; - - ngx_pool_t *pool; - - ngx_shmtx_t *mutex; - ngx_shmtx_sh_t *lock; - ngx_stream_zone_hash_t *hash; /* hash in shm */ - ngx_stream_zone_node_t *stream_node;/* node in shm */ - ngx_int_t *free_node; /* free node chain */ - ngx_int_t *alloc; /* node number in use*/ -}; - - -static ngx_command_t ngx_stream_zone_commands[] = { - - { ngx_string("stream_zone"), - NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE2, - ngx_stream_zone, - 0, - 0, - NULL }, - - ngx_null_command -}; - - -static ngx_core_module_t ngx_stream_zone_module_ctx = { - ngx_string("rtmp_stream_zone"), - ngx_stream_zone_create_conf, /* create conf */ - ngx_stream_zone_init_conf /* init conf */ -}; - - -ngx_module_t ngx_stream_zone_module = { - NGX_MODULE_V1, - &ngx_stream_zone_module_ctx, /* module context */ - ngx_stream_zone_commands, /* module directives */ - NGX_CORE_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - ngx_stream_zone_init_process, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - ngx_stream_zone_exit_process, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static ngx_stream_zone_node_t * -ngx_stream_zone_get_node(ngx_str_t *name, ngx_int_t pslot) -{ - ngx_stream_zone_conf_t *szcf; - ngx_stream_zone_node_t *node; - - szcf = (ngx_stream_zone_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_stream_zone_module); - - ngx_shmtx_lock(szcf->mutex); - - if (*szcf->free_node == -1) { - ngx_shmtx_unlock(szcf->mutex); - return NULL; - } - - node = &szcf->stream_node[*szcf->free_node]; - *szcf->free_node = node->next; - - *ngx_copy(node->name, name->data, ngx_min(NAME_LEN - 1, name->len)) = '\0'; - node->slot = pslot; - node->next = -1; - - ++*szcf->alloc; - - ngx_shmtx_unlock(szcf->mutex); - - return node; -} - -static void -ngx_stream_zone_put_node(ngx_int_t idx) -{ - ngx_stream_zone_conf_t *szcf; - ngx_stream_zone_node_t *node; - - szcf = (ngx_stream_zone_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_stream_zone_module); - - ngx_shmtx_lock(szcf->mutex); - - node = &szcf->stream_node[idx]; - - node->next = *szcf->free_node; - *szcf->free_node = idx; - - --*szcf->alloc; - - ngx_shmtx_unlock(szcf->mutex); -} - -static void * -ngx_stream_zone_create_conf(ngx_cycle_t *cf) -{ - ngx_stream_zone_conf_t *conf; - - conf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_zone_conf_t)); - if (conf == NULL) { - return NULL; - } - - conf->nbuckets = NGX_CONF_UNSET; - conf->nstreams = NGX_CONF_UNSET; - conf->pool = ngx_create_pool(4096, cf->log); - - return conf; -} - -static char * -ngx_stream_zone_init_conf(ngx_cycle_t *cycle, void *conf) -{ - size_t len; - ngx_shm_t shm; - ngx_stream_zone_conf_t *szcf = conf; - - ngx_conf_init_value(szcf->nbuckets, 512); - ngx_conf_init_value(szcf->nstreams, 40960); - - /* create shm zone */ - len = sizeof(ngx_shmtx_t) + sizeof(ngx_shmtx_sh_t) - + sizeof(ngx_stream_zone_hash_t) * szcf->nbuckets - + sizeof(ngx_stream_zone_node_t) * szcf->nstreams - + sizeof(ngx_int_t) + sizeof(ngx_int_t); - - shm.size = len; - shm.name = stream_zone_key; - shm.log = cycle->log; - - if (ngx_shm_alloc(&shm) != NGX_OK) { - return NGX_CONF_ERROR; - } - - return ngx_stream_zone_shm_init(&shm, szcf, cycle); -} - -static void -ngx_stream_zone_clear(ngx_cycle_t *cycle) -{ - ngx_stream_zone_conf_t *szcf; - volatile ngx_int_t idx, cur, next; - - szcf = (ngx_stream_zone_conf_t *) ngx_get_conf(cycle->conf_ctx, - ngx_stream_zone_module); - - if (szcf->nbuckets <= 0 || szcf->nstreams <= 0) { - return; - } - - for (idx = 0; idx < szcf->nbuckets; ++idx) { - - ngx_shmtx_lock(&szcf->hash[idx].mutex); - cur = -1; - - while (1) { - if (cur == -1) { - next = szcf->hash[idx].node; - } else { - next = szcf->stream_node[cur].next; - } - - if (next == -1) { - break; - } - - if (szcf->stream_node[next].slot == ngx_process_slot) { - if (cur == -1) { - szcf->hash[idx].node = szcf->stream_node[next].next; - } else { - szcf->stream_node[cur].next = szcf->stream_node[next].next; - } - - ngx_stream_zone_put_node(next); - continue; - } - - cur = next; - } - ngx_shmtx_unlock(&szcf->hash[idx].mutex); - } -} - -static ngx_int_t -ngx_stream_zone_init_process(ngx_cycle_t *cycle) -{ - ngx_stream_zone_clear(cycle); - - return NGX_OK; -} - -static void -ngx_stream_zone_exit_process(ngx_cycle_t *cycle) -{ - ngx_stream_zone_clear(cycle); -} - -static char * -ngx_stream_zone_shm_init(ngx_shm_t *shm, ngx_stream_zone_conf_t *szcf, - ngx_cycle_t *cycle) -{ - u_char *p; - ngx_int_t i, next; - - p = shm->addr; - - szcf->mutex = (ngx_shmtx_t *) p; - p += sizeof(ngx_shmtx_t); - - szcf->lock = (ngx_shmtx_sh_t *) p; - p += sizeof(ngx_shmtx_sh_t); - - szcf->hash = (ngx_stream_zone_hash_t *) p; - p += sizeof(ngx_stream_zone_hash_t) * szcf->nbuckets; - - szcf->stream_node = (ngx_stream_zone_node_t *) p; - p += sizeof(ngx_stream_zone_node_t) * szcf->nstreams; - - szcf->free_node = (ngx_int_t *) p; - p += sizeof(ngx_int_t); - - szcf->alloc = (ngx_int_t *) p; - - /* init shm zone */ -#if (NGX_HAVE_ATOMIC_OPS) - - p = NULL; - -#else - p = ngx_pnalloc(szcf->pool, cycle->lock_file.len - + stream_zone_key.len); - if (p == NULL) { - return NGX_CONF_ERROR; - } - *ngx_sprintf(p, "%V%V", &cycle->lock_file, &stream_zone_key) = 0; - -#endif - - if (ngx_shmtx_create(szcf->mutex, szcf->lock, p) != NGX_OK) { - return NGX_CONF_ERROR; - } - - for (i = 0; i < szcf->nbuckets; ++i) { -#if (NGX_HAVE_ATOMIC_OPS) - - p = NULL; - -#else - p = ngx_pnalloc(szcf->pool, cycle->lock_file.len + stream_zone_key.len - + NGX_INT32_LEN); - if (p == NULL) { - return NGX_CONF_ERROR; - } - *ngx_sprintf(p, "%V%V%d", &cycle->lock_file, - &stream_zone_key, i) = 0; - -#endif - - if (ngx_shmtx_create(&szcf->hash[i].mutex, &szcf->hash[i].lock, p) - != NGX_OK) - { - return NGX_CONF_ERROR; - } - - szcf->hash[i].node = -1; - } - - next = -1; - i = szcf->nstreams; - - do { - --i; - - szcf->stream_node[i].slot = -1; - szcf->stream_node[i].idx = i; - szcf->stream_node[i].next = next; - next = i; - } while (i); - - *szcf->free_node = i; - *szcf->alloc = 0; - - return NGX_CONF_OK; -} - -static char * -ngx_stream_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_uint_t i; - ngx_str_t *value; - ngx_stream_zone_conf_t *szcf = conf; - - value = cf->args->elts; - - for (i = 1; i < cf->args->nelts; ++i) { - - if (ngx_strncmp(value[i].data, "buckets=", 8) == 0) { - szcf->nbuckets = ngx_atoi(value[i].data + 8, value[i].len - 8); - - if (szcf->nbuckets <= 0) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid buckets \"%V\"", &value[i]); - return NGX_CONF_ERROR; - } - - continue; - } - - if (ngx_strncmp(value[i].data, "streams=", 8) == 0) { - szcf->nstreams = ngx_atoi(value[i].data + 8, value[i].len - 8); - - if (szcf->nstreams <= 0) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid streams \"%V\"", &value[i]); - return NGX_CONF_ERROR; - } - - continue; - } - - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid parameter \"%V\"", &value[i]); - return NGX_CONF_ERROR; - } - - return NGX_CONF_OK; -} - - -ngx_int_t -ngx_stream_zone_insert_stream(ngx_str_t *name) -{ - ngx_stream_zone_conf_t *szcf; - volatile ngx_uint_t idx; - volatile ngx_int_t i, pslot; - ngx_stream_zone_node_t *node; - - szcf = (ngx_stream_zone_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_stream_zone_module); - - if (szcf->nbuckets <= 0 || szcf->nstreams <= 0) { - return NGX_ERROR; - } - - if (name->len >= NAME_LEN) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, - "stream name(%V) too long", name); - return NGX_ERROR; - } - - idx = ngx_hash_key(name->data, name->len) % szcf->nbuckets; - - ngx_shmtx_lock(&szcf->hash[idx].mutex); - i = szcf->hash[idx].node; - pslot = -1; - while (i != -1) { - if (ngx_strlen(szcf->stream_node[i].name) == name->len - && ngx_memcmp(szcf->stream_node[i].name, name->data, name->len) - == 0) - { - pslot = szcf->stream_node[i].slot; - break; - } - - i = szcf->stream_node[i].next; - } - - if (i == -1) { /* stream not in hash */ - node = ngx_stream_zone_get_node(name, ngx_process_slot); - if (node == NULL) { - ngx_shmtx_unlock(&szcf->hash[idx].mutex); - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, - "stream zone get node failed"); - return NGX_ERROR; - } - node->slot = ngx_process_slot; - - node->next = szcf->hash[idx].node; - szcf->hash[idx].node = node->idx; - - pslot = ngx_process_slot; - } - ngx_shmtx_unlock(&szcf->hash[idx].mutex); - - return pslot; -} - -void -ngx_stream_zone_delete_stream(ngx_str_t *name) -{ - ngx_stream_zone_conf_t *szcf; - volatile ngx_uint_t idx; - volatile ngx_int_t cur, next; - - szcf = (ngx_stream_zone_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_stream_zone_module); - - if (szcf->nbuckets <= 0 || szcf->nstreams <= 0) { - return; - } - - idx = ngx_hash_key(name->data, name->len) % szcf->nbuckets; - - ngx_shmtx_lock(&szcf->hash[idx].mutex); - cur = -1; - next = szcf->hash[idx].node; - while (next != -1) { - if (ngx_strlen(szcf->stream_node[next].name) == name->len - && ngx_memcmp(szcf->stream_node[next].name, name->data, name->len) - == 0) - { - if (szcf->stream_node[next].slot != ngx_process_slot) { - break; - } - - if (cur == -1) { /* link header */ - szcf->hash[idx].node = szcf->stream_node[next].next; - } else { - szcf->stream_node[cur].next = szcf->stream_node[next].next; - } - ngx_stream_zone_put_node(next); - break; - } - - cur = next; - next = szcf->stream_node[next].next; - } - ngx_shmtx_unlock(&szcf->hash[idx].mutex); -} - -ngx_chain_t * -ngx_stream_zone_state(ngx_http_request_t *r, ngx_flag_t detail) -{ - ngx_stream_zone_conf_t *szcf; - ngx_chain_t *cl; - ngx_buf_t *b; - size_t len; - volatile ngx_int_t idx, next; - - szcf = (ngx_stream_zone_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_stream_zone_module); - - if (szcf->nbuckets <= 0 || szcf->nstreams <= 0) { - return NULL; - } - - len = sizeof("##########stream zone state##########\n") - 1 - + sizeof("ngx_stream_zone buckets: \n") - 1 + NGX_OFF_T_LEN - + sizeof("ngx_stream_zone streams: \n") - 1 + NGX_OFF_T_LEN - + sizeof("ngx_stream_zone alloc: \n") - 1 + NGX_OFF_T_LEN; - - cl = ngx_alloc_chain_link(r->pool); - if (cl == NULL) { - return NULL; - } - cl->next = NULL; - - b = ngx_create_temp_buf(r->pool, len); - if (b == NULL) { - return NULL; - } - cl->buf = b; - - b->last = ngx_snprintf(b->last, len, - "##########stream zone state##########\n" - "ngx_stream_zone buckets: %i\nngx_stream_zone streams: %i\n" - "ngx_stream_zone alloc: %i\n", - szcf->nbuckets, szcf->nstreams, *szcf->alloc); - - if (detail) { - for (idx = 0; idx < szcf->nbuckets; ++idx) { - ngx_shmtx_lock(&szcf->hash[idx].mutex); - - next = szcf->hash[idx].node; - if (next == -1) { - ngx_shmtx_unlock(&szcf->hash[idx].mutex); - continue; - } - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "slot: %i", idx); - - while (next != -1) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "\t\tname:%s, slot:%i, idx:%i, next:%i", - szcf->stream_node[next].name, - szcf->stream_node[next].slot, - szcf->stream_node[next].idx, - szcf->stream_node[next].next); - - next = szcf->stream_node[next].next; - } - - ngx_shmtx_unlock(&szcf->hash[idx].mutex); - } - } - - return cl; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_stream_zone_module.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_stream_zone_module.h deleted file mode 100644 index ba2d082d08..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_stream_zone_module.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#ifndef _NGX_STREAM_ZONE_MODULE_H_INCLUDED_ -#define _NGX_STREAM_ZONE_MODULE_H_INCLUDED_ - - -#include -#include -#include - - -/* - * return value: - * process_slot for owner of stream, NGX_ERROR for error - * name: - * stream name - */ -ngx_int_t ngx_stream_zone_insert_stream(ngx_str_t *name); - -/* - * name: - * stream name - */ -void ngx_stream_zone_delete_stream(ngx_str_t *name); - -/* - * return value: - * chain of stream zone state for returning to http client - * paras: - * r: http request to query status of rbuf - * detail: print stream detail in log - */ -ngx_chain_t *ngx_stream_zone_state(ngx_http_request_t *r, ngx_flag_t detail); - - -#endif diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/config b/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/config deleted file mode 100644 index 134ede979f..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/config +++ /dev/null @@ -1,12 +0,0 @@ -ngx_addon_name=ngx_multiport_test_module - -HTTP_MODULES="$HTTP_MODULES \ - ngx_stream_zone_test_module \ - ngx_multiport_test_module \ - " - -NGX_ADDON_SRCS="$NGX_ADDON_SRCS - $ngx_addon_dir/ngx_stream_zone_test_module.c \ - $ngx_addon_dir/ngx_multiport_test_module.c \ - " - diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/nginx.conf b/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/nginx.conf deleted file mode 100644 index 3745d421d2..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/nginx.conf +++ /dev/null @@ -1,71 +0,0 @@ - -user root; -worker_processes 4; - -#error_log logs/error.log; -#error_log logs/error.log notice; -error_log logs/error.log info; - -#pid logs/nginx.pid; - -stream_zone buckets=10007 streams=10000; - -events { - worker_connections 1024; - multi_listen 9000 80; - multi_listen unix:/tmp/http.sock.80 80; -} - - -http { - include mime.types; - default_type application/octet-stream; - - #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - # '$status $body_bytes_sent "$http_referer" ' - # '"$http_user_agent" "$http_x_forwarded_for"'; - - #access_log logs/access.log main; - - sendfile on; - #tcp_nopush on; - - #keepalive_timeout 0; - keepalive_timeout 65; - - #gzip on; - - server { - listen 80; - server_name localhost; - - location /stream_zone_test/ { - stream_zone_test; - } - - location /multiport_test/ { - inner_proxy unix:/tmp/http.sock.80 /inner_proxy; - multiport_test; - } - - location /inner_proxy/ { - rewrite ^/inner_proxy/(.*):/(.*) /$2 break; - proxy_pass http://$1:; - } - - location / { - broadcast unix:/tmp/http.sock.80 /auth_proxy; - } - - location /auth_proxy/ { - rewrite ^/auth_proxy/(.*) /auth break; - proxy_pass http://$1:; - } - - location /auth { - # return 403; - echo "auth"; - echo $scheme://$host$uri?$args; - } - } -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/ngx_multiport_test_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/ngx_multiport_test_module.c deleted file mode 100644 index b9c3025d1b..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/ngx_multiport_test_module.c +++ /dev/null @@ -1,168 +0,0 @@ -#include -#include -#include -#include "ngx_multiport.h" -#include "ngx_test_macro.h" - - -static char *ngx_multiport_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); - - -static ngx_command_t ngx_multiport_test_commands[] = { - - { ngx_string("multiport_test"), - NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, - ngx_multiport_test, - 0, - 0, - NULL }, - - ngx_null_command -}; - - -static ngx_http_module_t ngx_multiport_test_module_ctx = { - NULL, /* preconfiguration */ - NULL, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - NULL, /* create location configuration */ - NULL /* merge location configuration */ -}; - - -ngx_module_t ngx_multiport_test_module = { - NGX_MODULE_V1, - &ngx_multiport_test_module_ctx, /* module context */ - ngx_multiport_test_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -ngx_int_t -ngx_multiport_test_get_port(ngx_http_request_t *r, char *multiport, - ngx_int_t pslot, char *expect) -{ - ngx_str_t port; - ngx_int_t rc; - ngx_str_t mp; - - mp.data = (u_char *) multiport; - mp.len = ngx_strlen(multiport); - - ngx_memzero(&port, sizeof(ngx_str_t)); - rc = ngx_multiport_get_port(r->pool, &port, &mp, pslot); - if (port.len) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "port: %V, %s, %d", - &port, port.data, port.len); - } - if (expect == NULL && rc == NGX_ERROR) { - return 1; - } else { - return ngx_test_str(&port, expect); - } - - return 0; -} - -static ngx_int_t -ngx_multiport_test_handler(ngx_http_request_t *r) -{ - ngx_buf_t *b; - ngx_chain_t cl; - size_t len; - ngx_int_t rc; - - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "multiport test handler"); - - rc = ngx_http_inner_proxy_request(r, ngx_multiport_get_slot(0)); - if (rc != NGX_DECLINED) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "inner proxy return %i", rc); - return rc; - } - - NGX_TEST_INIT - - /* test ngx_multiport_get_port */ - /* normal format */ - NGX_TEST_ISOK(ngx_multiport_test_get_port(r, "10", 127, "137")); - NGX_TEST_ISOK(ngx_multiport_test_get_port(r, "127.0.0.1:55635", 4, - "127.0.0.1:55639")); - NGX_TEST_ISOK(ngx_multiport_test_get_port(r, "[::127.0.0.1]:1024", 0, - "[::127.0.0.1]:1024")); - NGX_TEST_ISOK(ngx_multiport_test_get_port(r, "unix:/tmp.test", 7, - "unix:/tmp.test.7")); - - /* inet6 format error */ - NGX_TEST_ISOK(ngx_multiport_test_get_port(r, "[::127.0.0.1:1024", 0, NULL)); - NGX_TEST_ISOK(ngx_multiport_test_get_port(r, "[::127.0.0.1]:abcd", - 0, NULL)); - NGX_TEST_ISOK(ngx_multiport_test_get_port(r, "[::127.0.0.1]:65409", - 0, NULL)); - NGX_TEST_ISOK(ngx_multiport_test_get_port(r, "[::127.0.0.1]:", 0, NULL)); - NGX_TEST_ISOK(ngx_multiport_test_get_port(r, "[::127.0.0.1]", 0, NULL)); - - /* inet format error */ - NGX_TEST_ISOK(ngx_multiport_test_get_port(r, "127.0.0.1:", 4, NULL)); - NGX_TEST_ISOK(ngx_multiport_test_get_port(r, "abcd", 4, NULL)); - NGX_TEST_ISOK(ngx_multiport_test_get_port(r, "65410", 4, NULL)); - - /* pslot error */ - NGX_TEST_ISOK(ngx_multiport_test_get_port(r, "65410", -1, NULL)); - NGX_TEST_ISOK(ngx_multiport_test_get_port(r, "65410", 128, NULL)); - - /* test ngx_multiport_get_slot */ - NGX_TEST_ISOK(ngx_multiport_get_slot(4) == -1); - NGX_TEST_ISOK(ngx_multiport_get_slot(0) == 0); - NGX_TEST_ISOK(ngx_multiport_get_slot(1) == 1); - NGX_TEST_ISOK(ngx_multiport_get_slot(2) == 2); - NGX_TEST_ISOK(ngx_multiport_get_slot(3) == 3); - - r->headers_out.status = NGX_HTTP_OK; - - ngx_http_send_header(r); - - len = sizeof("pslot: %i TEST cases 4294967296, 4294967296 pass\n") - 1; - b = ngx_create_temp_buf(r->pool, len); - - if (b == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - b->last = ngx_snprintf(b->last, len, "pslot: %i TEST cases %d, %d pass\n", - ngx_process_slot, count, pass); - b->last_buf = 1; - b->last_in_chain = 1; - - cl.buf = b; - cl.next = NULL; - - return ngx_http_output_filter(r, &cl); -} - - -static char * -ngx_multiport_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_core_loc_conf_t *clcf; - - clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); - clcf->handler = ngx_multiport_test_handler; - - return NGX_CONF_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/ngx_stream_zone_test_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/ngx_stream_zone_test_module.c deleted file mode 100644 index 8adab4ff3b..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/ngx_stream_zone_test_module.c +++ /dev/null @@ -1,134 +0,0 @@ -#include -#include -#include -#include "ngx_stream_zone_module.h" - - -static char *ngx_stream_zone_test(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); - -static ngx_command_t ngx_stream_zone_test_commands[] = { - - { ngx_string("stream_zone_test"), - NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, - ngx_stream_zone_test, - 0, - 0, - NULL }, - - ngx_null_command -}; - - -static ngx_http_module_t ngx_stream_zone_test_module_ctx = { - NULL, /* preconfiguration */ - NULL, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - NULL, /* create location configuration */ - NULL /* merge location configuration */ -}; - - -ngx_module_t ngx_stream_zone_test_module = { - NGX_MODULE_V1, - &ngx_stream_zone_test_module_ctx, /* module context */ - ngx_stream_zone_test_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static ngx_int_t -ngx_stream_zone_test_handler(ngx_http_request_t *r) -{ - ngx_chain_t cl, *out; - ngx_buf_t *b; - size_t len; - ngx_str_t stream; - ngx_int_t rc; - - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "stream zone test handler"); - - rc = -1; - if (r->method == NGX_HTTP_GET) { - out = ngx_stream_zone_state(r, 1); - out->buf->last_buf = 1; - out->buf->last_in_chain = 1; - - r->headers_out.status = NGX_HTTP_OK; - ngx_http_send_header(r); - - return ngx_http_output_filter(r, out); - } else if (r->method == NGX_HTTP_DELETE) { - - if (ngx_http_arg(r, (u_char *) "stream", 6, &stream) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "stream zone test, no stream in http args"); - return NGX_HTTP_BAD_REQUEST; - } - - len = sizeof("delete stream=\n") - 1 + stream.len; - - ngx_stream_zone_delete_stream(&stream); - } else if (r->method == NGX_HTTP_POST) { - - if (ngx_http_arg(r, (u_char *) "stream", 6, &stream) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "stream zone test, no stream in http args"); - return NGX_HTTP_BAD_REQUEST; - } - - len = sizeof("stream= in process:4294967296\n") - 1 + stream.len; - - rc = ngx_stream_zone_insert_stream(&stream); - } else { - return NGX_HTTP_BAD_REQUEST; - } - - r->headers_out.status = NGX_HTTP_OK; - ngx_http_send_header(r); - - b = ngx_create_temp_buf(r->pool, len); - - if (b == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - if (r->method == NGX_HTTP_DELETE) { - b->last = ngx_snprintf(b->last, len, "delete stream=%V\n", &stream); - } else { - b->last = ngx_snprintf(b->last, len, - "stream=%V in process:%i\n", &stream, rc); - } - b->last_buf = 1; - b->last_in_chain = 1; - - cl.buf = b; - cl.next = NULL; - - return ngx_http_output_filter(r, &cl); -} - -static char * -ngx_stream_zone_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_core_loc_conf_t *clcf; - - clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); - clcf->handler = ngx_stream_zone_test_handler; - - return NGX_CONF_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/ngx_test_macro.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/ngx_test_macro.h deleted file mode 100644 index 6da2f68cae..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/ngx_test_macro.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#ifndef _NGX_TEST_MACRO_H_INCLUDE_ -#define _NGX_TEST_MACRO_H_INCLUDE_ - - -#include -#include - - -static ngx_int_t count = 0; -static ngx_int_t pass = 0; - -#define NGX_TEST_INIT count = 0, pass = 0; - -#define NGX_TEST_ISOK(testcase) \ -{ \ - ngx_int_t __ret = testcase; \ - ++count; \ - if (__ret) ++pass; \ - ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, " TEST "#testcase"%s",\ - (__ret ? " ...OK" : " ...ERROR")); \ -} - -#define NGX_TEST_INT(di, si) \ - (di == si) - -static ngx_inline ngx_int_t -ngx_test_str(ngx_str_t *nstr, char *cstr) -{ - size_t len; - - len = ngx_strlen(cstr); - - return (nstr->len == len && ngx_memcmp(nstr->data, cstr, len) == 0); -} - -#endif diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/AUTHORS b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/AUTHORS deleted file mode 100644 index db7b2e4ee9..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/AUTHORS +++ /dev/null @@ -1,9 +0,0 @@ -Project author: - - Roman Arutyunyan - Moscow, Russia, Pingo - - Contacts: - arut@qip.ru - arutyunyan.roman@gmail.com - cczjp89@gmail.com \ No newline at end of file diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/LICENSE b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/LICENSE deleted file mode 100644 index 15cb1e0ee9..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -Copyright (c) 2012-2014, Roman Arutyunyan -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/config b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/config deleted file mode 100644 index 4bf0264dc8..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/config +++ /dev/null @@ -1,169 +0,0 @@ -ngx_addon_name="ngx_rtmp_module" - -RTMP_CORE_MODULES=" \ - ngx_live_module \ - ngx_rtmp_module \ - ngx_rtmp_dynamic_module \ - ngx_rtmp_dynamic_core_module \ - ngx_rtmp_core_module \ - ngx_rtmp_cmd_module \ - ngx_rtmp_codec_module \ - ngx_rtmp_access_module \ - ngx_rtmp_live_module \ - ngx_live_record_module \ - ngx_live_relay_module \ - ngx_live_relay_rtmp_module \ - ngx_live_relay_static_module \ - ngx_live_relay_simple_module \ - ngx_rtmp_exec_module \ - ngx_rtmp_notify_module \ - ngx_live_relay_inner_module \ - ngx_rtmp_log_module \ - ngx_rtmp_limit_module \ - ngx_rtmp_hls_module \ - ngx_rtmp_dash_module \ - ngx_rtmp_shared_module \ - ngx_rtmp_record_module \ - ngx_rtmp_gop_module \ - ngx_rtmp_monitor_module \ - ngx_mpegts_live_module \ - ngx_mpegts_gop_module \ - ngx_hls_live_module \ - " - - -RTMP_HTTP_MODULES=" \ - ngx_rtmp_stat_module \ - ngx_rtmp_sys_stat_module \ - ngx_rtmp_control_module \ - ngx_http_flv_live_module \ - ngx_hls_http_module \ - ngx_mpegts_http_module \ - " - - -RTMP_DEPS=" \ - $ngx_addon_dir/ngx_netcall.h \ - $ngx_addon_dir/ngx_rtmp_amf.h \ - $ngx_addon_dir/ngx_rtmp_bandwidth.h \ - $ngx_addon_dir/ngx_rtmp_cmd_module.h \ - $ngx_addon_dir/ngx_rtmp_codec_module.h \ - $ngx_addon_dir/ngx_rtmp_eval.h \ - $ngx_addon_dir/ngx_rtmp.h \ - $ngx_addon_dir/ngx_rtmp_version.h \ - $ngx_addon_dir/ngx_rtmp_live_module.h \ - $ngx_addon_dir/ngx_rtmp_notify_module.h \ - $ngx_addon_dir/ngx_rtmp_streams.h \ - $ngx_addon_dir/ngx_rtmp_bitop.h \ - $ngx_addon_dir/ngx_rtmp_proxy_protocol.h \ - $ngx_addon_dir/ngx_rtmp_monitor_module.h \ - $ngx_addon_dir/hls/ngx_rtmp_mpegts.h \ - $ngx_addon_dir/dash/ngx_rtmp_mp4.h \ - $ngx_addon_dir/http/ngx_http_set_header.h \ - $ngx_addon_dir/ngx_live.h \ - $ngx_addon_dir/ngx_live_relay.h \ - $ngx_addon_dir/ngx_live_record.h \ - $ngx_addon_dir/ngx_rtmp_dynamic.h \ - $ngx_addon_dir/ngx_rtmp_variables.h \ - $ngx_addon_dir/ngx_rtmp_record_module.h \ - $ngx_addon_dir/mpegts/ngx_mpegts_live_module.h \ - $ngx_addon_dir/mpegts/ngx_hls_live_module.h \ - $ngx_addon_dir/mpegts/ngx_mpegts_gop_module.h \ - " - - -RTMP_CORE_SRCS=" \ - $ngx_addon_dir/ngx_netcall.c \ - $ngx_addon_dir/ngx_rtmp.c \ - $ngx_addon_dir/ngx_rtmp_init.c \ - $ngx_addon_dir/ngx_rtmp_handshake.c \ - $ngx_addon_dir/ngx_rtmp_handler.c \ - $ngx_addon_dir/ngx_rtmp_amf.c \ - $ngx_addon_dir/ngx_rtmp_send.c \ - $ngx_addon_dir/ngx_rtmp_eval.c \ - $ngx_addon_dir/ngx_rtmp_receive.c \ - $ngx_addon_dir/ngx_rtmp_core_module.c \ - $ngx_addon_dir/ngx_rtmp_cmd_module.c \ - $ngx_addon_dir/ngx_rtmp_codec_module.c \ - $ngx_addon_dir/ngx_rtmp_access_module.c \ - $ngx_addon_dir/ngx_rtmp_live_module.c \ - $ngx_addon_dir/ngx_rtmp_bandwidth.c \ - $ngx_addon_dir/ngx_rtmp_exec_module.c \ - $ngx_addon_dir/ngx_rtmp_notify_module.c \ - $ngx_addon_dir/ngx_rtmp_log_module.c \ - $ngx_addon_dir/ngx_rtmp_limit_module.c \ - $ngx_addon_dir/ngx_rtmp_bitop.c \ - $ngx_addon_dir/ngx_rtmp_proxy_protocol.c \ - $ngx_addon_dir/hls/ngx_rtmp_hls_module.c \ - $ngx_addon_dir/dash/ngx_rtmp_dash_module.c \ - $ngx_addon_dir/hls/ngx_rtmp_mpegts.c \ - $ngx_addon_dir/dash/ngx_rtmp_mp4.c \ - $ngx_addon_dir/ngx_live.c \ - $ngx_addon_dir/ngx_live_relay.c \ - $ngx_addon_dir/ngx_live_relay_httpflv.c \ - $ngx_addon_dir/ngx_live_relay_rtmp.c \ - $ngx_addon_dir/ngx_live_relay_inner.c \ - $ngx_addon_dir/ngx_live_relay_simple.c \ - $ngx_addon_dir/ngx_live_relay_static.c \ - $ngx_addon_dir/ngx_live_record.c \ - $ngx_addon_dir/ngx_rtmp_shared_module.c \ - $ngx_addon_dir/ngx_rtmp_gop_module.c \ - $ngx_addon_dir/ngx_rtmp_monitor_module.c \ - $ngx_addon_dir/ngx_rtmp_dynamic.c \ - $ngx_addon_dir/ngx_rtmp_variables.c \ - $ngx_addon_dir/ngx_rtmp_record_module.c \ - $ngx_addon_dir/mpegts/ngx_mpegts_live_module.c \ - $ngx_addon_dir/mpegts/ngx_hls_live_module.c \ - $ngx_addon_dir/mpegts/ngx_mpegts_gop_module.c \ - " - - -RTMP_HTTP_SRCS=" \ - $ngx_addon_dir/ngx_rtmp_sys_stat_module.c \ - $ngx_addon_dir/ngx_rtmp_stat_module.c \ - $ngx_addon_dir/ngx_rtmp_control_module.c \ - $ngx_addon_dir/http/ngx_http_flv_live_module.c \ - $ngx_addon_dir/http/ngx_http_set_header.c \ - $ngx_addon_dir/mpegts/ngx_hls_http_module.c \ - $ngx_addon_dir/mpegts/ngx_mpegts_http_module.c \ - " - -if [ -f auto/module ] ; then - ngx_module_incs=$ngx_addon_dir - ngx_module_deps=$RTMP_DEPS - - if [ $ngx_module_link = DYNAMIC ] ; then - ngx_module_name="$RTMP_CORE_MODULES $RTMP_HTTP_MODULES" - ngx_module_srcs="$RTMP_CORE_SRCS $RTMP_HTTP_SRCS" - - . auto/module - - else - ngx_module_type=CORE - ngx_module_name=$RTMP_CORE_MODULES - ngx_module_srcs=$RTMP_CORE_SRCS - - . auto/module - - - ngx_module_type=HTTP - ngx_module_name=$RTMP_HTTP_MODULES - ngx_module_incs="$ngx_addon_dir $ngx_addon_dir/http $ngx_addon_dir/hls $ngx_addon_dir/mpegts" - ngx_module_deps= - ngx_module_srcs=$RTMP_HTTP_SRCS - - . auto/module - fi - -else - CORE_MODULES="$CORE_MODULES $RTMP_CORE_MODULES" - HTTP_MODULES="$HTTP_MODULES $RTMP_HTTP_MODULES" - - NGX_ADDON_DEPS="$NGX_ADDON_DEPS $RTMP_DEPS" - NGX_ADDON_SRCS="$NGX_ADDON_SRCS $RTMP_CORE_SRCS $RTMP_HTTP_SRCS" - - CFLAGS="$CFLAGS -I$ngx_addon_dir -I$ngx_addon_dir/http -I$ngx_addon_dir/hls -I$ngx_addon_dir/mpegts" -fi - -USE_OPENSSL=YES - diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/dash/ngx_rtmp_dash_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/dash/ngx_rtmp_dash_module.c deleted file mode 100644 index b4946066a8..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/dash/ngx_rtmp_dash_module.c +++ /dev/null @@ -1,1532 +0,0 @@ - - -#include -#include -#include -#include -#include "ngx_rtmp_live_module.h" -#include "ngx_rtmp_mp4.h" - - -static ngx_rtmp_publish_pt next_publish; -static ngx_rtmp_close_stream_pt next_close_stream; -static ngx_rtmp_stream_begin_pt next_stream_begin; -static ngx_rtmp_stream_eof_pt next_stream_eof; - - -static ngx_int_t ngx_rtmp_dash_postconfiguration(ngx_conf_t *cf); -static void * ngx_rtmp_dash_create_app_conf(ngx_conf_t *cf); -static char * ngx_rtmp_dash_merge_app_conf(ngx_conf_t *cf, - void *parent, void *child); -static ngx_int_t ngx_rtmp_dash_write_init_segments(ngx_rtmp_session_t *s); - - -#define NGX_RTMP_DASH_BUFSIZE (1024*1024) -#define NGX_RTMP_DASH_MAX_MDAT (10*1024*1024) -#define NGX_RTMP_DASH_MAX_SAMPLES 1024 -#define NGX_RTMP_DASH_DIR_ACCESS 0744 - - -typedef struct { - uint32_t timestamp; - uint32_t duration; -} ngx_rtmp_dash_frag_t; - - -typedef struct { - ngx_uint_t id; - ngx_uint_t opened; - ngx_uint_t mdat_size; - ngx_uint_t sample_count; - ngx_uint_t sample_mask; - ngx_fd_t fd; - char type; - uint32_t earliest_pres_time; - uint32_t latest_pres_time; - ngx_rtmp_mp4_sample_t samples[NGX_RTMP_DASH_MAX_SAMPLES]; -} ngx_rtmp_dash_track_t; - - -typedef struct { - ngx_str_t playlist; - ngx_str_t playlist_bak; - ngx_str_t name; - ngx_str_t stream; - time_t start_time; - - ngx_uint_t nfrags; - ngx_uint_t frag; - ngx_rtmp_dash_frag_t *frags; /* circular 2 * winfrags + 1 */ - - unsigned opened:1; - unsigned has_video:1; - unsigned has_audio:1; - - ngx_file_t video_file; - ngx_file_t audio_file; - - ngx_uint_t id; - - ngx_rtmp_dash_track_t audio; - ngx_rtmp_dash_track_t video; -} ngx_rtmp_dash_ctx_t; - - -typedef struct { - ngx_str_t path; - ngx_msec_t playlen; -} ngx_rtmp_dash_cleanup_t; - - -typedef struct { - ngx_flag_t dash; - ngx_msec_t fraglen; - ngx_msec_t playlen; - ngx_flag_t nested; - ngx_str_t path; - ngx_uint_t winfrags; - ngx_flag_t cleanup; - ngx_path_t *slot; -} ngx_rtmp_dash_app_conf_t; - - -static ngx_command_t ngx_rtmp_dash_commands[] = { - - { ngx_string("dash"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_dash_app_conf_t, dash), - NULL }, - - { ngx_string("dash_fragment"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_dash_app_conf_t, fraglen), - NULL }, - - { ngx_string("dash_path"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_dash_app_conf_t, path), - NULL }, - - { ngx_string("dash_playlist_length"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_dash_app_conf_t, playlen), - NULL }, - - { ngx_string("dash_cleanup"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_dash_app_conf_t, cleanup), - NULL }, - - { ngx_string("dash_nested"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_dash_app_conf_t, nested), - NULL }, - - ngx_null_command -}; - - -static ngx_rtmp_module_t ngx_rtmp_dash_module_ctx = { - NULL, /* preconfiguration */ - ngx_rtmp_dash_postconfiguration, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - ngx_rtmp_dash_create_app_conf, /* create location configuration */ - ngx_rtmp_dash_merge_app_conf, /* merge location configuration */ -}; - - -ngx_module_t ngx_rtmp_dash_module = { - NGX_MODULE_V1, - &ngx_rtmp_dash_module_ctx, /* module context */ - ngx_rtmp_dash_commands, /* module directives */ - NGX_RTMP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static ngx_rtmp_dash_frag_t * -ngx_rtmp_dash_get_frag(ngx_rtmp_session_t *s, ngx_int_t n) -{ - ngx_rtmp_dash_ctx_t *ctx; - ngx_rtmp_dash_app_conf_t *dacf; - - dacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_dash_module); - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module); - - return &ctx->frags[(ctx->frag + n) % (dacf->winfrags * 2 + 1)]; -} - - -static void -ngx_rtmp_dash_next_frag(ngx_rtmp_session_t *s) -{ - ngx_rtmp_dash_ctx_t *ctx; - ngx_rtmp_dash_app_conf_t *dacf; - - dacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_dash_module); - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module); - - if (ctx->nfrags == dacf->winfrags) { - ctx->frag++; - } else { - ctx->nfrags++; - } -} - - -static ngx_int_t -ngx_rtmp_dash_rename_file(u_char *src, u_char *dst) -{ - /* rename file with overwrite */ - -#if (NGX_WIN32) - return MoveFileEx((LPCTSTR) src, (LPCTSTR) dst, MOVEFILE_REPLACE_EXISTING); -#else - return ngx_rename_file(src, dst); -#endif -} - - -static ngx_int_t -ngx_rtmp_dash_write_playlist(ngx_rtmp_session_t *s) -{ - char *sep; - u_char *p, *last; - ssize_t n; - ngx_fd_t fd; - struct tm tm; - ngx_str_t noname, *name; - ngx_uint_t i; - ngx_rtmp_dash_ctx_t *ctx; - ngx_rtmp_codec_ctx_t *codec_ctx; - ngx_rtmp_dash_frag_t *f; - ngx_rtmp_dash_app_conf_t *dacf; - - static u_char buffer[NGX_RTMP_DASH_BUFSIZE]; - static u_char start_time[sizeof("1970-09-28T12:00:00Z")]; - static u_char pub_time[sizeof("1970-09-28T12:00:00Z")]; - - dacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_dash_module); - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module); - codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - - if (dacf == NULL || ctx == NULL || codec_ctx == NULL) { - return NGX_ERROR; - } - - if (ctx->id == 0) { - ngx_rtmp_dash_write_init_segments(s); - } - - fd = ngx_open_file(ctx->playlist_bak.data, NGX_FILE_WRONLY, - NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS); - - if (fd == NGX_INVALID_FILE) { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "dash: open failed: '%V'", &ctx->playlist_bak); - return NGX_ERROR; - } - -#define NGX_RTMP_DASH_MANIFEST_HEADER \ - "\n" \ - "\n" \ - " \n" - - -#define NGX_RTMP_DASH_MANIFEST_VIDEO \ - " \n" \ - " \n" \ - " \n" \ - " \n" - - -#define NGX_RTMP_DASH_MANIFEST_VIDEO_FOOTER \ - " \n" \ - " \n" \ - " \n" \ - " \n" - - -#define NGX_RTMP_DASH_MANIFEST_TIME \ - " \n" - - -#define NGX_RTMP_DASH_MANIFEST_AUDIO \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" - - -#define NGX_RTMP_DASH_MANIFEST_AUDIO_FOOTER \ - " \n" \ - " \n" \ - " \n" \ - " \n" - - -#define NGX_RTMP_DASH_MANIFEST_FOOTER \ - " \n" \ - "\n" - - ngx_libc_gmtime(ctx->start_time, &tm); - - ngx_sprintf(start_time, "%4d-%02d-%02dT%02d:%02d:%02dZ%Z", - tm.tm_year + 1900, tm.tm_mon + 1, - tm.tm_mday, tm.tm_hour, - tm.tm_min, tm.tm_sec); - - ngx_libc_gmtime(ngx_time(), &tm); - - ngx_sprintf(pub_time, "%4d-%02d-%02dT%02d:%02d:%02dZ%Z", - tm.tm_year + 1900, tm.tm_mon + 1, - tm.tm_mday, tm.tm_hour, - tm.tm_min, tm.tm_sec); - - ngx_memset(buffer, 0, sizeof(buffer)); - last = buffer + sizeof(buffer); - - p = ngx_slprintf(buffer, last, NGX_RTMP_DASH_MANIFEST_HEADER, - start_time, - pub_time, - (ngx_uint_t) (dacf->fraglen / 1000), - (ngx_uint_t) (dacf->fraglen / 1000), - (ngx_uint_t) (dacf->fraglen / 250 + 1)); - - /* - * timeShiftBufferDepth formula: - * 2 * minBufferTime + max_fragment_length + 1 - */ - - n = ngx_write_fd(fd, buffer, p - buffer); - - ngx_str_null(&noname); - - name = (dacf->nested ? &noname : &ctx->name); - sep = (dacf->nested ? "" : "-"); - - if (ctx->has_video) { - p = ngx_slprintf(buffer, last, NGX_RTMP_DASH_MANIFEST_VIDEO, - codec_ctx->width, - codec_ctx->height, - (ngx_uint_t) codec_ctx->frame_rate, - &ctx->name, - codec_ctx->avc_profile, - codec_ctx->avc_compat, - codec_ctx->avc_level, - codec_ctx->width, - codec_ctx->height, - (ngx_uint_t) codec_ctx->frame_rate, - (ngx_uint_t) (codec_ctx->video_data_rate * 1000), - name, sep, - name, sep); - - for (i = 0; i < ctx->nfrags; i++) { - f = ngx_rtmp_dash_get_frag(s, i); - p = ngx_slprintf(p, last, NGX_RTMP_DASH_MANIFEST_TIME, - f->timestamp, f->duration); - } - - p = ngx_slprintf(p, last, NGX_RTMP_DASH_MANIFEST_VIDEO_FOOTER); - - n = ngx_write_fd(fd, buffer, p - buffer); - } - - if (ctx->has_audio) { - p = ngx_slprintf(buffer, last, NGX_RTMP_DASH_MANIFEST_AUDIO, - &ctx->name, - codec_ctx->audio_codec_id == NGX_RTMP_AUDIO_AAC ? - (codec_ctx->aac_sbr ? "40.5" : "40.2") : "6b", - codec_ctx->sample_rate, - (ngx_uint_t) (codec_ctx->audio_data_rate * 1000), - name, sep, - name, sep); - - for (i = 0; i < ctx->nfrags; i++) { - f = ngx_rtmp_dash_get_frag(s, i); - p = ngx_slprintf(p, last, NGX_RTMP_DASH_MANIFEST_TIME, - f->timestamp, f->duration); - } - - p = ngx_slprintf(p, last, NGX_RTMP_DASH_MANIFEST_AUDIO_FOOTER); - - n = ngx_write_fd(fd, buffer, p - buffer); - } - - p = ngx_slprintf(buffer, last, NGX_RTMP_DASH_MANIFEST_FOOTER); - n = ngx_write_fd(fd, buffer, p - buffer); - - if (n < 0) { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "dash: write failed: '%V'", &ctx->playlist_bak); - ngx_close_file(fd); - return NGX_ERROR; - } - - ngx_close_file(fd); - - if (ngx_rtmp_dash_rename_file(ctx->playlist_bak.data, ctx->playlist.data) - == NGX_FILE_ERROR) - { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "dash: rename failed: '%V'->'%V'", - &ctx->playlist_bak, &ctx->playlist); - return NGX_ERROR; - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_dash_write_init_segments(ngx_rtmp_session_t *s) -{ - ngx_fd_t fd; - ngx_int_t rc; - ngx_buf_t b; - ngx_rtmp_dash_ctx_t *ctx; - ngx_rtmp_codec_ctx_t *codec_ctx; - - static u_char buffer[NGX_RTMP_DASH_BUFSIZE]; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module); - codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - - if (ctx == NULL || codec_ctx == NULL) { - return NGX_ERROR; - } - - /* init video */ - - *ngx_sprintf(ctx->stream.data + ctx->stream.len, "init.m4v") = 0; - - fd = ngx_open_file(ctx->stream.data, NGX_FILE_RDWR, NGX_FILE_TRUNCATE, - NGX_FILE_DEFAULT_ACCESS); - - if (fd == NGX_INVALID_FILE) { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "dash: error creating video init file"); - return NGX_ERROR; - } - - b.start = buffer; - b.end = b.start + sizeof(buffer); - b.pos = b.last = b.start; - - ngx_rtmp_mp4_write_ftyp(&b); - ngx_rtmp_mp4_write_moov(s, &b, NGX_RTMP_MP4_VIDEO_TRACK); - - rc = ngx_write_fd(fd, b.start, (size_t) (b.last - b.start)); - if (rc == NGX_ERROR) { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "dash: writing video init failed"); - } - - ngx_close_file(fd); - - /* init audio */ - - *ngx_sprintf(ctx->stream.data + ctx->stream.len, "init.m4a") = 0; - - fd = ngx_open_file(ctx->stream.data, NGX_FILE_RDWR, NGX_FILE_TRUNCATE, - NGX_FILE_DEFAULT_ACCESS); - - if (fd == NGX_INVALID_FILE) { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "dash: error creating dash audio init file"); - return NGX_ERROR; - } - - b.pos = b.last = b.start; - - ngx_rtmp_mp4_write_ftyp(&b); - ngx_rtmp_mp4_write_moov(s, &b, NGX_RTMP_MP4_AUDIO_TRACK); - - rc = ngx_write_fd(fd, b.start, (size_t) (b.last - b.start)); - if (rc == NGX_ERROR) { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "dash: writing audio init failed"); - } - - ngx_close_file(fd); - - return NGX_OK; -} - - -static void -ngx_rtmp_dash_close_fragment(ngx_rtmp_session_t *s, ngx_rtmp_dash_track_t *t) -{ - u_char *pos, *pos1; - size_t left; - ssize_t n; - ngx_fd_t fd; - ngx_buf_t b; - ngx_rtmp_dash_ctx_t *ctx; - ngx_rtmp_dash_frag_t *f; - - static u_char buffer[NGX_RTMP_DASH_BUFSIZE]; - - if (!t->opened) { - return; - } - - ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->log, 0, - "dash: close fragment id=%ui, type=%c, pts=%uD", - t->id, t->type, t->earliest_pres_time); - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module); - - b.start = buffer; - b.end = buffer + sizeof(buffer); - b.pos = b.last = b.start; - - ngx_rtmp_mp4_write_styp(&b); - - pos = b.last; - b.last += 44; /* leave room for sidx */ - - ngx_rtmp_mp4_write_moof(&b, t->earliest_pres_time, t->sample_count, - t->samples, t->sample_mask, t->id); - pos1 = b.last; - b.last = pos; - - ngx_rtmp_mp4_write_sidx(&b, t->mdat_size + 8 + (pos1 - (pos + 44)), - t->earliest_pres_time, t->latest_pres_time); - b.last = pos1; - ngx_rtmp_mp4_write_mdat(&b, t->mdat_size + 8); - - /* move the data down to make room for the headers */ - - f = ngx_rtmp_dash_get_frag(s, ctx->nfrags); - - *ngx_sprintf(ctx->stream.data + ctx->stream.len, "%uD.m4%c", - f->timestamp, t->type) = 0; - - fd = ngx_open_file(ctx->stream.data, NGX_FILE_RDWR, - NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS); - - if (fd == NGX_INVALID_FILE) { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "dash: error creating dash temp video file"); - goto done; - } - - if (ngx_write_fd(fd, b.pos, (size_t) (b.last - b.pos)) == NGX_ERROR) { - goto done; - } - - left = (size_t) t->mdat_size; - -#if (NGX_WIN32) - if (SetFilePointer(t->fd, 0, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "dash: SetFilePointer error"); - goto done; - } -#else - if (lseek(t->fd, 0, SEEK_SET) == -1) { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "dash: lseek error"); - goto done; - } -#endif - - while (left > 0) { - - n = ngx_read_fd(t->fd, buffer, ngx_min(sizeof(buffer), left)); - if (n == NGX_ERROR) { - break; - } - - n = ngx_write_fd(fd, buffer, (size_t) n); - if (n == NGX_ERROR) { - break; - } - - left -= n; - } - -done: - - if (fd != NGX_INVALID_FILE) { - ngx_close_file(fd); - } - - ngx_close_file(t->fd); - - t->fd = NGX_INVALID_FILE; - t->opened = 0; -} - - -static ngx_int_t -ngx_rtmp_dash_close_fragments(ngx_rtmp_session_t *s) -{ - ngx_rtmp_dash_ctx_t *ctx; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module); - if (ctx == NULL || !ctx->opened) { - return NGX_OK; - } - - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->log, 0, - "dash: close fragments"); - - ngx_rtmp_dash_close_fragment(s, &ctx->video); - ngx_rtmp_dash_close_fragment(s, &ctx->audio); - - ngx_rtmp_dash_next_frag(s); - - ngx_rtmp_dash_write_playlist(s); - - ctx->id++; - ctx->opened = 0; - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_dash_open_fragment(ngx_rtmp_session_t *s, ngx_rtmp_dash_track_t *t, - ngx_uint_t id, char type) -{ - ngx_rtmp_dash_ctx_t *ctx; - - if (t->opened) { - return NGX_OK; - } - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->log, 0, - "dash: open fragment id=%ui, type='%c'", id, type); - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module); - - *ngx_sprintf(ctx->stream.data + ctx->stream.len, "raw.m4%c", type) = 0; - - t->fd = ngx_open_file(ctx->stream.data, NGX_FILE_RDWR, - NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS); - - if (t->fd == NGX_INVALID_FILE) { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "dash: error creating fragment file"); - return NGX_ERROR; - } - - t->id = id; - t->type = type; - t->sample_count = 0; - t->earliest_pres_time = 0; - t->latest_pres_time = 0; - t->mdat_size = 0; - t->opened = 1; - - if (type == 'v') { - t->sample_mask = NGX_RTMP_MP4_SAMPLE_SIZE| - NGX_RTMP_MP4_SAMPLE_DURATION| - NGX_RTMP_MP4_SAMPLE_DELAY| - NGX_RTMP_MP4_SAMPLE_KEY; - } else { - t->sample_mask = NGX_RTMP_MP4_SAMPLE_SIZE| - NGX_RTMP_MP4_SAMPLE_DURATION; - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_dash_open_fragments(ngx_rtmp_session_t *s) -{ - ngx_rtmp_dash_ctx_t *ctx; - - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->log, 0, - "dash: open fragments"); - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module); - - if (ctx->opened) { - return NGX_OK; - } - - ngx_rtmp_dash_open_fragment(s, &ctx->video, ctx->id, 'v'); - - ngx_rtmp_dash_open_fragment(s, &ctx->audio, ctx->id, 'a'); - - ctx->opened = 1; - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_dash_ensure_directory(ngx_rtmp_session_t *s) -{ - size_t len; - ngx_file_info_t fi; - ngx_rtmp_dash_ctx_t *ctx; - ngx_rtmp_dash_app_conf_t *dacf; - - static u_char path[NGX_MAX_PATH + 1]; - - dacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_dash_module); - - *ngx_snprintf(path, sizeof(path) - 1, "%V", &dacf->path) = 0; - - if (ngx_file_info(path, &fi) == NGX_FILE_ERROR) { - - if (ngx_errno != NGX_ENOENT) { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "dash: " ngx_file_info_n " failed on '%V'", - &dacf->path); - return NGX_ERROR; - } - - /* ENOENT */ - - if (ngx_create_dir(path, NGX_RTMP_DASH_DIR_ACCESS) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "dash: " ngx_create_dir_n " failed on '%V'", - &dacf->path); - return NGX_ERROR; - } - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "dash: directory '%V' created", &dacf->path); - - } else { - - if (!ngx_is_dir(&fi)) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "dash: '%V' exists and is not a directory", - &dacf->path); - return NGX_ERROR; - } - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "dash: directory '%V' exists", &dacf->path); - } - - if (!dacf->nested) { - return NGX_OK; - } - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module); - - len = dacf->path.len; - if (dacf->path.data[len - 1] == '/') { - len--; - } - - *ngx_snprintf(path, sizeof(path) - 1, "%*s/%V", len, dacf->path.data, - &ctx->name) = 0; - - if (ngx_file_info(path, &fi) != NGX_FILE_ERROR) { - - if (ngx_is_dir(&fi)) { - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "dash: directory '%s' exists", path); - return NGX_OK; - } - - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "dash: '%s' exists and is not a directory", path); - - return NGX_ERROR; - } - - if (ngx_errno != NGX_ENOENT) { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "dash: " ngx_file_info_n " failed on '%s'", path); - return NGX_ERROR; - } - - /* NGX_ENOENT */ - - if (ngx_create_dir(path, NGX_RTMP_DASH_DIR_ACCESS) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "dash: " ngx_create_dir_n " failed on '%s'", path); - return NGX_ERROR; - } - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "dash: directory '%s' created", path); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_dash_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v) -{ - u_char *p; - size_t len; - ngx_rtmp_dash_ctx_t *ctx; - ngx_rtmp_dash_frag_t *f; - ngx_rtmp_dash_app_conf_t *dacf; - - dacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_dash_module); - if (dacf == NULL || !dacf->dash || dacf->path.len == 0) { - goto next; - } - - if (s->interprocess) { - goto next; - } - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->log, 0, - "dash: publish: name='%s' type='%s'", v->name, v->type); - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module); - - if (ctx == NULL) { - ctx = ngx_pcalloc(s->pool, sizeof(ngx_rtmp_dash_ctx_t)); - if (ctx == NULL) { - goto next; - } - ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_dash_module); - - } else { - if (ctx->opened) { - goto next; - } - - f = ctx->frags; - ngx_memzero(ctx, sizeof(ngx_rtmp_dash_ctx_t)); - ctx->frags = f; - } - - if (ctx->frags == NULL) { - ctx->frags = ngx_pcalloc(s->pool, - sizeof(ngx_rtmp_dash_frag_t) * - (dacf->winfrags * 2 + 1)); - if (ctx->frags == NULL) { - return NGX_ERROR; - } - } - - ctx->id = 0; - - if (ngx_strstr(v->name, "..")) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "dash: bad stream name: '%s'", v->name); - return NGX_ERROR; - } - - ctx->name.len = ngx_strlen(v->name); - ctx->name.data = ngx_palloc(s->pool, ctx->name.len + 1); - - if (ctx->name.data == NULL) { - return NGX_ERROR; - } - - *ngx_cpymem(ctx->name.data, v->name, ctx->name.len) = 0; - - len = dacf->path.len + 1 + ctx->name.len + sizeof(".mpd"); - if (dacf->nested) { - len += sizeof("/index") - 1; - } - - ctx->playlist.data = ngx_palloc(s->pool, len); - p = ngx_cpymem(ctx->playlist.data, dacf->path.data, dacf->path.len); - - if (p[-1] != '/') { - *p++ = '/'; - } - - p = ngx_cpymem(p, ctx->name.data, ctx->name.len); - - /* - * ctx->stream holds initial part of stream file path - * however the space for the whole stream path - * is allocated - */ - - ctx->stream.len = p - ctx->playlist.data + 1; - ctx->stream.data = ngx_palloc(s->pool, - ctx->stream.len + NGX_INT32_LEN + - sizeof(".m4x")); - - ngx_memcpy(ctx->stream.data, ctx->playlist.data, ctx->stream.len - 1); - ctx->stream.data[ctx->stream.len - 1] = (dacf->nested ? '/' : '-'); - - if (dacf->nested) { - p = ngx_cpymem(p, "/index.mpd", sizeof("/index.mpd") - 1); - } else { - p = ngx_cpymem(p, ".mpd", sizeof(".mpd") - 1); - } - - ctx->playlist.len = p - ctx->playlist.data; - - *p = 0; - - /* playlist bak (new playlist) path */ - - ctx->playlist_bak.data = ngx_palloc(s->pool, - ctx->playlist.len + sizeof(".bak")); - p = ngx_cpymem(ctx->playlist_bak.data, ctx->playlist.data, - ctx->playlist.len); - p = ngx_cpymem(p, ".bak", sizeof(".bak") - 1); - - ctx->playlist_bak.len = p - ctx->playlist_bak.data; - - *p = 0; - - ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->log, 0, - "dash: playlist='%V' playlist_bak='%V' stream_pattern='%V'", - &ctx->playlist, &ctx->playlist_bak, &ctx->stream); - - ctx->start_time = ngx_time(); - - if (ngx_rtmp_dash_ensure_directory(s) != NGX_OK) { - return NGX_ERROR; - } - -next: - return next_publish(s, v); -} - - -static ngx_int_t -ngx_rtmp_dash_close_stream(ngx_rtmp_session_t *s, ngx_rtmp_close_stream_t *v) -{ - ngx_rtmp_dash_ctx_t *ctx; - ngx_rtmp_dash_app_conf_t *dacf; - - dacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_dash_module); - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module); - - if (dacf == NULL || !dacf->dash || ctx == NULL) { - goto next; - } - - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->log, 0, - "dash: delete stream"); - - ngx_rtmp_dash_close_fragments(s); - -next: - return next_close_stream(s, v); -} - - -static void -ngx_rtmp_dash_update_fragments(ngx_rtmp_session_t *s, ngx_int_t boundary, - uint32_t timestamp) -{ - int32_t d; - ngx_int_t hit; - ngx_rtmp_dash_ctx_t *ctx; - ngx_rtmp_dash_frag_t *f; - ngx_rtmp_dash_app_conf_t *dacf; - - dacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_dash_module); - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module); - f = ngx_rtmp_dash_get_frag(s, ctx->nfrags); - - d = (int32_t) (timestamp - f->timestamp); - - if (d >= 0) { - - f->duration = timestamp - f->timestamp; - hit = (f->duration >= dacf->fraglen); - - /* keep fragment lengths within 2x factor for dash.js */ - if (f->duration >= dacf->fraglen * 2) { - boundary = 1; - } - - } else { - - /* sometimes clients generate slightly unordered frames */ - - hit = (-d > 1000); - } - - if (ctx->has_video && !hit) { - boundary = 0; - } - - if (!ctx->has_video && ctx->has_audio) { - boundary = hit; - } - - if (ctx->audio.mdat_size >= NGX_RTMP_DASH_MAX_MDAT) { - boundary = 1; - } - - if (ctx->video.mdat_size >= NGX_RTMP_DASH_MAX_MDAT) { - boundary = 1; - } - - if (!ctx->opened) { - boundary = 1; - } - - if (boundary) { - ngx_rtmp_dash_close_fragments(s); - ngx_rtmp_dash_open_fragments(s); - - f = ngx_rtmp_dash_get_frag(s, ctx->nfrags); - f->timestamp = timestamp; - } -} - - -static ngx_int_t -ngx_rtmp_dash_append(ngx_rtmp_session_t *s, ngx_chain_t *in, - ngx_rtmp_dash_track_t *t, ngx_int_t key, uint32_t timestamp, uint32_t delay) -{ - u_char *p; - size_t size, bsize; - ngx_rtmp_mp4_sample_t *smpl; - - static u_char buffer[NGX_RTMP_DASH_BUFSIZE]; - - p = buffer; - size = 0; - - for (; in && size < sizeof(buffer); in = in->next) { - - bsize = (size_t) (in->buf->last - in->buf->pos); - if (size + bsize > sizeof(buffer)) { - bsize = (size_t) (sizeof(buffer) - size); - } - - p = ngx_cpymem(p, in->buf->pos, bsize); - size += bsize; - } - - ngx_rtmp_dash_update_fragments(s, key, timestamp); - - if (t->sample_count == 0) { - t->earliest_pres_time = timestamp; - } - - t->latest_pres_time = timestamp; - - if (t->sample_count < NGX_RTMP_DASH_MAX_SAMPLES) { - - if (ngx_write_fd(t->fd, buffer, size) == NGX_ERROR) { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "dash: " ngx_write_fd_n " failed"); - return NGX_ERROR; - } - - smpl = &t->samples[t->sample_count]; - - smpl->delay = delay; - smpl->size = (uint32_t) size; - smpl->duration = 0; - smpl->timestamp = timestamp; - smpl->key = (key ? 1 : 0); - - if (t->sample_count > 0) { - smpl = &t->samples[t->sample_count - 1]; - smpl->duration = timestamp - smpl->timestamp; - } - - t->sample_count++; - t->mdat_size += (ngx_uint_t) size; - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_dash_audio(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - u_char htype; - ngx_rtmp_dash_ctx_t *ctx; - ngx_rtmp_codec_ctx_t *codec_ctx; - ngx_rtmp_dash_app_conf_t *dacf; - - dacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_dash_module); - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module); - codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - - if (dacf == NULL || !dacf->dash || ctx == NULL || - codec_ctx == NULL || h->mlen < 2) - { - return NGX_OK; - } - - /* Only AAC is supported */ - - if (codec_ctx->audio_codec_id != NGX_RTMP_AUDIO_AAC || - codec_ctx->aac_header == NULL) - { - return NGX_OK; - } - - if (in->buf->last - in->buf->pos < 2) { - return NGX_ERROR; - } - - /* skip AAC config */ - - htype = in->buf->pos[1]; - if (htype != 1) { - return NGX_OK; - } - - ctx->has_audio = 1; - - /* skip RTMP & AAC headers */ - - in->buf->pos += 2; - - return ngx_rtmp_dash_append(s, in, &ctx->audio, 0, h->timestamp, 0); -} - - -static ngx_int_t -ngx_rtmp_dash_video(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - u_char *p; - uint8_t ftype, htype; - uint32_t delay; - ngx_rtmp_dash_ctx_t *ctx; - ngx_rtmp_codec_ctx_t *codec_ctx; - ngx_rtmp_dash_app_conf_t *dacf; - - dacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_dash_module); - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module); - codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - - if (dacf == NULL || !dacf->dash || ctx == NULL || codec_ctx == NULL || - codec_ctx->avc_header == NULL || h->mlen < 5) - { - return NGX_OK; - } - - /* Only H264 is supported */ - - if (codec_ctx->video_codec_id != NGX_RTMP_VIDEO_H264) { - return NGX_OK; - } - - if (in->buf->last - in->buf->pos < 5) { - return NGX_ERROR; - } - - ftype = (in->buf->pos[0] & 0xf0) >> 4; - - /* skip AVC config */ - - htype = in->buf->pos[1]; - if (htype != 1) { - return NGX_OK; - } - - p = (u_char *) &delay; - - p[0] = in->buf->pos[4]; - p[1] = in->buf->pos[3]; - p[2] = in->buf->pos[2]; - p[3] = 0; - - ctx->has_video = 1; - - /* skip RTMP & H264 headers */ - - in->buf->pos += 5; - - return ngx_rtmp_dash_append(s, in, &ctx->video, ftype == 1, h->timestamp, - delay); -} - - -static ngx_int_t -ngx_rtmp_dash_stream_begin(ngx_rtmp_session_t *s, ngx_rtmp_stream_begin_t *v) -{ - return next_stream_begin(s, v); -} - - -static ngx_int_t -ngx_rtmp_dash_stream_eof(ngx_rtmp_session_t *s, ngx_rtmp_stream_eof_t *v) -{ - ngx_rtmp_dash_close_fragments(s); - - return next_stream_eof(s, v); -} - - -static ngx_int_t -ngx_rtmp_dash_cleanup_dir(ngx_str_t *ppath, ngx_msec_t playlen) -{ - time_t mtime, max_age; - u_char *p; - u_char path[NGX_MAX_PATH + 1], mpd_path[NGX_MAX_PATH + 1]; - ngx_dir_t dir; - ngx_err_t err; - ngx_str_t name, spath, mpd; - ngx_int_t nentries, nerased; - ngx_file_info_t fi; - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, ngx_cycle->log, 0, - "dash: cleanup path='%V' playlen=%M", ppath, playlen); - - if (ngx_open_dir(ppath, &dir) != NGX_OK) { - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, ngx_cycle->log, ngx_errno, - "dash: cleanup open dir failed '%V'", ppath); - return NGX_ERROR; - } - - nentries = 0; - nerased = 0; - - for ( ;; ) { - ngx_set_errno(0); - - if (ngx_read_dir(&dir) == NGX_ERROR) { - err = ngx_errno; - - if (ngx_close_dir(&dir) == NGX_ERROR) { - ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, ngx_errno, - "dash: cleanup " ngx_close_dir_n " \"%V\" failed", - ppath); - } - - if (err == NGX_ENOMOREFILES) { - return nentries - nerased; - } - - ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, err, - "dash: cleanup " ngx_read_dir_n - " '%V' failed", ppath); - return NGX_ERROR; - } - - name.data = ngx_de_name(&dir); - if (name.data[0] == '.') { - continue; - } - - name.len = ngx_de_namelen(&dir); - - p = ngx_snprintf(path, sizeof(path) - 1, "%V/%V", ppath, &name); - *p = 0; - - spath.data = path; - spath.len = p - path; - - nentries++; - - if (!dir.valid_info && ngx_de_info(path, &dir) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, ngx_errno, - "dash: cleanup " ngx_de_info_n " \"%V\" failed", - &spath); - - continue; - } - - if (ngx_de_is_dir(&dir)) { - - if (ngx_rtmp_dash_cleanup_dir(&spath, playlen) == 0) { - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, ngx_cycle->log, 0, - "dash: cleanup dir '%V'", &name); - - /* - * null-termination gets spoiled in win32 - * version of ngx_open_dir - */ - - *p = 0; - - if (ngx_delete_dir(path) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, ngx_errno, - "dash: cleanup " ngx_delete_dir_n - " failed on '%V'", &spath); - } else { - nerased++; - } - } - - continue; - } - - if (!ngx_de_is_file(&dir)) { - continue; - } - - if (name.len >= 8 && name.data[name.len - 8] == 'i' && - name.data[name.len - 7] == 'n' && - name.data[name.len - 6] == 'i' && - name.data[name.len - 5] == 't' && - name.data[name.len - 4] == '.' && - name.data[name.len - 3] == 'm' && - name.data[name.len - 2] == '4') - { - if (name.len == 8) { - ngx_str_set(&mpd, "index"); - } else { - mpd.data = name.data; - mpd.len = name.len - 9; - } - - p = ngx_snprintf(mpd_path, sizeof(mpd_path) - 1, "%V/%V.mpd", - ppath, &mpd); - *p = 0; - - if (ngx_file_info(mpd_path, &fi) != NGX_FILE_ERROR) { - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, ngx_cycle->log, 0, - "dash: cleanup '%V' delayed, mpd exists '%s'", - &name, mpd_path); - continue; - } - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, ngx_cycle->log, 0, - "dash: cleanup '%V' allowed, mpd missing '%s'", - &name, mpd_path); - - max_age = 0; - - } else if (name.len >= 4 && name.data[name.len - 4] == '.' && - name.data[name.len - 3] == 'm' && - name.data[name.len - 2] == '4' && - name.data[name.len - 1] == 'v') - { - max_age = playlen / 500; - - } else if (name.len >= 4 && name.data[name.len - 4] == '.' && - name.data[name.len - 3] == 'm' && - name.data[name.len - 2] == '4' && - name.data[name.len - 1] == 'a') - { - max_age = playlen / 500; - - } else if (name.len >= 4 && name.data[name.len - 4] == '.' && - name.data[name.len - 3] == 'm' && - name.data[name.len - 2] == 'p' && - name.data[name.len - 1] == 'd') - { - max_age = playlen / 500; - - } else if (name.len >= 4 && name.data[name.len - 4] == '.' && - name.data[name.len - 3] == 'r' && - name.data[name.len - 2] == 'a' && - name.data[name.len - 1] == 'w') - { - max_age = playlen / 1000; - - } else { - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, ngx_cycle->log, 0, - "dash: cleanup skip unknown file type '%V'", &name); - continue; - } - - mtime = ngx_de_mtime(&dir); - if (mtime + max_age > ngx_cached_time->sec) { - continue; - } - - ngx_log_debug3(NGX_LOG_DEBUG_RTMP, ngx_cycle->log, 0, - "dash: cleanup '%V' mtime=%T age=%T", - &name, mtime, ngx_cached_time->sec - mtime); - - if (ngx_delete_file(path) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, ngx_errno, - "dash: cleanup " ngx_delete_file_n " failed on '%V'", - &spath); - continue; - } - - nerased++; - } -} - - -#if (nginx_version >= 1011005) -static ngx_msec_t -#else -static time_t -#endif -ngx_rtmp_dash_cleanup(void *data) -{ - ngx_rtmp_dash_cleanup_t *cleanup = data; - - ngx_rtmp_dash_cleanup_dir(&cleanup->path, cleanup->playlen); - -#if (nginx_version >= 1011005) - return cleanup->playlen * 2; -#else - return cleanup->playlen / 500; -#endif -} - - -static void * -ngx_rtmp_dash_create_app_conf(ngx_conf_t *cf) -{ - ngx_rtmp_dash_app_conf_t *conf; - - conf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_dash_app_conf_t)); - if (conf == NULL) { - return NULL; - } - - conf->dash = NGX_CONF_UNSET; - conf->fraglen = NGX_CONF_UNSET_MSEC; - conf->playlen = NGX_CONF_UNSET_MSEC; - conf->cleanup = NGX_CONF_UNSET; - conf->nested = NGX_CONF_UNSET; - - return conf; -} - - -static char * -ngx_rtmp_dash_merge_app_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_rtmp_dash_app_conf_t *prev = parent; - ngx_rtmp_dash_app_conf_t *conf = child; - ngx_rtmp_dash_cleanup_t *cleanup; - - ngx_conf_merge_value(conf->dash, prev->dash, 0); - ngx_conf_merge_msec_value(conf->fraglen, prev->fraglen, 5000); - ngx_conf_merge_msec_value(conf->playlen, prev->playlen, 30000); - ngx_conf_merge_value(conf->cleanup, prev->cleanup, 1); - ngx_conf_merge_value(conf->nested, prev->nested, 0); - - if (conf->fraglen) { - conf->winfrags = conf->playlen / conf->fraglen; - } - - /* schedule cleanup */ - - if (conf->dash && conf->path.len && conf->cleanup) { - if (conf->path.data[conf->path.len - 1] == '/') { - conf->path.len--; - } - - cleanup = ngx_pcalloc(cf->pool, sizeof(*cleanup)); - if (cleanup == NULL) { - return NGX_CONF_ERROR; - } - - cleanup->path = conf->path; - cleanup->playlen = conf->playlen; - - conf->slot = ngx_pcalloc(cf->pool, sizeof(*conf->slot)); - if (conf->slot == NULL) { - return NGX_CONF_ERROR; - } - - conf->slot->manager = ngx_rtmp_dash_cleanup; - conf->slot->name = conf->path; - conf->slot->data = cleanup; - conf->slot->conf_file = cf->conf_file->file.name.data; - conf->slot->line = cf->conf_file->line; - - if (ngx_add_path(cf, &conf->slot) != NGX_OK) { - return NGX_CONF_ERROR; - } - } - - ngx_conf_merge_str_value(conf->path, prev->path, ""); - - return NGX_CONF_OK; -} - - -static ngx_int_t -ngx_rtmp_dash_postconfiguration(ngx_conf_t *cf) -{ - ngx_rtmp_handler_pt *h; - ngx_rtmp_core_main_conf_t *cmcf; - - cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module); - - h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_VIDEO]); - *h = ngx_rtmp_dash_video; - - h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_AUDIO]); - *h = ngx_rtmp_dash_audio; - - next_publish = ngx_rtmp_publish; - ngx_rtmp_publish = ngx_rtmp_dash_publish; - - next_close_stream = ngx_rtmp_close_stream; - ngx_rtmp_close_stream = ngx_rtmp_dash_close_stream; - - next_stream_begin = ngx_rtmp_stream_begin; - ngx_rtmp_stream_begin = ngx_rtmp_dash_stream_begin; - - next_stream_eof = ngx_rtmp_stream_eof; - ngx_rtmp_stream_eof = ngx_rtmp_dash_stream_eof; - - return NGX_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/dash/ngx_rtmp_mp4.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/dash/ngx_rtmp_mp4.c deleted file mode 100644 index 98efe14dcf..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/dash/ngx_rtmp_mp4.c +++ /dev/null @@ -1,1167 +0,0 @@ - - -#include -#include -#include "ngx_rtmp_mp4.h" -#include - - -static ngx_int_t -ngx_rtmp_mp4_field_32(ngx_buf_t *b, uint32_t n) -{ - u_char bytes[4]; - - bytes[0] = ((uint32_t) n >> 24) & 0xFF; - bytes[1] = ((uint32_t) n >> 16) & 0xFF; - bytes[2] = ((uint32_t) n >> 8) & 0xFF; - bytes[3] = (uint32_t) n & 0xFF; - - if (b->last + sizeof(bytes) > b->end) { - return NGX_ERROR; - } - - b->last = ngx_cpymem(b->last, bytes, sizeof(bytes)); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_field_24(ngx_buf_t *b, uint32_t n) -{ - u_char bytes[3]; - - bytes[0] = ((uint32_t) n >> 16) & 0xFF; - bytes[1] = ((uint32_t) n >> 8) & 0xFF; - bytes[2] = (uint32_t) n & 0xFF; - - if (b->last + sizeof(bytes) > b->end) { - return NGX_ERROR; - } - - b->last = ngx_cpymem(b->last, bytes, sizeof(bytes)); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_field_16(ngx_buf_t *b, uint16_t n) -{ - u_char bytes[2]; - - bytes[0] = ((uint32_t) n >> 8) & 0xFF; - bytes[1] = (uint32_t) n & 0xFF; - - if (b->last + sizeof(bytes) > b->end) { - return NGX_ERROR; - } - - b->last = ngx_cpymem(b->last, bytes, sizeof(bytes)); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_field_8(ngx_buf_t *b, uint8_t n) -{ - u_char bytes[1]; - - bytes[0] = n & 0xFF; - - if (b->last + sizeof(bytes) > b->end) { - return NGX_ERROR; - } - - b->last = ngx_cpymem(b->last, bytes, sizeof(bytes)); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_put_descr(ngx_buf_t *b, int tag, size_t size) -{ - ngx_rtmp_mp4_field_8(b, (uint8_t) tag); - ngx_rtmp_mp4_field_8(b, size & 0x7F); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_data(ngx_buf_t *b, void *data, size_t n) -{ - if (b->last + n > b->end) { - return NGX_ERROR; - } - - b->last = ngx_cpymem(b->last, (u_char *) data, n); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_box(ngx_buf_t *b, const char box[4]) -{ - if (b->last + 4 > b->end) { - return NGX_ERROR; - } - - b->last = ngx_cpymem(b->last, (u_char *) box, 4); - - return NGX_OK; -} - - -static u_char * -ngx_rtmp_mp4_start_box(ngx_buf_t *b, const char box[4]) -{ - u_char *p; - - p = b->last; - - if (ngx_rtmp_mp4_field_32(b, 0) != NGX_OK) { - return NULL; - } - - if (ngx_rtmp_mp4_box(b, box) != NGX_OK) { - return NULL; - } - - return p; -} - - -static ngx_int_t -ngx_rtmp_mp4_update_box_size(ngx_buf_t *b, u_char *p) -{ - u_char *curpos; - - if (p == NULL) { - return NGX_ERROR; - } - - curpos = b->last; - - b->last = p; - - ngx_rtmp_mp4_field_32(b, (uint32_t) (curpos - p)); - - b->last = curpos; - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_write_matrix(ngx_buf_t *buf, uint32_t a, uint32_t b, uint32_t c, - uint32_t d, uint32_t tx, uint32_t ty) -{ - -/* - * transformation matrix - * |a b u| - * |c d v| - * |tx ty w| - */ - - ngx_rtmp_mp4_field_32(buf, a << 16); /* 16.16 format */ - ngx_rtmp_mp4_field_32(buf, b << 16); /* 16.16 format */ - ngx_rtmp_mp4_field_32(buf, 0); /* u in 2.30 format */ - ngx_rtmp_mp4_field_32(buf, c << 16); /* 16.16 format */ - ngx_rtmp_mp4_field_32(buf, d << 16); /* 16.16 format */ - ngx_rtmp_mp4_field_32(buf, 0); /* v in 2.30 format */ - ngx_rtmp_mp4_field_32(buf, tx << 16); /* 16.16 format */ - ngx_rtmp_mp4_field_32(buf, ty << 16); /* 16.16 format */ - ngx_rtmp_mp4_field_32(buf, 1 << 30); /* w in 2.30 format */ - - return NGX_OK; -} - - -ngx_int_t -ngx_rtmp_mp4_write_ftyp(ngx_buf_t *b) -{ - u_char *pos; - - pos = ngx_rtmp_mp4_start_box(b, "ftyp"); - - /* major brand */ - ngx_rtmp_mp4_box(b, "iso6"); - - /* minor version */ - ngx_rtmp_mp4_field_32(b, 1); - - /* compatible brands */ - ngx_rtmp_mp4_box(b, "isom"); - ngx_rtmp_mp4_box(b, "iso6"); - ngx_rtmp_mp4_box(b, "dash"); - - ngx_rtmp_mp4_update_box_size(b, pos); - - return NGX_OK; -} - - -ngx_int_t -ngx_rtmp_mp4_write_styp(ngx_buf_t *b) -{ - u_char *pos; - - pos = ngx_rtmp_mp4_start_box(b, "styp"); - - /* major brand */ - ngx_rtmp_mp4_box(b, "iso6"); - - /* minor version */ - ngx_rtmp_mp4_field_32(b, 1); - - /* compatible brands */ - ngx_rtmp_mp4_box(b, "isom"); - ngx_rtmp_mp4_box(b, "iso6"); - ngx_rtmp_mp4_box(b, "dash"); - - ngx_rtmp_mp4_update_box_size(b, pos); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_write_mvhd(ngx_buf_t *b) -{ - u_char *pos; - - pos = ngx_rtmp_mp4_start_box(b, "mvhd"); - - /* version */ - ngx_rtmp_mp4_field_32(b, 0); - - /* creation time */ - ngx_rtmp_mp4_field_32(b, 0); - - /* modification time */ - ngx_rtmp_mp4_field_32(b, 0); - - /* timescale */ - ngx_rtmp_mp4_field_32(b, 1000); - - /* duration */ - ngx_rtmp_mp4_field_32(b, 0); - - /* reserved */ - ngx_rtmp_mp4_field_32(b, 0x00010000); - ngx_rtmp_mp4_field_16(b, 0x0100); - ngx_rtmp_mp4_field_16(b, 0); - ngx_rtmp_mp4_field_32(b, 0); - ngx_rtmp_mp4_field_32(b, 0); - - ngx_rtmp_mp4_write_matrix(b, 1, 0, 0, 1, 0, 0); - - /* reserved */ - ngx_rtmp_mp4_field_32(b, 0); - ngx_rtmp_mp4_field_32(b, 0); - ngx_rtmp_mp4_field_32(b, 0); - ngx_rtmp_mp4_field_32(b, 0); - ngx_rtmp_mp4_field_32(b, 0); - ngx_rtmp_mp4_field_32(b, 0); - - /* next track id */ - ngx_rtmp_mp4_field_32(b, 1); - - ngx_rtmp_mp4_update_box_size(b, pos); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_write_tkhd(ngx_rtmp_session_t *s, ngx_buf_t *b, - ngx_rtmp_mp4_track_type_t ttype) -{ - u_char *pos; - ngx_rtmp_codec_ctx_t *codec_ctx; - - codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - - pos = ngx_rtmp_mp4_start_box(b, "tkhd"); - - /* version */ - ngx_rtmp_mp4_field_8(b, 0); - - /* flags: TrackEnabled */ - ngx_rtmp_mp4_field_24(b, 0x0000000f); - - /* creation time */ - ngx_rtmp_mp4_field_32(b, 0); - - /* modification time */ - ngx_rtmp_mp4_field_32(b, 0); - - /* track id */ - ngx_rtmp_mp4_field_32(b, 1); - - /* reserved */ - ngx_rtmp_mp4_field_32(b, 0); - - /* duration */ - ngx_rtmp_mp4_field_32(b, 0); - - /* reserved */ - ngx_rtmp_mp4_field_32(b, 0); - ngx_rtmp_mp4_field_32(b, 0); - ngx_rtmp_mp4_field_32(b, 0); - - /* reserved */ - ngx_rtmp_mp4_field_16(b, ttype == NGX_RTMP_MP4_VIDEO_TRACK ? 0 : 0x0100); - - /* reserved */ - ngx_rtmp_mp4_field_16(b, 0); - - ngx_rtmp_mp4_write_matrix(b, 1, 0, 0, 1, 0, 0); - - if (ttype == NGX_RTMP_MP4_VIDEO_TRACK) { - ngx_rtmp_mp4_field_32(b, (uint32_t) codec_ctx->width << 16); - ngx_rtmp_mp4_field_32(b, (uint32_t) codec_ctx->height << 16); - } else { - ngx_rtmp_mp4_field_32(b, 0); - ngx_rtmp_mp4_field_32(b, 0); - } - - ngx_rtmp_mp4_update_box_size(b, pos); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_write_mdhd(ngx_buf_t *b) -{ - u_char *pos; - - pos = ngx_rtmp_mp4_start_box(b, "mdhd"); - - /* version */ - ngx_rtmp_mp4_field_32(b, 0); - - /* creation time */ - ngx_rtmp_mp4_field_32(b, 0); - - /* modification time */ - ngx_rtmp_mp4_field_32(b, 0); - - /* time scale*/ - ngx_rtmp_mp4_field_32(b, 1000); - - /* duration */ - ngx_rtmp_mp4_field_32(b, 0); - - /* lanuguage */ - ngx_rtmp_mp4_field_16(b, 0x15C7); - - /* reserved */ - ngx_rtmp_mp4_field_16(b, 0); - - ngx_rtmp_mp4_update_box_size(b, pos); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_write_hdlr(ngx_buf_t *b, ngx_rtmp_mp4_track_type_t ttype) -{ - u_char *pos; - - pos = ngx_rtmp_mp4_start_box(b, "hdlr"); - - /* version and flags */ - ngx_rtmp_mp4_field_32(b, 0); - - /* pre defined */ - ngx_rtmp_mp4_field_32(b, 0); - - if (ttype == NGX_RTMP_MP4_VIDEO_TRACK) { - ngx_rtmp_mp4_box(b, "vide"); - } else { - ngx_rtmp_mp4_box(b, "soun"); - } - - /* reserved */ - ngx_rtmp_mp4_field_32(b, 0); - ngx_rtmp_mp4_field_32(b, 0); - ngx_rtmp_mp4_field_32(b, 0); - - if (ttype == NGX_RTMP_MP4_VIDEO_TRACK) { - /* video handler string, NULL-terminated */ - ngx_rtmp_mp4_data(b, "VideoHandler", sizeof("VideoHandler")); - } else { - /* sound handler string, NULL-terminated */ - ngx_rtmp_mp4_data(b, "SoundHandler", sizeof("SoundHandler")); - } - - ngx_rtmp_mp4_update_box_size(b, pos); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_write_vmhd(ngx_buf_t *b) -{ - /* size is always 20, apparently */ - ngx_rtmp_mp4_field_32(b, 20); - - ngx_rtmp_mp4_box(b, "vmhd"); - - /* version and flags */ - ngx_rtmp_mp4_field_32(b, 0x01); - - /* reserved (graphics mode=copy) */ - ngx_rtmp_mp4_field_32(b, 0); - ngx_rtmp_mp4_field_32(b, 0); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_write_smhd(ngx_buf_t *b) -{ - /* size is always 16, apparently */ - ngx_rtmp_mp4_field_32(b, 16); - - ngx_rtmp_mp4_box(b, "smhd"); - - /* version and flags */ - ngx_rtmp_mp4_field_32(b, 0); - - /* reserved (balance normally=0) */ - ngx_rtmp_mp4_field_16(b, 0); - ngx_rtmp_mp4_field_16(b, 0); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_write_dref(ngx_buf_t *b) -{ - u_char *pos; - - pos = ngx_rtmp_mp4_start_box(b, "dref"); - - /* version and flags */ - ngx_rtmp_mp4_field_32(b, 0); - - /* entry count */ - ngx_rtmp_mp4_field_32(b, 1); - - /* url size */ - ngx_rtmp_mp4_field_32(b, 0xc); - - ngx_rtmp_mp4_box(b, "url "); - - /* version and flags */ - ngx_rtmp_mp4_field_32(b, 0x00000001); - - ngx_rtmp_mp4_update_box_size(b, pos); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_write_dinf(ngx_buf_t *b) -{ - u_char *pos; - - pos = ngx_rtmp_mp4_start_box(b, "dinf"); - - ngx_rtmp_mp4_write_dref(b); - - ngx_rtmp_mp4_update_box_size(b, pos); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_write_avcc(ngx_rtmp_session_t *s, ngx_buf_t *b) -{ - u_char *pos, *p; - ngx_chain_t *in; - ngx_rtmp_codec_ctx_t *codec_ctx; - - codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - - if (codec_ctx == NULL) { - return NGX_ERROR; - } - - in = codec_ctx->avc_header->chain; - if (in == NULL) { - return NGX_ERROR; - } - - pos = ngx_rtmp_mp4_start_box(b, "avcC"); - - /* assume config fits one chunk (highly probable) */ - - /* - * Skip: - * - flv fmt - * - H264 CONF/PICT (0x00) - * - 0 - * - 0 - * - 0 - */ - - p = in->buf->pos + 5; - - if (p < in->buf->last) { - ngx_rtmp_mp4_data(b, p, (size_t) (in->buf->last - p)); - } else { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "dash: invalid avcc received"); - } - - ngx_rtmp_mp4_update_box_size(b, pos); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_write_video(ngx_rtmp_session_t *s, ngx_buf_t *b) -{ - u_char *pos; - ngx_rtmp_codec_ctx_t *codec_ctx; - - codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - - pos = ngx_rtmp_mp4_start_box(b, "avc1"); - - /* reserved */ - ngx_rtmp_mp4_field_32(b, 0); - ngx_rtmp_mp4_field_16(b, 0); - - /* data reference index */ - ngx_rtmp_mp4_field_16(b, 1); - - /* codec stream version & revision */ - ngx_rtmp_mp4_field_16(b, 0); - ngx_rtmp_mp4_field_16(b, 0); - - /* reserved */ - ngx_rtmp_mp4_field_32(b, 0); - ngx_rtmp_mp4_field_32(b, 0); - ngx_rtmp_mp4_field_32(b, 0); - - /* width & height */ - ngx_rtmp_mp4_field_16(b, (uint16_t) codec_ctx->width); - ngx_rtmp_mp4_field_16(b, (uint16_t) codec_ctx->height); - - /* horizontal & vertical resolutions 72 dpi */ - ngx_rtmp_mp4_field_32(b, 0x00480000); - ngx_rtmp_mp4_field_32(b, 0x00480000); - - /* data size */ - ngx_rtmp_mp4_field_32(b, 0); - - /* frame count */ - ngx_rtmp_mp4_field_16(b, 1); - - /* compressor name */ - ngx_rtmp_mp4_field_32(b, 0); - ngx_rtmp_mp4_field_32(b, 0); - ngx_rtmp_mp4_field_32(b, 0); - - /* reserved */ - ngx_rtmp_mp4_field_32(b, 0); - ngx_rtmp_mp4_field_32(b, 0); - ngx_rtmp_mp4_field_32(b, 0); - ngx_rtmp_mp4_field_32(b, 0); - ngx_rtmp_mp4_field_32(b, 0); - ngx_rtmp_mp4_field_16(b, 0x18); - ngx_rtmp_mp4_field_16(b, 0xffff); - - ngx_rtmp_mp4_write_avcc(s, b); - - ngx_rtmp_mp4_update_box_size(b, pos); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_write_esds(ngx_rtmp_session_t *s, ngx_buf_t *b) -{ - size_t dsi_len; - u_char *pos, *dsi; - ngx_buf_t *db; - ngx_rtmp_codec_ctx_t *codec_ctx; - - codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - - if (codec_ctx == NULL || codec_ctx->aac_header == NULL) { - return NGX_ERROR; - } - - db = codec_ctx->aac_header->chain->buf; - if (db == NULL) { - return NGX_ERROR; - } - - dsi = db->pos + 2; - if (dsi > db->last) { - return NGX_ERROR; - } - - dsi_len = db->last - dsi; - - pos = ngx_rtmp_mp4_start_box(b, "esds"); - - /* version */ - ngx_rtmp_mp4_field_32(b, 0); - - - /* ES Descriptor */ - - ngx_rtmp_mp4_put_descr(b, 0x03, 23 + dsi_len); - - /* ES_ID */ - ngx_rtmp_mp4_field_16(b, 1); - - /* flags */ - ngx_rtmp_mp4_field_8(b, 0); - - - /* DecoderConfig Descriptor */ - - ngx_rtmp_mp4_put_descr(b, 0x04, 15 + dsi_len); - - /* objectTypeIndication: Audio ISO/IEC 14496-3 (AAC) */ - ngx_rtmp_mp4_field_8(b, 0x40); - - /* streamType: AudioStream */ - ngx_rtmp_mp4_field_8(b, 0x15); - - /* bufferSizeDB */ - ngx_rtmp_mp4_field_24(b, 0); - - /* maxBitrate */ - ngx_rtmp_mp4_field_32(b, 0x0001F151); - - /* avgBitrate */ - ngx_rtmp_mp4_field_32(b, 0x0001F14D); - - - /* DecoderSpecificInfo Descriptor */ - - ngx_rtmp_mp4_put_descr(b, 0x05, dsi_len); - ngx_rtmp_mp4_data(b, dsi, dsi_len); - - - /* SL Descriptor */ - - ngx_rtmp_mp4_put_descr(b, 0x06, 1); - ngx_rtmp_mp4_field_8(b, 0x02); - - ngx_rtmp_mp4_update_box_size(b, pos); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_write_audio(ngx_rtmp_session_t *s, ngx_buf_t *b) -{ - u_char *pos; - ngx_rtmp_codec_ctx_t *codec_ctx; - - codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - - pos = ngx_rtmp_mp4_start_box(b, "mp4a"); - - /* reserved */ - ngx_rtmp_mp4_field_32(b, 0); - ngx_rtmp_mp4_field_16(b, 0); - - /* data reference index */ - ngx_rtmp_mp4_field_16(b, 1); - - /* reserved */ - ngx_rtmp_mp4_field_32(b, 0); - ngx_rtmp_mp4_field_32(b, 0); - - /* channel count */ - ngx_rtmp_mp4_field_16(b, (uint16_t) codec_ctx->audio_channels); - - /* sample size */ - ngx_rtmp_mp4_field_16(b, (uint16_t) (codec_ctx->sample_size * 8)); - - /* reserved */ - ngx_rtmp_mp4_field_32(b, 0); - - /* time scale */ - ngx_rtmp_mp4_field_16(b, 1000); - - /* sample rate */ - ngx_rtmp_mp4_field_16(b, (uint16_t) codec_ctx->sample_rate); - - ngx_rtmp_mp4_write_esds(s, b); -#if 0 - /* tag size*/ - ngx_rtmp_mp4_field_32(b, 8); - - /* null tag */ - ngx_rtmp_mp4_field_32(b, 0); -#endif - ngx_rtmp_mp4_update_box_size(b, pos); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_write_stsd(ngx_rtmp_session_t *s, ngx_buf_t *b, - ngx_rtmp_mp4_track_type_t ttype) -{ - u_char *pos; - - pos = ngx_rtmp_mp4_start_box(b, "stsd"); - - /* version & flags */ - ngx_rtmp_mp4_field_32(b, 0); - - /* entry count */ - ngx_rtmp_mp4_field_32(b, 1); - - if (ttype == NGX_RTMP_MP4_VIDEO_TRACK) { - ngx_rtmp_mp4_write_video(s, b); - } else { - ngx_rtmp_mp4_write_audio(s, b); - } - - ngx_rtmp_mp4_update_box_size(b, pos); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_write_stts(ngx_buf_t *b) -{ - u_char *pos; - - pos = ngx_rtmp_mp4_start_box(b, "stts"); - - ngx_rtmp_mp4_field_32(b, 0); /* version */ - ngx_rtmp_mp4_field_32(b, 0); /* entry count */ - - ngx_rtmp_mp4_update_box_size(b, pos); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_write_stsc(ngx_buf_t *b) -{ - u_char *pos; - - pos = ngx_rtmp_mp4_start_box(b, "stsc"); - - ngx_rtmp_mp4_field_32(b, 0); /* version */ - ngx_rtmp_mp4_field_32(b, 0); /* entry count */ - - ngx_rtmp_mp4_update_box_size(b, pos); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_write_stsz(ngx_buf_t *b) -{ - u_char *pos; - - pos = ngx_rtmp_mp4_start_box(b, "stsz"); - - ngx_rtmp_mp4_field_32(b, 0); /* version */ - ngx_rtmp_mp4_field_32(b, 0); /* entry count */ - ngx_rtmp_mp4_field_32(b, 0); /* moar zeros */ - - ngx_rtmp_mp4_update_box_size(b, pos); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_write_stco(ngx_buf_t *b) -{ - u_char *pos; - - pos = ngx_rtmp_mp4_start_box(b, "stco"); - - ngx_rtmp_mp4_field_32(b, 0); /* version */ - ngx_rtmp_mp4_field_32(b, 0); /* entry count */ - - ngx_rtmp_mp4_update_box_size(b, pos); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_write_stbl(ngx_rtmp_session_t *s, ngx_buf_t *b, - ngx_rtmp_mp4_track_type_t ttype) -{ - u_char *pos; - - pos = ngx_rtmp_mp4_start_box(b, "stbl"); - - ngx_rtmp_mp4_write_stsd(s, b, ttype); - ngx_rtmp_mp4_write_stts(b); - ngx_rtmp_mp4_write_stsc(b); - ngx_rtmp_mp4_write_stsz(b); - ngx_rtmp_mp4_write_stco(b); - - ngx_rtmp_mp4_update_box_size(b, pos); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_write_minf(ngx_rtmp_session_t *s, ngx_buf_t *b, - ngx_rtmp_mp4_track_type_t ttype) -{ - u_char *pos; - - pos = ngx_rtmp_mp4_start_box(b, "minf"); - - if (ttype == NGX_RTMP_MP4_VIDEO_TRACK) { - ngx_rtmp_mp4_write_vmhd(b); - } else { - ngx_rtmp_mp4_write_smhd(b); - } - - ngx_rtmp_mp4_write_dinf(b); - ngx_rtmp_mp4_write_stbl(s, b, ttype); - - ngx_rtmp_mp4_update_box_size(b, pos); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_write_mdia(ngx_rtmp_session_t *s, ngx_buf_t *b, - ngx_rtmp_mp4_track_type_t ttype) -{ - u_char *pos; - - pos = ngx_rtmp_mp4_start_box(b, "mdia"); - - ngx_rtmp_mp4_write_mdhd(b); - ngx_rtmp_mp4_write_hdlr(b, ttype); - ngx_rtmp_mp4_write_minf(s, b, ttype); - - ngx_rtmp_mp4_update_box_size(b, pos); - - return NGX_OK; -} - -static ngx_int_t -ngx_rtmp_mp4_write_trak(ngx_rtmp_session_t *s, ngx_buf_t *b, - ngx_rtmp_mp4_track_type_t ttype) -{ - u_char *pos; - - pos = ngx_rtmp_mp4_start_box(b, "trak"); - - ngx_rtmp_mp4_write_tkhd(s, b, ttype); - ngx_rtmp_mp4_write_mdia(s, b, ttype); - - ngx_rtmp_mp4_update_box_size(b, pos); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_write_mvex(ngx_buf_t *b) -{ - u_char *pos; - - pos = ngx_rtmp_mp4_start_box(b, "mvex"); - - ngx_rtmp_mp4_field_32(b, 0x20); - - ngx_rtmp_mp4_box(b, "trex"); - - /* version & flags */ - ngx_rtmp_mp4_field_32(b, 0); - - /* track id */ - ngx_rtmp_mp4_field_32(b, 1); - - /* default sample description index */ - ngx_rtmp_mp4_field_32(b, 1); - - /* default sample duration */ - ngx_rtmp_mp4_field_32(b, 0); - - /* default sample size, 1024 for AAC */ - ngx_rtmp_mp4_field_32(b, 0); - - /* default sample flags, key on */ - ngx_rtmp_mp4_field_32(b, 0); - - ngx_rtmp_mp4_update_box_size(b, pos); - - return NGX_OK; -} - - -ngx_int_t -ngx_rtmp_mp4_write_moov(ngx_rtmp_session_t *s, ngx_buf_t *b, - ngx_rtmp_mp4_track_type_t ttype) -{ - u_char *pos; - - pos = ngx_rtmp_mp4_start_box(b, "moov"); - - ngx_rtmp_mp4_write_mvhd(b); - ngx_rtmp_mp4_write_mvex(b); - ngx_rtmp_mp4_write_trak(s, b, ttype); - - ngx_rtmp_mp4_update_box_size(b, pos); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_write_tfhd(ngx_buf_t *b) -{ - u_char *pos; - - pos = ngx_rtmp_mp4_start_box(b, "tfhd"); - - /* version & flags */ - ngx_rtmp_mp4_field_32(b, 0x00020000); - - /* track id */ - ngx_rtmp_mp4_field_32(b, 1); - - ngx_rtmp_mp4_update_box_size(b, pos); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_write_tfdt(ngx_buf_t *b, uint32_t earliest_pres_time) -{ - u_char *pos; - - pos = ngx_rtmp_mp4_start_box(b, "tfdt"); - - /* version == 1 aka 64 bit integer */ - ngx_rtmp_mp4_field_32(b, 0x00000000); - ngx_rtmp_mp4_field_32(b, earliest_pres_time); - - ngx_rtmp_mp4_update_box_size(b, pos); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_write_trun(ngx_buf_t *b, uint32_t sample_count, - ngx_rtmp_mp4_sample_t *samples, ngx_uint_t sample_mask, u_char *moof_pos) -{ - u_char *pos; - uint32_t i, offset, nitems, flags; - - pos = ngx_rtmp_mp4_start_box(b, "trun"); - - nitems = 0; - - /* data offset present */ - flags = 0x01; - - if (sample_mask & NGX_RTMP_MP4_SAMPLE_DURATION) { - nitems++; - flags |= 0x000100; - } - - if (sample_mask & NGX_RTMP_MP4_SAMPLE_SIZE) { - nitems++; - flags |= 0x000200; - } - - if (sample_mask & NGX_RTMP_MP4_SAMPLE_KEY) { - nitems++; - flags |= 0x000400; - } - - if (sample_mask & NGX_RTMP_MP4_SAMPLE_DELAY) { - nitems++; - flags |= 0x000800; - } - - offset = (pos - moof_pos) + 20 + (sample_count * nitems * 4) + 8; - - ngx_rtmp_mp4_field_32(b, flags); - ngx_rtmp_mp4_field_32(b, sample_count); - ngx_rtmp_mp4_field_32(b, offset); - - for (i = 0; i < sample_count; i++, samples++) { - - if (sample_mask & NGX_RTMP_MP4_SAMPLE_DURATION) { - ngx_rtmp_mp4_field_32(b, samples->duration); - } - - if (sample_mask & NGX_RTMP_MP4_SAMPLE_SIZE) { - ngx_rtmp_mp4_field_32(b, samples->size); - } - - if (sample_mask & NGX_RTMP_MP4_SAMPLE_KEY) { - ngx_rtmp_mp4_field_32(b, samples->key ? 0x00000000 : 0x00010000); - } - - if (sample_mask & NGX_RTMP_MP4_SAMPLE_DELAY) { - ngx_rtmp_mp4_field_32(b, samples->delay); - } - } - - ngx_rtmp_mp4_update_box_size(b, pos); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_write_traf(ngx_buf_t *b, uint32_t earliest_pres_time, - uint32_t sample_count, ngx_rtmp_mp4_sample_t *samples, - ngx_uint_t sample_mask, u_char *moof_pos) -{ - u_char *pos; - - pos = ngx_rtmp_mp4_start_box(b, "traf"); - - ngx_rtmp_mp4_write_tfhd(b); - ngx_rtmp_mp4_write_tfdt(b, earliest_pres_time); - ngx_rtmp_mp4_write_trun(b, sample_count, samples, sample_mask, moof_pos); - - ngx_rtmp_mp4_update_box_size(b, pos); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mp4_write_mfhd(ngx_buf_t *b, uint32_t index) -{ - u_char *pos; - - pos = ngx_rtmp_mp4_start_box(b, "mfhd"); - - /* don't know what this is */ - ngx_rtmp_mp4_field_32(b, 0); - - /* fragment index. */ - ngx_rtmp_mp4_field_32(b, index); - - ngx_rtmp_mp4_update_box_size(b, pos); - - return NGX_OK; -} - - -ngx_int_t -ngx_rtmp_mp4_write_sidx(ngx_buf_t *b, ngx_uint_t reference_size, - uint32_t earliest_pres_time, uint32_t latest_pres_time) -{ - u_char *pos; - uint32_t duration; - - duration = latest_pres_time - earliest_pres_time; - - pos = ngx_rtmp_mp4_start_box(b, "sidx"); - - /* version */ - ngx_rtmp_mp4_field_32(b, 0); - - /* reference id */ - ngx_rtmp_mp4_field_32(b, 1); - - /* timescale */ - ngx_rtmp_mp4_field_32(b, 1000); - - /* earliest presentation time */ - ngx_rtmp_mp4_field_32(b, earliest_pres_time); - - /* first offset */ - ngx_rtmp_mp4_field_32(b, duration); /*TODO*/ - - /* reserved */ - ngx_rtmp_mp4_field_16(b, 0); - - /* reference count = 1 */ - ngx_rtmp_mp4_field_16(b, 1); - - /* 1st bit is reference type, the rest is reference size */ - ngx_rtmp_mp4_field_32(b, reference_size); - - /* subsegment duration */ - ngx_rtmp_mp4_field_32(b, duration); - - /* first bit is startsWithSAP (=1), next 3 bits are SAP type (=001) */ - ngx_rtmp_mp4_field_8(b, 0x90); - - /* SAP delta time */ - ngx_rtmp_mp4_field_24(b, 0); - - ngx_rtmp_mp4_update_box_size(b, pos); - - return NGX_OK; -} - - -ngx_int_t -ngx_rtmp_mp4_write_moof(ngx_buf_t *b, uint32_t earliest_pres_time, - uint32_t sample_count, ngx_rtmp_mp4_sample_t *samples, - ngx_uint_t sample_mask, uint32_t index) -{ - u_char *pos; - - pos = ngx_rtmp_mp4_start_box(b, "moof"); - - ngx_rtmp_mp4_write_mfhd(b, index); - ngx_rtmp_mp4_write_traf(b, earliest_pres_time, sample_count, samples, - sample_mask, pos); - - ngx_rtmp_mp4_update_box_size(b, pos); - - return NGX_OK; -} - - -ngx_uint_t -ngx_rtmp_mp4_write_mdat(ngx_buf_t *b, ngx_uint_t size) -{ - ngx_rtmp_mp4_field_32(b, size); - - ngx_rtmp_mp4_box(b, "mdat"); - - return NGX_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/dash/ngx_rtmp_mp4.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/dash/ngx_rtmp_mp4.h deleted file mode 100644 index 697b6c87c7..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/dash/ngx_rtmp_mp4.h +++ /dev/null @@ -1,52 +0,0 @@ - - -#ifndef _NGX_RTMP_MP4_H_INCLUDED_ -#define _NGX_RTMP_MP4_H_INCLUDED_ - - -#include -#include -#include - - -#define NGX_RTMP_MP4_SAMPLE_SIZE 0x01 -#define NGX_RTMP_MP4_SAMPLE_DURATION 0x02 -#define NGX_RTMP_MP4_SAMPLE_DELAY 0x04 -#define NGX_RTMP_MP4_SAMPLE_KEY 0x08 - - -typedef struct { - uint32_t size; - uint32_t duration; - uint32_t delay; - uint32_t timestamp; - unsigned key:1; -} ngx_rtmp_mp4_sample_t; - - -typedef enum { - NGX_RTMP_MP4_FILETYPE_INIT, - NGX_RTMP_MP4_FILETYPE_SEG -} ngx_rtmp_mp4_file_type_t; - - -typedef enum { - NGX_RTMP_MP4_VIDEO_TRACK, - NGX_RTMP_MP4_AUDIO_TRACK -} ngx_rtmp_mp4_track_type_t; - - -ngx_int_t ngx_rtmp_mp4_write_ftyp(ngx_buf_t *b); -ngx_int_t ngx_rtmp_mp4_write_styp(ngx_buf_t *b); -ngx_int_t ngx_rtmp_mp4_write_moov(ngx_rtmp_session_t *s, ngx_buf_t *b, - ngx_rtmp_mp4_track_type_t ttype); -ngx_int_t ngx_rtmp_mp4_write_moof(ngx_buf_t *b, uint32_t earliest_pres_time, - uint32_t sample_count, ngx_rtmp_mp4_sample_t *samples, - ngx_uint_t sample_mask, uint32_t index); -ngx_int_t ngx_rtmp_mp4_write_sidx(ngx_buf_t *b, - ngx_uint_t reference_size, uint32_t earliest_pres_time, - uint32_t latest_pres_time); -ngx_uint_t ngx_rtmp_mp4_write_mdat(ngx_buf_t *b, ngx_uint_t size); - - -#endif /* _NGX_RTMP_MP4_H_INCLUDED_ */ diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/hls/ngx_rtmp_hls_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/hls/ngx_rtmp_hls_module.c deleted file mode 100644 index 35f1c6e03b..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/hls/ngx_rtmp_hls_module.c +++ /dev/null @@ -1,2713 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include -#include -#include -#include -#include "ngx_rtmp_mpegts.h" - - -static ngx_rtmp_publish_pt next_publish; -static ngx_rtmp_close_stream_pt next_close_stream; -static ngx_rtmp_stream_begin_pt next_stream_begin; -static ngx_rtmp_stream_eof_pt next_stream_eof; - - -static char * ngx_rtmp_hls_variant(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); -static ngx_int_t ngx_rtmp_hls_postconfiguration(ngx_conf_t *cf); -static void * ngx_rtmp_hls_create_app_conf(ngx_conf_t *cf); -static char * ngx_rtmp_hls_merge_app_conf(ngx_conf_t *cf, - void *parent, void *child); -static ngx_int_t ngx_rtmp_hls_flush_audio(ngx_rtmp_session_t *s); -static ngx_int_t ngx_rtmp_hls_ensure_directory(ngx_rtmp_session_t *s, - ngx_str_t *path); - - -#define NGX_RTMP_HLS_BUFSIZE (1024*1024) -#define NGX_RTMP_HLS_DIR_ACCESS 0744 - - -typedef struct { - uint64_t id; - uint64_t key_id; - double duration; - unsigned active:1; - unsigned discont:1; /* before */ -} ngx_rtmp_hls_frag_t; - - -typedef struct { - ngx_str_t suffix; - ngx_array_t args; -} ngx_rtmp_hls_variant_t; - - -typedef struct { - unsigned opened:1; - - ngx_rtmp_mpegts_file_t file; - - ngx_str_t playlist; - ngx_str_t playlist_bak; - ngx_str_t var_playlist; - ngx_str_t var_playlist_bak; - ngx_str_t stream; - ngx_str_t keyfile; - ngx_str_t name; - u_char key[16]; - - uint64_t frag; - uint64_t frag_ts; - uint64_t key_id; - ngx_uint_t nfrags; - ngx_rtmp_hls_frag_t *frags; /* circular 2 * winfrags + 1 */ - - ngx_uint_t audio_cc; - ngx_uint_t video_cc; - ngx_uint_t key_frags; - - uint64_t aframe_base; - uint64_t aframe_num; - - ngx_buf_t *aframe; - uint64_t aframe_pts; - - ngx_rtmp_hls_variant_t *var; -} ngx_rtmp_hls_ctx_t; - - -typedef struct { - ngx_str_t path; - ngx_msec_t playlen; - ngx_uint_t frags_per_key; -} ngx_rtmp_hls_cleanup_t; - - -typedef struct { - ngx_flag_t hls; - ngx_msec_t fraglen; - ngx_msec_t max_fraglen; - ngx_msec_t muxdelay; - ngx_msec_t sync; - ngx_msec_t playlen; - ngx_uint_t winfrags; - ngx_flag_t continuous; - ngx_flag_t nested; - ngx_str_t path; - ngx_uint_t naming; - ngx_uint_t slicing; - ngx_uint_t type; - ngx_path_t *slot; - ngx_msec_t max_audio_delay; - size_t audio_buffer_size; - ngx_flag_t cleanup; - ngx_array_t *variant; - ngx_str_t base_url; - ngx_int_t granularity; - ngx_flag_t keys; - ngx_str_t key_path; - ngx_str_t key_url; - ngx_uint_t frags_per_key; -} ngx_rtmp_hls_app_conf_t; - - -#define NGX_RTMP_HLS_NAMING_SEQUENTIAL 1 -#define NGX_RTMP_HLS_NAMING_TIMESTAMP 2 -#define NGX_RTMP_HLS_NAMING_SYSTEM 3 - - -#define NGX_RTMP_HLS_SLICING_PLAIN 1 -#define NGX_RTMP_HLS_SLICING_ALIGNED 2 - - -#define NGX_RTMP_HLS_TYPE_LIVE 1 -#define NGX_RTMP_HLS_TYPE_EVENT 2 - - -static ngx_conf_enum_t ngx_rtmp_hls_naming_slots[] = { - { ngx_string("sequential"), NGX_RTMP_HLS_NAMING_SEQUENTIAL }, - { ngx_string("timestamp"), NGX_RTMP_HLS_NAMING_TIMESTAMP }, - { ngx_string("system"), NGX_RTMP_HLS_NAMING_SYSTEM }, - { ngx_null_string, 0 } -}; - - -static ngx_conf_enum_t ngx_rtmp_hls_slicing_slots[] = { - { ngx_string("plain"), NGX_RTMP_HLS_SLICING_PLAIN }, - { ngx_string("aligned"), NGX_RTMP_HLS_SLICING_ALIGNED }, - { ngx_null_string, 0 } -}; - - -static ngx_conf_enum_t ngx_rtmp_hls_type_slots[] = { - { ngx_string("live"), NGX_RTMP_HLS_TYPE_LIVE }, - { ngx_string("event"), NGX_RTMP_HLS_TYPE_EVENT }, - { ngx_null_string, 0 } -}; - - -static ngx_command_t ngx_rtmp_hls_commands[] = { - - { ngx_string("hls"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_hls_app_conf_t, hls), - NULL }, - - { ngx_string("hls_fragment"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_hls_app_conf_t, fraglen), - NULL }, - - { ngx_string("hls_max_fragment"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_hls_app_conf_t, max_fraglen), - NULL }, - - { ngx_string("hls_path"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_hls_app_conf_t, path), - NULL }, - - { ngx_string("hls_playlist_length"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_hls_app_conf_t, playlen), - NULL }, - - { ngx_string("hls_muxdelay"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_hls_app_conf_t, muxdelay), - NULL }, - - { ngx_string("hls_sync"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_hls_app_conf_t, sync), - NULL }, - - { ngx_string("hls_continuous"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_hls_app_conf_t, continuous), - NULL }, - - { ngx_string("hls_nested"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_hls_app_conf_t, nested), - NULL }, - - { ngx_string("hls_fragment_naming"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_enum_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_hls_app_conf_t, naming), - &ngx_rtmp_hls_naming_slots }, - - { ngx_string("hls_fragment_slicing"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_enum_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_hls_app_conf_t, slicing), - &ngx_rtmp_hls_slicing_slots }, - - { ngx_string("hls_type"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_enum_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_hls_app_conf_t, type), - &ngx_rtmp_hls_type_slots }, - - { ngx_string("hls_max_audio_delay"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_hls_app_conf_t, max_audio_delay), - NULL }, - - { ngx_string("hls_audio_buffer_size"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_hls_app_conf_t, audio_buffer_size), - NULL }, - - { ngx_string("hls_cleanup"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_hls_app_conf_t, cleanup), - NULL }, - - { ngx_string("hls_variant"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_1MORE, - ngx_rtmp_hls_variant, - NGX_RTMP_APP_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("hls_base_url"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_hls_app_conf_t, base_url), - NULL }, - - { ngx_string("hls_fragment_naming_granularity"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_hls_app_conf_t, granularity), - NULL }, - - { ngx_string("hls_keys"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_hls_app_conf_t, keys), - NULL }, - - { ngx_string("hls_key_path"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_hls_app_conf_t, key_path), - NULL }, - - { ngx_string("hls_key_url"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_hls_app_conf_t, key_url), - NULL }, - - { ngx_string("hls_fragments_per_key"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_hls_app_conf_t, frags_per_key), - NULL }, - - ngx_null_command -}; - - -static ngx_rtmp_module_t ngx_rtmp_hls_module_ctx = { - NULL, /* preconfiguration */ - ngx_rtmp_hls_postconfiguration, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - ngx_rtmp_hls_create_app_conf, /* create location configuration */ - ngx_rtmp_hls_merge_app_conf, /* merge location configuration */ -}; - - -ngx_module_t ngx_rtmp_hls_module = { - NGX_MODULE_V1, - &ngx_rtmp_hls_module_ctx, /* module context */ - ngx_rtmp_hls_commands, /* module directives */ - NGX_RTMP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static ngx_rtmp_hls_frag_t * -ngx_rtmp_hls_get_frag(ngx_rtmp_session_t *s, ngx_int_t n) -{ - ngx_rtmp_hls_ctx_t *ctx; - ngx_rtmp_hls_app_conf_t *hacf; - - hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module); - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); - - return &ctx->frags[(ctx->frag + n) % (hacf->winfrags * 2 + 1)]; -} - - -static void -ngx_rtmp_hls_next_frag(ngx_rtmp_session_t *s) -{ - ngx_rtmp_hls_ctx_t *ctx; - ngx_rtmp_hls_app_conf_t *hacf; - - hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module); - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); - - if (ctx->nfrags == hacf->winfrags) { - ctx->frag++; - } else { - ctx->nfrags++; - } -} - - -static ngx_int_t -ngx_rtmp_hls_rename_file(u_char *src, u_char *dst) -{ - /* rename file with overwrite */ - -#if (NGX_WIN32) - return MoveFileEx((LPCTSTR) src, (LPCTSTR) dst, MOVEFILE_REPLACE_EXISTING); -#else - return ngx_rename_file(src, dst); -#endif -} - - -static ngx_int_t -ngx_rtmp_hls_write_variant_playlist(ngx_rtmp_session_t *s) -{ - static u_char buffer[1024]; - - u_char *p, *last; - ssize_t rc; - ngx_fd_t fd; - ngx_str_t *arg; - ngx_uint_t n, k; - ngx_rtmp_hls_ctx_t *ctx; - ngx_rtmp_hls_variant_t *var; - ngx_rtmp_hls_app_conf_t *hacf; - - hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module); - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); - - fd = ngx_open_file(ctx->var_playlist_bak.data, NGX_FILE_WRONLY, - NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS); - - if (fd == NGX_INVALID_FILE) { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "hls: " ngx_open_file_n " failed: '%V'", - &ctx->var_playlist_bak); - - return NGX_ERROR; - } - -#define NGX_RTMP_HLS_VAR_HEADER "#EXTM3U\n#EXT-X-VERSION:3\n" - - rc = ngx_write_fd(fd, NGX_RTMP_HLS_VAR_HEADER, - sizeof(NGX_RTMP_HLS_VAR_HEADER) - 1); - if (rc < 0) { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "hls: " ngx_write_fd_n " failed: '%V'", - &ctx->var_playlist_bak); - ngx_close_file(fd); - return NGX_ERROR; - } - - var = hacf->variant->elts; - for (n = 0; n < hacf->variant->nelts; n++, var++) - { - p = buffer; - last = buffer + sizeof(buffer); - - p = ngx_slprintf(p, last, "#EXT-X-STREAM-INF:PROGRAM-ID=1"); - - arg = var->args.elts; - for (k = 0; k < var->args.nelts; k++, arg++) { - p = ngx_slprintf(p, last, ",%V", arg); - } - - if (p < last) { - *p++ = '\n'; - } - - p = ngx_slprintf(p, last, "%V%*s%V", - &hacf->base_url, - ctx->name.len - ctx->var->suffix.len, ctx->name.data, - &var->suffix); - if (hacf->nested) { - p = ngx_slprintf(p, last, "%s", "/index"); - } - - p = ngx_slprintf(p, last, "%s", ".m3u8\n"); - - rc = ngx_write_fd(fd, buffer, p - buffer); - if (rc < 0) { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "hls: " ngx_write_fd_n " failed '%V'", - &ctx->var_playlist_bak); - ngx_close_file(fd); - return NGX_ERROR; - } - } - - ngx_close_file(fd); - - if (ngx_rtmp_hls_rename_file(ctx->var_playlist_bak.data, - ctx->var_playlist.data) - == NGX_FILE_ERROR) - { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "hls: rename failed: '%V'->'%V'", - &ctx->var_playlist_bak, &ctx->var_playlist); - return NGX_ERROR; - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_hls_write_playlist(ngx_rtmp_session_t *s) -{ - static u_char buffer[1024]; - ngx_fd_t fd; - u_char *p, *end; - ngx_rtmp_hls_ctx_t *ctx; - ssize_t n; - ngx_rtmp_hls_app_conf_t *hacf; - ngx_rtmp_hls_frag_t *f; - ngx_uint_t i, max_frag; - ngx_str_t name_part, key_name_part; - uint64_t prev_key_id; - const char *sep, *key_sep; - - - hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module); - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); - - fd = ngx_open_file(ctx->playlist_bak.data, NGX_FILE_WRONLY, - NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS); - - if (fd == NGX_INVALID_FILE) { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "hls: " ngx_open_file_n " failed: '%V'", - &ctx->playlist_bak); - return NGX_ERROR; - } - - max_frag = hacf->fraglen / 1000; - - for (i = 0; i < ctx->nfrags; i++) { - f = ngx_rtmp_hls_get_frag(s, i); - if (f->duration > max_frag) { - max_frag = (ngx_uint_t) (f->duration + .5); - } - } - - p = buffer; - end = p + sizeof(buffer); - - p = ngx_slprintf(p, end, - "#EXTM3U\n" - "#EXT-X-VERSION:3\n" - "#EXT-X-MEDIA-SEQUENCE:%uL\n" - "#EXT-X-TARGETDURATION:%ui\n", - ctx->frag, max_frag); - - if (hacf->type == NGX_RTMP_HLS_TYPE_EVENT) { - p = ngx_slprintf(p, end, "#EXT-X-PLAYLIST-TYPE: EVENT\n"); - } - - n = ngx_write_fd(fd, buffer, p - buffer); - if (n < 0) { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "hls: " ngx_write_fd_n " failed: '%V'", - &ctx->playlist_bak); - ngx_close_file(fd); - return NGX_ERROR; - } - - sep = hacf->nested ? (hacf->base_url.len ? "/" : "") : "-"; - key_sep = hacf->nested ? (hacf->key_url.len ? "/" : "") : "-"; - - name_part.len = 0; - if (!hacf->nested || hacf->base_url.len) { - name_part = ctx->name; - } - - key_name_part.len = 0; - if (!hacf->nested || hacf->key_url.len) { - key_name_part = ctx->name; - } - - prev_key_id = 0; - - for (i = 0; i < ctx->nfrags; i++) { - f = ngx_rtmp_hls_get_frag(s, i); - - p = buffer; - end = p + sizeof(buffer); - - if (f->discont) { - p = ngx_slprintf(p, end, "#EXT-X-DISCONTINUITY\n"); - } - - if (hacf->keys && (i == 0 || f->key_id != prev_key_id)) { - p = ngx_slprintf(p, end, "#EXT-X-KEY:METHOD=AES-128," - "URI=\"%V%V%s%uL.key\",IV=0x%032XL\n", - &hacf->key_url, &key_name_part, - key_sep, f->key_id, f->key_id); - } - - prev_key_id = f->key_id; - - p = ngx_slprintf(p, end, - "#EXTINF:%.3f,\n" - "%V%V%s%uL.ts\n", - f->duration, &hacf->base_url, &name_part, sep, f->id); - - ngx_log_debug5(NGX_LOG_DEBUG_RTMP, s->log, 0, - "hls: fragment frag=%uL, n=%ui/%ui, duration=%.3f, " - "discont=%i", - ctx->frag, i + 1, ctx->nfrags, f->duration, f->discont); - - n = ngx_write_fd(fd, buffer, p - buffer); - if (n < 0) { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "hls: " ngx_write_fd_n " failed '%V'", - &ctx->playlist_bak); - ngx_close_file(fd); - return NGX_ERROR; - } - } - - ngx_close_file(fd); - - if (ngx_rtmp_hls_rename_file(ctx->playlist_bak.data, ctx->playlist.data) - == NGX_FILE_ERROR) - { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "hls: rename failed: '%V'->'%V'", - &ctx->playlist_bak, &ctx->playlist); - return NGX_ERROR; - } - - if (ctx->var) { - return ngx_rtmp_hls_write_variant_playlist(s); - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_hls_copy(ngx_rtmp_session_t *s, void *dst, u_char **src, size_t n, - ngx_chain_t **in) -{ - u_char *last; - size_t pn; - - if (*in == NULL) { - return NGX_ERROR; - } - - for ( ;; ) { - last = (*in)->buf->last; - - if ((size_t)(last - *src) >= n) { - if (dst) { - ngx_memcpy(dst, *src, n); - } - - *src += n; - - while (*in && *src == (*in)->buf->last) { - *in = (*in)->next; - if (*in) { - *src = (*in)->buf->pos; - } - } - - return NGX_OK; - } - - pn = last - *src; - - if (dst) { - ngx_memcpy(dst, *src, pn); - dst = (u_char *)dst + pn; - } - - n -= pn; - *in = (*in)->next; - - if (*in == NULL) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls: failed to read %uz byte(s)", n); - return NGX_ERROR; - } - - *src = (*in)->buf->pos; - } -} - - -static ngx_int_t -ngx_rtmp_hls_append_hevc_aud(ngx_rtmp_session_t *s, ngx_buf_t *out) -{ - static u_char aud_nal[] = { 0x00, 0x00, 0x00, 0x01, 0x46, 0x01, 0x50 }; - - if (out->last + sizeof(aud_nal) > out->end) { - return NGX_ERROR; - } - - out->last = ngx_cpymem(out->last, aud_nal, sizeof(aud_nal)); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_hls_append_hevc_vps_sps_pps(ngx_rtmp_session_t *s, ngx_buf_t *out) -{ - ngx_rtmp_codec_ctx_t *codec_ctx; - u_char *p; - ngx_chain_t *in; - ngx_rtmp_hls_ctx_t *ctx; - ngx_uint_t i, j, rnal_unit_len, nal_unit_len, - num_arrays, nal_unit_type, - rnum_nalus, num_nalus; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); - - codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - - if (ctx == NULL || codec_ctx == NULL) { - return NGX_ERROR; - } - - in = codec_ctx->avc_header->chain; - if (in == NULL) { - return NGX_ERROR; - } - - p = in->buf->pos; - /* 6 bytes - * FrameType 4 bits - * CodecID 4 bits - * AVCPacketType 1 byte - * CompositionTime 3 bytes - * HEVCDecoderConfigurationRecord - * configurationVersion 1 byte - */ - - /* 20 bytes - * HEVCDecoderConfigurationRecord - * general_profile_space 2 bits - * general_tier_flag 1 bit - * general_profile_idc 5 bits - * general_profile_compatibility_flags 4 bytes - * general_constraint_indicator_flags 6 bytes - * general_level_idc 1 byte - * min_spatial_segmentation_idc 4 bits reserved + 12 bits - * parallelismType 6 bits reserved + 2 bits - * chroma_format_idc 6 bits reserved + 2 bits - * bit_depth_luma_minus8 5 bits reserved + 3 bits - * bit_depth_chroma_minus8 5 bits reserved + 3 bits - * avgFrameRate 2 bytes - */ - - /* 1 bytes - * HEVCDecoderConfigurationRecord - * constantFrameRate 2 bits - * numTemporalLayers 3 bits - * temporalIdNested 1 bit - * lengthSizeMinusOne 2 bits - */ - - if (ngx_rtmp_hls_copy(s, NULL, &p, 27, &in) != NGX_OK) { - return NGX_ERROR; - } - - /* 1 byte - * HEVCDecoderConfigurationRecord - * numOfArrays 1 byte - */ - num_arrays = 0; - if (ngx_rtmp_hls_copy(s, &num_arrays, &p, 1, &in) != NGX_OK) { - return NGX_ERROR; - } - - for (i = 0; i < num_arrays; ++i) { - /* - * array_completeness 1 bit - * reserved 1 bit - * NAL_unit_type 6 bits - * numNalus 2 bytes - */ - if (ngx_rtmp_hls_copy(s, &nal_unit_type, &p, 1, &in) != NGX_OK) { // 32 33 34 39 - return NGX_ERROR; - } - nal_unit_type &= 0x3f; - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "rtmp-hls: append_vps_sps_pps| type %d", nal_unit_type); - if (ngx_rtmp_hls_copy(s, &rnum_nalus, &p, 2, &in) != NGX_OK) { - return NGX_ERROR; - } - num_nalus = 0; - ngx_rtmp_rmemcpy(&num_nalus, &rnum_nalus, 2); - for (j = 0; j < num_nalus; ++j) { - /* - * nalUnitLength 2 bytes - */ - if (ngx_rtmp_hls_copy(s, &rnal_unit_len, &p, 2, &in) != NGX_OK) { - return NGX_ERROR; - } - nal_unit_len = 0; - ngx_rtmp_rmemcpy(&nal_unit_len, &rnal_unit_len, 2); - if (out->end - out->last < 4) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls: too small buffer for hevc header NAL size"); - return NGX_ERROR; - } - - *out->last++ = 0; - *out->last++ = 0; - *out->last++ = 0; - *out->last++ = 1; - - if (out->end - out->last < (ngx_int_t)nal_unit_len) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls: too small buffer for hevc header NAL"); - return NGX_ERROR; - } - - if (ngx_rtmp_hls_copy(s, out->last, &p, nal_unit_len, &in) - != NGX_OK) - { - return NGX_ERROR; - } - - out->last += nal_unit_len; - } - } - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_hls_append_aud(ngx_rtmp_session_t *s, ngx_buf_t *out) -{ - static u_char aud_nal[] = { 0x00, 0x00, 0x00, 0x01, 0x09, 0xf0 }; - - if (out->last + sizeof(aud_nal) > out->end) { - return NGX_ERROR; - } - - out->last = ngx_cpymem(out->last, aud_nal, sizeof(aud_nal)); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_hls_append_sps_pps(ngx_rtmp_session_t *s, ngx_buf_t *out) -{ - ngx_rtmp_codec_ctx_t *codec_ctx; - u_char *p; - ngx_chain_t *in; - ngx_rtmp_hls_ctx_t *ctx; - int8_t nnals; - uint16_t len, rlen; - ngx_int_t n; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); - - codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - - if (ctx == NULL || codec_ctx == NULL) { - return NGX_ERROR; - } - - in = codec_ctx->avc_header->chain; - if (in == NULL) { - return NGX_ERROR; - } - - p = in->buf->pos; - - /* - * Skip bytes: - * - flv fmt - * - H264 CONF/PICT (0x00) - * - 0 - * - 0 - * - 0 - * - version - * - profile - * - compatibility - * - level - * - nal bytes - */ - - if (ngx_rtmp_hls_copy(s, NULL, &p, 10, &in) != NGX_OK) { - return NGX_ERROR; - } - - /* number of SPS NALs */ - if (ngx_rtmp_hls_copy(s, &nnals, &p, 1, &in) != NGX_OK) { - return NGX_ERROR; - } - - nnals &= 0x1f; /* 5lsb */ - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "hls: SPS number: %uz", nnals); - - /* SPS */ - for (n = 0; ; ++n) { - for (; nnals; --nnals) { - - /* NAL length */ - if (ngx_rtmp_hls_copy(s, &rlen, &p, 2, &in) != NGX_OK) { - return NGX_ERROR; - } - - ngx_rtmp_rmemcpy(&len, &rlen, 2); - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "hls: header NAL length: %uz", (size_t) len); - - /* AnnexB prefix */ - if (out->end - out->last < 4) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls: too small buffer for header NAL size"); - return NGX_ERROR; - } - - *out->last++ = 0; - *out->last++ = 0; - *out->last++ = 0; - *out->last++ = 1; - - /* NAL body */ - if (out->end - out->last < len) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls: too small buffer for header NAL"); - return NGX_ERROR; - } - - if (ngx_rtmp_hls_copy(s, out->last, &p, len, &in) != NGX_OK) { - return NGX_ERROR; - } - - out->last += len; - } - - if (n == 1) { - break; - } - - /* number of PPS NALs */ - if (ngx_rtmp_hls_copy(s, &nnals, &p, 1, &in) != NGX_OK) { - return NGX_ERROR; - } - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "hls: PPS number: %uz", nnals); - } - - return NGX_OK; -} - - -static uint64_t -ngx_rtmp_hls_get_fragment_id(ngx_rtmp_session_t *s, uint64_t ts) -{ - ngx_rtmp_hls_ctx_t *ctx; - ngx_rtmp_hls_app_conf_t *hacf; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); - - hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module); - - switch (hacf->naming) { - - case NGX_RTMP_HLS_NAMING_TIMESTAMP: - return ts; - - case NGX_RTMP_HLS_NAMING_SYSTEM: - return (uint64_t) ngx_cached_time->sec * 1000 + ngx_cached_time->msec; - - default: /* NGX_RTMP_HLS_NAMING_SEQUENTIAL */ - return ctx->frag + ctx->nfrags; - } -} - - -static ngx_int_t -ngx_rtmp_hls_close_fragment(ngx_rtmp_session_t *s) -{ - ngx_rtmp_hls_ctx_t *ctx; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); - if (ctx == NULL || !ctx->opened) { - return NGX_OK; - } - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "hls: close fragment n=%uL", ctx->frag); - - ngx_rtmp_mpegts_close_file(&ctx->file); - - ctx->opened = 0; - - ngx_rtmp_hls_next_frag(s); - - ngx_rtmp_hls_write_playlist(s); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_hls_open_fragment(ngx_rtmp_session_t *s, uint64_t ts, - ngx_int_t discont) -{ - uint64_t id; - ngx_fd_t fd; - ngx_uint_t g; - ngx_rtmp_hls_ctx_t *ctx; - ngx_rtmp_hls_frag_t *f; - ngx_rtmp_hls_app_conf_t *hacf; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); - - if (ctx->opened) { - return NGX_OK; - } - - hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module); - - if (ngx_rtmp_hls_ensure_directory(s, &hacf->path) != NGX_OK) { - return NGX_ERROR; - } - - if (hacf->keys && - ngx_rtmp_hls_ensure_directory(s, &hacf->key_path) != NGX_OK) - { - return NGX_ERROR; - } - - id = ngx_rtmp_hls_get_fragment_id(s, ts); - - if (hacf->granularity) { - g = (ngx_uint_t) hacf->granularity; - id = (uint64_t) (id / g) * g; - } - - ngx_sprintf(ctx->stream.data + ctx->stream.len, "%uL.ts%Z", id); - - if (hacf->keys) { - if (ctx->key_frags == 0) { - - ctx->key_frags = hacf->frags_per_key - 1; - ctx->key_id = id; - - if (RAND_bytes(ctx->key, 16) < 0) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls: failed to create key"); - return NGX_ERROR; - } - - ngx_sprintf(ctx->keyfile.data + ctx->keyfile.len, "%uL.key%Z", id); - - fd = ngx_open_file(ctx->keyfile.data, NGX_FILE_WRONLY, - NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS); - - if (fd == NGX_INVALID_FILE) { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "hls: failed to open key file '%s'", - ctx->keyfile.data); - return NGX_ERROR; - } - - if (ngx_write_fd(fd, ctx->key, 16) != 16) { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "hls: failed to write key file '%s'", - ctx->keyfile.data); - ngx_close_file(fd); - return NGX_ERROR; - } - - ngx_close_file(fd); - - } else { - if (hacf->frags_per_key) { - ctx->key_frags--; - } - - if (ngx_set_file_time(ctx->keyfile.data, 0, ngx_cached_time->sec) - != NGX_OK) - { - ngx_log_error(NGX_LOG_ALERT, s->log, ngx_errno, - ngx_set_file_time_n " '%s' failed", - ctx->keyfile.data); - } - } - } - - ngx_log_debug6(NGX_LOG_DEBUG_RTMP, s->log, 0, - "hls: open fragment file='%s', keyfile='%s', " - "frag=%uL, n=%ui, time=%uL, discont=%i", - ctx->stream.data, - ctx->keyfile.data ? ctx->keyfile.data : (u_char *) "", - ctx->frag, ctx->nfrags, ts, discont); - - if (hacf->keys && - ngx_rtmp_mpegts_init_encryption(&ctx->file, ctx->key, 16, ctx->key_id) - != NGX_OK) - { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls: failed to initialize hls encryption"); - return NGX_ERROR; - } - - ctx->file.acodec = s->acodec; - ctx->file.vcodec = s->vcodec; - if (ngx_rtmp_mpegts_open_file(&ctx->file, ctx->stream.data, - s->log) - != NGX_OK) - { - return NGX_ERROR; - } - - ctx->opened = 1; - - f = ngx_rtmp_hls_get_frag(s, ctx->nfrags); - - ngx_memzero(f, sizeof(*f)); - - f->active = 1; - f->discont = discont; - f->id = id; - f->key_id = ctx->key_id; - - ctx->frag_ts = ts; - - /* start fragment with audio to make iPhone happy */ - - ngx_rtmp_hls_flush_audio(s); - - return NGX_OK; -} - - -static void -ngx_rtmp_hls_restore_stream(ngx_rtmp_session_t *s) -{ - ngx_rtmp_hls_ctx_t *ctx; - ngx_file_t file; - ssize_t ret; - off_t offset; - u_char *p, *last, *end, *next, *pa, *pp, c; - ngx_rtmp_hls_frag_t *f; - double duration; - ngx_int_t discont; - uint64_t mag, key_id, base; - static u_char buffer[4096]; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); - - ngx_memzero(&file, sizeof(file)); - - file.log = s->log; - - ngx_str_set(&file.name, "m3u8"); - - file.fd = ngx_open_file(ctx->playlist.data, NGX_FILE_RDONLY, NGX_FILE_OPEN, - 0); - if (file.fd == NGX_INVALID_FILE) { - return; - } - - offset = 0; - ctx->nfrags = 0; - f = NULL; - duration = 0; - discont = 0; - key_id = 0; - - for ( ;; ) { - - ret = ngx_read_file(&file, buffer, sizeof(buffer), offset); - if (ret <= 0) { - goto done; - } - - p = buffer; - end = buffer + ret; - - for ( ;; ) { - last = ngx_strlchr(p, end, '\n'); - - if (last == NULL) { - if (p == buffer) { - goto done; - } - break; - } - - next = last + 1; - offset += (next - p); - - if (p != last && last[-1] == '\r') { - last--; - } - - -#define NGX_RTMP_MSEQ "#EXT-X-MEDIA-SEQUENCE:" -#define NGX_RTMP_MSEQ_LEN (sizeof(NGX_RTMP_MSEQ) - 1) - - - if (ngx_memcmp(p, NGX_RTMP_MSEQ, NGX_RTMP_MSEQ_LEN) == 0) { - - ctx->frag = (uint64_t) strtod((const char *) - &p[NGX_RTMP_MSEQ_LEN], NULL); - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "hls: restore sequence frag=%uL", ctx->frag); - } - - -#define NGX_RTMP_XKEY "#EXT-X-KEY:" -#define NGX_RTMP_XKEY_LEN (sizeof(NGX_RTMP_XKEY) - 1) - - if (ngx_memcmp(p, NGX_RTMP_XKEY, NGX_RTMP_XKEY_LEN) == 0) { - - /* recover key id from initialization vector */ - - key_id = 0; - base = 1; - pp = last - 1; - - for ( ;; ) { - if (pp < p) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls: failed to read key id"); - break; - } - - c = *pp; - if (c == 'x') { - break; - } - - if (c >= '0' && c <= '9') { - c -= '0'; - goto next; - } - - c |= 0x20; - - if (c >= 'a' && c <= 'f') { - c -= 'a' - 10; - goto next; - } - - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls: bad character in key id"); - break; - - next: - - key_id += base * c; - base *= 0x10; - pp--; - } - } - - -#define NGX_RTMP_EXTINF "#EXTINF:" -#define NGX_RTMP_EXTINF_LEN (sizeof(NGX_RTMP_EXTINF) - 1) - - - if (ngx_memcmp(p, NGX_RTMP_EXTINF, NGX_RTMP_EXTINF_LEN) == 0) { - - duration = strtod((const char *) &p[NGX_RTMP_EXTINF_LEN], NULL); - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "hls: restore durarion=%.3f", duration); - } - - -#define NGX_RTMP_DISCONT "#EXT-X-DISCONTINUITY" -#define NGX_RTMP_DISCONT_LEN (sizeof(NGX_RTMP_DISCONT) - 1) - - - if (ngx_memcmp(p, NGX_RTMP_DISCONT, NGX_RTMP_DISCONT_LEN) == 0) { - - discont = 1; - - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->log, 0, - "hls: discontinuity"); - } - - /* find '.ts\r' */ - - if (p + 4 <= last && - last[-3] == '.' && last[-2] == 't' && last[-1] == 's') - { - f = ngx_rtmp_hls_get_frag(s, ctx->nfrags); - - ngx_memzero(f, sizeof(*f)); - - f->duration = duration; - f->discont = discont; - f->active = 1; - f->id = 0; - - discont = 0; - - mag = 1; - for (pa = last - 4; pa >= p; pa--) { - if (*pa < '0' || *pa > '9') { - break; - } - f->id += (*pa - '0') * mag; - mag *= 10; - } - - f->key_id = key_id; - - ngx_rtmp_hls_next_frag(s); - - ngx_log_debug6(NGX_LOG_DEBUG_RTMP, s->log, 0, - "hls: restore fragment '%*s' id=%uL, " - "duration=%.3f, frag=%uL, nfrags=%ui", - (size_t) (last - p), p, f->id, f->duration, - ctx->frag, ctx->nfrags); - } - - p = next; - } - } - -done: - ngx_close_file(file.fd); -} - - -static ngx_int_t -ngx_rtmp_hls_ensure_directory(ngx_rtmp_session_t *s, ngx_str_t *path) -{ - size_t len; - ngx_file_info_t fi; - ngx_rtmp_hls_ctx_t *ctx; - ngx_rtmp_hls_app_conf_t *hacf; - - static u_char zpath[NGX_MAX_PATH + 1]; - - hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module); - - if (path->len + 1 > sizeof(zpath)) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, "hls: too long path"); - return NGX_ERROR; - } - - ngx_snprintf(zpath, sizeof(zpath), "%V%Z", path); - - if (ngx_file_info(zpath, &fi) == NGX_FILE_ERROR) { - - if (ngx_errno != NGX_ENOENT) { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "hls: " ngx_file_info_n " failed on '%V'", path); - return NGX_ERROR; - } - - /* ENOENT */ - - if (ngx_create_dir(zpath, NGX_RTMP_HLS_DIR_ACCESS) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "hls: " ngx_create_dir_n " failed on '%V'", path); - return NGX_ERROR; - } - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "hls: directory '%V' created", path); - - } else { - - if (!ngx_is_dir(&fi)) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls: '%V' exists and is not a directory", path); - return NGX_ERROR; - } - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "hls: directory '%V' exists", path); - } - - if (!hacf->nested) { - return NGX_OK; - } - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); - - len = path->len; - if (path->data[len - 1] == '/') { - len--; - } - - if (len + 1 + ctx->name.len + 1 > sizeof(zpath)) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, "hls: too long path"); - return NGX_ERROR; - } - - ngx_snprintf(zpath, sizeof(zpath) - 1, "%*s/%V%Z", len, path->data, - &ctx->name); - - if (ngx_file_info(zpath, &fi) != NGX_FILE_ERROR) { - - if (ngx_is_dir(&fi)) { - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "hls: directory '%s' exists", zpath); - return NGX_OK; - } - - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls: '%s' exists and is not a directory", zpath); - - return NGX_ERROR; - } - - if (ngx_errno != NGX_ENOENT) { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "hls: " ngx_file_info_n " failed on '%s'", zpath); - return NGX_ERROR; - } - - /* NGX_ENOENT */ - - if (ngx_create_dir(zpath, NGX_RTMP_HLS_DIR_ACCESS) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "hls: " ngx_create_dir_n " failed on '%s'", zpath); - return NGX_ERROR; - } - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "hls: directory '%s' created", zpath); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_hls_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v) -{ - ngx_rtmp_hls_app_conf_t *hacf; - ngx_rtmp_hls_ctx_t *ctx; - u_char *p, *pp; - ngx_rtmp_hls_frag_t *f; - ngx_buf_t *b; - size_t len; - ngx_rtmp_hls_variant_t *var; - ngx_uint_t n; - - hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module); - if (hacf == NULL || !hacf->hls || hacf->path.len == 0) { - goto next; - } - - if (s->interprocess) { - goto next; - } - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->log, 0, - "hls: publish: name='%s' type='%s'", - v->name, v->type); - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); - - if (ctx == NULL) { - - ctx = ngx_pcalloc(s->pool, sizeof(ngx_rtmp_hls_ctx_t)); - ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_hls_module); - - } else { - - f = ctx->frags; - b = ctx->aframe; - - ngx_memzero(ctx, sizeof(ngx_rtmp_hls_ctx_t)); - - ctx->frags = f; - ctx->aframe = b; - - if (b) { - b->pos = b->last = b->start; - } - } - - if (ctx->frags == NULL) { - ctx->frags = ngx_pcalloc(s->pool, - sizeof(ngx_rtmp_hls_frag_t) * - (hacf->winfrags * 2 + 1)); - if (ctx->frags == NULL) { - return NGX_ERROR; - } - } - - if (ngx_strstr(v->name, "..")) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls: bad stream name: '%s'", v->name); - return NGX_ERROR; - } - - ctx->name.len = ngx_strlen(v->name); - ctx->name.data = ngx_palloc(s->pool, ctx->name.len + 1); - - if (ctx->name.data == NULL) { - return NGX_ERROR; - } - - *ngx_cpymem(ctx->name.data, v->name, ctx->name.len) = 0; - - len = hacf->path.len + 1 + ctx->name.len + sizeof(".m3u8"); - if (hacf->nested) { - len += sizeof("/index") - 1; - } - - ctx->playlist.data = ngx_palloc(s->pool, len); - p = ngx_cpymem(ctx->playlist.data, hacf->path.data, hacf->path.len); - - if (p[-1] != '/') { - *p++ = '/'; - } - - p = ngx_cpymem(p, ctx->name.data, ctx->name.len); - - /* - * ctx->stream holds initial part of stream file path - * however the space for the whole stream path - * is allocated - */ - - ctx->stream.len = p - ctx->playlist.data + 1; - ctx->stream.data = ngx_palloc(s->pool, - ctx->stream.len + NGX_INT64_LEN + - sizeof(".ts")); - - ngx_memcpy(ctx->stream.data, ctx->playlist.data, ctx->stream.len - 1); - ctx->stream.data[ctx->stream.len - 1] = (hacf->nested ? '/' : '-'); - - /* varint playlist path */ - - if (hacf->variant) { - var = hacf->variant->elts; - for (n = 0; n < hacf->variant->nelts; n++, var++) { - if (ctx->name.len > var->suffix.len && - ngx_memcmp(var->suffix.data, - ctx->name.data + ctx->name.len - var->suffix.len, - var->suffix.len) - == 0) - { - ctx->var = var; - - len = (size_t) (p - ctx->playlist.data); - - ctx->var_playlist.len = len - var->suffix.len + sizeof(".m3u8") - - 1; - ctx->var_playlist.data = ngx_palloc(s->pool, - ctx->var_playlist.len + 1); - - pp = ngx_cpymem(ctx->var_playlist.data, ctx->playlist.data, - len - var->suffix.len); - pp = ngx_cpymem(pp, ".m3u8", sizeof(".m3u8") - 1); - *pp = 0; - - ctx->var_playlist_bak.len = ctx->var_playlist.len + - sizeof(".bak") - 1; - ctx->var_playlist_bak.data = ngx_palloc(s->pool, - ctx->var_playlist_bak.len + 1); - - pp = ngx_cpymem(ctx->var_playlist_bak.data, - ctx->var_playlist.data, - ctx->var_playlist.len); - pp = ngx_cpymem(pp, ".bak", sizeof(".bak") - 1); - *pp = 0; - - break; - } - } - } - - - /* playlist path */ - - if (hacf->nested) { - p = ngx_cpymem(p, "/index.m3u8", sizeof("/index.m3u8") - 1); - } else { - p = ngx_cpymem(p, ".m3u8", sizeof(".m3u8") - 1); - } - - ctx->playlist.len = p - ctx->playlist.data; - - *p = 0; - - /* playlist bak (new playlist) path */ - - ctx->playlist_bak.data = ngx_palloc(s->pool, - ctx->playlist.len + sizeof(".bak")); - p = ngx_cpymem(ctx->playlist_bak.data, ctx->playlist.data, - ctx->playlist.len); - p = ngx_cpymem(p, ".bak", sizeof(".bak") - 1); - - ctx->playlist_bak.len = p - ctx->playlist_bak.data; - - *p = 0; - - /* key path */ - - if (hacf->keys) { - len = hacf->key_path.len + 1 + ctx->name.len + 1 + NGX_INT64_LEN - + sizeof(".key"); - - ctx->keyfile.data = ngx_palloc(s->pool, len); - if (ctx->keyfile.data == NULL) { - return NGX_ERROR; - } - - p = ngx_cpymem(ctx->keyfile.data, hacf->key_path.data, - hacf->key_path.len); - - if (p[-1] != '/') { - *p++ = '/'; - } - - p = ngx_cpymem(p, ctx->name.data, ctx->name.len); - *p++ = (hacf->nested ? '/' : '-'); - - ctx->keyfile.len = p - ctx->keyfile.data; - } - - ngx_log_debug4(NGX_LOG_DEBUG_RTMP, s->log, 0, - "hls: playlist='%V' playlist_bak='%V' " - "stream_pattern='%V' keyfile_pattern='%V'", - &ctx->playlist, &ctx->playlist_bak, - &ctx->stream, &ctx->keyfile); - - if (hacf->continuous) { - ngx_rtmp_hls_restore_stream(s); - } - -next: - return next_publish(s, v); -} - - -static ngx_int_t -ngx_rtmp_hls_close_stream(ngx_rtmp_session_t *s, ngx_rtmp_close_stream_t *v) -{ - ngx_rtmp_hls_app_conf_t *hacf; - ngx_rtmp_hls_ctx_t *ctx; - - hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module); - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); - - if (hacf == NULL || !hacf->hls || ctx == NULL) { - goto next; - } - - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->log, 0, - "hls: close stream"); - - ngx_rtmp_hls_close_fragment(s); - -next: - return next_close_stream(s, v); -} - - -static ngx_int_t -ngx_rtmp_hls_parse_aac_header(ngx_rtmp_session_t *s, ngx_uint_t *objtype, - ngx_uint_t *srindex, ngx_uint_t *chconf) -{ - ngx_rtmp_codec_ctx_t *codec_ctx; - ngx_chain_t *cl; - u_char *p, b0, b1; - - codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - - cl = codec_ctx->aac_header->chain; - - p = cl->buf->pos; - - if (ngx_rtmp_hls_copy(s, NULL, &p, 2, &cl) != NGX_OK) { - return NGX_ERROR; - } - - if (ngx_rtmp_hls_copy(s, &b0, &p, 1, &cl) != NGX_OK) { - return NGX_ERROR; - } - - if (ngx_rtmp_hls_copy(s, &b1, &p, 1, &cl) != NGX_OK) { - return NGX_ERROR; - } - - *objtype = b0 >> 3; - if (*objtype == 0 || *objtype == 0x1f) { - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "hls: unsupported adts object type:%ui", *objtype); - return NGX_ERROR; - } - - if (*objtype > 4) { - - /* - * Mark all extended profiles as LC - * to make Android as happy as possible. - */ - - *objtype = 2; - } - - *srindex = ((b0 << 1) & 0x0f) | ((b1 & 0x80) >> 7); - if (*srindex == 0x0f) { - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "hls: unsupported adts sample rate:%ui", *srindex); - return NGX_ERROR; - } - - *chconf = (b1 >> 3) & 0x0f; - - ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->log, 0, - "hls: aac object_type:%ui, sample_rate_index:%ui, " - "channel_config:%ui", *objtype, *srindex, *chconf); - - return NGX_OK; -} - - -static void -ngx_rtmp_hls_update_fragment(ngx_rtmp_session_t *s, uint64_t ts, - ngx_int_t boundary, ngx_uint_t flush_rate) -{ - ngx_rtmp_hls_ctx_t *ctx; - ngx_rtmp_hls_app_conf_t *hacf; - ngx_rtmp_hls_frag_t *f; - ngx_msec_t ts_frag_len; - ngx_int_t same_frag, force,discont; - ngx_buf_t *b; - int64_t d; - - hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module); - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); - f = NULL; - force = 0; - discont = 1; - - if (ctx->opened) { - f = ngx_rtmp_hls_get_frag(s, ctx->nfrags); - d = (int64_t) (ts - ctx->frag_ts); - - if (d > (int64_t) hacf->max_fraglen * 90 || d < -90000) { - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "hls: force fragment split: %.3f sec, ", d / 90000.); - force = 1; - - } else { - f->duration = (ts - ctx->frag_ts) / 90000.; - discont = 0; - } - } - - switch (hacf->slicing) { - case NGX_RTMP_HLS_SLICING_PLAIN: - if (f && f->duration < hacf->fraglen / 1000.) { - boundary = 0; - } - break; - - case NGX_RTMP_HLS_SLICING_ALIGNED: - - ts_frag_len = hacf->fraglen * 90; - same_frag = ctx->frag_ts / ts_frag_len == ts / ts_frag_len; - - if (f && same_frag) { - boundary = 0; - } - - if (f == NULL && (ctx->frag_ts == 0 || same_frag)) { - ctx->frag_ts = ts; - boundary = 0; - } - - break; - } - - if (boundary || force) { - ngx_rtmp_hls_close_fragment(s); - ngx_rtmp_hls_open_fragment(s, ts, discont); - } - - b = ctx->aframe; - if (ctx->opened && b && b->last > b->pos && - ctx->aframe_pts + (uint64_t) hacf->max_audio_delay * 90 / flush_rate - < ts) - { - ngx_rtmp_hls_flush_audio(s); - } -} - - -static ngx_int_t -ngx_rtmp_hls_flush_audio(ngx_rtmp_session_t *s) -{ - ngx_rtmp_hls_ctx_t *ctx; - ngx_rtmp_mpegts_frame_t frame; - ngx_int_t rc; - ngx_buf_t *b; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); - - if (ctx == NULL || !ctx->opened) { - return NGX_OK; - } - - b = ctx->aframe; - - if (b == NULL || b->pos == b->last) { - return NGX_OK; - } - - ngx_memzero(&frame, sizeof(frame)); - - frame.dts = ctx->aframe_pts; - frame.pts = frame.dts; - frame.cc = ctx->audio_cc; - frame.pid = 0x101; - frame.sid = 0xc0; - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "hls: flush audio pts=%uL", frame.pts); - - rc = ngx_rtmp_mpegts_write_frame(&ctx->file, &frame, b); - - if (rc != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls: audio flush failed"); - } - - ctx->audio_cc = frame.cc; - b->pos = b->last = b->start; - - return rc; -} - - -static ngx_int_t -ngx_rtmp_hls_audio(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - ngx_rtmp_hls_app_conf_t *hacf; - ngx_rtmp_hls_ctx_t *ctx; - ngx_rtmp_codec_ctx_t *codec_ctx; - uint64_t pts, est_pts; - int64_t dpts; - size_t bsize; - ngx_buf_t *b; - u_char *p = NULL; - ngx_uint_t objtype, srindex, chconf, size = 0; - ngx_flag_t mp3_tag = 0; - - hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module); - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); - - codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - - if (hacf == NULL || !hacf->hls || ctx == NULL || - codec_ctx == NULL || h->mlen < 2) - { - return NGX_OK; - } - - if ((codec_ctx->audio_codec_id != NGX_RTMP_AUDIO_AAC || - codec_ctx->aac_header == NULL || ngx_rtmp_is_codec_header(in)) && - codec_ctx->audio_codec_id != NGX_RTMP_AUDIO_MP3) - { - return NGX_OK; - } - - if (s->pause) { - return NGX_OK; - } - - b = ctx->aframe; - - if (b == NULL) { - - b = ngx_pcalloc(s->pool, sizeof(ngx_buf_t)); - if (b == NULL) { - return NGX_ERROR; - } - - ctx->aframe = b; - - b->start = ngx_palloc(s->pool, hacf->audio_buffer_size); - if (b->start == NULL) { - return NGX_ERROR; - } - - b->end = b->start + hacf->audio_buffer_size; - b->pos = b->last = b->start; - } - - if (codec_ctx->audio_codec_id == NGX_RTMP_AUDIO_AAC) { - size = h->mlen - 2 + 7; - } else if (codec_ctx->audio_codec_id == NGX_RTMP_AUDIO_MP3) { - size = h->mlen - 1; - } - - pts = (uint64_t) h->timestamp * 90; - - if (b->start + size > b->end) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls: too big audio frame"); - return NGX_OK; - } - - /* - * start new fragment here if - * there's no video at all, otherwise - * do it in video handler - */ - - ngx_rtmp_hls_update_fragment(s, pts, codec_ctx->avc_header == NULL, 2); - - if (b->last + size > b->end) { - ngx_rtmp_hls_flush_audio(s); - } - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "hls: audio pts=%uL", pts); - - if (codec_ctx->audio_codec_id == NGX_RTMP_AUDIO_AAC) { - if (b->last + 7 > b->end) { - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->log, 0, - "hls: not enough buffer for audio header"); - return NGX_OK; - } - - p = b->last; - b->last += 5; - - /* copy payload */ - - for (; in && b->last < b->end; in = in->next) { - - bsize = in->buf->last - in->buf->pos; - if (b->last + bsize > b->end) { - bsize = b->end - b->last; - } - - b->last = ngx_cpymem(b->last, in->buf->pos, bsize); - } - - /* make up ADTS header */ - - if (ngx_rtmp_hls_parse_aac_header(s, &objtype, &srindex, &chconf) - != NGX_OK) - { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls: aac header error"); - return NGX_OK; - } - - /* we have 5 free bytes + 2 bytes of RTMP frame header */ - - p[0] = 0xff; - p[1] = 0xf1; - p[2] = (u_char) (((objtype - 1) << 6) | (srindex << 2) | - ((chconf & 0x04) >> 2)); - p[3] = (u_char) (((chconf & 0x03) << 6) | ((size >> 11) & 0x03)); - p[4] = (u_char) (size >> 3); - p[5] = (u_char) ((size << 5) | 0x1f); - p[6] = 0xfc; - } else if (codec_ctx->audio_codec_id == NGX_RTMP_AUDIO_MP3) { - if (b->last > b->end) { - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->log, 0, - "hls: not enough buffer for audio header"); - return NGX_OK; - } - - p = b->last; - - /* copy payload */ - - for (; in && b->last < b->end; in = in->next) { - - bsize = in->buf->last - in->buf->pos; - if (b->last + bsize > b->end) { - bsize = b->end - b->last; - } - - if (0 == mp3_tag) { - b->last = ngx_cpymem(b->last, in->buf->pos+1, bsize-1); - mp3_tag = 1; - } else { - b->last = ngx_cpymem(b->last, in->buf->pos, bsize); - } - } - } - - if (p != b->start) { - ctx->aframe_num++; - return NGX_OK; - } - - ctx->aframe_pts = pts; - - if (!hacf->sync || codec_ctx->sample_rate == 0) { - return NGX_OK; - } - - /* align audio frames */ - - /* TODO: We assume here AAC frame size is 1024 - * Need to handle AAC frames with frame size of 960 */ - - est_pts = ctx->aframe_base + ctx->aframe_num * 90000 * 1024 / - codec_ctx->sample_rate; - dpts = (int64_t) (est_pts - pts); - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->log, 0, - "hls: audio sync dpts=%L (%.5fs)", - dpts, dpts / 90000.); - - if (dpts <= (int64_t) hacf->sync * 90 && - dpts >= (int64_t) hacf->sync * -90) - { - ctx->aframe_num++; - ctx->aframe_pts = est_pts; - return NGX_OK; - } - - ctx->aframe_base = pts; - ctx->aframe_num = 1; - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->log, 0, - "hls: audio sync gap dpts=%L (%.5fs)", - dpts, dpts / 90000.); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_hls_video(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - ngx_rtmp_hls_app_conf_t *hacf; - ngx_rtmp_hls_ctx_t *ctx; - ngx_rtmp_codec_ctx_t *codec_ctx; - u_char *p; - uint8_t fmt, ftype, htype, nal_type, src_nal_type; - uint32_t len, rlen; - ngx_buf_t out, *b; - uint32_t cts; - ngx_rtmp_mpegts_frame_t frame; - ngx_uint_t nal_bytes; - ngx_int_t aud_sent, sps_pps_sent, boundary; - static u_char buffer[NGX_RTMP_HLS_BUFSIZE]; - ngx_rtmp_core_app_conf_t *cacf; - - cacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_core_module); - - hacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_hls_module); - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_hls_module); - - codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - - if (hacf == NULL || !hacf->hls || ctx == NULL || codec_ctx == NULL || - codec_ctx->avc_header == NULL || h->mlen < 1) - { - return NGX_OK; - } - - /* Only H264 is supported */ - if (codec_ctx->video_codec_id != NGX_RTMP_VIDEO_H264 && - codec_ctx->video_codec_id != cacf->hevc_codec) - { - return NGX_OK; - } - - if (s->pause) { - return NGX_OK; - } - - p = in->buf->pos; - if (ngx_rtmp_hls_copy(s, &fmt, &p, 1, &in) != NGX_OK) { - return NGX_ERROR; - } - - /* 1: keyframe (IDR) - * 2: inter frame - * 3: disposable inter frame */ - - ftype = (fmt & 0xf0) >> 4; - - /* H264 HDR/PICT */ - - if (ngx_rtmp_hls_copy(s, &htype, &p, 1, &in) != NGX_OK) { - return NGX_ERROR; - } - - /* proceed only with PICT */ - - if (htype != 1) { - return NGX_OK; - } - - /* 3 bytes: decoder delay */ - - if (ngx_rtmp_hls_copy(s, &cts, &p, 3, &in) != NGX_OK) { - return NGX_ERROR; - } - - cts = ((cts & 0x00FF0000) >> 16) | ((cts & 0x000000FF) << 16) | - (cts & 0x0000FF00); - - ngx_memzero(&out, sizeof(out)); - - out.start = buffer; - out.end = buffer + sizeof(buffer); - out.pos = out.start; - out.last = out.pos; - - nal_bytes = codec_ctx->avc_nal_bytes; - aud_sent = 0; - sps_pps_sent = 0; - - while (in) { - if (ngx_rtmp_hls_copy(s, &rlen, &p, nal_bytes, &in) != NGX_OK) { - return NGX_OK; - } - - len = 0; - ngx_rtmp_rmemcpy(&len, &rlen, nal_bytes); - - if (len == 0) { - continue; - } - - if (ngx_rtmp_hls_copy(s, &src_nal_type, &p, 1, &in) != NGX_OK) { - return NGX_OK; - } - - if (codec_ctx->video_codec_id == NGX_RTMP_VIDEO_H264) { - nal_type = src_nal_type & 0x1f; - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->log, 0, - "hls: h264 NAL type=%ui, len=%uD", - (ngx_uint_t) nal_type, len); - - if (nal_type >= 7 && nal_type <= 9) { - if (ngx_rtmp_hls_copy(s, NULL, &p, len - 1, &in) != NGX_OK) { - return NGX_ERROR; - } - continue; - } - - if (!aud_sent) { - switch (nal_type) { - case 1: - case 5: - case 6: - if (ngx_rtmp_hls_append_aud(s, &out) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls: error appending AUD NAL"); - } - aud_sent = 1; - break; - - case 9: - aud_sent = 1; - break; - } - } - - switch (nal_type) { - case 1: - sps_pps_sent = 0; - break; - case 5: - if (sps_pps_sent) { - break; - } - if (ngx_rtmp_hls_append_sps_pps(s, &out) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls: error appenging SPS/PPS NALs"); - } - sps_pps_sent = 1; - break; - } - } else { - if (src_nal_type == 0) { - if (ngx_rtmp_hls_copy(s, out.last, &p, 3, &in) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "rtmp-hls: video| buffer error"); - return NGX_ERROR; - } - if (out.last[0] == 0x00 && out.last[1] == 0x00 && - out.last[2] == 0x01) - { - ngx_rtmp_hls_copy(s, &src_nal_type, &p, 1, &in); - len -= 4; - } else { - p -= 3; - } - } - - nal_type = (src_nal_type >> 1) & 0x3f; - - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "hls: h265 NAL type=%ui, len=%uD", - (ngx_uint_t) nal_type, len); - - if (nal_type == 32 // VPS - || nal_type == 33 // SPS - || nal_type == 34 // PPS - || nal_type == 35 // AUD - ) - { - if (ngx_rtmp_hls_copy(s, NULL, &p, len - 1, &in) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "rtmp-hls: video| jump nal, failed copy "); - return NGX_ERROR; - } - continue; - } - - if (!aud_sent) { - if (ngx_rtmp_hls_append_hevc_aud(s, &out) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls: error appending AUD NAL"); - } - aud_sent = 1; - } - - if (!IS_IRAP(nal_type)) { - sps_pps_sent = 0; - } else if (!sps_pps_sent) { - if (ngx_rtmp_hls_append_hevc_vps_sps_pps(s, &out) != NGX_OK) - { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls: error appenging VPS/SPS/PPS NALs"); - } - sps_pps_sent = 1; - } - } - - /* AnnexB prefix */ - - if (out.end - out.last < 5) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls: not enough buffer for AnnexB prefix"); - return NGX_OK; - } - - /* first AnnexB prefix is long (4 bytes) */ - - if (out.last == out.pos) { - *out.last++ = 0; - } - - *out.last++ = 0; - *out.last++ = 0; - *out.last++ = 1; - *out.last++ = src_nal_type; - - /* NAL body */ - - if (out.end - out.last < (ngx_int_t) len) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls: not enough buffer for NAL"); - return NGX_OK; - } - - if (ngx_rtmp_hls_copy(s, out.last, &p, len - 1, &in) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "rtmp-hls: video| copy nal, failed copy, len %d, in %d", - len - 1, in->buf->last - in->buf->pos); - return NGX_ERROR; - } - - out.last += (len - 1); - } - - ngx_memzero(&frame, sizeof(frame)); - - frame.cc = ctx->video_cc; - frame.dts = (uint64_t) h->timestamp * 90; - frame.pts = frame.dts + cts * 90; - frame.pid = 0x100; - frame.sid = 0xe0; - frame.key = (ftype == 1); - - /* - * start new fragment if - * - we have video key frame AND - * - we have audio buffered or have no audio at all or stream is closed - */ - - b = ctx->aframe; - boundary = frame.key && (codec_ctx->aac_header == NULL || !ctx->opened || - (b && b->last > b->pos)); - - ngx_rtmp_hls_update_fragment(s, frame.dts, boundary, 1); - - if (!ctx->opened) { - return NGX_OK; - } - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->log, 0, - "hls: video pts=%uL, dts=%uL", frame.pts, frame.dts); - - if (ngx_rtmp_mpegts_write_frame(&ctx->file, &frame, &out) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls: video frame failed"); - } - - ctx->video_cc = frame.cc; - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_hls_stream_begin(ngx_rtmp_session_t *s, ngx_rtmp_stream_begin_t *v) -{ - return next_stream_begin(s, v); -} - - -static ngx_int_t -ngx_rtmp_hls_stream_eof(ngx_rtmp_session_t *s, ngx_rtmp_stream_eof_t *v) -{ - ngx_rtmp_hls_flush_audio(s); - - ngx_rtmp_hls_close_fragment(s); - - return next_stream_eof(s, v); -} - - -static ngx_int_t -ngx_rtmp_hls_cleanup_dir(ngx_str_t *ppath, ngx_msec_t playlen) -{ - ngx_dir_t dir; - time_t mtime, max_age; - ngx_err_t err; - ngx_str_t name, spath; - u_char *p; - ngx_int_t nentries, nerased; - u_char path[NGX_MAX_PATH + 1]; - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, ngx_cycle->log, 0, - "hls: cleanup path='%V' playlen=%M", - ppath, playlen); - - if (ngx_open_dir(ppath, &dir) != NGX_OK) { - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, ngx_cycle->log, ngx_errno, - "hls: cleanup open dir failed '%V'", ppath); - return NGX_ERROR; - } - - nentries = 0; - nerased = 0; - - for ( ;; ) { - ngx_set_errno(0); - - if (ngx_read_dir(&dir) == NGX_ERROR) { - err = ngx_errno; - - if (ngx_close_dir(&dir) == NGX_ERROR) { - ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, ngx_errno, - "hls: cleanup " ngx_close_dir_n " \"%V\" failed", - ppath); - } - - if (err == NGX_ENOMOREFILES) { - return nentries - nerased; - } - - ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, err, - "hls: cleanup " ngx_read_dir_n - " '%V' failed", ppath); - return NGX_ERROR; - } - - name.data = ngx_de_name(&dir); - if (name.data[0] == '.') { - continue; - } - - name.len = ngx_de_namelen(&dir); - - p = ngx_snprintf(path, sizeof(path) - 1, "%V/%V", ppath, &name); - *p = 0; - - spath.data = path; - spath.len = p - path; - - nentries++; - - if (!dir.valid_info && ngx_de_info(path, &dir) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, ngx_errno, - "hls: cleanup " ngx_de_info_n " \"%V\" failed", - &spath); - - continue; - } - - if (ngx_de_is_dir(&dir)) { - - if (ngx_rtmp_hls_cleanup_dir(&spath, playlen) == 0) { - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, ngx_cycle->log, 0, - "hls: cleanup dir '%V'", &name); - - /* - * null-termination gets spoiled in win32 - * version of ngx_open_dir - */ - - *p = 0; - - if (ngx_delete_dir(path) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, ngx_errno, - "hls: cleanup " ngx_delete_dir_n - " failed on '%V'", &spath); - } else { - nerased++; - } - } - - continue; - } - - if (!ngx_de_is_file(&dir)) { - continue; - } - - if (name.len >= 3 && name.data[name.len - 3] == '.' && - name.data[name.len - 2] == 't' && - name.data[name.len - 1] == 's') - { - max_age = playlen / 500; - - } else if (name.len >= 5 && name.data[name.len - 5] == '.' && - name.data[name.len - 4] == 'm' && - name.data[name.len - 3] == '3' && - name.data[name.len - 2] == 'u' && - name.data[name.len - 1] == '8') - { - max_age = playlen / 1000; - - } else if (name.len >= 4 && name.data[name.len - 4] == '.' && - name.data[name.len - 3] == 'k' && - name.data[name.len - 2] == 'e' && - name.data[name.len - 1] == 'y') - { - max_age = playlen / 500; - - } else { - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, ngx_cycle->log, 0, - "hls: cleanup skip unknown file type '%V'", &name); - continue; - } - - mtime = ngx_de_mtime(&dir); - if (mtime + max_age > ngx_cached_time->sec) { - continue; - } - - ngx_log_debug3(NGX_LOG_DEBUG_RTMP, ngx_cycle->log, 0, - "hls: cleanup '%V' mtime=%T age=%T", - &name, mtime, ngx_cached_time->sec - mtime); - - if (ngx_delete_file(path) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, ngx_errno, - "hls: cleanup " ngx_delete_file_n " failed on '%V'", - &spath); - continue; - } - - nerased++; - } -} - - -#if (nginx_version >= 1011005) -static ngx_msec_t -#else -static time_t -#endif -ngx_rtmp_hls_cleanup(void *data) -{ - ngx_rtmp_hls_cleanup_t *cleanup = data; - - ngx_rtmp_hls_cleanup_dir(&cleanup->path, cleanup->playlen); - -#if (nginx_version >= 1011005) - return cleanup->playlen * 2; -#else - return cleanup->playlen / 500; -#endif -} - - -static char * -ngx_rtmp_hls_variant(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_rtmp_hls_app_conf_t *hacf = conf; - - ngx_str_t *value, *arg; - ngx_uint_t n; - ngx_rtmp_hls_variant_t *var; - - value = cf->args->elts; - - if (hacf->variant == NULL) { - hacf->variant = ngx_array_create(cf->pool, 1, - sizeof(ngx_rtmp_hls_variant_t)); - if (hacf->variant == NULL) { - return NGX_CONF_ERROR; - } - } - - var = ngx_array_push(hacf->variant); - if (var == NULL) { - return NGX_CONF_ERROR; - } - - ngx_memzero(var, sizeof(ngx_rtmp_hls_variant_t)); - - var->suffix = value[1]; - - if (cf->args->nelts == 2) { - return NGX_CONF_OK; - } - - if (ngx_array_init(&var->args, cf->pool, cf->args->nelts - 2, - sizeof(ngx_str_t)) - != NGX_OK) - { - return NGX_CONF_ERROR; - } - - arg = ngx_array_push_n(&var->args, cf->args->nelts - 2); - if (arg == NULL) { - return NGX_CONF_ERROR; - } - - for (n = 2; n < cf->args->nelts; n++) { - *arg++ = value[n]; - } - - return NGX_CONF_OK; -} - - -static void * -ngx_rtmp_hls_create_app_conf(ngx_conf_t *cf) -{ - ngx_rtmp_hls_app_conf_t *conf; - - conf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_hls_app_conf_t)); - if (conf == NULL) { - return NULL; - } - - conf->hls = NGX_CONF_UNSET; - conf->fraglen = NGX_CONF_UNSET_MSEC; - conf->max_fraglen = NGX_CONF_UNSET_MSEC; - conf->muxdelay = NGX_CONF_UNSET_MSEC; - conf->sync = NGX_CONF_UNSET_MSEC; - conf->playlen = NGX_CONF_UNSET_MSEC; - conf->continuous = NGX_CONF_UNSET; - conf->nested = NGX_CONF_UNSET; - conf->naming = NGX_CONF_UNSET_UINT; - conf->slicing = NGX_CONF_UNSET_UINT; - conf->type = NGX_CONF_UNSET_UINT; - conf->max_audio_delay = NGX_CONF_UNSET_MSEC; - conf->audio_buffer_size = NGX_CONF_UNSET_SIZE; - conf->cleanup = NGX_CONF_UNSET; - conf->granularity = NGX_CONF_UNSET; - conf->keys = NGX_CONF_UNSET; - conf->frags_per_key = NGX_CONF_UNSET_UINT; - - return conf; -} - - -static char * -ngx_rtmp_hls_merge_app_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_rtmp_hls_app_conf_t *prev = parent; - ngx_rtmp_hls_app_conf_t *conf = child; - ngx_rtmp_hls_cleanup_t *cleanup; - - ngx_conf_merge_value(conf->hls, prev->hls, 0); - ngx_conf_merge_msec_value(conf->fraglen, prev->fraglen, 5000); - ngx_conf_merge_msec_value(conf->max_fraglen, prev->max_fraglen, - conf->fraglen * 10); - ngx_conf_merge_msec_value(conf->muxdelay, prev->muxdelay, 700); - ngx_conf_merge_msec_value(conf->sync, prev->sync, 2); - ngx_conf_merge_msec_value(conf->playlen, prev->playlen, 30000); - ngx_conf_merge_value(conf->continuous, prev->continuous, 1); - ngx_conf_merge_value(conf->nested, prev->nested, 0); - ngx_conf_merge_uint_value(conf->naming, prev->naming, - NGX_RTMP_HLS_NAMING_SEQUENTIAL); - ngx_conf_merge_uint_value(conf->slicing, prev->slicing, - NGX_RTMP_HLS_SLICING_PLAIN); - ngx_conf_merge_uint_value(conf->type, prev->type, - NGX_RTMP_HLS_TYPE_LIVE); - ngx_conf_merge_msec_value(conf->max_audio_delay, prev->max_audio_delay, - 300); - ngx_conf_merge_size_value(conf->audio_buffer_size, prev->audio_buffer_size, - NGX_RTMP_HLS_BUFSIZE); - ngx_conf_merge_value(conf->cleanup, prev->cleanup, 1); - ngx_conf_merge_str_value(conf->base_url, prev->base_url, ""); - ngx_conf_merge_value(conf->granularity, prev->granularity, 0); - ngx_conf_merge_value(conf->keys, prev->keys, 0); - ngx_conf_merge_str_value(conf->key_path, prev->key_path, ""); - ngx_conf_merge_str_value(conf->key_url, prev->key_url, ""); - ngx_conf_merge_uint_value(conf->frags_per_key, prev->frags_per_key, 0); - - if (conf->fraglen) { - conf->winfrags = conf->playlen / conf->fraglen; - } - - /* schedule cleanup */ - - if (conf->hls && conf->path.len && conf->cleanup && - conf->type != NGX_RTMP_HLS_TYPE_EVENT) - { - if (conf->path.data[conf->path.len - 1] == '/') { - conf->path.len--; - } - - cleanup = ngx_pcalloc(cf->pool, sizeof(*cleanup)); - if (cleanup == NULL) { - return NGX_CONF_ERROR; - } - - cleanup->path = conf->path; - cleanup->playlen = conf->playlen; - - conf->slot = ngx_pcalloc(cf->pool, sizeof(*conf->slot)); - if (conf->slot == NULL) { - return NGX_CONF_ERROR; - } - - conf->slot->manager = ngx_rtmp_hls_cleanup; - conf->slot->name = conf->path; - conf->slot->data = cleanup; - conf->slot->conf_file = cf->conf_file->file.name.data; - conf->slot->line = cf->conf_file->line; - - if (ngx_add_path(cf, &conf->slot) != NGX_OK) { - return NGX_CONF_ERROR; - } - } - - ngx_conf_merge_str_value(conf->path, prev->path, ""); - - if (conf->keys && conf->cleanup && conf->key_path.len && - ngx_strcmp(conf->key_path.data, conf->path.data) != 0 && - conf->type != NGX_RTMP_HLS_TYPE_EVENT) - { - if (conf->key_path.data[conf->key_path.len - 1] == '/') { - conf->key_path.len--; - } - - cleanup = ngx_pcalloc(cf->pool, sizeof(*cleanup)); - if (cleanup == NULL) { - return NGX_CONF_ERROR; - } - - cleanup->path = conf->key_path; - cleanup->playlen = conf->playlen; - - conf->slot = ngx_pcalloc(cf->pool, sizeof(*conf->slot)); - if (conf->slot == NULL) { - return NGX_CONF_ERROR; - } - - conf->slot->manager = ngx_rtmp_hls_cleanup; - conf->slot->name = conf->key_path; - conf->slot->data = cleanup; - conf->slot->conf_file = cf->conf_file->file.name.data; - conf->slot->line = cf->conf_file->line; - - if (ngx_add_path(cf, &conf->slot) != NGX_OK) { - return NGX_CONF_ERROR; - } - } - - ngx_conf_merge_str_value(conf->key_path, prev->key_path, ""); - - if (conf->key_path.len == 0) { - conf->key_path = conf->path; - } - - return NGX_CONF_OK; -} - - -static ngx_int_t -ngx_rtmp_hls_postconfiguration(ngx_conf_t *cf) -{ - ngx_rtmp_core_main_conf_t *cmcf; - ngx_rtmp_handler_pt *h; - - cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module); - - h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_VIDEO]); - *h = ngx_rtmp_hls_video; - - h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_AUDIO]); - *h = ngx_rtmp_hls_audio; - - next_publish = ngx_rtmp_publish; - ngx_rtmp_publish = ngx_rtmp_hls_publish; - - next_close_stream = ngx_rtmp_close_stream; - ngx_rtmp_close_stream = ngx_rtmp_hls_close_stream; - - next_stream_begin = ngx_rtmp_stream_begin; - ngx_rtmp_stream_begin = ngx_rtmp_hls_stream_begin; - - next_stream_eof = ngx_rtmp_stream_eof; - ngx_rtmp_stream_eof = ngx_rtmp_hls_stream_eof; - - return NGX_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/hls/ngx_rtmp_mpegts.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/hls/ngx_rtmp_mpegts.c deleted file mode 100644 index 110dfcac86..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/hls/ngx_rtmp_mpegts.c +++ /dev/null @@ -1,558 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include -#include "ngx_rtmp.h" -#include "ngx_rtmp_mpegts.h" - - -u_char ngx_rtmp_mpegts_pat[] = { - - /* TS */ - 0x47, 0x40, 0x00, 0x10, 0x00, - /* PSI */ - 0x00, 0xb0, 0x0d, 0x00, 0x01, 0xc1, 0x00, 0x00, - /* PAT */ - 0x00, 0x01, 0xf0, 0x01, - /* CRC */ - 0x2e, 0x70, 0x19, 0x05, - /* stuffing 167 bytes */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff -}; - - -static u_char ngx_mpegts_ts_header[] = { - /* TS */ - 0x47, 0x50, 0x01, 0x10, 0x00 -}; - -static u_char ngx_mpegts_pmt_header[] = { - /* PSI */ - 0x02, 0xb0, 0x17, 0x00, 0x01, 0xc1, 0x00, 0x00, - /* PMT */ - 0xe1, 0x00, - 0xf0, 0x00 -}; - - -enum { - NGX_RTMP_MPEGTS_PID_H264 = 0, - NGX_RTMP_MPEGTS_PID_H265, - NGX_RTMP_MPEGTS_PID_AAC, - NGX_RTMP_MPEGTS_PID_MP3 -}; - -static u_char ngx_mpegts_pid[4][5] = { - {0x1b, 0xe1, 0x00, 0xf0, 0x00}, /* h264 */ - {0x24, 0xe1, 0x00, 0xf0, 0x00}, /* h265 */ - {0x0f, 0xe1, 0x01, 0xf0, 0x00}, /* aac */ - {0x03, 0xe1, 0x01, 0xf0, 0x00} /* mp3 */ -}; - -/* 700 ms PCR delay */ -#define NGX_RTMP_HLS_DELAY 63000 - -static uint32_t crc32table[256] = { - 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, - 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, - 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, - 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, - 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, - 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, - 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, - 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, - 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, - 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, - 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, - 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, - 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, - 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, - 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, - 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, - 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, - 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, - 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, - 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, - 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, - 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, - 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, - 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, - 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, - 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, - 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, - 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, - 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, - 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, - 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, - 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, - 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, - 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, - 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, - 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, - 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, - 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, - 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, - 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, - 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, - 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, - 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 -}; - - -uint32_t -ngx_rtmp_mpegts_crc32(u_char *crc_buf, const u_char *data, int len) -{ - int i; - uint32_t crc = 0xFFFFFFFF; - - for(i = 0; i < len; i++) { - crc = (crc << 8) ^ crc32table[((crc >> 24) ^ *data++) & 0xFF]; - } - - crc_buf[0] = (crc & 0xff000000) >> 24; - crc_buf[1] = (crc & 0x00ff0000) >> 16; - crc_buf[2] = (crc & 0x0000ff00) >> 8; - crc_buf[3] = crc & 0x000000ff; - - return crc; -} - - -ngx_int_t -ngx_rtmp_mpegts_gen_pmt(ngx_int_t vcodec, ngx_int_t acodec, - ngx_log_t *log, u_char *pmt) -{ - u_char *p, crc_buf[4], *pmt_pos; - ngx_int_t vpid, apid; - u_char section_length; - - vpid = -1; - apid = -1; - - if (vcodec == acodec && vcodec == 0) { - return NGX_ERROR; - } - - p = pmt; - p = ngx_cpymem(p, ngx_mpegts_ts_header, sizeof(ngx_mpegts_ts_header)); - pmt_pos = p; - - p = ngx_cpymem(p, ngx_mpegts_pmt_header, sizeof(ngx_mpegts_pmt_header)); - - if (vcodec == 0) { - // ignore - } else if (vcodec == NGX_RTMP_VIDEO_H264) { - vpid = NGX_RTMP_MPEGTS_PID_H264; - } else if (vcodec == NGX_RTMP_HEVC_CODEC_ID) { - vpid = NGX_RTMP_MPEGTS_PID_H265; - } else if (log) { - ngx_log_error(NGX_LOG_ERR, log, 0, - "rtmp: gen_pmt| unknown video codec (%d)", vcodec); - } - - switch (acodec) { - case 0: //ignore - break; - - case NGX_RTMP_AUDIO_MP3: - apid = NGX_RTMP_MPEGTS_PID_MP3; - break; - - case NGX_RTMP_AUDIO_AAC: - apid = NGX_RTMP_MPEGTS_PID_AAC; - break; - - default: - if (log) { - ngx_log_error(NGX_LOG_ERR, log, 0, - "rtmp: gen_pmt| unknown video codec (%d)", vcodec); - } - } - - section_length = 13; - if (vpid != -1) { - p = ngx_cpymem(p, ngx_mpegts_pid[vpid], 5); - section_length += 5; - } - - if (apid != -1) { - p = ngx_cpymem(p, ngx_mpegts_pid[apid], 5); - section_length += 5; - } - - pmt_pos[2] = section_length; - - ngx_rtmp_mpegts_crc32(crc_buf, pmt_pos, p - pmt_pos); - p = ngx_cpymem(p, crc_buf, 4); - - ngx_memset(p, 0xff, 188 - (p - pmt)); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_mpegts_write_file(ngx_rtmp_mpegts_file_t *file, u_char *in, - size_t in_size) -{ - u_char *out; - size_t out_size, n; - ssize_t rc; - - static u_char buf[1024]; - - if (!file->encrypt) { - ngx_log_debug1(NGX_LOG_DEBUG_CORE, file->log, 0, - "mpegts: write %uz bytes", in_size); - - if (file->whandle == NULL) { - rc = ngx_write_fd(file->fd, in, in_size); - if (rc < 0) { - return NGX_ERROR; - } - - file->file_size += rc; - } else { - rc = file->whandle(file, in, in_size); - if (rc < 0) { - return NGX_ERROR; - } - } - - return NGX_OK; - } - - /* encrypt */ - - ngx_log_debug1(NGX_LOG_DEBUG_CORE, file->log, 0, - "mpegts: write %uz encrypted bytes", in_size); - - out = buf; - out_size = sizeof(buf); - - if (file->size > 0 && file->size + in_size >= 16) { - ngx_memcpy(file->buf + file->size, in, 16 - file->size); - - in += 16 - file->size; - in_size -= 16 - file->size; - - AES_cbc_encrypt(file->buf, out, 16, &file->key, file->iv, AES_ENCRYPT); - - out += 16; - out_size -= 16; - - file->size = 0; - } - - for ( ;; ) { - n = in_size & ~0x0f; - - if (n > 0) { - if (n > out_size) { - n = out_size; - } - - AES_cbc_encrypt(in, out, n, &file->key, file->iv, AES_ENCRYPT); - - in += n; - in_size -= n; - - } else if (out == buf) { - break; - } - - rc = ngx_write_fd(file->fd, buf, out - buf + n); - if (rc < 0) { - return NGX_ERROR; - } - - out = buf; - out_size = sizeof(buf); - } - - if (in_size) { - ngx_memcpy(file->buf + file->size, in, in_size); - file->size += in_size; - } - - return NGX_OK; -} - - -ngx_int_t -ngx_rtmp_mpegts_write_header(ngx_rtmp_mpegts_file_t *file) -{ - ngx_int_t ret; - u_char pmt[188]; - - ret = ngx_rtmp_mpegts_write_file(file, ngx_rtmp_mpegts_pat, - sizeof(ngx_rtmp_mpegts_pat)); - if (ret != NGX_OK) { - return ret; - } - - if (ngx_rtmp_mpegts_gen_pmt(file->vcodec, - file->acodec, file->log, pmt) != NGX_OK) - { - return NGX_ERROR; - } - - return ngx_rtmp_mpegts_write_file(file, pmt, sizeof(pmt)); -} - - -static u_char * -ngx_rtmp_mpegts_write_pcr(u_char *p, uint64_t pcr) -{ - *p++ = (u_char) (pcr >> 25); - *p++ = (u_char) (pcr >> 17); - *p++ = (u_char) (pcr >> 9); - *p++ = (u_char) (pcr >> 1); - *p++ = (u_char) (pcr << 7 | 0x7e); - *p++ = 0; - - return p; -} - - -static u_char * -ngx_rtmp_mpegts_write_pts(u_char *p, ngx_uint_t fb, uint64_t pts) -{ - ngx_uint_t val; - - val = fb << 4 | (((pts >> 30) & 0x07) << 1) | 1; - *p++ = (u_char) val; - - val = (((pts >> 15) & 0x7fff) << 1) | 1; - *p++ = (u_char) (val >> 8); - *p++ = (u_char) val; - - val = (((pts) & 0x7fff) << 1) | 1; - *p++ = (u_char) (val >> 8); - *p++ = (u_char) val; - - return p; -} - - -ngx_int_t -ngx_rtmp_mpegts_write_frame(ngx_rtmp_mpegts_file_t *file, - ngx_rtmp_mpegts_frame_t *f, ngx_buf_t *b) -{ - ngx_uint_t pes_size, header_size, body_size, in_size, stuff_size, flags; - u_char packet[188], *p, *base; - ngx_int_t first, rc; - - ngx_log_debug6(NGX_LOG_DEBUG_CORE, file->log, 0, - "mpegts: pid=%ui, sid=%ui, pts=%uL, " - "dts=%uL, key=%ui, size=%ui", - f->pid, f->sid, f->pts, f->dts, - (ngx_uint_t) f->key, (size_t) (b->last - b->pos)); - - first = 1; - - while (b->pos < b->last) { - p = packet; - - f->cc++; - - *p++ = 0x47; - *p++ = (u_char) (f->pid >> 8); - - if (first) { - p[-1] |= 0x40; - } - - *p++ = (u_char) f->pid; - *p++ = 0x10 | (f->cc & 0x0f); /* payload */ - - if (first) { - - if (f->key) { - packet[3] |= 0x20; /* adaptation */ - - *p++ = 7; /* size */ - *p++ = 0x50; /* random access + PCR */ - - p = ngx_rtmp_mpegts_write_pcr(p, f->dts - NGX_RTMP_HLS_DELAY); - } - - /* PES header */ - - *p++ = 0x00; - *p++ = 0x00; - *p++ = 0x01; - *p++ = (u_char) f->sid; - - header_size = 5; - flags = 0x80; /* PTS */ - - if (f->dts != f->pts) { - header_size += 5; - flags |= 0x40; /* DTS */ - } - - pes_size = (b->last - b->pos) + header_size + 3; - if (pes_size > 0xffff) { - pes_size = 0; - } - - *p++ = (u_char) (pes_size >> 8); - *p++ = (u_char) pes_size; - *p++ = 0x80; /* H222 */ - *p++ = (u_char) flags; - *p++ = (u_char) header_size; - - p = ngx_rtmp_mpegts_write_pts(p, flags >> 6, f->pts + - NGX_RTMP_HLS_DELAY); - - if (f->dts != f->pts) { - p = ngx_rtmp_mpegts_write_pts(p, 1, f->dts + - NGX_RTMP_HLS_DELAY); - } - - first = 0; - } - - body_size = (ngx_uint_t) (packet + sizeof(packet) - p); - in_size = (ngx_uint_t) (b->last - b->pos); - - if (body_size <= in_size) { - ngx_memcpy(p, b->pos, body_size); - b->pos += body_size; - - } else { - stuff_size = (body_size - in_size); - - if (packet[3] & 0x20) { - - /* has adaptation */ - - base = &packet[5] + packet[4]; - p = ngx_movemem(base + stuff_size, base, p - base); - ngx_memset(base, 0xff, stuff_size); - packet[4] += (u_char) stuff_size; - - } else { - - /* no adaptation */ - - packet[3] |= 0x20; - p = ngx_movemem(&packet[4] + stuff_size, &packet[4], - p - &packet[4]); - - packet[4] = (u_char) (stuff_size - 1); - if (stuff_size >= 2) { - packet[5] = 0; - ngx_memset(&packet[6], 0xff, stuff_size - 2); - } - } - - ngx_memcpy(p, b->pos, in_size); - b->pos = b->last; - } - - rc = ngx_rtmp_mpegts_write_file(file, packet, sizeof(packet)); - if (rc != NGX_OK) { - return rc; - } - } - - return NGX_OK; -} - - -ngx_int_t -ngx_rtmp_mpegts_init_encryption(ngx_rtmp_mpegts_file_t *file, - u_char *key, size_t key_len, uint64_t iv) -{ - if (AES_set_encrypt_key(key, key_len * 8, &file->key)) { - return NGX_ERROR; - } - - ngx_memzero(file->iv, 8); - - file->iv[8] = (u_char) (iv >> 56); - file->iv[9] = (u_char) (iv >> 48); - file->iv[10] = (u_char) (iv >> 40); - file->iv[11] = (u_char) (iv >> 32); - file->iv[12] = (u_char) (iv >> 24); - file->iv[13] = (u_char) (iv >> 16); - file->iv[14] = (u_char) (iv >> 8); - file->iv[15] = (u_char) (iv); - - file->encrypt = 1; - - return NGX_OK; -} - - -ngx_int_t -ngx_rtmp_mpegts_open_file(ngx_rtmp_mpegts_file_t *file, u_char *path, - ngx_log_t *log) -{ - file->log = log; - - file->fd = ngx_open_file(path, NGX_FILE_WRONLY, NGX_FILE_TRUNCATE, - NGX_FILE_DEFAULT_ACCESS); - - if (file->fd == NGX_INVALID_FILE) { - ngx_log_error(NGX_LOG_ERR, log, ngx_errno, - "hls: error creating fragment file"); - return NGX_ERROR; - } - - file->size = 0; - - if (ngx_rtmp_mpegts_write_header(file) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, log, ngx_errno, - "hls: error writing fragment header"); - ngx_close_file(file->fd); - return NGX_ERROR; - } - - return NGX_OK; -} - - -ngx_int_t -ngx_rtmp_mpegts_close_file(ngx_rtmp_mpegts_file_t *file) -{ - u_char buf[16]; - ssize_t rc; - - if (file->encrypt) { - ngx_memset(file->buf + file->size, 16 - file->size, 16 - file->size); - - AES_cbc_encrypt(file->buf, buf, 16, &file->key, file->iv, AES_ENCRYPT); - - rc = ngx_write_fd(file->fd, buf, 16); - if (rc < 0) { - return NGX_ERROR; - } - } - - ngx_close_file(file->fd); - - return NGX_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/hls/ngx_rtmp_mpegts.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/hls/ngx_rtmp_mpegts.h deleted file mode 100644 index a4a16a619f..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/hls/ngx_rtmp_mpegts.h +++ /dev/null @@ -1,58 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#ifndef _NGX_RTMP_MPEGTS_H_INCLUDED_ -#define _NGX_RTMP_MPEGTS_H_INCLUDED_ - - -#include -#include -#include - - -typedef struct ngx_rtmp_mpegts_file_s ngx_rtmp_mpegts_file_t; - - -typedef ssize_t (*ngx_rtmp_mpegts_write_pt) (ngx_rtmp_mpegts_file_t *file, - u_char *in, size_t in_size); - - -struct ngx_rtmp_mpegts_file_s { - ngx_fd_t fd; - ngx_log_t *log; - off_t file_size; - unsigned encrypt:1; - unsigned size:4; - u_char buf[16]; - u_char iv[16]; - AES_KEY key; - ngx_int_t acodec; - ngx_int_t vcodec; - ngx_buf_t wbuf; - ngx_rtmp_mpegts_write_pt whandle; -}; - - -typedef struct { - uint64_t pts; - uint64_t dts; - ngx_uint_t pid; - ngx_uint_t sid; - ngx_uint_t cc; - unsigned key:1; -} ngx_rtmp_mpegts_frame_t; - - -ngx_int_t ngx_rtmp_mpegts_init_encryption(ngx_rtmp_mpegts_file_t *file, - u_char *key, size_t key_len, uint64_t iv); -ngx_int_t ngx_rtmp_mpegts_open_file(ngx_rtmp_mpegts_file_t *file, u_char *path, - ngx_log_t *log); -ngx_int_t ngx_rtmp_mpegts_close_file(ngx_rtmp_mpegts_file_t *file); -ngx_int_t ngx_rtmp_mpegts_write_header(ngx_rtmp_mpegts_file_t *file); -ngx_int_t ngx_rtmp_mpegts_write_frame(ngx_rtmp_mpegts_file_t *file, - ngx_rtmp_mpegts_frame_t *f, ngx_buf_t *b); - -#endif /* _NGX_RTMP_MPEGTS_H_INCLUDED_ */ diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/http/ngx_http_flv_live_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/http/ngx_http_flv_live_module.c deleted file mode 100644 index aa31ef2474..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/http/ngx_http_flv_live_module.c +++ /dev/null @@ -1,733 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include -#include -#include -#include -#include "ngx_rtmp.h" -#include "ngx_rtmp_cmd_module.h" -#include "ngx_rbuf.h" -#include "ngx_http_set_header.h" -#include "ngx_rtmp_monitor_module.h" - - -static char *ngx_http_flv_live(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); - -static void *ngx_http_flv_live_create_loc_conf(ngx_conf_t *cf); -static char *ngx_http_flv_live_merge_loc_conf(ngx_conf_t *cf, void *parent, - void *child); - -static u_char ngx_flv_live_audio_header[] = "FLV\x1\x1\0\0\0\x9\0\0\0\0"; -static u_char ngx_flv_live_video_header[] = "FLV\x1\x4\0\0\0\x9\0\0\0\0"; -static u_char ngx_flv_live_av_header[] = "FLV\x1\x5\0\0\0\x9\0\0\0\0"; - -static ngx_keyval_t ngx_http_flv_live_headers[] = { - { ngx_string("Cache-Control"), ngx_string("no-cache") }, - { ngx_string("Content-Type"), ngx_string("video/x-flv") }, - { ngx_null_string, ngx_null_string } -}; - -#define NGX_FLV_TAG_SIZE 11 -#define NGX_FLV_PTS_SIZE 4 - -typedef struct { - ngx_rtmp_session_t *session; -} ngx_http_flv_live_ctx_t; - -typedef struct { - ngx_str_t app; - ngx_str_t flashver; - ngx_str_t swf_url; - ngx_str_t tc_url; - ngx_str_t page_url; - ngx_uint_t audio; - ngx_uint_t video; - - ngx_rtmp_addr_conf_t *addr_conf; -} ngx_http_flv_live_loc_conf_t; - - -static ngx_command_t ngx_http_flv_live_commands[] = { - - { ngx_string("flv_live"), - NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123, - ngx_http_flv_live, - NGX_HTTP_LOC_CONF_OFFSET, - 0, - NULL }, - - ngx_null_command -}; - - -static ngx_http_module_t ngx_http_flv_live_module_ctx = { - NULL, /* preconfiguration */ - NULL, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - ngx_http_flv_live_create_loc_conf, /* create location configuration */ - ngx_http_flv_live_merge_loc_conf /* merge location configuration */ -}; - - -ngx_module_t ngx_http_flv_live_module = { - NGX_MODULE_V1, - &ngx_http_flv_live_module_ctx, /* module context */ - ngx_http_flv_live_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static ngx_int_t -ngx_http_flv_live_send_header(ngx_http_request_t *r) -{ - ngx_int_t rc; - ngx_keyval_t *h; - ngx_buf_t *b; - ngx_chain_t out; - ngx_http_flv_live_loc_conf_t *hflcf; - - if (r->header_sent) { - return NGX_OK; - } - - hflcf = ngx_http_get_module_loc_conf(r, ngx_http_flv_live_module); - - r->headers_out.status = NGX_HTTP_OK; - r->keepalive = 0; /* set Connection to closed */ - - h = ngx_http_flv_live_headers; - while (h->key.len) { - rc = ngx_http_set_header_out(r, &h->key, &h->value); - if (rc != NGX_OK) { - return rc; - } - ++h; - } - - rc = ngx_http_send_header(r); - if (rc == NGX_ERROR || rc > NGX_OK) { - return rc; - } - - b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); - if (b == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - switch (hflcf->audio | (hflcf->video << 1)) { - case 1: // audio only - b->start = b->pos = ngx_flv_live_audio_header; - b->end = b->last = ngx_flv_live_audio_header + - sizeof(ngx_flv_live_audio_header) - 1; - break; - - case 2: // video only - b->start = b->pos = ngx_flv_live_video_header; - b->end = b->last = ngx_flv_live_video_header + - sizeof(ngx_flv_live_video_header) - 1; - break; - - case 3: // audio and video - b->start = b->pos = ngx_flv_live_av_header; - b->end = b->last = ngx_flv_live_av_header + - sizeof(ngx_flv_live_av_header) - 1; - break; - - default: - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "flv-live: send_header| av header config error."); - - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - b->memory = 1; - - out.buf = b; - out.next = NULL; - - return ngx_http_output_filter(r, &out); -} - -static ngx_chain_t * -ngx_http_flv_live_prepare_out_chain(ngx_rtmp_session_t *s) -{ - ngx_rtmp_frame_t *frame; - ngx_chain_t *head, **ll, *cl; - u_char *p; - size_t datasize, prev_tag_size; - - frame = NULL; - head = NULL; - datasize = 0; - - while (s->out_pos != s->out_last) { - frame = s->out[s->out_pos]; - if (frame->hdr.type != NGX_RTMP_MSG_VIDEO - && frame->hdr.type != NGX_RTMP_MSG_AUDIO - && frame->hdr.type != NGX_RTMP_MSG_AMF_META - && frame->hdr.type != NGX_RTMP_MSG_AMF3_META) - { - ngx_rtmp_shared_free_frame(frame); - ++s->out_pos; - s->out_pos %= s->out_queue; - frame = NULL; - - continue; - } - break; - } - - /* no frame to send */ - if (frame == NULL) { - return NULL; - } - - for (ll = &head; *ll; ll = &(*ll)->next); - - for (cl = frame->chain; cl; cl = cl->next) { - datasize += (cl->buf->last - cl->buf->pos); - } - prev_tag_size = datasize + NGX_FLV_TAG_SIZE; - - /* flv tag header */ - *ll = ngx_get_chainbuf(NGX_FLV_TAG_SIZE, 1); - if (*ll == NULL) { - goto falied; - } - p = (*ll)->buf->pos; - - /* TagType 1 byte */ - *p++ = frame->hdr.type; - - /* DataSize 3 bytes */ - *p++ = ((u_char *) &datasize)[2]; - *p++ = ((u_char *) &datasize)[1]; - *p++ = ((u_char *) &datasize)[0]; - - /* Timestamp 4 bytes */ - *p++ = ((u_char *) &frame->hdr.timestamp)[2]; - *p++ = ((u_char *) &frame->hdr.timestamp)[1]; - *p++ = ((u_char *) &frame->hdr.timestamp)[0]; - *p++ = ((u_char *) &frame->hdr.timestamp)[3]; - - /* StreamID 4 bytes, always set to 0 */ - *p++ = 0; - *p++ = 0; - *p++ = 0; - - (*ll)->buf->last = p; - ll = &(*ll)->next; - - /* flv payload */ - for (cl = frame->chain; cl; cl = cl->next) { - (*ll) = ngx_get_chainbuf(0, 0); - if (*ll == NULL) { - goto falied; - } - (*ll)->buf->pos = cl->buf->pos; - (*ll)->buf->last = cl->buf->last; - ll = &(*ll)->next; - } - - /* flv previous tag size */ - *ll = ngx_get_chainbuf(NGX_FLV_PTS_SIZE, 1); - if (*ll == NULL) { - goto falied; - } - p = (*ll)->buf->pos; - - *p++ = ((u_char *) &prev_tag_size)[3]; - *p++ = ((u_char *) &prev_tag_size)[2]; - *p++ = ((u_char *) &prev_tag_size)[1]; - *p++ = ((u_char *) &prev_tag_size)[0]; - - (*ll)->buf->last = p; - (*ll)->buf->flush = 1; - - ngx_rtmp_monitor_frame(s, &frame->hdr, NULL, frame->av_header, 0); - - return head; - -falied: - ngx_put_chainbufs(head); - - ngx_rtmp_finalize_session(s); - return NULL; -} - -static void -ngx_http_flv_live_write_handler(ngx_http_request_t *r) -{ - ngx_http_flv_live_ctx_t *ctx; - ngx_rtmp_session_t *s; - ngx_event_t *wev; - size_t present, sent; - ngx_int_t rc; - ngx_chain_t *cl; - - wev = r->connection->write; - - if (r->connection->destroyed) { - return; - } - - ctx = ngx_http_get_module_ctx(r, ngx_http_flv_live_module); - s = ctx->session; - - if (wev->timedout) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, NGX_ETIMEDOUT, - "http flv live, client timed out"); - r->connection->timedout = 1; - s->finalize_reason = NGX_LIVE_FLV_SEND_TIMEOUT; - if (r->header_sent) { - ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT); - } else { - r->error_page = 1; - ngx_http_finalize_request(r, NGX_HTTP_SERVICE_UNAVAILABLE); - } - - return; - } - - if (wev->timer_set) { - ngx_del_timer(wev); - } - - if (ngx_rtmp_core_main_conf->fast_reload && (ngx_exiting || ngx_terminate)) { - r->error_page = 1; - ngx_http_finalize_request(r, NGX_HTTP_SERVICE_UNAVAILABLE); - return; - } - - if (ngx_rtmp_prepare_merge_frame(s) == NGX_ERROR) { - ngx_http_finalize_request(r, NGX_ERROR); - return; - } - - if (s->out_chain) { - rc = ngx_http_flv_live_send_header(r); - if (rc == NGX_ERROR || rc > NGX_OK) { - s->finalize_reason = NGX_LIVE_FLV_SEND_ERR; - ngx_http_finalize_request(r, rc); - return; - } - } - - while (s->out_chain) { - present = r->connection->sent; - - if (r->connection->buffered) { - rc = ngx_http_output_filter(r, NULL); - } else { - rc = ngx_http_output_filter(r, s->out_chain); - } - - sent = r->connection->sent - present; - - ngx_rtmp_update_bandwidth(&ngx_rtmp_bw_out, sent); - - if (rc == NGX_AGAIN) { - ngx_add_timer(wev, s->timeout); - if (ngx_handle_write_event(wev, 0) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno, - "http flv live, handle write event failed"); - ngx_http_finalize_request(r, NGX_ERROR); - } - return; - } - - if (rc == NGX_ERROR) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno, - "http flv live, send error"); - s->finalize_reason = NGX_LIVE_FLV_SEND_ERR; - ngx_http_finalize_request(r, NGX_ERROR); - return; - } - - /* NGX_OK */ - for (cl = s->out_chain; cl;) { - s->out_chain = cl->next; - ngx_free_chain(s->pool, cl); - cl = s->out_chain; - } - - if (ngx_rtmp_prepare_merge_frame(s) == NGX_ERROR) { - ngx_http_finalize_request(r, NGX_ERROR); - return; - } - } - - if (wev->active) { - ngx_del_event(wev, NGX_WRITE_EVENT, 0); - } -} - - -static void -ngx_http_flv_live_parse_url(ngx_http_request_t *r, ngx_str_t *app, - ngx_str_t *name) -{ - u_char *p, *end, *pos; - - p = r->uri.data + 1; /* skip '/' */ - end = r->uri.data + r->uri.len; - app->data = p; - - pos = ngx_strnstr(p, ".flv", end - p); - if (pos) { - end = pos; - } - - p = (u_char *) ngx_strnstr(p, "/", end - p); - while (p) { - name->data = p; - p = (u_char *) ngx_strnstr(p + 1, "/", end - p); - } - - if (name->data == NULL) { - return; - } - - app->len = name->data - app->data; - - ++name->data; - name->len = end - name->data; -} - -static ngx_int_t -ngx_http_flv_live_parse(ngx_http_request_t *r, ngx_rtmp_session_t *s, - ngx_rtmp_play_t *v) -{ - ngx_http_flv_live_loc_conf_t *hflcf; - ngx_str_t app, stream; - size_t tcurl_len; - u_char *p; - - hflcf = ngx_http_get_module_loc_conf(r, ngx_http_flv_live_module); - - ngx_memzero(&app, sizeof(ngx_str_t)); - ngx_memzero(&stream, sizeof(ngx_str_t)); - - ngx_http_flv_live_parse_url(r, &app, &stream); - - if (app.len == 0 || stream.len == 0 || stream.len > NGX_RTMP_MAX_NAME) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "http flv live, url error: %V", &r->uri); - return NGX_HTTP_BAD_REQUEST; - } - - if (hflcf->app.len) { - app = hflcf->app; - } - - if (ngx_http_arg(r, (u_char *) "flashver", 8, &s->flashver) != NGX_OK) { - s->flashver = hflcf->flashver; - } - - ngx_http_arg(r, (u_char *) "app", 3, &app); - - s->app = app; - - /* tc_url */ -#if (NGX_HTTP_SSL) - if (r->connection->ssl) { - tcurl_len = sizeof("https://") - 1; - } else -#endif - { - tcurl_len = sizeof("http://") - 1; - } - tcurl_len += r->headers_in.server.len + 1 + app.len; - - s->tc_url.len = tcurl_len; - s->tc_url.data = ngx_pcalloc(r->pool, tcurl_len); - if (s->tc_url.data == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - p = s->tc_url.data; - -#if (NGX_HTTP_SSL) - if (r->connection->ssl) { - p = ngx_cpymem(p, "https://", sizeof("https://") - 1); - } else -#endif - { - p = ngx_cpymem(p, "http://", sizeof("http://") - 1); - } - - p = ngx_cpymem(p, r->headers_in.server.data, r->headers_in.server.len); - *p++ = '/'; - p = ngx_cpymem(p, app.data, app.len); - - /* page_url */ - if (r->headers_in.referer) { - s->page_url = r->headers_in.referer->value; - } else { - s->page_url = hflcf->page_url; - } - - s->acodecs = 0x0DF7; - s->vcodecs = 0xFC; - - ngx_memcpy(v->name, stream.data, stream.len); - - if (r->args.len) { - ngx_memcpy(v->args, r->args.data, - ngx_min(r->args.len, NGX_RTMP_MAX_ARGS)); - } - - ngx_rtmp_cmd_middleware_init(s); - - return NGX_OK; -} - -static void -ngx_http_flv_live_cleanup(void *data) -{ - ngx_http_request_t *r; - ngx_http_flv_live_ctx_t *ctx; - - r = data; - - ctx = ngx_http_get_module_ctx(r, ngx_http_flv_live_module); - - if (ctx == NULL) { - return; - } - - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "http flv live, cleanup"); - - if (ctx->session) { - ctx->session->request = NULL; - - if (ctx->session->finalize_reason == 0) { - ctx->session->finalize_reason = r->connection->read->error? - NGX_LIVE_FLV_RECV_ERR: - NGX_LIVE_NORMAL_CLOSE; - } - - ngx_rtmp_finalize_fake_session(ctx->session); - } -} - -static ngx_int_t -ngx_http_flv_live_handler(ngx_http_request_t *r) -{ - ngx_http_flv_live_loc_conf_t *hflcf; - ngx_http_flv_live_ctx_t *ctx; - ngx_rtmp_session_t *s; - ngx_rtmp_play_t v; - ngx_int_t rc; - ngx_uint_t n; - ngx_rtmp_core_srv_conf_t *cscf; - ngx_rtmp_core_app_conf_t **cacfp; - ngx_http_cleanup_t *cln; - ngx_rtmp_core_main_conf_t *cmcf; - - rc = ngx_http_discard_request_body(r); - - if (rc != NGX_OK) { - return rc; - } - - ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_flv_live_ctx_t)); - if (ctx == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - ngx_http_set_ctx(r, ctx, ngx_http_flv_live_module); - - /* cleanup handler */ - cln = ngx_http_cleanup_add(r, 0); - if (cln == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - cln->handler = ngx_http_flv_live_cleanup; - cln->data = r; - - hflcf = ngx_http_get_module_loc_conf(r, ngx_http_flv_live_module); - - /* create fake session */ - s = ngx_rtmp_create_session(hflcf->addr_conf); - if (s == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - s->connection = r->connection; - s->number = r->connection->number; - s->remote_addr_text.data = ngx_pcalloc(s->pool, r->connection->addr_text.len); - s->remote_addr_text.len = r->connection->addr_text.len; - ngx_memcpy(s->remote_addr_text.data, - r->connection->addr_text.data, r->connection->addr_text.len); - ngx_rtmp_set_combined_log(s, r->connection->log->data, - r->connection->log->handler); - s->log->connection = r->connection->number; - ctx->session = s; - - /* get host, app, stream name */ - ngx_memzero(&v, sizeof(ngx_rtmp_play_t)); - rc = ngx_http_flv_live_parse(r, s, &v); - if (rc != NGX_OK) { - return rc; - } - - if (ngx_rtmp_set_virtual_server(s, &s->domain)) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module); - - s->live_type = NGX_HTTP_FLV_LIVE; - s->live_server = ngx_live_create_server(&s->serverid); - s->request = r; - - v.silent = 1; - - cacfp = cscf->applications.elts; - for (n = 0; n < cscf->applications.nelts; ++n, ++cacfp) { - if ((*cacfp)->name.len == s->app.len && - ngx_strncmp((*cacfp)->name.data, s->app.data, s->app.len) == 0) - { - /* found app! */ - s->app_conf = (*cacfp)->app_conf; - break; - } - } - - if (s->app_conf == NULL) { - - if (cscf->default_app == NULL || cscf->default_app->app_conf == NULL) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "http flv live, application not found '%V'", &s->app); - return NGX_HTTP_NOT_FOUND; - } - - s->app_conf = cscf->default_app->app_conf; - } - - s->prepare_handler = ngx_http_flv_live_prepare_out_chain; - - s->stage = NGX_LIVE_PLAY; - s->ptime = ngx_current_msec; - - cmcf = ngx_rtmp_get_module_main_conf(s, ngx_rtmp_core_module); - s->variables = ngx_pcalloc(s->pool, cmcf->variables.nelts - * sizeof(ngx_http_variable_value_t)); - if (s->variables == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - if (ngx_rtmp_play_filter(s, &v) != NGX_OK) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - ngx_add_timer(r->connection->write, s->timeout); - - r->read_event_handler = ngx_http_test_reading; - r->write_event_handler = ngx_http_flv_live_write_handler; - - ++r->count; - - return NGX_DONE; -} - - -static void * -ngx_http_flv_live_create_loc_conf(ngx_conf_t *cf) -{ - ngx_http_flv_live_loc_conf_t *hflcf; - - hflcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_flv_live_loc_conf_t)); - if (hflcf == NULL) { - return NULL; - } - - return hflcf; -} - -static char * -ngx_http_flv_live_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_http_flv_live_loc_conf_t *prev = parent; - ngx_http_flv_live_loc_conf_t *conf = child; - - ngx_conf_merge_str_value(conf->app, prev->app, ""); - ngx_conf_merge_str_value(conf->flashver, prev->flashver, ""); - ngx_conf_merge_str_value(conf->swf_url, prev->swf_url, ""); - ngx_conf_merge_str_value(conf->tc_url, prev->tc_url, ""); - ngx_conf_merge_str_value(conf->page_url, prev->page_url, ""); - - return NGX_CONF_OK; -} - -static char * -ngx_http_flv_live(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_core_loc_conf_t *clcf; - ngx_http_flv_live_loc_conf_t *hflcf; - ngx_str_t *value, v; - ngx_uint_t i; - ngx_uint_t audio, video; - - clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); - clcf->handler = ngx_http_flv_live_handler; - - hflcf = conf; - - value = cf->args->elts; - - hflcf->addr_conf = ngx_rtmp_find_related_addr_conf(cf->cycle, &value[1]); - if (hflcf->addr_conf == NULL) { - return NGX_CONF_ERROR; - } - - audio = NGX_CONF_UNSET_UINT; - video = NGX_CONF_UNSET_UINT; - - for (i = 2; i < cf->args->nelts; ++i) { - if (ngx_strncmp(value[i].data, "app=", 4) == 0) { - v.data = value[i].data + 4; - v.len = value[i].len - 4; - hflcf->app = v; - } else if (ngx_strncmp(value[i].data, "audio=", 6) == 0) { - v.data = value[i].data + 6; - v.len = value[i].len - 6; - audio = ngx_atoi(v.data, v.len); - } else if (ngx_strncmp(value[i].data, "video=", 6) == 0) { - v.data = value[i].data + 6; - v.len = value[i].len - 6; - video = ngx_atoi(v.data, v.len); - } else { - return NGX_CONF_ERROR; - } - } - - if (audio == NGX_CONF_UNSET_UINT) { - audio = 1; - } - - if (video == NGX_CONF_UNSET_UINT) { - video = 1; - } - - hflcf->audio = audio; - hflcf->video = video; - - return NGX_CONF_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/http/ngx_http_set_header.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/http/ngx_http_set_header.c deleted file mode 100644 index ffef7aa593..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/http/ngx_http_set_header.c +++ /dev/null @@ -1,282 +0,0 @@ -#include -#include -#include - -typedef struct ngx_http_header_val_s ngx_http_header_val_t; - -typedef ngx_int_t (*ngx_http_set_header_pt)(ngx_http_request_t *r, - ngx_http_header_val_t *hv, ngx_str_t *value); - -struct ngx_http_header_val_s { - ngx_http_complex_value_t value; - ngx_uint_t hash; - ngx_str_t key; - ngx_http_set_header_pt handler; - ngx_uint_t offset; -}; - -typedef struct { - ngx_str_t name; - ngx_uint_t offset; - ngx_http_set_header_pt handler; - -} ngx_http_set_header_t; - -//TODO need fill all header set in future -/* for header has no quick link in ngx_http_headers_out_t */ -static ngx_int_t ngx_http_set_header_out_other(ngx_http_request_t *r, - ngx_http_header_val_t *hv, ngx_str_t *value); -/* for header has quick link like ngx_table_elt_t* in ngx_http_headers_out_t */ -static ngx_int_t ngx_http_set_header_out_builtin(ngx_http_request_t *r, - ngx_http_header_val_t *hv, ngx_str_t *value); -/* for header has quick link like ngx_array_t in ngx_http_headers_out_t */ -static ngx_int_t ngx_http_set_header_out_builtin_multi(ngx_http_request_t *r, - ngx_http_header_val_t *hv, ngx_str_t *value); -/* for header has quick link like ngx_table_elt_t* and - * other attribute in ngx_http_headers_out_t defined below */ -static ngx_int_t ngx_http_set_header_out_content_type(ngx_http_request_t *r, - ngx_http_header_val_t *hv, ngx_str_t *value); - -static ngx_http_set_header_t ngx_http_set_header_out_handlers[] = { - - { ngx_string("Server"), - offsetof(ngx_http_headers_out_t, server), - ngx_http_set_header_out_builtin }, - - { ngx_string("Date"), - offsetof(ngx_http_headers_out_t, date), - ngx_http_set_header_out_builtin }, - - { ngx_string("Content-Type"), - offsetof(ngx_http_headers_out_t, content_type), - ngx_http_set_header_out_content_type }, - - { ngx_string("Cache-Control"), - offsetof(ngx_http_headers_out_t, cache_control), - ngx_http_set_header_out_builtin_multi }, - - { ngx_null_string, 0, ngx_http_set_header_out_other } -}; - -static ngx_int_t -ngx_http_set_header_out_helper(ngx_http_request_t *r, - ngx_http_header_val_t *hv, ngx_str_t *value, unsigned no_create) -{ - ngx_table_elt_t *h; - ngx_list_part_t *part; - ngx_uint_t i; - - part = &r->headers_out.headers.part; - h = part->elts; - - for (i = 0; /* void */; ++i) { - - if (i >= part->nelts) { - if (part->next == NULL) { - break; - } - - part = part->next; - h = part->elts; - i = 0; - } - - if (h[i].hash != 0 - && h[i].key.len == hv->key.len - && ngx_strncasecmp(hv->key.data, h[i].key.data, h[i].key.len) == 0) - /* header has been set */ - { - h[i].value = *value; - if (value->len == 0) { /* if value is empty, remove header */ - h[i].hash = 0; - } else { - h[i].hash = hv->hash; - } - - return NGX_OK; - } - } - - if (no_create && value->len == 0) { /* set header to empty but header cannot found */ - return NGX_OK; - } - - /* header has not been set, create it */ - - h = ngx_list_push(&r->headers_out.headers); - - if (h == NULL) { - return NGX_ERROR; - } - - h->hash = hv->hash; - h->key = hv->key; - h->value = *value; - - h->lowcase_key = ngx_pnalloc(r->pool, h->key.len); - if (h->lowcase_key == NULL) { - return NGX_ERROR; - } - - ngx_strlow(h->lowcase_key, h->key.data, h->key.len); - - return NGX_OK; -} - -static ngx_int_t -ngx_http_set_header_out_other(ngx_http_request_t * r, - ngx_http_header_val_t * hv,ngx_str_t * value) -{ - return ngx_http_set_header_out_helper(r, hv, value, 0); -} - - -static ngx_int_t -ngx_http_set_header_out_builtin(ngx_http_request_t *r, - ngx_http_header_val_t *hv, ngx_str_t *value) -{ - ngx_table_elt_t *h, **old; - - if (hv->offset) { - old = (ngx_table_elt_t **) ((char *) &r->headers_out + hv->offset); - } else { - old = NULL; - } - - if (old == NULL || *old == NULL) { - /* user should use ngx_http_set_header_out_other but use this func to set header */ - //TODO - return ngx_http_set_header_out_helper(r, hv, value, 0); - } - - h = *old; - - h->value = *value; - if (value->len == 0) { /* if value is empty, remove header */ - - h->hash = 0; - return NGX_OK; - } - - h->hash = hv->hash; - h->key = hv->key; - - return NGX_OK; -} - -static ngx_int_t -ngx_http_set_header_out_builtin_multi(ngx_http_request_t *r, - ngx_http_header_val_t *hv, ngx_str_t *value) -{ - ngx_array_t *pa; - ngx_table_elt_t *ho, **ph; - ngx_uint_t i; - - pa = (ngx_array_t *) ((char *) &r->headers_out + hv->offset); - - if (pa->elts == NULL) { - if (ngx_array_init(pa, r->pool, 2, sizeof(ngx_table_elt_t *)) - != NGX_OK) - { - return NGX_ERROR; - } - } - - if (pa->nelts > 0) { - ph = pa->elts; - for (i = 1; i < pa->nelts; i++) { /* clear old value */ - ph[i]->hash = 0; - ph[i]->value.len = 0; - } - - ph[0]->value = *value; - - if (value->len == 0) { - ph[0]->hash = 0; - } else { - ph[0]->hash = hv->hash; - } - - return NGX_OK; - } - - /* header does not set */ - ph = ngx_array_push(pa); - if (ph == NULL) { - return NGX_ERROR; - } - - ho = ngx_list_push(&r->headers_out.headers); - if (ho == NULL) { - return NGX_ERROR; - } - - ho->value = *value; - ho->hash = hv->hash; - ho->key = hv->key; - *ph = ho; - - return NGX_OK; -} - -static ngx_int_t -ngx_http_set_header_out_content_type(ngx_http_request_t *r, - ngx_http_header_val_t *hv, ngx_str_t *value) -{ - ngx_uint_t i; - - r->headers_out.content_type_len = value->len; - - for (i = 0; i < value->len; i++) { - if (value->data[i] == ';') { - r->headers_out.content_type_len = i; - break; - } - } - - r->headers_out.content_type = *value; - r->headers_out.content_type_hash = hv->hash; - r->headers_out.content_type_lowcase = NULL; - - value->len = 0; - - return ngx_http_set_header_out_helper(r, hv, value, 1); -} - -ngx_int_t -ngx_http_set_header_out(ngx_http_request_t *r, ngx_str_t *key, ngx_str_t *value) -{ - ngx_http_header_val_t hv; - ngx_http_set_header_t *handlers = ngx_http_set_header_out_handlers; - ngx_uint_t i; - ngx_str_t v; - - hv.hash = ngx_hash_key_lc(key->data, key->len); - hv.key = *key; - - hv.offset = 0; - hv.handler = NULL; - - for (i = 0; handlers[i].name.len; ++i) { - if (hv.key.len != handlers[i].name.len - || ngx_strncasecmp(hv.key.data, handlers[i].name.data, - handlers[i].name.len) != 0) { - continue; - } - - /* match handler */ - hv.offset = handlers[i].offset; - hv.handler = handlers[i].handler; - - break; - } - - if (handlers[i].name.len == 0 && handlers[i].handler) { /* if not matched, use ngx_http_set_header as default*/ - hv.offset = handlers[i].offset; - hv.handler = handlers[i].handler; - } - - v = *value; - - return hv.handler(r, &hv, &v); -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/http/ngx_http_set_header.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/http/ngx_http_set_header.h deleted file mode 100644 index eca5f3e4fb..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/http/ngx_http_set_header.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _NGX_RTMP_HTTP_HEADER_OUT_H_INCLUDED_ -#define _NGX_RTMP_HTTP_HEADER_OUT_H_INCLUDED_ - -#include -#include -#include - -ngx_int_t ngx_http_set_header_out(ngx_http_request_t *r, - ngx_str_t *key, ngx_str_t *value); - -#endif diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_hls_http_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_hls_http_module.c deleted file mode 100644 index 599a942785..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_hls_http_module.c +++ /dev/null @@ -1,1303 +0,0 @@ - -/* - * Copyright (C) Pingo (cczjp89@gmail.com) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "ngx_http_set_header.h" -#include "ngx_mpegts_live_module.h" -#include "ngx_hls_live_module.h" -#include "ngx_rbuf.h" -#include "ngx_rtmp_dynamic.h" - -#ifndef NGX_HTTP_GONE -#define NGX_HTTP_GONE 410 -#endif - -static ngx_keyval_t ngx_302_headers[] = { - { ngx_string("Location"), ngx_null_string }, - { ngx_null_string, ngx_null_string } -}; - -static ngx_keyval_t ngx_m3u8_headers[] = { - { ngx_string("Cache-Control"), ngx_string("no-cache") }, - { ngx_string("Content-Type"), ngx_string("application/vnd.apple.mpegurl") }, - { ngx_null_string, ngx_null_string } -}; - -static ngx_keyval_t ngx_ts_headers[] = { - { ngx_string("Cache-Control"), ngx_string("no-cache") }, - { ngx_string("Content-Type"), ngx_string("video/mp2t") }, - { ngx_null_string, ngx_null_string } -}; - - -typedef struct { - ngx_str_t app; - ngx_str_t name; - ngx_str_t stream; - ngx_str_t serverid; - ngx_str_t sid; - ngx_rtmp_session_t *session; - ngx_msec_t timeout; - ngx_uint_t content_pos; - ngx_chain_t *m3u8; - ngx_uint_t out_pos; - ngx_uint_t out_last; - ngx_chain_t *out_chain; - ngx_hls_live_frag_t *frag; -} ngx_hls_http_ctx_t; - - -typedef struct { - ngx_str_t app; - ngx_str_t flashver; - ngx_str_t swf_url; - ngx_str_t tc_url; - ngx_str_t page_url; - ngx_msec_t timeout; - ngx_rtmp_addr_conf_t *addr_conf; -} ngx_hls_http_loc_conf_t; - -static u_char NGX_HLS_LIVE_ARG_SESSION[] = "session"; - -static ngx_int_t NGX_HLS_LIVE_ARG_SESSION_LENGTH = 7; - -static void * ngx_hls_http_create_loc_conf(ngx_conf_t *cf); -static char * ngx_hls_http_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child); -static char * ngx_http_hls(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -//static char * ngx_hls_http_variant(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -static ngx_int_t ngx_hls_http_postconfiguration(ngx_conf_t *cf); - -static ngx_command_t ngx_hls_http_commands[] = { - - { ngx_string("hls2_live"), - NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, - ngx_http_hls, - NGX_HTTP_LOC_CONF_OFFSET, - 0, - NULL }, - - ngx_null_command -}; - -static ngx_http_module_t ngx_hls_http_module_ctx = { - NULL, /* preconfiguration */ - ngx_hls_http_postconfiguration, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - ngx_hls_http_create_loc_conf, /* create location configuration */ - ngx_hls_http_merge_loc_conf /* merge location configuration */ -}; - -ngx_module_t ngx_hls_http_module = { - NGX_MODULE_V1, - &ngx_hls_http_module_ctx, /* module context */ - ngx_hls_http_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - -static void * -ngx_hls_http_create_loc_conf(ngx_conf_t *cf) -{ - ngx_hls_http_loc_conf_t *hlcf; - - hlcf = ngx_pcalloc(cf->pool, sizeof(ngx_hls_http_loc_conf_t)); - if (hlcf == NULL) { - return NULL; - } - - return hlcf; -} - -static char * -ngx_hls_http_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_hls_http_loc_conf_t *prev = parent; - ngx_hls_http_loc_conf_t *conf = child; - - ngx_conf_merge_str_value(conf->app, prev->app, ""); - ngx_conf_merge_str_value(conf->flashver, prev->flashver, ""); - ngx_conf_merge_str_value(conf->swf_url, prev->swf_url, ""); - ngx_conf_merge_str_value(conf->tc_url, prev->tc_url, ""); - ngx_conf_merge_str_value(conf->page_url, prev->page_url, ""); - - return NGX_CONF_OK; -} - - -static ngx_int_t -ngx_hls_http_ctx_init(ngx_http_request_t *r, ngx_rtmp_addr_conf_t *addr_conf) -{ - u_char *p, *e; - ngx_buf_t *buf; - ngx_rtmp_core_srv_conf_t *cscf; - ngx_hls_http_loc_conf_t *hlcf; - ngx_hls_http_ctx_t *ctx; - ngx_str_t *app, *name, *stream, *domain, *serverid; - ngx_int_t rc; - - hlcf = ngx_http_get_module_loc_conf(r, ngx_hls_http_module); - ctx = ngx_http_get_module_ctx(r, ngx_hls_http_module); - - app = &ctx->app; - name = &ctx->name; - stream = &ctx->stream; - serverid = &ctx->serverid; - domain = &r->headers_in.server; - - p = r->uri.data; - e = r->uri.data + r->uri.len; - - p++; - app->data = p; - p = ngx_strlchr(p, e, '/'); - if (p == NULL) { - app->data = NULL; - app->len = 0; - - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "hls-http: ctx_init| invalid uri, lack of app"); - - return NGX_ERROR; - } - app->len = p - app->data; - - if (hlcf->app.len > 0 && hlcf->app.data) { - *app = hlcf->app; - } - - p++; - name->data = p; - if (ngx_strncmp(&e[-5], ".m3u8", 5) == 0) { - p = ngx_strlchr(p, e, '.'); - } else if (ngx_strncmp(&e[-3], ".ts", 3) == 0) { - p = ngx_strlchr(p, e, '-'); - } else { - p = NULL; - } - - if (p == NULL) { - name->data = NULL; - name->len = 0; - - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "hls-http: ctx_init| invalid uri, lack of name"); - - return NGX_ERROR; - } - name->len = p - name->data; - - cscf = addr_conf->default_server-> - ctx->srv_conf[ngx_rtmp_core_module.ctx_index]; - - rc = ngx_rtmp_find_virtual_server(addr_conf->virtual_names, domain, &cscf); - if (rc != NGX_OK && rc != NGX_DECLINED) { - - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "hls-http: ctx_init| server(%V) not found.", domain); - - return NGX_ERROR; - } - - if (cscf && cscf->serverid.len) { - serverid->data = ngx_pcalloc(r->connection->pool, cscf->serverid.len); - if (serverid->data == NULL) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "hls-http: ctx_init| pcalloc failed."); - return NGX_ERROR; - } - serverid->len = cscf->serverid.len; - ngx_memcpy(serverid->data, cscf->serverid.data, cscf->serverid.len); - } else { - *serverid = *domain; - } - - buf = ngx_create_temp_buf(r->connection->pool, - serverid->len + 1 + app->len + name->len + 1); - buf->last = ngx_slprintf(buf->start, buf->end, - "%V/%V/%V", serverid, app, name); - - stream->data = buf->pos; - stream->len = buf->last - buf->pos; - - ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, - "hls-http: ctx_init| hls stream (%V).", stream); - - return NGX_OK; -} - - -static ngx_int_t -ngx_hls_http_send_header(ngx_http_request_t *r, ngx_uint_t status, ngx_keyval_t *h) -{ - ngx_int_t rc; - - r->headers_out.status = status; -// r->keepalive = 0; /* set Connection to closed */ - - //set eTag - if (ngx_http_set_etag(r) != NGX_OK) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - while (h && h->key.len) { - rc = ngx_http_set_header_out(r, &h->key, &h->value); - if (rc != NGX_OK) { - return rc; - } - ++h; - } - - return ngx_http_send_header(r); -} - -static ngx_int_t -ngx_hls_http_master_m3u8_handler(ngx_http_request_t *r, - ngx_rtmp_addr_conf_t *addr_conf) -{ - - ngx_int_t rc; - ngx_str_t m3u8_url; - ngx_str_t host; - u_char sstr[NGX_RTMP_MAX_SESSION] = {0}; - static ngx_uint_t sindex = 0; - ngx_str_t location = ngx_string(""); - ngx_str_t uri; - ngx_str_t uri_tail; - ngx_buf_t *m3u8; - ngx_chain_t out; - ngx_str_t scheme = ngx_string(""); - ngx_str_t http = ngx_string("http"); - ngx_str_t https = ngx_string("https"); - u_char *p; - - host = r->headers_in.host->value; - - rc = ngx_http_discard_request_body(r); - if (rc != NGX_OK) { - return rc; - } - - *ngx_snprintf(sstr, sizeof(sstr) - 1, "%uDt-%uDi-%dp-%uDc", - time(NULL), sindex++, ngx_process_slot, r->connection->number) = 0; - - ngx_http_arg(r, (u_char*)"location", 8, &location); - if (location.len == 0) { - uri = r->uri; - } else { - uri_tail.data = - ngx_strlchr(r->uri.data + 1, r->uri.data + r->uri.len - 1, '/'); - if (uri_tail.data == NULL) { - uri_tail = r->uri; - } else { - uri_tail.len = r->uri.data+r->uri.len - uri_tail.data; - } - - uri.len = location.len + uri_tail.len; - uri.data = ngx_pcalloc(r->pool, uri.len); - if (uri.data == NULL) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "hls-http: master_m3u8_handler| pcalloc uri buffer failed"); - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - ngx_snprintf(uri.data, uri.len, "%V%V", &location, &uri_tail); - } - - ngx_http_arg(r, (u_char*)"scheme", 6, &scheme); - if (scheme.len == 0) { -#if (NGX_HTTP_SSL) - if (r->connection->ssl) { - scheme = https; - } else -#endif - { - scheme = http; - } - } - - m3u8_url.len = scheme.len + ngx_strlen("://") + - host.len + - uri.len + - NGX_HLS_LIVE_ARG_SESSION_LENGTH + 2 + - ngx_strlen(sstr); - - if (r->args.len > 0) { - m3u8_url.len += 1 + r->args.len; - } - - m3u8_url.data = ngx_pcalloc(r->connection->pool, m3u8_url.len); - - p = ngx_snprintf(m3u8_url.data, m3u8_url.len, "%V://%V%V?%s=%s", - &scheme, &host, &uri, NGX_HLS_LIVE_ARG_SESSION, sstr); - - if (r->args.len > 0) { - ngx_slprintf(p, m3u8_url.data + m3u8_url.len, "&%V", &r->args); - } - - m3u8 = ngx_create_temp_buf(r->connection->pool, 64 * 1024); - m3u8->memory = 1; - m3u8->flush = 1; - out.buf = m3u8; - out.next = NULL; - - m3u8->last = ngx_snprintf(m3u8->pos, m3u8->end - m3u8->start, - "#EXTM3U\n" - "#EXT-X-STREAM-INF:BANDWIDTH=1,AVERAGE-BANDWIDTH=1\n" - //"#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1\n" - "%V\n", &m3u8_url); - - r->headers_out.content_length_n = m3u8->last - m3u8->pos; - - rc = ngx_hls_http_send_header(r, NGX_HTTP_OK, ngx_m3u8_headers); - if (rc != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "hls-http: master_m3u8_handler| " - "send header failed, redirect url: %V, rc=%d", &m3u8_url, rc); - } else { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "hls-http: master_m3u8_handler| redirect url %V", &m3u8_url); - } - - return ngx_http_output_filter(r, &out); -} - -static ngx_int_t -ngx_hls_http_redirect_handler(ngx_http_request_t *r, - ngx_rtmp_addr_conf_t *addr_conf) -{ - ngx_int_t rc; - ngx_str_t m3u8_url; - ngx_str_t host; - u_char sstr[NGX_RTMP_MAX_SESSION] = {0}; - static ngx_uint_t sindex = 0; - ngx_str_t location = ngx_string(""); - ngx_str_t uri; - ngx_str_t uri_tail; - ngx_str_t scheme = ngx_string(""); - ngx_str_t http = ngx_string("http"); - ngx_str_t https = ngx_string("https"); - u_char *p; - - host = r->headers_in.host->value; - - rc = ngx_http_discard_request_body(r); - if (rc != NGX_OK) { - return rc; - } - - *ngx_snprintf(sstr, sizeof(sstr) - 1, "%uDt-%uDi-%dp-%uDc", - time(NULL), sindex++, ngx_process_slot, r->connection->number) = 0; - - ngx_http_arg(r, (u_char*)"location", 8, &location); - if (location.len == 0) { - uri = r->uri; - } else { - uri_tail.data = - ngx_strlchr(r->uri.data + 1, r->uri.data + r->uri.len - 1, '/'); - if (uri_tail.data == NULL) { - uri_tail = r->uri; - } else { - uri_tail.len = r->uri.data+r->uri.len - uri_tail.data; - } - - uri.len = location.len + uri_tail.len; - uri.data = ngx_pcalloc(r->pool, uri.len); - if (uri.data == NULL) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "hls-http: redirect_handler| pcalloc uri buffer failed"); - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - ngx_snprintf(uri.data, uri.len, "%V%V", &location, &uri_tail); - } - - ngx_http_arg(r, (u_char*)"scheme", 6, &scheme); - if (scheme.len == 0) { -#if (NGX_HTTP_SSL) - if (r->connection->ssl) { - scheme = https; - } else -#endif - { - scheme = http; - } - } - - m3u8_url.len = scheme.len + ngx_strlen("://") + - host.len + - uri.len + - NGX_HLS_LIVE_ARG_SESSION_LENGTH + 2 + - ngx_strlen(sstr); - - if (r->args.len > 0) { - m3u8_url.len += 1 + r->args.len; - } - - m3u8_url.data = ngx_pcalloc(r->connection->pool, m3u8_url.len); - - p = ngx_snprintf(m3u8_url.data, m3u8_url.len, "%V://%V%V?%s=%s", - &scheme, &host, &uri, NGX_HLS_LIVE_ARG_SESSION, sstr); - - if (r->args.len > 0) { - ngx_slprintf(p, m3u8_url.data + m3u8_url.len, "&%V", &r->args); - } - - ngx_http_set_header_out(r, &ngx_302_headers[0].key, &m3u8_url); - - r->headers_out.content_length_n = 0; - r->header_only = 1; - - rc = ngx_hls_http_send_header(r, NGX_HTTP_MOVED_TEMPORARILY, NULL); - if (rc != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "hls-http: redirect_handler| " - "send header failed, redirect url: %V, rc=%d", &m3u8_url, rc); - } else { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "hls-http: redirect_handler| redirect url %V", &m3u8_url); - } - - return rc; -} - - -static ngx_hls_http_ctx_t * -ngx_hls_http_create_ctx(ngx_http_request_t *r, ngx_rtmp_addr_conf_t *addr_conf) -{ - ngx_hls_http_ctx_t *ctx; - ngx_rtmp_core_srv_conf_t *cscf; - u_char *p; - - cscf = addr_conf->default_server->ctx-> - srv_conf[ngx_rtmp_core_module.ctx_index]; - - ctx = ngx_http_get_module_ctx(r, ngx_hls_http_module); - if (ctx == NULL) { - p = ngx_pcalloc(r->connection->pool, sizeof(ngx_hls_http_ctx_t)); - - if (p == NULL) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "hls-http: create_ctx| alloc hls live ctx failed"); - return NULL; - } - - ctx = (ngx_hls_http_ctx_t *)p; - - ngx_http_set_ctx(r, ctx, ngx_hls_http_module); - } - - ctx->timeout = cscf->timeout; - - ngx_hls_http_ctx_init(r, addr_conf); - - if (ctx->app.len == 0 || ctx->name.len == 0) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "hls-http: create_ctx| parse app or name failed, uri %V", &r->uri); - return NULL; - } - - ngx_http_arg(r, NGX_HLS_LIVE_ARG_SESSION, NGX_HLS_LIVE_ARG_SESSION_LENGTH, - &ctx->sid); - - return ctx; -} - - -static void -ngx_hls_http_cleanup(void *data) -{ - ngx_http_request_t *r; - ngx_hls_http_ctx_t *ctx; - ngx_chain_t *cl; - - r = data; - ctx = ngx_http_get_module_ctx(r, ngx_hls_http_module); - - if (!ctx) { - return; - } - - if (ctx->out_chain == NULL) { - cl = ctx->out_chain; - while (cl) { - ctx->out_chain = cl->next; - ngx_put_chainbuf(cl); - cl = ctx->out_chain; - } - } - - ctx->content_pos = 0; - - if (ctx->session) { - ctx->session->request = NULL; - ctx->session->connection = NULL; - } - - ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, - "hls-http: cleanup_handler| http cleanup"); - - if (ctx->frag) { - ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, - "hls-http: cleanup_handler| free frag[%p]", ctx->frag); - ngx_hls_live_free_frag(ctx->frag); - ctx->frag = NULL; - } -} - - -static ngx_int_t -ngx_hls_http_parse(ngx_http_request_t *r, ngx_rtmp_session_t *s, - ngx_rtmp_play_t *v) -{ - ngx_hls_http_loc_conf_t *hlcf; - size_t tcurl_len; - u_char *p; - ngx_hls_http_ctx_t *ctx; - - ctx = ngx_http_get_module_ctx(r, ngx_hls_http_module); - - hlcf = ngx_http_get_module_loc_conf(r, ngx_hls_http_module); - -#define NGX_HLS_HTTP_SET_VAL(_val) \ - s->_val.data = ngx_pcalloc(s->pool, ctx->_val.len); \ - s->_val.len = ctx->_val.len; \ - ngx_memcpy(s->_val.data, ctx->_val.data, ctx->_val.len) - - NGX_HLS_HTTP_SET_VAL(app); - NGX_HLS_HTTP_SET_VAL(stream); - -#undef NGX_HLS_HTTP_SET_VAL - - if (ngx_http_arg(r, (u_char *) "flashver", 8, &s->flashver) != NGX_OK) { - s->flashver = hlcf->flashver; - } - - /* tc_url */ -#if (NGX_HTTP_SSL) - if (r->connection->ssl) { - tcurl_len = sizeof("https://") - 1; - } else -#endif - { - tcurl_len = sizeof("http://") - 1; - } - tcurl_len += r->headers_in.server.len + 1 + s->app.len; - - s->tc_url.len = tcurl_len; - s->tc_url.data = ngx_pcalloc(r->pool, tcurl_len); - if (s->tc_url.data == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - p = s->tc_url.data; - -#if (NGX_HTTP_SSL) - if (r->connection->ssl) { - p = ngx_cpymem(p, "https://", sizeof("https://") - 1); - } else -#endif - { - p = ngx_cpymem(p, "http://", sizeof("http://") - 1); - } - - p = ngx_cpymem(p, r->headers_in.server.data, r->headers_in.server.len); - *p++ = '/'; - p = ngx_cpymem(p, s->app.data, s->app.len); - - /* page_url */ - if (r->headers_in.referer) { - s->page_url = r->headers_in.referer->value; - } else { - s->page_url = hlcf->page_url; - } - - s->acodecs = 0x0DF7; - s->vcodecs = 0xFC; - - ngx_memcpy(v->name, ctx->name.data, ctx->name.len); - - if (r->args.len) { - ngx_memcpy(v->args, r->args.data, - ngx_min(r->args.len, NGX_RTMP_MAX_ARGS)); - } - - ngx_memcpy(v->session, ctx->sid.data, ctx->sid.len); - - ngx_rtmp_cmd_middleware_init(s); - - return NGX_OK; -} - - -static ngx_rtmp_session_t* -ngx_hls_http_create_session(ngx_http_request_t *r) -{ - ngx_hls_http_loc_conf_t *hlcf; - ngx_rtmp_session_t *s; - ngx_rtmp_play_t v; - ngx_int_t rc; - ngx_uint_t n; - ngx_rtmp_core_srv_conf_t *cscf; - ngx_rtmp_core_app_conf_t **cacfp; - ngx_rtmp_core_main_conf_t *cmcf; - - hlcf = ngx_http_get_module_loc_conf(r, ngx_hls_http_module); - - /* create fake session */ - s = ngx_rtmp_create_session(hlcf->addr_conf); - if (s == NULL) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "hls-http: create_session| create session failed"); - return NULL; - } - - /* get host, app, stream name */ - ngx_memzero(&v, sizeof(ngx_rtmp_play_t)); - - rc = ngx_hls_http_parse(r, s, &v); - if (rc != NGX_OK) { - return NULL; - } - - if (ngx_rtmp_set_virtual_server(s, &s->domain)) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "hls-http: create_session| set virtual server failed, %V", - &s->domain); - return NULL; - } - cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module); - - s->log->connection = r->connection->number; - s->number = r->connection->number; - s->live_type = NGX_HLS_LIVE; - s->live_server = ngx_live_create_server(&s->serverid); - s->remote_addr_text.data = ngx_pcalloc(s->pool, r->connection->addr_text.len); - s->remote_addr_text.len = r->connection->addr_text.len; - ngx_memcpy(s->remote_addr_text.data, - r->connection->addr_text.data, r->connection->addr_text.len); - - v.silent = 1; - - cacfp = cscf->applications.elts; - for (n = 0; n < cscf->applications.nelts; ++n, ++cacfp) { - if ((*cacfp)->name.len == s->app.len && - ngx_strncmp((*cacfp)->name.data, s->app.data, s->app.len) == 0) - { - /* found app! */ - s->app_conf = (*cacfp)->app_conf; - break; - } - } - - if (s->app_conf == NULL) { - - if (cscf->default_app == NULL || cscf->default_app->app_conf == NULL) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "hls-http: create_session| application not found '%V'", &s->app); - - ngx_rtmp_finalize_fake_session(s); - - return NULL; - } - - s->app_conf = cscf->default_app->app_conf; - } - - s->stage = NGX_LIVE_PLAY; - s->ptime = ngx_current_msec; -// s->connection = r->connection; - - cmcf = ngx_rtmp_get_module_main_conf(s, ngx_rtmp_core_module); - s->variables = ngx_pcalloc(s->pool, cmcf->variables.nelts - * sizeof(ngx_http_variable_value_t)); - if (s->variables == NULL) { - return NULL; - } - - if (ngx_rtmp_play_filter(s, &v) != NGX_OK) { - return NULL; - } - - ngx_add_timer(r->connection->write, s->timeout); - - return s; -} - - -static ngx_int_t -ngx_hls_http_m3u8_handler(ngx_http_request_t *r, ngx_rtmp_addr_conf_t *addr_conf) -{ - ngx_hls_http_ctx_t *ctx; - ngx_int_t rc; - ngx_rtmp_session_t *s; - ngx_chain_t *out; - ngx_buf_t *buf; - - ctx = ngx_hls_http_create_ctx(r, addr_conf); - if (ctx == NULL) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "hls-http: m3u8_handler| create ctx failed"); - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - s = ngx_hls_live_fetch_session(&ctx->serverid, &ctx->stream, &ctx->sid); - if (s == NULL) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "hls-http: m3u8_handler| hls session %V not found", &ctx->sid); - - s = ngx_hls_http_create_session(r); - if (s == NULL) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "hls-http: m3u8_handler| create hls session %V error", - &ctx->sid); - - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - s->sockaddr = ngx_pcalloc(s->pool, sizeof(struct sockaddr)); - ngx_memcpy(s->sockaddr, r->connection->sockaddr, sizeof(struct sockaddr)); - } - - s->request = r; - - ctx->session = s; - - if (!ctx->m3u8) { - ctx->m3u8 = ngx_pcalloc(r->connection->pool, sizeof(ngx_chain_t)); - ctx->m3u8->buf = ngx_create_temp_buf(r->connection->pool, 1024*512); - } - - out = ctx->m3u8; - buf = out->buf; - buf->last = buf->pos = buf->start; - buf->memory = 1; - buf->flush = 1; -// buf->last_in_chain = 1; -// buf->last_buf = 1; - - rc = ngx_hls_live_write_playlist(s, buf, &r->headers_out.last_modified_time); - if (rc != NGX_OK) { - goto again; - } - - r->headers_out.content_length_n = buf->last - buf->pos; - - s->out_bytes += r->headers_out.content_length_n; - - if (!r->header_sent) { - rc = ngx_hls_http_send_header(r, NGX_HTTP_OK, ngx_m3u8_headers); - if (rc != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "hls-http: m3u8_handler| send http header failed"); - return rc; - } - } - - rc = ngx_http_output_filter(r, out); - if (rc != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "hls-http: m3u8_handler| send http content failed"); - return rc; - } - - return rc; - -again: - r->count++; - - return NGX_DONE; -} - - -static u_char* -ngx_hls_http_strrchr(ngx_str_t *str, u_char c) -{ - u_char *s, *e; - - s = str->data; - e = str->data + str->len; - - e--; - while(e != s) { - if (*e == c) { - break; - } - e--; - } - - if (e == s) { - return NULL; - } - - return e; -} - - -static ngx_int_t -ngx_hls_http_parse_frag(ngx_http_request_t *r, ngx_str_t *name) -{ - u_char *s, *e; - - e = ngx_hls_http_strrchr(&r->uri, '?'); - if (e == NULL) { - e = r->uri.data + r->uri.len; - } - - s = ngx_hls_http_strrchr(&r->uri, '/'); - if (s == NULL) { - s = r->uri.data; - } else { - s++; - } - - name->data = s; - name->len = e - s; - - return NGX_OK; -} - -static ngx_chain_t * -ngx_hls_http_prepare_out_chain(ngx_http_request_t *r, ngx_int_t nframes) -{ - ngx_hls_http_ctx_t *ctx; - ngx_hls_live_frag_t *frag; - ngx_rtmp_session_t *s; - ngx_chain_t *out, *cl, **ll; - ngx_mpegts_frame_t *frame; - ngx_int_t i = 0; - - ctx = ngx_http_get_module_ctx(r, ngx_hls_http_module); - s = ctx->session; - frag = ctx->frag; - - out = NULL; - - ll = &out; - while (i < nframes && ctx->content_pos != frag->content_last) { - frame = frag->content[ctx->content_pos]; - - for (cl = frame->chain; cl; cl = cl->next) { - *ll = ngx_get_chainbuf(0, 0); - (*ll)->buf->pos = cl->buf->pos; - (*ll)->buf->last = cl->buf->last; - (*ll)->buf->flush = 1; - - ll = &(*ll)->next; - } - - *ll = NULL; - ctx->content_pos = ngx_hls_live_next(s, ctx->content_pos); - i++; - } - - return out; -} - -static void -ngx_hls_http_write_handler(ngx_http_request_t *r) -{ - ngx_hls_http_ctx_t *ctx; - ngx_rtmp_session_t *s; - ngx_event_t *wev; - size_t present, sent; - ngx_int_t rc; - ngx_chain_t *cl; - - wev = r->connection->write; //wev->handler = ngx_http_request_handler; - - if (r->connection->destroyed) { - return; - } - - ctx = ngx_http_get_module_ctx(r, ngx_hls_http_module); - s = ctx->session; - - if (wev->timedout) { - ngx_log_error(NGX_LOG_INFO, s->log, NGX_ETIMEDOUT, - "hls_http: write_handler| client timed out"); - r->connection->timedout = 1; - if (r->header_sent) { - ngx_http_finalize_request(r, NGX_HTTP_CLIENT_CLOSED_REQUEST); - } else { - r->error_page = 1; - ngx_http_finalize_request(r, NGX_HTTP_SERVICE_UNAVAILABLE); - } - - return; - } - - if (wev->timer_set) { - ngx_del_timer(wev); - } - - if (ctx->out_chain == NULL) { - ctx->out_chain = ngx_hls_http_prepare_out_chain(r, 4); - } - - rc = NGX_OK; - - while (ctx->out_chain) { - present = r->connection->sent; - - if (r->connection->buffered) { - rc = ngx_http_output_filter(r, NULL); - } else { - rc = ngx_http_output_filter(r, ctx->out_chain); - } - - sent = r->connection->sent - present; - - ngx_rtmp_update_bandwidth(&ngx_rtmp_bw_out, sent); - - if (rc == NGX_AGAIN) { - ngx_add_timer(wev, s->timeout); - if (ngx_handle_write_event(wev, 0) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "hls_http: write_handler| handle write event failed"); - ngx_http_finalize_request(r, NGX_ERROR); - } - return; - } - - if (rc == NGX_ERROR) { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "hls_http: write_handler| send error"); - ngx_http_finalize_request(r, NGX_ERROR); - - return; - } - - /* NGX_OK */ - cl = ctx->out_chain; - while (cl) { - ctx->out_chain = cl->next; - ngx_put_chainbuf(cl); - cl = ctx->out_chain; - } - - if (ctx->frag->content_pos == ctx->frag->content_last) { - ctx->out_chain = NULL; - break; - } - - ctx->out_chain = ngx_hls_http_prepare_out_chain(r, 4); - } - - if (wev->active) { - ngx_del_event(wev, NGX_WRITE_EVENT, 0); - } - - ngx_http_finalize_request(r, NGX_HTTP_OK); -} - -static ngx_int_t -ngx_hls_http_ts_handler(ngx_http_request_t *r, ngx_rtmp_addr_conf_t *addr_conf) -{ - ngx_hls_http_ctx_t *ctx; - ngx_rtmp_session_t *s; - ngx_hls_live_frag_t *frag; - ngx_int_t rc; - ngx_str_t name; - - ctx = ngx_hls_http_create_ctx(r, addr_conf); - if (ctx == NULL) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "hls-http: ts_handler| create ctx failed"); - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - s = ngx_hls_live_fetch_session(&ctx->serverid, &ctx->stream, &ctx->sid); - if (s == NULL) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "hls-http: ts_handler| hls session %V not found", &ctx->sid); - return NGX_DECLINED; - } - ctx->session = s; - s->request = r; - -// ngx_rtmp_set_combined_log(s, r->connection->log->data, -// r->connection->log->handler); - - rc = ngx_hls_http_parse_frag(r, &name); - if (rc != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "hls-http: ts_handler| parse frag args failed %V", &r->uri); - return NGX_HTTP_NOT_ALLOWED; - } - - frag = ngx_hls_live_find_frag(s, &name); - if (frag == NULL) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "hls-http: ts_handler| ts not found, %V", &r->uri); - return NGX_HTTP_NOT_FOUND; - } - - ctx->frag = frag; - - r->headers_out.content_length_n = frag->length; - r->headers_out.last_modified_time = frag->last_modified_time; - s->out_bytes += r->headers_out.content_length_n; - - rc = ngx_hls_http_send_header(r, NGX_HTTP_OK, ngx_ts_headers); - if (rc != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "hls-http: ts_handler| send http header failed, %V", &r->uri); - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - ngx_rtmp_shared_acquire_frag(frag); - - if (1) { - r->write_event_handler = ngx_hls_http_write_handler; - - r->count++; - - ngx_hls_http_write_handler(r); - - return NGX_DONE; - } else { - ctx->out_chain = ngx_hls_live_prepare_frag(s, frag); - - ngx_rtmp_update_bandwidth(&ngx_rtmp_bw_out, frag->length); - - return ngx_http_output_filter(r, ctx->out_chain); - } -} - - -static ngx_int_t -ngx_hls_http_handler(ngx_http_request_t *r) -{ - ngx_hls_http_loc_conf_t *hlcf; - ngx_int_t rc; - ngx_http_cleanup_t *cln; - ngx_str_t sstr; - ngx_hls_http_ctx_t *ctx; - - hlcf = ngx_http_get_module_loc_conf(r, ngx_hls_http_module); - - rc = ngx_http_discard_request_body(r); - - if (rc != NGX_OK) { - return rc; - } - - if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "hls-http: live_handler| donnot support the method"); - return NGX_HTTP_NOT_ALLOWED; - } - - if (ngx_rtmp_core_main_conf->fast_reload && (ngx_exiting || ngx_terminate)) { - return NGX_DECLINED; - } - - if (r->uri.len < 4) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "hls-http: live_handler| donnot support the file type"); - return NGX_DECLINED; - } - - ctx = ngx_http_get_module_ctx(r, ngx_hls_http_module); - if (!ctx) { - cln = ngx_http_cleanup_add(r, 0); - if (cln == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - cln->handler = ngx_hls_http_cleanup; - cln->data = r; - r->read_event_handler = ngx_http_test_reading; - } - - if(!ngx_strncmp(r->uri.data + r->uri.len - 5, ".m3u8", 5)) { - - rc = ngx_http_arg(r, NGX_HLS_LIVE_ARG_SESSION, - NGX_HLS_LIVE_ARG_SESSION_LENGTH, &sstr); - - if (rc != NGX_OK || sstr.len == 0) { - if (1) { - return ngx_hls_http_master_m3u8_handler(r, hlcf->addr_conf); - } else { - return ngx_hls_http_redirect_handler(r, hlcf->addr_conf); - } - } else { - return ngx_hls_http_m3u8_handler(r, hlcf->addr_conf); - } - - } else if (!ngx_strncmp(r->uri.data + r->uri.len - 3, ".ts", 3)) { - return ngx_hls_http_ts_handler(r, hlcf->addr_conf); - } - - return NGX_DECLINED; -} - -static ngx_int_t -ngx_hls_http_m3u8(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, ngx_chain_t *in) -{ - ngx_http_request_t *r; - ngx_int_t rc; - ngx_hls_http_ctx_t *ctx; - ngx_buf_t *buf; - ngx_chain_t *out; - - r = s->request; - if (!r) { - return NGX_ERROR; - } - - ctx = ngx_http_get_module_ctx(r, ngx_hls_http_module); - - if (!ctx->m3u8) { - ctx->m3u8 = ngx_pcalloc(r->connection->pool, sizeof(ngx_chain_t)); - ctx->m3u8->buf = ngx_create_temp_buf(r->connection->pool, 1024*512); - } - - out = ctx->m3u8; - buf = out->buf; - buf->last = buf->pos = buf->start; - buf->memory = 1; - buf->flush = 1; -// buf->last_in_chain = 1; -// buf->last_buf = 1; - - ngx_hls_live_write_playlist(s, buf, &r->headers_out.last_modified_time); - - r->headers_out.content_length_n = buf->last - buf->pos; - - s->out_bytes += r->headers_out.content_length_n; - - rc = ngx_hls_http_send_header(r, NGX_HTTP_OK, ngx_m3u8_headers); - if (rc != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "hls-http: m3u8| send http header failed"); - return rc; - } - - rc = ngx_http_output_filter(r, out); - if (rc != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "hls-http: m3u8| send http content failed"); - return rc; - } - - ngx_http_finalize_request(r, NGX_HTTP_OK); - - return NGX_OK; -} - -static ngx_int_t -ngx_hls_http_close(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, ngx_chain_t *in) -{ - ngx_http_request_t *r; - ngx_hls_http_ctx_t *ctx; - - r = s->request; - if (!r) { - return NGX_OK; - } - - ctx = ngx_http_get_module_ctx(r, ngx_hls_http_module); - if (!ctx) { - return NGX_OK; - } - - s->request = NULL; - s->connection = NULL; - ctx->session = NULL; - - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "hls-http: close| finalize http request"); - - ngx_http_finalize_request(r, NGX_HTTP_GONE); - - return NGX_OK; -} - - -static char * -ngx_http_hls(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_core_loc_conf_t *clcf; - ngx_hls_http_loc_conf_t *hlcf; - ngx_str_t *value; - ngx_uint_t n; - - clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); - clcf->handler = ngx_hls_http_handler; - - hlcf = conf; - - value = cf->args->elts; - - hlcf->addr_conf = ngx_rtmp_find_related_addr_conf(cf->cycle, &value[1]); - if (hlcf->addr_conf == NULL) { - return NGX_CONF_ERROR; - } - - for (n = 2; n < cf->args->nelts; ++n) { -#define PARSE_CONF_ARGS(arg) \ - { \ - size_t len = sizeof(#arg"=") - 1; \ - if (ngx_memcmp(value[n].data, #arg"=", len) == 0) { \ - hlcf->arg.data = value[n].data + len; \ - hlcf->arg.len = value[n].len - len; \ - continue; \ - } \ - } - - PARSE_CONF_ARGS(app); - PARSE_CONF_ARGS(flashver); - PARSE_CONF_ARGS(swf_url); - PARSE_CONF_ARGS(tc_url); - PARSE_CONF_ARGS(page_url); - -#undef PARSE_CONF_ARGS - - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "\"%V\" para not support", &value[n]); - return NGX_CONF_ERROR; - } - - return NGX_CONF_OK; -} - -static ngx_int_t -ngx_hls_http_postconfiguration(ngx_conf_t *cf) -{ - ngx_rtmp_core_main_conf_t *cmcf; - ngx_rtmp_handler_pt *h; - - cmcf = ngx_rtmp_core_main_conf; - - if (!cmcf) { - return NGX_OK; - } - - h = ngx_array_push(&cmcf->events[NGX_MPEGTS_MSG_M3U8]); - *h = ngx_hls_http_m3u8; - - h = ngx_array_push(&cmcf->events[NGX_MPEGTS_MSG_CLOSE]); - *h = ngx_hls_http_close; - - return NGX_OK; -} - diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_hls_live_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_hls_live_module.c deleted file mode 100644 index efab067928..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_hls_live_module.c +++ /dev/null @@ -1,1094 +0,0 @@ - -/* - * Copyright (C) Pingo (cczjp89@gmail.com) - */ - - -#include -#include -#include -#include -#include -#include "ngx_rbuf.h" -#include "ngx_hls_live_module.h" -#include "ngx_mpegts_live_module.h" -#include "ngx_rtmp_live_module.h" -#include "ngx_mpegts_gop_module.h" - -static ngx_rtmp_play_pt next_play; -static ngx_rtmp_close_stream_pt next_close_stream; - -static ngx_int_t ngx_hls_live_postconfiguration(ngx_conf_t *cf); -static void * ngx_hls_live_create_main_conf(ngx_conf_t *cf); -static void * ngx_hls_live_create_app_conf(ngx_conf_t *cf); -static char * ngx_hls_live_merge_app_conf(ngx_conf_t *cf, - void *parent, void *child); -static ngx_int_t -ngx_hls_live_write_frame(ngx_rtmp_session_t *s, ngx_mpegts_frame_t *frame); -static void -ngx_hls_live_update_playlist(ngx_rtmp_session_t *s); -static ngx_int_t -ngx_hls_live_update(ngx_rtmp_session_t *s, ngx_rtmp_codec_ctx_t *codec_ctx); - -static ngx_mpegts_video_pt next_mpegts_video; -static ngx_mpegts_audio_pt next_mpegts_audio; - -typedef struct { - ngx_flag_t hls; - ngx_msec_t fraglen; - ngx_msec_t max_fraglen; - ngx_msec_t playlen; - ngx_uint_t winfrags; - ngx_uint_t minfrags; - ngx_uint_t slicing; - ngx_uint_t type; - ngx_path_t *slot; - size_t audio_buffer_size; - ngx_flag_t cleanup; - ngx_array_t *variant; - ngx_str_t base_url; - ngx_pool_t *pool; - ngx_msec_t timeout; -} ngx_hls_live_app_conf_t; - -typedef struct { - ngx_hls_live_frag_t *free_frag; - ngx_pool_t *pool; -} ngx_hls_live_main_conf_t; - -ngx_hls_live_main_conf_t *ngx_hls_live_main_conf = NULL; - -#define NGX_RTMP_HLS_NAMING_SEQUENTIAL 1 -#define NGX_RTMP_HLS_NAMING_TIMESTAMP 2 -#define NGX_RTMP_HLS_NAMING_SYSTEM 3 - - -#define NGX_RTMP_HLS_SLICING_PLAIN 1 -#define NGX_RTMP_HLS_SLICING_ALIGNED 2 - - -#define NGX_RTMP_HLS_TYPE_LIVE 1 -#define NGX_RTMP_HLS_TYPE_EVENT 2 - - -static ngx_conf_enum_t ngx_hls_live_slicing_slots[] = { - { ngx_string("plain"), NGX_RTMP_HLS_SLICING_PLAIN }, - { ngx_string("aligned"), NGX_RTMP_HLS_SLICING_ALIGNED }, - { ngx_null_string, 0 } -}; - -/* -static ngx_conf_enum_t ngx_hls_live_type_slots[] = { - { ngx_string("live"), NGX_RTMP_HLS_TYPE_LIVE }, - { ngx_string("event"), NGX_RTMP_HLS_TYPE_EVENT }, - { ngx_null_string, 0 } -}; -*/ - -static ngx_command_t ngx_hls_live_commands[] = { - - { ngx_string("hls2memory"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_hls_live_app_conf_t, hls), - NULL }, - - { ngx_string("hls2"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_hls_live_app_conf_t, hls), - NULL }, - - { ngx_string("hls2_fragment"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_hls_live_app_conf_t, fraglen), - NULL }, - - { ngx_string("hls2_max_fragment"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_hls_live_app_conf_t, max_fraglen), - NULL }, - - { ngx_string("hls2_playlist_length"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_hls_live_app_conf_t, playlen), - NULL }, - - { ngx_string("hls2_minfrags"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_hls_live_app_conf_t, minfrags), - NULL }, - - { ngx_string("hls2_fragment_slicing"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_enum_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_hls_live_app_conf_t, slicing), - &ngx_hls_live_slicing_slots }, - - { ngx_string("hls2_audio_buffer_size"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_hls_live_app_conf_t, audio_buffer_size), - NULL }, - - { ngx_string("hls2_cleanup"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_hls_live_app_conf_t, cleanup), - NULL }, - - { ngx_string("hls2_base_url"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_hls_live_app_conf_t, base_url), - NULL }, - - { ngx_string("hls2_timeout"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_hls_live_app_conf_t, timeout), - NULL }, - - ngx_null_command -}; - - -static ngx_rtmp_module_t ngx_hls_live_module_ctx = { - NULL, /* preconfiguration */ - ngx_hls_live_postconfiguration, /* postconfiguration */ - - ngx_hls_live_create_main_conf, /* create main configuration */ - NULL, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - ngx_hls_live_create_app_conf, /* create location configuration */ - ngx_hls_live_merge_app_conf, /* merge location configuration */ -}; - - -ngx_module_t ngx_hls_live_module = { - NGX_MODULE_V1, - &ngx_hls_live_module_ctx, /* module context */ - ngx_hls_live_commands, /* module directives */ - NGX_RTMP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static ngx_hls_live_frag_t * -ngx_hls_live_get_frag(ngx_rtmp_session_t *s, ngx_int_t n) -{ - ngx_hls_live_ctx_t *ctx; - ngx_hls_live_app_conf_t *hacf; - - hacf = ngx_rtmp_get_module_app_conf(s, ngx_hls_live_module); - ctx = ngx_rtmp_get_module_ctx(s, ngx_hls_live_module); - - return ctx->frags[(ctx->nfrag + n) % (hacf->winfrags * 2 + 1)]; -} - - -static void -ngx_hls_live_next_frag(ngx_rtmp_session_t *s) -{ - ngx_hls_live_ctx_t *ctx; - ngx_hls_live_app_conf_t *hacf; - - hacf = ngx_rtmp_get_module_app_conf(s, ngx_hls_live_module); - ctx = ngx_rtmp_get_module_ctx(s, ngx_hls_live_module); - - if (ctx->nfrags == hacf->winfrags) { - ctx->nfrag++; - } else { - ctx->nfrags++; - } -} - - -ngx_int_t -ngx_hls_live_write_playlist(ngx_rtmp_session_t *s, ngx_buf_t *out, - time_t *last_modified_time) -{ - ngx_hls_live_ctx_t *ctx; - ngx_str_t m3u8; - ngx_hls_live_app_conf_t *hacf; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_hls_live_module); - if (ctx == NULL) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, "hls-live: playlist| ctx is null"); - - return NGX_ERROR; - } - - ctx->last_time = time(NULL); - - hacf = ngx_rtmp_get_module_app_conf(s, ngx_hls_live_module); - - if (ctx->nfrags < hacf->minfrags || ctx->playing == 0) { - return NGX_AGAIN; - } - - ngx_hls_live_update_playlist(s); - - *last_modified_time = ctx->playlist_modified_time; - - out->last = ngx_cpymem(out->pos, ctx->playlist->pos, - ctx->playlist->last - ctx->playlist->pos); - - m3u8.data = out->pos; - m3u8.len = out->last - out->pos; - - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, "hls-live: playlist| %V, %D", - &m3u8, ctx->last_time); - - return NGX_OK; -} - - -ngx_hls_live_frag_t* -ngx_hls_live_find_frag(ngx_rtmp_session_t *s, ngx_str_t *name) -{ - ngx_hls_live_ctx_t *ctx; - u_char *p0, *p1, *e; - ngx_uint_t frag_id; - ngx_hls_live_frag_t *frag; - ngx_hls_live_app_conf_t *hacf; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_hls_live_module); - - p0 = name->data; - e = p0 + name->len; - - for (; *e != '.' && e != p0; e--); - - if (e == p0) { - return NULL; - } - - p1 = e; - - for (; *e != '-' && e != p0; e--); - - if (e == p0) { - return NULL; - } - - p0 = e + 1; - - frag_id = ngx_atoi(p0, p1 - p0); - - hacf = ngx_rtmp_get_module_app_conf(s, ngx_hls_live_module); - - if (frag_id > ctx->nfrag + ctx->nfrags || - ctx->nfrag + ctx->nfrags - frag_id > hacf->winfrags * 2 + 1) - { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls-live: find_frag| invalid frag id[%d], curr id [%d]", - frag_id, ctx->nfrag + ctx->nfrags); - return NULL; - } - - frag = ctx->frags[frag_id % (hacf->winfrags * 2 + 1)]; - - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "hls-live: find_frag| find frag %p [%d] [frag %d] length %ui", - frag, frag_id, frag->id, frag->length); - - return frag; -} - -void -ngx_rtmp_shared_acquire_frag(ngx_hls_live_frag_t *frag) -{ - frag->ref++; -} - -ngx_chain_t* -ngx_hls_live_prepare_frag(ngx_rtmp_session_t *s, ngx_hls_live_frag_t *frag) -{ - ngx_chain_t *out, *cl, **ll, *last_chain; - ngx_mpegts_frame_t *frame; - - ll = &out; - if (frag->content_pos == frag->content_last) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, "hls-live: prepare_frag| " - "pos %D == last %D", - frag->content_pos, frag->content_last); - return NULL; - } - - last_chain = NULL; - - while (frag->content_pos != frag->content_last) { - frame = frag->content[frag->content_pos]; - - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, "hls-live: prepare_frag| " - "pos %D, last %D, frame chain %p", - frag->content_pos, frag->content_last, - frame); - for (cl = frame->chain; cl; cl = cl->next) { - *ll = ngx_get_chainbuf(0, 0); - (*ll)->buf->pos = cl->buf->pos; - (*ll)->buf->last = cl->buf->last; - (*ll)->buf->flush = 1; - - last_chain = *ll; - - ll = &(*ll)->next; - } - - *ll = NULL; - frag->content_pos = ngx_hls_live_next(s, frag->content_pos); - } - - if (last_chain) { - last_chain->buf->last_buf = 1; - last_chain->buf->last_in_chain = 1; - } - frag->content_pos = 0; - - return out; -} - - -ngx_rtmp_session_t* -ngx_hls_live_fetch_session(ngx_str_t *server, - ngx_str_t *stream, ngx_str_t *session) -{ - ngx_live_stream_t *live_stream; - ngx_hls_live_ctx_t *ctx; - - live_stream = ngx_live_fetch_stream(server, stream); - if (live_stream) { - for (ctx = live_stream->hls_ctx; ctx; ctx = ctx->next) { - if (session->len == ctx->sid.len && - !ngx_strncmp(ctx->sid.data, session->data, session->len)) - { - ngx_log_error(NGX_LOG_DEBUG, ctx->session->log, 0, - "hls-live: fetch_session| session[%p]" - "server %V, stream %V, session %V", - ctx->session, server, stream, session); - return ctx->session; - } - } - } - - return NULL; -} - -static uint64_t -ngx_hls_live_get_fragment_id(ngx_rtmp_session_t *s, uint64_t ts) -{ - ngx_hls_live_ctx_t *ctx; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_hls_live_module); - - return ctx->nfrag + ctx->nfrags; -} - -static void -ngx_hls_live_update_playlist(ngx_rtmp_session_t *s) -{ - u_char *p, *end; - ngx_hls_live_ctx_t *ctx; - ngx_hls_live_app_conf_t *hacf; - ngx_hls_live_frag_t *frag; - ngx_uint_t i, max_frag; - ngx_str_t name_part; - ngx_str_t m3u8; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_hls_live_module); - hacf = ngx_rtmp_get_module_app_conf(s, ngx_hls_live_module); - - time(&ctx->playlist_modified_time); - - max_frag = hacf->fraglen / 1000; - - frag = NULL; - - for (i = 0; i < ctx->nfrags; i++) { - frag = ngx_hls_live_get_frag(s, i); - if (frag && frag->duration > max_frag) { - max_frag = (ngx_uint_t) (frag->duration + .5); - } - } - - if (!ctx->playlist) { - ctx->playlist = ngx_create_temp_buf(s->pool, 1024*512); - } - - p = ctx->playlist->pos; - end = ctx->playlist->end; - - p = ngx_slprintf(p, end, - "#EXTM3U\n" - "#EXT-X-VERSION:3\n" - "#EXT-X-MEDIA-SEQUENCE:%uL\n" - "#EXT-X-TARGETDURATION:%ui\n", - ctx->nfrag, max_frag); - -// if (hacf->type == NGX_RTMP_HLS_TYPE_EVENT) { -// p = ngx_slprintf(p, end, "#EXT-X-PLAYLIST-TYPE: EVENT\n"); -// } - - name_part = s->name; - - for (i = 0; i < ctx->nfrags; i++) { - frag = ngx_hls_live_get_frag(s, i); - - if (frag->discont) { - p = ngx_slprintf(p, end, "#EXT-X-DISCONTINUITY\n"); - } - - p = ngx_slprintf(p, end, - "#EXTINF:%.3f,\n" - "%V%V-%uL.ts?session=%V&slot=%d\n", - frag->duration, &hacf->base_url, - &name_part, frag->id, &ctx->sid, ngx_process_slot); - - ngx_log_debug5(NGX_LOG_DEBUG_RTMP, s->log, 0, - "hls: fragment nfrag=%uL, n=%ui/%ui, duration=%.3f, " - "discont=%i", - ctx->nfrag, i + 1, ctx->nfrags, frag->duration, frag->discont); - } -/* - for (; frag && i < hacf->winfrags; i++) { - p = ngx_slprintf(p, end, - "#EXTINF:%.3f,\n" - "%V%V-%uL.ts?session=%V&slot=%d\n", - hacf->fraglen/1000.0, &hacf->base_url, - &name_part, i, &ctx->sid, ngx_process_slot); - } -*/ - ctx->playlist->last = p; - m3u8.data = ctx->playlist->pos; - m3u8.len = ctx->playlist->last - ctx->playlist->pos; - - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, "hls-live: playlist| %V", &m3u8); - -} - -static ngx_int_t -ngx_hls_live_close_fragment(ngx_rtmp_session_t *s) -{ - ngx_hls_live_ctx_t *ctx; - ngx_hls_live_app_conf_t *hacf; - - hacf = ngx_rtmp_get_module_app_conf(s, ngx_hls_live_module); - ctx = ngx_rtmp_get_module_ctx(s, ngx_hls_live_module); - - if (ctx == NULL || !ctx->opened) { - return NGX_OK; - } - - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "hls: close fragment id=%uL", ctx->nfrag); - - ctx->opened = 0; - - ngx_hls_live_next_frag(s); - - if (ctx->nfrags >= hacf->minfrags && !ctx->playing) - { - ctx->playing = 1; - ngx_rtmp_fire_event(s, NGX_MPEGTS_MSG_M3U8, NULL, NULL); - } - - return NGX_OK; -} - - -void -ngx_hls_live_free_frag(ngx_hls_live_frag_t *frag) -{ - ngx_mpegts_frame_t *frame; - ngx_uint_t i; - - frag->ref--; - - if (frag->ref > 0) { - return; - } - - ngx_log_error(NGX_LOG_DEBUG, ngx_cycle->log, 0, - "hls-live: free_frag| frag[%p] ref %ui", frag, frag->ref); - - for (i = 0; i < frag->content_last; ++i) { - frame = frag->content[i]; - if (frame) { - ngx_rtmp_shared_free_mpegts_frame(frame); - } - } - - frag->next = ngx_hls_live_main_conf->free_frag; - ngx_hls_live_main_conf->free_frag = frag; -} - - -static ngx_hls_live_frag_t* -ngx_hls_live_create_frag(ngx_rtmp_session_t *s) { - ngx_hls_live_frag_t *frag; - - if (ngx_hls_live_main_conf->free_frag) { - frag = ngx_hls_live_main_conf->free_frag; - ngx_hls_live_main_conf->free_frag = - ngx_hls_live_main_conf->free_frag->next; - - ngx_memzero(frag, sizeof(ngx_hls_live_frag_t) + - sizeof(ngx_mpegts_frame_t*) * s->out_queue); - } else { - frag = ngx_pcalloc(ngx_hls_live_main_conf->pool, - sizeof(ngx_hls_live_frag_t) + - sizeof(ngx_mpegts_frame_t*) * s->out_queue); - } - - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "hls-live: create_frag| create frag[%p]", frag); - - return frag; -} - - -static ngx_int_t -ngx_hls_live_open_fragment(ngx_rtmp_session_t *s, uint64_t ts, - ngx_int_t discont) -{ - uint64_t id; - ngx_hls_live_ctx_t *ctx; - ngx_hls_live_frag_t **ffrag, *frag; - ngx_hls_live_app_conf_t *hacf; - ngx_mpegts_frame_t *frame; - ngx_chain_t patpmt; - - hacf = ngx_rtmp_get_module_app_conf(s, ngx_hls_live_module); - - ctx = ngx_rtmp_get_module_ctx(s, ngx_hls_live_module); - - if (ctx->opened) { - return NGX_OK; - } - - id = ngx_hls_live_get_fragment_id(s, ts); - - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "hls: open_fragment| create frag[%uL] timestamp %uL", id, ts); - - ffrag = &(ctx->frags[id % (hacf->winfrags * 2 + 1)]); - if (*ffrag) { - ngx_hls_live_free_frag(*ffrag); - } - *ffrag = ngx_hls_live_create_frag(s); - - frag = *ffrag; - - ngx_memzero(frag, sizeof(*frag)); - - frag->ref = 1; - frag->active = 1; - frag->discont = discont; - frag->id = id; - - ctx->opened = 1; - ctx->frag_ts = ts; - - ngx_memzero(&patpmt, sizeof(patpmt)); - patpmt.buf = ngx_create_temp_buf(s->pool, 376); - patpmt.buf->last = ngx_cpymem(patpmt.buf->pos, - ngx_rtmp_mpegts_pat, 188); - - ngx_rtmp_mpegts_gen_pmt(s->vcodec, s->acodec, s->log, patpmt.buf->last); - patpmt.buf->last += 188; - - frame = ngx_rtmp_shared_alloc_mpegts_frame(&patpmt, 1); - - ngx_hls_live_write_frame(s, frame); - - ngx_rtmp_shared_free_mpegts_frame(frame); - - frag->length = 376; - - return NGX_OK; -} - - -static void -ngx_hls_live_timeout(ngx_event_t *ev) -{ - ngx_rtmp_session_t *s; - ngx_hls_live_ctx_t *ctx; - - s = ev->data; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_hls_live_module); - - if (time(NULL) - ctx->last_time > ctx->timeout/1000) { - ngx_log_error(NGX_LOG_ALERT, s->log, 0, "hls-live: timeout| " - "hls live timeout, %D - %D > %D.", time(NULL), ctx->last_time, - ctx->timeout/1000); - - ngx_rtmp_finalize_fake_session(s); - return; - } - - ngx_add_timer(ev, (ctx->timeout + 3000)/2); -} - - -static ngx_int_t -ngx_hls_live_join(ngx_rtmp_session_t *s, u_char *name, unsigned publisher) -{ - ngx_hls_live_ctx_t *ctx; - ngx_live_stream_t *st; - ngx_rtmp_live_app_conf_t *lacf; - ngx_hls_live_app_conf_t *hacf; - - hacf = ngx_rtmp_get_module_app_conf(s, ngx_hls_live_module); - - lacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_live_module); - if (lacf == NULL) { - return NGX_ERROR; - } - - ctx = ngx_rtmp_get_module_ctx(s, ngx_hls_live_module); - if (ctx && ctx->stream) { - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->log, 0, - "mpegts-live: join| already joined"); - return NGX_ERROR; - } - - if (ctx == NULL) { - ctx = ngx_pcalloc(s->pool, sizeof(ngx_hls_live_ctx_t)); - ngx_rtmp_set_ctx(s, ctx, ngx_hls_live_module); - - ctx->frags = ngx_pcalloc(s->pool, - sizeof(ngx_hls_live_frag_t *) * (hacf->winfrags * 2 + 1)); - if (ctx->frags == NULL) { - return NGX_ERROR; - } - } - - ctx->session = s; - - ngx_log_error(NGX_LOG_INFO, s->log, 0, - "mpegts-live: join| join '%s'", name); - - st = s->live_stream; - - if (!(publisher || st->publish_ctx || lacf->idle_streams)) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "mpegts-live: join| stream not found"); - - s->status = 404; - - ngx_rtmp_finalize_session(s); - - return NGX_ERROR; - } - - ctx->stream = st; - ctx->next = st->hls_ctx; - - st->hls_ctx = ctx; - - ctx->ev.data = s; - ctx->ev.handler = ngx_hls_live_timeout; - ctx->ev.log = s->log; - ctx->timeout = hacf->timeout; - - ngx_add_timer(&ctx->ev, (ctx->timeout + 3000)/2); - - return NGX_OK; -} - -static ngx_int_t -ngx_hls_live_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v) -{ - ngx_hls_live_app_conf_t *hacf; - ngx_hls_live_ctx_t *ctx; -// ngx_rtmp_codec_ctx_t *codec_ctx; - - hacf = ngx_rtmp_get_module_app_conf(s, ngx_hls_live_module); - if (hacf == NULL || !hacf->hls || s->live_type != NGX_HLS_LIVE) { - goto next; - } - - if (s->interprocess || s->live_type != NGX_HLS_LIVE) { - goto next; - } - - if (ngx_hls_live_join(s, v->name, 0) == NGX_ERROR) { - return NGX_ERROR; - } - - ctx = ngx_rtmp_get_module_ctx(s, ngx_hls_live_module); - - ctx->sid.len = ngx_strlen(v->session); - ctx->sid.data = ngx_pcalloc(s->pool, ctx->sid.len); - ngx_memcpy(ctx->sid.data, v->session, ctx->sid.len); -/* - if (s->live_stream->publish_ctx) { - - codec_ctx = ngx_rtmp_get_module_ctx(s->live_stream->publish_ctx->session, - ngx_rtmp_codec_module); - - ngx_mpegts_gop_link(s->live_stream->publish_ctx->session, - s, hacf->playlen, hacf->playlen); - ngx_hls_live_update(s, codec_ctx); - } -*/ -next: - return next_play(s, v); -} - - -static ngx_int_t -ngx_hls_live_close_stream(ngx_rtmp_session_t *s, ngx_rtmp_close_stream_t *v) -{ - ngx_hls_live_app_conf_t *hacf; - ngx_hls_live_ctx_t *ctx, **cctx; - ngx_uint_t i; - ngx_hls_live_frag_t *frag; - - hacf = ngx_rtmp_get_module_app_conf(s, ngx_hls_live_module); - - ctx = ngx_rtmp_get_module_ctx(s, ngx_hls_live_module); - - if (hacf == NULL || !hacf->hls || ctx == NULL) { - goto next; - } - - if (ctx->ev.timer_set) { - ngx_del_timer(&ctx->ev); - } - - if (ctx->stream == NULL) { - goto next; - } - - ngx_rtmp_fire_event(s, NGX_MPEGTS_MSG_CLOSE, NULL, NULL); - - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->log, 0, - "hls: close stream"); - - ngx_hls_live_close_fragment(s); - - for (i = 0; i < 2 * hacf->winfrags + 1; i++) { - frag = ctx->frags[i % (hacf->winfrags * 2 + 1)]; - if (frag) { - ngx_hls_live_free_frag(frag); - } - } - - for (cctx = &ctx->stream->hls_ctx; *cctx; cctx = &(*cctx)->next) { - if (*cctx == ctx) { - *cctx = ctx->next; - break; - } - } - - if (ctx->stream->hls_ctx) { - ctx->stream = NULL; - goto next; - } - -next: - return next_close_stream(s, v); -} - - -static void -ngx_hls_live_update_fragment(ngx_rtmp_session_t *s, uint64_t ts, - ngx_int_t boundary) -{ - ngx_hls_live_ctx_t *ctx; - ngx_hls_live_app_conf_t *hacf; - ngx_hls_live_frag_t *frag; - ngx_msec_t ts_frag_len; - ngx_int_t same_frag, force,discont; - int64_t d; - - hacf = ngx_rtmp_get_module_app_conf(s, ngx_hls_live_module); - ctx = ngx_rtmp_get_module_ctx(s, ngx_hls_live_module); - frag = NULL; - force = 0; - discont = 1; - - if (ctx->opened) { - frag = ngx_hls_live_get_frag(s, ctx->nfrags); - d = (int64_t) (ts - ctx->frag_ts); - - if (d > (int64_t) hacf->max_fraglen * 90 || d < -90000) { - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "hls: force fragment split: %.3f sec, ", d / 90000.); - force = 1; -// if (!boundary) { - discont = 0; -// } - } else { - frag->duration = (ts - ctx->frag_ts) / 90000.; - discont = 0; - } - } - - switch (hacf->slicing) { - case NGX_RTMP_HLS_SLICING_PLAIN: - if (frag && frag->duration < hacf->fraglen / 1000.) { - boundary = 0; - } - break; - - case NGX_RTMP_HLS_SLICING_ALIGNED: - - ts_frag_len = hacf->fraglen * 90; - same_frag = ctx->frag_ts / ts_frag_len == ts / ts_frag_len; - - if (frag && same_frag) { - boundary = 0; - } - - if (frag == NULL && (ctx->frag_ts == 0 || same_frag)) { - ctx->frag_ts = ts; - boundary = 0; - } - - break; - } - - if (boundary || force) { - ngx_hls_live_close_fragment(s); - ngx_hls_live_open_fragment(s, ts, discont); - } -} - - -static ngx_int_t -ngx_hls_live_write_frame(ngx_rtmp_session_t *s, ngx_mpegts_frame_t *frame) -{ - ngx_hls_live_frag_t *frag; - ngx_hls_live_ctx_t *ctx; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_hls_live_module); - - frag = ngx_hls_live_get_frag(s, ctx->nfrags); - - frag->length += frame->length; - - frag->content[frag->content_last] = frame; - frag->content_last = ngx_hls_live_next(s, frag->content_last); - time(&frag->last_modified_time); - - ngx_rtmp_shared_acquire_frame(frame); - - return NGX_OK; -} - - -static ngx_int_t -ngx_hls_live_update(ngx_rtmp_session_t *s, ngx_rtmp_codec_ctx_t *codec_ctx) -{ - ngx_hls_live_ctx_t *ctx; - ngx_mpegts_frame_t *frame; - ngx_int_t boundary; - ngx_buf_t *b; - - b = NULL; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_hls_live_module); - - while (s->out_pos != s->out_last) { - - frame = s->mpegts_out[s->out_pos]; -#if 1 - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "hls-live: update| " - "frame[%p] pos[%O] last[%O] pts[%uL] type [%d], key %d, opened %d", - frame, s->out_pos, s->out_last,frame->pts, - frame->type, frame->key, ctx->opened); -#endif - boundary = 0; - - if (frame->type == NGX_MPEGTS_MSG_AUDIO) { - boundary = codec_ctx->avc_header == NULL; - } else if (frame->type == NGX_MPEGTS_MSG_VIDEO) { - b = ctx->aframe; - boundary = frame->key && - (codec_ctx->aac_header == NULL || !ctx->opened || - (b && b->last > b->pos)); - } else { - return NGX_ERROR; - } - - s->acodec = codec_ctx->audio_codec_id; - s->vcodec = codec_ctx->video_codec_id; - - ngx_hls_live_update_fragment(s, frame->pts, boundary); - - if (!ctx->opened) { - break; - } - - ngx_hls_live_write_frame(s, frame); - - ngx_rtmp_shared_free_mpegts_frame(frame); - - ++s->out_pos; - s->out_pos %= s->out_queue; - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_hls_live_av(ngx_rtmp_session_t *s, ngx_mpegts_frame_t *frame) -{ - ngx_live_stream_t *live_stream; - ngx_hls_live_ctx_t *ctx; - ngx_rtmp_session_t *ss; - ngx_rtmp_codec_ctx_t *codec_ctx; - ngx_hls_live_app_conf_t *hacf; - - codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - hacf = ngx_rtmp_get_module_app_conf(s, ngx_hls_live_module); - - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "hls-live: av| pts[%uL] type [%d] key[%d]", - frame->dts/90, frame->type, frame->key); - - live_stream = s->live_stream; - for (ctx = live_stream->hls_ctx; ctx; ctx = ctx->next) { - ss = ctx->session; - - switch (ngx_mpegts_gop_link(s, ss, hacf->playlen, hacf->playlen)) { - case NGX_DECLINED: - continue; - case NGX_ERROR: - ngx_rtmp_finalize_fake_session(ss); - continue; - default: - break; - } - - ngx_hls_live_update(ss, codec_ctx); - } - - if (frame->type == NGX_MPEGTS_MSG_VIDEO) { - return next_mpegts_video(s, frame); - } else if (frame->type == NGX_MPEGTS_MSG_AUDIO) { - return next_mpegts_audio(s, frame); - } - - return NGX_ERROR; -} - -static void * -ngx_hls_live_create_main_conf(ngx_conf_t *cf) -{ - ngx_hls_live_main_conf_t *conf; - - conf = ngx_pcalloc(cf->pool, sizeof(ngx_hls_live_main_conf_t)); - if (conf == NULL) { - return NULL; - } - - conf->pool = ngx_create_pool(1024, ngx_cycle->log); - ngx_hls_live_main_conf = conf; - - return conf; -} - -static void * -ngx_hls_live_create_app_conf(ngx_conf_t *cf) -{ - ngx_hls_live_app_conf_t *conf; - - conf = ngx_pcalloc(cf->pool, sizeof(ngx_hls_live_app_conf_t)); - if (conf == NULL) { - return NULL; - } - - conf->pool = ngx_create_pool(1024, ngx_cycle->log); - - conf->hls = NGX_CONF_UNSET; - conf->fraglen = NGX_CONF_UNSET_MSEC; - conf->max_fraglen = NGX_CONF_UNSET_MSEC; - conf->playlen = NGX_CONF_UNSET_MSEC; - conf->slicing = NGX_CONF_UNSET_UINT; - conf->type = NGX_CONF_UNSET_UINT; - conf->audio_buffer_size = NGX_CONF_UNSET_SIZE; - conf->cleanup = NGX_CONF_UNSET; - conf->timeout = NGX_CONF_UNSET_MSEC; - conf->minfrags = NGX_CONF_UNSET_UINT; - - return conf; -} - - -static char * -ngx_hls_live_merge_app_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_hls_live_app_conf_t *prev = parent; - ngx_hls_live_app_conf_t *conf = child; - - ngx_conf_merge_value(conf->hls, prev->hls, 0); - ngx_conf_merge_msec_value(conf->fraglen, prev->fraglen, 5000); - ngx_conf_merge_msec_value(conf->max_fraglen, prev->max_fraglen, - conf->fraglen * 10); - ngx_conf_merge_msec_value(conf->playlen, prev->playlen, conf->fraglen * 3); - ngx_conf_merge_uint_value(conf->slicing, prev->slicing, - NGX_RTMP_HLS_SLICING_PLAIN); - ngx_conf_merge_value(conf->cleanup, prev->cleanup, 1); - ngx_conf_merge_str_value(conf->base_url, prev->base_url, ""); - ngx_conf_merge_uint_value(conf->minfrags, prev->minfrags, 2); - - conf->timeout = conf->playlen * 3; - - if (conf->fraglen) { - conf->winfrags = conf->playlen / conf->fraglen; - } - - return NGX_CONF_OK; -} - - -static ngx_int_t -ngx_hls_live_postconfiguration(ngx_conf_t *cf) -{ - next_play = ngx_rtmp_play; - ngx_rtmp_play = ngx_hls_live_play; - - next_close_stream = ngx_rtmp_close_stream; - ngx_rtmp_close_stream = ngx_hls_live_close_stream; - - next_mpegts_video = ngx_mpegts_video; - ngx_mpegts_video = ngx_hls_live_av; - - next_mpegts_audio = ngx_mpegts_audio; - ngx_mpegts_audio = ngx_hls_live_av; - - return NGX_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_hls_live_module.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_hls_live_module.h deleted file mode 100644 index b019c886a4..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_hls_live_module.h +++ /dev/null @@ -1,95 +0,0 @@ - -/* - * Copyright (C) Pingo (cczjp89@gmail.com) - */ - -#ifndef _NGX_HLS_LIVE_MODULE_H_INCLUDE_ -#define _NGX_HLS_LIVE_MODULE_H_INCLUDE_ - -#define ngx_hls_live_next(s, pos) ((pos + 1) % s->out_queue) -#define ngx_hls_live_prev(s, pos) (pos == 0 ? s->out_queue - 1 : pos - 1) - -typedef struct ngx_hls_live_frag_s ngx_hls_live_frag_t; -typedef struct ngx_hls_live_play_s ngx_hls_live_play_t; - -struct ngx_hls_live_play_s { - ngx_str_t name; - /* connection parameters */ - ngx_rtmp_addr_conf_t *addr_conf; - ngx_str_t app; - ngx_str_t stream; - ngx_str_t args; - ngx_str_t flashver; - ngx_str_t swf_url; - ngx_str_t tc_url; - uint32_t acodecs; - uint32_t vcodecs; - ngx_str_t page_url; - ngx_str_t domain; - ngx_str_t serverid; - ngx_log_t *log; -}; - -struct ngx_hls_live_frag_s { - ngx_uint_t ref; - ngx_hls_live_frag_t *next; - time_t last_modified_time; - uint64_t id; - uint64_t key_id; - double duration; - unsigned active:1; - unsigned discont:1; /* before */ - ngx_uint_t length; - ngx_chain_t *out; - ngx_uint_t content_last; - ngx_uint_t content_pos; - ngx_mpegts_frame_t *content[0]; -}; - -struct ngx_hls_live_ctx_s { - unsigned opened:1; - unsigned playing:1; - - ngx_buf_t *patpmt; - ngx_rtmp_session_t *session; - - ngx_str_t sid; - ngx_live_stream_t *stream; - ngx_str_t name; - - uint64_t nfrag; - uint64_t frag_ts; - uint64_t key_id; - ngx_uint_t nfrags; - ngx_hls_live_frag_t **frags; /* circular 2 * winfrags + 1 */ - ngx_hls_live_frag_t *frag; - - ngx_uint_t audio_cc; - ngx_uint_t video_cc; - ngx_uint_t key_frags; - - uint64_t aframe_base; - uint64_t aframe_num; - - ngx_buf_t *aframe; - uint64_t aframe_pts; - ngx_event_t ev; - ngx_msec_t timeout; - ngx_msec_t last_time; - time_t playlist_modified_time; - ngx_buf_t *playlist; - ngx_hls_live_ctx_t *next; -}; - -ngx_int_t ngx_hls_live_write_playlist(ngx_rtmp_session_t *s, ngx_buf_t *out, - time_t *last_modified_time); -ngx_hls_live_frag_t* ngx_hls_live_find_frag(ngx_rtmp_session_t *s, - ngx_str_t *name); -ngx_chain_t* ngx_hls_live_prepare_frag(ngx_rtmp_session_t *s, - ngx_hls_live_frag_t *frag); -void ngx_hls_live_free_frag(ngx_hls_live_frag_t *frag); -ngx_rtmp_session_t* ngx_hls_live_fetch_session(ngx_str_t *server, - ngx_str_t *stream, ngx_str_t *session); -void ngx_rtmp_shared_acquire_frag(ngx_hls_live_frag_t *frag); - -#endif diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_gop_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_gop_module.c deleted file mode 100644 index 0827da9dee..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_gop_module.c +++ /dev/null @@ -1,731 +0,0 @@ - -/* - * Copyright (C) Pingo (cczjp89@gmail.com) - */ - -#include -#include -#include "ngx_rtmp.h" -#include "ngx_rtmp_codec_module.h" -#include "ngx_rtmp_live_module.h" -#include "ngx_mpegts_live_module.h" - - -static ngx_rtmp_close_stream_pt next_close_stream; - -static ngx_mpegts_video_pt next_mpegts_video; -static ngx_mpegts_audio_pt next_mpegts_audio; - -static void *ngx_mpegts_gop_create_app_conf(ngx_conf_t *cf); -static char *ngx_mpegts_gop_merge_app_conf(ngx_conf_t *cf, void *parent, - void *child); - -static ngx_int_t ngx_mpegts_gop_postconfiguration(ngx_conf_t *cf); - -#define ngx_mpegts_gop_next(s, pos) ((pos + 1) % s->out_queue) -#define ngx_mpegts_gop_prev(s, pos) (pos == 0 ? s->out_queue - 1 : pos - 1) - -typedef struct { - /* publisher: head of cache - * player: cache send position of publisher's out - */ - size_t gop_pos; - /* tail of cache */ - size_t gop_last; - /* 0 for not send, 1 for sending, 2 for sent */ - ngx_flag_t send_gop; - - ngx_mpegts_frame_t *keyframe; - - ngx_uint_t meta_version; - - uint64_t first_timestamp; - uint64_t current_timestamp; - - ngx_uint_t base_type; - - /* only for publisher, must at last of ngx_mpegts_gop_ctx_t */ - ngx_mpegts_frame_t *cache[]; -} ngx_mpegts_gop_ctx_t; - -typedef struct { - ngx_msec_t cache_time; - ngx_msec_t roll_back; - ngx_msec_t one_off_send; - ngx_flag_t low_latency; - ngx_flag_t send_all; - ngx_msec_t fix_timestamp; - ngx_flag_t zero_start; -} ngx_mpegts_gop_app_conf_t; - - -static ngx_command_t ngx_mpegts_gop_commands[] = { - - { ngx_string("mpegts_cache_time"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_mpegts_gop_app_conf_t, cache_time), - NULL }, - - { ngx_string("mpegts_roll_back"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_mpegts_gop_app_conf_t, roll_back), - NULL }, - - { ngx_string("mpegts_one_off_send"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_mpegts_gop_app_conf_t, one_off_send), - NULL }, - - { ngx_string("mpegts_low_latency"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_mpegts_gop_app_conf_t, low_latency), - NULL }, - - { ngx_string("mpegts_send_all"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_mpegts_gop_app_conf_t, send_all), - NULL }, - - { ngx_string("mpegts_fix_timestamp"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_mpegts_gop_app_conf_t, fix_timestamp), - NULL }, - - { ngx_string("mpegts_zero_start"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_mpegts_gop_app_conf_t, zero_start), - NULL }, - - ngx_null_command -}; - - -static ngx_rtmp_module_t ngx_mpegts_gop_module_ctx = { - NULL, /* preconfiguration */ - ngx_mpegts_gop_postconfiguration, /* postconfiguration */ - NULL, /* create main configuration */ - NULL, /* init main configuration */ - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - ngx_mpegts_gop_create_app_conf, /* create app configuration */ - ngx_mpegts_gop_merge_app_conf /* merge app configuration */ -}; - - -ngx_module_t ngx_mpegts_gop_module = { - NGX_MODULE_V1, - &ngx_mpegts_gop_module_ctx, /* module context */ - ngx_mpegts_gop_commands, /* module directives */ - NGX_RTMP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void * -ngx_mpegts_gop_create_app_conf(ngx_conf_t *cf) -{ - ngx_mpegts_gop_app_conf_t *gacf; - - gacf = ngx_pcalloc(cf->pool, sizeof(ngx_mpegts_gop_app_conf_t)); - if (gacf == NULL) { - return NULL; - } - - gacf->cache_time = NGX_CONF_UNSET_MSEC; - gacf->roll_back = NGX_CONF_UNSET_MSEC; - gacf->one_off_send = NGX_CONF_UNSET_MSEC; - gacf->low_latency = NGX_CONF_UNSET; - gacf->send_all = NGX_CONF_UNSET; - gacf->fix_timestamp = NGX_CONF_UNSET_MSEC; - gacf->zero_start = NGX_CONF_UNSET; - - return gacf; -} - -static char * -ngx_mpegts_gop_merge_app_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_mpegts_gop_app_conf_t *prev = parent; - ngx_mpegts_gop_app_conf_t *conf = child; - - ngx_conf_merge_msec_value(conf->cache_time, prev->cache_time, 0); - ngx_conf_merge_msec_value(conf->roll_back, prev->roll_back, conf->cache_time); - ngx_conf_merge_msec_value(conf->one_off_send, prev->one_off_send, 3000); - ngx_conf_merge_value(conf->low_latency, prev->low_latency, 0); - ngx_conf_merge_value(conf->send_all, prev->send_all, 0); - ngx_conf_merge_msec_value(conf->fix_timestamp, prev->fix_timestamp, 10000); - ngx_conf_merge_value(conf->zero_start, prev->zero_start, 0); - - return NGX_CONF_OK; -} - - -static ngx_int_t -ngx_mpegts_gop_link_frame(ngx_rtmp_session_t *s, ngx_mpegts_frame_t *frame) -{ - ngx_uint_t nmsg; - - if (frame == NULL) { - return NGX_OK; - } - - nmsg = (s->out_last - s->out_pos) % s->out_queue + 1; - - if (nmsg >= s->out_queue) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "link frame nmsg(%ui) >= out_queue(%O)", nmsg, s->out_queue); - return NGX_AGAIN; - } - -#if 0 - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "link frame pos[%O] last[%O], pts[%ud]", - s->out_pos, s->out_last, frame->pts); -#endif - - s->mpegts_out[s->out_last] = frame; - s->out_last = ngx_mpegts_gop_next(s, s->out_last); - - ngx_rtmp_shared_acquire_mpegts_frame(frame); - - return NGX_OK; -} - - -static void -ngx_mpegts_gop_reset_gop(ngx_rtmp_session_t *s, ngx_mpegts_gop_ctx_t *ctx, - ngx_mpegts_frame_t *frame) -{ - ngx_mpegts_gop_app_conf_t *gacf; - ngx_mpegts_frame_t *f, *next_keyframe; - size_t pos; - ngx_uint_t nmsg; - ngx_msec_t cache_time; - - pos = ctx->gop_pos; - - f = ctx->cache[pos]; - if (f == NULL) { - return; - } - - gacf = ngx_rtmp_get_module_app_conf(s, ngx_mpegts_gop_module); - - cache_time = gacf->cache_time > gacf->roll_back ? - gacf->cache_time : gacf->roll_back; - - /* only audio in cache */ - if (ctx->keyframe == NULL) { - if (frame->pts - ctx->cache[ctx->gop_pos]->pts > cache_time * 90) { - ngx_rtmp_shared_free_mpegts_frame(f); - ctx->cache[ctx->gop_pos] = NULL; - ctx->gop_pos = ngx_mpegts_gop_next(s, ctx->gop_pos); - } - - return; - } - - /* only video of video + audio */ - next_keyframe = ctx->keyframe->next; - - /* only one gop in cache */ - if (next_keyframe == NULL) { - return; - } - - nmsg = (ctx->gop_last - ctx->gop_pos) % s->out_queue + 2; - if (nmsg >= s->out_queue) { - goto reset; - } - - if (frame->type == NGX_MPEGTS_MSG_AUDIO) { - return; - } - - if (frame->type == NGX_MPEGTS_MSG_VIDEO && frame->pts - - next_keyframe->pts < cache_time * 90) - { - return; - } - -reset: - for (pos = ctx->gop_pos; ctx->cache[pos] != next_keyframe; - pos = ngx_mpegts_gop_next(s, pos)) - { - f = ctx->cache[pos]; - - ngx_rtmp_shared_free_mpegts_frame(f); - - ctx->cache[pos] = NULL; - } - - ctx->keyframe = next_keyframe; - ctx->gop_pos = pos; -} - -static void -ngx_mpegts_gop_print_cache(ngx_rtmp_session_t *s, ngx_mpegts_gop_ctx_t *ctx) -{ -#if (NGX_DEBUG) - ngx_mpegts_frame_t *frame; - u_char content[10240], *p; - size_t pos; - - ngx_memzero(content, sizeof(content)); - - p = content; - for (pos = ctx->gop_pos; pos != ctx->gop_last; - pos = ngx_mpegts_gop_next(s, pos)) - { - frame = ctx->cache[pos]; - switch (frame->type) { - case NGX_MPEGTS_MSG_AUDIO: - *p++ = 'A'; - break; - case NGX_MPEGTS_MSG_VIDEO: - *p++ = 'V'; - break; - default: - *p++ = 'O'; - break; - } - - if (frame->key) { - *p++ = 'I'; - } - - *p++ = ' '; - } - - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "[%z %z] %s", ctx->gop_pos, ctx->gop_last, content); -#endif -} - -ngx_int_t -ngx_mpegts_gop_cache(ngx_rtmp_session_t *s, ngx_mpegts_frame_t *frame) -{ - ngx_mpegts_gop_app_conf_t *gacf; - ngx_mpegts_gop_ctx_t *ctx; - ngx_mpegts_frame_t **keyframe; - ngx_uint_t nmsg; - - gacf = ngx_rtmp_get_module_app_conf(s, ngx_mpegts_gop_module); - if (gacf->cache_time == 0) { - return NGX_OK; - } - - ctx = ngx_rtmp_get_module_ctx(s, ngx_mpegts_gop_module); - if (ctx == NULL) { - ctx = ngx_pcalloc(s->pool, sizeof(ngx_mpegts_gop_ctx_t) - + s->out_queue * sizeof(ngx_mpegts_frame_t *)); - if (ctx == NULL) { - return NGX_ERROR; - } - ngx_rtmp_set_ctx(s, ctx, ngx_mpegts_gop_module); - } - - nmsg = (ctx->gop_last - ctx->gop_pos) % s->out_queue + 1; - if (nmsg >= s->out_queue) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "cache frame nmsg(%ui) >= out_queue(%z)", nmsg, s->out_queue); - return NGX_AGAIN; - } -#if 0 - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "cache frame: %ud[%d], %ud, %ud", - frame->type, frame->key, frame->pts, frame->length); -#endif - /* first video frame is not intra_frame */ - if (ctx->keyframe == NULL && frame->type == NGX_MPEGTS_MSG_VIDEO - && !frame->key) - { - return NGX_OK; - } - - /* video intra_frame */ - if (frame->key) { - for (keyframe = &ctx->keyframe; *keyframe; - keyframe = &((*keyframe)->next)); - *keyframe = frame; - } - - frame->pos = ctx->gop_last; - ctx->current_timestamp = frame->pts; - ctx->cache[ctx->gop_last] = frame; - ctx->gop_last = ngx_mpegts_gop_next(s, ctx->gop_last); - - ngx_rtmp_shared_acquire_mpegts_frame(frame); - - ngx_mpegts_gop_reset_gop(s, ctx, frame); - - ngx_mpegts_gop_print_cache(s, ctx); - - return NGX_OK; -} - - -static ngx_int_t -ngx_mpegts_gop_send_gop(ngx_rtmp_session_t *s, ngx_rtmp_session_t *ss) -{ - ngx_mpegts_gop_app_conf_t *gacf; - ngx_mpegts_gop_ctx_t *sctx, *ssctx; - ngx_mpegts_frame_t *frame, *keyframe; - size_t pos; - - gacf = ngx_rtmp_get_module_app_conf(s, ngx_mpegts_gop_module); - - sctx = ngx_rtmp_get_module_ctx(s, ngx_mpegts_gop_module); - ssctx = ngx_rtmp_get_module_ctx(ss, ngx_mpegts_gop_module); - - /* already send gop */ - if (ssctx->send_gop == 2) { - return NGX_OK; - } - - //***************************************************************** - // - // TODO: send pat pmt - // - //***************************************************************** - - /* link frame in s to ss */ - if (ssctx->send_gop == 0) { - ssctx->gop_pos = sctx->gop_pos; - if (sctx->cache[ssctx->gop_pos] == NULL) { - return NGX_AGAIN; - } - - ssctx->send_gop = 1; - ssctx->first_timestamp = sctx->cache[ssctx->gop_pos]->pts; - ssctx->base_type = sctx->cache[ssctx->gop_pos]->type; - } else { - if (sctx->cache[ssctx->gop_pos] == NULL) { - ssctx->gop_pos = sctx->gop_pos; - } - } - - frame = NULL; - - keyframe = sctx->keyframe; - while (ss->roll_back && keyframe && - ((sctx->current_timestamp - keyframe->pts) > ss->roll_back * 90)) - { - ngx_log_error(NGX_LOG_INFO, s->log, 0, - "rtmp-gop: send_gop| curr %D - k %D, %D", - sctx->current_timestamp, keyframe->pts, ss->roll_back * 90); - frame = keyframe; - keyframe = keyframe->next; - } - - if (frame == NULL) { - pos = ssctx->gop_pos; - frame = sctx->cache[pos]; - } else { - pos = frame->pos; - } - - while (frame) { - - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "send gop link %D, type %d, curr %D", - frame->pts/90, frame->type, sctx->current_timestamp/90); - if (ngx_mpegts_gop_link_frame(ss, frame) == NGX_AGAIN) { - break; - } - - if (!gacf->send_all && frame->type == ssctx->base_type && - frame->pts - ssctx->first_timestamp >= gacf->one_off_send * 90) - { - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "gone %D, type %d, first %D, curr %D, send %D", - frame->pts/90, frame->type, ssctx->first_timestamp/90, - sctx->current_timestamp/90, gacf->one_off_send); - - ssctx->send_gop = 2; - pos = ngx_mpegts_gop_next(s, pos); - break; - } - - pos = ngx_mpegts_gop_next(s, pos); - frame = sctx->cache[pos]; - } - - if (frame == NULL) { /* send all frame in cache */ - ssctx->send_gop = 2; - } - - ssctx->gop_pos = pos; - ngx_rtmp_send_message(ss, NULL, 0); - - return NGX_AGAIN; -} - -ngx_int_t -ngx_mpegts_gop_send(ngx_rtmp_session_t *s, ngx_rtmp_session_t *ss) -{ - ngx_mpegts_gop_app_conf_t *gacf; - ngx_mpegts_gop_ctx_t *sctx, *ssctx; - ngx_mpegts_frame_t *frame; - - gacf = ngx_rtmp_get_module_app_conf(s, ngx_mpegts_gop_module); - if (gacf->cache_time == 0) { - return NGX_DECLINED; - } - - sctx = ngx_rtmp_get_module_ctx(s, ngx_mpegts_gop_module); - if (sctx == NULL) { /* publisher doesn't publish av frame */ - return NGX_DECLINED; - } - - ssctx = ngx_rtmp_get_module_ctx(ss, ngx_mpegts_gop_module); - if (ssctx == NULL) { - ssctx = ngx_pcalloc(ss->pool, sizeof(ngx_mpegts_gop_ctx_t)); - if (ssctx == NULL) { - return NGX_ERROR; - } - ngx_rtmp_set_ctx(ss, ssctx, ngx_mpegts_gop_module); - } - - if (ngx_mpegts_gop_send_gop(s, ss) == NGX_AGAIN) { - return NGX_OK; - } - - if (sctx->cache[ssctx->gop_pos] == NULL) { - ngx_log_error(NGX_LOG_ERR, ss->log, 0, - "mpegts-gop: gop_send| current gop pos is NULL, " - "skip to new postion [pos %d last %d] %d", - sctx->gop_pos, sctx->gop_last, ssctx->gop_pos); - - ssctx->gop_pos = sctx->gop_pos; - } - - frame = sctx->cache[ssctx->gop_pos]; - if (ngx_mpegts_gop_link_frame(ss, frame) == NGX_AGAIN) { - return NGX_AGAIN; - } - - ssctx->gop_pos = ngx_mpegts_gop_next(s, ssctx->gop_pos); - ngx_rtmp_send_message(ss, NULL, 0); - - return NGX_OK; -} - -static ngx_int_t -ngx_mpegts_gop_offset_frames(ngx_rtmp_session_t *s, ngx_rtmp_session_t *ss, - ngx_msec_t time_offset, ngx_msec_t duration) -{ - ngx_mpegts_gop_ctx_t *sctx, *ssctx; - ngx_mpegts_frame_t *frame, *keyframe; - size_t pos; - - sctx = ngx_rtmp_get_module_ctx(s, ngx_mpegts_gop_module); - ssctx = ngx_rtmp_get_module_ctx(ss, ngx_mpegts_gop_module); - - /* already send gop */ - if (ssctx->send_gop == 2) { - return NGX_OK; - } - - //***************************************************************** - // - // TODO: send pat pmt - // - //***************************************************************** - - /* link frame in s to ss */ - if (ssctx->send_gop == 0) { - ssctx->gop_pos = sctx->gop_pos; - if (sctx->cache[ssctx->gop_pos] == NULL) { - return NGX_AGAIN; - } - - ssctx->send_gop = 1; - ssctx->first_timestamp = sctx->cache[ssctx->gop_pos]->pts; - ssctx->base_type = sctx->cache[ssctx->gop_pos]->type; - } else { - if (sctx->cache[ssctx->gop_pos] == NULL) { - ssctx->gop_pos = sctx->gop_pos; - } - } - - frame = NULL; - - keyframe = sctx->keyframe; - while (time_offset && keyframe && - ((sctx->current_timestamp - keyframe->pts) > time_offset * 90)) - { - ngx_log_error(NGX_LOG_DEBUG, ss->log, 0, - "mpegts-gop: offset_frames| curr %D - k %D = %D, %D", - sctx->current_timestamp, keyframe->pts, - (sctx->current_timestamp - keyframe->pts) / 90, time_offset); - frame = keyframe; - keyframe = keyframe->next; - ssctx->first_timestamp = frame->pts; - ssctx->base_type = frame->type; - } - - if (frame == NULL) { - pos = ssctx->gop_pos; - frame = sctx->cache[pos]; - } else { - pos = frame->pos; - } - - while (frame) { - - if (ngx_mpegts_gop_link_frame(ss, frame) == NGX_AGAIN) { - break; - } - - if (frame->type == ssctx->base_type && - frame->pts - ssctx->first_timestamp >= duration * 90) - { - ngx_log_error(NGX_LOG_INFO, ss->log, 0, "gone %D, first %D, curr %D", - frame->pts, ssctx->first_timestamp, sctx->current_timestamp); - ssctx->send_gop = 2; - pos = ngx_mpegts_gop_next(s, pos); - break; - } - - pos = ngx_mpegts_gop_next(s, pos); - frame = sctx->cache[pos]; - } - - if (frame == NULL) { /* send all frame in cache */ - ssctx->send_gop = 2; - } - - ssctx->gop_pos = pos; - - return NGX_AGAIN; -} - -ngx_int_t -ngx_mpegts_gop_link(ngx_rtmp_session_t *s, ngx_rtmp_session_t *ss, - ngx_msec_t time_offset, ngx_msec_t duration) -{ - ngx_mpegts_gop_app_conf_t *gacf; - ngx_mpegts_gop_ctx_t *sctx, *ssctx; - ngx_mpegts_frame_t *frame; - - gacf = ngx_rtmp_get_module_app_conf(s, ngx_mpegts_gop_module); - if (gacf->cache_time == 0) { - return NGX_DECLINED; - } - - sctx = ngx_rtmp_get_module_ctx(s, ngx_mpegts_gop_module); - if (sctx == NULL) { /* publisher doesn't publish av frame */ - return NGX_DECLINED; - } - - ssctx = ngx_rtmp_get_module_ctx(ss, ngx_mpegts_gop_module); - if (ssctx == NULL) { - ssctx = ngx_pcalloc(ss->pool, sizeof(ngx_mpegts_gop_ctx_t)); - if (ssctx == NULL) { - return NGX_ERROR; - } - ngx_rtmp_set_ctx(ss, ssctx, ngx_mpegts_gop_module); - } - - if (ngx_mpegts_gop_offset_frames(s, ss, time_offset, duration) == NGX_AGAIN) - { - return NGX_OK; - } - - /* new frame is video key frame */ - if (sctx->cache[ssctx->gop_pos] == NULL) { - ngx_log_error(NGX_LOG_ERR, ss->log, 0, - "mpegts-gop: link| current gop pos is NULL, " - "skip to new postion [pos %d last %d] %d", - sctx->gop_pos, sctx->gop_last, ssctx->gop_pos); - - ssctx->gop_pos = sctx->gop_pos; - } - - frame = sctx->cache[ssctx->gop_pos]; - if (ngx_mpegts_gop_link_frame(ss, frame) == NGX_AGAIN) { - return NGX_AGAIN; - } - - ssctx->gop_pos = ngx_mpegts_gop_next(s, ssctx->gop_pos); - - return NGX_OK; -} - - -static ngx_int_t -ngx_mpegts_gop_close_stream(ngx_rtmp_session_t *s, ngx_rtmp_close_stream_t *v) -{ - ngx_mpegts_gop_ctx_t *ctx; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_mpegts_gop_module); - if (ctx == NULL) { - goto next; - } - - if (!s->published) { - goto next; - } - - /* free cache in publisher */ - while (ctx->gop_pos != ctx->gop_last) { - ngx_rtmp_shared_free_mpegts_frame(ctx->cache[ctx->gop_pos]); - ctx->gop_pos = ngx_mpegts_gop_next(s, ctx->gop_pos); - } - -next: - return next_close_stream(s, v); -} - -static ngx_int_t -ngx_mpegts_gop_av(ngx_rtmp_session_t *s, ngx_mpegts_frame_t *frame) -{ - if (frame->type == NGX_MPEGTS_MSG_VIDEO) { - ngx_mpegts_gop_cache(s, frame); - - return next_mpegts_video(s, frame); - } else if (frame->type == NGX_MPEGTS_MSG_AUDIO) { - ngx_mpegts_gop_cache(s, frame); - - return next_mpegts_audio(s, frame); - } - - return NGX_ERROR; -} - -static ngx_int_t -ngx_mpegts_gop_postconfiguration(ngx_conf_t *cf) -{ - next_close_stream = ngx_rtmp_close_stream; - ngx_rtmp_close_stream = ngx_mpegts_gop_close_stream; - - next_mpegts_video = ngx_mpegts_video; - ngx_mpegts_video = ngx_mpegts_gop_av; - - next_mpegts_audio = ngx_mpegts_audio; - ngx_mpegts_audio = ngx_mpegts_gop_av; - - return NGX_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_gop_module.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_gop_module.h deleted file mode 100644 index 3b1ca53074..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_gop_module.h +++ /dev/null @@ -1,19 +0,0 @@ - -/* - * Copyright (C) Pingo (cczjp89@gmail.com) - */ - -#ifndef _NGX_MPEGTS_GOP_MODULE_H_INCLUDE_ -#define _NGX_MPEGTS_GOP_MODULE_H_INCLUDE_ - -#include "ngx_rtmp.h" - -ngx_int_t -ngx_mpegts_gop_cache(ngx_rtmp_session_t *s, ngx_mpegts_frame_t *frame); -ngx_int_t -ngx_mpegts_gop_link(ngx_rtmp_session_t *s, ngx_rtmp_session_t *ss, - ngx_msec_t time_offset, ngx_msec_t duration); -ngx_int_t -ngx_mpegts_gop_send(ngx_rtmp_session_t *s, ngx_rtmp_session_t *ss); - -#endif diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_http_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_http_module.c deleted file mode 100644 index ce2ac3cb49..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_http_module.c +++ /dev/null @@ -1,611 +0,0 @@ - -/* - * Copyright (C) Pingo (cczjp89@gmail.com) - */ - - -#include -#include -#include -#include -#include "ngx_rtmp.h" -#include "ngx_rtmp_cmd_module.h" -#include "ngx_rbuf.h" -#include "ngx_http_set_header.h" -#include "ngx_rtmp_monitor_module.h" -#include "ngx_mpegts_gop_module.h" -#include "ngx_mpegts_live_module.h" - - -static char *ngx_mpegts_http(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); - -static void *ngx_mpegts_http_create_loc_conf(ngx_conf_t *cf); -static char *ngx_mpegts_http_merge_loc_conf(ngx_conf_t *cf, void *parent, - void *child); - -static ngx_keyval_t ngx_mpegts_http_headers[] = { - { ngx_string("Cache-Control"), ngx_string("no-cache") }, -// { ngx_string("Content-Type"), ngx_string("video/x-ts") }, - { ngx_null_string, ngx_null_string } -}; - -typedef struct { - ngx_rtmp_session_t *session; -} ngx_mpegts_http_ctx_t; - -typedef struct { - ngx_str_t app; - ngx_str_t flashver; - ngx_str_t swf_url; - ngx_str_t tc_url; - ngx_str_t page_url; - - ngx_rtmp_addr_conf_t *addr_conf; -} ngx_mpegts_http_loc_conf_t; - - -static ngx_command_t ngx_mpegts_http_commands[] = { - - { ngx_string("ts_live"), - NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12, - ngx_mpegts_http, - NGX_HTTP_LOC_CONF_OFFSET, - 0, - NULL }, - - ngx_null_command -}; - - -static ngx_http_module_t ngx_mpegts_http_module_ctx = { - NULL, /* preconfiguration */ - NULL, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - ngx_mpegts_http_create_loc_conf, /* create location configuration */ - ngx_mpegts_http_merge_loc_conf /* merge location configuration */ -}; - - -ngx_module_t ngx_mpegts_http_module = { - NGX_MODULE_V1, - &ngx_mpegts_http_module_ctx, /* module context */ - ngx_mpegts_http_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static ngx_int_t -ngx_mpegts_http_send_header(ngx_http_request_t *r) -{ - ngx_int_t rc; - ngx_keyval_t *h; - ngx_chain_t out; - ngx_mpegts_http_ctx_t *ctx; - ngx_rtmp_session_t *s, *ps; - - if (r->header_sent) { - return NGX_OK; - } - - ctx = ngx_http_get_module_ctx(r, ngx_mpegts_http_module); - s = ctx->session; - ps = s->live_stream->publish_ctx->session; - - r->headers_out.status = NGX_HTTP_OK; - r->keepalive = 0; /* set Connection to closed */ - - h = ngx_mpegts_http_headers; - while (h->key.len) { - rc = ngx_http_set_header_out(r, &h->key, &h->value); - if (rc != NGX_OK) { - return rc; - } - ++h; - } - - rc = ngx_http_send_header(r); - if (rc == NGX_ERROR || rc > NGX_OK) { - return rc; - } - - ngx_memzero(&out, sizeof(out)); - out.buf = ngx_create_temp_buf(s->pool, 376); - out.buf->last = ngx_cpymem(out.buf->pos, - ngx_rtmp_mpegts_pat, 188); - - ngx_rtmp_mpegts_gen_pmt(ps->vcodec, ps->acodec, s->log, out.buf->last); - out.buf->last += 188; - - out.buf->flush = 1; - out.buf->memory = 1; - - return ngx_http_output_filter(r, &out); -} - -static void -ngx_mpegts_http_write_handler(ngx_http_request_t *r) -{ - ngx_mpegts_http_ctx_t *ctx; - ngx_rtmp_session_t *s; - ngx_event_t *wev; - size_t present, sent; - ngx_int_t rc; - ngx_chain_t *cl; - - wev = r->connection->write; - - if (r->connection->destroyed) { - return; - } - - ctx = ngx_http_get_module_ctx(r, ngx_mpegts_http_module); - s = ctx->session; - - if (wev->timedout) { - ngx_log_error(NGX_LOG_INFO, s->log, NGX_ETIMEDOUT, - "mpegts-http: write_handler| client timed out"); - r->connection->timedout = 1; - s->finalize_reason = NGX_LIVE_FLV_SEND_TIMEOUT; - if (r->header_sent) { - ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT); - } else { - r->error_page = 1; - ngx_http_finalize_request(r, NGX_HTTP_SERVICE_UNAVAILABLE); - } - - return; - } - - if (wev->timer_set) { - ngx_del_timer(wev); - } - - if (ngx_rtmp_core_main_conf->fast_reload && (ngx_exiting || ngx_terminate)) { - r->error_page = 1; - ngx_http_finalize_request(r, NGX_HTTP_SERVICE_UNAVAILABLE); - return; - } - - if (ngx_rtmp_prepare_merge_frame(s) == NGX_ERROR) { - ngx_http_finalize_request(r, NGX_ERROR); - return; - } - - if (s->out_chain) { - rc = ngx_mpegts_http_send_header(r); - if (rc == NGX_ERROR || rc > NGX_OK) { - s->finalize_reason = NGX_LIVE_FLV_SEND_ERR; - ngx_http_finalize_request(r, rc); - return; - } - } - - while (s->out_chain) { - present = r->connection->sent; - - if (r->connection->buffered) { - rc = ngx_http_output_filter(r, NULL); - } else { - rc = ngx_http_output_filter(r, s->out_chain); - } - - sent = r->connection->sent - present; - - ngx_rtmp_update_bandwidth(&ngx_rtmp_bw_out, sent); - - if (rc == NGX_AGAIN) { - ngx_add_timer(wev, s->timeout); - if (ngx_handle_write_event(wev, 0) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno, - "mpegts-http: write_handler| write event failed"); - ngx_http_finalize_request(r, NGX_ERROR); - } - return; - } - - if (rc == NGX_ERROR) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno, - "mpegts-http: write_handler| send error"); - s->finalize_reason = NGX_LIVE_FLV_SEND_ERR; - ngx_http_finalize_request(r, NGX_ERROR); - return; - } - - /* NGX_OK */ - for (cl = s->out_chain; cl;) { - s->out_chain = cl->next; - ngx_free_chain(s->pool, cl); - cl = s->out_chain; - } - - if (ngx_rtmp_prepare_merge_frame(s) == NGX_ERROR) { - ngx_http_finalize_request(r, NGX_ERROR); - return; - } - } - - if (wev->active) { - ngx_del_event(wev, NGX_WRITE_EVENT, 0); - } -} - - -static void -ngx_mpegts_http_parse_url(ngx_http_request_t *r, ngx_str_t *app, - ngx_str_t *name) -{ - u_char *p, *end, *pos; - - p = r->uri.data + 1; /* skip '/' */ - end = r->uri.data + r->uri.len; - app->data = p; - - pos = (u_char *) ngx_strnstr(p, ".ts", end - p); - if (pos) { - end = pos; - } - - p = (u_char *) ngx_strnstr(p, "/", end - p); - while (p) { - name->data = p; - p = (u_char *) ngx_strnstr(p + 1, "/", end - p); - } - - if (name->data == NULL) { - return; - } - - app->len = name->data - app->data; - - ++name->data; - name->len = end - name->data; -} - -static ngx_int_t -ngx_mpegts_http_parse(ngx_http_request_t *r, ngx_rtmp_session_t *s, - ngx_rtmp_play_t *v) -{ - ngx_mpegts_http_loc_conf_t *hflcf; - ngx_str_t app, stream; - size_t tcurl_len; - u_char *p; - - hflcf = ngx_http_get_module_loc_conf(r, ngx_mpegts_http_module); - - ngx_memzero(&app, sizeof(ngx_str_t)); - ngx_memzero(&stream, sizeof(ngx_str_t)); - - ngx_mpegts_http_parse_url(r, &app, &stream); - - if (app.len == 0 || stream.len == 0 || stream.len > NGX_RTMP_MAX_NAME) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "mpegts-http: http_parse| url error: %V", &r->uri); - return NGX_HTTP_BAD_REQUEST; - } - - if (hflcf->app.len) { - app = hflcf->app; - } - - ngx_http_arg(r, (u_char *) "app", 3, &app); - - s->app = app; - - if (ngx_http_arg(r, (u_char *) "flashver", 8, &s->flashver) != NGX_OK) { - s->flashver = hflcf->flashver; - } - - /* tc_url */ -#if (NGX_HTTP_SSL) - if (r->connection->ssl) { - tcurl_len = sizeof("https://") - 1; - } else -#endif - { - tcurl_len = sizeof("http://") - 1; - } - tcurl_len += r->headers_in.server.len + 1 + app.len; - - s->tc_url.len = tcurl_len; - s->tc_url.data = ngx_pcalloc(r->pool, tcurl_len); - if (s->tc_url.data == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - p = s->tc_url.data; - -#if (NGX_HTTP_SSL) - if (r->connection->ssl) { - p = ngx_cpymem(p, "https://", sizeof("https://") - 1); - } else -#endif - { - p = ngx_cpymem(p, "http://", sizeof("http://") - 1); - } - - p = ngx_cpymem(p, r->headers_in.server.data, r->headers_in.server.len); - *p++ = '/'; - p = ngx_cpymem(p, app.data, app.len); - - /* page_url */ - if (r->headers_in.referer) { - s->page_url = r->headers_in.referer->value; - } else { - s->page_url = hflcf->page_url; - } - - s->acodecs = 0x0DF7; - s->vcodecs = 0xFC; - - ngx_memcpy(v->name, stream.data, stream.len); - - if (r->args.len) { - ngx_memcpy(v->args, r->args.data, - ngx_min(r->args.len, NGX_RTMP_MAX_ARGS)); - } - - ngx_rtmp_cmd_middleware_init(s); - - return NGX_OK; -} - -static void -ngx_mpegts_http_cleanup(void *data) -{ - ngx_http_request_t *r; - ngx_mpegts_http_ctx_t *ctx; - - r = data; - - ctx = ngx_http_get_module_ctx(r, ngx_mpegts_http_module); - - if (ctx == NULL) { - return; - } - - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "mpegts-http: cleanup| cleanup"); - - if (ctx->session) { - ctx->session->request = NULL; - - if (ctx->session->finalize_reason == 0) { - ctx->session->finalize_reason = r->connection->read->error? - NGX_LIVE_FLV_RECV_ERR : NGX_LIVE_NORMAL_CLOSE; - } - - ngx_rtmp_finalize_fake_session(ctx->session); - } -} - -static ngx_chain_t * -ngx_mpegts_http_prepare_out_chain(ngx_rtmp_session_t *s) -{ - ngx_mpegts_frame_t *frame; - ngx_chain_t *head, **ll, *cl; - - frame = NULL; - head = NULL; - - if (s->out_pos != s->out_last) { - frame = s->mpegts_out[s->out_pos]; - } - - /* no frame to send */ - if (frame == NULL) { - return NULL; - } - - ll = &head; - - for (cl = frame->chain; cl; cl = cl->next) { - (*ll) = ngx_get_chainbuf(0, 0); - if (*ll == NULL) { - goto falied; - } - (*ll)->buf->pos = cl->buf->pos; - (*ll)->buf->last = cl->buf->last; - if (!(*ll)->next) { - (*ll)->buf->flush = 1; - } - - ll = &(*ll)->next; - } - - return head; - -falied: - ngx_put_chainbufs(head); - - ngx_rtmp_finalize_session(s); - return NULL; -} - -static ngx_int_t -ngx_mpegts_http_handler(ngx_http_request_t *r) -{ - ngx_mpegts_http_loc_conf_t *hflcf; - ngx_mpegts_http_ctx_t *ctx; - ngx_rtmp_session_t *s; - ngx_rtmp_play_t v; - ngx_int_t rc; - ngx_uint_t n; - ngx_rtmp_core_srv_conf_t *cscf; - ngx_rtmp_core_app_conf_t **cacfp; - ngx_http_cleanup_t *cln; - ngx_rtmp_core_main_conf_t *cmcf; - - ctx = ngx_pcalloc(r->pool, sizeof(ngx_mpegts_http_ctx_t)); - if (ctx == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - ngx_http_set_ctx(r, ctx, ngx_mpegts_http_module); - - /* cleanup handler */ - cln = ngx_http_cleanup_add(r, 0); - if (cln == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - cln->handler = ngx_mpegts_http_cleanup; - cln->data = r; - - hflcf = ngx_http_get_module_loc_conf(r, ngx_mpegts_http_module); - - /* create fake session */ - s = ngx_rtmp_create_session(hflcf->addr_conf); - if (s == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - ctx->session = s; - s->connection = r->connection; - ngx_rtmp_set_combined_log(s, r->connection->log->data, - r->connection->log->handler); - s->log->connection = r->connection->number; - s->number = r->connection->number; - s->remote_addr_text.data = ngx_pcalloc(s->pool, r->connection->addr_text.len); - s->remote_addr_text.len = r->connection->addr_text.len; - ngx_memcpy(s->remote_addr_text.data, - r->connection->addr_text.data, r->connection->addr_text.len); - - /* get host, app, stream name */ - ngx_memzero(&v, sizeof(ngx_rtmp_play_t)); - rc = ngx_mpegts_http_parse(r, s, &v); - if (rc != NGX_OK) { - return rc; - } - - if (ngx_rtmp_set_virtual_server(s, &s->domain)) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module); - - s->live_type = NGX_MPEGTS_LIVE; - s->live_server = ngx_live_create_server(&s->serverid); - s->request = r; - - v.silent = 1; - - cacfp = cscf->applications.elts; - for (n = 0; n < cscf->applications.nelts; ++n, ++cacfp) { - if ((*cacfp)->name.len == s->app.len && - ngx_strncmp((*cacfp)->name.data, s->app.data, s->app.len) == 0) - { - /* found app! */ - s->app_conf = (*cacfp)->app_conf; - break; - } - } - - if (s->app_conf == NULL) { - - if (cscf->default_app == NULL || cscf->default_app->app_conf == NULL) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "mpegts-http: http_handler| " - "application not found '%V'", &s->app); - return NGX_HTTP_NOT_FOUND; - } - - s->app_conf = cscf->default_app->app_conf; - } - - s->prepare_handler = ngx_mpegts_http_prepare_out_chain; - - s->stage = NGX_LIVE_PLAY; - s->ptime = ngx_current_msec; - - cmcf = ngx_rtmp_get_module_main_conf(s, ngx_rtmp_core_module); - s->variables = ngx_pcalloc(s->pool, cmcf->variables.nelts - * sizeof(ngx_http_variable_value_t)); - if (s->variables == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - if (ngx_rtmp_play_filter(s, &v) != NGX_OK) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - ngx_add_timer(r->connection->write, s->timeout); - - r->read_event_handler = ngx_http_test_reading; - r->write_event_handler = ngx_mpegts_http_write_handler; - - ++r->count; - - return NGX_DONE; -} - - -static void * -ngx_mpegts_http_create_loc_conf(ngx_conf_t *cf) -{ - ngx_mpegts_http_loc_conf_t *hflcf; - - hflcf = ngx_pcalloc(cf->pool, sizeof(ngx_mpegts_http_loc_conf_t)); - if (hflcf == NULL) { - return NULL; - } - - return hflcf; -} - -static char * -ngx_mpegts_http_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_mpegts_http_loc_conf_t *prev = parent; - ngx_mpegts_http_loc_conf_t *conf = child; - - ngx_conf_merge_str_value(conf->app, prev->app, ""); - ngx_conf_merge_str_value(conf->flashver, prev->flashver, ""); - ngx_conf_merge_str_value(conf->swf_url, prev->swf_url, ""); - ngx_conf_merge_str_value(conf->tc_url, prev->tc_url, ""); - ngx_conf_merge_str_value(conf->page_url, prev->page_url, ""); - - return NGX_CONF_OK; -} - -static char * -ngx_mpegts_http(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_core_loc_conf_t *clcf; - ngx_mpegts_http_loc_conf_t *hflcf; - ngx_str_t *value, v; - ngx_uint_t i; - - clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); - clcf->handler = ngx_mpegts_http_handler; - - hflcf = conf; - - value = cf->args->elts; - - hflcf->addr_conf = ngx_rtmp_find_related_addr_conf(cf->cycle, &value[1]); - if (hflcf->addr_conf == NULL) { - return NGX_CONF_ERROR; - } - - for (i = 2; i < cf->args->nelts; ++i) { - if (ngx_strncmp(value[i].data, "app=", 4) == 0) { - v.data = value[i].data + 4; - v.len = value[i].len - 4; - hflcf->app = v; - } else { - return NGX_CONF_ERROR; - } - } - - return NGX_CONF_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_live_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_live_module.c deleted file mode 100644 index 1bac711e59..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_live_module.c +++ /dev/null @@ -1,1891 +0,0 @@ - -/* - * Copyright (C) Pingo (cczjp89@gmail.com) - */ - -#include -#include -#include -#include "ngx_rtmp.h" -#include "ngx_rtmp_cmd_module.h" -#include "ngx_rtmp_live_module.h" -#include "ngx_rbuf.h" -#include "ngx_mpegts_live_module.h" -#include "ngx_mpegts_gop_module.h" -#include "ngx_rtmp_codec_module.h" - -ngx_mpegts_video_pt ngx_mpegts_video; -ngx_mpegts_audio_pt ngx_mpegts_audio; - -static ngx_rtmp_publish_pt next_publish; -static ngx_rtmp_play_pt next_play; -static ngx_rtmp_close_stream_pt next_close_stream; - -#define NGX_MPEGTS_BUF_SIZE 1316 -#define NGX_RTMP_MPEG_BUFSIZE 1024*1024 - -#define TS_AUDIO_TYPE_AAC 0 -#define TS_AUDIO_TYPE_MP3 1 - -#define TS_VIDEO_TYPE_H264 0 -#define TS_VIDEO_TYPE_H265 1 - -typedef struct ngx_mpegts_live_app_conf_s { - ngx_pool_t *pool; - size_t audio_buffer_size; - ngx_msec_t sync; - ngx_msec_t audio_delay; - size_t out_queue; - ngx_mpegts_live_ctx_t *players; - u_char packet_buffer[NGX_RTMP_MPEG_BUFSIZE]; -} ngx_mpegts_live_app_conf_t; - -typedef struct ngx_mpegts_live_avc_codec_s { - ngx_rtmp_frame_t *avc_header; - ngx_uint_t video_codec_id; - ngx_uint_t avc_nal_bytes; -} ngx_mpegts_live_avc_codec_t; - -typedef struct ngx_mpegts_live_aac_codec_s { - ngx_rtmp_frame_t *aac_header; - uint64_t sample_rate; -} ngx_mpegts_live_aac_codec_t; - -struct ngx_mpegts_live_ctx_s { - - ngx_mpegts_live_ctx_t *next; - ngx_rtmp_session_t *session; - ngx_live_stream_t *stream; - - /* mpegts-module config */ - size_t audio_buffer_size; - ngx_msec_t sync; - ngx_msec_t audio_delay; - size_t out_queue; - - /* pat pmt frame*/ - ngx_mpegts_frame_t *patpmt; - - /* video packet */ - ngx_mpegts_live_avc_codec_t *avc_codec; - ngx_uint_t video_cc; - - /* audio packet */ - ngx_mpegts_live_aac_codec_t *aac_codec; - ngx_uint_t audio_cc; - uint64_t aframe_pts; - ngx_uint_t aframe_num; - ngx_msec_t aframe_base; - ngx_buf_t *aframe; -}; - -/* 700 ms PCR delay */ -#define NGX_RTMP_MEGPTS_DELAY 63000 - -static void * -ngx_mpegts_live_create_app_conf(ngx_conf_t *cf); -static char * -ngx_mpegts_live_merge_app_conf(ngx_conf_t *cf, void *parent, void *child); -static ngx_int_t -ngx_mpegts_live_postconfiguration(ngx_conf_t *cf); - -static ngx_command_t ngx_mpegts_live_commands[] = { - - { ngx_string("mpegts_audio_buffer_size"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_mpegts_live_app_conf_t, audio_buffer_size), - NULL }, - - { ngx_string("mpegts_sync"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_mpegts_live_app_conf_t, sync), - NULL }, - - { ngx_string("mpegts_audio_delay"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_mpegts_live_app_conf_t, audio_delay), - NULL }, - - { ngx_string("mpegts_out_queue"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_mpegts_live_app_conf_t, out_queue), - NULL }, - - ngx_null_command -}; - - -static ngx_rtmp_module_t ngx_mpegts_live_ctx = { - NULL, /* preconfiguration */ - ngx_mpegts_live_postconfiguration, /* postconfiguration */ - NULL, /* create main configuration */ - NULL, /* init main configuration */ - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - ngx_mpegts_live_create_app_conf, /* create app configuration */ - ngx_mpegts_live_merge_app_conf /* merge app configuration */ -}; - - -ngx_module_t ngx_mpegts_live_module = { - NGX_MODULE_V1, - &ngx_mpegts_live_ctx, /* module context */ - ngx_mpegts_live_commands, /* module directives */ - NGX_RTMP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void * -ngx_mpegts_live_create_app_conf(ngx_conf_t *cf) -{ - ngx_mpegts_live_app_conf_t *macf; - - macf = ngx_pcalloc(cf->pool, sizeof(ngx_mpegts_live_app_conf_t)); - if (!macf) { - return NULL; - } - - macf->audio_buffer_size = NGX_CONF_UNSET; - macf->sync = NGX_CONF_UNSET_MSEC; - macf->audio_delay = NGX_CONF_UNSET_MSEC; - macf->out_queue = NGX_CONF_UNSET; - - return macf; -} - - -static char * -ngx_mpegts_live_merge_app_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_mpegts_live_app_conf_t *prev = parent; - ngx_mpegts_live_app_conf_t *conf = child; - - ngx_conf_merge_size_value(conf->audio_buffer_size, prev->audio_buffer_size, - NGX_RTMP_MPEG_BUFSIZE); - ngx_conf_merge_msec_value(conf->sync, prev->sync, 2); - ngx_conf_merge_msec_value(conf->audio_delay, prev->audio_delay, 300); - ngx_conf_merge_size_value(conf->out_queue, prev->out_queue, 4096); - conf->pool = ngx_create_pool(4096, &cf->cycle->new_log); - if (!conf->pool) { - return NGX_CONF_ERROR; - } - - return NGX_CONF_OK; -} - -static u_char * -ngx_mpegts_live_write_pcr(u_char *p, uint64_t pcr) -{ - *p++ = (u_char) (pcr >> 25); - *p++ = (u_char) (pcr >> 17); - *p++ = (u_char) (pcr >> 9); - *p++ = (u_char) (pcr >> 1); - *p++ = (u_char) (pcr << 7 | 0x7e); - *p++ = 0; - - return p; -} - -static u_char * -ngx_mpegts_live_write_pts(u_char *p, ngx_uint_t fb, uint64_t pts) -{ - ngx_uint_t val; - - val = fb << 4 | (((pts >> 30) & 0x07) << 1) | 1; - *p++ = (u_char) val; - - val = (((pts >> 15) & 0x7fff) << 1) | 1; - *p++ = (u_char) (val >> 8); - *p++ = (u_char) val; - - val = (((pts) & 0x7fff) << 1) | 1; - *p++ = (u_char) (val >> 8); - *p++ = (u_char) val; - - return p; -} - -ngx_int_t -ngx_mpegts_live_shared_append_chain(ngx_mpegts_frame_t *f, ngx_buf_t *b, - ngx_flag_t mandatory) -{ - ngx_uint_t pes_size, header_size, body_size, in_size, stuff_size, flags; - u_char *packet, *p, *base; - ngx_int_t first; - ngx_chain_t *cl, **ll; - uint64_t pcr; - - for (ll = &f->chain; (*ll) && (*ll)->next; ll = &(*ll)->next); - cl = *ll; - - if ((b == NULL || b->pos == b->last) && mandatory) { - *ll = ngx_get_chainbuf(NGX_MPEGTS_BUF_SIZE, 1); - (*ll)->buf->flush = 1; - return NGX_OK; - } - - first = 1; - - while (b->pos < b->last) { - if ((*ll) && (*ll)->buf->end - (*ll)->buf->last < 188) { - ll = &(*ll)->next; - cl = *ll; - } - - if (*ll == NULL) { - *ll = ngx_get_chainbuf(NGX_MPEGTS_BUF_SIZE, 1); - cl = *ll; - cl->buf->flush = 1; - } - - packet = cl->buf->last; - p = packet; - - f->cc++; - - *p++ = 0x47; - *p++ = (u_char) (f->pid >> 8); - - if (first) { - p[-1] |= 0x40; - } - - *p++ = (u_char) f->pid; - *p++ = 0x10 | (f->cc & 0x0f); /* payload */ - - if (first) { - - if (f->key) { - packet[3] |= 0x20; /* adaptation */ - - *p++ = 7; /* size */ - *p++ = 0x50; /* random access + PCR */ - if (f->dts < NGX_RTMP_MEGPTS_DELAY) { - pcr = 0; - } else { - pcr = f->dts; - } - p = ngx_mpegts_live_write_pcr(p, pcr); - } - - /* PES header */ - - *p++ = 0x00; - *p++ = 0x00; - *p++ = 0x01; - *p++ = (u_char) f->sid; - - header_size = 5; - flags = 0x80; /* PTS */ - - if (f->dts != f->pts) { - header_size += 5; - flags |= 0x40; /* DTS */ - } - - pes_size = (b->last - b->pos) + header_size + 3; - if (pes_size > 0xffff) { - pes_size = 0; - } - - *p++ = (u_char) (pes_size >> 8); - *p++ = (u_char) pes_size; - *p++ = 0x80; /* H222 */ - *p++ = (u_char) flags; - *p++ = (u_char) header_size; - - p = ngx_mpegts_live_write_pts(p, flags >> 6, f->pts + - NGX_RTMP_MEGPTS_DELAY); - - if (f->dts != f->pts) { - p = ngx_mpegts_live_write_pts(p, 1, f->dts + - NGX_RTMP_MEGPTS_DELAY); - } - - first = 0; - } - - body_size = (ngx_uint_t) (packet + 188 - p); - in_size = (ngx_uint_t) (b->last - b->pos); - - if (body_size <= in_size) { - ngx_memcpy(p, b->pos, body_size); - b->pos += body_size; - - } else { - stuff_size = (body_size - in_size); - - if (packet[3] & 0x20) { - - /* has adaptation */ - - base = &packet[5] + packet[4]; - p = ngx_movemem(base + stuff_size, base, p - base); - ngx_memset(base, 0xff, stuff_size); - packet[4] += (u_char) stuff_size; - - } else { - - /* no adaptation */ - - packet[3] |= 0x20; - p = ngx_movemem(&packet[4] + stuff_size, &packet[4], - p - &packet[4]); - - packet[4] = (u_char) (stuff_size - 1); - if (stuff_size >= 2) { - packet[5] = 0; - ngx_memset(&packet[6], 0xff, stuff_size - 2); - } - } - - ngx_memcpy(p, b->pos, in_size); - b->pos = b->last; - } - - cl->buf->last += 188; - f->length += 188; - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_mpegts_live_copy(ngx_rtmp_session_t *s, void *dst, u_char **src, size_t n, - ngx_chain_t **in) -{ - u_char *last; - size_t pn; - - if (*in == NULL) { - return NGX_ERROR; - } - - for ( ;; ) { - last = (*in)->buf->last; - - if ((size_t)(last - *src) >= n) { - if (dst) { - ngx_memcpy(dst, *src, n); - } - - *src += n; - - while (*in && *src == (*in)->buf->last) { - *in = (*in)->next; - if (*in) { - *src = (*in)->buf->pos; - } - } - - return NGX_OK; - } - - pn = last - *src; - - if (dst) { - ngx_memcpy(dst, *src, pn); - dst = (u_char *)dst + pn; - } - - n -= pn; - *in = (*in)->next; - - if (*in == NULL) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "rtmp-mpegts: mpegts_copy| failed to read %uz byte(s)", n); - return NGX_ERROR; - } - - *src = (*in)->buf->pos; - } -} - - -static ngx_int_t -ngx_mpegts_live_append_aud(ngx_rtmp_session_t *s, ngx_buf_t *out) -{ - static u_char aud_nal[] = { 0x00, 0x00, 0x00, 0x01, 0x09, 0xf0 }; - - if (out->last + sizeof(aud_nal) > out->end) { - return NGX_ERROR; - } - - out->last = ngx_cpymem(out->last, aud_nal, sizeof(aud_nal)); - - return NGX_OK; -} - - -static ngx_int_t -ngx_mpegts_live_append_sps_pps(ngx_rtmp_session_t *s, ngx_buf_t *out) -{ - u_char *p; - ngx_chain_t *in; - ngx_mpegts_live_ctx_t *ctx; - int8_t nnals; - uint16_t len, rlen; - ngx_int_t n; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_mpegts_live_module); - - if (ctx == NULL || ctx->avc_codec == NULL) { - return NGX_ERROR; - } - - in = ctx->avc_codec->avc_header->chain; - if (in == NULL) { - return NGX_ERROR; - } - - p = in->buf->pos; - - /* - * Skip bytes: - * - flv fmt - * - H264 CONF/PICT (0x00) - * - 0 - * - 0 - * - 0 - * - version - * - profile - * - compatibility - * - level - * - nal bytes - */ - - if (ngx_mpegts_live_copy(s, NULL, &p, 10, &in) != NGX_OK) { - return NGX_ERROR; - } - - /* number of SPS NALs */ - if (ngx_mpegts_live_copy(s, &nnals, &p, 1, &in) != NGX_OK) { - return NGX_ERROR; - } - - nnals &= 0x1f; /* 5lsb */ - - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "rtmp-mpegts: append_sps_pps| SPS number: %uz", nnals); - - /* SPS */ - for (n = 0; ; ++n) { - for (; nnals; --nnals) { - - /* NAL length */ - if (ngx_mpegts_live_copy(s, &rlen, &p, 2, &in) != NGX_OK) { - return NGX_ERROR; - } - - ngx_rtmp_rmemcpy(&len, &rlen, 2); - - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "rtmp-mpegts: append_sps_pps| header NAL length: %uz", (size_t) len); - - /* AnnexB prefix */ - if (out->end - out->last < 4) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "rtmp-mpegts: append_sps_pps| too small buffer for header NAL size"); - return NGX_ERROR; - } - - *out->last++ = 0; - *out->last++ = 0; - *out->last++ = 0; - *out->last++ = 1; - - /* NAL body */ - if (out->end - out->last < len) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "rtmp-mpegts: append_sps_pps| too small buffer for header NAL"); - return NGX_ERROR; - } - - if (ngx_mpegts_live_copy(s, out->last, &p, len, &in) != NGX_OK) { - return NGX_ERROR; - } - - out->last += len; - } - - if (n == 1) { - break; - } - - /* number of PPS NALs */ - if (ngx_mpegts_live_copy(s, &nnals, &p, 1, &in) != NGX_OK) { - return NGX_ERROR; - } - - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "rtmp-mpegts: append_sps_pps| PPS number: %uz", nnals); - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_mpegts_live_init_aac_codec(ngx_rtmp_session_t *s) -{ - ngx_mpegts_live_ctx_t *ctx; - ngx_rtmp_codec_ctx_t *codec_ctx; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_mpegts_live_module); - codec_ctx = ngx_rtmp_get_module_ctx(s->live_stream->publish_ctx->session, ngx_rtmp_codec_module); - - if (ctx->aac_codec) { - return NGX_OK; - } - - if (codec_ctx == NULL || codec_ctx->aac_header == NULL) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "rtmp-mpegts: aac_codec| codec ctx %p, aac_header is null", codec_ctx); - return NGX_AGAIN; - } - - ctx->aac_codec = ngx_pcalloc(s->pool, sizeof(ngx_mpegts_live_aac_codec_t)); - if (ctx->aac_codec == NULL) { - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "rtmp-mpegts: aac_codec| alloc mpegts aac_codec failed"); - return NGX_ERROR; - } - - ctx->aac_codec->aac_header = ngx_rtmp_shared_alloc_frame(1024, - codec_ctx->aac_header->chain, 0); - - ctx->aac_codec->sample_rate = codec_ctx->sample_rate; - - return NGX_OK; -} - - -static ngx_int_t -ngx_mpegts_live_init_avc_codec(ngx_rtmp_session_t *s) -{ - ngx_mpegts_live_ctx_t *ctx; - ngx_rtmp_codec_ctx_t *codec_ctx; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_mpegts_live_module); - codec_ctx = ngx_rtmp_get_module_ctx(s->live_stream->publish_ctx->session, ngx_rtmp_codec_module); - - if (ctx->avc_codec) { - return NGX_OK; - } - - if (codec_ctx == NULL || codec_ctx->avc_header == NULL) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "rtmp-mpegts: avc_codec| codec ctx %p, avc_header is null", codec_ctx); - return NGX_AGAIN; - } - - ctx->avc_codec = ngx_pcalloc(s->pool, sizeof(ngx_mpegts_live_avc_codec_t)); - if (ctx->avc_codec == NULL) { - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "rtmp-mpegts: avc_codec| alloc mpegts avc_codec failed"); - return NGX_ERROR; - } - - ctx->avc_codec->video_codec_id = codec_ctx->video_codec_id; - ctx->avc_codec->avc_nal_bytes = codec_ctx->avc_nal_bytes; - ctx->avc_codec->avc_header = ngx_rtmp_shared_alloc_frame(1024, - codec_ctx->avc_header->chain, 0); - - return NGX_OK; -} - -/* -static void -ngx_mpegts_live_append_out_chain(ngx_chain_t **header, ngx_mpegts_frame_t *frame) -{ - ngx_chain_t **ll; - ngx_chain_t *tail; - - ngx_rtmp_shared_acquire_frame(frame); - tail = frame->chain; - - for (ll = header; *ll; ll = &((*ll)->next)) { - (*ll)->buf->flush = 1; - } - - *ll = tail; - - for (; *ll; ll = &((*ll)->next)) { - (*ll)->buf->flush = 1; - if (!(*ll)->next) { - (*ll)->buf->last_in_chain = 1; - } - } -} -*/ - -static ngx_int_t -ngx_mpegts_live_flush_audio(ngx_rtmp_session_t *s) -{ - ngx_mpegts_live_ctx_t *ctx; - ngx_mpegts_frame_t *frame; - ngx_int_t rc; - ngx_buf_t *b; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_mpegts_live_module); - - if (ctx == NULL) { - return NGX_OK; - } - - b = ctx->aframe; - - if (b == NULL || b->pos == b->last) { - return NGX_OK; - } - - frame = ngx_rtmp_shared_alloc_mpegts_frame(NULL, 0); - - frame->dts = ctx->aframe_pts; - frame->pts = ctx->aframe_pts; - frame->cc = ctx->audio_cc; - frame->pid = 0x101; - frame->sid = 0xc0; - frame->type = NGX_MPEGTS_MSG_AUDIO; - - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "rtmp-mpegts: flush_audio| pts=%uL", frame->pts); - - rc = ngx_mpegts_live_shared_append_chain(frame, b, 1); - - if (rc != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "rtmp-mpegts: flush_audio| flush failed"); - } else { - ctx->audio_cc = frame->cc; - ngx_mpegts_live_audio_filter(s, frame); - } - - ngx_rtmp_shared_free_mpegts_frame(frame); - - b->pos = b->last = b->start; - - return rc; -} - - -static ngx_int_t -ngx_mpegts_live_append_hevc_vps_sps_pps(ngx_rtmp_session_t *s, ngx_buf_t *out) -{ - ngx_mpegts_live_ctx_t *ctx; - u_char *p; - ngx_chain_t *in; - ngx_uint_t rnal_unit_len, nal_unit_len, i, j, - num_arrays, nal_unit_type, rnum_nalus, - num_nalus; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_mpegts_live_module); - - if (ctx == NULL || ctx->avc_codec == NULL) { - return NGX_ERROR; - } - - in = ctx->avc_codec->avc_header->chain; - if (in == NULL) { - return NGX_ERROR; - } - - p = in->buf->pos; - /* 6 bytes - * FrameType 4 bits - * CodecID 4 bits - * AVCPacketType 1 byte - * CompositionTime 3 bytes - * HEVCDecoderConfigurationRecord - * configurationVersion 1 byte - */ - - /* 20 bytes - * HEVCDecoderConfigurationRecord - * general_profile_space 2 bits - * general_tier_flag 1 bit - * general_profile_idc 5 bits - * general_profile_compatibility_flags 4 bytes - * general_constraint_indicator_flags 6 bytes - * general_level_idc 1 byte - * min_spatial_segmentation_idc 4 bits reserved + 12 bits - * parallelismType 6 bits reserved + 2 bits - * chroma_format_idc 6 bits reserved + 2 bits - * bit_depth_luma_minus8 5 bits reserved + 3 bits - * bit_depth_chroma_minus8 5 bits reserved + 3 bits - * avgFrameRate 2 bytes - */ - - /* 1 bytes - * HEVCDecoderConfigurationRecord - * constantFrameRate 2 bits - * numTemporalLayers 3 bits - * temporalIdNested 1 bit - * lengthSizeMinusOne 2 bits - */ - - if (ngx_mpegts_live_copy(s, NULL, &p, 27, &in) != NGX_OK) { - return NGX_ERROR; - } - - /* 1 byte - * HEVCDecoderConfigurationRecord - * numOfArrays 1 byte - */ - num_arrays = 0; - if (ngx_mpegts_live_copy(s, &num_arrays, &p, 1, &in) != NGX_OK) { - return NGX_ERROR; - } - - for (i = 0; i < num_arrays; ++i) { - /* - * array_completeness 1 bit - * reserved 1 bit - * NAL_unit_type 6 bits - * numNalus 2 bytes - */ - if (ngx_mpegts_live_copy(s, &nal_unit_type, &p, 1, &in) != NGX_OK) { - return NGX_ERROR; - } - nal_unit_type &= 0x3f; - - if (ngx_mpegts_live_copy(s, &rnum_nalus, &p, 2, &in) != NGX_OK) { - return NGX_ERROR; - } - num_nalus = 0; - ngx_rtmp_rmemcpy(&num_nalus, &rnum_nalus, 2); - - for (j = 0; j < num_nalus; ++j) { - /* - * nalUnitLength 2 bytes - */ - if (ngx_mpegts_live_copy(s, &rnal_unit_len, &p, 2, &in) != NGX_OK) { - return NGX_ERROR; - } - nal_unit_len = 0; - ngx_rtmp_rmemcpy(&nal_unit_len, &rnal_unit_len, 2); - if (out->end - out->last < 4) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls: too small buffer for header NAL size"); - return NGX_ERROR; - } - - *out->last++ = 0; - *out->last++ = 0; - *out->last++ = 0; - *out->last++ = 1; - - if (out->end - out->last < (ngx_int_t)nal_unit_len) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls: too small buffer for header NAL"); - return NGX_ERROR; - } - - if (ngx_mpegts_live_copy(s, out->last, &p, nal_unit_len, &in) != NGX_OK) { - return NGX_ERROR; - } - - out->last += nal_unit_len; - } - } - return NGX_OK; -} - - -/* set h265 aud first, now is null*/ -static ngx_int_t -ngx_mpegts_live_append_hevc_aud(ngx_rtmp_session_t *s, ngx_buf_t *out) -{ - static u_char aud_nal[] = { 0x00, 0x00, 0x00, 0x01, 0x46, 0x01, 0x50 }; - - if (out->last + sizeof(aud_nal) > out->end) { - return NGX_ERROR; - } - - out->last = ngx_cpymem(out->last, aud_nal, sizeof(aud_nal)); - - return NGX_OK; -} - - -static ngx_int_t -ngx_mpegts_live_h265_handler(ngx_rtmp_session_t *s, ngx_rtmp_frame_t *f) -{ - ngx_mpegts_live_ctx_t *ctx; - ngx_mpegts_live_app_conf_t *macf; - u_char *p; - uint8_t fmt, ftype, htype, nal_type, src_nal_type; - uint32_t len, rlen; - ngx_buf_t out; - uint32_t cts; - ngx_mpegts_frame_t *frame; - ngx_uint_t nal_bytes; - ngx_int_t aud_sent, sps_pps_sent; - u_char *buffer; - ngx_rtmp_header_t *h; - ngx_chain_t *in; - ngx_int_t rc; - ngx_rtmp_core_app_conf_t *cacf; - - cacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_core_module); - - h = &f->hdr; - in = f->chain; - - macf = ngx_rtmp_get_module_app_conf(s, ngx_mpegts_live_module); - buffer = macf->packet_buffer; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_mpegts_live_module); - if (ctx == NULL || h->mlen < 1) { - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "rtmp-mpegts: h265_handler| " - "resource error, mpegts_ctx=%p, h->mlen=%d", - ctx, h->mlen); - return NGX_OK; - } - - if (ctx->avc_codec == NULL) { - rc = ngx_mpegts_live_init_avc_codec(s); - if (rc == NGX_ERROR) { - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "rtmp-mpegts: h265_handler| init avc_codec failed"); - return NGX_OK; - } else if (rc == NGX_AGAIN) { - return NGX_OK; - } - } - - /* H265 is supported */ - if (ctx->avc_codec->video_codec_id != cacf->hevc_codec) - { - return NGX_OK; - } - - p = in->buf->pos; - if (ngx_mpegts_live_copy(s, &fmt, &p, 1, &in) != NGX_OK) { - return NGX_ERROR; - } - - /* 1: keyframe (IDR) - * 2: inter frame - * 3: disposable inter frame */ - - ftype = (fmt & 0xf0) >> 4; // 0x17/0x27/... - - /* H264 HDR/PICT */ - - if (ngx_mpegts_live_copy(s, &htype, &p, 1, &in) != NGX_OK) { - return NGX_ERROR; - } - - /* proceed only with PICT */ - - if (htype != 1) { /*0:AVC sequence header,1:AVC NALU 2:AVC end of sequence*/ - return NGX_OK; - } - - /* 3 bytes: decoder delay */ - - if (ngx_mpegts_live_copy(s, &cts, &p, 3, &in) != NGX_OK) { - return NGX_ERROR; - } - /* convert big end to little end */ - cts = ((cts & 0x00FF0000) >> 16) | ((cts & 0x000000FF) << 16) | - (cts & 0x0000FF00); - - ngx_memzero(&out, sizeof(out)); - - out.start = buffer; - out.end = buffer + NGX_RTMP_MPEG_BUFSIZE; - out.pos = out.start; - out.last = out.pos; - - nal_bytes = ctx->avc_codec->avc_nal_bytes; - aud_sent = 0; - sps_pps_sent = 0; - ngx_int_t vps_copy = 0; - ngx_int_t sps_copy = 0; - ngx_int_t pps_copy = 0; - - while (in) { - if (ngx_mpegts_live_copy(s, &rlen, &p, nal_bytes, &in) != NGX_OK) { - return NGX_OK; - } - - len = 0; - ngx_rtmp_rmemcpy(&len, &rlen, nal_bytes); - - if (len == 0) { - continue; - } - - if (ngx_mpegts_live_copy(s, &src_nal_type, &p, 1, &in) != NGX_OK) { - return NGX_OK; - } - - nal_type = (src_nal_type & 0x7e) >> 1; - - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "rtmp-mpegts: h265_handler| h265 NAL type=%ui, len=%uD", - (ngx_uint_t) nal_type, len); - - /* h264 format of rtmp_flv contains NAL header Prefix "00 00 00 01" */ - if (0 == nal_type) { - u_char nal_header[4] = {0}; - if (ngx_mpegts_live_copy(s, nal_header, &p, 3, &in) != NGX_OK) { - return NGX_OK; - } - - if (0 != ngx_strcmp(nal_header, "\0\0\1")) { - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "mpegts module: h265 hander| " - "is not h265 NAL header [00 00 00 01]"); - p -= 3; - goto NAL_TRAIL_N; - return NGX_OK; - } - - if (ngx_mpegts_live_copy(s, &src_nal_type, &p, 1, &in) != NGX_OK) { - return NGX_OK; - } - - nal_type = (src_nal_type & 0x7e) >> 1; - if (0 == nal_type) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "mpegts module: h265 hander| h265 NAL type reparse error"); - return NGX_OK; - } - -#define HEVC_NAL_AUD_LENGTH 0 - if (out.end - out.last < (ngx_int_t) (len + HEVC_NAL_AUD_LENGTH)) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "mpegts module: h265 hander| not enough buffer for NAL"); - return NGX_OK; - } -#if 1 - if (ngx_mpegts_live_append_hevc_aud(s, &out) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "mpegts module: h265 hander| error appending AUD NAL"); - } -#endif - /* back to 00 00 01 nal_type*/ - p = p - 4; - if (ngx_mpegts_live_copy(s, out.last, &p, len - 1, &in) != NGX_OK) { - return NGX_ERROR; - } - - out.last += (len - 1); - break; - } - -NAL_TRAIL_N: - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->log, 0, - "mpegts module: h265 hander| h265 NAL type=%ui, len=%uD", - (ngx_uint_t) nal_type, len); - - /* - * NAL_VPS 32 - * NAL_SPS 33 - * NAL_PPS 34 - * NAL_AUD 35 - * NAL_SEI_PREFIX 39 - * NAL_SEI_SUFFIX 40 - */ - if ((nal_type >= 32 && nal_type <= 35) - || nal_type == 39 || nal_type == 40) - { - if (out.end - out.last < (5 + len -1)) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls: not enough buffer for AnnexB prefix"); - return NGX_OK; - } - if (32 == nal_type) { - ++vps_copy; - if(!aud_sent){ - if (ngx_mpegts_live_append_hevc_aud(s, &out) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls: error appending AUD NAL"); - } - aud_sent = 1; - } - } else if (33 == nal_type) { - ++sps_copy; - } else if (34 == nal_type) { - ++pps_copy; - } else if (35 == nal_type) { - aud_sent = 1; - } - - *out.last++ = 0; - *out.last++ = 0; - *out.last++ = 0; - *out.last++ = 1; - *out.last++ = src_nal_type; - if (ngx_mpegts_live_copy(s, out.last, &p, len - 1, &in) != NGX_OK) { - return NGX_ERROR; - } - out.last += (len - 1); - continue; - } - - if (vps_copy > 0 && sps_copy > 0 && pps_copy > 0) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "mpegts vps_copy %i, sps_copy %i, pps_copy %i\n", - vps_copy, sps_copy, pps_copy); - sps_pps_sent = 1; - } - - if (!aud_sent) { - if (35 == nal_type) { - aud_sent = 1; - } else if (!sps_pps_sent) { - if (ngx_mpegts_live_append_hevc_vps_sps_pps(s, &out) != NGX_OK) - { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls: error appending AUD NAL"); - } - aud_sent = 1; - } - } - - if (IS_IRAP(nal_type)) { - if (!sps_pps_sent) { - if (ngx_mpegts_live_append_hevc_vps_sps_pps(s, &out) != NGX_OK) - { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls: error appenging VPS/SPS/PPS NALs"); - } - sps_pps_sent = 1; - } - } - - /* AnnexB prefix */ - if (out.end - out.last < 5) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls: not enough buffer for AnnexB prefix"); - return NGX_OK; - } - - /* first AnnexB prefix is long (4 bytes) */ - - if (out.last == out.pos) { - *out.last++ = 0; - } - - *out.last++ = 0; - *out.last++ = 0; - *out.last++ = 1; - *out.last++ = src_nal_type; - - /* NAL body */ - if (out.end - out.last < (ngx_int_t) len) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls: not enough buffer for NAL"); - return NGX_OK; - } - - if (ngx_mpegts_live_copy(s, out.last, &p, len - 1, &in) != NGX_OK) { - return NGX_ERROR; - } - - out.last += (len - 1); - } - - frame = ngx_rtmp_shared_alloc_mpegts_frame(NULL, 0); - if (frame == NULL) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "rtmp-mpegts: h265_handler| " - "memory error, alloc mpegts frame failed"); - return NGX_ERROR; - } - - /* continuity counter */ - frame->cc = ctx->video_cc; - frame->dts = (uint64_t) h->timestamp * 90; - /* pts = dts + composition time */ - frame->pts = frame->dts + cts * 90; - /* program id */ - frame->pid = 0x100; - /* stream id, video range from 0xe0 to 0xef */ - frame->sid = 0xe0; - frame->key = (ftype == 1); - frame->type = NGX_MPEGTS_MSG_VIDEO; - - /* - * start new fragment if - * - we have video key frame AND - * - we have audio buffered or have no audio at all or stream is closed - */ - if (ctx->aframe && ctx->aframe->last > ctx->aframe->pos && - ctx->aframe_pts + (uint64_t) ctx->audio_delay * 90 < frame->dts) - { - ngx_mpegts_live_flush_audio(s); - } - - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "rtmp-mpegts: h265_handler| video pts=%uL, dts=%uL", - frame->pts, frame->dts); - - if (ngx_mpegts_live_shared_append_chain(frame, &out, 1) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "rtmp-mpegts: h264_handler| video frame failed"); - } else { - ctx->video_cc = frame->cc; - ngx_mpegts_live_video_filter(s, frame); - } - - ngx_rtmp_shared_free_mpegts_frame(frame); - - return NGX_OK; -} - - -static ngx_int_t -ngx_mpegts_live_h264_handler(ngx_rtmp_session_t *s, ngx_rtmp_frame_t *f) -{ - ngx_rtmp_header_t *h; - ngx_chain_t *in; - ngx_mpegts_live_ctx_t *ctx; - u_char *p; - uint8_t fmt, ftype, htype, nal_type, src_nal_type; - uint32_t len, rlen; - ngx_buf_t out; - uint32_t cts; - ngx_mpegts_frame_t *frame; - ngx_uint_t nal_bytes; - ngx_int_t aud_sent, sps_pps_sent; - u_char *buffer; - ngx_mpegts_live_app_conf_t *macf; - ngx_int_t rc; - - h = &f->hdr; - in = f->chain; - - macf = ngx_rtmp_get_module_app_conf(s, ngx_mpegts_live_module); - buffer = macf->packet_buffer; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_mpegts_live_module); - if (ctx == NULL || h->mlen < 1) { - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "mpegts-mux: h264_handler| " - "resource error, mpegts_ctx=%p, h->mlen=%d", - ctx, h->mlen); - return NGX_OK; - } - - if (ctx->avc_codec == NULL) { - rc = ngx_mpegts_live_init_avc_codec(s); - if (rc == NGX_ERROR) { - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "mpegts-mux: h264_handler| init avc_codec failed"); - return NGX_OK; - } else if (rc == NGX_AGAIN) { - return NGX_OK; - } - } - - /* H264 is supported */ - if (ctx->avc_codec->video_codec_id != NGX_RTMP_VIDEO_H264) { - return NGX_OK; - } - - p = in->buf->pos; - if (ngx_mpegts_live_copy(s, &fmt, &p, 1, &in) != NGX_OK) { - return NGX_ERROR; - } - - /* 1: keyframe (IDR) - * 2: inter frame - * 3: disposable inter frame */ - - ftype = (fmt & 0xf0) >> 4; - - /* H264 HDR/PICT */ - - if (ngx_mpegts_live_copy(s, &htype, &p, 1, &in) != NGX_OK) { - return NGX_ERROR; - } - - /* proceed only with PICT */ - - if (htype != 1) { - return NGX_OK; - } - - /* 3 bytes: decoder delay */ - - if (ngx_mpegts_live_copy(s, &cts, &p, 3, &in) != NGX_OK) { - return NGX_ERROR; - } - - cts = ((cts & 0x00FF0000) >> 16) | ((cts & 0x000000FF) << 16) | - (cts & 0x0000FF00); - - ngx_memzero(&out, sizeof(out)); - - out.start = buffer; - out.end = buffer + NGX_RTMP_MPEG_BUFSIZE; - out.pos = out.start; - out.last = out.pos; - - nal_bytes = ctx->avc_codec->avc_nal_bytes; - aud_sent = 0; - sps_pps_sent = 0; - - while (in) { - if (ngx_mpegts_live_copy(s, &rlen, &p, nal_bytes, &in) != NGX_OK) { - return NGX_OK; - } - - len = 0; - ngx_rtmp_rmemcpy(&len, &rlen, nal_bytes); - - if (len == 0) { - continue; - } - - if (ngx_mpegts_live_copy(s, &src_nal_type, &p, 1, &in) != NGX_OK) { - return NGX_OK; - } - - nal_type = src_nal_type & 0x1f; - - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "mpegts-mux: h264_handler| h264 NAL type=%ui, len=%uD", - (ngx_uint_t) nal_type, len); - - if (nal_type >= 7 && nal_type <= 9) { - if (ngx_mpegts_live_copy(s, NULL, &p, len - 1, &in) != NGX_OK) { - return NGX_ERROR; - } - continue; - } - - if (!aud_sent) { - switch (nal_type) { - case 1: - case 5: - case 6: - if (ngx_mpegts_live_append_aud(s, &out) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "mpegts-mux: h264_handler| error appending AUD NAL"); - } - aud_sent = 1; - break; - - case 9: - aud_sent = 1; - break; - } - } - - switch (nal_type) { - case 1: - sps_pps_sent = 0; - break; - case 5: - if (sps_pps_sent) { - break; - } - if (ngx_mpegts_live_append_sps_pps(s, &out) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "mpegts-mux: h264_handler| error appenging SPS/PPS NALs"); - } - sps_pps_sent = 1; - break; - } - - /* AnnexB prefix */ - - if (out.end - out.last < 5) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "mpegts-mux: h264_handler| not enough buffer for AnnexB prefix"); - return NGX_OK; - } - - /* first AnnexB prefix is long (4 bytes) */ - - if (out.last == out.pos) { - *out.last++ = 0; - } - - *out.last++ = 0; - *out.last++ = 0; - *out.last++ = 1; - *out.last++ = src_nal_type; - - /* NAL body */ - - if (out.end - out.last < (ngx_int_t) len) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "mpegts-mux: h264_handler| not enough buffer for NAL"); - return NGX_OK; - } - - if (ngx_mpegts_live_copy(s, out.last, &p, len - 1, &in) != NGX_OK) { - return NGX_ERROR; - } - - out.last += (len - 1); - } - - frame = ngx_rtmp_shared_alloc_mpegts_frame(NULL, 0); - if (frame == NULL) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "mpegts-mux: h264_handler| " - "memory error, alloc mpegts frame failed"); - return NGX_ERROR; - } - - frame->cc = ctx->video_cc; - frame->dts = (uint64_t) h->timestamp * 90; - frame->pts = frame->dts + (cts * 90); - frame->pid = 0x100; - frame->sid = 0xe0; - frame->key = (ftype == 1); - frame->type = NGX_MPEGTS_MSG_VIDEO; - - if (ctx->aframe && ctx->aframe->last > ctx->aframe->pos && - ctx->aframe_pts + (uint64_t) ctx->audio_delay * 90 < frame->dts) - { - ngx_mpegts_live_flush_audio(s); - } - - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "mpegts-mux: h264_handler| video pts=%uL, dts=%uL", - frame->pts/90, frame->dts/90); - - if (ngx_mpegts_live_shared_append_chain(frame, &out, 1) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "mpegts-mux: h264_handler| video frame failed"); - } else { - ctx->video_cc = frame->cc; - ngx_mpegts_live_video_filter(s, frame); - } - - ngx_rtmp_shared_free_mpegts_frame(frame); - - return NGX_OK; -} - - -static ngx_int_t -ngx_mpegts_live_parse_aac_header(ngx_rtmp_session_t *s, ngx_uint_t *objtype, - ngx_uint_t *srindex, ngx_uint_t *chconf) -{ - ngx_mpegts_live_ctx_t *ctx; - ngx_chain_t *cl; - u_char *p, b0, b1; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_mpegts_live_module); - - cl = ctx->aac_codec->aac_header->chain; - - p = cl->buf->pos; - - if (ngx_mpegts_live_copy(s, NULL, &p, 2, &cl) != NGX_OK) { - return NGX_ERROR; - } - - if (ngx_mpegts_live_copy(s, &b0, &p, 1, &cl) != NGX_OK) { - return NGX_ERROR; - } - - if (ngx_mpegts_live_copy(s, &b1, &p, 1, &cl) != NGX_OK) { - return NGX_ERROR; - } - - *objtype = b0 >> 3; - if (*objtype == 0 || *objtype == 0x1f) { - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "rtmp-mpegts: parse_aac_header| " - "unsupported adts object type:%ui", *objtype); - return NGX_ERROR; - } - - if (*objtype > 4) { - - /* - * Mark all extended profiles as LC - * to make Android as happy as possible. - */ - - *objtype = 2; - } - - *srindex = ((b0 << 1) & 0x0f) | ((b1 & 0x80) >> 7); - if (*srindex == 0x0f) { - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "rtmp-mpegts: parse_aac_header| " - "unsupported adts sample rate:%ui", *srindex); - return NGX_ERROR; - } - - *chconf = (b1 >> 3) & 0x0f; - - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "rtmp-mpegts: parse_aac_header| " - "aac object_type:%ui, sample_rate_index:%ui, " - "channel_config:%ui", *objtype, *srindex, *chconf); - - return NGX_OK; -} - - -static ngx_int_t -ngx_mpegts_live_aac_handler(ngx_rtmp_session_t *s, ngx_rtmp_frame_t *f) -{ - ngx_rtmp_header_t *h; - ngx_chain_t *in; - ngx_mpegts_live_ctx_t *ctx; - uint64_t pts, est_pts; - int64_t dpts; - size_t bsize; - ngx_buf_t *b; - u_char *p; - ngx_uint_t objtype, srindex, chconf, size; - ngx_int_t rc; - - h = &f->hdr; - in = f->chain; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_mpegts_live_module); - - if (ctx == NULL || h->mlen < 2) { - return NGX_OK; - } - - if (ctx->aac_codec == NULL) { - rc = ngx_mpegts_live_init_aac_codec(s); - if (rc == NGX_ERROR) { - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "rtmp-mpegts: aac_handler| init aac_codec failed"); - return NGX_OK; - } else if(rc == NGX_AGAIN) { - return NGX_OK; - } - } - - if (ngx_rtmp_is_codec_header(in)) { - return NGX_OK; - } - - b = ctx->aframe; - - if (b == NULL) { - - b = ngx_pcalloc(s->pool, sizeof(ngx_buf_t)); - if (b == NULL) { - return NGX_ERROR; - } - - ctx->aframe = b; - - b->start = ngx_palloc(s->pool, ctx->audio_buffer_size); - if (b->start == NULL) { - return NGX_ERROR; - } - - b->end = b->start + ctx->audio_buffer_size; - b->pos = b->last = b->start; - } - - size = h->mlen - 2 + 7; - pts = (uint64_t) h->timestamp * 90; - - if (b->start + size > b->end) { - return NGX_OK; - } - - if (b->last > b->pos && - ctx->aframe_pts + (uint64_t) ctx->audio_delay * 90 / 2 < pts) - { - ngx_mpegts_live_flush_audio(s); - } - - if (b->last + size > b->end) { - ngx_mpegts_live_flush_audio(s); - } - - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "rtmp-mpegts: aac_handler| audio pts=%uL", pts); - - if (b->last + 7 > b->end) { - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "rtmp-mpegts: aac_handler| not enough buffer for audio header"); - return NGX_OK; - } - - p = b->last; - b->last += 5; - - /* copy payload */ - - for (; in && b->last < b->end; in = in->next) { - - bsize = in->buf->last - in->buf->pos; - if (b->last + bsize > b->end) { - bsize = b->end - b->last; - } - - b->last = ngx_cpymem(b->last, in->buf->pos, bsize); - } - - /* make up ADTS header */ - - if (ngx_mpegts_live_parse_aac_header(s, &objtype, &srindex, &chconf) - != NGX_OK) - { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "rtmp-mpegts: aac_handler| aac header error"); - return NGX_OK; - } - - /* we have 5 free bytes + 2 bytes of RTMP frame header */ - - p[0] = 0xff; - p[1] = 0xf1; - p[2] = (u_char) (((objtype - 1) << 6) | (srindex << 2) | - ((chconf & 0x04) >> 2)); - p[3] = (u_char) (((chconf & 0x03) << 6) | ((size >> 11) & 0x03)); - p[4] = (u_char) (size >> 3); - p[5] = (u_char) ((size << 5) | 0x1f); - p[6] = 0xfc; - - if (p != b->start) { - ctx->aframe_num++; - return NGX_OK; - } - - ctx->aframe_pts = pts; - - if (!ctx->sync || ctx->aac_codec->sample_rate == 0) { - return NGX_OK; - } - - /* align audio frames */ - - /* TODO: We assume here AAC frame size is 1024 - * Need to handle AAC frames with frame size of 960 */ - - est_pts = ctx->aframe_base + ctx->aframe_num * 90000 * 1024 / - ctx->aac_codec->sample_rate; - dpts = (int64_t) (est_pts - pts); - - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "rtmp-mpegts: aac_handler| audio sync dpts=%L (%.5fs)", - dpts, dpts / 90000.); - - if (dpts <= (int64_t) ctx->sync * 90 && - dpts >= (int64_t) ctx->sync * -90) - { - ctx->aframe_num++; - ctx->aframe_pts = est_pts; - return NGX_OK; - } - - ctx->aframe_base = pts; - ctx->aframe_num = 1; - - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "rtmp-mpegts: aac_handler| audio sync gap dpts=%L (%.5fs)", - dpts, dpts / 90000.); - - return NGX_OK; -} - -static ngx_int_t -ngx_mpegts_live_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - ngx_mpegts_live_ctx_t *ctx; - ngx_rtmp_frame_t frame; - ngx_rtmp_codec_ctx_t *codec_ctx; - ngx_rtmp_core_app_conf_t *cacf; - - cacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_core_module); - - codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - - ctx = ngx_rtmp_get_module_ctx(s, ngx_mpegts_live_module); - if (ctx == NULL || codec_ctx == NULL || codec_ctx->avc_header == NULL) { - return NGX_OK; - } - - /* Only H264 and H265 is supported */ - if (codec_ctx->video_codec_id != NGX_RTMP_VIDEO_H264 && - codec_ctx->video_codec_id != cacf->hevc_codec) - { - return NGX_OK; - } - - if (s->pause) { - return NGX_OK; - } - - ngx_memzero(&frame, sizeof(frame)); - - frame.hdr = *h; - frame.chain = in; - - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "mpegts-mux: av| pts[%uL] type [%d] key[%d]", - frame.hdr.timestamp, frame.hdr.type, frame.keyframe); - - switch (frame.hdr.type) { - case NGX_RTMP_MSG_AUDIO: - // only aac, for now - ngx_mpegts_live_aac_handler(s, &frame); - break; - - case NGX_RTMP_MSG_VIDEO: - /* h264 h265 */ - if (codec_ctx->video_codec_id == NGX_RTMP_VIDEO_H264) { - ngx_mpegts_live_h264_handler(s, &frame); - } else if (codec_ctx->video_codec_id == cacf->hevc_codec) { - ngx_mpegts_live_h265_handler(s, &frame); - } - break; - - default: - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "rtmp-mpegts: av| unknown frame-type=%d", frame.hdr.type); - break; - } - - return NGX_OK; -} - -ngx_int_t -ngx_mpegts_live_video_filter(ngx_rtmp_session_t *s, ngx_mpegts_frame_t *frame) -{ - return ngx_mpegts_video(s, frame); -} - -ngx_int_t -ngx_mpegts_live_audio_filter(ngx_rtmp_session_t *s, ngx_mpegts_frame_t *frame) -{ - return ngx_mpegts_audio(s, frame); -} - -static ngx_int_t -ngx_mpegts_live_avframe(ngx_rtmp_session_t *s, ngx_mpegts_frame_t *frame) -{ - ngx_mpegts_live_ctx_t *cctx; - ngx_rtmp_session_t *ss; - - for (cctx = s->live_stream->mpegts_ctx; cctx; cctx = cctx->next) { - ss = cctx->session; - ngx_mpegts_gop_send(s, ss); - - if (!s->connection->write->active) { - ngx_post_event(s->connection->write, &ngx_posted_events); - } - } - - return NGX_OK; -} - -static ngx_int_t -ngx_mpegts_live_ctx_init(ngx_rtmp_session_t *s) -{ - ngx_mpegts_live_app_conf_t *macf; - ngx_mpegts_live_ctx_t *ctx; - - macf = ngx_rtmp_get_module_app_conf(s, ngx_mpegts_live_module); - if (macf == NULL) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "rtmp-mpegts: ctx_init| get app conf failed"); - return NGX_ERROR; - } - - ctx = ngx_rtmp_get_module_ctx(s, ngx_mpegts_live_module); - if (ctx == NULL) { - ctx = ngx_pcalloc(s->pool, sizeof(ngx_mpegts_live_ctx_t)); - if (ctx == NULL) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "rtmp-mpegts: ctx_init| pcalloc ctx failed"); - return NGX_ERROR; - } - - ngx_rtmp_set_ctx(s, ctx, ngx_mpegts_live_module); - ctx->session = s; - } - - ctx->sync = macf->sync; - ctx->audio_buffer_size = macf->audio_buffer_size; - ctx->audio_delay = macf->audio_delay; - ctx->out_queue = macf->out_queue; - - return NGX_OK; -} - -static ngx_int_t -ngx_mpegts_live_join(ngx_rtmp_session_t *s, u_char *name, unsigned publisher) -{ - ngx_mpegts_live_ctx_t *ctx; - ngx_live_stream_t *st; - ngx_rtmp_live_app_conf_t *lacf; - - lacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_live_module); - if (lacf == NULL) { - return NGX_ERROR; - } - - ctx = ngx_rtmp_get_module_ctx(s, ngx_mpegts_live_module); - if (ctx && ctx->stream) { - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->log, 0, - "mpegts-live: join| already joined"); - return NGX_ERROR; - } - - if (ctx == NULL) { - ctx = ngx_pcalloc(s->pool, sizeof(ngx_mpegts_live_ctx_t)); - if (ctx == NULL) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "mpegts-live: join| pcalloc ctx failed"); - return NGX_ERROR; - } - - ngx_rtmp_set_ctx(s, ctx, ngx_mpegts_live_module); - } - - ngx_memzero(ctx, sizeof(*ctx)); - - ctx->session = s; - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "mpegts-live: join| join '%s'", name); - - st = s->live_stream; - - if (!(publisher || st->publish_ctx || lacf->idle_streams)) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "mpegts-live: join| stream not found"); - - s->status = 404; - - return NGX_ERROR; - } - - ctx->stream = st; - ctx->next = st->mpegts_ctx; - - st->mpegts_ctx = ctx; - - return NGX_OK; -} - -static ngx_int_t -ngx_mpegts_live_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v) -{ - ngx_mpegts_live_ctx_init(s); - - return next_publish(s, v); -} - -static ngx_int_t -ngx_mpegts_live_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v) -{ - if (s->live_type != NGX_MPEGTS_LIVE) { - goto next; - } - - if (ngx_mpegts_live_join(s, v->name, 0) == NGX_ERROR) { - return NGX_ERROR; - } - -next: - return next_play(s, v); -} - -static ngx_int_t -ngx_mpegts_live_close_stream(ngx_rtmp_session_t *s, ngx_rtmp_close_stream_t *v) -{ - ngx_mpegts_live_ctx_t *ctx, **cctx; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_mpegts_live_module); - if (ctx == NULL) { - goto next; - } - - if (ctx->stream == NULL) { - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->log, 0, - "mpegts-live: close_stream| not joined"); - goto next; - } - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "mpegts-live: close_stream| leave '%s'", ctx->stream->name); - - for (cctx = &ctx->stream->mpegts_ctx; *cctx; cctx = &(*cctx)->next) { - if (*cctx == ctx) { - *cctx = ctx->next; - break; - } - } - - if (ctx->stream->mpegts_ctx) { - ctx->stream = NULL; - goto next; - } - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "mpegts-live: close_stream| delete empty stream '%s'", - ctx->stream->name); - - ctx->stream = NULL; - -next: - return next_close_stream(s, v); -} - -static ngx_int_t -ngx_mpegts_live_postconfiguration(ngx_conf_t *cf) -{ - ngx_rtmp_core_main_conf_t *cmcf; - ngx_rtmp_handler_pt *h; - - cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module); - - /* register raw event handlers */ - - h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_AUDIO]); - *h = ngx_mpegts_live_av; - - h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_VIDEO]); - *h = ngx_mpegts_live_av; - - next_publish = ngx_rtmp_publish; - ngx_rtmp_publish = ngx_mpegts_live_publish; - - next_play = ngx_rtmp_play; - ngx_rtmp_play = ngx_mpegts_live_play; - - next_close_stream = ngx_rtmp_close_stream; - ngx_rtmp_close_stream = ngx_mpegts_live_close_stream; - - ngx_mpegts_video = ngx_mpegts_live_avframe; - ngx_mpegts_audio = ngx_mpegts_live_avframe; - - return NGX_OK; -} - diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_live_module.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_live_module.h deleted file mode 100644 index 11c27d480c..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_live_module.h +++ /dev/null @@ -1,29 +0,0 @@ - -/* - * Copyright (C) Pingo (cczjp89@gmail.com) - */ - -#ifndef _NGX_RTMP_MPEGTS_MODULE_H -#define _NGX_RTMP_MPEGTS_MODULE_H - -#include "ngx_rtmp.h" - -typedef ngx_int_t (*ngx_mpegts_video_pt)(ngx_rtmp_session_t *s, - ngx_mpegts_frame_t *frame); -typedef ngx_int_t (*ngx_mpegts_audio_pt)(ngx_rtmp_session_t *s, - ngx_mpegts_frame_t *frame); - -extern ngx_mpegts_video_pt ngx_mpegts_video; -extern ngx_mpegts_audio_pt ngx_mpegts_audio; - -ngx_int_t -ngx_rtmp_mpegts_gen_pmt(ngx_int_t vcodec, ngx_int_t acodec, - ngx_log_t *log, u_char *pmt); -ngx_int_t -ngx_mpegts_live_video_filter(ngx_rtmp_session_t *s, ngx_mpegts_frame_t *frame); -ngx_int_t -ngx_mpegts_live_audio_filter(ngx_rtmp_session_t *s, ngx_mpegts_frame_t *frame); - -extern u_char ngx_rtmp_mpegts_pat[]; - -#endif diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live.c deleted file mode 100644 index 713f14a92b..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live.c +++ /dev/null @@ -1,449 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include "ngx_live.h" - - -static void *ngx_live_create_conf(ngx_cycle_t *cf); -static char *ngx_live_init_conf(ngx_cycle_t *cycle, void *conf); - - -static ngx_command_t ngx_live_commands[] = { - - { ngx_string("stream_buckets"), - NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - 0, - offsetof(ngx_live_conf_t, stream_buckets), - NULL }, - - { ngx_string("server_buckets"), - NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - 0, - offsetof(ngx_live_conf_t, server_buckets), - NULL }, - - ngx_null_command -}; - - -static ngx_core_module_t ngx_live_module_ctx = { - ngx_string("live"), - ngx_live_create_conf, /* create conf */ - ngx_live_init_conf /* init conf */ -}; - - -ngx_module_t ngx_live_module = { - NGX_MODULE_V1, - &ngx_live_module_ctx, /* module context */ - ngx_live_commands, /* module directives */ - NGX_CORE_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void * -ngx_live_create_conf(ngx_cycle_t *cycle) -{ - ngx_live_conf_t *lcf; - - lcf = ngx_pcalloc(cycle->pool, sizeof(ngx_live_conf_t)); - if (lcf == NULL) { - return NULL; - } - - lcf->stream_buckets = NGX_CONF_UNSET_SIZE; - lcf->server_buckets = NGX_CONF_UNSET_SIZE; - - return lcf; -} - -static char * -ngx_live_init_conf(ngx_cycle_t *cycle, void *conf) -{ - ngx_live_conf_t *lcf = conf; - - lcf->pool = ngx_create_pool(4096, cycle->log); - if (lcf->pool == NULL) { - return NGX_CONF_ERROR; - } - - ngx_conf_init_size_value(lcf->stream_buckets, 10007); - ngx_conf_init_size_value(lcf->server_buckets, 1031); - - lcf->servers = ngx_pcalloc(lcf->pool, - sizeof(ngx_live_server_t *) * lcf->server_buckets); - if (lcf->servers == NULL) { - return NGX_CONF_ERROR; - } - - return NGX_CONF_OK; -} - - -static ngx_live_server_t ** -ngx_live_find_server(ngx_str_t *serverid) -{ - ngx_live_conf_t *lcf; - ngx_live_server_t **psrv; - - lcf = (ngx_live_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_live_module); - - psrv = &lcf->servers[ngx_hash_key(serverid->data, serverid->len) - % lcf->server_buckets]; - for (; *psrv; psrv = &(*psrv)->next) { - if (ngx_strlen((*psrv)->serverid) == serverid->len && - ngx_memcmp((*psrv)->serverid, serverid->data, serverid->len) == 0) - { - break; - } - } - - return psrv; -} - -static ngx_live_server_t * -ngx_live_get_server(ngx_str_t *serverid) -{ - ngx_live_conf_t *lcf; - ngx_live_server_t *srv; - - if (serverid->len > NGX_LIVE_SERVERID_LEN - 1) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, - "serverid too long: %ui", serverid->len); - return NULL; - } - - lcf = (ngx_live_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_live_module); - - srv = lcf->free_server; - if (srv == NULL) { - srv = ngx_pcalloc(lcf->pool, sizeof(ngx_live_server_t)); - if (srv == NULL) { - return NULL; - } - - srv->streams = ngx_pcalloc(lcf->pool, - sizeof(ngx_live_stream_t *) * lcf->stream_buckets); - if (srv->streams == NULL) { - return NULL; - } - - ++lcf->alloc_server_count; - } else { - lcf->free_server = srv->next; - --lcf->free_server_count; - } - - *ngx_cpymem(srv->serverid, serverid->data, serverid->len) = 0; - srv->deleted = 0; - srv->n_stream = 0; - - return srv; -} - -static void -ngx_live_put_server(ngx_live_server_t *server) -{ - ngx_live_conf_t *lcf; - - lcf = (ngx_live_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_live_module); - - server->next = lcf->free_server; - lcf->free_server = server; - ++lcf->free_server_count; -} - -static ngx_live_stream_t ** -ngx_live_find_stream(ngx_live_server_t *server, ngx_str_t *stream) -{ - ngx_live_conf_t *lcf; - ngx_live_stream_t **pst; - - lcf = (ngx_live_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_live_module); - - pst = &server->streams[ngx_hash_key(stream->data, stream->len) - % lcf->stream_buckets]; - for (; *pst; pst = &(*pst)->next) { - if (ngx_strlen((*pst)->name) == stream->len && - ngx_memcmp((*pst)->name, stream->data, stream->len) == 0) - { - break; - } - } - - return pst; -} - -static ngx_live_stream_t * -ngx_live_get_stream(ngx_str_t *stream) -{ - ngx_live_conf_t *lcf; - ngx_live_stream_t *st; - - if (stream->len > NGX_LIVE_STREAM_LEN - 1) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, - "stream too long: %ui", stream->len); - return NULL; - } - - lcf = (ngx_live_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_live_module); - - st = lcf->free_stream; - if (st == NULL) { - st = ngx_pcalloc(lcf->pool, sizeof(ngx_live_stream_t)); - ++lcf->alloc_stream_count; - } else { - lcf->free_stream = st->next; - --lcf->free_stream_count; - ngx_memzero(st, sizeof(ngx_live_stream_t)); - } - - *ngx_cpymem(st->name, stream->data, stream->len) = 0; - st->pslot = -1; - st->epoch = ngx_current_msec; - ngx_map_init(&st->pubctx, ngx_map_hash_int, ngx_cmp_int); - - return st; -} - -static void -ngx_live_put_stream(ngx_live_stream_t *st) -{ - ngx_live_conf_t *lcf; - - lcf = (ngx_live_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_live_module); - - st->next = lcf->free_stream; - lcf->free_stream = st; - ++lcf->free_stream_count; -} - -ngx_live_server_t * -ngx_live_create_server(ngx_str_t *serverid) -{ - ngx_live_server_t **psrv; - - psrv = ngx_live_find_server(serverid); - if (*psrv) { - (*psrv)->deleted = 0; - return *psrv; - } - - *psrv = ngx_live_get_server(serverid); - - return *psrv; -} - -ngx_live_server_t * -ngx_live_fetch_server(ngx_str_t *serverid) -{ - ngx_live_server_t **psrv; - - psrv = ngx_live_find_server(serverid); - - return *psrv; -} - -void -ngx_live_delete_server(ngx_str_t *serverid) -{ - ngx_live_server_t **psrv, *srv; - - psrv = ngx_live_find_server(serverid); - if (*psrv == NULL) { - return; - } - - if ((*psrv)->n_stream != 0) { - (*psrv)->deleted = 1; - } - - if ((*psrv)->n_stream == 0) { - srv = *psrv; - *psrv = srv->next; - ngx_live_put_server(srv); - } -} - -ngx_live_stream_t * -ngx_live_create_stream(ngx_str_t *serverid, ngx_str_t *stream) -{ - ngx_live_server_t **psrv; - ngx_live_stream_t **pst; - - psrv = ngx_live_find_server(serverid); - if (*psrv == NULL) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, - "server %V does not exist when create stream", serverid); - return NULL; - } - - pst = ngx_live_find_stream(*psrv, stream); - - if (*pst) { - return *pst; - } - - *pst = ngx_live_get_stream(stream); - ++(*psrv)->n_stream; - - return *pst; -} - -ngx_live_stream_t * -ngx_live_fetch_stream(ngx_str_t *serverid, ngx_str_t *stream) -{ - ngx_live_server_t **psrv; - ngx_live_stream_t **pst; - - psrv = ngx_live_find_server(serverid); - if (*psrv == NULL) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, - "server %V does not exist when fetch stream", serverid); - return NULL; - } - - pst = ngx_live_find_stream(*psrv, stream); - - return *pst; -} - -void -ngx_live_delete_stream(ngx_str_t *serverid, ngx_str_t *stream) -{ - ngx_live_server_t **psrv; - ngx_live_stream_t **pst, *st; - - psrv = ngx_live_find_server(serverid); - if (*psrv == NULL) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, - "server %V does not exist when delete stream", serverid); - return; - } - - pst = ngx_live_find_stream(*psrv, stream); - - if (*pst == NULL) { - return; - } - - st = *pst; - - *pst = st->next; - ngx_live_put_stream(st); - --(*psrv)->n_stream; - - if ((*psrv)->deleted && (*psrv)->n_stream == 0) { - ngx_live_delete_server(serverid); - } -} - -void -ngx_live_create_ctx(ngx_rtmp_session_t *s, unsigned publishing) -{ - ngx_rtmp_core_ctx_t *ctx, **pctx; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_core_module); - if (ctx == NULL) { - ctx = ngx_pcalloc(s->pool, sizeof(ngx_rtmp_core_ctx_t)); - if (ctx == NULL) { - return; - } - - ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_core_module); - } - - ctx->publishing = publishing; - ctx->session = s; - if (publishing) { - pctx = &s->live_stream->publish_ctx; - } else { - pctx = &s->live_stream->play_ctx; - } - - ctx->next = (*pctx); - *pctx = ctx; -} - -void -ngx_live_delete_ctx(ngx_rtmp_session_t *s) -{ - ngx_rtmp_core_ctx_t *ctx, **pctx; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_core_module); - if (ctx == NULL) { - return; - } - - if (ctx->publishing) { - pctx = &s->live_stream->publish_ctx; - } else { - pctx = &s->live_stream->play_ctx; - } - - for (/* void */; *pctx; pctx = &(*pctx)->next) { - if (*pctx == ctx) { - *pctx = ctx->next; - return; - } - } -} - - -ngx_chain_t * -ngx_live_state(ngx_http_request_t *r) -{ - ngx_live_conf_t *lcf; - ngx_chain_t *cl; - ngx_buf_t *b; - size_t len; - - lcf = (ngx_live_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_live_module); - - - len = sizeof("##########ngx live state##########\n") - 1 - + sizeof("ngx_live nalloc server: \n") - 1 + NGX_OFF_T_LEN - + sizeof("ngx_live nfree server: \n") - 1 + NGX_OFF_T_LEN - + sizeof("ngx_live nalloc stream: \n") - 1 + NGX_OFF_T_LEN - + sizeof("ngx_live nfree stream: \n") - 1 + NGX_OFF_T_LEN; - - cl = ngx_alloc_chain_link(r->pool); - if (cl == NULL) { - return NULL; - } - cl->next = NULL; - - b = ngx_create_temp_buf(r->pool, len); - if (b == NULL) { - return NULL; - } - cl->buf = b; - - b->last = ngx_snprintf(b->last, len, - "##########ngx live state##########\n" - "ngx_live nalloc server: %ui\nngx_live nfree server: %ui\n" - "ngx_live nalloc stream: %ui\nngx_live nfree stream: %ui\n", - lcf->alloc_server_count, lcf->free_server_count, - lcf->alloc_stream_count, lcf->free_stream_count); - - return cl; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live.h deleted file mode 100644 index 8fad1693c7..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#ifndef _NGX_LIVE_H_INCLUDED_ -#define _NGX_LIVE_H_INCLUDED_ - - -#include "ngx_rtmp.h" - - -typedef struct { - size_t stream_buckets; - size_t server_buckets; - - ngx_live_server_t **servers; - - ngx_live_server_t *free_server; - ngx_live_stream_t *free_stream; - - ngx_uint_t alloc_server_count; - ngx_uint_t free_server_count; - - ngx_uint_t alloc_stream_count; - ngx_uint_t free_stream_count; - - ngx_pool_t *pool; -} ngx_live_conf_t; - - -extern ngx_module_t ngx_live_module; - - -/* - * paras: - * r: http request to query status of rbuf - */ -ngx_chain_t *ngx_live_state(ngx_http_request_t *r); - - -#endif diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_record.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_record.c deleted file mode 100644 index 3ff27e2020..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_record.c +++ /dev/null @@ -1,1307 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include -#include -#include "ngx_rtmp.h" -#include "ngx_rtmp_cmd_module.h" -#include "ngx_rtmp_codec_module.h" -#include "ngx_live_record.h" - - -ngx_live_record_start_pt ngx_live_record_start; -ngx_live_record_update_pt ngx_live_record_update; -ngx_live_record_done_pt ngx_live_record_done; - -static ngx_live_record_start_pt next_record_start; -static ngx_live_record_update_pt next_record_update; -static ngx_live_record_done_pt next_record_done; - -static ngx_rtmp_publish_pt next_publish; -static ngx_rtmp_close_stream_pt next_close_stream; - - -static ngx_int_t ngx_live_record_postconfiguration(ngx_conf_t *cf); -static void * ngx_live_record_create_app_conf(ngx_conf_t *cf); -static char * ngx_live_record_merge_app_conf(ngx_conf_t *cf, - void *parent, void *child); - - -#define NGX_LIVE_RECORD_BUFSIZE (10*1024*1024) - - -typedef struct { - ngx_flag_t record; - ngx_str_t path; - ngx_msec_t interval; - - ngx_msec_t min_fraglen; - ngx_msec_t max_fraglen; - - size_t buffer; -} ngx_live_record_app_conf_t; - - -static ngx_command_t ngx_live_record_commands[] = { - - { ngx_string("live_record"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_live_record_app_conf_t, record), - NULL }, - - { ngx_string("live_record_path"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_live_record_app_conf_t, path), - NULL }, - - { ngx_string("live_record_interval"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_live_record_app_conf_t, interval), - NULL }, - - { ngx_string("live_record_min_fragment"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_live_record_app_conf_t, min_fraglen), - NULL }, - - { ngx_string("live_record_max_fragment"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_live_record_app_conf_t, max_fraglen), - NULL }, - - { ngx_string("live_record_buffer"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_live_record_app_conf_t, buffer), - NULL }, - - ngx_null_command -}; - - -static ngx_rtmp_module_t ngx_live_record_module_ctx = { - NULL, /* preconfiguration */ - ngx_live_record_postconfiguration, /* postconfiguration */ - NULL, /* create main configuration */ - NULL, /* init main configuration */ - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - ngx_live_record_create_app_conf, /* create app configuration */ - ngx_live_record_merge_app_conf /* merge app configuration */ -}; - - -ngx_module_t ngx_live_record_module = { - NGX_MODULE_V1, - &ngx_live_record_module_ctx, /* module context */ - ngx_live_record_commands, /* module directives */ - NGX_RTMP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void * -ngx_live_record_create_app_conf(ngx_conf_t *cf) -{ - ngx_live_record_app_conf_t *racf; - - racf = ngx_pcalloc(cf->pool, sizeof(ngx_live_record_app_conf_t)); - - if (racf == NULL) { - return NULL; - } - - racf->record = NGX_CONF_UNSET; - racf->interval = NGX_CONF_UNSET_MSEC; - racf->min_fraglen = NGX_CONF_UNSET_MSEC; - racf->max_fraglen = NGX_CONF_UNSET_MSEC; - racf->buffer = NGX_CONF_UNSET_SIZE; - - return racf; -} - - -static char * -ngx_live_record_merge_app_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_err_t err; - ngx_live_record_app_conf_t *prev; - ngx_live_record_app_conf_t *conf; - u_char path[NGX_MAX_PATH + 1]; - - prev = parent; - conf = child; - - ngx_conf_merge_value(conf->record, prev->record, 0); - ngx_conf_merge_str_value(conf->path, prev->path, "record"); - ngx_conf_merge_msec_value(conf->interval, prev->interval, 10 * 60 * 1000); - ngx_conf_merge_msec_value(conf->min_fraglen, prev->min_fraglen, 8 * 1000); - ngx_conf_merge_msec_value(conf->max_fraglen, prev->max_fraglen, 12 * 1000); - ngx_conf_merge_msec_value(conf->buffer, prev->buffer, 1024 * 1024); - - if (conf->path.data[conf->path.len - 1] == '/') { - --conf->path.len; - } - - if (ngx_get_full_name(cf->pool, &cf->cycle->prefix, &conf->path) - != NGX_OK) - { - return NGX_CONF_ERROR; - } - - *ngx_snprintf(path, sizeof(path) - 1, "%V/", &conf->path) = 0; - err = ngx_create_full_path(path, 0755); - if (err) { - ngx_conf_log_error(NGX_LOG_CRIT, cf, err, - ngx_create_dir_n " \"%s\" failed", path); - return NGX_CONF_ERROR; - } - - return NGX_CONF_OK; -} - - -static ssize_t -ngx_live_record_flush(ngx_rtmp_mpegts_file_t *file) -{ - ssize_t rc; - - rc = ngx_write_fd(file->fd, file->wbuf.pos, - file->wbuf.last - file->wbuf.pos); - if (rc < 0) { - ngx_log_error(NGX_LOG_ERR, file->log, ngx_errno, - "flush record buf error"); - return rc; - } - - file->file_size += rc; - file->wbuf.last = file->wbuf.pos; - - return rc; -} - - -static ssize_t -ngx_live_record_write_buf(ngx_rtmp_mpegts_file_t *file, u_char *in, - size_t in_size) -{ - u_char *p, *end; - size_t len; - ssize_t rc, n; - - end = in + in_size; - n = 0; - - for (p = in; p != end; /* void */ ) { - len = ngx_min(file->wbuf.end - file->wbuf.last, end - p); - file->wbuf.last = ngx_cpymem(file->wbuf.last, p, len); - - p += len; - n += len; - - if (file->wbuf.last == file->wbuf.end) { - rc = ngx_live_record_flush(file); - if (rc < 0) { - return rc; - } - } - } - - return n; -} - - -static ngx_int_t -ngx_live_record_open_file(ngx_rtmp_session_t *s) -{ - ngx_live_record_app_conf_t *lracf; - ngx_live_record_ctx_t *ctx; - ngx_err_t err; - off_t file_size; - size_t len; - struct tm tm; - u_char *p; - ngx_rtmp_codec_ctx_t *codec_ctx; - - lracf = ngx_rtmp_get_module_app_conf(s, ngx_live_record_module); - - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_record_module); - codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - - len = lracf->path.len + sizeof("/") - 1 + s->serverid.len + sizeof("/") - 1 - + s->app.len + sizeof("/") - 1 + s->name.len + sizeof("/") - 1 - + sizeof("YYYYMMDD/") - 1 + s->name.len - + NGX_OFF_T_LEN + sizeof("_.ts") - 1; - - if (ctx->file.name.len == 0) { // first create in current session - ctx->file.name.data = ngx_pcalloc(s->pool, len + 1); - if (ctx->file.name.data == NULL) { - ngx_log_error(NGX_LOG_CRIT, s->log, 0, - "record: alloc for ts name failed"); - return NGX_ERROR; - } - } - - // fill file name - ngx_libc_localtime(ctx->last_time, &tm); - - p = ngx_snprintf(ctx->file.name.data, len, - "%V/%V/%V/%V/%04d%02d%02d/%V_%d.ts", - &lracf->path, &s->serverid, &s->app, &s->name, - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, - &s->name, ctx->last_time); - *p = 0; - ctx->file.name.len = p - ctx->file.name.data; - - // create dir - err = ngx_create_full_path(ctx->file.name.data, 0755); - if (err) { - ngx_log_error(NGX_LOG_ERR, s->log, err, - ngx_create_dir_n " \"%V\" failed", &ctx->index.name); - return NGX_ERROR; - } - - // open file - ctx->file.fd = ngx_open_file(ctx->file.name.data, NGX_FILE_RDWR, - NGX_FILE_CREATE_OR_OPEN, NGX_FILE_DEFAULT_ACCESS); - if (ctx->file.fd == NGX_INVALID_FILE) { - ngx_log_error(NGX_LOG_CRIT, s->log, ngx_errno, - "record: failed to open file '%V'", &ctx->file.name); - - return NGX_ERROR; - } - - file_size = lseek(ctx->file.fd, 0, SEEK_END); - if (file_size == (off_t) -1) { - ngx_log_error(NGX_LOG_CRIT, s->log, ngx_errno, - "record: %V seek failed", &ctx->file.name); - - return NGX_ERROR; - } - - if (ctx->ts.wbuf.start == NULL) { - ctx->ts.wbuf.start = ngx_pcalloc(s->pool, lracf->buffer); - if (ctx->ts.wbuf.start == NULL) { - ngx_log_error(NGX_LOG_CRIT, s->log, 0, - "record: alloc write buffer error"); - return NGX_ERROR; - } - - ctx->ts.wbuf.pos = ctx->ts.wbuf.last = ctx->ts.wbuf.start; - ctx->ts.wbuf.end = ctx->ts.wbuf.start + lracf->buffer; - - ctx->ts.whandle = ngx_live_record_write_buf; - } - ctx->ts.fd = ctx->file.fd; - ctx->ts.log = s->log; - ctx->ts.file_size = file_size; - ctx->ts.vcodec = codec_ctx->video_codec_id; - ctx->ts.acodec = codec_ctx->audio_codec_id; - - if (file_size == 0) { // empty file - if (ngx_rtmp_mpegts_write_header(&ctx->ts) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "record: error writing fragment header"); - - return NGX_ERROR; - } - ngx_live_record_flush(&ctx->ts); - } - - ctx->startsize = ctx->ts.file_size; - ctx->endsize = ctx->ts.file_size; - - return NGX_OK; -} - - -static void -ngx_live_record_write_index(ngx_rtmp_session_t *s, ngx_live_record_ctx_t *ctx, - ngx_msec_t curr_time) -{ - u_char *p, buf[1024]; - - ngx_live_record_flush(&ctx->ts); - - ctx->endsize = ctx->ts.file_size - 1; - - p = ngx_snprintf(buf, sizeof(buf) - 1, - "%V-%D.ts?startsize=%O&endsize=%O&starttime=%M&endtime=%M\n", - &s->name, ctx->last_time, ctx->startsize, ctx->endsize, - ctx->starttime, ctx->endtime); - *p = 0; - - if (ngx_write_fd(ctx->index.fd, buf, p - buf) < 0) { - ngx_log_error(NGX_LOG_ERR, s->log, ngx_errno, - "record, write %V failed: %s", &ctx->index.name, buf); - } - - ctx->startsize = ctx->ts.file_size; - ctx->starttime = curr_time; -} - - -static ngx_int_t -ngx_live_record_open_index(ngx_rtmp_session_t *s) -{ - ngx_live_record_app_conf_t *lracf; - ngx_live_record_ctx_t *ctx; - ngx_err_t err; - size_t len; - struct tm tm; - u_char *p; - - lracf = ngx_rtmp_get_module_app_conf(s, ngx_live_record_module); - - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_record_module); - - len = lracf->path.len + sizeof("/") - 1 + s->serverid.len + sizeof("/") - 1 - + s->app.len + sizeof("/") - 1 + s->name.len + sizeof("/") - 1 - + sizeof("index/YYYYMMDD/") - 1 + s->name.len - + NGX_OFF_T_LEN + sizeof("-.m3u8") - 1; - - if (ctx->index.name.len == 0) { // first create in current session - ctx->index.name.data = ngx_pcalloc(s->pool, len + 1); - if (ctx->index.name.data == NULL) { - ngx_log_error(NGX_LOG_CRIT, s->log, 0, - "record: alloc for index name failed"); - return NGX_ERROR; - } - } - - // fill index and file name - ngx_libc_localtime(ctx->last_time, &tm); - - p = ngx_snprintf(ctx->index.name.data, len, - "%V/%V/%V/%V/index/%04d%02d%02d/%V-%D.m3u8", - &lracf->path, &s->serverid, &s->app, &s->name, - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, - &s->name, ctx->last_time); - *p = 0; - ctx->index.name.len = p - ctx->index.name.data; - - // create dir - err = ngx_create_full_path(ctx->index.name.data, 0755); - if (err) { - ngx_log_error(NGX_LOG_ERR, s->log, err, - ngx_create_dir_n " \"%V\" failed", &ctx->index.name); - return NGX_ERROR; - } - - // open index - ctx->index.fd = ngx_open_file(ctx->index.name.data, NGX_FILE_RDWR, - NGX_FILE_CREATE_OR_OPEN, NGX_FILE_DEFAULT_ACCESS); - if (ctx->index.fd == NGX_INVALID_FILE) { - ngx_log_error(NGX_LOG_CRIT, s->log, ngx_errno, - "record: failed to open index '%V'", &ctx->index.name); - - return NGX_OK; - } - - if (lseek(ctx->index.fd, 0, SEEK_END) == (off_t) -1) { - ngx_log_error(NGX_LOG_CRIT, s->log, ngx_errno, - "record, %V seek failed", &ctx->index.name); - - return NGX_OK; - } - - return ngx_live_record_open_file(s); -} - - -static void -ngx_live_record_close_index(ngx_rtmp_session_t *s, ngx_live_record_ctx_t *ctx) -{ - if (ctx->index.fd == -1 || ctx->file.fd == -1) { - return; - } - - ngx_live_record_write_index(s, ctx, 0); - - ngx_close_file(ctx->file.fd); - ctx->file.fd = -1; - - ngx_close_file(ctx->index.fd); - ctx->index.fd = -1; -} - - -static void -ngx_live_record_reopen_index(ngx_rtmp_session_t *s, ngx_live_record_ctx_t *ctx, - ngx_msec_t curr_time, time_t last_time) -{ - // close old index and file - ngx_live_record_close_index(s, ctx); - - ngx_live_record_update(s); - - ctx->last_time = last_time; - - ctx->begintime = curr_time; - ctx->starttime = curr_time; - ctx->endtime = curr_time; - - // open new index and file - if (ngx_live_record_open_index(s) == NGX_ERROR) { - ctx->last_time = 0; - - if (ctx->index.fd != -1) { - ngx_close_file(ctx->index.fd); - } - - if (ctx->file.fd != -1) { - ngx_close_file(ctx->file.fd); - } - - return; - } -} - - -static ngx_int_t -ngx_live_record_copy(ngx_rtmp_session_t *s, void *dst, u_char **src, size_t n, - ngx_chain_t **in) -{ - u_char *last; - size_t pn; - - if (*in == NULL) { - return NGX_ERROR; - } - - for ( ;; ) { - last = (*in)->buf->last; - - if ((size_t)(last - *src) >= n) { - if (dst) { - ngx_memcpy(dst, *src, n); - } - - *src += n; - - while (*in && *src == (*in)->buf->last) { - *in = (*in)->next; - if (*in) { - *src = (*in)->buf->pos; - } - } - - return NGX_OK; - } - - pn = last - *src; - - if (dst) { - ngx_memcpy(dst, *src, pn); - dst = (u_char *)dst + pn; - } - - n -= pn; - *in = (*in)->next; - - if (*in == NULL) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "hls: failed to read %uz byte(s)", n); - return NGX_ERROR; - } - - *src = (*in)->buf->pos; - } -} - - -static ngx_int_t -ngx_live_record_parse_aac_header(ngx_rtmp_session_t *s, ngx_uint_t *objtype, - ngx_uint_t *srindex, ngx_uint_t *chconf) -{ - ngx_rtmp_codec_ctx_t *codec_ctx; - ngx_chain_t *cl; - u_char *p, b0, b1; - - codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - - cl = codec_ctx->aac_header->chain; - - p = cl->buf->pos; - - if (ngx_live_record_copy(s, NULL, &p, 2, &cl) != NGX_OK) { - return NGX_ERROR; - } - - if (ngx_live_record_copy(s, &b0, &p, 1, &cl) != NGX_OK) { - return NGX_ERROR; - } - - if (ngx_live_record_copy(s, &b1, &p, 1, &cl) != NGX_OK) { - return NGX_ERROR; - } - - *objtype = b0 >> 3; - if (*objtype == 0 || *objtype == 0x1f) { - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "record: unsupported adts object type:%ui", *objtype); - return NGX_ERROR; - } - - if (*objtype > 4) { - - /* - * Mark all extended profiles as LC - * to make Android as happy as possible. - */ - - *objtype = 2; - } - - *srindex = ((b0 << 1) & 0x0f) | ((b1 & 0x80) >> 7); - if (*srindex == 0x0f) { - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "record: unsupported adts sample rate:%ui", *srindex); - return NGX_ERROR; - } - - *chconf = (b1 >> 3) & 0x0f; - - ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->log, 0, - "record: aac object_type:%ui, sample_rate_index:%ui, " - "channel_config:%ui", *objtype, *srindex, *chconf); - - return NGX_OK; -} - - -static ngx_int_t -ngx_live_record_append_aud(ngx_rtmp_session_t *s, ngx_buf_t *out) -{ - static u_char aud_nal[] = { 0x00, 0x00, 0x00, 0x01, 0x09, 0xf0 }; - - if (out->last + sizeof(aud_nal) > out->end) { - return NGX_ERROR; - } - - out->last = ngx_cpymem(out->last, aud_nal, sizeof(aud_nal)); - - return NGX_OK; -} - - -static ngx_int_t -ngx_live_record_append_sps_pps(ngx_rtmp_session_t *s, ngx_buf_t *out) -{ - ngx_rtmp_codec_ctx_t *codec_ctx; - u_char *p; - ngx_chain_t *in; - int8_t nnals; - uint16_t len, rlen; - ngx_int_t n; - - codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - - if (codec_ctx == NULL || codec_ctx->avc_header == NULL) { - return NGX_OK; - } - - in = codec_ctx->avc_header->chain; - if (in == NULL) { - return NGX_ERROR; - } - - p = in->buf->pos; - - /* - * Skip bytes: - * - flv fmt - * - H264 CONF/PICT (0x00) - * - 0 - * - 0 - * - 0 - * - version - * - profile - * - compatibility - * - level - * - nal bytes - */ - - if (ngx_live_record_copy(s, NULL, &p, 10, &in) != NGX_OK) { - return NGX_ERROR; - } - - /* number of SPS NALs */ - if (ngx_live_record_copy(s, &nnals, &p, 1, &in) != NGX_OK) { - return NGX_ERROR; - } - - nnals &= 0x1f; /* 5lsb */ - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "record: SPS number: %uz", nnals); - - /* SPS */ - for (n = 0; ; ++n) { - for (; nnals; --nnals) { - - /* NAL length */ - if (ngx_live_record_copy(s, &rlen, &p, 2, &in) != NGX_OK) { - return NGX_ERROR; - } - - ngx_rtmp_rmemcpy(&len, &rlen, 2); - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "record: header NAL length: %uz", (size_t) len); - - /* AnnexB prefix */ - if (out->end - out->last < 4) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "record: too small buffer for header NAL size"); - return NGX_ERROR; - } - - *out->last++ = 0; - *out->last++ = 0; - *out->last++ = 0; - *out->last++ = 1; - - /* NAL body */ - if (out->end - out->last < len) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "record: too small buffer for header NAL"); - return NGX_ERROR; - } - - if (ngx_live_record_copy(s, out->last, &p, len, &in) != NGX_OK) { - return NGX_ERROR; - } - - out->last += len; - } - - if (n == 1) { - break; - } - - /* number of PPS NALs */ - if (ngx_live_record_copy(s, &nnals, &p, 1, &in) != NGX_OK) { - return NGX_ERROR; - } - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "record: PPS number: %uz", nnals); - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_live_record_aac(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - ngx_live_record_ctx_t *ctx; - ngx_rtmp_codec_ctx_t *codec_ctx; - uint64_t pts; - ngx_rtmp_mpegts_frame_t frame; - ngx_buf_t out; - u_char *p; - ngx_uint_t objtype, srindex, chconf, size; - static u_char buffer[NGX_LIVE_RECORD_BUFSIZE]; - ngx_live_record_app_conf_t *lracf; - ngx_msec_t curr_time; - time_t last_time; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_record_module); - - codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - if (codec_ctx == NULL || codec_ctx->aac_header == NULL) { - return NGX_OK; - } - - if (h->mlen < 2) { - return NGX_OK; - } - - if (ctx->open == 2) { - if (codec_ctx->avc_header == NULL) { // pure audio - ctx->open = 1; - } else { - return NGX_OK; - } - } - - lracf = ngx_rtmp_get_module_app_conf(s, ngx_live_record_module); - - if (ctx->last_time == 0) { - ctx->publish_epoch = ngx_current_msec; - ctx->last_time = ngx_time() - ngx_time() % (lracf->interval / 1000); - ctx->basetime = ctx->publish_epoch - h->timestamp; - - ctx->begintime = ngx_current_msec; - ctx->starttime = ngx_current_msec; - ctx->endtime = ngx_current_msec; - - // open new index and file - if (ngx_live_record_open_index(s) == NGX_ERROR) { - ctx->last_time = 0; - - if (ctx->index.fd != -1) { - ngx_close_file(ctx->index.fd); - } - - if (ctx->file.fd != -1) { - ngx_close_file(ctx->file.fd); - } - - return NGX_OK; - } - } - - /* - * FLV Audio data config - * SoundFormat 4bits, SoundRate 2bits, SoundSize 1bit, SoundType 1bit - * AACPacketType 1byte - * - * mpegts ADTS 7 bytes - */ - size = h->mlen - 2 + 7; - pts = (uint64_t) h->timestamp * 90; - - p = in->buf->pos; - - /* skip FLV Audio data config */ - if (ngx_live_record_copy(s, NULL, &p, 2, &in) != NGX_OK) { - return NGX_ERROR; - } - - ngx_memzero(&out, sizeof(out)); - - out.start = buffer; - out.end = buffer + sizeof(buffer); - out.pos = out.start; - out.last = out.pos; - - /* make up ADTS */ - if (ngx_live_record_parse_aac_header(s, &objtype, &srindex, &chconf) - != NGX_OK) - { - ngx_log_error(NGX_LOG_ERR, s->log, 0, "record: aac header error"); - return NGX_OK; - } - - *out.last++ = 0xff; - *out.last++ = 0xf1; - *out.last++ = (u_char) (((objtype - 1) << 6) | (srindex << 2) | - ((chconf & 0x04) >> 2)); - *out.last++ = (u_char) (((chconf & 0x03) << 6) | ((size >> 11) & 0x03)); - *out.last++ = (u_char) (size >> 3); - *out.last++ = (u_char) ((size << 5) | 0x1f); - *out.last++ = 0xfc; - - /* copy payload */ - while (in) { - if (in->buf->last - p) { - out.last = ngx_cpymem(out.last, p, in->buf->last - p); - } - - in = in->next; - if (in) { - p = in->buf->pos; - } - } - - // reopen index and ts file - curr_time = ctx->basetime + h->timestamp; - if (codec_ctx->avc_header == NULL) { // no video - last_time = curr_time / 1000 - (curr_time / 1000) - % (lracf->interval / 1000); - if (curr_time > ctx->starttime + lracf->min_fraglen) { - if (last_time > ctx->last_time) { - ngx_live_record_reopen_index(s, ctx, curr_time, last_time); - } else { - ngx_live_record_write_index(s, ctx, curr_time); - } - } - } - - /* write frame */ - ngx_memzero(&frame, sizeof(frame)); - - frame.cc = ctx->audio_cc; - frame.dts = pts; - frame.pts = frame.dts; - frame.pid = 0x101; - frame.sid = 0xc0; - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->log, 0, - "record: audio pts=%uL, dts=%uL", frame.pts, frame.dts); - - if (ngx_rtmp_mpegts_write_frame(&ctx->ts, &frame, &out) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, "record: audio frame failed"); - } - - ctx->endtime = curr_time; - ctx->audio_cc = frame.cc; - - return NGX_OK; -} - - -static ngx_int_t -ngx_live_record_avc(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - ngx_live_record_ctx_t *ctx; - ngx_rtmp_codec_ctx_t *codec_ctx; - u_char *p; - uint8_t fmt, ftype, nal_type, src_nal_type; - uint32_t len, rlen; - ngx_buf_t out; - uint32_t cts; - ngx_rtmp_mpegts_frame_t frame; - ngx_uint_t nal_bytes; - ngx_int_t aud_sent, sps_pps_sent; - static u_char buffer[NGX_LIVE_RECORD_BUFSIZE]; - ngx_live_record_app_conf_t *lracf; - ngx_msec_t curr_time; - time_t last_time; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_record_module); - - codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - - p = in->buf->pos; - if (ngx_live_record_copy(s, &fmt, &p, 1, &in) != NGX_OK) { - return NGX_ERROR; - } - - /* - * frame type: - * 1: keyframe (for AVC, a seekable frame) - * 2: inter frame (for AVC, a non- seekable frame) - * 3: disposable inter frame (H.263 only) - * 4: generated keyframe (reserved for server use only) - * 5: video info/command frame - */ - ftype = (fmt & 0xf0) >> 4; - - if (ctx->open == 2) { // wait for key frame - if (ftype == 1) { - ctx->open = 1; - } else { - return NGX_OK; - } - } - - lracf = ngx_rtmp_get_module_app_conf(s, ngx_live_record_module); - - if (ctx->last_time == 0) { - ctx->publish_epoch = ngx_current_msec; - ctx->last_time = ngx_time() - ngx_time() % (lracf->interval / 1000); - ctx->basetime = ctx->publish_epoch - h->timestamp; - - ctx->begintime = ngx_current_msec; - ctx->starttime = ngx_current_msec; - ctx->endtime = ngx_current_msec; - - // open new index and file - if (ngx_live_record_open_index(s) == NGX_ERROR) { - ctx->last_time = 0; - - if (ctx->index.fd != -1) { - ngx_close_file(ctx->index.fd); - } - - if (ctx->file.fd != -1) { - ngx_close_file(ctx->file.fd); - } - - return NGX_OK; - } - } - - if (ngx_live_record_copy(s, NULL, &p, 1, &in) != NGX_OK) { - return NGX_ERROR; - } - - if (ngx_live_record_copy(s, &cts, &p, 3, &in) != NGX_OK) { - return NGX_ERROR; - } - - /* CompositionTime */ - cts = ((cts & 0x00FF0000) >> 16) | ((cts & 0x000000FF) << 16) | - (cts & 0x0000FF00); - - /* Data */ - ngx_memzero(&out, sizeof(out)); - - out.start = buffer; - out.end = buffer + sizeof(buffer); - out.pos = out.start; - out.last = out.pos; - - nal_bytes = codec_ctx->avc_nal_bytes; - aud_sent = 0; - sps_pps_sent = 0; - - while (in) { - if (ngx_live_record_copy(s, &rlen, &p, nal_bytes, &in) != NGX_OK) { - return NGX_OK; - } - - len = 0; - ngx_rtmp_rmemcpy(&len, &rlen, nal_bytes); - - if (len == 0) { - continue; - } - - if (ngx_live_record_copy(s, &src_nal_type, &p, 1, &in) != NGX_OK) { - return NGX_OK; - } - - nal_type = src_nal_type & 0x1f; - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->log, 0, - "record: h264 NAL type=%ui, len=%uD", - (ngx_uint_t) nal_type, len); - - if (nal_type >= 7 && nal_type <= 9) { - if (ngx_live_record_copy(s, NULL, &p, len - 1, &in) != NGX_OK) { - return NGX_ERROR; - } - continue; - } - - if (!aud_sent) { - switch (nal_type) { - case 1: - case 5: - case 6: - if (ngx_live_record_append_aud(s, &out) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "record: error appending AUD NAL"); - } - aud_sent = 1; - break; - - case 9: - aud_sent = 1; - break; - } - } - - switch (nal_type) { - case 1: - sps_pps_sent = 0; - break; - case 5: - if (sps_pps_sent) { - break; - } - if (ngx_live_record_append_sps_pps(s, &out) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "record: error appenging SPS/PPS NALs"); - } - sps_pps_sent = 1; - break; - } - - /* AnnexB prefix */ - - if (out.end - out.last < 5) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "record: not enough buffer for AnnexB prefix"); - return NGX_OK; - } - - /* first AnnexB prefix is long (4 bytes) */ - - if (out.last == out.pos) { - *out.last++ = 0; - } - - *out.last++ = 0; - *out.last++ = 0; - *out.last++ = 1; - *out.last++ = src_nal_type; - - /* NAL body */ - - if (out.end - out.last < (ngx_int_t) len) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "record: not enough buffer for NAL"); - return NGX_OK; - } - - if (ngx_live_record_copy(s, out.last, &p, len - 1, &in) != NGX_OK) { - return NGX_ERROR; - } - - out.last += (len - 1); - } - - // reopen index and ts file - curr_time = ctx->basetime + h->timestamp; - last_time = curr_time / 1000 - (curr_time / 1000) - % (lracf->interval / 1000); - if (ftype == 1) { // key frame - if (curr_time > ctx->starttime + lracf->min_fraglen) { - if (last_time > ctx->last_time) { - ngx_live_record_reopen_index(s, ctx, curr_time, last_time); - } else { - ngx_live_record_write_index(s, ctx, curr_time); - } - } - } else if (curr_time > ctx->starttime + lracf->max_fraglen) { // force slice - if (last_time > ctx->last_time) { - ngx_log_error(NGX_LOG_INFO, s->log, 0, "record: force slice, " - "curr_time:%M, starttime:%M, max_fraglen:%M", - curr_time, ctx->starttime, lracf->max_fraglen); - - ngx_live_record_reopen_index(s, ctx, curr_time, last_time); - } else { - ngx_live_record_write_index(s, ctx, curr_time); - } - } - - /* write frame */ - ngx_memzero(&frame, sizeof(frame)); - - frame.cc = ctx->video_cc; - frame.dts = (uint64_t) h->timestamp * 90; - frame.pts = (h->timestamp + cts) * 90; - frame.pid = 0x100; - frame.sid = 0xe0; - frame.key = (ftype == 1); - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->log, 0, - "record: video pts=%uL, dts=%uL", frame.pts, frame.dts); - - if (ngx_rtmp_mpegts_write_frame(&ctx->ts, &frame, &out) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, "record: video frame failed"); - } - - ctx->endtime = curr_time; - ctx->video_cc = frame.cc; - - return NGX_OK; -} - - -static ngx_int_t -ngx_live_record_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - ngx_live_record_ctx_t *ctx; - ngx_rtmp_codec_ctx_t *codec_ctx; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_record_module); - if (ctx == NULL || !ctx->open) { - return NGX_OK; - } - - if (ngx_rtmp_is_codec_header(in)) { - return NGX_OK; - } - - codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - - if (h->type == NGX_RTMP_MSG_AUDIO) { - switch (codec_ctx->audio_codec_id) { - case NGX_RTMP_AUDIO_AAC: - return ngx_live_record_aac(s, h, in); - } - } else { - switch (codec_ctx->video_codec_id) { - case NGX_RTMP_VIDEO_H264: - return ngx_live_record_avc(s, h, in); - } - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_live_record_start_handle(ngx_rtmp_session_t *s) -{ - ngx_live_record_ctx_t *ctx; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_record_module); - - return next_publish(s, &ctx->pubv); -} - - -static ngx_int_t -ngx_live_record_update_handle(ngx_rtmp_session_t *s) -{ - return NGX_OK; -} - - -static ngx_int_t -ngx_live_record_done_handle(ngx_rtmp_session_t *s) -{ - return NGX_OK; -} - - -const char * -ngx_live_record_open(ngx_rtmp_session_t *s) -{ - ngx_live_record_ctx_t *ctx; - - if (s->interprocess) { - return "interprocess"; - } - - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_record_module); - - if (ctx->open) { - return NGX_CONF_OK; - } - - ngx_log_error(NGX_LOG_INFO, s->log, 0, "record: open %V:", &s->stream); - - ctx->open = 2; - - return NGX_CONF_OK; -} - - -const char * -ngx_live_record_close(ngx_rtmp_session_t *s) -{ - ngx_live_record_ctx_t *ctx; - - if (s->interprocess) { - return "interprocess"; - } - - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_record_module); - - if (ctx->open == 0) { - return NGX_CONF_OK; - } - - ngx_log_error(NGX_LOG_INFO, s->log, 0, "record: close %V:", &s->stream); - - ngx_live_record_done(s); - - ngx_live_record_close_index(s, ctx); - - ctx->open = 0; - ctx->last_time = 0; - - return NGX_CONF_OK; -} - - -static ngx_int_t -ngx_live_record_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v) -{ - ngx_live_record_app_conf_t *lracf; - ngx_live_record_ctx_t *ctx; - - if (s->interprocess) { - return next_publish(s, v); - } - - ctx = ngx_pcalloc(s->pool, sizeof(ngx_live_record_ctx_t)); - if (ctx == NULL) { - return NGX_ERROR; - } - ngx_rtmp_set_ctx(s, ctx, ngx_live_record_module); - - lracf = ngx_rtmp_get_module_app_conf(s, ngx_live_record_module); - - if (lracf->record) { - ctx->open = 1; - } - ctx->pubv = *v; - ctx->index.fd = -1; - ctx->file.fd = -1; - - return ngx_live_record_start(s); -} - - -static ngx_int_t -ngx_live_record_close_stream(ngx_rtmp_session_t *s, ngx_rtmp_close_stream_t *v) -{ - ngx_live_record_ctx_t *ctx; - - if (s->interprocess) { - goto next; - } - - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_record_module); - if (ctx == NULL) { - goto next; - } - - if (ctx->open == 0) { - goto next; - } - - ngx_live_record_done(s); - - ngx_live_record_close_index(s, ctx); - ctx->open = 0; - -next: - return next_close_stream(s, v); -} - - -static ngx_int_t -ngx_live_record_postconfiguration(ngx_conf_t *cf) -{ - ngx_rtmp_core_main_conf_t *cmcf; - ngx_rtmp_handler_pt *h; - - cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module); - - h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_AUDIO]); - *h = ngx_live_record_av; - - h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_VIDEO]); - *h = ngx_live_record_av; - - next_record_start = ngx_live_record_start; - ngx_live_record_start = ngx_live_record_start_handle; - - next_record_update = ngx_live_record_update; - ngx_live_record_update = ngx_live_record_update_handle; - - next_record_done = ngx_live_record_done; - ngx_live_record_done = ngx_live_record_done_handle; - - next_publish = ngx_rtmp_publish; - ngx_rtmp_publish = ngx_live_record_publish; - - next_close_stream = ngx_rtmp_close_stream; - ngx_rtmp_close_stream = ngx_live_record_close_stream; - - return NGX_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_record.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_record.h deleted file mode 100644 index 0d008c2097..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_record.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#ifndef _NGX_LIVE_RECORD_H_INCLUDED_ -#define _NGX_LIVE_RECORD_H_INCLUDED_ - - -#include -#include -#include "ngx_rtmp.h" -#include "hls/ngx_rtmp_mpegts.h" - - -typedef struct { - unsigned open; /* 0 close, 1 open, 2 wait for key */ - - time_t last_time; - - ngx_file_t index; - - ngx_rtmp_mpegts_file_t ts; - ngx_file_t file; - - ngx_rtmp_publish_t pubv; - - ngx_uint_t audio_cc; - ngx_uint_t video_cc; - - ngx_msec_t begintime; - ngx_msec_t starttime; - ngx_msec_t endtime; - off_t startsize; - off_t endsize; - - ngx_msec_t publish_epoch; - ngx_msec_t basetime; -} ngx_live_record_ctx_t; - - -typedef ngx_int_t (*ngx_live_record_start_pt)(ngx_rtmp_session_t *s); -typedef ngx_int_t (*ngx_live_record_update_pt)(ngx_rtmp_session_t *s); -typedef ngx_int_t (*ngx_live_record_done_pt)(ngx_rtmp_session_t *s); - - -extern ngx_live_record_start_pt ngx_live_record_start; -extern ngx_live_record_update_pt ngx_live_record_update; -extern ngx_live_record_done_pt ngx_live_record_done; - - -extern ngx_module_t ngx_live_record_module; - - -const char *ngx_live_record_open(ngx_rtmp_session_t *s); -const char *ngx_live_record_close(ngx_rtmp_session_t *s); - - -#endif diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay.c deleted file mode 100644 index 148c9ffda9..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay.c +++ /dev/null @@ -1,418 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include "ngx_live_relay.h" -#include "ngx_rtmp_cmd_module.h" -#include "ngx_toolkit_misc.h" - - -static ngx_rtmp_publish_pt next_publish; -static ngx_rtmp_play_pt next_play; -static ngx_rtmp_close_stream_pt next_close_stream; - - -static ngx_int_t ngx_live_relay_postconfiguration(ngx_conf_t *cf); -static void *ngx_live_relay_create_app_conf(ngx_conf_t *cf); -static char *ngx_live_relay_merge_app_conf(ngx_conf_t *cf, void *parent, - void *child); - - -ngx_live_push_pt ngx_live_push; -ngx_live_pull_pt ngx_live_pull; -ngx_live_push_close_pt ngx_live_push_close; -ngx_live_pull_close_pt ngx_live_pull_close; - - -typedef ngx_int_t (* relay_create_pt)(ngx_rtmp_session_t *rs, - ngx_live_relay_t *relay, - ngx_live_relay_url_t *url); - - -static relay_create_pt create_relay[] = { - ngx_live_relay_create_httpflv, - ngx_live_relay_create_rtmp -}; - - -static const char *relay_protocol[] = { - "httpflv", - "rtmp" -}; - - -static const char *relay_type[] = { - "push", - "pull" -}; - - -static ngx_command_t ngx_live_relay_commands[] = { - - { ngx_string("failed_reconnect"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_live_relay_app_conf_t, failed_reconnect), - NULL }, - - { ngx_string("relay_reconnect"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_live_relay_app_conf_t, relay_reconnect), - NULL }, - - ngx_null_command -}; - - -static ngx_rtmp_module_t ngx_live_relay_module_ctx = { - NULL, /* preconfiguration */ - ngx_live_relay_postconfiguration, /* postconfiguration */ - NULL, /* create main configuration */ - NULL, /* init main configuration */ - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - ngx_live_relay_create_app_conf, /* create app configuration */ - ngx_live_relay_merge_app_conf /* merge app configuration */ -}; - - -ngx_module_t ngx_live_relay_module = { - NGX_MODULE_V1, - &ngx_live_relay_module_ctx, /* module context */ - ngx_live_relay_commands, /* module directives */ - NGX_RTMP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void * -ngx_live_relay_create_app_conf(ngx_conf_t *cf) -{ - ngx_live_relay_app_conf_t *racf; - - racf = ngx_pcalloc(cf->pool, sizeof(ngx_live_relay_app_conf_t)); - if (racf == NULL) { - return NULL; - } - - racf->failed_reconnect = NGX_CONF_UNSET_MSEC; - racf->relay_reconnect = NGX_CONF_UNSET_MSEC; - - return racf; -} - - -static char * -ngx_live_relay_merge_app_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_live_relay_app_conf_t *prev = parent; - ngx_live_relay_app_conf_t *conf = child; - - ngx_conf_merge_msec_value(conf->failed_reconnect, prev->failed_reconnect, - 50); - ngx_conf_merge_msec_value(conf->relay_reconnect, prev->relay_reconnect, - 3000); - - return NGX_CONF_OK; -} - - -ngx_int_t -ngx_live_relay_create(ngx_rtmp_session_t *rs, ngx_live_relay_t *relay) -{ - ngx_live_relay_ctx_t *ctx; - ngx_live_relay_url_t *url; - relay_create_pt create; - - ctx = ngx_rtmp_get_module_ctx(rs, ngx_live_relay_module); - if (ctx->idx >= relay->urls.nelts) { - ctx->idx = 0; - } - ctx->failed_delay = 0; - - url = relay->urls.elts; - url += ctx->idx; - - if (url->relay_type >= NGX_LIVE_RELAY_MAXTYPE) { - ngx_log_error(NGX_LOG_ERR, rs->log, 0, "unsupported relay type %ui", - url->relay_type); - return NGX_ERROR; - } - - create = create_relay[url->relay_type]; - - ngx_log_error(NGX_LOG_INFO, rs->log, 0, - "create %s relay %s to %V:%d, domain='%V' app='%V' name='%V' " - "pargs='%V' referer='%V' user_agent='%V'", - relay_protocol[url->relay_type], relay_type[rs->publishing], - &url->url.host, url->port, &relay->domain, &relay->app, - &relay->name, &relay->pargs, &relay->referer, &relay->user_agent); - - ++ctx->idx; - - return create(rs, relay, url); -} - - -ngx_int_t -ngx_live_relay_play_local(ngx_rtmp_session_t *rs) -{ - ngx_rtmp_play_t v; - - ngx_memzero(&v, sizeof(ngx_rtmp_play_t)); - v.silent = 1; - *(ngx_cpymem(v.name, rs->name.data, ngx_min(sizeof(v.name) - 1, - rs->name.len))) = 0; - if (rs->pargs.len) { - *(ngx_cpymem(v.args, rs->pargs.data, ngx_min(sizeof(v.args) - 1, - rs->pargs.len))) = 0; - } - - return ngx_rtmp_play_filter(rs, &v); -} - - -ngx_int_t -ngx_live_relay_publish_local(ngx_rtmp_session_t *rs) -{ - ngx_rtmp_publish_t v; - - ngx_memzero(&v, sizeof(ngx_rtmp_publish_t)); - v.silent = 1; - *(ngx_cpymem(v.name, rs->name.data, ngx_min(sizeof(v.name) - 1, - rs->name.len))) = 0; - if (rs->pargs.len) { - *(ngx_cpymem(v.args, rs->pargs.data, ngx_min(sizeof(v.args) - 1, - rs->pargs.len))) = 0; - } - - return ngx_rtmp_publish_filter(rs, &v); -} - - -static ngx_int_t -ngx_live_relay_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v) -{ - ngx_live_relay_ctx_t *ctx; - - // second publish will not trigger push - if (s->live_stream->publish_ctx->next != NULL) { - goto next; - } - - if (ngx_live_push(s) != NGX_OK) { - return NGX_ERROR; - } - - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - if (ctx == NULL) { - goto next; - } - - if (ctx->reconnect.timer_set) { - ngx_del_timer(&ctx->reconnect); - } - - if (ctx->reconnect.posted) { - ngx_delete_posted_event(&ctx->reconnect); - } - - ctx->successd = 1; - ctx->failed_reconnect = 0; - - ctx->idx = 0; - -next: - return next_publish(s, v); -} - - -static ngx_int_t -ngx_live_relay_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v) -{ - ngx_live_relay_ctx_t *ctx; - - if (ngx_live_pull(s) != NGX_OK) { - return NGX_ERROR; - } - - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - if (ctx == NULL) { - goto next; - } - - if (ctx->reconnect.timer_set) { - ngx_del_timer(&ctx->reconnect); - } - - if (ctx->reconnect.posted) { - ngx_delete_posted_event(&ctx->reconnect); - } - - ctx->successd = 1; - ctx->failed_reconnect = 0; - - ctx->idx = 0; - -next: - - return next_play(s, v); -} - - -static ngx_int_t -ngx_live_relay_close_stream(ngx_rtmp_session_t *s, ngx_rtmp_close_stream_t *v) -{ - ngx_rtmp_core_ctx_t *ctx; - ngx_live_relay_ctx_t *rctx; - - if (s->live_stream == NULL) { - goto next; - } - - if (s->publishing) { - /* - * normal publisher close or relay puller close - * need to trigger ngx_live_pull_close - */ - ngx_live_pull_close(s); - - // all publishers close, close push (play + relay) - if (s->live_stream->publish_ctx == NULL) { - for (ctx = s->live_stream->play_ctx; ctx; ctx = ctx->next) { - if (ctx->session->relay) { - ctx->session->finalize_reason = NGX_LIVE_RELAY_CLOSE; - ngx_rtmp_finalize_session(ctx->session); - } - } - } - } else { - rctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - if (rctx) { - // push close will trigger relay push reconnect in relay modules - ngx_live_push_close(s); - } - - // all players close, close pull (publish + relay) - if (s->live_stream->play_ctx == NULL) { - for (ctx = s->live_stream->publish_ctx; ctx; ctx = ctx->next) { - if (ctx->session->relay) { - ctx->session->finalize_reason = NGX_LIVE_RELAY_CLOSE; - ngx_rtmp_finalize_session(ctx->session); - } - } - } - } - -next: - return next_close_stream(s, v); -} - - -static ngx_int_t -ngx_live_relay_push(ngx_rtmp_session_t *s) -{ - return NGX_OK; -} - - -static ngx_int_t -ngx_live_relay_pull(ngx_rtmp_session_t *s) -{ - return NGX_OK; -} - - -static ngx_int_t -ngx_live_relay_push_close(ngx_rtmp_session_t *s) -{ - ngx_live_relay_ctx_t *ctx; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - - if (ctx && ctx->reconnect.timer_set) { - ngx_del_timer(&ctx->reconnect); - } - - if (ctx && ctx->reconnect.posted) { - ngx_delete_posted_event(&ctx->reconnect); - } - - return NGX_OK; -} - - -/* - * pull reconnect need to trigger ngx_live_pull chain - */ -static ngx_int_t -ngx_live_relay_pull_close(ngx_rtmp_session_t *s) -{ - ngx_live_relay_ctx_t *ctx; - ngx_flag_t has_player; - ngx_rtmp_core_ctx_t *cctx;; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - - has_player = 0; - - if (s->static_pull == 0) { - for (cctx = s->live_stream->play_ctx; cctx; cctx = cctx->next) { - if (cctx->session->relay == 0) { // has pure player, not relay push - has_player = 1; - break; - } - } - } - - if (has_player || s->static_pull) { // has player in stream - // ctx is NULL, s is a normal publisher - // ctx is not NULL, s is a puller, if giveup flag set - // no need to create pull reconnect - if (ctx == NULL || !ctx->giveup) { - ngx_live_pull(s); - } - } - - if (ctx && ctx->reconnect.timer_set) { - ngx_del_timer(&ctx->reconnect); - } - - if (ctx && ctx->reconnect.posted) { - ngx_delete_posted_event(&ctx->reconnect); - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_live_relay_postconfiguration(ngx_conf_t *cf) -{ - next_publish = ngx_rtmp_publish; - ngx_rtmp_publish = ngx_live_relay_publish; - - next_play = ngx_rtmp_play; - ngx_rtmp_play = ngx_live_relay_play; - - next_close_stream = ngx_rtmp_close_stream; - ngx_rtmp_close_stream = ngx_live_relay_close_stream; - - ngx_live_pull = ngx_live_relay_pull; - ngx_live_push = ngx_live_relay_push; - ngx_live_pull_close = ngx_live_relay_pull_close; - ngx_live_push_close = ngx_live_relay_push_close; - - return NGX_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay.h deleted file mode 100644 index b52405b555..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#ifndef _NGX_LIVE_RELAY_H_INCLUDE_ -#define _NGX_LIVE_RELAY_H_INCLUDE_ - - -#include -#include "ngx_rtmp.h" - - -#define NGX_LIVE_RELAY_HTTPFLV 0 -#define NGX_LIVE_RELAY_RTMP 1 -#define NGX_LIVE_RELAY_MAXTYPE 2 - - -typedef struct { - // reconnect - ngx_event_t reconnect; - ngx_flag_t successd; // connect successd - /* - * connect failed for first time, reconnect immediately - * then reconnect after failed_reconect - * then reconnect after 2 * failed_reconect - * then reconnect after 2 * 2 * failed_reconect - * ... - * when failed_reconnect is bigger than relay_reconnect - * then use relay_reconnect as failed_reconect - * - * connect failed not include connect timeout - */ - ngx_msec_t failed_reconnect; // reconnect timeout - ngx_flag_t failed_delay; - ngx_flag_t giveup; // no need to reconnect - - // base para - ngx_str_t domain; - ngx_str_t app; - ngx_str_t args; // rtmp app args - ngx_str_t name; - ngx_str_t pargs; - - // other para - ngx_str_t referer; // rtmp page_url - ngx_str_t user_agent; // rtmp flashver - ngx_str_t swf_url; // rtmp swf_url - uint32_t acodecs; - uint32_t vcodecs; - - void *tag; - ngx_uint_t idx; -} ngx_live_relay_ctx_t; - - -typedef struct { - ngx_request_url_t url; - in_port_t port; - ngx_uint_t relay_type; -} ngx_live_relay_url_t; - - -typedef struct { - ngx_msec_t failed_reconnect; - ngx_msec_t relay_reconnect; -} ngx_live_relay_app_conf_t; - - -extern ngx_module_t ngx_live_relay_module; - - -ngx_int_t ngx_live_relay_create_httpflv(ngx_rtmp_session_t *rs, - ngx_live_relay_t *relay, ngx_live_relay_url_t *url); - -ngx_int_t ngx_live_relay_create_rtmp(ngx_rtmp_session_t *rs, - ngx_live_relay_t *relay, ngx_live_relay_url_t *url); - -ngx_int_t ngx_live_relay_create(ngx_rtmp_session_t *rs, - ngx_live_relay_t *relay); - -ngx_int_t ngx_live_relay_play_local(ngx_rtmp_session_t *rs); - -ngx_int_t ngx_live_relay_publish_local(ngx_rtmp_session_t *rs); - - -typedef ngx_int_t (*ngx_live_pull_pt)(ngx_rtmp_session_t *s); -typedef ngx_int_t (*ngx_live_push_pt)(ngx_rtmp_session_t *s); -typedef ngx_int_t (*ngx_live_pull_close_pt)(ngx_rtmp_session_t *s); -typedef ngx_int_t (*ngx_live_push_close_pt)(ngx_rtmp_session_t *s); - - -extern ngx_live_push_pt ngx_live_push; -extern ngx_live_pull_pt ngx_live_pull; -extern ngx_live_push_close_pt ngx_live_push_close; -extern ngx_live_pull_close_pt ngx_live_pull_close; - - -#endif diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_httpflv.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_httpflv.c deleted file mode 100644 index 142e023ba0..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_httpflv.c +++ /dev/null @@ -1,637 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include "ngx_live_relay.h" -#include "ngx_http_client.h" -#include "ngx_toolkit_misc.h" -#include "ngx_dynamic_resolver.h" -#include "ngx_rbuf.h" - - -typedef struct { - ngx_uint_t status; - char *code; - char *level; - char *desc; -} ngx_http_status_code_t; - - -static ngx_http_status_code_t ngx_http_relay_status_code[] = { - { 400, "NetStream.Play.BadName", "error", "Bad Request" }, - { 403, "NetStream.Play.Forbidden", "error", "Forbidden" }, - { 404, "NetStream.Play.StreamNotFound", "error", "No such stream" }, - { 503, "NetStream.Play.ServiceUnavailable", "error", "Service Unavailable"}, - { 0, "NetStream.Play.StreamError", "error", "Stream Error" } -}; - - -static ngx_int_t -ngx_live_relay_httpflv_parse(ngx_rtmp_session_t *s, ngx_buf_t *b) -{ - u_char ch, *p, *pc; - ngx_rtmp_stream_t *st; - ngx_rtmp_header_t *h; - ngx_chain_t **ll; - size_t len; - ngx_rtmp_core_srv_conf_t *cscf; - ngx_int_t rc = NGX_AGAIN; - enum { - flv_header_F = 0, - flv_header_FL, - flv_header_FLV, - flv_header_Version, - flv_header_Flags, - flv_header_DataOffset0, - flv_header_DataOffset1, - flv_header_DataOffset2, - flv_header_DataOffset3, - flv_tagsize0, - flv_tagsize1, - flv_tagsize2, - flv_tagsize3, - flv_tagtype, - flv_datasize0, - flv_datasize1, - flv_datasize2, - flv_timestamp0, - flv_timestamp1, - flv_timestamp2, - flv_timestamp_extended, - flv_streamid0, - flv_streamid1, - flv_streamid2, - flv_data - } state; - - state = s->flv_state; - cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module); - - for (p = b->pos; p < b->last; ++p) { - ch = *p; - - switch (state) { - - case flv_header_F: - switch (ch) { - case 'F': - state = flv_header_FL; - break; - default: - rc = NGX_ERROR; - goto done; - } - break; - - case flv_header_FL: - switch (ch) { - case 'L': - state = flv_header_FLV; - break; - default: - rc = NGX_ERROR; - goto done; - } - break; - - case flv_header_FLV: - switch (ch) { - case 'V': - state = flv_header_Version; - break; - default: - rc = NGX_ERROR; - goto done; - } - break; - - case flv_header_Version: - s->flv_version = ch; - if (s->flv_version != 1) { - rc = NGX_ERROR; - goto done; - } - state = flv_header_Flags; - break; - - case flv_header_Flags: - s->flv_flags = ch; - state = flv_header_DataOffset0; - break; - - case flv_header_DataOffset0: - pc = (u_char *) &s->flv_data_offset; - pc[3] = ch; - state = flv_header_DataOffset1; - break; - - case flv_header_DataOffset1: - pc = (u_char *) &s->flv_data_offset; - pc[2] = ch; - state = flv_header_DataOffset2; - break; - - case flv_header_DataOffset2: - pc = (u_char *) &s->flv_data_offset; - pc[1] = ch; - state = flv_header_DataOffset3; - break; - - case flv_header_DataOffset3: - pc = (u_char *) &s->flv_data_offset; - pc[0] = ch; - state = flv_tagsize0; - break; - - case flv_tagsize0: - s->flv_tagsize = 0; - pc = (u_char *) &s->flv_tagsize; - pc[3] = ch; - state = flv_tagsize1; - break; - - case flv_tagsize1: - pc = (u_char *) &s->flv_tagsize; - pc[2] = ch; - state = flv_tagsize2; - break; - - case flv_tagsize2: - pc = (u_char *) &s->flv_tagsize; - pc[1] = ch; - state = flv_tagsize3; - break; - - case flv_tagsize3: - pc = (u_char *) &s->flv_tagsize; - pc[0] = ch; - - st = &s->in_streams[0]; - h = &st->hdr; - - if (h->mlen == 0 && s->flv_first_pts == 0) { - s->flv_first_pts = 1; - if (s->flv_tagsize != 0) { - rc = NGX_ERROR; - goto done; - } - } else { - if (h->mlen + 11 != s->flv_tagsize) { - rc = NGX_ERROR; - goto done; - } - } - state = flv_tagtype; - - break; - - case flv_tagtype: - if (ch != NGX_RTMP_MSG_AMF_META && ch != NGX_RTMP_MSG_AUDIO - && ch != NGX_RTMP_MSG_VIDEO) - { - rc = NGX_ERROR; - goto done; - } - - st = &s->in_streams[0]; - h = &st->hdr; - h->type = ch; - state = flv_datasize0; - - break; - - case flv_datasize0: - st = &s->in_streams[0]; - h = &st->hdr; - h->mlen = 0; - pc = (u_char *) &h->mlen; - - pc[2] = ch; - state = flv_datasize1; - - break; - - case flv_datasize1: - st = &s->in_streams[0]; - h = &st->hdr; - pc = (u_char *) &h->mlen; - - pc[1] = ch; - state = flv_datasize2; - - break; - - case flv_datasize2: - st = &s->in_streams[0]; - h = &st->hdr; - pc = (u_char *) &h->mlen; - - pc[0] = ch; - state = flv_timestamp0; - st->len = h->mlen; - - break; - - case flv_timestamp0: - st = &s->in_streams[0]; - h = &st->hdr; - pc = (u_char *) &h->timestamp; - - pc[2] = ch; - state = flv_timestamp1; - - break; - - case flv_timestamp1: - st = &s->in_streams[0]; - h = &st->hdr; - pc = (u_char *) &h->timestamp; - - pc[1] = ch; - state = flv_timestamp2; - - break; - - case flv_timestamp2: - st = &s->in_streams[0]; - h = &st->hdr; - pc = (u_char *) &h->timestamp; - - pc[0] = ch; - state = flv_timestamp_extended; - - break; - - case flv_timestamp_extended: - st = &s->in_streams[0]; - h = &st->hdr; - pc = (u_char *) &h->timestamp; - - pc[3] = ch; - state = flv_streamid0; - - break; - - case flv_streamid0: - st = &s->in_streams[0]; - h = &st->hdr; - h->msid = 0; - pc = (u_char *) &h->msid; - - pc[2] = ch; - state = flv_streamid1; - - break; - - case flv_streamid1: - st = &s->in_streams[0]; - h = &st->hdr; - pc = (u_char *) &h->msid; - - pc[1] = ch; - state = flv_streamid2; - - break; - - case flv_streamid2: - st = &s->in_streams[0]; - h = &st->hdr; - pc = (u_char *) &h->msid; - - pc[0] = ch; - state = flv_data; - - break; - - case flv_data: - st = &s->in_streams[0]; - - for (ll = &st->in; (*ll) && (*ll)->buf->last == (*ll)->buf->end; - ll = &(*ll)->next); - - for (;;) { - if (*ll == NULL) { - *ll = ngx_get_chainbuf(cscf->chunk_size, 1); - } - - len = ngx_min(st->len, b->last - p); - if ((*ll)->buf->end - (*ll)->buf->last >= (long) len) { - (*ll)->buf->last = ngx_cpymem((*ll)->buf->last, p, len); - p += len; - st->len -= len; - - break; - } - - len = (*ll)->buf->end - (*ll)->buf->last; - (*ll)->buf->last = ngx_cpymem((*ll)->buf->last, p, len); - p += len; - st->len -= len; - - ll = &(*ll)->next; - } - - if (st->len != 0) { - rc = NGX_AGAIN; - goto done; - } - - state = flv_tagsize0; - rc = NGX_OK; - goto done; - } - } - -done: - b->pos = p; - s->flv_state = state; - - return rc; -} - - -static void -ngx_live_relay_httpflv_recv_body(void *request, ngx_http_request_t *hcr) -{ - ngx_int_t n; - ngx_rtmp_session_t *s; - ngx_chain_t *cl, *l, *in; - ngx_rtmp_header_t *h; - ngx_rtmp_stream_t *st = NULL; - - s = request; - - n = ngx_http_client_read_body(hcr, &cl); - - if (n == 0 || n == NGX_ERROR) { - s->finalize_reason = n == 0? NGX_LIVE_NORMAL_CLOSE: - NGX_LIVE_FLV_RECV_ERR; - ngx_log_error(NGX_LOG_INFO, s->log, ngx_errno, - "http relay, recv body error"); - ngx_rtmp_finalize_session(s); - return; - } - - l = cl; - for (;;) { - if (l && l->buf->pos == l->buf->last) { - l = l->next; - } - - if (l == NULL) { - return; - } - - n = ngx_live_relay_httpflv_parse(s, l->buf); - - if (n == NGX_ERROR) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "http relay, parse flv frame failed in state %d", - s->flv_state); - ngx_http_client_finalize_request(hcr, 1); - - return; - } - - if (n == NGX_AGAIN) { - continue; - } - - /* NGX_OK */ - st = &s->in_streams[0]; - h = &st->hdr; - in = st->in; - - if (ngx_rtmp_receive_message(s, h, in) != NGX_OK) { - ngx_rtmp_finalize_session(s); - return; - } - - ngx_put_chainbufs(st->in); - st->in = NULL; - } -} - - -static void -ngx_live_relay_httpflv_cleanup(void *data) -{ - ngx_rtmp_session_t *s; - - s = data; - - ngx_log_error(NGX_LOG_INFO, s->log, 0, "http flv client, cleanup"); - - if (s) { - if (s->close.posted) { - ngx_delete_posted_event(&s->close); - } - - if (s->finalize_reason == 0) { - s->finalize_reason = NGX_LIVE_FLV_RECV_ERR; - } - - ngx_rtmp_finalize_fake_session(s); - } -} - - -static void -ngx_live_relay_httpflv_error(ngx_rtmp_session_t *s, ngx_uint_t status) -{ - ngx_live_stream_t *st; - ngx_rtmp_core_ctx_t *cctx; - char *code, *level, *desc; - size_t i; - - for (i = 0; ngx_http_relay_status_code[i].status; ++i) { - - if (status != ngx_http_relay_status_code[i].status) { - continue; - } - - break; - } - - code = ngx_http_relay_status_code[i].code; - level = ngx_http_relay_status_code[i].level; - desc = ngx_http_relay_status_code[i].desc; - - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "http relay transit, %d: level='%s' code='%s' description='%s'", - status, level, code, desc); - - st = ngx_live_create_stream(&s->serverid, &s->stream); - cctx = st->play_ctx; - - for (; cctx; cctx = cctx->next) { - cctx->session->status = status; - ngx_rtmp_send_status(cctx->session, code, level, desc); - - if (ngx_strcmp(level, "error") == 0 && !cctx->session->static_pull) { - cctx->session->finalize_reason = NGX_LIVE_RELAY_TRANSIT; - ngx_rtmp_finalize_session(cctx->session); - } - } -} - - -static void -ngx_live_relay_httpflv_recv(void *request, ngx_http_request_t *hcr) -{ - ngx_rtmp_session_t *s; - ngx_uint_t status_code; - - s = request; - status_code = ngx_http_client_status_code(hcr); - - s->stage = NGX_LIVE_PLAY; - s->ptime = ngx_current_msec; - - s->connection = hcr->connection; - ngx_rtmp_set_combined_log(s, hcr->connection->log->data, - hcr->connection->log->handler); - s->log->connection = s->connection->number; - - if (ngx_rtmp_core_main_conf->fast_reload && (ngx_exiting || ngx_terminate)) { - ngx_live_relay_httpflv_error(s, NGX_LIVE_PROCESS_EXIT); - s->finalize_reason = NGX_LIVE_PROCESS_EXIT; - ngx_http_client_finalize_request(hcr, 1); - return; - } - - if (status_code != NGX_HTTP_OK) { - ngx_live_relay_httpflv_error(s, status_code); - s->finalize_reason = NGX_LIVE_FLV_RECV_ERR; - ngx_http_client_finalize_request(hcr, 1); - return; - } - - ngx_live_relay_publish_local(s); - - ngx_http_client_set_read_handler(hcr, ngx_live_relay_httpflv_recv_body); - ngx_live_relay_httpflv_recv_body(request, hcr); -} - - -static ngx_int_t -ngx_live_relay_httpflv_send_request(ngx_rtmp_session_t *s, - ngx_live_relay_url_t *url) -{ - ngx_http_request_t *hcr; - ngx_str_t request_url; - size_t len; - ngx_live_relay_ctx_t *ctx; - ngx_http_cleanup_t *cln; - u_char *p; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - - // request url - // http:// + url + ':' + port + '/' + app + '/' + name + ['?' + pargs] - len = 7 + url->url.host.len + 1 + sizeof("65535") - 1 - + 1 + ctx->app.len + 1 + ctx->name.len; - if (ctx->pargs.len) { - len = len + 1 + ctx->pargs.len; - } - - request_url.data = ngx_pcalloc(s->pool, len); - if (request_url.data == NULL) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "alloc mem for request url failed"); - return NGX_ERROR; - } - - if (ctx->pargs.len) { - p = ngx_snprintf(request_url.data, len, "http://%V:%d/%V/%V?%V", - &url->url.host, url->port, &ctx->app, &ctx->name, &ctx->pargs); - } else { - p = ngx_snprintf(request_url.data, len, "http://%V:%d/%V/%V", - &url->url.host, url->port, &ctx->app, &ctx->name); - } - request_url.len = p - request_url.data; - - // request headers - ngx_keyval_t headers[] = { - { ngx_string("Host"), ctx->domain }, - { ngx_string("Referer"), ctx->referer }, - { ngx_string("User-Agent"), ctx->user_agent }, - { ngx_null_string, ngx_null_string } - }; - - s->stage = NGX_LIVE_CONNECT; - s->connect_time = ngx_current_msec; - - hcr = ngx_http_client_get(s->log, &request_url, headers, s); - ngx_http_client_set_read_handler(hcr, ngx_live_relay_httpflv_recv); - - cln = ngx_http_client_cleanup_add(hcr, 0); - if (cln == NULL) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, "http client add cleanup failed"); - ngx_live_relay_httpflv_error(s, NGX_HTTP_INTERNAL_SERVER_ERROR); - ngx_http_client_finalize_request(hcr, 1); - return NGX_ERROR; - } - cln->handler = ngx_live_relay_httpflv_cleanup; - cln->data = s; - - s->request = hcr; - s->live_type = NGX_HTTP_FLV_LIVE; - - return NGX_OK; -} - - -ngx_int_t -ngx_live_relay_create_httpflv(ngx_rtmp_session_t *s, ngx_live_relay_t *relay, - ngx_live_relay_url_t *url) -{ - ngx_live_relay_ctx_t *rctx; - // must use ngx_sockaddr_t, because sizeof(struct sockaddr) - // is not long enouph, content will be covered by other var - ngx_sockaddr_t nsa; - struct sockaddr *sa; - socklen_t len; - - rctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - if (rctx == NULL) { - return NGX_ERROR; - } - -#define NGX_LIVE_RELAY_CTX(para) \ - if (ngx_copy_str(s->pool, &rctx->para, &relay->para) != NGX_OK) { \ - goto destroy; \ - } - - NGX_LIVE_RELAY_CTX(domain); - NGX_LIVE_RELAY_CTX(app); - NGX_LIVE_RELAY_CTX(name); - NGX_LIVE_RELAY_CTX(pargs); - NGX_LIVE_RELAY_CTX(referer); - NGX_LIVE_RELAY_CTX(user_agent); -#undef NGX_LIVE_RELAY_CTX - - rctx->tag = relay->tag; - - // get address, host in url must be resolv sync - sa = (struct sockaddr *) &nsa; - len = ngx_dynamic_resolver_gethostbyname(&url->url.host, sa); - if (len == 0) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "relay httpflv: gethostbyname failed %V", &url->url.host); - goto destroy; - } - - // send http request - if (ngx_live_relay_httpflv_send_request(s, url) != NGX_OK) { - goto destroy; - } - - return NGX_OK; - -destroy: - ngx_rtmp_finalize_session(s); - - return NGX_ERROR; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_inner.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_inner.c deleted file mode 100644 index 235b3f1d74..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_inner.c +++ /dev/null @@ -1,399 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include -#include -#include "ngx_live_relay.h" -#include "ngx_stream_zone_module.h" -#include "ngx_multiport.h" - - -static ngx_live_push_pt next_push; -static ngx_live_pull_pt next_pull; -static ngx_live_push_close_pt next_push_close; -static ngx_live_pull_close_pt next_pull_close; - - -static void *ngx_live_relay_inner_create_app_conf(ngx_conf_t *cf); -static char *ngx_live_relay_inner_merge_app_conf(ngx_conf_t *cf, - void *parent, void *child); -static ngx_int_t ngx_live_relay_inner_postconfiguration(ngx_conf_t *cf); - - -typedef struct { - ngx_flag_t inner_pull; - ngx_str_t inner_pull_port; -} ngx_live_relay_inner_app_conf_t; - - -static ngx_command_t ngx_live_relay_inner_commands[] = { - - { ngx_string("rtmp_auto_pull"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_FLAG, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_live_relay_inner_app_conf_t, inner_pull), - NULL }, - - { ngx_string("rtmp_auto_pull_port"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_live_relay_inner_app_conf_t, inner_pull_port), - NULL }, - - ngx_null_command -}; - - -static ngx_rtmp_module_t ngx_live_relay_inner_module_ctx = { - NULL, /* preconfiguration */ - ngx_live_relay_inner_postconfiguration, /* postconfiguration */ - NULL, /* create main configuration */ - NULL, /* init main configuration */ - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - ngx_live_relay_inner_create_app_conf, /* create app configuration */ - ngx_live_relay_inner_merge_app_conf /* merge app configuration */ -}; - - -ngx_module_t ngx_live_relay_inner_module = { - NGX_MODULE_V1, - &ngx_live_relay_inner_module_ctx, /* module context */ - ngx_live_relay_inner_commands, /* module directives */ - NGX_RTMP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void * -ngx_live_relay_inner_create_app_conf(ngx_conf_t *cf) -{ - ngx_live_relay_inner_app_conf_t *conf; - - conf = ngx_pcalloc(cf->pool, sizeof(ngx_live_relay_inner_app_conf_t)); - if (conf == NULL) { - return NULL; - } - - conf->inner_pull = NGX_CONF_UNSET; - - return conf; -} - -static char * -ngx_live_relay_inner_merge_app_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_live_relay_inner_app_conf_t *prev = parent; - ngx_live_relay_inner_app_conf_t *conf = child; - - ngx_conf_merge_value(conf->inner_pull, prev->inner_pull, 1); - ngx_conf_merge_str_value(conf->inner_pull_port, prev->inner_pull_port, - "unix:/tmp/inner.sock"); - - return NGX_CONF_OK; -} - - -static ngx_int_t -ngx_live_relay_inner_create_relay(ngx_rtmp_session_t *rs, - ngx_live_relay_t *relay, ngx_int_t pslot) -{ - ngx_live_relay_inner_app_conf_t *riacf; - ngx_live_relay_url_t *url; - ngx_str_t port; - - riacf = ngx_rtmp_get_module_app_conf(rs, ngx_live_relay_inner_module); - - ngx_memzero(relay, sizeof(ngx_live_relay_t)); - if (ngx_array_init(&relay->urls, rs->pool, 1, sizeof(ngx_live_relay_url_t)) - != NGX_OK) - { - ngx_log_error(NGX_LOG_ERR, rs->log, 0, - "inner relay, relay init error: %V", &riacf->inner_pull_port); - return NGX_ERROR; - } - - url = ngx_array_push(&relay->urls); - if (url == NULL) { - ngx_log_error(NGX_LOG_ERR, rs->log, 0, - "inner relay, get url failed: %V", &riacf->inner_pull_port); - return NGX_ERROR; - } - relay->tag = &ngx_live_relay_inner_module; - - ngx_memzero(url, sizeof(ngx_live_relay_url_t)); - ngx_memzero(&port, sizeof(ngx_str_t)); - - if (ngx_multiport_get_port(rs->pool, &port, - &riacf->inner_pull_port, pslot) == NGX_ERROR) - { - ngx_log_error(NGX_LOG_ERR, rs->log, 0, - "inner relay, get mulitport error: %V", - &riacf->inner_pull_port); - return NGX_ERROR; - } - - url->url.host = port; - url->url.host_with_port = port; - url->relay_type = NGX_LIVE_RELAY_RTMP; - - return NGX_OK; -} - - -static void -ngx_live_relay_inner_handler(ngx_event_t *ev) -{ - ngx_rtmp_session_t *s; - ngx_live_relay_app_conf_t *lracf; - ngx_live_relay_ctx_t *ctx; - ngx_live_relay_t relay; - - s = ev->data; - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - - if (!ctx->failed_delay && ev->timedout) { // connect timeout - ngx_log_error(NGX_LOG_ERR, s->log, NGX_ETIMEDOUT, - "inner relay, relay timeout"); - s->finalize_reason = NGX_LIVE_RELAY_TIMEOUT; - ngx_rtmp_finalize_session(s); - - return; - } - - // relay pull, no player or relay push no publisher - if ((s->publishing && s->live_stream->play_ctx == NULL) - || (!s->publishing && s->live_stream->publish_ctx == NULL)) - { - return; - } - - lracf = ngx_rtmp_get_module_app_conf(s, ngx_live_relay_module); - - ngx_add_timer(&ctx->reconnect, lracf->relay_reconnect); - - if (ngx_live_relay_inner_create_relay(s, &relay, s->live_stream->pslot) - != NGX_OK) - { - return; - } - - ngx_live_relay_create(s, &relay); -} - - -// if stream's need to continue pull or push chain, otherwise return NGX_OK -static ngx_int_t -ngx_live_relay_inner_relay(ngx_rtmp_session_t *s, unsigned publishing) -{ - ngx_rtmp_session_t *rs; - ngx_live_relay_ctx_t *ctx, *pctx; - ngx_live_relay_app_conf_t *lracf; - ngx_int_t pslot; - - pslot = ngx_stream_zone_insert_stream(&s->stream); - if (pslot == NGX_ERROR) { // stream zone not configured or configured error - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "inner relay, insert stream %V failed", &s->stream); - return NGX_DECLINED; - } - - ngx_log_error(NGX_LOG_INFO, s->log, 0, - "inner relay, stream %V not in current process, " - "pslot:%i ngx_process_slot:%i", - &s->stream, pslot, ngx_process_slot); - - s->live_stream->pslot = pslot; - if (pslot == ngx_process_slot) { // current process become stream owner - return NGX_DECLINED; - } - - rs = ngx_rtmp_create_relay_session(s, &ngx_live_relay_inner_module); - if (rs == NULL) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "inner relay, create relay session failed"); - return NGX_DECLINED; - } - rs->publishing = publishing; - rs->live_stream = s->live_stream; - ngx_live_create_ctx(rs, publishing); - - ctx = ngx_rtmp_get_module_ctx(rs, ngx_live_relay_module); - ctx->reconnect.log = rs->log; - ctx->reconnect.data = rs; - ctx->reconnect.handler = ngx_live_relay_inner_handler; - - lracf = ngx_rtmp_get_module_app_conf(rs, ngx_live_relay_module); - - // play trigger pull or publish trigger push - if (s->publishing != rs->publishing) { - ngx_post_event(&ctx->reconnect, &ngx_posted_events); - return NGX_OK; - } - - // normal publisher close, need to trigger pull - if (s->publishing && !s->relay) { - ngx_post_event(&ctx->reconnect, &ngx_posted_events); - return NGX_OK; - } - - // reconnect - pctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - if (pctx->successd) { // prev relay susccessd - ngx_post_event(&ctx->reconnect, &ngx_posted_events); - return NGX_OK; - } - - if (!pctx->reconnect.timer_set) { // prev relay timeout - ctx->failed_reconnect = ngx_min(pctx->failed_reconnect * 2, - lracf->relay_reconnect); - ngx_post_event(&ctx->reconnect, &ngx_posted_events); - return NGX_OK; - } - - if (pctx->failed_reconnect) { - ctx->failed_reconnect = ngx_min(pctx->failed_reconnect * 2, - lracf->relay_reconnect); - } else { - ctx->failed_reconnect = lracf->failed_reconnect; - } - - ctx->failed_delay = 1; - ngx_add_timer(&ctx->reconnect, ctx->failed_reconnect); - - return NGX_OK; -} - - -static ngx_int_t -ngx_live_relay_inner_push(ngx_rtmp_session_t *s) -{ - ngx_live_relay_inner_app_conf_t *riacf; - - riacf = ngx_rtmp_get_module_app_conf(s, ngx_live_relay_inner_module); - - if (!riacf->inner_pull) { - goto next; - } - - if (s->relay) { - goto next; - } - - if (ngx_live_relay_inner_relay(s, 0) == NGX_OK) { - return NGX_OK; - } - -next: - return next_push(s); -} - - -static ngx_int_t -ngx_live_relay_inner_pull(ngx_rtmp_session_t *s) -{ - ngx_live_relay_inner_app_conf_t *riacf; - - riacf = ngx_rtmp_get_module_app_conf(s, ngx_live_relay_inner_module); - - if (!riacf->inner_pull) { - goto next; - } - - if (!s->publishing && s->relay) { // relay push - goto next; - } - - if (s->live_stream->pslot != -1) { - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "inner relay, stream %V already in current process", - &s->stream); - if (s->live_stream->pslot == ngx_process_slot) { - // stream leader is in current process, continue pull or push chain - goto next; - } - - return NGX_OK; - } - - if (ngx_live_relay_inner_relay(s, 1) == NGX_OK) { - return NGX_OK; - } - -next: - return next_pull(s); -} - - -static ngx_int_t -ngx_live_relay_inner_push_close(ngx_rtmp_session_t *s) -{ - ngx_live_relay_ctx_t *ctx; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - if (ctx->tag != &ngx_live_relay_inner_module) { - goto next; - } - - // relay push and has publisher in stream - if (!ctx->giveup && s->live_stream->publish_ctx) { - ngx_live_relay_inner_relay(s, 0); - } - -next: - return next_push_close(s); -} - - -static ngx_int_t -ngx_live_relay_inner_pull_close(ngx_rtmp_session_t *s) -{ - ngx_live_relay_ctx_t *ctx; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - if (ctx == NULL) { - goto next; - } - - if (ctx->tag != &ngx_live_relay_inner_module) { - goto next; - } - - // inner relay close - s->live_stream->pslot = -1; - -next: - return next_pull_close(s); -} - - -static ngx_int_t -ngx_live_relay_inner_postconfiguration(ngx_conf_t *cf) -{ - /* chain handlers */ - - next_push = ngx_live_push; - ngx_live_push = ngx_live_relay_inner_push; - - next_pull = ngx_live_pull; - ngx_live_pull = ngx_live_relay_inner_pull; - - next_push_close = ngx_live_push_close; - ngx_live_push_close = ngx_live_relay_inner_push_close; - - next_pull_close = ngx_live_pull_close; - ngx_live_pull_close = ngx_live_relay_inner_pull_close; - - return NGX_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_rtmp.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_rtmp.c deleted file mode 100644 index f510991cf5..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_rtmp.c +++ /dev/null @@ -1,860 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include "ngx_live_relay.h" -#include "ngx_poold.h" -#include "ngx_toolkit_misc.h" -#include "ngx_dynamic_resolver.h" - - -static ngx_int_t ngx_live_relay_rtmp_postconfiguration(ngx_conf_t *cf); -static void *ngx_live_relay_rtmp_create_app_conf(ngx_conf_t *cf); -static char *ngx_live_relay_rtmp_merge_app_conf(ngx_conf_t *cf, void *parent, - void *child); - - -typedef struct { - ngx_msec_t buflen; -} ngx_live_relay_rtmp_app_conf_t; - - -typedef struct { - char *code; - ngx_uint_t status; - ngx_flag_t finalize; -} ngx_rtmp_status_code_t; - - -static ngx_rtmp_status_code_t ngx_rtmp_relay_status_error_code[] = { - { "NetStream.Publish.BadName", 400, 1 }, - { "NetStream.Stream.Forbidden", 403, 1 }, - { "NetStream.Play.StreamNotFound", 404, 1 }, - { "NetStream.Relay.ServerError", 500, 1 }, - { NULL, 0, 0 } -}; - - -#define NGX_RTMP_RELAY_CONNECT_TRANS 1 -#define NGX_RTMP_RELAY_CREATE_STREAM_TRANS 2 - - -#define NGX_RTMP_RELAY_CSID_AMF_INI 3 -#define NGX_RTMP_RELAY_CSID_AMF 5 -#define NGX_RTMP_RELAY_MSID 1 - - -static ngx_command_t ngx_live_relay_rtmp_commands[] = { - - { ngx_string("relay_buffer"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_live_relay_rtmp_app_conf_t, buflen), - NULL }, - - ngx_null_command -}; - - -static ngx_rtmp_module_t ngx_live_relay_rtmp_module_ctx = { - NULL, /* preconfiguration */ - ngx_live_relay_rtmp_postconfiguration, /* postconfiguration */ - NULL, /* create main configuration */ - NULL, /* init main configuration */ - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - ngx_live_relay_rtmp_create_app_conf, /* create app configuration */ - ngx_live_relay_rtmp_merge_app_conf /* merge app configuration */ -}; - - -ngx_module_t ngx_live_relay_rtmp_module = { - NGX_MODULE_V1, - &ngx_live_relay_rtmp_module_ctx, /* module context */ - ngx_live_relay_rtmp_commands, /* module directives */ - NGX_RTMP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void * -ngx_live_relay_rtmp_create_app_conf(ngx_conf_t *cf) -{ - ngx_live_relay_rtmp_app_conf_t *racf; - - racf = ngx_pcalloc(cf->pool, sizeof(ngx_live_relay_rtmp_app_conf_t)); - if (racf == NULL) { - return NULL; - } - - racf->buflen = NGX_CONF_UNSET_MSEC; - - return racf; -} - - -static char * -ngx_live_relay_rtmp_merge_app_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_live_relay_rtmp_app_conf_t *prev = parent; - ngx_live_relay_rtmp_app_conf_t *conf = child; - - ngx_conf_merge_msec_value(conf->buflen, prev->buflen, 5000); - - return NGX_CONF_OK; -} - - -static ngx_int_t -ngx_live_relay_rtmp_send_connect(ngx_rtmp_session_t *s) -{ - ngx_str_t app, tcurl; - double acodecs = 3575, vcodecs = 252; - static double trans = NGX_RTMP_RELAY_CONNECT_TRANS; - - static ngx_rtmp_amf_elt_t out_cmd[] = { - - { NGX_RTMP_AMF_STRING, - ngx_string("app"), - NULL, 0 }, /* <-- fill */ - - { NGX_RTMP_AMF_STRING, - ngx_string("tcUrl"), - NULL, 0 }, /* <-- fill */ - - { NGX_RTMP_AMF_STRING, - ngx_string("pageUrl"), - NULL, 0 }, /* <-- fill */ - - { NGX_RTMP_AMF_STRING, - ngx_string("swfUrl"), - NULL, 0 }, /* <-- fill */ - - { NGX_RTMP_AMF_STRING, - ngx_string("flashVer"), - NULL, 0 }, /* <-- fill */ - - { NGX_RTMP_AMF_NUMBER, - ngx_string("audioCodecs"), - NULL, 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_string("videoCodecs"), - NULL, 0 } - }; - - static ngx_rtmp_amf_elt_t out_elts[] = { - - { NGX_RTMP_AMF_STRING, - ngx_null_string, - "connect", 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_null_string, - &trans, 0 }, - - { NGX_RTMP_AMF_OBJECT, - ngx_null_string, - out_cmd, sizeof(out_cmd) } - }; - - ngx_rtmp_core_app_conf_t *cacf; - ngx_rtmp_core_srv_conf_t *cscf; - ngx_live_relay_ctx_t *ctx; - ngx_rtmp_header_t h; - - - cacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_core_module); - cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module); - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - if (cacf == NULL || ctx == NULL) { - return NGX_ERROR; - } - - /* app */ - if (ctx->args.len) { - app.len = ctx->app.len + 1 + ctx->args.len; - app.data = ngx_pcalloc(s->pool, app.len); - if (app.data == NULL) { - return NGX_ERROR; - } - - ngx_snprintf(app.data, app.len, "%V?%V", &ctx->app, &ctx->args); - } else { - app = ctx->app; - } - - out_cmd[0].data = app.data; - out_cmd[0].len = app.len; - - /* tcUrl */ - tcurl.len = sizeof("rtmp://") - 1 + ctx->domain.len + 1 + ctx->app.len; - tcurl.data = ngx_palloc(s->pool, tcurl.len); - if (tcurl.data == NULL) { - return NGX_ERROR; - } - ngx_snprintf(tcurl.data, tcurl.len, "rtmp://%V/%V", - &ctx->domain, &ctx->app); - - out_cmd[1].data = tcurl.data; - out_cmd[1].len = tcurl.len; - - /* pageUrl */ - out_cmd[2].data = ctx->referer.data; - out_cmd[2].len = ctx->referer.len; - - /* swfUrl */ - out_cmd[3].data = ctx->swf_url.data; - out_cmd[3].len = ctx->swf_url.len; - - /* flashVer */ - out_cmd[4].data = ctx->user_agent.data; - out_cmd[4].len = ctx->user_agent.len; - - if (ctx->acodecs != 0) { - acodecs = (double) ctx->acodecs; - } - out_cmd[5].data = &acodecs; - - if (ctx->vcodecs != 0) { - vcodecs = (double) ctx->vcodecs; - } - out_cmd[6].data = &vcodecs; - - ngx_memzero(&h, sizeof(h)); - h.csid = NGX_RTMP_RELAY_CSID_AMF_INI; - h.type = NGX_RTMP_MSG_AMF_CMD; - - s->status = NGX_LIVE_CONNECT; - s->connect_time = ngx_current_msec; - - return ngx_rtmp_send_chunk_size(s, cscf->chunk_size) != NGX_OK - || ngx_rtmp_send_ack_size(s, cscf->ack_window) != NGX_OK - || ngx_rtmp_send_amf(s, &h, out_elts, - sizeof(out_elts) / sizeof(out_elts[0])) != NGX_OK - ? NGX_ERROR - : NGX_OK; -} - - -static ngx_int_t -ngx_live_relay_rtmp_send_create_stream(ngx_rtmp_session_t *s) -{ - static double trans = NGX_RTMP_RELAY_CREATE_STREAM_TRANS; - - static ngx_rtmp_amf_elt_t out_elts[] = { - - { NGX_RTMP_AMF_STRING, - ngx_null_string, - "createStream", 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_null_string, - &trans, 0 }, - - { NGX_RTMP_AMF_NULL, - ngx_null_string, - NULL, 0 } - }; - - ngx_rtmp_header_t h; - - - ngx_memzero(&h, sizeof(h)); - h.csid = NGX_RTMP_RELAY_CSID_AMF_INI; - h.type = NGX_RTMP_MSG_AMF_CMD; - - s->stage = NGX_LIVE_CREATE_STREAM; - s->create_stream_time = ngx_current_msec; - - return ngx_rtmp_send_amf(s, &h, out_elts, - sizeof(out_elts) / sizeof(out_elts[0])); -} - - -static ngx_int_t -ngx_live_relay_rtmp_send_publish(ngx_rtmp_session_t *s) -{ - ngx_str_t name; - static double trans; - - static ngx_rtmp_amf_elt_t out_elts[] = { - - { NGX_RTMP_AMF_STRING, - ngx_null_string, - "publish", 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_null_string, - &trans, 0 }, - - { NGX_RTMP_AMF_NULL, - ngx_null_string, - NULL, 0 }, - - { NGX_RTMP_AMF_STRING, - ngx_null_string, - NULL, 0 }, /* <- to fill */ - - { NGX_RTMP_AMF_STRING, - ngx_null_string, - "live", 0 } - }; - - ngx_rtmp_header_t h; - ngx_live_relay_ctx_t *ctx; - - - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - if (ctx == NULL) { - return NGX_ERROR; - } - - if (ctx->pargs.len) { - name.len = ctx->name.len + 1 + ctx->pargs.len; - name.data = ngx_pcalloc(s->pool, name.len); - if (name.data == NULL) { - return NGX_ERROR; - } - - ngx_snprintf(name.data, name.len, "%V?%V", &ctx->name, &ctx->pargs); - } else { - name = ctx->name; - } - - out_elts[3].data = name.data; - out_elts[3].len = name.len; - - ngx_memzero(&h, sizeof(h)); - h.csid = NGX_RTMP_RELAY_CSID_AMF; - h.msid = NGX_RTMP_RELAY_MSID; - h.type = NGX_RTMP_MSG_AMF_CMD; - - s->stage = NGX_LIVE_PUBLISH; - s->ptime = ngx_current_msec; - - return ngx_rtmp_send_amf(s, &h, out_elts, - sizeof(out_elts) / sizeof(out_elts[0])); -} - - -static ngx_int_t -ngx_live_relay_rtmp_send_play(ngx_rtmp_session_t *s) -{ - ngx_str_t name; - static double trans; - static double start, duration; - - static ngx_rtmp_amf_elt_t out_elts[] = { - - { NGX_RTMP_AMF_STRING, - ngx_null_string, - "play", 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_null_string, - &trans, 0 }, - - { NGX_RTMP_AMF_NULL, - ngx_null_string, - NULL, 0 }, - - { NGX_RTMP_AMF_STRING, - ngx_null_string, - NULL, 0 }, /* <- fill */ - - { NGX_RTMP_AMF_NUMBER, - ngx_null_string, - &start, 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_null_string, - &duration, 0 }, - }; - - ngx_rtmp_header_t h; - ngx_live_relay_ctx_t *ctx; - ngx_live_relay_rtmp_app_conf_t *racf; - - - racf = ngx_rtmp_get_module_app_conf(s, ngx_live_relay_rtmp_module); - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - if (racf == NULL) { - return NGX_ERROR; - } - - if (ctx->pargs.len) { - name.len = ctx->name.len + 1 + ctx->pargs.len; - name.data = ngx_pcalloc(s->pool, name.len); - if (name.data == NULL) { - return NGX_ERROR; - } - - ngx_snprintf(name.data, name.len, "%V?%V", &ctx->name, &ctx->pargs); - } else { - name = ctx->name; - } - - out_elts[3].data = name.data; - out_elts[3].len = name.len; - - start = -1000; - duration = -1000; - - ngx_memzero(&h, sizeof(h)); - h.csid = NGX_RTMP_RELAY_CSID_AMF; - h.msid = NGX_RTMP_RELAY_MSID; - h.type = NGX_RTMP_MSG_AMF_CMD; - - s->stage = NGX_LIVE_PLAY; - s->ptime = ngx_current_msec; - - return ngx_rtmp_send_amf(s, &h, out_elts, - sizeof(out_elts) / sizeof(out_elts[0])) != NGX_OK - || ngx_rtmp_send_set_buflen(s, NGX_RTMP_RELAY_MSID, - racf->buflen) != NGX_OK - ? NGX_ERROR - : NGX_OK; -} - - -static ngx_int_t -ngx_live_relay_rtmp_status_error(ngx_rtmp_session_t *s, char *type, char *code, - char *level, char *desc) -{ - ngx_rtmp_core_ctx_t *cctx; - size_t i; - ngx_flag_t status = 0; - - if (ngx_strcmp(type, "onStatus") == 0) { - status = 1; - } - - for (i = 0; ngx_rtmp_relay_status_error_code[i].code; ++i) { - - if (ngx_strcmp(ngx_rtmp_relay_status_error_code[i].code, code) - != 0) - { - continue; - } - - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "relay transit, %s: level='%s' code='%s' description='%s'", - type, level, code, desc); - - if (s->publishing) { - cctx = s->live_stream->play_ctx; - } else { - cctx = s->live_stream->publish_ctx; - } - - for (; cctx; cctx = cctx->next) { - cctx->session->status = ngx_rtmp_relay_status_error_code[i].status; - status ? ngx_rtmp_send_status(cctx->session, code, level, desc) - : ngx_rtmp_send_error(cctx->session, code, level, desc); - - if (ngx_rtmp_relay_status_error_code[i].finalize - && !cctx->session->static_pull) - { - cctx->session->finalize_reason = NGX_LIVE_RELAY_TRANSIT; - ngx_rtmp_finalize_session(cctx->session); - } - } - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_live_relay_rtmp_on_result(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - ngx_live_relay_ctx_t *ctx; - static struct { - double trans; - u_char level[32]; - u_char code[128]; - u_char desc[1024]; - } v; - - static ngx_rtmp_amf_elt_t in_inf[] = { - - { NGX_RTMP_AMF_STRING, - ngx_string("level"), - &v.level, sizeof(v.level) }, - - { NGX_RTMP_AMF_STRING, - ngx_string("code"), - &v.code, sizeof(v.code) }, - - { NGX_RTMP_AMF_STRING, - ngx_string("description"), - &v.desc, sizeof(v.desc) }, - }; - - static ngx_rtmp_amf_elt_t in_elts[] = { - - { NGX_RTMP_AMF_NUMBER, - ngx_null_string, - &v.trans, 0 }, - - { NGX_RTMP_AMF_NULL, - ngx_null_string, - NULL, 0 }, - - { NGX_RTMP_AMF_OBJECT, - ngx_null_string, - in_inf, sizeof(in_inf) }, - }; - - - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - if (ctx == NULL) { - return NGX_OK; - } - - ngx_memzero(&v, sizeof(v)); - if (ngx_rtmp_receive_amf(s, in, in_elts, - sizeof(in_elts) / sizeof(in_elts[0]))) - { - return NGX_ERROR; - } - - ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->log, 0, - "relay: _result: level='%s' code='%s' description='%s'", - v.level, v.code, v.desc); - - switch ((ngx_int_t)v.trans) { - case NGX_RTMP_RELAY_CONNECT_TRANS: - return ngx_live_relay_rtmp_send_create_stream(s); - - case NGX_RTMP_RELAY_CREATE_STREAM_TRANS: - if (s->publishing == 0) { - if (ngx_live_relay_rtmp_send_publish(s) != NGX_OK) { - return NGX_ERROR; - } - return ngx_live_relay_play_local(s); - - } else { - if (ngx_live_relay_rtmp_send_play(s) != NGX_OK) { - return NGX_ERROR; - } - return ngx_live_relay_publish_local(s); - } - - default: - return NGX_OK; - } -} - - -static ngx_int_t -ngx_live_relay_rtmp_on_error(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - ngx_live_relay_ctx_t *ctx; - static struct { - double trans; - u_char level[32]; - u_char code[128]; - u_char desc[1024]; - } v; - - static ngx_rtmp_amf_elt_t in_inf[] = { - - { NGX_RTMP_AMF_STRING, - ngx_string("level"), - &v.level, sizeof(v.level) }, - - { NGX_RTMP_AMF_STRING, - ngx_string("code"), - &v.code, sizeof(v.code) }, - - { NGX_RTMP_AMF_STRING, - ngx_string("description"), - &v.desc, sizeof(v.desc) }, - }; - - static ngx_rtmp_amf_elt_t in_elts[] = { - - { NGX_RTMP_AMF_NUMBER, - ngx_null_string, - &v.trans, 0 }, - - { NGX_RTMP_AMF_NULL, - ngx_null_string, - NULL, 0 }, - - { NGX_RTMP_AMF_OBJECT, - ngx_null_string, - in_inf, sizeof(in_inf) }, - }; - - - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - if (ctx == NULL) { - return NGX_OK; - } - - ngx_memzero(&v, sizeof(v)); - if (ngx_rtmp_receive_amf(s, in, in_elts, - sizeof(in_elts) / sizeof(in_elts[0]))) - { - return NGX_ERROR; - } - - ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->log, 0, - "relay: _error: level='%s' code='%s' description='%s'", - v.level, v.code, v.desc); - - ngx_live_relay_rtmp_status_error(s, "_error", (char *) v.code, - (char *) v.level, (char *) v.desc); - - return NGX_OK; -} - - -static ngx_int_t -ngx_live_relay_rtmp_on_status(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - ngx_live_relay_ctx_t *ctx; - static struct { - double trans; - u_char level[32]; - u_char code[128]; - u_char desc[1024]; - } v; - - static ngx_rtmp_amf_elt_t in_inf[] = { - - { NGX_RTMP_AMF_STRING, - ngx_string("level"), - &v.level, sizeof(v.level) }, - - { NGX_RTMP_AMF_STRING, - ngx_string("code"), - &v.code, sizeof(v.code) }, - - { NGX_RTMP_AMF_STRING, - ngx_string("description"), - &v.desc, sizeof(v.desc) }, - }; - - static ngx_rtmp_amf_elt_t in_elts[] = { - - { NGX_RTMP_AMF_NUMBER, - ngx_null_string, - &v.trans, 0 }, - - { NGX_RTMP_AMF_NULL, - ngx_null_string, - NULL, 0 }, - - { NGX_RTMP_AMF_OBJECT, - ngx_null_string, - in_inf, sizeof(in_inf) }, - }; - - static ngx_rtmp_amf_elt_t in_elts_meta[] = { - - { NGX_RTMP_AMF_OBJECT, - ngx_null_string, - in_inf, sizeof(in_inf) }, - }; - - - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - if (ctx == NULL) { - return NGX_OK; - } - - ngx_memzero(&v, sizeof(v)); - if (h->type == NGX_RTMP_MSG_AMF_META) { - ngx_rtmp_receive_amf(s, in, in_elts_meta, - sizeof(in_elts_meta) / sizeof(in_elts_meta[0])); - } else { - ngx_rtmp_receive_amf(s, in, in_elts, - sizeof(in_elts) / sizeof(in_elts[0])); - } - - ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->log, 0, - "relay: onStatus: level='%s' code='%s' description='%s'", - v.level, v.code, v.desc); - - ngx_live_relay_rtmp_status_error(s, "onStatus", (char *) v.code, - (char *) v.level, (char *) v.desc); - - return NGX_OK; -} - - -static ngx_int_t -ngx_live_relay_rtmp_handshake_done(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - ngx_live_relay_ctx_t *ctx; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - if (ctx == NULL) { - return NGX_OK; - } - - return ngx_live_relay_rtmp_send_connect(s); -} - - -static ngx_int_t -ngx_live_relay_rtmp_get_peer(ngx_peer_connection_t *pc, void *data) -{ - return NGX_OK; -} - - -static void -ngx_live_relay_rtmp_free_peer(ngx_peer_connection_t *pc, void *data, - ngx_uint_t state) -{ -} - - -ngx_int_t -ngx_live_relay_create_rtmp(ngx_rtmp_session_t *s, ngx_live_relay_t *relay, - ngx_live_relay_url_t *url) -{ - ngx_live_relay_ctx_t *rctx; - ngx_pool_t *pool; - ngx_peer_connection_t *pc; - ngx_connection_t *c; - ngx_int_t rc; - ngx_str_t name; - u_char text[NGX_SOCKADDRLEN]; - // must use ngx_sockaddr_t, because sizeof(struct sockaddr) - // is not long enouph, content will be covered by other var - ngx_sockaddr_t nsa; - struct sockaddr *sa; - socklen_t len; - - rctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - if (rctx == NULL) { - return NGX_ERROR; - } - - pool = ngx_create_pool(4096, ngx_cycle->log); - if (pool == NULL) { - goto destroy; - } - -#define NGX_LIVE_RELAY_CTX(para) \ - if (ngx_copy_str(s->pool, &rctx->para, &relay->para) != NGX_OK) { \ - goto destroy; \ - } - - NGX_LIVE_RELAY_CTX(domain); - NGX_LIVE_RELAY_CTX(app); - NGX_LIVE_RELAY_CTX(name); - NGX_LIVE_RELAY_CTX(pargs); - NGX_LIVE_RELAY_CTX(referer); - NGX_LIVE_RELAY_CTX(user_agent); -#undef NGX_LIVE_RELAY_CTX - - rctx->tag = relay->tag; - - // connect server - pc = ngx_pcalloc(s->pool, sizeof(ngx_peer_connection_t)); - if (pc == NULL) { - goto destroy; - } - pc->log = s->log; - - // get address - sa = (struct sockaddr *) &nsa; - len = ngx_dynamic_resolver_gethostbyname(&url->url.host, sa); - if (len == 0) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "relay rtmp: gethostbyname failed %V", &url->url.host); - goto destroy; - } - - if (url->port != 0) { - ngx_inet_set_port(sa, url->port); - } - - ngx_memzero(text, sizeof(text)); - name.len = ngx_sock_ntop(sa, len, text, NGX_SOCKADDRLEN, 1); - name.data = text; - - /* copy log to keep shared log unchanged */ - pc->get = ngx_live_relay_rtmp_get_peer; - pc->free = ngx_live_relay_rtmp_free_peer; - pc->name = &name; - pc->socklen = len; - pc->sockaddr = sa; - - rc = ngx_event_connect_peer(pc); - if (rc != NGX_OK && rc != NGX_AGAIN ) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, "relay: connection failed"); - goto destroy; - } - c = pc->connection; - if (ngx_copy_str(pool, &c->addr_text, &url->url.host_with_port) != NGX_OK) { - goto destroy; - } - ngx_rtmp_init_session(s, c); - c->pool = pool; - -#if (NGX_STAT_STUB) - (void) ngx_atomic_fetch_add(ngx_stat_active, 1); -#endif - - ngx_rtmp_client_handshake(s, 1); - - return NGX_OK; - -destroy: - if (pool) { - ngx_destroy_pool(pool); - } - - ngx_rtmp_finalize_session(s); - - return NGX_ERROR; -} - - -static ngx_int_t -ngx_live_relay_rtmp_postconfiguration(ngx_conf_t *cf) -{ - ngx_rtmp_core_main_conf_t *cmcf; - ngx_rtmp_handler_pt *h; - ngx_rtmp_amf_handler_t *ch; - - cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module); - - h = ngx_array_push(&cmcf->events[NGX_RTMP_HANDSHAKE_DONE]); - *h = ngx_live_relay_rtmp_handshake_done; - - ch = ngx_array_push(&cmcf->amf); - ngx_str_set(&ch->name, "_result"); - ch->handler = ngx_live_relay_rtmp_on_result; - - ch = ngx_array_push(&cmcf->amf); - ngx_str_set(&ch->name, "_error"); - ch->handler = ngx_live_relay_rtmp_on_error; - - ch = ngx_array_push(&cmcf->amf); - ngx_str_set(&ch->name, "onStatus"); - ch->handler = ngx_live_relay_rtmp_on_status; - - return NGX_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_simple.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_simple.c deleted file mode 100644 index 43c0e0f475..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_simple.c +++ /dev/null @@ -1,460 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include -#include -#include "ngx_live_relay.h" -#include "ngx_rtmp_dynamic.h" -#include "ngx_dynamic_resolver.h" - - -static ngx_live_push_pt next_push; -static ngx_live_pull_pt next_pull; -static ngx_live_push_close_pt next_push_close; - - -static void *ngx_live_relay_simple_create_app_conf(ngx_conf_t *cf); -static char *ngx_live_relay_simple_merge_app_conf(ngx_conf_t *cf, - void *parent, void *child); -static ngx_int_t ngx_live_relay_simple_postconfiguration(ngx_conf_t *cf); - -static char *ngx_live_relay_push(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); -static char *ngx_live_relay_pull(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); - - -typedef struct { - ngx_live_relay_t pull; - ngx_array_t pushes; /* ngx_live_relay_t */ -} ngx_live_relay_simple_app_conf_t; - - -typedef struct { - ngx_live_relay_t *relay; -} ngx_live_relay_simple_ctx_t; - - -static ngx_command_t ngx_live_relay_simple_commands[] = { - - { ngx_string("push"), - NGX_RTMP_APP_CONF|NGX_CONF_1MORE, - ngx_live_relay_push, - NGX_RTMP_APP_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("pull"), - NGX_RTMP_APP_CONF|NGX_CONF_1MORE, - ngx_live_relay_pull, - NGX_RTMP_APP_CONF_OFFSET, - 0, - NULL }, - - ngx_null_command -}; - - -static ngx_rtmp_module_t ngx_live_relay_simple_module_ctx = { - NULL, /* preconfiguration */ - ngx_live_relay_simple_postconfiguration,/* postconfiguration */ - NULL, /* create main configuration */ - NULL, /* init main configuration */ - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - ngx_live_relay_simple_create_app_conf, /* create app configuration */ - ngx_live_relay_simple_merge_app_conf /* merge app configuration */ -}; - - -ngx_module_t ngx_live_relay_simple_module = { - NGX_MODULE_V1, - &ngx_live_relay_simple_module_ctx, /* module context */ - ngx_live_relay_simple_commands, /* module directives */ - NGX_RTMP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void * -ngx_live_relay_simple_create_app_conf(ngx_conf_t *cf) -{ - ngx_live_relay_simple_app_conf_t *conf; - - conf = ngx_pcalloc(cf->pool, sizeof(ngx_live_relay_simple_app_conf_t)); - if (conf == NULL) { - return NULL; - } - - if (ngx_array_init(&conf->pushes, cf->pool, 8, sizeof(ngx_live_relay_t)) - != NGX_OK) - { - return NULL; - } - - return conf; -} - - -static char * -ngx_live_relay_simple_merge_app_conf(ngx_conf_t *cf, void *parent, void *child) -{ - return NGX_CONF_OK; -} - - -static void -ngx_live_relay_simple_handler(ngx_event_t *ev) -{ - ngx_rtmp_session_t *s; - ngx_live_relay_app_conf_t *lracf; - ngx_live_relay_ctx_t *ctx; - ngx_live_relay_simple_ctx_t *sctx; - ngx_live_relay_t *relay; - - s = ev->data; - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - - if (!ctx->failed_delay && ev->timedout) { // connect timeout - ngx_log_error(NGX_LOG_ERR, s->log, NGX_ETIMEDOUT, - "simple relay, relay timeout"); - s->finalize_reason = NGX_LIVE_RELAY_TIMEOUT; - ngx_rtmp_finalize_session(s); - - return; - } - - // relay pull, no player or relay push no publisher - if ((s->publishing && s->live_stream->play_ctx == NULL) - || (!s->publishing && s->live_stream->publish_ctx == NULL)) - { - return; - } - - lracf = ngx_rtmp_get_module_app_conf(s, ngx_live_relay_module); - - ngx_add_timer(&ctx->reconnect, lracf->relay_reconnect); - - sctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_simple_module); - relay = sctx->relay; - - ngx_live_relay_create(s, relay); -} - - -static ngx_int_t -ngx_live_relay_simple_relay(ngx_rtmp_session_t *s, ngx_live_relay_t *relay, - unsigned publishing) -{ - ngx_rtmp_session_t *rs; - ngx_live_relay_ctx_t *ctx, *pctx; - ngx_live_relay_app_conf_t *lracf; - ngx_live_relay_simple_ctx_t *sctx; - - rs = ngx_rtmp_create_relay_session(s, &ngx_live_relay_simple_module); - if (rs == NULL) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "relay simple, create relay session failed"); - return NGX_DECLINED; - } - rs->publishing = publishing; - rs->live_stream = s->live_stream; - ngx_live_create_ctx(rs, publishing); - - sctx = ngx_pcalloc(rs->pool, sizeof(ngx_live_relay_simple_ctx_t)); - if (sctx == NULL) { - ngx_log_error(NGX_LOG_ERR, rs->log, 0, - "relay simple, create simple relay ctx failed"); - ngx_rtmp_finalize_session(rs); - - return NGX_OK; - } - ngx_rtmp_set_ctx(rs, sctx, ngx_live_relay_simple_module); - sctx->relay = relay; - - ctx = ngx_rtmp_get_module_ctx(rs, ngx_live_relay_module); - ctx->reconnect.log = rs->log; - ctx->reconnect.data = rs; - ctx->reconnect.handler = ngx_live_relay_simple_handler; - - if (s->publishing != rs->publishing) { - ngx_post_event(&ctx->reconnect, &ngx_posted_events); - return NGX_OK; - } - - // normal publisher close, need to trigger pull - if (s->publishing && !s->relay) { - ngx_post_event(&ctx->reconnect, &ngx_posted_events); - return NGX_OK; - } - - // reconnect - pctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - if (pctx->successd) { // prev relay successd - ngx_post_event(&ctx->reconnect, &ngx_posted_events); - return NGX_OK; - } - - ctx->idx = pctx->idx; - ctx->failed_reconnect = pctx->failed_reconnect; - - if (ctx->idx < relay->urls.nelts) { // retry backup url immediately - ngx_post_event(&ctx->reconnect, &ngx_posted_events); - return NGX_OK; - } - - lracf = ngx_rtmp_get_module_app_conf(rs, ngx_live_relay_module); - - if (!pctx->reconnect.timer_set) { // prev relay timeout - ctx->failed_reconnect = ngx_min(pctx->failed_reconnect * 2, - lracf->relay_reconnect); - ngx_post_event(&ctx->reconnect, &ngx_posted_events); - return NGX_OK; - } - - if (pctx->failed_reconnect) { - ctx->failed_reconnect = ngx_min(pctx->failed_reconnect * 2, - lracf->relay_reconnect); - } else { - ctx->failed_reconnect = lracf->failed_reconnect; - } - - ctx->failed_delay = 1; - ngx_add_timer(&ctx->reconnect, ctx->failed_reconnect); - - return NGX_OK; -} - - -static ngx_int_t -ngx_live_relay_simple_push(ngx_rtmp_session_t *s) -{ - ngx_live_relay_simple_app_conf_t *rsacf; - ngx_live_relay_t *relay; - ngx_uint_t i; - - rsacf = ngx_rtmp_get_module_app_conf(s, ngx_live_relay_simple_module); - - if (rsacf->pushes.nelts == 0) { // not configured - goto next; - } - - if (s->relay && s->static_pull == 0) { - goto next; - } - - relay = rsacf->pushes.elts; - for (i = 0; i < rsacf->pushes.nelts; ++i, ++relay) { - ngx_live_relay_simple_relay(s, relay, 0); - } - -next: - return next_push(s); -} - - -static ngx_int_t -ngx_live_relay_simple_pull(ngx_rtmp_session_t *s) -{ - ngx_live_relay_simple_app_conf_t *rsacf; - ngx_live_relay_t *relay; - - rsacf = ngx_rtmp_get_module_app_conf(s, ngx_live_relay_simple_module); - - if (rsacf->pull.urls.nelts == 0) { // not configured - goto next; - } - - if (!s->publishing && s->relay) { // relay push - goto next; - } - - if (s->live_stream->publish_ctx) { // already has publisher - goto next; - } - - relay = &rsacf->pull; - - if (ngx_live_relay_simple_relay(s, relay, 1) == NGX_OK) { - return NGX_OK; - } - -next: - return next_pull(s); -} - - -static ngx_int_t -ngx_live_relay_simple_push_close(ngx_rtmp_session_t *s) -{ - ngx_live_relay_ctx_t *ctx; - ngx_live_relay_simple_ctx_t *sctx; - ngx_live_relay_t *relay; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - if (ctx->tag != &ngx_live_relay_simple_module) { - goto next; - } - - // relay push and has publisher in stream - if (!ctx->giveup && s->live_stream->publish_ctx) { - sctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_simple_module); - relay = sctx->relay; - - ngx_live_relay_simple_relay(s, relay, 0); - } - -next: - return next_push_close(s); -} - - -static char * -ngx_live_relay_push_pull(ngx_conf_t *cf, ngx_live_relay_t *relay) -{ - ngx_live_relay_url_t *url; - ngx_str_t *value, n, v; - ngx_uint_t i; - u_char *p; - - relay->tag = &ngx_live_relay_simple_module; - - if (ngx_array_init(&relay->urls, cf->pool, 8, sizeof(ngx_live_relay_url_t)) - != NGX_OK) - { - return NGX_CONF_ERROR; - } - - value = cf->args->elts; - ++value; - - for (i = 1; i < cf->args->nelts; ++i, ++value) { - if (ngx_strncasecmp(value->data, (u_char *) "rtmp://", 7) == 0 - || ngx_strncasecmp(value->data, (u_char *) "http://", 7) == 0) - { - url = ngx_array_push(&relay->urls); - if (url == NULL) { - return NGX_CONF_ERROR; - } - ngx_memzero(url, sizeof(ngx_live_relay_url_t)); - - if (value->data[0] == 'h') { - url->relay_type = NGX_LIVE_RELAY_HTTPFLV; - } else { - url->relay_type = NGX_LIVE_RELAY_RTMP; - } - - if (ngx_parse_request_url(&url->url, value) != NGX_OK) { - return NGX_CONF_ERROR; - } - - url->port = ngx_request_port(&url->url.scheme, &url->url.port); - if (url->port == 0) { - return "invalid port"; - } - - ngx_dynamic_resolver_add_domain(&url->url.host, cf->cycle); - - continue; - } - - p = ngx_strlchr(value->data, value->data + value->len, '='); - - if (p == NULL) { - return "unsupported parameter format"; - } else { - n.data = value->data; - n.len = p - value->data; - - v.data = p + 1; - v.len = value->data + value->len - v.data; - } - -#define NGX_LIVE_RELAY_STR_PAR(name, var) \ - if (n.len == sizeof(name) - 1 \ - && ngx_strncasecmp(n.data, (u_char *) name, n.len) == 0) \ - { \ - relay->var = v; \ - continue; \ - } - - NGX_LIVE_RELAY_STR_PAR("domain", domain); - NGX_LIVE_RELAY_STR_PAR("app", app); - NGX_LIVE_RELAY_STR_PAR("name", name); - NGX_LIVE_RELAY_STR_PAR("pargs", pargs); - NGX_LIVE_RELAY_STR_PAR("referer", referer); - NGX_LIVE_RELAY_STR_PAR("user_agent", user_agent); - -#undef NGX_LIVE_RELAY_STR_PAR - - return "unsupported parameter"; - } - - return NGX_CONF_OK; -} - - -static char * -ngx_live_relay_push(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_live_relay_simple_app_conf_t *rsacf; - ngx_live_relay_t *relay; - char *rc; - - rsacf = conf; - - relay = ngx_array_push(&rsacf->pushes); - if (relay == NULL) { - return NGX_CONF_ERROR; - } - ngx_memzero(relay, sizeof(ngx_live_relay_t)); - - rc = ngx_live_relay_push_pull(cf, relay); - if (rc != NGX_CONF_OK) { - return rc; - } - - return NGX_CONF_OK; -} - - -static char * -ngx_live_relay_pull(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_live_relay_simple_app_conf_t *rsacf; - - rsacf = conf; - - if (rsacf->pull.urls.nelts) { - return "is duplicate"; - } - - return ngx_live_relay_push_pull(cf, &rsacf->pull); -} - - -static ngx_int_t -ngx_live_relay_simple_postconfiguration(ngx_conf_t *cf) -{ - /* chain handlers */ - - next_push = ngx_live_push; - ngx_live_push = ngx_live_relay_simple_push; - - next_pull = ngx_live_pull; - ngx_live_pull = ngx_live_relay_simple_pull; - - next_push_close = ngx_live_push_close; - ngx_live_push_close = ngx_live_relay_simple_push_close; - - return NGX_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_static.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_static.c deleted file mode 100644 index 6b63504a5f..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_static.c +++ /dev/null @@ -1,656 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include -#include -#include "ngx_rtmp.h" -#include "ngx_live_relay.h" -#include "ngx_map.h" -#include "ngx_dynamic_conf.h" -#include "ngx_rtmp_dynamic.h" -#include "ngx_dynamic_resolver.h" - -static ngx_live_pull_pt next_pull; - - -static void *ngx_live_relay_static_create_main_conf(ngx_conf_t *cf); -static char *ngx_live_relay_static_init_main_conf(ngx_conf_t *cf, void *conf); - -static void *ngx_live_relay_static_create_main_dconf(ngx_conf_t *cf); -static char *ngx_live_relay_static_init_main_dconf(ngx_conf_t *cf, void *conf); - -static char *ngx_live_relay_pull(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); - -static ngx_int_t ngx_live_relay_static_postconfiguration(ngx_conf_t *cf); - - -typedef struct ngx_live_relay_static_relay_s ngx_live_relay_static_relay_t; - -struct ngx_live_relay_static_relay_s { - ngx_map_node_t node; - ngx_live_relay_t *relay; - ngx_rtmp_session_t *session; - ngx_live_relay_static_relay_t *next; -}; - - -typedef struct { - /* ngx_live_relay_static_relay_t */ - ngx_map_t pulls[2]; - /* 0 and 1 for index of conf */ - unsigned used; - ngx_str_t pull_port; - - ngx_live_relay_static_relay_t *free; - unsigned nalloc; - unsigned nfree; -} ngx_live_relay_static_main_conf_t; - - -typedef struct { - ngx_array_t pulls; /* ngx_live_relay_t */ -} ngx_live_relay_static_main_dconf_t; - - -typedef struct { - ngx_live_relay_static_relay_t *relay; -} ngx_live_relay_static_ctx_t; - - -static ngx_command_t ngx_live_relay_static_dcommands[] = { - - { ngx_string("static_pull"), - NGX_RTMP_MAIN_CONF|NGX_CONF_1MORE, - ngx_live_relay_pull, - NGX_RTMP_MAIN_CONF_OFFSET, - 0, - NULL }, - - ngx_null_command -}; - - -static ngx_rtmp_dynamic_module_t ngx_live_relay_static_module_dctx = { - ngx_live_relay_static_create_main_dconf,/* create main configuration */ - ngx_live_relay_static_init_main_dconf, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - NULL, /* create app configuration */ - NULL /* merge app configuration */ -}; - - -static ngx_command_t ngx_live_relay_static_commands[] = { - - { ngx_string("static_pull_port"), - NGX_RTMP_MAIN_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, - NGX_RTMP_MAIN_CONF_OFFSET, - offsetof(ngx_live_relay_static_main_conf_t, pull_port), - NULL }, - - ngx_null_command -}; - - -static ngx_rtmp_module_t ngx_live_relay_static_module_ctx = { - NULL, /* preconfiguration */ - ngx_live_relay_static_postconfiguration,/* postconfiguration */ - ngx_live_relay_static_create_main_conf, /* create main configuration */ - ngx_live_relay_static_init_main_conf, /* init main configuration */ - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - NULL, /* create app configuration */ - NULL /* merge app configuration */ -}; - - -ngx_module_t ngx_live_relay_static_module = { - NGX_MODULE_V1, - &ngx_live_relay_static_module_ctx, /* module context */ - ngx_live_relay_static_commands, /* module directives */ - NGX_RTMP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - (uintptr_t) &ngx_live_relay_static_module_dctx, /* module dynamic context */ - (uintptr_t) ngx_live_relay_static_dcommands, /* module dynamic directives */ - NGX_MODULE_V1_DYNAMIC_PADDING -}; - - -static void -ngx_live_relay_static_handler(ngx_event_t *ev) -{ - ngx_rtmp_session_t *s; - ngx_live_relay_app_conf_t *lracf; - ngx_live_relay_ctx_t *ctx; - ngx_live_relay_static_ctx_t *sctx; - ngx_live_relay_t *relay; - - s = ev->data; - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - - if (!ctx->failed_delay && ev->timedout) { // connect timeout - ngx_log_error(NGX_LOG_ERR, s->log, NGX_ETIMEDOUT, - "static relay, relay timeout"); - s->finalize_reason = NGX_LIVE_RELAY_TIMEOUT; - ngx_rtmp_finalize_session(s); - - return; - } - - lracf = ngx_rtmp_get_module_app_conf(s, ngx_live_relay_module); - - ngx_add_timer(&ctx->reconnect, lracf->relay_reconnect); - - sctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_static_module); - relay = sctx->relay->relay; - - ngx_live_relay_create(s, relay); -} - - -static ngx_int_t -ngx_live_relay_static_relay(ngx_rtmp_session_t *s, - ngx_live_relay_static_relay_t *r) -{ - ngx_rtmp_session_t *rs; - ngx_live_relay_ctx_t *ctx, *pctx; - ngx_live_relay_app_conf_t *lracf; - ngx_live_relay_static_main_conf_t *rsmcf; - ngx_live_relay_static_ctx_t *sctx; - ngx_live_relay_t *relay; - ngx_rtmp_addr_conf_t *addr_conf; - - relay = r->relay; - rsmcf = ngx_rtmp_cycle_get_module_main_conf(ngx_cycle, - ngx_live_relay_static_module); - addr_conf = ngx_rtmp_find_related_addr_conf((ngx_cycle_t *) ngx_cycle, - &rsmcf->pull_port); - if (addr_conf == NULL) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, - "relay static, find related add_conf for %V failed", - &rsmcf->pull_port); - return NGX_DECLINED; - } - - rs = ngx_rtmp_create_static_session(relay, addr_conf, - &ngx_live_relay_static_module); - if (rs == NULL) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, - "relay static, create relay session %V failed", &relay->stream); - return NGX_DECLINED; - } - r->session = rs; - - rs->publishing = 1; - rs->live_stream = ngx_live_create_stream(&rs->domain, &rs->stream); - ngx_live_create_ctx(rs, 1); - - sctx = ngx_pcalloc(rs->pool, sizeof(ngx_live_relay_static_ctx_t)); - if (sctx == NULL) { - ngx_log_error(NGX_LOG_ERR, rs->log, 0, - "relay static, create static relay ctx failed"); - ngx_rtmp_finalize_session(rs); - - return NGX_OK; - } - ngx_rtmp_set_ctx(rs, sctx, ngx_live_relay_static_module); - sctx->relay = r; - - ctx = ngx_rtmp_get_module_ctx(rs, ngx_live_relay_module); - ctx->reconnect.log = rs->log; - ctx->reconnect.data = rs; - ctx->reconnect.handler = ngx_live_relay_static_handler; - - if (s == NULL) { - ngx_post_event(&ctx->reconnect, &ngx_posted_events); - return NGX_OK; - } - - // reconnect - pctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - if (pctx->successd) { // prev relay successd - ngx_post_event(&ctx->reconnect, &ngx_posted_events); - return NGX_OK; - } - - ctx->idx = pctx->idx; - ctx->failed_reconnect = pctx->failed_reconnect; - - if (ctx->idx < relay->urls.nelts) { // retry backup url immediately - ngx_post_event(&ctx->reconnect, &ngx_posted_events); - return NGX_OK; - } - - lracf = ngx_rtmp_get_module_app_conf(rs, ngx_live_relay_module); - - if (!pctx->reconnect.timer_set) { // prev relay timeout - ctx->failed_reconnect = ngx_min(pctx->failed_reconnect * 2, - lracf->relay_reconnect); - ngx_post_event(&ctx->reconnect, &ngx_posted_events); - return NGX_OK; - } - - if (pctx->failed_reconnect) { - ctx->failed_reconnect = ngx_min(pctx->failed_reconnect * 2, - lracf->relay_reconnect); - } else { - ctx->failed_reconnect = lracf->failed_reconnect; - } - - ctx->failed_delay = 1; - ngx_add_timer(&ctx->reconnect, ctx->failed_reconnect); - - return NGX_OK; -} - - -// only be called when reconnect -static ngx_int_t -ngx_live_relay_static_pull(ngx_rtmp_session_t *s) -{ - ngx_live_relay_static_ctx_t *ctx; - ngx_live_relay_ctx_t *rctx; - - rctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - if (rctx == NULL || rctx->tag != &ngx_live_relay_static_module) { - goto next; - } - - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_static_module); - - if (ngx_live_relay_static_relay(s, ctx->relay) == NGX_OK) { - return NGX_OK; - } - -next: - return next_pull(s); -} - - -static ngx_live_relay_static_relay_t * -ngx_live_relay_get_static_relay(ngx_live_relay_static_main_conf_t *rsmcf) -{ - ngx_live_relay_static_relay_t *r; - - r = rsmcf->free; - if (r) { - rsmcf->free = r->next; - r->session = NULL; - r->next = NULL; - - --rsmcf->nfree; - } else { - r = ngx_pcalloc(ngx_cycle->pool, sizeof(ngx_live_relay_static_relay_t)); - if (r == NULL) { - return NULL; - } - - ++rsmcf->nalloc; - } - - return r; -} - - -static void -ngx_live_relay_put_static_relay(ngx_live_relay_static_main_conf_t *rsmcf, - ngx_live_relay_static_relay_t *r) -{ - r->next = rsmcf->free; - rsmcf->free = r; - ++rsmcf->nfree; -} - - -static void * -ngx_live_relay_static_create_main_conf(ngx_conf_t *cf) -{ - ngx_live_relay_static_main_conf_t *rsmcf; - - rsmcf = ngx_pcalloc(cf->pool, sizeof(ngx_live_relay_static_main_conf_t)); - if (rsmcf == NULL) { - return NULL; - } - - rsmcf->used = 1; - - ngx_map_init(&rsmcf->pulls[0], ngx_map_hash_str, ngx_cmp_str); - ngx_map_init(&rsmcf->pulls[1], ngx_map_hash_str, ngx_cmp_str); - - return rsmcf; -} - - -static char * -ngx_live_relay_static_init_main_conf(ngx_conf_t *cf, void *conf) -{ - ngx_live_relay_static_main_conf_t *rsmcf; - - rsmcf = conf; - - if (rsmcf->pull_port.len == 0) { - rsmcf->pull_port.data = (u_char *) "1935"; - rsmcf->pull_port.len = sizeof("1935") - 1; - } - - return NGX_CONF_OK; -} - - -static void * -ngx_live_relay_static_create_main_dconf(ngx_conf_t *cf) -{ - ngx_live_relay_static_main_dconf_t *rsmdcf; - - rsmdcf = ngx_pcalloc(cf->pool, sizeof(ngx_live_relay_static_main_dconf_t)); - if (rsmdcf == NULL) { - return NULL; - } - - if (ngx_array_init(&rsmdcf->pulls, cf->pool, 64, sizeof(ngx_live_relay_t)) - != NGX_OK) - { - return NULL; - } - - return rsmdcf; -} - - -// merge all static pull into ngx_live_relay_static_main_conf_t; -static char * -ngx_live_relay_static_init_main_dconf(ngx_conf_t *cf, void *conf) -{ - ngx_live_relay_static_main_conf_t *rsmcf; - ngx_live_relay_static_main_dconf_t *rsmdcf; - ngx_core_conf_t *ccf; - ngx_live_relay_t *relay; - ngx_live_relay_static_relay_t *srelay, *old, *sl, *sln, **sll; - ngx_live_relay_static_ctx_t *ctx; - ngx_live_relay_ctx_t *rctx; - ngx_map_node_t *node; - unsigned used; - char *rc; - ngx_uint_t i, hash; - - rsmdcf = conf; - rsmcf = ngx_rtmp_cycle_get_module_main_conf(ngx_cycle, - ngx_live_relay_static_module); - ccf = (ngx_core_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_core_module); - - used = rsmcf->used? 0: 1; - sl = NULL; - sll = &sl; - - relay = rsmdcf->pulls.elts; - for (i = 0; i < rsmdcf->pulls.nelts; ++i, ++relay) { - // should static pull in current process? - if (ngx_process == NGX_PROCESS_WORKER) { - hash = ngx_hash_key_lc(relay->stream.data, relay->stream.len); - if (hash % ccf->worker_processes != ngx_worker) { - continue; - } - } - - // check static pull duplicate - node = ngx_map_find(&rsmcf->pulls[used], (intptr_t) &relay->stream); - if (node) { - rc = "duplicate static pull"; - goto error; - } - - srelay = ngx_live_relay_get_static_relay(rsmcf); - if (srelay == NULL) { - rc = "get static relay failed"; - goto error; - } - srelay->relay = relay; - srelay->node.raw_key = (intptr_t) &relay->stream; - ngx_map_insert(&rsmcf->pulls[used], &srelay->node, 0); - - // check static pull is exist - node = ngx_map_find(&rsmcf->pulls[rsmcf->used], - (intptr_t) &relay->stream); - if (node) { - old = (ngx_live_relay_static_relay_t *) node; - srelay->session = old->session; - - // link swap static pull - *sll = old; - sll = &(*sll)->next; - } - } - - // delete swap static pull from old - while (sl) { - sln = sl; - sl = sl->next; - ngx_map_delete(&rsmcf->pulls[rsmcf->used], - (intptr_t) &sln->relay->stream); - ngx_live_relay_put_static_relay(rsmcf, sln); - } - - // stop deleted static pull - node = ngx_map_begin(&rsmcf->pulls[rsmcf->used]); - while (node) { - srelay = (ngx_live_relay_static_relay_t *) node; - node = ngx_map_next(node); - ngx_live_relay_put_static_relay(rsmcf, srelay); - - rctx = ngx_rtmp_get_module_ctx(srelay->session, ngx_live_relay_module); - rctx->giveup = 1; - srelay->session->finalize_reason = NGX_LIVE_NORMAL_CLOSE; - ngx_rtmp_finalize_session(srelay->session); - - ngx_map_delete(&rsmcf->pulls[rsmcf->used], - (intptr_t) &srelay->relay->stream); - } - - // new static relay - node = ngx_map_begin(&rsmcf->pulls[used]); - for (; node; node = ngx_map_next(node)) { - srelay = (ngx_live_relay_static_relay_t *) node; - if (srelay->session == NULL) { - ngx_live_relay_static_relay(NULL, srelay); - } else { - ctx = ngx_rtmp_get_module_ctx(srelay->session, - ngx_live_relay_static_module); - ctx->relay = srelay; - } - } - - rsmcf->used = used; - - return NGX_CONF_OK; - -error: - // recycle static relay resource - node = ngx_map_begin(&rsmcf->pulls[used]); - while (node) { - srelay = (ngx_live_relay_static_relay_t *) node; - node = ngx_map_next(node); - ngx_live_relay_put_static_relay(rsmcf, srelay); - - ngx_map_delete(&rsmcf->pulls[used], - (intptr_t) &srelay->relay->stream); - } - - return rc; -} - - -static char * -ngx_live_relay_pull(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_live_relay_static_main_dconf_t *rsmdcf; - ngx_live_relay_t *relay; - ngx_live_relay_url_t *url; - ngx_str_t *value, n, v; - ngx_uint_t i; - u_char *p; - - rsmdcf = conf; - - relay = ngx_array_push(&rsmdcf->pulls); - if (relay == NULL) { - return NGX_CONF_ERROR; - } - ngx_memzero(relay, sizeof(ngx_live_relay_t)); - - relay->tag = &ngx_live_relay_static_module; - - if (ngx_array_init(&relay->urls, cf->pool, 8, sizeof(ngx_live_relay_url_t)) - != NGX_OK) - { - return NGX_CONF_ERROR; - } - - value = cf->args->elts; - ++value; - - for (i = 1; i < cf->args->nelts; ++i, ++value) { - if (ngx_strncasecmp(value->data, (u_char *) "rtmp://", 7) == 0 - || ngx_strncasecmp(value->data, (u_char *) "http://", 7) == 0) - { - url = ngx_array_push(&relay->urls); - if (url == NULL) { - return NGX_CONF_ERROR; - } - ngx_memzero(url, sizeof(ngx_live_relay_url_t)); - - if (value->data[0] == 'h') { - url->relay_type = NGX_LIVE_RELAY_HTTPFLV; - } else { - url->relay_type = NGX_LIVE_RELAY_RTMP; - } - - if (ngx_parse_request_url(&url->url, value) != NGX_OK) { - return NGX_CONF_ERROR; - } - - url->port = ngx_request_port(&url->url.scheme, &url->url.port); - if (url->port == 0) { - return "invalid port"; - } - - ngx_dynamic_resolver_add_domain(&url->url.host, cf->cycle); - - continue; - } - - p = ngx_strlchr(value->data, value->data + value->len, '='); - - if (p == NULL) { - return "unsupported parameter format"; - } else { - n.data = value->data; - n.len = p - value->data; - - v.data = p + 1; - v.len = value->data + value->len - v.data; - } - -#define NGX_LIVE_RELAY_STR_PAR(name, var) \ - if (n.len == sizeof(name) - 1 \ - && ngx_strncasecmp(n.data, (u_char *) name, n.len) == 0) \ - { \ - relay->var = v; \ - continue; \ - } - - NGX_LIVE_RELAY_STR_PAR("domain", domain); - NGX_LIVE_RELAY_STR_PAR("app", app); - NGX_LIVE_RELAY_STR_PAR("name", name); - NGX_LIVE_RELAY_STR_PAR("pargs", pargs); - NGX_LIVE_RELAY_STR_PAR("referer", referer); - NGX_LIVE_RELAY_STR_PAR("user_agent", user_agent); - -#undef NGX_LIVE_RELAY_STR_PAR - - return "unsupported parameter"; - } - - if (relay->domain.len == 0) { - return "domain not configured"; - } - - if (relay->app.len == 0) { - return "app not configured"; - } - - if (relay->name.len == 0) { - return "name not configured"; - } - - // domain/app/name - relay->stream.len = relay->domain.len + 1 + relay->app.len + 1 - + relay->name.len; - relay->stream.data = ngx_pcalloc(cf->pool, relay->stream.len); - if (relay->stream.data == NULL) { - return NGX_CONF_ERROR; - } - ngx_snprintf(relay->stream.data, relay->stream.len, "%V/%V/%V", - &relay->domain, &relay->app, &relay->name); - - return NGX_CONF_OK; -} - - -static ngx_int_t -ngx_live_relay_static_postconfiguration(ngx_conf_t *cf) -{ - next_pull = ngx_live_pull; - ngx_live_pull = ngx_live_relay_static_pull; - - return NGX_OK; -} - - -ngx_chain_t * -ngx_live_relay_static_state(ngx_http_request_t *r) -{ - ngx_live_relay_static_main_conf_t *rsmcf; - ngx_chain_t *cl; - ngx_buf_t *b; - size_t len; - - rsmcf = ngx_rtmp_cycle_get_module_main_conf(ngx_cycle, - ngx_live_relay_static_module); - - len = sizeof("##########rtmp live relay static##########\n") - 1 - + sizeof("relay_static alloc frame: \n") - 1 + NGX_OFF_T_LEN - + sizeof("relay_static free frame: \n") - 1 + NGX_OFF_T_LEN; - - cl = ngx_alloc_chain_link(r->pool); - if (cl == NULL) { - return NULL; - } - cl->next = NULL; - - b = ngx_create_temp_buf(r->pool, len); - if (b == NULL) { - return NULL; - } - cl->buf = b; - - b->last = ngx_snprintf(b->last, len, - "##########rtmp live relay static##########\n" - "relay_static alloc frame: %ui\n" - "relay_static free frame: %ui\n", - rsmcf->nalloc, rsmcf->nfree); - - return cl; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_netcall.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_netcall.c deleted file mode 100644 index 277bd91e18..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_netcall.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include "ngx_netcall.h" -#include "ngx_poold.h" - - -// cleanup only be called when connect failed(exclusive timeout) -static void -ngx_netcall_cleanup(void *data) -{ - ngx_netcall_ctx_t *nctx; - - nctx = data; - - if (nctx->ev.timer_set) { - ngx_del_timer(&nctx->ev); - } - - if (nctx->ev.posted) { - ngx_delete_posted_event(&nctx->ev); - } - - if (nctx->hcr) { - ngx_http_client_detach(nctx->hcr); - nctx->handler(nctx, NGX_ERROR); - nctx->hcr = NULL; - } -} - -// netcall timeout -static void -ngx_netcall_timeout(ngx_event_t *ev) -{ - ngx_netcall_ctx_t *nctx; - - nctx = ev->data; - - if (nctx->ev.timer_set) { - ngx_del_timer(&nctx->ev); - } - - if (nctx->ev.posted) { - ngx_delete_posted_event(&nctx->ev); - } - - if (nctx->hcr) { - ngx_http_client_detach(nctx->hcr); - nctx->handler(nctx, NGX_ERROR); - nctx->hcr = NULL; - } -} - -static void -ngx_netcall_handler(void *data, ngx_http_request_t *hcr) -{ - ngx_netcall_ctx_t *nctx; - ngx_int_t code; - - nctx = data; - - if (nctx->ev.timer_set) { - ngx_del_timer(&nctx->ev); - } - - if (nctx->ev.posted) { - ngx_delete_posted_event(&nctx->ev); - } - - code = ngx_http_client_status_code(hcr); - - if (nctx->hcr) { - ngx_http_client_detach(nctx->hcr); - nctx->handler(nctx, code); - nctx->hcr = NULL; - } -} - -static void -ngx_netcall_destroy_handler(ngx_event_t *ev) -{ - ngx_netcall_ctx_t *nctx; - - nctx = ev->data; - - NGX_DESTROY_POOL(nctx->pool); -} - -ngx_netcall_ctx_t * -ngx_netcall_create_ctx(ngx_uint_t type, ngx_str_t *groupid, ngx_uint_t stage, - ngx_msec_t timeout, ngx_msec_t update, ngx_uint_t idx) -{ - ngx_netcall_ctx_t *ctx; - ngx_pool_t *pool; - - pool = NGX_CREATE_POOL(4096, ngx_cycle->log); - if (pool == NULL) { - return NULL; - } - - ctx = ngx_pcalloc(pool, sizeof(ngx_netcall_ctx_t)); - if (ctx == NULL) { - NGX_DESTROY_POOL(pool); - return NULL; - } - - ctx->url.data = ngx_pcalloc(pool, NGX_NETCALL_MAX_URL_LEN); - if (ctx->url.data == NULL) { - NGX_DESTROY_POOL(pool); - return NULL; - } - - ctx->pool = pool; - - ctx->idx = idx; - ctx->type = type; - - ctx->groupid.len = groupid->len; - ctx->groupid.data = ngx_pcalloc(pool, ctx->groupid.len); - if (ctx->groupid.data == NULL) { - NGX_DESTROY_POOL(pool); - return NULL; - } - ngx_memcpy(ctx->groupid.data, groupid->data, groupid->len); - - ctx->ev.log = ngx_cycle->log; - ctx->ev.data = ctx; - - ctx->stage = stage; - ctx->timeout = timeout; - ctx->update = update; - - return ctx; -} - -void -ngx_netcall_create(ngx_netcall_ctx_t *nctx, ngx_log_t *log) -{ - ngx_http_request_t *hcr; - ngx_http_cleanup_t *cln; - - hcr = ngx_http_client_get(log, &nctx->url, NULL, nctx); - if (hcr == NULL) { - return; - } - - ngx_http_client_set_read_handler(hcr, ngx_netcall_handler); - - cln = ngx_http_client_cleanup_add(hcr, 0); - if (cln == NULL) { - ngx_log_error(NGX_LOG_ERR, log, 0, - "netcall create add cleanup failed"); - return; - } - cln->handler = ngx_netcall_cleanup; - cln->data = nctx; - - // detach old http client request - if (nctx->hcr) { - ngx_http_client_detach(nctx->hcr); - } - - nctx->hcr = hcr; - - nctx->ev.log = log; - nctx->ev.handler = ngx_netcall_timeout; - ngx_add_timer(&nctx->ev, nctx->timeout); -} - -void -ngx_netcall_destroy(ngx_netcall_ctx_t *nctx) -{ - if (nctx->ev.timer_set) { - ngx_del_timer(&nctx->ev); - } - - if (nctx->ev.posted) { - ngx_delete_posted_event(&nctx->ev); - } - - if (nctx->hcr) { // use detach will keep client connection alive - ngx_http_client_detach(nctx->hcr); - nctx->hcr = NULL; - } - - // destroy may called in nctx->handler - // destroy pool may cause memory error - // so we destroy nctx pool asynchronous - nctx->ev.handler = ngx_netcall_destroy_handler; - // reset ev log, use rtmp session log may be destroy - nctx->ev.log = ngx_cycle->log; - ngx_post_event(&nctx->ev, &ngx_posted_events); -} - -ngx_str_t * -ngx_netcall_header(ngx_netcall_ctx_t *nctx, ngx_str_t *key) -{ - ngx_http_request_t *hcr; - - hcr = nctx->hcr; - - return ngx_http_client_header_in(hcr, key); -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_netcall.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_netcall.h deleted file mode 100644 index 3d55d41350..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_netcall.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#ifndef _NGX_NETCALL_H_INCLUDE_ -#define _NGX_NETCALL_H_INCLUDE_ - - -#include -#include "ngx_http_client.h" - - -#define NGX_NETCALL_MAX_URL_LEN 2048 - -typedef struct ngx_netcall_ctx_s ngx_netcall_ctx_t; - -typedef void (* ngx_netcall_handler_pt)(ngx_netcall_ctx_t *ctx, ngx_int_t code); - -struct ngx_netcall_ctx_s { - ngx_pool_t *pool; - - ngx_str_t url; - - ngx_uint_t idx; - ngx_uint_t type; - ngx_str_t groupid; - ngx_uint_t stage; - ngx_msec_t timeout; - ngx_msec_t update; - - ngx_event_t ev; - ngx_http_request_t *hcr; - ngx_netcall_handler_pt handler; - void *data; -}; - - -ngx_netcall_ctx_t *ngx_netcall_create_ctx(ngx_uint_t type, ngx_str_t *groupid, - ngx_uint_t stage, ngx_msec_t timeout, ngx_msec_t update, ngx_uint_t idx); - -void ngx_netcall_create(ngx_netcall_ctx_t *nctx, ngx_log_t *log); -void ngx_netcall_destroy(ngx_netcall_ctx_t *nctx); -ngx_str_t *ngx_netcall_header(ngx_netcall_ctx_t *nctx, ngx_str_t *key); - - -#endif diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp.c deleted file mode 100644 index 2151b30a78..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp.c +++ /dev/null @@ -1,1343 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include -#include -#include -#include "ngx_rtmp.h" -#include "ngx_rtmp_variables.h" - - -static char *ngx_rtmp_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -static ngx_int_t ngx_rtmp_optimize_servers(ngx_conf_t *cf, - ngx_rtmp_core_main_conf_t *cmcf, ngx_array_t *ports); -static ngx_int_t ngx_rtmp_add_addrs(ngx_conf_t *cf, ngx_rtmp_port_t *mport, - ngx_rtmp_conf_addr_t *addr); -#if (NGX_HAVE_INET6) -static ngx_int_t ngx_rtmp_add_addrs6(ngx_conf_t *cf, ngx_rtmp_port_t *mport, - ngx_rtmp_conf_addr_t *addr); -#endif -static ngx_int_t ngx_rtmp_cmp_conf_addrs(const void *one, const void *two); -static ngx_int_t ngx_rtmp_init_events(ngx_conf_t *cf, - ngx_rtmp_core_main_conf_t *cmcf); -static ngx_int_t ngx_rtmp_init_event_handlers(ngx_conf_t *cf, - ngx_rtmp_core_main_conf_t *cmcf); -static char * ngx_rtmp_merge_applications(ngx_conf_t *cf, - ngx_array_t *applications, void **app_conf, ngx_rtmp_module_t *module, - ngx_uint_t ctx_index); -static ngx_int_t ngx_rtmp_init_process(ngx_cycle_t *cycle); - - -#if (nginx_version >= 1007011) -ngx_queue_t ngx_rtmp_init_queue; -#elif (nginx_version >= 1007005) -ngx_thread_volatile ngx_queue_t ngx_rtmp_init_queue; -#else -ngx_thread_volatile ngx_event_t *ngx_rtmp_init_queue; -#endif - -ngx_int_t NGX_RTMP_HEVC_CODEC_ID = NGX_RTMP_VIDEO_H265; - -ngx_uint_t ngx_rtmp_max_module; - - -static ngx_command_t ngx_rtmp_commands[] = { - - { ngx_string("rtmp"), - NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, - ngx_rtmp_block, - 0, - 0, - NULL }, - - ngx_null_command -}; - - -static ngx_core_module_t ngx_rtmp_module_ctx = { - ngx_string("rtmp"), - NULL, - NULL -}; - - -ngx_module_t ngx_rtmp_module = { - NGX_MODULE_V1, - &ngx_rtmp_module_ctx, /* module context */ - ngx_rtmp_commands, /* module directives */ - NGX_CORE_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - ngx_rtmp_init_process, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static char * -ngx_rtmp_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - char *rv; - ngx_uint_t m, mi, s; - ngx_conf_t pcf; - ngx_array_t ports; - ngx_module_t **modules; - ngx_rtmp_module_t *module; - ngx_rtmp_conf_ctx_t *ctx; - ngx_rtmp_core_srv_conf_t *cscf, **cscfp; - ngx_rtmp_core_main_conf_t *cmcf; - - ctx = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_conf_ctx_t)); - if (ctx == NULL) { - return NGX_CONF_ERROR; - } - - *(ngx_rtmp_conf_ctx_t **) conf = ctx; - - /* count the number of the rtmp modules and set up their indices */ - -#if (nginx_version >= 1009011) - - ngx_rtmp_max_module = ngx_count_modules(cf->cycle, NGX_RTMP_MODULE); - -#else - - ngx_rtmp_max_module = 0; - for (m = 0; ngx_modules[m]; m++) { - if (ngx_modules[m]->type != NGX_RTMP_MODULE) { - continue; - } - - ngx_modules[m]->ctx_index = ngx_rtmp_max_module++; - } - -#endif - - - /* the rtmp main_conf context, it is the same in the all rtmp contexts */ - - ctx->main_conf = ngx_pcalloc(cf->pool, - sizeof(void *) * ngx_rtmp_max_module); - if (ctx->main_conf == NULL) { - return NGX_CONF_ERROR; - } - - - /* - * the rtmp null srv_conf context, it is used to merge - * the server{}s' srv_conf's - */ - - ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_rtmp_max_module); - if (ctx->srv_conf == NULL) { - return NGX_CONF_ERROR; - } - - - /* - * the rtmp null app_conf context, it is used to merge - * the server{}s' app_conf's - */ - - ctx->app_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_rtmp_max_module); - if (ctx->app_conf == NULL) { - return NGX_CONF_ERROR; - } - - - /* - * create the main_conf's, the null srv_conf's, and the null app_conf's - * of the all rtmp modules - */ - -#if (nginx_version >= 1009011) - modules = cf->cycle->modules; -#else - modules = ngx_modules; -#endif - - for (m = 0; modules[m]; m++) { - if (modules[m]->type != NGX_RTMP_MODULE) { - continue; - } - - module = modules[m]->ctx; - mi = modules[m]->ctx_index; - - if (module->create_main_conf) { - ctx->main_conf[mi] = module->create_main_conf(cf); - if (ctx->main_conf[mi] == NULL) { - return NGX_CONF_ERROR; - } - } - - if (module->create_srv_conf) { - ctx->srv_conf[mi] = module->create_srv_conf(cf); - if (ctx->srv_conf[mi] == NULL) { - return NGX_CONF_ERROR; - } - } - - if (module->create_app_conf) { - ctx->app_conf[mi] = module->create_app_conf(cf); - if (ctx->app_conf[mi] == NULL) { - return NGX_CONF_ERROR; - } - } - } - - pcf = *cf; - cf->ctx = ctx; - - for (m = 0; modules[m]; m++) { - if (modules[m]->type != NGX_RTMP_MODULE) { - continue; - } - - module = modules[m]->ctx; - - if (module->preconfiguration) { - if (module->preconfiguration(cf) != NGX_OK) { - return NGX_CONF_ERROR; - } - } - } - - /* parse inside the rtmp{} block */ - - cf->module_type = NGX_RTMP_MODULE; - cf->cmd_type = NGX_RTMP_MAIN_CONF; - rv = ngx_conf_parse(cf, NULL); - - if (rv != NGX_CONF_OK) { - *cf = pcf; - return rv; - } - - - /* init rtmp{} main_conf's, merge the server{}s' srv_conf's */ - - cmcf = ctx->main_conf[ngx_rtmp_core_module.ctx_index]; - cscfp = cmcf->servers.elts; - - for (m = 0; modules[m]; m++) { - if (modules[m]->type != NGX_RTMP_MODULE) { - continue; - } - - module = modules[m]->ctx; - mi = modules[m]->ctx_index; - - /* init rtmp{} main_conf's */ - - cf->ctx = ctx; - - if (module->init_main_conf) { - rv = module->init_main_conf(cf, ctx->main_conf[mi]); - if (rv != NGX_CONF_OK) { - *cf = pcf; - return rv; - } - } - - for (s = 0; s < cmcf->servers.nelts; s++) { - - /* merge the server{}s' srv_conf's */ - - cf->ctx = cscfp[s]->ctx; - - if (module->merge_srv_conf) { - rv = module->merge_srv_conf(cf, - ctx->srv_conf[mi], - cscfp[s]->ctx->srv_conf[mi]); - if (rv != NGX_CONF_OK) { - *cf = pcf; - return rv; - } - } - - if (module->merge_app_conf) { - - /* merge the server{}'s app_conf */ - - /*ctx->app_conf = cscfp[s]->ctx->loc_conf;*/ - - rv = module->merge_app_conf(cf, - ctx->app_conf[mi], - cscfp[s]->ctx->app_conf[mi]); - if (rv != NGX_CONF_OK) { - *cf = pcf; - return rv; - } - - /* merge the applications{}' app_conf's */ - - cscf = cscfp[s]->ctx->srv_conf[ngx_rtmp_core_module.ctx_index]; - - rv = ngx_rtmp_merge_applications(cf, &cscf->applications, - cscfp[s]->ctx->app_conf, - module, mi); - if (rv != NGX_CONF_OK) { - *cf = pcf; - return rv; - } - } - - } - } - - - if (ngx_rtmp_init_events(cf, cmcf) != NGX_OK) { - return NGX_CONF_ERROR; - } - - for (m = 0; modules[m]; m++) { - if (modules[m]->type != NGX_RTMP_MODULE) { - continue; - } - - module = modules[m]->ctx; - - if (module->postconfiguration) { - if (module->postconfiguration(cf) != NGX_OK) { - return NGX_CONF_ERROR; - } - } - } - - *cf = pcf; - - if (ngx_rtmp_init_event_handlers(cf, cmcf) != NGX_OK) { - return NGX_CONF_ERROR; - } - - if (ngx_array_init(&ports, cf->temp_pool, 4, sizeof(ngx_rtmp_conf_port_t)) - != NGX_OK) - { - return NGX_CONF_ERROR; - } - - if (ngx_rtmp_optimize_servers(cf, cmcf, cmcf->ports) != NGX_OK) { - return NGX_CONF_ERROR; - } - - return NGX_CONF_OK; -} - - -static char * -ngx_rtmp_merge_applications(ngx_conf_t *cf, ngx_array_t *applications, - void **app_conf, ngx_rtmp_module_t *module, ngx_uint_t ctx_index) -{ - char *rv; - ngx_rtmp_conf_ctx_t *ctx, saved; - ngx_rtmp_core_app_conf_t **cacfp; - ngx_uint_t n; - ngx_rtmp_core_app_conf_t *cacf; - - if (applications == NULL) { - return NGX_CONF_OK; - } - - ctx = (ngx_rtmp_conf_ctx_t *) cf->ctx; - saved = *ctx; - - cacfp = applications->elts; - for (n = 0; n < applications->nelts; ++n, ++cacfp) { - - ctx->app_conf = (*cacfp)->app_conf; - - rv = module->merge_app_conf(cf, app_conf[ctx_index], - (*cacfp)->app_conf[ctx_index]); - if (rv != NGX_CONF_OK) { - return rv; - } - - cacf = (*cacfp)->app_conf[ngx_rtmp_core_module.ctx_index]; - rv = ngx_rtmp_merge_applications(cf, &cacf->applications, - (*cacfp)->app_conf, - module, ctx_index); - if (rv != NGX_CONF_OK) { - return rv; - } - } - - *ctx = saved; - - return NGX_CONF_OK; -} - - -static ngx_int_t -ngx_rtmp_init_events(ngx_conf_t *cf, ngx_rtmp_core_main_conf_t *cmcf) -{ - size_t n; - - for(n = 0; n < NGX_RTMP_MAX_EVENT; ++n) { - if (ngx_array_init(&cmcf->events[n], cf->pool, 1, - sizeof(ngx_rtmp_handler_pt)) != NGX_OK) - { - return NGX_ERROR; - } - } - - if (ngx_array_init(&cmcf->amf, cf->pool, 1, - sizeof(ngx_rtmp_amf_handler_t)) != NGX_OK) - { - return NGX_ERROR; - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_init_event_handlers(ngx_conf_t *cf, ngx_rtmp_core_main_conf_t *cmcf) -{ - ngx_hash_init_t calls_hash; - ngx_rtmp_handler_pt *eh; - ngx_rtmp_amf_handler_t *h; - ngx_hash_key_t *ha; - size_t n, m; - - static size_t pm_events[] = { - NGX_RTMP_MSG_CHUNK_SIZE, - NGX_RTMP_MSG_ABORT, - NGX_RTMP_MSG_ACK, - NGX_RTMP_MSG_ACK_SIZE, - NGX_RTMP_MSG_BANDWIDTH - }; - - static size_t amf_events[] = { - NGX_RTMP_MSG_AMF_CMD, - NGX_RTMP_MSG_AMF_META, - NGX_RTMP_MSG_AMF_SHARED, - NGX_RTMP_MSG_AMF3_CMD, - NGX_RTMP_MSG_AMF3_META, - NGX_RTMP_MSG_AMF3_SHARED - }; - - /* init standard protocol events */ - for(n = 0; n < sizeof(pm_events) / sizeof(pm_events[0]); ++n) { - eh = ngx_array_push(&cmcf->events[pm_events[n]]); - *eh = ngx_rtmp_protocol_message_handler; - } - - /* init amf events */ - for(n = 0; n < sizeof(amf_events) / sizeof(amf_events[0]); ++n) { - eh = ngx_array_push(&cmcf->events[amf_events[n]]); - *eh = ngx_rtmp_amf_message_handler; - } - - /* init user protocol events */ - eh = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_USER]); - *eh = ngx_rtmp_user_message_handler; - - /* aggregate to audio/video map */ - eh = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_AGGREGATE]); - *eh = ngx_rtmp_aggregate_message_handler; - - /* init amf callbacks */ - ngx_array_init(&cmcf->amf_arrays, cf->pool, 1, sizeof(ngx_hash_key_t)); - - h = cmcf->amf.elts; - for(n = 0; n < cmcf->amf.nelts; ++n, ++h) { - ha = cmcf->amf_arrays.elts; - for(m = 0; m < cmcf->amf_arrays.nelts; ++m, ++ha) { - if (h->name.len == ha->key.len - && !ngx_strncmp(h->name.data, ha->key.data, ha->key.len)) - { - break; - } - } - if (m == cmcf->amf_arrays.nelts) { - ha = ngx_array_push(&cmcf->amf_arrays); - ha->key = h->name; - ha->key_hash = ngx_hash_key_lc(ha->key.data, ha->key.len); - ha->value = ngx_array_create(cf->pool, 1, - sizeof(ngx_rtmp_handler_pt)); - if (ha->value == NULL) { - return NGX_ERROR; - } - } - - eh = ngx_array_push((ngx_array_t*)ha->value); - *eh = h->handler; - } - - calls_hash.hash = &cmcf->amf_hash; - calls_hash.key = ngx_hash_key_lc; - calls_hash.max_size = 512; - calls_hash.bucket_size = ngx_cacheline_size; - calls_hash.name = "amf_hash"; - calls_hash.pool = cf->pool; - calls_hash.temp_pool = NULL; - - if (ngx_hash_init(&calls_hash, cmcf->amf_arrays.elts, cmcf->amf_arrays.nelts) - != NGX_OK) - { - return NGX_ERROR; - } - - return NGX_OK; -} - - -/* add the server core module configuration to the address:port */ - -static ngx_int_t -ngx_rtmp_add_server(ngx_conf_t *cf, ngx_rtmp_core_srv_conf_t *cscf, - ngx_rtmp_conf_addr_t *addr) -{ - ngx_uint_t i; - ngx_rtmp_core_srv_conf_t **server; - - if (addr->servers.elts == NULL) { - if (ngx_array_init(&addr->servers, cf->temp_pool, 4, - sizeof(ngx_rtmp_core_srv_conf_t *)) - != NGX_OK) - { - return NGX_ERROR; - } - - } else { - server = addr->servers.elts; - for (i = 0; i < addr->servers.nelts; i++) { - if (server[i] == cscf) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "a duplicate listen %s", addr->opt.addr); - return NGX_ERROR; - } - } - } - - server = ngx_array_push(&addr->servers); - if (server == NULL) { - return NGX_ERROR; - } - - *server = cscf; - - return NGX_OK; -} - - -/* - * add the server address, the server names and the server core module - * configurations to the port list - */ - -static ngx_int_t -ngx_rtmp_add_address(ngx_conf_t *cf, ngx_rtmp_core_srv_conf_t *cscf, - ngx_rtmp_conf_port_t *port, ngx_rtmp_listen_opt_t *lsopt) -{ - ngx_rtmp_conf_addr_t *addr; - - if (port->addrs.elts == NULL) { - if (ngx_array_init(&port->addrs, cf->temp_pool, 4, - sizeof(ngx_rtmp_conf_addr_t)) - != NGX_OK) - { - return NGX_ERROR; - } - } - - addr = ngx_array_push(&port->addrs); - if (addr == NULL) { - return NGX_ERROR; - } - - addr->opt = *lsopt; - addr->hash.buckets = NULL; - addr->hash.size = 0; - addr->wc_head = NULL; - addr->wc_tail = NULL; -#if (NGX_PCRE) - addr->nregex = 0; - addr->regex = NULL; -#endif - addr->default_server = cscf; - addr->servers.elts = NULL; - - return ngx_rtmp_add_server(cf, cscf, addr); -} - - -static ngx_int_t -ngx_rtmp_add_addresses(ngx_conf_t *cf, ngx_rtmp_core_srv_conf_t *cscf, - ngx_rtmp_conf_port_t *port, ngx_rtmp_listen_opt_t *lsopt) -{ - ngx_uint_t i, default_server, proxy_protocol; - ngx_rtmp_conf_addr_t *addr; - - /* - * we cannot compare whole sockaddr struct's as kernel - * may fill some fields in inherited sockaddr struct's - */ - - addr = port->addrs.elts; - - for (i = 0; i < port->addrs.nelts; i++) { - - if (ngx_cmp_sockaddr(lsopt->sockaddr, lsopt->socklen, - addr[i].opt.sockaddr, - addr[i].opt.socklen, 0) - != NGX_OK) - { - continue; - } - - /* the address is already in the address list */ - - if (ngx_rtmp_add_server(cf, cscf, &addr[i]) != NGX_OK) { - return NGX_ERROR; - } - - /* preserve default_server bit during listen options overwriting */ - default_server = addr[i].opt.default_server; - - proxy_protocol = lsopt->proxy_protocol || addr[i].opt.proxy_protocol; - - if (lsopt->set) { - - if (addr[i].opt.set) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "duplicate listen options for %s", addr[i].opt.addr); - return NGX_ERROR; - } - - addr[i].opt = *lsopt; - } - - /* check the duplicate "default" server for this address:port */ - - if (lsopt->default_server) { - - if (default_server) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "a duplicate default server for %s", addr[i].opt.addr); - return NGX_ERROR; - } - - default_server = 1; - addr[i].default_server = cscf; - } - - addr[i].opt.default_server = default_server; - addr[i].opt.proxy_protocol = proxy_protocol; - - return NGX_OK; - } - - /* add the address to the addresses list that bound to this port */ - - return ngx_rtmp_add_address(cf, cscf, port, lsopt); -} - - -ngx_int_t -ngx_rtmp_add_listen(ngx_conf_t *cf, ngx_rtmp_core_srv_conf_t *cscf, - ngx_rtmp_listen_opt_t *lsopt) -{ - in_port_t p; - ngx_uint_t i; - struct sockaddr *sa; - ngx_rtmp_conf_port_t *port; - ngx_rtmp_core_main_conf_t *cmcf; - - cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module); - - if (cmcf->ports == NULL) { - cmcf->ports = ngx_array_create(cf->temp_pool, 2, - sizeof(ngx_rtmp_conf_port_t)); - if (cmcf->ports == NULL) { - return NGX_ERROR; - } - } - - sa = lsopt->sockaddr; - p = ngx_inet_get_port(sa); - - port = cmcf->ports->elts; - for (i = 0; i < cmcf->ports->nelts; i++) { - - if (p != port[i].port || sa->sa_family != port[i].family) { - continue; - } - - /* a port is already in the port list */ - - return ngx_rtmp_add_addresses(cf, cscf, &port[i], lsopt); - } - - /* add a port to the port list */ - - port = ngx_array_push(cmcf->ports); - if (port == NULL) { - return NGX_ERROR; - } - - port->family = sa->sa_family; - port->port = p; - port->addrs.elts = NULL; - - return ngx_rtmp_add_address(cf, cscf, port, lsopt); -} - - -static int ngx_libc_cdecl -ngx_rtmp_cmp_dns_wildcards(const void *one, const void *two) -{ - ngx_hash_key_t *first, *second; - - first = (ngx_hash_key_t *) one; - second = (ngx_hash_key_t *) two; - - return ngx_dns_strcmp(first->key.data, second->key.data); -} - - -static ngx_int_t -ngx_rtmp_server_names(ngx_conf_t *cf, ngx_rtmp_core_main_conf_t *cmcf, - ngx_rtmp_conf_addr_t *addr) -{ - ngx_int_t rc; - ngx_uint_t n, s; - ngx_hash_init_t hash; - ngx_hash_keys_arrays_t ha; - ngx_rtmp_server_name_t *name; - ngx_rtmp_core_srv_conf_t **cscfp; -#if (NGX_PCRE) - ngx_uint_t regex, i; - - regex = 0; -#endif - - ngx_memzero(&ha, sizeof(ngx_hash_keys_arrays_t)); - - ha.temp_pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, cf->log); - if (ha.temp_pool == NULL) { - return NGX_ERROR; - } - - ha.pool = cf->pool; - - if (ngx_hash_keys_array_init(&ha, NGX_HASH_LARGE) != NGX_OK) { - goto failed; - } - - cscfp = addr->servers.elts; - - for (s = 0; s < addr->servers.nelts; s++) { - - name = cscfp[s]->server_names.elts; - - for (n = 0; n < cscfp[s]->server_names.nelts; n++) { - -#if (NGX_PCRE) - if (name[n].regex) { - regex++; - continue; - } -#endif - - rc = ngx_hash_add_key(&ha, &name[n].name, name[n].server, - NGX_HASH_WILDCARD_KEY); - - if (rc == NGX_ERROR) { - return NGX_ERROR; - } - - if (rc == NGX_DECLINED) { - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "invalid server name or wildcard \"%V\" on %s", - &name[n].name, addr->opt.addr); - return NGX_ERROR; - } - - if (rc == NGX_BUSY) { - ngx_log_error(NGX_LOG_WARN, cf->log, 0, - "conflicting server name \"%V\" on %s, ignored", - &name[n].name, addr->opt.addr); - } - } - } - - hash.key = ngx_hash_key_lc; - hash.max_size = cmcf->server_names_hash_max_size; - hash.bucket_size = cmcf->server_names_hash_bucket_size; - hash.name = "rtmp_server_names_hash"; - hash.pool = cf->pool; - - if (ha.keys.nelts) { - hash.hash = &addr->hash; - hash.temp_pool = NULL; - - if (ngx_hash_init(&hash, ha.keys.elts, ha.keys.nelts) != NGX_OK) { - goto failed; - } - } - - if (ha.dns_wc_head.nelts) { - - ngx_qsort(ha.dns_wc_head.elts, (size_t) ha.dns_wc_head.nelts, - sizeof(ngx_hash_key_t), ngx_rtmp_cmp_dns_wildcards); - - hash.hash = NULL; - hash.temp_pool = ha.temp_pool; - - if (ngx_hash_wildcard_init(&hash, ha.dns_wc_head.elts, - ha.dns_wc_head.nelts) - != NGX_OK) - { - goto failed; - } - - addr->wc_head = (ngx_hash_wildcard_t *) hash.hash; - } - - if (ha.dns_wc_tail.nelts) { - - ngx_qsort(ha.dns_wc_tail.elts, (size_t) ha.dns_wc_tail.nelts, - sizeof(ngx_hash_key_t), ngx_rtmp_cmp_dns_wildcards); - - hash.hash = NULL; - hash.temp_pool = ha.temp_pool; - - if (ngx_hash_wildcard_init(&hash, ha.dns_wc_tail.elts, - ha.dns_wc_tail.nelts) - != NGX_OK) - { - goto failed; - } - - addr->wc_tail = (ngx_hash_wildcard_t *) hash.hash; - } - - ngx_destroy_pool(ha.temp_pool); - -#if (NGX_PCRE) - - if (regex == 0) { - return NGX_OK; - } - - addr->nregex = regex; - addr->regex = ngx_palloc(cf->pool, regex * sizeof(ngx_rtmp_server_name_t)); - if (addr->regex == NULL) { - return NGX_ERROR; - } - - i = 0; - - for (s = 0; s < addr->servers.nelts; s++) { - - name = cscfp[s]->server_names.elts; - - for (n = 0; n < cscfp[s]->server_names.nelts; n++) { - if (name[n].regex) { - addr->regex[i++] = name[n]; - } - } - } - -#endif - - return NGX_OK; - -failed: - - ngx_destroy_pool(ha.temp_pool); - - return NGX_ERROR; -} - - -static ngx_listening_t * -ngx_rtmp_add_listening(ngx_conf_t *cf, ngx_rtmp_conf_addr_t *addr) -{ - ngx_listening_t *ls; - - ls = ngx_create_listening(cf, addr->opt.sockaddr, - addr->opt.socklen); - if (ls == NULL) { - return NULL; - } - - ls->addr_ntop = 1; - ls->handler = ngx_rtmp_init_connection; - ls->pool_size = 4096; - - /* TODO: error_log directive */ - ls->logp = &cf->cycle->new_log; - ls->log.data = &ls->addr_text; - ls->log.handler = ngx_accept_log_error; - - ls->keepalive = addr->opt.so_keepalive; -#if (NGX_HAVE_KEEPALIVE_TUNABLE) - ls->keepidle = addr->opt.tcp_keepidle; - ls->keepintvl = addr->opt.tcp_keepintvl; - ls->keepcnt = addr->opt.tcp_keepcnt; -#endif - -#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) - ls->ipv6only = addr->opt.ipv6only; -#endif - -#if (NGX_HAVE_REUSEPORT) - ls->reuseport = addr->opt.reuseport; -#endif - - return ls; -} - - -static ngx_int_t -ngx_rtmp_init_listening(ngx_conf_t *cf, ngx_rtmp_conf_port_t *port) -{ - ngx_uint_t i, last, bind_wildcard; - ngx_listening_t *ls; - ngx_rtmp_port_t *mport; - ngx_rtmp_conf_addr_t *addr; - - addr = port->addrs.elts; - last = port->addrs.nelts; - - /* - * If there is a binding to an "*:port" then we need to bind() to - * the "*:port" only and ignore other implicit bindings. The bindings - * have been already sorted: explicit bindings are on the start, then - * implicit bindings go, and wildcard binding is in the end. - */ - - if (addr[last - 1].opt.wildcard) { - addr[last - 1].opt.bind = 1; - bind_wildcard = 1; - - } else { - bind_wildcard = 0; - } - - i = 0; - - while (i < last) { - - if (bind_wildcard && !addr[i].opt.bind) { - i++; - continue; - } - - ls = ngx_rtmp_add_listening(cf, &addr[i]); - if (ls == NULL) { - return NGX_ERROR; - } - - mport = ngx_palloc(cf->pool, sizeof(ngx_rtmp_port_t)); - if (mport == NULL) { - return NGX_ERROR; - } - - ls->servers = mport; - - if (i == last - 1) { - mport->naddrs = last; - - } else { - mport->naddrs = 1; - i = 0; - } - - switch (ls->sockaddr->sa_family) { -#if (NGX_HAVE_INET6) - case AF_INET6: - if (ngx_rtmp_add_addrs6(cf, mport, addr) != NGX_OK) { - return NGX_ERROR; - } - break; -#endif - default: /* AF_INET */ - if (ngx_rtmp_add_addrs(cf, mport, addr) != NGX_OK) { - return NGX_ERROR; - } - break; - } - -#if nginx_version < 1015002 - if (ngx_clone_listening(cf, ls) != NGX_OK) { -#else - if (ngx_clone_listening(cf->cycle, ls) != NGX_OK) { -#endif - return NGX_ERROR; - } - - addr++; - last--; - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_optimize_servers(ngx_conf_t *cf, ngx_rtmp_core_main_conf_t *cmcf, - ngx_array_t *ports) -{ - ngx_uint_t i, p; - ngx_rtmp_conf_port_t *port; - ngx_rtmp_conf_addr_t *addr; - - if (ports == NULL) { - return NGX_OK; - } - - port = ports->elts; - for (p = 0; p < ports->nelts; p++) { - - ngx_sort(port[p].addrs.elts, (size_t) port[p].addrs.nelts, - sizeof(ngx_rtmp_conf_addr_t), ngx_rtmp_cmp_conf_addrs); - - /* - * check whether all name-based servers have the same - * configuration as a default server for given address:port - */ - - addr = port[p].addrs.elts; - for (i = 0; i < port[p].addrs.nelts; ++i) { - - if (addr[i].servers.nelts > 1 -#if (NGX_PCRE) - || addr[i].default_server->captures -#endif - ) - { - if (ngx_rtmp_server_names(cf, cmcf, &addr[i]) != NGX_OK) { - return NGX_ERROR; - } - } - - if (ngx_rtmp_init_listening(cf, &port[p]) != NGX_OK) { - return NGX_ERROR; - } - } - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_add_addrs(ngx_conf_t *cf, ngx_rtmp_port_t *mport, - ngx_rtmp_conf_addr_t *addr) -{ - u_char *p; - size_t len; - ngx_uint_t i; - ngx_rtmp_in_addr_t *addrs; - struct sockaddr_in *sin; - u_char buf[NGX_SOCKADDR_STRLEN]; - ngx_rtmp_virtual_names_t *vn; - - mport->addrs = ngx_pcalloc(cf->pool, - mport->naddrs * sizeof(ngx_rtmp_in_addr_t)); - if (mport->addrs == NULL) { - return NGX_ERROR; - } - - addrs = mport->addrs; - - for (i = 0; i < mport->naddrs; i++) { - - sin = (struct sockaddr_in *) addr[i].opt.sockaddr; - addrs[i].addr = sin->sin_addr.s_addr; - addrs[i].conf.default_server = addr[i].default_server; - - len = ngx_sock_ntop(addr[i].opt.sockaddr, -#if (nginx_version >= 1005003) - addr[i].opt.socklen, -#endif - buf, NGX_SOCKADDR_STRLEN, 1); - - p = ngx_pnalloc(cf->pool, len); - if (p == NULL) { - return NGX_ERROR; - } - - ngx_memcpy(p, buf, len); - - addrs[i].conf.addr_text.len = len; - addrs[i].conf.addr_text.data = p; - addrs[i].conf.proxy_protocol = addr->opt.proxy_protocol; - - if (addr[i].hash.buckets == NULL - && (addr[i].wc_head == NULL - || addr[i].wc_head->hash.buckets == NULL) - && (addr[i].wc_tail == NULL - || addr[i].wc_tail->hash.buckets == NULL) -#if (NGX_PCRE) - && addr[i].nregex == 0 -#endif - ) - { - continue; - } - - vn = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_virtual_names_t)); - if (vn == NULL) { - return NGX_ERROR; - } - - addrs[i].conf.virtual_names = vn; - - vn->names.hash = addr[i].hash; - vn->names.wc_head = addr[i].wc_head; - vn->names.wc_tail = addr[i].wc_tail; -#if (NGX_PCRE) - vn->nregex = addr[i].nregex; - vn->regex = addr[i].regex; -#endif - } - - return NGX_OK; -} - - -#if (NGX_HAVE_INET6) - -static ngx_int_t -ngx_rtmp_add_addrs6(ngx_conf_t *cf, ngx_rtmp_port_t *mport, - ngx_rtmp_conf_addr_t *addr) -{ - u_char *p; - size_t len; - ngx_uint_t i; - ngx_rtmp_in6_addr_t *addrs6; - struct sockaddr_in6 *sin6; - u_char buf[NGX_SOCKADDR_STRLEN]; - ngx_rtmp_virtual_names_t *vn; - - mport->addrs = ngx_pcalloc(cf->pool, - mport->naddrs * sizeof(ngx_rtmp_in6_addr_t)); - if (mport->addrs == NULL) { - return NGX_ERROR; - } - - addrs6 = mport->addrs; - - for (i = 0; i < mport->naddrs; i++) { - - sin6 = (struct sockaddr_in6 *) addr[i].opt.sockaddr; - addrs6[i].addr6 = sin6->sin6_addr; - addrs6[i].conf.default_server = addr[i].default_server; - - len = ngx_sock_ntop(addr[i].opt.sockaddr, -#if (nginx_version >= 1005003) - addr[i].opt.socklen, -#endif - buf, NGX_SOCKADDR_STRLEN, 1); - - p = ngx_pnalloc(cf->pool, len); - if (p == NULL) { - return NGX_ERROR; - } - - ngx_memcpy(p, buf, len); - - addrs6[i].conf.addr_text.len = len; - addrs6[i].conf.addr_text.data = p; - addrs6[i].conf.proxy_protocol = addr->opt.proxy_protocol; - - if (addr[i].hash.buckets == NULL - && (addr[i].wc_head == NULL - || addr[i].wc_head->hash.buckets == NULL) - && (addr[i].wc_tail == NULL - || addr[i].wc_tail->hash.buckets == NULL) -#if (NGX_PCRE) - && addr[i].nregex == 0 -#endif - ) - { - continue; - } - - vn = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_virtual_names_t)); - if (vn == NULL) { - return NGX_ERROR; - } - - addrs6[i].conf.virtual_names = vn; - - vn->names.hash = addr[i].hash; - vn->names.wc_head = addr[i].wc_head; - vn->names.wc_tail = addr[i].wc_tail; -#if (NGX_PCRE) - vn->nregex = addr[i].nregex; - vn->regex = addr[i].regex; -#endif - } - - return NGX_OK; -} - -#endif - - -static ngx_int_t -ngx_rtmp_cmp_conf_addrs(const void *one, const void *two) -{ - ngx_rtmp_conf_addr_t *first, *second; - - first = (ngx_rtmp_conf_addr_t *) one; - second = (ngx_rtmp_conf_addr_t *) two; - - if (first->opt.wildcard) { - /* a wildcard must be the last resort, shift it to the end */ - return 1; - } - - if (first->opt.bind && !second->opt.bind) { - /* shift explicit bind()ed addresses to the start */ - return -1; - } - - if (!first->opt.bind && second->opt.bind) { - /* shift explicit bind()ed addresses to the start */ - return 1; - } - - /* do not sort by default */ - - return 0; -} - - -ngx_int_t -ngx_rtmp_fire_event(ngx_rtmp_session_t *s, ngx_uint_t evt, - ngx_rtmp_header_t *h, ngx_chain_t *in) -{ - ngx_rtmp_core_main_conf_t *cmcf; - ngx_array_t *ch; - ngx_rtmp_handler_pt *hh; - size_t n; - - cmcf = ngx_rtmp_get_module_main_conf(s, ngx_rtmp_core_module); - - ch = &cmcf->events[evt]; - hh = ch->elts; - for(n = 0; n < ch->nelts; ++n, ++hh) { - if (*hh && (*hh)(s, h, in) != NGX_OK) { - return NGX_ERROR; - } - } - return NGX_OK; -} - - -void * -ngx_rtmp_rmemcpy(void *dst, const void* src, size_t n) -{ - u_char *d, *s; - - d = dst; - s = (u_char*)src + n - 1; - - while(s >= (u_char*)src) { - *d++ = *s--; - } - - return dst; -} - - -ngx_int_t -ngx_rtmp_find_virtual_server(ngx_rtmp_virtual_names_t *virtual_names, - ngx_str_t *host, ngx_rtmp_core_srv_conf_t **cscfp) -{ - ngx_rtmp_core_srv_conf_t *cscf; - - if (virtual_names == NULL) { - return NGX_DECLINED; - } - - cscf = ngx_hash_find_combined(&virtual_names->names, - ngx_hash_key(host->data, host->len), - host->data, host->len); - - if (cscf) { - *cscfp = cscf; - return NGX_OK; - } - -#if (NGX_PCRE) - - if (host->len && virtual_names->nregex) { - ngx_int_t n; - ngx_uint_t i; - ngx_rtmp_server_name_t *sn; - - sn = virtual_names->regex; - - for (i = 0; i < virtual_names->nregex; ++i) { - - n = ngx_regex_exec(sn[i].regex->regex, host, NULL, 0); - - if (n == NGX_REGEX_NO_MATCHED) { - continue; - } - - if (n >= 0) { - *cscfp = sn[i].server; - return NGX_OK; - } - - return NGX_ERROR; - } - } - -#endif - - return NGX_DECLINED; -} - -ngx_int_t -ngx_rtmp_set_virtual_server(ngx_rtmp_session_t *s, ngx_str_t *host) -{ - ngx_int_t rc; - ngx_rtmp_addr_conf_t *addr_conf; - ngx_rtmp_core_srv_conf_t *cscf; - -#if (NGX_SUPPRESS_WARN) - cscf = NULL; -#endif - - addr_conf = s->addr_conf; - - rc = ngx_rtmp_find_virtual_server(addr_conf->virtual_names, host, &cscf); - - if (rc == NGX_ERROR) { - return NGX_ERROR; - } - - if (rc == NGX_DECLINED) { - return NGX_OK; - } - - s->srv_conf = cscf->ctx->srv_conf; - - return NGX_OK; -} - -static ngx_int_t -ngx_rtmp_init_process(ngx_cycle_t *cycle) -{ -#if (nginx_version >= 1007005) - ngx_queue_init(&ngx_rtmp_init_queue); -#endif - return NGX_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp.h deleted file mode 100644 index c5867d8f91..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp.h +++ /dev/null @@ -1,1022 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#ifndef _NGX_RTMP_H_INCLUDED_ -#define _NGX_RTMP_H_INCLUDED_ - - -#include -#include -#include -#include -#include -#include - -#include "ngx_rtmp_amf.h" -#include "ngx_rtmp_bandwidth.h" -#include "ngx_http_client.h" -#include "ngx_netcall.h" -#include "ngx_map.h" - - -#if (NGX_WIN32) -typedef __int8 int8_t; -typedef unsigned __int8 uint8_t; -#endif - - -#if (NGX_PCRE) - -typedef struct { - ngx_uint_t capture; - ngx_int_t index; -} ngx_rtmp_regex_variable_t; - -typedef struct { - ngx_regex_t *regex; - ngx_uint_t ncaptures; - ngx_rtmp_regex_variable_t *variables; - ngx_uint_t nvariables; - ngx_str_t name; -} ngx_rtmp_regex_t; - -typedef struct { - ngx_rtmp_regex_t *regex; - void *value; -} ngx_rtmp_map_regex_t; - -#endif - - -typedef struct { - void **main_conf; - void **srv_conf; - void **app_conf; -} ngx_rtmp_conf_ctx_t; - - -typedef struct { - void *addrs; - ngx_uint_t naddrs; -} ngx_rtmp_port_t; - - -typedef struct { - int family; - in_port_t port; - ngx_array_t addrs; /* array of ngx_rtmp_conf_addr_t */ -} ngx_rtmp_conf_port_t; - - -#define NGX_RTMP_VERSION 3 - -#define NGX_LOG_DEBUG_RTMP NGX_LOG_DEBUG_CORE - -#define NGX_RTMP_DEFAULT_CHUNK_SIZE 128 - - -/* RTMP message types */ -#define NGX_RTMP_MSG_CHUNK_SIZE 1 -#define NGX_RTMP_MSG_ABORT 2 -#define NGX_RTMP_MSG_ACK 3 -#define NGX_RTMP_MSG_USER 4 -#define NGX_RTMP_MSG_ACK_SIZE 5 -#define NGX_RTMP_MSG_BANDWIDTH 6 -#define NGX_RTMP_MSG_EDGE 7 -#define NGX_RTMP_MSG_AUDIO 8 -#define NGX_RTMP_MSG_VIDEO 9 -#define NGX_RTMP_MSG_AMF3_META 15 -#define NGX_RTMP_MSG_AMF3_SHARED 16 -#define NGX_RTMP_MSG_AMF3_CMD 17 -#define NGX_RTMP_MSG_AMF_META 18 -#define NGX_RTMP_MSG_AMF_SHARED 19 -#define NGX_RTMP_MSG_AMF_CMD 20 -#define NGX_RTMP_MSG_AGGREGATE 22 -#define NGX_RTMP_MSG_MAX 22 - -#define NGX_RTMP_CONNECT NGX_RTMP_MSG_MAX + 1 -#define NGX_RTMP_DISCONNECT NGX_RTMP_MSG_MAX + 2 -#define NGX_RTMP_HANDSHAKE_DONE NGX_RTMP_MSG_MAX + 3 -#define NGX_MPEGTS_MSG_AUDIO NGX_RTMP_MSG_MAX + 4 -#define NGX_MPEGTS_MSG_VIDEO NGX_RTMP_MSG_MAX + 5 -#define NGX_MPEGTS_MSG_PATPMT NGX_RTMP_MSG_MAX + 6 -#define NGX_MPEGTS_MSG_M3U8 NGX_RTMP_MSG_MAX + 7 -#define NGX_MPEGTS_MSG_CLOSE NGX_RTMP_MSG_MAX + 8 -#define NGX_RTMP_MAX_EVENT NGX_RTMP_MSG_MAX + 9 - - -/* RMTP control message types */ -#define NGX_RTMP_USER_STREAM_BEGIN 0 -#define NGX_RTMP_USER_STREAM_EOF 1 -#define NGX_RTMP_USER_STREAM_DRY 2 -#define NGX_RTMP_USER_SET_BUFLEN 3 -#define NGX_RTMP_USER_RECORDED 4 -#define NGX_RTMP_USER_PING_REQUEST 6 -#define NGX_RTMP_USER_PING_RESPONSE 7 -#define NGX_RTMP_USER_UNKNOWN 8 -#define NGX_RTMP_USER_BUFFER_END 31 - - -/* Chunk header: - * max 3 basic header - * + max 11 message header - * + max 4 extended header (timestamp) */ -#define NGX_RTMP_MAX_CHUNK_HEADER 18 - -#define IS_IRAP(_nal_type_) (_nal_type_ >= 16 && _nal_type_ <= 23) - -/* Audio codecs */ -enum { - /* Uncompressed codec id is actually 0, - * but we use another value for consistency */ - NGX_RTMP_AUDIO_UNCOMPRESSED = 16, - NGX_RTMP_AUDIO_ADPCM = 1, - NGX_RTMP_AUDIO_MP3 = 2, - NGX_RTMP_AUDIO_LINEAR_LE = 3, - NGX_RTMP_AUDIO_NELLY16 = 4, - NGX_RTMP_AUDIO_NELLY8 = 5, - NGX_RTMP_AUDIO_NELLY = 6, - NGX_RTMP_AUDIO_G711A = 7, - NGX_RTMP_AUDIO_G711U = 8, - NGX_RTMP_AUDIO_AAC = 10, - NGX_RTMP_AUDIO_SPEEX = 11, - NGX_RTMP_AUDIO_MP3_8 = 14, - NGX_RTMP_AUDIO_DEVSPEC = 15, -}; - - -/* Video codecs */ -enum { - NGX_RTMP_VIDEO_JPEG = 1, - NGX_RTMP_VIDEO_SORENSON_H263 = 2, - NGX_RTMP_VIDEO_SCREEN = 3, - NGX_RTMP_VIDEO_ON2_VP6 = 4, - NGX_RTMP_VIDEO_ON2_VP6_ALPHA = 5, - NGX_RTMP_VIDEO_SCREEN2 = 6, - NGX_RTMP_VIDEO_H264 = 7, - NGX_RTMP_VIDEO_H265 = 12 -}; - -extern ngx_int_t NGX_RTMP_HEVC_CODEC_ID; - -typedef struct { - uint32_t csid; /* chunk stream id */ - uint32_t timestamp; /* timestamp (delta) */ - uint32_t mlen; /* message length */ - uint8_t type; /* message type id */ - uint32_t msid; /* message stream id */ -} ngx_rtmp_header_t; - - -typedef struct { - ngx_rtmp_header_t hdr; - uint32_t dtime; - uint32_t len; /* current fragment length */ - uint8_t ext; - ngx_chain_t *in; -} ngx_rtmp_stream_t; - - -typedef struct ngx_rtmp_frame_s ngx_rtmp_frame_t; - -struct ngx_rtmp_frame_s { - ngx_rtmp_header_t hdr; - ngx_flag_t av_header; - ngx_flag_t keyframe; - ngx_flag_t mandatory; - ngx_uint_t ref; - - ngx_rtmp_frame_t *next; - ngx_chain_t *chain; -}; - -typedef struct ngx_mpegts_frame_s ngx_mpegts_frame_t; - -struct ngx_mpegts_frame_s { - uint64_t pts; - uint64_t dts; - ngx_uint_t pid; - ngx_uint_t sid; - ngx_uint_t cc; - unsigned key:1; - ngx_uint_t ref; - - ngx_uint_t type; - ngx_uint_t length; - size_t pos; - - ngx_mpegts_frame_t *next; - ngx_chain_t *chain; -}; - -/* disable zero-sized array warning by msvc */ - -#if (NGX_WIN32) -#pragma warning(push) -#pragma warning(disable:4200) -#endif - -#define NGX_RTMP_LIVE 0 -#define NGX_HTTP_FLV_LIVE 1 -#define NGX_HLS_LIVE 2 -#define NGX_MPEGTS_LIVE 3 - -typedef struct ngx_rtmp_session_s ngx_rtmp_session_t; - -#define NGX_RTMP_MAX_MERGE_FRAME 64 - -typedef ngx_chain_t * (* ngx_rtmp_prepared_pt)(ngx_rtmp_session_t *s); - -typedef struct ngx_live_stream_s ngx_live_stream_t; -typedef struct ngx_live_server_s ngx_live_server_t; -typedef struct ngx_rtmp_addr_conf_s ngx_rtmp_addr_conf_t; - -#define NGX_LIVE_INIT 0 -#define NGX_LIVE_HANDSHAKE_DONE 1 -#define NGX_LIVE_CONNECT 2 -#define NGX_LIVE_CREATE_STREAM 3 -#define NGX_LIVE_PUBLISH 4 -#define NGX_LIVE_PLAY 5 -#define NGX_LIVE_AV 6 -#define NGX_LIVE_CLOSE 7 - -#define NGX_LIVE_INTERNAL_ERR 0 -#define NGX_LIVE_NORMAL_CLOSE 1 -#define NGX_LIVE_RTMP_SEND_ERR 2 -#define NGX_LIVE_RTMP_SEND_TIMEOUT 3 -#define NGX_LIVE_FLV_SEND_ERR 4 -#define NGX_LIVE_FLV_SEND_TIMEOUT 5 -#define NGX_LIVE_RTMP_RECV_ERR 6 -#define NGX_LIVE_FLV_RECV_ERR 7 -#define NGX_LIVE_RELAY_TRANSIT 8 -#define NGX_LIVE_RELAY_TIMEOUT 9 -#define NGX_LIVE_CONTROL_DROP 10 -#define NGX_LIVE_DROP_IDLE 11 -#define NGX_LIVE_OCLP_NOTIFY_ERR 12 -#define NGX_LIVE_OCLP_RELAY_ERR 13 -#define NGX_LIVE_OCLP_PARA_ERR 14 -#define NGX_LIVE_RELAY_CLOSE 15 -#define NGX_LIVE_PROCESS_EXIT 16 - -struct ngx_rtmp_session_s { - ngx_atomic_uint_t number; - struct sockaddr *sockaddr; - ngx_msec_t roll_back; - - unsigned int destroyed:1; - - ngx_flag_t pause; - - ngx_int_t acodec; - ngx_int_t vcodec; - uint32_t signature; /* "RTMP" */ /* <-- FIXME wtf */ - - ngx_event_t close; - - ngx_pool_t *pool; - ngx_log_t *log; - - ngx_rtmp_addr_conf_t *addr_conf; - - void **ctx; - void **main_conf; - void **srv_conf; - void **app_conf; - - ngx_live_server_t *live_server; - ngx_live_stream_t *live_stream; - - ngx_str_t remote_addr_text; - ngx_str_t *addr_text; - int connected; - - ngx_http_variable_value_t *variables; - -#if (NGX_PCRE) - ngx_uint_t ncaptures; - int *captures; - u_char *captures_data; -#endif - -#if (nginx_version >= 1007005) - ngx_queue_t posted_dry_events; -#else - ngx_event_t *posted_dry_events; -#endif - - /* client buffer time in msec */ - uint32_t buflen; - uint32_t ack_size; - - ngx_str_t groupid; - - /* app/name */ - ngx_str_t stream; - - /* stream name in publish or play*/ - ngx_str_t name; - ngx_str_t pargs; /* play or publish args */ - - /* connection parameters */ - ngx_str_t app; - ngx_str_t args; - ngx_str_t flashver; - ngx_str_t swf_url; - ngx_str_t tc_url; - uint32_t acodecs; - uint32_t vcodecs; - ngx_str_t page_url; - - /* middleware */ - ngx_str_t scheme; - ngx_str_t domain; - ngx_str_t serverid; - - /* handshake data */ - ngx_buf_t *hs_buf; - u_char *hs_digest; - unsigned hs_old:1; - ngx_uint_t hs_stage; - - /* connection timestamps */ - ngx_msec_t epoch; - ngx_msec_t peer_epoch; - ngx_msec_t base_time; - uint32_t current_time; - - /* ping */ - ngx_event_t ping_evt; - unsigned ping_active:1; - unsigned ping_reset:1; - - /* auto-pushed? */ - unsigned interprocess:1; - unsigned static_pull:1; - unsigned relay:1; - unsigned played:1; - unsigned published:1; - unsigned closed:1; - unsigned publishing:1; - unsigned finalized:1; - - /* live type: 0- RTMP 1- http-flv 2- hls */ - unsigned live_type:2; - ngx_uint_t status; - ngx_http_request_t *request; - - unsigned flv_state; - - ngx_uint_t flv_version; - ngx_uint_t flv_flags; - unsigned flv_data_offset; - unsigned flv_tagsize; - unsigned flv_first_pts; - - /* input stream 0 (reserved by RTMP spec) - * is used as free chain link */ - - ngx_rtmp_stream_t *in_streams; - uint32_t in_csid; - ngx_uint_t in_chunk_size; - ngx_pool_t *in_pool; - uint32_t in_bytes; - uint32_t in_last_ack; - - ngx_pool_t *in_old_pool; - ngx_int_t in_chunk_size_changing; - - ngx_connection_t *connection; - - /* merge frame and send */ - ngx_mpegts_frame_t *prepare_mpegts_frame[NGX_RTMP_MAX_MERGE_FRAME]; - ngx_rtmp_frame_t *prepare_frame[NGX_RTMP_MAX_MERGE_FRAME]; - ngx_chain_t *merge[NGX_RTMP_MAX_MERGE_FRAME]; - ngx_uint_t nframe; - ngx_rtmp_prepared_pt prepare_handler; - - /* for trace and statistics */ - ngx_int_t notify_status; - ngx_uint_t finalize_reason; - ngx_uint_t stage; - ngx_msec_t init_time; - ngx_msec_t handshake_done_time; - ngx_msec_t connect_time; - ngx_msec_t create_stream_time; - ngx_msec_t ptime; /* publish or play time */ - ngx_msec_t first_data; /* audio video or metadata*/ - ngx_msec_t first_metadata; - ngx_msec_t first_audio; - ngx_msec_t first_video; - ngx_msec_t close_stream_time; - - /* circular buffer of RTMP message pointers */ - ngx_msec_t timeout; - uint32_t out_bytes; - size_t out_pos, out_last; - ngx_chain_t *out_chain; - unsigned out_buffer:1; - size_t out_queue; - size_t out_cork; - ngx_mpegts_frame_t **mpegts_out; - ngx_rtmp_frame_t *out[0]; -}; - -/* live stream manage */ -#define NGX_LIVE_SERVERID_LEN 512 -#define NGX_LIVE_STREAM_LEN 512 - -typedef struct ngx_rtmp_core_ctx_s ngx_rtmp_core_ctx_t; -typedef struct ngx_rtmp_live_ctx_s ngx_rtmp_live_ctx_t; -typedef struct ngx_mpegts_live_ctx_s ngx_mpegts_live_ctx_t; -typedef struct ngx_hls_live_ctx_s ngx_hls_live_ctx_t; - -struct ngx_rtmp_core_ctx_s { - ngx_rtmp_core_ctx_t *next; - ngx_rtmp_session_t *session; - - unsigned publishing:1; -}; - - -#define NGX_RTMP_MAX_OCLP 8 -#define NGX_RTMP_MAX_PUSH 8 - - -struct ngx_live_stream_s { - u_char name[NGX_LIVE_STREAM_LEN]; - - ngx_int_t pslot; - - ngx_rtmp_core_ctx_t *publish_ctx; - ngx_rtmp_core_ctx_t *play_ctx; - - /* notify */ - ngx_netcall_ctx_t *stream_nctx; - - ngx_live_stream_t *next; - - /* for live */ - ngx_map_t pubctx; - ngx_rtmp_live_ctx_t *ctx; - ngx_mpegts_live_ctx_t *mpegts_ctx; - ngx_hls_live_ctx_t *hls_ctx; - ngx_rtmp_bandwidth_t bw_in; - ngx_rtmp_bandwidth_t bw_in_audio; - ngx_rtmp_bandwidth_t bw_in_video; - ngx_rtmp_bandwidth_t bw_out; - ngx_msec_t epoch; - unsigned active:1; - unsigned publishing:1; - unsigned notify_meta:1; -}; - -struct ngx_live_server_s { - u_char serverid[NGX_LIVE_SERVERID_LEN]; - ngx_uint_t n_stream; - ngx_flag_t deleted; - - ngx_live_server_t *next; - - ngx_live_stream_t **streams; -}; - - -ngx_live_server_t *ngx_live_create_server(ngx_str_t *serverid); -ngx_live_server_t *ngx_live_fetch_server(ngx_str_t *serverid); -void ngx_live_delete_server(ngx_str_t *serverid); - -ngx_live_stream_t *ngx_live_create_stream(ngx_str_t *serverid, - ngx_str_t *stream); -ngx_live_stream_t *ngx_live_fetch_stream(ngx_str_t *serverid, - ngx_str_t *stream); -void ngx_live_delete_stream(ngx_str_t *serverid, ngx_str_t *stream); - -void ngx_live_create_ctx(ngx_rtmp_session_t *s, unsigned publishing); -void ngx_live_delete_ctx(ngx_rtmp_session_t *s); - -void ngx_live_print(); - -#if (NGX_WIN32) -#pragma warning(pop) -#endif - - -/* handler result code: - * NGX_ERROR - error - * NGX_OK - success, may continue - * NGX_DONE - success, input parsed, reply sent; need no - * more calls on this event */ -typedef ngx_int_t (*ngx_rtmp_handler_pt)(ngx_rtmp_session_t *s, - ngx_rtmp_header_t *h, ngx_chain_t *in); - - -typedef struct { - ngx_str_t name; - ngx_rtmp_handler_pt handler; -} ngx_rtmp_amf_handler_t; - - -typedef struct { - ngx_flag_t fast_reload; - - ngx_array_t servers; /* ngx_rtmp_core_srv_conf_t */ - - ngx_array_t events[NGX_RTMP_MAX_EVENT]; - - ngx_hash_t amf_hash; - ngx_array_t amf_arrays; - ngx_array_t amf; - - ngx_uint_t server_names_hash_max_size; - ngx_uint_t server_names_hash_bucket_size; - - ngx_hash_t variables_hash; - - ngx_array_t variables; /* ngx_http_variable_t */ - ngx_array_t prefix_variables; /* ngx_http_variable_t */ - ngx_uint_t ncaptures; - - ngx_uint_t variables_hash_max_size; - ngx_uint_t variables_hash_bucket_size; - - ngx_hash_keys_arrays_t *variables_keys; - - ngx_array_t *ports; /* ngx_rtmp_conf_port_t */ -} ngx_rtmp_core_main_conf_t; - - -/* global main conf for stats */ -extern ngx_rtmp_core_main_conf_t *ngx_rtmp_core_main_conf; - - -typedef struct { - ngx_array_t applications; /* ngx_rtmp_core_app_conf_t */ - ngx_str_t name; - ngx_uint_t merge_frame; - ngx_flag_t tcp_nodelay; - void **app_conf; - ngx_uint_t hevc_codec; -} ngx_rtmp_core_app_conf_t; - - -typedef struct ngx_rtmp_core_srv_conf_s { - ngx_array_t applications; /* ngx_rtmp_core_app_conf_t */ - - ngx_rtmp_core_app_conf_t *default_app; - - ngx_msec_t timeout; - ngx_msec_t ping; - ngx_msec_t ping_timeout; - ngx_flag_t so_keepalive; - ngx_int_t max_streams; - - ngx_uint_t ack_window; - - ngx_int_t chunk_size; - ngx_pool_t *pool; - ngx_chain_t *free; - ngx_chain_t *free_hs; - size_t max_message; - ngx_flag_t play_time_fix; - ngx_flag_t publish_time_fix; - ngx_flag_t busy; - size_t out_queue; - size_t out_cork; - ngx_msec_t buflen; - - ngx_rtmp_conf_ctx_t *ctx; - - unsigned listen:1; -#if (NGX_PCRE) - unsigned captures:1; -#endif - - ngx_str_t server_name; - ngx_str_t serverid; - - /* array of the ngx_rtmp_server_name_t, "server_name" directive */ - ngx_array_t server_names; -} ngx_rtmp_core_srv_conf_t; - - -typedef struct { -#if (NGX_PCRE) - ngx_rtmp_regex_t *regex; -#endif - ngx_rtmp_core_srv_conf_t *server; /* virtual name server conf */ - ngx_str_t name; -} ngx_rtmp_server_name_t; - - -typedef struct { - ngx_hash_combined_t names; - - ngx_uint_t nregex; - ngx_rtmp_server_name_t *regex; -} ngx_rtmp_virtual_names_t; - - -struct ngx_rtmp_addr_conf_s { - ngx_rtmp_core_srv_conf_t *default_server; - ngx_rtmp_virtual_names_t *virtual_names; - - ngx_str_t addr_text; - unsigned proxy_protocol:1; -}; - -typedef struct { - in_addr_t addr; - ngx_rtmp_addr_conf_t conf; -} ngx_rtmp_in_addr_t; - - -#if (NGX_HAVE_INET6) - -typedef struct { - struct in6_addr addr6; - ngx_rtmp_addr_conf_t conf; -} ngx_rtmp_in6_addr_t; - -#endif - - -typedef struct { - struct sockaddr *sockaddr; - socklen_t socklen; - - unsigned set:1; - unsigned default_server:1; - unsigned bind:1; - unsigned wildcard:1; -#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) - unsigned ipv6only:2; -#endif - unsigned reuseport:1; - unsigned so_keepalive:2; - unsigned proxy_protocol:1; -#if (NGX_HAVE_KEEPALIVE_TUNABLE) - int tcp_keepidle; - int tcp_keepintvl; - int tcp_keepcnt; -#endif - - u_char addr[NGX_SOCKADDR_STRLEN + 1]; -} ngx_rtmp_listen_opt_t; - - -typedef struct { - ngx_rtmp_listen_opt_t opt; - - ngx_hash_t hash; - ngx_hash_wildcard_t *wc_head; - ngx_hash_wildcard_t *wc_tail; - -#if (NGX_PCRE) - ngx_uint_t nregex; - ngx_rtmp_server_name_t *regex; -#endif - - /* the default server configuration for this address:port */ - ngx_rtmp_core_srv_conf_t *default_server; - ngx_array_t servers; /* array of ngx_http_core_srv_conf_t */ -} ngx_rtmp_conf_addr_t; - - -/* nginx dynamic conf */ -typedef struct { - ngx_str_t serverid; -} ngx_rtmp_core_srv_dconf_t; - - -typedef struct { - ngx_int_t (*preconfiguration)(ngx_conf_t *cf); - ngx_int_t (*postconfiguration)(ngx_conf_t *cf); - - void *(*create_main_conf)(ngx_conf_t *cf); - char *(*init_main_conf)(ngx_conf_t *cf, void *conf); - - void *(*create_srv_conf)(ngx_conf_t *cf); - char *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, - void *conf); - - void *(*create_app_conf)(ngx_conf_t *cf); - char *(*merge_app_conf)(ngx_conf_t *cf, void *prev, - void *conf); -} ngx_rtmp_module_t; - -#define NGX_RTMP_MODULE 0x504D5452 /* "RTMP" */ - -#define NGX_RTMP_MAIN_CONF 0x02000000 -#define NGX_RTMP_SRV_CONF 0x04000000 -#define NGX_RTMP_APP_CONF 0x08000000 -#define NGX_RTMP_REC_CONF 0x10000000 - - -#define NGX_RTMP_MAIN_CONF_OFFSET offsetof(ngx_rtmp_conf_ctx_t, main_conf) -#define NGX_RTMP_SRV_CONF_OFFSET offsetof(ngx_rtmp_conf_ctx_t, srv_conf) -#define NGX_RTMP_APP_CONF_OFFSET offsetof(ngx_rtmp_conf_ctx_t, app_conf) - - -#define ngx_rtmp_get_module_ctx(s, module) (s)->ctx[module.ctx_index] -#define ngx_rtmp_set_ctx(s, c, module) s->ctx[module.ctx_index] = c; -#define ngx_rtmp_delete_ctx(s, module) s->ctx[module.ctx_index] = NULL; - - -#define ngx_rtmp_get_module_main_conf(s, module) \ - (s)->main_conf[module.ctx_index] -#define ngx_rtmp_get_module_srv_conf(s, module) (s)->srv_conf[module.ctx_index] -#define ngx_rtmp_get_module_app_conf(s, module) ((s)->app_conf ? \ - (s)->app_conf[module.ctx_index] : NULL) - -#define ngx_rtmp_conf_get_module_main_conf(cf, module) \ - ((ngx_rtmp_conf_ctx_t *) cf->ctx)->main_conf[module.ctx_index] -#define ngx_rtmp_conf_get_module_srv_conf(cf, module) \ - ((ngx_rtmp_conf_ctx_t *) cf->ctx)->srv_conf[module.ctx_index] -#define ngx_rtmp_conf_get_module_app_conf(cf, module) \ - ((ngx_rtmp_conf_ctx_t *) cf->ctx)->app_conf[module.ctx_index] - -#define ngx_rtmp_cycle_get_module_main_conf(cycle, module) \ - (cycle->conf_ctx[ngx_rtmp_module.index] ? \ - ((ngx_rtmp_conf_ctx_t *) cycle->conf_ctx[ngx_rtmp_module.index]) \ - ->main_conf[module.ctx_index]: \ - NULL) - -/* for virtual server */ -#if (NGX_PCRE) -ngx_rtmp_regex_t *ngx_rtmp_regex_compile(ngx_conf_t *cf, - ngx_regex_compile_t *rc); -ngx_int_t ngx_rtmp_regex_exec(ngx_rtmp_session_t *s, ngx_rtmp_regex_t *re, - ngx_str_t *str); -#endif -ngx_int_t ngx_rtmp_add_listen(ngx_conf_t *cf, ngx_rtmp_core_srv_conf_t *cscf, - ngx_rtmp_listen_opt_t *lsopt); -ngx_int_t ngx_rtmp_set_virtual_server(ngx_rtmp_session_t *s, ngx_str_t *host); - - -#ifdef NGX_DEBUG -char* ngx_rtmp_message_type(uint8_t type); -char* ngx_rtmp_user_message_type(uint16_t evt); -#endif - - -typedef struct { - ngx_array_t urls; // ngx_live_relay_url_t - - ngx_str_t domain; - ngx_str_t app; - ngx_str_t name; - ngx_str_t pargs; - ngx_str_t referer; // rtmp page_url - ngx_str_t user_agent; // rtmp flashver - - ngx_str_t stream; - - void *tag; // module create relay -} ngx_live_relay_t; - - -void ngx_rtmp_init_connection(ngx_connection_t *c); -ngx_rtmp_session_t *ngx_rtmp_create_session(ngx_rtmp_addr_conf_t *addr_conf); -ngx_rtmp_session_t *ngx_rtmp_create_relay_session(ngx_rtmp_session_t *s, - void *tag); -ngx_rtmp_session_t *ngx_rtmp_create_static_session(ngx_live_relay_t *relay, - ngx_rtmp_addr_conf_t *addr_conf, void *tag); - -void ngx_rtmp_set_combined_log(ngx_rtmp_session_t *s, void *d, - ngx_log_handler_pt h); -void ngx_rtmp_init_session(ngx_rtmp_session_t *s, ngx_connection_t *c); -void ngx_rtmp_finalize_session(ngx_rtmp_session_t *s); -void ngx_rtmp_finalize_fake_session(ngx_rtmp_session_t *s); -void ngx_rtmp_handshake(ngx_rtmp_session_t *s); -void ngx_rtmp_client_handshake(ngx_rtmp_session_t *s, unsigned async); -void ngx_rtmp_free_handshake_buffers(ngx_rtmp_session_t *s); -void ngx_rtmp_cycle(ngx_rtmp_session_t *s); -void ngx_rtmp_reset_ping(ngx_rtmp_session_t *s); -ngx_int_t ngx_rtmp_fire_event(ngx_rtmp_session_t *s, ngx_uint_t evt, - ngx_rtmp_header_t *h, ngx_chain_t *in); - -ngx_int_t ngx_rtmp_set_chunk_size(ngx_rtmp_session_t *s, ngx_uint_t size); - - -/* Bit reverse: we need big-endians in many places */ -void * ngx_rtmp_rmemcpy(void *dst, const void* src, size_t n); - -#define ngx_rtmp_rcpymem(dst, src, n) \ - (((u_char*)ngx_rtmp_rmemcpy(dst, src, n)) + (n)) - - -static ngx_inline uint16_t -ngx_rtmp_r16(uint16_t n) -{ - return (n << 8) | (n >> 8); -} - - -static ngx_inline uint32_t -ngx_rtmp_r32(uint32_t n) -{ - return (n << 24) | ((n << 8) & 0xff0000) | ((n >> 8) & 0xff00) | (n >> 24); -} - - -static ngx_inline uint64_t -ngx_rtmp_r64(uint64_t n) -{ - return (uint64_t) ngx_rtmp_r32((uint32_t) n) << 32 | - ngx_rtmp_r32((uint32_t) (n >> 32)); -} - - -ngx_int_t -ngx_rtmp_find_virtual_server(ngx_rtmp_virtual_names_t *virtual_names, - ngx_str_t *host, ngx_rtmp_core_srv_conf_t **cscfp); - -/* Receiving messages */ -ngx_int_t ngx_rtmp_receive_message(ngx_rtmp_session_t *s, - ngx_rtmp_header_t *h, ngx_chain_t *in); -ngx_int_t ngx_rtmp_protocol_message_handler(ngx_rtmp_session_t *s, - ngx_rtmp_header_t *h, ngx_chain_t *in); -ngx_int_t ngx_rtmp_user_message_handler(ngx_rtmp_session_t *s, - ngx_rtmp_header_t *h, ngx_chain_t *in); -ngx_int_t ngx_rtmp_aggregate_message_handler(ngx_rtmp_session_t *s, - ngx_rtmp_header_t *h, ngx_chain_t *in); -ngx_int_t ngx_rtmp_amf_message_handler(ngx_rtmp_session_t *s, - ngx_rtmp_header_t *h, ngx_chain_t *in); -ngx_int_t ngx_rtmp_amf_shared_object_handler(ngx_rtmp_session_t *s, - ngx_rtmp_header_t *h, ngx_chain_t *in); - - -/* Shared output buffers */ - -ngx_int_t ngx_rtmp_prepare_merge_frame(ngx_rtmp_session_t *s); -void ngx_rtmp_free_merge_frame(ngx_rtmp_session_t *s); - -void ngx_rtmp_shared_append_chain(ngx_rtmp_frame_t *frame, size_t size, - ngx_chain_t *cl, ngx_flag_t mandatory); -ngx_rtmp_frame_t *ngx_rtmp_shared_alloc_frame(size_t size, ngx_chain_t *cl, - ngx_flag_t mandatory); -void ngx_rtmp_shared_free_frame(ngx_rtmp_frame_t *frame); - -#define ngx_rtmp_shared_acquire_frame(frame) ++frame->ref; - -ngx_chain_t *ngx_rtmp_shared_state(ngx_http_request_t *r); - -void ngx_mpegts_shared_append_chain(ngx_mpegts_frame_t *frame, ngx_chain_t *cl, - ngx_flag_t mandatory); -ngx_mpegts_frame_t *ngx_rtmp_shared_alloc_mpegts_frame(ngx_chain_t *cl, - ngx_flag_t mandatory); -void ngx_rtmp_shared_free_mpegts_frame(ngx_mpegts_frame_t *frame); - -#define ngx_rtmp_shared_acquire_mpegts_frame(frame) ++frame->ref; - -/* Sending messages */ -ngx_int_t ngx_rtmp_send_message(ngx_rtmp_session_t *s, ngx_rtmp_frame_t *out, - ngx_uint_t priority); - -/* GOP */ -ngx_int_t ngx_rtmp_gop_cache(ngx_rtmp_session_t *s, ngx_rtmp_frame_t *frame); -ngx_int_t ngx_rtmp_gop_send(ngx_rtmp_session_t *s, ngx_rtmp_session_t *ss); - -/* RTMP Relation server */ -ngx_rtmp_addr_conf_t *ngx_rtmp_find_related_addr_conf(ngx_cycle_t *cycle, - ngx_str_t *addr); - -/* core */ -ngx_int_t ngx_rtmp_arg(ngx_rtmp_session_t *s, u_char *name, size_t len, - ngx_str_t *value); - -/* Note on priorities: - * the bigger value the lower the priority. - * priority=0 is the highest */ - - -#define NGX_RTMP_LIMIT_SOFT 0 -#define NGX_RTMP_LIMIT_HARD 1 -#define NGX_RTMP_LIMIT_DYNAMIC 2 - -/* Protocol control messages */ -ngx_rtmp_frame_t *ngx_rtmp_create_chunk_size(ngx_rtmp_session_t *s, - uint32_t chunk_size); -ngx_rtmp_frame_t *ngx_rtmp_create_abort(ngx_rtmp_session_t *s, - uint32_t csid); -ngx_rtmp_frame_t *ngx_rtmp_create_ack(ngx_rtmp_session_t *s, - uint32_t seq); -ngx_rtmp_frame_t *ngx_rtmp_create_ack_size(ngx_rtmp_session_t *s, - uint32_t ack_size); -ngx_rtmp_frame_t *ngx_rtmp_create_bandwidth(ngx_rtmp_session_t *s, - uint32_t ack_size, uint8_t limit_type); - -ngx_int_t ngx_rtmp_send_chunk_size(ngx_rtmp_session_t *s, - uint32_t chunk_size); -ngx_int_t ngx_rtmp_send_abort(ngx_rtmp_session_t *s, - uint32_t csid); -ngx_int_t ngx_rtmp_send_ack(ngx_rtmp_session_t *s, - uint32_t seq); -ngx_int_t ngx_rtmp_send_ack_size(ngx_rtmp_session_t *s, - uint32_t ack_size); -ngx_int_t ngx_rtmp_send_bandwidth(ngx_rtmp_session_t *s, - uint32_t ack_size, uint8_t limit_type); - -/* User control messages */ -ngx_rtmp_frame_t *ngx_rtmp_create_stream_begin(ngx_rtmp_session_t *s, - uint32_t msid); -ngx_rtmp_frame_t *ngx_rtmp_create_stream_eof(ngx_rtmp_session_t *s, - uint32_t msid); -ngx_rtmp_frame_t *ngx_rtmp_create_stream_dry(ngx_rtmp_session_t *s, - uint32_t msid); -ngx_rtmp_frame_t *ngx_rtmp_create_set_buflen(ngx_rtmp_session_t *s, - uint32_t msid, uint32_t buflen_msec); -ngx_rtmp_frame_t *ngx_rtmp_create_recorded(ngx_rtmp_session_t *s, - uint32_t msid); -ngx_rtmp_frame_t *ngx_rtmp_create_ping_request(ngx_rtmp_session_t *s, - uint32_t timestamp); -ngx_rtmp_frame_t *ngx_rtmp_create_ping_response(ngx_rtmp_session_t *s, - uint32_t timestamp); - -ngx_int_t ngx_rtmp_send_stream_begin(ngx_rtmp_session_t *s, - uint32_t msid); -ngx_int_t ngx_rtmp_send_stream_eof(ngx_rtmp_session_t *s, - uint32_t msid); -ngx_int_t ngx_rtmp_send_stream_dry(ngx_rtmp_session_t *s, - uint32_t msid); -ngx_int_t ngx_rtmp_send_set_buflen(ngx_rtmp_session_t *s, - uint32_t msid, uint32_t buflen_msec); -ngx_int_t ngx_rtmp_send_recorded(ngx_rtmp_session_t *s, - uint32_t msid); -ngx_int_t ngx_rtmp_send_ping_request(ngx_rtmp_session_t *s, - uint32_t timestamp); -ngx_int_t ngx_rtmp_send_ping_response(ngx_rtmp_session_t *s, - uint32_t timestamp); - -/* AMF sender/receiver */ -ngx_int_t ngx_rtmp_append_amf(ngx_rtmp_session_t *s, - ngx_chain_t **first, ngx_chain_t **last, - ngx_rtmp_amf_elt_t *elts, size_t nelts); -ngx_int_t ngx_rtmp_receive_amf(ngx_rtmp_session_t *s, ngx_chain_t *in, - ngx_rtmp_amf_elt_t *elts, size_t nelts); - -ngx_rtmp_frame_t *ngx_rtmp_create_amf(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_rtmp_amf_elt_t *elts, size_t nelts); -ngx_int_t ngx_rtmp_send_amf(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_rtmp_amf_elt_t *elts, size_t nelts); - -/* AMF status sender */ -ngx_rtmp_frame_t *ngx_rtmp_create_error(ngx_rtmp_session_t *s, char *code, - char* level, char *desc); -ngx_rtmp_frame_t *ngx_rtmp_create_status(ngx_rtmp_session_t *s, char *code, - char* level, char *desc); -ngx_rtmp_frame_t *ngx_rtmp_create_play_status(ngx_rtmp_session_t *s, char *code, - char* level, ngx_uint_t duration, ngx_uint_t bytes); -ngx_rtmp_frame_t *ngx_rtmp_create_sample_access(ngx_rtmp_session_t *s); - -ngx_int_t ngx_rtmp_send_error(ngx_rtmp_session_t *s, char *code, - char* level, char *desc); -ngx_int_t ngx_rtmp_send_status(ngx_rtmp_session_t *s, char *code, - char* level, char *desc); -ngx_int_t ngx_rtmp_send_play_status(ngx_rtmp_session_t *s, char *code, - char* level, ngx_uint_t duration, ngx_uint_t bytes); -ngx_int_t ngx_rtmp_send_sample_access(ngx_rtmp_session_t *s); -void ngx_rtmp_mpegts_mux(ngx_rtmp_session_t *s); - - -/* Frame types */ -#define NGX_RTMP_VIDEO_KEY_FRAME 1 -#define NGX_RTMP_VIDEO_INTER_FRAME 2 -#define NGX_RTMP_VIDEO_DISPOSABLE_FRAME 3 - - -static ngx_inline ngx_int_t -ngx_rtmp_get_video_frame_type(ngx_chain_t *in) -{ - return (in->buf->pos[0] & 0xf0) >> 4; -} - - -static ngx_inline ngx_int_t -ngx_rtmp_is_codec_header(ngx_chain_t *in) -{ - return in->buf->pos + 1 < in->buf->last && in->buf->pos[1] == 0; -} - - -extern ngx_rtmp_bandwidth_t ngx_rtmp_bw_out; -extern ngx_rtmp_bandwidth_t ngx_rtmp_bw_in; - - -extern ngx_uint_t ngx_rtmp_naccepted; -#if (nginx_version >= 1007011) -extern ngx_queue_t ngx_rtmp_init_queue; -#elif (nginx_version >= 1007005) -extern ngx_thread_volatile ngx_queue_t ngx_rtmp_init_queue; -#else -extern ngx_thread_volatile ngx_event_t *ngx_rtmp_init_queue; -#endif - -extern ngx_uint_t ngx_rtmp_max_module; -extern ngx_module_t ngx_rtmp_module; -extern ngx_module_t ngx_rtmp_core_module; - -#endif /* _NGX_RTMP_H_INCLUDED_ */ diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_access_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_access_module.c deleted file mode 100644 index 55b5d0350e..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_access_module.c +++ /dev/null @@ -1,482 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include -#include "ngx_rtmp.h" -#include "ngx_rtmp_cmd_module.h" - - -static ngx_rtmp_publish_pt next_publish; -static ngx_rtmp_play_pt next_play; - - -#define NGX_RTMP_ACCESS_PUBLISH 0x01 -#define NGX_RTMP_ACCESS_PLAY 0x02 - - -static char * ngx_rtmp_access_rule(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); -static ngx_int_t ngx_rtmp_access_postconfiguration(ngx_conf_t *cf); -static void * ngx_rtmp_access_create_app_conf(ngx_conf_t *cf); -static char * ngx_rtmp_access_merge_app_conf(ngx_conf_t *cf, - void *parent, void *child); - - -typedef struct { - in_addr_t mask; - in_addr_t addr; - ngx_uint_t deny; - ngx_uint_t flags; -} ngx_rtmp_access_rule_t; - - -#if (NGX_HAVE_INET6) - -typedef struct { - struct in6_addr addr; - struct in6_addr mask; - ngx_uint_t deny; - ngx_uint_t flags; -} ngx_rtmp_access_rule6_t; - -#endif - - -typedef struct { - ngx_array_t rules; /* array of ngx_rtmp_access_rule_t */ -#if (NGX_HAVE_INET6) - ngx_array_t rules6; /* array of ngx_rtmp_access_rule6_t */ -#endif -} ngx_rtmp_access_app_conf_t; - - -static ngx_command_t ngx_rtmp_access_commands[] = { - - { ngx_string("allow"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE12, - ngx_rtmp_access_rule, - NGX_RTMP_APP_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("deny"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE12, - ngx_rtmp_access_rule, - NGX_RTMP_APP_CONF_OFFSET, - 0, - NULL }, - - ngx_null_command -}; - - -static ngx_rtmp_module_t ngx_rtmp_access_module_ctx = { - NULL, /* preconfiguration */ - ngx_rtmp_access_postconfiguration, /* postconfiguration */ - NULL, /* create main configuration */ - NULL, /* init main configuration */ - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - ngx_rtmp_access_create_app_conf, /* create app configuration */ - ngx_rtmp_access_merge_app_conf, /* merge app configuration */ -}; - - -ngx_module_t ngx_rtmp_access_module = { - NGX_MODULE_V1, - &ngx_rtmp_access_module_ctx, /* module context */ - ngx_rtmp_access_commands, /* module directives */ - NGX_RTMP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void * -ngx_rtmp_access_create_app_conf(ngx_conf_t *cf) -{ - ngx_rtmp_access_app_conf_t *aacf; - - aacf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_access_app_conf_t)); - if (aacf == NULL) { - return NULL; - } - - if (ngx_array_init(&aacf->rules, cf->pool, 1, - sizeof(ngx_rtmp_access_rule_t)) - != NGX_OK) - { - return NULL; - } - -#if (NGX_HAVE_INET6) - if (ngx_array_init(&aacf->rules6, cf->pool, 1, - sizeof(ngx_rtmp_access_rule6_t)) - != NGX_OK) - { - return NULL; - } -#endif - - return aacf; -} - - -static ngx_int_t -ngx_rtmp_access_merge_rules(ngx_array_t *prev, ngx_array_t *rules) -{ - void *p; - - if (prev->nelts == 0) { - return NGX_OK; - } - - if (rules->nelts == 0) { - *rules = *prev; - return NGX_OK; - } - - p = ngx_array_push_n(rules, prev->nelts); - if (p == NULL) { - return NGX_ERROR; - } - - ngx_memcpy(p, prev->elts, prev->size * prev->nelts); - - return NGX_OK; -} - - -static char * -ngx_rtmp_access_merge_app_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_rtmp_access_app_conf_t *prev = parent; - ngx_rtmp_access_app_conf_t *conf = child; - - if (ngx_rtmp_access_merge_rules(&prev->rules, &conf->rules) != NGX_OK) { - return NGX_CONF_ERROR; - } - -#if (NGX_HAVE_INET6) - if (ngx_rtmp_access_merge_rules(&prev->rules6, &conf->rules6) != NGX_OK) { - return NGX_CONF_ERROR; - } -#endif - - return NGX_CONF_OK; -} - - -static ngx_int_t -ngx_rtmp_access_found(ngx_rtmp_session_t *s, ngx_uint_t deny) -{ - if (deny) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "access forbidden by rule"); - return NGX_ERROR; - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_access_inet(ngx_rtmp_session_t *s, in_addr_t addr, ngx_uint_t flag) -{ - ngx_uint_t i; - ngx_rtmp_access_rule_t *rule; - ngx_rtmp_access_app_conf_t *ascf; - - ascf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_access_module); - - rule = ascf->rules.elts; - for (i = 0; i < ascf->rules.nelts; i++) { - - ngx_log_debug3(NGX_LOG_DEBUG_HTTP, s->log, 0, - "access: %08XD %08XD %08XD", - addr, rule[i].mask, rule[i].addr); - - if ((addr & rule[i].mask) == rule[i].addr && (flag & rule[i].flags)) { - return ngx_rtmp_access_found(s, rule[i].deny); - } - } - - return NGX_OK; -} - - -#if (NGX_HAVE_INET6) - -static ngx_int_t -ngx_rtmp_access_inet6(ngx_rtmp_session_t *s, u_char *p, ngx_uint_t flag) -{ - ngx_uint_t n; - ngx_uint_t i; - ngx_rtmp_access_rule6_t *rule6; - ngx_rtmp_access_app_conf_t *ascf; - - ascf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_access_module); - - rule6 = ascf->rules6.elts; - for (i = 0; i < ascf->rules6.nelts; i++) { - -#if (NGX_DEBUG) - { - size_t cl, ml, al; - u_char ct[NGX_INET6_ADDRSTRLEN]; - u_char mt[NGX_INET6_ADDRSTRLEN]; - u_char at[NGX_INET6_ADDRSTRLEN]; - - cl = ngx_inet6_ntop(p, ct, NGX_INET6_ADDRSTRLEN); - ml = ngx_inet6_ntop(rule6[i].mask.s6_addr, mt, NGX_INET6_ADDRSTRLEN); - al = ngx_inet6_ntop(rule6[i].addr.s6_addr, at, NGX_INET6_ADDRSTRLEN); - - ngx_log_debug6(NGX_LOG_DEBUG_HTTP, s->log, 0, - "access: %*s %*s %*s", cl, ct, ml, mt, al, at); - } -#endif - - for (n = 0; n < 16; n++) { - if ((p[n] & rule6[i].mask.s6_addr[n]) != rule6[i].addr.s6_addr[n]) { - goto next; - } - } - - if (flag & rule6[i].flags) { - return ngx_rtmp_access_found(s, rule6[i].deny); - } - - next: - continue; - } - - return NGX_OK; -} - -#endif - - -static ngx_int_t -ngx_rtmp_access(ngx_rtmp_session_t *s, ngx_uint_t flag) -{ - struct sockaddr_in *sin; - ngx_rtmp_access_app_conf_t *ascf; -#if (NGX_HAVE_INET6) - u_char *p; - in_addr_t addr; - struct sockaddr_in6 *sin6; -#endif - - ascf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_access_module); - if (ascf == NULL) { - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, s->log, 0, - "access: NULL app conf"); - return NGX_ERROR; - } - - /* relay etc */ - if (s->sockaddr == NULL) { - return NGX_OK; - } - - switch (s->sockaddr->sa_family) { - - case AF_INET: - sin = (struct sockaddr_in *) s->sockaddr; - return ngx_rtmp_access_inet(s, sin->sin_addr.s_addr, flag); - -#if (NGX_HAVE_INET6) - - case AF_INET6: - sin6 = (struct sockaddr_in6 *) s->sockaddr; - p = sin6->sin6_addr.s6_addr; - - if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { - addr = p[12] << 24; - addr += p[13] << 16; - addr += p[14] << 8; - addr += p[15]; - return ngx_rtmp_access_inet(s, htonl(addr), flag); - } - - return ngx_rtmp_access_inet6(s, p, flag); - -#endif - } - - return NGX_OK; -} - - -static char * -ngx_rtmp_access_rule(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_rtmp_access_app_conf_t *ascf = conf; - - ngx_int_t rc; - ngx_uint_t all; - ngx_str_t *value; - ngx_cidr_t cidr; - ngx_rtmp_access_rule_t *rule; -#if (NGX_HAVE_INET6) - ngx_rtmp_access_rule6_t *rule6; -#endif - size_t n; - ngx_uint_t flags; - - ngx_memzero(&cidr, sizeof(ngx_cidr_t)); - - value = cf->args->elts; - - n = 1; - flags = 0; - - if (cf->args->nelts == 2) { - - flags = NGX_RTMP_ACCESS_PUBLISH | NGX_RTMP_ACCESS_PLAY; - - } else { - - for(; n < cf->args->nelts - 1; ++n) { - - if (value[n].len == sizeof("publish") - 1 && - ngx_strcmp(value[1].data, "publish") == 0) - { - flags |= NGX_RTMP_ACCESS_PUBLISH; - continue; - - } - - if (value[n].len == sizeof("play") - 1 && - ngx_strcmp(value[1].data, "play") == 0) - { - flags |= NGX_RTMP_ACCESS_PLAY; - continue; - - } - - ngx_log_error(NGX_LOG_ERR, cf->log, 0, - "unexpected access specified: '%V'", &value[n]); - return NGX_CONF_ERROR; - } - } - - all = (value[n].len == 3 && ngx_strcmp(value[n].data, "all") == 0); - - if (!all) { - - rc = ngx_ptocidr(&value[n], &cidr); - - if (rc == NGX_ERROR) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid parameter \"%V\"", &value[1]); - return NGX_CONF_ERROR; - } - - if (rc == NGX_DONE) { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, - "low address bits of %V are meaningless", - &value[1]); - } - } - - switch (cidr.family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - case 0: /* all */ - - rule6 = ngx_array_push(&ascf->rules6); - if (rule6 == NULL) { - return NGX_CONF_ERROR; - } - - rule6->mask = cidr.u.in6.mask; - rule6->addr = cidr.u.in6.addr; - rule6->deny = (value[0].data[0] == 'd') ? 1 : 0; - rule6->flags = flags; - - if (!all) { - break; - } - - rule = ngx_array_push(&ascf->rules); - if (rule == NULL) { - return NGX_CONF_ERROR; - } - - rule->mask = cidr.u.in.mask; - rule->addr = cidr.u.in.addr; - rule->deny = (value[0].data[0] == 'd') ? 1 : 0; - rule->flags = flags; - - break; - /* "all" passes through */ -#endif - - default: /* AF_INET */ - - rule = ngx_array_push(&ascf->rules); - if (rule == NULL) { - return NGX_CONF_ERROR; - } - - rule->mask = cidr.u.in.mask; - rule->addr = cidr.u.in.addr; - rule->deny = (value[0].data[0] == 'd') ? 1 : 0; - rule->flags = flags; - } - - return NGX_CONF_OK; -} - - -static ngx_int_t -ngx_rtmp_access_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v) -{ - if (s->interprocess) { - goto next; - } - - if (ngx_rtmp_access(s, NGX_RTMP_ACCESS_PUBLISH) != NGX_OK) { - return NGX_ERROR; - } - -next: - return next_publish(s, v); -} - - -static ngx_int_t -ngx_rtmp_access_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v) -{ - if (ngx_rtmp_access(s, NGX_RTMP_ACCESS_PLAY) != NGX_OK) { - return NGX_ERROR; - } - - return next_play(s, v); -} - - -static ngx_int_t -ngx_rtmp_access_postconfiguration(ngx_conf_t *cf) -{ - /* chain handlers */ - next_publish = ngx_rtmp_publish; - ngx_rtmp_publish = ngx_rtmp_access_publish; - - next_play = ngx_rtmp_play; - ngx_rtmp_play = ngx_rtmp_access_play; - - return NGX_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_amf.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_amf.c deleted file mode 100644 index 77521ecea9..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_amf.c +++ /dev/null @@ -1,664 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include -#include "ngx_rtmp_amf.h" -#include "ngx_rtmp.h" -#include - - -static ngx_inline void* -ngx_rtmp_amf_reverse_copy(void *dst, void* src, size_t len) -{ - size_t k; - - if (dst == NULL || src == NULL) { - return NULL; - } - - for(k = 0; k < len; ++k) { - ((u_char*)dst)[k] = ((u_char*)src)[len - 1 - k]; - } - - return dst; -} - -#define NGX_RTMP_AMF_DEBUG_SIZE 16 - -#ifdef NGX_DEBUG -static void -ngx_rtmp_amf_debug(const char* op, ngx_log_t *log, u_char *p, size_t n) -{ - u_char hstr[3 * NGX_RTMP_AMF_DEBUG_SIZE + 1]; - u_char str[NGX_RTMP_AMF_DEBUG_SIZE + 1]; - u_char *hp, *sp; - static u_char hex[] = "0123456789ABCDEF"; - size_t i; - - hp = hstr; - sp = str; - - for(i = 0; i < n && i < NGX_RTMP_AMF_DEBUG_SIZE; ++i) { - *hp++ = ' '; - if (p) { - *hp++ = hex[(*p & 0xf0) >> 4]; - *hp++ = hex[*p & 0x0f]; - *sp++ = (*p >= 0x20 && *p <= 0x7e) ? - *p : (u_char)'?'; - ++p; - } else { - *hp++ = 'X'; - *hp++ = 'X'; - *sp++ = '?'; - } - } - *hp = *sp = '\0'; - - ngx_log_debug4(NGX_LOG_DEBUG_RTMP, log, 0, - "AMF %s (%d)%s '%s'", op, n, hstr, str); -} -#endif - -static ngx_int_t -ngx_rtmp_amf_get(ngx_rtmp_amf_ctx_t *ctx, void *p, size_t n) -{ - size_t size; - ngx_chain_t *l; - size_t offset; - u_char *pos, *last; -#ifdef NGX_DEBUG - void *op = p; - size_t on = n; -#endif - - if (!n) - return NGX_OK; - - for(l = ctx->link, offset = ctx->offset; l; l = l->next, offset = 0) { - - pos = l->buf->pos + offset; - last = l->buf->last; - - if (last >= pos + n) { - if (p) { - p = ngx_cpymem(p, pos, n); - } - ctx->offset = offset + n; - ctx->link = l; - -#ifdef NGX_DEBUG - ngx_rtmp_amf_debug("read", ctx->log, (u_char*)op, on); -#endif - - return NGX_OK; - } - - size = last - pos; - - if (p) { - p = ngx_cpymem(p, pos, size); - } - - n -= size; - } - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, ctx->log, 0, - "AMF read eof (%d)", n); - - return NGX_DONE; -} - - -static ngx_int_t -ngx_rtmp_amf_put(ngx_rtmp_amf_ctx_t *ctx, void *p, size_t n) -{ - ngx_buf_t *b; - size_t size; - ngx_chain_t *l, *ln; - -#ifdef NGX_DEBUG - ngx_rtmp_amf_debug("write", ctx->log, (u_char*)p, n); -#endif - - l = ctx->link; - - if (ctx->link && ctx->first == NULL) { - ctx->first = ctx->link; - } - - while(n) { - b = l ? l->buf : NULL; - - if (b == NULL || b->last == b->end) { - - ln = ctx->alloc(ctx->arg); - if (ln == NULL) { - return NGX_ERROR; - } - - if (ctx->first == NULL) { - ctx->first = ln; - } - - if (l) { - l->next = ln; - } - - l = ln; - ctx->link = l; - b = l->buf; - } - - size = b->end - b->last; - - if (size >= n) { - b->last = ngx_cpymem(b->last, p, n); - return NGX_OK; - } - - b->last = ngx_cpymem(b->last, p, size); - p = (u_char*)p + size; - n -= size; - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_amf_read_object(ngx_rtmp_amf_ctx_t *ctx, ngx_rtmp_amf_elt_t *elts, - size_t nelts) -{ - uint8_t type; - uint16_t len; - size_t n, namelen, maxlen; - ngx_int_t rc; - u_char buf[2]; - - maxlen = 0; - for(n = 0; n < nelts; ++n) { - namelen = elts[n].name.len; - if (namelen > maxlen) - maxlen = namelen; - } - - for( ;; ) { - -#if !(NGX_WIN32) - char name[maxlen]; -#else - char name[1024]; - if (maxlen > sizeof(name)) { - return NGX_ERROR; - } -#endif - /* read key */ - switch (ngx_rtmp_amf_get(ctx, buf, 2)) { - case NGX_DONE: - /* Envivio sends unfinalized arrays */ - return NGX_OK; - case NGX_OK: - break; - default: - return NGX_ERROR; - } - - ngx_rtmp_amf_reverse_copy(&len, buf, 2); - - if (!len) - break; - - if (len <= maxlen) { - rc = ngx_rtmp_amf_get(ctx, name, len); - - } else { - rc = ngx_rtmp_amf_get(ctx, name, maxlen); - if (rc != NGX_OK) - return NGX_ERROR; - rc = ngx_rtmp_amf_get(ctx, 0, len - maxlen); - } - - if (rc != NGX_OK) - return NGX_ERROR; - - /* TODO: if we require array to be sorted on name - * then we could be able to use binary search */ - for(n = 0; n < nelts - && (len != elts[n].name.len - || ngx_strncmp(name, elts[n].name.data, len)); - ++n); - - if (ngx_rtmp_amf_read(ctx, n < nelts ? &elts[n] : NULL, 1) != NGX_OK) - return NGX_ERROR; - } - - if (ngx_rtmp_amf_get(ctx, &type, 1) != NGX_OK - || type != NGX_RTMP_AMF_END) - { - return NGX_ERROR; - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_amf_read_array(ngx_rtmp_amf_ctx_t *ctx, ngx_rtmp_amf_elt_t *elts, - size_t nelts) -{ - uint32_t len; - size_t n; - u_char buf[4]; - - /* read length */ - if (ngx_rtmp_amf_get(ctx, buf, 4) != NGX_OK) - return NGX_ERROR; - - ngx_rtmp_amf_reverse_copy(&len, buf, 4); - - for (n = 0; n < len; ++n) { - if (ngx_rtmp_amf_read(ctx, n < nelts ? &elts[n] : NULL, 1) != NGX_OK) - return NGX_ERROR; - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_amf_read_variant(ngx_rtmp_amf_ctx_t *ctx, ngx_rtmp_amf_elt_t *elts, - size_t nelts) -{ - uint8_t type; - ngx_int_t rc; - size_t n; - ngx_rtmp_amf_elt_t elt; - - rc = ngx_rtmp_amf_get(ctx, &type, 1); - if (rc != NGX_OK) { - return rc; - } - - ngx_memzero(&elt, sizeof(elt)); - for (n = 0; n < nelts; ++n, ++elts) { - if (type == elts->type) { - elt.data = elts->data; - elt.len = elts->len; - } - } - - elt.type = type | NGX_RTMP_AMF_TYPELESS; - - return ngx_rtmp_amf_read(ctx, &elt, 1); -} - - -static ngx_int_t -ngx_rtmp_amf_is_compatible_type(uint8_t t1, uint8_t t2) -{ - return t1 == t2 - || (t1 == NGX_RTMP_AMF_OBJECT && t2 == NGX_RTMP_AMF_MIXED_ARRAY) - || (t2 == NGX_RTMP_AMF_OBJECT && t1 == NGX_RTMP_AMF_MIXED_ARRAY); -} - - -ngx_int_t -ngx_rtmp_amf_read(ngx_rtmp_amf_ctx_t *ctx, ngx_rtmp_amf_elt_t *elts, - size_t nelts) -{ - void *data; - ngx_int_t type; - uint8_t type8; - size_t n; - uint16_t len; - ngx_int_t rc; - u_char buf[8]; - uint32_t max_index; - - for(n = 0; n < nelts; ++n) { - - if (elts && elts->type & NGX_RTMP_AMF_TYPELESS) { - type = elts->type & ~NGX_RTMP_AMF_TYPELESS; - data = elts->data; - - } else { - switch (ngx_rtmp_amf_get(ctx, &type8, 1)) { - case NGX_DONE: - if (elts->type & NGX_RTMP_AMF_OPTIONAL) { - return NGX_OK; - } else { - return NGX_ERROR; - } - break; - case NGX_ERROR: - return NGX_ERROR; - } - type = type8; - data = (elts && - ngx_rtmp_amf_is_compatible_type( - (uint8_t) (elts->type & 0xff), (uint8_t) type)) - ? elts->data - : NULL; - - if (elts && (elts->type & NGX_RTMP_AMF_CONTEXT)) { - if (data) { - *(ngx_rtmp_amf_ctx_t *) data = *ctx; - } - data = NULL; - } - } - - switch (type) { - case NGX_RTMP_AMF_NUMBER: - if (ngx_rtmp_amf_get(ctx, buf, 8) != NGX_OK) { - return NGX_ERROR; - } - ngx_rtmp_amf_reverse_copy(data, buf, 8); - break; - - case NGX_RTMP_AMF_BOOLEAN: - if (ngx_rtmp_amf_get(ctx, data, 1) != NGX_OK) { - return NGX_ERROR; - } - break; - - case NGX_RTMP_AMF_STRING: - if (ngx_rtmp_amf_get(ctx, buf, 2) != NGX_OK) { - return NGX_ERROR; - } - ngx_rtmp_amf_reverse_copy(&len, buf, 2); - - if (data == NULL) { - rc = ngx_rtmp_amf_get(ctx, data, len); - - } else if (elts->len <= len) { - rc = ngx_rtmp_amf_get(ctx, data, elts->len - 1); - if (rc != NGX_OK) - return NGX_ERROR; - ((char*)data)[elts->len - 1] = 0; - rc = ngx_rtmp_amf_get(ctx, NULL, len - elts->len + 1); - - } else { - rc = ngx_rtmp_amf_get(ctx, data, len); - ((char*)data)[len] = 0; - } - - if (rc != NGX_OK) { - return NGX_ERROR; - } - - break; - - case NGX_RTMP_AMF_NULL: - case NGX_RTMP_AMF_ARRAY_NULL: - break; - - case NGX_RTMP_AMF_MIXED_ARRAY: - if (ngx_rtmp_amf_get(ctx, &max_index, 4) != NGX_OK) { - return NGX_ERROR; - } - if (ngx_rtmp_amf_read_object(ctx, data, - data && elts ? elts->len / sizeof(ngx_rtmp_amf_elt_t) : 0 - ) != NGX_OK) - { - return NGX_ERROR; - } - break; - - case NGX_RTMP_AMF_OBJECT: - if (ngx_rtmp_amf_read_object(ctx, data, - data && elts ? elts->len / sizeof(ngx_rtmp_amf_elt_t) : 0 - ) != NGX_OK) - { - return NGX_ERROR; - } - break; - - case NGX_RTMP_AMF_ARRAY: - if (ngx_rtmp_amf_read_array(ctx, data, - data && elts ? elts->len / sizeof(ngx_rtmp_amf_elt_t) : 0 - ) != NGX_OK) - { - return NGX_ERROR; - } - break; - - case NGX_RTMP_AMF_VARIANT_: - if (ngx_rtmp_amf_read_variant(ctx, data, - data && elts ? elts->len / sizeof(ngx_rtmp_amf_elt_t) : 0 - ) != NGX_OK) - { - return NGX_ERROR; - } - break; - - case NGX_RTMP_AMF_INT8: - if (ngx_rtmp_amf_get(ctx, data, 1) != NGX_OK) { - return NGX_ERROR; - } - break; - - case NGX_RTMP_AMF_INT16: - if (ngx_rtmp_amf_get(ctx, buf, 2) != NGX_OK) { - return NGX_ERROR; - } - ngx_rtmp_amf_reverse_copy(data, buf, 2); - break; - - case NGX_RTMP_AMF_INT32: - if (ngx_rtmp_amf_get(ctx, buf, 4) != NGX_OK) { - return NGX_ERROR; - } - ngx_rtmp_amf_reverse_copy(data, buf, 4); - break; - - case NGX_RTMP_AMF_END: - return NGX_OK; - - default: - return NGX_ERROR; - } - - if (elts) { - ++elts; - } - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_amf_write_object(ngx_rtmp_amf_ctx_t *ctx, - ngx_rtmp_amf_elt_t *elts, size_t nelts) -{ - uint16_t len; - size_t n; - u_char buf[2]; - - for(n = 0; n < nelts; ++n) { - - len = (uint16_t) elts[n].name.len; - - if (ngx_rtmp_amf_put(ctx, - ngx_rtmp_amf_reverse_copy(buf, - &len, 2), 2) != NGX_OK) - { - return NGX_ERROR; - } - - if (ngx_rtmp_amf_put(ctx, elts[n].name.data, len) != NGX_OK) { - return NGX_ERROR; - } - - if (ngx_rtmp_amf_write(ctx, &elts[n], 1) != NGX_OK) { - return NGX_ERROR; - } - } - - if (ngx_rtmp_amf_put(ctx, "\0\0", 2) != NGX_OK) { - return NGX_ERROR; - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_amf_write_array(ngx_rtmp_amf_ctx_t *ctx, - ngx_rtmp_amf_elt_t *elts, size_t nelts) -{ - uint32_t len; - size_t n; - u_char buf[4]; - - len = nelts; - if (ngx_rtmp_amf_put(ctx, - ngx_rtmp_amf_reverse_copy(buf, - &len, 4), 4) != NGX_OK) - { - return NGX_ERROR; - } - - for(n = 0; n < nelts; ++n) { - if (ngx_rtmp_amf_write(ctx, &elts[n], 1) != NGX_OK) { - return NGX_ERROR; - } - } - - return NGX_OK; -} - - -ngx_int_t -ngx_rtmp_amf_write(ngx_rtmp_amf_ctx_t *ctx, - ngx_rtmp_amf_elt_t *elts, size_t nelts) -{ - size_t n; - ngx_int_t type; - uint8_t type8; - void *data; - uint16_t len; - uint32_t max_index; - u_char buf[8]; - - for(n = 0; n < nelts; ++n) { - - type = elts[n].type; - data = elts[n].data; - len = (uint16_t) elts[n].len; - - if (type & NGX_RTMP_AMF_TYPELESS) { - type &= ~NGX_RTMP_AMF_TYPELESS; - } else { - type8 = (uint8_t)type; - if (ngx_rtmp_amf_put(ctx, &type8, 1) != NGX_OK) - return NGX_ERROR; - } - - switch(type) { - case NGX_RTMP_AMF_NUMBER: - if (ngx_rtmp_amf_put(ctx, - ngx_rtmp_amf_reverse_copy(buf, - data, 8), 8) != NGX_OK) - { - return NGX_ERROR; - } - break; - - case NGX_RTMP_AMF_BOOLEAN: - if (ngx_rtmp_amf_put(ctx, data, 1) != NGX_OK) { - return NGX_ERROR; - } - break; - - case NGX_RTMP_AMF_STRING: - if (len == 0 && data) { - len = (uint16_t) ngx_strlen((u_char*) data); - } - - if (ngx_rtmp_amf_put(ctx, - ngx_rtmp_amf_reverse_copy(buf, - &len, 2), 2) != NGX_OK) - { - return NGX_ERROR; - } - - if (ngx_rtmp_amf_put(ctx, data, len) != NGX_OK) { - return NGX_ERROR; - } - break; - - case NGX_RTMP_AMF_NULL: - case NGX_RTMP_AMF_ARRAY_NULL: - break; - - case NGX_RTMP_AMF_MIXED_ARRAY: - max_index = 0; - if (ngx_rtmp_amf_put(ctx, &max_index, 4) != NGX_OK) { - return NGX_ERROR; - } - - type8 = NGX_RTMP_AMF_END; - if (ngx_rtmp_amf_write_object(ctx, data, - elts[n].len / sizeof(ngx_rtmp_amf_elt_t)) != NGX_OK - || ngx_rtmp_amf_put(ctx, &type8, 1) != NGX_OK) - { - return NGX_ERROR; - } - break; - - case NGX_RTMP_AMF_OBJECT: - type8 = NGX_RTMP_AMF_END; - if (ngx_rtmp_amf_write_object(ctx, data, - elts[n].len / sizeof(ngx_rtmp_amf_elt_t)) != NGX_OK - || ngx_rtmp_amf_put(ctx, &type8, 1) != NGX_OK) - { - return NGX_ERROR; - } - break; - - case NGX_RTMP_AMF_ARRAY: - if (ngx_rtmp_amf_write_array(ctx, data, - elts[n].len / sizeof(ngx_rtmp_amf_elt_t)) != NGX_OK) - { - return NGX_ERROR; - } - break; - - case NGX_RTMP_AMF_INT8: - if (ngx_rtmp_amf_put(ctx, data, 1) != NGX_OK) { - return NGX_ERROR; - } - break; - - case NGX_RTMP_AMF_INT16: - if (ngx_rtmp_amf_put(ctx, - ngx_rtmp_amf_reverse_copy(buf, - data, 2), 2) != NGX_OK) - { - return NGX_ERROR; - } - break; - - case NGX_RTMP_AMF_INT32: - if (ngx_rtmp_amf_put(ctx, - ngx_rtmp_amf_reverse_copy(buf, - data, 4), 4) != NGX_OK) - { - return NGX_ERROR; - } - break; - - default: - return NGX_ERROR; - } - } - - return NGX_OK; -} - diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_amf.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_amf.h deleted file mode 100644 index 8f70a129dc..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_amf.h +++ /dev/null @@ -1,71 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#ifndef _NGX_RTMP_AMF_H_INCLUDED_ -#define _NGX_RTMP_AMF_H_INCLUDED_ - - -#include -#include - - -/* basic types */ -#define NGX_RTMP_AMF_NUMBER 0x00 -#define NGX_RTMP_AMF_BOOLEAN 0x01 -#define NGX_RTMP_AMF_STRING 0x02 -#define NGX_RTMP_AMF_OBJECT 0x03 -#define NGX_RTMP_AMF_NULL 0x05 -#define NGX_RTMP_AMF_ARRAY_NULL 0x06 -#define NGX_RTMP_AMF_MIXED_ARRAY 0x08 -#define NGX_RTMP_AMF_END 0x09 -#define NGX_RTMP_AMF_ARRAY 0x0a - -/* extended types */ -#define NGX_RTMP_AMF_INT8 0x0100 -#define NGX_RTMP_AMF_INT16 0x0101 -#define NGX_RTMP_AMF_INT32 0x0102 -#define NGX_RTMP_AMF_VARIANT_ 0x0103 - -/* r/w flags */ -#define NGX_RTMP_AMF_OPTIONAL 0x1000 -#define NGX_RTMP_AMF_TYPELESS 0x2000 -#define NGX_RTMP_AMF_CONTEXT 0x4000 - -#define NGX_RTMP_AMF_VARIANT (NGX_RTMP_AMF_VARIANT_\ - |NGX_RTMP_AMF_TYPELESS) - - -typedef struct { - ngx_int_t type; - ngx_str_t name; - void *data; - size_t len; -} ngx_rtmp_amf_elt_t; - - -typedef ngx_chain_t * (*ngx_rtmp_amf_alloc_pt)(void *arg); - - -typedef struct { - ngx_chain_t *link, *first; - size_t offset; - ngx_rtmp_amf_alloc_pt alloc; - void *arg; - ngx_log_t *log; -} ngx_rtmp_amf_ctx_t; - - -/* reading AMF */ -ngx_int_t ngx_rtmp_amf_read(ngx_rtmp_amf_ctx_t *ctx, - ngx_rtmp_amf_elt_t *elts, size_t nelts); - -/* writing AMF */ -ngx_int_t ngx_rtmp_amf_write(ngx_rtmp_amf_ctx_t *ctx, - ngx_rtmp_amf_elt_t *elts, size_t nelts); - - -#endif /* _NGX_RTMP_AMF_H_INCLUDED_ */ - diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_bandwidth.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_bandwidth.c deleted file mode 100644 index 82f9f0d47c..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_bandwidth.c +++ /dev/null @@ -1,26 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include -#include "ngx_rtmp_bandwidth.h" - - -void -ngx_rtmp_update_bandwidth(ngx_rtmp_bandwidth_t *bw, uint32_t bytes) -{ - if (ngx_cached_time->sec > bw->intl_end) { - bw->bandwidth = ngx_cached_time->sec > - bw->intl_end + NGX_RTMP_BANDWIDTH_INTERVAL - ? 0 - : bw->intl_bytes / NGX_RTMP_BANDWIDTH_INTERVAL; - bw->intl_bytes = 0; - bw->intl_end = ngx_cached_time->sec + NGX_RTMP_BANDWIDTH_INTERVAL; - } - - bw->bytes += bytes; - bw->intl_bytes += bytes; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_bandwidth.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_bandwidth.h deleted file mode 100644 index b4984825bf..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_bandwidth.h +++ /dev/null @@ -1,31 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#ifndef _NGX_RTMP_BANDWIDTH_H_INCLUDED_ -#define _NGX_RTMP_BANDWIDTH_H_INCLUDED_ - - -#include -#include - - -/* Bandwidth update interval in seconds */ -#define NGX_RTMP_BANDWIDTH_INTERVAL 10 - - -typedef struct { - uint64_t bytes; - uint64_t bandwidth; /* bytes/sec */ - - time_t intl_end; - uint64_t intl_bytes; -} ngx_rtmp_bandwidth_t; - - -void ngx_rtmp_update_bandwidth(ngx_rtmp_bandwidth_t *bw, uint32_t bytes); - - -#endif /* _NGX_RTMP_BANDWIDTH_H_INCLUDED_ */ diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_bitop.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_bitop.c deleted file mode 100644 index 855d425fd2..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_bitop.c +++ /dev/null @@ -1,63 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include -#include "ngx_rtmp_bitop.h" - - -void -ngx_rtmp_bit_init_reader(ngx_rtmp_bit_reader_t *br, u_char *pos, u_char *last) -{ - ngx_memzero(br, sizeof(ngx_rtmp_bit_reader_t)); - - br->pos = pos; - br->last = last; -} - - -uint64_t -ngx_rtmp_bit_read(ngx_rtmp_bit_reader_t *br, ngx_uint_t n) -{ - uint64_t v; - ngx_uint_t d; - - v = 0; - - while (n) { - - if (br->pos >= br->last) { - br->err = 1; - return 0; - } - - d = (br->offs + n > 8 ? (ngx_uint_t) (8 - br->offs) : n); - - v <<= d; - v += (*br->pos >> (8 - br->offs - d)) & ((u_char) 0xff >> (8 - d)); - - br->offs += d; - n -= d; - - if (br->offs == 8) { - br->pos++; - br->offs = 0; - } - } - - return v; -} - - -uint64_t -ngx_rtmp_bit_read_golomb(ngx_rtmp_bit_reader_t *br) -{ - ngx_uint_t n; - - for (n = 0; ngx_rtmp_bit_read(br, 1) == 0 && !br->err; n++); - - return ((uint64_t) 1 << n) + ngx_rtmp_bit_read(br, n) - 1; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_bitop.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_bitop.h deleted file mode 100644 index c954a35f39..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_bitop.h +++ /dev/null @@ -1,46 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#ifndef _NGX_RTMP_BITOP_H_INCLUDED_ -#define _NGX_RTMP_BITOP_H_INCLUDED_ - - -#include -#include - - -typedef struct { - u_char *pos; - u_char *last; - ngx_uint_t offs; - ngx_uint_t err; -} ngx_rtmp_bit_reader_t; - - -void ngx_rtmp_bit_init_reader(ngx_rtmp_bit_reader_t *br, u_char *pos, - u_char *last); -uint64_t ngx_rtmp_bit_read(ngx_rtmp_bit_reader_t *br, ngx_uint_t n); -uint64_t ngx_rtmp_bit_read_golomb(ngx_rtmp_bit_reader_t *br); - - -#define ngx_rtmp_bit_read_err(br) ((br)->err) - -#define ngx_rtmp_bit_read_eof(br) ((br)->pos == (br)->last) - -#define ngx_rtmp_bit_read_8(br) \ - ((uint8_t) ngx_rtmp_bit_read(br, 8)) - -#define ngx_rtmp_bit_read_16(br) \ - ((uint16_t) ngx_rtmp_bit_read(br, 16)) - -#define ngx_rtmp_bit_read_32(br) \ - ((uint32_t) ngx_rtmp_bit_read(br, 32)) - -#define ngx_rtmp_bit_read_64(br) \ - ((uint64_t) ngx_rtmp_read(br, 64)) - - -#endif /* _NGX_RTMP_BITOP_H_INCLUDED_ */ diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_cmd_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_cmd_module.c deleted file mode 100644 index b29d002c17..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_cmd_module.c +++ /dev/null @@ -1,1096 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include -#include "ngx_rtmp_cmd_module.h" -#include "ngx_rtmp_notify_module.h" -#include "ngx_rtmp_streams.h" -#include "ngx_stream_zone_module.h" -#include "ngx_dynamic_conf.h" -#include "ngx_toolkit_misc.h" -#include "ngx_rtmp_dynamic.h" - - -#define NGX_RTMP_FMS_VERSION "FMS/3,0,1,123" -#define NGX_RTMP_CAPABILITIES 31 - - -static ngx_int_t ngx_rtmp_cmd_connect(ngx_rtmp_session_t *s, - ngx_rtmp_connect_t *v); -static ngx_int_t ngx_rtmp_cmd_disconnect(ngx_rtmp_session_t *s); -static ngx_int_t ngx_rtmp_cmd_create_stream(ngx_rtmp_session_t *s, - ngx_rtmp_create_stream_t *v); -static ngx_int_t ngx_rtmp_cmd_close_stream(ngx_rtmp_session_t *s, - ngx_rtmp_close_stream_t *v); -static ngx_int_t ngx_rtmp_cmd_delete_stream(ngx_rtmp_session_t *s, - ngx_rtmp_delete_stream_t *v); -static ngx_int_t ngx_rtmp_cmd_publish(ngx_rtmp_session_t *s, - ngx_rtmp_publish_t *v); -static ngx_int_t ngx_rtmp_cmd_play(ngx_rtmp_session_t *s, - ngx_rtmp_play_t *v); -static ngx_int_t ngx_rtmp_cmd_seek(ngx_rtmp_session_t *s, - ngx_rtmp_seek_t *v); -static ngx_int_t ngx_rtmp_cmd_pause(ngx_rtmp_session_t *s, - ngx_rtmp_pause_t *v); - - -static ngx_int_t ngx_rtmp_cmd_stream_begin(ngx_rtmp_session_t *s, - ngx_rtmp_stream_begin_t *v); -static ngx_int_t ngx_rtmp_cmd_stream_eof(ngx_rtmp_session_t *s, - ngx_rtmp_stream_eof_t *v); -static ngx_int_t ngx_rtmp_cmd_stream_dry(ngx_rtmp_session_t *s, - ngx_rtmp_stream_dry_t *v); -static ngx_int_t ngx_rtmp_cmd_recorded(ngx_rtmp_session_t *s, - ngx_rtmp_recorded_t *v); -static ngx_int_t ngx_rtmp_cmd_set_buflen(ngx_rtmp_session_t *s, - ngx_rtmp_set_buflen_t *v); - - -ngx_rtmp_connect_pt ngx_rtmp_connect; -ngx_rtmp_disconnect_pt ngx_rtmp_disconnect; -ngx_rtmp_create_stream_pt ngx_rtmp_create_stream; -ngx_rtmp_close_stream_pt ngx_rtmp_close_stream; -ngx_rtmp_delete_stream_pt ngx_rtmp_delete_stream; -ngx_rtmp_publish_pt ngx_rtmp_publish; -ngx_rtmp_play_pt ngx_rtmp_play; -ngx_rtmp_seek_pt ngx_rtmp_seek; -ngx_rtmp_pause_pt ngx_rtmp_pause; - - -ngx_rtmp_stream_begin_pt ngx_rtmp_stream_begin; -ngx_rtmp_stream_eof_pt ngx_rtmp_stream_eof; -ngx_rtmp_stream_dry_pt ngx_rtmp_stream_dry; -ngx_rtmp_recorded_pt ngx_rtmp_recorded; -ngx_rtmp_set_buflen_pt ngx_rtmp_set_buflen; - - -static ngx_int_t ngx_rtmp_cmd_postconfiguration(ngx_conf_t *cf); - - -static ngx_rtmp_module_t ngx_rtmp_cmd_module_ctx = { - NULL, /* preconfiguration */ - ngx_rtmp_cmd_postconfiguration, /* postconfiguration */ - NULL, /* create main configuration */ - NULL, /* init main configuration */ - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - NULL, /* create app configuration */ - NULL /* merge app configuration */ -}; - - -ngx_module_t ngx_rtmp_cmd_module = { - NGX_MODULE_V1, - &ngx_rtmp_cmd_module_ctx, /* module context */ - NULL, /* module directives */ - NGX_RTMP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -void -ngx_rtmp_cmd_fill_args(u_char name[NGX_RTMP_MAX_NAME], - u_char args[NGX_RTMP_MAX_ARGS]) -{ - u_char *p; - - p = (u_char *)ngx_strchr(name, '?'); - if (p == NULL) { - return; - } - - *p++ = 0; - ngx_cpystrn(args, p, NGX_RTMP_MAX_ARGS); -} - -void -ngx_rtmp_cmd_reset_vhost(ngx_rtmp_session_t *s, ngx_rtmp_connect_t *v) -{ - ngx_request_url_t ru; - ngx_str_t tcurl; - char *p; - - tcurl.data = v->tc_url; - tcurl.len = ngx_strlen(v->tc_url); - - if (ngx_parse_request_url(&ru, &tcurl) == NGX_ERROR) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "tcurl error, %s", v->tc_url); - return; - } - - if (ngx_inet_addr(ru.host.data, ru.host.len) == INADDR_NONE) { - /* domain is not ip */ - return; - } - - p = ngx_strstr(v->app, "/"); - if (p == NULL) { /* app only has one level */ - return; - } - - /* use first level of app as domain, the rest as app */ - *ngx_snprintf(v->tc_url, NGX_RTMP_MAX_URL, "rtmp://%s", v->app) = 0; - *ngx_snprintf(v->app, NGX_RTMP_MAX_NAME, "%s", p + 1) = 0; -} - -void -ngx_rtmp_cmd_middleware_init(ngx_rtmp_session_t *s) -{ - ngx_rtmp_core_srv_dconf_t *rcsdf; - ngx_rtmp_core_srv_conf_t *rcsf; - ngx_request_url_t rurl; - - if (ngx_parse_request_url(&rurl, &s->tc_url) == NGX_ERROR) { - return; - } - - s->scheme = rurl.scheme; - s->domain = rurl.host; - - rcsf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module); - rcsdf = ngx_rtmp_get_module_srv_dconf(s, &ngx_rtmp_core_module); - if (rcsdf && rcsdf->serverid.len) { - s->serverid.data = ngx_pcalloc(s->pool, - rcsdf->serverid.len); - if (s->serverid.data == NULL) { - return; - } - s->serverid.len = rcsdf->serverid.len; - ngx_memcpy(s->serverid.data, rcsdf->serverid.data, s->serverid.len); - } else if (rcsf && rcsf->serverid.len) { - s->serverid.data = ngx_pcalloc(s->pool, - rcsf->serverid.len); - if (s->serverid.data == NULL) { - return; - } - s->serverid.len = rcsf->serverid.len; - ngx_memcpy(s->serverid.data, rcsf->serverid.data, s->serverid.len); - }else { - s->serverid = s->domain; - } -} - -void -ngx_rtmp_cmd_stream_init(ngx_rtmp_session_t *s, u_char *name, u_char *args, - unsigned publishing) -{ - u_char *p; - - if (s->name.len == 0) { - s->name.len = ngx_strlen(name); - s->name.data = ngx_palloc(s->pool, s->name.len); - ngx_memcpy(s->name.data, name, s->name.len); - } - - if (s->pargs.len == 0) { - s->pargs.len = ngx_strlen(args); - s->pargs.data = ngx_palloc(s->pool, s->pargs.len); - ngx_memcpy(s->pargs.data, args, s->pargs.len); - } - - if (s->stream.len == 0) { - /* serverid/app/name */ - s->stream.len = s->serverid.len + 1 + s->app.len + 1 + s->name.len; - s->stream.data = ngx_palloc(s->pool, s->stream.len); - p = s->stream.data; - - p = ngx_copy(p, s->serverid.data, s->serverid.len); - *p++ = '/'; - p = ngx_copy(p, s->app.data, s->app.len); - *p++ = '/'; - p = ngx_copy(p, s->name.data, s->name.len); - } - - s->live_stream = ngx_live_create_stream(&s->serverid, &s->stream); - - ngx_live_create_ctx(s, publishing); - s->publishing = publishing; - - ngx_rtmp_notify_stream_start(s); -} - -ngx_int_t -ngx_rtmp_publish_filter(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v) -{ - if (s->published) { - ngx_log_error(NGX_LOG_INFO, s->log, 0, "session has been published"); - return NGX_OK; - } - - ngx_log_error(NGX_LOG_INFO, s->log, 0, "rtmp publish filter"); - - s->published = 1; - - if (!s->relay) { /* relay pull */ - ngx_rtmp_cmd_stream_init(s, v->name, v->args, 1); - } - - return ngx_rtmp_publish(s, v); -} - -ngx_int_t -ngx_rtmp_play_filter(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v) -{ - if (s->played) { - ngx_log_error(NGX_LOG_INFO, s->log, 0, "session has been played"); - return NGX_OK; - } - - ngx_log_error(NGX_LOG_INFO, s->log, 0, "rtmp play filter"); - - s->played = 1; - - if (!s->relay) { /* relay push */ - ngx_rtmp_cmd_stream_init(s, v->name, v->args, 0); - } - - return ngx_rtmp_play(s, v); -} - -ngx_int_t -ngx_rtmp_close_stream_filter(ngx_rtmp_session_t *s, ngx_rtmp_close_stream_t *v) -{ - if (s->closed) { - ngx_log_error(NGX_LOG_INFO, s->log, 0, "session has been closed"); - return NGX_OK; - } - - ngx_log_error(NGX_LOG_INFO, s->log, 0, "rtmp close stream filter"); - - s->closed = 1; - - ngx_live_delete_ctx(s); - if (s->live_stream && s->live_stream->play_ctx == NULL - && s->live_stream->publish_ctx == NULL) - { - if (s->live_stream->pslot == ngx_process_slot) { - ngx_stream_zone_delete_stream(&s->stream); - } - ngx_rtmp_notify_stream_done(s); - ngx_live_delete_stream(&s->serverid, &s->stream); - } - - return ngx_rtmp_close_stream(s, v); -} - -static ngx_int_t -ngx_rtmp_cmd_connect_init(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - size_t len; - ngx_rtmp_core_srv_conf_t *cscf; - ngx_rtmp_core_app_conf_t **cacfp; - ngx_uint_t n; - u_char *p; - - static ngx_rtmp_connect_t v; - - static ngx_rtmp_amf_elt_t in_cmd[] = { - - { NGX_RTMP_AMF_STRING, - ngx_string("app"), - v.app, sizeof(v.app) }, - - { NGX_RTMP_AMF_STRING, - ngx_string("flashVer"), - v.flashver, sizeof(v.flashver) }, - - { NGX_RTMP_AMF_STRING, - ngx_string("swfUrl"), - v.swf_url, sizeof(v.swf_url) }, - - { NGX_RTMP_AMF_STRING, - ngx_string("tcUrl"), - v.tc_url, sizeof(v.tc_url) }, - - { NGX_RTMP_AMF_NUMBER, - ngx_string("audioCodecs"), - &v.acodecs, sizeof(v.acodecs) }, - - { NGX_RTMP_AMF_NUMBER, - ngx_string("videoCodecs"), - &v.vcodecs, sizeof(v.vcodecs) }, - - { NGX_RTMP_AMF_STRING, - ngx_string("pageUrl"), - v.page_url, sizeof(v.page_url) }, - - { NGX_RTMP_AMF_NUMBER, - ngx_string("objectEncoding"), - &v.object_encoding, 0}, - }; - - static ngx_rtmp_amf_elt_t in_elts[] = { - - { NGX_RTMP_AMF_NUMBER, - ngx_null_string, - &v.trans, 0 }, - - { NGX_RTMP_AMF_OBJECT, - ngx_null_string, - in_cmd, sizeof(in_cmd) }, - }; - - ngx_memzero(&v, sizeof(v)); - if (ngx_rtmp_receive_amf(s, in, in_elts, - sizeof(in_elts) / sizeof(in_elts[0]))) - { - return NGX_ERROR; - } - - len = ngx_strlen(v.app); - if (len > 10 && !ngx_memcmp(v.app + len - 10, "/_definst_", 10)) { - v.app[len - 10] = 0; - } else if (len && v.app[len - 1] == '/') { - v.app[len - 1] = 0; - } - - ngx_rtmp_cmd_fill_args(v.app, v.args); - ngx_rtmp_cmd_reset_vhost(s, &v); - -#define NGX_RTMP_SET_STRPAR(name) \ - s->name.len = ngx_strlen(v.name); \ - s->name.data = ngx_palloc(s->pool, s->name.len); \ - ngx_memcpy(s->name.data, v.name, s->name.len) - - NGX_RTMP_SET_STRPAR(app); - NGX_RTMP_SET_STRPAR(args); - NGX_RTMP_SET_STRPAR(flashver); - NGX_RTMP_SET_STRPAR(swf_url); - NGX_RTMP_SET_STRPAR(tc_url); - NGX_RTMP_SET_STRPAR(page_url); - -#undef NGX_RTMP_SET_STRPAR - - p = ngx_strlchr(s->app.data, s->app.data + s->app.len, '?'); - if (p) { - s->app.len = (p - s->app.data); - } - - s->acodecs = (uint32_t) v.acodecs; - s->vcodecs = (uint32_t) v.vcodecs; - - ngx_rtmp_cmd_middleware_init(s); - - if (ngx_rtmp_set_virtual_server(s, &s->domain)) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "rtmp connect, set vhost for \"%V\" failed", &s->domain); - return NGX_ERROR; - } - cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module); - - /* find application & set app_conf */ - cacfp = cscf->applications.elts; - for(n = 0; n < cscf->applications.nelts; ++n, ++cacfp) { - if ((*cacfp)->name.len == s->app.len && - ngx_strncmp((*cacfp)->name.data, s->app.data, s->app.len) == 0) - { - /* found app! */ - s->app_conf = (*cacfp)->app_conf; - break; - } - } - - if (s->app_conf == NULL) { - - if (cscf->default_app == NULL || cscf->default_app->app_conf == NULL) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "connect: application not found: '%V'", &s->app); - return NGX_ERROR; - } - - s->app_conf = cscf->default_app->app_conf; - } - - s->live_server = ngx_live_create_server(&s->serverid); - - s->stage = NGX_LIVE_CONNECT; - s->connect_time = ngx_current_msec; - - return ngx_rtmp_connect(s, &v); -} - - -static ngx_int_t -ngx_rtmp_cmd_connect(ngx_rtmp_session_t *s, ngx_rtmp_connect_t *v) -{ - ngx_rtmp_core_srv_conf_t *cscf; - ngx_rtmp_core_app_conf_t *cacf; - ngx_rtmp_header_t h; - int tcp_nodelay; - - static double trans; - static double capabilities = NGX_RTMP_CAPABILITIES; - static double object_encoding = 0; - - static ngx_rtmp_amf_elt_t out_obj[] = { - - { NGX_RTMP_AMF_STRING, - ngx_string("fmsVer"), - NGX_RTMP_FMS_VERSION, 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_string("capabilities"), - &capabilities, 0 }, - }; - - static ngx_rtmp_amf_elt_t out_inf[] = { - - { NGX_RTMP_AMF_STRING, - ngx_string("level"), - "status", 0 }, - - { NGX_RTMP_AMF_STRING, - ngx_string("code"), - "NetConnection.Connect.Success", 0 }, - - { NGX_RTMP_AMF_STRING, - ngx_string("description"), - "Connection succeeded.", 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_string("objectEncoding"), - &object_encoding, 0 } - }; - - static ngx_rtmp_amf_elt_t out_elts[] = { - - { NGX_RTMP_AMF_STRING, - ngx_null_string, - "_result", 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_null_string, - &trans, 0 }, - - { NGX_RTMP_AMF_OBJECT, - ngx_null_string, - out_obj, sizeof(out_obj) }, - - { NGX_RTMP_AMF_OBJECT, - ngx_null_string, - out_inf, sizeof(out_inf) }, - }; - - if (s->connected) { - ngx_log_error(NGX_LOG_INFO, s->log, 0, - "connect: duplicate connection"); - return NGX_ERROR; - } - - cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module); - - /* set tcp_nodelay */ - cacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_core_module); - if (cacf->tcp_nodelay && - s->connection->tcp_nodelay == NGX_TCP_NODELAY_UNSET) - { - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->log, 0, - "tcp_nodelay"); - - tcp_nodelay = 1; - - if (setsockopt(s->connection->fd, IPPROTO_TCP, TCP_NODELAY, - (const void *) &tcp_nodelay, sizeof(int)) == -1) - { - ngx_connection_error(s->connection, ngx_socket_errno, - "setsockopt(TCP_NODELAY) failed"); - return NGX_ERROR; - } - - s->connection->tcp_nodelay = NGX_TCP_NODELAY_SET; - } - - trans = v->trans; - - /* fill session parameters */ - s->connected = 1; - - ngx_memzero(&h, sizeof(h)); - h.csid = NGX_RTMP_CSID_AMF_INI; - h.type = NGX_RTMP_MSG_AMF_CMD; - - object_encoding = v->object_encoding; - - return ngx_rtmp_send_ack_size(s, cscf->ack_window) != NGX_OK || - ngx_rtmp_send_bandwidth(s, cscf->ack_window, - NGX_RTMP_LIMIT_DYNAMIC) != NGX_OK || - ngx_rtmp_send_chunk_size(s, cscf->chunk_size) != NGX_OK || - ngx_rtmp_send_amf(s, &h, out_elts, - sizeof(out_elts) / sizeof(out_elts[0])) - != NGX_OK ? NGX_ERROR : NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_cmd_create_stream_init(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - static ngx_rtmp_create_stream_t v; - - static ngx_rtmp_amf_elt_t in_elts[] = { - - { NGX_RTMP_AMF_NUMBER, - ngx_null_string, - &v.trans, sizeof(v.trans) }, - }; - - if (ngx_rtmp_receive_amf(s, in, in_elts, - sizeof(in_elts) / sizeof(in_elts[0]))) - { - return NGX_ERROR; - } - - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->log, 0, "createStream"); - - s->stage = NGX_LIVE_CREATE_STREAM; - s->create_stream_time = ngx_current_msec; - - return ngx_rtmp_create_stream(s, &v); -} - - -static ngx_int_t -ngx_rtmp_cmd_create_stream(ngx_rtmp_session_t *s, ngx_rtmp_create_stream_t *v) -{ - /* support one message stream per connection */ - static double stream; - static double trans; - ngx_rtmp_header_t h; - - static ngx_rtmp_amf_elt_t out_elts[] = { - - { NGX_RTMP_AMF_STRING, - ngx_null_string, - "_result", 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_null_string, - &trans, 0 }, - - { NGX_RTMP_AMF_NULL, - ngx_null_string, - NULL, 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_null_string, - &stream, sizeof(stream) }, - }; - - trans = v->trans; - stream = NGX_RTMP_MSID; - - ngx_memzero(&h, sizeof(h)); - - h.csid = NGX_RTMP_CSID_AMF_INI; - h.type = NGX_RTMP_MSG_AMF_CMD; - - return ngx_rtmp_send_amf(s, &h, out_elts, - sizeof(out_elts) / sizeof(out_elts[0])) == NGX_OK ? - NGX_DONE : NGX_ERROR; -} - - -static ngx_int_t -ngx_rtmp_cmd_close_stream_init(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - static ngx_rtmp_close_stream_t v; - - static ngx_rtmp_amf_elt_t in_elts[] = { - - { NGX_RTMP_AMF_NUMBER, - ngx_null_string, - &v.stream, 0 }, - }; - - if (ngx_rtmp_receive_amf(s, in, in_elts, - sizeof(in_elts) / sizeof(in_elts[0]))) - { - return NGX_ERROR; - } - - s->finalize_reason = NGX_LIVE_NORMAL_CLOSE; - - return ngx_rtmp_close_stream_filter(s, &v); -} - - -static ngx_int_t -ngx_rtmp_cmd_close_stream(ngx_rtmp_session_t *s, ngx_rtmp_close_stream_t *v) -{ - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_cmd_delete_stream_init(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - static ngx_rtmp_delete_stream_t v; - - static ngx_rtmp_amf_elt_t in_elts[] = { - - { NGX_RTMP_AMF_NUMBER, - ngx_null_string, - NULL, 0 }, - - { NGX_RTMP_AMF_NULL, - ngx_null_string, - NULL, 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_null_string, - &v.stream, 0 }, - }; - - if (ngx_rtmp_receive_amf(s, in, in_elts, - sizeof(in_elts) / sizeof(in_elts[0]))) - { - return NGX_ERROR; - } - - s->finalize_reason = NGX_LIVE_NORMAL_CLOSE; - - return ngx_rtmp_delete_stream(s, &v); -} - - -static ngx_int_t -ngx_rtmp_cmd_delete_stream(ngx_rtmp_session_t *s, ngx_rtmp_delete_stream_t *v) -{ - ngx_rtmp_close_stream_t cv; - - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->log, 0, "deleteStream"); - - cv.stream = 0; - - return ngx_rtmp_close_stream_filter(s, &cv); -} - - -static ngx_int_t -ngx_rtmp_cmd_publish_init(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - static ngx_rtmp_publish_t v; - - static ngx_rtmp_amf_elt_t in_elts[] = { - - /* transaction is always 0 */ - { NGX_RTMP_AMF_NUMBER, - ngx_null_string, - NULL, 0 }, - - { NGX_RTMP_AMF_NULL, - ngx_null_string, - NULL, 0 }, - - { NGX_RTMP_AMF_STRING, - ngx_null_string, - &v.name, sizeof(v.name) }, - - { NGX_RTMP_AMF_OPTIONAL | NGX_RTMP_AMF_STRING, - ngx_null_string, - &v.type, sizeof(v.type) }, - }; - - ngx_memzero(&v, sizeof(v)); - - if (ngx_rtmp_receive_amf(s, in, in_elts, - sizeof(in_elts) / sizeof(in_elts[0]))) - { - return NGX_ERROR; - } - - ngx_rtmp_cmd_fill_args(v.name, v.args); - - ngx_log_debug4(NGX_LOG_DEBUG_RTMP, s->log, 0, - "publish: name='%s' args='%s' type=%s silent=%d", - v.name, v.args, v.type, v.silent); - - s->stage = NGX_LIVE_PUBLISH; - s->ptime = ngx_current_msec; - - return ngx_rtmp_publish_filter(s, &v); -} - - -static ngx_int_t -ngx_rtmp_cmd_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v) -{ - ngx_log_error(NGX_LOG_INFO, s->log, 0, - "publish: name='%V' pargs='%V' app='%V' args='%V' flashver='%V' " - "swf_url='%V' tc_url='%V' page_url='%V' acodecs=%uD vcodecs=%uD " - "scheme='%V' domain='%V' serverid='%V' stream='%V' groupid='%V'", - &s->name, &s->pargs, &s->app, &s->args, &s->flashver, - &s->swf_url, &s->tc_url, &s->page_url, s->acodecs, s->vcodecs, - &s->scheme, &s->domain, &s->serverid, &s->stream, &s->groupid); - - return NGX_OK; -} - -static ngx_int_t -ngx_rtmp_cmd_play_init(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - static ngx_rtmp_play_t v; - - static ngx_rtmp_amf_elt_t in_elts[] = { - - /* transaction is always 0 */ - { NGX_RTMP_AMF_NUMBER, - ngx_null_string, - NULL, 0 }, - - { NGX_RTMP_AMF_NULL, - ngx_null_string, - NULL, 0 }, - - { NGX_RTMP_AMF_STRING, - ngx_null_string, - &v.name, sizeof(v.name) }, - - { NGX_RTMP_AMF_OPTIONAL | NGX_RTMP_AMF_NUMBER, - ngx_null_string, - &v.start, 0 }, - - { NGX_RTMP_AMF_OPTIONAL | NGX_RTMP_AMF_NUMBER, - ngx_null_string, - &v.duration, 0 }, - - { NGX_RTMP_AMF_OPTIONAL | NGX_RTMP_AMF_BOOLEAN, - ngx_null_string, - &v.reset, 0 } - }; - - ngx_memzero(&v, sizeof(v)); - - if (ngx_rtmp_receive_amf(s, in, in_elts, - sizeof(in_elts) / sizeof(in_elts[0]))) - { - return NGX_ERROR; - } - - ngx_rtmp_cmd_fill_args(v.name, v.args); - - ngx_log_debug6(NGX_LOG_DEBUG_RTMP, s->log, 0, - "play: name='%s' args='%s' start=%i duration=%i " - "reset=%i silent=%i", - v.name, v.args, (ngx_int_t) v.start, - (ngx_int_t) v.duration, (ngx_int_t) v.reset, - (ngx_int_t) v.silent); - - s->stage = NGX_LIVE_PLAY; - s->ptime = ngx_current_msec; - - return ngx_rtmp_play_filter(s, &v); -} - - -static ngx_int_t -ngx_rtmp_cmd_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v) -{ - ngx_log_error(NGX_LOG_INFO, s->log, 0, - "play: name='%V' pargs='%V' app='%V' args='%V' flashver='%V' " - "swf_url='%V' tc_url='%V' page_url='%V' acodecs=%uD vcodecs=%uD " - "scheme='%V' domain='%V' serverid='%V' stream='%V' groupid='%V'", - &s->name, &s->pargs, &s->app, &s->args, &s->flashver, - &s->swf_url, &s->tc_url, &s->page_url, s->acodecs, s->vcodecs, - &s->scheme, &s->domain, &s->serverid, &s->stream, &s->groupid); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_cmd_play2_init(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - static ngx_rtmp_play_t v; - static ngx_rtmp_close_stream_t vc; - - static ngx_rtmp_amf_elt_t in_obj[] = { - - { NGX_RTMP_AMF_NUMBER, - ngx_string("start"), - &v.start, 0 }, - - { NGX_RTMP_AMF_STRING, - ngx_string("streamName"), - &v.name, sizeof(v.name) }, - }; - - static ngx_rtmp_amf_elt_t in_elts[] = { - - /* transaction is always 0 */ - { NGX_RTMP_AMF_NUMBER, - ngx_null_string, - NULL, 0 }, - - { NGX_RTMP_AMF_NULL, - ngx_null_string, - NULL, 0 }, - - { NGX_RTMP_AMF_OBJECT, - ngx_null_string, - &in_obj, sizeof(in_obj) } - }; - - ngx_memzero(&v, sizeof(v)); - - if (ngx_rtmp_receive_amf(s, in, in_elts, - sizeof(in_elts) / sizeof(in_elts[0]))) - { - return NGX_ERROR; - } - - ngx_rtmp_cmd_fill_args(v.name, v.args); - - ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->log, 0, - "play2: name='%s' args='%s' start=%i", - v.name, v.args, (ngx_int_t) v.start); - - /* continue from current timestamp */ - - if (v.start < 0) { - v.start = s->current_time; - } - - ngx_memzero(&vc, sizeof(vc)); - - /* close_stream should be synchronous */ - ngx_rtmp_close_stream_filter(s, &vc); - - return ngx_rtmp_play_filter(s, &v); -} - - -static ngx_int_t -ngx_rtmp_cmd_pause_init(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - static ngx_rtmp_pause_t v; - - static ngx_rtmp_amf_elt_t in_elts[] = { - - { NGX_RTMP_AMF_NUMBER, - ngx_null_string, - NULL, 0 }, - - { NGX_RTMP_AMF_NULL, - ngx_null_string, - NULL, 0 }, - - { NGX_RTMP_AMF_BOOLEAN, - ngx_null_string, - &v.pause, 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_null_string, - &v.position, 0 }, - }; - - ngx_memzero(&v, sizeof(v)); - - if (ngx_rtmp_receive_amf(s, in, in_elts, - sizeof(in_elts) / sizeof(in_elts[0]))) - { - return NGX_ERROR; - } - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->log, 0, - "pause: pause=%i position=%i", - (ngx_int_t) v.pause, (ngx_int_t) v.position); - - return ngx_rtmp_pause(s, &v); -} - - -static ngx_int_t -ngx_rtmp_cmd_pause(ngx_rtmp_session_t *s, ngx_rtmp_pause_t *v) -{ - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_cmd_disconnect_init(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - s->stage = NGX_LIVE_CLOSE; - s->close_stream_time = ngx_current_msec; - - ngx_log_error(NGX_LOG_INFO, s->log, 0, "disconnect"); - - return ngx_rtmp_disconnect(s); -} - - -static ngx_int_t -ngx_rtmp_cmd_disconnect(ngx_rtmp_session_t *s) -{ - return ngx_rtmp_delete_stream(s, NULL); -} - - -static ngx_int_t -ngx_rtmp_cmd_seek_init(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - static ngx_rtmp_seek_t v; - - static ngx_rtmp_amf_elt_t in_elts[] = { - - /* transaction is always 0 */ - { NGX_RTMP_AMF_NUMBER, - ngx_null_string, - NULL, 0 }, - - { NGX_RTMP_AMF_NULL, - ngx_null_string, - NULL, 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_null_string, - &v.offset, sizeof(v.offset) }, - }; - - ngx_memzero(&v, sizeof(v)); - - if (ngx_rtmp_receive_amf(s, in, in_elts, - sizeof(in_elts) / sizeof(in_elts[0]))) - { - return NGX_ERROR; - } - - ngx_log_error(NGX_LOG_INFO, s->log, 0, - "seek: offset=%i", (ngx_int_t) v.offset); - - return ngx_rtmp_seek(s, &v); -} - - -static ngx_int_t -ngx_rtmp_cmd_seek(ngx_rtmp_session_t *s, ngx_rtmp_seek_t *v) -{ - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_cmd_stream_begin(ngx_rtmp_session_t *s, ngx_rtmp_stream_begin_t *v) -{ - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_cmd_stream_eof(ngx_rtmp_session_t *s, ngx_rtmp_stream_eof_t *v) -{ - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_cmd_stream_dry(ngx_rtmp_session_t *s, ngx_rtmp_stream_dry_t *v) -{ - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_cmd_recorded(ngx_rtmp_session_t *s, - ngx_rtmp_recorded_t *v) -{ - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_cmd_set_buflen(ngx_rtmp_session_t *s, ngx_rtmp_set_buflen_t *v) -{ - return NGX_OK; -} - - -static ngx_rtmp_amf_handler_t ngx_rtmp_cmd_map[] = { - { ngx_string("connect"), ngx_rtmp_cmd_connect_init }, - { ngx_string("createStream"), ngx_rtmp_cmd_create_stream_init }, - { ngx_string("closeStream"), ngx_rtmp_cmd_close_stream_init }, - { ngx_string("deleteStream"), ngx_rtmp_cmd_delete_stream_init }, - { ngx_string("publish"), ngx_rtmp_cmd_publish_init }, - { ngx_string("play"), ngx_rtmp_cmd_play_init }, - { ngx_string("play2"), ngx_rtmp_cmd_play2_init }, - { ngx_string("seek"), ngx_rtmp_cmd_seek_init }, - { ngx_string("pause"), ngx_rtmp_cmd_pause_init }, - { ngx_string("pauseraw"), ngx_rtmp_cmd_pause_init }, -}; - - -static ngx_int_t -ngx_rtmp_cmd_postconfiguration(ngx_conf_t *cf) -{ - ngx_rtmp_core_main_conf_t *cmcf; - ngx_rtmp_handler_pt *h; - ngx_rtmp_amf_handler_t *ch, *bh; - size_t n, ncalls; - - cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module); - - /* redirect disconnects to deleteStream - * to free client modules from registering - * disconnect callback */ - - h = ngx_array_push(&cmcf->events[NGX_RTMP_DISCONNECT]); - if (h == NULL) { - return NGX_ERROR; - } - - *h = ngx_rtmp_cmd_disconnect_init; - - /* register AMF callbacks */ - - ncalls = sizeof(ngx_rtmp_cmd_map) / sizeof(ngx_rtmp_cmd_map[0]); - - ch = ngx_array_push_n(&cmcf->amf, ncalls); - if (ch == NULL) { - return NGX_ERROR; - } - - bh = ngx_rtmp_cmd_map; - - for(n = 0; n < ncalls; ++n, ++ch, ++bh) { - *ch = *bh; - } - - ngx_rtmp_connect = ngx_rtmp_cmd_connect; - ngx_rtmp_disconnect = ngx_rtmp_cmd_disconnect; - ngx_rtmp_create_stream = ngx_rtmp_cmd_create_stream; - ngx_rtmp_close_stream = ngx_rtmp_cmd_close_stream; - ngx_rtmp_delete_stream = ngx_rtmp_cmd_delete_stream; - ngx_rtmp_publish = ngx_rtmp_cmd_publish; - ngx_rtmp_play = ngx_rtmp_cmd_play; - ngx_rtmp_seek = ngx_rtmp_cmd_seek; - ngx_rtmp_pause = ngx_rtmp_cmd_pause; - - ngx_rtmp_stream_begin = ngx_rtmp_cmd_stream_begin; - ngx_rtmp_stream_eof = ngx_rtmp_cmd_stream_eof; - ngx_rtmp_stream_dry = ngx_rtmp_cmd_stream_dry; - ngx_rtmp_recorded = ngx_rtmp_cmd_recorded; - ngx_rtmp_set_buflen = ngx_rtmp_cmd_set_buflen; - - return NGX_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_cmd_module.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_cmd_module.h deleted file mode 100644 index 5bc3c03caf..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_cmd_module.h +++ /dev/null @@ -1,166 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#ifndef _NGX_RTMP_CMD_H_INCLUDED_ -#define _NGX_RTMP_CMD_H_INCLUDED_ - - -#include -#include -#include -#include "ngx_rtmp.h" - - -#define NGX_RTMP_MAX_NAME 256 -#define NGX_RTMP_MAX_FLASHVER 256 -#define NGX_RTMP_MAX_URL 256 -#define NGX_RTMP_MAX_SESSION 256 -#define NGX_RTMP_MAX_ARGS NGX_RTMP_MAX_NAME - - -/* Basic RTMP call support */ - -typedef struct { - double trans; - u_char app[NGX_RTMP_MAX_NAME]; - u_char args[NGX_RTMP_MAX_ARGS]; - u_char flashver[NGX_RTMP_MAX_FLASHVER]; - u_char swf_url[NGX_RTMP_MAX_URL]; - u_char tc_url[NGX_RTMP_MAX_URL]; - double acodecs; - double vcodecs; - u_char page_url[NGX_RTMP_MAX_URL]; - double object_encoding; -} ngx_rtmp_connect_t; - - -typedef struct { - double trans; - double stream; -} ngx_rtmp_create_stream_t; - - -typedef struct { - double stream; -} ngx_rtmp_delete_stream_t; - - -typedef struct { - double stream; -} ngx_rtmp_close_stream_t; - - -typedef struct { - u_char name[NGX_RTMP_MAX_NAME]; - u_char args[NGX_RTMP_MAX_ARGS]; - u_char type[16]; - int silent; -} ngx_rtmp_publish_t; - - -typedef struct { - u_char name[NGX_RTMP_MAX_NAME]; - u_char args[NGX_RTMP_MAX_ARGS]; - u_char session[NGX_RTMP_MAX_SESSION]; - double start; - double duration; - int reset; - int silent; -} ngx_rtmp_play_t; - - -typedef struct { - double offset; -} ngx_rtmp_seek_t; - - -typedef struct { - uint8_t pause; - double position; -} ngx_rtmp_pause_t; - - -typedef struct { - uint32_t msid; -} ngx_rtmp_msid_t; - - -typedef ngx_rtmp_msid_t ngx_rtmp_stream_begin_t; -typedef ngx_rtmp_msid_t ngx_rtmp_stream_eof_t; -typedef ngx_rtmp_msid_t ngx_rtmp_stream_dry_t; -typedef ngx_rtmp_msid_t ngx_rtmp_recorded_t; - - -typedef struct { - uint32_t msid; - uint32_t buflen; -} ngx_rtmp_set_buflen_t; - - -void ngx_rtmp_cmd_fill_args(u_char name[NGX_RTMP_MAX_NAME], - u_char args[NGX_RTMP_MAX_ARGS]); -void ngx_rtmp_cmd_middleware_init(ngx_rtmp_session_t *s); -void ngx_rtmp_cmd_stream_init(ngx_rtmp_session_t *s, u_char *name, u_char *args, - unsigned publishing); - -ngx_int_t ngx_rtmp_publish_filter(ngx_rtmp_session_t *s, - ngx_rtmp_publish_t *v); -ngx_int_t ngx_rtmp_play_filter(ngx_rtmp_session_t *s, - ngx_rtmp_play_t *v); -ngx_int_t ngx_rtmp_close_stream_filter(ngx_rtmp_session_t *s, - ngx_rtmp_close_stream_t *v); - -ngx_int_t ngx_rtmp_push_filter(ngx_rtmp_session_t *s); -ngx_int_t ngx_rtmp_pull_filter(ngx_rtmp_session_t *s); - -typedef ngx_int_t (*ngx_rtmp_connect_pt)(ngx_rtmp_session_t *s, - ngx_rtmp_connect_t *v); -typedef ngx_int_t (*ngx_rtmp_disconnect_pt)(ngx_rtmp_session_t *s); -typedef ngx_int_t (*ngx_rtmp_create_stream_pt)(ngx_rtmp_session_t *s, - ngx_rtmp_create_stream_t *v); -typedef ngx_int_t (*ngx_rtmp_close_stream_pt)(ngx_rtmp_session_t *s, - ngx_rtmp_close_stream_t *v); -typedef ngx_int_t (*ngx_rtmp_delete_stream_pt)(ngx_rtmp_session_t *s, - ngx_rtmp_delete_stream_t *v); -typedef ngx_int_t (*ngx_rtmp_publish_pt)(ngx_rtmp_session_t *s, - ngx_rtmp_publish_t *v); -typedef ngx_int_t (*ngx_rtmp_play_pt)(ngx_rtmp_session_t *s, - ngx_rtmp_play_t *v); -typedef ngx_int_t (*ngx_rtmp_seek_pt)(ngx_rtmp_session_t *s, - ngx_rtmp_seek_t *v); -typedef ngx_int_t (*ngx_rtmp_pause_pt)(ngx_rtmp_session_t *s, - ngx_rtmp_pause_t *v); - -typedef ngx_int_t (*ngx_rtmp_stream_begin_pt)(ngx_rtmp_session_t *s, - ngx_rtmp_stream_begin_t *v); -typedef ngx_int_t (*ngx_rtmp_stream_eof_pt)(ngx_rtmp_session_t *s, - ngx_rtmp_stream_eof_t *v); -typedef ngx_int_t (*ngx_rtmp_stream_dry_pt)(ngx_rtmp_session_t *s, - ngx_rtmp_stream_dry_t *v); -typedef ngx_int_t (*ngx_rtmp_recorded_pt)(ngx_rtmp_session_t *s, - ngx_rtmp_recorded_t *v); -typedef ngx_int_t (*ngx_rtmp_set_buflen_pt)(ngx_rtmp_session_t *s, - ngx_rtmp_set_buflen_t *v); - - -extern ngx_rtmp_connect_pt ngx_rtmp_connect; -extern ngx_rtmp_disconnect_pt ngx_rtmp_disconnect; -extern ngx_rtmp_create_stream_pt ngx_rtmp_create_stream; -extern ngx_rtmp_close_stream_pt ngx_rtmp_close_stream; -extern ngx_rtmp_delete_stream_pt ngx_rtmp_delete_stream; -extern ngx_rtmp_publish_pt ngx_rtmp_publish; -extern ngx_rtmp_play_pt ngx_rtmp_play; -extern ngx_rtmp_seek_pt ngx_rtmp_seek; -extern ngx_rtmp_pause_pt ngx_rtmp_pause; - -extern ngx_rtmp_stream_begin_pt ngx_rtmp_stream_begin; -extern ngx_rtmp_stream_eof_pt ngx_rtmp_stream_eof; -extern ngx_rtmp_stream_dry_pt ngx_rtmp_stream_dry; -extern ngx_rtmp_set_buflen_pt ngx_rtmp_set_buflen; -extern ngx_rtmp_recorded_pt ngx_rtmp_recorded; - - -#endif /*_NGX_RTMP_CMD_H_INCLUDED_ */ diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_codec_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_codec_module.c deleted file mode 100644 index 9fe27b60e8..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_codec_module.c +++ /dev/null @@ -1,1376 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include -#include "ngx_rtmp_codec_module.h" -#include "ngx_rtmp_live_module.h" -#include "ngx_rtmp_cmd_module.h" -#include "ngx_rtmp_bitop.h" -#include "ngx_rbuf.h" - - -#define NGX_RTMP_CODEC_META_OFF 0 -#define NGX_RTMP_CODEC_META_ON 1 -#define NGX_RTMP_CODEC_META_COPY 2 - - -static void * ngx_rtmp_codec_create_app_conf(ngx_conf_t *cf); -static char * ngx_rtmp_codec_merge_app_conf(ngx_conf_t *cf, - void *parent, void *child); -static ngx_int_t ngx_rtmp_codec_postconfiguration(ngx_conf_t *cf); -static ngx_int_t ngx_rtmp_codec_reconstruct_meta(ngx_rtmp_session_t *s); -static ngx_int_t ngx_rtmp_codec_copy_meta(ngx_rtmp_session_t *s, - ngx_rtmp_header_t *h, ngx_chain_t *in); -static ngx_int_t ngx_rtmp_codec_prepare_meta(ngx_rtmp_session_t *s, - uint32_t timestamp); -static void ngx_rtmp_codec_parse_aac_header(ngx_rtmp_session_t *s, - ngx_chain_t *in); -static void ngx_rtmp_codec_parse_avc_header(ngx_rtmp_session_t *s, - ngx_chain_t *in); -static void ngx_rtmp_codec_parse_hevc_header(ngx_rtmp_session_t *s, - ngx_chain_t *in); -#if (NGX_DEBUG) -static void ngx_rtmp_codec_dump_header(ngx_rtmp_session_t *s, const char *type, - ngx_chain_t *in); -#endif - - -typedef struct { - ngx_uint_t meta; -} ngx_rtmp_codec_app_conf_t; - - -static ngx_conf_enum_t ngx_rtmp_codec_meta_slots[] = { - { ngx_string("off"), NGX_RTMP_CODEC_META_OFF }, - { ngx_string("on"), NGX_RTMP_CODEC_META_ON }, - { ngx_string("copy"), NGX_RTMP_CODEC_META_COPY }, - { ngx_null_string, 0 } -}; - - -static ngx_command_t ngx_rtmp_codec_commands[] = { - - { ngx_string("meta"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_enum_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_codec_app_conf_t, meta), - &ngx_rtmp_codec_meta_slots }, - - ngx_null_command -}; - - -static ngx_rtmp_module_t ngx_rtmp_codec_module_ctx = { - NULL, /* preconfiguration */ - ngx_rtmp_codec_postconfiguration, /* postconfiguration */ - NULL, /* create main configuration */ - NULL, /* init main configuration */ - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - ngx_rtmp_codec_create_app_conf, /* create app configuration */ - ngx_rtmp_codec_merge_app_conf /* merge app configuration */ -}; - - -ngx_module_t ngx_rtmp_codec_module = { - NGX_MODULE_V1, - &ngx_rtmp_codec_module_ctx, /* module context */ - ngx_rtmp_codec_commands, /* module directives */ - NGX_RTMP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static const char * -audio_codecs[] = { - "", - "ADPCM", - "MP3", - "LinearLE", - "Nellymoser16", - "Nellymoser8", - "Nellymoser", - "G711A", - "G711U", - "", - "AAC", - "Speex", - "", - "", - "MP3-8K", - "DeviceSpecific", - "Uncompressed" -}; - - -static const char * -video_codecs[] = { - "", - "Jpeg", - "Sorenson-H263", - "ScreenVideo", - "On2-VP6", - "On2-VP6-Alpha", - "ScreenVideo2", - "H264", -}; - - -u_char * -ngx_rtmp_get_audio_codec_name(ngx_uint_t id) -{ - return (u_char *)(id < sizeof(audio_codecs) / sizeof(audio_codecs[0]) - ? audio_codecs[id] - : ""); -} - - -u_char * -ngx_rtmp_get_video_codec_name(ngx_uint_t id) -{ - return (u_char *)(id < sizeof(video_codecs) / sizeof(video_codecs[0]) - ? video_codecs[id] - : ""); -} - - -static ngx_uint_t -ngx_rtmp_codec_get_next_version() -{ - ngx_uint_t v; - static ngx_uint_t version; - - do { - v = ++version; - } while (v == 0); - - return v; -} - - -static ngx_int_t -ngx_rtmp_codec_disconnect(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - ngx_rtmp_codec_ctx_t *ctx; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - if (ctx == NULL) { - return NGX_OK; - } - - if (ctx->avc_header) { - ngx_rtmp_shared_free_frame(ctx->avc_header); - ctx->avc_header = NULL; - } - - if (ctx->aac_header) { - ngx_rtmp_shared_free_frame(ctx->aac_header); - ctx->aac_header = NULL; - } - - if (ctx->meta) { - ngx_rtmp_shared_free_frame(ctx->meta); - ctx->meta = NULL; - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_codec_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - ngx_rtmp_core_srv_conf_t *cscf; - ngx_rtmp_core_app_conf_t *cacf; - ngx_rtmp_codec_ctx_t *ctx; - ngx_rtmp_frame_t **header; - uint8_t fmt; - u_char frametype; - static ngx_uint_t sample_rates[] = - { 5512, 11025, 22050, 44100 }; - - if (h->type != NGX_RTMP_MSG_AUDIO && h->type != NGX_RTMP_MSG_VIDEO) { - return NGX_OK; - } - - if (h->type == NGX_RTMP_MSG_VIDEO) { - frametype = in->buf->pos[0] & 0xf0; - if (frametype != 0x10 && frametype != 0x20) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "codec: receive unkwnon frametype %02xD", frametype); - return NGX_OK; - } - } - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - if (ctx == NULL) { - ctx = ngx_pcalloc(s->pool, sizeof(ngx_rtmp_codec_ctx_t)); - ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_codec_module); - } - - /* save codec */ - if (in->buf->last - in->buf->pos < 1) { - return NGX_OK; - } - - fmt = in->buf->pos[0]; - if (h->type == NGX_RTMP_MSG_AUDIO) { - ctx->audio_codec_id = (fmt & 0xf0) >> 4; - ctx->audio_channels = (fmt & 0x01) + 1; - ctx->sample_size = (fmt & 0x02) ? 2 : 1; - - if (ctx->sample_rate == 0) { - ctx->sample_rate = sample_rates[(fmt & 0x0c) >> 2]; - } - s->acodec = ctx->audio_codec_id; - } else { - ctx->video_codec_id = (fmt & 0x0f); - s->vcodec = ctx->video_codec_id; - } - - /* save AVC/AAC header */ - if (in->buf->last - in->buf->pos < 3) { - return NGX_OK; - } - - /* no conf */ - if (!ngx_rtmp_is_codec_header(in)) { - return NGX_OK; - } - - cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module); - cacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_core_module); - header = NULL; - - if (h->type == NGX_RTMP_MSG_AUDIO) { - if (ctx->audio_codec_id == NGX_RTMP_AUDIO_AAC) { - header = &ctx->aac_header; - ngx_rtmp_codec_parse_aac_header(s, in); - } - } else { - if (ctx->video_codec_id == NGX_RTMP_VIDEO_H264) { - header = &ctx->avc_header; - ngx_rtmp_codec_parse_avc_header(s, in); - } else if (ctx->video_codec_id == cacf->hevc_codec) { - header = &ctx->avc_header; - ngx_rtmp_codec_parse_hevc_header(s, in); - } - } - - if (header == NULL) { - return NGX_OK; - } - - if (*header) { - ngx_rtmp_shared_free_frame(*header); - } - - *header = ngx_rtmp_shared_alloc_frame(cscf->chunk_size, in, 0); - - return NGX_OK; -} - - -static void -ngx_rtmp_codec_parse_aac_header(ngx_rtmp_session_t *s, ngx_chain_t *in) -{ - ngx_uint_t idx; - ngx_rtmp_codec_ctx_t *ctx; - ngx_rtmp_bit_reader_t br; - - static ngx_uint_t aac_sample_rates[] = - { 96000, 88200, 64000, 48000, - 44100, 32000, 24000, 22050, - 16000, 12000, 11025, 8000, - 7350, 0, 0, 0 }; - -#if (NGX_DEBUG) - ngx_rtmp_codec_dump_header(s, "aac", in); -#endif - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - - ngx_rtmp_bit_init_reader(&br, in->buf->pos, in->buf->last); - - ngx_rtmp_bit_read(&br, 16); - - ctx->aac_profile = (ngx_uint_t) ngx_rtmp_bit_read(&br, 5); - if (ctx->aac_profile == 31) { - ctx->aac_profile = (ngx_uint_t) ngx_rtmp_bit_read(&br, 6) + 32; - } - - idx = (ngx_uint_t) ngx_rtmp_bit_read(&br, 4); - if (idx == 15) { - ctx->sample_rate = (ngx_uint_t) ngx_rtmp_bit_read(&br, 24); - } else { - ctx->sample_rate = aac_sample_rates[idx]; - } - - ctx->aac_chan_conf = (ngx_uint_t) ngx_rtmp_bit_read(&br, 4); - - if (ctx->aac_profile == 5 || ctx->aac_profile == 29) { - - if (ctx->aac_profile == 29) { - ctx->aac_ps = 1; - } - - ctx->aac_sbr = 1; - - idx = (ngx_uint_t) ngx_rtmp_bit_read(&br, 4); - if (idx == 15) { - ctx->sample_rate = (ngx_uint_t) ngx_rtmp_bit_read(&br, 24); - } else { - ctx->sample_rate = aac_sample_rates[idx]; - } - - ctx->aac_profile = (ngx_uint_t) ngx_rtmp_bit_read(&br, 5); - if (ctx->aac_profile == 31) { - ctx->aac_profile = (ngx_uint_t) ngx_rtmp_bit_read(&br, 6) + 32; - } - } - - /* MPEG-4 Audio Specific Config - - 5 bits: object type - if (object type == 31) - 6 bits + 32: object type - 4 bits: frequency index - if (frequency index == 15) - 24 bits: frequency - 4 bits: channel configuration - - if (object_type == 5) - 4 bits: frequency index - if (frequency index == 15) - 24 bits: frequency - 5 bits: object type - if (object type == 31) - 6 bits + 32: object type - - var bits: AOT Specific Config - */ - - ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->log, 0, - "codec: aac header profile=%ui, " - "sample_rate=%ui, chan_conf=%ui", - ctx->aac_profile, ctx->sample_rate, ctx->aac_chan_conf); -} - - -/* - * ITU-T H.265 7.3.1 General NAL unit syntax - */ -static ngx_int_t -ngx_rtmp_codec_parse_hevc_nal_to_rbsp(ngx_rtmp_session_t *s, u_char *p, - ngx_rtmp_bit_reader_t *br, ngx_uint_t nal_unit_type, - ngx_uint_t nal_unit_len) -{ - ngx_uint_t i, count, rbsp_bytes; - - /* - * nal_unit - * nal_unit_header() - * NumBytesInRbsp = 0 - * for (i = 2; i < NumBytesInNalUnit; i++) - * if (i + 2 < NumBytesInNalUnit && next_bits(24) == 0x000003) { - * rbsp_byte[NumBytesInRbsp++] - * rbsp_byte[NumBytesInRbsp++] - * i += 2 - * emulation_prevention_three_byte // equal to 0x03 - * } else - * rbsp_byte[NumBytesInRbsp++] - * - * nal_unit_header - * forbidden_zero_bit 1 bit - * nal_unit_type 6 bits - * nuh_layer_id 6 bits - * nuh_temporal_id_plus1 3 bits - * - * ITU-T H.265 7.4.2.1 - * emulation_prevention_three_byte is a byte equal to 0x03. - * When an emulation_prevention_three_byte is present in the NAL unit, - * it shall be discarded by the decoding process - * Within the NAL unit, the following three-byte sequences shall not - * occur at any byte-aligned position: - * 0x000000 - * 0x000001 - * 0x000002 - * Within the NAL unit, any four-byte sequence that starts with - * 0x000003 other than the following sequences shall not occur at - * any byte-aligned position: - * 0x00000300 - * 0x00000301 - * 0x00000302 - * 0x00000303 - */ - - ngx_rtmp_bit_read(br, 1); - if (ngx_rtmp_bit_read(br, 6) != nal_unit_type) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "nal_unit_type not expect %ui", nal_unit_type); - return NGX_ERROR; - } - ngx_rtmp_bit_read(br, 6); - ngx_rtmp_bit_read(br, 3); - - count = 0; - rbsp_bytes = 0; - for (i = 0; i < nal_unit_len; ++i) { - if (count == 2) { /* already 0x0000 */ - if (br->pos[i] < 0x03) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "three bytes sequence error"); - return NGX_ERROR; - } - - if (br->pos[i] == 0x03 && br->pos[i + 1] > 0x03) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "four bytes sequence error"); - return NGX_ERROR; - } - - if (br->pos[i] == 0x03) { - count = 0; - continue; - } - } - - *p++ = br->pos[i]; - ++rbsp_bytes; - if (br->pos[i] == 0x00) { - ++count; - } else { - count = 0; - } - } - - return rbsp_bytes; -} - -/* - * ITU-T H.265 7.3.3 Profile, tier and level syntax - */ -static void -ngx_rtmp_codec_parse_hevc_ptl(ngx_rtmp_session_t *s, ngx_rtmp_bit_reader_t *br, - ngx_flag_t profilePresentFlag, ngx_uint_t maxNumSubLayersMinus1) -{ - ngx_uint_t i, slppf[8], sllpf[8]; - - if (profilePresentFlag) { - /* - * profile_tier_level - * general_profile_space 2 bits - * general_tier_flag 1 bit - * general_profile_idc 5 bits - * for (j = 0; j < 32; j++) - * general_profile_compatibility_flag[j] 1 bit - * general_progressive_source_flag 1 bit - * general_interlaced_source_flag 1 bit - * general_non_packed_constraint_flag 1 bit - * general_frame_only_constraint_flag 1 bit - * - * general_max_12bit_constraint_flag 1 bit - * general_max_10bit_constraint_flag 1 bit - * general_max_8bit_constraint_flag 1 bit - * general_max_422chroma_constraint_flag 1 bit - * general_max_420chroma_constraint_flag 1 bit - * general_max_monochrome_constraint_flag 1 bit - * general_intra_constraint_flag 1 bit - * general_one_picture_only_constraint_flag 1 bit - * general_lower_bit_rate_constraint_flag 1 bit - * general_reserved_zero_34bits 34 bits - * - * general_inbld_flag 1 bit - */ - ngx_rtmp_bit_read(br, 88); - } - - /* - * profile_tier_level - * general_level_idc 8 bits - */ - ngx_rtmp_bit_read(br, 8); - - /* - * profile_tier_level - * for(i = 0; i < maxNumSubLayersMinus1; i++) { - * sub_layer_profile_present_flag[i] 1 bit - * sub_layer_level_present_flag[i] 1 bit - * } - * - * if (maxNumSubLayersMinus1 > 0) - * for(i = maxNumSubLayersMinus1; i < 8; i++) - * reserved_zero_2bits[i] 2 bits - */ - for (i = 0; i < maxNumSubLayersMinus1; ++i) { - slppf[i] = ngx_rtmp_bit_read(br, 1); - sllpf[i] = ngx_rtmp_bit_read(br, 1); - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "%d sub_layer_profile_present_flag:%d, " - "sub_layer_level_present_flag:%d", i, slppf[i], sllpf[i]); - } - - if (maxNumSubLayersMinus1 > 0) { - for (i = maxNumSubLayersMinus1; i < 8; ++i) { - ngx_uint_t t = ngx_rtmp_bit_read(br, 2); - ngx_log_error(NGX_LOG_ERR, s->log, 0, "zero bit %d", t); - } - } - - /* - * profile_tier_level - * for (i = 0; i < maxNumSubLayersMinus1; i++) { - * if (sub_layer_profile_present_flag[i] { - * 44 bits - * } - * if (sub_layer_level_present_flag[i]) { - * sub_layer_level_idc[i] 8 bits - * } - * } - */ - for (i = 0; i < maxNumSubLayersMinus1; ++i) { - if (slppf[i]) { - ngx_rtmp_bit_read(br, 88); - } - - if (sllpf[i]) { - ngx_rtmp_bit_read(br, 8); - } - } -} - -/* - * ITU-T H.265 7.3.2.2 Sequence parameter set RBSP syntax - */ -static void -ngx_rtmp_codec_parse_hevc_sps(ngx_rtmp_session_t *s, ngx_rtmp_codec_ctx_t *ctx, - ngx_rtmp_bit_reader_t *pbr, ngx_uint_t nal_unit_len) -{ - ngx_uint_t mslm, psi, cfi, width, height, - subwidthC, subheightC, - cwlo, cwro, cwto, cwbo; - ngx_rtmp_bit_reader_t br; - u_char buf[4096]; - ngx_int_t rbsp_bytes; - - ngx_rtmp_bit_init_reader(&br, pbr->pos, pbr->pos + nal_unit_len); - rbsp_bytes = ngx_rtmp_codec_parse_hevc_nal_to_rbsp(s, buf, &br, NAL_SPS, - nal_unit_len); - if (rbsp_bytes == NGX_ERROR) { - return; - } - - ngx_rtmp_bit_init_reader(&br, buf, buf + rbsp_bytes); - - /* - * seq_parameter_set_rbsp - * sps_video_parameter_set_id 4 bits - * sps_max_sub_layers_minus1 3 bits - * sps_temporal_id_nesting_flag 1 bit - */ - ngx_rtmp_bit_read(&br, 4); - mslm = ngx_rtmp_bit_read(&br, 3); - ngx_rtmp_bit_read(&br, 1); - - /* - * seq_parameter_set_rbsp - * profile_tier_level(1, sps_max_sub_layers_minus1) - */ - ngx_rtmp_codec_parse_hevc_ptl(s, &br, 1, mslm); - - /* calc resolution */ - /* - * seq_parameter_set_rbsp - * sps_seq_parameter_set_id v - * chroma_format_idc v - * if (chroma_format_idc == 3) - * separate_colour_plane_flag 1 bit - * pic_width_in_luma_samples v - * pic_height_in_luma_samples v - * conformance_window_flag 1 bit - * if (conformance_window_flag) { - * conf_win_left_offset v - * conf_win_right_offset v - * conf_win_top_offset v - * conf_win_bottom_offset v - * } - */ - psi = ngx_rtmp_bit_read_golomb(&br); - if (psi > 16 || br.err) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "read sps_seq_parameter_set_id error: %ui", psi); - return; - } - - cfi = ngx_rtmp_bit_read_golomb(&br); - if (cfi > 3 || br.err) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "read chroma_format_idc error: %ui", cfi); - return; - } - - if (cfi == 3) { - ngx_rtmp_bit_read(&br, 1); - } - - width = (ngx_uint_t) ngx_rtmp_bit_read_golomb(&br); - if (br.err) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, "read width error"); - return; - } - - height = (ngx_uint_t) ngx_rtmp_bit_read_golomb(&br); - if (br.err) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, "read height error"); - return; - } - - if (ngx_rtmp_bit_read(&br, 1)) { - cwlo = (ngx_uint_t) ngx_rtmp_bit_read_golomb(&br); - cwro = (ngx_uint_t) ngx_rtmp_bit_read_golomb(&br); - cwto = (ngx_uint_t) ngx_rtmp_bit_read_golomb(&br); - cwbo = (ngx_uint_t) ngx_rtmp_bit_read_golomb(&br); - - /* - * ITU-T H.265 Table 6-1 - */ - if (cfi == 1) { /* 4:2:0 */ - subwidthC = 2; - subheightC = 2; - } else if (cfi == 2) { /* 4:2:2 */ - subwidthC = 2; - subheightC = 1; - } else { /* Monochrome or 4:4:4 */ - subwidthC = 1; - subheightC = 1; - } - - /* - * ITU-T H.265 7.4.3.2.1 - * - * horizontal picture coordinates from - * SubWidthC * conf_win_left_offset to - * pic_width_in_luma_samples - (SubWidthC * conf_win_right_offset + 1) - * vertical picture coordinates from - * SubHeightC * conf_win_top_offset to - * pic_height_in_luma_samples - - * (SubHeightC * conf_win_bottom_offset + 1) - */ - ctx->width = width - (subwidthC * cwro + 1) - (subwidthC * cwlo); - ctx->height = height - (subheightC * cwbo + 1) - (subheightC * cwto); - } else { - ctx->width = width; - ctx->height = height; - } - - return; -} - -static void -ngx_rtmp_codec_parse_hevc_header(ngx_rtmp_session_t *s, ngx_chain_t *in) -{ - ngx_uint_t i, j, num_arrays, nal_unit_type, num_nalus, - nal_unit_len; - ngx_rtmp_codec_ctx_t *ctx; - ngx_rtmp_bit_reader_t br; - -#if (NGX_DEBUG) - ngx_rtmp_codec_dump_header(s, "hevc", in); -#endif - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - - ngx_rtmp_bit_init_reader(&br, in->buf->pos, in->buf->last); - - /* - * FrameType 4 bits - * CodecID 4 bits - * AVCPacketType 1 byte - * CompositionTime 3 bytes - * HEVCDecoderConfigurationRecord - * configurationVersion 1 byte - */ - ngx_rtmp_bit_read(&br, 48); - - /* - * HEVCDecoderConfigurationRecord - * general_profile_space 2 bits - * general_tier_flag 1 bit - * general_profile_idc 5 bits - * general_profile_compatibility_flags 4 bytes - * general_constraint_indicator_flags 6 bytes - * general_level_idc 1 byte - * min_spatial_segmentation_idc 4 bits reserved + 12 bits - * parallelismType 6 bits reserved + 2 bits - * chroma_format_idc 6 bits reserved + 2 bits - * bit_depth_luma_minus8 5 bits reserved + 3 bits - * bit_depth_chroma_minus8 5 bits reserved + 3 bits - * avgFrameRate 2 bytes - */ - ngx_rtmp_bit_read(&br, 160); - - /* - * HEVCDecoderConfigurationRecord - * constantFrameRate 2 bits - * numTemporalLayers 3 bits - * temporalIdNested 1 bit - * lengthSizeMinusOne 2 bits - */ - ctx->avc_nal_bytes = (ngx_uint_t) ((ngx_rtmp_bit_read_8(&br) & 0x03) + 1); - - /* - * HEVCDecoderConfigurationRecord - * numOfArrays 1 byte - */ - num_arrays = (ngx_uint_t) ngx_rtmp_bit_read_8(&br); - - for (i = 0; i < num_arrays; ++i) { - /* - * array_completeness 1 bit - * reserved 1 bit - * NAL_unit_type 6 bits - * numNalus 2 bytes - */ - nal_unit_type = (ngx_uint_t) (ngx_rtmp_bit_read_8(&br) & 0x3f); - num_nalus = (ngx_uint_t) ngx_rtmp_bit_read_16(&br); - - for (j = 0; j < num_nalus; ++j) { - /* - * nalUnitLength 2 bytes - */ - nal_unit_len = (ngx_uint_t) ngx_rtmp_bit_read_16(&br); - - switch (nal_unit_type) { - case NAL_SPS: - ngx_rtmp_codec_parse_hevc_sps(s, ctx, &br, nal_unit_len); - ngx_rtmp_bit_read(&br, nal_unit_len * 8); - break; - default: - ngx_rtmp_bit_read(&br, nal_unit_len * 8); - break; - } - } - } - - ngx_log_debug7(NGX_LOG_DEBUG_RTMP, s->log, 0, - "codec: hevc header " - "profile=%ui, compat=%ui, level=%ui, " - "nal_bytes=%ui, ref_frames=%ui, width=%ui, height=%ui", - ctx->avc_profile, ctx->avc_compat, ctx->avc_level, - ctx->avc_nal_bytes, ctx->avc_ref_frames, - ctx->width, ctx->height); -} - - -static void -ngx_rtmp_codec_parse_avc_header(ngx_rtmp_session_t *s, ngx_chain_t *in) -{ - ngx_uint_t profile_idc, width, height, crop_left, crop_right, - crop_top, crop_bottom, frame_mbs_only, n, cf_idc, - num_ref_frames; - ngx_rtmp_codec_ctx_t *ctx; - ngx_rtmp_bit_reader_t br; - -#if (NGX_DEBUG) - ngx_rtmp_codec_dump_header(s, "avc", in); -#endif - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - - ngx_rtmp_bit_init_reader(&br, in->buf->pos, in->buf->last); - - ngx_rtmp_bit_read(&br, 48); - - ctx->avc_profile = (ngx_uint_t) ngx_rtmp_bit_read_8(&br); - ctx->avc_compat = (ngx_uint_t) ngx_rtmp_bit_read_8(&br); - ctx->avc_level = (ngx_uint_t) ngx_rtmp_bit_read_8(&br); - - /* nal bytes */ - ctx->avc_nal_bytes = (ngx_uint_t) ((ngx_rtmp_bit_read_8(&br) & 0x03) + 1); - - /* nnals */ - if ((ngx_rtmp_bit_read_8(&br) & 0x1f) == 0) { - return; - } - - /* nal size */ - ngx_rtmp_bit_read(&br, 16); - - /* nal type */ - if (ngx_rtmp_bit_read_8(&br) != 0x67) { - return; - } - - /* SPS */ - - /* profile idc */ - profile_idc = (ngx_uint_t) ngx_rtmp_bit_read(&br, 8); - - /* flags */ - ngx_rtmp_bit_read(&br, 8); - - /* level idc */ - ngx_rtmp_bit_read(&br, 8); - - /* SPS id */ - ngx_rtmp_bit_read_golomb(&br); - - if (profile_idc == 100 || profile_idc == 110 || - profile_idc == 122 || profile_idc == 244 || profile_idc == 44 || - profile_idc == 83 || profile_idc == 86 || profile_idc == 118) - { - /* chroma format idc */ - cf_idc = (ngx_uint_t) ngx_rtmp_bit_read_golomb(&br); - - if (cf_idc == 3) { - - /* separate color plane */ - ngx_rtmp_bit_read(&br, 1); - } - - /* bit depth luma - 8 */ - ngx_rtmp_bit_read_golomb(&br); - - /* bit depth chroma - 8 */ - ngx_rtmp_bit_read_golomb(&br); - - /* qpprime y zero transform bypass */ - ngx_rtmp_bit_read(&br, 1); - - /* seq scaling matrix present */ - if (ngx_rtmp_bit_read(&br, 1)) { - - for (n = 0; n < (cf_idc != 3 ? 8u : 12u); n++) { - - /* seq scaling list present */ - if (ngx_rtmp_bit_read(&br, 1)) { - - /* TODO: scaling_list() - if (n < 6) { - } else { - } - */ - } - } - } - } - - /* log2 max frame num */ - ngx_rtmp_bit_read_golomb(&br); - - /* pic order cnt type */ - switch (ngx_rtmp_bit_read_golomb(&br)) { - case 0: - - /* max pic order cnt */ - ngx_rtmp_bit_read_golomb(&br); - break; - - case 1: - - /* delta pic order alwys zero */ - ngx_rtmp_bit_read(&br, 1); - - /* offset for non-ref pic */ - ngx_rtmp_bit_read_golomb(&br); - - /* offset for top to bottom field */ - ngx_rtmp_bit_read_golomb(&br); - - /* num ref frames in pic order */ - num_ref_frames = (ngx_uint_t) ngx_rtmp_bit_read_golomb(&br); - - for (n = 0; n < num_ref_frames; n++) { - - /* offset for ref frame */ - ngx_rtmp_bit_read_golomb(&br); - } - } - - /* num ref frames */ - ctx->avc_ref_frames = (ngx_uint_t) ngx_rtmp_bit_read_golomb(&br); - - /* gaps in frame num allowed */ - ngx_rtmp_bit_read(&br, 1); - - /* pic width in mbs - 1 */ - width = (ngx_uint_t) ngx_rtmp_bit_read_golomb(&br); - - /* pic height in map units - 1 */ - height = (ngx_uint_t) ngx_rtmp_bit_read_golomb(&br); - - /* frame mbs only flag */ - frame_mbs_only = (ngx_uint_t) ngx_rtmp_bit_read(&br, 1); - - if (!frame_mbs_only) { - - /* mbs adaprive frame field */ - ngx_rtmp_bit_read(&br, 1); - } - - /* direct 8x8 inference flag */ - ngx_rtmp_bit_read(&br, 1); - - /* frame cropping */ - if (ngx_rtmp_bit_read(&br, 1)) { - - crop_left = (ngx_uint_t) ngx_rtmp_bit_read_golomb(&br); - crop_right = (ngx_uint_t) ngx_rtmp_bit_read_golomb(&br); - crop_top = (ngx_uint_t) ngx_rtmp_bit_read_golomb(&br); - crop_bottom = (ngx_uint_t) ngx_rtmp_bit_read_golomb(&br); - - } else { - - crop_left = 0; - crop_right = 0; - crop_top = 0; - crop_bottom = 0; - } - - ctx->width = (width + 1) * 16 - (crop_left + crop_right) * 2; - ctx->height = (2 - frame_mbs_only) * (height + 1) * 16 - - (crop_top + crop_bottom) * 2; - - ngx_log_debug7(NGX_LOG_DEBUG_RTMP, s->log, 0, - "codec: avc header " - "profile=%ui, compat=%ui, level=%ui, " - "nal_bytes=%ui, ref_frames=%ui, width=%ui, height=%ui", - ctx->avc_profile, ctx->avc_compat, ctx->avc_level, - ctx->avc_nal_bytes, ctx->avc_ref_frames, - ctx->width, ctx->height); -} - - -#if (NGX_DEBUG) -static void -ngx_rtmp_codec_dump_header(ngx_rtmp_session_t *s, const char *type, - ngx_chain_t *in) -{ - u_char buf[256], *p, *pp; - u_char hex[] = "0123456789abcdef"; - - for (pp = buf, p = in->buf->pos; - p < in->buf->last && pp < buf + sizeof(buf) - 1; - ++p) - { - *pp++ = hex[*p >> 4]; - *pp++ = hex[*p & 0x0f]; - } - - *pp = 0; - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->log, 0, - "codec: %s header %s", type, buf); -} -#endif - - -static ngx_int_t -ngx_rtmp_codec_reconstruct_meta(ngx_rtmp_session_t *s) -{ - ngx_rtmp_codec_ctx_t *ctx; - ngx_rtmp_core_srv_conf_t *cscf; - ngx_int_t rc; - - static struct { - double width; - double height; - double duration; - double frame_rate; - double video_data_rate; - double video_codec_id; - double audio_data_rate; - double audio_codec_id; - u_char profile[32]; - u_char level[32]; - } v; - - static ngx_rtmp_amf_elt_t out_inf[] = { - - { NGX_RTMP_AMF_STRING, - ngx_string("Server"), - "PingOS (https://pingos.io)", 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_string("width"), - &v.width, 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_string("height"), - &v.height, 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_string("displayWidth"), - &v.width, 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_string("displayHeight"), - &v.height, 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_string("duration"), - &v.duration, 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_string("framerate"), - &v.frame_rate, 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_string("fps"), - &v.frame_rate, 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_string("videodatarate"), - &v.video_data_rate, 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_string("videocodecid"), - &v.video_codec_id, 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_string("audiodatarate"), - &v.audio_data_rate, 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_string("audiocodecid"), - &v.audio_codec_id, 0 }, - - { NGX_RTMP_AMF_STRING, - ngx_string("profile"), - &v.profile, sizeof(v.profile) }, - - { NGX_RTMP_AMF_STRING, - ngx_string("level"), - &v.level, sizeof(v.level) }, - }; - - static ngx_rtmp_amf_elt_t out_elts[] = { - - { NGX_RTMP_AMF_STRING, - ngx_null_string, - "onMetaData", 0 }, - - { NGX_RTMP_AMF_OBJECT, - ngx_null_string, - out_inf, sizeof(out_inf) }, - }; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - if (ctx == NULL) { - return NGX_OK; - } - - if (ctx->meta) { - ngx_rtmp_shared_free_frame(ctx->meta); - } - - cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module); - - ctx->meta = ngx_rtmp_shared_alloc_frame(cscf->chunk_size, NULL, 1); - - v.width = ctx->width; - v.height = ctx->height; - v.duration = ctx->duration; - v.frame_rate = ctx->frame_rate; - v.video_data_rate = ctx->video_data_rate; - v.video_codec_id = ctx->video_codec_id; - v.audio_data_rate = ctx->audio_data_rate; - v.audio_codec_id = ctx->audio_codec_id; - ngx_memcpy(v.profile, ctx->profile, sizeof(ctx->profile)); - ngx_memcpy(v.level, ctx->level, sizeof(ctx->level)); - - rc = ngx_rtmp_append_amf(s, &ctx->meta->chain, &ctx->meta->chain, out_elts, - sizeof(out_elts) / sizeof(out_elts[0])); - if (rc != NGX_OK || ctx->meta == NULL) { - return NGX_ERROR; - } - - return ngx_rtmp_codec_prepare_meta(s, 0); -} - - -static ngx_int_t -ngx_rtmp_codec_copy_meta(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - ngx_rtmp_codec_ctx_t *ctx; - ngx_rtmp_core_srv_conf_t *cscf; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - - cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module); - - if (ctx->meta) { - ngx_rtmp_shared_free_frame(ctx->meta); - } - - ctx->meta = ngx_rtmp_shared_alloc_frame(cscf->chunk_size, in, 0); - - if (ctx->meta == NULL) { - return NGX_ERROR; - } - - return ngx_rtmp_codec_prepare_meta(s, h->timestamp); -} - - -static ngx_int_t -ngx_rtmp_codec_prepare_meta(ngx_rtmp_session_t *s, uint32_t timestamp) -{ - ngx_rtmp_codec_ctx_t *ctx; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - - ctx->meta->hdr.csid = NGX_RTMP_CSID_AMF; - ctx->meta->hdr.msid = NGX_RTMP_MSID; - ctx->meta->hdr.type = NGX_RTMP_MSG_AMF_META; - ctx->meta->hdr.timestamp = timestamp; - - ctx->meta_version = ngx_rtmp_codec_get_next_version(); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_codec_meta_data(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - ngx_rtmp_codec_app_conf_t *cacf; - ngx_rtmp_codec_ctx_t *ctx; - ngx_uint_t skip; - - static struct { - double width; - double height; - double duration; - double frame_rate; - double video_data_rate; - double video_codec_id_n; - u_char video_codec_id_s[32]; - double audio_data_rate; - double audio_codec_id_n; - u_char audio_codec_id_s[32]; - u_char profile[32]; - u_char level[32]; - } v; - - static ngx_rtmp_amf_elt_t in_video_codec_id[] = { - - { NGX_RTMP_AMF_NUMBER, - ngx_null_string, - &v.video_codec_id_n, 0 }, - - { NGX_RTMP_AMF_STRING, - ngx_null_string, - &v.video_codec_id_s, sizeof(v.video_codec_id_s) }, - }; - - static ngx_rtmp_amf_elt_t in_audio_codec_id[] = { - - { NGX_RTMP_AMF_NUMBER, - ngx_null_string, - &v.audio_codec_id_n, 0 }, - - { NGX_RTMP_AMF_STRING, - ngx_null_string, - &v.audio_codec_id_s, sizeof(v.audio_codec_id_s) }, - }; - - static ngx_rtmp_amf_elt_t in_inf[] = { - - { NGX_RTMP_AMF_NUMBER, - ngx_string("width"), - &v.width, 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_string("height"), - &v.height, 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_string("duration"), - &v.duration, 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_string("framerate"), - &v.frame_rate, 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_string("fps"), - &v.frame_rate, 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_string("videodatarate"), - &v.video_data_rate, 0 }, - - { NGX_RTMP_AMF_VARIANT, - ngx_string("videocodecid"), - in_video_codec_id, sizeof(in_video_codec_id) }, - - { NGX_RTMP_AMF_NUMBER, - ngx_string("audiodatarate"), - &v.audio_data_rate, 0 }, - - { NGX_RTMP_AMF_VARIANT, - ngx_string("audiocodecid"), - in_audio_codec_id, sizeof(in_audio_codec_id) }, - - { NGX_RTMP_AMF_STRING, - ngx_string("profile"), - &v.profile, sizeof(v.profile) }, - - { NGX_RTMP_AMF_STRING, - ngx_string("level"), - &v.level, sizeof(v.level) }, - }; - - static ngx_rtmp_amf_elt_t in_elts[] = { - - { NGX_RTMP_AMF_STRING, - ngx_null_string, - NULL, 0 }, - - { NGX_RTMP_AMF_OBJECT, - ngx_null_string, - in_inf, sizeof(in_inf) }, - }; - - cacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_codec_module); - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - if (ctx == NULL) { - ctx = ngx_pcalloc(s->pool, sizeof(ngx_rtmp_codec_ctx_t)); - ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_codec_module); - } - - ngx_memzero(&v, sizeof(v)); - - /* use -1 as a sign of unchanged data; - * 0 is a valid value for uncompressed audio */ - v.audio_codec_id_n = -1; - - /* FFmpeg sends a string in front of actal metadata; ignore it */ - skip = !(in->buf->last > in->buf->pos - && *in->buf->pos == NGX_RTMP_AMF_STRING); - if (ngx_rtmp_receive_amf(s, in, in_elts + skip, - sizeof(in_elts) / sizeof(in_elts[0]) - skip)) - { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "codec: error parsing data frame"); - return NGX_OK; - } - - ctx->width = (ngx_uint_t) v.width; - ctx->height = (ngx_uint_t) v.height; - ctx->duration = (ngx_uint_t) v.duration; - ctx->frame_rate = v.frame_rate; - ctx->video_data_rate = (ngx_uint_t) v.video_data_rate; - ctx->video_codec_id = (ngx_uint_t) v.video_codec_id_n; - ctx->audio_data_rate = (ngx_uint_t) v.audio_data_rate; - ctx->audio_codec_id = (v.audio_codec_id_n == -1 - ? 0 : v.audio_codec_id_n == 0 - ? NGX_RTMP_AUDIO_UNCOMPRESSED : (ngx_uint_t) v.audio_codec_id_n); - ngx_memcpy(ctx->profile, v.profile, sizeof(v.profile)); - ngx_memcpy(ctx->level, v.level, sizeof(v.level)); - - ngx_log_debug8(NGX_LOG_DEBUG_RTMP, s->log, 0, - "codec: data frame: " - "width=%ui height=%ui duration=%ui frame_rate=%f " - "video=%s (%ui) audio=%s (%ui)", - ctx->width, ctx->height, ctx->duration, ctx->frame_rate, - ngx_rtmp_get_video_codec_name(ctx->video_codec_id), - ctx->video_codec_id, - ngx_rtmp_get_audio_codec_name(ctx->audio_codec_id), - ctx->audio_codec_id); - - switch (cacf->meta) { - case NGX_RTMP_CODEC_META_ON: - return ngx_rtmp_codec_reconstruct_meta(s); - case NGX_RTMP_CODEC_META_COPY: - return ngx_rtmp_codec_copy_meta(s, h, in); - } - - /* NGX_RTMP_CODEC_META_OFF */ - - return NGX_OK; -} - - -static void * -ngx_rtmp_codec_create_app_conf(ngx_conf_t *cf) -{ - ngx_rtmp_codec_app_conf_t *cacf; - - cacf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_codec_app_conf_t)); - if (cacf == NULL) { - return NULL; - } - - cacf->meta = NGX_CONF_UNSET_UINT; - - return cacf; -} - - -static char * -ngx_rtmp_codec_merge_app_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_rtmp_codec_app_conf_t *prev = parent; - ngx_rtmp_codec_app_conf_t *conf = child; - - ngx_conf_merge_uint_value(conf->meta, prev->meta, NGX_RTMP_CODEC_META_ON); - - return NGX_CONF_OK; -} - - -static ngx_int_t -ngx_rtmp_codec_postconfiguration(ngx_conf_t *cf) -{ - ngx_rtmp_core_main_conf_t *cmcf; - ngx_rtmp_handler_pt *h; - ngx_rtmp_amf_handler_t *ch; - - cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module); - - h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_AUDIO]); - *h = ngx_rtmp_codec_av; - - h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_VIDEO]); - *h = ngx_rtmp_codec_av; - - h = ngx_array_push(&cmcf->events[NGX_RTMP_DISCONNECT]); - *h = ngx_rtmp_codec_disconnect; - - /* register metadata handler */ - ch = ngx_array_push(&cmcf->amf); - if (ch == NULL) { - return NGX_ERROR; - } - ngx_str_set(&ch->name, "@setDataFrame"); - ch->handler = ngx_rtmp_codec_meta_data; - - ch = ngx_array_push(&cmcf->amf); - if (ch == NULL) { - return NGX_ERROR; - } - ngx_str_set(&ch->name, "onMetaData"); - ch->handler = ngx_rtmp_codec_meta_data; - - - return NGX_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_codec_module.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_codec_module.h deleted file mode 100644 index 961d9cd91b..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_codec_module.h +++ /dev/null @@ -1,85 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#ifndef _NGX_RTMP_CODEC_H_INCLUDED_ -#define _NGX_RTMP_CODEC_H_INCLUDED_ - - -#include -#include -#include "ngx_rtmp.h" - - -/* hevc nal type */ -enum { - NAL_TRAIL_N = 0, - NAL_TRAIL_R = 1, - NAL_TSA_N = 2, - NAL_TSA_R = 3, - NAL_STSA_N = 4, - NAL_STSA_R = 5, - NAL_RADL_N = 6, - NAL_RADL_R = 7, - NAL_RASL_N = 8, - NAL_RASL_R = 9, - NAL_BLA_W_LP = 16, - NAL_BLA_W_RADL = 17, - NAL_BLA_N_LP = 18, - NAL_IDR_W_RADL = 19, - NAL_IDR_N_LP = 20, - NAL_CRA_NUT = 21, - NAL_VPS = 32, - NAL_SPS = 33, - NAL_PPS = 34, - NAL_AUD = 35, - NAL_EOS_NUT = 36, - NAL_EOB_NUT = 37, - NAL_FD_NUT = 38, - NAL_SEI_PREFIX = 39, - NAL_SEI_SUFFIX = 40, -}; - - -u_char * ngx_rtmp_get_audio_codec_name(ngx_uint_t id); -u_char * ngx_rtmp_get_video_codec_name(ngx_uint_t id); - - -typedef struct { - ngx_uint_t width; - ngx_uint_t height; - ngx_uint_t duration; - double frame_rate; - ngx_uint_t video_data_rate; - ngx_uint_t video_codec_id; - ngx_uint_t audio_data_rate; - ngx_uint_t audio_codec_id; - ngx_uint_t aac_profile; - ngx_uint_t aac_chan_conf; - ngx_uint_t aac_sbr; - ngx_uint_t aac_ps; - ngx_uint_t avc_profile; /* avc or hevc */ - ngx_uint_t avc_compat; /* avc or hevc */ - ngx_uint_t avc_level; /* avc or hevc */ - ngx_uint_t avc_nal_bytes; /* avc or hevc */ - ngx_uint_t avc_ref_frames; /* avc or hevc */ - ngx_uint_t sample_rate; /* 5512, 11025, 22050, 44100 */ - ngx_uint_t sample_size; /* 1=8bit, 2=16bit */ - ngx_uint_t audio_channels; /* 1, 2 */ - u_char profile[32]; - u_char level[32]; - - ngx_rtmp_frame_t *avc_header; /* avc or hevc */ - ngx_rtmp_frame_t *aac_header; - - ngx_rtmp_frame_t *meta; - ngx_uint_t meta_version; -} ngx_rtmp_codec_ctx_t; - - -extern ngx_module_t ngx_rtmp_codec_module; - - -#endif /* _NGX_RTMP_LIVE_H_INCLUDED_ */ diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_control_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_control_module.c deleted file mode 100644 index 4966ec5742..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_control_module.c +++ /dev/null @@ -1,922 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include -#include -#include "ngx_rtmp.h" -#include "ngx_live.h" -#include "ngx_rtmp_live_module.h" -#include "ngx_live_record.h" -#include "ngx_rtmp_record_module.h" -#include "ngx_rtmp_dynamic.h" - - -static char *ngx_rtmp_control(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -static void *ngx_rtmp_control_create_loc_conf(ngx_conf_t *cf); -static char *ngx_rtmp_control_merge_loc_conf(ngx_conf_t *cf, - void *parent, void *child); - - -typedef const char * (*ngx_rtmp_control_handler_t)(ngx_http_request_t *r, - ngx_rtmp_session_t *); - - -#define NGX_RTMP_CONTROL_ALL 0xff -#define NGX_RTMP_CONTROL_RECORD 0x01 -#define NGX_RTMP_CONTROL_DROP 0x02 -#define NGX_RTMP_CONTROL_REDIRECT 0x04 -#define NGX_RTMP_CONTROL_PAUSE 0x08 -#define NGX_RTMP_CONTROL_RESUME 0x10 - - -enum { - NGX_RTMP_CONTROL_FILTER_CLIENT = 0, - NGX_RTMP_CONTROL_FILTER_PUBLISHER, - NGX_RTMP_CONTROL_FILTER_SUBSCRIBER -}; - - -typedef struct { - ngx_uint_t count; - ngx_uint_t filter; - ngx_str_t method; - ngx_str_t path; - ngx_array_t sessions; /* ngx_rtmp_session_t * */ -} ngx_rtmp_control_ctx_t; - - -typedef struct { - ngx_uint_t control; -} ngx_rtmp_control_loc_conf_t; - - -static ngx_conf_bitmask_t ngx_rtmp_control_masks[] = { - { ngx_string("all"), NGX_RTMP_CONTROL_ALL }, - { ngx_string("record"), NGX_RTMP_CONTROL_RECORD }, - { ngx_string("drop"), NGX_RTMP_CONTROL_DROP }, - { ngx_string("redirect"), NGX_RTMP_CONTROL_REDIRECT }, - { ngx_string("pause"), NGX_RTMP_CONTROL_PAUSE }, - { ngx_string("resume"), NGX_RTMP_CONTROL_RESUME }, - { ngx_null_string, 0 } -}; - - -static ngx_command_t ngx_rtmp_control_commands[] = { - - { ngx_string("rtmp_control"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, - ngx_rtmp_control, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_rtmp_control_loc_conf_t, control), - ngx_rtmp_control_masks }, - - ngx_null_command -}; - - -static ngx_http_module_t ngx_rtmp_control_module_ctx = { - NULL, /* preconfiguration */ - NULL, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - ngx_rtmp_control_create_loc_conf, /* create location configuration */ - ngx_rtmp_control_merge_loc_conf, /* merge location configuration */ -}; - - -ngx_module_t ngx_rtmp_control_module = { - NGX_MODULE_V1, - &ngx_rtmp_control_module_ctx, /* module context */ - ngx_rtmp_control_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static const char * -ngx_rtmp_control_record_handler(ngx_http_request_t *r, ngx_rtmp_session_t *s) -{ - ngx_rtmp_control_ctx_t *ctx; - ngx_uint_t rn; - ngx_str_t rec = ngx_null_string; - ngx_rtmp_core_app_conf_t *cacf; - ngx_rtmp_record_app_conf_t *racf; - - ctx = ngx_http_get_module_ctx(r, ngx_rtmp_control_module); - cacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_core_module); - racf = cacf->app_conf[ngx_rtmp_record_module.ctx_index]; - - if (ngx_http_arg(r, (u_char *) "rec", sizeof("rec") - 1, &rec) != NGX_OK) { - rec.len = 0; - } - - rn = ngx_rtmp_record_find(racf, &rec); - if (rn == NGX_CONF_UNSET_UINT) { - return "Recorder not found"; - } - - if (ctx->method.len == sizeof("start") - 1 && - ngx_strncmp(ctx->method.data, "start", ctx->method.len) == 0) - { - ngx_rtmp_record_open(s, rn, &ctx->path); - - return ngx_live_record_open(s); - - } else if (ctx->method.len == sizeof("stop") - 1 && - ngx_strncmp(ctx->method.data, "stop", ctx->method.len) == 0) - { - ngx_rtmp_record_close(s, rn, &ctx->path); - - return ngx_live_record_close(s); - - } else { - return "Undefined method"; - } -} - - -static const char * -ngx_rtmp_control_drop_handler(ngx_http_request_t *r, ngx_rtmp_session_t *s) -{ - ngx_rtmp_control_ctx_t *ctx; - - ctx = ngx_http_get_module_ctx(r, ngx_rtmp_control_module); - - s->finalize_reason = NGX_LIVE_CONTROL_DROP; - ngx_rtmp_finalize_session(s); - - ++ctx->count; - - return NGX_CONF_OK; -} - - -static const char * -ngx_rtmp_control_redirect_handler(ngx_http_request_t *r, ngx_rtmp_session_t *s) -{ - ngx_str_t name; - ngx_rtmp_play_t vplay; - ngx_rtmp_publish_t vpublish; - ngx_rtmp_live_ctx_t *lctx; - ngx_rtmp_control_ctx_t *ctx; - ngx_rtmp_close_stream_t vc; - - if (ngx_http_arg(r, (u_char *) "newname", sizeof("newname") - 1, &name) - != NGX_OK) - { - return "newname not specified"; - } - - if (name.len >= NGX_RTMP_MAX_NAME) { - name.len = NGX_RTMP_MAX_NAME - 1; - } - - ctx = ngx_http_get_module_ctx(r, ngx_rtmp_control_module); - ctx->count++; - - ngx_memzero(&vc, sizeof(ngx_rtmp_close_stream_t)); - - /* close_stream should be synchronous */ - ngx_rtmp_close_stream_filter(s, &vc); - - lctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_live_module); - - if (lctx && lctx->publishing) { - /* publish */ - - ngx_memzero(&vpublish, sizeof(ngx_rtmp_publish_t)); - - ngx_memcpy(vpublish.name, name.data, name.len); - - ngx_rtmp_cmd_fill_args(vpublish.name, vpublish.args); - - if (ngx_rtmp_publish_filter(s, &vpublish) != NGX_OK) { - return "publish failed"; - } - - } else { - /* play */ - - ngx_memzero(&vplay, sizeof(ngx_rtmp_play_t)); - - ngx_memcpy(vplay.name, name.data, name.len); - - ngx_rtmp_cmd_fill_args(vplay.name, vplay.args); - - if (ngx_rtmp_play_filter(s, &vplay) != NGX_OK) { - return "play failed"; - } - } - - return NGX_CONF_OK; -} - -static const char * -ngx_rtmp_control_pause_handler(ngx_http_request_t *r, ngx_rtmp_session_t *s) -{ - ngx_rtmp_control_ctx_t *ctx; - - ctx = ngx_http_get_module_ctx(r, ngx_rtmp_control_module); - - s->pause = 1; - - ++ctx->count; - - return NGX_CONF_OK; -} - -static const char * -ngx_rtmp_control_resume_handler(ngx_http_request_t *r, ngx_rtmp_session_t *s) -{ - ngx_rtmp_control_ctx_t *ctx; - - ctx = ngx_http_get_module_ctx(r, ngx_rtmp_control_module); - - if (s->pause == 1) { - s->pause = 2; - } - - ++ctx->count; - - return NGX_CONF_OK; -} - -static const char * -ngx_rtmp_control_walk_session(ngx_http_request_t *r, ngx_rtmp_core_ctx_t *cctx) -{ - ngx_str_t addr, *paddr, clientid; - ngx_rtmp_session_t *s, **ss; - ngx_rtmp_control_ctx_t *ctx; - - s = cctx->session; - - if (s == NULL) { - return NGX_CONF_OK; - } - - if (ngx_http_arg(r, (u_char *) "addr", sizeof("addr") - 1, &addr) - == NGX_OK) - { - paddr = s->addr_text; - if (paddr->len != addr.len || - ngx_strncmp(paddr->data, addr.data, addr.len)) - { - return NGX_CONF_OK; - } - } - - if (ngx_http_arg(r, (u_char *) "clientid", sizeof("clientid") - 1, - &clientid) - == NGX_OK) - { - if (s->number != - (ngx_uint_t) ngx_atoi(clientid.data, clientid.len)) - { - return NGX_CONF_OK; - } - } - - ctx = ngx_http_get_module_ctx(r, ngx_rtmp_control_module); - - switch (ctx->filter) { - case NGX_RTMP_CONTROL_FILTER_PUBLISHER: - if (!cctx->publishing) { - return NGX_CONF_OK; - } - break; - - case NGX_RTMP_CONTROL_FILTER_SUBSCRIBER: - if (cctx->publishing) { - return NGX_CONF_OK; - } - break; - - case NGX_RTMP_CONTROL_FILTER_CLIENT: - break; - } - - ss = ngx_array_push(&ctx->sessions); - if (ss == NULL) { - return "allocation error"; - } - - *ss = s; - - return NGX_CONF_OK; -} - - -static const char * -ngx_rtmp_control_walk_stream(ngx_http_request_t *r, ngx_live_stream_t *st) -{ - const char *s; - ngx_rtmp_core_ctx_t *ctx; - - for (ctx = st->play_ctx; ctx; ctx = ctx->next) { - s = ngx_rtmp_control_walk_session(r, ctx); - if (s != NGX_CONF_OK) { - return s; - } - } - - for (ctx = st->publish_ctx; ctx; ctx = ctx->next) { - s = ngx_rtmp_control_walk_session(r, ctx); - if (s != NGX_CONF_OK) { - return s; - } - } - - return NGX_CONF_OK; -} - - -static const char * -ngx_rtmp_control_walk_server(ngx_http_request_t *r, ngx_live_server_t *srv) -{ - ngx_live_conf_t *lcf; - ngx_live_stream_t *st; - ngx_str_t serverid, app, name, stream; - size_t n; - const char *s; - u_char *p; - - lcf = (ngx_live_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_live_module); - - if (ngx_http_arg(r, (u_char *) "app", sizeof("app") - 1, &app) != NGX_OK) { - app.len = 0; - } - - if (app.len == 0) { - for (n = 0; n < lcf->stream_buckets; ++n) { - for (st = srv->streams[n]; st; st = st->next) { - s = ngx_rtmp_control_walk_stream(r, st); - if (s != NGX_CONF_OK) { - return s; - } - } - } - - return NGX_CONF_OK; - } - - if (ngx_http_arg(r, (u_char *) "name", sizeof("name") - 1, &name) - != NGX_OK) - { - name.len = 0; - } - - serverid.data = srv->serverid; - serverid.len = ngx_strlen(srv->serverid); - - /* serverid/app/name */ - stream.len = serverid.len + 1 + app.len + 1 + name.len; - stream.data = ngx_pcalloc(r->pool, stream.len); - p = stream.data; - p = ngx_copy(p, serverid.data, serverid.len); - *p++ = '/'; - p = ngx_copy(p, app.data, app.len); - *p++ = '/'; - p = ngx_copy(p, name.data, name.len); - - if (name.len == 0) { - for (n = 0; n < lcf->stream_buckets; ++n) { - for (st = srv->streams[n]; st; st = st->next) { - if (ngx_memcmp(stream.data, st->name, stream.len) == 0) { - s = ngx_rtmp_control_walk_stream(r, st); - if (s != NGX_CONF_OK) { - return s; - } - } - } - } - } else { - st = ngx_live_fetch_stream(&serverid, &stream); - if (st) { - s = ngx_rtmp_control_walk_stream(r, st); - if (s != NGX_CONF_OK) { - return s; - } - } - } - - return NGX_CONF_OK; -} - - -static const char * -ngx_rtmp_control_walk(ngx_http_request_t *r, ngx_rtmp_control_handler_t h) -{ - ngx_live_server_t *server; - ngx_str_t srv; - ngx_str_t serverid = ngx_null_string; - ngx_uint_t n; - const char *msg; - ngx_rtmp_session_t **s; - ngx_rtmp_control_ctx_t *ctx; - - if (ngx_http_arg(r, (u_char *) "srv", sizeof("srv") - 1, &srv) != NGX_OK) { - return "Server not set"; - } - - ctx = ngx_http_get_module_ctx(r, ngx_rtmp_control_module); - - serverid = srv; - - if (!serverid.len) { - ngx_rmtp_get_serverid_by_domain(&serverid, &srv); - } - - server = ngx_live_fetch_server(&serverid); - if (server == NULL) { - return NGX_CONF_OK; - } - - msg = ngx_rtmp_control_walk_server(r, server); - if (msg != NGX_CONF_OK) { - return msg; - } - - s = ctx->sessions.elts; - for (n = 0; n < ctx->sessions.nelts; n++) { - msg = h(r, s[n]); - if (msg != NGX_CONF_OK) { - return msg; - } - } - - return NGX_CONF_OK; -} - - -static ngx_int_t -ngx_rtmp_control_record(ngx_http_request_t *r, ngx_str_t *method) -{ - ngx_buf_t *b; - const char *msg; - ngx_chain_t cl; - ngx_rtmp_control_ctx_t *ctx; - size_t len; - - ctx = ngx_http_get_module_ctx(r, ngx_rtmp_control_module); - ctx->filter = NGX_RTMP_CONTROL_FILTER_PUBLISHER; - - msg = ngx_rtmp_control_walk(r, ngx_rtmp_control_record_handler); - if (msg != NGX_CONF_OK) { - goto error; - } - - /* output record path */ - - len = sizeof("ok\n") - 1; - - r->headers_out.status = NGX_HTTP_OK; - r->headers_out.content_length_n = len; - - b = ngx_create_temp_buf(r->pool, len); - if (b == NULL) { - goto error; - } - - ngx_memzero(&cl, sizeof(cl)); - cl.buf = b; - - b->last = ngx_cpymem(b->pos, "ok\n", len); - b->last_buf = 1; - - ngx_http_send_header(r); - - return ngx_http_output_filter(r, &cl); - -error: - return NGX_HTTP_INTERNAL_SERVER_ERROR; -} - - -static ngx_int_t -ngx_rtmp_control_drop(ngx_http_request_t *r, ngx_str_t *method) -{ - size_t len; - u_char *p; - ngx_buf_t *b; - ngx_chain_t cl; - const char *msg; - ngx_rtmp_control_ctx_t *ctx; - - ctx = ngx_http_get_module_ctx(r, ngx_rtmp_control_module); - - if (ctx->method.len == sizeof("publisher") - 1 && - ngx_memcmp(ctx->method.data, "publisher", ctx->method.len) == 0) - { - ctx->filter = NGX_RTMP_CONTROL_FILTER_PUBLISHER; - - } else if (ctx->method.len == sizeof("subscriber") - 1 && - ngx_memcmp(ctx->method.data, "subscriber", ctx->method.len) - == 0) - { - ctx->filter = NGX_RTMP_CONTROL_FILTER_SUBSCRIBER; - - } else if (method->len == sizeof("client") - 1 && - ngx_memcmp(ctx->method.data, "client", ctx->method.len) == 0) - { - ctx->filter = NGX_RTMP_CONTROL_FILTER_CLIENT; - - } else { - msg = "Undefined filter"; - goto error; - } - - msg = ngx_rtmp_control_walk(r, ngx_rtmp_control_drop_handler); - if (msg != NGX_CONF_OK) { - goto error; - } - - /* output count */ - - len = NGX_INT_T_LEN; - - p = ngx_palloc(r->connection->pool, len); - if (p == NULL) { - return NGX_ERROR; - } - - len = (size_t) (ngx_snprintf(p, len, "%ui", ctx->count) - p); - - r->headers_out.status = NGX_HTTP_OK; - r->headers_out.content_length_n = len; - - b = ngx_calloc_buf(r->pool); - if (b == NULL) { - goto error; - } - - b->start = b->pos = p; - b->end = b->last = p + len; - b->temporary = 1; - b->last_buf = 1; - - ngx_memzero(&cl, sizeof(cl)); - cl.buf = b; - - ngx_http_send_header(r); - - return ngx_http_output_filter(r, &cl); - -error: - return NGX_HTTP_INTERNAL_SERVER_ERROR; -} - - -static ngx_int_t -ngx_rtmp_control_redirect(ngx_http_request_t *r, ngx_str_t *method) -{ - size_t len; - u_char *p; - ngx_buf_t *b; - ngx_chain_t cl; - const char *msg; - ngx_rtmp_control_ctx_t *ctx; - - ctx = ngx_http_get_module_ctx(r, ngx_rtmp_control_module); - - if (ctx->method.len == sizeof("publisher") - 1 && - ngx_memcmp(ctx->method.data, "publisher", ctx->method.len) == 0) - { - ctx->filter = NGX_RTMP_CONTROL_FILTER_PUBLISHER; - - } else if (ctx->method.len == sizeof("subscriber") - 1 && - ngx_memcmp(ctx->method.data, "subscriber", ctx->method.len) - == 0) - { - ctx->filter = NGX_RTMP_CONTROL_FILTER_SUBSCRIBER; - - } else if (ctx->method.len == sizeof("client") - 1 && - ngx_memcmp(ctx->method.data, "client", ctx->method.len) == 0) - { - ctx->filter = NGX_RTMP_CONTROL_FILTER_CLIENT; - - } else { - msg = "Undefined filter"; - goto error; - } - - msg = ngx_rtmp_control_walk(r, ngx_rtmp_control_redirect_handler); - if (msg != NGX_CONF_OK) { - goto error; - } - - /* output count */ - - len = NGX_INT_T_LEN; - - p = ngx_pcalloc(r->connection->pool, len); - if (p == NULL) { - msg = "ngx_palloc failed"; - goto error; - } - - len = (size_t) (ngx_snprintf(p, len, "%ui", ctx->count) - p); - - r->headers_out.status = NGX_HTTP_OK; - r->headers_out.content_length_n = len; - - b = ngx_calloc_buf(r->pool); - if (b == NULL) { - msg = "calloc buf failed"; - goto error; - } - - b->start = b->pos = p; - b->end = b->last = p + len; - b->temporary = 1; - b->last_buf = 1; - - ngx_memzero(&cl, sizeof(cl)); - cl.buf = b; - - ngx_http_send_header(r); - - return ngx_http_output_filter(r, &cl); - -error: - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "rtmp-control: redirect| %s", msg); - return NGX_HTTP_INTERNAL_SERVER_ERROR; -} - - -static ngx_int_t -ngx_rtmp_control_pause(ngx_http_request_t *r, ngx_str_t *method) -{ - size_t len; - u_char *p; - ngx_buf_t *b; - ngx_chain_t cl; - const char *msg; - ngx_rtmp_control_ctx_t *ctx; - - ctx = ngx_http_get_module_ctx(r, ngx_rtmp_control_module); - - if (ctx->method.len == sizeof("publisher") - 1 && - ngx_memcmp(ctx->method.data, "publisher", ctx->method.len) == 0) - { - ctx->filter = NGX_RTMP_CONTROL_FILTER_PUBLISHER; - - } else if (ctx->method.len == sizeof("subscriber") - 1 && - ngx_memcmp(ctx->method.data, "subscriber", ctx->method.len) - == 0) - { - ctx->filter = NGX_RTMP_CONTROL_FILTER_SUBSCRIBER; - - } else if (method->len == sizeof("client") - 1 && - ngx_memcmp(ctx->method.data, "client", ctx->method.len) == 0) - { - ctx->filter = NGX_RTMP_CONTROL_FILTER_CLIENT; - - } else { - msg = "Undefined filter"; - goto error; - } - - msg = ngx_rtmp_control_walk(r, ngx_rtmp_control_pause_handler); - if (msg != NGX_CONF_OK) { - goto error; - } - - /* output count */ - - len = NGX_INT_T_LEN; - - p = ngx_palloc(r->connection->pool, len); - if (p == NULL) { - return NGX_ERROR; - } - - len = (size_t) (ngx_snprintf(p, len, "%ui", ctx->count) - p); - - r->headers_out.status = NGX_HTTP_OK; - r->headers_out.content_length_n = len; - - b = ngx_calloc_buf(r->pool); - if (b == NULL) { - goto error; - } - - b->start = b->pos = p; - b->end = b->last = p + len; - b->temporary = 1; - b->last_buf = 1; - - ngx_memzero(&cl, sizeof(cl)); - cl.buf = b; - - ngx_http_send_header(r); - - return ngx_http_output_filter(r, &cl); - -error: - return NGX_HTTP_INTERNAL_SERVER_ERROR; -} - - -static ngx_int_t -ngx_rtmp_control_resume(ngx_http_request_t *r, ngx_str_t *method) -{ - size_t len; - u_char *p; - ngx_buf_t *b; - ngx_chain_t cl; - const char *msg; - ngx_rtmp_control_ctx_t *ctx; - - ctx = ngx_http_get_module_ctx(r, ngx_rtmp_control_module); - - if (ctx->method.len == sizeof("publisher") - 1 && - ngx_memcmp(ctx->method.data, "publisher", ctx->method.len) == 0) - { - ctx->filter = NGX_RTMP_CONTROL_FILTER_PUBLISHER; - - } else if (ctx->method.len == sizeof("subscriber") - 1 && - ngx_memcmp(ctx->method.data, "subscriber", ctx->method.len) - == 0) - { - ctx->filter = NGX_RTMP_CONTROL_FILTER_SUBSCRIBER; - - } else if (method->len == sizeof("client") - 1 && - ngx_memcmp(ctx->method.data, "client", ctx->method.len) == 0) - { - ctx->filter = NGX_RTMP_CONTROL_FILTER_CLIENT; - - } else { - msg = "Undefined filter"; - goto error; - } - - msg = ngx_rtmp_control_walk(r, ngx_rtmp_control_resume_handler); - if (msg != NGX_CONF_OK) { - goto error; - } - - /* output count */ - - len = NGX_INT_T_LEN; - - p = ngx_palloc(r->connection->pool, len); - if (p == NULL) { - return NGX_ERROR; - } - - len = (size_t) (ngx_snprintf(p, len, "%ui", ctx->count) - p); - - r->headers_out.status = NGX_HTTP_OK; - r->headers_out.content_length_n = len; - - b = ngx_calloc_buf(r->pool); - if (b == NULL) { - goto error; - } - - b->start = b->pos = p; - b->end = b->last = p + len; - b->temporary = 1; - b->last_buf = 1; - - ngx_memzero(&cl, sizeof(cl)); - cl.buf = b; - - ngx_http_send_header(r); - - return ngx_http_output_filter(r, &cl); - -error: - return NGX_HTTP_INTERNAL_SERVER_ERROR; -} - - -static ngx_int_t -ngx_rtmp_control_handler(ngx_http_request_t *r) -{ - u_char *p; - ngx_str_t section, method; - ngx_uint_t n; - ngx_rtmp_control_ctx_t *ctx; - ngx_rtmp_control_loc_conf_t *llcf; - - llcf = ngx_http_get_module_loc_conf(r, ngx_rtmp_control_module); - if (llcf->control == 0) { - return NGX_DECLINED; - } - - /* uri format: .../section/method?args */ - - ngx_str_null(§ion); - ngx_str_null(&method); - - for (n = r->uri.len; n; --n) { - p = &r->uri.data[n - 1]; - - if (*p != '/') { - continue; - } - - if (method.data) { - section.data = p + 1; - section.len = method.data - section.data - 1; - break; - } - - method.data = p + 1; - method.len = r->uri.data + r->uri.len - method.data; - } - - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "rtmp_control: section='%V' method='%V'", - §ion, &method); - - ctx = ngx_pcalloc(r->pool, sizeof(ngx_rtmp_control_ctx_t)); - if (ctx == NULL) { - return NGX_ERROR; - } - - ngx_http_set_ctx(r, ctx, ngx_rtmp_control_module); - - if (ngx_array_init(&ctx->sessions, r->pool, 1, sizeof(void *)) != NGX_OK) { - return NGX_ERROR; - } - - ctx->method = method; - -#define NGX_RTMP_CONTROL_SECTION(flag, secname) \ - if (llcf->control & NGX_RTMP_CONTROL_##flag && \ - section.len == sizeof(#secname) - 1 && \ - ngx_strncmp(section.data, #secname, sizeof(#secname) - 1) == 0) \ - { \ - return ngx_rtmp_control_##secname(r, &method); \ - } - - NGX_RTMP_CONTROL_SECTION(RECORD, record); - NGX_RTMP_CONTROL_SECTION(DROP, drop); - NGX_RTMP_CONTROL_SECTION(REDIRECT, redirect); - NGX_RTMP_CONTROL_SECTION(PAUSE, pause); - NGX_RTMP_CONTROL_SECTION(RESUME, resume); - -#undef NGX_RTMP_CONTROL_SECTION - - return NGX_DECLINED; -} - - -static void * -ngx_rtmp_control_create_loc_conf(ngx_conf_t *cf) -{ - ngx_rtmp_control_loc_conf_t *conf; - - conf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_control_loc_conf_t)); - if (conf == NULL) { - return NULL; - } - - conf->control = 0; - - return conf; -} - - -static char * -ngx_rtmp_control_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_rtmp_control_loc_conf_t *prev = parent; - ngx_rtmp_control_loc_conf_t *conf = child; - - ngx_conf_merge_bitmask_value(conf->control, prev->control, 0); - - return NGX_CONF_OK; -} - - -static char * -ngx_rtmp_control(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_core_loc_conf_t *clcf; - - clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); - clcf->handler = ngx_rtmp_control_handler; - - return ngx_conf_set_bitmask_slot(cf, cmd, conf); -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_core_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_core_module.c deleted file mode 100644 index 3396adf0c4..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_core_module.c +++ /dev/null @@ -1,1203 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include -#include -#include -#include "ngx_rtmp.h" -#include "ngx_dynamic_conf.h" -#include "ngx_rtmp_dynamic.h" -#include "ngx_rtmp_variables.h" - - -static ngx_int_t ngx_rtmp_core_preconfiguration(ngx_conf_t *cf); - -static void *ngx_rtmp_core_create_main_conf(ngx_conf_t *cf); -static char *ngx_rtmp_core_init_main_conf(ngx_conf_t *cf, void *conf); -static void *ngx_rtmp_core_create_srv_conf(ngx_conf_t *cf); -static char *ngx_rtmp_core_merge_srv_conf(ngx_conf_t *cf, void *parent, - void *child); -static void *ngx_rtmp_core_create_app_conf(ngx_conf_t *cf); -static char *ngx_rtmp_core_merge_app_conf(ngx_conf_t *cf, void *parent, - void *child); -static char *ngx_rtmp_core_server(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); -static char *ngx_rtmp_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); -static char *ngx_rtmp_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); -static char *ngx_rtmp_core_application(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); - -static void *ngx_rtmp_core_create_srv_dconf(ngx_conf_t *cf); -static char *ngx_rtmp_core_init_srv_dconf(ngx_conf_t *cf, void *conf); - -static char *ngx_rtmp_merge_frame(ngx_conf_t *cf, void *post, void *data); - -static ngx_conf_post_handler_pt ngx_rtmp_merge_frame_p = - ngx_rtmp_merge_frame; - -ngx_rtmp_core_main_conf_t *ngx_rtmp_core_main_conf; - - -static ngx_conf_deprecated_t ngx_conf_deprecated_so_keepalive = { - ngx_conf_deprecated, "so_keepalive", - "so_keepalive\" parameter of the \"listen" -}; - - -static ngx_command_t ngx_rtmp_core_commands[] = { - - { ngx_string("server_names_hash_max_size"), - NGX_RTMP_MAIN_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - NGX_RTMP_MAIN_CONF_OFFSET, - offsetof(ngx_rtmp_core_main_conf_t, server_names_hash_max_size), - NULL }, - - { ngx_string("server_names_hash_bucket_size"), - NGX_RTMP_MAIN_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - NGX_RTMP_MAIN_CONF_OFFSET, - offsetof(ngx_rtmp_core_main_conf_t, server_names_hash_bucket_size), - NULL }, - - { ngx_string("fast_reload"), - NGX_RTMP_MAIN_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_MAIN_CONF_OFFSET, - offsetof(ngx_rtmp_core_main_conf_t, fast_reload), - NULL }, - - { ngx_string("server"), - NGX_RTMP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, - ngx_rtmp_core_server, - 0, - 0, - NULL }, - - { ngx_string("listen"), - NGX_RTMP_SRV_CONF|NGX_CONF_TAKE12, - ngx_rtmp_core_listen, - NGX_RTMP_SRV_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("server_name"), - NGX_RTMP_SRV_CONF|NGX_CONF_1MORE, - ngx_rtmp_core_server_name, - NGX_RTMP_SRV_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("application"), - NGX_RTMP_SRV_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE1, - ngx_rtmp_core_application, - NGX_RTMP_SRV_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("so_keepalive"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_CONF_FLAG, - ngx_conf_set_flag_slot, - NGX_RTMP_SRV_CONF_OFFSET, - offsetof(ngx_rtmp_core_srv_conf_t, so_keepalive), - &ngx_conf_deprecated_so_keepalive }, - - { ngx_string("timeout"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_SRV_CONF_OFFSET, - offsetof(ngx_rtmp_core_srv_conf_t, timeout), - NULL }, - - { ngx_string("ping"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_SRV_CONF_OFFSET, - offsetof(ngx_rtmp_core_srv_conf_t, ping), - NULL }, - - { ngx_string("ping_timeout"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_SRV_CONF_OFFSET, - offsetof(ngx_rtmp_core_srv_conf_t, ping_timeout), - NULL }, - - { ngx_string("max_streams"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - NGX_RTMP_SRV_CONF_OFFSET, - offsetof(ngx_rtmp_core_srv_conf_t, max_streams), - NULL }, - - { ngx_string("ack_window"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - NGX_RTMP_SRV_CONF_OFFSET, - offsetof(ngx_rtmp_core_srv_conf_t, ack_window), - NULL }, - - { ngx_string("chunk_size"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - NGX_RTMP_SRV_CONF_OFFSET, - offsetof(ngx_rtmp_core_srv_conf_t, chunk_size), - NULL }, - - { ngx_string("max_message"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_RTMP_SRV_CONF_OFFSET, - offsetof(ngx_rtmp_core_srv_conf_t, max_message), - NULL }, - - { ngx_string("out_queue"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_RTMP_SRV_CONF_OFFSET, - offsetof(ngx_rtmp_core_srv_conf_t, out_queue), - NULL }, - - { ngx_string("merge_frame"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_core_app_conf_t, merge_frame), - &ngx_rtmp_merge_frame_p }, - - { ngx_string("tcp_nodelay"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_FLAG, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_core_app_conf_t, tcp_nodelay), - NULL }, - - { ngx_string("out_cork"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_RTMP_SRV_CONF_OFFSET, - offsetof(ngx_rtmp_core_srv_conf_t, out_cork), - NULL }, - - { ngx_string("busy"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_SRV_CONF_OFFSET, - offsetof(ngx_rtmp_core_srv_conf_t, busy), - NULL }, - - /* time fixes are needed for flash clients */ - { ngx_string("play_time_fix"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_SRV_CONF_OFFSET, - offsetof(ngx_rtmp_core_srv_conf_t, play_time_fix), - NULL }, - - { ngx_string("publish_time_fix"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_SRV_CONF_OFFSET, - offsetof(ngx_rtmp_core_srv_conf_t, publish_time_fix), - NULL }, - - { ngx_string("buflen"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_SRV_CONF_OFFSET, - offsetof(ngx_rtmp_core_srv_conf_t, buflen), - NULL }, - - { ngx_string("serverid"), - NGX_RTMP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, - NGX_RTMP_SRV_CONF_OFFSET, - offsetof(ngx_rtmp_core_srv_conf_t, serverid), - NULL }, - - { ngx_string("hevc_codecid"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_core_app_conf_t, hevc_codec), - NULL }, - - ngx_null_command -}; - - -static ngx_rtmp_module_t ngx_rtmp_core_module_ctx = { - ngx_rtmp_core_preconfiguration, /* preconfiguration */ - NULL, /* postconfiguration */ - ngx_rtmp_core_create_main_conf, /* create main configuration */ - ngx_rtmp_core_init_main_conf, /* init main configuration */ - ngx_rtmp_core_create_srv_conf, /* create server configuration */ - ngx_rtmp_core_merge_srv_conf, /* merge server configuration */ - ngx_rtmp_core_create_app_conf, /* create app configuration */ - ngx_rtmp_core_merge_app_conf /* merge app configuration */ -}; - -/* nginx rtmp dynamic */ -static ngx_command_t ngx_rtmp_core_dcommands[] = { - - { ngx_string("serverid"), - NGX_RTMP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, - NGX_RTMP_SRV_CONF_OFFSET, - offsetof(ngx_rtmp_core_srv_dconf_t, serverid), - NULL }, - - ngx_null_command -}; - -static ngx_rtmp_dynamic_module_t ngx_rtmp_core_module_dctx = { - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - ngx_rtmp_core_create_srv_dconf, /* create server configuration */ - ngx_rtmp_core_init_srv_dconf, /* merge server configuration */ - - NULL, /* create app configuration */ - NULL /* merge app configuration */ -}; - - -ngx_module_t ngx_rtmp_core_module = { - NGX_MODULE_V1, - &ngx_rtmp_core_module_ctx, /* module context */ - ngx_rtmp_core_commands, /* module directives */ - NGX_RTMP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - (uintptr_t) &ngx_rtmp_core_module_dctx, /* module dynamic context */ - (uintptr_t) ngx_rtmp_core_dcommands, /* module dynamic directives */ - NGX_MODULE_V1_DYNAMIC_PADDING -}; - - -static void * -ngx_rtmp_core_create_main_conf(ngx_conf_t *cf) -{ - ngx_rtmp_core_main_conf_t *cmcf; - - cmcf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_core_main_conf_t)); - if (cmcf == NULL) { - return NULL; - } - - ngx_rtmp_core_main_conf = cmcf; - - if (ngx_array_init(&cmcf->servers, cf->pool, 4, - sizeof(ngx_rtmp_core_srv_conf_t *)) - != NGX_OK) - { - return NULL; - } - - cmcf->server_names_hash_max_size = NGX_CONF_UNSET_UINT; - cmcf->server_names_hash_bucket_size = NGX_CONF_UNSET_UINT; - cmcf->fast_reload = NGX_CONF_UNSET; - cmcf->variables_hash_max_size = 1024; - cmcf->variables_hash_bucket_size = 64; - - return cmcf; -} - - -static char * -ngx_rtmp_core_init_main_conf(ngx_conf_t *cf, void *conf) -{ - ngx_rtmp_core_main_conf_t *cmcf; - - cmcf = conf; - - ngx_conf_init_uint_value(cmcf->server_names_hash_max_size, 512); - ngx_conf_init_uint_value(cmcf->server_names_hash_bucket_size, - ngx_cacheline_size); - ngx_conf_init_value(cmcf->fast_reload, 0); - - return NGX_CONF_OK; -} - - -static void * -ngx_rtmp_core_create_srv_conf(ngx_conf_t *cf) -{ - ngx_rtmp_core_srv_conf_t *conf; - - conf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_core_srv_conf_t)); - if (conf == NULL) { - return NULL; - } - - if (ngx_array_init(&conf->applications, cf->pool, 4, - sizeof(ngx_rtmp_core_app_conf_t *)) - != NGX_OK) - { - return NULL; - } - - if (ngx_array_init(&conf->server_names, cf->temp_pool, 4, - sizeof(ngx_rtmp_server_name_t)) - != NGX_OK) - { - return NULL; - } - - conf->timeout = NGX_CONF_UNSET_MSEC; - conf->ping = NGX_CONF_UNSET_MSEC; - conf->ping_timeout = NGX_CONF_UNSET_MSEC; - conf->so_keepalive = NGX_CONF_UNSET; - conf->max_streams = NGX_CONF_UNSET; - conf->chunk_size = NGX_CONF_UNSET; - conf->ack_window = NGX_CONF_UNSET_UINT; - conf->max_message = NGX_CONF_UNSET_SIZE; - conf->out_queue = NGX_CONF_UNSET_SIZE; - conf->out_cork = NGX_CONF_UNSET_SIZE; - conf->play_time_fix = NGX_CONF_UNSET; - conf->publish_time_fix = NGX_CONF_UNSET; - conf->buflen = NGX_CONF_UNSET_MSEC; - conf->busy = NGX_CONF_UNSET; - - return conf; -} - - -static char * -ngx_rtmp_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_rtmp_core_srv_conf_t *prev = parent; - ngx_rtmp_core_srv_conf_t *conf = child; - - ngx_str_t name; - ngx_rtmp_server_name_t *sn; - - ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 60000); - ngx_conf_merge_msec_value(conf->ping, prev->ping, 60000); - ngx_conf_merge_msec_value(conf->ping_timeout, prev->ping_timeout, 30000); - - ngx_conf_merge_value(conf->so_keepalive, prev->so_keepalive, 0); - ngx_conf_merge_value(conf->max_streams, prev->max_streams, 32); - ngx_conf_merge_value(conf->chunk_size, prev->chunk_size, 4096); - ngx_conf_merge_uint_value(conf->ack_window, prev->ack_window, 5000000); - ngx_conf_merge_size_value(conf->max_message, prev->max_message, - 1 * 1024 * 1024); - ngx_conf_merge_size_value(conf->out_queue, prev->out_queue, 2048); - ngx_conf_merge_size_value(conf->out_cork, prev->out_cork, - conf->out_queue / 8); - ngx_conf_merge_value(conf->play_time_fix, prev->play_time_fix, 1); - ngx_conf_merge_value(conf->publish_time_fix, prev->publish_time_fix, 1); - ngx_conf_merge_msec_value(conf->buflen, prev->buflen, 1000); - ngx_conf_merge_value(conf->busy, prev->busy, 0); - ngx_conf_merge_str_value(conf->serverid, prev->serverid, "default"); - - if (prev->pool == NULL) { - prev->pool = ngx_create_pool(4096, &cf->cycle->new_log); - if (prev->pool == NULL) { - return NGX_CONF_ERROR; - } - } - - conf->pool = prev->pool; - - if (conf->server_names.nelts == 0) { - sn = ngx_array_push(&conf->server_names); -#if (NGX_PCRE) - sn->regex = NULL; -#endif - sn->server = conf; - ngx_str_set(&sn->name, ""); - } - - sn = conf->server_names.elts; - name = sn[0].name; - -#if (NGX_PCRE) - if (sn->regex) { - name.len++; - name.data--; - } else -#endif - if (name.data[0] == '.') { - name.len--; - name.data++; - } - - conf->server_name.len = name.len; - conf->server_name.data = ngx_pstrdup(cf->pool, &name); - if (conf->server_name.data == NULL) { - return NGX_CONF_ERROR; - } - - return NGX_CONF_OK; -} - - -static void * -ngx_rtmp_core_create_app_conf(ngx_conf_t *cf) -{ - ngx_rtmp_core_app_conf_t *conf; - - conf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_core_app_conf_t)); - if (conf == NULL) { - return NULL; - } - - if (ngx_array_init(&conf->applications, cf->pool, 1, - sizeof(ngx_rtmp_core_app_conf_t *)) - != NGX_OK) - { - return NULL; - } - - conf->hevc_codec = NGX_CONF_UNSET_UINT; - conf->merge_frame = NGX_CONF_UNSET_UINT; - conf->tcp_nodelay = NGX_CONF_UNSET; - - return conf; -} - - -static char * -ngx_rtmp_core_merge_app_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_rtmp_core_app_conf_t *prev = parent; - ngx_rtmp_core_app_conf_t *conf = child; - - ngx_conf_merge_uint_value(conf->hevc_codec, prev->hevc_codec, 12); - ngx_conf_merge_uint_value(conf->merge_frame, prev->merge_frame, 32); - ngx_conf_merge_value(conf->tcp_nodelay, prev->tcp_nodelay, 1); - - NGX_RTMP_HEVC_CODEC_ID = conf->hevc_codec; - - return NGX_CONF_OK; -} - -/* nginx rtmp dynamic */ -static void * -ngx_rtmp_core_create_srv_dconf(ngx_conf_t *cf) -{ - ngx_rtmp_core_srv_dconf_t *conf; - - conf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_core_srv_dconf_t)); - if (conf == NULL) { - return NULL; - } - - return conf; -} - -static char * -ngx_rtmp_core_init_srv_dconf(ngx_conf_t *cf, void *conf) -{ - return NGX_CONF_OK; -} - - -static char * -ngx_rtmp_merge_frame(ngx_conf_t *cf, void *post, void *data) -{ - ngx_uint_t *mfp; - - mfp = data; - - if (*mfp > NGX_RTMP_MAX_MERGE_FRAME) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "the merge_frame must be no larger than %ui", - NGX_RTMP_MAX_MERGE_FRAME); - return NGX_CONF_ERROR; - } - - return NGX_CONF_OK; -} - - -static char * -ngx_rtmp_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - char *rv; - void *mconf; - ngx_uint_t m; - ngx_conf_t pcf; - ngx_module_t **modules; - ngx_rtmp_module_t *module; - struct sockaddr_in *sin; - ngx_rtmp_conf_ctx_t *ctx, *rtmp_ctx; - ngx_rtmp_listen_opt_t lsopt; - ngx_rtmp_core_srv_conf_t *cscf, **cscfp; - ngx_rtmp_core_main_conf_t *cmcf; - - ctx = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_conf_ctx_t)); - if (ctx == NULL) { - return NGX_CONF_ERROR; - } - - rtmp_ctx = cf->ctx; - ctx->main_conf = rtmp_ctx->main_conf; - - /* the server{}'s srv_conf */ - - ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_rtmp_max_module); - if (ctx->srv_conf == NULL) { - return NGX_CONF_ERROR; - } - - ctx->app_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_rtmp_max_module); - if (ctx->app_conf == NULL) { - return NGX_CONF_ERROR; - } - -#if (nginx_version >= 1009011) - modules = cf->cycle->modules; -#else - modules = ngx_modules; -#endif - - for (m = 0; modules[m]; m++) { - if (modules[m]->type != NGX_RTMP_MODULE) { - continue; - } - - module = modules[m]->ctx; - - if (module->create_srv_conf) { - mconf = module->create_srv_conf(cf); - if (mconf == NULL) { - return NGX_CONF_ERROR; - } - - ctx->srv_conf[modules[m]->ctx_index] = mconf; - } - - if (module->create_app_conf) { - mconf = module->create_app_conf(cf); - if (mconf == NULL) { - return NGX_CONF_ERROR; - } - - ctx->app_conf[modules[m]->ctx_index] = mconf; - } - } - - /* the server configuration context */ - - cscf = ctx->srv_conf[ngx_rtmp_core_module.ctx_index]; - cscf->ctx = ctx; - - cmcf = ctx->main_conf[ngx_rtmp_core_module.ctx_index]; - - cscfp = ngx_array_push(&cmcf->servers); - if (cscfp == NULL) { - return NGX_CONF_ERROR; - } - - *cscfp = cscf; - - /* parse inside server{} */ - - pcf = *cf; - cf->ctx = ctx; - cf->cmd_type = NGX_RTMP_SRV_CONF; - - rv = ngx_conf_parse(cf, NULL); - - *cf = pcf; - - if (rv == NGX_CONF_OK && !cscf->listen) { - /* if listen not configured, set 1935 as default */ - ngx_memzero(&lsopt, sizeof(ngx_rtmp_listen_opt_t)); - - lsopt.sockaddr = ngx_pcalloc(cf->pool, NGX_SOCKADDR_STRLEN); - if (lsopt.sockaddr == NULL) { - return NGX_CONF_ERROR; - } - - sin = (struct sockaddr_in *) lsopt.sockaddr; - - sin->sin_family = AF_INET; - sin->sin_port = htons(1935); - sin->sin_addr.s_addr = INADDR_ANY; - - lsopt.socklen = sizeof(struct sockaddr_in); - lsopt.wildcard = 1; - - (void) ngx_sock_ntop(lsopt.sockaddr, lsopt.socklen, lsopt.addr, - NGX_SOCKADDR_STRLEN, 1); - - if (ngx_rtmp_add_listen(cf, cscf, &lsopt) != NGX_OK) { - return NGX_CONF_ERROR; - } - } - - return rv; -} - - -static char * -ngx_rtmp_core_application(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - char *rv; - ngx_int_t i; - ngx_str_t *value; - ngx_conf_t save; - ngx_module_t **modules; - ngx_rtmp_module_t *module; - ngx_rtmp_conf_ctx_t *ctx, *pctx; - ngx_rtmp_core_srv_conf_t *cscf; - ngx_rtmp_core_app_conf_t *cacf, **cacfp; - - ctx = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_conf_ctx_t)); - if (ctx == NULL) { - return NGX_CONF_ERROR; - } - - pctx = cf->ctx; - ctx->main_conf = pctx->main_conf; - ctx->srv_conf = pctx->srv_conf; - - ctx->app_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_rtmp_max_module); - if (ctx->app_conf == NULL) { - return NGX_CONF_ERROR; - } - -#if (nginx_version >= 1009011) - modules = cf->cycle->modules; -#else - modules = ngx_modules; -#endif - - for (i = 0; modules[i]; i++) { - if (modules[i]->type != NGX_RTMP_MODULE) { - continue; - } - - module = modules[i]->ctx; - - if (module->create_app_conf) { - ctx->app_conf[modules[i]->ctx_index] = module->create_app_conf(cf); - if (ctx->app_conf[modules[i]->ctx_index] == NULL) { - return NGX_CONF_ERROR; - } - } - } - - cacf = ctx->app_conf[ngx_rtmp_core_module.ctx_index]; - cacf->app_conf = ctx->app_conf; - - value = cf->args->elts; - - cacf->name = value[1]; - cscf = pctx->srv_conf[ngx_rtmp_core_module.ctx_index]; - - if (cacf->name.len == 1 && cacf->name.data[0] == '*') { /* default_app */ - cscf->default_app = cacf; - } - - cacfp = ngx_array_push(&cscf->applications); - if (cacfp == NULL) { - return NGX_CONF_ERROR; - } - - *cacfp = cacf; - - save = *cf; - cf->ctx = ctx; - cf->cmd_type = NGX_RTMP_APP_CONF; - - rv = ngx_conf_parse(cf, NULL); - - *cf= save; - - return rv; -} - - -static char * -ngx_rtmp_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_rtmp_core_srv_conf_t *cscf = conf; - - ngx_str_t *value; - ngx_url_t u; - ngx_uint_t i; - ngx_rtmp_listen_opt_t lsopt; - - cscf->listen = 1; - - value = cf->args->elts; - - ngx_memzero(&u, sizeof(ngx_url_t)); - - u.url = value[1]; - u.listen = 1; - u.default_port = 1935; - - if (ngx_parse_url(cf->pool, &u) != NGX_OK) { - if (u.err) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "%s in \"%V\" of the \"listen\" directive", - u.err, &u.url); - } - - return NGX_CONF_ERROR; - } - - ngx_memzero(&lsopt, sizeof(ngx_rtmp_listen_opt_t)); - - lsopt.sockaddr = ngx_pcalloc(cf->pool, NGX_SOCKADDR_STRLEN); - if (lsopt.sockaddr == NULL) { - return NGX_CONF_ERROR; - } - ngx_memcpy(lsopt.sockaddr, (u_char *) &u.sockaddr, u.socklen); - - lsopt.socklen = u.socklen; - lsopt.wildcard = u.wildcard; - - (void) ngx_sock_ntop(lsopt.sockaddr, lsopt.socklen, lsopt.addr, - NGX_SOCKADDR_STRLEN, 1); - - for (i = 2; i < cf->args->nelts; i++) { - - if (ngx_strcmp(value[i].data, "default_server") == 0 - || ngx_strcmp(value[i].data, "default") == 0) - { - lsopt.default_server = 1; - continue; - } - - if (ngx_strcmp(value[i].data, "bind") == 0) { - lsopt.bind = 1; - continue; - } - - if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) { -#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) - struct sockaddr *sa; - - sa = lsopt.sockaddr; - - if (sa->sa_family == AF_INET6) { - - if (ngx_strcmp(&value[i].data[10], "n") == 0) { - lsopt.ipv6only = 1; - - } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) { - lsopt.ipv6only = 0; - - } else { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid ipv6only flags \"%s\"", - &value[i].data[9]); - return NGX_CONF_ERROR; - } - - lsopt.bind = 1; - - } else { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "ipv6only is not supported " - "on addr \"%s\", ignored", lsopt.addr); - } - - continue; -#else - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "bind ipv6only is not supported " - "on this platform"); - return NGX_CONF_ERROR; -#endif - } - - if (ngx_strcmp(value[i].data, "reuseport") == 0) { -#if (NGX_HAVE_REUSEPORT) - lsopt.reuseport = 1; - lsopt.set = 1; - lsopt.bind = 1; -#else - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "reuseport is not supported " - "on this platform, ignored"); -#endif - continue; - } - - if (ngx_strncmp(value[i].data, "so_keepalive=", 13) == 0) { - - if (ngx_strcmp(&value[i].data[13], "on") == 0) { - lsopt.so_keepalive = 1; - - } else if (ngx_strcmp(&value[i].data[13], "off") == 0) { - lsopt.so_keepalive = 2; - - } else { - -#if (NGX_HAVE_KEEPALIVE_TUNABLE) - u_char *p, *end; - ngx_str_t s; - - end = value[i].data + value[i].len; - s.data = value[i].data + 13; - - p = ngx_strlchr(s.data, end, ':'); - if (p == NULL) { - p = end; - } - - if (p > s.data) { - s.len = p - s.data; - - lsopt.tcp_keepidle = ngx_parse_time(&s, 1); - if (lsopt.tcp_keepidle == (time_t) NGX_ERROR) { - goto invalid_so_keepalive; - } - } - - s.data = (p < end) ? (p + 1) : end; - - p = ngx_strlchr(s.data, end, ':'); - if (p == NULL) { - p = end; - } - - if (p > s.data) { - s.len = p - s.data; - - lsopt.tcp_keepintvl = ngx_parse_time(&s, 1); - if (lsopt.tcp_keepintvl == (time_t) NGX_ERROR) { - goto invalid_so_keepalive; - } - } - - s.data = (p < end) ? (p + 1) : end; - - if (s.data < end) { - s.len = end - s.data; - - lsopt.tcp_keepcnt = ngx_atoi(s.data, s.len); - if (lsopt.tcp_keepcnt == NGX_ERROR) { - goto invalid_so_keepalive; - } - } - - if (lsopt.tcp_keepidle == 0 && lsopt.tcp_keepintvl == 0 - && lsopt.tcp_keepcnt == 0) - { - goto invalid_so_keepalive; - } - - lsopt.so_keepalive = 1; - -#else - - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "the \"so_keepalive\" parameter accepts " - "only \"on\" or \"off\" on this platform"); - return NGX_CONF_ERROR; - -#endif - } - - lsopt.bind = 1; - - continue; - -#if (NGX_HAVE_KEEPALIVE_TUNABLE) - invalid_so_keepalive: - - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid so_keepalive value: \"%s\"", - &value[i].data[13]); - return NGX_CONF_ERROR; -#endif - } - - if (ngx_strcmp(value[i].data, "proxy_protocol") == 0) { - lsopt.proxy_protocol = 1; - continue; - } - - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "the invalid \"%V\" parameter", &value[i]); - return NGX_CONF_ERROR; - } - - if (ngx_rtmp_add_listen(cf, cscf, &lsopt) == NGX_OK) { - return NGX_CONF_OK; - } - - return NGX_CONF_ERROR; -} - -static char * -ngx_rtmp_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_rtmp_core_srv_conf_t *cscf = conf; - - u_char ch; - ngx_str_t *value; - ngx_uint_t i; - ngx_rtmp_server_name_t *sn; - - value = cf->args->elts; - - for (i = 1; i < cf->args->nelts; i++) { - - ch = value[i].data[0]; - - if ((ch == '*' && (value[i].len < 3 || value[i].data[1] != '.')) - || (ch == '.' && value[i].len < 2)) - { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "server name \"%V\" is invalid", &value[i]); - return NGX_CONF_ERROR; - } - - if (ngx_strchr(value[i].data, '/')) { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, - "server name \"%V\" has suspicious symbols", - &value[i]); - } - - sn = ngx_array_push(&cscf->server_names); - if (sn == NULL) { - return NGX_CONF_ERROR; - } - -#if (NGX_PCRE) - sn->regex = NULL; -#endif - sn->server = cscf; - - if (ngx_strcasecmp(value[i].data, (u_char *) "$hostname") == 0) { - sn->name = cf->cycle->hostname; - - } else { - sn->name = value[i]; - } - - if (value[i].data[0] != '~') { - ngx_strlow(sn->name.data, sn->name.data, sn->name.len); - continue; - } - -#if (NGX_PCRE) - { - u_char *p; - ngx_regex_compile_t rc; - u_char errstr[NGX_MAX_CONF_ERRSTR]; - - if (value[i].len == 1) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "empty regex in server name \"%V\"", &value[i]); - return NGX_CONF_ERROR; - } - - value[i].len--; - value[i].data++; - - ngx_memzero(&rc, sizeof(ngx_regex_compile_t)); - - rc.pattern = value[i]; - rc.err.len = NGX_MAX_CONF_ERRSTR; - rc.err.data = errstr; - - for (p = value[i].data; p < value[i].data + value[i].len; p++) { - if (*p >= 'A' && *p <= 'Z') { - rc.options = NGX_REGEX_CASELESS; - break; - } - } - - sn->regex = ngx_rtmp_regex_compile(cf, &rc); - if (sn->regex == NULL) { - return NGX_CONF_ERROR; - } - - sn->name = value[i]; - cscf->captures = (rc.captures > 0); - } -#else - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "using regex \"%V\" " - "requires PCRE library", &value[i]); - - return NGX_CONF_ERROR; -#endif - } - - return NGX_CONF_OK; -} - -static ngx_rtmp_addr_conf_t * -ngx_rtmp_get_addr_conf(ngx_listening_t *ls, struct sockaddr *sa, socklen_t len) -{ - ngx_uint_t i; - ngx_rtmp_addr_conf_t *addr_conf; - ngx_rtmp_port_t *port; - struct sockaddr_in *sin; - ngx_rtmp_in_addr_t *addr; -#if (NGX_HAVE_INET6) - struct sockaddr_in6 *sin6; - ngx_rtmp_in6_addr_t *addr6; -#endif - - port = ls->servers; - addr_conf = NULL; - - if (port->naddrs > 1) { - switch (sa->sa_family) { -#if (NGX_HAVE_INET6) - case AF_INET6: - sin6 = (struct sockaddr_in6 *) sa; - - addr6 = port->addrs; - - /* the last address is "*" */ - - for (i = 0; i < port->naddrs - 1; ++i) { - if (ngx_memcmp(&addr6[i].addr6, &sin6->sin6_addr, 16) == 0) { - break; - } - } - - addr_conf = &addr6[i].conf; - - break; -#endif - default: - sin = (struct sockaddr_in *) sa; - - addr = port->addrs; - - /* the last address is "*" */ - - for (i = 0; i < port->naddrs - 1; ++i) { - if (addr[i].addr == sin->sin_addr.s_addr) { - break; - } - } - - addr_conf = &addr[i].conf; - - break; - } - } else { - - switch (sa->sa_family) { -#if (NGX_HAVE_INET6) - case AF_INET6: - addr6 = port->addrs; - addr_conf = &addr6[0].conf; - break; -#endif - - default: - addr = port->addrs; - addr_conf = &addr[0].conf; - break; - } - } - - return addr_conf; -} - -ngx_rtmp_addr_conf_t * -ngx_rtmp_find_related_addr_conf(ngx_cycle_t *cycle, ngx_str_t *addr) -{ - ngx_url_t u; - ngx_listening_t *ls; - ngx_uint_t i; - - ngx_memzero(&u, sizeof(ngx_url_t)); - - u.url = *addr; - u.listen = 1; - u.default_port = 0; - - if (ngx_parse_url(cycle->pool, &u) != NGX_OK) { - if (u.err) { - ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, - "Relation port err: %V", addr); - } - - return NULL; - } - - ls = cycle->listening.elts; - - for (i = 0; i < cycle->listening.nelts; ++i, ++ls) { - - if (ls->handler == ngx_rtmp_init_connection - && ls->socklen == u.socklen - && ngx_memcmp(ls->sockaddr, (u_char *) &u.sockaddr, - u.socklen) == 0) - { - return ngx_rtmp_get_addr_conf(ls, &u.sockaddr.sockaddr, u.socklen); - } - } - - ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, - "Can not find relation port: %V", addr); - - return NULL; -} - - -ngx_int_t -ngx_rtmp_arg(ngx_rtmp_session_t *s, u_char *name, size_t len, ngx_str_t *value) -{ - u_char *p, *last; - - if (s->pargs.len == 0) { - return NGX_DECLINED; - } - - p = s->pargs.data; - last = p + s->pargs.len; - - for ( /* void */ ; p < last; p++) { - - /* we need '=' after name, so drop one char from last */ - - p = ngx_strlcasestrn(p, last - 1, name, len - 1); - - if (p == NULL) { - return NGX_DECLINED; - } - - if ((p == s->pargs.data || *(p - 1) == '&') && *(p + len) == '=') { - - value->data = p + len + 1; - - p = ngx_strlchr(p, last, '&'); - - if (p == NULL) { - p = s->pargs.data + s->pargs.len; - } - - value->len = p - value->data; - - return NGX_OK; - } - } - - return NGX_DECLINED; -} - - -static ngx_int_t -ngx_rtmp_core_preconfiguration(ngx_conf_t *cf) -{ - return ngx_rtmp_variables_add_core_vars(cf); -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_dynamic.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_dynamic.c deleted file mode 100644 index fd92cad97a..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_dynamic.c +++ /dev/null @@ -1,999 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include -#include -#include "ngx_rtmp.h" -#include "ngx_rtmp_dynamic.h" - - -static void *ngx_rtmp_dynamic_create_conf(ngx_conf_t *cf); -static void *ngx_rtmp_dynamic_core_create_main_conf(ngx_conf_t *cf); -static char *ngx_rtmp_dynamic_core_init_main_conf(ngx_conf_t *cf, void *conf); -static void *ngx_rtmp_dynamic_core_create_srv_conf(ngx_conf_t *cf); -static char *ngx_rtmp_dynamic_core_init_srv_conf(ngx_conf_t *cf, void *conf); -static void *ngx_rtmp_dynamic_core_create_app_conf(ngx_conf_t *cf); -static char *ngx_rtmp_dynamic_core_init_app_conf(ngx_conf_t *cf, void *conf); - -static char *ngx_rtmp_dynamic_block(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); -static char *ngx_rtmp_dynamic_core_server(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); -static char *ngx_rtmp_dynamic_core_server_name(ngx_conf_t *cf, - ngx_command_t *cmd, void *conf); -static char *ngx_rtmp_dynamic_core_application(ngx_conf_t *cf, - ngx_command_t *cmd, void *conf); - - -typedef struct { - ngx_str_t name; - ngx_map_node_t node; - - void **app_conf; -} ngx_rtmp_dynamic_core_app_conf_t; - -typedef struct { - /* array of the ngx_rtmp_server_name_t, "server_name" directive */ - ngx_array_t server_names; - - ngx_rtmp_dynamic_core_app_conf_t *default_app; - ngx_map_t app_conf; - - void **srv_conf; -} ngx_rtmp_dynamic_core_srv_conf_t; - -typedef struct { -#if (NGX_PCRE) - ngx_dynamic_regex_t *regex; -#endif - ngx_rtmp_dynamic_core_srv_conf_t *server; /* virtual name server conf */ - ngx_str_t name; -} ngx_rtmp_dynamic_server_name_t; - - -typedef struct { - /* ngx_rtmp_dynamic_srv_conf_t */ - ngx_array_t servers; - - ngx_uint_t server_names_hash_max_size; - ngx_uint_t server_names_hash_bucket_size; - - /* the default server configuration for this address:port */ - ngx_rtmp_dynamic_core_srv_conf_t *default_server; - - ngx_hash_combined_t names; - -#if (NGX_PCRE) - ngx_uint_t nregex; - ngx_rtmp_dynamic_server_name_t *regex; -#endif -} ngx_rtmp_dynamic_core_main_conf_t; - - -typedef struct { - void **main_conf; -} ngx_rtmp_dynamic_conf_t; - - -static ngx_core_module_t ngx_rtmp_dynamic_module_ctx = { - ngx_string("rtmp_dynamic"), - NULL, - NULL -}; - -static ngx_command_t ngx_rtmp_dynamic_dcommands[] = { - - { ngx_string("rtmp"), - NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, - ngx_rtmp_dynamic_block, - 0, - 0, - NULL }, - - ngx_null_command -}; - -static ngx_dynamic_core_module_t ngx_rtmp_dynamic_module_dctx = { - ngx_string("rtmp_dynamic"), - ngx_rtmp_dynamic_create_conf, - NULL -}; - -ngx_module_t ngx_rtmp_dynamic_module = { - NGX_MODULE_V1, - &ngx_rtmp_dynamic_module_ctx, /* module context */ - NULL, /* module directives */ - NGX_CORE_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - (uintptr_t) &ngx_rtmp_dynamic_module_dctx, /* module dynamic context */ - (uintptr_t) ngx_rtmp_dynamic_dcommands, /* module dynamic directives */ - NGX_MODULE_V1_DYNAMIC_PADDING -}; - - -static ngx_rtmp_module_t ngx_rtmp_dynamic_core_module_ctx = { - NULL, /* preconfiguration */ - NULL, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - NULL, /* create application configuration */ - NULL /* merge application configuration */ -}; - - -static ngx_command_t ngx_rtmp_dynamic_core_dcommands[] = { - - { ngx_string("server_names_hash_max_size"), - NGX_RTMP_MAIN_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - 0, - offsetof(ngx_rtmp_dynamic_core_main_conf_t, server_names_hash_max_size), - NULL }, - - { ngx_string("server_names_hash_bucket_size"), - NGX_RTMP_MAIN_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - 0, - offsetof(ngx_rtmp_dynamic_core_main_conf_t, - server_names_hash_bucket_size), - NULL }, - - { ngx_string("server"), - NGX_RTMP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, - ngx_rtmp_dynamic_core_server, - 0, - 0, - NULL }, - - { ngx_string("server_name"), - NGX_RTMP_SRV_CONF|NGX_CONF_1MORE, - ngx_rtmp_dynamic_core_server_name, - 0, - 0, - NULL }, - - { ngx_string("application"), - NGX_RTMP_SRV_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE12, - ngx_rtmp_dynamic_core_application, - 0, - 0, - NULL }, - - ngx_null_command -}; - - -static ngx_rtmp_dynamic_module_t ngx_rtmp_dynamic_core_module_dctx = { - ngx_rtmp_dynamic_core_create_main_conf, /* create main configuration */ - ngx_rtmp_dynamic_core_init_main_conf, /* init main configuration */ - - ngx_rtmp_dynamic_core_create_srv_conf, /* create srv configuration */ - ngx_rtmp_dynamic_core_init_srv_conf, /* init srv configuration */ - - ngx_rtmp_dynamic_core_create_app_conf, /* create app configuration */ - ngx_rtmp_dynamic_core_init_app_conf /* init app configuration */ -}; - - -ngx_module_t ngx_rtmp_dynamic_core_module = { - NGX_MODULE_V1, - &ngx_rtmp_dynamic_core_module_ctx, /* module context */ - NULL, /* module directives */ - NGX_RTMP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - (uintptr_t) &ngx_rtmp_dynamic_core_module_dctx, /* module dynamic context */ - (uintptr_t) ngx_rtmp_dynamic_core_dcommands, /* module dynamic directives */ - NGX_MODULE_V1_DYNAMIC_PADDING -}; - - -static void * -ngx_rtmp_dynamic_create_conf(ngx_conf_t *cf) -{ - ngx_rtmp_dynamic_conf_t *rdccf; - - rdccf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_dynamic_conf_t)); - if (rdccf == NULL) { - return NULL; - } - - return rdccf; -} - -static void * -ngx_rtmp_dynamic_core_create_main_conf(ngx_conf_t *cf) -{ - ngx_rtmp_dynamic_core_main_conf_t *rdcmcf; - - rdcmcf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_dynamic_core_main_conf_t)); - if (rdcmcf == NULL) { - return NULL; - } - - if (ngx_array_init(&rdcmcf->servers, cf->pool, 4, - sizeof(ngx_rtmp_dynamic_core_srv_conf_t *)) != NGX_OK) - { - return NULL; - } - - rdcmcf->server_names_hash_max_size = NGX_CONF_UNSET_UINT; - rdcmcf->server_names_hash_bucket_size = NGX_CONF_UNSET_UINT; - - return rdcmcf; -} - -static char * -ngx_rtmp_dynamic_core_init_main_conf(ngx_conf_t *cf, void *conf) -{ - ngx_rtmp_dynamic_core_main_conf_t *rdcmcf; - - rdcmcf = conf; - - ngx_conf_init_uint_value(rdcmcf->server_names_hash_max_size, 512); - ngx_conf_init_uint_value(rdcmcf->server_names_hash_bucket_size, - ngx_cacheline_size); - - return NGX_CONF_OK; -} - -static void * -ngx_rtmp_dynamic_core_create_srv_conf(ngx_conf_t *cf) -{ - ngx_rtmp_dynamic_core_srv_conf_t *rdcscf; - - rdcscf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_dynamic_core_srv_conf_t)); - if (rdcscf == NULL) { - return NULL; - } - - if (ngx_array_init(&rdcscf->server_names, cf->pool, 4, - sizeof(ngx_rtmp_dynamic_server_name_t)) != NGX_OK) - { - return NULL; - } - - return rdcscf; -} - -static char * -ngx_rtmp_dynamic_core_init_srv_conf(ngx_conf_t *cf, void *conf) -{ - return NGX_CONF_OK; -} - -static void * -ngx_rtmp_dynamic_core_create_app_conf(ngx_conf_t *cf) -{ - ngx_rtmp_dynamic_core_app_conf_t *rdcacf; - - rdcacf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_dynamic_core_app_conf_t)); - if (rdcacf == NULL) { - return NULL; - } - - return rdcacf; -} - -static char * -ngx_rtmp_dynamic_core_init_app_conf(ngx_conf_t *cf, void *conf) -{ - return NGX_CONF_OK; -} - -static ngx_int_t -ngx_rtmp_dynamic_core_find_application(ngx_rtmp_session_t *s, - ngx_rtmp_dynamic_core_srv_conf_t *rdcscf, - ngx_rtmp_dynamic_core_app_conf_t **rdcacf) -{ - ngx_map_node_t *node; - - node = ngx_map_find(&rdcscf->app_conf, (intptr_t) &s->app); - if (node == NULL) { - *rdcacf = rdcscf->default_app; - } else { - *rdcacf = (ngx_rtmp_dynamic_core_app_conf_t *) - ((char *) node - offsetof(ngx_rtmp_dynamic_core_app_conf_t, node)); - } - - return NGX_OK; -} - -static ngx_int_t -ngx_rtmp_dynamic_core_init_virtual_servers(ngx_conf_t *cf, - ngx_rtmp_dynamic_conf_t *hdcf) -{ - ngx_rtmp_dynamic_core_main_conf_t *rdcmcf; - ngx_rtmp_dynamic_core_srv_conf_t **rdcscfp; - ngx_hash_init_t hash; - ngx_hash_keys_arrays_t ha; - ngx_rtmp_dynamic_server_name_t *name; - ngx_uint_t s, n; - ngx_int_t rc; -#if (NGX_PCRE) - ngx_uint_t regex, i; - - regex = 0; -#endif - - rdcmcf = hdcf->main_conf[ngx_rtmp_dynamic_core_module.ctx_index]; - - ngx_memzero(&ha, sizeof(ngx_hash_keys_arrays_t)); - - ha.temp_pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, cf->log); - if (ha.temp_pool == NULL) { - return NGX_ERROR; - } - - ha.pool = cf->pool; - - if (ngx_hash_keys_array_init(&ha, NGX_HASH_LARGE) != NGX_OK) { - goto failed; - } - - rdcscfp = rdcmcf->servers.elts; - rdcmcf->default_server = rdcscfp[0]; - - for (s = 0; s < rdcmcf->servers.nelts; ++s) { - - name = rdcscfp[s]->server_names.elts; - - for (n = 0; n < rdcscfp[s]->server_names.nelts; ++n) { -#if (NGX_PCRE) - if (name[n].regex) { - ++regex; - continue; - } -#endif - - rc = ngx_hash_add_key(&ha, &name[n].name, name[n].server, - NGX_HASH_WILDCARD_KEY); - if (rc == NGX_ERROR) { - return NGX_ERROR; - } - - if (rc == NGX_DECLINED) { - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "invalid server name or wildcard \"%V\"", - &name[n].name); - return NGX_ERROR; - } - - if (rc == NGX_BUSY) { - ngx_log_error(NGX_LOG_WARN, cf->log, 0, - "conflicting server name \"%V\", ignored", - &name[n].name); - } - } - } - - hash.key = ngx_hash_key_lc; - hash.max_size = rdcmcf->server_names_hash_max_size; - hash.bucket_size = rdcmcf->server_names_hash_bucket_size; - hash.name = "rtmp_dynamic_server_names_hash"; - hash.pool = cf->pool; - - if (ha.keys.nelts) { - hash.hash = &rdcmcf->names.hash; - hash.temp_pool = NULL; - - if (ngx_hash_init(&hash, ha.keys.elts, ha.keys.nelts) != NGX_OK) { - goto failed; - } - } - - if (ha.dns_wc_head.nelts) { - - ngx_qsort(ha.dns_wc_head.elts, (size_t) ha.dns_wc_head.nelts, - sizeof(ngx_hash_key_t), ngx_dynamic_cmp_dns_wildcards); - - hash.hash = NULL; - hash.temp_pool = ha.temp_pool; - - if (ngx_hash_wildcard_init(&hash, ha.dns_wc_head.elts, - ha.dns_wc_head.nelts) != NGX_OK) - { - goto failed; - } - - rdcmcf->names.wc_head = (ngx_hash_wildcard_t *) hash.hash; - } - - if (ha.dns_wc_tail.nelts) { - - ngx_qsort(ha.dns_wc_tail.elts, (size_t) ha.dns_wc_tail.nelts, - sizeof(ngx_hash_key_t), ngx_dynamic_cmp_dns_wildcards); - - hash.hash = NULL; - hash.temp_pool = ha.temp_pool; - - if (ngx_hash_wildcard_init(&hash, ha.dns_wc_tail.elts, - ha.dns_wc_tail.nelts) != NGX_OK) - { - goto failed; - } - - rdcmcf->names.wc_tail = (ngx_hash_wildcard_t *) hash.hash; - - } - - ngx_destroy_pool(ha.temp_pool); - -#if (NGX_PCRE) - if (regex == 0) { - return NGX_OK; - } - - rdcmcf->nregex = regex; - rdcmcf->regex = ngx_pcalloc(cf->pool, - regex * sizeof(ngx_rtmp_dynamic_server_name_t)); - if (rdcmcf->regex == NULL) { - return NGX_ERROR; - } - - i = 0; - - for (s = 0; s < rdcmcf->servers.nelts; ++s) { - - name = rdcscfp[s]->server_names.elts; - - for (n = 0; n < rdcscfp[s]->server_names.nelts; ++n) { - if (name[n].regex) { - rdcmcf->regex[i++] = name[n]; - } - } - } -#endif - - return NGX_OK; - -failed: - ngx_destroy_pool(ha.temp_pool); - - return NGX_ERROR; -} - -static ngx_int_t -ngx_rtmp_dynamic_core_find_virtual_server(ngx_str_t *server, - ngx_rtmp_dynamic_core_main_conf_t *rdcmcf, - ngx_rtmp_dynamic_core_srv_conf_t **rdcscfp) -{ - ngx_rtmp_dynamic_core_srv_conf_t *rdcscf; - - rdcscf = ngx_hash_find_combined(&rdcmcf->names, - ngx_hash_key(server->data, server->len), - server->data, server->len); - - if (rdcscf) { - *rdcscfp = rdcscf; - return NGX_OK; - } - -#if (NGX_PCRE) - - if (server->len && rdcmcf->nregex) { - ngx_int_t n; - ngx_uint_t i; - ngx_rtmp_dynamic_server_name_t *sn; - - sn = rdcmcf->regex; - - for (i = 0; i < rdcmcf->nregex; ++i) { - - n = ngx_regex_exec(sn[i].regex->regex, server, NULL, 0); - - if (n == NGX_REGEX_NO_MATCHED) { - continue; - } - - if (n >= 0) { - *rdcscfp = sn[i].server; - return NGX_OK; - } - - return NGX_ERROR; - } - } -#endif - - return NGX_DECLINED; -} - -static char * -ngx_rtmp_dynamic_core_application(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf) -{ - ngx_rtmp_dynamic_module_t *module; - ngx_rtmp_dynamic_core_app_conf_t *rdcacf; - ngx_rtmp_dynamic_core_srv_conf_t *rdcscf; - ngx_conf_t pcf; - void *mconf, **app_conf; - ngx_uint_t i, ci; - ngx_str_t *value; - char *rv = NULL; - - rdcscf = conf; - - /* app_conf is temp cause hdclcf does not created now */ - app_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_rtmp_max_module); - if (app_conf == NULL) { - return NGX_CONF_ERROR; - } - - for (i = 0; cf->cycle->modules[i]; ++i) { - if (cf->cycle->modules[i]->type != NGX_RTMP_MODULE) { - continue; - } - - module = (ngx_rtmp_dynamic_module_t *) - cf->cycle->modules[i]->spare_hook0; - - if (module == NULL) { - continue; - } - - if (module->create_app_conf) { - mconf = module->create_app_conf(cf); - if (mconf == NULL) { - return NGX_CONF_ERROR; - } - - app_conf[cf->cycle->modules[i]->ctx_index] = mconf; - } - } - - rdcacf = app_conf[ngx_rtmp_dynamic_core_module.ctx_index]; - rdcacf->app_conf = app_conf; - - value = cf->args->elts; - - rdcacf->name = value[1]; - if (rdcacf->name.len == 1 && rdcacf->name.data[0] == '*') { /* default */ - if (rdcscf->default_app) { - return "is duplicate"; - } - - rdcscf->default_app = rdcacf; - } else { - rdcacf->node.raw_key = (intptr_t) &rdcacf->name; - ngx_map_insert(&rdcscf->app_conf, &rdcacf->node, 0); - } - - pcf = *cf; - cf->ctx = rdcacf->app_conf; - cf->cmd_type = NGX_RTMP_APP_CONF; - - if (ngx_dynamic_conf_parse(cf, 0) != NGX_OK) { - goto failed; - } - - for (i = 0; cf->cycle->modules[i]; ++i) { - if (cf->cycle->modules[i]->type != NGX_RTMP_MODULE) { - continue; - } - - module = (ngx_rtmp_dynamic_module_t *) - cf->cycle->modules[i]->spare_hook0; - ci = cf->cycle->modules[i]->ctx_index; - if (module == NULL) { - continue; - } - - if (module->init_app_conf) { - rv = module->init_app_conf(cf, rdcacf->app_conf[ci]); - if (rv != NGX_CONF_OK) { - goto failed; - } - } - } - - *cf = pcf; - - return NGX_CONF_OK; - -failed: - *cf = pcf; - - if (rv) { - return rv; - } - - return NGX_CONF_ERROR; -} - -static char * -ngx_rtmp_dynamic_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf) -{ - ngx_rtmp_dynamic_core_srv_conf_t *rdcscf; - u_char ch; - ngx_str_t *value; - ngx_uint_t i; - ngx_rtmp_dynamic_server_name_t *sn; - - rdcscf = conf; - - value = cf->args->elts; - - for (i = 1; i < cf->args->nelts; i++) { - - ch = value[i].data[0]; - - if ((ch == '*' && (value[i].len < 3 || value[i].data[1] != '.')) - || (ch == '.' && value[i].len < 2)) - { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "server name \"%V\" is invalid", &value[i]); - return NGX_CONF_ERROR; - } - - if (ngx_strchr(value[i].data, '/')) { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, - "server name \"%V\" has suspicious symbols", - &value[i]); - } - - sn = ngx_array_push(&rdcscf->server_names); - if (sn == NULL) { - return NGX_CONF_ERROR; - } - -#if (NGX_PCRE) - sn->regex = NULL; -#endif - sn->server = rdcscf; - - if (ngx_strcasecmp(value[i].data, (u_char *) "$hostname") == 0) { - sn->name = cf->cycle->hostname; - - } else { - sn->name = value[i]; - } - - if (value[i].data[0] != '~') { - ngx_strlow(sn->name.data, sn->name.data, sn->name.len); - continue; - } - -#if (NGX_PCRE) - { - u_char *p; - ngx_regex_compile_t rc; - u_char errstr[NGX_MAX_CONF_ERRSTR]; - - if (value[i].len == 1) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "empty regex in server name \"%V\"", &value[i]); - return NGX_CONF_ERROR; - } - - value[i].len--; - value[i].data++; - - ngx_memzero(&rc, sizeof(ngx_regex_compile_t)); - - rc.pattern = value[i]; - rc.err.len = NGX_MAX_CONF_ERRSTR; - rc.err.data = errstr; - - for (p = value[i].data; p < value[i].data + value[i].len; p++) { - if (*p >= 'A' && *p <= 'Z') { - rc.options = NGX_REGEX_CASELESS; - break; - } - } - - sn->regex = ngx_dynamic_regex_compile(cf, &rc); - if (sn->regex == NULL) { - return NGX_CONF_ERROR; - } - - sn->name = value[i]; - } -#else - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "using regex \"%V\" " - "requires PCRE library", &value[i]); - - return NGX_CONF_ERROR; -#endif - } - - return NGX_CONF_OK; -} - -static char * -ngx_rtmp_dynamic_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_rtmp_dynamic_module_t *module; - ngx_rtmp_dynamic_core_main_conf_t *rdcmcf; - ngx_rtmp_dynamic_core_srv_conf_t *rdcscf, **rdcscfp; - ngx_conf_t pcf; - void *mconf, **srv_conf; - ngx_uint_t i, ci; - char *rv = NULL; - - rdcmcf = conf; - - /* srv_conf is temp cause hdcscf does not created now */ - srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_rtmp_max_module); - if (srv_conf == NULL) { - return NGX_CONF_ERROR; - } - - for (i = 0; cf->cycle->modules[i]; ++i) { - if (cf->cycle->modules[i]->type != NGX_RTMP_MODULE) { - continue; - } - - module = (ngx_rtmp_dynamic_module_t *) - cf->cycle->modules[i]->spare_hook0; - if (module == NULL) { - continue; - } - - if (module->create_srv_conf) { - mconf = module->create_srv_conf(cf); - if (mconf == NULL) { - return NGX_CONF_ERROR; - } - - srv_conf[cf->cycle->modules[i]->ctx_index] = mconf; - } - } - - rdcscf = srv_conf[ngx_rtmp_dynamic_core_module.ctx_index]; - rdcscf->srv_conf = srv_conf; - ngx_map_init(&rdcscf->app_conf, ngx_map_hash_str, ngx_cmp_str); - - /* save hdcscf into hdcmcf */ - rdcscfp = ngx_array_push(&rdcmcf->servers); - if (rdcscfp == NULL) { - return NGX_CONF_ERROR; - } - *rdcscfp = rdcscf; - - pcf = *cf; - cf->ctx = rdcscf->srv_conf; - cf->cmd_type = NGX_RTMP_SRV_CONF; - - if (ngx_dynamic_conf_parse(cf, 0) != NGX_OK) { - goto failed; - } - - for (i = 0; cf->cycle->modules[i]; ++i) { - if (cf->cycle->modules[i]->type != NGX_RTMP_MODULE) { - continue; - } - - module = (ngx_rtmp_dynamic_module_t *) - cf->cycle->modules[i]->spare_hook0; - ci = cf->cycle->modules[i]->ctx_index; - if (module == NULL) { - continue; - } - - if (module->init_srv_conf) { - rv = module->init_srv_conf(cf, rdcscf->srv_conf[ci]); - if (rv != NGX_CONF_OK) { - goto failed; - } - } - } - - *cf = pcf; - - return NGX_CONF_OK; - -failed: - *cf = pcf; - - if (rv) { - return rv; - } - - return NGX_CONF_ERROR; -} - -static char * -ngx_rtmp_dynamic_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_rtmp_dynamic_conf_t *rdccf; - ngx_rtmp_dynamic_module_t *module; - ngx_conf_t pcf; - ngx_uint_t i, ci; - char *rv = NULL; - - rdccf = conf; - - /* create main_conf ctx */ - rdccf->main_conf = ngx_pcalloc(cf->pool, sizeof(void *) - * ngx_rtmp_max_module); - if (rdccf->main_conf == NULL) { - return NGX_CONF_ERROR; - } - - /* create http dynamic conf for all http module */ - for (i = 0; cf->cycle->modules[i]; ++i) { - if (cf->cycle->modules[i]->type != NGX_RTMP_MODULE) { - continue; - } - - module = (ngx_rtmp_dynamic_module_t *) - cf->cycle->modules[i]->spare_hook0; - ci = cf->cycle->modules[i]->ctx_index; - - if (module == NULL) { - continue; - } - - if (module->create_main_conf) { - rdccf->main_conf[ci] = module->create_main_conf(cf); - if (rdccf->main_conf[ci] == NULL) { - return NGX_CONF_ERROR; - } - } - } - - /* save conf for recovery */ - pcf = *cf; - - cf->ctx = rdccf->main_conf; - cf->module_type = NGX_RTMP_MODULE; - cf->cmd_type = NGX_RTMP_MAIN_CONF; - - if (ngx_dynamic_conf_parse(cf, 0) != NGX_OK) { - goto failed; - } - - for (i = 0; cf->cycle->modules[i]; ++i) { - if (cf->cycle->modules[i]->type != NGX_RTMP_MODULE) { - continue; - } - - module = (ngx_rtmp_dynamic_module_t *) - cf->cycle->modules[i]->spare_hook0; - ci = cf->cycle->modules[i]->ctx_index; - - if (module == NULL) { - continue; - } - - if (module->init_main_conf) { - rv = module->init_main_conf(cf, rdccf->main_conf[ci]); - if (rv != NGX_CONF_OK) { - goto failed; - } - } - } - - if (ngx_rtmp_dynamic_core_init_virtual_servers(cf, rdccf) != NGX_OK) { - goto failed; - } - - *cf = pcf; - - return NGX_CONF_OK; - -failed: - *cf = pcf; - - if (rv) { - return rv; - } - - return NGX_CONF_ERROR; -} - - -/* interface from here */ - -void * -ngx_rtmp_get_module_main_dconf(ngx_rtmp_session_t *s, ngx_module_t *m) -{ - ngx_rtmp_dynamic_conf_t *rdcf; - - rdcf = ngx_get_dconf(&ngx_rtmp_dynamic_module); - if (rdcf == NULL || rdcf->main_conf == NULL) { - return NULL; - } - - return rdcf->main_conf[m->ctx_index]; -} - -void * -ngx_rtmp_get_module_srv_dconf(ngx_rtmp_session_t *s, ngx_module_t *m) -{ - ngx_rtmp_dynamic_core_main_conf_t *rdcmcf; - ngx_rtmp_dynamic_core_srv_conf_t *rdcscf; - ngx_int_t rc; - - rdcmcf = ngx_rtmp_get_module_main_dconf(s, &ngx_rtmp_dynamic_core_module); - if (rdcmcf == NULL) { - return NULL; - } - - rc = ngx_rtmp_dynamic_core_find_virtual_server(&s->domain, rdcmcf, &rdcscf); - switch (rc) { - case NGX_ERROR: - return NULL; - case NGX_DECLINED: /* virtual server not found */ - return rdcmcf->default_server->srv_conf[m->ctx_index]; - default: - return rdcscf->srv_conf[m->ctx_index]; - } -} - -void * -ngx_rtmp_get_module_app_dconf(ngx_rtmp_session_t *s, ngx_module_t *m) -{ - ngx_rtmp_dynamic_core_srv_conf_t *rdcscf; - ngx_rtmp_dynamic_core_app_conf_t *rdcacf; - ngx_int_t rc; - - rdcscf = ngx_rtmp_get_module_srv_dconf(s, &ngx_rtmp_dynamic_core_module); - if (rdcscf == NULL) { - return NULL; - } - - rdcacf = NULL; - rc = ngx_rtmp_dynamic_core_find_application(s, rdcscf, &rdcacf); - if (rc == NGX_ERROR) { - return NULL; - } - - if (rdcacf) { - return rdcacf->app_conf[m->ctx_index]; - } - - return NULL; -} - -void -ngx_rmtp_get_serverid_by_domain(ngx_str_t *serverid, ngx_str_t *domain) -{ - ngx_rtmp_dynamic_conf_t *rdcf; - ngx_rtmp_dynamic_core_main_conf_t *rdcmcf; - ngx_rtmp_dynamic_core_srv_conf_t *rdcscf; - ngx_rtmp_core_srv_dconf_t *rcsdcf; - - rdcf = ngx_get_dconf(&ngx_rtmp_dynamic_module); - if (rdcf == NULL || rdcf->main_conf) { - goto notfound; - } - - rdcmcf = rdcf->main_conf[ngx_rtmp_dynamic_core_module.ctx_index]; - if (rdcmcf == NULL) { - goto notfound; - } - - ngx_rtmp_dynamic_core_find_virtual_server(domain, rdcmcf, &rdcscf); - if (rdcscf && rdcscf->srv_conf) { - rcsdcf = rdcscf->srv_conf[ngx_rtmp_core_module.ctx_index]; - if (rcsdcf && rcsdcf->serverid.len) { - *serverid = rcsdcf->serverid; - return; - } - } - -notfound: - *serverid = *domain; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_dynamic.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_dynamic.h deleted file mode 100644 index f74c724388..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_dynamic.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#ifndef _NGX_RTMP_DYNAMIC_H_INCLUDED_ -#define _NGX_RTMP_DYNAMIC_H_INCLUDED_ - - -#include -#include -#include "ngx_map.h" -#include "ngx_dynamic_conf.h" -#include "ngx_rtmp.h" - - -typedef struct { - void *(*create_main_conf)(ngx_conf_t *cf); - char *(*init_main_conf)(ngx_conf_t *cf, void *conf); - - void *(*create_srv_conf)(ngx_conf_t *cf); - char *(*init_srv_conf)(ngx_conf_t *cf, void *conf); - - void *(*create_app_conf)(ngx_conf_t *cf); - char *(*init_app_conf)(ngx_conf_t *cf, void *conf); -} ngx_rtmp_dynamic_module_t; - - -void *ngx_rtmp_get_module_main_dconf(ngx_rtmp_session_t *s, ngx_module_t *m); -void *ngx_rtmp_get_module_srv_dconf(ngx_rtmp_session_t *s, ngx_module_t *m); -void *ngx_rtmp_get_module_app_dconf(ngx_rtmp_session_t *s, ngx_module_t *m); - -void ngx_rmtp_get_serverid_by_domain(ngx_str_t *serverid, ngx_str_t *domain); - - -#endif diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_eval.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_eval.c deleted file mode 100644 index d79d647298..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_eval.c +++ /dev/null @@ -1,298 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include -#include "ngx_rtmp_eval.h" - - -#define NGX_RTMP_EVAL_BUFLEN 16 - - -static void -ngx_rtmp_eval_session_str(void *ctx, ngx_rtmp_eval_t *e, ngx_str_t *ret) -{ - *ret = *(ngx_str_t *) ((u_char *) ctx + e->offset); -} - - -static void -ngx_rtmp_eval_connection_str(void *ctx, ngx_rtmp_eval_t *e, ngx_str_t *ret) -{ - ngx_rtmp_session_t *s = ctx; - - *ret = *(ngx_str_t *) ((u_char *) s->connection + e->offset); -} - - -ngx_rtmp_eval_t ngx_rtmp_eval_session[] = { - - { ngx_string("app"), - ngx_rtmp_eval_session_str, - offsetof(ngx_rtmp_session_t, app) }, - - { ngx_string("flashver"), - ngx_rtmp_eval_session_str, - offsetof(ngx_rtmp_session_t, flashver) }, - - { ngx_string("swfurl"), - ngx_rtmp_eval_session_str, - offsetof(ngx_rtmp_session_t, swf_url) }, - - { ngx_string("tcurl"), - ngx_rtmp_eval_session_str, - offsetof(ngx_rtmp_session_t, tc_url) }, - - { ngx_string("pageurl"), - ngx_rtmp_eval_session_str, - offsetof(ngx_rtmp_session_t, page_url) }, - - { ngx_string("addr"), - ngx_rtmp_eval_connection_str, - offsetof(ngx_connection_t, addr_text) }, - - ngx_rtmp_null_eval -}; - - -static void -ngx_rtmp_eval_append(ngx_buf_t *b, void *data, size_t len, ngx_log_t *log) -{ - size_t buf_len; - - if (b->last + len > b->end) { - buf_len = 2 * (b->last - b->pos) + len; - - b->start = ngx_alloc(buf_len, log); - if (b->start == NULL) { - return; - } - - b->last = ngx_cpymem(b->start, b->pos, b->last - b->pos); - b->pos = b->start; - b->end = b->start + buf_len; - } - - b->last = ngx_cpymem(b->last, data, len); -} - - -static void -ngx_rtmp_eval_append_var(void *ctx, ngx_buf_t *b, ngx_rtmp_eval_t **e, - ngx_str_t *name, ngx_log_t *log) -{ - ngx_uint_t k; - ngx_str_t v; - ngx_rtmp_eval_t *ee; - - for (; *e; ++e) { - for (k = 0, ee = *e; ee->handler; ++k, ++ee) { - if (ee->name.len == name->len && - ngx_memcmp(ee->name.data, name->data, name->len) == 0) - { - ee->handler(ctx, ee, &v); - ngx_rtmp_eval_append(b, v.data, v.len, log); - } - } - } -} - - -ngx_int_t -ngx_rtmp_eval(void *ctx, ngx_str_t *in, ngx_rtmp_eval_t **e, ngx_str_t *out, - ngx_log_t *log) -{ - u_char c, *p; - ngx_str_t name; - ngx_buf_t b; - ngx_uint_t n; - - enum { - NORMAL, - ESCAPE, - NAME, - SNAME - } state = NORMAL; - - b.pos = b.last = b.start = ngx_alloc(NGX_RTMP_EVAL_BUFLEN, log); - if (b.pos == NULL) { - return NGX_ERROR; - } - - b.end = b.pos + NGX_RTMP_EVAL_BUFLEN; - name.data = NULL; - - for (n = 0; n < in->len; ++n) { - p = &in->data[n]; - c = *p; - - switch (state) { - case SNAME: - if (c != '}') { - continue; - } - - name.len = p - name.data; - ngx_rtmp_eval_append_var(ctx, &b, e, &name, log); - - state = NORMAL; - - continue; - - case NAME: - if (c == '{' && name.data == p) { - ++name.data; - state = SNAME; - continue; - } - if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { - continue; - } - - name.len = p - name.data; - ngx_rtmp_eval_append_var(ctx, &b, e, &name, log); - switch (c) { - case '$': - name.data = p + 1; - state = NAME; - continue; - case '\\': - state = ESCAPE; - continue; - } - - ngx_rtmp_eval_append(&b, &c, 1, log); - state = NORMAL; - break; - - case NORMAL: - switch (c) { - case '$': - name.data = p + 1; - state = NAME; - continue; - case '\\': - state = ESCAPE; - continue; - } - ngx_rtmp_eval_append(&b, &c, 1, log); - state = NORMAL; - break; - - case ESCAPE: - ngx_rtmp_eval_append(&b, &c, 1, log); - state = NORMAL; - break; - - } - } - - if (state == NAME) { - p = &in->data[n]; - name.len = p - name.data; - ngx_rtmp_eval_append_var(ctx, &b, e, &name, log); - } - - c = 0; - ngx_rtmp_eval_append(&b, &c, 1, log); - - out->data = b.pos; - out->len = b.last - b.pos - 1; - - return NGX_OK; -} - - -ngx_int_t -ngx_rtmp_eval_streams(ngx_str_t *in) -{ -#if !(NGX_WIN32) - ngx_int_t mode, create, v, close_src; - ngx_fd_t dst, src; - u_char *path; - - path = in->data; - - while (*path >= '0' && *path <= '9') { - path++; - } - - switch ((char) *path) { - - case '>': - - v = (path == in->data ? 1 : ngx_atoi(in->data, path - in->data)); - if (v == NGX_ERROR) { - return NGX_ERROR; - } - - dst = (ngx_fd_t) v; - mode = NGX_FILE_WRONLY; - create = NGX_FILE_TRUNCATE; - path++; - - if (*path == (u_char) '>') { - mode = NGX_FILE_APPEND; - create = NGX_FILE_CREATE_OR_OPEN; - path++; - } - - break; - - case '<': - - v = (path == in->data ? 0 : ngx_atoi(in->data, path - in->data)); - if (v == NGX_ERROR) { - return NGX_ERROR; - } - - dst = (ngx_fd_t) v; - mode = NGX_FILE_RDONLY; - create = NGX_FILE_OPEN; - path++; - - break; - - default: - - return NGX_DONE; - } - - if (*path == (u_char) '&') { - - path++; - v = ngx_atoi(path, in->data + in->len - path); - if (v == NGX_ERROR) { - return NGX_ERROR; - } - src = (ngx_fd_t) v; - close_src = 0; - - } else { - - src = ngx_open_file(path, mode, create, NGX_FILE_DEFAULT_ACCESS); - if (src == NGX_INVALID_FILE) { - return NGX_ERROR; - } - close_src = 1; - - } - - if (src == dst) { - return NGX_OK; - } - - dup2(src, dst); - - if (close_src) { - ngx_close_file(src); - } - return NGX_OK; - -#else - return NGX_DONE; -#endif -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_eval.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_eval.h deleted file mode 100644 index b05d16b111..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_eval.h +++ /dev/null @@ -1,44 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#ifndef _NGX_RTMP_EVAL_H_INCLUDED_ -#define _NGX_RTMP_EVAL_H_INCLUDED_ - - -#include -#include -#include "ngx_rtmp.h" - - -typedef struct ngx_rtmp_eval_s ngx_rtmp_eval_t; - - -typedef void (* ngx_rtmp_eval_pt)(void *ctx, ngx_rtmp_eval_t *e, - ngx_str_t *ret); - - -struct ngx_rtmp_eval_s { - ngx_str_t name; - ngx_rtmp_eval_pt handler; - ngx_uint_t offset; -}; - - -#define ngx_rtmp_null_eval { ngx_null_string, NULL, 0 } - - -/* standard session eval variables */ -extern ngx_rtmp_eval_t ngx_rtmp_eval_session[]; - - -ngx_int_t ngx_rtmp_eval(void *ctx, ngx_str_t *in, ngx_rtmp_eval_t **e, - ngx_str_t *out, ngx_log_t *log); - - -ngx_int_t ngx_rtmp_eval_streams(ngx_str_t *in); - - -#endif /* _NGX_RTMP_EVAL_H_INCLUDED_ */ diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_exec_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_exec_module.c deleted file mode 100644 index 2d6c2fed3f..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_exec_module.c +++ /dev/null @@ -1,1551 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include -#include "ngx_rtmp_cmd_module.h" -#include "ngx_rtmp_eval.h" -#include "ngx_poold.h" -#include - -#ifdef NGX_LINUX -#include -#endif - - -#if !(NGX_WIN32) -static ngx_rtmp_publish_pt next_publish; -static ngx_rtmp_play_pt next_play; -static ngx_rtmp_close_stream_pt next_close_stream; -#endif - - -static ngx_int_t ngx_rtmp_exec_init_process(ngx_cycle_t *cycle); -static ngx_int_t ngx_rtmp_exec_postconfiguration(ngx_conf_t *cf); -static void * ngx_rtmp_exec_create_main_conf(ngx_conf_t *cf); -static char * ngx_rtmp_exec_init_main_conf(ngx_conf_t *cf, void *conf); -static void * ngx_rtmp_exec_create_app_conf(ngx_conf_t *cf); -static char * ngx_rtmp_exec_merge_app_conf(ngx_conf_t *cf, - void *parent, void *child); -/*static char * ngx_rtmp_exec_block(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf);*/ -static char * ngx_rtmp_exec_conf(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); -static char *ngx_rtmp_exec_kill_signal(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); - - -#define NGX_RTMP_EXEC_RESPAWN 0x01 -#define NGX_RTMP_EXEC_KILL 0x02 - - -#define NGX_RTMP_EXEC_PUBLISHING 0x01 -#define NGX_RTMP_EXEC_PLAYING 0x02 - - -enum { - NGX_RTMP_EXEC_PUSH, - NGX_RTMP_EXEC_PULL, - - NGX_RTMP_EXEC_PUBLISH, - NGX_RTMP_EXEC_PUBLISH_DONE, - NGX_RTMP_EXEC_PLAY, - NGX_RTMP_EXEC_PLAY_DONE, - NGX_RTMP_EXEC_RECORD_DONE, - - NGX_RTMP_EXEC_MAX, - - NGX_RTMP_EXEC_STATIC -}; - - -typedef struct { - ngx_str_t id; - ngx_uint_t type; - ngx_str_t cmd; - ngx_array_t args; /* ngx_str_t */ - ngx_array_t names; -} ngx_rtmp_exec_conf_t; - - -typedef struct { - ngx_rtmp_exec_conf_t *conf; - ngx_log_t *log; - ngx_rtmp_eval_t **eval; - void *eval_ctx; - unsigned active:1; - unsigned managed:1; - ngx_pid_t pid; - ngx_pid_t *save_pid; - int pipefd; - ngx_connection_t dummy_conn; /*needed by ngx_xxx_event*/ - ngx_event_t read_evt, write_evt; - ngx_event_t respawn_evt; - ngx_msec_t respawn_timeout; - ngx_int_t kill_signal; -} ngx_rtmp_exec_t; - - -typedef struct { - ngx_array_t static_conf; /* ngx_rtmp_exec_conf_t */ - ngx_array_t static_exec; /* ngx_rtmp_exec_t */ - ngx_msec_t respawn_timeout; - ngx_int_t kill_signal; - ngx_log_t *log; -} ngx_rtmp_exec_main_conf_t; - - -typedef struct ngx_rtmp_exec_pull_ctx_s ngx_rtmp_exec_pull_ctx_t; - -struct ngx_rtmp_exec_pull_ctx_s { - ngx_pool_t *pool; - ngx_uint_t counter; - ngx_str_t name; - ngx_str_t app; - ngx_array_t pull_exec; /* ngx_rtmp_exec_t */ - ngx_rtmp_exec_pull_ctx_t *next; -}; - - -typedef struct { - ngx_int_t active; - ngx_array_t conf[NGX_RTMP_EXEC_MAX]; - /* ngx_rtmp_exec_conf_t */ - ngx_flag_t respawn; - ngx_flag_t options; - ngx_uint_t nbuckets; - ngx_rtmp_exec_pull_ctx_t **pull; -} ngx_rtmp_exec_app_conf_t; - - -typedef struct { - ngx_uint_t flags; - ngx_str_t path; /* /tmp/rec/myfile-123.flv */ - ngx_str_t filename; /* myfile-123.flv */ - ngx_str_t basename; /* myfile-123 */ - ngx_str_t dirname; /* /tmp/rec */ - ngx_str_t recorder; - u_char name[NGX_RTMP_MAX_NAME]; - u_char args[NGX_RTMP_MAX_ARGS]; - u_char starttime[NGX_RTMP_MAX_NAME]; - ngx_array_t push_exec; /* ngx_rtmp_exec_t */ - ngx_rtmp_exec_pull_ctx_t *pull; -} ngx_rtmp_exec_ctx_t; - - -#if !(NGX_WIN32) -static void ngx_rtmp_exec_respawn(ngx_event_t *ev); -static ngx_int_t ngx_rtmp_exec_kill(ngx_rtmp_exec_t *e, ngx_int_t kill_signal); -static ngx_int_t ngx_rtmp_exec_run(ngx_rtmp_exec_t *e); -#endif - - -static ngx_command_t ngx_rtmp_exec_commands[] = { -/* - { ngx_string("exec_block"), - NGX_RTMP_APP_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS|NGX_CONF_TAKE1, - ngx_rtmp_exec_block, - NGX_RTMP_APP_CONF_OFFSET, - 0, - NULL }, -*/ - { ngx_string("exec"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_1MORE, - ngx_rtmp_exec_conf, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_exec_app_conf_t, conf) + - NGX_RTMP_EXEC_PUSH * sizeof(ngx_array_t), - NULL }, - - { ngx_string("exec_push"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_1MORE, - ngx_rtmp_exec_conf, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_exec_app_conf_t, conf) + - NGX_RTMP_EXEC_PUSH * sizeof(ngx_array_t), - NULL }, - - { ngx_string("exec_pull"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_1MORE, - ngx_rtmp_exec_conf, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_exec_app_conf_t, conf) + - NGX_RTMP_EXEC_PULL * sizeof(ngx_array_t), - NULL }, - - { ngx_string("exec_publish"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_1MORE, - ngx_rtmp_exec_conf, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_exec_app_conf_t, conf) + - NGX_RTMP_EXEC_PUBLISH * sizeof(ngx_array_t), - NULL }, - - { ngx_string("exec_publish_done"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_1MORE, - ngx_rtmp_exec_conf, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_exec_app_conf_t, conf) + - NGX_RTMP_EXEC_PUBLISH_DONE * sizeof(ngx_array_t), - NULL }, - - { ngx_string("exec_play"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_1MORE, - ngx_rtmp_exec_conf, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_exec_app_conf_t, conf) + - NGX_RTMP_EXEC_PLAY * sizeof(ngx_array_t), - NULL }, - - { ngx_string("exec_play_done"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_1MORE, - ngx_rtmp_exec_conf, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_exec_app_conf_t, conf) + - NGX_RTMP_EXEC_PLAY_DONE * sizeof(ngx_array_t), - NULL }, - - { ngx_string("exec_record_done"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_RTMP_REC_CONF| - NGX_CONF_1MORE, - ngx_rtmp_exec_conf, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_exec_app_conf_t, conf) + - NGX_RTMP_EXEC_RECORD_DONE * sizeof(ngx_array_t), - NULL }, - - { ngx_string("exec_static"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_1MORE, - ngx_rtmp_exec_conf, - NGX_RTMP_MAIN_CONF_OFFSET, - offsetof(ngx_rtmp_exec_main_conf_t, static_conf), - NULL }, - - { ngx_string("respawn"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_exec_app_conf_t, respawn), - NULL }, - - { ngx_string("respawn_timeout"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_MAIN_CONF_OFFSET, - offsetof(ngx_rtmp_exec_main_conf_t, respawn_timeout), - NULL }, - - { ngx_string("exec_kill_signal"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_rtmp_exec_kill_signal, - NGX_RTMP_MAIN_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("exec_options"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_exec_app_conf_t, options), - NULL }, - - ngx_null_command -}; - - -static ngx_rtmp_module_t ngx_rtmp_exec_module_ctx = { - NULL, /* preconfiguration */ - ngx_rtmp_exec_postconfiguration, /* postconfiguration */ - ngx_rtmp_exec_create_main_conf, /* create main configuration */ - ngx_rtmp_exec_init_main_conf, /* init main configuration */ - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - ngx_rtmp_exec_create_app_conf, /* create app configuration */ - ngx_rtmp_exec_merge_app_conf /* merge app configuration */ -}; - - -ngx_module_t ngx_rtmp_exec_module = { - NGX_MODULE_V1, - &ngx_rtmp_exec_module_ctx, /* module context */ - ngx_rtmp_exec_commands, /* module directives */ - NGX_RTMP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - ngx_rtmp_exec_init_process, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void -ngx_rtmp_exec_eval_ctx_cstr(void *sctx, ngx_rtmp_eval_t *e, ngx_str_t *ret) -{ - ngx_rtmp_session_t *s = sctx; - - ngx_rtmp_exec_ctx_t *ctx; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_exec_module); - if (ctx == NULL) { - ret->len = 0; - return; - } - - ret->data = (u_char *) ctx + e->offset; - ret->len = ngx_strlen(ret->data); -} - - -static void -ngx_rtmp_exec_eval_ctx_str(void *sctx, ngx_rtmp_eval_t *e, ngx_str_t *ret) -{ - ngx_rtmp_session_t *s = sctx; - - ngx_rtmp_exec_ctx_t *ctx; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_exec_module); - if (ctx == NULL) { - ret->len = 0; - return; - } - - *ret = * (ngx_str_t *) ((u_char *) ctx + e->offset); -} - - -static void -ngx_rtmp_exec_eval_pctx_str(void *ctx, ngx_rtmp_eval_t *e, ngx_str_t *ret) -{ - *ret = *(ngx_str_t *) ((u_char *) ctx + e->offset); -} - - -static ngx_rtmp_eval_t ngx_rtmp_exec_push_specific_eval[] = { - - { ngx_string("name"), - ngx_rtmp_exec_eval_ctx_cstr, - offsetof(ngx_rtmp_exec_ctx_t, name) }, - - { ngx_string("args"), - ngx_rtmp_exec_eval_ctx_cstr, - offsetof(ngx_rtmp_exec_ctx_t, args) }, - - ngx_rtmp_null_eval -}; - - -static ngx_rtmp_eval_t * ngx_rtmp_exec_push_eval[] = { - ngx_rtmp_eval_session, - ngx_rtmp_exec_push_specific_eval, - NULL -}; - - -static ngx_rtmp_eval_t ngx_rtmp_exec_pull_specific_eval[] = { - - { ngx_string("name"), - ngx_rtmp_exec_eval_pctx_str, - offsetof(ngx_rtmp_exec_pull_ctx_t, name) }, - - { ngx_string("app"), - ngx_rtmp_exec_eval_pctx_str, - offsetof(ngx_rtmp_exec_pull_ctx_t, app) }, - - ngx_rtmp_null_eval -}; - - -static ngx_rtmp_eval_t * ngx_rtmp_exec_pull_eval[] = { - ngx_rtmp_exec_pull_specific_eval, - NULL -}; - - -static ngx_rtmp_eval_t ngx_rtmp_exec_event_specific_eval[] = { - - { ngx_string("name"), - ngx_rtmp_exec_eval_ctx_cstr, - offsetof(ngx_rtmp_exec_ctx_t, name) }, - - { ngx_string("args"), - ngx_rtmp_exec_eval_ctx_cstr, - offsetof(ngx_rtmp_exec_ctx_t, args) }, - - { ngx_string("path"), - ngx_rtmp_exec_eval_ctx_str, - offsetof(ngx_rtmp_exec_ctx_t, path) }, - - { ngx_string("filename"), - ngx_rtmp_exec_eval_ctx_str, - offsetof(ngx_rtmp_exec_ctx_t, filename) }, - - { ngx_string("basename"), - ngx_rtmp_exec_eval_ctx_str, - offsetof(ngx_rtmp_exec_ctx_t, basename) }, - - { ngx_string("dirname"), - ngx_rtmp_exec_eval_ctx_str, - offsetof(ngx_rtmp_exec_ctx_t, dirname) }, - - { ngx_string("recorder"), - ngx_rtmp_exec_eval_ctx_str, - offsetof(ngx_rtmp_exec_ctx_t, recorder) }, - - { ngx_string("starttime"), - ngx_rtmp_exec_eval_ctx_cstr, - offsetof(ngx_rtmp_exec_ctx_t, starttime) }, - - ngx_rtmp_null_eval -}; - - -static ngx_rtmp_eval_t * ngx_rtmp_exec_event_eval[] = { - ngx_rtmp_eval_session, - ngx_rtmp_exec_event_specific_eval, - NULL -}; - - -static void * -ngx_rtmp_exec_create_main_conf(ngx_conf_t *cf) -{ - ngx_rtmp_exec_main_conf_t *emcf; - - emcf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_exec_main_conf_t)); - if (emcf == NULL) { - return NULL; - } - - emcf->respawn_timeout = NGX_CONF_UNSET_MSEC; - emcf->kill_signal = NGX_CONF_UNSET; - - if (ngx_array_init(&emcf->static_conf, cf->pool, 1, - sizeof(ngx_rtmp_exec_conf_t)) != NGX_OK) - { - return NULL; - } - - return emcf; -} - - -static char * -ngx_rtmp_exec_init_main_conf(ngx_conf_t *cf, void *conf) -{ - ngx_rtmp_exec_main_conf_t *emcf = conf; - ngx_rtmp_exec_conf_t *ec; - ngx_rtmp_exec_t *e; - ngx_uint_t n; - - if (emcf->respawn_timeout == NGX_CONF_UNSET_MSEC) { - emcf->respawn_timeout = 5000; - } - -#if !(NGX_WIN32) - if (emcf->kill_signal == NGX_CONF_UNSET) { - emcf->kill_signal = SIGKILL; - } -#endif - - if (ngx_array_init(&emcf->static_exec, cf->pool, - emcf->static_conf.nelts, - sizeof(ngx_rtmp_exec_t)) != NGX_OK) - { - return NGX_CONF_ERROR; - } - - e = ngx_array_push_n(&emcf->static_exec, emcf->static_conf.nelts); - if (e == NULL) { - return NGX_CONF_ERROR; - } - - emcf->log = &cf->cycle->new_log; - - ec = emcf->static_conf.elts; - - for (n = 0; n < emcf->static_conf.nelts; n++, e++, ec++) { - ngx_memzero(e, sizeof(*e)); - e->conf = ec; - e->managed = 1; - e->log = emcf->log; - e->respawn_timeout = emcf->respawn_timeout; - e->kill_signal = emcf->kill_signal; - } - - return NGX_CONF_OK; -} - - -static void * -ngx_rtmp_exec_create_app_conf(ngx_conf_t *cf) -{ - ngx_rtmp_exec_app_conf_t *eacf; - - eacf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_exec_app_conf_t)); - if (eacf == NULL) { - return NULL; - } - - eacf->respawn = NGX_CONF_UNSET; - eacf->options = NGX_CONF_UNSET; - eacf->nbuckets = NGX_CONF_UNSET_UINT; - - return eacf; -} - - -static ngx_int_t -ngx_rtmp_exec_merge_confs(ngx_array_t *conf, ngx_array_t *prev) -{ - size_t n; - ngx_rtmp_exec_conf_t *ec, *pec; - - if (prev->nelts == 0) { - return NGX_OK; - } - - if (conf->nelts == 0) { - *conf = *prev; - return NGX_OK; - } - - ec = ngx_array_push_n(conf, prev->nelts); - if (ec == NULL) { - return NGX_ERROR; - } - - pec = prev->elts; - for (n = 0; n < prev->nelts; n++, ec++, pec++) { - *ec = *pec; - } - - return NGX_OK; -} - - -static char * -ngx_rtmp_exec_merge_app_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_rtmp_exec_app_conf_t *prev = parent; - ngx_rtmp_exec_app_conf_t *conf = child; - - ngx_uint_t n; - - ngx_conf_merge_value(conf->respawn, prev->respawn, 1); - ngx_conf_merge_uint_value(conf->nbuckets, prev->nbuckets, 1024); - - for (n = 0; n < NGX_RTMP_EXEC_MAX; n++) { - if (ngx_rtmp_exec_merge_confs(&conf->conf[n], &prev->conf[n]) != NGX_OK) - { - return NGX_CONF_ERROR; - } - - if (conf->conf[n].nelts) { - conf->active = 1; - prev->active = 1; - } - } - - if (conf->conf[NGX_RTMP_EXEC_PULL].nelts > 0) { - conf->pull = ngx_pcalloc(cf->pool, sizeof(void *) * conf->nbuckets); - if (conf->pull == NULL) { - return NGX_CONF_ERROR; - } - } - - return NGX_CONF_OK; -} - - -static ngx_int_t -ngx_rtmp_exec_init_process(ngx_cycle_t *cycle) -{ -#if !(NGX_WIN32) - ngx_rtmp_core_main_conf_t *cmcf = ngx_rtmp_core_main_conf; - ngx_rtmp_core_srv_conf_t **cscf; - ngx_rtmp_conf_ctx_t *cctx; - ngx_rtmp_exec_main_conf_t *emcf; - ngx_rtmp_exec_t *e; - ngx_uint_t n; - - if (cmcf == NULL || cmcf->servers.nelts == 0) { - return NGX_OK; - } - - /* execs are always started by the first worker */ - if (ngx_process_slot) { - return NGX_OK; - } - - cscf = cmcf->servers.elts; - cctx = (*cscf)->ctx; - emcf = cctx->main_conf[ngx_rtmp_exec_module.ctx_index]; - - /* FreeBSD note: - * When worker is restarted, child process (ffmpeg) will - * not be terminated if it's connected to another - * (still alive) worker. That leads to starting - * another instance of exec_static process. - * Need to kill previously started processes. - * - * On Linux "prctl" syscall is used to kill child - * when nginx worker is terminated. - */ - - e = emcf->static_exec.elts; - for (n = 0; n < emcf->static_exec.nelts; ++n, ++e) { - e->respawn_evt.data = e; - e->respawn_evt.log = e->log; - e->respawn_evt.handler = ngx_rtmp_exec_respawn; - ngx_post_event((&e->respawn_evt), &ngx_rtmp_init_queue); - } -#endif - - return NGX_OK; -} - - -#if !(NGX_WIN32) -static void -ngx_rtmp_exec_respawn(ngx_event_t *ev) -{ - ngx_rtmp_exec_run((ngx_rtmp_exec_t *) ev->data); -} - - -static void -ngx_rtmp_exec_child_dead(ngx_event_t *ev) -{ - ngx_connection_t *dummy_conn = ev->data; - ngx_rtmp_exec_t *e; - - e = dummy_conn->data; - - ngx_log_error(NGX_LOG_INFO, e->log, 0, - "exec: child %ui exited; %s", (ngx_int_t) e->pid, - e->respawn_timeout == NGX_CONF_UNSET_MSEC ? "respawning" : - "ignoring"); - - ngx_rtmp_exec_kill(e, 0); - - if (e->respawn_timeout == NGX_CONF_UNSET_MSEC) { - return; - } - - if (e->respawn_timeout == 0) { - ngx_rtmp_exec_run(e); - return; - } - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, e->log, 0, - "exec: shedule respawn %Mmsec", e->respawn_timeout); - - e->respawn_evt.data = e; - e->respawn_evt.log = e->log; - e->respawn_evt.handler = ngx_rtmp_exec_respawn; - - ngx_add_timer(&e->respawn_evt, e->respawn_timeout); -} - - -static ngx_int_t -ngx_rtmp_exec_kill(ngx_rtmp_exec_t *e, ngx_int_t kill_signal) -{ - if (e->respawn_evt.timer_set) { - ngx_del_timer(&e->respawn_evt); - } - - if (e->read_evt.active) { - ngx_del_event(&e->read_evt, NGX_READ_EVENT, 0); - } - - if (e->active == 0) { - return NGX_OK; - } - - ngx_log_error(NGX_LOG_INFO, e->log, 0, - "exec: terminating child %ui", (ngx_int_t) e->pid); - - e->active = 0; - close(e->pipefd); - if (e->save_pid) { - *e->save_pid = NGX_INVALID_PID; - } - - if (kill_signal == 0) { - return NGX_OK; - } - - if (kill(e->pid, kill_signal) == -1) { - ngx_log_error(NGX_LOG_INFO, e->log, ngx_errno, - "exec: kill failed pid=%i", (ngx_int_t) e->pid); - } else { - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, e->log, 0, - "exec: killed pid=%i", (ngx_int_t) e->pid); - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_exec_run(ngx_rtmp_exec_t *e) -{ - int fd, ret, maxfd, pipefd[2]; - char **args, **arg_out; - ngx_pid_t pid; - ngx_str_t *arg_in, a; - ngx_uint_t n; - ngx_rtmp_exec_conf_t *ec; - - ec = e->conf; - - ngx_log_error(NGX_LOG_INFO, e->log, 0, - "exec: starting %s child '%V'", - e->managed ? "managed" : "unmanaged", &ec->cmd); - - pipefd[0] = -1; - pipefd[1] = -1; - - if (e->managed) { - - if (e->active) { - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, e->log, 0, - "exec: already active '%V'", &ec->cmd); - return NGX_OK; - } - - if (pipe(pipefd) == -1) { - ngx_log_error(NGX_LOG_INFO, e->log, ngx_errno, - "exec: pipe failed"); - return NGX_ERROR; - } - - /* make pipe write end survive through exec */ - - ret = fcntl(pipefd[1], F_GETFD); - - if (ret != -1) { - ret &= ~FD_CLOEXEC; - ret = fcntl(pipefd[1], F_SETFD, ret); - } - - if (ret == -1) { - - close(pipefd[0]); - close(pipefd[1]); - - ngx_log_error(NGX_LOG_INFO, e->log, ngx_errno, - "exec: fcntl failed"); - - return NGX_ERROR; - } - } - - pid = fork(); - - switch (pid) { - - case -1: - - /* failure */ - - if (pipefd[0] != -1) { - close(pipefd[0]); - } - - if (pipefd[1] != -1) { - close(pipefd[1]); - } - - ngx_log_error(NGX_LOG_INFO, e->log, ngx_errno, - "exec: fork failed"); - - return NGX_ERROR; - - case 0: - - /* child */ - -#if (NGX_LINUX) - if (e->managed) { - prctl(PR_SET_PDEATHSIG, e->kill_signal, 0, 0, 0); - } -#endif - - /* close all descriptors but pipe write end */ - - maxfd = sysconf(_SC_OPEN_MAX); - for (fd = 0; fd < maxfd; ++fd) { - if (fd == pipefd[1]) { - continue; - } - - close(fd); - } - - fd = open("/dev/null", O_RDWR); - - dup2(fd, STDIN_FILENO); - dup2(fd, STDOUT_FILENO); - dup2(fd, STDERR_FILENO); - - args = ngx_alloc((ec->args.nelts + 2) * sizeof(char *), e->log); - if (args == NULL) { - exit(1); - } - - arg_in = ec->args.elts; - arg_out = args; - *arg_out++ = (char *) ec->cmd.data; - - for (n = 0; n < ec->args.nelts; n++, ++arg_in) { - - if (e->eval == NULL) { - a = *arg_in; - } else { - ngx_rtmp_eval(e->eval_ctx, arg_in, e->eval, &a, e->log); - } - - if (ngx_rtmp_eval_streams(&a) != NGX_DONE) { - continue; - } - - *arg_out++ = (char *) a.data; - } - - *arg_out = NULL; - -#if (NGX_DEBUG) - { - char **p; - - for (p = args; *p; p++) { - ngx_write_fd(STDERR_FILENO, "'", 1); - ngx_write_fd(STDERR_FILENO, *p, strlen(*p)); - ngx_write_fd(STDERR_FILENO, "' ", 2); - } - - ngx_write_fd(STDERR_FILENO, "\n", 1); - } -#endif - - if (execvp((char *) ec->cmd.data, args) == -1) { - char *msg; - - msg = strerror(errno); - - ngx_write_fd(STDERR_FILENO, "execvp error: ", 14); - ngx_write_fd(STDERR_FILENO, msg, strlen(msg)); - ngx_write_fd(STDERR_FILENO, "\n", 1); - - exit(1); - } - - break; - - default: - - /* parent */ - - if (pipefd[1] != -1) { - close(pipefd[1]); - } - - if (pipefd[0] != -1) { - - e->active = 1; - e->pid = pid; - e->pipefd = pipefd[0]; - - if (e->save_pid) { - *e->save_pid = pid; - } - - e->dummy_conn.fd = e->pipefd; - e->dummy_conn.data = e; - e->dummy_conn.read = &e->read_evt; - e->dummy_conn.write = &e->write_evt; - e->read_evt.data = &e->dummy_conn; - e->write_evt.data = &e->dummy_conn; - - e->read_evt.log = e->log; - e->read_evt.handler = ngx_rtmp_exec_child_dead; - - if (ngx_add_event(&e->read_evt, NGX_READ_EVENT, 0) != NGX_OK) { - ngx_log_error(NGX_LOG_INFO, e->log, ngx_errno, - "exec: failed to add child control event"); - } - } - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, e->log, 0, - "exec: child '%V' started pid=%i", - &ec->cmd, (ngx_int_t) pid); - break; - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_exec_init_ctx(ngx_rtmp_session_t *s, u_char name[NGX_RTMP_MAX_NAME], - u_char args[NGX_RTMP_MAX_ARGS], ngx_uint_t flags) -{ - ngx_uint_t n; - ngx_array_t *push_conf; - ngx_rtmp_exec_t *e; - ngx_rtmp_exec_ctx_t *ctx; - ngx_rtmp_exec_conf_t *ec; - ngx_rtmp_exec_app_conf_t *eacf; - ngx_rtmp_exec_main_conf_t *emcf; - time_t t; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_exec_module); - - if (ctx != NULL) { - goto done; - } - - ctx = ngx_pcalloc(s->pool, sizeof(ngx_rtmp_exec_ctx_t)); - - if (ctx == NULL) { - return NGX_ERROR; - } - - ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_exec_module); - - eacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_exec_module); - - emcf = ngx_rtmp_get_module_main_conf(s, ngx_rtmp_exec_module); - - push_conf = &eacf->conf[NGX_RTMP_EXEC_PUSH]; - - if (push_conf->nelts > 0) { - - if (ngx_array_init(&ctx->push_exec, s->pool, - push_conf->nelts, - sizeof(ngx_rtmp_exec_t)) != NGX_OK) - { - return NGX_ERROR; - } - - e = ngx_array_push_n(&ctx->push_exec, push_conf->nelts); - - if (e == NULL) { - return NGX_ERROR; - } - - ec = push_conf->elts; - - for (n = 0; n < push_conf->nelts; n++, e++, ec++) { - ngx_memzero(e, sizeof(*e)); - e->conf = ec; - e->managed = 1; - e->log = s->log; - e->eval = ngx_rtmp_exec_push_eval; - e->eval_ctx = s; - e->kill_signal = emcf->kill_signal; - e->respawn_timeout = (eacf->respawn ? emcf->respawn_timeout : - NGX_CONF_UNSET_MSEC); - } - } - -done: - - ngx_memcpy(ctx->name, name, NGX_RTMP_MAX_NAME); - ngx_memcpy(ctx->args, args, NGX_RTMP_MAX_ARGS); - - t = time( 0 ); - strftime((char *)(ctx->starttime), sizeof(ctx->starttime), - "%Y%m%d%H%M%S", localtime(&t)); - - ctx->flags |= flags; - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_exec_init_pull_ctx(ngx_rtmp_session_t *s, - u_char name[NGX_RTMP_MAX_NAME]) -{ - size_t len; - ngx_uint_t n; - ngx_pool_t *pool; - ngx_array_t *pull_conf; - ngx_rtmp_exec_t *e; - ngx_rtmp_exec_ctx_t *ctx; - ngx_rtmp_exec_conf_t *ec; - ngx_rtmp_exec_pull_ctx_t *pctx, **ppctx; - ngx_rtmp_exec_app_conf_t *eacf; - ngx_rtmp_exec_main_conf_t *emcf; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_exec_module); - if (ctx->pull != NULL) { - return NGX_OK; - } - - eacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_exec_module); - - pull_conf = &eacf->conf[NGX_RTMP_EXEC_PULL]; - - if (pull_conf->nelts == 0) { - return NGX_OK; - } - - emcf = ngx_rtmp_get_module_main_conf(s, ngx_rtmp_exec_module); - - len = ngx_strlen(name); - - ppctx = &eacf->pull[ngx_hash_key(name, len) % eacf->nbuckets]; - - for (; *ppctx; ppctx = &(*ppctx)->next) { - pctx = *ppctx; - - if (pctx->name.len == len && - ngx_strncmp(name, pctx->name.data, len) == 0) - { - goto done; - } - } - - pool = NGX_CREATE_POOL(4096, emcf->log); - if (pool == NULL) { - return NGX_ERROR; - } - - pctx = ngx_pcalloc(pool, sizeof(ngx_rtmp_exec_pull_ctx_t)); - if (pctx == NULL) { - goto error; - } - - pctx->pool = pool; - pctx->name.len = len; - pctx->name.data = ngx_palloc(pool, len); - - if (pctx->name.data == NULL) { - goto error; - } - - ngx_memcpy(pctx->name.data, name, len); - - pctx->app.len = s->app.len; - pctx->app.data = ngx_palloc(pool, s->app.len); - - if (pctx->app.data == NULL) { - goto error; - } - - ngx_memcpy(pctx->app.data, s->app.data, s->app.len); - - if (ngx_array_init(&pctx->pull_exec, pool, pull_conf->nelts, - sizeof(ngx_rtmp_exec_t)) != NGX_OK) - { - goto error; - } - - e = ngx_array_push_n(&pctx->pull_exec, pull_conf->nelts); - if (e == NULL) { - goto error; - } - - ec = pull_conf->elts; - for (n = 0; n < pull_conf->nelts; n++, e++, ec++) { - ngx_memzero(e, sizeof(*e)); - e->conf = ec; - e->managed = 1; - e->log = emcf->log; - e->eval = ngx_rtmp_exec_pull_eval; - e->eval_ctx = pctx; - e->kill_signal = emcf->kill_signal; - e->respawn_timeout = (eacf->respawn ? emcf->respawn_timeout : - NGX_CONF_UNSET_MSEC); - } - - *ppctx = pctx; - -done: - - ctx->pull = pctx; - ctx->pull->counter++; - - return NGX_OK; - -error: - - NGX_DESTROY_POOL(pool); - - return NGX_ERROR; -} - - -static ngx_int_t -ngx_rtmp_exec_filter(ngx_rtmp_session_t *s, ngx_rtmp_exec_conf_t *ec) -{ - size_t len; - ngx_str_t *v; - ngx_uint_t n; - ngx_rtmp_exec_ctx_t *ctx; - - if (ec->names.nelts == 0) { - return NGX_OK; - } - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_exec_module); - - len = ngx_strlen(ctx->name); - - v = ec->names.elts; - for (n = 0; n < ec->names.nelts; n++, s++) { - if (v->len == len && ngx_strncmp(v->data, ctx->name, len) == 0) { - return NGX_OK; - } - } - - return NGX_DECLINED; -} - - -static void -ngx_rtmp_exec_unmanaged(ngx_rtmp_session_t *s, ngx_array_t *e, const char *op) -{ - ngx_uint_t n; - ngx_rtmp_exec_t en; - ngx_rtmp_exec_conf_t *ec; - - if (e->nelts == 0) { - return; - } - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->log, 0, - "exec: %s %uz unmanaged command(s)", op, e->nelts); - - ec = e->elts; - for (n = 0; n < e->nelts; n++, ec++) { - if (ngx_rtmp_exec_filter(s, ec) != NGX_OK) { - continue; - } - - ngx_memzero(&en, sizeof(ngx_rtmp_exec_t)); - - en.conf = ec; - en.eval = ngx_rtmp_exec_event_eval; - en.eval_ctx = s; - en.log = s->log; - - ngx_rtmp_exec_run(&en); - } -} - - -static void -ngx_rtmp_exec_managed(ngx_rtmp_session_t *s, ngx_array_t *e, const char *op) -{ - ngx_uint_t n; - ngx_rtmp_exec_t *en; - - if (e->nelts == 0) { - return; - } - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->log, 0, - "exec: %s %uz managed command(s)", op, e->nelts); - - en = e->elts; - for (n = 0; n < e->nelts; n++, en++) { - if (ngx_rtmp_exec_filter(s, en->conf) == NGX_OK) { - ngx_rtmp_exec_run(en); - } - } -} - - -static ngx_int_t -ngx_rtmp_exec_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v) -{ - ngx_rtmp_exec_ctx_t *ctx; - ngx_rtmp_exec_app_conf_t *eacf; - - eacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_exec_module); - - if (eacf == NULL || !eacf->active) { - goto next; - } - - if (s->interprocess) { - goto next; - } - - if (ngx_rtmp_exec_init_ctx(s, v->name, v->args, NGX_RTMP_EXEC_PUBLISHING) - != NGX_OK) - { - goto next; - } - - ngx_rtmp_exec_unmanaged(s, &eacf->conf[NGX_RTMP_EXEC_PUBLISH], "publish"); - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_exec_module); - - ngx_rtmp_exec_managed(s, &ctx->push_exec, "push"); - -next: - return next_publish(s, v); -} - - -static ngx_int_t -ngx_rtmp_exec_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v) -{ - ngx_rtmp_exec_ctx_t *ctx; - ngx_rtmp_exec_pull_ctx_t *pctx; - ngx_rtmp_exec_app_conf_t *eacf; - - eacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_exec_module); - - if (eacf == NULL || !eacf->active) { - goto next; - } - - if (ngx_rtmp_exec_init_ctx(s, v->name, v->args, NGX_RTMP_EXEC_PLAYING) - != NGX_OK) - { - goto next; - } - - ngx_rtmp_exec_unmanaged(s, &eacf->conf[NGX_RTMP_EXEC_PLAY], "play"); - - if (ngx_rtmp_exec_init_pull_ctx(s, v->name) != NGX_OK) { - goto next; - } - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_exec_module); - pctx = ctx->pull; - - if (pctx && pctx->counter == 1) { - ngx_rtmp_exec_managed(s, &pctx->pull_exec, "pull"); - } - -next: - return next_play(s, v); -} - - -static ngx_int_t -ngx_rtmp_exec_close_stream(ngx_rtmp_session_t *s, ngx_rtmp_close_stream_t *v) -{ - size_t n; - ngx_rtmp_exec_t *e; - ngx_rtmp_exec_ctx_t *ctx; - ngx_rtmp_exec_pull_ctx_t *pctx, **ppctx; - ngx_rtmp_exec_app_conf_t *eacf; - - eacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_exec_module); - if (eacf == NULL) { - goto next; - } - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_exec_module); - if (ctx == NULL) { - goto next; - } - - if (ctx->flags & NGX_RTMP_EXEC_PUBLISHING) { - ngx_rtmp_exec_unmanaged(s, &eacf->conf[NGX_RTMP_EXEC_PUBLISH_DONE], - "publish_done"); - } - - if (ctx->flags & NGX_RTMP_EXEC_PLAYING) { - ngx_rtmp_exec_unmanaged(s, &eacf->conf[NGX_RTMP_EXEC_PLAY_DONE], - "play_done"); - } - - ctx->flags = 0; - - if (ctx->push_exec.nelts > 0) { - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "exec: delete %uz push command(s)", - ctx->push_exec.nelts); - - e = ctx->push_exec.elts; - for (n = 0; n < ctx->push_exec.nelts; n++, e++) { - ngx_rtmp_exec_kill(e, e->kill_signal); - } - } - - pctx = ctx->pull; - - if (pctx && --pctx->counter == 0) { - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "exec: delete %uz pull command(s)", - pctx->pull_exec.nelts); - - e = pctx->pull_exec.elts; - for (n = 0; n < pctx->pull_exec.nelts; n++, e++) { - ngx_rtmp_exec_kill(e, e->kill_signal); - } - - ppctx = &eacf->pull[ngx_hash_key(pctx->name.data, pctx->name.len) % - eacf->nbuckets]; - - for (; *ppctx; ppctx = &(*ppctx)->next) { - if (pctx == *ppctx) { - *ppctx = pctx->next; - break; - } - } - - NGX_DESTROY_POOL(pctx->pool); - } - - ctx->pull = NULL; - -next: - return next_close_stream(s, v); -} -#endif /* NGX_WIN32 */ - - -static char * -ngx_rtmp_exec_conf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - char *p = conf; - - size_t n, nargs; - ngx_str_t *s, *value, v; - ngx_array_t *confs; - ngx_rtmp_exec_conf_t *ec; - ngx_rtmp_exec_app_conf_t *eacf; - - confs = (ngx_array_t *) (p + cmd->offset); - - eacf = ngx_rtmp_conf_get_module_app_conf(cf, ngx_rtmp_exec_module); - - if (confs->nalloc == 0 && ngx_array_init(confs, cf->pool, 1, - sizeof(ngx_rtmp_exec_conf_t)) - != NGX_OK) - { - return NGX_CONF_ERROR; - } - - value = cf->args->elts; - - ec = ngx_array_push(confs); - if (ec == NULL) { - return NGX_CONF_ERROR; - } - - ngx_memzero(ec, sizeof(ngx_rtmp_exec_conf_t)); - - /* type is undefined for explicit execs */ - - ec->type = NGX_CONF_UNSET_UINT; - ec->cmd = value[1]; - - if (ngx_array_init(&ec->names, cf->pool, 1, sizeof(ngx_str_t)) != NGX_OK) { - return NGX_CONF_ERROR; - } - - if (cf->args->nelts == 2) { - return NGX_CONF_OK; - } - - nargs = cf->args->nelts - 2; - if (ngx_array_init(&ec->args, cf->pool, nargs, sizeof(ngx_str_t)) != NGX_OK) - { - return NGX_CONF_ERROR; - } - - for (n = 2; n < cf->args->nelts; n++) { - - v = value[n]; - - if (eacf->options == 1) { - - if (v.len >= 5 && ngx_strncmp(v.data, "name=", 5) == 0) { - - s = ngx_array_push(&ec->names); - if (s == NULL) { - return NGX_CONF_ERROR; - } - - v.data += 5; - v.len -= 5; - - *s = v; - - continue; - } - } - - s = ngx_array_push(&ec->args); - if (s == NULL) { - return NGX_CONF_ERROR; - } - - *s = v; - } - - return NGX_CONF_OK; -} - -/* -static char * -ngx_rtmp_exec_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - char *rv; - ngx_str_t *value; - ngx_conf_t save; - ngx_array_t *confs; - ngx_rtmp_conf_ctx_t *ctx, *pctx; - ngx_rtmp_exec_conf_t *ec, *eec; - ngx_rtmp_exec_app_conf_t *eacf; - ngx_rtmp_exec_main_conf_t *emcf; - - value = cf->args->elts; - - eacf = ngx_rtmp_conf_get_module_app_conf(cf, ngx_rtmp_exec_module); - - emcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_exec_module); - - ctx = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_conf_ctx_t)); - if (ctx == NULL) { - return NGX_CONF_ERROR; - } - - pctx = cf->ctx; - - ctx->main_conf = pctx->main_conf; - ctx->srv_conf = pctx->srv_conf; - - ctx->app_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_rtmp_max_module); - if (ctx->app_conf == NULL) { - return NGX_CONF_ERROR; - } - - ec = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_exec_conf_t)); - if (ec == NULL) { - return NGX_CONF_ERROR; - } - - ec->id = value[1]; - ec->type = NGX_CONF_UNSET_UINT; - - ctx->app_conf[ngx_rtmp_exec_module.ctx_index] = ec; - - save = *cf; - - cf->ctx = ctx; - cf->cmd_type = NGX_RTMP_EXEC_CONF; - - rv = ngx_conf_parse(cf, NULL); - *cf= save; - - switch (ec->type) { - - case NGX_RTMP_EXEC_STATIC: - confs = &emcf->static_conf; - break; - - case NGX_CONF_UNSET_UINT: - return "unspecified exec type"; - - default: - confs = &eacf->conf[ec->type]; - } - - if (confs->nalloc == 0 && ngx_array_init(confs, cf->pool, 1, - sizeof(ngx_rtmp_exec_conf_t)) - != NGX_OK) - { - return NGX_CONF_ERROR; - } - - eec = ngx_array_push(confs); - if (eec == NULL) { - return NGX_CONF_ERROR; - } - - *eec = *ec; - - return rv; -} -*/ - -static char * -ngx_rtmp_exec_kill_signal(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_rtmp_exec_main_conf_t *emcf = conf; - - ngx_str_t *value; - - value = cf->args->elts; - value++; - - emcf->kill_signal = ngx_atoi(value->data, value->len); - if (emcf->kill_signal != NGX_ERROR) { - return NGX_CONF_OK; - } - -#define NGX_RMTP_EXEC_SIGNAL(name) \ - if (value->len == sizeof(#name) - 1 && \ - ngx_strncasecmp(value->data, (u_char *) #name, value->len) == 0) \ - { \ - emcf->kill_signal = SIG##name; \ - return NGX_CONF_OK; \ - } - - /* POSIX.1-1990 signals */ - -#if !(NGX_WIN32) - NGX_RMTP_EXEC_SIGNAL(HUP); - NGX_RMTP_EXEC_SIGNAL(INT); - NGX_RMTP_EXEC_SIGNAL(QUIT); - NGX_RMTP_EXEC_SIGNAL(ILL); - NGX_RMTP_EXEC_SIGNAL(ABRT); - NGX_RMTP_EXEC_SIGNAL(FPE); - NGX_RMTP_EXEC_SIGNAL(KILL); - NGX_RMTP_EXEC_SIGNAL(SEGV); - NGX_RMTP_EXEC_SIGNAL(PIPE); - NGX_RMTP_EXEC_SIGNAL(ALRM); - NGX_RMTP_EXEC_SIGNAL(TERM); - NGX_RMTP_EXEC_SIGNAL(USR1); - NGX_RMTP_EXEC_SIGNAL(USR2); - NGX_RMTP_EXEC_SIGNAL(CHLD); - NGX_RMTP_EXEC_SIGNAL(CONT); - NGX_RMTP_EXEC_SIGNAL(STOP); - NGX_RMTP_EXEC_SIGNAL(TSTP); - NGX_RMTP_EXEC_SIGNAL(TTIN); - NGX_RMTP_EXEC_SIGNAL(TTOU); -#endif - -#undef NGX_RMTP_EXEC_SIGNAL - - return "unknown signal"; -} - - -static ngx_int_t -ngx_rtmp_exec_postconfiguration(ngx_conf_t *cf) -{ -#if !(NGX_WIN32) - - next_publish = ngx_rtmp_publish; - ngx_rtmp_publish = ngx_rtmp_exec_publish; - - next_play = ngx_rtmp_play; - ngx_rtmp_play = ngx_rtmp_exec_play; - - next_close_stream = ngx_rtmp_close_stream; - ngx_rtmp_close_stream = ngx_rtmp_exec_close_stream; - -#endif /* NGX_WIN32 */ - - return NGX_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_gop_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_gop_module.c deleted file mode 100644 index 771f292c77..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_gop_module.c +++ /dev/null @@ -1,734 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include -#include -#include "ngx_rtmp.h" -#include "ngx_rtmp_codec_module.h" -#include "ngx_rtmp_live_module.h" - - -static ngx_rtmp_close_stream_pt next_close_stream; - - -static void *ngx_rtmp_gop_create_app_conf(ngx_conf_t *cf); -static char *ngx_rtmp_gop_merge_app_conf(ngx_conf_t *cf, void *parent, - void *child); - -static ngx_int_t ngx_rtmp_gop_postconfiguration(ngx_conf_t *cf); - -#define ngx_rtmp_gop_next(s, pos) ((pos + 1) % s->out_queue) -#define ngx_rtmp_gop_prev(s, pos) (pos == 0 ? s->out_queue - 1 : pos - 1) - -typedef struct { - /* publisher: head of cache - * player: cache send position of publisher's out - */ - size_t gop_pos; - /* tail of cache */ - size_t gop_last; - /* 0 for not send, 1 for sending, 2 for sent */ - ngx_flag_t send_gop; - - ngx_rtmp_frame_t *keyframe; - - ngx_rtmp_frame_t *aac_header; - ngx_rtmp_frame_t *avc_header; - - ngx_rtmp_frame_t *latest_aac_header; - ngx_rtmp_frame_t *latest_avc_header; - - ngx_uint_t meta_version; - - uint32_t first_timestamp; - - /* only for publisher, must at last of ngx_rtmp_gop_ctx_t */ - ngx_rtmp_frame_t *cache[]; -} ngx_rtmp_gop_ctx_t; - -typedef struct { - ngx_msec_t cache_time; - ngx_flag_t low_latency; - ngx_flag_t send_all; - ngx_msec_t fix_timestamp; - ngx_flag_t zero_start; -} ngx_rtmp_gop_app_conf_t; - - -static ngx_command_t ngx_rtmp_gop_commands[] = { - - { ngx_string("cache_time"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_gop_app_conf_t, cache_time), - NULL }, - - { ngx_string("low_latency"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_gop_app_conf_t, low_latency), - NULL }, - - { ngx_string("send_all"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_gop_app_conf_t, send_all), - NULL }, - - { ngx_string("fix_timestamp"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_gop_app_conf_t, fix_timestamp), - NULL }, - - { ngx_string("zero_start"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_gop_app_conf_t, zero_start), - NULL }, - ngx_null_command -}; - - -static ngx_rtmp_module_t ngx_rtmp_gop_module_ctx = { - NULL, /* preconfiguration */ - ngx_rtmp_gop_postconfiguration, /* postconfiguration */ - NULL, /* create main configuration */ - NULL, /* init main configuration */ - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - ngx_rtmp_gop_create_app_conf, /* create app configuration */ - ngx_rtmp_gop_merge_app_conf /* merge app configuration */ -}; - - -ngx_module_t ngx_rtmp_gop_module = { - NGX_MODULE_V1, - &ngx_rtmp_gop_module_ctx, /* module context */ - ngx_rtmp_gop_commands, /* module directives */ - NGX_RTMP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void * -ngx_rtmp_gop_create_app_conf(ngx_conf_t *cf) -{ - ngx_rtmp_gop_app_conf_t *gacf; - - gacf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_gop_app_conf_t)); - if (gacf == NULL) { - return NULL; - } - - gacf->cache_time = NGX_CONF_UNSET_MSEC; - gacf->low_latency = NGX_CONF_UNSET; - gacf->send_all = NGX_CONF_UNSET; - gacf->fix_timestamp = NGX_CONF_UNSET_MSEC; - gacf->zero_start = NGX_CONF_UNSET; - - return gacf; -} - -static char * -ngx_rtmp_gop_merge_app_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_rtmp_gop_app_conf_t *prev = parent; - ngx_rtmp_gop_app_conf_t *conf = child; - - ngx_conf_merge_msec_value(conf->cache_time, prev->cache_time, 0); - ngx_conf_merge_value(conf->low_latency, prev->low_latency, 0); - ngx_conf_merge_value(conf->send_all, prev->send_all, 0); - ngx_conf_merge_msec_value(conf->fix_timestamp, prev->fix_timestamp, 10000); - ngx_conf_merge_value(conf->zero_start, prev->zero_start, 0); - - return NGX_CONF_OK; -} - -static ngx_int_t -ngx_rtmp_gop_link_frame(ngx_rtmp_session_t *s, ngx_rtmp_frame_t *frame) -{ - ngx_uint_t nmsg; - ngx_rtmp_live_chunk_stream_t *cs; - ngx_uint_t csidx; - ngx_rtmp_live_ctx_t *lctx; - ngx_rtmp_gop_ctx_t *ctx; - uint32_t delta; - ngx_rtmp_gop_app_conf_t *gacf; - - if (frame == NULL) { - return NGX_OK; - } - - gacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_gop_module); - if (gacf->fix_timestamp) { - lctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_live_module); - csidx = !(frame->hdr.type == NGX_RTMP_MSG_VIDEO); - - cs = &lctx->cs[csidx]; - - delta = frame->hdr.timestamp > cs->last_timestamp ? - frame->hdr.timestamp - cs->last_timestamp : - cs->last_timestamp - frame->hdr.timestamp; - - if (delta > gacf->fix_timestamp) { - delta = 0; - } - - if (!gacf->zero_start && cs->timestamp == 0) { - cs->timestamp = frame->hdr.timestamp; - } else if (frame->hdr.timestamp > cs->last_timestamp) { - cs->timestamp += delta; - } else if (cs->timestamp >= delta) { - cs->timestamp -= delta; - } - - cs->last_timestamp = frame->hdr.timestamp; - - ngx_log_error(NGX_LOG_DEBUG, s->log, 0, - "gop: link_frame| type %d, delta %d," - " timestamp %uD, fixed timestamp %uD", - frame->hdr.type, delta, frame->hdr.timestamp, cs->timestamp); - - frame->hdr.timestamp = cs->timestamp; - if (frame->hdr.type == NGX_RTMP_MSG_AMF_META) { - frame->hdr.timestamp = 0; - } - } - - nmsg = (s->out_last - s->out_pos) % s->out_queue + 1; - - if (nmsg >= s->out_queue) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "link frame nmsg(%ui) >= out_queue(%O)", nmsg, s->out_queue); - return NGX_AGAIN; - } - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_gop_module); - - if (frame->hdr.type == NGX_RTMP_MSG_AUDIO && frame->av_header) { - ctx->latest_aac_header = frame; - } - - if (frame->hdr.type == NGX_RTMP_MSG_VIDEO && frame->av_header) { - ctx->latest_avc_header = frame; - } - - s->out[s->out_last] = frame; - s->out_last = ngx_rtmp_gop_next(s, s->out_last); - - ngx_rtmp_shared_acquire_frame(frame); - - return NGX_OK; -} - -static void -ngx_rtmp_gop_set_avframe_tag(ngx_rtmp_frame_t *frame) -{ - ngx_chain_t *cl; - - if (frame->hdr.type != NGX_RTMP_MSG_AUDIO && - frame->hdr.type != NGX_RTMP_MSG_VIDEO) - { - return; - } - - cl = frame->chain; - - frame->av_header = ngx_rtmp_is_codec_header(cl); - frame->keyframe = (frame->hdr.type == NGX_RTMP_MSG_VIDEO) - ? (ngx_rtmp_get_video_frame_type(cl) == NGX_RTMP_VIDEO_KEY_FRAME) - : 0; - - if (frame->av_header) { - frame->mandatory = 1; - } -} - -static void -ngx_rtmp_gop_reset_avheader(ngx_rtmp_gop_ctx_t *ctx, - ngx_rtmp_frame_t *frame) -{ - if (frame->hdr.type == NGX_RTMP_MSG_AUDIO) { - if (ctx->aac_header) { - ngx_rtmp_shared_free_frame(ctx->aac_header); - } - ctx->aac_header = frame; - } else { - if (ctx->avc_header) { - ngx_rtmp_shared_free_frame(ctx->avc_header); - } - ctx->avc_header = frame; - } -} - -static void -ngx_rtmp_gop_reset_gop(ngx_rtmp_session_t *s, ngx_rtmp_gop_ctx_t *ctx, - ngx_rtmp_frame_t *frame) -{ - ngx_rtmp_gop_app_conf_t *gacf; - ngx_rtmp_frame_t *f, *next_keyframe; - size_t pos; - ngx_uint_t nmsg; - - /* reset av_header at the front of cache */ - for (pos = ctx->gop_pos; pos != ctx->gop_last; - pos = ngx_rtmp_gop_next(s, pos)) - { - if (ctx->cache[pos]->av_header) { - ngx_rtmp_gop_reset_avheader(ctx, ctx->cache[pos]); - ctx->gop_pos = ngx_rtmp_gop_next(s, ctx->gop_pos); - continue; - } - - break; - } - - f = ctx->cache[pos]; - if (f == NULL) { - return; - } - - gacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_gop_module); - - /* only audio in cache */ - if (ctx->keyframe == NULL) { - if (frame->hdr.timestamp - ctx->cache[ctx->gop_pos]->hdr.timestamp - > gacf->cache_time) - { - ngx_rtmp_shared_free_frame(f); - ctx->cache[ctx->gop_pos] = NULL; - ctx->gop_pos = ngx_rtmp_gop_next(s, ctx->gop_pos); - } - - return; - } - - /* only video of video + audio */ - next_keyframe = ctx->keyframe->next; - - /* only one gop in cache */ - if (next_keyframe == NULL) { - return; - } - - nmsg = (ctx->gop_last - ctx->gop_pos) % s->out_queue + 2; - if (nmsg >= s->out_queue) { - goto reset; - } - - if (frame->hdr.type == NGX_RTMP_MSG_AUDIO) { - return; - } - - if (frame->hdr.type == NGX_RTMP_MSG_VIDEO && frame->hdr.timestamp - - next_keyframe->hdr.timestamp < gacf->cache_time) - { - return; - } - -reset: - for (pos = ctx->gop_pos; ctx->cache[pos] != next_keyframe; - pos = ngx_rtmp_gop_next(s, pos)) - { - f = ctx->cache[pos]; - - if (f->av_header) { - ngx_rtmp_gop_reset_avheader(ctx, f); - } else { - ngx_rtmp_shared_free_frame(f); - } - - ctx->cache[pos] = NULL; - } - - ctx->keyframe = next_keyframe; - ctx->gop_pos = pos; -} - -static void -ngx_rtmp_gop_print_cache(ngx_rtmp_session_t *s, ngx_rtmp_gop_ctx_t *ctx) -{ -#if (NGX_DEBUG) - ngx_rtmp_frame_t *frame; - u_char content[10240], *p; - size_t pos; - - ngx_memzero(content, sizeof(content)); - - p = content; - for (pos = ctx->gop_pos; pos != ctx->gop_last; - pos = ngx_rtmp_gop_next(s, pos)) - { - frame = ctx->cache[pos]; - switch (frame->hdr.type) { - case NGX_RTMP_MSG_AUDIO: - *p++ = 'A'; - break; - case NGX_RTMP_MSG_VIDEO: - *p++ = 'V'; - break; - default: - *p++ = 'O'; - break; - } - - if (frame->keyframe) { - *p++ = 'I'; - } - - if (frame->av_header) { - *p++ = 'H'; - } - - *p++ = ' '; - } - - ngx_log_debug5(NGX_LOG_DEBUG_RTMP, s->log, 0, - "[%z %z] [%p %p] %s", ctx->gop_pos, ctx->gop_last, ctx->aac_header, - ctx->avc_header, content); -#endif -} - -ngx_int_t -ngx_rtmp_gop_cache(ngx_rtmp_session_t *s, ngx_rtmp_frame_t *frame) -{ - ngx_rtmp_gop_app_conf_t *gacf; - ngx_rtmp_gop_ctx_t *ctx; - ngx_rtmp_frame_t **keyframe; - ngx_uint_t nmsg; - - gacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_gop_module); - if (gacf->cache_time == 0) { - return NGX_OK; - } - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_gop_module); - if (ctx == NULL) { - ctx = ngx_pcalloc(s->pool, sizeof(ngx_rtmp_gop_ctx_t) - + s->out_queue * sizeof(ngx_rtmp_frame_t *)); - if (ctx == NULL) { - return NGX_ERROR; - } - ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_gop_module); - } - - nmsg = (ctx->gop_last - ctx->gop_pos) % s->out_queue + 1; - if (nmsg >= s->out_queue) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "cache frame nmsg(%ui) >= out_queue(%z)", nmsg, s->out_queue); - return NGX_AGAIN; - } - - ngx_rtmp_gop_set_avframe_tag(frame); - - ngx_log_debug5(NGX_LOG_DEBUG_RTMP, s->log, 0, - "cache frame: %ud[%d %d], %ud, %ud", - frame->hdr.type, frame->keyframe, frame->av_header, - frame->hdr.timestamp, frame->hdr.mlen); - - if (frame->hdr.type == NGX_RTMP_MSG_AUDIO && frame->av_header) { - ctx->latest_aac_header = frame; - } - - if (frame->hdr.type == NGX_RTMP_MSG_VIDEO && frame->av_header) { - ctx->latest_avc_header = frame; - } - - /* first video frame is not intra_frame or video header */ - if (ctx->keyframe == NULL && frame->hdr.type == NGX_RTMP_MSG_VIDEO - && !frame->keyframe && !frame->av_header) - { - return NGX_OK; - } - - /* video intra_frame */ - if (frame->keyframe && !frame->av_header) { - for (keyframe = &ctx->keyframe; *keyframe; - keyframe = &((*keyframe)->next)); - *keyframe = frame; - } - - ctx->cache[ctx->gop_last] = frame; - ctx->gop_last = ngx_rtmp_gop_next(s, ctx->gop_last); - - ngx_rtmp_shared_acquire_frame(frame); - - ngx_rtmp_gop_reset_gop(s, ctx, frame); - - ngx_rtmp_gop_print_cache(s, ctx); - - return NGX_OK; -} - -static ngx_int_t -ngx_rtmp_gop_send_meta(ngx_rtmp_session_t *s, ngx_rtmp_session_t *ss) -{ - ngx_rtmp_gop_ctx_t *ssctx; - ngx_rtmp_codec_ctx_t *cctx; - - ssctx = ngx_rtmp_get_module_ctx(ss, ngx_rtmp_gop_module); - cctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - - /* meta */ - if (ssctx->meta_version != cctx->meta_version - && ngx_rtmp_gop_link_frame(ss, cctx->meta) == NGX_AGAIN) - { - return NGX_AGAIN; - } - ssctx->meta_version = cctx->meta_version; - - return NGX_OK; -} - -static ngx_int_t -ngx_rtmp_gop_send_gop(ngx_rtmp_session_t *s, ngx_rtmp_session_t *ss) -{ - ngx_rtmp_gop_app_conf_t *gacf; - ngx_rtmp_gop_ctx_t *sctx, *ssctx; - ngx_rtmp_frame_t *frame; - size_t pos; - - gacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_gop_module); - - sctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_gop_module); - ssctx = ngx_rtmp_get_module_ctx(ss, ngx_rtmp_gop_module); - - /* already send gop */ - if (ssctx->send_gop == 3) { - return NGX_OK; - } - - if (ssctx->send_gop == 0) { - if (ngx_rtmp_gop_send_meta(s, ss) == NGX_AGAIN) { - return NGX_AGAIN; - } - - ngx_rtmp_send_message(ss, NULL, 0); - - ssctx->send_gop = 1; - - return NGX_AGAIN; - } - - /* link frame in s to ss */ - if (ssctx->send_gop == 1) { - ssctx->gop_pos = sctx->gop_pos; - if (sctx->cache[ssctx->gop_pos] == NULL) { - return NGX_AGAIN; - } - - if (sctx->aac_header) { - if (ngx_rtmp_gop_link_frame(ss, sctx->aac_header) == NGX_AGAIN) { - return NGX_AGAIN; - } - } - - if (sctx->avc_header) { - if (ngx_rtmp_gop_link_frame(ss, sctx->avc_header) == NGX_AGAIN) { - return NGX_AGAIN; - } - } - - ssctx->send_gop = 2; - ssctx->first_timestamp = sctx->cache[ssctx->gop_pos]->hdr.timestamp; - } else { - if (sctx->cache[ssctx->gop_pos] == NULL) { - ssctx->gop_pos = sctx->gop_pos; - } - } - - pos = ssctx->gop_pos; - frame = sctx->cache[pos]; - while (frame) { - if (!gacf->send_all && - frame->hdr.timestamp - ssctx->first_timestamp >= gacf->cache_time) - { - ssctx->send_gop = 3; - break; - } - - if (ngx_rtmp_gop_link_frame(ss, frame) == NGX_AGAIN) { - break; - } - - pos = ngx_rtmp_gop_next(s, pos); - frame = sctx->cache[pos]; - } - - if (frame == NULL) { /* send all frame in cache */ - ssctx->send_gop = 3; - } - - ssctx->gop_pos = pos; - ngx_rtmp_send_message(ss, NULL, 0); - - return NGX_AGAIN; -} - -ngx_int_t -ngx_rtmp_gop_send(ngx_rtmp_session_t *s, ngx_rtmp_session_t *ss) -{ - ngx_rtmp_gop_app_conf_t *gacf; - ngx_rtmp_gop_ctx_t *sctx, *ssctx; - ngx_rtmp_frame_t *frame; - size_t pos; - - gacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_gop_module); - if (gacf->cache_time == 0) { - return NGX_DECLINED; - } - - sctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_gop_module); - if (sctx == NULL) { /* publisher doesn't publish av frame */ - return NGX_DECLINED; - } - - ssctx = ngx_rtmp_get_module_ctx(ss, ngx_rtmp_gop_module); - if (ssctx == NULL) { - ssctx = ngx_pcalloc(ss->pool, sizeof(ngx_rtmp_gop_ctx_t)); - if (ssctx == NULL) { - return NGX_ERROR; - } - ngx_rtmp_set_ctx(ss, ssctx, ngx_rtmp_gop_module); - } - - if (ngx_rtmp_gop_send_gop(s, ss) == NGX_AGAIN) { - return NGX_OK; - } - - /* send frame by frame */ - if (ngx_rtmp_gop_send_meta(s, ss) == NGX_AGAIN) { - return NGX_AGAIN; - } - - pos = ngx_rtmp_gop_prev(s, sctx->gop_last); - /* new frame is video key frame */ - if (sctx->cache[pos]->keyframe && !sctx->cache[pos]->av_header) { - if (gacf->low_latency && pos != ssctx->gop_pos) { - ssctx->gop_pos = pos; - - ss->out_pos = ss->out_last; - - ngx_log_error(NGX_LOG_INFO, ss->log, 0, - "gop, low latency, chase to new keyframe"); - - if (sctx->latest_aac_header - && sctx->latest_aac_header != ssctx->latest_aac_header) - { - if (ngx_rtmp_gop_link_frame(ss, sctx->latest_aac_header) - == NGX_AGAIN) - { - return NGX_AGAIN; - } - } - - if (sctx->latest_avc_header - && sctx->latest_avc_header != ssctx->latest_avc_header) - { - if (ngx_rtmp_gop_link_frame(ss, sctx->latest_avc_header) - == NGX_AGAIN) - { - return NGX_AGAIN; - } - } - } - } else { - if (sctx->cache[ssctx->gop_pos] == NULL) { - ngx_log_error(NGX_LOG_ERR, ss->log, 0, - "gop, current gop pos is NULL, " - "skip to new postion [pos %d last %d] %d", - sctx->gop_pos, sctx->gop_last, ssctx->gop_pos); - - if (sctx->aac_header - && sctx->aac_header != ssctx->latest_aac_header) - { - if (ngx_rtmp_gop_link_frame(ss, sctx->aac_header) - == NGX_AGAIN) - { - return NGX_AGAIN; - } - } - - if (sctx->avc_header - && sctx->avc_header != ssctx->latest_avc_header) - { - if (ngx_rtmp_gop_link_frame(ss, sctx->avc_header) - == NGX_AGAIN) - { - return NGX_AGAIN; - } - } - - ssctx->gop_pos = sctx->gop_pos; - } - } - - frame = sctx->cache[ssctx->gop_pos]; - if (ngx_rtmp_gop_link_frame(ss, frame) == NGX_AGAIN) { - return NGX_AGAIN; - } - - ssctx->gop_pos = ngx_rtmp_gop_next(s, ssctx->gop_pos); - ngx_rtmp_send_message(ss, NULL, 0); - - return NGX_OK; -} - -static ngx_int_t -ngx_rtmp_gop_close_stream(ngx_rtmp_session_t *s, ngx_rtmp_close_stream_t *v) -{ - ngx_rtmp_gop_ctx_t *ctx; - ngx_rtmp_live_ctx_t *lctx; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_gop_module); - if (ctx == NULL) { - goto next; - } - - lctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_live_module); - - if (!lctx->publishing) { - goto next; - } - - if (ctx->avc_header) { - ngx_rtmp_shared_free_frame(ctx->avc_header); - } - - if (ctx->aac_header) { - ngx_rtmp_shared_free_frame(ctx->aac_header); - } - - /* free cache in publisher */ - while (ctx->gop_pos != ctx->gop_last) { - ngx_rtmp_shared_free_frame(ctx->cache[ctx->gop_pos]); - ctx->gop_pos = ngx_rtmp_gop_next(s, ctx->gop_pos); - } - -next: - return next_close_stream(s, v); -} - -static ngx_int_t -ngx_rtmp_gop_postconfiguration(ngx_conf_t *cf) -{ - next_close_stream = ngx_rtmp_close_stream; - ngx_rtmp_close_stream = ngx_rtmp_gop_close_stream; - - return NGX_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_handler.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_handler.c deleted file mode 100644 index 7503653262..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_handler.c +++ /dev/null @@ -1,948 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include -#include "ngx_rtmp.h" -#include "ngx_rtmp_amf.h" -#include "ngx_rbuf.h" -#include "ngx_poold.h" -#include "ngx_rtmp_monitor_module.h" - - -static void ngx_rtmp_recv(ngx_event_t *rev); -static void ngx_rtmp_send(ngx_event_t *rev); -static void ngx_rtmp_ping(ngx_event_t *rev); -static ngx_int_t ngx_rtmp_finalize_set_chunk_size(ngx_rtmp_session_t *s); - - -ngx_uint_t ngx_rtmp_naccepted; - - -ngx_rtmp_bandwidth_t ngx_rtmp_bw_out; -ngx_rtmp_bandwidth_t ngx_rtmp_bw_in; - - -#ifdef NGX_DEBUG -char* -ngx_rtmp_message_type(uint8_t type) -{ - static char* types[] = { - "?", - "chunk_size", - "abort", - "ack", - "user", - "ack_size", - "bandwidth", - "edge", - "audio", - "video", - "?", - "?", - "?", - "?", - "?", - "amf3_meta", - "amf3_shared", - "amf3_cmd", - "amf_meta", - "amf_shared", - "amf_cmd", - "?", - "aggregate" - }; - - return type < sizeof(types) / sizeof(types[0]) - ? types[type] - : "?"; -} - - -char* -ngx_rtmp_user_message_type(uint16_t evt) -{ - static char* evts[] = { - "stream_begin", - "stream_eof", - "stream dry", - "set_buflen", - "recorded", - "", - "ping_request", - "ping_response", - }; - - return evt < sizeof(evts) / sizeof(evts[0]) - ? evts[evt] - : "?"; -} -#endif - - -void -ngx_rtmp_cycle(ngx_rtmp_session_t *s) -{ - ngx_connection_t *c; - - c = s->connection; - c->read->handler = ngx_rtmp_recv; - c->write->handler = ngx_rtmp_send; - - s->ping_evt.data = c; - s->ping_evt.log = s->log; - s->ping_evt.handler = ngx_rtmp_ping; - ngx_rtmp_reset_ping(s); - - ngx_rtmp_recv(c->read); -} - - -static ngx_chain_t * -ngx_rtmp_alloc_in_buf(ngx_rtmp_session_t *s) -{ - ngx_chain_t *cl; - ngx_buf_t *b; - size_t size; - - if ((cl = ngx_alloc_chain_link(s->in_pool)) == NULL - || (cl->buf = ngx_calloc_buf(s->in_pool)) == NULL) - { - return NULL; - } - - cl->next = NULL; - b = cl->buf; - size = s->in_chunk_size + NGX_RTMP_MAX_CHUNK_HEADER; - - b->start = b->last = b->pos = ngx_palloc(s->in_pool, size); - if (b->start == NULL) { - return NULL; - } - b->end = b->start + size; - - return cl; -} - - -void -ngx_rtmp_reset_ping(ngx_rtmp_session_t *s) -{ - ngx_rtmp_core_srv_conf_t *cscf; - - cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module); - if (cscf->ping == 0) { - return; - } - - s->ping_active = 0; - s->ping_reset = 0; - ngx_add_timer(&s->ping_evt, cscf->ping); - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "ping: wait %Mms", cscf->ping); -} - - -static void -ngx_rtmp_ping(ngx_event_t *pev) -{ - ngx_connection_t *c; - ngx_rtmp_session_t *s; - ngx_rtmp_core_srv_conf_t *cscf; - - c = pev->data; - s = c->data; - - cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module); - - /* i/o event has happened; no need to ping */ - if (s->ping_reset) { - ngx_rtmp_reset_ping(s); - return; - } - - if (s->ping_active) { - ngx_log_error(NGX_LOG_INFO, s->log, 0, "ping: unresponded"); - ngx_rtmp_finalize_session(s); - return; - } - - if (cscf->busy) { - ngx_log_error(NGX_LOG_INFO, s->log, 0, "ping: not busy between pings"); - ngx_rtmp_finalize_session(s); - return; - } - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "ping: schedule %Mms", cscf->ping_timeout); - - if (ngx_rtmp_send_ping_request(s, (uint32_t)ngx_current_msec) != NGX_OK) { - ngx_rtmp_finalize_session(s); - return; - } - - s->ping_active = 1; - ngx_add_timer(pev, cscf->ping_timeout); -} - - -static void -ngx_rtmp_recv(ngx_event_t *rev) -{ - ngx_int_t n; - ngx_connection_t *c; - ngx_rtmp_session_t *s; - ngx_rtmp_core_srv_conf_t *cscf; - ngx_rtmp_header_t *h; - ngx_rtmp_stream_t *st, *st0; - ngx_chain_t *in, *head; - ngx_buf_t *b; - u_char *p, *pp, *old_pos; - size_t size, fsize, old_size; - uint8_t fmt, ext; - uint32_t csid, timestamp; - - c = rev->data; - s = c->data; - b = NULL; - old_pos = NULL; - old_size = 0; - cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module); - - if (c->destroyed) { - return; - } - - if (ngx_rtmp_core_main_conf->fast_reload && (ngx_exiting || ngx_terminate)) { - s->finalize_reason = NGX_LIVE_PROCESS_EXIT; - ngx_rtmp_finalize_session(s); - return; - } - - for( ;; ) { - - st = &s->in_streams[s->in_csid]; - - /* allocate new buffer */ - if (st->in == NULL) { - st->in = ngx_rtmp_alloc_in_buf(s); - if (st->in == NULL) { - ngx_log_error(NGX_LOG_INFO, s->log, 0, "in buf alloc failed"); - ngx_rtmp_finalize_session(s); - return; - } - } - - h = &st->hdr; - in = st->in; - b = in->buf; - - if (old_size) { - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "reusing formerly read data: %d", old_size); - - b->pos = b->start; - b->last = ngx_movemem(b->pos, old_pos, old_size); - - if (s->in_chunk_size_changing) { - ngx_rtmp_finalize_set_chunk_size(s); - } - - } else { - - if (old_pos) { - b->pos = b->last = b->start; - } - - n = c->recv(c, b->last, b->end - b->last); - - if (n == NGX_ERROR || n == 0) { - s->finalize_reason = n == 0? NGX_LIVE_NORMAL_CLOSE: - NGX_LIVE_RTMP_RECV_ERR; - ngx_rtmp_finalize_session(s); - return; - } - - if (n == NGX_AGAIN) { - if (ngx_handle_read_event(c->read, 0) != NGX_OK) { - ngx_rtmp_finalize_session(s); - } - return; - } - - s->ping_reset = 1; - ngx_rtmp_update_bandwidth(&ngx_rtmp_bw_in, n); - b->last += n; - s->in_bytes += n; - - if (s->in_bytes >= 0xf0000000) { - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->log, 0, - "resetting byte counter"); - s->in_bytes = 0; - s->in_last_ack = 0; - } - - if (s->ack_size && s->in_bytes - s->in_last_ack >= s->ack_size) { - - s->in_last_ack = s->in_bytes; - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "sending RTMP ACK(%uD)", s->in_bytes); - - if (ngx_rtmp_send_ack(s, s->in_bytes)) { - ngx_rtmp_finalize_session(s); - return; - } - } - } - - old_pos = NULL; - old_size = 0; - - /* parse headers */ - if (b->pos == b->start) { - p = b->pos; - - /* chunk basic header */ - fmt = (*p >> 6) & 0x03; - csid = *p++ & 0x3f; - - if (csid == 0) { - if (b->last - p < 1) - continue; - csid = 64; - csid += *(uint8_t*)p++; - - } else if (csid == 1) { - if (b->last - p < 2) - continue; - csid = 64; - csid += *(uint8_t*)p++; - csid += (uint32_t)256 * (*(uint8_t*)p++); - } - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->log, 0, - "RTMP bheader fmt=%d csid=%D", - (int)fmt, csid); - - if (csid >= (uint32_t)cscf->max_streams) { - ngx_log_error(NGX_LOG_INFO, s->log, 0, - "RTMP in chunk stream too big: %D >= %D", - csid, cscf->max_streams); - ngx_rtmp_finalize_session(s); - return; - } - - /* link orphan */ - if (s->in_csid == 0) { - - /* unlink from stream #0 */ - st->in = st->in->next; - - /* link to new stream */ - s->in_csid = csid; - st = &s->in_streams[csid]; - if (st->in == NULL) { - in->next = in; - } else { - in->next = st->in->next; - st->in->next = in; - } - st->in = in; - h = &st->hdr; - h->csid = csid; - } - - ext = st->ext; - timestamp = st->dtime; - if (fmt <= 2 ) { - if (b->last - p < 3) - continue; - /* timestamp: - * big-endian 3b -> little-endian 4b */ - pp = (u_char*)×tamp; - pp[2] = *p++; - pp[1] = *p++; - pp[0] = *p++; - pp[3] = 0; - - ext = (timestamp == 0x00ffffff); - - if (fmt <= 1) { - if (b->last - p < 4) - continue; - /* size: - * big-endian 3b -> little-endian 4b - * type: - * 1b -> 1b*/ - pp = (u_char*)&h->mlen; - pp[2] = *p++; - pp[1] = *p++; - pp[0] = *p++; - pp[3] = 0; - h->type = *(uint8_t*)p++; - - if (fmt == 0) { - if (b->last - p < 4) - continue; - /* stream: - * little-endian 4b -> little-endian 4b */ - pp = (u_char*)&h->msid; - pp[0] = *p++; - pp[1] = *p++; - pp[2] = *p++; - pp[3] = *p++; - } - } - } - - /* extended header */ - if (ext) { - if (b->last - p < 4) - continue; - pp = (u_char*)×tamp; - pp[3] = *p++; - pp[2] = *p++; - pp[1] = *p++; - pp[0] = *p++; - } - - if (st->len == 0) { - /* Messages with type=3 should - * never have ext timestamp field - * according to standard. - * However that's not always the case - * in real life */ - st->ext = (ext && cscf->publish_time_fix); - if (fmt) { - st->dtime = timestamp; - } else { - h->timestamp = timestamp; - st->dtime = 0; - } - } - - ngx_log_debug8(NGX_LOG_DEBUG_RTMP, s->log, 0, - "RTMP mheader fmt=%d %s (%d) " - "time=%uD+%uD mlen=%D len=%D msid=%D", - (int)fmt, ngx_rtmp_message_type(h->type), (int)h->type, - h->timestamp, st->dtime, h->mlen, st->len, h->msid); - - /* header done */ - b->pos = p; - - if (h->mlen > cscf->max_message) { - ngx_log_error(NGX_LOG_INFO, s->log, 0, - "too big message: %uz", cscf->max_message); - ngx_rtmp_finalize_session(s); - return; - } - } - - size = b->last - b->pos; - fsize = h->mlen - st->len; - - if (size < ngx_min(fsize, s->in_chunk_size)) - continue; - - /* buffer is ready */ - - if (fsize > s->in_chunk_size) { - /* collect fragmented chunks */ - st->len += s->in_chunk_size; - b->last = b->pos + s->in_chunk_size; - old_pos = b->last; - old_size = size - s->in_chunk_size; - - } else { - /* handle! */ - head = st->in->next; - st->in->next = NULL; - b->last = b->pos + fsize; - old_pos = b->last; - old_size = size - fsize; - st->len = 0; - h->timestamp += st->dtime; - - if (ngx_rtmp_receive_message(s, h, head) != NGX_OK) { - ngx_rtmp_finalize_session(s); - return; - } - - if (s->in_chunk_size_changing) { - /* copy old data to a new buffer */ - if (!old_size) { - ngx_rtmp_finalize_set_chunk_size(s); - } - - } else { - /* add used bufs to stream #0 */ - st0 = &s->in_streams[0]; - st->in->next = st0->in; - st0->in = head; - st->in = NULL; - } - } - - s->in_csid = 0; - } -} - - -static ngx_flag_t -ngx_rtmp_relative_timestamp(ngx_rtmp_session_t *s, ngx_rtmp_header_t *lh) -{ - return 0; -} - -static ngx_chain_t * -ngx_rtmp_prepare_out_chain(ngx_rtmp_session_t *s) -{ - ngx_rtmp_core_srv_conf_t *cscf; - ngx_rtmp_frame_t *frame; - ngx_chain_t *head, *l, **ll; - uint32_t mlen, timestamp, ext_timestamp; - uint8_t fmt, hsize, thsize; - static uint8_t hdrsize[] = { 12, 8, 4, 1 }; - ngx_flag_t relative; - ngx_rtmp_header_t lh; - u_char th[7], *p, *pp; - - cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module); - - frame = s->out[s->out_pos]; - head = NULL; - - if (frame->hdr.csid >= (uint32_t)cscf->max_streams) { - ngx_log_error(NGX_LOG_INFO, s->log, 0, - "RTMP out chunk stream too big: %D >= %D", - frame->hdr.csid, cscf->max_streams); - goto failed; - } - - mlen = 0; - fmt = 0; - relative = ngx_rtmp_relative_timestamp(s, &lh); - - for (l = frame->chain; l; l = l->next) { - mlen += ngx_buf_size(l->buf); - } - - if (relative && lh.csid && frame->hdr.msid == lh.msid) { - ++fmt; - if (frame->hdr.type == lh.type && mlen && mlen == lh.mlen) { - ++fmt; - if (frame->hdr.timestamp == lh.timestamp) { - ++fmt; - } - } - timestamp = frame->hdr.timestamp - lh.timestamp; - } else { - timestamp = frame->hdr.timestamp; - } - - hsize = hdrsize[fmt]; - - ngx_log_debug7(NGX_LOG_DEBUG_RTMP, s->log, 0, - "RTMP prep %s (%d) fmt=%d csid=%uD timestamp=%uD mlen=%uD msid=%uD", - ngx_rtmp_message_type(frame->hdr.type), (int)frame->hdr.type, - (int)fmt, frame->hdr.csid, timestamp, mlen, frame->hdr.msid); - - ext_timestamp = 0; - if (timestamp >= 0x00ffffff) { - ext_timestamp = timestamp; - timestamp = 0x00ffffff; - hsize += 4; - } - - if (frame->hdr.csid >= 64) { - ++hsize; - if (frame->hdr.csid >= 320) { - ++hsize; - } - } - - /* fill initial header */ - head = ngx_get_chainbuf(NGX_RTMP_MAX_CHUNK_HEADER, 1); - if (head == NULL) { - goto failed; - } - p = head->buf->pos; - - /* basic header */ - *p = (fmt << 6); - if (frame->hdr.csid >= 2 && frame->hdr.csid <= 63) { - *p++ |= (((uint8_t)frame->hdr.csid) & 0x3f); - } else if (frame->hdr.csid >= 64 && frame->hdr.csid < 320) { - ++p; - *p++ = (uint8_t)(frame->hdr.csid - 64); - } else { - *p++ |= 1; - *p++ = (uint8_t)(frame->hdr.csid - 64); - *p++ = (uint8_t)((frame->hdr.csid - 64) >> 8); - } - - /* create fmt3 header for successive fragments */ - thsize = p - head->buf->pos; - ngx_memcpy(th, head->buf->pos, thsize); - th[0] |= 0xc0; - - /* message header */ - if (fmt <= 2) { - pp = (u_char *)×tamp; - *p++ = pp[2]; - *p++ = pp[1]; - *p++ = pp[0]; - if (fmt <= 1) { - pp = (u_char *)&mlen; - *p++ = pp[2]; - *p++ = pp[1]; - *p++ = pp[0]; - *p++ = frame->hdr.type; - if (fmt == 0) { - pp = (u_char *)&frame->hdr.msid; - *p++ = pp[0]; - *p++ = pp[1]; - *p++ = pp[2]; - *p++ = pp[3]; - } - } - } - - /* extended timestamp */ - if (ext_timestamp) { - pp = (u_char *)&ext_timestamp; - *p++ = pp[3]; - *p++ = pp[2]; - *p++ = pp[1]; - *p++ = pp[0]; - - /* This CONTRADICTS the standard - * but that's the way flash client - * wants data to be encoded; - * ffmpeg complains */ - if (cscf->play_time_fix) { - ngx_memcpy(&th[thsize], p - 4, 4); - thsize += 4; - } - } - head->buf->last = p; - - /* append headers to successive fragments */ - ll = &head->next; - l = frame->chain; - while (l && l->buf->pos == l->buf->last) { - l = l->next; - } - if (l == NULL) { - return head; - } - - *ll = ngx_get_chainbuf(0, 0); - (*ll)->buf->pos = l->buf->pos; - (*ll)->buf->last = l->buf->last; - - for (l = l->next; l; l = l->next) { - /* chunk header */ - ll = &(*ll)->next; - *ll = ngx_get_chainbuf(NGX_RTMP_MAX_CHUNK_HEADER, 1); - (*ll)->buf->last = ngx_cpymem((*ll)->buf->last, th, thsize); - - /* payload */ - ll = &(*ll)->next; - *ll = ngx_get_chainbuf(0, 0); - (*ll)->buf->pos = l->buf->pos; - (*ll)->buf->last = l->buf->last; - } - - ngx_rtmp_monitor_frame(s, &frame->hdr, NULL, frame->av_header, 0); - - return head; - -failed: - ngx_put_chainbufs(head); - - ngx_rtmp_finalize_session(s); - return NULL; -} - -static void -ngx_rtmp_send(ngx_event_t *wev) -{ - ngx_connection_t *c; - ngx_rtmp_session_t *s; - ngx_int_t n; - ngx_chain_t *chain, *cl; - off_t sent; - - c = wev->data; - s = c->data; - - if (c->destroyed) { - return; - } - - if (wev->timedout) { - ngx_log_error(NGX_LOG_INFO, s->log, NGX_ETIMEDOUT, "client timed out"); - c->timedout = 1; - s->finalize_reason = NGX_LIVE_RTMP_SEND_TIMEOUT; - ngx_rtmp_finalize_session(s); - return; - } - - if (wev->timer_set) { - ngx_del_timer(wev); - } - - if (s->prepare_handler == NULL) { - s->prepare_handler = ngx_rtmp_prepare_out_chain; - } - - if (ngx_rtmp_core_main_conf->fast_reload && (ngx_exiting || ngx_terminate)) { - s->finalize_reason = NGX_LIVE_PROCESS_EXIT; - ngx_rtmp_finalize_session(s); - return; - } - - if (ngx_rtmp_prepare_merge_frame(s) == NGX_ERROR) { - ngx_rtmp_finalize_session(s); - return; - } - - while (s->out_chain) { - sent = c->sent; - - chain = c->send_chain(c, s->out_chain, 0); - - n = c->sent - sent; - - if (chain == NGX_CHAIN_ERROR) { /* NGX_ERROR */ - c->error = 1; - s->finalize_reason = NGX_LIVE_RTMP_SEND_ERR; - ngx_rtmp_finalize_session(s); - return; - } - - for (cl = s->out_chain; cl != chain;) { - s->out_chain = cl->next; - ngx_free_chain(s->pool, cl); - cl = s->out_chain; - } - - if (chain) { /* NGX_AGAIN */ - ngx_add_timer(c->write, s->timeout); - if (ngx_handle_write_event(c->write, 0) != NGX_OK) { - ngx_rtmp_finalize_session(s); - } - return; - } - - s->out_bytes += n; - s->ping_reset = 1; - ngx_rtmp_update_bandwidth(&ngx_rtmp_bw_out, n); - - if (ngx_rtmp_prepare_merge_frame(s) == NGX_ERROR) { - ngx_rtmp_finalize_session(s); - return; - } - } - - if (wev->active) { - ngx_del_event(wev, NGX_WRITE_EVENT, 0); - } - - ngx_event_process_posted((ngx_cycle_t *) ngx_cycle, &s->posted_dry_events); -} - - -ngx_int_t -ngx_rtmp_send_message(ngx_rtmp_session_t *s, ngx_rtmp_frame_t *out, - ngx_uint_t priority) -{ - ngx_uint_t nmsg; - - if (out == NULL) { - goto send; - } - - nmsg = (s->out_last - s->out_pos) % s->out_queue + 1; - - if (priority > 3) { - priority = 3; - } - - /* drop packet? - * Note we always leave 1 slot free */ - if (nmsg + priority * s->out_queue / 4 >= s->out_queue) { - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->log, 0, - "RTMP drop message bufs=%ui, priority=%ui", - nmsg, priority); - return NGX_AGAIN; - } - - s->out[s->out_last++] = out; - s->out_last %= s->out_queue; - - ngx_rtmp_shared_acquire_frame(out); - - ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->log, 0, - "RTMP send nmsg=%ui, priority=%ui #%ui", - nmsg, priority, s->out_last); - - if (priority && s->out_buffer && nmsg < s->out_cork) { - return NGX_OK; - } - -send: - if (!s->connection->write->active) { - ngx_post_event(s->connection->write, &ngx_posted_events); - } - - return NGX_OK; -} - - -ngx_int_t -ngx_rtmp_receive_message(ngx_rtmp_session_t *s, - ngx_rtmp_header_t *h, ngx_chain_t *in) -{ - ngx_rtmp_core_main_conf_t *cmcf; - ngx_array_t *evhs; - size_t n; - ngx_rtmp_handler_pt *evh; - - cmcf = ngx_rtmp_get_module_main_conf(s, ngx_rtmp_core_module); - -#ifdef NGX_DEBUG - { - int nbufs; - ngx_chain_t *ch; - - for(nbufs = 1, ch = in; - ch->next; - ch = ch->next, ++nbufs); - - ngx_log_debug7(NGX_LOG_DEBUG_RTMP, s->log, 0, - "RTMP recv %s (%d) csid=%D timestamp=%D " - "mlen=%D msid=%D nbufs=%d", - ngx_rtmp_message_type(h->type), (int)h->type, - h->csid, h->timestamp, h->mlen, h->msid, nbufs); - } -#endif - - if (h->type > NGX_RTMP_MSG_MAX) { - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "unexpected RTMP message type: %d", (int)h->type); - return NGX_OK; - } - - evhs = &cmcf->events[h->type]; - evh = evhs->elts; - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, "nhandlers: %d", evhs->nelts); - - for(n = 0; n < evhs->nelts; ++n, ++evh) { - if (!evh) { - continue; - } - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, "calling handler %d", n); - - switch ((*evh)(s, h, in)) { - case NGX_ERROR: - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "handler %d failed", n); - return NGX_ERROR; - case NGX_DONE: - return NGX_OK; - } - } - - return NGX_OK; -} - - -ngx_int_t -ngx_rtmp_set_chunk_size(ngx_rtmp_session_t *s, ngx_uint_t size) -{ - ngx_rtmp_core_srv_conf_t *cscf; - ngx_chain_t *li, *fli, *lo, *flo; - ngx_buf_t *bi, *bo; - ngx_int_t n; - - cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module); - - s->in_old_pool = s->in_pool; - s->in_chunk_size = size; - s->in_pool = NGX_CREATE_POOL(4096, ngx_cycle->log); - - /* copy existing chunk data */ - if (s->in_old_pool) { - s->in_chunk_size_changing = 1; - s->in_streams[0].in = NULL; - - for(n = 1; n < cscf->max_streams; ++n) { - /* stream buffer is circular - * for all streams except for the current one - * (which caused this chunk size change); - * we can simply ignore it */ - li = s->in_streams[n].in; - if (li == NULL || li->next == NULL) { - s->in_streams[n].in = NULL; - continue; - } - /* move from last to the first */ - li = li->next; - fli = li; - lo = ngx_rtmp_alloc_in_buf(s); - if (lo == NULL) { - return NGX_ERROR; - } - flo = lo; - for ( ;; ) { - bi = li->buf; - bo = lo->buf; - - if (bo->end - bo->last >= bi->last - bi->pos) { - bo->last = ngx_cpymem(bo->last, bi->pos, - bi->last - bi->pos); - li = li->next; - if (li == fli) { - lo->next = flo; - s->in_streams[n].in = lo; - break; - } - continue; - } - - bi->pos += (ngx_cpymem(bo->last, bi->pos, - bo->end - bo->last) - bo->last); - lo->next = ngx_rtmp_alloc_in_buf(s); - lo = lo->next; - if (lo == NULL) { - return NGX_ERROR; - } - } - } - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_finalize_set_chunk_size(ngx_rtmp_session_t *s) -{ - if (s->in_chunk_size_changing && s->in_old_pool) { - NGX_DESTROY_POOL(s->in_old_pool); - s->in_old_pool = NULL; - s->in_chunk_size_changing = 0; - } - return NGX_OK; -} - - diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_handshake.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_handshake.c deleted file mode 100644 index 352aa29f32..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_handshake.c +++ /dev/null @@ -1,641 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include -#include "ngx_rtmp.h" - -#include -#include - - -static void ngx_rtmp_handshake_send(ngx_event_t *wev); -static void ngx_rtmp_handshake_recv(ngx_event_t *rev); -static void ngx_rtmp_handshake_done(ngx_rtmp_session_t *s); - - -/* RTMP handshake : - * - * =peer1= =peer2= - * challenge ----> (.....[digest1]......) ----> 1537 bytes - * response <---- (...........[digest2]) <---- 1536 bytes - * - * - * - both packets contain random bytes except for digests - * - digest1 position is calculated on random packet bytes - * - digest2 is always at the end of the packet - * - * digest1: HMAC_SHA256(packet, peer1_partial_key) - * digest2: HMAC_SHA256(packet, HMAC_SHA256(digest1, peer2_full_key)) - */ - - -/* Handshake keys */ -static u_char -ngx_rtmp_server_key[] = { - 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ', - 'F', 'l', 'a', 's', 'h', ' ', 'M', 'e', 'd', 'i', 'a', ' ', - 'S', 'e', 'r', 'v', 'e', 'r', ' ', - '0', '0', '1', - - 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, - 0x02, 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, - 0x93, 0xB8, 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE -}; - - -static u_char -ngx_rtmp_client_key[] = { - 'G', 'e', 'n', 'u', 'i', 'n', 'e', ' ', 'A', 'd', 'o', 'b', 'e', ' ', - 'F', 'l', 'a', 's', 'h', ' ', 'P', 'l', 'a', 'y', 'e', 'r', ' ', - '0', '0', '1', - - 0xF0, 0xEE, 0xC2, 0x4A, 0x80, 0x68, 0xBE, 0xE8, 0x2E, 0x00, 0xD0, 0xD1, - 0x02, 0x9E, 0x7E, 0x57, 0x6E, 0xEC, 0x5D, 0x2D, 0x29, 0x80, 0x6F, 0xAB, - 0x93, 0xB8, 0xE6, 0x36, 0xCF, 0xEB, 0x31, 0xAE -}; - - -static const u_char -ngx_rtmp_server_version[4] = { - 0x0D, 0x0E, 0x0A, 0x0D -}; - - -static const u_char -ngx_rtmp_client_version[4] = { - 0x0C, 0x00, 0x0D, 0x0E -}; - - -#define NGX_RTMP_HANDSHAKE_KEYLEN SHA256_DIGEST_LENGTH -#define NGX_RTMP_HANDSHAKE_BUFSIZE 3073 -#define NGX_RTMP_HANDSHAKE_CHALLENGE_SIZE 1537 - - -#define NGX_RTMP_HANDSHAKE_SERVER_RECV_CHALLENGE 1 -#define NGX_RTMP_HANDSHAKE_SERVER_SEND_CHALLRESP 2 -#define NGX_RTMP_HANDSHAKE_SERVER_RECV_RESPONSE 3 -#define NGX_RTMP_HANDSHAKE_SERVER_DONE 4 - - -#define NGX_RTMP_HANDSHAKE_CLIENT_SEND_CHALLENGE 6 -#define NGX_RTMP_HANDSHAKE_CLIENT_RECV_CHALLENGE 7 -#define NGX_RTMP_HANDSHAKE_CLIENT_RECV_RESPONSE 8 -#define NGX_RTMP_HANDSHAKE_CLIENT_SEND_RESPONSE 9 -#define NGX_RTMP_HANDSHAKE_CLIENT_DONE 10 - - -static ngx_str_t ngx_rtmp_server_full_key - = { sizeof(ngx_rtmp_server_key), ngx_rtmp_server_key }; -static ngx_str_t ngx_rtmp_server_partial_key - = { 36, ngx_rtmp_server_key }; - -static ngx_str_t ngx_rtmp_client_full_key - = { sizeof(ngx_rtmp_client_key), ngx_rtmp_client_key }; -static ngx_str_t ngx_rtmp_client_partial_key - = { 30, ngx_rtmp_client_key }; - - -static ngx_int_t -ngx_rtmp_make_digest(ngx_str_t *key, ngx_buf_t *src, - u_char *skip, u_char *dst, ngx_log_t *log) -{ - static HMAC_CTX *hmac; - unsigned int len; - - if (hmac == NULL) { -#if OPENSSL_VERSION_NUMBER < 0x10100000L - static HMAC_CTX shmac; - hmac = &shmac; - HMAC_CTX_init(hmac); -#else - hmac = HMAC_CTX_new(); - if (hmac == NULL) { - return NGX_ERROR; - } -#endif - } - - HMAC_Init_ex(hmac, key->data, key->len, EVP_sha256(), NULL); - - if (skip && src->pos <= skip && skip <= src->last) { - if (skip != src->pos) { - HMAC_Update(hmac, src->pos, skip - src->pos); - } - if (src->last != skip + NGX_RTMP_HANDSHAKE_KEYLEN) { - HMAC_Update(hmac, skip + NGX_RTMP_HANDSHAKE_KEYLEN, - src->last - skip - NGX_RTMP_HANDSHAKE_KEYLEN); - } - } else { - HMAC_Update(hmac, src->pos, src->last - src->pos); - } - - HMAC_Final(hmac, dst, &len); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_find_digest(ngx_buf_t *b, ngx_str_t *key, size_t base, ngx_log_t *log) -{ - size_t n, offs; - u_char digest[NGX_RTMP_HANDSHAKE_KEYLEN]; - u_char *p; - - offs = 0; - for (n = 0; n < 4; ++n) { - offs += b->pos[base + n]; - } - offs = (offs % 728) + base + 4; - p = b->pos + offs; - - if (ngx_rtmp_make_digest(key, b, p, digest, log) != NGX_OK) { - return NGX_ERROR; - } - - if (ngx_memcmp(digest, p, NGX_RTMP_HANDSHAKE_KEYLEN) == 0) { - return offs; - } - - return NGX_ERROR; -} - - -static ngx_int_t -ngx_rtmp_write_digest(ngx_buf_t *b, ngx_str_t *key, size_t base, - ngx_log_t *log) -{ - size_t n, offs; - u_char *p; - - offs = 0; - for (n = 8; n < 12; ++n) { - offs += b->pos[base + n]; - } - offs = (offs % 728) + base + 12; - p = b->pos + offs; - - if (ngx_rtmp_make_digest(key, b, p, p, log) != NGX_OK) { - return NGX_ERROR; - } - - return NGX_OK; -} - - -static void -ngx_rtmp_fill_random_buffer(ngx_buf_t *b, u_char *end) -{ - for (; b->last != end; ++b->last) { - *b->last = (u_char) rand(); - } -} - - -static ngx_buf_t * -ngx_rtmp_alloc_handshake_buffer(ngx_rtmp_session_t *s) -{ - ngx_rtmp_core_srv_conf_t *cscf; - ngx_chain_t *cl; - ngx_buf_t *b; - - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->log, 0, - "handshake: allocating buffer"); - - cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module); - - if (cscf->free_hs) { - cl = cscf->free_hs; - b = cl->buf; - cscf->free_hs = cl->next; - ngx_free_chain(cscf->pool, cl); - - } else { - b = ngx_pcalloc(cscf->pool, sizeof(ngx_buf_t)); - if (b == NULL) { - return NULL; - } - b->memory = 1; - b->start = ngx_pcalloc(cscf->pool, NGX_RTMP_HANDSHAKE_BUFSIZE); - if (b->start == NULL) { - return NULL; - } - b->end = b->start + NGX_RTMP_HANDSHAKE_BUFSIZE; - } - - b->pos = b->last = b->start; - - return b; -} - - -void -ngx_rtmp_free_handshake_buffers(ngx_rtmp_session_t *s) -{ - ngx_rtmp_core_srv_conf_t *cscf; - ngx_chain_t *cl; - - if (s->hs_buf == NULL) { - return; - } - cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module); - cl = ngx_alloc_chain_link(cscf->pool); - if (cl == NULL) { - return; - } - cl->buf = s->hs_buf; - cl->next = cscf->free_hs; - cscf->free_hs = cl; - s->hs_buf = NULL; -} - - -static ngx_int_t -ngx_rtmp_handshake_create_challenge(ngx_rtmp_session_t *s, - const u_char version[4], ngx_str_t *key) -{ - ngx_buf_t *b; - u_char *end; - - b = s->hs_buf; - b->last = b->pos = b->start; - end = b->start + NGX_RTMP_HANDSHAKE_CHALLENGE_SIZE; - *b->last++ = '\x03'; - b->last = ngx_rtmp_rcpymem(b->last, &s->epoch, 4); - b->last = ngx_cpymem(b->last, version, 4); - ngx_rtmp_fill_random_buffer(b, end); - ++b->pos; - if (ngx_rtmp_write_digest(b, key, 0, s->log) != NGX_OK) { - return NGX_ERROR; - } - --b->pos; - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_handshake_parse_challenge(ngx_rtmp_session_t *s, - ngx_str_t *peer_key, ngx_str_t *key) -{ - ngx_buf_t *b; - u_char *p; - ngx_int_t offs; - - b = s->hs_buf; - if (*b->pos != '\x03') { - ngx_log_error(NGX_LOG_INFO, s->log, 0, - "handshake: unexpected RTMP version: %i", - (ngx_int_t)*b->pos); - return NGX_ERROR; - } - ++b->pos; - s->peer_epoch = 0; - ngx_rtmp_rmemcpy(&s->peer_epoch, b->pos, 4); - - p = b->pos + 4; - ngx_log_debug5(NGX_LOG_DEBUG_RTMP, s->log, 0, - "handshake: peer version=%i.%i.%i.%i epoch=%uD", - (ngx_int_t)p[3], (ngx_int_t)p[2], - (ngx_int_t)p[1], (ngx_int_t)p[0], - (uint32_t)s->peer_epoch); - if (*(uint32_t *)p == 0) { - s->hs_old = 1; - return NGX_OK; - } - - offs = ngx_rtmp_find_digest(b, peer_key, 772, s->log); - if (offs == NGX_ERROR) { - offs = ngx_rtmp_find_digest(b, peer_key, 8, s->log); - } - if (offs == NGX_ERROR) { - ngx_log_error(NGX_LOG_INFO, s->log, 0, "handshake: digest not found"); - s->hs_old = 1; - return NGX_OK; - } - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "handshake: digest found at pos=%i", offs); - b->pos += offs; - b->last = b->pos + NGX_RTMP_HANDSHAKE_KEYLEN; - s->hs_digest = ngx_palloc(s->pool, NGX_RTMP_HANDSHAKE_KEYLEN); - if (ngx_rtmp_make_digest(key, b, NULL, s->hs_digest, s->log) - != NGX_OK) - { - return NGX_ERROR; - } - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_handshake_create_response(ngx_rtmp_session_t *s) -{ - ngx_buf_t *b; - u_char *p, *pos; - ngx_str_t key; - - b = s->hs_buf; - pos = b->pos; - b->pos = b->start + NGX_RTMP_HANDSHAKE_CHALLENGE_SIZE; - ngx_rtmp_fill_random_buffer(b, b->end); - if (s->hs_digest) { - p = b->last - NGX_RTMP_HANDSHAKE_KEYLEN; - key.data = s->hs_digest; - key.len = NGX_RTMP_HANDSHAKE_KEYLEN; - if (ngx_rtmp_make_digest(&key, b, p, p, s->log) != NGX_OK) { - return NGX_ERROR; - } - } - b->pos = pos; - - return NGX_OK; -} - - -static void -ngx_rtmp_handshake_done(ngx_rtmp_session_t *s) -{ - ngx_rtmp_free_handshake_buffers(s); - - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->log, 0, - "handshake: done"); - - if (ngx_rtmp_fire_event(s, NGX_RTMP_HANDSHAKE_DONE, - NULL, NULL) != NGX_OK) - { - ngx_rtmp_finalize_session(s); - return; - } - - s->stage = NGX_LIVE_HANDSHAKE_DONE; - s->handshake_done_time = ngx_current_msec; - - ngx_rtmp_cycle(s); -} - - -static void -ngx_rtmp_handshake_recv(ngx_event_t *rev) -{ - ssize_t n; - ngx_connection_t *c; - ngx_rtmp_session_t *s; - ngx_buf_t *b; - - c = rev->data; - s = c->data; - - if (c->destroyed) { - return; - } - - if (rev->timedout) { - ngx_log_error(NGX_LOG_INFO, s->log, NGX_ETIMEDOUT, - "handshake: recv: client timed out"); - c->timedout = 1; - ngx_rtmp_finalize_session(s); - return; - } - - if (rev->timer_set) { - ngx_del_timer(rev); - } - - b = s->hs_buf; - - while (b->last != b->end) { - n = c->recv(c, b->last, b->end - b->last); - - if (n == NGX_ERROR || n == 0) { - ngx_rtmp_finalize_session(s); - return; - } - - if (n == NGX_AGAIN) { - ngx_add_timer(rev, s->timeout); - if (ngx_handle_read_event(c->read, 0) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "handshake: recv: handle read event error"); - ngx_rtmp_finalize_session(s); - } - return; - } - - b->last += n; - } - - if (rev->active) { - ngx_del_event(rev, NGX_READ_EVENT, 0); - } - - ++s->hs_stage; - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "handshake: stage %ui", s->hs_stage); - - switch (s->hs_stage) { - case NGX_RTMP_HANDSHAKE_SERVER_SEND_CHALLRESP: - if (ngx_rtmp_handshake_parse_challenge(s, - &ngx_rtmp_client_partial_key, - &ngx_rtmp_server_full_key) != NGX_OK) - { - ngx_log_error(NGX_LOG_INFO, s->log, 0, - "handshake: error parsing challenge"); - ngx_rtmp_finalize_session(s); - return; - } - - // create version and challege - if (ngx_rtmp_handshake_create_challenge(s, ngx_rtmp_server_version, - &ngx_rtmp_server_partial_key) != NGX_OK) - { - ngx_log_error(NGX_LOG_INFO, s->log, 0, - "handshake: error creating challenge"); - ngx_rtmp_finalize_session(s); - return; - } - - // create response - if (s->hs_old) { - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->log, 0, - "handshake: old-style response"); - s->hs_buf->last = s->hs_buf->end; - } else if (ngx_rtmp_handshake_create_response(s) != NGX_OK) { - ngx_log_error(NGX_LOG_INFO, s->log, 0, - "handshake: response error"); - ngx_rtmp_finalize_session(s); - return; - } - - ngx_rtmp_handshake_send(c->write); - break; - - case NGX_RTMP_HANDSHAKE_SERVER_DONE: - ngx_rtmp_handshake_done(s); - break; - - case NGX_RTMP_HANDSHAKE_CLIENT_RECV_RESPONSE: - if (ngx_rtmp_handshake_parse_challenge(s, - &ngx_rtmp_server_partial_key, - &ngx_rtmp_client_full_key) != NGX_OK) - { - ngx_log_error(NGX_LOG_INFO, s->log, 0, - "handshake: error parsing challenge"); - ngx_rtmp_finalize_session(s); - return; - } - s->hs_buf->pos = s->hs_buf->last = s->hs_buf->start - + NGX_RTMP_HANDSHAKE_CHALLENGE_SIZE; - ngx_rtmp_handshake_recv(c->read); - break; - - case NGX_RTMP_HANDSHAKE_CLIENT_SEND_RESPONSE: - if (ngx_rtmp_handshake_create_response(s) != NGX_OK) { - ngx_log_error(NGX_LOG_INFO, s->log, 0, - "handshake: response error"); - ngx_rtmp_finalize_session(s); - return; - } - ngx_rtmp_handshake_send(c->write); - break; - } -} - - -static void -ngx_rtmp_handshake_send(ngx_event_t *wev) -{ - ngx_int_t n; - ngx_connection_t *c; - ngx_rtmp_session_t *s; - ngx_buf_t *b; - - c = wev->data; - s = c->data; - - if (c->destroyed) { - return; - } - - if (wev->timedout) { - ngx_log_error(NGX_LOG_INFO, s->log, NGX_ETIMEDOUT, - "handshake: send: client timed out"); - c->timedout = 1; - ngx_rtmp_finalize_session(s); - return; - } - - if (wev->timer_set) { - ngx_del_timer(wev); - } - - b = s->hs_buf; - - while(b->pos != b->last) { - n = c->send(c, b->pos, b->last - b->pos); - - if (n == NGX_ERROR) { - ngx_rtmp_finalize_session(s); - return; - } - - if (n == NGX_AGAIN || n == 0) { - ngx_add_timer(c->write, s->timeout); - if (ngx_handle_write_event(c->write, 0) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "handshake: recv: handle write event error"); - ngx_rtmp_finalize_session(s); - } - return; - } - - b->pos += n; - } - - if (wev->active) { - ngx_del_event(wev, NGX_WRITE_EVENT, 0); - } - - ++s->hs_stage; - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "handshake: stage %ui", s->hs_stage); - - switch (s->hs_stage) { - - case NGX_RTMP_HANDSHAKE_SERVER_RECV_RESPONSE: - s->hs_buf->last = s->hs_buf->start - + NGX_RTMP_HANDSHAKE_CHALLENGE_SIZE; - ngx_rtmp_handshake_recv(c->read); - break; - - case NGX_RTMP_HANDSHAKE_CLIENT_RECV_CHALLENGE: - s->hs_buf->pos = s->hs_buf->last = s->hs_buf->end - - NGX_RTMP_HANDSHAKE_CHALLENGE_SIZE; - ngx_rtmp_handshake_recv(c->read); - break; - - case NGX_RTMP_HANDSHAKE_CLIENT_DONE: - ngx_rtmp_handshake_done(s); - break; - } -} - - -void -ngx_rtmp_handshake(ngx_rtmp_session_t *s) -{ - ngx_connection_t *c; - - c = s->connection; - c->read->handler = ngx_rtmp_handshake_recv; - c->write->handler = ngx_rtmp_handshake_send; - - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->log, 0, - "handshake: start server handshake"); - - s->hs_buf = ngx_rtmp_alloc_handshake_buffer(s); - s->hs_buf->pos = s->hs_buf->last = s->hs_buf->end - - NGX_RTMP_HANDSHAKE_CHALLENGE_SIZE; - s->hs_stage = NGX_RTMP_HANDSHAKE_SERVER_RECV_CHALLENGE; - - ngx_rtmp_handshake_recv(c->read); -} - - -void -ngx_rtmp_client_handshake(ngx_rtmp_session_t *s, unsigned async) -{ - ngx_connection_t *c; - - c = s->connection; - c->read->handler = ngx_rtmp_handshake_recv; - c->write->handler = ngx_rtmp_handshake_send; - - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->log, 0, - "handshake: start client handshake"); - - s->hs_buf = ngx_rtmp_alloc_handshake_buffer(s); - s->hs_stage = NGX_RTMP_HANDSHAKE_CLIENT_SEND_CHALLENGE; - - if (ngx_rtmp_handshake_create_challenge(s, - ngx_rtmp_client_version, - &ngx_rtmp_client_partial_key) != NGX_OK) - { - ngx_rtmp_finalize_session(s); - return; - } - - if (async) { - ngx_add_timer(c->write, s->timeout); - if (ngx_handle_write_event(c->write, 0) != NGX_OK) { - ngx_rtmp_finalize_session(s); - } - return; - } - - ngx_rtmp_handshake_send(c->write); -} - diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_init.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_init.c deleted file mode 100644 index ef4c519bf1..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_init.c +++ /dev/null @@ -1,787 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include -#include "ngx_rtmp.h" -#include "ngx_rtmp_cmd_module.h" -#include "ngx_live_relay.h" -#include "ngx_rtmp_proxy_protocol.h" -#include "ngx_http_client.h" -#include "ngx_rbuf.h" -#include "ngx_poold.h" - - -static void ngx_rtmp_close_connection(ngx_connection_t *c); -static u_char * ngx_rtmp_log_error(ngx_log_t *log, u_char *buf, size_t len); - - -typedef struct { - ngx_str_t *client; - ngx_rtmp_session_t *session; - void *data; // combined log - ngx_log_handler_pt handler; // combined log handler -} ngx_rtmp_error_log_ctx_t; - - -char *ngx_live_stage[] = { - "init", - "handshake_done", - "connect", - "create_stream", - "publish", - "play", - "audio_video", - "close_stream", -}; - - -char *ngx_live_err[] = { - "internal_err", - "normal_close", - "rtmp_send_err", - "rtmp_send_timeout", - "flv_send_err", - "flv_send_timeout", - "rtmp_recv_err", - "flv_recv_err", - "relay_transit", - "relay_timeout", - "control_drop", - "drop_idle", - "notify_notify_err", - "notify_relay_err", - "notify_para_err", - "relay_close", - "process_exit", -}; - - -void -ngx_rtmp_init_connection(ngx_connection_t *c) -{ - ngx_uint_t i; - ngx_rtmp_port_t *port; - struct sockaddr *sa; - struct sockaddr_in *sin; - ngx_rtmp_in_addr_t *addr; - ngx_rtmp_session_t *s; - ngx_rtmp_addr_conf_t *addr_conf; - ngx_int_t unix_socket; -#if (NGX_HAVE_INET6) - struct sockaddr_in6 *sin6; - ngx_rtmp_in6_addr_t *addr6; -#endif - - ++ngx_rtmp_naccepted; - - /* find the server configuration for the address:port */ - - /* AF_INET only */ - - port = c->listening->servers; - unix_socket = 0; - - if (port->naddrs > 1) { - - /* - * There are several addresses on this port and one of them - * is the "*:port" wildcard so getsockname() is needed to determine - * the server address. - * - * AcceptEx() already gave this address. - */ - - if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) { - ngx_rtmp_close_connection(c); - return; - } - - sa = c->local_sockaddr; - - switch (sa->sa_family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - sin6 = (struct sockaddr_in6 *) sa; - - addr6 = port->addrs; - - /* the last address is "*" */ - - for (i = 0; i < port->naddrs - 1; i++) { - if (ngx_memcmp(&addr6[i].addr6, &sin6->sin6_addr, 16) == 0) { - break; - } - } - - addr_conf = &addr6[i].conf; - - break; -#endif - - case AF_UNIX: - unix_socket = 1; - - sin = (struct sockaddr_in *) sa; - - addr = port->addrs; - - /* the last address is "*" */ - - for (i = 0; i < port->naddrs - 1; i++) { - if (addr[i].addr == sin->sin_addr.s_addr) { - break; - } - } - - addr_conf = &addr[i].conf; - - break; - - default: /* AF_INET */ - sin = (struct sockaddr_in *) sa; - - addr = port->addrs; - - /* the last address is "*" */ - - for (i = 0; i < port->naddrs - 1; i++) { - if (addr[i].addr == sin->sin_addr.s_addr) { - break; - } - } - - addr_conf = &addr[i].conf; - - break; - } - - } else { - switch (c->local_sockaddr->sa_family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - addr6 = port->addrs; - addr_conf = &addr6[0].conf; - break; -#endif - - case AF_UNIX: - unix_socket = 1; - addr = port->addrs; - addr_conf = &addr[0].conf; - break; - - default: /* AF_INET */ - addr = port->addrs; - addr_conf = &addr[0].conf; - break; - } - } - - ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%ui client connected '%V'", - c->number, &c->addr_text); - - s = ngx_rtmp_create_session(addr_conf); - if (s == NULL) { - ngx_log_error(NGX_LOG_INFO, c->log, 0, "create rtmp session failed"); - return; - } - s->log->connection = c->number; - s->number = c->number; - s->remote_addr_text.data = ngx_pcalloc(s->pool, c->addr_text.len); - s->remote_addr_text.len = c->addr_text.len; - ngx_memcpy(s->remote_addr_text.data, c->addr_text.data, c->addr_text.len); - s->sockaddr = ngx_pcalloc(s->pool, sizeof(struct sockaddr)); - ngx_memcpy(s->sockaddr, c->sockaddr, sizeof(struct sockaddr)); - - ngx_rtmp_init_session(s, c); - - /* only auto-pushed connections are - * done through unix socket */ - - s->interprocess = unix_socket; - - if (addr_conf->proxy_protocol) { - ngx_rtmp_proxy_protocol(s); - - } else { - ngx_rtmp_handshake(s); - } -} - - -static u_char * -ngx_rtmp_log_error(ngx_log_t *log, u_char *buf, size_t len) -{ - u_char *p; - ngx_rtmp_session_t *s; - ngx_rtmp_error_log_ctx_t *ctx; - - p = buf; - - ctx = log->data; - - if (ctx->client) { - p = ngx_snprintf(buf, len, ", client: %V", ctx->client); - len -= p - buf; - buf = p; - } - - s = ctx->session; - - if (s == NULL) { - return p; - } - - p = ngx_snprintf(buf, len, ", server: %V, session: %p", s->addr_text, s); - len -= p - buf; - buf = p; - - if (s->stream.len) { - p = ngx_snprintf(buf, len, ", stream: %V", &s->stream); - len -= p - buf; - buf = p; - } - - if (ctx->data) { // combined log - log->data = ctx->data; - p = ctx->handler(log, p, len); - log->data = ctx; - } - - return p; -} - - -static void -ngx_rtmp_close_connection(ngx_connection_t *c) -{ - ngx_pool_t *pool; - - if (c == NULL) { - return; - } - - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, c->log, 0, "close connection"); - -#if (NGX_STAT_STUB) - (void) ngx_atomic_fetch_add(ngx_stat_active, -1); -#endif - - pool = c->pool; - ngx_close_connection(c); - ngx_destroy_pool(pool); -} - - -static void -ngx_rtmp_close_session(ngx_rtmp_session_t *s) -{ - if (s->ping_evt.timer_set) { - ngx_del_timer(&s->ping_evt); - } - - if (s->in_old_pool) { - NGX_DESTROY_POOL(s->in_old_pool); - s->in_old_pool = NULL; - } - - if (s->in_pool) { - NGX_DESTROY_POOL(s->in_pool); - s->in_pool = NULL; - } - - if (s->live_type == NGX_HTTP_FLV_LIVE) { - ngx_put_chainbufs(s->in_streams[0].in); - } - - ngx_rtmp_free_handshake_buffers(s); - - ngx_rtmp_free_merge_frame(s); - - if (s->live_type == NGX_MPEGTS_LIVE) { - while (s->out_pos != s->out_last) { - ngx_rtmp_shared_free_mpegts_frame(s->mpegts_out[s->out_pos++]); - s->out_pos %= s->out_queue; - } - } else { - while (s->out_pos != s->out_last) { - ngx_rtmp_shared_free_frame(s->out[s->out_pos++]); - s->out_pos %= s->out_queue; - } - } - - if (s->pool) { - NGX_DESTROY_POOL(s->pool); - } -} - - -static void -ngx_rtmp_close_session_handler(ngx_event_t *e) -{ - ngx_rtmp_session_t *s; - ngx_connection_t *c; - - s = e->data; - c = s->connection; - if (c) { - c->destroyed = 1; - } - - ngx_log_error(NGX_LOG_INFO, s->log, 0, "async close session"); - - ngx_rtmp_fire_event(s, NGX_RTMP_DISCONNECT, NULL, NULL); - - // close connection before session, connection log use session log - // may cause memory error - ngx_rtmp_close_connection(c); - - ngx_rtmp_close_session(s); -} - - -static void -ngx_rtmp_async_finalize_http_client(ngx_event_t *ev) -{ - ngx_rtmp_session_t *s; - ngx_http_request_t *hcr; - - s = ev->data; - hcr = s->request; - - ngx_log_error(NGX_LOG_INFO, s->log, 0, "asyn finalize http client"); - - if (hcr) { - ngx_http_client_finalize_request(hcr, 1); - } -} - - -static void -ngx_rtmp_async_finalize_http_request(ngx_event_t *ev) -{ - ngx_rtmp_session_t *s; - ngx_http_request_t *r; - - s = ev->data; - r = s->request; - - ngx_log_error(NGX_LOG_INFO, s->log, 0, "asyn finalize http request"); - - if (!r) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, "Http request is null"); - return; - } - - if (r->header_sent) { - ngx_http_finalize_request(r, NGX_HTTP_CLIENT_CLOSED_REQUEST); - ngx_http_run_posted_requests(r->connection); - } else { - r->error_page = 1; - - if (s->status) { - ngx_http_finalize_request(r, s->status); - } else { - ngx_http_finalize_request(r, NGX_HTTP_SERVICE_UNAVAILABLE); - } - } -} - - -void -ngx_rtmp_finalize_session(ngx_rtmp_session_t *s) -{ - ngx_event_t *e; - ngx_connection_t *c; - - ngx_log_error(NGX_LOG_INFO, s->log, 0, "finalize session"); - - if (s->live_type == NGX_HLS_LIVE) { - ngx_rtmp_finalize_fake_session(s); - return; - } - - c = s->connection; - if (c && c->destroyed) { - return; - } - - if (s->finalized) { - ngx_log_error(NGX_LOG_WARN, s->log, 0, "The session has been finalized."); - return; - } - - s->finalized = 1; - - if (s->live_type != NGX_RTMP_LIVE) { - e = &s->close; - e->data = s; - if (s->relay) { - e->handler = ngx_rtmp_async_finalize_http_client; - } else { - e->handler = ngx_rtmp_async_finalize_http_request; - } - e->log = s->log; - - ngx_post_event(e, &ngx_posted_events); - - return; - } - - e = &s->close; - e->data = s; - e->handler = ngx_rtmp_close_session_handler; - e->log = s->log; - - ngx_post_event(e, &ngx_posted_events); -} - - -// session combined with http request or http client request -void -ngx_rtmp_finalize_fake_session(ngx_rtmp_session_t *s) -{ - ngx_log_error(NGX_LOG_INFO, s->log, 0, "finalize fake session"); - - - if (s->finalized) { - ngx_log_error(NGX_LOG_WARN, s->log, 0, "The fake session has been finalized."); - return; - } - - s->finalized = 1; - - ngx_rtmp_fire_event(s, NGX_RTMP_DISCONNECT, NULL, NULL); - - ngx_rtmp_close_session(s); -} - - -void -ngx_rtmp_set_combined_log(ngx_rtmp_session_t *s, void *d, ngx_log_handler_pt h) -{ - ngx_rtmp_error_log_ctx_t *ctx; - - ctx = s->log->data; - ctx->data = d; - ctx->handler = h; -} - - -// Only rtmp need to init session -void -ngx_rtmp_init_session(ngx_rtmp_session_t *s, ngx_connection_t *c) -{ - ngx_rtmp_error_log_ctx_t *ctx; - ngx_rtmp_core_main_conf_t *cmcf; - - cmcf = ngx_rtmp_get_module_main_conf(s, ngx_rtmp_core_module); - - c->data = s; - s->connection = c; - - c->log = s->log; - c->write->log = s->log; - c->read->log = s->log; - - ctx = s->log->data; - ctx->client = &c->addr_text; - - s->log->connection = c->number; - - c->log_error = NGX_ERROR_INFO; - - ngx_rtmp_set_chunk_size(s, NGX_RTMP_DEFAULT_CHUNK_SIZE); - - if (s->variables == NULL) { - s->variables = ngx_pcalloc(s->pool, cmcf->variables.nelts - * sizeof(ngx_http_variable_value_t)); - } - - if (s->variables == NULL) { - ngx_rtmp_finalize_session(s); - return; - } - - return; -} - - -ngx_rtmp_session_t * -ngx_rtmp_create_relay_session(ngx_rtmp_session_t *s, void *tag) -{ - ngx_rtmp_session_t *rs; - ngx_live_relay_ctx_t *rctx; - ngx_rtmp_core_main_conf_t *cmcf; - - rs = ngx_rtmp_create_session(s->addr_conf); - if (rs == NULL) { - return NULL; - } - - rs->relay = 1; - rs->main_conf = s->main_conf; - rs->srv_conf = s->srv_conf; - rs->app_conf = s->app_conf; - - // clone para from origin session -#define NGX_RTMP_RELAY_SESSION_COPY_PARA(para) \ - if (ngx_copy_str(rs->pool, &rs->para, &s->para) != NGX_OK) { \ - goto destroy; \ - } - - NGX_RTMP_RELAY_SESSION_COPY_PARA(stream); - - NGX_RTMP_RELAY_SESSION_COPY_PARA(name); - NGX_RTMP_RELAY_SESSION_COPY_PARA(pargs); - - NGX_RTMP_RELAY_SESSION_COPY_PARA(app); - NGX_RTMP_RELAY_SESSION_COPY_PARA(args); - NGX_RTMP_RELAY_SESSION_COPY_PARA(flashver); - NGX_RTMP_RELAY_SESSION_COPY_PARA(swf_url); - NGX_RTMP_RELAY_SESSION_COPY_PARA(tc_url); - NGX_RTMP_RELAY_SESSION_COPY_PARA(page_url); - - NGX_RTMP_RELAY_SESSION_COPY_PARA(serverid); -#undef NGX_RTMP_RELAY_SESSION_COPY_PARA - - rs->acodecs = s->acodecs; - rs->vcodecs = s->vcodecs; - - ngx_rtmp_cmd_middleware_init(rs); - - // create relay ctx - rctx = ngx_pcalloc(rs->pool, sizeof(ngx_live_relay_ctx_t)); - if (rctx == NULL) { - goto destroy; - } - rctx->domain = rs->domain; - rctx->app = rs->app; - rctx->args = rs->args; - rctx->name = rs->name; - rctx->pargs = rs->pargs; - - rctx->referer = rs->page_url; - rctx->user_agent = rs->flashver; - rctx->swf_url = rs->swf_url; - rctx->acodecs = rs->acodecs; - rctx->vcodecs = rs->vcodecs; - - rctx->tag = tag; - - ngx_rtmp_set_ctx(rs, rctx, ngx_live_relay_module); - - cmcf = ngx_rtmp_get_module_main_conf(rs, ngx_rtmp_core_module); - if (rs->variables == NULL) { - rs->variables = ngx_pcalloc(rs->pool, cmcf->variables.nelts - * sizeof(ngx_http_variable_value_t)); - } - - return rs; - -destroy: - ngx_rtmp_close_session(rs); - - return NULL; -} - - -ngx_rtmp_session_t * -ngx_rtmp_create_static_session(ngx_live_relay_t *relay, - ngx_rtmp_addr_conf_t *addr_conf, void *tag) -{ - ngx_rtmp_session_t *rs; - ngx_live_relay_ctx_t *rctx; - ngx_uint_t n; - ngx_rtmp_core_srv_conf_t *cscf; - ngx_rtmp_core_app_conf_t **cacfp; - - rs = ngx_rtmp_create_session(addr_conf); - if (rs == NULL) { - return NULL; - } - - rs->static_pull = 1; - rs->relay = 1; - - // clone para from origin session -#define NGX_RTMP_RELAY_SESSION_COPY_PARA(to, from) \ - if (ngx_copy_str(rs->pool, &rs->to, &relay->from) != NGX_OK) { \ - goto destroy; \ - } - - NGX_RTMP_RELAY_SESSION_COPY_PARA(app, app); - NGX_RTMP_RELAY_SESSION_COPY_PARA(name, name); - NGX_RTMP_RELAY_SESSION_COPY_PARA(pargs, pargs); - NGX_RTMP_RELAY_SESSION_COPY_PARA(page_url, referer); - NGX_RTMP_RELAY_SESSION_COPY_PARA(flashver, user_agent); - - NGX_RTMP_RELAY_SESSION_COPY_PARA(stream, stream); -#undef NGX_RTMP_RELAY_SESSION_COPY_PARA - - rs->tc_url.len = sizeof("rtmp://") - 1 + relay->domain.len - + sizeof("/") - 1 + relay->app.len; - rs->tc_url.data = ngx_pcalloc(rs->pool, rs->tc_url.len); - if (rs->tc_url.data == NULL) { - goto destroy; - } - ngx_snprintf(rs->tc_url.data, rs->tc_url.len, "rtmp://%V/%V", - &relay->domain, &relay->app); - - ngx_rtmp_cmd_middleware_init(rs); - - if (ngx_rtmp_set_virtual_server(rs, &rs->domain)) { - goto destroy; - } - cscf = ngx_rtmp_get_module_srv_conf(rs, ngx_rtmp_core_module); - - rs->live_server = ngx_live_create_server(&rs->serverid); - - cacfp = cscf->applications.elts; - for (n = 0; n < cscf->applications.nelts; ++n, ++cacfp) { - if ((*cacfp)->name.len == rs->app.len && - ngx_strncmp((*cacfp)->name.data, rs->app.data, rs->app.len) == 0) - { - /* found app! */ - rs->app_conf = (*cacfp)->app_conf; - break; - } - } - - if (rs->app_conf == NULL) { - - if (cscf->default_app == NULL || cscf->default_app->app_conf == NULL) { - ngx_log_error(NGX_LOG_ERR, rs->log, 0, - "static session: application not found: '%V'", &rs->app); - goto destroy; - } - - rs->app_conf = cscf->default_app->app_conf; - } - - // create relay ctx - rctx = ngx_pcalloc(rs->pool, sizeof(ngx_live_relay_ctx_t)); - if (rctx == NULL) { - goto destroy; - } - rctx->domain = rs->domain; - rctx->app = rs->app; - rctx->args = rs->args; - rctx->name = rs->name; - rctx->pargs = rs->pargs; - - rctx->referer = rs->page_url; - rctx->user_agent = rs->flashver; - rctx->swf_url = rs->swf_url; - rctx->acodecs = rs->acodecs; - rctx->vcodecs = rs->vcodecs; - - rctx->tag = tag; - - ngx_rtmp_set_ctx(rs, rctx, ngx_live_relay_module); - - return rs; - -destroy: - ngx_rtmp_close_session(rs); - - return NULL; -} - - -// if return NULL, memory must be error -ngx_rtmp_session_t * -ngx_rtmp_create_session(ngx_rtmp_addr_conf_t *addr_conf) -{ - ngx_rtmp_session_t *s; - ngx_rtmp_core_srv_conf_t *cscf; - ngx_pool_t *pool; - ngx_rtmp_error_log_ctx_t *ctx; - - pool = NGX_CREATE_POOL(4096, ngx_cycle->log); - if (pool == NULL) { - return NULL; - } - - s = ngx_pcalloc(pool, sizeof(ngx_rtmp_session_t) + - sizeof(ngx_rtmp_frame_t *) * ((ngx_rtmp_core_srv_conf_t *) - addr_conf->default_server->ctx-> srv_conf[ngx_rtmp_core_module - .ctx_index])->out_queue); - if (s == NULL) { - goto destroy; - } - s->pool = pool; - - s->addr_conf = addr_conf; - - s->main_conf = addr_conf->default_server->ctx->main_conf; - s->srv_conf = addr_conf->default_server->ctx->srv_conf; - - s->addr_text = ngx_pcalloc(s->pool, sizeof(ngx_str_t)); - s->addr_text->data = ngx_pcalloc(s->pool, addr_conf->addr_text.len); - s->addr_text->len = addr_conf->addr_text.len; - ngx_memcpy(s->addr_text->data, - addr_conf->addr_text.data, addr_conf->addr_text.len); - - s->ctx = ngx_pcalloc(pool, sizeof(void *) * ngx_rtmp_max_module); - if (s->ctx == NULL) { - goto destroy; - } - - cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module); - - s->out_queue = cscf->out_queue; - s->out_cork = cscf->out_cork; - s->in_streams = ngx_pcalloc(pool, sizeof(ngx_rtmp_stream_t) - * cscf->max_streams); - if (s->in_streams == NULL) { - goto destroy; - } - -#if (nginx_version >= 1007005) - ngx_queue_init(&s->posted_dry_events); -#endif - - s->epoch = ngx_current_msec; - s->timeout = cscf->timeout; - s->buflen = cscf->buflen; - - // init log - ctx = ngx_pcalloc(pool, sizeof(ngx_rtmp_error_log_ctx_t)); - if (ctx == NULL) { - goto destroy; - } - - ctx->session = s; - - s->log = ngx_pcalloc(pool, sizeof(ngx_log_t)); - if (s->pool == NULL) { - goto destroy; - } - *s->log = ngx_cycle->new_log; - - s->log->handler = ngx_rtmp_log_error; - s->log->data = ctx; - - s->stage = NGX_LIVE_INIT; - s->init_time = ngx_current_msec; - - s->mpegts_out = ngx_pcalloc(s->pool, sizeof(ngx_mpegts_frame_t *) * - ((ngx_rtmp_core_srv_conf_t *) addr_conf->default_server->ctx-> - srv_conf[ngx_rtmp_core_module.ctx_index])->out_queue); - - return s; - -destroy: - if (pool) { - NGX_DESTROY_POOL(pool); - } - - return NULL; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_limit_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_limit_module.c deleted file mode 100644 index dae814375d..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_limit_module.c +++ /dev/null @@ -1,205 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include -#include "ngx_rtmp.h" - - -typedef struct { - ngx_int_t max_conn; - ngx_shm_zone_t *shm_zone; -} ngx_rtmp_limit_main_conf_t; - - -static ngx_str_t shm_name = ngx_string("rtmp_limit"); - - -static ngx_int_t ngx_rtmp_limit_postconfiguration(ngx_conf_t *cf); -static void *ngx_rtmp_limit_create_main_conf(ngx_conf_t *cf); - - -static ngx_command_t ngx_rtmp_limit_commands[] = { - - { ngx_string("max_connections"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - NGX_RTMP_MAIN_CONF_OFFSET, - offsetof(ngx_rtmp_limit_main_conf_t, max_conn), - NULL }, - - ngx_null_command -}; - - -static ngx_rtmp_module_t ngx_rtmp_limit_module_ctx = { - NULL, /* preconfiguration */ - ngx_rtmp_limit_postconfiguration, /* postconfiguration */ - ngx_rtmp_limit_create_main_conf, /* create main configuration */ - NULL, /* init main configuration */ - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - NULL, /* create app configuration */ - NULL /* merge app configuration */ -}; - - -ngx_module_t ngx_rtmp_limit_module = { - NGX_MODULE_V1, - &ngx_rtmp_limit_module_ctx, /* module context */ - ngx_rtmp_limit_commands, /* module directives */ - NGX_RTMP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void * -ngx_rtmp_limit_create_main_conf(ngx_conf_t *cf) -{ - ngx_rtmp_limit_main_conf_t *lmcf; - - lmcf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_limit_main_conf_t)); - if (lmcf == NULL) { - return NULL; - } - - lmcf->max_conn = NGX_CONF_UNSET; - - return lmcf; -} - - -static ngx_int_t -ngx_rtmp_limit_connect(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - ngx_rtmp_limit_main_conf_t *lmcf; - ngx_slab_pool_t *shpool; - ngx_shm_zone_t *shm_zone; - uint32_t *nconn, n; - ngx_int_t rc; - - lmcf = ngx_rtmp_get_module_main_conf(s, ngx_rtmp_limit_module); - if (lmcf->max_conn == NGX_CONF_UNSET) { - return NGX_OK; - } - - shm_zone = lmcf->shm_zone; - shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; - nconn = shm_zone->data; - - ngx_shmtx_lock(&shpool->mutex); - n = ++*nconn; - ngx_shmtx_unlock(&shpool->mutex); - - rc = n > (ngx_uint_t) lmcf->max_conn ? NGX_ERROR : NGX_OK; - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "limit: inc conection counter: %uD", n); - - if (rc != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "limit: too many connections: %uD > %i", - n, lmcf->max_conn); - } - - return rc; -} - - -static ngx_int_t -ngx_rtmp_limit_disconnect(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - ngx_rtmp_limit_main_conf_t *lmcf; - ngx_slab_pool_t *shpool; - ngx_shm_zone_t *shm_zone; - uint32_t *nconn, n; - - lmcf = ngx_rtmp_get_module_main_conf(s, ngx_rtmp_limit_module); - if (lmcf->max_conn == NGX_CONF_UNSET) { - return NGX_OK; - } - - shm_zone = lmcf->shm_zone; - shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; - nconn = shm_zone->data; - - ngx_shmtx_lock(&shpool->mutex); - n = --*nconn; - ngx_shmtx_unlock(&shpool->mutex); - - (void) n; - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "limit: dec conection counter: %uD", n); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_limit_shm_init(ngx_shm_zone_t *shm_zone, void *data) -{ - ngx_slab_pool_t *shpool; - uint32_t *nconn; - - if (data) { - shm_zone->data = data; - return NGX_OK; - } - - shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; - - nconn = ngx_slab_alloc(shpool, 4); - if (nconn == NULL) { - return NGX_ERROR; - } - - *nconn = 0; - - shm_zone->data = nconn; - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_limit_postconfiguration(ngx_conf_t *cf) -{ - ngx_rtmp_core_main_conf_t *cmcf; - ngx_rtmp_limit_main_conf_t *lmcf; - ngx_rtmp_handler_pt *h; - - cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module); - - h = ngx_array_push(&cmcf->events[NGX_RTMP_CONNECT]); - *h = ngx_rtmp_limit_connect; - - h = ngx_array_push(&cmcf->events[NGX_RTMP_DISCONNECT]); - *h = ngx_rtmp_limit_disconnect; - - lmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_limit_module); - if (lmcf->max_conn == NGX_CONF_UNSET) { - return NGX_OK; - } - - lmcf->shm_zone = ngx_shared_memory_add(cf, &shm_name, ngx_pagesize * 2, - &ngx_rtmp_limit_module); - if (lmcf->shm_zone == NULL) { - return NGX_ERROR; - } - - lmcf->shm_zone->init = ngx_rtmp_limit_shm_init; - - return NGX_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_live_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_live_module.c deleted file mode 100644 index 502bc8e2d9..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_live_module.c +++ /dev/null @@ -1,1108 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include -#include "ngx_rtmp_live_module.h" -#include "ngx_rtmp_cmd_module.h" -#include "ngx_rtmp_codec_module.h" - - -static ngx_rtmp_publish_pt next_publish; -static ngx_rtmp_play_pt next_play; -static ngx_rtmp_close_stream_pt next_close_stream; -static ngx_rtmp_pause_pt next_pause; -static ngx_rtmp_stream_begin_pt next_stream_begin; -static ngx_rtmp_stream_eof_pt next_stream_eof; - - -static ngx_int_t ngx_rtmp_live_postconfiguration(ngx_conf_t *cf); -static void * ngx_rtmp_live_create_app_conf(ngx_conf_t *cf); -static char * ngx_rtmp_live_merge_app_conf(ngx_conf_t *cf, - void *parent, void *child); -static char *ngx_rtmp_live_set_msec_slot(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); -static void ngx_rtmp_live_start(ngx_rtmp_session_t *s); -static void ngx_rtmp_live_stop(ngx_rtmp_session_t *s); - - -static ngx_command_t ngx_rtmp_live_commands[] = { - - { ngx_string("live"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_live_app_conf_t, live), - NULL }, - - { ngx_string("buffer"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_live_app_conf_t, buflen), - NULL }, - - { ngx_string("sync"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_rtmp_live_set_msec_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_live_app_conf_t, sync), - NULL }, - - { ngx_string("interleave"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_live_app_conf_t, interleave), - NULL }, - - { ngx_string("wait_key"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_live_app_conf_t, wait_key), - NULL }, - - { ngx_string("wait_video"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_live_app_conf_t, wait_video), - NULL }, - - { ngx_string("publish_notify"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_live_app_conf_t, publish_notify), - NULL }, - - { ngx_string("play_restart"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_live_app_conf_t, play_restart), - NULL }, - - { ngx_string("idle_streams"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_live_app_conf_t, idle_streams), - NULL }, - - { ngx_string("drop_idle_publisher"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_rtmp_live_set_msec_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_live_app_conf_t, idle_timeout), - NULL }, - - ngx_null_command -}; - - -static ngx_rtmp_module_t ngx_rtmp_live_module_ctx = { - NULL, /* preconfiguration */ - ngx_rtmp_live_postconfiguration, /* postconfiguration */ - NULL, /* create main configuration */ - NULL, /* init main configuration */ - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - ngx_rtmp_live_create_app_conf, /* create app configuration */ - ngx_rtmp_live_merge_app_conf /* merge app configuration */ -}; - - -ngx_module_t ngx_rtmp_live_module = { - NGX_MODULE_V1, - &ngx_rtmp_live_module_ctx, /* module context */ - ngx_rtmp_live_commands, /* module directives */ - NGX_RTMP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void * -ngx_rtmp_live_create_app_conf(ngx_conf_t *cf) -{ - ngx_rtmp_live_app_conf_t *lacf; - - lacf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_live_app_conf_t)); - if (lacf == NULL) { - return NULL; - } - - lacf->live = NGX_CONF_UNSET; - lacf->buflen = NGX_CONF_UNSET_MSEC; - lacf->sync = NGX_CONF_UNSET_MSEC; - lacf->idle_timeout = NGX_CONF_UNSET_MSEC; - lacf->interleave = NGX_CONF_UNSET; - lacf->wait_key = NGX_CONF_UNSET; - lacf->wait_video = NGX_CONF_UNSET; - lacf->publish_notify = NGX_CONF_UNSET; - lacf->play_restart = NGX_CONF_UNSET; - lacf->idle_streams = NGX_CONF_UNSET; - - return lacf; -} - - -static char * -ngx_rtmp_live_merge_app_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_rtmp_live_app_conf_t *prev = parent; - ngx_rtmp_live_app_conf_t *conf = child; - - ngx_conf_merge_value(conf->live, prev->live, 0); - ngx_conf_merge_msec_value(conf->buflen, prev->buflen, 0); - ngx_conf_merge_msec_value(conf->sync, prev->sync, 300); - ngx_conf_merge_msec_value(conf->idle_timeout, prev->idle_timeout, 0); - ngx_conf_merge_value(conf->interleave, prev->interleave, 0); - ngx_conf_merge_value(conf->wait_key, prev->wait_key, 1); - ngx_conf_merge_value(conf->wait_video, prev->wait_video, 0); - ngx_conf_merge_value(conf->publish_notify, prev->publish_notify, 0); - ngx_conf_merge_value(conf->play_restart, prev->play_restart, 0); - ngx_conf_merge_value(conf->idle_streams, prev->idle_streams, 1); - - return NGX_CONF_OK; -} - - -static char * -ngx_rtmp_live_set_msec_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - char *p = conf; - ngx_str_t *value; - ngx_msec_t *msp; - - msp = (ngx_msec_t *) (p + cmd->offset); - - value = cf->args->elts; - - if (value[1].len == sizeof("off") - 1 && - ngx_strncasecmp(value[1].data, (u_char *) "off", value[1].len) == 0) - { - *msp = 0; - return NGX_CONF_OK; - } - - return ngx_conf_set_msec_slot(cf, cmd, conf); -} - - -static void -ngx_rtmp_live_idle(ngx_event_t *pev) -{ - ngx_connection_t *c; - ngx_rtmp_session_t *s; - - c = pev->data; - s = c->data; - - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "live: drop idle publisher"); - - s->finalize_reason = NGX_LIVE_DROP_IDLE; - ngx_rtmp_finalize_session(s); -} - - -static void -ngx_rtmp_live_set_status(ngx_rtmp_session_t *s, ngx_rtmp_frame_t *control, - ngx_rtmp_frame_t **status, size_t nstatus, - unsigned active) -{ - ngx_rtmp_live_app_conf_t *lacf; - ngx_rtmp_live_ctx_t *ctx, *pctx; - ngx_rtmp_frame_t **frame; - ngx_event_t *e; - size_t n; - - lacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_live_module); - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_live_module); - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "live: set active=%ui", active); - - if (ctx->active == active) { - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "live: unchanged active=%ui", active); - return; - } - - ctx->active = active; - - if (ctx->publishing) { - - /* publisher */ - - if (lacf->idle_timeout) { - e = &ctx->idle_evt; - - if (active && !ctx->idle_evt.timer_set) { - e->data = s->connection; - e->log = s->log; - e->handler = ngx_rtmp_live_idle; - - ngx_add_timer(e, lacf->idle_timeout); - - } else if (!active && ctx->idle_evt.timer_set) { - ngx_del_timer(e); - } - } - - ctx->stream->active = active; - - for (pctx = ctx->stream->ctx; pctx; pctx = pctx->next) { - if (pctx->publishing == 0) { - ngx_rtmp_live_set_status(pctx->session, control, status, - nstatus, active); - } - } - - return; - } - - /* subscriber */ - - if (control && ngx_rtmp_send_message(s, control, 0) != NGX_OK) { - ngx_rtmp_finalize_session(s); - return; - } - - if (!ctx->silent) { - frame = status; - - for (n = 0; n < nstatus; ++n, ++frame) { - if (*frame && ngx_rtmp_send_message(s, *frame, 0) != NGX_OK) { - ngx_rtmp_finalize_session(s); - return; - } - } - } - - ctx->cs[0].active = 0; - ctx->cs[0].dropped = 0; - - ctx->cs[1].active = 0; - ctx->cs[1].dropped = 0; -} - - -static void -ngx_rtmp_live_start(ngx_rtmp_session_t *s) -{ - ngx_rtmp_live_app_conf_t *lacf; - ngx_rtmp_frame_t *control; - ngx_rtmp_frame_t *status[3]; - size_t n, nstatus; - - if (s->live_type == NGX_HLS_LIVE) { - return; - } - - lacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_live_module); - - control = ngx_rtmp_create_stream_begin(s, NGX_RTMP_MSID); - - nstatus = 0; - - if (lacf->play_restart) { - status[nstatus++] = ngx_rtmp_create_status(s, "NetStream.Play.Start", - "status", "Start live"); - status[nstatus++] = ngx_rtmp_create_sample_access(s); - } - - if (lacf->publish_notify) { - status[nstatus++] = ngx_rtmp_create_status(s, - "NetStream.Play.PublishNotify", - "status", "Start publishing"); - } - - ngx_rtmp_live_set_status(s, control, status, nstatus, 1); - - if (control) { - ngx_rtmp_shared_free_frame(control); - } - - for (n = 0; n < nstatus; ++n) { - ngx_rtmp_shared_free_frame(status[n]); - } -} - - -static void -ngx_rtmp_live_stop(ngx_rtmp_session_t *s) -{ - ngx_rtmp_live_app_conf_t *lacf; - ngx_rtmp_frame_t *control; - ngx_rtmp_frame_t *status[3]; - size_t n, nstatus; - - lacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_live_module); - - control = ngx_rtmp_create_stream_eof(s, NGX_RTMP_MSID); - - nstatus = 0; - - if (lacf->play_restart) { - status[nstatus++] = ngx_rtmp_create_status(s, "NetStream.Play.Stop", - "status", "Stop live"); - } - - if (lacf->publish_notify) { - status[nstatus++] = ngx_rtmp_create_status(s, - "NetStream.Play.UnpublishNotify", - "status", "Stop publishing"); - } - - ngx_rtmp_live_set_status(s, control, status, nstatus, 0); - - if (control) { - ngx_rtmp_shared_free_frame(control); - } - - for (n = 0; n < nstatus; ++n) { - ngx_rtmp_shared_free_frame(status[n]); - } -} - - -static ngx_int_t -ngx_rtmp_live_stream_begin(ngx_rtmp_session_t *s, ngx_rtmp_stream_begin_t *v) -{ - ngx_rtmp_live_ctx_t *ctx; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_live_module); - - if (ctx == NULL || ctx->stream == NULL || !ctx->publishing) { - goto next; - } - - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->log, 0, - "live: stream_begin"); - - ngx_rtmp_live_start(s); - -next: - return next_stream_begin(s, v); -} - - -static ngx_int_t -ngx_rtmp_live_stream_eof(ngx_rtmp_session_t *s, ngx_rtmp_stream_eof_t *v) -{ - ngx_rtmp_live_ctx_t *ctx; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_live_module); - - if (ctx == NULL || ctx->stream == NULL || !ctx->publishing) { - goto next; - } - - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->log, 0, - "live: stream_eof"); - - ngx_rtmp_live_stop(s); - -next: - return next_stream_eof(s, v); -} - - -static void -ngx_rtmp_live_join(ngx_rtmp_session_t *s, u_char *name, unsigned publisher) -{ - ngx_rtmp_live_ctx_t *ctx; - ngx_live_stream_t *st; - ngx_rtmp_live_app_conf_t *lacf; - ngx_str_t pubpri; - - lacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_live_module); - if (lacf == NULL) { - return; - } - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_live_module); - if (ctx && ctx->stream) { - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->log, 0, - "live: already joined"); - return; - } - - if (ctx == NULL) { - ctx = ngx_palloc(s->pool, sizeof(ngx_rtmp_live_ctx_t)); - ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_live_module); - } - - ngx_memzero(ctx, sizeof(*ctx)); - - ctx->session = s; - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "live: join '%s'", name); - - st = s->live_stream; - - if (!(publisher || st->publish_ctx || lacf->idle_streams)) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "live: stream not found"); - - s->status = 404; - ngx_rtmp_send_status(s, "NetStream.Play.StreamNotFound", "error", - "No such stream"); - - ngx_rtmp_finalize_session(s); - - return; - } - - if (publisher) { - // set publish priority - if (s->relay) { // relay pull - ctx->pubpri = -1; - } else { - if (ngx_rtmp_arg(s, (u_char *) "pubpri", 6, &pubpri) == NGX_OK) { - ctx->pubpri = ngx_atoi(pubpri.data, pubpri.len); - if (ctx->pubpri == NGX_ERROR) { // invalid publish priority - ctx->pubpri = 0; - } - } - } - - // duplicate publish priority - if (ngx_map_find(&st->pubctx, (intptr_t) ctx->pubpri)) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "live: already publishing"); - - ngx_rtmp_send_status(s, "NetStream.Publish.BadName", "error", - "Already publishing"); - - return; - } - - ctx->node.raw_key = (intptr_t) ctx->pubpri; - ngx_map_insert(&st->pubctx, &ctx->node, 0); - - st->publishing = 1; - } - - ctx->stream = st; - ctx->publishing = publisher; - ctx->next = st->ctx; - - st->ctx = ctx; - - if (lacf->buflen) { - s->out_buffer = 1; - } - - ctx->cs[0].csid = NGX_RTMP_CSID_VIDEO; - ctx->cs[1].csid = NGX_RTMP_CSID_AUDIO; - - if (!ctx->publishing && ctx->stream->active) { - ngx_rtmp_live_start(s); - } -} - - -static ngx_int_t -ngx_rtmp_live_close_stream(ngx_rtmp_session_t *s, ngx_rtmp_close_stream_t *v) -{ - ngx_rtmp_session_t *ss; - ngx_rtmp_live_ctx_t *ctx, **cctx, *pctx; - ngx_rtmp_live_app_conf_t *lacf; - - lacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_live_module); - if (lacf == NULL) { - goto next; - } - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_live_module); - if (ctx == NULL) { - goto next; - } - - if (ctx->stream == NULL) { - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->log, 0, - "live: not joined"); - goto next; - } - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "live: leave '%s'", ctx->stream->name); - - if (s->publishing) { - ngx_map_delete(&s->live_stream->pubctx, (intptr_t) ctx->pubpri); - } - - if (ctx->stream->publishing && ctx->publishing) { - ctx->stream->publishing = 0; - } - - for (cctx = &ctx->stream->ctx; *cctx; cctx = &(*cctx)->next) { - if (*cctx == ctx) { - *cctx = ctx->next; - break; - } - } - - if (ctx->publishing || ctx->stream->active) { - ngx_rtmp_live_stop(s); - } - - if (ctx->publishing) { - ngx_rtmp_send_status(s, "NetStream.Unpublish.Success", - "status", "Stop publishing"); - if (!lacf->idle_streams) { - for (pctx = ctx->stream->ctx; pctx; pctx = pctx->next) { - if (pctx->publishing == 0) { - ss = pctx->session; - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, ss->log, 0, - "live: no publisher"); - ngx_rtmp_finalize_session(ss); - } - } - } - } - - if (ctx->stream->ctx) { - ctx->stream = NULL; - goto next; - } - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "live: delete empty stream '%s'", - ctx->stream->name); - - ctx->stream = NULL; - - if (!ctx->silent && !ctx->publishing && !lacf->play_restart) { - ngx_rtmp_send_status(s, "NetStream.Play.Stop", "status", "Stop live"); - } - -next: - return next_close_stream(s, v); -} - - -static ngx_int_t -ngx_rtmp_live_pause(ngx_rtmp_session_t *s, ngx_rtmp_pause_t *v) -{ - ngx_rtmp_live_ctx_t *ctx; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_live_module); - - if (ctx == NULL || ctx->stream == NULL) { - goto next; - } - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->log, 0, - "live: pause=%i timestamp=%f", - (ngx_int_t) v->pause, v->position); - - if (v->pause) { - if (ngx_rtmp_send_status(s, "NetStream.Pause.Notify", "status", - "Paused live") - != NGX_OK) - { - return NGX_ERROR; - } - - ctx->paused = 1; - - ngx_rtmp_live_stop(s); - - } else { - if (ngx_rtmp_send_status(s, "NetStream.Unpause.Notify", "status", - "Unpaused live") - != NGX_OK) - { - return NGX_ERROR; - } - - ctx->paused = 0; - - ngx_rtmp_live_start(s); - } - -next: - return next_pause(s, v); -} - -static ngx_int_t -ngx_rtmp_live_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - ngx_rtmp_live_ctx_t *ctx, *pctx; - ngx_rtmp_codec_ctx_t *codec_ctx; - ngx_rtmp_frame_t *header, *coheader, *meta, *avframe, *dummy; - ngx_rtmp_core_srv_conf_t *cscf; - ngx_rtmp_live_app_conf_t *lacf; - ngx_rtmp_session_t *ss; - ngx_rtmp_header_t ch, lh, clh; - ngx_int_t rc, mandatory, dummy_audio; - ngx_uint_t prio; - ngx_uint_t peers; - ngx_uint_t meta_version; - ngx_uint_t csidx; - uint32_t delta; - ngx_rtmp_live_chunk_stream_t *cs; - u_char frametype; - -#define MSG_TYPE (h->type == NGX_RTMP_MSG_VIDEO ? "video" : "audio") - - lacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_live_module); - if (lacf == NULL) { - return NGX_ERROR; - } - - if (!lacf->live || in == NULL || in->buf == NULL || s->pause == 1) { - return NGX_OK; - } - - codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - - if (s->pause == 2) { - if ((codec_ctx && codec_ctx->video_codec_id == 0) || - (h->type == NGX_RTMP_MSG_VIDEO && - ngx_rtmp_get_video_frame_type(in) == NGX_RTMP_VIDEO_KEY_FRAME)) - { - s->pause = 0; - } else { - return NGX_OK; - } - } - - if (h->type == NGX_RTMP_MSG_VIDEO) { - frametype = in->buf->pos[0] & 0xf0; - if (frametype != 0x10 && frametype != 0x20) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "codec: receive unkwnon frametype %02xD", frametype); - return NGX_OK; - } - } - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_live_module); - if (ctx == NULL || ctx->stream == NULL) { - return NGX_OK; - } - - if (ctx->publishing == 0) { - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "live: %s from non-publisher", MSG_TYPE); - return NGX_OK; - } - - if (!ctx->stream->active) { - ngx_rtmp_live_start(s); - } - - if (ctx->idle_evt.timer_set) { - ngx_add_timer(&ctx->idle_evt, lacf->idle_timeout); - } - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->log, 0, - "live: %s packet timestamp=%uD", - MSG_TYPE, h->timestamp); - - s->current_time = h->timestamp; - - peers = 0; - header = NULL; - coheader = NULL; - meta = NULL; - dummy = NULL; - meta_version = 0; - mandatory = 0; - - prio = (h->type == NGX_RTMP_MSG_VIDEO ? - ngx_rtmp_get_video_frame_type(in) : 0); - - cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module); - - csidx = !(lacf->interleave || h->type == NGX_RTMP_MSG_VIDEO); - - cs = &ctx->cs[csidx]; - - ngx_memzero(&ch, sizeof(ch)); - - ch.timestamp = h->timestamp; - ch.msid = NGX_RTMP_MSID; - ch.csid = cs->csid; - ch.type = h->type; - ch.mlen = h->mlen; - - lh = ch; - - if (cs->active) { - lh.timestamp = cs->timestamp; - } - - clh = lh; - clh.type = (h->type == NGX_RTMP_MSG_AUDIO ? NGX_RTMP_MSG_VIDEO : - NGX_RTMP_MSG_AUDIO); - - cs->active = 1; - cs->timestamp = ch.timestamp; - - delta = ch.timestamp - lh.timestamp; -/* - if (delta >> 31) { - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->log, 0, - "live: clipping non-monotonical timestamp %uD->%uD", - lh.timestamp, ch.timestamp); - - delta = 0; - - ch.timestamp = lh.timestamp; - } -*/ - avframe = ngx_rtmp_shared_alloc_frame(cscf->chunk_size, in, 0); - avframe->hdr = ch; - - if (codec_ctx) { - - if (h->type == NGX_RTMP_MSG_AUDIO) { - header = codec_ctx->aac_header; - - if (lacf->interleave) { - coheader = codec_ctx->avc_header; - } - - if (codec_ctx->audio_codec_id == NGX_RTMP_AUDIO_AAC && - ngx_rtmp_is_codec_header(in)) - { - prio = 0; - mandatory = 1; - } - - } else { - header = codec_ctx->avc_header; - - if (lacf->interleave) { - coheader = codec_ctx->aac_header; - } - - if (codec_ctx->video_codec_id == NGX_RTMP_VIDEO_H264 && - ngx_rtmp_is_codec_header(in)) - { - prio = 0; - mandatory = 1; - } - } - - if (codec_ctx->meta) { - meta = codec_ctx->meta; - meta_version = codec_ctx->meta_version; - } - } - - if (ngx_rtmp_gop_cache(s, avframe) == NGX_ERROR) { - return NGX_ERROR; - } - - /* broadcast to all subscribers */ - - for (pctx = ctx->stream->ctx; pctx; pctx = pctx->next) { - // not the highest priority - if (ngx_map_rbegin(&ctx->stream->pubctx) != &ctx->node) { - break; - } - - // do not send to publish session - if (pctx->publishing || pctx->paused || s->pause) { - continue; - } - - ss = pctx->session; - cs = &pctx->cs[csidx]; - - if (ss->live_type == NGX_MPEGTS_LIVE || ss->live_type == NGX_HLS_LIVE) { - continue; - } - - /* send gop cache is set */ - switch (ngx_rtmp_gop_send(s, ss)) { - case NGX_DECLINED: - break; - case NGX_ERROR: - ngx_rtmp_finalize_session(ss); - continue; - default: - peers++; - continue; - } - - /* send metadata */ - - if (meta && meta_version != pctx->meta_version) { - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, ss->log, 0, - "live: meta"); - - if (ngx_rtmp_send_message(ss, meta, 0) == NGX_OK) { - pctx->meta_version = meta_version; - } - } - - /* sync stream */ - - if (cs->active && (lacf->sync && cs->dropped > lacf->sync)) { - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, ss->log, 0, - "live: sync %s dropped=%uD", MSG_TYPE, cs->dropped); - - cs->active = 0; - cs->dropped = 0; - } - - /* absolute packet */ - - if (!cs->active) { - - if (mandatory) { - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, ss->log, 0, - "live: skipping header"); - continue; - } - - if (lacf->wait_video && h->type == NGX_RTMP_MSG_AUDIO && - !pctx->cs[0].active) - { - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, ss->log, 0, - "live: waiting for video"); - continue; - } - - if (lacf->wait_key && prio != NGX_RTMP_VIDEO_KEY_FRAME && - (lacf->interleave || h->type == NGX_RTMP_MSG_VIDEO)) - { - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, ss->log, 0, - "live: skip non-key"); - continue; - } - - dummy_audio = 0; - if (lacf->wait_video && h->type == NGX_RTMP_MSG_VIDEO && - !pctx->cs[1].active) - { - dummy_audio = 1; - if (dummy == NULL) { - dummy = ngx_rtmp_shared_alloc_frame(cscf->chunk_size, - NULL, 1); - dummy->hdr = clh; - } - } - - if (header || coheader) { - - /* send absolute codec header */ - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, ss->log, 0, - "live: abs %s header timestamp=%uD", - MSG_TYPE, lh.timestamp); - - if (header) { - header->hdr = lh; - rc = ngx_rtmp_send_message(ss, header, 0); - if (rc != NGX_OK) { - continue; - } - } - - if (coheader) { - coheader->hdr = clh; - rc = ngx_rtmp_send_message(ss, coheader, 0); - if (rc != NGX_OK) { - continue; - } - - } else if (dummy_audio) { - ngx_rtmp_send_message(ss, dummy, 0); - } - - cs->timestamp = lh.timestamp; - cs->active = 1; - ss->current_time = cs->timestamp; - - } - } - - /* send av packet */ - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, ss->log, 0, - "live: rel %s packet delta=%uD", - MSG_TYPE, delta); - - if (ngx_rtmp_send_message(ss, avframe, prio) != NGX_OK) { - ++pctx->ndropped; - - cs->dropped += delta; - - if (mandatory) { - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, ss->log, 0, - "live: mandatory packet failed"); - ngx_rtmp_finalize_session(ss); - } - - continue; - } - - cs->timestamp += delta; - ++peers; - ss->current_time = cs->timestamp; - } - - if (avframe) { - ngx_rtmp_shared_free_frame(avframe); - } - - if (dummy) { - ngx_rtmp_shared_free_frame(dummy); - } - - ngx_rtmp_update_bandwidth(&ctx->stream->bw_in, h->mlen); - ngx_rtmp_update_bandwidth(&ctx->stream->bw_out, h->mlen * peers); - - ngx_rtmp_update_bandwidth(h->type == NGX_RTMP_MSG_AUDIO ? - &ctx->stream->bw_in_audio : - &ctx->stream->bw_in_video, - h->mlen); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_live_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v) -{ - ngx_rtmp_live_app_conf_t *lacf; - ngx_rtmp_live_ctx_t *ctx; - - lacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_live_module); - - if (lacf == NULL || !lacf->live) { - goto next; - } - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->log, 0, - "live: publish: name='%s' type='%s'", - v->name, v->type); - - /* join stream as publisher */ - - ngx_rtmp_live_join(s, v->name, 1); - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_live_module); - if (ctx == NULL || !ctx->publishing) { - goto next; - } - - ctx->silent = v->silent; - - if (!ctx->silent) { - ngx_rtmp_send_status(s, "NetStream.Publish.Start", - "status", "Start publishing"); - } - -next: - return next_publish(s, v); -} - - -static ngx_int_t -ngx_rtmp_live_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v) -{ - ngx_rtmp_live_app_conf_t *lacf; - ngx_rtmp_live_ctx_t *ctx; - ngx_rtmp_session_t *ps; - - lacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_live_module); - - if (lacf == NULL || !lacf->live || - s->live_type == NGX_HLS_LIVE || s->live_type == NGX_MPEGTS_LIVE) - { - goto next; - } - - ngx_log_debug4(NGX_LOG_DEBUG_RTMP, s->log, 0, - "live: play: name='%s' start=%uD duration=%uD reset=%d", - v->name, (uint32_t) v->start, - (uint32_t) v->duration, (uint32_t) v->reset); - - /* join stream as subscriber */ - - ngx_rtmp_live_join(s, v->name, 0); - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_live_module); - if (ctx == NULL) { - goto next; - } - - ctx->silent = v->silent; - - if (!ctx->silent && !lacf->play_restart) { - ngx_rtmp_send_status(s, "NetStream.Play.Start", - "status", "Start live"); - ngx_rtmp_send_sample_access(s); - } - - if (s->live_stream->publish_ctx && s->live_stream->publish_ctx->session) { - ps = s->live_stream->publish_ctx->session; - ngx_rtmp_gop_send(ps, s); - } - -next: - return next_play(s, v); -} - - -static ngx_int_t -ngx_rtmp_live_postconfiguration(ngx_conf_t *cf) -{ - ngx_rtmp_core_main_conf_t *cmcf; - ngx_rtmp_handler_pt *h; - - cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module); - - /* register raw event handlers */ - - h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_AUDIO]); - *h = ngx_rtmp_live_av; - - h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_VIDEO]); - *h = ngx_rtmp_live_av; - - /* chain handlers */ - - next_publish = ngx_rtmp_publish; - ngx_rtmp_publish = ngx_rtmp_live_publish; - - next_play = ngx_rtmp_play; - ngx_rtmp_play = ngx_rtmp_live_play; - - next_close_stream = ngx_rtmp_close_stream; - ngx_rtmp_close_stream = ngx_rtmp_live_close_stream; - - next_pause = ngx_rtmp_pause; - ngx_rtmp_pause = ngx_rtmp_live_pause; - - next_stream_begin = ngx_rtmp_stream_begin; - ngx_rtmp_stream_begin = ngx_rtmp_live_stream_begin; - - next_stream_eof = ngx_rtmp_stream_eof; - ngx_rtmp_stream_eof = ngx_rtmp_live_stream_eof; - - return NGX_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_live_module.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_live_module.h deleted file mode 100644 index cd9896ae5a..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_live_module.h +++ /dev/null @@ -1,66 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#ifndef _NGX_RTMP_LIVE_H_INCLUDED_ -#define _NGX_RTMP_LIVE_H_INCLUDED_ - - -#include -#include -#include "ngx_rtmp.h" -#include "ngx_rtmp_cmd_module.h" -#include "ngx_rtmp_bandwidth.h" -#include "ngx_rtmp_streams.h" -#include "ngx_map.h" - - -typedef struct { - unsigned active:1; - uint32_t timestamp; - uint32_t last_timestamp; - uint32_t csid; - uint32_t dropped; -} ngx_rtmp_live_chunk_stream_t; - - -struct ngx_rtmp_live_ctx_s { - ngx_map_node_t node; - ngx_int_t pubpri; - ngx_rtmp_session_t *session; - ngx_live_stream_t *stream; - ngx_rtmp_live_ctx_t *next; - ngx_uint_t ndropped; - ngx_rtmp_live_chunk_stream_t cs[2]; - ngx_uint_t meta_version; - ngx_event_t idle_evt; - unsigned active:1; - unsigned publishing:1; - unsigned silent:1; - unsigned paused:1; -}; - - -typedef struct { - ngx_flag_t live; - ngx_flag_t meta; - ngx_msec_t sync; - ngx_msec_t idle_timeout; - ngx_flag_t atc; - ngx_flag_t interleave; - ngx_flag_t wait_key; - ngx_flag_t wait_video; - ngx_flag_t publish_notify; - ngx_flag_t play_restart; - ngx_flag_t idle_streams; - ngx_flag_t fix_timestamp; - ngx_msec_t buflen; -} ngx_rtmp_live_app_conf_t; - - -extern ngx_module_t ngx_rtmp_live_module; - - -#endif /* _NGX_RTMP_LIVE_H_INCLUDED_ */ diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_log_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_log_module.c deleted file mode 100644 index 80c978fc39..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_log_module.c +++ /dev/null @@ -1,1350 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include -#include "ngx_rtmp_cmd_module.h" -#include "ngx_rtmp_codec_module.h" - - -static ngx_rtmp_publish_pt next_publish; -static ngx_rtmp_play_pt next_play; - - -static ngx_int_t ngx_rtmp_log_postconfiguration(ngx_conf_t *cf); -static void *ngx_rtmp_log_create_main_conf(ngx_conf_t *cf); -static void * ngx_rtmp_log_create_app_conf(ngx_conf_t *cf); -static char * ngx_rtmp_log_merge_app_conf(ngx_conf_t *cf, - void *parent, void *child); -static char * ngx_rtmp_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); -static char * ngx_rtmp_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); -static char * ngx_rtmp_log_compile_format(ngx_conf_t *cf, ngx_array_t *ops, - ngx_array_t *args, ngx_uint_t s); - - -typedef struct ngx_rtmp_log_op_s ngx_rtmp_log_op_t; - -#define MAX_ACCESS_LOG_LINE_LEN 4096 - -typedef size_t (*ngx_rtmp_log_op_getlen_pt)(ngx_rtmp_session_t *s, - ngx_rtmp_log_op_t *op); -typedef u_char * (*ngx_rtmp_log_op_getdata_pt)(ngx_rtmp_session_t *s, - u_char *buf, ngx_rtmp_log_op_t *log); - - -struct ngx_rtmp_log_op_s { - ngx_rtmp_log_op_getlen_pt getlen; - ngx_rtmp_log_op_getdata_pt getdata; - ngx_str_t value; - ngx_uint_t offset; -}; - - -typedef struct { - ngx_str_t name; - ngx_rtmp_log_op_getlen_pt getlen; - ngx_rtmp_log_op_getdata_pt getdata; - ngx_uint_t offset; -} ngx_rtmp_log_var_t; - - -typedef struct { - ngx_str_t name; - ngx_array_t *ops; /* ngx_rtmp_log_op_t */ -} ngx_rtmp_log_fmt_t; - - -typedef struct { - ngx_open_file_t *file; - time_t disk_full_time; - time_t error_log_time; - ngx_msec_t trunc_timer; - ngx_rtmp_log_fmt_t *format; -} ngx_rtmp_log_t; - - -typedef struct { - ngx_array_t *logs; /* ngx_rtmp_log_t */ - ngx_uint_t off; -} ngx_rtmp_log_app_conf_t; - - -typedef struct { - ngx_array_t formats; /* ngx_rtmp_log_fmt_t */ - ngx_uint_t combined_used; -} ngx_rtmp_log_main_conf_t; - - -typedef struct { - ngx_rtmp_session_t *session; - ngx_event_t event; - ngx_rtmp_log_t *log; -} ngx_rtmp_log_timer_ctx_t; - -typedef struct { - unsigned play:1; - unsigned publish:1; - ngx_uint_t last_bytes; - u_char name[NGX_RTMP_MAX_NAME]; - u_char stream[NGX_RTMP_MAX_NAME]; - u_char args[NGX_RTMP_MAX_ARGS]; - ngx_array_t timers; /* ngx_rtmp_log_timer_ctx_t */ -} ngx_rtmp_log_ctx_t; - - -static ngx_str_t ngx_rtmp_access_log = ngx_string(NGX_HTTP_LOG_PATH); - - -static ngx_command_t ngx_rtmp_log_commands[] = { - - { ngx_string("access_log"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE123, - ngx_rtmp_log_set_log, - NGX_RTMP_APP_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("log_format"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_2MORE, - ngx_rtmp_log_set_format, - NGX_RTMP_MAIN_CONF_OFFSET, - 0, - NULL }, - - ngx_null_command -}; - - -static ngx_rtmp_module_t ngx_rtmp_log_module_ctx = { - NULL, /* preconfiguration */ - ngx_rtmp_log_postconfiguration, /* postconfiguration */ - ngx_rtmp_log_create_main_conf, /* create main configuration */ - NULL, /* init main configuration */ - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - ngx_rtmp_log_create_app_conf, /* create app configuration */ - ngx_rtmp_log_merge_app_conf /* merge app configuration */ -}; - - -ngx_module_t ngx_rtmp_log_module = { - NGX_MODULE_V1, - &ngx_rtmp_log_module_ctx, /* module context */ - ngx_rtmp_log_commands, /* module directives */ - NGX_RTMP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static ngx_str_t ngx_rtmp_combined_fmt = - ngx_string("$remote_addr [$time_local] $command " - "\"$app\" \"$name\" \"$args\" - " - "$bytes_received $bytes_sent " - "\"$pageurl\" \"$flashver\" ($session_readable_time)"); - - -static size_t -ngx_rtmp_log_var_default_getlen(ngx_rtmp_session_t *s, ngx_rtmp_log_op_t *op) -{ - return op->value.len; -} - - -static u_char * -ngx_rtmp_log_var_default_getdata(ngx_rtmp_session_t *s, u_char *buf, - ngx_rtmp_log_op_t *op) -{ - return ngx_cpymem(buf, op->value.data, op->value.len); -} - -static size_t -ngx_rtmp_log_var_parg_getlen(ngx_rtmp_session_t *s, ngx_rtmp_log_op_t *op) -{ - ngx_str_t *name = &(op->value); - u_char *arg; - size_t len; - ngx_str_t value; - - len = name->len - (sizeof("parg_") - 1); - arg = name->data + sizeof("parg_") - 1; - - if (ngx_rtmp_arg(s, arg, len, &value) != NGX_OK) { - return op->value.len; - } - - return value.len; -} - - -static u_char * -ngx_rtmp_log_var_parg_getdata(ngx_rtmp_session_t *s, u_char *buf, - ngx_rtmp_log_op_t *op) -{ - ngx_str_t *name = &(op->value); - u_char *arg; - size_t len; - ngx_str_t value; - - len = name->len - (sizeof("parg_") - 1); - arg = name->data + sizeof("parg_") - 1; - - if (ngx_rtmp_arg(s, arg, len, &value) != NGX_OK) { - return ngx_cpymem(buf, op->value.data, op->value.len); - } - - return ngx_cpymem(buf, value.data, value.len); -} - -static size_t -ngx_rtmp_log_var_connection_getlen(ngx_rtmp_session_t *s, ngx_rtmp_log_op_t *op) -{ - return NGX_INT_T_LEN; -} - -static u_char * -ngx_rtmp_log_var_connection_getdata(ngx_rtmp_session_t *s, u_char *buf, - ngx_rtmp_log_op_t *op) -{ - return ngx_sprintf(buf, "%ui", (ngx_uint_t) s->number); -} - - -static size_t -ngx_rtmp_log_var_remote_addr_getlen(ngx_rtmp_session_t *s, - ngx_rtmp_log_op_t *op) -{ - return s->remote_addr_text.len; -} - - -static u_char * -ngx_rtmp_log_var_remote_addr_getdata(ngx_rtmp_session_t *s, u_char *buf, - ngx_rtmp_log_op_t *op) -{ - return ngx_cpymem(buf, s->remote_addr_text.data, - s->remote_addr_text.len); -} - - -static size_t -ngx_rtmp_log_var_msec_getlen(ngx_rtmp_session_t *s, - ngx_rtmp_log_op_t *op) -{ - return NGX_TIME_T_LEN + 4; -} - - -static u_char * -ngx_rtmp_log_var_msec_getdata(ngx_rtmp_session_t *s, u_char *buf, - ngx_rtmp_log_op_t *op) -{ - ngx_time_t *tp; - - tp = ngx_timeofday(); - - return ngx_sprintf(buf, "%T.%03M", tp->sec, tp->msec); -} - -static size_t -ngx_rtmp_log_var_sec_getlen(ngx_rtmp_session_t *s, - ngx_rtmp_log_op_t *op) -{ - return NGX_TIME_T_LEN + 4; -} - - -static u_char * -ngx_rtmp_log_var_sec_getdata(ngx_rtmp_session_t *s, u_char *buf, - ngx_rtmp_log_op_t *op) -{ - ngx_time_t *tp; - - tp = ngx_timeofday(); - - return ngx_sprintf(buf, "%T", tp->sec); -} - - -static size_t -ngx_rtmp_log_var_session_string_getlen(ngx_rtmp_session_t *s, - ngx_rtmp_log_op_t *op) -{ - return ((ngx_str_t *) ((u_char *) s + op->offset))->len; -} - - -static u_char * -ngx_rtmp_log_var_session_string_getdata(ngx_rtmp_session_t *s, u_char *buf, - ngx_rtmp_log_op_t *op) -{ - ngx_str_t *str; - - str = (ngx_str_t *) ((u_char *) s + op->offset); - - return ngx_cpymem(buf, str->data, str->len); -} - - -static size_t -ngx_rtmp_log_var_command_getlen(ngx_rtmp_session_t *s, - ngx_rtmp_log_op_t *op) -{ - return sizeof("PLAY+PUBLISH") - 1; -} - - -static u_char * -ngx_rtmp_log_var_command_getdata(ngx_rtmp_session_t *s, u_char *buf, - ngx_rtmp_log_op_t *op) -{ - ngx_rtmp_log_ctx_t *ctx; - ngx_str_t *cmd; - ngx_uint_t n; - - static ngx_str_t commands[] = { - ngx_string("NONE"), - ngx_string("PLAY"), - ngx_string("PUBLISH"), - ngx_string("PLAY+PUBLISH") - }; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_log_module); - - n = ctx ? (ctx->play + ctx->publish * 2) : 0; - - cmd = &commands[n]; - - return ngx_cpymem(buf, cmd->data, cmd->len); -} - - -static size_t -ngx_rtmp_log_var_context_cstring_getlen(ngx_rtmp_session_t *s, - ngx_rtmp_log_op_t *op) -{ - return ngx_max(NGX_RTMP_MAX_NAME, NGX_RTMP_MAX_ARGS); -} - - -static u_char * -ngx_rtmp_log_var_context_cstring_getdata(ngx_rtmp_session_t *s, u_char *buf, - ngx_rtmp_log_op_t *op) -{ - ngx_rtmp_log_ctx_t *ctx; - u_char *p; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_log_module); - if (ctx == NULL) { - return buf; - } - - p = (u_char *) ctx + op->offset; - while (*p) { - *buf++ = *p++; - } - - return buf; -} - - -static size_t -ngx_rtmp_log_var_session_uint32_getlen(ngx_rtmp_session_t *s, - ngx_rtmp_log_op_t *op) -{ - return NGX_INT32_LEN; -} - - -static u_char * -ngx_rtmp_log_var_session_uint32_getdata(ngx_rtmp_session_t *s, u_char *buf, - ngx_rtmp_log_op_t *op) -{ - uint32_t *v; - - v = (uint32_t *) ((uint8_t *) s + op->offset); - - return ngx_sprintf(buf, "%uD", *v); -} - -static u_char * -ngx_rtmp_log_var_session_video_flag(ngx_rtmp_session_t *s, u_char *buf, - ngx_rtmp_log_op_t *op) -{ - ngx_rtmp_codec_ctx_t *ctx; - ngx_int_t flag; - - flag = 0; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - if (ctx) { - flag = (ctx->video_codec_id > 0); - } - - return ngx_sprintf(buf, "%d", flag); -} - -static u_char * -ngx_rtmp_log_var_session_audio_flag(ngx_rtmp_session_t *s, u_char *buf, - ngx_rtmp_log_op_t *op) -{ - ngx_rtmp_codec_ctx_t *ctx; - ngx_int_t flag; - - flag = 0; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - if (ctx) { - flag = (ctx->audio_codec_id > 0); - } - - return ngx_sprintf(buf, "%d", flag); -} - -static u_char * -ngx_rtmp_log_var_session_bitrate_getdata(ngx_rtmp_session_t *s, u_char *buf, - ngx_rtmp_log_op_t *op) -{ - ngx_rtmp_log_ctx_t *ctx; - uint32_t bitrate; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_log_module); - if (!ctx) { - return buf; - } - - bitrate = 0; - if (s->publishing) { - bitrate = 8 * (s->in_bytes - ctx->last_bytes); - ctx->last_bytes = s->in_bytes; - } else { - bitrate = 8 * (s->out_bytes - ctx->last_bytes); - ctx->last_bytes = s->out_bytes; - } - - return ngx_sprintf(buf, "%D", bitrate); -} - -static size_t -ngx_rtmp_log_var_time_local_getlen(ngx_rtmp_session_t *s, - ngx_rtmp_log_op_t *op) -{ - return ngx_cached_http_log_time.len; -} - - -static u_char * -ngx_rtmp_log_var_time_local_getdata(ngx_rtmp_session_t *s, u_char *buf, - ngx_rtmp_log_op_t *op) -{ - return ngx_cpymem(buf, ngx_cached_http_log_time.data, - ngx_cached_http_log_time.len); -} - - -static size_t -ngx_rtmp_log_var_session_time_getlen(ngx_rtmp_session_t *s, - ngx_rtmp_log_op_t *op) -{ - return NGX_INT64_LEN; -} - - -static u_char * -ngx_rtmp_log_var_session_time_getdata(ngx_rtmp_session_t *s, u_char *buf, - ngx_rtmp_log_op_t *op) -{ - return ngx_sprintf(buf, "%L", - (int64_t) (ngx_current_msec - s->epoch) / 1000); -} - - -static size_t -ngx_rtmp_log_var_session_readable_time_getlen(ngx_rtmp_session_t *s, - ngx_rtmp_log_op_t *op) -{ - return NGX_INT_T_LEN + sizeof("d 23h 59m 59s") - 1; -} - - -static u_char * -ngx_rtmp_log_var_session_readable_time_getdata(ngx_rtmp_session_t *s, - u_char *buf, ngx_rtmp_log_op_t *op) -{ - int64_t v; - ngx_uint_t days, hours, minutes, seconds; - - v = (ngx_current_msec - s->epoch) / 1000; - - days = (ngx_uint_t) (v / (60 * 60 * 24)); - hours = (ngx_uint_t) (v / (60 * 60) % 24); - minutes = (ngx_uint_t) (v / 60 % 60); - seconds = (ngx_uint_t) (v % 60); - - if (days) { - buf = ngx_sprintf(buf, "%uid ", days); - } - - if (days || hours) { - buf = ngx_sprintf(buf, "%uih ", hours); - } - - if (days || hours || minutes) { - buf = ngx_sprintf(buf, "%uim ", minutes); - } - - buf = ngx_sprintf(buf, "%uis", seconds); - - return buf; -} - - -static ngx_rtmp_log_var_t ngx_rtmp_log_vars[] = { - { ngx_string("connection"), - ngx_rtmp_log_var_connection_getlen, - ngx_rtmp_log_var_connection_getdata, - 0 }, - - { ngx_string("remote_addr"), - ngx_rtmp_log_var_remote_addr_getlen, - ngx_rtmp_log_var_remote_addr_getdata, - 0 }, - - { ngx_string("app"), - ngx_rtmp_log_var_session_string_getlen, - ngx_rtmp_log_var_session_string_getdata, - offsetof(ngx_rtmp_session_t, app) }, - - { ngx_string("flashver"), - ngx_rtmp_log_var_session_string_getlen, - ngx_rtmp_log_var_session_string_getdata, - offsetof(ngx_rtmp_session_t, flashver) }, - - { ngx_string("swfurl"), - ngx_rtmp_log_var_session_string_getlen, - ngx_rtmp_log_var_session_string_getdata, - offsetof(ngx_rtmp_session_t, swf_url) }, - - { ngx_string("tcurl"), - ngx_rtmp_log_var_session_string_getlen, - ngx_rtmp_log_var_session_string_getdata, - offsetof(ngx_rtmp_session_t, tc_url) }, - - { ngx_string("domain"), - ngx_rtmp_log_var_session_string_getlen, - ngx_rtmp_log_var_session_string_getdata, - offsetof(ngx_rtmp_session_t, domain) }, - - { ngx_string("parg_"), - ngx_rtmp_log_var_parg_getlen, - ngx_rtmp_log_var_parg_getdata, - 0 }, - - { ngx_string("pageurl"), - ngx_rtmp_log_var_session_string_getlen, - ngx_rtmp_log_var_session_string_getdata, - offsetof(ngx_rtmp_session_t, page_url) }, - - { ngx_string("command"), - ngx_rtmp_log_var_command_getlen, - ngx_rtmp_log_var_command_getdata, - 0 }, - - { ngx_string("name"), - ngx_rtmp_log_var_context_cstring_getlen, - ngx_rtmp_log_var_context_cstring_getdata, - offsetof(ngx_rtmp_log_ctx_t, name) }, - - { ngx_string("stream"), - ngx_rtmp_log_var_context_cstring_getlen, - ngx_rtmp_log_var_context_cstring_getdata, - offsetof(ngx_rtmp_log_ctx_t, stream) }, - - { ngx_string("args"), - ngx_rtmp_log_var_context_cstring_getlen, - ngx_rtmp_log_var_context_cstring_getdata, - offsetof(ngx_rtmp_log_ctx_t, args) }, - - { ngx_string("bytes_sent"), - ngx_rtmp_log_var_session_uint32_getlen, - ngx_rtmp_log_var_session_uint32_getdata, - offsetof(ngx_rtmp_session_t, out_bytes) }, - - { ngx_string("bytes_received"), - ngx_rtmp_log_var_session_uint32_getlen, - ngx_rtmp_log_var_session_uint32_getdata, - offsetof(ngx_rtmp_session_t, in_bytes) }, - - { ngx_string("time_local"), - ngx_rtmp_log_var_time_local_getlen, - ngx_rtmp_log_var_time_local_getdata, - 0 }, - - { ngx_string("msec"), - ngx_rtmp_log_var_msec_getlen, - ngx_rtmp_log_var_msec_getdata, - 0 }, - - { ngx_string("ntp"), - ngx_rtmp_log_var_sec_getlen, - ngx_rtmp_log_var_sec_getdata, - 0 }, - - { ngx_string("session_time"), - ngx_rtmp_log_var_session_time_getlen, - ngx_rtmp_log_var_session_time_getdata, - 0 }, - - { ngx_string("session_readable_time"), - ngx_rtmp_log_var_session_readable_time_getlen, - ngx_rtmp_log_var_session_readable_time_getdata, - 0 }, - - { ngx_string("bitrate"), - ngx_rtmp_log_var_session_uint32_getlen, - ngx_rtmp_log_var_session_bitrate_getdata, - 0 }, - - { ngx_string("be_video"), - ngx_rtmp_log_var_session_uint32_getlen, - ngx_rtmp_log_var_session_video_flag, - 0 }, - - { ngx_string("be_audio"), - ngx_rtmp_log_var_session_uint32_getlen, - ngx_rtmp_log_var_session_audio_flag, - 0 }, - - { ngx_null_string, NULL, NULL, 0 } -}; - - -static void * -ngx_rtmp_log_create_main_conf(ngx_conf_t *cf) -{ - ngx_rtmp_log_main_conf_t *lmcf; - ngx_rtmp_log_fmt_t *fmt; - - lmcf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_log_main_conf_t)); - if (lmcf == NULL) { - return NULL; - } - - if (ngx_array_init(&lmcf->formats, cf->pool, 4, sizeof(ngx_rtmp_log_fmt_t)) - != NGX_OK) - { - return NULL; - } - - fmt = ngx_array_push(&lmcf->formats); - if (fmt == NULL) { - return NULL; - } - - ngx_str_set(&fmt->name, "combined"); - - fmt->ops = ngx_array_create(cf->pool, 16, sizeof(ngx_rtmp_log_op_t)); - if (fmt->ops == NULL) { - return NULL; - } - - return lmcf; - -} - - -static void * -ngx_rtmp_log_create_app_conf(ngx_conf_t *cf) -{ - ngx_rtmp_log_app_conf_t *lacf; - - lacf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_log_app_conf_t)); - if (lacf == NULL) { - return NULL; - } - - return lacf; -} - - -static char * -ngx_rtmp_log_merge_app_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_rtmp_log_app_conf_t *prev = parent; - ngx_rtmp_log_app_conf_t *conf = child; - ngx_rtmp_log_main_conf_t *lmcf; - ngx_rtmp_log_fmt_t *fmt; - ngx_rtmp_log_t *log; - - if (conf->logs || conf->off) { - return NGX_OK; - } - - conf->logs = prev->logs; - conf->off = prev->off; - - if (conf->logs || conf->off) { - return NGX_OK; - } - - conf->logs = ngx_array_create(cf->pool, 2, sizeof(ngx_rtmp_log_t)); - if (conf->logs == NULL) { - return NGX_CONF_ERROR; - } - - log = ngx_array_push(conf->logs); - if (log == NULL) { - return NGX_CONF_ERROR; - } - - log->file = ngx_conf_open_file(cf->cycle, &ngx_rtmp_access_log); - if (log->file == NULL) { - return NGX_CONF_ERROR; - } - - log->disk_full_time = 0; - log->error_log_time = 0; - log->trunc_timer = 0; - - lmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_log_module); - fmt = lmcf->formats.elts; - - log->format = &fmt[0]; - lmcf->combined_used = 1; - - return NGX_CONF_OK; -} - - -/* - * access_log off; - * access_log file; - * access_log file format_name; - * access_log file trunc=1m; - * access_log file format_name trunc=1m; - */ -static char * -ngx_rtmp_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_rtmp_log_app_conf_t *lacf = conf; - - ngx_rtmp_log_main_conf_t *lmcf; - ngx_rtmp_log_fmt_t *fmt; - ngx_rtmp_log_t *log; - ngx_str_t *value, name, timer; - ngx_uint_t n; - ngx_flag_t format_configured; - - name.len = 0; - format_configured = 0; - - value = cf->args->elts; - - if (ngx_strcmp(value[1].data, "off") == 0) { - lacf->off = 1; - return NGX_CONF_OK; - } - - if (lacf->logs == NULL) { - lacf->logs = ngx_array_create(cf->pool, 2, sizeof(ngx_rtmp_log_t)); - if (lacf->logs == NULL) { - return NGX_CONF_ERROR; - } - } - - log = ngx_array_push(lacf->logs); - if (log == NULL) { - return NGX_CONF_ERROR; - } - - ngx_memzero(log, sizeof(*log)); - - lmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_log_module); - - log->file = ngx_conf_open_file(cf->cycle, &value[1]); - if (log->file == NULL) { - return NGX_CONF_ERROR; - } - - for (n = 2; n < cf->args->nelts; ++n) { - /* sizeof("trunc=") - 1 = 6 */ - if (ngx_memcmp("trunc=", value[n].data, 6) == 0) { - timer.data = value[n].data + 6; - timer.len = value[n].len - 6; - - log->trunc_timer = ngx_parse_time(&timer, 0); - if (log->trunc_timer == (ngx_msec_t) NGX_ERROR) { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, - "unknown trunc timer format \"%V\"", &timer); - return NGX_CONF_ERROR; - } - } else { - if (format_configured) { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, - "format name has been configured"); - return NGX_CONF_ERROR; - } - - format_configured = 1; - name = value[n]; - } - } - - if (name.len == 0) { - ngx_str_set(&name, "combined"); - lmcf->combined_used = 1; - - } else { - if (ngx_strcmp(name.data, "combined") == 0) { - lmcf->combined_used = 1; - } - } - - fmt = lmcf->formats.elts; - for (n = 0; n < lmcf->formats.nelts; ++n, ++fmt) { - if (fmt->name.len == name.len && - ngx_strncasecmp(fmt->name.data, name.data, name.len) == 0) - { - log->format = fmt; - break; - } - } - - if (log->format == NULL) { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "unknown log format \"%V\"", - &name); - return NGX_CONF_ERROR; - } - - return NGX_CONF_OK; -} - - -static char * -ngx_rtmp_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_rtmp_log_main_conf_t *lmcf = conf; - ngx_rtmp_log_fmt_t *fmt; - ngx_str_t *value; - ngx_uint_t i; - - value = cf->args->elts; - - if (cf->cmd_type != NGX_RTMP_MAIN_CONF) { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, - "\"log_format\" directive can only be used on " - "\"rtmp\" level"); - } - - fmt = lmcf->formats.elts; - for (i = 0; i < lmcf->formats.nelts; i++) { - if (fmt[i].name.len == value[1].len && - ngx_strcmp(fmt[i].name.data, value[1].data) == 0) - { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "duplicate \"log_format\" name \"%V\"", - &value[1]); - return NGX_CONF_ERROR; - } - } - - fmt = ngx_array_push(&lmcf->formats); - if (fmt == NULL) { - return NGX_CONF_ERROR; - } - - fmt->name = value[1]; - - fmt->ops = ngx_array_create(cf->pool, 16, sizeof(ngx_rtmp_log_op_t)); - if (fmt->ops == NULL) { - return NGX_CONF_ERROR; - } - - return ngx_rtmp_log_compile_format(cf, fmt->ops, cf->args, 2); -} - - -static char * -ngx_rtmp_log_compile_format(ngx_conf_t *cf, ngx_array_t *ops, ngx_array_t *args, - ngx_uint_t s) -{ - size_t i, len; - u_char *data, *d, c; - ngx_uint_t bracket; - ngx_str_t *value, var, pre_var; - ngx_rtmp_log_op_t *op; - ngx_rtmp_log_var_t *v; - u_char *p; - - value = args->elts; - - for (; s < args->nelts; ++s) { - i = 0; - - len = value[s].len; - d = value[s].data; - - while (i < len) { - - op = ngx_array_push(ops); - if (op == NULL) { - return NGX_CONF_ERROR; - } - - ngx_memzero(op, sizeof(*op)); - - data = &d[i]; - - if (d[i] == '$') { - if (++i == len) { - goto invalid; - } - - if (d[i] == '{') { - bracket = 1; - if (++i == len) { - goto invalid; - } - } else { - bracket = 0; - } - - var.data = &d[i]; - - for (var.len = 0; i < len; ++i, ++var.len) { - c = d[i]; - - if (c == '}' && bracket) { - ++i; - bracket = 0; - break; - } - - if ((c >= 'A' && c <= 'Z') || - (c >= 'a' && c <= 'z') || - (c >= '0' && c <= '9') || - (c == '_')) - { - continue; - } - - break; - } - - if (bracket) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "missing closing bracket in \"%V\"", - &var); - return NGX_CONF_ERROR; - } - - if (var.len == 0) { - goto invalid; - } - - for (v = ngx_rtmp_log_vars; v->name.len; ++v) { - if (v->name.len == var.len && - ngx_strncmp(v->name.data, var.data, var.len) == 0) - { - op->getlen = v->getlen; - op->getdata = v->getdata; - op->offset = v->offset; - break; - } - } - - if (v->name.len == 0) { - p = ngx_strnstr(var.data, "_", var.len); - if (p == NULL) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "unknown variable \"%V\"", &var); - return NGX_CONF_ERROR; - } - - pre_var.data = var.data; - pre_var.len = p - var.data + 1; - for (v = ngx_rtmp_log_vars; v->name.len; ++v) { - if (v->name.len == pre_var.len && - !ngx_strncmp(v->name.data, pre_var.data, pre_var.len)) - { - op->getlen = v->getlen; - op->getdata = v->getdata; - op->offset = v->offset; - op->value = var; - break; - } - } - } - - if (v->name.len == 0) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "unknown variable \"%V\"", &var); - return NGX_CONF_ERROR; - } - - continue; - } - - ++i; - - while (i < len && d[i] != '$') { - ++i; - } - - op->getlen = ngx_rtmp_log_var_default_getlen; - op->getdata = ngx_rtmp_log_var_default_getdata; - - op->value.len = &d[i] - data; - - op->value.data = ngx_pnalloc(cf->pool, op->value.len); - if (op->value.data == NULL) { - return NGX_CONF_ERROR; - } - - ngx_memcpy(op->value.data, data, op->value.len); - } - } - - return NGX_CONF_OK; - -invalid: - - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%s\"", data); - - return NGX_CONF_ERROR; -} - - -static ngx_rtmp_log_ctx_t * -ngx_rtmp_log_set_names(ngx_rtmp_session_t *s, u_char *name, u_char *args) -{ - ngx_rtmp_log_ctx_t *ctx; - ngx_rtmp_log_app_conf_t *lacf; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_log_module); - if (ctx == NULL) { - ctx = ngx_pcalloc(s->pool, sizeof(ngx_rtmp_log_ctx_t)); - if (ctx == NULL) { - return NULL; - } - - lacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_log_module); - - if (lacf->logs) { - if (ngx_array_init(&ctx->timers, s->pool, - lacf->logs->nelts, sizeof(ngx_rtmp_log_timer_ctx_t)) != NGX_OK) - { - return NULL; - } - } - - ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_log_module); - } - - ngx_memcpy(ctx->stream, s->stream.data, s->stream.len); - ngx_memcpy(ctx->name, name, NGX_RTMP_MAX_NAME); - ngx_memcpy(ctx->args, args, NGX_RTMP_MAX_ARGS); - - return ctx; -} - - -static void -ngx_rtmp_log_write(ngx_rtmp_session_t *s, ngx_rtmp_log_t *log, u_char *buf, - size_t len) -{ - u_char *name; - time_t now; - ssize_t n; - int err; - - err = 0; - name = log->file->name.data; - n = ngx_write_fd(log->file->fd, buf, len); - - if (n == (ssize_t) len) { - return; - } - - now = ngx_time(); - - if (n == -1) { - err = ngx_errno; - - if (err == NGX_ENOSPC) { - log->disk_full_time = now; - } - - if (now - log->error_log_time > 59) { - ngx_log_error(NGX_LOG_ALERT, s->log, err, - ngx_write_fd_n " to \"%s\" failed", name); - log->error_log_time = now; - } - } - - if (now - log->error_log_time > 59) { - ngx_log_error(NGX_LOG_ALERT, s->log, err, - ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz", - name, n, len); - log->error_log_time = now; - } -} - -static void -ngx_rtmp_log_pre_write(ngx_rtmp_session_t *s, ngx_rtmp_log_t *log) -{ - ngx_rtmp_log_op_t *op; - u_char line[MAX_ACCESS_LOG_LINE_LEN], *p; - size_t len; - ngx_uint_t n; - - if (ngx_time() == log->disk_full_time) { - /* FreeBSD full disk protection; - * nginx http logger does the same */ - return; - } - - len = 0; - op = log->format->ops->elts; - for (n = 0; n < log->format->ops->nelts; ++n, ++op) { - len += op->getlen(s, op); - } - len += NGX_LINEFEED_SIZE; - - if (len > MAX_ACCESS_LOG_LINE_LEN) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "Access line len %z greater than %d", - len, MAX_ACCESS_LOG_LINE_LEN); - ngx_rtmp_finalize_session(s); - - return; - } - - p = line; - op = log->format->ops->elts; - for (n = 0; n < log->format->ops->nelts; ++n, ++op) { - p = op->getdata(s, p, op); - } - - ngx_linefeed(p); - - ngx_rtmp_log_write(s, log, line, p - line); -} - -static void -ngx_rtmp_log_trunc_timer(ngx_event_t *ev) -{ - ngx_rtmp_log_timer_ctx_t *ltctx; - ngx_rtmp_session_t *s; - ngx_rtmp_log_t *log; - ngx_msec_t t; - - ltctx = ev->data; - - s = ltctx->session; - log = ltctx->log; - - ngx_rtmp_log_pre_write(s, log); - - t = log->trunc_timer - ngx_current_msec % log->trunc_timer; - ngx_add_timer(ev, t); -} - -static void -ngx_rtmp_log_add_trunc_timer(ngx_rtmp_session_t *s, ngx_rtmp_log_ctx_t *ctx, - ngx_rtmp_log_t *log) -{ - ngx_rtmp_log_timer_ctx_t *ltctx; - ngx_event_t *e; - ngx_msec_t t; - - ltctx = ngx_array_push(&ctx->timers); - ngx_memzero(ltctx, sizeof(ngx_rtmp_log_timer_ctx_t)); - ltctx->session = s; - ltctx->log = log; - e = <ctx->event; - - e->data = ltctx; - e->log = s->log; - e->handler = ngx_rtmp_log_trunc_timer; - - t = log->trunc_timer - ngx_current_msec % log->trunc_timer; - ngx_add_timer(e, t); -} - -static ngx_int_t -ngx_rtmp_log_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v) -{ - ngx_rtmp_log_app_conf_t *lacf; - ngx_rtmp_log_t *log; - ngx_rtmp_log_ctx_t *ctx; - ngx_uint_t i; - - if (s->interprocess || s->relay) { - goto next; - } - - ctx = ngx_rtmp_log_set_names(s, v->name, v->args); - if (ctx == NULL) { - goto next; - } - - if (ctx->publish) { /* avoid multi push */ - goto next; - } - - ctx->publish = 1; - - lacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_log_module); - - if (lacf->logs == NULL) { - goto next; - } - - log = lacf->logs->elts; - for (i = 0; i < lacf->logs->nelts; ++i, ++log) { - if (log->trunc_timer != 0) { - ngx_rtmp_log_add_trunc_timer(s, ctx, log); - } - } - -next: - return next_publish(s, v); -} - - -static ngx_int_t -ngx_rtmp_log_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v) -{ - ngx_rtmp_log_app_conf_t *lacf; - ngx_rtmp_log_t *log; - ngx_rtmp_log_ctx_t *ctx; - ngx_uint_t i; - - if (s->interprocess || s->relay) { - goto next; - } - - ctx = ngx_rtmp_log_set_names(s, v->name, v->args); - if (ctx == NULL) { - goto next; - } - - if (ctx->play) { /* avoid mulit pull */ - goto next; - } - - ctx->play = 1; - - lacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_log_module); - - if (lacf->logs == NULL) { - goto next; - } - - log = lacf->logs->elts; - for (i = 0; i < lacf->logs->nelts; ++i, ++log) { - if (log->trunc_timer != 0) { - ngx_rtmp_log_add_trunc_timer(s, ctx, log); - } - } - -next: - return next_play(s, v); -} - - -static ngx_int_t -ngx_rtmp_log_disconnect(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - ngx_rtmp_log_app_conf_t *lacf; - ngx_rtmp_log_ctx_t *ctx; - ngx_rtmp_log_timer_ctx_t *ltctx; - ngx_rtmp_log_t *log; - ngx_uint_t i; - - if (s->interprocess || s->relay) { - return NGX_OK; - } - - lacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_log_module); - if (lacf == NULL || lacf->off || lacf->logs == NULL) { - return NGX_OK; - } - - log = lacf->logs->elts; - for (i = 0; i < lacf->logs->nelts; ++i, ++log) { - ngx_rtmp_log_pre_write(s, log); - } - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_log_module); - - if (ctx == NULL) { - return NGX_OK; - } - - ltctx = ctx->timers.elts; - for (i = 0; i < ctx->timers.nelts; ++i, ++ltctx) { - ngx_del_timer(<ctx->event); - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_log_postconfiguration(ngx_conf_t *cf) -{ - ngx_rtmp_core_main_conf_t *cmcf; - ngx_rtmp_handler_pt *h; - ngx_rtmp_log_main_conf_t *lmcf; - ngx_array_t a; - ngx_rtmp_log_fmt_t *fmt; - ngx_str_t *value; - - lmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_log_module); - if (lmcf->combined_used) { - if (ngx_array_init(&a, cf->pool, 1, sizeof(ngx_str_t)) != NGX_OK) { - return NGX_ERROR; - } - - value = ngx_array_push(&a); - if (value == NULL) { - return NGX_ERROR; - } - - *value = ngx_rtmp_combined_fmt; - fmt = lmcf->formats.elts; - - if (ngx_rtmp_log_compile_format(cf, fmt->ops, &a, 0) - != NGX_CONF_OK) - { - return NGX_ERROR; - } - } - - cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module); - - h = ngx_array_push(&cmcf->events[NGX_RTMP_DISCONNECT]); - *h = ngx_rtmp_log_disconnect; - - next_publish = ngx_rtmp_publish; - ngx_rtmp_publish = ngx_rtmp_log_publish; - - next_play = ngx_rtmp_play; - ngx_rtmp_play = ngx_rtmp_log_play; - - return NGX_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_monitor_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_monitor_module.c deleted file mode 100644 index 0a8d29f576..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_monitor_module.c +++ /dev/null @@ -1,458 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include "ngx_rtmp_monitor_module.h" -#include "ngx_rtmp_cmd_module.h" -#include "ngx_rtmp_codec_module.h" - - -static ngx_rtmp_close_stream_pt next_close_stream; - - -static void *ngx_rtmp_monitor_create_app_conf(ngx_conf_t *cf); -static char *ngx_rtmp_monitor_merge_app_conf(ngx_conf_t *cf, - void *parent, void *child); -static ngx_int_t ngx_rtmp_monitor_postconfiguration(ngx_conf_t *cf); - -static char *ngx_rtmp_monitor_dump(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); -static char *ngx_rtmp_monitor_buffered_log(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); - - -#define NGX_RTMP_MONITOR_BUFFER_SIZE 61 - - -typedef struct { - ngx_str_t dump_path; - ngx_flag_t monitor; - ngx_log_t *buffered_log; -} ngx_rtmp_monitor_app_conf_t; - - -typedef struct { - ngx_event_t consume; - ngx_msec_t buffered; - ngx_uint_t nbuffered; - - double frame_rate; - double nframes; - - double buffers[NGX_RTMP_MONITOR_BUFFER_SIZE]; - ngx_uint_t fps[NGX_RTMP_MONITOR_BUFFER_SIZE]; - ngx_uint_t curr; - - ngx_flag_t dump; - - unsigned publishing:1; -} ngx_rtmp_monitor_ctx_t; - - -static ngx_command_t ngx_rtmp_monitor_commands[] = { - - { ngx_string("dump"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_rtmp_monitor_dump, - NGX_RTMP_APP_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("buffered_log"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_1MORE, - ngx_rtmp_monitor_buffered_log, - NGX_RTMP_APP_CONF_OFFSET, - 0, - NULL }, - - ngx_null_command -}; - - -static ngx_rtmp_module_t ngx_rtmp_monitor_module_ctx = { - NULL, /* preconfiguration */ - ngx_rtmp_monitor_postconfiguration, /* postconfiguration */ - NULL, /* create main configuration */ - NULL, /* init main configuration */ - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - ngx_rtmp_monitor_create_app_conf, /* create app configuration */ - ngx_rtmp_monitor_merge_app_conf /* merge app configuration */ -}; - - -ngx_module_t ngx_rtmp_monitor_module = { - NGX_MODULE_V1, - &ngx_rtmp_monitor_module_ctx, /* module context */ - ngx_rtmp_monitor_commands, /* module directives */ - NGX_RTMP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void -ngx_rtmp_monitor_dump_frame(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ -} - -static void -ngx_rtmp_monitor_consume(ngx_event_t *ev) -{ - ngx_rtmp_session_t *s, *ps; - ngx_rtmp_monitor_ctx_t *ctx; - ngx_rtmp_codec_ctx_t *cctx; - ngx_rtmp_monitor_app_conf_t *macf; - u_char peer[NGX_SOCKADDR_STRLEN]; - u_char local[NGX_SOCKADDR_STRLEN]; - struct sockaddr paddr, laddr; - socklen_t plen, llen; - - s = ev->data; - - macf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_monitor_module); - - if (macf->monitor == 0) { - return; - } - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_monitor_module); - if (ctx == NULL) { - return; - } - - if (ctx->publishing) { - ps = s; - } else { - if (s->live_stream->publish_ctx) { - ps = s->live_stream->publish_ctx->session; - } else { - goto next; - } - } - - cctx = ngx_rtmp_get_module_ctx(ps, ngx_rtmp_codec_module); - if (cctx == NULL) { - goto next; - } - - if (cctx->frame_rate != 0) { - ctx->frame_rate = cctx->frame_rate; - } - -next: - if (ctx->frame_rate == 0) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "monitor, frame rate error, stream: %V, frame rate: %.2f", - &s->stream, ctx->frame_rate); - return; - } - - ctx->nframes -= ctx->frame_rate; - - if (ctx->nframes <= 0) { - ctx->nframes = 0; - if (ctx->buffered == 0) { - ++ctx->nbuffered; - } - ++ctx->buffered; - - ngx_memzero(local, sizeof(local)); - ngx_memzero(peer, sizeof(peer)); - plen = sizeof(paddr); - llen = sizeof(laddr); - - if (s->connection) { - getpeername(s->connection->fd, &paddr, &plen); - getsockname(s->connection->fd, &laddr, &llen); - - ngx_sock_ntop(&paddr, plen, peer, NGX_SOCKADDR_STRLEN, 1); - ngx_sock_ntop(&laddr, llen, local, NGX_SOCKADDR_STRLEN, 1); - - ngx_log_error(NGX_LOG_ERR, macf->buffered_log, 0, - "%p %s, peer: %s, local: %s, " - "stream: %V, buffered: %ui, time: %uis", - s, ctx->publishing ? "publisher" : "player", peer, local, - &s->stream, ctx->nbuffered, ctx->buffered); - - } - } else { - ctx->buffered = 0; - } - - ctx->buffers[ctx->curr] = ctx->nframes; - - ctx->curr = (ctx->curr + 1) % NGX_RTMP_MONITOR_BUFFER_SIZE; - - ctx->fps[ctx->curr] = 0; - - ngx_add_timer(&ctx->consume, 1000); -} - -static ngx_int_t -ngx_rtmp_monitor_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - ngx_rtmp_monitor_frame(s, h, in, ngx_rtmp_is_codec_header(in), 1); - -// if (h->type == NGX_RTMP_MSG_VIDEO) { -// ngx_log_error(NGX_LOG_INFO, s->log, 0, -// "!!!!!!video(%d): %02xD %02xD %02xD %02xD %02xD", -// h->mlen, in->buf->pos[0], in->buf->pos[1], in->buf->pos[2], -// in->buf->pos[3], in->buf->pos[4], in->buf->pos[5]); -// } -// -// if (h->type == NGX_RTMP_MSG_AUDIO) { -// ngx_log_error(NGX_LOG_INFO, s->log, 0, -// "!!!!!!audio(%d): %02xD %02xD %02xD %02xD %02xD", -// h->mlen, in->buf->pos[0], in->buf->pos[1], in->buf->pos[2], -// in->buf->pos[3], in->buf->pos[4], in->buf->pos[5]); -// } - - return NGX_OK; -} - -static ngx_int_t -ngx_rtmp_monitor_meta_data(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - if (s->first_metadata == 0) { - s->stage = NGX_LIVE_AV; - s->first_metadata = ngx_current_msec; - s->first_data = s->first_data == 0? ngx_current_msec: s->first_data; - } - - ngx_log_error(NGX_LOG_INFO, s->log, 0, "receive metadata"); - - return NGX_OK; -} - -static ngx_int_t -ngx_rtmp_monitor_close_stream(ngx_rtmp_session_t *s, ngx_rtmp_close_stream_t *v) -{ - ngx_rtmp_monitor_ctx_t *ctx; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_monitor_module); - - if (ctx == NULL) { - goto next; - } - - if (ctx->consume.timer_set) { - ngx_del_timer(&ctx->consume); - } - - if (ctx->consume.posted) { - ngx_delete_posted_event(&ctx->consume); - } - -next: - return next_close_stream(s, v); -} - -void -ngx_rtmp_monitor_frame(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in, ngx_flag_t is_header, ngx_flag_t publishing) -{ - ngx_rtmp_monitor_app_conf_t *macf; - ngx_rtmp_monitor_ctx_t *ctx; - - if (s->first_metadata == 0 && (h->type == NGX_RTMP_MSG_AMF_META - || h->type == NGX_RTMP_MSG_AMF3_META)) - { - s->stage = NGX_LIVE_AV; - s->first_metadata = ngx_current_msec; - s->first_data = s->first_data == 0? ngx_current_msec: s->first_data; - } - - if (s->first_audio == 0 && h->type == NGX_RTMP_MSG_AUDIO) { - s->stage = NGX_LIVE_AV; - s->first_audio = ngx_current_msec; - s->first_data = s->first_data == 0? ngx_current_msec: s->first_data; - } - - if (s->first_video == 0 && h->type == NGX_RTMP_MSG_VIDEO) { - s->stage = NGX_LIVE_AV; - s->first_video = ngx_current_msec; - s->first_data = s->first_data == 0? ngx_current_msec: s->first_data; - } - - if (h->type == NGX_RTMP_MSG_AUDIO && is_header) { - if (s->publishing) { - ngx_log_error(NGX_LOG_INFO, s->log, 0, "receive audio header"); - } else { - ngx_log_error(NGX_LOG_INFO, s->log, 0, "send audio header"); - } - } - - if (h->type == NGX_RTMP_MSG_VIDEO && is_header) { - if (s->publishing) { - ngx_log_error(NGX_LOG_INFO, s->log, 0, "receive video header"); - } else { - ngx_log_error(NGX_LOG_INFO, s->log, 0, "send video header"); - } - } - - if (h->type != NGX_RTMP_MSG_VIDEO) { - return; - } - - macf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_monitor_module); - - if (macf->monitor == 0) { - return; - } - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_monitor_module); - - if (ctx == NULL) { - ctx = ngx_pcalloc(s->pool, sizeof(ngx_rtmp_monitor_ctx_t)); - if (ctx == NULL) { - return; - } - ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_monitor_module); - - ctx->dump = macf->dump_path.len > 0; - ctx->publishing = publishing; - - ctx->consume.data = s; - ctx->consume.log = s->log; - ctx->consume.handler = ngx_rtmp_monitor_consume; - ngx_add_timer(&ctx->consume, 1000); - } - - if (publishing && ctx->dump) { - ngx_rtmp_monitor_dump_frame(s, h, in); - } - - if (is_header) { - return; - } - - ++ctx->nframes; - ++ctx->fps[ctx->curr]; -} - - -static void * -ngx_rtmp_monitor_create_app_conf(ngx_conf_t *cf) -{ - ngx_rtmp_monitor_app_conf_t *macf; - - macf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_monitor_app_conf_t)); - if (macf == NULL) { - return NULL; - } - - macf->monitor = NGX_CONF_UNSET; - - return macf; -} - -static char * -ngx_rtmp_monitor_merge_app_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_rtmp_monitor_app_conf_t *prev = parent; - ngx_rtmp_monitor_app_conf_t *conf = child; - - if (conf->dump_path.data == NULL) { - conf->dump_path = prev->dump_path; - } - - ngx_conf_merge_value(conf->monitor, prev->monitor, 0); - - if (conf->buffered_log == NULL) { - if (prev->buffered_log) { - conf->buffered_log = prev->buffered_log; - } else { - conf->buffered_log = &cf->cycle->new_log; - } - } - - return NGX_CONF_OK; -} - -static char * -ngx_rtmp_monitor_dump(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_rtmp_monitor_app_conf_t *macf; - ngx_str_t *value; - - macf = conf; - - if (macf->dump_path.len) { - return "is duplicate"; - } - - value = cf->args->elts; - - macf->dump_path = value[1]; - - if (macf->dump_path.len > 0 && - macf->dump_path.data[macf->dump_path.len - 1] == '/') - { - --macf->dump_path.len; - } - - if (ngx_conf_full_name(cf->cycle, &macf->dump_path, 0) != NGX_OK) { - return NGX_CONF_ERROR; - } - - return NGX_CONF_OK; -} - -static char * -ngx_rtmp_monitor_buffered_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_rtmp_monitor_app_conf_t *macf; - - macf = conf; - - macf->monitor = 1; - - return ngx_log_set_log(cf, &macf->buffered_log); -} - -static ngx_int_t -ngx_rtmp_monitor_postconfiguration(ngx_conf_t *cf) -{ - ngx_rtmp_core_main_conf_t *cmcf; - ngx_rtmp_handler_pt *h; - ngx_rtmp_amf_handler_t *ch; - - cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module); - - h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_AUDIO]); - *h = ngx_rtmp_monitor_av; - - h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_VIDEO]); - *h = ngx_rtmp_monitor_av; - - /* register metadata handler */ - ch = ngx_array_push(&cmcf->amf); - if (ch == NULL) { - return NGX_ERROR; - } - ngx_str_set(&ch->name, "@setDataFrame"); - ch->handler = ngx_rtmp_monitor_meta_data; - - ch = ngx_array_push(&cmcf->amf); - if (ch == NULL) { - return NGX_ERROR; - } - ngx_str_set(&ch->name, "onMetaData"); - ch->handler = ngx_rtmp_monitor_meta_data; - - next_close_stream = ngx_rtmp_close_stream; - ngx_rtmp_close_stream = ngx_rtmp_monitor_close_stream; - - return NGX_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_monitor_module.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_monitor_module.h deleted file mode 100644 index 1ba70cd6c3..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_monitor_module.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#ifndef _NGX_RTMP_MONITOR_H_INCLUDED_ -#define _NGX_RTMP_MONITOR_H_INCLUDED_ - - -#include -#include -#include -#include "ngx_rtmp.h" - - -void ngx_rtmp_monitor_frame(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in, ngx_flag_t is_header, ngx_flag_t publishing); - - -#endif diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_notify_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_notify_module.c deleted file mode 100644 index 14df5ab4a7..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_notify_module.c +++ /dev/null @@ -1,1964 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - * - * Open Capability Live Platform - */ - - -#include -#include -#include "ngx_rtmp.h" -#include "ngx_rtmp_cmd_module.h" -#include "ngx_live_record.h" -#include "ngx_live_relay.h" -#include "ngx_dynamic_resolver.h" -#include "ngx_toolkit_misc.h" -#include "ngx_netcall.h" -#include "ngx_rtmp_variables.h" - - -static ngx_live_record_start_pt next_record_start; -static ngx_live_record_update_pt next_record_update; -static ngx_live_record_done_pt next_record_done; - - -static ngx_rtmp_publish_pt next_publish; -static ngx_rtmp_play_pt next_play; -static ngx_rtmp_close_stream_pt next_close_stream; - - -static ngx_live_push_pt next_push; -static ngx_live_pull_pt next_pull; -static ngx_live_push_close_pt next_push_close; -static ngx_live_pull_close_pt next_pull_close; - - -static ngx_int_t ngx_rtmp_notify_init_process(ngx_cycle_t *cycle); - -static ngx_int_t ngx_rtmp_notify_postconfiguration(ngx_conf_t *cf); -static void *ngx_rtmp_notify_create_main_conf(ngx_conf_t *cf); -static char *ngx_rtmp_notify_init_main_conf(ngx_conf_t *cf, void *conf); -static void *ngx_rtmp_notify_create_srv_conf(ngx_conf_t *cf); -static char *ngx_rtmp_notify_merge_srv_conf(ngx_conf_t *cf, void *parent, - void *child); -static void *ngx_rtmp_notify_create_app_conf(ngx_conf_t *cf); -static char *ngx_rtmp_notify_merge_app_conf(ngx_conf_t *cf, void *parent, - void *child); - -static char *ngx_rtmp_notify_on_main_event(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); -static char *ngx_rtmp_notify_on_srv_event(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); -static char *ngx_rtmp_notify_on_app_event(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); - -#define NGX_RTMP_OCLP_START 0x01 -#define NGX_RTMP_OCLP_UPDATE 0x02 -#define NGX_RTMP_OCLP_DONE 0x04 - - -enum { - NGX_RTMP_OCLP_PROC, /* only notify */ - NGX_RTMP_OCLP_MAIN_MAX -}; - -enum { - NGX_RTMP_OCLP_CONNECT, /* only notify */ - NGX_RTMP_OCLP_SRV_MAX -}; - -enum { - NGX_RTMP_OCLP_PLAY, /* only notify */ - NGX_RTMP_OCLP_PUBLISH, /* only notify */ - NGX_RTMP_OCLP_PULL, /* relay pull */ - NGX_RTMP_OCLP_PUSH, /* relay push */ - NGX_RTMP_OCLP_STREAM, /* only notify */ - NGX_RTMP_OCLP_META, /* for transcode */ - NGX_RTMP_OCLP_RECORD, /* for record */ - NGX_RTMP_OCLP_APP_MAX -}; - -static char *ngx_rtmp_notify_stage[] = { - "", - "start", - "update", - "", - "done", -}; - -static char *ngx_rtmp_notify_app_type[] = { - "play", - "publish", - "pull", - "push", - "stream", - "meta", - "record", -}; - -typedef struct { - ngx_uint_t status; - char *code; - char *level; - char *desc; -} ngx_rtmp_notify_relay_error_t; - -static ngx_rtmp_notify_relay_error_t ngx_rtmp_notify_relay_errors[] = { - { 404, "NetStream.Play.StreamNotFound", "error", "No such stream" }, - { 400, "NetStream.Publish.BadName", "error", "Already publishing" }, - { 0, NULL, NULL, NULL }, -}; - - -#define NGX_RTMP_OCLP_META_VIDEO 0 -#define NGX_RTMP_OCLP_META_AUDIO 1 -#define NGX_RTMP_OCLP_META_BOTH 2 - -static ngx_conf_enum_t ngx_rtmp_notify_meta_type[] = { - { ngx_string("video"), NGX_RTMP_OCLP_META_VIDEO }, - { ngx_string("audio"), NGX_RTMP_OCLP_META_AUDIO }, - { ngx_string("both"), NGX_RTMP_OCLP_META_BOTH }, - { ngx_null_string, 0 } -}; - -typedef struct { - ngx_str_t url; - ngx_str_t args; - ngx_str_t groupid; - ngx_uint_t stage; - ngx_msec_t timeout; - ngx_msec_t update; -} ngx_rtmp_notify_event_t; - -typedef struct { - ngx_rtmp_notify_event_t events[NGX_RTMP_OCLP_MAIN_MAX]; -} ngx_rtmp_notify_main_conf_t; - -typedef struct { - ngx_rtmp_notify_event_t events[NGX_RTMP_OCLP_SRV_MAX]; -} ngx_rtmp_notify_srv_conf_t; - -typedef struct { - ngx_flag_t ignore_invalid_notify; - ngx_flag_t meta_once; - ngx_uint_t meta_type; - ngx_array_t events[NGX_RTMP_OCLP_APP_MAX]; -} ngx_rtmp_notify_app_conf_t; - - -typedef struct { - ngx_netcall_ctx_t *nctx; - ngx_netcall_ctx_t *rctx; - - ngx_rtmp_notify_event_t *event; - ngx_uint_t type; - ngx_live_relay_t *relay; - - ngx_rtmp_publish_t publish_v; - ngx_rtmp_play_t play_v; -} ngx_rtmp_notify_ctx_t; - - -static ngx_command_t ngx_rtmp_notify_commands[] = { - - { ngx_string("ignore_invalid_notify"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_notify_app_conf_t, ignore_invalid_notify), - NULL }, - - { ngx_string("on_proc"), - NGX_RTMP_MAIN_CONF|NGX_CONF_1MORE, - ngx_rtmp_notify_on_main_event, - NGX_RTMP_MAIN_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("on_connect"), - NGX_RTMP_SRV_CONF|NGX_CONF_1MORE, - ngx_rtmp_notify_on_srv_event, - NGX_RTMP_SRV_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("on_play"), - NGX_RTMP_APP_CONF|NGX_CONF_1MORE, - ngx_rtmp_notify_on_app_event, - NGX_RTMP_APP_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("on_publish"), - NGX_RTMP_APP_CONF|NGX_CONF_1MORE, - ngx_rtmp_notify_on_app_event, - NGX_RTMP_APP_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("on_pull"), - NGX_RTMP_APP_CONF|NGX_CONF_1MORE, - ngx_rtmp_notify_on_app_event, - NGX_RTMP_APP_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("on_push"), - NGX_RTMP_APP_CONF|NGX_CONF_1MORE, - ngx_rtmp_notify_on_app_event, - NGX_RTMP_APP_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("on_stream"), - NGX_RTMP_APP_CONF|NGX_CONF_1MORE, - ngx_rtmp_notify_on_app_event, - NGX_RTMP_APP_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("on_meta"), - NGX_RTMP_APP_CONF|NGX_CONF_1MORE, - ngx_rtmp_notify_on_app_event, - NGX_RTMP_APP_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("on_record"), - NGX_RTMP_APP_CONF|NGX_CONF_1MORE, - ngx_rtmp_notify_on_app_event, - NGX_RTMP_APP_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("on_meta_once"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_1MORE, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_notify_app_conf_t, meta_once), - NULL }, - - { ngx_string("on_meta_type"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_1MORE, - ngx_conf_set_enum_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_notify_app_conf_t, meta_type), - &ngx_rtmp_notify_meta_type }, -//////////////////////////////////////////////////////////////////// - - { ngx_string("oclp_proc"), - NGX_RTMP_MAIN_CONF|NGX_CONF_1MORE, - ngx_rtmp_notify_on_main_event, - NGX_RTMP_MAIN_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("oclp_connect"), - NGX_RTMP_SRV_CONF|NGX_CONF_1MORE, - ngx_rtmp_notify_on_srv_event, - NGX_RTMP_SRV_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("oclp_play"), - NGX_RTMP_APP_CONF|NGX_CONF_1MORE, - ngx_rtmp_notify_on_app_event, - NGX_RTMP_APP_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("oclp_publish"), - NGX_RTMP_APP_CONF|NGX_CONF_1MORE, - ngx_rtmp_notify_on_app_event, - NGX_RTMP_APP_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("oclp_pull"), - NGX_RTMP_APP_CONF|NGX_CONF_1MORE, - ngx_rtmp_notify_on_app_event, - NGX_RTMP_APP_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("oclp_push"), - NGX_RTMP_APP_CONF|NGX_CONF_1MORE, - ngx_rtmp_notify_on_app_event, - NGX_RTMP_APP_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("oclp_stream"), - NGX_RTMP_APP_CONF|NGX_CONF_1MORE, - ngx_rtmp_notify_on_app_event, - NGX_RTMP_APP_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("oclp_meta"), - NGX_RTMP_APP_CONF|NGX_CONF_1MORE, - ngx_rtmp_notify_on_app_event, - NGX_RTMP_APP_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("oclp_record"), - NGX_RTMP_APP_CONF|NGX_CONF_1MORE, - ngx_rtmp_notify_on_app_event, - NGX_RTMP_APP_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("oclp_meta_once"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_1MORE, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_notify_app_conf_t, meta_once), - NULL }, - - { ngx_string("oclp_meta_type"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF|NGX_CONF_1MORE, - ngx_conf_set_enum_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_notify_app_conf_t, meta_type), - &ngx_rtmp_notify_meta_type }, - - ngx_null_command -}; - - -static ngx_rtmp_module_t ngx_rtmp_notify_module_ctx = { - NULL, /* preconfiguration */ - ngx_rtmp_notify_postconfiguration, /* postconfiguration */ - ngx_rtmp_notify_create_main_conf, /* create main configuration */ - ngx_rtmp_notify_init_main_conf, /* init main configuration */ - ngx_rtmp_notify_create_srv_conf, /* create server configuration */ - ngx_rtmp_notify_merge_srv_conf, /* merge server configuration */ - ngx_rtmp_notify_create_app_conf, /* create app configuration */ - ngx_rtmp_notify_merge_app_conf /* merge app configuration */ -}; - - -ngx_module_t ngx_rtmp_notify_module = { - NGX_MODULE_V1, - &ngx_rtmp_notify_module_ctx, /* module context */ - ngx_rtmp_notify_commands, /* module directives */ - NGX_RTMP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - ngx_rtmp_notify_init_process, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void * -ngx_rtmp_notify_create_main_conf(ngx_conf_t *cf) -{ - ngx_rtmp_notify_main_conf_t *omcf; - - omcf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_notify_main_conf_t)); - if (omcf == NULL) { - return NULL; - } - - return omcf; -} - -static char * -ngx_rtmp_notify_init_main_conf(ngx_conf_t *cf, void *conf) -{ - return NGX_CONF_OK; -} - -static void * -ngx_rtmp_notify_create_srv_conf(ngx_conf_t *cf) -{ - ngx_rtmp_notify_srv_conf_t *oscf; - - oscf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_notify_srv_conf_t)); - if (oscf == NULL) { - return NULL; - } - - return oscf; -} - -static char * -ngx_rtmp_notify_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) -{ - return NGX_CONF_OK; -} - -static void * -ngx_rtmp_notify_create_app_conf(ngx_conf_t *cf) -{ - ngx_rtmp_notify_app_conf_t *oacf; - ngx_uint_t n; - - oacf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_notify_app_conf_t)); - if (oacf == NULL) { - return NULL; - } - - for (n = 0; n < NGX_RTMP_OCLP_APP_MAX; ++n) { - if (ngx_array_init(&oacf->events[n], cf->pool, NGX_RTMP_MAX_OCLP, - sizeof(ngx_rtmp_notify_event_t)) == NGX_ERROR) - { - return NULL; - } - } - - oacf->meta_once = NGX_CONF_UNSET; - oacf->meta_type = NGX_CONF_UNSET_UINT; - oacf->ignore_invalid_notify = NGX_CONF_UNSET; - - return oacf; -} - -static char * -ngx_rtmp_notify_merge_app_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_rtmp_notify_app_conf_t *prev = parent; - ngx_rtmp_notify_app_conf_t *conf = child; - - ngx_conf_merge_value(conf->meta_once, prev->meta_once, 1); - ngx_conf_merge_uint_value(conf->meta_type, prev->meta_type, - NGX_RTMP_OCLP_META_VIDEO); - ngx_conf_merge_value(conf->ignore_invalid_notify, - prev->ignore_invalid_notify, 1); - - return NGX_CONF_OK; -} - -static ngx_int_t -ngx_rtmp_notify_create_event(ngx_conf_t *cf, ngx_rtmp_notify_event_t *event, - ngx_str_t *values, ngx_uint_t n) -{ - ngx_request_url_t ru; - ngx_str_t tmp; - ngx_uint_t i; - u_char *p, *last; - - for (i = 0; i < n; ++i) { - if (ngx_strncmp(values[i].data, "args=", 5) == 0) { - tmp = values[i]; - tmp.len -= 5; - tmp.data += 5; - ngx_rtmp_variable_transform_index(cf, &tmp, &event->args); -// event->args.len = values[i].len - 5; -// event->args.data = values[i].data + 5; - continue; - } - - if (ngx_strncmp(values[i].data, "groupid=", 8) == 0) { - event->groupid.len = values[i].len - 8; - event->groupid.data = values[i].data + 8; - continue; - } - - if (ngx_strncmp(values[i].data, "stage=", 6) == 0) { - p = values[i].data + 6; - last = values[i].data + values[i].len; - - while (1) { - tmp.data = p; - p = ngx_strlchr(p, last, ','); - if (p == NULL) { - tmp.len = last - tmp.data; - } else { - tmp.len = p - tmp.data; - } - - switch (tmp.len) { - case 4: - if (ngx_strncmp(tmp.data, "done", 4) == 0) { - event->stage |= NGX_RTMP_OCLP_DONE; - } else { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, - "unknown stage \"%V\"", &tmp); - return NGX_ERROR; - } - break; - case 5: - if (ngx_strncmp(tmp.data, "start", 5) == 0) { - event->stage |= NGX_RTMP_OCLP_START; - } else { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, - "unknown stage \"%V\"", &tmp); - return NGX_ERROR; - } - break; - case 6: - if (ngx_strncmp(tmp.data, "update", 6) == 0) { - event->stage |= NGX_RTMP_OCLP_UPDATE; - } else { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, - "unknown stage \"%V\"", &tmp); - return NGX_ERROR; - } - break; - default: - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, - "unknown stage \"%V\"", &tmp); - return NGX_ERROR; - } - - if (p == last || p == NULL) { - break; - } - - ++p; - } - - continue; - } - - if (ngx_strncmp(values[i].data, "timeout=", 8) == 0) { - tmp.len = values[i].len - 8; - tmp.data = values[i].data + 8; - - event->timeout = ngx_parse_time(&tmp, 0); - if (event->timeout == (ngx_msec_t) NGX_ERROR) { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, - "unknown timeout timer format \"%V\"", &tmp); - return NGX_ERROR; - } - - continue; - } - - if (ngx_strncmp(values[i].data, "update=", 7) == 0) { - tmp.len = values[i].len - 7; - tmp.data = values[i].data + 7; - - event->update = ngx_parse_time(&tmp, 0); - if (event->update == (ngx_msec_t) NGX_ERROR) { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, - "unknown cont timer format \"%V\"", &tmp); - return NGX_ERROR; - } - - continue; - } - - if (ngx_strncmp(values[i].data, "http://", 7) != 0) { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "must be http url"); - return NGX_ERROR; - } - - if (event->url.len != 0) { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "duplicate url"); - return NGX_ERROR; - } - - event->url.len = values[i].len; - event->url.data = values[i].data; - if (values[i].data[values[i].len - 1] != '/') { - event->url.data = ngx_pcalloc(cf->pool, values[i].len + 1); - event->url.len = values[i].len + 1; - ngx_snprintf(event->url.data, event->url.len, "%V/", &values[i]); - } - - if (ngx_parse_request_url(&ru, &event->url) != NGX_OK) { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "request url format error"); - return NGX_ERROR; - } - - ngx_dynamic_resolver_add_domain(&ru.host, cf->cycle); - } - - if (event->url.len == 0) { - return NGX_ERROR; - } else { - if (event->timeout == 0) { - event->timeout = 3000; - } - - if (event->update == 0) { - event->update = 60000; - } - - event->stage |= NGX_RTMP_OCLP_START; - - return NGX_OK; - } -} - -static char * -ngx_rtmp_notify_on_main_event(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_rtmp_notify_main_conf_t *omcf; - ngx_str_t *name, *value; - ngx_uint_t n; - - omcf = conf; - - value = cf->args->elts; - - name = &value[0]; - - n = 0; - - switch (name->len) { - case sizeof("on_proc") - 1: - n = NGX_RTMP_OCLP_PROC; - break; - case sizeof("oclp_proc") - 1: - n = NGX_RTMP_OCLP_PROC; - break; - } - - if (ngx_rtmp_notify_create_event(cf, &omcf->events[n], &value[1], - cf->args->nelts - 1) == NGX_ERROR) - { - return NGX_CONF_ERROR; - } - - return NGX_CONF_OK; -} - -static char * -ngx_rtmp_notify_on_srv_event(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_rtmp_notify_srv_conf_t *oscf; - ngx_str_t *name, *value; - ngx_uint_t n; - - oscf = conf; - - value = cf->args->elts; - - name = &value[0]; - - n = 0; - - switch (name->len) { - case sizeof("on_connect") - 1: - n = NGX_RTMP_OCLP_CONNECT; - break; - case sizeof("oclp_connect") - 1: - n = NGX_RTMP_OCLP_CONNECT; - break; - } - - if (ngx_rtmp_notify_create_event(cf, &oscf->events[n], &value[1], - cf->args->nelts - 1) == NGX_ERROR) - { - return NGX_CONF_ERROR; - } - - return NGX_CONF_OK; -} - -static char * -ngx_rtmp_notify_on_app_event(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_rtmp_notify_app_conf_t *oacf; - ngx_rtmp_notify_event_t *event; - ngx_str_t *name, *value; - ngx_uint_t n; - - oacf = conf; - - value = cf->args->elts; - - name = &value[0]; - - n = 0; - - if (name->data[1] == 'c') { - switch (name->len) { - case sizeof("oclp_play") - 1: - if (name->data[8] == 'y') { /* oclp_play */ - n = NGX_RTMP_OCLP_PLAY; - if (oacf->events[n].nelts != 0) { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "duplicate %V", name); - return NGX_CONF_ERROR; - } - } else if (name->data[8] == 'l') { /* oclp_pull */ - n = NGX_RTMP_OCLP_PULL; - if (oacf->events[n].nelts != 0) { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "duplicate %V", name); - return NGX_CONF_ERROR; - } - } else if (name->data[8] == 'h') { /* oclp_push */ - n = NGX_RTMP_OCLP_PUSH; - } else if (name->data[8] == 'a') { /* oclp_meta */ - n = NGX_RTMP_OCLP_META; - } - break; - case sizeof("oclp_publish") - 1: - n = NGX_RTMP_OCLP_PUBLISH; - if (oacf->events[n].nelts != 0) { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "duplicate %V", name); - return NGX_CONF_ERROR; - } - break; - case sizeof("oclp_stream") - 1: - if (name->data[5] == 's') { /* oclp_stream */ - n = NGX_RTMP_OCLP_STREAM; - } else if (name->data[5] == 'r') { /* oclp_record */ - n = NGX_RTMP_OCLP_RECORD; - } - - if (oacf->events[n].nelts != 0) { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "duplicate %V", name); - return NGX_CONF_ERROR; - } - break; - } - } else { - switch (name->len) { - case sizeof("on_play") - 1: - if (name->data[6] == 'y') { /* on_play */ - n = NGX_RTMP_OCLP_PLAY; - if (oacf->events[n].nelts != 0) { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "duplicate %V", name); - return NGX_CONF_ERROR; - } - } else if (name->data[6] == 'l') { /* on_pull */ - n = NGX_RTMP_OCLP_PULL; - if (oacf->events[n].nelts != 0) { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "duplicate %V", name); - return NGX_CONF_ERROR; - } - } else if (name->data[6] == 'h') { /* on_push */ - n = NGX_RTMP_OCLP_PUSH; - } else if (name->data[6] == 'a') { /* on_meta */ - n = NGX_RTMP_OCLP_META; - } - break; - case sizeof("on_publish") - 1: - n = NGX_RTMP_OCLP_PUBLISH; - if (oacf->events[n].nelts != 0) { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "duplicate %V", name); - return NGX_CONF_ERROR; - } - break; - case sizeof("on_stream") - 1: - if (name->data[3] == 's') { /* on_stream */ - n = NGX_RTMP_OCLP_STREAM; - } else if (name->data[3] == 'r') { /* on_record */ - n = NGX_RTMP_OCLP_RECORD; - } - - if (oacf->events[n].nelts != 0) { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "duplicate %V", name); - return NGX_CONF_ERROR; - } - break; - } - } - - - if (oacf->events[n].nelts >= NGX_RTMP_MAX_OCLP) { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "too much %V events", name); - return NGX_CONF_ERROR; - } - - event = ngx_array_push(&oacf->events[n]); - ngx_memzero(event, sizeof(ngx_rtmp_notify_event_t)); - if (ngx_rtmp_notify_create_event(cf, event, &value[1], cf->args->nelts - 1) - == NGX_ERROR) - { - return NGX_CONF_ERROR; - } - - return NGX_CONF_OK; -} - - -static void -ngx_rtmp_notify_init_process_url(ngx_str_t *url, ngx_pool_t *pool, - ngx_rtmp_notify_event_t *event) -{ - size_t len; - u_char *p; - - len = event->url.len + sizeof("?call=init_process&worker_id=") - 1 - + sizeof("256") - 1; - - url->data = ngx_pcalloc(pool, len); - if (url->data == NULL) { - return; - } - - p = url->data; - p = ngx_snprintf(p, len, "%V?call=init_process&worker_id=%ui", - &event->url, ngx_worker); - url->len = p - url->data; -} - -static void -ngx_rtmp_notify_init_process_handle(ngx_netcall_ctx_t *nctx, ngx_int_t code) -{ - if (code != NGX_HTTP_OK) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, - "notify init process notify error: %i", code); - } - - return; -} - -static void -ngx_rtmp_notify_init_process_create(ngx_event_t *ev) -{ - ngx_netcall_ctx_t *nctx; - - nctx = ev->data; - - ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, "notify init process create"); - - ngx_netcall_create(nctx, ngx_cycle->log); -} - -static ngx_int_t -ngx_rtmp_notify_init_process(ngx_cycle_t *cycle) -{ - ngx_rtmp_notify_main_conf_t *omcf; - ngx_rtmp_notify_event_t *event; - ngx_rtmp_conf_ctx_t *ctx; - ngx_netcall_ctx_t *nctx; - ngx_event_t *ev; - - if (ngx_process != NGX_PROCESS_WORKER && - ngx_process != NGX_PROCESS_SINGLE) - { - return NGX_OK; - } - - if (ngx_rtmp_core_main_conf == NULL) { - return NGX_OK; - } - - ctx = (ngx_rtmp_conf_ctx_t *) ngx_get_conf(cycle->conf_ctx, - ngx_rtmp_module); - omcf = (ngx_rtmp_notify_main_conf_t *) - ctx->main_conf[ngx_rtmp_notify_module.ctx_index]; - - if (omcf->events[NGX_RTMP_OCLP_PROC].url.len == 0) { - return NGX_OK; - } - - event = &omcf->events[NGX_RTMP_OCLP_PROC]; - - nctx = ngx_netcall_create_ctx(NGX_RTMP_OCLP_PROC, &event->groupid, - event->stage, event->timeout, event->update, 0); - if (nctx == NULL) { - return NGX_ERROR; - } - - ngx_rtmp_notify_init_process_url(&nctx->url, nctx->pool, event); - nctx->handler = ngx_rtmp_notify_init_process_handle; - nctx->data = nctx; - - ev = &nctx->ev; - ev->handler = ngx_rtmp_notify_init_process_create; - - ngx_post_event(ev, &ngx_rtmp_init_queue); - - return NGX_OK; -} - -static void -ngx_rtmp_notify_common_url(ngx_str_t *url, ngx_rtmp_session_t *s, - ngx_rtmp_notify_event_t *event, ngx_netcall_ctx_t *nctx, ngx_uint_t stage) -{ - ngx_request_url_t ru; - size_t len; - u_char *p, *buf; - ngx_live_record_ctx_t *lrctx; - unsigned fill = 0; - ngx_str_t args; - - ngx_memzero(&ru, sizeof(ngx_request_url_t)); - ngx_parse_request_url(&ru, &event->url); - - len = NGX_NETCALL_MAX_URL_LEN; - buf = url->data; - p = ngx_snprintf(buf, len , "%V", &event->url); - if (fill) { - *p++ = '/'; - } - len -= p - buf; - buf = p; - - if (ru.args.len) { // url already has args - p = ngx_snprintf(buf, len, - "&call=%s&act=%s&domain=%V&app=%V&name=%V&clientid=%D", - ngx_rtmp_notify_app_type[nctx->type], - ngx_rtmp_notify_stage[stage], - &s->domain, &s->app, &s->name, s->number); - } else { - p = ngx_snprintf(buf, len, - "?call=%s&act=%s&domain=%V&app=%V&name=%V&clientid=%D", - ngx_rtmp_notify_app_type[nctx->type], - ngx_rtmp_notify_stage[stage], - &s->domain, &s->app, &s->name, s->number); - } - len -= p - buf; - buf = p; - - if (nctx->type == NGX_RTMP_OCLP_RECORD && stage != NGX_RTMP_OCLP_START) { - lrctx = ngx_rtmp_get_module_ctx(s, ngx_live_record_module); - p = ngx_snprintf(buf, len, "&begintime=%M&endtime=%M&index=%V&file=%V", - lrctx->begintime, lrctx->endtime, &lrctx->index.name, - &lrctx->file.name); - - len -= p - buf; - buf = p; - } - - if (event->groupid.len) { - p = ngx_snprintf(buf, len, "&groupid=%V", &event->groupid); - len -= p - buf; - buf = p; - } - - if (event->args.len) { - ngx_rtmp_fetch_variable(s, s->pool, &event->args, &args); - if (args.len > 0) { - p = ngx_snprintf(buf, len, "&%V", &args); - len -= p - buf; - buf = p; - } - } - - url->len = p - url->data; -} - -static void -ngx_rtmp_notify_common_timer(ngx_event_t *ev) -{ - ngx_netcall_ctx_t *nctx; - - nctx = ev->data; - - ngx_log_error(NGX_LOG_INFO, ev->log, 0, "notify %s update create %V", - ngx_rtmp_notify_app_type[nctx->type], &nctx->url); - - ngx_netcall_create(nctx, ev->log); -} - -static void -ngx_rtmp_notify_common_update_handle(ngx_netcall_ctx_t *nctx, ngx_int_t code) -{ - ngx_event_t *ev; - - ev = &nctx->ev; - ev->handler = ngx_rtmp_notify_common_timer; - - if (code != NGX_HTTP_OK) { - ngx_log_error(NGX_LOG_ERR, ev->log, 0, - "notify %s update notify error: %i", - ngx_rtmp_notify_app_type[nctx->type], code); - } - - ngx_add_timer(ev, nctx->update); -} - -static void -ngx_rtmp_notify_common_update_create(ngx_rtmp_session_t *s, - ngx_netcall_ctx_t *nctx) -{ - ngx_rtmp_notify_app_conf_t *oacf; - ngx_rtmp_notify_event_t *event; - ngx_event_t *ev; - - if ((nctx->stage & NGX_RTMP_OCLP_UPDATE) == NGX_RTMP_OCLP_UPDATE) { - oacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module); - - event = oacf->events[nctx->type].elts; - event += nctx->idx; - - ngx_rtmp_notify_common_url(&nctx->url, s, event, nctx, - NGX_RTMP_OCLP_UPDATE); - nctx->handler = ngx_rtmp_notify_common_update_handle; - - ev = &nctx->ev; - ev->data = nctx; - ev->handler = ngx_rtmp_notify_common_timer; - - ngx_add_timer(ev, nctx->update); - } -} - -static void -ngx_rtmp_notify_common_done(ngx_rtmp_session_t *s, ngx_netcall_ctx_t *nctx) -{ - ngx_rtmp_notify_app_conf_t *oacf; - ngx_rtmp_notify_event_t *event; - - if (nctx == NULL) { - return; - } - - if ((nctx->stage & NGX_RTMP_OCLP_DONE) == NGX_RTMP_OCLP_DONE) { - oacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module); - event = oacf->events[nctx->type].elts; - - ngx_rtmp_notify_common_url(&nctx->url, s, event, nctx, - NGX_RTMP_OCLP_DONE); - - ngx_log_error(NGX_LOG_INFO, s->log, 0, - "notify %s done create %V %p", - ngx_rtmp_notify_app_type[nctx->type], &nctx->url, nctx); - - ngx_netcall_create(nctx, s->log); - } - - ngx_netcall_destroy(nctx); -} - -static void -ngx_rtmp_notify_pnotify_start_handle(ngx_netcall_ctx_t *nctx, ngx_int_t code) -{ - ngx_rtmp_session_t *s; - ngx_rtmp_notify_ctx_t *octx; - ngx_rtmp_notify_app_conf_t *oacf; - - s = nctx->data; - - octx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_notify_module); - - oacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module); - - s->notify_status = code; - - if (code < NGX_HTTP_OK || code > NGX_HTTP_SPECIAL_RESPONSE) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "notify %s start notify error: %i", - ngx_rtmp_notify_app_type[nctx->type], code); - - if (code != -1 || !oacf->ignore_invalid_notify) { - goto error; - } - - goto next; - } - -next: - if (octx->type == NGX_RTMP_OCLP_PUBLISH) { - if (next_publish(s, &octx->publish_v) != NGX_OK) { - goto error; - } - } else { - if (next_play(s, &octx->play_v) != NGX_OK) { - goto error; - } - } - - ngx_rtmp_notify_common_update_create(s, nctx); - - return; - -error: - if (octx->type == NGX_RTMP_OCLP_PUBLISH) { - ngx_rtmp_send_status(s, "NetStream.Publish.Forbidden", "status", - "Publish stream Forbidden"); - } else if (s->live_type == NGX_RTMP_LIVE) { - s->status = 403; - ngx_rtmp_send_status(s, "NetStream.Play.Forbidden", "status", - "Play stream Forbidden"); - } - s->finalize_reason = NGX_LIVE_OCLP_NOTIFY_ERR; - ngx_rtmp_finalize_session(s); -} - -static ngx_int_t -ngx_rtmp_notify_pnotify_start(ngx_rtmp_session_t *s, ngx_uint_t type) -{ - ngx_rtmp_notify_app_conf_t *oacf; - ngx_rtmp_notify_event_t *event; - ngx_rtmp_notify_ctx_t *ctx; - ngx_netcall_ctx_t *nctx; - - oacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module); - - if (oacf->events[type].nelts == 0) { - return NGX_DECLINED; - } - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_notify_module); - if (ctx == NULL) { - ctx = ngx_pcalloc(s->pool, sizeof(ngx_rtmp_notify_ctx_t)); - if (ctx == NULL) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, "palloc notify ctx failed"); - return NGX_ERROR; - } - ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_notify_module); - } - - event = oacf->events[type].elts; - - nctx = ngx_netcall_create_ctx(type, &event->groupid, - event->stage, event->timeout, event->update, 0); - nctx->ev.log = s->log; - - ngx_rtmp_notify_common_url(&nctx->url, s, event, nctx, - NGX_RTMP_OCLP_START); - nctx->handler = ngx_rtmp_notify_pnotify_start_handle; - nctx->data = s; - - ctx->nctx = nctx; - ctx->type = type; - - ngx_log_error(NGX_LOG_INFO, s->log, 0, "notify %s start create %V", - ngx_rtmp_notify_app_type[nctx->type], &nctx->url); - - ngx_netcall_create(nctx, s->log); - - return NGX_OK; -} - -static void -ngx_rtmp_notify_pnotify_done(ngx_rtmp_session_t *s) -{ - ngx_rtmp_notify_ctx_t *ctx; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_notify_module); - if (ctx == NULL) { - return; - } - - ngx_rtmp_notify_common_done(s, ctx->nctx); -} - -static void -ngx_rtmp_notify_relay_error(ngx_rtmp_session_t *s, ngx_uint_t status) -{ - ngx_rtmp_core_ctx_t *cctx; - size_t i; - - for (i = 0; ngx_rtmp_notify_relay_errors[i].status; ++i) { - if (status != ngx_rtmp_notify_relay_errors[i].status) { - continue; - } - - if (s->publishing) { // relay pull - cctx = s->live_stream->play_ctx; - } else { // relay push - cctx = s->live_stream->publish_ctx; - } - - for (; cctx; cctx = cctx->next) { - if (!cctx->session->static_pull) { - cctx->session->status = status; - cctx->session->finalize_reason = NGX_LIVE_RELAY_TRANSIT; - ngx_rtmp_finalize_session(cctx->session); - } - } - } -} - -static void -ngx_rtmp_notify_relay_start_handle(ngx_netcall_ctx_t *nctx, ngx_int_t code) -{ - ngx_rtmp_session_t *s; - ngx_live_relay_t relay; - ngx_live_relay_url_t *url; - ngx_str_t *local_name; - ngx_str_t *local_domain; - u_char *p, *last; - ngx_rtmp_notify_ctx_t *octx; - ngx_live_relay_ctx_t *ctx; - - static ngx_str_t location = ngx_string("location"); - static ngx_str_t domain = ngx_string("domain"); - - s = nctx->data; - // relay pull, no player or relay push no publisher - if ((s->publishing && s->live_stream->play_ctx == NULL) - || (!s->publishing && s->live_stream->publish_ctx == NULL)) - { - return; - } - - s->notify_status = code; - - if (code == -1) { // wait for notify relay reconnect - ngx_log_error(NGX_LOG_ERR, s->log, 0, "notify relay start failed"); - - s->finalize_reason = NGX_LIVE_OCLP_RELAY_ERR; - ngx_rtmp_finalize_session(s); // only reconnect immediately - - return; - } - - if (code >= 400) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, - "notify: relay_start_handle| " - "notify error: %i", code); - - if (s->publishing) { // relay pull - ngx_rtmp_notify_relay_error(s, 404); - } else { // relay push - ngx_rtmp_notify_relay_error(s, 400); - } - s->finalize_reason = NGX_LIVE_OCLP_RELAY_ERR; - ngx_rtmp_finalize_session(s); - - return; - } - - if (code == NGX_HTTP_OK) { // successd but no need to relay - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - ctx->giveup = 1; - s->finalize_reason = NGX_LIVE_NORMAL_CLOSE; - ngx_rtmp_finalize_session(s); - return; - } - - /* redirect */ - local_name = ngx_netcall_header(nctx, &location); - if (local_name == NULL) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "notify relay start has no Location when redirect"); - s->finalize_reason = NGX_LIVE_OCLP_PARA_ERR; - ngx_rtmp_finalize_session(s); - - return; - } - - ngx_memzero(&relay, sizeof(ngx_live_relay_t)); - if (ngx_array_init(&relay.urls, s->pool, 1, sizeof(ngx_live_relay_url_t)) - != NGX_OK) - { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "notify relay start, init relay urls failed"); - ngx_rtmp_finalize_session(s); - - return; - } - - url = ngx_array_push(&relay.urls); - if (url == NULL) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "notify relay start, alloc url from relay urls failed"); - ngx_rtmp_finalize_session(s); - - return; - } - ngx_memzero(url, sizeof(ngx_live_relay_url_t)); - relay.tag = &ngx_rtmp_notify_module; - - if (ngx_parse_request_url(&url->url, local_name) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "notify relay start, request url format error: %V", &location); - s->finalize_reason = NGX_LIVE_OCLP_PARA_ERR; - ngx_rtmp_finalize_session(s); - - return; - } - - if (ngx_strncasecmp(url->url.scheme.data, (u_char *) "rtmp://", 7) == 0) { - url->relay_type = NGX_LIVE_RELAY_RTMP; - } - - url->port = ngx_request_port(&url->url.scheme, &url->url.port); - if (url->port == 0) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "notify relay start, request url port error"); - s->finalize_reason = NGX_LIVE_OCLP_PARA_ERR; - ngx_rtmp_finalize_session(s); - - return; - } - - // set domain - local_domain = ngx_netcall_header(nctx, &domain); - if (local_domain && local_domain->len) { - relay.domain = *local_domain; - } - - if (url->url.path.len == 0) { // no app and stream - goto relay_create; - } - - p = url->url.path.data; - last = url->url.path.data + url->url.path.len; - - // set app - relay.app.data = p; - p = ngx_strlchr(p, last, '/'); - if (p == NULL) { // only has app - relay.app.len = last - relay.app.data; - goto relay_create; - } else { - relay.app.len = p - relay.app.data; - } - - ++p; - if (p == last) { - goto relay_create; - } - - // set stream name - relay.name.data = p; - relay.name.len = last - relay.name.data; - - // set args - if (url->url.args.len) { - relay.pargs = url->url.args; - } - -relay_create: - octx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_notify_module); - ngx_rtmp_notify_common_update_create(s, octx->nctx); - - ngx_live_relay_create(s, &relay); - - return; -} - -static void -ngx_rtmp_notify_relay_handler(ngx_event_t *ev) -{ - ngx_rtmp_session_t *s; - ngx_live_relay_app_conf_t *lracf; - ngx_live_relay_ctx_t *ctx; - ngx_rtmp_notify_ctx_t *octx; - ngx_rtmp_notify_event_t *event; - ngx_netcall_ctx_t *nctx; - - s = ev->data; - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - - octx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_notify_module); - event = octx->event; - - if (!ctx->failed_delay && ev->timedout) { // connect timeout - ngx_log_error(NGX_LOG_ERR, s->log, NGX_ETIMEDOUT, - "notify relay, relay timeout"); - s->finalize_reason = NGX_LIVE_RELAY_TIMEOUT; - ngx_rtmp_finalize_session(s); - - if (octx->nctx->hcr) { - ngx_http_client_detach(octx->nctx->hcr); - octx->nctx->hcr = NULL; - - if (octx->nctx->ev.timer_set) { - ngx_del_timer(&octx->nctx->ev); - } - - if (octx->nctx->ev.posted) { - ngx_delete_posted_event(&octx->nctx->ev); - } - } - - return; - } - - // relay pull, no player or relay push no publisher - if ((s->publishing && s->live_stream->play_ctx == NULL) - || (!s->publishing && s->live_stream->publish_ctx == NULL)) - { - return; - } - - lracf = ngx_rtmp_get_module_app_conf(s, ngx_live_relay_module); - - // this timer control start netcall until relay create success - ngx_add_timer(&ctx->reconnect, lracf->relay_reconnect); - - nctx = ngx_netcall_create_ctx(octx->type, &event->groupid, event->stage, - event->timeout, event->update, 0); - if (nctx == NULL) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, "notify relay, create nctx failed"); - ngx_rtmp_finalize_session(s); - - return; - } - nctx->ev.log = s->log; - - ngx_rtmp_notify_common_url(&nctx->url, s, event, nctx, - NGX_RTMP_OCLP_START); - nctx->handler = ngx_rtmp_notify_relay_start_handle; - nctx->data = s; - - ngx_log_error(NGX_LOG_INFO, s->log, 0, "notify %s start create %V", - ngx_rtmp_notify_app_type[nctx->type], &nctx->url); - - octx->nctx = nctx; - - ngx_netcall_create(nctx, s->log); -} - -static ngx_int_t -ngx_rtmp_notify_relay_start(ngx_rtmp_session_t *s, ngx_rtmp_notify_event_t *event, - ngx_uint_t type, unsigned publishing) -{ - ngx_rtmp_session_t *rs; - ngx_live_relay_ctx_t *ctx, *pctx; - ngx_live_relay_app_conf_t *lracf; - ngx_rtmp_notify_ctx_t *octx; - - rs = ngx_rtmp_create_relay_session(s, &ngx_rtmp_notify_module); - if (rs == NULL) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "notify relay start, create relay session failed"); - return NGX_DECLINED; - } - rs->publishing = publishing; - rs->groupid = event->groupid; - rs->live_stream = s->live_stream; - ngx_live_create_ctx(rs, publishing); - - octx = ngx_pcalloc(rs->pool, sizeof(ngx_rtmp_notify_ctx_t)); - if (octx == NULL) { - ngx_log_error(NGX_LOG_ERR, rs->log, 0, - "notify relay start, create notify ctx failed"); - ngx_rtmp_finalize_session(rs); - - return NGX_OK; - } - ngx_rtmp_set_ctx(rs, octx, ngx_rtmp_notify_module); - octx->event = event; - octx->type = type; - - ctx = ngx_rtmp_get_module_ctx(rs, ngx_live_relay_module); - ctx->reconnect.log = rs->log; - ctx->reconnect.data = rs; - ctx->reconnect.handler = ngx_rtmp_notify_relay_handler; - - if (s->publishing != rs->publishing) { - ngx_post_event(&ctx->reconnect, &ngx_posted_events); - return NGX_OK; - } - - // normal publisher close, need to trigger pull - if (s->publishing && !s->relay) { - ngx_post_event(&ctx->reconnect, &ngx_posted_events); - return NGX_OK; - } - - // reconnect - pctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - if (pctx->successd) { // prev relay successd - ngx_post_event(&ctx->reconnect, &ngx_posted_events); - return NGX_OK; - } - - ctx->idx = pctx->idx; - ctx->failed_reconnect = pctx->failed_reconnect; - - lracf = ngx_rtmp_get_module_app_conf(rs, ngx_live_relay_module); - - if (!pctx->reconnect.timer_set) { // prev relay timeout - ctx->failed_reconnect = ngx_min(pctx->failed_reconnect * 2, - lracf->relay_reconnect); - ngx_post_event(&ctx->reconnect, &ngx_posted_events); - return NGX_OK; - } - - if (pctx->failed_reconnect) { - ctx->failed_reconnect = ngx_min(pctx->failed_reconnect * 2, - lracf->relay_reconnect); - } else { - ctx->failed_reconnect = lracf->failed_reconnect; - } - - ctx->failed_delay = 1; - ngx_add_timer(&ctx->reconnect, ctx->failed_reconnect); - - return NGX_OK; -} - -static void -ngx_rtmp_notify_relay_done(ngx_rtmp_session_t *s) -{ - ngx_rtmp_notify_ctx_t *octx; - ngx_netcall_ctx_t *nctx; - - octx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_notify_module); - nctx = octx->nctx; - ngx_rtmp_notify_common_done(s, nctx); -} - -static void -ngx_rtmp_notify_stream_start_handle(ngx_netcall_ctx_t *nctx, ngx_int_t code) -{ - ngx_live_stream_t *st; - ngx_rtmp_session_t *s; - - st = nctx->data; - - if (code != NGX_HTTP_OK) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, - "notify stream start notify error: %i", code); - - return; - } - - if (st->play_ctx) { - s = st->play_ctx->session; - } else if (st->publish_ctx) { - s = st->publish_ctx->session; - } else { - ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, - "notify stream start handle but all stream session close"); - return; - } - - ngx_rtmp_notify_common_update_create(s, nctx); -} - -void -ngx_rtmp_notify_stream_start(ngx_rtmp_session_t *s) -{ - ngx_rtmp_notify_app_conf_t *oacf; - ngx_rtmp_notify_event_t *event; - ngx_netcall_ctx_t *nctx; - - oacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module); - - if (oacf->events[NGX_RTMP_OCLP_STREAM].nelts == 0) { - return; - } - - nctx = s->live_stream->stream_nctx; - if (nctx) { /* stream start has been sent */ - return; - } - - event = oacf->events[NGX_RTMP_OCLP_STREAM].elts; - - if ((event->stage & NGX_RTMP_OCLP_START) == NGX_RTMP_OCLP_START) { - nctx = ngx_netcall_create_ctx(NGX_RTMP_OCLP_STREAM, &event->groupid, - event->stage, event->timeout, event->update, 0); - - ngx_rtmp_notify_common_url(&nctx->url, s, event, nctx, - NGX_RTMP_OCLP_START); - nctx->handler = ngx_rtmp_notify_stream_start_handle; - nctx->data = s->live_stream; - - s->live_stream->stream_nctx = nctx; - - ngx_log_error(NGX_LOG_INFO, s->log, 0, - "notify stream start create %V", &nctx->url); - - ngx_netcall_create(nctx, ngx_cycle->log); - } -} - -void -ngx_rtmp_notify_stream_done(ngx_rtmp_session_t *s) -{ - ngx_netcall_ctx_t *nctx; - - nctx = s->live_stream->stream_nctx; - ngx_rtmp_notify_common_done(s, nctx); - s->live_stream->stream_nctx = NULL; -} - -static void -ngx_rtmp_notify_record_start_handle(ngx_netcall_ctx_t *nctx, ngx_int_t code) -{ - ngx_rtmp_session_t *s; - ngx_live_record_ctx_t *ctx; - - s = nctx->data; - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_record_module); - - if (code == NGX_HTTP_OK) { - ctx->open = 1; - } else if (code != -1) { - ctx->open = 0; - } - - ngx_log_error(NGX_LOG_INFO, s->log, 0, - "notify record receive code %i, open: %d", code, ctx->open); - - if (next_record_start(s) != NGX_OK) { - ngx_rtmp_finalize_session(s); - } -} - -static ngx_int_t -ngx_rtmp_notify_record_start(ngx_rtmp_session_t *s) -{ - ngx_rtmp_notify_app_conf_t *oacf; - ngx_netcall_ctx_t *nctx; - ngx_rtmp_notify_ctx_t *octx; - ngx_rtmp_notify_event_t *event; - - oacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module); - - if (oacf->events[NGX_RTMP_OCLP_RECORD].nelts == 0) { - goto next; - } - - octx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_notify_module); - if (octx == NULL) { - octx = ngx_pcalloc(s->pool, sizeof(ngx_rtmp_notify_ctx_t)); - if (octx == NULL) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, "pcalloc notify ctx failed"); - goto next; - } - ngx_rtmp_set_ctx(s, octx, ngx_rtmp_notify_module); - } - - event = oacf->events[NGX_RTMP_OCLP_RECORD].elts; - - nctx = ngx_netcall_create_ctx(NGX_RTMP_OCLP_RECORD, &event->groupid, - event->stage, event->timeout, event->update, 0); - - ngx_rtmp_notify_common_url(&nctx->url, s, event, nctx, - NGX_RTMP_OCLP_START); - nctx->handler = ngx_rtmp_notify_record_start_handle; - nctx->data = s; - - octx->rctx = nctx; - octx->type = NGX_RTMP_OCLP_RECORD; - - ngx_log_error(NGX_LOG_INFO, s->log, 0, "notify record start create %V", - &nctx->url); - - ngx_netcall_create(nctx, s->log); - - return NGX_OK; - -next: - return next_record_start(s); -} - -static void -ngx_rtmp_notify_record_update_handle(ngx_netcall_ctx_t *nctx, ngx_int_t code) -{ - ngx_rtmp_session_t *s; - - s = nctx->data; - - if (code != NGX_HTTP_OK) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "notify record update notify error: %i", code); - } -} - -static ngx_int_t -ngx_rtmp_notify_record_update(ngx_rtmp_session_t *s) -{ - ngx_rtmp_notify_app_conf_t *oacf; - ngx_netcall_ctx_t *nctx; - ngx_rtmp_notify_ctx_t *octx; - ngx_rtmp_notify_event_t *event; - - octx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_notify_module); - if (octx == NULL || octx->rctx == NULL) { - goto next; - } - - nctx = octx->rctx; - - if ((nctx->stage & NGX_RTMP_OCLP_UPDATE) == NGX_RTMP_OCLP_UPDATE) { - oacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module); - event = oacf->events[nctx->type].elts; - - ngx_rtmp_notify_common_url(&nctx->url, s, event, nctx, - NGX_RTMP_OCLP_UPDATE); - nctx->handler = ngx_rtmp_notify_record_update_handle; - - ngx_log_error(NGX_LOG_INFO, s->log, 0, - "notify record update create %V %p", &nctx->url, nctx); - - ngx_netcall_create(nctx, s->log); - } - -next: - return next_record_update(s); -} - -static ngx_int_t -ngx_rtmp_notify_record_done(ngx_rtmp_session_t *s) -{ - ngx_rtmp_notify_app_conf_t *oacf; - ngx_netcall_ctx_t *nctx; - ngx_rtmp_notify_ctx_t *octx; - ngx_rtmp_notify_event_t *event; - - octx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_notify_module); - if (octx == NULL || octx->rctx == NULL) { - goto next; - } - - nctx = octx->rctx; - - if ((nctx->stage & NGX_RTMP_OCLP_DONE) == NGX_RTMP_OCLP_DONE) { - oacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module); - event = oacf->events[nctx->type].elts; - - ngx_rtmp_notify_common_url(&nctx->url, s, event, nctx, - NGX_RTMP_OCLP_DONE); - - ngx_log_error(NGX_LOG_INFO, s->log, 0, - "notify record done create %V %p", &nctx->url, nctx); - - ngx_netcall_create(nctx, s->log); - } - - ngx_netcall_destroy(nctx); - -next: - return next_record_done(s); -} - -static ngx_int_t -ngx_rtmp_notify_push(ngx_rtmp_session_t *s) -{ - ngx_rtmp_notify_app_conf_t *oacf; - ngx_rtmp_notify_event_t *event; - ngx_uint_t i; - - oacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module); - if (oacf->events[NGX_RTMP_OCLP_PUSH].nelts == 0) { // not configured - goto next; - } - - if (s->relay && s->static_pull == 0) { - goto next; - } - - event = oacf->events[NGX_RTMP_OCLP_PUSH].elts; - for (i = 0; i < oacf->events[NGX_RTMP_OCLP_PUSH].nelts; ++i, ++event) { - ngx_rtmp_notify_relay_start(s, event, NGX_RTMP_OCLP_PUSH, 0); - } - -next: - return next_push(s); -} - -static ngx_int_t -ngx_rtmp_notify_pull(ngx_rtmp_session_t *s) -{ - ngx_rtmp_notify_app_conf_t *oacf; - ngx_rtmp_notify_event_t *event; - - oacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module); - if (oacf->events[NGX_RTMP_OCLP_PULL].nelts == 0) { // not configured - goto next; - } - - if (!s->publishing && s->relay) { // relay push - goto next; - } - - if (s->live_stream->publish_ctx) { // already has publisher - goto next; - } - - event = oacf->events[NGX_RTMP_OCLP_PULL].elts; - - if (ngx_rtmp_notify_relay_start(s, event, NGX_RTMP_OCLP_PULL, 1) == NGX_OK) { - return NGX_OK; - } - -next: - return next_pull(s); -} - -static ngx_int_t -ngx_rtmp_notify_push_close(ngx_rtmp_session_t *s) -{ - ngx_live_relay_ctx_t *ctx; - ngx_rtmp_notify_ctx_t *octx; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - if (ctx->tag != &ngx_rtmp_notify_module) { - goto next; - } - - ngx_rtmp_notify_relay_done(s); // nctx will close in relay done - - // relay push and has publisher in stream - if (!ctx->giveup && s->live_stream->publish_ctx) { - octx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_notify_module); - - ngx_rtmp_notify_relay_start(s, octx->event, octx->type, 0); - } - -next: - return next_push_close(s); -} - -static ngx_int_t -ngx_rtmp_notify_pull_close(ngx_rtmp_session_t *s) -{ - ngx_live_relay_ctx_t *ctx; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - if (ctx == NULL) { - goto next; - } - - if (ctx->tag != &ngx_rtmp_notify_module) { - goto next; - } - - ngx_rtmp_notify_relay_done(s); // nctx will close in relay done - -next: - return next_pull_close(s); -} - -static ngx_int_t -ngx_rtmp_notify_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, ngx_chain_t *in) -{ - ngx_rtmp_notify_app_conf_t *oacf; - ngx_rtmp_notify_event_t *event; - ngx_uint_t i; - - if (ngx_rtmp_is_codec_header(in)) { - oacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module); - - if (oacf->meta_once && s->live_stream->notify_meta) { - return NGX_OK; - } - - switch (oacf->meta_type) { - case NGX_RTMP_OCLP_META_VIDEO: - if (h->type == NGX_RTMP_MSG_AUDIO) { - return NGX_OK; - } - - break; - case NGX_RTMP_OCLP_META_AUDIO: - if (h->type == NGX_RTMP_MSG_VIDEO) { - return NGX_OK; - } - - break; - default: - break; - } - - s->live_stream->notify_meta = 1; - - event = oacf->events[NGX_RTMP_OCLP_META].elts; - for (i = 0; i < oacf->events[NGX_RTMP_OCLP_META].nelts; ++i, ++event) { - ngx_rtmp_notify_relay_start(s, event, NGX_RTMP_OCLP_META, 0); - } - } - - return NGX_OK; -} - -static ngx_int_t -ngx_rtmp_notify_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v) -{ - ngx_rtmp_notify_ctx_t *octx; - - if (s->relay || s->interprocess) { - goto next; - } - - switch (ngx_rtmp_notify_pnotify_start(s, NGX_RTMP_OCLP_PUBLISH)) { - case NGX_OK: - break; - case NGX_DECLINED: - goto next; - default: - return NGX_ERROR; - } - - octx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_notify_module); - ngx_memcpy(&octx->publish_v, v, sizeof(ngx_rtmp_publish_t)); - - return NGX_OK; - -next: - return next_publish(s, v); -} - -static ngx_int_t -ngx_rtmp_notify_play(ngx_rtmp_session_t *s, ngx_rtmp_play_t *v) -{ - ngx_rtmp_notify_ctx_t *octx; - - if (s->relay || s->interprocess) { - goto next; - } - - switch (ngx_rtmp_notify_pnotify_start(s, NGX_RTMP_OCLP_PLAY)) { - case NGX_OK: - break; - case NGX_DECLINED: - goto next; - default: - return NGX_ERROR; - } - - octx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_notify_module); - ngx_memcpy(&octx->play_v, v, sizeof(ngx_rtmp_play_t)); - - return NGX_OK; - -next: - return next_play(s, v); -} - -static ngx_int_t -ngx_rtmp_notify_close_stream(ngx_rtmp_session_t *s, ngx_rtmp_close_stream_t *v) -{ - if (s->relay || s->interprocess) { - goto next; - } - - ngx_rtmp_notify_pnotify_done(s); - -next: - return next_close_stream(s, v); -} - -static ngx_int_t -ngx_rtmp_notify_postconfiguration(ngx_conf_t *cf) -{ - ngx_rtmp_core_main_conf_t *cmcf; - ngx_rtmp_handler_pt *h; - - cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module); - - h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_AUDIO]); - *h = ngx_rtmp_notify_av; - - h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_VIDEO]); - *h = ngx_rtmp_notify_av; - - /* record */ - next_record_start = ngx_live_record_start; - ngx_live_record_start = ngx_rtmp_notify_record_start; - - next_record_update = ngx_live_record_update; - ngx_live_record_update = ngx_rtmp_notify_record_update; - - next_record_done = ngx_live_record_done; - ngx_live_record_done = ngx_rtmp_notify_record_done; - - /* pull & push */ - next_push = ngx_live_push; - ngx_live_push = ngx_rtmp_notify_push; - - next_pull = ngx_live_pull; - ngx_live_pull = ngx_rtmp_notify_pull; - - next_push_close = ngx_live_push_close; - ngx_live_push_close = ngx_rtmp_notify_push_close; - - next_pull_close = ngx_live_pull_close; - ngx_live_pull_close = ngx_rtmp_notify_pull_close; - - /* publish & play */ - next_publish = ngx_rtmp_publish; - ngx_rtmp_publish = ngx_rtmp_notify_publish; - - next_play = ngx_rtmp_play; - ngx_rtmp_play = ngx_rtmp_notify_play; - - next_close_stream = ngx_rtmp_close_stream; - ngx_rtmp_close_stream = ngx_rtmp_notify_close_stream; - - return NGX_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_notify_module.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_notify_module.h deleted file mode 100644 index 889d10bb5c..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_notify_module.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - * - */ - - -#ifndef _NGX_RTMP_OCLP_MODULE_H_INCLUDED_ -#define _NGX_RTMP_OCLP_MODULE_H_INCLUDED_ - - -#include "ngx_rtmp.h" -#include "ngx_netcall.h" - - -void ngx_rtmp_notify_stream_start(ngx_rtmp_session_t *s); -void ngx_rtmp_notify_stream_done(ngx_rtmp_session_t *s); - - -#endif diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_proxy_protocol.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_proxy_protocol.c deleted file mode 100644 index 1b240556b1..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_proxy_protocol.c +++ /dev/null @@ -1,197 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include -#include -#include "ngx_rtmp_proxy_protocol.h" - - -static void ngx_rtmp_proxy_protocol_recv(ngx_event_t *rev); - - -void -ngx_rtmp_proxy_protocol(ngx_rtmp_session_t *s) -{ - ngx_event_t *rev; - ngx_connection_t *c; - - c = s->connection; - rev = c->read; - rev->handler = ngx_rtmp_proxy_protocol_recv; - - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->log, 0, - "proxy_protocol: start"); - - if (rev->ready) { - /* the deferred accept(), rtsig, aio, iocp */ - - if (ngx_use_accept_mutex) { - ngx_post_event(rev, &ngx_posted_events); - return; - } - - rev->handler(rev); - return; - } - - ngx_add_timer(rev, s->timeout); - - if (ngx_handle_read_event(rev, 0) != NGX_OK) { - ngx_rtmp_finalize_session(s); - return; - } -} - - -static void -ngx_rtmp_proxy_protocol_recv(ngx_event_t *rev) -{ - u_char buf[107], *p, *pp, *text; - size_t len; - ssize_t n; - ngx_err_t err; - ngx_int_t i; - ngx_addr_t addr; - ngx_connection_t *c; - ngx_rtmp_session_t *s; - - c = rev->data; - s = c->data; - - if (c->destroyed) { - return; - } - - if (rev->timedout) { - ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, - "proxy_protocol: recv: client timed out"); - c->timedout = 1; - ngx_rtmp_finalize_session(s); - return; - } - - if (rev->timer_set) { - ngx_del_timer(rev); - } - - n = recv(c->fd, (char *) buf, sizeof(buf), MSG_PEEK); - - err = ngx_socket_errno; - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, c->log, 0, "recv(): %d", n); - - if (n == -1) { - - if (err == NGX_EAGAIN) { - ngx_add_timer(rev, s->timeout); - - if (ngx_handle_read_event(c->read, 0) != NGX_OK) { - ngx_rtmp_finalize_session(s); - } - - return; - } - - ngx_rtmp_finalize_session(s); - - return; - } - - p = buf; - - if (n <= 8 && ngx_strncmp(p, "PROXY ", 6) != 0) { - goto bad_header; - } - - n -= 6; - p += 6; - - ngx_memzero(&addr, sizeof(ngx_addr_t)); - - if (n >= 7 && ngx_strncmp(p, "UNKNOWN", 7) == 0) { - n -= 7; - p += 7; - goto skip; - } - - if (n < 5 || ngx_strncmp(p, "TCP", 3) != 0 - || (p[3] != '4' && p[3] != '6') || p[4] != ' ') - { - goto bad_header; - } - - n -= 5; - p += 5; - - pp = ngx_strlchr(p, p + n, ' '); - - if (pp == NULL) { - goto bad_header; - } - - if (ngx_parse_addr(s->pool, &addr, p, pp - p) != NGX_OK) { - goto bad_header; - } - - n -= pp - p; - p = pp; - -skip: - - for (i = 0; i + 1 < n; i++) { - if (p[i] == CR && p[i + 1] == LF) { - break; - } - } - - if (i + 1 >= n) { - goto bad_header; - } - - n = p - buf + i + 2; - - if (c->recv(c, buf, n) != n) { - goto failed; - } - - if (addr.socklen) { - text = ngx_palloc(s->pool, NGX_SOCKADDR_STRLEN); - - if (text == NULL) { - goto failed; - } - - len = ngx_sock_ntop(addr.sockaddr, -#if (nginx_version >= 1005003) - addr.socklen, -#endif - text, NGX_SOCKADDR_STRLEN, 0); - if (len == 0) { - goto failed; - } - - c->sockaddr = addr.sockaddr; - c->socklen = addr.socklen; - c->addr_text.data = text; - c->addr_text.len = len; - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, c->log, 0, - "proxy_protocol: remote_addr:'%V'", &c->addr_text); - } - - ngx_rtmp_handshake(s); - - return; - -bad_header: - - ngx_log_error(NGX_LOG_INFO, c->log, 0, "proxy_protocol: bad header"); - -failed: - - ngx_rtmp_finalize_session(s); -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_proxy_protocol.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_proxy_protocol.h deleted file mode 100644 index e873c3c0ca..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_proxy_protocol.h +++ /dev/null @@ -1,19 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#ifndef _NGX_RTMP_PROXY_PROTOCOL_H_INCLUDED_ -#define _NGX_RTMP_PROXY_PROTOCOL_H_INCLUDED_ - - -#include -#include -#include "ngx_rtmp.h" - - -void ngx_rtmp_proxy_protocol(ngx_rtmp_session_t *c); - - -#endif /* _NGX_RTMP_PROXY_PROTOCOL_H_INCLUDED_ */ diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_receive.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_receive.c deleted file mode 100644 index dbf662a5f7..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_receive.c +++ /dev/null @@ -1,464 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include -#include "ngx_rtmp.h" -#include "ngx_rtmp_amf.h" -#include "ngx_rtmp_cmd_module.h" -#include - - -ngx_int_t -ngx_rtmp_protocol_message_handler(ngx_rtmp_session_t *s, - ngx_rtmp_header_t *h, ngx_chain_t *in) -{ - ngx_buf_t *b; - u_char *p; - uint32_t val; - uint8_t limit; - - b = in->buf; - - if (b->last - b->pos < 4) { - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->log, 0, - "too small buffer for %d message: %d", - (int)h->type, b->last - b->pos); - return NGX_OK; - } - - p = (u_char*)&val; - p[0] = b->pos[3]; - p[1] = b->pos[2]; - p[2] = b->pos[1]; - p[3] = b->pos[0]; - - switch(h->type) { - case NGX_RTMP_MSG_CHUNK_SIZE: - /* set chunk size =val */ - ngx_rtmp_set_chunk_size(s, val); - break; - - case NGX_RTMP_MSG_ABORT: - /* abort chunk stream =val */ - break; - - case NGX_RTMP_MSG_ACK: - /* receive ack with sequence number =val */ - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "receive ack seq=%uD", val); - break; - - case NGX_RTMP_MSG_ACK_SIZE: - /* receive window size =val */ - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "receive ack_size=%uD", val); - s->ack_size = val; - break; - - case NGX_RTMP_MSG_BANDWIDTH: - if (b->last - b->pos >= 5) { - limit = *(uint8_t*)&b->pos[4]; - - (void)val; - (void)limit; - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->log, 0, - "receive bandwidth=%uD limit=%d", - val, (int)limit); - - /* receive window size =val - * && limit */ - } - break; - - default: - return NGX_ERROR; - } - - return NGX_OK; -} - - -ngx_int_t -ngx_rtmp_user_message_handler(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - ngx_buf_t *b; - u_char *p; - uint16_t evt; - uint32_t val; - - b = in->buf; - - if (b->last - b->pos < 6) { - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "too small buffer for user message: %d", - b->last - b->pos); - return NGX_OK; - } - - p = (u_char*)&evt; - - p[0] = b->pos[1]; - p[1] = b->pos[0]; - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->log, 0, - "RTMP recv user evt %s (%i)", - ngx_rtmp_user_message_type(evt), (ngx_int_t) evt); - - p = (u_char *) &val; - - p[0] = b->pos[5]; - p[1] = b->pos[4]; - p[2] = b->pos[3]; - p[3] = b->pos[2]; - - switch(evt) { - case NGX_RTMP_USER_STREAM_BEGIN: - { - ngx_rtmp_stream_begin_t v; - - v.msid = val; - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "receive: stream_begin msid=%uD", v.msid); - - return ngx_rtmp_stream_begin(s, &v); - } - - case NGX_RTMP_USER_STREAM_EOF: - { - ngx_rtmp_stream_eof_t v; - - v.msid = val; - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "receive: stream_eof msid=%uD", v.msid); - - return ngx_rtmp_stream_eof(s, &v); - } - - case NGX_RTMP_USER_STREAM_DRY: - { - ngx_rtmp_stream_dry_t v; - - v.msid = val; - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "receive: stream_dry msid=%uD", v.msid); - - return ngx_rtmp_stream_dry(s, &v); - } - - case NGX_RTMP_USER_SET_BUFLEN: - { - ngx_rtmp_set_buflen_t v; - - v.msid = val; - - if (b->last - b->pos < 10) { - return NGX_OK; - } - - p = (u_char *) &v.buflen; - - p[0] = b->pos[9]; - p[1] = b->pos[8]; - p[2] = b->pos[7]; - p[3] = b->pos[6]; - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->log, 0, - "receive: set_buflen msid=%uD buflen=%uD", - v.msid, v.buflen); - - /*TODO: move this to play module */ - s->buflen = v.buflen; - - return ngx_rtmp_set_buflen(s, &v); - } - - case NGX_RTMP_USER_RECORDED: - { - ngx_rtmp_recorded_t v; - - v.msid = val; - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "receive: recorded msid=%uD", v.msid); - - return ngx_rtmp_recorded(s, &v); - } - - case NGX_RTMP_USER_PING_REQUEST: - return ngx_rtmp_send_ping_response(s, val); - - case NGX_RTMP_USER_PING_RESPONSE: - - /* val = incoming timestamp */ - - ngx_rtmp_reset_ping(s); - - return NGX_OK; - - default: - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "unexpected user event: %i", (ngx_int_t) evt); - - return NGX_OK; - } -} - - -static ngx_int_t -ngx_rtmp_fetch(ngx_chain_t **in, u_char *ret) -{ - while (*in && (*in)->buf->pos >= (*in)->buf->last) { - *in = (*in)->next; - } - - if (*in == NULL) { - return NGX_DONE; - } - - *ret = *(*in)->buf->pos++; - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_fetch_uint8(ngx_chain_t **in, uint8_t *ret) -{ - return ngx_rtmp_fetch(in, (u_char *) ret); -} - - -static ngx_int_t -ngx_rtmp_fetch_uint32(ngx_chain_t **in, uint32_t *ret, ngx_int_t n) -{ - u_char *r = (u_char *) ret; - ngx_int_t rc; - - *ret = 0; - - while (--n >= 0) { - rc = ngx_rtmp_fetch(in, &r[n]); - if (rc != NGX_OK) { - return rc; - } - } - - return NGX_OK; -} - - -ngx_int_t -ngx_rtmp_aggregate_message_handler(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - uint32_t base_time, timestamp, prev_size; - size_t len; - ngx_int_t first; - u_char *last; - ngx_int_t rc; - ngx_buf_t *b; - ngx_chain_t *cl, *next; - ngx_rtmp_header_t ch; - - ch = *h; - - first = 1; - base_time = 0; - - while (in) { - if (ngx_rtmp_fetch_uint8(&in, &ch.type) != NGX_OK) { - return NGX_OK; - } - - if (ngx_rtmp_fetch_uint32(&in, &ch.mlen, 3) != NGX_OK) { - return NGX_ERROR; - } - - if (ngx_rtmp_fetch_uint32(&in, ×tamp, 3) != NGX_OK) { - return NGX_ERROR; - } - - if (ngx_rtmp_fetch_uint8(&in, (uint8_t *) ×tamp + 3) != NGX_OK) - { - return NGX_ERROR; - } - - if (ngx_rtmp_fetch_uint32(&in, &ch.msid, 3) != NGX_OK) - { - return NGX_ERROR; - } - - if (first) { - base_time = timestamp; - first = 0; - } - - ngx_log_debug6(NGX_LOG_DEBUG_RTMP, s->log, 0, - "RTMP aggregate %s (%d) len=%uD time=%uD (+%D) msid=%uD", - ngx_rtmp_message_type(ch.type), - (ngx_int_t) ch.type, ch.mlen, ch.timestamp, - timestamp - base_time, ch.msid); - - /* limit chain */ - - len = 0; - cl = in; - while (cl) { - b = cl->buf; - len += (b->last - b->pos); - if (len > ch.mlen) { - break; - } - cl = cl->next; - } - - if (cl == NULL) { - ngx_log_error(NGX_LOG_INFO, s->log, 0, - "RTMP error parsing aggregate"); - return NGX_ERROR; - } - - next = cl->next; - cl->next = NULL; - b = cl->buf; - last = b->last; - b->last -= (len - ch.mlen); - - /* handle aggregated message */ - - ch.timestamp = h->timestamp + timestamp - base_time; - - rc = ngx_rtmp_receive_message(s, &ch, in); - - /* restore chain before checking the result */ - - in = cl; - in->next = next; - b->pos = b->last; - b->last = last; - - if (rc != NGX_OK) { - return rc; - } - - /* read 32-bit previous tag size */ - - if (ngx_rtmp_fetch_uint32(&in, &prev_size, 4) != NGX_OK) { - return NGX_OK; - } - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "RTMP aggregate prev_size=%uD", prev_size); - } - - return NGX_OK; -} - - -ngx_int_t -ngx_rtmp_amf_message_handler(ngx_rtmp_session_t *s, - ngx_rtmp_header_t *h, ngx_chain_t *in) -{ - ngx_rtmp_amf_ctx_t act; - ngx_rtmp_core_main_conf_t *cmcf; - ngx_array_t *ch; - ngx_rtmp_handler_pt *ph; - size_t len, n; - - static u_char func[128]; - - static ngx_rtmp_amf_elt_t elts[] = { - - { NGX_RTMP_AMF_STRING, - ngx_null_string, - func, sizeof(func) }, - }; - - /* AMF command names come with string type, but shared object names - * come without type */ - if (h->type == NGX_RTMP_MSG_AMF_SHARED || - h->type == NGX_RTMP_MSG_AMF3_SHARED) - { - elts[0].type |= NGX_RTMP_AMF_TYPELESS; - } else { - elts[0].type &= ~NGX_RTMP_AMF_TYPELESS; - } - - if ((h->type == NGX_RTMP_MSG_AMF3_SHARED || - h->type == NGX_RTMP_MSG_AMF3_META || - h->type == NGX_RTMP_MSG_AMF3_CMD) - && in->buf->last > in->buf->pos) - { - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "AMF3 prefix: %ui", (ngx_int_t)*in->buf->pos); - ++in->buf->pos; - } - - cmcf = ngx_rtmp_get_module_main_conf(s, ngx_rtmp_core_module); - - /* read AMF func name & transaction id */ - ngx_memzero(&act, sizeof(act)); - act.link = in; - act.log = s->log; - memset(func, 0, sizeof(func)); - - if (ngx_rtmp_amf_read(&act, elts, - sizeof(elts) / sizeof(elts[0])) != NGX_OK) - { - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->log, 0, - "AMF cmd failed"); - return NGX_ERROR; - } - - /* skip name */ - in = act.link; - in->buf->pos += act.offset; - - len = ngx_strlen(func); - - ch = ngx_hash_find(&cmcf->amf_hash, - ngx_hash_strlow(func, func, len), func, len); - - if (ch && ch->nelts) { - ph = ch->elts; - for (n = 0; n < ch->nelts; ++n, ++ph) { - ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->log, 0, - "AMF func '%s' passed to handler %d/%d", - func, n, ch->nelts); - switch ((*ph)(s, h, in)) { - case NGX_ERROR: - return NGX_ERROR; - case NGX_DONE: - return NGX_OK; - } - } - } else { - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "AMF cmd '%s' no handler", func); - } - - return NGX_OK; -} - - -ngx_int_t -ngx_rtmp_receive_amf(ngx_rtmp_session_t *s, ngx_chain_t *in, - ngx_rtmp_amf_elt_t *elts, size_t nelts) -{ - ngx_rtmp_amf_ctx_t act; - - ngx_memzero(&act, sizeof(act)); - act.link = in; - act.log = s->log; - - return ngx_rtmp_amf_read(&act, elts, nelts); -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_record_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_record_module.c deleted file mode 100644 index 4cff47e60f..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_record_module.c +++ /dev/null @@ -1,1308 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include -#include "ngx_rtmp.h" -#include "ngx_rtmp_cmd_module.h" -#include "ngx_rtmp_codec_module.h" -#include "ngx_rtmp_record_module.h" - - -ngx_rtmp_record_done_pt ngx_rtmp_record_done; - - -static ngx_rtmp_publish_pt next_publish; -static ngx_rtmp_close_stream_pt next_close_stream; -static ngx_rtmp_stream_begin_pt next_stream_begin; -static ngx_rtmp_stream_eof_pt next_stream_eof; - - -static char *ngx_rtmp_record_recorder(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); -static ngx_int_t ngx_rtmp_record_postconfiguration(ngx_conf_t *cf); -static void * ngx_rtmp_record_create_app_conf(ngx_conf_t *cf); -static char * ngx_rtmp_record_merge_app_conf(ngx_conf_t *cf, - void *parent, void *child); -static ngx_int_t ngx_rtmp_record_write_frame(ngx_rtmp_session_t *s, - ngx_rtmp_record_rec_ctx_t *rctx, - ngx_rtmp_header_t *h, ngx_chain_t *in, ngx_int_t inc_nframes); -static ngx_int_t ngx_rtmp_record_av(ngx_rtmp_session_t *s, - ngx_rtmp_header_t *h, ngx_chain_t *in); -static ngx_int_t ngx_rtmp_record_node_av(ngx_rtmp_session_t *s, - ngx_rtmp_record_rec_ctx_t *rctx, ngx_rtmp_header_t *h, ngx_chain_t *in); -static ngx_int_t ngx_rtmp_record_node_open(ngx_rtmp_session_t *s, - ngx_rtmp_record_rec_ctx_t *rctx); -static ngx_int_t ngx_rtmp_record_node_close(ngx_rtmp_session_t *s, - ngx_rtmp_record_rec_ctx_t *rctx); -static void ngx_rtmp_record_make_path(ngx_rtmp_session_t *s, - ngx_rtmp_record_rec_ctx_t *rctx, ngx_str_t *path); -static ngx_int_t ngx_rtmp_record_init(ngx_rtmp_session_t *s); - - -static ngx_conf_bitmask_t ngx_rtmp_record_mask[] = { - { ngx_string("off"), NGX_RTMP_RECORD_OFF }, - { ngx_string("all"), NGX_RTMP_RECORD_AUDIO | - NGX_RTMP_RECORD_VIDEO }, - { ngx_string("audio"), NGX_RTMP_RECORD_AUDIO }, - { ngx_string("video"), NGX_RTMP_RECORD_VIDEO }, - { ngx_string("keyframes"), NGX_RTMP_RECORD_KEYFRAMES }, - { ngx_string("manual"), NGX_RTMP_RECORD_MANUAL }, - { ngx_null_string, 0 } -}; - - -static ngx_command_t ngx_rtmp_record_commands[] = { - - { ngx_string("record"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF| - NGX_RTMP_REC_CONF|NGX_CONF_1MORE, - ngx_conf_set_bitmask_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_record_app_conf_t, flags), - ngx_rtmp_record_mask }, - - { ngx_string("record_path"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF| - NGX_RTMP_REC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_record_app_conf_t, path), - NULL }, - - { ngx_string("record_suffix"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF| - NGX_RTMP_REC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_record_app_conf_t, suffix), - NULL }, - - { ngx_string("record_unique"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF| - NGX_RTMP_REC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_record_app_conf_t, unique), - NULL }, - - { ngx_string("record_append"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF| - NGX_RTMP_REC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_record_app_conf_t, append), - NULL }, - - { ngx_string("record_lock"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF| - NGX_RTMP_REC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_record_app_conf_t, lock_file), - NULL }, - - { ngx_string("record_max_size"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF| - NGX_RTMP_REC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_record_app_conf_t, max_size), - NULL }, - - { ngx_string("record_max_frames"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF| - NGX_RTMP_REC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_record_app_conf_t, max_frames), - NULL }, - - { ngx_string("record_interval"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF| - NGX_RTMP_REC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_record_app_conf_t, interval), - NULL }, - - { ngx_string("record_notify"), - NGX_RTMP_MAIN_CONF|NGX_RTMP_SRV_CONF|NGX_RTMP_APP_CONF| - NGX_RTMP_REC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_flag_slot, - NGX_RTMP_APP_CONF_OFFSET, - offsetof(ngx_rtmp_record_app_conf_t, notify), - NULL }, - - { ngx_string("recorder"), - NGX_RTMP_APP_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE1, - ngx_rtmp_record_recorder, - NGX_RTMP_APP_CONF_OFFSET, - 0, - NULL }, - - - ngx_null_command -}; - - -static ngx_rtmp_module_t ngx_rtmp_record_module_ctx = { - NULL, /* preconfiguration */ - ngx_rtmp_record_postconfiguration, /* postconfiguration */ - NULL, /* create main configuration */ - NULL, /* init main configuration */ - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - ngx_rtmp_record_create_app_conf, /* create app configuration */ - ngx_rtmp_record_merge_app_conf /* merge app configuration */ -}; - - -ngx_module_t ngx_rtmp_record_module = { - NGX_MODULE_V1, - &ngx_rtmp_record_module_ctx, /* module context */ - ngx_rtmp_record_commands, /* module directives */ - NGX_RTMP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void * -ngx_rtmp_record_create_app_conf(ngx_conf_t *cf) -{ - ngx_rtmp_record_app_conf_t *racf; - - racf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_record_app_conf_t)); - - if (racf == NULL) { - return NULL; - } - - racf->max_size = NGX_CONF_UNSET_SIZE; - racf->max_frames = NGX_CONF_UNSET_SIZE; - racf->interval = NGX_CONF_UNSET_MSEC; - racf->unique = NGX_CONF_UNSET; - racf->append = NGX_CONF_UNSET; - racf->lock_file = NGX_CONF_UNSET; - racf->notify = NGX_CONF_UNSET; - racf->url = NGX_CONF_UNSET_PTR; - - if (ngx_array_init(&racf->rec, cf->pool, 1, sizeof(void *)) != NGX_OK) { - return NULL; - } - - return racf; -} - - -static char * -ngx_rtmp_record_merge_app_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_rtmp_record_app_conf_t *prev = parent; - ngx_rtmp_record_app_conf_t *conf = child; - ngx_rtmp_record_app_conf_t **rracf; - - ngx_conf_merge_str_value(conf->path, prev->path, ""); - ngx_conf_merge_str_value(conf->suffix, prev->suffix, ".flv"); - ngx_conf_merge_size_value(conf->max_size, prev->max_size, 0); - ngx_conf_merge_size_value(conf->max_frames, prev->max_frames, 0); - ngx_conf_merge_value(conf->unique, prev->unique, 0); - ngx_conf_merge_value(conf->append, prev->append, 0); - ngx_conf_merge_value(conf->lock_file, prev->lock_file, 0); - ngx_conf_merge_value(conf->notify, prev->notify, 0); - ngx_conf_merge_msec_value(conf->interval, prev->interval, - (ngx_msec_t) NGX_CONF_UNSET); - ngx_conf_merge_bitmask_value(conf->flags, prev->flags, 0); - ngx_conf_merge_ptr_value(conf->url, prev->url, NULL); - - if (conf->flags) { - rracf = ngx_array_push(&conf->rec); - if (rracf == NULL) { - return NGX_CONF_ERROR; - } - - *rracf = conf; - } - - return NGX_CONF_OK; -} - - -static ngx_int_t -ngx_rtmp_record_write_header(ngx_file_t *file) -{ - static u_char flv_header[] = { - 0x46, /* 'F' */ - 0x4c, /* 'L' */ - 0x56, /* 'V' */ - 0x01, /* version = 1 */ - 0x05, /* 00000 1 0 1 = has audio & video */ - 0x00, - 0x00, - 0x00, - 0x09, /* header size */ - 0x00, - 0x00, - 0x00, - 0x00 /* PreviousTagSize0 (not actually a header) */ - }; - - return ngx_write_file(file, flv_header, sizeof(flv_header), 0) == NGX_ERROR - ? NGX_ERROR - : NGX_OK; -} - - -static ngx_rtmp_record_rec_ctx_t * -ngx_rtmp_record_get_node_ctx(ngx_rtmp_session_t *s, ngx_uint_t n) -{ - ngx_rtmp_record_ctx_t *ctx; - ngx_rtmp_record_rec_ctx_t *rctx; - - if (ngx_rtmp_record_init(s) != NGX_OK) { - return NULL; - } - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_record_module); - - if (n >= ctx->rec.nelts) { - return NULL; - } - - rctx = ctx->rec.elts; - - return &rctx[n]; -} - - -ngx_int_t -ngx_rtmp_record_open(ngx_rtmp_session_t *s, ngx_uint_t n, ngx_str_t *path) -{ - ngx_rtmp_record_rec_ctx_t *rctx; - ngx_int_t rc; - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "record: #%ui manual open", n); - - rctx = ngx_rtmp_record_get_node_ctx(s, n); - - if (rctx == NULL) { - return NGX_ERROR; - } - - rc = ngx_rtmp_record_node_open(s, rctx); - if (rc != NGX_OK) { - return rc; - } - - if (path) { - ngx_rtmp_record_make_path(s, rctx, path); - } - - return NGX_OK; -} - - -ngx_int_t -ngx_rtmp_record_close(ngx_rtmp_session_t *s, ngx_uint_t n, ngx_str_t *path) -{ - ngx_rtmp_record_rec_ctx_t *rctx; - ngx_int_t rc; - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "record: #%ui manual close", n); - - rctx = ngx_rtmp_record_get_node_ctx(s, n); - - if (rctx == NULL) { - return NGX_ERROR; - } - - rc = ngx_rtmp_record_node_close(s, rctx); - if (rc != NGX_OK) { - return rc; - } - - if (path) { - ngx_rtmp_record_make_path(s, rctx, path); - } - - return NGX_OK; -} - - -ngx_uint_t -ngx_rtmp_record_find(ngx_rtmp_record_app_conf_t *racf, ngx_str_t *id) -{ - ngx_rtmp_record_app_conf_t **pracf, *rracf; - ngx_uint_t n; - - pracf = racf->rec.elts; - - for (n = 0; n < racf->rec.nelts; ++n, ++pracf) { - rracf = *pracf; - - if (rracf->id.len == id->len && - ngx_strncmp(rracf->id.data, id->data, id->len) == 0) - { - return n; - } - } - - return NGX_CONF_UNSET_UINT; -} - - -/* This funcion returns pointer to a static buffer */ -static void -ngx_rtmp_record_make_path(ngx_rtmp_session_t *s, - ngx_rtmp_record_rec_ctx_t *rctx, ngx_str_t *path) -{ - ngx_rtmp_record_ctx_t *ctx; - ngx_rtmp_record_app_conf_t *rracf; - u_char *p, *l; - struct tm tm; - - static u_char buf[NGX_TIME_T_LEN + 1]; - static u_char pbuf[NGX_MAX_PATH + 1]; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_record_module); - - rracf = rctx->conf; - - /* create file path */ - p = pbuf; - l = pbuf + sizeof(pbuf) - 1; - - p = ngx_cpymem(p, rracf->path.data, - ngx_min(rracf->path.len, (size_t)(l - p - 1))); - *p++ = '/'; - p = (u_char *)ngx_escape_uri(p, ctx->name, ngx_min(ngx_strlen(ctx->name), - (size_t)(l - p)), NGX_ESCAPE_URI_COMPONENT); - - /* append timestamp */ - if (rracf->unique) { - p = ngx_cpymem(p, buf, ngx_min(ngx_sprintf(buf, "-%T", - rctx->timestamp) - buf, l - p)); - } - - if (ngx_strchr(rracf->suffix.data, '%')) { - ngx_libc_localtime(rctx->timestamp, &tm); - p += strftime((char *) p, l - p, (char *) rracf->suffix.data, &tm); - } else { - p = ngx_cpymem(p, rracf->suffix.data, - ngx_min(rracf->suffix.len, (size_t)(l - p))); - } - - *p = 0; - path->data = pbuf; - path->len = p - pbuf; - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->log, 0, - "record: %V path: '%V'", &rracf->id, path); -} - - -static void -ngx_rtmp_record_notify_error(ngx_rtmp_session_t *s, - ngx_rtmp_record_rec_ctx_t *rctx) -{ - ngx_rtmp_record_app_conf_t *rracf = rctx->conf; - - rctx->failed = 1; - - if (!rracf->notify) { - return; - } - - ngx_rtmp_send_status(s, "NetStream.Record.Failed", "error", - rracf->id.data ? (char *) rracf->id.data : ""); -} - - -static ngx_int_t -ngx_rtmp_record_node_open(ngx_rtmp_session_t *s, - ngx_rtmp_record_rec_ctx_t *rctx) -{ - ngx_rtmp_record_app_conf_t *rracf; - ngx_err_t err; - ngx_str_t path; - ngx_int_t mode, create_mode; - u_char buf[8], *p; - off_t file_size; - uint32_t tag_size, mlen, timestamp; - - rracf = rctx->conf; - tag_size = 0; - - if (rctx->file.fd != NGX_INVALID_FILE) { - return NGX_AGAIN; - } - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "record: %V opening", &rracf->id); - - ngx_memzero(rctx, sizeof(*rctx)); - rctx->conf = rracf; - rctx->last = *ngx_cached_time; - rctx->timestamp = ngx_cached_time->sec; - - ngx_rtmp_record_make_path(s, rctx, &path); - - mode = rracf->append ? NGX_FILE_RDWR : NGX_FILE_WRONLY; - create_mode = rracf->append ? NGX_FILE_CREATE_OR_OPEN : NGX_FILE_TRUNCATE; - - ngx_memzero(&rctx->file, sizeof(rctx->file)); - rctx->file.offset = 0; - rctx->file.log = s->log; - rctx->file.fd = ngx_open_file(path.data, mode, create_mode, - NGX_FILE_DEFAULT_ACCESS); - ngx_str_set(&rctx->file.name, "recorded"); - - if (rctx->file.fd == NGX_INVALID_FILE) { - err = ngx_errno; - - if (err != NGX_ENOENT) { - ngx_log_error(NGX_LOG_CRIT, s->log, err, - "record: %V failed to open file '%V'", - &rracf->id, &path); - } - - ngx_rtmp_record_notify_error(s, rctx); - - return NGX_OK; - } - -#if !(NGX_WIN32) - if (rracf->lock_file) { - err = ngx_lock_fd(rctx->file.fd); - if (err) { - ngx_log_error(NGX_LOG_CRIT, s->log, err, - "record: %V lock failed", &rracf->id); - } - } -#endif - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->log, 0, - "record: %V opened '%V'", &rracf->id, &path); - - if (rracf->notify) { - ngx_rtmp_send_status(s, "NetStream.Record.Start", "status", - rracf->id.data ? (char *) rracf->id.data : ""); - } - - if (rracf->append) { - - file_size = 0; - timestamp = 0; - -#if (NGX_WIN32) - { - LONG lo, hi; - - lo = 0; - hi = 0; - lo = SetFilePointer(rctx->file.fd, lo, &hi, FILE_END); - file_size = (lo == INVALID_SET_FILE_POINTER ? - (off_t) -1 : (off_t) hi << 32 | (off_t) lo); - } -#else - file_size = lseek(rctx->file.fd, 0, SEEK_END); -#endif - if (file_size == (off_t) -1) { - ngx_log_error(NGX_LOG_CRIT, s->log, ngx_errno, - "record: %V seek failed", &rracf->id); - goto done; - } - - if (file_size < 4) { - goto done; - } - - if (ngx_read_file(&rctx->file, buf, 4, file_size - 4) != 4) { - ngx_log_error(NGX_LOG_CRIT, s->log, ngx_errno, - "record: %V tag size read failed", &rracf->id); - goto done; - } - - p = (u_char *) &tag_size; - p[0] = buf[3]; - p[1] = buf[2]; - p[2] = buf[1]; - p[3] = buf[0]; - - if (tag_size == 0 || tag_size + 4 > file_size) { - file_size = 0; - goto done; - } - - if (ngx_read_file(&rctx->file, buf, 8, file_size - tag_size - 4) != 8) - { - ngx_log_error(NGX_LOG_CRIT, s->log, ngx_errno, - "record: %V tag read failed", &rracf->id); - goto done; - } - - p = (u_char *) &mlen; - p[0] = buf[3]; - p[1] = buf[2]; - p[2] = buf[1]; - p[3] = 0; - - if (tag_size != mlen + 11) { - ngx_log_error(NGX_LOG_CRIT, s->log, ngx_errno, - "record: %V tag size mismatch: " - "tag_size=%uD, mlen=%uD", &rracf->id, tag_size, mlen); - goto done; - } - - p = (u_char *) ×tamp; - p[3] = buf[7]; - p[0] = buf[6]; - p[1] = buf[5]; - p[2] = buf[4]; - -done: - rctx->file.offset = file_size; - rctx->time_shift = timestamp; - - ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->log, 0, - "record: append offset=%O, time=%uD, tag_size=%uD", - file_size, timestamp, tag_size); - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_record_init(ngx_rtmp_session_t *s) -{ - ngx_rtmp_record_app_conf_t *racf, **rracf; - ngx_rtmp_record_rec_ctx_t *rctx; - ngx_rtmp_record_ctx_t *ctx; - ngx_uint_t n; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_record_module); - - if (ctx) { - return NGX_OK; - } - - racf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_record_module); - - if (racf == NULL || racf->rec.nelts == 0) { - return NGX_OK; - } - - ctx = ngx_pcalloc(s->connection->pool, sizeof(ngx_rtmp_record_ctx_t)); - - if (ctx == NULL) { - return NGX_ERROR; - } - - ngx_rtmp_set_ctx(s, ctx, ngx_rtmp_record_module); - - if (ngx_array_init(&ctx->rec, s->connection->pool, racf->rec.nelts, - sizeof(ngx_rtmp_record_rec_ctx_t)) - != NGX_OK) - { - return NGX_ERROR; - } - - rracf = racf->rec.elts; - - rctx = ngx_array_push_n(&ctx->rec, racf->rec.nelts); - - if (rctx == NULL) { - return NGX_ERROR; - } - - for (n = 0; n < racf->rec.nelts; ++n, ++rracf, ++rctx) { - ngx_memzero(rctx, sizeof(*rctx)); - - rctx->conf = *rracf; - rctx->file.fd = NGX_INVALID_FILE; - } - - return NGX_OK; -} - - -static void -ngx_rtmp_record_start(ngx_rtmp_session_t *s) -{ - ngx_rtmp_record_app_conf_t *racf; - ngx_rtmp_record_rec_ctx_t *rctx; - ngx_rtmp_record_ctx_t *ctx; - ngx_uint_t n; - - racf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_record_module); - if (racf == NULL || racf->rec.nelts == 0) { - return; - } - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_record_module); - if (ctx == NULL) { - return; - } - - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->log, 0, - "record: start"); - - rctx = ctx->rec.elts; - for (n = 0; n < ctx->rec.nelts; ++n, ++rctx) { - if (rctx->conf->flags & (NGX_RTMP_RECORD_OFF|NGX_RTMP_RECORD_MANUAL)) { - continue; - } - ngx_rtmp_record_node_open(s, rctx); - } -} - - -static void -ngx_rtmp_record_stop(ngx_rtmp_session_t *s) -{ - ngx_rtmp_record_app_conf_t *racf; - ngx_rtmp_record_rec_ctx_t *rctx; - ngx_rtmp_record_ctx_t *ctx; - ngx_uint_t n; - - racf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_record_module); - if (racf == NULL || racf->rec.nelts == 0) { - return; - } - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_record_module); - if (ctx == NULL) { - return; - } - - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->log, 0, - "record: stop"); - - rctx = ctx->rec.elts; - for (n = 0; n < ctx->rec.nelts; ++n, ++rctx) { - ngx_rtmp_record_node_close(s, rctx); - } -} - - -static ngx_int_t -ngx_rtmp_record_publish(ngx_rtmp_session_t *s, ngx_rtmp_publish_t *v) -{ - ngx_rtmp_record_app_conf_t *racf; - ngx_rtmp_record_ctx_t *ctx; - u_char *p; - - if (s->interprocess) { - goto next; - } - - racf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_record_module); - - if (racf == NULL || racf->rec.nelts == 0) { - goto next; - } - - if (ngx_rtmp_record_init(s) != NGX_OK) { - return NGX_ERROR; - } - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "record: publish %ui nodes", - racf->rec.nelts); - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_record_module); - - ngx_memcpy(ctx->name, v->name, sizeof(ctx->name)); - ngx_memcpy(ctx->args, v->args, sizeof(ctx->args)); - - /* terminate name on /../ */ - for (p = ctx->name; *p; ++p) { - if (ngx_path_separator(p[0]) && - p[1] == '.' && p[2] == '.' && - ngx_path_separator(p[3])) - { - *p = 0; - break; - } - } - - ngx_rtmp_record_start(s); - -next: - return next_publish(s, v); -} - - -static ngx_int_t -ngx_rtmp_record_stream_begin(ngx_rtmp_session_t *s, ngx_rtmp_stream_begin_t *v) -{ - if (s->interprocess) { - goto next; - } - - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->log, 0, - "record: stream_begin"); - - ngx_rtmp_record_start(s); - -next: - return next_stream_begin(s, v); -} - - -static ngx_int_t -ngx_rtmp_record_stream_eof(ngx_rtmp_session_t *s, ngx_rtmp_stream_begin_t *v) -{ - if (s->interprocess) { - goto next; - } - - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->log, 0, - "record: stream_eof"); - - ngx_rtmp_record_stop(s); - -next: - return next_stream_eof(s, v); -} - - -static ngx_int_t -ngx_rtmp_record_node_close(ngx_rtmp_session_t *s, - ngx_rtmp_record_rec_ctx_t *rctx) -{ - ngx_rtmp_record_app_conf_t *rracf; - ngx_err_t err; - void **app_conf; - ngx_int_t rc; - ngx_rtmp_record_done_t v; - u_char av; - - rracf = rctx->conf; - - if (rctx->file.fd == NGX_INVALID_FILE) { - return NGX_AGAIN; - } - - if (rctx->initialized) { - av = 0; - - if (rctx->video) { - av |= 0x01; - } - - if (rctx->audio) { - av |= 0x04; - } - - if (ngx_write_file(&rctx->file, &av, 1, 4) == NGX_ERROR) { - ngx_log_error(NGX_LOG_CRIT, s->log, ngx_errno, - "record: %V error writing av mask", &rracf->id); - } - } - - if (ngx_close_file(rctx->file.fd) == NGX_FILE_ERROR) { - err = ngx_errno; - ngx_log_error(NGX_LOG_CRIT, s->log, err, - "record: %V error closing file", &rracf->id); - - ngx_rtmp_record_notify_error(s, rctx); - } - - rctx->file.fd = NGX_INVALID_FILE; - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "record: %V closed", &rracf->id); - - if (rracf->notify) { - ngx_rtmp_send_status(s, "NetStream.Record.Stop", "status", - rracf->id.data ? (char *) rracf->id.data : ""); - } - - app_conf = s->app_conf; - - if (rracf->rec_conf) { - s->app_conf = rracf->rec_conf; - } - - v.recorder = rracf->id; - ngx_rtmp_record_make_path(s, rctx, &v.path); - - rc = ngx_rtmp_record_done(s, &v); - - s->app_conf = app_conf; - - return rc; -} - - -static ngx_int_t -ngx_rtmp_record_close_stream(ngx_rtmp_session_t *s, - ngx_rtmp_close_stream_t *v) -{ - if (s->interprocess) { - goto next; - } - - ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->log, 0, - "record: close_stream"); - - ngx_rtmp_record_stop(s); - -next: - return next_close_stream(s, v); -} - - -static ngx_int_t -ngx_rtmp_record_write_frame(ngx_rtmp_session_t *s, - ngx_rtmp_record_rec_ctx_t *rctx, - ngx_rtmp_header_t *h, ngx_chain_t *in, - ngx_int_t inc_nframes) -{ - u_char hdr[11], *p, *ph; - uint32_t timestamp, tag_size; - ngx_rtmp_record_app_conf_t *rracf; - - rracf = rctx->conf; - - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->log, 0, - "record: %V frame: mlen=%uD", - &rracf->id, h->mlen); - - if (h->type == NGX_RTMP_MSG_VIDEO) { - rctx->video = 1; - } else { - rctx->audio = 1; - } - - timestamp = h->timestamp - rctx->epoch; - - if ((int32_t) timestamp < 0) { - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->log, 0, - "record: %V cut timestamp=%D", &rracf->id, timestamp); - - timestamp = 0; - } - - /* write tag header */ - ph = hdr; - - *ph++ = (u_char)h->type; - - p = (u_char*)&h->mlen; - *ph++ = p[2]; - *ph++ = p[1]; - *ph++ = p[0]; - - p = (u_char*)×tamp; - *ph++ = p[2]; - *ph++ = p[1]; - *ph++ = p[0]; - *ph++ = p[3]; - - *ph++ = 0; - *ph++ = 0; - *ph++ = 0; - - tag_size = (ph - hdr) + h->mlen; - - if (ngx_write_file(&rctx->file, hdr, ph - hdr, rctx->file.offset) - == NGX_ERROR) - { - ngx_rtmp_record_notify_error(s, rctx); - - ngx_close_file(rctx->file.fd); - - return NGX_ERROR; - } - - /* write tag body - * FIXME: NGINX - * ngx_write_chain seems to fit best - * but it suffers from uncontrollable - * allocations. - * we're left with plain writing */ - for(; in; in = in->next) { - if (in->buf->pos == in->buf->last) { - continue; - } - - if (ngx_write_file(&rctx->file, in->buf->pos, in->buf->last - - in->buf->pos, rctx->file.offset) - == NGX_ERROR) - { - return NGX_ERROR; - } - } - - /* write tag size */ - ph = hdr; - p = (u_char*)&tag_size; - - *ph++ = p[3]; - *ph++ = p[2]; - *ph++ = p[1]; - *ph++ = p[0]; - - if (ngx_write_file(&rctx->file, hdr, ph - hdr, - rctx->file.offset) - == NGX_ERROR) - { - return NGX_ERROR; - } - - rctx->nframes += inc_nframes; - - /* watch max size */ - if ((rracf->max_size && rctx->file.offset >= (ngx_int_t) rracf->max_size) || - (rracf->max_frames && rctx->nframes >= rracf->max_frames)) - { - ngx_rtmp_record_node_close(s, rctx); - } - - return NGX_OK; -} - - -static size_t -ngx_rtmp_record_get_chain_mlen(ngx_chain_t *in) -{ - size_t ret; - - for (ret = 0; in; in = in->next) { - ret += (in->buf->last - in->buf->pos); - } - - return ret; -} - - -static ngx_int_t -ngx_rtmp_record_av(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_chain_t *in) -{ - ngx_rtmp_record_ctx_t *ctx; - ngx_rtmp_record_rec_ctx_t *rctx; - ngx_uint_t n; - - ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_record_module); - - if (ctx == NULL || s->pause) { - return NGX_OK; - } - - rctx = ctx->rec.elts; - - for (n = 0; n < ctx->rec.nelts; ++n, ++rctx) { - ngx_rtmp_record_node_av(s, rctx, h, in); - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_record_node_av(ngx_rtmp_session_t *s, ngx_rtmp_record_rec_ctx_t *rctx, - ngx_rtmp_header_t *h, ngx_chain_t *in) -{ - ngx_time_t next; - ngx_rtmp_header_t ch; - ngx_rtmp_codec_ctx_t *codec_ctx; - ngx_int_t keyframe, brkframe; - ngx_rtmp_record_app_conf_t *rracf; - - rracf = rctx->conf; - - if (rracf->flags & NGX_RTMP_RECORD_OFF) { - ngx_rtmp_record_node_close(s, rctx); - return NGX_OK; - } - - keyframe = (h->type == NGX_RTMP_MSG_VIDEO) - ? (ngx_rtmp_get_video_frame_type(in) == NGX_RTMP_VIDEO_KEY_FRAME) - : 0; - - brkframe = (h->type == NGX_RTMP_MSG_VIDEO) - ? keyframe - : (rracf->flags & NGX_RTMP_RECORD_VIDEO) == 0; - - if (brkframe && (rracf->flags & NGX_RTMP_RECORD_MANUAL) == 0) { - - if (rracf->interval != (ngx_msec_t) NGX_CONF_UNSET) { - - next = rctx->last; - next.msec += rracf->interval; - next.sec += (next.msec / 1000); - next.msec %= 1000; - - if (ngx_cached_time->sec > next.sec || - (ngx_cached_time->sec == next.sec && - ngx_cached_time->msec > next.msec)) - { - ngx_rtmp_record_node_close(s, rctx); - ngx_rtmp_record_node_open(s, rctx); - } - - } else if (!rctx->failed) { - ngx_rtmp_record_node_open(s, rctx); - } - } - - if ((rracf->flags & NGX_RTMP_RECORD_MANUAL) && - !brkframe && rctx->nframes == 0) - { - return NGX_OK; - } - - if (rctx->file.fd == NGX_INVALID_FILE) { - return NGX_OK; - } - - if (h->type == NGX_RTMP_MSG_AUDIO && - (rracf->flags & NGX_RTMP_RECORD_AUDIO) == 0) - { - return NGX_OK; - } - - if (h->type == NGX_RTMP_MSG_VIDEO && - (rracf->flags & NGX_RTMP_RECORD_VIDEO) == 0 && - ((rracf->flags & NGX_RTMP_RECORD_KEYFRAMES) == 0 || !keyframe)) - { - return NGX_OK; - } - - if (!rctx->initialized) { - - rctx->initialized = 1; - rctx->epoch = h->timestamp - rctx->time_shift; - - if (rctx->file.offset == 0 && - ngx_rtmp_record_write_header(&rctx->file) != NGX_OK) - { - ngx_rtmp_record_node_close(s, rctx); - return NGX_OK; - } - } - - codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - if (codec_ctx) { - ch = *h; - - /* AAC header */ - if (!rctx->aac_header_sent && codec_ctx->aac_header && - (rracf->flags & NGX_RTMP_RECORD_AUDIO)) - { - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "record: %V writing AAC header", &rracf->id); - - ch.type = NGX_RTMP_MSG_AUDIO; - ch.mlen = - ngx_rtmp_record_get_chain_mlen(codec_ctx->aac_header->chain); - - if (ngx_rtmp_record_write_frame(s, rctx, &ch, - codec_ctx->aac_header->chain, 0) - != NGX_OK) - { - return NGX_OK; - } - - rctx->aac_header_sent = 1; - } - - /* AVC header */ - if (!rctx->avc_header_sent && codec_ctx->avc_header && - (rracf->flags & (NGX_RTMP_RECORD_VIDEO| - NGX_RTMP_RECORD_KEYFRAMES))) - { - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "record: %V writing AVC header", &rracf->id); - - ch.type = NGX_RTMP_MSG_VIDEO; - ch.mlen = - ngx_rtmp_record_get_chain_mlen(codec_ctx->avc_header->chain); - - if (ngx_rtmp_record_write_frame(s, rctx, &ch, - codec_ctx->avc_header->chain, 0) - != NGX_OK) - { - return NGX_OK; - } - - rctx->avc_header_sent = 1; - } - } - - if (h->type == NGX_RTMP_MSG_VIDEO) { - if (codec_ctx && codec_ctx->video_codec_id == NGX_RTMP_VIDEO_H264 && - !rctx->avc_header_sent) - { - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "record: %V skipping until H264 header", &rracf->id); - return NGX_OK; - } - - if (ngx_rtmp_get_video_frame_type(in) == NGX_RTMP_VIDEO_KEY_FRAME && - ((codec_ctx && codec_ctx->video_codec_id != NGX_RTMP_VIDEO_H264) || - !ngx_rtmp_is_codec_header(in))) - { - rctx->video_key_sent = 1; - } - - if (!rctx->video_key_sent) { - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "record: %V skipping until keyframe", &rracf->id); - return NGX_OK; - } - - } else { - if (codec_ctx && codec_ctx->audio_codec_id == NGX_RTMP_AUDIO_AAC && - !rctx->aac_header_sent) - { - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "record: %V skipping until AAC header", &rracf->id); - return NGX_OK; - } - } - - return ngx_rtmp_record_write_frame(s, rctx, h, in, 1); -} - - -static ngx_int_t -ngx_rtmp_record_done_init(ngx_rtmp_session_t *s, ngx_rtmp_record_done_t *v) -{ - return NGX_OK; -} - - -static char * -ngx_rtmp_record_recorder(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - char *rv; - ngx_int_t i; - ngx_str_t *value; - ngx_conf_t save; - ngx_module_t **modules; - ngx_rtmp_module_t *module; - ngx_rtmp_core_app_conf_t *cacf, **pcacf, *rcacf; - ngx_rtmp_record_app_conf_t *racf, **pracf, *rracf; - ngx_rtmp_conf_ctx_t *ctx, *pctx; - - value = cf->args->elts; - - cacf = ngx_rtmp_conf_get_module_app_conf(cf, ngx_rtmp_core_module); - - racf = ngx_rtmp_conf_get_module_app_conf(cf, ngx_rtmp_record_module); - - ctx = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_conf_ctx_t)); - if (ctx == NULL) { - return NGX_CONF_ERROR; - } - - pctx = cf->ctx; - - ctx->main_conf = pctx->main_conf; - ctx->srv_conf = pctx->srv_conf; - - ctx->app_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_rtmp_max_module); - if (ctx->app_conf == NULL) { - return NGX_CONF_ERROR; - } - -#if (nginx_version >= 1009011) - modules = cf->cycle->modules; -#else - modules = ngx_modules; -#endif - - for (i = 0; modules[i]; i++) { - if (modules[i]->type != NGX_RTMP_MODULE) { - continue; - } - - module = modules[i]->ctx; - - if (module->create_app_conf) { - ctx->app_conf[modules[i]->ctx_index] = module->create_app_conf(cf); - if (ctx->app_conf[modules[i]->ctx_index] == NULL) { - return NGX_CONF_ERROR; - } - } - } - - /* add to sub-applications */ - rcacf = ctx->app_conf[ngx_rtmp_core_module.ctx_index]; - rcacf->app_conf = ctx->app_conf; - pcacf = ngx_array_push(&cacf->applications); - if (pcacf == NULL) { - return NGX_CONF_ERROR; - } - *pcacf = rcacf; - - /* add to recorders */ - rracf = ctx->app_conf[ngx_rtmp_record_module.ctx_index]; - rracf->rec_conf = ctx->app_conf; - pracf = ngx_array_push(&racf->rec); - if (pracf == NULL) { - return NGX_CONF_ERROR; - } - *pracf = rracf; - - rracf->id = value[1]; - - - save = *cf; - cf->ctx = ctx; - cf->cmd_type = NGX_RTMP_REC_CONF; - - rv = ngx_conf_parse(cf, NULL); - *cf= save; - - return rv; -} - - -static ngx_int_t -ngx_rtmp_record_postconfiguration(ngx_conf_t *cf) -{ - ngx_rtmp_core_main_conf_t *cmcf; - ngx_rtmp_handler_pt *h; - - ngx_rtmp_record_done = ngx_rtmp_record_done_init; - - cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module); - - h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_AUDIO]); - *h = ngx_rtmp_record_av; - - h = ngx_array_push(&cmcf->events[NGX_RTMP_MSG_VIDEO]); - *h = ngx_rtmp_record_av; - - next_publish = ngx_rtmp_publish; - ngx_rtmp_publish = ngx_rtmp_record_publish; - - next_close_stream = ngx_rtmp_close_stream; - ngx_rtmp_close_stream = ngx_rtmp_record_close_stream; - - next_stream_begin = ngx_rtmp_stream_begin; - ngx_rtmp_stream_begin = ngx_rtmp_record_stream_begin; - - next_stream_eof = ngx_rtmp_stream_eof; - ngx_rtmp_stream_eof = ngx_rtmp_record_stream_eof; - - return NGX_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_record_module.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_record_module.h deleted file mode 100644 index 6450dcbf9e..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_record_module.h +++ /dev/null @@ -1,96 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#ifndef _NGX_RTMP_RECORD_H_INCLUDED_ -#define _NGX_RTMP_RECORD_H_INCLUDED_ - - -#include -#include -#include "ngx_rtmp.h" - - -#define NGX_RTMP_RECORD_OFF 0x01 -#define NGX_RTMP_RECORD_AUDIO 0x02 -#define NGX_RTMP_RECORD_VIDEO 0x04 -#define NGX_RTMP_RECORD_KEYFRAMES 0x08 -#define NGX_RTMP_RECORD_MANUAL 0x10 - - -typedef struct { - ngx_str_t id; - ngx_uint_t flags; - ngx_str_t path; - size_t max_size; - size_t max_frames; - ngx_msec_t interval; - ngx_str_t suffix; - ngx_flag_t unique; - ngx_flag_t append; - ngx_flag_t lock_file; - ngx_flag_t notify; - ngx_url_t *url; - - void **rec_conf; - ngx_array_t rec; /* ngx_rtmp_record_app_conf_t * */ -} ngx_rtmp_record_app_conf_t; - - -typedef struct { - ngx_rtmp_record_app_conf_t *conf; - ngx_file_t file; - ngx_uint_t nframes; - uint32_t epoch, time_shift; - ngx_time_t last; - time_t timestamp; - unsigned failed:1; - unsigned initialized:1; - unsigned aac_header_sent:1; - unsigned avc_header_sent:1; - unsigned video_key_sent:1; - unsigned audio:1; - unsigned video:1; -} ngx_rtmp_record_rec_ctx_t; - - -typedef struct { - ngx_array_t rec; /* ngx_rtmp_record_rec_ctx_t */ - u_char name[NGX_RTMP_MAX_NAME]; - u_char args[NGX_RTMP_MAX_ARGS]; -} ngx_rtmp_record_ctx_t; - - -ngx_uint_t ngx_rtmp_record_find(ngx_rtmp_record_app_conf_t *racf, - ngx_str_t *id); - - -/* Manual recording control, - * 'n' is record node index in config array. - * Note: these functions allocate path in static buffer */ - -ngx_int_t ngx_rtmp_record_open(ngx_rtmp_session_t *s, ngx_uint_t n, - ngx_str_t *path); -ngx_int_t ngx_rtmp_record_close(ngx_rtmp_session_t *s, ngx_uint_t n, - ngx_str_t *path); - - -typedef struct { - ngx_str_t recorder; - ngx_str_t path; -} ngx_rtmp_record_done_t; - - -typedef ngx_int_t (*ngx_rtmp_record_done_pt)(ngx_rtmp_session_t *s, - ngx_rtmp_record_done_t *v); - - -extern ngx_rtmp_record_done_pt ngx_rtmp_record_done; - - -extern ngx_module_t ngx_rtmp_record_module; - - -#endif /* _NGX_RTMP_RECORD_H_INCLUDED_ */ diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_send.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_send.c deleted file mode 100644 index cc54afc692..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_send.c +++ /dev/null @@ -1,699 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include -#include "ngx_rtmp.h" -#include "ngx_rtmp_amf.h" -#include "ngx_rtmp_streams.h" -#include "ngx_rbuf.h" - - -#define NGX_RTMP_USER_START(s, tp) \ - ngx_chain_t *__l; \ - ngx_buf_t *__b; \ - ngx_rtmp_core_srv_conf_t *__cscf; \ - ngx_rtmp_frame_t *__f; \ - \ - __cscf = ngx_rtmp_get_module_srv_conf( \ - s, ngx_rtmp_core_module); \ - \ - __f = ngx_rtmp_shared_alloc_frame(__cscf->chunk_size, NULL, 1); \ - __f->hdr.type = tp; \ - __f->hdr.csid = 2; \ - __l = __f->chain; \ - if (__l == NULL) { \ - return NULL; \ - } \ - __b = __l->buf; - -#define NGX_RTMP_UCTL_START(s, type, utype) \ - NGX_RTMP_USER_START(s, type); \ - *(__b->last++) = (u_char)((utype) >> 8); \ - *(__b->last++) = (u_char)(utype); - -#define NGX_RTMP_USER_OUT1(v) \ - *(__b->last++) = ((u_char*)&v)[0]; - -#define NGX_RTMP_USER_OUT4(v) \ - *(__b->last++) = ((u_char*)&v)[3]; \ - *(__b->last++) = ((u_char*)&v)[2]; \ - *(__b->last++) = ((u_char*)&v)[1]; \ - *(__b->last++) = ((u_char*)&v)[0]; - -#define NGX_RTMP_USER_END(s) \ - return __f; - - -static ngx_int_t -ngx_rtmp_send_shared_packet(ngx_rtmp_session_t *s, ngx_rtmp_frame_t *frame) -{ - ngx_int_t rc; - - if (frame == NULL) { - return NGX_ERROR; - } - - rc = ngx_rtmp_send_message(s, frame, 0); - - ngx_rtmp_shared_free_frame(frame); - - return rc; -} - - -/* Protocol control messages */ - -ngx_rtmp_frame_t * -ngx_rtmp_create_chunk_size(ngx_rtmp_session_t *s, uint32_t chunk_size) -{ - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "chunk_size=%uD", chunk_size); - - { - NGX_RTMP_USER_START(s, NGX_RTMP_MSG_CHUNK_SIZE); - - NGX_RTMP_USER_OUT4(chunk_size); - - NGX_RTMP_USER_END(s); - } -} - - -ngx_int_t -ngx_rtmp_send_chunk_size(ngx_rtmp_session_t *s, uint32_t chunk_size) -{ - return ngx_rtmp_send_shared_packet(s, - ngx_rtmp_create_chunk_size(s, chunk_size)); -} - - -ngx_rtmp_frame_t * -ngx_rtmp_create_abort(ngx_rtmp_session_t *s, uint32_t csid) -{ - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "create: abort csid=%uD", csid); - - { - NGX_RTMP_USER_START(s, NGX_RTMP_MSG_CHUNK_SIZE); - - NGX_RTMP_USER_OUT4(csid); - - NGX_RTMP_USER_END(s); - } -} - - -ngx_int_t -ngx_rtmp_send_abort(ngx_rtmp_session_t *s, uint32_t csid) -{ - return ngx_rtmp_send_shared_packet(s, - ngx_rtmp_create_abort(s, csid)); -} - - -ngx_rtmp_frame_t * -ngx_rtmp_create_ack(ngx_rtmp_session_t *s, uint32_t seq) -{ - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "create: ack seq=%uD", seq); - - { - NGX_RTMP_USER_START(s, NGX_RTMP_MSG_ACK); - - NGX_RTMP_USER_OUT4(seq); - - NGX_RTMP_USER_END(s); - } -} - - -ngx_int_t -ngx_rtmp_send_ack(ngx_rtmp_session_t *s, uint32_t seq) -{ - return ngx_rtmp_send_shared_packet(s, - ngx_rtmp_create_ack(s, seq)); -} - - -ngx_rtmp_frame_t * -ngx_rtmp_create_ack_size(ngx_rtmp_session_t *s, uint32_t ack_size) -{ - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "create: ack_size=%uD", ack_size); - - { - NGX_RTMP_USER_START(s, NGX_RTMP_MSG_ACK_SIZE); - - NGX_RTMP_USER_OUT4(ack_size); - - NGX_RTMP_USER_END(s); - } -} - - -ngx_int_t -ngx_rtmp_send_ack_size(ngx_rtmp_session_t *s, uint32_t ack_size) -{ - return ngx_rtmp_send_shared_packet(s, - ngx_rtmp_create_ack_size(s, ack_size)); -} - - -ngx_rtmp_frame_t * -ngx_rtmp_create_bandwidth(ngx_rtmp_session_t *s, uint32_t ack_size, - uint8_t limit_type) -{ - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->log, 0, - "create: bandwidth ack_size=%uD limit=%d", - ack_size, (int)limit_type); - - { - NGX_RTMP_USER_START(s, NGX_RTMP_MSG_BANDWIDTH); - - NGX_RTMP_USER_OUT4(ack_size); - NGX_RTMP_USER_OUT1(limit_type); - - NGX_RTMP_USER_END(s); - } -} - - -ngx_int_t -ngx_rtmp_send_bandwidth(ngx_rtmp_session_t *s, uint32_t ack_size, - uint8_t limit_type) -{ - return ngx_rtmp_send_shared_packet(s, - ngx_rtmp_create_bandwidth(s, ack_size, limit_type)); -} - - -/* User control messages */ - -ngx_rtmp_frame_t * -ngx_rtmp_create_stream_begin(ngx_rtmp_session_t *s, uint32_t msid) -{ - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "create: stream_begin msid=%uD", msid); - - { - NGX_RTMP_UCTL_START(s, NGX_RTMP_MSG_USER, NGX_RTMP_USER_STREAM_BEGIN); - - NGX_RTMP_USER_OUT4(msid); - - NGX_RTMP_USER_END(s); - } -} - - -ngx_int_t -ngx_rtmp_send_stream_begin(ngx_rtmp_session_t *s, uint32_t msid) -{ - return ngx_rtmp_send_shared_packet(s, - ngx_rtmp_create_stream_begin(s, msid)); -} - - -ngx_rtmp_frame_t * -ngx_rtmp_create_stream_eof(ngx_rtmp_session_t *s, uint32_t msid) -{ - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "create: stream_end msid=%uD", msid); - - { - NGX_RTMP_UCTL_START(s, NGX_RTMP_MSG_USER, NGX_RTMP_USER_STREAM_EOF); - - NGX_RTMP_USER_OUT4(msid); - - NGX_RTMP_USER_END(s); - } -} - - -ngx_int_t -ngx_rtmp_send_stream_eof(ngx_rtmp_session_t *s, uint32_t msid) -{ - return ngx_rtmp_send_shared_packet(s, - ngx_rtmp_create_stream_eof(s, msid)); -} - - -ngx_rtmp_frame_t * -ngx_rtmp_create_stream_dry(ngx_rtmp_session_t *s, uint32_t msid) -{ - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "create: stream_dry msid=%uD", msid); - - { - NGX_RTMP_UCTL_START(s, NGX_RTMP_MSG_USER, NGX_RTMP_USER_STREAM_DRY); - - NGX_RTMP_USER_OUT4(msid); - - NGX_RTMP_USER_END(s); - } -} - - -ngx_int_t -ngx_rtmp_send_stream_dry(ngx_rtmp_session_t *s, uint32_t msid) -{ - return ngx_rtmp_send_shared_packet(s, - ngx_rtmp_create_stream_dry(s, msid)); -} - - -ngx_rtmp_frame_t * -ngx_rtmp_create_set_buflen(ngx_rtmp_session_t *s, uint32_t msid, - uint32_t buflen_msec) -{ - ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->log, 0, - "create: set_buflen msid=%uD buflen=%uD", - msid, buflen_msec); - - { - NGX_RTMP_UCTL_START(s, NGX_RTMP_MSG_USER, NGX_RTMP_USER_SET_BUFLEN); - - NGX_RTMP_USER_OUT4(msid); - NGX_RTMP_USER_OUT4(buflen_msec); - - NGX_RTMP_USER_END(s); - } -} - - -ngx_int_t -ngx_rtmp_send_set_buflen(ngx_rtmp_session_t *s, uint32_t msid, - uint32_t buflen_msec) -{ - return ngx_rtmp_send_shared_packet(s, - ngx_rtmp_create_set_buflen(s, msid, buflen_msec)); -} - - -ngx_rtmp_frame_t * -ngx_rtmp_create_recorded(ngx_rtmp_session_t *s, uint32_t msid) -{ - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "create: recorded msid=%uD", msid); - - { - NGX_RTMP_UCTL_START(s, NGX_RTMP_MSG_USER, NGX_RTMP_USER_RECORDED); - - NGX_RTMP_USER_OUT4(msid); - - NGX_RTMP_USER_END(s); - } -} - - -ngx_int_t -ngx_rtmp_send_recorded(ngx_rtmp_session_t *s, uint32_t msid) -{ - return ngx_rtmp_send_shared_packet(s, - ngx_rtmp_create_recorded(s, msid)); -} - - -ngx_rtmp_frame_t * -ngx_rtmp_create_ping_request(ngx_rtmp_session_t *s, uint32_t timestamp) -{ - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "create: ping_request timestamp=%uD", timestamp); - - { - NGX_RTMP_UCTL_START(s, NGX_RTMP_MSG_USER, NGX_RTMP_USER_PING_REQUEST); - - NGX_RTMP_USER_OUT4(timestamp); - - NGX_RTMP_USER_END(s); - } -} - - -ngx_int_t -ngx_rtmp_send_ping_request(ngx_rtmp_session_t *s, uint32_t timestamp) -{ - return ngx_rtmp_send_shared_packet(s, - ngx_rtmp_create_ping_request(s, timestamp)); -} - - -ngx_rtmp_frame_t * -ngx_rtmp_create_ping_response(ngx_rtmp_session_t *s, uint32_t timestamp) -{ - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "create: ping_response timestamp=%uD", timestamp); - - { - NGX_RTMP_UCTL_START(s, NGX_RTMP_MSG_USER, NGX_RTMP_USER_PING_RESPONSE); - - NGX_RTMP_USER_OUT4(timestamp); - - NGX_RTMP_USER_END(s); - } -} - - -ngx_int_t -ngx_rtmp_send_ping_response(ngx_rtmp_session_t *s, uint32_t timestamp) -{ - return ngx_rtmp_send_shared_packet(s, - ngx_rtmp_create_ping_response(s, timestamp)); -} - - -static ngx_chain_t * -ngx_rtmp_alloc_amf_buf(void *arg) -{ - return ngx_get_chainbuf(((ngx_rtmp_core_srv_conf_t *)arg)->chunk_size, 1); -} - - -/* AMF sender */ - -/* NOTE: this function does not free shared bufs on error */ -ngx_int_t -ngx_rtmp_append_amf(ngx_rtmp_session_t *s, - ngx_chain_t **first, ngx_chain_t **last, - ngx_rtmp_amf_elt_t *elts, size_t nelts) -{ - ngx_rtmp_amf_ctx_t act; - ngx_rtmp_core_srv_conf_t *cscf; - ngx_int_t rc; - - cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module); - - memset(&act, 0, sizeof(act)); - act.arg = cscf; - act.alloc = ngx_rtmp_alloc_amf_buf; - act.log = s->log; - - if (first) { - act.first = *first; - } - - if (last) { - act.link = *last; - } - - rc = ngx_rtmp_amf_write(&act, elts, nelts); - - if (first) { - *first = act.first; - } - - if (last) { - *last = act.link; - } - - return rc; -} - - -ngx_rtmp_frame_t * -ngx_rtmp_create_amf(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_rtmp_amf_elt_t *elts, size_t nelts) -{ - ngx_int_t rc; - ngx_rtmp_core_srv_conf_t *cscf; - ngx_rtmp_frame_t *frame; - - ngx_log_debug1(NGX_LOG_DEBUG_RTMP, s->log, 0, - "create: amf nelts=%ui", nelts); - - cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module); - - frame = ngx_rtmp_shared_alloc_frame(cscf->chunk_size, NULL, 1); - frame->hdr = *h; - - rc = ngx_rtmp_append_amf(s, &frame->chain, &frame->chain, elts, nelts); - - if (rc != NGX_OK) { - ngx_rtmp_shared_free_frame(frame); - return NULL; - } - - return frame; -} - - -ngx_int_t -ngx_rtmp_send_amf(ngx_rtmp_session_t *s, ngx_rtmp_header_t *h, - ngx_rtmp_amf_elt_t *elts, size_t nelts) -{ - return ngx_rtmp_send_shared_packet(s, - ngx_rtmp_create_amf(s, h, elts, nelts)); -} - - -ngx_rtmp_frame_t * -ngx_rtmp_create_error(ngx_rtmp_session_t *s, char *code, char* level, - char *desc) -{ - ngx_rtmp_header_t h; - static double trans; - - static ngx_rtmp_amf_elt_t out_inf[] = { - - { NGX_RTMP_AMF_STRING, - ngx_string("level"), - NULL, 0 }, - - { NGX_RTMP_AMF_STRING, - ngx_string("code"), - NULL, 0 }, - - { NGX_RTMP_AMF_STRING, - ngx_string("description"), - NULL, 0 }, - }; - - static ngx_rtmp_amf_elt_t out_elts[] = { - - { NGX_RTMP_AMF_STRING, - ngx_null_string, - "_error", 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_null_string, - &trans, 0 }, - - { NGX_RTMP_AMF_NULL, - ngx_null_string, - NULL, 0 }, - - { NGX_RTMP_AMF_OBJECT, - ngx_null_string, - out_inf, - sizeof(out_inf) }, - }; - - ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->log, 0, - "create: error code='%s' level='%s' desc='%s'", - code, level, desc); - - out_inf[0].data = level; - out_inf[1].data = code; - out_inf[2].data = desc; - - memset(&h, 0, sizeof(h)); - - h.type = NGX_RTMP_MSG_AMF_CMD; - h.csid = NGX_RTMP_CSID_AMF; - h.msid = NGX_RTMP_MSID; - - return ngx_rtmp_create_amf(s, &h, out_elts, - sizeof(out_elts) / sizeof(out_elts[0])); -} - - -ngx_int_t -ngx_rtmp_send_error(ngx_rtmp_session_t *s, char *code, char* level, char *desc) -{ - return ngx_rtmp_send_shared_packet(s, - ngx_rtmp_create_error(s, code, level, desc)); -} - - -ngx_rtmp_frame_t * -ngx_rtmp_create_status(ngx_rtmp_session_t *s, char *code, char* level, - char *desc) -{ - ngx_rtmp_header_t h; - static double trans; - - static ngx_rtmp_amf_elt_t out_inf[] = { - - { NGX_RTMP_AMF_STRING, - ngx_string("level"), - NULL, 0 }, - - { NGX_RTMP_AMF_STRING, - ngx_string("code"), - NULL, 0 }, - - { NGX_RTMP_AMF_STRING, - ngx_string("description"), - NULL, 0 }, - }; - - static ngx_rtmp_amf_elt_t out_elts[] = { - - { NGX_RTMP_AMF_STRING, - ngx_null_string, - "onStatus", 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_null_string, - &trans, 0 }, - - { NGX_RTMP_AMF_NULL, - ngx_null_string, - NULL, 0 }, - - { NGX_RTMP_AMF_OBJECT, - ngx_null_string, - out_inf, - sizeof(out_inf) }, - }; - - ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->log, 0, - "create: status code='%s' level='%s' desc='%s'", - code, level, desc); - - out_inf[0].data = level; - out_inf[1].data = code; - out_inf[2].data = desc; - - memset(&h, 0, sizeof(h)); - - h.type = NGX_RTMP_MSG_AMF_CMD; - h.csid = NGX_RTMP_CSID_AMF; - h.msid = NGX_RTMP_MSID; - - return ngx_rtmp_create_amf(s, &h, out_elts, - sizeof(out_elts) / sizeof(out_elts[0])); -} - - -ngx_int_t -ngx_rtmp_send_status(ngx_rtmp_session_t *s, char *code, char* level, char *desc) -{ - return ngx_rtmp_send_shared_packet(s, - ngx_rtmp_create_status(s, code, level, desc)); -} - - -ngx_rtmp_frame_t * -ngx_rtmp_create_play_status(ngx_rtmp_session_t *s, char *code, char* level, - ngx_uint_t duration, ngx_uint_t bytes) -{ - ngx_rtmp_header_t h; - static double dduration; - static double dbytes; - - static ngx_rtmp_amf_elt_t out_inf[] = { - - { NGX_RTMP_AMF_STRING, - ngx_string("code"), - NULL, 0 }, - - { NGX_RTMP_AMF_STRING, - ngx_string("level"), - NULL, 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_string("duration"), - &dduration, 0 }, - - { NGX_RTMP_AMF_NUMBER, - ngx_string("bytes"), - &dbytes, 0 }, - }; - - static ngx_rtmp_amf_elt_t out_elts[] = { - - { NGX_RTMP_AMF_STRING, - ngx_null_string, - "onPlayStatus", 0 }, - - { NGX_RTMP_AMF_OBJECT, - ngx_null_string, - out_inf, - sizeof(out_inf) }, - }; - - ngx_log_debug4(NGX_LOG_DEBUG_RTMP, s->log, 0, - "create: play_status code='%s' level='%s' " - "duration=%ui bytes=%ui", - code, level, duration, bytes); - - out_inf[0].data = code; - out_inf[1].data = level; - - dduration = duration; - dbytes = bytes; - - memset(&h, 0, sizeof(h)); - - h.type = NGX_RTMP_MSG_AMF_META; - h.csid = NGX_RTMP_CSID_AMF; - h.msid = NGX_RTMP_MSID; - h.timestamp = duration; - - return ngx_rtmp_create_amf(s, &h, out_elts, - sizeof(out_elts) / sizeof(out_elts[0])); -} - - -ngx_int_t -ngx_rtmp_send_play_status(ngx_rtmp_session_t *s, char *code, char* level, - ngx_uint_t duration, ngx_uint_t bytes) -{ - return ngx_rtmp_send_shared_packet(s, - ngx_rtmp_create_play_status(s, code, level, duration, bytes)); -} - - -ngx_rtmp_frame_t * -ngx_rtmp_create_sample_access(ngx_rtmp_session_t *s) -{ - ngx_rtmp_header_t h; - - static int access = 1; - - static ngx_rtmp_amf_elt_t access_elts[] = { - - { NGX_RTMP_AMF_STRING, - ngx_null_string, - "|RtmpSampleAccess", 0 }, - - { NGX_RTMP_AMF_BOOLEAN, - ngx_null_string, - &access, 0 }, - - { NGX_RTMP_AMF_BOOLEAN, - ngx_null_string, - &access, 0 }, - }; - - memset(&h, 0, sizeof(h)); - - h.type = NGX_RTMP_MSG_AMF_META; - h.csid = NGX_RTMP_CSID_AMF; - h.msid = NGX_RTMP_MSID; - - return ngx_rtmp_create_amf(s, &h, access_elts, - sizeof(access_elts) / sizeof(access_elts[0])); -} - - -ngx_int_t -ngx_rtmp_send_sample_access(ngx_rtmp_session_t *s) -{ - return ngx_rtmp_send_shared_packet(s, - ngx_rtmp_create_sample_access(s)); -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_shared_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_shared_module.c deleted file mode 100644 index cdbf5d0de4..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_shared_module.c +++ /dev/null @@ -1,402 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include -#include -#include "ngx_rtmp.h" -#include "ngx_rbuf.h" - - -static void *ngx_rtmp_shared_create_conf(ngx_cycle_t *cycle); -static char *ngx_rtmp_shared_init_conf(ngx_cycle_t *cycle, void *conf); - - -/* 1316 == 188 * 7 RTP pack 7 MPEG-TS packets as a RTP package */ -#define NGX_MPEGTS_BUF_SIZE 1316 - -typedef struct { - ngx_rtmp_frame_t *free_frame; - ngx_mpegts_frame_t *free_mpegts_frame; - ngx_pool_t *pool; - - ngx_uint_t nalloc_frame; - ngx_uint_t nfree_frame; -} ngx_rtmp_shared_conf_t; - - -static ngx_command_t ngx_rtmp_shared_commands[] = { - - ngx_null_command -}; - - -static ngx_core_module_t ngx_rtmp_shared_module_ctx = { - ngx_string("rtmp_shared"), - ngx_rtmp_shared_create_conf, /* create conf */ - ngx_rtmp_shared_init_conf /* init conf */ -}; - - -ngx_module_t ngx_rtmp_shared_module = { - NGX_MODULE_V1, - &ngx_rtmp_shared_module_ctx, /* module context */ - ngx_rtmp_shared_commands, /* module directives */ - NGX_CORE_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void * -ngx_rtmp_shared_create_conf(ngx_cycle_t *cycle) -{ - ngx_rtmp_shared_conf_t *rscf; - - rscf = ngx_pcalloc(cycle->pool, sizeof(ngx_rtmp_shared_conf_t)); - if (rscf == NULL) { - return NULL; - } - - return rscf; -} - - -static char * -ngx_rtmp_shared_init_conf(ngx_cycle_t *cycle, void *conf) -{ - ngx_rtmp_shared_conf_t *rscf = conf; - - rscf->pool = ngx_create_pool(4096, cycle->log); - if (rscf->pool == NULL) { - return NGX_CONF_ERROR; - } - - return NGX_CONF_OK; -} - - -ngx_int_t -ngx_rtmp_prepare_merge_frame(ngx_rtmp_session_t *s) -{ - ngx_rtmp_core_app_conf_t *cacf; - ngx_chain_t *ll, **ln; - ngx_uint_t n; - - // merge frame not send completely - if (s->out_chain) { - return NGX_OK; - } - - cacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_core_module); - - ngx_rtmp_free_merge_frame(s); - - ln = &s->out_chain; - - for (n = 0; n < cacf->merge_frame && s->out_pos != s->out_last; ++n) { - // save frame chain with rtmp chunk or flv tag - s->merge[n] = s->prepare_handler(s); - - if (s->out_pos == s->out_last) { - break; - } - - // normal link to chain all merge frames - for (ll = s->merge[n]; ll; ll = ll->next, ln = &(*ln)->next) { - *ln = ngx_alloc_chain_link(s->pool); - if (*ln == NULL) { - s->nframe = n; - return NGX_ERROR; - } - (*ln)->next = NULL; - - (*ln)->buf = ll->buf; - } - - // save frame prepare to send - if (s->live_type == NGX_MPEGTS_LIVE) { - s->prepare_mpegts_frame[n] = s->mpegts_out[s->out_pos]; - } else { - s->prepare_frame[n] = s->out[s->out_pos]; - } - - ++s->out_pos; - s->out_pos %= s->out_queue; - } - - s->nframe = n; - - return NGX_OK; -} - -void -ngx_rtmp_free_merge_frame(ngx_rtmp_session_t *s) -{ - ngx_uint_t n; - - if (s->live_type == NGX_MPEGTS_LIVE) { - for (n = 0; n < s->nframe; ++n) { - ngx_put_chainbufs(s->merge[n]); - s->merge[n] = NULL; - - ngx_rtmp_shared_free_mpegts_frame(s->prepare_mpegts_frame[n]); - s->prepare_mpegts_frame[n] = NULL; - } - } else { - for (n = 0; n < s->nframe; ++n) { - ngx_put_chainbufs(s->merge[n]); - s->merge[n] = NULL; - - ngx_rtmp_shared_free_frame(s->prepare_frame[n]); - s->prepare_frame[n] = NULL; - } - } - - s->nframe = 0; -} - -void -ngx_rtmp_shared_append_chain(ngx_rtmp_frame_t *frame, size_t size, - ngx_chain_t *cl, ngx_flag_t mandatory) -{ - ngx_chain_t **ll; - u_char *p; - size_t len; - - for (ll = &frame->chain; (*ll) && (*ll)->next; ll = &(*ll)->next); - - if (cl == NULL) { - if (mandatory) { - *ll = ngx_get_chainbuf(size, 1); - } - return; - } - - p = cl->buf->pos; - - for (;;) { - if ((*ll) && (*ll)->buf->last == (*ll)->buf->end) { - ll = &(*ll)->next; - } - - if (*ll == NULL) { - *ll = ngx_get_chainbuf(size, 1); - } - - while ((*ll)->buf->end - (*ll)->buf->last >= cl->buf->last - p) { - len = cl->buf->last - p; - (*ll)->buf->last = ngx_cpymem((*ll)->buf->last, p, len); - cl = cl->next; - if (cl == NULL) { - return; - } - p = cl->buf->pos; - } - - len = (*ll)->buf->end - (*ll)->buf->last; - (*ll)->buf->last = ngx_cpymem((*ll)->buf->last, p, len); - p += len; - } -} - -ngx_rtmp_frame_t * -ngx_rtmp_shared_alloc_frame(size_t size, ngx_chain_t *cl, ngx_flag_t mandatory) -{ - ngx_rtmp_shared_conf_t *rscf; - ngx_rtmp_frame_t *frame; - - rscf = (ngx_rtmp_shared_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_rtmp_shared_module); - - frame = rscf->free_frame; - if (frame) { - rscf->free_frame = frame->next; - frame->chain = NULL; - --rscf->nfree_frame; - } else { - frame = ngx_pcalloc(rscf->pool, sizeof(ngx_rtmp_frame_t)); - if (frame == NULL) { - return NULL; - } - ++rscf->nalloc_frame; - } - - frame->ref = 1; - frame->next = NULL; - - ngx_rtmp_shared_append_chain(frame, size, cl, mandatory); - - return frame; -} - -void -ngx_rtmp_shared_free_frame(ngx_rtmp_frame_t *frame) -{ - ngx_rtmp_shared_conf_t *rscf; - ngx_chain_t *cl; - - rscf = (ngx_rtmp_shared_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_rtmp_shared_module); - - if (frame == NULL || --frame->ref) { - return; - } - - /* recycle chainbuf */ - cl = frame->chain; - while (cl) { - frame->chain = cl->next; - ngx_put_chainbuf(cl); - cl = frame->chain; - } - - /* recycle frame */ - frame->next = rscf->free_frame; - rscf->free_frame = frame; - ++rscf->nfree_frame; -} - -void -ngx_mpegts_shared_append_chain(ngx_mpegts_frame_t *frame, ngx_chain_t *cl, - ngx_flag_t mandatory) -{ - ngx_chain_t **ll; - u_char *p; - size_t len; - - for (ll = &frame->chain; (*ll) && (*ll)->next; ll = &(*ll)->next); - - if (cl == NULL) { - if (mandatory) { - *ll = ngx_get_chainbuf(NGX_MPEGTS_BUF_SIZE, 1); - } - return; - } - - p = cl->buf->pos; - - for (;;) { - if ((*ll) && (*ll)->buf->last == (*ll)->buf->end) { - ll = &(*ll)->next; - } - - if (*ll == NULL) { - *ll = ngx_get_chainbuf(NGX_MPEGTS_BUF_SIZE, 1); - } - - while ((*ll)->buf->end - (*ll)->buf->last >= cl->buf->last - p) { - len = cl->buf->last - p; - (*ll)->buf->last = ngx_cpymem((*ll)->buf->last, p, len); - cl = cl->next; - if (cl == NULL) { - return; - } - p = cl->buf->pos; - } - - len = (*ll)->buf->end - (*ll)->buf->last; - (*ll)->buf->last = ngx_cpymem((*ll)->buf->last, p, len); - p += len; - } -} - -ngx_mpegts_frame_t * -ngx_rtmp_shared_alloc_mpegts_frame(ngx_chain_t *cl, ngx_flag_t mandatory) -{ - ngx_rtmp_shared_conf_t *rscf; - ngx_mpegts_frame_t *frame; - - rscf = (ngx_rtmp_shared_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_rtmp_shared_module); - - frame = rscf->free_mpegts_frame; - if (frame) { - rscf->free_mpegts_frame = frame->next; - --rscf->nfree_frame; - } else { - frame = ngx_pcalloc(rscf->pool, sizeof(ngx_mpegts_frame_t)); - if (frame == NULL) { - return NULL; - } - ++rscf->nalloc_frame; - } - - ngx_memset(frame, 0, sizeof(ngx_mpegts_frame_t)); - frame->ref = 1; - frame->next = NULL; - - ngx_mpegts_shared_append_chain(frame, cl, mandatory); - - return frame; -} - -void -ngx_rtmp_shared_free_mpegts_frame(ngx_mpegts_frame_t *frame) -{ - ngx_rtmp_shared_conf_t *rscf; - ngx_chain_t *cl; - - rscf = (ngx_rtmp_shared_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_rtmp_shared_module); - - if (frame == NULL || --frame->ref) { - return; - } - - /* recycle chainbuf */ - cl = frame->chain; - while (cl) { - frame->chain = cl->next; - ngx_put_chainbuf(cl); - cl = frame->chain; - } - - /* recycle frame */ - frame->next = rscf->free_mpegts_frame; - rscf->free_mpegts_frame = frame; - ++rscf->nfree_frame; -} - -ngx_chain_t * -ngx_rtmp_shared_state(ngx_http_request_t *r) -{ - ngx_rtmp_shared_conf_t *rscf; - ngx_chain_t *cl; - ngx_buf_t *b; - size_t len; - - rscf = (ngx_rtmp_shared_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_rtmp_shared_module); - - len = sizeof("##########rtmp shared state##########\n") - 1 - + sizeof("ngx_rtmp_shared alloc frame: \n") - 1 + NGX_OFF_T_LEN - + sizeof("ngx_rtmp_shared free frame: \n") - 1 + NGX_OFF_T_LEN; - - cl = ngx_alloc_chain_link(r->pool); - if (cl == NULL) { - return NULL; - } - cl->next = NULL; - - b = ngx_create_temp_buf(r->pool, len); - if (b == NULL) { - return NULL; - } - cl->buf = b; - - b->last = ngx_snprintf(b->last, len, - "##########rtmp shared state##########\n" - "ngx_rtmp_shared alloc frame: %ui\n" - "ngx_rtmp_shared free frame: %ui\n", - rscf->nalloc_frame, rscf->nfree_frame); - - return cl; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_stat_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_stat_module.c deleted file mode 100644 index 7a5aed0067..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_stat_module.c +++ /dev/null @@ -1,754 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include -#include -#include -#include "ngx_rtmp.h" -#include "ngx_live.h" -#include "ngx_rtmp_version.h" -#include "ngx_rtmp_live_module.h" -#include "ngx_rtmp_codec_module.h" - - -static ngx_int_t ngx_rtmp_stat_init_process(ngx_cycle_t *cycle); -static char *ngx_rtmp_stat(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -static ngx_int_t ngx_rtmp_stat_postconfiguration(ngx_conf_t *cf); -static void * ngx_rtmp_stat_create_loc_conf(ngx_conf_t *cf); -static char * ngx_rtmp_stat_merge_loc_conf(ngx_conf_t *cf, - void *parent, void *child); - - -static time_t start_time; - - -#define NGX_RTMP_STAT_ALL 0xff -#define NGX_RTMP_STAT_GLOBAL 0x01 -#define NGX_RTMP_STAT_LIVE 0x02 -#define NGX_RTMP_STAT_CLIENTS 0x04 -#define NGX_RTMP_STAT_PLAY 0x08 - -/* - * global: stat-{bufs-{total,free,used}, total bytes in/out, bw in/out} - cscf -*/ - - -typedef struct { - ngx_uint_t stat; - ngx_str_t stylesheet; -} ngx_rtmp_stat_loc_conf_t; - - -static ngx_conf_bitmask_t ngx_rtmp_stat_masks[] = { - { ngx_string("all"), NGX_RTMP_STAT_ALL }, - { ngx_string("global"), NGX_RTMP_STAT_GLOBAL }, - { ngx_string("live"), NGX_RTMP_STAT_LIVE }, - { ngx_string("clients"), NGX_RTMP_STAT_CLIENTS }, - { ngx_null_string, 0 } -}; - - -static ngx_command_t ngx_rtmp_stat_commands[] = { - - { ngx_string("rtmp_stat"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, - ngx_rtmp_stat, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_rtmp_stat_loc_conf_t, stat), - ngx_rtmp_stat_masks }, - - { ngx_string("rtmp_stat_stylesheet"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_rtmp_stat_loc_conf_t, stylesheet), - NULL }, - - ngx_null_command -}; - - -static ngx_http_module_t ngx_rtmp_stat_module_ctx = { - NULL, /* preconfiguration */ - ngx_rtmp_stat_postconfiguration, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - ngx_rtmp_stat_create_loc_conf, /* create location configuration */ - ngx_rtmp_stat_merge_loc_conf, /* merge location configuration */ -}; - - -ngx_module_t ngx_rtmp_stat_module = { - NGX_MODULE_V1, - &ngx_rtmp_stat_module_ctx, /* module context */ - ngx_rtmp_stat_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - ngx_rtmp_stat_init_process, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -#define NGX_RTMP_STAT_BUFSIZE 256 - - -static ngx_int_t -ngx_rtmp_stat_init_process(ngx_cycle_t *cycle) -{ - /* - * HTTP process initializer is called - * after event module initializer - * so we can run posted events here - */ - - ngx_event_process_posted(cycle, &ngx_rtmp_init_queue); - - return NGX_OK; -} - - -/* ngx_escape_html does not escape characters out of ASCII range - * which are bad for xslt */ - -static void * -ngx_rtmp_stat_escape(ngx_http_request_t *r, void *data, size_t len) -{ - u_char *p, *np; - void *new_data; - size_t n; - - p = data; - - for (n = 0; n < len; ++n, ++p) { - if (*p < 0x20 || *p >= 0x7f) { - break; - } - } - - if (n == len) { - return data; - } - - new_data = ngx_palloc(r->pool, len); - if (new_data == NULL) { - return NULL; - } - - p = data; - np = new_data; - - for (n = 0; n < len; ++n, ++p, ++np) { - *np = (*p < 0x20 || *p >= 0x7f) ? (u_char) ' ' : *p; - } - - return new_data; -} - -#if (NGX_WIN32) -/* - * Fix broken MSVC memcpy optimization for 4-byte data - * when this function is inlined - */ -__declspec(noinline) -#endif - -static void -ngx_rtmp_stat_output(ngx_http_request_t *r, ngx_chain_t ***lll, - void *data, size_t len, ngx_uint_t escape) -{ - ngx_chain_t *cl; - ngx_buf_t *b; - size_t real_len; - - if (len == 0) { - return; - } - - if (escape) { - data = ngx_rtmp_stat_escape(r, data, len); - if (data == NULL) { - return; - } - } - - real_len = escape - ? len + ngx_escape_html(NULL, data, len) - : len; - - cl = **lll; - if (cl && cl->buf->last + real_len > cl->buf->end) { - *lll = &cl->next; - } - - if (**lll == NULL) { - cl = ngx_alloc_chain_link(r->pool); - if (cl == NULL) { - return; - } - b = ngx_create_temp_buf(r->pool, - ngx_max(NGX_RTMP_STAT_BUFSIZE, real_len)); - if (b == NULL || b->pos == NULL) { - return; - } - cl->next = NULL; - cl->buf = b; - **lll = cl; - } - - b = (**lll)->buf; - - if (escape) { - b->last = (u_char *)ngx_escape_html(b->last, data, len); - } else { - b->last = ngx_cpymem(b->last, data, len); - } -} - - -/* These shortcuts assume 2 variables exist in current context: - * ngx_http_request_t *r - * ngx_chain_t ***lll */ - -/* plain data */ -#define NGX_RTMP_STAT(data, len) ngx_rtmp_stat_output(r, lll, data, len, 0) - -/* escaped data */ -#define NGX_RTMP_STAT_E(data, len) ngx_rtmp_stat_output(r, lll, data, len, 1) - -/* literal */ -#define NGX_RTMP_STAT_L(s) NGX_RTMP_STAT((s), sizeof(s) - 1) - -/* ngx_str_t */ -#define NGX_RTMP_STAT_S(s) NGX_RTMP_STAT((s)->data, (s)->len) - -/* escaped ngx_str_t */ -#define NGX_RTMP_STAT_ES(s) NGX_RTMP_STAT_E((s)->data, (s)->len) - -/* C string */ -#define NGX_RTMP_STAT_CS(s) NGX_RTMP_STAT((s), ngx_strlen(s)) - -/* escaped C string */ -#define NGX_RTMP_STAT_ECS(s) NGX_RTMP_STAT_E((s), ngx_strlen(s)) - - -#define NGX_RTMP_STAT_BW 0x01 -#define NGX_RTMP_STAT_BYTES 0x02 -#define NGX_RTMP_STAT_BW_BYTES 0x03 - - -static void -ngx_rtmp_stat_bw(ngx_http_request_t *r, ngx_chain_t ***lll, - ngx_rtmp_bandwidth_t *bw, char *name, - ngx_uint_t flags) -{ - u_char buf[NGX_INT64_LEN + 9]; - - ngx_rtmp_update_bandwidth(bw, 0); - - if (flags & NGX_RTMP_STAT_BW) { - NGX_RTMP_STAT_L("%uLbandwidth * 8) - - buf); - NGX_RTMP_STAT_CS(name); - NGX_RTMP_STAT_L(">\r\n"); - } - - if (flags & NGX_RTMP_STAT_BYTES) { - NGX_RTMP_STAT_L("%uLbytes) - - buf); - NGX_RTMP_STAT_CS(name); - NGX_RTMP_STAT_L(">\r\n"); - } -} - - -#ifdef NGX_RTMP_POOL_DEBUG -static void -ngx_rtmp_stat_get_pool_size(ngx_pool_t *pool, ngx_uint_t *nlarge, - ngx_uint_t *size) -{ - ngx_pool_large_t *l; - ngx_pool_t *p, *n; - - *nlarge = 0; - for (l = pool->large; l; l = l->next) { - ++*nlarge; - } - - *size = 0; - for (p = pool, n = pool->d.next; /* void */; p = n, n = n->d.next) { - *size += (p->d.last - (u_char *)p); - if (n == NULL) { - break; - } - } -} - - -static void -ngx_rtmp_stat_dump_pool(ngx_http_request_t *r, ngx_chain_t ***lll, - ngx_pool_t *pool) -{ - ngx_uint_t nlarge, size; - u_char buf[NGX_INT_T_LEN]; - - size = 0; - nlarge = 0; - ngx_rtmp_stat_get_pool_size(pool, &nlarge, &size); - NGX_RTMP_STAT_L(""); - NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%ui", nlarge) - buf); - NGX_RTMP_STAT_L(""); - NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%ui", size) - buf); - NGX_RTMP_STAT_L("\r\n"); -} -#endif - - - -static void -ngx_rtmp_stat_client(ngx_http_request_t *r, ngx_chain_t ***lll, - ngx_rtmp_session_t *s) -{ - u_char buf[NGX_INT_T_LEN]; - -#ifdef NGX_RTMP_POOL_DEBUG - ngx_rtmp_stat_dump_pool(r, lll, s->pool); -#endif - NGX_RTMP_STAT_L(""); - NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), "%ui", - (ngx_uint_t) s->number) - buf); - NGX_RTMP_STAT_L(""); - - NGX_RTMP_STAT_L("
"); - NGX_RTMP_STAT_ES(s->addr_text); - NGX_RTMP_STAT_L("
"); - - NGX_RTMP_STAT_L(""); - NGX_RTMP_STAT_ES(&(s->remote_addr_text)); - NGX_RTMP_STAT_L(""); - - NGX_RTMP_STAT_L(""); - - if (s->flashver.len) { - NGX_RTMP_STAT_L(""); - NGX_RTMP_STAT_ES(&s->flashver); - NGX_RTMP_STAT_L(""); - } - - if (s->page_url.len) { - NGX_RTMP_STAT_L(""); - NGX_RTMP_STAT_ES(&s->page_url); - NGX_RTMP_STAT_L(""); - } - - if (s->swf_url.len) { - NGX_RTMP_STAT_L(""); - NGX_RTMP_STAT_ES(&s->swf_url); - NGX_RTMP_STAT_L(""); - } -} - - -static char * -ngx_rtmp_stat_get_aac_profile(ngx_uint_t p, ngx_uint_t sbr, ngx_uint_t ps) { - switch (p) { - case 1: - return "Main"; - case 2: - if (ps) { - return "HEv2"; - } - if (sbr) { - return "HE"; - } - return "LC"; - case 3: - return "SSR"; - case 4: - return "LTP"; - case 5: - return "SBR"; - default: - return ""; - } -} - - -static char * -ngx_rtmp_stat_get_avc_profile(ngx_uint_t p) { - switch (p) { - case 66: - return "Baseline"; - case 77: - return "Main"; - case 100: - return "High"; - default: - return ""; - } -} - - -static void -ngx_rtmp_stat_live(ngx_http_request_t *r, ngx_chain_t ***lll, - ngx_live_server_t *srv) -{ - ngx_live_stream_t *stream; - ngx_rtmp_codec_ctx_t *codec; - ngx_rtmp_live_ctx_t *ctx; - ngx_rtmp_session_t *s; - size_t n; - ngx_uint_t nclients, total_nclients; - u_char buf[NGX_INT_T_LEN]; - u_char bbuf[NGX_INT32_LEN]; - ngx_rtmp_stat_loc_conf_t *slcf; - ngx_live_conf_t *lcf; - u_char *cname; - u_char *p; - - slcf = ngx_http_get_module_loc_conf(r, ngx_rtmp_stat_module); - lcf = (ngx_live_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_live_module); - - NGX_RTMP_STAT_L("\r\n"); - - total_nclients = 0; - for (n = 0; n < lcf->stream_buckets; ++n) { - for (stream = srv->streams[n]; stream; stream = stream->next) { - NGX_RTMP_STAT_L("\r\n"); - - NGX_RTMP_STAT_L(""); - p = stream->name + ngx_strlen(stream->name); - while (*p != '/' && p != stream->name) { - p--; - } - - if (p != stream->name) { - p++; - } - - NGX_RTMP_STAT_ECS(p); - NGX_RTMP_STAT_L("\r\n"); - - NGX_RTMP_STAT_L(""); - - ngx_rtmp_stat_bw(r, lll, &stream->bw_in, "in", - NGX_RTMP_STAT_BW_BYTES); - ngx_rtmp_stat_bw(r, lll, &stream->bw_out, "out", - NGX_RTMP_STAT_BW_BYTES); - ngx_rtmp_stat_bw(r, lll, &stream->bw_in_audio, "audio", - NGX_RTMP_STAT_BW); - ngx_rtmp_stat_bw(r, lll, &stream->bw_in_video, "video", - NGX_RTMP_STAT_BW); - - nclients = 0; - codec = NULL; - for (ctx = stream->ctx; ctx; ctx = ctx->next, ++nclients) { - s = ctx->session; - if (slcf->stat & NGX_RTMP_STAT_CLIENTS) { - NGX_RTMP_STAT_L(""); - - ngx_rtmp_stat_client(r, lll, s); - - NGX_RTMP_STAT_L(""); - NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), - "%ui", ctx->ndropped) - buf); - NGX_RTMP_STAT_L(""); - - NGX_RTMP_STAT_L(""); - NGX_RTMP_STAT(bbuf, ngx_snprintf(bbuf, sizeof(bbuf), - "%D", ctx->cs[1].timestamp - - ctx->cs[0].timestamp) - bbuf); - NGX_RTMP_STAT_L(""); - - NGX_RTMP_STAT_L(""); - NGX_RTMP_STAT(bbuf, ngx_snprintf(bbuf, sizeof(bbuf), - "%D", s->current_time) - bbuf); - NGX_RTMP_STAT_L(""); - - if (ctx->publishing) { - NGX_RTMP_STAT_L(""); - } - - if (ctx->active) { - NGX_RTMP_STAT_L(""); - } - - NGX_RTMP_STAT_L("\r\n"); - } - if (ctx->publishing) { - codec = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module); - } - } - total_nclients += nclients; - - if (codec) { - NGX_RTMP_STAT_L(""); - - NGX_RTMP_STAT_L(""); - - NGX_RTMP_STAT_L(""); - - NGX_RTMP_STAT_L("\r\n"); - } - - NGX_RTMP_STAT_L(""); - NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), - "%ui", nclients) - buf); - NGX_RTMP_STAT_L("\r\n"); - - if (stream->publishing) { - NGX_RTMP_STAT_L("\r\n"); - } - - if (stream->active) { - NGX_RTMP_STAT_L("\r\n"); - } - - NGX_RTMP_STAT_L("\r\n"); - } - } - - NGX_RTMP_STAT_L(""); - NGX_RTMP_STAT(buf, ngx_snprintf(buf, sizeof(buf), - "%ui", total_nclients) - buf); - NGX_RTMP_STAT_L("\r\n"); - - NGX_RTMP_STAT_L("\r\n"); -} - - -static ngx_int_t -ngx_rtmp_stat_handler(ngx_http_request_t *r) -{ - ngx_rtmp_stat_loc_conf_t *slcf; - ngx_live_conf_t *lcf; - ngx_live_server_t *psrv; - ngx_chain_t *cl, *l, **ll, ***lll; - size_t n; - off_t len; - static u_char tbuf[NGX_TIME_T_LEN]; - static u_char nbuf[NGX_INT_T_LEN]; - - slcf = ngx_http_get_module_loc_conf(r, ngx_rtmp_stat_module); - if (slcf->stat == 0) { - return NGX_DECLINED; - } - - cl = NULL; - ll = &cl; - lll = ≪ - - NGX_RTMP_STAT_L("\r\n"); - if (slcf->stylesheet.len) { - NGX_RTMP_STAT_L("stylesheet); - NGX_RTMP_STAT_L("\" ?>\r\n"); - } - - NGX_RTMP_STAT_L("\r\n"); - -#ifdef NGINX_VERSION - NGX_RTMP_STAT_L("" NGINX_VERSION "\r\n"); -#endif - -#ifdef NGINX_RTMP_VERSION - NGX_RTMP_STAT_L("" NGINX_RTMP_VERSION "\r\n"); -#endif - -#ifdef NGX_COMPILER - NGX_RTMP_STAT_L("" NGX_COMPILER "\r\n"); -#endif - NGX_RTMP_STAT_L("" __DATE__ " " __TIME__ "\r\n"); - - NGX_RTMP_STAT_L(""); - NGX_RTMP_STAT(nbuf, ngx_snprintf(nbuf, sizeof(nbuf), - "%ui", (ngx_uint_t) ngx_getpid()) - nbuf); - NGX_RTMP_STAT_L("\r\n"); - - NGX_RTMP_STAT_L(""); - NGX_RTMP_STAT(tbuf, ngx_snprintf(tbuf, sizeof(tbuf), - "%T", ngx_cached_time->sec - start_time) - tbuf); - NGX_RTMP_STAT_L("\r\n"); - - NGX_RTMP_STAT_L(""); - NGX_RTMP_STAT(nbuf, ngx_snprintf(nbuf, sizeof(nbuf), - "%ui", ngx_rtmp_naccepted) - nbuf); - NGX_RTMP_STAT_L("\r\n"); - - ngx_rtmp_stat_bw(r, lll, &ngx_rtmp_bw_in, "in", NGX_RTMP_STAT_BW_BYTES); - ngx_rtmp_stat_bw(r, lll, &ngx_rtmp_bw_out, "out", NGX_RTMP_STAT_BW_BYTES); - - lcf = (ngx_live_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_live_module); - - for (n = 0; n < lcf->server_buckets; ++n) { - for (psrv = lcf->servers[n]; psrv; psrv = psrv->next) { - NGX_RTMP_STAT_L("\r\n"); - - NGX_RTMP_STAT_L(""); - NGX_RTMP_STAT(psrv->serverid, ngx_strlen(psrv->serverid)); - NGX_RTMP_STAT_L("\r\n"); - - ngx_rtmp_stat_live(r, lll, psrv); - NGX_RTMP_STAT_L("\r\n"); - } - } - - NGX_RTMP_STAT_L("\r\n"); - - len = 0; - for (l = cl; l; l = l->next) { - len += (l->buf->last - l->buf->pos); - } - ngx_str_set(&r->headers_out.content_type, "text/xml"); - r->headers_out.content_length_n = len; - r->headers_out.status = NGX_HTTP_OK; - ngx_http_send_header(r); - (*ll)->buf->last_buf = 1; - return ngx_http_output_filter(r, cl); -} - - -static void * -ngx_rtmp_stat_create_loc_conf(ngx_conf_t *cf) -{ - ngx_rtmp_stat_loc_conf_t *conf; - - conf = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_stat_loc_conf_t)); - if (conf == NULL) { - return NULL; - } - - conf->stat = 0; - - return conf; -} - - -static char * -ngx_rtmp_stat_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_rtmp_stat_loc_conf_t *prev = parent; - ngx_rtmp_stat_loc_conf_t *conf = child; - - ngx_conf_merge_bitmask_value(conf->stat, prev->stat, 0); - ngx_conf_merge_str_value(conf->stylesheet, prev->stylesheet, ""); - - return NGX_CONF_OK; -} - - -static char * -ngx_rtmp_stat(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_core_loc_conf_t *clcf; - - clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); - clcf->handler = ngx_rtmp_stat_handler; - - return ngx_conf_set_bitmask_slot(cf, cmd, conf); -} - - -static ngx_int_t -ngx_rtmp_stat_postconfiguration(ngx_conf_t *cf) -{ - start_time = ngx_cached_time->sec; - - return NGX_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_streams.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_streams.h deleted file mode 100644 index d957b8e5d5..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_streams.h +++ /dev/null @@ -1,19 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#ifndef _NGX_RTMP_STREAMS_H_INCLUDED_ -#define _NGX_RTMP_STREAMS_H_INCLUDED_ - - -#define NGX_RTMP_MSID 1 - -#define NGX_RTMP_CSID_AMF_INI 3 -#define NGX_RTMP_CSID_AMF 5 -#define NGX_RTMP_CSID_AUDIO 6 -#define NGX_RTMP_CSID_VIDEO 7 - - -#endif /* _NGX_RTMP_STREAMS_H_INCLUDED_ */ diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_sys_stat_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_sys_stat_module.c deleted file mode 100644 index 7c7fae742e..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_sys_stat_module.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include -#include -#include -#include -#include "ngx_rtmp.h" -#include "ngx_rbuf.h" -#include "ngx_poold.h" -#include "ngx_stream_zone_module.h" -#include "ngx_event_timer_module.h" -#include "ngx_event_resolver.h" -#include "ngx_dynamic_resolver.h" -#include "ngx_live.h" - - -static char *ngx_rtmp_sys_stat(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); - - -extern ngx_chain_t *ngx_live_relay_static_state(ngx_http_request_t *r); - - -static ngx_command_t ngx_rtmp_sys_stat_commands[] = { - - { ngx_string("sys_stat"), - NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, - ngx_rtmp_sys_stat, - NGX_HTTP_LOC_CONF_OFFSET, - 0, - NULL }, - - ngx_null_command -}; - - -static ngx_http_module_t ngx_rtmp_sys_stat_module_ctx = { - NULL, /* preconfiguration */ - NULL, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - NULL, /* create location configuration */ - NULL /* merge location configuration */ -}; - - -ngx_module_t ngx_rtmp_sys_stat_module = { - NGX_MODULE_V1, - &ngx_rtmp_sys_stat_module_ctx, /* module context */ - ngx_rtmp_sys_stat_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static ngx_int_t -ngx_rtmp_sys_stat_handler(ngx_http_request_t *r) -{ - ngx_chain_t **ll, *out; - ngx_buf_t *b; - ngx_str_t detail_arg; - ngx_uint_t detail = 0; - size_t len; - - if (ngx_http_arg(r, (u_char *) "detail", sizeof("detail") - 1, &detail_arg) - == NGX_OK) - { - detail = 1; - } - - r->headers_out.status = NGX_HTTP_OK; - ngx_http_send_header(r); - - ll = &out; - - len = sizeof("--------------------------------------------------\n") - 1 - + sizeof("ngx_worker: ngx_process_slot: pid: \n") - 1 - + 3 * NGX_OFF_T_LEN; - - *ll = ngx_alloc_chain_link(r->pool); - if (*ll == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - (*ll)->next = NULL; - - b = ngx_create_temp_buf(r->pool, len); - if (b == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - (*ll)->buf = b; - - b->last = ngx_snprintf(b->last, len, - "--------------------------------------------------\n" - "ngx_worker: %i ngx_process_slot: %i pid: %i\n", - ngx_worker, ngx_process_slot, ngx_pid); - - if (*ll) { - ll = &(*ll)->next; - } - *ll = ngx_live_state(r); - - if (*ll) { - ll = &(*ll)->next; - } - *ll = ngx_live_relay_static_state(r); - - if (*ll) { - ll = &(*ll)->next; - } - *ll = ngx_rtmp_shared_state(r); - - if (*ll) { - ll = &(*ll)->next; - } - *ll = ngx_rbuf_state(r, detail); - - if (*ll) { - ll = &(*ll)->next; - } - *ll = ngx_stream_zone_state(r, 0); - - if (*ll) { - ll = &(*ll)->next; - } - *ll = ngx_event_timer_state(r); - - if (*ll) { - ll = &(*ll)->next; - } - *ll = ngx_event_resolver_state(r); - - if (*ll) { - ll = &(*ll)->next; - } - *ll = ngx_dynamic_resolver_state(r); - - if (*ll) { - ll = &(*ll)->next; - } - *ll = ngx_poold_state(r, detail); - - (*ll)->buf->last_buf = 1; - - return ngx_http_output_filter(r, out); -} - -static char * -ngx_rtmp_sys_stat(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_core_loc_conf_t *clcf; - - clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); - clcf->handler = ngx_rtmp_sys_stat_handler; - - return NGX_CONF_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_variables.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_variables.c deleted file mode 100644 index fbb92caff2..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_variables.c +++ /dev/null @@ -1,1578 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include -#include -#include -#include "ngx_rtmp.h" -#include "ngx_rtmp_variables.h" -#include "ngx_live_relay.h" - - -static ngx_int_t ngx_rtmp_variable_session_get_str(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_rtmp_variable_session_get_uint(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_rtmp_variable_session_get_int(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_rtmp_variable_session_get_msec(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data); - -static ngx_int_t ngx_rtmp_variable_relay_get_str(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_rtmp_variable_relay_get_uint(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data); - -static ngx_int_t ngx_rtmp_variable_finalize_reason(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_rtmp_variable_stage(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_rtmp_variable_remote_addr(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_rtmp_variable_remote_port(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_rtmp_variable_local_addr(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_rtmp_variable_local_port(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_rtmp_variable_nginx_version(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_rtmp_variable_pid(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_rtmp_variable_msec(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_rtmp_variable_time_iso8601(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_rtmp_variable_time_local(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_rtmp_variable_ngx_worker(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_rtmp_variable_argument(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data); - - -static ngx_rtmp_variable_t ngx_rtmp_core_variables[] = { - - { ngx_string("domain"), NULL, ngx_rtmp_variable_session_get_str, - offsetof(ngx_rtmp_session_t, domain), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("app"), NULL, ngx_rtmp_variable_session_get_str, - offsetof(ngx_rtmp_session_t, app), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("name"), NULL, ngx_rtmp_variable_session_get_str, - offsetof(ngx_rtmp_session_t, name), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("stream"), NULL, ngx_rtmp_variable_session_get_str, - offsetof(ngx_rtmp_session_t, stream), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("pargs"), NULL, ngx_rtmp_variable_session_get_str, - offsetof(ngx_rtmp_session_t, pargs), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("args"), NULL, ngx_rtmp_variable_session_get_str, - offsetof(ngx_rtmp_session_t, args), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("flashver"), NULL, ngx_rtmp_variable_session_get_str, - offsetof(ngx_rtmp_session_t, flashver), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("swf_url"), NULL, ngx_rtmp_variable_session_get_str, - offsetof(ngx_rtmp_session_t, swf_url), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("tc_url"), NULL, ngx_rtmp_variable_session_get_str, - offsetof(ngx_rtmp_session_t, tc_url), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("page_url"), NULL, ngx_rtmp_variable_session_get_str, - offsetof(ngx_rtmp_session_t, page_url), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("acodecs"), NULL, ngx_rtmp_variable_session_get_uint, - offsetof(ngx_rtmp_session_t, acodecs), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("vcodecs"), NULL, ngx_rtmp_variable_session_get_uint, - offsetof(ngx_rtmp_session_t, vcodecs), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("scheme"), NULL, ngx_rtmp_variable_session_get_str, - offsetof(ngx_rtmp_session_t, scheme), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("serverid"), NULL, ngx_rtmp_variable_session_get_str, - offsetof(ngx_rtmp_session_t, serverid), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("groupid"), NULL, ngx_rtmp_variable_session_get_str, - offsetof(ngx_rtmp_session_t, groupid), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("notify_status"), NULL, ngx_rtmp_variable_session_get_int, - offsetof(ngx_rtmp_session_t, notify_status), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("finalize_reason"), NULL, ngx_rtmp_variable_finalize_reason, - 0, NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("stage"), NULL, ngx_rtmp_variable_stage, - 0, NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("init"), NULL, ngx_rtmp_variable_session_get_msec, - offsetof(ngx_rtmp_session_t, init_time), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("handshake_done"), NULL, ngx_rtmp_variable_session_get_msec, - offsetof(ngx_rtmp_session_t, handshake_done_time), - NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("connect"), NULL, ngx_rtmp_variable_session_get_msec, - offsetof(ngx_rtmp_session_t, connect_time), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("create_stream"), NULL, ngx_rtmp_variable_session_get_msec, - offsetof(ngx_rtmp_session_t, create_stream_time), - NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("ptime"), NULL, ngx_rtmp_variable_session_get_msec, - offsetof(ngx_rtmp_session_t, ptime), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("first_data"), NULL, ngx_rtmp_variable_session_get_msec, - offsetof(ngx_rtmp_session_t, first_data), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("first_metadata"), NULL, ngx_rtmp_variable_session_get_msec, - offsetof(ngx_rtmp_session_t, first_metadata), - NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("first_audio"), NULL, ngx_rtmp_variable_session_get_msec, - offsetof(ngx_rtmp_session_t, first_audio), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("first_video"), NULL, ngx_rtmp_variable_session_get_msec, - offsetof(ngx_rtmp_session_t, first_video), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("close_stream"), NULL, ngx_rtmp_variable_session_get_msec, - offsetof(ngx_rtmp_session_t, close_stream_time), - NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("relay_domain"), NULL, ngx_rtmp_variable_relay_get_str, - offsetof(ngx_live_relay_ctx_t, domain), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("relay_app"), NULL, ngx_rtmp_variable_relay_get_str, - offsetof(ngx_live_relay_ctx_t, app), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("relay_name"), NULL, ngx_rtmp_variable_relay_get_str, - offsetof(ngx_live_relay_ctx_t, name), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("relay_args"), NULL, ngx_rtmp_variable_relay_get_str, - offsetof(ngx_live_relay_ctx_t, args), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("relay_pargs"), NULL, ngx_rtmp_variable_relay_get_str, - offsetof(ngx_live_relay_ctx_t, pargs), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("relay_referer"), NULL, ngx_rtmp_variable_relay_get_str, - offsetof(ngx_live_relay_ctx_t, referer), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("relay_user_agent"), NULL, ngx_rtmp_variable_relay_get_str, - offsetof(ngx_live_relay_ctx_t, user_agent), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("relay_swf_url"), NULL, ngx_rtmp_variable_relay_get_str, - offsetof(ngx_live_relay_ctx_t, swf_url), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("relay_acodecs"), NULL, ngx_rtmp_variable_relay_get_uint, - offsetof(ngx_live_relay_ctx_t, acodecs), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("relay_vcodecs"), NULL, ngx_rtmp_variable_relay_get_uint, - offsetof(ngx_live_relay_ctx_t, vcodecs), NGX_RTMP_VAR_NOCACHEABLE, 0}, - - { ngx_string("remote_addr"), NULL, ngx_rtmp_variable_remote_addr, - 0, NGX_RTMP_VAR_NOCACHEABLE, 0 }, - - { ngx_string("remote_port"), NULL, ngx_rtmp_variable_remote_port, - 0, NGX_RTMP_VAR_NOCACHEABLE, 0 }, - - { ngx_string("server_addr"), NULL, ngx_rtmp_variable_local_addr, - 0, NGX_RTMP_VAR_NOCACHEABLE, 0 }, - - { ngx_string("server_port"), NULL, ngx_rtmp_variable_local_port, - 0, NGX_RTMP_VAR_NOCACHEABLE, 0 }, - - { ngx_string("nginx_version"), NULL, - ngx_rtmp_variable_nginx_version, 0, 0, 0}, - - { ngx_string("pid"), NULL, ngx_rtmp_variable_pid, 0, 0, 0}, - - { ngx_string("msec"), NULL, ngx_rtmp_variable_msec, - 0, NGX_RTMP_VAR_NOCACHEABLE, 0 }, - - { ngx_string("time_iso8601"), NULL, ngx_rtmp_variable_time_iso8601, - 0, NGX_RTMP_VAR_NOCACHEABLE, 0 }, - - { ngx_string("time_local"), NULL, ngx_rtmp_variable_time_local, - 0, NGX_RTMP_VAR_NOCACHEABLE, 0 }, - - { ngx_string("ngx_worker"), NULL, ngx_rtmp_variable_ngx_worker, - 0, 0, 0}, - - { ngx_string("parg_"), NULL, ngx_rtmp_variable_argument, - 0, NGX_RTMP_VAR_NOCACHEABLE|NGX_RTMP_VAR_PREFIX, 0 }, - - { ngx_null_string, NULL, NULL, 0, 0, 0 } -}; - - -ngx_rtmp_variable_value_t ngx_rtmp_variable_null_value = - ngx_rtmp_variable(""); -ngx_rtmp_variable_value_t ngx_rtmp_variable_true_value = - ngx_rtmp_variable("1"); - - -static ngx_uint_t ngx_rtmp_variable_depth = 100; - - -extern char *ngx_live_stage[]; -extern char *ngx_live_err[]; - - -static ngx_int_t -ngx_rtmp_variable_session_get_str(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data) -{ - ngx_str_t *str; - - str = (ngx_str_t *) ((u_char *) s + data); - - v->data = str->data; - v->len = str->len; - v->valid = 1; - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_variable_session_get_uint(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data) -{ - ngx_uint_t *ui; - - ui = (ngx_uint_t *) ((u_char *) s + data); - - if (v->data == NULL) { - v->data = ngx_pnalloc(s->pool, NGX_INT_T_LEN); - if (v->data == NULL) { - return NGX_ERROR; - } - } - - v->len = ngx_sprintf(v->data, "%ui", *ui) - v->data; - v->valid = 1; - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_variable_session_get_int(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data) -{ - ngx_int_t *i; - - i = (ngx_int_t *) ((u_char *) s + data); - - if (v->data == NULL) { - v->data = ngx_pnalloc(s->pool, NGX_INT_T_LEN); - if (v->data == NULL) { - return NGX_ERROR; - } - } - - v->len = ngx_sprintf(v->data, "%i", *i) - v->data; - v->valid = 1; - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_variable_session_get_msec(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data) -{ - ngx_msec_t *m; - - m = (ngx_msec_t *) ((u_char *) s + data); - - if (v->data == NULL) { - v->data = ngx_pnalloc(s->pool, NGX_INT_T_LEN); - if (v->data == NULL) { - return NGX_ERROR; - } - } - - v->len = ngx_sprintf(v->data, "%i", *m) - v->data; - v->valid = 1; - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_variable_relay_get_str(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data) -{ - ngx_live_relay_ctx_t *ctx; - ngx_str_t *str; - - if (!s->relay) { - v->not_found = 1; - return NGX_OK; - } - - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - - str = (ngx_str_t *) ((u_char *) ctx + data); - - v->data = str->data; - v->len = str->len; - v->valid = 1; - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_variable_relay_get_uint(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data) -{ - ngx_live_relay_ctx_t *ctx; - ngx_uint_t *ui; - - if (!s->relay) { - v->not_found = 1; - return NGX_OK; - } - - ctx = ngx_rtmp_get_module_ctx(s, ngx_live_relay_module); - - ui = (ngx_uint_t *) ((u_char *) ctx + data); - - if (v->data == NULL) { - v->data = ngx_pnalloc(s->pool, NGX_INT_T_LEN); - if (v->data == NULL) { - return NGX_ERROR; - } - } - - v->len = ngx_sprintf(v->data, "%ui", *ui) - v->data; - v->valid = 1; - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_variable_finalize_reason(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data) -{ - v->data = (u_char *) ngx_live_err[s->finalize_reason]; - v->len = ngx_strlen(v->data); - v->valid = 1; - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_variable_stage(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data) -{ - v->data = (u_char *) ngx_live_stage[s->stage]; - v->len = ngx_strlen(v->data); - v->valid = 1; - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_variable_remote_addr(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data) -{ - ngx_sockaddr_t nsa; - struct sockaddr *sa; - socklen_t len; - - if (s->connection == NULL || s->connection->fd == (ngx_socket_t) -1) { - v->not_found = 1; - return NGX_OK; - } - - sa = (struct sockaddr *) &nsa; - len = sizeof(nsa); - - if (getpeername(s->connection->fd, sa, &len) == -1) { - v->not_found = 1; - return NGX_OK; - } - - if (v->data == NULL) { - v->data = ngx_pnalloc(s->pool, NGX_SOCKADDRLEN); - if (v->data == NULL) { - return NGX_ERROR; - } - } - - v->valid = 1; - v->no_cacheable = 0; - v->not_found = 0; - v->len = ngx_sock_ntop(sa, sizeof(nsa), v->data, NGX_SOCKADDRLEN, 0); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_variable_remote_port(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data) -{ - ngx_sockaddr_t nsa; - struct sockaddr *sa; - socklen_t len; - in_port_t port; - - if (s->connection == NULL || s->connection->fd == (ngx_socket_t) -1) { - v->not_found = 1; - return NGX_OK; - } - - sa = (struct sockaddr *) &nsa; - len = sizeof(nsa); - - if (getpeername(s->connection->fd, sa, &len) == -1) { - v->not_found = 1; - return NGX_OK; - } - - if (v->data == NULL) { - v->data = ngx_pnalloc(s->pool, sizeof("65535") - 1); - if (v->data == NULL) { - return NGX_ERROR; - } - } - - port = ngx_inet_get_port(sa); - if (port == 0) { - v->not_found = 1; - return NGX_OK; - } - - v->valid = 1; - v->no_cacheable = 0; - v->not_found = 0; - v->len = ngx_sprintf(v->data, "%ui", port) - v->data; - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_variable_local_addr(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data) -{ - ngx_sockaddr_t nsa; - struct sockaddr *sa; - socklen_t len; - - if (s->connection == NULL || s->connection->fd == (ngx_socket_t) -1) { - v->not_found = 1; - return NGX_OK; - } - - sa = (struct sockaddr *) &nsa; - len = sizeof(nsa); - - if (getsockname(s->connection->fd, sa, &len) == -1) { - v->not_found = 1; - return NGX_OK; - } - - if (v->data == NULL) { - v->data = ngx_pnalloc(s->pool, NGX_SOCKADDRLEN); - if (v->data == NULL) { - return NGX_ERROR; - } - } - - v->valid = 1; - v->no_cacheable = 0; - v->not_found = 0; - v->len = ngx_sock_ntop(sa, sizeof(nsa), v->data, NGX_SOCKADDRLEN, 0); - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_variable_local_port(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data) -{ - ngx_sockaddr_t nsa; - struct sockaddr *sa; - socklen_t len; - in_port_t port; - - if (s->connection == NULL || s->connection->fd == (ngx_socket_t) -1) { - v->not_found = 1; - return NGX_OK; - } - - sa = (struct sockaddr *) &nsa; - len = sizeof(nsa); - - if (getsockname(s->connection->fd, sa, &len) == -1) { - v->not_found = 1; - return NGX_OK; - } - - if (v->data == NULL) { - v->data = ngx_pnalloc(s->pool, sizeof("65535") - 1); - if (v->data == NULL) { - return NGX_ERROR; - } - } - - port = ngx_inet_get_port(sa); - if (port == 0) { - v->not_found = 1; - return NGX_OK; - } - - v->valid = 1; - v->no_cacheable = 0; - v->not_found = 0; - v->len = ngx_sprintf(v->data, "%ui", port) - v->data; - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_variable_nginx_version(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data) -{ - v->len = sizeof(NGINX_VERSION) - 1; - v->valid = 1; - v->no_cacheable = 0; - v->not_found = 0; - v->data = (u_char *) NGINX_VERSION; - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_variable_pid(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data) -{ - if (v->data == NULL) { - v->data = ngx_pnalloc(s->pool, NGX_INT64_LEN); - if (v->data == NULL) { - return NGX_ERROR; - } - } - - v->len = ngx_sprintf(v->data, "%P", ngx_pid) - v->data; - v->valid = 1; - v->no_cacheable = 0; - v->not_found = 0; - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_variable_msec(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data) -{ - ngx_time_t *tp; - - if (v->data == NULL) { - v->data = ngx_pnalloc(s->pool, NGX_TIME_T_LEN + 4); - if (v->data == NULL) { - return NGX_ERROR; - } - } - - tp = ngx_timeofday(); - - v->len = ngx_sprintf(v->data, "%T.%03M", tp->sec, tp->msec) - v->data; - v->valid = 1; - v->no_cacheable = 1; - v->not_found = 0; - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_variable_time_iso8601(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data) -{ - if (v->data == NULL) { - v->data = ngx_pnalloc(s->pool, ngx_cached_http_log_iso8601.len); - if (v->data == NULL) { - return NGX_ERROR; - } - } - - ngx_memcpy(v->data, ngx_cached_http_log_iso8601.data, - ngx_cached_http_log_iso8601.len); - - v->len = ngx_cached_http_log_iso8601.len; - v->valid = 1; - v->no_cacheable = 1; - v->not_found = 0; - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_variable_time_local(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data) -{ - if (v->data == NULL) { - v->data = ngx_pnalloc(s->pool, ngx_cached_http_log_time.len); - if (v->data == NULL) { - return NGX_ERROR; - } - } - - ngx_memcpy(v->data, ngx_cached_http_log_time.data, - ngx_cached_http_log_time.len); - - v->len = ngx_cached_http_log_time.len; - v->valid = 1; - v->no_cacheable = 1; - v->not_found = 0; - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_variable_ngx_worker(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data) -{ - if (v->data == NULL) { - v->data = ngx_pnalloc(s->pool, NGX_INT64_LEN); - if (v->data == NULL) { - return NGX_ERROR; - } - } - - v->len = ngx_sprintf(v->data, "%ui", ngx_worker) - v->data; - v->valid = 1; - v->no_cacheable = 0; - v->not_found = 0; - - return NGX_OK; -} - - -static ngx_int_t -ngx_rtmp_variable_argument(ngx_rtmp_session_t *s, - ngx_http_variable_value_t *v, uintptr_t data) -{ - ngx_str_t *name = (ngx_str_t *) data; - - u_char *arg; - size_t len; - ngx_str_t value; - - len = name->len - (sizeof("parg_") - 1); - arg = name->data + sizeof("parg_") - 1; - - if (ngx_rtmp_arg(s, arg, len, &value) != NGX_OK) { - v->not_found = 1; - return NGX_OK; - } - - v->data = value.data; - v->len = value.len; - v->valid = 1; - v->no_cacheable = 0; - v->not_found = 0; - - return NGX_OK; -} - - -static ngx_rtmp_variable_t * -ngx_rtmp_add_prefix_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags) -{ - ngx_uint_t i; - ngx_rtmp_variable_t *v; - ngx_rtmp_core_main_conf_t *cmcf; - - cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module); - - v = cmcf->prefix_variables.elts; - for (i = 0; i < cmcf->prefix_variables.nelts; i++) { - if (name->len != v[i].name.len - || ngx_strncasecmp(name->data, v[i].name.data, name->len) != 0) - { - continue; - } - - v = &v[i]; - - if (!(v->flags & NGX_HTTP_VAR_CHANGEABLE)) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "the duplicate \"%V\" variable", name); - return NULL; - } - - v->flags &= flags | ~NGX_HTTP_VAR_WEAK; - - return v; - } - - v = ngx_array_push(&cmcf->prefix_variables); - if (v == NULL) { - return NULL; - } - - v->name.len = name->len; - v->name.data = ngx_pnalloc(cf->pool, name->len); - if (v->name.data == NULL) { - return NULL; - } - - ngx_strlow(v->name.data, name->data, name->len); - - v->set_handler = NULL; - v->get_handler = NULL; - v->data = 0; - v->flags = flags; - v->index = 0; - - return v; -} - - -static u_char * -ngx_rtmp_strlechr(u_char *p, u_char *last) -{ - while (p != last) { - if ((*p >= '0' && *p <= '9') || - (*p >= 'a' && *p <= 'z') || - (*p >= 'A' && *p <= 'Z') || - *p == '_') - { - p++; - continue; - } - - return p; - } - - return NULL; -} - - -ngx_int_t -ngx_rtmp_variable_transform_index(ngx_conf_t *cf, ngx_str_t *origin, ngx_str_t *target) -{ - u_char *p, *e, *t; - u_char *wp, *we; - ngx_str_t str, var; - ngx_buf_t *buf; - ngx_int_t index; - - p = origin->data; - e = origin->data + origin->len; - - buf = ngx_create_temp_buf(cf->pool, 2 * origin->len); - if (buf == NULL) { - return NGX_ERROR; - } - - wp = buf->start; - we = buf->end; - - while (p < e) { - t = ngx_strlchr(p, e, '$'); - if (t == NULL) { - t = e; - } - str.data = p; - str.len = t - p; - wp = ngx_slprintf(wp, we, "%V", &str); - - if (t == e) { - break; - } - - var.data = ++t; - t = ngx_rtmp_strlechr(t, e); - if (t == NULL) { - t = e; - } - var.len = t - var.data; - - index = ngx_rtmp_get_variable_index(cf, &var); - if (index == NGX_ERROR) { - return NGX_ERROR; - } - - wp = ngx_slprintf(wp, we, "$%d", index); - p = t; - } - - target->data = buf->start; - target->len = wp - buf->start; - - return NGX_OK; -} - - -ngx_int_t -ngx_rtmp_fetch_variable(ngx_rtmp_session_t *s, ngx_pool_t *pool, - ngx_str_t *origin, ngx_str_t *target) -{ - ngx_rtmp_variable_value_t *vv; - u_char *p, *e, *t; - u_char *wp, *we; - ngx_chain_t *ch, *cl, *ct; - u_char *pt; - ngx_uint_t length; - ngx_int_t index; - ngx_str_t var; - - length = 0; - p = origin->data; - e = p + origin->len; - - #define NGX_RTMP_NOTIFY_BUF(__start__, __end__) \ - ct = cl; \ - pt = ngx_pcalloc(pool, sizeof(ngx_chain_t) + \ - sizeof(ngx_buf_t) + __end__ - __start__); \ - cl = (ngx_chain_t*)pt; \ - cl->buf = (ngx_buf_t*)(pt + sizeof(ngx_chain_t)); \ - cl->buf->start = \ - cl->buf->pos = \ - cl->buf->last = pt + sizeof(ngx_chain_t) + sizeof(ngx_buf_t); \ - if (ch == NULL) { \ - ch = cl; \ - } else { \ - ct->next = cl; \ - } \ - cl->buf->last = ngx_cpymem(cl->buf->pos, __start__, __end__ - __start__); \ - length += __end__ - __start__ - - ch = cl = ct = NULL; - - while(p < e) { - t = ngx_strlchr(p, e, '$'); - if (t == NULL) { - t = e; - } - NGX_RTMP_NOTIFY_BUF(p, t); - if (t == e) { - break; - } - - var.data = ++t; - t = ngx_rtmp_strlechr(t, e); - if (t == NULL) { - t = e; - } - var.len = t - var.data; - index = ngx_atoi(var.data, var.len); - vv = ngx_rtmp_get_indexed_variable(s, index); - if (vv == NULL) { - p = t; - continue; - } - wp = vv->data; - we = vv->data + vv->len; - - NGX_RTMP_NOTIFY_BUF(wp, we); - p = t; - } - - #undef NGX_RTMP_NOTIFY_BUF - - wp = ngx_pcalloc(pool, length); - we = wp; - - for (ct = ch; ct;) { - we = ngx_cpymem(we, ct->buf->pos, ct->buf->last - ct->buf->pos); - cl = ct->next; - ngx_pfree(pool, ct); - ct = cl; - } - target->data = wp; - target->len = we - wp; - if (target->len != length) { - ngx_log_error(NGX_LOG_ERR, s->connection->log, 0, - "variable: fetch_variable| target len = %d, content length = %d", - target->len, length); - return NGX_ERROR; - } - - return NGX_OK; -} - -ngx_rtmp_variable_t * -ngx_rtmp_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags) -{ - ngx_int_t rc; - ngx_uint_t i; - ngx_hash_key_t *key; - ngx_rtmp_variable_t *v; - ngx_rtmp_core_main_conf_t *cmcf; - - if (name->len == 0) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid variable name \"$\""); - return NULL; - } - - if (flags & NGX_HTTP_VAR_PREFIX) { - return ngx_rtmp_add_prefix_variable(cf, name, flags); - } - - cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module); - - key = cmcf->variables_keys->keys.elts; - for (i = 0; i < cmcf->variables_keys->keys.nelts; i++) { - if (name->len != key[i].key.len - || ngx_strncasecmp(name->data, key[i].key.data, name->len) != 0) - { - continue; - } - - v = key[i].value; - - if (!(v->flags & NGX_HTTP_VAR_CHANGEABLE)) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "the duplicate \"%V\" variable", name); - return NULL; - } - - v->flags &= flags | ~NGX_HTTP_VAR_WEAK; - - return v; - } - - v = ngx_palloc(cf->pool, sizeof(ngx_rtmp_variable_t)); - if (v == NULL) { - return NULL; - } - - v->name.len = name->len; - v->name.data = ngx_pnalloc(cf->pool, name->len); - if (v->name.data == NULL) { - return NULL; - } - - ngx_strlow(v->name.data, name->data, name->len); - - v->set_handler = NULL; - v->get_handler = NULL; - v->data = 0; - v->flags = flags; - v->index = 0; - - rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v, 0); - - if (rc == NGX_ERROR) { - return NULL; - } - - if (rc == NGX_BUSY) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "conflicting variable name \"%V\"", name); - return NULL; - } - - return v; -} - - -ngx_int_t -ngx_rtmp_get_variable_index(ngx_conf_t *cf, ngx_str_t *name) -{ - ngx_uint_t i = 0, n; - ngx_rtmp_variable_t *v, *av; - ngx_rtmp_core_main_conf_t *cmcf; - ngx_hash_key_t *key; - - if (name->len == 0) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid variable name \"$\""); - return NGX_ERROR; - } - - cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module); - - v = cmcf->variables.elts; - key = cmcf->variables_keys->keys.elts; - - if (v == NULL) { - if (ngx_array_init(&cmcf->variables, cf->pool, 4, - sizeof(ngx_http_variable_t)) - != NGX_OK) - { - return NGX_ERROR; - } - - } else { - for (i = 0; i < cmcf->variables.nelts; i++) { - if (name->len != v[i].name.len - || ngx_strncasecmp(name->data, v[i].name.data, name->len) != 0) - { - continue; - } - - return i; - } - } - - v = ngx_array_push(&cmcf->variables); - if (v == NULL) { - return NGX_ERROR; - } - - v->name.len = name->len; - v->name.data = ngx_pnalloc(cf->pool, name->len); - if (v->name.data == NULL) { - return NGX_ERROR; - } - - ngx_strlow(v->name.data, name->data, name->len); - - for (n = 0; n < cmcf->variables_keys->keys.nelts; n++) { - av = key[n].value; - if (av->get_handler - && v->name.len == key[n].key.len - && ngx_strncmp(v->name.data, key[n].key.data, v->name.len) == 0) - { - v->get_handler = av->get_handler; - v->data = av->data; - av->flags= NGX_RTMP_VAR_INDEXED; - v->flags = av->flags; - av->index = i; - - goto next; - } - } - - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "variables: get_variable_index| unknown \"%V\" variable", - &v->name); - - return NGX_ERROR; - -next: - v->set_handler = NULL; - v->index = cmcf->variables.nelts - 1; - - return v->index; -} - - -ngx_rtmp_variable_value_t * -ngx_rtmp_get_indexed_variable(ngx_rtmp_session_t *s, ngx_uint_t index) -{ - ngx_rtmp_variable_t *v; - ngx_rtmp_core_main_conf_t *cmcf; - - cmcf = ngx_rtmp_get_module_main_conf(s, ngx_rtmp_core_module); - - if (cmcf->variables.nelts <= index) { - ngx_log_error(NGX_LOG_ALERT, s->log, 0, - "unknown variable index: %ui", index); - return NULL; - } - - if (s->variables[index].not_found || s->variables[index].valid) { - return &s->variables[index]; - } - - v = cmcf->variables.elts; - - if (ngx_rtmp_variable_depth == 0) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "cycle while evaluating variable \"%V\"", - &v[index].name); - return NULL; - } - - ngx_rtmp_variable_depth--; - - if (v[index].get_handler(s, &s->variables[index], v[index].data) - == NGX_OK) - { - ngx_rtmp_variable_depth++; - - if (v[index].flags & NGX_HTTP_VAR_NOCACHEABLE) { - s->variables[index].no_cacheable = 1; - } - - return &s->variables[index]; - } - - ngx_rtmp_variable_depth++; - - s->variables[index].valid = 0; - s->variables[index].not_found = 1; - - return NULL; -} - - -ngx_rtmp_variable_value_t * -ngx_rtmp_get_flushed_variable(ngx_rtmp_session_t *s, ngx_uint_t index) -{ - ngx_rtmp_variable_value_t *v; - - v = &s->variables[index]; - - if (v->valid || v->not_found) { - if (!v->no_cacheable) { - return v; - } - - v->valid = 0; - v->not_found = 0; - } - - return ngx_rtmp_get_indexed_variable(s, index); -} - - -ngx_rtmp_variable_value_t * -ngx_rtmp_get_variable(ngx_rtmp_session_t *s, ngx_str_t *name, ngx_uint_t key) -{ - size_t len; - ngx_uint_t i, n; - ngx_rtmp_variable_t *v; - ngx_rtmp_variable_value_t *vv; - ngx_rtmp_core_main_conf_t *cmcf; - - cmcf = ngx_rtmp_get_module_main_conf(s, ngx_rtmp_core_module); - - v = ngx_hash_find(&cmcf->variables_hash, key, name->data, name->len); - - if (v) { - if (v->flags & NGX_HTTP_VAR_INDEXED) { - return ngx_rtmp_get_flushed_variable(s, v->index); - } - - if (ngx_rtmp_variable_depth == 0) { - ngx_log_error(NGX_LOG_ERR, s->log, 0, - "cycle while evaluating variable \"%V\"", name); - return NULL; - } - - ngx_rtmp_variable_depth--; - - vv = ngx_palloc(s->pool, sizeof(ngx_rtmp_variable_value_t)); - - if (vv && v->get_handler(s, vv, v->data) == NGX_OK) { - ngx_rtmp_variable_depth++; - return vv; - } - - ngx_rtmp_variable_depth++; - return NULL; - } - - vv = ngx_palloc(s->pool, sizeof(ngx_rtmp_variable_value_t)); - if (vv == NULL) { - return NULL; - } - - len = 0; - - v = cmcf->prefix_variables.elts; - n = cmcf->prefix_variables.nelts; - - for (i = 0; i < cmcf->prefix_variables.nelts; i++) { - if (name->len >= v[i].name.len && name->len > len - && ngx_strncmp(name->data, v[i].name.data, v[i].name.len) == 0) - { - len = v[i].name.len; - n = i; - } - } - - if (n != cmcf->prefix_variables.nelts) { - if (v[n].get_handler(s, vv, (uintptr_t) name) == NGX_OK) { - return vv; - } - - return NULL; - } - - vv->not_found = 1; - - return vv; -} - - -void * -ngx_rtmp_map_find(ngx_rtmp_session_t *s, ngx_rtmp_map_t *map, ngx_str_t *match) -{ - void *value; - u_char *low; - size_t len; - ngx_uint_t key; - - len = match->len; - - if (len) { - low = ngx_pnalloc(s->pool, len); - if (low == NULL) { - return NULL; - } - - } else { - low = NULL; - } - - key = ngx_hash_strlow(low, match->data, len); - - value = ngx_hash_find_combined(&map->hash, key, low, len); - if (value) { - return value; - } - -#if (NGX_PCRE) - - if (len && map->nregex) { - ngx_int_t n; - ngx_uint_t i; - ngx_rtmp_map_regex_t *reg; - - reg = map->regex; - - for (i = 0; i < map->nregex; i++) { - - n = ngx_rtmp_regex_exec(s, reg[i].regex, match); - - if (n == NGX_OK) { - return reg[i].value; - } - - if (n == NGX_DECLINED) { - continue; - } - - /* NGX_ERROR */ - - return NULL; - } - } - -#endif - - return NULL; -} - - -#if (NGX_PCRE) - -static ngx_int_t -ngx_rtmp_variable_not_found(ngx_rtmp_session_t *s, ngx_rtmp_variable_value_t *v, - uintptr_t data) -{ - v->not_found = 1; - return NGX_OK; -} - - -ngx_rtmp_regex_t * -ngx_rtmp_regex_compile(ngx_conf_t *cf, ngx_regex_compile_t *rc) -{ - u_char *p; - size_t size; - ngx_str_t name; - ngx_uint_t i, n; - ngx_rtmp_variable_t *v; - ngx_rtmp_regex_t *re; - ngx_rtmp_regex_variable_t *rv; - ngx_rtmp_core_main_conf_t *cmcf; - - rc->pool = cf->pool; - - if (ngx_regex_compile(rc) != NGX_OK) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc->err); - return NULL; - } - - re = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_regex_t)); - if (re == NULL) { - return NULL; - } - - re->regex = rc->regex; - re->ncaptures = rc->captures; - re->name = rc->pattern; - - cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module); - cmcf->ncaptures = ngx_max(cmcf->ncaptures, re->ncaptures); - - n = (ngx_uint_t) rc->named_captures; - - if (n == 0) { - return re; - } - - rv = ngx_palloc(rc->pool, n * sizeof(ngx_rtmp_regex_variable_t)); - if (rv == NULL) { - return NULL; - } - - re->variables = rv; - re->nvariables = n; - - size = rc->name_size; - p = rc->names; - - for (i = 0; i < n; i++) { - rv[i].capture = 2 * ((p[0] << 8) + p[1]); - - name.data = &p[2]; - name.len = ngx_strlen(name.data); - - v = ngx_rtmp_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE); - if (v == NULL) { - return NULL; - } - - rv[i].index = ngx_rtmp_get_variable_index(cf, &name); - if (rv[i].index == NGX_ERROR) { - return NULL; - } - - v->get_handler = ngx_rtmp_variable_not_found; - - p += size; - } - - return re; -} - - -ngx_int_t -ngx_rtmp_regex_exec(ngx_rtmp_session_t *s, ngx_rtmp_regex_t *re, ngx_str_t *str) -{ - ngx_int_t rc, index; - ngx_uint_t i, n, len; - ngx_rtmp_variable_value_t *vv; - ngx_rtmp_core_main_conf_t *cmcf; - - cmcf = ngx_rtmp_get_module_main_conf(s, ngx_rtmp_core_module); - - if (re->ncaptures) { - len = cmcf->ncaptures; - - if (s->captures == NULL) { - s->captures = ngx_palloc(s->pool, len * sizeof(int)); - if (s->captures == NULL) { - return NGX_ERROR; - } - } - - } else { - len = 0; - } - - rc = ngx_regex_exec(re->regex, str, s->captures, len); - - if (rc == NGX_REGEX_NO_MATCHED) { - return NGX_DECLINED; - } - - if (rc < 0) { - ngx_log_error(NGX_LOG_ALERT, s->log, 0, - ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"", - rc, str, &re->name); - return NGX_ERROR; - } - - for (i = 0; i < re->nvariables; i++) { - - n = re->variables[i].capture; - index = re->variables[i].index; - vv = &s->variables[index]; - - vv->len = s->captures[n + 1] - s->captures[n]; - vv->valid = 1; - vv->no_cacheable = 0; - vv->not_found = 0; - vv->data = &str->data[s->captures[n]]; - -#if (NGX_DEBUG) - { - ngx_rtmp_variable_t *v; - - v = cmcf->variables.elts; - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, s->log, 0, - "http regex set $%V to \"%v\"", &v[index].name, vv); - } -#endif - } - - s->ncaptures = rc * 2; - s->captures_data = str->data; - - return NGX_OK; -} - -#endif - - -ngx_int_t -ngx_rtmp_variables_add_core_vars(ngx_conf_t *cf) -{ - ngx_rtmp_variable_t *cv, *v; - ngx_rtmp_core_main_conf_t *cmcf; - - cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module); - - cmcf->variables_keys = ngx_pcalloc(cf->temp_pool, - sizeof(ngx_hash_keys_arrays_t)); - if (cmcf->variables_keys == NULL) { - return NGX_ERROR; - } - - cmcf->variables_keys->pool = cf->pool; - cmcf->variables_keys->temp_pool = cf->pool; - - if (ngx_hash_keys_array_init(cmcf->variables_keys, NGX_HASH_SMALL) - != NGX_OK) - { - return NGX_ERROR; - } - - if (ngx_array_init(&cmcf->prefix_variables, cf->pool, 8, - sizeof(ngx_rtmp_variable_t)) - != NGX_OK) - { - return NGX_ERROR; - } - - for (cv = ngx_rtmp_core_variables; cv->name.len; cv++) { - v = ngx_rtmp_add_variable(cf, &cv->name, cv->flags); - if (v == NULL) { - return NGX_ERROR; - } - - *v = *cv; - } - - return NGX_OK; -} - - -ngx_int_t -ngx_rtmp_variables_init_vars(ngx_conf_t *cf) -{ - size_t len; - ngx_uint_t i, n; - ngx_hash_key_t *key; - ngx_hash_init_t hash; - ngx_rtmp_variable_t *v, *av, *pv; - ngx_rtmp_core_main_conf_t *cmcf; - - /* set the handlers for the indexed http variables */ - - cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module); - - v = cmcf->variables.elts; - pv = cmcf->prefix_variables.elts; - key = cmcf->variables_keys->keys.elts; - - for (i = 0; i < cmcf->variables.nelts; i++) { - - for (n = 0; n < cmcf->variables_keys->keys.nelts; n++) { - - av = key[n].value; - - if (v[i].name.len == key[n].key.len - && ngx_strncmp(v[i].name.data, key[n].key.data, v[i].name.len) - == 0) - { - v[i].get_handler = av->get_handler; - v[i].data = av->data; - - av->flags |= NGX_HTTP_VAR_INDEXED; - v[i].flags = av->flags; - - av->index = i; - - if (av->get_handler == NULL - || (av->flags & NGX_HTTP_VAR_WEAK)) - { - break; - } - - goto next; - } - } - - len = 0; - av = NULL; - - for (n = 0; n < cmcf->prefix_variables.nelts; n++) { - if (v[i].name.len >= pv[n].name.len && v[i].name.len > len - && ngx_strncmp(v[i].name.data, pv[n].name.data, pv[n].name.len) - == 0) - { - av = &pv[n]; - len = pv[n].name.len; - } - } - - if (av) { - v[i].get_handler = av->get_handler; - v[i].data = (uintptr_t) &v[i].name; - v[i].flags = av->flags; - - goto next; - } - - if (v[i].get_handler == NULL) { - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "unknown \"%V\" variable", &v[i].name); - - return NGX_ERROR; - } - - next: - continue; - } - - - for (n = 0; n < cmcf->variables_keys->keys.nelts; n++) { - av = key[n].value; - - if (av->flags & NGX_HTTP_VAR_NOHASH) { - key[n].key.data = NULL; - } - } - - - hash.hash = &cmcf->variables_hash; - hash.key = ngx_hash_key; - hash.max_size = cmcf->variables_hash_max_size; - hash.bucket_size = cmcf->variables_hash_bucket_size; - hash.name = "variables_hash"; - hash.pool = cf->pool; - hash.temp_pool = NULL; - - if (ngx_hash_init(&hash, cmcf->variables_keys->keys.elts, - cmcf->variables_keys->keys.nelts) - != NGX_OK) - { - return NGX_ERROR; - } - - cmcf->variables_keys = NULL; - - return NGX_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_variables.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_variables.h deleted file mode 100644 index 3b85ee4b75..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_variables.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#ifndef _NGX_RTMP_VARIABLES_H_INCLUDED_ -#define _NGX_RTMP_VARIABLES_H_INCLUDED_ - - -#include -#include -#include "ngx_rtmp.h" - - -typedef ngx_variable_value_t ngx_rtmp_variable_value_t; - -#define ngx_rtmp_variable(v) { sizeof(v) - 1, 1, 0, 0, 0, (u_char *) v } - -typedef struct ngx_rtmp_variable_s ngx_rtmp_variable_t; - -typedef void (*ngx_rtmp_set_variable_pt) (ngx_rtmp_session_t *s, - ngx_rtmp_variable_value_t *v, uintptr_t data); -typedef ngx_int_t (*ngx_rtmp_get_variable_pt) (ngx_rtmp_session_t *s, - ngx_rtmp_variable_value_t *v, uintptr_t data); - - -#define NGX_RTMP_VAR_CHANGEABLE 1 -#define NGX_RTMP_VAR_NOCACHEABLE 2 -#define NGX_RTMP_VAR_INDEXED 4 -#define NGX_RTMP_VAR_NOHASH 8 -#define NGX_RTMP_VAR_WEAK 16 -#define NGX_RTMP_VAR_PREFIX 32 - - -struct ngx_rtmp_variable_s { - ngx_str_t name; /* must be first to build the hash */ - ngx_rtmp_set_variable_pt set_handler; - ngx_rtmp_get_variable_pt get_handler; - uintptr_t data; - ngx_uint_t flags; - ngx_uint_t index; -}; - - -ngx_rtmp_variable_t *ngx_rtmp_add_variable(ngx_conf_t *cf, ngx_str_t *name, - ngx_uint_t flags); -ngx_int_t ngx_rtmp_get_variable_index(ngx_conf_t *cf, ngx_str_t *name); -ngx_rtmp_variable_value_t *ngx_rtmp_get_indexed_variable(ngx_rtmp_session_t *s, - ngx_uint_t index); -ngx_rtmp_variable_value_t *ngx_rtmp_get_flushed_variable(ngx_rtmp_session_t *s, - ngx_uint_t index); - -ngx_rtmp_variable_value_t *ngx_rtmp_get_variable(ngx_rtmp_session_t *s, - ngx_str_t *name, ngx_uint_t key); - -ngx_int_t ngx_rtmp_variable_unknown_header(ngx_rtmp_variable_value_t *v, - ngx_str_t *var, ngx_list_part_t *part, size_t prefix); - - -typedef struct { - ngx_hash_combined_t hash; -#if (NGX_PCRE) - ngx_rtmp_map_regex_t *regex; - ngx_uint_t nregex; -#endif -} ngx_rtmp_map_t; - - -void *ngx_rtmp_map_find(ngx_rtmp_session_t *s, ngx_rtmp_map_t *map, - ngx_str_t *match); - - -ngx_int_t ngx_rtmp_variables_add_core_vars(ngx_conf_t *cf); -ngx_int_t ngx_rtmp_variables_init_vars(ngx_conf_t *cf); - -ngx_int_t ngx_rtmp_variable_transform_index(ngx_conf_t *cf, - ngx_str_t *origin, ngx_str_t *target); -ngx_int_t ngx_rtmp_fetch_variable(ngx_rtmp_session_t *s, ngx_pool_t *pool, - ngx_str_t *origin, ngx_str_t *target); - -extern ngx_rtmp_variable_value_t ngx_rtmp_variable_null_value; -extern ngx_rtmp_variable_value_t ngx_rtmp_variable_true_value; - - -#endif diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_version.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_version.h deleted file mode 100644 index 1bdce4984b..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_version.h +++ /dev/null @@ -1,15 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#ifndef _NGX_RTMP_VERSION_H_INCLUDED_ -#define _NGX_RTMP_VERSION_H_INCLUDED_ - - -#define nginx_rtmp_version 1001004 -#define NGINX_RTMP_VERSION "1.1.4" - - -#endif /* _NGX_RTMP_VERSION_H_INCLUDED_ */ diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/COPYRIGHT b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/COPYRIGHT deleted file mode 100644 index 837a6682d6..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/COPYRIGHT +++ /dev/null @@ -1,24 +0,0 @@ -Copyright (C) 2016-2020, by Jie Wu "AlexWoo" . -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -SUCH DAMAGE. - diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/README.md b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/README.md deleted file mode 100644 index 672e6a0fd4..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/README.md +++ /dev/null @@ -1,37 +0,0 @@ -# Module nginx-toolkit-module ---- -## Instructions - -Nginx event toolkit modules. It contains modules below, and will add more in the future. - -- [ngx-event-timer-module](doc/ngx-event-timer-module.md) - - Independent timer for nginx - -- [ngx-event-resolver-module](doc/ngx-event-resolver-module.md) - - Common resovler in event modules, just like http resolver, stream resolver in nginx, but can be used by http modules, stream modules and other modules - -- [ngx-dynamic-resolver-module](doc/ngx-dynamic-resolver-module.md) - - System will resolver domain in dynamic resolver every few seconds configured - - The module will return addr whose domain is resolved in dynamic resolver, otherwise, the module will add domain into dynamic resolver, resolv domain by event resolver, and call callback when resolved - -- [ngx-dynamic-conf-module](doc/ngx-dynamic-conf-module.md) - - System will reload conf when nginx dynamic config file change. Developer can use this module to reload file without reload nginx worker - - Now it support NGX\_CORE\_MODULE and NGX\_HTTP\_MODULE - -- [ngx-map](doc/ngx-map.md) - - A map implement use ngx\_rbtree - -- [ngx-rbuf](doc/ngx-rbuf.md) - - A recycled chainbuf for nginx - -- [ngx-toolkit-misc](doc/ngx-toolkit-misc.md) - - Misc toolkit functions diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/config b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/config deleted file mode 100644 index 6f476df6be..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/config +++ /dev/null @@ -1,47 +0,0 @@ -ngx_addon_name=ngx_toolkit_module - - -CORE_MODULES="$CORE_MODULES \ - ngx_http_dynamic_module \ - " - -EVENT_MODULES="$EVENT_MODULES \ - ngx_event_timer_module \ - ngx_dynamic_conf_module \ - ngx_event_resolver_module \ - ngx_dynamic_resolver_module \ - " - -HTTP_MODULES="$HTTP_MODULES \ - ngx_http_dynamic_core_module \ - ngx_http_trace_module \ - " - -NGX_ADDON_SRCS="$NGX_ADDON_SRCS \ - $ngx_addon_dir/ngx_event_timer_module.c \ - $ngx_addon_dir/ngx_event_resolver.c \ - $ngx_addon_dir/ngx_dynamic_resolver.c \ - $ngx_addon_dir/ngx_dynamic_conf.c \ - $ngx_addon_dir/ngx_http_dynamic.c \ - $ngx_addon_dir/ngx_toolkit_misc.c \ - $ngx_addon_dir/ngx_map.c \ - $ngx_addon_dir/ngx_rbuf.c \ - $ngx_addon_dir/ngx_poold.c \ - $ngx_addon_dir/ngx_timerd.c \ - $ngx_addon_dir/ngx_http_trace_module.c \ - " - -NGX_ADDON_DEPS="$NGX_ADDON_DEPS \ - $ngx_addon_dir/ngx_event_timer_module.h \ - $ngx_addon_dir/ngx_event_resolver.h \ - $ngx_addon_dir/ngx_dynamic_resolver.h \ - $ngx_addon_dir/ngx_dynamic_conf.h \ - $ngx_addon_dir/ngx_http_dynamic.h \ - $ngx_addon_dir/ngx_toolkit_misc.h \ - $ngx_addon_dir/ngx_map.h \ - $ngx_addon_dir/ngx_rbuf.h \ - $ngx_addon_dir/ngx_poold.h \ - $ngx_addon_dir/ngx_timerd.h \ - " - -CFLAGS="$CFLAGS -I $ngx_addon_dir" diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-dynamic-conf-module.md b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-dynamic-conf-module.md deleted file mode 100644 index 31264bd695..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-dynamic-conf-module.md +++ /dev/null @@ -1,343 +0,0 @@ -# Module ngx-dynamic-conf-module ---- -## Instructions - -System will reload conf when nginx dynamic config file change. Developer can use this module to reload file without reload nginx worker. - -Now it support NGX\_CORE\_MODULE and NGX\_HTTP\_MODULE - -## Directives - - Syntax : dynamic_conf dynamic_file time; - Default : - - Context : main - -Set dynamic config file and interval system checked file changed. - - Syntax : dynamic_log log_file level; - Default : - - Context : main - -Set dynamic conf load log file and log level. If not configured, use cycle log as default. - -Example: - - dynamic_conf conf/nginx_dynamic.conf 10; - dynamic_log logs/error_dynamic.log info; - -## API - -### MAIN dynamic conf - -**header file** - -For using this API, You should include the header file as below: - - #include "ngx_dynamic_conf.h" - -**dynamic module define** - - typedef struct { - ngx_str_t name; - void *(*create_conf)(ngx_conf_t *cf); - char *(*init_conf)(ngx_conf_t *cf, void *conf); - } ngx_dynamic_core_module_t; - -dynamic conf module define as below - - ngx_module_t ngx_test_module = { - NGX_MODULE_V1, - &ngx_test_module_ctx, /* module context */ - ngx_test_commands, /* module directives */ - NGX_CORE_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - (uintptr_t) &ngx_test_module_dctx, /* module dynamic context */ - (uintptr_t) ngx_test_dcommands, /* module dynamic directives */ - NGX_MODULE_V1_DYNAMIC_PADDING - }; - -**module dynamic context** struct define as above, **module dynamic directives** define use ngx\_command\_t. Use ngx\_dynamic\_core\_test\_module define in t/ngx\_dynamic\_conf\_test\_module.c as reference - -**ngx\_dynamic\_conf\_parse** - - ngx_int_t ngx_dynamic_conf_parse(ngx_conf_t *cf, unsigned init) - -- return value: - - - return NGX\_OK for successd, NGX\_ERROR for failed - -- paras: - - - cf : ngx\_conf\_t passed from ngx\_dynamic\_conf\_load_conf - - init : only ngx\_dynamic\_conf\_load\_conf set 1, otherwise set 0 - -This interface is supported for other dynamic conf module, such as ngx\_conf\_parse - -**ngx\_dynamic\_regex\_compile** - - typedef struct { - ngx_regex_t *regex; - ngx_str_t name; - } ngx_dynamic_regex_t; - - ngx_dynamic_regex_t *ngx_dynamic_regex_compile(ngx_conf_t *cf, - ngx_regex_compile_t *rc); - -- return value: - - - return regex context - -- paras: - - - cf: ngx\_conf\_t passed in dynamic cmd handler - - rc: regex options - -compile regex - -**ngx\_get\_dconf** - - void *ngx_get_dconf(ngx_module_t *m) - -return NGX\_CORE\_MODULE dynamic config for module - -### HTTP dynamic conf - -**header file** - -For using this API, You should include the header file as below: - - #include "ngx_dynamic_conf.h" - -**dynamic module define** - -dynamic conf module define is same as MAIN dynamic conf - -http dynamic conf context define as below: - - typedef struct { - void *(*create_main_conf)(ngx_conf_t *cf); - char *(*init_main_conf)(ngx_conf_t *cf, void *conf); - - void *(*create_srv_conf)(ngx_conf_t *cf); - char *(*init_srv_conf)(ngx_conf_t *cf, void *conf); - - void *(*create_loc_conf)(ngx_conf_t *cf); - char *(*init_loc_conf)(ngx_conf_t *cf, void *conf); - } ngx_http_dynamic_module_t; - -**notice:** http dynamic conf do not support merge - -**ngx\_http\_get\_module\_main\_dconf** - - void *ngx_http_get_module_main_dconf(ngx_http_request_t *r, ngx_module_t *m); - -return http request main dynamic conf for module m - -**ngx\_http\_get\_module\_srv\_dconf** - - void *ngx_http_get_module_srv_dconf(ngx_http_request_t *r, ngx_module_t *m); - -return http request srv dynamic conf for module m - -**ngx\_http\_get\_module\_loc\_dconf** - - void *ngx_http_get_module_loc_dconf(ngx_http_request_t *r, ngx_module_t *m); - -return http request loc dynamic conf for module m - -## Build - -cd to NGINX source directory & run this: - - ./configure --add-module=/path/to/nginx-toolkit-module/ - make && make install - -## Example - -See - -- t/ngx\_dynamic\_conf\_test\_module.c as MAIN conf for usage of dynamic conf -- t/ngx\_http\_dynamic\_test\_module.c as HTTP conf for usage of http dynamic conf - -**Build:** - - ./configure --with-debug --add-module=/path/to/nginx-toolkit-module/ --add-module=/path/to/nginx-toolkit-module/t - make && make install - -**Configure:** - - dynamic_conf conf/nginx_dynamic.conf 10; - dynamic_log logs/error_dynamic.log info; - - http { - - ... - - server { - - ... - - location /dynamic_conf_test/ { - dynamic_conf_test; - } - } - } - -**Dynamic Configure:** - - dynamic_test_i 200; - dynamic_test_s hello_world; - - http { - main_int 1000; - main_str gogogo; - - #defult server - server { - srv_int 1; - srv_str default; - } - - #wildcard_head - server { - srv_int 2; - srv_str wildcard_head; - serverid baidu; - server_name *.baidu.com; - } - - #wildcard_tail - server { - srv_int 3; - srv_str wildcard_tail; - serverid google; - server_name www.google.*; - } - - #hash - server { - srv_int 4; - srv_str hash; - serverid sina; - server_name sports.sina.com.cn; - - location = / { - loc_int 1; - loc_str =/; - } - - location / { - loc_int 2; - loc_str /; - } - - location ^~ /test1/ { - loc_int 3; - loc_str ^~/test1/; - } - - location ~* \.(gif|jpg|jpeg)$ { - loc_int 4; - loc_str ~*\.(gif|jpg|jpeg)$; - } - - location /test { - loc_int 5; - loc_str /test; - } - } - - #pcre - server { - srv_int 5; - srv_str pcre; - serverid test; - server_name ~^flv(?!.*(dl\.))[A-Za-z0-9]*\.test\.com$; - } - - #multi - server { - srv_int 6; - srv_str multi; - serverid others; - server_name ~^flv(?!.*(dl\.))[A-Za-z0-9]*\.haha\.com$ www.sohu.com; - server_name *.qq.com; - } - } - -**Test:** - -- Main for dynamic config - - get conf configured in dynamic config file for test module - - curl -v 'http://127.0.0.1/dynamic_conf_test/test' - - change config in dynamic config, the test api will return new config value after dynamic conf refresh - -- Main for http - - curl -v 'http://127.0.0.1/' - - change config in http block of dynamic config, the test api will return new config value after dynamic conf refresh - -- Server for http - - - defult server - - curl -v 'http://127.0.0.1/http_dynamic_test/test' - curl -v -H 'Host: github.com' 'http://127.0.0.1/http_dynamic_test/test' - - - wildcard_head - - curl -v -H 'Host: map.baidu.com' 'http://127.0.0.1/http_dynamic_test/test' - - - wildcard_tail - - curl -v -H 'Host: www.google.co.jp' 'http://127.0.0.1/http_dynamic_test/test' - - - hash - - curl -v -H 'Host: sports.sina.com.cn' 'http://127.0.0.1/http_dynamic_test/test' - - - pcre - - curl -v -H 'Host: flvdl7a8e4223.test.com' 'http://127.0.0.1/http_dynamic_test/test' - - - multi - - curl -v -H 'Host: flvdl7a8e4223.haha.com' 'http://127.0.0.1/http_dynamic_test/test' - curl -v -H 'Host: www.sohu.com' 'http://127.0.0.1/http_dynamic_test/test' - curl -v -H 'Host: v.qq.com' 'http://127.0.0.1/http_dynamic_test/test' - -- Location for http - - - no location - - curl -v -H 'Host: flvdl7a8e4223.haha.com' 'http://127.0.0.1/' - - - location = / - - curl -v -H 'Host: sports.sina.com.cn' 'http://127.0.0.1/' - - - location / - - curl -v -H 'Host: sports.sina.com.cn' 'http://127.0.0.1/t' - - - location ^~ /test1/ - - curl -v -H 'Host: sports.sina.com.cn' 'http://127.0.0.1/test1/123' - - - ~* \.(gif|jpg|jpeg)$ - - curl -v -H 'Host: sports.sina.com.cn' 'http://127.0.0.1/test/123.gif' - - - /test - - curl -v -H 'Host: sports.sina.com.cn' 'http://127.0.0.1/test/123' diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-dynamic-resolver-module.md b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-dynamic-resolver-module.md deleted file mode 100644 index 4eeda28fd4..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-dynamic-resolver-module.md +++ /dev/null @@ -1,157 +0,0 @@ -# Module ngx-dynamic-resolver-module ---- -## Instructions - -System will resolver domain in dynamic resolver every few seconds configured. - -The module will return addr whose domain is resolved in dynamic resolver, otherwise, the module will add domain into dynamic resolver, resolv domain by event resolver, and call callback when resolved. - -## Directives - - Syntax : dynamic_refresh_interval time; - Default : dynamic_refresh_interval 5m; - Context : events - -Set time interval for DNS query frequency, 0 for shutdown this function. - - Syntax : dynamic_domain_buckets number; - Default : dynamic_domain_buckets 101; - Context : events - -Bucket for dynamic resolver domain hash table. Use prime key is Recommended. - -Example: - - events { - resolver 192.168.84.254 valid=1m; - dynamic_refresh_interval 5m; - dynamic_domain_buckets 1001; - } - -## API - -**header file** - -For using this API, You should include the header file as below: - - #include "ngx_dynamic_resolver.h" - -**start resolver** - - void ngx_dynamic_resolver_start_resolver(ngx_str_t *domain, - ngx_dynamic_resolver_handler_pt h, void *data); - -- return value: - - - None - -- paras: - - - domain: domain for DNS query - - h : callback handler - - data : data for callback - -h's protype is: - - typedef void (* ngx_dynamic_resolver_handler_pt)(void *data, - struct sockaddr *sa, socklen_t socklen); - -- return value: - - - None - -- paras: - - - data : user private data set in ngx\_dynamic\_resolver\_start\_resolver - - sa : sock address get - - socklen: sock address len, 0 for get none address - -**gethostbyname** - - socklen_t ngx_dynamic_resolver_gethostbyname(ngx_str_t *domain, struct sockaddr *sa); - -- return value: - - - socklen for successd - - 0 for failed - -- paras: - - - domain: domain for query - - sa : sock address get - -**add domain** - - void ngx_dynamic_resolver_add_domain(ngx_str_t *domain); - -- return value: - - - None - -- paras: - - - domain: domain for query - - -**del domain** - - void ngx_dynamic_resolver_del_domain(ngx_str_t *domain); - -- return value: - - - None - -- paras: - - - domain: domain for DNS query - -## Build - -cd to NGINX source directory & run this: - - ./configure --add-module=/path/to/nginx-toolkit-module/ - make && make install - -## Example - -See t/ngx\_dynamic\_resolver\_test\_module.c as reference - -Build: - - ./configure --with-debug --add-module=/path/to/nginx-toolkit-module/ --add-module=/path/to/nginx-toolkit-module/t - make && make install - -Configure: - - events { - resolver 192.168.84.254 valid=1m; - dynamic_refresh_interval 5m; - } - - http { - - ... - - server { - - ... - - location /dynamic_resolver_test/ { - dynamic_resolver_test 192.168.84.4 www.test1.com; - } - } - } - -Test: - -- sync resolver - - curl -v 'http://127.0.0.1/dynamic_resolver_test/resolver?domain=www.test1.com&sync=1' - -- start resolver - - curl -v 'http://127.0.0.1/dynamic_resolver_test/resolver?domain=www.test.com' - -- del domain - - curl -XDELETE -v 'http://127.0.0.1/dynamic_resolver_test/resolver?domain=www.test.com' diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-event-resolver-module.md b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-event-resolver-module.md deleted file mode 100644 index 4f43e2f3d6..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-event-resolver-module.md +++ /dev/null @@ -1,126 +0,0 @@ -# Module ngx-event-resolver-module ---- -## Instructions - -Common resovler in event modules, just like http resolver, stream resolver in nginx, but can be used by http modules, stream modules and other modules - -## Directives - - Syntax : resolver address ... [valid=time] [ipv6=on|off]; - Default : - - Context : events - -Configures name servers used to resolve names into addresses, for example: - -> resolver 127.0.0.1 [::1]:5353; - -An address can be specified as a domain name or IP address, and an optional port. If port is not specified, the port 53 is used. Name servers are queried in a round-robin fashion. - -By default, nginx will look up both IPv4 and IPv6 addresses while resolving. If looking up of IPv6 addresses is not desired, the ipv6=off parameter can be specified. - -By default, nginx caches answers using the TTL value of a response. The optional valid parameter allows overriding it: - -> resolver 127.0.0.1 [::1]:5353 valid=30s; - - Syntax : resolver_timeout time; - Default : resolver_timeout 60s; - Context : events - -Sets a timeout for name resolution, for example: - -> resolver\_timeout 5s; - -Example: - - events { - resolver 192.168.84.254 valid=20s; - resolver_timeout 10s; - } - -## API - -**header file** - -For using this API, You should include the header file as below: - - #include "ngx_event_resolver.h" - -**resolver a domain** - - void ngx_event_resolver_start_resolver(ngx_str_t *domain, - ngx_event_resolver_handler_pt h, void *data); - -- return value: - - None - -- paras: - - - domain: domain for resolving - - h : callback handler - - data : data for callback - -h's protype is: - - typedef void (* ngx_event_resolver_handler_pt)(void *data, - ngx_resolver_addr_t *addrs, ngx_uint_t naddrs); - -- return value: - - None - -- paras: - - - data : user private data set in ngx\_event\_resolver\_start\_resolver - - addrs : addrs resolv by DNS - - naddrs: number of addrs resolv by DNS - - -## Build - -cd to NGINX source directory & run this: - - ./configure --add-module=/path/to/nginx-toolkit-module/ - make && make install - -## Example - -See t/ngx\_event\_resolver\_test\_module.c as reference - -Build: - - ./configure --with-debug --add-module=/path/to/nginx-toolkit-module/ --add-module=/path/to/nginx-toolkit-module/t - make && make install - -Configure: - - events { - resolver 192.168.84.254 114.114.114.114 valid=20s; - resolver_timeout 10s; - } - - http { - - ... - - server { - - ... - - location /event_resolver_test/ { - event_resolver_test; - } - } - } - -Install bind server - - /path/to/nginx-toolkit-module/t/dns_install.sh - -modify /var/named/test.com.zone dns ip address to fit your enviroment - -Test: - -- add domain for resolving - - curl -v "http://127.0.0.1/event_resolver_test/domain?domain=www.test.com" diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-event-timer-module.md b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-event-timer-module.md deleted file mode 100644 index 333d1206cf..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-event-timer-module.md +++ /dev/null @@ -1,112 +0,0 @@ -# Module ngx-event-timer-module ---- -## Instructions - -Independent timer for nginx - -## Directives - - Syntax : worker_timers number; - Default : worker_timers 1024; - Context : events - -Sets the maximum number of timers that can be used in worker process. - - events { - ... - worker_timers 1024; - } - -## API - -**header file** - -For using this API, You should include the header file as below: - - #include "ngx_event_timer_module.h" - -**registe domain** - - ngx_int_t ngx_event_timer_add_timer(ngx_msec_t tv, - ngx_timer_handler_pt h, void *data); - -- return value: - - return timerid for successd, NGX_ERROR for failed. - - Error: - - - h is NULL - - not enough timer for assigned - -- paras: - - - tv : timer interval to trigger handler - - h : timer handler - - data : data of h para - -Register a timer handler, timer interval is tv, measured by millisecond. When timer triggered, h will be called, using data as function parameters. - -h's protype is: - - typedef void (* ngx_timer_handler_pt)(void *data); - -- return value: - - None - -- paras: - - - data: data set in ngx\_event\_timer\_add\_timer, for paras transmit - -**del timer** - - void ngx_event_timer_del_timer(ngx_uint_t timerid); - -- return value: - - void - -- paras: - - - timerid: return by ngx\_event\_timer\_add\_timer - -Deregister timer handler. - -## Build - -cd to NGINX source directory & run this: - - ./configure --add-module=/path/to/nginx-toolkit-module/ - make && make install - -## Example - -See t/ngx\_event\_timer\_test\_module.c as reference - -Build: - - ./configure --add-module=/path/to/nginx-toolkit-module/t/ --add-module=/path/to/nginx-toolkit-module/ - make && make install - -Configure: - - location /event_timer_test/ { - event_timer_test; - } - -Test: - -add timer - - curl -XPOST -v "http://127.0.0.1/event_timer_test/timer?time=3s" - -Test module will start a timer when process init. It will log after 3 seconds, set in args: - - 2016/12/10 18:48:37 [error] 20295#0: event timer test timer handler - -del timer - - curl -XDELETE -v "http://127.0.0.1/event_timer_test/timer?timerid=1" - -Test module will stop a timer whose timerid is 1 diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-map.md b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-map.md deleted file mode 100644 index 52f094ddaa..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-map.md +++ /dev/null @@ -1,112 +0,0 @@ -# ngx-map ---- -## Instructions - -A map implement use ngx_rbtree - -## API - -**header file** - -For using this API, You should include the header file as below: - - #include "ngx_map.h" - -**structure** - - typedef struct { - ngx_rbtree_t rbtree; - ngx_rbtree_node_t sentinel; - ngx_map_hash_pt hash; - ngx_cmp_pt cmp; - } ngx_map_t; - - typedef struct { - ngx_rbtree_node_t rn; - intptr_t raw_key; - ngx_map_t *map; - } ngx_map_node_t; - -use ngx\_map\_t instance as a map, use ngx\_map\_init to initial. Put ngx\_map\_node\_t in your structure, and set raw_key, then you can insert your node in the map. Use raw_key, you can find node in map, or delete node in map. - -**ngx\_map\_init** - - void ngx_map_init(ngx_map_t *map, ngx_map_hash_pt hash, ngx_cmp_pt cmp) - -Interface for init a map, hash is hash func handler to calculate hashkey for rawkey, cmp is compare func handler for compare two raw_key, when raw_keys' hashkey is same. - -We support base hash and cmp func as below: - - /* ngx_str_t */ - ngx_rbtree_key_t ngx_map_hash_str(intptr_t key) - int ngx_cmp_str(intptr_t key1, intptr_t key2) - - /* ngx_uint_t */ - ngx_rbtree_key_t ngx_map_hash_uint(intptr_t key) - int ngx_cmp_uint(intptr_t key1, intptr_t key2) - - /* ngx_int_t */ - ngx_rbtree_key_t ngx_map_hash_int(intptr_t key) - int ngx_cmp_int(intptr_t key1, intptr_t key2) - -User also can use own hash and cmp func with protype below: - - /* - * key: key for map node - */ - typedef ngx_rbtree_key_t (* ngx_map_hash_pt)(intptr_t key); - - /* - * if key1 < key2, return -1 - * if key1 = key2, return 0 - * if key1 > key2, return 1 - */ - typedef int (* ngx_cmp_pt)(intptr_t key1, intptr_t key2); - -**ngx\_map\_empty** - - #define ngx_map_empty(map) (map->rbtree.root == map->rbtree.sentinel) - -If map is empty, return 1, else, return false - -**ngx\_map\_begin** - - ngx_map_node_t *ngx_map_begin(ngx_map_t *map) - -Return the mininum key node of map - -**ngx\_map\_rbegin** - - ngx_map_node_t *ngx_map_rbegin(ngx_map_t *map) - -Return the maxinum key node of map - -**ngx\_map\_next** - - ngx_map_node_t *ngx_map_next(ngx_map_node_t *n) - -Return the next node of n, if n is the maximum key node in map, return NULL - -**ngx\_map\_prev** - - ngx_map_node_t *ngx_map_prev(ngx_map_node_t *n) - -Return the previous node of n, if n is the mininum key node in map, return NULL - -**ngx\_map\_insert** - - void ngx_map_insert(ngx_map_t *map, ngx_map_node_t *node, ngx_flag_t covered) - -Interface for insert a node in map. New node will force replace old node in map if raw_key is same when covered set to 1. Otherwise, new node can't insert in map - -**ngx\_map\_delete** - - void ngx_map_delete(ngx_map_t *map, intptr_t key) - -Interface for delete a node in map, if node's raw_key equal to key in paras. If node is not exist, do nothing. - -**ngx\_map\_find** - - ngx_map_node_t *ngx_map_find(ngx_map_t *map, intptr_t key) - -Interface for find a node in map, if node's raw_key equal to key in paras. If node is not exist, return NULL. \ No newline at end of file diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-poold.md b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-poold.md deleted file mode 100644 index a631ffa7cd..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-poold.md +++ /dev/null @@ -1,19 +0,0 @@ -# ngx-poold ---- -## Instructions - -Pool debug for check whether pool is destroy or destroy twice - -## API - -**NGX\_CREATE\_POOL** - - #define NGX_CREATE_POOL(size, log) - -Replace NGX\_CREATE\_POOL instead of ngx\_create\_pool, it will record position creating pool. must use with NGX\_DESTROY\_POOL - -**NGX\_DESTROY\_POOL** - - #define NGX_DESTROY_POOL(pool) - -Replace NGX\_DESTROY\_POOL instead of ngx\_destroy\_pool, it will delete info which NGX\_CREATE\_POOL add. If pool not register in record pool, the pool will not destroy, and log delete twice log and position call the NGX\_DESTROY\_POOL. \ No newline at end of file diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-rbuf.md b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-rbuf.md deleted file mode 100644 index 84d22998d2..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-rbuf.md +++ /dev/null @@ -1,40 +0,0 @@ -# ngx-rbuf ---- -## Instructions - -A recycled chainbuf for nginx - -## API - -**header file** - -For using this API, You should include the header file as below: - - #include "ngx_rbuf.h" - -**ngx\_get\_chainbuf** - - ngx_chain_t *ngx_get_chainbuf(size_t size, ngx_flag_t alloc_rbuf); - -Interface for get a chain with buf, if alloc\_rbuf is set to 1, rbuf will alloc a buf with size set in paras; if alloc\_rbuf is set to 0, size is nonsense here. - -Notice, for recycled buf better memory manager, the size should be same for the same usage. Such as chunk size in nginx rtmp module. - - -**ngx\_put\_chainbuf** - - void ngx_put_chainbuf(ngx_chain_t *cl); - -Interface for recycle chain with buf alloc from rbuf - -**ngx\_rbuf\_statee** - - ngx_chain_t *ngx_rbuf_state(ngx_http_request_t *r); - -Interface for query rbuf state, result: - - ngx_rbuf_nalloc_node: 1 - ngx_rbuf_nalloc_buf: 1 - ngx_rbuf_nfree_buf: 1 - ngx_rbuf_nalloc_chain: 3 - ngx_rbuf_nalloc_chain: 3 diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-toolkit-misc.md b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-toolkit-misc.md deleted file mode 100644 index 23e61be21b..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-toolkit-misc.md +++ /dev/null @@ -1,89 +0,0 @@ -# ngx-toolkit-misc ---- -## Instructions - -Misc toolkit functions - -## API - -**header file** - -For using this API, You should include the header file as below: - - #include "ngx_toolkit_misc.h" - -**structure** - - /* - * scheme://[user@]host[:port]/path[?args][#fragment] - */ - typedef struct { - ngx_str_t scheme; - ngx_str_t user; - ngx_str_t host; - ngx_str_t port; - ngx_str_t path; - ngx_str_t args; - ngx_str_t fragment; - - ngx_str_t host_with_port; /* host[:port] */ - ngx_str_t uri_with_args; /* /path[?args][#fragment] */ - } ngx_request_url_t; - -**ngx\_parse\_request\_url** - - ngx_int_t ngx_parse_request_url(ngx_request_url_t *request_url, ngx_str_t *url); - -parse request url format as: scheme://[user@]host[:port]/path[?args][#fragment] - -- return value: - - - NGX_OK: parse success - - NGX_ERROR: request url format error - -- paras: - - - request_url: url parse result return to user, all paras in request url is segment point to url - - url: request url for parse - - -**ngx\_request\_port** - - in_port_t ngx_request_port(ngx_str_t *scheme, ngx_str_t *port); - -convert port to in_port_t according to scheme and port - -- return value: - - - If port is set to correct number range in [1, 65535], return port - - If port is set to non correct value, return 0 - - If port is not set, return default value for scheme: - - - 80 for http - - 443 for https - - 1935 for rtmp - - 0 for others now - -- values: - - - scheme : sheme string like http https or rtmp - - port : port for convert to in_port_t - - -**ngx\_md5\_file** - - #define NGX_MD5KEY_LEN 32 - - ngx_int_t ngx_md5_file(ngx_fd_t fd, u_char md5key[NGX_MD5KEY_LEN]); - -calculating file md5key as md5sum in shell - -- return value: - - - NGX_OK: calculating success - - NGX_ERROR: calculating error such as file is not exist - -- paras: - - - fd: file desc for calculating md5key - - md5key: md5key result \ No newline at end of file diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_dynamic_conf.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_dynamic_conf.c deleted file mode 100644 index fd8f15b8f6..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_dynamic_conf.c +++ /dev/null @@ -1,963 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include "ngx_dynamic_conf.h" -#include "ngx_toolkit_misc.h" -#include "ngx_event_timer_module.h" - - -static ngx_int_t ngx_dynamic_conf_process_init(ngx_cycle_t *cycle); - -static void *ngx_dynamic_conf_module_create_conf(ngx_cycle_t *cycle); -static char *ngx_dynamic_conf_module_init_conf(ngx_cycle_t *cycle, void *conf); - -static char *ngx_dynamic_conf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -static char *ngx_dynamic_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); - - -#define NGX_CONF_BUFFER 4096 - -ngx_uint_t ngx_core_max_module; - -static ngx_uint_t arg_number[] = { - NGX_CONF_NOARGS, - NGX_CONF_TAKE1, - NGX_CONF_TAKE2, - NGX_CONF_TAKE3, - NGX_CONF_TAKE4, - NGX_CONF_TAKE5, - NGX_CONF_TAKE6, - NGX_CONF_TAKE7 -}; - -typedef struct { - void **module_conf; /* index is module index */ - ngx_pool_t *pool; /* dynamic conf alloc pool */ -} ngx_dynamic_conf_ctx_t; - -typedef struct { - ngx_dynamic_conf_ctx_t *conf[2]; - unsigned used; /* 0 and 1 for index of conf */ - - ngx_str_t file; - ngx_msec_t refresh; - ngx_log_t *log; - - u_char md5key[NGX_MD5KEY_LEN + 1]; -} ngx_dynamic_conf_conf_t; - - -static ngx_command_t ngx_dynamic_conf_commands[] = { - - { ngx_string("dynamic_conf"), - NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE2, - ngx_dynamic_conf, - 0, - 0, - NULL }, - - { ngx_string("dynamic_log"), - NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_1MORE, - ngx_dynamic_log, - 0, - 0, - NULL }, - - ngx_null_command -}; - - -ngx_core_module_t ngx_dynamic_conf_module_ctx = { - ngx_string("dynamic_conf"), - ngx_dynamic_conf_module_create_conf, - ngx_dynamic_conf_module_init_conf -}; - - -ngx_module_t ngx_dynamic_conf_module = { - NGX_MODULE_V1, - &ngx_dynamic_conf_module_ctx, /* module context */ - ngx_dynamic_conf_commands, /* module directives */ - NGX_CORE_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - ngx_dynamic_conf_process_init, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void * -ngx_dynamic_conf_module_create_conf(ngx_cycle_t *cycle) -{ - ngx_dynamic_conf_conf_t *conf; - - conf = ngx_pcalloc(cycle->pool, sizeof(ngx_dynamic_conf_conf_t)); - if (conf == NULL) { - return NULL; - } - - conf->refresh = NGX_CONF_UNSET_MSEC; - - return conf; -} - -static char * -ngx_dynamic_conf_module_init_conf(ngx_cycle_t *cycle, void *conf) -{ - ngx_dynamic_conf_conf_t *dccf; - - dccf = conf; - - ngx_conf_init_msec_value(dccf->refresh, 60000); - - if (dccf->log == NULL) { - dccf->log = &cycle->new_log; - } - - return NGX_CONF_OK; -} - -static char * -ngx_dynamic_conf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_dynamic_conf_conf_t *dccf; - ngx_str_t *value; - ngx_fd_t fd; - - dccf = conf; - - if (dccf->file.len) { - return "is duplicate"; - } - - value = cf->args->elts; - - dccf->file = value[1]; - - if (ngx_conf_full_name(cf->cycle, &dccf->file, 0)) { - return NGX_CONF_ERROR; - } - - /* test file, ngx_conf_full_name will fill '\0' at end of file name */ - fd = ngx_open_file(dccf->file.data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); - if (fd == NGX_INVALID_FILE) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, "dynamic conf " - ngx_open_file_n " \"%s\" failed", dccf->file.data); - return NGX_CONF_ERROR; - } - ngx_close_file(fd); - - dccf->refresh = ngx_parse_time(&value[2], 0); - if (dccf->refresh == (ngx_msec_t) NGX_ERROR) { - return "invalid refresh"; - } - - dccf->used = 1; - - return NGX_CONF_OK; -} - -static char * -ngx_dynamic_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_dynamic_conf_conf_t *dccf = conf; - - return ngx_log_set_log(cf, &dccf->log); -} - - -static ngx_int_t -ngx_dynamic_conf_handler(ngx_conf_t *cf, ngx_int_t last) -{ - char *rv; - ngx_uint_t i, found; - ngx_str_t *name; - ngx_command_t *cmd; - void *conf; - - name = cf->args->elts; - - found = 0; - - for (i = 0; cf->cycle->modules[i]; ++i) { - - cmd = (ngx_command_t *) cf->cycle->modules[i]->spare_hook1; - if (cmd == NULL) { - continue; - } - - for (/* void */; cmd->name.len; ++cmd) { - - if (name->len != cmd->name.len) { - continue; - } - - if (ngx_strcmp(name->data, cmd->name.data) != 0) { - continue; - } - - found = 1; - - if (cf->cycle->modules[i]->type != NGX_CONF_MODULE - && cf->cycle->modules[i]->type != cf->module_type) - { - continue; - } - - /* is the directive's location right ? */ - - if (!(cmd->type & cf->cmd_type)) { - continue; - } - - if (!(cmd->type & NGX_CONF_BLOCK) && last != NGX_OK) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "directive \"%s\" is not terminated by \";\"", - name->data); - return NGX_ERROR; - } - - if ((cmd->type & NGX_CONF_BLOCK) && last != NGX_CONF_BLOCK_START) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "directive \"%s\" has no opening \"{\"", - name->data); - return NGX_ERROR; - } - - /* is the directive's argument count right ? */ - - if (!(cmd->type & NGX_CONF_ANY)) { - - if (cmd->type & NGX_CONF_FLAG) { - - if (cf->args->nelts != 2) { - goto invalid; - } - - } else if (cmd->type & NGX_CONF_1MORE) { - - if (cf->args->nelts < 2) { - goto invalid; - } - - } else if (cmd->type & NGX_CONF_2MORE) { - - if (cf->args->nelts < 3) { - goto invalid; - } - - } else if (cf->args->nelts > NGX_CONF_MAX_ARGS) { - - goto invalid; - - } else if (!(cmd->type & arg_number[cf->args->nelts - 1])) { - goto invalid; - } - } - - /* set up the directive's configuration context */ - - conf = ((void **) cf->ctx)[cf->cycle->modules[i]->ctx_index]; - - rv = cmd->set(cf, cmd, conf); - - if (rv == NGX_CONF_OK) { - return NGX_OK; - } - - if (rv == NGX_CONF_ERROR) { - return NGX_ERROR; - } - - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "\"%s\" directive %s", name->data, rv); - - return NGX_ERROR; - } - } - - if (found) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "\"%s\" directive is not allowed here", name->data); - - return NGX_ERROR; - } - - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "unknown directive \"%s\"", name->data); - - return NGX_ERROR; - -invalid: - - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid number of arguments in \"%s\" directive", - name->data); - - return NGX_ERROR; -} - -/* same as ngx_conf_read_token in ngx_conf_file.c */ -static ngx_int_t -ngx_dynamic_conf_read_token(ngx_conf_t *cf) -{ - u_char *start, ch, *src, *dst; - off_t file_size; - size_t len; - ssize_t n, size; - ngx_uint_t found, need_space, last_space, sharp_comment, - variable; - ngx_uint_t quoted, s_quoted, d_quoted, start_line; - ngx_str_t *word; - ngx_buf_t *b; - - found = 0; - need_space = 0; - last_space = 1; - sharp_comment = 0; - variable = 0; - quoted = 0; - s_quoted = 0; - d_quoted = 0; - - cf->args->nelts = 0; - b = cf->conf_file->buffer; - start = b->pos; - start_line = cf->conf_file->line; - - file_size = ngx_file_size(&cf->conf_file->file.info); - - for ( ;; ) { - - if (b->pos >= b->last) { - - if (cf->conf_file->file.offset >= file_size) { - - if (cf->args->nelts > 0 || !last_space) { - - if (cf->conf_file->file.fd == NGX_INVALID_FILE) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "unexpected end of parameter, " - "expecting \";\""); - return NGX_ERROR; - } - - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "unexpected end of file, " - "expecting \";\" or \"}\""); - return NGX_ERROR; - } - - return NGX_CONF_FILE_DONE; - } - - len = b->pos - start; - - if (len == NGX_CONF_BUFFER) { - cf->conf_file->line = start_line; - - if (d_quoted) { - ch = '"'; - - } else if (s_quoted) { - ch = '\''; - - } else { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "too long parameter \"%*s...\" started", - 10, start); - return NGX_ERROR; - } - - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "too long parameter, probably " - "missing terminating \"%c\" character", ch); - return NGX_ERROR; - } - - if (len) { - ngx_memmove(b->start, start, len); - } - - size = (ssize_t) (file_size - cf->conf_file->file.offset); - - if (size > b->end - (b->start + len)) { - size = b->end - (b->start + len); - } - - n = ngx_read_file(&cf->conf_file->file, b->start + len, size, - cf->conf_file->file.offset); - - if (n == NGX_ERROR) { - return NGX_ERROR; - } - - if (n != size) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - ngx_read_file_n " returned " - "only %z bytes instead of %z", - n, size); - return NGX_ERROR; - } - - b->pos = b->start + len; - b->last = b->pos + n; - start = b->start; - } - - ch = *b->pos++; - - if (ch == LF) { - cf->conf_file->line++; - - if (sharp_comment) { - sharp_comment = 0; - } - } - - if (sharp_comment) { - continue; - } - - if (quoted) { - quoted = 0; - continue; - } - - if (need_space) { - if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) { - last_space = 1; - need_space = 0; - continue; - } - - if (ch == ';') { - return NGX_OK; - } - - if (ch == '{') { - return NGX_CONF_BLOCK_START; - } - - if (ch == ')') { - last_space = 1; - need_space = 0; - - } else { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "unexpected \"%c\"", ch); - return NGX_ERROR; - } - } - - if (last_space) { - if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) { - continue; - } - - start = b->pos - 1; - start_line = cf->conf_file->line; - - switch (ch) { - - case ';': - case '{': - if (cf->args->nelts == 0) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "unexpected \"%c\"", ch); - return NGX_ERROR; - } - - if (ch == '{') { - return NGX_CONF_BLOCK_START; - } - - return NGX_OK; - - case '}': - if (cf->args->nelts != 0) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "unexpected \"}\""); - return NGX_ERROR; - } - - return NGX_CONF_BLOCK_DONE; - - case '#': - sharp_comment = 1; - continue; - - case '\\': - quoted = 1; - last_space = 0; - continue; - - case '"': - start++; - d_quoted = 1; - last_space = 0; - continue; - - case '\'': - start++; - s_quoted = 1; - last_space = 0; - continue; - - default: - last_space = 0; - } - - } else { - if (ch == '{' && variable) { - continue; - } - - variable = 0; - - if (ch == '\\') { - quoted = 1; - continue; - } - - if (ch == '$') { - variable = 1; - continue; - } - - if (d_quoted) { - if (ch == '"') { - d_quoted = 0; - need_space = 1; - found = 1; - } - - } else if (s_quoted) { - if (ch == '\'') { - s_quoted = 0; - need_space = 1; - found = 1; - } - - } else if (ch == ' ' || ch == '\t' || ch == CR || ch == LF - || ch == ';' || ch == '{') - { - last_space = 1; - found = 1; - } - - if (found) { - word = ngx_array_push(cf->args); - if (word == NULL) { - return NGX_ERROR; - } - - word->data = ngx_pnalloc(cf->pool, b->pos - 1 - start + 1); - if (word->data == NULL) { - return NGX_ERROR; - } - - for (dst = word->data, src = start, len = 0; - src < b->pos - 1; - len++) - { - if (*src == '\\') { - switch (src[1]) { - case '"': - case '\'': - case '\\': - src++; - break; - - case 't': - *dst++ = '\t'; - src += 2; - continue; - - case 'r': - *dst++ = '\r'; - src += 2; - continue; - - case 'n': - *dst++ = '\n'; - src += 2; - continue; - } - - } - *dst++ = *src++; - } - *dst = '\0'; - word->len = len; - - if (ch == ';') { - return NGX_OK; - } - - if (ch == '{') { - return NGX_CONF_BLOCK_START; - } - - found = 0; - } - } - } -} - -ngx_int_t -ngx_dynamic_conf_parse(ngx_conf_t *cf, unsigned init) -{ - ngx_int_t rc; - enum { - parse_init = 0, - parse_block - } type; - - type = init ? parse_init : parse_block; - - for (;;) { - rc = ngx_dynamic_conf_read_token(cf); - - /* - * ngx_conf_read_token() may return - * - * NGX_ERROR there is error - * NGX_OK the token terminated by ";" was found - * NGX_CONF_BLOCK_START the token terminated by "{" was found - * NGX_CONF_BLOCK_DONE the "}" was found - * NGX_CONF_FILE_DONE the configuration file is done - */ - - if (rc == NGX_ERROR) { - return NGX_ERROR; - } - - if (rc == NGX_CONF_BLOCK_DONE) { - - if (type != parse_block) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected \"}\""); - return NGX_ERROR; - } - - return NGX_OK; - } - - if (rc == NGX_CONF_FILE_DONE) { - - if (type == parse_block) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "unexpected end of file, expecting \"}\""); - return NGX_ERROR; - } - - return NGX_OK; - } - - rc = ngx_dynamic_conf_handler(cf, rc); - - if (rc == NGX_ERROR) { - return NGX_ERROR; - } - } -} - -static ngx_int_t -ngx_dynamic_conf_load_conf(ngx_fd_t fd, ngx_dynamic_conf_conf_t *dccf) -{ - ngx_dynamic_conf_ctx_t *conf; - ngx_dynamic_core_module_t *module; - ngx_pool_t *pool; - ngx_conf_t cf; - ngx_buf_t buf; - ngx_conf_file_t conf_file; - u_char buffer[NGX_CONF_BUFFER]; - ngx_uint_t i; - void *rv; - - ngx_memzero(&cf, sizeof(ngx_conf_t)); - - pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, dccf->log); - if (pool == NULL) { - return NGX_ERROR; - } - pool->log = dccf->log; - - conf = ngx_pcalloc(pool, sizeof(ngx_dynamic_conf_ctx_t)); - if (conf == NULL) { - goto failed; - } - conf->pool = pool; - - ngx_core_max_module = ngx_count_modules((ngx_cycle_t *) ngx_cycle, - NGX_CORE_MODULE); - - conf->module_conf = ngx_pcalloc(pool, sizeof(void *) * ngx_core_max_module); - if (conf->module_conf == NULL) { - goto failed; - } - - cf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t)); - if (cf.args == NULL) { - goto failed; - } - - cf.temp_pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, dccf->log); - if (cf.temp_pool == NULL) { - goto failed; - } - - cf.ctx = conf->module_conf; - cf.cycle = (ngx_cycle_t *) ngx_cycle; - cf.pool = pool; - cf.log = dccf->log; - cf.module_type = NGX_CORE_MODULE; - cf.cmd_type = NGX_MAIN_CONF; - - cf.conf_file = &conf_file; - - if (ngx_fd_info(fd, &cf.conf_file->file.info) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_EMERG, cf.log, ngx_errno, - ngx_fd_info_n " failed"); - } - - cf.conf_file->buffer = &buf; - - buf.pos = buf.last = buf.start = buffer; - buf.end = buf.start + NGX_CONF_BUFFER; - buf.temporary = 1; - - cf.conf_file->file.fd = fd; - cf.conf_file->file.name.len = dccf->file.len; - cf.conf_file->file.name.data = dccf->file.data; - cf.conf_file->file.offset = 0; - cf.conf_file->file.log = cf.log; - cf.conf_file->line = 1; - - for (i = 0; ngx_cycle->modules[i]; ++i) { - if (ngx_cycle->modules[i]->type != NGX_CORE_MODULE) { - continue; - } - - module = (ngx_dynamic_core_module_t *) - ngx_cycle->modules[i]->spare_hook0; - if (module == NULL) { /* dctx not configured */ - continue; - } - - if (module->create_conf) { - rv = module->create_conf(&cf); - if (rv == NULL) { - goto failed; - } - conf->module_conf[ngx_cycle->modules[i]->ctx_index] = rv; - } - } - - if (ngx_dynamic_conf_parse(&cf, 1) != NGX_OK) { - goto failed; - } - - for (i = 0; ngx_cycle->modules[i]; ++i) { - if (ngx_cycle->modules[i]->type != NGX_CORE_MODULE) { - continue; - } - - module = (ngx_dynamic_core_module_t *) ngx_cycle->modules[i]-> - spare_hook0; - if (module == NULL) { - continue; - } - - if (module->init_conf) { - - rv = conf->module_conf[ngx_cycle->modules[i]->ctx_index]; - if (module->init_conf(&cf, rv) == NGX_CONF_ERROR) { - goto failed; - } - } - } - - /* load conf ok, switch conf to new conf */ - if (dccf->conf[dccf->used]) { - pool = dccf->conf[dccf->used]->pool; - dccf->conf[dccf->used] = NULL; - ngx_destroy_pool(pool); - } - - dccf->used = dccf->used ? 0 : 1; - dccf->conf[dccf->used] = conf; - - return NGX_OK; - -failed: - if (cf.temp_pool) { - ngx_destroy_pool(cf.temp_pool); - } - - ngx_destroy_pool(pool); - - return NGX_ERROR; -} - -static void -ngx_dynamic_conf_check_conf(void *data) -{ - ngx_dynamic_conf_conf_t *dccf; - ngx_fd_t fd; - u_char md5key[NGX_MD5KEY_LEN]; - NGX_START_TIMING - - dccf = data; - - if (ngx_exiting) { /* avoid nginx reload worker hungup */ - return; - } - - fd = ngx_open_file(dccf->file.data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); - if (fd == NGX_INVALID_FILE) { - ngx_log_error(NGX_LOG_ERR, dccf->log, ngx_errno, - ngx_open_file_n "\"%V\" failed", &dccf->file); - goto done; - } - - /* check md5key for dynamic conf file */ - if (ngx_md5_file(fd, md5key) == NGX_ERROR) { - ngx_log_error(NGX_LOG_ERR, dccf->log, 0, "md5 file \"%V\" failed", - &dccf->file); - goto done; - } - - if (ngx_memcmp(dccf->md5key, md5key, NGX_MD5KEY_LEN) == 0) { - ngx_log_debug1(NGX_LOG_DEBUG_CORE, dccf->log, 0, - "\"%V\" md5key not change", &dccf->file); - goto done; - } - - /* parse dynamic conf */ - if (ngx_dynamic_conf_load_conf(fd, dccf) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, dccf->log, 0, "load file \"%V\" failed", - &dccf->file); - goto done; - } - - ngx_memcpy(dccf->md5key, md5key, NGX_MD5KEY_LEN); - - ngx_log_error(NGX_LOG_INFO, dccf->log, 0, - "dynamic conf load successd, md5key: \"%s\"", dccf->md5key); - -done: - ngx_close_file(fd); - - ngx_event_timer_add_timer(dccf->refresh, ngx_dynamic_conf_check_conf, dccf); - - NGX_STOP_TIMING(dccf->log, "ngx_dynamic_conf_check_conf") -} - -static ngx_int_t ngx_dynamic_conf_process_init(ngx_cycle_t *cycle) -{ - ngx_dynamic_conf_conf_t *dccf; - ngx_fd_t fd; - u_char md5key[NGX_MD5KEY_LEN]; - - NGX_START_TIMING - - dccf = (ngx_dynamic_conf_conf_t *) ngx_get_conf(cycle->conf_ctx, - ngx_dynamic_conf_module); - - if (dccf->file.len == 0) { /* dynamic conf not configured */ - return NGX_OK; - } - - fd = ngx_open_file(dccf->file.data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); - if (fd == NGX_INVALID_FILE) { - ngx_log_error(NGX_LOG_ERR, dccf->log, ngx_errno, - ngx_open_file_n "\"%V\" failed", &dccf->file); - return NGX_ERROR; - } - - /* parse dynamic conf */ - if (ngx_dynamic_conf_load_conf(fd, dccf) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, dccf->log, 0, "load file \"%V\" failed", - &dccf->file); - return NGX_ERROR; - } - - /* calc md5key for dynamic conf file */ - if (ngx_md5_file(fd, md5key) == NGX_ERROR) { - ngx_log_error(NGX_LOG_ERR, dccf->log, 0, "md5 file \"%V\" failed", - &dccf->file); - return NGX_ERROR; - } - - ngx_close_file(fd); - - ngx_memcpy(dccf->md5key, md5key, NGX_MD5KEY_LEN); - - ngx_log_error(NGX_LOG_INFO, dccf->log, 0, - "dynamic conf load successd, md5key: \"%s\"", dccf->md5key); - - /* add dynamic conf parse timer */ - ngx_event_timer_add_timer(dccf->refresh, ngx_dynamic_conf_check_conf, dccf); - - NGX_STOP_TIMING(dccf->log, "ngx_dynamic_conf_process_init") - - return NGX_OK; -} - -#if (NGX_PCRE) -ngx_dynamic_regex_t * -ngx_dynamic_regex_compile(ngx_conf_t *cf, ngx_regex_compile_t *rc) -{ - ngx_dynamic_regex_t *re; - - rc->pool = cf->pool; - - if (ngx_regex_compile(rc) != NGX_OK) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc->err); - return NULL; - } - - re = ngx_pcalloc(cf->pool, sizeof(ngx_regex_elt_t)); - if (re == NULL) { - return NULL; - } - - re->regex = rc->regex; - re->name = rc->pattern; - - return re; -} -#endif - -int -ngx_dynamic_cmp_dns_wildcards(const void *one, const void *two) -{ - ngx_hash_key_t *first, *second; - - first = (ngx_hash_key_t *) one; - second = (ngx_hash_key_t *) two; - - return ngx_dns_strcmp(first->key.data, second->key.data); -} - -void * -ngx_get_dconf(ngx_module_t *m) -{ - ngx_dynamic_conf_conf_t *dccf; - - dccf = (ngx_dynamic_conf_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, - ngx_dynamic_conf_module); - - if (dccf->conf[dccf->used] == 0) { /* dynamic conf not configured */ - return NULL; - } - - return dccf->conf[dccf->used]->module_conf[m->ctx_index]; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_dynamic_conf.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_dynamic_conf.h deleted file mode 100644 index 3d2f6d168a..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_dynamic_conf.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - - -#ifndef _NGX_DYNAMIC_COMMAND_H_INCLUDED_ -#define _NGX_DYNAMIC_COMMAND_H_INCLUDED_ - - -#include -#include -#include - - -typedef struct { - ngx_str_t name; - void *(*create_conf)(ngx_conf_t *cf); - char *(*init_conf)(ngx_conf_t *cf, void *conf); -} ngx_dynamic_core_module_t; - - -#if (NGX_PCRE) -typedef struct { - ngx_regex_t *regex; - ngx_str_t name; -} ngx_dynamic_regex_t; -#endif - -#if 0 -/* - * if use dynamic conf, module define should use - * NGX_MODULE_V1_DYNAMIC_PADDING and set - * module dynamic context and - * module dynamic directives as bellow - */ -ngx_module_t ngx_test_module = { - NGX_MODULE_V1, - &ngx_test_module_ctx, /* module context */ - ngx_test_commands, /* module directives */ - NGX_CORE_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - &ngx_test_module_dctx, /* module dynamic context */ - ngx_test_dcommands, /* module dynamic directives */ - NGX_MODULE_V1_DYNAMIC_PADDING -}; -#endif -#define NGX_MODULE_V1_DYNAMIC_PADDING 0, 0, 0, 0, 0, 0 - -extern ngx_uint_t ngx_core_max_module; - -/* - * return value: - * return NGX_OK for successd, NGX_ERROR for failed - * paras: - * cf: ngx_conf_t passed from ngx_dynamic_conf_load_conf - * init: only ngx_dynamic_conf_load_conf set 1, otherwise set 0 - */ -ngx_int_t ngx_dynamic_conf_parse(ngx_conf_t *cf, unsigned init); - -/* - * return value: - * return regex context - * paras: - * cf: ngx_conf_t passed in dynamic cmd handler - * rc: regex options - */ -#if (NGX_PCRE) -ngx_dynamic_regex_t *ngx_dynamic_regex_compile(ngx_conf_t *cf, - ngx_regex_compile_t *rc); -#endif - -int ngx_dynamic_cmp_dns_wildcards(const void *one, const void *two); - -void *ngx_get_dconf(ngx_module_t *m); - - -#endif diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_dynamic_resolver.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_dynamic_resolver.c deleted file mode 100644 index 6f1592ff26..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_dynamic_resolver.c +++ /dev/null @@ -1,700 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include -#include -#include -#include "ngx_event_timer_module.h" -#include "ngx_event_resolver.h" -#include "ngx_dynamic_resolver.h" -#include "ngx_toolkit_misc.h" - - -static ngx_int_t ngx_dynamic_resolver_process_init(ngx_cycle_t *cycle); - -static void *ngx_dynamic_resolver_create_conf(ngx_cycle_t *cycle); -static char *ngx_dynamic_resolver_init_conf(ngx_cycle_t *cycle, void *conf); - - -#define MAX_DOMAIN_LEN 128 -#define MAX_ADDRS 8 - - -typedef struct ngx_dynamic_resolver_ctx_s ngx_dynamic_resolver_ctx_t; -typedef struct ngx_dynamic_resolver_domain_s ngx_dynamic_resolver_domain_t; - -struct ngx_dynamic_resolver_ctx_s { - ngx_dynamic_resolver_handler_pt h; - void *data; - - ngx_dynamic_resolver_ctx_t *next; -}; - -typedef struct { - struct sockaddr sockaddr; - socklen_t socklen; - u_short priority; - u_short weight; -} ngx_dynamic_resolver_addr_t; - -struct ngx_dynamic_resolver_domain_s { - ngx_str_t domain; - u_char domain_cstr[MAX_DOMAIN_LEN]; - - ngx_uint_t naddrs; - ngx_dynamic_resolver_addr_t addrs[MAX_ADDRS]; - - ngx_dynamic_resolver_ctx_t *ctx; - - ngx_dynamic_resolver_domain_t *next; -}; - -typedef struct { - ngx_msec_t refresh_interval; - - size_t domain_buckets; - ngx_dynamic_resolver_domain_t **resolver_hash; - - ngx_dynamic_resolver_ctx_t *free_ctx; - ngx_dynamic_resolver_domain_t *free_domain; - - ngx_uint_t nalloc_ctx; - ngx_uint_t nfree_ctx; - ngx_uint_t nalloc_domain; - ngx_uint_t nfree_domain; -} ngx_dynamic_resolver_conf_t; - - -static ngx_str_t dynamic_resolver_name = ngx_string("dynamic_resolver"); - - -static ngx_command_t ngx_dynamic_resolver_commands[] = { - - { ngx_string("dynamic_refresh_interval"), - NGX_EVENT_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - 0, - offsetof(ngx_dynamic_resolver_conf_t, refresh_interval), - NULL }, - - { ngx_string("dynamic_domain_buckets"), - NGX_EVENT_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - 0, - offsetof(ngx_dynamic_resolver_conf_t, domain_buckets), - NULL }, - - ngx_null_command -}; - - -ngx_event_module_t ngx_dynamic_resolver_module_ctx = { - &dynamic_resolver_name, - ngx_dynamic_resolver_create_conf, /* create configuration */ - ngx_dynamic_resolver_init_conf, /* init configuration */ - - { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } -}; - - -/* this module use ngx_cycle->log */ -ngx_module_t ngx_dynamic_resolver_module = { - NGX_MODULE_V1, - &ngx_dynamic_resolver_module_ctx, /* module context */ - ngx_dynamic_resolver_commands, /* module directives */ - NGX_EVENT_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - ngx_dynamic_resolver_process_init, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void * -ngx_dynamic_resolver_create_conf(ngx_cycle_t *cycle) -{ - ngx_dynamic_resolver_conf_t *conf; - - conf = ngx_pcalloc(cycle->pool, sizeof(ngx_dynamic_resolver_conf_t)); - if (conf == NULL) { - return NULL; - } - - conf->refresh_interval = NGX_CONF_UNSET_MSEC; - conf->domain_buckets = NGX_CONF_UNSET_UINT; - - return conf; -} - -static char * -ngx_dynamic_resolver_init_conf(ngx_cycle_t *cycle, void *conf) -{ - ngx_dynamic_resolver_conf_t *drcf = conf; - - ngx_conf_init_msec_value(drcf->refresh_interval, 5000); - ngx_conf_init_uint_value(drcf->domain_buckets, 101); - - if (drcf->refresh_interval > 0 && drcf->domain_buckets > 0) { - drcf->resolver_hash = ngx_pcalloc(cycle->pool, - sizeof(ngx_dynamic_resolver_domain_t *) * drcf->domain_buckets); - } - - return NGX_CONF_OK; -} - -/* reuse for ngx_dynamic_resolver_ctx_t */ -static ngx_dynamic_resolver_ctx_t * -ngx_dynamic_resolver_get_ctx(ngx_cycle_t *cycle) -{ - ngx_dynamic_resolver_conf_t *drcf; - ngx_dynamic_resolver_ctx_t *ctx; - - drcf = ngx_event_get_conf(cycle->conf_ctx, ngx_dynamic_resolver_module); - - ctx = drcf->free_ctx; - - if (ctx == NULL) { - ctx = ngx_pcalloc(cycle->pool, sizeof(ngx_dynamic_resolver_ctx_t)); - - if (ctx == NULL) { - ngx_log_error(NGX_LOG_ERR, cycle->log, 0, "dynamic resolver, " - "alloc memory dynamic resolver ctx failed"); - return NULL; - } - ++drcf->nalloc_ctx; - } else { - drcf->free_ctx = drcf->free_ctx->next; - ngx_memzero(ctx, sizeof(ngx_dynamic_resolver_ctx_t)); - --drcf->nfree_ctx; - } - - return ctx; -} - -static void -ngx_dynamic_resolver_put_ctx(ngx_dynamic_resolver_ctx_t *ctx, - ngx_cycle_t *cycle) -{ - ngx_dynamic_resolver_conf_t *drcf; - - drcf = ngx_event_get_conf(cycle->conf_ctx, ngx_dynamic_resolver_module); - - ctx->next = drcf->free_ctx; - drcf->free_ctx = ctx; - ++drcf->nfree_ctx; -} - -/* reuse for ngx_dynamic_resolver_domain_t */ -static ngx_dynamic_resolver_domain_t * -ngx_dynamic_resolver_get_domain(ngx_cycle_t *cycle) -{ - ngx_dynamic_resolver_conf_t *drcf; - ngx_dynamic_resolver_domain_t *domain; - - drcf = ngx_event_get_conf(cycle->conf_ctx, ngx_dynamic_resolver_module); - - domain = drcf->free_domain; - - if (domain == NULL) { - domain = ngx_pcalloc(cycle->pool, - sizeof(ngx_dynamic_resolver_domain_t)); - - if (domain == NULL) { - ngx_log_error(NGX_LOG_ERR, cycle->log, 0, "dynamic resolver, " - "alloc memory dynamic resolver domain failed"); - return NULL; - } - ++drcf->nalloc_domain; - } else { - drcf->free_domain = drcf->free_domain->next; - ngx_memzero(domain, sizeof(ngx_dynamic_resolver_domain_t)); - --drcf->nfree_domain; - } - - return domain; -} - -static void -ngx_dynamic_resolver_put_domain(ngx_dynamic_resolver_domain_t *domain, - ngx_cycle_t *cycle) -{ - ngx_dynamic_resolver_conf_t *drcf; - - drcf = ngx_event_get_conf(cycle->conf_ctx, ngx_dynamic_resolver_module); - - domain->next = drcf->free_domain; - drcf->free_domain = domain; - ++drcf->nfree_domain; -} - - -static void -ngx_dynamic_resolver_on_result(void *data, ngx_resolver_addr_t *addrs, - ngx_uint_t naddrs) -{ - ngx_dynamic_resolver_domain_t *domain; - ngx_dynamic_resolver_ctx_t *ctx; - ngx_uint_t i, n; - - domain = data; - - if (domain == NULL) { - ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, "dynamic resolver, " - "%V has been deleted", &domain->domain); - return; - } - - if (naddrs == 0) { - ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, "dynamic resolver, " - "domain '%V' resolver failed", &domain->domain); - - while (domain->ctx) { - ctx = domain->ctx; - domain->ctx = ctx->next; - - ctx->h(ctx->data, NULL, 0); - ngx_dynamic_resolver_put_ctx(ctx, (ngx_cycle_t *) ngx_cycle); - } - - return; - } - - domain->naddrs = ngx_min(naddrs, MAX_ADDRS); - for (i = 0; i < domain->naddrs; ++i) { - ngx_memcpy(&domain->addrs[i].sockaddr, addrs[i].sockaddr, - addrs[i].socklen); - domain->addrs[i].socklen = addrs[i].socklen; - domain->addrs[i].priority = addrs[i].priority; - domain->addrs[i].weight = addrs[i].weight; - - n = ngx_random() % domain->naddrs; - - while (domain->ctx) { - ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, - "dynamic resolver, resolver '%V' successd", - &domain->domain); - ctx = domain->ctx; - domain->ctx = ctx->next; - - ctx->h(ctx->data, &domain->addrs[n].sockaddr, - domain->addrs[n].socklen); - ngx_dynamic_resolver_put_ctx(ctx, (ngx_cycle_t *) ngx_cycle); - - ++n; - n %= domain->naddrs; - } - } -} - -static void -ngx_dynamic_resolver_on_timer(void *data) -{ - ngx_dynamic_resolver_conf_t *drcf; - ngx_dynamic_resolver_domain_t *domain; - ngx_uint_t i; - - if (ngx_exiting) { - return; - } - - drcf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_dynamic_resolver_module); - - for (i = 0; i < drcf->domain_buckets; ++i) { - domain = drcf->resolver_hash[i]; - while (domain) { - ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, - "dynamic resolver, on timer start resolver %V", - &domain->domain); - - ngx_event_resolver_start_resolver(&domain->domain, - ngx_dynamic_resolver_on_result, domain); - domain = domain->next; - } - } - - ngx_event_timer_add_timer(drcf->refresh_interval, - ngx_dynamic_resolver_on_timer, NULL); -} - -static ngx_int_t -ngx_dynamic_resolver_process_init(ngx_cycle_t *cycle) -{ - ngx_dynamic_resolver_conf_t *drcf; - - drcf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_dynamic_resolver_module); - if (drcf->refresh_interval == 0) { - return NGX_OK; - } - - ngx_event_timer_add_timer(0, ngx_dynamic_resolver_on_timer, NULL); - - return NGX_OK; -} - - -void -ngx_dynamic_resolver_add_domain(ngx_str_t *domain, ngx_cycle_t *cycle) -{ - ngx_dynamic_resolver_conf_t *drcf; - ngx_dynamic_resolver_domain_t *d; - ngx_uint_t idx; - struct sockaddr sa; - socklen_t len; - u_char temp[MAX_DOMAIN_LEN]; - - if (domain == NULL || domain->len == 0) { - ngx_log_error(NGX_LOG_ERR, cycle->log, 0, - "dynamic resolver add, domain is NULL"); - return; - } - - len = ngx_sock_pton(&sa, domain->data, domain->len); - /* addr is IP address */ - if (len) { - ngx_log_error(NGX_LOG_DEBUG_CORE, cycle->log, 0, - "dynamic resolver add, domain is ipv4/ipv6/unix address"); - - return; - } - - drcf = ngx_event_get_conf(cycle->conf_ctx, ngx_dynamic_resolver_module); - if (drcf->refresh_interval == 0) { - ngx_log_error(NGX_LOG_ERR, cycle->log, 0, "dynamic resolver add, " - "dynamic resolver closed when add domain"); - return; - } - - if (domain->len > MAX_DOMAIN_LEN) { - ngx_log_error(NGX_LOG_ERR, cycle->log, 0, "dynamic resolver add, " - "domain length(%z) is too long", domain->len); - return; - } - - ngx_memzero(temp, MAX_DOMAIN_LEN); - idx = ngx_hash_strlow(temp, domain->data, domain->len); - idx %= drcf->domain_buckets; - - ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0, "dynamic resolver add, " - "prepare add %V in %d slot", domain, idx); - - for (d = drcf->resolver_hash[idx]; d; d = d->next) { - - if (d->domain.len == domain->len && - ngx_memcmp(d->domain.data, temp, domain->len) == 0) - { - ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0, - "dynamic resolver add, %V is in dynamic resolv hash table", - domain); - return; - } - } - - d = ngx_dynamic_resolver_get_domain(cycle); - if (d == NULL) { - return; - } - - /* add domain in dynamic resolver */ - d->next = drcf->resolver_hash[idx]; - drcf->resolver_hash[idx] = d; - - ngx_memcpy(d->domain_cstr, temp, MAX_DOMAIN_LEN); - d->domain.data = d->domain_cstr; - d->domain.len = domain->len; -} - -void -ngx_dynamic_resolver_del_domain(ngx_str_t *domain) -{ - ngx_dynamic_resolver_conf_t *drcf; - ngx_dynamic_resolver_domain_t **pd, *d; - ngx_dynamic_resolver_ctx_t *ctx; - ngx_uint_t idx; - struct sockaddr sa; - socklen_t len; - u_char temp[MAX_DOMAIN_LEN]; - - if (domain == NULL || domain->len == 0) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, - "dynamic resolver del, domain is NULL"); - return; - } - - len = ngx_sock_pton(&sa, domain->data, domain->len); - /* addr is IP address */ - if (len) { - ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, - "dynamic resolver del, domain is ipv4/ipv6/unix address"); - - return; - } - - drcf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_dynamic_resolver_module); - if (drcf->refresh_interval == 0) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "dynamic resolver del, " - "dynamic resolver closed when del domain"); - return; - } - - if (domain->len > MAX_DOMAIN_LEN) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "dynamic resolver del, " - "domain length(%z) is too long", domain->len); - return; - } - - ngx_memzero(temp, MAX_DOMAIN_LEN); - idx = ngx_hash_strlow(temp, domain->data, domain->len); - idx %= drcf->domain_buckets; - - ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, "dynamic resolver del, " - "prepare del %V in %d slot", domain, idx); - - for (pd = &drcf->resolver_hash[idx]; *pd; pd = &(*pd)->next) { - - if ((*pd)->domain.len == domain->len && - ngx_memcmp((*pd)->domain.data, temp, domain->len) == 0) - { - d= *pd; - *pd = (*pd)->next; - - while (d->ctx) { - ctx = d->ctx; - d->ctx = ctx->next; - - ctx->h(ctx->data, NULL, 0); - ngx_dynamic_resolver_put_ctx(ctx, (ngx_cycle_t *) ngx_cycle); - } - - ngx_dynamic_resolver_put_domain(d, (ngx_cycle_t *) ngx_cycle); - - return; - } - } - - ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, "dynamic resolver del, " - "%V is not in dynamic resolv hash table", domain); -} - -void -ngx_dynamic_resolver_start_resolver(ngx_str_t *domain, - ngx_dynamic_resolver_handler_pt h, void *data) -{ - ngx_dynamic_resolver_conf_t *drcf; - ngx_dynamic_resolver_domain_t *d; - ngx_dynamic_resolver_ctx_t *ctx; - ngx_uint_t idx, n; - struct sockaddr sa; - socklen_t len; - u_char temp[MAX_DOMAIN_LEN]; - - if (domain == NULL || domain->len == 0) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, - "dynamic resolver async, domain is NULL"); - return; - } - - len = ngx_sock_pton(&sa, domain->data, domain->len); - /* addr is ipv4/ipv6/unix address */ - if (len) { - ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, - "dynamic resolver async, domain is ipv4/ipv6/unix address"); - - h(data, &sa, len); - - return; - } - - drcf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_dynamic_resolver_module); - if (drcf->refresh_interval == 0) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "dynamic resolver async, " - "dynamic resolver closed when start resolver"); - goto failed; - } - - if (domain->len > MAX_DOMAIN_LEN) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "dynamic resolver async, " - "domain length(%z) is too long", domain->len); - goto failed; - } - - ngx_memzero(temp, MAX_DOMAIN_LEN); - idx = ngx_hash_strlow(temp, domain->data, domain->len); - idx %= drcf->domain_buckets; - - d = drcf->resolver_hash[idx]; - while (d) { - if (d->domain.len == domain->len && - ngx_memcmp(d->domain.data, temp, domain->len) == 0) - { - break; - } - d = d->next; - } - - if (d == NULL) { /* not found */ - d = ngx_dynamic_resolver_get_domain((ngx_cycle_t *) ngx_cycle); - if (d == NULL) { - goto failed; - } - - /* add domain in dynamic resolver */ - d->next = drcf->resolver_hash[idx]; - drcf->resolver_hash[idx] = d; - - ngx_memcpy(d->domain_cstr, temp, MAX_DOMAIN_LEN); - d->domain.data = d->domain_cstr; - d->domain.len = domain->len; - } - - /* domain is not resolved */ - if (d->naddrs == 0) { - - /* add call back in resolver list */ - ctx = ngx_dynamic_resolver_get_ctx((ngx_cycle_t *) ngx_cycle); - if (ctx == NULL) { - goto failed; - } - - ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, - "dynamic resolver async, domain '%V' is not resolved", - &d->domain); - ctx->h = h; - ctx->data = data; - - ctx->next = d->ctx; - d->ctx = ctx; - - ngx_event_resolver_start_resolver(&d->domain, - ngx_dynamic_resolver_on_result, d); - - return; - } - - ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, - "dynamic resolver async, domain '%V' is resolved, call directly", - &d->domain); - - /* call callback */ - n = ngx_random() % d->naddrs; - h(data, &d->addrs[n].sockaddr, d->addrs[n].socklen); - - return; - -failed: - - h(data, NULL, 0); -} - -socklen_t -ngx_dynamic_resolver_gethostbyname(ngx_str_t *domain, struct sockaddr *sa) -{ - ngx_dynamic_resolver_conf_t *drcf; - ngx_dynamic_resolver_domain_t *d; - ngx_uint_t idx, n; - socklen_t len; - u_char temp[MAX_DOMAIN_LEN]; - - if (domain == NULL) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, - "dynamic resolver sync, domain is NULL"); - return 0; - } - - len = ngx_sock_pton(sa, domain->data, domain->len); - /* addr is ipv4/ipv6/unix address */ - if (len) { - ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, - "dynamic resolver sync, domain is ipv4/ipv6/unix address"); - - return len; - } - - drcf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_dynamic_resolver_module); - if (drcf->refresh_interval == 0) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "dynamic resolver sync, " - "dynamic resolver closed when start resolver"); - return 0; - } - - if (domain->len > MAX_DOMAIN_LEN) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "dynamic resolver sync, " - "domain length(%z) is too long", domain->len); - return 0; - } - - ngx_memzero(temp, MAX_DOMAIN_LEN); - idx = ngx_hash_strlow(temp, domain->data, domain->len); - idx %= drcf->domain_buckets; - - d = drcf->resolver_hash[idx]; - while (d) { - if (d->domain.len == domain->len && - ngx_memcmp(d->domain.data, temp, domain->len) == 0) - { - if (d->naddrs == 0) { - ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, - "dynamic resolver sync, domain '%V' is not resolved", - &d->domain); - return 0; - } - - n = ngx_random() % d->naddrs; - ngx_memcpy(sa, &d->addrs[n].sockaddr, d->addrs[n].socklen); - - return d->addrs[n].socklen; - } - - d = d->next; - } - - ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, "dynamic resolver sync, " - "domain '%V' is not in dynamic resolver table", domain); - - return 0; -} - -ngx_chain_t * -ngx_dynamic_resolver_state(ngx_http_request_t *r) -{ - ngx_dynamic_resolver_conf_t *drcf; - ngx_chain_t *cl; - ngx_buf_t *b; - size_t len; - - drcf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_dynamic_resolver_module); - - len = sizeof("##########dynamic resolver state##########\n") - 1 - + sizeof("ngx_dynamic_resolver alloc ctx: \n") - 1 + NGX_OFF_T_LEN - + sizeof("ngx_dynamic_resolver free ctx: \n") - 1 + NGX_OFF_T_LEN - + sizeof("ngx_dynamic_resolver alloc domain: \n") - 1 + NGX_OFF_T_LEN - + sizeof("ngx_dynamic_resolver free domain: \n") - 1 + NGX_OFF_T_LEN; - - cl = ngx_alloc_chain_link(r->pool); - if (cl == NULL) { - return NULL; - } - cl->next = NULL; - - b = ngx_create_temp_buf(r->pool, len); - if (b == NULL) { - return NULL; - } - cl->buf = b; - - b->last = ngx_snprintf(b->last, len, - "##########dynamic resolver state##########\n" - "ngx_dynamic_resolver alloc ctx: %ui\n" - "ngx_dynamic_resolver free ctx: %ui\n" - "ngx_dynamic_resolver alloc domain: %ui\n" - "ngx_dynamic_resolver free domain: %ui\n", - drcf->nalloc_ctx, drcf->nfree_ctx, - drcf->nalloc_domain, drcf->nfree_domain); - - return cl; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_dynamic_resolver.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_dynamic_resolver.h deleted file mode 100644 index 4bce494803..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_dynamic_resolver.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#ifndef _NGX_DYNAMIC_RESOLVER_H_INCLUDED_ -#define _NGX_DYNAMIC_RESOLVER_H_INCLUDED_ - - -#include -#include -#include - - -/* - * paras: - * data : user private data set in ngx_dynamic_resolver_start_resolver - * sa : sock address get - * socklen: sock address len, 0 for get none address - */ -typedef void (* ngx_dynamic_resolver_handler_pt)(void *data, - struct sockaddr *sa, socklen_t socklen); - -/* - * add domain into dynamic resolver - * - * paras: - * domain: domain for DNS query - */ - -void ngx_dynamic_resolver_add_domain(ngx_str_t *domain, ngx_cycle_t *cycle); - -/* - * del domain from dynamic resolver - * - * paras: - * domain: domain for DNS query - */ -void ngx_dynamic_resolver_del_domain(ngx_str_t *domain); - -/* - * get addr from dynamic resolver by domain if exist, - * otherwise, get from resolver configured into event resolver - * and add domain into dynamic resolver - * - * paras: - * domain: domain for DNS query - * h : callback handler - * data : data for callback - */ -void ngx_dynamic_resolver_start_resolver(ngx_str_t *domain, - ngx_dynamic_resolver_handler_pt h, void *data); - -/* - * get addr from dynamic resolver by domain, - * - * return: - * 0 for failed - * socklen for successd - * - * paras: - * domain: domain for query - * sa : sockaddr for domain - */ -socklen_t ngx_dynamic_resolver_gethostbyname(ngx_str_t *domain, - struct sockaddr *sa); - -/* - * paras: - * r: http request to query status of dynamic resolver - */ -ngx_chain_t *ngx_dynamic_resolver_state(ngx_http_request_t *r); - - -#endif diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_event_resolver.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_event_resolver.c deleted file mode 100644 index acd194e217..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_event_resolver.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include "ngx_event_resolver.h" - - -static void *ngx_event_resolver_create_conf(ngx_cycle_t *cycle); -static char *ngx_event_resolver_init_conf(ngx_cycle_t *cycle, void *conf); - -static char *ngx_event_resolver(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); - - -typedef struct ngx_event_resolver_ctx_s ngx_event_resolver_ctx_t; - -struct ngx_event_resolver_ctx_s { - ngx_event_resolver_handler_pt handler; - void *data; - ngx_event_resolver_ctx_t *next; -}; - -typedef struct { - ngx_msec_t resolver_timeout; - ngx_resolver_t *resolver; - ngx_event_resolver_ctx_t *free_ctx; - - ngx_uint_t nalloc; - ngx_uint_t nfree; -} ngx_event_resolver_conf_t; - - -static ngx_str_t event_resolver_name = ngx_string("event_resolver"); - - -static ngx_command_t ngx_event_resolver_commands[] = { - - { ngx_string("resolver"), - NGX_EVENT_CONF|NGX_CONF_1MORE, - ngx_event_resolver, - 0, - 0, - NULL }, - - { ngx_string("resolver_timeout"), - NGX_EVENT_CONF|NGX_CONF_TAKE1, - ngx_conf_set_msec_slot, - 0, - offsetof(ngx_event_resolver_conf_t, resolver_timeout), - NULL }, - - ngx_null_command -}; - - -ngx_event_module_t ngx_event_resolver_module_ctx = { - &event_resolver_name, - ngx_event_resolver_create_conf, /* create configuration */ - ngx_event_resolver_init_conf, /* init configuration */ - - { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } -}; - - -/* this module use ngx_cycle->log */ -ngx_module_t ngx_event_resolver_module = { - NGX_MODULE_V1, - &ngx_event_resolver_module_ctx, /* module context */ - ngx_event_resolver_commands, /* module directives */ - NGX_EVENT_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void * -ngx_event_resolver_create_conf(ngx_cycle_t *cycle) -{ - ngx_event_resolver_conf_t *conf; - - conf = ngx_pcalloc(cycle->pool, sizeof(ngx_event_resolver_conf_t)); - if (conf == NULL) { - return NULL; - } - - conf->resolver_timeout = NGX_CONF_UNSET_MSEC; - - return conf; -} - -static char * -ngx_event_resolver_init_conf(ngx_cycle_t *cycle, void *conf) -{ - ngx_event_resolver_conf_t *ercf = conf; - - ngx_conf_init_msec_value(ercf->resolver_timeout, 60000); - - return NGX_CONF_OK; -} - -static char * -ngx_event_resolver(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_event_resolver_conf_t *ercf = conf; - - ngx_str_t *value; - - if (ercf->resolver) { - return "is duplicate"; - } - - value = cf->args->elts; - - ercf->resolver = ngx_resolver_create(cf, &value[1], cf->args->nelts - 1); - if (ercf->resolver == NULL) { - return NGX_CONF_ERROR; - } - - return NGX_CONF_OK; -} - - -static ngx_event_resolver_ctx_t * -ngx_event_resolver_get_ctx() -{ - ngx_event_resolver_ctx_t *ctx; - ngx_event_resolver_conf_t *ercf; - - ercf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_resolver_module); - - ctx = ercf->free_ctx; - if (ctx == NULL) { - ctx = ngx_pcalloc(ngx_cycle->pool, sizeof(ngx_event_resolver_ctx_t)); - ++ercf->nalloc; - } else { - ercf->free_ctx = ctx->next; - ctx->next = NULL; - --ercf->nfree; - } - - return ctx; -} - -static void -ngx_event_resolver_put_ctx(ngx_event_resolver_ctx_t *ctx) -{ - ngx_event_resolver_conf_t *ercf; - - ercf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_resolver_module); - - ctx->next = ercf->free_ctx; - ercf->free_ctx = ctx; - ++ercf->nfree; -} - -static void -ngx_event_resolver_handler(ngx_resolver_ctx_t *ctx) -{ - ngx_event_resolver_ctx_t *erctx; - - erctx = ctx->data; - - if (ctx->state) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, - "event resolver, domain '%V' could not be resolved (%i: %s)", - &ctx->name, ctx->state, ngx_resolver_strerror(ctx->state)); - erctx->handler(erctx->data, NULL, 0); - - goto failed; - } - - erctx->handler(erctx->data, ctx->addrs, ctx->naddrs); - -failed: - ngx_resolve_name_done(ctx); - ngx_event_resolver_put_ctx(erctx); -} - -void -ngx_event_resolver_start_resolver(ngx_str_t *domain, - ngx_event_resolver_handler_pt h, void *data) -{ - ngx_event_resolver_conf_t *ercf; - ngx_event_resolver_ctx_t *erctx; - ngx_resolver_ctx_t *ctx, temp; - - ercf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_resolver_module); - - ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, "event resolver, " - "start resolv domain '%V'", domain); - - if (ercf->resolver == NULL) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "event resolver, " - "resolver does not configured"); - h(data, NULL, 0); - - return; - } - - temp.name = *domain; - - erctx = ngx_event_resolver_get_ctx(); - if (erctx == NULL) { - return; - } - erctx->handler = h; - erctx->data = data; - - ctx = ngx_resolve_start(ercf->resolver, &temp); - if (ctx == NULL) { - goto failed; - } - - if (ctx == NGX_NO_RESOLVER) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "event resolver, " - "no resolver defined to resolv %V", domain); - goto failed; - } - - ctx->name = *domain; - ctx->handler = ngx_event_resolver_handler; - ctx->data = erctx; - ctx->timeout = ercf->resolver_timeout; - - if (ngx_resolve_name(ctx) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "event resolver, " - "resolv %V failed", domain); - - goto failed; - } - - return; - -failed: - h(data, NULL, 0); - - if (ctx == NULL || ctx == NGX_NO_RESOLVER) { - ngx_resolve_name_done(ctx); - ngx_event_resolver_put_ctx(erctx); - } -} - -ngx_chain_t * -ngx_event_resolver_state(ngx_http_request_t *r) -{ - ngx_event_resolver_conf_t *ercf; - ngx_chain_t *cl; - ngx_buf_t *b; - size_t len; - - ercf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_resolver_module); - - len = sizeof("##########event resolver state##########\n") - 1 - + sizeof("ngx_event_resolver alloc: \n") - 1 + NGX_OFF_T_LEN - + sizeof("ngx_event_resolver free: \n") - 1 + NGX_OFF_T_LEN; - - cl = ngx_alloc_chain_link(r->pool); - if (cl == NULL) { - return NULL; - } - cl->next = NULL; - - b = ngx_create_temp_buf(r->pool, len); - if (b == NULL) { - return NULL; - } - cl->buf = b; - - b->last = ngx_snprintf(b->last, len, - "##########event resolver state##########\n" - "ngx_event_resolver alloc: %ui\nngx_event_resolver free: %ui\n", - ercf->nalloc, ercf->nfree); - - return cl; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_event_resolver.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_event_resolver.h deleted file mode 100644 index 89668e4de2..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_event_resolver.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - - -#ifndef _NGX_EVENT_RESOLVER_H_INCLUDED_ -#define _NGX_EVENT_RESOLVER_H_INCLUDED_ - - -#include -#include -#include -#include - - -/* - * paras: - * data : user private data set in ngx_event_resolver_start_resolver - * addrs : addrs resolv by DNS - * naddrs: number of addrs resolv by DNS - */ -typedef void (* ngx_event_resolver_handler_pt)(void *data, - ngx_resolver_addr_t *addrs, ngx_uint_t naddrs); - - -/* - * paras: - * domain: domain for resolving - * h : callback handler - * data : data for callback - */ -void ngx_event_resolver_start_resolver(ngx_str_t *domain, - ngx_event_resolver_handler_pt h, void *data); - -/* - * paras: - * r: http request to query status of event resolver - */ -ngx_chain_t *ngx_event_resolver_state(ngx_http_request_t *r); - - -#endif diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_event_timer_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_event_timer_module.c deleted file mode 100644 index c63787ee1e..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_event_timer_module.c +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include "ngx_event_timer_module.h" - - -static ngx_int_t ngx_event_timer_process_init(ngx_cycle_t *cycle); - -static void *ngx_event_timer_create_conf(ngx_cycle_t *cycle); -static char *ngx_event_timer_init_conf(ngx_cycle_t *cycle, void *conf); - - -typedef struct { - ngx_uint_t timerid; - - ngx_event_t event; - - ngx_timer_handler_pt handler; - void *data; -} ngx_event_timer_ctx_t; - -typedef struct { - ngx_uint_t timer_n; - - ngx_event_timer_ctx_t *timer_ctx; /* array to store timers */ - - ngx_event_timer_ctx_t *free_timers; /* timer unused */ - ngx_uint_t free_timer_n; -} ngx_event_timer_conf_t; - - -static ngx_str_t event_timer_name = ngx_string("event_timer"); - - -static ngx_command_t ngx_event_timer_commands[] = { - - { ngx_string("worker_timers"), - NGX_EVENT_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - 0, - offsetof(ngx_event_timer_conf_t, timer_n), - NULL }, - - ngx_null_command -}; - - -ngx_event_module_t ngx_event_timer_module_ctx = { - &event_timer_name, - ngx_event_timer_create_conf, /* create configuration */ - ngx_event_timer_init_conf, /* init configuration */ - - { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } -}; - - -/* this module use ngx_cycle->log */ -ngx_module_t ngx_event_timer_module = { - NGX_MODULE_V1, - &ngx_event_timer_module_ctx, /* module context */ - ngx_event_timer_commands, /* module directives */ - NGX_EVENT_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - ngx_event_timer_process_init, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void * -ngx_event_timer_create_conf(ngx_cycle_t *cycle) -{ - ngx_event_timer_conf_t *conf; - - conf = ngx_pcalloc(cycle->pool, sizeof(ngx_event_timer_conf_t)); - if (conf == NULL) { - return NULL; - } - - conf->timer_n = NGX_CONF_UNSET_UINT; - - return conf; -} - -static char * -ngx_event_timer_init_conf(ngx_cycle_t *cycle, void *conf) -{ - ngx_event_timer_conf_t *etcf = conf; - - ngx_conf_init_uint_value(etcf->timer_n, 1024); - - return NGX_CONF_OK; -} - -static ngx_int_t -ngx_event_timer_process_init(ngx_cycle_t *cycle) -{ - ngx_event_timer_conf_t *etcf; - ngx_event_timer_ctx_t *t, *next; - ngx_uint_t i; - - etcf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_timer_module); - - if (etcf->timer_n == 0) { - return NGX_OK; - } - - etcf->timer_ctx = - ngx_alloc(sizeof(ngx_event_timer_ctx_t) * etcf->timer_n, cycle->log); - if (etcf->timer_ctx == NULL) { - return NGX_ERROR; - } - - t = etcf->timer_ctx; - - i = etcf->timer_n; - next = NULL; - - do { - --i; - - t[i].timerid = i; - t[i].event.timer_set = 0; - t[i].event.log = NULL; - t[i].handler = NULL; - t[i].data = next; - - next = &t[i]; - } while (i); - - etcf->free_timers = next; - etcf->free_timer_n = etcf->timer_n; - - return NGX_OK; -} - -static ngx_event_timer_ctx_t * -ngx_event_timer_get_timer() -{ - ngx_event_timer_conf_t *etcf; - ngx_event_timer_ctx_t *free; - - etcf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_timer_module); - - free = etcf->free_timers; - if (etcf->free_timer_n == 0) { - ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, - "nginx event timer module, no free timer"); - return NULL; - } - - etcf->free_timers = free->data; - --etcf->free_timer_n; - - return free; -} - -static void -ngx_event_timer_free_timer(ngx_event_timer_ctx_t *ctx) -{ - ngx_event_timer_conf_t *etcf; - - etcf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_timer_module); - - ctx->data = etcf->free_timers; - etcf->free_timers = ctx; - ++etcf->free_timer_n; -} - -static void -ngx_event_timer_event_handler(ngx_event_t *e) -{ - ngx_event_timer_ctx_t *ctx; - - ctx = e->data; - - if (ctx->handler) { - ctx->handler(ctx->data); - } - - ngx_event_timer_free_timer(ctx); -} - -ngx_int_t -ngx_event_timer_add_timer(ngx_msec_t tv, ngx_timer_handler_pt h, void *data) -{ - ngx_event_timer_ctx_t *ctx; - - if (h == NULL) { - return NGX_ERROR; - } - - ctx = ngx_event_timer_get_timer(); - if (ctx == NULL) { - return NGX_ERROR; - } - - ctx->event.handler = ngx_event_timer_event_handler; - ctx->event.data = ctx; - - ctx->handler = h; - ctx->data = data; - - if (ctx->event.log == NULL) { - ctx->event.log = ngx_cycle->log; - } - - ngx_event_add_timer(&ctx->event, tv); - - return ctx->timerid; -} - -void -ngx_event_timer_del_timer(ngx_uint_t timerid) -{ - ngx_event_timer_ctx_t *ctx; - ngx_event_timer_conf_t *etcf; - - etcf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_timer_module); - - ctx = &etcf->timer_ctx[timerid]; - - if (!ctx->event.timer_set) { - ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0, - "timer has already deleted"); - return; - } - - ngx_event_del_timer(&ctx->event); - ngx_event_timer_free_timer(ctx); -} - -ngx_chain_t * -ngx_event_timer_state(ngx_http_request_t *r) -{ - ngx_event_timer_conf_t *etcf; - ngx_chain_t *cl; - ngx_buf_t *b; - size_t len; - - etcf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_timer_module); - - len = sizeof("##########event timer state##########\n") - 1 - + sizeof("ngx_event_timer alloc: \n") - 1 + NGX_OFF_T_LEN - + sizeof("ngx_event_timer free: \n") - 1 + NGX_OFF_T_LEN; - - cl = ngx_alloc_chain_link(r->pool); - if (cl == NULL) { - return NULL; - } - cl->next = NULL; - - b = ngx_create_temp_buf(r->pool, len); - if (b == NULL) { - return NULL; - } - cl->buf = b; - - b->last = ngx_snprintf(b->last, len, - "##########event timer state##########\n" - "ngx_event_timer alloc: %ui\nngx_event_timer free: %ui\n", - etcf->timer_n, etcf->free_timer_n); - - return cl; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_event_timer_module.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_event_timer_module.h deleted file mode 100644 index 9b02f71536..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_event_timer_module.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#ifndef _NGX_EVENT_TIMER_MODULE_H_INCLUDED_ -#define _NGX_EVENT_TIMER_MODULE_H_INCLUDED_ - - -#include -#include -#include -#include - - -typedef void (* ngx_timer_handler_pt)(void *data); - -/* - * return value: - * return timerid for successd, NGX_ERROR for failed - * paras: - * tv : timer interval to trigger handler - * h : timer handler - * data : data of h para - */ -ngx_int_t ngx_event_timer_add_timer(ngx_msec_t tv, - ngx_timer_handler_pt h, void *data); - -/* - * paras: - * timerid: value return in ngx_timer_add_timer - */ -void ngx_event_timer_del_timer(ngx_uint_t timerid); - -/* - * paras: - * r: http request to query status of event timer - */ -ngx_chain_t *ngx_event_timer_state(ngx_http_request_t *r); - - -#endif diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_http_dynamic.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_http_dynamic.c deleted file mode 100644 index 440e7444cb..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_http_dynamic.c +++ /dev/null @@ -1,1677 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include -#include -#include -#include "ngx_dynamic_conf.h" -#include "ngx_http_dynamic.h" - - -static void *ngx_http_dynamic_create_conf(ngx_conf_t *cf); -static void *ngx_http_dynamic_core_create_main_conf(ngx_conf_t *cf); -static char *ngx_http_dynamic_core_init_main_conf(ngx_conf_t *cf, void *conf); -static void *ngx_http_dynamic_core_create_srv_conf(ngx_conf_t *cf); -static char *ngx_http_dynamic_core_init_srv_conf(ngx_conf_t *cf, void *conf); -static void *ngx_http_dynamic_core_create_loc_conf(ngx_conf_t *cf); -static char *ngx_http_dynamic_core_init_loc_conf(ngx_conf_t *cf, void *conf); - -static char *ngx_http_dynamic_block(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); -static char *ngx_http_dynamic_core_server(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); -static char *ngx_http_dynamic_core_server_name(ngx_conf_t *cf, - ngx_command_t *cmd, void *conf); -static char *ngx_http_dynamic_core_location(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); - - -typedef struct ngx_http_dynamic_location_tree_node_s - ngx_http_dynamic_location_tree_node_t; -typedef struct ngx_http_dynamic_core_loc_conf_s - ngx_http_dynamic_core_loc_conf_t; - -struct ngx_http_dynamic_core_loc_conf_s { - ngx_str_t name; /* location name */ - -#if (NGX_PCRE) - ngx_dynamic_regex_t *regex; -#endif - - unsigned exact_match:1; - unsigned noregex:1; - - ngx_queue_t *locations; - - ngx_http_dynamic_location_tree_node_t *static_locations; -#if (NGX_PCRE) - ngx_http_dynamic_core_loc_conf_t **regex_locations; -#endif - - void **loc_conf; -}; - -typedef struct { - ngx_queue_t queue; - ngx_http_dynamic_core_loc_conf_t *exact; - ngx_http_dynamic_core_loc_conf_t *inclusive; - ngx_str_t *name; - u_char *file_name; - ngx_uint_t line; - ngx_queue_t list; -} ngx_http_dynamic_location_queue_t; - -struct ngx_http_dynamic_location_tree_node_s { - ngx_http_dynamic_location_tree_node_t *left; - ngx_http_dynamic_location_tree_node_t *right; - ngx_http_dynamic_location_tree_node_t *tree; - - ngx_http_dynamic_core_loc_conf_t *exact; - ngx_http_dynamic_core_loc_conf_t *inclusive; - - u_char len; - u_char name[1]; -}; - - -typedef struct { - /* array of the ngx_http_dynamic_server_name_t, "server_name" directive */ - ngx_array_t server_names; - - ngx_http_dynamic_core_loc_conf_t *hdclcf; - - void **srv_conf; -} ngx_http_dynamic_core_srv_conf_t; - -typedef struct { -#if (NGX_PCRE) - ngx_dynamic_regex_t *regex; -#endif - ngx_http_dynamic_core_srv_conf_t *server; /* virtual name server conf */ - ngx_str_t name; -} ngx_http_dynamic_server_name_t; - - -typedef struct { - /* ngx_http_dynamic_srv_conf_t */ - ngx_array_t servers; - - ngx_uint_t server_names_hash_max_size; - ngx_uint_t server_names_hash_bucket_size; - - /* the default server configuration for this address:port */ - ngx_http_dynamic_core_srv_conf_t *default_server; - - ngx_hash_combined_t names; - -#if (NGX_PCRE) - ngx_uint_t nregex; - ngx_http_dynamic_server_name_t *regex; -#endif -} ngx_http_dynamic_core_main_conf_t; - - -typedef struct { - void **main_conf; -} ngx_http_dynamic_conf_t; - - -static ngx_core_module_t ngx_http_dynamic_module_ctx = { - ngx_string("http_dynamic"), - NULL, - NULL -}; - -static ngx_command_t ngx_http_dynamic_dcommands[] = { - - { ngx_string("http"), - NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, - ngx_http_dynamic_block, - 0, - 0, - NULL }, - - ngx_null_command -}; - -static ngx_dynamic_core_module_t ngx_http_dynamic_module_dctx = { - ngx_string("http_dynamic"), - ngx_http_dynamic_create_conf, - NULL -}; - -ngx_module_t ngx_http_dynamic_module = { - NGX_MODULE_V1, - &ngx_http_dynamic_module_ctx, /* module context */ - NULL, /* module directives */ - NGX_CORE_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - (uintptr_t) &ngx_http_dynamic_module_dctx, /* module dynamic context */ - (uintptr_t) ngx_http_dynamic_dcommands, /* module dynamic directives */ - NGX_MODULE_V1_DYNAMIC_PADDING -}; - - -static ngx_http_module_t ngx_http_dynamic_core_module_ctx = { - NULL, /* preconfiguration */ - NULL, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - NULL, /* create location configuration */ - NULL /* merge location configuration */ -}; - - -static ngx_command_t ngx_http_dynamic_core_dcommands[] = { - - { ngx_string("server_names_hash_max_size"), - NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - 0, - offsetof(ngx_http_dynamic_core_main_conf_t, server_names_hash_max_size), - NULL }, - - { ngx_string("server_names_hash_bucket_size"), - NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - 0, - offsetof(ngx_http_dynamic_core_main_conf_t, - server_names_hash_bucket_size), - NULL }, - - { ngx_string("server"), - NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, - ngx_http_dynamic_core_server, - 0, - 0, - NULL }, - - { ngx_string("server_name"), - NGX_HTTP_SRV_CONF|NGX_CONF_1MORE, - ngx_http_dynamic_core_server_name, - 0, - 0, - NULL }, - - { ngx_string("location"), - NGX_HTTP_SRV_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE12, - ngx_http_dynamic_core_location, - 0, - 0, - NULL }, - - ngx_null_command -}; - - -static ngx_http_dynamic_module_t ngx_http_dynamic_core_module_dctx = { - ngx_http_dynamic_core_create_main_conf, /* create main configuration */ - ngx_http_dynamic_core_init_main_conf, /* init main configuration */ - - ngx_http_dynamic_core_create_srv_conf, /* create server configuration */ - ngx_http_dynamic_core_init_srv_conf, /* init server configuration */ - - ngx_http_dynamic_core_create_loc_conf, /* create location configuration */ - ngx_http_dynamic_core_init_loc_conf /* init location configuration */ -}; - - -ngx_module_t ngx_http_dynamic_core_module = { - NGX_MODULE_V1, - &ngx_http_dynamic_core_module_ctx, /* module context */ - NULL, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - (uintptr_t) &ngx_http_dynamic_core_module_dctx, /* module dynamic context */ - (uintptr_t) ngx_http_dynamic_core_dcommands, /* module dynamic directives */ - NGX_MODULE_V1_DYNAMIC_PADDING -}; - - -static void * -ngx_http_dynamic_create_conf(ngx_conf_t *cf) -{ - ngx_http_dynamic_conf_t *hdccf; - - hdccf = ngx_pcalloc(cf->pool, sizeof(ngx_http_dynamic_conf_t)); - if (hdccf == NULL) { - return NULL; - } - - return hdccf; -} - -static void * -ngx_http_dynamic_core_create_main_conf(ngx_conf_t *cf) -{ - ngx_http_dynamic_core_main_conf_t *hdcmcf; - - hdcmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_dynamic_core_main_conf_t)); - if (hdcmcf == NULL) { - return NULL; - } - - if (ngx_array_init(&hdcmcf->servers, cf->pool, 4, - sizeof(ngx_http_dynamic_core_srv_conf_t *)) != NGX_OK) - { - return NULL; - } - - hdcmcf->server_names_hash_max_size = NGX_CONF_UNSET_UINT; - hdcmcf->server_names_hash_bucket_size = NGX_CONF_UNSET_UINT; - - return hdcmcf; -} - -static char * -ngx_http_dynamic_core_init_main_conf(ngx_conf_t *cf, void *conf) -{ - ngx_http_dynamic_core_main_conf_t *hdcmcf; - - hdcmcf = conf; - - ngx_conf_init_uint_value(hdcmcf->server_names_hash_max_size, 512); - ngx_conf_init_uint_value(hdcmcf->server_names_hash_bucket_size, - ngx_cacheline_size); - - return NGX_CONF_OK; -} - -static void * -ngx_http_dynamic_core_create_srv_conf(ngx_conf_t *cf) -{ - ngx_http_dynamic_core_srv_conf_t *hdcscf; - - hdcscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_dynamic_core_srv_conf_t)); - if (hdcscf == NULL) { - return NULL; - } - - if (ngx_array_init(&hdcscf->server_names, cf->pool, 4, - sizeof(ngx_http_dynamic_server_name_t)) != NGX_OK) - { - return NULL; - } - - return hdcscf; -} - -static char * -ngx_http_dynamic_core_init_srv_conf(ngx_conf_t *cf, void *conf) -{ - return NGX_CONF_OK; -} - -static void * -ngx_http_dynamic_core_create_loc_conf(ngx_conf_t *cf) -{ - ngx_http_dynamic_core_loc_conf_t *hdclcf; - - hdclcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_dynamic_core_loc_conf_t)); - if (hdclcf == NULL) { - return NULL; - } - - return hdclcf; -} - -static char * -ngx_http_dynamic_core_init_loc_conf(ngx_conf_t *cf, void *conf) -{ - return NGX_CONF_OK; -} - -static ngx_int_t -ngx_http_dynamic_core_regex_location(ngx_conf_t *cf, - ngx_http_dynamic_core_loc_conf_t *hdclcf, - ngx_str_t *regex, ngx_uint_t caseless) -{ -#if (NGX_PCRE) - ngx_regex_compile_t rc; - u_char errstr[NGX_MAX_CONF_ERRSTR]; - - ngx_memzero(&rc, sizeof(ngx_regex_compile_t)); - - rc.pattern = *regex; - rc.err.len = NGX_MAX_CONF_ERRSTR; - rc.err.data = errstr; - -#if (NGX_HAVE_CASELESS_FILESYSTEM) - rc.options = NGX_REGEX_CASELESS; -#else - rc.options = caseless ? NGX_REGEX_CASELESS : 0; -#endif - - hdclcf->regex = ngx_dynamic_regex_compile(cf, &rc); - if (hdclcf->regex == NULL) { - return NGX_ERROR; - } - - hdclcf->name = *regex; - - return NGX_OK; - -#else - - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "using regex \"%V\" requires PCRE library", - regex); - return NGX_ERROR; - -#endif -} - -static ngx_int_t -ngx_http_dynamic_core_predeal_location(ngx_conf_t *cf, - ngx_http_dynamic_core_loc_conf_t *hdclcf) -{ - ngx_str_t *value, *name; - size_t len; - u_char *mod; - - value = cf->args->elts; - - if (cf->args->nelts == 3) { - - len = value[1].len; - mod = value[1].data; - name = &value[2]; - - if (len == 1 && mod[0] == '=') { - - hdclcf->name = *name; - hdclcf->exact_match = 1; - - } else if (len == 2 && mod[0] == '^' && mod[1] == '~') { - - hdclcf->name = *name; - hdclcf->noregex = 1; - - } else if (len == 1 && mod[0] == '~') { - - if (ngx_http_dynamic_core_regex_location(cf, hdclcf, name, 0) - != NGX_OK) - { - return NGX_ERROR; - } - - } else if (len == 2 && mod[0] == '~' && mod[1] == '*') { - - if (ngx_http_dynamic_core_regex_location(cf, hdclcf, name, 1) - != NGX_OK) - { - return NGX_ERROR; - } - - } else { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid location modifier \"%V\"", &value[1]); - return NGX_ERROR; - } - } else { /* cf->args->nelts == 2 */ - - name = &value[1]; - - if (name->data[0] == '=') { - - hdclcf->name.len = name->len - 1; - hdclcf->name.data = name->data + 1; - hdclcf->exact_match = 1; - - } else if (name->data[0] == '^' && name->data[1] == '~') { - - hdclcf->name.len = name->len - 2; - hdclcf->name.data = name->data + 2; - hdclcf->noregex = 1; - - } else if (name->data[0] == '~') { - - name->len--; - name->data++; - - if (name->data[0] == '*') { - - name->len--; - name->data++; - - if (ngx_http_dynamic_core_regex_location(cf, hdclcf, name, 1) - != NGX_OK) - { - return NGX_ERROR; - } - - } else { - if (ngx_http_dynamic_core_regex_location(cf, hdclcf, name, 0) - != NGX_OK) - { - return NGX_ERROR; - } - } - - } else { - - hdclcf->name = *name; - } - } - - return NGX_OK; -} - -static ngx_int_t -ngx_http_dynamic_core_cmp_locations(const ngx_queue_t *one, - const ngx_queue_t *two) -{ - ngx_int_t rc; - ngx_http_dynamic_core_loc_conf_t *first, *second; - ngx_http_dynamic_location_queue_t *lq1, *lq2; - - lq1 = (ngx_http_dynamic_location_queue_t *) one; - lq2 = (ngx_http_dynamic_location_queue_t *) two; - - first = lq1->exact ? lq1->exact : lq1->inclusive; - second = lq2->exact ? lq2->exact : lq2->inclusive; - -#if (NGX_PCRE) - if (first->regex && !second->regex) { - /* shift the regex matches to the end */ - return 1; - } - - if (!first->regex && second->regex) { - /* shift the regex matches to the end */ - return -1; - } - - if (first->regex || second->regex) { - /* do not sort the regex matches */ - return 0; - } -#endif - - rc = ngx_filename_cmp(first->name.data, second->name.data, - ngx_min(first->name.len, second->name.len) + 1); - - if (rc == 0 && !first->exact_match && second->exact_match) { - /* an exact match must be before the same inclusive one */ - return 1; - } - - return rc; -} - -static ngx_int_t -ngx_http_dynamic_core_join_exact_locations(ngx_conf_t *cf, - ngx_queue_t *locations) -{ - ngx_queue_t *q, *x; - ngx_http_dynamic_location_queue_t *lq, *lx; - - q = ngx_queue_head(locations); - - while (q != ngx_queue_last(locations)) { - - x = ngx_queue_next(q); - - lq = (ngx_http_dynamic_location_queue_t *) q; - lx = (ngx_http_dynamic_location_queue_t *) x; - - if (lq->name->len == lx->name->len - && ngx_filename_cmp(lq->name->data, lx->name->data, lx->name->len) - == 0) - { - if ((lq->exact && lx->exact) || (lq->inclusive && lx->inclusive)) { - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "duplicate location \"%V\" in %s:%ui", - lx->name, lx->file_name, lx->line); - - return NGX_ERROR; - } - - lq->inclusive = lx->inclusive; - - ngx_queue_remove(x); - - continue; - } - - q = ngx_queue_next(q); - } - - return NGX_OK; -} - -static void -ngx_http_dynamic_core_create_locations_list(ngx_queue_t *locations, - ngx_queue_t *q) -{ - u_char *name; - size_t len; - ngx_queue_t *x, tail; - ngx_http_dynamic_location_queue_t *lq, *lx; - - if (q == ngx_queue_last(locations)) { - return; - } - - lq = (ngx_http_dynamic_location_queue_t *) q; - - if (lq->inclusive == NULL) { - ngx_http_dynamic_core_create_locations_list(locations, - ngx_queue_next(q)); - return; - } - - len = lq->name->len; - name = lq->name->data; - - for (x = ngx_queue_next(q); - x != ngx_queue_sentinel(locations); - x = ngx_queue_next(x)) - { - lx = (ngx_http_dynamic_location_queue_t *) x; - - if (len > lx->name->len - || ngx_filename_cmp(name, lx->name->data, len) != 0) - { - break; - } - } - - q = ngx_queue_next(q); - - if (q == x) { - ngx_http_dynamic_core_create_locations_list(locations, x); - return; - } - - ngx_queue_split(locations, q, &tail); - ngx_queue_add(&lq->list, &tail); - - if (x == ngx_queue_sentinel(locations)) { - ngx_http_dynamic_core_create_locations_list(&lq->list, - ngx_queue_head(&lq->list)); - return; - } - - ngx_queue_split(&lq->list, x, &tail); - ngx_queue_add(locations, &tail); - - ngx_http_dynamic_core_create_locations_list(&lq->list, - ngx_queue_head(&lq->list)); - - ngx_http_dynamic_core_create_locations_list(locations, x); -} - -/* - * to keep cache locality for left leaf nodes, allocate nodes in following - * order: node, left subtree, right subtree, inclusive subtree - */ - -static ngx_http_dynamic_location_tree_node_t * -ngx_http_dynamic_core_create_locations_tree(ngx_conf_t *cf, - ngx_queue_t *locations, size_t prefix) -{ - size_t len; - ngx_queue_t *q, tail; - ngx_http_dynamic_location_queue_t *lq; - ngx_http_dynamic_location_tree_node_t *node; - - q = ngx_queue_middle(locations); - - lq = (ngx_http_dynamic_location_queue_t *) q; - len = lq->name->len - prefix; - - node = ngx_palloc(cf->pool, - offsetof(ngx_http_dynamic_location_tree_node_t, name) + len); - if (node == NULL) { - return NULL; - } - - node->left = NULL; - node->right = NULL; - node->tree = NULL; - node->exact = lq->exact; - node->inclusive = lq->inclusive; - - node->len = (u_char) len; - ngx_memcpy(node->name, &lq->name->data[prefix], len); - - ngx_queue_split(locations, q, &tail); - - if (ngx_queue_empty(locations)) { - /* - * ngx_queue_split() insures that if left part is empty, - * then right one is empty too - */ - goto inclusive; - } - - node->left = ngx_http_dynamic_core_create_locations_tree(cf, locations, - prefix); - if (node->left == NULL) { - return NULL; - } - - ngx_queue_remove(q); - - if (ngx_queue_empty(&tail)) { - goto inclusive; - } - - node->right = ngx_http_dynamic_core_create_locations_tree(cf, &tail, - prefix); - if (node->right == NULL) { - return NULL; - } - -inclusive: - - if (ngx_queue_empty(&lq->list)) { - return node; - } - - node->tree = ngx_http_dynamic_core_create_locations_tree(cf, &lq->list, - prefix + len); - if (node->tree == NULL) { - return NULL; - } - - return node; -} - -static ngx_int_t -ngx_http_dynamic_core_init_locations(ngx_conf_t *cf, - ngx_http_dynamic_core_loc_conf_t *phdclcf) -{ - ngx_queue_t *q, *locations, tail; - ngx_http_dynamic_core_loc_conf_t *hdclcf; - ngx_http_dynamic_location_queue_t *lq; - ngx_http_dynamic_core_loc_conf_t **hdclcfp; -#if (NGX_PCRE) - ngx_uint_t r; - ngx_queue_t *regex; -#endif - - locations = phdclcf->locations; - - if (locations == NULL) { - return NGX_OK; - } - - ngx_queue_sort(locations, ngx_http_dynamic_core_cmp_locations); - -#if (NGX_PCRE) - regex = NULL; - r = 0; -#endif - - for (q = ngx_queue_head(locations); - q != ngx_queue_sentinel(locations); - q = ngx_queue_next(q)) - { - lq = (ngx_http_dynamic_location_queue_t *) q; - - hdclcf = lq->exact ? lq->exact : lq->inclusive; - -#if (NGX_PCRE) - - if (hdclcf->regex) { - r++; - - if (regex == NULL) { - regex = q; - } - - continue; - } - -#endif - } - - if (q != ngx_queue_sentinel(locations)) { - ngx_queue_split(locations, q, &tail); - } - -#if (NGX_PCRE) - - if (regex) { - - hdclcfp = ngx_palloc(cf->pool, - (r + 1) * sizeof(ngx_http_dynamic_core_loc_conf_t *)); - if (hdclcfp == NULL) { - return NGX_ERROR; - } - - phdclcf->regex_locations = hdclcfp; - - for (q = regex; - q != ngx_queue_sentinel(locations); - q = ngx_queue_next(q)) - { - lq = (ngx_http_dynamic_location_queue_t *) q; - - *(hdclcfp++) = lq->exact; - } - - *hdclcfp = NULL; - - ngx_queue_split(locations, regex, &tail); - } - -#endif - - return NGX_OK; -} - -static ngx_int_t -ngx_http_dynamic_core_init_static_location_trees(ngx_conf_t *cf, - ngx_http_dynamic_core_loc_conf_t *phdclcf) -{ - ngx_queue_t *locations; - - locations = phdclcf->locations; - - if (locations == NULL) { - return NGX_OK; - } - - if (ngx_queue_empty(locations)) { - return NGX_OK; - } - - if (ngx_http_dynamic_core_join_exact_locations(cf, locations) != NGX_OK) { - return NGX_ERROR; - } - - ngx_http_dynamic_core_create_locations_list(locations, - ngx_queue_head(locations)); - - phdclcf->static_locations = - ngx_http_dynamic_core_create_locations_tree(cf, locations, 0); - if (phdclcf->static_locations == NULL) { - return NGX_ERROR; - } - - return NGX_OK; -} - -static ngx_int_t -ngx_http_dynamic_core_add_location(ngx_conf_t *cf, ngx_queue_t **locations, - ngx_http_dynamic_core_loc_conf_t *hdclcf) -{ - ngx_http_dynamic_location_queue_t *lq; - - if (ngx_http_dynamic_core_predeal_location(cf, hdclcf) != NGX_OK) { - return NGX_ERROR; - } - - if (*locations == NULL) { - *locations = ngx_pcalloc(cf->temp_pool, - sizeof(ngx_http_location_queue_t)); - if (*locations == NULL) { - return NGX_ERROR; - } - - ngx_queue_init(*locations); - } - - lq = ngx_pcalloc(cf->temp_pool, sizeof(ngx_http_location_queue_t)); - if (lq == NULL) { - return NGX_ERROR; - } - - if (hdclcf->exact_match -#if (NGX_PCRE) - || hdclcf->regex -#endif - ) - { - lq->exact = hdclcf; - lq->inclusive = NULL; - } else { - lq->exact = NULL; - lq->inclusive = hdclcf; - } - - lq->name = &hdclcf->name; - lq->file_name = cf->conf_file->file.name.data; - lq->line = cf->conf_file->line; - - ngx_queue_init(&lq->list); - - ngx_queue_insert_tail(*locations, &lq->queue); - - return NGX_OK; -} - -/* - * NGX_OK - exact or regex match - * NGX_AGAIN - inclusive match - * NGX_DECLINED - no match - */ - -static ngx_int_t -ngx_http_dynamic_core_find_static_location(ngx_http_request_t *r, - ngx_http_dynamic_core_loc_conf_t *phdclcf, - ngx_http_dynamic_core_loc_conf_t **hdclcf) -{ - ngx_http_dynamic_location_tree_node_t *node; - u_char *uri; - size_t len, n; - ngx_int_t rc, rv; - - len = r->uri.len; - uri = r->uri.data; - - rv = NGX_DECLINED; - - node = phdclcf->static_locations; - - for ( ;; ) { - - if (node == NULL) { - return rv; - } - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "test location: \"%*s\"", - (size_t) node->len, node->name); - - n = (len <= (size_t) node->len) ? len : node->len; - - rc = ngx_filename_cmp(uri, node->name, n); - - if (rc != 0) { - node = (rc < 0) ? node->left : node->right; - - continue; - } - - if (len > (size_t) node->len) { - - if (node->inclusive) { - - *hdclcf = node->inclusive-> - loc_conf[ngx_http_dynamic_core_module.ctx_index]; - rv = NGX_AGAIN; - - node = node->tree; - uri += n; - len -= n; - - continue; - } - - /* exact only */ - - node = node->right; - - continue; - } - - if (len == (size_t) node->len) { - - if (node->exact) { - *hdclcf = node->exact-> - loc_conf[ngx_http_dynamic_core_module.ctx_index]; - return NGX_OK; - - } else { - *hdclcf = node->inclusive-> - loc_conf[ngx_http_dynamic_core_module.ctx_index]; - return NGX_AGAIN; - } - } - - /* len < node->len */ - - node = node->left; - } -} - -/* - * NGX_OK - exact or regex match - * NGX_AGAIN - inclusive match - * NGX_ERROR - regex error - * NGX_DECLINED - no match - */ - -static ngx_int_t -ngx_http_dynamic_core_find_location(ngx_http_request_t *r, - ngx_http_dynamic_core_srv_conf_t *hdcscf, - ngx_http_dynamic_core_loc_conf_t **hdclcf) -{ - ngx_int_t rc; - ngx_http_dynamic_core_loc_conf_t *phdclcf; -#if (NGX_PCRE) - ngx_int_t n; - ngx_uint_t noregex; - ngx_http_dynamic_core_loc_conf_t **hdclcfp; - - noregex = 0; -#endif - - phdclcf = hdcscf->hdclcf; - - rc = ngx_http_dynamic_core_find_static_location(r, phdclcf, hdclcf); - - if (rc == NGX_AGAIN) { - -#if (NGX_PCRE) - noregex = (*hdclcf)->noregex; -#endif - - } - - if (rc == NGX_OK || rc == NGX_DONE) { - return rc; - } - - /* rc == NGX_DECLINED or rc == NGX_AGAIN in nested location */ - -#if (NGX_PCRE) - - if (noregex == 0 && phdclcf->regex_locations) { - - for (hdclcfp = phdclcf->regex_locations; *hdclcfp; hdclcfp++) { - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "test location: ~ \"%V\"", &(*hdclcfp)->name); - - n = ngx_regex_exec((*hdclcfp)->regex->regex, &r->uri, NULL, 0); - - if (n == NGX_OK) { - *hdclcf = (*hdclcfp)-> - loc_conf[ngx_http_dynamic_core_module.ctx_index]; - - return NGX_OK; - } - - if (n == NGX_REGEX_NO_MATCHED) { - continue; - } - - return NGX_ERROR; - } - } -#endif - - return rc; -} - -static ngx_int_t -ngx_http_dynamic_core_init_virtual_servers(ngx_conf_t *cf, - ngx_http_dynamic_conf_t *hdcf) -{ - ngx_http_dynamic_core_main_conf_t *hdcmcf; - ngx_http_dynamic_core_srv_conf_t **hdcscfp; - ngx_hash_init_t hash; - ngx_hash_keys_arrays_t ha; - ngx_http_dynamic_server_name_t *name; - ngx_uint_t s, n; - ngx_int_t rc; -#if (NGX_PCRE) - ngx_uint_t regex, i; - - regex = 0; -#endif - - hdcmcf = hdcf->main_conf[ngx_http_dynamic_core_module.ctx_index]; - - ngx_memzero(&ha, sizeof(ngx_hash_keys_arrays_t)); - - ha.temp_pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, cf->log); - if (ha.temp_pool == NULL) { - return NGX_ERROR; - } - - ha.pool = cf->pool; - - if (ngx_hash_keys_array_init(&ha, NGX_HASH_LARGE) != NGX_OK) { - goto failed; - } - - hdcscfp = hdcmcf->servers.elts; - hdcmcf->default_server = hdcscfp[0]; - - for (s = 0; s < hdcmcf->servers.nelts; ++s) { - - name = hdcscfp[s]->server_names.elts; - - for (n = 0; n < hdcscfp[s]->server_names.nelts; ++n) { -#if (NGX_PCRE) - if (name[n].regex) { - ++regex; - continue; - } -#endif - - rc = ngx_hash_add_key(&ha, &name[n].name, name[n].server, - NGX_HASH_WILDCARD_KEY); - if (rc == NGX_ERROR) { - return NGX_ERROR; - } - - if (rc == NGX_DECLINED) { - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "invalid server name or wildcard \"%V\"", - &name[n].name); - return NGX_ERROR; - } - - if (rc == NGX_BUSY) { - ngx_log_error(NGX_LOG_WARN, cf->log, 0, - "conflicting server name \"%V\", ignored", - &name[n].name); - } - } - } - - hash.key = ngx_hash_key_lc; - hash.max_size = hdcmcf->server_names_hash_max_size; - hash.bucket_size = hdcmcf->server_names_hash_bucket_size; - hash.name = "http_dynamic_server_names_hash"; - hash.pool = cf->pool; - - if (ha.keys.nelts) { - hash.hash = &hdcmcf->names.hash; - hash.temp_pool = NULL; - - if (ngx_hash_init(&hash, ha.keys.elts, ha.keys.nelts) != NGX_OK) { - goto failed; - } - } - - if (ha.dns_wc_head.nelts) { - - ngx_qsort(ha.dns_wc_head.elts, (size_t) ha.dns_wc_head.nelts, - sizeof(ngx_hash_key_t), ngx_dynamic_cmp_dns_wildcards); - - hash.hash = NULL; - hash.temp_pool = ha.temp_pool; - - if (ngx_hash_wildcard_init(&hash, ha.dns_wc_head.elts, - ha.dns_wc_head.nelts) != NGX_OK) - { - goto failed; - } - - hdcmcf->names.wc_head = (ngx_hash_wildcard_t *) hash.hash; - } - - if (ha.dns_wc_tail.nelts) { - - ngx_qsort(ha.dns_wc_tail.elts, (size_t) ha.dns_wc_tail.nelts, - sizeof(ngx_hash_key_t), ngx_dynamic_cmp_dns_wildcards); - - hash.hash = NULL; - hash.temp_pool = ha.temp_pool; - - if (ngx_hash_wildcard_init(&hash, ha.dns_wc_tail.elts, - ha.dns_wc_tail.nelts) != NGX_OK) - { - goto failed; - } - - hdcmcf->names.wc_tail = (ngx_hash_wildcard_t *) hash.hash; - - } - - ngx_destroy_pool(ha.temp_pool); - -#if (NGX_PCRE) - if (regex == 0) { - return NGX_OK; - } - - hdcmcf->nregex = regex; - hdcmcf->regex = ngx_pcalloc(cf->pool, - regex * sizeof(ngx_http_dynamic_server_name_t)); - if (hdcmcf->regex == NULL) { - return NGX_ERROR; - } - - i = 0; - - for (s = 0; s < hdcmcf->servers.nelts; ++s) { - - name = hdcscfp[s]->server_names.elts; - - for (n = 0; n < hdcscfp[s]->server_names.nelts; ++n) { - if (name[n].regex) { - hdcmcf->regex[i++] = name[n]; - } - } - } -#endif - - return NGX_OK; - -failed: - ngx_destroy_pool(ha.temp_pool); - - return NGX_ERROR; -} - -static ngx_int_t -ngx_http_dynamic_core_find_virtual_server(ngx_http_request_t *r, - ngx_http_dynamic_core_main_conf_t *hdcmcf, - ngx_http_dynamic_core_srv_conf_t **hdcscfp) -{ - ngx_http_dynamic_core_srv_conf_t *hdcscf; - ngx_str_t *server; - - server = &r->headers_in.server; - - hdcscf = ngx_hash_find_combined(&hdcmcf->names, - ngx_hash_key(server->data, server->len), - server->data, server->len); - - if (hdcscf) { - *hdcscfp = hdcscf; - return NGX_OK; - } - -#if (NGX_PCRE) - - if (server->len && hdcmcf->nregex) { - ngx_int_t n; - ngx_uint_t i; - ngx_http_dynamic_server_name_t *sn; - - sn = hdcmcf->regex; - - for (i = 0; i < hdcmcf->nregex; ++i) { - - n = ngx_regex_exec(sn[i].regex->regex, server, NULL, 0); - - if (n == NGX_REGEX_NO_MATCHED) { - continue; - } - - if (n >= 0) { - *hdcscfp = sn[i].server; - return NGX_OK; - } - - return NGX_ERROR; - } - } -#endif - - return NGX_DECLINED; -} - -static char * -ngx_http_dynamic_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_dynamic_module_t *module; - ngx_http_dynamic_core_loc_conf_t *hdclcf, *phdclcf; - ngx_http_dynamic_core_srv_conf_t *hdcscf; - ngx_conf_t pcf; - void *mconf, **loc_conf; - ngx_uint_t i, ci; - char *rv = NULL; - - hdcscf = conf; - phdclcf = hdcscf->hdclcf; - - /* loc_conf is temp cause hdclcf does not created now */ - loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module); - if (loc_conf == NULL) { - return NGX_CONF_ERROR; - } - - for (i = 0; cf->cycle->modules[i]; ++i) { - if (cf->cycle->modules[i]->type != NGX_HTTP_MODULE) { - continue; - } - - module = (ngx_http_dynamic_module_t *) - cf->cycle->modules[i]->spare_hook0; - - if (module == NULL) { - continue; - } - - if (module->create_loc_conf) { - mconf = module->create_loc_conf(cf); - if (mconf == NULL) { - return NGX_CONF_ERROR; - } - - loc_conf[cf->cycle->modules[i]->ctx_index] = mconf; - } - } - - hdclcf = loc_conf[ngx_http_dynamic_core_module.ctx_index]; - hdclcf->loc_conf = loc_conf; - - if (ngx_http_dynamic_core_add_location(cf, &phdclcf->locations, hdclcf) - != NGX_OK) - { - return NGX_CONF_ERROR; - } - - pcf = *cf; - cf->ctx = hdclcf->loc_conf; - cf->cmd_type = NGX_HTTP_LOC_CONF; - - if (ngx_dynamic_conf_parse(cf, 0) != NGX_OK) { - goto failed; - } - - for (i = 0; cf->cycle->modules[i]; ++i) { - if (cf->cycle->modules[i]->type != NGX_HTTP_MODULE) { - continue; - } - - module = (ngx_http_dynamic_module_t *) - cf->cycle->modules[i]->spare_hook0; - ci = cf->cycle->modules[i]->ctx_index; - if (module == NULL) { - continue; - } - - if (module->init_loc_conf) { - rv = module->init_loc_conf(cf, hdclcf->loc_conf[ci]); - if (rv != NGX_CONF_OK) { - goto failed; - } - } - } - - *cf = pcf; - - return NGX_CONF_OK; - -failed: - *cf = pcf; - - if (rv) { - return rv; - } - - return NGX_CONF_ERROR; -} - -static char * -ngx_http_dynamic_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf) -{ - ngx_http_dynamic_core_srv_conf_t *hdcscf; - u_char ch; - ngx_str_t *value; - ngx_uint_t i; - ngx_http_dynamic_server_name_t *sn; - - hdcscf = conf; - - value = cf->args->elts; - - for (i = 1; i < cf->args->nelts; i++) { - - ch = value[i].data[0]; - - if ((ch == '*' && (value[i].len < 3 || value[i].data[1] != '.')) - || (ch == '.' && value[i].len < 2)) - { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "server name \"%V\" is invalid", &value[i]); - return NGX_CONF_ERROR; - } - - if (ngx_strchr(value[i].data, '/')) { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, - "server name \"%V\" has suspicious symbols", - &value[i]); - } - - sn = ngx_array_push(&hdcscf->server_names); - if (sn == NULL) { - return NGX_CONF_ERROR; - } - -#if (NGX_PCRE) - sn->regex = NULL; -#endif - sn->server = hdcscf; - - if (ngx_strcasecmp(value[i].data, (u_char *) "$hostname") == 0) { - sn->name = cf->cycle->hostname; - - } else { - sn->name = value[i]; - } - - if (value[i].data[0] != '~') { - ngx_strlow(sn->name.data, sn->name.data, sn->name.len); - continue; - } - -#if (NGX_PCRE) - { - u_char *p; - ngx_regex_compile_t rc; - u_char errstr[NGX_MAX_CONF_ERRSTR]; - - if (value[i].len == 1) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "empty regex in server name \"%V\"", &value[i]); - return NGX_CONF_ERROR; - } - - value[i].len--; - value[i].data++; - - ngx_memzero(&rc, sizeof(ngx_regex_compile_t)); - - rc.pattern = value[i]; - rc.err.len = NGX_MAX_CONF_ERRSTR; - rc.err.data = errstr; - - for (p = value[i].data; p < value[i].data + value[i].len; p++) { - if (*p >= 'A' && *p <= 'Z') { - rc.options = NGX_REGEX_CASELESS; - break; - } - } - - sn->regex = ngx_dynamic_regex_compile(cf, &rc); - if (sn->regex == NULL) { - return NGX_CONF_ERROR; - } - - sn->name = value[i]; - } -#else - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "using regex \"%V\" " - "requires PCRE library", &value[i]); - - return NGX_CONF_ERROR; -#endif - } - - return NGX_CONF_OK; -} - -static char * -ngx_http_dynamic_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_dynamic_module_t *module; - ngx_http_dynamic_core_main_conf_t *hdcmcf; - ngx_http_dynamic_core_srv_conf_t *hdcscf, **hdcscfp; - ngx_http_dynamic_core_loc_conf_t *phdclcf; - ngx_conf_t pcf; - void *mconf, **srv_conf; - ngx_uint_t i, ci; - char *rv = NULL; - - hdcmcf = conf; - - /* srv_conf is temp cause hdcscf does not created now */ - srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module); - if (srv_conf == NULL) { - return NGX_CONF_ERROR; - } - - for (i = 0; cf->cycle->modules[i]; ++i) { - if (cf->cycle->modules[i]->type != NGX_HTTP_MODULE) { - continue; - } - - module = (ngx_http_dynamic_module_t *) - cf->cycle->modules[i]->spare_hook0; - if (module == NULL) { - continue; - } - - if (module->create_srv_conf) { - mconf = module->create_srv_conf(cf); - if (mconf == NULL) { - return NGX_CONF_ERROR; - } - - srv_conf[cf->cycle->modules[i]->ctx_index] = mconf; - } - } - - hdcscf = srv_conf[ngx_http_dynamic_core_module.ctx_index]; - hdcscf->srv_conf = srv_conf; - - hdcscf->hdclcf = ngx_pcalloc(cf->pool, - sizeof(ngx_http_dynamic_core_loc_conf_t)); - - /* save hdcscf into hdcmcf */ - hdcscfp = ngx_array_push(&hdcmcf->servers); - if (hdcscfp == NULL) { - return NGX_CONF_ERROR; - } - *hdcscfp = hdcscf; - - pcf = *cf; - cf->ctx = hdcscf->srv_conf; - cf->cmd_type = NGX_HTTP_SRV_CONF; - - if (ngx_dynamic_conf_parse(cf, 0) != NGX_OK) { - goto failed; - } - - for (i = 0; cf->cycle->modules[i]; ++i) { - if (cf->cycle->modules[i]->type != NGX_HTTP_MODULE) { - continue; - } - - module = (ngx_http_dynamic_module_t *) - cf->cycle->modules[i]->spare_hook0; - ci = cf->cycle->modules[i]->ctx_index; - if (module == NULL) { - continue; - } - - if (module->init_srv_conf) { - rv = module->init_srv_conf(cf, hdcscf->srv_conf[ci]); - if (rv != NGX_CONF_OK) { - goto failed; - } - } - } - - *cf = pcf; - - phdclcf = hdcscf->hdclcf; - - if (ngx_http_dynamic_core_init_locations(cf, phdclcf) != NGX_OK) { - return NGX_CONF_ERROR; - } - - if (ngx_http_dynamic_core_init_static_location_trees(cf, phdclcf) != NGX_OK) { - return NGX_CONF_ERROR; - } - - return NGX_CONF_OK; - -failed: - *cf = pcf; - - if (rv) { - return rv; - } - - return NGX_CONF_ERROR; - -} - -static char * -ngx_http_dynamic_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_dynamic_conf_t *hdccf; - ngx_http_dynamic_module_t *module; - ngx_conf_t pcf; - ngx_uint_t i, ci; - char *rv = NULL; - - hdccf = conf; - - /* create main_conf ctx */ - hdccf->main_conf = ngx_pcalloc(cf->pool, sizeof(void *) - * ngx_http_max_module); - if (hdccf->main_conf == NULL) { - return NGX_CONF_ERROR; - } - - /* create http dynamic conf for all http module */ - for (i = 0; cf->cycle->modules[i]; ++i) { - if (cf->cycle->modules[i]->type != NGX_HTTP_MODULE) { - continue; - } - - module = (ngx_http_dynamic_module_t *) - cf->cycle->modules[i]->spare_hook0; - ci = cf->cycle->modules[i]->ctx_index; - - if (module == NULL) { - continue; - } - - if (module->create_main_conf) { - hdccf->main_conf[ci] = module->create_main_conf(cf); - if (hdccf->main_conf[ci] == NULL) { - return NGX_CONF_ERROR; - } - } - } - - /* save conf for recovery */ - pcf = *cf; - - cf->ctx = hdccf->main_conf; - cf->module_type = NGX_HTTP_MODULE; - cf->cmd_type = NGX_HTTP_MAIN_CONF; - - if (ngx_dynamic_conf_parse(cf, 0) != NGX_OK) { - goto failed; - } - - for (i = 0; cf->cycle->modules[i]; ++i) { - if (cf->cycle->modules[i]->type != NGX_HTTP_MODULE) { - continue; - } - - module = (ngx_http_dynamic_module_t *) - cf->cycle->modules[i]->spare_hook0; - ci = cf->cycle->modules[i]->ctx_index; - - if (module == NULL) { - continue; - } - - if (module->init_main_conf) { - rv = module->init_main_conf(cf, hdccf->main_conf[ci]); - if (rv != NGX_CONF_OK) { - goto failed; - } - } - } - - if (ngx_http_dynamic_core_init_virtual_servers(cf, hdccf) != NGX_OK) { - goto failed; - } - - *cf = pcf; - - return NGX_CONF_OK; - -failed: - *cf = pcf; - - if (rv) { - return rv; - } - - return NGX_CONF_ERROR; -} - - -/* interface from here */ - -void * -ngx_http_get_module_main_dconf(ngx_http_request_t *r, ngx_module_t *m) -{ - ngx_http_dynamic_conf_t *hdcf; - - hdcf = ngx_get_dconf(&ngx_http_dynamic_module); - if (hdcf == NULL) { - return NULL; - } - - return hdcf->main_conf[m->ctx_index]; -} - -void * -ngx_http_get_module_srv_dconf(ngx_http_request_t *r, ngx_module_t *m) -{ - ngx_http_dynamic_core_main_conf_t *hdcmcf; - ngx_http_dynamic_core_srv_conf_t *hdcscf; - ngx_int_t rc; - - hdcmcf = ngx_http_get_module_main_dconf(r, &ngx_http_dynamic_core_module); - if (hdcmcf == NULL) { - return NULL; - } - - rc = ngx_http_dynamic_core_find_virtual_server(r, hdcmcf, &hdcscf); - switch (rc) { - case NGX_ERROR: - return NULL; - case NGX_DECLINED: /* virtual server not found */ - return hdcmcf->default_server->srv_conf[m->ctx_index]; - default: - return hdcscf->srv_conf[m->ctx_index]; - } -} - -void * -ngx_http_get_module_loc_dconf(ngx_http_request_t *r, ngx_module_t *m) -{ - ngx_http_dynamic_core_srv_conf_t *hdcscf; - ngx_http_dynamic_core_loc_conf_t *hdclcf; - ngx_int_t rc; - - hdcscf = ngx_http_get_module_srv_dconf(r, &ngx_http_dynamic_core_module); - if (hdcscf == NULL) { - return NULL; - } - - hdclcf = NULL; - rc = ngx_http_dynamic_core_find_location(r, hdcscf, &hdclcf); - if (rc == NGX_ERROR) { - return NULL; - } - - if (hdclcf) { - return hdclcf->loc_conf[m->ctx_index]; - } - - return NULL; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_http_dynamic.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_http_dynamic.h deleted file mode 100644 index 04d2a961d2..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_http_dynamic.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#ifndef _NGX_HTTP_DYNAMIC_H_INCLUDED_ -#define _NGX_HTTP_DYNAMIC_H_INCLUDED_ - - -#include -#include - - -typedef struct { - void *(*create_main_conf)(ngx_conf_t *cf); - char *(*init_main_conf)(ngx_conf_t *cf, void *conf); - - void *(*create_srv_conf)(ngx_conf_t *cf); - char *(*init_srv_conf)(ngx_conf_t *cf, void *conf); - - void *(*create_loc_conf)(ngx_conf_t *cf); - char *(*init_loc_conf)(ngx_conf_t *cf, void *conf); -} ngx_http_dynamic_module_t; - - -void *ngx_http_get_module_main_dconf(ngx_http_request_t *r, ngx_module_t *m); -void *ngx_http_get_module_srv_dconf(ngx_http_request_t *r, ngx_module_t *m); -void *ngx_http_get_module_loc_dconf(ngx_http_request_t *r, ngx_module_t *m); - - -#endif diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_http_trace_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_http_trace_module.c deleted file mode 100644 index 20fa12a4a7..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_http_trace_module.c +++ /dev/null @@ -1,527 +0,0 @@ -#include -#include -#include - - -typedef struct { - ngx_flag_t trace; -} ngx_http_trace_main_conf_t; - - -typedef struct { - u_char traceid[32]; /* X-NTM-Traceid */ - u_char cid[32]; /* X-NTM-Currentid */ - u_char pid[32]; /* X-NTM-Parentid */ - ngx_flag_t debug; /* X-NTM-Debug */ -} ngx_http_trace_ctx_t; - - -static void *ngx_http_trace_create_main_conf(ngx_conf_t *cf); -static char *ngx_http_trace_init_main_conf(ngx_conf_t *cf, void *conf); - -static char *ngx_http_trace(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); - -static ngx_int_t ngx_http_trace_add_variables(ngx_conf_t *cf); -static ngx_int_t ngx_http_trace_init(ngx_conf_t *cf); - -static ngx_int_t ngx_http_trace_traceid_variable(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_http_trace_currentid_variable(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_http_trace_parentid_variable(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_http_trace_debug_variable(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_http_trace_newid_variable(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data); - - -static ngx_command_t ngx_http_trace_commands[] = { - - { ngx_string("http_trace"), - NGX_HTTP_MAIN_CONF|NGX_CONF_NOARGS, - ngx_http_trace, - 0, - 0, - NULL }, - - ngx_null_command -}; - - -static ngx_http_module_t ngx_http_trace_module_ctx = { - ngx_http_trace_add_variables, /* preconfiguration */ - ngx_http_trace_init, /* postconfiguration */ - - ngx_http_trace_create_main_conf, /* create main configuration */ - ngx_http_trace_init_main_conf, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - NULL, /* create location configuration */ - NULL /* merge location configuration */ -}; - - -ngx_module_t ngx_http_trace_module = { - NGX_MODULE_V1, - &ngx_http_trace_module_ctx, /* module context */ - ngx_http_trace_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static ngx_http_variable_t ngx_http_trace_vars[] = { - - { ngx_string("ntm_traceid"), NULL, - ngx_http_trace_traceid_variable, 0, 0, 0 }, - - { ngx_string("ntm_currentid"), NULL, - ngx_http_trace_currentid_variable, 0, 0, 0 }, - - { ngx_string("ntm_parentid"), NULL, - ngx_http_trace_parentid_variable, 0, 0, 0 }, - - { ngx_string("ntm_debug"), NULL, - ngx_http_trace_debug_variable, 0, 0, 0 }, - - { ngx_string("ntm_newid"), NULL, - ngx_http_trace_newid_variable, 0, 0, 0 }, - - { ngx_null_string, NULL, NULL, 0, 0, 0 } -}; - - -static void -ngx_http_trace_genid(u_char *id) { - ngx_sprintf(id, "%08xD%08xD%08xD%08xD", - (uint32_t) ngx_random(), (uint32_t) ngx_random(), - (uint32_t) ngx_random(), (uint32_t) ngx_random()); -} - - -static u_char * -ngx_http_trace_log_error(ngx_log_t *log, u_char *buf, size_t len) -{ - u_char *p; - ngx_http_request_t *r; - ngx_http_log_ctx_t *ctx; - ngx_http_trace_ctx_t *tctx; - ngx_str_t traceid, currentid, parentid; - - if (log->action) { - p = ngx_snprintf(buf, len, " while %s", log->action); - len -= p - buf; - buf = p; - } - - ctx = log->data; - - p = ngx_snprintf(buf, len, ", client: %V", &ctx->connection->addr_text); - len -= p - buf; - buf = p; - - r = ctx->request; - - if (r) { - p = r->log_handler(r, ctx->current_request, p, len); - len -= p - buf; - buf = p; - - } else { - p = ngx_snprintf(p, len, ", server: %V", - &ctx->connection->listening->addr_text); - len -= p - buf; - buf = p; - } - - tctx = ngx_http_get_module_ctx(r, ngx_http_trace_module); - if (tctx) { - traceid.data = tctx->traceid; - traceid.len = sizeof(tctx->traceid); - - currentid.data = tctx->cid; - currentid.len = sizeof(tctx->cid); - - parentid.data = tctx->pid; - parentid.len = sizeof(tctx->pid); - - p = ngx_snprintf(p, len, ", [NGINX-TRACE] traceid: %V, currentid: %V, " - "parentid: %V [NGINX-TRACE-END]", - &traceid, ¤tid, &parentid); - } - - return p; -} - - -// First request without X-NTM-Traceid X-NTM-Currentid or X-NTM-Parentid -// Need to gen these ids and set X-NTM headers in main request -static ngx_int_t -ngx_http_trace_first_request(ngx_http_request_t *r, ngx_http_trace_ctx_t *ctx) -{ - ngx_table_elt_t *h; - - ngx_http_trace_genid(ctx->traceid); - ngx_http_trace_genid(ctx->cid); - ngx_sprintf(ctx->pid, "00000000000000000000000000000000"); - - // Set X-NTM-Traceid - h = ngx_list_push(&r->headers_in.headers); - if (h == NULL) { - return NGX_ERROR; - } - - h->key.data = (u_char *) "X-NTM-Traceid"; - h->key.len = sizeof("X-NTM-Traceid") - 1; - - h->value.data = ctx->traceid; - h->value.len = sizeof(ctx->traceid); - - h->lowcase_key = ngx_pnalloc(r->pool, h->key.len); - if (h->lowcase_key == NULL) { - return NGX_ERROR; - } - h->hash = ngx_hash_strlow(h->lowcase_key, h->key.data, h->key.len); - - // Set X-NTM-Currentid - h = ngx_list_push(&r->headers_in.headers); - if (h == NULL) { - return NGX_ERROR; - } - - h->key.data = (u_char *) "X-NTM-Currentid"; - h->key.len = sizeof("X-NTM-Currentid") - 1; - - h->value.data = ctx->cid; - h->value.len = sizeof(ctx->cid); - - h->lowcase_key = ngx_pnalloc(r->pool, h->key.len); - if (h->lowcase_key == NULL) { - return NGX_ERROR; - } - h->hash = ngx_hash_strlow(h->lowcase_key, h->key.data, h->key.len); - - // Set X-NTM-Parentid - h = ngx_list_push(&r->headers_in.headers); - if (h == NULL) { - return NGX_ERROR; - } - - h->key.data = (u_char *) "X-NTM-Parentid"; - h->key.len = sizeof("X-NTM-Parentid") - 1; - - h->value.data = ctx->pid; - h->value.len = sizeof(ctx->pid); - - h->lowcase_key = ngx_pnalloc(r->pool, h->key.len); - if (h->lowcase_key == NULL) { - return NGX_ERROR; - } - h->hash = ngx_hash_strlow(h->lowcase_key, h->key.data, h->key.len); - - return NGX_OK; -} - - -static ngx_int_t -ngx_http_trace_handler(ngx_http_request_t *r) -{ - ngx_http_trace_main_conf_t *tmcf; - ngx_http_trace_ctx_t *ctx; - ngx_http_variable_value_t v; - ngx_str_t header; - - if (r != r->main) { // subrequest - return NGX_DECLINED; - } - - tmcf = ngx_http_get_module_main_conf(r, ngx_http_trace_module); - if (!tmcf->trace) { - return NGX_DECLINED; - } - - ctx = ngx_http_get_module_ctx(r, ngx_http_trace_module); - if (ctx) { // ctx already create, enter twice - return NGX_DECLINED; - } - - ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_trace_ctx_t)); - if (ctx == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - ngx_http_set_ctx(r, ctx, ngx_http_trace_module); - - // traceid currentid parentid log into nginx error log - r->connection->log->handler = ngx_http_trace_log_error; - - // Get X-NTM-Debug - header.data = (u_char *) "http_x_ntm_debug"; - header.len = sizeof("http_x_ntm_debug") - 1; - ngx_http_variable_unknown_header(&v, &header, &r->headers_in.headers.part, - sizeof("http_") - 1); - if (!v.not_found && v.len == 1 && v.data[0] == '1') { - // Has header X-NTM-Debug: 1 - ctx->debug = 1; - } - - // Get X-NTM-Traceid - header.data = (u_char *) "http_x_ntm_traceid"; - header.len = sizeof("http_x_ntm_traceid") - 1; - ngx_http_variable_unknown_header(&v, &header, &r->headers_in.headers.part, - sizeof("http_") - 1); - if (v.not_found) { - goto notfound; - } - - ngx_memcpy(ctx->traceid, v.data, ngx_min(v.len, sizeof(ctx->traceid))); - - // Get X-NTM-Currentid - header.data = (u_char *) "http_x_ntm_currentid"; - header.len = sizeof("http_x_ntm_currentid") - 1; - ngx_http_variable_unknown_header(&v, &header, &r->headers_in.headers.part, - sizeof("http_") - 1); - if (v.not_found) { - goto notfound; - } - - ngx_memcpy(ctx->cid, v.data, ngx_min(v.len, sizeof(ctx->cid))); - - // Get X-NTM-Parentid - header.data = (u_char *) "http_x_ntm_parentid"; - header.len = sizeof("http_x_ntm_parentid") - 1; - ngx_http_variable_unknown_header(&v, &header, &r->headers_in.headers.part, - sizeof("http_") - 1); - if (v.not_found) { - goto notfound; - } - - ngx_memcpy(ctx->pid, v.data, ngx_min(v.len, sizeof(ctx->pid))); - - return NGX_DECLINED; - -notfound: - - if (ngx_http_trace_first_request(r, ctx) != NGX_OK) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - return NGX_DECLINED; -} - - -static ngx_int_t -ngx_http_trace_traceid_variable(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data) -{ - ngx_http_trace_ctx_t *ctx; - - ctx = ngx_http_get_module_ctx(r, ngx_http_trace_module); - if (ctx == NULL) { - v->not_found = 1; - return NGX_OK; - } - - v->data = ctx->traceid; - v->len = sizeof(ctx->traceid); - v->valid = 1; - v->no_cacheable = 0; - v->not_found = 0; - - return NGX_OK; -} - - -static ngx_int_t -ngx_http_trace_currentid_variable(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data) -{ - ngx_http_trace_ctx_t *ctx; - - ctx = ngx_http_get_module_ctx(r, ngx_http_trace_module); - if (ctx == NULL) { - v->not_found = 1; - return NGX_OK; - } - - v->data = ctx->cid; - v->len = sizeof(ctx->cid); - v->valid = 1; - v->no_cacheable = 0; - v->not_found = 0; - - return NGX_OK; -} - - -static ngx_int_t -ngx_http_trace_parentid_variable(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data) -{ - ngx_http_trace_ctx_t *ctx; - - ctx = ngx_http_get_module_ctx(r, ngx_http_trace_module); - if (ctx == NULL) { - v->not_found = 1; - return NGX_OK; - } - - v->data = ctx->pid; - v->len = sizeof(ctx->pid); - v->valid = 1; - v->no_cacheable = 0; - v->not_found = 0; - - return NGX_OK; -} - - -static ngx_int_t -ngx_http_trace_debug_variable(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data) -{ - ngx_http_trace_ctx_t *ctx; - - ctx = ngx_http_get_module_ctx(r, ngx_http_trace_module); - if (ctx == NULL) { - v->not_found = 1; - return NGX_OK; - } - - if (ctx->debug) { - v->data = (u_char *) "1"; - } else { - v->data = (u_char *) "0"; - } - - v->len = sizeof("1") - 1; - v->valid = 1; - v->no_cacheable = 0; - v->not_found = 0; - - return NGX_OK; -} - - -static ngx_int_t -ngx_http_trace_newid_variable(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data) -{ - ngx_http_trace_ctx_t *ctx; - u_char *newid; - - ctx = ngx_http_get_module_ctx(r, ngx_http_trace_module); - if (ctx == NULL) { - v->not_found = 1; - return NGX_OK; - } - - newid = ngx_pcalloc(r->pool, sizeof(ctx->cid)); - if (newid == NULL) { - return NGX_ERROR; - } - - // fill newid - ngx_http_trace_genid(newid); - - v->data = newid; - v->len = sizeof(ctx->cid); - v->valid = 1; - v->no_cacheable = 0; - v->not_found = 0; - - return NGX_OK; -} - - -static void * -ngx_http_trace_create_main_conf(ngx_conf_t *cf) -{ - ngx_http_trace_main_conf_t *conf; - - conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_trace_main_conf_t)); - if (conf == NULL) { - return NULL; - } - - conf->trace = NGX_CONF_UNSET; - - return conf; -} - - -static char * -ngx_http_trace_init_main_conf(ngx_conf_t *cf, void *conf) -{ - ngx_http_trace_main_conf_t *tmcf; - - tmcf = conf; - - ngx_conf_init_value(tmcf->trace, 0); - - return NGX_CONF_OK; -} - - -static char * -ngx_http_trace(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_trace_main_conf_t *tmcf; - - tmcf = conf; - - if (tmcf->trace != NGX_CONF_UNSET) { - return "is duplicate"; - } - - tmcf->trace = 1; - - return NGX_CONF_OK; -} - - -static ngx_int_t -ngx_http_trace_add_variables(ngx_conf_t *cf) -{ - ngx_http_variable_t *var, *v; - - for (v = ngx_http_trace_vars; v->name.len; v++) { - var = ngx_http_add_variable(cf, &v->name, v->flags); - if (var == NULL) { - return NGX_ERROR; - } - - var->get_handler = v->get_handler; - var->data = v->data; - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_http_trace_init(ngx_conf_t *cf) -{ - ngx_http_handler_pt *h; - ngx_http_core_main_conf_t *cmcf; - - cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); - - h = ngx_array_push(&cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers); - if (h == NULL) { - return NGX_ERROR; - } - - *h = ngx_http_trace_handler; - - return NGX_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_map.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_map.c deleted file mode 100644 index c41bc16d4b..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_map.c +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include "ngx_map.h" - - -static void -ngx_map_rbtree_insert_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node, - ngx_rbtree_node_t *sentinel) -{ - ngx_rbtree_node_t **p; - intptr_t *raw_key, *raw_key_temp; - ngx_map_t **map; - - for (;;) { - - if (node->key < temp->key) { - p = &temp->left; - } else if (node->key > temp->key) { - p = &temp->right; - } else { - raw_key = (intptr_t *)((char *) node - + offsetof(ngx_map_node_t, raw_key)); - raw_key_temp = (intptr_t *)((char *) temp - + offsetof(ngx_map_node_t, raw_key)); - map = (ngx_map_t **)((char *) node + offsetof(ngx_map_node_t, map)); - - switch ((*map)->cmp(*raw_key, *raw_key_temp)) { - case -1: - p = &temp->left; - break; - case 1: - p = &temp->right; - break; - default: /* key is duplicate */ - return; - } - } - - if (*p == sentinel) { - break; - } - - temp = *p; - } - - *p = node; - node->parent = temp; - node->left = sentinel; - node->right = sentinel; - ngx_rbt_red(node); -} - -void -ngx_map_init(ngx_map_t *map, ngx_map_hash_pt hash, ngx_cmp_pt cmp) -{ - ngx_rbtree_init(&map->rbtree, &map->sentinel, ngx_map_rbtree_insert_value); - map->hash = hash; - map->cmp = cmp; -} - -ngx_map_node_t * -ngx_map_begin(ngx_map_t *map) -{ - ngx_rbtree_node_t *p; - - if (ngx_map_empty(map)) { - return NULL; - } - - p = map->rbtree.root; - - for (;;) { - if (p->left == map->rbtree.sentinel) { - break; - } - - p = p->left; - } - - return (ngx_map_node_t *) p; -} - -ngx_map_node_t * -ngx_map_rbegin(ngx_map_t *map) -{ - ngx_rbtree_node_t *p; - - if (ngx_map_empty(map)) { - return NULL; - } - - p = map->rbtree.root; - - for (;;) { - if (p->right == map->rbtree.sentinel) { - break; - } - - p = p->right; - } - - return (ngx_map_node_t *) p; -} - -ngx_map_node_t * -ngx_map_next(ngx_map_node_t *n) -{ - ngx_map_t *map; - ngx_rbtree_node_t *p, *top; - - map = n->map; - p = &n->rn; - top = NULL; - - if (p->right != map->rbtree.sentinel) { - // current node has right subtree - top = p->right; - } else { - for (;;) { - if (p == map->rbtree.root) { - return NULL; - } - - if (p->parent->left == p) { - return (ngx_map_node_t *) p->parent; - } - - // p->parent->right == p - p = p->parent; - } - } - - // get the mininum node - p = top; - for (;;) { - if (p->left == map->rbtree.sentinel) { - break; - } - - p = p->left; - } - - return (ngx_map_node_t *) p; -} - -ngx_map_node_t * -ngx_map_prev(ngx_map_node_t *n) -{ - ngx_map_t *map; - ngx_rbtree_node_t *p, *top; - - map = n->map; - p = &n->rn; - top = NULL; - - if (p->left != map->rbtree.sentinel) { - // current node has left subtree - top = p->left; - } else { - for (;;) { - if (p == map->rbtree.root) { - return NULL; - } - - if (p->parent->right == p) { - return (ngx_map_node_t *) p->parent; - } - - // p->parent->left == p - p = p->parent; - } - } - - // get the maximum node - p = top; - for (;;) { - if (p->right == map->rbtree.sentinel) { - break; - } - - p = p->right; - } - - return (ngx_map_node_t *) p; -} - -void -ngx_map_insert(ngx_map_t *map, ngx_map_node_t *node, ngx_flag_t covered) -{ - ngx_map_node_t *n; - - node->rn.key = map->hash(node->raw_key); - node->map = map; - - n = ngx_map_find(map, node->raw_key); - if (n == NULL) { - ngx_rbtree_insert(&map->rbtree, &node->rn); - } else if (covered) { - ngx_map_delete(map, node->raw_key); - ngx_rbtree_insert(&map->rbtree, &node->rn); - } -} - -void -ngx_map_delete(ngx_map_t *map, intptr_t key) -{ - ngx_map_node_t *node; - - node = ngx_map_find(map, key); - if (node) { - ngx_rbtree_delete(&map->rbtree, &node->rn); - } -} - -ngx_map_node_t * -ngx_map_find(ngx_map_t *map, intptr_t key) -{ - ngx_rbtree_node_t *p; - ngx_rbtree_key_t k; - intptr_t *key_temp; - - if (ngx_map_empty(map)) { - return NULL; - } - - k = map->hash(key); - p = map->rbtree.root; - - for (;;) { - if (k < p->key) { - p = p->left; - } else if (k > p->key) { - p = p->right; - } else { - key_temp = (intptr_t *)((char *) p - + offsetof(ngx_map_node_t, raw_key)); - - switch (map->cmp(key, *key_temp)) { - case -1: - p = p->left; - break; - case 1: - p = p->right; - break; - case 0: - return (ngx_map_node_t *) p; - } - } - - if (p == map->rbtree.sentinel) { - return NULL; - } - } -} - - -/* ngx_str_t */ -ngx_rbtree_key_t -ngx_map_hash_str(intptr_t key) -{ - ngx_str_t *k; - - k = (ngx_str_t *) key; - - return ngx_hash_key(k->data, k->len); -} - -int -ngx_cmp_str(intptr_t key1, intptr_t key2) -{ - ngx_str_t *k1, *k2; - ngx_int_t rc; - - k1 = (ngx_str_t *) key1; - k2 = (ngx_str_t *) key2; - - rc = ngx_memn2cmp(k1->data, k2->data, k1->len, k2->len); - - if (rc < 0) { - return -1; - } else if (rc > 0) { - return 1; - } else { - return 0; - } -} - -/* ngx_uint_t */ -ngx_rbtree_key_t -ngx_map_hash_uint(intptr_t key) -{ - return (ngx_rbtree_key_t) key; -} - -int -ngx_cmp_uint(intptr_t key1, intptr_t key2) -{ - if ((ngx_uint_t) key1 < (ngx_uint_t) key2) { - return -1; - } else if ((ngx_uint_t) key1 > (ngx_uint_t) key2) { - return 1; - } else { - return 0; - } -} - -/* ngx_int_t */ -ngx_rbtree_key_t -ngx_map_hash_int(intptr_t key) -{ - return (ngx_rbtree_key_t) key; -} - -int -ngx_cmp_int(intptr_t key1, intptr_t key2) -{ - if ((ngx_int_t) key1 < (ngx_int_t) key2) { - return -1; - } else if ((ngx_int_t) key1 > (ngx_int_t) key2) { - return 1; - } else { - return 0; - } -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_map.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_map.h deleted file mode 100644 index c7626d3a92..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_map.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#ifndef _NGX_MAP_H_INCLUDED_ -#define _NGX_MAP_H_INCLUDED_ - - -#include -#include - - -/* - * key: key for map node - */ -typedef ngx_rbtree_key_t (* ngx_map_hash_pt)(intptr_t key); - -/* - * if key1 < key2, return -1 - * if key1 = key2, return 0 - * if key1 > key2, return 1 - */ -typedef int (* ngx_cmp_pt)(intptr_t key1, intptr_t key2); - - -/* ngx_str_t */ -ngx_rbtree_key_t ngx_map_hash_str(intptr_t key); -int ngx_cmp_str(intptr_t key1, intptr_t key2); - -/* ngx_uint_t */ -ngx_rbtree_key_t ngx_map_hash_uint(intptr_t key); -int ngx_cmp_uint(intptr_t key1, intptr_t key2); - -/* ngx_int_t */ -ngx_rbtree_key_t ngx_map_hash_int(intptr_t key); -int ngx_cmp_int(intptr_t key1, intptr_t key2); - - -typedef struct { - ngx_rbtree_t rbtree; - ngx_rbtree_node_t sentinel; - ngx_map_hash_pt hash; - ngx_cmp_pt cmp; -} ngx_map_t; - -typedef struct { - ngx_rbtree_node_t rn; - intptr_t raw_key; - ngx_map_t *map; -} ngx_map_node_t; - - -/* - * return value: - * None - * paras: - * map : map for initial - * hash: hash func for calc key's hash - * cmp : cmp func for cmp two keys - */ -void ngx_map_init(ngx_map_t *map, ngx_map_hash_pt hash, ngx_cmp_pt cmp); - -/* - * return value: - * if map is empty return 1, else return 0 - */ -#define ngx_map_empty(map) (map->rbtree.root == map->rbtree.sentinel) - -/* - * return value: - * the mininum key map node, if map is empty, return NULL - * paras: - * map: map for operate - */ -ngx_map_node_t *ngx_map_begin(ngx_map_t *map); - -/* - * return value: - * the maximum key map node, if map is empty, return NULL - * paras: - * map: map for operate - */ -ngx_map_node_t *ngx_map_rbegin(ngx_map_t *map); - -/* - * return value: - * the next bigger key map node, if none, return NULL - * paras: - * n : current node - */ -ngx_map_node_t *ngx_map_next(ngx_map_node_t *n); - -/* - * return value: - * the next smaller key map node, if none, return NULL - * paras: - * n : current node - */ -ngx_map_node_t *ngx_map_prev(ngx_map_node_t *n); - -/* - * return value: - * None - * paras: - * map : map for operate - * node : map node for inserting into map - * covered: 1 for covered if key is same, 0 do nothing if key is same - */ -void ngx_map_insert(ngx_map_t *map, ngx_map_node_t *node, ngx_flag_t covered); - -/* - * return value: - * None - * paras: - * map: map for operate - * key: map node key for deleting from map - */ -void ngx_map_delete(ngx_map_t *map, intptr_t key); - -/* - * return value: - * node in map searching by key, NULL for not found - * paras: - * map: map for operate - * key: node key for searching - */ -ngx_map_node_t *ngx_map_find(ngx_map_t *map, intptr_t key); - - -#endif diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_poold.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_poold.c deleted file mode 100644 index bab46342b4..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_poold.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include "ngx_poold.h" -#include "ngx_map.h" - - -typedef struct ngx_poold_node_s ngx_poold_node_t; - -static ngx_pool_t *ngx_poold_pool; - -static ngx_map_t ngx_poold_map; -static ngx_poold_node_t *ngx_poold_free_node; - -static ngx_uint_t ngx_poold_nalloc; -static ngx_uint_t ngx_poold_nfree; - - -struct ngx_poold_node_s { - ngx_map_node_t m; /* map node */ - ngx_poold_node_t *next; /* free node */ - - ngx_pool_t *pool; - char *file; /* file create pool */ - int line; /* line create pool */ -}; - - -static ngx_int_t -ngx_poold_init() -{ - ngx_poold_pool = ngx_create_pool(4096, ngx_cycle->log); - if (ngx_poold_pool == NULL) { - return NGX_ERROR; - } - - ngx_map_init(&ngx_poold_map, ngx_map_hash_uint, ngx_cmp_uint); - ngx_poold_free_node = NULL; - - ngx_poold_nalloc = 0; - ngx_poold_nfree = 0; - - return NGX_OK; -} - - -static ngx_poold_node_t * -ngx_poold_get_node() -{ - ngx_poold_node_t *n; - - n = ngx_poold_free_node; - if (n == NULL) { - n = ngx_pcalloc(ngx_poold_pool, sizeof(ngx_poold_node_t)); - if (n == NULL) { - return NULL; - } - - ++ngx_poold_nalloc; - } else { - ngx_poold_free_node = n->next; - ngx_memzero(n, sizeof(ngx_poold_node_t)); - - --ngx_poold_nfree; - } - - return n; -} - - -static void -ngx_poold_put_node(ngx_poold_node_t *node) -{ - if (ngx_poold_pool == NULL) { - return; - } - - if (node == NULL) { - return; - } - - node->next = ngx_poold_free_node; - ngx_poold_free_node = node; - - ++ngx_poold_nfree; -} - - -ngx_pool_t * -ngx_create_pool_debug(size_t size, ngx_log_t *log, char *file, int line) -{ - ngx_poold_node_t *node; - - if (ngx_poold_pool == NULL) { - ngx_poold_init(); - } - - /* construct a poold node */ - node = ngx_poold_get_node(); - node->pool = ngx_create_pool(size, log); - node->file = file; - node->line = line; - - /* record node in poold map */ - node->m.raw_key = (intptr_t) node->pool; - ngx_map_insert(&ngx_poold_map, &node->m, 0); - - return node->pool; -} - - -void -ngx_destroy_pool_debug(ngx_pool_t *pool, char *file, int line) -{ - ngx_poold_node_t *node; - ngx_map_node_t *m; - - /* get node by pool */ - m = ngx_map_find(&ngx_poold_map, (intptr_t) pool); - if (m == NULL) { - ngx_log_error(NGX_LOG_EMERG, ngx_cycle->log, 0, - "destroy pool twice: %s:%d", file, line); - return; - } - ngx_map_delete(&ngx_poold_map, (intptr_t) pool); - node = (ngx_poold_node_t *) ((char *) m - offsetof(ngx_poold_node_t, m)); - - ngx_destroy_pool(pool); - - /* put node in poold map */ - ngx_poold_put_node(node); -} - - -ngx_chain_t * -ngx_poold_state(ngx_http_request_t *r, unsigned detail) -{ - ngx_chain_t *cl; - ngx_buf_t *b; - ngx_map_node_t *node; - ngx_poold_node_t *pn; - size_t len, len1; - ngx_uint_t n; - - len = sizeof("##########ngx debug pool##########\n") - 1 - + sizeof("ngx_poold nalloc node: \n") - 1 + NGX_OFF_T_LEN - + sizeof("ngx_poold nfree node: \n") - 1 + NGX_OFF_T_LEN; - - len1 = 0; - - /* node for create pool */ - if (detail) { - n = ngx_poold_nalloc - ngx_poold_nfree; - /* " file:line\n" */ - len1 = 4 + 256 + 1 + NGX_OFF_T_LEN + 1; - len += len1 * n; - } - - cl = ngx_alloc_chain_link(r->pool); - if (cl == NULL) { - return NULL; - } - cl->next = NULL; - - b = ngx_create_temp_buf(r->pool, len); - if (b == NULL) { - return NULL; - } - cl->buf = b; - - b->last = ngx_snprintf(b->last, len, - "##########ngx debug pool##########\n" - "ngx_poold nalloc node: %ui\nngx_poold nfree node: %ui\n", - ngx_poold_nalloc, ngx_poold_nfree); - - if (detail) { - for (node = ngx_map_begin(&ngx_poold_map); node; - node = ngx_map_next(node)) - { - /* m is first element of ngx_poold_node_t */ - pn = (ngx_poold_node_t *) node; - b->last = ngx_snprintf(b->last, len1, " %s:%d\n", - pn->file, pn->line); - } - } - - return cl; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_poold.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_poold.h deleted file mode 100644 index 588283901c..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_poold.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#ifndef _NGX_POOL_DEBUG_H_INCLUDED_ -#define _NGX_POOL_DEBUG_H_INCLUDED_ - - -#include -#include -#include - - -#define NGX_CREATE_POOL(size, log) \ - ngx_create_pool_debug(size, log, __FILE__, __LINE__) - -#define NGX_DESTROY_POOL(pool) \ - ngx_destroy_pool_debug(pool, __FILE__, __LINE__) - - -/* - * create pool and record where to create it for debugging - * such as pool not destroy - * - * paras: - * size: pool size for pool creating interface in raw ngx_create_pool - * log: log for pool creating interface in raw ngx_create_pool - * file: use __FILE__ for recording file - * line: use __LINE__ for recording line - * return: - * pool for successd, NULL for failed - */ -ngx_pool_t *ngx_create_pool_debug(size_t size, ngx_log_t *log, - char *file, int line); - - -/* - * destroy pool for debugging, use as pair for ngx_create_pool_debug - * - * paras: - * pool: pool for pool destroying interface in ran ngx_destroy_pool - * file: use __FILE__ for recording file - * line: use __LINE__ for recording line - */ -void ngx_destroy_pool_debug(ngx_pool_t *pool, char *file, int line); - - -/* - * paras: - * r: http request to query status of rbuf - */ -ngx_chain_t *ngx_poold_state(ngx_http_request_t *r, unsigned detail); - - -#endif diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_rbuf.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_rbuf.c deleted file mode 100644 index 6b80bd59c4..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_rbuf.c +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include -#include -#include -#include "ngx_map.h" - - -static ngx_pool_t *ngx_rbuf_pool; - -static ngx_map_t ngx_rbuf_map; -static ngx_chain_t *ngx_rbuf_free_chain; - -static ngx_uint_t ngx_rbuf_nalloc_node; - -static ngx_uint_t ngx_rbuf_nalloc_buf; -static ngx_uint_t ngx_rbuf_nfree_buf; - -static ngx_uint_t ngx_rbuf_nalloc_chain; -static ngx_uint_t ngx_rbuf_nfree_chain; - -static ngx_map_t ngx_rbuf_using; - -#define ngx_rbuf_buf(b) \ - (ngx_rbuf_t *) ((u_char *) (b) - offsetof(ngx_rbuf_t, buf)) - -typedef struct ngx_rbuf_s ngx_rbuf_t; - -struct ngx_rbuf_s { - size_t size; - ngx_rbuf_t *next; - u_char buf[]; -}; - -typedef struct { - ngx_map_node_t node; - ngx_rbuf_t *rbuf; -} ngx_rbuf_node_t; - -typedef struct { - ngx_chain_t cl; - ngx_buf_t buf; - unsigned alloc; - - ngx_map_node_t node; - char *file; - int line; -} ngx_chainbuf_t; - - -static ngx_int_t -ngx_rbuf_init() -{ - ngx_rbuf_pool = ngx_create_pool(4096, ngx_cycle->log); - if (ngx_rbuf_pool == NULL) { - return NGX_ERROR; - } - - ngx_map_init(&ngx_rbuf_map, ngx_map_hash_uint, ngx_cmp_uint); - ngx_map_init(&ngx_rbuf_using, ngx_map_hash_uint, ngx_cmp_uint); - - ngx_rbuf_nalloc_node = 0; - ngx_rbuf_nalloc_buf = 0; - ngx_rbuf_nfree_buf = 0; - ngx_rbuf_nalloc_chain = 0; - ngx_rbuf_nfree_chain = 0; - - return NGX_OK; -} - - -static ngx_rbuf_t * -ngx_rbuf_get_buf(size_t key) -{ - ngx_rbuf_node_t *rn; - ngx_map_node_t *node; - ngx_rbuf_t *rb; - - node = ngx_map_find(&ngx_rbuf_map, key); - if (node == NULL) { /* new key */ - rn = ngx_pcalloc(ngx_rbuf_pool, sizeof(ngx_rbuf_node_t)); - if (rn == NULL) { - return NULL; - } - - node = &rn->node; - node->raw_key = key; - ngx_map_insert(&ngx_rbuf_map, node, 0); - - ++ngx_rbuf_nalloc_node; - } else { - rn = (ngx_rbuf_node_t *) node; - } - - rb = rn->rbuf; - if (rb == NULL) { - rb = ngx_pcalloc(ngx_rbuf_pool, sizeof(ngx_rbuf_t) + key); - if (rb == NULL) { - return NULL; - } - rb->size = key; - - ++ngx_rbuf_nalloc_buf; - } else { - rn->rbuf = rb->next; - rb->next = NULL; - - --ngx_rbuf_nfree_buf; - } - - return rb; -} - -static void -ngx_rbuf_put_buf(ngx_rbuf_t *rb) -{ - ngx_rbuf_node_t *rn; - ngx_map_node_t *node; - - node = ngx_map_find(&ngx_rbuf_map, rb->size); - if (node == NULL) { - return; - } - - rn = (ngx_rbuf_node_t *) node; - rb->next = rn->rbuf; - rn->rbuf = rb; - - ++ngx_rbuf_nfree_buf; -} - - -static u_char * -ngx_rbuf_alloc(size_t size) -{ - ngx_rbuf_t *rb; - - rb = ngx_rbuf_get_buf(size); - - return rb->buf; -} - -static void -ngx_rbuf_free(u_char *rb) -{ - ngx_rbuf_t *rbuf; - - rbuf = ngx_rbuf_buf(rb); - ngx_rbuf_put_buf(rbuf); -} - - -ngx_chain_t * -ngx_get_chainbuf_debug(size_t size, ngx_flag_t alloc_rbuf, char *file, int line) -{ - ngx_chainbuf_t *cb; - ngx_chain_t *cl; - - if (ngx_rbuf_pool == NULL) { - ngx_rbuf_init(); - } - - cl = ngx_rbuf_free_chain; - if (cl) { - ngx_rbuf_free_chain = cl->next; - cl->next = NULL; - cb = (ngx_chainbuf_t *) cl; - - --ngx_rbuf_nfree_chain; - } else { - cb = ngx_pcalloc(ngx_rbuf_pool, sizeof(ngx_chainbuf_t)); - if (cb == NULL) { - return NULL; - } - - cl = &cb->cl; - cl->buf = &cb->buf; - - ++ngx_rbuf_nalloc_chain; - } - - if (alloc_rbuf) { - cl->buf->last = cl->buf->pos = cl->buf->start = ngx_rbuf_alloc(size); - cl->buf->end = cl->buf->start + size; - cb->alloc = 1; - } else { - cl->buf->pos = cl->buf->last = cl->buf->start = cl->buf->end = NULL; - cb->alloc = 0; - } - cl->buf->memory = 1; - - // record chainbuf in using map - cb->file = file; - cb->line = line; - cb->node.raw_key = (intptr_t) cl; - ngx_map_insert(&ngx_rbuf_using, &cb->node, 0); - - return cl; -} - -void -ngx_put_chainbuf_debug(ngx_chain_t *cl, char *file, int line) -{ - ngx_chainbuf_t *cb; - - if (ngx_rbuf_pool == NULL) { - return; - } - - if (cl == NULL) { - return; - } - - cb = (ngx_chainbuf_t *) cl; - - if (cb->alloc) { - ngx_rbuf_free(cl->buf->start); - } - cl->next = ngx_rbuf_free_chain; - ngx_rbuf_free_chain = cl; - ++ngx_rbuf_nfree_chain; - - // delete chainbuf from using map - if (ngx_map_find(&ngx_rbuf_using, (intptr_t) cl) == NULL) { - ngx_log_error(NGX_LOG_EMERG, ngx_cycle->log, 0, - "destroy chainbuf twice: %s:%d", file, line); - return; - } - ngx_map_delete(&ngx_rbuf_using, (intptr_t) cl); -} - -ngx_chain_t * -ngx_rbuf_state(ngx_http_request_t *r, unsigned detail) -{ - ngx_chain_t *cl; - ngx_buf_t *b; - size_t len, len1; - ngx_uint_t n; - ngx_chainbuf_t *cb; - ngx_map_node_t *node; - - len = sizeof("##########ngx rbuf state##########\n") - 1 - + sizeof("ngx_rbuf nalloc node: \n") - 1 + NGX_OFF_T_LEN - + sizeof("ngx_rbuf nalloc buf: \n") - 1 + NGX_OFF_T_LEN - + sizeof("ngx_rbuf nfree buf: \n") - 1 + NGX_OFF_T_LEN - + sizeof("ngx_rbuf nalloc chain: \n") - 1 + NGX_OFF_T_LEN - + sizeof("ngx_rbuf nfree chain: \n") - 1 + NGX_OFF_T_LEN; - - len1 = 0; - - if (detail) { - n = ngx_rbuf_nalloc_chain - ngx_rbuf_nfree_chain; - /* " file:line\n" */ - len1 = 4 + 256 + 1 + NGX_OFF_T_LEN + 1; - len += len1 * n; - } - - cl = ngx_alloc_chain_link(r->pool); - if (cl == NULL) { - return NULL; - } - cl->next = NULL; - - b = ngx_create_temp_buf(r->pool, len); - if (b == NULL) { - return NULL; - } - cl->buf = b; - - b->last = ngx_snprintf(b->last, len, - "##########ngx rbuf state##########\nngx_rbuf nalloc node: %ui\n" - "ngx_rbuf nalloc buf: %ui\nngx_rbuf nfree buf: %ui\n" - "ngx_rbuf nalloc chain: %ui\nngx_rbuf nfree chain: %ui\n", - ngx_rbuf_nalloc_node, ngx_rbuf_nalloc_buf, ngx_rbuf_nfree_buf, - ngx_rbuf_nalloc_chain, ngx_rbuf_nfree_chain); - - if (detail) { - for (node = ngx_map_begin(&ngx_rbuf_using); node; - node = ngx_map_next(node)) - { - cb = (ngx_chainbuf_t *) ((char *) node - - offsetof(ngx_chainbuf_t, node)); - b->last = ngx_snprintf(b->last, len1, " %s:%d\n", - cb->file, cb->line); - } - } - - return cl; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_rbuf.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_rbuf.h deleted file mode 100644 index 7002d55905..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_rbuf.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#ifndef _NGX_RBUF_H_INCLUDED_ -#define _NGX_RBUF_H_INCLUDED_ - - -#include -#include -#include - - -ngx_chain_t *ngx_get_chainbuf_debug(size_t size, ngx_flag_t alloc_rbuf, - char *file, int line); -void ngx_put_chainbuf_debug(ngx_chain_t *cl, char *file, int len); - -/* - * paras: - * size: buffer size for allocate - * alloc_rbuf: whether alloc rbuf - * return: - * nginx chain - */ -#define ngx_get_chainbuf(size, alloc_rbuf) \ - ngx_get_chainbuf_debug(size, alloc_rbuf, __FILE__, __LINE__); - -/* - * paras: - * cl: nginx chain return by ngx_rtmp_shared_get_chainbuf - */ -#define ngx_put_chainbuf(cl) \ - ngx_put_chainbuf_debug(cl, __FILE__, __LINE__); - - -/* - * paras: - * cl: nginx chain return by ngx_rtmp_shared_get_chainbuf - */ -#define ngx_put_chainbufs(cl) \ -{ \ - ngx_chain_t *l; \ - \ - l = cl; \ - while (l) { \ - cl = l->next; \ - ngx_put_chainbuf_debug(l, __FILE__, __LINE__); \ - l = cl; \ - } \ -} - -/* - * paras: - * r: http request to query status of rbuf - */ -ngx_chain_t *ngx_rbuf_state(ngx_http_request_t *r, unsigned detail); - -#endif diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_timerd.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_timerd.c deleted file mode 100644 index a28109bca7..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_timerd.c +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include "ngx_timerd.h" -#include "ngx_map.h" - - -typedef struct ngx_timerd_node_s ngx_timerd_node_t; - -static ngx_pool_t *ngx_timerd_pool; - -static ngx_map_t ngx_timerd_map; -static ngx_timerd_node_t *ngx_timerd_free_node; - -static ngx_uint_t timerd_footprint; -static ngx_uint_t ngx_timerd_nalloc; -static ngx_uint_t ngx_timerd_nfree; - - -struct ngx_timerd_node_s { - ngx_map_node_t m; /* map node */ - ngx_timerd_node_t *next; /* free node */ - - ngx_uint_t footprint; - off_t fpoff; - ngx_event_t ev; - - ngx_event_t *uev; - char *file; /* file create pool */ - int line; /* line create pool */ -}; - - -static ngx_int_t -ngx_timerd_init() -{ - ngx_timerd_pool = ngx_create_pool(4096, ngx_cycle->log); - if (ngx_timerd_pool == NULL) { - return NGX_ERROR; - } - - ngx_map_init(&ngx_timerd_map, ngx_map_hash_uint, ngx_cmp_uint); - ngx_timerd_free_node = NULL; - - ngx_timerd_nalloc = 0; - ngx_timerd_nfree = 0; - - return NGX_OK; -} - - -static ngx_timerd_node_t * -ngx_timerd_get_node() -{ - ngx_timerd_node_t *n; - - n = ngx_timerd_free_node; - if (n == NULL) { - n = ngx_pcalloc(ngx_timerd_pool, sizeof(ngx_timerd_node_t)); - if (n == NULL) { - return NULL; - } - - ++ngx_timerd_nalloc; - } else { - ngx_timerd_free_node = n->next; - ngx_memzero(n, sizeof(ngx_timerd_node_t)); - - --ngx_timerd_nfree; - } - - return n; -} - - -static void -ngx_timerd_put_node(ngx_timerd_node_t *node) -{ - if (ngx_timerd_pool == NULL) { - return; - } - - if (node == NULL) { - return; - } - - node->next = ngx_timerd_free_node; - ngx_timerd_free_node = node; - - ++ngx_timerd_nfree; -} - - -static void -ngx_timerd_wrap(ngx_event_t *ev) -{ - ngx_timerd_node_t *node; - ngx_event_t *uev; - ngx_uint_t *fp; - - node = ev->data; - uev = node->uev; - - fp = (ngx_uint_t *) ((char *) (uev->data) + node->fpoff); - if (*fp != node->footprint) { - ngx_log_error(NGX_LOG_EMERG, ngx_cycle->log, 0, - "timer wrap, timer trigger but not timer owner: %s:%d", - node->file, node->line); - return; - } - - ngx_map_delete(&ngx_timerd_map, (intptr_t) uev); - - uev->timer_set = 0; - uev->timedout = 1; - - uev->handler(uev); - - ngx_timerd_put_node(node); -} - - -ngx_uint_t -ngx_timerd_footprint() -{ - return timerd_footprint++; -} - - -void -ngx_add_timer_debug(ngx_event_t *ev, ngx_msec_t timer, off_t fpoff, - char *file, int line) -{ - ngx_timerd_node_t *node; - ngx_map_node_t *m; - ngx_uint_t *fp; - - if (ngx_timerd_pool == NULL) { - ngx_timerd_init(); - } - - fp = (ngx_uint_t *) ((char *) ev->data + fpoff); - - m = ngx_map_find(&ngx_timerd_map, (intptr_t) ev); - if (m == NULL) { // first add - node = ngx_timerd_get_node(); - - node->m.raw_key = (intptr_t) ev; - ngx_map_insert(&ngx_timerd_map, &node->m, 0); - - node->footprint = *fp; - node->fpoff = fpoff; - - node->ev.log = ngx_cycle->log; - node->ev.data = node; - node->ev.handler = ngx_timerd_wrap; - - node->uev = ev; - node->file = file; - node->line = line; - } else { - node = (ngx_timerd_node_t *) ((char *) m - - offsetof(ngx_timerd_node_t, m)); - if (node->footprint != *fp) { - ngx_log_error(NGX_LOG_EMERG, ngx_cycle->log, 0, - "add timer but not timer owner(%s:%d): %s:%d", - node->file, node->line, file, line); - return; - } - } - - ev->timer_set = 1; - ngx_add_timer(&node->ev, timer); -} - - -void -ngx_del_timer_debug(ngx_event_t *ev, ngx_uint_t footprint, char *file, int line) -{ - ngx_timerd_node_t *node; - ngx_map_node_t *m; - - /* get node by pool */ - m = ngx_map_find(&ngx_timerd_map, (intptr_t) ev); - if (m == NULL) { - ngx_log_error(NGX_LOG_EMERG, ngx_cycle->log, 0, - "delete timer twice: %s:%d", file, line); - return; - } - - node = (ngx_timerd_node_t *) ((char *) m - offsetof(ngx_timerd_node_t, m)); - if (node->footprint != footprint) { - ngx_log_error(NGX_LOG_EMERG, ngx_cycle->log, 0, - "delete timer but not timer owner: %s:%d", file, line); - return; - } - - ngx_map_delete(&ngx_timerd_map, (intptr_t) ev); - - if (node->ev.timer_set) { - ev->timer_set = 0; - ngx_del_timer(&node->ev); - } - - if (node->ev.posted) { - ngx_delete_posted_event(&node->ev); - } - - /* put node in timerd map */ - ngx_timerd_put_node(node); -} - - -ngx_chain_t * -ngx_timerd_state(ngx_http_request_t *r, unsigned detail) -{ - ngx_chain_t *cl; - ngx_buf_t *b; - ngx_map_node_t *node; - ngx_timerd_node_t *pn; - size_t len, len1; - ngx_uint_t n; - - len = sizeof("##########ngx debug pool##########\n") - 1 - + sizeof("ngx_timerd nalloc node: \n") - 1 + NGX_OFF_T_LEN - + sizeof("ngx_timerd nfree node: \n") - 1 + NGX_OFF_T_LEN; - - len1 = 0; - - /* node for create pool */ - if (detail) { - n = ngx_timerd_nalloc - ngx_timerd_nfree; - /* " file:line\n" */ - len1 = 4 + 256 + 1 + NGX_OFF_T_LEN + 1; - len += len1 * n; - } - - cl = ngx_alloc_chain_link(r->pool); - if (cl == NULL) { - return NULL; - } - cl->next = NULL; - - b = ngx_create_temp_buf(r->pool, len); - if (b == NULL) { - return NULL; - } - cl->buf = b; - - b->last = ngx_snprintf(b->last, len, - "##########ngx debug pool##########\n" - "ngx_timerd nalloc node: %ui\nngx_timerd nfree node: %ui\n", - ngx_timerd_nalloc, ngx_timerd_nfree); - - if (detail) { - for (node = ngx_map_begin(&ngx_timerd_map); node; - node = ngx_map_next(node)) - { - /* m is first element of ngx_timerd_node_t */ - pn = (ngx_timerd_node_t *) node; - b->last = ngx_snprintf(b->last, len1, " %s:%d\n", - pn->file, pn->line); - } - } - - return cl; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_timerd.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_timerd.h deleted file mode 100644 index 7c64d4267d..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_timerd.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#ifndef _NGX_TIMER_DEBUG_H_INCLUDED_ -#define _NGX_TIMER_DEBUG_H_INCLUDED_ - - -#include -#include -#include - - -#define NGX_ADD_TIMER(ev, timer, fpoff) \ - ngx_add_timer_debug(ev, timer, fpoff, __FILE__, __LINE__) - -#define NGX_DEL_TIMER(ev, footprint) \ - ngx_del_timer_debug(ev, footprint, __FILE__, __LINE__) - - -/* - * generate a new footprint - * - * return: - * footprint - */ -ngx_uint_t ngx_timerd_footprint(); - - -/* - * add timer and record where to add it for debugging - * such as timer not destroy - * - * paras: - * ev: nginx event for timer - * timer: timer interval for triggering timer - * fpoff: footprint offset in event data - * file: use __FILE__ for recording file - * line: use __LINE__ for recording line - * return: - * pool for successd, NULL for failed - */ -void ngx_add_timer_debug(ngx_event_t *ev, ngx_msec_t timer, off_t fpoff, - char *file, int line); - - -/* - * destroy pool for debugging, use as pair for ngx_create_pool_debug - * - * paras: - * ev: nginx event for timer - * footprint: footprint value in user event data - * file: use __FILE__ for recording file - * line: use __LINE__ for recording line - */ -void ngx_del_timer_debug(ngx_event_t *ev, ngx_uint_t footprint, - char *file, int line); - - -/* - * paras: - * r: http request to query status of rbuf - */ -ngx_chain_t *ngx_timerd_state(ngx_http_request_t *r, unsigned detail); - - -#endif diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_toolkit_misc.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_toolkit_misc.c deleted file mode 100644 index 804546075f..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_toolkit_misc.c +++ /dev/null @@ -1,383 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#include "ngx_toolkit_misc.h" -#include - - -typedef struct { - ngx_str_t scheme; - in_port_t port; -} ngx_scheme_port_t; - - -ngx_scheme_port_t ngx_sheme_port[] = { - { ngx_string("http"), 80 }, - { ngx_string("https"), 443 }, - { ngx_string("rtmp"), 1935 }, - { ngx_null_string, 0 } -}; - - -#define FILEBUFSIZE 8192 - - -socklen_t -ngx_sock_pton_unix(struct sockaddr *sa, u_char *text, size_t len) -{ -#if NGX_HAVE_UNIX_DOMAIN - u_char *path; - struct sockaddr_un *saun; - - // skip 'unix:' - path = text + 5; - len -= 5; - - if (len == 0) { - ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, - "no path in the unix domain"); - return 0; - } - - ++len; // sun_path need '\0' as end - if (len > sizeof(saun->sun_path)) { - ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, - "too long path in the unix domain socket"); - return 0; - } - - saun = (struct sockaddr_un *) sa; - saun->sun_family = AF_UNIX; - (void) ngx_cpystrn((u_char *) saun->sun_path, path, len); - - return sizeof(struct sockaddr_un); - -#else - ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, - "the unix domain sockets are not supported on this platform"); - - return 0; -#endif -} - -socklen_t -ngx_sock_pton_inet6(struct sockaddr *sa, u_char *text, size_t len) -{ -#if NGX_HAVE_INET6 - struct in6_addr inaddr6; - struct sockaddr_in6 *sin6; - u_char *p, *last; - ngx_int_t port; - size_t alen, plen; - - last = text + len; - p = ngx_strlchr(text, last, ']'); - - if (p == NULL || p == last - 1) { - ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, - "not a ipv6 address format"); - return 0; - } - - ++text; - alen = p - text; - - /* - * prevent MSVC8 warning: - * potentially uninitialized local variable 'inaddr6' used - */ - ngx_memzero(&inaddr6, sizeof(struct in6_addr)); - - if (ngx_inet6_addr(text, alen, inaddr6.s6_addr) != NGX_OK) { - // not ipv6 address - return 0; - } - - sa->sa_family = AF_INET6; - - sin6 = (struct sockaddr_in6 *) sa; - ngx_memcpy(sin6->sin6_addr.s6_addr, inaddr6.s6_addr, 16); - - ++p; - if (*p == ':') { // has port - ++p; - plen = last - p; - - port = ngx_atoi(p, plen); - if (port < 0 || port > 65535) { - ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, - "invalid port: %i", port); - return 0; - } - - ngx_inet_set_port(sa, (in_port_t) port); - } - - return sizeof(struct sockaddr_in6); - -#else - ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, - "the INET6 sockets are not supported on this platform"); - - return 0; -#endif -} - -socklen_t -ngx_sock_pton_inet(struct sockaddr *sa, u_char *text, size_t len) -{ - in_addr_t inaddr; - struct sockaddr_in *sin; - u_char *p, *last; - ngx_int_t port; - size_t alen, plen; - - last = text + len; - p = ngx_strlchr(text, last, ':'); - alen = len; - - if (p != NULL) { // have port - alen = p - text; - } - - inaddr = ngx_inet_addr(text, alen); - if (inaddr == INADDR_NONE) { - // not ipv4 address - return 0; - } - - sa->sa_family = AF_INET; - - sin = (struct sockaddr_in *) sa; - sin->sin_addr.s_addr = inaddr; - - if (p != NULL) { // has port - ++p; - plen = last - p; - - port = ngx_atoi(p, plen); - if (port < 0 || port > 65535) { - ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, - "invalid port: %i", port); - return 0; - } - - ngx_inet_set_port(sa, (in_port_t) port); - } - - return sizeof(struct sockaddr_in); -} - -ngx_int_t -ngx_parse_request_url(ngx_request_url_t *request_url, ngx_str_t *url) -{ - u_char *last, *host_last; - u_char *scheme; - u_char *user, *host, *port; - u_char *path, *args, *fragment; - - /* NULL url */ - if (url->len == 0) { - return NGX_ERROR; - } - - last = url->data + url->len; - - scheme = url->data; - - user = (u_char *) ngx_strnstr(scheme, "://", last - scheme); - - if (user == NULL) { - return NGX_ERROR; - } - - request_url->scheme.data = scheme; - request_url->scheme.len = user - scheme; - - user += 3; - if (user >= last) { - return NGX_ERROR; - } - - host_last = ngx_strlchr(user, last, '/'); - if (host_last == NULL) { - host_last = last; - } - - host = ngx_strlchr(user, host_last, '@'); - if (host == NULL) { /* no user */ - host = user; - } else { - if (user == host) { /* user is "" */ - return NGX_ERROR; - } - - request_url->user.data = user; - request_url->user.len = host - user; - ++host; - if (host == host_last) { /* no host */ - return NGX_ERROR; - } - } - - port = ngx_strlchr(host, host_last, ':'); - if (port == NULL) { /* no port */ - request_url->host.data = host; - request_url->host.len = host_last - host; - - request_url->host_with_port = request_url->host; - } else { - request_url->host.data = host; - request_url->host.len = port - host; - ++port; - if (port == host_last) { /* port error */ - return NGX_ERROR; - } - - request_url->port.data = port; - request_url->port.len = host_last - port; - - request_url->host_with_port.data = host; - request_url->host_with_port.len = host_last - host; - } - - path = ++host_last; - if (path >= last) { /* no path */ - goto done; - } - - args = ngx_strlchr(path, last, '?'); - if (args == NULL) { /* no args */ - request_url->path.data = path; - request_url->path.len = last - path; - - request_url->uri_with_args = request_url->path; - - goto done; - } else { - request_url->path.data = path; - request_url->path.len = args - path; - ++args; - if (args == last) { /* args error */ - return NGX_ERROR; - } - } - - fragment = ngx_strlchr(args, last, '#'); - if (fragment == NULL) { /* no fragment */ - request_url->args.data = args; - request_url->args.len = last - args; - } else { - request_url->args.data = args; - request_url->args.len = fragment - args; - ++fragment; - if (fragment == last) { /* fragment error */ - return NGX_ERROR; - } - - request_url->fragment.data = fragment; - request_url->fragment.len = last - fragment; - } - - request_url->uri_with_args.data = path; - request_url->uri_with_args.len = last - path; - -done: - return NGX_OK; -} - -in_port_t -ngx_request_port(ngx_str_t *scheme, ngx_str_t *port) -{ - ngx_int_t p; - ngx_scheme_port_t *sp; - - if (port->len) { - p = ngx_atoi(port->data, port->len); - if (p < 1 || p > 65535) { /* invalid port */ - return 0; - } - - return p; - } - - for (sp = ngx_sheme_port; sp->port != 0; ++sp) { - if (sp->scheme.len == scheme->len - && ngx_memcmp(sp->scheme.data, scheme->data, scheme->len) == 0) - { - return sp->port; - } - } - - return 0; -} - -ngx_int_t -ngx_md5_file(ngx_fd_t fd, u_char md5key[NGX_MD5KEY_LEN]) -{ - ngx_md5_t ctx; - u_char buf[FILEBUFSIZE]; - u_char md5[16]; - ssize_t n; - ngx_uint_t i; - u_char *p; - - ngx_md5_init(&ctx); - - for (;;) { - n = ngx_read_fd(fd, buf, FILEBUFSIZE); - - if (n == 0) { /* read eof of file */ - break; - } - - if (n == NGX_FILE_ERROR) { - return NGX_ERROR; - } - - ngx_md5_update(&ctx, buf, n); - } - - ngx_md5_final(md5, &ctx); - - p = md5key; - for (i = 0; i < 16; ++i) { - p = ngx_sprintf(p, "%02xi", md5[i]); - } - - return NGX_OK; -} - -ngx_int_t -ngx_copy_str(ngx_pool_t *pool, ngx_str_t *dst, ngx_str_t *src) -{ - if (src->len == 0) { - return NGX_OK; - } - - dst->len = src->len; - dst->data = ngx_palloc(pool, src->len); - if (dst->data == NULL) { - return NGX_ERROR; - } - - ngx_memcpy(dst->data, src->data, src->len); - - return NGX_OK; -} - -socklen_t -ngx_sock_pton(struct sockaddr *sa, u_char *text, size_t len) -{ - if (len >= 5 && ngx_strncasecmp(text, (u_char *) "unix:", 5) == 0) { - return ngx_sock_pton_unix(sa, text, len); - } - - if (len && text[0] == '[') { - return ngx_sock_pton_inet6(sa, text, len); - } - - return ngx_sock_pton_inet(sa, text, len); -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_toolkit_misc.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_toolkit_misc.h deleted file mode 100644 index eefeb7704d..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_toolkit_misc.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#ifndef _NGX_TOOLKIT_MISC_H_INCLUDED_ -#define _NGX_TOOLKIT_MISC_H_INCLUDED_ - - -#include -#include - - -/* - * scheme://[user@]host[:port]/path[?args][#fragment] - */ -typedef struct { - ngx_str_t scheme; - ngx_str_t user; - ngx_str_t host; - ngx_str_t port; - ngx_str_t path; - ngx_str_t args; - ngx_str_t fragment; - - ngx_str_t host_with_port; /* host[:port] */ - ngx_str_t uri_with_args; /* /path[?args][#fragment] */ -} ngx_request_url_t; - - -#define NGX_MD5KEY_LEN 32 - - -/* - * parse request url format as: - * scheme://[user@]host[:port]/path[?args][#fragment] - * - * return value: - * NGX_OK : parse success - * NGX_ERROR: request url format error - * paras: - * request_url: url parse result return to user, - * all paras in request url is segment point to url - * url : request url for parse - */ -ngx_int_t ngx_parse_request_url(ngx_request_url_t *request_url, ngx_str_t *url); - -/* - * convert port to in_port_t according to scheme and port - * - * return value: - * If port is set to correct number range in [1, 65535], return port - * If port is set to non correct value, return 0 - * If port is not set, return default value for scheme: - * 80 for http - * 443 for https - * 1935 for rtmp - * 0 for others now - * values: - * scheme : sheme string like http https or rtmp - * port : port for convert to in_port_t - */ -in_port_t ngx_request_port(ngx_str_t *scheme, ngx_str_t *port); - -/* - * calculating file md5key as md5sum in shell - * - * return value: - * NGX_OK : calculating success - * NGX_ERROR: calculating error such as file is not exist - * paras: - * fd : file desc for calculating md5key - * md5key: md5key result - */ -ngx_int_t ngx_md5_file(ngx_fd_t fd, u_char md5key[NGX_MD5KEY_LEN]); - - -/* - * copy str - * - * return value: - * NGX_OK: copy successd - * NGX_ERROR: copy failed - * paras: - * pool: for alloc space for storing str - * dst: str copy to - * src: str copy from - */ -ngx_int_t ngx_copy_str(ngx_pool_t *pool, ngx_str_t *dst, ngx_str_t *src); - - -/* - * parse text to struct sockaddr - * - * return value: - * 0: if text is not ipv4/ipv6/unix address - * >0: socklen for sa - * - * paras: - * sa: struct sockadd parse to - * text: ipv4/ipv6/unix address for parsing, text could have port - * len: text's length - */ -socklen_t ngx_sock_pton(struct sockaddr *sa, u_char *text, size_t len); - - -#ifdef NGX_DEBUG - -#define NGX_START_TIMING \ - struct timeval __start, __end; \ - ngx_gettimeofday(&__start); - -#define NGX_STOP_TIMING(log, msg) \ - ngx_gettimeofday(&__end); \ - ngx_log_error(NGX_LOG_INFO, log, 0, msg " spend %ui us", \ - (__end.tv_sec - __start.tv_sec) * 1000000 \ - + (__end.tv_usec - __start.tv_usec)); - -#else - -#define NGX_START_TIMING -#define NGX_STOP_TIMING(log, msg) - -#endif - -#endif diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/config b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/config deleted file mode 100644 index 23541ea221..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/config +++ /dev/null @@ -1,32 +0,0 @@ -ngx_addon_name=ngx_toolkit_test_module - - -CORE_MODULES="$CORE_MODULES - ngx_dynamic_core_test_module \ - " - -HTTP_MODULES="$HTTP_MODULES \ - ngx_event_timer_test_module \ - ngx_event_resolver_test_module \ - ngx_dynamic_resolver_test_module \ - ngx_dynamic_conf_test_module \ - ngx_http_dynamic_test_module \ - ngx_toolkit_misc_test_module \ - ngx_map_test_module \ - ngx_rbuf_test_module \ - ngx_poold_test_module \ - ngx_timerd_test_module \ - " - -NGX_ADDON_SRCS="$NGX_ADDON_SRCS \ - $ngx_addon_dir/ngx_event_timer_test_module.c \ - $ngx_addon_dir/ngx_event_resolver_test_module.c \ - $ngx_addon_dir/ngx_dynamic_resolver_test_module.c \ - $ngx_addon_dir/ngx_dynamic_conf_test_module.c \ - $ngx_addon_dir/ngx_http_dynamic_test_module.c \ - $ngx_addon_dir/ngx_toolkit_misc_test_module.c \ - $ngx_addon_dir/ngx_map_test_module.c \ - $ngx_addon_dir/ngx_rbuf_test_module.c \ - $ngx_addon_dir/ngx_poold_test_module.c \ - $ngx_addon_dir/ngx_timerd_test_module.c \ - " diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/dns_install.sh b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/dns_install.sh deleted file mode 100644 index 5ba6c24ec6..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/dns_install.sh +++ /dev/null @@ -1,7 +0,0 @@ -#! /bin/bash - -yum install -y bind bind-chroot bind-utils -cp -f named.conf /etc/ -cp -f test.com.zone /var/named/ -chgrp named /etc/named.conf -chgrp named /var/named/test.com.zone diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/md5testfile b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/md5testfile deleted file mode 100644 index 837a6682d6..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/md5testfile +++ /dev/null @@ -1,24 +0,0 @@ -Copyright (C) 2016-2020, by Jie Wu "AlexWoo" . -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -SUCH DAMAGE. - diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/named.conf b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/named.conf deleted file mode 100644 index 79e0d0f67a..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/named.conf +++ /dev/null @@ -1,25 +0,0 @@ -options { - directory "/var/named"; - recursion no; -}; - -logging { - channel default_debug { - file "data/named.run"; - severity dynamic; - }; -}; - -zone "test.com." { - type master; - file "test.com.zone"; -}; - -zone "test1.com." { - type master; - file "test1.com.zone"; -}; - -include "/etc/named.rfc1912.zones"; -include "/etc/named.root.key"; - diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/nginx.conf b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/nginx.conf deleted file mode 100644 index b7d89ce44b..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/nginx.conf +++ /dev/null @@ -1,94 +0,0 @@ - -user root; -worker_processes 1; - -#error_log logs/error.log; -#error_log logs/error.log notice; -error_log logs/error.log info; -#error_log logs/error.log debug; - -#pid logs/nginx.pid; - -dynamic_conf conf/nginx_dynamic.conf 10; -dynamic_log logs/error_dynamic.log info; - -events { - worker_connections 1024; - worker_timers 1024; - resolver 192.168.84.254 valid=20s; - resolver_timeout 10s; - dynamic_refresh_interval 5m; -} - -http { - include mime.types; - default_type application/octet-stream; - - sendfile on; - - keepalive_timeout 65; - - server { - listen 80; - server_name localhost; - - location /trace1/ { - proxy_http_version 1.1; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header Connection ""; - proxy_set_header X-NTM-Parentid $ntm_currentid; - proxy_set_header X-NTM-Currentid $ntm_newid; - proxy_pass http://127.0.0.1/trace/; - } - - location /trace/ { - echo $http_x_ntm_traceid; - echo $http_x_ntm_currentid; - echo $http_x_ntm_parentid; - echo $http_x_ntm_debug; - echo "trace variables"; - echo $ntm_traceid; - echo $ntm_currentid; - echo $ntm_parentid; - echo $ntm_debug; - } - - location /event_timer_test/ { - event_timer_test; - } - - location /event_resolver_test/ { - event_resolver_test; - } - - location /dynamic_resolver_test/ { - dynamic_resolver_test 192.168.84.4 www.test1.com; - } - - location /dynamic_conf_test/ { - dynamic_conf_test; - } - - location / { - http_dynamic_test; - } - - location /map_test/ { - map_test; - } - - location /toolkit_misc_test/ { - toolkit_misc_test; - } - - location /rbuf_test/ { - rbuf_test; - } - - location /poold_test/ { - poold_test; - } - } -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/nginx_dynamic.conf b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/nginx_dynamic.conf deleted file mode 100644 index 6bef7d59b2..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/nginx_dynamic.conf +++ /dev/null @@ -1,74 +0,0 @@ -dynamic_test_i 200; -dynamic_test_s hello_world; - -http { - main_int 1000; - main_str gogogo; - - #defult server - server { - srv_int 1; - srv_str default; - } - - #wildcard_head - server { - srv_int 2; - srv_str wildcard_head; - server_name *.baidu.com; - } - - #wildcard_tail - server { - srv_int 3; - srv_str wildcard_tail; - server_name www.google.*; - } - - #hash - server { - srv_int 4; - srv_str hash; - server_name sports.sina.com.cn; - - location = / { - loc_int 1; - loc_str =/; - } - - location / { - loc_int 2; - loc_str /; - } - - location ^~ /test1/ { - loc_int 3; - loc_str ^~/test1/; - } - - location ~* \.(gif|jpg|jpeg)$ { - loc_int 4; - loc_str ~*\.(gif|jpg|jpeg)$; - } - - location /test { - loc_int 5; - loc_str /test; - } - } - - #pcre - server { - srv_int 5; - srv_str pcre; - server_name ~^flv(?!.*(dl\.))[A-Za-z0-9]*\.test\.com$; - } - - #multi - server { - srv_int 6; - srv_str multi; - server_name ~^flv(?!.*(dl\.))[A-Za-z0-9]*\.haha\.com$ www.sohu.com; - server_name *.qq.com; - } -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_dynamic_conf_test_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_dynamic_conf_test_module.c deleted file mode 100644 index ec24ad39c9..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_dynamic_conf_test_module.c +++ /dev/null @@ -1,200 +0,0 @@ -#include -#include -#include -#include "ngx_dynamic_conf.h" - - -/******************************************************************************/ -static void *ngx_dynamic_core_test_create_conf(ngx_conf_t *cf); -static char *ngx_dynamic_core_test_init_conf(ngx_conf_t *cf, void *conf); - - -typedef struct { - ngx_uint_t i; - ngx_str_t s; -} ngx_dynamic_core_test_conf_t; - - -ngx_core_module_t ngx_dynamic_core_test_module_ctx = { - ngx_string("dynamic_core_test"), - NULL, - NULL -}; - -static ngx_command_t ngx_dynamic_core_test_dcommands[] = { - - { ngx_string("dynamic_test_i"), - NGX_MAIN_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - 0, - offsetof(ngx_dynamic_core_test_conf_t, i), - NULL }, - - { ngx_string("dynamic_test_s"), - NGX_MAIN_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, - 0, - offsetof(ngx_dynamic_core_test_conf_t, s), - NULL }, - - ngx_null_command -}; - - -static ngx_dynamic_core_module_t ngx_dynamic_core_test_module_dctx = { - ngx_string("dynamic_core_test"), - ngx_dynamic_core_test_create_conf, - ngx_dynamic_core_test_init_conf -}; - - -ngx_module_t ngx_dynamic_core_test_module = { - NGX_MODULE_V1, - &ngx_dynamic_core_test_module_ctx, /* module context */ - NULL, /* module directives */ - NGX_CORE_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - (uintptr_t) &ngx_dynamic_core_test_module_dctx, /* module dynamic context */ - (uintptr_t) ngx_dynamic_core_test_dcommands, /* module dynamic directives */ - NGX_MODULE_V1_DYNAMIC_PADDING -}; - - -static void * -ngx_dynamic_core_test_create_conf(ngx_conf_t *cf) -{ - ngx_dynamic_core_test_conf_t *conf; - - conf = ngx_pcalloc(cf->pool, sizeof(ngx_dynamic_core_test_conf_t)); - if (conf == NULL) { - return NULL; - } - - conf->i = NGX_CONF_UNSET_UINT; - - return conf; -} - - -static char * -ngx_dynamic_core_test_init_conf(ngx_conf_t *cf, void *conf) -{ - ngx_dynamic_core_test_conf_t *dctcf; - - dctcf = conf; - - ngx_conf_init_uint_value(dctcf->i, 1000); - - return NGX_CONF_OK; -} -/******************************************************************************/ - - -static char *ngx_dynamic_conf_test(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); - - -#define MAXBUFSIZE 4096 - - -static ngx_command_t ngx_dynamic_conf_test_commands[] = { - - { ngx_string("dynamic_conf_test"), - NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, - ngx_dynamic_conf_test, - 0, - 0, - NULL }, - - ngx_null_command -}; - - -static ngx_http_module_t ngx_dynamic_conf_test_module_ctx = { - NULL, /* preconfiguration */ - NULL, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - NULL, /* create location configuration */ - NULL /* merge location configuration */ -}; - - -ngx_module_t ngx_dynamic_conf_test_module = { - NGX_MODULE_V1, - &ngx_dynamic_conf_test_module_ctx, /* module context */ - ngx_dynamic_conf_test_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static ngx_int_t -ngx_dynamic_conf_test_handler(ngx_http_request_t *r) -{ - ngx_chain_t cl; - ngx_buf_t *b; - ngx_dynamic_core_test_conf_t *dctcf; - - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "dynamic conf test handler"); - - b = ngx_create_temp_buf(r->pool, MAXBUFSIZE); - - if (b == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - dctcf = (ngx_dynamic_core_test_conf_t *) - ngx_get_dconf(&ngx_dynamic_core_test_module); - if (dctcf == NULL) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, - "dynamic conf test handler, dynamic conf not configured"); - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - r->headers_out.status = NGX_HTTP_OK; - - ngx_http_send_header(r); - - b->last = ngx_snprintf(b->last, MAXBUFSIZE, "dynamic core test %ui [%V]\n", - dctcf->i, &dctcf->s); - b->last_buf = 1; - b->last_in_chain = 1; - - cl.buf = b; - cl.next = NULL; - - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "send body"); - - return ngx_http_output_filter(r, &cl); -} - - -static char * -ngx_dynamic_conf_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_core_loc_conf_t *clcf; - - clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); - clcf->handler = ngx_dynamic_conf_test_handler; - - return NGX_CONF_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_dynamic_resolver_test_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_dynamic_resolver_test_module.c deleted file mode 100644 index 4bd53c95e0..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_dynamic_resolver_test_module.c +++ /dev/null @@ -1,193 +0,0 @@ -#include -#include -#include -#include "ngx_dynamic_resolver.h" - - -static char *ngx_dynamic_resolver_test(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); - - -typedef struct { - ngx_flag_t sync; -} ngx_dynamic_resolver_test_ctx_t; - - -static ngx_command_t ngx_dynamic_resolver_test_commands[] = { - - { ngx_string("dynamic_resolver_test"), - NGX_HTTP_LOC_CONF|NGX_CONF_ANY, - ngx_dynamic_resolver_test, - 0, - 0, - NULL }, - - ngx_null_command -}; - - -static ngx_http_module_t ngx_dynamic_resolver_test_module_ctx = { - NULL, /* preconfiguration */ - NULL, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - NULL, /* create location configuration */ - NULL /* merge location configuration */ -}; - - -ngx_module_t ngx_dynamic_resolver_test_module = { - NGX_MODULE_V1, - &ngx_dynamic_resolver_test_module_ctx, /* module context */ - ngx_dynamic_resolver_test_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void -ngx_dynamic_resolver_test_result(void *data, struct sockaddr *sa, socklen_t len) -{ - ngx_dynamic_resolver_test_ctx_t *ctx; - ngx_chain_t cl; - ngx_buf_t *b; - ngx_int_t rc; - ngx_http_request_t *r; - u_char text[NGX_SOCKADDRLEN]; - - r = data; - - r->headers_out.status = NGX_HTTP_OK; - - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "send header"); - - if (len == 0) { - r->headers_out.content_length_n = 0; - r->header_only = 1; - } - - ctx = ngx_http_get_module_ctx(r, ngx_dynamic_resolver_test_module); - if (ctx == NULL) { - ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - return; - } - - rc = ngx_http_send_header(r); - if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { - ngx_http_finalize_request(r, rc); - return; - } - - ngx_memzero(text, sizeof(text)); - len = ngx_sock_ntop(sa, len, text, NGX_SOCKADDRLEN, 0) + 1; - - b = ngx_create_temp_buf(r->pool, len); - - if (b == NULL) { - ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - return; - } - - b->last = ngx_snprintf(b->last, len, "%s\n", text); - b->last_buf = 1; - b->last_in_chain = 1; - - cl.buf = b; - cl.next = NULL; - - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "send body"); - - ngx_http_output_filter(r, &cl); - - if (ctx->sync) { - return; - } - - ngx_http_finalize_request(r, NGX_OK); -} - -static ngx_int_t -ngx_dynamic_resolver_test_handler(ngx_http_request_t *r) -{ - ngx_dynamic_resolver_test_ctx_t *ctx; - ngx_str_t domain, sync; - struct sockaddr sa; - socklen_t len; - - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "dynamic resolver test handler"); - - ctx = ngx_pcalloc(r->pool, sizeof(ngx_dynamic_resolver_test_ctx_t)); - if (ctx == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - ngx_http_set_ctx(r, ctx, ngx_dynamic_resolver_test_module); - - if (ngx_http_arg(r, (u_char *) "domain", 6, &domain) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "dynamic resolver test, no domain in http args"); - return NGX_HTTP_BAD_REQUEST; - } - - if (ngx_http_arg(r, (u_char *) "sync", 4, &sync) == NGX_OK) { - ctx->sync = 1; - } - - if (r->method == NGX_HTTP_GET && ctx->sync == 0) { - r->count++; - ngx_dynamic_resolver_start_resolver(&domain, - ngx_dynamic_resolver_test_result, r); - - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "dynamic resolver test, after start resolver"); - return NGX_DONE; - } else if (r->method == NGX_HTTP_GET && ctx->sync) { - ngx_memzero(&sa, sizeof(sa)); - len = ngx_dynamic_resolver_gethostbyname(&domain, &sa); - ngx_dynamic_resolver_test_result(r, &sa, len); - - return NGX_OK; - } else if (r->method != NGX_HTTP_DELETE) { - return NGX_HTTP_BAD_REQUEST; - } - - ngx_dynamic_resolver_del_domain(&domain); - - r->headers_out.status = NGX_HTTP_OK; - r->headers_out.content_length_n = 0; - r->header_only = 1; - - return ngx_http_send_header(r); -} - - -static char * -ngx_dynamic_resolver_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_core_loc_conf_t *clcf; - ngx_str_t *value; - ngx_uint_t i; - - clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); - clcf->handler = ngx_dynamic_resolver_test_handler; - - value = cf->args->elts; - - for (i = 1; i < cf->args->nelts; ++i) { - ngx_dynamic_resolver_add_domain(&value[i], cf->cycle); - } - - return NGX_CONF_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_event_resolver_test_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_event_resolver_test_module.c deleted file mode 100644 index fbfcb988a8..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_event_resolver_test_module.c +++ /dev/null @@ -1,150 +0,0 @@ -#include -#include -#include -#include "ngx_event_resolver.h" - - -static char *ngx_event_resolver_test(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); - - -static ngx_command_t ngx_event_resolver_test_commands[] = { - - { ngx_string("event_resolver_test"), - NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, - ngx_event_resolver_test, - 0, - 0, - NULL }, - - ngx_null_command -}; - - -static ngx_http_module_t ngx_event_resolver_test_module_ctx = { - NULL, /* preconfiguration */ - NULL, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - NULL, /* create location configuration */ - NULL /* merge location configuration */ -}; - - -ngx_module_t ngx_event_resolver_test_module = { - NGX_MODULE_V1, - &ngx_event_resolver_test_module_ctx, /* module context */ - ngx_event_resolver_test_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void -ngx_event_resolver_test_result(void *data, ngx_resolver_addr_t *addrs, - ngx_uint_t naddrs) -{ - ngx_chain_t *cl, **ll; - ngx_buf_t *b; - size_t len; - ngx_int_t rc; - ngx_uint_t i; - ngx_http_request_t *r; - u_char text[NGX_SOCKADDRLEN]; - - r = data; - - r->headers_out.status = NGX_HTTP_OK; - - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "send header"); - - if (naddrs == 0) { - r->headers_out.content_length_n = 0; - r->header_only = 1; - } - - rc = ngx_http_send_header(r); - if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { - ngx_http_finalize_request(r, rc); - return; - } - - ll = &cl; - for (i = 0; i < naddrs; ++i) { - len = ngx_sock_ntop(addrs[i].sockaddr, addrs[i].socklen, text, - NGX_SOCKADDRLEN, 0) + 1; - - b = ngx_create_temp_buf(r->pool, len); - - if (b == NULL) { - ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - return; - } - - b->last = ngx_snprintf(b->last, len, "%s\n", text); - if (i == naddrs - 1) { - b->last_buf = 1; - b->last_in_chain = 1; - } - - *ll = ngx_alloc_chain_link(r->pool); - (*ll)->buf = b; - (*ll)->next = NULL; - ll = &(*ll)->next; - } - - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "send body"); - - ngx_http_output_filter(r, cl); - - ngx_http_finalize_request(r, NGX_OK); -} - -static ngx_int_t -ngx_event_resolver_test_handler(ngx_http_request_t *r) -{ - ngx_str_t domain; - - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "event resolver test handler"); - - if (ngx_http_arg(r, (u_char *) "domain", sizeof("domain") - 1, &domain) - != NGX_OK) - { - return NGX_HTTP_BAD_REQUEST; - } - - ++r->count; - - ngx_event_resolver_start_resolver(&domain, - ngx_event_resolver_test_result, r); - - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "after start resolver"); - - return NGX_DONE; -} - - -static char * -ngx_event_resolver_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_core_loc_conf_t *clcf; - - clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); - clcf->handler = ngx_event_resolver_test_handler; - - return NGX_CONF_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_event_timer_test_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_event_timer_test_module.c deleted file mode 100644 index 320b803a8f..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_event_timer_test_module.c +++ /dev/null @@ -1,151 +0,0 @@ -#include -#include -#include -#include "ngx_event_timer_module.h" - - -static char *ngx_event_timer_test(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); - -static ngx_command_t ngx_event_timer_test_commands[] = { - - { ngx_string("event_timer_test"), - NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, - ngx_event_timer_test, - 0, - 0, - NULL }, - - ngx_null_command -}; - - -static ngx_http_module_t ngx_event_timer_test_module_ctx = { - NULL, /* preconfiguration */ - NULL, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - NULL, /* create location configuration */ - NULL /* merge location configuration */ -}; - - -ngx_module_t ngx_event_timer_test_module = { - NGX_MODULE_V1, - &ngx_event_timer_test_module_ctx, /* module context */ - ngx_event_timer_test_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void -ngx_event_timer_test_timer_handler(void *data) -{ - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, - "event timer test timer handler"); -} - -static ngx_int_t -ngx_event_timer_test_handler(ngx_http_request_t *r) -{ - ngx_chain_t cl; - ngx_buf_t *b; - size_t len; - ngx_int_t rc, timerid; - ngx_msec_t time; - ngx_str_t arg; - - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, - "event timer test handler"); - - if (r->method == NGX_HTTP_DELETE) { - len = sizeof("delete timer timerid=NGX_OFF_T_LEN\n") - 1; - - if (ngx_http_arg(r, (u_char *) "timerid", 7, &arg) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "event timer test, no timerid in http args"); - return NGX_HTTP_BAD_REQUEST; - } - - timerid = ngx_atoi(arg.data, arg.len); - if (timerid == NGX_ERROR) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "event timer test, timerid arg not int type"); - return NGX_HTTP_BAD_REQUEST; - } - - ngx_event_timer_del_timer(timerid); - } else if (r->method == NGX_HTTP_POST) { - len = sizeof("add timer timerid=NGX_OFF_T_LEN\n") - 1; - - if (ngx_http_arg(r, (u_char *) "time", 4, &arg) != NGX_OK) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "event timer test, no time in http args"); - return NGX_HTTP_BAD_REQUEST; - } - - time = ngx_parse_time(&arg, 0); - if (time == (ngx_msec_t) NGX_ERROR) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "event timer test, time arg not time type"); - return NGX_HTTP_BAD_REQUEST; - } - - timerid = ngx_event_timer_add_timer(time, - ngx_event_timer_test_timer_handler, NULL); - } else { - return NGX_HTTP_BAD_REQUEST; - } - - r->headers_out.status = NGX_HTTP_OK; - - rc = ngx_http_send_header(r); - if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { - return rc; - } - - b = ngx_create_temp_buf(r->pool, len); - - if (b == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - if (r->method == NGX_HTTP_DELETE) { - b->last = ngx_snprintf(b->last, len, - "delete timer timerid=%i\n", timerid); - } else { - b->last = ngx_snprintf(b->last, len, - "add timer timerid=%i\n", timerid); - } - b->last_buf = 1; - b->last_in_chain = 1; - - cl.buf = b; - cl.next = NULL; - - return ngx_http_output_filter(r, &cl); -} - -static char * -ngx_event_timer_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_core_loc_conf_t *clcf; - - clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); - clcf->handler = ngx_event_timer_test_handler; - - return NGX_CONF_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_http_dynamic_test_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_http_dynamic_test_module.c deleted file mode 100644 index eb0f09a834..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_http_dynamic_test_module.c +++ /dev/null @@ -1,300 +0,0 @@ -#include -#include -#include -#include "ngx_dynamic_conf.h" -#include "ngx_http_dynamic.h" - - -static char *ngx_http_dynamic_test(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); - -static void *ngx_http_dynamic_test_create_main_conf(ngx_conf_t *cf); -static char *ngx_http_dynamic_test_init_main_conf(ngx_conf_t *cf, void *conf); -static void *ngx_http_dynamic_test_create_srv_conf(ngx_conf_t *cf); -static char *ngx_http_dynamic_test_init_srv_conf(ngx_conf_t *cf, void *conf); -static void *ngx_http_dynamic_test_create_loc_conf(ngx_conf_t *cf); -static char *ngx_http_dynamic_test_init_loc_conf(ngx_conf_t *cf, void *conf); - -#define MAXBUFSIZE 4096 - -typedef struct { - ngx_uint_t mi; - ngx_str_t ms; -} ngx_http_dynamic_test_main_conf_t; - -typedef struct { - ngx_uint_t si; - ngx_str_t ss; -} ngx_http_dynamic_test_srv_conf_t; - -typedef struct { - ngx_uint_t li; - ngx_str_t ls; -} ngx_http_dynamic_test_loc_conf_t; - - -static ngx_command_t ngx_http_dynamic_test_commands[] = { - - { ngx_string("http_dynamic_test"), - NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, - ngx_http_dynamic_test, - 0, - 0, - NULL }, - - ngx_null_command -}; - -static ngx_http_module_t ngx_http_dynamic_test_module_ctx = { - NULL, /* preconfiguration */ - NULL, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - NULL, /* create location configuration */ - NULL /* merge location configuration */ -}; - -static ngx_command_t ngx_http_dynamic_test_dcommands[] = { - - { ngx_string("main_int"), - NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - 0, - offsetof(ngx_http_dynamic_test_main_conf_t, mi), - NULL }, - - { ngx_string("main_str"), - NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, - 0, - offsetof(ngx_http_dynamic_test_main_conf_t, ms), - NULL }, - - { ngx_string("srv_int"), - NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - 0, - offsetof(ngx_http_dynamic_test_srv_conf_t, si), - NULL }, - - { ngx_string("srv_str"), - NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, - 0, - offsetof(ngx_http_dynamic_test_srv_conf_t, ss), - NULL }, - - { ngx_string("loc_int"), - NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - 0, - offsetof(ngx_http_dynamic_test_loc_conf_t, li), - NULL }, - - { ngx_string("loc_str"), - NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_str_slot, - 0, - offsetof(ngx_http_dynamic_test_loc_conf_t, ls), - NULL }, - - ngx_null_command -}; - -static ngx_http_dynamic_module_t ngx_http_dynamic_test_module_dctx = { - ngx_http_dynamic_test_create_main_conf, /* create main configuration */ - ngx_http_dynamic_test_init_main_conf, /* init main configuration */ - - ngx_http_dynamic_test_create_srv_conf, /* create server configuration */ - ngx_http_dynamic_test_init_srv_conf, /* init server configuration */ - - ngx_http_dynamic_test_create_loc_conf, /* create location configuration */ - ngx_http_dynamic_test_init_loc_conf /* init location configuration */ -}; - -ngx_module_t ngx_http_dynamic_test_module = { - NGX_MODULE_V1, - &ngx_http_dynamic_test_module_ctx, /* module context */ - ngx_http_dynamic_test_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - (uintptr_t) &ngx_http_dynamic_test_module_dctx, /* module dynamic context */ - (uintptr_t) ngx_http_dynamic_test_dcommands, /* module dynamic directives */ - NGX_MODULE_V1_DYNAMIC_PADDING -}; - - -static void * -ngx_http_dynamic_test_create_main_conf(ngx_conf_t *cf) -{ - ngx_http_dynamic_test_main_conf_t *conf; - - conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_dynamic_test_main_conf_t)); - if (conf == NULL) { - return NULL; - } - - conf->mi = NGX_CONF_UNSET_UINT; - - return conf; -} - -static char * -ngx_http_dynamic_test_init_main_conf(ngx_conf_t *cf, void *conf) -{ - ngx_http_dynamic_test_main_conf_t *hdtmcf; - - hdtmcf = conf; - - ngx_conf_init_uint_value(hdtmcf->mi, 100); - - if (hdtmcf->ms.len == 0) { - ngx_str_set(&hdtmcf->ms, "test for ms"); - } - - return NGX_CONF_OK; -} - -static void * -ngx_http_dynamic_test_create_srv_conf(ngx_conf_t *cf) -{ - ngx_http_dynamic_test_srv_conf_t *conf; - - conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_dynamic_test_srv_conf_t)); - if (conf == NULL) { - return NULL; - } - - conf->si = NGX_CONF_UNSET_UINT; - - return conf; -} - -static char * -ngx_http_dynamic_test_init_srv_conf(ngx_conf_t *cf, void *conf) -{ - ngx_http_dynamic_test_srv_conf_t *hdtscf; - - hdtscf = conf; - - ngx_conf_init_uint_value(hdtscf->si, 100); - - if (hdtscf->ss.len == 0) { - ngx_str_set(&hdtscf->ss, "test for ss"); - } - - return NGX_CONF_OK; -} - -static void * -ngx_http_dynamic_test_create_loc_conf(ngx_conf_t *cf) -{ - ngx_http_dynamic_test_loc_conf_t *conf; - - conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_dynamic_test_loc_conf_t)); - if (conf == NULL) { - return NULL; - } - - conf->li = NGX_CONF_UNSET_UINT; - - return conf; -} - -static char * -ngx_http_dynamic_test_init_loc_conf(ngx_conf_t *cf, void *conf) -{ - ngx_http_dynamic_test_loc_conf_t *hdtlcf; - - hdtlcf = conf; - - ngx_conf_init_uint_value(hdtlcf->li, 100); - - if (hdtlcf->ls.len == 0) { - ngx_str_set(&hdtlcf->ls, "test for ls"); - } - - return NGX_CONF_OK; -} - -static ngx_int_t -ngx_http_dynamic_test_handler(ngx_http_request_t *r) -{ - ngx_chain_t cl; - ngx_buf_t *b; - ngx_http_dynamic_test_main_conf_t *hdtmcf; - ngx_http_dynamic_test_srv_conf_t *hdtscf; - ngx_http_dynamic_test_loc_conf_t *hdtlcf; - - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "http dynamic test handler"); - - b = ngx_create_temp_buf(r->pool, MAXBUFSIZE); - - if (b == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - hdtmcf = ngx_http_get_module_main_dconf(r, &ngx_http_dynamic_test_module); - if (hdtmcf == NULL) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, - "dynamic conf test handler, dynamic main conf not configured"); - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - hdtscf = ngx_http_get_module_srv_dconf(r, &ngx_http_dynamic_test_module); - if (hdtscf == NULL) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, - "dynamic conf test handler, dynamic srv conf not configured"); - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - hdtlcf = ngx_http_get_module_loc_dconf(r, &ngx_http_dynamic_test_module); - if (hdtlcf == NULL) { - ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, - "dynamic conf test handler, dynamic loc conf not configured"); - } - - r->headers_out.status = NGX_HTTP_OK; - - ngx_http_send_header(r); - - b->last = ngx_snprintf(b->last, MAXBUFSIZE, - "dynamic core test mi:%ui ms:%V\n", hdtmcf->mi, &hdtmcf->ms); - b->last = ngx_snprintf(b->last, MAXBUFSIZE, - "dynamic core test si:%ui ss:%V\n", hdtscf->si, &hdtscf->ss); - if (hdtlcf) { - b->last = ngx_snprintf(b->last, MAXBUFSIZE, - "dynamic core test li:%ui ls:%V\n", hdtlcf->li, &hdtlcf->ls); - } - b->last_buf = 1; - b->last_in_chain = 1; - - cl.buf = b; - cl.next = NULL; - - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "send body"); - - return ngx_http_output_filter(r, &cl); -} - -static char * -ngx_http_dynamic_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_core_loc_conf_t *clcf; - - clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); - clcf->handler = ngx_http_dynamic_test_handler; - - return NGX_CONF_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_map_test_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_map_test_module.c deleted file mode 100644 index d0762bfe40..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_map_test_module.c +++ /dev/null @@ -1,251 +0,0 @@ -#include -#include -#include -#include "ngx_map.h" -#include "ngx_test_macro.h" - - -static char *ngx_map_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); - - -static ngx_command_t ngx_map_test_commands[] = { - - { ngx_string("map_test"), - NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, - ngx_map_test, - 0, - 0, - NULL }, - - ngx_null_command -}; - - -static ngx_http_module_t ngx_map_test_module_ctx = { - NULL, /* preconfiguration */ - NULL, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - NULL, /* create location configuration */ - NULL /* merge location configuration */ -}; - - -ngx_module_t ngx_map_test_module = { - NGX_MODULE_V1, - &ngx_map_test_module_ctx, /* module context */ - ngx_map_test_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -#define MAP_NODE_INIT_STR(n, k) \ - ngx_map_node_t n; \ - static ngx_str_t k = ngx_string(#k); \ - ngx_memzero(&n, sizeof(ngx_map_node_t)); \ - n.raw_key = (intptr_t) &k; - -#define MAP_NODE_PRINT_KEY_STR(n) \ - { \ - ngx_str_t *s = (ngx_str_t *) (n)->raw_key; \ - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, \ - "!!!!!!!!!!!!!!!!%V", s); \ - } - -static ngx_int_t -ngx_map_test_handler(ngx_http_request_t *r) -{ - ngx_buf_t *b; - ngx_chain_t cl; - size_t len; - ngx_map_t map; - - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "map test handler"); - - ngx_memzero(&map, sizeof(ngx_map_t)); - ngx_map_init(&map, ngx_map_hash_str, ngx_cmp_str); - - MAP_NODE_INIT_STR(n1, k1) - MAP_NODE_INIT_STR(n2, k2) - MAP_NODE_INIT_STR(n3, k3) - MAP_NODE_INIT_STR(n4, k4) - MAP_NODE_INIT_STR(n5, k5) - MAP_NODE_INIT_STR(n6, k6) - MAP_NODE_INIT_STR(n7, k7) - MAP_NODE_INIT_STR(n8, k8) - MAP_NODE_INIT_STR(n9, k9) - MAP_NODE_INIT_STR(n10, k10) - ngx_map_node_t n11; - static ngx_str_t k11 = ngx_string("k5"); - ngx_memzero(&n11, sizeof(ngx_map_node_t)); - n11.raw_key = (intptr_t) &k11; - - ngx_map_insert(&map, &n1, 0); - ngx_map_insert(&map, &n2, 0); - ngx_map_insert(&map, &n3, 0); - ngx_map_insert(&map, &n4, 0); - ngx_map_insert(&map, &n5, 0); - ngx_map_insert(&map, &n6, 0); - ngx_map_insert(&map, &n7, 0); - ngx_map_insert(&map, &n8, 0); - ngx_map_insert(&map, &n9, 0); - ngx_map_insert(&map, &n10, 0); - ngx_map_insert(&map, &n11, 0); - - NGX_TEST_INIT - - ngx_map_node_t *n; - n = ngx_map_begin(&map); - MAP_NODE_PRINT_KEY_STR(n) - NGX_TEST_ISOK(&n1 == n) - - n = ngx_map_next(n); - MAP_NODE_PRINT_KEY_STR(n) - NGX_TEST_ISOK(&n2 == n) - - n = ngx_map_next(n); - MAP_NODE_PRINT_KEY_STR(n) - NGX_TEST_ISOK(&n3 == n) - - n = ngx_map_next(n); - MAP_NODE_PRINT_KEY_STR(n) - NGX_TEST_ISOK(&n4 == n) - - n = ngx_map_next(n); - MAP_NODE_PRINT_KEY_STR(n) - NGX_TEST_ISOK(&n5 == n) - - n = ngx_map_next(n); - MAP_NODE_PRINT_KEY_STR(n) - NGX_TEST_ISOK(&n6 == n) - - n = ngx_map_next(n); - MAP_NODE_PRINT_KEY_STR(n) - NGX_TEST_ISOK(&n7 == n) - - n = ngx_map_next(n); - MAP_NODE_PRINT_KEY_STR(n) - NGX_TEST_ISOK(&n8 == n) - - n = ngx_map_next(n); - MAP_NODE_PRINT_KEY_STR(n) - NGX_TEST_ISOK(&n9 == n) - - n = ngx_map_next(n); - MAP_NODE_PRINT_KEY_STR(n) - NGX_TEST_ISOK(&n10 == n) - - n = ngx_map_next(n); - NGX_TEST_ISOK(NULL == n) - - n = ngx_map_rbegin(&map); - MAP_NODE_PRINT_KEY_STR(n) - NGX_TEST_ISOK(&n10 == n) - - n = ngx_map_prev(n); - MAP_NODE_PRINT_KEY_STR(n) - NGX_TEST_ISOK(&n9 == n) - - n = ngx_map_prev(n); - MAP_NODE_PRINT_KEY_STR(n) - NGX_TEST_ISOK(&n8 == n) - - n = ngx_map_prev(n); - MAP_NODE_PRINT_KEY_STR(n) - NGX_TEST_ISOK(&n7 == n) - - n = ngx_map_prev(n); - MAP_NODE_PRINT_KEY_STR(n) - NGX_TEST_ISOK(&n6 == n) - - n = ngx_map_prev(n); - MAP_NODE_PRINT_KEY_STR(n) - NGX_TEST_ISOK(&n5 == n) - - n = ngx_map_prev(n); - MAP_NODE_PRINT_KEY_STR(n) - NGX_TEST_ISOK(&n4 == n) - - n = ngx_map_prev(n); - MAP_NODE_PRINT_KEY_STR(n) - NGX_TEST_ISOK(&n3 == n) - - n = ngx_map_prev(n); - MAP_NODE_PRINT_KEY_STR(n) - NGX_TEST_ISOK(&n2 == n) - - n = ngx_map_prev(n); - MAP_NODE_PRINT_KEY_STR(n) - NGX_TEST_ISOK(&n1 == n) - - n = ngx_map_prev(n); - NGX_TEST_ISOK(NULL == n) - - static ngx_str_t kk1 = ngx_string("k100"); - NGX_TEST_ISOK(NULL == ngx_map_find(&map, (intptr_t) &kk1)) - - static ngx_str_t kk2 = ngx_string("k5"); - NGX_TEST_ISOK(&n5 == ngx_map_find(&map, (intptr_t) &kk2)) - - ngx_map_insert(&map, &n11, 1); - NGX_TEST_ISOK(&n11 == ngx_map_find(&map, (intptr_t) &kk2)) - - static ngx_str_t kk3 = ngx_string("k8"); - ngx_map_delete(&map, (intptr_t) &kk3); - NGX_TEST_ISOK(NULL == ngx_map_find(&map, (intptr_t) &kk3)) - - static ngx_str_t kk4 = ngx_string("k8"); - ngx_map_insert(&map, &n8, 1); - NGX_TEST_ISOK(&n8 == ngx_map_find(&map, (intptr_t) &kk4)) - - static ngx_str_t kk5 = ngx_string("k7"); - NGX_TEST_ISOK(&n7 == ngx_map_find(&map, (intptr_t) &kk5)) - - r->headers_out.status = NGX_HTTP_OK; - - ngx_http_send_header(r); - - len = sizeof("TEST cases 4294967296, 4294967296 pass\n") - 1; - b = ngx_create_temp_buf(r->pool, len); - - if (b == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - b->last = ngx_snprintf(b->last, len, "TEST cases %d, %d pass\n", - count, pass); - b->last_buf = 1; - b->last_in_chain = 1; - - cl.buf = b; - cl.next = NULL; - - return ngx_http_output_filter(r, &cl); -} - - -static char * -ngx_map_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_core_loc_conf_t *clcf; - - clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); - clcf->handler = ngx_map_test_handler; - - return NGX_CONF_OK; -} - diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_poold_test_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_poold_test_module.c deleted file mode 100644 index da93021d69..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_poold_test_module.c +++ /dev/null @@ -1,90 +0,0 @@ -#include -#include -#include -#include "ngx_poold.h" - - -static char *ngx_poold_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); - - -static ngx_command_t ngx_poold_test_commands[] = { - - { ngx_string("poold_test"), - NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, - ngx_poold_test, - 0, - 0, - NULL }, - - ngx_null_command -}; - - -static ngx_http_module_t ngx_poold_test_module_ctx = { - NULL, /* preconfiguration */ - NULL, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - NULL, /* create location configuration */ - NULL /* merge location configuration */ -}; - - -ngx_module_t ngx_poold_test_module = { - NGX_MODULE_V1, - &ngx_poold_test_module_ctx, /* module context */ - ngx_poold_test_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static ngx_int_t -ngx_poold_test_handler(ngx_http_request_t *r) -{ - ngx_chain_t *out; - ngx_pool_t *pool; - - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "poold test handler"); - - pool = NGX_CREATE_POOL(4096, r->connection->log); - - pool = NGX_CREATE_POOL(1024, r->connection->log); - - NGX_DESTROY_POOL(pool); - - NGX_DESTROY_POOL(pool); - - r->headers_out.status = NGX_HTTP_OK; - ngx_http_send_header(r); - - out = ngx_poold_state(r, 1); - out->buf->last_buf = 1; - - return ngx_http_output_filter(r, out); -} - - -static char * -ngx_poold_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_core_loc_conf_t *clcf; - - clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); - clcf->handler = ngx_poold_test_handler; - - return NGX_CONF_OK; -} - diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_rbuf_test_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_rbuf_test_module.c deleted file mode 100644 index 3a112ecec7..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_rbuf_test_module.c +++ /dev/null @@ -1,116 +0,0 @@ -#include -#include -#include -#include "../ngx_rbuf.h" - - -static char *ngx_rbuf_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); - - -static ngx_command_t ngx_rbuf_test_commands[] = { - - { ngx_string("rbuf_test"), - NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, - ngx_rbuf_test, - 0, - 0, - NULL }, - - ngx_null_command -}; - - -static ngx_http_module_t ngx_rbuf_test_module_ctx = { - NULL, /* preconfiguration */ - NULL, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - NULL, /* create location configuration */ - NULL /* merge location configuration */ -}; - - -ngx_module_t ngx_rbuf_test_module = { - NGX_MODULE_V1, - &ngx_rbuf_test_module_ctx, /* module context */ - ngx_rbuf_test_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static ngx_int_t -ngx_rbuf_test_handler(ngx_http_request_t *r) -{ - ngx_str_t size; - ngx_int_t key; - ngx_chain_t *cl, *cl1, *cl2; - ngx_chain_t *out; - - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "rbuf test handler"); - - if (ngx_http_arg(r, (u_char *) "size", sizeof("size") - 1, &size) - != NGX_OK) - { - return NGX_HTTP_BAD_REQUEST; - } - - key = ngx_atoi(size.data, size.len); - cl = ngx_get_chainbuf(key, 1); - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "cl: %p", cl); - - cl1 = ngx_get_chainbuf(key, 0); - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "cl1: %p", cl1); - cl1->buf->start = cl->buf->start; - cl1->buf->end = cl->buf->end; - cl1->buf->pos = cl->buf->pos; - cl1->buf->last = cl->buf->last; - - cl2 = ngx_get_chainbuf(key, 0); - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "cl2: %p", cl2); - cl2->buf->start = cl->buf->start; - cl2->buf->end = cl->buf->end; - cl2->buf->pos = cl->buf->pos; - cl2->buf->last = cl->buf->last; - - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "rbuf free"); - - ngx_put_chainbuf(cl2); - - ngx_put_chainbuf(cl); - - ngx_put_chainbuf(cl1); - - r->headers_out.status = NGX_HTTP_OK; - ngx_http_send_header(r); - - out = ngx_rbuf_state(r, 1); - out->buf->last_buf = 1; - - return ngx_http_output_filter(r, out); -} - - -static char * -ngx_rbuf_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_core_loc_conf_t *clcf; - - clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); - clcf->handler = ngx_rbuf_test_handler; - - return NGX_CONF_OK; -} - diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_test_macro.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_test_macro.h deleted file mode 100644 index 6da2f68cae..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_test_macro.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com - */ - - -#ifndef _NGX_TEST_MACRO_H_INCLUDE_ -#define _NGX_TEST_MACRO_H_INCLUDE_ - - -#include -#include - - -static ngx_int_t count = 0; -static ngx_int_t pass = 0; - -#define NGX_TEST_INIT count = 0, pass = 0; - -#define NGX_TEST_ISOK(testcase) \ -{ \ - ngx_int_t __ret = testcase; \ - ++count; \ - if (__ret) ++pass; \ - ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, " TEST "#testcase"%s",\ - (__ret ? " ...OK" : " ...ERROR")); \ -} - -#define NGX_TEST_INT(di, si) \ - (di == si) - -static ngx_inline ngx_int_t -ngx_test_str(ngx_str_t *nstr, char *cstr) -{ - size_t len; - - len = ngx_strlen(cstr); - - return (nstr->len == len && ngx_memcmp(nstr->data, cstr, len) == 0); -} - -#endif diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_timerd_test_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_timerd_test_module.c deleted file mode 100644 index df3064960a..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_timerd_test_module.c +++ /dev/null @@ -1,198 +0,0 @@ -#include -#include -#include -#include "ngx_timerd.h" - - -static char *ngx_timerd_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); - - -typedef struct { - ngx_pool_t *pool; - ngx_event_t ev; - ngx_uint_t footprint; -} ngx_timer_test_data_t; - - -static ngx_command_t ngx_timerd_test_commands[] = { - - { ngx_string("timerd_test"), - NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, - ngx_timerd_test, - 0, - 0, - NULL }, - - ngx_null_command -}; - - -static ngx_http_module_t ngx_timerd_test_module_ctx = { - NULL, /* preconfiguration */ - NULL, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - NULL, /* create location configuration */ - NULL /* merge location configuration */ -}; - - -ngx_module_t ngx_timerd_test_module = { - NGX_MODULE_V1, - &ngx_timerd_test_module_ctx, /* module context */ - ngx_timerd_test_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void -ngx_timerd_test_timer(ngx_event_t *ev) -{ - ngx_timer_test_data_t *data; - - data = ev->data; - - ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, "timerd test timer: %p %ui", - data, data->footprint); -} - - -static ngx_int_t -ngx_timerd_test_handler(ngx_http_request_t *r) -{ - ngx_chain_t *out; - - // normal timer trigger - ngx_timer_test_data_t *test; - ngx_pool_t *pool; - - pool = ngx_create_pool(4096, r->connection->log); - test = ngx_pcalloc(pool, sizeof(ngx_timer_test_data_t)); - - test->pool = pool; - test->footprint = ngx_timerd_footprint(); - test->ev.data = test; - test->ev.handler = ngx_timerd_test_timer; - NGX_ADD_TIMER(&test->ev, 5000, offsetof(ngx_timer_test_data_t, footprint)); - - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "!!!!!!!!!!normal timer trigger: %p %ui", test, test->footprint); - - // delete timer twice - ngx_timer_test_data_t *test1; - ngx_pool_t *pool1; - - pool1 = ngx_create_pool(4096, r->connection->log); - test1 = ngx_pcalloc(pool1, sizeof(ngx_timer_test_data_t)); - - test1->pool = pool1; - test1->footprint = ngx_timerd_footprint(); - test1->ev.data = test1; - test1->ev.handler = ngx_timerd_test_timer; - NGX_ADD_TIMER(&test1->ev, 5000, offsetof(ngx_timer_test_data_t, footprint)); - - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "!!!!!!!!!!delete timer twice: %p %ui", test1, test1->footprint); - NGX_DEL_TIMER(&test1->ev, test1->footprint); - NGX_DEL_TIMER(&test1->ev, test1->footprint); - - // timer trigger after event destroy - ngx_timer_test_data_t *test2; - ngx_pool_t *pool2; - - pool2 = ngx_create_pool(4096, r->connection->log); - test2 = ngx_pcalloc(pool2, sizeof(ngx_timer_test_data_t)); - - test2->pool = pool2; - test2->footprint = ngx_timerd_footprint(); - test2->ev.data = test2; - test2->ev.handler = ngx_timerd_test_timer; - NGX_ADD_TIMER(&test2->ev, 5000, offsetof(ngx_timer_test_data_t, footprint)); - - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "!!!!!!!!!!timer trigger after event destroy: %p %ui", - test2, test2->footprint); - test2->footprint = ngx_timerd_footprint(); - - ngx_destroy_pool(pool2); - - // delete timer after event destroy - ngx_timer_test_data_t *test3; - ngx_pool_t *pool3; - - pool3 = ngx_create_pool(4096, r->connection->log); - test3 = ngx_pcalloc(pool3, sizeof(ngx_timer_test_data_t)); - - test3->pool = pool3; - test3->footprint = ngx_timerd_footprint(); - test3->ev.data = test3; - test3->ev.handler = ngx_timerd_test_timer; - NGX_ADD_TIMER(&test3->ev, 5000, offsetof(ngx_timer_test_data_t, footprint)); - - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "!!!!!!!!!!delete timer after event destroy: %p %ui", - test3, test3->footprint); - test3->footprint = ngx_timerd_footprint(); - - NGX_DEL_TIMER(&test3->ev, test3->footprint); - - ngx_destroy_pool(pool3); - - - // add timer after event destroy - ngx_timer_test_data_t *test4; - ngx_pool_t *pool4; - - pool4 = ngx_create_pool(4096, r->connection->log); - test4 = ngx_pcalloc(pool4, sizeof(ngx_timer_test_data_t)); - - test4->pool = pool4; - test4->footprint = ngx_timerd_footprint(); - test4->ev.data = test4; - test4->ev.handler = ngx_timerd_test_timer; - NGX_ADD_TIMER(&test4->ev, 5000, offsetof(ngx_timer_test_data_t, footprint)); - - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "!!!!!!!!!!add timer after event destroy: %p %ui", - test4, test4->footprint); - test4->footprint = ngx_timerd_footprint(); - - NGX_ADD_TIMER(&test4->ev, 5000, offsetof(ngx_timer_test_data_t, footprint)); - - ngx_destroy_pool(pool4); - - - r->headers_out.status = NGX_HTTP_OK; - ngx_http_send_header(r); - - out = ngx_timerd_state(r, 1); - out->buf->last_buf = 1; - - return ngx_http_output_filter(r, out); -} - - -static char * -ngx_timerd_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_core_loc_conf_t *clcf; - - clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); - clcf->handler = ngx_timerd_test_handler; - - return NGX_CONF_OK; -} - diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_toolkit_misc_test_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_toolkit_misc_test_module.c deleted file mode 100644 index 6c58f71ecc..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_toolkit_misc_test_module.c +++ /dev/null @@ -1,285 +0,0 @@ -#include -#include -#include -#include "ngx_toolkit_misc.h" -#include "ngx_test_macro.h" - - -static char *ngx_toolkit_misc_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); - - -static ngx_command_t ngx_toolkit_misc_test_commands[] = { - - { ngx_string("toolkit_misc_test"), - NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, - ngx_toolkit_misc_test, - 0, - 0, - NULL }, - - ngx_null_command -}; - - -static ngx_http_module_t ngx_toolkit_misc_test_module_ctx = { - NULL, /* preconfiguration */ - NULL, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - NULL, /* create location configuration */ - NULL /* merge location configuration */ -}; - - -ngx_module_t ngx_toolkit_misc_test_module = { - NGX_MODULE_V1, - &ngx_toolkit_misc_test_module_ctx, /* module context */ - ngx_toolkit_misc_test_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static ngx_int_t -ngx_parse_toolkit_misc_test(ngx_int_t ret, char *url, char *scheme, char *user, - char *host, char *port, char *path, char *args, char *fragment, - char *host_with_port, char *uri_with_args) -{ - ngx_int_t _ret; - ngx_str_t _url; - ngx_request_url_t rurl; - - ngx_memzero(&rurl, sizeof(ngx_request_url_t)); - _url.data = (u_char *) url; - _url.len = ngx_strlen(url); - - _ret = ngx_parse_request_url(&rurl, &_url); - if (ret != _ret) { - return 0; - } - - if (_ret == NGX_ERROR) { - return 1; - } - -#define TEST(para) \ - if (para == NULL && rurl.para.len) { \ - return 0; \ - } else if (para && ngx_test_str(&rurl.para, para) == NGX_ERROR) { \ - return 0; \ - } - - TEST(scheme) - TEST(user) - TEST(host) - TEST(port) - TEST(path) - TEST(args) - TEST(fragment) - TEST(host_with_port) - TEST(uri_with_args) - -#undef TEST - - return 1; -} - -static ngx_int_t -ngx_request_port_test(in_port_t expect, char *scheme, char *port) -{ - in_port_t ret; - ngx_str_t _scheme, _port; - - _scheme.data = (u_char *) scheme; - _scheme.len = ngx_strlen(scheme); - - _port.data = (u_char *) port; - _port.len = ngx_strlen(port); - - ret = ngx_request_port(&_scheme, &_port); - - return ret == expect; -} - -static ngx_int_t -ngx_toolkit_misc_test_handler(ngx_http_request_t *r) -{ - ngx_buf_t *b; - ngx_chain_t cl; - size_t len; - ngx_fd_t fd; - u_char md5key[NGX_MD5KEY_LEN]; - ngx_str_t file; - - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "request url test handler"); - - NGX_TEST_INIT - - NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_ERROR, "test", - NULL, - NULL, NULL, NULL, - NULL, NULL, NULL, - NULL, NULL)); - NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_ERROR, "http://", - NULL, - NULL, NULL, NULL, - NULL, NULL, NULL, - NULL, NULL)); - NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_ERROR, "http://alex@", - NULL, - NULL, NULL, NULL, - NULL, NULL, NULL, - NULL, NULL)); - NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_OK, "http://alex@test", - "http", - "alex", "test", NULL, - NULL, NULL, NULL, - "test", NULL)); - NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_ERROR, "http://alex@test:", - NULL, - NULL, NULL, NULL, - NULL, NULL, NULL, - NULL, NULL)); - NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_OK, "http://alex@test:8080", - "http", - "alex", "test", "8080", - NULL, NULL, NULL, - "test:8080", NULL)); - NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_ERROR, "http://@test:8080", - NULL, - NULL, NULL, NULL, - NULL, NULL, NULL, - NULL, NULL)); - NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_OK, "http://test", - "http", - NULL, "test", NULL, - NULL, NULL, NULL, - "test", NULL)); - NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_ERROR, "http://test:", - NULL, - NULL, NULL, NULL, - NULL, NULL, NULL, - NULL, NULL)); - NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_OK, "http://test:8080", - "http", - NULL, "test", "8080", - NULL, NULL, NULL, - "test:8080", NULL)); - NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_OK, "http://test:8080/", - "http", - NULL, "test", "8080", - NULL, NULL, NULL, - "test:8080", NULL)); - NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_OK, "http://test:8080/live", - "http", - NULL, "test", "8080", - "live", NULL, NULL, - "test:8080", "live")); - NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_OK, - "http://alex@test/live/test", - "http", - "alex", "test", "8080", - "live/test", NULL, NULL, - "test", "live/test")); - NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_ERROR, - "http://alex@test:80/live/test?", - NULL, - NULL, NULL, NULL, - NULL, NULL, NULL, - NULL, NULL)); - NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_OK, - "http://alex@test:80/live/test?a=b&c=d", - "http", - "alex", "test", "80", - "live/test", "a=b&c=d", NULL, - "test:80", "live/test?a=b&c=d")); - NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_ERROR, - "http://alex@/live/test?a=b&c=d", - NULL, - NULL, NULL, NULL, - NULL, NULL, NULL, - NULL, NULL)); - NGX_TEST_ISOK(ngx_parse_toolkit_misc_test(NGX_OK, - "http://alex@test:8080/live/test?a=b&c=d#test", - "http", - "alex", "test", "8080", - "live/test", "a=b&c=d", "test", - "test:8080", "live/test?a=b&c=d#test")); - - NGX_TEST_ISOK(ngx_request_port_test(0, "", "abcd")); - NGX_TEST_ISOK(ngx_request_port_test(1234, "", "1234")); - NGX_TEST_ISOK(ngx_request_port_test(0, "", "102222")); - NGX_TEST_ISOK(ngx_request_port_test(0, "rtp", "")); - NGX_TEST_ISOK(ngx_request_port_test(80, "http", "")); - NGX_TEST_ISOK(ngx_request_port_test(443, "https", "")); - NGX_TEST_ISOK(ngx_request_port_test(1935, "rtmp", "")); - - file.data = (u_char *) "/usr/local/nginx/conf/md5testfile"; - file.len = sizeof("/usr/local/nginx/conf/md5testfile") - 1; - - fd = ngx_open_file(file.data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); - if (fd == NGX_INVALID_FILE) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno, - ngx_open_file_n " %s failed", file.data); - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - if (ngx_md5_file(fd, md5key)) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "md5 file %V failed", &file); - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - NGX_TEST_ISOK(ngx_memcmp(md5key, "d4309a79dbeaeb6d7811734ce483db59", 32) - == 0); - - ngx_close_file(fd); - - - r->headers_out.status = NGX_HTTP_OK; - - ngx_http_send_header(r); - - len = sizeof("TEST cases 4294967296, 4294967296 pass\n") - 1; - b = ngx_create_temp_buf(r->pool, len); - - if (b == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - b->last = ngx_snprintf(b->last, len, "TEST cases %d, %d pass\n", - count, pass); - b->last_buf = 1; - b->last_in_chain = 1; - - cl.buf = b; - cl.next = NULL; - - return ngx_http_output_filter(r, &cl); -} - - -static char * -ngx_toolkit_misc_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_core_loc_conf_t *clcf; - - clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); - clcf->handler = ngx_toolkit_misc_test_handler; - - return NGX_CONF_OK; -} - diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/test.com.zone b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/test.com.zone deleted file mode 100644 index 6432d87d15..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/test.com.zone +++ /dev/null @@ -1,14 +0,0 @@ -$TTL 3H -@ IN SOA @ wj19840501.gmail.com. ( - 0 ; serial - 1D ; refresh - 1H ; retry - 1W ; expire - 3H ; minimum - ) - -@ IN NS dns -dns IN A 192.168.84.254 -www IN A 1.1.1.1 -www IN A 1.1.1.2 -www IN A 1.1.1.3 diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/test1.com.zone b/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/test1.com.zone deleted file mode 100644 index 27ed83c7f9..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/test1.com.zone +++ /dev/null @@ -1,14 +0,0 @@ -$TTL 3H -@ IN SOA @ wj19840501.gmail.com. ( - 0 ; serial - 1D ; refresh - 1H ; retry - 1W ; expire - 3H ; minimum - ) - -@ IN NS dns -dns IN A 192.168.84.254 -www IN A 1.1.1.4 -www IN A 1.1.1.5 -www IN A 1.1.1.6 diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/LICENSE b/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/LICENSE deleted file mode 100644 index 2bc5ec20be..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -Copyright (C) 2017 Roman Arutyunyan -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/README.rst b/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/README.rst deleted file mode 100644 index b32e846f5e..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/README.rst +++ /dev/null @@ -1,256 +0,0 @@ -************************* -NGINX MPEG-TS Live Module -************************* - - -.. contents:: - - -Features -======== - -- receives MPEG-TS over HTTP -- produces and manages live HLS_ -- produces and manages live MPEG-DASH_ - - -Compatibility -============= - -- `nginx `_ version >= 1.11.5 - - -Build -===== - -Building nginx with the module: - -.. code-block:: bash - - # static module - $ ./configure --add-module=/path/to/nginx-ts-module - - # dynamic module - $ ./configure --add-dynamic-module=/path/to/nginx-ts-module - - -Directives -========== - -ts --- - -========== ======== -*Syntax:* ``ts`` -*Context:* location -========== ======== - -Sets up a live MPEG-TS handler for the location. -This directive is **required** for HLS or MPEG-DASH generation. - -The last URI component is used as a stream name. -For example, if the URI is ``/foo/bar/baz``, the stream name is ``baz``. - -A simple way to stream MPEG-TS over HTTP is by running ``ffmpeg``: - -.. code-block:: bash - - $ ffmpeg ... -f mpegts http://127.0.0.1:8000/foo - - -By default, HTTP request body size is limited in nginx. -To enable live streaming without size limitation, use the directive -``client_max_body_size 0``. - - -ts_hls ------- - -========== ======== -*Syntax:* ``ts_hls path=PATH [segment=MIN[:MAX]] [segments=NUMBER] [max_size=SIZE] [noclean]`` -*Context:* location -========== ======== - -Enables generating live HLS in the location. -The ``PATH`` parameter specifies a directory where HLS playlist and segment -files will be created. -The directory is created if missing. -For every publshed stream a subdirectory with the stream name is created under -the ``PATH`` directory. -The HLS playlist file created in the stream subdirectory is named -``index.m3u8``. -A path handler is installed to watch files in the directory. -The old files in the directory are automatically deleted once they get old -enough and are not supposed to be accessed by clients anymore. -It is not allowed to reuse the path in other ``ts_hls`` or ``ts_dash`` -directives. - -The ``segment`` parameter specifies minimum and maximum segment durations. -If the stream has video, segments are started at video key frames. -If a key frame does not appear within ``MAX`` duration, the segment is -truncated. -The default value for minimum segment duration is 5 seconds. -If unspecified, maximum segment duration is set to be twice as much as the -minimum. - -The ``segments`` parameter specifies the maximum number of segments in a -playlist. -As new segments are added to the playlist, the oldest segments are removed from -it. - -The ``max_size`` parameter specifies the maximum size of a segment. -A segment is truncated once it reaches this size. - -The ``noclean`` parameter indicates that the old files (segments and the -playlist) should not be automatically deleted from disk. - -Example:: - - location / { - ts; - ts_hls path=/var/hls segment=10s; - } - - -ts_dash -------- - -========== ======== -*Syntax:* ``ts_dash path=PATH [segment=MIN[:MAX]] [segments=NUMBER] [max_size=SIZE] [noclean]`` -*Context:* location -========== ======== - -Enables generating live MPEG-DASH in the location. -The ``PATH`` parameter specifies a directory where MPEG-DASH manifest and -segment files will be created. -The directory is created if missing. -For every publshed stream a subdirectory with the stream name is created under -the ``PATH`` directory. -The MPEG-DASH manifest file created in the stream subdirectory is named -``index.mpd``. -A path handler is installed to watch files in the directory. -The old files in the directory are automatically deleted once they get old -enough and are not supposed to be accessed by clients anymore. -It is not allowed to reuse the path in other ``ts_hls`` or ``ts_dash`` -directives. - -The ``segment`` parameter specifies minimum and maximum segment durations. -If the stream has video, segments are started at video key frames. -If a key frame does not appear within ``MAX`` duration, the segment is -truncated. -The default value for minimum segment duration is 5 seconds. -If unspecified, maximum segment duration is set to be twice as much as the -minimum. - - When setting an explicit value for the ``MAX`` parameter, the following - note should be taken into account. - If the next segment is shorter than the previous one by a factor more that - two, dash.js_ can end up in a busy cycle requesting the second segment over - and over again. - -The ``segments`` parameter specifies the maximum number of segments in a -manifest. -As new segments are added to the manifest, the oldest segments are removed from -it. - -The ``max_size`` parameter specifies the maximum size of a segment. -A segment is truncated once it reaches this size. - -The ``noclean`` parameter indicates that the old files (segments and the -manifest) should not be automatically deleted from disk. - -Example:: - - location / { - ts; - ts_dash path=/var/hls segment=10s; - } - - -Example -======= - -nginx.conf:: - - # nginx.conf - - events { - } - - http { - server { - listen 8000; - - location / { - root html; - } - - location /publish/ { - ts; - ts_hls path=/var/media/hls segment=10s; - ts_dash path=/var/media/dash segment=10s; - - client_max_body_size 0; - } - - location /play/ { - types { - application/x-mpegURL m3u8; - application/dash+xml mpd; - video/MP2T ts; - video/mp4 mp4; - } - alias /var/media/; - } - } - } - -HLS in HTML: - -.. code-block:: html - - - - - -MPEG-DASH in HTML using the dash.js_ player: - -.. code-block:: html - - - - - - - -Broadcasting a single-bitrate mp4 file: - -.. code-block:: bash - - $ ffmpeg -re -i ~/Movies/sintel.mp4 -bsf:v h264_mp4toannexb - -c copy -f mpegts http://127.0.0.1:8000/publish/sintel - -Broadcasting an mp4 file in multiple bitrates. -For proper HLS generation streams should be grouped into MPEG-TS programs with -the ``-program`` option of ``ffmpeg``: - -.. code-block:: bash - - $ ffmpeg -re -i ~/Movies/sintel.mp4 -bsf:v h264_mp4toannexb - -map 0:0 -map 0:1 -map 0:0 -map 0:1 - -c:v:0 copy - -c:a:0 copy - -c:v:1 libx264 -b:v:1 100k - -c:a:1 libfaac -ac:a:1 1 -b:a:1 32k - -program "st=0:st=1" -program "st=2:st=3" - -f mpegts http://127.0.0.1:8000/publish/sintel - - -.. _HLS: https://tools.ietf.org/html/draft-pantos-http-live-streaming-23 -.. _MPEG-DASH: https://en.wikipedia.org/wiki/Dynamic_Adaptive_Streaming_over_HTTP -.. _dash.js: https://github.com/Dash-Industry-Forum/dash.js diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/config b/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/config deleted file mode 100644 index aebcdab2c3..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/config +++ /dev/null @@ -1,18 +0,0 @@ -ngx_module_type=HTTP -ngx_addon_name=ngx_http_ts_module -ngx_module_name=ngx_http_ts_module -ngx_module_incs= -ngx_module_deps="$ngx_addon_dir/src/ngx_ts_stream.h \ - $ngx_addon_dir/src/ngx_ts_hls.h \ - $ngx_addon_dir/src/ngx_ts_dash.h \ - $ngx_addon_dir/src/ngx_ts_avc.h \ - $ngx_addon_dir/src/ngx_ts_aac.h" -ngx_module_srcs="$ngx_addon_dir/src/ngx_http_ts_module.c \ - $ngx_addon_dir/src/ngx_ts_stream.c \ - $ngx_addon_dir/src/ngx_ts_hls.c \ - $ngx_addon_dir/src/ngx_ts_dash.c \ - $ngx_addon_dir/src/ngx_ts_dash_mp4.c \ - $ngx_addon_dir/src/ngx_ts_avc.c \ - $ngx_addon_dir/src/ngx_ts_aac.c" - -. auto/module diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_http_ts_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_http_ts_module.c deleted file mode 100644 index 316cf61c6d..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_http_ts_module.c +++ /dev/null @@ -1,263 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include -#include - -#include "ngx_ts_stream.h" -#include "ngx_ts_hls.h" -#include "ngx_ts_dash.h" - - -typedef struct { - ngx_ts_hls_conf_t *hls; - ngx_ts_dash_conf_t *dash; -} ngx_http_ts_loc_conf_t; - - -typedef struct { - ngx_ts_stream_t *ts; -} ngx_http_ts_ctx_t; - - -static ngx_int_t ngx_http_ts_handler(ngx_http_request_t *r); -static void ngx_http_ts_init(ngx_http_request_t *r); -static void ngx_http_ts_read_event_handler(ngx_http_request_t *r); - -static char *ngx_http_ts(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -static void *ngx_http_ts_create_conf(ngx_conf_t *cf); -static char *ngx_http_ts_merge_conf(ngx_conf_t *cf, void *parent, void *child); - - -static ngx_command_t ngx_http_ts_commands[] = { - - { ngx_string("ts"), - NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS, - ngx_http_ts, - 0, - 0, - NULL }, - - { ngx_string("ts_hls"), - NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, - ngx_ts_hls_set_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_ts_loc_conf_t, hls), - NULL }, - - { ngx_string("ts_dash"), - NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, - ngx_ts_dash_set_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_ts_loc_conf_t, dash), - NULL }, - - ngx_null_command -}; - - -static ngx_http_module_t ngx_http_ts_module_ctx = { - NULL, /* preconfiguration */ - NULL, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - NULL, /* create server configuration */ - NULL, /* merge server configuration */ - - ngx_http_ts_create_conf, /* create location configuration */ - ngx_http_ts_merge_conf /* merge location configuration */ -}; - - -ngx_module_t ngx_http_ts_module = { - NGX_MODULE_V1, - &ngx_http_ts_module_ctx, /* module context */ - ngx_http_ts_commands, /* module directives */ - NGX_HTTP_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static ngx_int_t -ngx_http_ts_handler(ngx_http_request_t *r) -{ - ngx_int_t rc; - ngx_str_t name; - ngx_uint_t n; - ngx_http_ts_ctx_t *ctx; - ngx_http_ts_loc_conf_t *tlcf; - - ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_ts_ctx_t)); - if (ctx == NULL) { - return NGX_ERROR; - } - - ctx->ts = ngx_pcalloc(r->pool, sizeof(ngx_ts_stream_t)); - if (ctx->ts == NULL) { - return NGX_ERROR; - } - - ctx->ts->pool = r->pool; - ctx->ts->log = r->connection->log; - - for (n = 0; n < r->uri.len; n++) { - if (r->uri.data[r->uri.len - 1 - n] == '/') { - break; - } - } - - name.data = &r->uri.data[r->uri.len - n]; - name.len = n; - - /* XXX detect streams with the same name, add shared zone */ - - tlcf = ngx_http_get_module_loc_conf(r, ngx_http_ts_module); - - if (tlcf->hls) { - if (ngx_ts_hls_create(tlcf->hls, ctx->ts, &name) == NULL) { - return NGX_ERROR; - } - } - - if (tlcf->dash) { - if (ngx_ts_dash_create(tlcf->dash, ctx->ts, &name) == NULL) { - return NGX_ERROR; - } - } - - ngx_http_set_ctx(r, ctx, ngx_http_ts_module); - - r->request_body_no_buffering = 1; - - rc = ngx_http_read_client_request_body(r, ngx_http_ts_init); - - if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { - return rc; - } - - return NGX_DONE; -} - - -static void -ngx_http_ts_init(ngx_http_request_t *r) -{ - ngx_http_ts_ctx_t *ctx; - ngx_http_request_body_t *rb; - - rb = r->request_body; - - if (rb == NULL) { - ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - return; - } - - ctx = ngx_http_get_module_ctx(r, ngx_http_ts_module); - - if (ngx_ts_read(ctx->ts, rb->bufs) != NGX_OK) { - ngx_http_finalize_request(r, NGX_ERROR); - return; - } - - if (r->reading_body) { - r->read_event_handler = ngx_http_ts_read_event_handler; - } -} - - -static void -ngx_http_ts_read_event_handler(ngx_http_request_t *r) -{ - ngx_int_t rc; - ngx_http_ts_ctx_t *ctx; - ngx_http_request_body_t *rb; - - if (ngx_exiting || ngx_terminate) { - ngx_http_finalize_request(r, NGX_HTTP_CLOSE); - return; - } - - ctx = ngx_http_get_module_ctx(r, ngx_http_ts_module); - - rb = r->request_body; - - for ( ;; ) { - rc = ngx_http_read_unbuffered_request_body(r); - - if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { - ngx_http_finalize_request(r, rc); - return; - } - - if (rb->bufs == NULL) { - return; - } - - if (ngx_ts_read(ctx->ts, rb->bufs) != NGX_OK) { - ngx_http_finalize_request(r, NGX_ERROR); - return; - } - - if (rc == NGX_OK) { - ngx_http_finalize_request(r, NGX_HTTP_NO_CONTENT); - return; - } - - rb->bufs = NULL; - } -} - - -static char * -ngx_http_ts(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_core_loc_conf_t *clcf; - - clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); - clcf->handler = ngx_http_ts_handler; - - return NGX_CONF_OK; -} - - -static void * -ngx_http_ts_create_conf(ngx_conf_t *cf) -{ - ngx_http_ts_loc_conf_t *conf; - - conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ts_loc_conf_t)); - if (conf == NULL) { - return NULL; - } - - conf->hls = NGX_CONF_UNSET_PTR; - conf->dash = NGX_CONF_UNSET_PTR; - - return conf; -} - - -static char * -ngx_http_ts_merge_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_http_ts_loc_conf_t *prev = parent; - ngx_http_ts_loc_conf_t *conf = child; - - ngx_conf_merge_ptr_value(conf->hls, prev->hls, NULL); - ngx_conf_merge_ptr_value(conf->dash, prev->dash, NULL); - - return NGX_CONF_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_stream_ts_module.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_stream_ts_module.c deleted file mode 100644 index aff1447477..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_stream_ts_module.c +++ /dev/null @@ -1,243 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include -#include - -#include "ngx_ts_stream.h" -#include "ngx_ts_hls.h" -#include "ngx_ts_dash.h" - - -typedef struct { - ngx_ts_hls_conf_t *hls; - ngx_ts_dash_conf_t *dash; -} ngx_stream_ts_srv_conf_t; - - -typedef struct { - ngx_ts_stream_t *ts; -} ngx_stream_ts_ctx_t; - - -static void ngx_stream_ts_handler(ngx_stream_session_t *s); -static char *ngx_stream_ts(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -static void *ngx_stream_ts_create_conf(ngx_conf_t *cf); -static char *ngx_stream_ts_merge_conf(ngx_conf_t *cf, void *parent, - void *child); - - -static ngx_command_t ngx_stream_ts_commands[] = { - - { ngx_string("ts"), - NGX_STREAM_SRV_CONF|NGX_CONF_NOARGS, - ngx_stream_ts, - 0, - 0, - NULL }, - - { ngx_string("ts_hls"), - NGX_STREAM_SRV_CONF|NGX_CONF_1MORE, - ngx_ts_hls_set_slot, - NGX_STREAM_SRV_CONF_OFFSET, - offsetof(ngx_stream_ts_srv_conf_t, hls), - NULL }, - - { ngx_string("ts_dash"), - NGX_STREAM_SRV_CONF|NGX_CONF_1MORE, - ngx_ts_dash_set_slot, - NGX_STREAM_SRV_CONF_OFFSET, - offsetof(ngx_stream_ts_srv_conf_t, dash), - NULL }, - - ngx_null_command -}; - - -static ngx_stream_module_t ngx_stream_ts_module_ctx = { - NULL, /* preconfiguration */ - NULL, /* postconfiguration */ - - NULL, /* create main configuration */ - NULL, /* init main configuration */ - - ngx_stream_ts_create_conf, /* create server configuration */ - ngx_stream_ts_merge_conf /* merge server configuration */ -}; - - -ngx_module_t ngx_stream_ts_module = { - NGX_MODULE_V1, - &ngx_stream_ts_module_ctx, /* module context */ - ngx_stream_ts_commands, /* module directives */ - NGX_STREAM_MODULE, /* module type */ - NULL, /* init master */ - NULL, /* init module */ - NULL, /* init process */ - NULL, /* init thread */ - NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ - NGX_MODULE_V1_PADDING -}; - - -static void -ngx_stream_ts_handler(ngx_stream_session_t *s); -{ - ngx_str_t name; - ngx_connection_t *c; - ngx_stream_ts_ctx_t *ctx; - ngx_stream_ts_srv_conf_t *tscf; - - c = s->connection; - - ctx = ngx_pcalloc(c->pool, sizeof(ngx_stream_ts_ctx_t)); - if (ctx == NULL) { - ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR); - return; - } - - ctx->ts = ngx_pcalloc(c->pool, sizeof(ngx_ts_stream_t)); - if (ctx->ts == NULL) { - ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR); - return; - } - - ctx->ts->pool = c->pool; - ctx->ts->log = c->log; - - /* XXX */ - ngx_ste_set(&name, "foo"); - - /* XXX detect streams with the same name, add shared zone */ - - tscf = ngx_stream_get_module_srv_conf(s, ngx_stream_ts_module); - - if (tscf->hls) { - if (ngx_ts_hls_create(tscf->hls, ctx->ts, &name) == NULL) { - ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR); - return; - } - } - - if (tscf->dash) { - if (ngx_ts_dash_create(tscf->dash, ctx->ts, &name) == NULL) { - ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR); - return; - } - } - - ngx_stream_set_ctx(r, ctx, ngx_stream_ts_module); - - c->write->handler = ngx_stream_ts_read_handler; - - ngx_stream_ts_read_handler(c->write); -} - - -static voi -ngx_stream_ts_read_handler(ngx_event_t *rev) -{ - ssize_t n; - ngx_buf_t b; - ngx_chain_t in; - ngx_connection_t *c; - ngx_stream_ts_ctx_t *ctx; - ngx_stream_session_t *s; - u_char buf[4096]; - - c = rev->data; - s = c->data; - - if (ngx_exiting || ngx_terminate) { - ngx_stream_finalize_request(s, NGX_STREAM_OK); - return; - } - - if (rev->timedout) { - ngx_stream_finalize_session(s, NGX_STREAM_OK); - return; - } - - ctx = ngx_stream_get_module_ctx(s, ngx_stream_ts_module); - - in.buf = &b; - in.next = NULL; - - ngx_memzero(&b, sizeof(ngx_buf_t)); - - while (rev->ready) { - n = c->recv(c, buf, sizeof(buf)); - - if (n == NGX_ERROR || n == 0) { - ngx_stream_finalize_session(s, NGX_STREAM_OK); - return; - } - - if (n == NGX_AGAIN) { - break; - } - - b.pos = buf; - b.last = buf + n; - - if (ngx_ts_read(ctx->ts, &in) != NGX_OK) { - ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR); - return; - } - } - - ngx_add_timer(rev, 5000); /* XXX */ - - if (ngx_handle_read_event(rev, 0) != NGX_OK) { - ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR); - return; - } -} - - -static char * -ngx_stream_ts(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_stream_core_srv_conf_t *cscf; - - cscf = ngx_stream_conf_get_module_srv_conf(cf, ngx_stream_core_module); - cscf->handler = ngx_stream_ts_handler; - - return NGX_CONF_OK; -} - - -static void * -ngx_stream_ts_create_conf(ngx_conf_t *cf) -{ - ngx_stream_ts_srv_conf_t *conf; - - conf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_ts_srv_conf_t)); - if (conf == NULL) { - return NULL; - } - - conf->hls = NGX_CONF_UNSET_PTR; - conf->dash = NGX_CONF_UNSET_PTR; - - return conf; -} - - -static char * -ngx_stream_ts_merge_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_stream_ts_srv_conf_t *prev = parent; - ngx_stream_ts_srv_conf_t *conf = child; - - ngx_conf_merge_ptr_value(conf->hls, prev->hls, NULL); - ngx_conf_merge_ptr_value(conf->dash, prev->dash, NULL); - - return NGX_CONF_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_aac.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_aac.c deleted file mode 100644 index b060694c61..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_aac.c +++ /dev/null @@ -1,69 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include - -#include "ngx_ts_aac.h" - - -ngx_ts_aac_params_t * -ngx_ts_aac_decode_params(ngx_ts_stream_t *ts, u_char *adts, size_t adts_len) -{ - /* - * XXX - * https://wiki.multimedia.cx/index.php/ADTS - */ - - ngx_ts_aac_params_t *aac; - - static ngx_uint_t freq[] = { - 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, - 16000, 12000, 11025, 8000, 7350, 0, 0, 0 - }; - - if (adts_len < 7) { - return NULL; - } - - aac = ngx_pcalloc(ts->pool, sizeof(ngx_ts_aac_params_t)); - if (aac == NULL) { - return NULL; - } - - /* MPEG Version: 0 for MPEG-4, 1 for MPEG-2 */ - aac->version = (adts[1] & 0x08) ? 1 : 0; - - /* - * MPEG-4 Audio Object Types: - * 1: AAC Main - * 2: AAC LC (Low Complexity) - * 3: AAC SSR (Scalable Sample Rate) - * 4: AAC LTP (Long Term Prediction) - */ - aac->profile = (adts[2] >> 6) + 1; - - aac->freq_index = (adts[2] >> 2) & 0x0f; - - aac->freq = freq[aac->freq_index]; - if (aac->freq == 0) { - goto failed; - } - - aac->chan = ((adts[2] & 0x01) << 2) | (adts[3] >> 6); - - ngx_log_debug4(NGX_LOG_DEBUG_CORE, ts->log, 0, - "ts aac version:%ui, profile:%ui, freq:%ui, chan:%ui", - aac->version, aac->profile, aac->freq, aac->chan); - - return aac; - -failed: - - ngx_log_error(NGX_LOG_ERR, ts->log, 0, "failed to parse AAC parameters"); - - return NULL; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_aac.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_aac.h deleted file mode 100644 index 4274021a42..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_aac.h +++ /dev/null @@ -1,30 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include - -#include "ngx_ts_stream.h" - - -#ifndef _NGX_TS_AAC_H_INCLUDED_ -#define _NGX_TS_AAC_H_INCLUDED_ - - -typedef struct { - ngx_uint_t version; - ngx_uint_t profile; - ngx_uint_t freq_index; - ngx_uint_t freq; - ngx_uint_t chan; -} ngx_ts_aac_params_t; - - -ngx_ts_aac_params_t *ngx_ts_aac_decode_params(ngx_ts_stream_t *ts, u_char *adts, - size_t adts_len); - - -#endif /* _NGX_TS_AAC_H_INCLUDED_ */ diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_avc.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_avc.c deleted file mode 100644 index 6d22eed903..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_avc.c +++ /dev/null @@ -1,298 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include - -#include "ngx_ts_avc.h" - - -typedef struct { - u_char *pos; - u_char *last; - ngx_uint_t shift; - ngx_uint_t err; /* unsigned err:1; */ - const char *name; - ngx_log_t *log; -} ngx_ts_avc_reader_t; - - -static void ngx_ts_avc_init_reader(ngx_ts_avc_reader_t *br, u_char *buf, - size_t len, ngx_log_t *log); -static uint64_t ngx_ts_avc_read(ngx_ts_avc_reader_t *br, ngx_uint_t bits); -static uint64_t ngx_ts_avc_read_golomb(ngx_ts_avc_reader_t *br); - - -static void -ngx_ts_avc_init_reader(ngx_ts_avc_reader_t *br, u_char *buf, size_t len, - ngx_log_t *log) -{ - ngx_memzero(br, sizeof(ngx_ts_avc_reader_t)); - - br->pos = buf; - br->last = buf + len; - br->log = log; -} - - -static uint64_t -ngx_ts_avc_read(ngx_ts_avc_reader_t *br, ngx_uint_t bits) -{ - uint64_t v; - ngx_uint_t k, n; - - if (br->err) { - return 0; - } - - v = 0; - n = bits; - - while (n) { - if (br->pos == br->last) { - br->err = 1; - break; - } - - k = ngx_min(8 - br->shift, n); - - /* - * [-------------|||||||||--------------] - * br->shift k - */ - - v = (v << k) | (*br->pos & (0xff >> br->shift)) >> (8 - br->shift - k); - - n -= k; - br->shift += k; - - if (br->shift == 8) { - br->shift = 0; - br->pos++; - } - } - - ngx_log_debug3(NGX_LOG_DEBUG_CORE, br->log, 0, - "ts avc %s[%uL]:%uL", br->name, bits, v); - - return v; -} - - -static uint64_t -ngx_ts_avc_read_golomb(ngx_ts_avc_reader_t *br) -{ - /* - * ISO/IEC 14496-10:2004(E) - * 9.1 Parsing process for Exp-Golomb codes, p. 159 - */ - - uint64_t v; - ngx_uint_t n; - - if (br->err) { - return 0; - } - - n = 0; - - while (ngx_ts_avc_read(br, 1) == 0) { - if (br->err) { - return 0; - } - - n++; - } - - v = ((uint64_t) 1 << n) - 1 + ngx_ts_avc_read(br, n); - - ngx_log_debug2(NGX_LOG_DEBUG_CORE, br->log, 0, "ts avc %s:%uL", - br->name, v); - - return v; -} - - -ngx_ts_avc_params_t * -ngx_ts_avc_decode_params(ngx_ts_stream_t *ts, u_char *sps, size_t sps_len, - u_char *pps, size_t pps_len) -{ - /* - * ISO/IEC 14496-10:2004(E) - * 7.3.2.1 Sequence parameter set RBSP syntax, p. 31 - */ - - ngx_uint_t type, n, i; - ngx_ts_avc_reader_t br; - ngx_ts_avc_params_t *avc; - - /* ignore PPS so far */ - - avc = ngx_pcalloc(ts->pool, sizeof(ngx_ts_avc_params_t)); - if (avc == NULL) { - return NULL; - } - - ngx_ts_avc_init_reader(&br, sps, sps_len, ts->log); - - br.name = "nalu_type"; - type = ngx_ts_avc_read(&br, 8); - if ((type & 0x1f) != 7) { - goto failed; - } - - br.name = "profile_idc"; - avc->profile_idc = ngx_ts_avc_read(&br, 8); - - br.name = "constraints"; - avc->constraints = ngx_ts_avc_read(&br, 8); - - br.name = "level_idc"; - avc->level_idc = ngx_ts_avc_read(&br, 8); - - br.name = "seq_parameter_set_id"; - avc->sps_id = ngx_ts_avc_read_golomb(&br); - - if (avc->profile_idc == 100 - || avc->profile_idc == 110 - || avc->profile_idc == 122 - || avc->profile_idc == 244 - || avc->profile_idc == 44 - || avc->profile_idc == 83 - || avc->profile_idc == 86 - || avc->profile_idc == 118 - || avc->profile_idc == 128 - || avc->profile_idc == 138 - || avc->profile_idc == 139 - || avc->profile_idc == 134) - { - br.name = "chroma_format_idc"; - avc->chroma_format_idc = ngx_ts_avc_read_golomb(&br); - - if (avc->chroma_format_idc == 3) { - br.name = - "residual_colour_transform_flagseparate_colour_plane_flag"; - avc->residual_colour_transform_flagseparate_colour_plane_flag = - ngx_ts_avc_read(&br, 1); - } - - br.name = "bit_depth_luma_minus8"; - avc->bit_depth_luma = ngx_ts_avc_read_golomb(&br) + 8; - - br.name = "bit_depth_chroma_minus8"; - avc->bit_depth_chroma = ngx_ts_avc_read_golomb(&br) + 8; - - br.name = "qpprime_y_zero_transform_bypass_flag"; - avc->qpprime_y_zero_transform_bypass_flag = ngx_ts_avc_read(&br, 1); - - br.name = "seq_scaling_matrix_present_flag"; - avc->seq_scaling_matrix_present_flag = ngx_ts_avc_read(&br, 1); - - if (avc->seq_scaling_matrix_present_flag) { - n = (avc->chroma_format_idc != 3) ? 8 : 12; - - for (i = 0; i < n; i++) { - br.name = "seq_scaling_list_present_flag[i]"; - if (ngx_ts_avc_read(&br, 1)) { - goto failed; - } - } - } - } - - br.name = "log2_max_frame_num_minus4"; - avc->max_frame_num = (1 << (ngx_ts_avc_read_golomb(&br) + 4)); - - br.name = "pic_order_cnt_type"; - avc->pic_order_cnt_type = ngx_ts_avc_read_golomb(&br); - - if (avc->pic_order_cnt_type == 0) { - br.name = "log2_max_pic_order_cnt_lsb_minus4"; - avc->max_pic_order_cnt_lsb = (1 << (ngx_ts_avc_read_golomb(&br) + 4)); - - } else if (avc->pic_order_cnt_type == 1) { - br.name = "delta_pic_order_always_zero_flag"; - avc->delta_pic_order_always_zero_flag = ngx_ts_avc_read(&br, 1); - - br.name = "offset_for_non_ref_pic"; - avc->offset_for_non_ref_pic = ngx_ts_avc_read_golomb(&br); - - br.name = "offset_for_top_to_bottom_field"; - avc->offset_for_top_to_bottom_field = ngx_ts_avc_read_golomb(&br); - - br.name = "num_ref_frames_in_pic_order_cnt_cycle"; - n = ngx_ts_avc_read_golomb(&br); - - for (i = 0; i < n; i++) { - br.name = "offset_for_ref_frame[i]"; - (void) ngx_ts_avc_read_golomb(&br); - } - } - - br.name = "num_ref_frames"; - avc->num_ref_frames = ngx_ts_avc_read_golomb(&br); - - br.name = "gaps_in_frame_num_value_allowed_flag"; - avc->gaps_in_frame_num_value_allowed_flag = ngx_ts_avc_read(&br, 1); - - br.name = "pic_width_in_mbs_minus1"; - avc->pic_width_in_mbs = ngx_ts_avc_read_golomb(&br) + 1; - - br.name = "pic_height_in_map_units_minus1"; - avc->pic_height_in_map_units = ngx_ts_avc_read_golomb(&br) + 1; - - br.name = "frame_mbs_only_flag"; - avc->frame_mbs_only_flag = ngx_ts_avc_read(&br, 1); - - if (!avc->frame_mbs_only_flag) { - br.name = "mb_adaptive_frame_field_flag"; - avc->mb_adaptive_frame_field_flag = ngx_ts_avc_read(&br, 1); - } - - br.name = "direct_8x8_inference_flag"; - avc->direct_8x8_inference_flag = ngx_ts_avc_read(&br, 1); - - br.name = "frame_cropping_flag"; - avc->frame_cropping_flag = ngx_ts_avc_read(&br, 1); - - if (avc->frame_cropping_flag) { - br.name = "frame_crop_left_offset"; - avc->frame_crop_left_offset = ngx_ts_avc_read_golomb(&br); - - br.name = "frame_crop_right_offset"; - avc->frame_crop_right_offset = ngx_ts_avc_read_golomb(&br); - - br.name = "frame_crop_top_offset"; - avc->frame_crop_top_offset = ngx_ts_avc_read_golomb(&br); - - br.name = "frame_crop_bottom_offset"; - avc->frame_crop_bottom_offset = ngx_ts_avc_read_golomb(&br); - } - - if (br.err) { - goto failed; - } - - avc->width = - avc->pic_width_in_mbs * 16 - - (avc->frame_crop_left_offset + avc->frame_crop_right_offset) * 2; - - avc->height = - (2 - avc->frame_mbs_only_flag) * avc->pic_height_in_map_units * 16 - - (avc->frame_crop_top_offset + avc->frame_crop_bottom_offset) * 2; - - ngx_log_debug2(NGX_LOG_DEBUG_CORE, ts->log, 0, - "ts avc width:%ui, height:%ui", avc->width, avc->height); - - return avc; - -failed: - - ngx_log_error(NGX_LOG_ERR, ts->log, 0, - "failed to parse AVC parameters"); - - return NULL; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_avc.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_avc.h deleted file mode 100644 index e1fe42ee0a..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_avc.h +++ /dev/null @@ -1,57 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include - -#include "ngx_ts_stream.h" - - -#ifndef _NGX_TS_AVC_H_INCLUDED_ -#define _NGX_TS_AVC_H_INCLUDED_ - - -typedef struct { - ngx_uint_t profile_idc; - ngx_uint_t constraints; - ngx_uint_t level_idc; - ngx_uint_t sps_id; - ngx_uint_t chroma_format_idc; - ngx_uint_t bit_depth_luma; - ngx_uint_t bit_depth_chroma; - ngx_uint_t max_frame_num; - ngx_uint_t pic_order_cnt_type; - ngx_uint_t max_pic_order_cnt_lsb; - ngx_int_t offset_for_non_ref_pic; - ngx_int_t offset_for_top_to_bottom_field; - ngx_uint_t num_ref_frames_in_pic_order_cnt_cycle; - ngx_uint_t num_ref_frames; - ngx_uint_t pic_width_in_mbs; - ngx_uint_t pic_height_in_map_units; - ngx_uint_t frame_crop_left_offset; - ngx_uint_t frame_crop_right_offset; - ngx_uint_t frame_crop_top_offset; - ngx_uint_t frame_crop_bottom_offset; - ngx_uint_t width; - ngx_uint_t height; - - unsigned delta_pic_order_always_zero_flag:1; - unsigned gaps_in_frame_num_value_allowed_flag:1; - unsigned frame_mbs_only_flag:1; - unsigned mb_adaptive_frame_field_flag:1; - unsigned direct_8x8_inference_flag:1; - unsigned frame_cropping_flag:1; - unsigned residual_colour_transform_flagseparate_colour_plane_flag:1; - unsigned qpprime_y_zero_transform_bypass_flag:1; - unsigned seq_scaling_matrix_present_flag:1; -} ngx_ts_avc_params_t; - - -ngx_ts_avc_params_t *ngx_ts_avc_decode_params(ngx_ts_stream_t *ts, u_char *sps, - size_t sps_len, u_char *pps, size_t pps_len); - - -#endif /* _NGX_TS_AVC_H_INCLUDED_ */ diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_dash.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_dash.c deleted file mode 100644 index de8b55d247..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_dash.c +++ /dev/null @@ -1,1426 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include - -#include "ngx_ts_dash.h" - - -#define NGX_TS_DASH_DATETIME_LEN sizeof("2000-12-31T23:59:59Z") -#define NGX_TS_DASH_CODEC_LEN sizeof("avc1.PPPCCCLLL") - - -static void ngx_ts_dash_cleanup(void *data); -static ngx_int_t ngx_ts_dash_handler(ngx_ts_handler_data_t *hd); -static ngx_int_t ngx_ts_dash_pmt_handler(ngx_ts_dash_t *dash); -static ngx_int_t ngx_ts_dash_pes_handler(ngx_ts_dash_t *dash, - ngx_ts_program_t *prog, ngx_ts_es_t *es, ngx_chain_t *in); -static void ngx_ts_dash_update_bandwidth(ngx_ts_dash_t *dash, - ngx_ts_dash_rep_t *rep, ngx_chain_t *in, uint64_t dts); -static ngx_int_t ngx_ts_dash_copy_avc(ngx_ts_dash_t *dash, - ngx_ts_dash_rep_t *rep, ngx_chain_t *in); -static ngx_int_t ngx_ts_dash_copy_aac(ngx_ts_dash_t *dash, - ngx_ts_dash_rep_t *rep, ngx_chain_t *in); -static ngx_int_t ngx_ts_dash_copy_default(ngx_ts_dash_t *dash, - ngx_ts_dash_rep_t *rep, ngx_chain_t *in); -static ngx_int_t ngx_ts_dash_close_segment(ngx_ts_dash_t *dash, - ngx_ts_dash_rep_t *rep); -static ngx_int_t ngx_ts_dash_update_playlist(ngx_ts_dash_t *dash); -static ngx_int_t ngx_ts_dash_write_file(u_char *path1, u_char *path2, - u_char *data, size_t len, ngx_log_t *log); -static void ngx_ts_dash_format_datetime(u_char *p, time_t t); -static void ngx_ts_dash_format_codec(u_char *p, ngx_ts_dash_rep_t *rep); -static ngx_int_t ngx_ts_dash_update_init_segments(ngx_ts_dash_t *dash); -static ngx_int_t ngx_ts_dash_open_segment(ngx_ts_dash_t *dash, - ngx_ts_dash_rep_t *rep); - -static ngx_msec_t ngx_ts_dash_file_manager(void *data); -static ngx_int_t ngx_ts_dash_manage_file(ngx_tree_ctx_t *ctx, ngx_str_t *path); -static ngx_int_t ngx_ts_dash_manage_directory(ngx_tree_ctx_t *ctx, - ngx_str_t *path); -static ngx_int_t ngx_ts_dash_delete_directory(ngx_tree_ctx_t *ctx, - ngx_str_t *path); -static ngx_int_t ngx_ts_dash_delete_file(ngx_tree_ctx_t *ctx, ngx_str_t *path); - - -ngx_ts_dash_t * -ngx_ts_dash_create(ngx_ts_dash_conf_t *conf, ngx_ts_stream_t *ts, - ngx_str_t *name) -{ - size_t len; - ngx_ts_dash_t *dash; - ngx_pool_cleanup_t *cln; - - ngx_log_debug0(NGX_LOG_DEBUG_CORE, ts->log, 0, "ts dash create"); - - dash = ngx_pcalloc(ts->pool, sizeof(ngx_ts_dash_t)); - if (dash == NULL) { - return NULL; - } - - dash->conf = conf; - dash->ts = ts; - dash->playlist_len = 128; - dash->init_seg_len = 256; - - dash->path.len = conf->path->name.len + 1 + name->len; - dash->path.data = ngx_pnalloc(ts->pool, dash->path.len + 1); - if (dash->path.data == NULL) { - return NULL; - } - - ngx_sprintf(dash->path.data, "%V/%V%Z", &conf->path->name, name); - - /* index.mpd */ - - len = dash->path.len + sizeof("/index.mpd"); - - dash->mpd_path = ngx_pnalloc(ts->pool, len); - if (dash->mpd_path == NULL) { - return NULL; - } - - ngx_sprintf(dash->mpd_path, "%V/index.mpd%Z", &dash->path); - - /* index.mpd.tmp */ - - len += sizeof(".tmp") - 1; - - dash->mpd_tmp_path = ngx_pnalloc(ts->pool, len); - if (dash->mpd_tmp_path == NULL) { - return NULL; - } - - ngx_sprintf(dash->mpd_tmp_path, "%s.tmp%Z", dash->mpd_path); - - cln = ngx_pool_cleanup_add(ts->pool, 0); - if (cln == NULL) { - return NULL; - } - - cln->handler = ngx_ts_dash_cleanup; - cln->data = dash; - - if (ngx_ts_add_handler(ts, ngx_ts_dash_handler, dash) != NGX_OK) { - return NULL; - } - - return dash; -} - - -static void -ngx_ts_dash_cleanup(void *data) -{ - ngx_ts_dash_t *dash = data; - - ngx_uint_t i, j; - ngx_ts_dash_set_t *set; - ngx_ts_dash_rep_t *rep; - - ngx_log_debug0(NGX_LOG_DEBUG_CORE, dash->ts->log, 0, "ts dash cleanup"); - - dash->flush = 1; - - for (i = 0; i < dash->nsets; i++) { - set = &dash->sets[i]; - - for (j = 0; j < set->nreps; j++) { - rep = &set->reps[j]; - - if (ngx_ts_dash_close_segment(dash, rep) != NGX_OK) { - return; - } - } - } -} - - -static ngx_int_t -ngx_ts_dash_handler(ngx_ts_handler_data_t *hd) -{ - ngx_ts_dash_t *dash = hd->data; - - switch (hd->event) { - - case NGX_TS_PMT: - return ngx_ts_dash_pmt_handler(dash); - - case NGX_TS_PES: - return ngx_ts_dash_pes_handler(dash, hd->prog, hd->es, hd->bufs); - - default: - return NGX_OK; - } -} - - -static ngx_int_t -ngx_ts_dash_pmt_handler(ngx_ts_dash_t *dash) -{ - size_t len; - ngx_uint_t i, j, n; - ngx_ts_es_t *es; - ngx_ts_stream_t *ts; - ngx_ts_program_t *prog; - ngx_ts_dash_rep_t *rep; - ngx_ts_dash_set_t *set, *aset, *vset; - - if (dash->sets) { - return NGX_OK; - } - - ts = dash->ts; - - ngx_log_debug0(NGX_LOG_DEBUG_CORE, ts->log, 0, "ts dash pmt"); - - n = 0; - - for (i = 0; i < ts->nprogs; i++) { - prog = &ts->progs[i]; - - if (prog->es == NULL) { - return NGX_OK; - } - - n += prog->nes; - } - - dash->nsets = 0; - dash->sets = ngx_pcalloc(ts->pool, 2 * sizeof(ngx_ts_dash_set_t)); - if (dash->sets == NULL) { - return NGX_ERROR; - } - - aset = NULL; - vset = NULL; - - for (i = 0; i < ts->nprogs; i++) { - prog = &ts->progs[i]; - - for (j = 0; j < prog->nes; j++) { - es = &prog->es[j]; - - switch (es->type) { - case NGX_TS_VIDEO_MPEG1: - case NGX_TS_VIDEO_MPEG2: - case NGX_TS_VIDEO_MPEG4: - case NGX_TS_VIDEO_AVC: - if (vset == NULL) { - vset = &dash->sets[dash->nsets++]; - vset->video = 1; - } - - set = vset; - break; - - case NGX_TS_AUDIO_MPEG1: - case NGX_TS_AUDIO_MPEG2: - case NGX_TS_AUDIO_AAC: - if (aset == NULL) { - aset = &dash->sets[dash->nsets++]; - } - - set = aset; - break; - - default: - continue; - } - - if (set->reps == NULL) { - set->nreps = 0; - set->reps = ngx_pcalloc(ts->pool, - n * sizeof(ngx_ts_dash_rep_t)); - if (set->reps == NULL) { - return NGX_ERROR; - } - } - - rep = &set->reps[set->nreps++]; - - rep->es = es; - - rep->nsegs = dash->conf->nsegs; - rep->segs = ngx_pcalloc(ts->pool, - rep->nsegs * sizeof(ngx_ts_dash_segment_t)); - if (rep->segs == NULL) { - return NGX_ERROR; - } - - len = dash->path.len + 1 + NGX_INT_T_LEN + 1 + NGX_INT64_LEN - + sizeof(".mp4"); - - rep->path.data = ngx_pnalloc(ts->pool, len); - if (rep->path.data == NULL) { - return NGX_ERROR; - } - - rep->path.len = ngx_sprintf(rep->path.data, "%V/%ui.", - &dash->path, (ngx_uint_t) es->pid) - - rep->path.data; - - /* init.mp4 */ - - len = dash->path.len + 1 + NGX_INT_T_LEN + sizeof(".init.mp4"); - - rep->init_path = ngx_pnalloc(ts->pool, len); - if (rep->init_path == NULL) { - return NGX_ERROR; - } - - ngx_sprintf(rep->init_path, "%V/%ui.init.mp4%Z", - &dash->path, (ngx_uint_t) es->pid); - - /* init.mp4.tmp */ - - len += sizeof(".tmp") - 1; - - rep->init_tmp_path = ngx_pnalloc(ts->pool, len); - if (rep->init_tmp_path == NULL) { - return NGX_ERROR; - } - - ngx_sprintf(rep->init_tmp_path, "%s.tmp%Z", rep->init_path); - } - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_ts_dash_pes_handler(ngx_ts_dash_t *dash, ngx_ts_program_t *prog, - ngx_ts_es_t *es, ngx_chain_t *in) -{ - ngx_uint_t i, j; - ngx_ts_dash_set_t *set; - ngx_ts_dash_rep_t *rep; - - if (!es->ptsf) { - return NGX_OK; - } - - ngx_log_debug1(NGX_LOG_DEBUG_CORE, dash->ts->log, 0, "ts dash pes pid:%ud", - (unsigned) es->pid); - - for (i = 0; i < dash->nsets; i++) { - set = &dash->sets[i]; - - for (j = 0; j < set->nreps; j++) { - rep = &set->reps[j]; - - if (rep->es == es) { - goto found; - } - } - } - - ngx_log_debug1(NGX_LOG_DEBUG_CORE, dash->ts->log, 0, - "ts dash skip es pid:%ud", (unsigned) es->pid); - - return NGX_OK; - -found: - - ngx_ts_dash_update_bandwidth(dash, rep, in, es->dts); - - if (ngx_ts_dash_close_segment(dash, rep) != NGX_OK) { - return NGX_ERROR; - } - - if (ngx_ts_dash_open_segment(dash, rep) != NGX_OK) { - return NGX_ERROR; - } - - switch (es->type) { - case NGX_TS_VIDEO_AVC: - return ngx_ts_dash_copy_avc(dash, rep, in); - - case NGX_TS_AUDIO_AAC: - return ngx_ts_dash_copy_aac(dash, rep, in); -/* - case NGX_TS_AUDIO_MPEG1: - case NGX_TS_AUDIO_MPEG2: - return ngx_ts_dash_copy_mp3(dash, rep, in); -*/ - - default: - return ngx_ts_dash_copy_default(dash, rep, in); - } -} - - -static void -ngx_ts_dash_update_bandwidth(ngx_ts_dash_t *dash, ngx_ts_dash_rep_t *rep, - ngx_chain_t *in, uint64_t dts) -{ - int64_t d, analyze; - - if (rep->bandwidth) { - return; - } - - if (rep->bandwidth_bytes == 0) { - rep->bandwidth_dts = dts; - } - - while (in) { - rep->bandwidth_bytes += in->buf->last - in->buf->pos; - in = in->next; - } - - d = dts - rep->bandwidth_dts; - analyze = (int64_t) dash->conf->analyze * 90; - - if (d >= analyze) { - rep->bandwidth = rep->bandwidth_bytes * 8 * 90000 / d; - } - - ngx_log_debug2(NGX_LOG_DEBUG_CORE, dash->ts->log, 0, - "ts dash bandwidth:%ui, pid:%ud", - rep->bandwidth, (unsigned) rep->es->pid); -} - - -static ngx_int_t -ngx_ts_dash_copy_avc(ngx_ts_dash_t *dash, ngx_ts_dash_rep_t *rep, - ngx_chain_t *in) -{ - /* - * Source format: - * ISO/IEC 14496-10:2004(E) - * Annex B. Byte Stream Format, p. 216 - * - * Destination format: - * ISO/IEC 14496-15:2004(E) - * 5.3.4.2 Sample format, p. 15 - */ - - size_t n, size, len; - u_char *p, *s, *spec, c, type, buf[4]; - ngx_uint_t z; - ngx_chain_t *cl; - - if (in == NULL) { - return NGX_OK; - } - - p = in->buf->pos; - - size = 0; - - while (in) { - z = 0; - len = 0; - type = 0; - cl = in; - s = p; - - for ( ;; ) { - if (p == in->buf->last) { - in = in->next; - if (in == NULL) { - break; - } - - p = in->buf->pos; - continue; - } - - c = *p++; - - if (c == 0) { - z++; - continue; - } - - if (c == 1 && z >= 2) { - break; - } - - if (z >= 3) { - goto failed; - } - - if (len == 0) { - type = z ? 0 : (c & 0x1f); - } - - len += z + 1; - z = 0; - } - - if (len == 0) { - continue; - } - - if (type == 7 || type == 8) { - if ((type == 7 && rep->sps) || (type == 8 && rep->pps)) { - continue; - } - - if (len > 0xffff) { - goto failed; - } - - spec = ngx_pnalloc(dash->ts->pool, len); - if (spec == NULL) { - return NGX_ERROR; - } - - if (type == 7) { - rep->sps = spec; - rep->sps_len = len; - - } else if (type == 8) { - rep->pps = spec; - rep->pps_len = len; - } - - while (len) { - if (s == cl->buf->last) { - cl = cl->next; - s = cl->buf->pos; - } - - n = ngx_min((size_t) (cl->buf->last - s), len); - - spec = ngx_cpymem(spec, s, n); - - s += n; - len -= n; - } - - if (rep->sps && rep->pps) { - rep->avc = ngx_ts_avc_decode_params(dash->ts, - rep->sps, rep->sps_len, - rep->pps, rep->pps_len); - if (rep->avc == NULL) { - return NGX_ERROR; - } - } - - continue; - } - - buf[0] = len >> 24; - buf[1] = len >> 16; - buf[2] = len >> 8; - buf[3] = len; - - if (ngx_ts_dash_append_data(dash, rep, buf, 4) != NGX_OK) { - return NGX_ERROR; - } - - size += 4; - - while (len) { - if (s == cl->buf->last) { - cl = cl->next; - s = cl->buf->pos; - } - - n = ngx_min((size_t) (cl->buf->last - s), len); - - if (ngx_ts_dash_append_data(dash, rep, s, n) != NGX_OK) { - return NGX_ERROR; - } - - size += n; - s += n; - len -= n; - } - } - - ngx_log_debug2(NGX_LOG_DEBUG_CORE, dash->ts->log, 0, - "ts dash AVC frame:%uz, dts:%uL", size, rep->es->dts); - - return ngx_ts_dash_append_meta(dash, rep, size, rep->es->dts); - -failed: - - ngx_log_error(NGX_LOG_ERR, dash->ts->log, 0, "invalid AVC frame"); - - return NGX_ERROR; - -} - - -static ngx_int_t -ngx_ts_dash_copy_aac(ngx_ts_dash_t *dash, ngx_ts_dash_rep_t *rep, - ngx_chain_t *in) -{ - /* - * XXX - * ISO/IEC CD 14496-3 Subpart 4: 1998 - * 1.1.2 Audio_Data_Transport_Stream frame, ADTS, p. 10 - */ - - size_t len, n; - u_char *p, adts[9]; - uint64_t dts; - ngx_uint_t i; - - if (in == NULL) { - return NGX_OK; - } - - ngx_log_debug1(NGX_LOG_DEBUG_CORE, dash->ts->log, 0, "ts dash AAC ts:%uL", - rep->es->dts); - - i = 0; - - p = in->buf->pos; - - for ( ;; ) { - n = 0; - - /* protection_absent */ - adts[1] = 0; - - while (n < ((adts[1] & 0x01) ? 7 : 9 )) { - if (p == in->buf->last) { - in = in->next; - - if (in == NULL) { - if (n == 0) { - return NGX_OK; - } - - goto failed; - } - - p = in->buf->pos; - continue; - } - - adts[n++] = *p++; - } - - if (rep->aac == NULL) { - rep->aac = ngx_ts_aac_decode_params(dash->ts, adts, 7); - if (rep->aac == NULL) { - return NGX_ERROR; - } - } - - len = adts[3] & 0x03; - len = (len << 8) + adts[4]; - len = (len << 3) + (adts[5] >> 5); - - if (len < n) { - goto failed; - } - - len -= n; - - dts = rep->es->dts + (uint64_t) 90000 * 1024 * i++ / rep->aac->freq; - - ngx_log_debug3(NGX_LOG_DEBUG_CORE, dash->ts->log, 0, - "ts dash AAC adts:%uz, frame:%uz, ts:%uL", n, len, dts); - - if (ngx_ts_dash_append_meta(dash, rep, len, dts) != NGX_OK) { - return NGX_ERROR; - } - - while (len) { - if (p == in->buf->last) { - in = in->next; - if (in == NULL) { - goto failed; - } - - p = in->buf->pos; - } - - n = ngx_min((size_t) (in->buf->last - p), len); - - if (ngx_ts_dash_append_data(dash, rep, p, n) != NGX_OK) { - return NGX_ERROR; - } - - p += n; - len -= n; - } - } - -failed: - - ngx_log_error(NGX_LOG_ERR, dash->ts->log, 0, "invalid AAC ADTS frame"); - - return NGX_ERROR; -} - - -static ngx_int_t -ngx_ts_dash_copy_default(ngx_ts_dash_t *dash, ngx_ts_dash_rep_t *rep, - ngx_chain_t *in) -{ - size_t n, size; - - for (size = 0; in; in = in->next) { - n = in->buf->last - in->buf->pos; - - if (ngx_ts_dash_append_data(dash, rep, in->buf->pos, n) != NGX_OK) { - return NGX_ERROR; - } - - size += n; - } - - return ngx_ts_dash_append_meta(dash, rep, size, rep->es->dts); -} - - -static ngx_int_t -ngx_ts_dash_close_segment(ngx_ts_dash_t *dash, ngx_ts_dash_rep_t *rep) -{ - size_t max_size; - ssize_t n; - int64_t d, min_seg, max_seg; - ngx_err_t err; - ngx_str_t *path; - ngx_file_t file; - ngx_uint_t try; - ngx_chain_t *out; - ngx_ts_es_t *es; - ngx_ts_stream_t *ts; - ngx_ts_dash_segment_t *seg; - - if (rep->meta == NULL) { - return NGX_OK; - } - - ts = dash->ts; - - es = rep->es; - - d = es->dts - rep->seg_dts; - - min_seg = (int64_t) dash->conf->min_seg * 90; - max_seg = (int64_t) dash->conf->max_seg * 90; - max_size = dash->conf->max_size; - - if (!dash->flush) { - if (d < min_seg - || (d < max_seg && es->video && !es->rand)) - { - if (max_size == 0 || rep->nmeta + rep->ndata < max_size) { - return NGX_OK; - } - - ngx_log_error(NGX_LOG_WARN, ts->log, 0, - "closing DASH segment \"%V%uL.mp4\" on size limit", - &rep->path, rep->seg_dts); - } - } - - path = &rep->path; - - ngx_memzero(&file, sizeof(ngx_file_t)); - - file.log = ts->log; - file.name.data = path->data; - file.name.len = ngx_sprintf(path->data + path->len, "%uL.mp4%Z", - rep->seg_dts) - - path->data - 1; - - ngx_log_debug1(NGX_LOG_DEBUG_CORE, ts->log, 0, - "ts dash close segment \"%s\"", file.name.data); - - for (try = 0; /* void */; try++) { - file.fd = ngx_open_file(path->data, - NGX_FILE_WRONLY, - NGX_FILE_TRUNCATE, - NGX_FILE_DEFAULT_ACCESS); - - if (file.fd != NGX_INVALID_FILE) { - break; - } - - err = ngx_errno; - - if (try || (err != NGX_ENOENT && err != NGX_ENOTDIR)) { - ngx_log_error(NGX_LOG_EMERG, ts->log, err, - ngx_open_file_n " \"%s\" failed", path->data); - return NGX_ERROR; - } - - /* XXX dir access mode */ - if (ngx_create_dir(dash->path.data, 0700) == NGX_FILE_ERROR) { - err = ngx_errno; - - if (err != NGX_EEXIST) { - ngx_log_error(NGX_LOG_CRIT, ts->log, err, - ngx_create_dir_n " \"%s\" failed", - dash->path.data); - return NGX_ERROR; - } - } - } - - out = ngx_ts_dash_end_segment(dash, rep); - - n = ngx_write_chain_to_file(&file, out, 0, ts->pool); - - if (ngx_close_file(file.fd) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ALERT, ts->log, ngx_errno, - ngx_close_file_n " \"%s\" failed", path->data); - } - - ngx_ts_dash_free_segment(dash, rep, out); - - if (n == NGX_ERROR) { - return NGX_ERROR; - } - - seg = &rep->segs[rep->seg++ % rep->nsegs]; - seg->start = rep->seg_dts; - seg->duration = d; - - if (ngx_ts_dash_update_playlist(dash) != NGX_OK) { - return NGX_ERROR; - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_ts_dash_update_playlist(ngx_ts_dash_t *dash) -{ - u_char *p, *last, *data; - time_t now; - size_t len; - ngx_uint_t i, j, k, pid, bandwidth, min_update, min_buftime, - buf_depth; - ngx_ts_stream_t *ts; - ngx_ts_dash_set_t *set; - ngx_ts_dash_rep_t *rep; - ngx_ts_dash_segment_t *seg; - u_char codec[NGX_TS_DASH_CODEC_LEN]; - u_char avail_start_time[NGX_TS_DASH_DATETIME_LEN]; - u_char pub_time[NGX_TS_DASH_DATETIME_LEN]; - - if (ngx_ts_dash_update_init_segments(dash) != NGX_OK) { - return NGX_ERROR; - } - - ts = dash->ts; - - ngx_log_debug1(NGX_LOG_DEBUG_CORE, ts->log, 0, - "ts dash update playlist \"%s\"", dash->mpd_path); - - now = ngx_time(); - - if (dash->availability_start == 0) { - dash->availability_start = now; - } - - ngx_ts_dash_format_datetime(avail_start_time, dash->availability_start); - ngx_ts_dash_format_datetime(pub_time, now); - - /* - * timeShiftBufferDepth - * ---------------------------------------- - * | | - * -----///////----------------*-----------------> now - * | | | - * ---------------- ----------------- - * liveDelay lastSegDuration - * = 2 * minBufferTime - * - */ - - min_update = dash->conf->min_seg / 1000; - min_buftime = dash->conf->min_seg / 1000; - buf_depth = 2 * min_buftime + dash->conf->max_seg / 1000 + 1; - - for ( ;; ) { - ngx_log_debug1(NGX_LOG_DEBUG_CORE, ts->log, 0, - "ts dash playlist len:%uz", dash->playlist_len); - - data = ngx_alloc(dash->playlist_len, ts->log); - if (data == NULL) { - return NGX_ERROR; - } - - p = data; - last = data + dash->playlist_len; - - p = ngx_slprintf(p, last, - "\n" - "\n" - " \n", - avail_start_time, pub_time, min_update, min_buftime, buf_depth); - - for (i = 0; i < dash->nsets; i++) { - set = &dash->sets[i]; - - p = ngx_slprintf(p, last, - " \n", - set->video ? "video" : "audio"); - - for (j = 0; j < set->nreps; j++) { - rep = &set->reps[j]; - - if (rep->bandwidth == 0) { - ngx_log_debug0(NGX_LOG_DEBUG_CORE, ts->log, 0, - "ts dash bandwidth not available"); - ngx_free(data); - return NGX_OK; - } - - pid = rep->es->pid; - bandwidth = rep->bandwidth; - - ngx_ts_dash_format_codec(codec, rep); - - p = ngx_slprintf(p, last, - " \n" - " \n" - " \n", - pid, codec, bandwidth); - - for (k = 0; k < rep->nsegs; k++) { - seg = &rep->segs[(rep->seg + k) % rep->nsegs]; - - if (seg->duration) { - p = ngx_slprintf(p, last, - " \n", - seg->start, seg->duration); - } - } - - p = ngx_slprintf(p, last, - " \n" - " \n" - " \n"); - } - - p = ngx_slprintf(p, last, - " \n"); - } - - p = ngx_slprintf(p, last, - " \n" - "\n"); - - if (p != last) { - break; - } - - ngx_free(data); - - dash->playlist_len *= 2; - } - - len = p - data; - - if (ngx_ts_dash_write_file(dash->mpd_tmp_path, dash->mpd_path, data, len, - ts->log) - != NGX_OK) - { - ngx_free(data); - return NGX_ERROR; - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_ts_dash_write_file(u_char *path1, u_char *path2, u_char *data, size_t len, - ngx_log_t *log) -{ - ssize_t n; - ngx_fd_t fd; - ngx_err_t err; - - fd = ngx_open_file(path1, - NGX_FILE_WRONLY, - NGX_FILE_TRUNCATE, - NGX_FILE_DEFAULT_ACCESS); - - if (fd == NGX_INVALID_FILE) { - ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, - ngx_open_file_n " \"%s\" failed", path1); - return NGX_ERROR; - } - - n = ngx_write_fd(fd, data, len); - - err = errno; - - if (ngx_close_file(fd) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, - ngx_close_file_n " \"%s\" failed", path1); - return NGX_ERROR; - } - - if (n < 0) { - ngx_log_error(NGX_LOG_ALERT, log, err, - ngx_write_fd_n " to \"%s\" failed", path1); - return NGX_ERROR; - } - - if ((size_t) n != len) { - ngx_log_error(NGX_LOG_ALERT, log, 0, - "incomplete write to \"%s\"", path1); - return NGX_ERROR; - } - - if (path2) { - if (ngx_rename_file(path1, path2) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, - ngx_rename_file_n " \"%s\" to \"%s\" failed", - path1, path2); - return NGX_ERROR; - } - } - - return NGX_OK; -} - - -static void -ngx_ts_dash_format_datetime(u_char *p, time_t t) -{ - struct tm tm; - - ngx_libc_gmtime(t, &tm); - - if (strftime((char *) p, NGX_TS_DASH_DATETIME_LEN, "%Y-%m-%dT%H:%M:%SZ", - &tm) - == 0) - { - *p = 0; - } -} - - -static void -ngx_ts_dash_format_codec(u_char *p, ngx_ts_dash_rep_t *rep) -{ - ngx_uint_t oti; - - if (rep->avc) { - ngx_sprintf(p, "avc1.%02uXi%02uXi%02uXi%Z", - rep->avc->profile_idc, - rep->avc->constraints, - rep->avc->level_idc); - return; - } - - if (rep->aac) { - ngx_sprintf(p, "mp4a.40.%ui%Z", rep->aac->profile); - return; - } - - oti = ngx_ts_dash_get_oti(rep->es->type); - - ngx_sprintf(p, "mp4%c.%02uXi%Z", rep->es->video ? 'v' : 'a', oti); -} - - -static ngx_int_t -ngx_ts_dash_update_init_segments(ngx_ts_dash_t *dash) -{ - u_char *data; - ngx_buf_t out; - ngx_uint_t i, j; - ngx_ts_stream_t *ts; - ngx_ts_dash_set_t *set; - ngx_ts_dash_rep_t *rep; - - ts = dash->ts; - - for (i = 0; i < dash->nsets; i++) { - set = &dash->sets[i]; - - for (j = 0; j < set->nreps; j++) { - rep = &set->reps[j]; - - if (rep->bandwidth == 0) { - continue; - } - - for ( ;; ) { - ngx_log_debug2(NGX_LOG_DEBUG_CORE, ts->log, 0, - "ts dash write init segment \"%s\", buf:%uz", - rep->init_path, dash->init_seg_len); - - ngx_memzero(&out, sizeof(ngx_buf_t)); - - data = ngx_alloc(dash->init_seg_len, ts->log); - if (data == NULL) { - return NGX_ERROR; - } - - out.start = data; - out.pos = data; - out.last = data; - out.end = data + dash->init_seg_len; - - ngx_ts_dash_write_init_segment(&out, rep); - - if (out.last < out.end) { - break; - } - - ngx_free(data); - - dash->init_seg_len *= 2; - } - - if (ngx_ts_dash_write_file(rep->init_tmp_path, rep->init_path, - out.pos, out.last - out.pos, ts->log) - != NGX_OK) - { - ngx_free(data); - return NGX_ERROR; - } - - ngx_free(data); - } - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_ts_dash_open_segment(ngx_ts_dash_t *dash, ngx_ts_dash_rep_t *rep) -{ - ngx_ts_es_t *es; - - if (rep->meta) { - return NGX_OK; - } - - ngx_log_debug2(NGX_LOG_DEBUG_CORE, dash->ts->log, 0, - "ts dash open segment \"%V%uL.mp4\"", - &rep->path, rep->seg_dts); - - es = rep->es; - - rep->seg_pts = es->pts; - rep->seg_dts = es->dts; - - return ngx_ts_dash_start_segment(dash, rep); -} - - -static ngx_msec_t -ngx_ts_dash_file_manager(void *data) -{ - ngx_ts_dash_conf_t *dash = data; - - ngx_tree_ctx_t tree; - - ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, - "ts dash file manager"); - - tree.init_handler = NULL; - tree.file_handler = ngx_ts_dash_manage_file; - tree.pre_tree_handler = ngx_ts_dash_manage_directory; - tree.post_tree_handler = ngx_ts_dash_delete_directory; - tree.spec_handler = ngx_ts_dash_delete_file; - tree.data = dash; - tree.alloc = 0; - tree.log = ngx_cycle->log; - - (void) ngx_walk_tree(&tree, &dash->path->name); - - return dash->max_seg * dash->nsegs; -} - - -static ngx_int_t -ngx_ts_dash_manage_file(ngx_tree_ctx_t *ctx, ngx_str_t *path) -{ - ngx_ts_dash_conf_t *dash = ctx->data; - - time_t age, max_age; - - age = ngx_time() - ctx->mtime; - - max_age = 0; - - if (path->len >= 4 - && ngx_memcmp(path->data + path->len - 4, ".mpd", 4) == 0) - { - max_age = dash->max_seg * dash->nsegs / 1000; - } - - if (path->len >= 4 - && ngx_memcmp(path->data + path->len - 4, ".mp4", 4) == 0) - { - max_age = dash->max_seg * dash->nsegs / 500; - } - - if (path->len >= 4 - && ngx_memcmp(path->data + path->len - 4, ".tmp", 4) == 0) - { - max_age = 10; - } - - ngx_log_debug3(NGX_LOG_DEBUG_CORE, ctx->log, 0, - "ts dash file \"%s\", age:%T, max_age:%T", - path->data, age, max_age); - - if (age < max_age) { - return NGX_OK; - } - - return ngx_ts_dash_delete_file(ctx, path); -} - - -static ngx_int_t -ngx_ts_dash_manage_directory(ngx_tree_ctx_t *ctx, ngx_str_t *path) -{ - return NGX_OK; -} - - -static ngx_int_t -ngx_ts_dash_delete_directory(ngx_tree_ctx_t *ctx, ngx_str_t *path) -{ - ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->log, 0, - "ts dash delete dir: \"%s\"", path->data); - - /* non-empty directory will not be removed anyway */ - - /* TODO count files instead */ - - (void) ngx_delete_dir(path->data); - - return NGX_OK; -} - - -static ngx_int_t -ngx_ts_dash_delete_file(ngx_tree_ctx_t *ctx, ngx_str_t *path) -{ - ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->log, 0, - "ts dash file delete: \"%s\"", path->data); - - if (ngx_delete_file(path->data) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno, - ngx_delete_file_n " \"%s\" failed", path->data); - } - - return NGX_OK; -} - - -char * -ngx_ts_dash_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - char *p = conf; - - ssize_t max_size; - ngx_str_t *value, s, ss, path; - ngx_int_t v; - ngx_uint_t i, nsegs, clean; - ngx_msec_t min_seg, max_seg, analyze; - ngx_ts_dash_conf_t *dash, **field; - - field = (ngx_ts_dash_conf_t **) (p + cmd->offset); - - if (*field != NGX_CONF_UNSET_PTR) { - return "is duplicate"; - } - - value = cf->args->elts; - - ngx_str_null(&path); - - min_seg = 5000; - max_seg = 10000; - analyze = 0; - max_size = 16 * 1024 * 1024; - nsegs = 6; - clean = 1; - - for (i = 1; i < cf->args->nelts; i++) { - - if (ngx_strncmp(value[i].data, "path=", 5) == 0) { - - path.len = value[i].len - 5; - path.data = value[i].data + 5; - - if (path.data[path.len - 1] == '/') { - path.len--; - } - - if (ngx_conf_full_name(cf->cycle, &path, 0) != NGX_OK) { - return NGX_CONF_ERROR; - } - - continue; - } - - if (ngx_strncmp(value[i].data, "segment=", 8) == 0) { - - s.len = value[i].len - 8; - s.data = value[i].data + 8; - - ss.data = (u_char *) ngx_strchr(s.data, ':'); - - if (ss.data) { - ss.len = s.data + s.len - ss.data - 1; - s.len = ss.data - s.data; - ss.data++; - } - - min_seg = ngx_parse_time(&s, 0); - if (min_seg == (ngx_msec_t) NGX_ERROR) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid segment duration value \"%V\"", - &value[i]); - return NGX_CONF_ERROR; - } - - if (ss.data) { - max_seg = ngx_parse_time(&ss, 0); - if (max_seg == (ngx_msec_t) NGX_ERROR) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid segment duration value \"%V\"", - &value[i]); - return NGX_CONF_ERROR; - } - - } else { - max_seg = min_seg * 2; - } - - continue; - } - - if (ngx_strncmp(value[i].data, "analyze=", 8) == 0) { - - s.len = value[i].len - 8; - s.data = value[i].data + 8; - - analyze = ngx_parse_time(&s, 0); - if (analyze == (ngx_msec_t) NGX_ERROR) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid analyze duration value \"%V\"", - &value[i]); - return NGX_CONF_ERROR; - } - - continue; - } - - if (ngx_strncmp(value[i].data, "max_size=", 9) == 0) { - - s.len = value[i].len - 9; - s.data = value[i].data + 9; - - max_size = ngx_parse_size(&s); - if (max_size == NGX_ERROR) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid max segment size value \"%V\"", - &value[i]); - return NGX_CONF_ERROR; - } - - continue; - } - - if (ngx_strncmp(value[i].data, "segments=", 9) == 0) { - - v = ngx_atoi(value[i].data + 9, value[i].len - 9); - if (v == NGX_ERROR) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid segments number value \"%V\"", - &value[i]); - return NGX_CONF_ERROR; - } - - nsegs = v; - - continue; - } - - if (ngx_strcmp(value[i].data, "noclean") == 0) { - clean = 0; - continue; - } - - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid parameter \"%V\"", &value[i]); - return NGX_CONF_ERROR; - } - - if (path.len == 0) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "\"%V\" must have \"path\" parameter", &cmd->name); - return NGX_CONF_ERROR; - } - - dash = ngx_pcalloc(cf->pool, sizeof(ngx_ts_dash_conf_t)); - if (dash == NULL) { - return NGX_CONF_ERROR; - } - - dash->path = ngx_pcalloc(cf->pool, sizeof(ngx_path_t)); - if (dash->path == NULL) { - return NGX_CONF_ERROR; - } - - dash->path->name = path; - - dash->min_seg = min_seg; - dash->max_seg = max_seg; - dash->analyze = analyze ? analyze : min_seg; - dash->max_size = max_size; - dash->nsegs = nsegs; - - if (clean) { - dash->path->manager = ngx_ts_dash_file_manager; - } - - dash->path->data = dash; - dash->path->conf_file = cf->conf_file->file.name.data; - dash->path->line = cf->conf_file->line; - - if (ngx_add_path(cf, &dash->path) != NGX_OK) { - return NGX_CONF_ERROR; - } - - *field = dash; - - return NGX_CONF_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_dash.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_dash.h deleted file mode 100644 index 5a1a8f5849..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_dash.h +++ /dev/null @@ -1,134 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include - -#include "ngx_ts_stream.h" -#include "ngx_ts_avc.h" -#include "ngx_ts_aac.h" - - -#ifndef _NGX_TS_DASH_H_INCLUDED_ -#define _NGX_TS_DASH_H_INCLUDED_ - - -typedef struct { - ngx_path_t *path; - ngx_msec_t min_seg; - ngx_msec_t max_seg; - ngx_msec_t analyze; - size_t max_size; - ngx_uint_t nsegs; -} ngx_ts_dash_conf_t; - - -typedef struct { - uint64_t start; - uint64_t duration; -} ngx_ts_dash_segment_t; - - -typedef struct { - u_char *dts; /* 64-bit */ - u_char *pts; /* 64-bit */ - u_char *seq; - u_char *duration; - u_char *sample_duration; - u_char *nsamples; - u_char *traf; - u_char *trun; - u_char *moof; - u_char *moof_mdat; - u_char *moof_data; - u_char *mdat; -} ngx_ts_dash_subs_t; - - -typedef struct { - ngx_ts_es_t *es; - - ngx_ts_dash_segment_t *segs; - ngx_uint_t nsegs; - ngx_uint_t seg; - uint64_t seg_pts; - uint64_t seg_dts; - uint64_t dts; - - ngx_uint_t bandwidth; - ngx_uint_t bandwidth_bytes; - uint64_t bandwidth_dts; - - u_char *sps; - u_char *pps; - size_t sps_len; - size_t pps_len; - - ngx_ts_avc_params_t *avc; - ngx_ts_aac_params_t *aac; - - ngx_str_t path; - u_char *init_path; - u_char *init_tmp_path; - - ngx_chain_t *meta; - ngx_chain_t *last_meta; - ngx_chain_t *data; - ngx_chain_t *last_data; - - ngx_uint_t nsamples; - ngx_uint_t nmeta; - ngx_uint_t ndata; - - ngx_ts_dash_subs_t subs; -} ngx_ts_dash_rep_t; - - -typedef struct { - ngx_ts_dash_rep_t *reps; - ngx_uint_t nreps; - ngx_uint_t video; /* unsigned video:1; */ -} ngx_ts_dash_set_t; - - -typedef struct { - ngx_ts_stream_t *ts; - ngx_ts_dash_conf_t *conf; - - u_char *mpd_path; - u_char *mpd_tmp_path; - ngx_str_t path; - size_t playlist_len; - size_t init_seg_len; - time_t availability_start; - - ngx_chain_t *free; - ngx_ts_dash_set_t *sets; - ngx_uint_t nsets; - - ngx_uint_t flush; /* unsigned flush:1; */ -} ngx_ts_dash_t; - - -ngx_ts_dash_t *ngx_ts_dash_create(ngx_ts_dash_conf_t *conf, ngx_ts_stream_t *ts, - ngx_str_t *name); -char *ngx_ts_dash_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); - -void ngx_ts_dash_write_init_segment(ngx_buf_t *b, ngx_ts_dash_rep_t *rep); - -ngx_int_t ngx_ts_dash_start_segment(ngx_ts_dash_t *dash, - ngx_ts_dash_rep_t *rep); -ngx_chain_t *ngx_ts_dash_end_segment(ngx_ts_dash_t *dash, - ngx_ts_dash_rep_t *rep); -void ngx_ts_dash_free_segment(ngx_ts_dash_t *dash, ngx_ts_dash_rep_t *rep, - ngx_chain_t *out); -ngx_int_t ngx_ts_dash_append_meta(ngx_ts_dash_t *dash, ngx_ts_dash_rep_t *rep, - size_t size, uint64_t dts); -ngx_int_t ngx_ts_dash_append_data(ngx_ts_dash_t *dash, ngx_ts_dash_rep_t *rep, - u_char *data, size_t len); - - -#endif /* _NGX_TS_DASH_H_INCLUDED_ */ diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_dash_mp4.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_dash_mp4.c deleted file mode 100644 index 6ed34faa4f..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_dash_mp4.c +++ /dev/null @@ -1,1486 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include - -#include "ngx_ts_dash.h" - - -#define NGX_TS_DASH_BUFFER_SIZE 1024 - -#define NGX_TS_DASH_DEFAULT_WIDTH 400 -#define NGX_TS_DASH_DEFAULT_HEIGHT 400 - - -/* - * ISO base media file format - * ISO/IEC 14496-12:2008(E) - */ - - -static void ngx_ts_dash_box_styp(ngx_buf_t *b); -static void ngx_ts_dash_box_sidx(ngx_buf_t *b, ngx_ts_dash_rep_t *rep); -static void ngx_ts_dash_box_moof(ngx_buf_t *b, ngx_ts_dash_rep_t *rep); -static void ngx_ts_dash_box_mfhd(ngx_buf_t *b, ngx_ts_dash_rep_t *rep); -static void ngx_ts_dash_box_traf(ngx_buf_t *b, ngx_ts_dash_rep_t *rep); -static void ngx_ts_dash_box_tfhd(ngx_buf_t *b); -static void ngx_ts_dash_box_tfdt(ngx_buf_t *b, ngx_ts_dash_rep_t *rep); -static void ngx_ts_dash_box_trun(ngx_buf_t *b, ngx_ts_dash_rep_t *rep); -static void ngx_ts_dash_box_mdat(ngx_buf_t *b, ngx_ts_dash_rep_t *rep); -static void ngx_ts_dash_box_ftyp(ngx_buf_t *b); -static void ngx_ts_dash_box_moov(ngx_buf_t *b, ngx_ts_dash_rep_t *rep); -static void ngx_ts_dash_box_mvhd(ngx_buf_t *b); -static void ngx_ts_dash_box_mvex(ngx_buf_t *b); -static void ngx_ts_dash_box_trex(ngx_buf_t *b); -static void ngx_ts_dash_box_trak(ngx_buf_t *b, ngx_ts_dash_rep_t *rep); -static void ngx_ts_dash_box_tkhd(ngx_buf_t *b, ngx_ts_dash_rep_t *rep); -static void ngx_ts_dash_box_mdia(ngx_buf_t *b, ngx_ts_dash_rep_t *rep); -static void ngx_ts_dash_box_mdhd(ngx_buf_t *b); -static void ngx_ts_dash_box_hdlr(ngx_buf_t *b, ngx_ts_dash_rep_t *rep); -static void ngx_ts_dash_box_minf(ngx_buf_t *b, ngx_ts_dash_rep_t *rep); -static void ngx_ts_dash_box_vmhd(ngx_buf_t *b); -static void ngx_ts_dash_box_smhd(ngx_buf_t *b); -static void ngx_ts_dash_box_dinf(ngx_buf_t *b); -static void ngx_ts_dash_box_dref(ngx_buf_t *b); -static void ngx_ts_dash_box_url(ngx_buf_t *b); -static void ngx_ts_dash_box_stbl(ngx_buf_t *b, ngx_ts_dash_rep_t *rep); -static void ngx_ts_dash_box_stts(ngx_buf_t *b); -static void ngx_ts_dash_box_stsc(ngx_buf_t *b); -static void ngx_ts_dash_box_stsz(ngx_buf_t *b); -static void ngx_ts_dash_box_stco(ngx_buf_t *b); -static void ngx_ts_dash_box_stsd(ngx_buf_t *b, ngx_ts_dash_rep_t *rep); -static void ngx_ts_dash_box_video(ngx_buf_t *b, ngx_ts_dash_rep_t *rep); -static void ngx_ts_dash_box_audio(ngx_buf_t *b, ngx_ts_dash_rep_t *rep); -static void ngx_ts_dash_box_avcc(ngx_buf_t *b, ngx_ts_dash_rep_t *rep); -static void ngx_ts_dash_box_esds(ngx_buf_t *b, ngx_ts_dash_rep_t *rep); - -static u_char *ngx_ts_dash_box(ngx_buf_t *b, const char type[4]); -static u_char *ngx_ts_dash_box_full(ngx_buf_t *b, const char type[4], - u_char version, uint32_t flags); -static void ngx_ts_dash_box_update(ngx_buf_t *b, u_char *p); - -static void ngx_ts_dash_desc_es(ngx_buf_t *b, ngx_ts_dash_rep_t *rep); -static void ngx_ts_dash_desc_dec_conf(ngx_buf_t *b, ngx_ts_dash_rep_t *rep); -static void ngx_ts_dash_desc_dec_spec(ngx_buf_t *b, ngx_ts_dash_rep_t *rep); -static void ngx_ts_dash_desc_sl_conf(ngx_buf_t *b); - -static u_char *ngx_ts_dash_desc(ngx_buf_t *b, u_char tag); -static void ngx_ts_dash_desc_update(ngx_buf_t *b, u_char *p); - -static void ngx_ts_dash_cpymem(ngx_buf_t *b, const void *data, size_t size); -static void ngx_ts_dash_write64(ngx_buf_t *b, uint64_t v); -static void ngx_ts_dash_write32(ngx_buf_t *b, uint32_t v); -static void ngx_ts_dash_write24(ngx_buf_t *b, uint32_t v); -static void ngx_ts_dash_write16(ngx_buf_t *b, uint16_t v); -static void ngx_ts_dash_write8(ngx_buf_t *b, u_char v); - -static void ngx_ts_dash_set_sub(ngx_buf_t *b, u_char **p); -static uint32_t ngx_ts_dash_get32(u_char *p); -static void ngx_ts_dash_put32(u_char *p, uint32_t v); -static void ngx_ts_dash_put64(u_char *p, uint64_t v); - -static ngx_chain_t *ngx_ts_dash_get_buffer(ngx_ts_dash_t *dash); - - -void -ngx_ts_dash_write_init_segment(ngx_buf_t *b, ngx_ts_dash_rep_t *rep) -{ - ngx_ts_dash_box_ftyp(b); - ngx_ts_dash_box_moov(b, rep); -} - - -static void -ngx_ts_dash_box_styp(ngx_buf_t *b) -{ - /* TODO - * ETSI TS 126 244 V12.3.0 (2014-10) - * 13.2 Segment types, p. 52 - */ - - u_char *p; - - p = ngx_ts_dash_box(b, "styp"); - - /* major_brand */ - ngx_ts_dash_cpymem(b, "iso6", 4); /* XXX 3gh9 */ - - /* TODO version */ - /* minor_version */ - ngx_ts_dash_write32(b, 1); - - /* TODO brands */ - /* compatible_brands */ - ngx_ts_dash_cpymem(b, "isom", 4); - ngx_ts_dash_cpymem(b, "iso6", 4); - ngx_ts_dash_cpymem(b, "dash", 4); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_sidx(ngx_buf_t *b, ngx_ts_dash_rep_t *rep) -{ - /* TODO - * ETSI TS 126 244 V12.3.0 (2014-10) - * 13.4 Segment Index Box, p. 53 - */ - - u_char *p; - - p = ngx_ts_dash_box_full(b, "sidx", 1, 0); - - /* reference_ID */ - ngx_ts_dash_write32(b, 1); - - /* timescale */ - ngx_ts_dash_write32(b, 90000); - - /* earliest_presentation_time */ - ngx_ts_dash_set_sub(b, &rep->subs.pts); - ngx_ts_dash_write64(b, 0); - - /* first_offset */ - ngx_ts_dash_write64(b, 0); - - /* reference_count */ - ngx_ts_dash_write32(b, 1); - - /* referenced_size */ - ngx_ts_dash_set_sub(b, &rep->subs.moof_mdat); - ngx_ts_dash_write32(b, 0); - - /* subsegment_duration */ - ngx_ts_dash_set_sub(b, &rep->subs.duration); - ngx_ts_dash_write32(b, 0); - - /* starts_with_SAP, SAP_type, SAP_delta_time */ - ngx_ts_dash_write32(b, 0x80000000); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_moof(ngx_buf_t *b, ngx_ts_dash_rep_t *rep) -{ - u_char *p; - - ngx_ts_dash_set_sub(b, &rep->subs.moof); - - p = ngx_ts_dash_box(b, "moof"); - - ngx_ts_dash_box_mfhd(b, rep); - ngx_ts_dash_box_traf(b, rep); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_mfhd(ngx_buf_t *b, ngx_ts_dash_rep_t *rep) -{ - u_char *p; - - p = ngx_ts_dash_box_full(b, "mfhd", 0, 0); - - /* sequence_number */ - ngx_ts_dash_set_sub(b, &rep->subs.seq); - ngx_ts_dash_write32(b, 0); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_traf(ngx_buf_t *b, ngx_ts_dash_rep_t *rep) -{ - u_char *p; - - ngx_ts_dash_set_sub(b, &rep->subs.traf); - - p = ngx_ts_dash_box(b, "traf"); - - ngx_ts_dash_box_tfhd(b); - ngx_ts_dash_box_tfdt(b, rep); - ngx_ts_dash_box_trun(b, rep); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_tfhd(ngx_buf_t *b) -{ - u_char *p; - - p = ngx_ts_dash_box_full(b, "tfhd", 0, 0); - - /* track_ID */ - ngx_ts_dash_write32(b, 1); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_tfdt(ngx_buf_t *b, ngx_ts_dash_rep_t *rep) -{ - /* - * ETSI TS 126 244 V12.3.0 (2014-10) - * 13.5 Track Fragment Decode Time Box, p. 55 - */ - - u_char *p; - - p = ngx_ts_dash_box_full(b, "tfdt", 1, 0); - - /* baseMediaDecodeTime */ - ngx_ts_dash_set_sub(b, &rep->subs.dts); - ngx_ts_dash_write64(b, 0); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_trun(ngx_buf_t *b, ngx_ts_dash_rep_t *rep) -{ - u_char *p; - uint32_t flags; - - flags = 0x000001 /* data-offset-present */ - | 0x000100 /* sample-duration-present */ - | 0x000200; /* sample-size-present */ - - if (rep->es->video) { - flags |= 0x000400 /* sample-flags-present */ - | 0x000800; /* sample-composition-time-offset-present */ - } - - ngx_ts_dash_set_sub(b, &rep->subs.trun); - - p = ngx_ts_dash_box_full(b, "trun", 0, flags); - - /* sample_count */ - ngx_ts_dash_set_sub(b, &rep->subs.nsamples); - ngx_ts_dash_write32(b, 0); - - /* data_offset */ - ngx_ts_dash_set_sub(b, &rep->subs.moof_data); - ngx_ts_dash_write32(b, 0); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_mdat(ngx_buf_t *b, ngx_ts_dash_rep_t *rep) -{ - u_char *p; - - ngx_ts_dash_set_sub(b, &rep->subs.mdat); - - p = ngx_ts_dash_box(b, "mdat"); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_ftyp(ngx_buf_t *b) -{ - /* - * ISO/IEC 14496-12:2008(E) - * 4.3 File Type Box, p. 4 - */ - - u_char *p; - - p = ngx_ts_dash_box(b, "ftyp"); - - /* major_brand */ - ngx_ts_dash_cpymem(b, "iso6", 4); - - /* minor_version */ - ngx_ts_dash_write32(b, 1); - - /* TODO brands */ - /* compatible_brands */ - ngx_ts_dash_cpymem(b, "isom", 4); - ngx_ts_dash_cpymem(b, "iso6", 4); - ngx_ts_dash_cpymem(b, "dash", 4); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_moov(ngx_buf_t *b, ngx_ts_dash_rep_t *rep) -{ - u_char *p; - - p = ngx_ts_dash_box(b, "moov"); - - ngx_ts_dash_box_mvhd(b); - ngx_ts_dash_box_mvex(b); - ngx_ts_dash_box_trak(b, rep); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_mvhd(ngx_buf_t *b) -{ - u_char *p; - time_t now; - - p = ngx_ts_dash_box_full(b, "mvhd", 0, 0); - - now = ngx_time(); - - /* creation_time */ - ngx_ts_dash_write32(b, now); - - /* modification_time */ - ngx_ts_dash_write32(b, now); - - /* timescale */ - ngx_ts_dash_write32(b, 90000); - - /* duration */ - ngx_ts_dash_write32(b, 0); - - /* rate */ - ngx_ts_dash_write32(b, 0x00010000); - - /* volume */ - ngx_ts_dash_write32(b, 0x01000000); - - /* reserved */ - ngx_ts_dash_write64(b, 0); - - /* matrix */ - ngx_ts_dash_write32(b, 0x00010000); - ngx_ts_dash_write32(b, 0x00000000); - ngx_ts_dash_write32(b, 0x00000000); - ngx_ts_dash_write32(b, 0x00000000); - ngx_ts_dash_write32(b, 0x00010000); - ngx_ts_dash_write32(b, 0x00000000); - ngx_ts_dash_write32(b, 0x00000000); - ngx_ts_dash_write32(b, 0x00000000); - ngx_ts_dash_write32(b, 0x40000000); - - /* pre_defined */ - ngx_ts_dash_write32(b, 0); - ngx_ts_dash_write32(b, 0); - ngx_ts_dash_write32(b, 0); - ngx_ts_dash_write32(b, 0); - ngx_ts_dash_write32(b, 0); - ngx_ts_dash_write32(b, 0); - - /* next_track_ID */ - ngx_ts_dash_write32(b, 1); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_mvex(ngx_buf_t *b) -{ - u_char *p; - - p = ngx_ts_dash_box(b, "mvex"); - - ngx_ts_dash_box_trex(b); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_trex(ngx_buf_t *b) -{ - u_char *p; - - p = ngx_ts_dash_box_full(b, "trex", 0, 0); - - /* track_ID */ - ngx_ts_dash_write32(b, 1); - - /* default_sample_description_index */ - ngx_ts_dash_write32(b, 1); - - /* default_sample_duration */ - ngx_ts_dash_write32(b, 0); - - /* default_sample_size */ - ngx_ts_dash_write32(b, 0); - - /* default_sample_flags */ - ngx_ts_dash_write32(b, 0); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_trak(ngx_buf_t *b, ngx_ts_dash_rep_t *rep) -{ - u_char *p; - - p = ngx_ts_dash_box(b, "trak"); - - ngx_ts_dash_box_tkhd(b, rep); - ngx_ts_dash_box_mdia(b, rep); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_tkhd(ngx_buf_t *b, ngx_ts_dash_rep_t *rep) -{ - u_char *p; - time_t now; - - /* flags: Track_enabled (0x01), Track_in_movie (0x02) */ - p = ngx_ts_dash_box_full(b, "tkhd", 0, 0x03); - - now = ngx_time(); - - /* creation_time */ - ngx_ts_dash_write32(b, now); - - /* modification_time */ - ngx_ts_dash_write32(b, now); - - /* track_ID */ - ngx_ts_dash_write32(b, 1); - - /* reserved */ - ngx_ts_dash_write32(b, 0); - - /* duration */ - ngx_ts_dash_write32(b, 0xffffffff); - - /* reserved */ - ngx_ts_dash_write32(b, 0); - ngx_ts_dash_write32(b, 0); - - /* layer, alternate_group */ - ngx_ts_dash_write32(b, 0); - - /* volume */ - ngx_ts_dash_write32(b, rep->es->video ? 0x00000000 : 0x01000000); - - /* matrix */ - ngx_ts_dash_write32(b, 0x00010000); - ngx_ts_dash_write32(b, 0x00000000); - ngx_ts_dash_write32(b, 0x00000000); - ngx_ts_dash_write32(b, 0x00000000); - ngx_ts_dash_write32(b, 0x00010000); - ngx_ts_dash_write32(b, 0x00000000); - ngx_ts_dash_write32(b, 0x00000000); - ngx_ts_dash_write32(b, 0x00000000); - ngx_ts_dash_write32(b, 0x40000000); - - ngx_ts_dash_write32(b, (rep->avc ? rep->avc->width - : NGX_TS_DASH_DEFAULT_WIDTH) << 16); - - ngx_ts_dash_write32(b, (rep->avc ? rep->avc->height - : NGX_TS_DASH_DEFAULT_HEIGHT) << 16); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_mdia(ngx_buf_t *b, ngx_ts_dash_rep_t *rep) -{ - u_char *p; - - p = ngx_ts_dash_box(b, "mdia"); - - ngx_ts_dash_box_mdhd(b); - ngx_ts_dash_box_hdlr(b, rep); - ngx_ts_dash_box_minf(b, rep); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_mdhd(ngx_buf_t *b) -{ - u_char *p; - - time_t now; - - p = ngx_ts_dash_box_full(b, "mdhd", 0, 0); - - now = ngx_time(); - - /* creation_time */ - ngx_ts_dash_write32(b, now); - - /* modification_time */ - ngx_ts_dash_write32(b, now); - - /* timescale */ - ngx_ts_dash_write32(b, 90000); - - /* duration */ - ngx_ts_dash_write32(b, 0); - - /* language: und */ - ngx_ts_dash_write32(b, 0x55c40000); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_hdlr(ngx_buf_t *b, ngx_ts_dash_rep_t *rep) -{ - u_char *p; - - p = ngx_ts_dash_box_full(b, "hdlr", 0, 0); - - /* pre_defined */ - ngx_ts_dash_write32(b, 0); - - /* handler_type */ - ngx_ts_dash_cpymem(b, rep->es->video ? "vide" : "soun", 4); - - /* reserved */ - ngx_ts_dash_write32(b, 0); - ngx_ts_dash_write32(b, 0); - ngx_ts_dash_write32(b, 0); - - /* name */ - ngx_ts_dash_cpymem(b, rep->es->video ? "video" : "audio", 6); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_minf(ngx_buf_t *b, ngx_ts_dash_rep_t *rep) -{ - u_char *p; - - p = ngx_ts_dash_box(b, "minf"); - - if (rep->es->video) { - ngx_ts_dash_box_vmhd(b); - - } else { - ngx_ts_dash_box_smhd(b); - } - - ngx_ts_dash_box_dinf(b); - ngx_ts_dash_box_stbl(b, rep); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_vmhd(ngx_buf_t *b) -{ - u_char *p; - - p = ngx_ts_dash_box_full(b, "vmhd", 0, 1); - - /* graphicsmode, opcolor */ - ngx_ts_dash_write32(b, 0); - ngx_ts_dash_write32(b, 0); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_smhd(ngx_buf_t *b) -{ - u_char *p; - - p = ngx_ts_dash_box_full(b, "smhd", 0, 0); - - /* balance, reserved */ - ngx_ts_dash_write32(b, 0); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_dinf(ngx_buf_t *b) -{ - u_char *p; - - p = ngx_ts_dash_box(b, "dinf"); - - ngx_ts_dash_box_dref(b); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_dref(ngx_buf_t *b) -{ - u_char *p; - - p = ngx_ts_dash_box_full(b, "dref", 0, 0); - - /* entry_count */ - ngx_ts_dash_write32(b, 1); - - ngx_ts_dash_box_url(b); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_url(ngx_buf_t *b) -{ - u_char *p; - - p = ngx_ts_dash_box_full(b, "url ", 0, 0x01); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_stbl(ngx_buf_t *b, ngx_ts_dash_rep_t *rep) -{ - u_char *p; - - p = ngx_ts_dash_box(b, "stbl"); - - ngx_ts_dash_box_stsd(b, rep); - ngx_ts_dash_box_stts(b); - ngx_ts_dash_box_stsc(b); - ngx_ts_dash_box_stsz(b); - ngx_ts_dash_box_stco(b); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_stts(ngx_buf_t *b) -{ - u_char *p; - - p = ngx_ts_dash_box_full(b, "stts", 0, 0); - - /* entry_count */ - ngx_ts_dash_write32(b, 0); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_stsc(ngx_buf_t *b) -{ - u_char *p; - - p = ngx_ts_dash_box_full(b, "stsc", 0, 0); - - /* entry_count */ - ngx_ts_dash_write32(b, 0); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_stsz(ngx_buf_t *b) -{ - u_char *p; - - p = ngx_ts_dash_box_full(b, "stsz", 0, 0); - - /* sample_size */ - ngx_ts_dash_write32(b, 0); - - /* sample_count */ - ngx_ts_dash_write32(b, 0); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_stco(ngx_buf_t *b) -{ - u_char *p; - - p = ngx_ts_dash_box_full(b, "stco", 0, 0); - - /* entry_count */ - ngx_ts_dash_write32(b, 0); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_stsd(ngx_buf_t *b, ngx_ts_dash_rep_t *rep) -{ - u_char *p; - - p = ngx_ts_dash_box_full(b, "stsd", 0, 0); - - /* entry_count */ - ngx_ts_dash_write32(b, 1); - - if (rep->es->video) { - ngx_ts_dash_box_video(b, rep); - - } else { - ngx_ts_dash_box_audio(b, rep); - } - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_video(ngx_buf_t *b, ngx_ts_dash_rep_t *rep) -{ - u_char *p; - ngx_uint_t avc1; - - avc1 = (rep->es->type == NGX_TS_VIDEO_AVC); - - p = ngx_ts_dash_box(b, avc1 ? "avc1" : "mp4v"); - - /* reserved */ - ngx_ts_dash_write32(b, 0); - ngx_ts_dash_write16(b, 0); - - /* data_reference_index */ - ngx_ts_dash_write16(b, 1); - - /* pre_defined, reserved */ - ngx_ts_dash_write32(b, 0); - ngx_ts_dash_write32(b, 0); - ngx_ts_dash_write32(b, 0); - ngx_ts_dash_write32(b, 0); - - ngx_ts_dash_write16(b, rep->avc ? rep->avc->width - : NGX_TS_DASH_DEFAULT_WIDTH); - - ngx_ts_dash_write16(b, rep->avc ? rep->avc->height - : NGX_TS_DASH_DEFAULT_HEIGHT); - - /* horizresolution */ - ngx_ts_dash_write32(b, 0x00480000); - - /* vertresolution */ - ngx_ts_dash_write32(b, 0x00480000); - - /* reserved */ - ngx_ts_dash_write32(b, 0); - - /* frame_count */ - ngx_ts_dash_write16(b, 1); - - /* compressorname */ - ngx_ts_dash_write32(b, 0); - ngx_ts_dash_write32(b, 0); - ngx_ts_dash_write32(b, 0); - ngx_ts_dash_write32(b, 0); - ngx_ts_dash_write32(b, 0); - ngx_ts_dash_write32(b, 0); - ngx_ts_dash_write32(b, 0); - ngx_ts_dash_write32(b, 0); - - /* depth */ - ngx_ts_dash_write16(b, 0x0018); - - /* pre_defined */ - ngx_ts_dash_write16(b, 0xffff); - - if (avc1) { - ngx_ts_dash_box_avcc(b, rep); - - } else { - ngx_ts_dash_box_esds(b, rep); - } - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_audio(ngx_buf_t *b, ngx_ts_dash_rep_t *rep) -{ - u_char *p; - - p = ngx_ts_dash_box(b, "mp4a"); - - /* reserved */ - ngx_ts_dash_write32(b, 0); - ngx_ts_dash_write16(b, 0); - - /* data_reference_index */ - ngx_ts_dash_write16(b, 1); - - /* reserved */ - ngx_ts_dash_write32(b, 0); - ngx_ts_dash_write32(b, 0); - - /* channel_count */ - ngx_ts_dash_write16(b, 2); - - /* samplesize */ - ngx_ts_dash_write16(b, 16); - - /* pre_defined, reserved */ - ngx_ts_dash_write32(b, 0); - - /* XXX samplerate */ - ngx_ts_dash_write32(b, 90000); - - ngx_ts_dash_box_esds(b, rep); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_avcc(ngx_buf_t *b, ngx_ts_dash_rep_t *rep) -{ - u_char *p, *sps, *pps; - size_t sps_len, pps_len; - - sps_len = rep->sps_len; - pps_len = rep->pps_len; - - if (sps_len < 4 || pps_len == 0) { - return; - } - - sps = rep->sps; - pps = rep->pps; - - p = ngx_ts_dash_box(b, "avcC"); - - /* - * ISO/IEC 14496-15:2004(E) - * 5.2.4.1 AVC decoder configuration record, p. 12 - */ - - /* configurationVersion */ - ngx_ts_dash_write8(b, 1); - - /* AVCProfileIndication, profile_compatibility, AVCLevelIndication */ - ngx_ts_dash_cpymem(b, &sps[1], 3); - - /* lengthSizeMinusOne (lengthSize = 4) */ - ngx_ts_dash_write8(b, 0xff); - - /* numOfSequenceParameterSets = 1 */ - ngx_ts_dash_write8(b, 0xe1); - - /* sequenceParameterSetLength */ - ngx_ts_dash_write16(b, sps_len); - - /* sequenceParameterSetNALUnit */ - ngx_ts_dash_cpymem(b, sps, sps_len); - - /* numOfPictureParameterSets */ - ngx_ts_dash_write8(b, 1); - - /* pictureParameterSetLength */ - ngx_ts_dash_write16(b, pps_len); - - /* pictureParameterSetNALUnit */ - ngx_ts_dash_cpymem(b, pps, pps_len); - - ngx_ts_dash_box_update(b, p); -} - - -static void -ngx_ts_dash_box_esds(ngx_buf_t *b, ngx_ts_dash_rep_t *rep) -{ - u_char *p; - - p = ngx_ts_dash_box_full(b, "esds", 0, 0); - - ngx_ts_dash_desc_es(b, rep); - - ngx_ts_dash_box_update(b, p); -} - - -static u_char * -ngx_ts_dash_box(ngx_buf_t *b, const char type[4]) -{ - /* - * class Box - * ISO/IEC 14496-12:2008(E) - * 4.2 Object Structure, p. 4 - */ - - u_char *p; - - p = b->last; - - /* size */ - ngx_ts_dash_write32(b, 0); - - /* type */ - ngx_ts_dash_cpymem(b, type, 4); - - return p; -} - - -static u_char * -ngx_ts_dash_box_full(ngx_buf_t *b, const char type[4], u_char version, - uint32_t flags) -{ - /* - * class Box - * ISO/IEC 14496-12:2008(E) - * 4.2 Object Structure, p. 4 - */ - - u_char *p; - - p = ngx_ts_dash_box(b, type); - - /* version */ - ngx_ts_dash_write8(b, version); - - /* flags */ - ngx_ts_dash_write24(b, flags); - - return p; -} - - -static void -ngx_ts_dash_box_update(ngx_buf_t *b, u_char *p) -{ - uint32_t size; - - if (p + 4 > b->end) { - return; - } - - size = b->last - p; - - *p++ = (u_char) (size >> 24); - *p++ = (u_char) (size >> 16); - *p++ = (u_char) (size >> 8); - *p++ = (u_char) size; -} - - -static void -ngx_ts_dash_desc_es(ngx_buf_t *b, ngx_ts_dash_rep_t *rep) -{ - /* - * ISO/IEC 14496-1:2001(E) - * 8.6.5 ES_Descriptor, p. 28 - */ - - u_char *p; - - p = ngx_ts_dash_desc(b, 0x03); - - /* ES_ID */ - ngx_ts_dash_write16(b, 1); - - /* flags */ - ngx_ts_dash_write8(b, 0); - - ngx_ts_dash_desc_dec_conf(b, rep); - ngx_ts_dash_desc_sl_conf(b); - - ngx_ts_dash_desc_update(b, p); -} - - -static void -ngx_ts_dash_desc_dec_conf(ngx_buf_t *b, ngx_ts_dash_rep_t *rep) -{ - /* - * ISO/IEC 14496-1:2001(E) - * 8.6.6 DecoderConfigDescriptor, p. 30 - */ - - u_char *p; - - p = ngx_ts_dash_desc(b, 0x04); - - /* objectTypeIndication */ - ngx_ts_dash_write8(b, ngx_ts_dash_get_oti(rep->es->type)); - - /* streamType, upStream, reserved */ - ngx_ts_dash_write8(b, (rep->es->video ? 0x04 : 0x05) << 2); - - /* bufferSizeDB */ - ngx_ts_dash_write24(b, 0); - - /* maxBitrate */ - ngx_ts_dash_write32(b, rep->bandwidth * 2); - - /* avgBitrate */ - ngx_ts_dash_write32(b, rep->bandwidth); - - ngx_ts_dash_desc_dec_spec(b, rep); - - ngx_ts_dash_desc_update(b, p); -} - - -static void -ngx_ts_dash_desc_dec_spec(ngx_buf_t *b, ngx_ts_dash_rep_t *rep) -{ - u_char *p; - - if (rep->aac == NULL) { - return; - } - - /* TODO - * AudioSpecificConfig - * https://wiki.multimedia.cx/index.php/MPEG-4_Audio#Audio_Specific_Config - */ - - p = ngx_ts_dash_desc(b, 0x05); - - ngx_ts_dash_write8(b, - (rep->aac->profile << 3) + (rep->aac->freq_index >> 1)); - ngx_ts_dash_write8(b, (rep->aac->freq_index << 7) + (rep->aac->chan << 3)); - - ngx_ts_dash_desc_update(b, p); -} - - -static void -ngx_ts_dash_desc_sl_conf(ngx_buf_t *b) -{ - /* - * ISO/IEC 14496-1:2001(E) - * 10.2.3 SL Packet Header Configuration, p. 227 - */ - - u_char *p; - - p = ngx_ts_dash_desc(b, 0x06); - - /* predefined */ - ngx_ts_dash_write8(b, 0x02); - - ngx_ts_dash_desc_update(b, p); -} - - -static u_char * -ngx_ts_dash_desc(ngx_buf_t *b, u_char tag) -{ - /* - * ISO/IEC 14496-1:2001(E) - * 8.2.2 BaseDescriptor, p. 16 - */ - - u_char *p; - - ngx_ts_dash_write8(b, tag); - - p = b->last; - - /* size */ - ngx_ts_dash_write32(b, 0); - - return p; -} - - -static void -ngx_ts_dash_desc_update(ngx_buf_t *b, u_char *p) -{ - uint32_t size; - - if (p + 4 > b->end) { - return; - } - - size = b->last - p - 4; - - *p++ = (size >> 21) | 0x80; - *p++ = (size >> 14) | 0x80; - *p++ = (size >> 7) | 0x80; - *p++ = size & 0x7f; -} - - -static void -ngx_ts_dash_cpymem(ngx_buf_t *b, const void *data, size_t size) -{ - size_t n; - - n = ngx_min((size_t) (b->end - b->last), size); - - b->last = ngx_cpymem(b->last, data, n); -} - - -static void -ngx_ts_dash_write64(ngx_buf_t *b, uint64_t v) -{ - ngx_int_t n; - - for (n = 56; n >= 0 && b->last < b->end; n -= 8) { - *b->last++ = (u_char) (v >> n); - } -} - - -static void -ngx_ts_dash_write32(ngx_buf_t *b, uint32_t v) -{ - ngx_int_t n; - - for (n = 24; n >= 0 && b->last < b->end; n -= 8) { - *b->last++ = (u_char) (v >> n); - } -} - - -static void -ngx_ts_dash_write24(ngx_buf_t *b, uint32_t v) -{ - ngx_int_t n; - - for (n = 16; n >= 0 && b->last < b->end; n -= 8) { - *b->last++ = (u_char) (v >> n); - } -} - - -static void -ngx_ts_dash_write16(ngx_buf_t *b, uint16_t v) -{ - ngx_int_t n; - - for (n = 8; n >= 0 && b->last < b->end; n -= 8) { - *b->last++ = (u_char) (v >> n); - } -} - - -static void -ngx_ts_dash_write8(ngx_buf_t *b, u_char v) -{ - if (b->last < b->end) { - *b->last++ = v; - } -} - - -ngx_int_t -ngx_ts_dash_start_segment(ngx_ts_dash_t *dash, ngx_ts_dash_rep_t *rep) -{ - ngx_buf_t *b; - - ngx_memzero(&rep->subs, sizeof(ngx_ts_dash_subs_t)); - - rep->nsamples = 0; - rep->nmeta = 0; - rep->ndata = 0; - - rep->meta = ngx_ts_dash_get_buffer(dash); - if (rep->meta == NULL) { - return NGX_ERROR; - } - - rep->last_meta = rep->meta; - - b = rep->meta->buf; - - ngx_ts_dash_box_styp(b); - ngx_ts_dash_box_sidx(b, rep); - ngx_ts_dash_box_moof(b, rep); - - if (b->last == b->end) { - return NGX_ERROR; - } - - rep->data = ngx_ts_dash_get_buffer(dash); - if (rep->data == NULL) { - return NGX_ERROR; - } - - rep->last_data = rep->data; - - b = rep->data->buf; - - ngx_ts_dash_box_mdat(b, rep); - - if (b->last == b->end) { - return NGX_ERROR; - } - - return NGX_OK; -} - - -ngx_chain_t * -ngx_ts_dash_end_segment(ngx_ts_dash_t *dash, ngx_ts_dash_rep_t *rep) -{ - int32_t d; - uint32_t traf, trun, moof, mdat; - ngx_chain_t *out; - ngx_ts_dash_subs_t *subs; - - subs = &rep->subs; - - ngx_ts_dash_put64(subs->pts, rep->seg_pts); - ngx_ts_dash_put64(subs->dts, rep->seg_dts); - - ngx_ts_dash_put32(subs->seq, rep->seg); - ngx_ts_dash_put32(subs->nsamples, rep->nsamples); - ngx_ts_dash_put32(subs->duration, rep->es->dts - rep->seg_dts); - - d = rep->es->dts - rep->dts; - - if (subs->sample_duration && d > 0) { - ngx_ts_dash_put32(subs->sample_duration, d); - } - - traf = ngx_ts_dash_get32(subs->traf) + rep->nmeta; - ngx_ts_dash_put32(subs->traf, traf); - - trun = ngx_ts_dash_get32(subs->trun) + rep->nmeta; - ngx_ts_dash_put32(subs->trun, trun); - - moof = ngx_ts_dash_get32(subs->moof) + rep->nmeta; - ngx_ts_dash_put32(subs->moof, moof); - - mdat = ngx_ts_dash_get32(subs->mdat) + rep->ndata; - ngx_ts_dash_put32(subs->mdat, mdat); - - ngx_ts_dash_put32(subs->moof_mdat, moof + mdat); - ngx_ts_dash_put32(subs->moof_data, moof + 8); - - out = rep->meta; - rep->last_meta->next = rep->data; - - rep->meta = NULL; - rep->data = NULL; - rep->last_meta = NULL; - rep->last_data = NULL; - - return out; -} - - -static void -ngx_ts_dash_set_sub(ngx_buf_t *b, u_char **p) -{ - *p = b->last; -} - - -static uint32_t -ngx_ts_dash_get32(u_char *p) -{ - uint32_t v; - - v = *p++; - v = (v << 8) + *p++; - v = (v << 8) + *p++; - v = (v << 8) + *p; - - return v; -} - - -static void -ngx_ts_dash_put32(u_char *p, uint32_t v) -{ - *p++ = (u_char) (v >> 24); - *p++ = (u_char) (v >> 16); - *p++ = (u_char) (v >> 8); - *p++ = (u_char) v; -} - - -static void -ngx_ts_dash_put64(u_char *p, uint64_t v) -{ - *p++ = (u_char) (v >> 56); - *p++ = (u_char) (v >> 48); - *p++ = (u_char) (v >> 40); - *p++ = (u_char) (v >> 32); - *p++ = (u_char) (v >> 24); - *p++ = (u_char) (v >> 16); - *p++ = (u_char) (v >> 8); - *p++ = (u_char) v; -} - - -void -ngx_ts_dash_free_segment(ngx_ts_dash_t *dash, ngx_ts_dash_rep_t *rep, - ngx_chain_t *out) -{ - ngx_chain_t *cl; - - for (cl = out; cl->next; cl = cl->next); - - cl->next = dash->free; - dash->free = out; -} - - -ngx_int_t -ngx_ts_dash_append_meta(ngx_ts_dash_t *dash, ngx_ts_dash_rep_t *rep, - size_t size, uint64_t dts) -{ - size_t n; - ngx_buf_t *b; - ngx_chain_t *cl; - ngx_ts_es_t *es; - - es = rep->es; - - rep->ndata += size; - rep->nsamples++; - - n = es->video ? 16 : 8; - - cl = rep->last_meta; - b = cl->buf; - - if ((size_t) (b->end - b->last) < n) { - cl->next = ngx_ts_dash_get_buffer(dash); - if (cl->next == NULL) { - return NGX_ERROR; - } - - cl = cl->next; - rep->last_meta = cl; - b = cl->buf; - } - - rep->nmeta += n; - - /* sample_duration */ - if (rep->subs.sample_duration) { - ngx_ts_dash_put32(rep->subs.sample_duration, dts - rep->dts); - } - - ngx_ts_dash_set_sub(b, &rep->subs.sample_duration); - ngx_ts_dash_write32(b, 0); - - /* sample_size */ - ngx_ts_dash_write32(b, size); - - if (es->video) { - - /* - * ISO/IEC 14496-12:2008(E) - * 8.8.3 Track Extends Box, Sample flags, p. 44 - * sample_is_difference_sample for non-key sample - */ - - ngx_ts_dash_write32(b, es->rand ? 0x00000000 : 0x00010000); - - /* sample_composition_time_offset */ - ngx_ts_dash_write32(b, es->pts - es->dts); - } - - rep->dts = dts; - - return NGX_OK; -} - - -ngx_int_t -ngx_ts_dash_append_data(ngx_ts_dash_t *dash, ngx_ts_dash_rep_t *rep, - u_char *data, size_t len) -{ - size_t n; - ngx_chain_t *cl; - - cl = rep->last_data; - - while (len) { - if (cl->buf->last == cl->buf->end) { - cl->next = ngx_ts_dash_get_buffer(dash); - if (cl->next == NULL) { - return NGX_ERROR; - } - - cl = cl->next; - rep->last_data = cl; - } - - n = ngx_min((size_t) (cl->buf->end - cl->buf->last), len); - - cl->buf->last = ngx_cpymem(cl->buf->last, data, n); - - data += n; - len -= n; - } - - return NGX_OK; -} - - -static ngx_chain_t * -ngx_ts_dash_get_buffer(ngx_ts_dash_t *dash) -{ - ngx_buf_t *b; - ngx_chain_t *out; - - if (dash->free) { - out = dash->free; - dash->free = out->next; - out->next = NULL; - b = out->buf; - - } else { - out = ngx_alloc_chain_link(dash->ts->pool); - if (out == NULL) { - return NULL; - } - - ngx_log_debug1(NGX_LOG_DEBUG_CORE, dash->ts->log, 0, - "ts dash alloc buffer:%d", NGX_TS_DASH_BUFFER_SIZE); - - b = ngx_create_temp_buf(dash->ts->pool, NGX_TS_DASH_BUFFER_SIZE); - if (b == NULL) { - return NULL; - } - - out->buf = b; - out->next = NULL; - } - - b->pos = b->start; - b->last = b->start; - - return out; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_hls.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_hls.c deleted file mode 100644 index 8ce47e7090..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_hls.c +++ /dev/null @@ -1,1002 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include - -#include "ngx_ts_hls.h" - - -static void ngx_ts_hls_cleanup(void *data); -static ngx_int_t ngx_ts_hls_handler(ngx_ts_handler_data_t *hd); -static ngx_int_t ngx_ts_hls_pat_handler(ngx_ts_hls_t *hls); -static ngx_int_t ngx_ts_hls_pes_handler(ngx_ts_hls_t *hls, - ngx_ts_program_t *prog, ngx_ts_es_t *es, ngx_chain_t *bufs); -static void ngx_ts_hls_update_bandwidth(ngx_ts_hls_t *hls, - ngx_ts_hls_variant_t *var, ngx_chain_t *bufs, uint64_t dts); -static ngx_int_t ngx_ts_hls_close_segment(ngx_ts_hls_t *hls, - ngx_ts_hls_variant_t *var, ngx_ts_es_t *es); -static ngx_int_t ngx_ts_hls_update_playlist(ngx_ts_hls_t *hls, - ngx_ts_hls_variant_t *var); -static ngx_int_t ngx_ts_hls_update_master_playlist(ngx_ts_hls_t *hls); -static ngx_int_t ngx_ts_hls_write_file(u_char *path, u_char *tmp_path, - u_char *data, size_t len, ngx_log_t *log); -static ngx_int_t ngx_ts_hls_open_segment(ngx_ts_hls_t *hls, - ngx_ts_hls_variant_t *var); - -static ngx_msec_t ngx_ts_hls_file_manager(void *data); -static ngx_int_t ngx_ts_hls_manage_file(ngx_tree_ctx_t *ctx, ngx_str_t *path); -static ngx_int_t ngx_ts_hls_manage_directory(ngx_tree_ctx_t *ctx, - ngx_str_t *path); -static ngx_int_t ngx_ts_hls_delete_directory(ngx_tree_ctx_t *ctx, - ngx_str_t *path); -static ngx_int_t ngx_ts_hls_delete_file(ngx_tree_ctx_t *ctx, ngx_str_t *path); - - -ngx_ts_hls_t * -ngx_ts_hls_create(ngx_ts_hls_conf_t *conf, ngx_ts_stream_t *ts, ngx_str_t *name) -{ - ngx_ts_hls_t *hls; - ngx_pool_cleanup_t *cln; - - ngx_log_debug0(NGX_LOG_DEBUG_CORE, ts->log, 0, "ts hls create"); - - hls = ngx_pcalloc(ts->pool, sizeof(ngx_ts_hls_t)); - if (hls == NULL) { - return NULL; - } - - hls->conf = conf; - hls->ts = ts; - - hls->path.len = conf->path->name.len + 1 + name->len; - hls->path.data = ngx_pnalloc(ts->pool, hls->path.len + 1); - if (hls->path.data == NULL) { - return NULL; - } - - ngx_sprintf(hls->path.data, "%V/%V%Z", &conf->path->name, name); - - cln = ngx_pool_cleanup_add(ts->pool, 0); - if (cln == NULL) { - return NULL; - } - - cln->handler = ngx_ts_hls_cleanup; - cln->data = hls; - - if (ngx_ts_add_handler(ts, ngx_ts_hls_handler, hls) != NGX_OK) { - return NULL; - } - - return hls; -} - - -static void -ngx_ts_hls_cleanup(void *data) -{ - ngx_ts_hls_t *hls = data; - - int64_t d, maxd; - ngx_uint_t n, i; - ngx_ts_es_t *es; - ngx_ts_stream_t *ts; - ngx_ts_hls_segment_t *seg; - ngx_ts_hls_variant_t *var; - - hls->done = 1; - - ts = hls->ts; - - ngx_log_debug0(NGX_LOG_DEBUG_CORE, ts->log, 0, "ts hls cleanup"); - - for (n = 0; n < hls->nvars; n++) { - var = &hls->vars[n]; - - if (var->file.fd != NGX_INVALID_FILE) { - if (ngx_close_file(var->file.fd) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ALERT, ts->log, ngx_errno, - ngx_close_file_n " \"%s\" failed", - var->file.name.data); - } - - var->file.fd = NGX_INVALID_FILE; - } - - maxd = 0; - - for (i = 0; i < var->prog->nes; i++) { - es = &var->prog->es[i]; - - d = es->dts - var->seg_dts; - if (maxd < d) { - maxd = d; - } - } - - seg = &var->segs[var->seg % var->nsegs]; - seg->id = var->seg++; - seg->duration = maxd; - - (void) ngx_ts_hls_update_playlist(hls, var); - } -} - - -static ngx_int_t -ngx_ts_hls_handler(ngx_ts_handler_data_t *hd) -{ - ngx_ts_hls_t *hls = hd->data; - - switch (hd->event) { - - case NGX_TS_PAT: - return ngx_ts_hls_pat_handler(hls); - - case NGX_TS_PES: - return ngx_ts_hls_pes_handler(hls, hd->prog, hd->es, hd->bufs); - - default: - return NGX_OK; - } -} - - -static ngx_int_t -ngx_ts_hls_pat_handler(ngx_ts_hls_t *hls) -{ - size_t len; - u_char *p; - ngx_uint_t n; - ngx_ts_stream_t *ts; - ngx_ts_program_t *prog; - ngx_ts_hls_variant_t *var; - - if (hls->vars) { - return NGX_OK; - } - - ts = hls->ts; - - ngx_log_debug0(NGX_LOG_DEBUG_CORE, ts->log, 0, "ts hls pat"); - - hls->nvars = ts->nprogs; - hls->vars = ngx_pcalloc(ts->pool, - sizeof(ngx_ts_hls_variant_t) * ts->nprogs); - if (hls->vars == NULL) { - return NGX_ERROR; - } - - if (hls->nvars > 1) { - /* index.m3u8 */ - - len = hls->path.len + sizeof("/index.m3u8"); - - hls->m3u8_path = ngx_pnalloc(ts->pool, len); - if (hls->m3u8_path == NULL) { - return NGX_ERROR; - } - - ngx_sprintf(hls->m3u8_path, "%V/index.m3u8%Z", &hls->path); - - /* index.m3u8.tmp */ - - len += sizeof(".tmp") - 1; - - hls->m3u8_tmp_path = ngx_pnalloc(ts->pool, len); - if (hls->m3u8_tmp_path == NULL) { - return NGX_ERROR; - } - - ngx_sprintf(hls->m3u8_tmp_path, "%s.tmp%Z", hls->m3u8_path); - } - - for (n = 0; n < ts->nprogs; n++) { - prog = &ts->progs[n]; - var = &hls->vars[n]; - - var->prog = prog; - var->file.fd = NGX_INVALID_FILE; - var->file.log = ts->log; - - var->nsegs = hls->conf->nsegs; - var->segs = ngx_pcalloc(ts->pool, - sizeof(ngx_ts_hls_segment_t) * hls->conf->nsegs); - if (var->segs == NULL) { - return NGX_ERROR; - } - - /* [.].ts */ - - len = hls->path.len + 1 + NGX_INT_T_LEN + sizeof(".ts"); - - if (hls->nvars > 1) { - len += NGX_INT_T_LEN + 1; - } - - p = ngx_pnalloc(ts->pool, len); - if (p == NULL) { - return NGX_ERROR; - } - - var->path.data = p; - - if (hls->nvars > 1) { - p = ngx_sprintf(p, "%V/%ui.", - &hls->path, (ngx_uint_t) prog->number); - - } else { - p = ngx_sprintf(p, "%V/", &hls->path); - } - - var->path.len = p - var->path.data; - - /* (|index).m3u8 */ - - len = hls->path.len + 1 + sizeof(".m3u8"); - - if (hls->nvars > 1) { - len += NGX_INT_T_LEN; - - } else { - len += sizeof("index") - 1; - } - - var->m3u8_path = ngx_pnalloc(ts->pool, len); - if (var->m3u8_path == NULL) { - return NGX_ERROR; - } - - if (hls->nvars > 1) { - ngx_sprintf(var->m3u8_path, "%V/%ui.m3u8%Z", - &hls->path, (ngx_uint_t) prog->number); - - } else { - ngx_sprintf(var->m3u8_path, "%V/index.m3u8%Z", &hls->path); - } - - /* (|index).m3u8.tmp */ - - len += sizeof(".tmp") - 1; - - var->m3u8_tmp_path = ngx_pnalloc(ts->pool, len); - if (var->m3u8_tmp_path == NULL) { - return NGX_ERROR; - } - - ngx_sprintf(var->m3u8_tmp_path, "%s.tmp%Z", var->m3u8_path); - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_ts_hls_pes_handler(ngx_ts_hls_t *hls, ngx_ts_program_t *prog, - ngx_ts_es_t *es, ngx_chain_t *bufs) -{ - ngx_uint_t n; - ngx_chain_t *out; - ngx_ts_stream_t *ts; - ngx_ts_hls_variant_t *var; - - if (!es->ptsf) { - return NGX_OK; - } - - ts = hls->ts; - - ngx_log_debug1(NGX_LOG_DEBUG_CORE, ts->log, 0, "ts hls pes pid:%ud", - (unsigned) es->pid); - - for (n = 0; n < hls->nvars; n++) { - var = &hls->vars[n]; - if (prog == var->prog) { - goto found; - } - } - - ngx_log_error(NGX_LOG_ERR, ts->log, 0, "TS program not found"); - - return NGX_ERROR; - -found: - - ngx_ts_hls_update_bandwidth(hls, var, bufs, es->pts); - - if (ngx_ts_hls_close_segment(hls, var, es) != NGX_OK) { - return NGX_ERROR; - } - - if (ngx_ts_hls_open_segment(hls, var) != NGX_OK) { - return NGX_ERROR; - } - - out = ngx_ts_write_pes(ts, prog, es, bufs); - if (out == NULL) { - return NGX_ERROR; - } - - if (ngx_write_chain_to_file(&var->file, out, var->file.offset, ts->pool) - == NGX_ERROR) - { - return NGX_ERROR; - } - - ngx_ts_free_chain(ts, &out); - - return NGX_OK; -} - -static void -ngx_ts_hls_update_bandwidth(ngx_ts_hls_t *hls, ngx_ts_hls_variant_t *var, - ngx_chain_t *bufs, uint64_t dts) -{ - int64_t d, analyze; - - if (var->bandwidth) { - return; - } - - if (var->bandwidth_bytes == 0) { - var->bandwidth_dts = dts; - } - - while (bufs) { - var->bandwidth_bytes += bufs->buf->last - bufs->buf->pos; - bufs = bufs->next; - } - - d = dts - var->bandwidth_dts; - analyze = (int64_t) hls->conf->analyze * 90; - - if (d >= analyze) { - var->bandwidth = var->bandwidth_bytes * 8 * 90000 / d; - } - - ngx_log_debug2(NGX_LOG_DEBUG_CORE, hls->ts->log, 0, - "ts hls bandwidth:%ui, pid:%ud", - var->bandwidth, (unsigned) var->prog->pid); -} - - -static ngx_int_t -ngx_ts_hls_close_segment(ngx_ts_hls_t *hls, ngx_ts_hls_variant_t *var, - ngx_ts_es_t *es) -{ - off_t max_size; - int64_t d, min_seg, max_seg; - ngx_ts_stream_t *ts; - ngx_ts_hls_segment_t *seg; - - ts = hls->ts; - - if (var->file.fd == NGX_INVALID_FILE) { - var->seg_dts = es->dts; - return NGX_OK; - } - - d = es->dts - var->seg_dts; - - min_seg = (int64_t) hls->conf->min_seg * 90; - max_seg = (int64_t) hls->conf->max_seg * 90; - max_size = hls->conf->max_size; - - if (d < min_seg - || (d < max_seg && es->video && !es->rand) - || (d < max_seg && !es->video && var->prog->video)) - { - if (max_size == 0 || var->file.offset < max_size) { - return NGX_OK; - } - - ngx_log_error(NGX_LOG_WARN, ts->log, 0, - "closing HLS segment \"%s\" on size limit", - var->file.name.data); - } - - ngx_log_debug1(NGX_LOG_DEBUG_CORE, ts->log, 0, - "ts hls close segment \"%s\"", var->file.name.data); - - var->seg_dts = es->dts; - - seg = &var->segs[var->seg % var->nsegs]; - seg->id = var->seg++; - seg->duration = d; - seg->size = var->file.offset; - - if (ngx_close_file(var->file.fd) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ALERT, ts->log, ngx_errno, - ngx_close_file_n " \"%s\" failed", var->file.name.data); - } - - ngx_memzero(&var->file, sizeof(ngx_file_t)); - - var->file.fd = NGX_INVALID_FILE; - var->file.log = ts->log; - - if (ngx_ts_hls_update_playlist(hls, var) != NGX_OK) { - return NGX_ERROR; - } - - return ngx_ts_hls_update_master_playlist(hls); -} - - -static ngx_int_t -ngx_ts_hls_update_playlist(ngx_ts_hls_t *hls, ngx_ts_hls_variant_t *var) -{ - size_t len; - u_char *p, *data; - uint64_t maxd; - ngx_int_t rc; - ngx_uint_t i, ms, td; - ngx_ts_stream_t *ts; - ngx_ts_hls_segment_t *seg; - - ts = hls->ts; - - ngx_log_debug1(NGX_LOG_DEBUG_CORE, ts->log, 0, - "ts hls update playlist \"%s\"", var->m3u8_path); - - len = sizeof("#EXTM3U\n" - "#EXT-X-VERSION:3\n" - "#EXT-X-MEDIA-SEQUENCE:\n" - "#EXT-X-TARGETDURATION:\n\n") - 1 - + 2 * NGX_INT_T_LEN; - - maxd = 0; - - for (i = 0; i < var->nsegs; i++) { - seg = &var->segs[(var->seg + i) % var->nsegs]; - - if (seg->duration) { - if (maxd < seg->duration) { - maxd = seg->duration; - } - - len += sizeof("#EXTINF:.xxx,\n" - ".ts\n") - 1 - + 2 * NGX_INT_T_LEN; - - if (hls->nvars > 1) { - len += NGX_INT_T_LEN + 1; - } - } - } - - if (hls->done) { - len += sizeof("\n#EXT-X-ENDLIST\n") - 1; - } - - data = ngx_alloc(len, ts->log); - if (data == NULL) { - return NGX_ERROR; - } - - p = data; - - ms = var->seg <= var->nsegs ? 0 : var->seg - var->nsegs; - td = (hls->conf->max_seg + 999) / 1000; - - p = ngx_sprintf(p, "#EXTM3U\n" - "#EXT-X-VERSION:3\n" - "#EXT-X-MEDIA-SEQUENCE:%ui\n" - "#EXT-X-TARGETDURATION:%ui\n\n", ms, td); - - for (i = 0; i < var->nsegs; i++) { - seg = &var->segs[(var->seg + i) % var->nsegs]; - - if (seg->duration) { - p = ngx_sprintf(p, "#EXTINF:%.3f,\n", seg->duration / 90000.); - - if (hls->nvars > 1) { - p = ngx_sprintf(p, "%ui.%ui.ts\n", - (ngx_uint_t) var->prog->number, seg->id); - - } else { - p = ngx_sprintf(p, "%ui.ts\n", seg->id); - } - } - } - - if (hls->done) { - p = ngx_cpymem(p, "\n#EXT-X-ENDLIST\n", - sizeof("\n#EXT-X-ENDLIST\n") - 1); - } - - rc = ngx_ts_hls_write_file(var->m3u8_path, var->m3u8_tmp_path, data, - p - data, ts->log); - - ngx_free(data); - - return rc; -} - - -static ngx_int_t -ngx_ts_hls_update_master_playlist(ngx_ts_hls_t *hls) -{ - size_t len; - u_char *p, *data; - ngx_int_t rc; - ngx_uint_t n; - ngx_ts_stream_t *ts; - ngx_ts_hls_variant_t *var; - - /* TODO touch file if it exists*/ - - if (hls->nvars == 1) { - return NGX_OK; - } - - ts = hls->ts; - - ngx_log_debug1(NGX_LOG_DEBUG_CORE, ts->log, 0, - "ts hls update master playlist \"%s\"", hls->m3u8_path); - - len = sizeof("#EXTM3U\n") - 1; - - for (n = 0; n < hls->nvars; n++) { - var = &hls->vars[n]; - - if (var->bandwidth == 0) { - ngx_log_debug0(NGX_LOG_DEBUG_CORE, ts->log, 0, - "ts hls bandwidth not available"); - return NGX_OK; - } - - len += sizeof("#EXT-X-STREAM-INF:BANDWIDTH=\n") - 1 + NGX_INT_T_LEN - + NGX_INT_T_LEN + sizeof(".m3u8\n") - 1; - } - - data = ngx_alloc(len, ts->log); - if (data == NULL) { - return NGX_ERROR; - } - - p = data; - - p = ngx_cpymem(p, "#EXTM3U\n", sizeof("#EXTM3U\n") - 1); - - for (n = 0; n < hls->nvars; n++) { - var = &hls->vars[n]; - - p = ngx_sprintf(p, "#EXT-X-STREAM-INF:BANDWIDTH=%ui\n%ui.m3u8\n", - var->bandwidth, (ngx_uint_t) var->prog->number); - } - - rc = ngx_ts_hls_write_file(hls->m3u8_path, hls->m3u8_tmp_path, data, - p - data, ts->log); - - ngx_free(data); - - return rc; -} - - -static ngx_int_t -ngx_ts_hls_write_file(u_char *path, u_char *tmp_path, u_char *data, size_t len, - ngx_log_t *log) -{ - ssize_t n; - ngx_fd_t fd; - ngx_err_t err; - - fd = ngx_open_file(tmp_path, - NGX_FILE_WRONLY, - NGX_FILE_TRUNCATE, - NGX_FILE_DEFAULT_ACCESS); - - if (fd == NGX_INVALID_FILE) { - ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, - ngx_open_file_n " \"%s\" failed", tmp_path); - return NGX_ERROR; - } - - n = ngx_write_fd(fd, data, len); - - err = ngx_errno; - - if (ngx_close_file(fd) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, - ngx_close_file_n " \"%s\" failed", tmp_path); - return NGX_ERROR; - } - - if (n < 0) { - ngx_log_error(NGX_LOG_ALERT, log, err, - ngx_write_fd_n " to \"%s\" failed", tmp_path); - return NGX_ERROR; - } - - if ((size_t) n != len) { - ngx_log_error(NGX_LOG_ALERT, log, 0, - "incomplete write to \"%s\"", tmp_path); - return NGX_ERROR; - } - - if (ngx_rename_file(tmp_path, path) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, - ngx_rename_file_n " \"%s\" to \"%s\" failed", - tmp_path, path); - return NGX_ERROR; - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_ts_hls_open_segment(ngx_ts_hls_t *hls, ngx_ts_hls_variant_t *var) -{ - size_t n; - ngx_err_t err; - ngx_str_t *path; - ngx_uint_t try; - ngx_chain_t *out, **ll; - ngx_ts_stream_t *ts; - - if (var->file.fd != NGX_INVALID_FILE) { - return NGX_OK; - } - - ts = hls->ts; - - path = &var->path; - - n = ngx_sprintf(path->data + path->len, "%ui.ts%Z", var->seg) - path->data - - 1; - - var->file.name.data = path->data; - var->file.name.len = n; - - ngx_log_debug1(NGX_LOG_DEBUG_CORE, ts->log, 0, - "ts hls open segment \"%s\"", var->file.name.data); - - for (try = 0; /* void */; try++) { - var->file.fd = ngx_open_file(path->data, - NGX_FILE_WRONLY, - NGX_FILE_TRUNCATE, - NGX_FILE_DEFAULT_ACCESS); - - if (var->file.fd != NGX_INVALID_FILE) { - break; - } - - err = ngx_errno; - - if (try || (err != NGX_ENOENT && err != NGX_ENOTDIR)) { - ngx_log_error(NGX_LOG_EMERG, ts->log, err, - ngx_open_file_n " \"%s\" failed", path->data); - return NGX_ERROR; - } - - /* XXX dir access mode */ - if (ngx_create_dir(hls->path.data, 0700) == NGX_FILE_ERROR) { - err = ngx_errno; - - if (err != NGX_EEXIST) { - ngx_log_error(NGX_LOG_CRIT, ts->log, err, - ngx_create_dir_n " \"%s\" failed", - hls->path.data); - return NGX_ERROR; - } - } - } - - if (var->prologue == NULL) { - out = ngx_ts_write_pat(ts, var->prog); - if (out == NULL) { - return NGX_ERROR; - } - - for (ll = &out; *ll; ll = &(*ll)->next); - - *ll = ngx_ts_write_pmt(ts, var->prog); - if (*ll == NULL) { - return NGX_ERROR; - } - - var->prologue = out; - } - - if (ngx_write_chain_to_file(&var->file, var->prologue, 0, ts->pool) - == NGX_ERROR) - { - return NGX_ERROR; - } - - return NGX_OK; -} - - -static ngx_msec_t -ngx_ts_hls_file_manager(void *data) -{ - ngx_ts_hls_conf_t *hls = data; - - ngx_tree_ctx_t tree; - - ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, - "ts hls file manager"); - - tree.init_handler = NULL; - tree.file_handler = ngx_ts_hls_manage_file; - tree.pre_tree_handler = ngx_ts_hls_manage_directory; - tree.post_tree_handler = ngx_ts_hls_delete_directory; - tree.spec_handler = ngx_ts_hls_delete_file; - tree.data = hls; - tree.alloc = 0; - tree.log = ngx_cycle->log; - - (void) ngx_walk_tree(&tree, &hls->path->name); - - return hls->max_seg * hls->nsegs; -} - - -static ngx_int_t -ngx_ts_hls_manage_file(ngx_tree_ctx_t *ctx, ngx_str_t *path) -{ - ngx_ts_hls_conf_t *hls = ctx->data; - - time_t age, max_age; - - age = ngx_time() - ctx->mtime; - - max_age = 0; - - if (path->len >= 5 - && ngx_memcmp(path->data + path->len - 5, ".m3u8", 5) == 0) - { - max_age = hls->max_seg * hls->nsegs / 1000; - } - - if (path->len >= 3 - && ngx_memcmp(path->data + path->len - 3, ".ts", 3) == 0) - { - max_age = hls->max_seg * hls->nsegs / 500; - } - - if (path->len >= 4 - && ngx_memcmp(path->data + path->len - 4, ".tmp", 3) == 0) - { - max_age = 10; - } - - ngx_log_debug3(NGX_LOG_DEBUG_CORE, ctx->log, 0, - "ts hls file \"%s\", age:%T, max_age:%T", - path->data, age, max_age); - - if (age < max_age) { - return NGX_OK; - } - - return ngx_ts_hls_delete_file(ctx, path); -} - - -static ngx_int_t -ngx_ts_hls_manage_directory(ngx_tree_ctx_t *ctx, ngx_str_t *path) -{ - return NGX_OK; -} - - -static ngx_int_t -ngx_ts_hls_delete_directory(ngx_tree_ctx_t *ctx, ngx_str_t *path) -{ - ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->log, 0, - "ts hls delete dir: \"%s\"", path->data); - - /* non-empty directory will not be removed anyway */ - - /* TODO count files instead */ - - (void) ngx_delete_dir(path->data); - - return NGX_OK; -} - - -static ngx_int_t -ngx_ts_hls_delete_file(ngx_tree_ctx_t *ctx, ngx_str_t *path) -{ - ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->log, 0, - "ts hls file delete: \"%s\"", path->data); - - if (ngx_delete_file(path->data) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno, - ngx_delete_file_n " \"%s\" failed", path->data); - } - - return NGX_OK; -} - - -char * -ngx_ts_hls_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - char *p = conf; - - ssize_t max_size; - ngx_str_t *value, s, ss, path; - ngx_int_t v; - ngx_uint_t i, nsegs, clean; - ngx_msec_t min_seg, max_seg, analyze; - ngx_ts_hls_conf_t *hls, **field; - - field = (ngx_ts_hls_conf_t **) (p + cmd->offset); - - if (*field != NGX_CONF_UNSET_PTR) { - return "is duplicate"; - } - - value = cf->args->elts; - - ngx_str_null(&path); - - min_seg = 5000; - max_seg = 10000; - analyze = 0; - max_size = 16 * 1024 * 1024; - nsegs = 6; - clean = 1; - - for (i = 1; i < cf->args->nelts; i++) { - - if (ngx_strncmp(value[i].data, "path=", 5) == 0) { - - path.len = value[i].len - 5; - path.data = value[i].data + 5; - - if (path.data[path.len - 1] == '/') { - path.len--; - } - - if (ngx_conf_full_name(cf->cycle, &path, 0) != NGX_OK) { - return NGX_CONF_ERROR; - } - - continue; - } - - if (ngx_strncmp(value[i].data, "segment=", 8) == 0) { - - s.len = value[i].len - 8; - s.data = value[i].data + 8; - - ss.data = (u_char *) ngx_strchr(s.data, ':'); - - if (ss.data) { - ss.len = s.data + s.len - ss.data - 1; - s.len = ss.data - s.data; - ss.data++; - } - - min_seg = ngx_parse_time(&s, 0); - if (min_seg == (ngx_msec_t) NGX_ERROR) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid segment duration value \"%V\"", - &value[i]); - return NGX_CONF_ERROR; - } - - if (ss.data) { - max_seg = ngx_parse_time(&ss, 0); - if (max_seg == (ngx_msec_t) NGX_ERROR) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid segment duration value \"%V\"", - &value[i]); - return NGX_CONF_ERROR; - } - - } else { - max_seg = min_seg * 2; - } - - continue; - } - - if (ngx_strncmp(value[i].data, "analyze=", 8) == 0) { - - s.len = value[i].len - 8; - s.data = value[i].data + 8; - - analyze = ngx_parse_time(&s, 0); - if (analyze == (ngx_msec_t) NGX_ERROR) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid analyze duration value \"%V\"", - &value[i]); - return NGX_CONF_ERROR; - } - - continue; - } - - if (ngx_strncmp(value[i].data, "max_size=", 9) == 0) { - - s.len = value[i].len - 9; - s.data = value[i].data + 9; - - max_size = ngx_parse_size(&s); - if (max_size == NGX_ERROR) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid max segment size value \"%V\"", - &value[i]); - return NGX_CONF_ERROR; - } - - continue; - } - - if (ngx_strncmp(value[i].data, "segments=", 9) == 0) { - - v = ngx_atoi(value[i].data + 9, value[i].len - 9); - if (v == NGX_ERROR) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid segments number value \"%V\"", - &value[i]); - return NGX_CONF_ERROR; - } - - nsegs = v; - - continue; - } - - if (ngx_strcmp(value[i].data, "noclean") == 0) { - clean = 0; - continue; - } - - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid parameter \"%V\"", &value[i]); - return NGX_CONF_ERROR; - } - - if (path.len == 0) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "\"%V\" must have \"path\" parameter", &cmd->name); - return NGX_CONF_ERROR; - } - - hls = ngx_pcalloc(cf->pool, sizeof(ngx_ts_hls_conf_t)); - if (hls == NULL) { - return NGX_CONF_ERROR; - } - - hls->path = ngx_pcalloc(cf->pool, sizeof(ngx_path_t)); - if (hls->path == NULL) { - return NGX_CONF_ERROR; - } - - hls->path->name = path; - - hls->min_seg = min_seg; - hls->max_seg = max_seg; - hls->analyze = analyze ? analyze : min_seg; - hls->max_size = max_size; - hls->nsegs = nsegs; - - if (clean) { - hls->path->manager = ngx_ts_hls_file_manager; - } - - hls->path->data = hls; - hls->path->conf_file = cf->conf_file->file.name.data; - hls->path->line = cf->conf_file->line; - - if (ngx_add_path(cf, &hls->path) != NGX_OK) { - return NGX_CONF_ERROR; - } - - *field = hls; - - return NGX_CONF_OK; -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_hls.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_hls.h deleted file mode 100644 index 031f018c52..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_hls.h +++ /dev/null @@ -1,75 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include - -#include "ngx_ts_stream.h" - - -#ifndef _NGX_TS_HLS_H_INCLUDED_ -#define _NGX_TS_HLS_H_INCLUDED_ - - -typedef struct { - ngx_path_t *path; - ngx_msec_t min_seg; - ngx_msec_t max_seg; - ngx_msec_t analyze; - size_t max_size; - ngx_uint_t nsegs; -} ngx_ts_hls_conf_t; - - -typedef struct { - ngx_uint_t id; - uint64_t duration; - off_t size; -} ngx_ts_hls_segment_t; - - -typedef struct { - ngx_file_t file; - ngx_chain_t *prologue; - - ngx_uint_t bandwidth; - ngx_uint_t bandwidth_bytes; - uint64_t bandwidth_dts; - - ngx_ts_hls_segment_t *segs; - ngx_uint_t nsegs; - ngx_uint_t seg; - uint64_t seg_dts; - - u_char *m3u8_path; - u_char *m3u8_tmp_path; - ngx_str_t path; - - ngx_ts_program_t *prog; -} ngx_ts_hls_variant_t; - - -typedef struct { - ngx_ts_stream_t *ts; - ngx_ts_hls_conf_t *conf; - - u_char *m3u8_path; - u_char *m3u8_tmp_path; - ngx_str_t path; - - ngx_ts_hls_variant_t *vars; - ngx_uint_t nvars; - - ngx_uint_t done; /* unsigned done:1; */ -} ngx_ts_hls_t; - - -ngx_ts_hls_t *ngx_ts_hls_create(ngx_ts_hls_conf_t *conf, ngx_ts_stream_t *ts, - ngx_str_t *name); -char *ngx_ts_hls_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); - - -#endif /* _NGX_TS_HLS_H_INCLUDED_ */ diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_stream.c b/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_stream.c deleted file mode 100644 index b778040d94..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_stream.c +++ /dev/null @@ -1,1496 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include - -#include "ngx_ts_stream.h" - - -#define NGX_TS_PACKET_SIZE 188 - - -typedef struct { - ngx_chain_t *cl; - u_char *p; -} ngx_ts_byte_read_t; - - -typedef struct { - unsigned pusi:1; - unsigned cont:4; - unsigned rand:1; - unsigned pcrf:1; - unsigned stuff:1; - uint16_t pid; - uint64_t pcr; -} ngx_ts_header_t; - - -static ngx_int_t ngx_ts_run_handlers(ngx_ts_event_e event, ngx_ts_stream_t *ts, - ngx_ts_program_t *prog, ngx_ts_es_t *es, ngx_chain_t *bufs); -static void ngx_ts_byte_read_init(ngx_ts_byte_read_t *br, ngx_chain_t *cl); -static ngx_int_t ngx_ts_byte_read(ngx_ts_byte_read_t *br, u_char *dst, - size_t len); -static ngx_int_t ngx_ts_byte_read_skip(ngx_ts_byte_read_t *br, size_t len); -static ngx_int_t ngx_ts_byte_read8(ngx_ts_byte_read_t *br, u_char *v); -static ngx_int_t ngx_ts_byte_read16(ngx_ts_byte_read_t *br, uint16_t *v); - -static ssize_t ngx_ts_read_header(ngx_ts_stream_t *ts, u_char *p, - ngx_ts_header_t *h); -static ngx_int_t ngx_ts_read_packet(ngx_ts_stream_t *ts, ngx_buf_t *b); -static ngx_int_t ngx_ts_read_pat(ngx_ts_stream_t *ts, ngx_ts_header_t *h, - ngx_buf_t *b); -static ngx_int_t ngx_ts_read_pmt(ngx_ts_stream_t *ts, ngx_ts_program_t *prog, - ngx_ts_header_t *h, ngx_buf_t *b); -static ngx_int_t ngx_ts_read_pes(ngx_ts_stream_t *ts, ngx_ts_program_t *prog, - ngx_ts_es_t *es, ngx_ts_header_t *h, ngx_buf_t *b); -static ngx_chain_t *ngx_ts_packetize(ngx_ts_stream_t *ts, ngx_ts_header_t *h, - ngx_chain_t *in); - -static ngx_int_t ngx_ts_free_buf(ngx_ts_stream_t *ts, ngx_buf_t *b); -static ngx_int_t ngx_ts_append_buf(ngx_ts_stream_t *ts, ngx_ts_header_t *h, - ngx_chain_t **ll, ngx_buf_t *b); -static uint32_t ngx_ts_crc32(u_char *p, size_t len); - - -static uint32_t ngx_ts_crc32_table_ieee[] = { - 0x00000000, 0xb71dc104, 0x6e3b8209, 0xd926430d, - 0xdc760413, 0x6b6bc517, 0xb24d861a, 0x0550471e, - 0xb8ed0826, 0x0ff0c922, 0xd6d68a2f, 0x61cb4b2b, - 0x649b0c35, 0xd386cd31, 0x0aa08e3c, 0xbdbd4f38, - 0x70db114c, 0xc7c6d048, 0x1ee09345, 0xa9fd5241, - 0xacad155f, 0x1bb0d45b, 0xc2969756, 0x758b5652, - 0xc836196a, 0x7f2bd86e, 0xa60d9b63, 0x11105a67, - 0x14401d79, 0xa35ddc7d, 0x7a7b9f70, 0xcd665e74, - 0xe0b62398, 0x57abe29c, 0x8e8da191, 0x39906095, - 0x3cc0278b, 0x8bdde68f, 0x52fba582, 0xe5e66486, - 0x585b2bbe, 0xef46eaba, 0x3660a9b7, 0x817d68b3, - 0x842d2fad, 0x3330eea9, 0xea16ada4, 0x5d0b6ca0, - 0x906d32d4, 0x2770f3d0, 0xfe56b0dd, 0x494b71d9, - 0x4c1b36c7, 0xfb06f7c3, 0x2220b4ce, 0x953d75ca, - 0x28803af2, 0x9f9dfbf6, 0x46bbb8fb, 0xf1a679ff, - 0xf4f63ee1, 0x43ebffe5, 0x9acdbce8, 0x2dd07dec, - 0x77708634, 0xc06d4730, 0x194b043d, 0xae56c539, - 0xab068227, 0x1c1b4323, 0xc53d002e, 0x7220c12a, - 0xcf9d8e12, 0x78804f16, 0xa1a60c1b, 0x16bbcd1f, - 0x13eb8a01, 0xa4f64b05, 0x7dd00808, 0xcacdc90c, - 0x07ab9778, 0xb0b6567c, 0x69901571, 0xde8dd475, - 0xdbdd936b, 0x6cc0526f, 0xb5e61162, 0x02fbd066, - 0xbf469f5e, 0x085b5e5a, 0xd17d1d57, 0x6660dc53, - 0x63309b4d, 0xd42d5a49, 0x0d0b1944, 0xba16d840, - 0x97c6a5ac, 0x20db64a8, 0xf9fd27a5, 0x4ee0e6a1, - 0x4bb0a1bf, 0xfcad60bb, 0x258b23b6, 0x9296e2b2, - 0x2f2bad8a, 0x98366c8e, 0x41102f83, 0xf60dee87, - 0xf35da999, 0x4440689d, 0x9d662b90, 0x2a7bea94, - 0xe71db4e0, 0x500075e4, 0x892636e9, 0x3e3bf7ed, - 0x3b6bb0f3, 0x8c7671f7, 0x555032fa, 0xe24df3fe, - 0x5ff0bcc6, 0xe8ed7dc2, 0x31cb3ecf, 0x86d6ffcb, - 0x8386b8d5, 0x349b79d1, 0xedbd3adc, 0x5aa0fbd8, - 0xeee00c69, 0x59fdcd6d, 0x80db8e60, 0x37c64f64, - 0x3296087a, 0x858bc97e, 0x5cad8a73, 0xebb04b77, - 0x560d044f, 0xe110c54b, 0x38368646, 0x8f2b4742, - 0x8a7b005c, 0x3d66c158, 0xe4408255, 0x535d4351, - 0x9e3b1d25, 0x2926dc21, 0xf0009f2c, 0x471d5e28, - 0x424d1936, 0xf550d832, 0x2c769b3f, 0x9b6b5a3b, - 0x26d61503, 0x91cbd407, 0x48ed970a, 0xfff0560e, - 0xfaa01110, 0x4dbdd014, 0x949b9319, 0x2386521d, - 0x0e562ff1, 0xb94beef5, 0x606dadf8, 0xd7706cfc, - 0xd2202be2, 0x653deae6, 0xbc1ba9eb, 0x0b0668ef, - 0xb6bb27d7, 0x01a6e6d3, 0xd880a5de, 0x6f9d64da, - 0x6acd23c4, 0xddd0e2c0, 0x04f6a1cd, 0xb3eb60c9, - 0x7e8d3ebd, 0xc990ffb9, 0x10b6bcb4, 0xa7ab7db0, - 0xa2fb3aae, 0x15e6fbaa, 0xccc0b8a7, 0x7bdd79a3, - 0xc660369b, 0x717df79f, 0xa85bb492, 0x1f467596, - 0x1a163288, 0xad0bf38c, 0x742db081, 0xc3307185, - 0x99908a5d, 0x2e8d4b59, 0xf7ab0854, 0x40b6c950, - 0x45e68e4e, 0xf2fb4f4a, 0x2bdd0c47, 0x9cc0cd43, - 0x217d827b, 0x9660437f, 0x4f460072, 0xf85bc176, - 0xfd0b8668, 0x4a16476c, 0x93300461, 0x242dc565, - 0xe94b9b11, 0x5e565a15, 0x87701918, 0x306dd81c, - 0x353d9f02, 0x82205e06, 0x5b061d0b, 0xec1bdc0f, - 0x51a69337, 0xe6bb5233, 0x3f9d113e, 0x8880d03a, - 0x8dd09724, 0x3acd5620, 0xe3eb152d, 0x54f6d429, - 0x7926a9c5, 0xce3b68c1, 0x171d2bcc, 0xa000eac8, - 0xa550add6, 0x124d6cd2, 0xcb6b2fdf, 0x7c76eedb, - 0xc1cba1e3, 0x76d660e7, 0xaff023ea, 0x18ede2ee, - 0x1dbda5f0, 0xaaa064f4, 0x738627f9, 0xc49be6fd, - 0x09fdb889, 0xbee0798d, 0x67c63a80, 0xd0dbfb84, - 0xd58bbc9a, 0x62967d9e, 0xbbb03e93, 0x0cadff97, - 0xb110b0af, 0x060d71ab, 0xdf2b32a6, 0x6836f3a2, - 0x6d66b4bc, 0xda7b75b8, 0x035d36b5, 0xb440f7b1 -}; - - -ngx_int_t -ngx_ts_add_handler(ngx_ts_stream_t *ts, ngx_ts_handler_pt handler, void *data) -{ - ngx_ts_handler_t *h; - - h = ngx_palloc(ts->pool, sizeof(ngx_ts_handler_t)); - if (h == NULL) { - return NGX_ERROR; - } - - h->handler = handler; - h->data = data; - - h->next = ts->handlers; - ts->handlers = h; - - return NGX_OK; -} - - -static ngx_int_t -ngx_ts_run_handlers(ngx_ts_event_e event, ngx_ts_stream_t *ts, - ngx_ts_program_t *prog, ngx_ts_es_t *es, ngx_chain_t *bufs) -{ - ngx_ts_handler_t *h; - ngx_ts_handler_data_t hd; - - hd.event = event; - hd.ts = ts; - hd.prog = prog; - hd.es = es; - hd.bufs = bufs; - - for (h = ts->handlers; h; h = h->next) { - hd.data = h->data; - - if (h->handler(&hd) != NGX_OK) { - return NGX_ERROR; - } - } - - return NGX_OK; -} - - -static void -ngx_ts_byte_read_init(ngx_ts_byte_read_t *br, ngx_chain_t *cl) -{ - br->cl = cl; - br->p = cl ? cl->buf->pos : NULL; -} - - -static ngx_int_t -ngx_ts_byte_read(ngx_ts_byte_read_t *br, u_char *dst, size_t len) -{ - size_t n; - - while (br->cl && len) { - n = ngx_min((size_t) (br->cl->buf->last - br->p), len); - - if (dst) { - dst = ngx_cpymem(dst, br->p, n); - } - - br->p += n; - len -= n; - - if (br->p == br->cl->buf->last) { - br->cl = br->cl->next; - br->p = br->cl ? br->cl->buf->pos : NULL; - } - } - - return len ? NGX_AGAIN : NGX_OK; -} - - -static ngx_int_t -ngx_ts_byte_read_skip(ngx_ts_byte_read_t *br, size_t len) -{ - return ngx_ts_byte_read(br, NULL, len); -} - - -static ngx_int_t -ngx_ts_byte_read8(ngx_ts_byte_read_t *br, u_char *v) -{ - return ngx_ts_byte_read(br, v, 1); -} - - -static ngx_int_t -ngx_ts_byte_read16(ngx_ts_byte_read_t *br, uint16_t *v) -{ - if (ngx_ts_byte_read(br, (u_char *) v, 2) == NGX_AGAIN) { - return NGX_AGAIN; - } - -#if (NGX_HAVE_LITTLE_ENDIAN) - *v = htons(*v); -#endif - - return NGX_OK; -} - - -ngx_int_t -ngx_ts_read(ngx_ts_stream_t *ts, ngx_chain_t *in) -{ - size_t n, size; - ngx_buf_t *b; - ngx_chain_t *cl; - - ngx_log_debug0(NGX_LOG_DEBUG_CORE, ts->log, 0, "ts read"); - - for (/* void */; in; in = in->next) { - - while (in->buf->pos != in->buf->last) { - b = ts->buf; - - if (b == NULL) { - if (ts->free) { - cl = ts->free; - ts->free = cl->next; - - b = cl->buf; - ngx_free_chain(ts->pool, cl); - - b->pos = b->start; - b->last = b->start; - - } else { - b = ngx_create_temp_buf(ts->pool, NGX_TS_PACKET_SIZE); - if (b == NULL) { - return NGX_ERROR; - } - } - - ts->buf = b; - } - - n = b->end - b->last; - size = in->buf->last - in->buf->pos; - - if (n > size) { - n = size; - } - - b->last = ngx_cpymem(b->last, in->buf->pos, n); - in->buf->pos += n; - - if (b->last == b->end) { - if (ngx_ts_read_packet(ts, b) != NGX_OK) { - return NGX_ERROR; - } - - ts->buf = NULL; - } - } - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_ts_read_packet(ngx_ts_stream_t *ts, ngx_buf_t *b) -{ - ssize_t n; - ngx_uint_t i, j; - ngx_chain_t *cl; - ngx_ts_es_t *es; - ngx_ts_header_t h; - ngx_ts_program_t *prog; - - n = ngx_ts_read_header(ts, b->pos, &h); - - if (n == NGX_ERROR) { - return NGX_ERROR; - } - - if (n == NGX_DONE) { - b->pos = b->last; - - } else { - b->pos += n; - } - - if (h.pid == 0) { - return ngx_ts_read_pat(ts, &h, b); - } - - for (i = 0; i < ts->nprogs; i++) { - prog = &ts->progs[i]; - - if (h.pid == prog->pid) { - return ngx_ts_read_pmt(ts, prog, &h, b); - } - - for (j = 0; j < prog->nes; j++) { - es = &prog->es[j]; - - if (h.pid == es->pid) { - return ngx_ts_read_pes(ts, prog, es, &h, b); - } - } - } - - ngx_log_error(NGX_LOG_INFO, ts->log, 0, - "dropping unexpected TS packet pid:0x%04uxd", - (unsigned) h.pid); - - cl = ngx_alloc_chain_link(ts->pool); - if (cl == NULL) { - return NGX_ERROR; - } - - cl->buf = b; - cl->next = ts->free; - ts->free = cl; - - return NGX_OK; -} - - -static ssize_t -ngx_ts_read_header(ngx_ts_stream_t *ts, u_char *p, ngx_ts_header_t *h) -{ - /* - * TS Packet Header - * ISO/IEC 13818-1 : 2000 (E) - * 2.4.3.2 Transport Stream packet layer, p. 18 - */ - - u_char alen, afic; - ssize_t n; - uint64_t pcrb, pcre; - - /* sync_byte */ - if (*p++ != 0x47) { - ngx_log_error(NGX_LOG_ERR, ts->log, 0, "invalid TS sync byte"); - return NGX_ERROR; - } - - ngx_memzero(h, sizeof(ngx_ts_header_t)); - - /* payload_unit_start_indicator */ - h->pusi = (*p & 0x40) ? 1 : 0; - - /* PID */ - h->pid = *p++ & 0x1f; - h->pid = (h->pid << 8) + *p++; - - /* adaptation_field_control */ - afic = (*p & 0x30) >> 4; - - /* continuity_counter */ - h->cont = *p++ & 0x0f; - - if (afic == 0) { - ngx_log_error(NGX_LOG_ERR, ts->log, 0, "invalid TS packet"); - return NGX_ERROR; - } - - n = 4; - - if (afic & 0x02) { - /* adaptation_field_length */ - alen = *p++; - - if (alen > 183) { - ngx_log_error(NGX_LOG_ERR, ts->log, 0, - "too long TS adaptation field"); - return NGX_ERROR; - } - - if (afic & 0x01) { - n += alen + 1; - - } else { - n = NGX_DONE; - } - - if (alen) { - /* random_access_indicator */ - h->rand = (*p & 0x40) ? 1 : 0; - - /* PCR_flag */ - h->pcrf = (*p & 0x10) ? 1 : 0; - - p++; - - if (h->pcrf) { - /* program_clock_reference_base */ - pcrb = *p++; - pcrb = (pcrb << 8) + *p++; - pcrb = (pcrb << 8) + *p++; - pcrb = (pcrb << 8) + *p++; - pcrb = (pcrb << 1) + (*p >> 7); - - /* program_clock_reference_extension */ - pcre = *p++ & 0x01; - pcre = (pcre << 8) + *p++; - - h->pcr = pcrb * 300 + pcre; - } - } - } - - ngx_log_debug6(NGX_LOG_DEBUG_CORE, ts->log, 0, "ts packet " - "pid:0x%04uxd, pusi:%d, c:%02d, r:%d, pcr:%uL, n:%uz", - (unsigned) h->pid, h->pusi, h->cont, h->rand, h->pcr, - n == NGX_DONE ? 0 : NGX_TS_PACKET_SIZE - n); - - return n; -} - - -static ngx_int_t -ngx_ts_read_pat(ngx_ts_stream_t *ts, ngx_ts_header_t *h, ngx_buf_t *b) -{ - /* - * PAT - * ISO/IEC 13818-1 : 2000 (E) - * 2.4.4.3 Program association Table, p. 43 - */ - - u_char ptr; - uint16_t len, number, pid; - ngx_uint_t nprogs, n; - ngx_ts_program_t *prog; - ngx_ts_byte_read_t br, pr; - - ngx_log_debug0(NGX_LOG_DEBUG_CORE, ts->log, 0, "ts pat"); - - if (ts->nprogs) { - ngx_log_debug0(NGX_LOG_DEBUG_CORE, ts->log, 0, - "ts dropping successive pat"); - return ngx_ts_free_buf(ts, b); - } - - if (ngx_ts_append_buf(ts, h, &ts->bufs, b) != NGX_OK) { - return NGX_ERROR; - } - - ngx_ts_byte_read_init(&br, ts->bufs); - - /* pointer_field */ - if (ngx_ts_byte_read8(&br, &ptr) == NGX_AGAIN) { - return NGX_OK; - } - - /* skipped bytes + table_id */ - if (ngx_ts_byte_read_skip(&br, ptr + 1) == NGX_AGAIN) { - return NGX_OK; - } - - /* section_length */ - if (ngx_ts_byte_read16(&br, &len) == NGX_AGAIN) { - return NGX_OK; - } - - len &= 0x0fff; - - if (len < 9) { - ngx_log_error(NGX_LOG_ERR, ts->log, 0, "malformed PAT"); - return NGX_ERROR; - } - - if (len > 0x03fd) { - ngx_log_error(NGX_LOG_ERR, ts->log, 0, "too big PAT: %ud", - (unsigned) len); - return NGX_ERROR; - } - - pr = br; - - if (ngx_ts_byte_read_skip(&pr, len) == NGX_AGAIN) { - return NGX_OK; - } - - /* PAT is fully available */ - - /* transport_stream_id .. last_section_number */ - ngx_ts_byte_read_skip(&br, 5); - - nprogs = (len - 9) / 4; - - ts->progs = ngx_pcalloc(ts->pool, - nprogs * sizeof(ngx_ts_program_t)); - if (ts->progs == NULL) { - return NGX_ERROR; - } - - prog = ts->progs; - - for (n = 0; n < nprogs; n++) { - /* program_number */ - (void) ngx_ts_byte_read16(&br, &number); - - /* network_PID / program_map_PID */ - (void) ngx_ts_byte_read16(&br, &pid); - - if (number) { - pid = pid & 0x1fff; - - prog->number = number; - prog->pid = pid; - prog++; - - ngx_log_debug2(NGX_LOG_DEBUG_CORE, ts->log, 0, - "ts program %ud, pid:0x%04uxd", - (unsigned) number, (unsigned) pid); - } - } - - ts->nprogs = prog - ts->progs; - - if (ngx_ts_run_handlers(NGX_TS_PAT, ts, NULL, NULL, NULL) != NGX_OK) { - return NGX_ERROR; - } - - ngx_ts_free_chain(ts, &ts->bufs); - - return NGX_OK; -} - - -static ngx_int_t -ngx_ts_read_pmt(ngx_ts_stream_t *ts, ngx_ts_program_t *prog, ngx_ts_header_t *h, - ngx_buf_t *b) -{ - /* - * PMT - * ISO/IEC 13818-1 : 2000 (E) - * 2.4.4.8 Program Map Table, p. 46 - */ - - u_char ptr, type; - uint16_t len, pilen, elen, pid; - ngx_uint_t nes, n; - ngx_ts_es_t *es; - ngx_ts_byte_read_t br, pr; - - ngx_log_debug0(NGX_LOG_DEBUG_CORE, ts->log, 0, "ts pmt"); - - if (prog->nes) { - ngx_log_debug0(NGX_LOG_DEBUG_CORE, ts->log, 0, - "ts dropping successive pmt"); - return ngx_ts_free_buf(ts, b); - } - - if (ngx_ts_append_buf(ts, h, &prog->bufs, b) != NGX_OK) { - return NGX_ERROR; - } - - ngx_ts_byte_read_init(&br, prog->bufs); - - /* pointer_field */ - if (ngx_ts_byte_read8(&br, &ptr) == NGX_AGAIN) { - return NGX_OK; - } - - /* skipped bytes + table_id */ - if (ngx_ts_byte_read_skip(&br, ptr + 1) == NGX_AGAIN) { - return NGX_OK; - } - - /* section_length */ - if (ngx_ts_byte_read16(&br, &len) == NGX_AGAIN) { - return NGX_OK; - } - - len &= 0x0fff; - - if (len < 13) { - ngx_log_error(NGX_LOG_ERR, ts->log, 0, "malformed PMT"); - return NGX_ERROR; - } - - if (len > 0x03fd) { - ngx_log_error(NGX_LOG_ERR, ts->log, 0, "too big PMT: %ud", - (unsigned) len); - return NGX_ERROR; - } - - pr = br; - - if (ngx_ts_byte_read_skip(&pr, len) == NGX_AGAIN) { - return NGX_OK; - } - - /* PMT is fully available */ - - /* program_number .. last_sesion_number */ - (void) ngx_ts_byte_read_skip(&br, 5); - - /* PCR_PID */ - (void) ngx_ts_byte_read16(&br, &pid); - - prog->pcr_pid = pid & 0x1fff; - - /* program_info_length */ - (void) ngx_ts_byte_read16(&br, &pilen); - - pilen &= 0x0fff; - - if (ngx_ts_byte_read_skip(&br, pilen) == NGX_AGAIN - || len < 13 + pilen) - { - ngx_log_error(NGX_LOG_ERR, ts->log, 0, "malformed PMT"); - return NGX_ERROR; - } - - len -= 13 + pilen; - - pr = br; - - for (nes = 0; len > 0; nes++) { - if (ngx_ts_byte_read(&pr, NULL, 3) == NGX_AGAIN - || ngx_ts_byte_read16(&pr, &elen) == NGX_AGAIN - || ngx_ts_byte_read(&pr, NULL, elen & 0x0fff) == NGX_AGAIN - || len < 5 + (elen & 0x0fff)) - { - ngx_log_error(NGX_LOG_ERR, ts->log, 0, "malformed PMT"); - return NGX_ERROR; - } - - len -= 5 + (elen & 0x0fff); - } - - es = ngx_pcalloc(ts->pool, nes * sizeof(ngx_ts_es_t)); - if (es == NULL) { - return NGX_ERROR; - } - - prog->es = es; - prog->nes = nes; - - for (n = 0; n < nes; n++, es++) { - /* stream_type */ - (void) ngx_ts_byte_read8(&br, &type); - - /* elementary_PID */ - (void) ngx_ts_byte_read16(&br, &pid); - - /* ES_info_length */ - (void) ngx_ts_byte_read16(&br, &elen); - - /* ES_info */ - (void) ngx_ts_byte_read_skip(&br, elen & 0x0fff); - - pid = pid & 0x1fff; - - es->type = type; - es->pid = pid; - - if (type == NGX_TS_VIDEO_MPEG1 - || type == NGX_TS_VIDEO_MPEG2 - || type == NGX_TS_VIDEO_MPEG4 - || type == NGX_TS_VIDEO_AVC) - { - es->video = 1; - prog->video = 1; - } - - ngx_log_debug3(NGX_LOG_DEBUG_CORE, ts->log, 0, - "ts es type:%ui, video:%d, pid:0x%04uxd", - (ngx_uint_t) type, es->video, (unsigned) pid); - } - - if (ngx_ts_run_handlers(NGX_TS_PMT, ts, prog, NULL, NULL) != NGX_OK) { - return NGX_ERROR; - } - - ngx_ts_free_chain(ts, &prog->bufs); - - return NGX_OK; -} - - -static ngx_int_t -ngx_ts_read_pes(ngx_ts_stream_t *ts, ngx_ts_program_t *prog, ngx_ts_es_t *es, - ngx_ts_header_t *h, ngx_buf_t *b) -{ - /* - * PES Packet - * ISO/IEC 13818-1 : 2000 (E) - * 2.4.3.6 PES packet, p. 31 - */ - - u_char sid, pfx[3], v8, hlen; - uint16_t len, flags, v16; - uint64_t pts, dts; - ngx_uint_t ptsf; - ngx_ts_byte_read_t br, pr; - - ngx_log_debug0(NGX_LOG_DEBUG_CORE, ts->log, 0, "ts pes"); - - if (es->bufs && h->pusi && b) { - if (ngx_ts_read_pes(ts, prog, es, h, NULL) != NGX_OK) { - return NGX_ERROR; - } - } - - if (es->bufs == NULL) { - es->rand = h->rand; - } - - if (h->pcrf && prog->pcr_pid == es->pid) { - prog->pcr = h->pcr; - } - - if (ngx_ts_append_buf(ts, h, &es->bufs, b) != NGX_OK) { - return NGX_ERROR; - } - - ngx_ts_byte_read_init(&br, es->bufs); - - /* packet_start_code_prefix */ - if (ngx_ts_byte_read(&br, pfx, 3) == NGX_AGAIN) { - return NGX_OK; - } - - if (pfx[0] != 0 || pfx[1] != 0 || pfx[2] != 1) { - ngx_log_error(NGX_LOG_INFO, ts->log, 0, "missing PES start prefix"); - return NGX_ERROR; - } - - /* stream_id */ - if (ngx_ts_byte_read8(&br, &sid) == NGX_AGAIN) { - return NGX_OK; - } - - es->sid = sid; - - /* PES_packet_length */ - if (ngx_ts_byte_read16(&br, &len) == NGX_AGAIN) { - return NGX_OK; - } - - if (len) { - pr = br; - - if (ngx_ts_byte_read_skip(&pr, len) == NGX_AGAIN) { - return NGX_OK; - } - - } else if (b) { - /* wait for PUSI */ - return NGX_OK; - } - - /* PES is fully available */ - - if (sid == 0xbe) { /* padding_stream */ - ngx_ts_free_chain(ts, &es->bufs); - return NGX_OK; - } - - ptsf = 0; - - if (sid != 0xbc /* program_stream_map */ - && sid != 0xbf /* private_stream_2 */ - && sid != 0xf0 /* ECM_stream */ - && sid != 0xf1 /* EMM_stream */ - && sid != 0xff /* program_stream_directory */ - && sid != 0xf2 /* DSMCC_stream */ - && sid != 0xf8) /* ITU-T Rec. H.222.1 type E stream */ - { - /* PES_scrambling_control .. PES_extension_flag */ - if (ngx_ts_byte_read16(&br, &flags) == NGX_AGAIN) { - return NGX_OK; - } - - /* PES_header_data_length */ - if (ngx_ts_byte_read8(&br, &hlen) == NGX_AGAIN) { - return NGX_OK; - } - - if (len) { - if (len < 3 + hlen) { - ngx_log_error(NGX_LOG_INFO, ts->log, 0, "malformed PES"); - return NGX_ERROR; - } - - len -= 3 + hlen; - } - - pr = br; - - if (ngx_ts_byte_read_skip(&br, hlen) == NGX_AGAIN) { - return NGX_OK; - } - - if ((flags & 0x00c0) == 0x0080) { /* PTS_DTS_flags == '10' */ - ptsf = 1; - - /* PTS[32..30] */ - if (ngx_ts_byte_read8(&pr, &v8) == NGX_AGAIN) { - return NGX_OK; - } - - pts = (uint64_t) (v8 & 0x0e) << 29; - - /* PTS[29..15] */ - if (ngx_ts_byte_read16(&pr, &v16) == NGX_AGAIN) { - return NGX_OK; - } - - pts |= (uint64_t) (v16 & 0xfffe) << 14; - - /* PTS[14..0] */ - if (ngx_ts_byte_read16(&pr, &v16) == NGX_AGAIN) { - return NGX_OK; - } - - pts |= v16 >> 1; - - es->pts = pts; - es->dts = pts; - - ngx_log_debug1(NGX_LOG_DEBUG_CORE, ts->log, 0, - "ts pes pts:%uL", pts); - } - - if ((flags & 0x00c0) == 0x00c0) { /* PTS_DTS_flags == '11' */ - ptsf = 1; - - /* PTS[32..30] */ - if (ngx_ts_byte_read8(&pr, &v8) == NGX_AGAIN) { - return NGX_OK; - } - - pts = (uint64_t) (v8 & 0x0e) << 29; - - /* PTS[29..15] */ - if (ngx_ts_byte_read16(&pr, &v16) == NGX_AGAIN) { - return NGX_OK; - } - - pts |= (uint64_t) (v16 & 0xfffe) << 14; - - /* PTS[14..0] */ - if (ngx_ts_byte_read16(&pr, &v16) == NGX_AGAIN) { - return NGX_OK; - } - - pts |= v16 >> 1; - - /* DTS[32..30] */ - if (ngx_ts_byte_read8(&pr, &v8) == NGX_AGAIN) { - return NGX_OK; - } - - dts = (uint64_t) (v8 & 0x0e) << 29; - - /* DTS[29..15] */ - if (ngx_ts_byte_read16(&pr, &v16) == NGX_AGAIN) { - return NGX_OK; - } - - dts |= (uint64_t) (v16 & 0xfffe) << 14; - - /* DTS[14..0] */ - if (ngx_ts_byte_read16(&pr, &v16) == NGX_AGAIN) { - return NGX_OK; - } - - dts |= v16 >> 1; - - es->pts = pts; - es->dts = dts; - - ngx_log_debug2(NGX_LOG_DEBUG_CORE, ts->log, 0, - "ts pes pts:%uL, dts:%uL", pts, dts); - } - } - - if (br.cl) { - br.cl->buf->pos = br.p; - } - - if (len) { - pr = br; - - if (ngx_ts_byte_read_skip(&pr, len) == NGX_AGAIN) { - return NGX_OK; - } - - if (pr.cl) { - pr.cl->buf->last = pr.p; - } - } - - es->ptsf = ptsf; - - if (ngx_ts_run_handlers(NGX_TS_PES, ts, prog, es, br.cl) != NGX_OK) { - return NGX_ERROR; - } - - ngx_ts_free_chain(ts, &es->bufs); - - return NGX_OK; -} - - -ngx_chain_t * -ngx_ts_write_pat(ngx_ts_stream_t *ts, ngx_ts_program_t *prog) -{ - size_t len; - u_char *p, *data; - uint32_t crc; - ngx_buf_t b; - ngx_uint_t n, nprogs; - ngx_chain_t in; - ngx_ts_header_t h; - - if (prog) { - nprogs = 1; - - } else { - nprogs = ts->nprogs; - prog = ts->progs; - } - - len = 9 + nprogs * 4; - - data = ngx_pnalloc(ts->pool, 4 + len); - if (data == NULL) { - return NULL; - } - - p = data; - - /* pointer_field */ - *p++ = 0; - - /* table_id */ - *p++ = 0; - - /* section_syntax_indicator, section_length */ - *p++ = 0x80 | (u_char) (len >> 8); - *p++ = (u_char) len; - - /* transport_stream_id */ - *p++ = 0; - *p++ = 0; - - /* version_number, current_next_indicator */ - *p++ = 0x01; - - /* section_number */ - *p++ = 0; - - /* last_section_number */ - *p++ = 0; - - for (n = 0; n < nprogs; n++, prog++) { - /* program_number */ - *p++ = (u_char) (prog->number >> 8); - *p++ = (u_char) prog->number; - - /* program_map_PID */ - *p++ = (u_char) (prog->pid >> 8); - *p++ = (u_char) prog->pid; - } - - crc = ngx_ts_crc32(data + 1, p - data - 1); - - *p++ = (u_char) crc; - *p++ = (u_char) (crc >> 8); - *p++ = (u_char) (crc >> 16); - *p++ = (u_char) (crc >> 24); - - ngx_memzero(&b, sizeof(ngx_buf_t)); - - b.start = data; - b.pos = data; - b.last = p; - b.end = p; - - in.buf = &b; - in.next = NULL; - - ngx_memzero(&h, sizeof(ngx_ts_header_t)); - - return ngx_ts_packetize(ts, &h, &in); -} - - -ngx_chain_t * -ngx_ts_write_pmt(ngx_ts_stream_t *ts, ngx_ts_program_t *prog) -{ - size_t len; - u_char *p, *data; - uint32_t crc; - ngx_buf_t b; - ngx_uint_t n; - ngx_chain_t in; - ngx_ts_es_t *es; - ngx_ts_header_t h; - - len = 13 + 5 * prog->nes; - - data = ngx_pnalloc(ts->pool, 4 + len); - if (data == NULL) { - return NULL; - } - - p = data; - - /* pointer_field */ - *p++ = 0; - - /* table_id */ - *p++ = 0x02; - - /* section_syntax_indicator */ - *p++ = 0x80 | (u_char) (len >> 8); - *p++ = (u_char) len; - - /* program_number */ - *p++ = (u_char) (prog->number >> 8); - *p++ = (u_char) prog->number; - - /* version_number, current_next_indicator */ - *p++ = 0x01; - - /* section_number */ - *p++ = 0; - - /* last_section_number */ - *p++ = 0; - - /* PCR_PID */ - *p++ = (u_char) (prog->pcr_pid >> 8); - *p++ = (u_char) prog->pcr_pid; - - /* program_info_length */ - *p++ = 0; - *p++ = 0; - - for (n = 0; n < prog->nes; n++) { - es = &prog->es[n]; - - /* stream_type */ - *p++ = es->type; - - /* elementary_PID */ - *p++ = (u_char) (es->pid >> 8); - *p++ = (u_char) es->pid; - - /* ES_info_length */ - *p++ = 0; - *p++ = 0; - } - - crc = ngx_ts_crc32(data + 1, p - data - 1); - - *p++ = (u_char) crc; - *p++ = (u_char) (crc >> 8); - *p++ = (u_char) (crc >> 16); - *p++ = (u_char) (crc >> 24); - - ngx_memzero(&b, sizeof(ngx_buf_t)); - - b.start = data; - b.pos = data; - b.last = p; - b.end = p; - - in.buf = &b; - in.next = NULL; - - ngx_memzero(&h, sizeof(ngx_ts_header_t)); - - h.pid = prog->pid; - - return ngx_ts_packetize(ts, &h, &in); -} - - -ngx_chain_t * -ngx_ts_write_pes(ngx_ts_stream_t *ts, ngx_ts_program_t *prog, ngx_ts_es_t *es, - ngx_chain_t *bufs) -{ - size_t len; - u_char *p, *plen, *phflags, *phlen; - ngx_buf_t b; - ngx_chain_t in, *cl, *out; - ngx_ts_header_t h; - u_char buf[19]; - - p = buf; - - /* packet_start_code_prefix */ - *p++ = 0; - *p++ = 0; - *p++ = 1; - - /* stream_id */ - *p++ = es->sid; - - /* PES_packet_length */ - plen = p; - *p++ = 0; - *p++ = 0; - - if (es->sid != 0xbc /* program_stream_map */ - && es->sid != 0xbe /* padding_stream */ - && es->sid != 0xbf /* private_stream_2 */ - && es->sid != 0xf0 /* ECM_stream */ - && es->sid != 0xf1 /* EMM_stream */ - && es->sid != 0xff /* program_stream_directory */ - && es->sid != 0xf2 /* DSMCC_stream */ - && es->sid != 0xf8) /* ITU-T Rec. H.222.1 type E stream */ - { - /* PES_scrambling_control .. original_or_copy */ - *p++ = 0x80; - - /* XXX ptsf */ - - /* PTS_DTS_flags .. PES_extension_flag */ - phflags = p; - *p++ = 0; - - /* PES_header_data_lenth */ - phlen = p; - *p++ = 0; - - if (es->pts == es->dts) { - *phlen += 5; - *phflags |= 0x80; - - /* PTS */ - *p++ = 0x21 | (u_char) ((es->pts >> 29) & 0x0e); - *p++ = (u_char) (es->pts >> 22); - *p++ = 0x01 | (u_char) (es->pts >> 14); - *p++ = (u_char) (es->pts >> 7); - *p++ = 0x01 | (u_char) (es->pts << 1); - - } else { - *phlen += 10; - *phflags |= 0xc0; - - /* PTS */ - *p++ = 0x31 | (u_char) ((es->pts >> 29) & 0x0e); - *p++ = (u_char) (es->pts >> 22); - *p++ = 0x01 | (u_char) (es->pts >> 14); - *p++ = (u_char) (es->pts >> 7); - *p++ = 0x01 | (u_char) (es->pts << 1); - - /* DTS */ - *p++ = 0x11 | (u_char) ((es->dts >> 29) & 0x0e); - *p++ = (u_char) (es->dts >> 22); - *p++ = 0x01 | (u_char) (es->dts >> 14); - *p++ = (u_char) (es->dts >> 7); - *p++ = 0x01 | (u_char) (es->dts << 1); - } - } - - len = p - plen - 2; - for (cl = bufs; cl; cl = cl->next) { - len += cl->buf->last - cl->buf->pos; - } - - if (len <= 0xffff) { - *plen++ = (u_char) (len >> 8); - *plen++ = (u_char) len; - } - - ngx_memzero(&b, sizeof(ngx_buf_t)); - - b.start = buf; - b.pos = buf; - b.last = p; - b.end = p; - - in.buf = &b; - in.next = bufs; - - ngx_memzero(&h, sizeof(ngx_ts_header_t)); - - h.pid = es->pid; - h.rand = es->rand; - h.cont = es->cont; - h.stuff = 1; - - if (prog->pcr_pid == es->pid) { - h.pcrf = 1; - h.pcr = prog->pcr; - } - - out = ngx_ts_packetize(ts, &h, &in); - if (out == NULL) { - return NULL; - } - - es->cont = h.cont; - - return out; -} - - -static ngx_chain_t * -ngx_ts_packetize(ngx_ts_stream_t *ts, ngx_ts_header_t *h, ngx_chain_t *in) -{ - u_char *p, *ip, *af, *aflen; - size_t n, left; - uint64_t pcrb, pcre; - ngx_buf_t *b; - ngx_chain_t *out, *cl, **ll; - - left = 0; - - for (cl = in; cl; cl = cl->next) { - left += cl->buf->last - cl->buf->pos; - } - - ip = in->buf->pos; - - ll = &out; - - do { - if (ts->free) { - cl = ts->free; - ts->free = cl->next; - b = cl->buf; - - } else { - ngx_log_debug1(NGX_LOG_DEBUG_CORE, ts->log, 0, - "ts alloc buffer:%d", NGX_TS_PACKET_SIZE); - - b = ngx_create_temp_buf(ts->pool, NGX_TS_PACKET_SIZE); - if (b == NULL) { - return NULL; - } - - cl = ngx_alloc_chain_link(ts->pool); - if (cl == NULL) { - return NULL; - } - - cl->buf = b; - } - - b->pos = b->start; - b->last = b->end; - - p = b->pos; - - /* sync_byte */ - *p++ = 0x47; - - /* payload_unit_start_indicator, PID */ - *p++ = (ll == &out ? 0x40 : 0x00) | (u_char) (h->pid >> 8); - *p++ = (u_char) h->pid; - - /* payload_present, continuity_counter */ - af = p; - *p++ = 0x10 | h->cont; - h->cont = (h->cont + 1) & 0x0f; - - if (h->rand || h->pcrf || (h->stuff && left < 184)) { - /* adaptation_field_control */ - *af |= 0x20; - - /* adaptation_field_length */ - aflen = p; - *p++ = 1; - - /* random_access_indicator, PCR_flag */ - *p++ = (h->rand ? 0x40 : 0x00) | (h->pcrf ? 0x10 : 0x00); - - if (h->pcrf) { - pcrb = h->pcr / 300; - pcre = h->pcr % 300; - - /* - * program_clock_reference_base, - * program_clock_reference_extension - */ - *p++ = (u_char) (pcrb >> 25); - *p++ = (u_char) (pcrb >> 17); - *p++ = (u_char) (pcrb >> 9); - *p++ = (u_char) (pcrb >> 1); - *p++ = (u_char) (pcrb << 7) | (u_char) ((pcre >> 8) & 0x01); - *p++ = (u_char) pcre; - - *aflen += 6; - } - - if (h->stuff && left < (size_t) (b->end - p)) { - n = b->end - p - left; - - /* stuffing_byte */ - ngx_memset(p, '\xff', n); - p += n; - *aflen += n; - } - } - - /* data_byte */ - - while (p != b->end) { - n = ngx_min(in->buf->last - ip, b->end - p); - - p = ngx_cpymem(p, ip, n); - - left -= n; - ip += n; - - if (ip == in->buf->last) { - in = in->next; - if (in == NULL) { - ngx_memset(p, '\xff', b->end - p); - break; - } - - ip = in->buf->pos; - } - } - - h->rand = 0; - h->pcrf = 0; - - *ll = cl; - ll = &cl->next; - - } while (in); - - *ll = NULL; - - return out; -} - - -static ngx_int_t -ngx_ts_free_buf(ngx_ts_stream_t *ts, ngx_buf_t *b) -{ - ngx_chain_t *cl; - - cl = ngx_alloc_chain_link(ts->pool); - if (cl == NULL) { - return NGX_ERROR; - } - - cl->buf = b; - cl->next = ts->free; - ts->free = cl; - - return NGX_OK; -} - - -void -ngx_ts_free_chain(ngx_ts_stream_t *ts, ngx_chain_t **ll) -{ - ngx_chain_t **fl; - - if (*ll == NULL) { - return; - } - - fl = ll; - - while (*ll) { - ll = &(*ll)->next; - } - - *ll = ts->free; - ts->free = *fl; - - *fl = NULL; -} - - -static ngx_int_t -ngx_ts_append_buf(ngx_ts_stream_t *ts, ngx_ts_header_t *h, ngx_chain_t **ll, - ngx_buf_t *b) -{ - ngx_chain_t *cl; - - if (b == NULL) { - return NGX_OK; - } - - if (!h->pusi && *ll == NULL) { - ngx_log_error(NGX_LOG_INFO, ts->log, 0, "dropping orhaned TS packet"); - return ngx_ts_free_buf(ts, b); - } - - if (h->pusi && *ll) { - ngx_log_error(NGX_LOG_INFO, ts->log, 0, - "dropping unfinished TS packets"); - ngx_ts_free_chain(ts, ll); - } - - while (*ll) { - ll = &(*ll)->next; - } - - cl = ngx_alloc_chain_link(ts->pool); - if (cl == NULL) { - return NGX_ERROR; - } - - cl->buf = b; - cl->next = NULL; - - *ll = cl; - - return NGX_OK; -} - - -static uint32_t -ngx_ts_crc32(u_char *p, size_t len) -{ - uint32_t crc; - - crc = 0xffffffff; - - while (len--) { - crc = ngx_ts_crc32_table_ieee[(crc ^ *p++) & 0xff] ^ (crc >> 8); - } - - return crc; -} - - -ngx_uint_t -ngx_ts_dash_get_oti(u_char type) -{ - /* - * ISO/IEC 14496-1:2001(E) - * Table 8 - objectTypeIndication Values, p. 30 - */ - - switch (type) { - case NGX_TS_VIDEO_MPEG1: - return 0x6a; - - case NGX_TS_VIDEO_MPEG2: - /* treat as Main Profile */ - return 0x61; - - case NGX_TS_VIDEO_MPEG4: - return 0x20; - - case NGX_TS_VIDEO_AVC: - return 0x21; - - case NGX_TS_AUDIO_MPEG1: - return 0x6b; - - case NGX_TS_AUDIO_MPEG2: - return 0x69; - - case NGX_TS_AUDIO_AAC: - /* consider as ISO/IEC 14496-3 Audio */ - return 0x40; - - default: - return 0; - } -} diff --git a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_stream.h b/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_stream.h deleted file mode 100644 index bd031abacb..0000000000 --- a/package/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_stream.h +++ /dev/null @@ -1,113 +0,0 @@ - -/* - * Copyright (C) Roman Arutyunyan - */ - - -#include -#include - - -#ifndef _NGX_TS_STREAM_H_INCLUDED_ -#define _NGX_TS_STREAM_H_INCLUDED_ - - -/* - * ISO/IEC 13818-1 : 2000 (E) - * Table 2-29 – Stream type assignments, p. 48 - * - * ISO/IEC 13818-1:2007/Amd.3:2009 (E) - * Table 2-34 – Stream type assignments, p. 6 - */ - -#define NGX_TS_VIDEO_MPEG1 0x01 /* ISO/IEC 11172-2, MPEG-1 Video */ -#define NGX_TS_VIDEO_MPEG2 0x02 /* ISO/IEC 13818-2, MPEG-2 Video */ -#define NGX_TS_VIDEO_MPEG4 0x10 /* ISO/IEC 14496-2, MPEG-4 Video */ -#define NGX_TS_VIDEO_AVC 0x1b /* ISO/IEC 14496-10, AVC */ - -#define NGX_TS_AUDIO_MPEG1 0x03 /* ISO/IEC 11172-3, MPEG-1 Audio */ -#define NGX_TS_AUDIO_MPEG2 0x04 /* ISO/IEC 13818-3, MPEG-2 Audio */ -#define NGX_TS_AUDIO_AAC 0x0f /* ISO/IEC 13818-7, MPEG-2 AAC ADTS Audio */ - - -typedef enum { - NGX_TS_PAT = 0, - NGX_TS_PMT, - NGX_TS_PES -} ngx_ts_event_e; - - -typedef struct { - u_char type; - u_char sid; - u_char cont; - uint16_t pid; - uint64_t pts; - uint64_t dts; - unsigned ptsf:1; - unsigned rand:1; - unsigned video:1; - ngx_chain_t *bufs; /* ES */ -} ngx_ts_es_t; - - -typedef struct { - uint16_t number; - uint16_t pid; - uint16_t pcr_pid; - uint64_t pcr; - ngx_uint_t video; /* unisgned video:1; */ - ngx_uint_t nes; - ngx_ts_es_t *es; - ngx_chain_t *bufs; /* PMT */ -} ngx_ts_program_t; - - -typedef struct ngx_ts_handler_s ngx_ts_handler_t; - - -typedef struct { - ngx_uint_t nprogs; - ngx_ts_program_t *progs; - ngx_log_t *log; - ngx_pool_t *pool; - ngx_buf_t *buf; - ngx_chain_t *free; - ngx_chain_t *bufs; /* PAT */ - ngx_ts_handler_t *handlers; - void *data; -} ngx_ts_stream_t; - - -typedef struct { - ngx_ts_event_e event; - ngx_ts_stream_t *ts; - ngx_ts_program_t *prog; - ngx_ts_es_t *es; - ngx_chain_t *bufs; - void *data; -} ngx_ts_handler_data_t; - - -typedef ngx_int_t (*ngx_ts_handler_pt)(ngx_ts_handler_data_t *hd); - - -struct ngx_ts_handler_s { - ngx_ts_handler_pt handler; - void *data; - ngx_ts_handler_t *next; -}; - - -ngx_int_t ngx_ts_add_handler(ngx_ts_stream_t *ts, ngx_ts_handler_pt handler, - void *data); -ngx_int_t ngx_ts_read(ngx_ts_stream_t *ts, ngx_chain_t *in); -ngx_chain_t *ngx_ts_write_pat(ngx_ts_stream_t *ts, ngx_ts_program_t *prog); -ngx_chain_t *ngx_ts_write_pmt(ngx_ts_stream_t *ts, ngx_ts_program_t *prog); -ngx_chain_t *ngx_ts_write_pes(ngx_ts_stream_t *ts, ngx_ts_program_t *prog, - ngx_ts_es_t *es, ngx_chain_t *bufs); -void ngx_ts_free_chain(ngx_ts_stream_t *ts, ngx_chain_t **ll); -ngx_uint_t ngx_ts_dash_get_oti(u_char type); - - -#endif /* _NGX_TS_STREAM_H_INCLUDED_ */ diff --git a/package/lienol/luci-app-nginx-pingos/patches/101-feature_test_fix.patch b/package/lienol/luci-app-nginx-pingos/patches/101-feature_test_fix.patch deleted file mode 100644 index b867c88dd2..0000000000 --- a/package/lienol/luci-app-nginx-pingos/patches/101-feature_test_fix.patch +++ /dev/null @@ -1,116 +0,0 @@ ---- a/auto/cc/name -+++ b/auto/cc/name -@@ -7,7 +7,7 @@ if [ "$NGX_PLATFORM" != win32 ]; then - - ngx_feature="C compiler" - ngx_feature_name= -- ngx_feature_run=yes -+ ngx_feature_run= - ngx_feature_incs= - ngx_feature_path= - ngx_feature_libs= ---- a/auto/cc/conf -+++ b/auto/cc/conf -@@ -183,7 +183,7 @@ if [ "$NGX_PLATFORM" != win32 ]; then - else - ngx_feature="gcc builtin atomic operations" - ngx_feature_name=NGX_HAVE_GCC_ATOMIC -- ngx_feature_run=yes -+ ngx_feature_run=no - ngx_feature_incs= - ngx_feature_path= - ngx_feature_libs= -@@ -204,7 +204,7 @@ if [ "$NGX_PLATFORM" != win32 ]; then - else - ngx_feature="C99 variadic macros" - ngx_feature_name="NGX_HAVE_C99_VARIADIC_MACROS" -- ngx_feature_run=yes -+ ngx_feature_run=no - ngx_feature_incs="#include - #define var(dummy, ...) sprintf(__VA_ARGS__)" - ngx_feature_path= -@@ -218,7 +218,7 @@ if [ "$NGX_PLATFORM" != win32 ]; then - - ngx_feature="gcc variadic macros" - ngx_feature_name="NGX_HAVE_GCC_VARIADIC_MACROS" -- ngx_feature_run=yes -+ ngx_feature_run=no - ngx_feature_incs="#include - #define var(dummy, args...) sprintf(args)" - ngx_feature_path= ---- a/auto/os/linux -+++ b/auto/os/linux -@@ -36,7 +36,7 @@ fi - - ngx_feature="epoll" - ngx_feature_name="NGX_HAVE_EPOLL" --ngx_feature_run=yes -+ngx_feature_run=no - ngx_feature_incs="#include " - ngx_feature_path= - ngx_feature_libs= -@@ -110,7 +110,7 @@ ngx_feature_test="int fd; struct stat sb - CC_AUX_FLAGS="$cc_aux_flags -D_GNU_SOURCE" - ngx_feature="sendfile()" - ngx_feature_name="NGX_HAVE_SENDFILE" --ngx_feature_run=yes -+ngx_feature_run=no - ngx_feature_incs="#include - #include " - ngx_feature_path= -@@ -131,7 +131,7 @@ fi - CC_AUX_FLAGS="$cc_aux_flags -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64" - ngx_feature="sendfile64()" - ngx_feature_name="NGX_HAVE_SENDFILE64" --ngx_feature_run=yes -+ngx_feature_run=no - ngx_feature_incs="#include - #include " - ngx_feature_path= -@@ -149,7 +149,7 @@ ngx_include="sys/prctl.h"; . auto/includ - - ngx_feature="prctl(PR_SET_DUMPABLE)" - ngx_feature_name="NGX_HAVE_PR_SET_DUMPABLE" --ngx_feature_run=yes -+ngx_feature_run=no - ngx_feature_incs="#include " - ngx_feature_path= - ngx_feature_libs= ---- a/auto/unix -+++ b/auto/unix -@@ -840,7 +840,7 @@ ngx_feature_test="void *p; p = memalign( - - ngx_feature="mmap(MAP_ANON|MAP_SHARED)" - ngx_feature_name="NGX_HAVE_MAP_ANON" --ngx_feature_run=yes -+ngx_feature_run=no - ngx_feature_incs="#include " - ngx_feature_path= - ngx_feature_libs= -@@ -853,7 +853,7 @@ ngx_feature_test="void *p; - - ngx_feature='mmap("/dev/zero", MAP_SHARED)' - ngx_feature_name="NGX_HAVE_MAP_DEVZERO" --ngx_feature_run=yes -+ngx_feature_run=no - ngx_feature_incs="#include - #include - #include " -@@ -868,7 +868,7 @@ ngx_feature_test='void *p; int fd; - - ngx_feature="System V shared memory" - ngx_feature_name="NGX_HAVE_SYSVSHM" --ngx_feature_run=yes -+ngx_feature_run=no - ngx_feature_incs="#include - #include " - ngx_feature_path= -@@ -882,7 +882,7 @@ ngx_feature_test="int id; - - ngx_feature="POSIX semaphores" - ngx_feature_name="NGX_HAVE_POSIX_SEM" --ngx_feature_run=yes -+ngx_feature_run=no - ngx_feature_incs="#include " - ngx_feature_path= - ngx_feature_libs= diff --git a/package/lienol/luci-app-nginx-pingos/patches/102-sizeof_test_fix.patch b/package/lienol/luci-app-nginx-pingos/patches/102-sizeof_test_fix.patch deleted file mode 100644 index 7d2430eab9..0000000000 --- a/package/lienol/luci-app-nginx-pingos/patches/102-sizeof_test_fix.patch +++ /dev/null @@ -1,27 +0,0 @@ ---- a/auto/types/sizeof -+++ b/auto/types/sizeof -@@ -25,8 +25,14 @@ $NGX_INCLUDE_UNISTD_H - $NGX_INCLUDE_INTTYPES_H - $NGX_INCLUDE_AUTO_CONFIG_H - -+char object_code_block[] = { -+ '\n', 'e', '4', 'V', 'A', -+ '0', 'x', ('0' + sizeof($ngx_type)), -+ 'Y', '3', 'p', 'M', '\n' -+}; -+ - int main(void) { -- printf("%d", (int) sizeof($ngx_type)); -+ printf("dummy use of object_code_block to avoid gc-section: %c", object_code_block[0]); - return 0; - } - -@@ -40,7 +46,7 @@ eval "$ngx_test >> $NGX_AUTOCONF_ERR 2>& - - - if [ -x $NGX_AUTOTEST ]; then -- ngx_size=`$NGX_AUTOTEST` -+ ngx_size=`sed -ne 's/^e4VA0x\(.\)Y3pM$/\1/p' < $NGX_AUTOTEST` - echo " $ngx_size bytes" - fi - diff --git a/package/lienol/luci-app-nginx-pingos/patches/103-sys_nerr.patch b/package/lienol/luci-app-nginx-pingos/patches/103-sys_nerr.patch deleted file mode 100644 index 5f5d106fed..0000000000 --- a/package/lienol/luci-app-nginx-pingos/patches/103-sys_nerr.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- a/src/os/unix/ngx_errno.c -+++ b/src/os/unix/ngx_errno.c -@@ -8,6 +8,9 @@ - #include - #include - -+#ifndef NGX_SYS_NERR -+#define NGX_SYS_NERR 128 -+#endif - - /* - * The strerror() messages are copied because: diff --git a/package/lienol/luci-app-nginx-pingos/patches/104-endianness_fix.patch b/package/lienol/luci-app-nginx-pingos/patches/104-endianness_fix.patch deleted file mode 100644 index 081bcdb00a..0000000000 --- a/package/lienol/luci-app-nginx-pingos/patches/104-endianness_fix.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff --git a/auto/endianness b/auto/endianness -index 1b552b6b..2b6f9ea4 100644 ---- a/auto/endianness -+++ b/auto/endianness -@@ -12,6 +12,16 @@ checking for system byte ordering - - END - -+if [ "${CONFIG_BIG_ENDIAN}" != "y" ]; then -+ echo " little endian" -+ have=NGX_HAVE_LITTLE_ENDIAN . auto/have -+else -+ echo " big endian" -+fi -+ -+return -+ -+ - - cat << END > $NGX_AUTOTEST.c - diff --git a/package/lienol/luci-app-nginx-pingos/patches/200-config.patch b/package/lienol/luci-app-nginx-pingos/patches/200-config.patch deleted file mode 100644 index f35009576a..0000000000 --- a/package/lienol/luci-app-nginx-pingos/patches/200-config.patch +++ /dev/null @@ -1,18 +0,0 @@ ---- a/conf/nginx.conf -+++ b/conf/nginx.conf -@@ -1,5 +1,5 @@ - --#user nobody; -+user nobody nogroup; - worker_processes 1; - - #error_log logs/error.log; -@@ -16,7 +16,7 @@ events { - - http { - include mime.types; -- default_type application/octet-stream; -+ #default_type application/octet-stream; - - #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - # '$status $body_bytes_sent "$http_referer" ' diff --git a/package/lienol/luci-app-nginx-pingos/patches/201-ignore-invalid-options.patch b/package/lienol/luci-app-nginx-pingos/patches/201-ignore-invalid-options.patch deleted file mode 100644 index 88b521353c..0000000000 --- a/package/lienol/luci-app-nginx-pingos/patches/201-ignore-invalid-options.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- a/auto/options -+++ b/auto/options -@@ -396,8 +396,7 @@ $0: warning: the \"--with-sha1-asm\" opt - --test-build-solaris-sendfilev) NGX_TEST_BUILD_SOLARIS_SENDFILEV=YES ;; - - *) -- echo "$0: error: invalid option \"$option\"" -- exit 1 -+ echo "$0: error: ignoring invalid option \"$option\"" - ;; - esac - done diff --git a/package/lienol/luci-app-nginx-pingos/po/zh-cn/pingos.po b/package/lienol/luci-app-nginx-pingos/po/zh-cn/pingos.po deleted file mode 100644 index 1b49421e03..0000000000 --- a/package/lienol/luci-app-nginx-pingos/po/zh-cn/pingos.po +++ /dev/null @@ -1,44 +0,0 @@ -msgid "Running Status" -msgstr "运行状态" - -msgid "Status" -msgstr "状态" - -msgid "Collecting data..." -msgstr "正在收集数据..." - -msgid "NOT RUNNING" -msgstr "未运行" - -msgid "RUNNING" -msgstr "运行中" - -msgid "If you need external network access, please open the port by yourself." -msgstr "如需外网访问,请自行放行端口。" - -msgid "Global Settings" -msgstr "全局设置" - -msgid "Edit Template" -msgstr "编辑模板" - -msgid "Edit the template that is used for generating the %s configuration." -msgstr "编辑生成 %s 的模板" - -msgid "This is the content of the file '%s'" -msgstr "这是文件内容:%s" - -msgid "Values enclosed by pipe symbols ('|') should not be changed. They get their values from the '%s' tab." -msgstr "由管道符(“|”)包围的值不应更改。它们将从 '%s' 标签中获取其值。" - -msgid "Listen IPv6" -msgstr "监听IPv6" - -msgid "Record" -msgstr "录像" - -msgid "Path" -msgstr "路径" - -msgid "Stream name" -msgstr "流名" diff --git a/package/lienol/luci-app-nginx-pingos/root/etc/config/pingos b/package/lienol/luci-app-nginx-pingos/root/etc/config/pingos deleted file mode 100644 index 128af52251..0000000000 --- a/package/lienol/luci-app-nginx-pingos/root/etc/config/pingos +++ /dev/null @@ -1,11 +0,0 @@ - -config global - option enable '0' - option ipv6 '0' - option https '0' - option ts_record '0' - option flv_record '0' - option http_port '18080' - option rtmp_port '1935' - option hls '1' - option hls2 '1' diff --git a/package/lienol/luci-app-nginx-pingos/root/etc/init.d/pingos b/package/lienol/luci-app-nginx-pingos/root/etc/init.d/pingos deleted file mode 100755 index 979f2eefb9..0000000000 --- a/package/lienol/luci-app-nginx-pingos/root/etc/init.d/pingos +++ /dev/null @@ -1,68 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2020 Lienol - -START=99 - -CONFIG="pingos" - -TEMP_PATH="/var/etc/$CONFIG" -NGINX_CONFIG="$TEMP_PATH/nginx.conf" - -config_t_get() { - local index=0 - [ -n "$4" ] && index=$4 - local ret=$(uci get $CONFIG.@$1[$index].$2 2>/dev/null) - echo ${ret:=$3} -} - -gen_nginx_config() { - ipv6=$(config_t_get global ipv6 0) - http_port=$(config_t_get global http_port) - [ "$(config_t_get global https 0)" == "1" ] && { - http_port="$http_port ssl" - ssl_certificate="ssl_certificate $(config_t_get global certificate);" - ssl_certificate_key="ssl_certificate_key $(config_t_get global key);" - } - rtmp_port=$(config_t_get global rtmp_port) - hls=$(config_t_get global hls 0) - [ $hls == 1 ] && hls=on || hls=off - hls2=$(config_t_get global hls2 0) - [ $hls2 == 1 ] && hls2=on || hls2=off - ts_record=$(config_t_get global ts_record 0) - [ $ts_record == 1 ] && ts_record=on || ts_record=off - flv_record=$(config_t_get global flv_record 0) - [ $flv_record == 1 ] && flv_record=all || flv_record=off - record_path=$(config_t_get global record_path "$TEMP_PATH/record") - - sed -e "s#|TMP_PATH|#$TEMP_PATH#g" \ - -e "s#|HTTP_PORT|#$http_port#g" \ - -e "s#|ssl_certificate|#$ssl_certificate#g" \ - -e "s#|ssl_certificate_key|#$ssl_certificate_key#g" \ - -e "s#|RTMP_PORT|#$rtmp_port#g" \ - -e "s#|HLS|#$hls#g" \ - -e "s#|HLS2|#$hls2#g" \ - -e "s#|TS_RECORD|#$ts_record#g" \ - -e "s#|FLV_RECORD|#$flv_record#g" \ - -e "s#|RECORD_PATH|#$record_path#g" \ - /etc/$CONFIG.template > $1 - - [ "$ipv6" = "0" ] && sed -i '/listen \[::\]:/d' $1 -} - -start() { - ENABLED=$(config_t_get global enable 0) - [ "$ENABLED" = "0" ] && return 0 - mkdir -p $TEMP_PATH $TEMP_PATH/lib - gen_nginx_config $NGINX_CONFIG - /usr/sbin/pingos -c $NGINX_CONFIG >/dev/null 2>&1 & -} - -stop() { - /usr/sbin/pingos -c $NGINX_CONFIG -s stop >/dev/null 2>&1 - rm -rf $TEMP_PATH -} - -restart() { - stop - start -} \ No newline at end of file diff --git a/package/lienol/luci-app-nginx-pingos/root/etc/pingos.template b/package/lienol/luci-app-nginx-pingos/root/etc/pingos.template deleted file mode 100644 index 9e94111f9a..0000000000 --- a/package/lienol/luci-app-nginx-pingos/root/etc/pingos.template +++ /dev/null @@ -1,209 +0,0 @@ -user root; -daemon on; -master_process on; -worker_processes 1; -#worker_rlimit 4g; - -#error_log |TMP_PATH|/error.log; -#error_log |TMP_PATH|/error.log notice; -error_log |TMP_PATH|/error.log info; - -worker_rlimit_nofile 102400; -worker_rlimit_core 2G; -working_directory |TMP_PATH|; - -pid |TMP_PATH|/pingos.pid; - -events { - use epoll; - worker_connections 4096; - multi_listen unix:|TMP_PATH|/http |HTTP_PORT|; - multi_listen unix:|TMP_PATH|/rtmp |RTMP_PORT|; - - dynamic_refresh_interval 5s; - dynamic_domain_buckets 1001; - resolver 114.114.114.114 valid=1m; - resolver_timeout 30s; -} - -#stream_zone buckets=1024 streams=4096; - -#dynamic_conf conf/nginx_dynamic.conf 10; -#dynamic_log |TMP_PATH|/dynamic.log info; - -rtmp { - log_format log_bandwidth '{"app":"$app","name":"$name","bitrate":$bitrate,"args":"$args","timestamp":$ntp,"ts":"$time_local","type":"$command","remote_addr":"$remote_addr","domain":"$domain"}'; - access_log |TMP_PATH|/bandwidth.log log_bandwidth trunc=60s; - - server { - listen |RTMP_PORT|; - listen [::]:|RTMP_PORT| ipv6only=on; - serverid 000; - out_queue 2048; - server_name localhost; - rtmp_auto_pull on; - rtmp_auto_pull_port unix:|TMP_PATH|/rtmp; - - application push { - live on; - push rtmp://127.0.0.1:|RTMP_PORT|/live app=live; - } - - application live { - live_record |TS_RECORD|; - live_record_path |RECORD_PATH|; - - recorder r1{ - record |FLV_RECORD|; - record_path |RECORD_PATH|; - } - - live on; - hls |HLS|; - hls_path |TMP_PATH|/hls; - hls_fragment 4000ms; - #hls_max_fragment 10000ms; - hls_playlist_length 12000ms; - hls_type live; - - hls2 |HLS2|; - mpegts_cache_time 20s; - - hls2_fragment 2000ms; - hls2_max_fragment 3000ms; - hls2_playlist_length 6000ms; - - wait_key on; - wait_video on; - cache_time 1s; - send_all on; - low_latency off; - fix_timestamp 2s; - # h265 codecid, default 12 - hevc_codecid 12; - } - } -} - -http { - include /usr/share/pingos/conf/mime.types; - default_type application/octet-stream; - - log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_X-Forwarded-For" "$http_X-Real-IP" "$host"'; - - - access_log |TMP_PATH|/access.log main; - - sendfile on; - #tcp_nopush on; - - #keepalive_timeout 0; - keepalive_timeout 65; - - #reset_server_name www.test1.com www.test2.com; - #gzip on; - - upstream hlsm { - #hash $remote_addr consistent; - hash $arg_session consistent; - # 这里需要注意,你要开几个进程,就要按这个规则写几条记录 - server unix:|TMP_PATH|/http.0; - #server unix:|TMP_PATH|/http.1; - } - - server { - listen |HTTP_PORT|; - listen [::]:|HTTP_PORT|; - |ssl_certificate| - |ssl_certificate_key| - ssl_session_cache shared:SSL:1m; - ssl_session_timeout 5m; - ssl_ciphers HIGH:!aNULL:!MD5; - ssl_prefer_server_ciphers on; - - location /rtmp_stat { - rtmp_stat all; - rtmp_stat_stylesheet /stat.xsl; - } - - location /xstat { - rtmp_stat all; - } - - location /sys_stat { - sys_stat; - } - location ~ .mp4$ { - root /usr/share/pingos/html; - #mp4; - } - - location /control { - rtmp_control all; - } - location /flv { - flv_live |RTMP_PORT| app=live; - add_header 'Access-Control-Allow-Origin' '*'; - add_header "Access-Control-Allow-Credentials" "true"; - add_header "Access-Control-Allow-Methods" "*"; - add_header "Access-Control-Allow-Headers" "Content-Type,Access-Token"; - add_header "Access-Control-Expose-Headers" "*"; - } - location /ts { - ts_live |RTMP_PORT| app=live; - expires -1; - add_header 'Access-Control-Allow-Origin' '*'; - add_header "Access-Control-Allow-Credentials" "true"; - add_header "Access-Control-Allow-Methods" "*"; - add_header "Access-Control-Allow-Headers" "Content-Type,Access-Token"; - add_header "Access-Control-Expose-Headers" "*"; - } - location /hls { - # Serve HLS fragments - types { - application/vnd.apple.mpegurl m3u8; - video/mp2t ts; - } - root |TMP_PATH|; - expires -1; - add_header Cache-Control no-cache; - add_header 'Access-Control-Allow-Origin' '*'; - add_header "Access-Control-Allow-Credentials" "true"; - add_header "Access-Control-Allow-Methods" "*"; - add_header "Access-Control-Allow-Headers" "Content-Type,Access-Token"; - add_header "Access-Control-Expose-Headers" "*"; - } - - location /hlsm { - hls2_live |RTMP_PORT| app=live; - add_header 'Access-Control-Allow-Origin' '*'; - add_header Cache-Control no-cache; - add_header "Access-Control-Allow-Credentials" "true"; - add_header "Access-Control-Allow-Methods" "*"; - add_header "Access-Control-Allow-Headers" "Content-Type,Access-Token"; - add_header "Access-Control-Expose-Headers" "*"; - } - - location /hls2 { - proxy_buffering on; - proxy_buffer_size 4k; - proxy_buffers 8 1M; - proxy_busy_buffers_size 2M; - proxy_max_temp_file_size 0; - set $hls_args location=/hls2&scheme=$scheme; -# if ($args) { -# set $hls_args $args&location=/hls2&scheme=$scheme; -# } - proxy_set_header Host $host:$server_port; - rewrite ^/(.*)/(.*)\.(.*)$ /hlsm/$2.$3?$hls_args break; - proxy_pass http://hlsm; - } - - location / { - chunked_transfer_encoding on; - root /usr/share/pingos/html/; - } - } -} diff --git a/package/lienol/luci-app-nginx-pingos/root/etc/uci-defaults/luci-app-nginx-pingos b/package/lienol/luci-app-nginx-pingos/root/etc/uci-defaults/luci-app-nginx-pingos deleted file mode 100755 index cd6d3ff86c..0000000000 --- a/package/lienol/luci-app-nginx-pingos/root/etc/uci-defaults/luci-app-nginx-pingos +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@pingos[-1] - add ucitrack pingos - set ucitrack.@pingos[-1].init=pingos - commit ucitrack -EOF - -rm -rf /tmp/luci-*cache -exit 0 diff --git a/package/lienol/luci-app-nginx-pingos/root/resource/conf-template/nginx.conf b/package/lienol/luci-app-nginx-pingos/root/resource/conf-template/nginx.conf deleted file mode 100644 index 0d80be84b8..0000000000 --- a/package/lienol/luci-app-nginx-pingos/root/resource/conf-template/nginx.conf +++ /dev/null @@ -1,205 +0,0 @@ -user root; -daemon on; -master_process on; -worker_processes 1; -#worker_rlimit 4g; - -#error_log logs/error.log; -#error_log logs/error.log notice; -error_log logs/error.log info; - -worker_rlimit_nofile 102400; -worker_rlimit_core 2G; -working_directory /tmp; - -pid logs/nginx.pid; - -events { - use epoll; - worker_connections 4096; - multi_listen unix:/tmp/http 8080; - multi_listen unix:/tmp/rtmp 1935; - - dynamic_refresh_interval 5s; - dynamic_domain_buckets 1001; - resolver 114.114.114.114 valid=1m; - resolver_timeout 30s; -} - -#stream_zone buckets=1024 streams=4096; - -#dynamic_conf conf/nginx_dynamic.conf 10; -#dynamic_log logs/dynamic.log info; - -rtmp { - log_format log_bandwidth '{"app":"$app","name":"$name","bitrate":$bitrate,"args":"$args","timestamp":$ntp,"ts":"$time_local","type":"$command","remote_addr":"$remote_addr","domain":"$domain"}'; - access_log logs/bandwidth.log log_bandwidth trunc=60s; - - server { - listen 1935; - serverid 000; - out_queue 2048; - server_name live.pingos.io; - rtmp_auto_pull on; - rtmp_auto_pull_port unix:/tmp/rtmp; - - application push { - live on; - push rtmp://127.0.0.1/live app=live; - } - - application live { - live_record on; - live_record_path /data/record; - - recorder r1{ - record all; - record_path /data/record; - } - - live on; - hls on; - hls_path /tmp/hls; - hls_fragment 4000ms; -# hls_max_fragment 10000ms; - hls_playlist_length 12000ms; - hls_type live; - - hls2 on; - mpegts_cache_time 20s; - - hls2_fragment 2000ms; - hls2_max_fragment 3000ms; - hls2_playlist_length 6000ms; - - wait_key on; - wait_video on; - cache_time 1s; - send_all on; - low_latency off; - fix_timestamp 2s; -# h265 codecid, default 12 - hevc_codecid 12; - } - } -} - -http { - include mime.types; - default_type application/octet-stream; - - log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_X-Forwarded-For" "$http_X-Real-IP" "$host"'; - - - access_log logs/access.log main; - - sendfile on; - #tcp_nopush on; - - #keepalive_timeout 0; - keepalive_timeout 65; - - #reset_server_name www.test1.com www.test2.com; - #gzip on; - - upstream hlsm { -# hash $remote_addr consistent; - hash $arg_session consistent; - # 这里需要注意,你要开几个进程,就要按这个规则写几条记录 - server unix:/tmp/http.0; -# server unix:/tmp/http.1; -# server unix:/tmp/http.2; -# server unix:/tmp/http.3; - } - - server { - listen 8080; -# listen 443 ssl; -# ssl_certificate /usr/local/pingos/cert/full_chain.pem; -# ssl_certificate_key /usr/local/pingos/cert/privkey.pem; - location /rtmp_stat { - rtmp_stat all; - rtmp_stat_stylesheet /stat.xsl; - } - - location /xstat { - rtmp_stat all; - } - - location /sys_stat { - sys_stat; - } - location ~ .mp4$ { - root html; - #mp4; - } - - location /control { - rtmp_control all; - } - location /flv { - flv_live 1935 app=live; - add_header 'Access-Control-Allow-Origin' '*'; - add_header "Access-Control-Allow-Credentials" "true"; - add_header "Access-Control-Allow-Methods" "*"; - add_header "Access-Control-Allow-Headers" "Content-Type,Access-Token"; - add_header "Access-Control-Expose-Headers" "*"; - } - location /ts { - ts_live 1935 app=live; - expires -1; - add_header 'Access-Control-Allow-Origin' '*'; - add_header "Access-Control-Allow-Credentials" "true"; - add_header "Access-Control-Allow-Methods" "*"; - add_header "Access-Control-Allow-Headers" "Content-Type,Access-Token"; - add_header "Access-Control-Expose-Headers" "*"; - } - location /hls { - # Serve HLS fragments - types { - application/vnd.apple.mpegurl m3u8; - video/mp2t ts; - } - root /tmp; - expires -1; - add_header Cache-Control no-cache; - add_header 'Access-Control-Allow-Origin' '*'; - add_header "Access-Control-Allow-Credentials" "true"; - add_header "Access-Control-Allow-Methods" "*"; - add_header "Access-Control-Allow-Headers" "Content-Type,Access-Token"; - add_header "Access-Control-Expose-Headers" "*"; - } - - location /hlsm { - hls2_live 1935 app=live; - add_header 'Access-Control-Allow-Origin' '*'; - add_header Cache-Control no-cache; - add_header "Access-Control-Allow-Credentials" "true"; - add_header "Access-Control-Allow-Methods" "*"; - add_header "Access-Control-Allow-Headers" "Content-Type,Access-Token"; - add_header "Access-Control-Expose-Headers" "*"; - } - - location /hls2 { - proxy_buffering on; - proxy_buffer_size 4k; - proxy_buffers 8 1M; - proxy_busy_buffers_size 2M; - proxy_max_temp_file_size 0; - set $hls_args location=/hls2&scheme=$scheme; -# if ($args) { -# set $hls_args $args&location=/hls2&scheme=$scheme; -# } - proxy_set_header Host $host:$server_port; - rewrite ^/(.*)/(.*)\.(.*)$ /hlsm/$2.$3?$hls_args break; - proxy_pass http://hlsm; - } - - location / { - chunked_transfer_encoding on; - root html/; - } - } -} diff --git a/package/lienol/luci-app-nginx-pingos/root/resource/crossdomain.xml b/package/lienol/luci-app-nginx-pingos/root/resource/crossdomain.xml deleted file mode 100644 index e5b559ad4c..0000000000 --- a/package/lienol/luci-app-nginx-pingos/root/resource/crossdomain.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/package/lienol/luci-app-nginx-pingos/root/resource/stat.xsl b/package/lienol/luci-app-nginx-pingos/root/resource/stat.xsl deleted file mode 100644 index 0e433c7509..0000000000 --- a/package/lienol/luci-app-nginx-pingos/root/resource/stat.xsl +++ /dev/null @@ -1,355 +0,0 @@ - - - - - - - - - - - - - RTMP statistics - - - -
- Generated by - PingOS , - nginx , - pid , - built   - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
RTMP#clientsVideoAudioIn bytesOut bytesIn bits/sOut bits/sStateTime
Accepted: codecbits/ssizefpscodecbits/sfreqchan - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - - - - - - - - - - - - - - - live streams - - - - - - - - - - - - vod streams - - - - - - - - - - - - - #cccccc - #dddddd - - - - - - var d=document.getElementById('-'); - d.style.display=d.style.display=='none'?'':'none'; - return false - - - - [EMPTY] - - - - - -    - - - - - - - - - - - - - - - -   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
IdStateAddressFlash versionPage URLSWF URLDroppedTimestampA-VTime
- - -
- - - - - - - - - - - d - - - - h - - - - m - - - s - - - - - - - - - - - - - T - - - G - - - M - - K - - - - b - B - - /s - - - - - - active - idle - - - - - - - publishing - playing - - - - - - - - - #cccccc - #eeeeee - - - - - - - - http://apps.db.ripe.net/search/query.html?searchtext= - - whois - - - - - - - - - - - - - - - - - - - - - - - - - - publishing - - - - active - - - - x - - -
diff --git a/package/lienol/luci-app-passwall/Makefile b/package/lienol/luci-app-passwall/Makefile deleted file mode 100644 index a8eb6ebac8..0000000000 --- a/package/lienol/luci-app-passwall/Makefile +++ /dev/null @@ -1,168 +0,0 @@ -# Copyright (C) 2018-2020 L-WRT Team -# Copyright (C) 2021 xiaorouji -# This is free software, licensed under the GNU General Public License v3. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=luci-app-passwall -PKG_VERSION:=4 -PKG_RELEASE:=19 -PKG_DATE:=20210327 - -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) - -include $(INCLUDE_DIR)/package.mk - -define Package/$(PKG_NAME)/config -menu "Configuration" - -config PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks - bool "Include Shadowsocks" - default y - -config PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Rust - bool "Include Shadowsocks Rust (AEAD ciphers only)" - depends on aarch64||arm||i386||mips||mipsel||x86_64 - default y if aarch64||x86_64 - -config PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Server - bool "Include Shadowsocks Server" - default y - -config PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR - bool "Include ShadowsocksR" - default y - -config PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Server - bool "Include ShadowsocksR Server" - default y - -config PACKAGE_$(PKG_NAME)_INCLUDE_Xray - bool "Include Xray" - default y if i386||x86_64||arm||aarch64 - -config PACKAGE_$(PKG_NAME)_INCLUDE_Trojan_Plus - bool "Include Trojan_Plus" - default y - -config PACKAGE_$(PKG_NAME)_INCLUDE_Trojan_GO - bool "Include Trojan_GO" - default n - -config PACKAGE_$(PKG_NAME)_INCLUDE_Brook - bool "Include Brook" - default n - -config PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy - bool "Include NaiveProxy" - default n - -config PACKAGE_$(PKG_NAME)_INCLUDE_kcptun - bool "Include kcptun" - default n - -config PACKAGE_$(PKG_NAME)_INCLUDE_haproxy - bool "Include haproxy" - default y - -config PACKAGE_$(PKG_NAME)_INCLUDE_ChinaDNS_NG - bool "Include ChinaDNS-NG" - default n - -config PACKAGE_$(PKG_NAME)_INCLUDE_dns2socks - bool "Include dns2socks" - default y - -config PACKAGE_$(PKG_NAME)_INCLUDE_v2ray-plugin - bool "Include v2ray-plugin (Shadowsocks plugin)" - default y if i386||x86_64||arm||aarch64 - -config PACKAGE_$(PKG_NAME)_INCLUDE_simple-obfs - bool "Include simple-obfs (Shadowsocks plugin)" - default y if i386||x86_64||arm||aarch64 - -endmenu -endef - -define Package/$(PKG_NAME) - CATEGORY:=LuCI - SUBMENU:=3. Applications - TITLE:=LuCI support for PassWall - PKGARCH:=all - DEPENDS:=+libmbedtls +iptables-mod-tproxy +ip +ipset +coreutils +coreutils-base64 +coreutils-nohup +luci-lib-jsonc \ - +curl +ca-certificates +resolveip +unzip +dnsmasq-full +tcping +libuci-lua \ - +ipt2socks \ - +microsocks \ - +pdnsd-alt \ - +PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks:shadowsocks-libev-ss-redir \ - +PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks:shadowsocks-libev-ss-local \ - +PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Rust:shadowsocks-rust-sslocal \ - +PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Server:shadowsocks-libev-ss-server \ - +PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR:shadowsocksr-libev-ssr-redir \ - +PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR:shadowsocksr-libev-ssr-local \ - +PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Server:shadowsocksr-libev-ssr-server \ - +PACKAGE_$(PKG_NAME)_INCLUDE_Xray:xray-core \ - +PACKAGE_$(PKG_NAME)_INCLUDE_Xray:xray-geodata \ - +PACKAGE_$(PKG_NAME)_INCLUDE_Trojan_Plus:trojan-plus \ - +PACKAGE_$(PKG_NAME)_INCLUDE_Trojan_GO:trojan-go \ - +PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy:naiveproxy \ - +PACKAGE_$(PKG_NAME)_INCLUDE_Brook:brook \ - +PACKAGE_$(PKG_NAME)_INCLUDE_kcptun:kcptun-client \ - +PACKAGE_$(PKG_NAME)_INCLUDE_haproxy:haproxy \ - +PACKAGE_$(PKG_NAME)_INCLUDE_ChinaDNS_NG:chinadns-ng \ - +PACKAGE_$(PKG_NAME)_INCLUDE_dns2socks:dns2socks \ - +PACKAGE_$(PKG_NAME)_INCLUDE_v2ray-plugin:v2ray-plugin \ - +PACKAGE_$(PKG_NAME)_INCLUDE_simple-obfs:simple-obfs -endef - -define Build/Prepare -endef - -define Build/Configure -endef - -define Build/Compile -endef - -define Package/$(PKG_NAME)/conffiles -/etc/config/passwall -/etc/config/passwall_server -/usr/share/passwall/rules/direct_host -/usr/share/passwall/rules/direct_ip -/usr/share/passwall/rules/proxy_host -/usr/share/passwall/rules/proxy_ip -endef - -define Package/$(PKG_NAME)/install - $(INSTALL_DIR) $(1)/etc/config - $(INSTALL_CONF) ./root/etc/config/passwall $(1)/etc/config/passwall - $(INSTALL_CONF) ./root/etc/config/passwall_server $(1)/etc/config/passwall_server - - $(INSTALL_DIR) $(1)/etc/init.d - $(INSTALL_BIN) ./root/etc/init.d/passwall $(1)/etc/init.d/passwall - $(INSTALL_BIN) ./root/etc/init.d/passwall_server $(1)/etc/init.d/passwall_server - - $(INSTALL_DIR) $(1)/etc/uci-defaults - $(INSTALL_CONF) ./root/etc/uci-defaults/* $(1)/etc/uci-defaults - - $(INSTALL_DIR) $(1)/usr/share/passwall - cp -pR ./root/usr/share/passwall/* $(1)/usr/share/passwall - $(INSTALL_CONF) ./root/etc/config/passwall $(1)/usr/share/passwall/config.default - - $(INSTALL_DIR) $(1)/usr/lib/lua/luci - cp -pR ./luasrc/* $(1)/usr/lib/lua/luci/ - - $(INSTALL_DIR) $(1)/usr/lib/lua/luci/i18n - po2lmo ./po/zh-cn/passwall.po $(1)/usr/lib/lua/luci/i18n/passwall.zh-cn.lmo -endef - -define Package/$(PKG_NAME)/postinst -#!/bin/sh -chmod a+x $${IPKG_INSTROOT}/usr/share/passwall/* >/dev/null 2>&1 -chmod a+x $${IPKG_INSTROOT}/usr/lib/lua/luci/model/cbi/passwall/server/api/app.lua >/dev/null 2>&1 -touch $${IPKG_INSTROOT}/etc/config/passwall_show >/dev/null 2>&1 -exit 0 -endef - -$(eval $(call BuildPackage,$(PKG_NAME))) diff --git a/package/lienol/luci-app-passwall/luasrc/controller/passwall.lua b/package/lienol/luci-app-passwall/luasrc/controller/passwall.lua deleted file mode 100644 index 776407f930..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/controller/passwall.lua +++ /dev/null @@ -1,401 +0,0 @@ --- Copyright (C) 2018-2020 L-WRT Team --- Copyright (C) 2021 xiaorouji - -module("luci.controller.passwall", package.seeall) -local api = require "luci.model.cbi.passwall.api.api" -local appname = api.appname -local ucic = luci.model.uci.cursor() -local http = require "luci.http" -local util = require "luci.util" -local i18n = require "luci.i18n" -local kcptun = require("luci.model.cbi." .. appname ..".api.kcptun") -local brook = require("luci.model.cbi." .. appname ..".api.brook") -local xray = require("luci.model.cbi." .. appname ..".api.xray") -local trojan_go = require("luci.model.cbi." .. appname ..".api.trojan_go") - -function index() - appname = require "luci.model.cbi.passwall.api.api".appname - entry({"admin", "services", appname}).dependent = true - entry({"admin", "services", appname, "reset_config"}, call("reset_config")).leaf = true - entry({"admin", "services", appname, "show"}, call("show_menu")).leaf = true - entry({"admin", "services", appname, "hide"}, call("hide_menu")).leaf = true - if not nixio.fs.access("/etc/config/passwall") then return end - if nixio.fs.access("/etc/config/passwall_show") then - entry({"admin", "services", appname}, alias("admin", "services", appname, "settings"), _("Pass Wall"), 1).dependent = true - end - --[[ Client ]] - entry({"admin", "services", appname, "settings"}, cbi(appname .. "/client/global"), _("Basic Settings"), 1).dependent = true - entry({"admin", "services", appname, "node_list"}, cbi(appname .. "/client/node_list"), _("Node List"), 2).dependent = true - entry({"admin", "services", appname, "auto_switch"}, cbi(appname .. "/client/auto_switch"), _("Auto Switch"), 3).leaf = true - entry({"admin", "services", appname, "other"}, cbi(appname .. "/client/other", {autoapply = true}), _("Other Settings"), 92).leaf = true - if nixio.fs.access("/usr/sbin/haproxy") then - entry({"admin", "services", appname, "haproxy"}, cbi(appname .. "/client/haproxy"), _("Load Balancing"), 93).leaf = true - end - entry({"admin", "services", appname, "node_subscribe"}, cbi(appname .. "/client/node_subscribe"), _("Node Subscribe"), 94).dependent = true - entry({"admin", "services", appname, "app_update"}, cbi(appname .. "/client/app_update"), _("App Update"), 95).leaf = true - entry({"admin", "services", appname, "rule"}, cbi(appname .. "/client/rule"), _("Rule Manage"), 96).leaf = true - entry({"admin", "services", appname, "rule_list"}, cbi(appname .. "/client/rule_list"), _("Rule List Manage"), 97).leaf = true - entry({"admin", "services", appname, "node_config"}, cbi(appname .. "/client/node_config")).leaf = true - entry({"admin", "services", appname, "shunt_rules"}, cbi(appname .. "/client/shunt_rules")).leaf = true - entry({"admin", "services", appname, "acl"}, cbi(appname .. "/client/acl"), _("Access control"), 98).leaf = true - entry({"admin", "services", appname, "log"}, form(appname .. "/client/log"), _("Watch Logs"), 999).leaf = true - - --[[ Server ]] - entry({"admin", "services", appname, "server"}, cbi(appname .. "/server/index"), _("Server-Side"), 99).leaf = true - entry({"admin", "services", appname, "server_user"}, cbi(appname .. "/server/user")).leaf = true - - --[[ API ]] - entry({"admin", "services", appname, "server_user_status"}, call("server_user_status")).leaf = true - entry({"admin", "services", appname, "server_user_log"}, call("server_user_log")).leaf = true - entry({"admin", "services", appname, "server_get_log"}, call("server_get_log")).leaf = true - entry({"admin", "services", appname, "server_clear_log"}, call("server_clear_log")).leaf = true - entry({"admin", "services", appname, "link_add_node"}, call("link_add_node")).leaf = true - entry({"admin", "services", appname, "get_now_use_node"}, call("get_now_use_node")).leaf = true - entry({"admin", "services", appname, "get_redir_log"}, call("get_redir_log")).leaf = true - entry({"admin", "services", appname, "get_log"}, call("get_log")).leaf = true - entry({"admin", "services", appname, "clear_log"}, call("clear_log")).leaf = true - entry({"admin", "services", appname, "status"}, call("status")).leaf = true - entry({"admin", "services", appname, "socks_status"}, call("socks_status")).leaf = true - entry({"admin", "services", appname, "connect_status"}, call("connect_status")).leaf = true - entry({"admin", "services", appname, "check_port"}, call("check_port")).leaf = true - entry({"admin", "services", appname, "ping_node"}, call("ping_node")).leaf = true - entry({"admin", "services", appname, "set_node"}, call("set_node")).leaf = true - entry({"admin", "services", appname, "copy_node"}, call("copy_node")).leaf = true - entry({"admin", "services", appname, "clear_all_nodes"}, call("clear_all_nodes")).leaf = true - entry({"admin", "services", appname, "delete_select_nodes"}, call("delete_select_nodes")).leaf = true - entry({"admin", "services", appname, "update_rules"}, call("update_rules")).leaf = true - entry({"admin", "services", appname, "kcptun_check"}, call("kcptun_check")).leaf = true - entry({"admin", "services", appname, "kcptun_update"}, call("kcptun_update")).leaf = true - entry({"admin", "services", appname, "brook_check"}, call("brook_check")).leaf = true - entry({"admin", "services", appname, "brook_update"}, call("brook_update")).leaf = true - entry({"admin", "services", appname, "xray_check"}, call("xray_check")).leaf = true - entry({"admin", "services", appname, "xray_update"}, call("xray_update")).leaf = true - entry({"admin", "services", appname, "trojan_go_check"}, call("trojan_go_check")).leaf = true - entry({"admin", "services", appname, "trojan_go_update"}, call("trojan_go_update")).leaf = true -end - -local function http_write_json(content) - http.prepare_content("application/json") - http.write_json(content or {code = 1}) -end - -function reset_config() - luci.sys.call('[ -f "/usr/share/passwall/config.default" ] && cp -f /usr/share/passwall/config.default /etc/config/passwall && /etc/init.d/passwall reload') - luci.http.redirect(api.url()) -end - -function show_menu() - luci.sys.call("touch /etc/config/passwall_show") - luci.http.redirect(api.url()) -end - -function hide_menu() - luci.sys.call("rm -rf /etc/config/passwall_show") - luci.http.redirect(luci.dispatcher.build_url("admin", "status", "overview")) -end - -function link_add_node() - local lfile = "/tmp/links.conf" - local link = luci.http.formvalue("link") - luci.sys.call('echo \'' .. link .. '\' > ' .. lfile) - luci.sys.call("lua /usr/share/passwall/subscribe.lua add log") -end - -function get_now_use_node() - local e = {} - local data, code, msg = nixio.fs.readfile("/var/etc/passwall/id/TCP") - if data then - e["TCP"] = util.trim(data) - end - local data, code, msg = nixio.fs.readfile("/var/etc/passwall/id/UDP") - if data then - e["UDP"] = util.trim(data) - end - luci.http.prepare_content("application/json") - luci.http.write_json(e) -end - -function get_redir_log() - local proto = luci.http.formvalue("proto") - proto = proto:upper() - local filename = proto - if nixio.fs.access("/var/etc/passwall/" .. filename .. ".log") then - local content = luci.sys.exec("cat /var/etc/passwall/" .. filename .. ".log") - content = content:gsub("\n", "
") - luci.http.write(content) - else - luci.http.write(string.format("", i18n.translate("Not enabled log"))) - end -end - -function get_log() - -- luci.sys.exec("[ -f /var/log/passwall.log ] && sed '1!G;h;$!d' /var/log/passwall.log > /var/log/passwall_show.log") - luci.http.write(luci.sys.exec("[ -f '/var/log/passwall.log' ] && cat /var/log/passwall.log")) -end - -function clear_log() - luci.sys.call("echo '' > /var/log/passwall.log") -end - -function status() - -- local dns_mode = ucic:get(appname, "@global[0]", "dns_mode") - local e = {} - e.dns_mode_status = luci.sys.call("netstat -apn | grep ':7913 ' >/dev/null") == 0 - e.haproxy_status = luci.sys.call(string.format("top -bn1 | grep -v grep | grep '%s/bin/' | grep haproxy >/dev/null", appname)) == 0 - e["kcptun_tcp_node_status"] = luci.sys.call(string.format("top -bn1 | grep -v grep | grep '%s/bin/kcptun' | grep -i 'tcp' >/dev/null", appname)) == 0 - e["tcp_node_status"] = luci.sys.call(string.format("top -bn1 | grep -v -E 'grep|kcptun' | grep '%s/bin/' | grep -i 'TCP' >/dev/null", appname)) == 0 - - if (ucic:get(appname, "@global[0]", "udp_node") or "nil") == "tcp" then - e["udp_node_status"] = e["tcp_node_status"] - else - e["udp_node_status"] = luci.sys.call(string.format("top -bn1 | grep -v grep | grep '%s/bin/' | grep -i 'UDP' >/dev/null", appname)) == 0 - end - luci.http.prepare_content("application/json") - luci.http.write_json(e) -end - -function socks_status() - local e = {} - local index = luci.http.formvalue("index") - local id = luci.http.formvalue("id") - e.index = index - e.socks_status = luci.sys.call(string.format("top -bn1 | grep -v grep | grep '%s/bin/' | grep '%s' | grep 'SOCKS_' > /dev/null", appname, id)) == 0 - local use_http = ucic:get(appname, id, "http_port") or 0 - e.use_http = 0 - if tonumber(use_http) > 0 then - e.use_http = 1 - e.http_status = luci.sys.call(string.format("top -bn1 | grep -v grep | grep '%s/bin/' | grep '%s' | grep -E 'HTTP_|HTTP2SOCKS' > /dev/null", appname, id)) == 0 - end - luci.http.prepare_content("application/json") - luci.http.write_json(e) -end - -function connect_status() - local e = {} - e.use_time = "" - local url = luci.http.formvalue("url") - local result = luci.sys.exec('curl --connect-timeout 3 -o /dev/null -I -skL -w "%{http_code}:%{time_starttransfer}" ' .. url) - local code = tonumber(luci.sys.exec("echo -n '" .. result .. "' | awk -F ':' '{print $1}'") or "0") - if code ~= 0 then - local use_time = luci.sys.exec("echo -n '" .. result .. "' | awk -F ':' '{print $2}'") - if use_time:find("%.") then - e.use_time = string.format("%.2f", use_time * 1000) - else - e.use_time = string.format("%.2f", use_time / 1000) - end - e.ping_type = "curl" - end - luci.http.prepare_content("application/json") - luci.http.write_json(e) -end - -function ping_node() - local index = luci.http.formvalue("index") - local address = luci.http.formvalue("address") - local port = luci.http.formvalue("port") - local e = {} - e.index = index - local nodes_ping = ucic:get(appname, "@global_other[0]", "nodes_ping") or "" - if nodes_ping:find("tcping") and luci.sys.exec("echo -n $(command -v tcping)") ~= "" then - e.ping = luci.sys.exec(string.format("echo -n $(tcping -q -c 1 -i 1 -t 2 -p %s %s 2>&1 | grep -o 'time=[0-9]*' | awk -F '=' '{print $2}') 2>/dev/null", port, address)) - end - if e.ping == nil or tonumber(e.ping) == 0 then - e.ping = luci.sys.exec("echo -n $(ping -c 1 -W 1 %q 2>&1 | grep -o 'time=[0-9]*' | awk -F '=' '{print $2}') 2>/dev/null" % address) - end - luci.http.prepare_content("application/json") - luci.http.write_json(e) -end - -function set_node() - local protocol = luci.http.formvalue("protocol") - local section = luci.http.formvalue("section") - ucic:set(appname, "@global[0]", protocol .. "_node", section) - ucic:commit(appname) - luci.sys.call("/etc/init.d/passwall restart > /dev/null 2>&1 &") - luci.http.redirect(api.url("log")) -end - -function copy_node() - local section = luci.http.formvalue("section") - local uuid = api.gen_uuid() - ucic:section(appname, "nodes", uuid) - for k, v in pairs(ucic:get_all(appname, section)) do - local filter = k:find("%.") - if filter and filter == 1 then - else - xpcall(function() - ucic:set(appname, uuid, k, v) - end, - function(e) - end) - end - end - ucic:commit(appname) - luci.http.redirect(api.url("node_config", uuid)) -end - -function clear_all_nodes() - ucic:foreach(appname, "nodes", function(node) - ucic:delete(appname, node['.name']) - end) - - local function clear(type) - local node_num = ucic:get(appname, "@global_other[0]", type .. "_node_num") or 1 - for i = 1, node_num, 1 do - local node = ucic:get(appname, "@global[0]", type .. "_node" .. i) - if node then - ucic:set(appname, '@global[0]', type .. "_node" .. i, "nil") - end - end - end - clear("tcp") - clear("udp") - - ucic:commit(appname) - luci.sys.call("/etc/init.d/" .. appname .. " restart") -end - -function delete_select_nodes() - local ids = luci.http.formvalue("ids") - string.gsub(ids, '[^' .. "," .. ']+', function(w) - ucic:delete(appname, w) - end) - ucic:commit(appname) - luci.sys.call("/etc/init.d/" .. appname .. " restart > /dev/null 2>&1 &") -end - -function check_port() - local node_name = "" - - local retstring = "
" - retstring = retstring .. "检测端口连通性,不支持UDP检测
" - ucic:foreach(appname, "nodes", function(s) - local ret = "" - local tcp_socket - if (s.use_kcp and s.use_kcp == "1" and s.kcp_port) or (s.transport and s.transport == "mkcp" and s.port) then - else - local type = s.type - if type and s.address and s.port and s.remarks then - node_name = "%s:[%s] %s:%s" % {s.type, s.remarks, s.address, s.port} - tcp_socket = nixio.socket("inet", "stream") - tcp_socket:setopt("socket", "rcvtimeo", 3) - tcp_socket:setopt("socket", "sndtimeo", 3) - ret = tcp_socket:connect(s.address, s.port) - if tostring(ret) == "true" then - retstring = retstring .. "" .. node_name .. " OK.
" - else - retstring = retstring .. "" .. node_name .. " Error.
" - end - ret = "" - end - end - if tcp_socket then tcp_socket:close() end - end) - luci.http.prepare_content("application/json") - luci.http.write_json({ret = retstring}) -end - -function update_rules() - local update = luci.http.formvalue("update") - luci.sys.call("lua /usr/share/passwall/rule_update.lua log '" .. update .. "' > /dev/null 2>&1 &") -end - -function server_user_status() - local e = {} - e.index = luci.http.formvalue("index") - e.status = luci.sys.call(string.format("top -bn1 | grep -v 'grep' | grep '%s/bin/' | grep -i '%s' >/dev/null", appname .. "_server", luci.http.formvalue("id"))) == 0 - http_write_json(e) -end - -function server_user_log() - local id = luci.http.formvalue("id") - if nixio.fs.access("/var/etc/passwall_server/" .. id .. ".log") then - local content = luci.sys.exec("cat /var/etc/passwall_server/" .. id .. ".log") - content = content:gsub("\n", "
") - luci.http.write(content) - else - luci.http.write(string.format("", i18n.translate("Not enabled log"))) - end -end - -function server_get_log() - luci.http.write(luci.sys.exec("[ -f '/var/log/passwall_server.log' ] && cat /var/log/passwall_server.log")) -end - -function server_clear_log() - luci.sys.call("echo '' > /var/log/passwall_server.log") -end - -function kcptun_check() - local json = kcptun.to_check("") - http_write_json(json) -end - -function kcptun_update() - local json = nil - local task = http.formvalue("task") - if task == "extract" then - json = kcptun.to_extract(http.formvalue("file"), http.formvalue("subfix")) - elseif task == "move" then - json = kcptun.to_move(http.formvalue("file")) - else - json = kcptun.to_download(http.formvalue("url")) - end - - http_write_json(json) -end - -function brook_check() - local json = brook.to_check("") - http_write_json(json) -end - -function brook_update() - local json = nil - local task = http.formvalue("task") - if task == "move" then - json = brook.to_move(http.formvalue("file")) - else - json = brook.to_download(http.formvalue("url")) - end - - http_write_json(json) -end - -function xray_check() - local json = xray.to_check("") - http_write_json(json) -end - -function xray_update() - local json = nil - local task = http.formvalue("task") - if task == "extract" then - json = xray.to_extract(http.formvalue("file"), http.formvalue("subfix")) - elseif task == "move" then - json = xray.to_move(http.formvalue("file")) - else - json = xray.to_download(http.formvalue("url")) - end - - http_write_json(json) -end - -function trojan_go_check() - local json = trojan_go.to_check("") - http_write_json(json) -end - -function trojan_go_update() - local json = nil - local task = http.formvalue("task") - if task == "extract" then - json = trojan_go.to_extract(http.formvalue("file"), http.formvalue("subfix")) - elseif task == "move" then - json = trojan_go.to_move(http.formvalue("file")) - else - json = trojan_go.to_download(http.formvalue("url")) - end - - http_write_json(json) -end diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/api.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/api.lua deleted file mode 100644 index 510c203c2c..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/api.lua +++ /dev/null @@ -1,441 +0,0 @@ -module("luci.model.cbi.passwall.api.api", package.seeall) -local fs = require "nixio.fs" -local sys = require "luci.sys" -local uci = require"luci.model.uci".cursor() -local util = require "luci.util" -local datatypes = require "luci.cbi.datatypes" -local i18n = require "luci.i18n" - -appname = "passwall" -curl = "/usr/bin/curl" -curl_args = {"-skL", "--connect-timeout 3", "--retry 3", "-m 60"} -command_timeout = 300 -LEDE_BOARD = nil -DISTRIB_TARGET = nil - -function url(...) - local url = string.format("admin/services/%s", appname) - local args = { ... } - for i, v in pairs(args) do - if v ~= "" then - url = url .. "/" .. v - end - end - return require "luci.dispatcher".build_url(url) -end - -function trim(s) - return (s:gsub("^%s*(.-)%s*$", "%1")) -end - -function is_exist(table, value) - for index, k in ipairs(table) do - if k == value then - return true - end - end - return false -end - -function get_args(arg, myarg) - local var = {} - for i, arg_k in pairs(arg) do - if i > 0 then - if is_exist(myarg, arg_k) == true then - local v = arg[i + 1] - if v then - if is_exist(myarg, v) == false then - var[arg_k] = v - end - end - end - end - end - return var -end - -function get_valid_nodes() - local nodes_ping = uci_get_type("global_other", "nodes_ping") or "" - local nodes = {} - uci:foreach(appname, "nodes", function(e) - e.id = e[".name"] - if e.type and e.remarks then - if e.protocol and (e.protocol == "_balancing" or e.protocol == "_shunt") then - e["remark"] = "%s:[%s] " % {i18n.translatef(e.type .. e.protocol), e.remarks} - e["node_type"] = "special" - nodes[#nodes + 1] = e - end - if e.port and e.address then - local address = e.address - if datatypes.ipaddr(address) or datatypes.hostname(address) then - local type2 = e.type - local address2 = address - if type2 == "Xray" and e.protocol then - local protocol = e.protocol - if protocol == "vmess" then - protocol = "VMess" - elseif protocol == "vless" then - protocol = "VLESS" - else - protocol = protocol:gsub("^%l",string.upper) - end - type2 = type2 .. " " .. protocol - end - if datatypes.ip6addr(address) then address2 = "[" .. address .. "]" end - e["remark"] = "%s:[%s]" % {type2, e.remarks} - if nodes_ping:find("info") then - e["remark"] = "%s:[%s] %s:%s" % {type2, e.remarks, address2, e.port} - end - if e.use_kcp and e.use_kcp == "1" then - e["remark"] = "%s+%s:[%s]" % {type2, "Kcptun", e.remarks} - if nodes_ping:find("info") then - e["remark"] = "%s+%s:[%s] %s" % {type2, "Kcptun", e.remarks, address2} - end - end - e.node_type = "normal" - nodes[#nodes + 1] = e - end - end - end - end) - return nodes -end - -function get_full_node_remarks(n) - local remarks = "" - if n then - if n.protocol and (n.protocol == "_balancing" or n.protocol == "_shunt") then - remarks = "%s:[%s] " % {i18n.translatef(n.type .. n.protocol), n.remarks} - else - local type2 = n.type - if n.type == "Xray" and n.protocol then - local protocol = n.protocol - if protocol == "vmess" then - protocol = "VMess" - elseif protocol == "vless" then - protocol = "VLESS" - else - protocol = protocol:gsub("^%l",string.upper) - end - type2 = type2 .. " " .. protocol - end - if n.use_kcp and n.use_kcp == "1" then - remarks = "%s+%s:[%s] %s" % {type2, "Kcptun", n.remarks, n.address} - else - remarks = "%s:[%s] %s:%s" % {type2, n.remarks, n.address, n.port} - end - end - end - return remarks -end - -function gen_uuid(format) - local uuid = sys.exec("echo -n $(cat /proc/sys/kernel/random/uuid)") - if format == nil then - uuid = string.gsub(uuid, "-", "") - end - return uuid -end - -function uci_get_type(type, config, default) - local value = uci:get_first(appname, type, config, default) or sys.exec("echo -n $(uci -q get " .. appname .. ".@" .. type .."[0]." .. config .. ")") - if (value == nil or value == "") and (default and default ~= "") then - value = default - end - return value -end - -function uci_get_type_id(id, config, default) - local value = uci:get(appname, id, config, default) or sys.exec("echo -n $(uci -q get " .. appname .. "." .. id .. "." .. config .. ")") - if (value == nil or value == "") and (default and default ~= "") then - value = default - end - return value -end - -function chmod_755(file) - if file and file ~= "" then - if not fs.access(file, "rwx", "rx", "rx") then - fs.chmod(file, 755) - end - end -end - -function get_customed_path(e) - return uci_get_type("global_app", e .. "_file") -end - -function is_finded(e) - return luci.sys.exec('type -t -p "/bin/%s" -p "%s" "%s"' % {e, get_customed_path(e), e}) ~= "" and true or false -end - - -function clone(org) - local function copy(org, res) - for k,v in pairs(org) do - if type(v) ~= "table" then - res[k] = v; - else - res[k] = {}; - copy(v, res[k]) - end - end - end - - local res = {} - copy(org, res) - return res -end - -function get_xray_path() - local path = uci_get_type("global_app", "xray_file") - return path -end - -function get_xray_version(file) - if file == nil then file = get_xray_path() end - chmod_755(file) - if fs.access(file) then - if file == get_xray_path() then - local md5 = sys.exec("echo -n $(md5sum " .. file .. " | awk '{print $1}')") - if fs.access("/tmp/psw_" .. md5) then - return sys.exec("cat /tmp/psw_" .. md5) - else - local version = sys.exec("echo -n $(%s -version | awk '{print $2}' | sed -n 1P)" % file) - sys.call("echo '" .. version .. "' > " .. "/tmp/psw_" .. md5) - return version - end - else - return sys.exec("echo -n $(%s -version | awk '{print $2}' | sed -n 1P)" % file) - end - end - return "" -end - -function get_trojan_go_path() - local path = uci_get_type("global_app", "trojan_go_file") - return path -end - -function get_trojan_go_version(file) - if file == nil then file = get_trojan_go_path() end - chmod_755(file) - if fs.access(file) then - if file == get_trojan_go_path() then - local md5 = sys.exec("echo -n $(md5sum " .. file .. " | awk '{print $1}')") - if fs.access("/tmp/psw_" .. md5) then - return sys.exec("cat /tmp/psw_" .. md5) - else - local version = sys.exec("echo -n $(%s -version | awk '{print $2}' | sed -n 1P)" % file) - sys.call("echo '" .. version .. "' > " .. "/tmp/psw_" .. md5) - return version - end - else - return sys.exec("echo -n $(%s -version | awk '{print $2}' | sed -n 1P)" % file) - end - end - return "" -end - -function get_kcptun_path() - local path = uci_get_type("global_app", "kcptun_client_file") - return path -end - -function get_kcptun_version(file) - if file == nil then file = get_kcptun_path() end - chmod_755(file) - if fs.access(file) then - if file == get_kcptun_path() then - local md5 = sys.exec("echo -n $(md5sum " .. file .. " | awk '{print $1}')") - if fs.access("/tmp/psw_" .. md5) then - return sys.exec("cat /tmp/psw_" .. md5) - else - local version = sys.exec("echo -n $(%s -v | awk '{print $3}')" % file) - sys.call("echo '" .. version .. "' > " .. "/tmp/psw_" .. md5) - return version - end - else - return sys.exec("echo -n $(%s -v | awk '{print $3}')" % file) - end - end - return "" -end - -function get_brook_path() - local path = uci_get_type("global_app", "brook_file") - return path -end - -function get_brook_version(file) - if file == nil then file = get_brook_path() end - chmod_755(file) - if fs.access(file) then - if file == get_brook_path() then - local md5 = sys.exec("echo -n $(md5sum " .. file .. " | awk '{print $1}')") - if fs.access("/tmp/psw_" .. md5) then - return sys.exec("cat /tmp/psw_" .. md5) - else - local version = sys.exec("echo -n $(%s -v | awk '{print $3}')" % file) - sys.call("echo '" .. version .. "' > " .. "/tmp/psw_" .. md5) - return version - end - else - return sys.exec("echo -n $(%s -v | awk '{print $3}')" % file) - end - end - return "" -end - -function get_free_space(dir) - if dir == nil then dir = "/" end - if sys.call("df -k " .. dir .. " >/dev/null") == 0 then - return tonumber(sys.exec("echo -n $(df -k " .. dir .. " | awk 'NR>1' | awk '{print $4}')")) - end - return 0 -end - -function get_file_space(file) - if file == nil then return 0 end - if fs.access(file) then - return tonumber(sys.exec("echo -n $(du -k " .. file .. " | awk '{print $1}')")) - end - return 0 -end - -function _unpack(t, i) - i = i or 1 - if t[i] ~= nil then return t[i], _unpack(t, i + 1) end -end - -function exec(cmd, args, writer, timeout) - local os = require "os" - local nixio = require "nixio" - - local fdi, fdo = nixio.pipe() - local pid = nixio.fork() - - if pid > 0 then - fdo:close() - - if writer or timeout then - local starttime = os.time() - while true do - if timeout and os.difftime(os.time(), starttime) >= timeout then - nixio.kill(pid, nixio.const.SIGTERM) - return 1 - end - - if writer then - local buffer = fdi:read(2048) - if buffer and #buffer > 0 then - writer(buffer) - end - end - - local wpid, stat, code = nixio.waitpid(pid, "nohang") - - if wpid and stat == "exited" then return code end - - if not writer and timeout then nixio.nanosleep(1) end - end - else - local wpid, stat, code = nixio.waitpid(pid) - return wpid and stat == "exited" and code - end - elseif pid == 0 then - nixio.dup(fdo, nixio.stdout) - fdi:close() - fdo:close() - nixio.exece(cmd, args, nil) - nixio.stdout:close() - os.exit(1) - end -end - -function compare_versions(ver1, comp, ver2) - local table = table - - local av1 = util.split(ver1, "[%.%-]", nil, true) - local av2 = util.split(ver2, "[%.%-]", nil, true) - - local max = table.getn(av1) - local n2 = table.getn(av2) - if (max < n2) then max = n2 end - - for i = 1, max, 1 do - local s1 = av1[i] or "" - local s2 = av2[i] or "" - - if comp == "~=" and (s1 ~= s2) then return true end - if (comp == "<" or comp == "<=") and (s1 < s2) then return true end - if (comp == ">" or comp == ">=") and (s1 > s2) then return true end - if (s1 ~= s2) then return false end - end - - return not (comp == "<" or comp == ">") -end - -function auto_get_arch() - local arch = nixio.uname().machine or "" - if fs.access("/usr/lib/os-release") then - LEDE_BOARD = sys.exec("echo -n `grep 'LEDE_BOARD' /usr/lib/os-release | awk -F '[\\042\\047]' '{print $2}'`") - end - if fs.access("/etc/openwrt_release") then - DISTRIB_TARGET = sys.exec("echo -n `grep 'DISTRIB_TARGET' /etc/openwrt_release | awk -F '[\\042\\047]' '{print $2}'`") - end - - if arch == "mips" then - if LEDE_BOARD and LEDE_BOARD ~= "" then - if string.match(LEDE_BOARD, "ramips") == "ramips" then - arch = "ramips" - else - arch = sys.exec("echo '" .. LEDE_BOARD .. "' | grep -oE 'ramips|ar71xx'") - end - elseif DISTRIB_TARGET and DISTRIB_TARGET ~= "" then - if string.match(DISTRIB_TARGET, "ramips") == "ramips" then - arch = "ramips" - else - arch = sys.exec("echo '" .. DISTRIB_TARGET .. "' | grep -oE 'ramips|ar71xx'") - end - end - end - - return util.trim(arch) -end - -function get_file_info(arch) - local file_tree = "" - local sub_version = "" - - if arch == "x86_64" then - file_tree = "amd64" - elseif arch == "aarch64" then - file_tree = "arm64" - elseif arch == "ramips" then - file_tree = "mipsle" - elseif arch == "ar71xx" then - file_tree = "mips" - elseif arch:match("^i[%d]86$") then - file_tree = "386" - elseif arch:match("^armv[5-8]") then - file_tree = "arm" - sub_version = arch:match("[5-8]") - if LEDE_BOARD and string.match(LEDE_BOARD, "bcm53xx") == "bcm53xx" then - sub_version = "5" - elseif DISTRIB_TARGET and string.match(DISTRIB_TARGET, "bcm53xx") == - "bcm53xx" then - sub_version = "5" - end - sub_version = "5" - end - - return file_tree, sub_version -end - -function get_api_json(url) - local jsonc = require "luci.jsonc" - local json_content = luci.sys.exec(curl .. " " .. _unpack(curl_args) .. " " .. url) - if json_content == "" then return {} end - return jsonc.parse(json_content) or {} -end diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/brook.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/brook.lua deleted file mode 100644 index 4213ccb7b5..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/brook.lua +++ /dev/null @@ -1,152 +0,0 @@ -module("luci.model.cbi.passwall.api.brook", package.seeall) -local fs = require "nixio.fs" -local sys = require "luci.sys" -local util = require "luci.util" -local i18n = require "luci.i18n" -local api = require "luci.model.cbi.passwall.api.api" - -local brook_api = "https://api.github.com/repos/txthinking/brook/releases/latest" - -function to_check(arch) - local app_path = api.get_brook_path() or "" - if app_path == "" then - return { - code = 1, - error = i18n.translatef("You did not fill in the %s path. Please save and apply then update manually.", "Brook") - } - end - if not arch or arch == "" then arch = api.auto_get_arch() end - - local file_tree, sub_version = api.get_file_info(arch) - - if file_tree == "" then - return { - code = 1, - error = i18n.translate("Can't determine ARCH, or ARCH not supported.") - } - end - - file_tree = "_linux_" .. file_tree - - local json = api.get_api_json(brook_api) - - if json.tag_name == nil then - return { - code = 1, - error = i18n.translate("Get remote version info failed.") - } - end - - local now_version = api.get_brook_version() - local remote_version = json.tag_name:match("[^v]+") - local needs_update = api.compare_versions(now_version, "<", remote_version) - local html_url, download_url - - if needs_update then - html_url = json.html_url - for _, v in ipairs(json.assets) do - if v.name and v.name:match(file_tree .. sub_version) then - download_url = v.browser_download_url - break - end - end - end - - if needs_update and not download_url then - return { - code = 1, - now_version = now_version, - version = remote_version, - html_url = html_url, - error = i18n.translate("New version found, but failed to get new version download url.") - } - end - - return { - code = 0, - update = needs_update, - now_version = now_version, - version = remote_version, - url = {html = html_url, download = download_url} - } -end - -function to_download(url) - local app_path = api.get_brook_path() or "" - if app_path == "" then - return { - code = 1, - error = i18n.translatef("You did not fill in the %s path. Please save and apply then update manually.", "Brook") - } - end - if not url or url == "" then - return {code = 1, error = i18n.translate("Download url is required.")} - end - - sys.call("/bin/rm -f /tmp/brook_download.*") - - local tmp_file = util.trim(util.exec("mktemp -u -t brook_download.XXXXXX")) - - local result = api.exec(api.curl, {api._unpack(api.curl_args), "-o", tmp_file, url}, nil, api.command_timeout) == 0 - - if not result then - api.exec("/bin/rm", {"-f", tmp_file}) - return { - code = 1, - error = i18n.translatef("File download failed or timed out: %s", url) - } - end - - return {code = 0, file = tmp_file} -end - -function to_move(file) - local app_path = api.get_brook_path() or "" - if app_path == "" then - return { - code = 1, - error = i18n.translatef("You did not fill in the %s path. Please save and apply then update manually.", "Brook") - } - end - if not file or file == "" or not fs.access(file) then - sys.call("/bin/rm -rf /tmp/brook_download.*") - return {code = 1, error = i18n.translate("Client file is required.")} - end - - local new_version = api.get_brook_version(file) - if new_version == "" then - sys.call("/bin/rm -rf /tmp/brook_download.*") - return { - code = 1, - error = i18n.translate("The client file is not suitable for current device.") - } - end - - local app_path_bak - - if fs.access(app_path) then - app_path_bak = app_path .. ".bak" - api.exec("/bin/mv", {"-f", app_path, app_path_bak}) - end - - local result = api.exec("/bin/mv", {"-f", file, app_path}, nil, api.command_timeout) == 0 - - if not result or not fs.access(app_path) then - sys.call("/bin/rm -rf /tmp/brook_download.*") - if app_path_bak then - api.exec("/bin/mv", {"-f", app_path_bak, app_path}) - end - return { - code = 1, - error = i18n.translatef("Can't move new file to path: %s", app_path) - } - end - - api.exec("/bin/chmod", {"755", app_path}) - - if app_path_bak then api.exec("/bin/rm", {"-f", app_path_bak}) end - - sys.call("/bin/rm -rf /tmp/brook_download.*") - - return {code = 0} -end diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_naiveproxy.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_naiveproxy.lua deleted file mode 100644 index 91c9e9b00e..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_naiveproxy.lua +++ /dev/null @@ -1,28 +0,0 @@ -local api = require "luci.model.cbi.passwall.api.api" -local ucursor = require "luci.model.uci".cursor() -local jsonc = require "luci.jsonc" - -local myarg = { - "-node", "-run_type", "-local_addr", "-local_port", "-server_host", "-server_port" -} - -local var = api.get_args(arg, myarg) - -local node_section = var["-node"] -if not node_section then - print("-node 不能为空") - return -end -local run_type = var["-run_type"] -local local_addr = var["-local_addr"] -local local_port = var["-local_port"] -local server_host = var["-server_host"] -local server_port = var["-server_port"] -local node = ucursor:get_all("passwall", node_section) - -local config = { - listen = run_type .. "://" .. local_addr .. ":" .. local_port, - proxy = node.protocol .. "://" .. node.username .. ":" .. node.password .. "@" .. (server_host or node.address) .. ":" .. (server_port or node.port) -} - -print(jsonc.stringify(config, 1)) diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_shadowsocks.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_shadowsocks.lua deleted file mode 100644 index d88e5c09c1..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_shadowsocks.lua +++ /dev/null @@ -1,46 +0,0 @@ -local api = require "luci.model.cbi.passwall.api.api" -local ucursor = require "luci.model.uci".cursor() -local jsonc = require "luci.jsonc" - -local myarg = { - "-node", "-local_addr", "-local_port", "-server_host", "-server_port" -} - -local var = api.get_args(arg, myarg) - -local node_section = var["-node"] -if not node_section then - print("-node 不能为空") - return -end -local local_addr = var["-local_addr"] -local local_port = var["-local_port"] -local server_host = var["-server_host"] -local server_port = var["-server_port"] -local node = ucursor:get_all("passwall", node_section) - -local config = { - server = server_host or node.address, - server_port = tonumber(server_port) or tonumber(node.port), - local_address = local_addr, - local_port = tonumber(local_port), - password = node.password, - method = node.method, - timeout = tonumber(node.timeout), - fast_open = (node.tcp_fast_open and node.tcp_fast_open == "true") and true or false, - reuse_port = true -} - -if node.type == "SS" then - if node.plugin and node.plugin ~= "none" then - config.plugin = node.plugin - config.plugin_opts = node.plugin_opts or nil - end -elseif node.type == "SSR" then - config.protocol = node.protocol - config.protocol_param = node.protocol_param - config.obfs = node.obfs - config.obfs_param = node.obfs_param -end - -print(jsonc.stringify(config, 1)) diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_trojan.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_trojan.lua deleted file mode 100644 index 1ef8a51668..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_trojan.lua +++ /dev/null @@ -1,85 +0,0 @@ -local api = require "luci.model.cbi.passwall.api.api" -local ucursor = require"luci.model.uci".cursor() -local json = require "luci.jsonc" - -local myarg = { - "-node", "-run_type", "-local_addr", "-local_port", "-server_host", "-server_port", "-loglevel" -} - -local var = api.get_args(arg, myarg) - -local node_section = var["-node"] -if not node_section then - print("-node 不能为空") - return -end -local run_type = var["-run_type"] -local local_addr = var["-local_addr"] -local local_port = var["-local_port"] -local server_host = var["-server_host"] -local server_port = var["-server_port"] -local loglevel = var["-loglevel"] or 2 -local node = ucursor:get_all("passwall", node_section) - -local cipher = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:AES128-SHA:AES256-SHA:DES-CBC3-SHA" -local cipher13 = "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384" -local trojan = { - run_type = run_type, - local_addr = local_addr, - local_port = tonumber(local_port), - remote_addr = server_host or node.address, - remote_port = tonumber(server_port) or tonumber(node.port), - password = {node.password}, - log_level = tonumber(loglevel), - ssl = { - verify = (node.tls_allowInsecure ~= "1") and true or false, - verify_hostname = true, - cert = nil, - cipher = cipher, - cipher_tls13 = cipher13, - sni = node.tls_serverName or node.address, - alpn = {"h2", "http/1.1"}, - reuse_session = true, - session_ticket = (node.tls_sessionTicket and node.tls_sessionTicket == "1") and true or false, - curves = "" - }, - udp_timeout = 60, - mux = (node.mux == "1") and { - enabled = true, - concurrency = tonumber(node.mux_concurrency), - idle_timeout = 60, - } or nil, - tcp = { - no_delay = true, - keep_alive = true, - reuse_port = true, - fast_open = (node.tcp_fast_open == "true") and true or false, - fast_open_qlen = 20 - } -} -if node.type == "Trojan-Go" then - trojan.ssl.cipher = (node.fingerprint == nil) and cipher or (node.fingerprint == "disable" and cipher13 .. ":" .. cipher or "") - trojan.ssl.cipher_tls13 = (node.fingerprint == nil) and cipher13 or nil - trojan.ssl.fingerprint = (node.fingerprint ~= nil and node.fingerprint ~= "disable") and node.fingerprint or "" - trojan.ssl.alpn = (node.trojan_transport == 'ws') and {} or {"h2", "http/1.1"} - if node.tls ~= "1" and node.trojan_transport == "original" then trojan.ssl = nil end - trojan.transport_plugin = ((not node.tls or node.tls ~= "1") and node.trojan_transport == "original") and { - enabled = node.plugin_type ~= nil, - type = node.plugin_type or "plaintext", - command = node.plugin_type ~= "plaintext" and node.plugin_cmd or nil, - option = node.plugin_type ~= "plaintext" and node.plugin_option or nil, - arg = node.plugin_type ~= "plaintext" and { node.plugin_arg } or nil, - env = {} - } or nil - trojan.websocket = (node.trojan_transport and node.trojan_transport:find('ws')) and { - enabled = true, - path = node.ws_path or "/", - host = node.ws_host or (node.tls_serverName or node.address) - } or nil - trojan.shadowsocks = (node.ss_aead == "1") and { - enabled = true, - method = node.ss_aead_method or "aead_aes_128_gcm", - password = node.ss_aead_pwd or "" - } or nil -end -print(json.stringify(trojan, 1)) diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_xray.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_xray.lua deleted file mode 100644 index fac9b40912..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_xray.lua +++ /dev/null @@ -1,576 +0,0 @@ -module("luci.model.cbi.passwall.api.gen_xray", package.seeall) -local api = require "luci.model.cbi.passwall.api.api" - -local myarg = { - "-node", "-proto", "-redir_port", "-socks_proxy_port", "-http_proxy_port", "-dns_listen_port", "-dns_server", "-doh_url", "-doh_host", "-doh_socks_address", "-doh_socks_port", "-loglevel" -} - -local var = api.get_args(arg, myarg) - -local node_section = var["-node"] -local proto = var["-proto"] -local redir_port = var["-redir_port"] -local socks_proxy_port = var["-socks_proxy_port"] -local http_proxy_port = var["-http_proxy_port"] -local dns_listen_port = var["-dns_listen_port"] -local dns_server = var["-dns_server"] -local doh_url = var["-doh_url"] -local doh_host = var["-doh_host"] -local doh_socks_address = var["-doh_socks_address"] -local doh_socks_port = var["-doh_socks_port"] -local loglevel = var["-loglevel"] or "warning" -local network = proto -local new_port - -local ucursor = require"luci.model.uci".cursor() -local sys = require "luci.sys" -local json = require "luci.jsonc" -local appname = api.appname -local dns = nil -local inbounds = {} -local outbounds = {} -local routing = nil - -local function get_new_port() - if new_port then - new_port = tonumber(sys.exec(string.format("echo -n $(/usr/share/%s/app.sh get_new_port %s tcp)", appname, new_port + 1))) - else - new_port = tonumber(sys.exec(string.format("echo -n $(/usr/share/%s/app.sh get_new_port auto tcp)", appname))) - end - return new_port -end - -function gen_outbound(node, tag, is_proxy, proxy_tag) - local result = nil - if node and node ~= "nil" then - local node_id = node[".name"] - if tag == nil then - tag = node_id - end - - if proxy_tag then - node.proxySettings = { - tag = proxy_tag, - transportLayer = true - } - end - - if node.type == "Xray" or node.type == "V2ray" then - is_proxy = nil - end - - if node.type ~= "Xray" and node.type ~= "V2ray" then - if node.type == "Socks" then - node.protocol = "socks" - node.transport = "tcp" - else - local node_type = proto or "socks" - local relay_port = node.port - new_port = get_new_port() - node.port = new_port - sys.call(string.format('/usr/share/%s/app.sh run_socks "%s" "%s" "%s" "%s" "%s" "%s" "%s" "%s"> /dev/null', appname, - new_port, --flag - node_id, --node - "127.0.0.1", --bind - new_port, --socks port - string.format("/var/etc/%s/v2_%s_%s_%s.json", appname, node_type, node_id, new_port), --config file - "0", --http port - "nil", -- http config file - (is_proxy and is_proxy == "1" and relay_port) and tostring(relay_port) or "" --relay port - ) - ) - node.protocol = "socks" - node.transport = "tcp" - node.address = "127.0.0.1" - end - node.stream_security = "none" - else - if node.tls and node.tls == "1" then - node.stream_security = "tls" - if node.xtls and node.xtls == "1" then - node.stream_security = "xtls" - end - end - end - - result = { - _flag_tag = node_id, - _flag_is_proxy = (is_proxy and is_proxy == "1") and "1" or "0", - tag = tag, - proxySettings = node.proxySettings or nil, - protocol = node.protocol, - mux = (node.stream_security ~= "xtls") and { - enabled = (node.mux == "1") and true or false, - concurrency = (node.mux_concurrency) and tonumber(node.mux_concurrency) or 8 - } or nil, - -- 底层传输配置 - streamSettings = (node.protocol == "vmess" or node.protocol == "vless" or node.protocol == "socks" or node.protocol == "shadowsocks" or node.protocol == "trojan") and { - network = node.transport, - security = node.stream_security, - xtlsSettings = (node.stream_security == "xtls") and { - serverName = node.tls_serverName, - allowInsecure = (node.tls_allowInsecure == "1") and true or false - } or nil, - tlsSettings = (node.stream_security == "tls") and { - serverName = node.tls_serverName, - allowInsecure = (node.tls_allowInsecure == "1") and true or false, - fingerprint = (node.fingerprint and node.fingerprint ~= "disable") and node.fingerprint or nil - } or nil, - tcpSettings = (node.transport == "tcp" and node.protocol ~= "socks") and { - header = { - type = node.tcp_guise, - request = (node.tcp_guise == "http") and { - path = node.tcp_guise_http_path or {"/"}, - headers = { - Host = node.tcp_guise_http_host or {} - } - } or nil - } - } or nil, - kcpSettings = (node.transport == "mkcp") and { - mtu = tonumber(node.mkcp_mtu), - tti = tonumber(node.mkcp_tti), - uplinkCapacity = tonumber(node.mkcp_uplinkCapacity), - downlinkCapacity = tonumber(node.mkcp_downlinkCapacity), - congestion = (node.mkcp_congestion == "1") and true or false, - readBufferSize = tonumber(node.mkcp_readBufferSize), - writeBufferSize = tonumber(node.mkcp_writeBufferSize), - seed = (node.mkcp_seed and node.mkcp_seed ~= "") and node.mkcp_seed or nil, - header = {type = node.mkcp_guise} - } or nil, - wsSettings = (node.transport == "ws") and { - path = node.ws_path or "", - headers = (node.ws_host ~= nil) and - {Host = node.ws_host} or nil - } or nil, - httpSettings = (node.transport == "h2") and - {path = node.h2_path, host = node.h2_host} or - nil, - dsSettings = (node.transport == "ds") and - {path = node.ds_path} or nil, - quicSettings = (node.transport == "quic") and { - security = node.quic_security, - key = node.quic_key, - header = {type = node.quic_guise} - } or nil, - grpcSettings = (node.transport == "grpc") and { - serviceName = node.grpc_serviceName - } or nil - } or nil, - settings = { - vnext = (node.protocol == "vmess" or node.protocol == "vless") and { - { - address = node.address, - port = tonumber(node.port), - users = { - { - id = node.uuid, - alterId = tonumber(node.alter_id), - level = 0, - security = (node.protocol == "vmess") and node.security or nil, - encryption = node.encryption or "none", - flow = node.flow or nil - } - } - } - } or nil, - servers = (node.protocol == "socks" or node.protocol == "http" or node.protocol == "shadowsocks" or node.protocol == "trojan") and { - { - address = node.address, - port = tonumber(node.port), - method = node.method or nil, - flow = node.flow or nil, - password = node.password or "", - users = (node.username and node.password) and - {{user = node.username, pass = node.password}} or nil - } - } or nil - } - } - end - return result -end - -if node_section then - local node = ucursor:get_all(appname, node_section) - if socks_proxy_port then - table.insert(inbounds, { - listen = "0.0.0.0", - port = tonumber(socks_proxy_port), - protocol = "socks", - settings = {auth = "noauth", udp = true} - }) - network = "tcp,udp" - end - if http_proxy_port then - table.insert(inbounds, { - listen = "0.0.0.0", - port = tonumber(http_proxy_port), - protocol = "http", - settings = {allowTransparent = false} - }) - end - - if redir_port then - table.insert(inbounds, { - port = tonumber(redir_port), - protocol = "dokodemo-door", - settings = {network = proto, followRedirect = true}, - sniffing = {enabled = true, destOverride = {"http", "tls"}} - }) - if proto == "tcp" and node.tcp_socks == "1" then - table.insert(inbounds, { - listen = "0.0.0.0", - port = tonumber(node.tcp_socks_port), - protocol = "socks", - settings = { - auth = node.tcp_socks_auth, - accounts = (node.tcp_socks_auth == "password") and { - { - user = node.tcp_socks_auth_username, - pass = node.tcp_socks_auth_password - } - } or nil, - udp = true - } - }) - end - end - - local up_trust_doh = ucursor:get(appname, "@global[0]", "up_trust_doh") - if up_trust_doh then - local t = {} - string.gsub(up_trust_doh, '[^' .. "," .. ']+', function (w) - table.insert(t, w) - end) - if #t > 1 then - local host = sys.exec("echo -n $(echo " .. t[1] .. " | sed 's/https:\\/\\///g' | awk -F ':' '{print $1}' | awk -F '/' '{print $1}')") - dns = { - hosts = { - [host] = t[2] - } - } - end - end - - if node.protocol == "_shunt" then - local rules = {} - - local default_node_id = node.default_node or "_direct" - local default_outboundTag - if default_node_id == "_direct" then - default_outboundTag = "direct" - elseif default_node_id == "_blackhole" then - default_outboundTag = "blackhole" - else - local default_node = ucursor:get_all(appname, default_node_id) - local main_node_id = node.main_node or "nil" - local is_proxy = "0" - local proxy_tag - if main_node_id ~= "nil" then - if main_node_id ~= default_node_id then - local main_node = ucursor:get_all(appname, main_node_id) - local main_node_outbound = gen_outbound(main_node, "main") - if main_node_outbound then - table.insert(outbounds, main_node_outbound) - is_proxy = "1" - proxy_tag = "main" - if default_node.type ~= "Xray" and default_node.type ~= "V2ray" then - proxy_tag = nil - new_port = get_new_port() - table.insert(inbounds, { - tag = "proxy_default", - listen = "127.0.0.1", - port = new_port, - protocol = "dokodemo-door", - settings = {network = "tcp,udp", address = default_node.address, port = tonumber(default_node.port)} - }) - if default_node.tls_serverName == nil then - default_node.tls_serverName = default_node.address - end - default_node.address = "127.0.0.1" - default_node.port = new_port - table.insert(rules, 1, { - type = "field", - inboundTag = {"proxy_default"}, - outboundTag = "main" - }) - end - end - end - end - local default_outbound = gen_outbound(default_node, "default", is_proxy, proxy_tag) - if default_outbound then - table.insert(outbounds, default_outbound) - default_outboundTag = "default" - end - end - - ucursor:foreach(appname, "shunt_rules", function(e) - local name = e[".name"] - local _node_id = node[name] or "nil" - local is_proxy = node[name .. "_proxy"] or "0" - local outboundTag - if _node_id == "_direct" then - outboundTag = "direct" - elseif _node_id == "_blackhole" then - outboundTag = "blackhole" - elseif _node_id == "_default" then - outboundTag = "default" - else - if _node_id ~= "nil" then - local has_outbound - for index, value in ipairs(outbounds) do - if value["_flag_tag"] == _node_id and value["_flag_is_proxy"] == is_proxy then - has_outbound = api.clone(value) - break - end - end - if has_outbound then - has_outbound["tag"] = name - table.insert(outbounds, has_outbound) - outboundTag = name - else - local _node = ucursor:get_all(appname, _node_id) - if node.type ~= "Xray" and node.type ~= "V2ray" then - if is_proxy == "1" then - new_port = get_new_port() - table.insert(inbounds, { - tag = "proxy_" .. name, - listen = "127.0.0.1", - port = new_port, - protocol = "dokodemo-door", - settings = {network = "tcp,udp", address = _node.address, port = tonumber(_node.port)} - }) - if _node.tls_serverName == nil then - _node.tls_serverName = _node.address - end - _node.address = "127.0.0.1" - _node.port = new_port - table.insert(rules, 1, { - type = "field", - inboundTag = {"proxy_" .. name}, - outboundTag = "default" - }) - end - end - local _outbound = gen_outbound(_node, name, is_proxy, (is_proxy == "1" and "default" or nil)) - if _outbound then - table.insert(outbounds, _outbound) - outboundTag = name - end - end - end - end - if outboundTag then - if outboundTag == "default" then - outboundTag = default_outboundTag - end - local protocols = nil - if e["protocol"] and e["protocol"] ~= "" then - protocols = {} - string.gsub(e["protocol"], '[^' .. " " .. ']+', function(w) - table.insert(protocols, w) - end) - end - if e.domain_list then - local _domain = {} - string.gsub(e.domain_list, '[^' .. "\r\n" .. ']+', function(w) - table.insert(_domain, w) - end) - table.insert(rules, { - type = "field", - outboundTag = outboundTag, - domain = _domain, - protocol = protocols - }) - end - if e.ip_list then - local _ip = {} - string.gsub(e.ip_list, '[^' .. "\r\n" .. ']+', function(w) - table.insert(_ip, w) - end) - table.insert(rules, { - type = "field", - outboundTag = outboundTag, - ip = _ip, - protocol = protocols - }) - end - if not e.domain_list and not e.ip_list and protocols then - table.insert(rules, { - type = "field", - outboundTag = outboundTag, - protocol = protocols - }) - end - end - end) - - if default_outboundTag then - table.insert(rules, { - type = "field", - outboundTag = default_outboundTag, - network = network - }) - end - - routing = { - domainStrategy = node.domainStrategy or "AsIs", - rules = rules - } - elseif node.protocol == "_balancing" then - if node.balancing_node then - local nodes = node.balancing_node - local length = #nodes - for i = 1, length do - local node = ucursor:get_all(appname, nodes[i]) - local outbound = gen_outbound(node) - if outbound then table.insert(outbounds, outbound) end - end - routing = { - domainStrategy = node.domainStrategy or "AsIs", - balancers = {{tag = "balancer", selector = nodes}}, - rules = { - {type = "field", network = "tcp,udp", balancerTag = "balancer"} - } - } - end - else - local outbound = gen_outbound(node) - if outbound then table.insert(outbounds, outbound) end - end -end - -if dns_server then - local rules = {} - - dns = { - tag = "dns-in1", - servers = { - dns_server - } - } - if doh_url and doh_host then - dns.hosts = { - [doh_host] = dns_server - } - dns.servers = { - doh_url - } - end - - if dns_listen_port then - table.insert(inbounds, { - listen = "127.0.0.1", - port = tonumber(dns_listen_port), - protocol = "dokodemo-door", - tag = "dns-in", - settings = { - address = dns_server, - port = 53, - network = "udp" - } - }) - end - - table.insert(rules, { - type = "field", - inboundTag = { - "dns-in" - }, - outboundTag = "dns-out" - }) - - local outboundTag = "direct" - if doh_socks_address and doh_socks_port then - table.insert(outbounds, 1, { - tag = "out", - protocol = "socks", - streamSettings = { - network = "tcp", - security = "none" - }, - settings = { - servers = { - { - address = doh_socks_address, - port = tonumber(doh_socks_port) - } - } - } - }) - outboundTag = "out" - end - table.insert(rules, { - type = "field", - inboundTag = { - "dns-in1" - }, - outboundTag = outboundTag - }) - - routing = { - domainStrategy = "IPOnDemand", - rules = rules - } -end - -if inbounds or outbounds then - table.insert(outbounds, { - protocol = "freedom", - tag = "direct", - settings = { - domainStrategy = "UseIPv4" - }, - streamSettings = { - sockopt = { - mark = 255 - } - } - }) - table.insert(outbounds, { - protocol = "blackhole", - tag = "blackhole" - }) - table.insert(outbounds, { - protocol = "dns", - tag = "dns-out" - }) - - local xray = { - log = { - -- error = string.format("/var/etc/%s/%s.log", appname, node[".name"]), - loglevel = loglevel - }, - -- DNS - dns = dns, - -- 传入连接 - inbounds = inbounds, - -- 传出连接 - outbounds = outbounds, - -- 路由 - routing = routing, - -- 本地策略 - --[[ - policy = { - levels = { - [0] = { - handshake = 4, - connIdle = 300, - uplinkOnly = 2, - downlinkOnly = 5, - bufferSize = 10240, - statsUserUplink = false, - statsUserDownlink = false - } - }, - system = { - statsInboundUplink = false, - statsInboundDownlink = false - } - } - ]]-- - } - print(json.stringify(xray, 1)) -end diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_xray_proto.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_xray_proto.lua deleted file mode 100644 index 7baed80b38..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_xray_proto.lua +++ /dev/null @@ -1,87 +0,0 @@ -local api = require "luci.model.cbi.passwall.api.api" -local json = require "luci.jsonc" -local inbounds = {} -local outbounds = {} -local routing = nil - -local myarg = { - "-local_proto", "-local_address", "-local_port", "-server_proto", "-server_address", "-server_port", "-server_username", "-server_password" -} - -local var = api.get_args(arg, myarg) - -local local_proto = var["-local_proto"] -local local_address = var["-local_address"] -local local_port = var["-local_port"] -local server_proto = var["-server_proto"] -local server_address = var["-server_address"] -local server_port = var["-server_port"] -local server_username = var["-server_username"] -local server_password = var["-server_password"] - -function gen_outbound(proto, address, port, username, password) - local result = { - protocol = proto, - streamSettings = { - network = "tcp", - security = "none" - }, - settings = { - servers = { - { - address = address, - port = tonumber(port), - users = (username and password) and { - { - user = username, - pass = password - } - } or nil - } - } - } - } - return result -end - -if local_proto ~= "nil" and local_address ~= "nil" and local_port ~= "nil" then - local inbound = { - listen = local_address, - port = tonumber(local_port), - protocol = local_proto, - settings = { - accounts = nil - } - } - if local_proto == "socks" then - inbound.settings.auth = "noauth" - inbound.settings.udp = true - elseif local_proto == "http" then - inbound.settings.allowTransparent = false - end - table.insert(inbounds, inbound) -end - -if server_proto ~= "nil" and server_address ~= "nil" and server_port ~= "nil" then - local outbound = gen_outbound(server_proto, server_address, server_port, server_username, server_password) - if outbound then table.insert(outbounds, outbound) end -end - --- 额外传出连接 -table.insert(outbounds, { - protocol = "freedom", tag = "direct", settings = {keep = ""} -}) - -local xray = { - log = { - -- error = string.format("/var/etc/passwall/%s.log", node[".name"]), - loglevel = "warning" - }, - -- 传入连接 - inbounds = inbounds, - -- 传出连接 - outbounds = outbounds, - -- 路由 - routing = routing -} -print(json.stringify(xray, 1)) diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/kcptun.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/kcptun.lua deleted file mode 100644 index 867875a120..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/kcptun.lua +++ /dev/null @@ -1,201 +0,0 @@ -module("luci.model.cbi.passwall.api.kcptun", package.seeall) -local fs = require "nixio.fs" -local sys = require "luci.sys" -local util = require "luci.util" -local i18n = require "luci.i18n" -local api = require "luci.model.cbi.passwall.api.api" - -local kcptun_api = "https://api.github.com/repos/xtaci/kcptun/releases/latest" - -function to_check(arch) - local app_path = api.get_kcptun_path() or "" - if app_path == "" then - return { - code = 1, - error = i18n.translatef("You did not fill in the %s path. Please save and apply then update manually.", "Kcptun") - } - end - if not arch or arch == "" then arch = api.auto_get_arch() end - - local file_tree, sub_version = api.get_file_info(arch) - - if file_tree == "" then - return { - code = 1, - error = i18n.translate("Can't determine ARCH, or ARCH not supported.") - } - end - - local json = api.get_api_json(kcptun_api) - - if json.tag_name == nil then - return { - code = 1, - error = i18n.translate("Get remote version info failed.") - } - end - - local now_version = api.get_kcptun_version() - local remote_version = json.tag_name:match("[^v]+") - local needs_update = api.compare_versions(now_version, "<", remote_version) - local html_url, download_url - - if needs_update then - html_url = json.html_url - for _, v in ipairs(json.assets) do - if v.name and v.name:match("linux%-" .. file_tree .. sub_version) then - download_url = v.browser_download_url - break - end - end - end - - if needs_update and not download_url then - return { - code = 1, - now_version = now_version, - version = remote_version, - html_url = html_url, - error = i18n.translate("New version found, but failed to get new version download url.") - } - end - - return { - code = 0, - update = needs_update, - now_version = now_version, - version = remote_version, - url = {html = html_url, download = download_url} - } -end - -function to_download(url) - local app_path = api.get_kcptun_path() or "" - if app_path == "" then - return { - code = 1, - error = i18n.translatef("You did not fill in the %s path. Please save and apply then update manually.", "Kcptun") - } - end - if not url or url == "" then - return {code = 1, error = i18n.translate("Download url is required.")} - end - - sys.call("/bin/rm -f /tmp/kcptun_download.*") - - local tmp_file = util.trim(util.exec("mktemp -u -t kcptun_download.XXXXXX")) - - local result = api.exec(api.curl, {api._unpack(api.curl_args), "-o", tmp_file, url}, nil, api.command_timeout) == 0 - - if not result then - api.exec("/bin/rm", {"-f", tmp_file}) - return { - code = 1, - error = i18n.translatef("File download failed or timed out: %s", url) - } - end - - return {code = 0, file = tmp_file} -end - -function to_extract(file, subfix) - local app_path = api.get_kcptun_path() or "" - if app_path == "" then - return { - code = 1, - error = i18n.translatef("You did not fill in the %s path. Please save and apply then update manually.", "Kcptun") - } - end - if not file or file == "" or not fs.access(file) then - return {code = 1, error = i18n.translate("File path required.")} - end - - sys.call("/bin/rm -rf /tmp/kcptun_extract.*") - local tmp_dir = util.trim(util.exec("mktemp -d -t kcptun_extract.XXXXXX")) - - local output = {} - api.exec("/bin/tar", {"-C", tmp_dir, "-zxvf", file}, - function(chunk) output[#output + 1] = chunk end) - - local files = util.split(table.concat(output)) - - api.exec("/bin/rm", {"-f", file}) - - local new_file = nil - for _, f in pairs(files) do - if f:match("client_linux_%s" % subfix) then - new_file = tmp_dir .. "/" .. util.trim(f) - break - end - end - - if not new_file then - for _, f in pairs(files) do - if f:match("client_") then - new_file = tmp_dir .. "/" .. util.trim(f) - break - end - end - end - - if not new_file then - api.exec("/bin/rm", {"-rf", tmp_dir}) - return { - code = 1, - error = i18n.translatef("Can't find client in file: %s", file) - } - end - - return {code = 0, file = new_file} -end - -function to_move(file) - local app_path = api.get_kcptun_path() or "" - if app_path == "" then - return { - code = 1, - error = i18n.translatef("You did not fill in the %s path. Please save and apply then update manually.", "Kcptun") - } - end - if not file or file == "" or not fs.access(file) then - sys.call("/bin/rm -rf /tmp/kcptun_extract.*") - return {code = 1, error = i18n.translate("Client file is required.")} - end - - local new_version = api.get_kcptun_version(file) - if new_version == "" then - sys.call("/bin/rm -rf /tmp/kcptun_extract.*") - return { - code = 1, - error = i18n.translate("The client file is not suitable for current device.") - } - end - - local app_path_bak - - if fs.access(app_path) then - app_path_bak = app_path .. ".bak" - api.exec("/bin/mv", {"-f", app_path, app_path_bak}) - end - - local result = api.exec("/bin/mv", {"-f", file, app_path}, nil, api.command_timeout) == 0 - - if not result or not fs.access(app_path) then - sys.call("/bin/rm -rf /tmp/kcptun_extract.*") - if app_path_bak then - api.exec("/bin/mv", {"-f", app_path_bak, app_path}) - end - return { - code = 1, - error = i18n.translatef("Can't move new file to path: %s", app_path) - } - end - - api.exec("/bin/chmod", {"755", app_path}) - - if app_path_bak then api.exec("/bin/rm", {"-f", app_path_bak}) end - - sys.call("/bin/rm -rf /tmp/kcptun_extract.*") - - return {code = 0} -end diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/trojan_go.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/trojan_go.lua deleted file mode 100644 index f346e91aee..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/trojan_go.lua +++ /dev/null @@ -1,175 +0,0 @@ -module("luci.model.cbi.passwall.api.trojan_go", package.seeall) -local fs = require "nixio.fs" -local sys = require "luci.sys" -local util = require "luci.util" -local i18n = require "luci.i18n" -local api = require "luci.model.cbi.passwall.api.api" - -local trojan_go_api = "https://api.github.com/repos/peter-tank/trojan-go/releases/latest" - -function to_check(arch) - local app_path = api.get_trojan_go_path() or "" - if app_path == "" then - return { - code = 1, - error = i18n.translatef("You did not fill in the %s path. Please save and apply then update manually.", "Trojan-GO") - } - end - if not arch or arch == "" then arch = api.auto_get_arch() end - - local file_tree, sub_version = api.get_file_info(arch) - - if file_tree == "" then - return { - code = 1, - error = i18n.translate("Can't determine ARCH, or ARCH not supported.") - } - end - - if file_tree == "mips" then file_tree = "mips%-hardfloat" end - if file_tree == "mipsle" then file_tree = "mipsle%-hardfloat" end - if file_tree == "arm64" then - file_tree = "armv8" - else - if sub_version and sub_version:match("^[5-8]$") then file_tree = file_tree .. "v" .. sub_version end - end - - local json = api.get_api_json(trojan_go_api) - - if json == nil or json.tag_name == nil then - return { - code = 1, - error = i18n.translate("Get remote version info failed.") - } - end - - local now_version = api.get_trojan_go_version() - local remote_version = json.tag_name:match("[^v]+") - local needs_update = api.compare_versions(now_version, "<", remote_version) - local html_url, download_url - - if needs_update then - html_url = json.html_url - for _, v in ipairs(json.assets) do - if v.name and v.name:match("linux%-" .. file_tree .. "%.zip") then - download_url = v.browser_download_url - break - end - end - end - - if needs_update and not download_url then - return { - code = 1, - now_version = now_version, - version = remote_version, - html_url = html_url, - error = i18n.translate("New version found, but failed to get new version download url.") .. " [linux-" .. file_tree .. ".zip]" - } - end - - return { - code = 0, - update = needs_update, - now_version = now_version, - version = remote_version, - url = {html = html_url, download = download_url} - } -end - -function to_download(url) - local app_path = api.get_trojan_go_path() or "" - if app_path == "" then - return { - code = 1, - error = i18n.translatef("You did not fill in the %s path. Please save and apply then update manually.", "Trojan-GO") - } - end - if not url or url == "" then - return {code = 1, error = i18n.translate("Download url is required.")} - end - - sys.call("/bin/rm -f /tmp/trojan-go_download.*") - - local tmp_file = util.trim(util.exec("mktemp -u -t trojan-go_download.XXXXXX")) - - local result = api.exec(api.curl, {api._unpack(api.curl_args), "-o", tmp_file, url}, nil, api.command_timeout) == 0 - - if not result then - api.exec("/bin/rm", {"-f", tmp_file}) - return { - code = 1, - error = i18n.translatef("File download failed or timed out: %s", url) - } - end - - return {code = 0, file = tmp_file} -end - -function to_extract(file, subfix) - local app_path = api.get_trojan_go_path() or "" - if app_path == "" then - return { - code = 1, - error = i18n.translatef("You did not fill in the %s path. Please save and apply then update manually.", "Trojan-GO") - } - end - if sys.exec("echo -n $(opkg list-installed | grep -c unzip)") ~= "1" then - api.exec("/bin/rm", {"-f", file}) - return { - code = 1, - error = i18n.translate("Not installed unzip, Can't unzip!") - } - end - - if not file or file == "" or not fs.access(file) then - return {code = 1, error = i18n.translate("File path required.")} - end - - sys.call("/bin/rm -rf /tmp/trojan-go_extract.*") - local tmp_dir = util.trim(util.exec("mktemp -d -t trojan-go_extract.XXXXXX")) - - local output = {} - api.exec("/usr/bin/unzip", {"-o", file, "-d", tmp_dir}, - function(chunk) output[#output + 1] = chunk end) - - local files = util.split(table.concat(output)) - - api.exec("/bin/rm", {"-f", file}) - - return {code = 0, file = tmp_dir} -end - -function to_move(file) - local app_path = api.get_trojan_go_path() or "" - if app_path == "" then - return { - code = 1, - error = i18n.translatef("You did not fill in the %s path. Please save and apply then update manually.", "Trojan-GO") - } - end - if not file or file == "" then - sys.call("/bin/rm -rf /tmp/trojan-go_extract.*") - return {code = 1, error = i18n.translate("Client file is required.")} - end - - local app_path_bak - - if fs.access(app_path) then - app_path_bak = app_path .. ".bak" - api.exec("/bin/mv", {"-f", app_path, app_path_bak}) - end - - local result = api.exec("/bin/mv", { "-f", file .. "/trojan-go", app_path }, nil, api.command_timeout) == 0 - sys.call("/bin/rm -rf /tmp/trojan-go_extract.*") - if not result or not fs.access(app_path) then - return { - code = 1, - error = i18n.translatef("Can't move new file to path: %s", app_path) - } - end - - api.exec("/bin/chmod", {"-R", "755", app_path}) - - return {code = 0} -end diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/xray.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/xray.lua deleted file mode 100644 index bf4797ec1a..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/xray.lua +++ /dev/null @@ -1,175 +0,0 @@ -module("luci.model.cbi.passwall.api.xray", package.seeall) -local fs = require "nixio.fs" -local sys = require "luci.sys" -local util = require "luci.util" -local i18n = require "luci.i18n" -local api = require "luci.model.cbi.passwall.api.api" - -local xray_api = "https://api.github.com/repos/XTLS/Xray-core/releases/latest" -local is_armv7 = false - -function to_check(arch) - local app_path = api.get_xray_path() or "" - if app_path == "" then - return { - code = 1, - error = i18n.translatef("You did not fill in the %s path. Please save and apply then update manually.", "Xray") - } - end - if not arch or arch == "" then arch = api.auto_get_arch() end - - local file_tree, sub_version = api.get_file_info(arch) - if sub_version == "7" then is_armv7 = true end - - if file_tree == "" then - return { - code = 1, - error = i18n.translate("Can't determine ARCH, or ARCH not supported.") - } - end - - if file_tree == "amd64" then file_tree = "64" end - if file_tree == "386" then file_tree = "32" end - if file_tree == "mipsle" then file_tree = "mips32le" end - if file_tree == "mips" then file_tree = "mips32" end - - local json = api.get_api_json(xray_api) - - if json.tag_name == nil then - return { - code = 1, - error = i18n.translate("Get remote version info failed.") - } - end - - local now_version = api.get_xray_version() - local remote_version = json.tag_name:match("[^v]+") - local needs_update = api.compare_versions(now_version, "<", remote_version) - local html_url, download_url - - if needs_update then - html_url = json.html_url - for _, v in ipairs(json.assets) do - if v.name and v.name:match("linux%-" .. file_tree) then - download_url = v.browser_download_url - break - end - end - end - - if needs_update and not download_url then - return { - code = 1, - now_version = now_version, - version = remote_version, - html_url = html_url, - error = i18n.translate("New version found, but failed to get new version download url.") - } - end - - return { - code = 0, - update = needs_update, - now_version = now_version, - version = remote_version, - url = {html = html_url, download = download_url} - } -end - -function to_download(url) - local app_path = api.get_xray_path() or "" - if app_path == "" then - return { - code = 1, - error = i18n.translatef("You did not fill in the %s path. Please save and apply then update manually.", "Xray") - } - end - if not url or url == "" then - return {code = 1, error = i18n.translate("Download url is required.")} - end - - sys.call("/bin/rm -f /tmp/xray_download.*") - - local tmp_file = util.trim(util.exec("mktemp -u -t xray_download.XXXXXX")) - - local result = api.exec(api.curl, {api._unpack(api.curl_args), "-o", tmp_file, url}, nil, api.command_timeout) == 0 - - if not result then - api.exec("/bin/rm", {"-f", tmp_file}) - return { - code = 1, - error = i18n.translatef("File download failed or timed out: %s", url) - } - end - - return {code = 0, file = tmp_file} -end - -function to_extract(file, subfix) - local app_path = api.get_xray_path() or "" - if app_path == "" then - return { - code = 1, - error = i18n.translatef("You did not fill in the %s path. Please save and apply then update manually.", "Xray") - } - end - - if not file or file == "" or not fs.access(file) then - return {code = 1, error = i18n.translate("File path required.")} - end - - if sys.exec("echo -n $(opkg list-installed | grep -c unzip)") ~= "1" then - api.exec("/bin/rm", {"-f", file}) - return { - code = 1, - error = i18n.translate("Not installed unzip, Can't unzip!") - } - end - - sys.call("/bin/rm -rf /tmp/xray_extract.*") - local tmp_dir = util.trim(util.exec("mktemp -d -t xray_extract.XXXXXX")) - - local output = {} - api.exec("/usr/bin/unzip", {"-o", file, "-d", tmp_dir}, - function(chunk) output[#output + 1] = chunk end) - - local files = util.split(table.concat(output)) - - api.exec("/bin/rm", {"-f", file}) - - return {code = 0, file = tmp_dir} -end - -function to_move(file) - local app_path = api.get_xray_path() or "" - if app_path == "" then - return { - code = 1, - error = i18n.translatef("You did not fill in the %s path. Please save and apply then update manually.", "Xray") - } - end - if not file or file == "" then - sys.call("/bin/rm -rf /tmp/xray_extract.*") - return {code = 1, error = i18n.translate("Client file is required.")} - end - - if not arch or arch == "" then arch = api.auto_get_arch() end - local file_tree, sub_version = api.get_file_info(arch) - local t = "" - sys.call("/etc/init.d/passwall stop") - local result = nil - if sub_version and sub_version == "7" then t = "_armv7" end - result = api.exec("/bin/mv", { "-f", file .. "/xray" .. t, app_path }, nil, api.command_timeout) == 0 - sys.call("/bin/rm -rf /tmp/xray_extract.*") - if not result or not fs.access(app_path) then - return { - code = 1, - error = i18n.translatef("Can't move new file to path: %s", app_path) - } - end - - api.chmod_755(app_path) - sys.call("/etc/init.d/passwall restart >/dev/null 2>&1 &") - - return {code = 0} -end diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/acl.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/acl.lua deleted file mode 100644 index 1f38d21f5f..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/acl.lua +++ /dev/null @@ -1,103 +0,0 @@ -local sys = require "luci.sys" -local appname = "passwall" - -m = Map(appname) - -local global_proxy_mode = (m.uci:get(appname, "@global[0]", "tcp_proxy_mode") or "") .. (m.uci:get(appname, "@global[0]", "udp_proxy_mode") or "") - --- [[ ACLs Settings ]]-- -s = m:section(TypedSection, "acl_rule", translate("ACLs"), "" .. translate("ACLs is a tools which used to designate specific IP proxy mode, IP or MAC address can be entered.") .. "") -s.template = "cbi/tblsection" -s.sortable = true -s.anonymous = true -s.addremove = true - ----- Enable -o = s:option(Flag, "enabled", translate("Enable")) -o.default = 1 -o.rmempty = false - ----- Remarks -o = s:option(Value, "remarks", translate("Remarks")) -o.rmempty = true - ----- IP Address -o = s:option(Value, "ip", translate("IP")) -o.datatype = "ip4addr" -o.rmempty = true - -local temp = {} -for index, n in ipairs(luci.ip.neighbors({family = 4})) do - if n.dest then temp[index] = n.dest:string() end -end -local ips = {} -for _, key in pairs(temp) do table.insert(ips, key) end -table.sort(ips) - -for index, key in pairs(ips) do o:value(key, temp[key]) end --- webadmin.cbi_add_knownips(o) - ----- MAC Address -o = s:option(Value, "mac", translate("MAC")) -o.rmempty = true -sys.net.mac_hints(function(e, t) o:value(e, "%s (%s)" % {e, t}) end) - ----- TCP Proxy Mode -tcp_proxy_mode = s:option(ListValue, "tcp_proxy_mode", translatef("%s Proxy Mode", "TCP")) -tcp_proxy_mode.default = "default" -tcp_proxy_mode.rmempty = false -tcp_proxy_mode:value("default", translate("Default")) -tcp_proxy_mode:value("disable", translate("No Proxy")) -tcp_proxy_mode:value("global", translate("Global Proxy")) -if global_proxy_mode:find("returnhome") then - tcp_proxy_mode:value("returnhome", translate("China List")) -else - tcp_proxy_mode:value("gfwlist", translate("GFW List")) - tcp_proxy_mode:value("chnroute", translate("Not China List")) -end - ----- UDP Proxy Mode -udp_proxy_mode = s:option(ListValue, "udp_proxy_mode", translatef("%s Proxy Mode", "UDP")) -udp_proxy_mode.default = "default" -udp_proxy_mode.rmempty = false -udp_proxy_mode:value("default", translate("Default")) -udp_proxy_mode:value("disable", translate("No Proxy")) -udp_proxy_mode:value("global", translate("Global Proxy")) -if global_proxy_mode:find("returnhome") then - udp_proxy_mode:value("returnhome", translate("China List")) -else - udp_proxy_mode:value("gfwlist", translate("GFW List")) - udp_proxy_mode:value("chnroute", translate("Game Mode")) -end - ----- TCP No Redir Ports -o = s:option(Value, "tcp_no_redir_ports", translate("TCP No Redir Ports")) -o.default = "default" -o:value("disable", translate("No patterns are used")) -o:value("default", translate("Default")) -o:value("1:65535", translate("All")) - ----- UDP No Redir Ports -o = s:option(Value, "udp_no_redir_ports", translate("UDP No Redir Ports")) -o.default = "default" -o:value("disable", translate("No patterns are used")) -o:value("default", translate("Default")) -o:value("1:65535", translate("All")) - ----- TCP Redir Ports -o = s:option(Value, "tcp_redir_ports", translate("TCP Redir Ports")) -o.default = "default" -o:value("default", translate("Default")) -o:value("1:65535", translate("All")) -o:value("80,443", "80,443") -o:value("80:65535", "80 " .. translate("or more")) -o:value("1:443", "443 " .. translate("or less")) - ----- UDP Redir Ports -o = s:option(Value, "udp_redir_ports", translate("UDP Redir Ports")) -o.default = "default" -o:value("default", translate("Default")) -o:value("1:65535", translate("All")) -o:value("53", "53") - -return m diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/app_update.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/app_update.lua deleted file mode 100644 index 6d13369078..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/app_update.lua +++ /dev/null @@ -1,38 +0,0 @@ -local appname = "passwall" - -m = Map(appname) - --- [[ App Settings ]]-- -s = m:section(TypedSection, "global_app", translate("App Update"), - "" .. - translate("Please confirm that your firmware supports FPU.") .. - "") -s.anonymous = true -s:append(Template(appname .. "/app_update/xray_version")) -s:append(Template(appname .. "/app_update/trojan_go_version")) -s:append(Template(appname .. "/app_update/kcptun_version")) -s:append(Template(appname .. "/app_update/brook_version")) - -o = s:option(Value, "xray_file", translatef("%s App Path", "Xray")) -o.default = "/usr/bin/xray" -o.rmempty = false - -o = s:option(Value, "trojan_go_file", translatef("%s App Path", "Trojan-Go")) -o.default = "/usr/bin/trojan-go" -o.rmempty = false - -o = s:option(Value, "kcptun_client_file", translatef("%s Client App Path", "Kcptun")) -o.default = "/usr/bin/kcptun-client" -o.rmempty = false - -o = s:option(Value, "brook_file", translatef("%s App Path", "Brook")) -o.default = "/usr/bin/brook" -o.rmempty = false - -o = s:option(DummyValue, "tips", " ") -o.rawhtml = true -o.cfgvalue = function(t, n) - return string.format('%s', translate("if you want to run from memory, change the path, /tmp beginning then save the application and update it manually.")) -end - -return m diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/auto_switch.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/auto_switch.lua deleted file mode 100644 index 7df6d104bf..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/auto_switch.lua +++ /dev/null @@ -1,33 +0,0 @@ -local api = require "luci.model.cbi.passwall.api.api" -local appname = api.appname - -local nodes_table = {} -for k, e in ipairs(api.get_valid_nodes()) do - nodes_table[#nodes_table + 1] = e -end - -m = Map(appname) - --- [[ Auto Switch Settings ]]-- -s = m:section(TypedSection, "auto_switch") -s.anonymous = true - ----- Enable -o = s:option(Flag, "enable", translate("Enable")) -o.default = 0 -o.rmempty = false - ----- Testing Time -o = s:option(Value, "testing_time", translate("How often is a diagnosis made"), translate("Units:minutes")) -o.default = "1" - -o = s:option(DynamicList, "tcp_node", "TCP " .. translate("List of backup nodes")) -for k, v in pairs(nodes_table) do - if v.node_type == "normal" then - o:value(v.id, v["remark"]) - end -end - -o = s:option(Flag, "restore_switch", "TCP " .. translate("Restore Switch"), translate("When detects main node is available, switch back to the main node.")) - -return m diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua deleted file mode 100644 index f2613b0481..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua +++ /dev/null @@ -1,386 +0,0 @@ -local uci = require"luci.model.uci".cursor() -local api = require "luci.model.cbi.passwall.api.api" -local appname = api.appname -local has_xray = api.is_finded("xray") - -m = Map(appname) - -local nodes_table = {} -for k, e in ipairs(api.get_valid_nodes()) do - nodes_table[#nodes_table + 1] = e -end - -local socks_table = {} -uci:foreach(appname, "socks", function(s) - if s.enabled == "1" and s.node then - local id, remarks - local same, i = s.node:match("^(tcp)") - if same then - remarks = translatef("Same as the tcp node") - else - for k, n in pairs(nodes_table) do - if (s.node == n.id) then - remarks = n["remark"]; break - end - end - end - id = "127.0.0.1" .. ":" .. s.port - socks_table[#socks_table + 1] = { - id = id, - remarks = id .. " - " .. (remarks or translate("Misconfigured")) - } - end -end) - -local doh_validate = function(self, value, t) - if value ~= "" then - local flag = 0 - local util = require "luci.util" - local val = util.split(value, ",") - local url = val[1] - val[1] = nil - for i = 1, #val do - local v = val[i] - if v then - if not datatypes.ipmask4(v) then - flag = 1 - end - end - end - if flag == 0 then - return value - end - end - return nil, translate("DoH request address") .. " " .. translate("Format must be:") .. " URL,IP" -end - -local redir_mode_validate = function(self, value, t) - local tcp_proxy_mode_v = tcp_proxy_mode:formvalue(t) or "" - local udp_proxy_mode_v = udp_proxy_mode:formvalue(t) or "" - local localhost_tcp_proxy_mode_v = localhost_tcp_proxy_mode:formvalue(t) or "" - local localhost_udp_proxy_mode_v = localhost_udp_proxy_mode:formvalue(t) or "" - local s = tcp_proxy_mode_v .. udp_proxy_mode_v .. localhost_tcp_proxy_mode_v .. localhost_udp_proxy_mode_v - if s:find("returnhome") then - if s:find("chnroute") or s:find("gfwlist") then - return nil, translate("China list or gfwlist cannot be used together with outside China list!") - end - end - return value -end - -local status = m:get("@global_other[0]", "status") or "" -if status:find("big_icon") then - m:append(Template(appname .. "/global/status")) -else - m:append(Template(appname .. "/global/status2")) -end - -s = m:section(TypedSection, "global") -s.anonymous = true -s.addremove = false - -s:tab("Main", translate("Main")) - --- [[ Global Settings ]]-- -o = s:taboption("Main", Flag, "enabled", translate("Main switch")) -o.rmempty = false - ----- TCP Node -tcp_node = s:taboption("Main", ListValue, "tcp_node", "" .. translate("TCP Node") .. "") -tcp_node.description = "" ---tcp_node.description = translate("For proxy specific list.") ---tcp_node.description = o.description .. "
" -local current_node = luci.sys.exec(string.format("[ -f '/var/etc/%s/id/TCP' ] && echo -n $(cat /var/etc/%s/id/TCP)", appname, appname)) -if current_node and current_node ~= "" and current_node ~= "nil" then - local n = uci:get_all(appname, current_node) - if n then - if tonumber(m:get("@auto_switch[0]", "enable") or 0) == 1 then - local remarks = api.get_full_node_remarks(n) - local url = api.url("node_config", current_node) - tcp_node.description = tcp_node.description .. translatef("Current node: %s", string.format('%s', url, remarks)) .. "
" - end - end -end -tcp_node:value("nil", translate("Close")) - --- 分流 -if has_xray and #nodes_table > 0 then - local normal_list = {} - local shunt_list = {} - for k, v in pairs(nodes_table) do - if v.node_type == "normal" then - normal_list[#normal_list + 1] = v - end - if v.type == "Xray" and v.protocol == "_shunt" then - shunt_list[#shunt_list + 1] = v - end - end - for k, v in pairs(shunt_list) do - uci:foreach(appname, "shunt_rules", function(e) - local id = e[".name"] - o = s:taboption("Main", ListValue, v.id .. "." .. id .. "_node", string.format('* %s', api.url("shunt_rules", id), translate(e.remarks))) - o:depends("tcp_node", v.id) - o:value("nil", translate("Close")) - o:value("_default", translate("Default")) - o:value("_direct", translate("Direct Connection")) - o:value("_blackhole", translate("Blackhole")) - for k1, v1 in pairs(normal_list) do - o:value(v1.id, v1["remark"]) - end - o.cfgvalue = function(self, section) - return m:get(v.id, id) or "nil" - end - o.write = function(self, section, value) - m:set(v.id, id, value) - end - end) - - local id = "default_node" - o = s:taboption("Main", ListValue, v.id .. "." .. id, "* " .. translate("Default")) - o:depends("tcp_node", v.id) - o:value("_direct", translate("Direct Connection")) - o:value("_blackhole", translate("Blackhole")) - for k1, v1 in pairs(normal_list) do - o:value(v1.id, v1["remark"]) - end - o.cfgvalue = function(self, section) - return m:get(v.id, id) or "nil" - end - o.write = function(self, section, value) - m:set(v.id, id, value) - end - - local id = "main_node" - o = s:taboption("Main", ListValue, v.id .. "." .. id, "* " .. translate("Default") .. " " .. translate("Preproxy")) - o:depends("tcp_node", v.id) - o:value("nil", translate("Close")) - for k1, v1 in pairs(normal_list) do - o:value(v1.id, v1["remark"]) - end - o.cfgvalue = function(self, section) - return m:get(v.id, id) or "nil" - end - o.write = function(self, section, value) - m:set(v.id, id, value) - end - end -end - -udp_node = s:taboption("Main", ListValue, "udp_node", "" .. translate("UDP Node") .. "") -udp_node:value("nil", translate("Close")) ---udp_node.description = translate("For proxy game network, DNS hijack etc.") .. "
" .. translate("The selected server will not use Kcptun.") -udp_node:value("tcp_", translate("Same as the tcp node")) ---udp_node:value("tcp", translate("Same as the tcp node")) ---udp_node:value("tcp_", translate("Same as the tcp node") .. "(" .. translate("New process") .. ")") - -s:tab("DNS", translate("DNS")) - ----- DNS Forward Mode -o = s:taboption("DNS", ListValue, "dns_mode", translate("Filter Mode")) -o.rmempty = false -o:reset_values() -o:value("fake_ip", translatef("Fake IP")) -if api.is_finded("pdnsd") then - o:value("pdnsd", "pdnsd " .. translatef("Requery DNS By %s", translate("TCP Node"))) -end -if api.is_finded("dns2socks") then - o:value("dns2socks", "dns2socks") -end -if has_xray then - o:value("xray_doh", "Xray DNS(DoH)") -end -o:value("udp", translatef("Requery DNS By %s", translate("UDP Node"))) -o:value("custom", translate("Custom DNS") .. "(UDP)") -o:value("nonuse", translate("No Filter")) - ----- Custom DNS -o = s:taboption("DNS", Value, "custom_dns", translate("Custom DNS")) -o.default = "127.0.0.1#5353" -o.validate = function(self, value, t) - local v = string.gsub(value, "#", ":") - if not datatypes.ipaddrport(v) then - return nil, translate("Custom DNS") .. " " .. translate("Not valid IP format, please re-enter!") - end - return value -end -o:depends({dns_mode = "custom"}) - -o = s:taboption("DNS", ListValue, "up_trust_doh_dns", translate("Resolver For The List Proxied")) -o:value("tcp", translatef("Requery DNS By %s", translate("TCP Node"))) -o:value("socks", translatef("Requery DNS By %s", translate("Socks Node"))) -o:depends("dns_mode", "xray_doh") - -o = s:taboption("DNS", Value, "socks_server", translate("Socks Server"), translate("Make sure socks service is available on this address.")) -for k, v in pairs(socks_table) do o:value(v.id, v.remarks) end -o.validate = function(self, value, t) - if not datatypes.ipaddrport(value) then - return nil, translate("Socks Server") .. " " .. translate("Not valid IP format, please re-enter!") - end - return value -end -o:depends({dns_mode = "dns2socks"}) -o:depends({dns_mode = "xray_doh", up_trust_doh_dns = "socks"}) - ----- DoH -o = s:taboption("DNS", Value, "up_trust_doh", translate("DoH request address")) -o:value("https://dns.adguard.com/dns-query,176.103.130.130", "AdGuard") -o:value("https://cloudflare-dns.com/dns-query,1.1.1.1", "Cloudflare") -o:value("https://security.cloudflare-dns.com/dns-query,1.1.1.2", "Cloudflare-Security") -o:value("https://doh.opendns.com/dns-query,208.67.222.222", "OpenDNS") -o:value("https://dns.google/dns-query,8.8.8.8", "Google") -o:value("https://doh.libredns.gr/dns-query,116.202.176.26", "LibreDNS") -o:value("https://doh.libredns.gr/ads,116.202.176.26", "LibreDNS (No Ads)") -o:value("https://dns.quad9.net/dns-query,9.9.9.9", "Quad9-Recommended") -o.default = "https://dns.google/dns-query,8.8.8.8" -o.validate = doh_validate -o:depends({dns_mode = "xray_doh"}) - ----- DNS Forward -o = s:taboption("DNS", Value, "dns_forward", translate("Remote DNS")) ---o.description = translate("IP:Port mode acceptable, multi value split with english comma.") .. " " .. translate("If you use dns2socks, only the first one is valid.") -o.default = "8.8.8.8" -o:value("8.8.8.8", "8.8.8.8 (Google DNS)") -o:value("8.8.4.4", "8.8.4.4 (Google DNS)") -o:value("208.67.222.222", "208.67.222.222 (Open DNS)") -o:value("208.67.220.220", "208.67.220.220 (Open DNS)") -o:depends({dns_mode = "dns2socks"}) -o:depends({dns_mode = "pdnsd"}) -o:depends({dns_mode = "udp"}) - ---[[ -o = s:taboption("DNS", Flag, "dns_cache", translate("Cache Resolved")) -o.default = "1" -o:depends({dns_mode = "dns2socks"}) -o:depends({dns_mode = "pdnsd"}) -]]-- - -o = s:taboption("DNS", Button, "clear_ipset", translate("Clear IPSET"), translate("Try this feature if the rule modification does not take effect.")) -o.inputstyle = "remove" -function o.write(e, e) - luci.sys.call("/usr/share/" .. appname .. "/iptables.sh flush_ipset > /dev/null 2>&1 &") -end - -s:tab("Proxy", translate("Mode")) - ----- TCP Default Proxy Mode -tcp_proxy_mode = s:taboption("Proxy", ListValue, "tcp_proxy_mode", "TCP " .. translate("Default") .. translate("Proxy Mode")) --- o.description = translate("If not available, try clearing the cache.") -tcp_proxy_mode:value("disable", translate("No Proxy")) -tcp_proxy_mode:value("global", translate("Global Proxy")) -tcp_proxy_mode:value("gfwlist", translate("GFW List")) -tcp_proxy_mode:value("chnroute", translate("Not China List")) -tcp_proxy_mode:value("returnhome", translate("China List")) -tcp_proxy_mode.default = "chnroute" ---tcp_proxy_mode.validate = redir_mode_validate - ----- UDP Default Proxy Mode -udp_proxy_mode = s:taboption("Proxy", ListValue, "udp_proxy_mode", "UDP " .. translate("Default") .. translate("Proxy Mode")) -udp_proxy_mode:value("disable", translate("No Proxy")) -udp_proxy_mode:value("global", translate("Global Proxy")) -udp_proxy_mode:value("gfwlist", translate("GFW List")) -udp_proxy_mode:value("chnroute", translate("Game Mode")) -udp_proxy_mode:value("returnhome", translate("China List")) -udp_proxy_mode.default = "chnroute" ---udp_proxy_mode.validate = redir_mode_validate - ----- Localhost TCP Proxy Mode -localhost_tcp_proxy_mode = s:taboption("Proxy", ListValue, "localhost_tcp_proxy_mode", translate("Router Localhost") .. " TCP " .. translate("Proxy Mode")) --- o.description = translate("The server client can also use this rule to scientifically surf the Internet.") -localhost_tcp_proxy_mode:value("default", translate("Default")) -localhost_tcp_proxy_mode:value("global", translate("Global Proxy")) -localhost_tcp_proxy_mode:value("gfwlist", translate("GFW List")) -localhost_tcp_proxy_mode:value("chnroute", translate("Not China List")) -localhost_tcp_proxy_mode:value("returnhome", translate("China List")) -localhost_tcp_proxy_mode.default = "default" ---localhost_tcp_proxy_mode.validate = redir_mode_validate - ----- Localhost UDP Proxy Mode -localhost_udp_proxy_mode = s:taboption("Proxy", ListValue, "localhost_udp_proxy_mode", translate("Router Localhost") .. " UDP " .. translate("Proxy Mode")) -localhost_udp_proxy_mode:value("default", translate("Default")) -localhost_udp_proxy_mode:value("global", translate("Global Proxy")) -localhost_udp_proxy_mode:value("gfwlist", translate("GFW List")) -localhost_udp_proxy_mode:value("chnroute", translate("Game Mode")) -localhost_udp_proxy_mode:value("returnhome", translate("China List")) -localhost_udp_proxy_mode:value("disable", translate("No Proxy")) -localhost_udp_proxy_mode.default = "default" -localhost_udp_proxy_mode.validate = redir_mode_validate - -s:tab("log", translate("Log")) -o = s:taboption("log", Flag, "close_log_tcp", translatef("%s Node Log Close", "TCP")) -o.rmempty = false - -o = s:taboption("log", Flag, "close_log_udp", translatef("%s Node Log Close", "UDP")) -o.rmempty = false - -loglevel = s:taboption("log", ListValue, "loglevel", "Xray" .. translate("Log Level")) -loglevel.default = "warning" -loglevel:value("debug") -loglevel:value("info") -loglevel:value("warning") -loglevel:value("error") - -trojan_loglevel = s:taboption("log", ListValue, "trojan_loglevel", "Trojan" .. translate("Log Level")) -trojan_loglevel.default = "2" -trojan_loglevel:value("0", "all") -trojan_loglevel:value("1", "info") -trojan_loglevel:value("2", "warn") -trojan_loglevel:value("3", "error") -trojan_loglevel:value("4", "fatal") - -s:tab("tips", translate("Tips")) - -o = s:taboption("tips", DummyValue, "") -o.template = appname .. "/global/tips" - --- [[ Socks Server ]]-- -o = s:taboption("Main", Flag, "socks_enabled", "Socks " .. translate("Main switch")) -o.rmempty = false - -s = m:section(TypedSection, "socks", translate("Socks Config")) -s.anonymous = true -s.addremove = true -s.template = "cbi/tblsection" -function s.create(e, t) - TypedSection.create(e, api.gen_uuid()) -end - -o = s:option(DummyValue, "status", translate("Status")) -o.rawhtml = true -o.cfgvalue = function(t, n) - return string.format('
', n) -end - ----- Enable -o = s:option(Flag, "enabled", translate("Enable")) -o.default = 1 -o.rmempty = false - -socks_node = s:option(ListValue, "node", translate("Socks Node")) -socks_node:value("tcp", translate("Same as the tcp node")) - -o = s:option(Value, "port", "Socks " .. translate("Listen Port")) -o.default = 9050 -o.datatype = "port" -o.rmempty = false - -if has_xray then - o = s:option(Value, "http_port", "HTTP " .. translate("Listen Port") .. " " .. translate("0 is not use")) - o.default = 0 - o.datatype = "port" -end - -for k, v in pairs(nodes_table) do - tcp_node:value(v.id, v["remark"]) - udp_node:value(v.id, v["remark"]) - if v.type == "Socks" then - if has_xray then - socks_node:value(v.id, v["remark"]) - end - else - socks_node:value(v.id, v["remark"]) - end -end - -m:append(Template(appname .. "/global/footer")) - -return m diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/haproxy.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/haproxy.lua deleted file mode 100644 index ea000623de..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/haproxy.lua +++ /dev/null @@ -1,106 +0,0 @@ -local e = require "luci.sys" -local net = require "luci.model.network".init() -local api = require "luci.model.cbi.passwall.api.api" -local appname = api.appname - -local nodes_table = {} -for k, e in ipairs(api.get_valid_nodes()) do - if e.node_type == "normal" then - nodes_table[#nodes_table + 1] = { - id = e[".name"], - obj = e, - remarks = e["remark"] - } - end -end - -m = Map(appname) - --- [[ Haproxy Settings ]]-- -s = m:section(TypedSection, "global_haproxy") -s.anonymous = true - -s:append(Template(appname .. "/haproxy/status")) - ----- Balancing Enable -o = s:option(Flag, "balancing_enable", translate("Enable Load Balancing")) -o.rmempty = false -o.default = false - ----- Console Username -o = s:option(Value, "console_user", translate("Console Username")) -o.default = "" -o:depends("balancing_enable", true) - ----- Console Password -o = s:option(Value, "console_password", translate("Console Password")) -o.password = true -o.default = "" -o:depends("balancing_enable", true) - ----- Console Port -o = s:option(Value, "console_port", translate("Console Port"), translate( - "In the browser input routing IP plus port access, such as:192.168.1.1:1188")) -o.default = "1188" -o:depends("balancing_enable", true) - --- [[ Balancing Settings ]]-- -s = m:section(TypedSection, "haproxy_config", "", - "" .. - translate("Add a node, Export Of Multi WAN Only support Multi Wan. Load specific gravity range 1-256. Multiple primary servers can be load balanced, standby will only be enabled when the primary server is offline! Multiple groups can be set, Haproxy port same one for each group.") .. - "\n" .. translate("Note that the node configuration parameters for load balancing must be consistent, otherwise problems can arise!") .. - "") -s.template = "cbi/tblsection" -s.sortable = true -s.anonymous = true -s.addremove = true - ----- Enable -o = s:option(Flag, "enabled", translate("Enable")) -o.default = 1 -o.rmempty = false - ----- Node Address -o = s:option(Value, "lbss", translate("Node Address")) -for k, v in pairs(nodes_table) do o:value(v.obj.address .. ":" .. v.obj.port, v.remarks) end -o.rmempty = false - ----- Node Port -o = s:option(Value, "lbort", translate("Node Port")) -o:value("default", translate("Default")) -o.default = "default" -o.rmempty = false - ----- Haproxy Port -o = s:option(Value, "haproxy_port", translate("Haproxy Port")) -o.default = "1181" -o.rmempty = false - ----- Node Weight -o = s:option(Value, "lbweight", translate("Node Weight")) -o.default = "5" -o.rmempty = false - ----- Export -o = s:option(ListValue, "export", translate("Export Of Multi WAN")) -o:value(0, translate("Auto")) -local ifaces = e.net:devices() -for _, iface in ipairs(ifaces) do - if (iface:match("^br") or iface:match("^eth*") or iface:match("^pppoe*")) then - local nets = net:get_interface(iface) - nets = nets and nets:get_networks() or {} - for k, v in pairs(nets) do nets[k] = nets[k].sid end - nets = table.concat(nets, ",") - o:value(iface, ((#nets > 0) and "%s (%s)" % {iface, nets} or iface)) - end -end -o.default = 0 -o.rmempty = false - ----- Mode -o = s:option(ListValue, "backup", translate("Mode")) -o:value(0, translate("Primary")) -o:value(1, translate("Standby")) -o.rmempty = false - -return m diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/log.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/log.lua deleted file mode 100644 index 5580e17aab..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/log.lua +++ /dev/null @@ -1,8 +0,0 @@ -local api = require "luci.model.cbi.passwall.api.api" -local appname = api.appname - -f = SimpleForm(appname) -f.reset = false -f.submit = false -f:append(Template(appname .. "/log/log")) -return f diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/node_config.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/node_config.lua deleted file mode 100644 index 027185540e..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/node_config.lua +++ /dev/null @@ -1,684 +0,0 @@ -local uci = require"luci.model.uci".cursor() -local api = require "luci.model.cbi.passwall.api.api" -local appname = api.appname - -local ss_encrypt_method_list = { - "rc4-md5", "aes-128-cfb", "aes-192-cfb", "aes-256-cfb", "aes-128-ctr", - "aes-192-ctr", "aes-256-ctr", "bf-cfb", "camellia-128-cfb", - "camellia-192-cfb", "camellia-256-cfb", "salsa20", "chacha20", - "chacha20-ietf", -- aead - "aes-128-gcm", "aes-192-gcm", "aes-256-gcm", "chacha20-ietf-poly1305", - "xchacha20-ietf-poly1305" -} - -local ssr_encrypt_method_list = { - "none", "table", "rc2-cfb", "rc4", "rc4-md5", "rc4-md5-6", "aes-128-cfb", - "aes-192-cfb", "aes-256-cfb", "aes-128-ctr", "aes-192-ctr", "aes-256-ctr", - "bf-cfb", "camellia-128-cfb", "camellia-192-cfb", "camellia-256-cfb", - "cast5-cfb", "des-cfb", "idea-cfb", "seed-cfb", "salsa20", "chacha20", - "chacha20-ietf" -} - -local ssr_protocol_list = { - "origin", "verify_simple", "verify_deflate", "verify_sha1", "auth_simple", - "auth_sha1", "auth_sha1_v2", "auth_sha1_v4", "auth_aes128_md5", - "auth_aes128_sha1", "auth_chain_a", "auth_chain_b", "auth_chain_c", - "auth_chain_d", "auth_chain_e", "auth_chain_f" -} -local ssr_obfs_list = { - "plain", "http_simple", "http_post", "random_head", "tls_simple", - "tls1.0_session_auth", "tls1.2_ticket_auth" -} - -local v_ss_encrypt_method_list = { - "aes-128-cfb", "aes-256-cfb", "aes-128-gcm", "aes-256-gcm", "chacha20", "chacha20-ietf", "chacha20-poly1305", "chacha20-ietf-poly1305" -} - -local security_list = {"none", "auto", "aes-128-gcm", "chacha20-poly1305"} - -local header_type_list = { - "none", "srtp", "utp", "wechat-video", "dtls", "wireguard" -} -local force_fp = { - "disable", "firefox", "chrome", "ios" -} -local encrypt_methods_ss_aead = { - "dummy", - "aead_chacha20_poly1305", - "aead_aes_128_gcm", - "aead_aes_256_gcm", - "chacha20-ietf-poly1305", - "aes-128-gcm", - "aes-256-gcm", -} - -m = Map(appname, translate("Node Config")) -m.redirect = api.url() - -s = m:section(NamedSection, arg[1], "nodes", "") -s.addremove = false -s.dynamic = false - -share = s:option(DummyValue, "passwall", " ") -share.rawhtml = true -share.template = "passwall/node_list/link_share_man" -share.value = arg[1] - -remarks = s:option(Value, "remarks", translate("Node Remarks")) -remarks.default = translate("Remarks") -remarks.rmempty = false - -type = s:option(ListValue, "type", translate("Type")) -if api.is_finded("ipt2socks") then - type:value("Socks", translate("Socks")) -end -if api.is_finded("sslocal") or api.is_finded("ss-redir") then - type:value("SS", translate("Shadowsocks")) -end -if api.is_finded("ssr-redir") then - type:value("SSR", translate("ShadowsocksR")) -end -if api.is_finded("xray") then - type:value("Xray", translate("Xray")) - type.description = translate("Xray is currently directly compatible with V2ray and used.") -end -if api.is_finded("brook") then - type:value("Brook", translate("Brook")) -end ---[[ -if api.is_finded("trojan-plus") or api.is_finded("trojan") then - type:value("Trojan", translate("Trojan")) -end -]]-- -if api.is_finded("trojan-plus") then - type:value("Trojan-Plus", translate("Trojan-Plus")) -end -if api.is_finded("trojan-go") then - type:value("Trojan-Go", translate("Trojan-Go")) -end -if api.is_finded("naive") then - type:value("Naiveproxy", translate("NaiveProxy")) -end - -protocol = s:option(ListValue, "protocol", translate("Protocol")) -protocol:value("vmess", translate("Vmess")) -protocol:value("vless", translate("VLESS")) -protocol:value("http", translate("HTTP")) -protocol:value("socks", translate("Socks")) -protocol:value("shadowsocks", translate("Shadowsocks")) -protocol:value("trojan", translate("Trojan")) -protocol:value("_balancing", translate("Balancing")) -protocol:value("_shunt", translate("Shunt")) -protocol:depends("type", "Xray") - -local nodes_table = {} -for k, e in ipairs(api.get_valid_nodes()) do - if e.node_type == "normal" then - nodes_table[#nodes_table + 1] = { - id = e[".name"], - remarks = e["remark"] - } - end -end - --- 负载均衡列表 -balancing_node = s:option(DynamicList, "balancing_node", translate("Load balancing node list"), translate("Load balancing node list, document")) -for k, v in pairs(nodes_table) do balancing_node:value(v.id, v.remarks) end -balancing_node:depends("protocol", "_balancing") - --- 分流 -uci:foreach(appname, "shunt_rules", function(e) - o = s:option(ListValue, e[".name"], string.format('* %s', api.url("shunt_rules", e[".name"]), translate(e.remarks))) - o:value("nil", translate("Close")) - o:value("_default", translate("Default")) - o:value("_direct", translate("Direct Connection")) - o:value("_blackhole", translate("Blackhole")) - o:depends("protocol", "_shunt") - - if #nodes_table > 0 then - _proxy = s:option(Flag, e[".name"] .. "_proxy", translate(e.remarks) .. translate("Preproxy"), translate("Use the default node for the transit.")) - _proxy.default = 0 - - for k, v in pairs(nodes_table) do - o:value(v.id, v.remarks) - _proxy:depends(e[".name"], v.id) - end - end -end) - -shunt_tips = s:option(DummyValue, "shunt_tips", " ") -shunt_tips.rawhtml = true -shunt_tips.cfgvalue = function(t, n) - return string.format('%s', translate("No shunt rules? Click me to go to add.")) -end -shunt_tips:depends("protocol", "_shunt") - -default_node = s:option(ListValue, "default_node", translate("Default") .. " " .. translate("Node")) -default_node:value("_direct", translate("Direct Connection")) -default_node:value("_blackhole", translate("Blackhole")) -for k, v in pairs(nodes_table) do default_node:value(v.id, v.remarks) end -default_node:depends("protocol", "_shunt") - -if #nodes_table > 0 then - o = s:option(ListValue, "main_node", translate("Default") .. " " .. translate("Node") .. translate("Preproxy"), translate("Use this node proxy to forward the default node.")) - o:value("nil", translate("Close")) - for k, v in pairs(nodes_table) do - o:value(v.id, v.remarks) - o:depends("default_node", v.id) - end -end - -domainStrategy = s:option(ListValue, "domainStrategy", translate("Domain Strategy")) -domainStrategy:value("AsIs") -domainStrategy:value("IPIfNonMatch") -domainStrategy:value("IPOnDemand") -domainStrategy.description = "
  • " .. translate("'AsIs': Only use domain for routing. Default value.") -.. "
  • " .. translate("'IPIfNonMatch': When no rule matches current domain, resolves it into IP addresses (A or AAAA records) and try all rules again.") -.. "
  • " .. translate("'IPOnDemand': As long as there is a IP-based rule, resolves the domain into IP immediately.") -.. "
" -domainStrategy:depends("protocol", "_balancing") -domainStrategy:depends("protocol", "_shunt") - --- Brook协议 -brook_protocol = s:option(ListValue, "brook_protocol", translate("Protocol")) -brook_protocol:value("client", translate("Brook")) -brook_protocol:value("wsclient", translate("WebSocket")) -brook_protocol:depends("type", "Brook") -function brook_protocol.cfgvalue(self, section) - return m:get(section, "protocol") -end -function brook_protocol.write(self, section, value) - m:set(section, "protocol", value) -end - -brook_tls = s:option(Flag, "brook_tls", translate("Use TLS")) -brook_tls:depends("brook_protocol", "wsclient") - --- Naiveproxy协议 -naiveproxy_protocol = s:option(ListValue, "naiveproxy_protocol", translate("Protocol")) -naiveproxy_protocol:value("https", translate("HTTPS")) -naiveproxy_protocol:value("quic", translate("QUIC")) -naiveproxy_protocol:depends("type", "Naiveproxy") -function naiveproxy_protocol.cfgvalue(self, section) - return m:get(section, "protocol") -end -function naiveproxy_protocol.write(self, section, value) - m:set(section, "protocol", value) -end - -address = s:option(Value, "address", translate("Address (Support Domain Name)")) -address.rmempty = false -address:depends("type", "Socks") -address:depends("type", "SS") -address:depends("type", "SSR") -address:depends("type", "Brook") -address:depends("type", "Trojan") -address:depends("type", "Trojan-Plus") -address:depends("type", "Trojan-Go") -address:depends("type", "Naiveproxy") -address:depends({ type = "Xray", protocol = "vmess" }) -address:depends({ type = "Xray", protocol = "vless" }) -address:depends({ type = "Xray", protocol = "http" }) -address:depends({ type = "Xray", protocol = "socks" }) -address:depends({ type = "Xray", protocol = "shadowsocks" }) -address:depends({ type = "Xray", protocol = "trojan" }) - ---[[ -use_ipv6 = s:option(Flag, "use_ipv6", translate("Use IPv6")) -use_ipv6.default = 0 -use_ipv6:depends("type", "Socks") -use_ipv6:depends("type", "SS") -use_ipv6:depends("type", "SSR") -use_ipv6:depends("type", "Brook") -use_ipv6:depends("type", "Trojan") -use_ipv6:depends("type", "Trojan-Plus") -use_ipv6:depends("type", "Trojan-Go") -use_ipv6:depends({ type = "Xray", protocol = "vmess" }) -use_ipv6:depends({ type = "Xray", protocol = "vless" }) -use_ipv6:depends({ type = "Xray", protocol = "http" }) -use_ipv6:depends({ type = "Xray", protocol = "socks" }) -use_ipv6:depends({ type = "Xray", protocol = "shadowsocks" }) -use_ipv6:depends({ type = "Xray", protocol = "trojan" }) ---]] - -port = s:option(Value, "port", translate("Port")) -port.datatype = "port" -port.rmempty = false -port:depends("type", "Socks") -port:depends("type", "SS") -port:depends("type", "SSR") -port:depends("type", "Brook") -port:depends("type", "Trojan") -port:depends("type", "Trojan-Plus") -port:depends("type", "Trojan-Go") -port:depends("type", "Naiveproxy") -port:depends({ type = "Xray", protocol = "vmess" }) -port:depends({ type = "Xray", protocol = "vless" }) -port:depends({ type = "Xray", protocol = "http" }) -port:depends({ type = "Xray", protocol = "socks" }) -port:depends({ type = "Xray", protocol = "shadowsocks" }) -port:depends({ type = "Xray", protocol = "trojan" }) - -username = s:option(Value, "username", translate("Username")) -username:depends("type", "Socks") -username:depends("type", "Naiveproxy") -username:depends({ type = "Xray", protocol = "http" }) -username:depends({ type = "Xray", protocol = "socks" }) - -password = s:option(Value, "password", translate("Password")) -password.password = true -password:depends("type", "Socks") -password:depends("type", "SS") -password:depends("type", "SSR") -password:depends("type", "Brook") -password:depends("type", "Trojan") -password:depends("type", "Trojan-Plus") -password:depends("type", "Trojan-Go") -password:depends("type", "Naiveproxy") -password:depends({ type = "Xray", protocol = "http" }) -password:depends({ type = "Xray", protocol = "socks" }) -password:depends({ type = "Xray", protocol = "shadowsocks" }) -password:depends({ type = "Xray", protocol = "trojan" }) - -ss_encrypt_method = s:option(ListValue, "ss_encrypt_method", translate("Encrypt Method")) -for a, t in ipairs(ss_encrypt_method_list) do ss_encrypt_method:value(t) end -ss_encrypt_method:depends("type", "SS") -function ss_encrypt_method.cfgvalue(self, section) - return m:get(section, "method") -end -function ss_encrypt_method.write(self, section, value) - m:set(section, "method", value) -end - -ssr_encrypt_method = s:option(ListValue, "ssr_encrypt_method", translate("Encrypt Method")) -for a, t in ipairs(ssr_encrypt_method_list) do ssr_encrypt_method:value(t) end -ssr_encrypt_method:depends("type", "SSR") -function ssr_encrypt_method.cfgvalue(self, section) - return m:get(section, "method") -end -function ssr_encrypt_method.write(self, section, value) - m:set(section, "method", value) -end - -security = s:option(ListValue, "security", translate("Encrypt Method")) -for a, t in ipairs(security_list) do security:value(t) end -security:depends({ type = "Xray", protocol = "vmess" }) - -encryption = s:option(Value, "encryption", translate("Encrypt Method")) -encryption.default = "none" -encryption:depends({ type = "Xray", protocol = "vless" }) - -v_ss_encrypt_method = s:option(ListValue, "v_ss_encrypt_method", translate("Encrypt Method")) -for a, t in ipairs(v_ss_encrypt_method_list) do v_ss_encrypt_method:value(t) end -v_ss_encrypt_method:depends("protocol", "shadowsocks") -function v_ss_encrypt_method.cfgvalue(self, section) - return m:get(section, "method") -end -function v_ss_encrypt_method.write(self, section, value) - m:set(section, "method", value) -end - -ssr_protocol = s:option(ListValue, "ssr_protocol", translate("Protocol")) -for a, t in ipairs(ssr_protocol_list) do ssr_protocol:value(t) end -ssr_protocol:depends("type", "SSR") -function ssr_protocol.cfgvalue(self, section) - return m:get(section, "protocol") -end -function ssr_protocol.write(self, section, value) - m:set(section, "protocol", value) -end - -protocol_param = s:option(Value, "protocol_param", translate("Protocol_param")) -protocol_param:depends("type", "SSR") - -obfs = s:option(ListValue, "obfs", translate("Obfs")) -for a, t in ipairs(ssr_obfs_list) do obfs:value(t) end -obfs:depends("type", "SSR") - -obfs_param = s:option(Value, "obfs_param", translate("Obfs_param")) -obfs_param:depends("type", "SSR") - -timeout = s:option(Value, "timeout", translate("Connection Timeout")) -timeout.datatype = "uinteger" -timeout.default = 300 -timeout:depends("type", "SS") -timeout:depends("type", "SSR") - -tcp_fast_open = s:option(ListValue, "tcp_fast_open", translate("TCP Fast Open"), translate("Need node support required")) -tcp_fast_open:value("false") -tcp_fast_open:value("true") -tcp_fast_open:depends("type", "SS") -tcp_fast_open:depends("type", "SSR") -tcp_fast_open:depends("type", "Trojan") -tcp_fast_open:depends("type", "Trojan-Plus") -tcp_fast_open:depends("type", "Trojan-Go") - -ss_plugin = s:option(ListValue, "ss_plugin", translate("plugin")) -ss_plugin:value("none", translate("none")) -if api.is_finded("v2ray-plugin") then ss_plugin:value("v2ray-plugin") end -if api.is_finded("obfs-local") then ss_plugin:value("obfs-local") end -ss_plugin:depends("type", "SS") -function ss_plugin.cfgvalue(self, section) - return m:get(section, "plugin") -end -function ss_plugin.write(self, section, value) - m:set(section, "plugin", value) -end - -ss_plugin_opts = s:option(Value, "ss_plugin_opts", translate("opts")) -ss_plugin_opts:depends("ss_plugin", "v2ray-plugin") -ss_plugin_opts:depends("ss_plugin", "obfs-local") -function ss_plugin_opts.cfgvalue(self, section) - return m:get(section, "plugin_opts") -end -function ss_plugin_opts.write(self, section, value) - m:set(section, "plugin_opts", value) -end - -use_kcp = s:option(Flag, "use_kcp", translate("Use Kcptun"), - "" .. translate("Please confirm whether the Kcptun is installed. If not, please go to Rule Update download installation.") .. "") -use_kcp.default = 0 -use_kcp:depends("type", "SS") -use_kcp:depends("type", "SSR") -use_kcp:depends("type", "Brook") - -kcp_server = s:option(Value, "kcp_server", translate("Kcptun Server")) -kcp_server.placeholder = translate("Default:Current Server") -kcp_server:depends("use_kcp", "1") - -kcp_port = s:option(Value, "kcp_port", translate("Kcptun Port")) -kcp_port.datatype = "port" -kcp_port:depends("use_kcp", "1") - -kcp_opts = s:option(TextValue, "kcp_opts", translate("Kcptun Config"), translate("--crypt aes192 --key abc123 --mtu 1350 --sndwnd 128 --rcvwnd 1024 --mode fast")) -kcp_opts.placeholder = "--crypt aes192 --key abc123 --mtu 1350 --sndwnd 128 --rcvwnd 1024 --mode fast" -kcp_opts:depends("use_kcp", "1") - -uuid = s:option(Value, "uuid", translate("ID")) -uuid.password = true -uuid:depends({ type = "Xray", protocol = "vmess" }) -uuid:depends({ type = "Xray", protocol = "vless" }) - -alter_id = s:option(Value, "alter_id", translate("Alter ID")) -alter_id:depends("protocol", "vmess") - -tls = s:option(Flag, "tls", translate("TLS")) -tls.default = 0 -tls.validate = function(self, value, t) - if value then - local type = type:formvalue(t) or "" - if value == "0" and (type == "Trojan" or type == "Trojan-Plus") then - return nil, translate("Original Trojan only supported 'tls', please choose 'tls'.") - end - return value - end -end -tls:depends({ type = "Xray", protocol = "vmess" }) -tls:depends({ type = "Xray", protocol = "vless" }) -tls:depends({ type = "Xray", protocol = "socks" }) -tls:depends({ type = "Xray", protocol = "trojan" }) -tls:depends({ type = "Xray", protocol = "shadowsocks" }) -tls:depends("type", "Trojan") -tls:depends("type", "Trojan-Plus") -tls:depends("type", "Trojan-Go") - -xtls = s:option(Flag, "xtls", translate("XTLS")) -xtls.default = 0 -xtls:depends({ type = "Xray", protocol = "vless", tls = true }) -xtls:depends({ type = "Xray", protocol = "trojan", tls = true }) - -flow = s:option(Value, "flow", translate("flow")) -flow.default = "xtls-rprx-direct" -flow:value("xtls-rprx-origin") -flow:value("xtls-rprx-origin-udp443") -flow:value("xtls-rprx-direct") -flow:value("xtls-rprx-direct-udp443") -flow:value("xtls-rprx-splice") -flow:value("xtls-rprx-splice-udp443") -flow:depends("xtls", true) - --- [[ TLS部分 ]] -- -tls_sessionTicket = s:option(Flag, "tls_sessionTicket", translate("Session Ticket")) -tls_sessionTicket.default = "0" -tls_sessionTicket:depends({ type = "Trojan", tls = true }) -tls_sessionTicket:depends({ type = "Trojan-Plus", tls = true }) -tls_sessionTicket:depends({ type = "Trojan-Go", tls = true }) - -trojan_go_fingerprint = s:option(ListValue, "trojan_go_fingerprint", translate("Finger Print")) -for a, t in ipairs(force_fp) do trojan_go_fingerprint:value(t) end -trojan_go_fingerprint.default = "firefox" -trojan_go_fingerprint:depends({ type = "Trojan-Go", tls = true }) -function trojan_go_fingerprint.cfgvalue(self, section) - return m:get(section, "fingerprint") -end -function trojan_go_fingerprint.write(self, section, value) - m:set(section, "fingerprint", value) -end - -tls_serverName = s:option(Value, "tls_serverName", translate("Domain")) -tls_serverName:depends("tls", true) - -tls_allowInsecure = s:option(Flag, "tls_allowInsecure", translate("allowInsecure"), translate("Whether unsafe connections are allowed. When checked, Certificate validation will be skipped.")) -tls_allowInsecure.default = "0" -tls_allowInsecure:depends("tls", true) - -xray_fingerprint = s:option(ListValue, "fingerprint", translate("Finger Print")) -xray_fingerprint:value("disable") -xray_fingerprint:value("chrome") -xray_fingerprint:value("firefox") -xray_fingerprint:value("safari") -xray_fingerprint:value("randomized") -xray_fingerprint.default = "disable" -xray_fingerprint:depends({ type = "Xray", tls = true, xtls = false }) - -trojan_transport = s:option(ListValue, "trojan_transport", translate("Transport")) -trojan_transport:value("original", "Original") -trojan_transport:value("ws", "WebSocket") -trojan_transport:value("h2", "HTTP/2") -trojan_transport:value("h2+ws", "HTTP/2 & WebSocket") -trojan_transport.default = "original" -trojan_transport:depends("type", "Trojan-Go") - -trojan_plugin = s:option(ListValue, "plugin_type", translate("Plugin Type")) -trojan_plugin:value("plaintext", "Plain Text") -trojan_plugin:value("shadowsocks", "ShadowSocks") -trojan_plugin:value("other", "Other") -trojan_plugin.default = "plaintext" -trojan_plugin:depends({ tls = false, trojan_transport = "original" }) - -trojan_plugin_cmd = s:option(Value, "plugin_cmd", translate("Plugin Binary")) -trojan_plugin_cmd.placeholder = "eg: /usr/bin/v2ray-plugin" -trojan_plugin_cmd:depends({ plugin_type = "shadowsocks" }) -trojan_plugin_cmd:depends({ plugin_type = "other" }) - -trojan_plugin_op = s:option(Value, "plugin_option", translate("Plugin Option")) -trojan_plugin_op.placeholder = "eg: obfs=http;obfs-host=www.baidu.com" -trojan_plugin_op:depends({ plugin_type = "shadowsocks" }) -trojan_plugin_op:depends({ plugin_type = "other" }) - -trojan_plugin_arg = s:option(DynamicList, "plugin_arg", translate("Plugin Option Args")) -trojan_plugin_arg.placeholder = "eg: [\"-config\", \"test.json\"]" -trojan_plugin_arg:depends({ plugin_type = "shadowsocks" }) -trojan_plugin_arg:depends({ plugin_type = "other" }) - -transport = s:option(ListValue, "transport", translate("Transport")) -transport:value("tcp", "TCP") -transport:value("mkcp", "mKCP") -transport:value("ws", "WebSocket") -transport:value("h2", "HTTP/2") -transport:value("ds", "DomainSocket") -transport:value("quic", "QUIC") -transport:value("grpc", "gRPC") -transport:depends({ type = "Xray", protocol = "vmess" }) -transport:depends({ type = "Xray", protocol = "vless" }) -transport:depends({ type = "Xray", protocol = "socks" }) -transport:depends({ type = "Xray", protocol = "shadowsocks" }) -transport:depends({ type = "Xray", protocol = "trojan" }) - ---[[ -ss_transport = s:option(ListValue, "ss_transport", translate("Transport")) -ss_transport:value("ws", "WebSocket") -ss_transport:value("h2", "HTTP/2") -ss_transport:value("h2+ws", "HTTP/2 & WebSocket") -ss_transport:depends({ type = "Xray", protocol = "shadowsocks" }) -]]-- - --- [[ TCP部分 ]]-- - --- TCP伪装 -tcp_guise = s:option(ListValue, "tcp_guise", translate("Camouflage Type")) -tcp_guise:value("none", "none") -tcp_guise:value("http", "http") -tcp_guise:depends("transport", "tcp") - --- HTTP域名 -tcp_guise_http_host = s:option(DynamicList, "tcp_guise_http_host", translate("HTTP Host")) -tcp_guise_http_host:depends("tcp_guise", "http") - --- HTTP路径 -tcp_guise_http_path = s:option(DynamicList, "tcp_guise_http_path", translate("HTTP Path")) -tcp_guise_http_path:depends("tcp_guise", "http") - --- [[ mKCP部分 ]]-- - -mkcp_guise = s:option(ListValue, "mkcp_guise", translate("Camouflage Type"), translate('
none: default, no masquerade, data sent is packets with no characteristics.
srtp: disguised as an SRTP packet, it will be recognized as video call data (such as FaceTime).
utp: packets disguised as uTP will be recognized as bittorrent downloaded data.
wechat-video: packets disguised as WeChat video calls.
dtls: disguised as DTLS 1.2 packet.
wireguard: disguised as a WireGuard packet. (not really WireGuard protocol)')) -for a, t in ipairs(header_type_list) do mkcp_guise:value(t) end -mkcp_guise:depends("transport", "mkcp") - -mkcp_mtu = s:option(Value, "mkcp_mtu", translate("KCP MTU")) -mkcp_mtu.default = "1350" -mkcp_mtu:depends("transport", "mkcp") - -mkcp_tti = s:option(Value, "mkcp_tti", translate("KCP TTI")) -mkcp_tti.default = "20" -mkcp_tti:depends("transport", "mkcp") - -mkcp_uplinkCapacity = s:option(Value, "mkcp_uplinkCapacity", translate("KCP uplinkCapacity")) -mkcp_uplinkCapacity.default = "5" -mkcp_uplinkCapacity:depends("transport", "mkcp") - -mkcp_downlinkCapacity = s:option(Value, "mkcp_downlinkCapacity", translate("KCP downlinkCapacity")) -mkcp_downlinkCapacity.default = "20" -mkcp_downlinkCapacity:depends("transport", "mkcp") - -mkcp_congestion = s:option(Flag, "mkcp_congestion", translate("KCP Congestion")) -mkcp_congestion:depends("transport", "mkcp") - -mkcp_readBufferSize = s:option(Value, "mkcp_readBufferSize", translate("KCP readBufferSize")) -mkcp_readBufferSize.default = "1" -mkcp_readBufferSize:depends("transport", "mkcp") - -mkcp_writeBufferSize = s:option(Value, "mkcp_writeBufferSize", translate("KCP writeBufferSize")) -mkcp_writeBufferSize.default = "1" -mkcp_writeBufferSize:depends("transport", "mkcp") - -mkcp_seed = s:option(Value, "mkcp_seed", translate("KCP Seed")) -mkcp_seed:depends("transport", "mkcp") - --- [[ WebSocket部分 ]]-- -ws_host = s:option(Value, "ws_host", translate("WebSocket Host")) -ws_host:depends("transport", "ws") -ws_host:depends("ss_transport", "ws") -ws_host:depends("trojan_transport", "h2+ws") -ws_host:depends("trojan_transport", "ws") - -ws_path = s:option(Value, "ws_path", translate("WebSocket Path")) -ws_path:depends("transport", "ws") -ws_path:depends("ss_transport", "ws") -ws_path:depends("trojan_transport", "h2+ws") -ws_path:depends("trojan_transport", "ws") - --- [[ HTTP/2部分 ]]-- -h2_host = s:option(Value, "h2_host", translate("HTTP/2 Host")) -h2_host:depends("transport", "h2") -h2_host:depends("ss_transport", "h2") -h2_host:depends("trojan_transport", "h2+ws") -h2_host:depends("trojan_transport", "h2") - -h2_path = s:option(Value, "h2_path", translate("HTTP/2 Path")) -h2_path:depends("transport", "h2") -h2_path:depends("ss_transport", "h2") -h2_path:depends("trojan_transport", "h2+ws") -h2_path:depends("trojan_transport", "h2") - --- [[ DomainSocket部分 ]]-- -ds_path = s:option(Value, "ds_path", "Path", translate("A legal file path. This file must not exist before running.")) -ds_path:depends("transport", "ds") - --- [[ QUIC部分 ]]-- -quic_security = s:option(ListValue, "quic_security", translate("Encrypt Method")) -quic_security:value("none") -quic_security:value("aes-128-gcm") -quic_security:value("chacha20-poly1305") -quic_security:depends("transport", "quic") - -quic_key = s:option(Value, "quic_key", translate("Encrypt Method") .. translate("Key")) -quic_key:depends("transport", "quic") - -quic_guise = s:option(ListValue, "quic_guise", translate("Camouflage Type")) -for a, t in ipairs(header_type_list) do quic_guise:value(t) end -quic_guise:depends("transport", "quic") - --- [[ gRPC部分 ]]-- -grpc_serviceName = s:option(Value, "grpc_serviceName", "ServiceName") -grpc_serviceName:depends("transport", "grpc") - --- [[ Trojan-Go Shadowsocks2 ]] -- -ss_aead = s:option(Flag, "ss_aead", translate("Shadowsocks2")) -ss_aead:depends("type", "Trojan-Go") -ss_aead.default = "0" - -ss_aead_method = s:option(ListValue, "ss_aead_method", translate("Encrypt Method")) -for _, v in ipairs(encrypt_methods_ss_aead) do ss_aead_method:value(v, v) end -ss_aead_method.default = "aead_aes_128_gcm" -ss_aead_method:depends("ss_aead", "1") - -ss_aead_pwd = s:option(Value, "ss_aead_pwd", translate("Password")) -ss_aead_pwd.password = true -ss_aead_pwd:depends("ss_aead", "1") - --- [[ Mux ]]-- -mux = s:option(Flag, "mux", translate("Mux")) -mux:depends({ type = "Xray", protocol = "vmess" }) -mux:depends({ type = "Xray", protocol = "vless", xtls = false }) -mux:depends({ type = "Xray", protocol = "http" }) -mux:depends({ type = "Xray", protocol = "socks" }) -mux:depends({ type = "Xray", protocol = "shadowsocks" }) -mux:depends("type", "Trojan-Go") - -mux_concurrency = s:option(Value, "mux_concurrency", translate("Mux Concurrency")) -mux_concurrency.default = 8 -mux_concurrency:depends("mux", "1") - --- [[ 当作为TCP节点时,是否同时开启socks代理 ]]-- ---[[ -tcp_socks = s:option(Flag, "tcp_socks", translate("TCP Open Socks"), translate("When using this TCP node, whether to open the socks proxy at the same time")) -tcp_socks.default = 0 -tcp_socks:depends("type", "Xray") - -tcp_socks_port = s:option(Value, "tcp_socks_port", "Socks " .. translate("Port"), translate("Do not conflict with other ports")) -tcp_socks_port.datatype = "port" -tcp_socks_port.default = 1080 -tcp_socks_port:depends("tcp_socks", "1") - -tcp_socks_auth = s:option(ListValue, "tcp_socks_auth", translate("Socks for authentication"), translate('Socks protocol authentication, support anonymous and password.')) -tcp_socks_auth:value("noauth", translate("anonymous")) -tcp_socks_auth:value("password", translate("User Password")) -tcp_socks_auth:depends("tcp_socks", "1") - -tcp_socks_auth_username = s:option(Value, "tcp_socks_auth_username", "Socks " .. translate("Username")) -tcp_socks_auth_username:depends("tcp_socks_auth", "password") - -tcp_socks_auth_password = s:option(Value, "tcp_socks_auth_password", "Socks " .. translate("Password")) -tcp_socks_auth_password:depends("tcp_socks_auth", "password") ---]] - -protocol.validate = function(self, value) - if value == "_shunt" or value == "_balancing" then - address.rmempty = true - port.rmempty = true - end - return value -end - -return m diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/node_list.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/node_list.lua deleted file mode 100644 index 556f624ac8..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/node_list.lua +++ /dev/null @@ -1,111 +0,0 @@ -local api = require "luci.model.cbi.passwall.api.api" -local appname = api.appname - -m = Map(appname) - --- [[ Other Settings ]]-- -s = m:section(TypedSection, "global_other") -s.anonymous = true - -o = s:option(MultiValue, "nodes_ping", " ") -o:value("auto_ping", translate("Auto Ping"), translate("This will automatically ping the node for latency")) -o:value("tcping", translate("Tcping"), translate("This will use tcping replace ping detection of node")) -o:value("info", translate("Show server address and port"), translate("Show server address and port")) - --- [[ Add the node via the link ]]-- -s:append(Template(appname .. "/node_list/link_add_node")) - -local nodes_ping = m:get("@global_other[0]", "nodes_ping") or "" - --- [[ Node List ]]-- -s = m:section(TypedSection, "nodes") -s.anonymous = true -s.addremove = true -s.template = "cbi/tblsection" -s.extedit = api.url("node_config", "%s") -function s.create(e, t) - local uuid = api.gen_uuid() - t = uuid - TypedSection.create(e, t) - luci.http.redirect(e.extedit:format(t)) -end - -function s.remove(e, t) - s.map.proceed = true - s.map:del(t) - luci.http.redirect(api.url("node_list")) -end - -s.sortable = true --- 简洁模式 -o = s:option(DummyValue, "add_mode", "") -o.cfgvalue = function(t, n) - local v = Value.cfgvalue(t, n) - if v and v ~= '' then - local group = m:get(n, "group") or "" - if group ~= "" then - v = v .. " " .. group - end - return v - else - return '' - end -end -o = s:option(DummyValue, "remarks", translate("Remarks")) -o.rawhtml = true -o.cfgvalue = function(t, n) - local str = "" - local is_sub = m:get(n, "is_sub") or "" - local group = m:get(n, "group") or "" - local remarks = m:get(n, "remarks") or "" - local type = m:get(n, "type") or "" - str = str .. string.format("", appname, n, type) - if type == "Xray" then - local protocol = m:get(n, "protocol") - if protocol == "_balancing" then - protocol = translate("Balancing") - elseif protocol == "_shunt" then - protocol = translate("Shunt") - elseif protocol == "vmess" then - protocol = "VMess" - elseif protocol == "vless" then - protocol = "VLESS" - else - protocol = protocol:gsub("^%l",string.upper) - end - type = type .. " " .. protocol - end - local address = m:get(n, "address") or "" - local port = m:get(n, "port") or "" - str = str .. translate(type) .. ":" .. remarks - if address ~= "" and port ~= "" then - if nodes_ping:find("info") then - if datatypes.ip6addr(address) then - str = str .. string.format("([%s]:%s)", address, port) - else - str = str .. string.format("(%s:%s)", address, port) - end - end - str = str .. string.format("", appname, n, address) - str = str .. string.format("", appname, n, port) - end - return str -end - ----- Ping -o = s:option(DummyValue, "ping", translate("Latency")) -o.width = "8%" -o.rawhtml = true -o.cfgvalue = function(t, n) - local result = "---" - if not nodes_ping:find("auto_ping") then - result = string.format('Ping', n) - else - result = string.format('---', n) - end - return result -end - -m:append(Template(appname .. "/node_list/node_list")) - -return m diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe.lua deleted file mode 100644 index 815c9d597c..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe.lua +++ /dev/null @@ -1,84 +0,0 @@ -local api = require "luci.model.cbi.passwall.api.api" -local appname = api.appname - -m = Map(appname) - --- [[ Subscribe Settings ]]-- -s = m:section(TypedSection, "global_subscribe", "") -s.anonymous = true - ----- Subscribe via proxy -o = s:option(Flag, "subscribe_proxy", translate("Subscribe via proxy")) -o.default = 0 -o.rmempty = false - ----- Enable auto update subscribe -o = s:option(Flag, "auto_update_subscribe", - translate("Enable auto update subscribe")) -o.default = 0 -o.rmempty = false - ----- Week update rules -o = s:option(ListValue, "week_update_subscribe", translate("Week update rules")) -o:value(7, translate("Every day")) -for e = 1, 6 do o:value(e, translate("Week") .. e) end -o:value(0, translate("Week") .. translate("day")) -o.default = 0 -o:depends("auto_update_subscribe", true) - ----- Day update rules -o = s:option(ListValue, "time_update_subscribe", translate("Day update rules")) -for e = 0, 23 do o:value(e, e .. translate("oclock")) end -o.default = 0 -o:depends("auto_update_subscribe", true) - -o = s:option(ListValue, "filter_keyword_mode", translate("Filter keyword Mode")) -o:value("0", translate("Close")) -o:value("1", translate("Discard List")) -o:value("2", translate("Keep List")) - -o = s:option(DynamicList, "filter_discard_list", translate("Discard List")) - -o = s:option(DynamicList, "filter_keep_list", translate("Keep List")) - -o = s:option(Flag, "allowInsecure", translate("allowInsecure"), translate("Whether unsafe connections are allowed. When checked, Certificate validation will be skipped.")) -o.default = "1" -o.rmempty = false - ----- Manual subscription -o = s:option(Button, "_update", translate("Manual subscription")) -o.inputstyle = "apply" -function o.write(e, e) - luci.sys.call("lua /usr/share/" .. appname .. "/subscribe.lua start log > /dev/null 2>&1 &") - luci.http.redirect(api.url("log")) -end - ----- Subscribe Delete All -o = s:option(Button, "_stop", translate("Delete All Subscribe Node")) -o.inputstyle = "remove" -function o.write(e, e) - luci.sys.call("lua /usr/share/" .. appname .. "/subscribe.lua truncate log > /dev/null 2>&1 &") - luci.http.redirect(api.url("log")) -end - -s = m:section(TypedSection, "subscribe_list", "", - "" .. translate( - "Please input the subscription url first, save and submit before updating. If you subscribe to update, it is recommended to delete all subscriptions and then re-subscribe.") .. - "") -s.addremove = true -s.anonymous = true -s.sortable = true -s.template = "cbi/tblsection" - -o = s:option(Flag, "enabled", translate("Enabled")) -o.rmempty = false - -o = s:option(Value, "remark", translate("Subscribe Remark")) -o.width = "auto" -o.rmempty = false - -o = s:option(Value, "url", translate("Subscribe URL")) -o.width = "auto" -o.rmempty = false - -return m diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/other.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/other.lua deleted file mode 100644 index bdd566ed46..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/other.lua +++ /dev/null @@ -1,131 +0,0 @@ -local api = require "luci.model.cbi.passwall.api.api" -local appname = api.appname - -m = Map(appname) - --- [[ Delay Settings ]]-- -s = m:section(TypedSection, "global_delay", translate("Delay Settings")) -s.anonymous = true -s.addremove = false - ----- Delay Start -o = s:option(Value, "start_delay", translate("Delay Start"), - translate("Units:seconds")) -o.default = "1" -o.rmempty = true - ----- Open and close Daemon -o = s:option(Flag, "start_daemon", translate("Open and close Daemon")) -o.default = 1 -o.rmempty = false - ---[[ ----- Open and close automatically -o = s:option(Flag, "auto_on", translate("Open and close automatically")) -o.default = 0 -o.rmempty = false - ----- Automatically turn off time -o = s:option(ListValue, "time_off", translate("Automatically turn off time")) -o.default = nil -o:depends("auto_on", true) -o:value(nil, translate("Disable")) -for e = 0, 23 do o:value(e, e .. translate("oclock")) end - ----- Automatically turn on time -o = s:option(ListValue, "time_on", translate("Automatically turn on time")) -o.default = nil -o:depends("auto_on", true) -o:value(nil, translate("Disable")) -for e = 0, 23 do o:value(e, e .. translate("oclock")) end - ----- Automatically restart time -o = s:option(ListValue, "time_restart", translate("Automatically restart time")) -o.default = nil -o:depends("auto_on", true) -o:value(nil, translate("Disable")) -for e = 0, 23 do o:value(e, e .. translate("oclock")) end ---]] - --- [[ Forwarding Settings ]]-- -s = m:section(TypedSection, "global_forwarding", - translate("Forwarding Settings")) -s.anonymous = true -s.addremove = false - ----- TCP No Redir Ports -o = s:option(Value, "tcp_no_redir_ports", translate("TCP No Redir Ports")) -o.default = "disable" -o:value("disable", translate("No patterns are used")) -o:value("1:65535", translate("All")) - ----- UDP No Redir Ports -o = s:option(Value, "udp_no_redir_ports", translate("UDP No Redir Ports"), - "" .. translate( - "Fill in the ports you don't want to be forwarded by the agent, with the highest priority.") .. - "") -o.default = "disable" -o:value("disable", translate("No patterns are used")) -o:value("1:65535", translate("All")) - ----- TCP Redir Ports -o = s:option(Value, "tcp_redir_ports", translate("TCP Redir Ports")) -o.default = "22,25,53,143,465,587,993,995,80,443" -o:value("1:65535", translate("All")) -o:value("22,25,53,143,465,587,993,995,80,443", translate("Common Use")) -o:value("80,443", translate("Only Web")) -o:value("80:65535", "80 " .. translate("or more")) -o:value("1:443", "443 " .. translate("or less")) - ----- UDP Redir Ports -o = s:option(Value, "udp_redir_ports", translate("UDP Redir Ports")) -o.default = "1:65535" -o:value("1:65535", translate("All")) -o:value("53", "DNS") - ---[[ ----- Proxy IPv6 -o = s:option(Flag, "proxy_ipv6", translate("Proxy IPv6"), - translate("The IPv6 traffic can be proxyed when selected")) -o.default = 0 ---]] - ---[[ ----- TCP Redir Port -o = s:option(Value, "tcp_redir_port", translate("TCP Redir Port")) -o.datatype = "port" -o.default = 1041 -o.rmempty = true - ----- UDP Redir Port -o = s:option(Value, "udp_redir_port", translate("UDP Redir Port")) -o.datatype = "port" -o.default = 1051 -o.rmempty = true - ----- Kcptun Port -o = s:option(Value, "kcptun_port", translate("Kcptun Port")) -o.datatype = "port" -o.default = 12948 -o.rmempty = true ---]] - --- [[ Other Settings ]]-- -s = m:section(TypedSection, "global_other", translate("Other Settings")) -s.anonymous = true -s.addremove = false - ----- IPv6 TProxy -o = s:option(Flag, "ipv6_tproxy", translate("IPv6 TProxy"), - "" .. translate( - "Experimental feature.Make sure that your node supports IPv6.") .. - "") -o.default = 0 -o.rmempty = false - -o = s:option(MultiValue, "status", translate("Status info")) -o:value("big_icon", translate("Big icon")) -- 大图标 -o:value("show_check_port", translate("Show node check")) -- 显示节点检测 -o:value("show_ip111", translate("Show Show IP111")) -- 显示IP111 - -return m diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/rule.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/rule.lua deleted file mode 100644 index f87cadecb5..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/rule.lua +++ /dev/null @@ -1,72 +0,0 @@ -local api = require "luci.model.cbi.passwall.api.api" -local appname = api.appname - -m = Map(appname) --- [[ Rule Settings ]]-- -s = m:section(TypedSection, "global_rules", translate("Rule status")) -s.anonymous = true - ---[[ -o = s:option(Flag, "adblock", translate("Enable adblock")) -o.rmempty = false -]]-- - ----- gfwlist URL -o = s:option(Value, "gfwlist_url", translate("GFW domains(gfwlist) Update URL")) -o:value("https://cdn.jsdelivr.net/gh/Loukky/gfwlist-by-loukky/gfwlist.txt", translate("Loukky/gfwlist-by-loukky")) -o:value("https://cdn.jsdelivr.net/gh/gfwlist/gfwlist/gfwlist.txt", translate("gfwlist/gfwlist")) -o.default = "https://cdn.jsdelivr.net/gh/Loukky/gfwlist-by-loukky/gfwlist.txt" - -----chnroute URL -o = s:option(Value, "chnroute_url", translate("China IPs(chnroute) Update URL")) -o:value("https://ispip.clang.cn/all_cn.txt", translate("Clang.CN")) -o:value("https://ispip.clang.cn/all_cn_cidr.txt", translate("Clang.CN.CIDR")) -o.default = "https://ispip.clang.cn/all_cn.txt" - -----chnroute6 URL -o = s:option(Value, "chnroute6_url", translate("China IPv6s(chnroute6) Update URL")) -o:value("https://ispip.clang.cn/all_cn_ipv6.txt", translate("Clang.CN.IPv6")) -o.default = "https://ispip.clang.cn/all_cn_ipv6.txt" - -----chnlist URL -o = s:option(DynamicList, "chnlist_url", translate("China List(Chnlist) Update URL")) - -s:append(Template(appname .. "/rule/rule_version")) - ----- Auto Update -o = s:option(Flag, "auto_update", translate("Enable auto update rules")) -o.default = 0 -o.rmempty = false - ----- Week Update -o = s:option(ListValue, "week_update", translate("Week update rules")) -o:value(7, translate("Every day")) -for e = 1, 6 do o:value(e, translate("Week") .. e) end -o:value(0, translate("Week") .. translate("day")) -o.default = 0 -o:depends("auto_update", true) - ----- Time Update -o = s:option(ListValue, "time_update", translate("Day update rules")) -for e = 0, 23 do o:value(e, e .. translate("oclock")) end -o.default = 0 -o:depends("auto_update", true) - -o = s:option(Value, "xray_location_asset", translate("Location of Xray asset"), translate("This variable specifies a directory where geoip.dat and geosite.dat files are.")) -o.default = "/usr/share/xray/" -o.rmempty = false - -s = m:section(TypedSection, "shunt_rules", "Xray " .. translate("Shunt Rule"), "" .. translate("Please note attention to the priority, the higher the order, the higher the priority.") .. "") -s.template = "cbi/tblsection" -s.anonymous = false -s.addremove = true -s.sortable = true -s.extedit = api.url("shunt_rules", "%s") -function s.create(e, t) - TypedSection.create(e, t) - luci.http.redirect(e.extedit:format(t)) -end - -o = s:option(DummyValue, "remarks", translate("Remarks")) - -return m diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/rule_list.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/rule_list.lua deleted file mode 100644 index ac13806eb6..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/rule_list.lua +++ /dev/null @@ -1,133 +0,0 @@ -local fs = require "nixio.fs" -local api = require "luci.model.cbi.passwall.api.api" -local appname = api.appname -local path = string.format("/usr/share/%s/rules/", appname) - -m = Map(appname) -m.apply_on_parse=true -function m.on_apply(self) -luci.sys.call("/etc/init.d/passwall reload > /dev/null 2>&1 &") -end --- [[ Rule List Settings ]]-- -s = m:section(TypedSection, "global_rules") -s.anonymous = true - -s:tab("direct_list", translate("Direct List")) -s:tab("proxy_list", translate("Proxy List")) -s:tab("block_list", translate("Block List")) - ----- Direct Hosts -local direct_host = path .. "direct_host" -o = s:taboption("direct_list", TextValue, "direct_host", "", "" .. translate("Join the direct hosts list of domain names will not proxy.") .. "") -o.rows = 15 -o.wrap = "off" -o.cfgvalue = function(self, section) return fs.readfile(direct_host) or "" end -o.write = function(self, section, value) fs.writefile(direct_host, value:gsub("\r\n", "\n")) end -o.remove = function(self, section, value) fs.writefile(direct_host, "") end -o.validate = function(self, value) - local hosts= {} - string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(hosts, w) end) - for index, host in ipairs(hosts) do - if not datatypes.hostname(host) then - return nil, host .. " " .. translate("Not valid domain name, please re-enter!") - end - end - return value -end - ----- Direct IP -local direct_ip = path .. "direct_ip" -o = s:taboption("direct_list", TextValue, "direct_ip", "", "" .. translate("These had been joined ip addresses will not proxy. Please input the ip address or ip address segment,every line can input only one ip address. For example: 192.168.0.0/24 or 223.5.5.5.") .. "") -o.rows = 15 -o.wrap = "off" -o.cfgvalue = function(self, section) return fs.readfile(direct_ip) or "" end -o.write = function(self, section, value) fs.writefile(direct_ip, value:gsub("\r\n", "\n")) end -o.remove = function(self, section, value) fs.writefile(direct_ip, "") end -o.validate = function(self, value) - local ipmasks= {} - string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(ipmasks, w) end) - for index, ipmask in ipairs(ipmasks) do - if not ( datatypes.ipmask4(ipmask) or datatypes.ipmask6(ipmask) ) then - return nil, ipmask .. " " .. translate("Not valid IP format, please re-enter!") - end - end - return value -end - ----- Proxy Hosts -local proxy_host = path .. "proxy_host" -o = s:taboption("proxy_list", TextValue, "proxy_host", "", "" .. translate("These had been joined websites will use proxy. Please input the domain names of websites, every line can input only one website domain. For example: google.com.") .. "") -o.rows = 15 -o.wrap = "off" -o.cfgvalue = function(self, section) return fs.readfile(proxy_host) or "" end -o.write = function(self, section, value) fs.writefile(proxy_host, value:gsub("\r\n", "\n")) end -o.remove = function(self, section, value) fs.writefile(proxy_host, "") end -o.validate = function(self, value) - local hosts= {} - string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(hosts, w) end) - for index, host in ipairs(hosts) do - if not datatypes.hostname(host) then - return nil, host .. " " .. translate("Not valid domain name, please re-enter!") - end - end - return value -end - ----- Proxy IP -local proxy_ip = path .. "proxy_ip" -o = s:taboption("proxy_list", TextValue, "proxy_ip", "", "" .. translate("These had been joined ip addresses will use proxy. Please input the ip address or ip address segment, every line can input only one ip address. For example: 35.24.0.0/24 or 8.8.4.4.") .. "") -o.rows = 15 -o.wrap = "off" -o.cfgvalue = function(self, section) return fs.readfile(proxy_ip) or "" end -o.write = function(self, section, value) fs.writefile(proxy_ip, value:gsub("\r\n", "\n")) end -o.remove = function(self, section, value) fs.writefile(proxy_ip, "") end -o.validate = function(self, value) - local ipmasks= {} - string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(ipmasks, w) end) - for index, ipmask in ipairs(ipmasks) do - if not ( datatypes.ipmask4(ipmask) or datatypes.ipmask6(ipmask) ) then - return nil, ipmask .. " " .. translate("Not valid IP format, please re-enter!") - end - end - return value -end - ----- Block Hosts -local block_host = path .. "block_host" -o = s:taboption("block_list", TextValue, "block_host", "", "" .. translate("These had been joined websites will be block. Please input the domain names of websites, every line can input only one website domain. For example: twitter.com.") .. "") -o.rows = 15 -o.wrap = "off" -o.cfgvalue = function(self, section) return fs.readfile(block_host) or "" end -o.write = function(self, section, value) fs.writefile(block_host, value:gsub("\r\n", "\n")) end -o.remove = function(self, section, value) fs.writefile(block_host, "") end -o.validate = function(self, value) - local hosts= {} - string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(hosts, w) end) - for index, host in ipairs(hosts) do - if not datatypes.hostname(host) then - return nil, host .. " " .. translate("Not valid domain name, please re-enter!") - end - end - return value -end - ----- Block IP -local block_ip = path .. "block_ip" -o = s:taboption("block_list", TextValue, "block_ip", "", "" .. translate("These had been joined ip addresses will be block. Please input the ip address or ip address segment, every line can input only one ip address.") .. "") -o.rows = 15 -o.wrap = "off" -o.cfgvalue = function(self, section) return fs.readfile(block_ip) or "" end -o.write = function(self, section, value) fs.writefile(block_ip, value:gsub("\r\n", "\n")) end -o.remove = function(self, section, value) fs.writefile(block_ip, "") end -o.validate = function(self, value) - local ipmasks= {} - string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(ipmasks, w) end) - for index, ipmask in ipairs(ipmasks) do - if not ( datatypes.ipmask4(ipmask) or datatypes.ipmask6(ipmask) ) then - return nil, ipmask .. " " .. translate("Not valid IP format, please re-enter!") - end - end - return value -end - -return m diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/shunt_rules.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/shunt_rules.lua deleted file mode 100644 index d0976d4257..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/shunt_rules.lua +++ /dev/null @@ -1,78 +0,0 @@ -local api = require "luci.model.cbi.passwall.api.api" -local appname = api.appname - -m = Map(appname, "Xray" .. translate("Shunt") .. translate("Rule")) -m.redirect = api.url() - -s = m:section(NamedSection, arg[1], "shunt_rules", "") -s.addremove = false -s.dynamic = false - -remarks = s:option(Value, "remarks", translate("Remarks")) -remarks.default = arg[1] -remarks.rmempty = false - -protocol = s:option(MultiValue, "protocol", translate("Protocol")) -protocol:value("http") -protocol:value("tls") -protocol:value("bittorrent") - -domain_list = s:option(TextValue, "domain_list", translate("Domain")) -domain_list.rows = 10 -domain_list.wrap = "off" -domain_list.validate = function(self, value) - local hosts= {} - string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(hosts, w) end) - for index, host in ipairs(hosts) do - local flag = 1 - local tmp_host = host - if host:find("regexp:") and host:find("regexp:") == 1 then - flag = 0 - elseif host:find("domain:.") and host:find("domain:.") == 1 then - tmp_host = host:gsub("domain:", "") - elseif host:find("full:.") and host:find("full:.") == 1 then - tmp_host = host:gsub("full:", "") - elseif host:find("geosite:") and host:find("geosite:") == 1 then - flag = 0 - elseif host:find("ext:") and host:find("ext:") == 1 then - flag = 0 - end - if flag == 1 then - if not datatypes.hostname(tmp_host) then - return nil, tmp_host .. " " .. translate("Not valid domain name, please re-enter!") - end - end - end - return value -end -domain_list.description = "
  • " .. translate("Plaintext: If this string matches any part of the targeting domain, this rule takes effet. Example: rule 'sina.com' matches targeting domain 'sina.com', 'sina.com.cn' and 'www.sina.com', but not 'sina.cn'.") -.. "
  • " .. translate("Regular expression: Begining with 'regexp:', the rest is a regular expression. When the regexp matches targeting domain, this rule takes effect. Example: rule 'regexp:\\.goo.*\\.com$' matches 'www.google.com' and 'fonts.googleapis.com', but not 'google.com'.") -.. "
  • " .. translate("Subdomain (recommended): Begining with 'domain:' and the rest is a domain. When the targeting domain is exactly the value, or is a subdomain of the value, this rule takes effect. Example: rule 'domain:v2ray.com' matches 'www.v2ray.com', 'v2ray.com', but not 'xv2ray.com'.") -.. "
  • " .. translate("Full domain: Begining with 'full:' and the rest is a domain. When the targeting domain is exactly the value, the rule takes effect. Example: rule 'domain:v2ray.com' matches 'v2ray.com', but not 'www.v2ray.com'.") -.. "
  • " .. translate("Pre-defined domain list: Begining with 'geosite:' and the rest is a name, such as geosite:google or geosite:cn.") -.. "
  • " .. translate("Domains from file: Such as 'ext:file:tag'. The value must begin with ext: (lowercase), and followed by filename and tag. The file is placed in resource directory, and has the same format of geosite.dat. The tag must exist in the file.") -.. "
" -ip_list = s:option(TextValue, "ip_list", "IP") -ip_list.rows = 10 -ip_list.wrap = "off" -ip_list.validate = function(self, value) - local ipmasks= {} - string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(ipmasks, w) end) - for index, ipmask in ipairs(ipmasks) do - if ipmask:find("geoip:") and ipmask:find("geoip:") == 1 then - elseif ipmask:find("ext:") and ipmask:find("ext:") == 1 then - else - if not (datatypes.ipmask4(ipmask) or datatypes.ipmask6(ipmask)) then - return nil, ipmask .. " " .. translate("Not valid IP format, please re-enter!") - end - end - end - return value -end -ip_list.description = "
  • " .. translate("IP: such as '127.0.0.1'.") -.. "
  • " .. translate("CIDR: such as '127.0.0.0/8'.") -.. "
  • " .. translate("GeoIP: such as 'geoip:cn'. It begins with geoip: (lower case) and followed by two letter of country code.") -.. "
  • " .. translate("IPs from file: Such as 'ext:file:tag'. The value must begin with ext: (lowercase), and followed by filename and tag. The file is placed in resource directory, and has the same format of geoip.dat. The tag must exist in the file.") -.. "
" - -return m diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/app.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/app.lua deleted file mode 100755 index 9128db9e64..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/app.lua +++ /dev/null @@ -1,174 +0,0 @@ -#!/usr/bin/lua - -local action = arg[1] -local sys = require 'luci.sys' -local jsonc = require "luci.jsonc" -local ucic = require"luci.model.uci".cursor() -local api = require "luci.model.cbi.passwall.api.api" - -local CONFIG = "passwall_server" -local CONFIG_PATH = "/var/etc/" .. CONFIG -local LOG_APP_FILE = "/var/log/" .. CONFIG .. ".log" -local TMP_BIN_PATH = CONFIG_PATH .. "/bin" - -local function log(...) - local f, err = io.open(LOG_APP_FILE, "a") - if f and err == nil then - local str = os.date("%Y-%m-%d %H:%M:%S: ") .. table.concat({...}, " ") - f:write(str .. "\n") - f:close() - end -end - -local function cmd(cmd) - sys.call(cmd) -end - -local function ln_start(s, d, command, output) - if not output then - output = "/dev/null" - end - d = TMP_BIN_PATH .. "/" .. d - cmd(string.format('[ ! -f "%s" ] && ln -s %s %s 2>/dev/null', d, s, d)) - return string.format("%s >%s 2>&1 &", d .. " " ..command, output) -end - -local function gen_include() - cmd(string.format("echo '#!/bin/sh' > /var/etc/%s.include", CONFIG)) - local function extract_rules(n, a) - local _ipt = "iptables" - if n == "6" then - _ipt = "ip6tables" - end - local result = "*" .. a - result = result .. "\n" .. sys.exec(_ipt .. '-save -t ' .. a .. ' | grep "PSW-SERVER" | sed -e "s/^-A \\(INPUT\\)/-I \\1 1/"') - result = result .. "COMMIT" - return result - end - local f, err = io.open("/var/etc/" .. CONFIG .. ".include", "a") - if f and err == nil then - f:write('iptables-save -c | grep -v "PSW-SERVER" | iptables-restore -c' .. "\n") - f:write('iptables-restore -n <<-EOT' .. "\n") - f:write(extract_rules("4", "filter") .. "\n") - f:write("EOT" .. "\n") - f:write('ip6tables-save -c | grep -v "PSW-SERVER" | ip6tables-restore -c' .. "\n") - f:write('ip6tables-restore -n <<-EOT' .. "\n") - f:write(extract_rules("6", "filter") .. "\n") - f:write("EOT" .. "\n") - f:close() - end -end - -local function start() - local enabled = tonumber(ucic:get(CONFIG, "@global[0]", "enable") or 0) - if enabled == nil or enabled == 0 then - return - end - cmd(string.format("mkdir -p %s %s", CONFIG_PATH, TMP_BIN_PATH)) - cmd(string.format("touch %s", LOG_APP_FILE)) - cmd("iptables -N PSW-SERVER") - cmd("iptables -I INPUT -j PSW-SERVER") - cmd("ip6tables -N PSW-SERVER") - cmd("ip6tables -I INPUT -j PSW-SERVER") - ucic:foreach(CONFIG, "user", function(user) - local id = user[".name"] - local enable = user.enable - if enable and tonumber(enable) == 1 then - local enable_log = user.log - local log_path = nil - if enable_log and enable_log == "1" then - log_path = CONFIG_PATH .. "/" .. id .. ".log" - else - log_path = nil - end - local remarks = user.remarks - local port = tonumber(user.port) - local bin - local config = {} - local config_file = CONFIG_PATH .. "/" .. id .. ".json" - local udp_forward = 1 - local type = user.type or "" - if type == "Socks" then - local auth = "" - if user.auth and user.auth == "1" then - local username = user.username or "" - local password = user.password or "" - if username ~= "" and password ~= "" then - username = "-u " .. username - password = "-P " .. password - auth = username .. " " .. password - end - end - bin = ln_start("/usr/bin/microsocks", "microsocks_" .. id, string.format("-i :: -p %s %s", port, auth), log_path) - elseif type == "SS" or type == "SSR" then - config = require("luci.model.cbi.passwall.server.api.shadowsocks").gen_config(user) - local udp_param = "" - udp_forward = tonumber(user.udp_forward) or 1 - if udp_forward == 1 then - udp_param = "-u" - end - type = type:lower() - bin = ln_start("/usr/bin/" .. type .. "-server", type .. "-server", "-c " .. config_file .. " " .. udp_param, log_path) - elseif type == "Xray" then - config = require("luci.model.cbi.passwall.server.api.xray").gen_config(user) - bin = ln_start(api.get_xray_path(), "xray", "-config=" .. config_file, log_path) - elseif type == "Trojan" then - config = require("luci.model.cbi.passwall.server.api.trojan").gen_config(user) - bin = ln_start("/usr/sbin/trojan", "trojan", "-c " .. config_file, log_path) - elseif type == "Trojan-Plus" then - config = require("luci.model.cbi.passwall.server.api.trojan").gen_config(user) - bin = ln_start("/usr/sbin/trojan-plus", "trojan-plus", "-c " .. config_file, log_path) - elseif type == "Trojan-Go" then - config = require("luci.model.cbi.passwall.server.api.trojan").gen_config(user) - bin = ln_start(api.get_trojan_go_path(), "trojan-go", "-config " .. config_file, log_path) - elseif type == "Brook" then - local brook_protocol = user.protocol - local brook_password = user.password - bin = ln_start(api.get_brook_path(), "brook_" .. id, string.format("%s -l :%s -p %s", brook_protocol, port, brook_password), log_path) - end - - if next(config) then - local f, err = io.open(config_file, "w") - if f and err == nil then - f:write(jsonc.stringify(config, 1)) - f:close() - end - log(string.format("%s %s 生成配置文件并运行 - %s", remarks, port, config_file)) - end - - if bin then - cmd(bin) - end - - local bind_local = user.bind_local or 0 - if bind_local and tonumber(bind_local) ~= 1 then - cmd(string.format('iptables -A PSW-SERVER -p tcp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks)) - cmd(string.format('ip6tables -A PSW-SERVER -p tcp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks)) - if udp_forward == 1 then - cmd(string.format('iptables -A PSW-SERVER -p udp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks)) - cmd(string.format('ip6tables -A PSW-SERVER -p udp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks)) - end - end - end - end) - gen_include() -end - -local function stop() - cmd(string.format("top -bn1 | grep -v 'grep' | grep '%s/' | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1", CONFIG_PATH)) - cmd("iptables -D INPUT -j PSW-SERVER 2>/dev/null") - cmd("iptables -F PSW-SERVER 2>/dev/null") - cmd("iptables -X PSW-SERVER 2>/dev/null") - cmd("ip6tables -D INPUT -j PSW-SERVER 2>/dev/null") - cmd("ip6tables -F PSW-SERVER 2>/dev/null") - cmd("ip6tables -X PSW-SERVER 2>/dev/null") - cmd(string.format("rm -rf %s %s /var/etc/%s.include", CONFIG_PATH, LOG_APP_FILE, CONFIG)) -end - -if action then - if action == "start" then - start() - elseif action == "stop" then - stop() - end -end \ No newline at end of file diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/shadowsocks.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/shadowsocks.lua deleted file mode 100644 index fdd18e0e2f..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/shadowsocks.lua +++ /dev/null @@ -1,19 +0,0 @@ -module("luci.model.cbi.passwall.server.api.shadowsocks", package.seeall) -function gen_config(user) - local config = {} - config.server = {"[::0]", "0.0.0.0"} - config.server_port = tonumber(user.port) - config.password = user.password - config.timeout = tonumber(user.timeout) - config.fast_open = (user.tcp_fast_open and user.tcp_fast_open == "1") and true or false - config.method = user.method - - if user.type == "SSR" then - config.protocol = user.protocol - config.protocol_param = user.protocol_param - config.obfs = user.obfs - config.obfs_param = user.obfs_param - end - - return config -end diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/trojan.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/trojan.lua deleted file mode 100644 index 5f6a2b4ac3..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/trojan.lua +++ /dev/null @@ -1,60 +0,0 @@ -module("luci.model.cbi.passwall.server.api.trojan", package.seeall) -function gen_config(user) - local cipher = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:AES128-SHA:AES256-SHA:DES-CBC3-SHA" - local cipher13 = "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384" - local config = { - run_type = "server", - local_addr = "::", - local_port = tonumber(user.port), - remote_addr = (user.remote_enable == "1" and user.remote_address) and user.remote_address or nil, - remote_port = (user.remote_enable == "1" and user.remote_port) and tonumber(user.remote_port) or nil, - password = user.uuid, - log_level = (user.log and user.log == "1") and tonumber(user.loglevel) or 5, - ssl = { - cert = user.tls_certificateFile, - key = user.tls_keyFile, - key_password = "", - cipher = user.fingerprint == nil and cipher or (user.fingerprint == "disable" and cipher13 .. ":" .. cipher or ""), - cipher_tls13 = user.fingerprint == nil and cipher13 or nil, - sni = nil, - verify = (user.tls_allowInsecure ~= "1") and true or false, - verify_hostname = false, - reuse_session = true, - session_ticket = (user.tls_sessionTicket == "1") and true or false, - prefer_server_cipher = true, - session_timeout = 600, - plain_http_response = "", - curves = "", - dhparam = "" - }, - udp_timeout = 60, - disable_http_check = true, - transport_plugin = ((user.tls == nil or user.tls ~= "1") and user.trojan_transport == "original") and { - enabled = user.plugin_type ~= nil, - type = user.plugin_type or "plaintext", - command = user.plugin_type ~= "plaintext" and user.plugin_cmd or nil, - option = user.plugin_type ~= "plaintext" and user.plugin_option or nil, - arg = user.plugin_type ~= "plaintext" and { user.plugin_arg } or nil, - env = {} - } or nil, - websocket = (user.trojan_transport and user.trojan_transport:find('ws')) and { - enabled = true, - path = user.ws_path or "/", - host = user.ws_host or "" - } or nil, - shadowsocks = (user.ss_aead == "1") and { - enabled = true, - method = user.ss_aead_method or "aead_aes_128_gcm", - password = user.ss_aead_pwd or "" - } or nil, - tcp = { - prefer_ipv4 = false, - no_delay = true, - keep_alive = true, - reuse_port = false, - fast_open = (user.tcp_fast_open and user.tcp_fast_open == "1") and true or false, - fast_open_qlen = 20 - } - } - return config -end \ No newline at end of file diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/xray.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/xray.lua deleted file mode 100644 index 7052b32f84..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/xray.lua +++ /dev/null @@ -1,233 +0,0 @@ -module("luci.model.cbi.passwall.server.api.xray", package.seeall) -local ucic = require"luci.model.uci".cursor() - -function gen_config(user) - local settings = nil - local routing = nil - local outbounds = { - {protocol = "freedom", tag = "direct"}, {protocol = "blackhole", tag = "blocked"} - } - - if user.protocol == "vmess" or user.protocol == "vless" then - if user.uuid then - local clients = {} - for i = 1, #user.uuid do - clients[i] = { - id = user.uuid[i], - flow = ("1" == user.xtls) and user.flow or nil, - alterId = user.alter_id and tonumber(user.alter_id) or nil - } - end - settings = { - clients = clients, - decryption = user.decryption or "none" - } - end - elseif user.protocol == "socks" then - settings = { - auth = ("1" == user.auth) and "password" or "noauth", - accounts = ("1" == user.auth) and { - { - user = user.username, - pass = user.password - } - } - } - elseif user.protocol == "http" then - settings = { - allowTransparent = false, - accounts = ("1" == user.auth) and { - { - user = user.username, - pass = user.password - } - } - } - user.transport = "tcp" - user.tcp_guise = "none" - elseif user.protocol == "shadowsocks" then - settings = { - method = user.method, - password = user.password, - network = user.ss_network or "TCP,UDP" - } - elseif user.protocol == "trojan" then - if user.uuid then - local clients = {} - for i = 1, #user.uuid do - clients[i] = { - flow = ("1" == user.xtls) and user.flow or nil, - password = user.uuid[i], - } - end - settings = { - clients = clients - } - end - elseif user.protocol == "mtproto" then - settings = { - users = { - { - secret = (user.password == nil) and "" or user.password - } - } - } - end - - if user.fallback and user.fallback == "1" then - local fallbacks = {} - for i = 1, #user.fallback_list do - local fallbackStr = user.fallback_list[i] - if fallbackStr then - local tmp = {} - string.gsub(fallbackStr, '[^' .. "," .. ']+', function(w) - table.insert(tmp, w) - end) - local dest = tmp[1] or "" - local path = tmp[2] - if dest:find("%.") then - else - dest = tonumber(dest) - end - fallbacks[i] = { - path = path, - dest = dest, - xver = 1 - } - end - end - settings.fallbacks = fallbacks - end - - routing = { - domainStrategy = "IPOnDemand", - rules = { - { - type = "field", - ip = {"10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"}, - outboundTag = (user.accept_lan == nil or user.accept_lan == "0") and "blocked" or "direct" - } - } - } - - if user.transit_node and user.transit_node ~= "nil" then - local transit_node_t = ucic:get_all("passwall", user.transit_node) - if user.transit_node == "_socks" or user.transit_node == "_http" then - transit_node_t = { - type = "Xray", - protocol = user.transit_node:gsub("_", ""), - transport = "tcp", - address = user.transit_node_address, - port = user.transit_node_port, - username = (user.transit_node_username and user.transit_node_username ~= "") and user.transit_node_username or nil, - password = (user.transit_node_password and user.transit_node_password ~= "") and user.transit_node_password or nil, - } - end - local gen_xray = require("luci.model.cbi.passwall.api.gen_xray") - local outbound = gen_xray.gen_outbound(transit_node_t, "transit") - if outbound then - table.insert(outbounds, 1, outbound) - end - end - - local config = { - log = { - -- error = "/var/etc/passwall_server/log/" .. user[".name"] .. ".log", - loglevel = ("1" == user.log) and user.loglevel or "none" - }, - -- 传入连接 - inbounds = { - { - listen = (user.bind_local == "1") and "127.0.0.1" or nil, - port = tonumber(user.port), - protocol = user.protocol, - settings = settings, - streamSettings = { - network = user.transport, - security = "none", - xtlsSettings = ("1" == user.tls and "1" == user.xtls) and { - alpn = { - "h2", - "http/1.1" - }, - disableSystemRoot = false, - certificates = { - { - certificateFile = user.tls_certificateFile, - keyFile = user.tls_keyFile - } - } - } or nil, - tlsSettings = ("1" == user.tls) and { - alpn = { - "h2", - "http/1.1" - }, - disableSystemRoot = false, - certificates = { - { - certificateFile = user.tls_certificateFile, - keyFile = user.tls_keyFile - } - } - } or nil, - tcpSettings = (user.transport == "tcp") and { - acceptProxyProtocol = (user.acceptProxyProtocol and user.acceptProxyProtocol == "1") and true or false, - header = { - type = user.tcp_guise, - request = (user.tcp_guise == "http") and { - path = user.tcp_guise_http_path or {"/"}, - headers = { - Host = user.tcp_guise_http_host or {} - } - } or nil - } - } or nil, - kcpSettings = (user.transport == "mkcp") and { - mtu = tonumber(user.mkcp_mtu), - tti = tonumber(user.mkcp_tti), - uplinkCapacity = tonumber(user.mkcp_uplinkCapacity), - downlinkCapacity = tonumber(user.mkcp_downlinkCapacity), - congestion = (user.mkcp_congestion == "1") and true or false, - readBufferSize = tonumber(user.mkcp_readBufferSize), - writeBufferSize = tonumber(user.mkcp_writeBufferSize), - seed = (user.mkcp_seed and user.mkcp_seed ~= "") and user.mkcp_seed or nil, - header = {type = user.mkcp_guise} - } or nil, - wsSettings = (user.transport == "ws") and { - acceptProxyProtocol = (user.acceptProxyProtocol and user.acceptProxyProtocol == "1") and true or false, - headers = (user.ws_host) and {Host = user.ws_host} or nil, - path = user.ws_path - } or nil, - httpSettings = (user.transport == "h2") and { - path = user.h2_path, host = user.h2_host - } or nil, - dsSettings = (user.transport == "ds") and { - path = user.ds_path - } or nil, - quicSettings = (user.transport == "quic") and { - security = user.quic_security, - key = user.quic_key, - header = {type = user.quic_guise} - } or nil, - grpcSettings = (user.transport == "grpc") and { - serviceName = user.grpc_serviceName - } or nil - } - } - }, - -- 传出连接 - outbounds = outbounds, - routing = routing - } - - if "1" == user.tls then - config.inbounds[1].streamSettings.security = "tls" - if user.xtls and user.xtls == "1" then - config.inbounds[1].streamSettings.security = "xtls" - config.inbounds[1].streamSettings.tlsSettings = nil - end - end - - return config -end diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/index.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/index.lua deleted file mode 100644 index 706a7d6419..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/index.lua +++ /dev/null @@ -1,74 +0,0 @@ -local api = require "luci.model.cbi.passwall.api.api" -local appname = api.appname - -m = Map("passwall_server", translate("Server-Side")) - -t = m:section(NamedSection, "global", "global") -t.anonymous = true -t.addremove = false - -e = t:option(Flag, "enable", translate("Enable")) -e.rmempty = false - -t = m:section(TypedSection, "user", translate("Users Manager")) -t.anonymous = true -t.addremove = true -t.sortable = true -t.template = "cbi/tblsection" -t.extedit = api.url("server_user", "%s") -function t.create(e, t) - local uuid = api.gen_uuid() - t = uuid - TypedSection.create(e, t) - luci.http.redirect(e.extedit:format(t)) -end -function t.remove(e, t) - e.map.proceed = true - e.map:del(t) - luci.http.redirect(api.url("server")) -end - -e = t:option(Flag, "enable", translate("Enable")) -e.width = "5%" -e.rmempty = false - -e = t:option(DummyValue, "status", translate("Status")) -e.rawhtml = true -e.cfgvalue = function(t, n) - return string.format('%s', translate("Collecting data...")) -end - -e = t:option(DummyValue, "remarks", translate("Remarks")) -e.width = "15%" - ----- Type -e = t:option(DummyValue, "type", translate("Type")) -e.cfgvalue = function(t, n) - local v = Value.cfgvalue(t, n) - if v then - if v == "Xray" then - local protocol = m:get(n, "protocol") - if protocol == "vmess" then - protocol = "VMess" - elseif protocol == "vless" then - protocol = "VLESS" - else - protocol = protocol:gsub("^%l",string.upper) - end - return v .. " -> " .. protocol - end - return v - end -end - -e = t:option(DummyValue, "port", translate("Port")) - -e = t:option(Flag, "log", translate("Log")) -e.default = "1" -e.rmempty = false - -m:append(Template("passwall/server/log")) - -m:append(Template("passwall/server/users_list_status")) -return m - diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/user.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/user.lua deleted file mode 100644 index 6e5cd098ab..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/user.lua +++ /dev/null @@ -1,611 +0,0 @@ -local api = require "luci.model.cbi.passwall.api.api" -local appname = api.appname - -local ss_encrypt_method_list = { - "rc4-md5", "aes-128-cfb", "aes-192-cfb", "aes-256-cfb", "aes-128-ctr", - "aes-192-ctr", "aes-256-ctr", "bf-cfb", "camellia-128-cfb", - "camellia-192-cfb", "camellia-256-cfb", "salsa20", "chacha20", - "chacha20-ietf", -- aead - "aes-128-gcm", "aes-192-gcm", "aes-256-gcm", "chacha20-ietf-poly1305", - "xchacha20-ietf-poly1305" -} - -local ssr_encrypt_method_list = { - "none", "table", "rc2-cfb", "rc4", "rc4-md5", "rc4-md5-6", "aes-128-cfb", - "aes-192-cfb", "aes-256-cfb", "aes-128-ctr", "aes-192-ctr", "aes-256-ctr", - "bf-cfb", "camellia-128-cfb", "camellia-192-cfb", "camellia-256-cfb", - "cast5-cfb", "des-cfb", "idea-cfb", "seed-cfb", "salsa20", "chacha20", - "chacha20-ietf" -} - -local ssr_protocol_list = { - "origin", "verify_simple", "verify_deflate", "verify_sha1", "auth_simple", - "auth_sha1", "auth_sha1_v2", "auth_sha1_v4", "auth_aes128_md5", - "auth_aes128_sha1", "auth_chain_a", "auth_chain_b", "auth_chain_c", - "auth_chain_d", "auth_chain_e", "auth_chain_f" -} -local ssr_obfs_list = { - "plain", "http_simple", "http_post", "random_head", "tls_simple", - "tls1.0_session_auth", "tls1.2_ticket_auth" -} - -local v_ss_encrypt_method_list = { - "aes-128-cfb", "aes-256-cfb", "aes-128-gcm", "aes-256-gcm", "chacha20", "chacha20-ietf", "chacha20-poly1305", "chacha20-ietf-poly1305" -} - -local header_type_list = { - "none", "srtp", "utp", "wechat-video", "dtls", "wireguard" -} - -local encrypt_methods_ss_aead = { - "dummy", - "aead_chacha20_poly1305", - "aead_aes_128_gcm", - "aead_aes_256_gcm", - "chacha20-ietf-poly1305", - "aes-128-gcm", - "aes-256-gcm", -} - -m = Map("passwall_server", translate("Server Config")) -m.redirect = api.url("server") - -s = m:section(NamedSection, arg[1], "user", "") -s.addremove = false -s.dynamic = false - -enable = s:option(Flag, "enable", translate("Enable")) -enable.default = "1" -enable.rmempty = false - -remarks = s:option(Value, "remarks", translate("Remarks")) -remarks.default = translate("Remarks") -remarks.rmempty = false - -type = s:option(ListValue, "type", translate("Type")) -if api.is_finded("microsocks") then - type:value("Socks", translate("Socks")) -end -if api.is_finded("ss-server") then - type:value("SS", translate("Shadowsocks")) -end -if api.is_finded("ssr-server") then - type:value("SSR", translate("ShadowsocksR")) -end -if api.is_finded("xray") then - type:value("Xray", translate("Xray")) -end -if api.is_finded("brook") then - type:value("Brook", translate("Brook")) -end ---[[ -if api.is_finded("trojan-plus") or api.is_finded("trojan") then - type:value("Trojan", translate("Trojan")) -end -]]-- -if api.is_finded("trojan-plus") then - type:value("Trojan-Plus", translate("Trojan-Plus")) -end -if api.is_finded("trojan-go") then - type:value("Trojan-Go", translate("Trojan-Go")) -end - -protocol = s:option(ListValue, "protocol", translate("Protocol")) -protocol:value("vmess", "Vmess") -protocol:value("vless", "VLESS") -protocol:value("http", "HTTP") -protocol:value("socks", "Socks") -protocol:value("shadowsocks", "Shadowsocks") -protocol:value("trojan", "Trojan") -protocol:value("mtproto", "MTProto") -protocol:depends("type", "Xray") - --- Brook协议 -brook_protocol = s:option(ListValue, "brook_protocol", translate("Protocol")) -brook_protocol:value("server", "Brook") -brook_protocol:value("wsserver", "WebSocket") -brook_protocol:depends("type", "Brook") -function brook_protocol.cfgvalue(self, section) - return m:get(section, "protocol") -end -function brook_protocol.write(self, section, value) - m:set(section, "protocol", value) -end - -brook_tls = s:option(Flag, "brook_tls", translate("Use TLS")) -brook_tls:depends("brook_protocol", "wsserver") - -port = s:option(Value, "port", translate("Port")) -port.datatype = "port" -port.rmempty = false - -auth = s:option(Flag, "auth", translate("Auth")) -auth.validate = function(self, value, t) - if value and value == "1" then - local user_v = username:formvalue(t) or "" - local pass_v = password:formvalue(t) or "" - if user_v == "" or pass_v == "" then - return nil, translate("Username and Password must be used together!") - end - end - return value -end -auth:depends("type", "Socks") -auth:depends({ type = "Xray", protocol = "socks" }) -auth:depends({ type = "Xray", protocol = "http" }) - -username = s:option(Value, "username", translate("Username")) -username:depends("auth", true) - -password = s:option(Value, "password", translate("Password")) -password.password = true -password:depends("auth", true) -password:depends("type", "SS") -password:depends("type", "SSR") -password:depends("type", "Brook") -password:depends({ type = "Xray", protocol = "shadowsocks" }) - -mtproto_password = s:option(Value, "mtproto_password", translate("Password"), translate("The MTProto protocol must be 32 characters and can only contain characters from 0 to 9 and a to f.")) -mtproto_password:depends({ type = "Xray", protocol = "mtproto" }) -mtproto_password.default = arg[1] -function mtproto_password.cfgvalue(self, section) - return m:get(section, "password") -end -function mtproto_password.write(self, section, value) - m:set(section, "password", value) -end - -decryption = s:option(Value, "decryption", translate("Encrypt Method")) -decryption.default = "none" -decryption:depends({ type = "Xray", protocol = "vless" }) - -ss_encrypt_method = s:option(ListValue, "ss_encrypt_method", translate("Encrypt Method")) -for a, t in ipairs(ss_encrypt_method_list) do ss_encrypt_method:value(t) end -ss_encrypt_method:depends("type", "SS") -function ss_encrypt_method.cfgvalue(self, section) - return m:get(section, "method") -end -function ss_encrypt_method.write(self, section, value) - m:set(section, "method", value) -end - -ssr_encrypt_method = s:option(ListValue, "ssr_encrypt_method", translate("Encrypt Method")) -for a, t in ipairs(ssr_encrypt_method_list) do ssr_encrypt_method:value(t) end -ssr_encrypt_method:depends("type", "SSR") -function ssr_encrypt_method.cfgvalue(self, section) - return m:get(section, "method") -end -function ssr_encrypt_method.write(self, section, value) - m:set(section, "method", value) -end - -v_ss_encrypt_method = s:option(ListValue, "v_ss_encrypt_method", translate("Encrypt Method")) -for a, t in ipairs(v_ss_encrypt_method_list) do v_ss_encrypt_method:value(t) end -v_ss_encrypt_method:depends({ type = "Xray", protocol = "shadowsocks" }) -function v_ss_encrypt_method.cfgvalue(self, section) - return m:get(section, "method") -end -function v_ss_encrypt_method.write(self, section, value) - m:set(section, "method", value) -end - -ss_network = s:option(ListValue, "ss_network", translate("Transport")) -ss_network.default = "tcp,udp" -ss_network:value("tcp", "TCP") -ss_network:value("udp", "UDP") -ss_network:value("tcp,udp", "TCP,UDP") -ss_network:depends({ type = "Xray", protocol = "shadowsocks" }) - -ssr_protocol = s:option(ListValue, "ssr_protocol", translate("Protocol")) -for a, t in ipairs(ssr_protocol_list) do ssr_protocol:value(t) end -ssr_protocol:depends("type", "SSR") -function ssr_protocol.cfgvalue(self, section) - return m:get(section, "protocol") -end -function ssr_protocol.write(self, section, value) - m:set(section, "protocol", value) -end - -protocol_param = s:option(Value, "protocol_param", translate("Protocol_param")) -protocol_param:depends("type", "SSR") - -obfs = s:option(ListValue, "obfs", translate("Obfs")) -for a, t in ipairs(ssr_obfs_list) do obfs:value(t) end -obfs:depends("type", "SSR") - -obfs_param = s:option(Value, "obfs_param", translate("Obfs_param")) -obfs_param:depends("type", "SSR") - -timeout = s:option(Value, "timeout", translate("Connection Timeout")) -timeout.datatype = "uinteger" -timeout.default = 300 -timeout:depends("type", "SS") -timeout:depends("type", "SSR") - -udp_forward = s:option(Flag, "udp_forward", translate("UDP Forward")) -udp_forward.default = "1" -udp_forward.rmempty = false -udp_forward:depends("type", "SSR") - -uuid = s:option(DynamicList, "uuid", translate("ID") .. "/" .. translate("Password")) -for i = 1, 3 do - uuid:value(api.gen_uuid(1)) -end -uuid:depends({ type = "Xray", protocol = "vmess" }) -uuid:depends({ type = "Xray", protocol = "vless" }) -uuid:depends({ type = "Xray", protocol = "trojan" }) -uuid:depends("type", "Trojan") -uuid:depends("type", "Trojan-Go") -uuid:depends("type", "Trojan-Plus") - -alter_id = s:option(Value, "alter_id", translate("Alter ID")) -alter_id:depends({ type = "Xray", protocol = "vmess" }) - -tls = s:option(Flag, "tls", translate("TLS")) -tls.default = 0 -tls.validate = function(self, value, t) - if value then - local type = type:formvalue(t) or "" - if value == "0" and (type == "Trojan" or type == "Trojan-Plus") then - return nil, translate("Original Trojan only supported 'tls', please choose 'tls'.") - end - if value == "1" then - local ca = tls_certificateFile:formvalue(t) or "" - local key = tls_keyFile:formvalue(t) or "" - if ca == "" or key == "" then - return nil, translate("Public key and Private key path can not be empty!") - end - end - return value - end -end -tls:depends({ type = "Xray", protocol = "vmess" }) -tls:depends({ type = "Xray", protocol = "vless" }) -tls:depends({ type = "Xray", protocol = "socks" }) -tls:depends({ type = "Xray", protocol = "shadowsocks" }) -tls:depends({ type = "Xray", protocol = "trojan" }) -tls:depends("type", "Trojan") -tls:depends("type", "Trojan-Plus") -tls:depends("type", "Trojan-Go") - -xtls = s:option(Flag, "xtls", translate("XTLS")) -xtls.default = 0 -xtls:depends({ type = "Xray", protocol = "vless", tls = true }) -xtls:depends({ type = "Xray", protocol = "trojan", tls = true }) - -flow = s:option(Value, "flow", translate("flow")) -flow.default = "xtls-rprx-direct" -flow:value("xtls-rprx-origin") -flow:value("xtls-rprx-origin-udp443") -flow:value("xtls-rprx-direct") -flow:value("xtls-rprx-direct-udp443") -flow:depends("xtls", true) - --- [[ TLS部分 ]] -- - -tls_allowInsecure = s:option(Flag, "tls_allowInsecure", translate("allowInsecure"), translate("Whether unsafe connections are allowed. When checked, Certificate validation will be skipped.")) -tls_allowInsecure.default = "0" -tls_allowInsecure:depends({ type = "Trojan", tls = true }) -tls_allowInsecure:depends({ type = "Trojan-Plus", tls = true }) -tls_allowInsecure:depends({ type = "Trojan-Go", tls = true }) - -tls_certificateFile = s:option(FileUpload, "tls_certificateFile", translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem") -tls_certificateFile.validate = function(self, value, t) - if value and value ~= "" then - if not nixio.fs.access(value) then - return nil, translate("Can't find this file!") - else - return value - end - end - return nil -end -tls_certificateFile.default = "/etc/config/ssl/" .. arg[1] .. ".pem" -tls_certificateFile:depends("tls", true) - -tls_keyFile = s:option(FileUpload, "tls_keyFile", translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key") -tls_keyFile.validate = function(self, value, t) - if value and value ~= "" then - if not nixio.fs.access(value) then - return nil, translate("Can't find this file!") - else - return value - end - end - return nil -end -tls_keyFile.default = "/etc/config/ssl/" .. arg[1] .. ".key" -tls_keyFile:depends("tls", true) - -tls_sessionTicket = s:option(Flag, "tls_sessionTicket", translate("Session Ticket")) -tls_sessionTicket.default = "0" -tls_sessionTicket:depends({ type = "Trojan", tls = true }) -tls_sessionTicket:depends({ type = "Trojan-Plus", tls = true }) -tls_sessionTicket:depends({ type = "Trojan-Go", tls = true }) - -transport = s:option(ListValue, "transport", translate("Transport")) -transport:value("tcp", "TCP") -transport:value("mkcp", "mKCP") -transport:value("ws", "WebSocket") -transport:value("h2", "HTTP/2") -transport:value("ds", "DomainSocket") -transport:value("quic", "QUIC") -transport:value("grpc", "gRPC") -transport:depends({ type = "Xray", protocol = "vmess" }) -transport:depends({ type = "Xray", protocol = "vless" }) -transport:depends({ type = "Xray", protocol = "socks" }) -transport:depends({ type = "Xray", protocol = "shadowsocks" }) -transport:depends({ type = "Xray", protocol = "trojan" }) - -trojan_transport = s:option(ListValue, "trojan_transport", translate("Transport")) -trojan_transport:value("original", "Original") -trojan_transport:value("ws", "WebSocket") -trojan_transport:value("h2", "HTTP/2") -trojan_transport:value("h2+ws", "HTTP/2 & WebSocket") -trojan_transport.default = "ws" -trojan_transport:depends("type", "Trojan-Go") - -trojan_plugin = s:option(ListValue, "plugin_type", translate("Plugin Type")) -trojan_plugin:value("plaintext", "Plain Text") -trojan_plugin:value("shadowsocks", "ShadowSocks") -trojan_plugin:value("other", "Other") -trojan_plugin.default = "plaintext" -trojan_plugin:depends({ tls = false, trojan_transport = "original" }) - -trojan_plugin_cmd = s:option(Value, "plugin_cmd", translate("Plugin Binary")) -trojan_plugin_cmd.placeholder = "eg: /usr/bin/v2ray-plugin" -trojan_plugin_cmd:depends({ plugin_type = "shadowsocks" }) -trojan_plugin_cmd:depends({ plugin_type = "other" }) - -trojan_plugin_op = s:option(Value, "plugin_option", translate("Plugin Option")) -trojan_plugin_op.placeholder = "eg: obfs=http;obfs-host=www.baidu.com" -trojan_plugin_op:depends({ plugin_type = "shadowsocks" }) -trojan_plugin_op:depends({ plugin_type = "other" }) - -trojan_plugin_arg = s:option(DynamicList, "plugin_arg", translate("Plugin Option Args")) -trojan_plugin_arg.placeholder = "eg: [\"-config\", \"test.json\"]" -trojan_plugin_arg:depends({ plugin_type = "shadowsocks" }) -trojan_plugin_arg:depends({ plugin_type = "other" }) - --- [[ WebSocket部分 ]]-- - -ws_host = s:option(Value, "ws_host", translate("WebSocket Host")) -ws_host:depends("transport", "ws") -ws_host:depends("ss_transport", "ws") -ws_host:depends("trojan_transport", "h2+ws") -ws_host:depends("trojan_transport", "ws") - -ws_path = s:option(Value, "ws_path", translate("WebSocket Path")) -ws_path:depends("transport", "ws") -ws_path:depends("ss_transport", "ws") -ws_path:depends("trojan_transport", "h2+ws") -ws_path:depends("trojan_transport", "ws") - --- [[ HTTP/2部分 ]]-- - -h2_host = s:option(Value, "h2_host", translate("HTTP/2 Host")) -h2_host:depends("transport", "h2") -h2_host:depends("ss_transport", "h2") -h2_host:depends("trojan_transport", "h2+ws") -h2_host:depends("trojan_transport", "h2") - -h2_path = s:option(Value, "h2_path", translate("HTTP/2 Path")) -h2_path:depends("transport", "h2") -h2_path:depends("ss_transport", "h2") -h2_path:depends("trojan_transport", "h2+ws") -h2_path:depends("trojan_transport", "h2") - --- [[ TCP部分 ]]-- - --- TCP伪装 -tcp_guise = s:option(ListValue, "tcp_guise", translate("Camouflage Type")) -tcp_guise:value("none", "none") -tcp_guise:value("http", "http") -tcp_guise:depends("transport", "tcp") - --- HTTP域名 -tcp_guise_http_host = s:option(DynamicList, "tcp_guise_http_host", translate("HTTP Host")) -tcp_guise_http_host:depends("tcp_guise", "http") - --- HTTP路径 -tcp_guise_http_path = s:option(DynamicList, "tcp_guise_http_path", translate("HTTP Path")) -tcp_guise_http_path:depends("tcp_guise", "http") - --- [[ mKCP部分 ]]-- - -mkcp_guise = s:option(ListValue, "mkcp_guise", translate("Camouflage Type"), translate('
none: default, no masquerade, data sent is packets with no characteristics.
srtp: disguised as an SRTP packet, it will be recognized as video call data (such as FaceTime).
utp: packets disguised as uTP will be recognized as bittorrent downloaded data.
wechat-video: packets disguised as WeChat video calls.
dtls: disguised as DTLS 1.2 packet.
wireguard: disguised as a WireGuard packet. (not really WireGuard protocol)')) -for a, t in ipairs(header_type_list) do mkcp_guise:value(t) end -mkcp_guise:depends("transport", "mkcp") - -mkcp_mtu = s:option(Value, "mkcp_mtu", translate("KCP MTU")) -mkcp_mtu.default = "1350" -mkcp_mtu:depends("transport", "mkcp") - -mkcp_tti = s:option(Value, "mkcp_tti", translate("KCP TTI")) -mkcp_tti.default = "20" -mkcp_tti:depends("transport", "mkcp") - -mkcp_uplinkCapacity = s:option(Value, "mkcp_uplinkCapacity", translate("KCP uplinkCapacity")) -mkcp_uplinkCapacity.default = "5" -mkcp_uplinkCapacity:depends("transport", "mkcp") - -mkcp_downlinkCapacity = s:option(Value, "mkcp_downlinkCapacity", translate("KCP downlinkCapacity")) -mkcp_downlinkCapacity.default = "20" -mkcp_downlinkCapacity:depends("transport", "mkcp") - -mkcp_congestion = s:option(Flag, "mkcp_congestion", translate("KCP Congestion")) -mkcp_congestion:depends("transport", "mkcp") - -mkcp_readBufferSize = s:option(Value, "mkcp_readBufferSize", translate("KCP readBufferSize")) -mkcp_readBufferSize.default = "1" -mkcp_readBufferSize:depends("transport", "mkcp") - -mkcp_writeBufferSize = s:option(Value, "mkcp_writeBufferSize", translate("KCP writeBufferSize")) -mkcp_writeBufferSize.default = "1" -mkcp_writeBufferSize:depends("transport", "mkcp") - -mkcp_seed = s:option(Value, "mkcp_seed", translate("KCP Seed")) -mkcp_seed:depends("transport", "mkcp") - --- [[ DomainSocket部分 ]]-- - -ds_path = s:option(Value, "ds_path", "Path", translate("A legal file path. This file must not exist before running.")) -ds_path:depends("transport", "ds") - --- [[ QUIC部分 ]]-- -quic_security = s:option(ListValue, "quic_security", translate("Encrypt Method")) -quic_security:value("none") -quic_security:value("aes-128-gcm") -quic_security:value("chacha20-poly1305") -quic_security:depends("transport", "quic") - -quic_key = s:option(Value, "quic_key", translate("Encrypt Method") .. translate("Key")) -quic_key:depends("transport", "quic") - -quic_guise = s:option(ListValue, "quic_guise", translate("Camouflage Type")) -for a, t in ipairs(header_type_list) do quic_guise:value(t) end -quic_guise:depends("transport", "quic") - --- [[ gRPC部分 ]]-- -grpc_serviceName = s:option(Value, "grpc_serviceName", "ServiceName") -grpc_serviceName:depends("transport", "grpc") - -acceptProxyProtocol = s:option(Flag, "acceptProxyProtocol", translate("acceptProxyProtocol"), translate("Whether to receive PROXY protocol, when this node want to be fallback or forwarded by proxy, it must be enable, otherwise it cannot be used.")) -acceptProxyProtocol:depends({ type = "Xray", transport = "tcp" }) -acceptProxyProtocol:depends({ type = "Xray", transport = "ws" }) - --- [[ Fallback部分 ]]-- -fallback = s:option(Flag, "fallback", translate("Fallback")) -fallback:depends({ type = "Xray", protocol = "vless", transport = "tcp" }) -fallback:depends({ type = "Xray", protocol = "trojan", transport = "tcp" }) - ---[[ -fallback_alpn = s:option(Value, "fallback_alpn", "Fallback alpn") -fallback_alpn:depends("fallback", true) - -fallback_path = s:option(Value, "fallback_path", "Fallback path") -fallback_path:depends("fallback", true) - -fallback_dest = s:option(Value, "fallback_dest", "Fallback dest") -fallback_dest:depends("fallback", true) - -fallback_xver = s:option(Value, "fallback_xver", "Fallback xver") -fallback_xver.default = 0 -fallback_xver:depends("fallback", true) -]]-- - -fallback_list = s:option(DynamicList, "fallback_list", "Fallback", translate("dest,path")) -fallback_list:depends("fallback", true) - -ss_aead = s:option(Flag, "ss_aead", translate("Shadowsocks2")) -ss_aead:depends("type", "Trojan-Go") -ss_aead.default = "0" - -ss_aead_method = s:option(ListValue, "ss_aead_method", translate("Encrypt Method")) -for _, v in ipairs(encrypt_methods_ss_aead) do ss_aead_method:value(v, v) end -ss_aead_method.default = "aead_aes_128_gcm" -ss_aead_method:depends("ss_aead", true) - -ss_aead_pwd = s:option(Value, "ss_aead_pwd", translate("Password")) -ss_aead_pwd.password = true -ss_aead_pwd:depends("ss_aead", true) - -tcp_fast_open = s:option(Flag, "tcp_fast_open", translate("TCP Fast Open")) -tcp_fast_open.default = "0" -tcp_fast_open:depends("type", "SS") -tcp_fast_open:depends("type", "SSR") -tcp_fast_open:depends("type", "Trojan") -tcp_fast_open:depends("type", "Trojan-Plus") -tcp_fast_open:depends("type", "Trojan-Go") - -remote_enable = s:option(Flag, "remote_enable", translate("Enable Remote"), translate("You can forward to Nginx/Caddy/Xray/V2ray WebSocket and more.")) -remote_enable.default = "1" -remote_enable.rmempty = false -remote_enable:depends("type", "Trojan") -remote_enable:depends("type", "Trojan-Plus") -remote_enable:depends("type", "Trojan-Go") - -remote_address = s:option(Value, "remote_address", translate("Remote Address")) -remote_address.default = "127.0.0.1" -remote_address:depends("remote_enable", 1) - -remote_port = s:option(Value, "remote_port", translate("Remote Port")) -remote_port.datatype = "port" -remote_port.default = "80" -remote_port:depends("remote_enable", 1) - -bind_local = s:option(Flag, "bind_local", translate("Bind Local"), translate("When selected, it can only be accessed locally, It is recommended to turn on when using reverse proxies or be fallback.")) -bind_local.default = "0" -bind_local:depends("type", "Xray") - -accept_lan = s:option(Flag, "accept_lan", translate("Accept LAN Access"), translate("When selected, it can accessed lan , this will not be safe!")) -accept_lan.default = "0" -accept_lan.rmempty = false -accept_lan:depends("type", "Xray") - -local nodes_table = {} -for k, e in ipairs(api.get_valid_nodes()) do - if e.node_type == "normal" and e.type == "Xray" then - nodes_table[#nodes_table + 1] = { - id = e[".name"], - remarks = e["remark"] - } - end -end - -transit_node = s:option(ListValue, "transit_node", translate("transit node")) -transit_node:value("nil", translate("Close")) -transit_node:value("_socks", translate("Custom Socks")) -transit_node:value("_http", translate("Custom HTTP")) -for k, v in pairs(nodes_table) do transit_node:value(v.id, v.remarks) end -transit_node.default = "nil" -transit_node:depends("type", "Xray") - -transit_node_address = s:option(Value, "transit_node_address", translate("Address (Support Domain Name)")) -transit_node_address:depends("transit_node", "_socks") -transit_node_address:depends("transit_node", "_http") - -transit_node_port = s:option(Value, "transit_node_port", translate("Port")) -transit_node_port.datatype = "port" -transit_node_port:depends("transit_node", "_socks") -transit_node_port:depends("transit_node", "_http") - -transit_node_username = s:option(Value, "transit_node_username", translate("Username")) -transit_node_username:depends("transit_node", "_socks") -transit_node_username:depends("transit_node", "_http") - -transit_node_password = s:option(Value, "transit_node_password", translate("Password")) -transit_node_password.password = true -transit_node_password:depends("transit_node", "_socks") -transit_node_password:depends("transit_node", "_http") - -log = s:option(Flag, "log", translate("Log")) -log.default = "1" -log.rmempty = false - -loglevel = s:option(ListValue, "loglevel", translate("Log Level")) -loglevel.default = "warning" -loglevel:value("debug") -loglevel:value("info") -loglevel:value("warning") -loglevel:value("error") -loglevel:depends({ type = "Xray", log = true }) - -trojan_loglevel = s:option(ListValue, "trojan_loglevel", translate("Log Level")) -trojan_loglevel.default = "2" -trojan_loglevel:value("0", "all") -trojan_loglevel:value("1", "info") -trojan_loglevel:value("2", "warn") -trojan_loglevel:value("3", "error") -trojan_loglevel:value("4", "fatal") -function trojan_loglevel.cfgvalue(self, section) - return m:get(section, "loglevel") -end -function trojan_loglevel.write(self, section, value) - m:set(section, "loglevel", value) -end -trojan_loglevel:depends({ type = "Trojan", log = true }) -trojan_loglevel:depends({ type = "Trojan-Plus", log = true }) -trojan_loglevel:depends({ type = "Trojan-Go", log = true }) - -return m diff --git a/package/lienol/luci-app-passwall/luasrc/view/passwall/app_update/brook_version.htm b/package/lienol/luci-app-passwall/luasrc/view/passwall/app_update/brook_version.htm deleted file mode 100644 index 9783e9b02c..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/view/passwall/app_update/brook_version.htm +++ /dev/null @@ -1,157 +0,0 @@ -<% -local api = require "luci.model.cbi.passwall.api.api" -local brook_version = api.get_brook_version() --%> - - - -
- -
-
- 【 <%=brook_version%> 】 - - -
-
-
\ No newline at end of file diff --git a/package/lienol/luci-app-passwall/luasrc/view/passwall/app_update/kcptun_version.htm b/package/lienol/luci-app-passwall/luasrc/view/passwall/app_update/kcptun_version.htm deleted file mode 100644 index af88ddb8fd..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/view/passwall/app_update/kcptun_version.htm +++ /dev/null @@ -1,173 +0,0 @@ -<% -local api = require "luci.model.cbi.passwall.api.api" -local kcptun_version = api.get_kcptun_version() --%> - - - -
- -
-
- 【 <%=kcptun_version%> 】 - - -
-
-
\ No newline at end of file diff --git a/package/lienol/luci-app-passwall/luasrc/view/passwall/app_update/trojan_go_version.htm b/package/lienol/luci-app-passwall/luasrc/view/passwall/app_update/trojan_go_version.htm deleted file mode 100644 index 8e90703991..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/view/passwall/app_update/trojan_go_version.htm +++ /dev/null @@ -1,173 +0,0 @@ -<% -local api = require "luci.model.cbi.passwall.api.api" -local trojan_go_version = api.get_trojan_go_version() --%> - - - -
- -
-
- 【 <%=trojan_go_version%> 】 - - -
-
-
\ No newline at end of file diff --git a/package/lienol/luci-app-passwall/luasrc/view/passwall/app_update/xray_version.htm b/package/lienol/luci-app-passwall/luasrc/view/passwall/app_update/xray_version.htm deleted file mode 100644 index c9164003c9..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/view/passwall/app_update/xray_version.htm +++ /dev/null @@ -1,173 +0,0 @@ -<% -local api = require "luci.model.cbi.passwall.api.api" -local xray_version = api.get_xray_version() --%> - - - -
- -
-
- 【 <%=xray_version%> 】 - - -
-
-
\ No newline at end of file diff --git a/package/lienol/luci-app-passwall/luasrc/view/passwall/global/footer.htm b/package/lienol/luci-app-passwall/luasrc/view/passwall/global/footer.htm deleted file mode 100644 index f532e88ef9..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/view/passwall/global/footer.htm +++ /dev/null @@ -1,147 +0,0 @@ -<% -local api = require "luci.model.cbi.passwall.api.api" -local auto_switch = api.uci_get_type("auto_switch", "enable", 0) --%> - \ No newline at end of file diff --git a/package/lienol/luci-app-passwall/luasrc/view/passwall/global/status.htm b/package/lienol/luci-app-passwall/luasrc/view/passwall/global/status.htm deleted file mode 100644 index 5c6d4287f7..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/view/passwall/global/status.htm +++ /dev/null @@ -1,357 +0,0 @@ -<% -local api = require "luci.model.cbi.passwall.api.api" -local status = api.uci_get_type("global_other", "status", "") --%> - - - -
- - <%:Running Status%> - -
-
-
-
-
- -
-
-
-

TCP
<%:NOT RUNNING%>

-
-
-
-
-
-
-
- -
-
-
-

UDP
<%:NOT RUNNING%>

-
-
-
-
-
-
-
- -
-
-
-

DNS
<%:NOT RUNNING%>

-
-
-
-
-
-
-
- -
-
-
-

<%:Load Balancing%>
<%:NOT RUNNING%>

-
-
-
-
-
-
-
- -
-
-
-

Kcptun
<%:NOT RUNNING%>

-
-
-
-
-
-
-
- -
-
-
-

<%:Baidu Connection%>
<%:Touch Check%>

-
-
-
-
-
-
-
- -
-
-
-

<%:Google Connection%>
<%:Touch Check%>

-
-
-
-
-
-
-
- -
-
-
-

<%:GitHub Connection%>
<%:Touch Check%>

-
-
-
- <% if status:find("show_check_port") then %> -
-
-
-
- -
-
-
-

<%:Node Check%>
<%:Touch Check%>

- -
-
-
- <% end %> - <% if status:find("show_ip111") then %> -
-
-
-
- -
-
-
-

IP111.cn
<%:Touch Check%>

-
-
-
- <% end %> -
- -
diff --git a/package/lienol/luci-app-passwall/luasrc/view/passwall/global/status2.htm b/package/lienol/luci-app-passwall/luasrc/view/passwall/global/status2.htm deleted file mode 100644 index c7bc3c8e27..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/view/passwall/global/status2.htm +++ /dev/null @@ -1,262 +0,0 @@ -<% -local api = require "luci.model.cbi.passwall.api.api" -local status = api.uci_get_type("global_other", "status", "") --%> - - - -
- - <%:Running Status%> - -
-
- -
- <%:Collecting data...%> -
-
- -
- -
- <%:Collecting data...%> -
-
- - <% if api.is_finded("kcptun-client") then %> -
- -
- <%:Collecting data...%> -
-
- <% end %> - - <% if api.is_finded("haproxy") then %> -
- -
- <%:Collecting data...%> -
-
- <% end %> - -
- -
- <%:Collecting data...%> -
-
- -
- -
- - -
-
-
- -
- - -
-
-
- -
- - -
-
- <% if status:find("show_check_port") then %> -
- -
- - - -
-
- <% end %> - <% if status:find("show_ip111") then %> -
- -
- -
-
- <% end %> -
-
- - diff --git a/package/lienol/luci-app-passwall/luasrc/view/passwall/global/tips.htm b/package/lienol/luci-app-passwall/luasrc/view/passwall/global/tips.htm deleted file mode 100644 index b5a45a4b70..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/view/passwall/global/tips.htm +++ /dev/null @@ -1,15 +0,0 @@ -<% -local api = require "luci.model.cbi.passwall.api.api" --%> -
- -
- <%:You can use load balancing for failover.%> -
- <%:Restore the default configuration method. Input example in the address bar:%> http://192.168.1.1<%=api.url("reset_config")%> -
- <%:Hide menu method, input example in the address bar:%> http://192.168.1.1<%=api.url("hide")%> -
- <%:After the hidden to the display, input example in the address bar:%> http://192.168.1.1<%=api.url("show")%> -
-
diff --git a/package/lienol/luci-app-passwall/luasrc/view/passwall/haproxy/status.htm b/package/lienol/luci-app-passwall/luasrc/view/passwall/haproxy/status.htm deleted file mode 100644 index 25567a7e1f..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/view/passwall/haproxy/status.htm +++ /dev/null @@ -1,24 +0,0 @@ -<% -local api = require "luci.model.cbi.passwall.api.api" -local console_port = api.uci_get_type("global_haproxy", "console_port", "") --%> -

- - \ No newline at end of file diff --git a/package/lienol/luci-app-passwall/luasrc/view/passwall/log/log.htm b/package/lienol/luci-app-passwall/luasrc/view/passwall/log/log.htm deleted file mode 100644 index 75e5783170..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/view/passwall/log/log.htm +++ /dev/null @@ -1,30 +0,0 @@ -<% -local api = require "luci.model.cbi.passwall.api.api" --%> - -
- - -
diff --git a/package/lienol/luci-app-passwall/luasrc/view/passwall/node_list/link_add_node.htm b/package/lienol/luci-app-passwall/luasrc/view/passwall/node_list/link_add_node.htm deleted file mode 100644 index 4728ceea4d..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/view/passwall/node_list/link_add_node.htm +++ /dev/null @@ -1,105 +0,0 @@ -<% -local api = require "luci.model.cbi.passwall.api.api" --%> - - - - - - - -
- -
- - - - - - -
-
\ No newline at end of file diff --git a/package/lienol/luci-app-passwall/luasrc/view/passwall/node_list/link_share_man.htm b/package/lienol/luci-app-passwall/luasrc/view/passwall/node_list/link_share_man.htm deleted file mode 100644 index def9ca590f..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/view/passwall/node_list/link_share_man.htm +++ /dev/null @@ -1,787 +0,0 @@ -<%+cbi/valueheader%> -<% -local api = require "luci.model.cbi.passwall.api.api" --%> - - - - -<%+cbi/valuefooter%> diff --git a/package/lienol/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm b/package/lienol/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm deleted file mode 100644 index f3b23e021c..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm +++ /dev/null @@ -1,413 +0,0 @@ -<% --- Copyright (C) 2018-2020 L-WRT Team --- Copyright (C) 2021 xiaorouji -local api = require "luci.model.cbi.passwall.api.api" --%> - - - - - -
-
-
<%:You choose node is:%>
-
- - - -
-
-
\ No newline at end of file diff --git a/package/lienol/luci-app-passwall/luasrc/view/passwall/rule/rule_version.htm b/package/lienol/luci-app-passwall/luasrc/view/passwall/rule/rule_version.htm deleted file mode 100644 index f6cea0bfdd..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/view/passwall/rule/rule_version.htm +++ /dev/null @@ -1,80 +0,0 @@ -<% -local api = require "luci.model.cbi.passwall.api.api" - -local gfwlist_update = api.uci_get_type("global_rules", "gfwlist_update", "1") == "1" and "checked='checked'" or "" -local chnroute_update = api.uci_get_type("global_rules", "chnroute_update", "1") == "1" and "checked='checked'" or "" -local chnroute6_update = api.uci_get_type("global_rules", "chnroute6_update", "1") == "1" and "checked='checked'" or "" -local chnlist_update = api.uci_get_type("global_rules", "chnlist_update", "1") == "1" and "checked='checked'" or "" -local geoip_update = api.uci_get_type("global_rules", "geoip_update", "1") == "1" and "checked='checked'" or "" -local geosite_update = api.uci_get_type("global_rules", "geosite_update", "1") == "1" and "checked='checked'" or "" --%> - - -
-
-
- -
-
- - - - - - - -
-
-
-
-
diff --git a/package/lienol/luci-app-passwall/luasrc/view/passwall/server/log.htm b/package/lienol/luci-app-passwall/luasrc/view/passwall/server/log.htm deleted file mode 100644 index 309c85a318..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/view/passwall/server/log.htm +++ /dev/null @@ -1,34 +0,0 @@ -<% -local api = require "luci.model.cbi.passwall.api.api" --%> - -
- - <%:Logs%> - - - -
\ No newline at end of file diff --git a/package/lienol/luci-app-passwall/luasrc/view/passwall/server/users_list_status.htm b/package/lienol/luci-app-passwall/luasrc/view/passwall/server/users_list_status.htm deleted file mode 100644 index cd0d9f7bdf..0000000000 --- a/package/lienol/luci-app-passwall/luasrc/view/passwall/server/users_list_status.htm +++ /dev/null @@ -1,38 +0,0 @@ -<% -local api = require "luci.model.cbi.passwall.api.api" --%> - \ No newline at end of file diff --git a/package/lienol/luci-app-passwall/po/zh-cn/passwall.po b/package/lienol/luci-app-passwall/po/zh-cn/passwall.po deleted file mode 100644 index e5e0c9298c..0000000000 --- a/package/lienol/luci-app-passwall/po/zh-cn/passwall.po +++ /dev/null @@ -1,1229 +0,0 @@ -msgid "Pass Wall" -msgstr "PassWall" - -msgid "Auto" -msgstr "自动" - -msgid "RUNNING" -msgstr "运行中" - -msgid "NOT RUNNING" -msgstr "未运行" - -msgid "Working..." -msgstr "连接正常" - -msgid "Problem detected!" -msgstr "连接失败" - -msgid "Very Fast" -msgstr "非常快" - -msgid "Fast" -msgstr "很快" - -msgid "General" -msgstr "一般般" - -msgid "Slow" -msgstr "很慢" - -msgid "Very Slow" -msgstr "非常慢" - -msgid "Touch Check" -msgstr "点我检测" - -msgid "Kernel Unsupported" -msgstr "内核不支持" - -msgid "Use IPv6" -msgstr "使用IPv6" - -msgid "Parsing IP" -msgstr "域名解析IP" - -msgid "TCP Server" -msgstr "TCP服务器" - -msgid "UDP Server" -msgstr "UDP服务器" - -msgid "Main Settings" -msgstr "节点选择" - -msgid "Basic Settings" -msgstr "基本设置" - -msgid "Node List" -msgstr "节点列表" - -msgid "Other Settings" -msgstr "高级设置" - -msgid "Load Balancing" -msgstr "负载均衡" - -msgid "Enter interface" -msgstr "进入界面" - -msgid "Rule Manage" -msgstr "规则管理" - -msgid "Rule List Manage" -msgstr "直连/代理名单管理" - -msgid "Access control" -msgstr "访问控制" - -msgid "Watch Logs" -msgstr "查看日志" - -msgid "Node Config" -msgstr "节点配置" - -msgid "Running Status" -msgstr "运行状态" - -msgid "Baidu Connection" -msgstr "百度连接" - -msgid "Google Connection" -msgstr "谷歌连接" - -msgid "GitHub Connection" -msgstr "GitHub连接" - -msgid "Node Check" -msgstr "节点检测" - -msgid "Check..." -msgstr "检测中..." - -msgid "Clear" -msgstr "清除" - -msgid "Main switch" -msgstr "主开关" - -msgid "TCP Node" -msgstr "TCP节点" - -msgid "UDP Node" -msgstr "UDP节点" - -msgid "Edit Current Node" -msgstr "编辑当前节点" - -msgid "Socks Config" -msgstr "Socks配置" - -msgid "Socks Node" -msgstr "Socks节点" - -msgid "Listen Port" -msgstr "监听端口" - -msgid "0 is not use" -msgstr "0为不使用" - -msgid "Same as the tcp node" -msgstr "与TCP节点相同" - -msgid "New process" -msgstr "另开进程" - -msgid "Current node: %s" -msgstr "当前节点:%s" - -msgid "For proxy specific list." -msgstr "用于代理特定的列表。" - -msgid "For proxy game network, DNS hijack etc." -msgstr "用于代理游戏或DNS劫持等..." - -msgid "The selected server will not use Kcptun." -msgstr "选中的服务器不会使用Kcptun。" - -msgid "The client can use the router's Socks Servie." -msgstr "客户端可以使用路由器的 Socks 服务。" - -msgid "Filter Mode" -msgstr "过滤模式" - -msgid "No Filter" -msgstr "不过滤" - -msgid "Custom DNS" -msgstr "自定义DNS" - -msgid "IP:Port mode ecceptable for specify other filtered name services." -msgstr "定义接受 IP:Port 形式的输入,以指定其它域名服务的过滤服务。" - -msgid "Local DNS" -msgstr "本地DNS" - -msgid "Remote DNS" -msgstr "远程DNS" - -msgid "IP:Port mode acceptable, multi value split with english comma." -msgstr "接受 IP:Port 形式的输入,多个以英文逗号分隔。" - -msgid "If you use dns2socks, only the first one is valid." -msgstr "如果使用dns2socks,只有第一个生效。" - -msgid "When the selection is not the default, this DNS is forced to be set to dnsmasq upstream DNS." -msgstr "当选择的不是默认,则将此DNS强制设置为dnsmasq上游DNS。" - -msgid "When custom, Please follow the format strictly:" -msgstr "当自定义时,请严格遵循以下格式:" - -msgid "Use ChinaDNS-NG" -msgstr "使用ChinaDNS-NG" - -msgid "When checked, forced to be set to dnsmasq upstream DNS." -msgstr "当勾选,则将强制设置为dnsmasq上游DNS。" - -msgid "Use ChinaList" -msgstr "使用chnlist" - -msgid "Only useful in non-gfwlist mode." -msgstr "仅可用于非防火墙表。" - -msgid "When used, the domestic DNS will be used only when the chnlist rule is hit, and the domain name that misses the rule will be resolved by remote DNS." -msgstr "当使用时,只有当命中chnlist规则时,才会使用国内DNS,未命中规则的域名将会使用远程DNS解析。" - -msgid "Ali" -msgstr "阿里" - -msgid "Baidu" -msgstr "百度" - -msgid "Resolver For The List Proxied" -msgstr "解析被代理的域名列表" - -msgid "Requery DNS By %s" -msgstr "通过%s请求DNS" - -msgid "Forward To Socks Server" -msgstr "转发至 Socks 服务器" - -msgid "Socks Server" -msgstr "Socks服务器" - -msgid "Misconfigured" -msgstr "配置不当" - -msgid "Make sure socks service is available on this address." -msgstr "请确保此Socks服务可用。" - -msgid "ChinaDNS-NG Fair Mode" -msgstr "ChinaDNS-NG 公平模式" - -msgid "Format must be:" -msgstr "格式必须为:" - -msgid "DoH request address" -msgstr "DoH 请求地址" - -msgid "DoH bootstrap DNS" -msgstr "DoH Bootstrap DNS" - -msgid "The Bootstrap DNS server is used to resolve the IP address of the DoH resolver you specify as the upstream." -msgstr "Bootstrap DNS 服务器用于解析您指定为上游的 DoH 解析器的 IP 地址。" - -msgid "China list or gfwlist cannot be used together with outside China list!" -msgstr "中国列表不能和中国列表外或防火墙表一起使用!" - -msgid "Cache Resolved" -msgstr "缓存解析结果" - -msgid "Dnsmasq default dns" -msgstr "Dnsmasq的默认DNS" - -msgid "When the accessed domain name does not exist in the rule list, the default DNS used." -msgstr "当访问的域名不存在规则列表中,使用的默认DNS。" - -msgid "Clear IPSET" -msgstr "清空 IPSET" - -msgid "Try this feature if the rule modification does not take effect." -msgstr "如果修改规则后没有生效,请尝试此功能。" - -msgid "The server client can also use this rule to scientifically surf the Internet." -msgstr "本机服务器的客户端也可以使用这个代理模式上网。" - -msgid "Tips" -msgstr "小提示" - -msgid "You can use load balancing for failover." -msgstr "可以使用负载均衡实现故障切换功能。" - -msgid "Restore the default configuration method. Input example in the address bar:" -msgstr "恢复默认配置方法,地址栏输入例:" - -msgid "DNS Export Of Multi WAN" -msgstr "国内DNS指定解析出口" - -msgid "Node Export Of Multi WAN" -msgstr "节点指定出口" - -msgid "Only support Multi Wan." -msgstr "只有多线接入才有效。" - -msgid "Not Specify" -msgstr "不指定" - -msgid "custom" -msgstr "自定义" - -msgid "Multi Process Option" -msgstr "多进程并发" - -msgid "you can start SS/SSR with multiple process" -msgstr "当使用SS/SSR时可使用多进程并发" - -msgid "Process" -msgstr "进程" - -msgid "1 Process" -msgstr "单进程" - -msgid "Proxy Mode" -msgstr "代理模式" - -msgid "%s Proxy Mode" -msgstr "%s 代理模式" - -msgid "If not available, try clearing the cache." -msgstr "如果无法使用,请尝试清除缓存。" - -msgid "No Proxy" -msgstr "不代理" - -msgid "Global Proxy" -msgstr "全局代理" - -msgid "GFW List" -msgstr "防火墙表" - -msgid "Not China List" -msgstr "中国列表以外" - -msgid "Game Mode" -msgstr "游戏模式" - -msgid "China List" -msgstr "中国列表" - -msgid "Localhost" -msgstr "本机" - -msgid "Router Localhost" -msgstr "路由器自身" - -msgid "Danger" -msgstr "危险" - -msgid "Operation" -msgstr "操作" - -msgid "Add Node" -msgstr "添加节点" - -msgid "Add the node via the link" -msgstr "通过链接添加节点" - -msgid "SS/SSR/Vmess/VLESS/Trojan Link" -msgstr "SS/SSR/Vmess/VLESS/Trojan链接" - -msgid "Please enter the correct link, ss:// ssr:// vmess:// vless:// trojan://" -msgstr "请输入正确的链接,ss:// ssr:// vmess:// vless:// trojan://" - -msgid "Clear all nodes" -msgstr "清空所有节点" - -msgid "Are you sure to clear all nodes?" -msgstr "你确定要清空所有节点吗?" - -msgid "Error" -msgstr "错误" - -msgid "Delete select nodes" -msgstr "删除选择的节点" - -msgid "To Top" -msgstr "置顶" - -msgid "Select" -msgstr "选择" - -msgid "DeSelect" -msgstr "反选" - -msgid "Select all" -msgstr "全选" - -msgid "DeSelect all" -msgstr "全不选" - -msgid "Are you sure to delete select nodes?" -msgstr "你确定要删除选择的节点吗?" - -msgid "You no select nodes !" -msgstr "你没有选择任何节点!" - -msgid "Are you sure set to" -msgstr "你确定要设为" - -msgid "the server?" -msgstr "服务器吗?" - -msgid "You choose node is:" -msgstr "你选择的节点是:" - -msgid "Timeout" -msgstr "超时" - -msgid "Node Remarks" -msgstr "节点备注" - -msgid "Add Mode" -msgstr "添加方式" - -msgid "Type" -msgstr "类型" - -msgid "Balancing" -msgstr "负载均衡" - -msgid "Xray_balancing" -msgstr "Xray 负载均衡" - -msgid "V2ray_balancing" -msgstr "V2ray 负载均衡" - -msgid "Shunt" -msgstr "分流" - -msgid "Xray_shunt" -msgstr "Xray 分流" - -msgid "V2ray_shunt" -msgstr "V2ray 分流" - -msgid "Preproxy" -msgstr "前置代理" - -msgid "Direct Connection" -msgstr "直连" - -msgid "Blackhole" -msgstr "黑洞" - -msgid "Use the default node for the transit." -msgstr "使用默认节点代理转发。" - -msgid "No shunt rules? Click me to go to add." -msgstr "没有分流规则?点我前往去添加。" - -msgid "Use this node proxy to forward the default node." -msgstr "使用此节点代理转发默认节点。" - -msgid "Domain Strategy" -msgstr "域名解析策略" - -msgid "'AsIs': Only use domain for routing. Default value." -msgstr "AsIs:只使用域名进行路由选择。默认值。" - -msgid "'IPIfNonMatch': When no rule matches current domain, resolves it into IP addresses (A or AAAA records) and try all rules again." -msgstr "IPIfNonMatch:当域名没有匹配任何规则时,将域名解析成 IP(A 记录或 AAAA 记录)再次进行匹配。" - -msgid "'IPOnDemand': As long as there is a IP-based rule, resolves the domain into IP immediately." -msgstr "IPOnDemand:当匹配时碰到任何基于 IP 的规则,将域名立即解析为 IP 进行匹配。" - -msgid "Load balancing node list" -msgstr "负载均衡节点列表" - -msgid "Load balancing node list, document" -msgstr "负载均衡节点列表,文档原理" - -msgid "From Share URL" -msgstr "导入分享URL" - -msgid "Build Share URL" -msgstr "导出分享URL" - -msgid "Import Finished" -msgstr "导入完成:" - -msgid "Not a supported scheme:" -msgstr "不支持这种样式的:" - -msgid "Invalid Share URL Format" -msgstr "无效的分享URL信息" - -msgid "Paste Share URL Here" -msgstr "在此处粘贴分享信息" - -msgid "Share URL to clipboard unable." -msgstr "无法分享URL到剪贴板。" - -msgid "Share URL to clipboard successfully." -msgstr "成功复制分享URL到剪贴板。" - -msgid "Faltal on get option, please help in debug:" -msgstr "代码错误,请协助捉虫:" - -msgid "Faltal on set option, please help in debug:" -msgstr "代码错误,请协助捉虫:" - -msgid "Address" -msgstr "地址" - -msgid "Address (Support Domain Name)" -msgstr "地址(支持域名)" - -msgid "Trojan Verify Cert" -msgstr "验证证书" - -msgid "Trojan Cert Path" -msgstr "证书路径" - -msgid "Finger Print" -msgstr "指纹伪造" - -msgid "Shadowsocks2" -msgstr "二次加密" - -msgid "Encrypt Method" -msgstr "加密" - -msgid "Kcptun Switch" -msgstr "Kcptun开关" - -msgid "Latency" -msgstr "延迟" - -msgid "Show Add Mode" -msgstr "显示添加方式" - -msgid "Show Group" -msgstr "显示组" - -msgid "Group" -msgstr "组" - -msgid "Auto Ping" -msgstr "自动Ping" - -msgid "This will automatically ping the node for latency" -msgstr "选中后保存应用后即自动Ping节点" - -msgid "Use TCP Detection delay" -msgstr "使用TCP检测延迟" - -msgid "This will use tcping replace ping detection of node" -msgstr "选中后保存应用后即使用tcping替换ping检测节点" - -msgid "Concise display nodes" -msgstr "简洁显示节点" - -msgid "Show server address and port" -msgstr "显示服务器地址和端口" - -msgid "Apply" -msgstr "应用" - -msgid "Use" -msgstr "使用" - -msgid "Copy" -msgstr "复制" - -msgid "Delay Settings" -msgstr "定时配置" - -msgid "Open and close Daemon" -msgstr "启动守护进程" - -msgid "Delay Start" -msgstr "开机时延时启动" - -msgid "Units:seconds" -msgstr "单位:秒" - -msgid "Units:minutes" -msgstr "单位:分钟" - -msgid "Open and close automatically" -msgstr "定时自动开关" - -msgid "Automatically turn off time" -msgstr "自动关闭时间" - -msgid "Automatically turn on time" -msgstr "自动开启时间" - -msgid "Automatically restart time" -msgstr "自动重启时间" - -msgid "Forwarding Settings" -msgstr "转发配置" - -msgid "TCP No Redir Ports" -msgstr "TCP不转发端口" - -msgid "UDP No Redir Ports" -msgstr "UDP不转发端口" - -msgid "Fill in the ports you don't want to be forwarded by the agent, with the highest priority." -msgstr "填写你不希望被代理转发的端口,优先级最高。" - -msgid "TCP Redir Ports" -msgstr "TCP转发端口" - -msgid "UDP Redir Ports" -msgstr "UDP转发端口" - -msgid "No patterns are used" -msgstr "不使用" - -msgid "All" -msgstr "所有" - -msgid "Common Use" -msgstr "常用的" - -msgid "Only Web" -msgstr "仅网页" - -msgid "or more" -msgstr "及以上" - -msgid "or less" -msgstr "及以下" - -msgid "Default" -msgstr "默认" - -msgid "Close" -msgstr "关闭" - -msgid "Proxy Settings" -msgstr "代理配置" - -msgid "TCP Redir Port" -msgstr "TCP透明代理端口" - -msgid "UDP Redir Port" -msgstr "UDP透明代理端口" - -msgid "Socks Proxy Port" -msgstr "Socks代理端口" - -msgid "Kcptun Port" -msgstr "Kcptun端口" - -msgid "Custom Dnsmasq" -msgstr "自定义Dnsmasq设置" - -msgid "Setting a parameter error will cause dnsmasq fail to start." -msgstr "参数设置错误将会导致Dnsmasq无法启动。" - -msgid "Auto Switch" -msgstr "自动切换" - -msgid "When there is no server, an automatic reconnect scheme is used" -msgstr "当没有服务器时,则使用自动重连方案" - -msgid "How often is a diagnosis made" -msgstr "检测时间" - -msgid "Automatic switching cannot be used when this option is checked" -msgstr "当勾选此选项时,不能使用自动切换" - -msgid "Main node" -msgstr "主节点" - -msgid "List of backup nodes" -msgstr "备用节点的列表" - -msgid "Restore Switch" -msgstr "恢复切换" - -msgid "When detects main node is available, switch back to the main node." -msgstr "当检测到主节点可用时,切换回主节点。" - -msgid "Configure this node with 127.0.0.1: this port" -msgstr "使用127.0.0.1和此端口配置节点" - -msgid "Enable Load Balancing" -msgstr "开启负载均衡" - -msgid "Console Username" -msgstr "控制台账号" - -msgid "Console Password" -msgstr "控制台密码" - -msgid "Console Port" -msgstr "控制台端口" - -msgid "In the browser input routing IP plus port access, such as:192.168.1.1:1188" -msgstr "在浏览器输入路由IP加端口访问,如:192.168.1.1:1188" - -msgid "Haproxy Port" -msgstr "负载均衡端口" - -msgid "Add a node, Export Of Multi WAN Only support Multi Wan. Load specific gravity range 1-256. Multiple primary servers can be load balanced, standby will only be enabled when the primary server is offline! Multiple groups can be set, Haproxy port same one for each group." -msgstr "添加节点,指定出口功能是为多WAN用户准备的。负载比重范围1-256。多个主服务器可以负载均衡,备用只有在主服务器离线时才会启用!可以设置多个组,负载均衡端口相同则为一组。" - -msgid "Note that the node configuration parameters for load balancing must be consistent, otherwise problems can arise!" -msgstr "注意,负载均衡的节点配置参数必须一致,否则会出问题!" - -msgid "Node" -msgstr "节点" - -msgid "Node Address" -msgstr "节点地址" - -msgid "Node Port" -msgstr "节点端口" - -msgid "Node Weight" -msgstr "负载比重" - -msgid "Export Of Multi WAN" -msgstr "多WAN指定出口" - -msgid "Main" -msgstr "主要" - -msgid "Mode" -msgstr "模式" - -msgid "Primary" -msgstr "主要" - -msgid "Standby" -msgstr "备用" - -msgid "Manually update" -msgstr "手动更新" - -msgid "Enable custom URL" -msgstr "启用自定义规则地址" - -msgid "GFW domains(gfwlist) Update URL" -msgstr "防火墙域名列表(gfwlist)更新URL" - -msgid "China IPs(chnroute) Update URL" -msgstr "中国IP段(chnroute)更新URL" - -msgid "China IPv6s(chnroute6) Update URL" -msgstr "中国IPv6段(chnroute6)更新URL" - -msgid "China List(Chnlist) Update URL" -msgstr "中国域名列表(Chnlist)更新URL" - -msgid "Rule status" -msgstr "规则版本" - -msgid "Enable auto update rules" -msgstr "开启自动更新规则" - -msgid "Week update rules" -msgstr "更新时间星期" - -msgid "Day update rules" -msgstr "更新时间小时" - -msgid "Every day" -msgstr "每天" - -msgid "day" -msgstr "日" - -msgid "Week" -msgstr "周" - -msgid "oclock" -msgstr "点" - -msgid "Location of Xray asset" -msgstr "Xray 资源文件目录" - -msgid "This variable specifies a directory where geoip.dat and geosite.dat files are." -msgstr "此变量指定geoip.dat和geosite.dat文件所在的目录。" - -msgid "Shunt Rule" -msgstr "分流规则" - -msgid "Please note attention to the priority, the higher the order, the higher the priority." -msgstr "请注意优先级问题,排序越上面优先级越高。" - -msgid "Update..." -msgstr "更新中" - -msgid "It is the latest version" -msgstr "已是最新版本" - -msgid "Update successful" -msgstr "更新成功" - -msgid "Click to update" -msgstr "点击更新" - -msgid "Updating..." -msgstr "更新中" - -msgid "Unexpected error" -msgstr "意外错误" - -msgid "Updating, are you sure to close?" -msgstr "正在更新,你确认要关闭吗?" - -msgid "Downloading..." -msgstr "下载中" - -msgid "Unpacking..." -msgstr "解压中" - -msgid "Moving..." -msgstr "移动中" - -msgid "App Update" -msgstr "组件更新" - -msgid "Please confirm that your firmware supports FPU." -msgstr "请确认你的固件支持FPU。" - -msgid "if you want to run from memory, change the path, /tmp beginning then save the application and update it manually." -msgstr "如果你希望从内存中运行,请更改路径,/tmp 开头,然后保存应用后,再手动更新。" - -msgid "Make sure there is enough space to install %s" -msgstr "确保有足够的空间安装 %s" - -msgid "App Path" -msgstr "程序路径" - -msgid "%s App Path" -msgstr "%s 程序路径" - -msgid "%s Client App Path" -msgstr "%s 客户端程序路径" - -msgid "Trojan-Go Version API" -msgstr "Trojan-Go 版本 API" - -msgid "alternate API URL for version checking" -msgstr "用于版本检查的 API URL" - -msgid "Node Subscribe" -msgstr "节点订阅" - -msgid "Subscribe Remark" -msgstr "订阅备注(机场)" - -msgid "Subscribe URL" -msgstr "订阅网址" - -msgid "Please input the subscription url first, save and submit before updating. If you subscribe to update, it is recommended to delete all subscriptions and then re-subscribe." -msgstr "请输入订阅网址保存应用后再更新,如果订阅节点更新了,建议删除所有订阅,然后重新订阅。" - -msgid "Subscribe via proxy" -msgstr "通过代理订阅" - -msgid "Enable auto update subscribe" -msgstr "开启自动更新订阅" - -msgid "Manual subscription" -msgstr "手动订阅" - -msgid "Delete All Subscribe Node" -msgstr "删除所有订阅节点" - -msgid "Filter keyword Mode" -msgstr "过滤关键字模式" - -msgid "Discard List" -msgstr "丢弃列表" - -msgid "Keep List" -msgstr "保留列表" - -msgid "Add" -msgstr "添加" - -msgid "ACLs" -msgstr "访问控制" - -msgid "ACLs is a tools which used to designate specific IP proxy mode, IP or MAC address can be entered." -msgstr "访问控制列表是用于指定特殊IP代理模式的工具。IP、MAC地址可只填写一项。" - -msgid "Remarks" -msgstr "备注" - -msgid "Direct List" -msgstr "直连列表" - -msgid "Proxy List" -msgstr "代理列表" - -msgid "Block List" -msgstr "屏蔽列表" - -msgid "Join the direct hosts list of domain names will not proxy." -msgstr "加入的域名不走代理,对所有模式有效。且优先级最高。" - -msgid "These had been joined ip addresses will not proxy. Please input the ip address or ip address segment,every line can input only one ip address. For example: 192.168.0.0/24 or 223.5.5.5." -msgstr "加入的IP段不走代理,对所有模式有效。且优先级最高。可输入IP地址或地址段,如:192.168.0.0/24或223.5.5.5,每个地址段一行。" - -msgid "These had been joined websites will use proxy. Please input the domain names of websites, every line can input only one website domain. For example: google.com." -msgstr "加入的域名将走代理。输入网站域名,如:google.com,每个地址段一行。" - -msgid "These had been joined ip addresses will use proxy. Please input the ip address or ip address segment, every line can input only one ip address. For example: 35.24.0.0/24 or 8.8.4.4." -msgstr "加入的IP段将走代理。可输入IP地址或地址段,如:35.24.0.0/24或8.8.4.4,每个地址段一行。" - -msgid "These had been joined websites will be block. Please input the domain names of websites, every line can input only one website domain. For example: twitter.com." -msgstr "加入的域名将屏蔽。输入网站域名,如:twitter.com,每个地址段一行。" - -msgid "These had been joined ip addresses will be block. Please input the ip address or ip address segment, every line can input only one ip address." -msgstr "加入的IP段将屏蔽。可输入IP地址或地址段,每个地址段一行。" - -msgid "Not valid domain name, please re-enter!" -msgstr "不是有效域名,请重新输入!" - -msgid "Not valid IP format, please re-enter!" -msgstr "不是有效IP格式,请重新输入!" - -msgid "Plaintext: If this string matches any part of the targeting domain, this rule takes effet. Example: rule 'sina.com' matches targeting domain 'sina.com', 'sina.com.cn' and 'www.sina.com', but not 'sina.cn'." -msgstr "纯字符串: 当此字符串匹配目标域名中任意部分,该规则生效。比如'sina.com'可以匹配'sina.com'、'sina.com.cn'和'www.sina.com',但不匹配'sina.cn'。" - -msgid "Regular expression: Begining with 'regexp:', the rest is a regular expression. When the regexp matches targeting domain, this rule takes effect. Example: rule 'regexp:\\.goo.*\\.com$' matches 'www.google.com' and 'fonts.googleapis.com', but not 'google.com'." -msgstr "正则表达式: 由'regexp:'开始,余下部分是一个正则表达式。当此正则表达式匹配目标域名时,该规则生效。例如'regexp:\\.goo.*\\.com$'匹配'www.google.com'、'fonts.googleapis.com',但不匹配'google.com'。" - -msgid "Subdomain (recommended): Begining with 'domain:' and the rest is a domain. When the targeting domain is exactly the value, or is a subdomain of the value, this rule takes effect. Example: rule 'domain:v2ray.com' matches 'www.v2ray.com', 'v2ray.com', but not 'xv2ray.com'." -msgstr "子域名 (推荐): 由'domain:'开始,余下部分是一个域名。当此域名是目标域名或其子域名时,该规则生效。例如'domain:v2ray.com'匹配'www.v2ray.com'、'v2ray.com',但不匹配'xv2ray.com'。" - -msgid "Full domain: Begining with 'full:' and the rest is a domain. When the targeting domain is exactly the value, the rule takes effect. Example: rule 'domain:v2ray.com' matches 'v2ray.com', but not 'www.v2ray.com'." -msgstr "完整匹配: 由'full:'开始,余下部分是一个域名。当此域名完整匹配目标域名时,该规则生效。例如'full:v2ray.com'匹配'v2ray.com'但不匹配'www.v2ray.com'。" - -msgid "Pre-defined domain list: Begining with 'geosite:' and the rest is a name, such as geosite:google or geosite:cn." -msgstr "预定义域名列表:由'geosite:'开头,余下部分是一个名称,如geosite:google或者geosite:cn。" - -msgid "Domains from file: Such as 'ext:file:tag'. The value must begin with ext: (lowercase), and followed by filename and tag. The file is placed in resource directory, and has the same format of geosite.dat. The tag must exist in the file." -msgstr "从文件中加载域名: 形如'ext:file:tag',必须以ext:(小写)开头,后面跟文件名和标签,文件存放在资源目录中,文件格式与geosite.dat相同,标签必须在文件中存在。" - -msgid "IP: such as '127.0.0.1'." -msgstr "IP: 形如'127.0.0.1'。" - -msgid "CIDR: such as '127.0.0.0/8'." -msgstr "CIDR: 形如'10.0.0.0/8'." - -msgid "GeoIP: such as 'geoip:cn'. It begins with geoip: (lower case) and followed by two letter of country code." -msgstr "GeoIP: 形如'geoip:cn',必须以geoip:(小写)开头,后面跟双字符国家代码,支持几乎所有可以上网的国家。" - -msgid "IPs from file: Such as 'ext:file:tag'. The value must begin with ext: (lowercase), and followed by filename and tag. The file is placed in resource directory, and has the same format of geoip.dat. The tag must exist in the file." -msgstr "从文件中加载 IP: 形如'ext:file:tag',必须以ext:(小写)开头,后面跟文件名和标签,文件存放在资源目录中,文件格式与geoip.dat相同标签必须在文件中存在。" - -msgid "Clear logs" -msgstr "清空日志" - -msgid "Need node support required" -msgstr "需要节点支持" - -msgid "HAProxy cannot be used with KCP." -msgstr "HAProxy不能和KCP一起使用" - -msgid "Password" -msgstr "密码" - -msgid "Connection Timeout" -msgstr "连接超时时间" - -msgid "Local Port" -msgstr "本地端口" - -msgid "TCP Fast Open" -msgstr "TCP快速打开" - -msgid "Need node support required" -msgstr "需要节点支持" - -msgid "plugin" -msgstr "插件" - -msgid "opts" -msgstr "插件选项" - -msgid "Xray is currently directly compatible with V2ray and used." -msgstr "Xray 目前可直接兼容 V2ray 并使用。" - -msgid "Protocol" -msgstr "协议名称" - -msgid "Protocol_param" -msgstr "协议参数" - -msgid "Obfs" -msgstr "混淆" - -msgid "Obfs_param" -msgstr "混淆参数" - -msgid "Plugin Name" -msgstr "插件名称" - -msgid "Plugin Arguments" -msgstr "插件参数" - -msgid "Proxy IPv6" -msgstr "代理IPv6" - -msgid "The IPv6 traffic can be proxyed when selected" -msgstr "选中后可以代理IPv6流量" - -msgid "Use Kcptun" -msgstr "使用Kcptun" - -msgid "Please confirm whether the Kcptun is installed. If not, please go to Rule Update download installation." -msgstr "请确认Kcptun是否已安装,若没有请到自动更新下载安装。" - -msgid "Kcptun Server" -msgstr "Kcptun服务器" - -msgid "Default:Current Server" -msgstr "留空则使用当前服务器" - -msgid "Kcptun Config" -msgstr "Kcptun参数配置" - -msgid "--crypt aes192 --key abc123 --mtu 1350 --sndwnd 128 --rcvwnd 1024 --mode fast" -msgstr "参数中无需配置服务器IP和本地端口,需要配置的参数和格式如:--crypt aes192 --key abc123 --mtu 1350 --sndwnd 128 --rcvwnd 1024 --mode fast" - -msgid "Brook Protocol" -msgstr "Brook协议" - -msgid "Use TLS" -msgstr "使用TLS" - -msgid "Naiveproxy Protocol" -msgstr "Naiveproxy协议" - -msgid "V2ray Protocol" -msgstr "V2ray协议" - -msgid "Alter ID" -msgstr "额外ID(alterId)" - -msgid "User Level" -msgstr "用户等级(level)" - -msgid "Transport" -msgstr "传输方式" - -msgid "Camouflage Type" -msgstr "伪装类型" - -msgid "Transport Layer Encryption" -msgstr "传输层加密" - -msgid "Whether or not transport layer encryption is enabled, \"none\" for unencrypted, \"tls\" for using TLS, \"xtls\" for using XTLS." -msgstr "是否启入传输层加密,支持的选项有 \"none\" 表示不加密,\"tls\" 表示使用 TLS,\"xtls\" 表示使用 XTLS。" - -msgid "Original Trojan only supported 'tls', please choose 'tls'." -msgstr "原版Trojan只支持'tls',请选择'tls'。" - -msgid "Domain" -msgstr "域名" - -msgid "allowInsecure" -msgstr "允许不安全连接" - -msgid "Whether unsafe connections are allowed. When checked, Certificate validation will be skipped." -msgstr "是否允许不安全连接。当勾选时,将跳过证书验证。" - -msgid "
none: default, no masquerade, data sent is packets with no characteristics.
srtp: disguised as an SRTP packet, it will be recognized as video call data (such as FaceTime).
utp: packets disguised as uTP will be recognized as bittorrent downloaded data.
wechat-video: packets disguised as WeChat video calls.
dtls: disguised as DTLS 1.2 packet.
wireguard: disguised as a WireGuard packet. (not really WireGuard protocol)" -msgstr "
none:默认值,不进行伪装,发送的数据是没有特征的数据包。
srtp:伪装成 SRTP 数据包,会被识别为视频通话数据(如 FaceTime)。
utp:伪装成 uTP 数据包,会被识别为 BT 下载数据。
wechat-video:伪装成微信视频通话的数据包。
dtls:伪装成 DTLS 1.2 数据包。
wireguard:伪装成 WireGuard 数据包。(并不是真正的 WireGuard 协议)" - -msgid "A legal file path. This file must not exist before running." -msgstr "一个合法的文件路径。在运行之前,这个文件必须不存在。" - -msgid "TCP Open Socks" -msgstr "开启Socks" - -msgid "When using this TCP node, whether to open the socks proxy at the same time" -msgstr "使用此TCP节点时,是否同时打开socks代理" - -msgid "Do not conflict with other ports" -msgstr "端口不能冲突" - -msgid "Auth" -msgstr "身份认证" - -msgid "Socks for authentication" -msgstr "Socks认证方式" - -msgid "Socks protocol authentication, support anonymous and password." -msgstr "Socks 协议的认证方式,支持匿名方式和账号密码方式。" - -msgid "anonymous" -msgstr "匿名" - -msgid "User Password" -msgstr "账号密码" - -msgid "Username and Password must be used together!" -msgstr "账号和密码必须同时使用!" - -msgid "Node Number" -msgstr "节点数量" - -msgid "You can only set up a maximum of %s nodes for the time being, Used for access control." -msgstr "目前最多只能设置%s个节点,用于给访问控制使用。" - -msgid "IPv6 TProxy" -msgstr "IPv6透明代理(TProxy)" - -msgid "Experimental feature.Make sure that your node supports IPv6." -msgstr "实验特性,请确保你的节点支持IPv6" - -msgid "Status info" -msgstr "状态信息" - -msgid "Big icon" -msgstr "大图标" - -msgid "Show node check" -msgstr "显示节点检测" - -msgid "Show Show IP111" -msgstr "显示IP111" - -msgid "Hide menu method, input example in the address bar:" -msgstr "隐藏菜单方法,地址栏输入例:" - -msgid "After the hidden to the display, input example in the address bar:" -msgstr "当你隐藏后想再次显示,地址栏输入例:" - -msgid "The MTProto protocol must be 32 characters and can only contain characters from 0 to 9 and a to f." -msgstr "MTProto 协议必须为 32 个字符,仅可包含 0 到 9 和 a 到 f 之间的字符。" - -msgid "Whether to receive PROXY protocol, when this node want to be fallback or forwarded by proxy, it must be enable, otherwise it cannot be used." -msgstr "是否接收 PROXY protocol,当该节点要被回落或被代理转发时,必须启用,否则不能使用。" - -msgid "transit node" -msgstr "中转到此节点" - -msgid "Custom Socks" -msgstr "自定义 Socks" - -msgid "Custom HTTP" -msgstr "自定义 HTTP" - -msgid "Bind Local" -msgstr "本机监听" - -msgid "When selected, it can only be accessed locally, It is recommended to turn on when using reverse proxies or be fallback." -msgstr "当勾选时,只能由本机访问此端口,当想被反向代理或被回落时建议勾选此项。" - -msgid "Accept LAN Access" -msgstr "接受局域网访问" - -msgid "When selected, it can accessed lan , this will not be safe!" -msgstr "当勾选时,可以直接访问局域网,这将不安全!(非特殊情况不建议开启)" - -msgid "Enable Remote" -msgstr "启用转发" - -msgid "You can forward to Nginx/Caddy/V2ray WebSocket and more." -msgstr "您可以转发到Nginx/Caddy/V2ray WebSocket等。" - -msgid "Remote Address" -msgstr "远程地址" - -msgid "Remote Port" -msgstr "远程端口" - -msgid "as:" -msgstr "如:" - -msgid "Public key absolute path" -msgstr "公钥文件绝对路径" - -msgid "Private key absolute path" -msgstr "私钥文件绝对路径" - -msgid "Can't find this file!" -msgstr "找不到这个文件!" - -msgid "Public key and Private key path can not be empty!" -msgstr "公钥和私钥文件路径不能为空!" - -msgid "Server-Side" -msgstr "服务器端" - -msgid "Server Config" -msgstr "服务器配置" - -msgid "Users Manager" -msgstr "用户管理" - -msgid "Logs" -msgstr "日志" - -msgid "Log" -msgstr "日志" - -msgid "%s Node Log Close" -msgstr "%s 节点日志关闭" - -msgid "Log Level" -msgstr "日志等级" - -msgid "Not enabled log" -msgstr "未启用日志" - -msgid "UDP Forward" -msgstr "UDP转发" - -msgid "You did not fill in the %s path. Please save and apply then update manually." -msgstr "您没有填写 %s 路径。请保存应用后再手动更新。" - -msgid "Not installed unzip, Can't unzip!" -msgstr "未安装unzip,无法解压。" - -msgid "Can't determine ARCH, or ARCH not supported." -msgstr "无法确认ARCH架构,或是不支持。" - -msgid "Get remote version info failed." -msgstr "获取远程版本信息失败。" - -msgid "New version found, but failed to get new version download url." -msgstr "发现新版本,但未能获得新版本的下载地址。" - -msgid "Download url is required." -msgstr "请指定下载地址。" - -msgid "File download failed or timed out: %s" -msgstr "文件下载失败或超时:%s" - -msgid "File path required." -msgstr "请指定文件路径。" - -msgid "Can't find client in file: %s" -msgstr "无法在文件中找到客户端:%s" - -msgid "Client file is required." -msgstr "请指定客户端文件。" - -msgid "The client file is not suitable for current device." -msgstr "客户端文件不适合当前设备。" - -msgid "Can't move new file to path: %s" -msgstr "无法移动新文件到:%s" - -msgid "DNS Settings" -msgstr "DNS设置" diff --git a/package/lienol/luci-app-passwall/root/etc/config/passwall b/package/lienol/luci-app-passwall/root/etc/config/passwall deleted file mode 100644 index 6c00b2aad8..0000000000 --- a/package/lienol/luci-app-passwall/root/etc/config/passwall +++ /dev/null @@ -1,140 +0,0 @@ - -config global - option enabled '0' - option socks_enabled '0' - option tcp_node 'nil' - option udp_node 'nil' - option dns_mode 'pdnsd' - option up_china_dns 'default' - option dns_forward '8.8.8.8' - option tcp_proxy_mode 'chnroute' - option udp_proxy_mode 'chnroute' - option localhost_tcp_proxy_mode 'default' - option localhost_udp_proxy_mode 'default' - option socks_server '127.0.0.1:1080' - option close_log_tcp '0' - option close_log_udp '0' - option loglevel 'warning' - option trojan_loglevel '2' - -config global_haproxy - option balancing_enable '0' - -config global_delay - option auto_on '0' - option start_daemon '0' - option start_delay '1' - -config global_forwarding - option process '0' - option tcp_no_redir_ports 'disable' - option udp_no_redir_ports '80,443' - option tcp_redir_ports '22,25,53,143,465,587,993,995,80,443' - option udp_redir_ports '1:65535' - option proxy_ipv6 '0' - -config global_other - option status 'big_icon show_check_port show_ip111' - option nodes_ping 'auto_ping tcping' - option ipv6_tproxy '0' - -config global_rules - option auto_update '0' - option chnlist_update '1' - option chnroute_update '1' - option chnroute6_update '1' - option gfwlist_update '1' - option gfwlist_url 'https://cdn.jsdelivr.net/gh/Loukky/gfwlist-by-loukky/gfwlist.txt' - option chnroute_url 'https://ispip.clang.cn/all_cn.txt' - option chnroute6_url 'https://ispip.clang.cn/all_cn_ipv6.txt' - list chnlist_url 'https://cdn.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/accelerated-domains.china.conf' - list chnlist_url 'https://cdn.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/apple.china.conf' - list chnlist_url 'https://cdn.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/google.china.conf' - option xray_location_asset '/usr/share/xray/' - option geosite_update '1' - option geoip_update '1' - -config global_app - option xray_file '/usr/bin/xray' - option trojan_go_file '/usr/bin/trojan-go' - option kcptun_client_file '/usr/bin/kcptun-client' - option brook_file '/usr/bin/brook' - -config global_subscribe - option subscribe_proxy '0' - option auto_update_subscribe '0' - option allowInsecure '1' - option filter_keyword_mode '1' - list filter_discard_list '过期时间' - list filter_discard_list '剩余流量' - list filter_discard_list 'QQ群' - list filter_discard_list '官网' - -config auto_switch - option testing_time '1' - option enable '0' - -config nodes '696cd32c1d5149ee95fd1b3accbad6df' - option remarks '分流总节点' - option type 'Xray' - option protocol '_shunt' - option youtube 'nil' - option netflix 'nil' - option TVB 'nil' - option Telegram 'nil' - option default_node 'nil' - option default_proxy '0' - option domainStrategy 'IPIfNonMatch' - -config shunt_rules 'ads' - option remarks '广告' - option domain_list 'geosite:category-ads' - -config shunt_rules 'China' - option remarks 'China' - option domain_list 'geosite:cn' - option ip_list 'geoip:cn' - -config shunt_rules 'Telegram' - option remarks 'Telegram' - option ip_list '149.154.160.0/20 -91.108.4.0/22 -91.108.56.0/24 -109.239.140.0/24 -67.198.55.0/24' - -config shunt_rules 'youtube' - option remarks 'youtube' - option domain_list 'youtube -youtube.com -youtu.be -googlevideo.com -ytimg.com -gvt2.com' - -config shunt_rules 'netflix' - option remarks '奈飞' - option domain_list 'fast.com -netflix -netflix.com -netflix.net -nflxso.net -nflxext.com -nflximg.com -nflximg.net -nflxvideo.net -netflixdnstest0.com -netflixdnstest1.com -netflixdnstest2.com -netflixdnstest3.com -netflixdnstest4.com -netflixdnstest5.com -netflixdnstest6.com -netflixdnstest7.com -netflixdnstest8.com -netflixdnstest9.com' - -config shunt_rules 'TVB' - option remarks 'TVB' - option domain_list 'tvb.com -mytvsuper.com' diff --git a/package/lienol/luci-app-passwall/root/etc/config/passwall_server b/package/lienol/luci-app-passwall/root/etc/config/passwall_server deleted file mode 100644 index c9526cb285..0000000000 --- a/package/lienol/luci-app-passwall/root/etc/config/passwall_server +++ /dev/null @@ -1,4 +0,0 @@ - -config global 'global' - option enable '0' - diff --git a/package/lienol/luci-app-passwall/root/etc/init.d/passwall b/package/lienol/luci-app-passwall/root/etc/init.d/passwall deleted file mode 100755 index a8d7316071..0000000000 --- a/package/lienol/luci-app-passwall/root/etc/init.d/passwall +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh /etc/rc.common - -START=99 -STOP=15 - -boot() { - /usr/share/passwall/app.sh boot -} - -start() { - /usr/share/passwall/app.sh start -} - -stop() { - /usr/share/passwall/app.sh stop -} - -restart() { - stop - start -} \ No newline at end of file diff --git a/package/lienol/luci-app-passwall/root/etc/init.d/passwall_server b/package/lienol/luci-app-passwall/root/etc/init.d/passwall_server deleted file mode 100755 index 43504a825c..0000000000 --- a/package/lienol/luci-app-passwall/root/etc/init.d/passwall_server +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh /etc/rc.common - -START=99 - -start() { - /usr/lib/lua/luci/model/cbi/passwall/server/api/app.lua start -} - -stop() { - /usr/lib/lua/luci/model/cbi/passwall/server/api/app.lua stop -} - -restart() { - stop - start -} \ No newline at end of file diff --git a/package/lienol/luci-app-passwall/root/etc/uci-defaults/luci-app-passwall b/package/lienol/luci-app-passwall/root/etc/uci-defaults/luci-app-passwall deleted file mode 100755 index efae9989d5..0000000000 --- a/package/lienol/luci-app-passwall/root/etc/uci-defaults/luci-app-passwall +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - set dhcp.@dnsmasq[0].localuse=1 - commit dhcp - delete ucitrack.@passwall[-1] - add ucitrack passwall - set ucitrack.@passwall[-1].init=passwall - commit ucitrack - delete firewall.passwall - set firewall.passwall=include - set firewall.passwall.type=script - set firewall.passwall.path=/var/etc/passwall.include - set firewall.passwall.reload=1 - commit firewall - delete ucitrack.@passwall_server[-1] - add ucitrack passwall_server - set ucitrack.@passwall_server[-1].init=passwall_server - commit ucitrack - delete firewall.passwall_server - set firewall.passwall_server=include - set firewall.passwall_server.type=script - set firewall.passwall_server.path=/var/etc/passwall_server.include - set firewall.passwall_server.reload=1 - commit firewall - set uhttpd.main.max_requests=50 - commit uhttpd -EOF - -rm -rf /tmp/luci-*cache -exit 0 diff --git a/package/lienol/luci-app-passwall/root/usr/share/passwall/app.sh b/package/lienol/luci-app-passwall/root/usr/share/passwall/app.sh deleted file mode 100755 index b1c502b017..0000000000 --- a/package/lienol/luci-app-passwall/root/usr/share/passwall/app.sh +++ /dev/null @@ -1,1429 +0,0 @@ -#!/bin/sh -# Copyright (C) 2018-2020 L-WRT Team -# Copyright (C) 2021 xiaorouji - -. $IPKG_INSTROOT/lib/functions.sh -. $IPKG_INSTROOT/lib/functions/service.sh - -CONFIG=passwall -TMP_PATH=/var/etc/$CONFIG -TMP_BIN_PATH=$TMP_PATH/bin -TMP_ID_PATH=$TMP_PATH/id -TMP_PORT_PATH=$TMP_PATH/port -TMP_ROUTE_PATH=$TMP_PATH/route -LOCK_FILE=/var/lock/$CONFIG.lock -LOG_FILE=/var/log/$CONFIG.log -APP_PATH=/usr/share/$CONFIG -RULES_PATH=/usr/share/${CONFIG}/rules -TMP_DNSMASQ_PATH=/var/etc/dnsmasq-passwall.d -DNSMASQ_PATH=/etc/dnsmasq.d -LOCAL_DOH_PORT=7912 -DNS_PORT=7913 -TUN_DNS="127.0.0.1#${DNS_PORT}" -IS_DEFAULT_DNS=0 -LOCAL_DNS= -DEFAULT_DNS= -NO_PROXY= -use_tcp_node_resolve_dns=0 -use_udp_node_resolve_dns=0 -LUA_API_PATH=/usr/lib/lua/luci/model/cbi/$CONFIG/api -API_GEN_SS=$LUA_API_PATH/gen_shadowsocks.lua -API_GEN_XRAY=$LUA_API_PATH/gen_xray.lua -API_GEN_XRAY_PROTO=$LUA_API_PATH/gen_xray_proto.lua -API_GEN_TROJAN=$LUA_API_PATH/gen_trojan.lua -API_GEN_NAIVE=$LUA_API_PATH/gen_naiveproxy.lua -echolog() { - local d="$(date "+%Y-%m-%d %H:%M:%S")" - echo -e "$d: $*" >>$LOG_FILE -} - -config_n_get() { - local ret=$(uci -q get "${CONFIG}.${1}.${2}" 2>/dev/null) - echo "${ret:=$3}" -} - -config_t_get() { - local index=${4:-0} - local ret=$(uci -q get "${CONFIG}.@${1}[${index}].${2}" 2>/dev/null) - echo "${ret:=${3}}" -} - -set_lock(){ - exec 1000>"$LOCK_FILE" - flock -x 1000 -} - -trap 'rm -f "$LOCK_FILE"; exit $?' INT TERM EXIT - -unlock() { - failcount=1 - while [ "$failcount" -le 10 ]; do - if [ -f "$LOCK_FILE" ]; then - let "failcount++" - sleep 1s - [ "$failcount" -ge 10 ] && unset_lock - else - break - fi - done -} - -unset_lock(){ - flock -u 1000 - rm -rf "$LOCK_FILE" -} - -_exit() -{ - local rc=$1 - unset_lock - exit ${rc} -} - -get_enabled_anonymous_secs() { - uci -q show "${CONFIG}" | grep "${1}\[.*\.enabled='1'" | cut -d '.' -sf2 -} - -get_host_ip() { - local host=$2 - local count=$3 - [ -z "$count" ] && count=3 - local isip="" - local ip=$host - if [ "$1" == "ipv6" ]; then - isip=$(echo $host | grep -E "([[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){0,7}::[a-f0-9]{0,4}(:[a-f0-9]{1,4}){0,7}])") - if [ -n "$isip" ]; then - isip=$(echo $host | cut -d '[' -f2 | cut -d ']' -f1) - else - isip=$(echo $host | grep -E "([a-f0-9]{1,4}(:[a-f0-9]{1,4}){7}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){0,7}::[a-f0-9]{0,4}(:[a-f0-9]{1,4}){0,7})") - fi - else - isip=$(echo $host | grep -E "([0-9]{1,3}[\.]){3}[0-9]{1,3}") - fi - [ -z "$isip" ] && { - local t=4 - [ "$1" == "ipv6" ] && t=6 - local vpsrip=$(resolveip -$t -t $count $host | awk 'NR==1{print}') - ip=$vpsrip - } - echo $ip -} - -get_node_host_ip() { - local ip - local address=$(config_n_get $1 address) - [ -n "$address" ] && { - local use_ipv6=$(config_n_get $1 use_ipv6) - local network_type="ipv4" - [ "$use_ipv6" == "1" ] && network_type="ipv6" - ip=$(get_host_ip $network_type $address) - } - echo $ip -} - -get_ip_port_from() { - local __host=${1}; shift 1 - local __ipv=${1}; shift 1 - local __portv=${1}; shift 1 - - local val1 val2 - val2=$(echo $__host | sed -n 's/^.*[:#]\([0-9]*\)$/\1/p') - val1="${__host%%${val2:+[:#]${val2}*}}" - eval "${__ipv}=\"$val1\"; ${__portv}=\"$val2\"" -} - -host_from_url(){ - local f=${1} - - ## Remove protocol part of url ## - f="${f##http://}" - f="${f##https://}" - f="${f##ftp://}" - f="${f##sftp://}" - - ## Remove username and/or username:password part of URL ## - f="${f##*:*@}" - f="${f##*@}" - - ## Remove rest of urls ## - f="${f%%/*}" - echo "${f%%:*}" -} - -hosts_foreach() { - local __hosts - eval "__hosts=\$${1}"; shift 1 - local __func=${1}; shift 1 - local __default_port=${1}; shift 1 - local __ret=1 - - [ -z "${__hosts}" ] && return 0 - local __ip __port - for __host in $(echo $__hosts | sed 's/[ ,]/\n/g'); do - get_ip_port_from "$__host" "__ip" "__port" - eval "$__func \"${__host}\" \"\${__ip}\" \"\${__port:-${__default_port}}\" \"$@\"" - __ret=$? - [ ${__ret} -ge ${ERROR_NO_CATCH:-1} ] && return ${__ret} - done -} - -get_first_dns() { - local __hosts_val=${1}; shift 1 - __first() { - [ -z "${2}" ] && return 0 - echo "${2}#${3}" - return 1 - } - eval "hosts_foreach \"${__hosts_val}\" __first \"$@\"" -} - -get_last_dns() { - local __hosts_val=${1}; shift 1 - local __first __last - __every() { - [ -z "${2}" ] && return 0 - __last="${2}#${3}" - __first=${__first:-${__last}} - } - eval "hosts_foreach \"${__hosts_val}\" __every \"$@\"" - [ "${__first}" == "${__last}" ] || echo "${__last}" -} - -gen_dnsmasq_items() { - local ipsetlist=${1}; shift 1 - local fwd_dns=${1}; shift 1 - local outf=${1}; shift 1 - - awk -v ipsetlist="${ipsetlist}" -v ipsetoutf="${TMP_DNSMASQ_PATH}/ipset.conf" -v fwd_dns="${fwd_dns}" -v outf="${outf}" ' - BEGIN { - if(outf == "") {outf="/dev/stdout"; ipsetoutf="/dev/stdout";} - split(fwd_dns, dns, ","); setdns=length(dns)>0; setlist=length(ipsetlist)>0; - if(setdns) for(i in dns) if(length(dns[i])==0) delete dns[i]; - fail=1; - } - ! /^$/&&!/^#/ { - fail=0 - if(! (setdns || setlist)) {printf("server=%s\n", $0) >>outf; next;} - if(setdns) for(i in dns) printf("server=/.%s/%s\n", $0, dns[i]) >>outf; - - if(setlist) printf("ipset=/.%s/%s\n", $0, ipsetlist) >>ipsetoutf; - } - END {fflush(outf); close(outf); fflush(ipsetoutf); close(ipsetoutf); exit(fail);} - ' -} - -gen_dnsmasq_fake_items() { - local fwd_dns=${1}; shift 1 - local outf=${1}; shift 1 - - awk -v fwd_dns="${fwd_dns}" -v outf="${outf}" ' - BEGIN { - if(outf == "") outf="/dev/stdout"; - split(fwd_dns, dns, ","); setdns=length(dns)>0; - if(setdns) for(i in dns) if(length(dns[i])==0) delete dns[i]; - fail=1; - } - ! /^$/&&!/^#/ { - fail=0 - if(! setdns) {printf("address=%s\n", $0) >>outf; next;} - if(setdns) for(i in dns) printf("address=/.%s/%s\n", $0, dns[i]) >>outf; - } - END {fflush(outf); close(outf); exit(fail);} - ' -} - -check_port_exists() { - port=$1 - protocol=$2 - result= - if [ "$protocol" = "tcp" ]; then - result=$(netstat -tln | grep -c ":$port ") - elif [ "$protocol" = "udp" ]; then - result=$(netstat -uln | grep -c ":$port ") - fi - echo "${result}" -} - -get_new_port() { - port=$1 - [ "$port" == "auto" ] && port=2082 - protocol=$(echo $2 | tr 'A-Z' 'a-z') - result=$(check_port_exists $port $protocol) - if [ "$result" != 0 ]; then - temp= - if [ "$port" -lt 65535 ]; then - temp=$(expr $port + 1) - elif [ "$port" -gt 1 ]; then - temp=$(expr $port - 1) - fi - get_new_port $temp $protocol - else - echo $port - fi -} - -first_type() { - local path_name=${1} - type -t -p "/bin/${path_name}" -p "${TMP_BIN_PATH}/${path_name}" -p "${path_name}" "$@" | head -n1 -} - -ln_start_bin() { - local file_func=${1} - local ln_name=${2} - local output=${3} - - shift 3; - if [ "${file_func%%/*}" != "${file_func}" ]; then - [ ! -L "${file_func}" ] && { - ln -s "${file_func}" "${TMP_BIN_PATH}/${ln_name}" >/dev/null 2>&1 - file_func="${TMP_BIN_PATH}/${ln_name}" - } - [ -x "${file_func}" ] || echolog " - $(readlink ${file_func}) 没有执行权限,无法启动:${file_func} $*" - fi - #echo "${file_func} $*" >&2 - [ -n "${file_func}" ] || echolog " - 找不到 ${ln_name},无法启动..." - ${file_func:-echolog " - ${ln_name}"} "$@" >${output} 2>&1 & -} - -ENABLED=$(config_t_get global enabled 0) -SOCKS_ENABLED=$(config_t_get global socks_enabled 0) - -TCP_REDIR_PORT=1041 -TCP_NODE=$(config_t_get global tcp_node nil) - -UDP_REDIR_PORT=1051 -UDP_NODE=$(config_t_get global udp_node nil) - -[ "$UDP_NODE" == "tcp_" ] && UDP_NODE=$TCP_NODE -[ "$UDP_NODE" == "tcp" ] && UDP_REDIR_PORT=$TCP_REDIR_PORT - -TCP_REDIR_PORTS=$(config_t_get global_forwarding tcp_redir_ports '80,443') -UDP_REDIR_PORTS=$(config_t_get global_forwarding udp_redir_ports '1:65535') -TCP_NO_REDIR_PORTS=$(config_t_get global_forwarding tcp_no_redir_ports 'disable') -UDP_NO_REDIR_PORTS=$(config_t_get global_forwarding udp_no_redir_ports 'disable') -KCPTUN_REDIR_PORT=$(config_t_get global_forwarding kcptun_port 12948) -TCP_PROXY_MODE=$(config_t_get global tcp_proxy_mode chnroute) -UDP_PROXY_MODE=$(config_t_get global udp_proxy_mode chnroute) -LOCALHOST_TCP_PROXY_MODE=$(config_t_get global localhost_tcp_proxy_mode default) -LOCALHOST_UDP_PROXY_MODE=$(config_t_get global localhost_udp_proxy_mode default) -[ "$LOCALHOST_TCP_PROXY_MODE" == "default" ] && LOCALHOST_TCP_PROXY_MODE=$TCP_PROXY_MODE -[ "$LOCALHOST_UDP_PROXY_MODE" == "default" ] && LOCALHOST_UDP_PROXY_MODE=$UDP_PROXY_MODE -RESOLVFILE=/tmp/resolv.conf.d/resolv.conf.auto -[ -f "${RESOLVFILE}" ] && [ -s "${RESOLVFILE}" ] || RESOLVFILE=/tmp/resolv.conf.auto - -load_config() { - [ "$ENABLED" != 1 ] && NO_PROXY=1 - [ "$TCP_NODE" == "nil" -a "$UDP_NODE" == "nil" ] && { - echolog "没有选择节点!" - NO_PROXY=1 - } - - count_hosts_str= - [ -f "${RULES_PATH}/direct_host" ] && direct_hosts_str="$(echo -n $(cat ${RULES_PATH}/direct_host) | sed "s/ /|/g")" - [ -f "${RULES_PATH}/proxy_host" ] && proxy_hosts_str="$(echo -n $(cat ${RULES_PATH}/proxy_host) | sed "s/ /|/g")" - [ -n "$direct_hosts_str" ] && { - tmp="${direct_hosts_str}" - [ -n "$count_hosts_str" ] && tmp="${count_hosts_str}|${direct_hosts_str}" - count_hosts_str="$tmp" - } - [ -n "$proxy_hosts_str" ] && { - tmp="${proxy_hosts_str}" - [ -n "$count_hosts_str" ] && tmp="${count_hosts_str}|${proxy_hosts_str}" - count_hosts_str="$tmp" - } - - global=$(echo "${TCP_PROXY_MODE}${LOCALHOST_TCP_PROXY_MODE}${UDP_PROXY_MODE}${LOCALHOST_UDP_PROXY_MODE}" | grep "global") - returnhome=$(echo "${TCP_PROXY_MODE}${LOCALHOST_TCP_PROXY_MODE}${UDP_PROXY_MODE}${LOCALHOST_UDP_PROXY_MODE}" | grep "returnhome") - chnlist=$(echo "${TCP_PROXY_MODE}${LOCALHOST_TCP_PROXY_MODE}${UDP_PROXY_MODE}${LOCALHOST_UDP_PROXY_MODE}" | grep "chnroute") - gfwlist=$(echo "${TCP_PROXY_MODE}${LOCALHOST_TCP_PROXY_MODE}${UDP_PROXY_MODE}${LOCALHOST_UDP_PROXY_MODE}" | grep "gfwlist") - DNS_MODE=$(config_t_get global dns_mode pdnsd) - DNS_FORWARD=$(config_t_get global dns_forward 8.8.4.4:53 | sed 's/:/#/g') - DNS_CACHE=$(config_t_get global dns_cache 0) - LOCAL_DNS="default" - if [ "${LOCAL_DNS}" = "default" ]; then - DEFAULT_DNS=$(uci show dhcp | grep "@dnsmasq" | grep "\.server=" | awk -F '=' '{print $2}' | sed "s/'//g" | tr ' ' ',') - if [ -z "${DEFAULT_DNS}" ]; then - DEFAULT_DNS=$(echo -n $(sed -n 's/^nameserver[ \t]*\([^ ]*\)$/\1/p' "${RESOLVFILE}" | grep -v "0.0.0.0" | grep -v "127.0.0.1" | grep -v "^::$" | head -2) | tr ' ' ',') - fi - LOCAL_DNS="${DEFAULT_DNS:-119.29.29.29}" - IS_DEFAULT_DNS=1 - fi - PROXY_IPV6=$(config_t_get global_forwarding proxy_ipv6 0) - export XRAY_LOCATION_ASSET=$(config_t_get global_rules xray_location_asset "/usr/share/xray/") - mkdir -p /var/etc $TMP_PATH $TMP_BIN_PATH $TMP_ID_PATH $TMP_PORT_PATH $TMP_ROUTE_PATH - return 0 -} - -run_socks() { - local flag=$1 - local node=$2 - local bind=$3 - local socks_port=$4 - local config_file=$5 - local http_port=$6 - local http_config_file=$7 - local relay_port=$8 - local log_file="/dev/null" - local type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z') - local remarks=$(config_n_get $node remarks) - local server_host=$(config_n_get $node address) - local port=$(config_n_get $node port) - [ -n "$relay_port" ] && { - server_host="127.0.0.1" - port=$relay_port - } - local msg tmp - - if [ -n "$server_host" ] && [ -n "$port" ]; then - server_host=$(host_from_url "$server_host") - [ -n "$(echo -n $server_host | awk '{print gensub(/[!-~]/,"","g",$0)}')" ] && msg="$remarks,非法的代理服务器地址,无法启动 !" - tmp="(${server_host}:${port})" - else - msg="某种原因,此 Socks 服务的相关配置已失联,启动中止!" - fi - - if [ "$type" == "xray" ] && ([ -n "$(config_n_get $node balancing_node)" ] || [ "$(config_n_get $node default_node)" != "_direct" -a "$(config_n_get $node default_node)" != "_blackhole" ]); then - unset msg - fi - - [ -n "${msg}" ] && { - [ "$bind" != "127.0.0.1" ] && echolog " - 启动中止 ${bind}:${socks_port} ${msg}" - return 1 - } - [ "$bind" != "127.0.0.1" ] && echolog " - 启动 ${bind}:${socks_port} - 节点:$remarks${tmp}" - - case "$type" in - socks|\ - xray) - [ "$http_port" != "0" ] && { - local extra_param="-http_proxy_port $http_port" - config_file=$(echo $config_file | sed "s/SOCKS/HTTP_SOCKS/g") - } - lua $API_GEN_XRAY -node $node -socks_proxy_port $socks_port $extra_param > $config_file - ln_start_bin "$(first_type $(config_t_get global_app xray_file) xray)" xray $log_file -config="$config_file" - ;; - trojan-go) - lua $API_GEN_TROJAN -node $node -run_type client -local_addr $bind -local_port $socks_port -server_host $server_host -server_port $port > $config_file - ln_start_bin "$(first_type $(config_t_get global_app trojan_go_file) trojan-go)" trojan-go $log_file -config "$config_file" - ;; - trojan*) - lua $API_GEN_TROJAN -node $node -run_type client -local_addr $bind -local_port $socks_port -server_host $server_host -server_port $port > $config_file - ln_start_bin "$(first_type ${type})" "${type}" $log_file -c "$config_file" - ;; - naiveproxy) - lua $API_GEN_NAIVE -node $node -run_type socks -local_addr $bind -local_port $socks_port -server_host $server_host -server_port $port > $config_file - ln_start_bin "$(first_type naive)" naive $log_file "$config_file" - ;; - brook) - local protocol=$(config_n_get $node protocol client) - local brook_tls=$(config_n_get $node brook_tls 0) - [ "$protocol" == "wsclient" ] && { - [ "$brook_tls" == "1" ] && server_host="wss://${server_host}" || server_host="ws://${server_host}" - } - ln_start_bin "$(first_type $(config_t_get global_app brook_file) brook)" "brook_SOCKS_${flag}" $log_file "$protocol" --socks5 "$bind:$socks_port" -s "$server_host:$port" -p "$(config_n_get $node password)" - ;; - ss|ssr) - lua $API_GEN_SS -node $node -local_addr "0.0.0.0" -local_port $socks_port -server_host $server_host -server_port $port > $config_file - ss_program="$(first_type ${type}local ${type}-local)" - [ "$(printf '%s' "$ss_program" | awk -F '/' '{print $NF}')" = "${type}local" ] && \ - ss_extra_arg="-U" || ss_extra_arg="-u" - ln_start_bin "$ss_program" "${type}-local" $log_file -c "$config_file" -v $ss_extra_arg - ;; - esac - - # http to socks - [ "$type" != "xray" ] && [ "$type" != "socks" ] && [ "$http_port" != "0" ] && [ "$http_config_file" != "nil" ] && { - lua $API_GEN_XRAY_PROTO -local_proto http -local_address "0.0.0.0" -local_port $http_port -server_proto socks -server_address "127.0.0.1" -server_port $socks_port -server_username $_username -server_password $_password > $http_config_file - echo lua $API_GEN_XRAY_PROTO -local_proto http -local_address "0.0.0.0" -local_port $http_port -server_proto socks -server_address "127.0.0.1" -server_port $socks_port -server_username $_username -server_password $_password - ln_start_bin "$(first_type $(config_t_get global_app xray_file) xray)" xray $log_file -config="$http_config_file" - } -} - -run_redir() { - local node=$1 - local bind=$2 - local local_port=$3 - local config_file=$4 - local REDIR_TYPE=$5 - local log_file=$6 - [ -z "$log_file" ] && log_file="/dev/null" - local redir_type=$(echo $REDIR_TYPE | tr 'A-Z' 'a-z') - local type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z') - local close_log=$(config_t_get global close_log_${redir_type} 1) - [ "$close_log" = "1" ] && log_file="/dev/null" - local remarks=$(config_n_get $node remarks) - local server_host=$(config_n_get $node address) - local port=$(config_n_get $node port) - [ -n "$server_host" -a -n "$port" ] && { - # 判断节点服务器地址是否URL并去掉~ - local server_host=$(host_from_url "$server_host") - # 判断节点服务器地址是否包含汉字~ - local tmp=$(echo -n $server_host | awk '{print gensub(/[!-~]/,"","g",$0)}') - [ -n "$tmp" ] && { - echolog "$remarks节点,非法的服务器地址,无法启动!" - return 1 - } - [ "$bind" != "127.0.0.1" ] && echolog "${REDIR_TYPE}节点:$remarks,节点:${server_host}:${port},监听端口:$local_port" - } - eval ${REDIR_TYPE}_NODE_PORT=$port - - case "$REDIR_TYPE" in - UDP) - case "$type" in - socks) - local node_address=$(config_n_get $node address) - local node_port=$(config_n_get $node port) - local server_username=$(config_n_get $node username) - local server_password=$(config_n_get $node password) - eval port=\$UDP_REDIR_PORT - ln_start_bin "$(first_type ipt2socks)" "ipt2socks_udp" $log_file -U -l "$port" -b 0.0.0.0 -s "$node_address" -p "$node_port" -R -v - ;; - xray) - local loglevel=$(config_t_get global loglevel "warning") - lua $API_GEN_XRAY -node $node -proto udp -redir_port $local_port -loglevel $loglevel > $config_file - ln_start_bin "$(first_type $(config_t_get global_app xray_file) xray)" xray $log_file -config="$config_file" - ;; - trojan-go) - local loglevel=$(config_t_get global trojan_loglevel "2") - lua $API_GEN_TROJAN -node $node -run_type nat -local_addr "0.0.0.0" -local_port $local_port -loglevel $loglevel > $config_file - ln_start_bin "$(first_type $(config_t_get global_app trojan_go_file) trojan-go)" trojan-go $log_file -config "$config_file" - ;; - trojan*) - local loglevel=$(config_t_get global trojan_loglevel "2") - lua $API_GEN_TROJAN -node $node -run_type nat -local_addr "0.0.0.0" -local_port $local_port -loglevel $loglevel > $config_file - ln_start_bin "$(first_type ${type})" "${type}" $log_file -c "$config_file" - ;; - naiveproxy) - echolog "Naiveproxy不支持UDP转发!" - ;; - brook) - local protocol=$(config_n_get $node protocol client) - if [ "$protocol" == "wsclient" ]; then - echolog "Brook的WebSocket不支持UDP转发!" - else - ln_start_bin "$(first_type $(config_t_get global_app brook_file) brook)" "brook_udp" $log_file tproxy -l ":$local_port" -s "$server_host:$port" -p "$(config_n_get $node password)" - fi - ;; - ss|ssr) - lua $API_GEN_SS -node $node -local_addr "0.0.0.0" -local_port $local_port > $config_file - ss_program="$(first_type ${type}local ${type}-redir)" - [ "$(printf '%s' "$ss_program" | awk -F '/' '{print $NF}')" = "${type}local" ] && \ - ss_extra_arg="--protocol redir -u" || ss_extra_arg="-U" - ln_start_bin "$ss_program" "${type}-redir" $log_file -c "$config_file" -v $ss_extra_arg - ;; - esac - ;; - TCP) - local kcptun_use=$(config_n_get $node use_kcp 0) - if [ "$kcptun_use" == "1" ]; then - local kcptun_server_host=$(config_n_get $node kcp_server) - local network_type="ipv4" - local kcptun_port=$(config_n_get $node kcp_port) - local kcptun_config="$(config_n_get $node kcp_opts)" - if [ -z "$kcptun_port" -o -z "$kcptun_config" ]; then - echolog "Kcptun未配置参数,错误!" - return 1 - fi - if [ -n "$kcptun_port" -a -n "$kcptun_config" ]; then - local run_kcptun_ip=$server_host - [ -n "$kcptun_server_host" ] && run_kcptun_ip=$(get_host_ip $network_type $kcptun_server_host) - KCPTUN_REDIR_PORT=$(get_new_port $KCPTUN_REDIR_PORT tcp) - kcptun_params="-l 0.0.0.0:$KCPTUN_REDIR_PORT -r $run_kcptun_ip:$kcptun_port $kcptun_config" - ln_start_bin "$(first_type $(config_t_get global_app kcptun_client_file) kcptun-client)" "kcptun_tcp" $log_file $kcptun_params - fi - fi - local _socks_flag _socks_address _socks_port _socks_username _socks_password - case "$type" in - socks) - _socks_flag=1 - _socks_address=$(config_n_get $node address) - _socks_port=$(config_n_get $node port) - _socks_username=$(config_n_get $node username) - _socks_password=$(config_n_get $node password) - ;; - xray) - local loglevel=$(config_t_get global loglevel "warning") - local proto="-proto tcp" - [ "$UDP_NODE" == "tcp" ] && proto="-proto tcp,udp" - local extra_param="${proto}" - [ "$tcp_node_socks" = "1" ] && { - local socks_param="-socks_proxy_port $tcp_node_socks_port" - extra_param="${extra_param} ${socks_param}" - config_file=$(echo $config_file | sed "s/TCP/TCP_SOCKS_$tcp_node_socks_id/g") - } - [ "$tcp_node_http" = "1" ] && { - local http_param="-http_proxy_port $tcp_node_http_port" - extra_param="${extra_param} ${http_param}" - config_file=$(echo $config_file | sed "s/TCP/TCP_HTTP_$tcp_node_http_id/g") - } - lua $API_GEN_XRAY -node $node -redir_port $local_port -loglevel $loglevel $extra_param > $config_file - ln_start_bin "$(first_type $(config_t_get global_app xray_file) xray)" xray $log_file -config="$config_file" - ;; - trojan-go) - local loglevel=$(config_t_get global trojan_loglevel "2") - lua $API_GEN_TROJAN -node $node -run_type nat -local_addr "0.0.0.0" -local_port $local_port -loglevel $loglevel > $config_file - ln_start_bin "$(first_type $(config_t_get global_app trojan_go_file) trojan-go)" trojan-go $log_file -config "$config_file" - ;; - trojan*) - local loglevel=$(config_t_get global trojan_loglevel "2") - lua $API_GEN_TROJAN -node $node -run_type nat -local_addr "0.0.0.0" -local_port $local_port -loglevel $loglevel > $config_file - ln_start_bin "$(first_type ${type})" "${type}" $log_file -c "$config_file" - ;; - naiveproxy) - lua $API_GEN_NAIVE -node $node -run_type redir -local_addr "0.0.0.0" -local_port $local_port > $config_file - ln_start_bin "$(first_type naive)" naive $log_file "$config_file" - ;; - brook) - local server_ip=$server_host - local protocol=$(config_n_get $node protocol client) - local brook_tls=$(config_n_get $node brook_tls 0) - if [ "$protocol" == "wsclient" ]; then - [ "$brook_tls" == "1" ] && server_ip="wss://${server_ip}" || server_ip="ws://${server_ip}" - socks_port=$(get_new_port 2081 tcp) - ln_start_bin "$(first_type $(config_t_get global_app brook_file) brook)" "brook_tcp" $log_file wsclient --socks5 "127.0.0.1:$socks_port" -s "$server_ip:$port" -p "$(config_n_get $node password)" - _socks_flag=1 - _socks_address="127.0.0.1" - _socks_port=$socks_port - echolog "Brook的WebSocket不支持透明代理,将使用ipt2socks转换透明代理!" - [ "$UDP_NODE" == "tcp" ] && echolog "Brook的WebSocket不支持UDP转发!" - else - [ "$kcptun_use" == "1" ] && { - server_ip=127.0.0.1 - port=$KCPTUN_REDIR_PORT - } - ln_start_bin "$(first_type $(config_t_get global_app brook_file) brook)" "brook_tcp" $log_file tproxy -l ":$local_port" -s "$server_ip:$port" -p "$(config_n_get $node password)" - fi - ;; - ss|ssr) - ss_program="$(first_type ${type}local ${type}-redir)" - [ "$(printf '%s' "$ss_program" | awk -F '/' '{print $NF}')" = "${type}local" ] && \ - ss_extra_arg="--protocol redir" - if [ "$kcptun_use" == "1" ]; then - lua $API_GEN_SS -node $node -local_addr "0.0.0.0" -local_port $local_port -server_host "127.0.0.1" -server_port $KCPTUN_REDIR_PORT > $config_file - [ "$UDP_NODE" == "tcp" ] && echolog "Kcptun不支持UDP转发!" - else - lua $API_GEN_SS -node $node -local_addr "0.0.0.0" -local_port $local_port > $config_file - [ "$UDP_NODE" == "tcp" ] && ss_extra_arg="$ss_extra_arg -u" - fi - ln_start_bin "$ss_program" "${type}-redir" $log_file -c "$config_file" -v $ss_extra_arg - ;; - esac - if [ -n "$_socks_flag" ]; then - local extra_param="-T" - [ "$UDP_NODE" == "tcp" ] && extra_param="" - ln_start_bin "$(first_type ipt2socks)" "ipt2socks_tcp" $log_file -l "$local_port" -b 0.0.0.0 -s "$_socks_address" -p "$_socks_port" -R -v $extra_param - fi - unset _socks_flag _socks_address _socks_port _socks_username _socks_password - - [ "$type" != "xray" ] && { - [ "$tcp_node_socks" = "1" ] && { - local port=$tcp_node_socks_port - local config_file=$TMP_PATH/SOCKS_$tcp_node_socks_id.json - local log_file=$TMP_PATH/SOCKS_$tcp_node_socks_id.log - local http_port=0 - local http_config_file=$TMP_PATH/HTTP2SOCKS_$tcp_node_http_id.json - [ "$tcp_node_http" = "1" ] && { - http_port=$tcp_node_http_port - } - run_socks TCP $node "0.0.0.0" $port $config_file $http_port $http_config_file - } - } - ;; - esac - return 0 -} - -node_switch() { - [ -n "$1" -a -n "$2" ] && { - local node=$2 - top -bn1 | grep -E "$TMP_PATH" | grep -i "${1}" | grep -v "grep" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 - local config_file=$TMP_PATH/${1}.json - local log_file=$TMP_PATH/${1}.log - eval current_port=\$${1}_REDIR_PORT - local port=$(cat $TMP_PORT_PATH/${1}) - - local ids=$(uci show $CONFIG | grep "=socks" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}') - for id in $ids; do - [ "$(config_n_get $id enabled 0)" == "0" ] && continue - [ "$(config_n_get $id node nil)" != "tcp" ] && continue - local socks_port=$(config_n_get $id port) - local http_port=$(config_n_get $id http_port 0) - top -bn1 | grep -E "$TMP_PATH" | grep -i "SOCKS" | grep "$id" | grep -v "grep" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 - tcp_node_socks=1 - tcp_node_socks_port=$socks_port - tcp_node_socks_id=$id - [ "$http_port" != "0" ] && { - tcp_node_http=1 - tcp_node_http_port=$http_port - tcp_node_http_id=$id - } - break - done - - run_redir $node "0.0.0.0" $port $config_file $1 $log_file - echo $node > $TMP_ID_PATH/${1} - - [ "$1" = "TCP" ] && { - [ "$(config_t_get global udp_node nil)" = "tcp_" ] && { - top -bn1 | grep -E "$TMP_PATH" | grep -i "UDP" | grep -v "grep" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 - UDP_NODE=$node - start_redir UDP - } - } - - #local node_net=$(echo $1 | tr 'A-Z' 'a-z') - #uci set $CONFIG.@global[0].${node_net}_node=$node - #uci commit $CONFIG - restart_dnsmasq - } -} - -start_redir() { - eval node=\$${1}_NODE - [ "$node" != "nil" ] && { - TYPE=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z') - local config_file=$TMP_PATH/${1}.json - local log_file=$TMP_PATH/${1}.log - eval current_port=\$${1}_REDIR_PORT - local port=$(echo $(get_new_port $current_port $1)) - eval ${1}_REDIR=$port - run_redir $node "0.0.0.0" $port $config_file $1 $log_file - #eval ip=\$${1}_NODE_IP - echo $node > $TMP_ID_PATH/${1} - echo $port > $TMP_PORT_PATH/${1} - } -} - -start_socks() { - local ids=$(uci show $CONFIG | grep "=socks" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}') - echolog "分析 Socks 服务的节点配置..." - for id in $ids; do - local enabled=$(config_n_get $id enabled 0) - [ "$enabled" == "0" ] && continue - local node=$(config_n_get $id node nil) - [ "$node" == "nil" ] && continue - local port=$(config_n_get $id port) - local config_file=$TMP_PATH/SOCKS_${id}.json - local log_file=$TMP_PATH/SOCKS_${id}.log - local http_port=$(config_n_get $id http_port 0) - local http_config_file=$TMP_PATH/HTTP2SOCKS_${id}.json - [ "$node" == "tcp" ] && { - tcp_node_socks=1 - tcp_node_socks_port=$port - tcp_node_socks_id=$id - [ "$http_port" != "0" ] && { - tcp_node_http=1 - tcp_node_http_port=$http_port - tcp_node_http_id=$id - } - continue - } - run_socks $id $node "0.0.0.0" $port $config_file $http_port $http_config_file - done -} - -clean_log() { - logsnum=$(cat $LOG_FILE 2>/dev/null | wc -l) - [ "$logsnum" -gt 1000 ] && { - echo "" > $LOG_FILE - echolog "日志文件过长,清空处理!" - } -} - -clean_crontab() { - touch /etc/crontabs/root - #sed -i "/${CONFIG}/d" /etc/crontabs/root >/dev/null 2>&1 - sed -i "/$(echo "/etc/init.d/${CONFIG}" | sed 's#\/#\\\/#g')/d" /etc/crontabs/root >/dev/null 2>&1 - sed -i "/$(echo "lua ${APP_PATH}/rule_update.lua log" | sed 's#\/#\\\/#g')/d" /etc/crontabs/root >/dev/null 2>&1 - sed -i "/$(echo "lua ${APP_PATH}/subscribe.lua start log" | sed 's#\/#\\\/#g')/d" /etc/crontabs/root >/dev/null 2>&1 -} - -start_crontab() { - clean_crontab - auto_on=$(config_t_get global_delay auto_on 0) - if [ "$auto_on" = "1" ]; then - time_off=$(config_t_get global_delay time_off) - time_on=$(config_t_get global_delay time_on) - time_restart=$(config_t_get global_delay time_restart) - [ -z "$time_off" -o "$time_off" != "nil" ] && { - echo "0 $time_off * * * /etc/init.d/$CONFIG stop" >>/etc/crontabs/root - echolog "配置定时任务:每天 $time_off 点关闭服务。" - } - [ -z "$time_on" -o "$time_on" != "nil" ] && { - echo "0 $time_on * * * /etc/init.d/$CONFIG start" >>/etc/crontabs/root - echolog "配置定时任务:每天 $time_on 点开启服务。" - } - [ -z "$time_restart" -o "$time_restart" != "nil" ] && { - echo "0 $time_restart * * * /etc/init.d/$CONFIG restart" >>/etc/crontabs/root - echolog "配置定时任务:每天 $time_restart 点重启服务。" - } - fi - [ "$NO_PROXY" == 1 ] && { - echolog "运行于非代理模式,仅允许服务启停的定时任务。" - /etc/init.d/cron restart - return - } - - autoupdate=$(config_t_get global_rules auto_update) - weekupdate=$(config_t_get global_rules week_update) - dayupdate=$(config_t_get global_rules time_update) - if [ "$autoupdate" = "1" ]; then - local t="0 $dayupdate * * $weekupdate" - [ "$weekupdate" = "7" ] && t="0 $dayupdate * * *" - echo "$t lua $APP_PATH/rule_update.lua log > /dev/null 2>&1 &" >>/etc/crontabs/root - echolog "配置定时任务:自动更新规则。" - fi - - autoupdatesubscribe=$(config_t_get global_subscribe auto_update_subscribe) - weekupdatesubscribe=$(config_t_get global_subscribe week_update_subscribe) - dayupdatesubscribe=$(config_t_get global_subscribe time_update_subscribe) - if [ "$autoupdatesubscribe" = "1" ]; then - local t="0 $dayupdatesubscribe * * $weekupdatesubscribe" - [ "$weekupdatesubscribe" = "7" ] && t="0 $dayupdatesubscribe * * *" - echo "$t lua $APP_PATH/subscribe.lua start log > /dev/null 2>&1 &" >>/etc/crontabs/root - echolog "配置定时任务:自动更新节点订阅。" - fi - - start_daemon=$(config_t_get global_delay start_daemon 0) - [ "$start_daemon" = "1" ] && $APP_PATH/monitor.sh > /dev/null 2>&1 & - - AUTO_SWITCH_ENABLE=$(config_t_get auto_switch enable 0) - [ "$AUTO_SWITCH_ENABLE" = "1" ] && $APP_PATH/test.sh > /dev/null 2>&1 & - - /etc/init.d/cron restart -} - -stop_crontab() { - clean_crontab - /etc/init.d/cron restart - #echolog "清除定时执行命令。" -} - -start_dns() { - local pdnsd_forward other_port msg - dns_listen_port=${DNS_PORT} - pdnsd_forward=${DNS_FORWARD} - - china_ng_listen_port=$(expr $dns_listen_port + 1) - china_ng_listen="127.0.0.1#${china_ng_listen_port}" - china_ng_chn=$(echo -n $(echo "${LOCAL_DNS}" | sed "s/,/\n/g" | head -n2) | tr " " ",") - china_ng_gfw="127.0.0.1#${dns_listen_port}" - [ -n "${returnhome}" ] && china_ng_chn="${china_ng_gfw}" && china_ng_gfw="${LOCAL_DNS}" - - echolog "过滤服务配置:准备接管域名解析..." - - case "$DNS_MODE" in - nonuse) - echolog " - 不过滤DNS..." - TUN_DNS="" - use_chinadns_ng=$(config_t_get global always_use_chinadns_ng 0) - [ "$use_chinadns_ng" == "0" ] && return - ;; - dns2socks) - local dns2socks_socks_server=$(echo $(config_t_get global socks_server 127.0.0.1:9050) | sed "s/#/:/g") - local dns2socks_forward=$(get_first_dns DNS_FORWARD 53 | sed 's/#/:/g') - [ "$DNS_CACHE" == "0" ] && local dns2sock_cache="/d" - ln_start_bin "$(first_type dns2socks)" dns2socks "/dev/null" "$dns2socks_socks_server" "$dns2socks_forward" "127.0.0.1:$dns_listen_port" $dns2sock_cache - echolog " - dns2sock(127.0.0.1:${dns_listen_port}${dns2sock_cache}),${dns2socks_socks_server:-127.0.0.1:9050} -> ${dns2socks_forward-D8.8.8.8:53}" - echolog " - 域名解析:dns2socks..." - ;; - xray_doh) - up_trust_doh_dns=$(config_t_get global up_trust_doh_dns "tcp") - if [ "$up_trust_doh_dns" = "socks" ]; then - use_tcp_node_resolve_dns=0 - msg="Socks节点" - elif [ "${up_trust_doh_dns}" = "tcp" ]; then - use_tcp_node_resolve_dns=1 - msg="TCP节点" - fi - up_trust_doh=$(config_t_get global up_trust_doh "https://dns.google/dns-query,8.8.4.4") - _doh_url=$(echo $up_trust_doh | awk -F ',' '{print $1}') - _doh_host_port=$(echo $_doh_url | sed "s/https:\/\///g" | awk -F '/' '{print $1}') - _doh_host=$(echo $_doh_host_port | awk -F ':' '{print $1}') - _doh_port=$(echo $_doh_host_port | awk -F ':' '{print $2}') - _doh_bootstrap=$(echo $up_trust_doh | cut -d ',' -sf 2-) - - up_trust_doh_dns=$(config_t_get global up_trust_doh_dns "tcp") - if [ "$up_trust_doh_dns" = "socks" ]; then - socks_server=$(echo $(config_t_get global socks_server 127.0.0.1:9050) | sed "s/#/:/g") - socks_address=$(echo $socks_server | awk -F ':' '{print $1}') - socks_port=$(echo $socks_server | awk -F ':' '{print $2}') - lua $API_GEN_XRAY -dns_listen_port "${dns_listen_port}" -dns_server "${_doh_bootstrap}" -doh_url "${_doh_url}" -doh_host "${_doh_host}" -doh_socks_address "${socks_address}" -doh_socks_port "${socks_port}" > $TMP_PATH/DNS.json - ln_start_bin "$(first_type $(config_t_get global_app xray_file) xray)" xray $TMP_PATH/DNS.log -config="$TMP_PATH/DNS.json" - elif [ "${up_trust_doh_dns}" = "tcp" ]; then - DNS_FORWARD="" - _doh_bootstrap_dns=$(echo $_doh_bootstrap | sed "s/,/ /g") - for _dns in $_doh_bootstrap_dns; do - _dns=$(echo $_dns | awk -F ':' '{print $1}'):${_doh_port:-443} - [ -n "$DNS_FORWARD" ] && DNS_FORWARD=${DNS_FORWARD},${_dns} || DNS_FORWARD=${_dns} - done - lua $API_GEN_XRAY -dns_listen_port "${dns_listen_port}" -dns_server "${_doh_bootstrap}" -doh_url "${_doh_url}" -doh_host "${_doh_host}" > $TMP_PATH/DNS.json - ln_start_bin "$(first_type $(config_t_get global_app xray_file) xray)" xray $TMP_PATH/DNS.log -config="$TMP_PATH/DNS.json" - unset _dns _doh_bootstrap_dns - fi - unset _doh_url _doh_port _doh_bootstrap - echolog " - 域名解析 Xray DNS(DoH)..." - ;; - pdnsd) - gen_pdnsd_config "${dns_listen_port}" "${pdnsd_forward}" - ln_start_bin "$(first_type pdnsd)" pdnsd "/dev/null" --daemon -c "${TMP_PATH}/pdnsd/pdnsd.conf" -d - echolog " - 域名解析:pdnsd + 使用(TCP节点)解析域名..." - ;; - udp) - use_udp_node_resolve_dns=1 - TUN_DNS=${DNS_FORWARD} - echolog " - 域名解析:直接使用UDP节点请求DNS($TUN_DNS)" - ;; - fake_ip) - TUN_DNS="11.1.1.1" - echolog " - 域名解析:使用FakeIP方案..." - ;; - custom) - custom_dns=$(config_t_get global custom_dns) - TUN_DNS="$(echo ${custom_dns} | sed 's/:/#/g')" - echolog " - 域名解析:使用UDP协议自定义DNS($TUN_DNS)解析..." - ;; - esac - - [ -n "$chnlist" ] && [ "$DNS_MODE" != "custom" ] && [ "$DNS_MODE" != "fake_ip" ] && { - [ -n "$(first_type chinadns-ng)" ] && { - echolog "发现ChinaDNS-NG,将启动。" - CHINADNS_NG=1 - } - [ -n "$CHINADNS_NG" ] && { - echolog " | - (chinadns-ng) 只支持2~4级的域名过滤..." - if [ "$DNS_MODE" = "pdnsd" ]; then - msg="pdnsd" - elif [ "$DNS_MODE" = "dns2socks" ]; then - msg="dns2socks" - elif [ "$DNS_MODE" = "xray_doh" ]; then - msg="Xray DNS(DoH)" - elif [ "$DNS_MODE" = "udp" ]; then - use_udp_node_resolve_dns=1 - china_ng_gfw="${DNS_FORWARD}" - msg="udp" - elif [ "$DNS_MODE" = "custom" ]; then - custom_dns=$(config_t_get global custom_dns) - china_ng_gfw="$(echo ${custom_dns} | sed 's/:/#/g')" - msg="自定义DNS" - fi - - local gfwlist_param="${TMP_PATH}/chinadns_gfwlist" - [ -f "${RULES_PATH}/gfwlist" ] && cp -a "${RULES_PATH}/gfwlist" "${gfwlist_param}" - local chnlist_param="${TMP_PATH}/chinadns_chnlist" - [ -f "${RULES_PATH}/chnlist" ] && cp -a "${RULES_PATH}/chnlist" "${chnlist_param}" - - [ -f "${RULES_PATH}/proxy_host" ] && { - cat "${RULES_PATH}/proxy_host" >> "${gfwlist_param}" - echolog " | - [$?](chinadns-ng) 代理域名表合并到防火墙域名表" - } - [ -f "${RULES_PATH}/direct_host" ] && { - cat "${RULES_PATH}/direct_host" >> "${chnlist_param}" - echolog " | - [$?](chinadns-ng) 域名白名单合并到中国域名表" - } - chnlist_param=${chnlist_param:+-m "${chnlist_param}" -M} - ln_start_bin "$(first_type chinadns-ng)" chinadns-ng "${TMP_PATH}/chinadns-ng.log" -v -b 0.0.0.0 -l "${china_ng_listen_port}" ${china_ng_chn:+-c "${china_ng_chn}"} ${chnlist_param} ${china_ng_gfw:+-t "${china_ng_gfw}"} ${gfwlist_param:+-g "${gfwlist_param}"} -f - echolog " + 过滤服务:ChinaDNS-NG(:${china_ng_listen_port}) + ${msg}:国内DNS:${china_ng_chn:-D114.114.114.114},可信DNS:${china_ng_gfw:-D8.8.8.8}" - #[ -n "${global}${chnlist}" ] && [ -z "${returnhome}" ] && TUN_DNS="${china_ng_gfw}" - } - } - - [ "${use_udp_node_resolve_dns}" = "1" ] && echolog " * 要求代理 DNS 请求,如上游 DNS 非直连地址,确保 UDP 代理打开,并且已经正确转发!" - [ "${use_tcp_node_resolve_dns}" = "1" ] && echolog " * 请确认上游 DNS 支持 TCP 查询,如非直连地址,确保 TCP 代理打开,并且已经正确转发!" -} - -add_dnsmasq() { - local fwd_dns items item servers msg - - mkdir -p "${TMP_DNSMASQ_PATH}" "${DNSMASQ_PATH}" "/var/dnsmasq.d" - [ "$(config_t_get global_rules adblock 0)" = "1" ] && { - ln -s "${RULES_PATH}/adblock.conf" "${TMP_DNSMASQ_PATH}/adblock.conf" - echolog " - [$?]广告域名表中域名解析请求直接应答为 '0.0.0.0'" - } - - if [ "${DNS_MODE}" = "nonuse" ]; then - echolog " - 不对域名进行分流解析" - else - #屏蔽列表 - sort -u "${RULES_PATH}/block_host" | gen_dnsmasq_fake_items "0.0.0.0" "${TMP_DNSMASQ_PATH}/00-block_host.conf" - - #始终用国内DNS解析节点域名 - fwd_dns="${LOCAL_DNS}" - servers=$(uci show "${CONFIG}" | grep ".address=" | cut -d "'" -f 2) - hosts_foreach "servers" host_from_url | grep -v "google.c" | grep '[a-zA-Z]$' | sort -u | gen_dnsmasq_items "vpsiplist,vpsiplist6" "${fwd_dns}" "${TMP_DNSMASQ_PATH}/10-vpsiplist_host.conf" - echolog " - [$?]节点列表中的域名(vpsiplist):${fwd_dns:-默认}" - - #始终用国内DNS解析直连(白名单)列表 - [ -f "${RULES_PATH}/direct_host" ] && { - fwd_dns="${LOCAL_DNS}" - [ -n "$CHINADNS_NG" ] && unset fwd_dns - sort -u "${RULES_PATH}/direct_host" | gen_dnsmasq_items "whitelist,whitelist6" "${fwd_dns}" "${TMP_DNSMASQ_PATH}/11-direct_host.conf" - echolog " - [$?]域名白名单(whitelist):${fwd_dns:-默认}" - } - - if [ "$(config_t_get global_subscribe subscribe_proxy 0)" = "0" ]; then - #如果没有开启通过代理订阅 - fwd_dns="${LOCAL_DNS}" - for item in $(get_enabled_anonymous_secs "@subscribe_list"); do - host_from_url "$(config_n_get ${item} url)" | gen_dnsmasq_items "whitelist,whitelist6" "${fwd_dns}" "${TMP_DNSMASQ_PATH}/12-subscribe.conf" - done - echolog " - [$?]节点订阅域名(whitelist):${fwd_dns:-默认}" - else - #如果开启了通过代理订阅 - fwd_dns="${TUN_DNS}" - [ -n "$CHINADNS_NG" ] && fwd_dns="${china_ng_gfw}" - for item in $(get_enabled_anonymous_secs "@subscribe_list"); do - if [ "${DNS_MODE}" = "fake_ip" ]; then - host_from_url "$(config_n_get ${item} url)" | gen_dnsmasq_fake_items "11.1.1.1" "${TMP_DNSMASQ_PATH}/91-subscribe.conf" - else - host_from_url "$(config_n_get ${item} url)" | gen_dnsmasq_items "blacklist,blacklist6" "${fwd_dns}" "${TMP_DNSMASQ_PATH}/91-subscribe.conf" - fi - done - [ "${DNS_MODE}" != "fake_ip" ] && echolog " - [$?]节点订阅域名(blacklist):${fwd_dns:-默认}" - fi - - #始终使用远程DNS解析代理(黑名单)列表 - [ -f "${RULES_PATH}/proxy_host" ] && { - if [ "${DNS_MODE}" = "fake_ip" ]; then - sort -u "${RULES_PATH}/proxy_host" | gen_dnsmasq_fake_items "11.1.1.1" "${TMP_DNSMASQ_PATH}/97-proxy_host.conf" - else - fwd_dns="${TUN_DNS}" - [ -n "$CHINADNS_NG" ] && fwd_dns="${china_ng_gfw}" - [ -n "$CHINADNS_NG" ] && unset fwd_dns - sort -u "${RULES_PATH}/proxy_host" | gen_dnsmasq_items "blacklist,blacklist6" "${fwd_dns}" "${TMP_DNSMASQ_PATH}/97-proxy_host.conf" - echolog " - [$?]代理域名表(blacklist):${fwd_dns:-默认}" - fi - } - - #分流规则 - [ "$(config_n_get $TCP_NODE protocol)" = "_shunt" ] && { - fwd_dns="${TUN_DNS}" - local default_node_id=$(config_n_get $TCP_NODE default_node _direct) - local shunt_ids=$(uci show $CONFIG | grep "=shunt_rules" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}') - for shunt_id in $shunt_ids; do - local shunt_node_id=$(config_n_get $TCP_NODE ${shunt_id} nil) - if [ "$shunt_node_id" = "nil" ] || [ "$shunt_node_id" = "_default" ] || [ "$shunt_node_id" = "_direct" ] || [ "$shunt_node_id" = "_blackhole" ]; then - continue - fi - local shunt_node=$(config_n_get $shunt_node_id address nil) - [ "$shunt_node" = "nil" ] && continue - if [ "${DNS_MODE}" = "fake_ip" ]; then - config_n_get $shunt_id domain_list | grep -v 'regexp:\|geosite:\|ext:' | sed 's/domain:\|full:\|//g' | tr -s "\r\n" "\n" | sort -u | gen_dnsmasq_fake_items "11.1.1.1" "${TMP_DNSMASQ_PATH}/98-shunt_host.conf" - else - config_n_get $shunt_id domain_list | grep -v 'regexp:\|geosite:\|ext:' | sed 's/domain:\|full:\|//g' | tr -s "\r\n" "\n" | sort -u | gen_dnsmasq_items "shuntlist,shuntlist6" "${fwd_dns}" "${TMP_DNSMASQ_PATH}/98-shunt_host.conf" - fi - done - [ "${DNS_MODE}" != "fake_ip" ] && echolog " - [$?]Xray分流规则(shuntlist):${fwd_dns:-默认}" - } - - #如果没有使用回国模式 - if [ -z "${returnhome}" ]; then - [ -f "${RULES_PATH}/gfwlist" ] && { - if [ -n "$count_hosts_str" ]; then - grep -v -E "$count_hosts_str" "${RULES_PATH}/gfwlist" > "${TMP_PATH}/gfwlist" - else - cp -a "${RULES_PATH}/gfwlist" "${TMP_PATH}/gfwlist" - fi - } - if [ "${DNS_MODE}" = "fake_ip" ]; then - sort -u "${TMP_PATH}/gfwlist" | gen_dnsmasq_fake_items "11.1.1.1" "${TMP_DNSMASQ_PATH}/99-gfwlist.conf" - else - fwd_dns="${TUN_DNS}" - [ -n "$CHINADNS_NG" ] && fwd_dns="${china_ng_gfw}" - [ -n "$CHINADNS_NG" ] && unset fwd_dns - sort -u "${TMP_PATH}/gfwlist" | gen_dnsmasq_items "gfwlist,gfwlist6" "${fwd_dns}" "${TMP_DNSMASQ_PATH}/99-gfwlist.conf" - echolog " - [$?]防火墙域名表(gfwlist):${fwd_dns:-默认}" - rm -f "${TMP_PATH}/gfwlist" - fi - # Not China List 模式 - [ -n "${chnlist}" ] && { - fwd_dns="${LOCAL_DNS}" - [ -n "$CHINADNS_NG" ] && unset fwd_dns - [ -f "${RULES_PATH}/chnlist" ] && { - if [ -n "$count_hosts_str" ]; then - grep -v -E "$count_hosts_str" "${RULES_PATH}/chnlist" | gen_dnsmasq_items "chnroute,chnroute6" "${fwd_dns}" "${TMP_DNSMASQ_PATH}/19-chinalist_host.conf" - else - sort -u "${RULES_PATH}/chnlist" | gen_dnsmasq_items "chnroute,chnroute6" "${fwd_dns}" "${TMP_DNSMASQ_PATH}/19-chinalist_host.conf" - fi - echolog " - [$?]中国域名表(chnroute):${fwd_dns:-默认}" - } - } - else - #回国模式 - [ -f "${RULES_PATH}/chnlist" ] && { - if [ -n "$count_hosts_str" ]; then - grep -v -E "$count_hosts_str" "${RULES_PATH}/chnlist" > "${TMP_PATH}/chnlist" - else - cp -a "${RULES_PATH}/chnlist" "${TMP_PATH}/chnlist" - fi - } - if [ "${DNS_MODE}" = "fake_ip" ]; then - [ -f "${TMP_PATH}/chnlist" ] && sort -u "${TMP_PATH}/chnlist" | gen_dnsmasq_fake_items "11.1.1.1" "${TMP_DNSMASQ_PATH}/99-chinalist_host.conf" - else - fwd_dns="${TUN_DNS}" - [ -f "${TMP_PATH}/chnlist" ] && sort -u "${TMP_PATH}/chnlist" | gen_dnsmasq_items "chnroute,chnroute6" "${fwd_dns}" "${TMP_DNSMASQ_PATH}/99-chinalist_host.conf" - echolog " - [$?]中国域名表(chnroute):${fwd_dns:-默认}" - fi - rm -f "${TMP_PATH}/chnlist" - fi - - #awk '{gsub(/ipset=\//,""); gsub(/\//," ");key=$1;value=$2;if (sum[key] != "") {sum[key]=sum[key]","value} else {sum[key]=sum[key]value}} END{for(i in sum) print "ipset=/"i"/"sum[i]}' "${TMP_DNSMASQ_PATH}/ipset.conf" > "${TMP_DNSMASQ_PATH}/ipset.conf2" - #mv -f "${TMP_DNSMASQ_PATH}/ipset.conf2" "${TMP_DNSMASQ_PATH}/ipset.conf" - fi - if [ "${DNS_MODE}" != "nouse" ]; then - echo "conf-dir=${TMP_DNSMASQ_PATH}" > "/var/dnsmasq.d/dnsmasq-${CONFIG}.conf" - - if [ -z "${CHINADNS_NG}" ] && [ "${IS_DEFAULT_DNS}" = "1" ]; then - #echolog " - 不强制设置默认DNS" - return - else - echo "${DEFAULT_DNS}" > $TMP_PATH/default_DNS - msg="ISP" - servers="${LOCAL_DNS}" - [ -n "${chnlist}" ] && msg="中国列表以外" - [ -n "${returnhome}" ] && msg="中国列表" - [ -n "${global}" ] && msg="全局" - - #默认交给Chinadns-ng处理 - [ -n "$CHINADNS_NG" ] && { - servers="${china_ng_listen}" && msg="chinadns-ng" - } - - cat <<-EOF >> "/var/dnsmasq.d/dnsmasq-${CONFIG}.conf" - $(echo "${servers}" | sed 's/,/\n/g' | gen_dnsmasq_items) - all-servers - no-poll - no-resolv - EOF - echolog " - [$?]以上所列以外及默认(${msg}):${servers}" - fi - fi -} - -gen_pdnsd_config() { - local listen_port=${1} - local up_dns=${2} - local pdnsd_dir=${TMP_PATH}/pdnsd - local perm_cache=2048 - local _cache="on" - local query_method="tcp_only" - - mkdir -p "${pdnsd_dir}" - touch "${pdnsd_dir}/pdnsd.cache" - chown -R root.nogroup "${pdnsd_dir}" - if [ "${use_udp_node_resolve_dns}" = "1" ]; then - query_method="udp_only" - else - use_tcp_node_resolve_dns=1 - fi - [ "${DNS_CACHE}" = "0" ] && _cache="off" && perm_cache=0 - cat > "${pdnsd_dir}/pdnsd.conf" <<-EOF - global { - perm_cache = $perm_cache; - cache_dir = "$pdnsd_dir"; - run_as = "root"; - server_ip = 127.0.0.1; - server_port = ${listen_port}; - status_ctl = on; - query_method = ${query_method}; - min_ttl = 1h; - max_ttl = 1w; - timeout = 10; - par_queries = 2; - neg_domain_pol = on; - udpbufsize = 1024; - proc_limit = 2; - procq_limit = 8; - } - - EOF - echolog " + [$?]Pdnsd (127.0.0.1:${listen_port})..." - - append_pdnsd_updns() { - [ -z "${2}" ] && echolog " | - 略过错误 : ${1}" && return 0 - cat >> $pdnsd_dir/pdnsd.conf <<-EOF - server { - label = "node-${2}_${3}"; - ip = ${2}; - edns_query = on; - port = ${3}; - timeout = 4; - interval = 10m; - uptest = none; - purge_cache = off; - proxy_only = on; - caching = $_cache; - reject = ::/0; - reject_policy = negate; - } - EOF - echolog " | - [$?]上游DNS:${2}:${3}" - } - hosts_foreach up_dns append_pdnsd_updns 53 -} - -del_dnsmasq() { - rm -rf /var/dnsmasq.d/dnsmasq-$CONFIG.conf - rm -rf $DNSMASQ_PATH/dnsmasq-$CONFIG.conf - rm -rf $TMP_DNSMASQ_PATH -} - -add_ip2route() { - local ip=$(get_host_ip "ipv4" $1) - [ -z "$ip" ] && { - echolog " - 无法解析${1},路由表添加失败!" - return 1 - } - local remarks="${1}" - [ "$remarks" != "$ip" ] && remarks="${1}(${ip})" - local interface=$2 - local retries=5 - local failcount=0 - while [ "$failcount" -lt $retries ]; do - unset msg - ip route show dev ${interface} >/dev/null 2>&1 - if [ $? -ne 0 ]; then - let "failcount++" - echolog " - 找不到出口接口:$interface,1分钟后再重试(${failcount}/${retries}),${ip}" - [ "$failcount" -ge $retries ] && return 1 - sleep 1m - else - route add -host ${ip} dev ${interface} >/dev/null 2>&1 - echolog " - ${remarks}添加路由表${interface}接口成功!" - echo "$ip" >> $TMP_ROUTE_PATH/${interface} - break - fi - done -} - -delete_ip2route() { - [ -d "${TMP_ROUTE_PATH}" ] && { - for interface in $(ls ${TMP_ROUTE_PATH}); do - for ip in $(cat ${TMP_ROUTE_PATH}/${interface}); do - route del -host ${ip} dev ${interface} >/dev/null 2>&1 - done - done - } -} - -start_haproxy() { - local haproxy_path haproxy_file item items lport sort_items - - [ "$(config_t_get global_haproxy balancing_enable 0)" != "1" ] && return - echolog "HAPROXY 负载均衡..." - - haproxy_path=${TMP_PATH}/haproxy - mkdir -p "${haproxy_path}" - haproxy_file=${haproxy_path}/config.cfg - cat <<-EOF > "${haproxy_file}" - global - log 127.0.0.1 local2 - chroot ${haproxy_path} - maxconn 60000 - stats socket ${haproxy_path}/haproxy.sock - daemon - - defaults - mode tcp - log global - option tcplog - option dontlognull - option http-server-close - #option forwardfor except 127.0.0.0/8 - option redispatch - retries 2 - timeout http-request 10s - timeout queue 1m - timeout connect 10s - timeout client 1m - timeout server 1m - timeout http-keep-alive 10s - timeout check 10s - maxconn 3000 - - EOF - - items=$(get_enabled_anonymous_secs "@haproxy_config") - for item in $items; do - lport=$(config_n_get ${item} haproxy_port 0) - [ "${lport}" = "0" ] && echolog " - 丢弃1个明显无效的节点" && continue - sort_items="${sort_items}${IFS}${lport} ${item}" - done - - items=$(echo "${sort_items}" | sort -n | cut -d ' ' -sf 2) - - unset lport - local haproxy_port lbss lbort lbweight export backup - local msg bip bport hasvalid bbackup failcount interface - for item in ${items}; do - unset haproxy_port lbort bbackup - - eval $(uci -q show "${CONFIG}.${item}" | cut -d '.' -sf 3-) - get_ip_port_from "$lbss" bip bport - - [ "$lbort" = "default" ] && lbort=$bport || bport=$lbort - [ -z "$haproxy_port" ] || [ -z "$bip" ] || [ -z "$lbort" ] && echolog " - 丢弃1个明显无效的节点" && continue - [ "$backup" = "1" ] && bbackup="backup" - - [ "$lport" = "${haproxy_port}" ] || { - hasvalid="1" - lport=${haproxy_port} - echolog " + 入口 0.0.0.0:${lport}..." - cat <<-EOF >> "${haproxy_file}" - listen $lport - mode tcp - bind 0.0.0.0:$lport - EOF - } - - cat <<-EOF >> "${haproxy_file}" - server $bip:$bport $bip:$bport weight $lbweight check inter 1500 rise 1 fall 3 $bbackup - EOF - - if [ "$export" != "0" ]; then - add_ip2route ${bip} ${export} > /dev/null 2>&1 & - fi - echolog " | - 出口节点:${bip}:${bport},权重:${lbweight}" - done - - # 控制台配置 - local console_port=$(config_t_get global_haproxy console_port) - local console_user=$(config_t_get global_haproxy console_user) - local console_password=$(config_t_get global_haproxy console_password) - local auth="" - [ -n "$console_user" ] && [ -n "$console_password" ] && auth="stats auth $console_user:$console_password" - cat <<-EOF >> "${haproxy_file}" - - listen console - bind 0.0.0.0:$console_port - mode http - stats refresh 30s - stats uri / - stats admin if TRUE - $auth - EOF - - [ "${hasvalid}" != "1" ] && echolog " - 没有发现任何有效节点信息,不启动。" && return 0 - ln_start_bin "$(first_type haproxy)" haproxy "/dev/null" -f "${haproxy_file}" - echolog " * 控制台端口:${console_port}/,${auth:-公开}" -} - -kill_all() { - kill -9 $(pidof "$@") >/dev/null 2>&1 -} - -force_stop() { - stop - exit 0 -} - -backup_dnsmasq_servers() { - DNSMASQ_DNS=$(uci show dhcp | grep "@dnsmasq" | grep ".server=" | awk -F '=' '{print $2}' | sed "s/'//g" | tr ' ' ',') - if [ -n "${DNSMASQ_DNS}" ]; then - uci -q set $CONFIG.@global[0].dnsmasq_servers="${DNSMASQ_DNS}" - uci commit $CONFIG - fi -} - -restore_dnsmasq_servers() { - OLD_SERVER=$(uci -q get $CONFIG.@global[0].dnsmasq_servers | tr "," " ") - for server in $OLD_SERVER; do - uci -q del_list dhcp.@dnsmasq[0].server=$server - uci add_list dhcp.@dnsmasq[0].server=$server - done - uci commit dhcp - uci -q delete $CONFIG.@global[0].dnsmasq_servers - uci commit $CONFIG -} - -restart_dnsmasq() { - if [ -f "$TMP_PATH/default_DNS" ]; then - backup_dnsmasq_servers - sed -i "/list server/d" /etc/config/dhcp >/dev/null 2>&1 - /etc/init.d/dnsmasq restart >/dev/null 2>&1 - restore_dnsmasq_servers - else - /etc/init.d/dnsmasq restart >/dev/null 2>&1 - fi -} - -boot() { - [ "$ENABLED" == 1 ] && { - local delay=$(config_t_get global_delay start_delay 1) - if [ "$delay" -gt 0 ]; then - echolog "执行启动延时 $delay 秒后再启动!" - sleep $delay && start >/dev/null 2>&1 & - else - start - fi - } - return 0 -} - -start() { - #加锁防止并发开启服务 - set_lock - load_config - start_haproxy - [ "$SOCKS_ENABLED" = "1" ] && { - start_socks - } - [ "$NO_PROXY" == 1 ] || { - start_redir TCP - start_redir UDP - start_dns - add_dnsmasq - source $APP_PATH/iptables.sh start - restart_dnsmasq - echolog "重启 dnsmasq 服务[$?]" - } - start_crontab - echolog "运行完成!\n" - unset_lock -} - -stop() { - unlock - set_lock - clean_log - source $APP_PATH/iptables.sh stop - delete_ip2route - kill_all v2ray-plugin obfs-local - top -bn1 | grep -v "grep" | grep "sleep" | grep -E "9s|58s" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 - top -bn1 | grep -v "grep" | grep -v "app.sh" | grep "${CONFIG}/" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 - rm -rf $TMP_DNSMASQ_PATH $TMP_PATH - unset XRAY_LOCATION_ASSET - stop_crontab - del_dnsmasq - /etc/init.d/dnsmasq restart >/dev/null 2>&1 - echolog "重启 dnsmasq 服务[$?]" - echolog "清空并关闭相关程序和缓存完成。" - unset_lock -} - -arg1=$1 -shift -case $arg1 in -get_new_port) - get_new_port $@ - ;; -run_socks) - run_socks $@ - ;; -run_redir) - run_redir $@ - ;; -node_switch) - node_switch $@ - ;; -stop) - [ "$1" = "force" ] && force_stop - stop - ;; -start) - start - ;; -boot) - boot - ;; -esac diff --git a/package/lienol/luci-app-passwall/root/usr/share/passwall/iptables.sh b/package/lienol/luci-app-passwall/root/usr/share/passwall/iptables.sh deleted file mode 100755 index 078c37a8a0..0000000000 --- a/package/lienol/luci-app-passwall/root/usr/share/passwall/iptables.sh +++ /dev/null @@ -1,849 +0,0 @@ -#!/bin/sh - -IPSET_LANIPLIST="laniplist" -IPSET_VPSIPLIST="vpsiplist" -IPSET_SHUNTLIST="shuntlist" -IPSET_GFW="gfwlist" -IPSET_CHN="chnroute" -IPSET_BLACKLIST="blacklist" -IPSET_WHITELIST="whitelist" -IPSET_BLOCKLIST="blocklist" - -IPSET_LANIPLIST6="laniplist6" -IPSET_VPSIPLIST6="vpsiplist6" -IPSET_SHUNTLIST6="shuntlist6" -IPSET_GFW6="gfwlist6" -IPSET_CHN6="chnroute6" -IPSET_BLACKLIST6="blacklist6" -IPSET_WHITELIST6="whitelist6" -IPSET_BLOCKLIST6="blocklist6" - -PROXY_IPV6=0 - -FORCE_INDEX=2 - -ipt_n="iptables -t nat" -ipt_m="iptables -t mangle" -ip6t_m="ip6tables -t mangle" -FWI=$(uci -q get firewall.passwall.path 2>/dev/null) - -factor() { - if [ -z "$1" ] || [ -z "$2" ]; then - echo "" - elif [ "$1" == "1:65535" ]; then - echo "" - else - echo "$2 $1" - fi -} - -dst() { - echo "-m set $2 --match-set $1 dst" -} - -comment() { - local name=$(echo $1 | sed 's/ /_/g') - echo "-m comment --comment '$name'" -} - -destroy_ipset() { - for i in "$@"; do - ipset -q -F $i - ipset -q -X $i - done -} - -RULE_LAST_INDEX() { - [ $# -ge 3 ] || { - echolog "索引列举方式不正确(iptables),终止执行!" - exit 1 - } - local ipt_tmp=${1}; shift - local chain=${1}; shift - local list=${1}; shift - local default=${1:-0}; shift - local _index=$($ipt_tmp -n -L $chain --line-numbers 2>/dev/null | grep "$list" | head -n 1 | awk '{print $1}') - echo "${_index:-${default}}" -} - -REDIRECT() { - local redirect="-j REDIRECT --to-ports $1" - [ "$2" == "TPROXY" ] && redirect="-j TPROXY --tproxy-mark 0x1/0x1 --on-port $1" - [ "$2" == "MARK" ] && redirect="-j MARK --set-mark $1" - echo $redirect -} - -get_redirect_ipt() { - case "$1" in - disable) - echo "-j RETURN" - ;; - global) - echo "$(REDIRECT $2 $3)" - ;; - gfwlist) - echo "$(dst $IPSET_GFW) $(REDIRECT $2 $3)" - ;; - chnroute) - echo "$(dst $IPSET_CHN !) $(REDIRECT $2 $3)" - ;; - returnhome) - echo "$(dst $IPSET_CHN) $(REDIRECT $2 $3)" - ;; - esac -} - -get_redirect_ip6t() { - case "$1" in - disable) - echo "-j RETURN" - ;; - global) - echo "$(REDIRECT $2 $3)" - ;; - gfwlist) - echo "$(dst $IPSET_GFW6) $(REDIRECT $2 $3)" - ;; - chnroute) - echo "$(dst $IPSET_CHN6 !) $(REDIRECT $2 $3)" - ;; - returnhome) - echo "$(dst $IPSET_CHN6) $(REDIRECT $2 $3)" - ;; - esac -} - -get_action_chain_name() { - case "$1" in - disable) - echo "不代理" - ;; - global) - echo "全局代理" - ;; - gfwlist) - echo "防火墙列表" - ;; - chnroute) - echo "中国列表以外" - ;; - returnhome) - echo "中国列表" - ;; - esac -} - -gen_laniplist() { - cat <<-EOF - 0.0.0.0/8 - 10.0.0.0/8 - 100.64.0.0/10 - 127.0.0.0/8 - 169.254.0.0/16 - 172.16.0.0/12 - 192.168.0.0/16 - 224.0.0.0/4 - 240.0.0.0/4 - EOF -} - -gen_laniplist_6() { - cat <<-EOF - ::/128 - ::1/128 - ::ffff:0:0/96 - ::ffff:0:0:0/96 - 64:ff9b::/96 - 100::/64 - 2001::/32 - 2001:20::/28 - 2001:db8::/32 - 2002::/16 - fc00::/7 - fe80::/10 - ff00::/8 - EOF -} - -load_acl() { - local items=$(get_enabled_anonymous_secs "@acl_rule") - [ -n "$items" ] && { - local item enabled remarks ip mac tcp_proxy_mode udp_proxy_mod - local tcp_node udp_node tcp_no_redir_ports udp_no_redir_ports tcp_redir_ports udp_redir_ports - local TCP_NODE UDP_NODE TCP_NODE_TYPE UDP_NODE_TYPE ipt_tmp is_tproxy tcp_port udp_port msg msg2 - echolog "访问控制:" - for item in $items; do - unset ip mac tcp_port udp_port is_tproxy msg - eval $(uci -q show "${CONFIG}.${item}" | cut -d'.' -sf 3-) - [ -z "${ip}${mac}" ] && continue - tcp_proxy_mode=${tcp_proxy_mode:-default} - udp_proxy_mode=${udp_proxy_mode:-default} - tcp_no_redir_ports=${tcp_no_redir_ports:-default} - udp_no_redir_ports=${udp_no_redir_ports:-default} - tcp_redir_ports=${tcp_redir_ports:-default} - udp_redir_ports=${udp_redir_ports:-default} - [ "$tcp_proxy_mode" = "default" ] && tcp_proxy_mode=$TCP_PROXY_MODE - [ "$udp_proxy_mode" = "default" ] && udp_proxy_mode=$UDP_PROXY_MODE - [ "$tcp_no_redir_ports" = "default" ] && tcp_no_redir_ports=$TCP_NO_REDIR_PORTS - [ "$udp_no_redir_ports" = "default" ] && udp_no_redir_ports=$UDP_NO_REDIR_PORTS - [ "$tcp_redir_ports" = "default" ] && tcp_redir_ports=$TCP_REDIR_PORTS - [ "$udp_redir_ports" = "default" ] && udp_redir_ports=$UDP_REDIR_PORTS - - #echolog "访问控制:${item}..." - [ -n "$ip" ] && msg="IP:$ip," - [ -n "$mac" ] && msg="${msg:+${msg}和}MAC:$mac," - ipt_tmp=$ipt_n - [ "$tcp_proxy_mode" != "disable" ] && { - [ "$TCP_NODE" != "nil" ] && { - tcp_port=$TCP_REDIR_PORT - eval TCP_NODE_TYPE=$(echo $(config_n_get $TCP_NODE type) | tr 'A-Z' 'a-z') - [ "$TCP_NODE_TYPE" == "brook" ] && [ "$(config_n_get $TCP_NODE protocol client)" == "client" ] && is_tproxy=1 - #[ "$TCP_NODE_TYPE" == "trojan-go" ] && is_tproxy=1 - msg2="${msg}使用TCP节点 [$(get_action_chain_name $tcp_proxy_mode)]" - if [ -n "${is_tproxy}" ]; then - msg2="${msg2}(TPROXY:${tcp_port})代理" - ipt_tmp=$ipt_m && is_tproxy="TPROXY" - else - msg2="${msg2}(REDIRECT:${tcp_port})代理" - fi - [ "$tcp_no_redir_ports" != "disable" ] && { - $ipt_tmp -A PSW $(comment "$remarks") $(factor $ip "-s") $(factor $mac "-m mac --mac-source") -p tcp -m multiport --dport $tcp_no_redir_ports -j RETURN - $ip6t_m -A PSW $(comment "$remarks") $(factor $ip "-s") $(factor $mac "-m mac --mac-source") -p tcp -m multiport --dport $tcp_no_redir_ports -j RETURN 2>/dev/null - msg2="${msg2}[$?]除${tcp_no_redir_ports}外的" - } - msg2="${msg2}所有端口" - $ipt_tmp -A PSW $(comment "$remarks") -p tcp $(factor $ip "-s") $(factor $mac "-m mac --mac-source") -d 11.1.1.1 $(REDIRECT $tcp_port $is_tproxy) - $ipt_tmp -A PSW $(comment "$remarks") -p tcp $(factor $ip "-s") $(factor $mac "-m mac --mac-source") $(factor $tcp_redir_ports "-m multiport --dport") $(dst $IPSET_SHUNTLIST) $(REDIRECT $tcp_port $is_tproxy) - $ipt_tmp -A PSW $(comment "$remarks") -p tcp $(factor $ip "-s") $(factor $mac "-m mac --mac-source") $(factor $tcp_redir_ports "-m multiport --dport") $(dst $IPSET_BLACKLIST) $(REDIRECT $tcp_port $is_tproxy) - $ipt_tmp -A PSW $(comment "$remarks") -p tcp $(factor $ip "-s") $(factor $mac "-m mac --mac-source") $(factor $tcp_redir_ports "-m multiport --dport") $(get_redirect_ipt $tcp_proxy_mode $tcp_port $is_tproxy) - - if [ "$PROXY_IPV6" == "1" ]; then - $ip6t_m -A PSW $(comment "$remarks") -p tcp $(factor $ip "-s") $(factor $mac "-m mac --mac-source") $(factor $tcp_redir_ports "-m multiport --dport") $(dst $IPSET_SHUNTLIST6) $(REDIRECT $tcp_port TPROXY) 2>/dev/null - $ip6t_m -A PSW $(comment "$remarks") -p tcp $(factor $ip "-s") $(factor $mac "-m mac --mac-source") $(factor $tcp_redir_ports "-m multiport --dport") $(dst $IPSET_BLACKLIST6) $(REDIRECT $tcp_port TPROXY) 2>/dev/null - $ip6t_m -A PSW $(comment "$remarks") -p tcp $(factor $ip "-s") $(factor $mac "-m mac --mac-source") $(factor $tcp_redir_ports "-m multiport --dport") $(get_redirect_ip6t $tcp_proxy_mode $tcp_port TPROXY) 2>/dev/null - fi - } - echolog " - ${msg2}" - } - $ipt_tmp -A PSW $(comment "$remarks") $(factor $ip "-s") $(factor $mac "-m mac --mac-source") -p tcp -j RETURN - $ip6t_m -A PSW $(comment "$remarks") $(factor $ip "-s") $(factor $mac "-m mac --mac-source") -p tcp -j RETURN 2>/dev/null - - [ "$udp_proxy_mode" != "disable" ] && { - msg2="${msg}使用UDP节点 [$(get_action_chain_name $udp_proxy_mode)]" - [ "$UDP_NODE" != "nil" ] && { - udp_port=$UDP_REDIR_PORT - msg2="${msg2}(TPROXY:${udp_port})代理" - [ "$udp_no_redir_ports" != "disable" ] && { - $ipt_m -A PSW $(comment "$remarks") $(factor $ip "-s") $(factor $mac "-m mac --mac-source") -p udp -m multiport --dport $udp_no_redir_ports -j RETURN - $ip6t_m -A PSW $(comment "$remarks") $(factor $ip "-s") $(factor $mac "-m mac --mac-source") -p udp -m multiport --dport $udp_no_redir_ports -j RETURN 2>/dev/null - msg2="${msg2}[$?]除${udp_no_redir_ports}外的" - } - msg2="${msg2}所有端口" - $ipt_m -A PSW $(comment "$remarks") -p udp $(factor $ip "-s") $(factor $mac "-m mac --mac-source") -d 11.1.1.1 $(REDIRECT $udp_port TPROXY) - $ipt_m -A PSW $(comment "$remarks") -p udp $(factor $ip "-s") $(factor $mac "-m mac --mac-source") $(factor $udp_redir_ports "-m multiport --dport") $(dst $IPSET_SHUNTLIST) $(REDIRECT $udp_port TPROXY) - $ipt_m -A PSW $(comment "$remarks") -p udp $(factor $ip "-s") $(factor $mac "-m mac --mac-source") $(factor $udp_redir_ports "-m multiport --dport") $(dst $IPSET_BLACKLIST) $(REDIRECT $udp_port TPROXY) - $ipt_m -A PSW $(comment "$remarks") -p udp $(factor $ip "-s") $(factor $mac "-m mac --mac-source") $(factor $udp_redir_ports "-m multiport --dport") $(get_redirect_ipt $udp_proxy_mode $udp_port TPROXY) - - if [ "$PROXY_IPV6" == "1" ]; then - $ip6t_m -A PSW $(comment "$remarks") -p udp $(factor $ip "-s") $(factor $mac "-m mac --mac-source") $(factor $udp_redir_ports "-m multiport --dport") $(dst $IPSET_SHUNTLIST6) $(REDIRECT $udp_port TPROXY) 2>/dev/null - $ip6t_m -A PSW $(comment "$remarks") -p udp $(factor $ip "-s") $(factor $mac "-m mac --mac-source") $(factor $udp_redir_ports "-m multiport --dport") $(dst $IPSET_BLACKLIST6) $(REDIRECT $udp_port TPROXY) 2>/dev/null - $ip6t_m -A PSW $(comment "$remarks") -p udp $(factor $ip "-s") $(factor $mac "-m mac --mac-source") $(factor $udp_redir_ports "-m multiport --dport") $(get_redirect_ip6t $udp_proxy_mode $udp_port TPROXY) 2>/dev/null - fi - } - echolog " - ${msg2}" - } - $ipt_m -A PSW $(comment "$remarks") $(factor $ip "-s") $(factor $mac "-m mac --mac-source") -p udp -j RETURN - $ip6t_m -A PSW $(comment "$remarks") $(factor $ip "-s") $(factor $mac "-m mac --mac-source") -p udp -j RETURN 2>/dev/null - done - } - - # 加载TCP默认代理模式 - local ipt_tmp=$ipt_n - local is_tproxy msg - if [ "$TCP_PROXY_MODE" != "disable" ]; then - [ "$TCP_NO_REDIR_PORTS" != "disable" ] && { - $ipt_tmp -A PSW $(comment "默认") -p tcp -m multiport --dport $TCP_NO_REDIR_PORTS -j RETURN - $ip6t_m -A PSW $(comment "默认") -p tcp -m multiport --dport $TCP_NO_REDIR_PORTS -j RETURN - } - - ipt_tmp=$ipt_n - unset is_tproxy msg - [ "$TCP_NODE" != "nil" ] && { - local TCP_NODE_TYPE=$(echo $(config_n_get $TCP_NODE type) | tr 'A-Z' 'a-z') - [ "$TCP_NODE_TYPE" == "brook" ] && [ "$(config_n_get $TCP_NODE protocol client)" == "client" ] && is_tproxy=1 - #[ "$TCP_NODE_TYPE" == "trojan-go" ] && is_tproxy=1 - msg="TCP默认代理:使用TCP节点 [$(get_action_chain_name $TCP_PROXY_MODE)]" - if [ -n "$is_tproxy" ]; then - ipt_tmp=$ipt_m && is_tproxy="TPROXY" - msg="${msg}(TPROXY:${TCP_REDIR_PORT})代理" - else - msg="${msg}(REDIRECT:${TCP_REDIR_PORT})代理" - fi - [ "$TCP_NO_REDIR_PORTS" != "disable" ] && msg="${msg}除${TCP_NO_REDIR_PORTS}外的" - msg="${msg}所有端口" - $ipt_tmp -A PSW $(comment "默认") -p tcp -d 11.1.1.1 $(REDIRECT $TCP_REDIR_PORT $is_tproxy) - $ipt_tmp -A PSW $(comment "默认") -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport") $(dst $IPSET_SHUNTLIST) $(REDIRECT $TCP_REDIR_PORT $is_tproxy) - $ipt_tmp -A PSW $(comment "默认") -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport") $(dst $IPSET_BLACKLIST) $(REDIRECT $TCP_REDIR_PORT $is_tproxy) - $ipt_tmp -A PSW $(comment "默认") -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport") $(get_redirect_ipt $TCP_PROXY_MODE $TCP_REDIR_PORT $is_tproxy) - - if [ "$PROXY_IPV6" == "1" ]; then - $ip6t_m -A PSW $(comment "默认") -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport") $(dst $IPSET_SHUNTLIST6) $(REDIRECT $TCP_REDIR_PORT TPROXY) - $ip6t_m -A PSW $(comment "默认") -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport") $(dst $IPSET_BLACKLIST6) $(REDIRECT $TCP_REDIR_PORT TPROXY) - $ip6t_m -A PSW $(comment "默认") -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport") $(get_redirect_ip6t $TCP_PROXY_MODE $TCP_REDIR_PORT TPROXY) - fi - - echolog "${msg}" - } - fi - $ipt_n -A PSW $(comment "默认") -p tcp -j RETURN - $ipt_m -A PSW $(comment "默认") -p tcp -j RETURN - $ip6t_m -A PSW $(comment "默认") -p tcp -j RETURN - - # 加载UDP默认代理模式 - if [ "$UDP_PROXY_MODE" != "disable" ]; then - [ "$UDP_NO_REDIR_PORTS" != "disable" ] && { - $ipt_m -A PSW $(comment "默认") -p udp -m multiport --dport $UDP_NO_REDIR_PORTS -j RETURN - $ip6t_m -A PSW $(comment "默认") -p udp -m multiport --dport $UDP_NO_REDIR_PORTS -j RETURN - } - - [ "$UDP_NODE" != "nil" ] && { - msg="UDP默认代理:使用UDP节点 [$(get_action_chain_name $UDP_PROXY_MODE)](TPROXY:${UDP_REDIR_PORT})代理" - [ "$UDP_NO_REDIR_PORTS" != "disable" ] && msg="${msg}除${UDP_NO_REDIR_PORTS}外的" - msg="${msg}所有端口" - $ipt_m -A PSW $(comment "默认") -p udp -d 11.1.1.1 $(REDIRECT $UDP_REDIR_PORT TPROXY) - $ipt_m -A PSW $(comment "默认") -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") $(dst $IPSET_SHUNTLIST) $(REDIRECT $UDP_REDIR_PORT TPROXY) - $ipt_m -A PSW $(comment "默认") -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") $(dst $IPSET_BLACKLIST) $(REDIRECT $UDP_REDIR_PORT TPROXY) - $ipt_m -A PSW $(comment "默认") -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") $(get_redirect_ipt $UDP_PROXY_MODE $UDP_REDIR_PORT TPROXY) - - if [ "$PROXY_IPV6" == "1" ]; then - $ip6t_m -A PSW $(comment "默认") -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") $(dst $IPSET_SHUNTLIST6) $(REDIRECT $UDP_REDIR_PORT TPROXY) - $ip6t_m -A PSW $(comment "默认") -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") $(dst $IPSET_BLACKLIST6) $(REDIRECT $UDP_REDIR_PORT TPROXY) - $ip6t_m -A PSW $(comment "默认") -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") $(get_redirect_ip6t $UDP_PROXY_MODE $UDP_REDIR_PORT TPROXY) - fi - - echolog "${msg}" - } - fi - $ipt_m -A PSW $(comment "默认") -p udp -j RETURN - $ip6t_m -A PSW $(comment "默认") -p udp -j RETURN - unset is_tproxy msg -} - -filter_haproxy() { - uci show $CONFIG | grep "@haproxy_config" | grep "lbss=" | cut -d "'" -f 2 | grep -E "([0-9]{1,3}[\.]){3}[0-9]{1,3}" | awk -F ":" '{print $1}' | sed -e "/^$/d" | sed -e "s/^/add $IPSET_VPSIPLIST &/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R - for host in $(uci show $CONFIG | grep "@haproxy_config" | grep "lbss=" | cut -d "'" -f 2 | grep -v -E "([0-9]{1,3}[\.]){3}[0-9]{1,3}" | awk -F ":" '{print $1}'); do - ipset -q add $IPSET_VPSIPLIST $(get_host_ip ipv4 $host 1) - done - echolog "加入负载均衡的节点到ipset[$IPSET_VPSIPLIST]直连完成" -} - -filter_vpsip() { - uci show $CONFIG | grep ".address=" | cut -d "'" -f 2 | grep -E "([0-9]{1,3}[\.]){3}[0-9]{1,3}" | sed -e "/^$/d" | sed -e "s/^/add $IPSET_VPSIPLIST &/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R - uci show $CONFIG | grep ".address=" | cut -d "'" -f 2 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | sed -e "/^$/d" | sed -e "s/^/add $IPSET_VPSIPLIST6 &/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R - echolog "加入所有节点到ipset[$IPSET_VPSIPLIST]直连完成" -} - -filter_node() { - local proxy_node=${1} - local stream=$(echo ${2} | tr 'A-Z' 'a-z') - local proxy_port=${3} - - filter_rules() { - local node=${1} - local stream=${2} - local _proxy=${3} - local _port=${4} - local is_tproxy ipt_tmp ip6t_tmp msg msg2 - - if [ -n "$node" ] && [ "$node" != "nil" ]; then - local type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z') - local address=$(config_n_get $node address) - local port=$(config_n_get $node port) - ipt_tmp=$ipt_n - ip6t_tmp=$ip6t_m - [ "$stream" == "udp" ] && is_tproxy=1 - [ "$type" == "brook" ] && [ "$(config_n_get $node protocol client)" == "client" ] && is_tproxy=1 - #[ "$type" == "trojan-go" ] && is_tproxy=1 - if [ -n "$is_tproxy" ]; then - ipt_tmp=$ipt_m - ip6t_tmp=$ip6t_m - msg="TPROXY" - else - msg="REDIRECT" - fi - else - echolog " - 节点配置不正常,略过" - return 0 - fi - - local ADD_INDEX=$FORCE_INDEX - for _ipt in 4 6; do - [ "$_ipt" == "4" ] && _ipt=$ipt_tmp - [ "$_ipt" == "6" ] && _ipt=$ip6t_tmp - $_ipt -n -L PSW_OUTPUT | grep -q "${address}:${port}" - if [ $? -ne 0 ]; then - unset dst_rule - local dst_rule=$(REDIRECT 1 MARK) - msg2="按规则路由(${msg})" - [ "$_ipt" == "$ipt_m" -o "$_ipt" == "$ip6t_m" ] || { - dst_rule=$(REDIRECT $_port) - msg2="套娃使用(${msg}:${port} -> ${_port})" - } - [ -n "$_proxy" ] && [ "$_proxy" == "1" ] && [ -n "$_port" ] || { - ADD_INDEX=$(RULE_LAST_INDEX "$_ipt" PSW_OUT_PUT "$IPSET_VPSIPLIST" $FORCE_INDEX) - dst_rule=" -j RETURN" - msg2="直连代理" - } - $_ipt -w -I PSW_OUTPUT $ADD_INDEX $(comment "${address}:${port}") -p $stream -d $address --dport $port $dst_rule 2>/dev/null - else - msg2="已配置过的节点," - fi - done - msg="[$?]$(echo ${2} | tr 'a-z' 'A-Z')${msg2}使用链${ADD_INDEX},节点(${type}):${address}:${port}" - #echolog " - ${msg}" - } - - local proxy_protocol=$(config_n_get $proxy_node protocol) - local proxy_type=$(echo $(config_n_get $proxy_node type nil) | tr 'A-Z' 'a-z') - [ "$proxy_type" == "nil" ] && echolog " - 节点配置不正常,略过!:${proxy_node}" && return 0 - if [ "$proxy_protocol" == "_balancing" ]; then - #echolog " - 多节点负载均衡(${proxy_type})..." - proxy_node=$(config_n_get $proxy_node balancing_node) - for _node in $proxy_node; do - filter_rules "$_node" "$stream" - done - elif [ "$proxy_protocol" == "_shunt" ]; then - #echolog " - 按请求目的地址分流(${proxy_type})..." - local default_node=$(config_n_get $proxy_node default_node _direct) - local main_node=$(config_n_get $proxy_node main_node nil) - if [ "$main_node" != "nil" ]; then - filter_rules $main_node $stream - else - if [ "$default_node" != "_direct" ] && [ "$default_node" != "_blackhole" ]; then - filter_rules $default_node $stream - fi - fi -:</dev/null | grep -E -o "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" | sort -u | grep -v 0.0.0.0 | grep -v 127.0.0.1) - [ -n "$ISP_DNS" ] && { - #echolog "处理 ISP DNS 例外..." - for ispip in $ISP_DNS; do - ipset -! add $IPSET_WHITELIST $ispip >/dev/null 2>&1 & - #echolog " - 追加到白名单:${ispip}" - done - } - - local ISP_DNS6=$(cat $RESOLVFILE 2>/dev/null | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | awk -F % '{print $1}' | awk -F " " '{print $2}'| sort -u ) - [ -n "$ISP_DNS" ] && { - #echolog "处理 ISP IPv6 DNS 例外..." - for ispip6 in $ISP_DNS; do - ipset -! add $IPSET_WHITELIST6 $ispip6 >/dev/null 2>&1 & - #echolog " - 追加到白名单:${ispip6}" - done - } - - # 过滤所有节点IP - filter_vpsip > /dev/null 2>&1 & - filter_haproxy > /dev/null 2>&1 & - - $ipt_n -N PSW - $ipt_n -A PSW $(dst $IPSET_LANIPLIST) -j RETURN - $ipt_n -A PSW $(dst $IPSET_VPSIPLIST) -j RETURN - $ipt_n -A PSW $(dst $IPSET_WHITELIST) -j RETURN - $ipt_n -A PSW -m mark --mark 0xff -j RETURN - PR_INDEX=$(RULE_LAST_INDEX "$ipt_n" PREROUTING prerouting_rule) - PR_INDEX=$((PR_INDEX + 1)) - $ipt_n -I PREROUTING $PR_INDEX -p tcp -j PSW - unset PR_INDEX - - $ipt_n -N PSW_OUTPUT - $ipt_n -A PSW_OUTPUT $(dst $IPSET_LANIPLIST) -j RETURN - $ipt_n -A PSW_OUTPUT $(dst $IPSET_VPSIPLIST) -j RETURN - $ipt_n -A PSW_OUTPUT $(dst $IPSET_WHITELIST) -j RETURN - $ipt_n -A PSW_OUTPUT -m mark --mark 0xff -j RETURN - - # 据说能提升性能? - PR_INDEX=$(RULE_LAST_INDEX "$ipt_m" PREROUTING mwan3 1) - $ipt_m -N PSW_DIVERT - $ipt_m -A PSW_DIVERT -j MARK --set-mark 1 - $ipt_m -A PSW_DIVERT -j ACCEPT - $ipt_m -I PREROUTING $PR_INDEX -p tcp -m socket -j PSW_DIVERT - - $ipt_m -N PSW - $ipt_m -A PSW $(dst $IPSET_LANIPLIST) -j RETURN - $ipt_m -A PSW $(dst $IPSET_VPSIPLIST) -j RETURN - $ipt_m -A PSW $(dst $IPSET_WHITELIST) -j RETURN - $ipt_m -A PSW -m mark --mark 0xff -j RETURN - $ipt_m -A PSW $(dst $IPSET_BLOCKLIST) -j DROP - PR_INDEX=$((PR_INDEX + 1)) - $ipt_m -I PREROUTING $PR_INDEX -j PSW - unset PR_INDEX - - $ipt_m -N PSW_OUTPUT - $ipt_m -A PSW_OUTPUT $(dst $IPSET_LANIPLIST) -j RETURN - $ipt_m -A PSW_OUTPUT $(dst $IPSET_VPSIPLIST) -j RETURN - $ipt_m -A PSW_OUTPUT $(dst $IPSET_WHITELIST) -j RETURN - $ipt_m -A PSW_OUTPUT -m mark --mark 0xff -j RETURN - $ipt_m -A PSW_OUTPUT $(dst $IPSET_BLOCKLIST) -j DROP - - ip rule add fwmark 1 lookup 100 - ip route add local 0.0.0.0/0 dev lo table 100 - - local NODE_TYPE=$(echo $(config_n_get $TCP_NODE type) | tr 'A-Z' 'a-z') - local ipv6_tproxy=$(config_t_get global_other ipv6_tproxy 0) - - if [ $ipv6_tproxy == "1" ]; then - if [ $NODE_TYPE == "xray" ]; then - PROXY_IPV6=1 - echolog "节点类型:$NODE_TYPE,开启实验性IPv6透明代理(TProxy)..." - else - echolog "节点类型:$NODE_TYPE,暂不支持IPv6透明代理(TProxy)..." - fi - fi - - # 据说能提升性能? - $ip6t_m -N PSW_DIVERT - $ip6t_m -A PSW_DIVERT -j MARK --set-mark 1 - $ip6t_m -A PSW_DIVERT -j ACCEPT - $ip6t_m -A PREROUTING -p tcp -m socket -j PSW_DIVERT - - $ip6t_m -N PSW - $ip6t_m -A PSW $(dst $IPSET_LANIPLIST6) -j RETURN - $ip6t_m -A PSW $(dst $IPSET_VPSIPLIST6) -j RETURN - $ip6t_m -A PSW $(dst $IPSET_WHITELIST6) -j RETURN - $ip6t_m -A PSW -m mark --mark 0xff -j RETURN - $ip6t_m -A PSW $(dst $IPSET_BLOCKLIST6) -j DROP - $ip6t_m -A PREROUTING -j PSW - - $ip6t_m -N PSW_OUTPUT - $ip6t_m -A PSW_OUTPUT $(dst $IPSET_LANIPLIST6) -j RETURN - $ip6t_m -A PSW_OUTPUT $(dst $IPSET_VPSIPLIST6) -j RETURN - $ip6t_m -A PSW_OUTPUT $(dst $IPSET_WHITELIST6) -j RETURN - $ip6t_m -A PSW_OUTPUT -m mark --mark 0xff -j RETURN - $ip6t_m -A PSW_OUTPUT $(dst $IPSET_BLOCKLIST6) -j DROP - $ip6t_m -A OUTPUT -j PSW_OUTPUT - - ip -6 rule add fwmark 1 table 100 - ip -6 route add local ::/0 dev lo table 100 - - # 加载路由器自身代理 TCP - if [ "$TCP_NODE" != "nil" ]; then - local ipt_tmp=$ipt_n - local dns_l="PSW_OUTPUT" - local dns_r=$(REDIRECT $TCP_REDIR_PORT) - local blist_r=$(REDIRECT $TCP_REDIR_PORT) - local p_r=$(get_redirect_ipt $LOCALHOST_TCP_PROXY_MODE $TCP_REDIR_PORT) - TCP_NODE_TYPE=$(echo $(config_n_get $TCP_NODE type) | tr 'A-Z' 'a-z') - echolog "加载路由器自身 TCP 代理..." - if [ "$TCP_NODE_TYPE" == "brook" ] && [ "$(config_n_get $TCP_NODE protocol client)" == "client" ]; then - echolog " - 启用 TPROXY 模式" - ipt_tmp=$ipt_m - dns_l="PSW" - dns_r="$(REDIRECT $TCP_REDIR_PORT TPROXY)" - blist_r=$(REDIRECT 1 MARK) - p_r=$(get_redirect_ipt $LOCALHOST_TCP_PROXY_MODE 1 MARK) - fi - _proxy_tcp_access() { - [ -n "${2}" ] || return 0 - ipset -q test $IPSET_LANIPLIST ${2} - [ $? -eq 0 ] && { - echolog " - 上游 DNS 服务器 ${2} 已在直接访问的列表中,不强制向 TCP 代理转发对该服务器 TCP/${3} 端口的访问" - return 0 - } - local ADD_INDEX=$FORCE_INDEX - $ipt_tmp -I $dns_l $ADD_INDEX -p tcp -d ${2} --dport ${3} $dns_r - [ "$ipt_tmp" == "$ipt_m" ] && $ipt_tmp -I PSW_OUTPUT $ADD_INDEX -p tcp -d ${2} --dport ${3} $(REDIRECT 1 MARK) - echolog " - [$?]将上游 DNS 服务器 ${2}:${3} 加入到路由器自身代理的 TCP 转发链${ADD_INDEX}" - } - [ "$use_tcp_node_resolve_dns" == 1 ] && hosts_foreach DNS_FORWARD _proxy_tcp_access 53 - $ipt_tmp -A OUTPUT -p tcp -j PSW_OUTPUT - [ "$TCP_NO_REDIR_PORTS" != "disable" ] && { - $ipt_tmp -A PSW_OUTPUT -p tcp -m multiport --dport $TCP_NO_REDIR_PORTS -j RETURN - $ipt_tmp -A PSW_OUTPUT -p tcp -m multiport --sport $TCP_NO_REDIR_PORTS -j RETURN - $ip6t_m -A PSW_OUTPUT -p tcp -m multiport --dport $TCP_NO_REDIR_PORTS -j RETURN - $ip6t_m -A PSW_OUTPUT -p tcp -m multiport --sport $TCP_NO_REDIR_PORTS -j RETURN - echolog " - [$?]不代理TCP 端口:$TCP_NO_REDIR_PORTS" - } - $ipt_tmp -A PSW_OUTPUT -p tcp -d 11.1.1.1 $blist_r - $ipt_tmp -A PSW_OUTPUT -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport") $(dst $IPSET_SHUNTLIST) $blist_r - $ipt_tmp -A PSW_OUTPUT -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport") $(dst $IPSET_BLACKLIST) $blist_r - $ipt_tmp -A PSW_OUTPUT -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport") $p_r - - if [ "$PROXY_IPV6" == "1" ]; then - $ip6t_m -A PSW_OUTPUT -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport") $(dst $IPSET_SHUNTLIST6) $(REDIRECT 1 MARK) - $ip6t_m -A PSW_OUTPUT -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport") $(dst $IPSET_BLACKLIST6) $(REDIRECT 1 MARK) - $ip6t_m -A PSW_OUTPUT -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport") $(get_redirect_ip6t $LOCALHOST_TCP_PROXY_MODE 1 MARK) - fi - fi - - # 过滤Socks节点 - [ "$SOCKS_ENABLED" = "1" ] && { - local ids=$(uci show $CONFIG | grep "=socks" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}') - #echolog "分析 Socks 服务所使用节点..." - local id enabled node port msg num - for id in $ids; do - enabled=$(config_n_get $id enabled 0) - [ "$enabled" == "1" ] || continue - node=$(config_n_get $id node nil) - port=$(config_n_get $id port 0) - msg="Socks 服务 [:${port}]" - if [ "$node" == "nil" ] || [ "$port" == "0" ]; then - msg="${msg} 未配置完全,略过" - elif [ "$(echo $node | grep ^tcp)" ]; then - #eval "node=\${TCP_NODE}" - #msg="${msg} 使用与 TCP 代理自动切换${num} 相同的节点,延后处理" - continue - else - filter_node $node TCP > /dev/null 2>&1 & - filter_node $node UDP > /dev/null 2>&1 & - fi - #echolog " - ${msg}" - done - } - - # 处理轮换节点的分流或套娃 - local node port stream switch - for stream in TCP UDP; do - eval "node=\${${stream}_NODE}" - eval "port=\${${stream}_REDIR_PORT}" - #echolog "分析 $stream 代理自动切换..." - [ "$node" == "tcp" ] && [ "$stream" == "UDP" ] && { - eval "node=\${TCP_NODE}" - eval "port=\${TCP_REDIR_PORT}" - } - if [ "$node" != "nil" ]; then - filter_node $node $stream $port > /dev/null 2>&1 & - fi - done - - # 加载路由器自身代理 UDP - if [ "$UDP_NODE" != "nil" ]; then - echolog "加载路由器自身 UDP 代理..." - local UDP_NODE_TYPE=$(echo $(config_n_get $UDP_NODE type) | tr 'A-Z' 'a-z') - local ADD_INDEX=$FORCE_INDEX - _proxy_udp_access() { - [ -n "${2}" ] || return 0 - ipset -q test $IPSET_LANIPLIST ${2} - [ $? == 0 ] && { - echolog " - 上游 DNS 服务器 ${2} 已在直接访问的列表中,不强制向 UDP 代理转发对该服务器 UDP/${3} 端口的访问" - return 0 - } - $ipt_m -I PSW $ADD_INDEX -p udp -d ${2} --dport ${3} $(REDIRECT $UDP_REDIR_PORT TPROXY) - $ipt_m -I PSW_OUTPUT $ADD_INDEX -p udp -d ${2} --dport ${3} $(REDIRECT 1 MARK) - echolog " - [$?]将上游 DNS 服务器 ${2}:${3} 加入到路由器自身代理的 UDP 转发链${ADD_INDEX}" - } - [ "$use_udp_node_resolve_dns" == 1 ] && hosts_foreach DNS_FORWARD _proxy_udp_access 53 - $ipt_m -A OUTPUT -p udp -j PSW_OUTPUT - [ "$UDP_NO_REDIR_PORTS" != "disable" ] && { - $ipt_m -A PSW_OUTPUT -p udp -m multiport --dport $UDP_NO_REDIR_PORTS -j RETURN - $ipt_m -A PSW_OUTPUT -p udp -m multiport --sport $UDP_NO_REDIR_PORTS -j RETURN - $ip6t_m -A PSW_OUTPUT -p udp -m multiport --dport $UDP_NO_REDIR_PORTS -j RETURN - $ip6t_m -A PSW_OUTPUT -p udp -m multiport --sport $UDP_NO_REDIR_PORTS -j RETURN - echolog " - [$?]不代理 UDP 端口:$UDP_NO_REDIR_PORTS" - } - $ipt_m -A PSW_OUTPUT -p udp -d 11.1.1.1 $(REDIRECT 1 MARK) - $ipt_m -A PSW_OUTPUT -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") $(dst $IPSET_SHUNTLIST) $(REDIRECT 1 MARK) - $ipt_m -A PSW_OUTPUT -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") $(dst $IPSET_BLACKLIST) $(REDIRECT 1 MARK) - $ipt_m -A PSW_OUTPUT -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") $(get_redirect_ipt $LOCALHOST_UDP_PROXY_MODE 1 MARK) - - if [ "$PROXY_IPV6" == "1" ]; then - $ip6t_m -A PSW_OUTPUT -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") $(dst $IPSET_SHUNTLIST6) $(REDIRECT 1 MARK) - $ip6t_m -A PSW_OUTPUT -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") $(dst $IPSET_BLACKLIST6) $(REDIRECT 1 MARK) - $ip6t_m -A PSW_OUTPUT -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") $(get_redirect_ip6t $LOCALHOST_UDP_PROXY_MODE 1 MARK) - fi - fi - - # 加载ACLS - load_acl - - # dns_hijack "force" - - echolog "防火墙规则加载完成!" -} - -del_firewall_rule() { - for ipt in "$ipt_n" "$ipt_m" "$ip6t_m"; do - for chain in "PREROUTING" "OUTPUT"; do - for i in $(seq 1 $($ipt -nL $chain | grep -c PSW)); do - local index=$($ipt --line-number -nL $chain | grep PSW | head -1 | awk '{print $1}') - $ipt -D $chain $index 2>/dev/null - done - done - for chain in "PSW" "PSW_OUTPUT" "PSW_DIVERT"; do - $ipt -F $chain 2>/dev/null - $ipt -X $chain 2>/dev/null - done - done - - ip rule del fwmark 1 lookup 100 2>/dev/null - ip route del local 0.0.0.0/0 dev lo table 100 2>/dev/null - - ip -6 rule del fwmark 1 table 100 2>/dev/null - ip -6 route del local ::/0 dev lo table 100 2>/dev/null - - destroy_ipset $IPSET_LANIPLIST - destroy_ipset $IPSET_VPSIPLIST - #destroy_ipset $IPSET_SHUNTLIST - #destroy_ipset $IPSET_GFW - #destroy_ipset $IPSET_CHN - #destroy_ipset $IPSET_BLACKLIST - destroy_ipset $IPSET_BLOCKLIST - destroy_ipset $IPSET_WHITELIST - - destroy_ipset $IPSET_LANIPLIST6 - destroy_ipset $IPSET_VPSIPLIST6 - #destroy_ipset $IPSET_SHUNTLIST6 - #destroy_ipset $IPSET_GFW6 - #destroy_ipset $IPSET_CHN6 - #destroy_ipset $IPSET_BLACKLIST6 - destroy_ipset $IPSET_BLOCKLIST6 - destroy_ipset $IPSET_WHITELIST6 - - echolog "删除相关防火墙规则完成。" -} - -flush_ipset() { - destroy_ipset $IPSET_LANIPLIST $IPSET_VPSIPLIST $IPSET_SHUNTLIST $IPSET_GFW $IPSET_CHN $IPSET_BLACKLIST $IPSET_BLOCKLIST $IPSET_WHITELIST - destroy_ipset $IPSET_LANIPLIST6 $IPSET_VPSIPLIST6 $IPSET_SHUNTLIST6 $IPSET_GFW6 $IPSET_CHN6 $IPSET_BLACKLIST6 $IPSET_BLOCKLIST6 $IPSET_WHITELIST6 - /etc/init.d/passwall reload -} - -flush_include() { - echo '#!/bin/sh' >$FWI -} - -gen_include() { - flush_include - cat <<-EOF >>$FWI - /etc/init.d/passwall reload - EOF - return 0 -} - -start() { - add_firewall_rule - gen_include -} - -stop() { - del_firewall_rule - flush_include -} - -case $1 in -flush_ipset) - flush_ipset - ;; -stop) - stop - ;; -start) - start - ;; -*) ;; -esac diff --git a/package/lienol/luci-app-passwall/root/usr/share/passwall/monitor.sh b/package/lienol/luci-app-passwall/root/usr/share/passwall/monitor.sh deleted file mode 100755 index b9b89c0b71..0000000000 --- a/package/lienol/luci-app-passwall/root/usr/share/passwall/monitor.sh +++ /dev/null @@ -1,91 +0,0 @@ -#!/bin/sh - -CONFIG=passwall -TMP_PATH=/var/etc/$CONFIG -TMP_BIN_PATH=$TMP_PATH/bin -TMP_ID_PATH=$TMP_PATH/id - -config_n_get() { - local ret=$(uci -q get $CONFIG.$1.$2 2>/dev/null) - echo ${ret:=$3} -} - -config_t_get() { - local index=0 - [ -n "$4" ] && index=$4 - local ret=$(uci -q get $CONFIG.@$1[$index].$2 2>/dev/null) - echo ${ret:=$3} -} - -if [ "$(pgrep -f $CONFIG/monitor.sh | wc -l)" -gt 2 ]; then - exit 1 -fi - -ENABLED=$(config_t_get global enabled 0) -[ "$ENABLED" != 1 ] && return 1 -ENABLED=$(config_t_get global_delay start_daemon 0) -[ "$ENABLED" != 1 ] && return 1 -sleep 58s -while [ "$ENABLED" -eq 1 ] -do - #TCP - [ -f "$TMP_ID_PATH/TCP" ] && { - TCP_NODE=$(cat $TMP_ID_PATH/TCP) - if [ "$TCP_NODE" != "nil" ]; then - #kcptun - use_kcp=$(config_n_get $TCP_NODE use_kcp 0) - if [ $use_kcp -gt 0 ]; then - if ! pgrep -af "$TMP_BIN_PATH/kcptun.*(tcp|TCP)" > /dev/null 2>&1; then - /etc/init.d/$CONFIG restart - exit 0 - fi - fi - icount=$(pgrep -af "$TMP_BIN_PATH.*(tcp|TCP)" | grep -v kcptun | wc -l) - if [ $icount = 0 ]; then - /etc/init.d/$CONFIG restart - exit 0 - fi - fi - } - - #udp - [ -f "$TMP_ID_PATH/UDP" ] && { - UDP_NODE=$(cat $TMP_ID_PATH/UDP) - if [ "$UDP_NODE" != "nil" ]; then - [ "$UDP_NODE" == "tcp" ] && continue - [ "$UDP_NODE" == "tcp_" ] && UDP_NODE=$TCP_NODE - if ! pgrep -af "$TMP_BIN_PATH.*(udp|UDP)" > /dev/null 2>&1; then - /etc/init.d/$CONFIG restart - exit 0 - fi - fi - } - - #dns - dns_mode=$(config_t_get global dns_mode) - if [ "$dns_mode" == "pdnsd" ] || [ "$dns_mode" == "dns2socks" ] || [ "$dns_mode" == "xray_doh" ]; then - icount=$(netstat -apn | grep 7913 | wc -l) - if [ $icount = 0 ]; then - /etc/init.d/$CONFIG restart - exit 0 - fi - fi - - [ -f "$TMP_BIN_PATH/chinadns-ng" ] && { - if ! pgrep -x "$TMP_BIN_PATH/chinadns-ng" > /dev/null 2>&1; then - /etc/init.d/$CONFIG restart - exit 0 - fi - } - - #haproxy - use_haproxy=$(config_t_get global_haproxy balancing_enable 0) - if [ $use_haproxy -gt 0 ]; then - if ! pgrep -x "$TMP_BIN_PATH/haproxy" > /dev/null 2>&1; then - /etc/init.d/$CONFIG restart - exit 0 - fi - fi - - sleep 58s -done diff --git a/package/lienol/luci-app-passwall/root/usr/share/passwall/rule_update.lua b/package/lienol/luci-app-passwall/root/usr/share/passwall/rule_update.lua deleted file mode 100755 index d6fcb41d10..0000000000 --- a/package/lienol/luci-app-passwall/root/usr/share/passwall/rule_update.lua +++ /dev/null @@ -1,450 +0,0 @@ -#!/usr/bin/lua - -require 'luci.sys' -local luci = luci -local ucic = luci.model.uci.cursor() -local jsonc = require "luci.jsonc" -local i18n = require "luci.i18n" -local name = 'passwall' -local arg1 = arg[1] - -local rule_path = "/usr/share/" .. name .. "/rules" -local reboot = 0 -local gfwlist_update = 0 -local chnroute_update = 0 -local chnroute6_update = 0 -local chnlist_update = 0 -local geoip_update = 0 -local geosite_update = 0 - --- match comments/title/whitelist/ip address/excluded_domain -local comment_pattern = "^[!\\[@]+" -local ip_pattern = "^%d+%.%d+%.%d+%.%d+" -local ip4_ipset_pattern = "^%d+%.%d+%.%d+%.%d+[%/][%d]+$" -local ip6_ipset_pattern = ":-[%x]+%:+[%x]-[%/][%d]+$" -local domain_pattern = "([%w%-%_]+%.[%w%.%-%_]+)[%/%*]*" -local excluded_domain = {"apple.com","sina.cn","sina.com.cn","baidu.com","byr.cn","jlike.com","weibo.com","zhongsou.com","youdao.com","sogou.com","so.com","soso.com","aliyun.com","taobao.com","jd.com","qq.com"} - -local gfwlist_url = ucic:get_first(name, 'global_rules', "gfwlist_url", "https://cdn.jsdelivr.net/gh/Loukky/gfwlist-by-loukky/gfwlist.txt") -local chnroute_url = ucic:get_first(name, 'global_rules', "chnroute_url", "https://ispip.clang.cn/all_cn.txt") -local chnroute6_url = ucic:get_first(name, 'global_rules', "chnroute6_url", "https://ispip.clang.cn/all_cn_ipv6.txt") -local chnlist_url = ucic:get(name, "@global_rules[0]", "chnlist_url") or {"https://cdn.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/accelerated-domains.china.conf","https://cdn.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/apple.china.conf","https://cdn.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/google.china.conf"} -local geoip_api = "https://api.github.com/repos/Loyalsoldier/v2ray-rules-dat/releases/latest" -local geosite_api = "https://api.github.com/repos/Loyalsoldier/v2ray-rules-dat/releases/latest" -local xray_asset_location = ucic:get_first(name, 'global_rules', "xray_location_asset", "/usr/share/xray/") - -local log = function(...) - if arg1 then - local result = os.date("%Y-%m-%d %H:%M:%S: ") .. table.concat({...}, " ") - if arg1 == "log" then - local f, err = io.open("/var/log/passwall.log", "a") - if f and err == nil then - f:write(result .. "\n") - f:close() - end - elseif arg1 == "print" then - print(result) - end - end -end - --- base64decoding -local function base64_dec(data) - local bc='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' - data = string.gsub(data, '[^'..bc..'=]', '') - return (data:gsub('.', function(x) - if (x == '=') then return '' end - local r,f='',(bc:find(x)-1) - for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and '1' or '0') end - return r; - end):gsub('%d%d%d?%d?%d?%d?%d?%d?', function(x) - if (#x ~= 8) then return '' end - local c=0 - for i=1,8 do c=c+(x:sub(i,i)=='1' and 2^(8-i) or 0) end - return string.char(c) - end)) -end - --- trim -local function trim(text) - if not text or text == "" then return "" end - return (string.gsub(text, "^%s*(.-)%s*$", "%1")) -end - --- curl -local function curl(url, file) - local cmd = "curl -skL -w %{http_code} --retry 3 --connect-timeout 3 '" .. url .. "'" - if file then - cmd = cmd .. " -o " .. file - end - local stdout = luci.sys.exec(cmd) - - if file then - return tonumber(trim(stdout)) - else - return trim(stdout) - end -end - ---check excluded domain -local function check_excluded_domain(value) - for k,v in ipairs(excluded_domain) do - if value:find(v) then - return true - end - end -end - ---fetch gfwlist -local function fetch_gfwlist() - local sret = curl(gfwlist_url, "/tmp/gfwlist_dl") - if sret == 200 then - local domains = {} - local gfwlist = io.open("/tmp/gfwlist_dl", "r") - local decode = base64_dec(gfwlist:read("*all")) - gfwlist:close() - - gfwlist = io.open("/tmp/gfwlist_dl", "w") - gfwlist:write(decode) - gfwlist:close() - - for line in io.lines("/tmp/gfwlist_dl") do - if not (string.find(line, comment_pattern) or string.find(line, ip_pattern) or check_excluded_domain(line)) then - local start, finish, match = string.find(line, domain_pattern) - if (start) then - domains[match] = true - end - end - end - - local out = io.open("/tmp/gfwlist_tmp", "w") - for k,v in pairs(domains) do - out:write(string.format("%s\n", k)) - end - out:close() - end - - os.remove("/tmp/gfwlist_dl") - - return sret; -end - ---fetch chnroute -local function fetch_chnroute() - local sret = curl(chnroute_url, "/tmp/chnroute_dl") - - if sret == 200 then - local out = io.open("/tmp/chnroute_tmp", "w") - - for line in io.lines("/tmp/chnroute_dl") do - local start, finish, match = string.find(line, ip4_ipset_pattern) - if (start) then - out:write(string.format("%s\n", line)) - end - end - - out:close() - end - - os.remove("/tmp/chnroute_dl") - - return sret; -end - ---fetch chnroute6 -local function fetch_chnroute6() - local sret = curl(chnroute6_url, "/tmp/chnroute6_dl") - - if sret == 200 then - local out = io.open("/tmp/chnroute6_tmp", "w") - for line in io.lines("/tmp/chnroute6_dl") do - local start, finish, match = string.find(line, ip6_ipset_pattern) - if (start) then - out:write(string.format("%s\n", line)) - end - end - - out:close() - end - - os.remove("/tmp/chnroute6_dl") - - return sret; -end - ---fetch chnlist -local function fetch_chnlist() - local domains = {} - local sret = 200 - local sret_tmp = 0 - - for k,v in ipairs(chnlist_url) do - sret_tmp = curl(v, "/tmp/chnlist_dl"..k) - if sret_tmp == 200 then - for line in io.lines("/tmp/chnlist_dl"..k) do - local start, finish, match = string.find(line, domain_pattern) - if (start) then - domains[match] = true - end - end - else - sret = 0 - log("chnlist 第"..k.."条规则:"..v.."下载失败!") - end - os.remove("/tmp/chnlist_dl"..k) - end - - if sret == 200 then - local out = io.open("/tmp/cdn_tmp", "w") - for k,v in pairs(domains) do - out:write(string.format("%s\n", k)) - end - out:close() - - luci.sys.call("cat /tmp/cdn_tmp | sort -u > /tmp/chnlist_tmp") - os.remove("/tmp/cdn_tmp") - end - - return sret; -end - ---获取geoip -local function fetch_geoip() - --请求geoip - xpcall(function() - local json_str = curl(geoip_api) - local json = jsonc.parse(json_str) - if json.tag_name and json.assets then - for _, v in ipairs(json.assets) do - if v.name and v.name == "geoip.dat.sha256sum" then - local sret = curl(v.browser_download_url, "/tmp/geoip.dat.sha256sum") - if sret == 200 then - local f = io.open("/tmp/geoip.dat.sha256sum", "r") - local content = f:read() - f:close() - f = io.open("/tmp/geoip.dat.sha256sum", "w") - f:write(content:gsub("geoip.dat", "/tmp/geoip.dat"), "") - f:close() - - if nixio.fs.access(xray_asset_location .. "geoip.dat") then - luci.sys.call(string.format("cp -f %s %s", xray_asset_location .. "geoip.dat", "/tmp/geoip.dat")) - if luci.sys.call('sha256sum -c /tmp/geoip.dat.sha256sum > /dev/null 2>&1') == 0 then - log("geoip 版本一致,无需更新。") - return 1 - end - end - for _2, v2 in ipairs(json.assets) do - if v2.name and v2.name == "geoip.dat" then - sret = curl(v2.browser_download_url, "/tmp/geoip.dat") - if luci.sys.call('sha256sum -c /tmp/geoip.dat.sha256sum > /dev/null 2>&1') == 0 then - luci.sys.call(string.format("mkdir -p %s && cp -f %s %s", xray_asset_location, "/tmp/geoip.dat", xray_asset_location .. "geoip.dat")) - reboot = 1 - log("geoip 更新成功。") - return 1 - else - log("geoip 更新失败,请稍后再试。") - end - break - end - end - end - break - end - end - end - end, - function(e) - end) - - return 0 -end - ---获取geosite -local function fetch_geosite() - --请求geosite - xpcall(function() - local json_str = curl(geosite_api) - local json = jsonc.parse(json_str) - if json.tag_name and json.assets then - for _, v in ipairs(json.assets) do - if v.name and v.name == "geosite.dat.sha256sum" then - local sret = curl(v.browser_download_url, "/tmp/geosite.dat.sha256sum") - if sret == 200 then - local f = io.open("/tmp/geosite.dat.sha256sum", "r") - local content = f:read() - f:close() - f = io.open("/tmp/geosite.dat.sha256sum", "w") - f:write(content:gsub("geosite.dat", "/tmp/geosite.dat"), "") - f:close() - - if nixio.fs.access(xray_asset_location .. "geosite.dat") then - luci.sys.call(string.format("cp -f %s %s", xray_asset_location .. "geosite.dat", "/tmp/geosite.dat")) - if luci.sys.call('sha256sum -c /tmp/geosite.dat.sha256sum > /dev/null 2>&1') == 0 then - log("geosite 版本一致,无需更新。") - return 1 - end - end - for _2, v2 in ipairs(json.assets) do - if v2.name and v2.name == "geosite.dat" then - sret = curl(v2.browser_download_url, "/tmp/geosite.dat") - if luci.sys.call('sha256sum -c /tmp/geosite.dat.sha256sum > /dev/null 2>&1') == 0 then - luci.sys.call(string.format("mkdir -p %s && cp -f %s %s", xray_asset_location, "/tmp/geosite.dat", xray_asset_location .. "geosite.dat")) - reboot = 1 - log("geosite 更新成功。") - return 1 - else - log("geosite 更新失败,请稍后再试。") - end - break - end - end - end - break - end - end - end - end, - function(e) - end) - - return 0 -end - -if arg[2] then - if arg[2]:find("gfwlist") then - gfwlist_update = 1 - end - if arg[2]:find("chnroute") then - chnroute_update = 1 - end - if arg[2]:find("chnroute6") then - chnroute6_update = 1 - end - if arg[2]:find("chnlist") then - chnlist_update = 1 - end - if arg[2]:find("geoip") then - geoip_update = 1 - end - if arg[2]:find("geosite") then - geosite_update = 1 - end -else - gfwlist_update = ucic:get_first(name, 'global_rules', "gfwlist_update", 1) - chnroute_update = ucic:get_first(name, 'global_rules', "chnroute_update", 1) - chnroute6_update = ucic:get_first(name, 'global_rules', "chnroute6_update", 1) - chnlist_update = ucic:get_first(name, 'global_rules', "chnlist_update", 1) - geoip_update = ucic:get_first(name, 'global_rules', "geoip_update", 1) - geosite_update = ucic:get_first(name, 'global_rules', "geosite_update", 1) -end -if gfwlist_update == 0 and chnroute_update == 0 and chnroute6_update == 0 and chnlist_update == 0 and geoip_update == 0 and geosite_update == 0 then - os.exit(0) -end - -log("开始更新规则...") -if tonumber(gfwlist_update) == 1 then - log("gfwlist 开始更新...") - local old_md5 = luci.sys.exec("echo -n $(md5sum " .. rule_path .. "/gfwlist | awk '{print $1}')") - local status = fetch_gfwlist() - if status == 200 then - local new_md5 = luci.sys.exec("echo -n $([ -f '/tmp/gfwlist_tmp' ] && md5sum /tmp/gfwlist_tmp | awk '{print $1}')") - if old_md5 ~= new_md5 then - luci.sys.exec("mv -f /tmp/gfwlist_tmp " .. rule_path .. "/gfwlist") - reboot = 1 - log("gfwlist 更新成功...") - else - log("gfwlist 版本一致,无需更新。") - end - else - log("gfwlist 文件下载失败!") - end - - os.remove("/tmp/gfwlist_tmp") -end - -if tonumber(chnroute_update) == 1 then - log("chnroute 开始更新...") - local old_md5 = luci.sys.exec("echo -n $(md5sum " .. rule_path .. "/chnroute | awk '{print $1}')") - local status = fetch_chnroute() - if status == 200 then - local new_md5 = luci.sys.exec("echo -n $([ -f '/tmp/chnroute_tmp' ] && md5sum /tmp/chnroute_tmp | awk '{print $1}')") - if old_md5 ~= new_md5 then - luci.sys.exec("mv -f /tmp/chnroute_tmp " .. rule_path .. "/chnroute") - reboot = 1 - log("chnroute 更新成功...") - else - log("chnroute 版本一致,无需更新。") - end - else - log("chnroute 文件下载失败!") - end - os.remove("/tmp/chnroute_tmp") -end - -if tonumber(chnroute6_update) == 1 then - log("chnroute6 开始更新...") - local old_md5 = luci.sys.exec("echo -n $(md5sum " .. rule_path .. "/chnroute6 | awk '{print $1}')") - local status = fetch_chnroute6() - if status == 200 then - local new_md5 = luci.sys.exec("echo -n $([ -f '/tmp/chnroute6_tmp' ] && md5sum /tmp/chnroute6_tmp | awk '{print $1}')") - if old_md5 ~= new_md5 then - luci.sys.exec("mv -f /tmp/chnroute6_tmp " .. rule_path .. "/chnroute6") - reboot = 1 - log("chnroute6 更新成功...") - else - log("chnroute6 版本一致,无需更新。") - end - else - log("chnroute6 文件下载失败!") - end - os.remove("/tmp/chnroute6_tmp") -end - -if tonumber(chnlist_update) == 1 then - log("chnlist 开始更新...") - local old_md5 = luci.sys.exec("echo -n $(md5sum " .. rule_path .. "/chnlist | awk '{print $1}')") - local status = fetch_chnlist() - if status == 200 then - local new_md5 = luci.sys.exec("echo -n $([ -f '/tmp/chnlist_tmp' ] && md5sum /tmp/chnlist_tmp | awk '{print $1}')") - if old_md5 ~= new_md5 then - luci.sys.exec("mv -f /tmp/chnlist_tmp " .. rule_path .. "/chnlist") - reboot = 1 - log("chnlist 更新成功...") - else - log("chnlist 版本一致,无需更新。") - end - else - log("chnlist 文件下载失败!") - end - - os.remove("/tmp/chnlist_tmp") -end - -if tonumber(geoip_update) == 1 then - log("geoip 开始更新...") - local status = fetch_geoip() - os.remove("/tmp/geoip.dat") - os.remove("/tmp/geoip.dat.sha256sum") -end - -if tonumber(geosite_update) == 1 then - log("geosite 开始更新...") - local status = fetch_geosite() - os.remove("/tmp/geosite.dat") - os.remove("/tmp/geosite.dat.sha256sum") -end - -ucic:set(name, ucic:get_first(name, 'global_rules'), "gfwlist_update", gfwlist_update) -ucic:set(name, ucic:get_first(name, 'global_rules'), "chnroute_update", chnroute_update) -ucic:set(name, ucic:get_first(name, 'global_rules'), "chnroute6_update", chnroute6_update) -ucic:set(name, ucic:get_first(name, 'global_rules'), "chnlist_update", chnlist_update) -ucic:set(name, ucic:get_first(name, 'global_rules'), "geoip_update", geoip_update) -ucic:set(name, ucic:get_first(name, 'global_rules'), "geosite_update", geosite_update) -ucic:save(name) -luci.sys.call("uci commit " .. name) - -if reboot == 1 then - log("重启服务,应用新的规则。") - luci.sys.call("/usr/share/" .. name .. "/iptables.sh flush_ipset > /dev/null 2>&1 &") -end -log("规则更新完毕...") diff --git a/package/lienol/luci-app-passwall/root/usr/share/passwall/rules/adblock.conf b/package/lienol/luci-app-passwall/root/usr/share/passwall/rules/adblock.conf deleted file mode 100644 index 524806b4c1..0000000000 --- a/package/lienol/luci-app-passwall/root/usr/share/passwall/rules/adblock.conf +++ /dev/null @@ -1,6105 +0,0 @@ -address=/lievr.cc/0.0.0.0 -address=/qpokok.com/0.0.0.0 -address=/lolmp4.com/0.0.0.0 -address=/k8yy.tv/0.0.0.0 -address=/caredaily.me/0.0.0.0 -address=/9uys.co/0.0.0.0 -address=/mengbingyuan.com/0.0.0.0 -address=/0024aaaa.com/0.0.0.0 -address=/00880808.com/0.0.0.0 -address=/008844.cc/0.0.0.0 -address=/0133hao.net/0.0.0.0 -address=/02123s.com/0.0.0.0 -address=/022aifang.com/0.0.0.0 -address=/023hysj.com/0.0.0.0 -address=/025suyu.com/0.0.0.0 -address=/0313413.com/0.0.0.0 -address=/0351dvd.cn/0.0.0.0 -address=/0451106.com/0.0.0.0 -address=/04zl.cn/0.0.0.0 -address=/0516bm.com/0.0.0.0 -address=/0531kt.com/0.0.0.0 -address=/0571hy.com/0.0.0.0 -address=/0571yy.com/0.0.0.0 -address=/0592weixin.com/0.0.0.0 -address=/0728w.cn/0.0.0.0 -address=/0756sjlm.com.cn/0.0.0.0 -address=/0796gou.com/0.0.0.0 -address=/0798ls.com/0.0.0.0 -address=/080644.com/0.0.0.0 -address=/0937jyg.com/0.0.0.0 -address=/0bc.top/0.0.0.0 -address=/0nin.cn/0.0.0.0 -address=/0qkc.cn/0.0.0.0 -address=/0xxd.com/0.0.0.0 -address=/1000dy.com/0.0.0.0 -address=/100fenlm.com/0.0.0.0 -address=/103.249.254.113/0.0.0.0 -address=/104.195.62.12/0.0.0.0 -address=/104.197.140.120/0.0.0.0 -address=/104.198.198.188/0.0.0.0 -address=/104.203.214.3/0.0.0.0 -address=/104.203.72.254/0.0.0.0 -address=/104.233.203.164/0.0.0.0 -address=/104.237.67.78/0.0.0.0 -address=/106.187.95.251/0.0.0.0 -address=/107.187.255.178/0.0.0.0 -address=/111111qb.com/0.0.0.0 -address=/112.74.95.46/0.0.0.0 -address=/11370090.net/0.0.0.0 -address=/114.95.102.77/0.0.0.0 -address=/115.238.246.181/0.0.0.0 -address=/116.55.227.242/0.0.0.0 -address=/116zhuce.com/0.0.0.0 -address=/117.25.133.209/0.0.0.0 -address=/118.144.88.216/0.0.0.0 -address=/119.29.207.87/0.0.0.0 -address=/119.4.249.166/0.0.0.0 -address=/12086.net/0.0.0.0 -address=/121.40.25.88/0.0.0.0 -address=/122.114.239.160/0.0.0.0 -address=/122.227.254.195/0.0.0.0 -address=/123.59.150.56/0.0.0.0 -address=/12306media.com/0.0.0.0 -address=/12365chia.com/0.0.0.0 -address=/123hala.com/0.0.0.0 -address=/124.232.160.178/0.0.0.0 -address=/134.73.54.252/0.0.0.0 -address=/138138138.top/0.0.0.0 -address=/138lm.com/0.0.0.0 -address=/139.159.32.82/0.0.0.0 -address=/139.196.166.21/0.0.0.0 -address=/13wnjs.com/0.0.0.0 -address=/1515788.net/0.0.0.0 -address=/154.83.113.19/0.0.0.0 -address=/162.209.213.66/0.0.0.0 -address=/164.155.185.254/0.0.0.0 -address=/1680go.com/0.0.0.0 -address=/16k6.com/0.0.0.0 -address=/170yy.com/0.0.0.0 -address=/174.139.53.195/0.0.0.0 -address=/175bar.com/0.0.0.0 -address=/176um.com/0.0.0.0 -address=/178bx.cn/0.0.0.0 -address=/17tuozhai.com/0.0.0.0 -address=/17un.co/0.0.0.0 -address=/180.76.171.28/0.0.0.0 -address=/1818bobo.com/0.0.0.0 -address=/181lm.net/0.0.0.0 -address=/182.92.81.104/0.0.0.0 -address=/18tzx.com/0.0.0.0 -address=/194.36.101.178/0.0.0.0 -address=/1999sg.com/0.0.0.0 -address=/1d1a.com/0.0.0.0 -address=/1d1px.net/0.0.0.0 -address=/1haosuo.com/0.0.0.0 -address=/1i580.com/0.0.0.0 -address=/1kmb.cn/0.0.0.0 -address=/1kzh.com/0.0.0.0 -address=/1l1.cc/0.0.0.0 -address=/1lib.cn/0.0.0.0 -address=/1q8h.cn/0.0.0.0 -address=/1uandun.com/0.0.0.0 -address=/201071.com/0.0.0.0 -address=/2012ui.com/0.0.0.0 -address=/2048hd.space/0.0.0.0 -address=/211.103.159.32/0.0.0.0 -address=/211.149.225.23/0.0.0.0 -address=/211.167.105.131/0.0.0.0 -address=/218.25.246.118/0.0.0.0 -address=/219.234.83.60/0.0.0.0 -address=/21kk.cc/0.0.0.0 -address=/220.115.251.25/0.0.0.0 -address=/221.204.213.222/0.0.0.0 -address=/222im.com/0.0.0.0 -address=/22lm.cc/0.0.0.0 -address=/23.244.43.212/0.0.0.0 -address=/23.89.50.180/0.0.0.0 -address=/23456dj.com/0.0.0.0 -address=/23dsf.top/0.0.0.0 -address=/258pcf.com/0.0.0.0 -address=/268mob.cn/0.0.0.0 -address=/272xb.com/0.0.0.0 -address=/280dp.com/0.0.0.0 -address=/28487.net/0.0.0.0 -address=/28acglz.com/0.0.0.0 -address=/293870.com/0.0.0.0 -address=/29wjns.com/0.0.0.0 -address=/2d-c.cn/0.0.0.0 -address=/2g2h.com/0.0.0.0 -address=/2m2n.com/0.0.0.0 -address=/2zfzly.com/0.0.0.0 -address=/31365y.com/0.0.0.0 -address=/333dm.com/0.0.0.0 -address=/338336.com/0.0.0.0 -address=/33shangyou.com/0.0.0.0 -address=/3400.org/0.0.0.0 -address=/360baidus.com/0.0.0.0 -address=/361315.cc/0.0.0.0 -address=/365bibi.com/0.0.0.0 -address=/365che.cc/0.0.0.0 -address=/365safego.com/0.0.0.0 -address=/366safego.com/0.0.0.0 -address=/36pn.com/0.0.0.0 -address=/376zf.com/0.0.0.0 -address=/38taobao.com/0.0.0.0 -address=/39xc.net/0.0.0.0 -address=/3amall.cn/0.0.0.0 -address=/3g.990.net/0.0.0.0 -address=/3gmtr.com/0.0.0.0 -address=/3htai.com/0.0.0.0 -address=/3lga3.cn/0.0.0.0 -address=/3qmh.com/0.0.0.0 -address=/3qsys.com/0.0.0.0 -address=/3xx.vip/0.0.0.0 -address=/3ygww.com/0.0.0.0 -address=/4006825178.com/0.0.0.0 -address=/41msl.cn/0.0.0.0 -address=/4480dy.net/0.0.0.0 -address=/45.34.240.72/0.0.0.0 -address=/456juhd.com/0.0.0.0 -address=/46cq.cn/0.0.0.0 -address=/47.90.50.177/0.0.0.0 -address=/4ggww.com/0.0.0.0 -address=/50zera.com/0.0.0.0 -address=/5125129.com/0.0.0.0 -address=/5151gj.com/0.0.0.0 -address=/517m.cn/0.0.0.0 -address=/517pass.com/0.0.0.0 -address=/517xx.com/0.0.0.0 -address=/51fuliwang.cn/0.0.0.0 -address=/51jumintong.com/0.0.0.0 -address=/51sxzz.com/0.0.0.0 -address=/51weidashi.com/0.0.0.0 -address=/51xumei.com/0.0.0.0 -address=/5207470.com/0.0.0.0 -address=/520meirenyu.com/0.0.0.0 -address=/5269120.com/0.0.0.0 -address=/52kmk.com/0.0.0.0 -address=/52yugan.com/0.0.0.0 -address=/52zfl.com/0.0.0.0 -address=/550tg.com/0.0.0.0 -address=/5535aibo.com/0.0.0.0 -address=/57union.com/0.0.0.0 -address=/58.215.179.159/0.0.0.0 -address=/592man.com/0.0.0.0 -address=/593pi.cn/0.0.0.0 -address=/59gt.cn/0.0.0.0 -address=/5a8p12.cn/0.0.0.0 -address=/5eln.cn/0.0.0.0 -address=/5imoney.com/0.0.0.0 -address=/5jcom.com.cn/0.0.0.0 -address=/5pub.com/0.0.0.0 -address=/5rxk.cn/0.0.0.0 -address=/60.190.139.164/0.0.0.0 -address=/61.152.223.15/0.0.0.0 -address=/61.174.50.211/0.0.0.0 -address=/626uc.com/0.0.0.0 -address=/643226.com/0.0.0.0 -address=/652748.com/0.0.0.0 -address=/66.212.56.229/0.0.0.0 -address=/6612151.cn/0.0.0.0 -address=/6612152.cn/0.0.0.0 -address=/664gp.com/0.0.0.0 -address=/6666lm.com/0.0.0.0 -address=/66996.top/0.0.0.0 -address=/66997.top/0.0.0.0 -address=/66998.top/0.0.0.0 -address=/66san.com/0.0.0.0 -address=/6728812.com/0.0.0.0 -address=/68665565.com/0.0.0.0 -address=/69duk.com/0.0.0.0 -address=/6avz.com/0.0.0.0 -address=/6cc8cc.xyz/0.0.0.0 -address=/6dvip.com/0.0.0.0 -address=/6huu.com/0.0.0.0 -address=/6ped2nd3yp.com/0.0.0.0 -address=/700ok.net/0.0.0.0 -address=/70lm.com/0.0.0.0 -address=/70yst.cn/0.0.0.0 -address=/711kk.com/0.0.0.0 -address=/71sem.com/0.0.0.0 -address=/766ba.net/0.0.0.0 -address=/77417.cn/0.0.0.0 -address=/77power.com/0.0.0.0 -address=/7891655.cn/0.0.0.0 -address=/7895983.cn/0.0.0.0 -address=/7a096v.cn/0.0.0.0 -address=/7dah8.com/0.0.0.0 -address=/7gg.cc/0.0.0.0 -address=/7jiajiao.com/0.0.0.0 -address=/7wen.cn/0.0.0.0 -address=/7xi9g1.com1.z0.glb.clouddn.com/0.0.0.0 -address=/7xz3.com/0.0.0.0 -address=/80sjw.com/0.0.0.0 -address=/810251.com/0.0.0.0 -address=/813690.top/0.0.0.0 -address=/81c.cn/0.0.0.0 -address=/825145.com/0.0.0.0 -address=/827649.com/0.0.0.0 -address=/8368661.com/0.0.0.0 -address=/8521448.com/0.0.0.0 -address=/85tgw.com/0.0.0.0 -address=/860010.com/0.0.0.0 -address=/8800271.com.cn/0.0.0.0 -address=/88818122.cn/0.0.0.0 -address=/8881919.cc/0.0.0.0 -address=/88rpg.net/0.0.0.0 -address=/892155.com/0.0.0.0 -address=/89h8.com/0.0.0.0 -address=/8ao8ao.com/0.0.0.0 -address=/8hdp.cn/0.0.0.0 -address=/8mfty.com/0.0.0.0 -address=/8ucdn.com/0.0.0.0 -address=/904ad.com/0.0.0.0 -address=/91luopan.com/0.0.0.0 -address=/91xry.com/0.0.0.0 -address=/91ysa.com/0.0.0.0 -address=/91zgm.com/0.0.0.0 -address=/9377aa.com/0.0.0.0 -address=/9377bh.com/0.0.0.0 -address=/9377co.com/0.0.0.0 -address=/9377hi.com/0.0.0.0 -address=/9377if.com/0.0.0.0 -address=/9377ku.com/0.0.0.0 -address=/9377or.com/0.0.0.0 -address=/9377os.com/0.0.0.0 -address=/93manhua.com/0.0.0.0 -address=/94lm.com/0.0.0.0 -address=/94nw.com/0.0.0.0 -address=/95105012.com/0.0.0.0 -address=/95558000.com/0.0.0.0 -address=/96mob.com/0.0.0.0 -address=/9868.online/0.0.0.0 -address=/9898c.com/0.0.0.0 -address=/991pao.com/0.0.0.0 -address=/99909988.com/0.0.0.0 -address=/99dqw.com/0.0.0.0 -address=/99lolo.com/0.0.0.0 -address=/99pps.com/0.0.0.0 -address=/99tuan.com.cn/0.0.0.0 -address=/9dtiny.cn/0.0.0.0 -address=/9h6qq.cn/0.0.0.0 -address=/9kff.com/0.0.0.0 -address=/9nwg9sib9e.com/0.0.0.0 -address=/9wotuan.com/0.0.0.0 -address=/9xiazaiqi.com/0.0.0.0 -address=/a.youdao.com/0.0.0.0 -address=/a0b11.com/0.0.0.0 -address=/a0b22.com/0.0.0.0 -address=/a0b33.com/0.0.0.0 -address=/a0c66.com/0.0.0.0 -address=/a0c77.com/0.0.0.0 -address=/a0usa.top/0.0.0.0 -address=/a3p4.net/0.0.0.0 -address=/a907907.com/0.0.0.0 -address=/a9377j.com/0.0.0.0 -address=/aazcio.cn/0.0.0.0 -address=/abctcqq.top/0.0.0.0 -address=/acasys88.cn/0.0.0.0 -address=/acwgf.com/0.0.0.0 -address=/ad.52av.tv/0.0.0.0 -address=/ad.muyang888.top/0.0.0.0 -address=/ad000000.com/0.0.0.0 -address=/ad9377.com/0.0.0.0 -address=/adacgov.cn/0.0.0.0 -address=/adbot.tw/0.0.0.0 -address=/address9.com/0.0.0.0 -address=/adget.cn/0.0.0.0 -address=/adidaschile62tracksuit.com/0.0.0.0 -address=/adm-cnzz.net/0.0.0.0 -address=/adnex.tech/0.0.0.0 -address=/adomv.com/0.0.0.0 -address=/adreal.cn/0.0.0.0 -address=/adrs.sdo.com/0.0.0.0 -address=/ads.uc.cn/0.0.0.0 -address=/adsbang.top/0.0.0.0 -address=/adytx.com/0.0.0.0 -address=/aencx.net/0.0.0.0 -address=/aeoprw.cn/0.0.0.0 -address=/afj0.com/0.0.0.0 -address=/afjlb.com/0.0.0.0 -address=/agtsjb.com/0.0.0.0 -address=/agzxj8990.com/0.0.0.0 -address=/ahhuazhen.com/0.0.0.0 -address=/ahjzys.com/0.0.0.0 -address=/ahlxxx.com/0.0.0.0 -address=/ahszgog.com/0.0.0.0 -address=/ahyau.com/0.0.0.0 -address=/ahyuns.com/0.0.0.0 -address=/aigou023.com/0.0.0.0 -address=/aijielang.cn/0.0.0.0 -address=/aishang.bid/0.0.0.0 -address=/aishangcan.com/0.0.0.0 -address=/aishiguolong.com/0.0.0.0 -address=/ajaxcdn.org/0.0.0.0 -address=/ajuhd.com/0.0.0.0 -address=/akrwi.cn/0.0.0.0 -address=/alicmayuns.com/0.0.0.0 -address=/alifixed.cn/0.0.0.0 -address=/alimama.alicdn.com/0.0.0.0 -address=/alimb.top/0.0.0.0 -address=/aliqqjd.cn/0.0.0.0 -address=/alisinak.com/0.0.0.0 -address=/alitianxia168.com/0.0.0.0 -address=/aliyuncss.com/0.0.0.0 -address=/aliyunxin.com/0.0.0.0 -address=/allxin.com/0.0.0.0 -address=/amazingmagics.com/0.0.0.0 -address=/amensh.cn/0.0.0.0 -address=/anastasiaana.com/0.0.0.0 -address=/anioscp.com/0.0.0.0 -address=/anquanzhuomian.cn/0.0.0.0 -address=/anquanzhuomian.com/0.0.0.0 -address=/anreson.net/0.0.0.0 -address=/anzhuocpm.com/0.0.0.0 -address=/apkdo.com/0.0.0.0 -address=/aqgyju.cn/0.0.0.0 -address=/arealx.com/0.0.0.0 -address=/arrows-hitech.com/0.0.0.0 -address=/artedu.pw/0.0.0.0 -address=/as75.info/0.0.0.0 -address=/asir.vip/0.0.0.0 -address=/assigned.cn/0.0.0.0 -address=/aswlx.cn/0.0.0.0 -address=/at98.com/0.0.0.0 -address=/atanx.alicdn.com/0.0.0.0 -address=/audit8.com/0.0.0.0 -address=/auspiciousvp.com/0.0.0.0 -address=/awkjs.com/0.0.0.0 -address=/axhxa.com/0.0.0.0 -address=/axiba66.com/0.0.0.0 -address=/b588866.com/0.0.0.0 -address=/b7nkd.cn/0.0.0.0 -address=/b9377h.com/0.0.0.0 -address=/b99u.top/0.0.0.0 -address=/baiapk.com/0.0.0.0 -address=/baiduace.com/0.0.0.0 -address=/baiduappu.top/0.0.0.0 -address=/baiducom.bj.bcebos.com/0.0.0.0 -address=/baidujavascript.com/0.0.0.0 -address=/baidulao.com/0.0.0.0 -address=/baiduvip.life/0.0.0.0 -address=/baiduyoukualiyun.com/0.0.0.0 -address=/baiduyubaidu.com/0.0.0.0 -address=/baisuijk.com/0.0.0.0 -address=/baiyuandian.cc/0.0.0.0 -address=/bajieyy.cc/0.0.0.0 -address=/bangbang521.com/0.0.0.0 -address=/banjuanmao.com/0.0.0.0 -address=/baolic.com/0.0.0.0 -address=/battmd168a1.xyz/0.0.0.0 -address=/battmd168a2.xyz/0.0.0.0 -address=/bazhigu.com/0.0.0.0 -address=/bbdsdy.com/0.0.0.0 -address=/bccyyc.com/0.0.0.0 -address=/bdpuaw.com/0.0.0.0 -address=/bdtongfei.cn/0.0.0.0 -address=/bdyxzx.com/0.0.0.0 -address=/beatriceeatr.com/0.0.0.0 -address=/bebelait.com/0.0.0.0 -address=/bedhdig.cn/0.0.0.0 -address=/beeho.site/0.0.0.0 -address=/beijinglvyou.net.cn/0.0.0.0 -address=/bejzz.top/0.0.0.0 -address=/bench-life.me/0.0.0.0 -address=/bensezhiye.com/0.0.0.0 -address=/bfgg365.com/0.0.0.0 -address=/biandaosheng.com/0.0.0.0 -address=/biaoshipai.net/0.0.0.0 -address=/bigbos.top/0.0.0.0 -address=/billionfocus.com/0.0.0.0 -address=/bingyinq.com/0.0.0.0 -address=/biochempop.com/0.0.0.0 -address=/bivitr.com/0.0.0.0 -address=/biyibia.com/0.0.0.0 -address=/bj-bytsk.com/0.0.0.0 -address=/bjedpt.com/0.0.0.0 -address=/bjgtsh.com/0.0.0.0 -address=/bjtrld.com/0.0.0.0 -address=/bjyikao.org/0.0.0.0 -address=/bkyhq.cn/0.0.0.0 -address=/bla01.com/0.0.0.0 -address=/bllzgqbyp/0.0.0.0 -address=/blogdaka.cc/0.0.0.0 -address=/blogdaka.xyz/0.0.0.0 -address=/bnq86.com/0.0.0.0 -address=/borsendental.com/0.0.0.0 -address=/bosatria.cn/0.0.0.0 -address=/bosiwangzi.cn/0.0.0.0 -address=/boyueguoji.com/0.0.0.0 -address=/bp776.com/0.0.0.0 -address=/breezily168.com/0.0.0.0 -address=/bskeye.com/0.0.0.0 -address=/bsriedu.cn/0.0.0.0 -address=/btmp4.net/0.0.0.0 -address=/btssy.net/0.0.0.0 -address=/btwan5.com/0.0.0.0 -address=/bv8888.com/0.0.0.0 -address=/bxgmb.com/0.0.0.0 -address=/bxjpl.cn/0.0.0.0 -address=/bxjt518.com/0.0.0.0 -address=/bydonline.com/0.0.0.0 -address=/bypbwm.cn/0.0.0.0 -address=/cachesit.com/0.0.0.0 -address=/cadsips.com/0.0.0.0 -address=/caicool.co/0.0.0.0 -address=/caliyuna.cn/0.0.0.0 -address=/cangnews.com/0.0.0.0 -address=/caob5.info/0.0.0.0 -address=/caolvch.com/0.0.0.0 -address=/carpenterrprp.com/0.0.0.0 -address=/cayanfang.com/0.0.0.0 -address=/cb.baidu.com/0.0.0.0 -address=/cbjs.baidu.com/0.0.0.0 -address=/cc599.com/0.0.0.0 -address=/ccbaihehq.com/0.0.0.0 -address=/cccccd.com/0.0.0.0 -address=/cctyly.com/0.0.0.0 -address=/cd-best.cn/0.0.0.0 -address=/cdlinli.com/0.0.0.0 -address=/cdnjsp.wang/0.0.0.0 -address=/cdnny.com/0.0.0.0 -address=/cdyqc.com/0.0.0.0 -address=/cfboo.com/0.0.0.0 -address=/cferw.com/0.0.0.0 -address=/cfqpxzx.com/0.0.0.0 -address=/cg2017.com/0.0.0.0 -address=/cgskqg.com/0.0.0.0 -address=/chadegongxiao.com/0.0.0.0 -address=/championmachinery-cn.com/0.0.0.0 -address=/chaoliangyun.com/0.0.0.0 -address=/charlesfc.com/0.0.0.0 -address=/chaxinyong.net/0.0.0.0 -address=/chebse.com/0.0.0.0 -address=/chehuanjie.com/0.0.0.0 -address=/chengzhao95511.com/0.0.0.0 -address=/chenyanjiao.cn/0.0.0.0 -address=/china-pengdu.cn/0.0.0.0 -address=/china-star.cc/0.0.0.0 -address=/chinaheh.com/0.0.0.0 -address=/chinaweichu.net/0.0.0.0 -address=/chiuhua.com.cn/0.0.0.0 -address=/chmae.com/0.0.0.0 -address=/chnhty.com/0.0.0.0 -address=/chongxiaota.top/0.0.0.0 -address=/christinehris.com/0.0.0.0 -address=/chromc.com/0.0.0.0 -address=/chucity.com/0.0.0.0 -address=/chuhanweb.com/0.0.0.0 -address=/chushoushijian.cn/0.0.0.0 -address=/chuzushijian.cn/0.0.0.0 -address=/ci-web.cn/0.0.0.0 -address=/ciajingman.com/0.0.0.0 -address=/cj-cy.com/0.0.0.0 -address=/cjsdtj.com/0.0.0.0 -address=/ckseeknew.com/0.0.0.0 -address=/claz.com.cn/0.0.0.0 -address=/clcassd.com/0.0.0.0 -address=/cmaxisolation.com/0.0.0.0 -address=/cmslayue.com/0.0.0.0 -address=/cnbole.net/0.0.0.0 -address=/cncy8.com/0.0.0.0 -address=/cnfanglei.com/0.0.0.0 -address=/cnhbxx.com/0.0.0.0 -address=/cnkok.com/0.0.0.0 -address=/cnpinzhuo.com/0.0.0.0 -address=/cnscdj.com/0.0.0.0 -address=/cnsjx.net/0.0.0.0 -address=/cnxad.net/0.0.0.0 -address=/cnzz.com.so/0.0.0.0 -address=/cnzzlink.com/0.0.0.0 -address=/code222.com/0.0.0.0 -address=/code668.com/0.0.0.0 -address=/compass-fit.jp/0.0.0.0 -address=/cooolyi.cn/0.0.0.0 -address=/corocksi.com/0.0.0.0 -address=/cosoyoo.com/0.0.0.0 -address=/couqm.com.cn/0.0.0.0 -address=/cpcv.cc/0.0.0.0 -address=/cpms.cc/0.0.0.0 -address=/cpro.baidu.com/0.0.0.0 -address=/cpro.baidustatic.com/0.0.0.0 -address=/cpshwl.cn/0.0.0.0 -address=/cpv6.com/0.0.0.0 -address=/cpva.cc/0.0.0.0 -address=/cqfangduan.com/0.0.0.0 -address=/cqftonline.com/0.0.0.0 -address=/cqhnm.com/0.0.0.0 -address=/cqjjlsy.com/0.0.0.0 -address=/cqyhd.com/0.0.0.0 -address=/cralp.cn/0.0.0.0 -address=/crdrjs.info/0.0.0.0 -address=/cre99.com/0.0.0.0 -address=/crywl.com/0.0.0.0 -address=/csbthyhh.com/0.0.0.0 -address=/csgtfruit.com/0.0.0.0 -address=/csqiulong.com/0.0.0.0 -address=/cssdiv.club/0.0.0.0 -address=/cstoa.com/0.0.0.0 -address=/csxsyp.cn/0.0.0.0 -address=/ct1985.com/0.0.0.0 -address=/ctrhfd.top/0.0.0.0 -address=/ctripatm.cn/0.0.0.0 -address=/ctsywy.com/0.0.0.0 -address=/cweclub.cn/0.0.0.0 -address=/cwmlm.com/0.0.0.0 -address=/cxd-ailegou.com/0.0.0.0 -address=/cxfzw.cn/0.0.0.0 -address=/cy-block.cn/0.0.0.0 -address=/cyacc.com/0.0.0.0 -address=/cylinderlongcheng.com/0.0.0.0 -address=/cytcm.com/0.0.0.0 -address=/czdqhyo1.net/0.0.0.0 -address=/czjiuding.cn/0.0.0.0 -address=/czpush.com/0.0.0.0 -address=/czpwm.com/0.0.0.0 -address=/cztanchao.com/0.0.0.0 -address=/d15cjcet1djbmv.cloudfront.net/0.0.0.0 -address=/d3nh49.com/0.0.0.0 -address=/dadjia.com/0.0.0.0 -address=/dafapai.com/0.0.0.0 -address=/dahanedu.com/0.0.0.0 -address=/daima123.cc/0.0.0.0 -address=/dalianhengtai.com/0.0.0.0 -address=/daliantong.com.cn/0.0.0.0 -address=/dami66.cn/0.0.0.0 -address=/danangmo.cn/0.0.0.0 -address=/dandan11.top/0.0.0.0 -address=/dandan13.top/0.0.0.0 -address=/dandan15.top/0.0.0.0 -address=/danpinwu.com/0.0.0.0 -address=/dante2007.com/0.0.0.0 -address=/dashaowu.com/0.0.0.0 -address=/dashet.com/0.0.0.0 -address=/datafastguru.info/0.0.0.0 -address=/dawwx.com/0.0.0.0 -address=/dazhonghua.cn/0.0.0.0 -address=/dazibenwm.com/0.0.0.0 -address=/dbncp.com/0.0.0.0 -address=/dbojetp.cn/0.0.0.0 -address=/ddhtek.com/0.0.0.0 -address=/ddomm.com/0.0.0.0 -address=/detuns.com/0.0.0.0 -address=/df3n43m.com/0.0.0.0 -address=/df77.com/0.0.0.0 -address=/dgpzx.com/0.0.0.0 -address=/dhlmy.com/0.0.0.0 -address=/dhxyzx.cn/0.0.0.0 -address=/di9qu.com.cn/0.0.0.0 -address=/dianwenwang.com/0.0.0.0 -address=/diaojiaoji168.com/0.0.0.0 -address=/dilcn.net/0.0.0.0 -address=/dingon.com.cn/0.0.0.0 -address=/dingyuanyao.cn/0.0.0.0 -address=/diuling.com/0.0.0.0 -address=/dizhonghaihotel.com/0.0.0.0 -address=/djy518.com/0.0.0.0 -address=/dkqapp.cn/0.0.0.0 -address=/dleke.com/0.0.0.0 -address=/dlhygj.com/0.0.0.0 -address=/dlkjgjmy.com/0.0.0.0 -address=/dlpifu.com/0.0.0.0 -address=/dlrijiaele.com/0.0.0.0 -address=/dlzjdesign.com/0.0.0.0 -address=/dnskuu.com/0.0.0.0 -address=/dnvus.com/0.0.0.0 -address=/door2new.net/0.0.0.0 -address=/dou777.com/0.0.0.0 -address=/doudao.cn/0.0.0.0 -address=/dpc6.cn/0.0.0.0 -address=/dpjszs.com/0.0.0.0 -address=/dqsft.com/0.0.0.0 -address=/dragoncent.com/0.0.0.0 -address=/dreamfull.cn/0.0.0.0 -address=/drjgjngf.com/0.0.0.0 -address=/drlsf.com/0.0.0.0 -address=/drmcmm.baidu.com/0.0.0.0 -address=/drmfslx.cn/0.0.0.0 -address=/drxrc.com/0.0.0.0 -address=/dshrx.com/0.0.0.0 -address=/dszan.com/0.0.0.0 -address=/dtrcw.cc/0.0.0.0 -address=/dugbvb.com/0.0.0.0 -address=/duiwai.baidu.com/0.0.0.0 -address=/duobaoqj.com/0.0.0.0 -address=/duoduo.icu/0.0.0.0 -address=/duoqumanhua.com/0.0.0.0 -address=/duusuu.com/0.0.0.0 -address=/duyihu.net/0.0.0.0 -address=/dvr8.com/0.0.0.0 -address=/dw998.com/0.0.0.0 -address=/dx1200.com/0.0.0.0 -address=/dxssiyi.com/0.0.0.0 -address=/dy886.cn/0.0.0.0 -address=/dy8nb.com/0.0.0.0 -address=/dyssir.com/0.0.0.0 -address=/dzjzg.com/0.0.0.0 -address=/dzletao.com/0.0.0.0 -address=/dzxwnews.com/0.0.0.0 -address=/e-demx.com/0.0.0.0 -address=/e-heater.vip/0.0.0.0 -address=/e7001.com/0.0.0.0 -address=/e7002.com/0.0.0.0 -address=/e7009.com/0.0.0.0 -address=/e701.net/0.0.0.0 -address=/e70123.com/0.0.0.0 -address=/e7015.com/0.0.0.0 -address=/e704.net/0.0.0.0 -address=/e705.net/0.0.0.0 -address=/e706.net/0.0.0.0 -address=/e708.net/0.0.0.0 -address=/e719.net/0.0.0.0 -address=/ecuc123.net/0.0.0.0 -address=/eddjf.com/0.0.0.0 -address=/edncui.net/0.0.0.0 -address=/edo5.com/0.0.0.0 -address=/eduad.baidu.com/0.0.0.0 -address=/eduzzjy.com/0.0.0.0 -address=/eeee500.com/0.0.0.0 -address=/egjq.com.cn/0.0.0.0 -address=/einsuran.com.cn/0.0.0.0 -address=/eiv.baidu.com/0.0.0.0 -address=/ekeide.com/0.0.0.0 -address=/enohb.com/0.0.0.0 -address=/erdsyzb.com/0.0.0.0 -address=/erosyndc.com/0.0.0.0 -address=/erqimall.net/0.0.0.0 -address=/ethic.vip/0.0.0.0 -address=/evefashion.cn/0.0.0.0 -address=/expo123.net/0.0.0.0 -address=/eyd77s.com/0.0.0.0 -address=/ez33.org.cn/0.0.0.0 -address=/ezucods.cn/0.0.0.0 -address=/f1190.com/0.0.0.0 -address=/f2zd.com/0.0.0.0 -address=/f6ce.com/0.0.0.0 -address=/f70123.com/0.0.0.0 -address=/facebookma.cn/0.0.0.0 -address=/family-joy.com/0.0.0.0 -address=/fanli.in/0.0.0.0 -address=/farm-cn.plista.com/0.0.0.0 -address=/fastable.com/0.0.0.0 -address=/fccxgjg.com/0.0.0.0 -address=/fcsass.org.cn/0.0.0.0 -address=/fd7c.com/0.0.0.0 -address=/fdzsmfyy.com/0.0.0.0 -address=/fecjf.cn/0.0.0.0 -address=/feisia1.cn/0.0.0.0 -address=/fenggejiaju.com/0.0.0.0 -address=/fengyelin.net/0.0.0.0 -address=/fexiaen.com/0.0.0.0 -address=/ff112244.com/0.0.0.0 -address=/ffa9.cn/0.0.0.0 -address=/ffhtek.com/0.0.0.0 -address=/fjbzjc.com/0.0.0.0 -address=/fjkst.com/0.0.0.0 -address=/fjmeyer.com/0.0.0.0 -address=/fjsjsj.com/0.0.0.0 -address=/flowcodeapp.com/0.0.0.0 -address=/fnkjj.com/0.0.0.0 -address=/focusprolight.com/0.0.0.0 -address=/foreveryoung.gz01.bdysite.com/0.0.0.0 -address=/forrerri.com/0.0.0.0 -address=/fos123.com/0.0.0.0 -address=/founseezb.cn/0.0.0.0 -address=/fqtra.com/0.0.0.0 -address=/fst360.com/0.0.0.0 -address=/fsyzcs.com/0.0.0.0 -address=/ft76531.com/0.0.0.0 -address=/fthcz.com/0.0.0.0 -address=/fu68.com/0.0.0.0 -address=/fujianryt.com/0.0.0.0 -address=/fuxunb.com/0.0.0.0 -address=/fv99.com/0.0.0.0 -address=/fwqekk.top/0.0.0.0 -address=/fwt0.com/0.0.0.0 -address=/fxmacd.com/0.0.0.0 -address=/fxtducb.cn/0.0.0.0 -address=/fydgold132.com/0.0.0.0 -address=/fytza.cn/0.0.0.0 -address=/fzglqyy.com/0.0.0.0 -address=/g1.tagtic.cn/0.0.0.0 -address=/g1c5.com/0.0.0.0 -address=/g1f5.com/0.0.0.0 -address=/gangtiebang.net/0.0.0.0 -address=/gaoxiaocup.com/0.0.0.0 -address=/garacy.cn/0.0.0.0 -address=/gasxf.com/0.0.0.0 -address=/gaycloud.cn/0.0.0.0 -address=/gdbly.com/0.0.0.0 -address=/gdgy56.com/0.0.0.0 -address=/gdskywings.com/0.0.0.0 -address=/ge95.com/0.0.0.0 -address=/geili.co/0.0.0.0 -address=/geiyujieda.com/0.0.0.0 -address=/geryi.com/0.0.0.0 -address=/gf108.com/0.0.0.0 -address=/gf1352.com/0.0.0.0 -address=/gfd80.com/0.0.0.0 -address=/gg0376.com/0.0.0.0 -address=/gg570.com/0.0.0.0 -address=/ggdoubi.com/0.0.0.0 -address=/ggdydz.com/0.0.0.0 -address=/ggweb.net/0.0.0.0 -address=/ghnmg.top/0.0.0.0 -address=/ghosttty.cn/0.0.0.0 -address=/gjghy.com/0.0.0.0 -address=/glasszz.com/0.0.0.0 -address=/gm682.com/0.0.0.0 -address=/goge365-baidu.com/0.0.0.0 -address=/goodgz.cn/0.0.0.0 -address=/googlealiyun.cn/0.0.0.0 -address=/googletakes.com/0.0.0.0 -address=/gotoniubiurl.pw/0.0.0.0 -address=/gouhei.top/0.0.0.0 -address=/gouzhibao.cn/0.0.0.0 -address=/govgift.com/0.0.0.0 -address=/gowin01.com/0.0.0.0 -address=/gqswg.com/0.0.0.0 -address=/greenbetterkids.com/0.0.0.0 -address=/gshtrl.top/0.0.0.0 -address=/gso0.com/0.0.0.0 -address=/gssxb.com/0.0.0.0 -address=/gsycdb.com/0.0.0.0 -address=/gszbba.cn/0.0.0.0 -address=/gtmucs.cn/0.0.0.0 -address=/guangzizai.com/0.0.0.0 -address=/guduopu.com/0.0.0.0 -address=/gugulonger.cn/0.0.0.0 -address=/guidashu.com/0.0.0.0 -address=/guoshennet.com/0.0.0.0 -address=/guoxintdh.com/0.0.0.0 -address=/gutouwang.net/0.0.0.0 -address=/guzijie.top/0.0.0.0 -address=/gw069.com/0.0.0.0 -address=/gwylm.com/0.0.0.0 -address=/gxejgs.com/0.0.0.0 -address=/gxgzyny.com/0.0.0.0 -address=/gxhxmy88.com/0.0.0.0 -address=/gydag.com/0.0.0.0 -address=/gygdmy.com/0.0.0.0 -address=/gzdhzb.com/0.0.0.0 -address=/gze3.cn/0.0.0.0 -address=/gzktpf.com/0.0.0.0 -address=/gzmjnx.cn/0.0.0.0 -address=/gzqudou.com/0.0.0.0 -address=/gzxiongwa.cn/0.0.0.0 -address=/gzxxty168.com/0.0.0.0 -address=/h0o33.cn/0.0.0.0 -address=/h9377c.com/0.0.0.0 -address=/haitejs.com/0.0.0.0 -address=/haiwengji.net/0.0.0.0 -address=/haiyunimg.com/0.0.0.0 -address=/haiyunpush.com/0.0.0.0 -address=/haizirv.cn/0.0.0.0 -address=/hanju18.net/0.0.0.0 -address=/hanqidq.com/0.0.0.0 -address=/hao123rt.com/0.0.0.0 -address=/hao61.net/0.0.0.0 -address=/haohaowan8.com/0.0.0.0 -address=/haolew.com/0.0.0.0 -address=/harridan.cc/0.0.0.0 -address=/hascosafety.com/0.0.0.0 -address=/hbalx.cn/0.0.0.0 -address=/hbguohua.com/0.0.0.0 -address=/hbhnwy.com/0.0.0.0 -address=/hbhtbn.com/0.0.0.0 -address=/hblinwei.com/0.0.0.0 -address=/hbngfy.com/0.0.0.0 -address=/hbssjd.cn/0.0.0.0 -address=/hbstty.com/0.0.0.0 -address=/hbyingchang.cn/0.0.0.0 -address=/hbzjht.com/0.0.0.0 -address=/hcreditx.com/0.0.0.0 -address=/hcwljy.com/0.0.0.0 -address=/heib10.top/0.0.0.0 -address=/heib12.top/0.0.0.0 -address=/hejingroup.cn/0.0.0.0 -address=/helanpinpai.com/0.0.0.0 -address=/hengshui1.com/0.0.0.0 -address=/hesxz.com/0.0.0.0 -address=/heygugu.com/0.0.0.0 -address=/hezhenzi.com/0.0.0.0 -address=/hfjuki.com/0.0.0.0 -address=/hfsteel.net/0.0.0.0 -address=/hg-labs.com/0.0.0.0 -address=/hhhhbf.com/0.0.0.0 -address=/hhly88.com/0.0.0.0 -address=/hhppyt.com/0.0.0.0 -address=/hi760.com/0.0.0.0 -address=/hiad.myweb.hinet.net/0.0.0.0 -address=/hivecn.cn/0.0.0.0 -address=/hk662.com/0.0.0.0 -address=/hkfuy.com/0.0.0.0 -address=/hktv10.com/0.0.0.0 -address=/hmnjf.com/0.0.0.0 -address=/hmp33.com/0.0.0.0 -address=/hnasd.com/0.0.0.0 -address=/hnctsm.com/0.0.0.0 -address=/hnfpgm.com/0.0.0.0 -address=/hnh-hotel.com/0.0.0.0 -address=/hnhycp.com/0.0.0.0 -address=/hntymg.com/0.0.0.0 -address=/hnyiche3.com/0.0.0.0 -address=/hnyny.com/0.0.0.0 -address=/hongchenzhilu.com/0.0.0.0 -address=/hongtefm.com/0.0.0.0 -address=/hot-eam.com/0.0.0.0 -address=/houdaolj.com/0.0.0.0 -address=/houtanyun.com/0.0.0.0 -address=/hqygz.com/0.0.0.0 -address=/hr41.cn/0.0.0.0 -address=/hr44.com/0.0.0.0 -address=/hrbpay.com/0.0.0.0 -address=/hrcmzp.cn/0.0.0.0 -address=/hskj.net/0.0.0.0 -address=/hslyqs.com/0.0.0.0 -address=/huaerduo.com/0.0.0.0 -address=/huanqiucaizhi.com/0.0.0.0 -address=/huapuzs.com/0.0.0.0 -address=/huashengtai.net/0.0.0.0 -address=/huashuowork.com/0.0.0.0 -address=/hubojd.com/0.0.0.0 -address=/huichenbz.com/0.0.0.0 -address=/huimee.net/0.0.0.0 -address=/humanding.com/0.0.0.0 -address=/hurom365.cn/0.0.0.0 -address=/hw6.com/0.0.0.0 -address=/hxadt.com/0.0.0.0 -address=/hxgccl.cn/0.0.0.0 -address=/hxlif.com/0.0.0.0 -address=/hxnzyy.com/0.0.0.0 -address=/hxscba.com/0.0.0.0 -address=/hxtwl.cn/0.0.0.0 -address=/hxyifu.com/0.0.0.0 -address=/hxyx360.com/0.0.0.0 -address=/hylyl.club/0.0.0.0 -address=/hys4.com/0.0.0.0 -address=/hysjm.cn/0.0.0.0 -address=/hystq.com/0.0.0.0 -address=/hytgj.com/0.0.0.0 -address=/hyz86.com/0.0.0.0 -address=/hzaibi.com/0.0.0.0 -address=/hzmiyou.cn/0.0.0.0 -address=/hzxma.com/0.0.0.0 -address=/i.zhuoyaju.com/0.0.0.0 -address=/i3818.com/0.0.0.0 -address=/i92xue.com/0.0.0.0 -address=/icemf.com/0.0.0.0 -address=/id528.com/0.0.0.0 -address=/idasai.com/0.0.0.0 -address=/idasui.cn/0.0.0.0 -address=/idcqi.com/0.0.0.0 -address=/idianfang.com/0.0.0.0 -address=/idoc58.com/0.0.0.0 -address=/ie8q.cn/0.0.0.0 -address=/ienkdaged.cn/0.0.0.0 -address=/iewad.net/0.0.0.0 -address=/if1512.com/0.0.0.0 -address=/ifufen.com/0.0.0.0 -address=/ihualun.com/0.0.0.0 -address=/il8r.com/0.0.0.0 -address=/ilovechenyuqian.xyz/0.0.0.0 -address=/img1122.com/0.0.0.0 -address=/img80.net/0.0.0.0 -address=/imneinei.com/0.0.0.0 -address=/inpetusgames.com/0.0.0.0 -address=/insuf.cn/0.0.0.0 -address=/iomsew.com/0.0.0.0 -address=/iqiyi.kim/0.0.0.0 -address=/iqiyi.pub/0.0.0.0 -address=/iqu-operation.com/0.0.0.0 -address=/iroby.com/0.0.0.0 -address=/isabelisa.com/0.0.0.0 -address=/ishowbg.com/0.0.0.0 -address=/italy-lottery.com/0.0.0.0 -address=/itemccmod.com/0.0.0.0 -address=/iuuff.com/0.0.0.0 -address=/iwansf.com/0.0.0.0 -address=/iyoowi.com/0.0.0.0 -address=/iyptc.cn/0.0.0.0 -address=/iyygzs.com/0.0.0.0 -address=/j94.cc/0.0.0.0 -address=/ja9377.com/0.0.0.0 -address=/jackaow.com/0.0.0.0 -address=/jbyy010.com/0.0.0.0 -address=/jcdfdhx.top/0.0.0.0 -address=/jczzjx.com/0.0.0.0 -address=/jdlcg.cn/0.0.0.0 -address=/jdlhg.com/0.0.0.0 -address=/jermr.com/0.0.0.0 -address=/jfjsp.com/0.0.0.0 -address=/jfqkj.com/0.0.0.0 -address=/jgchq.com/0.0.0.0 -address=/jghcy.com/0.0.0.0 -address=/jgwsmqx.com/0.0.0.0 -address=/jhakie.com/0.0.0.0 -address=/jhtcdj.com/0.0.0.0 -address=/jhzl001.com/0.0.0.0 -address=/jiaheyonggu.com/0.0.0.0 -address=/jiajv.net/0.0.0.0 -address=/jianbaimei.com/0.0.0.0 -address=/jianbangjiaoyu.com/0.0.0.0 -address=/jianduankm.com/0.0.0.0 -address=/jianglongjie.cn/0.0.0.0 -address=/jiangmg.com/0.0.0.0 -address=/jianjiaovip.vip/0.0.0.0 -address=/jianmei123.com/0.0.0.0 -address=/jianyousj.com/0.0.0.0 -address=/jiasdart.cn/0.0.0.0 -address=/jiehantai.com/0.0.0.0 -address=/jiekc.com/0.0.0.0 -address=/jimeilm.com/0.0.0.0 -address=/jindu179.com/0.0.0.0 -address=/jingezhao.cn/0.0.0.0 -address=/jinglongtang.cn/0.0.0.0 -address=/jinshasi.cn/0.0.0.0 -address=/jiuku.cc/0.0.0.0 -address=/jiupinshan.cn/0.0.0.0 -address=/jiyou2014.com/0.0.0.0 -address=/jjxgly.com/0.0.0.0 -address=/jjz666.cn/0.0.0.0 -address=/jk939.com/0.0.0.0 -address=/jkjjkj.top/0.0.0.0 -address=/jkmxy.com/0.0.0.0 -address=/jktopia.com/0.0.0.0 -address=/jl027.com/0.0.0.0 -address=/jlssbz.com/0.0.0.0 -address=/jlwljym.com/0.0.0.0 -address=/jnyngg.cn/0.0.0.0 -address=/johtzj.com/0.0.0.0 -address=/josipr.com/0.0.0.0 -address=/jossuer.net/0.0.0.0 -address=/joyfuldoors.com/0.0.0.0 -address=/jozee.cn/0.0.0.0 -address=/jqsex.com/0.0.0.0 -address=/jqz9.com/0.0.0.0 -address=/js.xiao7cdn.com/0.0.0.0 -address=/js88895.net/0.0.0.0 -address=/jsadt.com/0.0.0.0 -address=/jschuangnuo.com/0.0.0.0 -address=/jscsd.cn/0.0.0.0 -address=/jsmwd.com/0.0.0.0 -address=/jsyxfdj.com/0.0.0.0 -address=/jsyzw132.com/0.0.0.0 -address=/jtdxz.top/0.0.0.0 -address=/jtkshop.net/0.0.0.0 -address=/jucaishequ.com/0.0.0.0 -address=/junfull.com/0.0.0.0 -address=/junkucm.com/0.0.0.0 -address=/jushikk.com/0.0.0.0 -address=/jutou5.com/0.0.0.0 -address=/juuhe.com/0.0.0.0 -address=/juyiqiche.com.cn/0.0.0.0 -address=/jwqj.net/0.0.0.0 -address=/jx118114.net/0.0.0.0 -address=/jxabp.com.cn/0.0.0.0 -address=/jxbjt.com/0.0.0.0 -address=/jxjzny.com/0.0.0.0 -address=/jxlqgs.com/0.0.0.0 -address=/jxsgxzx.com/0.0.0.0 -address=/jxwlkssb.com/0.0.0.0 -address=/jxxiangchu.com/0.0.0.0 -address=/jystea.com/0.0.0.0 -address=/k12shequ.com/0.0.0.0 -address=/k1815.com/0.0.0.0 -address=/ka12138.top/0.0.0.0 -address=/kan8.xyz/0.0.0.0 -address=/kawa11.space/0.0.0.0 -address=/kawinhome.com/0.0.0.0 -address=/kddtri.cn/0.0.0.0 -address=/kdqoehj.top/0.0.0.0 -address=/kehuziliaona.com/0.0.0.0 -address=/kele4.com/0.0.0.0 -address=/keyyou.net/0.0.0.0 -address=/kf3msfm.com/0.0.0.0 -address=/kfd3sm2c.com/0.0.0.0 -address=/kfi8.com/0.0.0.0 -address=/kfluoa.com/0.0.0.0 -address=/kgcj00.cn/0.0.0.0 -address=/kgcjgsa8.net/0.0.0.0 -address=/kguke.com/0.0.0.0 -address=/kh2134.com/0.0.0.0 -address=/khufaw2.com/0.0.0.0 -address=/kicnse.com/0.0.0.0 -address=/kilin.xyz/0.0.0.0 -address=/kingpolo.com.cn/0.0.0.0 -address=/kingwam.com/0.0.0.0 -address=/kitchenfurniture.cc/0.0.0.0 -address=/kjfoqi.cn/0.0.0.0 -address=/kjgen.com/0.0.0.0 -address=/kjwx8.com/0.0.0.0 -address=/kkcaicai.com/0.0.0.0 -address=/kl-toys.com/0.0.0.0 -address=/kld666.com/0.0.0.0 -address=/kldmm.com/0.0.0.0 -address=/klsdmr.com/0.0.0.0 -address=/kltces.com/0.0.0.0 -address=/kmadou.com/0.0.0.0 -address=/kmwqxqh.com/0.0.0.0 -address=/kod4pc293.com/0.0.0.0 -address=/kojwex.top/0.0.0.0 -address=/kokofits.com/0.0.0.0 -address=/kooyum.com/0.0.0.0 -address=/koukou7.com/0.0.0.0 -address=/kouwku.cn/0.0.0.0 -address=/kqy1.com/0.0.0.0 -address=/ksrsy.com/0.0.0.0 -address=/kt220.com/0.0.0.0 -address=/ktunions.com/0.0.0.0 -address=/ktv0311.com/0.0.0.0 -address=/ku9377.com/0.0.0.0 -address=/kuaipai666.cn/0.0.0.0 -address=/kuaizuoffice.com/0.0.0.0 -address=/kuwoyy.com/0.0.0.0 -address=/kwiago.com/0.0.0.0 -address=/kxrxh.com/0.0.0.0 -address=/kyouad.com/0.0.0.0 -address=/ladsblue.com/0.0.0.0 -address=/laifu365.com/0.0.0.0 -address=/lala-my.club/0.0.0.0 -address=/lamwatch.com/0.0.0.0 -address=/langchars.com/0.0.0.0 -address=/lanxiangji.com/0.0.0.0 -address=/laobei.top/0.0.0.0 -address=/laolinow.com/0.0.0.0 -address=/lashou1000.com/0.0.0.0 -address=/lc1b2.cn/0.0.0.0 -address=/lc442.com/0.0.0.0 -address=/ldgjhd.net/0.0.0.0 -address=/le4le.com/0.0.0.0 -address=/leamain.net/0.0.0.0 -address=/leeleo.top/0.0.0.0 -address=/leletuitui.com/0.0.0.0 -address=/leshigov.cn/0.0.0.0 -address=/letaojuan68.com/0.0.0.0 -address=/leztc.com/0.0.0.0 -address=/lfhnkp.com/0.0.0.0 -address=/lflili.com/0.0.0.0 -address=/lflucky.com/0.0.0.0 -address=/lhafy.com/0.0.0.0 -address=/lhengilin.com/0.0.0.0 -address=/lhusy.com/0.0.0.0 -address=/liangziweixg.com/0.0.0.0 -address=/librarymanagement.cn/0.0.0.0 -address=/lifu11.com/0.0.0.0 -address=/liliwoin.top/0.0.0.0 -address=/linjiajia.cn/0.0.0.0 -address=/linkbide.com/0.0.0.0 -address=/linkpage.cn/0.0.0.0 -address=/linkwuliu.com/0.0.0.0 -address=/lintyone.top/0.0.0.0 -address=/lisaiservice.top/0.0.0.0 -address=/lishuanghao.com/0.0.0.0 -address=/litlif.net/0.0.0.0 -address=/livehapp.com/0.0.0.0 -address=/lixuanbaojie.com/0.0.0.0 -address=/ljqnbiogjp.com/0.0.0.0 -address=/llguandongyan.com/0.0.0.0 -address=/llqss.top/0.0.0.0 -address=/lnctc.net/0.0.0.0 -address=/lnfund.org.cn/0.0.0.0 -address=/loandatec.com/0.0.0.0 -address=/log.interest.mix.sina.com.cn/0.0.0.0 -address=/long88.app/0.0.0.0 -address=/loveconer.com/0.0.0.0 -address=/lovestyl.com/0.0.0.0 -address=/lovexia.top/0.0.0.0 -address=/lsper.top/0.0.0.0 -address=/lsxmg.com/0.0.0.0 -address=/ltcprtc.com/0.0.0.0 -address=/ltdnc.com/0.0.0.0 -address=/lthxz.cn/0.0.0.0 -address=/lu.sogou.com/0.0.0.0 -address=/lu.sogoucdn.com/0.0.0.0 -address=/lubosheng.cn/0.0.0.0 -address=/lucting.cn/0.0.0.0 -address=/luntan588.space/0.0.0.0 -address=/luoyuanedu.cn/0.0.0.0 -address=/lv55p.cn/0.0.0.0 -address=/lvehaisen.com/0.0.0.0 -address=/lxqcgj.com/0.0.0.0 -address=/lyadu.com/0.0.0.0 -address=/lyaeccn.com/0.0.0.0 -address=/lygshgj.com/0.0.0.0 -address=/lyhdream.com/0.0.0.0 -address=/lymstsc.com/0.0.0.0 -address=/lyraik.cn/0.0.0.0 -address=/lyrymy.com/0.0.0.0 -address=/lytubaobao.com/0.0.0.0 -address=/lyunsd.cn/0.0.0.0 -address=/lyztdz.com/0.0.0.0 -address=/lzmm8.com/0.0.0.0 -address=/lzwla.top/0.0.0.0 -address=/magictreehouse.cn/0.0.0.0 -address=/magiphone.cn/0.0.0.0 -address=/maibahe300cc.com/0.0.0.0 -address=/mainbx.com/0.0.0.0 -address=/maisoncherry.com/0.0.0.0 -address=/maizhenai.cn/0.0.0.0 -address=/mall043.com/0.0.0.0 -address=/manparis.cn/0.0.0.0 -address=/maskbaby.com.cn/0.0.0.0 -address=/maxfull.info/0.0.0.0 -address=/mcdhshlsboom.com/0.0.0.0 -address=/meicubao.cn/0.0.0.0 -address=/meilides.com/0.0.0.0 -address=/meimeidaren.com/0.0.0.0 -address=/meimeiha.com/0.0.0.0 -address=/meiti1.net/0.0.0.0 -address=/mengheyu.com/0.0.0.0 -address=/menghuanzs.com/0.0.0.0 -address=/mengmengdas.com/0.0.0.0 -address=/mengyuanwei.com/0.0.0.0 -address=/metmt.com/0.0.0.0 -address=/mfcvxw.cn/0.0.0.0 -address=/mglvqian.com/0.0.0.0 -address=/mgwcn.com/0.0.0.0 -address=/mieyisi.com/0.0.0.0 -address=/min1319.com/0.0.0.0 -address=/mindopu.com/0.0.0.0 -address=/mingxianshanghang.cn/0.0.0.0 -address=/mingysh.com/0.0.0.0 -address=/mjx123.com/0.0.0.0 -address=/mkaqh.cn/0.0.0.0 -address=/mlt01.com/0.0.0.0 -address=/mm-cgnews.com/0.0.0.0 -address=/mmpnierhio.com/0.0.0.0 -address=/mnxtu.com/0.0.0.0 -address=/mofun.ltd/0.0.0.0 -address=/moguozhi.com/0.0.0.0 -address=/moodoocrv.com.cn/0.0.0.0 -address=/moonwish.com.cn/0.0.0.0 -address=/motohelpr.com/0.0.0.0 -address=/moutaihotel.cn/0.0.0.0 -address=/mozist.com/0.0.0.0 -address=/mr087.cn/0.0.0.0 -address=/mrksys.com/0.0.0.0 -address=/ms758.com/0.0.0.0 -address=/mscimg.com/0.0.0.0 -address=/msltzer.cn/0.0.0.0 -address=/mstzym.com/0.0.0.0 -address=/msujd.cn/0.0.0.0 -address=/mtqys.com/0.0.0.0 -address=/mu722.com/0.0.0.0 -address=/mushan.xin/0.0.0.0 -address=/mxdregs.com/0.0.0.0 -address=/mxmrt.com/0.0.0.0 -address=/mygeneclub.com/0.0.0.0 -address=/mytzdhz.cn/0.0.0.0 -address=/myzk1.com/0.0.0.0 -address=/namemek.com/0.0.0.0 -address=/nangong2.com/0.0.0.0 -address=/nbhxgjz.com/0.0.0.0 -address=/nbjjd.com/0.0.0.0 -address=/nbzq.net/0.0.0.0 -address=/ncachear.com/0.0.0.0 -address=/nchte.com/0.0.0.0 -address=/ndtzx.com/0.0.0.0 -address=/ne9377.com/0.0.0.0 -address=/newjulads.com/0.0.0.0 -address=/newsatads.com/0.0.0.0 -address=/newtech-beauty.com/0.0.0.0 -address=/newyiba.top/0.0.0.0 -address=/nextcps.com/0.0.0.0 -address=/ni87.com/0.0.0.0 -address=/nihaomama.monster/0.0.0.0 -address=/nijiua.com/0.0.0.0 -address=/niubiba.com/0.0.0.0 -address=/niuguwang.net.cn/0.0.0.0 -address=/niulail.top/0.0.0.0 -address=/niuxgame77.com/0.0.0.0 -address=/njdijiani.com/0.0.0.0 -address=/njfsk.com/0.0.0.0 -address=/njjrlf.com/0.0.0.0 -address=/njmpacc.com/0.0.0.0 -address=/njq.net/0.0.0.0 -address=/njwxh.com/0.0.0.0 -address=/nkeo.top/0.0.0.0 -address=/nkjwmb.com/0.0.0.0 -address=/nklwgj.com/0.0.0.0 -address=/nkrwxf.com/0.0.0.0 -address=/nkscdn.com/0.0.0.0 -address=/nktcw.cn/0.0.0.0 -address=/nktwpc.com/0.0.0.0 -address=/nmeithybnvik.com/0.0.0.0 -address=/nmkgs.cn/0.0.0.0 -address=/nmpcdn.com/0.0.0.0 -address=/nmqbg.com/0.0.0.0 -address=/nnedbx.com/0.0.0.0 -address=/nngft.com/0.0.0.0 -address=/noberlmall.com/0.0.0.0 -address=/nongsalei.com/0.0.0.0 -address=/notice.uchome.manyou.com/0.0.0.0 -address=/nowskip.com/0.0.0.0 -address=/nr1234.com/0.0.0.0 -address=/nsnmiaomu.cn/0.0.0.0 -address=/nterbx.com/0.0.0.0 -address=/nthtcs.com/0.0.0.0 -address=/ntxiangtai.com/0.0.0.0 -address=/nunc-china.com/0.0.0.0 -address=/nuonuo1.icu/0.0.0.0 -address=/nuxyz.cn/0.0.0.0 -address=/nvshuyun.com/0.0.0.0 -address=/nxrhs.com/0.0.0.0 -address=/nydql.com/0.0.0.0 -address=/nysita.com/0.0.0.0 -address=/nzezn.com/0.0.0.0 -address=/nzydzsw.com/0.0.0.0 -address=/o6uea.cn/0.0.0.0 -address=/oacustom.com/0.0.0.0 -address=/oaer9.cn/0.0.0.0 -address=/officeme.cn/0.0.0.0 -address=/oikxlcv.wang/0.0.0.0 -address=/okm918.com/0.0.0.0 -address=/olmall.vip/0.0.0.0 -address=/olmvkq.cn/0.0.0.0 -address=/olxt.top/0.0.0.0 -address=/omgnjvrjgpeg.com/0.0.0.0 -address=/omztf.cn/0.0.0.0 -address=/onlifjj.net/0.0.0.0 -address=/onsnv.com/0.0.0.0 -address=/openxt.cn/0.0.0.0 -address=/oq68.com/0.0.0.0 -address=/orchidscape.net/0.0.0.0 -address=/oumazg.com/0.0.0.0 -address=/overlordtea.cn/0.0.0.0 -address=/p3tt.com/0.0.0.0 -address=/p74.cc/0.0.0.0 -address=/panel-cn.com/0.0.0.0 -address=/papajia55.com/0.0.0.0 -address=/partner-safe.men/0.0.0.0 -address=/partnerwork.men/0.0.0.0 -address=/pay838.com/0.0.0.0 -address=/pcmzn.com/0.0.0.0 -address=/pdsjycm.com/0.0.0.0 -address=/pedailyu.com/0.0.0.0 -address=/penggua.com.cn/0.0.0.0 -address=/penxiangge.com/0.0.0.0 -address=/picsinfog.com/0.0.0.0 -address=/pjshw.cn/0.0.0.0 -address=/pjtymy.cn/0.0.0.0 -address=/pnhfc.com/0.0.0.0 -address=/pnxs.com/0.0.0.0 -address=/pofang.com/0.0.0.0 -address=/poijugh.top/0.0.0.0 -address=/poke88.com/0.0.0.0 -address=/polkoa.com/0.0.0.0 -address=/popeng.top/0.0.0.0 -address=/pos.baidu.com/0.0.0.0 -address=/powergg.top/0.0.0.0 -address=/poyang.com/0.0.0.0 -address=/pr00001.com/0.0.0.0 -address=/prohibited.cn/0.0.0.0 -address=/ptdrw.com/0.0.0.0 -address=/ptkhy.com/0.0.0.0 -address=/pubbirdf.com/0.0.0.0 -address=/pyzkk.com/0.0.0.0 -address=/pzrj6.top/0.0.0.0 -address=/qarsza.cn/0.0.0.0 -address=/qbyy010.com/0.0.0.0 -address=/qclcdn.cn/0.0.0.0 -address=/qcupup.com/0.0.0.0 -address=/qdchunyu.com/0.0.0.0 -address=/qdsfzz.cn/0.0.0.0 -address=/qfs365.com/0.0.0.0 -address=/qgjapp.com/0.0.0.0 -address=/qgss8.com/0.0.0.0 -address=/qhaif.com/0.0.0.0 -address=/qi-duo.com/0.0.0.0 -address=/qiailm.com/0.0.0.0 -address=/qianfuyin.com/0.0.0.0 -address=/qianmeiby.com/0.0.0.0 -address=/qigemm.com/0.0.0.0 -address=/qilashou.com/0.0.0.0 -address=/qingqu.la/0.0.0.0 -address=/qipskd.cn/0.0.0.0 -address=/qiqivv.com/0.0.0.0 -address=/qiqiww.com/0.0.0.0 -address=/qiqiyii.com/0.0.0.0 -address=/qjjtc.com/0.0.0.0 -address=/qjyzj.cn/0.0.0.0 -address=/qmkdy.com/0.0.0.0 -address=/qmname.com/0.0.0.0 -address=/qnvih8.cn/0.0.0.0 -address=/qo26.com/0.0.0.0 -address=/qoiusky.com/0.0.0.0 -address=/qqm98.com/0.0.0.0 -address=/qqtx.me/0.0.0.0 -address=/qs01.cn/0.0.0.0 -address=/qsart.cn/0.0.0.0 -address=/qsbz2011.com/0.0.0.0 -address=/qshxc.com/0.0.0.0 -address=/qsj65.com/0.0.0.0 -address=/qsmdeyz.cn/0.0.0.0 -address=/qtch888.com/0.0.0.0 -address=/qtmojo.cn/0.0.0.0 -address=/quadasdata.cn/0.0.0.0 -address=/quandangdang.net/0.0.0.0 -address=/quansj.cn/0.0.0.0 -address=/qucaigg.com/0.0.0.0 -address=/queene.cn/0.0.0.0 -address=/quw18.com/0.0.0.0 -address=/qwedcfv.com/0.0.0.0 -address=/qxfly.com/0.0.0.0 -address=/qxjdlf.com/0.0.0.0 -address=/qxxys.com/0.0.0.0 -address=/qycjrkfzx.com/0.0.0.0 -address=/qyctj.com/0.0.0.0 -address=/qytyf.com/0.0.0.0 -address=/qzdfc.com/0.0.0.0 -address=/qzkxt.com/0.0.0.0 -address=/qzmhnk.com/0.0.0.0 -address=/qzzljx.com/0.0.0.0 -address=/rainfinemalawi.com/0.0.0.0 -address=/rangeblessedness.men/0.0.0.0 -address=/rcaiv.com/0.0.0.0 -address=/rdiqt.cn/0.0.0.0 -address=/re.taotaosou.com/0.0.0.0 -address=/reliancevalve.com/0.0.0.0 -address=/remotedu.cn/0.0.0.0 -address=/rencai56.com/0.0.0.0 -address=/renminben.com/0.0.0.0 -address=/resetgey.com/0.0.0.0 -address=/rgdhct.cn/0.0.0.0 -address=/rhgyg.com/0.0.0.0 -address=/rickysblast.cn/0.0.0.0 -address=/rideraid.net/0.0.0.0 -address=/riqu2015.com/0.0.0.0 -address=/rjk1.com/0.0.0.0 -address=/rmetop.com/0.0.0.0 -address=/roay.cn/0.0.0.0 -address=/rongchengxxw.com/0.0.0.0 -address=/rongdingwl.cn/0.0.0.0 -address=/rpaulfrank.com/0.0.0.0 -address=/rqgsf.com/0.0.0.0 -address=/rrsubway.com/0.0.0.0 -address=/rscxwmj.cn/0.0.0.0 -address=/ruangkayu.cn/0.0.0.0 -address=/runiman.com/0.0.0.0 -address=/ruxianke.com/0.0.0.0 -address=/rwjfs.com/0.0.0.0 -address=/rx616.cn/0.0.0.0 -address=/s400cc.com/0.0.0.0 -address=/s9w.cc/0.0.0.0 -address=/sadobo.com/0.0.0.0 -address=/saf588.com/0.0.0.0 -address=/safe524.xyz/0.0.0.0 -address=/saferwet.com/0.0.0.0 -address=/sangxi.top/0.0.0.0 -address=/sanjinma.com/0.0.0.0 -address=/sboite.cn/0.0.0.0 -address=/sbrqp.com/0.0.0.0 -address=/scenepass.com/0.0.0.0 -address=/scfatao.com/0.0.0.0 -address=/scfrwo.cn/0.0.0.0 -address=/sciencelolb.com/0.0.0.0 -address=/sclizhong.com/0.0.0.0 -address=/scriptcc.cc/0.0.0.0 -address=/scw0.com/0.0.0.0 -address=/sdagxz.xyz/0.0.0.0 -address=/sdaixz.xyz/0.0.0.0 -address=/sdhzstone.net/0.0.0.0 -address=/sdjjr.com/0.0.0.0 -address=/sdqoi2d.com/0.0.0.0 -address=/sdtbhbyb.com/0.0.0.0 -address=/sdxkdj.cn/0.0.0.0 -address=/sdycd.com/0.0.0.0 -address=/sfloushi.com/0.0.0.0 -address=/sfxl.com.cn/0.0.0.0 -address=/sfz023.com/0.0.0.0 -address=/sgbfjs.info/0.0.0.0 -address=/shama5.com/0.0.0.0 -address=/shandongkuntuo.com/0.0.0.0 -address=/shanglinli.com/0.0.0.0 -address=/sharedaddomain.com/0.0.0.0 -address=/sharrysweb.com/0.0.0.0 -address=/shbywsd.cn/0.0.0.0 -address=/shengdianwang.cc/0.0.0.0 -address=/shenglonghg.net/0.0.0.0 -address=/shentupk85.com/0.0.0.0 -address=/shenyian.net/0.0.0.0 -address=/shiftrro.com/0.0.0.0 -address=/shkywh.com/0.0.0.0 -address=/shouwangba.cn/0.0.0.0 -address=/shouyouyou.com/0.0.0.0 -address=/show.kc.taotaosou.com/0.0.0.0 -address=/shucaihangjia.com/0.0.0.0 -address=/shushijiameng123.com/0.0.0.0 -address=/shuwuzhan.com/0.0.0.0 -address=/shxinjie.cn/0.0.0.0 -address=/shypqc.com/0.0.0.0 -address=/si9377.com/0.0.0.0 -address=/sicentlife.com/0.0.0.0 -address=/sigbusa.com/0.0.0.0 -address=/sigo99.com/0.0.0.0 -address=/sina-img.club/0.0.0.0 -address=/sinaalicdn.com/0.0.0.0 -address=/sinaaliyun.cn/0.0.0.0 -address=/sinawbimg.com/0.0.0.0 -address=/sino-seve.com/0.0.0.0 -address=/sitemobia.com/0.0.0.0 -address=/sjgnskf.com/0.0.0.0 -address=/sjmwkj.cn/0.0.0.0 -address=/sjy-stone.com.cn/0.0.0.0 -address=/skatehot.net/0.0.0.0 -address=/sm077.com/0.0.0.0 -address=/smallmovieapp.com/0.0.0.0 -address=/smf82.cn/0.0.0.0 -address=/smitionsory.co/0.0.0.0 -address=/smucdn.com/0.0.0.0 -address=/smxsg.com/0.0.0.0 -address=/snnnyy.com/0.0.0.0 -address=/so9l.com/0.0.0.0 -address=/socdm.com/0.0.0.0 -address=/sos0easy.com/0.0.0.0 -address=/sp96878.com/0.0.0.0 -address=/spcode.baidu.com/0.0.0.0 -address=/spectram.pro/0.0.0.0 -address=/spxnet.com/0.0.0.0 -address=/sqext.com/0.0.0.0 -address=/sscefsol.com/0.0.0.0 -address=/ssdaili.com/0.0.0.0 -address=/ssjy168.com/0.0.0.0 -address=/ssmuse1314.cn/0.0.0.0 -address=/sstar.vip/0.0.0.0 -address=/sstc360.com/0.0.0.0 -address=/st123.info/0.0.0.0 -address=/staqnet.com/0.0.0.0 -address=/static-cn.plista.com/0.0.0.0 -address=/staticjs.cn/0.0.0.0 -address=/steadfastsystem.com/0.0.0.0 -address=/stn88.com/0.0.0.0 -address=/stocksbsc.com/0.0.0.0 -address=/stsywl.com/0.0.0.0 -address=/sucodb.com/0.0.0.0 -address=/sufficient.cn/0.0.0.0 -address=/superli666.top/0.0.0.0 -address=/suukcn.com/0.0.0.0 -address=/svsatrerbxh.com/0.0.0.0 -address=/swtkc.cn/0.0.0.0 -address=/swzhaohuo.com.cn/0.0.0.0 -address=/sxbhzs.net/0.0.0.0 -address=/sxcol.cn/0.0.0.0 -address=/sxdyrq.com/0.0.0.0 -address=/sxybjjz.cn/0.0.0.0 -address=/sxympy.com/0.0.0.0 -address=/sxz67.com/0.0.0.0 -address=/sxzmj.cn/0.0.0.0 -address=/sykty.com/0.0.0.0 -address=/syofew6o.net/0.0.0.0 -address=/sytcyf.com/0.0.0.0 -address=/sytz1288.com/0.0.0.0 -address=/szapp22.cc/0.0.0.0 -address=/szdzbx.com/0.0.0.0 -address=/szfaq.com/0.0.0.0 -address=/szggdw.com/0.0.0.0 -address=/szjianxin.net/0.0.0.0 -address=/szrk3.com/0.0.0.0 -address=/sztbjs.com/0.0.0.0 -address=/szxiuchang.com/0.0.0.0 -address=/szxpsg.com/0.0.0.0 -address=/szxzytech.com/0.0.0.0 -address=/t415n.cn/0.0.0.0 -address=/t58b.com/0.0.0.0 -address=/t70123.com/0.0.0.0 -address=/taat00889.com/0.0.0.0 -address=/tad.suning.com/0.0.0.0 -address=/tangoutianxia.com/0.0.0.0 -address=/taobaly.cn/0.0.0.0 -address=/taobaoaliyun.cn/0.0.0.0 -address=/taobaojx.com/0.0.0.0 -address=/taobayun.cn/0.0.0.0 -address=/taoguanda.com/0.0.0.0 -address=/taohanpai.com/0.0.0.0 -address=/taoyuay.top/0.0.0.0 -address=/tbaocdn.com/0.0.0.0 -address=/tc600.com/0.0.0.0 -address=/tdayi.com/0.0.0.0 -address=/techantuijian.com/0.0.0.0 -address=/tequanma.com/0.0.0.0 -address=/tg.1155t.cn/0.0.0.0 -address=/th21333.com/0.0.0.0 -address=/thescenseproject.com/0.0.0.0 -address=/thishare.com/0.0.0.0 -address=/thli43.cn/0.0.0.0 -address=/thxnr.com/0.0.0.0 -address=/thyvjboy.com/0.0.0.0 -address=/tiangu99.com/0.0.0.0 -address=/tianjieleather.com/0.0.0.0 -address=/tianjiunion.cn/0.0.0.0 -address=/tianqi777.com/0.0.0.0 -address=/tianyanzs.com/0.0.0.0 -address=/tinglian.com/0.0.0.0 -address=/tj-cmys.com/0.0.0.0 -address=/tjgxzs.com/0.0.0.0 -address=/tjhhr.com/0.0.0.0 -address=/tjqonline.cn/0.0.0.0 -address=/tjys88.com/0.0.0.0 -address=/tkd777.cn/0.0.0.0 -address=/tngmn.com/0.0.0.0 -address=/togo666.com/0.0.0.0 -address=/tongdejiayuan.com/0.0.0.0 -address=/tongqing2015.com/0.0.0.0 -address=/toourbb.com/0.0.0.0 -address=/top267.com/0.0.0.0 -address=/tpe163.com/0.0.0.0 -address=/trackingpro.pro/0.0.0.0 -address=/tradeccl.com/0.0.0.0 -address=/trourted.pro/0.0.0.0 -address=/trzina.com/0.0.0.0 -address=/tsdlp.com/0.0.0.0 -address=/tsyndolls.com/0.0.0.0 -address=/ttbaods.com/0.0.0.0 -address=/ttfgames.cn/0.0.0.0 -address=/ttlowe.com/0.0.0.0 -address=/tukeai.com/0.0.0.0 -address=/tvbyb04.com/0.0.0.0 -address=/twitterzs.com/0.0.0.0 -address=/twldmx.com/0.0.0.0 -address=/twzui6.com/0.0.0.0 -address=/txdwc.cn/0.0.0.0 -address=/txt2017.com/0.0.0.0 -address=/txt2019.cc/0.0.0.0 -address=/ty229.com/0.0.0.0 -address=/tylll.com/0.0.0.0 -address=/u.huoying666.com/0.0.0.0 -address=/uadsaa.com/0.0.0.0 -address=/ubalh.com/0.0.0.0 -address=/ubmcvideo.baidustatic.com/0.0.0.0 -address=/uc610.com/0.0.0.0 -address=/ucaliyun.cn/0.0.0.0 -address=/ucbaba.top/0.0.0.0 -address=/uchaoqiang.top/0.0.0.0 -address=/ucrzgcs.cn/0.0.0.0 -address=/ucstatic.cn/0.0.0.0 -address=/ucxgg.com/0.0.0.0 -address=/ucxxii.com/0.0.0.0 -address=/ugg66.com/0.0.0.0 -address=/uhijmv.cn/0.0.0.0 -address=/ujikdd041o.cn/0.0.0.0 -address=/ukeiae.com/0.0.0.0 -address=/uklyv.cn/0.0.0.0 -address=/umjsik.com/0.0.0.0 -address=/uneede.com/0.0.0.0 -address=/uoyrsd.com/0.0.0.0 -address=/urhu.cn/0.0.0.0 -address=/urlat.cn/0.0.0.0 -address=/uvclick.com/0.0.0.0 -address=/uvsea.cn/0.0.0.0 -address=/uw9377.com/0.0.0.0 -address=/uzpmrbek.com/0.0.0.0 -address=/v707070.com/0.0.0.0 -address=/va88p.cn/0.0.0.0 -address=/vaedan.top/0.0.0.0 -address=/vboo349.com/0.0.0.0 -address=/vdazz.net/0.0.0.0 -address=/ve001nz.com/0.0.0.0 -address=/vedeh.com/0.0.0.0 -address=/vegent.cn/0.0.0.0 -address=/vertivchina.cn/0.0.0.0 -address=/vfdxlt.cn/0.0.0.0 -address=/vhpxa.top/0.0.0.0 -address=/victorjx.com/0.0.0.0 -address=/video231.oss-cn-beijing.aliyuncs.com/0.0.0.0 -address=/videondun.com/0.0.0.0 -address=/vmjjzk.cn/0.0.0.0 -address=/vnnv777.cn/0.0.0.0 -address=/vns3359.com/0.0.0.0 -address=/vs944.cn/0.0.0.0 -address=/vt863.cn/0.0.0.0 -address=/vtale.org/0.0.0.0 -address=/vvvulqn7.com/0.0.0.0 -address=/vwws6.net/0.0.0.0 -address=/vxsnk.com/0.0.0.0 -address=/w3989.com/0.0.0.0 -address=/w4pma.cn/0.0.0.0 -address=/w65p.com/0.0.0.0 -address=/wacc888.com/0.0.0.0 -address=/waihui518.com/0.0.0.0 -address=/wanfukang.cc/0.0.0.0 -address=/wangdaizao.com/0.0.0.0 -address=/wangdddy.com/0.0.0.0 -address=/wangdq.com/0.0.0.0 -address=/wangqipu.com/0.0.0.0 -address=/wangsufast.com/0.0.0.0 -address=/wantaico.com/0.0.0.0 -address=/wantfour.com/0.0.0.0 -address=/wapadv.com/0.0.0.0 -address=/waptime.net/0.0.0.0 -address=/watchsk.com/0.0.0.0 -address=/wazero.online/0.0.0.0 -address=/wcnmd.top/0.0.0.0 -address=/wdymwzz.com/0.0.0.0 -address=/wdzsb.com.cn/0.0.0.0 -address=/webabcd.com/0.0.0.0 -address=/webofxm.cn/0.0.0.0 -address=/weihuiyungou.com/0.0.0.0 -address=/weiqiqu.cn/0.0.0.0 -address=/weixiangzu.cn/0.0.0.0 -address=/wemdsm.com/0.0.0.0 -address=/werpig.com/0.0.0.0 -address=/wf321.com/0.0.0.0 -address=/wffengtai.com.cn/0.0.0.0 -address=/wgnlz.com/0.0.0.0 -address=/wgnmp.com/0.0.0.0 -address=/whafwl.com/0.0.0.0 -address=/whhxnz.com/0.0.0.0 -address=/whpxy.com/0.0.0.0 -address=/whshangsha.com/0.0.0.0 -address=/whytoss.com/0.0.0.0 -address=/wikigifth.com/0.0.0.0 -address=/winvestern.com.cn/0.0.0.0 -address=/wjguc.com/0.0.0.0 -address=/wka8.com/0.0.0.0 -address=/wlkpa.cn/0.0.0.0 -address=/wndlkj.com/0.0.0.0 -address=/wodhid.com/0.0.0.0 -address=/wojiabaoye.com/0.0.0.0 -address=/wole.us/0.0.0.0 -address=/wowips.com/0.0.0.0 -address=/wowoyy.cc/0.0.0.0 -address=/wq42219.com/0.0.0.0 -address=/wqsph.net/0.0.0.0 -address=/wrvdmh.cn/0.0.0.0 -address=/ws341.com/0.0.0.0 -address=/ws7j.com/0.0.0.0 -address=/wsgblw.com/0.0.0.0 -address=/wstztt.com/0.0.0.0 -address=/wu36n.cn/0.0.0.0 -address=/wu65.com/0.0.0.0 -address=/wuhufengze.com.cn/0.0.0.0 -address=/wushuangjiexi.top/0.0.0.0 -address=/wuwaii.com/0.0.0.0 -address=/wuweiqx.com/0.0.0.0 -address=/wuwho.cn/0.0.0.0 -address=/wuyekanba.com/0.0.0.0 -address=/wvstatic.cn/0.0.0.0 -address=/wwlolbs.com/0.0.0.0 -address=/wxbdfm.com/0.0.0.0 -address=/wxs666.cn/0.0.0.0 -address=/wxstatic.cn/0.0.0.0 -address=/wxxfqc.com/0.0.0.0 -address=/wyhzzy.com/0.0.0.0 -address=/wyttech.cn/0.0.0.0 -address=/wywsdx.com/0.0.0.0 -address=/wzaigo.com/0.0.0.0 -address=/wzjijia.com/0.0.0.0 -address=/wzsygdl.com/0.0.0.0 -address=/x6z6.com/0.0.0.0 -address=/x9377a.com/0.0.0.0 -address=/xa9t.com/0.0.0.0 -address=/xabaitai.com/0.0.0.0 -address=/xabmjr.com/0.0.0.0 -address=/xcads.cn/0.0.0.0 -address=/xcclzs.com/0.0.0.0 -address=/xchgx.com/0.0.0.0 -address=/xcjy876.com/0.0.0.0 -address=/xcsaz.com/0.0.0.0 -address=/xcxzxc.cn/0.0.0.0 -address=/xcy8.com/0.0.0.0 -address=/xcyjzs.net/0.0.0.0 -address=/xcyrc.com/0.0.0.0 -address=/xdbwc.com/0.0.0.0 -address=/xdcqcyp.com/0.0.0.0 -address=/xdywlw.cn/0.0.0.0 -address=/xhbqczl.com/0.0.0.0 -address=/xhmrv.com/0.0.0.0 -address=/xhrxb.com/0.0.0.0 -address=/xhsxgmt.cn/0.0.0.0 -address=/xhxnkyy.com/0.0.0.0 -address=/xhydrs.cn/0.0.0.0 -address=/xi0021.com/0.0.0.0 -address=/xiadaxiong.com/0.0.0.0 -address=/xiald.com/0.0.0.0 -address=/xiang7.vip/0.0.0.0 -address=/xiaobiaoucai.cn/0.0.0.0 -address=/xiaoyang.mobi/0.0.0.0 -address=/xiaozhishi852.com/0.0.0.0 -address=/xiaxuanfu.com/0.0.0.0 -address=/xibei70.com/0.0.0.0 -address=/xidexableact.cn/0.0.0.0 -address=/xihashuale.com/0.0.0.0 -address=/xilele.com/0.0.0.0 -address=/xiliweisha.cn/0.0.0.0 -address=/xinasiaj.com/0.0.0.0 -address=/xingjuhe.com/0.0.0.0 -address=/xingyao.doubiy.com/0.0.0.0 -address=/xingyaoapi.com/0.0.0.0 -address=/xinji2.com/0.0.0.0 -address=/xinlongrubber.com/0.0.0.0 -address=/xinyijiasc.cn/0.0.0.0 -address=/xiongdong.com/0.0.0.0 -address=/xiongzhangad.com/0.0.0.0 -address=/xixiashengdian.com/0.0.0.0 -address=/xjidian.com/0.0.0.0 -address=/xjzyq.com/0.0.0.0 -address=/xk2012.com/0.0.0.0 -address=/xkwfao.com/0.0.0.0 -address=/xlwnx.com/0.0.0.0 -address=/xm9178.com/0.0.0.0 -address=/xmcmn.com/0.0.0.0 -address=/xmliw.com/0.0.0.0 -address=/xmrepair.com/0.0.0.0 -address=/xmsqz.com/0.0.0.0 -address=/xmtsyg.com/0.0.0.0 -address=/xmxxwl.com/0.0.0.0 -address=/xn--fjqz50cv5q3so.ltd/0.0.0.0 -address=/xn--fjqz50cv5q3so.online/0.0.0.0 -address=/xn--mtso8sj6menhyil.online/0.0.0.0 -address=/xn--tst552fo5s.xyz/0.0.0.0 -address=/xn--wxt79hbyb675a.online/0.0.0.0 -address=/xn--wxtr9fwyxk9c.site/0.0.0.0 -address=/xn--wxtr9fwyxk9c.top/0.0.0.0 -address=/xn--wxtr9fwyxk9c.xn--io0a7i/0.0.0.0 -address=/xn--xhq9mt12cf5v.ink/0.0.0.0 -address=/xn--xhq9mt12cf5v.ren/0.0.0.0 -address=/xn--xhq9mt12cf5v.shop/0.0.0.0 -address=/xn--xhq9mt12cf5v.site/0.0.0.0 -address=/xn--xhq9mt12cf5v.top/0.0.0.0 -address=/xn--xhq9mt12cf5v.website/0.0.0.0 -address=/xn6ffc.com/0.0.0.0 -address=/xnjpg.com/0.0.0.0 -address=/xpjis.com/0.0.0.0 -address=/xpqfc.com/0.0.0.0 -address=/xq199.com/0.0.0.0 -address=/xt2d.cn/0.0.0.0 -address=/xtianqi.com.cn/0.0.0.0 -address=/xtxa.net/0.0.0.0 -address=/xtyizilaijx.cn/0.0.0.0 -address=/xu7b.com/0.0.0.0 -address=/xuanmeiguoji.com/0.0.0.0 -address=/xuehelei.com/0.0.0.0 -address=/xueyongbao.com/0.0.0.0 -address=/xugsh.cn/0.0.0.0 -address=/xul478.com/0.0.0.0 -address=/xulizui6.com/0.0.0.0 -address=/xunlaile.com/0.0.0.0 -address=/xuqinqi.cn/0.0.0.0 -address=/xvnfyutv.com/0.0.0.0 -address=/xvtpvc.cn/0.0.0.0 -address=/xxad.cc/0.0.0.0 -address=/xxhrd.com/0.0.0.0 -address=/xxlmxsh.com/0.0.0.0 -address=/xxwkjl.com/0.0.0.0 -address=/xxyzwtsylw.com/0.0.0.0 -address=/xycnz.com/0.0.0.0 -address=/xycnzz.com/0.0.0.0 -address=/xyqptm.com/0.0.0.0 -address=/xyqxr.com/0.0.0.0 -address=/xyrhd.com/0.0.0.0 -address=/xyssp.com/0.0.0.0 -address=/xytom.com/0.0.0.0 -address=/xz6d.com/0.0.0.0 -address=/xzyituo.com/0.0.0.0 -address=/xzzyi.com/0.0.0.0 -address=/y0o1g.cn/0.0.0.0 -address=/yageben.com/0.0.0.0 -address=/yalongrope.cn/0.0.0.0 -address=/yamaidei.cn/0.0.0.0 -address=/yangdasen.cn/0.0.0.0 -address=/yanglaopt.net/0.0.0.0 -address=/yaohq.com/0.0.0.0 -address=/yaoxiaoli.com/0.0.0.0 -address=/yaoyl.com/0.0.0.0 -address=/yatemy.cn/0.0.0.0 -address=/ychml.com/0.0.0.0 -address=/ychun03.com/0.0.0.0 -address=/ydlnt.com/0.0.0.0 -address=/ydqzkj.com/0.0.0.0 -address=/yenlm.com/0.0.0.0 -address=/yeyajipp.com/0.0.0.0 -address=/yezijizhang.com/0.0.0.0 -address=/yf898.com/0.0.0.0 -address=/yfycy.com/0.0.0.0 -address=/yhsmk.com/0.0.0.0 -address=/yhtcd.com/0.0.0.0 -address=/yidulive.net/0.0.0.0 -address=/yigyx.com/0.0.0.0 -address=/yijia2009.com/0.0.0.0 -address=/yijikm.com/0.0.0.0 -address=/yingdatuofu.com/0.0.0.0 -address=/yinhaijuan.com/0.0.0.0 -address=/yinyuehu.cn/0.0.0.0 -address=/yinyuncp.com/0.0.0.0 -address=/yiran686.cn/0.0.0.0 -address=/yiranxian.cn/0.0.0.0 -address=/yishuifa.org/0.0.0.0 -address=/yitai001.com/0.0.0.0 -address=/yiwuds.com/0.0.0.0 -address=/yixui.com/0.0.0.0 -address=/yjoiunf.com/0.0.0.0 -address=/yk0712.com/0.0.0.0 -address=/ykjmy.com/0.0.0.0 -address=/ymcqb.com/0.0.0.0 -address=/ynbojie.com/0.0.0.0 -address=/yndianju.com/0.0.0.0 -address=/ynmbz.com/0.0.0.0 -address=/ynwqls.com/0.0.0.0 -address=/yofoto.ltd/0.0.0.0 -address=/yongkang6.com/0.0.0.0 -address=/youfumei.com/0.0.0.0 -address=/yousee.com/0.0.0.0 -address=/youyoumw.com/0.0.0.0 -address=/ypa.focusoftime.com/0.0.0.0 -address=/ypmob.com/0.0.0.0 -address=/yqcy988.com/0.0.0.0 -address=/yqw88.com/0.0.0.0 -address=/yrzyks.cn/0.0.0.0 -address=/ysdhe.com/0.0.0.0 -address=/ysgsq.cn/0.0.0.0 -address=/ysjwj.com/0.0.0.0 -address=/ysnj74ed.com/0.0.0.0 -address=/yuanmengbi.com/0.0.0.0 -address=/yuanyanglw.com/0.0.0.0 -address=/yueyetiyu.com/0.0.0.0 -address=/yuggcd.com/0.0.0.0 -address=/yujiangchu.com/0.0.0.0 -address=/yujyjms.cn/0.0.0.0 -address=/yule8.net/0.0.0.0 -address=/yunmowu.com/0.0.0.0 -address=/yunsoka.com/0.0.0.0 -address=/yuyanbaojie.cn/0.0.0.0 -address=/yuyue008.cn/0.0.0.0 -address=/ywadf.cn/0.0.0.0 -address=/ywjsgc.com/0.0.0.0 -address=/ywjxsp168.cn/0.0.0.0 -address=/ywxi.net/0.0.0.0 -address=/yxgfcj.com/0.0.0.0 -address=/yxjad.com/0.0.0.0 -address=/yxmspx.com/0.0.0.0 -address=/yxszy.com/0.0.0.0 -address=/yxxwyz.com/0.0.0.0 -address=/yy58ju.com/0.0.0.0 -address=/yyp17.com/0.0.0.0 -address=/yyylg.cn/0.0.0.0 -address=/yzaosite.com/0.0.0.0 -address=/yzh360.com/0.0.0.0 -address=/yzwr588.com/0.0.0.0 -address=/yzygo.com/0.0.0.0 -address=/yzytb.com/0.0.0.0 -address=/zantainet.com/0.0.0.0 -address=/zbetter.org/0.0.0.0 -address=/zcrtd.com/0.0.0.0 -address=/zdjby.cn/0.0.0.0 -address=/zencu.com.cn/0.0.0.0 -address=/zfkmw.com/0.0.0.0 -address=/zgc66.com/0.0.0.0 -address=/zgksb.com/0.0.0.0 -address=/zgktxx.com/0.0.0.0 -address=/zgrsq.cn/0.0.0.0 -address=/zgtcar.com/0.0.0.0 -address=/zgunion.cn/0.0.0.0 -address=/zgyemy.com/0.0.0.0 -address=/zgyryt.com/0.0.0.0 -address=/zh1144.com/0.0.0.0 -address=/zhaibei112.top/0.0.0.0 -address=/zhangkc.com/0.0.0.0 -address=/zhao258.com/0.0.0.0 -address=/zhengyejixie.com/0.0.0.0 -address=/zhfosenghtr.com/0.0.0.0 -address=/zhichi08.com/0.0.0.0 -address=/zhihei.com/0.0.0.0 -address=/zhinengap.com/0.0.0.0 -address=/zhiong.net/0.0.0.0 -address=/zhixiuchang.com/0.0.0.0 -address=/zhjfad.com/0.0.0.0 -address=/zhongjiangguoji.org/0.0.0.0 -address=/zhongzk.com/0.0.0.0 -address=/zhuangzhaibancai.cn/0.0.0.0 -address=/zhuba8.com/0.0.0.0 -address=/zhudiaosz.com/0.0.0.0 -address=/zhufushuo.com/0.0.0.0 -address=/zhunishunli.com/0.0.0.0 -address=/zhy333.com/0.0.0.0 -address=/zhybzp.cn/0.0.0.0 -address=/zi63m.cn/0.0.0.0 -address=/ziig.com.cn/0.0.0.0 -address=/zisu.cn.com/0.0.0.0 -address=/zitanmushu.com/0.0.0.0 -address=/ziyuantx.com/0.0.0.0 -address=/zjhim.com/0.0.0.0 -address=/zjhoudao.com/0.0.0.0 -address=/zl588.com/0.0.0.0 -address=/zmgod.com/0.0.0.0 -address=/zmlled.cn/0.0.0.0 -address=/zp22938576.com/0.0.0.0 -address=/zqworks.com/0.0.0.0 -address=/zrpfk.com/0.0.0.0 -address=/zry8181.com/0.0.0.0 -address=/zsdexun.com.cn/0.0.0.0 -address=/zsedu99.cn/0.0.0.0 -address=/zsjyc.top/0.0.0.0 -address=/ztidu.com/0.0.0.0 -address=/ztvx8.com/0.0.0.0 -address=/zx573.cn/0.0.0.0 -address=/zxb918.com/0.0.0.0 -address=/zxhrq.cn/0.0.0.0 -address=/zxwdw.com/0.0.0.0 -address=/zybpj.com/0.0.0.0 -address=/zydyjzw.cn/0.0.0.0 -address=/zymro.com/0.0.0.0 -address=/zyqp9.com/0.0.0.0 -address=/zyrfanli.com/0.0.0.0 -address=/zyzjpx.cn/0.0.0.0 -address=/zzbaowen.com/0.0.0.0 -address=/zzkoubei.com/0.0.0.0 -address=/zzrcz.com/0.0.0.0 -address=/zzsssy.com/0.0.0.0 -address=/zzwflxs.com/0.0.0.0 -address=/zzyonghao.com/0.0.0.0 -address=/0x013d.website/0.0.0.0 -address=/0x01e7.website/0.0.0.0 -address=/1.hao123.com/0.0.0.0 -address=/100.admin5.com/0.0.0.0 -address=/100.pncdn.cn/0.0.0.0 -address=/107.172.176.197/0.0.0.0 -address=/108.171.248.234/0.0.0.0 -address=/115.29.141.121/0.0.0.0 -address=/119.29.80.185/0.0.0.0 -address=/120.27.34.156/0.0.0.0 -address=/122.228.236.165/0.0.0.0 -address=/20150930.cf/0.0.0.0 -address=/2016.bkill.net/0.0.0.0 -address=/205.209.138.102/0.0.0.0 -address=/23.91.3.114/0.0.0.0 -address=/360safego.com/0.0.0.0 -address=/5y9nfpes.52pk.com/0.0.0.0 -address=/614514.com/0.0.0.0 -address=/69.28.57.245/0.0.0.0 -address=/7mad.7m.cn/0.0.0.0 -address=/7xsf3h.com1.z0.glb.clouddn.com/0.0.0.0 -address=/801.tianyaui.com/0.0.0.0 -address=/8jkx.com/0.0.0.0 -address=/a.baomihua.com/0.0.0.0 -address=/a.nowscore.com/0.0.0.0 -address=/a.xywy.com/0.0.0.0 -address=/a2.b310.com/0.0.0.0 -address=/a2.xinhuanet.com/0.0.0.0 -address=/abc.hkepc.com/0.0.0.0 -address=/abc.hkepc.net/0.0.0.0 -address=/acodes.b2b.cn/0.0.0.0 -address=/acv5e.cn/0.0.0.0 -address=/ad-api.cnblogs.com/0.0.0.0 -address=/ad-img.diyidan.net/0.0.0.0 -address=/ad.52av.one/0.0.0.0 -address=/ad.bobi.tw/0.0.0.0 -address=/ad.cdnjm.cn/0.0.0.0 -address=/ad.walkgame.com/0.0.0.0 -address=/ad.wurangxian.top/0.0.0.0 -address=/adadmin.house365.com/0.0.0.0 -address=/add.freeimg8.com/0.0.0.0 -address=/adf.dahe.cn/0.0.0.0 -address=/adhome.1fangchan.com/0.0.0.0 -address=/adm.265g.com/0.0.0.0 -address=/adm.52swine.com/0.0.0.0 -address=/adm.6park.com/0.0.0.0 -address=/adm.beimg.com/0.0.0.0 -address=/adm.cloud.cnfol.com/0.0.0.0 -address=/adm.xmfish.com/0.0.0.0 -address=/admd.housefun.com.tw/0.0.0.0 -address=/admd.yam.com/0.0.0.0 -address=/admsapi.businessweekly.com.tw/0.0.0.0 -address=/adnetpub.yaolan.com/0.0.0.0 -address=/adp.cnki.net/0.0.0.0 -address=/adp.cnool.net/0.0.0.0 -address=/adpai.thepaper.cn/0.0.0.0 -address=/adpub.yaolan.com/0.0.0.0 -address=/adpubs.yaolan.com/0.0.0.0 -address=/ads-union.jd.com/0.0.0.0 -address=/ads.sohu.com/0.0.0.0 -address=/adsc.wasu.tv/0.0.0.0 -address=/adsclick.yx.js.cn/0.0.0.0 -address=/adshows.21cn.com/0.0.0.0 -address=/adt.xdrig.com/0.0.0.0 -address=/adv-sv-show.focus.cn/0.0.0.0 -address=/afp.chinanews.com/0.0.0.0 -address=/afp.wasu.cn/0.0.0.0 -address=/afpcreative.wasu.cn/0.0.0.0 -address=/ahd.ruten.com.tw/0.0.0.0 -address=/ai.bioon.com/0.0.0.0 -address=/alitui.weibo.com/0.0.0.0 -address=/am.szhome.com/0.0.0.0 -address=/amradmin.5173.com/0.0.0.0 -address=/ams.fx678.com/0.0.0.0 -address=/ann5.net/0.0.0.0 -address=/appimg.0575bbs.com/0.0.0.0 -address=/apple.www.letv.com/0.0.0.0 -address=/ashow.pcpop.com/0.0.0.0 -address=/assp.sohu.com/0.0.0.0 -address=/atiws.aipai.com/0.0.0.0 -address=/atm.youku.com/0.0.0.0 -address=/ax.ifeng.com/0.0.0.0 -address=/b.tukucc.com/0.0.0.0 -address=/badding.oss-ap-southeast-1.aliyuncs.com/0.0.0.0 -address=/baifen.music.baidu.com/0.0.0.0 -address=/besc.baidustatic.com/0.0.0.0 -address=/biz.gexing.com/0.0.0.0 -address=/biz.weibo.com/0.0.0.0 -address=/bk9gun.vpser.net/0.0.0.0 -address=/boardx.huanqiu.com/0.0.0.0 -address=/btn.onlylady.com/0.0.0.0 -address=/btn.pchome.net/0.0.0.0 -address=/business.92wy.com/0.0.0.0 -address=/by8974.com/0.0.0.0 -address=/c-5uwzmx78pmca09x24aiux2euavx2ekwu.g00.msn.com/0.0.0.0 -address=/cacafly.net/0.0.0.0 -address=/cdgfa.ifeng.com/0.0.0.0 -address=/cdn.wuyou.ca/0.0.0.0 -address=/chidir.com/0.0.0.0 -address=/client.88tours.com/0.0.0.0 -address=/cmm.xmfish.com/0.0.0.0 -address=/cms.fx678.com/0.0.0.0 -address=/cms.fx678img.com/0.0.0.0 -address=/cocoawu.b0.upaiyun.com/0.0.0.0 -address=/count.ddooo.com/0.0.0.0 -address=/cp2.eastmoney.com/0.0.0.0 -address=/cpm.cm.kankan.com/0.0.0.0 -address=/d-test.39.net/0.0.0.0 -address=/d0.xcar.com.cn/0.0.0.0 -address=/d1.3158.cn/0.0.0.0 -address=/d13jhr4vol1304.cloudfront.net/0.0.0.0 -address=/da.mgtv.com/0.0.0.0 -address=/de.as.pptv.com/0.0.0.0 -address=/dehua.ixinfan.com/0.0.0.0 -address=/deliver.ifeng.com/0.0.0.0 -address=/delivery.playallvideos.com/0.0.0.0 -address=/delivery.wasu.cn/0.0.0.0 -address=/djs.baomihua.com/0.0.0.0 -address=/doubleclick.ctfile.com/0.0.0.0 -address=/dsp.ali213.net/0.0.0.0 -address=/dup.baidustatic.com/0.0.0.0 -address=/dvs.china.com/0.0.0.0 -address=/dvser.china.com/0.0.0.0 -address=/dydab.com/0.0.0.0 -address=/e.yycqc.com/0.0.0.0 -address=/eap.big5.enorth.com.cn/0.0.0.0 -address=/eap.enorth.com.cn/0.0.0.0 -address=/ebp.renren.com/0.0.0.0 -address=/ecma.bdimg.com/0.0.0.0 -address=/ecmb.bdimg.com/0.0.0.0 -address=/emdcadvertise.eastmoney.com/0.0.0.0 -address=/erebor.douban.com/0.0.0.0 -address=/ermao.sikabeila.com/0.0.0.0 -address=/ff.meikanguo.com/0.0.0.0 -address=/fun.ynet.com/0.0.0.0 -address=/g.hsw.cn/0.0.0.0 -address=/g.lznews.cn/0.0.0.0 -address=/g.mnw.cn/0.0.0.0 -address=/g.ousns.net/0.0.0.0 -address=/g2.ousns.net/0.0.0.0 -address=/ganjituiguang.ganji.com/0.0.0.0 -address=/gdt.qq.com/0.0.0.0 -address=/gg.0598yu.com/0.0.0.0 -address=/gg.4kdy.net/0.0.0.0 -address=/gg.blueidea.com/0.0.0.0 -address=/gg.cs090.com/0.0.0.0 -address=/gg.g9mi6.com/0.0.0.0 -address=/gg.getbs.com/0.0.0.0 -address=/gg.gsdlcn.com/0.0.0.0 -address=/gg.gw032.com/0.0.0.0 -address=/gg.kugou.com/0.0.0.0 -address=/gg.sonhoo.com/0.0.0.0 -address=/gg.uuu9.com/0.0.0.0 -address=/gg.yxdown.com/0.0.0.0 -address=/gg86.pinggu.org/0.0.0.0 -address=/ggcode.2345.com/0.0.0.0 -address=/ggg.zj.com/0.0.0.0 -address=/ggs.myzaker.com/0.0.0.0 -address=/ggtp-1255424916.cos.ap-chengdu.myqcloud.com/0.0.0.0 -address=/ggw.gusuwang.com/0.0.0.0 -address=/ggw.watertu.com/0.0.0.0 -address=/go.hangzhou.com.cn/0.0.0.0 -address=/goto.www.iciba.com/0.0.0.0 -address=/gotourl.xyz/0.0.0.0 -address=/gp.jstv.com/0.0.0.0 -address=/greenhouseglobal.cn/0.0.0.0 -address=/gt.duowan.com/0.0.0.0 -address=/gt.yy.com/0.0.0.0 -address=/guang.lesports.com/0.0.0.0 -address=/guess.h.qhimg.com/0.0.0.0 -address=/hades.qyer.com/0.0.0.0 -address=/hiad.vmall.com/0.0.0.0 -address=/hz.shouyoutv.com/0.0.0.0 -address=/hzhyhm.com/0.0.0.0 -address=/i.syasn.com/0.0.0.0 -address=/iads.xinmin.cn/0.0.0.0 -address=/idcot.com/0.0.0.0 -address=/img.3sjt.com/0.0.0.0 -address=/img.meipic.net/0.0.0.0 -address=/img1.126.net/0.0.0.0 -address=/img2.126.net/0.0.0.0 -address=/img2.titan007.com/0.0.0.0 -address=/img3.126.net/0.0.0.0 -address=/imgadsame.liba.com/0.0.0.0 -address=/inte.sogou.com/0.0.0.0 -address=/ivy.pconline.com.cn/0.0.0.0 -address=/iwanad.baidu.com/0.0.0.0 -address=/j.avz4.com/0.0.0.0 -address=/jmsyzj.com/0.0.0.0 -address=/js.45bubu.com/0.0.0.0 -address=/js.bju888.com/0.0.0.0 -address=/js.bxwns.com/0.0.0.0 -address=/js.duotegame.com/0.0.0.0 -address=/js.hkslg520.com/0.0.0.0 -address=/jxad.jx163.com/0.0.0.0 -address=/knnwdyou.com/0.0.0.0 -address=/libfre.obs.cn-east-3.myhuaweicloud.com/0.0.0.0 -address=/lingdian98.com/0.0.0.0 -address=/ll.gxsky.com/0.0.0.0 -address=/lxting.com/0.0.0.0 -address=/m.aty.sohu.com/0.0.0.0 -address=/m2.lelemh.com/0.0.0.0 -address=/mall0.qiyipic.com/0.0.0.0 -address=/manage.wdfans.cn/0.0.0.0 -address=/market.178.com/0.0.0.0 -address=/market.21cn.com/0.0.0.0 -address=/market.duowan.com/0.0.0.0 -address=/mini.hao123.com/0.0.0.0 -address=/miniye.xjts.cn/0.0.0.0 -address=/money.qz828.com/0.0.0.0 -address=/myad.toocle.com/0.0.0.0 -address=/nirentang.com/0.0.0.0 -address=/ok.432kkk.com/0.0.0.0 -address=/p.7060.la/0.0.0.0 -address=/p.zol-img.com.cn/0.0.0.0 -address=/p4p.sina.com.cn/0.0.0.0 -address=/p8u.hinet.net/0.0.0.0 -address=/panda.kdnet.net/0.0.0.0 -address=/partner.toutiao.com/0.0.0.0 -address=/pekingpk10.com/0.0.0.0 -address=/pg-ad-b1.nosdn.127.net/0.0.0.0 -address=/phpad.cqnews.net/0.0.0.0 -address=/pic.0597kk.com/0.0.0.0 -address=/pic.fengniao.com/0.0.0.0 -address=/pics.xgo-img.com.cn/0.0.0.0 -address=/poster.weather.com.cn/0.0.0.0 -address=/pro.iweihai.cn/0.0.0.0 -address=/pub.funshion.com/0.0.0.0 -address=/publish.ad.youth.cn/0.0.0.0 -address=/qcvf.ifeng.com/0.0.0.0 -address=/qd.wanjuanba.com/0.0.0.0 -address=/qd.x4399.com/0.0.0.0 -address=/qn.bejson.com/0.0.0.0 -address=/qt.biqugezw.com/0.0.0.0 -address=/resource.baomihua.com/0.0.0.0 -address=/rh.qq.com/0.0.0.0 -address=/sa.sina.cn/0.0.0.0 -address=/same.chinadaily.com.cn/0.0.0.0 -address=/same.eastmoney.com/0.0.0.0 -address=/script.vccoo.com/0.0.0.0 -address=/sgg.southcn.com/0.0.0.0 -address=/share.gzdsw.com/0.0.0.0 -address=/ssgg.chazidian.com/0.0.0.0 -address=/ssp.hinet.net/0.0.0.0 -address=/ssp.zf313.com/0.0.0.0 -address=/sss.sege.xxx/0.0.0.0 -address=/sssvd.china.com/0.0.0.0 -address=/static-ssp.yidianzixun.com/0.0.0.0 -address=/sub.powerapple.com/0.0.0.0 -address=/super.cat898.com/0.0.0.0 -address=/super.kdnet.net/0.0.0.0 -address=/synacast.com/0.0.0.0 -address=/tcjy66.cc/0.0.0.0 -address=/tf.360.cn/0.0.0.0 -address=/tk.504pk.com/0.0.0.0 -address=/tp.sgcn.com/0.0.0.0 -address=/tt.biquge.la/0.0.0.0 -address=/u.63kc.com/0.0.0.0 -address=/u.cnzol.com/0.0.0.0 -address=/uc.zhuici.com/0.0.0.0 -address=/union.china.com.cn/0.0.0.0 -address=/union.yihaodian.com/0.0.0.0 -address=/untitled.dwstatic.com/0.0.0.0 -address=/up.hiao.com/0.0.0.0 -address=/vupload.duowan.com/0.0.0.0 -address=/web.900.la/0.0.0.0 -address=/wew.dushiwenxue.net/0.0.0.0 -address=/wowad.wow-classic.com/0.0.0.0 -address=/wpwdf.com/0.0.0.0 -address=/wuliao.epro.sogou.com/0.0.0.0 -address=/xc.macd.cn/0.0.0.0 -address=/xc.mydrivers.com/0.0.0.0 -address=/xdyjt.com/0.0.0.0 -address=/xinzheng8.pw/0.0.0.0 -address=/xs.houyi.baofeng.net/0.0.0.0 -address=/yktj.yzz.cn/0.0.0.0 -address=/yt-adp.nosdn.127.net/0.0.0.0 -address=/yt-adp.ws.126.net/0.0.0.0 -address=/yunbofangbt.com/0.0.0.0 -address=/z.nowscore.com/0.0.0.0 -address=/zkrdy.com/0.0.0.0 -address=/zt2088.com/0.0.0.0 -address=/ztyumn.ifeng.com/0.0.0.0 -address=/immedlinkum.info/0.0.0.0 -address=/xayah.date/0.0.0.0 -address=/003store.com/0.0.0.0 -address=/06362.com/0.0.0.0 -address=/1.01fy.cn/0.0.0.0 -address=/1.1010pic.com/0.0.0.0 -address=/1.11467.com/0.0.0.0 -address=/1.15lu.com/0.0.0.0 -address=/1.201980.com/0.0.0.0 -address=/1.32xp.com/0.0.0.0 -address=/1.51sxue.cn/0.0.0.0 -address=/1.5646.cn/0.0.0.0 -address=/1.66law.cn/0.0.0.0 -address=/1.92caijing.com/0.0.0.0 -address=/1.ajiyuming.com/0.0.0.0 -address=/1.arpun.com/0.0.0.0 -address=/1.bangdan5.com/0.0.0.0 -address=/1.bh5.com.cn/0.0.0.0 -address=/1.cjcp.cn/0.0.0.0 -address=/1.cn716.com/0.0.0.0 -address=/1.codesdq.com/0.0.0.0 -address=/1.codezh.com/0.0.0.0 -address=/1.dwx365.com/0.0.0.0 -address=/1.feihua.com/0.0.0.0 -address=/1.feihua.net.cn/0.0.0.0 -address=/1.glook.cn/0.0.0.0 -address=/1.guyaheng.com/0.0.0.0 -address=/1.hnyouneng.com/0.0.0.0 -address=/1.huilv.cc/0.0.0.0 -address=/1.huobiwang.cc/0.0.0.0 -address=/1.hysou.com/0.0.0.0 -address=/1.i1766.com/0.0.0.0 -address=/1.ideng.com/0.0.0.0 -address=/1.isanxia.com/0.0.0.0 -address=/1.jeasyui.net/0.0.0.0 -address=/1.jiqie.cn/0.0.0.0 -address=/1.kuaidiwo.cn/0.0.0.0 -address=/1.lvshi567.com/0.0.0.0 -address=/1.mgff.com/0.0.0.0 -address=/1.mm100.com/0.0.0.0 -address=/1.pncdn.cn/0.0.0.0 -address=/1.proewildfire.cn/0.0.0.0 -address=/1.qjhm.net/0.0.0.0 -address=/1.qt86.com/0.0.0.0 -address=/1.rr95.com/0.0.0.0 -address=/1.sj33.net/0.0.0.0 -address=/1.snzfj.net/0.0.0.0 -address=/1.soufy.cn/0.0.0.0 -address=/1.tongquee.com/0.0.0.0 -address=/1.ttxs123.net/0.0.0.0 -address=/1.tulaoshi.com/0.0.0.0 -address=/1.tuxi.com.cn/0.0.0.0 -address=/1.uc129.com/0.0.0.0 -address=/1.ufc123.com/0.0.0.0 -address=/1.v-x.com.cn/0.0.0.0 -address=/1.vsimg.com/0.0.0.0 -address=/1.wenzhangba.cn/0.0.0.0 -address=/1.win7china.com/0.0.0.0 -address=/1.wosoni.com/0.0.0.0 -address=/1.xiaopin5.com/0.0.0.0 -address=/1.xilu.com/0.0.0.0 -address=/1.xspic.com/0.0.0.0 -address=/1.xuexi.la/0.0.0.0 -address=/1.yac8.net/0.0.0.0 -address=/1.yuexw.com/0.0.0.0 -address=/1.yxzw.com.cn/0.0.0.0 -address=/1.zhev.com.cn/0.0.0.0 -address=/1.zhuangxiu567.com/0.0.0.0 -address=/1.zou114.com/0.0.0.0 -address=/1.zuowenjun.com/0.0.0.0 -address=/1.zw3e.com/0.0.0.0 -address=/1017.cn/0.0.0.0 -address=/11.96131.com.cn/0.0.0.0 -address=/11.golang8.com/0.0.0.0 -address=/111g.yiqig.cn/0.0.0.0 -address=/11888vip.cn/0.0.0.0 -address=/12.cookcai.com/0.0.0.0 -address=/1224.dxsbb.com/0.0.0.0 -address=/123.39jz.com/0.0.0.0 -address=/123456.asia/0.0.0.0 -address=/17.huanqiu.com/0.0.0.0 -address=/177o.com/0.0.0.0 -address=/1999019.com/0.0.0.0 -address=/2.haoxue360.com/0.0.0.0 -address=/2.heiyange.com/0.0.0.0 -address=/2.rengshu.com/0.0.0.0 -address=/21.cizhibaogao.org/0.0.0.0 -address=/21.fh21static.com/0.0.0.0 -address=/22.qingsongbar.com/0.0.0.0 -address=/283.laobanfa.com/0.0.0.0 -address=/3.chuanyi5.com/0.0.0.0 -address=/3.guidaye.com/0.0.0.0 -address=/3.ssqzj.com/0.0.0.0 -address=/32.huanqiu.com/0.0.0.0 -address=/321.jintang114.org/0.0.0.0 -address=/360640.com/0.0.0.0 -address=/51dengshan.cn/0.0.0.0 -address=/51gxqm.com/0.0.0.0 -address=/52linglei.com/0.0.0.0 -address=/52lubo.cn/0.0.0.0 -address=/52m.xde6.net/0.0.0.0 -address=/5dian.org/0.0.0.0 -address=/5egk.com/0.0.0.0 -address=/644446.com/0.0.0.0 -address=/66.zx1234.com/0.0.0.0 -address=/6669667.com/0.0.0.0 -address=/7011.stia.cn/0.0.0.0 -address=/7631.com/0.0.0.0 -address=/76e.org/0.0.0.0 -address=/7car.com.cn/0.0.0.0 -address=/80juqing.com/0.0.0.0 -address=/8131.qizhihaotian.cn/0.0.0.0 -address=/8dp.net/0.0.0.0 -address=/9wushuo.com/0.0.0.0 -address=/a.4aqq.com/0.0.0.0 -address=/a.52wubi.com/0.0.0.0 -address=/a.52zxw.com/0.0.0.0 -address=/a.armystar.com/0.0.0.0 -address=/a.bake818.cn/0.0.0.0 -address=/a.bizhiku.net/0.0.0.0 -address=/a.booksir.cn/0.0.0.0 -address=/a.diaoyu.cn/0.0.0.0 -address=/a.duanmeiwen.com/0.0.0.0 -address=/a.duduji.com/0.0.0.0 -address=/a.dyjqd.com/0.0.0.0 -address=/a.epinv.com/0.0.0.0 -address=/a.exam58.com/0.0.0.0 -address=/a.fengyx.com/0.0.0.0 -address=/a.fwsir.com/0.0.0.0 -address=/a.hsbianma.com/0.0.0.0 -address=/a.icdol.com/0.0.0.0 -address=/a.ihref.com/0.0.0.0 -address=/a.imgso.cn/0.0.0.0 -address=/a.jing55.com/0.0.0.0 -address=/a.kejixun.com/0.0.0.0 -address=/a.lz13.cn/0.0.0.0 -address=/a.mfcad.net/0.0.0.0 -address=/a.nanhuwang.com/0.0.0.0 -address=/a.oh100.com/0.0.0.0 -address=/a.psxxw.cn/0.0.0.0 -address=/a.qinghua5.com/0.0.0.0 -address=/a.qsjiajiao.com/0.0.0.0 -address=/a.rensheng5.com/0.0.0.0 -address=/a.shenchuang.com/0.0.0.0 -address=/a.thn21.com/0.0.0.0 -address=/a.tiyuxiu.com/0.0.0.0 -address=/a.tvsou.com/0.0.0.0 -address=/a.umilu.com/0.0.0.0 -address=/a.ut8d8.com/0.0.0.0 -address=/a.wanzhuang.com/0.0.0.0 -address=/a.wifi33.com/0.0.0.0 -address=/a.xixiyishu.com/0.0.0.0 -address=/a.xuezizhai.com/0.0.0.0 -address=/a.xxdy8.cn/0.0.0.0 -address=/a.yangshengtang123.com/0.0.0.0 -address=/a.yixie8.com/0.0.0.0 -address=/a.yl-taikang.com/0.0.0.0 -address=/a.yuzhainan.com/0.0.0.0 -address=/a.zuowenxuan.cn/0.0.0.0 -address=/a1.0s.net.cn/0.0.0.0 -address=/a1.7down.com/0.0.0.0 -address=/a1.99933.cn/0.0.0.0 -address=/a1.99966.cn/0.0.0.0 -address=/a1.aluntan.com/0.0.0.0 -address=/a1.bestopview.com/0.0.0.0 -address=/a1.bookapka.com/0.0.0.0 -address=/a1.firefoxchina.cn/0.0.0.0 -address=/a1.firstgw.com/0.0.0.0 -address=/a1.gexing.me/0.0.0.0 -address=/a1.lshou.com/0.0.0.0 -address=/a1.mingyihui.net/0.0.0.0 -address=/a1.q6u.com/0.0.0.0 -address=/a1.qqjay.com/0.0.0.0 -address=/a1.qqtn.com/0.0.0.0 -address=/a1.shusanqi.com/0.0.0.0 -address=/a1.sumiaowang.com/0.0.0.0 -address=/a1.twtym.com/0.0.0.0 -address=/a1.vdolady.com/0.0.0.0 -address=/a1.yuuedu.com/0.0.0.0 -address=/a1.zhanzhang.net/0.0.0.0 -address=/a15d55423.5tps.xyz/0.0.0.0 -address=/a3.ikafan.com/0.0.0.0 -address=/a3.jandan.net/0.0.0.0 -address=/aa.gushiwen.org/0.0.0.0 -address=/aa.xiangxiangmf.com/0.0.0.0 -address=/ab.cnbanbao.com/0.0.0.0 -address=/ab.pincai.com/0.0.0.0 -address=/abc.douguo.com/0.0.0.0 -address=/abcj.dooccn.com/0.0.0.0 -address=/abds.pingpingw.com/0.0.0.0 -address=/ac.86huoche.com/0.0.0.0 -address=/ac.art456.com/0.0.0.0 -address=/ac1.786ip.com/0.0.0.0 -address=/ac1.faxingchina.com/0.0.0.0 -address=/ad123.ynet.com/0.0.0.0 -address=/adbd.liuxue86.com/0.0.0.0 -address=/adccoo.cn/0.0.0.0 -address=/adjb.5nd.com/0.0.0.0 -address=/aiwen.cc/0.0.0.0 -address=/al.newxue.com/0.0.0.0 -address=/as1.m.hao123.com/0.0.0.0 -address=/as1.wenku.baidu.com/0.0.0.0 -address=/b.kouke5.com/0.0.0.0 -address=/b.unjs.com/0.0.0.0 -address=/b1.51scw.net/0.0.0.0 -address=/b1.91jucai.com/0.0.0.0 -address=/b1.b2b168.com/0.0.0.0 -address=/b1.b2b168.net/0.0.0.0 -address=/b1.baomihua.com/0.0.0.0 -address=/b1.c1km4.com/0.0.0.0 -address=/b1.fengdu100.com/0.0.0.0 -address=/b17.8794.cn/0.0.0.0 -address=/b7sw62.pingshu8.xyz/0.0.0.0 -address=/baid1.okooo.com/0.0.0.0 -address=/baidu1.codejie.net/0.0.0.0 -address=/baiduada.babihu.com/0.0.0.0 -address=/baidujs.cnys.com/0.0.0.0 -address=/baiduwapjs1.chinaiiss.com/0.0.0.0 -address=/bas.boshi.tv/0.0.0.0 -address=/bd-s.baixing.net/0.0.0.0 -address=/bd.czxuexi.com/0.0.0.0 -address=/bd.ershenghuo.com/0.0.0.0 -address=/bd.hao224.com/0.0.0.0 -address=/bd.haomagujia.com/0.0.0.0 -address=/bd.scw98.com/0.0.0.0 -address=/bd1-china.6789.com/0.0.0.0 -address=/bd1.365qilu.com/0.0.0.0 -address=/bd1.52che.com/0.0.0.0 -address=/bd1.99danji.com/0.0.0.0 -address=/bd1.dopa.com/0.0.0.0 -address=/bd1.flfgw.cn/0.0.0.0 -address=/bd1.heiguang.cn/0.0.0.0 -address=/bd1.jinbaozy.com/0.0.0.0 -address=/bd1.ningboseo0574.com/0.0.0.0 -address=/bd1.nxing.cn/0.0.0.0 -address=/bd1.pipaw.com/0.0.0.0 -address=/bd1.sosg.net/0.0.0.0 -address=/bd1.szhk.com/0.0.0.0 -address=/bd1.wowoqq.com/0.0.0.0 -address=/bd1.xiby.cn/0.0.0.0 -address=/bd1.yidu.cc/0.0.0.0 -address=/bd11.nipic.com/0.0.0.0 -address=/bd3.chuiyue.com/0.0.0.0 -address=/bdad.gaotie.net/0.0.0.0 -address=/bdasd.chinabig.com.cn/0.0.0.0 -address=/bdasd.wmxa.cn/0.0.0.0 -address=/bdcm.kandianla.com/0.0.0.0 -address=/bdcode.2345.com/0.0.0.0 -address=/bdcode.35d1.com/0.0.0.0 -address=/bdcode.qinglm.com/0.0.0.0 -address=/bdcode.youke.com/0.0.0.0 -address=/bdcode1.haodou.com/0.0.0.0 -address=/bddm.58news.org/0.0.0.0 -address=/bdfpbimg.ifengimg.com/0.0.0.0 -address=/bdgg.qjy168.com/0.0.0.0 -address=/bdgg.youbian.com/0.0.0.0 -address=/bdjb.gai001.com/0.0.0.0 -address=/bdjiaoben.wmxa.cn/0.0.0.0 -address=/bdjj.bzr99.com/0.0.0.0 -address=/bdjj.makepolo.net/0.0.0.0 -address=/bdjs.163lady.com/0.0.0.0 -address=/bdjs.6822.com/0.0.0.0 -address=/bdjs.91zhuti.com/0.0.0.0 -address=/bdjs.guangyuanol.cn/0.0.0.0 -address=/bdjs.ixiumei.com/0.0.0.0 -address=/bdjs.kaixin100.com/0.0.0.0 -address=/bdjs.shangc.net/0.0.0.0 -address=/bdjs.uimg.cn/0.0.0.0 -address=/bdjs.ylq.com/0.0.0.0 -address=/bdlmggcs1.familydoctor.com.cn/0.0.0.0 -address=/bdm.911cha.com/0.0.0.0 -address=/bdmjs.xywy.com/0.0.0.0 -address=/bdu.focus.cn/0.0.0.0 -address=/bdu1.coozhi.cn/0.0.0.0 -address=/bdu1.eol.cn/0.0.0.0 -address=/bdunion1.suxiazai.com/0.0.0.0 -address=/bdwmhz.120askimages.com/0.0.0.0 -address=/bdx.playnext.cn/0.0.0.0 -address=/becode.qiushibaike.com/0.0.0.0 -address=/becode.xiao84.com/0.0.0.0 -address=/beijing.buzhi5.com/0.0.0.0 -address=/bhaoea.cn/0.0.0.0 -address=/boy.fujieace.com/0.0.0.0 -address=/bt1.patexplorer.com/0.0.0.0 -address=/bu1.duba.com/0.0.0.0 -address=/bu1.vvvdj.com/0.0.0.0 -address=/c.booksir.com.cn/0.0.0.0 -address=/c.jjkk.org/0.0.0.0 -address=/c.mnjkw.cn/0.0.0.0 -address=/c.tvsou.com/0.0.0.0 -address=/c.xiaobaipan.com/0.0.0.0 -address=/c1.4qx.net/0.0.0.0 -address=/c1.china.cn/0.0.0.0 -address=/c6.friok.com/0.0.0.0 -address=/ca.cydp5.com/0.0.0.0 -address=/car.qcmrjx.com/0.0.0.0 -address=/cbdm.weathercn.com/0.0.0.0 -address=/cby521.cn/0.0.0.0 -address=/cby521.com/0.0.0.0 -address=/cc.xiaodapei.com/0.0.0.0 -address=/cdn1.tvzhe.com/0.0.0.0 -address=/cee1.iteye.com/0.0.0.0 -address=/cgm.shicimingju.com/0.0.0.0 -address=/chicken18.com/0.0.0.0 -address=/chuangyixi.com/0.0.0.0 -address=/cj1.256.cc/0.0.0.0 -address=/ckg.vipyl.com/0.0.0.0 -address=/classic.39health.com/0.0.0.0 -address=/cm.baidu.com/0.0.0.0 -address=/cn.bidushe.com/0.0.0.0 -address=/cod.southmoney.com/0.0.0.0 -address=/code.ditiezu.net/0.0.0.0 -address=/code.ts166.net/0.0.0.0 -address=/code.tui80.com/0.0.0.0 -address=/codeym.dictall.com/0.0.0.0 -address=/cp.7y7.com/0.0.0.0 -address=/cp.greenxf.cn/0.0.0.0 -address=/cp.jfcdns.com/0.0.0.0 -address=/cp.qbaobei.com/0.0.0.0 -address=/cpro.zol.com.cn/0.0.0.0 -address=/crayon.meishichina.com/0.0.0.0 -address=/cspb1.5w5w.com/0.0.0.0 -address=/css.juqingba.cn/0.0.0.0 -address=/ctc.weather.com.cn/0.0.0.0 -address=/d.ab126.com/0.0.0.0 -address=/d.dgzj.com/0.0.0.0 -address=/d.gz2010.cn/0.0.0.0 -address=/d.gzpinda.com/0.0.0.0 -address=/d.tonghua5.com/0.0.0.0 -address=/d.xaoyo.com/0.0.0.0 -address=/d.xitongtiandi.net/0.0.0.0 -address=/d1.5h.com/0.0.0.0 -address=/d1.handdiy.com/0.0.0.0 -address=/d1.zhuangxiu6.com/0.0.0.0 -address=/d6.mobaders.com/0.0.0.0 -address=/dai.siyuetian.net/0.0.0.0 -address=/dai18.mumu01.com/0.0.0.0 -address=/dai18.shangc.net/0.0.0.0 -address=/dail01.wanmeilr.com/0.0.0.0 -address=/daima.diaoben.net/0.0.0.0 -address=/daima.huoche.net/0.0.0.0 -address=/daima.ijq.tv/0.0.0.0 -address=/daima.jiazhao.com/0.0.0.0 -address=/daima.miercn.com/0.0.0.0 -address=/daima.niubb.net/0.0.0.0 -address=/daima.ysdui.com/0.0.0.0 -address=/daima.yutou123.cn/0.0.0.0 -address=/daiwofei2019.top/0.0.0.0 -address=/data.waptime.cn/0.0.0.0 -address=/datas.tianqistatic.com/0.0.0.0 -address=/daxueshengqiandai.com/0.0.0.0 -address=/dd1.diymianmo.com/0.0.0.0 -address=/df666.pzhttaax.cn/0.0.0.0 -address=/df888.eastday.com/0.0.0.0 -address=/dm.300zi.com/0.0.0.0 -address=/dm.3454.com/0.0.0.0 -address=/dm.51okc.com/0.0.0.0 -address=/dm.66qw.net/0.0.0.0 -address=/dm.66wenshen.com/0.0.0.0 -address=/dm.aizhan.com/0.0.0.0 -address=/dm.cnbanbao.com/0.0.0.0 -address=/dm.cqdxun.cn/0.0.0.0 -address=/dm.gucheng.com/0.0.0.0 -address=/dm.haojuzi.net/0.0.0.0 -address=/dm.huochepiao.com/0.0.0.0 -address=/dm.hxzdhn.com/0.0.0.0 -address=/dm.ishuo.cn/0.0.0.0 -address=/dm.jb51.net/0.0.0.0 -address=/dm.jsyst.cn/0.0.0.0 -address=/dm.pw0.cn/0.0.0.0 -address=/dm.riji.cn/0.0.0.0 -address=/dm.sanwen.net/0.0.0.0 -address=/dm.sanwen8.com/0.0.0.0 -address=/dm.sb580.com/0.0.0.0 -address=/dm.taobaojuhuasuan.cn/0.0.0.0 -address=/dm.wenshenxiu.com/0.0.0.0 -address=/dm.zuowenku.net/0.0.0.0 -address=/dm1.3199.cn/0.0.0.0 -address=/dm1.3328.cn/0.0.0.0 -address=/dm1.yongkao.com/0.0.0.0 -address=/dm1.zjydt.com/0.0.0.0 -address=/dmm.aizhan.com/0.0.0.0 -address=/dmr.cnhoney.com/0.0.0.0 -address=/dmsz.win7sky.com/0.0.0.0 -address=/dmym.aixyy.com/0.0.0.0 -address=/du1.bbdj.com/0.0.0.0 -address=/dudm.qingsj.cn/0.0.0.0 -address=/dzais.com/0.0.0.0 -address=/e.qiaoyuwang.com/0.0.0.0 -address=/ee.shixunwang.net/0.0.0.0 -address=/ejunshi.com/0.0.0.0 -address=/emjs.mkzhan.com/0.0.0.0 -address=/ent1.12584.cn/0.0.0.0 -address=/er.5ykj.com/0.0.0.0 -address=/f.520tingshu.com/0.0.0.0 -address=/f1.06ps.com/0.0.0.0 -address=/f1.ichong123.com/0.0.0.0 -address=/f1.lutouwang.net/0.0.0.0 -address=/f1.pig66.com/0.0.0.0 -address=/f1.zaojv.com/0.0.0.0 -address=/fanyi100.com.cn/0.0.0.0 -address=/fbmjc.39yst.com/0.0.0.0 -address=/feidalu.com/0.0.0.0 -address=/ff.guidaye.com/0.0.0.0 -address=/ff.xue163.net/0.0.0.0 -address=/firefang.cn/0.0.0.0 -address=/fmgoal.com/0.0.0.0 -address=/forad1.weimeicun.com/0.0.0.0 -address=/fotao9.com/0.0.0.0 -address=/fp.jj59.com/0.0.0.0 -address=/fp.nanrenwo.net/0.0.0.0 -address=/fpb.kuhou.com/0.0.0.0 -address=/fpb.sohu.com/0.0.0.0 -address=/fpb1.apple886.com/0.0.0.0 -address=/fpb1.gxfin.com/0.0.0.0 -address=/fpbcode.onlinedown.net/0.0.0.0 -address=/fxjs.2541.com/0.0.0.0 -address=/fzb01.qiushibaike.com/0.0.0.0 -address=/g.3lian.com/0.0.0.0 -address=/g.gegeyingshi.com/0.0.0.0 -address=/g.pgu.cc/0.0.0.0 -address=/g1.pptair.com/0.0.0.0 -address=/g1.taijuba.com/0.0.0.0 -address=/gaoguai.com/0.0.0.0 -address=/gb.it1352.com/0.0.0.0 -address=/gccode.gongchang.com/0.0.0.0 -address=/gg.egouz.com/0.0.0.0 -address=/gg.jkmeishi.com/0.0.0.0 -address=/gg1.jc001.cn/0.0.0.0 -address=/gg1.mengchongzu.com/0.0.0.0 -address=/ggdm1.nhaidu.net/0.0.0.0 -address=/gk1.582582.com/0.0.0.0 -address=/gk1.zjbiz.net/0.0.0.0 -address=/godloveme.cn/0.0.0.0 -address=/gold.szonline.net/0.0.0.0 -address=/gp.zaiyunli.cn/0.0.0.0 -address=/guang.sdsgwy.com/0.0.0.0 -address=/gzcl999.cn/0.0.0.0 -address=/gzcl999.com/0.0.0.0 -address=/gzm.xzbu.com/0.0.0.0 -address=/h1.cfxinxi.cn/0.0.0.0 -address=/h1.kukuw.com/0.0.0.0 -address=/ha.zixuekaoshi.net/0.0.0.0 -address=/hao.315hyw.com/0.0.0.0 -address=/hao.360hyzj.com/0.0.0.0 -address=/hao1.loxue.com/0.0.0.0 -address=/hapic1.zhuangxiu22.com/0.0.0.0 -address=/hccms.com.cn/0.0.0.0 -address=/hdc.maxli.cn/0.0.0.0 -address=/hh.jiankang.com/0.0.0.0 -address=/hi.xiunm.cn/0.0.0.0 -address=/hi.xiunm.com/0.0.0.0 -address=/hiorange1.jobui.com/0.0.0.0 -address=/hu.xbhy.com/0.0.0.0 -address=/huhai.cdwz8.cn/0.0.0.0 -address=/hy.huangye88.com.cn/0.0.0.0 -address=/hy.huangye88.net/0.0.0.0 -address=/iia1.pikacn.com/0.0.0.0 -address=/img.263y.com/0.0.0.0 -address=/img.ferlie.net/0.0.0.0 -address=/img.xuenb.com/0.0.0.0 -address=/img.yangshengtang123.com/0.0.0.0 -address=/img.zuowen8.com/0.0.0.0 -address=/img.zuowenwang.net/0.0.0.0 -address=/img1.biyan8.com/0.0.0.0 -address=/img1.eywdf.com/0.0.0.0 -address=/img1.leyun365.com/0.0.0.0 -address=/img1.yulu99.com/0.0.0.0 -address=/img16.diyifanwen.com/0.0.0.0 -address=/img2.pengfu.net/0.0.0.0 -address=/int.w3tong.com/0.0.0.0 -address=/ios.426g.com/0.0.0.0 -address=/j.baminw.cn/0.0.0.0 -address=/j.diangon.com/0.0.0.0 -address=/j.imdb.cn/0.0.0.0 -address=/j1.piaobing.com/0.0.0.0 -address=/jb.dianshu119.com/0.0.0.0 -address=/jb.ecar168.cn/0.0.0.0 -address=/jc1.dayfund.cn/0.0.0.0 -address=/jddaw.com/0.0.0.0 -address=/jiaoben.eastday.com/0.0.0.0 -address=/jiaoben.ganji.cn/0.0.0.0 -address=/jiaoben.jucanw.com/0.0.0.0 -address=/jiaoben.webkaka.com/0.0.0.0 -address=/jibn12.jintang114.org/0.0.0.0 -address=/jinghuazhijia.com/0.0.0.0 -address=/jinhonghao.cn/0.0.0.0 -address=/jinshui2018.chalook.net/0.0.0.0 -address=/jiyan.net/0.0.0.0 -address=/jke1.jianke.com/0.0.0.0 -address=/jm1.xiao89.com/0.0.0.0 -address=/jnsz.net.cn/0.0.0.0 -address=/js.23yy.com/0.0.0.0 -address=/js.51ir.cn/0.0.0.0 -address=/js.fc090.com/0.0.0.0 -address=/js.gdyjs.com/0.0.0.0 -address=/js.itaiju.com/0.0.0.0 -address=/js.jianbihuadq.com/0.0.0.0 -address=/js.kt250.com/0.0.0.0 -address=/js.ruiwen.com/0.0.0.0 -address=/js.shangxueba.com/0.0.0.0 -address=/js.ubaike.cn/0.0.0.0 -address=/js1.sxptfw.com/0.0.0.0 -address=/js1.xbaixing.com/0.0.0.0 -address=/jsb.qianzhan.com/0.0.0.0 -address=/jscode.acg68.com/0.0.0.0 -address=/jscode.jbzj.com/0.0.0.0 -address=/jsf.cnlinfo.net/0.0.0.0 -address=/jsm.39yst.com/0.0.0.0 -address=/jss.tvzhe.com/0.0.0.0 -address=/jx.renrensousuo.com/0.0.0.0 -address=/jy.zhongxues.com/0.0.0.0 -address=/k1.dancihu.com/0.0.0.0 -address=/k1.wanwenwan.cn/0.0.0.0 -address=/ka5188.com/0.0.0.0 -address=/kc.gouchezj.com/0.0.0.0 -address=/khrtac.xiangha.com/0.0.0.0 -address=/km1.muhoujiemi.com/0.0.0.0 -address=/kpshx.douguo.com/0.0.0.0 -address=/lang.t7114.com/0.0.0.0 -address=/libs.tvmao.cn/0.0.0.0 -address=/linyao.dxsdb.com/0.0.0.0 -address=/lixiangmo.com/0.0.0.0 -address=/ll38.com/0.0.0.0 -address=/lm.ijq.tv/0.0.0.0 -address=/lm1.tuliu.com/0.0.0.0 -address=/lm1.wzpcw.com/0.0.0.0 -address=/lraa.xiaoniutui.com/0.0.0.0 -address=/luoshenbest.cn/0.0.0.0 -address=/lv.myapks.com/0.0.0.0 -address=/lyz.radio366.com/0.0.0.0 -address=/m1.27com.com/0.0.0.0 -address=/m1.51kaowang.com/0.0.0.0 -address=/m1.81312.com/0.0.0.0 -address=/m1.darfd.com/0.0.0.0 -address=/m1.dxsbb.com/0.0.0.0 -address=/m1.hapi123.net/0.0.0.0 -address=/m1.jintang114.org/0.0.0.0 -address=/m1.kuanff.com/0.0.0.0 -address=/m1.nn670.com/0.0.0.0 -address=/m1.vodjk.com/0.0.0.0 -address=/m1.we556.com/0.0.0.0 -address=/ma1.meishij.net/0.0.0.0 -address=/mad1.jirou.com/0.0.0.0 -address=/matwbp.iask.sina.com.cn/0.0.0.0 -address=/mb.gulongbbs.com/0.0.0.0 -address=/mbjb1.girl13.com/0.0.0.0 -address=/mc.tvzhe.com/0.0.0.0 -address=/mc.weather.com.cn/0.0.0.0 -address=/md.tvzhe.com/0.0.0.0 -address=/meng.360zuowen.com/0.0.0.0 -address=/mf01.zybang.com/0.0.0.0 -address=/milk.yesky.com.cn/0.0.0.0 -address=/mo-tuo.com/0.0.0.0 -address=/mountain.zhidao.baidu.com/0.0.0.0 -address=/mpb1.iteye.com/0.0.0.0 -address=/mps.yuwenba.cn/0.0.0.0 -address=/mssheng.com/0.0.0.0 -address=/mt.59wz.com/0.0.0.0 -address=/my.gz2010.cn/0.0.0.0 -address=/myunion1.qm120.com/0.0.0.0 -address=/myunion1.tupians.com/0.0.0.0 -address=/nba.emohe.com/0.0.0.0 -address=/new.htcui.com/0.0.0.0 -address=/news.jiukang.org/0.0.0.0 -address=/ns1.chinayms.com/0.0.0.0 -address=/o.jy135.com/0.0.0.0 -address=/o.phb123.com/0.0.0.0 -address=/okkkk.com/0.0.0.0 -address=/p1.zhongyoo.com/0.0.0.0 -address=/p1.zhumengwl.com/0.0.0.0 -address=/pan.keyunzhan.com/0.0.0.0 -address=/pb.okk123.com/0.0.0.0 -address=/pb.shuxigua.com/0.0.0.0 -address=/pic50.pingguolv.com/0.0.0.0 -address=/pingbi.diudou.com/0.0.0.0 -address=/pingshu365.xyz/0.0.0.0 -address=/pkk1.zuimeiniwo.com/0.0.0.0 -address=/pp.wayqq.com/0.0.0.0 -address=/ppt.tianya999.com/0.0.0.0 -address=/psywed.com/0.0.0.0 -address=/ptw.la/0.0.0.0 -address=/q1.yyxwzx.com/0.0.0.0 -address=/qcjslm.com/0.0.0.0 -address=/qifake.com/0.0.0.0 -address=/qiji1.jdwx.info/0.0.0.0 -address=/qiyeb.iaskbus.com/0.0.0.0 -address=/qpb.sohu.com/0.0.0.0 -address=/qq167.com/0.0.0.0 -address=/qqhuhu.com/0.0.0.0 -address=/qujishu.com/0.0.0.0 -address=/r.99waiyu.com/0.0.0.0 -address=/rabc1.iteye.com/0.0.0.0 -address=/rbmry.com/0.0.0.0 -address=/rdbd.xsread.com/0.0.0.0 -address=/rmcxw.cn/0.0.0.0 -address=/rmcxw.net/0.0.0.0 -address=/ruan88.com/0.0.0.0 -address=/s.zixuntop.com/0.0.0.0 -address=/s1.dapenti.com/0.0.0.0 -address=/s1.dugoogle.com/0.0.0.0 -address=/s1.hualaoye.com/0.0.0.0 -address=/s1.qiqutt.cn/0.0.0.0 -address=/s1.qiqutt.com/0.0.0.0 -address=/s1.tuzhaozhao.com/0.0.0.0 -address=/s1.wan1979.com/0.0.0.0 -address=/s1.wesiedu.com/0.0.0.0 -address=/salary.xiao84.com/0.0.0.0 -address=/sbbd1.qulishi.com/0.0.0.0 -address=/sc.csai.cn/0.0.0.0 -address=/script-bd.baixing.net/0.0.0.0 -address=/sdd.dzsc.com/0.0.0.0 -address=/sdd.hi1718.com/0.0.0.0 -address=/sh996.dftoutiao.com/0.0.0.0 -address=/shicao.icantv.cn/0.0.0.0 -address=/shili.downxia.com/0.0.0.0 -address=/shili.wanyx.com/0.0.0.0 -address=/shop265.com/0.0.0.0 -address=/show.9zwang.com/0.0.0.0 -address=/sjbaiduadv1.redou.com/0.0.0.0 -address=/sjzqu.com/0.0.0.0 -address=/sp.dnqc.com/0.0.0.0 -address=/ss.shicimingju.com/0.0.0.0 -address=/ss.ting55.com/0.0.0.0 -address=/ssb.ah499.com/0.0.0.0 -address=/static.ichehome.com/0.0.0.0 -address=/static.jiaquyi.com/0.0.0.0 -address=/t.cnscore.com/0.0.0.0 -address=/t.douyaobuy.com/0.0.0.0 -address=/t1.612.com/0.0.0.0 -address=/thetestpage.39.net/0.0.0.0 -address=/ticcdn.com/0.0.0.0 -address=/tongj.xilu.com/0.0.0.0 -address=/tt123.eastday.com/0.0.0.0 -address=/tt123.hao0202.com/0.0.0.0 -address=/tu.zx110.org/0.0.0.0 -address=/tui98.cn/0.0.0.0 -address=/u1.2048sj.com/0.0.0.0 -address=/u1.20q.cn/0.0.0.0 -address=/u1.shuaiku.com/0.0.0.0 -address=/ub1.job592.com/0.0.0.0 -address=/un1.takefoto.cn/0.0.0.0 -address=/undm.qibulo.com/0.0.0.0 -address=/union1.cnbetacdn.com/0.0.0.0 -address=/uniondm.cz88.net/0.0.0.0 -address=/usejj.wangkl.com/0.0.0.0 -address=/uuu.pctowap.com/0.0.0.0 -address=/v1.kwpewga.cn/0.0.0.0 -address=/v1.phb123.com/0.0.0.0 -address=/v1.taksh.cn/0.0.0.0 -address=/ve.kj-cy.cn/0.0.0.0 -address=/vi1.souid.com/0.0.0.0 -address=/vv1.pyhfxdm.cn/0.0.0.0 -address=/vvv.ieduw.com/0.0.0.0 -address=/vyule.com/0.0.0.0 -address=/w.xiaopiaoyou.com/0.0.0.0 -address=/w1.diaoyou.com/0.0.0.0 -address=/w1.wayqq.com/0.0.0.0 -address=/w11.zhongkaohelp.com/0.0.0.0 -address=/w18.9939.com/0.0.0.0 -address=/wap001.bytravel.cn/0.0.0.0 -address=/wda.ydt.com.cn/0.0.0.0 -address=/whfpbc.99.com.cn/0.0.0.0 -address=/wj.jiancai365.cn/0.0.0.0 -address=/wm.mipcdn.com/0.0.0.0 -address=/wneia.iaskhot.com/0.0.0.0 -address=/ws.wenshenxiu.com/0.0.0.0 -address=/wuliao.chzsport.cn/0.0.0.0 -address=/wuliao.juqingba.cn/0.0.0.0 -address=/wyzq.rehuwang.com/0.0.0.0 -address=/x.mtrend.cn/0.0.0.0 -address=/x1.kantu.com/0.0.0.0 -address=/xbtw.com/0.0.0.0 -address=/xc.gouchezj.com/0.0.0.0 -address=/xcf-bd-js.chuimg.com/0.0.0.0 -address=/xiaopangtao.com/0.0.0.0 -address=/xiaoyutiao.com/0.0.0.0 -address=/xinju.cc/0.0.0.0 -address=/xinkuaiyu.com/0.0.0.0 -address=/xitongku.cc/0.0.0.0 -address=/xne1ocient87zxz.360doc.cn/0.0.0.0 -address=/xue.zbyw.cn/0.0.0.0 -address=/xuexi.hydcd.com/0.0.0.0 -address=/y1.spreton.com/0.0.0.0 -address=/y66xvgo5i.chuimg.com/0.0.0.0 -address=/yhzm.cc/0.0.0.0 -address=/yi.ximizi.com/0.0.0.0 -address=/yijiuningyia.gushiwen.org/0.0.0.0 -address=/yin1.zgpingshu.com/0.0.0.0 -address=/ykxwn.com/0.0.0.0 -address=/ynzhby.com/0.0.0.0 -address=/yong.chazidian.com/0.0.0.0 -address=/ys.muhoujiemi.com/0.0.0.0 -address=/ysx8.vip/0.0.0.0 -address=/ysxywj.com/0.0.0.0 -address=/yulzs.com/0.0.0.0 -address=/yx1.managershare.com/0.0.0.0 -address=/yy1.fwccw.com/0.0.0.0 -address=/yy2018.jintonghua.com/0.0.0.0 -address=/z1.chezhuzhinan.com/0.0.0.0 -address=/z1.cyla.cn/0.0.0.0 -address=/z1hihu.xmcimg.com/0.0.0.0 -address=/z888.izhufu.net/0.0.0.0 -address=/zfds1.tianya999.com/0.0.0.0 -address=/zg.mmyuer.com/0.0.0.0 -address=/zhaoshang8.com/0.0.0.0 -address=/zhgg.dre8.com/0.0.0.0 -address=/zhihu.xmcimg.com/0.0.0.0 -address=/zk.91post.com/0.0.0.0 -address=/zoom.zshu.net/0.0.0.0 -address=/zq84.com/0.0.0.0 -address=/0377shujuhuifu.top/0.0.0.0 -address=/0531mnk.net/0.0.0.0 -address=/1711811.com/0.0.0.0 -address=/18dusun.com/0.0.0.0 -address=/2013sh.com/0.0.0.0 -address=/210189.com/0.0.0.0 -address=/258pct.com/0.0.0.0 -address=/258ydh.com/0.0.0.0 -address=/265958.com/0.0.0.0 -address=/2pmob.com/0.0.0.0 -address=/360shopping.com.cn/0.0.0.0 -address=/3dqiang.com/0.0.0.0 -address=/60608787.com/0.0.0.0 -address=/711983.com/0.0.0.0 -address=/77rog.com/0.0.0.0 -address=/910weixin.com/0.0.0.0 -address=/913vt.com/0.0.0.0 -address=/93vitui.com/0.0.0.0 -address=/ailiyou1999.com/0.0.0.0 -address=/aliguojw.com/0.0.0.0 -address=/anhuilitian.net/0.0.0.0 -address=/aodongjiaosu.com/0.0.0.0 -address=/autoyou1678.com/0.0.0.0 -address=/bihutg.com/0.0.0.0 -address=/bjwwfx001.org.cn/0.0.0.0 -address=/blossommo.com/0.0.0.0 -address=/bycxsh.com/0.0.0.0 -address=/ccbccb.cn/0.0.0.0 -address=/cdxyb.cn/0.0.0.0 -address=/chinahdcm.com/0.0.0.0 -address=/dakawm.cc/0.0.0.0 -address=/dfcwg.com/0.0.0.0 -address=/dsgy521.com/0.0.0.0 -address=/dupinpu.com/0.0.0.0 -address=/enyayinxiang.com/0.0.0.0 -address=/etg98.com/0.0.0.0 -address=/fate-xy.com/0.0.0.0 -address=/feihongjiaoyu.com/0.0.0.0 -address=/fenvm.com/0.0.0.0 -address=/fjmailia.com/0.0.0.0 -address=/fm6w.com/0.0.0.0 -address=/front99.com/0.0.0.0 -address=/fuyigo.top/0.0.0.0 -address=/gogolm.xyz/0.0.0.0 -address=/gotourls.bid/0.0.0.0 -address=/guangtui1999.com/0.0.0.0 -address=/gzhctryy.com/0.0.0.0 -address=/gzmsm.cn/0.0.0.0 -address=/h01ce.cn/0.0.0.0 -address=/harbinbaojia.net/0.0.0.0 -address=/hdjxmf.com/0.0.0.0 -address=/hechaocheng.cn/0.0.0.0 -address=/henanfs.com/0.0.0.0 -address=/hfxs01il.com/0.0.0.0 -address=/hgo7r.cn/0.0.0.0 -address=/hulemedia.com/0.0.0.0 -address=/ip.hivps.xyz/0.0.0.0 -address=/jhwj88.com/0.0.0.0 -address=/jjqyk.com/0.0.0.0 -address=/jlhygy.com/0.0.0.0 -address=/juren0.com/0.0.0.0 -address=/kkdsdlc.com/0.0.0.0 -address=/kuangtuiguoo18888.com/0.0.0.0 -address=/kuuad.com/0.0.0.0 -address=/kyad88.com/0.0.0.0 -address=/la61d.cn/0.0.0.0 -address=/lucktui.com/0.0.0.0 -address=/meizhuzhuangshi.com.cn/0.0.0.0 -address=/mengchengbao.com/0.0.0.0 -address=/miaobeichina.com/0.0.0.0 -address=/mightiger.net/0.0.0.0 -address=/mlangw.net/0.0.0.0 -address=/nettsl.com/0.0.0.0 -address=/np176.com/0.0.0.0 -address=/pp9kk.com/0.0.0.0 -address=/pr33.cn/0.0.0.0 -address=/shanghuitianxia.cn/0.0.0.0 -address=/shanxiyizhao.com/0.0.0.0 -address=/shijiezhidao.com/0.0.0.0 -address=/shongcheng.com/0.0.0.0 -address=/shunlige.com/0.0.0.0 -address=/smsksx.com/0.0.0.0 -address=/somode.net/0.0.0.0 -address=/soonyou123.com/0.0.0.0 -address=/sssgao999.com/0.0.0.0 -address=/starstar19999.com/0.0.0.0 -address=/start1999.com/0.0.0.0 -address=/startui19999.com/0.0.0.0 -address=/sy123888.com/0.0.0.0 -address=/tangeb.com/0.0.0.0 -address=/tdtsd.com/0.0.0.0 -address=/tjshuimu.com/0.0.0.0 -address=/tkssw.com/0.0.0.0 -address=/tuituiyoo999.com/0.0.0.0 -address=/tuoguang1111.com/0.0.0.0 -address=/wangketuan.com/0.0.0.0 -address=/weduoke.com/0.0.0.0 -address=/weekslw.com/0.0.0.0 -address=/weixingshexiangji.net/0.0.0.0 -address=/wjdjcjcm444.cn/0.0.0.0 -address=/wxktv.cn/0.0.0.0 -address=/xiaohui2.cn/0.0.0.0 -address=/xlsschina15.net/0.0.0.0 -address=/xueyanshan.com/0.0.0.0 -address=/xvyljkr.com/0.0.0.0 -address=/xzqxz.net/0.0.0.0 -address=/ydeprint.com/0.0.0.0 -address=/ynjkkj.com/0.0.0.0 -address=/yootui19999.com/0.0.0.0 -address=/youhm.cn/0.0.0.0 -address=/youhuomeishi.com/0.0.0.0 -address=/yttz113.com/0.0.0.0 -address=/yunpifu.cn/0.0.0.0 -address=/yuxiangrc.com/0.0.0.0 -address=/yzjlsb.com/0.0.0.0 -address=/zgdmsj.cn/0.0.0.0 -address=/zhuyuanp.club/0.0.0.0 -address=/zhybw88.com/0.0.0.0 -address=/zrwhartongroup.com/0.0.0.0 -address=/ggtg8.com/0.0.0.0 -address=/liyueao.top/0.0.0.0 -address=/lpsgc.cn/0.0.0.0 -address=/yi71.com.cn/0.0.0.0 -address=/okx7.site/0.0.0.0 -address=/runkao.net/0.0.0.0 -address=/stunninglover.com/0.0.0.0 -address=/cryptaloot.pro/0.0.0.0 -address=/bbbr8.com/0.0.0.0 -address=/sdakxz.xyz/0.0.0.0 -address=/12rge.xyz/0.0.0.0 -address=/jnmqym4.cn/0.0.0.0 -address=/sokoyo-fq.com/0.0.0.0 -address=/zhongchengzp.com/0.0.0.0 -address=/01w47q.cn/0.0.0.0 -address=/0234408.cn/0.0.0.0 -address=/02m5j.cn/0.0.0.0 -address=/03196688.com/0.0.0.0 -address=/0532ci.com.cn/0.0.0.0 -address=/0551zgz.com/0.0.0.0 -address=/05q9n.cn/0.0.0.0 -address=/0755man.cn/0.0.0.0 -address=/07kfh.cn/0.0.0.0 -address=/0851ok.com/0.0.0.0 -address=/0923csfsteibv12.xyz/0.0.0.0 -address=/0b6h.cn/0.0.0.0 -address=/0fwg.cn/0.0.0.0 -address=/0n6h.cn/0.0.0.0 -address=/0ozo.cn/0.0.0.0 -address=/0pj1f.cn/0.0.0.0 -address=/0uk9e.cn/0.0.0.0 -address=/0z5jn.cn/0.0.0.0 -address=/1115potmgabfvixqwi.top/0.0.0.0 -address=/114com.cc/0.0.0.0 -address=/118ex.cn/0.0.0.0 -address=/119cgpt.com/0.0.0.0 -address=/12381236.com/0.0.0.0 -address=/12jf3.cn/0.0.0.0 -address=/12rng.cn/0.0.0.0 -address=/1314sss.top/0.0.0.0 -address=/1494.top/0.0.0.0 -address=/168xiazai.com/0.0.0.0 -address=/17bqg.top/0.0.0.0 -address=/17zheng.cn/0.0.0.0 -address=/183pu.cn/0.0.0.0 -address=/1fv3b.cn/0.0.0.0 -address=/1h4ig.cn/0.0.0.0 -address=/1j2h31.cn/0.0.0.0 -address=/1k4vd.cn/0.0.0.0 -address=/1mb034.cn/0.0.0.0 -address=/1r49n.cn/0.0.0.0 -address=/1x26q3.cn/0.0.0.0 -address=/215to.cn/0.0.0.0 -address=/216pu.cn/0.0.0.0 -address=/21u8f.cn/0.0.0.0 -address=/21xsk.com/0.0.0.0 -address=/228pu.cn/0.0.0.0 -address=/24haitao.net/0.0.0.0 -address=/258580w.cn/0.0.0.0 -address=/282l1.cn/0.0.0.0 -address=/28mcw1.cn/0.0.0.0 -address=/2fnrc.cn/0.0.0.0 -address=/2hqd0b.cn/0.0.0.0 -address=/2ktd0.cn/0.0.0.0 -address=/2p1ih.cn/0.0.0.0 -address=/2r3485.cn/0.0.0.0 -address=/2scjbg.com/0.0.0.0 -address=/2shoushi.com/0.0.0.0 -address=/2st5ne.cn/0.0.0.0 -address=/2txt.cc:8862/0.0.0.0 -address=/2v0ni.cn/0.0.0.0 -address=/2v9ml.cn/0.0.0.0 -address=/2wxb5.cn/0.0.0.0 -address=/2zm4.cn/0.0.0.0 -address=/365syt.cn/0.0.0.0 -address=/365yigou.cn/0.0.0.0 -address=/38ursg.cn/0.0.0.0 -address=/3ql1pb.cn/0.0.0.0 -address=/3s1xk.cn/0.0.0.0 -address=/3vn52l.cn/0.0.0.0 -address=/42rca.cn/0.0.0.0 -address=/47dx0c.cn/0.0.0.0 -address=/47n209.com/0.0.0.0 -address=/482hb.cn/0.0.0.0 -address=/49lkc.cn/0.0.0.0 -address=/4a3zf.cn/0.0.0.0 -address=/4df5ef.xyz/0.0.0.0 -address=/4ekx.cn/0.0.0.0 -address=/4excel.cn/0.0.0.0 -address=/4py3oe.cn/0.0.0.0 -address=/4qn1k.cn/0.0.0.0 -address=/4x9te.cn/0.0.0.0 -address=/4z5o27.cn/0.0.0.0 -address=/519397.com/0.0.0.0 -address=/51fishplace.com/0.0.0.0 -address=/51gpt.com/0.0.0.0 -address=/51posuiji.org.cn/0.0.0.0 -address=/51xvc.cn/0.0.0.0 -address=/52homie.cn/0.0.0.0 -address=/52tushuo.com/0.0.0.0 -address=/555b2b.com/0.0.0.0 -address=/57m1j.cn/0.0.0.0 -address=/58scx.com/0.0.0.0 -address=/58xmgys.com/0.0.0.0 -address=/5dydk.com/0.0.0.0 -address=/5kmm.top/0.0.0.0 -address=/5mbd2.com/0.0.0.0 -address=/5pb266.com/0.0.0.0 -address=/5q80n.cn/0.0.0.0 -address=/5tbiec.cn/0.0.0.0 -address=/5x0f.cn/0.0.0.0 -address=/5yv2e.cn/0.0.0.0 -address=/5yw4n.cn/0.0.0.0 -address=/605296.com/0.0.0.0 -address=/606w.cn/0.0.0.0 -address=/609623.com/0.0.0.0 -address=/63xs.com:8016/0.0.0.0 -address=/64si.com/0.0.0.0 -address=/678sky.com/0.0.0.0 -address=/688ct.com/0.0.0.0 -address=/6945k6.cn/0.0.0.0 -address=/69u0t.cn/0.0.0.0 -address=/69yll.cn/0.0.0.0 -address=/6c4t5.cn/0.0.0.0 -address=/6fai2.cn/0.0.0.0 -address=/6l1967.cn/0.0.0.0 -address=/6nzev.cn/0.0.0.0 -address=/6o87d.cn/0.0.0.0 -address=/6ou47b.cn/0.0.0.0 -address=/6shuge.com/0.0.0.0 -address=/6yush.cn/0.0.0.0 -address=/6yw7j.cn/0.0.0.0 -address=/70e.me/0.0.0.0 -address=/71mxc6.cn/0.0.0.0 -address=/71zrh.cn/0.0.0.0 -address=/73cm.com/0.0.0.0 -address=/74p030.cn/0.0.0.0 -address=/757g7g.cn/0.0.0.0 -address=/7ef4d.cn/0.0.0.0 -address=/7ez4.cn/0.0.0.0 -address=/7gbca.cn/0.0.0.0 -address=/7ia9h.cn/0.0.0.0 -address=/7m307.cn/0.0.0.0 -address=/7n3e8o.com/0.0.0.0 -address=/7x3mh.cn/0.0.0.0 -address=/805zx.cn/0.0.0.0 -address=/80f31.cn/0.0.0.0 -address=/81ngn1.cn/0.0.0.0 -address=/85rvq.cn/0.0.0.0 -address=/85wa.cn/0.0.0.0 -address=/88android.com/0.0.0.0 -address=/88k73d.cn/0.0.0.0 -address=/89tyge.top/0.0.0.0 -address=/8byu.cn/0.0.0.0 -address=/8fiv9a.cn/0.0.0.0 -address=/8hpay.cn/0.0.0.0 -address=/8i1xc.cn/0.0.0.0 -address=/8j24h.cn/0.0.0.0 -address=/8ls3n.cn/0.0.0.0 -address=/8p30k.cn/0.0.0.0 -address=/8t5vd.cn/0.0.0.0 -address=/8v61j.cn/0.0.0.0 -address=/8v7wg.com/0.0.0.0 -address=/91byy.cn/0.0.0.0 -address=/922x7c.cn/0.0.0.0 -address=/958so.cn/0.0.0.0 -address=/979067.com/0.0.0.0 -address=/97kuaixiu.com/0.0.0.0 -address=/97paa.com/0.0.0.0 -address=/996f3d.cn/0.0.0.0 -address=/99hg.wang/0.0.0.0 -address=/9a6wb.cn/0.0.0.0 -address=/9d7in.cn/0.0.0.0 -address=/9pb0h.cn/0.0.0.0 -address=/9x6lr.cn/0.0.0.0 -address=/9y88.com/0.0.0.0 -address=/9yyg.cn/0.0.0.0 -address=/a9v8.cn/0.0.0.0 -address=/aa.wenxue6.com/0.0.0.0 -address=/aaan.xyz/0.0.0.0 -address=/aaaw.xyz/0.0.0.0 -address=/aabbccddeeffgg.cn/0.0.0.0 -address=/aabku.cn/0.0.0.0 -address=/aauisg64017.cn/0.0.0.0 -address=/abc656.today/0.0.0.0 -address=/abckzo.cn/0.0.0.0 -address=/abeij.com/0.0.0.0 -address=/abfirst.cn/0.0.0.0 -address=/abuse8.com/0.0.0.0 -address=/acaog.com/0.0.0.0 -address=/acaox.com/0.0.0.0 -address=/acaoz.com/0.0.0.0 -address=/achig.com/0.0.0.0 -address=/actingidekex.cn/0.0.0.0 -address=/adaog.com/0.0.0.0 -address=/admddc.com/0.0.0.0 -address=/aduic.com/0.0.0.0 -address=/aercxy.com/0.0.0.0 -address=/afefw.com/0.0.0.0 -address=/affiliate6.com/0.0.0.0 -address=/afoux.com/0.0.0.0 -address=/aganj.com/0.0.0.0 -address=/agurl.top/0.0.0.0 -address=/ahuac.com/0.0.0.0 -address=/ahw3.com/0.0.0.0 -address=/aibangzs.com/0.0.0.0 -address=/aicydb.com/0.0.0.0 -address=/aikan6.com/0.0.0.0 -address=/ailezhai.cn/0.0.0.0 -address=/ailiby.cn/0.0.0.0 -address=/aimiyz.com/0.0.0.0 -address=/aiode.cn/0.0.0.0 -address=/aishake.cn/0.0.0.0 -address=/aishowbger.com/0.0.0.0 -address=/aiyyu.com/0.0.0.0 -address=/ajiez.com/0.0.0.0 -address=/ajkdg3.xyz/0.0.0.0 -address=/alksdh.com/0.0.0.0 -address=/allluck.cn/0.0.0.0 -address=/alryo.cn/0.0.0.0 -address=/anmeilai.net/0.0.0.0 -address=/anyysz.com/0.0.0.0 -address=/aomde.com/0.0.0.0 -address=/apjiangte.com/0.0.0.0 -address=/apmengxin.com/0.0.0.0 -address=/applequan.com/0.0.0.0 -address=/apxyz.com/0.0.0.0 -address=/archrug.com/0.0.0.0 -address=/autobedo.com.cn/0.0.0.0 -address=/avsmt.cn/0.0.0.0 -address=/awqsaged.cn/0.0.0.0 -address=/awtks.com/0.0.0.0 -address=/awyys.com/0.0.0.0 -address=/axizb.cn/0.0.0.0 -address=/axkxy.com/0.0.0.0 -address=/axsrq.cn/0.0.0.0 -address=/axuns.com/0.0.0.0 -address=/aykcic.com/0.0.0.0 -address=/ayues.com/0.0.0.0 -address=/b0lc.cn/0.0.0.0 -address=/b25ku.cn/0.0.0.0 -address=/b54ah.cn/0.0.0.0 -address=/baful.net/0.0.0.0 -address=/baidu.cmxsw.com/0.0.0.0 -address=/baiduspider1.cn/0.0.0.0 -address=/baitaoidc.com/0.0.0.0 -address=/baiyangzs.com/0.0.0.0 -address=/baolutongwuye.cn/0.0.0.0 -address=/bapkt.com/0.0.0.0 -address=/barnfps.com/0.0.0.0 -address=/bbbx.xyz/0.0.0.0 -address=/bbeyay41026.cn/0.0.0.0 -address=/bbvjs.com/0.0.0.0 -address=/bchur.com/0.0.0.0 -address=/bcunr.com/0.0.0.0 -address=/bdaor.com/0.0.0.0 -address=/bdiae.com/0.0.0.0 -address=/beifmu.com/0.0.0.0 -address=/bentengcn.com/0.0.0.0 -address=/berfd.xyz/0.0.0.0 -address=/bgcse.cn/0.0.0.0 -address=/bgj216.cn/0.0.0.0 -address=/bgtrtv.top/0.0.0.0 -address=/bhuak.com/0.0.0.0 -address=/bianxianwu.com/0.0.0.0 -address=/biboi.cn/0.0.0.0 -address=/biluzhang.cn/0.0.0.0 -address=/bingdiantao.com/0.0.0.0 -address=/bixuyao.com.cn/0.0.0.0 -address=/bjbrtc.com/0.0.0.0 -address=/bjdianyue.com/0.0.0.0 -address=/bjeai.com/0.0.0.0 -address=/bjhengdiao.com/0.0.0.0 -address=/bjqftcty.com/0.0.0.0 -address=/bjygfd.com/0.0.0.0 -address=/bjzcbx.com/0.0.0.0 -address=/blfyquz.cn/0.0.0.0 -address=/bmfwwz.top/0.0.0.0 -address=/bmgan.com/0.0.0.0 -address=/bmuju.com/0.0.0.0 -address=/bninc2.cn/0.0.0.0 -address=/bnzxc.xyz/0.0.0.0 -address=/bobotune.com/0.0.0.0 -address=/bodapet.com/0.0.0.0 -address=/bokanedu.net/0.0.0.0 -address=/boomgamescloud-cdn.cn/0.0.0.0 -address=/boweineng.cn/0.0.0.0 -address=/bpdffh.cn/0.0.0.0 -address=/bqhnj.cn/0.0.0.0 -address=/bqqsdv73724.cn/0.0.0.0 -address=/bslmw.com/0.0.0.0 -address=/bsmakeup.com.cn/0.0.0.0 -address=/bueson.com/0.0.0.0 -address=/bugcreator.cn/0.0.0.0 -address=/bulkeach.com/0.0.0.0 -address=/bvoer.com/0.0.0.0 -address=/bvosv.com/0.0.0.0 -address=/bx9000.top/0.0.0.0 -address=/bym03.cn/0.0.0.0 -address=/byujf.cn/0.0.0.0 -address=/c19f2.cn/0.0.0.0 -address=/c6z85.cn/0.0.0.0 -address=/c82d5.cn/0.0.0.0 -address=/ca88b.cn/0.0.0.0 -address=/caduka.cn/0.0.0.0 -address=/caichenguang.cn/0.0.0.0 -address=/caiji.wiki/0.0.0.0 -address=/cailawyer.cn/0.0.0.0 -address=/caiwanhui.top/0.0.0.0 -address=/calculated.cn/0.0.0.0 -address=/car156.net/0.0.0.0 -address=/casbanlly.com/0.0.0.0 -address=/cbvjddh.23txt.com/0.0.0.0 -address=/cccab.club/0.0.0.0 -address=/cchfjz.com/0.0.0.0 -address=/ccjxybj.cn/0.0.0.0 -address=/ccmdgg.com/0.0.0.0 -address=/ccouv.com/0.0.0.0 -address=/ccunf.com/0.0.0.0 -address=/cdfzcz.com/0.0.0.0 -address=/cdgxq.com/0.0.0.0 -address=/cdhenfan.com/0.0.0.0 -address=/cdiah.com/0.0.0.0 -address=/cdjkngs.cn/0.0.0.0 -address=/cdn.m.okdd.net/0.0.0.0 -address=/cdntlz.cn/0.0.0.0 -address=/cdouj.com/0.0.0.0 -address=/cdqjmc.com/0.0.0.0 -address=/ceiyo.com/0.0.0.0 -address=/cepegas.com/0.0.0.0 -address=/ceyiuy.com/0.0.0.0 -address=/cezezo.top/0.0.0.0 -address=/cfdanet.com/0.0.0.0 -address=/cfenl.com/0.0.0.0 -address=/cfhijdsb.cn/0.0.0.0 -address=/cgaij.com/0.0.0.0 -address=/cgoiiq.com/0.0.0.0 -address=/cgoul.com/0.0.0.0 -address=/cgxxmy.com/0.0.0.0 -address=/changhehengqi.com/0.0.0.0 -address=/chaojilamei.cn/0.0.0.0 -address=/chendjiangxing.cn/0.0.0.0 -address=/chengboke.cn/0.0.0.0 -address=/chenxiangqian.cn/0.0.0.0 -address=/chersc.com/0.0.0.0 -address=/chexiw.com/0.0.0.0 -address=/chfuw.com/0.0.0.0 -address=/chgdf.cn/0.0.0.0 -address=/china-waters.com.cn/0.0.0.0 -address=/chinaairs.cn/0.0.0.0 -address=/chinaqirun.cn/0.0.0.0 -address=/chinaweian.com/0.0.0.0 -address=/chinawms.cn/0.0.0.0 -address=/chrommotor.com/0.0.0.0 -address=/chuangxinfa.cn/0.0.0.0 -address=/chuhul.cn/0.0.0.0 -address=/chutangpu.cn/0.0.0.0 -address=/cike666.com/0.0.0.0 -address=/cindy17club.com/0.0.0.0 -address=/city009.com/0.0.0.0 -address=/cjh9.cn/0.0.0.0 -address=/cjieh.com/0.0.0.0 -address=/ckaiv.com/0.0.0.0 -address=/ckikq.com/0.0.0.0 -address=/claiks.com/0.0.0.0 -address=/clandia.cn/0.0.0.0 -address=/classicgir.cn/0.0.0.0 -address=/clmmw.com/0.0.0.0 -address=/cn-3drp.com/0.0.0.0 -address=/cni58.com/0.0.0.0 -address=/cniuv.com/0.0.0.0 -address=/cnlhg.cn/0.0.0.0 -address=/cnshef.com/0.0.0.0 -address=/cnxmyb.cn/0.0.0.0 -address=/cnyibs.com/0.0.0.0 -address=/cnzhqs.com/0.0.0.0 -address=/coccccc.cc/0.0.0.0 -address=/codejumps.com/0.0.0.0 -address=/codlw.com/0.0.0.0 -address=/coenr.com/0.0.0.0 -address=/cojia.net/0.0.0.0 -address=/comberry.cn/0.0.0.0 -address=/comesgo.com/0.0.0.0 -address=/continuedsys.cn/0.0.0.0 -address=/coolpadrom.cn/0.0.0.0 -address=/cornplus.cn/0.0.0.0 -address=/couas.com/0.0.0.0 -address=/countersys.cn/0.0.0.0 -address=/coveredsys.cn/0.0.0.0 -address=/cpxkvc.com/0.0.0.0 -address=/cqbaitong.cn/0.0.0.0 -address=/cqgya.com/0.0.0.0 -address=/cqhhct.com/0.0.0.0 -address=/cqlxscdc.top/0.0.0.0 -address=/cqytjzgc.com/0.0.0.0 -address=/crzytm.com/0.0.0.0 -address=/cs12d.com/0.0.0.0 -address=/cshwhy.cn/0.0.0.0 -address=/ctiev.com/0.0.0.0 -address=/cuoas.com/0.0.0.0 -address=/cuoss.com/0.0.0.0 -address=/cwj2h.cn/0.0.0.0 -address=/cwpush.com/0.0.0.0 -address=/cxaerp.com/0.0.0.0 -address=/cxb4.cn/0.0.0.0 -address=/cxcxt.com/0.0.0.0 -address=/cxrjl.cn/0.0.0.0 -address=/cxslchkb.cn/0.0.0.0 -address=/cyboke.cn/0.0.0.0 -address=/cyto-biotherapy.com/0.0.0.0 -address=/cyylove.com/0.0.0.0 -address=/cz345.cn/0.0.0.0 -address=/czhcloud.cn/0.0.0.0 -address=/czlhgz.com/0.0.0.0 -address=/czxjx.cn/0.0.0.0 -address=/czyiming.club/0.0.0.0 -address=/czzdf.com/0.0.0.0 -address=/d08kfa.cn/0.0.0.0 -address=/d5a5a.xyz/0.0.0.0 -address=/d72l4.com/0.0.0.0 -address=/d93nzb.cn/0.0.0.0 -address=/dachadu.cn/0.0.0.0 -address=/dadawm.cc/0.0.0.0 -address=/dailiq.cn/0.0.0.0 -address=/daishuxy.com/0.0.0.0 -address=/daizhankj.cn/0.0.0.0 -address=/dajean.com/0.0.0.0 -address=/dake.net.cn/0.0.0.0 -address=/damiren.com/0.0.0.0 -address=/daokejs.com/0.0.0.0 -address=/dasheducation.cn/0.0.0.0 -address=/daskm.com/0.0.0.0 -address=/dawanjiahn.com/0.0.0.0 -address=/dbaij.com/0.0.0.0 -address=/dbaof.com/0.0.0.0 -address=/dbeii.com/0.0.0.0 -address=/dbeij.com/0.0.0.0 -address=/dbiej.com/0.0.0.0 -address=/dbwmjj.com/0.0.0.0 -address=/dcaij.com/0.0.0.0 -address=/dceni.com/0.0.0.0 -address=/dcuom.com/0.0.0.0 -address=/ddanq.com/0.0.0.0 -address=/ddg1277.com/0.0.0.0 -address=/ddhuangchao.com/0.0.0.0 -address=/ddpxhq.cn/0.0.0.0 -address=/de093o.cn/0.0.0.0 -address=/dengfenzhang.cn/0.0.0.0 -address=/dependablewood.com/0.0.0.0 -address=/deyidesign.com/0.0.0.0 -address=/dezfu.com/0.0.0.0 -address=/dgaoz.com/0.0.0.0 -address=/dglscm.cn/0.0.0.0 -address=/dgxzwj.com/0.0.0.0 -address=/dhaof.com/0.0.0.0 -address=/dhbo4t.cn/0.0.0.0 -address=/dhgdp.cn/0.0.0.0 -address=/dhuhui.cn/0.0.0.0 -address=/dierqingchun.com/0.0.0.0 -address=/dinglixuan.cn/0.0.0.0 -address=/djhbxz.com/0.0.0.0 -address=/djhhy.com/0.0.0.0 -address=/dkdlsj.com/0.0.0.0 -address=/dkmnn.top/0.0.0.0 -address=/dldsrs.com/0.0.0.0 -address=/dlouf.com/0.0.0.0 -address=/dlvnxf.cn/0.0.0.0 -address=/dmouy.cn/0.0.0.0 -address=/dmpsj.cn/0.0.0.0 -address=/dn189.com/0.0.0.0 -address=/dnfeu.com/0.0.0.0 -address=/doowe.cn/0.0.0.0 -address=/doryhome.com/0.0.0.0 -address=/dqgpb.com/0.0.0.0 -address=/drc6i.cn/0.0.0.0 -address=/dreamrecord.cn/0.0.0.0 -address=/drevozone.com.cn/0.0.0.0 -address=/drgykb.cn/0.0.0.0 -address=/dscry.com/0.0.0.0 -address=/dsjcfw.com/0.0.0.0 -address=/dsjre.com/0.0.0.0 -address=/dsjyjj.cn/0.0.0.0 -address=/dssdr.top/0.0.0.0 -address=/dtzysm.com/0.0.0.0 -address=/duoyidd.com/0.0.0.0 -address=/dxcssc.cn/0.0.0.0 -address=/dxmci.com/0.0.0.0 -address=/dydyhg.com/0.0.0.0 -address=/dyfzyg.com/0.0.0.0 -address=/dzisou.com/0.0.0.0 -address=/dzrenju2.cn/0.0.0.0 -address=/e647ob.cn/0.0.0.0 -address=/e9emh.cn/0.0.0.0 -address=/ecuwa.cn/0.0.0.0 -address=/ediun.com/0.0.0.0 -address=/edumsys.com/0.0.0.0 -address=/edysn.cn/0.0.0.0 -address=/egqiyw.com/0.0.0.0 -address=/ehxyz.com/0.0.0.0 -address=/ei4f.cn/0.0.0.0 -address=/ejeenews.com/0.0.0.0 -address=/ejiur.com/0.0.0.0 -address=/ejwmc.cn/0.0.0.0 -address=/eloer.cn/0.0.0.0 -address=/elvx.top/0.0.0.0 -address=/emgwq.com/0.0.0.0 -address=/emshx.cn/0.0.0.0 -address=/enjuk.com/0.0.0.0 -address=/enjuw.com/0.0.0.0 -address=/eou01a.cn/0.0.0.0 -address=/epanr.com/0.0.0.0 -address=/eqiuy.com/0.0.0.0 -address=/erocw.com/0.0.0.0 -address=/eshuy.com/0.0.0.0 -address=/esuzm.cn/0.0.0.0 -address=/esyzdb.com/0.0.0.0 -address=/ew740.cn/0.0.0.0 -address=/ewphm.cn/0.0.0.0 -address=/exusr.com/0.0.0.0 -address=/eyaor.com/0.0.0.0 -address=/eysmaa.pw/0.0.0.0 -address=/ezfashion.com.cn/0.0.0.0 -address=/ezuon.com/0.0.0.0 -address=/fangdalaw.gd.cn/0.0.0.0 -address=/fangjslc.com/0.0.0.0 -address=/fanglinwang.cn/0.0.0.0 -address=/fangzhanla.cn/0.0.0.0 -address=/fangzi2.top/0.0.0.0 -address=/fanzhuang.net.cn/0.0.0.0 -address=/fbaot.com/0.0.0.0 -address=/fbieq.com/0.0.0.0 -address=/fcaot.com/0.0.0.0 -address=/fccay.cn/0.0.0.0 -address=/fchio.com/0.0.0.0 -address=/fcrdb.com/0.0.0.0 -address=/fcuit.com/0.0.0.0 -address=/fcunq.com/0.0.0.0 -address=/fdaoo.com/0.0.0.0 -address=/fdoun.com/0.0.0.0 -address=/feifish66.com/0.0.0.0 -address=/feipaihehuoren.cn/0.0.0.0 -address=/fenbengpan.cn/0.0.0.0 -address=/ffanq.com/0.0.0.0 -address=/ffychb.com/0.0.0.0 -address=/fgaon.com/0.0.0.0 -address=/fgzba.com/0.0.0.0 -address=/fhbv.cn/0.0.0.0 -address=/fipipo.cn/0.0.0.0 -address=/fj95560.com/0.0.0.0 -address=/fjhanmei.com/0.0.0.0 -address=/fjmrxys.com/0.0.0.0 -address=/fjshxzyyxgs.cn/0.0.0.0 -address=/fjtzjy.com/0.0.0.0 -address=/fjxyo.com/0.0.0.0 -address=/fkikij.cn/0.0.0.0 -address=/fkkse.com/0.0.0.0 -address=/fkogs.com/0.0.0.0 -address=/fninin.cn/0.0.0.0 -address=/fnxmyx.cn/0.0.0.0 -address=/focuscat.com/0.0.0.0 -address=/foshou.pw/0.0.0.0 -address=/fouas.com/0.0.0.0 -address=/foumm.com/0.0.0.0 -address=/fowpq.top/0.0.0.0 -address=/fqzds.com/0.0.0.0 -address=/friend17.net/0.0.0.0 -address=/frjxdv.cn/0.0.0.0 -address=/fshet.com/0.0.0.0 -address=/fstaw.com/0.0.0.0 -address=/fszhxd.com/0.0.0.0 -address=/ftrp4.cn/0.0.0.0 -address=/fuhuikang360.com/0.0.0.0 -address=/futengbao.com.cn/0.0.0.0 -address=/fuwosi.cn/0.0.0.0 -address=/fuxin-tech.com/0.0.0.0 -address=/fw.zhuaji.org/0.0.0.0 -address=/fwjoi.com/0.0.0.0 -address=/fwyang.com/0.0.0.0 -address=/fx6j3.cn/0.0.0.0 -address=/fxfhjs.com/0.0.0.0 -address=/fxunn.com/0.0.0.0 -address=/fy4zb.cn/0.0.0.0 -address=/fyehare.com/0.0.0.0 -address=/fyjyhm.com/0.0.0.0 -address=/fzdfwy.com/0.0.0.0 -address=/fzxrjx.com/0.0.0.0 -address=/fzyda.com/0.0.0.0 -address=/g3ao2q.cn/0.0.0.0 -address=/g4rre.xyz/0.0.0.0 -address=/gadhx.cn/0.0.0.0 -address=/gadwhy.com/0.0.0.0 -address=/gagkf.top/0.0.0.0 -address=/gaihunuo.cn/0.0.0.0 -address=/galaxyns.com/0.0.0.0 -address=/gameriew.com/0.0.0.0 -address=/ganggao123456.com/0.0.0.0 -address=/gaochaolian.cn/0.0.0.0 -address=/gaohuduo.cn/0.0.0.0 -address=/gaykes.com/0.0.0.0 -address=/gazoeft.cn/0.0.0.0 -address=/gb686.cn/0.0.0.0 -address=/gbeik.com/0.0.0.0 -address=/gbieg.com/0.0.0.0 -address=/gc8fjz.cn/0.0.0.0 -address=/gcaij.com/0.0.0.0 -address=/gcaog.com/0.0.0.0 -address=/gcfx777.com/0.0.0.0 -address=/gcheg.com/0.0.0.0 -address=/gcouh.com/0.0.0.0 -address=/gdaii.com/0.0.0.0 -address=/gdeih.com/0.0.0.0 -address=/gdfc0563.com/0.0.0.0 -address=/gdhdfs.com/0.0.0.0 -address=/gdlbdzkj.com/0.0.0.0 -address=/gdlvbiaokeji.cn/0.0.0.0 -address=/gdsqwy.org/0.0.0.0 -address=/gdunt.com/0.0.0.0 -address=/gedus.cn/0.0.0.0 -address=/gelinboer.cn/0.0.0.0 -address=/georgias.cn/0.0.0.0 -address=/gerunsenbo.cn/0.0.0.0 -address=/gghh486.cn/0.0.0.0 -address=/gghh493.cn/0.0.0.0 -address=/ggouh.com/0.0.0.0 -address=/ggz55268.com/0.0.0.0 -address=/giroud.top/0.0.0.0 -address=/gj632.cn/0.0.0.0 -address=/gjiai.com/0.0.0.0 -address=/gjiak.com/0.0.0.0 -address=/gjkpo.com/0.0.0.0 -address=/gjuet.com/0.0.0.0 -address=/gk277.cn/0.0.0.0 -address=/gky73.cn/0.0.0.0 -address=/globbiz.cn/0.0.0.0 -address=/glpen08.com/0.0.0.0 -address=/glvej.com/0.0.0.0 -address=/gmxyorg.cn/0.0.0.0 -address=/gnmbd.top/0.0.0.0 -address=/gobali.cn/0.0.0.0 -address=/gongfanglong.cn/0.0.0.0 -address=/googlespider1.cn/0.0.0.0 -address=/gou1zhe.com/0.0.0.0 -address=/goulanmeng.cn/0.0.0.0 -address=/gringrin.cn/0.0.0.0 -address=/grjs02.com/0.0.0.0 -address=/gtaih.com/0.0.0.0 -address=/gtchong.com/0.0.0.0 -address=/gtifund.cn/0.0.0.0 -address=/gtiou.com/0.0.0.0 -address=/gtnde.com/0.0.0.0 -address=/guaas.com/0.0.0.0 -address=/guangsss1999.com/0.0.0.0 -address=/guannin.com/0.0.0.0 -address=/guanqinjie.cn/0.0.0.0 -address=/guansenff.cn/0.0.0.0 -address=/guanzistory.com/0.0.0.0 -address=/guxiaom.cn/0.0.0.0 -address=/gwdqp.com/0.0.0.0 -address=/gxklsftz.cn/0.0.0.0 -address=/gxkyl.com/0.0.0.0 -address=/gxssjz.com/0.0.0.0 -address=/gxunj.com/0.0.0.0 -address=/gybdtg.com/0.0.0.0 -address=/gyeet.com/0.0.0.0 -address=/gyhzr.com/0.0.0.0 -address=/gyrtg.com/0.0.0.0 -address=/gyt168.com.cn/0.0.0.0 -address=/gz-bz.cn/0.0.0.0 -address=/gzjingm.cn/0.0.0.0 -address=/gzmxybg.com/0.0.0.0 -address=/gzmzts.com/0.0.0.0 -address=/gznsyh.com/0.0.0.0 -address=/gzrljx.cn/0.0.0.0 -address=/gzzena.com/0.0.0.0 -address=/h2pzh.cn/0.0.0.0 -address=/h5e6d5.xyz/0.0.0.0 -address=/hainufamliy.top/0.0.0.0 -address=/hajuwang.cn/0.0.0.0 -address=/hanmiyong.com/0.0.0.0 -address=/haoxianyangrouye.com/0.0.0.0 -address=/haoxinq.top/0.0.0.0 -address=/hawbfa.com/0.0.0.0 -address=/hbaog.com/0.0.0.0 -address=/hbbww.com/0.0.0.0 -address=/hbhxqcw.com/0.0.0.0 -address=/hblanghun.cn/0.0.0.0 -address=/hbnygj.com/0.0.0.0 -address=/hbttcc.com/0.0.0.0 -address=/hbyyzm.com/0.0.0.0 -address=/hc29x.cn/0.0.0.0 -address=/hcaig.com/0.0.0.0 -address=/hcenc.com/0.0.0.0 -address=/hchig.com/0.0.0.0 -address=/hchik.com/0.0.0.0 -address=/hdfdm.com/0.0.0.0 -address=/hdminfeng.com/0.0.0.0 -address=/hdswgc.com/0.0.0.0 -address=/hduic.com/0.0.0.0 -address=/headwell.cn/0.0.0.0 -address=/heavenwil.top/0.0.0.0 -address=/hebhec.cn/0.0.0.0 -address=/hebzycw.com/0.0.0.0 -address=/hehmy.cn/0.0.0.0 -address=/hehongmei.top/0.0.0.0 -address=/heib2.top/0.0.0.0 -address=/heizundg.cn/0.0.0.0 -address=/hellogalaxy.cn/0.0.0.0 -address=/helpinfo.cn/0.0.0.0 -address=/henanlinyu.cn/0.0.0.0 -address=/henduoqian.com/0.0.0.0 -address=/heylookhere.top/0.0.0.0 -address=/hfyxdl.com/0.0.0.0 -address=/hgdanbas.cn/0.0.0.0 -address=/hgrqp.com/0.0.0.0 -address=/hguac.com/0.0.0.0 -address=/hguas.com/0.0.0.0 -address=/hhslbz.cn/0.0.0.0 -address=/hiffyl.com/0.0.0.0 -address=/higoo4.com/0.0.0.0 -address=/hihifenxiang.com/0.0.0.0 -address=/hihufu.cn/0.0.0.0 -address=/hissq.com/0.0.0.0 -address=/hixili.top/0.0.0.0 -address=/hjiec.com/0.0.0.0 -address=/hjjnpx.com/0.0.0.0 -address=/hjkrlc.cn/0.0.0.0 -address=/hjryl.com/0.0.0.0 -address=/hjues.com/0.0.0.0 -address=/hjyll.top/0.0.0.0 -address=/hjzndq.com/0.0.0.0 -address=/hk7799.net/0.0.0.0 -address=/hk9600.com/0.0.0.0 -address=/hkdyys.cn/0.0.0.0 -address=/hkmqp.com/0.0.0.0 -address=/hldwmly.com/0.0.0.0 -address=/hlhulu.com/0.0.0.0 -address=/hljhufengling.cn/0.0.0.0 -address=/hmhqp.com/0.0.0.0 -address=/hmttoly.com/0.0.0.0 -address=/hmyangshengji.com/0.0.0.0 -address=/hnfxty.cn/0.0.0.0 -address=/hnhgw.cn/0.0.0.0 -address=/hnkuangshan.cn/0.0.0.0 -address=/hnwjlhg.cn/0.0.0.0 -address=/hnzyfs.com/0.0.0.0 -address=/hogyp.com/0.0.0.0 -address=/hondajd.cn/0.0.0.0 -address=/hongshikai.com/0.0.0.0 -address=/hongyangbg.com/0.0.0.0 -address=/how5.cn/0.0.0.0 -address=/hp-china.biz/0.0.0.0 -address=/hpzyl.com/0.0.0.0 -address=/hqgjcm.com/0.0.0.0 -address=/hqsjc.com/0.0.0.0 -address=/hs1s1.cn/0.0.0.0 -address=/hsbkr.com/0.0.0.0 -address=/htfmbt.com/0.0.0.0 -address=/htjsk.com/0.0.0.0 -address=/huayange.com/0.0.0.0 -address=/huayi65.com/0.0.0.0 -address=/huician.cn/0.0.0.0 -address=/huigoushop.com/0.0.0.0 -address=/huixingcheng.cn/0.0.0.0 -address=/hunpp.com/0.0.0.0 -address=/huoyiad1.cn/0.0.0.0 -address=/huzhanbin.cn/0.0.0.0 -address=/hwertd.xyz/0.0.0.0 -address=/hxiak.com/0.0.0.0 -address=/hycfxdc.com/0.0.0.0 -address=/hyjyjc.com/0.0.0.0 -address=/hypzv.com/0.0.0.0 -address=/hytcsh.cn/0.0.0.0 -address=/hyxca.top/0.0.0.0 -address=/hzht666.com/0.0.0.0 -address=/hzuok.com/0.0.0.0 -address=/hzuvw.com/0.0.0.0 -address=/hzxfmc.com/0.0.0.0 -address=/hzzfan.com/0.0.0.0 -address=/i-components.net/0.0.0.0 -address=/i05h.cn/0.0.0.0 -address=/i36mf.cn/0.0.0.0 -address=/ia22.com/0.0.0.0 -address=/iamqqo85467.cn/0.0.0.0 -address=/iangp.com/0.0.0.0 -address=/iangs.com/0.0.0.0 -address=/iauqwe.com/0.0.0.0 -address=/iavfta8090.com/0.0.0.0 -address=/ibaop.com/0.0.0.0 -address=/ibeiling.cn/0.0.0.0 -address=/ibeip.com/0.0.0.0 -address=/ibinp.com/0.0.0.0 -address=/icebeatuy.com/0.0.0.0 -address=/icyrd.com/0.0.0.0 -address=/idanmei.cn/0.0.0.0 -address=/identified.cn/0.0.0.0 -address=/ienkdaccessible.cn/0.0.0.0 -address=/ienkdago.cn/0.0.0.0 -address=/ieqmeq.com/0.0.0.0 -address=/ifeib.com/0.0.0.0 -address=/ihais.com/0.0.0.0 -address=/ihear123.com/0.0.0.0 -address=/ihhii.xyz/0.0.0.0 -address=/iigushi.com/0.0.0.0 -address=/ijieo.com/0.0.0.0 -address=/ijo5g.cn/0.0.0.0 -address=/ijuns.com/0.0.0.0 -address=/ijuny.com/0.0.0.0 -address=/imanchu.cn/0.0.0.0 -address=/imiek.com/0.0.0.0 -address=/imykgs.com/0.0.0.0 -address=/inccnd.com/0.0.0.0 -address=/increased.cn/0.0.0.0 -address=/infvb.com/0.0.0.0 -address=/internerl.com/0.0.0.0 -address=/intxt.cn/0.0.0.0 -address=/iq24ne.cn/0.0.0.0 -address=/iqiyi.space/0.0.0.0 -address=/irauz.com/0.0.0.0 -address=/irkuj.com/0.0.0.0 -address=/iruad.com/0.0.0.0 -address=/isgow.com/0.0.0.0 -address=/ishowms.com/0.0.0.0 -address=/itcoder.top/0.0.0.0 -address=/iyaos.com/0.0.0.0 -address=/iyouhu.cn/0.0.0.0 -address=/iyuey.com/0.0.0.0 -address=/izouo.com/0.0.0.0 -address=/izuis.com/0.0.0.0 -address=/j200d3.cn/0.0.0.0 -address=/j6y54.xyz/0.0.0.0 -address=/j6yh5.xyz/0.0.0.0 -address=/jaat3ax.site/0.0.0.0 -address=/jajattt.com/0.0.0.0 -address=/jbanb.com/0.0.0.0 -address=/jbbath.cn/0.0.0.0 -address=/jcaik.com/0.0.0.0 -address=/jcaip.com/0.0.0.0 -address=/jcboloni.cn/0.0.0.0 -address=/jcdb88.com/0.0.0.0 -address=/jcwwxn.com/0.0.0.0 -address=/jdaot.com/0.0.0.0 -address=/jdf494.cn/0.0.0.0 -address=/jdflower.cn/0.0.0.0 -address=/jdgsgl.com/0.0.0.0 -address=/jduiv.com/0.0.0.0 -address=/jdzlxtc.com/0.0.0.0 -address=/jgkto.com/0.0.0.0 -address=/jh99s.cn/0.0.0.0 -address=/jhbrc.xyz/0.0.0.0 -address=/jhf2e.cn/0.0.0.0 -address=/jia-huan.cn/0.0.0.0 -address=/jiangchunli.cn/0.0.0.0 -address=/jiaofulin.cn/0.0.0.0 -address=/jiaqingli.cn/0.0.0.0 -address=/jieyixiu.com/0.0.0.0 -address=/jifeidandar.com/0.0.0.0 -address=/jiguangyi.com.cn/0.0.0.0 -address=/jiirz.com/0.0.0.0 -address=/jim86d.cn/0.0.0.0 -address=/jinchaoyu.com/0.0.0.0 -address=/jingdayiyuan.com/0.0.0.0 -address=/jingoulong.cn/0.0.0.0 -address=/jingxiangyalvji.cn/0.0.0.0 -address=/jioeg.com/0.0.0.0 -address=/jiumishow.com/0.0.0.0 -address=/jixiby.cn/0.0.0.0 -address=/jiyuanzixun.com/0.0.0.0 -address=/jkert.com/0.0.0.0 -address=/jlkja.com/0.0.0.0 -address=/jlvskg.cn/0.0.0.0 -address=/jlxzt.com/0.0.0.0 -address=/jmxlaser.com/0.0.0.0 -address=/jndczg.com/0.0.0.0 -address=/jnsdkjzs.com/0.0.0.0 -address=/jollyspring.com/0.0.0.0 -address=/jotrening.com/0.0.0.0 -address=/jpenk.com/0.0.0.0 -address=/jpg1.oss-cn-beijing.aliyuncs.com/0.0.0.0 -address=/jrdkc.com/0.0.0.0 -address=/jsaik.com/0.0.0.0 -address=/jskang.cn/0.0.0.0 -address=/jssumei.cn/0.0.0.0 -address=/jstdjq.com/0.0.0.0 -address=/jsth999.com/0.0.0.0 -address=/jsyjwj.com/0.0.0.0 -address=/jullycn.com/0.0.0.0 -address=/jundazulin.com/0.0.0.0 -address=/just9229.cn/0.0.0.0 -address=/justincao84.cn/0.0.0.0 -address=/juyzr.com/0.0.0.0 -address=/jwhfn.cn/0.0.0.0 -address=/jwiyr.com/0.0.0.0 -address=/jxhcyc.com/0.0.0.0 -address=/jxinyue.top/0.0.0.0 -address=/jxnrfx.com/0.0.0.0 -address=/jxxcfd.com/0.0.0.0 -address=/jxyufa.com/0.0.0.0 -address=/jyhwt.cn/0.0.0.0 -address=/jyjhkz.com/0.0.0.0 -address=/jzntxs.com/0.0.0.0 -address=/k2n0f.cn/0.0.0.0 -address=/k5ai3c.cn/0.0.0.0 -address=/k7tju.xyz/0.0.0.0 -address=/k859n.cn/0.0.0.0 -address=/k9wi2d.cn/0.0.0.0 -address=/kafka8.com/0.0.0.0 -address=/kaihutai.cn/0.0.0.0 -address=/kakappp.com/0.0.0.0 -address=/kanghuaixin.cn/0.0.0.0 -address=/kanjiaqun.cn/0.0.0.0 -address=/kbstyn.com/0.0.0.0 -address=/kcenu.com/0.0.0.0 -address=/kchaq.com/0.0.0.0 -address=/kcooy.com/0.0.0.0 -address=/kdieu.com/0.0.0.0 -address=/kdzbg.xyz/0.0.0.0 -address=/ketaoke.com/0.0.0.0 -address=/kexigia.com/0.0.0.0 -address=/kfand.com/0.0.0.0 -address=/kfeiu.com/0.0.0.0 -address=/kfuih.cn/0.0.0.0 -address=/kg962.cn/0.0.0.0 -address=/kguaq.com/0.0.0.0 -address=/khuoy.com/0.0.0.0 -address=/kjdw.com.cn/0.0.0.0 -address=/kjfhe.com/0.0.0.0 -address=/kjhfy.com/0.0.0.0 -address=/kl6636.net/0.0.0.0 -address=/klgzzs.cn/0.0.0.0 -address=/klsadm.com/0.0.0.0 -address=/kltent.cn/0.0.0.0 -address=/kmfnkj.com/0.0.0.0 -address=/kofcq5.cn/0.0.0.0 -address=/kongssew.com/0.0.0.0 -address=/koudaichaoshi.cn/0.0.0.0 -address=/kqiaq.com/0.0.0.0 -address=/ks67.com/0.0.0.0 -address=/ksdsuzhou.com/0.0.0.0 -address=/kshks5.site/0.0.0.0 -address=/ksylsh.cn/0.0.0.0 -address=/kteyz.com/0.0.0.0 -address=/ktzte.cn/0.0.0.0 -address=/kuaipaobiaoju.com/0.0.0.0 -address=/kuaituisss.com/0.0.0.0 -address=/kueofwt.cn/0.0.0.0 -address=/kuptmf.cn/0.0.0.0 -address=/kwjkd.com/0.0.0.0 -address=/kwp79i.cn/0.0.0.0 -address=/kxhie.com/0.0.0.0 -address=/kyxnz.cn/0.0.0.0 -address=/kz8tr2.cn/0.0.0.0 -address=/l30od.cn/0.0.0.0 -address=/l4elb.cn/0.0.0.0 -address=/l7g4e.cn/0.0.0.0 -address=/l93stb.cn/0.0.0.0 -address=/l9c4s.cn/0.0.0.0 -address=/la71f.cn/0.0.0.0 -address=/laiye315.top/0.0.0.0 -address=/laksdn.com/0.0.0.0 -address=/lanhouhou.cn/0.0.0.0 -address=/laojiayoufang.com/0.0.0.0 -address=/lawumi.cn/0.0.0.0 -address=/layyi.com/0.0.0.0 -address=/lbaij.com/0.0.0.0 -address=/lbaoj.com/0.0.0.0 -address=/lchar.com/0.0.0.0 -address=/lcrmm.top/0.0.0.0 -address=/legozu.com/0.0.0.0 -address=/lerenzx.cn/0.0.0.0 -address=/lesanmo.top/0.0.0.0 -address=/let83.cn/0.0.0.0 -address=/lfdydk.com/0.0.0.0 -address=/lfouz.com/0.0.0.0 -address=/lfzxcp.com/0.0.0.0 -address=/lgjygg.com/0.0.0.0 -address=/lglady.cn/0.0.0.0 -address=/lglkqm.cn/0.0.0.0 -address=/lguir.com/0.0.0.0 -address=/lhcyii.cn/0.0.0.0 -address=/lhhxlj.com/0.0.0.0 -address=/lianfuhuang.cn/0.0.0.0 -address=/lianyicq.cn/0.0.0.0 -address=/liaoruochen.cn/0.0.0.0 -address=/liaotian4.com/0.0.0.0 -address=/lifuzhubao.com/0.0.0.0 -address=/lihongdou.cn/0.0.0.0 -address=/lijie1010.top/0.0.0.0 -address=/linghangshouji.com/0.0.0.0 -address=/linwukui.cn/0.0.0.0 -address=/linyankm.cn/0.0.0.0 -address=/listenother.com/0.0.0.0 -address=/liufang1994.top/0.0.0.0 -address=/liujiaqi.top/0.0.0.0 -address=/lixianze.top/0.0.0.0 -address=/liyelaowu.cn/0.0.0.0 -address=/ljuer.com/0.0.0.0 -address=/lletd.cn/0.0.0.0 -address=/llvez.com/0.0.0.0 -address=/lnenz.com/0.0.0.0 -address=/lolvsdota.cn/0.0.0.0 -address=/longkoupeanut.cn/0.0.0.0 -address=/louisan.cn/0.0.0.0 -address=/lousivency.com.cn/0.0.0.0 -address=/lpaoz.com/0.0.0.0 -address=/lr96.top/0.0.0.0 -address=/lsiwd.cn/0.0.0.0 -address=/lusrg.cn/0.0.0.0 -address=/luxoshopde.com/0.0.0.0 -address=/luyouxi.cn/0.0.0.0 -address=/lvyishengtai.com/0.0.0.0 -address=/lwhsdfc.cn/0.0.0.0 -address=/lxind.cn/0.0.0.0 -address=/ly5200.cn/0.0.0.0 -address=/lybczlsb.com/0.0.0.0 -address=/lychangxu.cn/0.0.0.0 -address=/lyczhb.com/0.0.0.0 -address=/lyjz001.com/0.0.0.0 -address=/lyshengtu.cn/0.0.0.0 -address=/lzida.com/0.0.0.0 -address=/lzjycy.com/0.0.0.0 -address=/lzkjsj.com/0.0.0.0 -address=/lzytt.com/0.0.0.0 -address=/m19ud.cn/0.0.0.0 -address=/m216j.cn/0.0.0.0 -address=/m4ztka.cn/0.0.0.0 -address=/m652a.cn/0.0.0.0 -address=/m72r.cn/0.0.0.0 -address=/mammina.cn/0.0.0.0 -address=/mao1.jsnovel.com/0.0.0.0 -address=/maoyumao.net/0.0.0.0 -address=/matchjia.cn/0.0.0.0 -address=/maxoi.cn/0.0.0.0 -address=/mbaik.com/0.0.0.0 -address=/mbiek.com/0.0.0.0 -address=/mbusdw.cn/0.0.0.0 -address=/mcaik.com/0.0.0.0 -address=/md0z4dh.com/0.0.0.0 -address=/mdous.com/0.0.0.0 -address=/mdsfzh.cn/0.0.0.0 -address=/medprofile.cn/0.0.0.0 -address=/meizhuli365.cn/0.0.0.0 -address=/mendoc.cn/0.0.0.0 -address=/mengpr.com/0.0.0.0 -address=/meooe.com/0.0.0.0 -address=/mgldzcls.com/0.0.0.0 -address=/mgsue.cn/0.0.0.0 -address=/mhuos.com/0.0.0.0 -address=/miaiche.cn/0.0.0.0 -address=/miaos11.com/0.0.0.0 -address=/micreative-china.cn/0.0.0.0 -address=/mid5in.top/0.0.0.0 -address=/miiuv.com/0.0.0.0 -address=/mindrook.com/0.0.0.0 -address=/mingbangzichan.com/0.0.0.0 -address=/mjita.cn/0.0.0.0 -address=/ml44.cn/0.0.0.0 -address=/mlion.cn/0.0.0.0 -address=/mmfusheng.com/0.0.0.0 -address=/mmhhjt.com/0.0.0.0 -address=/mmkvi.com/0.0.0.0 -address=/mmpuh.cn/0.0.0.0 -address=/mmwdwg.cn/0.0.0.0 -address=/mnptinibfbv.com/0.0.0.0 -address=/mobiorg8.com/0.0.0.0 -address=/morningpiggy.com/0.0.0.0 -address=/moshangflower.cn/0.0.0.0 -address=/mouaa.com/0.0.0.0 -address=/movii-loft.cn/0.0.0.0 -address=/moxiaoyang.top/0.0.0.0 -address=/mqcwr.cn/0.0.0.0 -address=/mqgpo.com/0.0.0.0 -address=/mqies.com/0.0.0.0 -address=/mreod.cn/0.0.0.0 -address=/msdfd.cn/0.0.0.0 -address=/msuik.cn/0.0.0.0 -address=/mtcat.cn/0.0.0.0 -address=/mubite.cn/0.0.0.0 -address=/mujiangdashi.cn/0.0.0.0 -address=/mukkkoi.cn/0.0.0.0 -address=/mukqeq.cn/0.0.0.0 -address=/muqsad.xyz/0.0.0.0 -address=/muusn.cn/0.0.0.0 -address=/mwjpk.com/0.0.0.0 -address=/mx.biquge.info/0.0.0.0 -address=/mxtailor.com/0.0.0.0 -address=/mysty.com.cn/0.0.0.0 -address=/myuf6.xyz/0.0.0.0 -address=/myycrw.com/0.0.0.0 -address=/mzclass.club/0.0.0.0 -address=/n0h8g.cn/0.0.0.0 -address=/nabeghlavi.com.cn/0.0.0.0 -address=/nanyangqiaoxiang.cn/0.0.0.0 -address=/nashlin.top/0.0.0.0 -address=/nbaob.com/0.0.0.0 -address=/nbhotpo.com/0.0.0.0 -address=/ncoyqc.com/0.0.0.0 -address=/nd59w.cn/0.0.0.0 -address=/nduop.com/0.0.0.0 -address=/ndusa.cn/0.0.0.0 -address=/neijh.com/0.0.0.0 -address=/nernv.com/0.0.0.0 -address=/netko0o.com/0.0.0.0 -address=/newknowledge.cn/0.0.0.0 -address=/nfkos.com/0.0.0.0 -address=/ngceq.cn/0.0.0.0 -address=/ngsaang.top/0.0.0.0 -address=/nickarini.com/0.0.0.0 -address=/niegg.com/0.0.0.0 -address=/nihao987654.top/0.0.0.0 -address=/ningbojipiao.com/0.0.0.0 -address=/ningxiayy.com/0.0.0.0 -address=/nixiclothing.com/0.0.0.0 -address=/njguluyu.cn/0.0.0.0 -address=/njhuashidai.cn/0.0.0.0 -address=/njjmp.com/0.0.0.0 -address=/njxczy.com/0.0.0.0 -address=/njyyk.com/0.0.0.0 -address=/nk295.cn/0.0.0.0 -address=/nkwwbg.com/0.0.0.0 -address=/nkyyls.cn/0.0.0.0 -address=/nmmdzq.cn/0.0.0.0 -address=/nmqdnykj.com/0.0.0.0 -address=/nmtouzi.com/0.0.0.0 -address=/nnfiy.com/0.0.0.0 -address=/nongshengyi.cn/0.0.0.0 -address=/nq37f.cn/0.0.0.0 -address=/nqfwx.cn/0.0.0.0 -address=/nsjpu.com/0.0.0.0 -address=/nsxtob.cn/0.0.0.0 -address=/nthfds.xyz/0.0.0.0 -address=/ntpddq.com/0.0.0.0 -address=/nv43.com/0.0.0.0 -address=/nwwap.com/0.0.0.0 -address=/nwxzs.com/0.0.0.0 -address=/nxh2h.cn/0.0.0.0 -address=/nxkycx.com/0.0.0.0 -address=/nxwly.com/0.0.0.0 -address=/nxypz.com/0.0.0.0 -address=/nydjsm.cn/0.0.0.0 -address=/nyhnx.com/0.0.0.0 -address=/nykps.com/0.0.0.0 -address=/nyyxyx.com.cn/0.0.0.0 -address=/oangm.com/0.0.0.0 -address=/obeip.com/0.0.0.0 -address=/obj9.cn/0.0.0.0 -address=/octopuszyw.cn/0.0.0.0 -address=/oende.cn/0.0.0.0 -address=/oeocriaq.cn/0.0.0.0 -address=/oesnw.com/0.0.0.0 -address=/ohuam.com/0.0.0.0 -address=/oir85.cn/0.0.0.0 -address=/ojues.com/0.0.0.0 -address=/okshishi.com/0.0.0.0 -address=/okuis.com/0.0.0.0 -address=/okwan.cn/0.0.0.0 -address=/okx6.site/0.0.0.0 -address=/olc0.cn/0.0.0.0 -address=/on68xf.cn/0.0.0.0 -address=/once88.cn/0.0.0.0 -address=/onlyshow.top/0.0.0.0 -address=/oomyv.com/0.0.0.0 -address=/opengam.com/0.0.0.0 -address=/opqsr.com/0.0.0.0 -address=/orlandomp.com/0.0.0.0 -address=/osaws.com/0.0.0.0 -address=/osidf.xyz/0.0.0.0 -address=/osimym.com/0.0.0.0 -address=/osndy.com/0.0.0.0 -address=/osvp2.cn/0.0.0.0 -address=/ou15r.cn/0.0.0.0 -address=/oul78c.cn/0.0.0.0 -address=/oulvtrip.com/0.0.0.0 -address=/panwenjun.top/0.0.0.0 -address=/paochala.net/0.0.0.0 -address=/passwz.com/0.0.0.0 -address=/pbino.com/0.0.0.0 -address=/pcaoo.com/0.0.0.0 -address=/pd3a.cn/0.0.0.0 -address=/pdfbs.com/0.0.0.0 -address=/pdkuai.com/0.0.0.0 -address=/petsfairy.com/0.0.0.0 -address=/petsheying.com/0.0.0.0 -address=/phpape.com/0.0.0.0 -address=/pi920.com/0.0.0.0 -address=/pianyi95.top/0.0.0.0 -address=/piaogj.com/0.0.0.0 -address=/picbr.com/0.0.0.0 -address=/pieaa.com/0.0.0.0 -address=/piliangzhuce.cn/0.0.0.0 -address=/pincidao.cn/0.0.0.0 -address=/pinkmore.cn/0.0.0.0 -address=/pipysoft.cn/0.0.0.0 -address=/pitena.top/0.0.0.0 -address=/pjbjzf.com/0.0.0.0 -address=/pjxna.xyz/0.0.0.0 -address=/pkbook.com.cn/0.0.0.0 -address=/pkbrxja.cn/0.0.0.0 -address=/pkesports.cn/0.0.0.0 -address=/plerv.com/0.0.0.0 -address=/plokr.com/0.0.0.0 -address=/pmshy.cn/0.0.0.0 -address=/pochengweiyuan.com/0.0.0.0 -address=/pomhz.com/0.0.0.0 -address=/pomkl.com/0.0.0.0 -address=/pos68.cn/0.0.0.0 -address=/pougg.com/0.0.0.0 -address=/pptte.com/0.0.0.0 -address=/pqnlorg.cn/0.0.0.0 -address=/pqwtrq.xyz/0.0.0.0 -address=/prazpf.cn/0.0.0.0 -address=/psgch.xyz/0.0.0.0 -address=/pstarv.cn/0.0.0.0 -address=/ptgezc.com/0.0.0.0 -address=/ptummn.cn/0.0.0.0 -address=/ptuoa.com/0.0.0.0 -address=/puzwb.cn/0.0.0.0 -address=/pwjhg.com/0.0.0.0 -address=/px69z.cn/0.0.0.0 -address=/pxyvb.cn/0.0.0.0 -address=/pyerc.com/0.0.0.0 -address=/pyhuiyu.com/0.0.0.0 -address=/pzhygu.cn/0.0.0.0 -address=/pzuth.cn/0.0.0.0 -address=/pzvlnh.cn/0.0.0.0 -address=/q0uz4c.cn/0.0.0.0 -address=/q671e.cn/0.0.0.0 -address=/q7ms.cn/0.0.0.0 -address=/qaqact.cn/0.0.0.0 -address=/qcgkd322.vip/0.0.0.0 -address=/qd836.cn/0.0.0.0 -address=/qdiut.com/0.0.0.0 -address=/qdyazc.com/0.0.0.0 -address=/qflwh.cn/0.0.0.0 -address=/qgana.com/0.0.0.0 -address=/qgaot.com/0.0.0.0 -address=/qhdmqzc.cn/0.0.0.0 -address=/qhdop.com/0.0.0.0 -address=/qhuik.com/0.0.0.0 -address=/qhxcdmfj.cn/0.0.0.0 -address=/qi-shi.top/0.0.0.0 -address=/qiaopiguniang.com/0.0.0.0 -address=/qilungroup.cn/0.0.0.0 -address=/qinchugudao.com/0.0.0.0 -address=/qingzhencai.net/0.0.0.0 -address=/qiruidea.com/0.0.0.0 -address=/qjueu.com/0.0.0.0 -address=/qkptx.com/0.0.0.0 -address=/qlaot.com/0.0.0.0 -address=/qldua.cn/0.0.0.0 -address=/qloer.com/0.0.0.0 -address=/qlonglong.com/0.0.0.0 -address=/qneit.com/0.0.0.0 -address=/qq0au.cn/0.0.0.0 -address=/qqdashabi.top/0.0.0.0 -address=/qqiat.com/0.0.0.0 -address=/qrdqbe.cn/0.0.0.0 -address=/qsove.com/0.0.0.0 -address=/qtpngov.cn/0.0.0.0 -address=/quanjiapp.cn/0.0.0.0 -address=/quldu.com/0.0.0.0 -address=/quyejianzhan.tech/0.0.0.0 -address=/qxyu.top/0.0.0.0 -address=/qyttl.cn/0.0.0.0 -address=/qzbxfs.com/0.0.0.0 -address=/qzdag.com/0.0.0.0 -address=/qzdaren.com/0.0.0.0 -address=/qzyiming.cn/0.0.0.0 -address=/raeqqe.cn/0.0.0.0 -address=/rbign.cn/0.0.0.0 -address=/rbywg.com/0.0.0.0 -address=/rcaiu.com/0.0.0.0 -address=/rcynoe.cn/0.0.0.0 -address=/rdtylx.cn/0.0.0.0 -address=/rdxhrd.com/0.0.0.0 -address=/relaxspace.com.cn/0.0.0.0 -address=/renshengyiyi.com/0.0.0.0 -address=/represented.cn/0.0.0.0 -address=/requested.cn/0.0.0.0 -address=/rerwe.cn/0.0.0.0 -address=/rfese.com/0.0.0.0 -address=/ricqo.com/0.0.0.0 -address=/rishenglaw.cn/0.0.0.0 -address=/rjiau.com/0.0.0.0 -address=/rl972.cn/0.0.0.0 -address=/rmwdn.com/0.0.0.0 -address=/romgv.com/0.0.0.0 -address=/rongnews.com/0.0.0.0 -address=/rrkykn.cn/0.0.0.0 -address=/rrrwwwa.com/0.0.0.0 -address=/rtslgov.cn/0.0.0.0 -address=/ruiyufangchan.cn/0.0.0.0 -address=/ruxmc.cn/0.0.0.0 -address=/ruyidk.com/0.0.0.0 -address=/ruyiqufu.com/0.0.0.0 -address=/rxxdq.cn/0.0.0.0 -address=/s06th.cn/0.0.0.0 -address=/s2mvd.cn/0.0.0.0 -address=/sanitwealth.com/0.0.0.0 -address=/sbenx.com/0.0.0.0 -address=/sbiim.com/0.0.0.0 -address=/sbinx.com/0.0.0.0 -address=/sceyv.com/0.0.0.0 -address=/scouc.com/0.0.0.0 -address=/scoue.com/0.0.0.0 -address=/scqajt.cn/0.0.0.0 -address=/sczhilong.cn/0.0.0.0 -address=/sdabfw.cn/0.0.0.0 -address=/sdahxz.xyz/0.0.0.0 -address=/sdaiv.com/0.0.0.0 -address=/sdgdtz.cn/0.0.0.0 -address=/sdkdm.com/0.0.0.0 -address=/sdsqyyc.com/0.0.0.0 -address=/sdytsh.com/0.0.0.0 -address=/seawayz.com.cn/0.0.0.0 -address=/sec-cloud.cn/0.0.0.0 -address=/seerpiu002.com/0.0.0.0 -address=/self-study-service.com.cn/0.0.0.0 -address=/sezvc.com/0.0.0.0 -address=/sfanf.com/0.0.0.0 -address=/sguac.com/0.0.0.0 -address=/sgzs999.com/0.0.0.0 -address=/she-ke.cn/0.0.0.0 -address=/shenbimall.com/0.0.0.0 -address=/shengchaopiao.cn/0.0.0.0 -address=/shenhao258.top/0.0.0.0 -address=/shenyunkeji.com/0.0.0.0 -address=/shffcy.cn/0.0.0.0 -address=/shidailw.com/0.0.0.0 -address=/shjsxx.com/0.0.0.0 -address=/shsnjj.top/0.0.0.0 -address=/shuaixu.site/0.0.0.0 -address=/signstu.top/0.0.0.0 -address=/siguatv.cn/0.0.0.0 -address=/simon184.cn/0.0.0.0 -address=/sincetrade.com/0.0.0.0 -address=/sixgen.cn/0.0.0.0 -address=/sjaidu.com/0.0.0.0 -address=/sjczsc.com/0.0.0.0 -address=/sjuqc.com/0.0.0.0 -address=/slivercommander.cn/0.0.0.0 -address=/slvtx.com/0.0.0.0 -address=/slygzsc.cn/0.0.0.0 -address=/smckii.cn/0.0.0.0 -address=/smdhek58726.cn/0.0.0.0 -address=/smpdth.cn/0.0.0.0 -address=/smvip8.cn/0.0.0.0 -address=/smxay.com/0.0.0.0 -address=/sonomoyo.com/0.0.0.0 -address=/sonsang.cn/0.0.0.0 -address=/sosjyx.com/0.0.0.0 -address=/soso.ws/0.0.0.0 -address=/spahelani.com/0.0.0.0 -address=/sqa4e.xyz/0.0.0.0 -address=/sqwscy.com/0.0.0.0 -address=/srrux.com/0.0.0.0 -address=/ssdoi.com/0.0.0.0 -address=/starlizard.com.cn/0.0.0.0 -address=/statstat888.com/0.0.0.0 -address=/stdst.cn/0.0.0.0 -address=/stevenblue.cn/0.0.0.0 -address=/stuoe.com/0.0.0.0 -address=/subshall.cn/0.0.0.0 -address=/suehy.com/0.0.0.0 -address=/sugajo.cn/0.0.0.0 -address=/suitmatters.cn/0.0.0.0 -address=/suolaka.23txt.com/0.0.0.0 -address=/suoooi.cn/0.0.0.0 -address=/suwo0n.com/0.0.0.0 -address=/svfwer.top/0.0.0.0 -address=/swhgd.com/0.0.0.0 -address=/swq48b.cn/0.0.0.0 -address=/sxjkc.cn/0.0.0.0 -address=/sxjxhg.com/0.0.0.0 -address=/sxlczj.cn/0.0.0.0 -address=/sxmdxy.com/0.0.0.0 -address=/sxmutan.com/0.0.0.0 -address=/sxtyhl.top/0.0.0.0 -address=/sxxca.com/0.0.0.0 -address=/sxying.top/0.0.0.0 -address=/sxzzhj.com/0.0.0.0 -address=/sycbbs.com/0.0.0.0 -address=/symaa.cn/0.0.0.0 -address=/symab.cn/0.0.0.0 -address=/symad.cn/0.0.0.0 -address=/symae.cn/0.0.0.0 -address=/symag.cn/0.0.0.0 -address=/symah.cn/0.0.0.0 -address=/sysadult.cn/0.0.0.0 -address=/sysal.cn/0.0.0.0 -address=/sytsr.com/0.0.0.0 -address=/syxchj.cn/0.0.0.0 -address=/syxsa.cn/0.0.0.0 -address=/szqifu.com/0.0.0.0 -address=/szshouzhai.com/0.0.0.0 -address=/szwzjk.cn/0.0.0.0 -address=/szyuke.cn/0.0.0.0 -address=/tabwl.com/0.0.0.0 -address=/tajxgs.com/0.0.0.0 -address=/tatahn.com/0.0.0.0 -address=/tbaia.com/0.0.0.0 -address=/tbenq.com/0.0.0.0 -address=/tbieq.com/0.0.0.0 -address=/tbinq.com/0.0.0.0 -address=/tchep.com/0.0.0.0 -address=/tcnmf.com/0.0.0.0 -address=/tctakoh.com/0.0.0.0 -address=/tdain.com/0.0.0.0 -address=/tdoup.com/0.0.0.0 -address=/tenh2.cn/0.0.0.0 -address=/testself.vip/0.0.0.0 -address=/tgbrfv.cn/0.0.0.0 -address=/themecat.cn/0.0.0.0 -address=/themee.cn/0.0.0.0 -address=/thuyki.cn/0.0.0.0 -address=/tianhelife.com/0.0.0.0 -address=/tianhuafund.cn/0.0.0.0 -address=/tiankongzudui.com/0.0.0.0 -address=/tianxiazhenji.com/0.0.0.0 -address=/tiaopimiao.net/0.0.0.0 -address=/tiaoweiyou.cn/0.0.0.0 -address=/tick0.com/0.0.0.0 -address=/tinwong.cn/0.0.0.0 -address=/tiojk.com/0.0.0.0 -address=/tiwom.com/0.0.0.0 -address=/tjiaa.com/0.0.0.0 -address=/tk59n.cn/0.0.0.0 -address=/tkshyp.com/0.0.0.0 -address=/tl875f.cn/0.0.0.0 -address=/tmmjgcp.cn/0.0.0.0 -address=/tmrmixer.cn/0.0.0.0 -address=/tochgw.com/0.0.0.0 -address=/toissue.cn/0.0.0.0 -address=/tongjiwo.com/0.0.0.0 -address=/tp74ym.cn/0.0.0.0 -address=/travel-together.cn/0.0.0.0 -address=/travlcen.com/0.0.0.0 -address=/tsgyg.cn/0.0.0.0 -address=/tsrc8.com/0.0.0.0 -address=/tuadong.com/0.0.0.0 -address=/tukexiu.com/0.0.0.0 -address=/tuoxintrade.cn/0.0.0.0 -address=/txstatic.cn/0.0.0.0 -address=/txtxr.com/0.0.0.0 -address=/txwhds.com.cn/0.0.0.0 -address=/tymsyx.com/0.0.0.0 -address=/tyrghj.cn/0.0.0.0 -address=/tyyjzs.cn/0.0.0.0 -address=/u372q.cn/0.0.0.0 -address=/u7qy3e.cn/0.0.0.0 -address=/ubaii.com/0.0.0.0 -address=/uc4a.cn/0.0.0.0 -address=/ucaii.com/0.0.0.0 -address=/uchij.com/0.0.0.0 -address=/ucsmqq.site/0.0.0.0 -address=/udbyv8918.com/0.0.0.0 -address=/ueaeqqi.cn/0.0.0.0 -address=/uhor8.cn/0.0.0.0 -address=/uissm.com/0.0.0.0 -address=/uksnyf.cn/0.0.0.0 -address=/umbbs.cn/0.0.0.0 -address=/umm6.cn/0.0.0.0 -address=/umyai.com/0.0.0.0 -address=/unilz588.com/0.0.0.0 -address=/uo12.com/0.0.0.0 -address=/uqpfh.cn/0.0.0.0 -address=/urlet.cn/0.0.0.0 -address=/usty357a.site/0.0.0.0 -address=/uuopp.com/0.0.0.0 -address=/uxyrl.cn/0.0.0.0 -address=/uzhaj.com/0.0.0.0 -address=/uzyid.cn/0.0.0.0 -address=/v3iy0h.cn/0.0.0.0 -address=/v44i.cn/0.0.0.0 -address=/v5b99.cn/0.0.0.0 -address=/vb4rvq.cn/0.0.0.0 -address=/vbaiu.com/0.0.0.0 -address=/vbanm.com/0.0.0.0 -address=/vbaof.com/0.0.0.0 -address=/vbaou.com/0.0.0.0 -address=/vbieu.com/0.0.0.0 -address=/vbinu.com/0.0.0.0 -address=/vcaif.com/0.0.0.0 -address=/vchim.com/0.0.0.0 -address=/vchiy.com/0.0.0.0 -address=/vcuor.com/0.0.0.0 -address=/vdlha.cn/0.0.0.0 -address=/ve6j.cn/0.0.0.0 -address=/vers80.com/0.0.0.0 -address=/vf5yb4.cn/0.0.0.0 -address=/vgaom.com/0.0.0.0 -address=/vhuay.com/0.0.0.0 -address=/vichc.com/0.0.0.0 -address=/viiqx.com/0.0.0.0 -address=/viptv91.cn/0.0.0.0 -address=/vjuer.com/0.0.0.0 -address=/vkjnd.com/0.0.0.0 -address=/vkuay.com/0.0.0.0 -address=/vmiua.com/0.0.0.0 -address=/vnanf.com/0.0.0.0 -address=/vouky.com/0.0.0.0 -address=/vsxet.com/0.0.0.0 -address=/vvnna.com/0.0.0.0 -address=/vvocm.com/0.0.0.0 -address=/vwb4p.cn/0.0.0.0 -address=/vweit.com/0.0.0.0 -address=/vy74i.cn/0.0.0.0 -address=/vz71j.cn/0.0.0.0 -address=/w13qh.cn/0.0.0.0 -address=/w859u.cn/0.0.0.0 -address=/waby66.cn/0.0.0.0 -address=/wagenlux.cn/0.0.0.0 -address=/wanfcc.com/0.0.0.0 -address=/wangliqin.top/0.0.0.0 -address=/wangqing7.top/0.0.0.0 -address=/wanrenshe.com/0.0.0.0 -address=/wao24.com/0.0.0.0 -address=/warron.cn/0.0.0.0 -address=/wbanz.com/0.0.0.0 -address=/wbaor.com/0.0.0.0 -address=/wbies.com/0.0.0.0 -address=/wbiev.com/0.0.0.0 -address=/wcail.com/0.0.0.0 -address=/wcaos.com/0.0.0.0 -address=/wcjup.com/0.0.0.0 -address=/wdeie.com/0.0.0.0 -address=/wdiur.com/0.0.0.0 -address=/webenginner.com/0.0.0.0 -address=/webkooo.com/0.0.0.0 -address=/weboser.com/0.0.0.0 -address=/wechatpu.com/0.0.0.0 -address=/weikefanli.com/0.0.0.0 -address=/weimeicar.cn/0.0.0.0 -address=/weiziqiang.top/0.0.0.0 -address=/wenbangsh.com.cn/0.0.0.0 -address=/wenzhougy.cn/0.0.0.0 -address=/wervp.com/0.0.0.0 -address=/wfxoi.xyz/0.0.0.0 -address=/wfyqc.com/0.0.0.0 -address=/wgaoe.com/0.0.0.0 -address=/wghjq.cn/0.0.0.0 -address=/whrles.com/0.0.0.0 -address=/whsjg.cn/0.0.0.0 -address=/whxhhjx.com/0.0.0.0 -address=/wjdfv.com/0.0.0.0 -address=/wjier.com/0.0.0.0 -address=/wjyljl.cn/0.0.0.0 -address=/wkjava.top/0.0.0.0 -address=/wkjhd.com/0.0.0.0 -address=/wksrx.cn/0.0.0.0 -address=/wl963.com/0.0.0.0 -address=/wlshotel.cn/0.0.0.0 -address=/wnbfw.com/0.0.0.0 -address=/wo-x.cn/0.0.0.0 -address=/wokekk.com/0.0.0.0 -address=/wonwg.com/0.0.0.0 -address=/workbizs.com/0.0.0.0 -address=/woshiyunying.com/0.0.0.0 -address=/wotto.cn/0.0.0.0 -address=/woyvk.cn/0.0.0.0 -address=/wq19w.cn/0.0.0.0 -address=/wsoue.com/0.0.0.0 -address=/wsxxu.com/0.0.0.0 -address=/wuwuhh.top/0.0.0.0 -address=/wuyanauto.com/0.0.0.0 -address=/wuylp.com/0.0.0.0 -address=/wvcdn.cn/0.0.0.0 -address=/wvver.com/0.0.0.0 -address=/wwetjy.com/0.0.0.0 -address=/wxhdwy.com/0.0.0.0 -address=/wxhh678.com/0.0.0.0 -address=/wxhltd.com/0.0.0.0 -address=/wxmg2016.com/0.0.0.0 -address=/wxvsj.com.cn/0.0.0.0 -address=/wywna.cn/0.0.0.0 -address=/wzn4.cn/0.0.0.0 -address=/wzxw7.com/0.0.0.0 -address=/x3e2c.cn/0.0.0.0 -address=/x5cc5z.cn/0.0.0.0 -address=/xabtx.com/0.0.0.0 -address=/xacqp.com/0.0.0.0 -address=/xafxs.cn/0.0.0.0 -address=/xamaky.top/0.0.0.0 -address=/xamiqi.top/0.0.0.0 -address=/xavingtsun.com/0.0.0.0 -address=/xb29h.cn/0.0.0.0 -address=/xbaiv.com/0.0.0.0 -address=/xberu.com/0.0.0.0 -address=/xcbmwx.com/0.0.0.0 -address=/xcdzsw.com/0.0.0.0 -address=/xdkje.com/0.0.0.0 -address=/xdunv.com/0.0.0.0 -address=/xdyszx.com/0.0.0.0 -address=/xeihy.com/0.0.0.0 -address=/xfytjx.cn/0.0.0.0 -address=/xhaiu.com/0.0.0.0 -address=/xhct66.com/0.0.0.0 -address=/xhera.cn/0.0.0.0 -address=/xiakelea.com/0.0.0.0 -address=/xiangchim0.com/0.0.0.0 -address=/xiangshiw.net/0.0.0.0 -address=/xiansenmeng.cn/0.0.0.0 -address=/xieyanmin.com.cn/0.0.0.0 -address=/xindelin.cn/0.0.0.0 -address=/xinghao89.com/0.0.0.0 -address=/xingsky.cn/0.0.0.0 -address=/xingtai0.com/0.0.0.0 -address=/xingtaiju.cn/0.0.0.0 -address=/xinterface.cn/0.0.0.0 -address=/xinuocp666.com/0.0.0.0 -address=/xjtxcj.com/0.0.0.0 -address=/xk0x.cn/0.0.0.0 -address=/xkanf.com/0.0.0.0 -address=/xkena.com/0.0.0.0 -address=/xkqpco.com/0.0.0.0 -address=/xkunn.com/0.0.0.0 -address=/xmcxz.com/0.0.0.0 -address=/xmgdfb.cn/0.0.0.0 -address=/xmgysweb.com/0.0.0.0 -address=/xmljx.cn/0.0.0.0 -address=/xmndrx.cn/0.0.0.0 -address=/xn--2qux23confgml.club/0.0.0.0 -address=/xn--mtsr39cnql.video/0.0.0.0 -address=/xn--wxtr44c.video/0.0.0.0 -address=/xncgroup.cn/0.0.0.0 -address=/xnghmc.com/0.0.0.0 -address=/xnjzsn.com/0.0.0.0 -address=/xrain.net/0.0.0.0 -address=/xroun.com/0.0.0.0 -address=/xrpva.cn/0.0.0.0 -address=/xsyouwei.cn/0.0.0.0 -address=/xt725.cn/0.0.0.0 -address=/xtzxmy.com/0.0.0.0 -address=/xuehongxs.com:8862/0.0.0.0 -address=/xujx8.com/0.0.0.0 -address=/xunhuaji.cn/0.0.0.0 -address=/xurizhongguo.cn/0.0.0.0 -address=/xxkio.com/0.0.0.0 -address=/xxlywl.cn/0.0.0.0 -address=/xznykf.org/0.0.0.0 -address=/xztms.com/0.0.0.0 -address=/y05zw.cn/0.0.0.0 -address=/y12f.com/0.0.0.0 -address=/yajiuwz.xyz/0.0.0.0 -address=/yanbenji.cn/0.0.0.0 -address=/yangzhenpeng.top/0.0.0.0 -address=/yanjunbo.com/0.0.0.0 -address=/ybaih.com/0.0.0.0 -address=/ybaiu.com/0.0.0.0 -address=/ybanj.com/0.0.0.0 -address=/ybaoh.com/0.0.0.0 -address=/ybeih.com/0.0.0.0 -address=/ybfwmm.cn/0.0.0.0 -address=/ybhypt.com/0.0.0.0 -address=/ybrex.cn/0.0.0.0 -address=/ybtianxi.com/0.0.0.0 -address=/ychap.com/0.0.0.0 -address=/ycypzx.cn/0.0.0.0 -address=/ydfz.org/0.0.0.0 -address=/ydouu.com/0.0.0.0 -address=/yetaiguang.cn/0.0.0.0 -address=/yexfes.com/0.0.0.0 -address=/yfano.com/0.0.0.0 -address=/ygblogtag.cn/0.0.0.0 -address=/ygqczh.com/0.0.0.0 -address=/yguap.com/0.0.0.0 -address=/yicang8.com/0.0.0.0 -address=/yicixingjinkou.com/0.0.0.0 -address=/yicuntian.cn/0.0.0.0 -address=/yierheng.top/0.0.0.0 -address=/yijieweizf.com/0.0.0.0 -address=/yijuxie.com/0.0.0.0 -address=/yikuaiqian.com.cn/0.0.0.0 -address=/yimai51.cn/0.0.0.0 -address=/yimeize.cn/0.0.0.0 -address=/yingkepj.cn/0.0.0.0 -address=/yinlt.com/0.0.0.0 -address=/yinzantouzi.com/0.0.0.0 -address=/yiqima.xyz/0.0.0.0 -address=/yisloda.com/0.0.0.0 -address=/yitiaoyu.top/0.0.0.0 -address=/yiyuantian.com/0.0.0.0 -address=/yizhijin.cn/0.0.0.0 -address=/yjiaj.com/0.0.0.0 -address=/ymmdpk.cn/0.0.0.0 -address=/ynbzxh.com/0.0.0.0 -address=/yndushi.cn/0.0.0.0 -address=/ynizdm.cn/0.0.0.0 -address=/ynjczy.net/0.0.0.0 -address=/ynjyhm.com/0.0.0.0 -address=/ynmhg.cn/0.0.0.0 -address=/ynnke.com/0.0.0.0 -address=/ynp0h.cn/0.0.0.0 -address=/ynzby.cn/0.0.0.0 -address=/yo34b.cn/0.0.0.0 -address=/yoiur.com/0.0.0.0 -address=/youtui456.com/0.0.0.0 -address=/youweiprint.com/0.0.0.0 -address=/youyoukou.cn/0.0.0.0 -address=/yoxus.cn/0.0.0.0 -address=/ypzhwf.cn/0.0.0.0 -address=/yr29r.cn/0.0.0.0 -address=/ys6ot.cn/0.0.0.0 -address=/ysjweb.com/0.0.0.0 -address=/yssbi.net/0.0.0.0 -address=/ytbnm.cn/0.0.0.0 -address=/ytdksb.com/0.0.0.0 -address=/ytmaitian.com/0.0.0.0 -address=/ytmaksim.cn/0.0.0.0 -address=/yuanhangpiju.cn/0.0.0.0 -address=/yueduyy.com/0.0.0.0 -address=/yueyelive.com/0.0.0.0 -address=/yunanfuwuqi.com/0.0.0.0 -address=/yunxiufang.net/0.0.0.0 -address=/yuxiny.com/0.0.0.0 -address=/yuxyz.com/0.0.0.0 -address=/ywbwsm.com/0.0.0.0 -address=/ywqum.cn/0.0.0.0 -address=/ywrjgzs.com/0.0.0.0 -address=/yxhxs.com/0.0.0.0 -address=/yxsnf.cn/0.0.0.0 -address=/yybos.com.cn/0.0.0.0 -address=/yyeks.com/0.0.0.0 -address=/yyhqch.com/0.0.0.0 -address=/yyjhf.com/0.0.0.0 -address=/yymmsd.cn/0.0.0.0 -address=/z3uk6.cn/0.0.0.0 -address=/z41vm.cn/0.0.0.0 -address=/zabxb.com/0.0.0.0 -address=/zbeic.com/0.0.0.0 -address=/zbieo.com/0.0.0.0 -address=/zcand.com/0.0.0.0 -address=/zcaod.com/0.0.0.0 -address=/zcdor.com/0.0.0.0 -address=/zcpap.cn/0.0.0.0 -address=/zcpnq.cn/0.0.0.0 -address=/zenffs.cn/0.0.0.0 -address=/zenwq.com/0.0.0.0 -address=/zesod.cn/0.0.0.0 -address=/zfanc.com/0.0.0.0 -address=/zfood029.com/0.0.0.0 -address=/zfrgkm.cn/0.0.0.0 -address=/zgbsny.com/0.0.0.0 -address=/zgclmw.cn/0.0.0.0 -address=/zgfszs.com/0.0.0.0 -address=/zgjjkk.com/0.0.0.0 -address=/zgjkv.com/0.0.0.0 -address=/zgncpjyw.cn/0.0.0.0 -address=/zgsxhx.com/0.0.0.0 -address=/zhamm.cn/0.0.0.0 -address=/zhfyws.com/0.0.0.0 -address=/zhivalley.cn/0.0.0.0 -address=/zhiyaowan.cn/0.0.0.0 -address=/zhongfujiaoyu.cn/0.0.0.0 -address=/zhongwangmy.cn/0.0.0.0 -address=/zhouqin520.top/0.0.0.0 -address=/zhuanyule.cn/0.0.0.0 -address=/zhuifood.top/0.0.0.0 -address=/zhujiafangchan.cn/0.0.0.0 -address=/zhuyuanp.shop/0.0.0.0 -address=/zhuyuanp.top/0.0.0.0 -address=/zhywyl.cn/0.0.0.0 -address=/zizcy.com/0.0.0.0 -address=/zjhrondo.cn/0.0.0.0 -address=/zjkdaikuan.com/0.0.0.0 -address=/zjksgl.com/0.0.0.0 -address=/zjuwjdc.com/0.0.0.0 -address=/zjxrg.top/0.0.0.0 -address=/zkba9.cn/0.0.0.0 -address=/zkfborg.cn/0.0.0.0 -address=/zkwsdf.com/0.0.0.0 -address=/zlauk.cn/0.0.0.0 -address=/zm-bulu.cn/0.0.0.0 -address=/zmlfk.com/0.0.0.0 -address=/zmyuer.com/0.0.0.0 -address=/zougg.com/0.0.0.0 -address=/zpoder.com/0.0.0.0 -address=/zpyfsj.cn/0.0.0.0 -address=/zreder.com/0.0.0.0 -address=/zstjy.com/0.0.0.0 -address=/zsxpx.com/0.0.0.0 -address=/ztxbd.com/0.0.0.0 -address=/zu08e.cn/0.0.0.0 -address=/zunss.com/0.0.0.0 -address=/zuopp.com/0.0.0.0 -address=/zutodu.cn/0.0.0.0 -address=/zwkssb.com/0.0.0.0 -address=/zwsteel.cn/0.0.0.0 -address=/zwychain.cn/0.0.0.0 -address=/zx-jsp.com/0.0.0.0 -address=/zxhymh.com/0.0.0.0 -address=/zxin131.cn/0.0.0.0 -address=/zxjjzx.com/0.0.0.0 -address=/zywhjd.com/0.0.0.0 -address=/zyxwpj.com/0.0.0.0 -address=/zzalkk.com/0.0.0.0 -address=/zzhszj.com/0.0.0.0 -address=/zzkfs.xyz/0.0.0.0 -address=/zzmmkj.com/0.0.0.0 -address=/zzmtfz.com/0.0.0.0 -address=/zzqqhb.com/0.0.0.0 -address=/zzsdjq.com/0.0.0.0 -address=/zzsno1.com/0.0.0.0 -address=/corechina.net/0.0.0.0 -address=/diogv.com/0.0.0.0 -address=/iierq.com/0.0.0.0 -address=/jbflil.cn/0.0.0.0 -address=/shyanche.net/0.0.0.0 -address=/yljiaoluo.com/0.0.0.0 -address=/yqjxzw.com/0.0.0.0 -address=/assume8.com/0.0.0.0 -address=/kfdqwo.top/0.0.0.0 -address=/tianjin4.com/0.0.0.0 -address=/hy-dy.cn/0.0.0.0 -address=/liveappgirl.net/0.0.0.0 -address=/69lm.com.cn/0.0.0.0 -address=/qhdfxkj.com/0.0.0.0 -address=/shxqeps.com/0.0.0.0 -address=/hnpjshop.com/0.0.0.0 -address=/lopostone.com/0.0.0.0 -address=/qyqc4s.com/0.0.0.0 -address=/vuahb.com/0.0.0.0 -address=/103.49.209.27/0.0.0.0 -address=/146.148.85.61/0.0.0.0 -address=/172.81.246.180/0.0.0.0 -address=/212.64.34.17/0.0.0.0 -address=/45.126.123.80/0.0.0.0 -address=/815ff.com/0.0.0.0 -address=/chaogej.com/0.0.0.0 -address=/hdapp1003-a.akamaihd.net/0.0.0.0 -address=/hdapp1008-a.akamaihd.net/0.0.0.0 -address=/hdsrc-a.akamaihd.net/0.0.0.0 -address=/journalforum.org/0.0.0.0 -address=/nvsea.com/0.0.0.0 -address=/qhdbfjx.com/0.0.0.0 -address=/sohu999.com/0.0.0.0 -address=/tcmdz.com/0.0.0.0 -address=/withad.cn/0.0.0.0 -address=/9t5.me/0.0.0.0 -address=/abgligarchan.com/0.0.0.0 -address=/acticgreasonsc.info/0.0.0.0 -address=/adfrastingathles.info/0.0.0.0 -address=/adsrv.me/0.0.0.0 -address=/adziondin.club/0.0.0.0 -address=/aggravedgaree.info/0.0.0.0 -address=/agrammemarg.info/0.0.0.0 -address=/aickeeho.com/0.0.0.0 -address=/ailwayssteverin.info/0.0.0.0 -address=/airsanguages.info/0.0.0.0 -address=/airstossiplarge.info/0.0.0.0 -address=/albalbant.com/0.0.0.0 -address=/aleapeact.club/0.0.0.0 -address=/aliticalpassister.info/0.0.0.0 -address=/alldeveldefinite.info/0.0.0.0 -address=/allycollegedstrie.info/0.0.0.0 -address=/ampallall.site/0.0.0.0 -address=/anycadark.site/0.0.0.0 -address=/artantash.club/0.0.0.0 -address=/arthwhilearthu.info/0.0.0.0 -address=/artneesrparkete.info/0.0.0.0 -address=/ashaidart.site/0.0.0.0 -address=/ashamparm.site/0.0.0.0 -address=/atelovesinothic.info/0.0.0.0 -address=/atesbrothereso.info/0.0.0.0 -address=/atoultou.com/0.0.0.0 -address=/augnuxun.net/0.0.0.0 -address=/aujaujoa.net/0.0.0.0 -address=/aurdeert.net/0.0.0.0 -address=/auxml.com/0.0.0.0 -address=/awhootoa.net/0.0.0.0 -address=/awhoufob.com/0.0.0.0 -address=/ayrovalcontain.info/0.0.0.0 -address=/bathibsa.com/0.0.0.0 -address=/bauthair.net/0.0.0.0 -address=/bebreloomr.com/0.0.0.0 -address=/beewanuk.net/0.0.0.0 -address=/bestvideo2019.xyz/0.0.0.0 -address=/bidiology.com/0.0.0.0 -address=/boratestfishke.info/0.0.0.0 -address=/boubeeth.com/0.0.0.0 -address=/boursnormaticm.info/0.0.0.0 -address=/bupserge.com/0.0.0.0 -address=/cadslimz.com/0.0.0.0 -address=/camantasp.club/0.0.0.0 -address=/canonch.pro/0.0.0.0 -address=/casinohacksforyou.com/0.0.0.0 -address=/cauthuny.net/0.0.0.0 -address=/ceincreatedaughtcha.info/0.0.0.0 -address=/cespousseluniv.info/0.0.0.0 -address=/choorgiw.net/0.0.0.0 -address=/clickcdn.co/0.0.0.0 -address=/collectpush.com/0.0.0.0 -address=/counevan.pro/0.0.0.0 -address=/countertrck.com/0.0.0.0 -address=/cpcmart.com/0.0.0.0 -address=/criminglynuk.pro/0.0.0.0 -address=/cssimplicanab.info/0.0.0.0 -address=/ctsjackupspete.info/0.0.0.0 -address=/culreelt.com/0.0.0.0 -address=/cutopportings.info/0.0.0.0 -address=/cyneburg-yam.com/0.0.0.0 -address=/dacoloment.pro/0.0.0.0 -address=/dainaith.net/0.0.0.0 -address=/dardwebertoha.info/0.0.0.0 -address=/dcontonalscho.info/0.0.0.0 -address=/dddomainccc.com/0.0.0.0 -address=/delainlygoverhe.info/0.0.0.0 -address=/dgafgadsgkjg.top/0.0.0.0 -address=/diantcummiere.info/0.0.0.0 -address=/dimessing-parker.com/0.0.0.0 -address=/dingsincernett.info/0.0.0.0 -address=/discoverapp.xyz/0.0.0.0 -address=/ditookry.com/0.0.0.0 -address=/dmastescaugh.info/0.0.0.0 -address=/dolsoste.com/0.0.0.0 -address=/dooptoug.net/0.0.0.0 -address=/dorthuredwardles.info/0.0.0.0 -address=/dortoolr.com/0.0.0.0 -address=/duchoono.com/0.0.0.0 -address=/duhochid.net/0.0.0.0 -address=/duxumpou.com/0.0.0.0 -address=/echoazou.com/0.0.0.0 -address=/edcritessuspi.info/0.0.0.0 -address=/edencourtbrita.info/0.0.0.0 -address=/edoutoam.net/0.0.0.0 -address=/edvforeveretest.info/0.0.0.0 -address=/eeltaung.com/0.0.0.0 -address=/eengaums.com/0.0.0.0 -address=/eergurty.net/0.0.0.0 -address=/eforeantheirma.info/0.0.0.0 -address=/egroacho.com/0.0.0.0 -address=/ememoricane.info/0.0.0.0 -address=/encountryf.pro/0.0.0.0 -address=/enormitteen.pro/0.0.0.0 -address=/enseptedsome.info/0.0.0.0 -address=/entstronicsform.info/0.0.0.0 -address=/epresententifi.info/0.0.0.0 -address=/eraltradiansid.info/0.0.0.0 -address=/erkhxw.com/0.0.0.0 -address=/erversarycompa.info/0.0.0.0 -address=/esauwoan.com/0.0.0.0 -address=/estionexperime.info/0.0.0.0 -address=/eunformeranothe.info/0.0.0.0 -address=/fadsans.com/0.0.0.0 -address=/fadsecs.com/0.0.0.0 -address=/fadsims.com/0.0.0.0 -address=/fadsips.com/0.0.0.0 -address=/fadslims.com/0.0.0.0 -address=/fadsoks.com/0.0.0.0 -address=/fadspmz.com/0.0.0.0 -address=/fagmomqua.site/0.0.0.0 -address=/fazoumee.net/0.0.0.0 -address=/feed777.me/0.0.0.0 -address=/feelineweatyeng.info/0.0.0.0 -address=/ffortyimagist.info/0.0.0.0 -address=/fishkekcamp.info/0.0.0.0 -address=/fixsirrod.site/0.0.0.0 -address=/fufoatch.com/0.0.0.0 -address=/fuyuap.xyz/0.0.0.0 -address=/gadsans.com/0.0.0.0 -address=/gadsanz.com/0.0.0.0 -address=/gadsats.com/0.0.0.0 -address=/gadsecz.com/0.0.0.0 -address=/gadsimz.com/0.0.0.0 -address=/gadsipz.com/0.0.0.0 -address=/gadsokz.com/0.0.0.0 -address=/gedspecificano.info/0.0.0.0 -address=/gleergie.net/0.0.0.0 -address=/global-surveys.co/0.0.0.0 -address=/globwo.online/0.0.0.0 -address=/glomseci.com/0.0.0.0 -address=/gludraus.com/0.0.0.0 -address=/go2.global/0.0.0.0 -address=/gobovoul.net/0.0.0.0 -address=/graunada.com/0.0.0.0 -address=/grementessenti.info/0.0.0.0 -address=/grexoacu.com/0.0.0.0 -address=/groackam.com/0.0.0.0 -address=/h3btqpy2abc3.com/0.0.0.0 -address=/haftobso.net/0.0.0.0 -address=/hamadotax.site/0.0.0.0 -address=/heckagny.com/0.0.0.0 -address=/hoosorie.com/0.0.0.0 -address=/hounicuy.com/0.0.0.0 -address=/housopsi.net/0.0.0.0 -address=/huckauhy.com/0.0.0.0 -address=/hwhiffonprotect.info/0.0.0.0 -address=/iglaique.net/0.0.0.0 -address=/imounsos.com/0.0.0.0 -address=/ingdaughtexam.info/0.0.0.0 -address=/ingprographyt.info/0.0.0.0 -address=/ipsoorel.com/0.0.0.0 -address=/iulianus-mon.com/0.0.0.0 -address=/jahediretictho.info/0.0.0.0 -address=/jamestop.xyz/0.0.0.0 -address=/jaugloup.com/0.0.0.0 -address=/jechesmacaltont.info/0.0.0.0 -address=/jicmutse.com/0.0.0.0 -address=/jinsoopt.net/0.0.0.0 -address=/joawapti.net/0.0.0.0 -address=/justookr.net/0.0.0.0 -address=/katerigordas.pro/0.0.0.0 -address=/kaukoany.net/0.0.0.0 -address=/kcampairsang.info/0.0.0.0 -address=/keepaira.net/0.0.0.0 -address=/ketstheralinver.info/0.0.0.0 -address=/knottishhuntilc.info/0.0.0.0 -address=/koocaucy.com/0.0.0.0 -address=/koutobey.net/0.0.0.0 -address=/kumanaun.net/0.0.0.0 -address=/labortiontrifee.info/0.0.0.0 -address=/ladsdown.com/0.0.0.0 -address=/laichaim.net/0.0.0.0 -address=/lassistslegisten.info/0.0.0.0 -address=/ldevillaechildren.info/0.0.0.0 -address=/leathtexactlycin.info/0.0.0.0 -address=/leontius-eli.com/0.0.0.0 -address=/lessite.pro/0.0.0.0 -address=/linkev.com/0.0.0.0 -address=/loaphour.com/0.0.0.0 -address=/locothet.com/0.0.0.0 -address=/loobusir.com/0.0.0.0 -address=/lutachechu.pro/0.0.0.0 -address=/lynormationpas.info/0.0.0.0 -address=/lyzenoti.pro/0.0.0.0 -address=/madsans.com/0.0.0.0 -address=/maihaimo.com/0.0.0.0 -address=/maipoted.com/0.0.0.0 -address=/mbethnarrowe.info/0.0.0.0 -address=/mbledeparatea.info/0.0.0.0 -address=/meehaina.net/0.0.0.0 -address=/mewnetwag.site/0.0.0.0 -address=/mibsooks.net/0.0.0.0 -address=/mirafaren.pw/0.0.0.0 -address=/moapteeg.net/0.0.0.0 -address=/mozgvya.com/0.0.0.0 -address=/mptedcazdep.info/0.0.0.0 -address=/nadjustifygas.info/0.0.0.0 -address=/nailowhe.net/0.0.0.0 -address=/nbasicalbuffere.info/0.0.0.0 -address=/ncefoundanges.info/0.0.0.0 -address=/ncylegiatede.info/0.0.0.0 -address=/nelsdecademi.info/0.0.0.0 -address=/neltoole.net/0.0.0.0 -address=/nesoaghu.net/0.0.0.0 -address=/nessendencec.info/0.0.0.0 -address=/netcatx.com/0.0.0.0 -address=/newvideos.xyz/0.0.0.0 -address=/nfarmerlycompa.info/0.0.0.0 -address=/ngholishingsm.info/0.0.0.0 -address=/niebrundveepursuede.info/0.0.0.0 -address=/nishathlessharr.info/0.0.0.0 -address=/nishfarmerlypas.info/0.0.0.0 -address=/nlzz7a3md4sx.com/0.0.0.0 -address=/noagloot.net/0.0.0.0 -address=/noaloheb.com/0.0.0.0 -address=/noglolra.com/0.0.0.0 -address=/norakseemlyntr.info/0.0.0.0 -address=/noutstancerewe.info/0.0.0.0 -address=/ntsartingaccura.info/0.0.0.0 -address=/oajujirg.net/0.0.0.0 -address=/obaukads.com/0.0.0.0 -address=/obefjbb4mykw.com/0.0.0.0 -address=/officultpolicit.pro/0.0.0.0 -address=/ohmchoicechi.online/0.0.0.0 -address=/ommodatesjoin.info/0.0.0.0 -address=/omoaxaus.net/0.0.0.0 -address=/onindexicowillio.info/0.0.0.0 -address=/onscribedpastrong.info/0.0.0.0 -address=/ooxoatse.com/0.0.0.0 -address=/ophoahik.net/0.0.0.0 -address=/oratorsresente.info/0.0.0.0 -address=/ortantchangem.info/0.0.0.0 -address=/oselyprepartie.info/0.0.0.0 -address=/osmondards.pro/0.0.0.0 -address=/otsurvedchange.info/0.0.0.0 -address=/oughgoalityabo.info/0.0.0.0 -address=/ountapaveralle.info/0.0.0.0 -address=/ouzoadru.net/0.0.0.0 -address=/overribleintena.info/0.0.0.0 -address=/padsabz.com/0.0.0.0 -address=/padsatz.com/0.0.0.0 -address=/padsecs.com/0.0.0.0 -address=/pagiwp.com/0.0.0.0 -address=/pagnookr.net/0.0.0.0 -address=/parketbedde.info/0.0.0.0 -address=/pasaigul.com/0.0.0.0 -address=/paula-secundinus.com/0.0.0.0 -address=/paveralleycoun.info/0.0.0.0 -address=/peethobo.com/0.0.0.0 -address=/pgradualirelev.info/0.0.0.0 -address=/phabsoun.net/0.0.0.0 -address=/pharougn.com/0.0.0.0 -address=/pheevoug.com/0.0.0.0 -address=/phookree.com/0.0.0.0 -address=/plyvitablesagree.info/0.0.0.0 -address=/poleonaryprac.info/0.0.0.0 -address=/portedlysarcatc.info/0.0.0.0 -address=/possipationd.info/0.0.0.0 -address=/poubotem.com/0.0.0.0 -address=/poudeeri.com/0.0.0.0 -address=/poxeemso.com/0.0.0.0 -address=/prevealhealth.info/0.0.0.0 -address=/productorbash.info/0.0.0.0 -address=/productorsy.pro/0.0.0.0 -address=/psoaksoo.com/0.0.0.0 -address=/psoanouy.net/0.0.0.0 -address=/ptaivain.net/0.0.0.0 -address=/ptiftoud.com/0.0.0.0 -address=/ptogheeb.net/0.0.0.0 -address=/ptoulsey.com/0.0.0.0 -address=/push.house/0.0.0.0 -address=/pushpush.net/0.0.0.0 -address=/pushworldtool.com/0.0.0.0 -address=/realsrv.com/0.0.0.0 -address=/reasonalattracke.info/0.0.0.0 -address=/redappeneticfr.info/0.0.0.0 -address=/redewdit.pro/0.0.0.0 -address=/refunsiy.net/0.0.0.0 -address=/replentcautiful.info/0.0.0.0 -address=/revolutelyplan.info/0.0.0.0 -address=/rexadvert.xyz/0.0.0.0 -address=/rgvqcsxqge.com/0.0.0.0 -address=/rheaddelainlyco.info/0.0.0.0 -address=/riahungardedig.info/0.0.0.0 -address=/ridgelorridorsag.info/0.0.0.0 -address=/rinedcountilconsiden.info/0.0.0.0 -address=/rintellsfundrew.info/0.0.0.0 -address=/ripslifestassoci.info/0.0.0.0 -address=/riptukri.net/0.0.0.0 -address=/rizeintellingente.info/0.0.0.0 -address=/ronoutom.net/0.0.0.0 -address=/roustast.net/0.0.0.0 -address=/routeserve.info/0.0.0.0 -address=/rsleaderingmu.info/0.0.0.0 -address=/runmeethoomes.info/0.0.0.0 -address=/rydresa.info/0.0.0.0 -address=/sadorsagreeng.info/0.0.0.0 -address=/sadsecz.com/0.0.0.0 -address=/sapsixysho.pro/0.0.0.0 -address=/seepsocu.net/0.0.0.0 -address=/sgftrrs.com/0.0.0.0 -address=/shenouth.com/0.0.0.0 -address=/shiptoud.com/0.0.0.0 -address=/silsfrastinggove.info/0.0.0.0 -address=/singthouthappi.info/0.0.0.0 -address=/sisterncoalitical.info/0.0.0.0 -address=/smenqskfmpfxnb.bid/0.0.0.0 -address=/soagrist.net/0.0.0.0 -address=/soofeest.net/0.0.0.0 -address=/sousaira.com/0.0.0.0 -address=/spentalwithinga.info/0.0.0.0 -address=/ssqualismother.info/0.0.0.0 -address=/stargoug.com/0.0.0.0 -address=/stoassod.com/0.0.0.0 -address=/surfacecharo.info/0.0.0.0 -address=/taifouwo.com/0.0.0.0 -address=/tamechangekn.info/0.0.0.0 -address=/tartoals.net/0.0.0.0 -address=/taryarguestio.info/0.0.0.0 -address=/tentdinationgab.info/0.0.0.0 -address=/terialnevitiesini.info/0.0.0.0 -address=/thamsais.com/0.0.0.0 -address=/theeburs.com/0.0.0.0 -address=/thefastpush.com/0.0.0.0 -address=/thigeeph.com/0.0.0.0 -address=/thighiny.com/0.0.0.0 -address=/thimoaph.net/0.0.0.0 -address=/thitegnu.net/0.0.0.0 -address=/thodsserentlya.info/0.0.0.0 -address=/tifybecausingp.info/0.0.0.0 -address=/tionpronomyim.info/0.0.0.0 -address=/tiveacquisitsprett.info/0.0.0.0 -address=/toapsira.net/0.0.0.0 -address=/tonewithough.info/0.0.0.0 -address=/tujestimater.pro/0.0.0.0 -address=/uagesspecifica.info/0.0.0.0 -address=/ufoukolt.com/0.0.0.0 -address=/ugoupams.com/0.0.0.0 -address=/ummerciseha.info/0.0.0.0 -address=/uremechangec.info/0.0.0.0 -address=/urgwritishimpos.info/0.0.0.0 -address=/ushooque.net/0.0.0.0 -address=/uthworkreaseu.info/0.0.0.0 -address=/utpenedwritted.info/0.0.0.0 -address=/utstancecaricit.info/0.0.0.0 -address=/veewakim.net/0.0.0.0 -address=/viatepigan.com/0.0.0.0 -address=/virashux.net/0.0.0.0 -address=/vixirtab.com/0.0.0.0 -address=/vknrfwwxhxaxupqp.pro/0.0.0.0 -address=/wacucmiy.net/0.0.0.0 -address=/wadsotch.com/0.0.0.0 -address=/wagoapse.com/0.0.0.0 -address=/wahamtou.net/0.0.0.0 -address=/waitingpresen.info/0.0.0.0 -address=/watchingssui.info/0.0.0.0 -address=/waugeboa.net/0.0.0.0 -address=/weegebul.net/0.0.0.0 -address=/weethery.com/0.0.0.0 -address=/whadaupo.net/0.0.0.0 -address=/wheessoo.com/0.0.0.0 -address=/whoshood.com/0.0.0.0 -address=/wimsocou.com/0.0.0.0 -address=/woogoust.com/0.0.0.0 -address=/woovooza.net/0.0.0.0 -address=/yinsterkneeline.info/0.0.0.0 -address=/zaivikuk.com/0.0.0.0 -address=/zaugroaw.net/0.0.0.0 -address=/zaushegi.net/0.0.0.0 -address=/zudrurta.com/0.0.0.0 -address=/46.165.197.153/0.0.0.0 -address=/46.165.197.231/0.0.0.0 -address=/74.117.182.77/0.0.0.0 -address=/78.140.131.214/0.0.0.0 -address=/apopgo.com/0.0.0.0 -address=/arrowbucket.co/0.0.0.0 -address=/burporess.pro/0.0.0.0 -address=/clearadnetwork.com/0.0.0.0 -address=/clkrev.com/0.0.0.0 -address=/shillivee.pro/0.0.0.0 -address=/adminpromotion.com/0.0.0.0 -address=/adsalesforce.com/0.0.0.0 -address=/amazingfunnvideos.com/0.0.0.0 -address=/automationeventually.com/0.0.0.0 -address=/blissfulonline.com/0.0.0.0 -address=/capsuledaily.com/0.0.0.0 -address=/chanelets-aurning.com/0.0.0.0 -address=/clickercollections.com/0.0.0.0 -address=/clubpenguinclub.com/0.0.0.0 -address=/commercedirections.com/0.0.0.0 -address=/dialgold.com/0.0.0.0 -address=/effectivelyreport.com/0.0.0.0 -address=/gangidance.com/0.0.0.0 -address=/gladiatorbugs.com/0.0.0.0 -address=/greenmentioned.com/0.0.0.0 -address=/gunnersalmighty.com/0.0.0.0 -address=/happylifebab.com/0.0.0.0 -address=/hilltopgo.com/0.0.0.0 -address=/hugexdeal.com/0.0.0.0 -address=/includeinthebox.com/0.0.0.0 -address=/jasonsvid.com/0.0.0.0 -address=/libreriamedina.com/0.0.0.0 -address=/magararepublic.com/0.0.0.0 -address=/manorparty.com/0.0.0.0 -address=/menuexamples.com/0.0.0.0 -address=/myaarzoo.com/0.0.0.0 -address=/naughtyxparty.com/0.0.0.0 -address=/pennyotcstock.com/0.0.0.0 -address=/requestingreview.com/0.0.0.0 -address=/robovoiz.com/0.0.0.0 -address=/romeoforum.com/0.0.0.0 -address=/safeonlinesites.com/0.0.0.0 -address=/salemyticket.com/0.0.0.0 -address=/softxbutt.com/0.0.0.0 -address=/taodropship.com/0.0.0.0 -address=/thegreenzoneblog.com/0.0.0.0 -address=/ticktockhealth.com/0.0.0.0 -address=/topgreatxoffers.com/0.0.0.0 -address=/trackmackweldon.com/0.0.0.0 -address=/trafficshirts.com/0.0.0.0 -address=/travelstool.com/0.0.0.0 -address=/upcum.com/0.0.0.0 -address=/wallpapersfacts.com/0.0.0.0 -address=/wholesomehealthshop.com/0.0.0.0 -address=/167.206.10.148/0.0.0.0 -address=/acrabakasaka.com/0.0.0.0 -address=/ajkelra.com/0.0.0.0 -address=/akailoparzapi.com/0.0.0.0 -address=/akrazappi.com/0.0.0.0 -address=/alabardak.com/0.0.0.0 -address=/albertonne.com/0.0.0.0 -address=/arganostrella.com/0.0.0.0 -address=/atarshaboor.com/0.0.0.0 -address=/avalhukof.com/0.0.0.0 -address=/badokal.com/0.0.0.0 -address=/banomago.com/0.0.0.0 -address=/bapalolo.com/0.0.0.0 -address=/bapaquac.com/0.0.0.0 -address=/beglorena.com/0.0.0.0 -address=/bidoraln.com/0.0.0.0 -address=/bobarilla.com/0.0.0.0 -address=/boerilav.com/0.0.0.0 -address=/boiceta.com/0.0.0.0 -address=/bokilora.com/0.0.0.0 -address=/bolkazoopa.com/0.0.0.0 -address=/bondinra.com/0.0.0.0 -address=/borazita.com/0.0.0.0 -address=/bulbazoa.com/0.0.0.0 -address=/camtinolc.com/0.0.0.0 -address=/carutinv.com/0.0.0.0 -address=/chukalapopi.com/0.0.0.0 -address=/chukalorqa.com/0.0.0.0 -address=/ciridola.com/0.0.0.0 -address=/civitik.com/0.0.0.0 -address=/dagasaka.com/0.0.0.0 -address=/daghashmal.com/0.0.0.0 -address=/dbvault.net/0.0.0.0 -address=/dinovala.com/0.0.0.0 -address=/dodatova.com/0.0.0.0 -address=/dokaboka.com/0.0.0.0 -address=/dorapodorasham.com/0.0.0.0 -address=/dragolosa.com/0.0.0.0 -address=/drogomet.com/0.0.0.0 -address=/durazopa.com/0.0.0.0 -address=/egolina.com/0.0.0.0 -address=/erogaliv.com/0.0.0.0 -address=/foditgoz.com/0.0.0.0 -address=/forkitz.com/0.0.0.0 -address=/forkizata.com/0.0.0.0 -address=/forkmola.com/0.0.0.0 -address=/fulhudhoo.com/0.0.0.0 -address=/gamzetov.com/0.0.0.0 -address=/godibarl.com/0.0.0.0 -address=/golizoli.com/0.0.0.0 -address=/golokavi.com/0.0.0.0 -address=/haklopar.com/0.0.0.0 -address=/hariqavi.com/0.0.0.0 -address=/hirovivi.com/0.0.0.0 -address=/horheloopo.com/0.0.0.0 -address=/jerotidv.com/0.0.0.0 -address=/jilabukurlabu.com/0.0.0.0 -address=/jingavot.com/0.0.0.0 -address=/jojilabola.com/0.0.0.0 -address=/joribobo.com/0.0.0.0 -address=/jorjodika.com/0.0.0.0 -address=/kaidop.com/0.0.0.0 -address=/kalmloda.com/0.0.0.0 -address=/kilomansa.com/0.0.0.0 -address=/kilorama.com/0.0.0.0 -address=/kirilaboola.com/0.0.0.0 -address=/kofpag.com/0.0.0.0 -address=/kokilopi.com/0.0.0.0 -address=/kolimanq.com/0.0.0.0 -address=/koltruah.com/0.0.0.0 -address=/kompilukabalazooka.com/0.0.0.0 -address=/korketople.com/0.0.0.0 -address=/korkilazoopi.com/0.0.0.0 -address=/krakeshlaja.com/0.0.0.0 -address=/ktoloto.com/0.0.0.0 -address=/kuchebraska.com/0.0.0.0 -address=/kulkaridoopi.com/0.0.0.0 -address=/kulkerbolda.com/0.0.0.0 -address=/kulkulta.com/0.0.0.0 -address=/kullalabulla.com/0.0.0.0 -address=/kurkizraka.com/0.0.0.0 -address=/kurlikburlik.com/0.0.0.0 -address=/kuzalooza.com/0.0.0.0 -address=/liktirov.com/0.0.0.0 -address=/lokipodi.com/0.0.0.0 -address=/lokspeedarma.com/0.0.0.0 -address=/lulpolopolo.com/0.0.0.0 -address=/majosita.com/0.0.0.0 -address=/maokdata.com/0.0.0.0 -address=/measurementaz.com/0.0.0.0 -address=/megahrepsh.com/0.0.0.0 -address=/melahorgani.com/0.0.0.0 -address=/milparota.com/0.0.0.0 -address=/mitotach.com/0.0.0.0 -address=/mojigaga.com/0.0.0.0 -address=/monijorb.com/0.0.0.0 -address=/moninosa.com/0.0.0.0 -address=/morbitempus.com/0.0.0.0 -address=/moritava.com/0.0.0.0 -address=/mujilora.com/0.0.0.0 -address=/namitol.com/0.0.0.0 -address=/nanuyalailai.com/0.0.0.0 -address=/nepohita.com/0.0.0.0 -address=/nidorivo.com/0.0.0.0 -address=/niholaev.com/0.0.0.0 -address=/nimdinb.com/0.0.0.0 -address=/nitigoly.com/0.0.0.0 -address=/oddomane.com/0.0.0.0 -address=/opaalopaa.com/0.0.0.0 -address=/opjalajamak.com/0.0.0.0 -address=/paholita.com/0.0.0.0 -address=/perahbashmama.com/0.0.0.0 -address=/pipilazipi.com/0.0.0.0 -address=/pipilida.com/0.0.0.0 -address=/pitatagata.com/0.0.0.0 -address=/pompazilla.com/0.0.0.0 -address=/poratav.com/0.0.0.0 -address=/prikolizdesa.com/0.0.0.0 -address=/pukrazopchatka.com/0.0.0.0 -address=/pypozeqi.com/0.0.0.0 -address=/qaquzakalaka.com/0.0.0.0 -address=/qawiman.com/0.0.0.0 -address=/qewisoti.com/0.0.0.0 -address=/quavomi.com/0.0.0.0 -address=/rapizoda.com/0.0.0.0 -address=/ratkalol.com/0.0.0.0 -address=/reqpostanza.com/0.0.0.0 -address=/rewapala.com/0.0.0.0 -address=/rezilopompa.com/0.0.0.0 -address=/ripalazc.com/0.0.0.0 -address=/rodirola.com/0.0.0.0 -address=/rolkakuksa.com/0.0.0.0 -address=/scrappykoko.com/0.0.0.0 -address=/senolati.com/0.0.0.0 -address=/shmonekisot.com/0.0.0.0 -address=/shokala.com/0.0.0.0 -address=/shoxyloxi.com/0.0.0.0 -address=/tantella.com/0.0.0.0 -address=/tenlokif.com/0.0.0.0 -address=/tijorari.com/0.0.0.0 -address=/tikrailijorj.com/0.0.0.0 -address=/tilosman.com/0.0.0.0 -address=/tinkerta.com/0.0.0.0 -address=/tokaripupsi.com/0.0.0.0 -address=/tollibolli.com/0.0.0.0 -address=/totachrl.com/0.0.0.0 -address=/trasholita.com/0.0.0.0 -address=/trikroacha.com/0.0.0.0 -address=/udorik.com/0.0.0.0 -address=/ufraton.com/0.0.0.0 -address=/ukatoe.com/0.0.0.0 -address=/ulajilala.com/0.0.0.0 -address=/upnorma.com/0.0.0.0 -address=/uralap.com/0.0.0.0 -address=/utazwa.com/0.0.0.0 -address=/utorido.com/0.0.0.0 -address=/uzekrs.com/0.0.0.0 -address=/uzotarak.com/0.0.0.0 -address=/venonita.com/0.0.0.0 -address=/wakapita.com/0.0.0.0 -address=/wodipaca.com/0.0.0.0 -address=/wodizapt.com/0.0.0.0 -address=/xeozir.com/0.0.0.0 -address=/yaboshadi.com/0.0.0.0 -address=/yallboen.com/0.0.0.0 -address=/yeshhaod.com/0.0.0.0 -address=/yuituityula.com/0.0.0.0 -address=/zarazazapolaza.com/0.0.0.0 -address=/zepozipo.com/0.0.0.0 -address=/zilzolachi.com/0.0.0.0 -address=/zinovila.com/0.0.0.0 -address=/zipovoma.com/0.0.0.0 -address=/zirobata.com/0.0.0.0 -address=/zogzogolla.com/0.0.0.0 -address=/zonolali.com/0.0.0.0 -address=/zorbikala.com/0.0.0.0 -address=/zortinah.com/0.0.0.0 -address=/zozolilla.com/0.0.0.0 -address=/zukabota.com/0.0.0.0 -address=/arana.pw/0.0.0.0 -address=/beiren.xyz/0.0.0.0 -address=/daecan.xyz/0.0.0.0 -address=/daero.pw/0.0.0.0 -address=/daethana.pw/0.0.0.0 -address=/elabalar.pw/0.0.0.0 -address=/elmenor.xyz/0.0.0.0 -address=/farpeiros.pw/0.0.0.0 -address=/galiowen.com/0.0.0.0 -address=/gilzana.pw/0.0.0.0 -address=/glynzumin.pw/0.0.0.0 -address=/grebanise.pw/0.0.0.0 -address=/ianhice.pw/0.0.0.0 -address=/ianxalim.pw/0.0.0.0 -address=/iarfina.pw/0.0.0.0 -address=/iarvyre.pw/0.0.0.0 -address=/ilinan.xyz/0.0.0.0 -address=/inaharice.pw/0.0.0.0 -address=/inastina.pw/0.0.0.0 -address=/jomys.xyz/0.0.0.0 -address=/keaven.pw/0.0.0.0 -address=/kelris.pw/0.0.0.0 -address=/keymaris.com/0.0.0.0 -address=/liacyne.pw/0.0.0.0 -address=/miakalyn.pw/0.0.0.0 -address=/miastina.pw/0.0.0.0 -address=/miracan.pw/0.0.0.0 -address=/naetoris.pw/0.0.0.0 -address=/nornelis.pw/0.0.0.0 -address=/ololen.pw/0.0.0.0 -address=/omaceran.pw/0.0.0.0 -address=/omafaren.pw/0.0.0.0 -address=/omaris.pw/0.0.0.0 -address=/perkas.pw/0.0.0.0 -address=/ralozorwyn.pw/0.0.0.0 -address=/sarjor.pw/0.0.0.0 -address=/thefaren.pw/0.0.0.0 -address=/thenelis.pw/0.0.0.0 -address=/urifiel.pw/0.0.0.0 -address=/valkrana.xyz/0.0.0.0 -address=/wysara.pw/0.0.0.0 -address=/yinmyar.xyz/0.0.0.0 -address=/yllanala.pw/0.0.0.0 -address=/yllasatra.xyz/0.0.0.0 -address=/zinlar.pw/0.0.0.0 -address=/zumhice.pw/0.0.0.0 -address=/459517eb349739b.com/0.0.0.0 -address=/551f044b1a3f4ef.com/0.0.0.0 -address=/ae7c783736eb2ff.com/0.0.0.0 -address=/abrsamar.com/0.0.0.0 -address=/aclickads.com/0.0.0.0 -address=/adbidgo.com/0.0.0.0 -address=/adplexo.com/0.0.0.0 -address=/adservi.com/0.0.0.0 -address=/aebadu.com/0.0.0.0 -address=/aoredi.com/0.0.0.0 -address=/bebadu.com/0.0.0.0 -address=/billionpops.com/0.0.0.0 -address=/cebadu.com/0.0.0.0 -address=/clcknpop.com/0.0.0.0 -address=/clickadin.com/0.0.0.0 -address=/clickbigo.com/0.0.0.0 -address=/clmcom.com/0.0.0.0 -address=/coocopop.com/0.0.0.0 -address=/crptgate.com/0.0.0.0 -address=/debadu.com/0.0.0.0 -address=/dlsear.com/0.0.0.0 -address=/doubledeepclick.com/0.0.0.0 -address=/doublelimpup.com/0.0.0.0 -address=/dsp.wtf/0.0.0.0 -address=/earnbigo.com/0.0.0.0 -address=/eoredi.com/0.0.0.0 -address=/fabrkrup.com/0.0.0.0 -address=/fastpopclick.com/0.0.0.0 -address=/fastpopunder.com/0.0.0.0 -address=/febadu.com/0.0.0.0 -address=/fedsit.com/0.0.0.0 -address=/foxypp.com/0.0.0.0 -address=/fsitel.com/0.0.0.0 -address=/furmnas.com/0.0.0.0 -address=/gebadu.com/0.0.0.0 -address=/goredi.com/0.0.0.0 -address=/hebadu.com/0.0.0.0 -address=/hiblcom.com/0.0.0.0 -address=/horedi.com/0.0.0.0 -address=/hypoot.com/0.0.0.0 -address=/iddpop.com/0.0.0.0 -address=/iendoo.com/0.0.0.0 -address=/ioredi.com/0.0.0.0 -address=/isupopc.com/0.0.0.0 -address=/iupot.com/0.0.0.0 -address=/jebadu.com/0.0.0.0 -address=/joredi.com/0.0.0.0 -address=/joredii.com/0.0.0.0 -address=/koncbabae.com/0.0.0.0 -address=/koradu.com/0.0.0.0 -address=/lupoot.com/0.0.0.0 -address=/mdlsite.com/0.0.0.0 -address=/moomoopop.com/0.0.0.0 -address=/moradu.com/0.0.0.0 -address=/nebadu.com/0.0.0.0 -address=/nkmsite.com/0.0.0.0 -address=/nupoot.com/0.0.0.0 -address=/oebadu.com/0.0.0.0 -address=/oktpage.com/0.0.0.0 -address=/ooredi.com/0.0.0.0 -address=/pebadu.com/0.0.0.0 -address=/platado.com/0.0.0.0 -address=/popcain.com/0.0.0.0 -address=/popuexo.com/0.0.0.0 -address=/poredii.com/0.0.0.0 -address=/ppcashpop.com/0.0.0.0 -address=/profbigo.com/0.0.0.0 -address=/propbigo.com/0.0.0.0 -address=/pttsite.com/0.0.0.0 -address=/qebodu.com/0.0.0.0 -address=/qoredi.com/0.0.0.0 -address=/revbigo.com/0.0.0.0 -address=/roredi.com/0.0.0.0 -address=/sebadu.com/0.0.0.0 -address=/shareitpp.com/0.0.0.0 -address=/sitegoto.com/0.0.0.0 -address=/sitemnk.com/0.0.0.0 -address=/siterdm.com/0.0.0.0 -address=/sitetoway.com/0.0.0.0 -address=/soonbigo.com/0.0.0.0 -address=/sscashpop.com/0.0.0.0 -address=/svsub.com/0.0.0.0 -address=/syndicpop.com/0.0.0.0 -address=/syndopop.com/0.0.0.0 -address=/tebadu.com/0.0.0.0 -address=/terroppop.com/0.0.0.0 -address=/thterras.com/0.0.0.0 -address=/tosfeed.com/0.0.0.0 -address=/tplpages.com/0.0.0.0 -address=/trmnsite.com/0.0.0.0 -address=/tsandycateup.com/0.0.0.0 -address=/uebadu.com/0.0.0.0 -address=/uoredi.com/0.0.0.0 -address=/vebadu.com/0.0.0.0 -address=/voradu.com/0.0.0.0 -address=/voredi.com/0.0.0.0 -address=/vvcashpop.com/0.0.0.0 -address=/webodu.com/0.0.0.0 -address=/whalepp.com/0.0.0.0 -address=/woredi.com/0.0.0.0 -address=/xebadu.com/0.0.0.0 -address=/xoredi.com/0.0.0.0 -address=/xxladu.com/0.0.0.0 -address=/xxlargepop.com/0.0.0.0 -address=/xxssyndic.com/0.0.0.0 -address=/xxxadu.com/0.0.0.0 -address=/yebadu.com/0.0.0.0 -address=/yoredi.com/0.0.0.0 -address=/zavrotfro.com/0.0.0.0 -address=/abbp1.space./0.0.0.0 -address=/a.livesportmedia.eu/0.0.0.0 -address=/a.ucoz.net/0.0.0.0 -address=/a04296f070c0146f314d-0dcad72565cb350972beb3666a86f246.r50.cf5.rackcdn.com/0.0.0.0 -address=/ad.about.co.kr/0.0.0.0 -address=/ad.bitmedia.io/0.0.0.0 -address=/ad.edugram.com/0.0.0.0 -address=/ad.flux.com/0.0.0.0 -address=/ad.foxnetworks.com/0.0.0.0 -address=/ad.jamba.net/0.0.0.0 -address=/ad.livere.co.kr/0.0.0.0 -address=/ad.mesomorphosis.com/0.0.0.0 -address=/ad.netmedia.hu/0.0.0.0 -address=/ad.openmultimedia.biz/0.0.0.0 -address=/ad.outsidehub.com/0.0.0.0 -address=/ad.pickple.net/0.0.0.0 -address=/ad.proxy.sh/0.0.0.0 -address=/ad.rambler.ru/0.0.0.0 -address=/ad.reklamport.com/0.0.0.0 -address=/ad.sensismediasmart.com.au/0.0.0.0 -address=/ad.smartclip.net/0.0.0.0 -address=/ad.winningpartner.com/0.0.0.0 -address=/adingo.jp.eimg.jp/0.0.0.0 -address=/adn.ebay.com/0.0.0.0 -address=/ads.mp.mydas.mobi/0.0.0.0 -address=/ads.servebom.com/0.0.0.0 -address=/ads.tremorhub.com/0.0.0.0 -address=/adss.dotdo.net/0.0.0.0 -address=/advice-ads-cdn.vice.com/0.0.0.0 -address=/adz.zwee.ly/0.0.0.0 -address=/aff.eteachergroup.com/0.0.0.0 -address=/aff.marathonbet.com/0.0.0.0 -address=/aff.svjump.com/0.0.0.0 -address=/affiliate.heureka.cz/0.0.0.0 -address=/affiliateprogram.keywordspy.com/0.0.0.0 -address=/affiliates.allposters.com/0.0.0.0 -address=/affiliatesmedia.sbobet.com/0.0.0.0 -address=/affiliation.fotovista.com/0.0.0.0 -address=/affiliationjs.s3.amazonaws.com/0.0.0.0 -address=/airpushmarketing.s3.amazonaws.com/0.0.0.0 -address=/analytics.disneyinternational.com/0.0.0.0 -address=/ao-freegeoip.herokuapp.com/0.0.0.0 -address=/appnext-a.akamaihd.net/0.0.0.0 -address=/ard.ihookup.com/0.0.0.0 -address=/award.sitekeuring.net/0.0.0.0 -address=/b.babylon.com/0.0.0.0 -address=/banner.101xp.com/0.0.0.0 -address=/banner.3ddownloads.com/0.0.0.0 -address=/banner.europacasino.com/0.0.0.0 -address=/banner.titancasino.com/0.0.0.0 -address=/bl.wavecdn.de/0.0.0.0 -address=/blamads-assets.s3.amazonaws.com/0.0.0.0 -address=/bluhostedbanners.blucigs.com/0.0.0.0 -address=/btr.domywife.com/0.0.0.0 -address=/c.netu.tv/0.0.0.0 -address=/cas.clickability.com/0.0.0.0 -address=/cash.neweramediaworks.com/0.0.0.0 -address=/clarity.abacast.com/0.0.0.0 -address=/click.eyk.net/0.0.0.0 -address=/connect.summit.co.uk/0.0.0.0 -address=/content.livesportmedia.eu/0.0.0.0 -address=/cpm.amateurcommunity.de/0.0.0.0 -address=/creatives.inmotionhosting.com/0.0.0.0 -address=/ct.verticalhealth.net/0.0.0.0 -address=/d10lv7w3g0jvk9.cloudfront.net/0.0.0.0 -address=/d11tybz5ul8vel.cloudfront.net/0.0.0.0 -address=/d140sbu1b1m3h0.cloudfront.net/0.0.0.0 -address=/d144jmuhz9kvbq.cloudfront.net/0.0.0.0 -address=/d158nafix8anfs.cloudfront.net/0.0.0.0 -address=/d15gt9gwxw5wu0.cloudfront.net/0.0.0.0 -address=/d15kdpgjg3unno.cloudfront.net/0.0.0.0 -address=/d162nnmwf9bggr.cloudfront.net/0.0.0.0 -address=/d18xeipe1243h6.cloudfront.net/0.0.0.0 -address=/d1aezk8tun0dhm.cloudfront.net/0.0.0.0 -address=/d1aqvw7cn4ydzo.cloudfront.net/0.0.0.0 -address=/d1crt12zco2cvf.cloudfront.net/0.0.0.0 -address=/d1ebha2k07asm5.cloudfront.net/0.0.0.0 -address=/d1grtyyel8f1mh.cloudfront.net/0.0.0.0 -address=/d1i9kr6k34lyp.cloudfront.net/0.0.0.0 -address=/d1il9t8pu4dsoj.cloudfront.net/0.0.0.0 -address=/d1ks8roequxbwa.cloudfront.net/0.0.0.0 -address=/d1mbgf0ge24riu.cloudfront.net/0.0.0.0 -address=/d1n3tk65esqc4k.cloudfront.net/0.0.0.0 -address=/d1nmxiiewlx627.cloudfront.net/0.0.0.0 -address=/d1pdpbxj733bb1.cloudfront.net/0.0.0.0 -address=/d1qc76gneygidm.cloudfront.net/0.0.0.0 -address=/d1qggq1at2gusn.cloudfront.net/0.0.0.0 -address=/d1qk9ujrmkucbl.cloudfront.net/0.0.0.0 -address=/d1r90st78epsag.cloudfront.net/0.0.0.0 -address=/d1rguclfwp7nc8.cloudfront.net/0.0.0.0 -address=/d1rkf0bq85yx06.cloudfront.net/0.0.0.0 -address=/d1v99qnc7usc0g.cloudfront.net/0.0.0.0 -address=/d1wjz6mrey9f5v.cloudfront.net/0.0.0.0 -address=/d1zgderxoe1a.cloudfront.net/0.0.0.0 -address=/d21j20wsoewvjq.cloudfront.net/0.0.0.0 -address=/d22lo5bcpq2fif.cloudfront.net/0.0.0.0 -address=/d23guct4biwna6.cloudfront.net/0.0.0.0 -address=/d25dfknw9ghxs6.cloudfront.net/0.0.0.0 -address=/d25xkbr68qqtcn.cloudfront.net/0.0.0.0 -address=/d26c6kzavi5zwd.cloudfront.net/0.0.0.0 -address=/d29dbajta0the9.cloudfront.net/0.0.0.0 -address=/d29i6o40xcgdai.cloudfront.net/0.0.0.0 -address=/d2b560qq58menv.cloudfront.net/0.0.0.0 -address=/d2bgg7rjywcwsy.cloudfront.net/0.0.0.0 -address=/d2c4ylitp1qu24.cloudfront.net/0.0.0.0 -address=/d2cgumzzqhgmdu.cloudfront.net/0.0.0.0 -address=/d2d8qsxiai9qwj.cloudfront.net/0.0.0.0 -address=/d2edfzx4ay42og.cloudfront.net/0.0.0.0 -address=/d2focgxak1cn74.cloudfront.net/0.0.0.0 -address=/d2g9nmtuil60cb.cloudfront.net/0.0.0.0 -address=/d2ghscazvn398x.cloudfront.net/0.0.0.0 -address=/d2hvwfg7vv4mhf.cloudfront.net/0.0.0.0 -address=/d2izls9pm2f64q.cloudfront.net/0.0.0.0 -address=/d2kr2fnkbj2h4c.cloudfront.net/0.0.0.0 -address=/d2mic0r0bo3i6z.cloudfront.net/0.0.0.0 -address=/d2muzdhs7lpmo0.cloudfront.net/0.0.0.0 -address=/d2nlytvx51ywh9.cloudfront.net/0.0.0.0 -address=/d2nz8k4xyoudsx.cloudfront.net/0.0.0.0 -address=/d2o307dm5mqftz.cloudfront.net/0.0.0.0 -address=/d2oa97wrxvxm7y.cloudfront.net/0.0.0.0 -address=/d2pxbld8wrqyrk.cloudfront.net/0.0.0.0 -address=/d2qz7ofajpstv5.cloudfront.net/0.0.0.0 -address=/d2szg1g41jt3pq.cloudfront.net/0.0.0.0 -address=/d2taktuuo4oqx.cloudfront.net/0.0.0.0 -address=/d2va1d0hpla18n.cloudfront.net/0.0.0.0 -address=/d31vxm9ubutrmw.cloudfront.net/0.0.0.0 -address=/d32r9jwgeu9dzx.cloudfront.net/0.0.0.0 -address=/d33otidwg56k90.cloudfront.net/0.0.0.0 -address=/d34rdvn2ky3gnm.cloudfront.net/0.0.0.0 -address=/d355vwft2pa8h6.cloudfront.net/0.0.0.0 -address=/d359wjs9dpy12d.cloudfront.net/0.0.0.0 -address=/d3a42c7xs4vn3.cloudfront.net/0.0.0.0 -address=/d3ahinqqx1dy5v.cloudfront.net/0.0.0.0 -address=/d3aiy6aqoa3ykz.cloudfront.net/0.0.0.0 -address=/d3al52d8cojds7.cloudfront.net/0.0.0.0 -address=/d3dytsf4vrjn5x.cloudfront.net/0.0.0.0 -address=/d3hitamb7drqut.cloudfront.net/0.0.0.0 -address=/d3hs51abvkuanv.cloudfront.net/0.0.0.0 -address=/d3l320urli0p1u.cloudfront.net/0.0.0.0 -address=/d3lvr7yuk4uaui.cloudfront.net/0.0.0.0 -address=/d3nvrqlo8rj1kw.cloudfront.net/0.0.0.0 -address=/d3pe8wzpurrzss.cloudfront.net/0.0.0.0 -address=/d3pkae9owd2lcf.cloudfront.net/0.0.0.0 -address=/d3q33rbmdkxzj.cloudfront.net/0.0.0.0 -address=/d3uqm14ppr8tkw.cloudfront.net/0.0.0.0 -address=/d3vpf6i51y286p.cloudfront.net/0.0.0.0 -address=/d4ngwggzm3w7j.cloudfront.net/0.0.0.0 -address=/d5pb47xzjz3fc.cloudfront.net/0.0.0.0 -address=/d63a3au5lqmtu.cloudfront.net/0.0.0.0 -address=/d6sav80kktzcx.cloudfront.net/0.0.0.0 -address=/da3uf5ucdz00u.cloudfront.net/0.0.0.0 -address=/dal9hkyfi0m0n.cloudfront.net/0.0.0.0 -address=/dart.clearchannel.com/0.0.0.0 -address=/dasfdasfasdf.no-ip.info/0.0.0.0 -address=/data.neuroxmedia.com/0.0.0.0 -address=/dbam.dashbida.com/0.0.0.0 -address=/dbcdqp72lzmvj.cloudfront.net/0.0.0.0 -address=/dc5k8fg5ioc8s.cloudfront.net/0.0.0.0 -address=/ddvfoj5yrl2oi.cloudfront.net/0.0.0.0 -address=/deacon.ghfkk.com/0.0.0.0 -address=/delivery-dev.thebloggernetwork.com/0.0.0.0 -address=/delivery.thebloggernetwork.com/0.0.0.0 -address=/dew9ckzjyt2gn.cloudfront.net/0.0.0.0 -address=/display.digitalriver.com/0.0.0.0 -address=/djr4k68f8n55o.cloudfront.net/0.0.0.0 -address=/djv99sxoqpv11.cloudfront.net/0.0.0.0 -address=/djz9es32qen64.cloudfront.net/0.0.0.0 -address=/dm0acvguygm9h.cloudfront.net/0.0.0.0 -address=/dmkdtkad2jyb9.cloudfront.net/0.0.0.0 -address=/dojx47ab4dyxi.cloudfront.net/0.0.0.0 -address=/dpsq2uzakdgqz.cloudfront.net/0.0.0.0 -address=/dqhi3ea93ztgv.cloudfront.net/0.0.0.0 -address=/dr3k6qonw2kee.cloudfront.net/0.0.0.0 -address=/dr8pk6ovub897.cloudfront.net/0.0.0.0 -address=/drf8e429z5jzt.cloudfront.net/0.0.0.0 -address=/ds02gfqy6io6i.cloudfront.net/0.0.0.0 -address=/dsh7ky7308k4b.cloudfront.net/0.0.0.0 -address=/dsie7h4lo9wxu.cloudfront.net/0.0.0.0 -address=/dtakdb1z5gq7e.cloudfront.net/0.0.0.0 -address=/dtrk.slimcdn.com/0.0.0.0 -address=/dtto8zfzskfoa.cloudfront.net/0.0.0.0 -address=/du2uh7rq0r0d3.cloudfront.net/0.0.0.0 -address=/duzt6rhr7wo8p.cloudfront.net/0.0.0.0 -address=/dv7t7qyvgyrt5.cloudfront.net/0.0.0.0 -address=/dvc8653ec6uyk.cloudfront.net/0.0.0.0 -address=/dvnafl0qtqz9k.cloudfront.net/0.0.0.0 -address=/dvt4pepo9om3r.cloudfront.net/0.0.0.0 -address=/dxprljqoay4rt.cloudfront.net/0.0.0.0 -address=/dybxezbel1g44.cloudfront.net/0.0.0.0 -address=/epowernetworktrackerimages.s3.amazonaws.com/0.0.0.0 -address=/euwidget.imshopping.com/0.0.0.0 -address=/events.kalooga.com/0.0.0.0 -address=/ff.doubleclick.net/0.0.0.0 -address=/gateway.fortunelounge.com/0.0.0.0 -address=/gateways.s3.amazonaws.com/0.0.0.0 -address=/geo.connexionsecure.com/0.0.0.0 -address=/geobanner.passion.com/0.0.0.0 -address=/gfaf-banners.s3.amazonaws.com/0.0.0.0 -address=/gg.caixin.com/0.0.0.0 -address=/homad-global-configs.schneevonmorgen.com/0.0.0.0 -address=/im.ov.yahoo.co.jp/0.0.0.0 -address=/indieclick.3janecdn.com/0.0.0.0 -address=/karma.mdpcdn.com/0.0.0.0 -address=/kbnetworkz.s3.amazonaws.com/0.0.0.0 -address=/leaddyno-client-images.s3.amazonaws.com/0.0.0.0 -address=/marketing.888.com/0.0.0.0 -address=/mb.zam.com/0.0.0.0 -address=/mbid.marfeelrev.com/0.0.0.0 -address=/medrx.telstra.com.au/0.0.0.0 -address=/network.aufeminin.com/0.0.0.0 -address=/network.business.com/0.0.0.0 -address=/ntvcld-a.akamaihd.net/0.0.0.0 -address=/oas.luxweb.com/0.0.0.0 -address=/odin.goo.mx/0.0.0.0 -address=/on.maxspeedcdn.com/0.0.0.0 -address=/ox-i.cordillera.tv/0.0.0.0 -address=/partner.bargaindomains.com/0.0.0.0 -address=/partner.catchy.com/0.0.0.0 -address=/partner.premiumdomains.com/0.0.0.0 -address=/partners.fshealth.com/0.0.0.0 -address=/partners.optiontide.com/0.0.0.0 -address=/partners.rochen.com/0.0.0.0 -address=/partners.sportingbet.com.au/0.0.0.0 -address=/partners.vouchedfor.co.uk/0.0.0.0 -address=/partners.xpertmarket.com/0.0.0.0 -address=/pb.s3wfg.com/0.0.0.0 -address=/priceinfo.comuv.com/0.0.0.0 -address=/promos.fling.com/0.0.0.0 -address=/promote.pair.com/0.0.0.0 -address=/promotions.iasbet.com/0.0.0.0 -address=/pub.admedia.io/0.0.0.0 -address=/pub.betclick.com/0.0.0.0 -address=/pubportal.brkmd.com/0.0.0.0 -address=/pubs.hiddennetwork.com/0.0.0.0 -address=/rack.bauermedia.co.uk/0.0.0.0 -address=/res3.feedsportal.com/0.0.0.0 -address=/rotabanner.kulichki.net/0.0.0.0 -address=/rotator.tradetracker.net/0.0.0.0 -address=/s-yoolk-banner-assets.yoolk.com/0.0.0.0 -address=/s-yoolk-billboard-assets.yoolk.com/0.0.0.0 -address=/secretmedia.s3.amazonaws.com/0.0.0.0 -address=/servedby.keygamesnetwork.com/0.0.0.0 -address=/sitescout-video-cdn.edgesuite.net/0.0.0.0 -address=/slot.union.ucweb.com/0.0.0.0 -address=/smart.styria-digital.com/0.0.0.0 -address=/smblock.s3.amazonaws.com/0.0.0.0 -address=/squarespace.evyy.net/0.0.0.0 -address=/stats.hosting24.com/0.0.0.0 -address=/stats.sitesuite.org/0.0.0.0 -address=/streaming.rtbiddingplatform.com/0.0.0.0 -address=/stuff-nzwhistleout.s3.amazonaws.com/0.0.0.0 -address=/survey.g.doubleclick.net/0.0.0.0 -address=/syndication.jsadapi.com/0.0.0.0 -address=/syndication1.viraladnetwork.net/0.0.0.0 -address=/tags.sprizzy.com/0.0.0.0 -address=/tags2.adshell.net/0.0.0.0 -address=/tap.more-results.net/0.0.0.0 -address=/ti.tradetracker.net/0.0.0.0 -address=/track.bcvcmedia.com/0.0.0.0 -address=/twinplan.com/0.0.0.0 -address=/utility.rogersmedia.com/0.0.0.0 -address=/vice-publishers-cdn.vice.com/0.0.0.0 -address=/web-jp.ad-v.jp/0.0.0.0 -address=/whistleout.s3.amazonaws.com/0.0.0.0 -address=/widget.crowdignite.com/0.0.0.0 -address=/widget.kelkoo.com/0.0.0.0 -address=/widget.raaze.com/0.0.0.0 -address=/widget.searchschoolsnetwork.com/0.0.0.0 -address=/widget.shopstyle.com.au/0.0.0.0 -address=/widget.solarquotes.com.au/0.0.0.0 -address=/widgets.fie-data.co.uk/0.0.0.0 -address=/widgets.realestate.com.au/0.0.0.0 -address=/wlpinnaclesports.eacdn.com/0.0.0.0 -address=/wtpn.twenga.co.uk/0.0.0.0 -address=/wtpn.twenga.de/0.0.0.0 -address=/yb.torchbrowser.com/0.0.0.0 -address=/yeas.yahoo.co.jp/0.0.0.0 -address=/yield-op-idsync.live.streamtheworld.com/0.0.0.0 -address=/zapads.zapak.com/0.0.0.0 -address=/d141wsrw9m4as6.cloudfront.net/0.0.0.0 -address=/d1bxkgbbc428vi.cloudfront.net/0.0.0.0 -address=/d1ilwohzbe4ao6.cloudfront.net/0.0.0.0 -address=/d1jnvfp2m6fzvq.cloudfront.net/0.0.0.0 -address=/d1n1ppeppre6d4.cloudfront.net/0.0.0.0 -address=/d1rjzrtsxlzawf.cloudfront.net/0.0.0.0 -address=/d1w24oanovvxvg.cloudfront.net/0.0.0.0 -address=/d22z575k8abudv.cloudfront.net/0.0.0.0 -address=/d3a49eam5ump99.cloudfront.net/0.0.0.0 -address=/d3b2hhehkqd158.cloudfront.net/0.0.0.0 -address=/d3kpkrgd3aj4o7.cloudfront.net/0.0.0.0 -address=/d3t3lxfqz2g5hs.cloudfront.net/0.0.0.0 -address=/dn3uy6cx65ujf.cloudfront.net/0.0.0.0 -address=/dpd9yiocsyy6p.cloudfront.net/0.0.0.0 -address=/du01z5hhojprz.cloudfront.net/0.0.0.0 -address=/dw9uc6c6b8nwx.cloudfront.net/0.0.0.0 -address=/dxkkb5tytkivf.cloudfront.net/0.0.0.0 -address=/iadc.qwapi.com/0.0.0.0 -address=/d3jgr4uve1d188.cloudfront.net/0.0.0.0 -address=/d3ujids68p6xmq.cloudfront.net/0.0.0.0 -address=/ad.duga.jp/0.0.0.0 -address=/ad.iloveinterracial.com/0.0.0.0 -address=/ads.videosz.com/0.0.0.0 -address=/affiliates.thrixxx.com/0.0.0.0 -address=/ard.sweetdiscreet.com/0.0.0.0 -address=/bannershotlink.perfectgonzo.com/0.0.0.0 -address=/blaaaa12.googlecode.com/0.0.0.0 -address=/br.blackfling.com/0.0.0.0 -address=/br.fling.com/0.0.0.0 -address=/br.realitykings.com/0.0.0.0 -address=/core-queerclick.netdna-ssl.com/0.0.0.0 -address=/cpm.amateurcommunity.com/0.0.0.0 -address=/d1mib12jcgwmnv.cloudfront.net/0.0.0.0 -address=/d3ud741uvs727m.cloudfront.net/0.0.0.0 -address=/dailyvideo.securejoin.com/0.0.0.0 -address=/desk.cmix.org/0.0.0.0 -address=/feeds.videosz.com/0.0.0.0 -address=/freexxxvideoclip.aebn.net/0.0.0.0 -address=/gashot.yurivideos.com/0.0.0.0 -address=/geo.cliphunter.com/0.0.0.0 -address=/geo.frtya.com/0.0.0.0 -address=/geo.frtyd.com/0.0.0.0 -address=/geobanner.adultfriendfinder.com/0.0.0.0 -address=/geobanner.alt.com/0.0.0.0 -address=/geobanner.socialflirt.com/0.0.0.0 -address=/in.zog.link/0.0.0.0 -address=/partners.pornerbros.com/0.0.0.0 -address=/pub.nakedreel.com/0.0.0.0 -address=/s1magnettvcom.maynemyltf.netdna-cdn.com/0.0.0.0 -address=/surv.xbizmedia.com/0.0.0.0 -address=/sweet.game-rust.ru/0.0.0.0 -address=/tm-offers.gamingadult.com/0.0.0.0 -address=/tool.acces-vod.com/0.0.0.0 -address=/widgets.comcontent.net/0.0.0.0 -address=/widgetssec.cam-content.com/0.0.0.0 -address=/wt.adtrue24.com/0.0.0.0 -address=/a.w3techs.com/0.0.0.0 -address=/ad.9animes.ru/0.0.0.0 -address=/ad.digitimes.com.tw/0.0.0.0 -address=/ad.itweb.co.za/0.0.0.0 -address=/ad.khan.co.kr/0.0.0.0 -address=/ad.kisscartoon.is/0.0.0.0 -address=/ad.search.ch/0.0.0.0 -address=/ad.spreaker.com/0.0.0.0 -address=/addirector.vindicosuite.com/0.0.0.0 -address=/ads.yahoo.com/0.0.0.0 -address=/ads.zynga.com/0.0.0.0 -address=/adserver.pandora.com/0.0.0.0 -address=/adss.yahoo.com/0.0.0.0 -address=/aggnr.groovesharks.org/0.0.0.0 -address=/as.inbox.com/0.0.0.0 -address=/ban.seriesonlinex.org/0.0.0.0 -address=/beap.gemini.yahoo.com/0.0.0.0 -address=/cad.donga.com/0.0.0.0 -address=/click.livedoor.com/0.0.0.0 -address=/collector.viki.io/0.0.0.0 -address=/content.streamplay.to/0.0.0.0 -address=/creatives.livejasmin.com/0.0.0.0 -address=/d10lumateci472.cloudfront.net/0.0.0.0 -address=/d2fbkzyicji7c4.cloudfront.net/0.0.0.0 -address=/d2na2p72vtqyok.cloudfront.net/0.0.0.0 -address=/d2uepos3ef6db0.cloudfront.net/0.0.0.0 -address=/d3asksgk2foh5m.cloudfront.net/0.0.0.0 -address=/dash.tmearn.com/0.0.0.0 -address=/dbs.autolatest.ro/0.0.0.0 -address=/delivery.smashing.services/0.0.0.0 -address=/djv99sxoqpv11.cloudfront.net/0.0.0.0 -address=/dkm6b5q0h53z4.cloudfront.net/0.0.0.0 -address=/fontent.streamp1ay.me/0.0.0.0 -address=/fun.wormania.io/0.0.0.0 -address=/fun1.arcadeprehacks.com/0.0.0.0 -address=/gen.etherscan.io/0.0.0.0 -address=/hawk.pcgamer.com/0.0.0.0 -address=/imgcache.sythe.org/0.0.0.0 -address=/iurhxzmr.ga.gfycat.com/0.0.0.0 -address=/mail-ads.google.com/0.0.0.0 -address=/mms.graziadaily.co.uk/0.0.0.0 -address=/nas1.flashx.net/0.0.0.0 -address=/nicoad.nicovideo.jp/0.0.0.0 -address=/pmm.people.com.cn/0.0.0.0 -address=/ssa.1337x.to/0.0.0.0 -address=/tag.vlitag.com/0.0.0.0 -address=/tradecraft.s.llnwi.net/0.0.0.0 -address=/urs.zdnet.com/0.0.0.0 -address=/wall.vgr.com/0.0.0.0 -address=/web.tmearn.com/0.0.0.0 -address=/ww2.gestyy.com/0.0.0.0 -address=/x.castanet.net/0.0.0.0 -address=/gontent.steamplay.me/0.0.0.0 -address=/hontent.steamplay.me/0.0.0.0 -address=/wontent.powvideo.net/0.0.0.0 -address=/yontent.powvideo.net/0.0.0.0 -address=/meta.streamcloud.eu/0.0.0.0 -address=/pub1.cope.es/0.0.0.0 -address=/a.eporner.com/0.0.0.0 -address=/a.heavy-r.com/0.0.0.0 -address=/a3.hotpornfile.org/0.0.0.0 -address=/ad.eporner.com/0.0.0.0 -address=/ad.thisav.com/0.0.0.0 -address=/affiliates.goodvibes.com/0.0.0.0 -address=/ashot.txxx.com/0.0.0.0 -address=/b.boyfriendtv.com/0.0.0.0 -address=/b.pornoxo.com/0.0.0.0 -address=/b.xcafe.com/0.0.0.0 -address=/banner1.pornhost.com/0.0.0.0 -address=/banners.cams.com/0.0.0.0 -address=/bnnr.pornpics.com/0.0.0.0 -address=/brcache.madthumbs.com/0.0.0.0 -address=/cf1c0.thisav.com/0.0.0.0 -address=/creatives.cliphunter.com/0.0.0.0 -address=/creatives.pichunter.com/0.0.0.0 -address=/d1wi563t0137vz.cloudfront.net/0.0.0.0 -address=/d2q52i8yx3j68p.cloudfront.net/0.0.0.0 -address=/d39hdzmeufnl50.cloudfront.net/0.0.0.0 -address=/delivery.porn.com/0.0.0.0 -address=/dildo.tnaflix.com/0.0.0.0 -address=/dot.eporner.com/0.0.0.0 -address=/dot2.eporner.com/0.0.0.0 -address=/dyn.empflix.com/0.0.0.0 -address=/dyn.tnaflix.com/0.0.0.0 -address=/exit.macandbumble.com/0.0.0.0 -address=/go.pornav.net/0.0.0.0 -address=/go.sexu.tv/0.0.0.0 -address=/go.strpjmp.com/0.0.0.0 -address=/lw1.cdmediaworld.com/0.0.0.0 -address=/madmen.alastonsuomi.com/0.0.0.0 -address=/myashot.txxx.com/0.0.0.0 -address=/partners.keezmovies.com/0.0.0.0 -address=/plx.porndig.com/0.0.0.0 -address=/pr-static.empflix.com/0.0.0.0 -address=/pr-static.tnaflix.com/0.0.0.0 -address=/px.boundhub.com/0.0.0.0 -address=/r.radikal.ru/0.0.0.0 -address=/rev.fapdu.com/0.0.0.0 -address=/site.img.4tube.com/0.0.0.0 -address=/static.kinghost.com/0.0.0.0 -address=/sub.avgle.com/0.0.0.0 -address=/tkn.4tube.com/0.0.0.0 -address=/tkn.fux.com/0.0.0.0 -address=/tkn.pornerbros.com/0.0.0.0 -address=/tkn.porntube.com/0.0.0.0 -address=/uuvm.pornpics.com/0.0.0.0 -address=/x.eroticity.net/0.0.0.0 -address=/x.vipergirls.to/0.0.0.0 diff --git a/package/lienol/luci-app-passwall/root/usr/share/passwall/rules/block_host b/package/lienol/luci-app-passwall/root/usr/share/passwall/rules/block_host deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/package/lienol/luci-app-passwall/root/usr/share/passwall/rules/block_ip b/package/lienol/luci-app-passwall/root/usr/share/passwall/rules/block_ip deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/package/lienol/luci-app-passwall/root/usr/share/passwall/rules/chnlist b/package/lienol/luci-app-passwall/root/usr/share/passwall/rules/chnlist deleted file mode 100644 index 8548c90b4d..0000000000 --- a/package/lienol/luci-app-passwall/root/usr/share/passwall/rules/chnlist +++ /dev/null @@ -1,70410 +0,0 @@ -0-100.com -0-6.com -0-gold.net -00.net -00042.com -0006266.com -0007.net -0008887.com -000dn.com -000e.com -000wx.com -001133.app -001cndc.com -001d.com -001daima.com -001en.com -001jm.com -001job.com -001kd.com -001pp.com -001tech.com -001town.com -001xin.com -002lzj.com -0033.com -0037wan.com -00394.net -003store.com -004218.com -0044sun.com -004678.com -005.tv -00518.org -00544.com -0056.cc -0061.com.au -00615.net -006163.com -007.mx -007856.com -00791.com -007hd.com -007manhua.com -007qu.com -007shoes.com -007swz.com -007swzz.com -007yx.com -008008008.cc -008008456.com -008008789.com -00817.com -0082tv.com -0082tv.net -008321.com -00852wm.com -00853.la -0086crane.com -0086l.com -0088-0880.com -0088dns.com -008gj.com -009.com -00934.com -0098118.com -00991901.com -0099524.com -00997708.com -009y.com -00bx.com -00cdn.com -00cf.com -00cha.com -00cha.net -00ic.com -00it.net -00ksw.net -00lewen.com -00red.com -00sy.com -00sy.net -00tera.com -00txt.com -01-123.com -01-cf.com -010123456.com -010155.net -0101shop.com -01095113.com -010bianhu.com -010bjzs.com -010byyy.com -010cns.com -010dsmzyy.com -010hetongls.com -010jianzhan.com -010jing-pc.com -010lf.com -0110m.com -0123401234.com -0123456789.biz -0123456789.com -012logo.com -01365.com -01368.com -01368u.com -013767.com -0138.com -013888.com -014.cc -0149.com -016272.com -0168.cc -016sf.com -0196.site -01bz.wang -01caijing.com -01faxing.com -01happy.com -01home.com -01hour.com -01hr.com -01hrheibei.com -01isp.com -01isp.net -01jzw.com -01ke.com -01ki.com -01p.com -01retail.com -01rv.com -01tao.com -01teacher.com -01tingshu.com -01ue.com -01w.com -01water.com -01wb.com -01wed.com -01yo.com -01yun.com -01zhuanche.com -020.com -020.net -020218.com -020banjia.net -020bom.com -020h.com -020job.com -020xueche.com -020yhy.com -020ym.com -020zp.net -021-atp.com -021-cz.com -021-tp.com -021-zszx.com -021.com -021.net -0214.com -0214vip.com -02156506666.net -02163.com -0218bt.com -021bense.com -021bike.net -021bolang.com -021clean.com -021dianyuan.com -021dqfm.com -021dzjx.com -021east.com -021fx.com -021gjhb.com -021hly.org -021ja.com -021jcw.com -021jingwei.com -021jingwu.com -021js.com -021lawfirm.com -021mingyi.com -021networks.com -021phone.com -021ren.com -021sports.com -021tk.com -021wudi.com -021yongzhuo.com -021zu.com -022003.com -022china.com -022ee.com -022gangban.com -022meishu.com -022net.com -022s.com -022sunny.com -022v.com -022xinniang.com -023086.com -0231230.com -02345678.com -023buy.com -023che.com -023cq.cc -023dir.com -023dns.com -023gayss.com -023gaywz.com -023gmdk.com -023lvyou.com -023sm.com -023up.com -023wg.com -023yts.com -023zp.com -0243811.com -0243855.com -0245.cc -0245.org -024888.net -02489.com -024anfang.com -024bj.com -024bxkj.com -024eps.com -024feida.com -024frde.com -024fuchan.com -024fuwu.com -024fzy.com -024grc.com -024heyi.com -024hh.com -024hp.com -024hpg.com -024huada.com -024zihai.com -024zol.com -024zxw.com -02516.com -025art.com -025ct.com -025ebaidu.com -025kaiyi.com -025nj.com -025sc.com -025xingshi.net -025xl.com -025zp.com -026idc.com -0270.cc -02712122.com -02727.com -02766667777.com -027accp.com -027aige.com -027art.com -027cgb.com -027chuxun.com -027cloud.com -027down.com -027eat.com -027fcyy.com -027hcss.com -027hhl.com -027hjw.com -027hpedu.com -027hpit.com -027htxt.com -027hxj.com -027hxzy.com -027hy.com -027idc.com -027jsxh.com -027jz.cc -027kingzone.com -027lyw.com -027one.com -027qyt.com -027qyy.com -027tc.net -027tianle.com -027tianlong.com -027tytpf.com -027wcbyy.com -027website.com -027wei.com -027xf.com -027yunwei.com -027yx.com -027zhan.com -027zpw.com -0283home.com -028aide.com -028brother.com -028hema.com -028hr.org -028ip.com -028kingdee.net -028kuaidai.com -028office.com -028pxw.com -029-zx.net -029080.com -029558.com -029900.com -029jiuda.com -029judao.com -029k.com -029lintong.com -029rencai.com -029shw.com -029weichen.com -029wsw.com -029yjy.com -029yljj.com -029yuezi.com -029zp.com -029zx.net -02edu.com -02kdid.com -02laser.com -02o.pw -02shu.cc -02shu.com -02wan.com -02wq.com -030303.com -030mall.com -0310520.com -0310it.com -0311wifi.com -0312of.com -0314.online -0315xl.com -0316.cc -031v.com -032069.com -0328.com -033033.com -0335e.com -0335wl.com -03365365.com -0337111.com -03412.com -03414.com -034666.com -0349.info -035110000.com -0351data.com -0351fdc.com -0352fang.com -0352g.com -0355fk.com -0356f.com -0357hz.com -0368.com -036yx.com -0370zc.com -0371wang.com -037201.com -037398.com -0375art.com -0376.net -0376news.com -0377cw.com -0378zz.com -0379city.com -0379home.com -0379pfw.com -03964.com -03dq.com -03k.org -03nq.com -0411.com -041188888.com -0411e.com -0411hd.com -041234b.com -0415gift.com -04168.com -0416u.com -0417gou.com -0418fc.com -0421wcbzk.com -0427.com -0430.com -0431cn.com -0437.com -0438news.com -044045.com -04486.com -04518888.com -0452e.com -0453.com -0455zd.com -0460.com -0470a.com -0470fcw.com -0471fcw.com -0472.com -0479xx.com -04wan.com -051058.com -0510syedu.com -0511w.com -0512118114.com -0512bis.com -0512fangchan.com -0512pearl.com -0512s.com -0512xiangcheng.com -0512zp.com -0513.net -0513.org -0513011.com -0513syedu.com -0513zs.com -0514.com -0514rj.com -051591.com -0515auto.com -0515syedu.com -0515yc.tv -051689.com -0516k.com -0517.net -0517999.com -0517cw.com -0517w.com -051891.com -0518njyy.com -0519114.net -051jk.com -05236.com -0523tx.net -0523zp.com -0523zz.com -05273.com -0527zz.com -052yx.com -0531.com -053135.com -0531jb.com -0531soso.com -0531welt.com -0531wt.com -0532.com -0533.com -0535-0411.com -0536qz.com -0537tt.com -0537yz.com -053c.com -054057.com -0543hr.com -0546dsw.com -0546fdc.com -0550.com -0550dx.com -055110.com -055178.com -0551fangchan.com -0551hfhybdf.com -0551hybdf.com -0551wl.com -0552jie.com -05532.com -0553fang.com -0553zsw.com -0554news.com -0554zp.com -0555dsw.com -0555fc.com -0558.la -0558zp.com -0559fc.com -0561house.com -0563fang.org -0563job.com -0564luan.com -0566cn.net -0566fc.com -0566job.com -0567.com -057.com -0570fc.com -0570zs.com -057191.com -0571dns.com -0571ok.com -0573fang.com -0573ren.com -0574bbs.com -0574nbjg.com -05752008.com -0575bbs.com -0575dsw.com -0575life.com -0575xf.com -0576dsw.com -0577-it.com -0577cnw.com -0577home.net -0577hr.com -0577job.com -0577qiche.com -0578rencai.com -0578zhaopin.com -0579com.com -0579dm.com -0579fw.com -0591job.com -05927.com -0592dsw.com -0592jj.com -0592xl.com -05935.com -0593666.com -0594.com -059400.com -0595job.com -0595rc.com -0596fc.com -0597kk.com -0597ok.com -0597seo.com -0597zp.com -0598777.com -0598job.com -0598rc.com -0599yx.com -05bk.com -05bq.com -05cg.com -05info.com -05sun.com -05vm.com -05wan.com -06000w.com -062616.com -063108.com -0632idc.com -0634.com -06362.com -065201.com -0660hf.com -0663.net -0663job.com -0668.com -068632.com -06abc.com -06climate.com -06dns.com -06game.com -06mz.com -06peng.com -07.la -070210.com -0704tv.com -0706hjkv.xyz -07073.com -07073h5.com -07073sy.com -07073vr.com -0707cdn.com -0710522.com -0712fang.com -0712zpw.com -071333.com -0713fang.com -0713hb.com -0714news.com -0715fc.com -0715rc.com -0715zp.com -0716fw.com -0716mr.com -07170.net -07177.com -0717ad.com -0718.cc -071811.cc -0719house.com -0722fc.com -0722h.com -0722zs.com -0724c.com -0728f.com -0730188.com -0730news.com -0730seo.com -073122.com -0731cfw.com -0731fdc.com -0731i.com -0731jiaju.com -0731job.com -0731pgy.com -0731rj.com -0731tg.com -0731wan.com -0731zcgs.com -0733news.com -0734zpw.com -0735.com -07358.com -0735ba.com -0735jz.com -0735zx.com -0735zz.com -0736fdc.com -0736zz.com -0737rencai.com -0738.cc -0738rc.com -0738www.com -0739tc.com -0739tt.com -073img.com -07430743.com -0744tv.com -0745tuan.com -0746news.com -0750rc.com -0752qc.com -0754news.com -0755400.com -0755888.com -0755bdqn.com -0755caibao.com -0755car.com -0755haoyu.com -0755hz.com -0755pr.com -0755rc.com -0755si.com -0755ws.com -0755zb.com -0756hhr.com -0756home.com -0756idc.com -0756seo.com -0756tong.com -0756zx.com -0757fc.com -0757p.com -0757rc.com -0758net.com -0759job.com -0759k.com -0759yc.com -0760.com -0760bw.com -0760rc.com -076299.com -0762uu.com -0763f.com -0763home.com -0763zuche.com -076650.com -0768.gd -0769che.com -0769net.com -0769sun.com -0769sx.com -0769yp.com -0771.tel -0771bc.com -0771rc.com -0772fang.com -0772job.com -0775code.com -0775fcw.com -0775jzw.com -077sblive.com -07818ff.com -07890.com -0791jxhw.com -0791look.com -0791quanquan.com -0792jj.net -0792u.com -079768.com -0797rs.com -07996a.com -079y.com -07cn.com -07jm.com -07ka.com -07ren.com -07swz.com -0813fs.com -0817tv.com -0818tuan.com -0826j.com -082808.com -0832h.com -0832mh.com -083332.com -0835.com -0835meiya.com -0838.com -0838che.com -0838live.com -0852diaoyu.com -0852e.com -0852job.com -0853rc.com -0854job.com -0855job.com -0856job.com -0857job.com -0859job.com -086580.com -0869a.com -086jx.com -086kd.com -086mai.com -08817k.com -08817y.com -08817z.com -088kkj.com -0890.com -08946.com -08952.com -0898.net -08980898.com -0898100.com -089858.com -0898888.com -0898cc.com -0898cfw.com -0898hq.com -0898mmf.com -0898qw.com -0898xbfc.com -089dns.com -089u.com -08an.com -08c6.com -08cdn.com -08cms.com -08px.com -090expo.com -0912app.com -0914cn.com -0915home.com -091601.com -0916auto.com -0917.com -0917e.com -0919123.com -093.tv -0931lanzhou.com -0937js.com -0938net.com -093nd9.com -09418.com -09451.com -094j35.com -095196555.com -0951job.com -0951lz.com -09635.com -09685.com -096hg.com -0982b.com -0991dj.com -0991net.com -0992.cc -099sky.com -09ge.com -09jz.com -09rw.com -09shijue.com -09t55.com -0bug.org -0car0.com -0cneu2.com -0ctrl.com -0d.work -0dayku.com -0dj.net -0du520.com -0duxs.com -0easy.com -0fenbei.com -0fw.net -0gouche.com -0gsc.com -0ju.cc -0kee.com -0quan8.com -0rg.pw -0s8s.com -0x0.biz -0x0.ooo -0x0d.im -0x100.club -0x3.me -0x5.me -0x6.me -0x7.me -0x9.me -0xaa55.com -0xff000000.com -0xffffff.org -0xsky.com -0xue.com -0y856.com -1-111-1.com -1-123.com -1-b.tc -1-cs.net -1-du.net -1-yuan.net -1.cc -1.cm -1.cms.s81c.com -1.www.s81c.com -10.com -100-tong.com -100.com -100.me -10000.com -10000.sh -10000idc.net -10000ja.net -10000job.com -10000link.com -10000shequ.com -10000tc.com -10000yao.com -10001wan.com -100024.xyz -10006.info -1000ci.net -1000eb.net -1000fr.net -1000kan.cc -1000phone.com -1000phone.net -1000plan.org -1000seo.com -1000thinktank.com -1000tm.net -1000tuan.com -1000uc.com -1000xuexi.com -1000zhu.com -10010.com -10010400.net -10010hb.net -10010js.com -10010ll.com -10010mx.com -10010nm.com -100135.com -1001g.com -1001hw.com -1001p.com -100580.com -100669.com -1008011.com -10086.win -1008610086.com -10086web.com -100afrc.com -100allin.com -100alpha.com -100ask.net -100ask.org -100audio.com -100ayrc.com -100b.cc -100ben.net -100bt.com -100chou.com -100cjc.com -100credit.com -100cyrc.com -100dangong.com -100data.com -100dnrc.com -100du.com -100dyrc.com -100e.com -100ehui.com -100eshu.com -100exam.com -100fang.com -100font.com -100ftv.com -100hcrc.com -100hdy.com -100how.com -100ip.net -100jiapu.com -100kk.com -100ksw.com -100lnrc.com -100loujia.com -100lw.com -100market.net -100md.com -100mian.com -100msh.net -100ndrc.com -100niangudu.com -100nike.com -100njz.com -100nkrc.com -100pd.cc -100pd.com -100ppi.com -100qnrc.com -100rd.com -100rjrc.com -100run.com -100scrc.com -100shop.com -100skin.com -100steps.net -100stone.com -100sucai.com -100szy.com -100t.com -100tal.com -100tmt.com -100toutiao.com -100try.com -100txt.com -100txy.com -100wa.com -100weidu.com -100wen.cc -100wen.com -100wsanguo.com -100x100w.com -100xfrc.com -100xgrc.com -100xhs.com -100xiao.com -100xin.com -100xs.com -100xuexi.com -100xwrc.com -100ydrc.com -100yfrc.com -100yigui.com -100yingcai.com -100yiyao.com -100yue.com -100yxrc.com -100zhuang.com -100zp.com -101.com -10100000.com -10101111.com -10101111cdn.com -1010jiajiao.com -1010jz.com -1010pic.com -1010school.com -1010sh.com -101505.com -10155.com -1015600.com -10185.com -101hr.com -101jiajiao.com -101jm.net -101ms.com -101weiqi.com -1020m.com -1024.com -1024.ink -1024ie.com -1024nic.com -1024sj.com -1024ss.com -1024tools.com -10260.com -102cw.com -102no.com -102pay.com -103.com -1030car.com -103153.com -10333.com -1035.mobi -1040jy.com -10419.net -1048yy.com -105a.com -105mr.com -105zx.com -106.com -10639888.com -1065m.com -106666.cc -106666c.com -106666d.com -1066888.com -106903.com -1073.com -107788.com -107cine.com -107room.com -1080prmvb.com -108101.xyz -108105.xyz -108198.com -10852a.com -10865.com -108cun.com -108js.com -108pk.com -108qi.com -108sq.com -108tian.com -109.com -10909.com -1090ys.com -109814.com -109863.com -109876543210.com -10bests.com -10besty.com -10danteng.com -10fang.com -10gt.com -10hghg.com -10huan.com -10idc.com -10isp.com -10min.club -10moons.com -10pinping.com -10pkpk.com -10qianwan.com -10s1.com -10sea.com -10soo.com -10tiao.com -10vps.com -10yan.com -10yougame.com -10zk.com -11.org -11.vc -110.com -11000011.com -110hack.com -110kj.com -110monitor.com -110tm.com -1111.buzz -1111.com -111111111.com -11111111234567.com -11111s.info -111155268.com -1111biao.com -1113.cc -11160066.com -1116yl.com -1117797.com -111cn.net -111com.net -111g.com -111jz.com -111qqz.com -111yao.com -112112.com -1122.com -11222.com -1122dh.com -1123095.com -1124.cc -1128.org -112812.com -1128job.com -112seo.com -112wan.com -1131.cc -11315.com -11320.com -1133.cc -113989.com -113ya.com -114-91.com -114.114.114.114 -1140086.com -114160.com -11467.com -114admall.com -114best.com -114cb.com -114cbd.com -114chn.com -114desk.com -114dev.com -114dg.com -114dhc.com -114dns.com -114dns.net -114god.com -114hrb.com -114huoche.com -114hzw.com -114ic.com -114ic.net -114jc.com -114jcw.com -114jia.net -114la.com -114ljc.com -114mall.com -114menhu.com -114mo.com -114my.net -114oc.com -114park.com -114photo.com -114piaowu.com -114pifaa.com -114pinpai.com -114px.com -114qy.com -114s.com -114sf.com -114shouji.com -114study.com -114tjsc.com -114work.com -114xia.com -114yygh.com -114zhibo.com -114zpw.com -114zw.la -114zw.org -115.com -11544.com -1155.com -1155q.com -115800.com -1158pk.com -115cdn.net -115img.com -115jk.com -115z.com -1163.com -1166.com -11665.com -11684.com -116cd.com -116kj.com -116yx.com -11773.com -11777msc.com -117play.com -117show.com -118114.net -1185050.com -1188.com -1189.tv -118cy.com -118jm.com -118pan.com -118qikan.com -118study.com -118wa.com -119.cc -119120.org -1194229.com -119958.com -119hn.com -119tx.com -119you.com -11ads.com -11chuangye.com -11dns.com -11dream.net -11dy.net -11fldxn.com -11flow.com -11gai.com -11h5.com -11job.com -11k.cc -11kf.net -11lizhi.com -11lx.com -11my.net -11pdf.com -11player.com -11qp94.com -11space.com -11sun.com -11wyx.com -11xotn7p.com -11yuanma.com -11ziyun.com -120-job.com -120-news.com -120.net -12011.org -120185.com -120444.com -120ask.com -120askimages.com -120bjgcyy.org -120btc.com -120dxb.com -120fd.com -120gz.com -120hpyy.com -120kaoshi.com -120kid.com -120kq.com -120top.com -120w.info -120x.net -121121.net -12114job.com -12114rc.com -1212.com -12120.net -1213.me -121314.com -121ask.com -121dian.com -121down.com -121mu.com -121xia.com -121xz.com -122119.com -12225.com -12226.com -12227.com -122park.com -123-789.com -123-biyezheng.org -123.cc -123.com -12301china.com -12306.com -12306bypass.com -12308.com -123123.net -12317.com -12317wan.com -1231818.com -12333.com -12333ask.com -12333sb.com -12333si.com -1234.cx -1234001.com -1234365r.com -123456.la -123456789.tv -12345good.com -12345good.net -12345szzx.com -1234866.com -12349.net -1234biao.com -1234i.com -1234n.com -1234wu.com -1234wu.net -1234ye.com -1234yes.com -12354.com -12355.net -1236.com -12365auto.com -12366.com -12366.net -12366ca.com -12366cn.com -12366ns.com -123ad.com -123admin.com -123aoe.com -123baofeng.com -123bo.com -123buyu.com -123buyu.net -123cha.com -123chaogu.com -123du.cc -123ems.com -123fc.com -123haitao.com -123hala.com -123hao.com -123hdp.com -123huodong.com -123hw.com -123ku.com -123leyuan.com -123lihun.com -123lvxing.com -123meiyan.com -123nice.net -123novel.com -123qibu.com -123qy.com -123slg.com -123ths.com -123u.com -123wangsu.com -123webgame.com -123xun.com -123yingyu.com -125.la -12530.com -12540.org -12580.com -12580.net -12580.tv -12580emall.com -12580jnh.com -12580study.com -12581258.com -125a.net -125edu.com -125job.com -125mx.com -125p.com -125uu.com -125visa.com -125y.com -126.am -126.com -126.fm -126.la -126.net -126blog.com -126doc.com -126g.com -126qiye.com -126shu.com -126ts.com -126x.com -126z.net -127.net -1278721.com -12799.com -127tv.com -127v.com -127xx.com -128058.com -128456.com -1288.tv -128ic.com -128qd.com -128uu.com -12999.com -129w.com -12df3.com -12edu.com -12gang.com -12h5.com -12jn.com -12ky.com -12pk.com -12sporting.com -12tiku.com -12yao.com -12yc.cc -12ym.com -12ystar.com -12zw.com -13.gs -130158.com -131.com -13112.com -1314520sz.com -131458.com -1314mylove.com -1314study.com -1314wallet.com -1314zf.com -131cc.com -131qz.com -131zy.net -1322.com -132lawyer.com -13322.com -13377608388.com -133998.com -133china.com -133jz.com -13400.com -13482896776.com -135-139.com -135-cdn.com -135031.com -135198.net -135309.com -135650.com -1356789.com -1356net.com -1357g.com -135958.com -135995.com -135bianjiqi.com -135box.com -135editor.com -135edu.com -135fa.com -135plat.com -135top.com -135yuedu.com -136.com -1360.com -13610a.com -136136.com -13636.com -1365tu.com -136fc.com -136hr.com -13707.net -13720.com -1377.com -137home.com -13800.net -138085.com -138109.com -138292.com -1388012.com -138gzs.com -138jm.com -138top.com -138txt.com -138vps.com -139.com -139018.com -1391.com -13910.com -139130.com -139135.com -1392189.com -1392233.com -13937180868.com -13973.com -1398.org -139cai.com -139down.com -139life.com -139shop.com -139shu.com -139site.com -139talk.com -139w.com -139wanke.com -139y.com -139zhuti.com -13cg.com -13cr.com -13ddd.com -13ejob.com -13fuwu.com -13gm.com -13hangpifa.com -13ie.com -13mobi.com -13ww.net -13xiaoshuoa.com -13yx.com -140414.com -140ed8.com -1415926.com -1415926.mobi -1415926pi.com -14294.com -143573.com -14498.com -144n.com -144yd.com -1451cn.com -14583.com -147xiaoshuo.com -147xs.com -147xs.org -147xz.com -148-law.com -14866.com -1488.com -148com.com -148la.com -14hj.com -14xd.com -14zhu.com -150072.com -150075.com -1502828.com -150cn.com -151.hk -15111223344.com -15153.com -15166.com -151733.com -1518.com -151kan.com -151web.com -15211223344.com -152500.com -1529.org -15311223344.com -153g.net -1545ts.com -155.com -155175.com -15595.com -155idc.com -156580.com -15666.com -156zy.com -157120.com -1586f.com -1588.tv -15880.com -158c.com -158jixie.com -159.com -15cdn.com -15daili.com -15gg.com -15gift.com -15hn.com -15hr.com -15in.com -15lu.com -15ms.com -15pb.cc -15shu.net -15sing.com -15solo.com -15tianqi.com -15w.com -15wz.com -15xdd.com -15xs.com -15xsw.net -15yan.com -15yc.com -15yl.com -160.com -160.me -160015.com -16086371--c1.com -160edu.net -160yx.com -161580.com -1616.net -16163.com -1616dh.com -1616n.com -1618.com -161856.com -161gg.com -162.com -1626.com -1629hb.com -163.cm -163.com -163.fm -163.gg -163.lu -163.net -16307.com -1633.com -1633d.com -163663.com -163686.com -163cdn.com -163cp.com -163cs.com -163data.net -163fen.com -163gq.com -163jiasu.com -163k.cc -163k.com -163lady.com -163mu.com -163ns.com -163pinglun.com -163py.com -163ren.com -163sncn.com -163wh.com -163yu.com -163yun.com -164580.com -16466.com -165123.com -16587.com -16595.com -166.com -166.net -166015.com -166161.com -166396.com -1666.com -1668g.com -166cai.com -166ks.net -166sh.com -166xs.cc -166xs.com -166zw.com -16768.com -16789.net -16816.com -16831522.com -16838.com -168393.com -1684.cc -1684sm.com -1688.com -16881616.com -16885.com -16886000.com -16888.com -1688988.com -1688cdn.com -1688eric.com -1688gd.com -1688la.com -1688na.com -1688s.com -1688yinhua.com -1688zhuce.com -16899168.com -168cb.com -168chaogu.com -168dc.com -168dg.com -168dns.com -168f.info -168fff.com -168g.com -168hs.com -168huoche.com -168job.com -168kk.com -168kn.com -168lyq.com -168pd.com -168rc.com -168rcw.com -168tcw.com -168tea.com -168tex.com -168tochina.com -168w.cc -168yyzj.com -168zcw.com -169.com -169163.com -169369.com -16999.com -169gold.net -169it.com -169kang.com -169qk.com -169t.com -169vv.com -16app.tv -16boke.com -16dy.com -16fan.com -16fenqi.com -16game.net -16hyt.com -16i.cc -16ker.com -16kxsw.com -16lao.com -16lo.com -16manhua.com -16p.com -16pic.com -16rd.com -16sucai.com -16tree.com -16tz.com -16wl.cc -16xcw.com -16xx8.com -16xz.com -16zhan.com -17.com -170.com -17025.org -170hi.com -170i.com -170mv.com -170nsb.com -170tao.com -17117a.com -17167.com -1716dy.com -17173.com -17173cdn.com -17173ie.com -17173v.com -17173yx.com -1717518.com -1717ba.com -1717kf.com -1717pk.com -1717y.net -1717zy.com -1718001.com -1718china.com -1718world.com -171tax.com -171xs.com -171yxw.com -171zz.com -17207.com -172210.com -172222.com -17284.net -172tt.com -172xiaoyuan.com -173.com -1732.com -1732.net -17348.com -17350.com -17351.com -17369.com -173daxue.com -173eg.com -173fc.com -173funny.com -173iot.com -173kan.com -173kw.com -173on.com -173sy.com -173um.com -173uu.com -173yx.net -173zy.com -17439999.com -17446.com -17558.net -17566.com -1758.com -175club.com -175game.com -175ha.com -175kh.com -175pt.com -175pt.net -175wan.com -175wx.com -17611.com -176616.com -17666.mobi -17673.com -1768.com -176878.com -176quan.com -176vr.com -1773.com -17773d.com -1778.com -177817.com -177mh.net -178-go.com -178.com -178198.com -178448.com -178517.com -1787.ink -178800.cc -17888.com -1789a.com -178bird.com -178bit.com -178du.com -178hui.com -178linux.com -178online.com -178pt.com -178rw.com -178yr.com -179.com -179179.com -17937.net -1794game.com -1797wan.com -17986.net -17989.com -17admob.com -17ai.me -17avr.com -17b.net -17bang.ren -17bdc.com -17bianji.com -17byh.com -17cai.com -17caifu.com -17cdn.com -17ce.com -17chuang.cc -17coding.info -17cx.com -17daili.com -17dao.com -17dap.com -17dm.com -17doubao.com -17dp.com -17emarketing.com -17fanwen.com -17fee.com -17fengguo.com -17fengyou.com -17fifa.com -17firefox.com -17font.com -17forex.com -17g.com -17game.com -17gaoda.com -17getfun.com -17gwx.com -17haibao.com -17haoyun.com -17heli.com -17house.com -17hpl.com -17huang.com -17itou.com -17ivr.com -17jiaoyu.com -17jita.com -17k.com -17kanzb.com -17kgk.com -17kgl.com -17kjs.com -17kk.cc -17koko.com -17kouyu.com -17kshu.net -17kuxun.com -17kxgame.com -17kxs8.com -17kyun.com -17kzy.com -17liansuo.com -17liuxue.com -17ll.com -17luyouqi.com -17m3.com -17maimaimai.com -17meiwen.com -17mf.com -17miyou.com -17mqw.com -17mr.org -17ms.com -17neo.com -17oh.com -17ok.com -17oko.com -17palyba.com -17pr.com -17pxs.com -17python.com -17qcc.com -17qq.com -17qread.com -17rd.com -17rd.net -17read.com -17sct.com -17shengzhuan.com -17shouhui.com -17shuwu.com -17sucai.com -17syi.com -17sysj.com -17tanwan.com -17taotaoa.com -17taotaob.com -17taotaoba.com -17taotaoc.com -17tcw.com -17tigan.com -17track.net -17tui.cc -17tx.com -17u.com -17u.net -17u1u.com -17u7.com -17ugo.com -17uhui.com -17uhui.net -17ukulele.com -17uoo.com -17usoft.com -17usoft.net -17uxi.com -17v5.com -17vape.com -17vsell.com -17wan.la -17wan7.com -17wanba.com -17wanxiao.com -17wclass.com -17weike.com -17weixing.com -17wendao.com -17win.com -17ww.cc -17xgame.com -17xie.com -17xlm.com -17xsj.com -17xueba.com -17xxl.com -17ya.com -17yaoqu.com -17yc.com -17ym.org -17you.com -17yucai.com -17yund.com -17yy.com -17yyba.com -17zhaogong.com -17zhidao.com -17zhiliao.com -17zhuangxiu.com -17ziti.com -17zixue.com -17zub.com -17zuoye.com -17zuoye.net -17zwd.com -18008888338.com -180102.com -18095.com -181230.com -18183.com -181839.com -1818hm.com -1818nic.com -181ps.com -181ue.com -182208.com -183me.com -183post.com -183read.com -18488.com -185185.com -186078.com -1864445.com -1865u.com -1866.tv -18665348887.com -186688.com -1872.net -187801.com -188.com -188158.com -1884933.com -18856.com -1886zuche.com -1888.com.mo -188963.com -188app.xyz -188bifen.com -188cf.net -188diaoche.com -188doc.com -188hi.com -188lanxi.com -188mb.com -188naicha.com -188play.com -188seo.com -188soft.com -188wan.com -188yd.com -189.sh -1892139.com -1895m.com -189cha.com -189cube.com -189ebuy.com -189key.com -189qas.com -189rc.com -189read.com -189read.net -189sec.com -189share.com -189smarthome.com -189store.com -189works.com -189yo.com -189young.com -18ca.com -18caijing.com -18chonglou.com -18cr2ni4w.org -18dao.com -18dao.org -18daxue.com -18dx.com -18guanjia.com -18heat.com -18kf.net -18ladys.com -18link.com -18lipin.com -18o8.com -18ph.com -18qiang.com -18shuwu.com -18touch.com -18vps.com -18wk.com -18xs.org -18xsw.org -18yangzhi.com -18yax.com -18yl.com -18zg.com -1905.com -1905kk.com -190757.com -1909.tv -19196.com -1919game.net -192ly.com -1931.com -1937cn.com -193839.com -193sa.com -1947.cc -1949idc.com -195155.com -195855.com -19687.com -197946.com -197a.cc -197c.com -198174.com -198254.com -19830102.com -19831110.com -198358.com -198424.com -198503.xyz -198526.com -198526.net -1985t.com -1987.name -1988.tv -1988012.com -19888.tv -1988zp.com -198game.com -198game.net -198w.net -1992789.com -199508.com -1997sty.com -1998mall.com -1999019.com -1999dns.com -1999year.com -199cjcy.com -199it.com -199u2.com -199yt.com -199zw.com -19kan.com -19lou.com -19lou.tw -19mi.net -19ued.com -19where.com -19xsf.com -19yxw.com -19zhan.com -1an.com -1aq.com -1b23.com -1biaozhun.com -1biqu.com -1biquge.com -1bus.net -1cae.com -1caifu.com -1caitong.com -1cbn.com -1checker.com -1cloudsp.com -1cnmedia.com -1cno.com -1cnw.com -1d1d100.com -1dao99.com -1dfa.com -1dian0.com -1diaocha.com -1diary.me -1domedia.com -1drj.com -1drv.ws -1dufish.com -1duhy.com -1dume.com -1dusou.com -1dutm.com -1f11.com -1fenda.com -1fqw.com -1fx.cc -1g1g.com -1g31.com -1gangting.com -1gbru.com -1gesem.com -1ggame.com -1gjh.com -1gsoft.net -1hcang.com -1hhd.com -1hkt.com -1huamu.com -1i580.com -1iptv.com -1j1x.net -1jiaa.com -1jiajie.com -1jian.fun -1juzi.com -1k2k.com -1ka123.com -1kapp.com -1kapp.net -1ke.net -1kejian.com -1kg.org -1kj.com -1kj.tv -1kkk.com -1kmxc.com -1kongzhifa.com -1ksz.com -1kuang.com -1kx.me -1kxun.com -1ky.biz -1lan.tv -1lewen.com -1look.tv -1lou.com -1lzs.com -1m.net -1m3d.com -1m85.com -1mall.com -1mao.cc -1mayi.com -1meiyiliao.com -1mfc.com -1mfg.com -1miba.com -1mifudao.com -1mingpian.com -1mishu.com -1mit.com -1mm8.com -1mod.org -1more.com -1mpi.com -1mtime.com -1mushroom.com -1mxian.com -1n11.com -1nami.com -1news.cc -1nongjing.com -1nsou.com -1nyz.com -1o26.com -1p1g.com -1peixun.com -1pm2.com -1ppt.com -1px.wang -1q2q.com -1qfa.com -1qianbao.com -1qq.me -1qwe3r.com -1qyl.com -1r1g.com -1rtb.com -1safety.cc -1sapp.com -1shang.com -1shangbiao.com -1sheng.com -1shipin.net -1shoucang.com -1sj.tv -1sm23.com -1sohu.com -1speaking.com -1stchip.com -1stjc.com -1suplayer.me -1t.io -1t1t.com -1tai.com -1tdw.com -1techan.com -1textile.com -1thcity.com -1thx.com -1tieba.com -1ting.com -1tjob.com -1tong.com -1tu-design.com -1tu.com -1tu1.com -1uke.com -1uuc.com -1v1offcn.com -1vp.me -1wabao.com -1wandian.com -1wang.com -1wangyou.com -1wii.com -1x3x.com -1xbbs.com -1xiezuo.com -1y.com -1y0g.com -1y2y.com -1yabc.com -1yaoda.com -1yb.co -1yee.com -1ykh.com -1yltao.com -1yuanzheng.com -1yun.cc -1yyg.com -1zhangdan.com -1zhanok.com -1zhao.org -1zhe.com -1zhengji.com -1ziyou.com -1zjob.com -1zr.com -1zsoft.com -1zu.com -1zw.com -2-01-5830-0005.cdx.cedexis.net -2-46.com -2-class.com -2-mm.net -2.gy -20.com -200.net -200.sh -2000200.com -2000888.com -2000dns.com -2000new.com -2000y.net -2002000.xyz -200218.com -2003dns.com -20063365.com -2006q.com -2008php.com -2008red.com -2008zjj.com -2009.name -200call.com -200tc.com -200wan.com -200y.com -201061.com -2011mv.net -2011n.com -201201.com -2012ccfa.com -2013xp.com -2014.mobi -2014w7.com -201551.com -2015huo.com -2016ruanwen.com -2016win10.com -20174555.com -20176699.com -20180719.com -2018jsybh.com -2018waipan.com -2018zjjly.com -2019ayaya.com -2019cdac.com -2019zjj.com -202030.com -202096e.com -2020zjj.com -2029.cc -202m.com -202wan.com -204801.xyz -2048sj.com -204u.com -206dy.com -2088062.com -2088063.com -208xs.com -2095114.com -20biquge.com -20ju.com -20qu.com -20tc.com -20wx.com -20xue.com -20z.com -21-mars.com -21-rent.com -21-sun.com -210080.com -2100book.com -2100xs.com -210997.com -210z.com -2110000.com -2114.com -2115.com -211600.com -211ic.com -211lx.com -211n.com -212300.com -2125.com -21263.net -2128.net -2133.com -2144.com -2144gy.com -2146677.com -214yx.com -2155.com -217.net -217play.com -217wo.com -218318.com -218996.com -2197079.com -21bcr.com -21bowu.com -21cake.com -21cbr.com -21ccnn.com -21cd.com -21ce.cc -21cn.com -21cn.net -21cnev.com -21cnimg.com -21cnjy.com -21cnjy.net -21cnlunwen.com -21cos.com -21cp.cc -21cp.com -21ctest.com -21dagong.com -21datasheet.com -21dianyuan.com -21edu8.com -21educ.com -21ejob.com -21epub.com -21fid.com -21food.com -21hh.com -21hubei.com -21hulian.com -21ic.com -21ic.org -21icsearch.com -21ido.com -21jingji.com -21jrr.com -21js.com -21kan.com -21ks.net -21kunpeng.com -21ld.com -21maoyi.com -21mcu.com -21mmo.com -21momo.com -21muwu.com -21na.com -21nowart.com -21ou.com -21our.com -21part.com -21qa.net -21qphr.com -21rcw.com -21rv.com -21shhr.com -21shipin.com -21shte.net -21smov.com -21so.com -21softs.com -21spv.com -21sq.org -21tb.com -21tea.com -21tjsports.com -21tx.com -21tyn.com -21ukedu.com -21uv.com -21vbluecloud.com -21viacloud.com -21vianet.com -21voa.com -21wecan.com -21wenju.com -21wmd.com -21ww.cc -21xc.com -21xianhua.com -21xuema.com -21yinxiang.com -21yod.com -21yq.com -21yunwei.com -21zbs.com -21zixun.com -21znw.com -22-30.com -22-dns.com -22.com -221234.xyz -2213.com -221316.com -221400job.com -22145.com -2217.com -221700.com -222.com -222255268.com -222bz.com -222i.net -223.so -22332008.com -22333.fun -2239.com -224.com -2243.com -22442400.com -224700.com -224922.com -225721.com -2258.com -22588888.com -2265.com -226500.com -226531.com -226y.com -2280.com -2281wa.ren -228445.com -2288.org -228y.com -2295.com -2298.com -22baobei.com -22dm.com -22doc.com -22edu.com -22evil.com -22ff.com -22hd.com -22hyk.com -22ja.com -22k9.com -22kbw.com -22lianmeng.com -22lrc.com -22m6.com -22mt.in -22net.com -22plc.com -22shop.com -22sp.com -22tianbo.com -22vd.com -22zryx.com -22zw.com -22zy.net -23-01.com -2300sjz.com -230596.com -230tm.com -231122.com -2323u.com -2323wan.com -232485.com -232929.com -233.com -233000.com -2333u.com -23356.com -233863.com -2339.com -233py.com -233wo.com -233xiao.com -233xyx.com -2344.com -2345.cc -2345.com -2345.gd -2345.net -2345.org -23456v.com -2345a.com -2345ac.com -2345cdn.net -2345daohang.com -2345download.com -2345ff.com -2345kankan.com -2345licai.com -234du.com -236400.com -2366.com -2366app.com -23673.com -237.cc -237y.com -2380.ml -238200.com -239900.com -23bei.com -23book.com -23class.com -23code.com -23cpc.com -23do.com -23du.com -23ee.net -23hh.net -23job.net -23juqing.com -23kmm.com -23ks.com -23lvxing.com -23qb.com -23qb.net -23txt.com -23us.cc -23us.la -23us.so -23us.tv -23us23us.com -23uscom.com -23wow.com -23wx.cc -23wx.la -23wxw.com -23xs.cc -23xs.tv -23xsba.cc -23xsw.cc -23yy.com -240yx.com -243ty.com -2455000.com -246546.com -246ys.com -2478.com -2481e.com -248xyx.com -249581.com -24beta.com -24haowan.com -24hmb.com -24home.com -24jz.com -24k99.com -24ker.com -24korange.com -24kplus.com -24kwx.com -24maker.com -24money.com -24om.com -24pay.net -24timemap.com -24u7tos.com -24xin.com -2500.tv -25000li.com -2500city.com -2500sz.com -250sy.cc -251ai.com -2526game.com -2529.com -252ai.com -252yy.net -253.com -253952.com -253u.com -2541.com -254game.com -255616.com -25591.com -2566u8.com -256app.com -256game.com -25752.com -257ai.com -258.com -258288.com -25847.com -25863.com -2588.tv -25892.com -258c31.com -258ch.com -258fuwu.com -258jituan.com -258sd.com -258zw.com -25992.com -259go.com -25az.com -25djd.com -25dx.com -25game.com -25ku.com -25mao.com -25nc.com -25pp.com -25pyg.com -25un.com -25wy.com -25xm.com -25xt.com -25yi.com -25yz.com -260.net -261340.com -263.com -263.net -263em.com -263fc.com -263idc.com -263idc.net -263vps.com -263xmail.com -263y.com -263ytx.com -263zw.com -264006.com -264434.com -265.com -265660.com -26595.com -265g.com -265o.com -265ps.com -265tv.com -266555c.com -266wan.com -2678.com -267gg.com -26830.com -2686.com -2688.com -268888.net -268v.com -269.net -26923.com -26abc.com -26ef.com -26host.com -26joy.com -26ksw.com -26lady.com -26tc.com -26wd.com -26youxi.com -26yx.com -270top.com -2718037.com -27270.com -2727u.com -273u.com -275st.com -277sy.com -27844b.com -2799web.com -279wo.com -27aichi.com -27dt.com -27dy.com -27dyy.com -27k.cc -27l.com -27lmfq.com -27lvpai.com -27meng.com -27ws.com -27yx.com -28.com -2800.so -280xs.com -281010.com -28123.com -2828dy.com -28493.com -285868.com -2858999.com -285u.com -286sbc.com -288288dy.com -288609.com -288966.com -288idc.com -289.com -2898.com -28beiduo.com -28hotel.com -28jhw.org -28ka.com -28khy.com -28pifa.com -28rv.com -28sn.com -28tui.com -28u.org -28weixinqun.com -28xg.com -28xl.com -28y.com -28yj.com -2918.com -29293.com -2929gou.com -293.net -29365.bet -2952.cc -29663.com -296u.com -29797.com -298.name -2980.com -2981.com -298app1.com -2990.com -299035.com -299906.com -29dnue.com -29gl.com -29kaoshi.com -29xf.com -29yx.com -2abc8.com -2av7.com -2b9a2.com -2baxb.me -2bkw.com -2brui.com -2btu.com -2caipiao.com -2ccc.com -2ch.lt -2chcn.com -2cloo.com -2cname.com -2cp.com -2cq.com -2cto.com -2cy.news -2cycd.com -2cyxw.com -2cyzx.com -2d3d5d.net -2dan.cc -2danji.com -2days.org -2df.me -2dfire.com -2di.cc -2dianying.net -2djgame.net -2droom.com -2du.net -2dyou.com -2f.com -2fc5.com -2fz1.com -2gei.com -2gxw.com -2hainan.com -2hanju.com -2haohr.com -2heng.xin -2hua.com -2i0vw.com -2ibook.com -2ic.cc -2ita.com -2j88.com -2jianli.com -2jsu2.com -2k2k.cc -2k2k.com -2kandy.com -2ktq.com -2kz.net -2liang.net -2lieqi.com -2m2j.com -2mdn.net -2mjob.com -2mould.com -2ndmoon.net -2or3m.com -2p.com -2pcdn.com -2pjob.com -2pmob.com -2q10.com -2q1q.com -2qbb.com -2r3r.com -2r9qgy.com -2rich.net -2seachbusiness.com -2shihui.net -2shoujie.com -2shu8.cc -2shubao.com -2sitebbs.com -2smtc.com -2sx.net -2tianxin.com -2tudy.com -2tx.com -2uxs.com -2v8d.com -2vc00.com -2w.cm -2weima.com -2xiazai.com -2y9y.com -2ysfw5hz4.pw -2yuanma.com -2yun.com -2yup.com -2zfzly.com -2zhk.com -2zimu.com -2zzzzzz.com -3-ddesignsolutions.com -30.com -30.net -3000.com -300011facai.xyz -300033.info -3000api.com -3000idc.com -3000soft.net -3000test.com -3000yj.com -3001.net -300113.com -300400.net -300avs.com -300hu.com -300p.com -300ppt.com -300zi.com -301688.com -301773.com -301mba.com -301nn.com -301zhuanfa.com -3023.com -3033c.com -30556.com -307760.com -308308.com -309edu.com -309yy.com -30c.org -30cgy.com -30cn.net -30dj.com -30ka.com -30nl.net -30play.com -30px.com -30tqyb.com -30w.net -30wish.com -30xz.com -31.com -310game.com -310s-2520.com -310tv.com -310win.com -311100.com -311ksw.com -311wan.com -312168.com -312green.com -313.com -3131tyc.com -313515.com -3136525.com -31365y.com -313ab.com -3145.com -314pay.com -315003.com -3150315.com -315034.com -315166.com -315196.com -3158.com -315banzhao.com -315che.com -315fangwei.com -315hyw.com -315i.com -315online.com -315sc.org -315tech.com -315wangdai.com -315weishi.com -315z.net -315zqgl.com -315zw.com -315zww.com -31609.com -317608.com -317hu.com -3188.la -318ek.com -31966.net -3198.com -3199.com -319n.com -31alu.com -31bear.com -31bxg.com -31byq.com -31bzjx.com -31cg.com -31expo.com -31fabu.com -31food.com -31games.com -31gcjx.com -31gear.com -31huiyi.com -31jc.com -31jgj.com -31jiaju.com -31jmw.com -31jxw.com -31kan.com -31mada.com -31martech.com -31meijia.com -31mold.com -31myhome.com -31pump.com -31rzp.com -31seal.com -31sjjx.com -31spjx.com -31taoci.com -31wj.com -31xj.com -31xjd.com -31xs.com -31xs.net -31xs.org -31yj.com -31zscl.com -320106.com -3207.com -3208.net -320921.com -321200.com -321274.com -321ba.com -321cad.com -321cy.com -321dai.com -321fenx.com -321go.com -321kaishi.com -321key.com -321mh.com -321zou.com -322822.cc -322wl.com -3230.com -3234.com -323507.com -324.com -325286.com -32668g.com -32800.com -328f.com -32bh.com -32ka.com -32r.com -32w.net -32wan.com -32yx.com -33.com -330123456.com -3304399.com -3304399.net -3306safe.com -33105.com -331234.xyz -3312345.com -331ka.com -3320.net -3321.com -3322.cc -3322.net -3322.org -3323.com -3323399.com -332831.com -333-555.com -33324333.com -333333.com -3336653.com -333666999.club -3337726.com -3337729.com -3337751.com -3337756.com -3337765.com -3337783.com -3337785.com -3338863.com -3339.cc -3339auto.com -333ck.com -333cn.com -333job.com -333ku.com -333lh.cc -333mm.com -333racing.com -333y3.com -3341333.com -3342333.com -3344u.com -3347333.com -33519.com -3361.com -3366.com -3366.net -3366099.org -336655.com -336688.net -3366dns.com -3366img.com -3367.com -337y.com -338336.com -3387.com -3389dh.com -338c.com -3393.com -33app.net -33bus.com -33cp.com -33hei.com -33ip.com -33iq.com -33jianzhi.com -33jzw.com -33k.cc -33lc.com -33ly.com -33map.com -33map.net -33oncall.com -33or.com -33rpg.com -33shalong.com -33sp.com -33trip.com -33xs.com -33yq.com -34.com -341666666.com -345166.com -3454.com -3456.com -3456.tv -34580.com -345fk.com -345k.com -345kam.com -345ok.net -3464.com -349603.cc -3499.co -349broomestreet.com -34dm.com -34job.com -34l.com -34wl.com -34xiaoshuo.com -35.com -350.com -350.net -3500.com -350200.com -350abc.net -350bbs.net -352.com -3520.cc -3520.net -352200.com -3525.com -3533.com -3551.com -355pan.com -356123.com -35666c.com -35667.com -356688.com -3566t.com -357.com -357global.com -35941.com -3595.com -35ba.com -35dalu.com -35dxs.com -35free.net -35go.net -35hw.com -35inter.com -35kds.com -35mei.com -35nic.com -35pan.com -35pic.com -35q.com -35rc.com -35tyc.com -35vvv.com -35zw.com -35zww.com -36.la -360-bo.tv -360-g.net -360-game.net -360.cm -360.com -360.net -3600.com -3600.net -3600d.com -3600du.com -360114.com -360118.com -36099.com -360abc.com -360aiyi.com -360anyu.com -360bifen.net -360bike.net -360buy.com -360buyimg.com -360byd.com -360bzl.com -360caifu.com -360cdn.com -360changshi.com -360che.com -360chezhan.com -360chuguo.com -360cloudwaf.com -360daikuan.com -360dao.com -360doc.com -360doc2.net -360doc26.net -360doc28.net -360doc31.net -360doc33.net -360doc35.net -360doc7.net -360docs.net -360doo.com -360down.com -360drift.com -360drm.com -360dy.wang -360edu.com -360eet.com -360eol.com -360fdc.com -360gann.com -360gtm.com -360guanai.com -360haoyao.com -360hapi.com -360hitao.com -360hqb.com -360huzhubao.com -360hx.com -360hy.com -360hyzj.com -360ibm.com -360ic.com -360img.cc -360insurancemall.com -360ito.com -360jbw.com -360jk.com -360jq.com -360js.com -360jx.vip -360jzhm.com -360kad.com -360kan.com -360kb.com -360kuai.com -360kuaixue.com -360kxr.com -360laoshi.com -360lj.com -360longyan.com -360lvyouwang.com -360midi.com -360mkt.com -360os.com -360powder.com -360pw.com -360qc.com -360qd.com -360qhcdn.com -360qikan.com -360qikan.net -360qws.com -360safe.com -360safedns.com -360sdn.com -360shipu.com -360shouji.com -360shouzhuan.com -360shuashua.com -360sides.com -360sok.com -360stamp.com -360top.com -360totalsecurity.com -360tpcdn.com -360u9.com -360uu.com -360vipshop.com -360vps.com -360vrzy.com -360wbl.com -360webcache.com -360weizhan.com -360wscdn.com -360wxw.com -360wyw.com -360wzb.com -360wzws.com -360xh.com -360xiaos.com -360xiehui.com -360xinfang.com -360xixi.com -360xkw.com -360xs.com -360yfw.com -360youtu.com -360yun.org -360zhai.com -360zhaoa.com -360zhijia.com -360zhuizhu.com -360zhyx.com -360zimeiti.com -361.cm -361757.com -3618med.com -361a.com -361games.com -361mogame.com -361ser.com -361sport.com -361tuan.com -361way.com -362.cc -362233.com -363.com -363322014.com -363u.com -364000.com -365112233.com -365128.com -36543.com -365500.com -365708.com -36578.com -365960.com -365a8.com -365ailv.com -365art.com -365auto.com -365autogo.com -365azw.com -365bj.com -365book.net -365care.com -365cgw.com -365chanlun.com -365che.net -365cyd.net -365dhw.com -365diandao.com -365digitalonline.com -365ditu.com -365dmp.com -365dxlw.com -365editor.com -365eme.com -365essay.com -365exam.com -365f.com -365fdy.com -365gangqin.com -365gj.com -365haoshu.com -365heart.com -365htk.com -365huaer.com -365huifu.com -365huo.com -365ibank.com -365icl.com -365ime.com -365inews.com -365j.com -365jcw.com -365jia.com -365jiating.com -365jilin.com -365jq.com -365jw.com -365jz.com -365kan.tv -365key.com -365kk.cc -365kzj.com -365master.com -365mini.com -365pcbuy.com -365pk.com -365pp.com -365pr.net -365pub.com -365q123.com -365rili.com -365sec.com -365shequ.com -365sky.com -365ta.com -365tex.com -365ttcz.com -365ub.com -365webcall.com -365wenku.com -365world.com -365xiaoyanzi.com -365xiazai.com -365xuet.com -365yg.com -365you.com -365yyd.com -365zzd.com -3663.com -366300.com -366ec.com -366translation.com -36706.com -3673.com -367783.net -368mall.com -368tea.com -368yh.com -369.cc -369110.xyz -3694c.com -369785.com -3699.cc -36990.com -36992.com -3699wan.com -369beauty.com -369cc.com -369wenku.com -369xxw.com -369yizhi.com -36code.com -36dj.com -36dsj.com -36hjob.com -36jr.com -36kr.com -36kr.net -36krcdn.com -36krcnd.com -36mh.com -36nu.com -36sfw.com -36tr.com -36ve.net -36xs.net -36yc.com -36yh.com -36zhen.com -37.com -370fd.com -370fd.net -371.com -3710167.com -37163.com -37168.com -371fangte.com -371house.com -371love.com -371site.com -371zhongyi.com -37201.com -3721cha.com -3722.com -3727.cc -3733.com -3737.com -3737g.com -3737k.com -3737tyc.com -373best.com -373f.com -373house.com -373net.com -373yx.com -375263.com -375vip.com -377bbs.com -378699.com -37937.com -379941.com -379942.com -37bjw.com -37cos.com -37cs.com -37cu.com -37cy.com -37dh.com -37game2.com -37gogo.com -37hr.com -37job.net -37k.com -37live.com -37med.com -37pps.com -37rj.com -37see.com -37tang.com -37team.com -37wan.com -37wan.net -37wanimg.com -37women.com -37www.com -37yue.com -37yzy.com -37zone.com -37zw.net -3800.cx -380852.com -380871.com -380dy.com -3817.com -381818.com -381pk.com -38238r.com -3837.cc -3839.com -383940.com -3839app.com -3839app.net -3839img.com -3839pic.com -3839vc.com -3839video.com -383yun.com -3843zz.com -387a.com -388652.com -3887.com -389196.com -3892222.com -3895566.com -3899.net -38blog.com -38cun.com -38ejed.com -38fan.com -38hack.com -38hot.net -38hp.com -38hzt.com -38mhw.com -38shishang.com -38xf.com -38xinbo.com -38zj.com -39.net -391065.com -3911.com -391k.com -3937.com -39655.com -3970yy.com -3975.com -3975ad.com -3975ad.xyz -3975app.com -3975cdn.com -398990.com -39ask.net -39box.com -39clean.com -39cs.com -39dg.com -39ej7e.com -39fengliao.com -39h83s.com -39haohuo.com -39health.com -39hp.com -39jks.com -39kf.com -39kfw.com -39kx.com -39meitu.com -39mo.com -39shubao.com -39sk.com -39txt.com -39ws.com -39xh.com -39yst.com -3a4b5c.com -3alian.net -3aok.com -3ary.com -3avox.com -3b2o.com -3bu.com -3bwx.com -3c2p.com -3c3ww.com -3cjob.com -3conline.com -3cpp.org -3cvrc.com -3cwork.com -3cwu.com -3d-stereovision.com -3d-yizao.com -3d-zh.com -3d2000.com -3d2013.com -3d2s.com -3d414.com -3d56.net -3d66.com -3daima.com -3days.cc -3dbuyu.com -3dbuyu.net -3dch.net -3dclothes.org -3ddayin.net -3ddl.net -3ddl.org -3deazer.com -3demoo.com -3dfc.com -3dfrom.com -3dgenomics.org -3dhao.com -3dhat.com -3dhoo.com -3dhousedownload.com -3dinlife.com -3dinnet.com -3dkezhan.com -3dkk.com -3dkoukou.com -3dkunshan.com -3dllc.cc -3dlvyou.com -3dly.com -3dmax8.com -3dmaxvip.com -3dmgame.com -3dmgame.hk -3dmgame.net -3dmo.com -3dmomoda.com -3dnew.com -3doe.com -3dsc.com -3dsjw.com -3dsnail.com -3dsofang.com -3dtank.com -3dtaomo.com -3dtvbits.org -3dwebyx.com -3dwwwgame.com -3dxia.com -3dxt.com -3dxuan.com -3dxy.com -3dzyw.com -3e.net -3eyes.org -3fang.com -3fantizi.com -3g-edu.org -3g210.com -3g2win.com -3g3h.org -3g518.com -3g567.com -3g899.net -3gcomet.com -3gdisk.com -3gmimo.com -3gods.com -3gosc.com -3gpda.net -3gpk.net -3gsou.com -3gu.com -3gus.com -3h3.com -3haow.com -3hbox.com -3hgui.com -3j4.com -3jdh.com -3jidi.com -3jke.com -3jrx.com -3k.com -3k3cn.com -3k7.net -3ke.cc -3kid.com -3kk.com -3kmq.com -3ko.com -3kongjian.com -3laohu.com -3laz.com -3lbrand.com -3li.cc -3lian.com -3lii.com -3lsoft.com -3mbang.com -3mh0yvx.com -3miao.net -3miii.com -3mmr.com -3mtw.com -3n110.com -3nian.com -3png.com -3poo.com -3q2008.com -3q3q.cc -3qec.com -3qhouse.com -3qwe.com -3qzone.com -3r66.com -3rbcd.com -3renhe.net -3rkr.com -3rxing.org -3s.work -3s001.com -3s3w.com -3s78.com -3sbase.com -3scard.com -3shuwu.com -3snews.net -3songshu.com -3stl.com -3tilabs.com -3u.com -3uol.com -3us.com -3utui.com -3uww.cc -3v.do -3visual3.com -3vjia.com -3vkj.net -3vlm.net -3vsheji.com -3wads.com -3wap.cc -3wcoffee.com -3wfocus.com -3wht.com -3wmm.cc -3wmm.com -3wnb.com -3wsw.com -3wzhaopin.com -3x88.net -3xgd.com -3xiazai.com -3y7h.com -3yoqu.com -3yx.com -3z.cc -3zmuseum.com -3zxsw.com -4-xiang.com -4.cm -400-lighting.com -400.com -4000278400.com -4000279920.com -4000500521.com -4000600534.com -4000690600.com -4000730138.com -4000892990.com -4001006.com -4001006666.com -4001113900.com -4001581581.com -4001890001.com -4001961200.com -400516.com -4006008080.com -4006024680.com -4006026717.com -4006055885.com -4006138024.com -4006216888.com -4006287387.com -4006339177.com -4006620996.com -4006666688.com -4006695539.com -4006825178.com -4006906600.com -4007108885.net -4007112366.com -4007hao.com -4008000000.com -4008005152.com -4008005216.com -4008060066.com -4008075595.com -4008107107.com -4008109886.com -4008117117.com -4008123123.com -4008600011.com -4008800016.com -4008863456.com -4008885166.com -4008885818.com -4009515151.com -4009870870.com -4009991000.com -400csc.com -400cx.com -400gb.com -400iu.com -400jk.com -400jz.com -400lyw.com -400num.com -400qikan.com -400vv.com -400web.com -40279.com -404000.com -4040001.com -40407.com -404600.com -404forest.com -404mzk.com -404v.com -404wan.com -404wx.com -405400.com -406yx.com -407wan.com -4080dyy.com -4084.cc -4090.com -40manhua.com -40net.net -40tp.com -40ya.com -41188.com -411au.com -4124.com -4143.cc -41443.com -41717.net -4177.com -418999.com -418sbc.com -41game.com -41gw.com -41huiyi.com -41ms.com -41tp.com -41wan.com -41xt.com -42144.com -423down.com -4243.net -425300.co -425yx.com -42651.com -426g.com -42844.com -429006.com -42hq.com -42trip.com -42xz.com -4311.com -4321.com -432520.com -4339.cc -435000.com -435200.com -435214.com -4355.com -4366.com -436675.com -4377.com -4377info.com -437zhifu.com -438vip.com -439.cc -4399-xyx.com -4399.com -4399.net -43999yx.com -4399api.com -4399api.net -4399biule.com -4399data.com -4399dmw.com -4399er.com -4399hhh.com -4399i.net -4399j.com -4399pk.com -4399sj.com -4399swf.com -4399sy.com -4399wanju.com -4399youpai.com -43c55.com -43img.com -43xt.com -43zhubao.com -442zb.com -444475.com -4444s.vip -44485.com -4449992.com -4480.cc -44800.cc -4492.com -4493.com -44971.com -44england.com -44hyk.com -44pd.com -44pq.cc -44pq.co -44vs.com -45144.com -453600.net -455261.com -45575.com -456.net -45637s.com -4567.tv -4567w.com -456ss.com -457777c.com -457920.com -458hospital.com -458kq.com -4593xx.com -45app.com -45eee.com -45fan.com -45io.com -45ns.com -45r.com -45win.com -45xie.com -45zw.cc -462546.com -46412.com -4647.org -4658.net -466.com -46644.com -4671580.net -467541.com -467835.com -4699a.com -4699f.com -46design.com -46kavp.com -46mlsv.com -46z5j5.xyz -471go.com -4725u.com -47365.com -4738.com -47473.com -474b.com -4765.com -4779.com -477sblive.com -47819.com -47gs.com -47jh.com -47ks.com -47yun.com -47zu.com -48.com -4828229.com -4846.com -48575.com -485ka.com -4864678.com -4869.cc -48855268.com -48905.com -48hao.net -48iuz.com -49321.com -49358.com -49363.com -4948.com -4949567.com -49644913.com -497-img.com -497.com -498.net -499-img.com -49914.com -49app.com -49ivb.org -49jie.com -49pic.com -49w.cc -49wanwan.com -49you.com -49yu.com -4a40.com -4a8a.com -4apx.com -4aqq.com -4async.com -4c8t.com -4ci.cc -4cnzz.com -4cun.com -4d4c.com -4dai.com -4db.com -4dtime.com -4everdns.com -4f89.com -4fang.net -4fcom.net -4gfy.com -4ggame8.com -4ggogo.com -4gh6.com -4glte.org -4gqp.com -4gtoefl.com -4h6s.com -4hgame.com -4hok.org -4hou.com -4hpy.com -4inlook.com -4jplus.com -4k123.com -4kbizhi.com -4khi.com -4kong.com -4kyy.com -4l.hk -4lzx.com -4miao.com -4ngel.net -4paradigm.com -4px.com -4q5q.com -4qx.net -4sjob.com -4sscrm.com -4thetooth.com -4u4v.net -4usky.cc -4wad.com -4wxw.com -4xiazai.com -4xseo.com -4y4.net -4yang.com -4ye.cc -4yt.net -4yx.com -5-link.com -5-mail.com -5-project.com -5.hn -50-jia.com -500.com -50004.com -5000yan.com -50018.com -500boss.com -500cache.com -500d.me -500doc.com -500efuma.com -500gm.com -500px.me -500px.pro -500sucai.com -500talk.com -500tb.com -500wan.com -500wancache.com -500week.com -500zhongcai.com -5011.net -501811.com -501wan.com -50215.com -503118.com -50331.net -503error.com -504pk.com -5054399.com -5054399.net -505gg.com -505uu.com -5066.net -5068.com -5068yx.com -506fhq.com -507777.cc -508843.com -508job.com -50970.com -50bang.org -50cnnet.com -50fff.net -50mh.com -50pk.com -50pkpk.com -50sht.com -50tu.com -50union.com -50vm.com -50yc.com -50yin.com -50zera.com -50zw.co -50zw.com -50zw.la -50zw.net -50zww.com -51-cf.com -51-jia.com -51-n.com -51.am -51.com -51.design -51.la -51.net -5100.net -51008.com -510560.com -51099.com -510ka.com -511.la -511080.com -51110.com -51119.com -51147c.com -51168.tv -5117.com -511718.com -5117tools.com -5118.com -5118img.com -511god.net -511mv.com -511wan.com -511yj.com -5120.com -5120bb.com -51240.com -512play.com -512wx.com -5132.com -513523.com -5137.cc -51386.com -513c51.com -513hjs.com -513zg.com -514193.com -514200.com -51485148.com -51508.com -5151.com -51511.com -515158.com -5151doc.com -5151sc.com -5153.com -51555.net -51569.com -5156edu.com -5156rcw.com -5156ys.net -515app.com -515car.com -515fa.com -515ha.com -515ppt.com -51658042.com -51661182.com -51663.net -5166ys.com -516a.com -516edu.com -516ly.com -516tx.com -5173.com -5173cdn.com -5174f.com -517best.com -517dv.com -517ee.com -517hotel.com -517huizhou.com -517huwai.com -517idc.com -517japan.com -517kk.cc -517life.com -517lppz.com -517ming.com -517mr.com -517rcw.com -517sc.com -517tez.com -517w.com -517xc.com -517zp.com -518223.com -5184.com -51845.com -5184edu.com -5184pass.com -5185.cc -51864.com -5187g.com -5188.com -5188815.com -518ad.com -519.best -519397.com -51969.com -51985.net -5199.cc -5199.com -5199658.com -519dian.com -519rv.com -51ade.com -51ads.com -51adxfly.com -51aimei.com -51aistar.com -51aiwan.com -51anidea.com -51ape.com -51ape.net -51app.com -51ask.org -51asm.com -51aspx.com -51auto.com -51autogo.com -51autoimg.com -51awifi.com -51babybuy.com -51baigong.com -51baiyin.com -51banban.com -51banhui.com -51baoku.com -51baoshui.com -51baoxiu.com -51baozhanggui.com -51bbo.com -51bdtime.com -51bengou.com -51besttea.com -51bi.com -51biaoqing.com -51biz.com -51bjrc.com -51blackberry.com -51bmb.com -51bonli.com -51bos.com -51btceth.com -51btv.com -51bushou.com -51businessview.com -51buy.com -51bxg.com -51bzi.com -51cacg.com -51callcenter.com -51callu.net -51camel.com -51ccdn.com -51cdcs.com -51cdn.com -51chang.com -51changdu.com -51changdu.xyz -51changmi.com -51changshi.com -51changxie.com -51chaoban.com -51checai.com -51chongdian.net -51chost.com -51chudui.com -51chuguo.org -51chuli.com -51cir.com -51cjyy.com -51cma.org -51cname.net -51cnhr.com -51code.com -51cok.com -51comp.com -51coolpad.com -51cpm.com -51credit.com -51csr.com -51css.com -51cto.com -51cube.com -51cunzheng.com -51cxd.com -51dai.com -51daifu.com -51daima.com -51dangpu.com -51daquan.com -51daxueedu.com -51dayday.com -51dc.com -51devapp.com -51diangu.com -51din.com -51dingxiao.com -51ditu.com -51dns.com -51dojoy.com -51dongshi.com -51down.vip -51dpub.com -51drv.com -51dtv.com -51dugou.com -51dumo.com -51dzrc.com -51dzt.com -51dzw.com -51ean.com -51ebooks.com -51edu.com -51education.net -51eduline.com -51eim.com -51ejz.com -51ekt.com -51ele.net -51emo.com -51en.com -51eshop.com -51etong.com -51eway.com -51eyun.com -51f.com -51facai.com -51fane.net -51fangan.com -51fankui.com -51fanli.com -51fanli.net -51fdc.com -51feels.com -51feibao.com -51flrc.com -51fmzg.com -51fpg.com -51fubei.com -51fucai.com -51fund.com -51fxyh.com -51fxzq.com -51fytx.com -51g3.com -51g3.net -51g4.com -51gaifang.com -51gcw.com -51geeks.com -51gfl.com -51ggwu.com -51gh.net -51gif.com -51give.org -51gjie.com -51gjj.com -51gme.com -51golife.com -51gongjijin.com -51gouke.com -51goupiao.com -51gpb.com -51gran.com -51growup.com -51gsl.com -51guoji.com -51h5.com -51hanghai.com -51hangkong.com -51hanhua.com -51haofu.com -51haojob.com -51hcb.com -51hch.com -51hchc.com -51hcie.com -51hcw.com -51hei.com -51hejia.com -51hika.com -51hjgt.com -51hjk.com -51hlife.net -51honest.org -51hosting.com -51hostonline.com -51hsw.com -51huahong.com -51huanhuan.com -51huaxin.net -51huaya.com -51hunningtu.com -51hwzy.com -51hyper.com -51ias.com -51ibm.com -51idc.com -51iec.com -51ielts.com -51ifind.com -51ifonts.com -51img1.com -51img2.com -51img3.com -51img5.com -51imo.com -51ios.net -51itapp.com -51itjob.net -51itstudy.com -51iwifi.com -51ixuejiao.com -51jam.com -51jiabo.com -51jiameng.com -51jianxie.com -51jiasu.com -51jiaxiao.com -51jiecai.com -51jiemeng.com -51jingke.com -51jingying.com -51jinhuan.com -51jishu.com -51jiuhuo.com -51job.com -51jobcdn.com -51jobdns.com -51joyfish.com -51js.com -51jt.com -51jucaimi.com -51julebu.com -51junshi.com -51juzhai.com -51jyrc.com -51jyzs.com -51kahui.com -51kaiye.com -51kanke.com -51kaowang.com -51kaxun.com -51kehui.com -51kids.com -51kik.com -51kqn.com -51kt.com -51kupai.com -51kupin.com -51kywang.com -51la.net -51labour.com -51langtu.com -51ldb.com -51ldzx.com -51lexing.com -51lg.com -51lifes.com -51lingji.com -51liucheng.com -51ljms.com -51lolo.com -51lovo.com -51lucy.com -51lunwenwang.com -51luying.com -51lvh.com -51lyrc.com -51mag.com -51maimiao.com -51maiquan.com -51marryyou.com -51mdq.com -51meigu.com -51meiliao.com -51meishu.com -51microshop.com -51miit.com -51mike.com -51miz.com -51mkf.com -51mockup.com -51modo.cc -51mokao.com -51mole.com -51moot.net -51mp3ring.com -51mrp.com -51mta.com -51mtw.com -51mywellness.com -51nac.com -51nazhun.pub -51nb.com -51nicelearn.com -51niux.com -51nod.com -51nuoqi.com -51nwt.com -51ofc.com -51offer.com -51okc.com -51okf.com -51onb.com -51oneone.com -51onion.com -51only.com -51open.net -51opone.com -51osos.com -51ou.com -51pao.net -51papers.com -51pbnet.com -51pec.com -51peptide.com -51pgzs.com -51php.com -51piaozi.com -51pigai.com -51ping.com -51pintan.com -51pinwei.com -51pjys.com -51pla.com -51pocket.com -51pocket.net -51pot.com -51pptmoban.com -51ps.com -51psj.com -51psw.com -51puer.com -51q15.com -51qc.com -51qc.net -51qed.com -51qianduan.com -51qiangda.com -51qianguo.com -51qianvisa.com -51qicheng.com -51qilv.com -51qingjiao.com -51qinxue.com -51qqt.com -51qtg.com -51qub.com -51qudao888.com -51qudong.net -51qufx.com -51qumi.com -51qupu.com -51quzhe.com -51rc.com -51rcsl.com -51read.site -51readhome.com -51reboot.com -51rencai.com -51render.com -51renpin.com -51renxing.com -51report.com -51rong.com -51rp.com -51rry.com -51rz.com -51rz.org -51sai.com -51sanhu.com -51scb.com -51sdjob.com -51search.net -51seer.com -51self.com -51serive.com -51sgg.cc -51share.net -51shebao.com -51shebao.org -51sheyuan.com -51shiping.com -51shop.ink -51shoubei.com -51shoufei.net -51shoushi.com -51shubiao.com -51shuobo.com -51shyc.com -51signing.com -51simple.com -51sjk.com -51sky.net -51sole.com -51songguo.com -51souluo.com -51spjx.com -51sudeng.com -51suitui.com -51sxue.com -51taiwanziyouxing.com -51talk.com -51talkenglish.com -51tanbao.com -51tao.com -51taonan.com -51taoshi.com -51taowei.com -51taoyang.com -51tb.me -51test.net -51testing.com -51testing.net -51testing.org -51tfb.com -51tie.com -51tietu.net -51tijian.com -51ting.com -51tingyi.com -51tmt.net -51toefl.com -51tonglu.com -51tools.info -51toro.com -51touch.com -51toufang.com -51tour.com -51touxiang.com -51tra.com -51ttxue.com -51tudd.com -51tuiyi.com -51tunhuo.com -51tuodao.com -51tuz.com -51tv.com -51tv.net -51tvbao.com -51tyty.com -51tz.com -51uc.com -51ukf.com -51uyi.com -51uyun.com -51vba.com -51vhost.net -51vip.biz -51vs.com -51vv.com -51wan.com -51wangdai.com -51wanquan.com -51wcity.com -51web.com -51websec.com -51weihu.com -51wendang.com -51wf.com -51wincai.com -51windows.net -51wish.com -51wj.com -51wjrc.com -51wnl-cq.com -51wnl.com -51wofang.com -51world.win -51wp.com -51wtp.com -51wuduan.com -51wxjz.com -51wydj.com -51wyfl.com -51wyrc.com -51wzg.com -51wzxz.com -51xbl.com -51xbx.com -51xcrc.com -51xgjd.com -51xiancheng.com -51xianwan.com -51xiaohua.com -51xiaolu.com -51xie.com -51xingjy.com -51xpj.com -51xue8.com -51xuetang.com -51xuewen.com -51xuexiaoyi.com -51xueyingyu.com -51xumei.com -51xw.net -51xxs.com -51xxyy.com -51y5.com -51y5.net -51yabei.com -51yala.com -51yam.com -51yangsheng.com -51yanwang.com -51yasai.com -51yes.com -51yey.com -51yhdai.com -51yilu.com -51yip.com -51yjsteel.com -51ykb.com -51yonggao.com -51you.com -51youcai.cc -51youcai.com -51youdian.com -51yougo.com -51youth.com -51youz.com -51ys.com -51ysrc.com -51yuansu.com -51yue.net -51yuepin.com -51yueqian.com -51yuexin.com -51yund.com -51yunli.com -51yuu.com -51zan.com -51zbz.com -51zbz.net -51zd.net -51zhangdan.com -51zhantai.com -51zhaobizhi.com -51zhaowei.com -51zheduoduo.com -51zhengxin.com -51zhi.com -51zhishang.com -51zhiyuan.net -51zhizhao.com -51zhucai.com -51zhujia.com -51zixuewang.com -51zjxm.com -51zmt.net -51zpyc.com -51zr.com -51zsjc.com -51ztzj.com -51zuoti.com -51zupu.com -51zx.com -51zxw.net -51zyrc.com -51zyzy.com -51zzl.com -52-ic.com -520.com -520.net -5200.net -52004.net -5200cc.com -5200e.com -5200wx.com -520101.com -520520520520520.com -520730.com -5207758.com -52088.cc -52091w.com -520990.com -520apk.com -520bn.com -520cai.net -520cc.com -520cfc.com -520code.cc -520discount.com -520fx.com -520hhht.com -520im.com -520it.com -520jiabo.com -520jita.com -520lbl.com -520ldf.com -520lily.com -520link.com -520love520.com -520ly8.com -520meirenyu.com -520meirong.com -520mingmei.com -520ml.com -520mojing.com -520mwx.com -520shu.com -520sz.com -520tingshu.com -520wawa.com -520way.com -520wenshen.com -520xbw.com -520xiazai.com -520xiehou.com -520xp.com -520xst.com -520yidui.com -520z-2.com -520zg.net -520zuowens.com -520zwp.com -52112.com -52114.org -52115211.com -5211game.com -521360.com -52177.com -521che.com -521g.com -521g.org -521logo.com -521qw.com -521rmb.com -521ro.com -521szlx.com -521tieba.com -521up.com -52237377.com -522g.com -523333.com -5234444.com -52372.com -523touzi.com -523us.com -523xs.com -525.life -5251.net -5252cha.com -5252e.com -5253.com -5254.com -5258.net -525jmall.com -5262.com -52676.com -526net.com -526wan.com -527578.com -5277.com -527meeting.com -527pk.com -5281.com -52841819.com -528500.com -528529.com -52892.com -528btc.com -528day.com -5293.com -5299shop.com -529c31.com -52ae.cc -52ai.com -52ali88.com -52analysis.com -52article.com -52as.com -52asus.com -52audio.com -52ayw.com -52bar.com -52bd.net -52bendi.com -52biquge.com -52bji.com -52bjy.com -52blackberry.com -52bookshop.com -52bqg.com -52bss.com -52bus.com -52by.com -52cake.net -52ch.net -52che.com -52cik.com -52ckd.com -52click.net -52codes.net -52da.com -52daohang.com -52debug.net -52design.com -52dfg.com -52digua.com -52dmtp.com -52dns.com -52doc.com -52dr.net -52ds8.com -52dtv.com -52dzc.com -52dzxy.com -52ebook.com -52edy.com -52enku.com -52fangzi.com -52flac.com -52fmh.com -52foto.com -52fuqing.com -52fuqu.com -52fzw.com -52game.org -52gg.com -52gitlab.com -52grz.com -52guixi.com -52gvim.com -52hardware.com -52hejia.com -52hibuy.com -52hotel.net -52hrtt.com -52hrttpic.com -52hxw.com -52ico.com -52ig.net -52ij.com -52im.net -52investing.com -52inwet.com -52itstyle.com -52itstyle.vip -52jbh.com -52jbj.com -52jdyy.com -52jialejia.com -52jiaoshi.com -52jingsai.com -52jisu.com -52jkd.com -52jrjy.com -52js8.com -52jscn.com -52jt.net -52jubensha.com -52jxt.com -52jying.com -52kfly.com -52khs.com -52laodong.com -52liaoshen.com -52lieshou.com -52life.cc -52linglong.com -52lion.com -52lishi.com -52luckystar.com -52lvyou.com -52mac.com -52maicong.com -52mba.com -52mengdong.com -52mhw.com -52miji.com -52miniapps.com -52ml.net -52moshi.com -52mtc.com -52muyou.com -52njl.com -52njl.net -52op.net -52opencourse.com -52pachong.com -52pcfree.com -52ph.com -52pi.com -52pi.net -52pjb.net -52pk.com -52pk.net -52pkvr.com -52playpc.com -52podcast.com -52pojie.com -52ppt.com -52print.com -52programer.com -52ptt.com -52qixiang.com -52qj.com -52qmct.com -52qqba.com -52qudao.com -52queji.com -52qumao.com -52ra3.com -52rd.com -52rd.net -52rental.com -52saf.com -52samsung.com -52sddz.com -52shangou.com -52shici.com -52shijing.com -52shipping.com -52shouyu.com -52shuxue.com -52soji.com -52solution.com -52souji.net -52souluo.com -52soutu.com -52survey.com -52svip.cc -52svn.com -52t1.com -52tansuo.net -52tc.co -52tc.info -52tech.tech -52tfboy.com -52tian.net -52toys.com -52tps.com -52tq.net -52tql.com -52tt.com -52tt.vip -52udl.com -52unicode.com -52uyn.com -52vr.com -52vrdy.com -52wana.com -52wanh5.cc -52watch.net -52wendang.com -52wlw.com -52wmb.com -52wubi.com -52xiaomian.com -52xiaoshuowang.com -52xiaoyuan.net -52xie.com -52xinmiao.com -52xintaidu.com -52xinyou.com -52xitong.com -52xiuxian.com -52xiyou.com -52xpp.com -52xtxs.com -52xyz.com -52yawa.com -52yh.com -52yifei.com -52ykjob.com -52youju.com -52youpiao.com -52youtu.com -52ywan.com -52yww.com -52yxyx.com -52z.com -52zhaopin.com -52zhizuo.com -52zhushan.com -52zixue.com -52zuji.net -52zwxs.com -52zx.net -52zxw.com -52zy.com -52zzl.com -53.net -530p.com -531314.com -5317wan.com -531dns.com -531mk.com -5321vip.com -533.com -533.net -5334.com -5336.com -5338.org -533y.com -53431.com -53471.com -535300.net -53531dcg.com -53537yh.com -53537yht.com -535o.com -5360jx.com -5360ok.com -53617686.com -5366.com -53666.org -536wx.com -537.com -5379yx.com -538538.com -538618.com -5395.com -5396vvv.com -5399.com -539km.com -53chewu.com -53info.com -53kf.com -53kjw.com -53miji.com -53nic.com -53r.com -53shop.com -53shubiao.com -53sikao.com -53tct.com -53top.com -53xjd.com -53yao.com -53zw.net -54.com -54086.com -54114.com -543205.com -5433.com -545c.com -5460.net -548041.com -549493.com -549826.com -54admin.net -54benniao.com -54bk.com -54bt.com -54chen.com -54daxiang.com -54doctor.net -54doctors.net -54fcnr.com -54hacker.com -54hcz.com -54heb.com -54hei.com -54im.com -54jj.com -54jkw.com -54job.com -54kefu.net -54lol.com -54manong.com -54new.com -54op.com -54paike.com -54read.com -54sb.org -54share.com -54ske.com -54tf.com -54traveler.com -54tushu.com -54tusi.com -54up.net -54x03p.id -54yt.net -54yuqing.com -54zm.com -54zyz.org -55.cc -55.la -55015.com -550400.com -5504ll.com -551335.net -55178.com -55188.com -551house.com -552283.com -5523.com -553.com -55344.com -5548.net -555000d3.com -5551650.com -5551933.com -5552009.com -55555tao.com -555x.org -555yst.com -555zw.com -5566.net -5567.cc -5567.me -5568293.com -557.net -5577.com -5588.tv -55cc.cc -55coin.com -55dai.com -55dian.com -55doc.com -55duanzi.com -55duba.com -55dushu.com -55dx.com -55e5.com -55g.cc -55haitao.com -55hl.com -55hl.net -55home.com -55hyk.com -55i8.com -55idc.com -55jisu.com -55jj.com -55la.com -55lady.net -55lewen.com -55shantao.com -55tag.com -55tuan.com -55tuanimg.com -55wz.com -55xiazai.com -55y5.com -55you.com -55zm.com -56-7.com -56.com -560.im -56015.com -560la.com -560xs.com -5611.com -56135.com -5617.com -5628l.com -5629.com -5636.com -56360.com -564.cc -5648.cc -56506666.com -5654.com -566.com -5666.tv -566855.com -5669.com -566966.com -566job.com -5676.com -5678.net -5678la.com -567idc.com -5684.com -569.com -5694.com -56a.com -56ads.com -56beijing.org -56ca.com -56care.com -56china.com -56cj.com -56clte.org -56da.com -56dagong.com -56de.com -56dichan.com -56dr.com -56en.com -56ggb.com -56gk.com -56golf.com -56img.com -56img.net -56imgs.com -56kad.com -56kandy.com -56laile.com -56luxury.com -56md.com -56ml.com -56mp.com -56pan.com -56php.com -56qq.com -56qss.com -56show.com -56shuba.cc -56shuku.org -56steel.com -56tchr.com -56tj.com -56uo.com -56uu.com -56wen.com -56ye.net -56zzx.com -57.net -57023.com -571400.net -571free.com -571xz.com -5721.net -5755.com -575ib.com -576.com -57616.com -57665.com -5768.com -576tv.com -57821.com -579609.com -579944.com -57ac.com -57auto.com -57dj.com -57ee.net -57fx.com -57gif.com -57go.com -57lai.com -57piao.com -57px.com -57qy.com -57sc.com -57tibet.com -57tuan.com -57us.com -57uu.com -57wo.com -57yy.site -57zhe.com -58.com -5800.com -580114.com -580116.com -580168.com -580590.com -580ban.com -580eda.net -580jz.net -580k.com -580tequan.com -58199.com -582582.com -582hr.com -583go.com -5858.com -585998d.com -58611.net -5866.com -587c51.com -58801hn.com -588102.com -5884.com -5887.com -5888.tv -588991.com -588art.com -588ku.com -58921.com -5898yun.com -58abb.com -58bangmang.com -58baogao.com -58bo.com -58buy.com -58che.com -58cloud.com -58coin.com -58cyjm.com -58czt.com -58dadi.com -58daojia.com -58display.com -58dm.com -58fangdai.com -58fenlei.com -58game.com -58ganji.com -58gocm.net -58gush.com -58guzu.icu -58house.com -58huoban.com -58hzb.com -58img.com -58insure.com -58iwan.com -58jb.com -58jixie.com -58jurenqi.com -58kad.com -58kaifa.com -58kanshu.cc -58kasch.com -58kuaipai.com -58kuku.com -58moneys.com -58net.com -58pic.com -58picc.com -58player.com -58q8.com -58qz.com -58supin.com -58trz.com -58tyh.com -58ubk.com -58wan.com -58wangwei.com -58wanwan.com -58xinrui.com -58xs.com -58xs.la -58xs.tw -58xuechewang.com -58xuexi.com -58yiji.com -58yuefu.com -58yuesao.com -58zcw.com -58zhuiju.com -58zpw.com -59008gg.com -5906333.com -590m.com -59120.com -591234x.com -591522.com -59168.net -59178.com -5918dyw.com -5918s.com -591918.com -591change.com -591cto.com -591fan.com -591hx.com -591lw.com -591master.com -591moto.com -591vlog.com -591vr.com -591wed.com -591wy.com -591yhw.com -591yingshi.com -5923d.com -5925car.com -592meiju.com -592zn.com -59313313.com -593555b.com -59370.com -593yx.com -59490.com -5956pp.com -595818.com -595led.com -596fc.com -597.com -59706.com -597rcw.com -59881.com -59899m.com -598g.com -598rc.com -598wan.com -5999.tv -599ku.com -59b2b.com -59di.com -59dun.com -59edu.com -59hs.com -59iedu.com -59kankan.com -59na.com -59pk.net -59store.com -59w.net -59wj.com -59yx.com -5a49.com -5aaa.com -5acbd.com -5adanhao.com -5adm.net -5ag.net -5aivideo.com -5aiyoo.com -5ajob.com -5ajw.cc -5alt.me -5alw.com -5any.com -5atxt.com -5axxw.com -5azy.com -5bite.com -5biying.com -5bug.wang -5caicloud.com -5ce.com -5ceimg.com -5cgo.com -5cms.com -5cocoi.com -5coser.com -5cpod.com -5d2ede2.com -5d6d.com -5d6d.net -5dashi.com -5dfp.com -5dfsd2.com -5di.tv -5ding.com -5djbb.com -5djiaren.com -5djpg.com -5dm.cc -5dmail.net -5down.net -5dplay.net -5ds.com -5duo.com -5ebo.com -5eplay.com -5esc.com -5etv.com -5ewin.com -5fen.com -5fengshou.com -5fun.com -5fwan.com -5gcg.com -5goto.com -5gsu.com -5gwan.com -5gy.com -5h.com -5ha.net -5hb.org -5helpyou.com -5hom.org -5hrc.com -5i-training.net -5i.com -5i5aj.com -5i5j.com -5i5t.com -5i9u.com -5iag.com -5iag.net -5iape.com -5ibc.net -5ibear.com -5icaipu.com -5icbs.com -5ichecker.com -5ichong.com -5icomment.com -5icool.com -5icool.org -5idc.com -5idev.com -5idhl.com -5idream.net -5idy.com -5iec.com -5ifapiao.com -5ifit.com -5iflying.com -5ifund.com -5ifxw.com -5igen.com -5igupiao.com -5ihse.com -5ijuyi.com -5ikang.com -5ikfc.com -5iln.com -5ilog.com -5imeishi.com -5imoban.net -5imomo.com -5imx.com -5imxbbs.com -5iok.com -5iops.com -5ip.cc -5ip9.com -5ipatent.com -5ipkwan.com -5ips.net -5iqiqu.com -5isanguo.com -5its.com -5itx.com -5iucn.com -5ixs.net -5ixuexiwang.com -5iyq.com -5iyxw.net -5izt.net -5j.com -5j5k.com -5jin.org -5jjc.net -5jjdw.com -5jjx.net -5jli.com -5joys.com -5jwl.com -5jzw.com -5k5m.com -5kbox.com -5kcrm.com -5kcrm.net -5kda.com -5khouse.com -5lanren.com -5lejob.com -5lewen.com -5lux.com -5lyq.com -5m5m5m.com -5m68.com -5mapk.com -5minsgold.com -5mrk.com -5nd.com -5nj.com -5nlnzp.shop -5ooq.com -5pao.com -5pb.net -5pk.com -5plus1.net -5pop.com -5ppt.net -5pub.com -5q.com -5qdd.com -5qmall.com -5qq.com -5qwan.com -5qzone.net -5r1.net -5read.com -5rs.me -5s4f.com -5sai.com -5sdy.cc -5sdy.com -5see.com -5seestar.com -5sem.com -5sha.com -5sharing.com -5snow.com -5stmt.com -5sw.com -5tangs.com -5teacher.com -5thhospital.com -5thspace.net -5thspace.org -5tps.com -5tps.vip -5txl.com -5u18.com -5u3d.com -5u588.com -5u5u5u5u.com -5u71.com -5ugaizhuang.com -5uks.com -5upm.com -5usport.com -5uu.us -5uu6.com -5uu8.com -5v55.com -5vnt.com -5w.com -5w123.com -5w52.com -5w5w.com -5w8.net -5wanpk.com -5wanq.com -5weinisi.com -5wx.org -5wxw.com -5x9d.com -5xcg.com -5xiang0.com -5xiaobo.com -5xini.com -5xml.com -5xts.com -5xue.com -5xuni.com -5y100.com -5y51.com -5y6s.com -5y89.com -5ydj.com -5yedu.com -5yhua.org -5yi.com -5ykj.com -5you.com -5youchou.com -5yueyy.com -5yun.org -5z5zw.com -5zai.com -5zg.com -5zzu.com -6-china.com -6.gy -60.cm -6000gou.com -60012.com -600525.net -600895.com -600zi.com -601601.com -602.com -602img.com -603ee.com -6046.com -6046.net -605-zy.com -605zy.co -606188.cc -6070.tv -6071.com -607777.cc -607p.com -6080d.com -6080j.com -6080k.com -6090b.com -60dj.com -60eee.net -60malaysia.com -60mil.com -60nm.com -60tui.com -61.com -61.life -610213.net -612.com -6120aa.com -6122.net -612345.com -612459.com -6137.net -613k31.com -615c.com -61611.net -616114.com -6164.com -61658.com -6168511.com -616pic.com -616wan.com -618344.com -6186.com -61868.cc -6187wo.com -6188.net -618cj.com -618day.com -618hr.com -618ky.com -61916.com -619k.com -61baobao.com -61bb.com -61bbw.com -61co.com -61diy.com -61ertong.com -61gequ.com -61haodian.com -61hr.com -61ic.com -61info.com -61k.com -61kezhan.com -61mami.com -61mc.com -61sheji.com -61sou.com -61tg.com -61vps.com -61ww.com -61xiangce.com -62.com -6210k.com -623k.com -626367.com -626688.com -62669.com -626china.org -626x.com -628.com -629600.com -629k.com -629kf.com -62a.net -62game.com -62ma.com -63.com -630book.cc -630book.com -63243.com -6328.net -632news.com -63346.com -637000.cc -6383.com -639311.com -6399868.com -63diy.com -63pe.com -63pic.com -63qingyou.com -63tl.com -63ys.com -63yx.com -6417000.com -642online.com -64365.com -6446hh.com -64518.com -6453.net -64538.net -645w.com -646000.com -6463.com -64644444.com -649099.com -64dns.com -64ds.com -64gua.com -64ma.com -64mv.com -64w.cc -650011.com -651700.com -6522111.com -6528.com -6533.org -654320.com -6543210.com -654321wan.com -655a.com -655u.com -655yx.com -656463.com -656tt.com -657565.com -657802.com -65875.com -6588988.com -659595.com -65house.com -65mhxy.com -65singapore.com -65wan.com -65xs.net -66.to -6600.org -660pp.com -660x.com -66123123.com -661268.com -66131.com -66152.com -66163.com -66168.net -66173yx.com -661832.com -662city.com -662p.com -6631.com -663395.net -66378.com -664444.com -66460.com -6655.com -6655.la -6656pk.com -6661666.net -6665.com -666629b.com -6666519.net -666666.so -66667676.com -6669667.com -666baicai.com -666fanhao.com -666gps.com -666idc.com -666kao.com -666pic.com -666shuwu.com -666wan.com -666wan.net -666xinxin.com -6677000.com -6677293.com -667744.com -6677493.com -66777708.com -6678net.com -66825.com -66826.com -668559.com -6686672.com -6686693.com -6686697.com -66868.com -6686x1.com -6688.com -66880.com -66889.net -668895.com -6688pay.com -668app.com -668lw.com -668map.com -668news.com -6695.com -66991a.com -669pic.com -669play.com -669ye.com -66aliyun.com -66beian.com -66call.com -66cn.com -66diqiu.com -66ds.net -66dt.com -66e.cc -66fuzhuang.com -66house.com -66ip.com -66jiedai.com -66js.info -66kk.com -66liu.com -66mobi.com -66money.com -66mz8.com -66nao.com -66nh.com -66php.com -66play.com -66rou.com -66rpg.com -66ruian.com -66s.cc -66shlf.com -66shouyou.com -66sj.com -66sy.com -66team.com -66test.com -66to.net -66tv.tv -66u.com -66ui.com -66vod.net -66wc.com -66weiyou.com -66wz.com -66xh.com -66xue.com -66you.com -66ys.cc -66ys.co -66zhang.com -66zhizu.com -66zhuang.com -66zw.com -6711.com -6711img.com -676z.com -67712a.com -677dy.com -678266.com -678678.com -67876.com -6789.com -6789.net -678922c.com -678963333.com -6789che.com -6789go.com -678edu.net -678ie.com -678py.com -67cdn.com -67danji.com -67gu.com -67joy.com -67lm.com -67mb.com -67mo.com -67tuan.com -67wanwan.com -67yes.com -68.com -680.com -6816.com -682.com -68211.com -6822.com -683kj.com -6844.com -6868.com -6868shop.com -686fw.com -686ib.com -6873.com -688n.com -6899wan.com -68eg.com -68g5zbwf.icu -68gainian.com -68ge.com -68h5.com -68hanchen.com -68hr.com -68jt.com -68pk10.com -68play.com -68rong.com -68t68.com -68team.com -68tuku.com -68web.net -68websoft.com -68youhui.com -69005a.com -6903.com -6922000.com -69260.com -693836.com -693975.com -6949.com -695157.com -695175.com -695275.com -695828.com -695ljg.com -698wan.com -69916666.com -699g.com -699pic.com -699xs.com -69fenxiang.com -69hr.com -69jianzhi.com -69ps.com -69shu.com -69shu.org -69xiu.com -69y.com -69yc.com -69ys.com -6a.com -6aas.com -6abc.net -6acm.com -6api.net -6apt.com -6b3b.com -6c6c.com -6ccn.com -6cit.com -6cnzz.com -6d4d5.com -6d4g.com -6dad.com -6dafu.com -6dan.com -6diy.com -6ds.me -6du.in -6duoyu.com -6dvip.com -6eat.com -6edigital.com -6eys.com -6fcsj.com -6fok.com -6fwq.com -6g5fd1a.com -6gdown.com -6gh4.com -6ght.com -6hgame.com -6hwan.com -6iit.com -6jianshi.com -6jworld.com -6k.com -6k6g.com -6k9k.com -6kongbao.com -6kw.com -6laohu.com -6lk.net -6m5m.com -6mao.com -6mh7.com -6miii.com -6miu.com -6miu.net -6miv.com -6mshuwu.com -6mxs.com -6pifa.net -6plat.org -6play.net -6pmcn.com -6puppy.xyz -6renyou.com -6rooms.com -6s4qki.com -6s54.com -6say.com -6sfg.com -6sq.net -6stmmo.com -6t12.com -6temai.com -6tennis.com -6thhosp.com -6tiantian.com -6tie.com -6v.com -6v68.com -6vdy.com -6vhao.tv -6vps.net -6wan.com -6wang.cc -6wtx.com -6xd.com -6xigema.com -6xw.com -6yoo.com -6yu6.com -6yuexi.com -6yxk.com -6yyy7.com -6zrc.com -6zu.com -7-hotel.com -7-inc.com -7-vk.com -7-wx.com -700bike.com -700so.com -700static.com -700store.com -701sou.com -703804.com -705112.com -7068.cc -70689.com -706kj.com -70733.com -707377m.com -7080edu.com -7082.com -708870.com -708990.com -70dh.com -70dir.com -70god.com -70ppt.com -70qn.com -70soft.com -70wei.com -70yx.com -71.com -71.net -710071.net -71133.com -7116dns.com -711g.com -711pr.com -7120.com -712100.com -71234333.com -7130mgm.com -71360.com -7139.com -714.hk -715083.com -7152223.com -715300.com -7160.com -71668.net -71714.com -7176.com -717909.com -7190.cc -719000.com -7192.com -71ab.com -71acg.com -71acg.net -71baomu.com -71baomu.net -71dj.org -71dm.com -71du.com -71e.com -71edge.com -71gif.com -71http.com -71k.com -71lady.com -71lady.net -71one.net -71p.net -71study.com -71txt.com -71wl.com -71xe.com -71zs.com -720582.com -720pmovie.com -720static.com -720think.com -720ui.com -720wang.com -720yes.com -720yun.com -720yuntu.com -720zh.com -7211.com -72177.com -7230.com -724001.com -7255.com -726033.com -726p.com -7273.com -7280.com -728wy.com -7298.com -72book.com -72byte.com -72bz.com -72ce.com -72crm.com -72crm.net -72crm.org -72dj.com -72dns.com -72dns.net -72dy.com -72e.net -72en.com -72g.com -72h.io -72la.com -72laodian.com -72link.com -72sc.com -72up.com -72xf.com -72xit.com -72xuan.com -72zx.com -730646.com -731c.com -731yz.com -73232yx.com -732732.com -734969.com -735357.com -7360.cc -7369dy.cc -737.com -73789.com -7384tv.com -73994.com -73bc.com -73card.com -73yw.com -73zw.com -74.com -741978.com -7428.net -744zy.com -7474.com -7477.com -747wan.com -749997.com -74cms.com -74hy.com -75184.com -75271.com -75367.com -75510010.com -7555yl.com -75614.com -756u.com -7574.com -75757.com -7580.ltd -75n474.com -75team.com -75xyx.com -7618.com -761w.com -762rc.com -764100.com -7654.com -7659.com -765i.com -765q.com -766.com -7663.com -76676.com -766sf.com -766z.com -7676.com -7676u.com -7677wan.com -767stock.com -76868.com -769279.com -769car.com -76al.com -76baobao.com -76dongdong.com -76e.org -76jie.com -76ju.com -76wu.com -76xh.com -76xs.com -76y.com -76zu.com -7708hd.com -7708zf02.com -770921.com -7711.com -77119159.com -771633.com -77169.com -77169.net -7717wan.com -7723.com -7724.com -77248a.com -7724yx.com -7725.com -7729.com -77313.com -77348k.com -7735.net -773buy.com -773n.com -77495.com -77520a.com -7756.org -7759.com -7766.info -7766.org -776999h.com -777413.com -77745.com -777524.com -777684a.com -77773657.com -777kuu.com -777moban.com -777zp.com -77833.net -778669.com -7788.com -7788js.com -7788sky.com -7788tools.com -7788xj.com -7789.com -778buy.com -77927nn.com -77927tt.com -7794.com -77991.com -7799520.com -77acg.com -77bx.com -77ds.com -77ds.vip -77dy8.com -77ebooks.com -77hei.com -77jieri.com -77kp.com -77kpp.com -77l.com -77mh.com -77music.com -77mv.com -77nt.com -77power.com -77sbsun.com -77tianqi.com -77tng.com -77vcd.com -77xmd.com -77xsw.la -77y4.com -77ys.com -77zn.com -78.com -78114422.com -78187.com -782yx.com -78300.com -78302.com -78360.net -7849.com -785959.vip -7878hk.com -7881.com -788511.com -788899.com -788v.com -788wj.com -78901.net -789294.cc -789314.cc -789box.com -789gg.com -789hi.com -789msw.com -78bar.com -78dian.com -78diy.com -78dm.net -78fz.com -78gk.com -78hr.com -78oa.com -78pan.com -78zph.com -79.com -790092.com -793360.com -7937.com -7940.com -79432.com -794579.com -7958.com -7958.net -796.com -7964b.com -7979la.com -7979u.com -797sun.com -797xj.com -798092.com -7988wan.com -798com.com -798edu.com -798ydh.com -798youxi.com -799.net -799281.com -7999.com -7999.tv -799job.com -79cha.com -79da.com -79tao.com -79tui.com -79yx.com -79yx.net -7a31jmf.com -7a8k.com -7acg.com -7ahr.com -7analytics.com -7b2.com -7c.com -7caijiaqi.com -7caiyun.com -7capp.com -7ccj.com -7cen.com -7chacha.com -7cmz.com -7cname.com -7colorblog.com -7cwo.com -7cxk.com -7dah8.com -7dapei.com -7dianw.com -7didc.com -7do.net -7down.com -7down.net -7drc.com -7dsp.com -7dsw.com -7dtest.com -7dtime.com -7dugo.com -7e.hk -7east.com -7edown.com -7fei.com -7fgame.com -7flowers.com -7forz.com -7fresh.com -7fun.org -7gz.com -7hcn.com -7help.net -7ho.com -7hon.com -7hxsxs.com -7i2.com -7iaoshou.com -7icp.com -7ipr.com -7jia.com -7jia2.com -7jiaqi.com -7jjjj.com -7jk.com -7jubao.com -7junshi.com -7jxf.co -7k35.com -7k7k.com -7kk.com -7kla.com -7kuaitang.com -7kww.net -7kxs.com -7kzw.com -7liwu.com -7lizhi.com -7lk.com -7lw.com -7mah2.com -7mgame.com -7mo.cc -7modifier.com -7moe.com -7moor-fs1.com -7moor-fs2.com -7moor.com -7msj.com -7mx.com -7naicha.com -7nepal.com -7net.cc -7oh.net -7pa.com -7pc8.com -7pei.com -7po.com -7q5.com -7qile.com -7r7z.com -7road.com -7road.net -7runto.com -7rv.net -7scs.com -7sdn.com -7sheji.com -7sj.com -7su.com -7t9.com -7tgame.com -7tianshi.com -7tou.com -7tt3333.com -7usa.net -7uyx.com -7v6.net -7vk.com -7wa.cc -7wan.com -7wenta.com -7wenyi.com -7wkw.com -7wnews.com -7wsh.com -7wx.org -7x24cc.com -7x24s.com -7xdown.com -7xfilm.com -7xseo.com -7y5.net -7y7.com -7yc.com -7youxi.com -7yue.pro -7yueji.com -7yun.com -7yzone.com -7zgame.com -7zhan.com -7zhou.com -7zm.com -7zyd.com -7zzy.com -8-008.com -8-host.com -80.com -80.hk -80000.cc -800020308.com -8000ad.com -8003605.com -800400.net -800423.com -800535.com -800646.com -8006506.com -8006511.com -8006tu.com -800820.net -8008202191.com -800app.com -800bamboo.com -800best.com -800bestex.com -800cdn.com -800du.com -800hr.com -800li.net -800lie.com -800lj.com -800mei.net -800pai.com -800pharm.com -800t.net -800tu.com -800ux.com -800vod.com -800xs.net -800you.com -800youhuo.com -800zy99.com -801358.com -802203.com -8038.pw -8044445.com -80710.com -80714.com -80800.vip -8080i.com -8080s.net -8081.net -80881.com -8088sz.com -808cdn.com -808w.com -8090-sec.com -8090.com -8090.pk -8090.so -8090120.com -8090app.com -8090cdn.com -8090mt.com -8090st.com -8090vision.com -8090xx.com -8090yx.com -8090yxs.com -809635.com -809803.com -80anmo.net -80baicai.biz -80bi.com -80fans.com -80hman.com -80host.com -80iter.com -80juqing.com -80kongjian.com -80kuku.com -80ml.com -80nb.com -80note.com -80paper.com -80s.cm -80s.im -80s.la -80s.so -80s.tw -80sec.com -80shihua.com -80sjy.net -80smp4.net -80tian.com -80txt.com -80txt.la -80vps.com -80xb.com -80ym.com -80yunying.com -80zhan.com -810236.com -810251.com -8108188.com -810840.com -811odw.work -81312.com -81329999.net -815good.com -815ybw.com -81629.com -81677.com -8169.com -81761.com -817711.com -818.com -81813.com -818it.com -818ps.com -818today.com -818tu.com -81999.org -81comdns.com -81dk.com -81it.com -81js.net -81kx.com -81max.com -81tech.com -81toutiao.com -81tt.net -81un.net -81xy.com -81yy.cc -81zw.co -81zw.com -81zw.us -8203app.com -8211.com -821583.com -8222.com -82222919.com -82250856.com -822644.com -8232365.com -82326999.com -82335966.com -82341.com -8234567.com -8246.net -8264.com -826rc.com -826wan.com -828g.com -82a.net -82ip.com -82ky.com -82pk.com -82ucc.com -82xs.cc -82xs.com -83133.com -832200.com -8329555.com -833833833.net -8339.org -83480900.com -83666.com -83681111.com -837711.com -838.cc -83823.net -83830.com -8384cs.com -838dz.com -83990567.com -83dd.com -83edu.net -83h87d.com -83jie.com -83om.com -84.com -84.vc -8421.com -84384d.com -84399.com -844a.com -844wan.com -84519.com -84684.net -8477.com -849959.com -84dwc.com -84fk.com -84ktv.com -84lm.com -84lm.net -84lp89.com -84piao.com -84zcb.com -84zhu.com -85.com -850500.com -8518.com -8521.org -85384.com -853lab.com -8548965.com -8558.org -85655095.com -85679999.com -85814.com -85878078.com -858game.com -85ju.com -85kf.com -86-import.com -86.cc -86010.net -860527.com -860598.com -860816.com -861522.com -86175.com -861817.com -86188.com -86215.com -86262.com -8633.com -86516.com -865211.com -86590.com -866ds.com -866lvyou.com -866wn.com -8671.net -86722.com -8673h.com -867game.com -867wn.com -8682.cc -8684.com -868578.com -8686c.com -86873.com -86888qp.com -8688g.com -86933.com -869d.com -869v.com -86amsdy.com -86art.net -86campus.com -86clouds.com -86control.com -86ditu.com -86djw.com -86eh.com -86fis.com -86fm.com -86fsp.com -86fuwuwang.com -86game.com -86gc.net -86hh.com -86hr.com -86hud.com -86huoche.com -86jg.com -86jnjp.com -86jobs.com -86joy.com -86junshi.com -86kl.com -86kongqi.com -86kx.com -86lawyer.com -86mai.com -86mama.com -86mdo.com -86nb.com -86office.com -86pla.com -86ps.com -86qc.com -86sb.com -86shouji.com -86szs.com -86szs.wang -86uuu.com -86wan.com -86wol.com -86xq.com -86y.org -86zsw.com -87.com -870818.com -87121.net -8714.com -87188718.com -872.cc -8721.com -872872.com -872y.com -87311111.com -87535353.com -876326.com -876web.com -8770000.com -877325.com -87794560.com -878009.com -8782.net -87870.com -87994.com -87box.com -87g.com -87ma.com -87money.com -87pk.com -87yy.com -88-z.com -88.com -8800.org -8800808.com -8801.net -880114.com -880331.net -880735.com -88075.net -88077777.com -880834.com -8808808.com -8809806.com -880sy.com -880you.com -88106.com -88175.com -8825.com -8827777.com -8828dl.com -8828xljcw.com -88303887.com -88360.com -884109.com -884134.com -884358.com -8844.com -88444l.cc -88448.com -8848.com -8848hd.com -8848phone.com -885.com -8850006.com -88520.cc -885210.net -8855.org -88582.com -8858a.com -8860.net -8864.org -886520.cc -8866.org -886966.com -886abc.com -886bl.com -886vps.com -88765.com -887w.com -8881919.cc -8884321.com -88845678.com -88859.tw -88859c.com -88859d.com -8888800000.com -888pic.com -888ppt.com -888rj.com -888y17.com -8890tu.com -8898ad.com -8898wz.com -88995799.com -88999.com -889ppt.com -889su.com -889xp.com -88bada.com -88bank.com -88bx.com -88cdn.com -88dj.com -88duomi.com -88dushu.com -88eq.com -88fenxiao.com -88h3.com -88haodian.com -88hom.com -88ht.com -88htu.com -88hu.com -88jianshen.com -88jq.net -88klk.com -88koo.com -88lan.com -88lgo.com -88lm.cc -88meishi.com -88mf.com -88ming.net -88mmmoney.com -88ng.com -88pets.com -88popo.com -88rpg.net -88tang.com -88tph.com -88ty96.com -88u.com -88wakuang.com -88xiaoshuo.com -88xr.org -88ysg.com -88zha.com -8912128.com -89178.com -89303.com -893933.com -8961zx.com -896691.com -8977222.vip -8977444.app -8977444.vip -8977567.com -8977888.app -8977888.vip -8979.com -898.travel -8989118.com -898tc.com -8998cn.com -8999.cc -899art.com -89dj.com -89ds.com -89jl.com -89rfd.com -89uu.com -8a.hk -8ao8ao.com -8aza.com -8b2.net -8bb.com -8bcd9.com -8bears.com -8bit.xin -8btc-ops.com -8btc.com -8btm.com -8c8h.com -8cheche.com -8cname.com -8cnd.com -8cnet.com -8da.com -8dc.net -8ddao.com -8desk.com -8dexpress.com -8dlive.com -8dn.com -8dol.com -8dp.net -8dream.net -8du.in -8dudata.com -8dwww.com -8e8z.com -8europe.com -8fenxiang.com -8gov.com -8gw.com -8gyu.com -8hsleep.com -8ii9.cc -8illl.com -8jdns.net -8jiaoye.com -8jj.cc -8jxn.com -8jzw.cc -8k7k.com -8k8z.com -8kana.com -8kzw.com -8l8e.com -8le8le.com -8lhx.com -8liuxing.com -8lk.com -8llp.com -8mhh.com -8miu.com -8miu.net -8n6n.com -8njy.com -8o9o.com -8oqwl9.wang -8pingce.com -8pu.com -8qwe5.com -8qwx.com -8ruiyou.com -8s123.com -8s8s.com -8s8s.net -8she.com -8taobaodian.com -8tgh.com -8toto.com -8ttt8.com -8tupian.com -8twan.com -8u58.com -8u8.com -8ucdn.com -8uka.com -8ume.com -8uyx.com -8v.com -8wan.com -8wdns.com -8win.net -8wiu.com -8wq.com -8wss.com -8yao.cc -8ybct.com -8ym8.com -8yw.xyz -8yzw.com -8z.net -8zntx.com -8zy.com -9-zhuce.com -9.am -9000design.com -9000gou.com -9000idc.com -9000wy.com -900112.com -900cha.com -900php.com -900ppt.com -900top.com -90123.com -90370.com -903772.com -90432.net -90576.com -9080ysw.com -90880.com -908872.com -90907.com -90a.cc -90ckm.com -90e.com -90ko.net -90lhd.com -90pan.com -90qh.com -90sheji.com -90sjimg.com -90tank.com -90vm.com -90wmoyu.com -90wx.com -90yang.com -90zm.net -91.com -910app.com -910go.com -910play.com -91160.com -9118fu.com -911cha.com -911pop.com -911sblive.com -911sl.com -911wow.com -911yao.com -912366.com -912413.com -912414.com -912688.com -912k.com -912yx.com -913232.com -9133.com -9136.com -91378.com -913vr.com -913you.com -91472.com -915.com -915.im -9154wan.com -915658.com -915799.com -9158.com -9158ads.com -9158h5.com -915c.com -915lx.com -916607.com -916m.com -917.com -917118.com -917558.com -9178.work -917ka.com -917st.com -918433.com -9188.com -9188wan.com -918dxs.com -918jx.com -918ka.cc -918rc.com -918ys.net -9191mr.com -9191net.com -9191zx.com -919377.com -91985.com -91abroad.com -91ac.com -91act.com -91aiche.com -91aliyun.com -91all.net -91anjian.com -91art.net -91b2b.com -91baby.com -91bee.com -91boshuo.com -91bushou.com -91caijia.com -91canyin.com -91carnet.com -91cdkey.com -91ceshi.com -91cha.com -91chuxue.com -91clt.com -91cpm.com -91cps.com -91ctc.com -91cy.cc -91czxs.com -91daizhang.com -91danji.com -91data.com -91dba.com -91dbb.com -91dbq.com -91ddcc.com -91ddedu.com -91dena.com -91dict.com -91display.com -91dnso.com -91doujin.com -91dub.com -91duobaoyu.com -91dyl.com -91exam.org -91exiu.com -91feiyong.com -91feizhuliu.com -91fifa.com -91flac.com -91game.com -91gaoding.com -91gaoqing.com -91goodschool.com -91guohuaw.com -91guzhi.com -91h5.cc -91haiju.com -91haoke.com -91heytea.com -91huagu.com -91huayi.com -91huoke.com -91ios.com -91jbz.com -91jf.com -91jiabohui.com -91jiafang.com -91jianguo.com -91jin.com -91jinrong.com -91jinshu.com -91jkj.com -91jkys.com -91jm.com -91jmw.com -91job.com -91join.com -91jsj.com -91juice.com -91jxtc.com -91kami.com -91keto.com -91ks.cc -91kuzhan.com -91ld.com -91lda.com -91lewei.com -91liangcai.com -91linux.com -91listen.com -91lmgg.com -91lx.com -91lxs.com -91maker.com -91mariadb.com -91maths.com -91mcpz.com -91mitang.com -91money.com -91muzhi.com -91nzh.com -91open.com -91paobao.com -91pdf.com -91php.com -91pkpk.com -91px.com -91qzc.com -91render.com -91ri.org -91ronghui.com -91rtb.com -91ruyu.com -91safety.com -91sd.com -91sem.cc -91shenshu.com -91smart.net -91soer.com -91soker.com -91sotu.com -91sph.com -91spj.com -91sport.cc -91stb.com -91student.com -91suan.com -91suke.com -91taobaoquan.com -91tech.net -91tianqi.com -91ting.net -91tingge.com -91town.com -91tuyatu.com -91tw.net -91tzy.com -91ud.com -91up.com -91uqu.com -91vpn.com -91vps.com -91vst.com -91waijiao.com -91wan.com -91wangcai.com -91wangmeng.com -91watches.com -91way.com -91weimi.com -91weiwang.com -91wenmi.com -91whcp.com -91wii.com -91wllm.com -91wujia.com -91wutong.com -91wzg.com -91xcm.com -91xhg.com -91xiake.com -91xiazai.com -91xinche.com -91xsj.com -91xueshu.com -91xww.com -91xy.com -91y.com -91yao.com -91yian.com -91yinpin.com -91yixun.com -91yk.com -91yong.com -91you.com -91youban.com -91yuandian.com -91yuedu.com -91yunying.com -91yxbox.com -91zhiwang.com -91zhuti.com -91zwk.com -91zy.com -91zytu.com -92.net -921.com -9211.com -921118.wang -921716.com -9217w.com -9217web.com -921lu.com -922000.com -922c25.com -923qp6.com -925pk.com -925ps.com -927.la -927927.com -927953.com -927jx.com -928383.com -928vbi.com -92913.com -92987.com -9299.net -92anycall.com -92aq.com -92ay.com -92bbs.net -92bizhi.com -92byg.com -92caijing.com -92cloud.com -92cy.cc -92demo.com -92dp.com -92dxs.com -92ez.com -92fox.com -92game.net -92gushi.com -92gzc.com -92hidc.net -92jc.net -92jiangbei.com -92jn.com -92kaifa.com -92kk.com -92le.com -92lm.com -92lucky.com -92mp.com -92ni.com -92python.com -92sucai.com -92tianjin.com -92to.com -92u93e.com -92wan.com -92wenzhai.com -92wudao.com -92wx.com -92wy.com -92xygame.com -92you.com -9312.net -933.moe -934dsw.com -9355.com -93636.com -936647.com -936649.com -936u.com -9374ttyy.com -9377.com -937785.com -937791.com -9377a.com -9377co.com -9377df.com -9377g.com -9377ja.com -9377ku.com -9377ne.com -9377os.com -9377s.com -9377si.com -9377z.com -938030968.com -93913.com -9396.net -93966.com -93bok.com -93cg.com -93eu.com -93hdw9.com -93hui.com -93jiang.com -93kk.com -93ku.com -93lh.com -93ne.com -93njf0.com -93pk.com -93sdk.com -93soso.com -93tyy.com -93wgames.com -93zp.com -93zw.com -941.so -941fa.com -941jy.com -941mg.com -942ss.com -94445.com -9448x.com -9453job.com -945idc.com -945n48.com -9466.com -946vr.com -94831.com -9495.com -9499.net -94994.com -949949.com -94afx.com -94cb.com -94cto.com -94dreamer.com -94dwc.com -94he38.com -94hnr.com -94i5.com -94ip.com -94ixs.com -94lm.com -94mxd.com -94nw.com -94oz.com -94php.com -94pm.com -94qy.com -94rp.com -94te.com -94uv.com -94xsw.info -94xy.com -94yiren.com -94you.net -94ys.com -95.com -950004.com -95060.com -95081.com -950901.com -95095.com -95105369.com -95105555.com -95105556.com -95105899.com -9512.net -951368.com -95158.com -95169.com -95191.com -95195.com -952731.com -9527cha.com -9527cloud.com -95298.net -95303.com -95408.com -95504.net -95508.com -95511-8.com -95516.com -95516.net -95526.mobi -9553.com -9557.com -95572.com -95579.com -95588.com -95598pay.com -95599.hk -955yes.com -955yx.com -9560.cc -9564.com -9565.com -957ds.cc -9588.com -958jbs.com -959249.com -95949c.com -9596956.com -95amxpj.com -95book.com -95en.com -95epay.com -95fenapp.com -95gq.com -95idc.com -95jr.com -95k.com -95links.com -95name.com -95ns.net -95nw.com -95px.com -95vintage.com -95xiu.com -95ye.com -95yijing.com -96005656.com -960123.com -960638.com -96090090.com -960rc.com -9610.com -9611111.com -96160.cc -96189.com -9618968.com -96192.com -961u.com -962.net -96211.com -962121.net -962168.com -962222.net -96225.com -962518.com -962600.com -962740.com -96369.net -9637.com -963999.com -96516.net -96520.com -96533.com -9665.com -966599.com -9666sr.com -9669.com -96711jmbm.com -96804.com -96811.com -96822.com -9685222.app -9685333.app -9685777.app -96877.net -968pk.com -969009.com -9695565.com -9696e.com -9697.com -969g.com -96app.com -96bbs.com -96caifu.com -96chengbao.com -96dp.com -96go.com -96hq.com -96jm.com -96jx.com -96kaifa.com -96kb.com -96lh.net -96lou.com -96ni.net -96pc.com -96pk.com -96plus.com -96sdk.com -96shuba.cc -96sir.com -96ttt.com -96u.com -96weixin.com -96yx.com -96zxue.com -970655.com -9718.com -9718game.com -9724.com -973.com -973618.com -973xs.com -97616.net -9766.com -97695.wang -97775.com -977pk.com -977t.com -978012.com -97828bb.com -9787.com -978sy.com -97936.com -97971.com -97973.com -9797ly.com -9799.com -97add.com -97atc.com -97cms.com -97dod.com -97douyin.com -97gg.net -97go.com -97hs.com -97jumi.com -97jz.com -97kaifa.com -97kid.com -97kpb.com -97lk.com -97lp.com -97lpw.com -97manhua.com -97ol.com -97riju.net -97rp.com -97ting.com -97ui.com -97uimg.com -97wd.com -97xiaoshuo.com -97xiaoshuo.net -97xiazai.com -97you.net -97yrbl.com -98.com -9800.com -980cje.com -98201111.com -9823df.com -9831.com -983525.com -984g.com -985.so -98523.com -985994.com -985college.com -985gm.com -98654.com -987.com -9870123.com -9870n.com -9877yx.com -987app.com -987jx.com -987jx.net -987you.com -988.se -988001.com -98809.com -988272.com -988640.com -988svip.com -9898c.com -98a.ink -98ep.com -98fp.com -98jx.com -98jy.net -98key.com -98mp.com -98nice.com -98one.com -98stack.com -98t.net -98yigou.com -98znz.com -99-idc.com -99-ss.com -99.am -99.com -99083.com -9908qhb.com -990990.com -9911.biz -99114.com -99118.com -99166.com -991726.com -9919.wang -9919345.com -991kang.com -9928.tv -992892.com -9939.com -993dy.com -993h.com -994wan.com -9951766.com -9953636.com -9955365.net -9955993.com -995jz.com -996.com -996.pm -9966.org -9966333.com -9966w.com -996a.com -9973.com -997788.com -997hw.com -998.com -9981ypk.com -998580.com -99887w.com -998dns.com -998jk.com -998jx.com -9991.com -999120.net -999178.com -99939.com -9996132.com -999777.com -9998.tv -999ask.com -999brain.com -999d.com -999dns.net -999kan.com -999tea.com -999wx.com -999xy.net -99aiji.net -99bdf.com -99biaozhun.com -99bill.com -99bo.cc -99cc.com -99ceo.net -99cfw.com -99cloud.net -99daigou.com -99danji.com -99ddd.com -99down.com -99downer.com -99dushu.com -99dw.com -99edu.net -99eo.com -99eyao.com -99fang.com -99fei.net -99fenlei.com -99fund.com -99fund.org -99haoche.com -99haoling.com -99hdf.com -99hkjf.com -99huizhou.com -99ielts.com -99inn.cc -99jianzhu.com -99jiaoshi.com -99k5.com -99kgames.com -99lb.net -99leba.com -99max.me -99mc.com -99meiju.tv -99meijutv.com -99meili.com -99mingxing.com -99mst.com -99music.net -99n3.com -99niu.com -99pdf.com -99pet.com -99ppt.com -99pto.com -99qh.com -99qimingzi.com -99qumingzi.com -99read.com -99rom.com -99shiji.com -99sky.com -99sun.com -99sushe.com -99vu.com -99wed.com -99weiqi.com -99wuxian.com -99xitie.com -99xkx.com -99xr.com -99xsw.cc -99xsw.org -99xxg.com -99xyx.com -99yesrs.com -99yoo.com -99youmeng.com -99ys.com -99zhizhu.com -99zihua.com -99zuowen.com -99zzw.com -9ailai.com -9aimai.com -9aiot.com -9air.com -9aoduo.com -9aola.com -9apay.com -9beike.com -9bianli.com -9bie.org -9cb.com -9ccapital.com -9ccmsapi.com -9chew.com -9chun.com -9clive.com -9coc.com -9conn.net -9cts.com -9cwx.com -9d19.com -9d4d.com -9damao.com -9damao.net -9day-game.com -9ddm.com -9deli.com -9dfx.com -9djw92.com -9dm.net -9douyu.com -9droom.com -9duw.com -9dwork.com -9dyjbj.com -9earth.com -9ele.com -9enjoy.com -9fav.com -9fbank.com -9first.com -9fs.com -9g.com -9gaoding.com -9gty.net -9gui.net -9hcom.com -9he.com -9host.org -9ht.com -9icode.net -9icy.com -9idudu.com -9ie7.com -9igcw.com -9ihb.com -9ihere.com -9ihome.com -9ihs.com -9ilu.com -9imobi.com -9inx.com -9iphp.com -9ishe.com -9ixiangsheng.com -9iyoo.com -9j9y.com -9ji.com -9jiu9jiu.com -9jm7ywls.icu -9juewu.com -9juren.com -9jx.com -9k51.com -9k9by.com -9k9k.com -9k9ms.com -9kjt.com -9kld.com -9ku.com -9kus.com -9le8.com -9linux.com -9liuda.com -9man.com -9mayi.com -9mbv.com -9mcu.com -9mi.me -9mi01.com -9miao.com -9miaoketang.com -9miaoxueyuan.com -9mic.com -9msg.com -9nali.com -9now.net -9ok.com -9om.com -9open.com -9orange.com -9qc.com -9qu.com -9qu5.com -9rmb.com -9see.com -9simg.com -9skm.com -9sky.com -9stor.com -9subi.com -9syw.com -9taobao.com -9thws.com -9to.com -9tong.com -9too.net -9tov.com -9tripod.com -9txs.com -9u.net -9upk.com -9v.com -9w9.com -9wan9.com -9wee.com -9wee.net -9weihu.com -9wuli.com -9xiazaiqi.com -9xiu.com -9xkd.com -9xu.com -9xwang.com -9xyg.com -9xz.net -9yao.com -9yaocn.com -9yc.com -9ye.com -9yjk.com -9yjobtm.com -9yoho.com -9you.com -9you.net -9yread.com -9yuntu.com -9yuonline.com -9ywp.com -9zhitx.com -9zjob.com -9zonline.com -9zx.com -a-du.net -a-hospital.com -a-jazz.com -a-liai.com -a-sy.com -a0598.com -a0b88.com -a0bi.com -a0c00.com -a0c77.com -a1.mzstatic.com -a1166.com -a135.net -a152.cc -a166.com -a1714.com -a2.mzstatic.com -a2048.com -a21fs.com -a21yishion.com -a2dongman.com -a3.mzstatic.com -a3p4.com -a4.mzstatic.com -a4s6.com -a5.mzstatic.com -a5.net -a5628.com -a5805.com -a5a5a5.com -a5idc.net -a5r2.com -a5r6.com -a632079.me -a67.com -a67744.com -a67dy.com -a6a1.com -a7.com -a8.com -a8f947.com -a8tg.com -a8v5.com -a8z8.com -a9188.com -a9377j.com -a963.com -a9cdn.com -a9vg.com -aa43z7.com -aa65535.com -aa7.org -aa8828.com -aa99cdn.com -aaahsxb.com -aaapeixun.com -aaayun.com -aad.tw -aadongman.com -aads-cng.net -aamachina.org -aaniao.com -aapig.com -aaqqw.com -aarch64.me -aardio.com -aaspt.net -aastartups.com -aatccn.com -aaxxr.com -aayis.com -aazao.com -aazyz.com -ab173.com -ab59.com -ab74.com -ab95569.com -abab.com -abacaipu.com -abang.com -abbooa.com -abbyschoice.net -abbyychina.com -abc-ca.com -abc12345.net -abc12366.com -abc188.com -abc360.com -abcache.com -abcbxw.com -abcd5.com -abcdocker.com -abcdserver.com -abcdv.net -abcdvbbs.net -abcfintech.com -abchina.com -abcjiaoyu.com -abcjifang.com -abckantu.com -abclogs.com -abcs8.com -abcsub.com -abctang.com -abcve.com -abcxs.com -abcydia.com -abczw.com -abdstem.com -abe-tech.com -abeacon.com -abecage.com -aberdeenchinese.com -abiaogw.com -abiechina.com -abiestem.com -abifsey.com -abilie.com -abitcg.com -abiz.com -ablanxue.com -able-consultant.com -able-elec.com -ableaders.com -ablejeans.com -ablesci.com -ablesky.com -abletive.com -ablman.com -abloz.com -abmau.com -aboatedu.com -aboboo.com -aboilgame.com -abooky.com -aboutcg.com -aboutcg.net -aboutcg.org -aboutgk.com -aboutidc.com -aboutnuke.org -aboutyun.com -abreader.com -abroadstar.com -abs-world.net -abslw.com -abthink.com -abtionb.com -abto.cc -abuquant.com -abusi.net -abuyun.com -ac268.com -ac57.com -acadki.com -acadn.com -acaob.com -acbnews.com.au -acc-ask.com -acc5.com -accelink.com -accepa.com -accessgood.com -accessibilityunion.org -accessoft.com -accesspath.com -accgame.com -acconsys.com -account.htcvive.com -account.samsung.com -accsh.org -accspeed.com -accu.cc -accyy.com -acde.net -ace-pow.com -acechuang.com -acejoy.com -acelamicro.com -acesheep.com -acewill.net -acftu.org -acfun.cc -acfunchina.com -acfunwiki.org -acg-moe.com -acg.gd -acg.gg -acg.tv -acg17.com -acg18.com -acg183.com -acg18s.com -acg2.com -acg4.com -acg456.com -acg6.com -acg7.com -acgaa.xyz -acgcd.com -acgcp.com -acgdaily.com -acgdb.com -acgdoge.net -acgface.com -acgist.com -acgjie.com -acglf.com -acglingsheng8.com -acgmall.com -acgn.pw -acgnt.com -acgp.xyz -acgpiping.net -acgr.xyz -acgres.com -acgsj.com -acgtofe.com -acgtouch.com -acguz.com -acgvideo.com -acgvr.com -acgw.pw -acgz.xyz -acgzc.com -acgzone.net -achsd.com -aci-wh.com -acicfg.com -aciml.com -acing.com -acingame.com -acirno.com -acjw.net -ackeline.com -acmcoder.com -acmicpc.info -acmoba.com -acmsearch.com -acmx.xyz -acnow.net -aco-musical.com -aconline.com -acoolread.com -acpf-cn.org -across-mbox.com -acrpc.com -acshoes.com -acsrq.com -act-telecom.com -actacams.com -actamath.com -actcn.net -actime.net -actions-semi.com -actionsky.com -activeclub.net -activepower.net -actom.me -actoys.com -actranslation.com -actself.me -actuive.com -acucn.com -acumoxj.com -acuworld.net -acwifi.net -acwing.com -acxiomapac.com -acznw.com -ad-cn.net -ad-gone.com -ad-goods.com -ad-mex.com -ad-safe.com -ad-survey.com -ad-young.com -ad0359.com -ad110.com -ad12345.com -ad321.cc -ad5.com -ad518.com -ad7.com -ad778.com -adamlu.net -adamseo.com -adanxing.com -adarrive.com -adas-china.org -adashuo.com -adbats.com -adbxb.com -adccd.com -adcdownload.apple.com -adcdownload.apple.com.akadns.net -adcmove.com -adconfer.com -addaad.com -addgog.com -addictiongwas.com -addnewer.com -addoom.com -addpv.com -addsd.com -adeao.com -adeaz.com -adebang.com -adesk.com -adf.cc -adfeiwo.com -adflying.com -adfortest.com -adfuns.com -adfyt.com -adg-dental.com -adgomob.com -adhei.com -adhhome.com -adhimalayandi.com -adhouyi.com -adhubbj.xyz -adhudong.com -adidasevent.com -adiexpress.com -adiic.com -adinall.com -adinallcdn.com -adirects.com -adjie.com -adjucai.com -adjumo.com -adjuz.com -adl888.com -adl999.com -adlefee.com -adlefei.com -adluckin.com -adlvyou.com -admai.com -admaimai.com -admin.edu.pl -admin10000.com -admin168.net -admin5.com -admin5.net -admin6.com -admin60.com -admin88.com -adminso.com -admintony.com -adminxue.com -adminxy.com -admire.so -admpub.com -adnmb.com -adnmb1.com -adnmb2.com -adnmb3.com -adnonstop.com -adnyg.com -adobeae.com -adobeedu.com -adobetop.com -adoceans.com -adolphlwq.xyz -adoregeek.com -adpchina.com -adpgsc.com -adplusx.com -adpolestar.net -adportion.com -adquan.com -adrenascer.com -ads8.com -adsage.com -adsagedsp.com -adsame.com -adscover.com -adsensor.org -adservice.google.com -adslr.com -adsmogo.com -adsmogo.mobi -adsmogo.net -adsmogo.org -adssaas.com -adssap.com -adsspr.com -adsunflower.com -adt100.com -adtchrome.com -adtime.com -adtiming.com -adtmm.com -adunicorn.com -adunioncode.com -adunite.com -adups.com -adutp.com -adv5678.com -adview.com -advuser.com -adwangmai.com -adwetec.com -adwintech.com -adwo.com -adwuhu.com -adwzw.com -adx.ms -adxhi.com -adxiaozi.com -adxiny.com -adxpand.com -adxquare.com -adxvip.com -adyun.com -adzh.com -adzhongdian.com -adzop.com -adzshd.com -ae-people.com -ae256.com -ae60.com -aebiz.net -aec188.com -aecichina.com -aeenets.com -aegcar.com -aegins-dns.com -aegins-dns.net -aegins-network.net -aegins.cc -aegins.com -aegins.net -aehyok.com -aemedia.org -aendc.com -aeo-cctv.com -aeonlifes.com -aepku.com -aera-51.com -aerfaying.com -aerochina.net -aeroimginfo.com -aes01.com -aesdrink.com -aesucai.com -aevit.xyz -aex88.com -aexsw.com -af360.com -afanti100.com -afarway.com -afcec.com -afdian.net -afdiancdn.com -afdsc.com -afdvr.com -afengseo.com -afengsoft.com -afenxi.com -affecthing.com -affu.net -afgame.com -afhxm.com -afie.xin -afilmb.com -afjk.com -afjob88.com -afriendx.com -afshanghai.org -aft1v1.com -aft888.com -afu.io -afuchina.com -afunan.com -afunapp.com -afvdrf.vip -afzhan.com -ag17.wang -ag365.com -agalwood.net -agamepower.com -agcloudcs.com -agctc.com -age06.com -agemiracles.com -agenge.com -agenow.com -agentzh.org -agfoodpartnership.com -agile-china.com -agileex.com -aginomoto.com -agiso.com -agoodme.com -agora.io -agoraesportes.com -agoteno.com -agotools.com -agrantsem.com -agri35.com -agriturismi-sicilia.com -agrochemshow.com -agrodt.com -agrofairs.com -agrokingcn.com -agrosg.com -agrowingchina.com -agucn.com -aguo.com -agxs.net -agxsw.com -ah-inter.com -ah-px.com -ah12333.com -ah163.com -ah3c.com -ah499.com -ah5166.com -ah8.cc -ahacpp.com -ahalei.com -ahanxun.com -ahao.moe -ahaohao.com -ahauto.com -ahbaojia.com -ahbb.cc -ahbdfyy.com -ahbys.com -ahbztv.com -ahbzyy.com -ahcaijing.com -ahcaw.com -ahchanyi.com -ahcnb.com -ahdsez.com -ahdzfp.com -aheading.com -ahfbz.com -ahfdcb.com -ahfensitong.com -ahglj.com -ahgssh.com -ahhanmi.com -ahhhjx.com -ahhouse.com -ahhs10000.com -ahhtzx.com -ahhxcm.com -ahjdq.com -ahjem.com -ahjgxy.com -ahjingzhan.com -ahjk.com -ahjtxx.com -ahjyzb.com -ahjzjy.com -ahjzw.com -ahkemi.com -ahkende.com -ahkjksw.com -ahkjw.com -ahkrd88.com -ahkxsoft.com -ahlib.com -ahlife.com -ahljnews.com -ahmayun.com -ahmky.com -ahnews.org -ahougn.com -ahphi.com -ahqmdq.com -ahqnrc.com -ahrcty.com -ahrefa.com -ahrnsm.com -ahrunzi.com -ahscl.com -ahshsz.com -ahshuhua.net -ahsjxjy.com -ahsyj.com -ahsylsy.com -ahtarena.com -ahteacher.com -ahtlbyby.com -ahtlgc.com -ahtrain.com -ahtuangou.com -ahu.cc -ahuo5.com -ahuyi.com -ahwwfn.com -ahwwnews.com -ahydnet.com -ahydwy.com -ahyessoft.com -ahyhj.com -ahyouan.com -ahyouth.com -ahyx.cc -ahzs10000.com -ahzww.net -ai-cai.com -ai-competition.com -ai-factory.com -ai-indestry.com -ai-qingchang.com -ai-sheji.com -ai-start.com -ai-thinker.com -ai.cc -ai012.com -ai200808.com -ai2hao.com -ai7.com -ai7.org -ai8g.com -ai9475.com -aiagain.com -aiagain.net -aiai6.com -aiaisz.xyz -aiaiu.com -aiaor.com -aiba.com -aibaimm.com -aibaix.com -aibang.com -aibang5.com -aibaov.com -aibeidian.com -aibing.cc -aibo123.com -aibookba.com -aibosha.com -aibusy.com -aicai.com -aicaicdn.com -aicaike.com -aicdn.com -aicdn2.com -aicdn4.com -aichaicp.com -aichaoxing.com -aichatu.com -aichawu.com -aicheren.com -aichunjing.com -aicili.pw -aiclicash.com -aiclk.com -aicloud.com -aicode.cc -aicoinstorge.com -aicsnet.com -aicu8.com -aicunfu.com -aidafen.com -aidai.com -aidaily.com -aidaiz.com -aidalan.com -aidangbao.com -aidanji.com -aidaxing.com -aidaxue.com -aideep.com -aidefence.org -aideschool.com -aidg.cc -aidianji.net -aidiao.com -aidigger.com -aidigong.com -aidimedia.com -aidingbuding.com -aidlearning.net -aidog.com -aidong.me -aidoor.net -aidpaper.com -aidrive.com -aidujiudian.com -aiduoka.com -aiduwenxue.com -aidzs.com -aiec-alliance.com -aiegle.com -aiemy.com -aier021.com -aier0755.com -aierchina.com -aiezu.com -aifamu.com -aifanfan.com -aifang.com -aifangke.com -aifanr.net -aifanyi.net -aifcdn.com -aifei8.net -aifengjie.com -aifont.com -aifu10.com -aifu360.com -aigame100.com -aiganggu.com -aige010.com -aigei.com -aigewc.com -aigo.com -aigodiy.com -aigou.com -aigtek.com -aigupiao.com -aihacoin.com -aihaisi.com -aihala.com -aihandu.com -aihanfu.com -aihanfu.net -aihangtian.com -aihao.cc -aihao.org -aihecong.com -aihehuo.com -aihelp.net -aihoom.com -aihu.me -aihuahua.net -aihuajia.com -aihuaju.com -aihuau.com -aihuishou.com -aihundan.com -aihuo.cc -aii-alliance.org -aiijournal.com -aiimg.com -aiimooc.com -aiioii.com -aiizen.net -aijc.net -aiji66.com -aijianji.com -aijiaoqi.com -aijigeci.com -aijikong.com -aijishu.com -aijiutou.com -aiju.com -aikac.com -aikaitao.com -aikaixin.com -aikaiyuan.com -aikan.tv -aikan8.com -aikang.com -aikanshu8.com -aikcms.com -aiketour.com -aikeu.com -aikexi.com -aikf.com -aikontec.com -aikucun.com -ailaba.org -aileleba.com -ailete.com -ailewan.com -aili.com -ailianbang.com -ailinux.net -ailinzhou.com -ailisn.com -ailiyun.com -ailom.com -ailongmiao.com -ailuntan.com -ailvxing.com -ailvzhi.com -ailvzhidu.com -aimagang.com -aimantech.com -aimaoji.com -aimapp.net -aimeas.com -aimeike.tv -aimeit.com -aimikuajinggou.com -aiminer.cc -aimipay.net -aimiplay.com -aimituan.com -aimks.com -aimo.moe -aimodou.net -aimoge.com -aimsen.com -aimuju.com -ainiapp.com -ainirobot.com -ainiseo.com -ainiu.net -ainiugu6.com -ainiuwa.com -ainyi.com -aiodt.com -aiotvoice.com -aiouportal.com -aipai.com -aipark.com -aipear.com -aipenglai.com -aipiaxi.com -aipingxiang.com -aipinko.com -aipinpan.com -aippi-china.org -aiprose.com -aips.me -aipuo.com -aipz.com -aipz777.com -aiqianduan.com -aiqianxq.com -aiqin.com -aiqisoft.com -aiqiy.com -aiqiye.cc -aiqiyi.com -aiqiyivip.com -aiqu.com -aiqu.la -aiqucn.com -aiquya.com -aiqzu.net -air-level.com -air-matters.com -air-quality.com -air.cc -airasia.com -airbft.com -airchina.com -airchinacargo.com -airchinagroup.com -airchinaim.com -airchinajet.com -airchinamedia.com -aircn.org -aircourses.com -airdropin.com -airen1314.com -airforceworld.com -airmate-china.com -airmb.com -airmobyte.com -airnut.com -airpub.io -airsavvi.com -airspa.net -airtofly.com -airtu.com -airwh.com -ais56.com -aisaohuo.com -aisaw.com -aisbeijing.com -aisearch.cc -aisee.tv -aiseminar.com -aishangcan.com -aishengji.com -aisila.com -aisino.com -aisinogd.com -aisinogz.com -aisixiang.com -aisk.me -aisky.cc -aiskycdn.com -aisojie.com -aispeech.com -aispreadtech.com -aitaojin.com -aitaotu.cc -aitaotu.com -aite.xyz -aitebuy.com -aitecar.com -aitemple.com -aiti.fun -aitiancheng.com -aitoushe.com -aitrans.net -aituan.com -aitupian.com -aituwo.com -aitxt.com -aityp.com -aiurl.com -aiuw.com -aiuxdesign.com -aiuxian.com -aiuxstudio.com -aivcd.cc -aiviy.com -aiwall.com -aiwan4399.com -aiwan91.com -aiwanba.net -aiwanpai.com -aiwansc.com -aiweibang.com -aiweibk.com -aiweline.com -aiwen.cc -aiwenwo.net -aiwenyi.com -aiworkspace.com -aiwulao.com -aixchina.net -aixcoder.com -aixgl.com -aixiaoduo.com -aixiashu.com -aixiatxt.com -aixiawa.com -aixiegao.com -aixiezuo.com -aixifan.com -aixigua.com -aixinbaomu.com -aixinquban.com -aixinwu.org -aixinyunfan.com -aixq.com -aixsq.com -aixuedai.com -aixuefu.com -aixuejun.com -aixuetang.com -aixuexi.com -aixyz.com -aiyaapp.com -aiyadu.com -aiyangedu.com -aiyanqing.com -aiyaohai.com -aiyaopai.com -aiyichuan.com -aiyidu.com -aiyinghun.com -aiyingli.com -aiyingshi.com -aiyizhuang.com -aiykj.com -aiyole.com -aiyou.com -aiyou.tv -aiyouman.com -aiyoumi.com -aiyouxi.com -aiyouxi07.vip -aiyoweia.com -aiyuangong.com -aiyuke.com -aizaoqi.com -aizhan.com -aizhangfen.com -aizhanku.com -aizhaomu.com -aizhenghun.com -aizhengli.com -aizhengrong.net -aizhenrong.com -aizhet.com -aizhi.biz -aizhibaby.com -aizhicn.com -aizhigu.tv -aizhizu.com -aizhuizhui.com -aiziti.net -aizongyi.com -aizuna.com -aizuopin.com -ajaxjs.com -ajaxstu.com -ajbbkf.com -ajbtv.net -ajcctv.com -ajclass.com -ajebw.com -ajiang.net -ajinga.com -ajkcdn.com -ajkdns2.com -ajkimg.com -ajmide.com -ajoumba.com -ajpsp.com -ajrcb.com -ajs17.com -aju.space -ajwang.com -ajweishequ.com -ajxlx.com -ajyg.com -ak0.tw -ak1ak1.com -ak47ids.com -akaedu.org -akaifa.com -akaiwl.com -akandou.com -akanmai.com -akaxin.com -akbe.com -akbkgame.com -akdanji.com -akdcar.com -akdurak.com -akerp.com -akey.im -akey.me -akeyun.com -akhtm.com -akhy.com -akinoheya.com -akjunshi.com -akkogear.com -aklmbh.com -akniu.com -aknzb.com -akomr.com -akoofs.com -akppt.net -akq.ee -akr-developers.com -akscan.com -aksxw.com -aku.pub -akuaikan.com -akuziti.com -akyiyou.com -akylq.com -al-jin.com -al8l.com -alabmed.com -alaccountant.com -alacun.com -aladdin-e.com -aladdinnet.com -alading123.com -alai.net -albarhotelcollection.com -albbzjx.com -albltc.com -aldcup.com -aldnew.com -aldohaco.com -aldtop.com -aldwx.com -aledeco-hk.com -aleest.com -alenshaw.com -alertover.com -alexa.sx -alexyan.cc -aleyoo.com -alfeng.com -alfheim.cc -alfz999.com -algorithmart.com -ali213.com -ali213.net -ali37.net -ali727.com -aliagain.com -alianhome.com -aliapp.com -aliapp.org -aliavv.com -alibaba-inc.com -alibaba.com -alibaba.net -alibabacloud.com -alibabacorp.com -alibabadns.com -alibabadoctor.com -alibabagroup.com -alibabaonline.com -alibabapictures.com -alibabaplanet.com -alibabatech.org -alibabaued.com -alibabausercontent.com -alibench.com -alibjyun.com -alibjyun.net -alibole.com -alibuybuy.com -alicall.com -alicdm.com -alicdn.com -alicdngslb.com -alicelj.com -alicloudapi.com -alicloudlayer.com -alicloudsec.com -alicloudwaf.com -alicontainer.com -alidata.org -alidayu.com -alidns.com -aliedge.com -aliegame.com -alienfans.net -aliexpress.com -aliexpress.ru -alifabu.com -aligames.com -aligaofang.com -aligfwaf.com -aliguanlian.com -alihd.net -alihuahua.com -aliimg.com -alijijinhui.org -alijk.com -alikunlun.com -alikunlun.net -alili.tech -aliloan.com -alimama.com -alimebot.com -alimmdn.com -alinx.com -aliog.com -alip.biz -alipay-eco.com -alipay.com -alipay.hk -alipay.net -alipaycs.com -alipaydev.com -alipaydns.com -alipaylog.com -alipayobjects.com -alipcsec.com -aliplay.com -aliplus.com -aliqiche.com -aliresearch.com -alisoft.com -alisports.com -alitchina.com -alithefox.net -alithon.com -alitrip.com -alitrip.hk -aliued.com -aliunicorn.com -aliuv.com -alivecdn.com -alivl.com -alivv.com -alivv.net -aliway.com -aliwd.com -aliwears.com -aliwx.net -alixinwen.com -alixixi.com -alixox.com -aliyiyao.com -aliyue.net -aliyun-cdn.com -aliyun-inc.com -aliyun-ns.com -aliyun-youhui.com -aliyun.com -aliyun.org -aliyun365.com -aliyunbaike.com -aliyuncdn.com -aliyunceng.com -aliyuncs.com -aliyundaiwei.com -aliyunddos0010.com -aliyunddos0018.com -aliyunddos0020.com -aliyunddos0026.com -aliyunddos0030.com -aliyunddos1001.com -aliyunddos1002.com -aliyunddos1005.com -aliyunddos1006.com -aliyunddos1009.com -aliyunddos1010.com -aliyunddos1011.com -aliyunddos1012.com -aliyunddos1013.com -aliyunddos1015.com -aliyunddos1016.com -aliyunddos1017.com -aliyunddos1018.com -aliyunddos1019.com -aliyunddos1020.com -aliyunddos1022.com -aliyunddos1023.com -aliyunddos1025.com -aliyunddos1026.com -aliyunddos1028.com -aliyunddos1029.com -aliyundrive.com -aliyunduncc.com -aliyundunwaf.com -aliyunedu.net -aliyunfuwuqi.com -aliyungf.com -aliyunhn.com -aliyunj.com -aliyunlive.com -aliyunmeng.com -aliyunqifu.com -aliyunwaf.com -aliyunwaf1.com -aliyunwaf2.com -aliyunwaf3.com -aliyunwaf4.com -aliyunwaf5.com -aliyunyh.com -aliyunyhw.com -aliyunyunvip46.com -alizhaopin.com -alizila.com -aljj.com -alkuyi.com -all-dream.com -all3c.com -all4seiya.net -allappapi.com -allbrightlaw.com -allchinahardware.com -allchips.com -allcitygo.com -allcitysz.net -alldayfilm.com -alldk.com -alldobetter.com -allfang.com -allfunnies.com -allhistory.com -allianz360.com -allibook.com -alliedjeep.com -allinfinance.com -allinpay.com -alliread.com -alllget.com -alllook.tv -allmaga.net -allmei.com -allnow.com -allok.wang -alloyteam.com -allpayx.com -allposs.com -allpyra.com -allrace.com -allsenseww.com -allstack.net -allstor.org -alltoall.net -alltobid.com -alltosun.com -alltuu.com -allvideowidget.com -allwin368.com -allwinnertech.com -allwinso.com -allyes.com -allyes.net -allystar.com -alma-intl.com -almtlakes.org -aloha-ukulele.com -alonemonkey.com -along.party -alongsky.com -alookbrowser.com -alookql.com -alpaca.run -alpface.com -alpha-browser.com -alpha-star.org -alphabole.com -alphafun.com -alrseo.com -alsovalue.com -alswl.com -altstory.com -altxw.com -alu1886.com -aluaa.com -alumni-cn.org -alumni-scut.org -aluntan.com -alwaysdesign.xin -alwaysnb.com -alwindoor.com -alxw.com -alyisheng.com -alyxz.com -alyzq.com -am222566.com -am5.com -am774.com -am89.com -amaomb.com -amap.com -amarsoft.com -amassfreight.com -amaxchina.com -amazeui.org -amazingsys.com -amazon-awcs.com -amazon1688.com -ambassador-sh.com -ambassadorchina.com -amberbj.com -amberedu.com -ambereduwh.com -ambition-soft.com -ambitionbyte.com -amblrgg.co -amblrgg.live -ambow.com -amchamchina.org -amdotibet.com -amdt.net -amec-inc.com -amemv.com -americanobgyn.com -ameson.org -amethystum.com -amexpressnetwork.com -amfproject.org -amgbs.com -amgepic.com -amh.sh -amhaiqiang.com -amhimalayanet.com -amhl.net -amicool.net -amif-expo.com -amijiaoyu.com -aminer.org -aminglinux.com -aminoacid-jirong.com -amn57.com -amo9.com -amobbs.com -amon.org -amon1997.com -ampc8.com -ampcn.com -amplesky.com -ampmake.com -ampxl.com -ams-ic.com -amsjsy.com -amsoveasea.com -amssro.net -amsxdc.com -amtron-ic.com -amuletj.com -amuletor.com -amunion.com -amuren.com -amwiki.org -amysql.com -amyxun.com -amz123.com -amz520.com -amzcaptain.com -an-ran.com -an9.name -analysysdata.com -analytics-china.com -analyticskey.com -anandoor.com -anank.ke -ananzu.com -anatuprak.com -anav.com -anbang-life.com -anbanggroup.com -anchengcn.com -anchi-china.com -anchnet.com -ancii.com -ancun.com -and568.com -andaike.com -andan.me -andefz.com -andhj.com -andpay.me -andreader.com -android-doc.com -android-studio.org -androidchina.net -androidcookie.com -androidinvest.com -androidmi.com -androidonline.net -androidonlines.com -androidperformance.com -androidvista.com -androidx86.net -andwi.com -andyiac.com -andyron.com -andyx.net -ane56.com -aneasystone.com -anf-z.com -anfan.com -anfang086.com -anfang6688.com -anfantech.com -anfeng.com -anfensi.com -angeeks.com -angel-game.net -angel-usa.com -angelcrunch.com -angelhome.org -angeljjangnara.com -angell-studio.com -angellsec.com -angelmom.org -angelyeast.com -angelyeast.ru -angesi16.com -angiefans.com -angli.me -anglo-chinese.com -angroups.com -angruo.com -anguanjia.com -angui.org -angwei.net -anhei2.com -anhei3.net -anheng.com -anhouse.com -anhuaedu.com -anhui365.net -anhuihouniao.com -anhuihr.com -anhuijrw.com -anhuilife.com -anhuimobile.com -anhuinews.com -anhuiry.com -anhuiyl.com -ani-com.net -aniccw.net -aniceapp.com -anicoga.com -anijue.com -anilnikz.com -anilumin.com -animalchina.com -animationcritics.com -animetaste.net -anitama.net -anitoys.com -aniu.so -aniu.tv -anix.xyz -anji-auto.com -anji-ceva.com -anji-logistics.com -anji-tonghui.com -anji66.net -anjian.com -anjianghu.net -anjimicro.com -anjuke.com -anjukestatic.com -ankang06.org -ankangrc.com -ankangwang.com -ankebio.com -ankelife.com -ankerjiedian.com -ankevip.com -ankichina.net -ankki.com -anlaiye.com -anlan.ga -anlibaby.com -anlibang.com -anlink.com -anlogic.com -anlu114.com -anmobc.com -anmoxiansheng.com -ann5.net -ann9.com -annangela.moe -annchain.io -anneishuo.com -annelhair.com -annhe.net -annto.com -anoah.com -anonym-hi.com -anorectal.net -anosmcloud.com -anoyi.com -anqiaoqiao.com -anqingonline.com -anqiu.cc -anqn.com -anqu.com -anquan.info -anquan.org -anquan.us -anquan35.com -anquanbao.com -anquanke.com -anquanone.com -anquanquan.info -anquantong.com -anquanxia.com -anquanzhuomian.com -anqunzhi.com -anrayer.com -anrenmind.com -anrip.com -anruichina.com -anruili.com -ansgo.com -anshi7.com -anshouji.com -anshugao.com -ansiding.com -ansky.com -ansteelgroup.com -ant-clean.com -anta.com -antairui.net -antarx.com -antboxnet.com -antbuyhot.com -antdsp.com -antdtheme.com -antdv.com -ante88.com -antebao.com -antebo.com -antfin-inc.com -antfin.com -antfortune.com -antgroup.com -anticheatexpert.com -antiy.com -antiy.net -antns.com -antpedia.com -antpool.com -antriver.com -antrol.com -antrtb.com -antsdaq.com -antspainter.org -antuan.com -antuan365.com -antuan532.com -antuni.com -antutu.com -antutu.net -antuzhi.com -antzk.com -anw.red -anw8.com -anweishi.com -anweizhi.com -anxcn.com -anxia.com -anxiangren.com -anxiaoer.com -anxin.com -anxin360.com -anxin360.net -anxinapk.com -anxindavisa.com -anxindeli.com -anxinlirong.com -anxinmai.com -anxinssl.com -anxinyisheng.com -anxiu.com -anxiw.com -anxjm.com -anxnr.com -anxz.com -any123.com -any8.com -anyan.com -anyang100.com -anyangedu.com -anyant.com -anybeen.com -anydd.com -anyelse.com -anyew.com -anyforweb.com -anygame.info -anyiidc.com -anyilv.com -anyka.com -anyknew.com -anymcu.com -anymetre.com -anyoy.com -anyrtc.io -anysdk.com -anysql.net -anytesting.com -anything-fh.com -anytranscription.com -anyuantec.com -anyunjianzhan.com -anyv.net -anyway.fm -anywlan.com -anywood.com -anyxz.com -anz8.com -anzerclub.com -anzext.com -anzhen.org -anzhi.com -anzhibao.com -anzhitan.com -anzhixiao.com -anzhixun.com -anzhouinvest.com -anzhuo2.com -anzhuoapk.com -anzhuoshangdian.com -anzhuotan.com -anzhuowo.com -anzogame.com -anzow.com -ao-hua.com -aoaiao.com -aoao365.com -aoaob.com -aoapp.com -aobaishi.com -aobanqd.com -aobo62.com -aobosoft.com -aoc.com -aocai2008.com -aocde.com -aocdn.com -aoch.com -aochunsy.com -aoclia.com -aocslb.com -aodabo.tech -aodaliyaqianzheng.com -aoddoll.com -aodeng.cc -aodianyun.com -aodingsy.com -aoeboke.com -aoedi.com -aoerdz.com -aoetech.com -aofenghuanjing.com -aofrp.com -aohuasports.com -aoidf3.com -aoisnow.net -aojauto.com -aojian.net -aojian2.net -aojiaostudio.com -aojiyingyu.com -aojiyouxue.com -aojiyuke.com -aojoo.com -aoju.net -aokangsports.com -aolai.com -aolaigo.com -aolaiw.com -aolei520.com -aoliday.com -aolylcd.com -aomeng.net -aomenyule.net -aomoxo.com -aomygod.com -aomygodstatic.com -aonaotu.com -aoofu.com -aoogee.com -aoomoo.com -aoratec.com -aoscdn.com -aosens.com -aoseo.com -aoserp.com -aoshitang.com -aoshu.com -aosong.com -aosoo.com -aoswtc.com -aotian.com -aotocn.com -aotrip.net -aotu.io -aotuzuche.com -aowenmarketing.com -aoxingboli.com -aoxingsujiao.com -aoxintong.com -aoxtv.com -aoxuis.me -aoya-hk.com -aoyahuanqiu.com -aoye.com -aoyii.com -aoyor.com -aoyotech.com -aoyou.cc -aoyou.com -aoyou365.com -aoyoux.com -aoyuge.com -aoyunque.com -aozehuanbao.com -aozhougoufang.com -ap88.com -apa.me -apabi.com -apachecn.org -apad.pro -apcdianyuan.com -apcdns.net -apclc.com -apcow.com -apcupse.com -apdcdn.com -apdnews.com -ape8.com -apeeri.com -apehorse.com -apeiwan.com -apelearn.com -apesk.com -apetdog.com -apexmic.com -apexyun.com -apgblogs.com -apgoview.com -aphidic.com -api-zdj.com -api.bz -apiadmin.org -apiairasia.com -apicase.io -apicloud.com -apicvn.com -apieye.com -apigwtencent.com -apiview.com -apizb.com -apizl.com -apizza.cc -apizza.net -apk3.com -apk8.com -apkdo.com -apkevery.com -apkgu.com -apkjam.com -apkplug.com -apkrj.com -apksc.com -apkui.com -apkyx.com -apkzu.com -aplan.tv -aplum-inc.com -aplum.com -apluscap.com -aplusunion.com -apmarry.com -apmbooth.com -apme-magnetics.com -apmvista.com -apnring.com -apogel.com -apollo.auto -apollotop.com -apous.com -apowo.com -apowogame.com -apoyl.com -apozh.com -app-123.com -app-echo.com -app-measurement.com -app-router.com -app-sage.com -app-store.name -app-web-seo-aso.com -app-zh.com -app001.com -app111.com -app111.org -app1116.app -app120.com -app17.com -app178.com -app2pixel.com -app2xp.com -app4cms.net -app4life.mobi -app86.com -app887.com -appadhoc.com -appao.com -apparelsos.com -appbi.com -appbk.com -appbocai.com -appbsl.com -appbyme.com -appbz.info -appc1.com -appccc.com -appchina.com -appchizi.com -appcoo.com -appcool.com -appcpa.net -appcpx.com -appcup.com -appdaka.com -appdao.com -appdown.info -appdp.com -appduu.com -appeasou.com -appgame.com -appganhuo.com -appgenuine.com -appgole.com -appgz.com -appicplay.com -appjiagu.com -appjzy.com -appkai.com -appkaifa.com -appkefu.com -appkg.com -applaudads.com -appldnld.apple.com -appldnld.g.aaplimg.com -apple110.com -apple21.com -apple4.us -apple88.net -apple886.com -apple90.com -appleads-trk.com -appleadstech.com -applebl.com -applecun.com -applecx.com -applehunt.com -appletuan.com -applex.net -applicationloader.net -applinzi.com -applysquare.com -applysquare.net -appmifile.com -appnode.com -appnz.com -appotronics.com -apppoo.com -appresource.net -apps.apple.com -apps.mzstatic.com -apps.samsung.com -apps121.com -appscan.io -appsflower.com -appshike.com -appsimg.com -appsina.com -appsodo.com -appstochina.com -apptao.com -appubang.com -appublisher.com -appurl.cc -appurl.me -appving.com -appvipshop.com -appvv.com -appweiyuan.com -appwill.com -appwuhan.com -appwuhan.net -appxcode.com -appxzz.com -appyao.com -appying.com -appyxxy.com -appzhonghua.com -appzhu.com -apsgo.com -apt-blog.net -apt.so -aptchina.com -aptenon.com -aptongbang.com -apusic.com -apxm.net -aqara.com -aqb.so -aqbxcdn9.com -aqbz.org -aqdesk.com -aqdh.com -aqdkc.com -aqdog.com -aqdstatic.com -aqee.net -aqfen.com -aqfy.net -aqhuayu.com -aqidb.org -aqinfo.net -aqioo.com -aqisite.com -aqiyi.com -aqniu.com -aqqcx.com -aqquan.org -aqstats.com -aqtd.com -aqtxt.com -aqua-lunash.com -aquacity-tj.com -aquanutriera.com -aquanyou.com -aquapipetech.com -aquayee.com -aqueck.com -aqumon.com -aqyun.com -aqyzm.com -aqzpw.com -aqzt.com -aqzyzx.com -ar-max.com -aragexpo.com -arc-uds.com -arcas-da.com -arccode.net -arcdmi.com -archcollege.com -archcy.com -archermind.com -archeros.com -archerpeng.com -archery8.com -archerysalon.com -archgo.com -archi-motive.com -archiant.com -archidead.net -archina.com -archina.org -archiname.com -archio.pro -architbang.com -archlinuxmips.org -archsummit.com -arcsoftai.com -arctime.org -ardme.net -ardsec.com -areachina.com -arebz.com -arefly.com -arenacdn.com -ares.dl.playstation.net -arestech-sz.com -arhieason.com -aria2.org -ariesmob.com -arinchina.com -aris.la -arisastar.com -arkfeng.xyz -arkoo.com -arkrdigital.com -arkteam.net -arliki.com -arm001.com -arm9.net -arm9home.net -armbbs.net -armchina.com -armhf.tw -armsword.com -armystar.com -arocmag.com -arondight.me -arongsoft.com -arp.cc -arpg2.com -arpun.com -arrail-dental.com -arrow-tower.com -arrownock.com -arrowos.net -arrows-hitech.com -art-ba-ba.com -art-child.com -art138.com -art2500.com -art456.com -artacode.com -artarrival.com -artbeijing.net -artbookinchina.com -artcns.com -artddu.com -artebuy.com -artech-graphite.com -artfinace.com -artfoxlive.com -artgohome.com -artgoin.com -arthome163.com -arthtml.com -arthurchiao.art -arti200.com -artimg.net -artintern.net -artlinkart.com -artliving.tv -artlnk.com -artmai.net -artmotions.net -artoolinks.com -artopmedia.com -artp.cc -artplateno.com -artplusall.com -artrade.com -artron.net -artronimages.com -artrus.net -arts-360.com -arts-kunst.com -artsbuy.com -artsdoor.com -artsncollections.com -artsren.com -artvisioncg.com -artwe.com -artwer.com -artww.com -artxuanyi.com -artxun.com -arvato-ocs.com -arvinhk.com -aryasec.com -aryasport.com -arygames.com -as-doll.com -as-exchange.com -as-hitech.com -as2sc.com -as3f.com -asadwsdapp.com -asaimi.com -asaki.me -asao.com -asbeijing.com -asc-wines.com -aschina.org -asciima.com -asczwa.com -asczxcefsv.com -asd868.com -asdbi.com -asdyf.com -asean-china-center.org -aseantradecenter.com -asen0713.com -aseoe.com -asfcfs.com -asfzl.net -asgxsy.com -ashan.org -ashj.com -ashma.info -ashvsash.com -ashvsash.net -asia-dns.com -asiabt.com -asiaci.com -asiacool.com -asiacorp.net -asiadancing.com -asiae.com -asiaeap.com -asiafactor.com -asiafpd.com -asiaidc.net -asiainfo-sec.com -asiainfo.com -asiainfodata.com -asianewsphoto.com -asiarobot.net -asicminermarket.com -asifadeaway.com -asilu.com -asimi8.com -askceph.com -askci.com -asketchup.com -askktv.com -asklib.com -asklicai.com -askmaclean.com -askpanda.cc -askququ.com -asktao.com -askwx.com -askxt.org -aslzw.com -asm64.com -asnlab.com -asnlab.org -aso.ink -aso100.com -aso114.com -aso120.com -asoasm.com -asomob.com -asp01.com -asp163.net -asp168.com -asp300.com -asp8php.com -aspbc.com -aspcool.com -aspire-info.com -aspirecn.com -aspirer.wang -aspku.com -aspnet.tech -aspsky.net -aspx.cc -aspxhome.com -aspxhtml.com -asqql.com -asrmicro.com -asrock.com -asrockind.com -asrockrack.com -asrsingapore.com -assbbs.com -assdrty.com -assets-global.viveport.com -assets.analog.com -assets.uxengine.net -assets.volvocars.com -assrt.net -astbbs.com -astestech.com -astfc.com -asthis.net -astorpiano.com -astrocn.org -astron.ac -astropulsion.com -asussmart.com -asussz-zp.com -aswetalk.net -asyzonline.com -aszw.org -at-lib.com -at-siac.com -at0086.com -at0086.net -at58.com -at78.com -at851.com -at98.com -ata-edu.com -ata-test.net -atacchina.com -ataoju.com -ataozx.com -atatech.org -atayt.com -atbug.com -atchip.com -atchip.net -atcontainer.com -atcpu.com -atelier39.org -atf.com -atfeng.com -atguigu.com -atguigu.org -athaitao.com -athmapp.com -atianqi.com -atido.com -ating.info -atitsc.com -atiyun.com -atjiang.com -atjiehun.com -atlas1688.com -atm988.com -atmbox.com -atobo.com -atoken.com -atomhike.com -atomic-art.com -atominn.com -atool.org -atool9.com -atoolbox.net -atop.fun -atpanel.com -atpapapa.com -atq8.com -atriumlee.com -atstudy.com -attakids.com -attri.mobi -attyou.com -atuoyi.com -atwtech.net -atxwm.com -atyun.net -atzjg.net -atzlinux.com -atzuche.com -auak.com -aucanlink.com -aucheng.cc -aucheng.vip -aucnln.com -audio160.com -audiobookbay.nl -audiocn.com -audiocn.org -audiofamily.net -audiy.com -audlabs.com -audley-printer.com -augsky.com -augth.com -augurit.com -auiou.com -auly.com -auniontech.com -aunload.com -aurogon.com -auroivf.com -auromcs.com -ausbio.com -auscoo.com -ausdn.com -aushy.com -ausny.com -auspiciousvp.com -aussino.net -austargroup.com -austarskill.com -austarstudy.com -ausuu.com -auto-beijing.com -auto-ccpit.org -auto-learning.com -auto-made.com -auto-mooc.com -auto-wo.com -auto000.com -auto18.com -auto318.com -auto328.com -auto333.com -auto510.com -auto6s.com -auto98.com -autoai.com -autobaidu.com -autobizreview.com -autocamel.com -autochina360.com -autochips.com -autodg.com -autodmp.com -autodry.net -autodwg.com -autoesd.com -autofull.net -autogslb.com -autoharbin.org -autohome.com -autohr.org -autoitx.com -autojingji.com -autojkd.com -autojs.org -autonavi.com -autono1.com -autoparts-yoto.com -autophagy.net -autoplansearch.com -autoprotect365.com -autoq7.com -autoqingdao.com -autoshanghai.org -autosmt.net -autosup.com -autozw.com -auvplayer.com -auvps.com -auwinner.com -auxgroup.com -auyou.com -av-ic.com -av001.com -av010.com -av199.com -av2.me -av269.com -av380.net -avacvisa.com -avalon.pw -avalon233.com -avanpa.com -avatarmind.com -avatarmobi.com -avc-mr.com -avc-ott.com -avc.com.tw -avdll.com -avexchina.com -avgchannel.com -avgh5.com -avhome.net -avic021.com -avicnews.com -avicone.com -avicsec.com -avicui.com -avivaqueen.com -avivasign.com -avjoy.me -avlsec.com -avlyun.com -avnpc.com -avoscloud.com -avrvi.com -avrw.com -avtechcn.com -avtt0033.com -avtt830.com -avttw1.cc -aw.cc -aw99.com -awa919.com -awaimai.com -awaker.hk -awaker.net -awaysoft.com -awbang.com -awc618.com -awcloud.com -awcn.cc -aweasdzw.com -aweb.cc -awehunt.com -awesome-bruce.me -awinic.com -awjiaju.com -aword.net -awotuan.com -awoyun.com -awsok.com -awspal.com -awstar.net -awtmt.com -awuming.com -awx1.com -awzp.net -ax1x.com -ax2nc4.ren -ax630.com -axatp.com -axbsec.com -axbxw.com -axcf.com -axfys.com -axhub.im -axjsw.com -axlpw.com -axmag.com -axmro.com -axnsc.com -axshuyuan.com -axsoft.co -axtmy.com -axtoutiao.com -axuer.com -axure.org -axure.us -axureshop.com -axureux.com -axureyun.com -axxiaoshuo.com -axyxt.com -axzchou.com -axzlk.com -ay57.com -ay99.net -aya1.xyz -ayfdc.com -ayfy.com -aygjj.com -ayguge.com -ayi360.com -ayibang.com -ayidada.com -ayijx.com -ayjcysteel.com -ayjs.net -aymbb.com -ayqy.net -ayrbs.com -ayuren.com -ayurumen.com -ayushan.com -ayux.net -ayx007.cc -ayxbk.com -ayxz.com -az-meter.com -azber.com -azchcdnb.com -azchcdng.com -azchcdnj.com -azchcdnm.com -azfashao.com -azg168.com -azhimalayanvh.com -azhituo.com -azhjt.com -azonvo.com -azooo.com -azoyacdn.com -azoyagroup.com -azurew.com -azureyun.com -azycjd.com -azyx.com -azz.net -b-chem.com -b-eurochina.com -b-fairy.com -b086.com -b0w.me -b178.com -b1bj.com -b1uew01f.net -b23.tv -b2b-builder.com -b2b.biz -b2b168.com -b2b168.net -b2b168.org -b2b179.com -b2b6.com -b2b98.net -b2baa.com -b2bic.com -b2bname.com -b2bneican.com -b2bvip.com -b2bvip.net -b2c-seo.com -b2cedu.com -b2q.com -b2sun.cc -b301.cc -b35ii.com -b3inside.com -b5200.net -b58b.com -b5b6.com -b5m.com -b612kaji.com -b6ss.com -b7l.cc -b8yx.com -ba-li.com -ba125.com -baaidu.com -baalchina.net -baba.cc -baba100.com -bababian.com -bababus.com -babaike.com -babaimi.com -babaipu.com -babao.com -babaofan.com -babapi.com -babariji.com -babaxiong.com -babeijiu.com -babidou.com -babidou.net -babihu.com -babsoft.net -baby-bus.com -baby169.net -baby577.com -baby611.com -baby868.com -babybus.com -babybus.org -babycdn.com -babygiftsunder100.com -babyhaha168.com -babyinhere.com -babymob.com -babymoro.com -babymozart.cc -babyqiming.com -babytree.com -babytreeimg.com -babywear.biz -babywear.win -bacaoo.com -bacic5i5j.com -backzero.com -bacocis.com -badls.com -badmintoncn.com -badou5.com -badouxueyuan.com -badu.com -badudns.cc -baertt.com -bafafafa.com -bafang.com -bafangka.com -bafangwang.com -bagb2b.com -bagehd.com -bagesoft.net -bagevent.com -bagew.com -bageyalu.com -bags163.com -bagtree.com -bagualu.net -baguatoutiao.com -bagxs.com -bahens.com -bai.com -bai68.com -baibaidu.com -baibailai.com -baibaoyun.com -baibeipy.com -baibianwukong.com -baibianyishu.com -baibm.com -baibo8.com -baibu.com -baic-hs.com -baicai.com -baicaicn.com -baicaio.com -baicaiyouxuan.com -baicaosoft.com -baicells.com -baichanghui.com -baicheng.com -baichenginedu.com -baichuanhd.com -baichuanhudong.com -baicizhan.com -baicizhan.org -baiclouds.com -baicmotor.com -baicmotorsales.com -baicuoa.com -baidajob.com -baidao.com -baidd.com -baidenafu.com -baideye.com -baidu-360-yyy-kubo.com -baidu-int.com -baidu-itm.com -baidu-mgame.com -baidu-umoney.com -baidu-wenxue.com -baidu.cc -baidu.cm -baidu.com -baidu.jp -baidu.mobi -baidu.net -baidu1.com -baidu120.cc -baidu123.com -baidu521.com -baidubaidubaidu.com -baidubaidubaidu.net -baidubce.com -baiduc.com -baiducdn.net -baiducontent.com -baidudaquan.com -baidufanyi.com -baidufe.com -baidufree.com -baiduhua.com -baidulook.com -baidunongmin.com -baiduonce.com -baiduor.com -baidupan.com -baidupcs.com -baidusemer.com -baidushifen.com -baidusobing.com -baidustatic.com -baidustatie.com -baidutieba.com -baidutt.com -baiduux.com -baiduv.com -baiduwebgame.com -baiduyiyi.com -baiduyun.com -baiduyun.wiki -baiduyundns.com -baiduyundns.net -baiduyunpan.com -baiduyunpan.net -baiduyunwangpan.com -baiduyy.com -baiduzhidao.site -baiduzjn.com -baietu.com -baifan.net -baifendian.com -baifubao.com -baifumeiba.com -baigepo.com -baigm.com -baigo.net -baihe.com -baiheee.com -baihei.net -baihephoto.com -baihexs.com -baihong.com -baihui.com -baihuikangjt.com -baihuillq.com -baihuoke.com -baihuwang.com -baiila.com -baiinfo.com -baijiacloud.com -baijiahulian.com -baijiasheping.com -baijiasoft.com -baijiayun.com -baijiegroup.com -baijiekj.com -baijiexiu.com -baijincdn.com -baijindai.com -baijingapp.com -baijiu88.com -baijob.com -baijunyao.com -baike.biz -baike.com -baiked.com -baikemy.com -baikemy.net -baikezh.com -bailiaijia.com -bailiangroup.com -bailiban.com -bailiguangmang.com -bailitech.com -bailitop.com -bailuqixiu.com -baima.com -baimao-expo.com -baimao.com -baimaohui.net -baimda.com -baimei.com -baimg.com -baimiaoapp.com -baimin.com -baimingzhiyao.com -baimuda.cc -baina.com -bainaben.com -baineng.cc -baiozhuntuixing.com -baipu365.com -baiqiaogame.com -baiqishi.com -baiquandai.com -baiquefahuasi.com -baironginc.com -bairuitech.com -baise.cc -baise520.com -baiseyun.com -baisha2004.com -baishakm.com -baishan-cloud.com -baishan-cloud.net -baishan.com -baishancloud.org -baishangeek.com -baishew.com -baishicha.com -baishigo.com -baishishuju.com -baishixi.xyz -baishudata.com -baishuge.net -baishunet.com -baisiker.com -baisu.com -baitaihuge.com -baitaoblog.com -baiteng.org -baithu.com -baitianinfo.com -baitiao.com -baituibao.com -baiu.com -baiud.com -baiudu.com -baiven.com -baiwandz.com -baiwang.com -baiwantuan.com -baiwanzhan.com -baiwanzy.com -baiwanzy.vip -baiwt.com -baiwutong.com -baixiangnews.com -baixiangxiang.com -baixiaosheng.net -baixing.com -baixing.net -baixingcdn.com -baixinger.com -baixingfanli.com -baixingjd.com -baixingmall.com -baixingzixun.com -baixiong.online -baixiongz.com -baixiu.org -baixu.com -baiyangwang.com -baiye5.com -baiyewang.com -baiyi181.com -baiyiba.com -baiyinggd.com -baiyingtx.com -baiyinjg.com -baiyintouzi.com -baiyjk.com -baiyou100.com -baiyouo.com -baiyu.tech -baiyuemi.com -baiyunairport.com -baiyundou.net -baiyuno.com -baiyunxitong.com -baiyuxiong.com -baizhan.net -baizhanke.com -baizhenzhu.com -baizhibest.com -baizhiedu.com -baizhixx.com -baizhu.cc -bajiebofang.com -bajiecaiji.com -bajiege.com -bajiehechuang.com -bajiemoney.com -bajieyou.com -bajieziyuan.com -bajintech.com -bajiu.org -bajson.com -bakaawt.com -bakaxl.com -bakbitionb.com -bakchoi.com -bakumon.me -bala.cc -baldc.com -baletu.com -balijieji.com -ballgametime.com -ballpure.com -bama1688.com -bama555.com -bamaiwo.com -bamaol.cc -bamaol.com -bamayigou.com -bamaying.com -bamboo18.com -bamenzhushou.com -bamuyu.com -bananalighter.com -bananau.com -bananaumbrella.com -bananaunder.com -banbaise.com -banbao123.com -banbaowang.com -banciyuan.me -bandaoningmeng.com -bandari.net -bandcevent.com -bandenghui.com -bandengw.com -bandianli.com -bandoristation.com -banfubbs.com -banfuzg.com -bang5mai.com -bangbang.com -bangbang93.com -bangbangbang.wang -bangbangrent.com -bangboer.net -bangboss.com -bangcle.com -bangdao-tech.com -banggo.com -banghaiwai.com -bangirls.com -bangkebao.com -banglianai.com -bangmai.com -bangongdashi.com -bangongyi.com -bangongziyuan.com -bangqi66.com -bangqiu.biz -bangqu.com -bangquan.net -bangrong.com -bangrongjinfu.com -bangshouwang.com -bangthink.com -bangwo8.com -bangwo8.net -bangxuetang.com -bangyike.com -bangzechem.com -bangzhufu.com -banjiajia.com -banjiamao.com -banjuanshu.com -bank-of-china.com -bank-swift-code.info -bankaiyuan.com -bankcomm.com -bankcomm.com.mo -bankcomm.com.tw -bankcz.com -bankgz.com -bankhr.com -bankkf.com -bankksw.com -bankofbbg.com -bankofchangsha.com -bankofchina.com -bankofdl.com -bankofliaoyang.net -bankofshanghai.com -bankoftieling.com -bankofyk.com -bankpublish.com -banksteel.com -banluyoulian.com -banma-inc.com -banma.com -banmajsq.com -banmamedia.com -banpie.info -banquanyin.com -banqumusic.com -banri.me -bansha.com -banshier.com -bantangapp.com -bantangbuy.com -banwagong.men -banwojia.com -banxiayue.com -banyou.la -banyuetan.org -banyuetanxcx.com -banyunjuhe.com -banzhuren365.com -banzou.name -banzouku.com -bao-cun.com -bao-fang.com -bao-hulu.com -bao-jian.net -bao100.com -bao12333.com -bao21.com -bao315.com -bao369.com -baobao.com -baobao001.com -baobao18.com -baobao88.com -baobaobang.com -baobaoshu.com -baobaotd.com -baobei360.com -baobeicang.com -baobeigezi.com -baobeihr.com -baobeihuijia.com -baobeipai.com -baobeita.com -baobeituan.com -baobidai.com -baobookw.com -baocai.com -baocdn.com -baodan360.com -baodao120.com -baodaohealth.com -baodaosz.com -baodaren.net -baodigs.com -baodingmeishi.com -baodu.com -baofeng.com -baofeng.net -baofeng365.com -baofengcinema.com -baofengcloud.com -baofengtuandui.com -baofengzixun.com -baofoo.com -baofoo.net -baofu.com -baogang.info -baogao.com -baogao.store -baogaoting.com -baoguangsi.org -baohebao.com -baohejr.com -baohuagroup.com -baoimg.net -baojia.com -baojiazhijia.com -baojidaily.com -baojiehang.com -baojijob.com -baojinews.com -baokan.name -baokan.tv -baoku.com -baokuandi.com -baokutreasury.com -baolaina.cc -baolijuyuancn.com -baoltx.com -baomao1314.com -baomi.com -baomi.org -baomi365.com -baomiexpo.com -baomihua.com -baoming.com -baomitu.com -baonian.net -baoqin.com -baoqingvip.com -baoruan.com -baoshe.net -baoshuanglong.com -baoshuiguoji.com -baosiair.com -baosight.com -baosteel.com -baostock.com -baotime.com -baotoushizx.com -baotuba.com -baowu.com -baowugroup.com -baoxian.com -baoxianelife.com -baoxianhai.com -baoxianshichang.com -baoxianzx.com -baoxiaobar.com -baoxinleasing.com -baoxinwen.com -baoxuexi.com -baoyang1.com -baoyang888.com -baoyangcs.com -baoyatu.cc -baoyeah.com -baoyou5.net -baoyt.com -baoyung.com -baoyuntong.com -baoyushipin.me -baoyz.com -baoz.net -baozang.com -baozha.net -baozhenart.com -baozheng.cc -baozhilin.com -baozhuang.biz -baozhuang5.com -baozhuangren.com -baozifa.com -baozipu.com -baozou.com -baozoudawang.com -baozoudi.com -baozoumanhua.com -baozouribao.com -baozy.com -baping.com -baqima.com -baqiu.com -baquge.com -baquge.tw -barlowarl.com -barmap.com -barnettarn.com -baron-bj.com -barretlee.com -bartender.cc -bartholomewart.com -base64.us -base9174.com -basemu.com -basequan.com -basestonedata.com -bashan.com -bashuhuapai.com -basiccat.org -basicfinder.com -basilwang.net -bastengao.com -bathome.net -batian.net -batiaoyu.com -batmanit.com -batpool.com -batterydir.com -batterykey.com -battleofballs.com -baudu.com -baufortune.com -bauschlombchina.com -bawagon.com -bawanglongbengye.com -bax1.com -baxi.tv -baxiami.com -baxichina.com -baxue.com -baybox.club -baydn.com -baye.tech -bayescom.com -bayimob.com -bayinfu.com -bayinh.com -bayinmao.com -bayuegua.com -bayueju.com -bayueweb.com -bayunhome.com -bazaarjewelrychina.com -bazai.com -bazarajor.com -bazhan.com -bazhou.com -bazhua.me -bazhuay.com -bazhuayu.cc -bazhuayu.com -bazi5.com -bazp.net -bb-edu.com -bb-game.com -bb-pco.com -bb-seo.com -bb06.com -bb179.com -bb723.com -bbanp.com -bbaod.com -bbaqw.com -bbb77qqq.xyz -bbbaaa.com -bbbao.com -bbbb.com -bbbbbb.me -bbbtgo.com -bbbvip.com -bbc-sy.com -bbcmart.com -bbcss.com -bbctop.com -bbddaa.com -bbdservice.com -bbercn.com -bbfstore.com -bbgsite.com -bbgstatic.com -bbicn.com -bbioo.com -bbiquge.com -bbjkw.net -bbk.com -bbkantu.com -bbmy.net -bbobo.com -bbonfire.com -bbpose.com -bbqk.com -bbqmw.net -bbrtv.com -bbs-go.com -bbs1x.net -bbsaso.com -bbsds.com -bbse03.com -bbsheji.com -bbsls.net -bbsmax.com -bbsmovie.com -bbsut.com -bbsxp.com -bbtang.info -bbtcaster.com -bbtree.com -bbtw.net -bbugifts.com -bbwfish.com -bbwxbbs.com -bbxinwen.com -bbzhh.com -bbzhi.com -bc12345678.com -bc6888.com -bc797.com -bcactc.com -bcadx.com -bcb5.com -bcbanzou.com -bcbm55555.com -bcbm66666.com -bcbm688.com -bcbpm.com -bcbvi.com -bccfw.com -bccn.net -bccnsoft.com -bccv.com -bccyyc.com -bcdaren.com -bcdy.net -bceapp.com -bcebos.com -bcedns.com -bcedns.net -bcedocument.com -bcegc.com -bceimg.com -bcelive.com -bcevod.com -bcfans.com -bcitb.com -bcjy123.com -bclsw.com -bcmcdn.com -bcmeng.com -bcoderss.com -bcpcn.com -bcreat.com -bcrjl.com -bcsky.pro -bcsytv.com -bctest.com -bctmo.com -bcty365.com -bcvbw.com -bcweibo.com -bcwhy.com -bcxgame.com -bcxww.com -bcy.net -bcyimg.com -bczcdn.com -bczs.net -bczx.cc -bd-apaas.com -bd-caict.com -bd-film.cc -bd-film.co -bd-film.com -bd-gl.com -bd001.net -bd2020.com -bd689.com -bdall.com -bdaop.com -bdapark.com -bdatu.com -bdc-rays.com -bdchina.com -bdf2.com -bdf304.com -bdfkb.com -bdfzcd.net -bdfzgz.net -bdfzxj.net -bdgslb.com -bdhaoye.com -bdhuakan.com -bdi.pub -bdimg.com -bdinfo.net -bding.net -bditong.com -bdkssc.com -bdkyr.com -bdpan.com -bdqn027.com -bdqn666.com -bdqnwh.com -bdr88.com -bds-cn.com -bdsgps.com -bdshuang.com -bdsimg.com -bdsmluntan16.com -bdstatic.com -bdsye.com -bdtic.com -bdtjs.org -bdtkba.com -bdtm.net -bdurl.net -bdwater.com -bdwm.net -bdwork.com -bdxhj.com -bdxiaodai.com -bdxiguaimg.com -bdxiguavod.com -bdxx.net -bdydns.com -bdydns.net -bdysite.com -bdyxzx.com -be-xx.com -be90.com -beaacc.com -beacons.gcp.gvt2.com -beacons.gvt2.com -beacons3.gvt2.com -beadwallet.com -bear20.com -bearad.com -bearead.com -beargoo.com -bearjoy.com -bearminers.xyz -bearrental.com -bearyboard.com -bearychat.com -beasure.com -beats-digital.com -beatu.net -beautifullinux.com -beautifulzzzz.com -beautydiarytw.com -beautykeychina.com -bechangedt.com -bedese.com -bedtimepoem.com -beduu.com -bee-ji.com -bee-net.com -beebeepop.com -beebeeto.com -beecook.com -beedancing.com -beego.me -beejson.com -beekka.com -beelink.com -beemarket.tv -beep365.com -beeplay123.com -beervm.club -beeshow.tv -beestor.com -beestore.tv -beetobees.com -beeui.com -beevideo.tv -beeweart.com -begcl.com -bego.cc -begoto.com -begowin.com -begup.com -behake.com -behance.ltd -behe.com -bei1688.com -beian88.com -beianapi29.com -beianapi30.com -beianbaba.com -beianidc.com -beianok.com -beianw.net -beibei.com -beibeicdn.com -beibiaogroup.com -beibiaogroup.net -beibj.com -beidahuang.net -beidamusic.com -beidasoft.com -beidd.com -beidian.com -beidoou.com -beidou.org -beidou66.com -beidouone.com -beidousafety.org -beidouxingxueche.com -beifabook.com -beifang.net -beifangfoshifen.com -beifeng.com -beifengwang.com -beifuni.com -beiguorc.com -beihai365.com -beihaidc.com -beihaiting.com -beihangonline.com -beihuasoft.com -beiidc.com -beijing-hmo.com -beijing-hualian.com -beijing-ip.com -beijing-kids.com -beijing-marathon.com -beijing-time.org -beijingbang.com -beijingbaomu.com -beijingcenterforthearts.com -beijingfenxiangkeji.com -beijinghenghua.com -beijingidc.com -beijingjuyuan.com -beijingkbd.com -beijingnorthstar.com -beijingoperacats.com -beijingrc.com -beijingrc.net -beijingrenyi.com -beijingsheying.net -beijingtongxin.com -beijingtoon.com -beijingwenshendian.com -beijingxinzhuoyue.com -beijingxuezhi.com -beijingzhonghao.com -beike21.com -beikeapp.com -beikeba.com -beikeit.com -beikel.net -beikeread.com -beikongyun.com -beileike.com -beiliangshizi.com -beimai.com -beimap.com -beimeigoufang.com -beimeihongfeng.com -beimu.com -beingmate.com -beipy.com -beisen.com -beisencorp.com -beitaichufang.com -beitao8.com -beitasi2016.com -beitown.com -beiwaibest.com -beiwaiclass.com -beiwaiguoji.com -beiwaionline.com -beiwaiqingshao.com -beiweigroup.com -beiwo.com -beiwo.tv -beiwo77.com -beiwotv.com -beiww.com -beixingmh.com -beiyanmaoyi.com -beiying.online -beiyongzhan.com -beiyuu.com -beiyxiu.com -beizengtech.com -beizigen.com -beiziman.com -bej9.com -bejoin.net -bejson.com -belfone.com -belle8.com -belmeng.com -beltandroadforum.org -beltxman.com -bemfa.com -bemyceo.com -benbenq.com -benber.com -benbun.com -bendibao.com -bendiw.cc -bengbeng.com -bengden.com -bengfa.biz -benghuai.com -bengku.com -bengou.cm -bengou.com -bengtie.com -benhu.cc -benhu.com -benhu01.com -beniao.com -benimg.com -benkua.com -benlai.com -benlailife.com -benmu-health.com -benmuyuan.net -bensedl.com -benseshijue.com -benshouji.com -benwu.vip -benyh.com -benyht.com -benyouhui.com -benz-photo.com -benzhb.com -benzhibbs.com -benztu.com -bequgew.com -bequgezw.com -berlinix.com -berqin.com -berrl.com -berrycn.com -berrydigi.com -berryol.com -berui.com -bes.ren -besg-bee.com -beshtech.com -besplatnioglasisrbija.com -bessystem.com -best-inc.com -best-intl-school.com -best100design.com -best66.me -best73.com -bestapp.us -bestatic.com -bestb2b.com -bestbaijiu.com -bestcake.com -bestcbooks.com -bestdjb.com -bestdo.com -bestdvd.com.tw -bestebookdownload.com -bestedm.org -bestexpresser.com -bestfangchan.com -bestfuturevip.com -bestgo.com -besthotelonline.com.hk -besthuaxia.com -besticity.com -bestinwo.com -bestjimmy.com -bestlee.net -bestmephoto.com -bestopview.com -bestpeng.com -bestqliang.com -bestsapchina.com -bestshinhwa.com -bestsign.info -bestsign.tech -bestsrc.com -bestswifter.com -besttoneh.com -besttrav.com -bestvapp.com -bestvist.com -bestwa.com -bestwehotel.com -bestweshop.com -bestwing.me -bet007.com -bet63k.com -bet7158.com -bet810.vip -bet9504.com -bet9629.com -betaflare.com -betaidc.com -betajy.com -betamao.me -betanews.xyz -betawm.com -betop-cn.com -betop365.com -betslw15.com -bettbio.com -betterdsp.com -betteredu.net -betterzip.net -betterzipcn.com -betway2020.com -beva.com -beyebe.com -beylze.com -beyondbit.com -beyondcompare.cc -beyondcomparepro.com -beyondfund.com -beyonditsm.com -beyonds.com -beyoner.net -bf10087.com -bf35.com -bf92.com -bfcmovie.com -bfdcdn.com -bfdfe.com -bffzb.com -bfgame.com -bfimg.com -bfjjw.com -bfjr.com -bfqh.com -bfqifu.com -bfsu-artery.net -bfsutw.com -bftq.com -bfttiao.com -bftv.com -bfvyun.com -bfw.cc -bfyx.com -bfyx.net -bfzhuce.com -bg.v4.a.dl.ws.microsoft.com -bg4.v4.a.dl.ws.microsoft.com -bgbk.org -bgctv.com -bgcyygl.com -bgdeco.com -bgee.cc -bggd.com -bgjqr.com -bgk100.com -bgl88.com -bgmfans.com -bgmgw.com -bgmlist.com -bgnhds.icu -bgren.com -bgrimm.com -bgsdk.net -bgsdyz.com -bgteach.com -bguai.com -bgwl.net -bgyfhyx.com -bh.sb -bh1t.com -bh3.com -bh45.com -bh4dks.com -bh5.com -bharatcityghaziabad.com -bhdata.com -bhdns.net -bhdtc.com -bhfangchan.com -bhgmarketplace.com -bhgxq.com -bhhgallery.com -bhjysp.com -bhk.mobi -bhnsh.com -bhpiano.com -bhplay.net -bhrencai.com -bhuitong.com -bhxww.com -bhzhu203.com -bhzhuji.com -bhzpw.com -bhzygl.com -bhzyxy.net -bi-china-future.com -bi11.com -biacgn.com -bian-min.com -biancheng.net -biancui.com -bianews.com -bianfeng.com -bianhao6.com -bianjibu.net -bianjiyi.com -bianjub.com -bianlidianjiameng.net -bianlifeng.com -bianlun.net -bianmachaxun.com -bianshi8.com -biantaishuo.com -bianwa.com -bianwanjia.com -bianxianmao.com -bianxianwu.com -bianzhifu.com -bianzhihui.com -bianzhile.com -bianzhirensheng.com -biao12.com -biaoai.com -biaobaiju.com -biaodan.info -biaodianfu.com -biaoge.com -biaoge.me -biaoju01.com -biaonimeia.com -biaoniu.net -biaopeibao.com -biaoqing.com -biaoqing888.com -biaoqingjia.com -biaoqingmm.com -biaotukeji.com -biaoyi.com -biaoyu.org -biaoyu168.com -biaozhiku.com -biaozhun.org -biaozhun8.com -biaozhuns.com -biaozhunyisheng.com -biask.com -bibenet.com -bibgame.com -bibibi.net -bibiku.com -bibiqiqi.com -bibitie.com -biblibili.com -bibuzhengxing.com -bichi.me -bicn.vip -bicyc.com -bid-view.com -bidchance.com -biddingos.com -biddingx.com -bidemi.com -bidewu.com -bidianer.com -bidingxing.com -bidns.net -bidongni.com -bidu.com -biduo.cc -biduobao.com -bidwhy.com -biebird.com -biedoul.com -biermai.com -bieshu.com -bietongfeng.com -bieyangapp.com -bifa770.com -bifabu.com -bifen.la -bifong.com -big-bit.com -big-shanghai.com -bigaaa.net -bigaka.com -bigan.net -bigbaicai.com -bigbaicai.wang -bigbenmeng.com -bigbigsun.com -bigbigwork.com -bigbing.cc -bigc.at -bigcat.com -bigcood.xyz -bigcooe.xyz -bigdata-expo.org -bigdata.ren -bigdatabbs.com -bigdatabuy.com -bigdataedu.org -bigdatasafe.org -bigdatastudy.net -bigdiao.cc -bigecko.com -bigehudong.com -bigemao.com -bigengculture.com -bigeniao.com -bigerdata.com -bigertech.com -bigeshuju.com -bigeyes.com -biggeryun.com -biggsai.com -bightbc.com -bigjpg.com -bigma.cc -bigniu.com -bignox.com -bigops.com -bigplayers.com -bigqiao.com -bigsec.com -bigsec.net -bigtree.mobi -biguer.com -biguo100.com -biguolunwen.com -bigwayseo.com -bigwinepot.com -bigwww.com -bigxiao.com -bigzhong.com -bigzhu.com -bihaiji.com -bihaipack.com -bihongbo.com -bihoo.com -bihu-static.com -bihu.com -bihubao.com -bii-erg.com -biikan.com -biiquan.com -biji.io -biji13.com -bijiao.org -bijiaocheng.com -bijiasso.com -bijiatu.com -bijienetworks.com -bijietech.com -bijirim.com -bijiv.com -bijixia.net -bikehome.net -biketo.com -biketour-giant.com -biknow.com -bilebo.com -bili.com -biliapi.com -biliapi.net -bilibii.com -bilibili.cc -bilibili.co -bilibili.com -bilibili.ru -bilibili.tv -bilibiligame.net -bilibiliyoo.com -bilicdn2.com -bilicraft.com -biligame.com -biligame.net -bilimoe.com -bilingling.com -bilinstar.com -bilive.com -bilivideo.com -biliyu.com -bill-jc.com -billchn.com -billionconnect.com -billionseo.com -billowlink.com -billwang.net -biluzww.com -bim-times.com -bim99.org -bimcn.org -bimo.cc -binance.cc -binance.org -binancezh.cc -binancezh.co -binbinyl.com -bincailiuxue.com -binfen.tv -binfenyingyu.com -bing400.com -bingbing8.com -bingbingyy.com -bingchengwang.com -bingd.com -bingdian001.com -bingdian01.com -bingdong700.com -bingelmedia.com -binglai.net -binglanggu.com -binglingtech.com -binglixue.com -bingo929.com -bingofresh.com -bingohuang.com -bingqipu.net -bingsns.com -bingtuannet.com -bingwang.cc -bingyan.net -bingyublog.com -bingzhilv.com -binkery.com -binmt.cc -binmtplus.com -binospace.com -binpang.me -binqsoft.com -bintoutiao.com -binuoniu.com -binvul.com -binyin.com -binzhi.com -binzhouquan.com -binzhuang.com -bio-equip.com -bio-fuyang.com -bio360.net -bioberi.com -biocloud.net -biocome.com -biodiscover.com -biodiscover.net -biogo.net -biohyalux.com -biolab.xyz -biomasscn.com -bioon.com -bioon.net -biosren.com -biosrepair.com -biostatistic.net -biotgene.com -bipush.com -bipvcn.com -biqiga.com -biqige.cc -biqiudu.com -biqiuge.com -biqiwu.com -biqu6.com -biquan.link -biqubao.com -biqubu.com -biqudie.com -biqudu.com -biqudu.net -biqudu.tv -biqufu.com -biquga.com -biquge.cm -biquge.com.tw -biquge.cz -biquge.info -biquge.la -biquge.lu -biquge.tw -biquge.vip -biquge0.cc -biquge11.com -biquge5200.cc -biquge5200.com -biquge8.com -biquge99.cc -biqugeapp.com -biqugebook.com -biqugecom.com -biqugeg.com -biqugemm.com -biquger.com -biquges.com -biqugetv.com -biqugew.com -biqugewx.com -biqugex.com -biqugexs.com -biqugexsw.com -biqugexsw8.com -biqugexx.com -biqugg.com -biqugo.net -biqugu.net -biquguan.com -biquguo.com -biqukan.com -biquke.com -biquku.co -biquku.la -biqulou.net -biquluo.com -biqumo.com -biququ.com -biqushu.com -biqusoso.com -biqutxt.com -biquwo.com -biquwu.cc -biquyun.com -biransign.com -bird4d.com -birdandwood.com -birdol.com -birdpush.com -birdteam.net -bisairi.com -bisenet.com -bishe1234.com -bishen.ink -bishengoffice.com -bishequ.com -bisheziliao.com -bishijie.com -bishoujo.moe -bishuju.com -bitauto.com -bitautoimg.com -bitautotech.com -bitbank.com -bitbays.com -bitbee24.com -bitbug.net -bitcellulose.com -bitcoin86.com -bitcongress.com -bitcron.com -bitdad.com -bitdata.pro -bitdefender-cn.com -bite5.com -biteabc.com -bitecoin.com -biteedu.com -bitelf.com -bitell.com -bitett.com -bitetui.com -bitfish8.com -bitgo.cc -bitgo.net -bitguai.com -bithosts.net -bithub00.com -bitjia.com -bitkan.com -bitky.cc -bitmain.vip -bitmap.cc -bitmap3d.com -bitmingw.com -bitol.net -bitqiu.com -bitscat.org -bitscn.com -bitscn.net -bitsde.com -bitse.com -bitshuo.com -bitsqa.com -bitu360.com -bitvip.com -biuapp.im -biubiu.tv -biubiu001.com -biubiubiu.org -bivean.com -biwanshequ.com -bixia.org -bixiaobai.com -bixiaxs.net -bixingxing.com -bixishang.com -bixu.cc -bixu.me -bixueke.com -biyabi.com -biyage.com -biyangwang.com -biyao.com -biye.net -biye666.com -biyebi.com -biyele.com -biyelunwenjiance.com -biyezuopin.cc -biyi.net -biyidc.com -biyinjishi.com -biymx.com -biyong007.com -biyoshop.com -biyou.tech -biyoujz.com -biyuns.com -biyuwu.cc -biz178.com -biz72.com -bizcent.com -bizchallenge.net -bizcharts.net -bizcn.com -bizconfstreaming.com -bizgame.com -bizhi360.com -bizhi88.com -bizhicool.com -bizhidaquan.com -bizhimi.com -bizhiquan.com -bizhitupian.com -bizhongchou.com -bizmoto.com -biznewscn.com -bizopsmall.com -bizotrip.com -bizpai.com -bizsn.com -bizsofts.com -bizvane.com -bj-apc.com -bj-big.com -bj-dianxintong.net -bj-dsmzyy.com -bj-kpn.com -bj-sagtar.com -bj-saite.com -bj-sea.com -bj-shouqi.com -bj-sydc.com -bj-tvart.com -bj-zhongying.com -bj-zkhb.com -bj003.com -bj1.api.bing.com -bj1000e.com -bj148.org -bj159zx.com -bj1777.com -bj315.org -bj51.org -bj5188.com -bj520.com -bj597.com -bj65z.com -bj96007.com -bjadn.net -bjaic.com -bjaodidazhong.com -bjaokaihua.com -bjatv.com -bjbaidu88.com -bjbaodao.net -bjbeifangjx.com -bjbtfu.com -bjbus.com -bjbxg8.com -bjbywx.com -bjbzc.com -bjbzszxy.com -bjcae.com -bjcancer.org -bjcankao.com -bjcathay.com -bjcdc.org -bjcec.com -bjceis.com -bjcfzx.com -bjcgtrain.com -bjchild.com -bjcifco.net -bjckkj.com -bjcloud.net -bjcls.net -bjcma.com -bjcoco.com -bjcomic.net -bjcshy.com -bjcsyg.com -bjcta.net -bjcurio.com -bjcxdf.com -bjcyzg.com -bjdachi.com -bjdbrc.com -bjdcfy.com -bjdfart.com -bjdfxj.com -bjdiaoyu.com -bjdingyi.com -bjdjc.com -bjdlzl.com -bjdongxin.com -bjdsppa.com -bjdt360.com -bjeasycom.com -bjepn.com -bjewaytek.com -bjexmail.com -bjexx.com -bjfengguang.com -bjffdz.com -bjffkj.com -bjfsali.com -bjfwbz.org -bjfyw.org -bjfz.cc -bjgas.com -bjgemi.com -bjgesainuo.com -bjggk.com -bjglxf.com -bjgnjdwx.com -bjgongteng.com -bjgooo.com -bjgtzl.com -bjgujibaohu.com -bjhaiguang.com -bjhdnet.com -bjhdsc.com -bjheadline.com -bjhee.com -bjhengjia.net -bjheniantang.com -bjhj10000.com -bjhmxx.net -bjhouse.com -bjhrkc.com -bjhscx.com -bjhtzsgs.com -bjhwbr.com -bjhzkq.com -bjiab.com -bjicjm.com -bjidc.net -bjidit.com -bjiebtc.com -bjilife.com -bjinnovate.com -bjinternet.com -bjipwqzx.com -bjiwex.com -bjjabc.com -bjjap.com -bjjbsj.com -bjjchf.com -bjjdwx.com -bjjf.cc -bjjfsd.com -bjjhcczgs.com -bjjhwlgs.com -bjjihui.com -bjjiubo.com -bjjkglxh.org -bjjnzf.com -bjjqzyy.com -bjjssh.org -bjjtat.com -bjjubao.org -bjjzsc.com -bjjzzpt.com -bjk30.com -bjkaihua.com -bjkaihua.net -bjkhzx.com -bjkqj.com -bjkrtwl.com -bjl777.com -bjlcs-tech.com -bjlemon.com -bjlevsoft.com -bjlkhd.net -bjlmfq.com -bjlongview.com -bjlot.com -bjlsjt.com -bjlstd.net -bjlyw.com -bjmailqq.com -bjmakerspace.com -bjmama.com -bjmama.net -bjmantis.net -bjmcdh.com -bjmeikao.com -bjmeileju.com -bjmepin.com -bjmeri.org -bjmingdi.com -bjmjm.com -bjmslp.com -bjmti.com -bjmyw.com -bjnaxl.com -bjnsr.com -bjornfromsweden.com -bjp321.com -bjpengyi.com -bjpowernode.com -bjqh.org -bjqhgjj.com -bjqichezl.com -bjqingyang.com -bjqyjjlb.com -bjrc.com -bjrcb.com -bjrel.com -bjretech.com -bjreview.com -bjrhxp.com -bjrjgj.com -bjrmysjy.com -bjrun.com -bjry.com -bjsantakups.com -bjsasc.com -bjsbnet.com -bjscfl.com -bjsciencefestival.com -bjscivid.org -bjsclp.com -bjscp.com -bjscszh.com -bjsctx.com -bjsdfz.com -bjsdr.org -bjsfrj.com -bjsfyh.com -bjshcw.com -bjsheng.com -bjshijiyu.com -bjsjcq.com -bjsjob.com -bjsjwl.com -bjsjxtm.com -bjsly.com -bjsoho.com -bjsoky.com -bjsound.com -bjsoyo.com -bjspw.com -bjsqgy.com -bjsryc.com -bjssedu.com -bjssmd.net -bjsspm.com -bjssqt.com -bjsubway.cc -bjsubway.com -bjsudai.com -bjsuewin.com -bjsupor.com -bjswds.org -bjsxljs.com -bjsxt.com -bjsyqw.com -bjszhd.net -bjtata.com -bjtcf.com -bjtelecom.net -bjtimes.net -bjtitle.com -bjtjr.net -bjtjw.net -bjtjzx.com -bjtlky888.com -bjtobacco.com -bjtonghui.com -bjtopli.com -bjtth.org -bjttsf.com -bjtu-hedu.com -bjtvnews.com -bjtysd.net -bjtyzh.org -bjtzr.com -bjunionstar.net -bjuri.com -bjwanjiabao.com -bjweimob.com -bjweizhifu.com -bjwfz.com -bjwhds.com -bjwj2y.com -bjwkzl.com -bjwmys.com -bjwsk.com -bjwsyy.com -bjwszyxy.com -bjwwhc.com -bjwxhl.com -bjwyseo.com -bjxatq.com -bjxdxx.org -bjxf315.com -bjxiangxiu.com -bjximei.com -bjxinku.com -bjxinyou.com -bjxjyy666.com -bjxwx.com -bjxx8.com -bjxxw.com -bjxydh.com -bjxztqn.com -bjyah.com -bjyaoyang.com -bjyczb.com -bjyestar.com -bjyggc.com -bjyhwy.com -bjyqsj.com -bjythd.com -bjyunyu.com -bjywt.com -bjyytyc.com -bjzaxy.com -bjzbkj.com -bjzcha.com -bjzchl.com -bjzcth.com -bjzg.org -bjzghd.com -bjzgxr.net -bjzhishi.com -bjzhongxinjiancai.com -bjzhongyi.com -bjzjgyl.com -bjzklp.com -bjzmkm.com -bjznnt.com -bjzph.com -bjzqw.com -bjzs114.com -bjzuihui.com -bjzwzx.com -bjzxcp.com -bjzycd.com -bjzyrxgs.com -bjzzlx.com -bk41.net -bkbok.com -bkclouds.cc -bkdou.com -bkiex.com -bkill.com -bkill.net -bkjk-inc.com -bkjpress.com -bkn.cc -bkpcn.com -bkqq.com -bkweek.com -bkxs.net -bkzzy.com -bl.com -bl35.org -bl5.cc -bl9k.com -bla01.com -black-unique.com -blackbirdsport.com -blackdir.com -blackeep.com -blackh4t.org -blackholeskins.com -blackist.org -blackmailedslave.com -blackshark.com -blackshow.me -blackxl.org -blackyau.cc -blackzs.com -bladewan.com -blakat.cc -blangel-tool.com -blazefire.com -blazefire.net -blbx.com -blctwed.com -bld-hotel.com -bldimg.com -bldz.com -bleege.com -blemall.com -blendercn.org -blenderget.com -blessedbin.com -blhs.cc -blianb.com -bliao.com -blibee.com -blibee.net -blimage.com -bliner.me -blingabc.com -blingclubs.com -blissmall.net -blizzardcn.com -blizzcn.com -blmdq.com -bln7.com -bln8.com -blnjw.com -block.cc -block288.com -block360.pro -blockchain.hk -blockchain123.com -blockchainbrother.com -blockchainlabs.org -blockdao.net -blockflow.net -blockin.com -blockmeta.com -blockob.com -blocksite.cc -blockvalue.com -blog.anank.ke -blog.htc.com -blog.htcvive.com -blog.tutorabc.com -blog.vive.com -blog007.com -blog120.com -blog1984.com -blogbus.com -blogchen.com -blogchina.com -blogchinese.com -blogdriver.com -bloger.wang -blogfeng.com -blogfshare.com -bloggern.com -blogjava.net -bloglegal.com -blogqun.com -blogturn.com -blogways.net -blogxuan.com -bloomgamer.com -bloves.com -blpack.com -blqx.com -blqy.com -blskye.com -blue-city.com -blue-zero.com -bluebeebox.com -bluecefa.com -bluedash.net -bluedon.com -bluefeel.com -bluefite.com -bluefocus.com -bluehao.com -bluehn.com -blueidea.com -bluek.org -bluelettercn.org -bluelightfuse.com -bluelive.me -blueplus.cc -bluesdream.com -bluesharkinfo.com -blueshow.net -blueskykong.com -blueskyschool.net -blueskystudy.com -blueslc.tech -bluestar-pc.com -bluestep.cc -bluewhale.cc -blxyy.com -blyol.com -blyun.com -bm001.com -bm023.com -bm024.com -bm2088.com -bm49.cc -bm724.com -bm777777.com -bm8.tv -bm8885.com -bm999999.com -bmadx.com -bmatch.tech -bmcx.com -bmdbr.com -bmdxcx.com -bmeol.com -bmfsm.com -bmijs.com -bmlink.com -bmobapp.com -bmobcloud.com -bmobpay.com -bmp.ovh -bmpj.net -bmqb.com -bmqy.net -bmrtech.com -bmshow.com -bmtcled.com -bmw021.com -bmw143.com -bmw2434.com -bmw6259.com -bmw8033.com -bn016.com -bn13.com -bnapp.com -bnbcamp.com -bnbsky.com -bnbtrip.com -bnc66.com -bnchina.com -bnhshiguan.com -bnisolusi.com -bnjyks.com -bnmanhua.com -bnncn.com -bnnd.net -bnq86.com -bnqgsl.com -bnsx.net -bnupg.com -bnwin.com -bnxb.com -bnxxjs.com -bnyhbj.com -bnzt88.com -bo-blog.com -bo-yi.com -bo56.com -boai.com -boanying.com -boao360.com -boao369.com -boatsky.com -bob2012.com -bobaiw.com -bobaow.com -bobbns.com -bobcardjf.com -bobcfc.com -bobcoder.cc -bobidc.com -boblog.com -bobo.com -bobobd.com -bobopic.com -bobopos.com -bobosays.com -bobtj.com -bocaidaka.com -boce.com -bocep2c.com -bocichina.com -bocim.com -bocomcc.com -bocommleasing.com -bocommlife.com -bocommtrust.com -bocross.com -bocsolution.com -bocvi.com -bodedu.com -bodekang.com -bodimedia.net -bodoai.com -bodogqm.com -bodu.com -boduhappiness.com -boe.com -bofangw.com -bofengkj.com -bofyou.com -bog.ac -bogokj.com -bohaibbs.net -bohailife.net -bohaiyun.com -bohe.com -bohuihe.com -bohutmt.com -boiots.com -bojianger.com -bojoy.net -bojueii.com -bojun-import.com -bojuwang.com -bokao2o.com -boke.com -boke112.com -boke8.net -bokeboke.net -bokecc.com -bokecs.net -bokee.com -bokee.net -bokerb.com -bokeren.cc -bokesoft.com -bokeyz.com -bokhra.com -bokon.net -bol-system.com -bolaninfo.com -bolanjr.com -boldseas.com -bole.me -bolead.com -bolehu.net -bolejiang.com -bolelink.com -bolianpro.com -bolijob.com -boliquan.com -boll.me -bolo.me -bolopp.com -boloread.com -bolq.com -boluo.com -boluo.link -boluo.org -boluo1122.com -boluogouwu.com -boluomee.com -boluomeet.com -boluoyunyu.com -bom.ai -bom2buy.com -bomanair.com -bomin-china.com -bon-top.com -bon-wine.com -bondlady.com -bongmi.com -bongv.com -bonkee.net -bonree.com -bonsj.com -bonwai.com -boobooke.com -booea.com -booeoo.com -boohee.com -book118.com -book1234.com -book365.net -book520.com -bookask.com -bookba.net -bookbaowang.com -bookbook.in -bookdao.com -bookdown.net -bookersea.com -booking001.com -bookingtee.com -bookinlife.net -booklist.mobi -bookqi.com -bookresource.net -books51.com -bookschina.com -bookshadow.com -bookshi.com -bookshuku.com -booksky.cc -booksn.com -booktxt.com -booktxt.io -booktxt.net -bookuu.com -bookxnote.com -bookzx.org -boolan.com -boolaw.com -boole-tech.com -boolean93.com -boolix.com -boomsense.com -boonwin.com -boooba.com -boosj.com -boosyi.com -bootcampbeijing.com -bootcdn.net -bootcss.com -bootstrapmb.com -booyu-import.com -booz88.com -bopian.com -boqii.com -boqiicdn.com -boquxinxi.com -boraid.org -borlonclan.com -borninsummer.com -bornlead.com -borpor.com -borscon.com -boruiqin.com -boruishijie.com -boruisx.com -boruisz.com -boryou.com -bosdile.com -bosdsoft.com -bosenrui.com -bosera.com -bosera.com.hk -boshi.tv -boshika.com -boshixitong.com -boshiyl.com -boshuo.net -bosideng.com -bosideng.me -bosideng.net -bosigame.com -bosondata.net -bosonnlp.com -boss-young.com -bosscdn.com -bossgoo.com -bosshr.com -bosszhipin.com -bosunman.com -botcl.com -botfans.org -botmh.com -botnet.cc -botongr.com -botorange.com -bottos.org -botusg.com -botvs.com -bounb.com -boweifeng.com -bowin8.com -bowuku.com -bowuzhi.fm -boxgu.com -boxopened.com -boxshows.com -boxuegu.com -boxueio.com -boxui.com -boxuu.com -boxz.com -boy-toy.net -boy1818.com -boy1904.com -boyaa.com -boyaceo.com -boyais.com -boyasoftware.com -boyaxun.com -boycp.com -boydown.com -boyicn.com -boyie.com -boyingsj.com -boyue.com -boyuedata.com -boyunjian.com -boyunso.com -boyuonline.com -bozhihua.com -bozhong.com -bp576.com -bphetaomiao.com -bphots.com -bpimg.com -bppan.com -bppstore.com -bpqwxsh.com -bpsemi.com -bpteach.com -bpxxfw.com -bpzyf.com -bq04.com -bq233.com -bq8xs.com -bqatj.com -bqb12.com -bqfy.com -bqg26.com -bqg5.cc -bqg8.cc -bqiapp.com -bqimg.com -bql999.com -bqpoint.com -bqq8.com -bqruan.com -bqteng.com -br-tattoo.com -bragood.com -brainysite.com -brand4x4.com -brandcn.com -brandvista.com -brandzg.com -brandzw.com -brazzersstar.com -breadtrip.com -breakingnewsireland.com -breakyizhan.com -brentron.com -bricktou.com -bridgee.net -bridgetiger.com -brighost.com -brightdairy.com -brightfood.com -brire.com -britesemi.com -brlinked.com -broad-ocean.com -broadcasteye.com -broadon.net -broadskytech.com -brogiao.com -bronzesoft.com -brother-cn.net -brother66.com -browurl.com -brsiee.com -brtbeacon.com -bruce.wang -bruceit.com -brushes8.com -bryonypie.com -brzhang.club -bs-dolfin.net -bs008.com -bs56.net -bsbchina.com -bsbydd.com -bsccdn.com -bsccdn.net -bscdns.com -bscea.org -bscstorage.net -bsd4fz.com -bsdgco.com -bsdmap.com -bseas.com -bsgcnc.com -bsgslb.com -bsh-tech.com -bshaishu.com -bshare.com -bsida.com -bsidu.com -bsjhhzs.com -bsjquanwu.com -bsjuhui.com -bskk.com -bskrt.com -bskuav.com -bspapp.com -bspeizi.com -bspia.com -bsrczpw.com -bsrkt.com -bssrvdns.com -bst24.com -bsteel.net -bstinfo.com -bstjiaoyu.com -bstzcs.com -bsurl.cc -bswxue.com -bsx81.com -bsyjrb.com -bt.cc -btb8.com -btba.cc -btbat.com -btblt.com -btbt.tv -btbt4k.com -btbuluo.com -btby-pump.com -btc100.com -btc114.com -btc116.com -btc1212.com -btc123.com -btc126.com -btc17.com -btc38.com -btc5.net -btc789.com -btcake.com -btcb.com -btcbbs.com -btcbl.com -btcchina.com -btcfans.com -btcha.com -btckan.com -btcsearch.com -btcside.com -btcsos.com -btcwatch.com -btdad.live -btdog.com -btege.com -btfan.com -btgame01.com -btgang.com -btglotto.com -btgms.com -bthcywj.com -bthhotels.com -bthlt.com -bthuifu.com -bthyhz.com -btime.com -btiyu.com -btkiller.com -btmao.cc -btmeiju.com -btmil.com -btnotes.com -btoo3.com -btophr.com -btorange.com -btpan.com -btpig.com -btplay.net -btrcsc.com -bts.hk -btsabc.org -btschool.net -btsemi.com -btsha.com -btsmth.com -btsmth.org -btsou.org -btspreads.com -btsteel.com -btten.com -bttfuli.com -bttiantang.cc -bttiantang.com -bttt6.com -bttwo.com -btv.org -btvcd.net -btwob.net -btwuji.com -btxl8.com -btyou.com -buaaer.com -buagengen.com -bubalusplus.com -bubu5.com -bubugao.com -bubuko.com -bubukua.com -bubuol.com -bubuzheng.com -bucg.com -bucuo.me -bucuo100.com -budaixi.net -budao.com -budao24.com -buddhalikedoge.com -budejie.com -budhano.com -buding.tv -budongnvren.com -budopian.com -budou.com -budueba.com -bufan.com -buffst.com -bughd.com -bugku.com -bugnull.com -bugscan.net -bugsec.org -bugsevent.com -bugtags.com -buguangdeng.com -bugucn.com -bugutime.com -bugwz.com -bugxia.com -buhuiwan.com -buhuyo.com -build-decor.com -buildface.com -buildhr.com -buildjob.net -buimg.com -bujie.com -bukamanhua.com -bukexue.com -bukeyi.net -bukop.com -bulaisi.com -bulaoge.net -bulebulo.com -bulejie.com -bullcome.com -bullmind.com -buluanmai.com -buluo007.com -bumimi.com -bumiu.com -bumpermobi.com -bundpic.com -bunfly.com -bungba.com -bunze.com -burgud.com -burl.cc -burnelltek.com -burongyi.com -buroniworks.com -buruizi.com -bus365.com -bus84.com -busbaoche.com -busdh.com -bushangban.com -bushen365.com -bushome.net -businessconnectchina.com -businessreviewglobal-cdn.com -busionline.com -busiphi.com -busiyi888.com -busnc.com -busytrade.com -but7.com -buterp.com -butongshe.com -butonly.com -butterapis.com -buxia.net -buxiugangban.net -buy-hk.org -buy027.com -buy360.vip -buyanshufa.com -buyaor.cc -buybieshu.com -buycarcn.com -buychuan.com -buyfine.net -buyigang.com -buyihao.com -buyiju.com -buyinball.com -buyjk.com -buykee.com -buyku88.com -buylabel.com -buysun.net -buysweet.com -buytips.site -buyu46.com -buzhi5.com -buzhibushi.com -buzzads.com -buzzinate.com -buzzopt.com -bvgv.com -bvimg.com -bvseo.com -bw40.net -bw8848.com -bwae.org -bwangel.me -bwbot.org -bwchinese.com -bwda.net -bwfapiao.com -bwfhmall.com -bwgongye.com -bwgrt.com -bwgstock.com -bwhero.com -bwhgsb.com -bwie.net -bwjf.com -bwjsw.com -bwlc.net -bwmelon.com -bwptl.com -bwpx.com -bwsoft.net -bwxsj.com -bwzybf.com -bx1k.com -bx24k.com -bx58.com -bxb2b.com -bxd365.com -bxdaka.com -bxdlkj.com -bxfaka.com -bxgfw.com -bxgjyc.com -bxgtd.com -bxhaibao.com -bxjob.net -bxjr.com -bxjyw.com -bxkejian.com -bxkxw.com -bxlac.com -bxmns.com -bxpedia.com -bxr.im -bxrfund.com -bxsnews.com -bxsychina.com -bxwcn.net -bxwst.com -bxwx.la -bxwx.org -bxwx.tv -bxwx.us -bxwx520.com -bxwx99.com -bxwxtxt.com -bxxhdq.com -bxxy.com -bxycw.com -bxynzz.com -bxyuer.com -bxzhiku.com -bxzxw.com -by-health.com -by56.com -by6sx.com -bybbs.org -bybieyang.com -bybutter.com -bybzj.com -byc168.com -bycmw.com -byd.com -bydit.com -bydowstar.com -byecity.com -byete.com -byf.com -byfcw.com -byfen.com -byfuh.com -byfunds.com -byfzxy.com -bygamesdk.com -bygjhb.com -bygw.net -byhard.com -byi.pw -byimc.com -byjdxy.com -byjgxy.com -byjsjxy.com -byjzwh.com -byjzxy.com -byksgs.com -byloue.com -bylwcc.com -bylwjc.com -bymglasses.com -bymz.net -bynmc.com -bynsyh.com -byprxy.com -byqcxy.com -byqok.com -byr-navi.com -byr.cc -byr.wiki -byread.com -bysb.net -byshr.com -bysj999.com -bysocket.com -bysxfz.com -byte.online -byte2100.com -bytebye.com -bytecdn.com -byted.org -bytedance.com -bytedance.net -bytedanceapi.com -bytedns.net -byteedu.com -bytefcdn.com -byteimg.com -byteisland.com -bytesfield.com -bytesmanager.com -bytestacks.com -bytexns.com -bytexservice.com -bytrip.com -byts.com -bytter.com -bytx888.com -bywave.io -byxy.com -byyapp.com -byzhihuo.com -byzoro.com -byzp.com -bz-e.com -bz163.org -bz55.com -bzcm.net -bzd6688.com -bzdao.com -bzddrive.com -bzdiao.com -bzdww.com -bzfhw.bar -bzfwq.com -bzfxw.com -bzgd.com -bzkad.com -bzko.com -bzmfxz.com -bzname.com -bznsw.com -bznx.net -bzonl.com -bzpc119.com -bzr99.com -bzrb.net -bzrw.net -bzshw.com -bzsoso.com -bztzl.com -bzw315.com -bzwt1.cc -bzxinganghulan.com -bzxinwen.com -bzxz.net -bzxzk.net -bzzss.com -c-119.com -c-3.moe -c-c.com -c-cnc.com -c-cnzz.com -c-ctrip.com -c-estbon.com -c-fol.net -c-lion.com -c-lodop.com -c-ps.net -c-sky.com -c-sz.com -c-t.work -c-yl.com -c.admob.com -c.android.clients.google.com -c.citic -c.team -c0594.com -c0de4fun.com -c0ks.com -c1042.com -c114.net -c1ass.com -c1mzbm.shop -c1s.com -c21wuhan.com -c2h4.org -c32356.com -c32375.com -c32869.com -c360dn.com -c366.com -c3acg.com -c3crm.com -c3player.com -c3x.me -c4008.com -c400c.cc -c4d.live -c4datc.com -c4dba.com -c4dcn.com -c4dpro.com -c4dsky.com -c4hcdn.com -c4ys.com -c4yx.com -c50forum.com -c51rf.com -c53911.com -c571.com -c5game.com -c6.nz -c668sz.com -c68.com -c6c.com -c6n708.ren -c73160.com -c75uw72.com -c77c.com -c7c8.com -c7cc.com -c833.com -c9018.com -c969.com -c9cc.com -ca-sme.org -ca001.com -ca002.com -ca003.com -ca168.com -ca39.com -ca800.com -ca8077.com -caaa-spacechina.com -caaad.com -caacbook.com -caacsri.com -caaladi.com -caanb.com -caaorg.com -caasse.com -caayee.com -cabbagelol.net -cabbeen.com -cabee.org -cabhr.com -cabinetbuy.com -cableabc.com -cabling-system.com -cablingteam.com -cabontek.com -cabplink.com -cabxgw.com -cacfo.com -cacg.cc -cache.pack.google.com -cachecn.com -cachecn.net -cachekit.com -cachepro.com -cachetime.com -cackui.com -cacpp.com -cacre.org -cacrsi.com -cacs100.com -cactifans.com -cactifans.org -cad1688.com -cad8.net -cada.cc -cadcaecam.com -cadchat.cc -cadict.net -cadmon.net -cadreg.com -cadzhuan.com -cadzj.com -cadzxw.com -caecc.com -caexpo.com -caexpo.org -cafachine.com -cafagame.com -cafamuseum.org -cafebeta.com -cafecole-maison.com -caffeenglish.com -cagesblog.com -cagetest.com -cageystone.com -cago365.com -cagoe.com -cahkms.org -cahuo.com -cai188.com -cai8.net -caian.net -caibaodi.com -caibaojian.com -caibaopay.com -caibeike.com -caibianba.com -caibowen.net -caichongwang.com -caicomes.com -caicui.com -caidan2.com -caidao1.com -caidao8.com -caidaocloud.com -caidaoli.com -caidian.com -caidianqu.com -caiens.com -caifu110.com -caifuxingketang.com -caifuzhongwen.com -caigaowang.com -caigou2003.com -caigoubao.cc -caigoushichang.com -caiguayun.com -caihang.com -caihao.com -caihao.net -caihcom.com -caihezi.com -caihong360.com -caihong5g.com -caihongbashi.net -caihongqi.com -caihongtang.com -caihongto.com -caihuaw.com -caijienews.com -caijing28.com -caijing365.com -caijingcaipiao22270.com -caijingche.com -caijinglun.com -caijingmen.com -caijingmobile.com -caijingnews.net -caijingwu.com -caijixia.com -caijixia.net -caijizy.com -caiku.com -caikuai91.com -caikuan.net -cailele.com -cailianpress.com -cailiao.com -cailiaoniu.com -cailiaoren.com -cailol.com -cailongtong.com -cailutong.com -cailuw.com -caimai.cc -caimei365.com -caimigs.com -caimoge.com -caimomo.com -cainachina.com -caing.com -cainiao.com -cainiaodoc.com -cainiaojiaocheng.com -cainiaolc.com -cainiaoqidian.com -cainiaoxueyuan.com -cainu.net -caipiaogu.com -caipopo.com -caipucaipu.com -caipucn.com -caipun.com -caiqiuba.com -cairongquan.com -cairot.com -caisan.io -caishen66.com -caishencai.com -caisheng.net -caishenpo.com -caishenwang.online -caishimv.com -caishuixxi.com -caispace.com -caistv.com -cait.com -caitou.com -caitou.net -caitun.com -caiu8.com -caiweiming.com -caiwu51.com -caiwuchina.com -caixin.com -caixinfoundation.org -caixun.com -caiyiduo.com -caiyuanyou.com -caiyun.com -caiyunai.com -caiyunapp.com -caizhaowang.com -caizhihr.com -caj11.com -caj5.com -cake400.com -cake6.com -calawei.com -calculusdata.com -cali-light.com -calibur.tv -callda.com -callmewhy.com -caloinfo.com -calonye.com -calt.com -calvinneo.com -cambm.com -cambodiafang.com -cambricon.com -camcap.us -camcard.com -came-online.org -camelsee.com -camera360.com -camgle.com -camnpr.com -campanilechina.com -campingcn.com -campus-app.net -campusplus.com -campusroom.com -camscanner.com -can-dao.com -can.tv -canaan-creative.com -canasy.com -cancda.net -candelum.com -candou.com -candylab.net -candypay.com -candystars.net -canevent.com -canfire.net -cang.com -cangdu.org -cangfengzhe.com -cangnews.com -cangowin.com -cangpie.com -cangqiongkanshu.com -cangshui.net -cangshutun.com -cangtianbfq.com -cangya.com -canhighcenter.com -canhot.net -caniculab.com -canidc.com -canimktg.com -canjiren.net -cankao100.com -cankaoxiaoxi.com -canlongcom.com -canlyn.com -canmounet.com -canon8.com -canpdu.com -canpoint.net -canrike.com -cansine.com -cansuan.com -cantoge.com -canukiss.me -canvasf.com -canway.net -canwayit.com -canwaysoft.com -canyin.com -canyin168.com -canyin2017.com -canyin375.com -canyin88.com -canyincha.com -canyinzixun.com -canyon-model.com -canyouchina.com -canyuanzs.com -canzhisz.com -caobao.com -caodan.org -caogen.com -caogen88.com -caohaifeng.com -caohejing.com -caohejing.org -caohua.com -caoliu.com -caomeibook.com -caomeishuma.com -caomin5168.com -caotama.com -caoxianfc.com -caoxie.com -caoxile.com -caoxiu.net -caoxudong.info -caoyudong.com -capillarytech-cn.com -capitalcloud.net -capitalonline.net -capjoy.com -cappchem.com -cappeg.com -capsuleshanghai.com -capvision.com -capwhale.com -car0575.com -car136.com -car2100.com -car2sharechina.com -car365.org -car388.com -carben.me -carbonscn.com -carcav.com -carcdn.com -cardbaobao.com -cardcmb.com -cardcn.com -cardhw.pw -cardinfolink.com -cardniu.com -cardniudai.com -cardqu.com -care110.com -careerchina.com -careerqihang.com -careersky.org -careuc.com -carflac.com -cargeer.com -cargo001.com -carimg.com -carking001.com -carltonyu.com -carmov.com -carnegiebj.com -carnoc.com -carodpiano.com -carp56.com -carpela.me -carrobot.com -carry6.com -cartoonb2b.com -cartooncn.org -cartoonwin.com -carutoo.com -carvendy.com -carxoo.com -carzd.com -carzyuncle.com -cas01.com -cas2s.com -casarte.com -casbin.org -casboc.com -casctcp.com -case91.com -casece.org -casemeet.com -cashtoutiao.com -cashwaytech.com -cashzhan.com -casic-addsino.com -casic-amc.com -casic-t.com -casic.com -casic304.com -casic3s.com -casicloud.com -casicyber.com -casnb.com -casql.com -casqy.com -casszzy.com -castelu.com -casvino.com -casvm.com -casystar.com -cat898.com -catalog-tj.com -catfish-cms.com -catfun.tv -catguo.com -cathayfund.com -catjc.com -cato-travel.com -cattsoft.com -catv.net -caua99.com -cauchies.org -caup.net -cauvet.com -cav-ad.com -cavca.org -cavinessad.com -cavuc.com -cawae.net -caxa.com -caylor.cc -cazpw.com -cbca.net -cbdio.com -cbdj1816.com -cbdjrsh.org -cbe21.com -cbea.com -cbec365.com -cbes21.com -cbevent.com -cbex.com -cbfook.com -cbgcloud.com -cbi360.net -cbice.com -cbide.com -cbiec.com -cbiec.net -cbismb.com -cbj1998.com -cbjuice.com -cbjzw.org -cbmay.com -cbminfo.com -cbn.me -cbndata.com -cbndata.org -cbnmall.com -cbnri.org -cbnweek.com -cboad.com -cbos3d.com -cbqyw.net -cbrex.com -cbskc.com -cbsrb.com -cbsrc.com -cbtimer.com -cbvac.com -cbw111.com -cbxdxg.com -cby.me -cbzhuanyun.com -cc-1.com -cc-glass.com -cc.co -cc0808.com -cc1021.com -cc11bh.com -cc123.com -cc222.com -cc55k.com -cc6uu.com -cc8.cc -ccabchina.com -ccai.cc -ccapbook.com -ccapedu.com -ccartd.com -ccarting.com -ccb.com -ccbfund.com -ccbookfair.com -ccbpension.com -ccbride.com -ccc-2013.com -cccaq.com -cccbs.net -cccitu.com -cccity.cc -ccciw.com -cccnec.com -cccpan.com -ccctspm.org -cccwww.com -cccyds.com -cccyun.cc -ccd86.com -ccdby.com -ccddvr.com -ccdol.com -cceai.com -cceato.com -ccedisp.com -ccedpw.com -ccee.com -cceea.net -cceep.com -ccefb.com -ccement.com -ccen.net -ccepc.com -cces2006.org -ccets.com -ccfei.com -ccflow.org -ccgaa.com -ccgfie.com -ccgslb.com -ccgslb.net -ccgst.org -cchccc.com -cchezhan.com -cchfound.org -cchhdd.com -cchicc.com -cchongjing.com -cchorse.com -cchorse.net -cchtnet.com -ccian.com -cciatv.com -ccic.com -ccic2.com -cciccloud.com -ccice.com -ccidcom.com -ccidconsulting.com -ccidcyt.com -cciddata.com -cciddesign.com -ccidedu.com -ccidexpo.com -ccidgroup.com -ccidjinglue.com -ccidnet.com -ccidreport.com -ccidsmart.com -ccidthinktank.com -ccidwise.com -ccie.lol -ccieh3c.com -ccieshow.com -ccievide.com -ccigchina.com -ccigmall.com -ccihr.com -ccimz.com -ccipmedia.com -ccipp.org -ccitimes.com -cciup.com -ccjkwjjedu.com -ccjoin.com -ccjoy.com -ccjoyland.com -ccjt.net -ccjzzj.com -cclcn.com -cclexpo.com -cclimg.com -cclndx.com -cclolcc.com -cclqme.xyz -cclycs.com -cclyun.com -ccm-1.com -ccm99.com -ccmama.com -ccmanhua.com -ccmdl.adobe.com -ccmdls.adobe.com -ccme.cc -ccmfcm.com -ccmmcode.com -ccmodel.com -ccmodel.net -ccmw.net -ccn360.com -ccnee.com -ccnew.com -ccnovel.com -ccnpic.com -ccnt.com -ccnubbs.com -ccnulx.com -ccnvpt.com -ccoalnews.com -ccoclub.com -ccoco.vip -ccoi.ren -ccopyright.com -ccpc.io -ccpc02.com -ccpc360.com -ccpgssd.com -ccpit-academy.org -ccpit-ah.com -ccpit-ep.org -ccpit-henan.org -ccpit-ipc.org -ccpit-shaanxi.org -ccpit-sichuan.org -ccpit-sx.org -ccpit-tga.org -ccpit.org -ccpitbingtuan.org -ccpitbj.org -ccpitbm.org -ccpitbuild.org -ccpitcq.org -ccpitecc.com -ccpitfujian.org -ccpitgs.org -ccpitgx.org -ccpithebei.com -ccpithn.org -ccpithrb.org -ccpithz.org -ccpitjinan.org -ccpitjs.org -ccpitlight.org -ccpitln.org -ccpitnb.org -ccpitnmg.org -ccpitqd.org -ccpitsd.com -ccpitsy.org -ccpittex.com -ccpittj.org -ccpitwh.org -ccpitxiamen.org -ccpitxian.org -ccpitxj.org -ccplay.cc -ccpnt.org -ccprec.com -ccproxy.com -ccqtgb.com -ccqyj.com -ccrgt.com -ccrjw.com -ccshao.com -ccshell.com -ccsph.com -ccsw003.com -cct08.com -cct365.net -cctalk.com -cctaw.com -cctb.net -cctbn.com -cctcce.com -cctcct.com -cctiedu.com -cctime.com -cction.com -cctlife.com -cctocloud.com -cctpress.com -cctry.com -cctsnw.com -cctsx.com -cctuw.com -cctv-119.com -cctv-19.com -cctv.com -cctv18.com -cctv1zhibo.com -cctv4g.com -cctv5.name -cctv886.com -cctvcaizhi.com -cctvcdn.net -cctvcj.com -cctvctpc.com -cctvdyt.com -cctvfinance.com -cctvhn.com -cctvmall.com -cctvpic.com -cctvsdyxl.com -cctvse.net -cctvweishi.com -cctvxf.com -cctw.cc -cctzz.net -ccutchi.com -ccutu.com -ccv160.com -ccv168.com -ccv5.com -ccview.net -ccvita.com -ccvnn.com -ccwcw.com -ccwcyw.com -ccwonline.com -ccwonline.net -ccwow.cc -ccwqtv.com -ccwushu.com -ccwzz.cc -ccxcn.com -ccxcredit.com -ccxinshiji.com -ccxinshijicy.com -ccxinshijimc.com -ccxinyikeji.com -ccxinyuedu.com -ccxiyuecare.com -ccxjcg.com -ccxjd.com -ccyjjd.com -ccymf.com -ccyts.com -ccyyls.com -cczhenfeng.com -ccziben.com -cczihai.com -ccztv.com -cd-ct.com -cd-cxh.com -cd-kc.com -cd-taxi.com -cd-vv.com -cd-zc.com -cd120.com -cd37wan.com -cdabon.com -cdadata.com -cdadsj.com -cdaidu.com -cdairport.com -cdajcx.com -cdaten.com -cdbcw.com -cdbdsec.com -cdbjh.com -cdbsfund.com -cdbybo.com -cdccpit.org -cdchsj.com -cdchuandong.com -cdcoslm.com -cdcwkj.com -cdcyts.com -cdcz.net -cddgg.com -cddgg.net -cddo8.com -cddscj.com -cddsgk.com -cde-os.com -cdedu.com -cdeledu.com -cdfcn.com -cdfgsanya.com -cdfinger.com -cdfortis.com -cdfytx.com -cdgdad.com -cdggzy.com -cdgjbus.com -cdgjlxs.com -cdgmgd.com -cdgtw.net -cdh3c.com -cdhaiguang.com -cdhfund.com -cdhongfu.com -cdhr.net -cdhtnews.com -cditv.tv -cdjingfeng.com -cdjinpeng.com -cdjnrc.com -cdjsjx.com -cdjxjy.com -cdjzw.com -cdjzx120.com -cdkf.com -cdkjx.com -cdkx.net -cdlaobing.com -cdlbyl.com -cdlfvip.com -cdlgame.com -cdlinli.com -cdlinux.net -cdlkzb.com -cdlute.com -cdlxqn.com -cdmfund.org -cdmlrs.com -cdmm.net -cdmodernenglish.com -cdmoz.org -cdn-789.com -cdn-baidu.net -cdn-cdn.net -cdn-chuang.com -cdn-cn1.apple-mapkit.com -cdn-cn2.apple-mapkit.com -cdn-cn3.apple-mapkit.com -cdn-cn4.apple-mapkit.com -cdn-data-cloud.com -cdn-dns-kubo.com -cdn-files.net -cdn-hotels.com -cdn-ng.net -cdn-okzyw.com -cdn-speed.com -cdn-tudou.com -cdn-v.com -cdn.apple-mapkit.com -cdn.jsdelivr.net -cdn.marketplaceimages.windowsphone.com -cdn.razersynapse.com -cdn.samsung.com -cdn.shanghai.nyu.edu -cdn.zhuji5.com -cdn08.com -cdn1-okzy.com -cdn1.apple-mapkit.com -cdn11-okzy.com -cdn1218.com -cdn2-okzy.com -cdn2.apple-mapkit.com -cdn20.com -cdn20.info -cdn20.org -cdn2000.com -cdn3-okzy.com -cdn3.apple-mapkit.com -cdn30.com -cdn30.org -cdn33-okzy.com -cdn3344.com -cdn35.com -cdn4-okzy.com -cdn4.apple-mapkit.com -cdn5-okzy.com -cdn55.net -cdn55555.com -cdn56.com -cdn7-okzy.com -cdn79.com -cdn818.com -cdn86.net -cdn88.cc -cdn9-okzy.com -cdnbest.com -cdnbest.net -cdnbye.com -cdncache.net -cdncache.org -cdncenter.com -cdnchushou.com -cdncl.net -cdncloud.org -cdnclouds.net -cdndm.com -cdndm5.com -cdndm5.net -cdndns8.com -cdndo.com -cdnet110.com -cdnetworks.com -cdnetworks.net -cdngslb.com -cdngtm.com -cdnhwc1.com -cdnhwc2.com -cdnhwc3.com -cdnhwc6.com -cdni.net -cdnip567.com -cdnjtzy.com -cdnk8.com -cdnle.com -cdnle.net -cdnmama.com -cdnmaster.com -cdnok.com -cdnpan.com -cdnren.com -cdntip.com -cdntips.com -cdntips.net -cdnudns.com -cdnunion.com -cdnunion.org -cdnvp.com -cdnvpn.net -cdnvue.com -cdnyt69.com -cdnyzdjj.com -cdnzhuji.com -cdooc.com -cdqcnt.com -cdqcp.com -cdqph.com -cdqss.com -cdren.com -cdren.net -cdronghai.com -cdrtvu.com -cdruzhu.com -cdryny.com -cds-cdn.v.aaplimg.com -cds.apple.com -cds.apple.com.akadns.net -cdsb.com -cdsb.mobi -cdsenfa.com -cdsglxx.com -cdshangceng.com -cdshijue.com -cdsjjy.com -cdslsxh.com -cdsme.com -cdsns.com -cdsoso.me -cdsxlc.com -cdsydc.com -cdt-md.com -cdtaishan.com -cdtianda.com -cdtjc.com -cdueff.com -cdunu.com -cduyzh.com -cdvcloud.com -cdvisor.com -cdvtc.com -cdweikebaba.com -cdworking.com -cdxrdz.com -cdxsbdz.com -cdxwcx.com -cdxy.me -cdyee.com -cdyestar.com -cdygdq.com -cdyichu.com -cdyimei.com -cdyou.net -cdyuanhang.com -cdyushun.com -cdywgou.com -cdyzg.com -cdzcy.net -cdzdgw.com -cdzdhx.com -cdzgh.com -cdzhinan.com -cdzikao.com -cdzimeijia.com -cdzimo.com -cdzixun.net -cdzmn.com -cdzspcls.com -cdzszp.com -cdzvan.com -ce-air.com -ce02.net -ce04.com -ce12366.com -ce2293.com -ceair.com -ceairdutyfree.com -ceairgroup.com -ceaj.org -cebbank.com -cebcn.com -cebpubservice.com -cecb2b.com -cecc-cx.com -ceccen.com -cecdc.com -cece.com -cece.la -cecesat.com -cechoice.com -cecisp.com -cecloud.com -cecmath.com -cecom.cc -ceconline.com -ceconlinebbs.com -cecport.cc -cecport.com -cectcc.com -cectv.net -cedachina.org -cedarhd.com -cediy.com -cedock.com -ceecu.com -ceeie.com -ceeji.net -ceepsp.com -cef114.com -cefc.co -cehca.com -cehome.com -cehuashen.com -cehui8.com -ceiaec.org -ceibs.edu -ceibsonline.com -ceic.com -ceiceicei.com -ceicloud.com -ceiea.com -cekid.com -celebpalace.com -celia520.com -celiang.net -cellixsoft.com -cellmean.com -cells-net.com -cells-net.net -celunwen.com -celwk.com -cem5117.com -cement365.com -cementren.com -ceming.com -cemyun.com -cenbel.com -cencs.com -cenray-ic.com -censh.com -centainfo.com -centanet.com -centcc.com -cententcymbals.com -centerm.com -centong.com -centos.bz -centoscn.vip -centralsolomon.com -centrechina.com -centrincloud.com -centrixlink.com -century21cn.com -cenwor.com -cenwoy.com -cenya.com -ceobiao.com -ceoeo.com -ceoim.com -ceomoo.com -ceons4.com -ceook.com -ceoplaza.com -ceotx.com -ceowan.com -ceowww.com -cepin.com -ceping.com -cepmh.com -ceprei.com -ceprei.org -ceqt.net -cer.net -cerambath.org -ceramicschina.com -cernet.com -cernet.net -cernet2.net -cers.me -cersp.com -ceruchina.com -ces-transaction.com -cesafe.com -cescnb.com -cesfutures.com -ceshi112.com -ceshigo.com -ceshigu.com -ceshiguang.com -cespc.com -cesses.org -cet-46.com -cetc33.com -cetc52.com -cetccloud.com -cetccloud.store -cetcio.com -cetcmotor.com -cetcssi.com -cethik.com -ceunion.com -ceve-market.org -cevsn.com -cezxda.com -cf027.com -cf4w.com -cf668.com -cf865.com -cfachina.org -cfanclub.net -cfbond.com -cfc365.com -cfca-c.org -cfcdn.site -cfcglx.com -cfcp67.com -cfcpn.com -cfcyb.com -cfd-china.com -cfd163.com -cfda.pub -cfdaguanjia.com -cfdp.org -cfdtlee.com -cfeie.com -cfej.net -cfeks.com -cfgjwl.com -cfhi.com -cfhot.com -cfhpc.org -cfido.com -cfiec.net -cfimg.com -cfjs.cc -cfkq.net -cflm.com -cfm119.com -cfmcc.com -cfmmc.com -cfpa.pw -cfsino.com -cfsl2017.com -cftea.com -cftong.com -cfucn.com -cfund108.com -cfwaf.com -cfxydefsyy.com -cfxyfsyy.com -cfxyjy.com -cfyjzb.com -cfzb.org -cfzq.com -cg-cdn.net -cg-orz.com -cg-vipwebs.com -cg-zwdb.com -cg.am -cg009.com -cg98.com -cgaeo.com -cgahz.com -cgangs.com -cgartt.com -cgbbatterysw.com -cgbolo.com -cgboo.com -cgchina.net -cgcloud.net -cgcountry.com -cgdown.com -cgdream.org -cgebook.com -cgejournal.com -cger.com -cgf-csyc.com -cghlj.com -cgiale.com -cgiia.com -cgjoy.com -cgjoy.net -cgke.com -cgkee.com -cglnn.com -cglw.com -cgmantou.com -cgmao.com -cgmcc.net -cgmodel.com -cgmol.com -cgmxw.com -cgnjy.com -cgnmc.com -cgnne.com -cgnovo.com -cgohome.com -cgonet.com -cgown.com -cgpad.com -cgplayer.com -cgplusplus.com -cgpx.org -cgquanter.com -cgris.net -cgsdream.org -cgsec.com -cgsfusion.com -cgsoft.net -cgspread.com -cgstartup.com -cgtblog.com -cgtime.net -cgtn.com -cgtop.com -cgtsj.com -cgtsj.org -cgtz.com -cguardian.com -cgufo.com -cguiw.com -cguwan.com -cgvoo.com -cgvxingx-zhongjie.com -cgwang.com -cgwell.com -cgwic.com -cgws.com -cgxc.cc -cgxia.com -cgxm.net -cgylke.com -cgylw.com -cgyou.com -cgyouxi.com -cgzy.net -cgzyw.com -cgzz8.com -ch-auto.com -ch-water.com -ch.com -ch028.net -ch12333.com -ch318.com -ch3s.com -ch933.com -ch999.com -ch999img.com -cha-tm.com -cha086.com -cha127.com -chabeichong.com -chachaba.com -chachaqu.com -chachongba.cc -chachongba.com -chacuo.net -chadan.wang -chadianshang.com -chadianshang2.com -chadown.com -chaduo.com -chaej.com -chafanhou.com -chafei.net -chahaoba.com -chahaotai.com -chaheji.com -chahua.org -chahuilv.com -chahuo.com -chaic.com -chaichefang.com -chaicp.com -chaihezi.com -chaijing.com -chaim.in -chaimage.com -chain-store.net -chaincar.com -chaindd.com -chainflag.com -chainhoo.com -chainknow.com -chainnode.com -chainsdir.com -chainsinn.com -chainsql.net -chainwhy.com -chainwon.cc -chainwon.com -chairyfish.com -chaishiguan.com -chaitin.com -chajian110.com -chajianmi.com -chajiaotong.com -chajie.com -chajn.org -chakahao.com -chakd.com -chakuaizhao.com -chalangautozone.com -challenge-21c.com -chalwin.com -chamcfae.com -chamei.com -chamiji.com -champconsult.com -champhier.com -champzee.com -chance-ad.com -chandashi.com -changan.biz -changan.com -changancap.com -changandaxiyuancn.com -changanfunds.com -changansuzuki.com -changantaihe.com -changba-ktv.com -changba.com -changbaapi.com -changbaapp.com -changbaimg.com -changbalive.com -changchun-ccpit.com -changchundaxuehs.com -changeol.com -changfon.com -changfubai.com -changhe.tech -changhong.com -changhongdianzi.com -changhongit.com -changhongnet.com -changingedu.com -changjiangdata.com -changjiangexpress.com -changjiangtimes.com -changker.com -changkunet.com -changliuliang.com -changlongyingshi.com -changning.net -changpingquzhongxiyijieheyiyuan.com -changpu3d.com -changqingshu.net -changrongwang.com -changsha-show.com -changshabdc.com -changshacsa.com -changshang.com -changshiban.com -changshifang.com -changtounet.com -changtu.com -changtu8.com -changweibo.com -changweibo.net -changxie.com -changxingyun.com -changyan.com -changyifan.com -changyin-lab.com -changyou.com -changyouke.com -changyoyo.com -changyueba.com -changzhinews.com -chanjet.com -chanluntan.com -chanmama.com -channeleffect.com -channelray.com -channingsun.bid -chanpay.com -chanpin100.com -chanpinban.com -chanpindashi.com -chanshiyu.com -chantci.com -chanumber.com -chanwuhotel.com -chanyeren.com -chanyouji.com -chanzhi.org -chanzuimei.com -chaoart.com -chaobaida.com -chaochaojin.com -chaofan.wang -chaofan365.com -chaofan86.com -chaofenxiang.vip -chaoji.com -chaojialin.com -chaojibiaoge.com -chaojideng.com -chaojifan.com -chaojifangyu.com -chaojilian.net -chaojilock.com -chaojishipin.com -chaojixiaobaicai.club -chaojiying.com -chaojiyun.com -chaojizuowen.com -chaolady.com -chaolean.com -chaolen.com -chaoliutai.com -chaolongbus.com -chaomengdata.com -chaomi.cc -chaomo25.com -chaonanrc.com -chaonei.com -chaonengjie.com -chaonenglu.com -chaoqun.mobi -chaoren.com -chaoshanren.com -chaoshen.cc -chaoshengboliuliangji.com -chaoshenmanhua.com -chaoskeh.com -chaosu.com -chaosuduokai.com -chaosw.com -chaotag.com -chaov.com -chaowaihui.com -chaowaihui.net -chaoxianstore.com -chaoxin.com -chaoxing.com -chaoxz.com -chaoyindj.com -chaoyisy.com -chaoyuelm.com -chaoyuesd.com -chaoyuyun.com -chaozhiedu.com -chaozhoudaily.com -chaozhuo.net -chaozuo.com -chapaofan.com -chaphone.com -chaping.tv -chapmanapm.com -chappell1811.com -chapuw.com -chargerlab.com -chargerlink.com -charmelady.com -charmingglobe.com -chartboost-china.com -chashebao.com -chateacher.com -chatm.com -chatnos.com -chatplus.ai -chawenti.com -chawenyi.com -chawo.com -chaxinyu.net -chaxunfapiao.com -chayangge.com -chaye.com -chayeo.com -chayu.com -chayueshebao.com -chayuqing.com -chazc.com -chazhaokan.com -chazhilan.com -chazidian.com -chazishop.com -chaziwang.com -chazuo.com -chazuo.net -chazuowang.com -chbcnet.com -chbtc.com -chcedo.com -chcoin.com -chczz.com -chda.net -chdajob.com -chdelphin.com -chdmv.com -chdtv.net -che.com -che0.com -che12.com -che127.com -che168.com -che2.com -che300.com -che43.com -che6che5.com -cheaa.com -cheapermai.com -cheapyou.com -cheari.com -chebaba.com -chebada.com -chebao360.com -checheboke.com -chechong.com -check.cc -checkin.gstatic.com -checkip.pw -checkoo.com -checkpass.net -chedan5.com -chediandian.com -cheduo.com -cheduoshao.com -cheerfun.dev -cheerjoy.com -cheersee.com -cheersofa.com -cheerspublishing.com -cheerupmail.com -chefafa.com -chefans.com -chefugao.com -cheguanyi.com -chegun.com -cheguo.com -chehang168.com -chehejia.com -chehubao.com -chehui.com -chekb.com -chekucafe.com -chelun.com -chem17.com -chem31.com -chem36.com -chem365.net -chem960.com -chem99.com -chemalink.net -chemao.com -chemayi.com -chemcp.com -chemcyber.com -chemdrug.com -chemicalbook.com -chemishu.com -chemm.com -chemmade.com -chemnet.com -chemrc.com -chemsb.com -chemsrc.com -chemyq.com -chen7782.com -chenag.com -chenall.net -chenanz.com -chenapp.com -chencx.com -chende.net -chenefei.com -cheneyliu.com -cheng-nuo.com -cheng-sen.com -cheng.guru -cheng95.com -cheng95.net -chengadx.com -chengailvsuo.com -chengbo.org -chengchuanren.com -chengdebank.com -chengdechina.com -chengder.com -chengdu-expat.com -chengdulvshi.net -chengdun.com -chengedeco.com -chengfeilong.com -chenggua.com -chengguw.com -chengjing.com -chengkao365.com -chenglang.net -chenglangyun.com -chenglin.name -chengliwang.com -chenglong.ren -chenglou.net -chengpeiquan.com -chengrang.com -chengrengaokaobaoming.com -chengshidingxiang.com -chengshiluntan.com -chengshiw.com -chengshizg.com -chengshu.com -chengsmart.com -chengtour.com -chengtu.com -chenguangblog.com -chengxiangqian.com -chengxinyouxuan.com -chengxuan.com -chengxuyuans.com -chengyangnews.com -chengyangyang.com -chengye-capital.com -chengyin.org -chengyiqq.vip -chengyuw.com -chengyuwb.com -chengzhongmugu.wang -chengzi520.com -chengzijianzhan.com -chengzivr.com -chenhaiyue.com -chenhr.com -chenhui.org -chenii.com -chenjia.me -chenjie.info -chenjiehua.me -chenjiemusic.com -chenjunlu.com -chenksoft.com -chenlb.com -chenlianfu.com -chenlinux.com -chenlongyx.com -chenmomo.com -chenpeng.info -chenplus.com -chenpot.com -chenqiego.com -chenruixuan.com -chenshiyi.com -chensonglin.net -chenty.com -chenwentan.com -chenxi-sh.com -chenxinghb.com -chenxitxt.net -chenxm.cc -chenxuehu.com -chenxuhou.com -chenxunyun.com -cheny.org -chenyaorong.com -chenyea.com -chenyistyle.com -chenyongjun.vip -chenyuan588.com -chenyuanjian.com -chenyudong.com -chenzao.com -chenzhicheng.com -chenzhongkj.com -chenzhongtech.com -cheonhyeong.com -cheoo.com -cheoz.com -chepin88.com -chepinnet.com -chepinxiu.net -chepoo.com -cheredian.com -cherishhealth.net -cherongzi.com -cherriespie.com -cherry101.com -cherymanuals.com -chese.online -cheshi-img.com -cheshi.com -cheshi18.com -cheshirex.com -cheshouye.com -chess-nyl.com -chesscnamerecovery.com -chestar.net -chesthospital.com -chesudi.com -chesusu.com -chetuanwang.net -chetuanyuan.com -chetuobang.com -chetx.com -chetxia.com -chevip.com -cheweishop.com -chewen.com -chexiang.com -chexiaopang.com -chexin.cc -chexinwen.com -chexiu.com -chexun.com -chexun.net -cheyaoshi.com -cheyian.com -cheyipai.com -cheyishang.com -cheyisou.com -cheyo.net -cheyoo.com -cheyooh.com -cheyou123.com -cheyun.com -cheyuu.com -chez360.com -chezhanri.com -chezhibao.com -chezhu1.com -chezhuzhinan.com -chezizhu.com -chgcis.com -chgcw.com -chgjcm.com -chgjedu.com -chgjjzx.com -chgtmy.com -chhblog.com -chhua.com -chhzm.com -chi2ko.com -chi588.com -chiang.fun -chianqs.com -chibaole.com -chichuang.com -chidaolian.com -chidaoni.com -chidaoshop.com -chidown.com -chidudata.com -chiefmore.com -chiefsexy.com -chieftin.org -chifenghualvlvxingshe.com -chihaigames.com -chihe.so -chiheba.com -chiji-h5.com -chijianfeng.com -childlib.org -chillyroom.com -chilunyc.com -chimatong.com -chimee.org -chimelong.com -chimezi.com -china-10.com -china-3.com -china-315.com -china-ah.com -china-apt.com -china-asahi.com -china-asm.com -china-b.com -china-caa.org -china-cas.org -china-cba.net -china-cbn.com -china-cbs.com -china-ccie.com -china-ccw.com -china-cdt.com -china-ceco.com -china-ced.com -china-cfa.org -china-changjiang.net -china-channel.com -china-chuwei.com -china-cicc.org -china-clearing.com -china-cloud.com -china-co.com -china-coc.org -china-cold.com -china-consulate.org -china-csdz.com -china-csm.org -china-customs.com -china-cw.com -china-d.com -china-def.com -china-designer.com -china-dim.org -china-drm.net -china-ef.com -china-efe.org -china-eia.com -china-embassy.org -china-engine.net -china-entercom.com -china-enterprise.com -china-epa.com -china-epc.org -china-erzhong.com -china-esi.com -china-experts.com -china-fire.com -china-flash.com -china-flower.com -china-g.com -china-galaxy-inv.com -china-genius.com -china-goldcard.com -china-highway.com -china-holiday.com -china-hongfei.com -china-hrg.com -china-huaxue.com -china-huazhou.com -china-hzd.com -china-insurance.com -china-invests.net -china-isotope.com -china-jm.org -china-kaihua.com -china-kaoshi.com -china-key.com -china-kids-expo.com -china-lawoffice.com -china-led.net -china-lushan.com -china-lzmj.com -china-m2m.com -china-moutai.com -china-nengyuan.com -china-nlp.com -china-nysw.com -china-obgyn.net -china-packcon.com -china-pcba.com -china-pharmacy.com -china-pops.net -china-pub.com -china-qiao.com -china-reform.org -china-ric.com -china-riscv.com -china-russia.org -china-see.com -china-seeq.com -china-share.com -china-shimo.com -china-show.net -china-shufajia.com -china-sites.com -china-slate.com -china-sorsa.org -china-spacenews.com -china-sss.com -china-tattoos.com -china-toy-edu.org -china-toy-expo.com -china-twofoundation.com -china-up.com -china-vcom.com -china-vision.org -china-vo.org -china-wanlin.com -china-waste.com -china-wss.com -china-xinbiao.com -china-zbycg.com -china-zikao.com -china.com -china.mintel.com -china.nba.com -china.uxengine.net -china001.com -china12365.com -china17.net -china1baogao.com -china1f.com -china2000.org -china35.com -china356.com -china360.net -china3gpp.com -china4a.org -china50plus.com -china5e.com -china60.com -china618.com -china6688.com -china724.com -china777.org -china95.net -china9s.com -china9y.com -chinaacc.com -chinaacc.tv -chinaadec.com -chinaaet.com -chinaagrisci.com -chinaairer.com -chinaalex.com -chinaamc.com -chinaamuse.com -chinaanonymous.com -chinaapp.org -chinaar.com -chinaasc.org -chinaaseanenv.org -chinaaseantrade.com -chinaasic.com -chinaautosupplier.com -chinaaviationdaily.com -chinab4c.com -chinabaike.com -chinabaiker.com -chinabaogao.com -chinabaoke.net -chinabathware.com -chinabbtravel.com -chinabda.org -chinabdh.com -chinabdt.com -chinabeer.net -chinabenson.com -chinabeston.com -chinabgao.com -chinabidding.com -chinabiddingzb.com -chinabigdata.com -chinabike.net -chinabimdata.org -chinabmi.com -chinabn.org -chinabookinternational.org -chinabreed.com -chinabug.net -chinabus.info -chinabuses.com -chinabx.com -chinabym.com -chinabyte.com -chinabyte.net -chinabzp.com -chinac.com -chinac3.com -chinacace.org -chinacache.cedexis.com -chinacache.com -chinacache.net -chinacache.org -chinacaipu.com -chinacaj.net -chinacamel.com -chinacampus.org -chinacarbide.com -chinacarz.com -chinacasa.org -chinaccm.com -chinaccnet.com -chinaccnet.net -chinaccsi.com -chinacct.org -chinacdlm.com -chinaceot.com -chinaceotv.com -chinacfi.net -chinacfo.net -chinacft.org -chinacg.org -chinachemnet.com -chinachugui.com -chinacics.org -chinaciosummit.com -chinacir.com -chinacity.net -chinacitywater.org -chinackf.net -chinacleanexpo.com -chinaclip.net -chinacma.org -chinacmo.com -chinacnr.com -chinacoal.com -chinacomix.com -chinaconch.com -chinaconsulatesf.org -chinacourt.org -chinacpda.com -chinacpda.org -chinacpec.com -chinacpx.com -chinacqsb.com -chinacrane.net -chinacreator.com -chinacrumpler.com -chinacses.org -chinacsf.com -chinactv.com -chinaculture.org -chinacxgd.com -chinacxjs.org -chinacyzf.org -chinadafen.com -chinadailyglobal.com -chinadance.com -chinadart.com -chinadatatrading.com -chinaday.com -chinadazhaxie.com -chinadds.net -chinadegi.com -chinadengshi.com -chinadentalshow.com -chinadep.com -chinadeveloper.net -chinadiaoyou.com -chinadigit.org -chinadmoz.org -chinadns.org -chinadoudi.com -chinadrtv.com -chinadsl.net -chinadysj.com -chinadyt.com -chinadz.com -chinadzyl.com -chinae.com -chinae.net -chinaecnet.com -chinaecotech.org -chinaeda.org -chinaedu.com -chinaedu.net -chinaeducationexhibition.com -chinaedunet.com -chinaefu.net -chinaehs.net -chinaeic.net -chinaeinet.com -chinaeinv.com -chinaemed.com -chinaequity.net -chinaera.org -chinaesm.com -chinaexam.org -chinaexpo365.com -chinaexport.cc -chinaeye.com -chinafanyi.com -chinafarad.com -chinafea.org -chinaffmpeg.com -chinafiber.com -chinafic.org -chinafilm.com -chinafilms.net -chinafinancenet.com -chinafinanceonline.com -chinafishtv.com -chinafix.com -chinaflashmarket.com -chinaflier.com -chinafoodj.com -chinaforklift.com -chinafpd.net -chinafph.com -chinafpma.org -chinaftat.org -chinafudaoban.com -chinagames.net -chinagayles.com -chinagb.net -chinagb.org -chinagba.com -chinagcd.com -chinagcp.org -chinagdg.com -chinagiftsfair.com -chinagoldcoin.net -chinagoldgroup.com -chinagolfindustryexpo.com -chinagolfshow.com -chinagp.net -chinagps.cc -chinagrid.net -chinagrowthcapital.com -chinagungho.net -chinagungho.org -chinaguyao.com -chinagwy.org -chinagwyw.org -chinagzn.com -chinagznw.com -chinahacker.com -chinaham.com -chinahao.com -chinaharp.com -chinahazelnut.com -chinahbnet.com -chinahightech.com -chinahighway.com -chinahkidc.net -chinahlwyy.com -chinahnjob.com -chinahnjs.com -chinahorse.org -chinahost.org -chinahotel.com -chinahpa.org -chinahqjjw.com -chinahr.com -chinahrd.net -chinahrgy.com -chinahrt.com -chinahte.com -chinahtz.com -chinahuben.com -chinahumanrights.org -chinahvacr.com -chinahw.net -chinahydro.com -chinahyyj.com -chinai.shop -chinaidaa.org -chinaidcnet.net -chinaidns.com -chinaido.com -chinaielts.org -chinaiern.com -chinaiia.com -chinainfoseek.com -chinainout.com -chinaiol.com -chinaios.com -chinaipmagazine.com -chinaipo.com -chinaiprlaw.com -chinairn.com -chinairr.org -chinaitcapital.com -chinaitlab.com -chinaitpower.com -chinajcz.com -chinajeweler.com -chinajjz.com -chinajnhb.com -chinajoinin.com -chinajoy.net -chinajs120.com -chinajsxx.com -chinajungong.com -chinajuva.com -chinajxship.com -chinajyxdh.com -chinajzqc.com -chinakaoyan.com -chinakaratedo.org -chinakidville.com -chinakinglink.com -chinakingo.com -chinakongzi.org -chinaks.net -chinaksi.com -chinakyzl.com -chinalabexpo.com -chinalabs.com -chinalancoo.com -chinalandpress.com -chinalao.com -chinalawbook.com -chinalawedu.com -chinalawinfo.com -chinalawyeryn.com -chinaleather.org -chinaledger.com -chinaleeper.com -chinalibs.net -chinalicensing.org -chinalicensingexpo.com -chinalifang.com -chinalims.net -chinalink-sh.net -chinalink.tv -chinalinuxpub.com -chinalions.com -chinalm.org -chinalongmai.net -chinalsjt.com -chinalubricant.com -chinalure.com -chinalushan.com -chinaluxus.com -chinalxnet.com -chinamae.com -chinamags.org -chinamap.com -chinamarintec.com -chinamaven.com -chinambn.com -chinamca.com -chinamcache.com -chinamcloud.com -chinameasure.com -chinameat.org -chinamendu.com -chinamenwang.com -chinamerger.com -chinametro.net -chinamfi.net -chinamining.com -chinamlmcc.com -chinamobile.com -chinamobilesz.com -chinamootools.com -chinamost.net -chinamsa.org -chinamsr.com -chinamusical.net -chinamusicbusinessnews.com -chinamypp.com -chinanbb.com -chinaneccs.org -chinanet-sh.com -chinanet.cc -chinanet88.com -chinanetcenter.com -chinanetidc.com -chinanetsun-dns.com -chinanetsun.com -chinaneweast.com -chinanews.com -chinaningbo.com -chinanmi.com -chinanotary.org -chinaobp.com -chinaoct.com -chinaonward.net -chinaopc.org -chinaopen.com -chinaops.org -chinaopticsvalley.com -chinaore.com -chinaosx.com -chinaosx.net -chinaott.net -chinaowps.com -chinapastel.com -chinapay.com -chinape168.com -chinapen.org -chinapet.com -chinapet.net -chinapharm.net -chinaphoto.cc -chinapipe.net -chinaplat.com -chinapm.org -chinapnr.com -chinapoesy.com -chinaports.com -chinapost-life.com -chinapowerbi.com -chinapp.com -chinapptx.com -chinaprint.org -chinaproaudio.com -chinapsy.com -chinapubmed.net -chinaqi.net -chinaqianyehua.com -chinaqingtian.com -chinaqipeihui.com -chinaqiyuan.com -chinaqking.com -chinaql.org -chinaquickpcb.com -chinaqw.com -chinardr.com -chinardr.net -chinaredstar.com -chinaren.com -chinareports.org -chinarootdesign.com -chinarta.com -chinartlaw.com -chinarun.com -chinarzfh.com -chinasa.net -chinasaat.com -chinasafety.net -chinasanc.com -chinasatcom.com -chinasb.org -chinasbj.net -chinasbjy.com -chinasbsp.com -chinasciencejournal.com -chinascopefinancial.com -chinascrum.org -chinascsoft.com -chinasexq.com -chinashadt.com -chinashangpinku.com -chinashj.com -chinashop.cc -chinashpp.com -chinasi.com -chinasie.com -chinasilk.com -chinasiwei.com -chinasky.net -chinasmartpay.com -chinasnow.net -chinasnw.com -chinaso.com -chinasofti.com -chinasoftinc.com -chinasoftosg.com -chinasosuo.cc -chinasou.com -chinasoushang.com -chinaspeeds.com -chinaspringtown.com -chinassl.com -chinassl.net -chinasspp.com -chinastoneforest.com -chinastor.com -chinastor.org -chinasufa.com -chinasupercloud.com -chinaswim.com -chinaswitch.com -chinasws.com -chinasydw.org -chinatai.com -chinataiwan.org -chinatalent.org -chinatarena.com -chinatat.com -chinatechinsights.com -chinatelecom-ec.com -chinatelecom.com.mo -chinatelecomiot.com -chinatelling.com -chinatet.com -chinatex.com -chinatex.net -chinatex.org -chinatibetnews.com -chinaticket.com -chinatietong.com -chinatikfans.com -chinatimber.org -chinatimes.cc -chinatiner.com -chinatiredealer.com -chinatopbrands.net -chinatour-net.com -chinatourguide.com -chinatpm.com -chinatpm.net -chinatranslation.net -chinatravel.net -chinatraveldepot.com -chinatraveldesigner.com -chinatravelsolution.com -chinatruck.org -chinatrucks.com -chinatsi.com -chinatsp.com -chinattl.com -chinatungsten.com -chinatupai.com -chinatv-net.com -chinatvc.com -chinatyco.com -chinaufo.com -chinaui.com -chinauidesign.com -chinauma.com -chinaums.com -chinaun.net -chinaunicom-a.com -chinaunicom.com -chinaunionpay.com -chinauniversalasset.com -chinaunix.com -chinaunix.net -chinaunix.org -chinauo.com -chinauos.com -chinauos.net -chinauos.org -chinaupa.com -chinaups.com -chinaus-maker.org -chinaus.com -chinauso.com -chinavalin.com -chinavalue.net -chinavcpe.com -chinavfx.net -chinavid.com -chinavideo.org -chinavipsoft.com -chinavisual.com -chinavivaki.com -chinavnet.com -chinavoa.com -chinavr.net -chinawaijiao.com -chinawaiyu.com -chinawanda.com -chinawatchnet.com -chinawater.net -chinawbk.com -chinawbsyxh.com -chinawch.com -chinawebber.com -chinawebmap.com -chinaweiyu.com -chinawenben.com -chinawenwang.com -chinawestnews.net -chinawie.com -chinawiserv.com -chinawitmedia.com -chinawoodnet.com -chinawpn.com -chinawr.net -chinawudang.com -chinawutong.com -chinawutong.net -chinawuyuan.com -chinaxiaokang.com -chinaxinge.com -chinaxinport.com -chinaxpp.com -chinaxq.com -chinaxueqian.com -chinaxwcb.com -chinayigou.com -chinayigui.com -chinayk.com -chinaymc.com -chinaymtz.com -chinayouji.com -chinayyjx.com -chinayyo.com -chinaz.com -chinaz.net -chinazhai.net -chinazhaokao.com -chinazhiqing.org -chinazhw.com -chinazichan.com -chinazikao.com -chinazjph.com -chinazjy.com -chinaznj.com -chinazns.com -chinaznyj.com -chinazov.com -chinazxt.com -chinazyjr.com -chinca.org -chindiaforum.com -chine-info.com -chinebuy.com -chinee.com -chinese-luxury.com -chinese-no1.com -chineseacc.com -chineseafs.org -chineseall.com -chinesecio.com -chineseconsulate.org -chineseembassy.org -chinesehongker.com -chinesejk.com -chinesejy.com -chineselaw.com -chinesemooc.org -chineserose.com -chinesetown.net -chingkun.com -chingli.com -chingmi.com -chinlingo.com -chinput.com -chint.com -chint.net -chipcoo.com -chipcreation.com -chipdance.com -chiphell.com -chiplayout.net -chipmanufacturing.org -chiponeic.com -chipown.com -chiprf.com -chipsbank.com -chipsec.com -chipsgo.com -chipsir.com -chipwing.com -chipwings.com -chiq-cloud.com -chiralquest.com -chisc.net -chiselchina.com -chiser.cc -chishoes.com -chitanda.me -chitu.com -chitu101.com -chitu103.com -chitu104.com -chitu107.com -chitunion.com -chivast.com -chivox.com -chivoxapp.com -chiwayedu.com -chixing.net -chixm.com -chiyuebing.com -chiyuekj.com -chiyuewenhua.com -chizhoujob.com -chizhouren.com -chiznews.com -chjso.com -chkj365.com -chlahb.com -chloe99.com -chmecc.org -chmed.net -chmgames.com -chmia.org -chn112.com -chn168.com -chn789.net -chnart.com -chnau99999.com -chnbook.org -chnci.com -chncia.org -chncomic.com -chncpa.org -chncwds.com -chndesign.com -chndsnews.com -chndtb.com -chnews.net -chnfi.com -chnfm.com -chnfund.com -chngalaxy.com -chngc.net -chnjet.com -chnlanker.com -chnlib.com -chnmodel.com -chnmus.net -chnmusic.org -chnp2p.com -chnpac.com -chnpec.com -chnpic.net -chnppmuseum.com -chnroad.com -chnsuv.com -chnvc.com -chnweiyu.com -chocolatehappyland.com -chofn.com -chofn.net -chofn.org -chofnipr.com -choiceform.com -chong4.net -chongai.co -chongbaoge.com -chongbuluo.com -chongchi.com -chongchuang.biz -chongdeedu.com -chongdiantou.com -chongdongshequ.com -chonghi.com -chongnuoji.com -chongqingdongjin.com -chongsoft.com -chongwu.cc -chongwujiaoyi.com -chongxiaobao.net -chongzhi.com -chonka.com -chotee.com -chouchoujiang.com -choujue.net -choukang.com -choupangxia.com -chouqinshuwu.com -chouqu.com -chouti.cc -chouti.com -chpanshi.net -chplayer.com -chrent.com -chrice.net -chris-tina.com -christianlouboutin-shop.com -christianris.com -chrisyue.com -chrmn.com -chrom-china.com -chromecj.com -chromedownloads.net -chromefor.com -chromeliulanqi.com -chrstatic.com -chs.so -chshcms.com -chshouyu.com -chshuju.com -chsite.net -chsqh.com -chste.com -chtf.com -chtgc.com -chtpe.com -chtse.com -chuaiguo.com -chuairan.com -chuaizhe.com -chuanbofanyi.com -chuanbojia.com -chuanboyi.com -chuandaizc.com -chuandong.com -chuang.pro -chuangb.com -chuangbie.com -chuangcache.com -chuangcdn.com -chuangchangnet.com -chuangcifang.com -chuangduyouyue.com -chuangen.com -chuangfeixin.com -chuangjiangx.com -chuangke18.com -chuangkem.com -chuangkeup.com -chuangkit.com -chuanglian.net -chuanglinggame.com -chuangluo.com -chuangread.com -chuangshifurui.com -chuangshileather.com -chuangshizhenghe.com -chuangtoo.com -chuangx.org -chuangxin.com -chuangxinapi.com -chuangxinoa.com -chuangye.com -chuangye98.com -chuangyebaba.com -chuangyejia.com -chuangyejia.vip -chuangyejian.com -chuangyejmw.com -chuangyemeng.com -chuangyepu.com -chuangyezhu.com -chuangyijisu.com -chuangyimao.com -chuangyouqi.com -chuangyunet.com -chuangzaoshi.com -chuanjiaoban.com -chuanke.com -chuanmeixing.com -chuanmeizy.com -chuannan.net -chuanqi.com -chuanqian999.com -chuanqiu.net -chuanshanqundao.com -chuansong.me -chuansongme.com -chuantec.com -chuantou.org -chuantu.biz -chuanxincao.net -chuanye.com -chuanying365.com -chuanying520.com -chuanyinpx.com -chuapp.com -chubaodai.com -chubh.com -chucaotang.com -chucaotang.net -chuchuguwen.com -chuchujie.com -chudaoyou.com -chudeer.com -chudian365.com -chufa123.com -chufaba.me -chufw.com -chuge8.com -chuguo78.com -chuguofeng.com -chuguohao.com -chuhoi.com -chuimg.com -chuinet.com -chuixue.net -chuiyue.com -chuji8.com -chuju750.com -chujuan.net -chukong-inc.com -chukou1.com -chukuangren.com -chule.cc -chulouwang.com -chumacdn.com -chumanapp.com -chumengxiang.com -chumenwenwen.com -chumo028.com -chunbo.com -chunboimg.com -chuncui.net -chuncuinet.com -chundakj99.com -chundi.com -chundi.org -chunengauto.com -chunfengapp.com -chunge188.com -chungeseo.com -chungkwong.cc -chunjingtech.com -chunjiws.com -chunmi.com -chunqiuwang.com -chunshuitang.com -chunshuizhijia.com -chunsuns.com -chunxuanmao.com -chunyao.org -chunyiscdk.com -chunyu.me -chunyu.mobi -chunyuyisheng.com -chunzuijiuye.com -chuquan.me -chuqulvxing.com -chureng.com -churenjixie.com -chusan.com -chuseo.com -chushan.com -chushang027.com -chushibiao5.com -chushihome.com -chushiji.com -chushou.tv -chushu123.com -chutianlaser.com -chutianzhinu.com -chuwi.com -chuxiangyi.com -chuxindata.com -chuxingyouhui.com -chuxinhudong.com -chuxinm.com -chuxueyun.com -chuying.org -chuyouke.com -chuyu.me -chuzhaobiao.com -chvv.com -chw365.com -chwlsq.com -chxlm.com -chyangwa.net -chydafuse.com -chyfh.com -chysoft.net -chyw.pub -chyxx.com -chzhkeji.com -chzhw.com -chzybj.com -ci123.com -ci4s.com -ci52.com -ci800.com -ciamiecn.com -ciandcd.com -ciaoca.com -ciatcm.org -ciavision.com -cibfintech.com -cibn.cc -cibn.com -cibntv.net -ciboedu.org -cibonet.com -cibresearch.com -cibuser.com -cicaf.com -ciccfund.com -ciccorporate.com -ciccphoto.com -ciceme.com -cicet.net -ciciec.com -cicmag.com -cicphoto.com -cict.com -cicw.org -cidgroup.com -cidi.ai -cidiancn.com -cidianwang.com -cidschina.com -cidugushi.com -ciec-expo.com -ciect.com -cieet.com -cietac-hb.org -cietac-sc.org -cietac.org -cietv.com -cifalshanghai.org -cifco.net -cifm.com -cifnews.com -cifoo.com -ciftis.org -cigarambassador.com -cigbiexpo.com -cignacmb.com -cigotime.com -cihai123.com -cihexpo.com -ciia-if.org -ciicgat.com -ciidoo.com -ciie.org -ciif-expo.com -ciiip.com -ciimg.com -cijian.us -cijilu.com -cikeblog.com -ciku5.com -cili001.com -cili8.xyz -ciliba.buzz -ciliba.life -ciliba.pro -ciliguanjia.cyou -cilimao.me -cilin.org -cilogo.com -ciluwx.com -cim2025.net -cimc.com -ciming-bj.com -ciming-shop.com -ciming.com -cimingaoya.com -cimingsy.com -cimingyc.com -cimsic.com -cimtshow.com -cinasoft.com -cindasc.com -cindasoft.com -cinehello.com -cingta.com -ciniao.me -cinsee.com -cinyi.com -cio114.com -cio360.net -cioage.com -ciotimes.com -ciotour.com -ciou.com -cip.cc -cipgtrans.com -ciplawyer.com -cippe.net -ciprun.com -cipscom.com -ciqinghui.com -cirmall.com -cirno9.net -cirunzhang.com -cismag.net -cismef.com -cisskwt.com -citahub.com -citexpo.org -citiais.com -citic-cid.com -citic.com -citicbank.com -citicbankuser.com -citiccard.com -citics.com -citicsf.com -citicsinfo.com -citicsqh.com -citicsteel.com -citidigital.com -citisa.org -citiz.net -citreport.com -cits-sz.net -cits.com.mo -cits0871.com -cits2.com -citscq.com -citscsc.com -citshq.com -citssh.com -citszz.com -cittc.net -citure.net -citvc.com -citw2008.com -city8.com -city84.com -citydating92.xyz -citydh.com -citygf.com -cityhui.com -citylinker.com -citysbs.com -citysz.net -citytogo.com -cityup.org -citywo.com -cityy.com -civclub.net -civilcn.com -civilness.com -civiw.com -ciweek.com -ciweekly.com -ciwei.me -ciweimao.com -ciweishixi.com -ciweiyuedui.com -ciwong.com -ciwork.net -cixibank.com -ciyocon.com -ciyuan.men -ciyuanshequ.com -cj-elec.com -cjavapy.com -cjbigdata.com -cjcjw.com -cjcp.org -cjdby.net -cjdcw.com -cjdropshipping.com -cjeduw.com -cjftb.com -cjhb168.com -cjhospital.com -cjhxfund.com -cjienc.com -cjiit.com -cjjjs.com -cjk3d.net -cjkcgs.com -cjkhd.com -cjkj.ink -cjkz.com -cjlap.com -cjlhs.com -cjm.so -cjmakeding.com -cjmit.com -cjmx.com -cjn.com -cjnis.com -cjol.com -cjolimg.com -cjrcsc.com -cjsc.com -cjssy.com -cjting.me -cjty.net -cjveg.com -cjxz.com -cjyun.club -cjyun.org -cjyyw.com -cjzkw.com -cjzy.net -cjzzc.com -ck-qq.com -ck100.com -ck180.net -ck8733.com -ckair.com -ckck.vip -ckd.cc -ckd.im -ckd.so -ckdzb.com -ckefu.com -ckernel.org -ckeyedu.com -ckgcjl.com -ckimg.com -ckjr001.com -ckkpp.com -ckmov.com -ckook.com -ckplayer.com -ckplayer.tv -ckpoo.com -cksd888.com -cksic.com -ckuai.com -ckurk.org -ckxsw.com -ckxx.net -ckzhijiaedu.com -cl-acg.com -cl-hs.com -cl-kongtiao.com -cl-mail.ru -cl0438.com -cl1-cdn.origin-apple.com.akadns.net -cl1.apple.com -cl2-cn.apple.com -cl2.apple.com -cl2.apple.com.edgekey.net.globalredir.akadns.net -cl2009.com -cl3-cdn.origin-apple.com.akadns.net -cl3.apple.com -cl3000.com -cl4-cdn.origin-apple.com.akadns.net -cl4-cn.apple.com -cl4.apple.com -cl5-cdn.origin-apple.com.akadns.net -cl5.apple.com -cl597.com -clabso.com -clady.cc -claiks.com -clanzx.net -claritywallpaper.com -class01.com -classfoo.com -classmateer.com -clayidols.com -claykessack.com -claymore.wang -clb6.net -clboss.com -clbu.club -clcindex.com -clclibrary.com -clcmw.com -cld-mail.ru -clean-cn.com -cleaninfo.com -clear-sz.com -clear888.com -clearaki.com -cleey.com -clewm.net -clf.red -clfile.com -clg5.info -cli.im -click-v.com -click369.com -clickclaro.xyz -clickserve.dartsearch.net -clicksun.net -clickwifi.net -client51.com -clientflow.apple.com -clientflow.apple.com.akadns.net -clientservices.googleapis.com -cliffordtrading.com -cliim.com -cliim.net -clin003.com -clinicmed.net -clink-ads.xyz -clinkworld.com -cliport.com -clivechia.com -cljmmm123.com -clkyjt.com -clled.com -clloz.com -clocklab.tech -cloopen.com -cloopen.net -closertb.site -clotfun.mobi -clotfun.online -clotfun.xyz -clotheshr.com -clothjob.com -clothr.com -clouclip.com -cloud-cube.net -cloud-dns.net -cloud-frame.com -cloud-links.net -cloud-neofussvr.sslcs.cdngc.net -cloud-sun.com -cloud.ph -cloud301.net -cloudacc-inc.com -cloudajs.org -cloudangelfunds.com -cloudbility.com -cloudcc.com -cloudcdn.net -cloudcdns.com -cloudcdns.net -cloudcioevent.com -cloudcross.com -cloudcsp.com -cloudcusersyn.com -clouddcs.com -clouddn.com -clouddream.net -cloudgap.net -cloudgertopage.com -cloudgfw.com -cloudgfw.net -cloudglb.com -cloudglb.net -cloudgoing.com -cloudguarding.com -cloudhosts.xyz -cloudhua.com -cloudhvacr.com -cloudinnov.com -cloudinward.com -cloudiplc.com -cloudkirin.com -cloudleft.com -cloudmap.hk -cloudmes.io -cloudminds.com -cloudnapps.com -cloudp.cc -cloudpense.com -cloudphotoes.com -cloudpnr.com -cloudpsvn.com -cloudroom.com -cloudsation.com -cloudsea.org -cloudsee.com -cloudseeplus.com -cloudseetech.com -cloudserver01.com -cloudsgis.com -cloudsoar.com -cloudsohu.net -cloudstack-china.org -cloudtcp.net -cloudtomicro.com -cloudtopo.com -cloudtrans.com -cloudtui.com -cloudvast.com -cloudvdn.com -cloudvogue.com -cloudwise.com -cloudxns.com -cloudxns.net -cloudyo.net -cloudyouku.com -clpga.org -clsn.io -clssn.com -cltt.org -clubweixin.samsung.com -clusterdnsserver.com -clx360.com -clyric.com -clz.me -cm-analysis.com -cm-iov.com -cm10085.com -cm233.com -cm3721.com -cmacredit.org -cmaif.com -cmall.com -cmanuf.com -cmb-leasing.com -cmbajia.com -cmbchina.com -cmbchina.net -cmbchinaucs.com -cmbimg.com -cmbuy10086.com -cmbwinglungbank.com -cmc168.com -cmcc.in -cmcm.com -cmcmcdn.com -cmd5.com -cmd5.la -cmd5.org -cmda.net -cmdb.xyz -cmdmexpo.com -cmdrh.com -cmdschool.org -cmdy2020.com -cmdy5.com -cmechina.net -cmejob.com -cmenergyshipping.com -cmes.org -cmetamap.com -cmfchina.com -cmfish.com -cmfspay.com -cmft.com -cmfu.com -cmgame.com -cmge.com -cmgos.com -cmgrasp.com -cmhello.com -cmia.info -cmicapm.com -cmidc.net -cming.com -cmiyu.com -cmjoy.com -cmjz.net -cmljs.org -cmmim.com -cmnet-speed.com -cmnxt.com -cmo.so -cmoct.com -cmodes.com -cmol.com -cmpassport.com -cmpay.com -cmread.com -cms.ibm.com -cms1924.org -cmsblogs.com -cmschina.com -cmscmc.org -cmseasy.cc -cmsfg.com -cmsjournal.net -cmskcrm.com -cmsky.com -cmsn.biz -cmstop.com -cmswj.com -cmsyou.com -cmsyuanma.com -cmt178.com -cmt7.com -cmtdi.com -cmtech.net -cmu1h.com -cmuliang.com -cmwb.com -cmwin.com -cmxrcw.com -cmxwsj.com -cmys.tv -cmzd.com -cmzj.net -cmzy168.com -cmzyk.com -cn-api.samsungcloud.com -cn-bowei.com -cn-c114.net -cn-em.com -cn-fe.com -cn-healthcare.com -cn-java.com -cn-jnrc.com -cn-lcd.com -cn-mpa.com -cn-msedge.net -cn-mw.com -cn-office.com -cn-psy.com -cn-railway.net -cn-roofexpert.com -cn-soft.com -cn-truck.com -cn-visa.com -cn-xbn.com -cn-zhentai.com -cn.bing.com -cn.bing.net -cn.img.stb.s-msn.com -cn.msi.com -cn.net -cn.pandora.net -cn.vc -cn.windowssearch.com -cn0-6.com -cn00.com -cn006.com -cn010w.com -cn029.com -cn0434.com -cn0556.com -cn0713.com -cn0851.com -cn0917.com -cn12333.com -cn12365.org -cn168.com -cn18k.com -cn2-cn2.com -cn20.com -cn21edu.com -cn22.net -cn2che.com -cn314.com -cn357.com -cn360cn.com -cn365c.com -cn365d.com -cn3k5.com -cn3v.net -cn3wm.com -cn486.com -cn50hz.com -cn51.com -cn5135.com -cn539.com -cn68.com -cn6szx.com -cn716.com -cn8118.com -cn8fre.com -cn99.com -cn9f.com -cna5.com -cnaaa15.com -cnaaa6.com -cnaaa7.com -cnaaa9.com -cnacg.cc -cnad.com -cnaf.com -cnagcoin.com -cnaho.com -cnaicpa.org -cnaidai.com -cnaidc.com -cnaifm.com -cnair.com -cnal.com -cname-cdn.com -cname-url.com -cname.co -cname123.net -cnantennas.com -cnanzhi.com -cnautofinance.com -cnautonews.com -cnbabylon.com -cnball.net -cnbanbao.com -cnbang.net -cnbaowen.net -cnbct.org -cnbearing.biz -cnberg.com -cnbeta.com -cnbetacdn.com -cnbetnew.com -cnbidding.com -cnbigcloud.com -cnbiocell.com -cnbis.org -cnbizmedia.com -cnbkw.com -cnblogs.com -cnblogsc.com -cnblogse.com -cnbluebox.com -cnbmys.com -cnbntv.com -cnboat.com -cnbooks.org -cnbp.net -cnbuses.com -cnbw114.com -cnbzlf.com -cnbzol.com -cnbzs.com -cnc-gd.net -cnca.net -cncait.net -cncard.com -cncc.bingj.com -cnccac.com -cnccar.com -cnccchina.com -cncelab.com -cnceo.com -cncgw.org -cnchainnet.com -cnchanran.com -cncheng.com -cnchezhan.com -cnchu.com -cncico.com -cnciyuan.com -cncjmjg.com -cncloud.com -cncmrn.com -cncms.com -cncn.com -cncn.net -cncnbd.com -cncncloud.com -cncncn.com -cncnet.net -cncnki.com -cncnz.net -cncoders.net -cncolour.com -cncondom.com -cncookernet.com -cncoolm.com -cncopter.com -cncotton.com -cncourt.org -cncraftinfo.com -cncrk.com -cncrony.com -cncrypt.com -cncsj.net -cncszs.com -cnctui.com -cncz360.com -cnczjy.com -cnd8.com -cndae.com -cndao.com -cndata.com -cndatacom.com -cndds.com -cndesign.com -cndfilm.com -cndfjy.com -cndids.com -cndingxi.com -cndip.com -cndjyswlw.com -cndkc.net -cndns.com -cndns5.com -cndog.net -cndoornet.com -cndoors.com -cndrynet.com -cndsnet.com -cndss.net -cndtlab.com -cndw.com -cndy.org -cndzq.com -cndzys.com -cnecc.com -cnedoc.com -cnedres.org -cneeex.com -cnelc.com -cnelecom.net -cnelite.org -cneln.net -cnemb.com -cnena.com -cnenergy.org -cneol-dns.net -cnep001.com -cnepaper.com -cnepaper.net -cnerlang.com -cnern.org -cnesf.com -cnetea.net -cnetec.com -cnetsec.com -cnetworks.org -cneuol.com -cnevi.com -cnexp.net -cnexps.com -cneyoo.com -cnezsoft.com -cnfanews.com -cnfantasia.com -cnfaxie.org -cnfbfcw.com -cnfczn.com -cnfdlt.com -cnfeat.com -cnfeelings.com -cnfeol.com -cnffi.com -cnfiberhome.com -cnfilternet.com -cnfina.com -cnfirst.org -cnfish.com -cnfisher.com -cnfla.com -cnfmp.net -cnfol.com -cnfol.hk -cnfolimg.com -cnforever.com -cnforex.com -cnfpzz.com -cnfq.com -cnfqy.com -cnfrag.com -cnfree.org -cnfruit.com -cnfsae.com -cnfuchsiaos.com -cnfuyin.org -cnfxj.org -cnfygy.com -cnfyyj.com -cnfzdc.com -cnfzflw.com -cngal.org -cngaosu.com -cngb.org -cngba.com -cngbn.com -cngdwx.com -cnggt120.com -cngin.com -cnglb.com -cngnu.net -cngold.org -cngoldres.com -cngrain.com -cngreenfield.com -cngrok.com -cngui.com -cngulu.com -cnh168.com -cnh5.net -cnhacker.com -cnhackhy.com -cnhaio.com -cnhalo.net -cnhan.com -cnhandan.com -cnhangpaiw.com -cnhanxing.com -cnhaoshengyi.com -cnhaskell.com -cnhbgt.com -cnhbstock.com -cnhd.com -cnhetianyu.com -cnhhl.com -cnhls.com -cnhlsxe.com -cnhm.net -cnhmsq.com -cnhnb.com -cnhoney.com -cnhongke.org -cnhonker.com -cnhot.cc -cnhowotruck.com -cnhqzb-wx.com -cnhsjz.com -cnhszx.com -cnhuadong.net -cnhuanya.com -cnhubei.com -cnhubu.com -cnhutong.com -cnhvacrnet.com -cnhwjt.com -cnhzz.com -cniaas.com -cniao5.com -cniao8.com -cnibx.com -cnicif.com -cnidea.net -cnimg.elex.com -cninfo.net -cninnovatel.com -cninternetdownloadmanager.com -cnipa-gd.com -cnipa-hb.com -cnipa-pesc.com -cnipa-sc.com -cnipa-tj.com -cnipai.com -cnipr.com -cnisland.com -cnisp.org -cnispunion.org -cnit-research.com -cnit618.com -cnitblog.com -cniteyes.com -cniti.com -cnitom.com -cnitpm.com -cnjcs.com -cnjdz.net -cnjiaju.com -cnjidan.com -cnjingbu.com -cnjingchu.com -cnjiwang.com -cnjiyin.com -cnjj.com -cnjjl.com -cnjjwb.com -cnjlc.com -cnjnsb.com -cnjob.com -cnjoel.com -cnjournals.com -cnjpetr.org -cnjsqw.com -cnjunzilan.com -cnjxol.com -cnjyky.com -cnjywl.com -cnjzb.com -cnjzjj.com -cnk8.com -cnkaile.com -cnkang.com -cnkefa.com -cnkeyboard.com -cnkeyboard.net -cnki.mobi -cnki.net -cnki.vip -cnkicheck.info -cnkicheck.org -cnkiki.net -cnkinect.com -cnkiorg.com -cnkirito.moe -cnkis.net -cnkitop.com -cnkivip.net -cnkix.com -cnkizw.com -cnklog.com -cnkme.com -cnknowledge.com -cnkok.com -cnkore.com -cnkuai.com -cnky.net -cnlangier.com -cnlaw.net -cnledw.com -cnlhzb.com -cnlianjie.com -cnlid.net -cnlight.com -cnlightnet.com -cnliken.com -cnlinfo.net -cnlist.com -cnlist.org -cnlive.com -cnliveimg.com -cnllz.com -cnlogo8.com -cnluqiao.com -cnmanhua.com -cnmattson.com -cnmcom.com -cnmdy.com -cnmediae.com -cnmeifa.com -cnmeishu.com -cnmeiwei.com -cnmhmedical.com -cnmia.org -cnmill.com -cnmineqs.net -cnmkv.com -cnmo.com -cnmobile.net -cnmods.org -cnmoi.org -cnmsl.net -cnmsn.net -cnmstl.net -cnmsw.net -cnmtpt.com -cnmxk.com -cnmysql.com -cnnaihuo.com -cnnanbowang.com -cnnb.com -cnnbfdc.com -cnndns.com -cnnerv.com -cnnetsec.com -cnnewss.com -cnnfootballclub.com -cnnmol.com -cnnorip.org -cnnot.com -cnnovels.com -cnnpa.com -cnnpz.com -cnns.net -cnntt.com -cnnuo.com -cnobol.com -cnodejs.org -cnoee.com -cnoenet.com -cnohd.com -cnoic.com -cnoil.com -cnokcn.com -cnol.cc -cnolnic.com -cnolnic.net -cnonline.org -cnookr.com -cnool.net -cnophol.com -cnops.xyz -cnosr.com -cnoswiki.com -cnoutdoor.com -cnpaf.net -cnpatent.com -cnpc-hy.com -cnpenjing.com -cnpet.cc -cnpghouse.com -cnphar.net -cnpharm.com -cnphotos.net -cnphp.info -cnpickups.com -cnpkm.com -cnplugins.com -cnpmjs.org -cnpolitics.org -cnponer.com -cnpou.com -cnpowdernet.com -cnpowdertech.com -cnpps.org -cnprofit.com -cnpubg.com -cnpusi.com -cnpv.com -cnpython.com -cnpythoner.com -cnqc.com -cnqd.net -cnqiang.com -cnqiaoxiang.com -cnqjc.com -cnqjw.com -cnqlk.com -cnqr.org -cnquanjing.com -cnradio.com -cnrainbird.com -cnraksmart.com -cnrancher.com -cnratchet.com -cnrceo.com -cnrcloudfm.com -cnrdm.com -cnrdn.com -cnread.net -cnreagent.com -cnree.com -cnrencai.com -cnrepair.com -cnrepark.com -cnrexue.com -cnrmall.com -cnrmobile.com -cnrouter.com -cnrv.io -cns.hk -cnsaes.org -cnsal.com -cnsat.net -cnsav.com -cnsaw.com -cnsb.org -cnsc8.com -cnsce.net -cnscee.com -cnscfa.com -cnsdjxw.com -cnsdtv.com -cnsdzb.com -cnseay.com -cnsecer.com -cnseeq.com -cnsesan.com -cnsfk.com -cnshipnet.com -cnshipping.com -cnsikao.com -cnsimin.com -cnskf-bearing.com -cnskyit.com -cnsnpj.com -cnso.org -cnsoc.org -cnsoe.com -cnsoftbei.com -cnsoftnews.com -cnsolomo.com -cnsourcing.org -cnspeed.com -cnspeedtest.com -cnspeedtest.net -cnsphoto.com -cnssz.com -cnstea.com -cnstock.com -cnsun.cc -cnsun.net -cnsuning.com -cnsunp.com -cnsuomei.com -cnsupu.com -cnsuv.com -cnsyhz.com -cnsynews.com -cnsyyx.com -cntaiping.com -cntapp.com -cntca.com -cntexjob.com -cntheory.com -cnthub.com -cntiaoliao.com -cntofu.com -cntopgear.com -cntoplead.com -cntour2.com -cntour365.com -cntourwh.com -cntrades.com -cntronics.com -cntuku.com -cntuw.com -cntv.com -cntxw.com -cnuli.com -cnuninet.net -cnutcon.com -cnuuu.com -cnv168.com -cnvcs.com -cnvf.com -cnvps.com -cnvr-expo.com -cnvultr.com -cnwa.com -cnwage.com -cnwaking.com -cnwaternews.com -cnwb.net -cnwdjj.com -cnwdsy.com -cnwear.com -cnwebe.com -cnweblog.com -cnwebshow.com -cnwen.net -cnwenshi.net -cnwest.com -cnwhc.com -cnwhotel.com -cnwindows.com -cnwinenews.com -cnwnews.com -cnwtn.com -cnwxw.com -cnxad.com -cnxct.com -cnxds.com -cnxhacker.com -cnxiangyan.com -cnxiantao.com -cnxianzai.com -cnxiaoyuan.com -cnxibu.com -cnxile.com -cnxk.com -cnxklm.com -cnxnmy.com -cnxuntu.com -cny9.com -cnyanglao.com -cnygf.net -cnyicheng.com -cnyigui.com -cnyings.com -cnyingyin.com -cnyipu.com -cnyouhao.com -cnys.com -cnyu.com -cnyugan.com -cnyuheng.net -cnyuming.com -cnyunwei.com -cnyw.net -cnywinfo.com -cnyxs.com -cnzao.com -cnzazhi.net -cnzhanting.com -cnzhantuan.com -cnzhanzhang.com -cnzhengmu.com -cnzhibo.com -cnzhiyuanhui.com -cnzjol.com -cnzknet.com -cnzlapp.com -cnzmyn.com -cnzsqh.com -cnzsyz.com -cnzweal.com -cnzxsoft.com -cnzyao.com -cnzz.cc -cnzz.com -cnzz.net -cnzz6.com -cnzznz.com -co-effort.com -co-inclusion.org -co188.com -co188cdn.com -coachtech.online -coal-link.com -coalcn.com -coantec.com -coaoo.com -coatingol.com -cobbersz.com -cobenet.com -cobkl.com -cocas.cc -cocblo.com -cocccc.vip -coccccc.cc -cocimg.com -coco413.com -cocoachina.com -cocodiy.com -cocomanhua.com -cocophp.com -cocoren.com -cocos.com -cocos.org -cocos2d-x.org -cocos2dev.com -cocos2dx.net -cocosbcx.net -cocoseditor.com -cocostudio.org -cocounion.com -cocss.com -cocty.com -codante.org -code-by.org -code.sh -code4apk.com -code4app.net -code668.com -codeaha.com -codebe.org -codeblogbt.com -codebus.net -codebye.com -codecoke.com -codedefault.com -codedocs.net -codedq.net -codedream.xin -codeforge.com -codehy.com -codeisbug.com -codejie.net -codekissyoung.com -codekk.com -codeku.me -codelast.com -codelife.me -codelover.link -codemany.com -codemart.com -codemcx.work -codemm.net -codeok.com -codepiano.com -codepku.com -codeplayer.vip -codepub.com -coder.work -coder100.com -coder4.com -coder55.com -coderbee.net -coderclock.com -codercto.com -coderdock.com -coderhuo.tech -coderli.com -coderonline.net -coderplanets.com -coderprepares.com -codersec.net -coderxing.com -coderyuan.com -coderzh.com -codes51.com -codesec.net -codesky.me -codesky.net -codesocang.com -codesoft.hk -codesoftchina.com -codesoso.com -codespu.com -codess.cc -codetc.com -codeweblog.com -codewenda.com -codewoody.com -codeyu.com -codezyw.com -codin.im -coding-newsletter.com -coding-pages.com -coding.me -coding.net -coding.red -codingapp.com -codingbelief.com -codingboy.com -codingdao.com -codingdict.com -codingke.com -codinglabs.org -codingplayboy.com -codingpy.com -codingserf.com -codingsky.com -codingwhy.com -codingyang.com -codoon.com -codooncdn.com -codrim.net -cofco.com -cofcosp.com -cofeed.com -cofess.com -cofface.com -coffee-script.org -coffee08.com -cofly.com -cofool.com -cofoolfx.com -cogcpa.org -cogitosoft.com -cogobuy.com -cogonline.com -cohim.com -coilmx.com -coin007.com -coin163.com -coinall.live -coinall.ltd -coincola.net -coincsd.com -coineal.com -coinfire.vip -coingogo.com -coinlisit.com -coinnice.com -coinsky.com -coinvs.com -coinw.com -cojia.net -cokemine.com -cokll.com -col.ink -colabug.com -colachan.com -coladrive.com -colafile.com -colahotpot.com -colasmart.com -coldfunction.com -coldlar.com -colipu.com -colobu.com -color365.com -colorbird.com -colorfulltech.net -colorgg.com -coloros.com -coloros.net -colorv.com -colourfulchina.com -colourhs.com -colourlife.com -com-dy1-youku.com -com-h-bilibili.com -com-h-pptv.com -com-h-sina.com -com-i-youku.com -com-iqiyi.net -com-l-163.com -com-l-ifeng.com -com-l-iqiyi.com -com-l-qq.com -com-l-tudou.com -com-l-youku.com -com-ml-zyw.com -com-ok-baidu.com -com-ok-bilibili.com -com-ok-iqiyi.com -com-ok-qq.com -com-okzy.com -com-t-56.com -com-t-iqiyi.com -com-t-letv.com -com-v-sohu.com -com-v-tudou.com -com-www-163.com -com-youku.com -com-youku.net -com.fi -com.tv -com126.com -com21.com -com4loves.com -comac.cc -comba.xyz -combomen.com -combpm.com -combss.com -comebond.com -comefilm.com -comeken.com -comet.cc -comeyes.com -comflag.com -comfortzone.hk -comiai.com -comic123.net -comic520.com -comicdd.com -comicer.com -comicfans.net -comiclub.com -comicocn.com -comicst.com -comicv.com -comicyu.com -comidu.com -comiis.com -comingchina.com -comingspace.com -comlan.com -comlbs.com -commchina.net -comment.moe -communicatte.com -comocloud.net -companydns.com -compassedu.hk -compevt.com -comra.org -comsenz-service.com -comsenz.com -comseoer.com -comsharp.com -comsol.com -comvps.com -conchdesktop.com -concox.net -configuration.apple.com -configuration.apple.com.akadns.net -conflictmgmtassociates.com -conflux.fun -confuciusinstitute.net -cong9184.com -congm.in -congrongfund.com -congyicn.com -congzao.com -congzhi.com -connectivitycheck.gstatic.com -connector-systems.com -conoha.vip -conohavps.com -conpak.com.hk -conpersh.com -conshow.com -content.nike.com -contentchina.com -contentchina.net -contentstore.htcvive.com -contiez.com -conuo.com -convenice.com -convergemob.com -convertlab.com -conwos.com -conyedit.com -coo8.com -coocaa.com -coocaatv.com -coocare.com -cooch3d.com -coocox.org -coodir.com -coodoor.com -coodub.com -cooer.net -coofans.com -cooffee.net -coohua.com -cookbookchina.com -cookcai.com -cookie4you.com -cookietang.com -cool-admin.com -cool-de.com -cool80.com -coolact.net -coolaf.com -coolapk.com -coolapkmarket.com -coolbook.cc -coolbuy.com -coolchuan.com -coolcode.org -coolcode.tech -coolcoolcloud.com -cooldock.com -cooldu.com -cooleasy.net -coolecho.net -coolfd.com -coolgamebox.com -coolgua.net -coolguang.com -coolkit.cc -coolling.net -coolnull.com -coolook.org -coolool.com -coolpad.com -coolqi.com -coolrar.com -coolsc.net -coolsdream.com -coolsite360.com -coolsphoto.com -coolsrv.com -coolstar.xyz -coolwarmsy.com -coolwp.com -coolxap.com -coolyun.com -coolzou.com -cooo.us -coooz.com -coop100.com -coopb2b.com -coophone.com -coorain.net -coorfeon.com -cootek.com -cootekservice.com -coovbbs.com -coovee.com -coovee.net -coozhi.com -copyan.com -copyedu.com -copyfuture.com -copymanga.com -copymanga.org -corachic.com -coralsec.com -corebai.com -coreldrawchina.com -corp.google.com -corpautohome.com -corpease.net -corpize.com -corpus4u.org -cortexfx.bnpparibas.com -cos-show.com -cosco.com -coscon.com -coscoshipping.com -cose.space -cosedm.com -cosfund.com -coshelper.com -coshi.cc -coship.com -cosimcloud.com -cosinoplat.com -cosize.com -cosmoplat.com -cosoar.com -cosplay8.com -cosplayla.com -cosyjoy.com -coubei.com -counect.com -couns.com -couplefish.com -coupon996.com -couponmaster.store -coursegraph.com -covcec.com -coventrynv.com -coverweb.cc -covinda.com -covtv.com -cowarobot.com -cowgrrl.com -cowlevel.net -cowtransfer.com -coyuk.com -cp365.org -cp455.com -cpajia.com -cpass.com -cpatrk.net -cpbao.com -cpc.cc -cpcccac.com -cpcni.net -cpcpcp222.com -cpcpcp555.com -cpcw.com -cpcwe.com -cpdad.com -cpdaily.com -cpecc.net -cpeol.net -cpgzh.com -cphd68.com -cphoto.net -cphoto.org -cpiano.com -cpiaoju.com -cpiccdn.com -cpicsz.com -cpihualai.com -cpitsh.org -cpjltx.com -cplchain.com -cpnic.com -cpo.xyz -cpo2o.com -cpolar.com -cpolar.io -cpolive.com -cpooo.com -cpp-prog.com -cpp114.com -cppblog.com -cppccnews.com -cppcns.com -cppentry.com -cppfans.org -cppfoto.com -cpph.com -cppinfo.com -cpplay.com -cpplive.com -cpppc.org -cpppf.org -cppprog.com -cppwh.com -cps1688.com -cps800.com -cpsbeijing.org -cpsct.com -cpsenglish.com -cptae.com -cptxn.com -cpu668.com -cpubbs.com -cpvjob.com -cpxsxk.com -cpython.org -cq-wnl.com -cq315.org -cq3a.com -cq5135.com -cq6.com -cq6969.com -cqaaa.com -cqae.com -cqaso.com -cqbdfeng.com -cqbm2007.com -cqbnedu.com -cqbnrc.com -cqbntv.com -cqbyer.net -cqbys.com -cqc1.com -cqcaee.com -cqcatr.com -cqcb.com -cqcbank.com -cqccn.com -cqchzx.com -cqcimf.com -cqcklib.com -cqcoal.com -cqcp.net -cqcqcq.com -cqcsic.com -cqcsrc.com -cqcyls.com -cqdadi.com -cqdai.com -cqdailynews.com -cqddnap.com -cqddzx.com -cqdent.com -cqdting.com -cqdzw.com -cqedo.com -cqemme.com -cqfire.com -cqfuzhuang.com -cqfzb.org -cqgc.com -cqgz.com -cqh2o.com -cqhansa.com -cqhaoya.com -cqhcbk.com -cqhhr2.com -cqhimalayanky.com -cqhkcdns.com -cqhpoldi.com -cqhxgf.com -cqhxzb.com -cqhydraulic.com -cqiits.com -cqindex.com -cqivip.com -cqjbrc.com -cqjet.com -cqjiaz.com -cqjj.net -cqjjlsy.com -cqjjnet.com -cqjnw.org -cqjob.com -cqjsxx.com -cqjy.com -cqkdtui.com -cqkdtui1.com -cqkhg.com -cqkjwx.com -cqkqinfo.com -cqkundian.com -cqkx.com -cqkxzx.net -cqkytq.com -cqleba.com -cqliao.com -cqliving.com -cqlts.net -cqlyckj.com -cqmama.net -cqmas.com -cqmcu.com -cqmj.org -cqmjkjzx.com -cqmmgo.com -cqmt1069.com -cqmw.com -cqnc.cc -cqncnews.com -cqnews.net -cqnhn.com -cqnu0001.com -cqpa.org -cqpbx.com -cqph.com -cqpix.com -cqpost.com -cqqc3.com -cqqigao.com -cqqiyi.com -cqqnb.net -cqqp.com -cqqsl.com -cqqsyy.com -cqqzgrh.com -cqrc.net -cqrcb.com -cqshangceng.com -cqshenou.com -cqskl.com -cqslib.org -cqslsc.com -cqsms.net -cqsoft.org -cqsto.com -cqsxedu.com -cqsy.org -cqt8.com -cqtally.co -cqtally.com -cqtea.com -cqtransit.com -cqtresearch.com -cqttech.com -cquae.com -cquc.net -cqudp.com -cqvip.com -cqvip.vip -cqwangwo.com -cqwenbo.com -cqwin.com -cqwulong.net -cqxdfpr.com -cqxh120.com -cqxiehe.com -cqxingyun.com -cqxxzwj.com -cqxyfl.com -cqyc.net -cqyestar.com -cqyeze.com -cqyfgs.com -cqyouloft.com -cqyu.com -cqzhanguan.com -cqzhongxingyuan.com -cqzls.com -cqzq6.com -cqzww.com -cqzyx.net -cqzz.net -cr-expo.com -cr-nielsen.com -cr11gcsgd.com -cr11gee.com -cr173.com -cr175.com -cr18g.com -cr19gj.com -cr6868.com -crabchina.com -crabs.vip -crackersta.com -craftcontact.com -crandom.com -crazepony.com -crazy262.net -crazydyz.cc -crazyenglish.org -crazyflasher.com -crazyphper.com -crbeverage.com -crc.com.hk -crc81.com -crcapital.info -crcpp.org -crcrfsp.com -crct.com -cre.net -creatby.com -createcdigital.com -createpoint.qti.qualcomm.com -creati5.com -crec4.com -crec4mc.com -crecg.com -crecu.com -credit-cras.com -creditcn.com -creditsailing.com -creditxb.com -creke.net -creo-support.com -crewcn.com -crfchina.com -crfly.com -crfsdi.com -crgecent.com -crgy.com -cric.com -cric2009.com -cricbigdata.com -crifan.com -crifst.com -crimoon.net -crispstata.com -crjfw.com -crl.globalsign.net -crl.kaspersky.com -crl.pki.goog -crlcn.com -crlf0710.com -crlg.com -crm.cc -crm1001.com -crmch.com -crmclick.com -crmeb.com -crmeb.net -crmg-ms.com -crmgz.com -crmip.com -crmrj.net -crnds.com -crnews.net -crodigy.com -crohuiyi.com -crossmo.com -crossoverchina.com -crosswaycn.com -crowya.com -crpaas.com -crrcgc.cc -crs811.com -crsc.cc -crsky.com -crsn168.com -crxz.com -cryptape.com -cryptraco.com -crystalcg.com -crystaledu.com -cryuantafund.com -cryy120.com -cs-air.com -cs-ceo.com -cs-cjl.com -cs-show.com -cs0799.com -cs090.com -cs12333.com -cs27.com -cs2c.com -cs2ccloud.com -cs30.net -cs528.com -cs53.com -csadec.com -csair.com -csairdutyfree.com -csairholiday.com -csairshop.com -csapa.org -csaspx.com -csau.com -csbabao.com -csbdkj.com -csbidding.com -csbnj.net -csc108.com -csc86.com -cscan.co -cscatv.com -csccm.org -cscdf.org -cscec.com -cscec5b3.com -cscecst.com -cscectc.com -cscsf.com -cscyw.com -csdc.info -csdeshang.com -csdh.com -csdian.net -csdjy.com -csdn.com -csdn.net -csdn123.net -csdndoc.com -csdndx.com -csdndx.net -csdnxiazai.xyz -csdqp.com -csdxcw.com -csdyx.com -csea767.com -csebank.com -csflgg.com -csfqw.com -csftyy.com -csgm168.com -csgpc.org -csgwbn.com -csharpkit.com -csharpvideoluders.com -cshixi.com -cshnkj.com -cshu360.com -cshxdc.com -cshzw.com -csi.gstatic.com -csiaexpo.com -csic-711.com -csic-ljtech.com -csic612.com -csic6801.com -csic76.com -csic760.com -csiccq.com -csicmakers.com -csiea.net -csisseos.vip -csj309.vip -csjcs.com -csjwang.com -csjyzq.com -cskin.net -cskxjk.com -cslfans.com -cslgzj.com -cslleather.com -cslou.com -cslyrc.com -csmall.com -csmama.net -csmc-cloud.com -csmscon.com -csnbgsh.com -csnews.net -csnpr.com -cspda.net -cspengbo.com -cspiii.com -cspro.org -cspruc.com -cspxw.com -csqc.cc -csqnews.com -csrcare.com -csrcbank.com -csrcsc.com -csrda.com -csres.com -csrgm.com -csrme.com -csrpme.com -csrwindows.net -css-js.com -css.network -css6.com -css88.com -css88.vip -cssa-swansea.com -cssaaa.com -csser.me -cssf.com -cssf.net -cssforest.org -cssfz.com -cssg-ahi.com -cssgxmj.com -cssj.fun -csslcloud.net -cssmagic.net -cssmoban.com -cssmxx.com -cssplus.org -csspv.com -cssq33.com -cssqt.com -csstoday.net -csswgq.com -cssxt.com -cssyq.com -cssyzxx.com -cstat.apple.com -cstccloud.org -cstcloud.net -cstea.org -cstech.ltd -csteelnews.com -cstimer.net -csto.com -cstong.net -cstriker1407.info -csuboy.com -csuedu.com -csundec.com -csvclub.org -csvsc.com -csvw.com -csw18.com -csweigou.com -cswsadlab.com -csxcdj.com -csxdf.com -csxingfutemple.org -csxlj.com -csxnews.com -csxsjc.com -csxtedu.com -csxww.com -csyangchen.com -csyestar.com -csyeye.com -csytv.com -cszb556.com -cszexin.com -cszit.com -cszsjy.com -cszx.com -cszybdf.com -cszykt.com -cszywl.net -cszzjc.com -cszzw.com -ct-cdm.com -ct-laser.com -ct10000.com -ct108.com -ct597.com -ctaca.com -ctags.net -ctans.com -ctaoci.com -ctaweb.org -ctb50.com -ctc100.com -ctcdns.com -ctcefive.com -ctcmo.com -ctcnn.com -ctcnpa.com -ctcontents.com -ctcwri.org -ctdc-itshare.org -ctdcn.com -ctdisk.com -ctdns.net -ctdsb.com -ctdsb.net -cteaw.com -ctecdcs.com -ctex.org -ctfgjp.vip -ctfile.com -ctfile.net -ctflife.com -ctfmall.com -ctfo.com -ctfund.com -ctghealthy.com -ctghr.com -ctguqmx.com -cthnet.com -cthuwork.com -cthuwork.net -cthy.com -ctiforum.com -ctiku.com -ctime.com -ctisd.com -ctjin.com -ctjsoft.com -ctlcdn.com -ctldl.windowsupdate.com -ctmcdn.net -ctmon.com -ctn1986.com -ctnz.net -cto800.com -ctobsnssdk.com -ctocio.com -ctoclub.com -ctohome.com -ctoutiao.com -ctquan.com -ctrip-lvyou.com -ctrip-ttd.hk -ctrip.co.id -ctrip.co.kr -ctrip.com -ctrip.my -ctrip.sg -ctripa.com -ctripbiz.com -ctripbuy.hk -ctripcorp.com -ctripgslb.com -ctripins.com -ctrmi.com -ctrtb.com -ctsbw.com -ctsec.com -ctsho.com -ctsoo.com -ctsscs.com -ctssr.com -ctsto.com -ctszh.com -cttip.org -cttq.com -cttsd.com -cttv.co -ctule.com -ctvpost.com -ctvwx.com -ctxyw.com -ctycdn.com -ctyo.com -ctzrnet.com -cu-air.com -cu321.com -cuaa.net -cuan.la -cuantianhou.net -cuav.net -cubead.com -cubedat.com -cubejoy.com -cubie.cc -cucdc.com -cuchost.com -cuctv.com -cudaojia.com -cuebzzy.com -cuelog.com -cufe-ifc.org -cufe.cc -cufeyk.com -cufou.com -cug2313.com -cugstore.com -cuicc.com -cuihu100.com -cuihuan.net -cuijunwei.com -cuimm.com -cuiniaoedu.com -cuiniuhui.com -cuipengfei.me -cuipixiong.com -cuiqingcai.com -cuiqingcn.com -cuirushi.com -cuishuai.cc -cuiuc.com -cuiweijuxing.com -cuixx.com -cuiyongjian.com -cuizl.com -cuketest.com -cul-studies.com -culaiwan.com -cultofslavery.com -cumtenn.com -cumulon.com -cun58.com -cunan.com -cuncun8.com -cuncunle.com -cuncx.com -cunman.com -cunnar.com -cunyoulu.com -cuobiezi.net -cuour-edu.com -cuour.com -cuour.org -cupdata.com -cupdns.com -cupfox.com -cuphr.com -cupinn.com -cuplayer.com -cupoden.com -cureedit.com -curlc.com -curryhuang.com -cusdvs.net -custeel.com -customizemytumblr.com -cut35.com -cutecomm.com -cuteng.com -cutercounter.com -cuteximi.com -cutowallpaper.com -cutt.com -cutv.com -cuuhn.com -cuyoo.com -cuzz.site -cvchina.info -cvchome.com -cvcri.com -cvicse.com -cvicseks.com -cvmart.net -cvnad.com -cvonet.com -cvp-platform.com -cvrobot.net -cvte.com -cw.pub -cw100.com -cwan.com -cwbpsi.com -cwddd.com -cwdma.org -cwebgame.com -cwebgl.com -cwems.com -cwestc.com -cwmining.com -cwq.com -cwqu.com -cwroom.com -cwyan.com -cwziyouren.com -cx312.com -cx368.com -cx580.com -cx930.com -cx930.net -cxacg.com -cxc233.com -cxcc.me -cxcyds.com -cxdq.com -cxfuwu.com -cxgame.net -cxh99.com -cxhl365.net -cxhr.com -cximg.com -cxkjjy.com -cxmld.com -cxmms.com -cxmt.com -cxmtc.net -cxqb.net -cxsw3d.com -cxsyjy.com -cxta.com -cxthhhhh.com -cxtuku.com -cxtxt.com -cxw.com -cxwl.com -cxwt103.com -cxwt104.com -cxwt105.com -cxwt106.com -cxwt113.com -cxwz.org -cxxjs.com -cxxwnews.com -cxy61.com -cxy7.com -cxybl.com -cxyd.net -cxyl.org -cxylfc.com -cxymsg.com -cxyob.com -cxytiandi.com -cxyxwl.com -cxyym.com -cxz.com -cxz3d.com -cxzg.com -cxzuqiu.com -cxzw.com -cxzww.com -cy-cdn.com -cy-email.com -cy.com -cy12301.com -cy1990.com -cy2009.com -cy52.com -cy52.org -cy580.com -cy865.com -cy88.com -cy887.com -cy899.com -cyagen.com -cyb-bot.com -cyb-cie.com -cyb520.com -cyb800.com -cyberway-china.net -cybtc.com -cybtc.info -cybtc.net -cycares.com -cychaiqian.com -cyclingchina.net -cyclone-robotics.com -cycnet.com -cycoi.com -cycoo.com -cycyuan.com -cydf.com -cydia.love -cydiakk.com -cydiami.com -cydow.com -cydp5.com -cyedu.org -cyegushi.com -cyepai.com -cyfeng.com -cyfengchao.com -cygglm.com -cyhd.net -cyhm.com -cyhone.com -cyht168.com -cyhx98.com -cyidc.cc -cyikao.com -cyjcloud.com -cyjn.net -cyjnsy.com -cyjzzd.com -cyk-cable.com -cylong.com -cymzc.com -cynee.net -cynovan.com -cyol.com -cyol.net -cyou-inc.com -cyoupic.com -cypatent.com -cypmedia.com -cyprestar.com -cyqyzx.com -cyruc.com -cyslbm.com -cysq.com -cyss19.com -cysua.com -cytcard.com -cytcm.com -cyts.com -cytsls.com -cytstibet.com -cyttc.org -cyudun.net -cyuew.com -cyuyan100.com -cywetc.com -cyxqd.com -cyy18.com -cyyizuo.com -cyysjm.com -cyyz.org -cyyzws.com -cyzm.net -cz-hffm.com -cz-toshiba.com -cz-yk.com -cz.cc -cz2sc.com -cz365.com -cz8.com -cz89.com -cz910.com -czainuo.com -czb365.com -czbanbantong.com -czbank.com -czbh.com -czbq.net -czbtv.com -czbx18.com -czcarbon.com -czcits.com -czcqly.com -czctech.com -czcyme.com -czdrbz.com -czds.net -czedu.com -czepb.com -czfcdj.com -czfcw.com -czfdc.com -czfesco-mg.com -czfrd.com -czggsj.com -czgjj.com -czgjj.net -czgongzuo.com -czie.net -czifi.org -czitc.com -czjake.com -czjdu.com -czjdxl.com -czjpw.com -czjsy.com -czkbdq.net -czkingdee.com -czmarry.com -cznewcom.com -czodb.com -czongyi.com -czopen.com -czpoly.com -czqsyyey.com -czrj.com -czrxw.com -czry888.com -czshyhg.com -czsljky.com -czsrc.com -czssx.com -cztour.com -cztv.com -cztv.tv -cztvcloud.com -czur.com -czvv.com -czvv.net -czwlzx.com -czwsg5.com -czwyz.com -czxixi.com -czxsss.com -czxy.com -czyhq.com -czyjgd.com -czyxba.com -czzcm.com -czzsw.com -czzy-edu.com -d-ctrip.com -d-heaven.com -d-j.me -d-meng.com -d-prototype.com -d.cg -d03jd.com -d0evi1.com -d1222.com -d17.cc -d1cm.com -d1com.com -d1cy.com -d1ev.com -d1fm.com -d1h.net -d1lx.com -d1net.com -d1sm.com -d1sm.net -d1tele.com -d1tv.com -d1xn.com -d1xtw.com -d1xz.net -d1ye.com -d20.net -d21365.com -d2fan.com -d2film.com -d2kdi2ss.com -d2scdn.com -d2shost.com -d2zw.com -d3ch.com -d3cn.net -d3dweb.com -d3f.com -d3iz9md.com -d3skg.com -d3tt.com -d3zone.com -d4000.com -d5.nz -d586.com -d5h.net -d5power.com -d5wx.com -d5zz.com -d65d6.com -d77777777.com -d7baike.net -d7ol.com -d7vg.com -d8th.com -d8tv.com -da-qian.com -da-quan.net -da88.net -daanbar.com -daba.com -dabaicai.com -dabaicai.org -dabaicai.pw -dabaicai.shop -dabaigongju.com -daban001.com -dabangm.com -dabangp.com -dabangq.com -dabao123.com -dabaoku.com -dabaoku.net -dabieshu.com -dabin69.com -dabingseo.com -dabjy.com -dabo8.com -daboluo.net -dabusi.com -dacai.com -dacankao.com -dacankao.net -dachanet.com -dachenglaw.com -dachengnet.com -dachuizichan.com -dachuw.com -dachuw.net -dadaabc.com -dadaabcc.com -dadabew.com -dadabus.com -dadagame.com -dadagem.xyz -dadaizi.com -dadajiasu.com -dadajuan.com -dadakan.com -dadaojiayuan.com -dadatu.co -dadatu5.com -dadatutv.com -dadayou.com -dadazw.com -dadclab.com -daddymami.net -dadetong.com -dadeyu.com -dadianstudio.com -dadigho.com -dadighost.com -dadijilu.com -dadipedia.com -dadiwang.com -dadizq.com -dadou.com -dadoubao.com -dadukou.net -dadunet.com -daf-rs.com -dafa888-0.com -dafaji.com -dafakuaisantouzhupingtai.com -dafang24.com -dafangya.com -dafanqie.net -dafanshu.com -dafaqipaizx.com -dafayu.com -dafengning.com -dafhr.com -dafork.com -dafuhao-ol.com -dagangcheng.com -dagaqi.com -dagongcredit.com -dagongnet.com -daguangnews.com -dagumanhua.net -daguu.com -daguzhe.com -dahainan.com -dahaiyang.com -dahanghaiol.com -dahangzhou.com -dahanwl.com -dahanyu.com -daheapp.com -dahecc.com -dahecube.com -dahei.com -daheng-image.com -daheng-imaging.com -daheng-imavision.com -dahengit.com -dahepiao.com -daheshui.com -dahongba.net -dahouduan.com -dahua8.com -dahuaab.com -dahuangmei.com -dahuatech.cc -dahuatech.com -dahuawang.com -dahuitu.net -dahuoji.biz -dai35.com -dai361.com -dai911.com -daibi.com -daibini.com -daichanger.com -daichuqu.com -daicuo.cc -daicuo.co -daicuo.net -daicuo.vip -daicuo.wang -daidaitong.com -daidaitv.com -daidongxi.com -daijinquanaliyun.com -daijun.com -daikela.com -daikuan.com -daikuane.com -daikuanfanli.com -daili666.com -daili666.net -dailianqun.com -dailiantong.com -dailianzj.com -dailiba.com -dailibu.com -dailijizhang.cc -dailnkm.com -dailuopan.com -dailyeconomic.com -dailyqd.com -daimabiji.com -daimadog.com -daimafans.com -daimajia.com -daimajiaoliu.com -daimajiayuan.com -daimami.com -daimasucai.com -daimg.com -daimiyun.com -daishangqian.com -daishu.com -daishujiankang.com -daishutijian.com -daiwoqu.com -daixiaobao.com -daixiaomi.com -daixiaorui.com -daixingmo.com -daiyanbao.com -daiyanmama.com -daiyoubang.com -daiyuxia.com -daizhuzai.com -daizitouxiang.com -dajiabao.com -dajiachou.com -dajiadaohang.com -dajiadu8.com -dajialaikan.com -dajialawyer.com -dajianet.com -dajiangcp.com -dajiangsai.org -dajiangtai.com -dajianhui.com -dajiaochongmanhua.com -dajiashequ.com -dajiashuo.com -dajiatou.com -dajiazhao.com -dajiazhongyi.com -dajie.com -dajieimg.com -dajiezhu.com -dajixie.com -dajkd.com -dajuntech.com -dajuyuanyanchu.com -daka.app -daka.net -daka5837.com -dakahr.com -dakamao8.com -dakao8.com -dakao8.net -dakaruanwen.com -dakawm.cc -dakawm.net -dakayi.cc -dakele.com -dalaba.com -dalanxing.com -dali163.com -dalianair-china.com -dalianiso.com -daling.com -dalinggong.com -dalings.com -dalipan.com -dalongkeji.com -dalongyun.com -daluma.com -dalunews.com -daluo.com -daluwang.net -damailicai.com -damatu1.com -damddos.com -dameisheng.com -dameiweb.com -dameiyunduan.com -dameng.com -damengxiang.me -damgvig.bar -damingweb.com -damndigital.com -damnwallpapers.com -damotea.com -damoyang.com -damuchong.com -damuzzz.com -dan665.com -danaicha.com -danale.com -danbaise.com -dance365.com -dancechina.club -dancf.com -danche18.com -dancihu.com -dancingcg.com -dandanjiang.tv -dandanplay.com -dandanplay.net -dandantang.com -dandanz.com -dandinghuayi.com -dandongbank.com -danews.cc -dang-jian.com -dang3.com -dangan168.com -dangaoss.com -dangbei.com -dangbei.net -dangbeiprojector.com -dangcdn.com -dangdang.com -danghongyun.com -dangjian.com -dangjianwang.com -dangpu.com -dangran.me -dangtianle.com -dangwan.com -dangzhi.com -dangzhi.net -danhua.org -danhuaer.com -danhw.com -daniao.org -daniate.com -daningcenter.com -daningdaning.com -daniu.io -daniuit.com -daniujiaoyu.com -danji6.com -danji8.com -danjiali.com -danjicn.com -danjuanapp.com -danjuanfunds.com -danke.com -dankegongyu.com -dankexiaoyuan.com -danlan.org -danlu.net -danm8.com -danmei.la -danming-ic.com -danmo.com -danmu.com -dannysite.com -danotest.com -danpin.com -danqi.com -danqingshaonian.com -danqoo.com -danrenzheng.com -danseshu.com -danteng.me -dantuvc.com -danxia.com -danxin.net -danyang.com -danzhaowang.com -dao345.com -dao42.com -dao50.com -dao6.net -daoapp.io -daoapp.me -daocheng.net -daochu66.com -daocloud.io -daocloudapp.com -daodao.com -daodaojizhang.com -daodaoliang.com -daodian100.com -daodianfu.com -daododo.com -daoduoduo.com -daofengdj.com -daofenggame.com -daofengyx.com -daogeziyuan.com -daogoubang.com -daoguo.com -daohang4.com -daohang88.com -daohangtx.com -daohui.net -daoisms.org -daojia.com -daokers.com -daokeyuedu.com -daokoudai.com -daokoujinrong.com -daokouren.org -daomengad.com -daomengren.com -daomuxiaoshuo.com -daonazhuce.com -daonchina.com -daoqin.net -daoqm.com -daoscript.org -daota.info -daotin.com -daotudashi.com -daovoice.io -daoweijia.com -daoxiangcun.com -daoxila.com -daoxila.net -daoyouz.com -daoyu8.com -daozhao.com -dapaizixun.com -dapan.com -dapei.cc -dapengjiaoyu.com -dapenti.com -dapiniu.com -dapmax.com -dappdiscover.com -dapu.com -daqi.com -daqianduan.com -daqiangpco.com -daqids.com -daqihui.com -daqiso.com -daqsoft.com -daquan.com -darczpw.com -darentang.org -dariyu.com -darkhat.xyz -darkmi.com -darmao.com -darongcheng.com -darryring.com -dartchina.com -dartou.com -daruan.com -darwinlearns.com -dashabi6.com -dashangcloud.com -dashanghaizhuce.com -dashangmall.com -dashangu.com -dashedm.com -dashen520.com -dashengji.com -dashenglaile.com -dashengpan.com -dashenquan.com -dashentv.com -dashenxiaoshuo.com -dashet.com -dasheyuan.com -dashgame.com -dashi.com -dashikou.com -dashitech.com -dashiyou.com -dashoucloud.com -dashuju123.com -dashuye.com -dasougu.com -dasoujia.com -dassm.com -dasung.com -dasungtech.com -dat8.cc -data380.com -data985.com -datacaciques.com -datadragon.net -dataesb.com -dataeye.com -datagear.tech -datagrand.com -dataie.com -dataman-inc.com -datang.com -datang.net -datangweishi.com -datangzww.com -dataodu.com -dataoke.com -dataprajna.net -datarelab.com -datarj.com -datasecurity.htcsense.com -datasheet5.com -datasl.com -datasoldier.net -datastoragesummit.com -datatang.com -datathinking.com -datathinking.net -datatist.com -dataunion.net -datayes.com -datazt.com -datebao.com -datessr.com -datia-inspect.com -datian-cn.com -datianmen.com -datiegun.com -datongtaxi.com -datouwang.com -datouxiaw.com -datuc.com -davdian.com -davinfo.com -dawaiyu.com -dawandao.com -dawaner.net -dawanjiakaihu.com -daweibro.com -daweisoft.com -daweixinke.com -dawenxue.net -dawenxue.org -dawndiy.com -dawnlab.me -dawuge.com -dawuxia.net -dawx.com -dawx.net -daxi.com -daxia.com -daxia520.com -daxiaamu.com -daxiangdaili.com -daxianghuyu.com -daxiangqun.net -daxiit.com -daxiyu.com -daxueask.com -daxuecn.com -daxueit.com -daxuepc.com -daxueshengqiandai.com -daxueshi.com -daxuesou.com -daxuewa.com -daxuewang.com -daxuexuanze.com -dayaguqin.com -dayanmei.com -dayanzai.me -dayday.plus -daydayup123.com -dayee.com -dayhao.com -dayhr.com -dayichang.com -dayifund.org -dayila.net -dayima.com -dayin.com -dayin.la -dayinhu.com -dayinjiqudong.com -dayinpai.com -dayinpiano.com -dayitong.net -dayiyu.com -dayong.name -dayoo.com -dayou123.com -dayoufeng.com -dayrui.com -daytokens.com -dayu-valve.com -dayu.com -dayuad.com -dayue8.com -dayugame.net -dayugslb.com -dayukeji.com -dayuntongzhou.com -dayup.org -dazahui123.com -dazhaiwang.com -dazhan123.com -dazhangfang.com -dazhaoad.com -dazhaopeibang.com -dazhe114.com -dazhe5.com -dazhenzimiao.com -dazhewa.com -dazhongbanben.com -dazhongemiao.com -dazhonghr.com -dazhoudz8.com -dazhoushan.com -dazhuangwang.com -dazhuanlan.com -dazibo.com -dazidian.net -dazijia.com -dazpin.com -dazu666.com -dazui.com -db-cache.com -db-nw.com -db2car.com -db2china.net -db9db.com -dbank.com -dbankcdn.com -dbankcloud.asia -dbankcloud.com -dbankcloud.eu -dbankedge.net -dbaxiaoyu.com -dbbqb.com -dbccv.com -dbcdh.com -dbcsq.com -dbcxz1.com -dbcxz1.net -dbdna.com -dbfansub.com -dbfen.com -dbgeek.org -dbh123.net -dblgf.com -dbliu.com -dblwww.com -dbmailserver.com -dbmall.com -dbmeinv.com -dbqf.xyz -dbscar.com -dbshop.net -dbt-coin.com -dbyb.org -dbytwl.com -dbzgia.com -dbzyz.com -dc-cn.com -dcb123.com -dcdapp.com -dcement.com -dcetax.com -dcharm.com -dchpv.com -dcic-china.com -dcits.com -dcjdj.com -dcjianghu.com -dcjyw.com -dcloud.io -dcloudlive.com -dcloudstc.com -dcmagcn.com -dcsapi.com -dcsdn.com -dcsjw.com -dcsme.org -dctxf.com -dcv.so -dcwj168.com -dcxnews.com -dczou.com -dd-cdn.origin-apple.com.akadns.net -dd-img.com -dd-kan.com -dd-vending.com -dd.net -dd2007.com -dd321.com -dd373.com -dd4.com -dd6300.fun -dd66778899.com -dd7q.com -dd8828.com -ddbig.com -ddbiquge.cc -ddbiquge.com -ddchong.com -ddcode.net -ddcsh.com -ddd-china.com -dddazhe.com -dddccs8p.com -dddso.com -dddwan.com -ddepin.com -ddfans.com -ddfchina.com -ddgg123.com -ddgjjj.com -ddiaas.com -ddianle.com -ddianshang.com -ddimg.mobi -ddimg.net -dding.net -ddjjzz.com -ddjk.com -ddk-alink.com -ddkefu.com -ddkids.com -ddkt365.com -ddkwxd.com -ddky.com -ddle.cc -ddlequ.com -ddlives.com -ddmap.com -ddmapimg.com -ddmeishi.com -ddmer.com -ddnddn.com -ddnode.com -ddnsto.com -ddong.com -ddooo.com -ddos-defend.com -ddos.com -ddos2naive.com -ddosc.com -ddosendns.com -ddoswafcdn.xyz -ddove.com -ddpa.com -ddpai.com -ddport.com -ddqcw.com -ddr.kim -ddsaas.com -ddske.com -ddsoucai.com -ddspsc.com -ddstarapp.com -ddsy.com -ddtaba.com -ddtugame.com -ddtui.com -ddun.com -ddurl.to -dduser.mobi -dduwork.com -ddweilai.com -ddwzh.com -ddxia.com -ddxq.mobi -ddxs.cc -ddyun.com -ddyun123.com -ddyvip.com -ddzhj.com -ddztb.com -ddztv.com -ddzuqin.com -ddzzd.com -de0.cc -de116.com -de123.net -de1919.com -de518.com -deaconhousewuxi.com -deadnine.com -deahu.com -dealsmake.com -deansys.com -dear520dear.com -dearb.me -dearda.com -dearedu.com -dearisland.com -dearloc.com -dearprinter.com -deartree.com -deathearth.com -debao.com -debao.me -debo-info.com -debug.moe -debugdump.com -debuggap.com -debugger.wiki -debugo.com -debugtalk.com -debuycn.com -decard.com -decentcapital.com -decerp.cc -dechong.site -dechua.com -decorcn.com -decwhy.com -dede168.com -dede58.com -dedeadmin.com -dedecms51.com -dedecmsplus.com -dededao.com -dedeeims.com -dedejs.com -dedemao.com -dedesos.com -dedeyun.com -dedezhuji.com -deehai.com -deemob.com -deepai.com -deepano.com -deepba.com -deepbluenetwork.com -deepcloudsdp.com -deepdevelop.com -deepepg.com -deepermobile.com -deepfun.net -deepin.asia -deepin.com -deepin.io -deepin.org -deepinghost.com -deepinmind.com -deepleaper.com -deeplearn.me -deepoon.com -deepsheet.ltd -deepsheet.net -deepvision.ai -deepzz.com -deerchao.net -deerma.com -defcoding.com -defectink.com -deheheng.com -deheng.com -dehsm.com -dehua.net -dehuaca.com -deifei.com -deifgs.com -deikuo.com -dejieshi.com -dekeego.com -dektw.com -delai.me -delanauto.com -deli-tools.com -delib2b.com -delibao.com -delicloud.com -delightful.vip -delikaixi.com -delinklab.com -delishi.com -deliwenku.com -deliworld.com -delixi-electric.com -dell027.com -dellemc-solution.com -dellwh.com -delunyk.com -demage.com -demaxiya.com -demgs.com -demix.cc -demlution.com -demo8.com -democome.com -demodashi.com -demogic.com -demohour.com -demopu.com -demoso.net -demososo.com -denganliang.com -dengb.com -dengcuo.com -dengfeilong.com -denghao.org -denghaoxuan.com -denghuo.com -dengkanwen.com -dengliye.com -denglu.cc -dengpeng.me -dengshiyuanyi.com -dengta120.com -dengtacj.com -dengtadaka.com -dengxiaolong.com -dengxiaopingnet.com -dengzhr.com -denocn.org -deosin.com -dep-star.com -dephir.com -depin.com -deppon.com -deppxp.net -deqingbank.com -deqinglaw.com -derekchou.com -derenbs.com -dermau.com -derwer.com -derzh.com -des8.com -desaysv.com -deshui.wang -design521.com -designboard.cc -designsketchskill.com -designuuu.com -desk-site.com -desk9.com -deskcar.com -deskcity.com -deskcity.org -deskier.com -desktopcal.com -desktopqa.com -desktx.com -deskwc.com -despiertocfilms.com -destoon.com -detian-chem.com -detu.com -detuyun.com -dev-dh.com -dev798.com -dev996.com -devask.net -devclub.cc -develenv.com -developer.dji.com -developer.htcvive.com -developer.microsoft.com -developer.vive.com -devemi.com -devework.com -devexception.com -devexel-tech.com -devexel.com -devexpresscn.com -devio.org -devkang.com -devopen.club -devops-master.com -devpss.com -devqinwei.com -devsiki.com -devtang.com -devzeng.com -devzhang.com -dewmobile.net -dewu.com -dewumall.com -dexcoder.com -dexian.mobi -dexingrv.com -dexinsg.com -dexuee.com -deyang5.com -deyatech.com -deyayk.com -deyi.com -deyi.net -deyijijin.org -deyioo.com -deyiso.com -deyoulife.com -deyun.fun -deyunxiangsheng.com -deyurumen.com -dezhi.com -dezhong365.com -dezhoudaily.com -dezhoujiancai.com -dezhouqh.com -df77.com -df81.com -df9377.com -dfafei.com -dfbgv.com -dfcfw.com -dfcx-bj.com -dfdaily.com -dfdfoy.bar -dfdjy.net -dfedu.com -dfgzqc.com -dfham.com -dfhdw.com -dfhon.com -dfhtjn.com -dfkcgs.com -dfkhgj.com -dfmc.com -dfmcastrol.com -dfmingya.com -dfpk.com -dfrcb.com -dfs800.com -dfshurufa.com -dfshw.com -dfsjr.com -dfsrcw.com -dfss-club.com -dfstw.com -dfsyjm.com -dftoutiao.com -dftq.net -dfv5.net -dfxq.com -dfxwdc.com -dfyanyi.com -dfyapp.com -dfyl-luxgen.com -dfyoo.com -dfysw.net -dfyuan.com -dfyydl.com -dfyzx.com -dfzmzyc.com -dg-car.net -dg-hanxin.com -dg-huixin.com -dg-mall.com -dg11185.com -dg114.com -dg121.com -dgchangan.com -dgd2018.com -dgddh.xyz -dgdxs.com -dgg.net -dggdf.com -dggdk.com -dgggs.com -dggjqw.com -dggkj.com -dggvip.net -dghfw.com -dghh888.com -dghqmotor.com -dginfo.com -dgjiuqi.com -dgjoy.co -dgjs123.com -dgjyw.com -dgksxx.com -dglpool.com -dgmama.net -dgmaoken.com -dgn.cc -dgnxjx.com -dgod.net -dgq2018.com -dgqjj.com -dgrbcj.com -dgsbtjx.com -dgsgly.com -dgsltx.com -dgsme.org -dgssmy.com -dgt-factory.com -dgtle.com -dgtpcj.com -dgtuoyue.com -dgwap.com -dgwtrl.com -dgxue.com -dgxxzs.com -dgyejia.com -dgygpx.com -dgykz.com -dgyldjy.com -dgym519.com -dgyuanyi.com -dgzhihongjx.com -dgzhisen.com -dgzhuorui.com -dgzj.com -dgzsgjg.com -dgzz1.com -dgzzm.com -dh.cx -dh01.com -dh0580.com -dh5idnf.com -dh7373.com -dh7999.com -dh818.com -dh975.com -dh978.com -dhb168.com -dhcc.wang -dhhanfeng.com -dhhqfw.com -dhifi.com -dhimavision.com -dhjt.com -dhkq120.com -dhkqmz.com -dhkqyy.com -dhmeri.com -dhq898.com -dhqdb.com -dhqtech.com -dhrcbank.com -dhrest.com -dht5867.com -dhtyey.com -dhwooden.com -dhy85888.com -dhyjaqa.com -dhzw.org -di3fang.com -di3fang.vip -diablohu.com -diaidi.com -diaigame.com -diamondfsd.com -dian-ai.com -dian-ying.com -dian.io -dian.so -dian123.com -dian321.com -dian5.com -diananjia.com -dianapp.com -dianbank.com -dianbo.org -dianbobao.com -dianbook.cc -dianbucuo.com -dianchacha.com -dianclan.com -diandainfo.com -diandanbao.com -diandao.org -diandian.com -diandianchu.com -diandianshu.com -diandianwaimai.com -diandianxs.com -diandianyou.com -diandianys.com -diandianzhe.com -diandianzu.com -diandong.com -diandongche.biz -dianfengcms.com -dianfuji.com -diangan.org -diangon.com -diangong8.com -diangongwu.com -dianhen.com -dianhi.com -dianhong.com -dianhou.com -dianhua110.com -dianji007.com -dianjianggame.com -dianjiliuliang.com -dianjin123.com -dianjinghu.com -dianjingzhe.com -dianjishu.com -diankeji.com -diankeshequ.com -dianlancg.com -dianler.com -dianli.com -dianli08.com -dianliang8.com -dianliaoapp.com -dianlujitao.com -dianlut.com -dianm.cc -dianmi.net -dianmiaoshou.com -dianmoney.com -diannaoban.com -diannaodian.com -diannaokepu.com -diannaoxianka.com -diannaozs.com -dianniugu.com -dianopen.com -dianou.com -dianpifa.com -dianping.com -dianpingba.com -dianpu.ai -dianqiweixiu.net -dianqizazhi.com -dianranart.com -dianrong.com -dianru.com -dianru.net -diansan.com -dianshang.com -dianshanghy.com -dianshangyi.com -dianshi.com -dianshihome.com -dianshijia.com -dianshimo.com -diantansuo.com -diantoushi.com -diantui.net -dianview.com -dianwannan.com -dianwoba.com -dianwoda.com -dianwoyou.com -dianwuque.com -dianxin.net -dianxinnews.com -dianxinos.com -dianxs.com -dianyingbars.com -dianyingjie.com -dianyingshow.com -dianyingwenxue.com -dianyinjidiao.com -dianyong123.com -dianyongqi.com -dianyuan.com -dianyuanic.net -dianyue8.com -dianyuesh.com -dianzhanggui.net -dianzhangzhipin.com -dianzheli.com -dianzhentan.com -dianzhi.com -dianzhu.net -dianziaihaozhe.com -dianzis.com -dianziw.com -dianzixuexi.com -diaoao.com -diaoben.com -diaochapai.com -diaochapai.net -diaocn.com -diaoding.biz -diaojiang.com -diaokeji.net -diaorui.net -diaosi.net -diaosiweb.net -diaosu.so -diaosu9.com -diaosu98.com -diaosunet.com -diaox2.com -diaoy.com -diaoyan360.com -diaoyanbao.com -diaoyou.com -diaoyoupai.com -diaoyu.com -diaoyu123.com -diaoyu365.com -diaoyubo.com -diaoyula.com -diaoyuok.com -diaoyur.com -diaoyuren.com -diaoyuwang.com -diaoyuweng.com -diaoyuwo.com -diary365.net -diaxue.com -dib66.com -dibaotong.com -dibcn.com -diboot.com -dic123.com -dichan.com -dichanlao.com -dichanren.com -dictall.com -dida110.com -dida365.com -didacar.com -didachuxing.com -didao.com -didapinche.com -didatravel.com -didaxing.com -didialift.com -didiapp.com -didichuxing.com -dididadidi.com -dididapiao.com -dididawo.com -didiling.com -didipay.com -didiqiche.com -didispace.com -didistatic.com -didiwl.com -didiwuxian.com -didixk.com -didiyun.com -didiyunapi.com -didown.com -didu86.com -diducoder.com -diebaosoft.com -diebian.net -dieclock.com -diecuo.com -diediao.com -diediao123.com -diemameishi.com -diemoe.net -dierkezhan.com -diershoubing.com -difanapp.com -digbo.org -digcredit.com -digforfire.net -digforfire.org -digi-uniclick.net -digi-wo.com -digirepub.com -digisky.com -digitalchina.com -digitalcq.com -digitaling.com -digitalwuhan.com -digitalwuhan.net -digitlink.net -digitser.net -digiwin.com -digiwork.com -digod.com -digpage.com -digu.com -digu365.com -digua.com -diguage.com -diguan.wang -diguandai.wang -diguff.com -diguobbs.com -digwow.net -dihaoq.com -dihuikj.com -dijingchao.com -dijinlianmeng.com -dijitalevren.com -dijiu.com -dijiuban.com -diketattoo.com -dikudu.com -dili360.com -dili365.com -dilidili.tv -dililitv.cc -dililitv.com -dim0.com -dimeng.net -dimensionalzone.com -dimpurr.com -dinais.com -dindin.com -dingdanggj.com -dingdangsheji.com -dingdean.com -dingdian.la -dingdianku.com -dingdiann.com -dingdiansk.com -dingdianxs.com -dingdianzw.com -dingding.com -dingding.xin -dingding2014.com -dingdingdoctor.com -dingdingkaike.com -dingdone.com -dingdongcloud.com -dingdongqb.com -dingfang123.com -dinghaiec.com -dinghuaren.com -dinghuihuojia.com -dinghuoche.com -dingip.com -dingkeji.com -dinglc.com -dinglia.com -dingliss.com -dingniu8.com -dingniugu.com -dingqidong.com -dingsheng.com -dingshengjishu.com -dingshifa.com -dingshijixie.com -dingso.com -dingtalent.com -dingtalk.com -dingtalkapps.com -dingtangzqx.com -dingteam.com -dingxiang-inc.com -dingxin66.com -dingxin99.com -dingxinhui.com -dingxuewen.com -dingyantec.com -dingyiba.com -dingyueads.com -dingyunad.com -dingzepeizi.com -diningcity.asia -dinzd.com -dioenglish.com -dionly.com -diougens.net -dipaispa.com -dipan.com -dipephoto.com -dipont.com -dipplum.com -diqi.net -diqi.sh -diqibu.com -diqiujiayuan.com -diqiuw.com -diqu114.com -diqua.com -dir001.com -dircha.com -directui.com -discoversources.com -discuz.chat -discuz.com -discuz.net -discuz.org -discuzfans.net -discuzlab.com -dishen.com -dishuizhijia.com -diskgenius.com -disksing.com -dismall.com -disneybox.com -ditan360.com -ditan369.com -dithub.com -ditian-tech.com -ditiewang.net -ditiezu.com -ditiezu.net -ditu.live.com -ditu100.net -ditu6.com -dituge.com -dituhui.com -dituwuyou.com -diudou.com -diugai.com -diushouji.com -div.io -divcss5.com -divh5.com -diwork.com -dixiao.org -dixintong.com -dixueyazhijia.com -diybcq.com -diybeta.com -diybuy.net -diycode.cc -diydoutu.com -diyer.so -diygogogo.com -diygw.com -diyhi.com -diyicai.com -diyidan.com -diyidan.net -diyifangdai.com -diyifanwen.com -diyifanwen.net -diyihuifu.com -diyijuzi.com -diyinews.com -diyippt.com -diyiredian.com -diyishijian.com -diyitech.com -diyitui.com -diyiwl.wang -diyixiazai.com -diyixitong.com -diyiyou.com -diyiyunshi.com -diyiziti.com -diyju.com -diymianmo.com -diynova.com -diypda.com -diyring.cc -diytrade.com -diyvm.com -diywoju.com -diyworld.com -diywz.com -diyyh.com -diyzhuye.com -dizhi.xin -dj.net -dj10.com -dj134.com -dj175.com -dj34.com -dj3721.net -dj63.com -dj88.com -dj89.com -dj97.com -dj970.com -djbh.net -djbstatic.com -djbx.com -djcb71.com -djcc.com -djcp099.com -djdkk.com -djduoduo.com -djec.net -djhgyy.com -djhuying.com -djjw.com -djkk.com -djkpai.com -djkxl.com -djlsoft.net -djrcl.com -djsh5.com -djstechpc.com -djstg.com -dju8.com -djw51.com -djwcp.com -djwins.com -djwxw.com -djxww.com -djye.com -djyjg.com -djyjob.com -djystudio.com -djysx.com -djyyh.com -djzbl.com -djzhj.com -djzhx.com -djzr88.com -dk618.com -dkdangle.com -dkjiaoyang.com -dklogs.net -dkmol.net -dktime.org -dky.cc -dkybpc.com -dkys.org -dl-mec.com -dl-origin.ubnt.com -dl-rc.com -dl.delivery.mp.microsoft.com -dl.djicdn.com -dl.google.com -dl.l.google.com -dl.ubnt.com -dl0679.com -dl0728.com -dl24gjb.com -dl321.net -dl767.net -dl8z.com -dlangchina.com -dlarjn.com -dlbh.net -dlbljy.com -dlbyg.com -dlcaic.com -dlcdnets.asus.com -dld.com -dld56.com -dldlsw.com -dledu.com -dlemba.com -dlfederal.com -dlflavor.com -dlfreak.com -dlg029.com -dlgaoji.com -dlgcpvc.com -dlgslb.com -dlgslb.net -dlgwbn.com -dlgzxh.com -dlhexie.com -dlidli.wang -dljhedu.com -dljrw.com -dljs.net -dll01.com -dllake.com -dllcm.com -dlldone.com -dllgslb.com -dllhook.com -dllku.com -dllxsp.com -dllzj.com -dlmonita.com -dlmzk.com -dlnap.com -dlosri.com -dlpuwan.com -dlrjtz.com -dlrkb.com -dlrspace.com -dlsjcsb.com -dlsqb.com -dlssa.com -dlsstax.com -dlsunworld.com -dlszywz.com -dltobacco.com -dltubu.com -dlvalve.com -dlxgjy.com -dlxiongshi.com -dlxk.com -dlxww.com -dlyeren.com -dlyestar.com -dlyile.com -dlyilian.com -dlzb.com -dlztb.com -dlzyc.com -dlzycf.com -dm004.net -dm0571.com -dm176.com -dm190.com -dm300.com -dm321.net -dm5.com -dm77.com -dm789.com -dm9.com -dmacg.net -dmaku.com -dmall.com -dmallcdn.com -dmayun.com -dmbcdn.com -dmcbs.com -dmcdn.com -dmcgas.com -dmchina1.com -dmcoders.com -dmd968.com -dmeg88.com -dmeiti.com -dmeiti.net -dmeng.net -dmfuns.com -dmgapp.com -dmgeek.com -dmgpark.com -dmguo.com -dmhlj.com -dmhmusic.com -dmiug.com -dmjtxt.com -dmlei.com -dmmds.com -dmozdir.org -dmpans.com -dmqapp.com -dmread.com -dmrtb.com -dmssc.net -dmtg.com -dmtrck.com -dmyy.cc -dmyz.org -dmyzw.com -dmzfa.com -dmzj.com -dmzj1.com -dmzx.com -dn.com -dn1234.com -dn580.com -dnbbn.com -dnbbs.com -dnbcw.info -dnbiz.com -dnbwg.com -dncheng.com -dndci.com -dndiy.net -dnf8.com -dnfly.net -dnfziliao.com -dngjxx.com -dngswin10.com -dngswin7.com -dngsxitong.com -dngz.net -dnhys.com -dnion.com -dnjishu.com -dnjs8.com -dnjsb.com -dnmall.com -dnnskin.net -dnnunion.com -dnparking.com -dnpz.net -dnpz123.com -dnqc.com -dns-diy.com -dns-diy.net -dns-dns.net -dns-sky.com -dns-vip.net -dns.com -dns.la -dns.pub -dns002.com -dns0755.net -dns100.net -dns102.com -dns110.com -dns123.net -dns1861.com -dns2008.com -dns234.net -dns383.com -dns456456123.com -dns567.com -dns6868.com -dns800.com -dns999999.com -dnsabc-a.com -dnsabc-b.com -dnsabc-f.com -dnsabc-g.com -dnsan.com -dnsapple.com -dnsapple.net -dnsceo.net -dnscnc.com -dnscpu.com -dnscpu.net -dnscto.net -dnsddos.com -dnsdiy.com -dnsdizhi.com -dnsdun.com -dnsdun.net -dnsece.com -dnsfamily.com -dnsfang.com -dnsff.com -dnsfwq.com -dnsgtm.com -dnsgulf.net -dnshot.net -dnshwx.com -dnsinside.net -dnsip.net -dnsis.net -dnsjia.com -dnsmeasurement.com -dnsmsn.com -dnsng.net -dnsnn.com -dnsns5.com -dnsns6.com -dnsnw.com -dnsor.com -dnsoray.net -dnsoso.com -dnsour.com -dnspai.com -dnspig.com -dnspod.com -dnspod.net -dnspood.net -dnsppdd.com -dnsrw.com -dnss.vip -dnssina.com -dnsum.com -dnsurl.net -dnsv1.com -dnsv1.net -dnsv2.com -dnsv3.com -dnsv4.com -dnsv5.com -dnsv8.net -dnsvcache.com -dnsvhost.com -dnswa.com -dnswhk.com -dnswind.net -dnszh.com -dnwx.com -dnxp.net -dnxtc.net -dnzhuti.com -dnzjds.com -dnzsb.com -do-shi.com -do1024.com -do123.net -do1618.com -do1999.com -do24k.com -doabit.com -dobest.com -dobirduser.com -dobunkan.com -doc163.com -doc88.com -doccamera.com -docer.com -docexcel.net -docin365.com -docker.org -dockerinfo.net -dockerone.com -dockone.io -doclass.com -docools.com -docpe.com -docrepository.org -docs.djicdn.com -docs.microsoft.com -docs.oracle.com -docs4dev.com -docschina.org -docsou.com -doctorcom.com -docx88.com -doczhi.com -doczj.com -dodashang.com -dodjoy.com -dodo8.com -dodobook.me -dodobook.net -dodoca.com -dodoeasy.com -dodoedu.com -dodoh5.com -dodonew.com -dodotu.com -dodovip.com -doergob.com -doershow.com -dofanyi.com -dofund.com -dog126.com -dogecdn.com -dogecloud.com -dogedoge.com -dogfight360.com -doglobal.net -dogmr.com -dogwhere.com -doh.pub -dohuo.com -doido.com -doit.am -doitim.com -doki8.com -doko.com -dolanzz.com -dolboebishekonchennoenahui.xyz -dolcn.com -dole.club -dolfincdnx.com -dolfindns.net -doll-leaves.com -doll-zone.com -dollun.com -dolphin-browser.com -dolphin.com -dolphinphp.com -domaingz.com -domarketing.org -domengle.com -domikoo.com -domobcdn.com -domobnetwork.com -domolo.com -domp4.com -domyshop.com -doname.com -doncc.org -donever.com -donevii.com -donews.com -dong-shou.com -dong-xu.com -dong10.com -dongannews.com -dongao.com -dongbao120.com -dongbeiol.com -dongbeishifandaxue.com -dongbucaijing.com -dongcai.net -dongcaibaoxian.com -dongchedi.com -dongcheng120.com -dongchenghotels.com -dongdalou.com -dongdao.net -dongdongaijia.com -dongdongwenda.com -dongdongyx.com -dongdongzu.com -dongdui.com -dongeedu.com -dongeejiao.com -dongfang-wh.com -dongfang.com -dongfang77.com -dongfangfj.com -dongfangfuli.com -dongfangnews.com -dongfangtai.com -dongfangtech.net -dongfangweiting.com -dongfeeng.cc -dongfeng-honda-elysion.com -dongfeng-honda-gienia.com -dongfeng-honda-greiz.com -dongfeng-honda-inspire.com -dongfeng-honda-jade.com -dongfeng-honda-ur-v.com -dongfeng-honda-xr-v.com -dongfeng-honda.com -dongfeng-nissan.com -dongfeng-renault.net -dongfeng.net -dongfengtrucks.com -dongfund.com -dongganboy.com -dongge.com -donghaifunds.com -donghao.org -donghengjt.com -donghongqiao.com -donghuaxsp.com -donghulvdao.com -dongjinyu.com -dongjun.cc -dongke.org -dongkelun.com -donglibbs.com -donglingying.cc -donglishuzhai.net -donglizhixin.com -dongman.fm -dongmansoft.com -dongmanwang.com -dongmanxingkong.com -dongmiban.com -dongnanmaifeng.com -dongni100.com -dongnienglish.com -dongniyingyu.com -dongoog.com -dongputech.com -dongqil.com -dongqiniqin.com -dongqiudi.com -dongqiudi.net -dongsenzs.com -dongshenghuiyang.com -dongshihao.com -dongshou.com -dongshouke.com -dongsport.com -dongtaijt.com -dongting.com -dongtu.com -dongua.com -dongwm.com -dongxi.net -dongxingkonggu.com -dongxuyitai.com -dongyaods.com -dongzhougroup.com -dongzhuoyao.com -donhonet.net -donkey4u.com -donkeyroll.com -donvv.com -dooccn.com -doodoobird.com -doofull.com -dooioo.com -dooland.com -doomii.com -doonhome.com -dooo.cc -doooor.com -door-expo.com -dooreb.com -doorhr.com -dopa.com -dopic.net -dora-family.com -dorapp.com -doraunion.com -doreso.com -dormforce.net -dortail.com -doseoer.com -doserv.com -doshome.com -dosnap.com -dospy.com -dossav.com -dossen.com -dostor.com -dota.tw -dota2rpg.com -dota2tester.com -dotamax.com -dotcpp.com -doteck.com -dotgate.com -dotinapp.com -dou.bz -dou.li -douban.co -douban.com -douban.fm -douban666.com -douban888.com -doubanio.com -doubaojf.com -doubean.com -doubimeizhi.com -doubimm.net -doubleclick.net -douboshi.net -doubozhibo.com -douc.cc -doucang.com -douco.com -doudang.com -doudehui.com -doudier.com -doudou.com -doudou.in -doudou3.com -doudou911.com -doudouad.com -doudouba.com -doudoubianli.com -doudoubird.com -doudoudm.com -doudouyin.com -doufan.tv -doufl.com -doufm.net -doufu.la -douglassclub.com -douguo.com -douguo.net -douhan.li -douhaogongyu.com -douhaomei.com -douhaosoft.com -douhua.net -douhuibuy.com -douikan.com -doujind.com -doukantv.com -doukeji.com -doulai.com -doulaicha.com -doulaidu.cc -doulaidu.com -doulaidu8.cc -douliao.net -douluodalu123.com -douluodalu3.com -doumengkeji.mobi -doumi.com -doumili.com -doumistatic.com -doumobfour.club -doumobsix.site -doumobtech.online -doupai.cc -doupir.com -doupobook.com -doupocangqiong1.com -douqi.com -doutian.me -doutugou.net -doutukeji.com -doutushe.com -douwanweb.com -douxie.com -douy18.com -douya2.com -douyaobuy.com -douyapu.com -douyar.com -douyin.com -douyincdn.com -douyinpic.com -douyinstatic.com -douyinvideo.net -douyinvod.com -douyou100.com -douyu.com -douyu.tv -douyuscdn.com -douyutv.com -douzi.com -douzihuyu.com -dovechina.com -dovesky.com -dovov.com -dowater.com -dowebok.com -dowei.com -doweidu.com -dowell-health.com -dowhere.com -down0.com -down123.cc -down123.me -down1997.com -down7788.com -down9.xyz -downbei.com -downbetter.com -downcc.com -downclass.com -downerapi.com -downeyboy.com -downfeng.com -downfi.com -downg.com -downi9.com -downjoy.com -downk.cc -downkr.com -downkuai.com -download.developer.apple.com -download.microsoft.com -download.visualstudio.microsoft.com -download.windowsupdate.com -download05.com -downloadcenter.samsung.com -downok.com -downol.com -downos.com -downpb.com -downpp.com -downsave.com -downun.com -downv.com -downxia.com -downxy.com -downya.com -downyi.com -downza.com -downzai.com -downzz.com -dowv.com -doxue.com -doyoe.com -doyoo.net -doyoudo.com -doyouhike.net -dozer.cc -dozview.com -dp.image-gmkt.com -dp2px.com -dp2u.com -dpaot.com -dpcafc.com -dpcq1.net -dpcyjt.com -dper.com -dpfile.com -dpigu.com -dplayer.tv -dplor.com -dplord.com -dplslab.com -dpqct.com -dprktimes.com -dptech.com -dptechnology.net -dptkbs.com -dpwl.net -dpxian.me -dpxq.com -dq123.com -dq18.com -dq247.com -dq3c.com -dq99.net -dqccc.cc -dqccc.com -dqcccc.com -dqdaily.com -dqdgame.com -dqguo.com -dqhgwy.com -dqhui.com -dqiis.com -dqiong.com -dqjckj.com -dqjintuo.com -dqjob88.com -dqpi.net -dqrailing.com -dqshjt.com -dqyfapiao.com -dqzc.com -dqzdhw.com -dr009.com -dr668.com -dragon-guide.net -dragon-hotel.com -dragonballcn.com -dragoncg.com -dragonchinashoes.com -dragonest.com -dragonnewsru.com -dragonsea-china.com -dragontrail.com -drakeet.me -drasy.net -draveness.me -drawyoo.com -drcact.com -drcg8.com -drclvs.com -drcuiyutao.com -drdrq.com -dre8.com -dream.ren -dream1986.com -dream4ever.org -dream61.com -dreamcast.hk -dreamchasercapital.com -dreamdu.com -dreamersall.com -dreamershop.com -dreamine.com -dreamkite.net -dreammail.org -dreamo100.com -dreamofchinese.com -dreamore.com -dreampiggy.com -dreams-travel.com -dreamsky.me -dreamswood.com -dreamsz.net -dreamwaybbs.com -dreamxt.net -dreawer.com -drehere.com -drepr.com -dressjapan.com -drgou.com -drhudong.com -drice.cc -drip.im -dripcar.com -driverdevelop.com -drivergenius.com -driversdown.com -driverzeng.com -drivethelife.com -drli.group -drlmeng.com -drm-x.com -drm-x.net -drmhmhi.tokyo -drmj.org -droi.com -droibaas.com -dropboxchina.com -dropsec.xyz -drouma.com -drscrewdriver.com -drtyf.com -drugfuture.com -druggcp.net -drumchina.com -drunkpiano-liuyu.net -drupal001.com -drupal001.net -drupalba.com -drupalla.com -drupalproject.org -drupaluser.org -drvsky.com -drwfggc.com -ds-360.com -ds023.com -ds123456.com -ds5f.com -dsblog.net -dscbs.com -dsdbearing.com -dsdou.com -dsfdc.com -dsfof.com -dsgho.com -dshigao.com -dshjfh.com -dshmama.com -dshrc.com -dshyw.com -dskb.co -dsmi.cc -dsmyiyuan.com -dsmzyy.com -dsmzyy120.com -dsocean.com -dsonekey.com -dsook.com -dsp.com -dspwhy.com -dsq.com -dsqin.com -dssz.com -dssz.org -dsti.net -dstoutiao.com -dswjcms.com -dswmt.com -dswzxh.com -dsxdn.com -dszj.net -dszw.net -dtcash.com -dtcj.com -dtcms.net -dtcoalmine.com -dtcxw.com -dtdiefa.com -dtdream.com -dtdxcw.com -dtfcw.com -dtftsm.com -dth199.com -dthrb.com -dtidc.com -dtime.com -dtletao.com -dtmao.cc -dtmuban.com -dtqiufa.com -dtrcb.com -dts007.com -dtshot.com -dtsp99.com -dtssmodel.com -dtstack.com -dtstatic.com -dttc-icp.com -dttt.net -dturl.cc -dtxmw.com -dtxn.net -dtxww.com -dtysky.moe -dtyzg.com -du00.com -du114.com -du175.com -du1du.cc -du1du.org -du7.com -du7.org -du8.com -duai.com -dualaid.com -duanjn.com -duanlonggang.com -duanmale.com -duanmeiwen.com -duanqu.com -duanrong.com -duanshu.com -duantian.com -duanwenxue.com -duanwxue.com -duanxin321.com -duanxin520.com -duanzao001.com -duanzhihu.com -duanzikuaizui.com -duanziwang.com -duapp.com -duba.com -duba.net -dubbo.io -dubiwang.com -dubprince.com -duchang.org -dudong.com -dudubashi.com -dududu.la -dudumeijia.com -dudupo.com -duduyu.net -duelcn.com -dugoogle.com -duguying.net -duhao.net -duhub.com -dui.ai -dui1dui.com -dui88.com -duia.com -duiai.com -duihuan123.com -duihuashijie.com -duikuang.com -duiliandaquan.net -duimg.com -duimin.com -duino123.com -duiopen.com -duitang.com -duitianhe.com -duizhuang.com -dujiaoshou.org -dujiapin.com -dujin.org -dujiza.com -dukankan.com -dukechiang.com -dukuai.com -dullong.com -dullr.com -dulouw.com -dumanhua.com -dumasecurity.com -dumasoftware.com -dumeiwen.com -dumi0898.com -dumili.com -dumou.com -dunjiaodu.com -dunkhome.com -dunlve.com -duobaoqibin.com -duobei.com -duobeiyun.com -duobeiyun.net -duoben.net -duocaitou.com -duochang.cc -duodaa.com -duodada.com -duoddi.com -duodian.com -duoduo123.com -duoduobaba.com -duoduocdn.com -duoduotv.com -duoduoyin.com -duoduoyouli888.com -duoduozhifu.com -duoente.net -duofull.com -duogouhui.com -duohou.net -duohui.co -duoic.com -duojiaochong.com -duokaiwang.com -duokan.com -duokanbox.com -duokebao.net -duokebo.com -duokemao.com -duoketuan.com -duoku.com -duolabao.com -duolabaocdn.com -duoladayin.com -duolaima.com -duolapiao.com -duolduo.com -duole.com -duolebo.com -duolegame.com -duolerong.com -duolingptfe.com -duolunmoma.org -duoluodeyu.com -duoluohua.com -duoluosb.com -duomai.com -duomeiti.co -duomi.com -duomiapp.com -duomicheng.com -duomijuan.com -duomiyou.com -duomni.com -duomu.tv -duopao.com -duoqu.com -duorenwei.com -duorou.com -duosai.com -duose.com -duosenfashion.com -duoshou7.com -duoshoubang.com -duoshuo.com -duososo.com -duosq.com -duost.com -duotai.co -duotai.net -duote.com -duote.org -duotegame.com -duotin.com -duotoo.com -duotoupiao.com -duotuwang.com -duouoo.com -duowan.com -duowanns.com -duoxiaoshi.com -duoxinqi.com -duoxj.com -duoyewu.com -duoyi.com -duoyinsu.com -duoyit.com -duoyoumi.com -duoyun.info -duozhi.com -duozhishidai.com -duozhuayu.com -duoziwang.com -dup2.org -dupontcigar.com -dupv.com -dushicn.com -dushifang.com -dushijia.com -dushiliren.net -dushitiyan.com -dushiyufu.com -dushu.com -dushu.io -dushu369.com -dushudaren.com -dushuge.net -dushuzhong.com -dushw.com -dustit.me -dusuu.com -dute.me -dutenews.com -dutor.net -dutory.com -dutype.com -duuchin.com -duunion.com -duwenfei.com -duwenxue.com -duwenz.com -duwenzhang.com -duxcms.com -duxiaoman.com -duxiaoshuo.com -duxinjianli.com -duxiu.com -duyandb.com -duyao001.com -duyidu.com -duyixing.com -duzelong.com -duzhe.com -duzhebao.com -duzhoumo.com -dv37.com -dv58.com -dvagent.com -dvbbs.net -dvbcn.com -dvcms.com -dvd85.com -dvd94.com -dvdc100.com -dvdjy.com -dvmama.com -dvmission.com -dvr163.com -dvrdydns.com -dvvvs.com -dw.la -dw178.com -dw361.com -dwfei.com -dwinput.com -dwion.com -dwjoy.com -dwmoniqi.com -dwntme.com -dwpz9.com -dwqcw.com -dwrh.net -dwsedu.com -dwstatic.com -dwstock.com -dwsyw.com -dwt.life -dwtedx.com -dwz.date -dwz.lc -dwz.mn -dx-job.com -dx-tech.com -dx04131.com -dx114118.com -dx168.com -dxbei.com -dxclinics.com -dxcm.net -dxda.com -dxecs.com -dxf5.com -dxf6.com -dxias.com -dxjs.com -dxlfile.com -dxm.so -dxmpay.com -dxmstatic.com -dxnf.xyz -dxpei.com -dxpmedia.com -dxqyy.com -dxqzsw.com -dxrc.com -dxs96.com -dxsaxw.com -dxsbb.com -dxsckj.com -dxsclass.com -dxsdb.com -dxsng.com -dxsport.com -dxsvr.com -dxszx.com -dxton.com -dxwei.com -dxxnews.com -dxxps.com -dxxxfl.com -dxy.com -dxy.me -dxyan.org -dxycdn.com -dxyrc.com -dxzq.net -dxztc.com -dxzx.com -dxzy163.com -dy-gold.com -dy.cm -dy008.com -dy131.com -dy1905.net -dy2018.com -dy2018.net -dy23.xyz -dy2dy.com -dy666.cc -dy880.com -dybeta.com -dycar.net -dycars.com -dycdn.com -dycf.net -dycmjkgl.com -dycool.com -dydao.com -dydata.io -dydt.net -dydytt.com -dydytt.net -dyee.org -dyfc.net -dyfcw.com -dyg-hec.com -dygang.com -dygang.net -dygang.org -dygangs.com -dygod.com -dygod.net -dygod.org -dygodj8.com -dyhjw.com -dyhr88.com -dyhzj.com -dyj.cc -dyjqd.com -dylc.com -dylxx.net -dyly.com -dymi.cc -dyonr.com -dypai.com -dyqc.com -dyrbw.com -dyrcb.net -dyrjjt.com -dyrt168.com -dysfz.cc -dysxxw.com -dyteam.com -dytechnolog.com -dytol.com -dytt.net -dytt2019.net -dytt789.com -dytt8.com -dytt8.net -dyuzz.club -dyw0.com -dyxia.com -dyxldjy.com -dyxsdwm.com -dyxtw.com -dyxuexin.com -dyxw.com -dyxz.la -dyydy.com -dyymwy.com -dyynong.net -dyys.com -dyysoft.net -dyzxw.org -dz-z.com -dz.tt -dz11.com -dz19.net -dz1982.com -dz31hao.com -dz666.com -dz746.com -dz88.com -dz88.la -dzbarcode.com -dzbchina.com -dzblxx.com -dzbmama.com -dzboligang.com -dzcgtgcl.com -dzcj.tv -dzcmedu.com -dzcnc.com -dzdiy.com -dzdoll.com -dzdu.com -dzfc.com -dzfxh.com -dzgoo.com -dzgwg.com -dzgxq.com -dzhaoj.com -dzhope.com -dzhqexpo.com -dzjcp998.com -dzkbw.com -dzlhktsb.com -dzllzg.com -dzmdq.com -dzmhospital.com -dzng.com -dzoptics.com -dzpk.com -dzpz6.com -dzpz8.com -dzqiche.com -dzqu.com -dzrbs.com -dzrlvy.com -dzsaas.com -dzsaascdn.com -dzsc.com -dzsfx.com -dzsg.com -dzshengchi.com -dzsm.com -dzsrcw.com -dzssy.com -dzsyxx.com -dztcbj.com -dztcfj.com -dztchun.com -dztcjt.com -dztcnm.com -dztv.tv -dzty365.com -dzvv.com -dzwebs.net -dzwindows.com -dzwww.com -dzwww.net -dzxh8.com -dzxwnews.com -dzxxzy.com -dzynyy.com -dzyqc.com -dzyqh.com -dzysclite.com -dzyule.com -dzyysb.com -dzyzwl.com -dzz.cc -dzzgsw.com -dzzoffice.com -e-10031.com -e-3lue.com -e-bidding.org -e-bq.com -e-bq.org -e-buychina.com -e-celap.com -e-chinalife.com -e-cloudstore.com -e-cookies.net -e-cuc.com -e-cwinfo.com -e-cyb.com -e-dache.com -e-eway.com -e-flyinc.com -e-ging.com -e-ging.net -e-gooo.com -e-hongw.com -e-investingguide.com -e-jjj.com -e-lifemall.com -e-lining.com -e-lvyou.com -e-mallchina.com -e-micromacro.com -e-muzeo.com -e-nci.com -e-net.hk -e-onekey.com -e-picclife.com -e-pointchina.com -e-ruikd.com -e-sleb.com -e-sscard.com -e-tiller.com -e-tui.net -e0514.com -e0575.com -e0734.com -e077.com -e118114.com -e12345.com -e12e.com -e139.com -e1988.com -e1menjackets.com -e21cn.com -e22a.com -e24c.com -e253.com -e2capp.com -e2esoft.com -e2say.com -e360e.com -e365.org -e365mall.com -e3cloud.com -e3ol.com -e4008.com -e4asoft.com -e521.com -e546.net -e5618.com -e5n.com -e5yx.com -e66666.com -e6816.com -e68cname.com -e7890.com -e7e.co -e7e6.net -e7e7e7.com -e7wei.com -e816.cc -e836g.com -e890.com -e8ud3.com -e8zw.com -e9377f.com -e9727.com -e9898.com -e99999.com -ea-retina.com -ea3w.com -eabax.com -eachinfo.com -eachnet.com -eachsee.com -eaeb.com -eaes-seari.com -eafifaonline2.com -eaglexiang.org -eahui.com -eaibot.com -eaka365.com -eallcn.com -eallerp.com -earth2037.com -earthedu.com -earthstar-cloud.com -easck.com -eascs.com -easdo.com -easeapi.com -easeeyes.com -easemob.com -easerun.com -easetuner.com -easeus.com -easeyedelivery.com -easilysend.com -easiu.com -east.net -east263.com -eastall.com -eastbest.com -eastchinafair.com -eastcom-sw.com -eastcom.com -eastcompeace.com -eastcoms.com -eastday.com -eastdesign.net -eastdigit.com -easteat.com -eastent.com -easternalong.com -eastforever.com -eastftp.net -eastfu.com -easthome.com -eastib.com -eastled.com -eastlending.com -eastmoney.com -eastmoneyfutures.com -eastmoneyloans.com -eastobacco.com -eastsilver.com -eastsoo.com -eastsunintl.com -eastups.com -eastwinn.com -easy-all.net -easy-china.com -easy-linkholiday.com -easy-mock.com -easy136.com -easy2mine.com -easy2world.com -easy361.com -easy888.com -easyai.tech -easyaq.com -easyaq.org -easyar.com -easybug.org -easycolor.cc -easydarwin.org -easyder.com -easydoc.xyz -easyfami.com -easyfang.com -easyfapiao.com -easygametime.com -easyhexo.com -easyhin.com -easyhoo.net -easyicon.net -easyjf.com -easylaa.com -easyliao.com -easylink.io -easylinkin.com -easylinkin.net -easymks.com -easymorse.com -easymule.com -easynet.vip -easypayx.com -easypcmac.com -easyreadtech.com -easyrecovery.cc -easyrecovery.net -easyrecoverychina.com -easyrecoverycn.com -easysoc.org -easysofthome.com -easyswoole.com -easytalkee.com -easytifen.com -easytimetv.com -easytocn.com -easytouch.com -easytrip.com -easywechat.com -easyzw.com -eaticket.com -eatonchn.com -eaydu.com -eayou.com -eayuan.com -eayyou.com -eazytec-cloud.com -eb163.com -eb80.com -ebadu.com -ebadu.net -ebaifo.com -ebaina.com -ebama.net -ebangchina.com -ebanma.com -ebanshu.net -ebaoquan.org -ebasset.com -ebcmall.com -ebdan.net -ebdoor.com -ebeta.org -ebfcn.com -ebibi.com -ebigear.com -ebingqilin.com -ebiobuy.com -ebioe.com -ebiogo.com -ebioweb.com -ebjfinance.com -ebkj.net -eblockschina.com -ebnew.com -ebook.name -ebook23.com -ebookbao.net -ebookmen.com -ebooks.run -ebopark.com -eboxmaker.com -ebrun.com -ebscn.com -ebseek.com -ebtang.com -ebtrust.com -ebuckler.com -ebulks.com -ebuy31.com -ebways.com -ec-ae.com -ec-cloudtech.com -ec-founder.com -ec-world.com -ec.com -ec0715.com -ec3s.com -ec51.com -ec517.com -ec66.com -ec818.com -ecadi.com -ecaidian.com -ecaihr.com -ecaray.com -ecare365.com -ecartoon.net -ecasesoft.com -ecbcamp.com -eccang.com -eccc-china.com -eccdnx.com -eccn.com -eccnmall.com -ecco-market.com -ecctaa.com -ecdpower.net -ecduo.com -eceibs.com -eceibs20.com -ecej.com -ecer.com -eces66.com -ecgci.com -ecgoods.com -echanceyun.com -echangwang.com -echangye.com -echao8.com -echargenet.com -echarpile.com -echartsjs.com -echashi.com -echatsoft.com -echead.com -echiele.com -echinacareers.com -echinacities.com -echinagov.com -echinatobacco.com -echo188.com -echojb.com -echomod.com -echoteen.com -echuandan.com -eciawards.org -ecice06.com -ecig100.com -ecigm.com -ecitic.com -ecjobhome.com -ecjson.com -ecjtu.net -ecjtu.org -eckjzx.com -ecloud.hk -eclyw.com -ecmagnet.com -ecmoban.com -ecnsea.com -ecnudec.com -ecoalchina.com -ecochuse.com -ecocn.org -ecohumanity.org -ecomoter.com -ecookinn.com -ecoplastech.com -ecoprint.tech -ecorr.org -ecouser.net -ecovacs.com -ecp888.com -ecparty.net -ecphk.com -ecppn.com -ecqun.com -ecrrc.com -ecs004.com -ecsage.net -ecshop.com -ecshop123.com -ecsits.com -ecsponline.com -ecuc123.net -ecustmde.com -ecvv.com -ecwan77.net -ecwtnt.com -ecydm.com -ecyj.net -ecyti.com -ed2000.app -ed2000.com -ed2000k.com -ed2kers.com -ed2kfile.com -ed2kk.com -eda-china.com -eda1024.com -eda365.com -eda365.net -eda8.com -edabbs.com -edaboss.com -edaceo.com -edacn.net -edadoc.com -edagit.com -edai.com -edaibo.com -edaidb.com -edaili.com -edaixi.com -edajin.com -edajob.com -edanji.com -edaocha.com -edatahome.com -edatop.com -edawiki.com -edb-tech.com -edcba.com -eddic.net -eddyapple.com -eddycjy.com -ede35.com -edenab.com -edenw.com -edgeiptv.com -edgezzz.com -edhic.com -edianchi.com -edianshang.com -edianzu.com -ediclot.com -edieai.com -edifier.com -edingtou.com -edingzhuan.com -edinuan.com -edirect.asia -ediuschina.com -edk24.com -edmcn.net -ednrc.com -edns.com -edodocs.com -edogantt.com -edojia.com -edojs.com -edong.com -edongeejiao.com -edongli.net -edongyun.com -edooon.com -edosawa.com -edowning.net -edqgk.com -edragongame.com -edsionte.com -edspay.com -edt2017.com -edt2018.com -edtsoft.com -edu-book.com -edu-chineseembassy-uk.org -edu-job.org -edu-nw.com -edu-shanghai.net -edu.com -edu03.com -edu0851.com -edu201.com -edu24o1.com -edu24ol.com -edu399.com -edu510.com -edu5a.com -edu63.com -edu777.com -edu80.com -edu84.com -edu84.net -edu88.com -eduartisan.com -edub2b.net -educg.net -educhicago.org -educhn.net -edudc.net -eduease.com -eduego.com -eduei.com -eduglobal.com -eduglobalchina.com -eduiso.com -edujia.com -eduour.com -edupm.com -eduqz.net -edurck.com -edushi.com -edusoho.com -edusoho.net -edutao.com -edutime.net -edutt.com -eduu.com -eduuu.com -eduwenzheng.com -eduwest.com -eduwg.com -eduwo.com -eduwsw.com -eduwx.com -eduwz.net -eduxiao.com -eduyf.com -eduyo.com -eduzhai.net -eduzhi.com -eduzhixin.com -edward-han.com -edwiv.com -edzhishi.com -edzx.com -ee-forum.org -ee1234.com -ee68.com -ee8828.com -eebbk.com -eebbk.net -eebest.com -eeblog.net -eeboard.com -eebqg.com -eebyte.com -eechina.com -eecn.cc -eecnt.com -eecourse.com -eecso.com -eedns.com -eeduol.com -eee-eee.com -eee114.com -eee4.com -eee5701.com -eeedri.com -eeedu.net -eeeen.com -eeeetop.com -eeeff.com -eeeknow.com -eeelw.com -eeeqi.net -eeetb.com -eefans.com -eefcdn.com -eeff.net -eefocus.com -eehu.com -eeio99.com -eeioe.com -eekang.net -eelly.com -eeloves.com -eenot.com -eeook.com -eeparking.com -eeppt.com -eeq8.com -eeqiu.com -eer-mail.ru -eeskill.com -eeso.net -eetoday.com -eetop.com -eetop.wang -eetrend.com -eetrust.com -eeussf.com -eeworld.com -eeworm.com -eexing.com -eeyaa.net -eeybo.com -eeyy.com -ef-cdn.com -ef-school.com -ef360.com -ef360.net -ef82.com -ef9377.com -efala.net -efang.tv -efapiao.com -efashionchina.com -efe.cc -efenboo.com -efengji.org -efesco.com -eff-soft.com -effapp.com -effecthub.com -effevo.com -efficient.hk -effirst.com -efly.cc -eflybird.com -eflycloud.com -eflydns.net -eflyingfire.com -efmac.org -efnchina.com -efotile.com -efount.com -efpp.com -eftoutiao.com -efubo.com -efucms.com -efueloil.com -efwang.com -efwh.com -efy-tech.com -efyt6.com -egainnews.com -egaoxiu.com -egbgedu.com -egfcare.com -egg-born.org -egg.htcsense.com -eggjs.org -eggscute.com -eggtt.com -egonetworks.org -egongzheng.com -egoonet.com -egotops.com -egou.com -egou0515.com -egouo.net -egouz.com -egovsum.com -egreatworld.com -egret-labs.org -egret.com -egsea.com -egshuyuan.com -ehafo.com -ehaier.com -ehaimao.com -ehaiwang.com -ehangtian.com -ehaoyao.com -ehaoyao.us -ehclglobal.com -ehcoo.com -ehealthcareforum.com -ehedco.com -ehiman.com -ehinvest.hk -ehn3.com -ehome5.com -ehome8.com -ehomeclouds.com -ehomeday.com -ehometu.com -ehongyuan.com -ehouse411.com -ehousechina.com -ehoutai.com -ehowbuy.com -ehowbuy.net -ehsoftware.com -ehsy.com -ehtao.net -ehtttop.com -ehualu.com -ehuatai.com -ehub.net -ehui.net -ehujia.com -ehuoke.com -ehuoyan.com -ehust.net -ehuzhu.com -ehvacr.com -ei6nd.com -eiabbs.net -eickaopei.com -eicodesign.com -eicp.net -eidlink.com -eieku.com -eigentech.ai -eigenvr.com -eightbridge.com -eightedu.com -eigpay.com -eiicn.com -eiimg.com -eiiq.com -eilieili.cc -eimoney.com -eimway.com -eindex.me -einkcn.com -eintone.com -eiot.com -eipaibao.com -eiray.com -eis100.com -eisdl.com -eisoo.com -eistudy.com -eistudy.net -eit0571.com -ej38.com -ejamad.com -ejcms.com -ejcop.com -ejdyin.com -ejee.com -ejeegroup.com -ejfeng.com -ejiacn.com -ejiaju.cc -ejianji.com -ejianmedia.com -ejiayu.com -ejie.me -ejinqiao.com -ejinshan.net -ejion.net -ejiyao.com -ejmrh.com -ejoy.com -ejoy365hk.com -ejoy99.com -ejoychina.com -ejrfood.com -ejttp.com -eju.com -ejudata.com -ejunshi.com -ek6.com -ekaidian.com -ekan001.com -ekan123.com -ekang99.com -ekaobang.com -ekaoyan.com -ekaoyan365.com -ekclubinternational.com -eketong.com -ekexiu.com -ekoooo.com -eku.cc -ekuaibao.com -elabinfo.com -elanso.com -elanw.com -elatr.com -elbmodel.com -eldawa.com -ele.me -ele.to -ele001.com -ele12.com -elecbh.com -elecfans.com -elecfans.net -elecinfo.com -elecrystal.com -elecshop.com -eleme.io -elemecdn.com -element3ds.com -elementfresh.com -elenchina.com -elenet.me -elesos.com -elexcon.com -elfartworld.com -elfjs.com -elgnet.com -elht.com -elian5.com -elianhong.com -elianmeng.vip -elichtmedia.com -elikeme.com -elikeme.net -elitecrm.com -elitejlb.com -eliushi.com -elkpi.com -ellechina.com -ellemen.com -elliotxing.com -ellll.com -elmerlxy.com -eloancn.com -elong-edm.com -elong.com -elong.net -elongshine.com -elongstatic.com -elpcon.com -els001.com -elsenow.com -elsyhw.com -eltws.com -eluosidy.com -eluxiu.com -elvgufen.com -elvhome.com -elvshi.com -elvxing.net -elxk.com -elycn.com -emacs-china.org -emadao.com -emaileds.com -emailflame.com -emailxqq.com -emall.site -emall001.com -emao.com -emao.net -emarbox.com -emaup.com -emb168.com -embbnux.com -embcom.net -embed.cc -embedfire.com -embedhq.org -embedream.com -embedsky.com -embedtrain.org -embedu.org -embedunion.com -embedway.com -embest-tech.com -embexperts.com -embryform.com -embsky.com -emcbj.com -emcbtc.com -emcite.com -emcsosin.com -emdl.ws.microsoft.com -eme2000.com -emeixs.com -emeor.com -emepu.com -emindos.org -emiqu.com -emjob.com -emlinix.com -emlog.net -emohe.com -emojidaquan.com -emojimobile.com -empos.net -emrl0z.com -ems517.com -emshost.com -emswxw.com -emsym.com -emtronix.com -emtx.com -emu999.net -emuban.com -emuch.net -emufan.com -emugif.com -emui.com -emuia.com -emulatedlab.com -emumax.com -emushroom.net -emwan.com -emyard.com -en-sem.com -en.cc -en.tm -en51.com -en8848.com -en998.com -ename-dns.net -ename.com -ename.net -enappstore.com -enbar.net -enbowang.com -enbrands.com -enci-world.com -enciclopediagalega.com -encrypter.net -enec.net -enen6.com -enet15.com -enet360.com -enetedu.com -enfi.vip -enfodesk.com -enfogrowth.com -eng24.com -eng888.com -engeniustec.com -engliship4u.com -englishpad.com -englishtide.com -englishtownpromotion.com -engloncar.com -engpx.com -enguo.com -engz.net -enicn.com -enjoy.link -enjoy1992.com -enjoy3c.com -enjoydiy.com -enjoyfe.com -enjoykorea.net -enjoymeet.com -enjoyyue.com -enjoyz.com -enkichen.com -enkiorder.com -enkj.com -enlightent.com -enmajor.com -enmonster.com -enmotech.com -enmuo.com -ennresearch.com -ennweekly.com -enoya.com -enpapers.com -enqoo.com -enread.com -enroo.com -enroobbs.com -enrz.com -ensbiz.com -enscg.com -enshide.com -enshifdc.com -enshijob.com -enstellaedbtopst.com -enstylement.com -ent120.com -entboost.com -enterdesk.com -enterdesk.org -entts.com -enunix.com -envisioncn.com -enzj.com -eoaoo.com -eoeandroid.com -eoemarket.com -eoemarket.net -eoffcn.com -eoffice-mart.com -eoivisa.com -eol8.com -eolinker.com -eomarket.com -eomoy.com -eonun.com -eooioo.com -eooqoo.com -eoouoo.com -eoozoo.com -eoqjf.com -eoriver.com -eosantpool.com -eospark.com -eosyg.com -eovas.net -ep-china.net -epaas.net -epailive.com -epalfish.com -epama.com -epanshi.com -epbiao.com -epcdiy.org -epchina.com -epciu.com -epcnn.com -epcsw.com -epday.com -epeaksport.com -epeiyin.com -epet.com -epetbar.com -epetpet.com -epexpo-asia.com -ephen.me -ephoton.me -epichust.com -epinautomation.com -epinduo.com -epinga.com -epinv.com -epjike.com -epjob88.com -epjyw.com -eplove.com -epmao.com -epoos.com -epport.com -epqiming.com -epremierwigs.com -eprezi.com -eps114.com -epschool.net -epub360.com -epubchina.com -epubit.com -epweike.com -epwitkey.com -epwitkey.net -epwk.com -epwksx.com -epzcw.com -eq-hl.com -eqblog.com -eqbyc.com -eqceshi.com -eqding.com -eqh5.com -eqidi.com -eqie.com -eqifa.com -eqigou.com -eqingdan.com -eqiseo.com -eqishare.com -eqixiu.com -eqq9.com -equn.com -eqxiu.com -eqxiu.mobi -eqxiu.tv -eqxiul.com -eqxiuzhan.com -eqyn.com -eqz.cc -eraclean.com -eranet.com -ercc.cc -erdaicms.com -erdangjiade.com -erdianzhang.com -erdong.site -erdosrcb.com -ere3j2e001.com -erentalcarpro.com -ereuiib.com -erfdhiu.com -erg2008.com -ergedd.com -ergengtech.com -ergengtv.com -ergouzi.fun -erhaojie.com -eri.cx -ericfu.me -erichfund.com -erji.net -erke.com -erldoc.com -erlo.vip -erlou.com -ermao.com -ermiao.com -ernaonet.com -ernest.me -ernxzc.com -eroacg.com -erongda.com -erongdu.com -erongtu.com -erpchn.com -erpcoo.com -errenzhuan.cc -ershenghuo.net -ershicimi.com -ershouhui.com -ert7.com -ertongkongjian.com -ertongtuku.com -ertongyouleshebei.com -erun360.com -erutluv.com -erxe.club -erya100.com -eryajf.net -eryuapp.com -eryyutu.com -erzzz.com -es-soccer.com -es123.com -es9e.com -esa2000.com -esafenet.com -esavip.com -esbag.com -escdn.com -escjy.net -esclass.com -esdaxiagu.com -esde.cc -esduu.com -esensoft.com -esfimg.com -eshangxian.com -eshanyao.com -eshenlin.com -eshimin.com -eshiyun.info -eshop-switch.com -eshopb2c.com -eshow365.com -eshufa.com -eshukan.com -eshuu.com -eshzp.com -esinidc.com -esj365.com -esk365.com -eskgn.com -esky8.com -eskysky.com -eslosity.com -esmartwave.com -esnai.com -esnai.net -eso999.com -esoboy.com -eson.org -esoo.org -esoogle.com -esouou.com -esouti.com -esoyu.com -espier.mobi -espnlol.com -essaystar.com -essca.com -essclick.com -essdc.com -essemi.com -ession.com -essjj.com -essyy.com -estargm.com -estarsseoul.org -estory365.com -estrongs.com -estudychinese.com -esugimoto.com -esun21.com -esun88.com -esuniao.com -esunny.com -eswin.com -esxqk.com -esyantu.com -eszmall.com -esztsg.org -eszwdx.com -et59.com -etao.com -etaog.com -etaxcn.com -etccenter.com -etcchebao.com -etcsd.com -etdown.net -etelux.com -eternalsakura.com -eternalsakura13.com -eternalsys.com -etest8.com -eteste.com -etf.group -etf88.com -eth6.org -ethainan.com -ethan.pub -ethercap.com -ethern.me -ethfans.org -etiantian.com -etiantian.net -etiantian.org -etiaoliao.com -etimeusa.com -etiv.me -etjournals.com -etlong.com -etmchina.com -etmoc.com -eto9.com -etochina.org -etocrm.com -etomlink.com -etongdai.com -etongguan.com -etonkidd.com -etoote.com -etoplive.com -etosun.com -etoubao.com -etowz.com -etpass.com -etrack01.com -etrack02.com -etrack03.com -etrack04.com -etrack05.com -etrack07.com -etrack08.com -etranshare.com -etrd.org -ets-toeic.com -ets100.com -etsc-tech.com -etsoon.com -etsstar.com -etstock.net -ettbl.org -ettdnsv.com -ettol.com -ettshop.com -etu3.com -etu6.com -etuan.com -etudu.com -etulink.com -etuonet.com -etyy.com -etyyy.com -etz927.com -etzuqiu.com -eua.design -eub-inc.com -euci-software.com -eucjic.org -eudic.net -eueueu.com -eui.cc -euibe.com -eulike.com -eulixos.com -euratwin.com -eureka.name -eurochinesedaily.com -eusercenter.com -ev123.com -ev123.net -ev3ds.com -eva-game.com -eva001.com -evaad.com -evacg.com -evancg.com -evask360.com -evcar.com -evcard.com -evcard.vip -evdays.com -eve.moe -eventdove.com -events2.djicdn.com -evenyao.com -everdns.com -evereasycom.com -everedit.net -everet.org -evergrande.com -evergrandeauto.com -everlose.com -eversino.com -evervc.com -everychina.com -everydo.com -everyinch.net -everyouthtech.com -evestemptation.com -evfchina.com -evget.com -evgetedu.com -evhui.com -evideocloud.net -evideostb.com -evilbinary.org -evilcos.me -evileyesaint.com -evketang.com -evlo.us -evlook.com -evoc.com -evotrue.com -evzhidao.com -ew9z.com -ewaga.com -ewang.com -ewang100.net -ewanshang.com -ewarecomputer.com -ewatt.com -ewcache.com -ewceo.com -ewdcloud.com -ewdtx.com -ewebeditor.net -ewebsoft.com -ewebweb.com -ewecha.com -ewei.com -eweiqi.com -ewenxue.net -ewenyan.com -ewide.net -ewidecloud.com -ewidewater.com -ewin007.com -ewinall.com -ewind.us -ewinnet.com -ewku.com -ewoka.com -ewomail.com -eworksglobal.com -eworldship.com -ewp051.com -ewpeinfo.com -ewqcxz.com -ewstudy.com -ewt.cc -ewtang.com -ewteacher.com -ewuqa.com -ex-silver.com -ex-starch.com -exam58.com -exam76.com -exam8.com -examcoo.com -examda.com -examebook.com -exampx.com -examw.com -exands.com -exaphotons.com -exasic.com -exbot.net -exbulk.com -excake.com -excalibur.link -excaliburdx.com -excbio.com -excean.com -excel8.com -excel880.com -excel99.com -excelcn.com -excelhome.net -excelpx.com -exceltip.net -exchangecn.com -exchen.net -exdoll.com -exehack.net -exezhanqun.com -exfree.com -exhera.com -exiaoba.com -exinee.com -exiqu.com -exmailqq.com -exmrw.com -exnpk.com -exntech.com -exo-mk.com -expai.com -expba.com -expdns.net -expiredns.net -expirenotification.com -expirepausedns.com -expku.com -expo-china.com -expobbs.com -expoeye.net -exponingbo.com -expoon.com -expoooo.com -expotu.com -expowindow.com -expressjiaocheng.com -expreview.com -expsky.com -exsvc.net -ext2fsd.com -extfans.com -exthin.net -extmail.org -extremep2p.com -extron-tech.com -extstars.com -exuanfang.cc -exuanpin.com -exuanshi.com -exuekt.com -exuezhe.com -exunchi.com -exv9.com -exxstar.com -exxvip.com -exziyuan.com -ey-app.com -ey99.com -eyangguang.com -eyangmedia.com -eyao168.com -eyaobei.com -eyasglobal.com -eyasgloble.com -eycans.com -eydata.net -eye-young.vip -eye024.com -eye027.com -eye0712.com -eye0731.com -eyejin.com -eyeofcloud.com -eyeofcloud.net -eyepetizer.net -eyesar.com -eyeshenzhen.com -eyeuc.com -eyexp.com -eyhsj.com -eyoodns.com -eyou.com -eyou.net -eyoucms.com -eyoudi.com -eyoujj.com -eyourbusiness.com -eyrefree.org -eyuangong.com -eyuanzhou.com -eyugame.com -eyunidc.com -eyunker.com -eyunsou.com -eyunzhu.com -eyurumen.com -eyuyan.com -eyuyan.la -eyuyao.com -eywedu.com -eywedu.net -eywedu.org -eyy168.com -eyy8.vip -ez-leaf.com -ezagoo.com -ezaiai.com -ezbuypay.com -ezca.org -ezcname.com -ezcpt.com -ezcun.com -ezdcw.com -ezdmw.com -ezdnscenter.com -ezeroshop.com -ezhangdan.com -ezhangu.com -ezhaobiao.com -ezhicai.com -ezhijiantuoluo.com -ezhun.com -ezitong.com -ezlippi.com -ezliushao.com -ezloo.com -ezlost.com -eznowdns.com -eznowdns.net -ezqhdz.com -ezrpro.com -ezsmth.com -eztcn.com -eztest.org -eztg.com -eztvnet.com -eztxw.com -ezubao.com -ezucoo.com -ezwan.com -ezwebtest.com -f-0.cc -f-stack.org -f.cx -f008.com -f0580.com -f1-shanghai.com -f139.com -f1688.com -f1zd.com -f262.com -f2e.im -f2k.pub -f2pool.com -f2qu.com -f2time.com -f2zd.com -f315.cc -f32365.com -f3322.net -f3322.org -f41g.com -f537.com -f5432.com -f54321.com -f5gh.com -f5hf.com -f5sd.com -f5yx.com -f773.com -f7777.net -f8fm.com -f96.net -fa-today.com -fa597.com -faakee.com -fabang.com -fabao365.com -fabaofoundation.com -fabiao.com -fabiao.net -fabiaoqing.com -fabientech.com -fabigbig.com -fabu114.com -faburuanwen.com -facai1000.cc -facang.com -face100.net -face2ai.com -faceboer.com -facecloud.net -faceh5.com -facehufu.com -faceid.com -faceplusplus.com -facer.me -faceu.mobi -faceu.net -faceui.com -faceunity.com -facri.com -factj.com -factube.com -fad123.com -fadada.com -fadaren.com -fadedream.com -fadesky.com -fadfunds.com -fadianying.com -fadior.cc -fadsc.com -fadui.com -fafa9.com -fafa986.com -fafaku.com -fafawang.com -fafeng.com -fafuli.com -fafulou.com -fagaoshi.com -fageka.com -fagua.net -fahai.com -fahao8.com -fahraj.com -faidev.cc -faidns.com -faioo.com -faipod.com -fairso.com -fairyever.com -fairygui.com -fairysoftware.com -fairytest.com -faisco.com -faisys.com -faithlyrics.com -faiusr.com -faiusrd.com -faiww.com -fajiayun.com -fajingsi.org -fajjj.com -faka.cat -fala114.com -faloo.com -famanoder.com -famecl.com -famen88.com -famens.com -famensi.com -famicn.com -famige.com -familykoloro.com -familylifemag.com -famiyou.com -famousnudelady.com -famulei.com -fan-lun.com -fan-xun.com -fan-yong.com -fan88.com -fanai.com -fanbey.com -fancai.com -fanchongling.com -fanchuanxiao.net -fancyapi.com -fancydsp.com -fancyecommerce.com -fandaojian.com -fandengds.com -fandian.com -fandongxi.com -fanfannet.com -fanfanwx.com -fanfou.com -fang.com -fang027.com -fang33.com -fang668.com -fang99.cc -fang99.com -fangbaoqiang.net -fangbei.org -fangbianle.com -fangbx.com -fangcang.com -fangchan.com -fangchan0573.com -fangchanhz.com -fangchip.com -fangcloud.com -fangcs.net -fangdaijisuanqi.com -fangdaijisuanqi.net -fangdd.com -fangdede.com -fangdichanceo.com -fangdr.com -fangfa.net -fangfaku.net -fangfanwang.com -fanghaizhizao.com -fanghaofang.com -fanghouguo.com -fanghuafu.com -fanghuihui.com -fanging.com -fangjia.com -fangjiadp.com -fangjial.com -fangjs.com -fangkebao.cc -fangkeduo.net -fangketong.net -fangkewang.com -fangkuaitang.com -fangkuaiwang.com -fangkuaiyi.com -fangle.com -fanglimei.com -fanglist.com -fanglitong.com -fangmou.net -fangniaowang.net -fangqk.com -fangshanzi.com -fangshuigongcheng.net -fangshuitan888.com -fangsi.net -fangstar.com -fangtan007.com -fangtangtv.com -fangte.com -fangtingzfc.com -fangtoo.com -fangtoon.com -fangtuwang.com -fangtw.com -fangtx.com -fangwei315.com -fangweima.com -fangwuzaixian.com -fangxia979.com -fangxiaoer.com -fangxin.com -fangxinbao.com -fangxinmai.com -fangxinzhuomian.com -fangxuela.com -fangyb.com -fangyi.com -fangying.tv -fangyou.com -fangyouquan.com -fangyuan365.com -fangyuhui.com -fangyunlin.com -fangzd.com -fangzhipeng.com -fangzhizao.com -fangzhur.com -fangzongguan.com -fanhai-hk.com -fanhai8.com -fanhaobai.com -fanhaoyue.com -fanhonghua.net -fanhougame.com -fanhuan.com -fanhuan.org -faniuwenda.com -fanjian.net -fanjian8.com -fanjianhome.com -fanjinyan.com -fanli.com -fanli001.net -fanlibang.com -fanlibei.com -fanlicome.com -fanligame.com -fanlihe.com -fanlijinfu.com -fanlika.com -fanlisaas.com -fanlitou.com -fanmugua.net -fannaojiputi.com -fanpaimm.com -fanpusoft.com -fanqiang.com -fanqianzhushou.com -fanqie.im -fanqier.com -fanqiesoq.com -fanqietuan.com -fanqieui.com -fanqievv.com -fanqiewin10.com -fanquanba.com -fanquanwang.com -fanque.cc -fanren8.com -fanrenshucheng.com -fanruan.com -fans1.com -fans580.com -fans8.com -fansgu.com -fanshicekong.com -fanshuapp.com -fanshui.net -fanshuvideo.com -fanshuxiaobao.com -fanshuxiaozu.com -fansiji.com -fansimg.com -fansjoy.net -fansoon.com -fansx.com -fansyes.com -fantablade.com -fantaiai.com -fantanggame.com -fantatech.com -fantawild.com -fante.com -fanten123.com -fantizi5.com -fantong.com -fanuchdf.com -fanw8.com -fanwe.com -fanwen118.com -fanwenbaike.com -fanwenq.com -fanwenvip.com -fanxian.com -fanxiang.com -fanxiangds.com -fanxianke.com -fanxiaojian.com -fanxihui.com -fanxing.com -fanxuefei.com -fany-eda.com -fany-online.com -fanyantao.com -fanyeda.com -fanyedu.com -fanyeong.com -fanyi.com -fanyibase.com -fanyigou.com -fanyigou.net -fanyijia.com -fanyiqi.net -fanyishang.com -fanypcb.com -fanyu.com -fanyueciyuan.info -fanyuip.com -fanzehua.com -fanzhiyang.com -fapharm.com -fapiao.com -fapiao365.com -fapiaobang.com -fapiaoxx.com -faqrobot.org -faqwork.com -far123.com -far2000.com -fareastcontainers.com -farenhui.com -farennews.com -farerdak.com -farisl.com -farll.com -farmkd.com -farmsec.com -farpop.com -farsee2.com -fashaoyou.net -fasheng.org -fashengba.com -fashionhn.com -fashuounion.com -fasionchan.com -fast.im -fast8.com -fastadmin.net -fastapi.net -fastcdn.com -fastcname.com -fastdo.cc -fastgit.org -fastgz.com -fastidea.cc -fastidea.me -fastio.tech -fastmirror.org -fastmis.com -fastmovie88.com -fastmyna.com -fastreportcn.com -fastsoc.com -fastwebcdn.com -fat999.com -fatedier.com -fateqq.com -fatiao.pro -fatiaoyun.com -fatiaoyun.vip -fatjiong.com -fatkun.com -fatmouse.xyz -fatong9.com -fatsoon.com -fatvg.com -favdeb.com -favolist.com -favopen.com -favorites.ren -faw-benteng.com -faw-mazda.com -faw-vw.com -fawaitui.com -fawan.com -fawen8.com -fawjlqx.com -fawulu.com -fawuzaixian.com -fax52.com -faxdns.com -faxeye.com -faxindai.com -faxingchina.com -faxingcn.com -faxingnet.com -faxingshuo.com -faxingsj.com -faxingtp.com -faxingtupian.com -faxingzhan.com -faxiufang.com -faxsun.com -faxuan.net -fayea.com -fayifa.com -fayiyi.com -fayurumen.com -fazhijx.com -fazj.org -fb.mu -fb111.com -fbaba.net -fbabi.com -fbaichuan.com -fbicdn.com -fblife.com -fboae.com -fbook.net -fbuy365.com -fbxslw.com -fc0531.com -fc0633.com -fc12319.com -fc2.red -fc2live.pw -fc571.com -fc811.com -fcachinagsdp.com -fcai.com -fcbox.com -fcchbj.com -fccnj.com -fccook.com -fccs.com -fcczp.com -fcg51.com -fcgsnews.com -fcgtt.com -fcheche.com -fcjob88.com -fcloudpaas.com -fcnes.com -fcpiao.com -fcrc114.com -fcsjw.com -fcvvip.com -fcxjiuyuan.com -fcxxh.org -fcyhw.com -fcz360.com -fczx.com -fd-trust.com -fd167.com -fd597.com -fd7c.com -fdb713.com -fdc0760.com -fdcing.com -fdcyun.com -fdczbstatic.com -fdeent.org -fdemo.com -fdevops.com -fdjyw.com -fdjzu.com -fdkjgz.com -fdkm88.com -fdlly.com -fdlt.net -fdmgj.com -fdpx.com -fdqh360.com -fds.so -fdsr.org -fduky.com -fdzq.com -fe-cable.com -fe2x.cc -fe520.com -fearlazy.com -feaye.com -febug.com -fecable-gz.com -fecmall.com -fecn.net -fecshop.com -fedte.cc -feeclouds.com -feedou.com -feedsky.com -feedss.com -feeey.com -feehi.com -feekr.com -feelcars.com -feelchat.net -feelcode.net -feelec.net -feeliu.com -feemoo.com -feemoo.vip -feepan.com -feerbook.com -feesoon.com -feeyan.com -feeye.com -feeyeah.com -feeyo.com -feeyun.com -fegine.com -fegirl.com -feheadline.com -fei123.com -fei580.com -feiair.com -feibaojianshen.com -feibaokeji.com -feibisi.com -feibisi.org -feibit.com -feibo.com -feichangzhuan.com -feicool.com -feicui168.com -feicuiedu.com -feicuiwuyu.com -feidee.com -feidee.net -feidieshuo.com -feidm.com -feidou.com -feie.work -feierlaiedu.com -feifanblog.com -feifandesign.com -feifantxt.net -feifanwangg.com -feifei.com -feifeiboke.com -feifeicms.co -feifeixitong.com -feiffy.cc -feifustudio.com -feige.ee -feigedaojia.com -feigesp.com -feihu.me -feihuo.com -feihutaoke.com -feiin.com -feijizu.com -feikanu.net -feikongbao.com -feiku.com -feiliao.com -feiliks.com -feiliu.com -feillie.com -feilong.me -feilu.cc -feilvway.com -feimalv.com -feimanzb.com -feimao666.com -feimaojiasu.com -feimaoyun.com -feimosheji.com -feiniao.name -feiniaomy.com -feiniu.com -feiniubus.com -feinno.com -feinongbaike.com -feiphp.com -feipin.com -feiq18.com -feiren.com -feisan.net -feisu.com -feiteng.la -feitian001.com -feitianwu7.com -feitsui.com -feiwan.net -feixiaoquan.com -feixin2.com -feixiong.tv -feixuege.com -feixueteam.net -feiyangedu.com -feiyicheng.com -feiyiproxy.com -feiyit.com -feiyng.com -feiyu.com -feiyuapi.com -feiyuemu.com -feiyuhk.com -feiyuteam.com -feizan.com -feizao.tv -feizhaojun.com -feizhu.com -feizl.com -felearn.com -feling.net -felink.com -felix021.com -femba.net -femrice.com -fenbaner.net -fenbeijinfu.com -fenbi.com -fenbi8.com -fenbishufa.com -fenby.com -fencescn.com -fenduotie.com -fenfen.com -fenfenchaquan.com -fenfenriji.com -fenfenwz.com -fenfenzh.cc -feng.com -feng1.com -fengakj.com -fengbao.com -fengbaowo.com -fengbuy.com -fengcheco.com -fengchedm.com -fengchizixun.com -fengchj.com -fengchuanba.com -fengchusheng.com -fengcms.com -fengcx.com -fengdu.com -fengdzq.com -fengedu.com -fengeek.com -fengex.com -fengfeng.cc -fengfly.com -fenggeba.com -fenghenever.com -fenghuaju.cc -fenghuangxs.com -fenghui.tv -fenghuidongman.com -fenghuoyunji.com -fengiling.com -fengimg.com -fengj.com -fengji.me -fengji.net -fengjing.com -fengjr.com -fengjunzi.com -fengkongcloud.com -fengkuangzaoren.com -fengkui.net -fengli.com -fengli.su -fenglinjiu.com -fengmanginfo.com -fengmaniu.com -fengmi.tv -fengmi128.com -fengmk2.com -fengniao.com -fengniaocaijing.com -fengniaohuanjing.com -fengniaojr.com -fengniaosearch.com -fengone.com -fengqiangboy.com -fengqiyc.com -fengqu.com -fengqucdn.com -fengread.com -fengshangweekly.com -fengshui22.com -fengshui22.net -fengsung.com -fengtai.tv -fengtalk.com -fengting.io -fengtouwang.com -fengup.com -fengwanyx.com -fengwenyi.com -fengwo.com -fengxianghuawu.com -fengxianrc.com -fengxiaotx.com -fengxuan.co -fengyan.cc -fengyitong.name -fengyiyi.com -fengyu.cc -fengyuncx.com -fengyunlive.com -fengyunpdf.com -fengyunzhibo.com -fengyushan.com -fengyx.com -fengzhangame.net -fengzhiyuanseal.com -fengzigame.com -fengzixbs.com -fenha.net -fenking.club -fenlei168.com -fenlei265.com -fenleidao.com -fenleitong.com -fenliu.net -fennessy.hk -fenq.com -fenqianbang.com -fenqihome.com -fenqile.com -fenqix.com -fenqubiao.com -fens.me -fensebook.com -fenshua123.com -fensishenghuo.com -fensui168.com -fenxi.cc -fenxi.com -fenxi.org -fenxiangdashi.com -fenxianglife.com -fenxiaoba.net -fenxiuyun.com -fenxiyi.com -fenxuekeji.com -fenxw.com -fenying.net -fenyu.net -fenyucn.com -fenzhi.com -fenzijr.com -feotech.com -fequan.com -ferlie.net -fersese.com -fescoadecco.com -fescogroup.com -festaint.com -fetiononline.com -fetionpic.com -feverassets.net -fevte.com -feydj.com -ff54.ink -ff63.com -ff8828.com -ffan.com -ffasp.com -ffbtas.com -ffcell.com -ffdns.net -ffeeii.com -ffepower.com -fffzgh.com -ffhre.com -ffis.me -ffmarket.com -ffmulu.com -ffpedia.com -ffpic.com -ffpic.net -ffplay.net -ffquan.com -ffsgame.com -ffsky.com -fft123.com -ffxiv.xin -ffyd8.com -ffyinxiang.com -ffzy8.com -fg.cc -fghi34.com -fgidna.com -fgkj.cc -fgo.wiki -fgowiki.com -fgvisa.net -fh1551.com -fh21static.com -fh77.com -fh77.net -fh86.com -fhadmin.org -fhd001.com -fhdjh.com -fhdq.net -fhg90.com -fhhgj.com -fhkioskmodules.com -fhldns.com -fhlun.com -fhlyou.com -fhmion.com -fhoverseas.com -fhrlw.com -fhtlw.com -fhyx.com -fhyx.hk -fi94.com -fiberhome.com -fiberhomegroup.com -fibocom.com -fibodata.com -fibrlink.net -fidding.me -fiehff.com -fieldschina.com -fiery-data.com -fifsky.com -figoc.pw -fiiimg.com -fiinote.com -fiio.net -filcochina.com -file001.com -filediag.com -filetender.net -fillersmart.com -fillseo.com -films666.com -fim34s.com -fimmu.com -fimvisual.com -finacerun.com -finalshares.com -finaltheory.me -financeun.com -financial-trading-platform.com -financiers.cc -finansbankservices.net -finbtc.net -finchain.info -finchina.com -finctive.com -finderweb.net -findhro.com -findic.com -findic.kr -findic.tw -findic.us -finditandzip.ga -findlawimg.com -findme.wang -findoout.com -findshank.com -findshu.net -findxk.com -findyou.xin -findzd.com -finebi.com -fineidc.com -finer2.com -finereport.com -finereporthelp.com -finetopix.com -finetopix.net -fineui.com -fineway.com -finger66.com -fingerstylechina.com -fingertc.com -fingu.com -fingu.net -finlayliu.com -finndy.com -finogeeks.com -fintechinchina.com -fintechquan.com -finupfriends.com -finupgroup.com -finzfin.com -finzjr.com -fiphoenix.com -fir.im -fir.vip -fire233.com -fire2333.com -firebase-settings.crashlytics.com -firebirdprint.com -fireemblem.net -fireemulator.com -fireflyacg.com -firefoxbug.com -firefoxcn.com -firekylin.org -firemail.wang -firetry.com -firhq.com -firoyang.org -firstdrs.com -firstfood-cn.com -firstgw.com -firstheartbeat.net -firstlinkapp.com -firstp2p.com -firstproduction.net -firstrow-sports.com -firstsolver.com -fis3.com -fish2bird.com -fish3000.com -fish960.com -fishapi.com -fishcn.com -fisherac.com -fishing-sinkers.com -fishingbar.net -fishingjoy.com -fishings.biz -fishjava.com -fishlee.net -fishquant.com -fit-start.co -fit-time.com -fitnesspingtai.com -fitoneapp.com -fiuchina.com -fivestarsolar.com -fixsub.net -fiyta.com -fj-atfz.com -fj-ci.com -fj-jm.com -fj007.com -fj10010.com -fj173.net -fj263.com -fj96336.com -fj987.com -fjacg.com -fjanlian.com -fjba.xyz -fjber.com -fjbfan.com -fjbgwl.com -fjccdn.net -fjcesuo.com -fjcoop.com -fjcqjy.com -fjcyl.org -fjdaily.com -fjdh.com -fjdnf.com -fjeca.com -fjfoxiang.com -fjgdwl.com -fjgwy.org -fjhaode.com -fjhrss.com -fjhuazhou.com -fjhun.com -fjhxbank.com -fjhxcaee.com -fjii.com -fjjcjy.com -fjjmnh.com -fjjsp01.com -fjjsrckj.com -fjjszg.com -fjjyt.net -fjjyxny.com -fjlh.com -fjly.com -fjmlh.com -fjmstc.com -fjmwjx.com -fjnacc.com -fjndwb.com -fjnet.com -fjnjl.net -fjotic.com -fjpta.com -fjreading.com -fjsdfz.org -fjsdn.com -fjsen.com -fjsfa.org -fjsjs.com -fjsnhd.org -fjtelecom.com -fjtgyxa.vip -fjtn.com -fjtv.net -fjty1688.com -fjutu.com -fjvs.org -fjxisuzi.com -fjxn.com -fjybt.com -fjycw.com -fjyy.org -fjzfrc.com -fjzixun.com -fjzol.com -fjzprx.com -fk100.com -fk2019.com -fkblog.org -fkcaijing.com -fkdmg.com -fkdxg.com -fkesfg.com -fkjie.com -fktong.com -fkw.com -fkw100.com -fkxxyz.com -fkyuer.com -fkyun.com -fl-game.net -fl0632.com -fl168.com -fl365.com -fl5.co -fl78.com -fla38.com -flac.today -flac123.com -flachina.com -flacro.me -flamesky.org -flaredup.com -flash127.com -flash8.net -flash8f.com -flashempire.com -flashgame163.com -flashgene.com -flashget.com -flashgoing.com -flashmemoryworld.com -flashv8.com -flashwar.com -flashwing.net -flashye.com -flashyl.com -flatshare365.com -flduo.com -flexifont.com -fleyun.com -flgwx.com -flidc.net -fliggy.com -fliggy.hk -flintos.com -fliplinux.com -fliplus.com -flmjx.com -flnet.com -flnetiot.com -flooc.com -floorb2b.com -florentiavillage.com -floverow.com -flow.ci -flowbet365.com -flower-med.com -flower188.com -flower33.com -flowerpassword.com -flowever.net -flowportal.com -floyou.com -flpsz.com -flsnow.net -flstudiochina.com -fltacn.com -fltau.com -fltrp.com -fluke-ig.com -flutterchina.club -flvcd.com -flvsp.com -flvurl.net -flxc.net -flxdns.com -fly086.com -fly1999.com -fly3949.com -fly63.com -flyacat.com -flybridal.com -flyco.com -flycode.co -flycua.com -flydigi.com -flyenglish.com -flyert.com -flyertea.com -flyertrip.com -flyfish8.com -flyfishx.com -flyfood.name -flyfunny.com -flygon.net -flyguest.com -flyine.net -flyme.com -flymeos.com -flyml.net -flymobi.biz -flympu.com -flypy.com -flysnow.org -flytexpress.com -flyxg.com -flyym.com -flyzen.com -flyzy.com -flzc.com -flzhan.com -flzsdq.com -fm0754.com -fm120.com -fm4399.com -fm520.com -fm918.net -fm960.net -fmbimg.com -fmcoprc.gov.mo -fmeibao.com -fminers.com -fmketang.com -fmpan.com -fmsh.com -fmtol.com -fmttr.com -fmwei.com -fmwhahaha.com -fmy90.com -fn-mart.com -fn-tech.com -fn.com -fnetlink.com -fnf-foods.com -fngz01.com -fnji.com -fnjiasu.com -fnjsq.com -fnkq.com -fnmz.com -fnnsh.com -fnrcw.com -fnysb.com -fnzoo.com -fnzw.com -fo12.com -fob123.com -fobshanghai.com -focalhot.com -fochot.com -focus-eloan.com -focuschina.com -focussend.com -fodang.org -fodian.net -fodizi.com -fodlab.com -fodoco.com -fogangtong.com -fogtowerblog.com -fohee.net -fokan88.com -folieyun.com -folkw.com -foloda.com -folou.com -fomen123.com -foneplatform.com -fongmong.com -fonrex.com -fonsoft.net -fonsview.com -font.im -font168.com -font5.com -font6.com -fontke.com -fonts.googleapis.com -fonts.gstatic.com -foodbk.com -foodjx.com -foodmate.net -foods1.com -foodspace.net -foodszs.com -foodu14.com -foodzhan.net -fooher.com -foojoo.com -fookwood.com -fookyik.com -fooleap.org -foolyun.com -foooooot.com -fooww.com -for-compass.com -for-she.com -for512.com -for68.com -forbeschina.com -forbest.site -forbetty.com -forbugs.net -forbuyers.com -forcemz.net -ford.com -fordgo.com -forenose.com -forerunnercollege.com -foreseamall.com -foresl.com -forestfood.com -forestpest.org -forestpolice.org -forestsguardians.com -forevercd007.com -foreveross.com -forga.me -forgame.com -forgotfun.org -forindata.com -forjs.net -forlinx.com -forlinx.net -form-create.com -formtalk.net -formysql.com -fornature.com -forrealbio.com -forrerri.com -forsigner.com -forsou.com -forthxu.com -fortiortech.com -fortunebill.com -fortunevc.com -foryougroup.com -fos.cc -foscam.com -foshanaosibo.com -foshanmuseum.com -foshannet.com -foshannews.com -foshannews.net -fosss.org -fosun-uhi.com -fosun.com -fotao.name -fotao9.com -fotilestyle.com -foto8.net -fotomore.com -fotoplace.cc -fotosay.com -fototuan.com -fotuozhengfa.com -foufu.com -fouleide.com -founder.com -founderbn.com -foundercentury.com -foundereagle.com -founderff.com -founderfu.com -founderic.com -founderinternational.com -founderit.com -founderpcb.com -founderpod.com -foundersc.com -foundersz.com -foundertech.com -foundertype.com -founderuc.com -foundgame.com -foundpdf.com -founei.com -founpad.com -fountask.com -four00.com -fovmy.com -fox-studio.net -fox008.com -fox163.com -fox688.com -fox800.xyz -foxbeen.com -foxconn.com -foxera.com -foxmail.com -foxphp.com -foxtable.com -foxweixin.com -foxwho.com -foxwq.com -foxzw.com -foyuan.net -fpdisplay.com -fpgabbs.com -fpgall.com -fpgaw.com -fphis.com -fphs5.com -fpliu.com -fps7.com -fpsv.com -fpwap.com -fpzw.com -fq-china.com -fq.mk -fq597.com -fqapps.com -fqgj.net -fqis.xin -fqjyxx.com -fql.cc -fqpai.com -fqriji.com -fqsou.com -fqsszx.com -fqxs.org -fqzww.com -fr-odc.samsungapps.com -fr-trading.com -fr2007.com -fr8npi.com -fractal-technology.com -francissoung.com -francochinois.com -frankorz.com -frankway.net -franzsandner.com -frbao.com -frdic.com -fread.com -free-api.com -free-e.net -free-eyepro.com -free.mk -free789.com -freebsdchina.org -freebuf.com -freecls.com -freecplus.net -freed.ga -freedgo.com -freegeeker.com -freehome25.net -freehpcg.com -freeibook.com -freeidea.win -freejishu.com -freekaobo.com -freekeyan.com -freelycode.com -freemancn.com -freemerce.com -freemindworld.com -freemoban.com -freemojo.com -freeoa.net -freeqingnovel.com -freericheyes.com -freeshoppingchina.com -freessl.org -freetstar.com -freetvro.com -freeuid.com -freewhale.net -freexs.org -freeydch.com -freeyun.com -freezl.net -frensworkz.com -freqchina.com -fresh-ideas.cc -freshhema.com -freshnewsnet.com -frhelper.com -friendeye.com -friendlyvote.com -fright-tattoo.com -fringe-zero.com -friok.com -fristlvy.com -frjie.com -frkq.com -frlh168.com -fro14.com -froggy.link -frombyte.com -fromgeek.com -fromhomelearn.com -fromwiz.com -frontenddev.org -frontjs.com -frontopen.com -frontwize.com -frostwell.cc -frostwell.net -frostwing98.com -fruitday.com -frysb.com -frytea.com -fs-ade.com -fs.microsoft.com -fs0757.com -fs121.com -fs12330.org -fs23.com -fs234.com -fs31.com -fs315.org -fs7000.com -fsacn.com -fsaligzf.com -fsbankonline.com -fsbus.com -fsc555.com -fscinda.com -fsclzs.com -fsdhub.com -fsecity.com -fsehome.com -fsesa.com -fsgejian.com -fshd.com -fshzg.com -fsigc.com -fsjiaju.com -fsjoy.com -fskmp.com -fsky.pro -fsldwy.com -fslgz.com -fsllq.com -fslsg.com -fslwpq.com -fsmama.com -fsmeeting.com -fsmy88888.com -fsoptronics.com -fspage.com -fspcdn.com -fsq3626.com -fssfs.com -fsshenneng.com -fsswrl.com -fstcb.com -fswdgc.com -fswl66.com -fsxchina.com -fsxdwy.com -fsxsj.net -fsymltc.com -fsysb.com -fsyule.net -fszhjx.com -ft12.com -ft22.com -ftaro.com -ftbj.net -ftcauction.com -ftfast.com -ftfxgame.com -ftium4.com -ftnormal00ab.com -ftnormal00ak.com -ftnormal01as.com -ftoul.com -ftqq.com -ftrsit.com -ftsafe.com -ftsfund.com -ftsm-vip.com -ftt.me -ftuan.com -ftxad.com -ftxgame.com -ftxsoccer.com -ftxzq.com -ftzn.net -ftzsino.com -fu57.com -fubi8.com -fuchaoqun.com -fuckingdata.com -fudaiapp.com -fudanglp.com -fudanmed.com -fudannb.org -fudanpress.com -fudian-bank.com -fuduoduozy.com -fuedf.org -fufamy.com -fufeng-group.com -fufuok.com -fugetech.com -fugui.net -fuhai360.com -fuhancapital.com -fuhanziben.com -fuhao123.com -fuhaodaquan.org -fuhaoku.com -fuhaozi.com -fuheng.org -fuhuibao.club -fui.im -fuimg.com -fuiou.com -fuioupay.com -fujiabin.com -fujianlaser.com -fujianqq.com -fujianrc.com -fujieace.com -fujinli.com -fujunjie.com -fuka.cc -fukebi.com -fukun.org -fulantv.com -fulevmy.com -fuli.la -fuli1024.com -fuli404.net -fuliansheng.com -fuliao.com -fuliapps.com -fuliba2020.net -fulibbs.com -fulibest.com -fulichao.com -fulifb8.com -fulijd.com -fulimin.org -fulin.org -fulinedu.com -fuling.com -fulingwx.com -fuliti.com -fuliw.net -fuljk.com -full-way.com -fullstack.love -fulu.com -fumake.com -fuman8.net -fumu.com -fumubang.com -fumuhui.com -fun.tv -fun48.com -funchat.cc -fund001.com -fundebug.com -fundebug.net -fundog.cc -fundoy.com -fundrive.com -funeralchain.com -funfungolf.com -funinput.com -funiutang.net -funjsq.com -funletu.com -funliving.com -funmovie.cc -funnulldns.com -funnycore.com -funnypicsbox.com -funnyplaying.com -funshion.com -funshion.net -funshipin.com -funtoygame.com -funvge.com -funwear.com -funxun.com -funyqq.com -fupiaopifa.com -fuqian.la -fuqiangw.com -furongcaifu.com -furongedu.com -furrychina.com -furuijiaju.vip -fus158.com -fusaide.com -fusion.design -fusroda.io -fute.com -futu5.com -futuhk.com -futuku.com -futuniuniu.com -futunn.com -futureengineer.org -futureprize.org -futurescircle.com -futurescn.net -fututrade.com -fuwa.org -fuwaliuxue.com -fuwit.com -fuwo.com -fuwuce.com -fuwuhao.cc -fuwuqinet.com -fuwuqu.com -fuxiaohei.me -fuxinbank.com -fuxing56.com -fuxingtech.com -fuxingwang.com -fuyangseo.com -fuyangtv.com -fuych.net -fuyinchina.com -fuyinzm.com -fuyou888.com -fuyoubank.com -fuyoukache.com -fuyuan5.com -fuyuandian.com -fuyuncc.com -fuyuncun.com -fuyundata.com -fuyuzhe.com -fuz.cc -fuzamei.com -fuzangtang.com -fuzeetech.com -fuzegame.com -fuzhimao.com -fuzhongvisa.com -fuzhugo.com -fuzihao.org -fv99.com -fview.com -fvti.com -fw-biotech.com -fw4.co -fw4.me -fwcdn.com -fwcdn.net -fwdns.net -fwdq.com -fwdq.net -fwdqw.com -fwjia.com -fwmob.com -fwqbdn.com -fwqtg.net -fwqzx.com -fwsir.com -fwtoys.com -fwxgx.com -fwzjia.com -fx120.net -fx168.com -fx168api.com -fx168vip.com -fx273.com -fx3q.com -fx678.com -fx678.net -fx678red.com -fx968.com -fxbaogao.com -fxcccbbs.com -fxclass.net -fxcns.com -fxcsxb.com -fxdiv.com -fxdm.net -fxdp.com -fxeye.com -fxian.org -fxiaoke.com -fxingw.com -fxk8.com -fxlbb.com -fxlim.com -fxltsbl.com -fxmoe.com -fxo2opt.com -fxpan.com -fxsw.net -fxtiyu.com -fxtrip.com -fxtrips.com -fxw.la -fxwfx.com -fxwst.com -fxxkmakeding.xyz -fxxss.com -fxxw.net -fxxww.net -fxxz.com -fxyibai.com -fxzbr.com -fxzhj.com -fxzhjapp.com -fxzpfyy.com -fxzxgs.com -fxzygc.com -fy-data.com -fy-game.com -fy-ns.com -fy-team.com -fy027.com -fy169.net -fy558.com -fy98.com -fybiji.com -fybooks.com -fybxw.com -fycarto.com -fychinago.com -fychs.com -fydeos.com -fydisk.com -fydmodel.com -fydns360.net -fydongxiang.com -fydqw.com -fyeds0.com -fyeds1.com -fyeds2.com -fyeds3.com -fyeds4.com -fyeds5.com -fyeds6.com -fyeds7.com -fyeds8.com -fyeds9.com -fyfch.com -fygame.com -fygdrs.com -fygsoft.com -fyigou.com -fyjsz.net -fyktaqm.com -fynas.com -fynews.net -fyq99.com -fyrcbk.com -fyrexian.com -fyrwzz.com -fysjlogo.com -fysns.com -fytcw.com -fytxonline.com -fytz.net -fyuanpack.com -fywx.cc -fyzku.com -fz0512.com -fz173.com -fz222.com -fz2sc.com -fz597.com -fz80h.com -fzbm.com -fzbqk.com -fzbtv.com -fzccpit.org -fzcyjh.com -fzdeng.com -fzdmag.com -fzengine.com -fzf.com -fzfanyi.com -fzfapp.com -fzfzjx.com -fzg360.com -fzita.com -fzithome.com -fzjxw.com -fzl7.com -fzlft.com -fzlol.com -fzlu.com -fzmama.net -fzn.cc -fzpig.com -fzqcbz.com -fzrsrc.com -fzshbx.org -fzsjob.com -fzswy.com -fztxylgy.com -fzwcn.com -fzxiaomange.com -fzxyyqd.com -fzyfan.com -fzyfan.net -fzyfs.net -fzzfwz.com -fzzrlh.com -g-emall.com -g-film.com -g-photography.net -g-tu.com -g-var.com -g12345.com -g12e.com -g168.net -g188.net -g1c5.com -g1d.net -g1f5.com -g2.link -g207.com -g2b2b.com -g2g1.com -g2h3.com -g2us.com -g312.com -g32365.com -g3d.org -g3img.com -g3user.com -g5f4.com -g5h4.com -g72.com -g7430.com -g77775555.com -g77776666.com -g88885555.com -g88886666.com -g8f8.com -ga0.me -ga25.com -gaapqcloud.com -gabiplay.com -gac-capital.com -gac-nio.com -gacfca.com -gacfcasales.com -gacfiatauto.com -gachoplatvietnam.com -gack.citic -gaclib.net -gacmotor.com -gacsofinco.com -gaeamobile.net -gafata.com -gafei.com -gaga.me -gagaga.tech -gagahi.com -gagalee.ink -gaiamount.com -gaibar.com -gainda.net -gainet.com -gaingreat.com -gaini.net -gainscha.com -gaitu.com -gaitu8.com -gaituba.com -gaitubao.com -gaitubao.net -gaituxiu.com -gaixue.com -gaizhui.com -galaxix.com -galaxy-immi.com -galaxyappstore.com -galaxyasset.com -galaxyfont.com -galaxyinfo.com -galaxymacau.com -galaxyns.net -galeo.me -galgame.cc -galgame.net -galgamez.cc -galgamez.com -galiaoba.com -gallopgazelle.com -galstars.net -galsun.com -galudisu.info -gamdream.com -game-as.com -game-coder.com -game-props.com -game-reign.com -game-yx.com -game100.wiki -game1126.com -game12315.com -game13.com -game141.com -game189.com -game2.com -game333.net -game345.com -game3vs7novel.com -game4343.com -game5.com -game5399.com -game5iw.com -game798.com -game900.com -game9198.com -game9g.com -gameabc.com -gameabc2.com -gamebar.com -gamebbm.com -gamebean.com -gamebean.net -gamebee.net -gamebto.com -gamecomb.com -gamecps.com -gamed9.com -gamedashi.com -gameditu.com -gameegg.com -gameexp.com -gamefk.com -gamefm.com -gamefv.com -gamehome.tv -gamehui.com -gameinns.com -gamekee.com -gameloveman.com -gamemei.com -gameol.com -gamepf.com -gamept.com -gamerboom.com -gameres.com -gamerey.com -gamerhome.net -gamerlol.com -gamermake.com -gamersky.com -gamerstorm.com -gamescl.com -gameservice.com -gamesh.com -gamesifu.com -gamesir.com -gametanzi.com -gametaptap.com -gametea.com -gamethk.com -gametrees.com -gamevvip.com -gamewifi.net -gamexdd.com -gamexhb.com -gamexz.com -gameyj.com -gamfe.com -gammatimes.com -gamo2.com -gamutsoft.com -gamux.org -gan-ren.com -ganggeban123.com -ganggg.com -ganghaowang.com -gangjuw.com -gangpaibao.com -gangpiaoquan.com -gangqinpu.com -gangzai.online -ganhuoche.com -ganhuodaquan.com -ganji.com -ganjiangrc.com -ganjistatic1.com -ganjistatic2.com -gank-studio.com -gankgames.com -gankh5.com -ganlv.org -ganlvji.com -ganniu.com -ganopolymall.com -ganqi.com -ganqi.net -gansdai.com -ganso.net -gansuci.com -gansunet.com -gansupost.com -gansuyunshi.com -ganxi666.com -ganxianw.com -ganxiu.com -ganzhe.com -ganzhishi.com -gao3d.com -gao4.com -gao7.com -gao7gao8.com -gaobata.com -gaobei.com -gaobo.name -gaocegege.com -gaochengnews.net -gaochun.info -gaodabio.com -gaodage.com -gaodalei.com -gaode.com -gaodilicai.com -gaoding.com -gaoduanqianzheng.com -gaodugj.com -gaodun.com -gaodunwangxiao.com -gaofangcache.com -gaofeib2c.com -gaofeie.com -gaofen.com -gaofenplatform.com -gaoguai.com -gaoguang.com -gaogulou.com -gaohaipeng.com -gaohangip.com -gaohr.com -gaoimg.com -gaoji.ren -gaojianli.me -gaojie.com -gaojinbo.com -gaokao.com -gaokao365.com -gaokao789.com -gaokaobaoming.com -gaokaohelp.com -gaokaopai.com -gaokaoq.com -gaokaozhiku.com -gaokeyan.com -gaokw.com -gaokzx.com -gaolouimg.com -gaomaomao.com -gaomeig.com -gaomeluo.com -gaoming.city -gaomon.net -gaonengfun.com -gaopaiwood.com -gaopeng.com -gaoqing.la -gaoqing500.com -gaoqingpai.com -gaoqiwenda.com -gaoqixhb.com -gaore.com -gaosan.com -gaosboy.com -gaoshou.me -gaoshouvr.com -gaoshouyou.com -gaosiedu.com -gaosivip.com -gaosouyi.com -gaosu.com -gaosudu.com -gaotang.cc -gaotie.net -gaotieshike.com -gaotu006.club -gaotu100.com -gaowenya.com -gaoxiao88.net -gaoxiaobang.com -gaoxiaojob.com -gaoxiaotu.com -gaoxiaovod.com -gaoxin123.com -gaoxinbao.xyz -gaoxinkc.com -gaoyizaixian.com -gaoyj.com -gaoyong666.com -gaoyoujob.com -gaoyuan.xyz -gaoyun.cloud -gaoyuyuan.com -gaoyy.com -gaozeyuan.com -gaozhiip.com -gaozhongwuli.com -gaozhouba.com -gap.hk -gapitech.com -gara.cc -garden-aquarium.com -gardencn.com -garmuri.com -garnoc.com -garphy.com -garply.com -gas-analyzers.com -gasfw.com -gasgoo.com -gashr.com -gasshow.com -gaszx.com -gate-dhgames.com -gateface.com -gatefanyi.com -gatewang.com -gather-dns.com -gaussianoptics.com -gavindesign.com -gaxrmyy.com -gb-ceo.com -gbase8a.com -gbasebi.com -gbdex.com -gbgba.com -gbhome.com -gbiac.net -gbicdn.com -gbicom.com -gbin1.com -gblhgk.com -gblj365.com -gbofd.com -gboooo.com -gbpjam.com -gbsou.com -gbtags.com -gbtranswins.com -gbw114.com -gc-0511.com -gc-repair.com -gc-zb.com -gc1616.com -gc39.com -gc5.cc -gc600.com -gccdn.net -gcchina.com -gccmgw.com -gcgd.net -gch5game.com -gchao.com -gche8.com -gcihotel.net -gcimg.net -gcjc.com -gcjr.com -gcjx123.com -gcloudcs.com -gcloudgbs.com -gcloudsdk.com -gclxry.com -gcmc.cc -gcoreinc.com -gcores.com -gcstorage.com -gcsz.net -gcyts.com -gczp.cc -gczx.cc -gczyg.com -gd-china.com -gd-id.com -gd-linux.com -gd-linux.org -gd1580.com -gd165.com -gd2000.org -gd32.com -gd3n.com -gd520520.com -gda086.com -gdadjs.com -gdadri.com -gdajie.com -gdatacube.net -gdbljd.com -gdbyhtl.net -gdccsc.com -gdcct.com -gdcic.net -gdcom.wang -gdcoop.com -gdcrj.com -gdcts.com -gdctsvisa.com -gdcx.net -gdcyl.org -gddarf.com -gddata.net -gddg.cc -gdebidding.com -gdefair.com -gdems.com -gdevops.com -gdforestry.com -gdfplaza.com -gdgcep.com -gdggkf.com -gdgudong.com -gdgwyw.com -gdgzhp.com -gdh198.com -gdhaoma.com -gdhbsh.com -gdhouqin.com -gdhy0668.com -gdie.com -gdimmi.com -gdinfo.net -gdiso.com -gdjdxy.com -gdjinge.com -gdjn.org -gdjyw.com -gdkaman.com -gdkepler.com -gdkjb.com -gdkszx.com -gdkz88.com -gdlins.com -gdlppow.com -gdmappress.com -gdmingshizx.com -gdmm.com -gdmoa.org -gdmschina.com -gdmseduol.com -gdmuseum.com -gdmxjy.com -gdong.com -gdou.com -gdpanshi.com -gdpycy02.com -gdqynews.com -gdrc.com -gdrc360.com -gdrc365.com -gdrcu.com -gdrfyy.com -gds-services.com -gdscse.net -gdscw.com -gdsoq.com -gdspeedtest.com -gdsports.net -gdsrcw.com -gdssl.image-gmkt.com -gdstlab.com -gdswine.com -gdsxgd.com -gdszjgdj.org -gdtai.com -gdtex.com -gdtextbook.com -gdtimg.com -gdtnio.com -gdtone.com -gdtrafficad.com -gdtravel.com -gdttc.com -gdtz888.com -gdunis.com -gdupi.com -gdvolunteer.net -gdwca.com -gdwlife.com -gdwxmz.com -gdxgt.com -gdxxb.com -gdxy6.com -gdyjs.com -gdysdz.com -gdyxc.com -gdzhishen.com -gdzhlh.com -gdzhongshan.com -gdzj8.com -gdzp.org -gdzrch.win -gdzs2018.cc -gdzs2018.vip -gdzsxx.com -gdzt56.com -gdztck.com -gdzxtm.com -gdzypx.org -gdzzz.com -ge-garden.net -ge100.com -ge95.com -geakr.com -geapu.com -gearkr.com -gearton.com -geautos.com -gebi1.com -gebilaoshi.com -gebiqu.com -gec-sc.com -gec123.com -gecidao.com -gecimi.com -geciwang.net -gedou8.com -gedoumi.com -gedu.org -geeboo.com -geeboodata.com -geebook.com -geebookservice.com -geedai.com -geedu.com -geeetech.com -geeeu.com -geejing.com -geek-docs.com -geek-era.com -geek-papa.com -geek-share.com -geek-workshop.com -geekbang.org -geekbangtech.com -geekcar.com -geekdigging.com -geekdream.com -geekercloud.com -geekerconsulting.com -geekersq.cc -geekfans.com -geekhub.com -geekiron.com -geekjc.com -geekluo.com -geekmaker.com -geekman.vip -geekmar.xyz -geekniu.com -geekori.com -geekotg.com -geekpark.net -geekpie.club -geekpie.org -geekpie.tech -geekpwn.org -geeks.vc -geeksblog.cc -geektutu.com -geeku.net -geekwom.com -geekxue.com -geekzu.org -geely.com -geement.com -geeqee.com -geermunews.com -geesee.com -geeseteam.com -geetest.com -geewaza.com -geexek.com -geeyep.com -geezn.com -gegejia.com -gegeyingshi.com -geicloud.com -geihuasuan.com -geihui.com -geilicdn.com -geilijiasu.com -geimian.com -geindex.com -geiniwan.com -geishost.com -geisnic.com -geitu.net -geizan.cc -gejian.net -gejiawen.com -gelics.com -gelonghui.com -gelu.me -gemchina.com -gemdale.com -gemenwan.com -gemgsx.com -gemii.cc -gemini-galaxy.com -gemini530.net -geminight.com -gempay.com -gempoll.com -genban.org -gendantong.com -genekong.com -genesis2013.com -geneskies.com -genetalks.com -geneworldcn.com -gengnie.com -gengwen.net -geniatech.com -genrace.com -genscript.com -gensee.com -genshuixue.com -gentags.com -gentags.net -genymotion.net -genzhuang.org -geo-prism-cn.htcsense.com -geo-prism.htcsense.com -geo.kaspersky.com -geo2k.com -geogsci.com -geohey.com -geoidc.com -georgiaskater.com -geospatialsmart.com -geotmt.com -gepresearch.com -gepush.com -gequ77.com -gequdaquan.net -geren-jianli.com -gerenjianli.com -gerhard-china.com -germany-leica.net -geroinv.com -geruihuate.com -gesanghua.org -gesep.com -geshannet.com -geshui.com -geshui100.com -geshuishuilvbiao2017.com -gesuo.com -get.vip -get233.com -getbingo.net -getbs.com -getcn.net -gethover.com -getiis.com -getip.name -getkwai.com -getlema.com -getmarkman.com -getquicker.net -getqujing.com -getsurfboard.com -getteamyi.com -getui.com -getui.net -getuikit.net -getulab.com -getyii.com -gewai-cnc.com -gewala.com -gewara.com -gewu.vc -gexiao.me -gexing.com -gexing.me -gexings.com -gexingshuo.com -gexingzipai.com -geyan123.com -geyanw.com -geyo.com -geyoukj.com -gezhixq.net -gezida.com -gezila.com -gf-funds.com -gf.cc -gfan.com -gfanstore.com -gfbhgz.com -gfcdn.xyz -gfcvisa.com -gfd178.com -gfdns.net -gfdsa.net -gfedu.com -gffirm.com -gffwq.com -gfglb.com -gfgupiao.com -gfieo.com -gfjl.org -gfmz.com -gfnormal01ac.com -gfnormal01aq.com -gfnormal02ak.com -gfnormal03ab.com -gfnormal03aj.com -gfnormal04ac.com -gfnormal04ad.com -gfnormal04ar.com -gfnormal06aa.com -gfnormal07ak.com -gfnormal07ar.com -gfnormal07at.com -gfrtrttweet.com -gftuan.com -gfun.me -gfund.com -gfvip00ao.com -gfvip04af.com -gfvip05ad.com -gfvip07ap.com -gfvip08ad.com -gfvip08ao.com -gfvip08ar.com -gfvip09ac.com -gfvip09aj.com -gfvip09an.com -gfvip09aq.com -gfvip09at.com -gfxaa.com -gfxcamp.com -gfxiong.com -gfxtr1.com -gfxy.com -gfzj.us -gg-ev.com -gg-lb.com -gg-led.com -gg1994.com -gg8828.com -ggac.net -ggcida.com -ggcj.com -ggcykf.com -ggda365.com -ggdawanjia.com -ggdoc.com -ggemo.com -ggeye.com -ggfacai.com -gggjs.com -gginza.com -ggj88.com -ggjrw.com -ggjstz.com -gglenglish.com -ggmm777.com -ggmmqq.com -ggmovie.net -ggmzy1.com -ggo.la -ggo.net -ggpeixun.com -ggqule.com -ggqx.com -ggsafe.com -ggvnsr.com -ggwan.com -ggxt.net -ggxxe.com -ggytc.com -ggyum.com -ggyy8.cc -ggzgg.com -ggzuhao.com -gh.com -gh5e.vip -gh6.org -gh6j.com -gh8s.com -ghatg.com -ghboke.com -ghdhair.cc -ghflv.com -ghgy.com -ghgy.net -ghmba.com -ghmcchina.com -ghmp4.com -gho5.com -gholover.com -ghost008.com -ghost11.com -ghost123.com -ghost64.com -ghostchina.com -ghostsf.com -ghostw7.com -ghostwin10.net -ghostwin7.net -ghostxp2.com -ghostxp6.com -ghostxpsp3.com -ghostxpsp3.net -ghostxx.com -ghpym.com -ghrlib.com -ghs.net -ghsmpwalmart.com -ght.me -ghui.me -ghzhushou.com -ghzs.com -ghzs666.com -giabbs.com -giaimg.com -giant-cycling-lifestyle.com -giantcdn.com -gibcp.com -giccoo.com -gicp.net -giexya.com -gif-china.cc -gif5.net -gifcool.com -giffox.com -gifhome.com -gifhub.cc -gifmiao.com -gifms.com -gifshow.com -giftsbeijing.com -gifttu.com -gifu-pr.com -gifxu.com -giga-da.com -gigabyte.com -gigaget.com -giiso.com -giitu.com -gildata.com -gilieye.com -gillsonglobal.com -giltbridge.com -giltworld.com -gimcyun.com -gimhoy.com -gimmgimm.com -gimoo.net -gio.ren -giocdn.com -gionee.com -gionee.net -giordano.com -giraff3.com -girlbt.com -girls-frontline.com -girlw.net -giscafer.com -giser.net -giserdqy.com -gispark.com -gissaas.com -gissky.net -git-star.com -gitbook.net -gitcafe.net -gitee.com -gitee.io -githang.com -github-trending.com -githubmemory.com -gitissue.com -gitlib.com -gitlore.com -gitmemory.com -gitnavi.com -gitnoteapp.com -gitnova.com -gitos.net -gitsea.com -gitv.tv -gityuan.com -giuem.com -giveda.com -giveme5.cc -giyu8.com -gizwits.com -gj0479.com -gj2car.com -gj515.com -gj5s.com -gjalk.com -gjb9001b.com -gjbaek.ren -gjcdn.vip -gjceshi9.com -gjfax.com -gjggad.com -gjgov.com -gjgwy.net -gjgwy.org -gjgzpw.com -gjhwzjw.com -gjjcxw.com -gjjgb.com -gjjnhb.com -gjmrcp.com -gjnk5858.com -gjnlyd.com -gjpdh.com -gjtjjp.com -gjw.com -gjw123.com -gjxh.org -gjyoulun.com -gjyys.com -gjzy.com -gjzzpt.com -gk-net.com -gk-z.com -gk.link -gk027.com -gk114.com -gk99.com -gkbbapp.com -gkdgz.com -gkeydoor.com -gkjnet.com -gkkxd.com -gkmotor.com -gkong.com -gkoudai.com -gkpass.com -gkshuju.com -gkstk.com -gktianshanjd.com -gkwo.net -gkxd.com -gkzhan.com -gkzj.net -gkzxw.com -gl-data.com -gl-inet.com -gl258.com -glab.online -glab2018.com -glabuy.com -glailia.com -glamever.com -glamourred.com -glanimaltrade.com -glanu.com -glasseasy.com -glawyer.net -glb6.com -glbdns.com -glbdqn.com -glcanyin.net -glcct.com -gldtztc.com -gleasy.com -glface.com -glgczk.com -glgoo.com -glgoo.net -glgoo.org -glike.me -glinfo.com -gljmx.com -gljrkj.com -gljuji.xyz -gllue.com -gllue.me -glmama.com -glmapper.com -glmei.net -global-download.acer.com -global-harbor.com -global-jf.com -globalaccentchinese.com -globalbuy.cc -globalcompressor.com -globaldangdang.hk -globaletrust.com -globalflyingmagazine.com -globalhardwares.com -globalimporter.net -globalizex.com -globalmarket.com -globalmil.com -globalpingbao.com -globalscanner.com -globalsign.com -globalsigncdn.com -globalsources.com -globalstech.com -globeauto.org -globeedu.com -globeimmi.com -globepv.com -globrand.com -globrand.net -glodon.com -glofang.com -glorymobi.com -gloryre.com -gloryview.com -glorze.com -glosspp.com -glqh.com -glshimg.com -gltattoo.com -gltjk.com -gltop.com -glvs.com -glxlawyer.com -glyh.org -glzhuang.com -glzip.com -glzj88.com -glzy8.com -gm016.com -gm193.com -gm2007.com -gm825.com -gm86.com -gm88.com -gm99game.net -gmacsaic.com -gmail-cn.com -gmanhua.com -gmb2b.com -gmcc.net -gmcchina.net -gmdun.com -gmecity.com -gmed.cc -gmem.cc -gmem.site -gmgc.info -gmgcongress.com -gmgdc.com -gmgm668.com -gmhysj.com -gmilesquan.com -gming.org -gmiot.net -gmjk.com -gmm01.com -gmmicro.com -gmmsj.com -gmopce.com -gmrmyy.com -gmssl.org -gmt-china.org -gmtv.cc -gmwuf.com -gmz88.com -gn00.com -gn168.com -gn666.com -gnaixx.cc -gname-dns.com -gndaily.com -gnehr.com -gnetis.com -gnhpc.com -gnrcbank.com -gnss.help -gnssinfo.com -gnssopenlab.org -gnvip.net -gnway.com -go-gddq.com -go-goal.com -go.cc -go007.com -go0931.com -go2050.com -go24k.com -go2aaron.com -go2eu.com -go2hn.com -go2map.com -go2tu.com -go2uk.info -go2yd.com -go300.com -goalan.net -goaldetails.com -goalhi.com -goalmobi.com -goapk.com -gobanma.com -gobelike.net -gobivc.com -gocam.so -gocarjourney.com -gocea.net -goceshi.com -gocheck.net -gochego.com -gocn.vip -god51.com -godaily.org -godasai.com -godbach.com -godbiao.com -godblessyuan.com -goddelivery.com -goddessxzns.com -godeve.com -godic.net -godida.com -godiscoder.com -godiy8.com -godloveworld.com -godo.pub -godoor.com -godotdotdot.com -godpan.me -godrry.com -godruoyi.com -godsheepteam.com -godsignal.com -godwolf.com -goeasy.io -goepe.com -goertek.com -goflipped.net -goframe.org -gogbuy.com -gogo-le.com -gogo.so -gogo123.com -gogoauc.com -gogobids.com -gogofly.com -gogojiang.com -gogolinux.com -gogooffer.com -gogopzh.com -gogoqq.com -gogoup.com -gohighfund.com -goho.co -gohoedu.com -gohom.win -gohomesafe.org -gohong.com -gohugo.org -going-link.com -gojiaju.com -goke.com -gokols.com -gokuai.com -golang.so -golang123.com -golangapi.com -golangcaff.com -golanger.com -golangfoundation.org -golangtc.com -golangweb.com -golaravel.com -gold-v.com -gold58.com -gold600.com -gold678.com -gold8818.com -goldapple.name -goldav.net -goldbj.com -goldbox.vip -golden-book.com -golden-infor.com -goldenad.net -goldendoc.org -goldenholiday.com -goldenhome.cc -goldenname.com -goldentom.com -goldgrid.com -goldhoe.com -goldke.com -goldlvshi.com -goldmantis.com -goldmarkrealestate.com -goldtoutiao.com -golf568.com -golfchinese.com -golfvv.com -golink.com -golinksworld.com -golive-tv.com -golivetv.tv -golomber.com -golue.com -gomeart.com -gomecloud.com -gomegj.com -gomeholdings.com -gomehome.com -gomeplus.com -gomesell.com -gomo.com -gonever.com -gong123.com -gongbaike.com -gongboshi.com -gongchang.com -gongchengbing.com -gongchengshi.org -gongchou.com -gongfubb.com -gongfuworld.com -gongguan96.com -gongheshengshi.com -gongjianglaile.com -gongjiao.com -gongjiaomi.com -gongju.com -gongju5.com -gongjuji.net -gongjumi.com -gongkong.com -gongkong001.com -gongkongbpo.com -gongkongedu.com -gongkongke.com -gongkongmall.com -gongl8.com -gonglin91.com -gongmutang.com -gongnou.com -gongpin.net -gongpingjia.com -gongshang120.com -gongshe8.com -gongshe99.com -gongshi8.com -gongsibao.com -gongsijiaoyi.com -gongsizhijia.com -gongtingxiang.com -gongwuxing.com -gongxiangcj.com -gongxiao8.com -gongxinbang.com -gongxuku.com -gongye360.com -gongyeku.com -gongyelian.com -gongyeyun.com -gongyicn.org -gongyijijinhui-info.com -gongyingshi.com -gongyishibao.com -gongyixiang.com -gongzhong.me -gongzhonghaozhushou.com -gongzi.org -gongzicp.com -gongzifu.com -gongzuoshouji.net -gongzuoyun.org -gonsun.com -gonvvama.net -gonxhn.com -goo17.com -gooagoo.com -gooann.com -good-display.com -good-fine.com -good-import.com -good.cc -good1230.com -good321.net -goodaiai.com -goodapk.com -goodapp.net -goodbaby.com -goodbabygroup.com -goodbaike.com -gooddr.com -gooddu.com -goodealwigs.com -goodera8.com -goodev.org -goodgupiao.com -goodid.com -goodix.com -goodjd.com -goodjili.com -goodjzjg.com -goodlucknet.com -goodnas.net -goodnic.net -goodprogrammer.org -goodrain.com -goods-brand.com -goodstudydayup.com -goodtp.com -goofish.com -google-analytics.com -googleadservices.com -googleadsl.com -googleanalytics.com -googlebridge.com -googlefonts.net -googlesyndication.com -googletagmanager.com -googletagservices.com -googlevip8.com -googlevoice.org -googleyixia.com -googpc.com -goojer.com -goolink.org -goolpter.com -gooo8.com -gooooal.com -goooob.com -gooood.hk -goootech.com -goootu.com -goosai.com -goosail.com -gooseeker.com -goosetalk.com -gooxi.com -gooyo.com -goozp.com -gopedu.com -gopherchina.org -gopiaowu.com -goplaycn.com -goplayervideo.com -gopojie.net -gorichox.com -gorouter.info -gorse.com -goryun.com -gosanye.com -goshijia.com -gosinoic.com -gospelwin.com -gosuncdn.com -gosunm.com -goten.com -gotocdn.com -gotodn.com -gotohz.com -gotohzrb.com -gotoip.net -gotoip1.com -gotoip11.com -gotoip2.com -gotoip3.com -gotoip4.com -gotoip55.com -gotojp.net -gotokeep.com -gotonav.com -gotonets.com -gotooback.com -gotoubi.com -gotozhuan.com -gotran.com -gotvg.com -gou.com -gou898.com -gouai.com -goubanjia.com -goubibei.com -gouchezj.com -goufang.com -goufq.com -gougoujp.com -gougousc.com -gougoutxt.com -gouhai.com -gouhaowang.com -gouhuasuan.shop -goukuai.com -goulew.com -goulong.com -goumin.com -gounahaozi.org -goupuzi.com -gouso.com -gousu.com -goutanzi.com -gouwanmei.com -gouwu002.com -gouwubang.com -gouwuke.com -gouwumai.com -gouwuwang988.com -gouwuyu.com -govmade.com -gow100.com -gowa.club -gowan8.com -goweb2.net -goweb3.net -gowincms.com -gowinlease.com -gowinxp.com -gowithmi.com -goyihu.com -goyoo.com -goyouhuima.com -gozap.com -gp-cdn.net -gp-tm.com -gp1903.com -gp1907.com -gp1908.com -gp1909.com -gp1910.com -gp241.com -gp259.com -gp451.com -gp51.com -gp88888.com -gp891.com -gpai.net -gpautobid.com -gpbeta.com -gpcgd.com -gpcqjy.com -gpcxw.com -gpd.hk -gpdi.com -gper.club -gpio.me -gpl-express.com -gplayspace.com -gplqdb.com -gpnewtech.com -gppapp.com -gps8.com -gpshk.cc -gpslook.net -gpsoo.net -gpsspg.com -gpsuu.com -gpticket.org -gpxxz.com -gpxygpfx.com -gpxz.com -gpzbs.com -gqak.com -gqblinds.com -gqgkj.com -gqhmt.com -gqjd.net -gqk.tv -gqm168.com -gqooh.com -gqqsm.com -gqsoso.com -gqt168.com -gqtpw.com -gqzctsj.com -gqzyz.com -gqzzw.com -grablan.com -grabsun.com -gracece.com -gracg.com -gradaimmi.com -gradgroup.com -gradgroup.net -grainedu.com -grainstorage.net -gran.work -grandinsight.com -grandomics.com -grapchina.org -graphene.tv -graphmovie.com -graueneko.xyz -gray-ice.com -grcbank.com -grchina.com -gre.vip -greatbit.com -greatopensource.com -greatops.net -greatsk.com -greatssp.com -greatstartools.com -greatwalldns.com -gree-jd.com -gree.com -greebox.com -greedland.net -green-android.org -green12306.com -greenbodhi.com -greenchengjian.com -greencompute.org -greendh.com -greenhtml.com -greenhua.com -greenism.net -greenkoo.com -greenlandsc.com -greentomail.com -greenxcx.com -greenxf.com -greenxf.net -gretf.com -greycdn.net -greyli.com -greytech.org -grfy.net -grfyw.com -grg2013.com -grgbanking.com -grge23.com -grgits.com -grgsecurity.com -grgvision.com -grgyintong.com -gridsum.com -gridsumdissector.com -gridy.com -grieom.com -grikin.com -grinm.com -grirem.com -grmxdy.com -gro2004.com -gro2005.com -groad.net -groovyfilmes.com -grouk.com -group-purchasing.com -group.citic -groupjx.com -grouplus.com -growingio.com -grt-china.com -gruntjs.net -grvape.com -grxjgc.com -gryu.net -grzmz.com -gs-loc-cn.apple.com -gs-loc.apple.com -gs.ww.np.dl.playstation.net -gs14.com -gs2.ww.prod.dl.playstation.net -gs265.com -gs307.com -gsadds.com -gsbankchina.com -gsbankmall.com -gsbug.com -gscaijing.com -gscidc.net -gsdayu.com -gsdk.tv -gsdlcn.com -gsflcp.com -gsgs10086.com -gshhqy.com -gsi24.com -gsjie.com -gsjindu.com -gsjtky.com -gsjy.net -gsktraining.com -gskyty.com -gslxrc.com -gsmpers.com -gsmyi.com -gsnyjszg.com -gsp10-ssl-cn.ls.apple.com -gsp11-cn.ls.apple.com -gsp12-cn.ls.apple.com -gsp13-cn.ls.apple.com -gsp4-cn.ls.apple.com -gsp4-cn.ls.apple.com.edgekey.net -gsp4-cn.ls.apple.com.edgekey.net.globalredir.akadns.net -gsp5-cn.ls.apple.com -gsp85-cn-ssl.ls.apple.com -gspcc.com -gspe19-cn-ssl.ls.apple.com -gspe19-cn.ls-apple.com.akadns.net -gspe19-cn.ls.apple.com -gspe21-ssl.ls.apple.com -gspe21.ls.apple.com -gspe35-ssl.ls.apple.com -gsqx.com -gsrecv.com -gsrskw.com -gss-sh.org -gssfgk.com -gsstaf.com -gst-china.net -gstarcad.com -gstdt.com -gston.cc -gstonegames.com -gsxcdn.com -gsxiongjian.com -gsxservice.com -gsxtj.com -gsxzq.com -gsyuanquan.com -gszhuli.com -gszlyy.com -gszph.com -gt-oil.com -gt-semi.com -gt520.com -gta5sb.com -gtadata.com -gtags.net -gtan.com -gtanhao.com -gtaxqh.com -gtcedu.com -gtcim.com -gtdlife.com -gtdstudy.com -gter.net -gtfund.com -gtgres.com -gtibee.com -gtimg.com -gtja-allianz.com -gtja.com -gtjadev.com -gtjaqh.com -gtjazg.com -gtk2.com -gtlrxt.com -gtm-a1b2.com -gtm-a1b4.com -gtm-a2b3.com -gtm-a2b6.com -gtm-a3b1.com -gtm-a4b4.com -gtm-a4b8.com -gtm-a4b9.com -gtm-a5b4.com -gtm-i1d6.com -gtm-i1d9.com -gtm.oasisfeng.com -gtmlufax.com -gtn9.com -gtnqk.com -gto365.com -gtobal.com -gtobal.net -gtshuwu.com -gtshy.com -gttof2020.com -gttxidc.com -gtuu.com -gtxp2.com -gtzy123.com -gtzyb.com -gu166.com -gu360.net -guabu.com -guaguazs.com -guahao-inc.com -guahao.com -guahaoe.com -guahaowang.com -guaiguai.com -guaihaha.com -guaihaha.net -guaihou.com -guaikemov.com -guaili.org -guailuo.com -guainiuwang.com -guaiwei.com -guaiwola.com -guaixun.com -guajibao.club -guajibao.me -guajibaola.com -guajob.com -guakaoba.com -guan5.com -guanaitong.com -guanchangcun.com -guanchao.site -guandan.com -guandang.com -guandang.net -guandata.com -guandongphoto.com -guandongyucang.com -guang.com -guangbo.net -guangchangwu.net -guangchilieche.com -guangdauser.com -guangdiu.com -guangdongchuangke.com -guangfeng.com -guanggao.com -guanggoo.com -guanggu100.com -guanggua.com -guanghe.tv -guanghuayigou.com -guangjiaohui888.com -guangjie5u.com -guangjiela.com -guangka.com -guangkatf.com -guangli88.com -guanglunshiji.com -guangminggame.com -guangmingjx.com -guangsuss.com -guangwaifu.com -guangwangye.com -guangweihui.com -guangxigrc.com -guangxindai.com -guangxiyou.com -guangyaguang.com -guangyinglvxing.com -guangyuai.com -guangyv.com -guangzhitui.com -guangzhou-logistics.com -guangzhou-marathon.com -guanhuaju.com -guanjia2.com -guanjiajf.com -guanjianfeng.com -guankou.net -guanli360.com -guanli66.com -guanlixinli.com -guanmeikj.com -guannews.com -guannin.com -guanplus.com -guanqifeier.com -guanshangsq.com -guanshangyu.cc -guanshi.net -guanshuzw.com -guantaicn.com -guanting.com -guanvip8.com -guanwang.com -guanwangdaquan.com -guanwangyun.com -guanwawa.com -guanxiaokai.com -guanyiyun.com -guanyuanjs.com -guanzhongrc.com -guanzhu.mobi -guanzhulian.com -guapaijia.com -guardrailchina.com -guazhuan.com -guazi-apps.com -guazi.com -guazipai.com -guazistatic.com -guazixs.com -gubaw.com -gubo.net -gubo.org -gucciblog.net -gucheng.com -gucn.com -gucun.info -gucunpark.net -gudaiba.com -gudaovision.com -gudi.cc -guer.org -guestops.com -gufeiposuiji.com -gufengge.org -gufengmh.com -gufengmh8.com -guge.tw -gugeanzhuangqi.com -gugeapps.com -gugeapps.net -gugexs.com -gugong.net -gugooe.com -gugu.ws -gugu5.com -gugud.com -guguread.com -gugutown.com -guguyu.com -guguzhu.com -guhai66.com -gui333.com -gui66.com -guibi.com -guibook.com -guibuyu.org -guidaye.com -guidechem.com -guiderank-app.com -guiderank.org -guifun.com -guigu.org -guiguzhongguo.com -guiheyue.com -guihua.com -guihuayun.com -guiji.com -guijianghu.com -guijinshu.com -guikeyun.com -guilin.la -guilinhd.com -guilinlife.com -guilintravel.com -guimengning.com -guimi.com -guimilu.com -guimimianbao.cc -guimipay.net -guipp.com -guisd.com -guisheng.li -guitarchina.com -guitarpro.cc -guixue.com -guizeco.com -guizheng.net -guizhoujindu.com -gujianba.com -gujianzhixiang.com -gujibook.com -gujiushu.com -gukaifu.com -gukaihu.com -gukun.com -gulandscape.com -guleji.com -gullmap.com -gulltour.com -gulou120.com -gulu.tv -gulu001.com -gulugj.com -gulujie.com -gulutea.com -gumang.com -gumaor.com -gumei88.com -gumo.pro -gunfans.net -gunfixer.com -guntian.com -guo.com -guo7.com -guo98.com -guoanaz.com -guoanqi.com -guoanshequ.com -guoaso.com -guobencoffee.com -guobensd.com -guobiao99.com -guoboshi.com -guocaiqinghai.com -guocuijingju.com -guodafdc.com -guodegang.org -guodingnet.com -guodu.com -guodu.hk -guofen.com -guofenchaxun.com -guofenchaxun.net -guofenz.com -guoguo-app.com -guohanlawfirm.com -guohead.com -guohuapharm.com -guojieba.com -guojimami.com -guojinbao.com -guojing-tech.com -guojixuexiao.org -guojixumu.com -guojj.com -guojucloud.com -guojusoft.com -guokr.com -guokr.io -guokr.net -guoku.com -guolaiwanba.com -guoli.com -guoliangjie.com -guolianglab.org -guolin.tech -guoluonews.com -guoluzaiju.com -guolv.com -guomai.cc -guomii.com -guopc.com -guopeiwang.com -guopengliang.com -guopi8.com -guopika.com -guoping123.com -guopu.cc -guoqinwang.com -guorongfei.com -guoruiinfo.com -guoruijx.com -guoshi.com -guoshudq.com -guotaifilm.com -guotv.com -guowaidiaocha.com -guowaitianqi.com -guoxingjun.com -guoxinqh.com -guoxue.com -guoxue123.com -guoxuecc.com -guoxuedashi.com -guoxuejiaoyuwang.com -guoxuemeng.com -guoxuemi.com -guoxuwang.com -guoyang.cc -guoyb.com -guoyice.com -guoyitangtt.com -guoyu.com -guozeyu.com -guozh.net -guozhihua.net -guozhivip.com -guozhongxin.com -guozi.org -guozi.tv -guoziyx.com -gupaoedu.com -gupei.com -gupen.com -gupiao111.com -gupiao135.com -gupiao3.com -gupiao8.com -gupiaowajue.com -gupiaozhidao.com -gupowang.com -gupt.net -guqiankun.com -guqiu.com -guqu.net -gurudigger.com -gush88.com -gushequ.com -gushfx.com -gushi.ci -gushi.com -gushicimingju.com -gushidaquan.cc -gushimi.org -gushiwen.org -gusiyuan.com -gusuwang.com -gutianfood.com -gutou.com -gutouwang.net -gutun.net -guwan.com -guweimin.com -guwenxs.com -guwu121.com -guxiaobei.com -guxunw.com -guyidai.com -guyiyangsd.com -guyuenglish.com -guyungame.com -guzaosf.com -guzhangting.com -guzhifengds.com -guzhiwang.com -guziyy.com -guzzservices.com -gvi-tech.com -gvlocalization.com -gw-ec.com -gw2field.com -gw2sc.com -gw8888.com -gwamcc.com -gwapi.net -gwauto.com -gwclouds.net -gwdang.com -gwell.cc -gwidc.com -gwj-test.com -gwm-global.com -gwmfc.com -gwmsoft.com -gworg.com -gwoversea.com -gwylt.com -gwyoo.com -gwyou.com -gwypxw.com -gwyzk.com -gwzwfw.com -gx-newmedia.com -gx34.com -gx79.com -gx8899.com -gxaedu.com -gxaj.com -gxajk.com -gxar.com -gxb.io -gxb2b.net -gxbaidutg.com -gxbf.net -gxbys.com -gxbyw.com -gxc-coin.com -gxcards.com -gxcgw.com -gxcic.net -gxdahua.com -gxdmw.com -gxeqx.com -gxfdcw.com -gxfin.com -gxfxwh.com -gxganju.com -gxghtx.com -gxgkcat.com -gxh.cc -gxhl.com -gxhma.com -gxhouse.com -gxhxmy88.com -gxhzxw.com -gxiang.net -gxibvc.net -gxidc.com -gxind.com -gxit.online -gxjgdj.com -gxjtaq.com -gxjubao.org -gxjznet.com -gxkjbg.com -gxkjdns.com -gxkjec.com -gxkjjt.com -gxlcms.com -gxlxs2008.net -gxmenjin.com -gxmlyjy.com -gxmmkt.com -gxnas.com -gxnotes.com -gxp.cc -gxqcw.com -gxqs.org -gxrc.com -gxrwc.xyz -gxsell.com -gxshuairun.com -gxskm.com -gxsky.com -gxtodo.com -gxtstatic.com -gxw98.com -gxwmcu.com -gxwsxx.com -gxwztv.com -gxxgle.com -gxxiaotutu.com -gxxmyjs.com -gxycwy.com -gxylxtc.com -gxzhiwei.com -gxzjy.com -gxzmrl.com -gxzpw.org -gy-center.net -gy-fuji.com -gy.com -gy7n.com -gy818.com -gyb086.com -gycode.com -gydongli.com -gyersf.com -gyfmc.com -gyguohua.com -gyhj.org -gyip.net -gyljc.com -gymama.com -gymbo-online.com -gymsj.com -gymwen.com -gyncb.net -gynsh.net -gypserver.com -gyqcw.com -gyr.cc -gyrsq.com -gysk.com -gysou.com -gysq.org -gystatic.com -gytcwb.com -gytjz.com -gytsg.net -gytsjk.com -gytsm.com -gywlwh.com -gywygl.com -gyxdkjdl.com -gyxuan.com -gyypw.com -gyyqcloud.com -gyzfbz.net -gyzy.com -gyzyfw.com -gz-cmc.com -gz-cube.com -gz-data.com -gz-forever.com -gz-gz.com -gz-lodihair.com -gz-notary.com -gz-oe.com -gz-station.com -gz-test.com -gz007.net -gz121.com -gz12301.com -gz12333.com -gz300.com -gz360.com -gz4399.com -gz4u.net -gz5.com -gz528.com -gz91.com -gz9d.com -gzasp.net -gzate.com -gzaune.com -gzbaibian.net -gzbaozhilin.com -gzbfqx.com -gzbio.net -gzbmw.com -gzbpi.com -gzbsjg.com -gzcankao.com -gzcdns.com -gzchupai.com -gzcl999.com -gzcn.net -gzcppa.com -gzcycling.com -gzdai.com -gzdaily.com -gzdata.net -gzdbx.com -gzdingyu.com -gzdinuan.com -gzdirect.com -gzdsw.com -gzenxx.com -gzexpo.com -gzfangs.com -gzfga.cc -gzfilm.com -gzfsnet.com -gzfxkwl.com -gzgc120.com -gzgdwl.com -gzgjx99.com -gzguard12th.com -gzgxkj.com -gzhakj.com -gzhangcha.com -gzhaoxiang.net -gzhatao.com -gzhc365.com -gzhdcs.com -gzhhr.com -gzhhxxkj.com -gzhifi.com -gzhmi.com -gzhongyu020.com -gzhphb.com -gzhshoulu.wang -gzhtg.com -gzhtinfo.com -gzhuake.cc -gzhxpw.com -gzhzcj.com -gzhzgwyw.com -gzidc.com -gzif.net -gzittc.net -gzj568.com -gzjab.com -gzjcyuanlin.com -gzjingsha.com -gzjisikj.com -gzjpad.com -gzjqd.com -gzjtjx.com -gzjtjy.com -gzjunyu.com -gzjuqi.com -gzjzc.com -gzkz88.com -gzlc1688.com -gzlingli.com -gzliy.com -gzlug.org -gzlujiao.com -gzlz307.com -gzlzfm.com -gzmama.com -gzmath.com -gzmediaclick.com -gzmiyuan.com -gzmjhzs.com -gzmri.com -gzmtr.com -gzmxol.com -gzncstudios.com -gznemo.com -gznet.com -gzngn.com -gznote.com -gznwn.com -gznxbank.com -gznxcc.com -gzorsa.org -gzpeite.com -gzpinda.com -gzpma.com -gzpts.com -gzqiche.com -gzqiyuan.com -gzqunsheng.com -gzqwkj.com -gzqxxz.net -gzrishun.com -gzrmw.com -gzrobot.com -gzrobots.com -gzrsa.com -gzshandi.com -gzshangshan.net -gzshuaixin.com -gzshujuhui.com -gzsjyzx.com -gzsjzx.com -gzsmove.com -gzspeedtest.com -gzstv.com -gzsuiti.com -gzsums.net -gzsww.com -gzsy06.com -gzsy07.com -gzsyfk.com -gzszgas.com -gzszk.com -gztaiyou.com -gztcdj.com -gztfgame.com -gzthrc.com -gztopkt.com -gztour.org -gztv.com -gztwkadokawa.com -gztxedu.com -gzuc.net -gzuni.com -gzw.net -gzwanbao.com -gzwcds.com -gzwcjs.com -gzweicai.com -gzweix.com -gzwot.com -gzwrit.com -gzxcwsp.com -gzxdf.com -gzxf35.com -gzxftz.com -gzxhdyc.com -gzxiaopeng.com -gzxict.com -gzxszf.com -gzxtsg.com -gzxwtjy.com -gzycdy.com -gzyct.com -gzyeah.com -gzyitop.com -gzylxixin.com -gzyouai.com -gzysbpay.com -gzyszy.com -gzyucai.com -gzzbgs.com -gzzg.org -gzzhitu.com -gzzkzsw.com -gzzlfw.com -gzzoc.com -gzzongsi.com -gzzoo.com -gzzqy.net -gzzswy.com -gzzsxxw.com -gzzuwo.com -gzzy04.com -gzzy05.com -h-college.com -h-five.com -h-heguo.com -h-sea.net -h-ui.net -h-world.com -h0591.com -h0758.net -h0f.me -h1bz.com -h231.com -h2ero.com -h2ex.com -h2os.com -h2vm.com -h3c.com -h3c.com.hk -h3dns.net -h3ue2s.com -h3yun.com -h4.cc -h41s.com -h4399.com -h4kdxs.com -h5-page.net -h5-share.com -h5-x.com -h5.net -h5120.com -h51h.com -h5abc.com -h5aiwan.com -h5anli.com -h5app.com -h5avu.com -h5ay.com -h5data.com -h5ds.com -h5eco.com -h5gamecdn.club -h5in.net -h5jun.com -h5jw.com -h5king.com -h5ky.com -h5le.com -h5mc.com -h5mgd.com -h5mota.com -h5mugeda.com -h5no1.com -h5po.com -h5sg.com -h5shuo.com -h5tpl.com -h5uc.com -h5war.com -h5youxi.com -h6295.com -h6688.com -h6969.com -h6app.com -h7687.com -h7ec.com -h8jx.com -ha97.com -habadog.com -hac-ker.net -hacdn.com -hacdn.net -hack-cn.com -hack0nair.me -hack50.com -hack520.com -hack6.com -hackav.com -hackcn.net -hackdig.com -hackerav.com -hackernc.com -hackernews.cc -hackhome.com -hackhp.com -hackhw.com -hacking-linux.com -hacking8.com -hackline.net -hacknical.com -hackp.com -hackpascal.net -hackrf.net -hackroad.com -hackx.org -hacori.com -hacpai.com -haczjob.com -hadax.com -hadns.net -hadobi.com -hadsky.com -haers.com -haguan.com -haguotu.com -haguro.moe -haguworld.com -haha168.com -haha33.com -haha360.com -haha365.com -haha9911.com -hahack.com -hahadiaoyu.com -hahaha365.com -hahait.com -hahasou.com -hahawen.com -hahayouxi.com -hahour.com -hai0.com -haiall.com -haiana.com -haianbank.com -haianedu.net -haianw.com -haiaosheng66.com -haibao.com -haibaobaoxian.com -haibaoyl.com -haibaoyouxi.com -haibeinews.com -haibian.com -haibog.com -haiboinvest.com -haiboyi.com -haicent.com -haichufang.com -haicj.com -haidaibao.com -haidaoteam.com -haidaotrip.com -haidaozhu.com -haidii.com -haidilao.com -haidilao.net -haidilao.us -haidimao.com -haiduomi.cc -haienkj.com -haier.com -haier.hk -haier.net -haierubic.com -haieruplus.com -haierxue.com -haifangbest.com -haifeisi.com -haige.com -haigeek.com -haigui001.com -haiguime.com -haihaipin.com -haijia.org -haijiangzx.com -haijiaonet.com -haijincang.com -haijingfang.cc -haiketrip.com -hailiangip.com -haililiang.com -hailinzeng.com -hailiys.com -hailuowu.com -haima.me -haima001.com -haimawan.com -haimayisheng.com -haimazhuang.com -haimi.com -haimini.com -haina.com -hainachuan.org -hainan.com -hainan.net -hainan888.net -hainanairlines.com -hainancom.com -hainancp.com -hainandj.com -hainanfp.com -hainanfz.com -hainanjiuzi.com -hainanparadise.com -hainanpc.net -hainic.com -haining.tv -hainingnews.net -hainiubl.com -hainiuxy.com -hainuotech.com -hainvyy.com -haiqingyanyu.com -haiqisoft.com -haiqq.com -haiqukj.com -hair8.net -hairbobo.com -haireig.com -hairui.cc -hairunmedia.com -hairunpictures.com -haisapan.com -haisenyouxi8.com -haisheninfo.com -haishisheji.com -haishui.cc -haitaibrowser.com -haitaichina.com -haitang123.vip -haitao.co -haitao.com -haitao369.com -haitao8.com -haitaocheng.com -haitaohou.com -haitaoing.com -haitaoit.com -haitaoj.com -haitaolab.com -haitaopd.com -haitaoqq.com -haitaoseo.com -haitaoshen.com -haitaotong.com -haitaoyunfei.com -haitaozu.org -haitianhome.com -haitl.com -haitongjiaoyu.com -haitou.cc -haitou360.com -haitoucapital.com -haitoujia.com -haitum.com -haituncun.com -haitundr.com -haitunshenghuo.com -haituntui.com -haitunvoice.com -haitunwx.com -haituoqi.com -haitutech.com -haiwailoushi.com -haiwaimoney.com -haiwaituiguang.com -haiwaiyoujia.com -haiwanli.com -haiwanxinxi.com -haiweili.com -haiwen-law.com -haixia51.com -haixiahao.com -haixianlai.net -haixice.com -haixindichan.com -haixinews.com -haixiulive.com -haixiumv.com -haixiutv.com -haixiuvv.com -haixuan12.com -haixue.com -haixunpr.org -haixunw.com -haiyi701.com -haiyingku.com -haiyue.info -haiyuhe.com -haiyun.me -haiyunx.com -haiyusoft.com -haizhangs.com -haizhixing.net -haizhoumo.com -haizhuyx.com -haizihe.com -haizitong.com -hajjjc.com -haku77.com -halade.com -halaha.com -halffashion.com -halfrost.com -halidown.com -halixun.com -halloar.com -hallofix.com -hallotw.com -halobearing.com -halomobi.com -haluoha.com -hamanw.com -hambut.com -hampoo.net -han-cang.com -han-tang.cc -han66.com -hanamichi.wiki -hanbaiji.com -hanban.org -hanbaoying.com -hanboshi.com -hanchao9999.com -hancloud.com -hanclouds.com -hand-china.com -handage.com -handanjob.com -handanw.com -handanyz.com -handbb.com -handday.com -handdiy.com -handfunds.com -handian027.com -handikj.com -handone.com -handu.com -handuyishe.com -hanergy.com -hanergymobileenergy.com -hanfan.cc -hanfei.net -hanfengcars.com -hanfugong.com -hangge.com -hanghaimeng.com -hanghang666.com -hanghangcha.com -hangjiayun.com -hangkong.com -hangmeishangmao.com -hangmiwang.com -hangomart.com -hangowa.com -hangpu-topsys.com -hanguangbaihuo.com -hanguopai.com -hanguoyou.org -hanguozongyi.com -hangxinyiqi.xin -hangye114.net -hangyjx.com -hangzhiqiao.com -hangzhoufcw.com -hangzhoutianqi114.com -hanhai.net -hanhaiqikan.com -hanhande.com -hanhande.net -hanhuazu.cc -hanjianbing.org -hanjiaying.com -hanjie.biz -hanjjl.com -hanju.cc -hanjucc.com -hanjudao.com -hanjumi.net -hanjutiantang.com -hanjutv.com -hankewins.com -hanking.com -hankunlaw.com -hanlefang.net -hanlei.org -hanmadiancan.com -hanmaker.com -hanmanapp.com -hanmeilin.com -hannor.com -hanpinyuan.com -hanqiweb.com -hanshijiaoye.com -hanshow.com -hanshuliang.com -hansight.com -hansiji.com -hansme.com -hanspldata.com -hanspub.org -hansrobot.com -hansuku.com -hantang59.com -hantangrx.com -hantangxintong.com -hanterry.com -hantinghotels.com -hanvon.com -hanvonmfrs.com -hanvontouch.com -hanweb.com -hanweimetal.com -hanxinbank.com -hanxinsheng.com -hanyanseed.com -hanyi.studio -hanyou.com -hanyouwang.com -hanyucar.com -hanyuehui.site -hanyurumen.com -hanyutai.com -hanzhifeng.com -hanzhong123.com -hanzify.org -hanzigongfu.com -hao-sheng-yi.com -hao.ac -hao.wang -hao007.net -hao0202.com -hao120.cc -hao123-hao123.com -hao123.com -hao123.com.sg -hao123img.com -hao1258.com -hao163.com -hao168.cc -hao181.com -hao1970.com -hao1996.com -hao1cm.com -hao222.com -hao224.com -hao24.com -hao245.com -hao268.com -hao315.cc -hao315.com -hao315.tv -hao3399.com -hao360.com -hao378.com -hao394.com -hao568.com -hao6.com -hao61.net -hao661.com -hao695.com -hao6v.com -hao7188.com -hao753.com -hao76.com -hao86.com -hao8dai.com -hao9669.com -hao974.com -haoad.org -haoamc.com -haoayi.xyz -haobanyi.com -haobb360.com -haobiaoke.com -haobtc.com -haocai.com -haocai138.com -haocai1688.com -haocai777.com -haocax.com -haochali.cc -haochang.tv -haochangyou.com -haocheedai.com -haochi123.com -haochu.com -haodaibao.com -haodanku.com -haodaquan.com -haodeplus.com -haodevps.com -haodewap.com -haodewap.net -haodf.com -haodf.org -haodian8.com -haodiany.com -haodiaoyu.com -haodingdan.com -haodiy.net -haodns123.cc -haodou.com -haoduofangs.com -haoduorou.net -haoep.com -haoest.com -haofanben.com -haofangkankan.com -haofangyu.com -haofangyuan.net -haofaxing.com -haofenxiao.net -haofly.net -haofz.com -haogegebisai.com -haogj8.com -haogongzhang.com -haogoshop.com -haogow.com -haogu114.com -haohaizi.com -haohanfw.com -haohanguo.com -haohanseo.com -haohaotuan.com -haohaowan.com -haohaoxiu.com -haohaoyx.com -haohaozhu.com -haohaozhu.me -haohead.com -haohiyou.com -haohongfan.com -haoht123.com -haohtml.com -haohuan.com -haoii123.com -haoinvest.com -haoiyon.com -haoiyong.com -haoji.me -haojiameng.net -haojiaolian.com -haojiaolian.org -haojing.org -haoju55.com -haojuzi.net -haokan123.com -haokan5.com -haokan58.com -haokanbu.com -haokantu.com -haokanzhan.com -haokecheng.com -haokejie.com -haokoo.com -haoku.net -haolangtech.com -haolawyer.com -haole.com -haoleio.com -haolexiang.com -haolezen.com -haolietou.com -haolints.com -haoliv.com -haolizi.net -haolvlv.com -haolyy.com -haomagujia.com -haomaimrm.com -haomaishou.com -haomaiyi.com -haomaku.com -haomaotao.com -haomee.net -haomeili.net -haomijie.com -haomingr.com -haommn.com -haomou.net -haomove.com -haomugua.com -haonames.com -haonic.com -haonic.net -haonongzi.com -haopeixun.com -haopianw5.com -haopianyi.com -haopic.me -haopinku.com -haoq.tv -haoqiao.com -haoqicat.com -haoqikan.com -haoqixingstem.com -haoqq.com -haoqtv.com -haoqupu.com -haorc.com -haoread.com -haorencai.net -haorendao.com -haorooms.com -haoseals.com -haosenchina.com -haoservice.com -haosf.com -haosf5.com -haoshanxi.com -haoshengla.com -haoshengmall.com -haoshenqi.com -haoshetou.net -haoshici.com -haoshipin123.com -haoshiqi.net -haoshsh.com -haoshunjx.com -haosijia.com -haosijia.vip -haosix.com -haosou.com -haostay.com -haotb.com -haote.com -haotehui.com -haotianhuyu.com -haotihui.com -haotijin.com -haoting5.com -haotoufa.com -haotougao.com -haotougu.com -haotu.net -haotui.com -haotukankan.com -haotxt.com -haouc.com -haoux.com -haowa.com -haowaicaijing.com -haowandeni.com -haowangd.com -haowanyou.com -haoweiguang.me -haoweishow.com -haowen100.com -haoword.com -haowu.com -haowu.info -haowu.link -haowuyunji.com -haowuyx.com -haoxdai.com -haoxg.net -haoxiake.com -haoxiang.org -haoxipu.com -haoxitong.com -haoxiyou.com -haoxue.com -haoxuetang99.com -haoxxwang.com -haoxyx.com -haoyangmao8.com -haoychuang.com -haoyde.com -haoyhq.com -haoyisheng.com -haoyishui.com -haoyong.cc -haoyongapp.com -haoyongxitong.com -haoyouqian.com -haoyouyinxiang.com -haoyu.love -haoyuanxiao.com -haoyun13.com -haoyun56.com -haoyunbaike.com -haoyunbb.com -haoyuncn.net -haoyunma.com -haoyunmom.com -haoyy168.com -haozhai.com -haozhanhui.com -haozhebao.com -haozhegai.com -haozhexie.com -haozhuangji.com -haozhuodao.com -haozi.org -haozi.xyz -haozip.com -haozjj.com -haozu.com -haozuojia.com -hapi123.net -hapimall.com -hapingapp.com -hapiweb.com -hapjs.org -haplat.net -happigo.com -happy-fanshu.com -happy24uk.com -happycamp.cc -happycaoyue.com -happychang.net -happycodeboy.com -happyelements.com -happyev.com -happyjuzi.com -happylivelife.com -happymath.org -happymath2009.org -happymmall.com -happynear.wang -happyphonewoods.com -happypingpang.com -happyplaygame.net -happysky.org -happytify.cc -happytrave.com -happyux.com -happyya.com -haqu.com -harbin-electric.com -harborhousehome.com -hardkr.com -hardspell.com -hareric.com -harlanc.vip -harmay.com -harmight.com -harmony3.com -harmony4s.com -harmonyos.com -haroldrandom.me -harrynull.tech -harrypottermagicawakened.com -harttle.land -harvestcm.com -harvestpawn.com -hasary.com -hasea.com -hasee.com -hasee.net -hashcoding.net -hashfish.net -hashnest.com -hasndq.com -hat358.com -hatdot.com -hatfav.com -hatlonely.com -hatoem.com -haval-global.com -havefun.im -hawu.me -hax18.com -haxiu.com -haxiu.org -haxwx.cc -hayeen.com -hayseen.com -hazq.com -hb-green.com -hb-ws.com -hb-zikao.com -hb10000.com -hb10000sale.com -hb114.cc -hb12333.com -hb1629.com -hb189.cc -hb189.mobi -hb30.com -hb3rm.com -hb6.org -hb96568.com -hbadei.com -hbanbao.com -hbap.net -hbbaidu.com -hbbidding.com -hbbsw.vip -hbbutler.com -hbbxpx.com -hbbzyys.org -hbcccm.com -hbccp.org -hbccpit.org -hbcdc.com -hbcg.cc -hbcggl.com -hbchaopu.com -hbchen.com -hbchy.net -hbciqtc.com -hbcjaq.com -hbcjh.net -hbcjlq.com -hbcjw.com -hbcjxx.com -hbcms.com -hbcofco.com -hbcourt.org -hbcsche.com -hbcszb.com -hbctjk.com -hbcyclub.com -hbdangyang.com -hbddrn.com -hbdfcn.com -hbdfdh.com -hbdmia.com -hbdns.org -hbdthy.com -hbdtjqj.com -hbdzcg.com -hbecsc.com -hbeducloud.com -hbekt.com -hbepec.com -hbexqt.com -hbez.net -hbezzx.com -hbfie.org -hbfire.com -hbfnnyw.com -hbfootball.com -hbfy.com -hbfyhb.com -hbfzb.com -hbgajg.com -hbgdwl.com -hbglky.com -hbgonglue.com -hbgrb.net -hbgsetc.com -hbgsl.com -hbguanwei.com -hbgwy.org -hbgzh.com -hbha027.com -hbhande.com -hbhaolinju.com -hbhcdn.com -hbhdhd.com -hbhm.net -hbhtcm.com -hbhtxx.com -hbhxbb.com -hbhxqq.com -hbhyychem.com -hbhz.net -hbicpa.org -hbidc.net -hbifeng.com -hbinitiate.com -hbjcgy.com -hbjdxt.com -hbjfscc.com -hbjhc.com -hbjhpx.com -hbjhyh.com -hbjimin.com -hbjingming.com -hbjinnong.com -hbjjrb.com -hbjk114.com -hbjkjt.com -hbjlhw.com -hbjsinfo.com -hbjubao.com -hbjxjy.org -hbjxjyw.com -hbjxym.com -hbjz12333.com -hbjzx.com -hbjzzx.com -hbkqw.com -hbksw.com -hbky.com -hbla.net -hblady.com -hblccy.com -hble6.com -hblijiehb.com -hbliti.com -hblongdong.com -hblszq.com -hbltzb.com -hbly.net -hblykj.com -hbm360.com -hbmes.com -hbmmtt.com -hbnews.net -hbnewsoft.com -hbneww.com -hbooker.com -hbouc.com -hbpangu.net -hbpengxi.com -hbpic5.com -hbpictures.com -hbprjx.com -hbptzsbw.com -hbpukang.com -hbpygt.com -hbql.org -hbqnb.com -hbqnxy.com -hbqq.com -hbqtgg.com -hbqyj.org -hbqyxy.com -hbrb.net -hbrbmedia.com -hbrc.com -hbrcgd.com -hbrchina.org -hbrchinese.org -hbrd.net -hbread.com -hbrebond.com -hbrfyl.com -hbrqygr.com -hbruicai.com -hbryzx.net -hbrzkj.com -hbs-nd.com -hbsantak.com -hbsccloud.com -hbsdenterprise.com -hbsem.com -hbseo.com -hbsfgk.org -hbshbsh.com -hbshgzx.com -hbshls.com -hbshuzhou.com -hbsia.org -hbskw.com -hbslncy.com -hbslndx.com -hbsmw.com -hbsocar.com -hbsoft.net -hbsogdjt.com -hbspcar.com -hbsql.com -hbssfw.com -hbssspot.com -hbstars.com -hbsti.com -hbsunlink.com -hbswkj.com -hbswnews.com -hbsydw.org -hbszfw.com -hbsztv.com -hbszzd158.com -hbszzdlssz.com -hbszzk.com -hbszzx.com -hbtaiyang.com -hbtcw.com -hbtengniu.com -hbtlsd.com -hbtobacco.com -hbtxbaidu.com -hbtybio.com -hbtycp.com -hbvhbv.com -hbwh.net -hbwhgs.com -hbwhjj.com -hbwhrd.org -hbwjs.com -hbwlyh.com -hbwust.com -hbww.org -hbxdf.com -hbxhxkj.com -hbxiyuan.com -hbxtzy.com -hbxyairport.com -hbxytc.com -hbyczk.com -hbyhsg.com -hbyidu.com -hbyjfs.com -hbyoyo.com -hbyspx.com -hbyswy.com -hbzaxh.com -hbzbw.com -hbzgjx.com -hbzhan.com -hbzhanghe.com -hbzhjxzz.com -hbzhonghai.com -hbzjzb.com -hbzknet.com -hbzkw.com -hbzkzx.com -hbzkzxw.com -hbzlw.com -hbzncz.com -hbzqzx.com -hbzsb.com -hbzuojia.com -hbzxr.com -hbzxtyq.com -hbzywh.com -hc-byq.com -hc-cdn.com -hc-software.com -hc01.com -hc121.com -hc23.com -hc360-inc.com -hc360.com -hc39.com -hc79.com -hc9.com -hcbbs.com -hcbus.com -hcbuy.com -hcc11.com -hccpcba.com -hcdamai.com -hcdj.com -hcdyhr.com -hcgroup.com -hch518.com -hchaoche.com -hchaoshouyi.com -hchbblg.com -hchezhu.com -hchlidc.com -hcicloud.com -hcjietui.com -hcl100.com -hcmiraefund.com -hcocoa.com -hcpzdm.com -hcrjy.com -hcshebao.com -hcsilk.com -hcsindex.org -hcsip.com -hcstzz.com -hctxf.org -hcw.so -hcwiki.com -hcx123.com -hcx99.com -hcxcw.com -hcxy6.com -hcxzdanbao.com -hcy.cc -hcyacg.com -hcyy.org -hczc.com -hczhifu.com -hczxmr.com -hczypay.com -hd-ifc.com -hd-tvb.com -hd.gg -hd00.com -hd027.com -hd123.com -hd123.net -hd12333.com -hd199.com -hd199.net -hd288.com -hd3p.com -hd88599.com -hdavchina.com -hdb.com -hdbaichuan.com -hdbohua.com -hdchd.cc -hddhhn.com -hddznet.com -hdfimg.com -hdggapi.com -hdgogogo.com -hdhgzx.com -hdhospital.com -hdhui.com -hdimg0.com -hdingsheng.com -hdj.me -hdjay.com -hdjr.org -hdjwww.com -hdlchina.com -hdletv.com -hdlogo.com -hdltest.com -hdmayi.com -hdmm168.com -hdmnw.com -hdmv.org -hdnfm.com -hdpfans.com -hdpyqc.com -hdrconcepts.com -hds111.com -hdsbyby.com -hdscg.com -hdsdyyy.com -hdslb.com -hdslb.net -hdthjy.com -hdtmedia.com -hduofen.com -hdurl.me -hduzplus.xyz -hdwan.net -hdwbsaas.com -hdwhgs.com -hdylwf.com -hdyouxi.com -hdzp.com -hdzxyy.com -he-nan.com -he-one.com -he11oworld.com -he1j.com -he2d.com -he9630.com -heacn.net -head-way.com -headerhotel.com -headns.com -headphoneclub.com -heaedu.com -healthcareol.net -healthjd.com -healthr.com -healthych.com -healthythinkingkids.com -healthyun.com -heart-game.com -heartide.com -heartinsti.com -hebangdianzi.com -hebaodai.com -hebauto.com -hebbank.com -hebbr.com -hebca.com -hebcar.com -hebcsr.org -hebczce.com -hebei.cm -hebei0319.com -hebeidns.com -hebeifeimeng.com -hebeijd.com -hebeinongzi.com -hebeisy.com -hebeitenglong.com -hebeizhitui.com -hebeizhouji.com -hebgtjt.com -hebiw.com -hebjxw.com -hebl.name -hebmusic.com -hebnx.com -hebolaw.com -hebotc.com -hebradio.com -hebsg.net -hebshanggu.com -hebtv.com -hebxtjx.com -hec-al.com -hec-changjiang.com -hecai360.com -hecaijing.com -hecdn.com -hecdn.net -hechaku.com -hechangquan.com -hechengbb.com -heclouds.com -heconns.com -hecpharm.com -hedaotang.net -hedgehogrock.com -heduibu.com -heduwang.com -hedy-it.com -heeeeeh.com -heekca.com -heerit.com -hefei.cc -hefeizp.com -hegek7.com -hegii.com -hegoubbs.com -hegouvip.com -hegsryjq.com -heheba.com -hehesheng.com -heheshouyou.com -hehesy.com -hehewan.com -hehouse.com -hehuamei.com -hei7.net -heibai.org -heibaimanhua.com -heicha.com -heicheng51.com -heidiankeji.com -heigaga.com -heiguang.com -heiguang.net -heiguisf.com -heijiao.net -heijin.org -heilanhome.com -heilaot.com -heilei.com -heilqt.com -heiluo.com -heima.com -heima8.com -heimaba.com -heimabao.com -heimac.net -heimacode.com -heimadao.com -heimadata.com -heimai666.com -heimajijin.com -heimancc.com -heimaoseo.org -heimaoseojishu.com -heimaoshe.com -heimayijiancai.com -heimaying.com -heimeiai.com -heimeng.net -heimizhou.com -heiniubao.com -heinote.com -heirenlei.com -heisener.com -heisha.net -heishao.net -heishenhua.com -heisiwang.com -heitao.com -heitao.me -heitao2014.com -heixi.com -heiyaheiya.com -heiyan.com -heiyan.la -heiyan.org -heiyange.com -heiyanimg.com -heiyanwang.com -heiying.cc -heiyuege.com -heiyuewan.com -heiyunxitong.com -heizhushoes.com -heizuan.com -hejiajinrong.com -hejies.com -hejinchuitou.net -hejiu2016.com -hejizhan.com -hejun.com -heketai.com -hekouxin.com -heku.org -hel168.com -helensbar.com -helianhealth.com -helight.info -helijia.com -helingqi.com -heliopods.com -helishi.net -heliuyan.com -heliweb.net -helixcommunity.org -hello-code.com -hello-mom.com -hello1010.com -hellobanma.com -hellobi.com -hellobike.com -hellobiye.com -hellobtc.com -helloc4d.com -hellocq.net -hellodive.com -hellof1.com -helloflask.com -hellogame.net -hellogithub.com -hellogslb.com -hellohuohu.com -helloimg.com -hellojava.com -hellojava.info -hellokang.net -hellokid.com -hellokidvip.com -hellokvm.com -hellomeowlab.com -helloradio.org -hellorf.com -hellotalk8.com -helloweba.com -helloweba.net -hellowebfont.com -helloyao.com -helong.info -help-hope.org -helper-sys.com -helperaddress.com -helplib.com -helplib.net -helpmeng.com -helpton.com -heluo.cc -heluowenhua.net -hemabt.com -hemadaili.com -hemajy.com -hemamax.com -hemaos.com -hemayun.com -hemayx.com -heminjie.com -hempelgroup.com -hen360.com -henan100.com -henanart.com -henanfucai.com -henangeli.com -henanjianling.com -henanjubao.com -henanlvyi.com -henanpige.com -henansenli.com -henanyouth.com -henbt.com -hencin.com -hencoder.com -hengancaifu.com -hengannet.com -hengbogroup.com -hengcaotang.com -hengchang6.com -hengdayun.com -hengdianworld.com -hengdongli.com -hengdu.cc -hengdulaw.com -hengjiafish.net -hengli588.com -hengqian.com -hengqijy.com -hengqikuaiji.com -hengshenggongyi.net -hengshuilaobaigan.net -hengtiansoft.com -hengtianyun.com -hengwenzhendangqi.com -hengxiangtaji.com -hengxifintech.com -hengxinjinshu.com -hengyan.com -hengyer.com -hengyidai.com -hengyoux.com -henhaoji.com -henjay724.com -henkuai.com -henmimang.com -henri.ren -henshiyong.com -henxisoft.com -henzan.com -henzanapp.com -hepaidai.com -hepalink.com -hepan.com -hepan.org -hepawang.com -hepmall.com -hepost.com -hequnshebei.com -hercity.com -hercules-micro.com -herdsric.com -here120.com -herebbs.com -hereisdownload.com -hermesguanwang.com -heroad-data.com -heroestactics.com -heroicyang.com -herosanctuary.com -heroskate.com -herostart.com -herowind.com -heroworld.net -hertzhu.com -hesey.net -heshui.com -hetao101.com -hetaoa.com -hetaoapis.com -hetaocdn.com -hetaolin.com -hetianyu.cc -hetusoft.com -hetuwang.com -heu8.com -heweather.com -heweather.net -hewebgl.com -hewei.in -hexiangyu.me -hexianrc.com -hexiaoxiang.com -hexicomtech.com -hexie168.com -hexilai.com -hexindai.com -hexinli.org -hexlt.org -hexmeet.com -hexun.com -hey-ganzhou.com -heyang.cc -heyang365.com -heycode.com -heygugu.com -heyguo.com -heyi.com -heyinguanli.com -heylinux.com -heymore.com -heyou365.com -heyou51.com -heyoutz.com -heyplus.com -heyreport.com -heyria.com -heyshopstreet.com -heytaoge.com -heytap.com -heytapcs.com -heytapdownload.com -heytapimage.com -heytapmobi.com -heytea.com -heyuan5.com -heyuchan.com -heyunchou.com -heyuyhw.com -heywoodsminiprogram.com -heywow.net -hez70.com -heze.cc -hezebus.com -hezeribao.com -hezhenzi.com -hezhizheng.com -hezhonglaw.com -hezhoubbs.com -hezi.com -hezibook.com -hezibuluo.com -hezxs.com -hf-iflysse.com -hf10000.com -hf12345.vip -hf365.com -hf3bk.shop -hf777.com -hfbaogao.com -hfbeta.com -hfbz.com -hfcn.cc -hfcyh.com -hffund.com -hfgjj.com -hfgrandtheatre.com -hfhouse.com -hfhyw.com -hfi-health.com -hfjy.com -hfkeheng.com -hfkj0754.com -hfkktt.com -hflwy.com -hflz.com -hfmama.com -hfmoney.com -hfpph.com -hfqzdz.com -hfray.com -hfrc.net -hfrcbc.com -hfrqh.com -hfrsggff.com -hfsava.com -hfsid.com -hfssw.com -hfswcz.com -hftfund.com -hftogo.com -hftycj.com -hfun.me -hfwx.net -hfx.net -hfyestar.com -hfyjgg.com -hfyjwjg.com -hfykd.com -hfyt365.com -hg-daigou.com -hg-z.com -hg12333.com -hg226.cm -hg28a7.com -hg32x.com -hg3655.com -hg5177.com -hg5677.org -hg58.pw -hg6262.biz -hg6666.info -hg6668.cc -hg67822.com -hg707.com -hg7799.net -hg8880.org -hga833.cc -hga994.com -hgaas.com -hgame.com -hgbang.com -hgdgcxy.com -hgdjw.net -hgfdcscxx.com -hgfdrf.com -hghmxdjy.com -hgitv.com -hgjart.com -hgjt.net -hgjx.com -hglaser.com -hgmhu.com -hgnc.net -hgqst.com -hgw.gg -hgy413.com -hgyjs.com -hgyx.cc -hgzk.com -hgzkb.com -hgzrc.com -hh-gltd.com -hh010.com -hh04.com -hh1488.com -hhailuo.com -hhbg123.com -hhcmjt.com -hhcn.com -hhcq.net -hhczy.com -hhddzx.com -hhdx120.com -hheedat.com -hhfg.org -hhfxw.com -hhgslb.com -hhh233.net -hhh885.com -hhhai.com -hhhoo.com -hhhstz.com -hhhtnews.com -hhhtscf.com -hhjtwl.com -hhl1916.com -hhlaozihao.com -hhpj.net -hhrcard.com -hhrdc.com -hhrhl.vip -hhrtu.com -hhsjtyn.com -hhtravel.com -hhvv.com -hhwww.net -hhxdkj.com -hhxin.com -hhycdai.com -hhycdk.com -hhygame.com -hhyungu.com -hi-54.com -hi-books.com -hi-chic.com -hi-gtd.com -hi-lead.com -hi-linux.com -hi-roy.com -hi-spider.com -hi0755.net -hi138.com -hi1718.com -hi2000.com -hi2000.net -hi8090.com -hiapk.com -hiavr.com -hibangong.com -hibea.com -hibixin.com -hibt.net -hibtc.org -hibuzz.net -hiby.com -hibymusic.com -hic.cloud -hicamelia.com -hicat.net -hicc.me -hicdma.com -hiceon.com -hichao.com -hichina.com -hichinaimg.com -hicling.com -hicloud.com -hiconics-dl.com -hicoo.net -hicosmo.com -hicp.net -hicss.net -hiczp.com -hidesigncloud.com -hiditie.com -hidva.com -hienshi.com -hiersun-hdp.com -hiersun-ido.com -hiersun-zuanjindian.com -hiesquire.com -hifi168.com -hificat.com -hifidiy.net -hififf.com -hifime.net -hifini.com -hifiok.com -hifishes.com -hifishuo.com -hifiveai.com -hifly.mobi -hifly.tv -hifpga.com -hifreud.com -hifuntv.com -higame123.com -higeshi.com -highdigitizing.com -highgg.com -highgo.com -highlm.com -hightopo.com -highwayguitar.com -higon.com -higrid.net -hihell.com -hihocoder.com -hihonor.com -hihope.org -hihour.com -hiido.com -hiigame.net -hiimii.com -hiing.net -hijacky.com -hijiaoshi.com -hijoys.com -hijuu.com -hik-er.com -hikerell.com -hiknow.com -hikops.com -hikrobotics.com -hikvision-jl.com -hikvision.com -hilarryxu.com -hilistentome.com -hillstonenet.com -hillyton.com -hiloong.com -hilunwen.com -himaker.com -himawari-japan.com -himeidian.com -himengyou.com -himigame.com -himiku.com -himofi.com -himovie.net -himself65.com -himuzik.net -himy2.com -hinabian.com -hinavi.net -hindlish.com -hinew8.com -hinpy.com -hiogadw.bar -hiopensource.com -hioug.com -hioyun.com -hipandashop.com -hiparking.com -hipcam.net -hiphop8.com -hipiao.com -hippoanimation.com -hippter.com -hipring.net -hipu.com -hiram.wang -hirede.com -hiregistry.com -hireye.com -hiroop.com -hiross.org -hirosspac.com -hirossz.com -his.sh -his2000.com -hiscene.com -hisense-home.com -hisense-plaza.com -hisense-syxs.com -hisense.com -hisensehitachi.com -hisensesmarthome.com -hishendeng.com -hisihi.com -hisilicon.com -hisiphp.com -hislota.com -hismarttv.com -hisoft.com -hisofts.com -hisonracking.com -hisports.com -histarter.com -histatic.com -histriver.com -hisupplier.com -hit180.com -hitachi-helc.com -hitalk.com -hitalkers.com -hitevision-solution.com -hitfmfans.com -hitgk.com -hitnology.com -hitnslab.xyz -hitokoto.us -hitortoise.com -hitouch.com -hitoy.org -hitsword.org -hitui.com -hitutu.com -hitux.com -hituyu.com -hitv.com -hiuo08jnsoo00bytu32shcs555aa1564dvfguiio0o0885432.com -hivecn.net -hiveview.com -hivi.com -hivictor.net -hiwafer.com -hiwbb.com -hiwebgl.com -hiwechats.com -hiwemeet.com -hiwenku.com -hiwifi.com -hiworld.com -hixgo.com -hixianchang.com -hixiaoman.com -hiyd.com -hiyongche.com -hiyouib.com -hiyouqu.com -hizg.org -hizhu.com -hizhuanli.com -hizip.net -hizj.net -hizuan.net -hizyw.com -hj-mail.com -hj.vc -hj776.com -hjapi.com -hjbbs.com -hjbfq.com -hjchee.com -hjcjifen.com -hjclass.com -hjd123.com -hjdns.com -hjdns.net -hjdzn.com -hjenglish.com -hjgcd.com -hjgjmy.com -hjhanjy.com -hjhrcloud.com -hjiesuan.com -hjjg.com -hjjs.org -hjkhjkl.com -hjplw.com -hjpp.net -hjr-exchange.com -hjtag.com -hjwblog.com -hjwsky.com -hjwxcps.com -hjxsjx.com -hjy1314.com -hjygame.com -hjyl.org -hjylx.com -hjz518.com -hk-island.hk -hk-myungga.net -hk5.cc -hk515.net -hk6w.com -hkaco.com -hkance.com -hkanews.com -hkbchina.com -hkcd.com -hkcgart.com -hkcna.hk -hkcts.com -hkctshotels.com -hkctsmembers.com -hkemsys.com -hkfc.hk -hkfe.hk -hkfljt.com -hkfunbox.com -hkfuy.com -hkgcr.com -hkgzaixian.com -hkhanji.com -hkjapp.com -hkkaoyan.com -hkklock.com -hkkuaiyixiu.com -hklangya.com -hklego.com -hklongbang.com -hkm168.com -hkmjd.com -hkpanamie.com -hkpep.com -hkproperty.com -hkqbh.com -hkqkj.com -hkqq8.com -hkqzzlyy.com -hkskyloyd.com -hkslg.com -hkstv.tv -hkt4.com -hktv8.com -hktzschool.com -hkwb.net -hkxbjt.com -hkxen.com -hkyykq.com -hl-brushes.com -hl6799.com -hl95.com -hld-marathon.com -hldbtv.com -hlddjwl.com -hldgp.com -hldnews.com -hldqjx.com -hldsjsjx.com -hldtr.com -hlej.com -hlfssh.com -hlgad.com -hlgdata.com -hlglwl.com -hlgnet.com -hlgnet.net -hlhmf.com -hlideal.com -hlj-aptech.com -hljjjb.com -hljjnjp.org -hljjxrc.com -hljjytkj.com -hljnzy.net -hljpost.com -hljradio.com -hljrcc.com -hljsfjy.com -hljszjxhw.com -hljtv.com -hljyestar.com -hljyqnj.com -hljzfkyy.com -hljzhenpin.com -hljzqg.com -hlkncse.com -hlmseo.com -hlnmg.com -hloong.com -hlpretty.net -hlread.com -hlsdq.com -hlsm.net -hltcy.com -hlwidc.com -hlxsykd.com -hlxxq.com -hly.com -hlybar.com -hlytec.com -hlyy.cc -hlyy.in -hlzq.com -hlzsgw.com -hm-3223.net -hm-yc.com -hm-zif.com -hm120.com -hm16888.net -hm511.com -hm86.com -hmailserver.org -hmdevelop.com -hmecw.com -hmeiyy.com -hminvestment.com -hmlan.com -hmldds.com -hmltec.com -hmnst.com -hmplay.com -hmsce.org -hmsem.com -hmsemi.com -hmseo.net -hmsxw.com -hmting.com -hmxw.com -hmz.com -hmzone.com -hmzs.net -hmzx163.com -hn-pc.com -hn12333.com -hn165.com -hn96520.com -hnaccp.com -hnaee.com -hnagroup.com -hnair.com -hnair.net -hnaiya.com -hnangel.com -hnaorui.com -hnapay.com -hnayg.com -hnbaiyun.com -hnbljy.com -hnboxu.com -hnbwsd.com -hnccpit.org -hnchuncheng.com -hncloud.com -hncnnews.net -hncoolwarm.com -hncourt.org -hncreate.com -hncsmjzs.com -hncsmtr.com -hncsvod.com -hndbs.com -hndca.com -hndnews.com -hndpx.com -hndtl.com -hndxsg.org -hnehome.net -hnemb.com -hnetn.com -hnfa.org -hnfaren.com -hnfjwh.com -hnfjz.com -hnflcp.com -hnfyqmj.com -hngbw.com -hngh.org -hngican.com -hngoldcorp.com -hngou.com -hngwg.com -hngwmt.com -hngyzx.org -hnh.cc -hnhaitian.com -hnhaofang.com -hnhnled.com -hnhw.org -hnhxxk.com -hniec.org -hniois.com -hnisca.org -hniso.net -hnisvc.com -hnjg.com -hnjing.com -hnjing.net -hnjkjn.com -hnjkw.net -hnjn.net -hnjobw.com -hnjshzy.com -hnkeji999.com -hnkljnxh.com -hnks.com -hnksln.com -hnkuaifawu.com -hnlat.com -hnlbdl.com -hnleisu.com -hnliangku.com -hnlungtongzs.com -hnlzw.net -hnmdtv.com -hnmgjr.com -hnmsw.com -hnmuseum.com -hnmyyz.com -hnnuange.com -hnnx.com -hnnxs.com -hnnzwhyy.com -hnoceanrace.com -hnol.net -hnpet.net -hnpolice.com -hnpost.com -hnqfseed.com -hnquxing.com -hnquyou.com -hnrcsc.com -hnrcsc.net -hnrich.net -hnrledu.com -hnrmb.com -hnsdedu.com -hnsfdc.com -hnshengben.com -hnsimeng.com -hnsiwei.com -hnsktc.com -hnsmj.org -hnsss.com -hnst.org -hnstguolu.net -hnsy386.com -hnsyda.com -hnsyu.net -hnteacher.net -hntengn.com -hntianduo.com -hnticai.com -hntobacco.com -hntv.tv -hntvjiaotong.com -hnwisecom.com -hnwlcm.com -hnwlxh.net -hnwtv.com -hnwz8.com -hnxcdjk.com -hnxfpfb.com -hnxgzg.com -hnxmxit.com -hnxueqian.com -hnxuntang.com -hnxyjt.com -hnycsk.com -hnydmq.com -hnyfkj.com -hnyh.net -hnyingfang.com -hnyinhan.com -hnyouneng.com -hnyuandian.com -hnyugame.com -hnyumantang.com -hnyunji.com -hnyunww.com -hnyunzhiyi.com -hnyyss.com -hnzhaobiao.com -hnzjdc.com -hnzjfcw.com -hnzjgfw.com -hnzjip.com -hnzjzx.org -hnzqgljt.com -hnzqw.com -hnztfs.com -hnzxkd.com -hnzxyy.com -hnzyzx.com -hnzzgjly.com -hoau.net -hobalab.com -hobbiestree.com -hocode.com -hodoop.com -hoehub.com -hogesoft.com -hoho.tv -hoho666.com -hohode.com -hojeje.com -holaq.com -holdhr.com -holdsteel.com -holegots.com -holidays5.com -holiland.com -holleykingkong.com -hollischuang.com -hollmed.com -hollycrm.com -hollysys.com -hollyuc.com -holoem.com -hologres.io -holteksupport.com -holyxiongan.com -home-assistant.cc -home-cn.htcsense.com -home.htcsense.com -home0311.com -home0538.com -home0668.com -home133.com -home178.com -home4love.com -home602.com -home616.com -home77.com -homebehind.com -homecdn.com -homecloud-lab.com -homed.me -homedo.com -homeinmists.com -homeinns.com -homeintour.com -homeking365.com -homekingcdn.com -homekoo.com -homekoocdn.com -hometeda.com -hometex114.com -hometexjoin.com -homevv.com -homeyao.com -homezz.com -hommk.com -homolo.com -homolo.net -homolo.org -homomo.net -homylogistics.com -honda-sundiro.com -hondooy.com -hondsen.com -hong-lawfirm.com -hongbao.show -hongbaorili.com -hongbaosuoping.com -hongbeibang.com -hongbizi.org -hongbocheng.com -hongchalin.com -hongdaym.com -hongdefund.com -hongdezk.com -hongdian.com -hongdoufm.com -hongdoulive.com -hongen.com -hongfeiyang.com -hongfen.org -hongfeng.co -honggancn.com -honggebang.com -honghailt.com -honghanda.com -honghe-tech.com -honghonghu.com -honghuotai.com -hongjiang.info -hongjiejia.com -hongjing.com -hongjingedu.com -hongjiu66.com -hongkachengpin.com -hongkang-life.com -hongkevip.com -hongkongapi.com -hongkou.net -hongku.com -hongkunjinfu.com -hongleishicai.com -honglongwl.com -honglulan.com -hongmen.com -hongmoka.com -hongniang.com -hongpig.com -hongqi.tv -hongqipress.com -hongrenzhuang.site -hongru.com -hongsehuoxian.com -hongsejiqing.com -hongshi-tech.com -hongshn.xyz -hongshu.com -hongsungifts.com -hongt.com -hongtongad.com -hongtu.me -hongtuwang.com -hongweipeng.com -hongxiaolong.com -hongxin18.com -hongxinbao.com -hongxingzn.com -hongxinhuaxue.com -hongxiu.cc -hongxiu.com -hongyan.info -hongyanliren.com -hongyaxuan.com -hongyeshuzhai.com -hongyicd.net -hongyingfangshui.com -hongyingtao.net -hongyu123.com -hongyue.com -hongyunlww.com -hongyunvren.com -hongze.net -hongzhoukan.com -hongztl.com -honkaiimpact3.com -honorfair.com -honpery.com -honpu.com -honsuntec.com -honwind.com -honycapital.com -honyuan.net -hoodinn.com -hoodong.com -hoofei.com -hoogge.com -hookbase.com -hookdll.com -hoolai.com -hoolaigames.com -hoolo.tv -hoop-archi.com -hoop8.com -hoopchina.com -hoopugames.net -hoosho.com -hooshong.com -hooyagames.com -hooyoo.com -hope-tarsus.com -hopebank.com -hopecool.com -hopedafz.com -hopehook.com -hoperun.com -hopesn.com -hopetrip.com.hk -hophingfood.com -hori3d.com -horion.com -horizon.ai -horizonrcg.com -horn-yacht.com -horsa.org -horsehr.com -horti-expo2019.com -horti-expo2019.org -hortor.net -hortor002.com -hortor005.com -hortor020.com -hortorgames.com -hosizoraworks.org -hosjjk.com -hospmall.com -host163.com -host666.net -hostadm.net -hostbuf.com -hostcto.com -hostdie.com -hostelxian.com -hostgoip.com -hostker.com -hostkvm.com -hostloc.com -hostmsu.ru -hostspaces.net -hostxen.com -hotalk.com -hotcbit.org -hotdb.com -hotdeeplink.com -hotdic.com -hoteamsoft.com -hoteastday.com -hotelcis.com -hoteldecorate.com -hoteldig.com -hotelgg.com -hotelvi.com -hotent.com -hotent.xyz -hotgamehl.com -hotkd.com -hotkey123.com -hotkidclub.com -hotking.com -hotoos.com -hotpotpro.com -hotpub.com -hotread.com -hotsales.net -hotstoday.com -hottechsemi.com -hottui.com -houbank.com -houcaller.com -houdao.net -houdask.com -houdunwang.com -houge.biz -houkai.com -houmags.com -houpuwang.com -houqinbao.com -houqun.me -houqun.net -houquner.com -houruitouzi.com -house178.com -house365.com -house5.net -house510.com -house86.com -housebaby.com -housedp.com -housenhe.com -housoo.com -houtu666.com -houxue.com -houyicaiji.com -houyuantuan.com -houzhibo.com -hoverlees.com -hovertree.com -hovfree.com -how234.com -howardwchen.com -howbuy.com -howelllighting.com -howjingcai.com -howjoin.com -howsci.com -howsoftworks.net -howtoing.com -howzhi.com -hoxing.com -hoxled.com -hoxue.com -hoyoh.com -hozin.com -hp-marathon.com -hp123.com -hpcanon.com -hpccake.com -hpcoo.com -hpej.org -hpoi.net -hprx.com -hpstore.cc -hpuoj.com -hpwu.com -hpwxc.com -hpx05.com -hpxy.net -hpyk.com -hq114.net -hq2011.com -hq28g.com -hq52.com -hq88.com -hqart.net -hqbd.com -hqbnb.com -hqbpc.com -hqbsh.com -hqbuy.com -hqbuycdn.com -hqc-china.com -hqcanyin.com -hqcft.com -hqchip.com -hqck.net -hqcr.com -hqepay.com -hqew.com -hqew.net -hqewimg.com -hqgq.com -hqhl.net -hqhot.com -hqidi.com -hqjy.com -hqkjfrp.com -hqpcb.com -hqps.com -hqresearch.org -hqwhw.com -hqwx.com -hqwy.com -hqyj.com -hqys.net -hqytgyh.com -hqyun.com -hqz.com -hqzbcn.com -hr-mp.com -hr1000.com -hr135.com -hr2003.com -hr2trainer.com -hr369.com -hr44.com -hr510.com -hr5156.com -hr668.com -hr9000.com -hr987.com -hran.me -hrayw.com -hrbaodian.com -hrbar.com -hrbciming.com -hrbeduy.com -hrbesd.com -hrbmama.com -hrbmilan.com -hrbpay.com -hrbpma.com -hrbrc.com -hrbslh.com -hrbswx.com -hrbzdty.com -hrcfc.com -hrchina.cc -hrday.com -href.lu -hrexam.com -hrfc.net -hrflc.com -hrfoods.com -hrgongfu.com -hrgrobotics.com -hrhuiyi.com -hrhy365.com -hrintl.com.hk -hrloo.com -hrm100.com -hrmarket.net -hroot.co -hroot.com -hrpackage.com -hrrukou.com -hrs100.com -hrsalon.org -hrsay.com -hrsee.com -hrteachu.com -hrtechchina.com -hrtn.net -hrtx.com -hrunion.org -hrxiongan.com -hrzsh.com -hrzy.cc -hs-ceo.com -hs-fe.com -hs-outlets.com -hs.net -hs10000.com -hs13z.net -hs186.com -hs2005.net -hs65.com -hs950.com -hsakyy.com -hsbdc.com -hsboss.com -hsbsimu.com -hscbw.com -hsdatalab.com -hsdcw.com -hsddyy.com -hsdhw.com -hsdmall.com -hsehome.com -hsehome.org -hsez.net -hsf88.com -hsfdc.com -hsfund.com -hsgjj.com -hsgjjw.com -hsgjysj.com -hsgsrj.com -hshh.org -hshotel.com -hshs.com -hshton.com -hshuiyi.com -hshw.com -hshy.net -hshymanor.com -hshymbp.com -hsigus.com -hsiii.com -hsjingcheng.com -hslj.net -hsmc.com -hsmdb.com -hsmkj.net -hsmob.com -hsmrt.com -hsoow.com -hspress.net -hsqds.com -hsr2013.com -hssdtest.com -hssemi.com -hssenglish.com -hssjyj.com -hsslab.com -hsstr.com -hssxhd.com -hssyxx.com -hsszfx.com -hst.com -hst1966.net -hstechsz.com -hstong.com -hsutimes.com -hsw2013.com -hsweb.me -hswkzy.com -hswnjz.com -hsxiang.com -hsxxad.com -hsybyh.com -hsyjs.com -hsysupply.com -hsyuntai.com -hsyyf.me -hszfgjj.com -hszhizhen.net -hszk.org -hszlcn.com -hszqxs.com -hszsfz.com -hsztbzx.com -hszy8.com -hszzsyzx.net -hszzzx.net -ht-cao.com -ht-saae.com -ht-sonic.com -ht001.com -ht88.com -ht9.com -htanwang.com -htbaba.com -htback.com -htbenet.net -htc-media.com -htcbbs.net -htcis.net -htciy.com -htcxfund.com -htd2000.com -htdata.com -hteacher.net -hteos.com -htexam.com -htexam.net -htfcn.com -htfoxit.com -htfutures.com -htgjjl.com -htguosheng.com -htgwf.com -hthl.net -htidc.com -htinfor.com -htinns.com -htinnsjm.com -htjs.net -htjsq.com -htkaoyan.com -htky365.com -html51.com -html580.com -html5cn.org -html5code.net -html5dw.com -html5plus.org -html5train.com -html5tricks.com -htmleaf.com -htmlplusplus.com -htmlsucai.com -htnice.com -htouhui.com -htpc1.com -htqyy.com -htr-mold.com -htranslate.com -htrfid.com -htsc.com -htsec.com -htsgh5.com -htsh.cc -htstzm.com -htt5.com -httingshu.com -httpbaidu.com -httpcn.com -httprunner.org -httpsbaidu.com -hturl.cc -htuwenming.com -htv009.com -htwed.com -htxxpx.com -htxyin.com -htyou.com -htys.cc -htyunwang.com -htzdj.com -htzyw.com -hua-lan.com -hua-yong.com -hua.com -huaaiangel.com -huaaosoft.com -huaaotech.com -huaat.com -huabaike.com -huaban.com -huabanimg.com -huabanpro.com -huabaoclock.com -huabeipay.com -huabian.com -huabo.net -huabokeji.com -huacaomu.com -huacaoshumu.net -huacemedia.com -huacenter.com -huachen.me -huachengzq.com -huachenit.com -huachenyuanyang.com -huachuanxueyuan.com -huaci.cc -huacnlee.com -huacolor.com -huacolor.net -huada120.com -huadan.com -huadehyd.com -huadezhuo.com -huadiandanbao.com -huadianhulian.com -huadonghospital.com -huadongmedia.com -huadoo.com -huadream.com -huaducloud.com -huadunlian.com -huaduocai.net -huadx.com -huaease.net -huaer.cc -huafeiw.com -huafeng-food.com -huafeng.com -huafens.com -huafer.cc -huaguoshan.com -huahanart.com -huahua567.com -huahuacaocao.com -huahuakon.com -huahuo.com -huaibaobei.com -huaibei.com -huaidan1.com -huaidan1234.com -huaien.com -huaihai.tv -huaijiufu.com -huaimi.com -huain.com -huainanhai.com -huainanren.net -huainet.com -huaipu.net -huajia.cc -huajia2000.com -huajiakeji.com -huajialishe.com -huajianmed.com -huajiao.com -huajie8.com -huajin100.com -huajing-inf.com -huajuan.net -huajx.com -huakai.me -huake-weixin.com -huake360.com -huakebosi.com -huakeyun.com -hualady.com -hualala.com -hualang361.com -hualet.org -hualiandressing.com -hualianxin.com -hualongxiang.com -hualu5.com -hualv.com -huamanlou.cc -huameiyuezi.com -huami.com -huamoe.com -huan-tai.com -huan.tv -huanaotong.com -huanbao-world.com -huanbao.com -huanbaoscx.com -huanbeiloan.com -huancaicp.com -huandie.com -huang-jerryc.com -huang-ou.com -huangbaoche.com -huangbin.me -huangbowei.com -huangchun.net -huangdao.com -huangdaojiri.org -huangdc.com -huangea.com -huanggao.net -huanggaofang.com -huangh.com -huanghaicollege.com -huanghanlian.com -huanghecaifu.com -huangheidc.com -huanghepiao.com -huanghouyz.com -huangjiemin.com -huangjun.net -huangjunying.com -huanglei.me -huangli.cc -huangli.com -huangliangbo.com -huangniu.in -huangoxl.com -huangpucn.com -huangqi1688.com -huangshanzjy.com -huangshaotian.com -huangsw.com -huangwei.me -huangwei.pro -huangxin.me -huangxinwei.com -huangxubo.me -huangye88.com -huangye88.net -huangyixiaoshuo.com -huangyunkun.com -huangz.me -huangze.net -huanhaoba.com -huanhuanhuishou.com -huanhuba.com -huaniaoy.com -huanidc.com -huanjinghaojia.com -huanjutang.com -huanjuyun.com -huankkk.com -huanlang.com -huanle.com -huanle800.com -huanleap.com -huanlecdn.com -huanlefish.com -huanleguang.com -huanlejia.vip -huanletang.com -huanlj.com -huanmusic.com -huanna.net -huanpingge.com -huanqiu.com -huanqiuauto.com -huanqiujiemi.com -huanqiukexue.com -huanqiumil.com -huanqiuw.com -huanqiuyimin.com -huanqu-tec.com -huanrong2010.com -huante.com -huantest.com -huanwen.com -huanxi.com -huanxia.com -huanxiyl.com -huanyingzq.com -huanyou365.com -huanyouji.com -huanyudns.com -huanyue123.com -huanyutv.com -huaoe.com -huaon.com -huapiaoliang.com -huaqiao.org -huaqidigital.com -huaqin.com -huaqinchi.com -huaquandian.wang -huaraytech.com -huarong2006.com -huarongdao.com -huaruicom.com -huaruizs.com -huas.co -huasehui.com -huash.com -huashangtop.com -huashen-edu.com -huasheng100.com -huashengdaili.com -huashengls.com -huashenll.com -huashilm.com -huashitong.net -huashphoto.com -huashu-inc.com -huashuxia.net -huasyun.com -huatai-pb.com -huatefamen.net -huatengoa.com -huatengsci.com -huati365.com -huatu.com -huatugz.com -huatuo007.com -huatuowenda.com -huatuoyf.com -huaue.com -huawan.com -huawangzhixun.com -huawanyun.com -huawei.com -huaweicloud-dns.com -huaweicloud-dns.net -huaweicloud-dns.org -huaweicloud.com -huaweicloudwaf.com -huaweidevice.com -huaweidun.com -huaweigold.com -huaweimall.com -huaweimarine.com -huaweimossel.com -huaweirom.com -huaweisafedns.com -huaweistatic.com -huaweisymantec.com -huaweiuniversity.com -huaweizdl.com -huawenfanyi.com -huawenonline.com -huawenwin.com -huaxi.net -huaxi100.com -huaxia.com -huaxia369.com -huaxia77.com -huaxiaf.com -huaxiangdiao.com -huaxiayatong.com -huaxiazi.com -huaxincem.com -huaxing.com -huaxinnianhua.com -huaxirc.com -huaxiu.ink -huaxj.net -huaxuezoo.com -huaxunnsw.com -huayala.com -huayanghui.net -huayanxiu.com -huayanxiu.net -huayidiaosu.com -huayilanxin.com -huayilawyers.com -huayimedia.com -huayiming.com -huayinjapan.com -huayinziben.com -huayoumengze.com -huayoutianyu.com -huayu9527.com -huayuanlcd.com -huayuannongji.com -huayuebaobao.com -huayuejob.com -huayuidc.com -huayun.com -huayunshuzi.com -huayunyy.com -huayushufang.com -huazhen2008.com -huazhen2008.net -huazhengcaiwu.com -huazhenjiaoyu.com -huazhongcar.com -huazhongcnc.com -huazhonghua.com -huazhongtimes.com -huazhu.com -hubao.cc -hubcyts.com -hubei-design.com -hubei88.com -hubeibbs.net -hubeici.com -hubeidaily.net -hubeihome.net -hubeiip.com -hubeipbx.com -hubeisafety.org -hubeiwsd.com -hubeixuekao.com -hubeiyanjiusheng.com -hubeiyongtai.com -hubida.net -hubpd.com -hubu.com -hububbs.com -hubulab.com -hubwiz.com -hubzs.com -hucdn.com -huceo.com -huchao.me -huchaowei.com -hucheng100.com -hudai.com -hudbbs.com -hudong.com -hudongad.com -hudongba.com -hudongcdn.com -hudongkand.com -hudongku.net -hudu0.com -hudunsoft.com -huduntech.com -huelead.com -hueseman.com -hufangyun.com -hugaoba.com -hugd.com -hugeland.com -huhabao.com -huhanyong.com -huhoo.com -huhoo.net -huhua.net -huhuang.net -huhuhiiuio.com -huhuvr.com -hui-ben.com -hui-chao.com -hui.net -hui.so -hui10.com -hui100.com -hui20.com -hui43.com -hui712.com -hui800.com -hui800.net -huians.com -huibenbeno.win -huibo.com -huicaiba.com -huicaishui.net -huicaizhike.com -huiche100.com -huicheimg.com -huichengip.com -huichewang.com -huichexiang.net -huidang.com -huideyecai.com -huidicp.com -huidu.com -huidu.net -huiemall.com -huifachina.com -huifarm.com -huifenqi.com -huifudai.com -huifudashi.com -huifusihai.com -huifutz.com -huifuyimin.com -huigao-magnetics.com -huigetv.com -huigezi.org -huihaicenter.com -huihaicn.com -huihedian.com -huihua365.com -huihua8.com -huihuaren.com -huihuarensheng.com -huihui.moe -huihuitech.net -huiian.com -huiji.wiki -huijiame.com -huijiaoyun.com -huijidata.com -huijimall.com -huijistatic.com -huijitrans.com -huijiwiki.com -huijucn.com -huikaiwjj.com -huila88.com -huilan.com -huilanyujia.com -huilianyi.com -huiliubao.com -huilm.com -huilog.com -huilongsen.com -huilv.cc -huilv168.com -huilvwang.com -huilvwu.com -huim.com -huimaiche.com -huiman.net -huimaw.com -huimee.com -huimee.net -huimeisports.com -huimengya.com -huimin111.com -huimingcn.com -huinaimei.com -huing.net -huion.com -huioo.net -huiqiangkeji.com -huirendai.com -huiris.com -huirong168.com -huiruanzhijia.com -huishangbao.com -huishangol.com -huishenghuo888888.com -huishengqianzhushou.com -huishoubao.com -huishoushang.com -huishuaka.com -huishuang.xyz -huisituo.com -huisky.com -huisou.com -huisouimg.com -huisuoping.com -huitao.net -huitaoba.com -huitaoyouhui.com -huitongqingsuan.com -huitoubj.com -huitouche.com -huitouzi.cc -huitouzi.com -huitu.com -huiurl.com -huivo.com -huiweixin.com -huiwo.com -huiword.com -huixiang360.com -huixiangtiandi.com -huixiaoer.com -huixiaoer.net -huixing.hk -huixinkang.com -huixinli.com -huixinyt.com -huixinyun.com -huixuan100.com -huixuanjiasu.com -huiyan315.com -huiyankan.com -huiyaohuyu.com -huiyep.com -huiyi8.com -huiyiabc.com -huiyingjr.com -huiyinxun.com -huiyisheji.com -huiyizhuo.com -huiyou.com -huiyuandao.com -huiyuanyy.com -huize.com -huizecdn.com -huizhan-inc.com -huizhaofang.com -huizhek.com -huizhekou.net -huizhijiaxun.com -huizhimob.com -huizhonghengxing.com -huizhongkameng.com -huizhouf.com -huizuche.com -huizuoyuezi.com -hujia.org -hujiang.com -hujingyuan.com -hujiuzhou.com -hujuntao.com -hukai.me -huke88.com -hukou021.com -hukoushanghai.com -huladai.com -hulai.com -huliangongyu.com -hulianmaibo.com -hulinhong.com -huliqun.com -huliyx.com -hulkdev.com -huluboshi.com -huluhour.com -huluip.tech -huluo.com -hulusaas.com -hulusi.com -huluwa365.com -huluwa8.com -huluxia.com -huluxia.net -huluzc.com -humanrights-china.org -humengyun.com -humensec.com -huming.com -hunancatv.com -hunanedu.net -hunanpta.com -hunantv.com -hunanwb.com -hunanzhibo.com -hunbei.com -hunbei1.com -hunbohui.info -hunbys.com -huncct.com -hunche.net -hundsun.com -hundun.net -hundx.com -hunger-valley.com -hunhun520.com -hunjuwang.com -hunlang.com -hunli100.com -hunlihunli.com -hunliji.com -hunlimama.com -hunlimao.com -hunmiao.com -hunshitong.net -hunt007.com -huntchance.com -huntic.com -huntkey.com -huntkeydiy.com -hunuo.com -hunyinyiyuan.com -huo-cun.com -huo119.com -huoban.com -huobanjs.com -huobanmall.com -huobanxietong.com -huobaoyx.com -huobi.io -huobiapps.com -huobichat.com -huocai.com -huocc.com -huochai.mobi -huochaihe.cc -huoche.biz -huoche.com -huoche.net -huoche.wiki -huochepiao.com -huochepiao.net -huodao.hk -huoding.com -huodong.org -huodonghezi.com -huodonghui.net -huodongjia.com -huodongju.com -huodongju.net -huodongquan.net -huodongshu.com -huodongwang.com -huodongxing.com -huoduan.com -huofar.com -huofutp.com -huoguopaihang.com -huogz.com -huohoo.com -huohu123.com -huohuolife.com -huoji.com -huoju365.com -huojuli.com -huokebao.net -huokesoft.com -huolala.co -huolan.net -huolea.com -huoli.com -huolinhe.com -huolishaonianwang.com -huolug.com -huomao.com -huomao.tv -huomaotv.com -huomaqun.com -huoming.com -huopinjie.com -huoqiuapp.com -huoqiucaijing.com -huoshan.cc -huoshan.club -huoshan.com -huoshanvod.com -huoshanzhibo.com -huoshen.com -huoshen.net -huosu.com -huosubtc.com -huowan.com -huoxing24.com -huoxingba.com -huoxinggirl.com -huoxinglaike.com -huoxingzi.com -huoxun.com -huoyan.com -huoyan.io -huoyanio.com -huoying666.com -huoyuandl.com -huozw.com -hupan.com -hupo.com -hupo.tv -hupu.com -hupu.tv -hupucdn.com -huquan.net -hurongclub.com -hurun.net -husenji.com -hushangcaifu.com -hushenyun.com -hust-laser.com -hust-snde.com -hust.cc -hustcad.com -hustduyan.com -hustgroup.com -hustlife.com -hustlzp.com -hustnews.com -hustoj.com -hustonline.net -hustp.com -hustport.com -hustunique.com -hustwenhua.net -hustxb.com -husubao.com -hutaojie.com -hutaolinight.com -hutaow.com -hutone.net -hutong-school.com -hutoufeng.net -hutoulang.com -hutu.me -hutui9.com -hutuoweb.com -hutusi.com -huubaa.com -huuhoo.com -huwaibbs.com -huway.com -huweihuang.com -huweishen.com -huxi.cc -huxiaofan.com -huxiaoshi.com -huxinqk.com -huxiu.com -huxiu.link -huxiucdn.com -huya.com -huyahaha.com -huyanan.wang -huyanapp.com -huyanbao.com -huyaohui.com -huyaruanwen.com -huynet.com -huyouxiong.com -huyuxx.com -huzhan.com -huzhao1.com -huzheng.org -huzhifeng.com -huzhongxin.com -huzhoumuseum.com -huzhu001.com -huzicaotang.com -huziketang.com -huzs.net -huzu.com -hvac001.com -hvdiy.com -hvtong.com -hw-ai.com -hw-tm.com -hw100k.com -hw3static.com -hw444.com -hw555.com -hw99.com -hwactive.com -hwadmin.com -hwangda.com -hwanjia.com -hwasmart.com -hwccpc.com -hwcloudlive.com -hwclouds-dns.com -hwclouds-dns.net -hwclouds.com -hwclouds.mobi -hwclouds.net -hwcrazy.com -hwdef.com -hweimall.com -hwfcw.com -hwgmthree.com -hwht.com -hwjyw.com -hwk603.com -hwlantian.com -hwlpz.com -hwrecruit.com -hwsem.com -hwtrip.com -hwtxfilm.com -hwwt2.com -hwwt8.com -hwxda.com -hwxjp.com -hwxnet.com -hwxuanliuqi.com -hwzseo.com -hwzyjt.com -hx008.net -hx110.com -hx2car.com -hx2cars.com -hx3366.net -hx36.net -hx8886.com -hx95.com -hx99.net -hx9999.com -hxage.com -hxbdxled.com -hxbxw.com -hxcdn.net -hxchem.net -hxct.com -hxdi.com -hxdkfp.com -hxen.com -hxepawn.com -hxfeiji.com -hxfilm.com -hxfjw.com -hxgame.net -hxgqw.com -hxgs.net -hxgwott.com -hxhost.com -hxinq.com -hxjbcdn.com -hxjbh.com -hxjiqi.com -hxjlhn.com -hxkvm.com -hxland.com -hxlover.com -hxlsw.com -hxltad.com -hxmeishi.com -hxmrys.com -hxnews.com -hxppw.com -hxqc.com -hxqnj.org -hxqwx.com -hxrc.com -hxrdcnc.com -hxrdr.com -hxs168.com -hxsd.com -hxsd.tv -hxsec.com -hxshuizu.com -hxshx.com -hxsme.org -hxt-semitech.com -hxthjy.com -hxtk.com -hxttcp.com -hxwglm.com -hxxdsb.com -hxxkw.org -hxxl6.com -hxyg.org -hxyjw.com -hxys.com -hxytea.com -hxytw.com -hxyxsj.com -hxzdhn.com -hxzxg.com -hy-cgp.com -hy-zr.com -hy01888.com -hy05190134.com -hy123.com -hy2046.com -hy233.tv -hy628.com -hyahm.com -hyb2b.com -hybbtree.com -hycdn.com -hycfw.com -hycgy.com -hyckjic.com -hydarts.com -hydata.cc -hydbest.com -hydcd.com -hyds360.com -hydzfp.com -hyedu.com -hyext.com -hyfutures.com -hygame.cc -hyggfx.com -hygoldcup.com -hygy361.com -hyhfdaimei.com -hyhl66.com -hyhro.com -hyhygame.com -hyimmi.com -hyipchina.com -hyjgxx.com -hyjp.net -hykang.com -hykbl.com -hykcsoft.com -hylname.com -hyltxx.com -hym68.com -hymom.com -hynews.net -hynews.org -hynixic.com -hynpay.com -hyocr.com -hypefolio.com -hyper.sh -hypergryph.com -hyrainbow.com -hyrzb.com -hysdknb.com -hysec.com -hysseo.com -hysteeltube.com -hyt368.com -hytcshare.com -hytd.com -hytera.com -hytic.net -hyundai-hmtc.com -hyundaibeijing.com -hyuuhit.com -hywly.com -hyxdj.com -hyxrzs.com -hyyazhaji.com -hyyf.net -hyyic.com -hyyoa.com -hyyy4.com -hyz86.com -hyzcservice.com -hyzm.cc -hyzqxsb.com -hz-etest.com -hz-gn.com -hz-xin.com -hz100msh.com -hz66.com -hzaee.com -hzaichao.com -hzairport.com -hzamcare.com -hzbenet.com -hzbh.com -hzbike.com -hzbluebutterfly.com -hzbook.com -hzc.com -hzccb.net -hzccnet.com -hzcekong.com -hzcnc.com -hzcopyright.com -hzcourse.com -hzcuizhai.com -hzd.com -hzdajiangdong.com -hzdauto.com -hzdjr.com -hzdledu.com -hzdx.com -hzeduask.com -hzeg.com -hzfangwang.com -hzfc.cc -hzfucai.net -hzgh.org -hzgjj.com -hzgrow.com -hzguojiao.com -hzgxr.com -hzh1.com -hzhaoyi.com -hzhfzx.com -hzhike.com -hzhmktwx.com -hzhr.com -hzhuangxiang.com -hzhuanqu.com -hzhuti.com -hzhx.com -hzins.com -hzins.net -hzirun.com -hzjingxian.com -hzjinsen.com -hzjizhun.com -hzjlxx.com -hzjmjl.com -hzjs56.com -hzjunxing.com -hzjushan.com -hzjxy.net -hzlblp.com -hzlcyd.com -hzlhf.com -hzlug.org -hzlyun.com -hzmama.net -hzman.net -hzmantu.com -hzmba.com -hzmogo.com -hzmrhl.com -hzmylike.com -hzncc.com -hznews.com -hznsh.com -hznzcn.com -hzou.net -hzpgc.com -hzpzs.net -hzqimiao.com -hzqz.net -hzr1.com -hzrc.com -hzredream.com -hzsaso.com -hzsbz.com -hzsgjj.com -hzsjnxh.org -hztalk.com -hzti.com -hztosz.com -hztraining.com -hzvillas.com -hzwer.com -hzwindpower.com -hzwmw.com -hzwsjyjt.com -hzwtech.com -hzwxq.com -hzwyh.com -hzxiangda.com -hzxiyuege.com -hzxsjgxx.com -hzxyns.com -hzyestar.com -hzyhzp.com -hzylpco.com -hzyoka.com -hzypro.com -hzyuanshan.com -hzyuedu.com -hzyuewan.com -hzyz.net -hzzhaobiao.com -hzzkj.net -hzzp.com -hzzqs.com -hzzsbbs.com -hzzsfs.com -i-27.name -i-520.net -i-ab.com -i-bei.com -i-bigdatas.net -i-calorie.com -i-click.com -i-element.org -i-ev.com -i-excellence.com -i-hifi.com -i-jim.com -i-kan.me -i-lewan.com -i-ll.cc -i-matcher.com -i-md.com -i-modec.com -i-mofang.com -i-morefun.com -i-mprove.cc -i-now.com -i-oranges.com -i-same.com -i-shu.com -i-size.com -i-tongfang.com -i-tv.com -i-uya.com -i-xinnuo.com -i-xoron.com -i-yulan.com -i.dell.com -i0349.com -i05b.com -i0713.wang -i0746.com -i075.com -i0898.org -i100e.com -i11r.com -i121.net -i1758.com -i1766.com -i2abc.com -i2ya.com -i360mall.com -i3done.com -i3dpworld.com -i3ds.fun -i3geek.com -i3gt.com -i3smot.com -i3v.cc -i3youlun.com -i3yuan.com -i4px.com -i4t.com -i51game.com -i5399.com -i5738.com -i5i6.net -i5mai.com -i5read.com -i5seo.com -i6879.com -i7aot4.com -i7box.com -i7fh.com -i7gg.com -i7play.com -i7wx.com -i8001.com -i8cn.com -i8gua.com -i8i8i8.com -i8tq.com -i9.org -i91pv.com -i9star.com -i9wang.com -ia-shenzhen.com -ia22.com -iac-i.org -iacblog.com -iadmob.com -iadmore.com -iadsdk.apple.com -iaeac.org -iaikx.com -iakmai.com -ialicdn.com -ialloc.com -ialloc.org -iambanban.com -iambocai.com -iameduwork.com -iamfisher.net -iamhippo.com -iamjzs.com -iamle.com -iamlintao.com -iamsujie.com -iamtxt.com -iamue.com -iamverycute.com -iamwr.com -iamxiaoming.net -iamxk.com -ian.wang -ianalysis.xyz -ianvisa.com -iaoso.com -iaoyou.com -iapolo.com -iapp4me.com -iapple123.com -iappler.net -iapplianceweb.com -iapppay.com -iapps.im -iappstoday.com -iars-wuhan.com -iartmoney.com -iartsee.com -iask-media.com -iask.com -iask.in -iaskbus.com -iaskhot.com -iat-auto.com -iavira.com -iaviva.com -iaxure.com -iazhi.com -ib-china.com -ib566.com -ib68.com -ibaba88.com -ibadboy.net -ibailve.com -ibaizhu.com -ibanbu.com -ibangkf.com -ibangquan.com -ibanma.net -ibanquan.com -ibantang.com -ibanyu.com -ibaopen.com -ibaotu.com -ibaozou.com -ibayapp.com -ibbwhat.com -ibcar.net -ibcde.com -ibczy.com -ibeifeng.com -ibeiig.com -ibeike.com -ibeiliao.com -ibeiou.com -ibenxi.com -ibestapp.com -ibestfanli.com -ibestservice.com -ibestv.com -ibeta.me -ibgbuy.com -ibianqu.com -ibiaozhi.com -ibicn.com -ibiji.com -ibimawen.com -ibimuyu.com -ibingniao.com -ibiquge.net -ibiquke.com -ibireme.com -ibjq.wang -ibkcn.com -ibkda.com -ibl520.com -iblimg.com -ibloger.net -iblue.com -iblue.me -ibluesocial.com -ibmwclub.com -ibook8.com -ibooker.cc -ibookstar.com -ibornclinic.com -iboxpay.com -ibr.cc -ibrainproject.org -ibroadlink.com -ibruce.info -ibscdn.com -ibtba.cc -ibtmao.com -ibtsat.com -ibtyun.com -ibuick.com -ibuscloud.com -ibuspan.com -ibuying.com -ibw.cc -ic-ldo.com -ic2china.com -ic37.com -ic72.com -ic98.com -ic9cube.com -ica-alliance.org -icafe28.net -icafe8.com -icafebolger.com -icaidao.com -icaifu.com -icaikee.com -icaile.com -ican-contest.org -icandata.com -icanvip.net -icanzc.com -icaoye.com -icardfinancial.com -icaredbd.com -icasiso.com -icastlewar.com -icax.org -icbc-ltd.com -icbuy.com -icc.one -icc365.com -iccchina.com -iccemt.org -iccessh.org -iccgame.com -iccgame.net -icchaoren.com -iccidchaxun.com -iccircle.com -iccsmart.com -iccsz.com -icdn2.com -icdol.com -icdream.com -icdt-conf.com -ice.work -ice1000.org -iceasy.com -icebear.me -icebound.cc -icefoxgame.com -iceinto.com -icekr.com -icemle.org -iceshi.org -icesimba.com -icevpn.org -icewing.cc -icewingcc.com -icfans.com -icfcc.com -icfqs.com -icfusions.com -icgoo.net -icgu.com -icgvisa.com -ich8.com -ichacha.com -ichacha.net -ichang8.com -ichangbaishan.com -ichangtou.com -ichanyu.com -ichaoshangyue.com -ichaotu.com -icharm.me -ichat800.com -ichdata.com -ichefeng.com -ichehaopei.com -ichehome.com -ichenfei.com -ichengyun.net -ichennan.com -icheruby.com -ichinaceo.com -ichinaenergy.com -ichip.ren -ichishu.com -ichn.me -ichong123.com -ichuanglan.com -ichuangwei.com -ichuangye.com -ichuangyee.com -ichuanyi.com -ichunqiu.com -ichunt.com -ichushang.com -ichww.com -ichzh.com -iciba.com -icicicic.com -icidc.com -icifit.com -icignacmb.com -icinephile.com -icinfo.net -icirculation.com -icitymobile.com -icixun.com -iciyuan.com -icjiemi.com -ickeep.com -icketang.com -ickey.cc -ickimg.com -iclicash.com -iclickstatic.com -icloud-cdn.icloud.com.akadns.net -icloud.cdn-apple.com -icloudgslb.com -icloudnews.net -iclouds.work -icmade.com -icme14.org -icminer.com -icmsdev.com -icmsms2020.org -icmyk.cc -icnjob.com -icnkr.com -icnote.com -icnpda.com -icntv.tv -icnws.com -icoat.cc -icoc.bz -icoc.cc -icoc.in -icoc.me -icocg.com -icocoro.me -icode9.com -icodef.com -icodelogic.com -icoderobot.com -icom5g.com -iconfans.com -iconfans.org -icoolen.com -icoolxue.com -icoou.com -icopy.site -icoremail.net -icos8.com -icosky.com -icourse163.com -icourse163.org -icourt.cc -icp100.net -icp21.com -icpcn.com -icpcw.com -icpdaili.com -icphu.com -icpisp.net -icrazyidea.com -icroom.com -icrystalnotes.com -icshanghai.com -icshow.cc -icsisia.com -icslx.com -icsoc.net -icson.com -icss.me -icstreet.com -icswb.com -ict361.com -ictcsr.org -ictehi.com -ictest8.com -ictk-china.com -ictlce.com -ictown.com -ictpaas.com -ictun.com -ictuniv.com -icuiya.com -icver.com -icvip.com -icxbk.com -icxinli.com -icy-capital.com -icyif.com -icyip.com -icylife.net -iczhiku.com -iczhiyu.com -iczoom.com -id-bear.com -id-linking.com -id6.me -idabai.com -idachu.com -idafen.com -idaima.com -idangdai.com -idanpianji.com -idaocao.com -idataway.com -idaxiang.org -idaybreak.com -idc-icp.com -idc.moe -idc.sh -idc002.com -idc021.com -idc123.com -idc180.com -idc20.com -idc218.com -idc31.com -idc4.com -idc400.com -idc45.com -idc789.com -idc886.com -idc917.com -idc96.com -idc96.net -idcay.com -idcbest.com -idcbest.hk -idccenter.net -idccom.net -idccun.com -idcfengye.com -idchh.com -idchz.com -idcicp.com -idcicpdns.com -idcjf.com -idcjia.net -idckx.com -idcmiit.com -idcpv.com -idcquan.com -idcsec.com -idcser.com -idcsh.com -idcsh.net -idcsped.com -idcspy.com -idcspy.net -idcss.com -idctq.com -idcug.com -idcum.net -idcun.com -idcuw.com -idcvendor.com -idcvip.net -idcwn.com -idcys.com -idcyunwei.org -idea-king.org -idea1986.com -ideacms.net -ideagou.com -idealshanghai.com -ideanote.cc -ideaparfums.com -ideappt.com -ideasandroid.com -ideazhao.com -ideebank.com -ideepin.com -ideng.com -idesktopcal.com -idevz.org -idgvc.com -idianchou.com -idianfa.com -idianshijia.com -idig8.com -idkaiu.com -idler-et.com -idm.cc -idmdm.com -idn100.com -idname.com -idnscloud.com -ido-love.com -ido114.com -ido321.com -ido512.com -idoacg.com -idoall.org -idocbank.com -idocv.com -idol001.com -idolranking.info -idom.me -idomb.com -idongde.com -idongdong.com -idongte.com -idosend.com -idotools.com -idouba.net -idoupiao.com -idourl.com -idouyinstatic.com -idouzi.com -idown.hk -idoyun.com -idqqimg.com -idreamschool.com -idreamsky.com -idreamsoft.com -idrools.com -idrwl.com -idscn.com -idscn.net -idsie.com -idsky.net -idspub.net -idsuipai.com -idtcdn.com -idtechwh.com -idting.com -idudo.com -iduo8.com -iduobao.net -iduochong.com -iduoha.com -iduokan.net -idushu.com -idwzx.com -idyjy.com -idyzs.com -idzcp.com -idzoom.com -ie027.com -ie3.cc -ie515.com -ie525.com -ie586.net -ie815.com -ie915.com -ie935.com -ie977.com -ieasn.com -ieayoio.com -iebyte.com -iecdn.com -ieche.com -iecidc.com -iecie.com -iecity.com -iecnews.com -iecnu.com -iecool.com -iedh.net -iedon.com -ieduchina.com -ieduw.com -ieechina.com -ieeewifi.com -ieeod0.com -ieepa.org -iefang.com -iefans.net -ieforex.com -iegee.net -iegourl.com -iejiu.com -ieliulanqi.com -ielts68.com -ieltschn.com -iemblog.com -ienjoys.com -ienjoys.mobi -ieplconn.com -ierhou.com -iermu.com -iershoushu.com -iesdouyin.com -ieshu.com -iessay100.com -ietdata.com -iewb.net -iewie.org -iewzx.com -iexx.com -iezuo.com -ifabao.com -ifabiao.com -ifaclub.com -ifahao.com -ifanbei.com -ifangarden.com -ifanggo.com -ifangka.com -ifanr.com -ifanr.in -ifanrusercontent.com -ifareast.com -ifavart.com -ifaxin.com -ifaxin.org -ifc58.com -ifchange.com -ifeimo.com -ifeiyu.net -ifeng.co -ifeng.com -ifeng.fm -ifeng.name -ifengcdn.com -ifenghui.com -ifengimg.com -ifenglian.com -ifengo.com -ifengpai.com -ifengtui.com -ifenguo.com -ifengweekly.com -ifengwoo.com -ifensi.com -ifenso.net -ifenxi.com -ifere.com -ifeve.com -ifhzh.com -ifindever.com -ifindhs.com -ifintechnews.com -ifiretech.com -ifitbox.com -ifjing.com -iflying.com -iflyink.com -iflyos.vip -iflyread.com -iflyrec.com -iflyresearch.com -iflysec.com -iflytek.com -iflytektstd.com -ifma-china.org -ifmicro.com -ifmx.cc -iforce-media.com -iforl.com -ifoxfactory.com -ifread.net -ifreecdn.com -ifreecomm.com -ifreedom001.com -ifreepsd.com -ifreetalk.com -ifreeurl.com -ifreewallpaper.com -ifromvr.com -ifseclabs.com -iftell.com -ifttl.com -ifukua.com -ifulelol.com -ifumanhua.net -ifundstore.com -ifunmac.com -ifunvip.com -ifutest.com -ifutureworks.com -ifval.com -ifxsb.com -ifxtx.com -ifzxs.cc -igame007.com -igame58.com -igamecj.com -igao7.com -igaoda.com -igbox.net -igdmfg.com -igdzc.com -igea-un.org -igeak.com -igeekbar.com -igeidao.com -igelou.com -igenetech.com -igengmei.com -igerun.com -igeshui.com -igetget.com -igetui.com -igevin.info -igexin.com -igigo.net -igo180.com -igo998.com -igome.com -igooma.com -igorism.com -igoyx.com -igreatdream.com -igslb.net -igsttech.com -iguanyu.com -iguazutraffic.xyz -iguder.com -iguitar.me -igumo.cc -iguoguo.net -iguoplay.com -iguowan.com -igushuo.com -iguxuan.com -igwfmc.com -ih5games.com -ihacksoft.com -ihaier.co -ihaier.com -ihaima.com -ihaiu.com -ihalf.co -ihanghai.com -ihanhua.com -ihani.tv -ihanshi.com -ihaoge.net -ihaoxi.com -ihaozhuo.com -ihappy.vip -ihaveu.com -ihaveu.net -ihdt.tv -ihecc.org -ihei5.com -iheima.com -iheima.net -iheit.com -ihengheng.com -ihenji.com -ihepa.com -ihetou.com -ihewro.com -ihggccampaign.com -ihhubei.com -ihint.me -ihipop.info -ihisce.com -ihitui.com -ihjiu.com -ihktv.com -ihlnews.com -ihomefnt.com -ihomesoft.net -ihoms.com -ihongma.com -ihongpan.com -ihongqiqu.com -ihongyou.com -ihonker.org -ihou.com -ihr360.com -ihref.com -ihrscloud.com -ihuaben.com -ihuan.me -ihuangshi.com -ihuanling.com -ihuayou.net -ihuazhan.net -ihui.com -ihuidian.com -ihuigo.com -ihuikou.net -ihuipao.com -ihuiu.com -ihuman.com -ihumand.com -ihungyi.com -ihuochaihe.com -ihuoqiu.com -ihuoyan.com -ihuyi.com -ihuzuan.com -ihwrm.com -ihx.cc -ihxlife.com -ihypo.net -ihzzy.com -ii.cc -ii010.com -ii090.com -ii3g.com -ii74.com -ii77.com -iiad.com -iianews.com -iiaq.net -iibechina.com -iibq.com -iicp.net -iidns.com -iidvd.com -iiedns.xyz -iiexe.com -iifab.com -iigs9.com -iii80.com -iiiff.com -iiii1i.net -iiiimg.com -iiijk.com -iiilab.com -iiiview.net -iikuzhan.com -iikx.com -iiloo.com -iincn.net -iiong.com -iireadiness.com -iirii.com -iirsys.com -iis3.com -iis7.com -iischool.com -iisicp.com -iisp.com -iissbbs.com -iissnan.com -iitcp.com -iitoutiao.com -iivey.com -iiycy.com -iiyi.com -iiyibbs.com -ijac.net -ijh.cc -ijia360.com -ijiandao.com -ijiangyin.com -ijianhu.com -ijianji.com -ijiaodao.com -ijiaren.com -ijiatv.com -ijie.com -ijiedian.com -ijiela.com -ijindun.com -ijingdi.com -ijinshan.com -ijinzhuan.com -ijishu.cc -ijita.com -ijiujiao.com -ijiwei.com -ijiwen.com -ijizhi.com -ijjnews.com -ijnqc.com -ijogame.com -ijq.tv -ijsp.net -ijtoo.com -ijuanshi.com -ijuer.com -ijuhepay.com -ijunhai.com -ijunxun.com -ijutou.net -ijuwu.com -ijxkj.com -ijzhang.com -ik123.com -ik3cloud.com -ikacc.com -ikafan.com -ikaixun.com -ikaka.com -ikakuedu.com -ikancai.com -ikanchai.com -ikandian.com -ikanfan.com -ikang.com -ikao100.com -ikaoguo.com -ikaolaa.com -ikcd.net -ikcest.org -ikcrm.com -ikcw.com -ike-global.com -ikeguang.com -ikemeng.com -ikeyigou.com -ikikanan.com -ikjtao.com -ikjzd.com -ikkwx.org -ikmt.net -ikonfx.com -ikongjian.com -ikongjun.com -ikonke.com -ikoo8.com -ikozn.com -iksea.com -iku8.com -ikuai8-wifi.com -ikuai8.com -ikuailian.com -ikuaiy.net -ikuajing.com -ikuvn.com -ikx.me -ikxin.com -il8r.com -ilab-x.com -ilaic.org -ilaisa.com -ilaitui.com -ilancai.com -ilanluo.com -ilanni.com -ilanx.net -ilanx0.net -ilast.cc -ilaw66.com -ilawpress.com -ilazycat.com -ildhy.com -ileci.com -ileedarson.com -ileehoo.com -ilego.club -ilewan.com -ilewen.com -iliangcang.com -iliaoning.net -ilibrand.com -ilidubj.net -ilife69.com -ilifesmart.com -ilingdai.com -ilinkee.com -ilinki.net -ilinkone.com -ilinux.xyz -ilinuxkernel.com -ilinyi.net -ilishi.com -ilishi.net -ilitu.com -iliuliu.com -ilixiangguo.com -iliyu.com -ilkwork.com -illumpaper.com -ilohas.com -iloli.bid -ilongre.com -ilongterm.com -iloveanan.com -ilovefishc.com -ilovelvxing.com -iloveyou14.com -iloveyou3412.com -iloveyouxi.com -ilovezuan.com -iloxp.com -ilrose.com -ilsungf.com -ilucking.com -ilucong.net -ilufan.com -iluoy.com -iluoyang.com -iluqi.com -ilustrepro.com -iluvatar.ai -ilv6.com -ilvping.com -ilvxing.com -ilxdh.com -im-ad.com -im-cc.com -im020.com -im050.com -im17.com -im170.com -im286.com -im286.net -im2maker.com -im5.org -im520.com -im577.com -im87.net -imac.hk -imageaccelerate.com -imageedu.com -imagefz.com -imagepy.org -images-cache.com -images.apple.com -images.apple.com.akadns.net -images.apple.com.edgekey.net.globalredir.akadns.net -images.benchmarkemail.com -images.samsung.com -imageter.com -imagetotxt.com -imaginde.com -imags-google.com -imahui.com -imaibo.net -imaijia.com -imaitu.com -imalljoy.com -imandarin.net -imaojiang.com -imarketchina.com -imaschina.com -imasdk.googleapis.com -imatchic.com -imatlas.com -imayitxt.com -imazingchina.com -imbackr.com -imbatv.net -imbeer.com -imblog.in -imbossdog.com -imbtk.com -imbusy.me -imcaviare.com -imcec.org -imcn.me -imdac.org -imdadui.com -imdaike.com -imdo.co -imdou.net -imdst.com -imedao.com -imedicalai.com -imedp.com -imeete.com -imeete.net -imeibian.com -imeidb.com -imeihei.com -imeiju.cc -imeiju.io -imeijutt.com -imeitou.com -imekaku.com -imeme.tv -imesong.com -imever.me -imexue.com -imfer.me -imfirewall.com -img-space.com -img-sys.com -img.samsungapps.com -img005.com -img168.net -img16888.com -img4399.com -img898.com -imgcdc.com -imgcdn2.com -imgchr.com -imgeek.org -imgii.com -imglefeng.com -imglink.win -imgo.tv -imgscdn.com -imgsha.com -imgshangman.com -imgsina.com -imgtu.com -imhan.com -imhanjie.com -imhdr.com -imhuasheng.com -imhuchao.com -imhunk.com -imiaobige.com -imibaby.net -imicang.com -imiker.com -imindmap.cc -iminho.me -iminisd.com -imipy.com -imiqian.com -imitui.com -imjiayin.com -imkerwin.com -imkevinyang.com -imkira.com -imlaidian.com -imlcl.com -imlgm.com -imlianai.com -imlike.cc -imliuyi.com -imliyan.com -immi.cc -immi520.com -immiexpo.com -immivip.com -immomo.com -immomogame.com -immusician.com -immusoul.com -immwall.com -imnerd.org -imnight.com -imobile-ent.com -imobon.com -imochen.com -imochy.com -imoduo.com -imoe.me -imoeer.com -imofan.com -imoffice.com -imolink.com -imomoe.com -imomoe.in -imomoe.io -imomoe.jp -imooc.com -imoocc.com -imoodou.com -imoonfm.com -imooo.com -imopan.com -imosi.com -imotao.com -imoxiu.com -imp3.net -imperfectionstudio.com -imperial-vision.com -impk.cc -impk113.com -impnails.com -impng.com -importnew.com -impta.com -imqq.com -imqueenapp.com -imququ.com -imrfresh.com -imrobotic.com -imshell.com -imshuai.com -imshusheng.com -imsilkroad.com -imsle.com -imslr.com -imsobrr.com -imspm.com -imsun.net -imsxm.com -imtmp.net -imtuan.com -imtvs.cc -imuke.com -imuo.com -imushan.com -imuum.com -imw.me -imwaco.com -imwallet.com -imweb.io -imwenhua.com -imwexpo.com -imwork.net -imxh.com -imxingzhe.com -imxpan.com -imycdn.com -imydl.com -imydl.tech -imydns.net -imyip.net -imys.net -imysql.com -imyuedu.com -imzhitu.com -imzhongxin.com -imzhou.com -in-en.com -in001.com -in189.com -in66.com -in6way.com -in800.com -in955.com -inabr.com -inad.com -inanrenbang.com -inapian.com -inass.org -inbeijing.org -inbilin.com -inbooker.com -inboxarchiver.com -inc365.com -incake.net -incensechina.com -inchangling.com -incloudexpo.com -incnjp.com -incoto.com -ind-app-comp.com -ind9ed.com -indaboom.com -indexedu.com -indexedu.net -indiancn.com -indics.com -indiehacker.im -indielight.net -indienova.com -indier.com -indmi.com -indomoge.com -indongfang.com -industrial-automation-beijing.com -induta.com -indvaan.com -ineeke.com -ineice.com -ineng.org -inengyuan.com -inesa-it.com -inetgoes.com -inetnoc.com -inewhope.com -inewoffice.com -inewpower.com -inewya.com -inezha.com -infaq.net -infarts.net -infertilitybridge.com -inficn.com -infineon-autoeco.com -infineon-power-rf.org -infineonic.org -infinitescript.com -infinitiownerclub.com -infinityarts.net -infinitynewtab.com -info.cc -info10.com -info110.com -info35.com -infobidding.com -infobigdata.com -infocomm-journal.com -infoier.com -infoipwest.com -infong.net -infoobs.com -infoqstatic.com -inforbus.com -inforguard.net -informrack.com -inforsec.org -infoshow.net -infosoft.cc -infotorch.net -infovc.com -infowuxi.com -infoxa.com -infoxgame.com -infoxmation.com -infzm.com -ing10bbs.com -ing2ing.com -ingageapp.com -ingben.com -ingcore.com -ingdan.com -ingenic.com -ingkee.com -ingping.com -ingressplay.com -inhdd.com -inhe.net -inhehuo.com -inhi.kim -ini3e.com -inibiru.com -inicoapp.com -inidc.net -inimc.com -ininin.com -init-p01md-lb.push-apple.com.akadns.net -init-p01md.apple.com -init-p01st-lb.push-apple.com.akadns.net -init-p01st.push.apple.com -init-s01st-lb.push-apple.com.akadns.net -init-s01st.push.apple.com -initialview.com -initnil.com -inja.com -injoyflower.com -injz.net -inkankan.com -inkanke.com -inkcn.com -inke.com -inke.tv -inkedginger.com -inkeygo.com -inkonote.com -inktok.com -inkuai.com -inlaylink.com -inlishui.com -inlovektv.com -inlsd.org -inmeng.net -inmuu.com -inneed.club -innlym.me -innojoy.com -innotechx.com -innotron.com -innovatedigital.com -innovisgroup.com -innsue.com -innvitor.com -inoherb.com -inoneh5.com -inoteexpress.com -inovance-automotive.com -inpandora.com -inpla.net -inplayable.com -inpower.cc -inputmore.com -inrugao.com -ins-home.com -insarticle.com -inshockgroup.com -insisi.com -insnail.com -inspur.com -inspurpower.com -instr365.com -insun-china.com -insuns.com -inswindow.com -insxz.com -int-agri.com -int800.com -intaek.com -intcache.net -intdmp.com -intekey.com -intel-space.com -intelcupid.com -intelligentmanufactory.com -intelvisioncn.com -inter12.org -inter1908.net -interbator.com -internationalbrand.net -internbird.com -internet-dns.com -internetcaff.com -internetke.com -internettrademark.com -internetworld.cloud -intertid.com -intiea.org -intio.org -intlscdn.com -intmedic.com -intmian.com -intohard.com -intopet.com -intovfx.com -intowz.com -intozgc.com -intple.com -intsavi.com -intsig.net -intsweet.com -intwho.com -intwk.com -inuobi.com -inurl.org -inveno.com -inverter.so -invescogreatwall.com -investank.com -investguider.com -investoday.net -investorscn.com -investstkitts.org -inwaishe.com -inwatch.cc -inxedu.com -inyuapp.com -inzone-auto.com -inzotek.com -ioa365.com -ioage.com -iocrest.com -ioeyjsb.com -ioffershow.com -ioffice100.com -ioguma.com -ioio.in -ioio.pw -ioiox.com -iok.la -iol8.com -iomsew.com -ioneball.com -ionewu.com -ionic.wang -ionic8.com -ionichina.com -ionicliquid.org -iooeoo.com -iopenhec.com -ioperat.com -ioqq.com -ios1234.com -ios8.app -iosapps.itunes.g.aaplimg.com -iosappx.com -iosask.com -ioschina.cc -iosfengwo.com -ioshost.qtlcdn.com -iosinit.com -iosmu.com -iosre.com -ioswift.org -iot-online.com -iot101.com -iotachem.com -iotbay.com -iotcetc.com -iotexpo.org -iotfair.net -iotmag.com -iotpai.com -iotwrt.com -iotxing.com -iovweek.com -iowiki.com -ip-china.org -ip-guard.net -ip.fm -ip008.com -ip138.com -ip192.com -ip285.com -ip33.com -ip518.com -ip87.com -ipadown.com -ipadview.com -ipagame.net -ipaiban.com -ipail.com -ipalfish.com -ipalmap.com -ipampas.com -ipanda.com -ipandao.com -ipandata.com -ipanshi.com -ipaomi.com -ipaotuan.com -ipason.com -ipay.so -ipaylike.com -ipcc.com -ipcchain.org -ipcfun.com -ipchaxun.com -ipchina.com -ipclife.net -ipcmen.com -ipcool.info -ipcorecatalog.com -ipcxz.com -ipdaili.com -ipddz.com -ipdftool.com -ipdianhua.com -ipdsms.com -ipease.net -ipehua.com -ipengchen.com -ipengtai.com -iper2.com -ipexp.com -ipfeibiao.com -ipfen.com -ipfsbit.com -ipgoal.com -iph123.com -iphone-ld.apple.com -iphonediule.com -iphp8.com -ipianchang.com -ipiao.com -ipin.com -ipinba.com -ipinyou.com -ipip.net -ipktv.com -ipku.com -iplascloud.com -iplaymtg.com -iplaypy.com -iplaysoft.com -ipmay.com -ipmph.com -ipo.hk -ipo.la -ipo3.com -ipoceo.com -iposeidongame.com -ipple.net -ipplus360.com -ippzone.com -ipr114.net -ipr123.com -ipr66.com -iprchn.com -iprdaily.com -ipresst.com -iprun.com -ipsir.net -ipssh.net -iptalent.com -iptrm.com -ipuu.net -ipuyuan.com -ipv4.host -ipv6.la -ipyker.com -ipyy.com -iq123.com -iqalliance.org -iqcrj.com -iqdii.com -iqdnet.com -iqianbang.com -iqianggou.com -iqianjin.com -iqianyue.com -iqihang.com -iqilu.com -iqilun.com -iqinbao.com -iqing.com -iqing.in -iqingdao.com -iqingren.com -iqingua.com -iqishu.la -iqitu.com -iqiwx.com -iqiyi.com -iqiyi.kim -iqiyi.pub -iqiyi.space -iqiyi6123.com -iqiyih5.com -iqiyipic.com -iqshw.com -iquanba.com -iquanben.com -iquanfen.com -iquanwai.com -iqucai.com -iqujing.com -iquncha.com -iqunix.com -iqunix.store -iqupdate.com -iquwang.com -iqxbf.com -iqxedu.com -iqycamp.com -iqying.com -iradwine.com -iranshao.com -iraoping.com -iray.me -ircmnr.com -iread.cf -ireader.com -ireadercity.com -ireaderm.net -ireadweek.com -ireadyit.com -irealbest.com -irealtech.com -irecyclingtimes.com -irelxtech.com -iresearchad.com -iresearchchina.com -irest.tv -irising.me -irlianmeng.com -iroader.me -irockbunny.com -irockwill.com -iroing.com -ironfishchina.com -ironghui.com -ironxu.com -irootech.com -irory.me -irs01.com -irs01.net -irs03.com -irskj.com -iruanmi.com -iruidai.com -iruidian.com -iruixing.com -irukou.com -irunyan.com -is-programmer.com -is1-ssl.mzstatic.com -is1.mzstatic.com -is2-ssl.mzstatic.com -is2.mzstatic.com -is26.com -is3-ssl.mzstatic.com -is3.mzstatic.com -is36.com -is4-ssl.mzstatic.com -is4.mzstatic.com -is5-ssl.mzstatic.com -is5.mzstatic.com -is777.com -isaced.com -isamanhua.com -isaohao.com -isaonian.com -isay365.com -isbdai.org -iscrv.com -isdox.com -iseedog.com -iseoku.com -iseopai.com -isevenhouse.com -isfashion.com -isfirst.net -ish168.com -ishaanxi.com -ishala.com -ishang.net -ishangman.com -ishangtong.com -ishangu.com -ishangzu.com -ishanshan.com -ishansong.com -ishaohuang.com -ishare20.net -isharebest.com -ishareh5.com -isharepc.com -isheet.net -isheji5.com -ishenbao.com -ishengyiren.com -ishenping.com -ishenyou.com -ishhuo.com -ishici.com -ishiker.com -ishoujizhuan.com -ishowchina.com -ishowx.com -ishugui.com -ishuhui.com -ishuhui.net -ishuirong.com -ishuiyun.com -ishumei.com -ishuocha.com -ishuqi.com -isigu.com -isilicontech.com -isinosig.com -isixue.com -iskryou.com -isky000.com -iskylinem.com -iskysoft.com -iskytree.net -iskyworth.com -islide.cc -isluo.com -ismartgo.com -ismartware.com -isme.pub -isming.me -iso-est.com -iso-iso9000.com -isobar.tech -isoft-linux.org -isoftstone.com -isoftwind.com -isoo.cc -isorange.com -isoshu.com -isoucai.com -isoyes.com -isoying.com -isoyu.com -isp.cx -ispeaken.com -ispecial.xyz -isport2008.com -ispservice.cc -isqhy.com -israel-cars-rentals.com -isrcb.com -isscloud.com -issconline.com -issedu365.com -isthnew.com -istpei.com -istreamsche.com -istudyinchina.org -istylepdf.com -isudaji.com -isuike.com -isumiao.com -isummi.com -isun.org -isuoda.com -isux.us -isuzhou.me -isvee.com -isvjcloud.com -iswifting.com -it-api.com -it-bound.com -it-crazy.net -it-home.org -it-shit.com -it.link -it007.com -it086.net -it1069.com -it120.cc -it131.org -it1352.com -it163.com -it165.net -it168.com -it2021.com -it376.com -it399.com -it525.com -it528.com -it578.com -it610.com -it666.com -it689.com -it69.net -it707.com -it736.com -it7e.com -it7t.com -it8008.com -it892.com -it918.com -it985.com -it9g.com -itaic.org -itakeeasy.com -italyclassico.com -italycn.com -itamt.com -itangbole.com -itangyuan.com -itanhang.com -itanlian.com -itanzi.com -itao.com -itaoke.org -itaokecms.com -itaotm.com -itaotuo.com -itavcn.com -itbegin.com -itbeihe.com -itbiaoju.com -itbilu.com -itbkz.com -itblw.com -itbole.com -itbook5.com -itboth.com -itbour.com -itboy.net -itbulu.com -itbuy.com -itbyc.com -itbyte.net -itcacfo.com -itchaguan.com -itcodemonkey.com -itcpn.net -itczh.com -itdaan.com -itdabao.com -itdcw.com -itdhz.com -itdiffer.com -itdks.com -itdlc.com -itdoor.net -itdos.com -itdos.net -iteblog.com -itechate.com -itechol.com -itechwall.com -itedou.com -iteedu.com -iteer.net -itelly.net -itellyou.com -itensoft.com -itepian.com -iter168.com -iterduo.com -itest.info -itestworld.com -itetc.org -itexamprep.com -iteye.com -itfanr.cc -itfans.net -itfeed.com -itfenghui.com -itfly.net -itfw5.com -itgd.net -itgeeker.net -itgege.com -itgemini.net -itgo.me -itgochina.com -itgoodboy.com -itgxs.com -ithaowai.com -ithard.com -ithat.net -itheat.com -itheima.com -ithelei.com -ithenticatecn.com -ithml.com -ithome.com -ithome.net -ithor.com -ithor.net -ithothub.com -ithov.com -itiankong.com -itiankong.net -itiexue.net -itiger.com -itilxf.com -itimep.com -itings.com -itingwa.com -itit.io -itiyan.net -itiyun.com -itjcku.com -itjk.me -itjoy.net -itjspx.com -itjuzi.com -itkeyword.com -itkoala.com -itkoudai.com -itlanbao.com -itlu.org -itluantan.com -itmanbu.com -itmeseji.com -itmian4.com -itmind.net -itminus.com -itmo.com -itmoocs.com -itmop.com -itmsm.com -itmuch.com -itmyhome.com -itnan.net -itnb.cc -itnec.org -itnihao.com -itniwota.com -itnpc.com -itnpyfwshe.com -itnxs.com -itocp.com -itoec.org -itogame.com -itokit.com -itokoo.com -itonghui.com -itools.hk -itopbaby.com -itopers.com -itophis.com -itopic.org -itopplay.com -itopsdk.com -itotaku.net -itotii.com -itouchchina.com -itougu.com -itoumi.com -itoutiao.co -itoutiaoimg.com -itoutiaostatic.com -itouxian.com -itouzi.com -itpaidui.com -itpeo.net -itpon.com -itpow.com -itppi.org -itpub.net -itpux.com -itpux.net -itpwd.com -itrace.cc -itran.cc -itranca.com -itranslater.com -itrid.com -itrip.com -itruelife.com -itruke.com -itry.com -its114.com -itscoder.com -itshai.com -itsiwei.com -itsk.com -itslaw.com -itsmephoto.net -itsogo.net -itsoku.com -itstack.org -itsun.com -itsvse.com -ittribalwo.com -ituad.com -ituba.cc -itugo.com -ituibar.com -ituite.com -itunes-apple.com.akadns.net -itunes.apple.com -itunesconnect.apple.com -itushuo.com -itutu.tv -ituu.net -itwanger.com -itwendao.com -itwind.net -itwlw.com -itwork.club -itwulin.com -itxinwen.com -itxm.net -itxst.com -itxueguan.com -itxuexi.com -itxueyuan.com -itxueyuan.org -itxuye.com -itye.org -ityears.com -itying.com -ityouknow.com -itypen.com -ityuan.com -ityxb.com -itzcdn.com -itzh.org -itzhp.com -itziy.com -itzjj.com -itzk.com -itzm.com -itzmx.com -itzmx.net -itzpark.com -iu18.com -iu95522.com -iuban.com -iucars.com -iucdn.com -iudodo.com -iueux.com -iufida.com -iuinns.com -iuliao.com -iuni.com -iuniware.com -iuoooo.com -iuplus.com -iusheng.com -iuuu9.com -iuv360.com -iuvision.com -iuynfg.com -ivali.com -ivan.xin -ivemusic.net -ivideostar.com -iviewui.com -ivixivi.com -ivmoe.com -ivocaloid.com -ivsky.com -ivu4e.com -ivvmi.com -ivvy.org -ivwen.com -ivy-school.org -ivybaby.me -ivycoffee.com -ivydad.com -ivydom.com -ivynuts.com -ivypub.org -ivyschools.com -ivysoon.com -ivysun.net -ivywing.me -iwala.net -iwalls.vip -iwan0.com -iwan4399.com -iwanbei.com -iwanboy.com -iwangding.com -iwangnan.com -iwanoutdoor.com -iwanvr.com -iwanws.com -iwanyl.com -iwapan.com -iwasai.com -iwatch365.com -iwatch365.net -iwcoo.com -iwebad.com -iwebchoice.com -iwebxy.com -iwecan.net -iweeeb.com -iweek.ly -iweekapi.com -iweidu.net -iweizhijia.com -iweju.com -iwellen.com -iwencai.com -iwenson.com -iwgame.com -iwhgao.com -iwhr.com -iwin10.cc -iwin10.com -iwin10.net -iwingchina.com -iwiscloud.com -iwjw.com -iwncomm.com -iwodu.com -iwordnet.com -iworm.net -iwoshang.com -iwpai.com -iwshang.com -iwucha.com -iwuly.com -iwumeiti.com -iwwwwwi.com -iwxapi.com -iwyv.com -iwyvi.com -iwzwy.com -iwzxi.com -ixarea.com -ixbd.net -ixbren.net -ixcv.com -ixdba.net -ixdc.org -ixfc.net -ixiangche.com -ixiangyu.com -ixianlai.com -ixianzong.com -ixiao9.com -ixiaochengxu.cc -ixiaolu.com -ixiaomiyun.com -ixiaoyuanzhi.com -ixiatxt.com -ixibeiren.com -ixigua.com -ixiguan.com -ixiguavideo.com -iximo.com -ixingji.com -ixinglu.com -ixingmei.com -ixingpan.com -ixinmanzhishe.com -ixinqing.com -ixintui.com -ixinwei.com -ixiqi.com -ixiqin.com -ixiumei.com -ixiupet.com -ixixili.com -ixizang.com -ixmu.net -ixniang.com -ixpub.net -ixs.la -ixsch.com -ixu.me -ixueshu.com -ixueyi.com -ixxm.com -ixxplayer.com -ixyzero.com -iy51.com -iyangcong.com -iyaou.com -iyatrip.com -iyaxi.com -iyaxin.com -iyaya.com -iyaya.info -iyb.tm -iycdm.com -iycsky.com -iydsj.com -iydu.net -iyeeda.com -iyeele.com -iyenei.com -iyewu.club -iyingdi.com -iyingji.com -iyinxun.com -iyiou.com -iyiqi.com -iyishengyuan.com -iyiyun.com -iyizhai.com -iyocloud.com -iyong.com -iyooread.com -iyoowi.com -iyoucai.com -iyoudui.com -iyouguoo.com -iyouhun.com -iyoujia.com -iyoujiao.net -iyoule.com -iyouman.com -iyouqian.com -iyouxia.com -iyouxun.com -iytc.net -iyuedan.com -iyuedian.com -iyunbao.com -iyunbiao.com -iyunmai.com -iyunshu.com -iyuntian.com -iyunv.com -iyunyue.com -iyunzk.com -iyuxy.com -iyx668.com -iyxku.com -iyyin.com -iyz168.com -izacholsm.com -izamay.com -izaodao.com -izazamall.com -izestchina.com -izhangchu.com -izhangheng.com -izhaohe.com -izhaowo.com -izhenxin.com -izhequ.com -izheteng.com -izhihuicheng.net -izhihuo.com -izhikang.com -izhiliao.com -izhiqun.com -izhishi.com -izhizhao.com -izhongxia.com -izhuanfa.com -izhuce.com -izihun.com -iziyo.com -izjj.com -izmm.me -izmzg.com -izshare.net -izt6.com -izt8.com -iztwp.com -iztyy.com -izuche.com -izuchecdn.com -izudian.com -izuiyou.com -izumicn.com -izzx.cc -j-h-k.com -j-smu.com -j1.com -j1health.com -j1sc.com -j3pz.com -j66.net -j9p.com -jaadee.com -jaadee.net -jabizb.com -jacklm2.com -jackmt.com -jackon.me -jackslab.org -jackxiang.com -jacky-blog.com -jackyang.me -jackyyf.com -jackzhu.com -jadetowerccrc.com -jae.sh -jaeapp.com -jaeosc.com -jafeney.com -jakegame.com -jakehu.me -jakting.com -jals1rfsfo.com -jamespan.me -jamidol.com -jammyfm.com -jamoxi.com -jampotgames.com -jamxio.com -janbao.net -jandan.com -jandan.net -janezt.com -janmeng.com -janpn.com -janrain.biz -janxing.com -jappstore.com -jar-world3000.com -jarhu.com -jartto.wang -jaskni.com -jasolar.com -jason-z.com -jasongj.com -jasperxu.com -jasve.com -jatd.org -java-er.com -java1234.com -java2000.net -java2008.com -java2class.net -javaapk.com -javabloger.com -javaboy.org -javacui.com -javadoop.com -javaear.com -javaeye.com -javafxchina.net -javaresearch.org -javascriptcn.com -javashuo.com -javastudy.cloud -javatang.com -javaweb.io -javawind.net -javaxxz.com -javazhiyin.com -javazx.com -javier.io -javps.com -jaxcx.com -jaycn.com -jaydon.cc -jayfc.com -jayfu.tk -jayme.net -jaytrn.com -jazzyear.com -jb-hacker.com -jb1000.com -jb51.cc -jb51.net -jbaier023.com -jbaobao.com -jbb.one -jbcz.tv -jbczzcj.com -jbdown.com -jbelf.com -jbfoundry.com -jbhdq.com -jbl100.com -jblts.com -jbpbox.com -jbqipa.com -jbryun.com -jbtai.com -jbwtz.com -jbxy.com -jbzj.com -jbzwread.com -jbzyk.com -jbzyw.com -jc-ai.com -jc-dl.net -jc-pro.com -jc-saas.com -jc-smt.com -jc-space.com -jc0531.com -jc170.com -jc315.com -jc35.com -jc56.com -jc85.com -jcbctv.com -jccsoc.com -jccug.com -jcedu.org -jcf94.com -jcgcn.com -jchelec.com -jchl.com -jchla.com -jchxmc.com -jcj965.com -jcjpt.com -jcku.com -jcloud-cache.com -jcloud-cdn.com -jcloud.com -jcloudcache.com -jcloudcs.com -jcloudec.com -jcloudedge.com -jcloudgslb.com -jcloudimg.com -jcloudlb.com -jcmob.net -jcnk120.com -jcodecraeer.com -jcpeixun.com -jcqczb.com -jcqzw.com -jcrb.com -jcsb.com -jcsfs.com -jcsjt.com -jcspkj.com -jcssyxh.com -jctmj.net -jctrans.com -jctuku.com -jcu.cc -jcwcn.com -jcwgk.com -jcwxiao.com -jcyedan.com -jcyx2019.com -jczhijia.com -jczhiyao.com -jczqw.com -jd-88.com -jd-app.com -jd-bbs.com -jd-df.com -jd-ex.com -jd-fm.com -jd-tv.com -jd.co -jd.com -jd.hk -jd100.com -jd360.hk -jd5.com -jdair.net -jdajf.com -jdb100.com -jdbbs.com -jdbbx.com -jdbpcb.com -jdbusiness.com -jdcache.com -jdcapital.com -jdccie.com -jdcdn.com -jdcf88.com -jdcjsr.com -jdcloud-oss.com -jdcloud.com -jdcloudcache.com -jdcloudedge.com -jdcloudnaming.net -jdcloudstatic.net -jdcloudwaf.com -jdcq.net -jdctky.com -jdd.com -jddaw.com -jddb.net -jdddata.com -jddebug.com -jddglobal.com -jddj.com -jddmoto.com -jdedu.net -jdfcloud.com -jdfhq.com -jdfschool.com -jdgod.com -jdgslb.com -jdgwdq.com -jdhhmd.com -jdhonline.com -jdhyplay.com -jdiy.club -jdjob88.com -jdjrdns.com -jdjygold.com -jdjys.com -jdkcb.com -jdkindle.com -jdlxzx.com -jdnettv.com -jdnews.net -jdon.com -jdpay.com -jdpaydns.com -jdplay.com -jdsinspection.com -jdtjy.com -jdvisa.com -jdw001.com -jdwan.com -jdwl.com -jdworldwide.com -jdwx.cc -jdwx.info -jdwxmagazine.com -jdwxs.com -jdwxwz.com -jdxc.net -jdxcw.com -jdxfw.com -jdxlt.com -jdxs5200.net -jdy.com -jdycdn.com -jdyou.com -jdypcg.com -jdypf.com -jdzbth.com -jdzeduyun.com -jdzj.com -jdzjdz.com -jdzmc.com -jdzol.com -jdzol.net -jeacar.com -jeagine.com -jeanphy.online -jeanssalon.com -jeast.net -jeasyui.net -jeasyuicn.com -jedex56.com -jedi-games.com -jedoo.com -jeecg.com -jeecg.org -jeecms.com -jeejen.com -jeekun.com -jeep-leica-prize.com -jeeplus.org -jeepshoe.net -jeepxie.net -jeesci.com -jeesite.com -jeeyaa.com -jefang.com -jeffdesign.net -jeffjade.com -jeffstudio.net -jegotrip.com -jehudf.com -jelivor.com -jelleybrown.com -jellow.club -jellow.site -jellymoo.com -jellythink.com -jemabrit.com -jenglishj.com -jeoshi.com -jerehedu.com -jerei.com -jerryzou.com -jescard.com -jesgoo.com -jestq.com -jesusw.com -jethoo.com -jetmobo.com -jetneed.com -jetsum.com -jetsum.net -jevictek.com -jewellworld.com -jewelryseeds.com -jexus.org -jeyi.com -jf258.com -jf2688.com -jf88811.com -jf95.com -jf9p.com -jfbcb.com -jfbuilding.com -jfcaifu.com -jfcdns.com -jfcgf.com -jfdaily.com -jfdown.com -jfduoduo.com -jfdwy.com -jfedu.net -jfenz.com -jfewle.com -jfh.com -jfinal.com -jfinfo.com -jfocus.net -jfq.com -jfrogchina.com -jfshare.com -jfsky.com -jfstage.com -jfstatic.com -jftnz.com -jfuwu.com -jfxc.com -jfxqczl.com -jfydgame.com -jfyiyao.com -jfz.com -jfzhiyao.com -jfzkchina.com -jfzw.com -jgames.net -jgaoxiao.com -jgcqgf.com -jgdun.com -jgew3d.com -jgg09.com -jggame.net -jggjj.com -jgsdaily.com -jgshwx.com -jguo.com -jgvnews.com -jgwsoft.com -jgxlzd.com -jgy.com -jgyflqc.com -jgyljt.com -jgzx.org -jgzyw.com -jh0110.com -jh3j.com -jh61588.com -jh8k.com -jhcb.net -jhcms.com -jhctbank.com -jhdqz.com -jhdxjk.com -jhfl.com -jhforever.com -jhgtgb.com -jhgzn.net -jhlengku.com -jhm2012.com -jhnsh.com -jhnsyh.com -jhonge.net -jhonse.com -jhpz58.com -jhqshfly.com -jhrbaby.com -jhrcbank.com -jhsbggw.com -jhsctv.com -jhsdai.com -jhsfojiao.com -jhssapp.com -jhsssq.com -jht868.com -jhua168.com -jhwaimai.com -jhwl444.com -jhwrsq.com -jhxms.com -jhyongyou.com -ji36.net -ji7.com -jia-he-jia.com -jia.com -jia360.com -jia400.com -jiaads.com -jiaapps.com -jiabangcnc.com -jiabasha.com -jiacai001.com -jiachong.net -jiadianpj.com -jiadingqiang.com -jiae.com -jiafang168.com -jiafenqi.com -jiagedan.com -jiagew762.com -jiagle.com -jiagou1216.com -jiagouyun.com -jiaguhome.com -jiagulun.com -jiaheu.com -jiahongjingmao.com -jiahuacinema.com -jiahuafireworks.com -jiahuaming.com -jiahuism.com -jiain.net -jiaji.com -jiaji28.net -jiajia.tv -jiajiakt.com -jiajianhudong.com -jiajiao-edu.com -jiajiao114.com -jiajiaoban.com -jiajicompany.com -jiaju-hy.com -jiaju.cc -jiaju.com -jiaju100.com -jiajucj.com -jiajuketang.com -jiajumi.com -jiajuol.com -jiakaobaodian.com -jiakaodashi.com -jiakeshuma.com -jialaxin.cc -jialebao.cc -jialeo2o.com -jialez.com -jialidun.com -jializyw.com -jiameng.com -jiameng001.com -jiamengdp.com -jiamengfei.com -jiamengwoba.com -jiamiantech.com -jiaming.pro -jiaminghi.com -jiamisoft.com -jiamofang.net -jian.net -jianada-qianzheng.com -jianai360.com -jianbaizhan.com -jianbaolife.com -jianbh.com -jianbihua.cc -jianbihua.org -jianbihua360.com -jianbihuadq.com -jianbing.com -jiancai.com -jianchesl.com -jianchihu.net -jianchiyundong.com -jiandaima.com -jiandan.net -jiandana.com -jiandansousuo.com -jiandanxinli.com -jiandaopay.com -jiandaoyun.com -jiandati.com -jiando.com -jiandudu.com -jiane86.com -jianfei.com -jianfei.net -jianfeiba.com -jianfeibaike.com -jianfengstudio.com -jiangbeishuicheng.com -jiangboshidai.com -jiangcdn.com -jiangchaochina.com -jiangcheng.work -jiangcp.com -jiangduoduo.com -jianghaihao.com -jianghao.wang -jianghehuagong.com -jianghui.xyz -jiangjiaolong.com -jiangkk.com -jiangmin.com -jiangpaipinpai.com -jiangroom.com -jiangruyi.com -jiangshanlihong.com -jiangshi.org -jiangshi99.com -jiangsugqt.org -jianguo.tv -jianguoyun.com -jiangwang.net -jiangweishan.com -jiangxianli.com -jiangxindaojia.com -jiangxindc.com -jiangxinlingdu.com -jiangxiol.com -jiangxipiaoliu.com -jiangyuesong.me -jiangzi.com -jianhaobao.com -jianhen.net -jianhui.org -jianhui666.com -jianianle.com -jianingy.com -jianjian.tv -jianjiaobuluo.com -jianjie8.com -jiankang.com -jiankangchangshou.net -jiankanghebei.com -jiankangju.com -jiankangkuaile99.com -jianke.cc -jianke.com -jianke.net -jiankeba.com -jiankong.com -jiankong58.com -jiankongbao.com -jianlaixiaoshuo.com -jianlc.com -jianlc.net -jianli-sky.com -jianli9.com -jianliao.com -jianliben.com -jianlika.com -jianlimoban.net -jianliw.com -jianlixiu.com -jianloubao.com -jianluote.net -jianniang.com -jianpage.com -jianpaimeiye.com -jianpu8.com -jianpu99.net -jianpuw.com -jianq.com -jianqiaochina.com -jianshe99.com -jianshen8.com -jianshenmi.com -jianshiapp.com -jianshiduo.com -jianshu.com -jianshu.io -jianshu.tech -jianshuapi.com -jianshukeji.com -jianshunrui.com -jiantizi.com -jiantuku.com -jianwang360.com -jianweitv.com -jianwi.com -jianxun.io -jianyi.net -jianyu360.com -jianyuebg.com -jianyuweb.com -jianyv.com -jianzhanapp.com -jianzhanbao.net -jianzhangongsi.com -jianzhi.net -jianzhi8.com -jianzhiba.net -jianzhijiaoyu.com -jianzhikeji.com -jianzhila.net -jianzhimao.com -jianzhiwang.com -jianzhiwangzhan.com -jianzhiyixin.com -jianzhu2008.com -jiao4.com -jiaochengzhijia.com -jiaodafu.net -jiaodian.pub -jiaodong.net -jiaofei123.com -jiaofenw.com -jiaohuilian.com -jiaoliuqu.com -jiaomai.com -jiaoman.cc -jiaonan.net -jiaonizuocai.com -jiaoping.com -jiaoran.net -jiaoshouhuayuan.com -jiaoshouwang.com -jiaosm.com -jiaotou.org -jiaoyimao.com -jiaoyin.com -jiaoyitu.com -jiaoyiwu.cc -jiaoyixia.com -jiaoyizhu.com -jiaoyudao.com -jiaoyuwo.com -jiapin.com -jiapu.tv -jiapujidi.com -jiapuvip.com -jiaren.org -jiarenvip.com -jiarui.cc -jiasale.com -jiasao.net -jiashuangkuaizi.com -jiashule.com -jiaston.com -jiasuba.com -jiasubook.com -jiasuhui.com -jiasule.com -jiasule.net -jiasule.org -jiasuzhu.com -jiataoyuan.com -jiathis.com -jiatui.com -jiatx.com -jiawin.com -jiaxiaozhijia.com -jiaxincloud.com -jiaxiweb.com -jiaxuejiyin.com -jiayi56.com -jiayin618.com -jiayinleasing.com -jiayiss.com -jiayongluyou.com -jiayouhaoche.com -jiayouxueba.com -jiayu0x.com -jiayuan-law.com -jiayuan.com -jiayue99.com -jiazhao.com -jiazhongkeji.com -jiazhoulvke.com -jiazhua.com -jiazhuang.com -jiazhuang6.com -jiazijun.com -jiazile.com -jiazuo.cc -jibai.com -jibencaozuo.com -jibite.fun -jicaifund.com -jice.io -jichangbus.com -jichangdaba.com -jichangp.com -jiche.com -jicheng.net -jichibang2019.com -jicholding.com -jichuangke.com -jiclip.com -jidacheng.com -jidaihome.com -jidao.ren -jidaola.com -jide.com -jidekan.com -jideos.com -jidexiang.net -jidi.com -jidiaose.com -jidujiao.com -jiduu.com -jie0.com -jie518.com -jiebaodz.com -jiebohui.com -jiecao.com -jiecaojingxuan.com -jiechupm.com -jiedaibao.com -jiedianqian.com -jiefadg.com -jiefangcheng.net -jiefuku.com -jiegames.com -jiegeng.com -jiehuisoft.com -jiehun021.com -jiehun027.com -jiehunmishu.com -jiejiecool.com -jiejing.fun -jiekenmould.com -jiekon.com -jiekou.com -jielibj.com -jieligo.net -jielong-printing.com -jielongguanjia.com -jiemeng.tw -jiemeng8.com -jiemian.com -jiemo.net -jiemo8.com -jiemodui.com -jiepaids.com -jiepang.com -jiepei.com -jiepeng023.com -jieqi.com -jieqinwang.com -jieseba.org -jieshimt8.com -jieshu.me -jieshui8.com -jieshuwang.com -jieti5.com -jietu365.com -jietuosh.com -jietusoft.com -jiexi.la -jiexi.link -jiexi8.com -jiexiyouxuan.com -jieyou.com -jieyoujob.com -jieyue.net -jifang360.com -jifang365.com -jifangcheng.com -jifenapp.com -jifenfu.net -jifengdm.com -jifenh.com -jifenzhong.com -jigao616.com -jiguangcdn.com -jiguangdaili.com -jiguangdanci.com -jiguangkejigongsi.com -jiguangzhuisu.com -jiguo.com -jihai8.com -jihaoba.com -jiheyun.com -jihone.com -jihot.com -jihuachina.com -jihui.io -jihuoma.com -jijia.com -jijiagames.com -jijiangzhi.com -jijidown.com -jijigugu.club -jijikb.com -jijing.site -jijinhao.com -jijuduo.com -jikabao.com -jikaicai.com -jike.info -jikedaohang.com -jikedata.com -jikefan.com -jikejiazhuang.com -jikejidi.com -jikemac.com -jikexiu.com -jikexueyuan.com -jikipedia.com -jikzy.com -jilailawyer.com -jileniao.net -jilibao168.com -jiliguala.com -jilingban.com -jilinpujiyiyuan.com -jilinwula.com -jilipg.com -jiliyun.com -jillbanging.com -jilong-chem.com -jilupianzhijia.com -jimeng.mobi -jimi168.com -jimicn.com -jimifashion.com -jimiru-bj.com -jimistore.com -jimmylv.info -jimonet.cc -jimu.com -jimubox.com -jimuc.com -jimucake.com -jimucc.com -jimufund.com -jimujiazx.com -jin10.com -jin10x.com -jin24k.com -jinanguanggao.com -jinanxw.com -jinanxww.com -jinbaiteng.com -jinbaobeiqiming.com -jinbaoidc.com -jinbaonet.com -jinbiaohui.com -jinbifun.com -jinbikan.com -jinbilianmeng.com -jinbitou.net -jinbuguo.com -jinchaodengji.com -jinchongyu.com -jinchuang.org -jinchutou.com -jincin.com -jincon.com -jinda.tv -jindanlicai.com -jindaodao.com -jindian120.com -jindianweb.com -jindiaoqizhong.com -jindingfm.com -jindingmucai.com -jindun007.net -jindunfan.com -jinduoduo.net -jinfangka.com -jinfengkou.com -jinfengpaint.com -jinfengwine.com -jinfuzi.com -jing-xian.com -jingbotech.com -jingc.com -jingchang.tv -jingchengcb.com -jingchengwl.com -jingchurc.com -jingdaka.com -jingdata.com -jingdian230.com -jingdianjiu.com -jingdianju.com -jingdianlaoge.com -jingdianxitong.com -jingdiao.com -jingdigital.com -jingdong.com -jingdongdaili.com -jingdongyouxuan.com -jingdw.com -jingfentui.com -jingguan.ai -jinghaishop.com -jinghangapps.com -jinghua.com -jinghuasoft.com -jingjia.org -jingjiamicro.com -jingjiang.com -jingjiawang.com -jingjie360.com -jingjiu.com -jingkan.net -jingkids.com -jinglawyer.com -jinglingbiaozhu.com -jinglong0769.com -jingmaoyuanxin.com -jingmaozhan.com -jingme.net -jingmeiti.com -jingniukeji.com -jingoal.com -jingp.com -jingpai.com -jingpaidang.com -jingpinke.com -jingpinwenku.com -jingrandc.com -jingrongshuan.com -jingruigroup.com -jingsh.com -jingshuiqicai.com -jingsocial.com -jingsoo.com -jingtanggame.com -jingteinv.com -jingtiaowang.com -jingtuitui.com -jingtum.com -jingua168.com -jingujie.com -jingutrust.com -jingwei.com -jingwei.link -jingwentian.com -jingwuhui.com -jingxi.com -jingxialai.com -jingxianglawfirm.com -jingxingseo.com -jingxuanwang.com -jingy8.com -jingyakt.com -jingyan8.cc -jingyanben.com -jingyanbus.com -jingyanhome.com -jingyanshu.com -jingyanzhinan.com -jingyeqian.com -jingyi186.com -jingying.com -jingyougz.com -jingytech.com -jingyu.com -jingyuan.com -jingyuelaw.com -jingyuxiaoban.com -jingyuyun.com -jingzhan1688.com -jingzhe.me -jingzhengu.com -jingzhiyuanyi.com -jingzhuntuiguang.com -jingzong.org -jinhaidai.com -jinhaijiacheng.com -jinhe-energy.com -jinhengjgj.com -jinher.com -jinhuatv.com -jinhuazhe.com -jinhuicorp.com -jinhuizhibo.com -jinhusns.com -jinianbi.com -jiniance8.com -jinjiang.com -jinjianginns.com -jinjingquan.com -jinju8.com -jinjunmei.net -jinkagou.com -jinkan.org -jinke3d.com -jinkejoy.com -jinkongjianshe.com -jinkosolar.com -jinku.com -jinlaiba.com -jinlanqihua.com -jinlianchu.com -jinlider.com -jinligou.com -jinlila.com -jinlinghotel.com -jinlinghotels.com -jinliniuan.com -jinlishenghuo.com -jinliyu.cc -jinlong-jiaxiao.com -jinluanshi.com -jinmaojie.com -jinmaopartners.com -jinmenrc.com -jinmi.com -jinmogame.com -jinmuinfo.com -jinnao.wang -jinnianduoda.com -jinniu89.com -jinnong.cc -jinpengeye.com -jinphui.com -jinqiexia.com -jinquan158.com -jinqunla.com -jinridandong.com -jinriguanzhu.cc -jinrishici.com -jinritemai.com -jinrong-online.com -jinrongbaguanv.com -jinrongren.net -jinrongweb.com -jinrui-tech.com -jinruimedia.com -jins-cn.com -jins365.com -jinsdk.com -jinse.com -jinsebook.com -jinsedihao.com -jinsehuaqin.com -jinshangcaijing.com -jinshangdai.cc -jinshangdai.com -jinshanjiayuan.com -jinshanju.com -jinshare.com -jinshisoft.com -jinshongsheng.com -jinshuju.com -jinshuju.net -jinshuju.org -jinshujuapp.com -jinshujucdn.com -jinshujufiles.com -jinshun.com -jinsiwei.com -jintaimall.com -jintang114.org -jinti.com -jintiango.com -jintianjihao.com -jintiankansha.me -jintianpaper1.com -jintoutiao.com -jintuomc.com -jinwaimai.com -jinwin.net -jinxidao.com -jinxiu8.com -jinxuliang.com -jinxun.cc -jinyaco.com -jinyi2008.com -jinyindao.com -jinyinyouhui.com -jinyongwang.com -jinyoukai.com -jinyueya.com -jinyueya.net -jinyunweb.com -jinyuzd.cc -jinzheled.com -jinzhidagl.com -jinzhoubank.com -jinzhuanprint.com -jinzhucaifu.com -jinzhuguo.com -jinzjy.com -jinzunjy.com -jiongcun.com -jiongdm.com -jiongji.com -jiongshiwu.com -jiongyaya.com -jios.org -jiou.me -jiouai.com -jiouyun.com -jipays.com -jipiner.com -jipingacg.com -jipinwww.com -jipukeji.com -jiqid.com -jiqie.com -jiqike.com -jiqirenku.com -jiqizhixin.com -jiqunzhihui.com -jirengu.com -jiriba.com -jirou.com -jirou.org -jirry.me -jisapower.com -jisec.com -jishicn.com -jishida.vip -jishuchi.com -jishukong.com -jishuqq.com -jishutuan.com -jishux.com -jisi17.com -jisilu.com -jisu-cnd.com -jisu-edu.com -jisuan.mobi -jisuanke.com -jisuanqinet.com -jisuanzt.com -jisuapi.com -jisuchaxun.com -jisuchou.com -jisuclouds.com -jisucn.com -jisufeifei.com -jisuim.com -jisuimg.com -jisujie.com -jisukandian.com -jisuoffice.com -jisuoping.com -jisupdf.com -jisupdfeditor.com -jisupdftoword.com -jisupe.com -jisuqianbao.com -jisutodo.com -jisutp.com -jisutui.vip -jisuwebapp.com -jisuxia.com -jisuye.com -jisuyib.com -jita.im -jita5.com -jitailian.com -jitaqupu.com -jitashe.org -jitatang.com -jitavip.com -jitay.com -jite.net -jiterzzzz.com -jitongtianxia.com -jitu5.com -jituwang.com -jiu3000.com -jiub.ren -jiubuhua.com -jiucaicaijing.com -jiuchutong.com -jiucool.org -jiuday.com -jiudiandyw.com -jiudianjiu.com -jiudiankji168.com -jiudianyuedu.com -jiuding18.com -jiudingcapital.com -jiudingdalv.com -jiugang.com -jiugangbid.com -jiuguanfm.com -jiuhetx.com -jiuhongwl.com -jiuhuajob.com -jiuhuang.com -jiuhuar.com -jiuhuashan.cc -jiujhzp.com -jiujiange.com -jiujiui.com -jiujiunn.com -jiujiups.com -jiujiuwan.com -jiujiuwj.com -jiuku.com -jiulingwan.com -jiumaojiu.com -jiumaster.com -jiumei.com -jiumei8.com -jiunile.com -jiupaicn.com -jiupaicom.com -jiupin8.com -jiuq.com -jiurong.com -jiushikou.com -jiushixing.com -jiushu.net -jiushui.tv -jiusi.net -jiusihengyuan.com -jiusitm.com -jiusongjiankang.com -jiusp.cc -jiutu.net -jiuwa.net -jiuwan.com -jiuwei.net -jiuwu.tech -jiuwuqiong.com -jiuxian.com -jiuxianfeng.com -jiuxihuan.net -jiuxinban.com -jiuxing.com -jiuyan.info -jiuyao666.com -jiuyehb.com -jiuyi2005.com -jiuyiliebian.com -jiuyingnet.com -jiuyingwangluo.com -jiuys.com -jiuyuu.com -jiuzhaigou-china.com -jiuzheng.com -jiuzhilan.com -jiuzhinews.com -jiuzhu999.com -jiwa123.com -jiwanjiwan.com -jiweichengzhu.com -jiwu.com -jiwudai.com -jixiang10.com -jixiangbaiwei.com -jixiangjili.com -jixiangyou.com -jixianku.com -jixie100.net -jixie5.com -jixiewz.com -jixing8.com -jixunjsq.com -jixunlyq.com -jiye100.com -jiyiblog.com -jiyifa.com -jiyili.net -jiyin-tech.com -jiyin2020.com -jiyingw.com -jiyingw.net -jiyixcx.com -jiyou-tech.com -jiyoubang360.com -jiyoujia.com -jiyouwang.com -jiyuncn.com -jiyuqiao.com -jizhan.com -jizhangapp.com -jizhangzhuce.com -jizhiba.com -jizhidsp.com -jizhiwei.com -jizhiyingxiao.net -jizhiyouke.com -jizhuba.com -jizhuomi.com -jizhutaoke.com -jizunnet.com -jj-inn.com -jj-tv.com -jj20.com -jj3721.com -jj55.com -jj59.com -jj831.com -jjapk.com -jjb-static.com -jjbang.com -jjbank.net -jjbbs.com -jjbhn.com -jjbisai.com -jjblove.com -jjbnews.xyz -jjccb.com -jjcdn.com -jjcoffetel.cc -jjcoffetels.com -jjcpchina.com -jjcto.com -jjdc.net -jjdede.com -jjdiaoyu.com -jjdzc.com -jjecn.com -jjfinder.com -jjg630.com -jjgls.com -jjhgame.com -jjhgamedns.com -jjhh.com -jjhuifu.com -jjhuigou.com -jjhuoyan.com -jjhyxh.com -jjidc.com -jjiehao.com -jjinfo.com -jjisp.com -jjj.ee -jjjaaa.com -jjjg.co -jjjoystudios.com -jjjtimes.com -jjkeq.com -jjkk.org -jjklife.com -jjkucunxie.com -jjldbk.com -jjlsd.com -jjmh.com -jjmj.tv -jjmmw.com -jjnhh.com -jjnz.com -jjonline.org -jjplane.com -jjppt.com -jjqj.net -jjrfw.com -jjrjd.com -jjsedu.org -jjshang.com -jjsip.com -jjtang.com -jjtfyjy.com -jjtianshangi.com -jjtonline.com -jjtqnews.com -jjtravel.com -jjtxtx.com -jjunj.com -jjvod.tv -jjw.com -jjword.com -jjwxc.com -jjwxc.net -jjwxc.org -jjx88.net -jjxj.org -jjxsw.cc -jjxsw.com -jjxsw.la -jjxsw.org -jjxwzk.org -jjxyls.com -jjy118.com -jjygym.com -jjyx.com -jjyy.me -jjyyzy.com -jjzdm.com -jjzfgjj.com -jjzl800.com -jk-px.com -jk126.com -jk130.com -jk2h.com -jk37du.com -jk3a.com -jk51.com -jk520.net -jk724.com -jk8090.com -jkbexp.com -jkc8.com -jkcaijing.com -jkcorkpads.com -jkcsjd.com -jkdpw.com -jkdsz.com -jkeabc.com -jkgood.com -jkidc.com -jkimg.net -jkpan.cc -jkpj.com -jktcom.com -jktong.com -jkx.cc -jkxds.net -jkydt.com -jkyeo.com -jkys5.com -jkzhilu.com -jkzl.com -jl-news.com -jl-zh.com -jl0435.com -jl54.org -jl852.com -jladi.com -jlakes.org -jlc-gw.com -jlc.com -jlccpit.com -jlcerp.com -jldldz.com -jlforging.com -jlfzb.com -jlg86.com -jlhuaze.com -jljbbs.com -jljgdj.org -jlkj.cc -jllihua.com -jlmhw.com -jlonline.com -jlopen.com -jlpay.com -jlpz8.com -jlpzj.net -jlq.com -jlr360.com -jlscds.com -jlsdzgckcy.com -jlsemi.com -jlsjnw.com -jlspr.com -jltyjxzz.com -jluol.com -jlwlyx.com -jlwubi.com -jlxfw.com -jlyes.com -jlytjx.com -jlzkb.com -jlzsoft.com -jlzsw.com -jlzyz.com -jm1ph.com -jm2046.com -jm3q.com -jm678.com -jmabroad.com -jmads.net -jmbbs.com -jmd-china.com -jmdedu.com -jmedia360.com -jmeii.com -jmf0.com -jmf6.com -jmfans.com -jmgle.com -jmgo.com -jmhapp.com -jmhd8.com -jmicd.com -jmjc.tech -jmjiuchang.com -jmjxc.com -jmkjmob2.xyz -jmkjmob5.xyz -jmkx.com -jmlk.co -jmmuseum.com -jmonline.org -jmqy.com -jmrsksj.org -jmsqw.com -jmstatic.com -jmtd0531.com -jmtsg.com -jmtxjj.com -jmxfw.com -jmxw.net -jmyna.net -jmyzds.com -jmzcgs.com -jmzns.com -jn-bank.com -jn-nw.com -jn001.com -jn123456.com -jn1535.com -jnaoliyuan.com -jnbbbyy.com -jnbnzk.com -jncarw.com -jncjqgs.com -jncqj.com -jncyx.com -jndssd.com -jndwyy.com -jnesc.com -jnhouse.com -jnj-group.com -jnjj.com -jnjylh.com -jnky.com -jnlab.com -jnlc.com -jnliyu.com -jnlou.net -jnlqty.com -jnltgm.com -jnltwy.com -jnmama.com -jnmami.com -jnmtdl.com -jnnc.com -jnnews.tv -jnqbyy.com -jnqjyj.com -jnrain.com -jnshu.com -jnsino.com -jnstdc.com -jntianjin.club -jntinchina.com -jntxglass.com -jntyhl.com -jnw.cc -jnwb.net -jnxiuchuan.com -jnxmycnc.com -jnyestar.com -jnzcsyj.com -jnzfwz.com -jnzheming.com -jnzhonglidjc.com -jnzycw.com -jo668.com -joaquinchou.com -job0768.com -job10000.com -job1001.com -job120.com -job168.com -job256.com -job263.com -job36.com -job4ee.com -job510.com -job5156.com -job592.com -job910.com -job9151.com -job98.com -job9981.com -jobbole.com -jobcdp.com -jobcn.com -jobdeer.com -jobdogame.com -jobeast.com -jobgojob.com -jobguangfu.com -jobhb.com -jobi5.com -jobkoo.com -jobpin.com -jobsalon.net -jobsdigg.com -jobsitechina.com -jobsun.com -jobtong.com -jobui.com -jobuy.com -jobvvv.com -jobyp.com -jocat.com -jocctv.com -joci.net -joe92.com -joehill.me -joenchen.com -johhan.com -johnardo.com -johnwatsondev.com -joiest.com -joindata.net -joiningss.com -joinkchem.com -joinquant.com -joinsen.com -joint-harvest.com -jointforce.com -joinusad.com -joinvalue.com -joinwaylawfirm.com -joinwee.com -jojju.com -jojoin.com -jojoreading.com -joker.li -jolimark.com -jomodns.com -jonahome.net -jone.wang -jongta.com -jonllen.com -jonny.vip -jonsbo.com -joobot.com -joojcc.com -joojtech.com -joojzz.com -joomob.com -joooz.com -joowhee.com -joox.com -jooyoo.net -jooyuu.com -joozone.com -joqoo.com -josephcz.win -joshuais.me -josncdn.com -jotop.net -jotrin.com -jouav.com -jourlib.org -journeyui.com -jourserv.com -jouypub.com -jovcloud.com -jovetech.com -jowto.com -joy95.com -joyact.com -joyami.com -joyany.com -joyapi.com -joycbd.com -joydin.com -joyen.net -joyes.com -joyfire.net -joyglue.com -joying.com -joyj.com -joyk.com -joylife.hk -joymeng.com -joynb.net -joyncleon.com -joyocean.org -joyoung.com -joyowo.com -joyque.com -joyshebao.com -joysight.com -joyslink.com -joysung.com -joytrav.com -joytraveller.com -joyu.com -joyulf.com -joyup.tv -joyuyx.com -joywii.net -joywok.com -joyyang.com -joyyoo.com -joyzlan.com -jp.com -jp14.com -jpaifusen.com -jpanj.com -jpay.hk -jpbeta.net -jpeen.com -jpegonline.com -jperation.com -jpg.cm -jpg.dog -jphot.net -jpjc315.com -jpjww.com -jpkcnet.com -jpkix.com -jpmsg.com -jpnsp.com -jpqp888.com -jpshc.com -jpshuntong.com -jpsmile.com -jptaiyo.com -jpthome.com -jpush.io -jpuyy.com -jpwb.cc -jpwb.net -jpwind.com -jpwindow.com -jpwxapp.com -jpyoo.com -jpyssc.com -jpzyfx.com -jq-school.com -jq22.com -jq960.com -jqaaa.com -jqbyby.com -jqcool.net -jqdasuan.com -jqdns1.com -jqdns9.com -jqdzw.com -jqfax.com -jqgc.com -jqgcw.com -jqhtml.com -jqpress.com -jqr.com -jqr5.com -jqrkc.com -jqrzhijia.com -jqsite.com -jqskygame.com -jque.xyz -jquery123.com -jqueryajax.com -jqueryba.com -jqueryfuns.com -jquerywidget.com -jqw.com -jqw0099.com -jqwater.com -jqygjx.com -jqzhu.com -jqzhuangshi.com -jqzjop.com -jqzw.com -jr-soft.com -jr123.com -jr18.com -jr80.vip -jrdzj.cc -jrecchina.com -jrexam.com -jrgang.com -jrj.com -jrjhg.com -jrjingshan.com -jrjr.com -jrkan.cc -jrlady.com -jrmf360.com -jrncl.com -jrpxw.com -jrqiwen.com -jrqzw.net -jrsef.com -jrsmw.com -jrsnba.com -jrszw.com -jrszxww.com -jrtj120.com -jrwenku.com -jrxdmedia.com -jrxjnet.com -jrxzj.com -jryghq.com -jryglxs.com -jrysdq.com -jryzt.com -jrzj.com -js-aeroinfo.com -js-ceo.com -js-code.com -js-screen.com -js-weilong.com -js-yr.com -js04999.com -js0573.com -js11183.com -js118114.com -js165.com -js178.com -js17x.com -js3.org -js53777.com -js66649.com -js667.vip -js7xc.com -js8.in -js811.com -js96008.com -js99cf.com -jsahj.com -jsbc.com -jsbexam.com -jsbgj.com -jsceou.com -jsche.net -jschengta.com -jschunxing.com -jscj.com -jsckjqr.com -jsclearing.com -jscnc.net -jscqt.com -jscssimg.com -jscts.com -jsczyjg.com -jsd.cc -jsdaima.com -jsdujuan.com -jsdushi.net -jseepub.com -jseie.org -jseoptics.com -jser.com -jser.io -jsfof.com -jsform.com -jsform3.com -jsfw8.com -jsfycdn3.com -jsgbds.com -jsgblog.com -jsgc168.com -jsgcbank.com -jsgh.org -jsgho.net -jsgjksl.com -jsgrb.com -jsguolv.com -jsgyrcb.com -jshaman.com -jsharer.com -jshasl.com -jshbank.com -jshddq.net -jshmrcb.com -jshnh.com -jshqjt.com -jshrconsult.com -jshsoft.com -jshuabo.com -jshuachen.com -jshy.com -jshylm.com -jsimg.cc -jsinfo.net -jsiteec.org -jsjclykz.com -jsjdrcb.com -jsjdzf.com -jsjinfu.com -jsjjy.com -jsjkx.com -jsjlzxw.com -jsjs.cc -jsjs.org -jsjy666.com -jsjyhzy.cc -jsjyrcb.com -jsjznews.com -jskaiborui.com -jskpcg.org -jskwt.com -jskyztc.com -jsldweb.com -jslegal.com -jslottery.com -jslwzk.com -jsly001.com -jsmaochang.com -jsmen.com -jsmian.com -jsmjys.com -jsmo.xin -jsmsg.com -jsmxkj.com -jsmxw.com -jsncke.com -jsneco.com -jsningyi.com -jsnol.com -jsnx.net -jsnxs.com -jsocr.com -jsonin.com -jsonnode.com -jsp51.com -jspang.com -jspatch.com -jspcn.net -jspeople.com -jspfa.org -jspxcms.com -jsq001.com -jsq886.com -jsqlawer.com -jsqq.net -jsqt.com -jsr9.com -jsrcu.com -jsrrcb.com -jsrsrc.com -jsrtzx.com -jsruiyin.com -jsrun.net -jsrun.pro -jsrxjt.com -jss580.org -jssalt.com -jssdk.net -jssfx.com -jssgw.com -jsshow.net -jssj.cc -jssjys.com -jsslm.com -jssnrcb.com -jsswordshop.com -jssytc.com -jsszls.com -jstdtncj.com -jstfdz.com -jstoo.com -jstour.com -jstoys.net -jstucdn.com -jstv.com -jstxdm.com -jstxrcb.net -jstycn.com -jstyyghyy.com -jstzjy.net -jstzrcb.com -jsw988.com -jswebcall.com -jswku.com -jswmw.com -jswspocapi.com -jsxat788.com -jsxcra.com -jsxfedu.com -jsxhrb.com -jsxhrcb.com -jsxhw.org -jsxiaoguo.com -jsyd10086.net -jsyfkj.com -jsyihaotong.com -jsyks.com -jsypin.com -jsypj.com -jsyuanyou.com -jsyun.cc -jsyunbf.com -jsyxrcb.com -jszb123.com -jszbug.com -jszbw.com -jszg.org -jszgjt.net -jszhaobiao.com -jszikao.org -jszjqy.com -jszks.com -jszks.net -jszygs.com -jszyouxi.com -jt-yun.com -jt996.com -jtamc.com -jtbole.com -jtcyjm.com -jtfgq.com -jtggame.com -jtgzfw.com -jthailang.com -jthcsx.com -jthl.net -jtianling.com -jtimg.com -jtjr99.com -jtlw.com -jtnsh.com -jtnxs.com -jtpk668.com -jtqh.net -jtstudy.com -jttv.net -jtv123.com -jtyjy.com -jtyy.com -ju33.com -ju51.com -ju81.cc -juancdn.com -juandou.com -juangua.com -juanlaoda.com -juanpi.com -juanpimao.com -juanshangwang.com -juanyunkeji.com -juaq.com -jubaopay.com -jubaopeng5555.com -jubaozang.com -juben68.com -juben98.com -juc365.com -jucanw.com -jucelin.com -juchang.com -jucheng01.net -juchuangbio.com -jucong.com -judacdn.com -judouapp.com -judyclub.com -jue-ce.com -jue.so -jue1.com -juecan.com -juedui100.com -jueduilingyu.com -juehuo.com -juejin.im -juejinchain.com -juejinqifu.com -juemei.com -juemuren4449.com -jueok.com -jueshe.cc -juesheng.com -jueshinan.com -jueshitangmen.info -juesw.com -juetuzhi.net -juewei.com -juexiang.com -juezhao123.com -jufaanli.com -jufengshang.com -jufidc.com -jufoinfo.com -juhangye.com -juhaof.com -juhaokan.org -juhe.com -juhemulu.com -juheweb.com -juheying.com -juhuasuan.com -juhuio.com -juhuisuan.com -jui.org -juicefs.com -juimg.com -juiuns.com -jujayoupin.com -juji.tv -jujiangkk.com -jujiaobaby.com -jujiaonet.com -jujiaonet1.com -jujias.com -jujienet.com -jujin8.com -jujiu8.com -jujoy.com -jujuanpi.com -jujumao.com -jujusky.com -jujuwan.com -jukandiannews.com -juke51.com -jukebao.com -jukebao123.com -jukejia.com -juketool.com -jukuu.com -julaibao.com -julecn.com -juliachina.org -juliacn.com -juliancj.com -juliang8.com -julianhd.net -julihun.com -julive.com -julucn.com -julur.com -julyapp.com -julyclyde.org -julydate.com -julyedu.com -julysong.com -jumaicms.com -jumaizhijia.com -jumanhua.com -jumbobondhk.com -jumei.com -jumeiglobal.com -jumeinet.com -jumengren.com -jumi-cdn.com -jumi.com -jumi18.com -jumin.cc -juming-xz.com -juming.com -jumore.com -jumorenews.com -jumpcnnet.com -jumpjumpcat.com -jumple.com -jumppo.com -jumpserver.org -jumpstar-tech.com -jumpw.com -jumpwgame.com -jumpwo.com -jun360.com -jun4.com -junankeji.com -junantai.com -jundacheng.com -jundui.net -jundushan.com -junews.net -juneyao.com -juneyaoair.com -juneyaoairlines.com -jungebb.com -junhey.com -junhuisoft.com -juniu.tv -junjiahao.com -junjichu.net -junjiewang.com -junjing.net -junjunfudao.com -junka.com -junlee.net -junlishaokao.com -junlongtech.com -junmidao.com -junmin.org -junmoseo.com -junnanhao.com -junph.com -junpin.com -junpin360.com -junpinhui.com -junpinzhi.com -junqing.ren -junqing360.com -junren.net -junrongdai.com -junsaozg.com -junshencm.com -junshi.com -junshi81.com -junshidao.com -junshier.com -junshijia.com -junshiqianyanwang.com -junshis.com -junshishu.com -junshitx.com -junsw.com -junsz.com -juntongtian.com -juntx.com -junwei1000.com -junwu262.com -junyao.tech -junying.com -junyougame.com -junyudns.com -junyuewl.com -junyuxuan.com -junzhiip.com -junzhuan.com -junziboxue.com -junzimen.com -junziqian.com -juooo.com -jupindai.com -jupiterscdn.com -jupup.com -juqi.com -juqingjuqing.com -juqiwang.net -juqyxa.com -juren.com -jurenqi.com -jurongfangchan.com -jurongrencai.com -juseey.com -jusfoun.com -jusha.com -jushewang.com -jushigj.com -jushike.net -jushikk.com -jushiwangedu.com -jushuo.com -jussevent.com -jusstickets.com -just4coding.com -just4fun.ml -just4fun.site -just998.com -justalkcloud.com -justbilt.com -justbon.com -justcartoon.com -justdo.tv -justdojava.com -justep.com -justering.com -justjavac.com -justpodmedia.com -justsy.com -justwe.site -justyle.cc -justylepro.com -jutao.com -jutaobao.cc -jutean.com -jutingshop.com -jutoudang.com -jutuilian.com -juturn.com -juvefans.com -juwa.net -juwan.com -juwangmedia.com -juweixin.com -juxia.com -juxiangyou.com -juxin.tv -juxinfu.com -juxing-edu.com -juxingyi.com -juxinhuizhi.com -juyanbao.com -juyoufan.net -juyouqian.com -juyouqu.com -juyouquan.net -juyoutv.cc -juyouxi.com -juyouxuan.vip -juyuancaiyin.com -juzhen.com -juzhen.io -juzhiyuan.com -juzhongjoy.com -juzicy.com -juzifenqi.com -juzilab.com -juzilicai.com -juzimi.com -juzioo.com -juziseo.com -juzisy.com -juzivr.com -juzix.io -juziyinyue.com -juzizhoutou.net -jvcxp.com -jvmai.com -jvrong.com -jvyou.net -jw100.net -jwappgc.com -jwbl.com -jwdedu.com -jwdili.com -jwdns.com -jwetech.com -jwfirst.com -jwfun.com -jwipc.com -jwnote.com -jwshy.com -jwview.com -jwwey.com -jwx365.com -jwxlschool.com -jwyun.net -jx-bank.com -jx-nc.com -jx027.com -jx09.com -jx118114.net -jx3mogu.com -jx3pve.com -jx3tong.com -jx3yymj.com -jxage.com -jxal.net -jxaxs.com -jxbin.com -jxc4.com -jxcb.net -jxccb.com -jxcf.org -jxcsedu.com -jxcua.com -jxculb.com -jxdfcvv.com -jxdiguo.com -jxdkzz.net -jxdown.com -jxdyf.com -jxedt.com -jxeduyun.com -jxetv.com -jxexpressway.com -jxf57.com -jxf75.com -jxg1.com -jxgdw.com -jxgxbd.com -jxhyshiye.com -jxiaolan.com -jxicloud.com -jxidc.net -jximage.com -jxjdgy.com -jxjee.com -jxjhkq.com -jxjia.net -jxjob.net -jxjyzy.com -jxjyzy.net -jxkjzb.com -jxkp.com -jxlgjd.com -jxlhz.com -jxlwgame.com -jxmlkd.com -jxnchc.com -jxndxuebao.com -jxnxs.com -jxold.com -jxorg.com -jxpta.com -jxpz888.com -jxqcw.com -jxqgpx.com -jxqiheng.com -jxrencai.com -jxrjzx.com -jxrsrc.com -jxrtv.com -jxscct.com -jxsgfzx.com -jxsllw.com -jxslsyy.com -jxsqw.com -jxsrfdc.com -jxsthgz.com -jxsxdp.com -jxtech.net -jxtobo.com -jxtvshop.com -jxtyzx.org -jxtzw.com -jxunicom.com -jxvivi.com -jxwangwen.com -jxweizhi.com -jxwmanage.com -jxwz.net -jxxdf.com -jxxfzx.com -jxxhdn.com -jxxhsd.com -jxxyqm.com -jxycw.com -jxyqm.com -jxyrzdh.com -jxysyz.com -jxzy8.com -jxzyx.com -jy0604.com -jy0832.com -jy1.me -jy135.com -jy1991.com -jyacht.com -jyaochi.com -jyb8.com -jybanker.com -jybase.net -jyblife.com -jyblp.com -jyc99.com -jycbank.com -jycinema.com -jycljx.com -jycloudgslb.com -jycloudgslb.net -jydc.com -jydoc.com -jydspg.com -jydsxh.com -jyeoo.com -jyeoo.net -jyepc.com -jyfans.net -jyfund.com -jygame.net -jygjj.com -jyguagua.com -jygz.com -jyh007.com -jyhlo0.com -jyhmz.com -jyhyfintax.com -jyimg.com -jyjhkz.com -jyjjc.com -jyjxlt2009.net -jylfy.com -jyltx.com -jylw.com -jylzservice.com -jymys.com -jyncw.com -jynews.net -jyoptical.com -jyous.com -jypc.org -jyqkx.com -jyqxz2015.com -jyrd.com -jyrlzy.com -jysd.com -jyshhlxx.com -jysld.com -jysq.net -jyss.net -jysyzk.com -jyteasy.com -jyxdyzx.com -jyyun.com -jyyzsb.net -jyzpw.vip -jyzysp.com -jyzzx.com -jz-cert.com -jz-job.com -jz.cc -jz0045.com -jz0574.com -jz08.com -jz100.com -jz177.com -jz182.com -jz2005.com -jz51598.com -jz5u.net -jz6.com -jzant.com -jzb.com -jzbar.net -jzbdc.com -jzcbank.com -jzchou.com -jzclassroom.com -jzcxptm.com -jzdhyl.com -jzedu24.com -jzerp.com -jzfblog.com -jzgcjsysjzz.com -jzgjj.com -jzgwind.com -jzh.me -jzhfjh.com -jzhfz.com -jzic.com -jzjtop.com -jzkjjt.com -jzkuaiji.com -jzmob.com -jzmsmj.com -jzmt.net -jznqp.net -jznyjt.com -jzongguan.com -jzr666.com -jzrb.com -jzrc.net -jzrsrc.com -jzsc8.com -jzsgzmhjyxgs.com -jzshequ.com -jzsjyksy.com -jzsxinyudianqi.com -jzsyishu.com -jztdc.com -jztdj.com -jztey.com -jztggs.com -jztmgy.com -jztoo.com -jztsjx.com -jztsoft.com -jztvxmt.com -jztylxx.com -jztzw.net -jzwcom.com -jzxs.com -jzxue.com -jzyx.com -jzzhw.com -jzzx.com -jzzxlm.com -k-day.com -k-kbox.com -k-res.net -k-xian.com -k0898.com -k0rz3n.com -k11kuriosity.com -k12.vip -k125.com -k12zx.com -k12zy.com -k165.com -k18.com -k1u.com -k259.com -k2938.com -k2ma.com -k345.cc -k366.com -k369.com -k3851.com -k3887.com -k4nz.com -k5.cc -k518.com -k6271.com -k666.com -k6uk.com -k73.com -k780.com -k7kf.com -k8008.com -k8890.com -k8dream.com -k8jdw.com -k8kkoo.com -k8kkpp.com -k8kkqq.com -k8kkrr.com -k8kkss.com -k8sj.com -k8smeetup.com -k8stech.net -k8w.wang -k8ym.com -k913.com -k99.wang -ka114.net -ka20.com -ka5188.com -kaadas.com -kaayou.com -kaba365.com -kabasiji.com -kabitu.com -kaboy.net -kada.com -kadang.com -kadingding.com -kaesoon.com -kafka.cc -kafoom.com -kagirl.net -kagneen.com -kahxnsat.com -kai-ying.com -kaiba315.com -kaibo5888.com -kaiboda.org -kaiboer.com -kaichengschool.com -kaicong.info -kaidanbao.com -kaidianbang.com -kaieconblog.net -kaifabang.com -kaifae.com -kaifage.com -kaifakuai.com -kaifangkecheng.com -kaifaxueyuan.com -kaifenghenan.com -kaifu.com -kaifubiao.com -kaifuzq.com -kaige68.com -kaihu.la -kaihuadian.com -kaihui.com -kaihuia.com -kaijia.com -kaijia.me -kaijiaweishi.com -kaijun.win -kaikeba.com -kailing.pub -kaimanhua.com -kaimg.com -kaimigou.com -kaimulu.com -kaipan88.com -kaipanla.com -kaiqiancq.com -kaishigo.com -kaishikan.com -kaishilou.com -kaishuhezi.com -kaishustory.com -kaitianad.com -kaivps.com -kaiwind.com -kaixin.com -kaixin00.com -kaixin001.com -kaixin5.net -kaixinbao.com -kaixindou.net -kaixinguopiaowu.net -kaixinhui.com -kaixinhui.net -kaixinlu.com -kaixinly.com -kaixinpaopao.com -kaixintang.com -kaixinwenda.com -kaixue.io -kaiyanapp.com -kaiyuan.com -kaiyuan.me -kaiyuangroup.cc -kaiyuanhi.com -kaiyuanhotels.com -kaiyuanzg.com -kajicam.com -kaka.com -kaka3.com -kakadm.com -kakalili.com -kakamobi.com -kakazy-yun.com -kalading.com -kalamsaha.com -kalazan.com -kalcaddle.com -kalegou.com -kalingling.com -kaluli.com -kameng.com -kamenwang.com -kamidm.com -kamidox.com -kamopos.com -kan0512.com -kan300.com -kan302.com -kan7.me -kan84.net -kan98.com -kanam.me -kanbaobei.com -kanbardata.com -kanbilibili.com -kanbox.com -kanchao.com -kandian.com -kandian.net -kandianshi.com -kandshu.com -kandzww.com -kanfangapp.com -kanfangjilu.com -kanfaxing.com -kanfeidie.com -kanfou.net -kang5.net -kangaiweishi.com -kangame.tv -kangbaifoundation.com -kangbidz.com -kangchun.com -kangdajiuzhou.com -kangdaoai.com -kangepian.com -kanggou.com -kanggui.com -kanghu.net -kanghuayun.com -kanghui.com -kanghui.org -kanghuwang.com -kanglaohui.com -kangle.net -kanglesoft.com -kangleweb.net -kanglingjiu.com -kanglu.com -kangmeigym.com -kangqite.com -kangre.com -kangshijd.com -kanguo.com -kanguowai.com -kangxi55wlsf.com -kangxin.com -kangze.com -kangzhi.com -kanhaiwai.com -kanhuacanchan.com -kanimg.com -kaniuquan.com -kanjia.com -kanjian.com -kanjianlishi.com -kanjianmusic.com -kanjianxinli.com -kanjicho.com -kanjuqing.com -kankan365.cc -kankanblog.com -kankancity.com -kankanews.com -kankanmi.com -kankannews.com -kankantv.cc -kankanzhijian.com -kanketv.com -kankun-smartplug.com -kanlxy.com -kanman.com -kanmanhua.me -kanmee.com -kanmeinv.com -kanmx.com -kannb.com -kanqibao.com -kanqiye.com -kanqq.com -kanqu.com -kanquwen.com -kansea.com -kanshaa.com -kanshangji.com -kanshangjie.com -kanshu.com -kanshu.la -kanshu5.la -kanshu8.net -kanshuapp.com -kanshuge.com -kanshuhai.com -kanshula.com -kanshuwangzhan.com -kansp.com -kantao.net -kantiantang.com -kantiantang.net -kantsuu.com -kantu.com -kanwby.com -kanxiqu.com -kanxsw.com -kanxue.com -kanzhun.com -kao8.cc -kaoba.info -kaobeitu.com -kaocat.com -kaochong.com -kaoder.com -kaodianer.com -kaogua.com -kaojionline.com -kaola.com -kaola.com.hk -kaola100.com -kaolacdn.com -kaolafm.com -kaolafm.net -kaolazhengxin.com -kaopu001.com -kaopubao.com -kaopubao.net -kaopuj.com -kaopuwangzhuan.com -kaopuyun.com -kaopuyun.net -kaoqin.com -kaoqinyi.com -kaoshi110.net -kaoshi365.com -kaoshib.com -kaoshibaike.com -kaoshibao.com -kaoshibb.com -kaoshidian.com -kaoshishenqi.net -kaoshizixun.com -kaowana.com -kaowang.com -kaoyan.com -kaoyan.org -kaoyan001.com -kaoyan1v1.com -kaoyanbox.net -kaoyancas.com -kaoyancas.net -kaoyancc.com -kaoyangaofen.com -kaoyango.com -kaoyanjun.com -kaoyanzhijia.org -kaoyaya.com -kaozhiye.com -kapai8.com -kaquanbao.com -kargocard.com -karlzhou.com -karrytech.com -kartlover.com -karuimall.com -kascend.com -kashen.com -kasora.moe -kasscloud.com -kasumi.club -katcin.com -katebackdrop.com -katebetty.com -katongji.com -katvr.com -katyusha.net -kaven.xyz -kawabangga.com -kawahdinosaur.com -kayege.info -kayoudi.com -kaytrip.com -kaytune.com -kazaff.me -kazakcnr.com -kazhifu.com -kb.cc -kb9.com -kbdfans.com -kbdyw.com -kbengine.org -kbgogo.com -kbiao.me -kbiquge.com -kblcdn.com -kbrightlaw.com -kbscloud.com -kbuifw.com -kbyun.com -kcdns.net -kcdnvip.com -kchance.com -kcity.org -kcjyyjzzs.com -kcjzsc.com -kcloudidc.com -kcrcb.com -kcwiki.org -kcygo.com -kcyuri.com -kcyxjy.com -kd028.com -kd120.com -kd128.com -kd185.com -kd9000.com -kdbbx.com -kdcsw.com -kdd.cc -kddf.com -kddushu.com -kdebell.com -kdefan.com -kdesqt.com -kdfax.com -kdige.com -kdjvlol.bar -kdmobi.com -kdnet.net -kdniao.com -kdpt.net -kdroid.club -kdroid.org -kdscar.com -kdslife.com -kdslife.net -kdspjx.com -kdt.im -kdued.com -kdweibo.com -kdzs123.com -kdzwy.com -kdzxedu.com -ke.com -ke01.com -ke6.com -ke86.com -ke8u.com -keaidian.com -keaiq.com -keaitupian.com -kebango.com -kebi.biz -kebingzao.com -kechenggezi.com -kechuang.org -kechuangfu.com -keda-digital.com -keda-u.com -keda.com -kedang.net -keddoo.com -kede.com -kede.com.hk -kedi.cc -kedou.com -keede.com -keen8.com -keenonrobot.com -keensky.com -keenwon.com -keep.city -keep.com -keepc.com -keepcdn.com -keepyoga.com -keerworld.com -keewin.com -kefeng.wang -kefusoft.com -kefutoutiao.com -kefuzu.com -kegbq.com -kege.com -kehanedu.com -kehou.com -kehu51.com -kehuda.com -kejet.com -kejet.net -keji100.net -kejiabj.com -kejian.design -kejianyi.com -kejietextile.com -kejihai.com -kejijie.net -kejik.com -kejike.com -kejilie.com -kejimeixue.com -kejimt.com -kejingyuan.com -kejipindao.com -kejiqi.com -kejitai.com -kejiwang.cc -kejixun.com -kekaku.com -kekaoxing.com -kekaoyun.com -keke289.com -kekebaby.com -kekedj.com -kekejp.com -kekenet.com -kekepx.com -kekeshici.com -keketrip.com -kekexueba.com -kekiss.com -kele8.com -kelepi.com -keleqiu.com -keleyi.com -keli1.xyz -kelibiao.com -kellen.wang -kelon.com -kelphome.com -kelu.org -kema66.com -kemaicrm.com -keman.com -kemasheying.com -kemomimi.top -kemov.com -ken.io -ken74.com -kename.com -kenapple.com -kendocn.com -kendryte.com -kenfor.com -kenfor.net -kengatoki.com -kengdie.com -kengso.com -kengwan.com -keniu.com -keniub.com -kenshin.wang -kenshu.cc -kentepa.com -kentier.com -kenuonet.com -kenweini.com -kenwen.com -kenword.com -kepingtong.com -kepuchina.org -kepusky.com -ker58.com -kerlala.com -kermitym.com -kernel.cc -kerneldiy.com -kernelgo.org -kernelnote.com -kerneltravel.net -keruibell.com -kerunwh-edu.com -kerunzh-edu.com -keruotv.com -kerust.com -keruyun.com -keruyun.net -kesci.com -kescoode.com -kesense.com -keshizhongguo.com -kesion.com -kesucorp.com -kesum.com -ketangpai.com -ketuimage.com -kevinems.com -kevinjiang.info -kevinlq.com -kewail.com -kewaishu.net -kexianggroup.com -kexin001.com -kexing100.com -kexinguoji.com -kexinyun.org -kexn.net -kexue.com -kexue.fm -kexuelife.com -kexuexia.com -kexuezixunzzs.com -key007.com -keyan.life -keyboardancer.com -keycom-ip.com -keydatas.com -keydot.net -keyfc.net -keygotech.com -keyigroup.com -keyingwb.com -keylol.com -keymoe.com -keyoou.com -keyray-hk.com -keyshot.cc -keyuhome.com -keyunsoft.com -keywin.org -keyyou.net -kezool.com -kf.ai -kf25.com -kf3msfm.com -kf4137.com -kf5.com -kf911.com -kfang.xin -kfbiji.com -kfcdn.com -kfcha.com -kfcms.com -kfd3sm2c.com -kfd9999.com -kfdcc.com -kfj.cc -kflpump.com -kfqrc.com -kfrsrcw.com -kfw001.com -kfxinyuan.com -kfxxgc.com -kfyao.com -kfyou.com -kfzimg.com -kg-gold.com -kg.com -kgdb.info -kgfanr.com -kgimg.com -kgogame.com -kgula.com -kguowai.com -khdatasolutions.com -khdmw.com -khesport.com -khews.com -khlysc.com -khm123.com -khotyn.com -khqihuo.com -khriss.com -khruqc.com -khs1994.com -khysct.com -ki-pa.com -kiaic.com -kibey.com -kibinggroup.com -kiccoso.com -kicosoda.com -kid17.com -kidscoding8.com -kidsdown.com -kidseq.net -kidsyun.com -kidulte.com -kidulty.com -kiees.com -kihgwe.com -kiiik.com -kiimg.com -kik123.com -kikicici.com -kikoplay.fun -kikyoar.com -kililife.com -killdb.com -killman.net -kilvn.com -kimiss.com -kimiss.net -kimiter.com -kimleo.net -kimnote.com -kimqi.net -kimsom.com -kina.cc -kinboy.wang -kindeditor.net -kindle-china.org -kindle114.com -kindle1688.com -kindlehub.mobi -kindlelib.com -kindleport.com -kindlepush.com -kinefinity.com -king-capital.com -kingandwood.com -kingball.net -kingborn.org -kingbos.com -kingbrother.com -kingcheergame.com -kingclouddns.com -kingdee-soft.com -kingdee.com -kingdee.com.tw -kingdee.org -kingdeemall.com -kingdeestar.com -kingdeeyun.com -kingdeezx.com -kingdelgc.com -kingdomfishing.com -kingdun.net -kingexplorer.com -kinggoo.com -kinggrid.com -kingidc.net -kingkaid.com -kingland119.com -kinglandtech.net -kinglassquartz.com -kingnare.com -kingnet.com -kingnetdc.com -kingnettech.com -kingoit.com -kingosoft.com -kingreader.com -kingrein.com -kingroot.net -kings3d.com -kingsemi.com -kingsoft-office-service.com -kingsoft.com -kingsoft.net -kingsoftstore.com -kingst.org -kingstarfintech.com -kingstarmedical.com -kingtoo.vip -kingwam.com -kingwisoft.com -kingyon.com -kingysu.com -kinhom.com -kinpan.com -kinqee.com -kintiger.com -kinval.com -kinzoncap.com -kirgen.com -kirikira.com -kirimasharo.com -kirin-tech.com -kirincloud.net -kirinmach.com -kisa747.com -kischess.com -kisdee.com -kissyui.com -kiswo.com -kit-lee.me -kiteshow.com -kits029.com -kitstown.com -kiujq.com -kiwa-tech.com -kiwenlau.com -kiwisec.com -kj-hospital.com -kj-pcb.com -kj1487.com -kj1d.com -kj3.com -kj458.com -kj5544.com -kj991.com -kj992.com -kj993.com -kjb2c.com -kjbnm.xyz -kjcad.net -kjcdn.com -kjcgzh.com -kjchangdu.com -kjchina.com -kjcity.com -kjcxpp.com -kjdb.org -kjeport.com -kjiuye.com -kjj.com -kjkd.com -kjkp.com -kjkxun.com -kjltxn.com -kjnkj.club -kjr365.com -kjsng.com -kjson.com -kjsv.com -kjt.com -kjw.cc -kjwlxt.com -kjxfx.com -kjycx.com -kjzxtk.com -kk.com -kk.net -kk169.com -kk2w.cc -kk2w.net -kk30.com -kk3g.net -kk50.com -kk7b.com -kkapp.com -kkcache.com -kkcache.net -kkcaicai.com -kkcapture.com -kkcdn.net -kkcha.com -kkcodes.com -kkcoo.com -kkdict.com -kkdownload.com -kkeju.com -kkeye.com -kkfor.com -kkguan.com -kkh-global.com -kkhkk.com -kkidc.com -kkk5.com -kkkd.com -kkkkba.com -kkkmh.com -kkkwww.com -kklishi.com -kklover.com -kklxj.com -kkmaoyi.com -kkmh.com -kkminer.com -kkppdd57.com -kkqb.net -kkr5.com -kkredian.com -kkredian.xyz -kks.me -kksk.org -kksmg.com -kksofts.com -kktijian.com -kktv1.com -kktv5.com -kktv8.com -kkuu.com -kkx.net -kkyoo.com -kkyuedu.com -kkyxw.com -kkzj.com -kkzy-qq.com -kl1l5.com -kl321.com -kl688.com -kl800.com -klandk.com -klarini.com -kldjy.com -klhuyan.com -klianfa.com -klicen.com -klinlee.com -kljiyou.com -klkl.tv -kllife.com -klm123.com -klmh5.com -klmhw.com -klmnf.com -klmybbs.com -klmygjj.com -klmyssn.com -klniu.com -klqian.com -klshou.com -kltdo.com -kltong.com -klub11.com -klunf.com -klvtu.com -klxkc.com -klxuexi.com -km.com -km169.net -km18.net -km1818.com -km198.com -kmaa10.com -kmaa4.com -kmail.com -kmapp.net -kmcaishui.com -kmcenter.org -kmcits.com -kmcits0655.com -kmcxedu.com -kmdn.net -kmeecc.com -kmeitu.com -kmf.com -kmf2c.com -kmfangxun.com -kmg898.com -kmguolv.com -kmipo.net -kmksl.com -kmlcl.com -kmlhh.com -kmmama.com -kmtarena.net -kmw.com -kmway.com -kmxg.net -kmxkh.com -kmyestar.com -kmzljc.com -kmzx.org -kn120.com -kneng.net -knewbi.com -knewone.com -knewsmart.com -knifecms.com -kniu.cc -knotesapp.com -knowgive.com -knowncoin.com -knownpcb.com -knownsec.com -knowpia.com -knowsafe.com -knowyourself.cc -knoya.com -knsheng.com -knsyxw.com -knzlcq.com -koal.com -koalacam.net -koaladoit.com -koalareading.com -koboldgame.com -kobox.tv -kocla.com -kodcloud.com -kodmp.com -koduo.com -koeicn.com -kofficemart.com -kofuf.com -kofunion.net -koiclub.net -koijp.com -koikreative.com -koippt.com -kok1293.com -kok1367.com -kokkk2.com -kokojia.com -kokozu.net -kole8.com -kolrank.com -kolstore.com -komect.com -kometo.com -kompaz.win -kompletlywyred.com -konbo.net -konekomoe.com -konfan.net -kongapi.com -kongbao163.com -kongdao.com -kongdi.net -kongduan.com -kongfou.net -kongfz.com -kongge.com -konggu.net -kongjianjia.com -kongjie.com -kongjun.cc -kongjun.com -kongkonglx.com -konglei.com -kongming-inc.com -kongnar.com -kongqingquan.com -kongquecheng.com -kongqueyuzd.cc -kongrong.com -kongsun-hldgs.com -kongtiao365.com -kongyixueyuan.com -kongzhi.net -kongzhong.com -konka.com -konkamobile.com -konkek2.com -konlan.org -konotaku.com -konshan.com -kooaoo.com -koocdn.com -koofang.com -koofun.com -kookong.com -koolbao.com -kooldns.com -koolearn.com -koolproxy.com -koolyun.com -koopass.com -koorun.com -kooshui.com -kooteam.com -koouoo.com -koovin.com -koovoo.com -koowo.com -kooxoo.com -kooyx.com -koplayer.com -koreabt.com -koreaxing.com -koreayh.com -korimscdn.com -korirl.com -kotei-info.com -kotex-km.com -kotliner.me -koto.com -kotoo.com -kotrip.com -koubei.com -koubeiblog.com -koubeikc.com -koucai365.com -koudai.com -koudai8.com -koudaibaobao.com -koudaigou.net -koudailc.com -koudaili.com -koudaionline.com -koudaionline.net -koudaipe.com -koudaitiku.com -koudaitong.com -koudaiyunying.com -koudashijie.com -kouer.com -kouer.net -kouke5.com -koukousky.com -koukuko.com -koumakan.cc -kouqiang1.com -kouqing.com -koushare.com -kousou.cc -kouss.com -kouyu100.com -kouzi.com -kowa-dental.com -koyuki.cc -kpbgw.com -kpblw.com -kpjushi.com -kpkpw.com -kplanet.vip -kpqtw.com -kprepublic.com -kpsfloor.com -kpxsjz.com -kpzip.com -kpzip.net -kpzs.com -kq36.com -kq39.com -kq520.net -kq81.com -kq88.com -kqcfcw.com -kqgeo.com -kqidong.com -kqiqi.com -kqiwen.com -kqiwen.net -kqj123.com -kqqy.com -kqzjw.com -kqzlzx.com -kr-cell.com -kr.com -kr126.com -krahag.com -krbamboo.com -krdem.com -krdlw.com -krdrama.com -kriszhang.com -krmzz.org -krpano.tech -krshadow.com -krszf.com -krwz.com -krzer.com -krzzjn.com -ks-cdn.com -ks-cdn1.com -ks-live.com -ks-lxjy.com -ks-spring.com -ks1688.com -ks321.com -ks365.org -ks51.com -ks5u.com -ks6602.com -ksair.com.tw -ksandmen.com -ksapisrv.com -ksaxx.com -ksbao.cc -ksbao.com -kscac.com -kscdns.com -ksdlp.com -ksdnw.net -ksdown.com -ksense.com -ksfang.com -ksgnr.com -kshitachi.com -kshot.com -ksjgs.com -ksjsa.com -kskino.com -ksks001.com -ksmobile.com -ksmom.com -ksnds.com -ksnows.com -ksops.com -ksord.com -ksosoft.com -kspkg.com -ksqdq.com -ksren.com -ksria.com -ksrong.com -ksseg.com -kstao.com -ksudi.com -ksupdate.com -ksydx.com -ksyiqiwan.com -ksyna.com -ksyuki.com -ksyun.com -ksyunad.com -ksyuncdn-k1.com -ksyuncdn.com -ksyungslb.com -kszhuanjia.com -kt007.com -kt11.net -kt250.com -kt286.com -kt40.com -kt5u.com -ktanx.com -ktbiao.com -kting.info -ktjd.net -ktkj.com -ktlshu.vip -ktlstbg.com -ktmap.com -ktpf.cc -ktplay.com -ktsee.com -kttpdq.com -ktvc8.com -ktvdaren.com -ktvme.com -ktvsky.com -ktvxg.com -ktxuexi.com -ku1188.com -ku2048.net -ku25.com -ku3721.com -ku6.com -ku6.net -ku6cdn.com -ku6dj.com -ku6img.com -ku6vms.com -ku82.com -ku86.com -ku8ku8.com -ku90.com -ku9377.com -kuabaobao.com -kuacg.com -kuafugame.com -kuai-fei.com -kuai-ying.com -kuai.ma -kuai7.com -kuai8.com -kuaibbs.com -kuaibiancheng.com -kuaibiao2000.com -kuaibowang.net -kuaibuw.com -kuaicad.com -kuaichale.com -kuaidadi.com -kuaidaili.com -kuaidajian.com -kuaidi.com -kuaidi100.com -kuaidi123.net -kuaidihelp.com -kuaidil.com -kuaiduwen.com -kuaiex.com -kuaifa.mobi -kuaifaka.com -kuaifawu.com -kuaifeng.com -kuaigames.com -kuaigeng.com -kuaihaodai.com -kuaihou.com -kuaiji.cm -kuaiji.com -kuaiji.so -kuaiji66.com -kuaijilunwen.com -kuaijiren.com -kuaijiruanjian.com -kuaijishizi.com -kuaijisishu.com -kuaijitong.com -kuaijizheng365.com -kuaikanmanhua.com -kuaikq.com -kuaikuaicloud.com -kuaikuaidai.com -kuaikuaihuoche.com -kuaikuaiyu.com -kuaila.com -kuaile-u.com -kuaile800.com -kuailelunwen.com -kuailesh.com -kuailetongyao.com -kuaileworld.com -kuailexinli.com -kuailexs.com -kuailezu.com -kuailiyu.com -kuailiyu.net -kuailugroup.com -kuaimi.com -kuaipandata.com -kuaipao8.com -kuaipeilian.com -kuaipng.com -kuaiqiangche.com -kuaiqin.com -kuaiqin.net -kuaiqun.org -kuaishebao.com -kuaishou.com -kuaishouapp.com -kuaishoupay.com -kuaishouzt.com -kuaishubao.com -kuaisubeian.com -kuaisujiasu.net -kuaitijian.com -kuaitu666.com -kuaiwan.com -kuaiwan01.com -kuaiwanwo.com -kuaixiazai.com -kuaixun360.com -kuaiyan.com -kuaiyankanshu.net -kuaiyilicai.com -kuaiyingxiao88.com -kuaiyoujia.com -kuaiyouxi.com -kuaiyu.com -kuaiyunds.com -kuaizhan.com -kuaizhang.com -kuaizhe.com -kuaizhihui.com -kuaizip.com -kuaizitech.com -kuaizitech.net -kuaizq.com -kuaizy.com -kuajing.com -kuajing.hk -kuajingyan.com -kuakao.com -kuakao.net -kuaming.com -kuandao.com -kuang-chi.com -kuang-chi.org -kuangchan.biz -kuangchanglang.com -kuangjijia.com -kuangjiwan.com -kuangjue.com -kuangming.com -kuangren.cc -kuangrendao.com -kuangwan.tv -kuangxiangit.com -kuangyi.com -kuanye.net -kuark.com -kuashou.com -kubey.cc -kubicode.me -kubikeji.com -kubiops.com -kubo-360-tudou.com -kubozy-cdn-baidu.com -kuche.com -kuchuan.com -kudasuye.com -kudiannao.com -kudianqi.com -kudingyu.com -kudisk.cc -kuduiso.com -kuface.com -kufangwuyou.com -kufaxian.com -kuge.cc -kugou.com -kugou.la -kugou.net -kuguopush.com -kugz.net -kuhua.net -kuicc.com -kuihuo.com -kuishiba.com -kuishuling.com -kujiale.com -kujiang.com -kujingling.com -kuk8.com -kukahome.com -kuke.com -kuke99.com -kukecloud.com -kukseo.com -kuku9.com -kuku99.com -kukud.net -kukudesk.com -kukumai.com -kukupao.com -kukupig.com -kukuplay.com -kukushow.com -kukuspeak.com -kukuw.com -kukuxiu.com -kuleiman.com -kulengvps.com -kuletco.com -kuli.ren -kulianw.com -kuliqiang.com -kuliwang.net -kuman.com -kuman5.com -kumankeji.net -kumaoyun.com -kumifeng.com -kumt.net -kuncibandung.com -kungfucloud.com -kungfuenglish.com -kungge.com -kuniaozs.com -kunjyu.com -kunkkawu.com -kunleen.com -kunlun-cdn.com -kunlunaq.com -kunlunar.com -kunlunca.com -kunluncan.com -kunlunce.com -kunlunea.com -kunlungem.com -kunlungr.com -kunlunhuf.com -kunlunjue.com -kunlunle.com -kunlunli.com -kunlunno.com -kunlunpi.com -kunlunra.com -kunlunsa.com -kunlunsc.com -kunlunsl.com -kunlunso.com -kunlunta.com -kunlunvi.com -kunlunwe.com -kunmingbc.com -kunmingkanghui.com -kunnisser.com -kunpo.cc -kunshanidc.com -kunx.org -kunyueyun.com -kuodie.com -kuoo8.com -kuoruan.com -kuosanyun.com -kuosheng.net -kuotu.com -kuozhan.net -kupao.com -kuparts.com -kupoo.com -kuqin.com -kurogame.com -kurokingdom.com -kurongdai.com -kurukurumi.com -kurumi.ink -kushenchina.net -kushou.com -kushuzw.com -kusouji.com -kusuu.com -kutianxia.com -kutj.com -kutongji.com -kutoo8.com -kutsg.com -kutu66.com -kutuan.com -kuuhuu.com -kuuke.com -kuwan8.com -kuwanapp.com -kuwanbang.com -kuwen.net -kuxiaoji.com -kuxuexi.com -kuyh.com -kuyibu.com -kuyin123.com -kuyinyun.com -kuyiso.com -kuyoo.com -kuyubox.com -kuyumall.com -kuyun.com -kuyun1.com -kuzhengame.com -kvenjoy.com -kvh.io -kviso.com -kvogues.com -kvov.com -kvov.org -kwaicdn.com -kwaisczway7r4tz7m8.com -kwaishop.com -kwaixiaodian.com -kwaiying.com -kwaizt.com -kwenku.com -kwimgs.com -kwin.wang -kwin.xyz -kwstr.com -kwting.com -kwtzn.com -kwx.gd -kwxjh.net -kx001.com -kx1d.com -kx43.com -kx516.com -kx7p.com -kx9h.com -kxapp.com -kxbaidu.com -kxbld.com -kxbox.com -kxceping.com -kxdao.com -kxdpm.com -kxdw.com -kxewpz.com -kxfsw.com -kxgcw.com -kxinyk.com -kxji.com -kxjlt.org -kxnboat.com -kxpay.net -kxt.com -kxting.com -kxtry.com -kxtui.com -kxvuv.com -kxwan.com -kxxsc.com -kxyike.com -kxzmw.com -ky-express.com -ky6.com -ky711.com -ky958.com -kybapp.com -kybapp.net -kybimg.com -kyboye.com -kydev.net -kye-erp.com -kyemall.com -kyhere.com -kyhs.me -kyidc.net -kyimg.com -kyjxy.com -kyky049.com -kyleduo.com -kyleslight.net -kylienet.com -kyligence.io -kylin-os.com -kylinlot.com -kylinmobi.com -kylinos.com -kylinpet.com -kymco.cc -kymjs.com -kynix.com -kyoceraconnect.com -kypbuy.com -kyppt.com -kyqcfj.com -kytijian.com -kyuanma.com -kyun.hk -kyw4y0s.com -kyxdloan.com -kyy6.com -kyyj.net -kyzf.net -kzj365.com -kzlgd.com -kzore.com -kzsiee.com -kzt.cc -kztpms.com -kzwr.com -l-f.pw -l008.com -l2h.site -l36h.com -l5550.com -l68.net -l77777777.com -l7audiolab.com -l99.com -la-mo.com -la31.com -lab-z.com -labagd.com -labahao.com -labajun.com -labbang.com -labbase.net -labfan.com -laborlawtime.com -labtoday.net -labview.help -labxing.com -lacesar.com -lache.me -lactec.net -ladiyoga.com -ladjzs.com -ladouban.com -ladpex.com -lady177.com -lady361.com -lady8844.com -lady98.com -ladybirdedu.com -ladymetro.com -ladystr.com -ladywu.net -ladyyu.com -lafaso.com -lafhzx.com -lafoo.net -lagou.com -lagouevents.com -lagoujobs.com -lagowang.com -lahuashanbx.com -lai-ai.com -laibokeji.com -laibxw.com -laichou.com -laichuanfeng.com -laidacai.com -laidianba.net -laidiannet.com -laidingba.com -laidou.wang -laidudu.com -laifeng.com -laifu.net -laifudao.com -laigame7.net -laihema.com -laihua.com -laijiawen.com -laijiong.com -laijiuye.com -laikanxing.com -laikanxs.com -laiketui.com -lailaihui.com -lailikeji.com -lailook.net -laily.net -laimaidi.com -laimaika.net -laimanhua.com -laipai8.com -laiqi.net -laiqukankan.com -laird-tek.com -laishuge.com -laishui.info -laisj.com -laituia.com -laituijian.net -laiwang.com -laiwantv.com -laiwo.com -laiwu.net -laiwumedia.com -laixueedu.com -laixuexi.cc -laiyetxt.com -laiyifen.com -laiyihuo.com -laiyikeji.net -laiyinpai.com -laiyoushu.com -laiyouxi.com -laiyunzhou.com -laizee.com -laizhouba.net -laizhuan.com -laizi.net -laji51.com -lakala.com -laker.me -lakwdian.com -lalala.lol -lalkk.com -lalunalove.com -lamabang.com -lamahui.com -lamaison-arting.com -lamajie.com -lamall.com -lamaqun.com -lamateam.com -lamaying.com -lambda.hk -lamian.tv -lamiu.com -lamoart.com -lamost.org -lampchina.net -lampholder.cc -lampouomo.com -lampym.com -lamyu.com -lan-bridge.com -lan-gui.com -lan-kun.com -lan-lin.com -lan1001.com -lanbowanyouting.com -lanbozb.com -lanbu.net -lancdn.com -lancn.net -lanconvey.com -landa-solenoid.com -landai.com -landed.cc -landi.com -landian.la -landian.vip -landiannews.com -landing-med.com -landingbj.com -landizs.com -landongpage.com -landraco.com -landray.com -landscapecn.com -landtu.com -landui.com -landzestate.com -lanecn.com -lanfanapp.com -lanfeicastle.com -lanfeitech.com -lanfeiwine.com -lanfeng.net -lanfw.com -lang8.net -langao.com -langbobrand.com -langchao.com -langchengzhixin.com -langda.cc -langegruppe.com -langfang.com -langfangfc.com -langfly.com -langke.com -langke.tv -langlang.cc -langlangchinese.com -langlangjiajiao.com -langlib.com -langlive.com -langlvseo.com -langmanzg.com -langmanzw.com -langongju.com -langren.net -langren001.com -langren8.com -langrencard.com -langrenclub.com -langtaojin.com -langtze.com -languangdy.com -langya.org -langya3.com -langyabang.com -langyuekt.com -langyuseo.com -langzi.fun -lanhaicaijing.com -lanhaiweb.net -lanhaizhi.com -lanhii.com -lanhu.com -lanhuapp.com -lanhuhu.com -lanhusoft.com -lanindex.com -lanjie520.com -lanjing188.com -lanjing5.com -lanjinger.com -lanjingfm.com -lanjingtmt.com -lankdo.net -lanlanlife.com -lanlicai.com -lanlv.com -lanmao.com -lanmaos.com -lanmit.com -lanou3g.com -lanqb.com -lanqi.com -lanqiao.org -lanqibing.com -lanqiutv.com -lanqiuzu.com -lanreelh.com -lanren9.com -lanrenbijia.com -lanrenchengxu.com -lanrenclub.com -lanrenexcel.com -lanrenios.com -lanrenkaifa.com -lanrenmb.com -lanrentingshu.cc -lanrentuku.com -lanrenzhaofang.com -lanrenzhijia.com -lanrenzhoumo.com -lansedongli.com -lanseyujie.com -lansha.tv -lanshanweb.com -lanshi.hk -lanshizi.com -lanshou.net -lantaoyu.com -lantclean.com -lantian-hotel.com -lantian.tv -lantinglou.com -lantingmingjia.com -lantouzi.com -lantunyouxi.com -lanuss.com -lanvige.com -lanxicy.com -lanxinbase.com -lanxingman.com -lanxiniu.com -lanxiongsports.com -lanxum.com -lanyg.com -lanyingwang.com -lanyuanxiaoyao.com -lanyuevilla.com -lanyunbrand.com -lanyus.com -lanyusf.com -lanzhisky.com -lanzhouunicom.com -lanzhouyangsheng.com -lanzhuwh.com -lanzou.com -lanzoui.com -lanzous.com -lanzoux.com -lanzun.net -lao9.org -lao9123.com -laob.me -laobaigan-hs.com -laobanfa.com -laobangban.com -laobanmail.com -laobingmi.com -laobm.com -laobuluo.com -laobuxie.com -laocen.com -laod.wang -laodao.cc -laodong.me -laodong66.com -laodongfa.com -laoduo.net -laofu.online -laofuxi.com -laoge.xyz -laogedaojie.com -laogongshuo.com -laogu.cc -laogu.com -laogu.wang -laohanzong.com -laohe360.net -laohu.com -laohu8.com -laohuabao.com -laohuangli.net -laohucaijing.com -laohuyou.xyz -laohuyun.com -laojilu.com -laojiuxitong.com -laokaide.com -laoke.com -laolai.com -laolaosi.com -laoliang.net -laoliboke.com -laolinow.com -laoluoshouji.net -laomaotao.net -laomaotao.org -laomaotaopan.com -laomn.com -laomudong.cc -laonanren.cc -laonanren.com -laoniushuju.com -laoqiange.club -laoqiange.com -laoqianzhuang.com -laoqu123.net -laoren.com -laosiji.com -laosiji007.com -laosunit.com -laotiaomao.com -laowangappxy.xyz -laowangshengge.com -laowuxx.com -laoxiezi.com -laoxuehost.com -laoxuehost.net -laoxuezhuji.com -laoy.net -laoyaoba.com -laoyoujiaju.com -laoyouzhibo.com -laoyuanji.com -laoyuegou.com -laoyuge.com -laoyuji.com -laozizhu.com -laozongyi.com -laozu.com -laozuo.org -lapin365.com -lapland.name -laqddc.com -laqddcc.com -laqiangu.com -laravel-admin.org -larenla.com -larkapp.com -larksuite.com -larmb.com -laruence.com -laryoo.com -laser-cnc.com -laser4skin.com -laser568.com -laserfair.com -lashou.com -lashouimg.com -lastdream.net -lastikemami.com -lastww.com -lasy.site -lategege.com -latelee.org -latexstudio.net -latiaozixun.com -latiaozixun.net -latin100.com -lativ.com -latoooo.com -lattebank.com -lattecake.com -lavago.com -lavandehotels.com -lavapm.com -lavaradio.com -law-lib.com -law-star.com -lawbridge.org -lawbus.net -lawinfochina.com -lawlingyun.com -lawnewscn.com -laws5.com -lawschina.com -lawtimeimg.com -lawxin.com -lawxp.com -lawyee.com -lawyee.net -lawyee.org -lawyer027.com -lawyerbridge.com -lawyermr.com -lawyershanghai.net -lawyersuperman.com -layabox.com -layui-inc.com -layui.com -layuicdn.com -lazada.co.id -lazada.co.th -lazada.com -lazada.com.my -lazada.com.ph -lazada.sg -lazada.vn -lazonga.com -lazybios.com -lazylorna.com -lb-floor.com -lb0408.com -lbagan.com -lbal168.com -lbbniu.com -lbd99.com -lbddd.com -lbdyzj.com -lbdz.cc -lbesec.com -lbgoo.com -lbinin.com -lbl520.com -lboyue.com -lbrbis.com -lbwbw.com -lbx.cc -lbx777.com -lbxcn.com -lbxdrugs.com -lbxueyuan.com -lbyczf.com -lbzuo.com -lc-cn-n1-npxfk.com -lc-cn-n1-thovg.com -lc-news.com -lc123.net -lc787.com -lc800.com -lcbdf.net -lcbtv.com -lccareer.com -lccdn.net -lcchn.com -lccmw.com -lccz.com -lcddjm.com -lcdhome.net -lcdushi.com -lcdwiki.com -lcfby.com -lcfile.com -lcgod.com -lchot.com -lcjfz.com -lcjh.com -lckeshun.com -lckiss.com -lcode.org -lcofjp.com -lcol.net -lcouncil.com -lcrcbank.com -lcread.com -lcsrmyy.com -lcux.net -lcxwfc.com -lcxxg.com -lcyp.net -lczm.com -lczyy.com -ld0766.com -ld12366.com -ld1725.com -lday.me -ldcache.net -ldcang.com -ldd.me -lddengine.com -lddgo.net -ldeng.com -ldmap.net -ldmnq.com -ldmxxz.com -ldnovel.com -ldplayer.net -ldqxn.com -ldshj.com -ldsink.com -ldsjp.com -ldtui.com -ldxsfw.com -ldycdn.com -ldygo.com -ldyh666.com -ldz.cc -le-feng.com -le.com -le5le.com -le890.com -leachchen.com -leacol.com -lead-expo.com -leadal.com -leadal.net -leadbbs.com -leadcoretech.com -leader-tech.net -leadercf.com -leaderhero.com -leadermall.com -leadge.com -leadong.com -leaforbook.com -leafword.com -leagcard.com -leagsoft.com -leangoo.com -leankun.com -leanlan.com -leanote.com -leanote.org -leansoftx.com -leanwind.com -leap-pc.com -leapahead.vip -leapmie.com -leapmotor.com -learn-quantum.com -learndiary.com -learnfans.com -learnfuture.com -learning-archive.org -learnku.com -learnku.net -learsun.com -leb-china.com -lebang.com -lebang.net -lebogame.net -leboweb.com -lecai.com -lecake.com -lechain.com -lechange.com -leche.com -lechebang.com -lechinepay.com -lecloud.com -lecoinfrancais.org -leconginfo.com -lecoo.com -lecoo8.com -lecuntao.com -leda13.com -ledaiyu.com -ledanji.com -ledao.so -ledboke.com -ledcax.com -ledchina-sh.com -ledctl.com -lede.com -ledhxgc.com -ledi.us -ledianduo.com -lediaocha.com -ledo.com -ledongzone.com -ledpfw.net -ledth.com -ledu.com -ledu365.com -leduimg.com -lee130.com -leeco.com -leedongwook.net -leefanmr.com -leehom-cn.com -leehon.com -leeif.me -leeiio.me -leenzhu.com -leeon.me -leepoint.net -leesou.com -leetcode-cn.com -leetcodechina.com -leevy.net -leewiart.com -leeyegy.com -leeyuoxs.com -lefeng.com -lefengtuku.com -lefinance.com -leftfm.com -leftlady.com -leftso.com -legend-go.com -legendh5.com -legendsec.com -legendtkl.com -legoflow.com -legou456.com -legowechat.com -legu.cc -legu168.com -leguyu.com -leha.com -lehaitv.com -lehe.com -lehecai.com -lehepaper.com -lehihi.com -leho.com -lehu.host -lehu829.com -lehuadisplay.com -lehuipay.com -lehuiso.com -lehuozongxiang.com -leiba.com -leibei.cc -leida310.com -leidian.com -leidianip.com -leifengshi120.com -leifentaoci.com -leigod.com -leihuo.net -leikeji.com -leikw.com -leileiluoluo.com -leilong158.com -leimi.com -leimingtech.com -leimudata.com -leiniao.com -leiniao365.com -leining-shield.com -leiouxiong.com -leipengkai.com -leiphone.com -leipi.org -leiqunjs.com -leishen-lidar.com -leisoon.com -leisu.com -leisu123.com -leisurelypanda.com -leiting.com -leitingcn.com -leitingjunshi.com -leiue.com -leiyunge.com -leiyunge.net -leiyunge8.com -leiyunge88.com -lejiachao.com -lejian.com -lejianweike.com -lejiaolexue.com -lejj.com -leju.com -lejucaifu.com -lejuliang.com -lejunwl.com -lejuwh.com -lekannews.com -lekevr.com -lekoukou.com -lekpass.com -lelai.com -lele1688.com -leleda.com -leledp.com -lelefenxi.com -leleketang.com -lelelala.net -lelelove520.com -lelepyq.com -leleren.com -leletv.com -leletv.net -lelevod.com -lelewl.com -lelezone.com -lemai.com -lemaker.com -lemaker.org -lemall.com -lemedu.com -lemeitu.com -lemfix.com -lemicp.com -lemo360.com -lemobar.com -lemonyd.com -lemonyule.com -lemote.com -lempstack.com -lemuzhi.com -len-aquatics.org -lenget.com -lenggirl.com -lengqing.org -lengxiaohua.com -lengziyuan.com -lengzzz.com -lening100.com -leniugame.com -leniy.org -lenizhu.com -lenosoft.net -lenovator.com -lenovogame.com -lenovohci.com -lenovohit.com -lenovohuishang.com -lenovoimage.com -lenovomm.com -lenovomobile.com -lenovonetapp.com -lenovonowgo.com -lenovots.com -lenovouat.com -lenovowap.com -lenovows.com -lensuo.com -lenzhao.com -leo96.com -leoao.com -leobian.com -leoboard.com -leocode.net -leonblog.net -leonshadow.com -leosirius.fun -leozwang.com -lepaiok.com -lepan.cc -lepaowang.com -leqian.com -lequ.com -lequ7.com -lequan.wang -lequxs.com -lequyuanyi.com -lequz.com -leqv.online -lerengu.com -lergao.com -lerry.me -lers123.com -lers168.com -lers168.net -lerye.com -leshanvc.com -leshi123.cc -leshi123.com -leshou.com -leshow.com -leshu.com -leshuazf.com -leshuwu.com -leslie-cheung.com -lesofaka.com -lesoncooking.com -lesoshu.com -lesports.com -lesscss.net -lessisbetter.site -lestu.com -lesun.org -letabc.com -letaikeji.com -letao.com -letfind.com -leting.io -letmeneembibvnf.hk -letoom.com -letou8.com -letouqp.com -lets-study.com -letsebuy.com -letsfilm.org -lettercloud.net -letuknowit.com -letushu.com -letv-cdn.com -letv.com -letv8.com -letv8.net -letvapp.net -letvcdn.com -letvcloud.com -letvimg.com -letvlb.com -letvps.com -letwind.com -letwx.com -letyo.com -levect.com -leviathan.vip -leviding.com -levy.work -lewaila.com -lewaimai.com -lewang.ltd -leweicn.com -lewen.la -lewen.vip -lewen123.com -lewen55.com -lewen88.com -lewenba.cc -lewenn.com -lewenxsw.com -lewode.com -lexapro-web.com -lexar.com -lexiang-asset.com -lexiangjian.com -lexiangla.com -lexin.com -lexinchina.com -lexue.com -lexue8.com -lexueying.com -lexun.com -lexun365.com -leyan8.com -leyaoyao.com -leyaoyao.org -leybc.com -leyifan.com -leying.com -leying.org -leying365.com -leyingtt.com -leyishandong.com -leyix.com -leyixue.com -leyohotel.com -leyoucp.com -leyouquan.com -leyu5.com -leyuanbaby.com -leyubox.com -leyue100.com -leyun001.com -leyunapp.com -leyungame.com -leyunge.com -leyuntimes.com -leyuz.com -leyvo.com -lezai.com -lezf.com -lezhi.com -lezhi.me -lezhi99.com -lezhibo.com -lezhieducation.com -lezhiot.com -lezhiweilai.com -lezhiyun.com -lezhuan.com -lezhuan168.com -lezhuan365.com -lezi.com -lezyo.com -lf127.net -lf1782.com -lfan.net -lfang.com -lfbxw.com -lfcmw.com -lfengw.com -lfex.com -lfhacks.com -lfhygl.com -lfidc.net -lfkjgh.com -lfksqzj.com -lfkuncheng.com -lfl.gg -lflucky.com -lfmsj.com -lfoo.cc -lfork.com -lfppt.com -lfsxjzxh.com -lftdzd.com -lftuobang.com -lfungame.com -lfwin.com -lfwtc.com -lfx20.com -lfyzjck.com -lg1024.com -lg199.com -lg5.com -lgctshanghai.com -lgdisplayproduct.com -lgdlife.com -lgexam.com -lgmjg.com -lgo100.com -lgoing.com -lgole.com -lgpic.com -lgstatic.com -lguohe.com -lgzikao.com -lh-lx.com -lh168.net -lh310.com -lh75.com -lhao88.com -lhave.com -lhcmc.com -lhdyfc.com -lhflh.com -lhggjd.org -lhh.la -lhidc.net -lhlqw.com -lhm8.com -lhrbszb.com -lhs-arts.org -lhs11.com -lhsdad.com -lhsoso.com -lhtjyy.com -lhunan.com -lhwill.com -lhwytj.com -lhzjz.com -lhzly.net -lhzq.com -li-ca.com -li-ning.com -li63.com -li91.com -liageren.com -lialip.com -lialiu.com -lian666.com -lianaibashi.com -lianaibiji.com -lianbijr.com -liancaijing.com -lianchuang.com -liancsoft.com -liandaocn.com -liandaomobi.com -liandaquan.com -liangchan.net -liangchanba.com -liangduiban.com -liangjan.com -liangjian.com -liangjianghu.com -liangka.vip -liangkun.net -liangle.com -lianglong.org -liangongbao.com -liangongshequ.com -liangpinriyu.com -liangqikeji.com -liangshangou.com -liangshuang.name -liangshunet.com -lianguwang.com -liangxinyao.com -liangxu.wang -liangyadong.com -liangyi.com -liangyibang.net -liangyunchang.com -liangzhishu.com -liangziseo.com -liangzl.com -lianhaikeji.com -lianhecang.com -lianjia.com -lianjixia.com -liankexing.com -lianle.com -lianlianlvyou.com -lianlianpay.com -lianliantaoshop.com -lianlife.com -lianmeng.la -lianmeng.link -lianmeng90.com -lianmenhu.com -lianmishu.com -lianpingd.com -lianqi.net -lianqianluchangjia.com -lianshangbing.com -lianshijie.com -liansuo.com -liantai.cc -liantianhong.com -liantu.com -liantuobank.com -lianty.com -lianwangtech.com -lianwen.com -lianwifi.com -lianwo8.com -lianxiangcloud.com -lianxianjia.com -lianxinapp.com -lianxueqiu.com -lianyezy.com -lianyi.com -lianyu.com -lianzai.com -lianzais.com -lianzhong.com -lianzhongmingyuan.com -lianzhongyun.com -lianzhuli.com -liao1.net -liao98.com -liaocao.com -liaocheng.cc -liaochuo.com -liaocy.net -liaodanqi.me -liaogu.com -liaogx.com -liaohuqiu.net -liaoing.com -liaokeyu.com -liaokong.com -liaoliao.com -liaoliao99.com -liaosam.com -liaoshenrc.com -liaotiangou.com -liaotuo.org -liaow0316.com -liaoxuefeng.com -liaozhai.tv -liayoo.com -lib4d.com -liba.com -libaclub.com -libai.com -liball.me -libaopay.com -libaoyun.com -libchina.com -libinx.com -libisky.com -libivan.com -libomarathon.com -libreofficechina.org -libsou.com -libtop.com -libvideo.com -lic-bcbc.com -licai.com -licai18.com -licaibk.com -licaie.com -licaifan.com -licaigc.com -licaike.com -licaiker.com -licaimofang.com -licairen.net -licat.com -lichangtai.com -lichangtao.com -lichengdai.com -lichengwu.net -lichenjy.com -lichensafe.com -liciwang.com -licomsh.com -licqi.com -licstar.net -lid1688.com -lidaoliang.com -lidaren.com -lidazhuang.com -lidecloud.com -lidepower.com -lidewen.com -liding.me -lidodo.com -lidoooo.com -lidroid.com -liebao.live -liebaoidc.com -liebiao.com -liebrother.com -liechan.com -liefangzhe.com -liegou.org -lieguo.com -lieguozhi.com -liehu.tv -liehunwang.com -liehuo.net -liehuo.org -liejin99.com -lieju.com -lielb.com -lielema.com -lieliu.com -lieluobo.com -liemingwang.com -lienew.com -liepin.com -liepincc.com -liepinoverseas.com -lieqi.com -lieqinews.com -lierenzy.fun -liesauer.net -lietou-edm.com -lietou-static.com -lietou.com -lietou007.com -lietuwang.com -liewen.cc -liewen.la -liexing-ai.com -liexing.com -lieyou.com -lieyuncapital.com -lieyuncj.com -lieyunwang.com -lif8.com -lifanmy.com -life365.com -lifeall.com -lifeeu.com -lifeibo.com -lifeng.in -lifeng.net -lifeofguangzhou.com -lifesense.com -lifetm.com -lifetmt.com -lifevc.com -lifevccdn.com -lifeweeker.com -lifeweekly.cc -lifewtp.com -lifeyk.com -lifox.net -lifushop.com -ligerui.com -light3moon.com -lightalk.com -lightcss.com -lightfire.cc -lightget.com -lightgx.com -lighting163.com -lightingchina.com -lightinit.com -lightky.com -lightlygame.com -lightonus.com -lightpassport.com -lightplan.cc -lighttp.com -lightyy.com -liguda.com -liguhd.com -liguosong.com -lihaihong.com -lihaoquan.me -lihaoshuyuan.com -lihtao.com -lihua.com -lihuia.com -lihun66.com -lijiangdiy.com -lijiateng.com -lijiejie.com -lijigang.com -lijingquan.net -lijixiao.com -lijizhong.com -liju123.com -lijunkai.com -likamao.com -likangwei.com -likeacg.com -likecha.com -likechuxing.com -likecs.com -likeface.com -likefar.com -likefont.com -likehere.me -likeji.net -likejianzhan.com -likelink.net -likeshare-tech.com -likeshuo.com -liketm.com -liketry.com -likewed.com -liking.site -likingfit.club -likingfit.com -likuli.com -likuso.com -lili1996.com -lilinwei.com -lilishare.com -lilisi.com -lilithgame.com -lilithgames.com -lilosrv.com -liluotech.com -lilvb.com -lily-collection.com -lilyenglish.com -lilysamericandiner.com -lilysgame.com -lilyst.com -limaoxs.com -limax.com -limboy.com -limei.com -limian.com -limikeji.com -limin.com -liminglight.com -liminjie714.com -liminwang.com -limless.com -limoer.cc -limufang.com -linakesi.com -linban.com -linchuanschool.com -lincoc.com -lindiankanshu.com -linduwang.com -line0.com -linecg.com -linecg.net -linelayout.com -linewell.com -linewow.com -linezing.com -linfan.com -linfan.net -lingaoren.com -lingb.net -lingcaixinyuan.com -lingchenliang.com -lingd.cc -lingd.com -lingdai.name -lingdi.net -lingdiankanshu.co -lingdianksw.com -lingdonghuyu.com -lingdunwang.com -lingduohome.com -lingdz.com -lingfei.wang -lingfengyun.com -lingganjia.com -linghaofang.com -linghit.com -lingji666.com -lingjiaocheng.com -lingjoin.com -lingkaba.com -lingki.net -lingkou.com -lingla.com -linglingkaimen.com -linglongart.com -linglongtech.com -linglu666.com -lingmovie.com -lingnanpass.com -lingocn.com -lingosail.com -lingphone.net -lingquanb.com -lingquanba.wang -lingquanwu.com -lingqujz.com -lingrengame.com -lingrn.com -lingshandaoly.com -lingshangkaihua.com -lingshi.com -lingsky.com -lingtaoke.com -lingtiao.com -lingtool.com -lingtu.com -lingtuan.com -lingw.net -lingwu66.com -lingxi360.com -lingxianmulu.com -lingxicloud.com -lingxiu580.com -lingxmall.com -lingyi.org -lingyiliebian.com -lingyinsi.com -lingyinsi.org -lingyu.org -lingyuecloud.com -lingyuewx.com -lingyun.net -lingyun5.com -lingyutxt.com -lingzhanwenhua.com -lingzhilab.com -lingzhtech.com -linhao99.com -linhere.com -linhuiba.com -lining.com -lining0806.com -linjia.me -linjie.org -linjiedg.com -linjin.net -linjunet.com -linjunlong.com -link27.com -link2lib.com -linkadsapi.com -linkbroad.com -linkchant.com -linkchic.com -linked-f.com -linkedbyx.com -linkeddb.com -linkedhope.com -linkedin-event.com -linkedkeeper.com -linkedme.cc -linkedsee.com -linker.cc -linkernetworks.com -linkfinancier.com -linkfun.org -linkh5.com -linkh5.xyz -linkhaitao.com -linkheer.com -linkingme.com -linkist.net -linknewideas.com -linkpaper.net -linkpro.tech -linkrall-trk.com -linkresearcher.com -linkscue.com -linksfin.com -linksgood.com -linkshop.com -linksoon.net -linkstars.com -linktech.hk -linktom.com -linktom.net -linktt.com -linkunbin.com -linkvans.com -linkwebll.com -linlin.com -linlizone.com -linlongyun.com -linlongyx.com -linni.com -linnsea.com -linnyou.com -linodeclub.com -linovel.co -linovel.net -linovelib.com -linpx.com -linqu.tv -linquan.info -linquan.name -linquan.net -linqujob.com -linroid.com -linruanwangluo.com -linshang.com -lintey.com -lintongrc.com -linuo-paradigma.com -linuser.com -linux-code.com -linux-ren.org -linux.dog -linux.zone -linux178.com -linux265.com -linux5.net -linux6.com -linuxacme.icu -linuxba.com -linuxbaike.com -linuxbaodian.com -linuxboy.net -linuxcool.com -linuxdaxue.com -linuxdby.com -linuxde.net -linuxdot.net -linuxdown.net -linuxea.com -linuxeden.com -linuxeye.com -linuxfly.org -linuxgogo.com -linuxhobby.com -linuxidc.com -linuxidc.net -linuxkiss.com -linuxmi.com -linuxpanda.tech -linuxpk.com -linuxplus.org -linuxprobe.com -linuxqq.net -linuxrumen.com -linuxsight.com -linuxsir.com -linuxso.com -linuxsong.org -linuxstory.org -linuxtcpipstack.com -linuxtone.org -linuxyan.com -linuxyunwei.com -linuxyw.com -linwan.net -linweiyuan.com -linwenfa.com -linx-info.com -linxingyang.net -linyezhandidi.com -linyi.com -linyi.net -linyilongyuan.com -linyimama.com -linyiren.com -linzhuotech.com -linzhuxin.com -linzl.com -lionaka.com -lione.me -lionelliu.com -lipai365.com -lipf.tech -lipian.com -lipiji.com -lipilianghang.com -lipin.com -lipin010.com -lipinduihuan.com -lipip.com -lippt.com -liqiang999.com -liqihuoke.com -liqijt.com -liqile.com -liqinyi.com -liqu.com -liqucn.com -liquidnetwork.com -liqunshop.com -liqwei.com -lirenling.com -liriansu.com -liroi.com -lirui.name -lis99.com -lisa33xiaoq.net -lisdn.com -lisen.me -lishi.com -lishi5.com -lishi6.com -lishibu.com -lishichunqiu.com -lishiip.com -lishiming.net -lishiren.com -lishixinzhi.com -lishizhishi.com -lishouhong.com -lishuhang.me -lishui.com -lisizhang.com -lisp123.com -listarypro.com -listeneer.com -listenerri.com -listentide.com -listentoworld.com -listenvod.com -litang.me -litaow.com -litecoin.ink -litecoin.ren -litefeel.com -litets.com -liticool.club -litilala.site -litilala.xyz -litipumps.com -lititop.group -litpo.com -litten.me -little-sun.com -littleboy.net -littleee.com -littlekid.online -littleroost.net -littlesheep.com -littleswan.com -liu-kevin.com -liubaiapp.com -liubiji.com -liubo.live -liucaijiu.com -liuchengtu.com -liuchengtu.net -liuchuo.net -liudanking.com -liudatxt.com -liudon.org -liudu.com -liudu9.com -liudutv.com -liugejava.com -liugezhou.online -liugj.com -liugm.com -liuguofeng.com -liuhaolin.com -liuhu.net -liuinsect.com -liujg.com -liujiajia.me -liujiangblog.com -liujiasj.com -liujto.com -liujunworld.com -liujy.com -liukebao.com -liuker.org -liulan7.net -liulanmi.com -liulanqi.com -liulanqi.net -liulantao.com -liulian.com -liuliangbushou.com -liuliangcanmou.com -liuliangdada.com -liulianggo.com -liuliangjie.com -liulianglf.com -liuliangzu.com -liulianyu.com -liuliguo.com -liulin.cc -liulinblog.com -liulishuo.com -liulishuo.work -liulv.net -liumapp.com -liumeinet.com -liumh.com -liumwei.org -liumx.com -liunews.com -liunian.info -liunianbanxia.com -liurang.com -liushidong.com -liushuba.com -liusuping.com -liut.xyz -liuts.com -liuxianan.com -liuxiaoer.com -liuxiaofan.com -liuxiaolingtong.com -liuxing.com -liuxinzhou.com -liuxuchao.com -liuxue.com -liuxue114.com -liuxue360.com -liuxue51.net -liuxue86.com -liuxueban.org -liuxuecentre.com -liuxuegang.site -liuxuehksg.com -liuxuehr.com -liuxuekw.com -liuxuesmd.com -liuxuetown.com -liuxuewenshuwang.com -liuxueyun.com -liuxx.com -liuyanbaike.com -liuyang.com -liuyangfcw.com -liuyanzhao.com -liuyao.me -liuyifei.cc -liuyingqiang.com -liuyiwo.com -liuzhichao.com -liuzhixiang.com -liuzhoushide.com -liuzk.com -liuzongyang.com -liuzuo.com -liuzy88.com -live-era.com -live800.com -liveapp.ink -livechina.com -livecourse.com -liveinau.com -liveincy.com -liveme.com -livemediav.com -livemook.com -lives.one -livesone.net -livesupport24x7.com -liveuc.net -liveupdate01.asus.com -livevideostack.com -livinglabs.cc -livku.com -liwai.com -liwei.life -liwei.red -liweijia.com -liweiliang.com -liweiyameirong.com -liwenxin.com -liwenzhou.com -liwuhy.com -liwumaoapp.com -liwushuo.com -lixcx.com -lixiang.com -lixiangshu.net -lixianhezi.com -lixianhua.com -lixiaocrm.com -lixiaolai.com -lixiaomeng.net -lixiaoskb.com -lixiaoyun.com -lixiaozhe.com -lixin.co -lixingguang.com -lixiphp.com -lixuan360.com -liyangbit.com -liyangliang.me -liyangtuopan.com -liyangweb.com -liyanmobi.com -liyingfei.com -liyingkuan.com -liyipeixun.org -liyongseo.com -liyu8.com -liyuanheng.com -liyuanhospital.com -liyue.name -liyujn.com -lizaike.com -lizenghai.com -lizhaoblog.com -lizhaoxiang.com -lizhenwang.com -lizhi.com -lizhi.fm -lizhi.io -lizhi001.com -lizhi110.com -lizhi77.com -lizhidaren.com -lizhifilm.com -lizhifm.com -lizhiqiang.name -lizhiweike.com -lizhixia.com -lizhongyi.com -lizi.com -lizi.tw -liziqiche.com -lj-bank.com -lj168.com -ljbao.net -ljc58.com -ljcdn.com -ljcoop.com -ljemail.org -ljfjz.com -ljhis.com -ljhks.com -ljhks.net -ljia.net -ljimg.com -ljjgdj.org -ljjhfc.com -ljlcd.com -ljmeng.site -ljqkk.com -ljsdk.com -ljsw.io -ljt365.com -ljtx.com -ljw408com.com -ljwdns-vip.com -ljwit.com -ljxww.com -ljyewei.com -ljzfin.com -lkaty.com -lkcsgo.com -lkddq.com -lkgame.com -lkgshq.com -lkjl.com -lkjujm.com -lkkcdn.com -lkker.com -lkkued.com -lkmcdk.com -lkme.cc -lkong.net -lkxianglong.net -lkyou.com -ll-hao123.com -ll11.com -llbetter.com -llcat.tech -llduang.com -llever.com -llewan.com -llgkm.com -llgo.work -llidc.com -lljgame.com -lljgxx.com -llku.com -llqzg.net -llsapp.com -llscdn.com -llsops.com -llss.us -llsserver.com -llssite.com -llsstaging.com -lltaohuaxiang.com -lltoken.com -lltxy.com -llwin.com -llwt.ink -llycloud.com -llzg.com -llzw888.com -lm19.net -lm9999.com -lmacc.com -lmbang.com -lmbest.com -lmbld.com -lmdk01.com -lmdouble.com -lmf9.com -lmgouwu.com -lmjtgs.com -lmjx.net -lmlc.com -lmlphp.com -lmlym.com -lmm8.com -lmoskernel.org -lmsail.com -lmth2013.com -lmtw.com -lmtxz1.com -lmtxz1.net -lmview.com -lmwgame.com -lmwlhh.com -lmwljz.com -lmxxxz.com -lmxy521.com -lmyd5.com -lmyjsq.com -ln2car.com -lncld.net -lncldapi.com -lndao.com -lndhdx.com -lndzxy.com -lnemci.com -lnest.com -lnfw.net -lnfzb.com -lngqt.com -lnicc-dl.com -lnicp.com -lninfo.com -lnitec.com -lnjzxy.com -lnk0.com -lnkdata.com -lnlotto.com -lnmp.org -lnnoo.com -lnok.net -lnpjw.com -lnrcu.com -lnrsks.com -lnslymy.com -lntenghui.com -lntvu.com -lntycp.com -lnvsystem.com -lnyhrlzy.com -lnyun.net -lnyyzyxy.com -lnzikao.com -lnzsks.com -lo97.com -load-page.com -locatran.com -locez.com -lockfans.com -lockscreenimg.com -locnavi.com -locojoy.com -locoso.com -locoy.com -locoyposter.com -locren.com -loctek.com -locvps.com -lodashjs.com -loesspie.com -loexu.com -lofficielchina.net -loftcn.com -lofter.com -loftshine.com -log4d.com -log4geek.cc -logacg.com -logclub.com -logdu.com -loghao.com -logi-inno.com -logisticsy.com -logo-emblem.com -logo123.net -logo234.com -logo33.com -logo520.com -logo888.com -logoaa.com -logobiaozhi.com -logodao.com -logodashi.com -logohhh.com -logoids.com -logoly.pro -logonc.com -logooo.net -logopay.com -logoquan.com -logoshe.com -logosheji.com -logosj.com -logowu.com -logozhan.com -logozhizuowang.com -logphp.com -logwing.com -lohaa.com -lohaslady.com -lohasus.com -loho88.com -loji.com -lok.me -lokyi.name -lol123.net -lol99.com -loldan.com -loldh.com -loldk.com -loldytt.com -loldytt.org -loldytt.tv -loldyttt.com -loldyttw.com -loldyttw.net -lolgo.net -loli.cd -loli.ee -loli.my -lolico.moe -lolip.net -lolisb.com -lolitaf.com -lolitawardrobe.com -loliyun.vip -loljy.com -lolkeng.com -lolmax.com -lolmf.com -lolmz.com -lololer.com -lolshipin.com -loltmall.com -lolyculture.net -lomoment.com -lomu.me -lon3d.com -loncent.com -loncin.com -loncinindustries.com -london9999.com -londonermacao.com -lonelystar.org -lonery.com -long-jf.com -long-termproperty.com -long-tv.com -long5.com -long7.com -long708.com -longaa.com -longanlaw.com -longau.com -longcai.com -longcheer.com -longchen80.com -longchengtg.com -longcity.net -longclouds.com -longcore.com -longdai.com -longdang.org -longdear.com -longdezhu.com -longdian.com -longdoer.com -longene.org -longfenfa.com -longfor.com -longfu360.com -longger.net -longhoo.net -longhu.net -longhua.net -longhuiren.com -longhuvip.com -longigroup.com -longjcun.com -longjiazuo.com -longjushangcheng.com -longk.com -longlongweb.com -longmaosoft.com -longmeng.com -longmenmingche.com -longmiao.wang -longmotto.com -longmushengwu.com -longqikeji.com -longquan-baojian.com -longquecdn.com -longre.com -longren.com -longruo.com -longsan.com -longseek.com -longseor.com -longshangrc.com -longsheng.com -longsheng.org -longsheng988.com -longshine.com -longsok.com -longsto.com -longsunhenges.com -longsys.com -longtaifoods.com -longtaitouxiaoshuo.com -longtaiwj.com -longtanshuw.net -longtask.com -longteng52.com -longtengwang.com -longtugame.com -longtuohy.com -longwang.cc -longwenedu.com -longwiki.net -longwiki.org -longwin.org -longwindspg.com -longxi-tech.net -longxianwen.net -longxuan.ren -longyangm.com -longygo.com -longyin.net -longyu.cc -longyuedu.com -longyusheng.org -longzhongtv.com -longzhu.com -longzhu.tv -longzhulive.com -longzu.com -longzu5.co -lonlife.org -lontiumsemi.com -loocall.com -loodd.com -looeen.com -looeo.com -looeoo.com -loogfa.com -loohuo.com -look8.com -lookao.com -lookbaby.com -lookbc.com -lookbravo.com -lookchem.com -lookcss.com -lookdiv.com -lookgame.com -looking-car.com -lookr.cc -lookrv.com -looktm.com -looktmt.com -lookvin.com -loome.net -loonapp.com -loongnix.com -loongnix.org -loongshine.com -loongsin.com -loongson.org -loongsonclub.com -loongzone.com -looooker.com -loopjump.com -looquan.com -loorain.com -loorin.com -loosun.com -looyu.com -looyuoms.com -looyush.com -lopetech.net -lophoctienganh.org -lopkino.com -lorefree.com -lorjarmon.com -losala.com -losking.com -lossyou.com -lostali.com -lostphp.com -lostsakura.com -lotanelaw.com -lotevision.com -lotlab.org -lotour.com -lotour.net -lotpc.com -lotpen.com -lotsmv.com -lotusair.net -lotusdata.com -lotuseed.com -lotut.com -loubobooo.com -louding.com -louishan.com -louislivi.com -louisvv.com -loukee.com -loukky.com -loulansheji.com -loulantxt.com -loulanwang.com -loupan.com -louqun.com -loushi12.com -loushiwo.com -lousj.com -lousw.com -louyue.com -love.tv -love1992.com -love21cn.com -love3721.com -love616.com -love778.com -love84.com -love85g.com -lovean.com -loveapp.com -lovebank.ly -lovebizhi.com -loveforvenus.com -lovehaimi.com -lovehhy.net -lovehifi.com -loveineurope.com -loveinhere.com -lovejavascript.com -lovejia.win -lovelacelee.com -loveleesangwoo.com -loveliao.com -lovelive.tools -lovelivecn.org -lovelixiang.com -lovemojito.com -loveniwed.com -loveota.com -lovepd.com -loveqindy.com -loverili.com -lovesec.com -lovesoo.org -lovestu.com -loveteemo.com -loveuav.com -loveunix.net -lovev.com -lovewith.me -lovewj.info -lovewusun.com -lovexint.com -loveyd.com -loveyisheng.com -lovezbm.com -lovezhangjunning.com -lovfp.com -lovology.com -lovstone.com -lowpew.com -lowsfish.com -lowucity.com -loxpo.com -loxue.com -loyaltychina.com -loyo.cc -loyogame.com -lpcheng.com -lpllol.com -lplrbi.bar -lply.net -lppz.com -lprcx.com -lpswz.com -lptiyu.com -lpwnice.com -lpxin.com -lpxinjuhui.com -lpxt.com -lq-bm.com -lq328.com -lq41.vip -lq580.com -lq5u.com -lqabr.com -lqalm.com -lqart.com -lqbj.com -lqbj66.com -lqbld.com -lqbyj.com -lqgc.net -lqgcb.com -lqgrdj.com -lqhigo.com -lqhualang.com -lqjob88.com -lqjuwuwang.com -lqpsj.com -lqqm.com -lqrcb.com -lqsy.net -lqxshop.com -lqyaopin.com -lqzh.me -lqztbzx.com -lqzwdj.com -lr-amm.com -lr-link.com -lrc99.com -lrcb.net -lrcgc.com -lrcku.com -lrd.cc -lrdzt.com -lread.net -lrenwang.com -lrhold.net -lrist.com -lrkdzx.com -lrs001.com -lrscloud2.com -lrscloud3.com -lrswl.com -lrts.me -lrwoman.com -ls-17.com -ls-gb.com -ls-marathon.com -ls12.me -lsbankchina.com -lsbchina.com -lsccb.com -lscut.com -lsfyw.net -lsg3.com -lsgrandtheatre.com -lsgsgs.com -lsgw.com -lsgzn.com -lshou.com -lshv8.com -lsj.ac -lsjacg.com -lsjczj.com -lsjgcx.com -lsjrcdn.com -lsjsm.com -lsjtfinance.com -lsjvps.com -lsjxck.com -lsjyy3800.com -lskejisoft.com -lskyf.com -lsljgc.com -lsnetlib.com -lsoos.com -lspjy.com -lsq6.com -lsqifu.com -lssdjt.com -lssen.com -lstazl.com -lstest.com -lsttapp.com -lsttnews.com -lsun.net -lsuoled.com -lsup.net -lsw315.com -lswjg.com -lswlsw.com -lsxz.org -lsyouth.com -lsywtc.com -lszj.com -lszjyj.com -lszp.cc -lt-tree.com -lt-uv.com -lt3c.com -ltaaa.com -ltaaa.net -ltd.com -ltdcr.hk -ltesting.net -lthack.com -ltimg.net -ltkdj.com -ltlovezh.com -ltmei.com -ltmp.cc -ltnic.com -ltp-cloud.com -ltp.ai -ltplayer.com -ltrzyx.com -ltsf.com -ltswxy.com -lttconn.com -ltteach.com -lttvip.com -ltwkw.com -ltxjob.com -ltxs.me -lty.fun -ltzsjt.com -lu.com -lu35.com -lu4n.com -lua.ren -luaninfo.com -luanren.com -luastudio.net -lubandata.com -lubanjianye.com -lubanpm.com -lubanshop.com -lubanso.com -lubansoft.com -lubanu.com -lubanway.com -lubiao.com -lubotv.com -luchangwei.net -luchinfo2.com -luciaz.me -luck4ever.net -luckeeinc.com -luckfriend.com -luckincoffee.com -luckincoffeecdn.com -lucklnk.com -luckyair.net -luckycoding.com -luckycoffee.com -luckyjia.com -luckykun.com -luckyxp.net -lucode.net -lucoder.com -lucy365.com -lucydraw.com -ludake.com -ludashi.com -ludiban.com -ludmilaemarcos.com -ludongdong.com -ludou.org -luduzww.com -luedian.com -luexiao.com -luexpo.com -luezhi.com -lufangjia.com -lufax.com -lufaxcdn.com -lufengqiyun.com -luffycity.com -luftweb.com -lufuli.com -lufuli.net -lufunds.com -lugir.com -luhehospital.com -luhongfu.com -luics.com -lujiang56.com -lujianmei.com -lujianxin.com -lujingtao.com -lujq.me -lujun9972.win -lukachen.com -lukaplayer.com -lukeer.com -lukehubei.com -lukiya.com -lukou.com -lukuanart.com -lulala.com -lulaohan.com -lulinux.com -lulu77.com -lulufind.com -lum114.com -lumai.net -lumajia.com -lumanman1688.com -lumi258.com -lumiaxu.com -lumit.org -lumiunited.com -lumyhouse.com -lunar2013.com -lunchong.com -lunkuokeji.com -lunli1988.com -lunlishi.com -lunwencar.com -lunwenchachong.org -lunwendj.com -lunwenqikan.net -lunwenschool.com -lunwenstudy.com -lunwentianxia.com -lunwentong.com -lunwenxiazai.com -lunxia.com -lunzima.net -luo8.com -luobo020.com -luobo360.com -luobocai.com -luobotou.org -luobowin10.com -luobowin8.com -luoboxia.com -luochen.com -luocheng.org -luochenyl.com -luochenzhimu.com -luochunhui.com -luocs.com -luodian.com -luodiying.net -luodw.cc -luody.info -luofan.net -luogu.org -luohanyu.cc -luohuedu.net -luointo.com -luojiji.com -luojilab.com -luojituili.com -luokewan.com -luokr.com -luokuang.com -luolai.com -luolai.tech -luolei.org -luomapan.com -luomi.com -luoo.net -luoohu.com -luooqi.com -luoqiu.com -luoqiuzw.com -luoqiuzww.com -luosi.com -luosimao.com -luotiannews.com -luotianyi.org -luowave.com -luoxiang.com -luoxudong.com -luoxue.com -luoyechenfei.com -luoying66.com -luoyuanhang.com -luozhongxu.com -luozk.com -luozongle.com -lup2p.com -lupaworld.com -lupeng.me -lupeng88.com -luqidong.com -lure123.com -lurefans.com -lurelogs.com -lurenshuwx.com -lurezu.com -lusen.com -lushang.me -lushaojun.com -lushu.com -lusongsong.com -lussac.net -luster3ds.com -lustervision.com -lutao.com -lutong2013.com -luturen.com -luv66.com -luways.com -luwei.me -luweitech.com -luwenxinqing.com -lux88.com -luxee.com -luxemon.com -luxianpo.com -luxiao.com -luxiwang.com -luxiyun.com -luxtarget.com -luxuqing.com -luxury-theme.com -luyady.com -luyanghui.com -luyewooden.com -luyinla.com -luyouqi.biz -luyouqi.com -luyouxia.com -luyuanqj.com -luzexi.com -lv74.com -lv96.com -lvanol.com -lvbaishun.com -lvchanghuanbao.com -lvchayun.com -lvchehui.com -lvcheng.com -lvchicar.com -lvdoutang.com -lvfang.cc -lvfl.net -lvgaud.ga -lvgou.com -lvguang.net -lvhezi.com -lvhuadai.com -lvjihong.com -lvjinsuo.com -lvkun.site -lvlian5.com -lvluowang.com -lvlvlvyou.com -lvmae.com -lvmama.com -lvmama.ink -lvmotou.com -lvnanbao.com -lvpai114.com -lvping.com -lvren.com -lvruan.com -lvrui.io -lvse.com -lvsehuxiniubangcha.com -lvsetxt.com -lvshedesign.com -lvshi567.com -lvshiminglu.com -lvshou.com -lvshouwe.com -lvshunfang.com -lvtao.net -lvtu-vision.com -lvtu.com -lvtu8.com -lvtudiandian.com -lvwan365.com -lvwang.com -lvwenhan.com -lvwo.com -lvya.com -lvye.com -lvye.org -lvyestudy.com -lvyetong.com -lvyidoor.com -lvyou114.com -lvyou521.com -lvyoubaotech.com -lvyougl.com -lvyouw.net -lvyuanpam.com -lvyuetravel.com -lvzheng.com -lw0591.com -lw0703.com -lw208.com -lw23.com -lw54.com -lw85.com -lw880.com -lw881.com -lwcj.com -lwd3699.com -lwdjc.com -lweasy.com -lwedu.com -lwen.org -lwfengji.net -lwfjmj.com -lwgsw.com -lwhouse.com -lwinfo.com -lwinl.com -lwinst.com -lwj786.org -lwkz.cc -lwlm.com -lwons.com -lwork.com -lwqklm.com -lwrcb.com -lwsay.com -lwswxs.com -lwtxt.cc -lwtxw.com -lwurl.to -lwxgds.com -lwxiaoshuo.com -lwxs.org -lwxshow.com -lwxstxt.com -lwxxmp.com -lx-led.com -lx.cok.elexapp.com -lx.pub -lx138.com -lx167.com -lx2.cok.elex.com -lx2.cok.elexapp.com -lx3.cok.elexapp.com -lx598.com -lxall.net -lxbbt.com -lxckj.com -lxcvc.com -lxdms.com -lxdns.com -lxdns.info -lxdns.net -lxdns.org -lxf.me -lxg2016.com -lxin007.com -lxjep.com -lxjk999.com -lxjwlt.com -lxlggo.com -lxly168.com -lxmiyu.com -lxs123.com -lxsales.com -lxw1234.com -lxway.com -lxway.net -lxws.net -lxxm.com -lxy.me -lxy520.net -lxybaike.com -lxyes.com -ly-sky.com -ly-wz.com -ly.com -ly200-cdn.com -ly200.com -ly39zx.com -ly522.com -ly6080.com -lyancafe.com -lyancoffee.com -lyangchuanbo.com -lyaudio.com -lyblog.net -lybol.com -lybus.com -lycgs.com -lycheer.net -lychevy.com -lyclzyc.com -lycndq.com -lyd6688.com -lydezx.net -lydfyjhotel.com -lydhb888.com -lydsy.com -lydzpb.com -lyecs.com -lyfczxw.com -lyfff.com -lyg001.com -lyg01.net -lyg321.com -lyg800.com -lygdfrcb.com -lygfdc.com -lyghi.com -lygjnsb.com -lygmedia.com -lygnews.com -lygou.cc -lygrffw.com -lygsyyijia.com -lygzamzam.com -lyhanda.com -lyhero.com -lyhuadu.com -lyjiayi.com -lyjinqiao.com -lylryy.com -lymil.com -lymlgj.com -lyn8.com -lynkco.com -lyobs.com -lypd.com -lyps.net -lypyxx.com -lyqugee.com -lyragosa.com -lyrc.cc -lyric-robot.com -lyshgk.com -lysk.net -lysqdx.com -lysqzs.com -lysteel.com -lystrt.com -lytning.xyz -lytoufang.com -lytpw.com -lyun.me -lyunweb.com -lyvnee.com -lywf.me -lywww.com -lywxww.com -lyxyxx.com -lyy99.com -lyyapp.com -lyyourc.com -lyyrsy.com -lyyzfx.net -lyz810.com -lyzfgjj.com -lyzhujia.com -lyzp100.com -lz160.net -lz310.com -lz520.net -lz6.com -lzabcd.com -lzafny.com -lzane.com -lzbank.com -lzc369.com -lzcbnews.com -lzccb.com -lzcqt.com -lzeweb.com -lzfjq.com -lzg.im -lzgxq.com -lzhongdian.com -lzhpo.com -lzjdbjc.com -lzjoy.com -lzlj.com -lzmoyin.com -lzmy123.com -lzqs.net -lzqsyxx.com -lzsb.org -lzsmedia.com -lzsq.net -lzsysj.com -lztai.com -lztnd.com -lztv.tv -lztvnet.com -lztx123.com -lzvw.com -lzw.me -lzwifi.com -lzxdly.com -lzxgo.com -lzydjy.com -lzyun.vip -lzzyad.com -lzzzf.com -m-finder.com -m-rainbow.com -m.biz -m.dji.com -m.im -m.sohu -m.travelzoo.com -m0816.com -m096.com -m0n0china.org -m1315.com -m176.net -m18.com -m1905.com -m1910.com -m1938.com -m1ok.com -m1page.com -m1world.com -m2ez.com -m2mzy.com -m3guo.com -m448.com -m4yy.com -m598.com -m5bn.com -m5stack.com -m6.ai -m6go.com -m818.com -m8cool.com -m90cc.com -m937.com -m9o.net -ma-china.com -ma16.com -ma3office.com -mabangerp.com -mabibook.com -mabiji.com -mabotech.com -mac189.com -mac69.com -macabc.com -macaihong.net -macapp.so -macapp8.com -macappbox.com -macappx.com -macauinternationalclubbingshow.com -macaumonthly.net -macausuncityad.com -maccura.com -macdaxue.com -macflow.net -macgg.com -mach4s.com -machaojin.com -machbbs.com -machenike.com -machine-information.com -machine-visions.com -machine35.com -machine365.com -machinelearningconf.org -macidea.com -macjb.com -mackentan.com -mackext.com -macno1.com -macocn.com -macoshome.com -macpeers.com -macrocheng.com -macrosan.com -macrosilicon.com -macrounion.com -macrowing.com -macrr.com -macshuo.com -macsky.net -macsofter.com -macv.com -macw.com -macwk.com -macz.com -maczapp.com -maczd.com -maczhi.com -maczj.com -mad114.com -madailicai.com -made-in-china.com -madefuns.com -madeqr.com -madigi.net -madio.net -madisonboom.com -madku.com -madmalls.com -madou.com -madouer.com -madouka.com -madown.com -madserving.com -mafangwo.com -mafenggo.com -mafengs.com -mafengvwo.com -mafengwo.com -mafengwo.ink -mafengwo.net -mafenword.com -maff.com -mafutian.net -mag10000.com -mag998.com -magcloud.net -magecorn.com -magedu.com -magentochina.org -magewell.com -magi.com -magicboxgame.com -magicdata.io -magicleaders.com -magicnetmall.com -magicwatchface.com -magicwinmail.com -magicyourlife101.com -magook.com -maguang.net -magvision.com -mahetao.org -mahetao3.com -mahoupao.com -mahoupao.net -mahua.com -mahuatalk.com -mai.com -maianhao.com -maibasa.com -maibw.net -maicdn.com -maichawang.com -maiche.com -maiche168.com -maichuang.net -maicuole.com -maidangao.com -maidengju.net -maidi.me -maidige.com -maidixun.com -maidoc.com -maidou.com -maidouvr.com -maiduo.com -maienguoji.com -maiensiyuan.com -maifjb.com -maigevoice.com -maigoo.com -maigv.com -maihanji.com -maihaoche.com -maihehd.com -maijia.com -maijiaba.com -maijiabashi.com -maijiakan.com -maijichuang.net -maijx.com -maike51.com -maikenu.com -maikesi.cc -mail-qq.com -mail163.com -maila88.com -mailatuan.net -mailbusinfo.com -mailehudong.com -mailejifen.com -mailpanda.com -mailshanguo.com -maimaimaiw.com -maimemo.com -maimemostatus.com -maimengjun.com -maimengkeji.com -maimiaotech.com -maimieng.com -maimowang.com -maimuban.com -mainaer.com -mainone.com -maintao.com -mainwww.com -maipu.com -maiquan.me -mairoot.com -mairuan.com -mairuier.com -maiscrm.com -maishashop.com -maishebei.com -maishitv.com -maishou88.com -maishoudang.com -maishoumm.com -maisifenqi.com -maisorn.com -maisu.vip -maisucai.com -maitao.com -maitaods.com -maitaowang.com -maitianqinzi.com -maitianquan.com -maitix.com -maitix.net -maitoufa.org -maitu.cc -maituan.com -maiwe.com -maixhub.com -maixiaba.com -maixj.net -maixuewen.com -maixunlei.com -maiya91.com -maiyadi.com -maiyaole.com -maiymai.com -maizhi.com -maizhiying.me -maiziedu.com -maizijf.com -maizim.com -maizipo.com -maizitime.com -maizuo.com -majia99.com -majiamen.com -majianwei.com -majing.io -majorsec.com -majorserving.com -majsoul.com -maka.im -maka.mobi -makaevent.com -makaidong.com -makaiqian.com -make8.com -makeapp.co -makebizeasy.com -makecn.net -makedie.me -makeding.com -makefang.com -makefont.com -makejinrong.com -makelove.la -makepic.net -makepolo.com -makepolo.net -maker8.com -makerbio.com -makerfun.org -maketion.com -makeweiyuan.com -makezixun.com -makingvfx.com -makuwang.com -malabeibei.com -malagis.com -malait.com -malaosi.com -maldiveszh.com -maldun.com -males120.com -maliapi.com -maliquankai.com -mall-builder.com -mallchina.net -mallcoo.net -mallhaha.com -mallocfree.com -mallshow.net -mallstaroa.com -mallzhe.com -mallzto.com -malmam.com -malong.com -maltm.com -malu.me -mama100.com -mamacn.com -mamahao.com -mamahuo.com -mamcharge.com -mamecn.com -mamicode.com -mamilist.com -mamioo.com -mamipush.com -mamsh.org -man189.com -mana-harp.com -manage.c3edge.com -managershare.com -manben.com -manboker.com -mandao-tech.com -mandarincapital.net -mandarinedu.org -mandarinhouse.com -mandian.com -mandudu.com -manduwu.com -manew.com -manewvr.com -manfen.net -manfen5.com -manfenedu.com -manga32.com -mangafunc.fun -mangake.com -mangege.com -mangg.com -mangg.net -mangguo.com -mangguo.org -mangguo168.com -mangocity.com -mangoebike.com -mangogame.com -mangowed.com -mangrovetreesanya.com -mangtuhuyu.com -manguo42.com -mangxia.com -mangxuewang.com -manhua1.com -manhua123.net -manhua365.com -manhuaba.cc -manhuabei.com -manhuacheng.com -manhuadang.net -manhuadao.com -manhuadaohang.com -manhuadb.com -manhuafen.com -manhualang.com -manhuama.net -manhuang.org -manhuaniu.com -manhuapi.com -manhuaren.com -manhuatai.com -manhuav.com -manhuayang.com -manhuazj.com -manhui.net -maninmusic.com -manjiwang.com -manlinggame.com -manlongye.com -manluoni.com -manluotuo.com -manmanapp.com -manmanbuy.com -manmango.com -manmankan.com -manmu.net -mannkit.com -manogk.com -manong.io -manongdao.com -manonggu.com -manongjc.com -manongs.com -manongzj.com -manosp.com -manpianyi.com -manrong.win -manshen.net -mansss.com -mansuno.com -mantianxingmall.com -mantouji.net -mantusy.com -mantutu.com -manwuxian123.com -manxiangyi.com -many88.com -manyanu.com -manyjs.com -manylaw.com -manymoonsculture.org -manyoo.net -manyou.com -manyoujing.net -manzhan.com -manzhan8.com -manzj.net -manzuo.com -mao-shen.com -mao.li -mao999.com -maobotv.com -maobugames.com -maodou.com -maodouapp.com -maoerduo2018.com -maoflag.net -maogx.win -maoha.com -maohaha.com -maoken.com -maokz.com -maoln.com -maomaoche.com -maomaojie.com -maomaow.com -maomaoxue.com -maomego.com -maomiboy.com -maopuyouxi.com -maoqitian.com -maoqiuapp.com -maoshimei.com -maotaizuichen.com -maotuying.com -maowow.com -maoxiaotong.net -maoxinhang.com -maoxun.net -maoyan.com -maoyanziyuan.com -maoyi.biz -maoyia.com -maoyidi.com -maoyigu.com -maoyiw.com -maoyiwang.com -maoyouhui.cc -maoyuncloud.com -maoyundns.com -maozhuar.com -maozhuashow.com -mapabc.com -mapbar.com -mapeng.net -mapgis.com -mapgun.com -mapks.com -maple-game.com -maplebeats.com -maplef.net -mappn.com -maqingxi.com -maqinnews.com -marakaro.com -mararun.com -marcores.com -mariadbpub.com -marineoverseas.com -marioall.com -marioin.com -markchao.org -markdown.xyz -markdream.com -marketiva-platform.com -marketreportchina.com -markhoo.com -markjour.com -markmall.com -markmiao.com -marknum.com -markonreview.com -markorchem.com -marksmile.com -maro6.com -maroclub.net -maroon91.com -marry5.com -marry80.com -mars-droid.com -marsmers.com -marstor.com -marstv.com -martech365.com -martincl2.me -marveldental.net -mas-omkj.com -mas10010.com -mas300275.com -masadora.jp -masadora.net -masamaso.com -mascaw.com -mascwgs.com -masdiy.com -masdjy.com -masej.com -mashangmai.com -mashangshijie.com -mashanina.org -mass-evo.com -massage7.com -massclouds.com -masscrunch.com -masterlab.vip -mastersay.com -mastersim123.com -mastertimes.net -mastodonhub.com -mastudio.org -masuit.com -masxly.com -masyi.com -mat-test.com -matao.com -matchday.cc -matchvs.com -math168.com -mathchina.net -mathfan.com -mathfunc.com -mathpretty.com -mati.hk -maticsoft.com -matocloud.com -matongwu.com -matongxue.com -matools.com -matouwang.com -matt33.com -mattge.com -matthewsery.com -mattressmachinery.net -mauu.me -mavuz.com -mawei.live -mawen.co -mawentao.com -max-c.com -max232.net -maxacg.com -maxdoge.com -maxent-inc.com -maxgj.net -maxhub.com -maxhub.vip -maxiang.info -maxiang.io -maximiliansery.com -maxitas.com -maxjia.com -maxket.com -maxlicheng.com -maxlv.org -maxpda.com -maxreader.net -maxscend.com -maxstv.com -maxthon.com -maxthonimg.com -maxuscloud.com -maxvinch.com -maxwealthfund.com -maxwellsery.com -maxwi.com -maxxipoint.com -maya09.com -mayahuashi.com -mayatu.com -maybe2016.com -maybeiwill.me -maydeal.com -mayi.com -mayiangel.com -mayicms.com -mayidui.net -mayihot.com -mayihr.com -mayijieqian.com -mayima.net -mayinews.com -mayishebao.com -mayishoubei.com -mayitek.com -mayitxt.com -mayiw.com -mayiwenku.com -mayiyx.com -mayizhuanlan.com -mayou18.com -maysunmedia.com -mayswind.net -mayun1.com -maywant.com -mazakii.com -mazey.net -mazhan.com -mazhuang.org -mazida.com -maziyou.com -mb-go.com -mb301.com -mb5u.com -mb700.com -mb99.vip -mb999.vip -mbabao.com -mbabycare.com -mbachina.com -mbajyz.com -mbalib.com -mbalunwen.net -mbanggo.com -mbaobao.com -mbaoxian.net -mbazl.com -mbb0760.com -mbcjapan.net -mbcloud.com -mbcwm.org -mbgo.com -mbinary.xyz -mbo5.com -mbokee.com -mboxone.com -mbsky.com -mbtsg.com -mbulanna.com -mbz64.com -mc-ccpit.com -mc-test.com -mc.fyi -mc0411.com -mc123.cc -mc26.com -mc361.com -mc91.com -mcaccess-e.com -mcake.com -mcarding.com -mcbbs.net -mcbrother.com -mccaee.com -mcchcdn.com -mcchina.com -mcchou.com -mcdchina.net -mcdsusan.com -mcdusiv.com -mcdvisa.com -mcearnmore.com -mcfuzhu.net -mchat.com -mchifi.com -mcjcjx.com -mcjd.net -mcmssc.com -mcnnic.com -mcooks.com -mcool.com -mcpemaster.com -mcpmaid.com -mcqyy.com -mcsafebox.com -mcshiyan.com -mct01.com -mcu-home.com -mcu123.net -mcufan.com -mcujl.com -mculover.com -mcumonitor.com -mcusky.com -mcuzone.com -mcuzx.net -mcwshop.com -mcx666.com -mcyhfl.com -mcyo.pw -mcysw.net -mczyz.com -md1618.com -mdaxue.com -mdbchina.net -mdbig.com -mdbimg.com -mdckj.com -mdcui.com -mdddy.com -mdeasydiagnosis.com -mdeditor.com -mdeer.com -mdfull.com -mdinjn.com -mditie.com -mdjhxgjyc.com -mdjyadi.com -mdjyouth.com -mdmmm.com -mdnice.com -mdo52.com -mdouyin.com -mdpda.com -mdtr2pdf.com -mdtu.com -mduckstudio.com -mdvdns.com -mdvoo.com -mdy-edu.com -mdybk.com -me-city.com -me361.com -me4399.com -me97.com -meadin.com -meaninggame.com -meaquatietie.com -meazhi.com -meb.com -meban.cc -mec027.com -mechr.com -mechrevo.com -meckodo.com -mecoxlane.com -med-water.com -med126.com -med66.com -meda.cc -medai360.com -medeming.com -medfintech.com -media.licdn.com -mediaclub.cc -mediafq.com -mediatek.com -mediav.com -mediawords.org -mediaxinan.com -mediecogroup.com -medimg.org -meditic.com -meditrusthealth.com -mediumin.net -medky.net -medlinker.com -medlinker.net -medme.net -medmeeting.org -medsci-tech.com -meecai.com -meechao.com -meefon.com -meegoe.com -meegoq.com -meeket.com -meet99.com -meetfave.com -meethall.com -meetlawyer.com -meetsite.com -meetzoom.net -meeuapp.net -mefeng.net -megaemoji.com -megajoy.com -megalojs.org -megoal.org -megobike.com -megomap.com -megongshe.com -megou8.com -meguo.com -megvii.com -mei.com -mei1.info -mei521.com -meia.me -meianjuwang.com -meiaoju.com -meibai14.com -meibangzx.com -meibaninc.com -meibaolicarpet.com -meibg.com -meibo.tv -meican.com -meicanstatic.com -meichibao.com -meichuanmei.com -meichubang.com -meidaojia.com -meidebi.com -meideng.net -meidoumall.com -meierbei.com -meifajie.com -meifang8.com -meifazu.com -meifengyigou.com -meigeinc.com -meigmama.com -meigong8.com -meigongla.com -meigongyun.com -meiguanjia.net -meiguiwxw.com -meiguixs.com -meiguo-qianzheng.com -meiguoxiaoxue.com -meiguozhuji.com -meigushe.com -meih5.com -meih5.net -meihaotoutiao.com -meihaoxueyuan.com -meiheups.com -meihom.com -meihouyun.com -meihu99.com -meihua.info -meihuainfo.com -meihuappt.com -meihuboyue.com -meihudong.com -meihutong.com -meijia66.com -meijiacun.com -meijiaedu.com -meijiahuanxin.com -meijialove.com -meijiecao.net -meijiehang.com -meijiehezi.com -meijieu.com -meijiexia.com -meijingjie.com -meijingmall.com -meijiu.com -meiju.net -meiju111.com -meiju2018.com -meiju22.com -meijuba.com -meijucenter.com -meijufans.com -meijuniao.com -meijuniao.net -meijutt.com -meijutt.tv -meijuxia.com -meijuzhan.com -meijuzj.com -meijw.com -meikanguo.com -meike-shoes.com -meike15.com -meikeda.net -meiku123.com -meilanfangdajuyuan.org -meilele.com -meili-inc.com -meili1123.com -meilibaobao.com -meilides.com -meilijia.com -meiling.com -meiling360.com -meiliqueen.com -meilishuo.com -meilishuo.net -meilisite.com -meiliwan.com -meiliworks.com -meilunmeijia.com -meilvtong.com -meimeidu.com -meimeio.com -meimeixiazai.com -meimi.cc -meimingteng.com -meinv.com -meip0.me -meip4.me -meipai.com -meipian.me -meipian2.com -meipic.com -meipuapp.com -meiqia.com -meiqiantu.com -meiqiausercontent.com -meiqiu.me -meirenshang.com -meirenyu.vip -meiridazhe.com -meirids.com -meirijujiao.com -meirishangxin.com -meirishentie.com -meiritv.net -meiriyiwen.com -meiriyouxue.com -meirong.net -meirongshanghai.com -meisaitu.com -meisestatic.com -meisfuture.com -meishai.com -meishanren.com -meishe-app.com -meisheapp.com -meishesdk.com -meishi.cc -meishi13.com -meishichina.com -meishij.net -meishilife.com -meishiqin.com -meishiwangluo.com -meishow.com -meishubao.com -meishui.com -meishuquan.net -meisubq.com -meisupic.com -meitaixianlan.com -meitangdehulu.com -meitegou.com -meitianhui.com -meitibijia.com -meitironghe.org -meitiyun.org -meitu.com -meituan.com -meituan.net -meituan.xn--io0a7i -meituba.com -meitubase.com -meitudata.com -meitumobile.com -meitun.com -meituncdn.com -meitushop.com -meitussp.com -meitustat.com -meituyun.com -meituyunji.com -meiwai.net -meiweis.com -meiweishudan.com -meiwenfen.com -meiwenting.com -meiwentx.com -meixie.com -meixincdn.com -meixiong5.com -meixueyuan.com -meiyaapp.com -meiyan.com -meiyedana.com -meiyen.com -meiyi.ai -meiyinji.vip -meiyixia.com -meiyou.com -meiyue.com -meiyuktv.com -meiyuxiuxiu.com -meizhejie.com -meizhidi.com -meizhou.com -meizhou.net -meizitu.net -meizu.com -meizu.com.hk -meizu.net -meizudy.com -meizumi.com -mejoybaby.com -meke-shanghai.com -meke8.com -mekya.com -meldingcloud.com -melodyhome.com -melote.com -melove.net -memacx.com -memagames.com -memeyule.com -memorieslab.com -memorycarddeal.com -memoryhere.com -mems.me -memsconsulting.com -memseminar.com -memsensor.com -memuu.com -men.ci -menchuang.biz -meng2u.com -meng3.com -meng800.com -mengat.com -mengbaofun.com -mengchenghui.com -mengdian.com -mengdie.com -mengdiguo.com -mengdodo.com -menggang.com -menggetech.com -menghunli.com -mengjiagames.com -mengjianjiemeng.com -mengkang.net -menglan.com -menglangroup.com -menglegame.com -menglei.info -mengma.com -mengniang.tv -mengniu99.com -mengqiuju.com -mengshihm.com -mengso.com -mengtian.com -mengtu.cc -mengtuiapp.com -mengwuji.net -mengxi.com -mengxiangeka.com -mengyoo.com -mengyou.org -mengyuzhe.com -mengzhou.com -mengzhuangxiu.com -mengzhuboke.com -mengzone.com -menhood.wang -menjin.com -menksoft.com -menle.com -menpiao.com -menqiu.com -menvscode.com -menwee.com -menww.com -menwww.com -menxue.com -menyuannews.com -meowcat.org -meowpass.cc -mepai.me -mepcec.com -meplayplay.com -mequn.com -mercedes-benzarena.com -mergeek.com -merklechina.com -merry-box.com -merrytime.cc -mescroll.com -mesesoft.net -meshang.net -meshiot.com -mesince.com -mesresearch.com -mesu-cdn.apple.com.akadns.net -mesu-china.apple.com.akadns.net -mesu.apple.com -mesule.com -metacd.com -metajs.info -metal-min.com -metalchina.com -metao.com -meten.com -meteni.com -metenk12.com -metersbonwe.com -metersbonwe.net -metin520.com -metlifezeng.com -metnews.net -metroer.com -metrolife.mobi -metstr.com -metui.net -metvb.com -mewhoo.com -mexue.com -mexxum.com -meybuy.com -meyet.net -meyochina.com -mezw.com -mezzp.com -mf-y.com -mf100.org -mf8.biz -mf927.com -mf999.com -mfbgz.com -mfbuluo.com -mfcad.com -mfcad.net -mfcpx.com -mfcteda.com -mfexcel.com -mfisp.com -mfjmedia.com -mfk.com -mfkpp.com -mfpad.com -mfpjrj.com -mfqqx.com -mfqyw.com -mfsun.com -mftianshanam.com -mftvideo.com -mfxs888.com -mfyyw.com -mfzdb.com -mg-cdn.com -mg-pen.com -mg21.com -mg3721.com -mg6440.com -mg67.com -mgc-games.com -mgd5.com -mgenware.com -mgff.com -mgl9.com -mglip.com -mgmp3.net -mgogo.com -mgous.com -mgplay.com.tw -mgpyh.com -mgsdk.com -mgslb.com -mgtv.cloud -mgtv.com -mgtvzy2.com -mgw999.com -mgwxw.com -mgwyx.com -mgxzsy.com -mgyapp.com -mgyxw.net -mgyyw.com -mgzf.com -mgzgmyzz.com -mgzhibo.com -mgzxzs.com -mh1234.com -mh160.co -mh160.com -mh160.xyz -mh456.com -mh51.com -mh868.com -mhacn.com -mhaoche.com -mhaoma.com -mhbras.com -mhdns.com -mhealth100.com -mhecy.com -mhghl.com -mhhf.net -mhhospital.com -mhi-ac.com -mhimg.com -mhl.xyz -mhpdf.com -mhsf.com -mht.la -mhtclub.com -mhtml5.com -mhwmm.com -mhwy2.com -mhxk.com -mhxzhkl.com -mhyun.net -mhyv888.com -mhzd.cc -mhzd.net -mi-ae.net -mi-dun.com -mi-idc.com -mi-img.com -mi.com -mi1.cc -mia.com -mian4.net -mianbao.com -mianbaodianying.com -mianbaoduo.com -mianbaoimg.com -mianbaotou.com -miandanbx.com -mianfeidianhua.net -mianfeiic.com -mianfeiwendang.com -mianhuatang.cc -mianhuatang.la -mianjuapp.com -mianjue.com -mianjupark.com -mianshi365.com -mianshui365.com -miantiao.me -mianwai.com -miaobe.com -miaoche.com -miaodiyun.com -miaoerduo.com -miaofaxian.com -miaogao.net -miaogu.com -miaohealth.net -miaokaiyun.com -miaomiaojia.cc -miaomiaoxue.com -miaomiaoz.com -miaomiaozhe.com -miaomore.com -miaopai.com -miaopin8.com -miaoquantuan.com -miaoshou.com -miaoshou.net -miaoshoucdn.com -miaoshuwu.com -miaoshuzhai.com -miaostreet.com -miaotu2018.com -miaov.com -miaoweijianfei.com -miaowugo.com -miaowutech.com -miaoxiakuan.com -miaoxiala.com -miaoyu88.com -miaozao.com -miaozhen.com -miaozhun.com -miaxis.net -mibaoge.com -mibaostore.com -mibaoxian.com -mibimibi.com -mibokids.com -mibugs.com -mic-s.com -micai.com -micaitu.net -micaiying.com -micblo.com -michael-j.net -michaelapp.com -michelam.com -michong.com -michplay.com -micinv.com -miclle.com -mico.io -micro-bee.com -microad-cn.com -microad-z.com -microbell.com -microbt.com -microcai.org -microcardio.com -microdiag.com -microdreams.com -microfotos.com -microidc.com -microlensyh.com -microlz.com -micromouse.tech -microrui.net -microvcard.com -microvirt.com -microvoip.com -microyan.com -micstatic.com -micw.com -midaapi.com -midadata.com -midaijihua.com -midainc.com -midasbuy.com -midday.me -midea.com -midea.com.tr -midicn.com -midifan.com -midifan.org -midiyinyue.com -midlele.com -midofans.com -midonline.net -midsummer.cc -midukanshu.com -miduoke.net -midureader.com -midway.run -midwayjs.org -miecod.com -miejw.com -miensi.com -mier123.com -miercn.com -mierhuo.com -mieseng.com -miexue.com -mieyisi.com -mifangba.com -mifanli.com -mifanlicdn.com -mifei.com -mifen517.com -mifengcha.com -mifengv.com -mifengvv.com -mifengxiuchang.com -mifengzhibo.com -mifispark.com -migantech.com -migelab.com -migroom.com -migucloud.com -migudy.com -migufun.com -migutv.com -miguvideo.com -miguyu.com -mihayo.com -mihayou.com -mihoyo.com -mihtool.com -mihua.net -mihuashi.com -mihui365.com -mihuwa.com -miiblog.com -miicp.com -miidc.com -miidi.net -miidii.tech -miidol.com -miiee.com -miinaa.com -miit-icdc.org -miit.cc -miitip.org -mij.cc -miji8.com -mijiadns.com -mijiannet.com -mijiayoupin.com -mijishe.com -mijisou.com -mijwed.com -mika123.com -mika18.com -mikannovel.com -mikebao.cc -mikechen.cc -mikecrm.com -mikemiao111.com -mikewootc.com -mikoshu.me -miku.fm -miku.ink -mikuac.com -mikublog.com -mikucdn.com -mikuclub.fun -milan-bride.com -milanstand.com -milanvip.com -mileage.vip -milejia.com -miletu.com -milfuns.com -miliantech.com -miliao.com -milido.vip -milihua.com -milike.com -miliol.com -miliol.org -milipictures.com -miliyo.com -milkiy.com -milkjpg.com -milkplayer.com -milliway-ic.com -millll.net -millnovel.com -milnews.com -milo-star.com -miloktv.com -miloli.info -miloos.com -milu.com -milvzn.com -milzx.com -mima.club -mimaru.me -mimgame.com -mimi456.com -mimi518.com -mimidi.com -mimifr.com -mimiteng.com -mimixiaoke.com -mimo51.com -mimoe.cc -mimoprint.com -mimouse.net -mimtao.com -mimvp.com -min-xin.com -minapp.com -mincache.com -mincdn.com -mincoder.com -mind168.com -mindai.com -mindhave.com -mindmanager.cc -mindmanagerchina.com -mindmapper.cc -mindmeters.com -mindmm.com -mindopu.com -mindpin.com -mindray.com -mindstore.io -minecraftxz.com -mineplugin.org -miner.tools -minerbbs.com -minerfun.com -minerhome.com -minesage.com -minewtech.com -ming333.net -mingbaoxinwen.com -mingbianji.com -mingcalc.com -mingchaoonline.com -mingchaoyouxi.com -mingcloud.net -mingczh.com -mingda.net -mingdanwang.com -mingdao.com -mingdao.net -mingdao8.com -mingdaocloud.com -mingdiantou.com -mingdongman.com -mingdzs.com -mingf168.com -mingin.com -mingjian.com -mingjinglu.com -mingjiufu.com -minglian.com -mingliu8.com -mingliwenhua.com -mingluji.com -mingpian.biz -mingqiceping.com -mingqizhongyi.com -mingren888.com -mingrenteahouse.com -mingrenxiang.com -mingrenziliao.com -mingricctv.com -mingritouban.com -mingshiedu.com -mingsoft.net -mingtaokeji.com -mingtian.com -mingtrip.com -mingxiaodai.com -mingxing.com -mingxingku.com -mingxinglai.com -mingxiubgjj.com -mingyannet.com -mingyantong.com -mingyaohui.com -mingyi.com -mingyihui.net -mingyuanfund.com -mingyuanyun.com -mingyueqingfengshe.com -mingyuezw.com -mingzhuxiaoshuo.com -mingzihui.com -mingzw.net -minhang.cc -minhangshi.com -minhow.com -mini-audio.com -mini5cn-1.opera-mini.net -mini5cn.opera-mini.net -miniadx.com -miniaixue.com -miniblink.net -minidaxue.com -minidso.com -minigui.com -minigui.org -minihaowan.com -miniluck.com -miningconf.org -mininglamp.com -miniso.hk -minisoyo.com -ministudy.com -minitiao.com -minitos.com -miniui.com -miniwangdai.com -minixiazai.com -minniansoft.com -minor-tech.com -minqingguancha.com -minquan8.com -minra.com -minrank.com -minretail.com -minshengec.com -mintaibank.com -mintaylor.com -mintmuse.com -mints-id.com -minunix.com -minxindai.com -minxing365.com -minxue.net -minzu56.net -miot-spec.org -mipacc.com -mipang.com -mipangwang.com -mipay.com -mipcdn.com -mipengine.org -miplus.cloud -mipujia.com -miqiks.com -miquapp.com -miquw.com -mir2world.com -mir4399.com -miraclevision.net -mirari.cc -mirgaga.net -mirxat.com -misall.com -miscd.com -misclogic.com -mishangkeji.com -miskcoo.com -mispos.cc -missevan.com -missfresh.net -missku.com -missquq.com -misstar.com -missyou.run -missyuan.com -missyuan.net -misuland.com -misuvision.com -mitang.com -mitangbao.com -mite5.com -miteno.com -miteo.net -mitilove.com -mitiplus.com -mittrchina.com -miui.com -miutour.com -miutrip.com -miwifi.com -mix.moe -mixdo.net -mixgslb.com -mixian88.com -mixin.cc -mixiong.tv -mixrnb.com -mixvvideo.com -miy.cc -miyabaobei.com -miyabaobei.hk -miyaboke.com -miyakei.com -miyanlife.com -miyapay.com -miyomo.com -miyouu.com -miyuangz.com -miyupu.com -mizhe.com -mizhenhao.com -mizhimedia.com -mizholdings.com -mizhuanba.com -mizone.cc -mizuiren.com -mj85.com -mjasoft.com -mjceo.com -mjgzm.com -mjia.cc -mjjcn.com -mjjq.com -mjju.net -mjkqj.com -mjlong.com -mjmj8.net -mjmjm.com -mjmobi.com -mjoys.com -mjrui.com -mjtom.com -mjyun.com -mjyx.com -mjzj.com -mjzymh.com -mk-yiliao.com -mk2048.com -mkaliez.com -mkaq.org -mkb0898.com -mkbld.com -mkf.com -mkjump.com -mklimg.com -mknn.net -mkshell.com -mkswp.com -mkszxh.com -mktcreator.com -mktdatatech.com -mktzr.com -mkuai.net -mkvcn.com -mkwhat.com -mkzcdn.com -mkzhan.com -mkzoo.com -ml-cg.com -ml-kq.com -mlairport.com -mlbuy.com -mlcctv.com -mlgame.wang -mlgame.xin -mlgj.com -mlibaba.com -mlinks.cc -mlito.com -mlj130.com -mlj194.com -mlj36.com -mlj55.com -mljixie.com -mljr.com -mljtn.com -mljznj.com -mlkmba.com -mlkxs.com -mlkxshop.com -mllres.com -mlmcms.com -mlnk.me -mlnrz.com -mlnsoft.net -mlocso.com -mlog.club -mlogcn.com -mlook.mobi -mlrzsj.com -mlt01.com -mlwanwan.com -mlwed.com -mlwei.com -mlwu.net -mlxks.com -mlxsc.com -mlyfc.net -mlyfcyy.com -mlzcn.com -mm.cc -mm.com -mm.net -mm111.net -mm12581.com -mm131.kim -mm138.com -mm2hservices.com -mm2uu.com -mm4000.com -mm52.com -mm7920.com -mm8mm8.com -mm957.com -mmall.com -mmaqa.com -mmarket.com -mmb.to -mmbang.com -mmbang.info -mmbang.net -mmbao.com -mmbbx.com -mmbest.com -mmbjq.com -mmbread.com -mmc-data.com -mmcxu.com -mmdocx.com -mme.ink -mmfad.com -mmfang.cc -mmfi.net -mmfj.com -mmgal.com -mmgl.net -mmgogo.com -mmhktv.com -mmi-shanghai.com -mmia.com -mmicloud.com -mmim8.com -mmimm.com -mmkkgg.com -mmkkiivv.com -mmloo.com -mmm.io -mmmiao.com -mmmono.com -mmmtea.net -mmonly.cc -mmosite.com -mmscoo.com -mmsfw.com -mmsk.com -mmstat.com -mmtcw.com -mmtrix.com -mmtrixcnc.com -mmtrixcnet.com -mmtrixopt.com -mmuaa.com -mmwan.cc -mmww.com -mmxiaowu.com -mmy.moe -mmybt.com -mmycdn.com -mmyfilm.com -mmzh.com -mn-soft.com -mn21.com -mnancheng.com -mnbvtgv.com -mndsoft.com -mndvd.net -mnjj.group -mnkan.com -mnlscz.com -mnmnh.com -mnpz8.com -mnstory.net -mnwww.com -mnxz8.com -mo-yu.com -mo298.com -mo2g.com -mo9.com -moage.com -mob.com -mob55.com -mobaders.com -moban.com -mobanhao.com -mobanjing.com -mobanku.com -mobanlane.com -mobanma.com -mobanpai.com -mobantiankong.com -mobantianxia.com -mobantianxia.net -mobantu.com -mobanwang.com -mobartsgame.com -mobawan.com -mobayke.com -mobayx.com -mobcastlead.com -mobcent.com -mobdatas.com -mobee.tv -mobeehome.com -mobeiwenhua.com -mobgi.com -mobibal.com -mobibao.com -mobibrw.com -mobike.com -mobile-ease.com -mobileanjian.com -mobilebone.org -mobiledissector.com -mobilegamebase.com -mobilegamecdn.com -mobileppp.com -mobiletrain.org -mobileztgame.com -mobisense-hk.com -mobiw.com -mobjz.com -mobkeeper.com -mobking.biz -mobmvp.com -mobo168.com -moboage.com -moboplayer.com -moborobo.com -mobotap.com -moboway.com -mobring.co -mobrtb.com -mobstarry.com -mobtou.com -mobvoi.com -mocache.com -mocartoon.com -mocashanghai.org -mochain.info -mochashou.com -mockingbot.com -mockjs.com -mockplus.com -mockuai.com -mocn.cc -mocuz.com -modao.cc -modao.com -modao.io -modb.pro -modeng178.com -modengfei.com -modengyingxiang.com -modernsky.com -modian.com -modoer.com -modooplay.com -modulesocean.com -moduovr.com -moduseo.com -modusnb.com -modxz.com -moe.im -moe123.com -moe123.net -moe123.org -moe13.com -moe321.com -moe4sale.in -moebi.org -moeblog.vip -moeclub.org -moecoder.com -moeelf.com -moefactory.com -moefantasy.com -moefou.org -moehu.org -moehui.com -moeid.com -moejam.com -moejj.com -moejn.com -moejp.com -moeli-desu.com -moemiao.net -moeover.com -moeplay.com -moerlong.com -moesola.com -moetu.org -moetuji.com -moeu.net -moew.xyz -moeyue.com -moezu.com -moezx.cc -mofa.com -mofanbaby.com -mofang.com -mofang.jp -mofangge.com -mofangge.xin -mofanghr.com -mofangshe.com -mofangyu.com -mofavideo.com -mofazhu.com -mofile.com -mofishgames.com -mofoun.com -mofunenglish.com -mogoedit.com -mogohd.com -mogoroom.com -mogu.com -mogu.io -mogubill.com -mogucdn.com -moguf.com -mogujia.com -mogujie.com -mogujie.org -mogumiao.com -moguproxy.com -mogustore.com -mogutong.com -moguupd5.com -moguv.com -moguyun.com -moh.cc -moh7.com -moh8.com -mohe6.com -mohecm.com -moheqq.com -mohou.com -mohu.org -mohuanhua.com -moihu.com -moimg.net -moioi.com -moith.com -moji.com -moji001.com -moji002.com -mojicb.com -mojicdn.com -mojichina.com -mojidong.com -mojieai.com -mojifen.com -mojitest.com -mojuedu.com -mokahr.com -mokalady.com -mokaoba.com -mokayuedu.com -mokee.me -mokezhan.com -mokiee.com -moko.cc -moks.cc -mokuge.com -mokun.net -molbase.com -molbase.net -molegu.com -molei.net -molerose.com -molibaike.com -molie.com -molihe.cc -molinsoft.com -moliplayer.com -moliqiji.com -molixiangce.com -molizm.com -molloc.com -moltentec.com -momentcdn.net -momhui.com -momishi.com -momo9.me -momobako.com -momocdn.com -momomoxiaoxi.com -momooyo.com -momoshifu.com -momotn.com -momoyoyo.com -momzs.com -moneydai.com -moneydata.hk -moneygz.com -moneyslow.com -mongochina.com -monidai.com -monizl.com -monph.com -monseng.com -monsooncvs.com -monsterlin.com -montage-tech.com -monteamor.com -monternet.com -montnets.com -monv.com -monxin.com -moocollege.com -moodmoon.com -moodoon.com -moogos.com -moojnn.com -moomcherry.com -moomoo.com -moonbasa.com -moonbook.com -mooncell.wiki -moonfly.net -mooninbox.com -moonlian.com -moonsec.com -moonsun.cc -moontc.com -moonx.ai -moooc.cc -mooooc.com -moootooo.com -moore.live -moore.ren -moore8.com -moorecat.com -mooreelite.com -mooreiot.com -mooreren.com -moosee.net -moowo.com -mop-img.com -mop.com -mopaas.com -mopaasapp.com -mopairv.com -mopcn.com -mopei8.com -moper.me -mopiaoyao.com -mopicer.com -mopoint.com -mopsky.com -moqifei.com -moqikaka.com -moqilin.net -moqing.com -moqipobing.com -moqu8.com -moquu.com -moracoffee.cc -morechinese.cc -moreck.com -morefood.com -morefuntek.com -moreless.io -morequick.net -moresing.com -moretickets.com -moretime.vip -morevfx.com -morewis.com -morewiscloud.com -morigames.com -morketing.com -morncloud.com -morning.work -morningcore.com -morninghan.com -morningwhistle.com -morstar.net -mos86.com -mosea.net -moseacg.com -moseeker.com -mosesenglish.com -mosgcj.com -mosheng520.com -moshou.com -moshuanghua.com -moshuqiqiu.com -mosifel.com -mosoga.net -mossle.com -mostch.com -mostsd.com -motanku.com -motherchildren.com -motie.com -motieba.com -motieimg.com -motilive.com -motimaster.com -motionhubtuto.com -motisky.com -moto-one.com.hk -moto8.com -motong.wang -motou.com -motrix.app -mottoin.com -motuo2.com -motuowei.com -mouldbbs.com -mouldnews.com -moulem.com -moumi.com -mounriver.com -mounstar.com -mountor.net -mounui.com -mousycoder.com -mout.me -moutaichina.com -movcam.com -movcms.com -movesee.com -movesky.net -moviemeng.com -moviemore.com -movit-tech.com -movshow.com -mowan123.com -mowangblog.com -mowowo.com -mowuhe.com -moxdao.com -moxfive.xyz -moxiai.com -moxian.com -moxiaofei.com -moxing.net -moxingyun.com -moxiu.com -moxiu.net -moxiwh4.com -moyangmoyang.com -moyann.com -moye.me -moyimusic.com -moyoutang.com -moyoyo.com -moyuba.com -moyublog.com -moyugroup.com -moyumedia.com -moyuxiaoshuo.com -moz8.com -mozhan.com -mozheanquan.com -mozhedun.com -mozhenhau.com -mozhes.com -mozichina.com -mozigu.net -mozillaonline.com -mozillazg.com -mp4ba.cc -mp4ba.com -mp4ba.la -mp4cn.com -mp4dy.net -mp4ju.com -mpacc.net -mpaidata.com -mpanshi.com -mpdaogou.com -mpdsj.com -mpfmall.com -mphdx.com -mpiano.com -mplife.com -mplus.tech -mpopkart.com -mpos.ren -mpweixin.net -mpxiaomi.net -mpxiaoshuo.com -mpxx.net -mqant.com -mqcoffee.com -mqdek2.com -mqego.com -mqnzl.com -mquanquan.com -mqwds.cc -mqxww.com -mr-ping.com -mr77.com -mr91.com -mrabit.com -mrbanana.com -mrbluyee.com -mrcjcn.com -mrcjxw.com -mrcrm.com -mrcuriosity.org -mrcywang.com -mrdede.com -mrdios.com -mrentea.com -mrevisa.com -mrhallacg.com -mrhaoting.com -mrjiang.com -mrjjxw.com -mrkevin.net -mrm1336.com -mro9.com -mrpyq.com -mrqf.com -mrsbyjy.com -mrshuhua.net -mrsta.com -mrsu.me -mrtbc.com -mrw.so -mrwish.net -mrzhenggang.com -mrzhouxiaofei.com -mrzl.com -mrzs.net -ms024.com -ms115.com -ms211.com -ms315.com -ms6666111.com -msc1434.com -mscbsc.com -mschcdn.com -mscto.com -mscxw.com -msddp.com -msdelectron.com -msfpay.com -msgcarry.com -msgr.dlservice.microsoft.com -msgruser.dlservice.microsoft.com -msgtjj.com -mshamdy.com -mshandong.com -mshc2018.com -mshengb.com -mshishang.com -mshot.com -mshouyou.com -msits.com -msiyw.com -msjcqm.com -mskjf.com -mslzz.com -msmartlife.com -msmbjp.com -msooso.com -msotu.com -mspring.org -msrtvu.net -msstatic.com -mstarsemi.com -mstchina.com -mstvb.com -msunland.com -msvod.cc -msweekly.com -msxf.com -msxf.net -msxfmall.com -msxh.com -msxiaobing.com -msymjz.com -msyos.com -mszmapp.com -mszq.com -mszsx.com -mszxyh.com -mt-bbs.com -mt-wire.com -mt30.com -mt521.com -mtasia.net -mtavip.com -mtblj.com -mtchome.com -mtcnsoft.com -mtcop.com -mtcsys.com -mtcx99.com -mtdpgame.com -mtdx.net -mtedu.com -mtestin.com -mtgchina.com -mti100.com -mtiancity.com -mtianshitong.com -mtide.net -mtime.com -mtimeimg.com -mting.info -mtizt.com -mtk.com.tw -mtkan.net -mtkdy.com -mtketang.com -mtkg.cc -mtksj.com -mtktk.com -mtm.mo -mtmos.com -mtmss.com -mtmssdn.com -mtmssdn0.com -mtnets.com -mtnets.net -mtoilet.com -mtoou.info -mtr8.com -mtrendgroup.com -mtty.com -mtu46.com -mtunique.com -mtv123.com -mtw.so -mtwine.com -mtwl.net -mtxgx.com -mtxsnow.net -mtyee.com -mtyun.com -mtzc100.com -mtzcjy.com -mtzmyjf.com -mtzqty.com -mtzuichen.com -mtzxgf.com -mu8.cc -mubie.net -mubu.com -mubu.io -mucai-china.com -mucaipin.com -mucf.cc -mucfc.com -muchangqing.com -muchlab.com -muchong.com -muchrank.com -mudiao360.com -mudongguang.com -mudoudou.net -mudu.tv -mufengyue.com -muftc.com -mugeda.com -mugisama.com -muguaddy.com -muhai.net -muhoujiemi.com -muimg.com -mujj.us -mukewang.com -mukool.com -mulans.com -mulinf99.com -mulubang.com -mum.cc -mumayi.com -mumu01.com -mumumoo.com -munfan.com -muniao.com -murdermysterypa.com -murl.tv -muryi.net -muse-ui.org -muse100.com -mushafa.net -mushapi.com -mushroomchina.com -music.apple.com -music163.com -music4x.com -musicbody.net -musicchina-expo.com -musicdu.com -musiceol.com -musicsailor.com -musicsky.org -musicuu.com -musikid.com -musiness.vip -muslimwww.com -mustups.net -musyder.com -mutualhunter.com -mutuoluo.com -muwai.com -mux5.com -muxin.fun -muxiulin.com -muxufang.com -muyangkuaibao.com -muyee.com -muyewx.com -muyii.com -muying.com -muyingjie.com -muyingzhijia.com -muyishu.com -muyuanfoods.com -muyuge.com -muzhi.us -muzhibus.com -muzhigame.com -muzhiwan.com -muzi999.com -muzili.xyz -muzisoft.com -mvacc.com -mvben.com -mvgod.com -mvhere.com -mvmpg.com -mvnjar.com -mvoicer.com -mvote.net -mvpdj.com -mvyxws.com -mw1950.com -mwadx.com -mwcloudcdn.com -mwcloudcdn.info -mwcname.com -mweda.com -mwjournalchina.com -mwjx.com -mwrf.net -mwrfchina.org -mwrftech.com -mwyzhcdn.com -mx175.com -mx3g.com -mxarts.com -mxbnbc.id -mxchip.com -mxddp.com -mxde.com -mxguan.com -mxhaitao.com -mxhichina.com -mxiaoer.com -mxingkong.net -mxipp.tech -mxjinchao.com -mxjtedu.com -mxjyxx.com -mxk.cc -mxlvniao.com -mxnavi.com -mxnfq.com -mxnxs.com -mxpkw.com -mxqe.com -mxria.com -mxruv.com -mxs.com -mxslly.com -mxsyzen.com -mxtcn.com -mxtrip.net -mxtrk.com -mxtronics.com -mxw3.com -mxzsjt.com -mxzw.com -mxzx123.net -mxzzzs.com -my-3dcad.com -my-host.cc -my-summit.com -my.st.com -my0511.com -my0513.com -my0538.com -my0551.com -my0792.com -my0832.com -my089.com -my120.org -my1616.net -my285.com -my2852.com -my2space.com -my2w.com -my399.com -my3w.com -my419.com -my4399.com -my51a.com -my5m.com -my5v.com -my607.com -my68.com -my7475.com -my7v.com -my88316666.com -my9166.com -my9527.com -my97.net -myagric.com -myaijarvis.com -myalert.info -myalicdn.com -myanjian.com -myanmarembassy.com -myantu.com -myapks.com -myapotek.com -myapp.com -myappsky.com -myarowanas.com -myauth.us -mybank.cc -mybdqn.com -mybjx.net -mybosc.com -myboyan.com -mybwallet.com -mybxg.com -mycaigou.com -mycaijing.com -mycaixun.com -mycar168.com -mycaraok.com -mycardgame.net -mycat.io -mychebao.com -mychemy.com -mychery.com -mychinaevent.com -mychunyan.net -mycleanmymac.com -myclub2.com -mycnc.org -mycodes.net -mycollect.net -mycolorway.com -mycoov.com -mycos.cc -mycos.com -mycos.net -mycos.org -mycoser.com -mycospxk.com -mycoss.com -mycoss.net -mycoss.org -mycraft.cc -mycrtb.com -mydadao.com -mydao.net -mydbfx.com -mydcyj.com -mydebook.com -mydf.net -mydical.com -mydict.org -mydigi.net -mydigit.net -mydiyclub.com -mydll.org -mydnns.com -mydns8.com -mydnser.com -mydnspod.net -mydnsw.com -mydoc.io -mydockfinder.com -mydown.com -mydown168.com -mydreamplus.com -mydrivers.com -myeclipsecn.com -myekp.net -myezdns.com -myf6.com -myfans.cc -myfcomic.com -myfirstwon.com -myfreax.com -myfrfr.com -myfun.com -myfun7.com -myfund.com -myfx0816.com -mygame66.com -mygame82.com -mygame88.com -mygjp.com -mygobatv.com -mygolbs.com -myguancha.com -mygx.net -mygzb.com -myhack58.com -myhaowai.com -myhard.com -myhayo.com -myhexin.com -myhldz.com -myhongzuan.com -myhostadmin.net -myhuahuo.com -myhuaweicloud.com -myhuilv.com -myhuoxingtan.com -myhwclouds.com -myicloud.vip -myie.me -myie9.com -myiplay.com -myir-tech.com -myirtech.com -myitit.com -myjhxl.com -myjianzhu.com -myjishu.com -myjob.com -myjob500.com -myjoit.com -myjoy777.com -myk3.com -mykqyy.com -mylbabao.com -mylegist.com -mylesenglish.com -mylguoji.com -mylhospital.com -mylhz.com -mylibs.org -mylike.cc -mylike.com -mylikechat.com -mylikesz.com -mylikeyk.com -mylink.ink -mylitboy.com -mylotushealth.com -mylove19.com -mylovehome.com -mym001.com -mymaitian.com -mymanhua.com -mymetal.net -mymhotel.com -myminapp.com -mymofun.com -mymoive.com -mymova.com -mynam3.xyz -mynb8.com -mynee.com -myodatech.com -myoldtime.com -myonlystar.com -myoppo.com -myoschain.com -myottad.com -myouth.net -myp2pcam.com -myp2pch.net -mypcera.com -mypcrun.com -mypethome.com -mypian.com -mypiao.com -mypitaya.com -mypity.com -mypm.net -myprad.com -mypscloud.com -mypsy365.com -myptpt.com -myqcloud.com -myqcloud.net -myqee.com -myqiantu.com -myqqjd.com -myqzd.com -myra2.com -myrb.net -myreadme.com -myrice.com -myriptide.com -myrtb.net -myrunners.com -myruru.com -mysanco.com -myscore.org -mysemlife.com -myshow800.com -myshown.com -myshu.org -myshxz.com -mysinablog.com -mysinamail.com -mysipo.com -mysixue.com -mysmth.net -mysodao.com -mysongktv.com -mysore-yoga.com -myspain.org -mysqlab.net -mysqlops.com -mysqlpub.com -myssl.com -mysteel.com -mysteel.net -mysteelcdn.com -mysteelcms.com -mystudyerte.com -mysubmail.com -mysupa.com -mysuperdns.com -mysvw.com -myt126.com -mytanwan.com -mythbird.com -mythcall.com -mythcare.com -mythidea.com -mythroad.net -mythsman.com -mythware.com -mythware.net -mytijian.com -mytju.com -mytogo.com -mytokenpocket.vip -mytrix.me -mytv365.com -mytvgame.com -myuall.com -myubbs.com -myuclass.com -myun.tv -myunderseaworld.com -myunke.com -myunying.com -myushan.com -myvoyo.com -mywakao.com -mywang.net -mywayboo.net -myweimai.com -mywll.com -mywood.cc -myxns.org -myyishu.com -myyoudao.com -myywk.com -myyx618.com -myyx915.com -myyzd.com -myzaker.com -myzebravip.com -myzhidao.com -myzhongjin.com -myznh.com -myzte.com -mz-oneacg.com -mz-sys.com -mz-sys.vip -mz5k.vip -mz6.net -mzbei.com -mzeat.com -mzeyes.com -mzfile.com -mzfxw.com -mzgtuan.com -mzh.ren -mzhb.com -mzhfm.com -mzhu8.com -mzhujia.com -mzi8.com -mzitu.com -mzjmedia.com -mzmjapp.com -mzone.site -mzread.com -mzres.com -mzsky.cc -mzsmn.com -mztgame.com -mztzzx.com -mzuan.com -mzwu.com -mzwxzz.com -mzxwz.com -mzy5200.com -mzyfz.com -mzyun.ren -mzzjw.com -mzzjyjy.com -n-bros.net -n-mobile.com -n0808.com -n12345.com -n127.com -n21.cc -n2v.net -n3jh4.com -n3sd.com -n423.com -n459.com -n6zw.com -n77777777.com -n802.com -n8v9yw.vip -n9cn.net -n9z.net -naadou.com -nadianshi.com -naew.org -nafanlong.com -nagain.com -nagcloudcs.com -nahan.org -nahehuo.com -nahuayuan.com -nahuo.com -nahuo9.com -nahuotai.com -nai.la -nai8.me -naibabiji.com -naicha99.com -naichabiao.com -naichagang.com -naigirl.com -naiguo360.com -naikanxs.com -naimei.com -nainiuapp.com -naiping.net -naitang.com -naiveblue.com -naiyou.cc -najiaoluo.com -nakedhub.com -nakedsail.com -nakevip.com -nalanxi.com -nalichi.com -name1688.com -name2012.com -name5566.com -namedq.com -nameidi.com -namepre.com -namesilopro.com -namibox.com -namipan.com -namitiyu.com -namoc.org -nanadao.com -nanapro.org -nanbeiyou.com -nanbushenghuo.com -nancai.net -nanchao.win -nanchengru.com -nancyface.com -nancyruspoli.com -nandagang.cc -nandasoft.com -nandu.com -nanerjia.com -nanerlee.me -nanfu.com -nanguache.com -nangualin.com -nanhaitoday.com -nanhe111.com -nanhua.net -nanhufund.com -nanhuhr.com -nanhutravel.com -nanhuwang.com -nani.online -naniannatu.com -nanjiaosuo.com -nanjing365.net -nanjingchenxi.com -nanjinghuojia.net -nanjingkaishan.com -nanjingtianqi114.com -nanjingui.com -nanjishidu.me -nanjixiong.com -nankaimba.org -nanlebbs.com -nanlive.com -nanmo1.com -nanningjie.com -nanoer.net -nanopi.org -nanputuo.com -nanqi.org -nanrenbang.in -nanrenge.net -nanrentu.cc -nanrenwa.com -nanrenwo.net -nanshan.biz -nanshanski.com -nanshifaxing.com -nantaihu.com -nantongbike.com -nantonghua.net -nanxueqx.com -nanxunjob.com -nanyangcable.com -nanyuetong.com -nanzhao1.com -nanzixun.com -naobiao.com -naoda.net -naoffer.com -naolifanghealth.com -naonaola.com -naozhong.net -napiantian.com -naquan.com -naracn.com -narkii.com -narrowad.com -naruto4u.com -narutom.com -nas2x.com -nasgetinfo.com -nashangban.com -nashwork.com -nasimobi.com -nasiosoft.com -naslike.com -nasyun.com -nat123.com -natappfree.cc -natbbs.com -natertech.com -nationalchip.com -nationsky.com -nationstech.com -nativeadscn.com -naturali.io -naturallyariana.com -nature-museum.net -naturesvariety-china.com -natywish.com -nauac.com -nav80.com -navchina.com -navimentum.com -navinfo.com -naxcx.com -naxiang.vip -naxide.com -nayao.com -nayatec.com -nayei.com -nayishuo.com -nb-medicalsystem.com -nb-pyjx.com -nb-xn.com -nb301.xyz -nb591.com -nb888888.com -nba008.com -nba20.com -nbabm.com -nbahero.com -nbahi.com -nbayaobasketballclub.com -nbayaoschool.com -nbazww.com -nbb6666.com -nbbeer.com -nbbiao.com -nbc.hk -nbcsgo.com -nbcyl.com -nbdeli.com -nbdeli.net -nbdisco.com -nbdskj.com -nbegame.com -nbegame.net -nbfce.com -nbfox.com -nbgdjt.com -nbhao.org -nbhkdz.com -nbhky.com -nbimer.com -nbimg.com -nbjhawl.com -nbjlw.com -nbjnw.com -nbjzjn.com -nbjzwx.com -nbkc-rp.com -nbmai.com -nbmao.com -nbmedicalsystem.com -nbow.net -nbpolytheatre.com -nbprido.com -nbsason.com -nbshuoxue.com -nbsqbank.com -nbt.ren -nbtarena.com -nbtvs.com -nbudp.com -nbunicom.com -nbwb.net -nbweekly.com -nbyang.com -nbyeda.com -nbyhyy.com -ncacg.org -ncahlx.cc -ncaqys.com -ncartfoundation.org -ncdxbbs.com -ncfcsa.org -ncfcw.net -ncfgroup.com -ncfstatic.com -ncfwx.com -ncfz.com -nchjz.com -nchq.cc -nciku.com -nciyuan.com -ncjld.com -ncmem.com -ncnynl.com -ncpa-classic.com -ncpqh.com -ncpssd.org -ncq8.com -ncrica.org -ncseopx.com -ncsljc.com -ncu.me -ncu.space -ncvtinfo.com -ncvtmi.com -ncwsxd.com -ncwyxh.com -ncxb.com -ncyinghuochong.net -ncyunqi.com -nczfj.com -nd090.com -nd15.com -nd56.com -nd5f.com -nd68.com -nddaily.com -nddnrm.com -ndfeb1688.com -ndhys.com -ndidu.com -ndmh.com -ndoo.net -ndscsoft.com -ndser.net -ndtinfo.net -ndtsg.com -nduoa.com -nduotuan.com -ne21.com -neaechina.com -nearcharge.com -nearsnet.com -nease.net -neat-reader.com -neavo.me -nebulogy.com -necboa.com -nedaex.com -nedigitals.com -needexam.com -needma.com -needyouknow.com -neegle.net -neeq.cc -neets.cc -neeu.com -negroupedu.org -neigou.com -neihan8.com -neihan8s.com -neihanshequ.com -neihantu.cc -neihanx.com -neikuw.com -neimengguyongli.com -neitui.com -neitui.me -neituixiaowangzi.com -nelkshuhe.com -nellit.net -nemosdo.com -nengapp.com -nenggeimall.com -nengshida.com -nengyongma.com -nengzuo.com -nenup.com -neo.org -neoap.com -neoease.com -neoease.org -neofans.org -neofussvr.sslcs.cdngc.net -neojos.com -neokylinschool.com -neolee.com -neoremind.com -nepconchina.com -nepian.com -neptcn.com -ner98.com -nercel.com -nerocn.com -nesbbs.com -nestlechinese.com -net-add.com -net-swift.com -net0516.com -net111.info -net114.com -net130.com -net199.com -net2345.net -net263.com -net767.com -net9.org -neta.so -netac.com -netat.net -netbarcn.net -netbian.com -netbian.net -netcan666.com -netcnnet.net -netcoc.com -netcolor.com -netconst.com -netcoretec.com -netded.com -netdzb.com -netease.com -netease.im -netech-expo.com -netentsec.com -netesee.com -netgamecar.com -netiler.com -netinfi.com -netinfi.net -netinfo-security.org -netitest.com -netkao.com -netnoease.com -netoak.com -netok.cc -netpi.me -netposa.com -netqd.com -netqin.com -netqon.com -netrunrun.com -netskao.com -netsmell.com -netsoz.com -netspreading.com -netstatic.net -netsun.com -nettsz.com -nettvl.com -nettvl.net -networkbench.com -networkbrand.com -netzonesoft.com -neu-reality.com -neucrack.com -neuedu.com -neuhm.com -neunn.com -neusncp.com -neusoft.com -neutrontek.com -neuwill.com -neuzs.com -nev-battery.org -new-mobi.com -new-more.com -new-thread.com -new131.com -new1cloud.com -newacademic.net -newadblock.com -newadx.com -newaircloud.com -newapi.com -newasp.net -newayz.com -newbandeng.com -newbd.com -newbe.pro -newbeebook.com -newbiefly.com -newbmiao.com -newbolunesport.com -newcapec.net -newcger.com -newchainbase.com -newchannel.org -newchieve.com -newchinalife.com -newclasses.org -newclouddenfender.com -newcosemi.com -newdao.net -newday.me -newdefend.com -newdon.net -newdruginfo.com -newdu.com -newdun.com -newdun.net -newdur.com -newer2001.com -newfavor.net -newgamer.com -newhopeagri.com -newhopegroup.com -newhtml.net -newhua.com -newifi.com -newistock.com -newjson.com -newlandaidc.com -newlifex.com -newmaker.com -newman.mobi -newmargin.com -newnanbao.com -newnewle.com -newoasis.cc -newoer.com -newoo.com -neworiental.org -nework360.com -neworld.org -neworldedu.org -neworldjp.com -newperiod.net -news18a.com -news606.com -newsbz.net -newsccn.com -newscctv.net -newsdao.com -newseasoft.com -newsgd.com -newsgu.com -newshiyu.com -newsing.com -newskj.com -newskj.org -newsmth.com -newsmth.net -newsmy-car.com -newsmy.com -newsmyshop.com -newsn.net -newspluse.com -newssc.net -newssc.org -newstarpress.com -newstartsoft.com -newstjk.com -newsv5.com -newsxc.com -newsyc.com -newsyule.com -newtalentaward.com -newtonghua.com -newtop100.com -newtouch-elec.com -newtrekwang.me -newtrip.com -newume.com -newvfx.com -newxing.com -newxitong.com -newxue.com -newyx.net -newzgc.com -newzhizao.com -newzkoo.com -nexiao.com -nexmoe.com -next-union.com -nextday.im -nextjoy.com -nexto2o.com -nextpcb.com -nextrt.com -nextsee.com -nexttao.com -nextyu.com -nexus.dell.com -nfa5.com -nfcic.com -nfcjw.com -nfcmag.com -nffair.com -nffund.com -nffuzhu.com -nfhcys.com -nfjt.net -nflchina.com -nfltag.com -nfmedia.com -nfmrtfv.com -nfpeople.com -nfs-china.com -nfs-wuxi.com -nfschina.com -nftx8.com -nfwin.com -nfyk.com -nfzhouyi.com -nfzmbrand.com -ng-alain.com -ngabbs.com -ngacn.cc -ngacn.com -ngarihealth.com -ngbbs.com -ngcgears.com -ngctransmission.com -ngfans.net -ngh6.com -nginstar.net -ngjjtg.com -ngloom.me -ngnice.com -ngocn.net -ngoos.org -ngrok.wang -ngui.cc -nhaidu.net -nhbestmould.com -nhbhpx.club -nhdmd.com -nhganggeban.com -nhnexpo.com -nhnsc.com -nhnst.com -nhpz5.com -nhstu.com -nhxz.com -nhygkj.com -nhzedu.com -nhzj.com -nhzs.com -nhzy.org -ni8.com -nian.so -nianbin.com -niancode.com -nianhuiba.com -nianw.com -nianzhi.cc -niaobaike.com -niaobee.com -niaobulashi.com -niaocms.com -niaogebiji.com -niaola.com -niaowifi.com -niaoyun.com -niba.com -nibaguai.com -nibaku.com -nibiye.com -nic.ren -nic.wang -nicaifu.com -nice-app.com -nice1688.com -nicebing.com -niceboybao.com -nicecdn.com -nicefilm.com -niceimg.net -niceisp.com -nicekid.com -nicelabel.cc -nicelinks.site -niceloo.com -niceonegame.com -nicescale.com -nicetuan.net -nicksors.cc -nicky1605.com -nicolaszhao.com -niconiconi.cc -nicvision.com -nideu.com -nidianwobang.com -nidong.com -nie.io -nielsenccdata.tv -nies.org -niexiaotao.com -nieyou.com -nifengla.com -nifengsoft.com -nifengz.com -nightwishcn.com -nihao.net -nihaotw.com -nihaowang.com -nihaowua.com -nihontu-cn.com -nihuwo.net -niiwoo.com -nikanpian.com -nikefree-run.net -nikest.com -nikever.com -nikkiup2u2.com -niko-kp.com -nilai.com -nilegu.com -niliu.me -nima.wang -ninebot.com -ninecoign.com -ninepart.com -nineroad.com -ninesix.cc -ninestargroup.com -ningbo-airport.com -ningbocarnival.com -ningbocat.com -ningbofy.com -ningbotm.net -ningboys.com -ningdo.com -ninghao.net -ninghechuan.com -ningidc.com -ningkangyuan.com -ningkekeji.com -ningli.win -ningmengdou.com -ningmengyun.com -ningmoe.com -ningoo.net -ningto.com -nington.com -ningxingxing.com -ningxinm1.com -ninjacn.com -ninjadq.com -ninjamustdie.com -ninze.com -nio.com -nipei.com -nipic.com -nirgame.com -nisang.pw -nishuoa.com -nisure.net -nitaitag.com -nitianxieshen.com -nitutu.com -niu-ba.com -niu.com -niu8pz.com -niua.com -niuacc.com -niuap.com -niubafa.com -niubb.com -niubb.net -niubi114.com -niubilai.com -niubilety.com -niubixia.com -niubo.cc -niuboli.com -niubseo.net -niucache.com -niucdn.com -niuche.com -niucodata.com -niudai120.com -niudingfeng.com -niug8.com -niugame.net -niugp.com -niuguwang.com -niuhudong.com -niujinniu.com -niukk.com -niuliangyun.com -niumai.cc -niuniufund.com -niuniutui.com -niuniuwan.com -niupinhui.com -niupu.com -niuqia.com -niurenqushi.com -niurou6.com -niuschools.com -niushe.com -niutoushe.com -niutrip.com -niutuku.com -niuwap2p.com -niuwk.com -niuxgame77.com -niuxiao.net -niuxiaoq.com -niuxyun.com -niuxz.com -niuyou5.com -niuyuan.com -niuza.com -niuzhu.com -niuzhuan-test.com -nivtc.com -niwodai.com -niwodai.net -niwoning.com -niwota.com -niwoxuexi.com -nixiba.com -nixonli.com -nixwang.com -nizhan888.com -nizhanw.com -nizkeyboard.com -nizuixing.com -nj-bl.com -nj-fst.com -nj-marathon.org -njbaisou.com -njbys.com -njc100.com -njcdata.com -njcedu.com -njcgs.com -njcitygas.com -njcn888.com -njctkj.com -njcto.com -njcw.com -njd1.com -njdapaidang.com -njdewo.com -njdfwb.com -njfeiming.com -njfenghao.com -njgb.com -njgep.com -njgjj.com -njgxq.org -njhaiwai.com -njhengyou.com -njhgame.com -njhwsk.com -njhzmxx.com -njibhu.com -njjsyy.com -njjuntong.com -njkefayuan.com -njl114.com -njliaohua.com -njlike.com -njlzhou.com -njlzsx.net -njmama.com -njmuseum.com -njqxrc.com -njrc365.com -njruifukang.com -njrx.cc -njrylab.com -njsd-china.org -njshengyuanli.com -njsjz.com -njskps.com -njsxbw.com -njtuspark.com -njuaplusplus.com -njuftp.org -njw88.com -njweijin.com -njwfgs.com -njwww.net -njxsmaofa.com -njxsmfyh.com -njxsmz.com -njxzwh.com -njyayishipin.net -njycwy.com -njyingtaoya.com -njyongji.com -njywsd.com -njzc025.com -njzglxs.com -njzhzx.net -njzrxx.xyz -njzztyl.com -nk84.com -nkqingnianshuo.com -nkscdn.com -nktaba.com -nkw100.com -nkyp.com -nlark.com -nlinkline.com -nljb.net -nlnln.com -nlpir.org -nlpjob.com -nlscan.com -nlv2.com -nlxn.com -nly6.com -nlypx.com -nlzpy.com -nm8yx.com -nmbgjx.com -nmet168.com -nmgd.com -nmgdjkj.com -nmgdw.com -nmgfnzs.com -nmgfood.net -nmgfrank.com -nmggyy.com -nmgjzjn.com -nmgkjzx.com -nmglawyer.com -nmgmjml.com -nmgxwhz.com -nmgycyl.com -nmhfw.com -nmhrjy.com -nmimi.com -nmkjxy.com -nmmwz.com -nmszjy.com -nmtui.com -nmtyxy.com -nmvps.com -nmweidian.com -nmysyey.com -nmyygs.com -nmzh.net -nmzol.com -nn.ci -nn.com -nn92.com -nncc626.com -nncgs.com -nnchangyi.com -nncj.com -nndims.com -nnduyi.com -nnera.com -nnfzsx.com -nngdjt.com -nngjjx.com -nnhaocheng.com -nnit30.com -nnjioko.com -nnjt.com -nnlib.com -nnmama.com -nnmutong.com -nnn666.com -nnnews.net -nnpma.com -nnsc6.com -nnsky.com -nnszwl.com -nntlj.com -nntskq.com -nnudream.com -nnwb.com -nnweding.com -nnylf168.com -nnynrc.com -nnzsxblaw.com -noah-dream.com -noahedu.com -noahsnail.com -noahteck.com -nobanus.com -nocang.com -nocare.com -noclyt.com -nocode-tech.com -nocode.com -noddl.me -node.cyou -nodeasy.com -nodeclass.com -nodeedge.com -nodeing.com -nodejs999.com -nodekey.com -nodepacific.com -nodetoo.com -nohken-sdy.com -nohup.cc -noire.cc -nok2.com -nokia-sbell.com -nokia.la -nokia88.com -nolanchou.com -nomax.vip -nome.com -nonganxian.com -nongcun5.com -nongfuspring.com -nongji1688.com -nongji360.com -nongjia888.com -nongjitong.com -nongjx.com -nongli.com -nongli.net -nongli114.com -nonglirili.net -nongmintv.com -nongminys.com -nongnet.com -nongplay.com -nongquan.net -nongshang.com -nongxinyin.com -nongyaodai.com -nongyehu.com -nongzisc.com -nonobank.com -nonozone.net -noobcoder.club -noobyy.com -noodba.com -noogel.xyz -noohest.com -noontec.com -noops.me -nooshen.com -nopis.org -noposion.com -noq.cc -nordicways.com -nordritools.com -norinco.com -norincogroup-ebuy.com -normcore.com -normstar.net -northdm.com -northdy.com -northgun.com -northidc.net -northtimes.com -nosec.org -nosuchfield.com -not3.com -notadd.com -note52.com -notedeep.com -noteniu.com -notetech.org -nothing.la -notrisk.com -novaicare.com -novalide.com -novapps.com -novastargame.net -novel-supertv.com -novemideas.com -novotimes.com -novtium.com -now-cn.net -now-do.com -nowapi.com -nowbeta.com -nowchip.com -nowcoder.com -nowcoder.net -nowdigi.com -nowec.com -nowo.com -nowodds.com -nowre.com -nows.fun -nowscore.com -nowshipin.com -nowxz.com -nowyingshi.com -noxgroup.com -noxue.com -noxxxx.com -noyes88.com -npbdp.com -npcgo.com -npcka.com -nphoto.net -nplusgroup.com -nplusgroup.net -npodevelopment.org -npp.cc -npxsw.com -npyun.com -npz.com -nq.com -nq6.com -nr-esc.com -nrec.com -nren8.com -nrigold.com -nrsfh.com -nruan.com -nrz.cc -ns-atmosphere.com -ns1.hk -ns168.net -ns365.net -ns5n.com -ns8d.com -ns96.com -nsb008.com -nsb126.com -nsb757.com -nsbeta.info -nsbsun3388.com -nscloudwaf.com -nscscc.org -nseac.com -nsecsoft.com -nseer.com -nsfaxing.com -nsfocus.com -nsfocus.net -nsforce.net -nshen.net -nshzpks.com -nsini.com -nsisfans.com -nsnodes.com -nsns8.com -nsoad.com -nsoft.vip -nsrcx.com -nsrfww.com -nsrjlb.com -nss.im -nssd.org -nsshare.com -nsstream.com -nstom.net -nsw88.com -nsw99.com -nsydt.com -nszmz.com -nt.cc -ntalker.com -ntaow.com -ntce.com -ntcfy.com -ntdvf.com -ntechw.com -ntefyxq.com -ntejiazheng.com -ntes53.com -ntfsformac.cc -nthfw.com -ntjalh.com -ntjdsm.com -ntjoy.com -ntjrchina.com -ntjymall.com -ntneuro.org -ntp.felixc.at -ntpcb.com -ntqcct.com -ntrcb.com -ntrdjsjl.com -ntrqq.com -ntryjd.net -nttui.com -ntuiw.cc -ntuiw.com -ntwikis.com -ntwzy.com -ntxccb.com -ntzhoas.com -nu1l.com -nuan.io -nuandao.com -nuandaoimg.com -nuanjiayuan.com -nuanmaoer.com -nuanshi100.com -nuanyuehanxing.com -nubb.com -nubee.cc -nubeeda.com -nubia.cc -nubia.com -nucc.com -nucleisys.com -nuecidc.com -nuedcchina.com -nufans.net -nuicdc.org -nujian.net -nujuya.com -nullice.com -nullno.com -num1dns.com -nunu8.com -nuobeiliao.com -nuodasoft.com -nuodefund.com -nuoder.com -nuoji.com -nuojiugo.com -nuokui.com -nuomi.com -nuomi9.com -nuomicikoi.com -nuonuo.com -nuoweb.com -nuozhan.com -nuozhensh.com -nuqk.com -nutjs.com -nutriease.com -nutsbp.com -nutspace.com -nutz.io -nutzam.com -nuubao.com -nuuha.com -nuuxie.com -nuvoltatech.com -nuvoton-m0.com -nuvoton-mcu.com -nuxue.com -nv2118.com -nvcam.net -nvcong.com -nvdiao.com -nvidia-china.com -nvliren.com -nvloo.com -nvren.com -nvren55.com -nvsay.com -nvsheng.com -nvshengjie.com -nvshuyun.com -nvtnet.com -nvude3.com -nvwojk.com -nvwu.com -nvzhanshen.com -nvzhubo.cc -nvziwu.com -nw-host.com -nw175.com -nwbbs.com -nwct.me -nwenxue.com -nwpu.net -nwtongcheng.com -nwxs2.com -nwxs4.com -nx.cm -nx5.com -nxadmin.com -nxboluo.com -nxcells.com -nxdns.net -nxecaiji.com -nxengine.com -nxez.com -nxflcp.com -nxflv.com -nxggzyjy.org -nxgjbyy.com -nxgqt.org -nxgtjt.com -nxhjf.com -nxhscxkj.com -nxin.com -nxit.us -nxly766.com -nxnet.net -nxnews.net -nxnresearch.com -nxol.net -nxpic.org -nxrrvmy.com -nxsks.com -nxtianshangb.com -nxty88.com -nxwly.com -nxyoute.com -nxyqs.com -nxyuanjing.com -ny-yy.com -ny6.biz -ny83.com -ny913.com -nyaa.io -nyaacat.com -nyasama.com -nyato.com -nybai.com -nybaidu.net -nychinaren.com -nyckidsclub.com -nync.com -nypd520.com -nyrsksw.com -nysmfc.com -nyzydz.com -nz86.com -nzbdw.com -nzchina.com -nzcxh.com -nzh.me -nzjsw.com -nzsiteres.com -nzw-china.com -nzwgs.com -o--o.win -o-netcom.com -o-sky.com -o136.com -o2123.com -o2ee.com -o2mania.com -o2moment.com -o2o1111.com -o2o4.com -o2obill.com -o2oexpo.com -o2osd.com -o2ting.com -o2yhq.com -o37o.net -o3brown.com -o3ndix.com -o6222.com -o7h.net -oa025.com -oa0351.com -oa169.com -oa25.org -oa8000.com -oabg.net -oabus.net -oachn.net -oacn.org -oadun.com -oadz.com -oahelp.com -oahelp.net -oameibang.com -oatos.com -oauto.com -oawhy.com -obagame.com -obesu.com -obins.net -obj6.com -objc.com -objccn.io -objcer.com -objcoding.com -objectyan.me -obkoro1.com -obkprint.com -obolee.com -oborad.com -oborr.com -obowin.com -obsapp.net -obyee.com -ocar.tv -ocd120.com -oceancnc.com -oceanengine.com -oceanlau.com -oceanol.com -oceeq.com -ocesb01.com -ochukai.me -ocimg.com -oclkj.com -ocone.loan -ocooca.com -ocpan.org -ocrmaker.com -ocsp-lb.apple.com.akadns.net -ocsp.apple.com -ocsp.globalsign.com -ocsp.pki.goog -ocsp2.globalsign.com -oct-and.com -oct-asia.com -oct-cts.com -oct-sh.com -octbay.com -octeast.com -octeshow.com -octholding.com -octhotels.com -octinn.com -octjstz.com -octlink.com -octmami.com -octman.com -octo.fm -octocard.in -octoparse.com -octopgo.com -octopusgame.com -octre.com -octscc.com -octwuhan.com -oculist.net -odaily.com -odao.com -odict.net -odinichina.com -odinjc.com -odinliu.com -oealy.com -oeasy.org -oecr.com -oeebee.com -oeeee.com -oejournal.org -oelove.com -oemol.com -oemresource.com -oenhan.com -oeob.net -oeofo.com -oesell.com -oetsi.com -oeynet.com -ofcard.com -offcn.com -offer-wow.com -office-cn.net -office-peixun.com -office26.com -office68.com -officecdn.microsoft.com -officectrl.com -officedoyen.com -officeedit.com -officejc.net -officese.com -officeweb365.com -officewj.com -officexr.com -officezhushou.com -officezu.com -offodd.com -ofgame.net -ofidc.com -ofmonkey.com -ofo.com -ofo.so -ofpay.com -ofuns.com -ofurl.org -ofweek.com -ofyoo.com -ogaoxiao.com -ogccdn.com -ogengine.com -oh100.com -ohaotian.com -ohipic.com -ohmanhua.com -ohqly.com -ohtly.com -ohtpc.com -ohtvu.com -ohwit.com -ohwyaa.com -oi-wiki.org -oiaqye7985.com -oicat.com -oicq88.com -oicqzone.com -oicto.com -oidchina.org -oiegg.com -oigps.com -oilchem.net -oilepay.com -oilhr.com -oipapio.com -oiuwe.com -ok-meeting.com -ok06.com -ok1222.com -ok1616.com -ok165.com -ok1912.com -ok1997.com -ok22.org -ok365.com -ok3w.net -ok86.com -ok8809.com -ok9624.com -ok9803.com -oka-vip.com -okad.com -okajax.com -okaoyan.com -okayapi.com -okbao.com -okbase.net -okbike.net -okbmf.com -okbuy.com -okbuycdn.com -okcard.com -okcdn.me -okchang.com -okchexian.com -okdai.com -okdd.net -okemu.com -okex.vip -okexcn.com -okeycar.com -okfri.com -okgj.com -okhimalayanzi.com -okhqb.com -okidc.com -okidc.net -okideaad.com -okii.com -okinfo.org -okjike.com -okjingying.com -okjoys.com -okjsycj.com -okkkk.com -okkong.com -oklink.com -oklx.com -okmart.com -okmeeting.com -okmeike.com -okmyapp.com -okng.com -okoer.com -okokyun.com -okokzy.cc -okokzyyun.com -okooe.com -okooo.com -okoooimg.com -okpush.com -okrecovery.com -okskills.com -oksmk.com -oksun.com -oksvn.com -oktools.net -oktranslation.com -okuer.com -okweb.info -okwuyou.com -okxr.com -okyst.com -okz.com -okz.ltd -okzhaosheng.com -okzuowenxs.com -okzy.co -okzy.me -okzy.tv -okzyp2p.com -okzyw.com -okzyxz.com -okzyzy.cc -okzyzy.com -ol-cdn.com -ol-img.com -ol3vs.com -olabo.net -olacio.com -olami.ai -olcdn.com -oldboyedu.com -oldcat.me -oldcp.com -oldding.net -olddriver.website -oldenland.com -oldking.net -oldlinux.org -oldpan.me -oldrss.com -oleony.com -olinone.com -oliver.ren -oliveryang.net -oliyi.com -ollomall.com -olloop.com -olmy8.com -olymtech.com -omacloud.com -omchain.com -omd99.com -omdnchina.com -omegatravel.net -omegaxyz.com -ometal.com -omgdba.com -omiaozu.com -omicsclass.com -omicshare.net -omifanyi.com -omlzx.com -omlzz.com -ommoo.com -omni-pharma.com -omooo.net -omos88.com -omowork.com -ompchina.net -omsheji.com -omtmy.com -omtxw.com -omuying.com -on-sun.com -onacademic.com -onaliyun.com -onboxo.com -oncanyin.com -onccc.com -onceai.com -onceoa.com -onche.net -oncity.cc -oncloud.store -one-all.com -one-arts.com -one-lab.net -one918.com -onealert.com -oneapm.com -oneasp.com -onebiji.com -onebox.site -onecoder.site -oneconnectft.com -onedi.net -onedict.com -onedns.net -onefoot365.com -onegreen.net -onehang.com -onehome.me -onein.com -oneinstack.com -onekey.cc -onekeyghost.com -onekeyrom.com -onemanhua.com -onemex.com -onemovie.com -onemsdn.com -oneniceapp.com -onenoter.com -onephper.com -onepiecevip.com -oneplus.com -oneplusbbs.com -oneplusmobile.com -ones.ai -onescorpion.com -oneshao.com -onesight.com -onespace.cc -onethingcloud.com -onethingpcs.com -onetog.com -onetwo.ren -oneuos.com -onev.cat -onevcat.com -oneway.mobi -onewrt.com -onewsvod.com -onex.im -onexinli.com -onexmail.com -oneyac.com -oneyearonechange.com -onezapp.com -onezh.com -onijiang.com -onjobedu.com -online-edu.org -online-exam.site -onlinecn.com -onlinedown.net -onlinekr.com -onlinenic.net -onlinesjtu.com -onlinexijiang.com -onlinknews.com -only4.work -onlyay.net -onlycatch.com -onlyedu.com -onlyeduit.com -onlyidc.com -onlylady.com -onlyling.com -onlyliuxue.com -onlyou.com -onlyred.net -onlystem.com -onlytss.com -onlywem.com -onlyyou.com -onmpw.com -ono-bbb.com -onqc.com -ontheroadstore.com -onthink.com -ontvb.com -oo14.com -oobao.net -oocct.com -ooclab.com -oodso.com -ooe.la -oogcw.com -oogps.com -oohdear.com -oolap.com -oollttqq.com -oomake.com -ooniu.com -ooogo.com -ooomm.com -ooopic.com -ooopn.com -ooppoo.com -oouee.com -ooxx.me -ooxxc.com -op86.net -opahnet.com -opark.com -opatseg.com -opcns.net -opd2c.com -opdown.com -open-china.net -open-falcon.com -open-falcon.org -open-open.com -open189.net -openasic.org -openbayes.com -openbiox.org -openbpm.net -opencas.org -openclasses.info -opencoding.com -opencourt.vip -opendrivers.com -openedu.tv -openedv.com -openerp.hk -opengslb.com -openinstall.io -openke.net -openkruise.io -openkylin.com -openlab.cc -openlab.co -openlanguage.com -openlink.cc -openloong.org -openloongson.org -openos.org -openpard.org -openpcba.com -openqa.com -openredcloud.com -openresty.com -openresty.org -openrice.com -opensc.co -opensc.net -opensc.xyz -opensoce.com -openthos.com -openthos.org -openv.com -openwbs.com -openwrt.pro -openxiaoniu.com -openxinfo.com -operachina.com -opgtv.com -oplay.net -opmaterial.com -opp2.com -oppein.com -opplestore.com -oppo.com -oppo518.net -oppofind.com -oppomobile.com -oppopay.com -opposhop.in -opposhore.com -opqnext.com -oprtb.com -opsapp.com -opskb.com -opskumu.com -opslinux.com -opsnote.com -opsroad.com -opstool.com -optaim.com -optbbs.com -opticsjournal.net -opticsx.org -optimix.asia -optinetchina.com -optjcjj.com -optol.net -opvip.com -opwill.com -opxincai.com -opython.com -opzoon.com -oq78.com -oqss.com -or-sun.com -oracledatabase12g.com -oracleoaec.net -oradbca.com -oraev.com -oralpractice.com -orange2h.com -orangeapk.com -orangelive.tv -orangepi.org -orangevip.com -orasos.com -oray.com -oray.net -oraybox.com -oraycn.com -orayer.com -orayimg.com -orbitmes.com -orcadt.com -orchome.com -orcode.com -ordosbank.com -orfetuz.com -orgcc.com -orgleaf.com -orgnitu.net -orient-fund.com -orient-safety.com -orientalpatek.com -orientalpearltower.com -orientalwisdom.com -orientcasa.com -orientgolf.com -orientpc.com -orienttumor.com -originalkindergarten.com -origincn.com -originlee.com -originoo.com -orihard.com -oritive.com -orleto.com -ornglad.com -orpheus.ink -orsoon.com -orspr.com -orsun.cc -orvibo.com -orz.asia -orz.moe -orz123.com -orz520.com -orz9.com -orzbook.com -orzice.com -orzjoy.com -os-easy.com -os-v.com -os7blue.com -osall.com -osbccdn.com -osbean.com -osbzr.com -oscarma.com -oscartutor.com -oscarzhoud.com -oscdn.apple.com -oscdn.origin-apple.com.akadns.net -oschina.com -oschina.io -oschina.net -osechina.com -osedu.net -oseminfo.com -oserror.com -oseye.net -osfipin.com -osg.so -osgchina.org -oshadan.com -oshoplive.com -osjiaju.com -osk-clean.com -osmsg.com -osmy.net -osnt.wang -oso6.com -ososn.com -osp.io -ospp.com -oss.link -oss.so -osschina.com -ossxp.com -ostools.net -osvlabs.com -oswdj.com -oswhy.com -osx.cx -osyum.com -osyunwei.com -otcgd.com -otcms.com -otczg.com -otkglass.com -otms.com -otolines.com -otome.me -otomedream.com -otosaas.com -otp-express.com -otpub.com -ott4china.com -ottcn.com -ottcn.help -ottshopping.net -otype.com -ou99.com -ouapi.com -oubayun.com -oubk.com -oudapay.com -oudeqi.com -oudiscover.com -oufa-travel.com -oufengblog.com -oufusoft.com -ougei.com -ougepiano.com -ouhua.info -ouj.com -oujistore.com -oukan.online -ouklqd.com -oulvnet.com -oumengke.com -ounh.org -ouo.us -ouoou.com -ouou.com -ouougo.com -oupeng.com -oupengcloud.net -oupuzw.com -our-sky.com -ourail.com -ourats.com -ouravr.com -ourcdns.com -ourcm.net -ourcoders.com -ourd3js.com -ourden.net -ourdomains.com -ourdvs.com -ourdvs.info -ourdvs.net -ourdvsss.com -oureman.com -ourgame.com -ourglb.club -ourglb0.com -ourglb0.info -ourglb0.net -ourglb0.org -ourhlb.com -ourhlb.info -ourhlb.org -ourhy.net -ourjay.com -ourjg.com -ourjiangsu.com -ourjs.com -ourjz.com -ourku.com -ourl.co -ourlife365.com -ourlinc.com -ourpalm.com -ourplay.net -ourren.com -oursakura.com -oursec1.com -oursec2.com -ourselec.com -ourseo.net -oursketch.com -oursmc.com -ourtxt.net -ourwebat.com -ourwebcdn.com -ourwebcdn.info -ourwebcdn.net -ourwebcdn.org -ourwebhttps.com -ourwebpic.com -ourwebpic.info -ourwebpic.org -ourwen.com -oushangstyle.com -oushinet.com -oushivoyages.com -ousns.net -outerhaven.club -outlets365.com -ouvps.com -ouyabosi.com -ouyada.com -ouyaoxiazai.com -ouyeel.com -ouyingyimin.com -ouzhougoufang.com -ov98.com -ovalechina.com -ovbook.com -ovc-finance.com -ovcreative.com -ovcstf.com -ovdream.com -ovear.info -oversearecruit.com -overtrue.me -overturechina.com -ovital.com -ovital.net -ovoawh.com -ovopark.com -ovopic.com -ovscdns.com -ovscdns.net -ovuems.com -ovupre.com -ovuwork.com -ovwin.com -owecn.com -owendswang.com -owllook.net -owmy.ga -owspace.com -owulia.com -ox11.com -oxbridgedu.org -oxbtc.com -oxerr.net -oxiaohua.com -oxrm.com -oxygenos.com -oxyry.com -oyangiz.com -oycode.com -oycslia.xyz -oyeahgame.com -oyekeji.com -oyinli.com -oyksoft.com -oyohyee.com -oyonomg.com -oyonyou.com -oyoozo.com -oyoumo.com -oyqcmc.com -oyxdwx.com -oyyj-oys.org -oz138.com -ozrot.com -ozzyad.com -p-dragon.com -p-e-china.com -p.cdn.persaas.dell.com -p1.com -p12345.com -p138.com -p2220.com -p2cdn.com -p2hp.com -p2p.com -p2p001.com -p2p178.com -p2pbbs.net -p2pchina.com -p2pcq.com -p2peye.com -p2peye.net -p2pguancha.com -p2phx.com -p2pjd.com -p2pjj.com -p2psearcher.org -p2psearchers.com -p2ptouhang.com -p2pxing.com -p2pxsj.com -p2pzc.com -p31.net -p3k3.com -p4.cc -p491gt.com -p4pp.com -p4vip.com -p512.com -p5w.net -p8games.com -p99998888.com -pa18.com -pa1pa.com -pa80.com -paascloud.net -paat.com -pacdn.com -paceroom.net -pacgatelaw.com -package-design.net -packtom.com -packty.com -pactera.com -padasuo.net -padding.me -paddlepaddle.org -paddlewaver.com -paedu.net -pagead-googlehosted.l.google.com -pageadmin.net -pagechoice.com -pagechoice.net -pagecookery.com -pagurian.com -pahaoche.com -pahou.com -pahx.com -pahys.com -pai-hang-bang.com -paibanxia.com -paichen.net -paidai.com -paidai.org -paidanzi.com -paidui.com -paiduidai.com -paihang360.com -paihb.com -paihotels.cc -paike.com -paiky.net -pailixiang.com -pailubao.com -paimaprint.com -paiming.net -paintinghere.org -paipai.com -paipai123.com -paipaibang.com -paipaiimg.com -paipaitxt.com -paipianbang.com -paiqy.com -paisen.site -paishanglai.net -paishi.com -paiwo.co -paixie.net -paixin.com -paiyiws.com -paizhe.com -paizi.com -paizishop.com -palace-international.com -palanceli.com -palm-h.com -palmestore.com -palmjoys.com -palmtrends.com -palmyou.com -pamau.com -pamss.net -pamteng.com -pan-elektron.com -pan115.com -pan131.com -pan58.com -pan8.net -panabit.com -panbaidu.com -pancake.apple.com -pancake.cdn-apple.com.akadns.net -panchuang.net -pancishe.com -panda98.com -pandadai.com -pandadastudio.com -pandafoundation.org -pandainc.cc -pandaminer.com -pandara.xyz -pandateacher.com -pandatv.com -pandoe.com -pandolia.net -pandoramanager.com -pandoramanager.net -pandownload.com -pandoxie.com -panduoduo.me -panduoduo.net -panduoduo.online -panfn.com -pang0lin.com -pangbu.com -pangcheng.com -pangci.cc -pangdly.com -panghuasheng.com -pangku.com -pangmao56.com -pangmaovc.com -pangoing.com -pangolin-dsp-toutiao.com -pangolin-sdk-toutiao-b.com -pangolin-sdk-toutiao.com -pangomicro.com -pangong88.com -pangqiu.com -pangshu.com -pangukj.com -panguso.com -pangxieke.com -pangzhan.net -panjin.net -panjindamibest.com -panjk.com -panjunwen.com -panku.cc -panmeme.com -pannacloud.com -panoeade.com -panoramastock.com -panpay.com -panqibao.com -panshi101.com -panshianquan.com -panshixk.com -panshiyun.com -panshizz.com -panshy.com -pansino-solutions.com -pansoso.com -pansou.com -pantianxia.com -pantosafety.com -pantrysbest.com -pantum.com -panweizeng.com -panyueic.com -panyun.com -paoao.net -paobuqu.com -paochefang.com -paodoo.com -paofugroup.com -paojiao.com -paolanhuanbao.com -paomo.com -paomou.com -paopao.com -paopaoche.net -paopaochina.com -paopaoleg.com -paopaox.com -paoshuba.cc -paoxq.com -paoxue.com -papa21.com -papa91.com -papajohnshanghai.com -papapoi.com -papaquan.com -paparecipe.net -papegames.com -paper.tv -paper211.com -paperask.com -paperbus.com -paperbye.com -paperccb.com -paperclipclub.net -papercool.com -papereasy.com -papergod.com -paperisok.com -paperok.com -paperonce.org -paperopen.com -paperpass.com -paperpi.com -paperrater.net -paperright.com -papersay.com -papersee.com -papertime.cc -papertime.shop -paperweekly.site -paperword.com -paperwrite.net -paperyy.com -papocket.com -paquapp.com -parallelsras.com -paratera.com -parawikis.com -parduscycle.com -parentshk.com -paris-bride.com -paris-sengfu.net -parkbees.com -parkchina.net -parkdaily.com -parkingjet.com -parkmecn.com -parkviewgreen.com -parnassusdata.com -parryqiu.com -parsein.com -partinchina.com -parwix.com -pass7.cc -passby.me -passdesign.net -passer-by.com -passport.lenovo.com -passvpn.com -passwordkeyboard.com -pastein.net -patachina.org -patchallin.com -patent-cn.com -patexplorer.com -patindex.com -patmm.com -patos.cc -patsev.com -patsnapglobal.com -pautoclub.com -paxgl.com -payeco.com -payhearts.com -payloads.online -paymax.cc -paympay.com -payrao.com -paysapi.com -paytbf.com -paytend.com -payun.wang -payxinyi.com -pb89.com -pbcan.com -pbcdn.com -pbhz.com -pblie.com -pbootcms.com -pbsidc.com -pbsvpn.com -pbtdl.com -pbtxt.com -pc-dvd.com -pc-fly.com -pc02.com -pc120.com -pc120tv.com -pc123.net -pc141.com -pc18.net -pc34.com -pc3w.com -pc51.com -pc5210.com -pc6.com -pc6.org -pc6a.com -pc70.com -pc789789.com -pc811.com -pc840.com -pc841.com -pc9.com -pcaposter.com -pcb-hl.com -pcb-si.com -pcb3.com -pcb818.com -pcbask.com -pcbba.com -pcbbar.com -pcbbbs.com -pcbdoor.com -pcben.com -pcbhf.com -pcbhunt.com -pcbiot.com -pcbjob.com -pcbookcn.com -pcbres.com -pcbserve.com -pcbsheji.com -pcbtech.net -pcbtime.com -pccpa.hk -pccppc.com -pcdog.com -pcdrv.com -pcdsp.com -pceggs.com -pcejr.com -pceva.net -pcfcw.net -pcfreetime.com -pcfuns.com -pcgeshi.com -pcgogo.com -pcgta.cc -pch-img.net -pchome.com -pchome.net -pciiss.com -pcitc.com -pclic.com -pcme.info -pcmgr-global.com -pcmoe.net -pcnsh.com -pcoic.com -pcp-china.com -pcpop.com -pcquan.com -pcsee.org -pcspw.com -pct86.com -pctowap.com -pctu.net -pctutu.com -pctutu.net -pctvx.com -pcviva.com -pcw365.com -pcwenti.com -pcwl.com -pcyangguangban.com -pcyule.com -pd-sts.com -pd120.com -pd521.com -pdazw.com -pdbeta.com -pdcuo.com -pddcdn.com -pddeu.com -pddpic.com -pddugc.com -pdf-lib.org -pdf-tech.com -pdf.la -pdf00.com -pdf1122.com -pdf5.net -pdfac.com -pdfbianji.com -pdfdo.com -pdfdowell.com -pdfexpert.cc -pdfjia.com -pdflibr.com -pdfwang.com -pdfxd.com -pdfzj.com -pdgzf.com -pdidc.com -pdim.gs -pdm.so -pdosgk.com -pdown.org -pdrcfw.com -pdreading.com -pdryx.com -pdscb.com -pdsgjj.com -pdskgb.com -pdsxww.com -pdszhtl.com -pdvisa.com -pdxx.net -pe.vc -pe62.com -pe8.com -pe86.com -pe898.com -pea3nut.com -pea3nut.info -pea3nut.org -peace-read.com -peaceticket.com -peak-labs.com -pear.hk -pearlinpalm.com -pearvideo.com -peasrch.com -pec365.com -pediso.com -pediy.com -pedli.com -peento.com -peepic.com -peersafe.com.sg -pegatroncorp.com -peidu.com -peihao.space -peikua.com -peilian.com -peilian365.com -peilili.com -peiqiang.net -peise.net -peixun.net -peixun.pro -peixun5.com -peixun69.com -peixune.com -peixunmatou.com -peixunxue.com -peiyin.net -peiyinge.com -peiyou.com -peiyouwang.com -peizi.com -peizi0371.com -peizizhishu.com -peizizj.net -pemap.com -pending-renewal-domain.com -pendoapp.com -peng001.com -pengbo.com -pengchengenergy.com -pengfu.com -penging.com -pengjuan.com -pengke.com -penglaiu.com -penglei.name -pengpeng.com -pengpeng.la -pengpengqj.com -pengqi.club -pengqian.win -pengrl.com -pengshengcaishui.com -pengxun1.com -pengyaou.com -pengyou.com -pengyoufx.com -pengyoujia.me -pengyoukan.com -pengyuwei.net -penhuijiqi.com -penncodd.com -pentalaser.com -pentaq.com -penxiangge.com -peonyta.com -people-squared.com -peopleapp.com -peopleart.tv -peopledailypress.com -peoplenews.eu -peoplerail.com -peopleyuqing.com -pepresource.com -perfect-input.com -perfect-is-shit.com -perfect99.com -perfectdiary.com -perfectonlive.com -peropero.net -pes-china.com -pesiv.com -pesyun.com -pet82.com -pet86.com -peter-zhou.com -petersonlian.com -petkoo.com -petmrs.com -petnakanojo.com -petpcb.com -petrelteam.com -petroren.com -pets12345.com -pettwo.com -pewld.com -pewsc.com -pexue.com -pf110.com -pf168.com -pf178.com -pf999.net -pfan123.com -pfchai.com -pfhoo.com -pfmcchina.org -pfwx.com -pg-leak.com -pg114.net -pg77520.com -pg9997.com -pgbee.com -pgc.tv -pgcog.com -pgjcqm.com -pgl-world.com -pglstatp-toutiao.com -pgnan.com -pgsql.tech -pgsqldb.com -pgsqldb.org -pgu.cc -pgyer.com -pgygho.com -pgyidc.com -pgysoft.com -pgyst.net -pgzs.com -pgzx.net -ph1126.net -phalapi.net -phaser-china.com -phb123.com -phdwu.com -phedu.net -phenixos.com -phezzan.com -phgs001.us -phicomm.com -phida.net -philipswechat.com -philm.cc -philosophypeople.com -phnamedns.com -phnixpool.com -pho.so -phobos.apple.com -phodal.com -phoemix.net -phoenixos.com -phoenixstudio.org -phoenixtea.org -phoenixtv.com -phoent.com -phoer.net -phome.net -phone580.com -phonechn.com -phonecoolgame.com -phonegap.me -phonegap100.com -phonekr.com -phopic.com -photo0086.com -photo3050.com -photoartiz.com -photocnc.com -photocome.com -photohn.com -photoint.net -photoneray.com -photopai.com -photoplayhouse.com -photops.com -photosanxia.com -photowoo.com -photoyunnan.com -photozoomchina.com -phouses.com -php-master.com -php-note.com -php-oa.com -php-z.com -php168.com -php186.com -php2.cc -php230.com -php318.com -php7.site -phpac.com -phpbbchina.com -phpbloger.com -phpchina.com -phpcj.org -phpcom.net -phpcomposer.com -phpcomposer.net -phpconchina.com -phpcoo.com -phpcto.org -phpddt.com -phpdr.net -phpe.net -phpernote.com -phperxuqin.com -phperz.com -phpfans.net -phpfensi.com -phpfs.com -phpgen.com -phpha.com -phphub.org -phpjiami.com -phpjiayuan.com -phpkaiyuancms.com -phpkhbd.com -phpkoo.com -phpno.com -phpok.com -phpor.net -phppx.com -phprpc.org -phpsong.com -phpspider.org -phpstat.net -phpstudy.net -phpstudyimg.com -phptext.net -phpv.net -phpvar.com -phpvod.com -phpweb.net -phpweblog.net -phpwind.com -phpwind.net -phpxs.com -phpxy.com -phpyun.com -phuck.me -phys.net -physicalchina.vip -phyt88.com -phyy1.com -pi7.com -piadu.com -pianhd.com -pianke.me -pianohl.com -pianona.com -pianopu.com -pianoun.com -pianso.com -piantou.net -pianyim.com -pianyini.com -pianyit.com -pianyiwan.com -pianyiyouhui.com -pianyuan.net -pianzhui.com -pianziweb.com -piao.com -piao88.com -piao88.net -piao95.com -piaobuy.com -piaochong.com -piaode.ren -piaodown.com -piaofang168.com -piaohua.com -piaohua668.com -piaohuafl.com -piaojiaowang.com -piaojubao.com -piaoliang.com -piaolianghuay.com -piaoniu.com -piaoquantv.com -piaoshen.com -piaotian.org -piaotian.us -piaotian5.com -piaotongyun.com -piaowu99.com -piaowusong.com -piaowutong.cc -piaoxian.net -piaoyang.tk -piaoyi.org -piaoyun.net -piaozhilan.com -piaozone.com -piasy.com -pibaosi.net -pic-imges.com -pic-rere.com -pic138.com -pic16.com -pic21.com -pic720.com -pic97.com -picc.com -piccamc.com -picchealth.com -piccjs.com -picicafe.com -picooc.com -picosmos.net -picp.io -picp.net -pictureknow.com -picxiaobai.com -picyoung.com -picyq.com -pidcn.com -pieeco.com -piekee.com -piekee.net -pieshua.com -pifa333.com -pifamm.com -pifukezaixian.com -pig.ai -pig4cloud.com -pig66.com -pig87.com -pigai.org -pigcms.com -pigeonracingbooks.com -piggif.com -pigjian.com -pigqq.com -pigx.vip -pigxv.com -pigzz.com -pihitech.com -piikee.net -piimg.com -piios.com -piis.pw -pikacn.com -pikatao.com -pilaipiwang.com -pili-zz.net -pilibaba.com -pilidns.com -pilifu.com -pilifx.com -pimei.com -pin-ad.com -pin-color.net -pin-guan.com -pin-qu.com -pin18pin.com -pin5i.com -pinbaitai.com -pinbang.com -pincai.com -pincai360.com -pinchain.com -pindi88.com -pinduoduo.com -pinduoduo.net -pineprint.com -ping-jia.net -ping-qu.com -ping.ubnt.com -pingan.com -pingan.com.hk -pingancdn.com -pinganfang.com -pingansale.com -pinganwj.com -pinganyun.com -pingapple.com -pingcap.com -pingcegu.com -pingcoo.com -pingfangx.com -pingfenbang.com -pinggu.com -pinggu.org -pingguobaoxiu.com -pingguocms.com -pingguodj.com -pingguohe.net -pingguolv.com -pinghe.com -pingjiata.com -pinglun8.cc -pingnanlearning.com -pingnuosoft.com -pingpang.info -pingpangwang.com -pingpingdai.net -pingpingw.com -pingpingze.com -pingplusplus.com -pingpongx.com -pingshu8.com -pingshuku.com -pingshuocoal.com -pingstart.com -pingtan6.com -pingtandao.com -pinguangapp.com -pinguo.us -pingwest.com -pingxiaow.com -pingxonline.com -pingxuan123.com -pingxx.com -pingyin.cc -pingyou.cc -pingyumarathon.com -pinhaohuo.com -pinhecha.com -pinhuba.com -pinhui001.com -pinidea.co -pinjiaolian.com -pinjie.cc -pinkecity.com -pinkemi.com -pinkertech.com -pinkobaby.com -pinla.com -pinlian.net -pinlue.com -pinmie.com -pinmuch.com -pinpai1.com -pinpaidadao.com -pinpailiu.com -pinpailun.com -pinpaiv.com -pinshan.com -pinshanghe.com -pinshiwen.com -pinshu.cc -pinshu.com -pinsong8.com -pintour.com -pintu360.com -pintuan.com -pintuanzu.com -pintuer.com -pinweiduo.com -pinweiwed.com -pinwenba.com -pinwu123.com -pinyou8.com -pinyuan.cc -pinyuew.com -pinyuncloud.com -pinzhikeji.net -pinzs.com -pioneercnc.net -pioneerlinux.com -pioneersci.com -pioneertimes.net -pipa.com -pipacoding.com -pipapai.com -pipaw.com -pipaw.net -pipedetect.com -pipibus.com -pipikou.com -pipimp3.com -pipipan.com -pipipifa.com -pipiti.com -pipix.com -pipsemi.com -piqs.com -pisx.com -pites.cc -piworker.com -pix2code.net -pixelauth.com -pixhey.com -pixivacg.com -pixivic.com -pixivic.net -piyingke.com -piyipiba.com -pj-road.com -pj.com -pj00001.com -pj0585.com -pj155.com -pj52.net -pj886888.com -pjbest.com -pjcrwljs.com -pjf.name -pjforging.com -pjhome.net -pjhubs.com -pjialin.com -pjjs2.com -pjjyzx.com -pjnoi.com -pjob.net -pjrcn.com -pjtime.com -pjtx.net -pjylw.net -pk052.com -pk106.com -pk10fh.com -pk1352.com -pk1xia.com -pk2234.com -pk350.com -pk361.com -pk38.com -pk532.com -pk571.com -pk9294.com -pk995.com -pkbeta.com -pkbigdata.com -pkbkok.com -pkdyplayer.com -pkfj.xyz -pkgklk.com -pkhxg.com -pki-goog.l.google.com -pkm360.com -pkmmo.com -pko123.com -pkoplink.com -pkpk.com -pkpky.com -pkpmsoft.com -pkq2016.com -pksfc.com -pksky.com -pku-hit.com -pku-lvxin.com -pku666.com -pkubr.com -pkucat.com -pkufh.com -pkulaw.com -pkulaws.com -pkurc.com -pkusky.com -pkusp.com -pkvs.com -pkzx.com -plaidc.com -planckled.com -planetmeican.com -planoi.com -plantextra.com -plantower.com -plas2006.com -plasmatium.xyz -plateno.cc -plateno.com -platenogroup.com -platinum-traveller.com -platinumchina.com -play-analytics.com -play68.com -play700.com -play86.com -play910.com -playbeta.net -playcomet.jp -playcrab.com -playcvn.com -playfifa.com -playlu.com -playnail.com -playpangu.com -playpi.org -playsm.com -playstudy.com -playtai.com -playtai.net -playuav.com -playwonderful.com -playwx.com -playyx.com -plcdn.net -plcent.com -plcloud.com -plcsq.com -pldba.com -plesk-cn.com -plexjiasuqi.com -plmulu.com -plob.org -plotcup.com -plpeng.xin -plsmspx.com -plsub.com -pluosi.com -plures.net -plusgantt.com -plusmedia.site -plustudy.com -plutuspay.com -pluvet.com -plycd.com -plyz.net -pm-summit.org -pm222.com -pm25.com -pm25.in -pm265.com -pm28.com -pm360.com -pm360.net -pmacasia.com -pmcaff.com -pmdak.com -pmdaniu.com -pmec.net -pmichina.org -pmish-tech.com -pmkiki.com -pmovie.com -pmparkchina.com -pmpdubai.com -pmppcc.net -pmptuan.com -pmquanzi.com -pmr66.com -pms.com -pmsra.com -pmtalk.club -pmtoo.com -pmtown.com -pmway.com -pmxprecision.com -pmxsd.com -pmyes.com -pmyuanxing.com -pn66.com -pnetp.org -pngui.com -pnlyy.com -pnol.net -pnwww.com -pnxs.com -pnzpw.com -po369.com -pobaby.net -pobasoft.com -pobiji001.com -poboo.com -pocc.cc -pocketdigi.com -pocketuni.net -pocomagnetic.com -pocosite.com -pocsuite.org -poctchina.com -podinns.com -poem88.com -poemaster.com -poemlife.com -pohaier.com -pohover.com -poikm.com -poizon.com -poj.org -pojaa.com -pojie520.com -pokemmc.com -pokemon.name -pokermate.net -poketec.com -pokooo.com -polaris-vc.com -polarxiong.com -polaxiong.com -polayoutu.com -polingba.com -poluoluo.com -polycent.com -polycn.com -polycom-china.com -polycom-jl.com -polyhotel.com -polyhz.com -polytheatre.com -polytheatresz.com -polyv.net -polywuye.com -pomears.com -pomoho.com -pondsi.com -pongpong.club -ponley.com -ponycool.com -ponytest.com -ponytestqd.com -ponytestsh.com -ponytestsz.com -poo1.club -pooban.com -poobbs.com -poocg.com -poocg.me -pooioo.com -pook.com -poolflare.com -poolgpu.com -poolin.com -pooluo.com -poorren.com -pooy.net -pop-bags.com -pop-fashion.com -pop-shoe.com -pop136.com -pop800.com -popasp.com -popdg.com -popgamer.com -popgo.org -popiano.org -popjb.com -popkart.tv -popkx.com -popmanga.com -popmart.com -popmsg.com -popoho.com -popotang.com -popoxiu.com -poppace.com -poppur.com -popqiu.com -popsoft.com -popu.org -popumed.com -poputar.com -popziti.com -poqsoft.com -porlockz.com -porschesky.com -portoflower.com -ports-intl.com -pos.gold -posbar.com -posdls.com -poseidon.dl.playstation.net -poseidong.com -posfree.com -posn.net -post183.net -postcha.com -posterlabs.com -posters-4-sale.com -postgres.fun -postgresqlchina.com -postjson.com -postpony.com -potevio.com -potianji.net -potplayer.org -potplayer.pro -pouchcontainer.io -poukao.com -pouyehm.com -power-bd.com -power-sensor.com -powerbibbs.com -powercdn.com -powerde.com -powereasy.net -poweric-china.com -powerlaw.ai -powerleadercdn.com -powerleaderidc.com -powerskystudio.com -powervision.me -powerxene.com -powzamedia.com -poxiao669.com -poxiaotv.com -pozhishi.com -pp-sp.com -pp-xxgd.com -pp.cc -pp00.com -pp100.com -pp130.com -pp1o.com -pp25.com -pp250.com -pp51.com -pp6.cc -pp63.com -pp66.cc -pp70.com -pp8.com -pp8d.com -pp9570.com -pp9l.com -ppa18.com -ppaikd.com -ppbizon.com -ppcall.com -ppcn.net -ppcode.com -ppcost.com -ppdai.com -ppdaicdn.com -ppdd.com -ppdesk.com -ppdqk.com -ppduck.com -ppfeng.com -ppframe.com -ppfw.org -ppgame.com -pphimalayanrt.com -ppio.cloud -ppj.io -ppkankan01.com -ppkanshu.com -ppkao.com -pplib.net -pplive.com -ppliwu.com -pplock.com -ppm2.com -ppmake.com -ppmm.org -ppmoney.com -ppmoney.net -ppnad.com -ppnames.com -ppnba.net -pppet.net -pppie.com -pppoevps.com -pppoo.com -pppowerrr.tk -ppppgps.com -ppppic.com -ppqq.net -pps.tv -ppsao.com -ppsimg.com -ppspain.com -ppsport.com -ppstream.com -ppstream.net -ppstv.com -ppstv.net -ppswan.com -ppt118.com -ppt123.net -ppt360.com -ppt920.com -pptair.com -pptake.com -pptbest.com -pptboss.com -pptbz.com -pptelf.com -ppthi-hoo.com -pptjia.com -pptmall.net -pptmao.com -pptmind.com -pptok.com -pptschool.com -pptshop.com -pptstore.net -pptv.com -pptvyun.com -pptxy.com -pptzs.com -ppurl.com -ppvi.net -ppvod.net -ppwan.com -ppwwyyxx.com -ppxclub.com -ppxhw.com -ppxs.net -ppxwo.com -ppys.net -ppys5.com -ppzedu.com -ppzhan.com -ppzuche.com -ppzuowen.com -pqdtcn.com -pqgld.com -pqpo.me -pqt-bearing.com -pqyhigh.com -pqymiddle.com -pqzhichan.com -prcedu.com -prcee.org -pre-sence.com -pre.im -precise-test.com -precision-biz.com -prefer-tyl.site -prefershare.com -preludeid.com -premedglobal.com -presearchina.com -press-sci.com -prestolite-bj.com -prettyyes.com -prfc-cn.com -prfog.com -pricl.com -primerachina.com -primeton.com -princeblog.com -princeuk.org -print86.com -printer-china.com -printerwhy.net -printhome.com -printlake.com -prior24.com -prismcdn.com -privateadx.com -privatess.win -prjdrj.com -prm.dji.com -pro6e.com -procar.cc -process-safety-lab.com -processon.com -procivi.net -prod-support.apple-support.akadns.net -product1.djicdn.com -productivity.wiki -proginn.com -programfan.com -programlife.net -programmer.group -programmer.help -programschool.com -programtrader.net -progressingeography.com -prohui.com -project-oa.com -project.ci -projectaker.com -projector-window.com -projky.com -prolto.com -promisingedu.com -promoadx.com -proresearch.org -protect-file.com -prototype.im -prowritingteam.com -proya-group.com -proya.com -proyy.com -prwx.com -przhushou.com -przwt.com -ps123.net -ps265.com -ps314.com -psahz.com -psbc.com -psc4d.com -psd8.com -psdiv.com -psdyapp.com -psgui.com -psing.tech -psjay.com -psjia.com -psjxty.com -psncn.com -psnine.com -psoneart.com -pssclub.com -pstatp.com -pstips.net -pstv.tv -pstxg.com -psxiazai.com -psy-1.com -psyapp.com -psychcn.com -psychspace.com -psysh.com -pszx.com -pszyzxh.org -pt-bus.com -pt008.com -pt80.com -pt80.net -ptalking.com -ptausercontent.com -ptbus.com -ptc-asia.com -ptcloud.info -ptcxmy.com -ptd100.com -ptd99.com -ptdsh.com -ptfdc.com -ptfish.com -pthc1.com -pthc8.com -pthxuexi.com -ptimg.org -ptisys.com -ptkill.com -ptleju.com -ptmind.com -ptorch.com -ptotour.com -ptpcp.com -ptteng.com -ptweixin.com -ptxz.com -ptyg.com -ptyly.com -ptyqm.com -pua.hk -puaas.com -puahome.com -puaihospital.net -puansec.com -puasu.com -puata.info -pubchn.com -pubg8x.com -publiccms.com -pubmed007.com -pubone.cc -pubsage.com -pubukeji.com -pubuo.com -pubyun.com -pucms.com -pudaquan.com -pudn.com -pudongwater.com -puduoduo123.com -puduzhai.com -puem.org -puercha.cc -puercn.com -puertea.com -pufa5.org -pufei.net -pufei8.com -puhuacapital.com -puiedu.com -puji114.com -pujia8.com -pujiaba.com -pujiahh.com -pukegame.net -pukinte.com -pulisi.com -pullywood.com -pulsigame.com -pumpvip.com -punaide.com -punakong.com -punchbox.info -punchbox.org -puoke.com -pupuapi.com -pupugo.com -pupumall.com -pupumall.net -pupurazzi.com -pupuwang.com -purcotton.com -purcow.com -pureage.info -pureasme.com -purecpp.org -pureh2b.com -purenyy.com -puroyal.com -pusa123.com -push2333.com -push2u.com -pushauction.com -pushenbbs.com -pushgrid.net -pushjoy.com -pushthink.com -pushtime.net -pusi.site -puss7.com -putao.so -putaoa.com -putaocdn.com -putaogame.com -putclub.com -putdb.com -putian508.com -putiandai.com -putonsoft.com -putop.net -puusa.net -puwenlong.com -puworld.com -puyangxianw.com -puyuecs.com -puyuehui.com -puyurumen.com -puzeyf.com -pv001.net -pv265.com -pv4b.com -pvc123.com -pvkj.com -pvmama.com -pvpin.com -pw1999.com -pw60.com -pw88.com -pwmis.com -pwp.ink -pwrd.com -pwsannong.com -px0571.com -px5a.com -pxb7.com -pxbuy.com -pxcn168.com -pxdsm.com -pxecn.com -pxfeed.com -pxsky.net -pxtsc.com -pxtu.com -pxtx.com -pxx.io -pxyfhp.com -py-axa.com -py-yq.com -py.com -py1314.com -py137.com -py168.com -py3study.com -py40.com -py6.com -py94.com -pyasfunds.com -pychina.org -pycxjj.com -pyddd.com -pydef.com -pyer.site -pygdzhcs.com -pyguanf.com -pyguohai.com -pyhead.com -pyjia.com -pyjsh.com -pyjyz.com -pyker.com -pylhotel.com -pylist.com -pyneo.com -pynote.net -pyou.com -pysmei.com -pystarter.com -pytgo.com -python88.com -pythonav.com -pythonclub.org -pythondoc.com -pythoner.com -pythonheidong.com -pythonpub.com -pythontab.com -pythontip.com -pytorchtutorial.com -pyxjiang.com -pyxk.com -pyydhg.com -pyyiyou.com -pyynsm.com -pyyx.com -pz0033.com -pz18155.com -pz2777.com -pz2999.com -pz3433.com -pz4555.com -pz5355.com -pz550.com -pz580.com -pz6.com -pz660.com -pz6623.com -pz6682.com -pz7377.com -pz7533.com -pz779.com -pz81.com -pz88.com -pz997.com -pzds.com -pzhccb.com -pzhht.com -pzjdimg.com -pzjiadian.com -pzlink.com -pznews.com -pznrfsy.com -pznsh.com -pzoom.com -pzsmrk.com -pztuan.com -pzzwyh.com -q-5.net -q-dazzle.com -q-supreme.com -q1.com -q1qfc323.com -q1qq2.com -q2ak.com -q2d.com -q2zy.com -q3060.com -q5.com -q578.com -q68.com -q6haqi.com -q6u.com -q77777777.com -q8q7.com -qacn.net -qalex.com -qaqgame.com -qast.com -qaxanyu.com -qaxcloudwaf.com -qaxwzws.com -qayqa.com -qb5.tw -qb5200.co -qb5200.tw -qb86.cc -qbangmang.com -qbao.com -qbaobei.com -qbaoting.com -qbb6.com -qbdcc.com -qbdgame.com -qbeenslee.com -qbitai.com -qbj8.com -qbjrxs.com -qbox.me -qbsznkj.com -qbtlk.com -qbview.com -qbwu.net -qbxs5.com -qbxsb.com -qbxz.com -qc-dds.net -qc-hr.com -qc-pm.com -qc027.com -qc178.com -qc188.com -qc56.org -qc6.com -qcc.com -qccip.com -qccis.com -qccost.com -qccr.com -qccrm.com -qcdrp.com -qcds.com -qcenglish.com -qcgcj.com -qches.com -qchouses.com -qcjkjg.com -qcjlm.net -qcjslm.com -qckuaizhi.com -qcloud.com -qcloud.la -qcloudcdn.com -qcloudcjgj.com -qcloudimg.com -qcloudmail.com -qcloudwzgj.com -qcloudzygj.com -qcmoke.site -qcmrjx.com -qcmuzhi.com -qcoco.com -qconbeijing.com -qconshanghai.com -qcplay.com -qcq3.com -qcql.com -qcr.cc -qcr365.com -qcrlapp.com -qcsdn.com -qcsj.com -qcstudy.com -qctsw.com -qcwan.com -qcwdpt.com -qcwhw.com -qcwlpay.com -qcwlseo.com -qcwxjs.com -qcwyxx.com -qcymall.com -qcyoung.com -qd256.com -qd315.net -qdac.cc -qdaeon.com -qdaiduo.com -qdaily.com -qdailyapp.com -qdbdsk.com -qdcaijing.com -qdccb.com -qdccdl.com -qdcdn.com -qdcent.com -qdcu.com -qdcypf.com -qdcz.com -qddlxf.com -qddown.com -qdds.net -qdfuns.com -qdgege.com -qdgw.com -qdgxqrc.com -qdgxzg.com -qdhantang.com -qdhedu.com -qdhsty.com -qdingnet.com -qdit.com -qdjiejie.com -qdjimo.com -qdjjwsjf.com -qdjnbgjj.com -qdjxhz.com -qdkebang.com -qdkingst.com -qdkongtiao.com -qdkongtiaohuishou.com -qdlongre.com -qdmama.net -qdmcxh.com -qdmm.com -qdmmcmc.com -qdnsyh.com -qdooc.com -qdpdjx.com -qdppc.com -qdpr.com -qdqihang.com -qdqunweite.com -qdrhh.com -qdsay.com -qdsbx.com -qdsdds.com -qdshitangchengbao.com -qdshuanglide.com -qdsntsg.com -qdswphb.com -qdsysj.com -qdtgood.com -qdthgs.com -qdtongxinedu.net -qdtvu.com -qdtz.com -qdwenxue.com -qdwght.com -qdwsb.com -qdxfgy.com -qdxtcw.com -qdyijiamei.com -qdymjy.com -qdyudie.com -qdyxbyy.com -qdyyjj.com -qdzhengkang.com -qdzmm.com -qdznjt.com -qdzxyy.com -qdzz.com -qeefee.com -qeegee.com -qeejoo.com -qeeka.com -qeeniao.com -qeerd.com -qefee.com -qefeng.com -qeto.com -qf027.com -qfang.com -qfangimg.com -qfcm.net -qfedu.com -qfeiche.com -qfgolang.com -qfpay.com -qfq.me -qfrxyl.com -qfschl.com -qfsyj.com -qftouch.com -qfun.com -qfwwj.com -qg.net -qg108.com -qgbzyzl.com -qgc39.com -qgcyjq.org -qgdyc.net -qgdz222.com -qgenius.com -qgnyjc.com -qgpx.com -qgren.com -qgsydw.com -qgtql.com -qguiyang.com -qgvps.com -qgwsp.com -qgxl.org -qgysj.org -qgzzz.com -qh-cdn.com -qh-lb.com -qh.dlservice.microsoft.com -qh24.com -qh45.com -qh5800.com -qhbtv.com -qhcdn.com -qhclass.com -qhd.net -qhdae.com -qhdaikuan.com -qhdatongnews.com -qhdczzs.com -qhdfxkj.com -qhdgjj.com -qhdjcbj.com -qhdnews.com -qhdren.com -qhea.com -qhee-ma.com -qhee.com -qhfax.com -qhfx.net -qhgxq.com -qhgy.net -qhimg.com -qhimgs0.com -qhimgs1.com -qhimgs3.com -qhimgs4.com -qhimi.com -qhjyks.com -qhjyzb.com -qhkyfund.com -qhlhfund.com -qhlingwang.com -qhlly.com -qhm123.com -qhmhbkj.com -qhmsg.com -qhnews.com -qhpcc.com -qhpk.net -qhpta.com -qhrcsc.com -qhres.com -qhscw.net -qhserver.com -qhsetup.com -qhsklw.com -qhstatic.com -qhstv.com -qhsxf.net -qhtibetan.com -qhtycp.com -qhupdate.com -qhwh.com -qhwmw.com -qhxiaoshuo.com -qhxmlyts.com -qhxyms.com -qhxz.com -qhyccd.com -qhyedu.com -qhyzzzs.com -qi-che.com -qi-ju.com -qi-wen.com -qiachu.com -qiaiou.com -qiak.com -qiakr.com -qialol.com -qian-gua.com -qian10.net -qianba.com -qianbao.com -qianbao666.com -qianbaocard.com -qianbaocard.org -qianbaohr.com -qiancaosp1.xyz -qiancheng.me -qianchengriben.com -qiandaqian.com -qiandd.com -qiandu.com -qianduan.com -qianduan.net -qianduanblog.com -qianduanfan.com -qiandw.com -qianfan123.com -qianfan365.com -qianfangzy.com -qianfanyun.com -qiang.it -qiang100.com -qiangbe.com -qiangchezu.com -qiangchuan.com -qianggen.com -qianggongzhang.com -qianggou5.com -qiangidc.vip -qiangka.com -qianglihuifu.com -qiangmi.com -qiangqiang5.com -qianhai12315.com -qianhaiaiaitie.com -qianhuaweb.com -qianinfo.com -qianjia.com -qianjiayue.com -qianjin5.com -qianjing.com -qianjins.com -qianju.org -qianka.com -qiankun.su -qianliao.net -qianliao.tv -qianliaowang.com -qianlima.com -qianlima11.cc -qianlimafile.com -qianlinkj.com -qianliyanww.com -qianlong.com -qianlongnews.com -qianluxiaoshuo.com -qianmaiapp.com -qianmaidao.com -qianmi.com -qianmingyun.com -qianmo.info -qianmoqi.com -qianmu.org -qianpailive.com -qianpen.com -qianpin.com -qianqi.net -qianqian.com -qianqiankeji.xyz -qianqiantao.com -qianqianxs.com -qianqianxsw.com -qianqic.com -qianqu.cc -qianquduo.com -qianrenge.cc -qianrihong.net -qianrong.me -qianrushi.org -qianshenghua.com -qianshoublog.com -qiansw.com -qiantucdn.com -qianvisa.com -qianw.com -qianwa.com -qianwang365.com -qianwee.com -qianxian.info -qianxiangbank.com -qianxibj.net -qianxin.com -qianxinet.com -qianxixianhua.net -qianxun.com -qianyan.biz -qianyan001.com -qianyi806.com -qianyi808.com -qianyuangx.com -qianyue999.com -qianyuislands.com -qianyuwang.com -qianzhan.com -qianzhan123.com -qianzhengbanliliucheng.com -qianzhengdaiban.com -qiao024.com -qiao88.com -qiaobo.net -qiaobutang.com -qiaochucn.com -qiaodan.com -qiaofangyun.com -qiaofanxin.com -qiaohu.com -qiaohuapp.com -qiaohuisland.com -qiaohumall.com -qiaojiang.tv -qiaomen8.com -qiaomi.com -qiaomukeji.com -qiaoshenghuo.com -qiaoshoumama.com -qiaosiwang.com -qiaotu.com -qiaoxuanhong.com -qiaoyi.org -qiaoyou020.com -qiaqa.com -qiaqiafood.com -qiawei.com -qibingdaojia.com -qibo168.com -qibookw.com -qibosoft.com -qibuluo.com -qibuzw.com -qicaispace.com -qicaixianhua.com -qicaizz.com -qichacha.co -qichacha.com -qichacha.net -qichamao.com -qichecailiao.com -qichechaoren.com -qichegeyin.com -qichehot.com -qichetong.com -qichexin.com -qichezhan.net -qichuang.com -qicn.net -qicp.net -qida100.com -qidasoft.com -qidewang.com -qidian.com -qidiandasheng.com -qidianjob.com -qidianla.com -qidiantu.com -qidic.com -qidisheng.com -qidisheng.net -qidiwang.com -qidong.co -qidong.name -qidongyx.com -qidou.com -qiduocloud.com -qiduowei.com -qiecdn.com -qieerxi.com -qiehe.net -qieman.com -qiepianyun.com -qieseo.com -qieta.com -qietu6.com -qieying.com -qieyou.com -qieyuedu.com -qiezip.com -qifa002.com -qifa128.com -qifa168.net -qifa5355.com -qifake.com -qifangw.com -qifeiye.com -qifengle.com -qifub.com -qifuedu.com -qifun.com -qifuwang.com -qigongworld.net -qiguo.com -qiguoread.com -qihaoip.com -qihaxiaoshuo.com -qihihi.com -qihoo.com -qihoo.net -qihu.com -qihucdn.com -qihuiwang.com -qihuor.com -qihuorumen.com -qii404.me -qiigame.com -qijee.com -qiji.tech -qijiadianzi.com -qijianzs.com -qijiapay.com -qijilvxing.com -qijishow.com -qijizuopin.com -qijoe.com -qijuan.com -qijuib.com -qikan.com -qikan123.com -qikanol.com -qikanw.com -qikegu.com -qikoo.com -qikqiak.com -qiku-cloud.com -qiku.com -qikuailianwang.com -qikucdn.com -qikula.com -qilang.net -qilanxiaozhu.co -qilanxiaozhu.net -qilashou.com -qile771.com -qilecms.com -qilikongjian.com -qilinchess.com -qilindao.com -qiling.org -qilinlf.com -qilinxuan.net -qilong.com -qilongtan.com -qiluhospital.com -qiluhua.com -qiluivf.com -qiluyidian.mobi -qiluyidian.net -qimaren.com -qimi.com -qiming.info -qiming868.com -qimingcx.com -qimingdao.com -qimingpian.com -qimingvc.com -qimingventures.com -qimingwang123.com -qimingzi.net -qimiwang.com -qimo.biz -qimodesign.com -qimser.com -qin.com -qiname.net -qinbei.com -qinbing.com -qinbing114.com -qinblog.net -qincai.com -qincaigame.com -qinchacha.com -qinchu123.com -qinco.net -qineasy.com -qinengwuliu.com -qinfukai.com -qing-hei.com -qing-shan.com -qing5.com -qingbaomofang.com -qingbh.com -qingcache.com -qingcdn.com -qingchifan.com -qingchu.com -qingchunbank.com -qingchunyoufan.com -qingcigame.com -qingclass.cc -qingclass.com -qingclasscdn.com -qingcloud.com -qingdaochina.com -qingdaochina.org -qingdaograndtheatre.com -qingdaomaidige.com -qingdaomedia.com -qingdaomuseum.com -qingdaonews.com -qingdaoren.com -qingdaoticai.com -qingdong999.com -qingdou.net -qingfanqie.com -qingflow.com -qingfo.com -qingfuyun.com -qingfuzaixian.com -qingge100.com -qinggl.com -qingguo.com -qinghe.tv -qingheluo.com -qinghua.cc -qinghua2017.com -qinghua5.com -qinghuaonline.com -qinghuaxuezi.com -qinghuo.net -qingis.com -qingjianxiu.com -qingju.com -qingkai.com -qingkan.tw -qingkan9.com -qingkeji.com -qingkuaipdf.com -qinglai19.com -qinglanji.com -qingliange.com -qinglin.net -qingliuge.com -qingliulan.com -qinglm.com -qinglue.net -qinglvcha.com -qingmang.me -qingmang.mobi -qingmayun.com -qingmei.me -qingmo.com -qingmo.net -qingmob.com -qingnianlvxing.com -qingnianwang.com -qingpanduola.com -qingpingshan.com -qingpinji.com -qingqikeji.com -qingqin.com -qingrenw.com -qingruanit.net -qingsenshuizu.com -qingshow.net -qingsj.com -qingsong123.com -qingsongchou.com -qingstor.com -qingsucai.com -qingsword.com -qingtaoke.com -qingtian16265.com -qingtiancms.net -qingtin.com -qingting.fm -qingtingfm.com -qingtingip.com -qinguanjia.com -qingwawa.com -qingwk.com -qingxiaoyun.com -qingxuetang.com -qingyougames.com -qingyungou.com -qingzhanshi.com -qingzhiwenku.com -qingzhouaote.com -qingzhu.co -qingzhuyi.com -qiniao.com -qiniu.com -qiniu.in -qiniu.io -qiniuapi.com -qiniucdn.com -qiniudn.com -qiniudns.com -qiniukodo.com -qiniup.com -qiniupkg.com -qiniutek.com -qiniuts.com -qinlake.com -qinliancf.com -qinms.com -qinqiang.org -qinqiaozixun.com -qinqin.com -qinqinxiaobao.com -qinsmoon.com -qinto.com -qinwanghui.com -qinxue.com -qinxue100.com -qinxue365.com -qinxuye.me -qinyi.net -qinyipu.com -qinzc.me -qinzhe.com -qinzhou8.com -qinzi7.com -qinzidna.com -qinziheng.com -qionghaif.com -qiongliangjt.com -qiongming.com -qiongri.com -qipacao.com -qipaifan.com -qipamaijia.com -qipeiren.com -qipeisyj.com -qipeng.com -qiqici.com -qiqids.com -qiqilm.com -qiqipu.com -qiqipu.tv -qiqiuyu.com -qiqiuyun.net -qiqivv.com -qiqiww.com -qiqu.la -qiquhudong.com -qiqutang.com -qiquting.com -qiqutt.com -qire123.com -qiredy.com -qiremanhua.com -qirexiaoshuo.com -qirui.com -qisbook.com -qishenga.com -qishixitong.com -qishixunmei.com -qishu.cc -qishu.co -qishu.tw -qishunbao.com -qisool.com -qisucdn.com -qisuu.com -qisuu.la -qitete.com -qiti88.com -qitian.biz -qitiancom.com -qitoon.com -qiu-ai.com -qiu.com -qiuball.com -qiucinews.com -qiudao.net -qiudian.net -qiufaqf.com -qiufengblog.com -qiugonglue.com -qiujiaoyou.net -qiujieyl.com -qiujuer.net -qiukuixinxi.com -qiulishi.com -qiumei100.com -qiumeiapp.com -qiumibao.com -qiumijia.com -qiuquan.cc -qiushi.com -qiushibaike.com -qiushibang.com -qiushile.com -qiushu.cc -qiushubang.com -qiushuge.net -qiushuzw.com -qiusuo.net -qiusuoge.com -qiutianaimeili.com -qiuweili.com -qiuwen.org -qiuwu.net -qiuxiazx.com -qiuxue360.com -qiuyexitong.com -qiuyueban.com -qiuyuewenxue.com -qiuyumi.com -qiuzhang.com -qiuziti.com -qiuziyuan.net -qivsod.com -qiwen001.com -qiwen007.com -qiwen8.com -qiwendi.com -qiwenhui.com -qiwentu.com -qixia.ltd -qixiandoc.com -qixifuren.com -qixin.com -qixin007.com -qixin18.com -qixinbo.info -qixincha.com -qixing123.com -qixing318.com -qixingcdn.com -qixingcr.com -qixingquan.com -qixingtang.com -qixinqiguan.com -qixiwl.com -qixoo.com -qixunka.com -qiye.la -qiye.net -qiye163.com -qiye8848.com -qiyegongqiu.com -qiyegongqiu.net -qiyegu.com -qiyeku.com -qiyenet.net -qiyeshangpu.com -qiyeshangpu.net -qiyetuozhan.com -qiyeweixin.com -qiyewenhua.net -qiyexinyong.org -qiyexun.com -qiyexxw.com -qiyeyouxiang.net -qiyeyun.co -qiyi.com -qiyicc.com -qiyimusic.com -qiyipic.com -qiyou.com -qiyouji.com -qiyoujiage.com -qiyouwang.com -qiyouworld.com -qiytech.com -qiyuange.com -qiyucloud.com -qiyue.com -qiyuesuo.com -qiyujiasu.com -qiyukf.com -qiyukf.net -qiyukid.com -qiyunbook.com -qiyuntong.com -qiyunworld.com -qiyutianxia.com -qizhanming.com -qizheplay.com -qizhihaotian.com -qizhuyun.com -qizi.la -qizuang.com -qj023.com -qj258.com -qj26.com -qjbian.com -qjcz.com -qjdywhyq.com -qjfy.com -qjherb.com -qjhlw.com -qjhm.net -qji.cc -qjimage.com -qjishu.com -qjkc.net -qjrc.com -qjren.com -qjsb88.com -qjshe.com -qjsmartech.com -qjtrip.com -qjwhzs.com -qjxgold.com -qjy168.com -qjystang.com -qk365.com -qkan.com -qkang.com -qkblh.com -qkcdn.com -qkeke.com -qkhtml.com -qkkjd.com -qkl123.com -qklyz.com -qknown.com -qksw.com -qktoutiao.com -qktsw.vip -qkvop.com -qkzj.com -ql-cellbank.com -ql18.mobi -ql1d.com -ql47.com -ql789.com -qlbchina.com -qlcard.com -qlchat.com -qlcoder.com -qldzj.com -qlgpy.com -qlidc.com -qljgw.com -qll-times.com -qlmoney.com -qlmyjt.com -qlotc.net -qlpe8.com -qlpw.net -qlrc.com -qls.fun -qlteacher.com -qluu.com -qlxol.com -qm000.com -qm120.com -qm989.com -qmacro.com -qmail.com -qmango.com -qmcaifu.com -qmcmw.com -qmconfig.com -qmei.me -qmei.vip -qmengyun.com -qmht.com -qmht.mobi -qmitao.com -qmood.com -qmqm.net -qmrobot.com -qmsjmfb.com -qmtj.net -qmtk.com -qmtv.com -qmwtp.com -qmyiz.com -qmyxi.com -qmz5.com -qmzs.com -qn0854.com -qnbar.com -qnbqzj.com -qnche.com -qncye.com -qncye.net -qncyw.com -qndb.net -qnfuli.com -qngslb.com -qnhuifu.com -qnjslm.com -qnl1.com -qnmlgb.tech -qnmsq.com -qnq.moe -qnr.io -qnsb.com -qnsdk.com -qnssl.com -qntz.cc -qnvod.net -qnvod.vip -qnydns.com -qnydns.net -qo26.com -qooboo.com -qoocc.com -qoofan.com -qooic.com -qookar.com -qosq.com -qp110.com -qp46.com -qp832.com -qpb187.com -qpdiy.com -qpgame.com -qplmht.com -qplus.com -qpoc.com -qpstar.com -qpx.com -qpzq.net -qq-ex.com -qq-xmail.com -qq.cc -qq.ci -qq.cm -qq.com -qq.do -qq.net -qq1000.net -qq123.xin -qq163.cc -qq163.com -qq163.tv -qq190.com -qq2009.com -qq214.com -qq241.com -qq360wang.com -qq387.com -qq52o.me -qq545.com -qq5818.com -qq717.com -qq745.com -qq7c.com -qq8868.com -qq8868.net -qq933.com -qqahz.net -qqaiqin.com -qqaishu.com -qqan.com -qqapk.com -qqba.com -qqbaobao.com -qqbiaoqing.com -qqbiaoqing8.com -qqbibile.com -qqbite.com -qqbqg.com -qqcedsrc.com -qqcf.com -qqcg.com -qqchu.com -qqcjw.com -qqcyl.com -qqcyl.net -qqdcw.com -qqddc.com -qqdeveloper.com -qqdiannao.com -qqdiannaoguanjiadl.com -qqdna.com -qqdswl.com -qqe2.com -qqenglish.com -qqeo.com -qqershou.com -qqevd.com -qqfangke.com -qqgb.com -qqgd.com -qqgexing.com -qqgexingqianming.com -qqgx.com -qqgyhk.com -qqhao123.com -qqhaoniu.com -qqhbx.com -qqhelper.net -qqhot.com -qqhuhu.com -qqixk.com -qqjay.com -qqje.com -qqjia.com -qqjike.com -qqjishu.cc -qqjishuwang.com -qqjjsj.com -qqju.com -qqjyo.com -qqkeee.com -qqkqw.com -qqku.com -qqkuyou.com -qqkw.net -qqleju.com -qqlin.net -qqm98.com -qqma.com -qqmail.com -qqmcc.org -qqmeiwen.com -qqmofasi.com -qqmtc.com -qqmusic.com -qqnn.net -qqodjn.com -qqokk.com -qqopenapp.com -qqpao.com -qqpifu.com -qqpower.com -qqppt.com -qqq.com -qqq.tv -qqqiyemail.com -qqqnm.com -qqqq.com -qqqqqqqqqqq.com -qqqqqqqqqqqqq.com -qqqqqqqqqqqqqqqq.com -qqread.com -qqride.com -qqrizhi.com -qqro.com -qqshark.com -qqshidao.com -qqshuoshuo.com -qqsk.com -qqsm.com -qqsort.com -qqssly.com -qqstudent.com -qqsurvey.net -qqt6.com -qqteacher.com -qqtest.com -qqtf.com -qqtlr.com -qqtn.com -qqtouxiangzq.com -qqtss.net -qqttxx.com -qqtu8.com -qqtu8.net -qqty.com -qqtz.com -qqu.cc -qqumall.com -qqurl.com -qquu8.com -qqvv88.com -qqwaw.com -qqwechat.com -qqwmly.com -qqwmx.com -qqwtb.com -qqwwr.com -qqwx6.xyz -qqwx8.xyz -qqwxmail.com -qqxiazai.com -qqxifan.com -qqxmail.com -qqxs.cc -qqxs.la -qqxs5200.com -qqxsnew.com -qqxsw.la -qqxww.com -qqxy100.com -qqxzb-img.com -qqxzb.com -qqyewu.com -qqyjx.com -qqymail.com -qqyou.com -qqyouju.com -qqywf.com -qqyy.com -qqyyx.com -qqzaixian.com -qqzhi.com -qqzi.net -qqzl.cc -qqzonecn.com -qqzong.com -qqzsh.com -qqzshc.com -qqzuankuo.com -qqzzz.net -qr25.com -qrcpu.com -qrmanhua.com -qrtest.com -qrx.cc -qryy8.com -qs12315.com -qs7ly.com -qs921.com -qsbank.cc -qsbbs.net -qsbdc.com -qsboy.com -qscdns.com -qschou.com -qsduo.com -qsebao.com -qseeking.com -qsfcw.com -qshang.com -qsk666.com -qskimg.com -qsmh.vip -qsmyhsg.vip -qspfw.com -qspfwadmin.com -qsptv.com -qsrating.com -qss-lb.com -qssec.com -qstatic.com -qstbg.com -qstsking.com -qsw.la -qsw520.com -qsw521.com -qswhcb.com -qswzayy.com -qszs.com -qszt.com -qszt.net -qt-ly.com -qt361.com -qt56yun.com -qt6.com -qt86.com -qtadb.com -qtav.org -qtbcw.com -qtbig.com -qtccolor.com -qtcem.com -qtch888.com -qtcn.org -qtconcerthall.com -qtdebug.com -qtdream.com -qter.org -qtestin.com -qtfy30.com -qtfy7.com -qtfyfl.com -qthmedia.com -qthnews.com -qtj5.com -qtlcn.com -qtlglb.com -qtlglb.info -qtluyuan.com -qtmojo.com -qtonghua.com -qtrun.com -qtshe.com -qtshu.com -qtshu.la -qttc.net -qtulou.com -qtumist.com -qtwm.com -qtx.com -qtxt.net -qtyd.com -qu02.com -qu114.com -qu247.com -qu99.com -qua.com -qualisports.cc -quan.mx -quan0.com -quan007.com -quan99.net -quanbailing.com -quanben.com -quanbenwu.com -quancai360.com -quancdn.cc -quandangdang.net -quandashi.com -quanduoduo.com -quanfangtongvip.com -quanfeng.tech -quanguoban.com -quanidc.com -quanji.com -quanji.la -quanji.net -quanji360.com -quanji55.com -quanjiao.net -quanjing.com -quanjingke.com -quankan.tv -quanke8.com -quanlaoda.com -quanlaodaonline.com -quanlego.com -quanmaihuyu.com -quanmama.com -quanmamaimg.com -quanmeipai.com -quanmeishi.com -quanmin.la -quanmin.tv -quanmin110.com -quanminbagua.com -quanminbb.com -quanminyanxuan.com -quanquanapp.net -quanr.com -quanriai.com -quanshi.com -quanshishequ.com -quanshu.net -quanshuge.com -quanshuwan.com -quanso.net -quansucloud.com -quant.la -quantacn.com -quantao100.com -quantaoyougou.com -quantiku.org -quantil.com -quantone.com -quantuantuan.com -quantum-info.com -quanweili.com -quanxi.cc -quanxiangyun.com -quanxiaoshuo.com -quanyin.xyz -quanyouhui.cc -quanzhanketang.com -quanzhi.com -quanzhifu.net -quanzhoudaqin.com -quanziapp.com -quarkbook.com -quarkers.com -quasarchs.com -quazero.com -quba360.com -qubaike.com -qubaojie.net -qubi8.com -qucai.com -qucaiad.com -qucaidd.com -qucaigg.com -quce001.com -quceaiqing.com -quchao.net -quchaogu.com -quchew.com -quclouds.com -qudangdang.com -qudao.com -qudao.info -qudao168.com -qudaowuyou.com -qudingshui.com -qudong.com -qudong51.net -qududu.net -qudushu.com -quduwu.com -quduzixun.com -queenfather.com -queenshimei.com -quegame.com -quegoo.com -queqiaoba.com -querylist.cc -queshao.com -queshu.com -questyle.com -questyleaudio.com -queyang.com -qufair.com -qufaya.com -qufeisoft.com -qufenqi.com -qugongdi.com -quhaidiao.com -quhua.com -quhuaxue.com -quhubei.com -quhuichang.net -quiboat.com -quick-x.com -quickapi.net -quickbass.com -quickcan.com -quickh5.com -quicksdk.com -quicksdk.net -quilimen.com -quimg.com -quji.com -qujianpan.com -qujinhuo.com -qujishu.com -qujunde.com -qukaa.com -qukan.cc -qukanshu.com -qukantoutiao.net -qukantx.com -quklive.com -qukuai.com -qukuaila.com -qukuailiant.com -qukuba.com -quledu.net -qulishi.com -qulv.com -qumaishu.com -qumaiyao.com -qumifeng.com -quming66.com -qumingdashi.com -qumingxing.com -qumitech.com -qun.hk -quna.com -qunachi.com -qunaer.com -qunale888.com -qunar.com -qunar.ink -qunarcdn.com -qunarzz.com -qunba.com -quncrm.com -quner.com -qunfenxiang.net -qungame.com -qungong.com -qunhai.net -qunhei.com -qunhequnhe.com -qunjielong.com -qunkeng.com -qunliao.info -qunmi.vip -qunniao.com -qunqun.mobi -qunsou.co -quntuishou.com -qunxingvc.com -qunyingkeji.com -qunyiw.com -qunzou.com -quora123.com -qupai.me -qupaicloud.com -qupeiyin.com -qupf.com -qupu114.com -qupuji.com -quqi.com -quqiaoqiao.com -quqike.com -quqiuhun.com -ququabc.com -ququyou.com -ququzhu.com -qusem.com -qushimeiti.com -qushiw.com -qushixi.net -qushuba.com -qutanme.com -qutaojiao.com -qutaovip.com -qutego.com -quthing.com -qutingting.com -qutoutiao.net -qutouwang.com -qutu.com -qutuiwa.com -qutuw.com -quumii.com -quvisa.com -quwan.com -quwangming.com -quweikm.com -quweiting.com -quweiwu.com -quwenqing.com -quwenqushi.com -quwentxw.com -quwj.com -quwm.com -quword.com -quwuxian.com -quxds.com -quxia.com -quxianchang.com -quxiangtou.com -quxianzhuan.com -quxiaoyuan.com -quxier.com -quxingdong.com -quxiu.com -quxizang.com -quxuan.com -quxuetang.net -quyaoya.com -quyinginc.com -quyiyuan.com -quyouhui.net -quyuansu.com -quyundong.com -quzhiboapp.com -quzhuanpan.com -quzhuanxiang.com -quzz88.com -quzzgames.com -qv25i.xyz -qvip.net -qvkanwen.com -qvlz.com -qvpublish.com -qvxo.com -qw.cc -qw85.vip -qwdacy.com -qweather.com -qwertali.pw -qwertdd.pw -qwertgg.pw -qwgt.com -qwimm.com -qwolf.com -qwomcrm.com -qwpeo.net -qwpo2018.com -qwqk.net -qwqoffice.com -qwspcz.com -qwsy.com -qwxcs.com -qwxsw.com -qwyx66.com -qx100.com -qx1000.com -qx10086.net -qx100years.com -qx121.com -qx162.com -qx20.com -qxbnkj.com -qxbx.com -qxcdn.cc -qxcu.com -qxghost.com -qxiu.com -qxjlm.com -qxka.com -qxkp.net -qxlib.com -qxnecn.com -qxnic.com -qxnzx.com -qxrisk.com -qxs.la -qxslyfjq.com -qxswk.com -qxsxw.com -qxw.cc -qxwl21.com -qxwz.com -qxxsjk.com -qxyaoc.com -qxzc.net -qxznjy.com -qxzxp.com -qy-office.com -qy-qq.com -qy.net -qy01.com -qy1638.com -qy1815.com -qy266.com -qy435.com -qy587.com -qy6.com -qy6.net -qyaaaa.com -qyc2008.com -qycn.com -qycn.net -qycn.org -qydaili.com -qydimg.com -qydns1.com -qyec.com -qyer.com -qyerstatic.com -qyfwc.com -qyglzz.com -qygmgolf.com -qyham.com -qyhssd.com -qyi.io -qyjnxh.com -qyjpzx.com -qykh2009.com -qykj001.com -qyle1.com -qymgc.com -qynianjian.com -qyous.com -qyqzj.com -qyrb.com -qysd.net -qysfl.com -qysyyg.com -qyt1902.com -qytdesign.com -qyule.org -qyunz.com -qyvqg.com -qywl777.com -qywqc.com -qyx21.com -qyxxpd.com -qyyqyj.com -qyzc.net -qyzjc.com -qz100.com -qz123.com -qz2588.com -qz828.com -qz930.com -qz96811.com -qzamfz.com -qzav44.com -qzbbs.com -qzbigstone.com -qzbonline.com -qzbuxi.com -qzccbank.com -qzchkj.com -qzcklm.com -qzcns.com -qzdigg.com -qzdwz.com -qzfxyy.com -qzhhj.com -qzhlkj.net -qzhmzx.com -qzhne.com -qzhyxx.com -qzjkw.net -qzjlw.com -qzjzb.com -qzkey.com -qzlo.com -qznews360.com -qzobao.com -qzone.cc -qzone.com -qzoneapp.com -qzqstudio.com -qzrbx.com -qzrc.com -qzrx.net -qzshangwu.com -qzwb.com -qzxiangxiangkeji.com -qzxx.com -qzyb.com -qzze.com -qzzmt.com -qzzn.com -qzzres.com -qzzsbx.com -r-bride.com -r-s-services.com -r-tms.net -r036.com -r12345.com -r147emh.com -r1x1.com -r1y.com -r2g.net -r2yx.com -r337iz6.com -r51.net -r5k.com -r5tao.com -r77777777.com -r9t1.com -rabbitpre.com -rabbitpre.me -race604.com -racing-china.com -racktom.com -radeonfury.com -radicalmail.net -radida.com -radio1964.com -radiokm.com -radiotj.com -radiowar.org -raeblog.com -raidc.com -raidcn.com -rail-transit.com -railcn.net -rails365.net -railwayfan.net -rain8.com -rainasmoon.com -rainbond.com -rainbowcn.com -rainbowred.com -rainbowsoft.org -raindi.net -raindoe.com -raineggplant.com -rainersu.club -rainhz.com -rainjay.wang -rainmanfloor.com -rainyang.me -rainyin.com -raisecom.com -raisinsta.com -raiyi.com -rajax.me -rajjzs.com -rakinda-xm.com -ralf.ren -ramadaplaza-ovwh.com -ramostear.com -ran-wen.com -ran10.com -randellbeck.com -rangercd.com -rangnihaokan.com -ranhaer.net -ranhou.com -ranknowcn.com -ranling.com -rannabio.com -ranshao.com -rantu.com -ranwena.com -ranwenxs.com -ranyi.net -ranzhi.net -ranzhi.org -ranzhico.com -ranzy-leak.hk -ranzylock.hk -raoke.net -raonie.com -raorao.com -rap8.com -rapidppt.com -rapoo.com -rapospectre.com -rarbt.cc -rarbt.com -rarcbank.com -ras1n.me -rashost.com -raspigeek.com -rastargame.com -rata-catering.com -ratina.org -rationmcu.com -ratodo.com -ratoo.net -ratuo.com -ray-joy.com -ray4u.com -ray8.cc -raybetlink.com -raychase.net -raychien.site -raycom-inv.com -raycuslaser.com -raydonet.com -raygame3.com -raygame4.com -rayjoy.com -rayoptek.com -rayps.com -raysilicon.com -raythonsoft.com -raytoon.net -rayu.me -rayuu.com -rayyo.com -rayyzx.com -razifredz.com -razon.xyz -razonyang.com -razrlele.com -raztb.com -rb400.com -rbischina.org -rbqq.com -rbyair.com -rbz1672.com -rbzygs.com -rc.cc -rc0792.com -rc114.com -rc3cr.com -rccchina.com -rccoder.net -rcdang.com -rcdio.com -rcdn.fun -rcfans.com -rcgus.com -rclbbs.com -rcpx.cc -rcss88.com -rcuts.com -rcw0375.com -rcwl.net -rcyd.net -rczfang.com -rczp.org -rd-game.com -rd351.com -rdamicro.com -rdbom.com -rdbuy.com -rddoc.com -rdgz.org -rdidc.com -rdnsdb.com -rdplat.com -rdsdk.com -rdtoc.com -rdtuijian.com -rdwork.com -rdxmt.com -rdxw8.com -rdy.link -rdyhly.net -rdzhijia.com -rdzjw.com -rdzs.com -rdzx.net -re1d.com -reachace.com -react-china.org -react.mobi -reactjscn.com -read678.com -read8.net -read8.org -readblocks.com -readceo.com -readdsp.com -readend.net -readers365.com -readfree.net -readhb.com -readhr360.com -readhub.me -readjp.com -readlishi.com -readm.tech -readmail.net -readmeok.com -readmorejoy.com -readnovel.com -readpaul.com -readten.net -readu.net -ready4go.com -readzq.com -reaer.com -reai120.com -reaicomic.com -realclouds.org -realdatamed.com -realforcechina.com -realjf.com -reallct.com -really100.com -really100.net -reallylife.com -realmedy.com -realor.net -realqinwei.net -realsee.com -realsun.com -realtorforce.ca -realxen.com -realyer-sh.com -reasonclub.com -rebatesme.com -rebcenter.com -rebo5566.com -rebohu.com -rebooo.com -reborncodinglife.com -recaptcha.net -recgo.com -rechaos.com -rechuandao.com -recolighting.com -recordjapan.net -recovery-transfer.com -recoye.com -recuvachina.com -recycle366.com -red54.com -redatoms.com -redbaby.com -redcome.com -redcross-sha.org -redflag-linux.com -redfunding.com -redhai.com -redhome.cc -redhongan.com -redianduanzi.com -redianmao.com -redianyule.com -redianzixun.com -rediao.com -redicecn.com -redidc.com -redirector.gvt1.com -redisbook.com -redisdoc.com -redisfans.com -redisguide.com -redisinaction.com -redjun.com -rednetdns.com -redocn.com -redoop.com -redpact.com -redphon.com -redquan.com -redream.com -redrock.team -redsh.com -redshu.com -redstaraward.org -redsun-rp.com -redyue.com -redyue.org -reedii.com -reedoun.com -reeidc.com -reeiss.com -reeji.com -reekly.com -reenoo.com -reenoo.net -reeoo.com -refeng.net -refined-x.com -reflectiveego.com -reformdata.org -refractorywin.com -reg007.com -regainvip.com -regishome.com -reglogo.net -regtm.com -rehtt.com -rehuwang.com -rejoiceblog.com -rejushe.com -rekonquer.com -rekoo.com -rekoo.net -rela.me -relangba.com -relianfit.com -reloadbuzz.com -relx68.com -relxtech.com -remaijie.net -remapcity.com -remark.dance -remax-bj.com -remehealth.com -rememtek.com -remen88.com -remoteaps.com -remotedu.com -renaren.com -rencaiaaa.com -rencaijob.com -rendairen.com -rendajingjiluntan.com -rendease.com -rendefpc.com -renderbbs.com -renderbus.com -renderincloud.com -rendiyu.com -rendna.com -renfas.com -renhence.com -renhengshiye.com -renji.com -renjian.com -renjiaoshe.com -renjiyiyuan.com -renlijia.com -renliu580.com -renliwo.com -renlong1688.com -renmaiku.com -renmaitong.com -renminkaiguan.com -renniaofei.com -renping.cc -renqibaohe.com -renren-inc.com -renren.com -renren.io -renren3d.com -renrenbang.com -renrenbeidiao.com -renrenbit.com -renrenche.com -renrencou.com -renrendai.com -renrendoc.com -renrenfinance.com -renrenhuigo.com -renrening.com -renrenmoney.com -renrenso.com -renrensousuo.com -renrenstudy.com -renrentou.com -renrentrack.com -renrentui.com -renrenyee.com -renrk.com -renrousousuo.com -renrzx.com -rensheng123.com -rensheng2.com -rensheng5.com -rentiantech.com -rentixuewei.com -renwen.com -renwole.com -renwuyi.com -renxingwang.com -renyufei.com -renzha.net -reocar.com -repai.com -repaiapp.com -repaik.com -repanso.com -repian.com -repianimg.com -replays.net -rere-cdn.com -rererb.com -rerezy10.com -rerezy6.com -res0w.com -resclassaction.com -reserve-prime.apple.com -resheji.com -resistor.today -resouxs.com -resowolf.com -respect-lab.com -respondaudio.com -respusher.com -resuly.me -retalltech.com -reteng.org -retey.net -retow.com -return.net -returnc.com -reverselove.com -revvnu.com -rew65.com -reworlder.com -rewu.net -rewuwang.com -rexcdn.com -rexdf.org -rexinyisheng.com -rexsee.com -rexsong.com -rexuedongman.com -rexueqingchun.com -rexzoudesign.com -reyinapp.com -reyoo.com -reyun.com -rezhishi.net -rf-gsm.com -rf.hk -rf.tm -rfaexpo.com -rfchina.com -rfchost.com -rfcreader.com -rfctyy.com -rfd28.com -rfdl88.com -rfdy.hk -rfeyao.com -rffan.info -rffanlab.com -rfhhzx.com -rfidcardcube.com -rfidchina.org -rfidtech.cc -rfk.com -rfmwave.com -rfsister.com -rfthunder.com -rg950.com -rgb128.com -rgdhgdf.com -rgfc.net -rgoo.com -rgrcb.com -rgslb.com -rguidemetro.com -rgyun.com -rgznworld.com -rh98.com -rhce.cc -rhebank.com -rhhz.net -rhjyw.com -rhkj.com -rhsj520.com -rhusen03.com -rhy.com -rhyjcy.com -rhyme.cc -ri-china.com -riaway.com -ribaoapi.com -ribaow.com -ribenbang.com -ribencun.com -ribenshi.com -riboseyim.com -ricebook.com -ricequant.com -rich-futures.com -rich-healthcare.com -richba.com -richeninfo.com -richiecn.com -richkays.com -richong.com -richtj.com -ricklj.com -rickyid.com -rickysu.com -ricterz.me -rightknights.com -rightpaddle.com -rigol.com -rigouwang.com -riitao.com -riji001.com -rijigu.com -rijiwang.com -riju.tv -rijutv.com -rilvtong.com -rimiedu.com -rincon-mora.com -ringdoll.com -rinlink.com -rippleos.com -riscv-mcu.com -risecd.net -risecenter.com -risechina.org -riselinkedu.com -risenb.com -risencn.com -risesoft.net -risfond.com -rishao.com -risheng888.com -rishiqing.com -rishuncn.com -riskivy.com -risunsolar.com -riswing.com -ritaipaper.com -ritarpower.com -ritayzy.com -ritering.com -rivennero.com -rivergame.net -riwee.com -riyuba.com -riyuexing.org -riyuezhuan.com -riyuezw.com -riyugo.com -riyujob.com -riyurumen.com -rizhao9.com -rizhaochuanqi.com -rizhaociming.com -rizhi.xyz -rizhiyi.com -rizhuji.com -rizi168.com -rj-bai.com -rj889.net -rjdk.org -rjghome.com -rjh0.com -rjhcsoft.com -rjkflm.com -rjoy.com -rjreducer.com -rjs.com -rjsjmbwx.com -rjsos.com -rjty.com -rjypay.com -rjzxw.com -rkanr.com -rkdatabase.com -rkeji.com -rkgaming.com -rkidc.net -rksec.com -rkvir.com -rlair.net -rlbl888.com -rlkj.com -rlwyjf.com -rlydw.com -rlyl.net -rm-static.djicdn.com -rm5u.com -rm96.com -rmbtimes.com -rmcjzz.com -rmcteam.org -rmdhtyc.com -rmhospital.com -rmjtxw.com -rmjunshi.com -rmlxx.com -rmsznet.com -rmtgateway-dq10acc.com -rmttjkw.com -rmxiongan.com -rmylsc.com -rmzs.net -rmzt.com -rmzxb.com -rn-hswh.com -rnfengwo.com -rngtest.com -roadjava.com -roadoor.com -roame.net -robam.com -robei.com -roboo.com -robook.com -robot-china.com -robotedu.org -robotpark.cc -robotplaces.com -rock-chips.com -rock-lizard.org -rockbrain.net -rockemb.com -rockerfm.com -rockjitui.com -rockmanlab.com -rockmanlab.net -rockru.com -rocky.hk -rockyaero.com -rockyenglish.com -roclee.com -rocsf.org -roddypy.com -rohm-chip.com -roidmi.com -rojewel.com -rokid.com -rokidcdn.com -rokub.com -roland-china.com -rollupjs.com -rologo.com -rom100.com -romanting.com -romeng.men -romhui.com -romjd.com -romleyuan.com -romphone.net -romwang.com -romzhijia.net -romzhushou.com -romzj.com -roncoo.com -rong.io -rong24.com -rong360.com -ronganjx.com -rongba.com -rongbiz.com -rongbiz.net -rongbst.com -rongcaitek.com -rongchain.com -rongchenjx.com -rongdewang.com -rongechain.com -ronghub.com -ronghuisign.com -rongji.com -rongjinsuo.com -rongledz.com -ronglianmeng.net -rongmayisheng.com -rongnav.com -rongquaner.com -rongroad.com -rongshiedu.com -rongshu.com -rongshuxia.com -rongstone.com -rongtai-china.com -rongyaopeizi.com -rongyi.com -rongyiju.com -rongyitou.com -rongzhijia.com -rongzhitong.com -rongzhongleasing.com -rongzhongloan.com -rongzi.com -rongzibei.com -ronnylove.com -rontgens.com -roobo.com -roodoo.net -roof325.com -roogames.com -room365.com -roomse.com -roosur.com -root1111.com -rootcloud.com -rootguide.org -rootk.com -rootop.org -rootopen.com -rootzhushou.com -roov.org -ror-game.com -ros-lab.com -rosabc.com -rosaryshelties.com -rosecmsc.com -rosedata.com -roseduan.com -rosefinchfund.com -roshanca.com -rosinson.com -rossoarts.net -rossroma.com -roswiki.com -roszj.com -rotom-x.com -rouding.com -rouju.org -roukabz.com -round-in.com -roundexpo.com -roundyule.com -roushangqi.com -roushidongwu.com -rousin.com -router.fun -router.tw -routeryun.com -routewize.com -routingeye.com -rouwen.net -rouzip.com -rove.im -rowcan.com -royalpay.com.au -royole.com -royotech.com -rp-pet.com -rpg99.com -rpgmoba.com -rpo5156.com -rpsh.net -rpwtcn.com -rqcotton.com -rqi17.com -rqjrb.com -rqshbp.net -rqz1.com -rqzjzs.com -rr-sc.com -rr.tv -rr365.com -rrb365.com -rrbay.com -rrbts.org -rrcimg.com -rrcp.com -rrd.me -rrdaj.com -rrdyw.cc -rree.com -rrfed.com -rrfmn.com -rrhuodong.com -rrimg.com -rritcn.com -rrjc.com -rrjump.com -rrkf.com -rrky.com -rrkyw.com -rrl360.com -rrliuxue.com -rrmeiju.com -rrmj.tv -rrppt.com -rrr.me -rrrdai.com -rrrhteam.com -rrrrdaimao.com -rrs.com -rrscdn.com -rrsub.com -rrsub.net -rrswl.com -rrtiantang.com -rrting.net -rrtsangel.com -rrty.tv -rruu.com -rruu.net -rrxh5.cc -rrxiu.cc -rrxiu.me -rrxiu.net -rrys.tv -rrys2019.com -rrys2020.com -rrysapp.com -rrzuji.com -rrzxw.net -rs05.com -rs485.net -rs66.com -rscala.com -rscloudmart.com -rsdgd.com -rsdwg.com -rsdyy.com -rsng.net -rso.wang -rsp.ink -rsscc.com -rssmeet.com -rssmv.com -rsty77.com -rsu.su -rsw163.com -rszfg.com -rt-blend.com -rt-mart.net -rt-thread.org -rtasia.org -rtb5.com -rtbasia.com -rtcdeveloper.com -rtfcode.com -rtfcpa.com -rtfund.com -rthpc.com -rtjxssj.com -rtmap.com -rtmyjt.com -rtrrx.com -rtsac.org -rtxapp.com -rtxplugins.com -rtxuc.com -ru4.com -ruaimi.com -ruan8.com -ruandy.com -ruanfujia.com -ruanjiandown.com -ruanjianwuxian.com -ruankao.com -ruankao.org -ruanko.com -ruanman.net -ruanmei.com -ruanmou.net -ruanno1.com -ruantiku.com -ruanwen.la -ruanwenclass.com -ruanwenkezhan.com -ruanwenlala.com -ruanyuan.net -rubaoo.com -ruby-china.com -ruby-china.org -rubybrides.com -rubyconfchina.org -rubyer.me -ruchee.com -rueinet.com -rufei.ren -rufengda.com -rufengso.net -ruffood.com -rufida.com -rugao35.com -ruguoapp.com -ruhnn.com -rui2.net -ruian.com -ruibai.com -ruibaixiang.com -ruichuangfagao.com -ruicitijian.com -ruidaedu.com -ruideppt.com -ruideppt.net -ruidongcloud.com -ruidroid.xyz -ruiguandental.com -ruiguanrobot.com -ruihaimeifeng.com -ruihuo.com -ruiii.com -ruijienetworks.com -ruijiery.com -ruikesearch.com -ruilvtu.com -ruiqicanyin.com -ruiruigeblog.com -ruiscz.com -ruisizt.com -ruisky.com -ruitairt.com -ruiwant.com -ruiwen.com -ruixing.cc -ruixuesoft.com -ruixueys.com -ruixunidc.com -ruixunidc.net -ruiyang-ra.com -ruiyunit.com -ruizhiy.com -rujiazg.com -ruketang.com -rulejianzhan.com -rulesofsurvivalgame.com -rum8.perf.linkedin.com -runcome.com -runde666.net -rundejy.com -rundongex.com -runexception.com -runforrun.com -runfox.com -runhuayou.biz -runidc.com -runjf.com -runker.net -runker.online -runmang.com -runnar.com -runnerbar.com -runningcheese.com -runningls.com -runningmanzx.com -runnoob.com -runoob.com -runpho.com -runsisi.com -runsky.com -runteam.cc -runtianhotel.com -runtime.pw -runtimeedu.com -runtimewh.com -runtonggroup.com -runtronic.com -runwith.cc -runzhize.com -runzi.cc -ruochu.com -ruodian360.com -ruofan.me -ruokuai.com -ruoren.com -ruoshui.com -ruoxia.com -ruoyi.vip -ruozedata.com -ruqimobility.com -rushb.net -rushmail.com -rusinge.com -russellluo.com -russianavia.net -ruthus.com -rutisher.com -ruubypay.com -ruuxee.com -ruvar.com -ruvisas.com -ruwen5.com -ruxianke.com -ruyahui.com -ruyi.ai -ruyig.com -ruyile.com -ruyiqiming.com -ruyishi.com -ruyitianrong.com -ruyo.net -ruyu.com -ruyuexs.com -ruzw.com -rvfdp.com -rvmcu.com -rwtext.com -rwxqfbj.com -rwxwl.com -rxbj.com -rxdsj.com -rxgl.net -rxhui.com -rxian.com -rxjhbaby.com -rxjt.co -rxjy.com -rxs.cc -rxshc.com -rxys.com -ry165.com -ryanc.cc -rybbaby.com -rydth5.com -ryeex.com -ryg0212.com -ryjiaoyu.com -rylinkworld.com -rymama.com -rymooc.com -rypeixun.com -rysdline.com -rysummer.net -rytx.com -ryweike.com -rywsem.com -ryxxff.com -ryyyx.com -ryzxqp.com -rz.com -rz168.com -rzcdc.com -rzcdz2.com -rzfanyi.com -rzhuaqiangu.com -rzjrfw.com -rzlib.net -rzline.com -rznsl.com -rzok.net -rzwzg.com -rzx.me -rzxdjy.com -rzyjyl.com -s-dom.net -s-mob.com -s-ns.com -s-on-s.com -s-reader.com -s-sgames.com -s-ts.net -s.mzstatic.com -s135.com -s163.com -s1905.com -s1979.com -s1craft.com -s1s2-028.com -s2cinc.com -s3graphics.com -s4g5.com -s4yd.com -s5217.net -s575.com -s5tx.com -s60sky.com -s6qq.com -s72c.com -s8dj.com -s8j.com -s8x1.com -s8xs.com -s936.com -s95r.com -s98s2.com -s9jk.com -s9yun.com -sa-ec.com -sa-hs.cc -sa-log.com -sa20.com -saas88.com -saasruanjian.com -saasv.com -saaswaf.com -saayaa.com -sablog.net -sac-china.com -sacdr.net -sact-digital.com -sadhen.com -sadorrad.com -sae-china.org -saebbs.com -saf588.com -safe-store-md.com -safebrowsing-cache.google.com -safebrowsing.googleapis.com -safecenter.com -safecn.net -safehoo.com -safeionline.com -safejmp.com -safenext.com -safestcdn.com -safestdns.com -safewiki.org -sagetrc.com -sagocloud.com -sahcqmu.com -saibeiip.com -saibeinews.com -saibo.com -saic-gm.com -saicdt.com -saicgmac.com -saicgroup.com -saicjg.com -saicmaxus.com -saicmotor.com -saicyun.com -saiday.com -saier.me -saifou.com -saifutong.com -saigao.fun -saihuahong.com -saihuitong.com -saike.com -saikr.com -sail.name -sail2world.com -saili.science -sailingyun.com -saimogroup.com -sainacoffee.com -saintcos.hk -saintic.com -saipujianshen.com -saipujiaoyu.com -sairaicc.com -sairui020.com -saite-xdc.com -saitjr.com -saiyouedu.net -saiyunyx.com -sakway.com -saladns.com -salasolo.com -saleoilpaintings.com -salogs.com -salonglong.com -salongweb.com -salonwith.com -saltyfish.cloud -samankamyab.com -samanlehua.com -samebar.com -samhotele.com -saming.com -samirchen.com -samlog.club -samsunganycar.com -samsungfiberoptics.com -samsunghealthcn.com -samsungyx.com -samwell.net -samyaki.com -samyuong.com -samzhe.com -san-health.net -san-sheng.net -sanban18.com -sancanal.com -sanctpalace.com -sancunrenjian.org -sandaha.com -sandai.net -sandaile.com -sandbean.com -sandcomp.com -sandianzhong.com -sandingtv.com -sandslee.com -sandsresortsmacao.com -sanduoyun.com -sandworld.net -sandwych.com -sandy2.com -sanen.online -sanerer.com -sanfen.me -sanfen666.com -sanfengyun.com -sanfo.com -sanfu.com -sangfor.com -sangfor.net -sangfor.org -sangfordns.com -sangongzai.net -sangsir.com -sanguobbs.com -sanguocard.com -sanguoh5.com -sanguohero.com -sanguoinfo.com -sanguosha.com -sanguozz.com -sanhao.com -sanhaofushi.com -sanhaostreet.com -sanhe-scale.com -sanhong.org -sanhucidiao.cc -sanjiang.com -sanjiangpm.com -sanjiaoniu.com -sanjiaoshou.net -sanjiasoft.com -sanjieke.com -sanjinjiake.com -sanjueyaluosi.com -sanjun.com -sankaijian.com -sankgo.com -sankougift.com -sankuai.com -sanmaofafa.com -sanmudc.com -sannongejia.com -sannxx.com -sanpowergroup.com -sanpuzhiyao.com -sanqin.com -sanqindaily.com -sanqinyou.com -sanqiu.org -sanquan.com -sansancloud.com -sansanyun.com -sanshengcao.com -sansky.net -santaihu.com -santelvxing.com -santezjy.com -santiwang.com -santiyun.com -santongit.com -santostang.com -santsang.com -sanweimoxing.com -sanweiyiti.org -sanwen.com -sanwen.net -sanwen8.com -sanwer.com -sanxiamarathon.com -sanxiapharm.com -sanxige.com -sanxinbook.com -sanxiw.com -sanxu88.com -sanya100.com -sanyachloe.com -sanyadamei.com -sanyafz.com -sanyalacostahotel.com -sanyalove.net -sanyanblockchain.com -sanyaotc.com -sanyastar.com -sanyatour.com -sanye.cx -sanyexin.com -sanygroup.com -sanyhi.com -sanyibao.com -sanyipos.com -sanyoutj.com -sanyuanbaobao.com -sanyuantc.com -sanyuesha.com -sanzang5.net -sanzangwang.com -sanzei.com -sao.so -saohuo7.com -saoic.com -saomadang.com -saopu.com -saoso.com -saowen.net -sap-nj.com -sap1000.com -sap1200.com -sapjx.com -sapzh.com -saraba1st.com -sarft.net -sasee.org -sass.hk -sasschina.com -sasscss.com -satrip.com -saturdaysoft.com -satyam.net.in -saveen.com -savoirflare.com -savokiss.com -savouer.com -sawenow.com -sayabear.com -sayloving.com -saywash.com -sb1152.com -sb580.com -sb6189.com -sbanfu.com -sbanzu.com -sbc-mcc.com -sbc1434.com -sbc187.com -sbc398.com -sbc665.com -sbeira.com -sbgl.net -sbh15.com -sbiquge.com -sbk-h5.com -sbkk8.com -sbkk88.com -sblunwen.com -sbo8.com -sbosport9.com -sbr-info.com -sbrj.net -sbt123.com -sbwml.net -sbwxz.com -sbzj.com -sc-jiaoyu.com -sc-vis.com -sc.cc -sc.gg -sc115.com -sc119.cc -sc157.com -sc1588.com -sc1618.com -sc2c.com -sc2car.com -sc2p.com -sc2yun.com -sc666.com -sc823.com -sc946.com -scacm.com -scaffi.com -scanv.com -scarbbs.com -scarclinic-cn.com -scatwang.com -scboy.com -scbxmr.com -scbz.org -scc.ssacdn.com -scccyts.com -sccin.com -sccm.cc -sccnn.com -sccq.net -sccsfxdq.com -sccts.com -sccwz.com -scdakj.com -scdbzzw.com -scdn1e8v.com -scdng.com -scdng8js.com -scdnj3in.com -scdnl3bk.com -scdnl9cm.com -scdnmogt.com -scdno5zl.com -scdnrvy1.com -scdnucc5.com -scdnurea.com -scdnygb7.com -scdri.com -scdzmw.com -scedu.net -sceeo.com -scflcp.com -scflgc.com -scfzbs.com -scgc.net -scgckj.com -scgglm.com -scgh114.com -scgis.net -scgra.com -scgzzg.com -schengle.com -schezi.com -schkgl.com -schneidercampus.com -scholarmate.com -scholat.com -schoolcms.org -schoolgater.com -schove.com -schrb.com -schwarzeni.com -schwr.com -sci-hub.ee -sci-hub.ren -sci-hub.shop -sci-hub.tf -sci-hunter.com -sci99.com -scichina.com -scicn.net -scidict.org -sciencemeta.com -scienedit.com -scientrans.com -scies.org -scifans.com -scigy.com -scihubtw.tw -sciimg.com -scijuyi.com -scimao.com -scinno-cn.com -scinormem.com -scipaper.net -scipark.net -sciping.com -scisky.com -scistor.com -scitycase.com -sciyard.com -sciyon.com -scjimiao.com -scjjrb.com -scjtaq.com -scjyzb.net -scjzjyjc.com -scjzlyxxpt.com -sclezhu.com -sclf.org -sclinktech.com -scmenhu.com -scmeye.com -scmor.com -scmsky.com -scmylike.com -scnjnews.com -scntv.com -sco-marathon.com -scodereview.com -scoee.com -scommander.com -scomonline.net -scoregg.com -scp-wiki-cn.org -scpgroup.com -scpic8.com -scplt.com -scrdzf.com -scriptoj.com -scrmtech.com -scrsw.net -scrtf.com -scrumcn.com -scscms.com -scsdns.com -scsdzxh.org -scsgk.com -scsjnxh.org -scsstjt.com -sctaixin.com -sctbc.net -sctcmai.com -sctobacco.com -sctv.com -sctvf.com -scufida.com -scujj.com -scusec.org -scutcm.com -scutde.net -scutef.org -scutfresh.org -scutsee.com -scuvc.com -scw98.com -scweixiao.com -scwgtz.com -scwj.net -scwlylqx.com -scwy.net -scxdf.com -scxnyl.com -scxyoa.com -scycxh.com -scyl88.com -scymob.com -scyongqin.com -scyslb.com -scytyy.net -scyusuan.com -sczg.com -sczj.org -sczlb.com -sczlcts.com -sczprc.com -sczshz.net -sczsie.com -sczsxx.com -sczw.com -sczycp.com -sczyh30.com -sd-cellbank.com -sd-ex.com -sd-jtc.com -sd-sma.com -sd-xd.net -sd-ysjt.com -sd11185.com -sd173.com -sd235.net -sd5g.com -sda1.dev -sdailong.com -sdaoyou.com -sdawzm.com -sdbao.com -sdbdccq.com -sdbear.com -sdbeta.com -sdbykqn.com -sdbys.com -sdca119.com -sdchem.net -sdchina.com -sdchn.com -sdcisp.com -sdcqjy.com -sdcydl.com -sdd17.com -sddagongrubber.com -sddcp.com -sddeznsm.com -sddh.online -sddlys.com -sddxjtss.com -sde6.com -sdebank.com -sdeca.org -sdenews.com -sdeqs.com -sderp.com -sdestar.com -sdewj.com -sdey.net -sdfcxw.com -sdfengla.com -sdfhyl.com -sdfkxm.com -sdfll.com -sdfmgg.com -sdg-china.com -sdgdxt.com -sdgh.net -sdgho.com -sdglkt.com -sdgt1985.com -sdguanglu.com -sdgude.com -sdguguo.com -sdgw.com -sdgwy.org -sdhangmoguan.com -sdhk2008.com -sdhoukang.com -sdhsie.com -sdhtws.com -sdhuxiji.com -sdhxnykj.com -sdiandian.com -sdiborn.com -sdicvc.com -sdifenzhou.com -sdiread.com -sditol.com -sdj-tech.com -sdjcw.com -sdjinlan.com -sdjnwx.com -sdjr.online -sdjtcx.com -sdjushu.com -sdjyjszb.com -sdkclick.com -sdkclickurl.com -sdklh.com -sdksrv.com -sdlldj.com -sdlocw.com -sdlongli.com -sdly35.com -sdlzlib.com -sdmic.com -sdmyzsgs.com -sdnfv.org -sdnjsbc.com -sdnlab.com -sdnxs.com -sdnysc.com -sdo-shabake.com -sdo.com -sdodo.com -sdongpo.com -sdoprofile.com -sdpku.com -sdqlkr.com -sdqmy.com -sdqoi2d.com -sdrcu.com -sdrufu.com -sdsanteng.com -sdsgwy.com -sdshshb.com -sdshulifang.com -sdshyl.com -sdsjht.com -sdsmefina.com -sdssytgc.com -sdsszt.com -sdsyqz.com -sdtdata.com -sdtsrf.com -sdtuomei.com -sdtvjiankang.com -sdtxmq.com -sduod.com -sdutacm.org -sdv8dvj.com -sdwanping.com -sdwdxl.com -sdwebseo.com -sdwenlian.com -sdwgyy.com -sdwhsb.com -sdx.microsoft.com -sdxapp.com -sdxczn.com -sdxietong.com -sdxitong.com -sdxjpc.com -sdxvisa.com -sdxwy168.com -sdxyxhj.com -sdxzt.com -sdycee.com -sdyhwk.com -sdyinshuachang.com -sdyizhibi.com -sdylsc.com -sdyndcjx.com -sdynr.com -sdyuanbao.com -sdyxqy.com -sdyy.org -sdyyebh010.com -sdyypt.net -sdzbcg.com -sdzdmjg.com -sdzdsljbj.com -sdzhidian.com -sdzjsy.com -sdzk.co -se77en.cc -se7c.com -se7enzone.com -sea-group.org -sea-gullmall.com -sea789.com -seagulllocker.com -seaheart.cc -sealand-scan.com -sealand100.com -sealeadbattery.com -sealyun.com -seamanhome.com -seandou.com -seaning.com -seanxp.com -seanyxie.com -seapard.com -search1990.com -searcheasy.net -searchtb.com -seasouthgy.com -seassoon.com -seasungame.com -seavo.com -seayao.net -seayee.com -sebastianblade.com -sebigdata.com -seblong.com -sebug.net -sec-wiki.com -secaibi.com -secange.com -secbug.cc -secbug.org -secdoctor.com -secdriver.com -secfree.com -secisland.com -secist.com -seclover.com -secoo.com -secooart.com -secooimg.com -secpulse.com -secretgardenresorts.com -secretmine.net -secrss.com -secrui.com -secsilo.com -secu100.net -secun.com -securitycn.net -securityfrontline.org -securitypaper.org -secutimes.com -secwk.com -secwx.com -secye.com -sed3.com -see-far.com -see-source.com -see2know.com -seeapp.com -seebd.net -seebug.org -seebyleegee.com -seechentech.com -seecmedia.net -seecsee.com -seed-china.com -seedasdan.org -seeddsp.com -seedit.cc -seedit.com -seedland.cc -seedsufe.com -seedvd.com -seefarger.com -seegif.com -seek114.com -seekbetter.me -seekchem.com -seekfunbook.com -seekonly.net -seekoon.com -seekpetm.com -seekplay.online -seektea.net -seelvyou.com -seemmo.com -seemoread.com -seentao.com -seeqiu.net -seer520.com -seersee.com -seeseed.com -seeshentech.com -seetao.com -seetook.com -seewellintl.net -seewo.com -seexpo.com -seeyii.com -seeyon.com -seeyonoversea.com -seeyouhealth.com -seeyouyima.com -seezy.com -sefonsoft.com -segahome.com -segmentfault.com -segmentfault.net -segotep.com -segwayrobotics.com -seinfeldtv.com -seisman.info -sejai.com -sejiazu.com -sekede.net -sekorm.com -selboo.com -selfinflatingballoon.com -selfservicechina.com -selinuxplus.com -seliujs.com -sellingexpress.net -sem123.com -semgg.com -semgz.com -semicic.com -semidata.info -semiee.com -semielite.com -semiinsights.com -semiway.com -semlinker.com -sempk.com -semplus.org -semptian.com -semvseo.com -sencdn.com -sencha-china.com -send2boox.com -sendbp.com -sendcloud.net -sendcloud.org -sendocn.com -sendong.com -sends.cc -senfengg.com -sengguo.com -senguo.cc -senguo.com -sengxian.com -seniverse.com -senleo.com -senlujj.com -senmiaoschool.com -senra.me -sensate.hk -sense-hk.com -senselock.com -senseluxury.com -sensertek.com -sensetime.com -senseyun.com -sensorsdatavip.com -sensorshome.com -senszx.com -sentaijs.com -sentetuwen.com -sentsin.com -sentuxueyuan.com -senwy.com -senyuanhi.com -senyuanzhonggong.com -seo-820.com -seo-wuhan.com -seo.tm -seo123.net -seo628.com -seo8.org -seo8o.com -seoccc.com -seocun.com -seocxw.com -seodaniel.com -seofangfa.com -seohet.com -seohuizhou.com -seoniao.com -seopath.net -seopre.com -seoshenzhen.com -seosn.com -seosrx.net -seotcs.com -seotianxia.com -seoui.com -seowdw.com -seowenda.net -seowhy.com -seoxiaosai.com -seoxuetang.com -seoyu.net -seozf.com -seozhuanjia.com -seozyw.com -sepact.com -sepri.com -septicmk.com -septinn.com -septvean.com -septwolves.com -sepu.net -sequ.biz -sequoiadb.com -serholiu.com -servasoft.com -server-hold.com -serverless.ink -servicemesher.com -servicewechat.com -servingcdn.com -sesamestreetenglishchina.com -sescse.com -seseacg.com -sesier.com -sesliritim.com -seteuid0.com -settings.crashlytics.com -seuic.com -sevdot.com -sevenseas-china.com -sewise.com -sf-airlines.com -sf-bearing.com -sf-card.com -sf-companion.com -sf-express.com -sf-financial.com -sf-pay.com -sf-saas.com -sf-zs.net -sf.gg -sf007.com -sf024.com -sfacg.com -sfantree.com -sfb-100.com -sfb2c.com -sfbest.com -sfccn.com -sfcdn.org -sfddj.com -sfe68.com -sfe8.com -sfgj.org -sfgy.org -sfhfj.site -sfht.com -sfhxdfgl.com -sfile2012.com -sfitcdp.com -sfjdml.com -sfkedu.com -sfkj.vip -sflep.com -sflqw.com -sforest.in -sfpgmk.com -sfplay.net -sfwxf.com -sfyb.com -sfygroup.com -sfystatic.com -sfzj123.com -sg-micro.com -sg.work -sg0760.com -sg120.com -sg169.com -sg560.com -sg668.com -sg8.cc -sg91.net -sg92.com -sgaaw.com -sgamer.com -sgcctd.com -sgcctop.com -sgchinese.com -sgchinese.org -sgcn.com -sgcyjy.com -sgda.cc -sgdmobile.com -sge.sh -sghnny.com -sgjwb.com -sgllk.com -sglxcn.com -sgmlink.com -sgnet.cc -sgnongkang.com -sgou.com -sgshero.com -sgshuangfa.com -sgsxw.com -sguo.com -sgwk.info -sgyaogan.com -sgzhee.com -sgzm.com -sh-an.com -sh-arpm.com -sh-aurora.net -sh-baolai.com -sh-cyclerace.org -sh-decai.com -sh-deem.com -sh-dent.com -sh-dls.com -sh-eastwes.com -sh-ekeyboard.org -sh-gmc.com -sh-henian.com -sh-hilead.com -sh-holiday.com -sh-hywin.com -sh-iboran.com -sh-investment.net -sh-kaiyi.com -sh-ryjx.com -sh-service.com -sh-surface.com -sh-syh.org -sh-tangfeng.com -sh-warwick.com -sh-xinao.com -sh-yajia.com -sh-ybxhz.com -sh-yuy.com -sh-zbfm.com -sh.com -sh112.com -sh1122.com -sh414.com -sh5y.com -sh7.com -sh85gk.com -sh8y.com -sh8yyxmrk.com -sh9130.com -sh9yuan.com -sha-cun.com -sha-steel.com -sha2255.com -sha2299.com -sha2777.com -sha7000.com -sha990.com -shaanxirk.com -shabc.net -shaca.net -shachong8.com -shacumox.com -shaddockfishing.com -shadow-forum.com -shadowq.com -shafa.com -shafaguanjia.com -shahaizi.com -shaidc.com -shailema.com -shairport.com -shaisino.com -shaiwang.org -shaizai.com -shake123.com -shamiao.com -shan-san.com -shanai365.com -shanbay.com -shanbotv.com -shandagames.com -shandaz.com -shandianhuifu.com -shandianyidai.com -shandjj.com -shandongair.com -shandonghaiyang.com -shandongruixiang.com -shandongsannong.com -shandongyunpin.com -shandw.com -shang-tai.com -shang0898.com -shang168.com -shang360.com -shangbaolai.com -shangbiao.com -shangbw.com -shangc.net -shangcaifanyi.com -shangdandan.com -shangdaotong.com -shangdiguo.com -shangdixinxi.com -shangdu.com -shangdu.info -shangdumall.com -shangduo-ihome.com -shangeedu.com -shangeseo.com -shangfayuan.com -shangfox.com -shanggame.com -shanghai-air.com -shanghai-channel.com -shanghai-electric.com -shanghai-intex.com -shanghai-map.net -shanghaiairport.com -shanghaibaibian.com -shanghaiboji.com -shanghaicaiyi.com -shanghaichannel.net -shanghaiconcerthall.org -shanghaicup.com -shanghaidaily.com -shanghaidisneyresort.com -shanghaiferry.com -shanghaihino.com -shanghaiiot.org -shanghaik11.com -shanghaimart.com -shanghaimuseum.net -shanghainb.com -shanghaining.com -shanghaipower.com -shanghairanking.com -shanghairc.com -shanghairemax.com -shanghairolexmasters.com -shanghaishuangyanpi.com -shanghaitianqi114.com -shanghaixs.com -shanghaiyueshang.com -shanghaizaojia.com -shanghaizhenji.com -shangji998.com -shangjilian.com -shanglei.net -shangliancn.com -shanglin010.com -shangluotb.com -shanglv51.com -shangmayuan.com -shangmeijiu.com -shangpin.com -shangpintong.com -shangpo.com -shangpusou.com -shangpuzhan.com -shangquanquan.com -shangque.com -shangrao-marathon.com -shangshaban.com -shangshangke.me -shangshi360.com -shangshici.com -shangshu.cc -shangtao.net -shangtao360.com -shangtianapp.com -shangtongda.com -shanguansoft.com -shangusec.net -shangwu168.com -shangxiasha.com -shangxueba.com -shangxuebavip.com -shangyejihua.com -shangyekj.com -shangyexin.com -shangyexinzhi.com -shangyouze.com -shangyubank.com -shangyuer.com -shangz99991.com -shangzhibo.tv -shanhaizhanji.com -shanhe.cc -shanhu99.com -shanhuojiaoyi.com -shanhuu.com -shanhuxueyuan.com -shanjinqh.com -shankejingling.com -shanliao.com -shanlink.com -shanliulian.com -shanmao.me -shannon-sys.com -shannonai.com -shanp.com -shanpow.com -shanqb.com -shanqian.vip -shanse8.com -shanshuidan.com -shantoumama.com -shanweinews.net -shanxidiy.com -shanximuseum.com -shanxiol.com -shanxiumao.com -shanxiuxia.com -shanxuenet.com -shanyemangfu.com -shanyetang.com -shanyeyuanliang.com -shanyhs.com -shanyishanmei.com -shanyougame.com -shanzhaiba.com -shanzhaiji.com -shanzhaiwang.net -shanzhen.me -shanzhengren.com -shanzhonglei.com -shaodaren.com -shaodts.net -shaoerbc.org -shaoerbianchengwang.com -shaogood.com -shaoka5.com -shaoke.com -shaolintagou.com -shaolinwy.com -shaolinxuefei.com -shaoqun.com -shaoshilei.com -shaoxianchong.com -shaoyee.com -shaozi.info -shaozimama.com -shaphc.org -shaqing.com -shaqm.com -share-nydus.com -share1diantong.com -share2dlink.com -share2uu.com -sharecharger.com -sharecore.net -sharedaka.com -shareditor.com -sharegog.com -shareinstall.com -shareinstall.net -sharejs.com -shareoneplanet.org -sharetao.com -sharetome.com -sharetrace.com -sharevdi.com -sharewaf.com -sharewithu.com -sharing-water.com -sharkselection.com -sharpbai.com -shartu.com -shawdo.com -shawdubie.com -shawnzeng.com -shayangnala.com -shayugg.com -shayujizhang.com -shbaibai.com -shbaimeng.com -shbangde.com -shbars.com -shbbq.net -shbear.com -shbicycle.com -shbj.com -shbnrj.com -shbyer.com -shcaoan.com -shcas.net -shccineg.com -shccio.com -shchengsan.com -shchhukou.com -shchjj.com -shcljoy.com -shcngz.com -shcs2010.com -shcsdq.com -shcwbz.com -shcxzxgs.com -shd163.com -shdctp.com -shdjg.net -shdjg.org -shdjt.com -shdsd.com -shdzby168.com -shdzfp.com -she.vc -shebao.net -shebao5.com -shebao520.com -shebaotong.com -shebaoyizhan.com -shebiaotm.com -sheboo.com -sheca.com -shedejie.com -shedoor.com -shedunews.com -sheencity.com -sheepmats.com -sheepsun.com -sheetgit.com -sheeyi.com -shehrizat.com -shehuo.me -sheinet.com -sheitc.org -sheizhiwo.com -sheji.com -shejibao.com -shejiben.com -shejicool.com -shejidaren.com -shejigh.com -shejijia.com -shejijingsai.com -shejiku.net -shejipi.com -shejiqun.com -shejis.com -shejiwo.net -shejiye.com -shejizhaji.com -sheketiandi.com -shekou.com -shelive.net -shellsec.com -sheluyou.com -shelwee.com -shen-hua.com -shen1shen.com -shenanhui.com -shenbao.org -shenbiedu.com -shenbinghang.com -shenchai.com -shenchuang.com -shencut.com -shendamachine.com -shendoow.com -shendu.com -shendugho.com -shenduliaojie.com -shenduos.com -shenduwin10.com -shenduwin8.com -sheng-huo.org -shengangzc.com -shengbangshenghua.com -shengbaoluo.com -shengbenzixun.com -shengcai.net -shengcaijinrong.com -shengdan.com -shengdianhuadg.com -shengdianhuadk.com -shengfanwang.com -shenghan.org -shenghefilms.com -shengheplastic.com -shenghui56.com -shenghuojia.com -shenghuorili.com -shenghuowo.com -shenghuozhe.net -shengjing360.com -shengjinglvyou03.com -shengjoy.com -shenglei.org -shengli.com -shengmaofly.com -shengming.net -shengpay.com -shengphoto.com -shengqian51.com -shengqianlianmeng.net -shengqugames.com -shengtaidianzi.com -shengtaireli.com -shengtian.com -shengtongedu.com -shenguang.com -shengwu01.com -shengxiao.net -shengxin.ren -shengxinquan.net -shengyeji.com -shengyidi.com -shengynan.com -shengyouxi.com -shengzehr.com -shengzhaoli.com -shengzhouyigou.com -shenhaiedu.com -shenhexin.com -shenhexin.vip -shenhua.cc -shenhuagushi.net -shenjian.io -shenjianan.net -shenkexin.com -shenkong.net -shenlanbao.com -shenliancaijing.com -shenliyang.com -shenma.com -shenmadsp.com -shenmamov.cc -shenmaxs.com -shenmayouxi.com -shenmo.tech -shenmou.com -shenmouren.com -shenmufeiyang0912.com -shenou.com -shenpinwu.com -shenqhy.com -shenqibuy.com -shenquol.com -shenrennn.com -shenrongda.com -shenruan.org -shenshi111.com -shenshi777.com -shenshouwl.com -shenshouyouxi.com -shenshu.info -shenshuo.net -shenshuw.com -shentongdata.com -shenweimicro.com -shenweisupport.com -shenwud.com -shenxianyu.cc -shenxingnet.com -shenyangoffice.com -shenyecg.com -shenyehd.com -shenyequ.com -shenyongxiang.com -shenyou.tv -shenyunlaw.com -shenzan.com -shenzaole.com -shenzhekou.com -shenzhen-world.com -shenzhenair.com -shenzhenmarathon.org -shenzhenshouxin.com -shenzhenshui.com -shenzhentong.com -shenzhentour.com -shenzhenware.com -sheqjx.com -shequfu.com -shequfu.net -shequnguanjia.com -sher.vip -sherc.net -sheshui.com -sheui.com -sheup.net -shevdc.org -shexiannet.com -sheyi8.com -sheying001.net -sheyingtg.com -shezhan88.com -shfangshui.com -shfcw.com -shfdyk.com -shfft.com -shfilmmuseum.org -shfinancialnews.com -shfq.com -shfrp.com -shftth.com -shgaaz.com -shgao.com -shgaoxin.net -shgci.com -shgjj.com -shgsic.com -shgskj.com -shgyg.com -shhanqiao.com -shhbm.com -shheywow.com -shhglj.com -shhgzf.com -shhonghu.com -shhorse.com -shhssts.com -shhuangding.com -shhuayi.com -shhuihai.com -shhuu.com -shhws.com -shhxf119.com -shhxzq.com -shhyhy.com -shhzcj.com -shi-ci.com -shi-ming.com -shi78.com -shibeike.com -shibeiou.com -shibor.org -shicai.biz -shicaidai.com -shicaids.com -shichangbu.com -shichuedu.com -shici.store -shicimingju.com -shicishe.com -shiciyun.com -shida66.com -shidaedu.vip -shidaipinpai.com -shidaiyuhu.com -shidapx.com -shidastudy.com -shidi.org -shidiao136.com -shidiao18.com -shidz.com -shielday.com -shifee.com -shifen.com -shifen1.com -shifendaojia.com -shifeng.com -shifenkafei.com -shifenyuedu.com -shigaoshan.com -shigoog.com -shiguangkey.com -shiguangxu.com -shiguanvip.com -shihangwifi.com -shihaoguoji.com -shiid.com -shij001.com -shijiala.com -shijian.cc -shijianla.com -shijiaok.com -shijibenteng.com -shijicloud.com -shijie2.com -shijiebang.com -shijiebao.vip -shijieditu.net -shijiehuarenbao.com -shijiemap.com -shijiemingren.com -shijieqp.com -shijieshangzuihaodeyuyan.com -shijiexia.com -shijieyouxi.com -shijieyunlian.com -shijihr.com -shijihulian.com -shijiong.com -shijiudao.com -shijuba.com -shijue.me -shijueju.com -shijuew.com -shikang.net -shikee.com -shiku.co -shilawyer.com -shileizcc.com -shilian.com -shilian.net -shiliancj.com -shilipai.net -shilitie.net -shiliupo.com -shiliyoupin.com -shimano-fishchina.com -shimaosc.com -shimchunge.com -shiminjiaju.com -shimo.im -shimo.run -shimodev.com -shimolife.com -shimonote.net -shineenergy.com -shinelon.com -shinemediaworld.com -shinerayad.com -shineu.com -shinewing.com -shineyie.com -shingle.me -shinguang.com -shinianonline.com -shiningmidas.com -shinsoukun.com -shinybbs.com -shinybbs.info -shinycg.com -shinyway.org -shiove.com -ship56.net -shipengliang.com -shipgce.com -shiphr.com -shipping4me.com -shipsc.org -shiptux.com -shipuxiu.com -shipxy.com -shiqi.me -shiqichan.com -shiqichuban.com -shiqidu.com -shiqu.com -shiqumao.com -shiqutech.com -shishagame.com -shishangfengyun.com -shishike.com -shisongya.com -shisuint.org -shit.name -shitac.com -shitianxia.vip -shitibaodian.com -shitongaf.com -shitou.com -shitouboy.com -shitourom.com -shiwan.com -shiwangyun.com -shiweisemi.com -shiwenhua.org -shixian.com -shixiaojin.com -shixibiaozhi.com -shixijob.net -shixinhua.com -shixiong.name -shixiseng.com -shixiu.net -shixiu.org -shixun.co -shixunsuda.com -shixunwang.net -shixunwl.com -shiyan.com -shiyanbar.com -shiyanbar.net -shiyanbbs.com -shiyanhospital.com -shiyanjia.com -shiyanlou.com -shiye.org -shiyebian.net -shiyebian.org -shiyi.co -shiyi11.com -shiyibao.com -shiyicunxiao.com -shiyiyx.com -shiyongjun.biz -shiyousan.com -shiyu.pro -shiyue.com -shiyuegame.com -shiyunlaile.com -shiyunwatch.com -shiyunwulian.xyz -shizhuonet.com -shizila.com -shjdc.com -shjdceo.com -shjgdcl.com -shjgu.com -shjgxy.net -shjh120.com -shjhjc.com -shjingyuan.net -shjjmc.com -shjob.work -shjoycity.com -shjsit.com -shjt.net -shjxfc.com -shkegai.net -shkkl.com -shkuangjing.com -shkypump.com -shl56.com -shlandscape.com -shlawserve.com -shlcd.com -shld.com -shlea.org -shlitree.com -shlll.net -shlmth.com -shlpk.com -shlungu.com -shluolang.com -shmama.net -shmarathon.com -shmds-edu.com -shmds.com -shmedia.tech -shmet.com -shmetro.com -shmiaosai.com -shmljm.com -shmog.org -shmulan.com -shmusic.org -shmuzu.com -shmxcz.org -shmy365.com -shmyad.com -shmyapi.com -shmylike.co -shmylike.com -shnaer.com -shnb12315.com -shncsl.com -shnczq.org -shneweye.com -shnosbbs.com -shnsyh.com -shnti.com -shnupps.com -shoasis.net -shobserver.com -shockerli.net -shoegaze.com -shoeshr.com -shojo.cc -shokan.org -shokw.com -shootmedia.net -shop.samsung.com -shop123.com -shop2255.com -shop2cn.com -shop987.net -shopbackdrop.com -shopbop.ink -shopchaoren.com -shopin.net -shopj.net -shopjyh.com -shoplineimg.co -shopmaxmb.com -shopnc.net -shoprobam.com -shopvcc.com -shopxo.net -shopyy.com -shortof.com -shou555.com -shoubanjiang.com -shoubiaobaojia.com -shouce.ren -shouchaobao.vip -shoucheng123.com -shouchengdl.com -shoucw.com -shoudayy.net -shoudian.com -shoudian.info -shoudian.org -shouduit.com -shoudujuchang.com -shoudujuchangcn.com -shoudurc.com -shoufm.com -shougongke.com -shouhome.com -shouhoubang.com -shouji.com -shouji10086.com -shouji315.org -shouji56-img.com -shouji56.com -shoujibao.net -shoujiduoduo.com -shoujihuifu.com -shoujikanshu.cc -shoujimi.com -shoujitouping.com -shoujiw.com -shoujiwan.com -shouker.com -shouliwang.com -shouluo.me -shoumeinvren.com -shoumizhibo.com -shouqianba.com -shouqiev.com -shouqu.me -shoutao.biz -shouxi.com -shouxi88.com -shouxibet.com -shouxieti.com -shouxintec.com -shouyao.com -shouyeren.org -shouyihuo.com -shouyou.com -shouyouba.net -shouyoubus.com -shouyoucdn.com -shouyoujz.com -shouyouqianxian.com -shouyouribao.com -shouyoutan.com -shouyoutv.com -shouyouyou.com -shouyouzhijia.net -shouzan365.com -shouzhang.com -shouzhangapp.com -shouzhou365.com -shouzhuanfa.com -shouzhuanzhidao.com -shovesoft.com -show160.com -showapi.com -showapk.com -showchina.org -showcome.net -showdesk.io -showdoc.cc -showeb20.com -showerlee.com -showfrank.com -showing9.com -showji.com -showjoy.com -showjoy.net -showmebug.com -showself.com -showstart.com -showxiu.com -showxue.com -showxue.org -showyear.com -showyu.com -shoyoo.com -shpanli.com -shpans.com -shpanyou.com -shpd.net -shpgt.com -shpgx.com -shphouse.com -shphschool.com -shppa.net -shqcplw.com -shqi7.net -shqingzao.com -shqlty.com -shqmxx.com -shqswlgs.com -shqxp.com -shrail.com -shrca.org -shrcb.com -shrcdy.com -shrenqi.com -shrinkablesleeve.com -shrobotpark.com -shsaic.net -shsbnu.net -shsby.com -shsbzl.com -shsci.org -shscxh.net -shsee.com -shshilin.com -shsihua.com -shsipo.com -shsixun.com -shsjb.com -shsjdkt.com -shskapp.com -shsot.com -shspark.com -shspdt.com -shssp.org -shsunedu.com -shsxjy.com -shtbmy.com -shtdgj.com -shtdsc.com -shtefu.com -shtengshi.com -shtennis.org -shtfqx.com -shtianhe.cc -shtic.com -shtimg.com -shtion.com -shtml.net -shtrhospital.com -shtwjiebao.com -shu-ju.net -shu163.com -shuaacg.com -shuabuapp.com -shuadanfu.com -shuai.so -shuai.win -shuaibo.wang -shuaigay.com -shuaigay.nl -shuaigay1.com -shuaigeshe.com -shuaigetupian.com -shuaihuajun.com -shuaiming.com -shuainiba.com -shuaishou.com -shuaishouzhuang.com -shuaitong.vip -shuajb.com -shuaji.com -shuaji.net -shuajibang.net -shuajibao.com -shuajizhijia.net -shuame.com -shuanghao-cn.com -shuanghui.net -shuangkuai.co -shuanglicrane.com -shuangtao.com -shuangtv.net -shuangxian.com -shuangxinhui.com -shuangyuejn.com -shuangzan.com -shuangzheng.org -shuanshu.com -shuanyue.tech -shuashuaapp.com -shuazhibo.com -shubao201.com -shubao29.com -shubao95.com -shubaodd.com -shubulo.com -shubuzi.com -shucaiguaguo.com -shucaiwenshidapeng.com -shucaixiaoshuo.com -shuchengxian.com -shuchongread.com -shucong.com -shudaizi.org -shudan.vip -shudaxia.com -shudc.com -shuerjia.com -shufa.com -shufaai.com -shufabao.net -shufadashi.com -shufafin.com -shufagu.com -shufaji.com -shufami.com -shufashibie.com -shufawu.com -shufazidian.com -shufaziti.com -shufe.com -shuge.net -shuge.org -shugoo.com -shuguanghuayuan.com -shuguanxs.com -shuhai.com -shuhaidata.com -shuhaisc.com -shuhaitz.com -shuhegroup.com -shuhua66.com -shuhuang.la -shuhuangge.org -shuhuangla.com -shui-mai.com -shui.org -shui12366.com -shui2014.com -shuicai.cc -shuicao.cc -shuichachong.com -shuichan.cc -shuichan51.com -shuichuyu.com -shuidichou.com -shuididabingchou.net -shuidigongyi.com -shuidihuzhu.com -shuidihuzhu.net -shuidike.com -shuidishuju.com -shuidixy.com -shuiguo.com -shuihougongzi.com -shuihulu.com -shuihuoibm.com -shuijing100.com -shuijingcn.com -shuijingka.com -shuijingwanwq.com -shuijingwuyu.com -shuiku.net -shuiliaosheji.com -shuimiao.net -shuimoyuan.com -shuimujiaju.com -shuimushequ.com -shuinankeji.com -shuini.biz -shuipingzuo.com -shuiqian.cc -shuiwushi.net -shuixyh.com -shuiyinbao.com -shuiyoucam.com -shuizhiyuncaishui.com -shuizilong.com -shujike.com -shuju.net -shujuba.net -shujubang.com -shujubo.com -shujucun.com -shujupie.com -shujutang.com -shukeba.com -shukeju.com -shukoe.com -shukongwang.com -shukuai.com -shuland.com -shulb.com -shuliao.com -shulidata.com -shulihua.net -shuliyun.com -shuma2.com -shumahezi.com -shumeipai.net -shumeipaiba.com -shumenol.com -shumensy.com -shumiao.com -shumiimg.com -shumil.co -shumil.com -shumilou.com -shumilou.org -shumo.com -shundecity.com -shunderen.com -shunfalighting.com -shunmi.com -shunong.com -shunshikj.com -shunvzhi.com -shunwang.com -shunye.com -shunyiqu.com -shuo6.com -shuo66.com -shuoba.org -shuobao.com -shuoboku.com -shuomingshu.net -shuomingshuku.com -shuosanguo.com -shuosc.org -shuoshuo4.com -shuoshuo9.com -shuoshuokong.com -shuoshuokong.org -shuotcm.com -shuotiancn2012.com -shuotoutiao.com -shuotxts.com -shuowan.cc -shuowan.com -shuowan.net -shuqi.com -shuqiapi.com -shuqiread.com -shuqireader.com -shuqistat.com -shuquge.com -shuqun.com -shuqw.com -shuren100.com -shurenbang.net -shurenjt.com -shurenyun.com -shushangyun.com -shushao.com -shushi100.com -shushihome.com -shushubuyue.net -shusw.com -shuti.com -shuttle.co -shuwangxing.com -shuwulou.com -shuxiao.wang -shuyang.tv -shuyangba.com -shuyfdc.com -shuyong.net -shuyue.cc -shuyuewu.co -shuyun.com -shuzhiduo.com -shuzibao.com -shuziju.com -shuzixiaoyuan.com -shuziyinpin.com -shvlee.com -shwcfck.com -shwdbjgs.com -shweiya.com -shwglm.com -shwpbbs.com -shwqjx.com -shws.org -shwsg.net -shwyky.net -shxb.net -shxbe.com -shxf.net -shxhgzf.com -shxiaoran.com -shxibeiquanshe.com -shxt.com -shxwcb.com -shy99.com -shyacz.com -shyanke.com -shydjscl.com -shyestar.com -shyfci.com -shygc.net -shyhhema.com -shyingfu.net -shyjad.com -shykx.com -shykz123456.com -shymte.com -shyonghui.xyz -shyouai.com -shyouth.net -shyqxxy.com -shyrcb.com -shyuanting.com -shyunwei.net -shyuzhai.com -shyxcm.com -shyxfdc.com -shyxwz.com -shyywz.com -shyzsd.com -shzbc.com -shzbh.com -shzbhj.com -shzcgs.org -shzf.com -shzfzz.net -shzgd.org -shzgfjz.com -shzgh.org -shzh.net -shzhangji.com -shzhanmeng.com -shzhiyingedu.com -shzhyx.com -shzixu.com -shzq.com -shzsun.com -si-en.com -si-in.com -si.cdn.dell.com -si0769.com -si9377.com -siaedu.net -siaoao.com -sias-sha.com -sibida.net -sibub2c.com -sibumeirongyi.com -sic.hk -sicheng.net -sicher-elevator.com -sichina.com -sichuan163.com -sichuanair.com -sicimano.com -sicong.wang -sidatz.com -siddim.com -sidfate.com -siecc.org -sifalu.com -sifangguo.com -sifangvideo.com -sifayun.com -siff.com -sifive-china.com -sifou.com -sifve.com -sigchina.com -sightp.com -siglent.com -siglff.com -sigmachip.com -sigmamed.net -sigmoblive.com -sigu.cc -sigu.me -siguady.com -sigujx.com -siguoya.name -sigure.xyz -sigvc.org -sihai-inc.com -sihaidj.com -sihaimg.com -sihaishuyuan.com -sihaitv.com -sihaiyijia.com -siheal.com -sihuanpharm.com -sihuida.net -sihuisoft.com -siii.xyz -siiic.com -siilu.com -sijiaomao.com -sijifengxing.com -sijijun.com -sijinchuanbo.com -sijitao.net -sike.cc -sikiedu.com -sikushu.org -sileadinc.com -silenceper.com -silianmall.com -siliaobaba.com -siliaokelijixie.com -siliaoycw.com -siling.com -silingge.com -silkpresent.com -silkroadtechnologies.com -silksong.me -sillydong.com -silucar.com -silucg.com -siludao.com -siluecai.com -siluke.cc -siluke.com -siluke.la -siluke.tw -silukeke.com -silusheji.com -siluwu.com -silverfox-cn.com -silverlight.dlservice.microsoft.com -silverlighter.net -silversand.net -sim.djicdn.com -simapple.com -simayi.org -simba.pro -simcf.cc -simcom.com -simcomm2m.com -simcu.com -simengadx.com -simiam.com -simici3.com -simiki.org -simingtang.com -simon96.online -simope.com -simp.red -simperfect.com -simple-is-better.com -simpledatas.com -simplexue.com -simplezs.com -simu800.com -simul-china.com -simulway.com -simuwang.com -simwe.com -simxhs.com -sina.com -sina.lt -sina.net -sinaapp.com -sinacdn.com -sinacloud.com -sinacloud.net -sinaedge.com -sinahk.net -sinahlj.com -sinaif.com -sinaimg.com -sinaluming.com -sinanet.com -sinaquyong.com -sinashow.com -sinasinasinasina.com -sinastorage.com -sinasws.com -sinauda.com -sinawallent.com -sinawap.com -sinawf.com -sincetimes.com -sindsun.com -sinesafe.com -sinforcon.com -singbon.com -singcere.net -singdown.com -singee77.com -singhead.com -singhot.com -singlecool.com -singpodcast.com -singread.com -singtaonet.com -sinhoo.org -sinmeng.com -sinmv.com -sino-corrugated.com -sino-cr.com -sino-flexography.com -sino-foldingcarton.com -sino-life.com -sino-manager.com -sino-rainbow.cc -sino-uniontrust.com -sino-us.com -sino-web.net -sinoancher.com -sinoassistance.com -sinobaron.com -sinobasalt.com -sinobasedm.com -sinoca.com -sinocars.com -sinocateringexpo.com -sinocax.com -sinoces.com -sinochem.com -sinochemb2c.com -sinochemitc.com -sinocul.com -sinoec.net -sinoef.com -sinoergy.com -sinoevin.com -sinofo.com -sinofsx.com -sinohb.com -sinohotel.com -sinohowe.com -sinohx.com -sinohydro.com -sinoicc.com -sinoinfosec.com -sinoins.com -sinointeractive.com -sinologyinstitute.com -sinolub.com -sinolube.com -sinomapping.com -sinomaps.com -sinomatin.com -sinomod.com -sinonet.org -sinooceanland.com -sinooilgas.com -sinopec.com -sinopecgroup.com -sinopechyzx.com -sinopecnews.com -sinopecsales.com -sinopecsenmeifj.com -sinopharm.com -sinopharmzl.com -sinophex.com -sinopr.org -sinosig.com -sinosiglife.com -sinoss.net -sinostargroup.com -sinosteel.com -sinotf.com -sinotn.com -sinotone.cc -sinotone.net -sinotrans.com -sinovale.com -sinovatio.com -sinovationventures.com -sinovdc.com -sinovio.org -sinovo-tech.com -sinovoice.com -sinowealth.com -sinowealth.com.hk -sinowel.com -sinoxk.com -sinsam.com -sintu.com -sinvofund.com -sinvta.com -sinyuee.com -sinzk.com -sipai.com -sipaphoto.com -sipeed.com -sipgl-lcl.com -siphrd.com -sipo-gd.com -sipo-hb.com -sipo-pesc.com -sipo-sc.com -sipo-tj.com -siposchina.com -siqiangame.com -siqiclub.com -siqiquan.org -sique.com -sir66.com -sirenji.com -siryin.com -sisen.com -sishenkuangchao.com -sishuok.com -sishuxuefu.com -sisijiyi.com -sisijp.com -sisp-china.com -siswin.com -sitcoffee.com -site-digger.com -siteapp-static.com -siteinfourl.com -sitekc.com -siterankd.com -sites120.com -sitezj.com -sithc.com -sitiaoyu.com -sitongedu.org -sitongzixun.com -sitrigroup.com -sivan.in -sivps.com -siwaman.com -siwei.me -siweidaotu.com -siweidaoxiang.com -siweiearth.com -siweikongjian.net -siweiw.com -siwuprint.com -sixflower.com -sixianchina.com -sixiang.im -sixiangguo.net -sixiju.com -sixstaredu.com -sixtu.com -sixu.life -sixuexiazai.com -sixunited.com -siyaedu.net -siyanhui.com -siyuan.cc -siyuanedu.com -siyuanren.com -siyuefeng.com -siyunxi.com -siyuweb.com -sizeofvoid.net -sizuo.com -sj-lawyer.com -sj11hb.com -sj123.com -sj133.com -sj33.net -sj3w.com -sj88.com -sj96615.com -sj998.com -sjawards.com -sjbzx.com -sjcomic.com -sjdzp.com -sjdzp.net -sjetdz.com -sjfkai.com -sjfpro.com -sjfzxm.com -sjgnskf.com -sjhcip.com -sjhfrj.com -sjhgo.com -sjhl.cc -sjhy.net -sjmdh.com -sjmeigao.com -sjmxx.com -sjono.com -sjpcw.com -sjq315.com -sjqkd.com -sjrwzz.com -sjsbk.com -sjshw.net -sjsydq.com -sjtiantang.com -sjtickettech.com -sjtug.org -sjtujr.com -sjtxt.com -sjtxt.la -sjtype.com -sju56.com -sjvi.net -sjwtlm.com -sjwxzy.com -sjwyx.com -sjxinxiwang.com -sjxs.la -sjxyx.com -sjybsc.com -sjycbl.com -sjyst.net -sjytech.com -sjyx.com -sjyxt.com -sjyy1688.com -sjyyt.com -sjz.cc -sjzbasha.com -sjzbwx.com -sjzcmw.com -sjzcsw.com -sjzdbs.com -sjzhu.com -sjzhushou.com -sjziyuan.com -sjzkaitai.com -sjzkz.com -sjzlg.com -sjzlgz.com -sjzmama.com -sjznews.com -sjzptoo.com -sjzqcrl.com -sjzsidadianji.com -sjztd.com -sjzwww.com -sjzxtsh.com -sjzyu.com -sjzyyt.com -sjzyz.net -sjzz.cc -sjzzimu.com -sk163.com -sk1999.com -sk2game.com -skatehere.com -skcto.com -skdlabs.com -skeo.net -sketchchina.com -sketchchina.net -sketchcn.com -sketchui.net -sketchupbar.com -sketchupbbs.com -skg.com -skieer.com -skight.com -skinme.cc -skinpp.com -skip-links.com -skiy.net -skjcsc.com -sklhjx.com -sklinux.com -skllmd.com -sklse.org -sklxsj.com -skomart.com -skongmx.com -skrshop.tech -sks7.com -sksdwl.com -skusoft.com -skwl.org -skwo.net -sky-deep.com -sky-fire.com -sky-planning.net -sky003.com -sky1shop.com -skyaicdn.com -skyallhere.com -skyao.io -skybig.net -skybluead.com -skybluek.com -skycaiji.com -skycloudsoftware.com -skycn.com -skycn.net -skydust.net -skyeaglee.com -skyfollowsnow.pro -skyfont.com -skyfox.org -skygho.com -skyheng.com -skyju.cc -skylerzhang.com -skyliteapi.com -skylook.org -skymobiapp.net -skymoons.com -skymoons.net -skynj.com -skype-china.net -skyqzone.com -skyrivers.org -skyrj.com -skyrover.me -skysea.com -skysgame.com -skysrt.com -skyts.net -skytv.cc -skyue.com -skywhat.com -skywldh.com -skyworth-ac.com -skyworth-ai.com -skyworth-cloud.com -skyworth-ea.com -skyworth-mould.com -skyworth-qx.com -skyworth.com -skyworthbox.com -skyworthdigital.com -skyworthds.com -skyworthiot.com -skyworthlighting.com -skyxinli.com -skyyin.org -sl-360.com -sl088.com -sladjust.com -slanissue.com -slanmedia.com -slatic.net -slchos.com -sld-cctv.com -sldxcx.com -sleepboy.com -slegetank.com -slertness.com -slfwq.com -slghyd.com -slicercn.com -slieny.com -slimtheme.com -slink8.com -slinli.com -slinuxer.com -sliu.info -sljkj.com -sljypt.com -slkj.org -slksy.com -sllai.com -slmbio.com -slmwp.com -slogra.com -slooti.com -slpchelp.com -slpi1.com -slrbs.com -slready.com -slsteel.com -slswx7.com -slupdate.dlservice.microsoft.com -slvdy.com -slwh-dfh.com -slwswu.com -slwwedding.com -slzsxx.com -slzww.com -sm-check.com -sm-cq.com -sm-img1.com -sm-img2.com -sm-img3.com -sm-img4.com -sm-img5.com -sm160.com -sm160.net -sm688839.com -sm96596.com -smallk.net -smallpdfer.com -smallstep.vip -smallxu.me -smarch.com -smarchit.com -smart-idc.net -smart-rise.com -smart4e.com -smartbiyun.com -smartcityzhejiang.com -smartdeep.com -smartdot.com -smartedm.com -smartemple.com -smartermicro.com -smartfactory-expo.com -smartgaga.com -smartgeek.vip -smartgslb.com -smarthey.com -smarthomecn.com -smartisan.com -smartisanos.com -smartleon.net -smartlifein.com -smartlinku.com -smartmidea.net -smartoct.com -smartpigai.com -smartproxy.me -smartqian.com -smarts.online -smartsenstech.com -smartshe.com -smartsteps.com -smartstudy.com -smartwebee.com -smartx-cn.com -smartx.com -smartyao.com -smarun.com -smaryun.com -smaty.net -smbaike.com -smbais.com -smbinn.com -smbxw.com -smc18.com -smc3s.com -smd88.com -smdcn.net -smdiban.net -smdmark.com -smdy66.com -sme8718.com -smebb.com -smejs.com -smemo.info -smeoa.com -smesun.com -smfsgs.com -smfyun.com -smggw.com -smgif.com -smgstar.com -smhdoto.com -smianet.com -smics.co -smics.com -smil888.com -smilec.cc -smilejay.com -smilingwhitebear.com -smiseo.com -smjbo.com -smjyfx.com -smkmp.com -smmy365.com -smo-clinplus.com -smo-software.com -smohan.net -smokeliq.com -smoothgroup.cc -smovie168.com -smpeizi.com -smppw.com -sms9.net -smsbao.com -smshx.com -smskb.com -smsx.org -smsyun.cc -smszf.com -smt-dip.com -smt-job.com -smtcdns.com -smtcdns.net -smtchinamag.com -smtcl.com -smth.org -smthome.net -smtiger.com -smtsvs.com -smtsvspay.com -smtu.cc -smtvip.com -smucdn.com -smudc.com -smwenxue.com -smxdiy.com -smxgjj.com -smxs.com -smy01.com -smyfinancial.com -smyhvae.com -smyx.net -smzdm.co -smzdm.com -smzdmimg.com -smzdwan.com -smzwgk.com -smzy.com -sn-u.com -snai.edu -snail.com -snail007.com -snailgame.net -snailshub.com -snailsleep.net -snailyun.com -snapemoji.net -snasn.com -snbkf34.com -sncdental.com -sncoda.com -sndhr.com -sndo.com -sneac.com -sneakerhz.com -sneia.org -sngdxsn.com -snh0048.com -snh48.com -snh48club.com -sniec.net -snieri.com -snifast.com -sniffercoin.com -snipe-stock.com -snjairport.com -snjbs.com -snjjiu.com -snjrsks.com -snnd.co -snobten.com -snooda.com -snor-china.com -snowballsecurities.com -snowballtech.com -snowdream.tech -snrat.com -snren.com -snrtv.com -snrunning.com -sns.io -snsbao.com -snsfun.cc -snsfun.com -snsii.com -snsqw.com -snssdk.com -snsyx.com -snto.com -snuoen.com -snupg.com -snwx3.com -snwx8.com -snwxn.com -snxiaowai.com -snxw.com -snyu.com -snzfj.net -snzgy.com -snzhz.com -so-a.net -so-b.com -so-love.com -so-t.net -so-voioe.com -so-w.com -so.com -so147.com -so369.net -so5566.com -so8848.com -soarwatch.com -sob2b.cc -soba8.com -sobaidupan.com -sobanks.com -sobeautiful-wtbbs.com -sobeian.com -sobeycache.com -sobeycloud.com -sobot.com -sobug.com -sobuhu.com -socalzombiewalk.com -socang.com -socansoft.com -socay.com -socchina.net -sochengyi.com -sochips.com -socialark.net -socialbeta.com -socialfishface.com -socialjia.com -socomic.com -socool-tech.com -socsight.com -socvista.com -sod99.com -sodalife.xyz -sodao.com -sodc8.com -sodexo-cn.com -sodhef.com -sodino.com -sodocloud.com -sodocs.net -sodu.cc -sody123.com -soeasysdk.com -soeol.com -sofabiao.com -sofang.com -sofasofa.io -sofastack.tech -sofi-tech.com -sofreight.com -soft10.com -soft128.com -soft2005.com -soft50.com -soft5566.com -soft568.com -soft6.com -soft778.com -soft78.com -soft808.com -soft8899.com -softabc.com -softanchorinsight.com -softbanks.net -softbar.com -softbingo.net -softgostop.com -softhead-citavi.com -softhome.cc -softhy.net -softparkinfo.com -softtest.com -softwarechn.com -softwarekeyclub.com -softweek.net -softwelt.com -softwhy.com -softwincn.com -softxz.net -softyevents.com -softznz.com -sogaa.net -sogame8.com -sogeci.net -sogimall.net -sogo.com -sogoke.com -sogood360.com -sogou-inc.com -sogou-op.org -sogou.com -sogou2.com -sogoucdn.com -sogouw.com -sogouwenwen.com -soharp.com -soho-yiming.com -soho3q.com -sohochina.com -sohocute.com -sohonow.com -sohotask.com -sohovark.com -sohu-inc.com -sohu.com -sohu.net -sohucs.com -sohuhistory.com -sohuns.com -sohusce.com -sohuu.com -soicp.com -sojex.net -sojiang.com -sojiang.net -sojianli.com -sojson.com -sojump.com -sojump.hk -sokoban.ws -sokoyo-rj.com -soku.com -sokutu.com -solarbe.com -solaridc.com -soldierstory-toys.com -soleilneon.com -solepic.com -solezy.me -solidot.org -soliloquize.org -solo-launcher.com -solochex.com -solodonna.world -solosea.com -solotoon.com -solution9.net -solvso.com -solvyou.com -somanhua.com -somao123.com -somdom.com -someabcd.com -somebus.net -somecoding.com -someet.cc -someibo.com -somepen.com -somic.cc -somo.so -somode.com -somsds.com -sonald.me -sonceo.com -songanjun.com -songboy.net -songchuan12345.com -songcn.com -songguo7.com -songhaifeng.com -songhaoyun.com -songhaozhi.com -songhengnet.com -songjiayang.com -songjingmo.com -songker.com -songkun.me -songlei.net -songluhome.com -songqili.net -songqinedu.com -songqinnet.com -songruhui.com -songsgames.com -songshitang.com -songshizhao.com -songshu.cc -songshudiandian.com -songshuhui.net -songshushan.com -songshushuo.com -songsongruanwen.com -songsongxiongdi.com -songsongyingxiao.com -songsongyun.com -songtaste.com -songxiaocai.com -songyang.net -songyanjiaye.com -songyi.net -songyongzhi.com -songyuan163.com -songzhaopian.com -songzi100.com -songziren.com -sonhoo.com -sonhoo.net -soniu.net -sonkwo.com -sonkwo.hk -sonnewilling.com -sontan.net -sonysdf.com -sonyue.com -soobb.com -soocang.com -sooele.com -soogif.com -soojs.com -sooker.com -soolco.com -soomal.com -soonwill.com -soonyo.com -sooopu.com -soopat.com -soopay.net -sooshu.net -soosmart.com -sootoo.com -sootuu.com -sooxue.com -sooyooj.com -sooyuu.com -soozhu.com -sopaimai.com -sopanbar.com -sopanxia.com -sopdr.com -soperson.com -soppt.com -sopuning.com -soq.com -soqicrm.com -soquair.com -sorazone.com -sorpack.com -sos919.com -sosaw.com -sosdx.com -sosg.net -soshoo.com -soshoulu.com -soshuwu.com -sosidc.com -soso.com -sosoapi.com -sosobtc.com -sosody.net -sosohaha.com -sosomp.com -sosoo.net -sosoq.org -sosorank.com -sososteel.com -sosotec.com -sosotirp.com -sosowan.com -sosowenwen.com -sosoxian.com -sosoyunpan.com -sosoyy.com -sosuo.name -sotemall.com -sothink.com -sotuiwang.com -sotwm.com -sou-yun.com -sou94.com -souaiche.com -souaus.com -soubct.com -soucai.com -souche-fin.com -souche-inc.com -souche.com -soucod.com -soucomccs.com -soudaila.com -soudao.com -soudoc.com -souduanzu.com -souebao.com -soufang.com -soufoo.com -soufuli.net -soufun.com -soufunimg.com -souge.cc -sougoulvyou.com -sougu001.com -souho.cc -souho.net -souhu.com -souid.com -souidc.com -souidc.org -soujianghu.com -soukecheng.net -soukf.com -soukuren.com -soulady.net -soulapp.me -souldee.com -soulgame.mobi -souluo.net -soulv.com -soupan.info -soupf.net -soupian.org -soupingguo.com -soupis.com -soupu.com -soupu.org -soupv.com -souqian.com -souqiu8.com -souqiwang.net -souqupu.com -source.tutorabc.com -source3g.com -sourcecodecap.com -sourcedev.cc -sourcejoy.com -sousea.com -soushai.com -soushuking.com -sousou.com -sousoudus.com -soutaowang.com -southbeauty.com -southbeautygroup.com -southcn.com -southei.com -southernfund.com -southgis.com -southmoney.com -southnews.cc -southnews.net -southseagy.com -southzw.com -soutu123.com -soutudi.so -souutu.com -souvr.com -souwifi.com -souwoo.com -souxue8.com -souxuexiao.com -souya.com -souyi.cc -souyidai.com -souyue.mobi -souyunku.com -sov5.com -soven.com -sovxin.com -sowang.com -sowangpan.com -sowcar.com -soweather.com -sowerclub.com -sowin.com -sowu.com -soxs.cc -soxsok.com -soxuxu.com -soyao.me -soyep.com -soyim.com -soyobo.com -soyohui.com -soyouit.com -soyoung.com -soyouso.com -soyuli.com -soyunion.com -soyunpan.com -sozhen.com -sp.cc -sp588.cc -sp588.net -sp84.com -sp910.com -space1688.com -spacechina.com -spacesystech.com -spacexlanding.com -sparepart168.com -spark-app.store -spark4y.com -sparkandshine.net -sparkgis.com -sparkletour.com -sparkpool.com -sparlala.com -spasvo.com -spawatervip.net -spawor.com -spay365.com -spazio.plus -spbo.com -spbo1.com -spbosta.org -spc365.net -spcdntip.com -spcywang.com -spdbh5.com -spdbuser.com -spdcat.com -spdchgj.com -spdex.com -spdiy.com -spdiy.net -spdl.com -spdydns.com -spe777.com -speedcdns.com -speednt.com -speedpan.net -speedsz.net -speedws.info -speedws.org -speedycloud.cc -speiyou.com -spfmc.com -spforum.net -spgnux.com -spgyxx.com -sphinxrating.com -sphinxsearch.org -spiiker.com -spin-view.com -spinytech.com -spirit-doll.net -spirithy.com -spischolar.com -spjxcn.com -spl4cn.com -splaybow.com -splayer.org -splayer.work -splmcn.com -spnguru.com -spoience.com -spointdesign.com -spongeliu.com -sportk8.com -sportnanoapi.com -sportq.com -sports-idea.com -sportsdt.com -sposter.net -spot.download -spoto.net -spouyashop.com -spplnet.com -spprec.com -spps.cc -spr-atm.com -sprabbit.com -spralipay.com -spreton.com -spring4all.com -springairlines.com -springboot.io -springcloud.cc -springcocoon.com -springtour.com -spriteapp.com -sprzny.com -spswc.com -sptcc.com -sptccn.com -spthome.com -sptl.ltd -sptxm.com -spway.net -spyouxi.com -spzs.com -sq1996.com -sq580.com -sq688.com -sqa-chn.com -sqage.com -sqanju.com -sqchunqiu.com -sqdaily.com -sqfcw.com -sqggzy.com -sqiming.com -sqkb.com -sql110.com -sqlsec.com -sqmlw.com -sqph.org -sqrc.net -sqreader.com -sqrtthree.com -sqrtwo.com -sqstudio.com -sqsxs.com -squarecn.com -squarefong.com -squrab.com -sqwang.com -sqxy.net -sqzapp.com -sqzhongjian.com -sqzthg.com -sqzw.com -src.sr -srcb.com -srcbcz.com -srcmsh.com -srdlc.com -sreanalyze.com -srell.com -srfip.com -srgow.com -srichina.org -sritsoft.com -srjxj.com -srm.dji.com -srrsh.com -srrtvu.com -srssn.com -srtong.com -srun.com -srw00.com -srworld.net -srx3.net -srxww.com -sryjx.com -srzc.com -srzxg.com -srzxjt.com -ss-ceo.com -ss-mail.ru -ss0.me -ss6.co -ss6456.com -ss8899888.com -ssart.net -ssaxx.com -ssay.net -ssaya.win -ssbbww.com -ssc.com -sscity.org -sscmwl.com -ssdata.com -ssdax.com -ssddzy.com -ssdfans.com -ssdvd.net -sseinfo.com -ssf.cc -ssfxjy.com -ssggg.com -ssgushi.com -ssine.cc -ssine.ink -ssipex.com -ssjjss.com -ssjjtt.com -ssjlicai.com -ssjxx.com -ssjzw.com -ssky123.com -ssl-google-analytics.l.google.com -ssl.gstatic.com -sslaaa.com -sslceshi.com -sslchaoshi.com -sslchina.com -sslcity.com -ssldun.com -ssleye.com -sslibrary.com -sslnode.com -ssmec.com -ssnewyork.com -ssnn.net -ssofair.com -ssoomm.com -ssp86.com -sspaas.com -sspai.com -sspai.me -sspezz.com -ssports.com -ssports.net -ssppz.com -sspsky.com -ssqgx.com -ssqzj.com -ssreader.com -ssrrxx.com -ssrtys.com -sssie.com -ssso.com -ssstlc.com -sst-ic.com -sst-sd.com -ssuu.cc -ssvob.com -sswchina.com -ssxf.net -ssyar.com -ssyer.com -ssyj2015.com -ssyule.com -ssyzx.net -sszj.net -sszjnc.com -sszzz.com -st0008.com -st001.com -st123.com -st180.com -stackboom.xin -stackcc.com -stackoom.com -stackoverflow.club -stage1st.com -stage3rd.com -stajy.com -standardshop.net -star-boy.com -star-village-ent.com -star1024.com -star7th.com -starbaysoft.com -starcnm.com -stardict.net -stardict.org -stardoctor.com -starduster.me -stardustsky.net -starfivetech.com -stargame.com -starhsa.com -staridc.net -starlott.com -starlunwen.org -starming.com -starmobs.com -starpainters.net -starparkshenzhen.com -starpiao.com -starpoint0331.com -starrtc.com -starrysurvey.com -starschina.com -starschinalive.com -starsino.com -starstech.cc -starstech.tech -starstopic.com -starswar.org -start.htc.com -start.htcsense.com -startcarlife.com -starting2000.com -startogether1.com -startos.com -startos.org -startup-partner.com -starwarschina.com -stat-nba.com -stat18.com -static-exp1.licdn.com -static.licdn.com -staticaa.com -staticdn.net -staticec.com -staticf.com -staticfile.org -statickksmg.com -staticssl.image-gmkt.com -staycu.com -stbieshu.com -stc2002.com -stcash.com -stcmcu.com -stcmcudata.com -stcn.com -stcpsm.com -stcv66.com -stdaily.com -stdard.com -stdicloud.com -stdlibrary.com -stdout.pub -stdwp.com -steambang.com -steamboxs.com -steamchina.com -steamcn.com -steamproxy.net -steamrepcn.com -steamvpn.org -steamxdf.com -stec.net -stedu.net -steelphone.com -steelsearcher.co.kr -steelsearcher.com -stefg.org -steinslab.xyz -stemcellscn.com -stepfpga.com -stetcher.com -stevenshi.me -stewartcn.com -stfhq.com -stfile.com -stg8.com -stgairasia.com -stgod.com -sthforme.com -sthifi.com -sthke.com -stianran.com -stirlingchinese.com -stjfw.net -stjunshi.com -stjy.net -stkey.win -stlswm.com -stmbuy.com -stmcu.org -stmtax.com -stmybj.com -stnn.cc -stnts.com -sto80.com -stockhn.com -stocks-sparkline-lb.apple.com.akadns.net -stockstar.com -stockwei.com -stockxp.com -stointl.com -stone168.com -stonebuy.com -stoneios.com -stoneo2o.com -stonepoll.com -stonepoll.net -stoneread.com -stonescloud.com -stoneu.com -stonexp.com -stor-age.com -storagesemicon.com -store.apple.com -store.apple.com.edgekey.net -store.apple.com.edgekey.net.globalredir.akadns.net -store.dji.com -store.nike.com -store.samsung.com -store.storeimages.apple.com.akadns.net -store.storeimages.cdn-apple.com -storeedgefd.dsx.mp.microsoft.com -stormcodec.com -stormluke.me -stormorai.com -stormsend1.djicdn.com -story520.com -storyboardworld.com -storyday.com -storyren.com -storysec.com -stourweb.com -stovol.club -stoyard.com -str-mo.com -strconv.com -strcpy.me -streamaxtech.com -streamcomputing.com -strong-study.com -strongcms.net -strongled.com -stswjx.com -studa.net -studentboss.com -studioartiz.com -study-kit.com -studyapi.com -studycoder.com -studyems.com -studyez.com -studyfr.net -studyget.com -studygolang.com -studyinhk.net -studyintour.com -studyiris.com -studyjamscn.com -studylead.com -studylinux.net -studyofnet.com -studypay.com -studyvip.com -stuhome.net -stuhui.com -stuliving.com -stuln.com -stupid77.com -stupidet.com -stuq.com -stuq.org -stutimes.com -stvgame.com -stwaracademy.com -stxdgg.com -stxljy.com -styadmin.com -stylecdn.com -stylemode.com -styles-sys.com -stylewoman.net -styongtu.com -stzw.com -su-long.com -su-yongchen.com -suaee.com -suanbanyun.com -suandao.com -suanfazu.com -suangtianw.com -suanguajie.com -suanisp.com -suanjuzi.com -suanli.org -suanlitou.com -suanning.com -suanst.com -suanya.com -suaooo.com -suapp.me -subaonet.com -subaotuan.com -subar.me -subbt.net -subetter.com -subingkang.com -subinwechat.com -sublimetextcn.com -subline.org -subo.net -subo8988.com -subo988.com -subom.net -subond.com -suboyouku.com -suboyun.net -subuy.com -sucai.com -sucaibar.com -sucaidao.com -sucaifengbao.com -sucaifu.com -sucaihuo.com -sucaijishi.com -sucainiu.com -sucaitu.cc -sucaiw.com -suchasplus.com -suchen820.com -suchso.com -sucop.com -sucoupon.com -suda123.com -sudaizhijia.com -sudaoa.com -sudaqq.com -sudasuta.com -sudidc.com -sudu-67ph.com -sudu-kay6.com -sudu-pq2y.com -sudu-q6wk.com -sudu-r8gh.com -sudu-sq56.com -sudu-tf42.com -sudu-xu9b.com -sudu123.net -suducha.com -sududa.com -sudupower.net -sudusite.com -sueon.com -sufangxu.com -sufeinet.com -sufont.com -sugar918.com -sugarcanetechnology.com -sugarforex.com -sugarguo.com -sugarle.com -sugon.com -sugou.com -suhaodian.com -suhuibao.com -suhuishou.com -sui.com -suibianla.com -suibianzhao.com -suibiji.com -suicloud.com -suilengea.com -suileyoo.com -suinian.com -suinikan.com -suiniyi.com -suiqiao.com -suirui.com -suishenyun.net -suishouji.com -suisuijiang.com -suixin8.com -suixingjia.com -suixw.com -suiyichong.com -suiyiju.com -suiyuanjian.com -suiyuanka.com -suiyueyule.com -suizhoushi.com -suizui.net -sukimad.com -sukiu.net -sukkaw.com -sulabs.net -sulandscape.com -suleapi.com -sulianlian.com -suliaodingzhi.com -sumaart.com -sumaarts.com -sumatang.com -sumavision.com -sumeme.com -sumgotea.com -sumiaowang.com -suming.in -sumly.net -summall.com -summerlight.name -sumory.com -sumrday.net -sumsz.com -sumygg.com -sun-ada.net -sun-lion.com -sun-wish.com -sun0769.com -sun0816.com -sun66.net -sunater.com -sunbloger.com -sunbo.com -sunbo367.com -sunboxsoft.com -sunboyu.com -suncafe.cc -suncco.com -suncityad.com -sundabao.com -sundan.com -sundanimg.com -sundns.com -sundray.com -sunduse.com -sundxs.com -sunear.net -sunfarms.net -sunflyday.com -sunfounder.cc -sunfront.com -sunft.com -sungesoft.com -sungoal.org -sungoedu.com -sunhaojie.com -suninf.net -suning.com -suning.design -suningcloud.com -suningestate.com -suningholdings.com -sunjian1414.com -sunjidong.net -sunjiwen.com -sunjix.com -sunjs.com -sunke.me -sunlands.com -sunlands.wang -sunlandstudy.com -sunlandvip.com -sunlandzk.com -sunlife-everbright.com -sunlight-tech.com -sunlightbig.com -sunlogin.com -sunlons.com -sunlordinc.com -sunlune.com -sunmi.com -sunmingxia.com -sunmnet.com -sunnada.com -sunny90.com -sunnyaction.com -sunnychina.com -sunnyos.com -sunnyqi.com -sunnyxx.com -sunofbeaches.com -sunowo.com -sunpala.com -sunpcm.com -sunplusedu.com -sunpma.com -sunpun.com -sunrisedutyfree.com -sunrisenan.com -sunrtb.com -sunsharer.com -sunshe.com -sunshine-power.net -sunshinechn.com -sunsky-online.com -sunstu.com -suntalk-shftz.com -suntop168.com -suntray.com -suntrayoa.com -sunup3d.com -sunupcg.com -sunwayworld.com -sunweiwei.com -sunwy.org -sunxiaoning.com -sunxinfei.com -sunyansong.com -sunyea.com -sunyet.com -sunyingchao.com -sunyongfeng.com -sunyor.net -sunzhengyi.net -sunzhongwei.com -suo.im -suo.nz -suobao8.com -suobuy.com -suofeiya.com -suofeiyashop.com -suoge.net -suorang.com -suorong.com -suoxin5.com -suoyiren.com -supcompute.com -supcon.com -supdri.com -supei.com -super-mt.com -super-ssp.tv -super3g.com -superboss.cc -superbrowser.hk -superbuy.com -supercrm.com -superdns.net -superfix.com -superforeseer.com -superhl.com -superjq.com -superlb.net -superlib.com -superlib.net -superlink.mobi -supermap.com -supermap.io -supermapcloud.com -supermapol.com -supernano.com -superparse.com -superpb.com -superpowercn.com -superqq.com -superslide2.com -supersocket.net -superyd.com -superzl.com -supesite.com -supesoft.com -supfast.net -supfree.net -supmeter.com -supmil.com -supmil.net -supoin.com -supool.com -suporpe.com -suppig.net -support-china.apple-support.akadns.net -support-cn.samsung.com -support.apple.com -support.lenovo.com -supumall.com -supuy.com -suqian360.com -suqicloud.com -suqishi.com -suqnn.com -surdoc.net -sure56.com -suremotoo.site -surface-ser.com -surmon.me -surplusvalue.club -sursen.com -sursenelec.com -sursung.com -surtime.com -survey-y.com -surveyhills.com -surveyunion.com -survivor99.com -susong51.com -susongbbs.com -susouth.com -sustc.us -susudm.com -suteidc.com -sutuiapp.com -sutune.me -suuk.org -suukcn.com -suv666.com -suxiaohu.com -suxiazai.com -suxiege.com -suxinfa.com -suxing.me -suxuenet.com -suxuewang.com -suy.me -suyuening.com -suyugame.com -suyunbo.tv -suyutech.com -suzhenyi.com -suzhou.cc -suzhoubank.com -suzhoujinghui.com -suzhoulida.com -suzhoushilla.com -suzhousj.com -suzhouvisa.com -suzip.com -suzip.net -suzuki-china.com -suzuki-shanghai.com -svautolife.com -svenhetin.com -svinsight.com -svip15.com -svlengg.com -svlik.com -svmuu.com -svn999.com -svnbucket.com -svnspot.com -svnur4.com -svw-volkswagen.com -svwuc.com -sw0013.com -sw2008.com -sw996.com -swaeab.com -swakopuranium.com -swang8.com -swansea86.com -swansonchina.com -swap.wang -swaqds.com -swarma.net -swarma.org -swatou.com -swbbsc.com -swcatalog-cdn.apple.com.akadns.net -swcatalog.apple.com -swcd3.com -swcdn.apple.com -swcdn.g.aaplimg.com -swchina.org -swcpu.com -swdist.apple.com -swdist.apple.com.akadns.net -sweetalkos.com -sweetcelebrationpa.com -sweetdan.com -sweetlove.cc -sweetmartmarketing.com -sweetread.net -swfc-shanghai.com -swg36.com -swgzs.com -swhysc.com -swift.gg -swift51.com -swifter.tips -swifthumb.com -swiftlet.net -swiftmi.com -swiftstar.net -swijoy.com -swjack.com -swjinsheng.com -swjl.net -swjoy.com -swkong.com -swlhome.com -swlidc.com -swliuxue.com -swlsbj.com -swlte.com -swoft.org -swomc.net -swoole-cloud.com -swoole.com -swordair.com -swordart.online -swordnets.net -swordofmorning.com -swordtt.com -swotbbs.com -swothouse.com -swsbw.com -swscan-cdn.apple.com.akadns.net -swscan.apple.com -swsm.net -swsmu.com -swstsg.com -swt0.com -swupdl.adobe.com -swwlotus.com -swwy.com -swykjgs.com -sx189.com -sx2005.com -sx267.com -sx898.com -sxafz.com -sxbang.net -sxbawy.com -sxbrtkj.com -sxccb.com -sxcm.net -sxcntv.com -sxcqzyc.com -sxcwit.com -sxcyts.com -sxcywy.com -sxd408.com -sxddgxcy.com -sxdkj.com -sxdonggang.com -sxdwsx.com -sxdygbjy.com -sxdzyp.com -sxemc.com -sxepc.com -sxfblog.com -sxfu.org -sxgdtv.com -sxglpx.com -sxgoo.com -sxgs.com -sxhctv.com -sxhlxy.com -sxhm.com -sxhr.net -sxhsqccz.com -sxhuansi.net -sxhxbank.com -sxiaoshuo.com -sxjagc.com -sxjcylbx.com -sxjzxww.com -sxkid.com -sxkzxt.com -sxlcdn.com -sxldns.com -sxldtv.com -sxlychina.com -sxlyfood.com -sxmaps.com -sxmtdz.com -sxncb.com -sxnycl.com -sxol.com -sxpdk.com -sxpjp.com -sxplc.com -sxpmg.com -sxprgc.com -sxpta.com -sxpyzg.com -sxqns.com -sxrb.com -sxrbw.com -sxrczx.com -sxrong.com -sxrsj.net -sxrtv.com -sxruiheng.com -sxsapi.com -sxshu.com -sxsim.com -sxsimg.com -sxsjgy.com -sxslnews.com -sxsoft.com -sxsolid.com -sxszw.net -sxtppm.com -sxtvs.com -sxtybook.com -sxuyr2nx.com -sxvt58.com -sxwbs.com -sxwpyx.com -sxwrsa.org -sxww.com -sxxbdwh.com -sxxcrl.com -sxxdll.com -sxxiaomeng.com -sxxl.com -sxxt.net -sxxw.net -sxxyfw.com -sxy7.com -sxycrb.com -sxyj.net -sxzfcy.com -sxzhaobiao.com -sxzq.com -sxzt.org -sxzydj.com -sy-home.com -sy25.com -sy2k.com -sy3.com -sy76.com -sy916.net -sy9d.com -syb678.com -sybang.com -sybasebbs.com -syberos.com -sybj.com -sycaijing.com -sycdtz.com -sydcch.com -sydi.org -sydimg.com -syditie.com -sydjwl.com -sydm.hk -sydw8.com -sydwzp.com -sydzconn.com -sydzdiy.com -syebh.com -syf.ink -syfw.com -syg315.com -sygd.com -sygdjsj.com -sygtzc.com -syhccs.com -syhhidc.com -syhhkj.com -syhospital.com -syhpeizi.com -syhpz.com -syhtcgf.com -syhxnt.com -syitgz.com -syitu.com -syjiancai.com -syjkqzw.com -sykong.com -sylixos.com -syltdj.com -symama.com -symm-expo.com -symtc.com -symuge.com -syn029.com -synacast.com -synautilus.com -synball.com -sync.sh -synjones.com -synjones.net -synochip.com -synyan.net -syodr.com -syoits.com -syoker.com -syoogame.com -syoseo.com -syoucn.com -syouhui.com -sypao.com -sypole.com -syqnr.com -syr-sce.com -syrcb.net -sys-ele.com -syscan360.org -sysceo.com -sysclk.com -syscxp.com -sysengi.com -syshospital.com -syshospital.org -sysight.com -sysjdjy.com -sysmini.com -sysmk120.com -sysppc.com -sysrsksy.com -systoon.com -sysush.com -sysuyz.com -sysyfj.com -sysysjnk.com -sytcke.com -sythealth.com -sytlw.com -syttgame.com -sytuku.com -syuan.net -syuanxx.com -syue.com -sywg.com -sywgy.com -syxcn.com -syxiaoquan.com -syxj.net -syxlhw.com -syyim.com -syys8.com -syyx.com -syyyking.com -sz-3a.com -sz-amdc.com -sz-cerberus.com -sz-changfeng.com -sz-czzc.com -sz-dfl.com -sz-dns.net -sz-edsy.com -sz-etong.com -sz-iflysse.com -sz-jjb.com -sz-jlc.com -sz-lcsc.com -sz-mtr.com -sz-printing.com -sz-skt.com -sz-tianmai.com -sz-trip.com -sz-ua.com -sz-xfjc.com -sz-yongping.com -sz-ytq.com -sz0760.com -sz0dad.com -sz121.com -sz189.com -sz1978.com -sz240.com -sz315.org -sz4db.com -sz5156.com -sz5983.com -sz61.com -sz68.com -sz7h.com -sz836.com -sz886.com -szadst.com -szaeia.com -szaiaitie.com -szaima.com -szairport.com -szaisino.com -szaiten.com -szande.com -szaodis.com -szaudio.com -szbbs.org -szbcase.com -szbchx.com -szbdyd.com -szbeilu888.com -szbelle.com -szbelle.net -szbiu.com -szbwgr.com -szbwgy.com -szbwpt.com -szbyz.com -szc.com -szca.com -szcatic.cc -szcatic.com -szcec.com -szchi.net -szcno.com -szcompare.com -szcsot.com -szcssx.com -szcsw.com -szcua.org -szcud.com -szcwdz.com -szcxauto.com -szcy99.com -szczjy.com -szczkjgs.com -szdaily.com -szdave.com -szdc.org -szdcjd.com -szddns.net -szdesigncenter.org -szdiyibo.com -szdn1ms.com -szdxjf.com -szdyx8.com -szeant.com -szeasyin.com -szed.com -szedu.net -szeholiday.com -szelanpo.com -szelight.com -szen.in -szfa.com -szfachina.org -szffmr.com -szflysky.com -szfob.cc -szfuit.com -szfw.org -szfwzl.com -szfyhd.com -szgalaxy.com -szgccy.com -szgdsdkj.com -szgft.com -szgftz.com -szgla.com -szguanai.com -szgwsd.com -szhdlm.com -szhdyic.com -szhetai.com -szhgh.com -szhij.com -szhiross.com -szhk.app -szhk.com -szhkkd.com -szhlodz.com -szhlsg.com -szhmo.com -szhome.com -szhomeimg.com -szhot.com -szhtp.com -szhuace.com -szhuangchao.com -szhufu.com -szhuhang.com -szhulian.com -szhulian.net -szhydp.com -szhytrip.com -szider.com -szisland.com -szjcyyy.com -szjhons.com -szjhxjt.com -szjinshunyu.com -szjjtg.com -szjlwul.com -szjoys.com -szjyt66.com -szkb.net -szkingdom.com -szkoa.com -szksqy.com -szlande.com -szlangwei.com -szlcsc.com -szledia.org -szleezen.com -szlhtram.com -szlianya.net -szlihuam.com -szlilun.com -szlingsheng.com -szlips.com -szljnk.com -szlos.com -szlottery.org -szltz.com -szlvbarcode.com -szlwtech.com -szmadigi.com -szmall.com -szmama.com -szmama.net -szmc.net -szmctc.com -szmdfs.com -szmil.com -szminiao.com -szmsheng.com -szmslaser.com -szmtzc.com -szmuseum.com -szmynet.com -szn360.com -sznews.com -szniushi.com -sznmd.com -szns-marathon.com -szol.net -szolxd.com -szonline.net -szp168.com -szpa.com -szpama.com -szpcb-jlc.com -szpclab.com -szpda.com -szpiao.com -szpiaoyi.com -szpichappy.com -szpmi.org -szpowerpms.com -szpxb.com -szpxe.com -szqcz.com -szqf.org -szqgzx.com -szqianbaidun.com -szqinxindz.com -szqsq.com -szqt.net -szquanli.com -szrcfw.com -szrlqy.com -szronna.com -szrrjc.com -szschj.com -szsci.net -szscree.com -szsczx.com -szseafoodexpo.com -szsfxs.com -szshequ.org -szsia.com -szsing.com -szsjtjj.com -szskwn88.com -szsky.com -szsmk.com -szsn.pro -szsolar.org -szsq.net -szssty.com -szsti.net -szstsh.org -szsunlaser.com -szswt.net -szt365.com -sztaijier.com -sztalent.org -sztanko.com -sztara.com -szteacher.net -szthks.com -sztkc.com -sztopbrand.com -sztspi.com -sztxcpa.com -szuavia.org -szukwood.com -szvca.com -szvcgroup.com -szvft.com -szvi-bo.com -szwalking.com -szwb.com -szwblm.com -szwego.com -szweita.com -szwellsun.com -szwfb.com -szwfzs.com -szwgroup.com -szwstui.com -szwwco.com -szxbyx.com -szxccled.com -szxdhj.com -szxiangjun.com -szxihu.com -szxinjiaxin.com -szxinyixin.com -szxlga.com -szxqsx.com -szxsdmy.com -szxuexiao.com -szxxbq.com -szxxtx.com -szydsxy.com -szyfdz.net -szyhljt.com -szyibei.com -szyibuda.com -szyin.com -szyingzhan.com -szyixiu.net -szyjedu.com -szymweb.com -szyran.com -szysfxx.com -szysmpay.com -szyuda88.com -szyxwkj.com -szyyt.com -szyyx.com -szzbmy.com -szzfgjj.com -szzfzd.com -szzh365.com -szzppx.org -szzs360.com -szzxks.net -szzxs.com -szzyqc.net -t-bb.net -t-biao.com -t-cha.com -t-cheshi.com -t-chs.com -t-d.tv -t-firefly.com -t-gafa.com -t-io.org -t-ji.net -t-jiaju.com -t-jiu.com -t-nan.com -t-v.com -t.tt -t00ls.net -t00y.com -t027.com -t086.com -t10.com -t105.com -t12.com -t123yh.xyz -t1networks.com -t1y4.com -t1y5.com -t20000.com -t262.com -t2cn.com -t2u.me -t3315.com -t365777.com -t3pp.com -t4u8m.xyz -t56.net -t56jy.net -t58b.com -t5a9.com -t5xs.com -t6q.com -t85.net -t888w.com -t8tcdn.com -ta26.com -ta80.com -taaas.org -tabalt.net -tachangxing.com -tackson.com -taclsc.org -taculee.com -tadaigou.com -tadewo.com -tadiao168.com -tadseeker.com -tadu.com -taeapp.com -tag.gg -taglyst.com -tagmmm.com -tago.fun -tagphi.net -tagtxq.com -taguage.com -taguxdesign.com -tahua.net -tai-liang.com -tai3399.com -tai666666.com -tai87.com -taian.com -taianmedia.com -taiantang.net -taibai.cc -taibumall.com -taichangle.com -taichi-app.com -taicihome.com -taidadk.com -taidao.net -taidizh.com -taidous.com -taidu.com -taidupa.com -taifutj.com -taig.com -taigaoxiao.com -taigongwl.com -taigpro.com -taiguoyu.com -taihaikj.com -taihainet.com -taihangco.com -taihaocn.com -taihe.com -taihemedia.com -taiho.cc -taihuoniao.com -taihuwang.com -taihuyuan.com -taiji.com -taijicoder.com -taijidf.com -taijiny.com -taijio.com -taijs.com -taijutt.com -taijutv.com -taikang.com -taikanglife.com -taikangzhijia.com -taikeji.com -taikongmedia.com -taikr.com -tainicement.net -taiqigame.com -taiqingjiu.com -tairan.com -taishangshiwu.com -taishengtoys.com -taitaiblog.com -taitaikg.com -taiwandao.tw -taixingren.com -taixsw.com -taiyainfo.com -taiyang888.com -taiyangd.com -taiyangpo.com -taiyiplus.com -taiyougo.net -taiyulink.com -taizibao.com -tajubao.com -tajyw.net -takeinblue.com -takungpao.com -tal-rasha.com -taladapp.com -talang100-wp.com -talangy.com -talbrain.com -talebase.com -talebook.org -talentjava.com -talents-tech.com -talentsmag.com -taleqq.com -talicai.com -taliove.com -taljdns.com -talk-fun.com -talk.ai -talk007.com -talkgw.com -talkingchina.com -talkingdata.com -talkingdata.net -talklee.com -talkop.com -talkwithtrend.com -talkyun.com -taluo.com -tamaegis.com -tamc8.com -tamersunion.org -tamguo.com -tamigroup.com -tamll.com -tamtattoodx.com -tan.cc -tan07.com -tan14.net -tan8.com -tan90.me -tanbaicun.com -tanbo.name -tancdn.com -tandehao.com -tandjx.com -tang-lei.com -tang.su -tangangny.com -tangcuwang.com -tangdaoya.com -tangdou.com -tangdouimg.com -tangeche.com -tanghushi.com -tangide.com -tangjie.me -tangjiu.com -tangkx.com -tanglei.name -tanglue.co -tangmi.net -tangobrowser.net -tangongye.com -tangpin.me -tangqiu.tv -tangrenjv.com -tangruiqian.com -tangsanshu.com -tangshan.cc -tangshijun.com -tangshuang.net -tangshui.net -tangsongys.com -tangsuanradio.com -tangtang.org -tangtangbk.com -tangtanghr.com -tanguan.net -tangux.com -tangwumo.com -tangyingkang.com -tangzhekan2.net -tangzhuan666.com -tangzongchao.com -tanhaibo.net -tanho.com -tanhu.net -tanhuadao.com -tankmm.com -tankywoo.com -tanling.com -tanluxia.com -tanmer.com -tanmizhi.com -tannet-information.com -tanpoqiuer.com -tanqi888.com -tanrd.com -tanshudata.com -tansoole.com -tansuo233.com -tansuotv.com -tantanapi.com -tantanapp.com -tantu.com -tantu.info -tantuw.com -tanv.com -tanvc.com -tanwan.com -tanwan123.net -tanwanindex.com -tanwanyx.com -tanweime.com -tanwuapp.com -tanx.com -tanyihui.com -tanyu.mobi -tanyuantech.com -tanzhouedu.com -tanzhoujiaoyu.com -tanzhouvip.com -tao-jiujiu.com -tao-star.com -tao-studio.net -tao008.com -tao123.com -tao168.com -tao2tao.com -tao30.com -tao3c.com -tao616.com -tao800.com -tao885.com -taoad.com -taoba568.com -taobangban.com -taobao-img.com -taobao.co -taobao.com -taobao.cz -taobao.net -taobao.org -taobao.tw -taobao.wang -taobao92.com -taobaocdn.com -taobaocdn.net -taobaoux.com -taobaozxw.com -taobc.com -taobeihai.com -taobeirj.com -taobizhong.com -taobot.com -taobz.com -taoc.cc -taocece.com -taoche.com -taoci.com -taocloudx.com -taocms.org -taocz.com -taodabai.com -taodahuo.com -taodake.com -taodangpu.com -taodao.kim -taodaso.com -taodianjia.com -taodiantong.com -taodiqupu.com -taodocs.com -taodu.com -taodudu.cc -taoduyx.com -taofang.com -taofen8.com -taofont.com -taoguaji.com -taogula.com -taohaobang.com -taohua.com -taohuaan.net -taohuadao3.com -taohuazu.net -taohuazu.pw -taohui.pub -taohuichang.com -taohuizhou.com -taohuochang.com -taohuren.com -taohwu.com -taoibao.net -taojiji.com -taojin6.com -taojindi.com -taojingame.com -taojinhao.net -taojinhudong.com -taojinji.com -taojinyi.com -taokaifu.com -taoke.com -taokehome.com -taoketuitui.com -taokewenan.com -taokezhushou.com -taoku.com -taokuaiche.com -taokzu.com -taole1.com -taolutv.com -taolx.com -taomanhua.com -taomee.com -taomeiju.com -taomeisi.com -taoming.com -taomingyan.com -taonienie.com -taoniupin.com -taooo.cc -taopiaopiao.com -taopic.com -taoq.net -taoqao.com -taoqian123.com -taoquanquan.com -taoqutu.com -taosdata.com -taosem.com -taoshouyou.com -taoshu.com -taoshudang.com -taosidata.com -taosj.com -taosum.com -taotao.com -taotao3.com -taotaocar.com -taotaosou.com -taotieren.com -taotiwang.com -taotu8.net -taotumowang.com -taotuwu.com -taou.com -taowenxue.com -taowola.com -taoxiaolu.com -taoxiaoxing.com -taoxiaozhong.com -taoxie.com -taoxv.com -taoyeyou.com -taoyi-support.com -taoyinqing.com -taoyizhu.com -taoyoupin.com -taoyuantravel.com -taozaisheng.com -taozhexue.com -taozhutu.com -taozhuwu.com -tapas.net -tapdata.net -tapdb.com -tapdb.net -tapenjoy.com -tapimg.com -tapotiexie.com -tapque.com -taptap-api.com -taptap.com -taptapcode.com -taptapdada.com -tarczp.com -tarenacn.com -tarenwang.net -tarsocial.com -tartscenter.com -tasiyun.com -taskcity.com -taskcn.com -taskyou.net -taslgs.com -tasly.com -tastespirit.com -tastones.com -tastysteak.com -tatatimes.com -tatazu.com -taterli.com -tattoo114.com -tattoo77.com -taurus66.com -tavsiktlig.com -tax-edu.net -tax12366.org -taxiaoshuo.com -taxjiangkewang.com -taxnote.org -taxspirit.com -taxwen.com -taycss.cc -tayohya.com -tazhe.com -taznsb.com -tb.am -tb1u.com -tb51.net -tb58.net -tb888.net -tbadc.com -tbankw.com -tbcache.com -tbdazhe.com -tbdiy.com -tbh5.com -tbhcc.com -tbhelper.com -tbkf.net -tbl-import.com -tblk.me -tbnimg.com -tbq168.com -tbqw.com -tbrum15.com -tbsandbox.com -tbscache.com -tbscp.net -tbsgame.net -tbshops.com -tbsite.net -tbszd.com -tbt.cc -tburl.in -tburl.net -tbw-fuzhuang.com -tbw-hufu.com -tbw-xie.com -tbwan.com -tbwda.com -tbwfy.com -tbwshc.com -tbxt.com -tbyfsoft.com -tbyuantu.com -tc-21.com -tc-ds2000.com -tc12580.com -tc199.net -tc9011.com -tc930.com -tcc.so -tccqb.com -tccxfw.com -tcdai.com -tcdbcc.com -tcdnlive.com -tcdnos.com -tcdnv3.com -tcdnvod.com -tcdushi.com -tceic.com -tcgcardgame.com -tcgzxx.com -tchbgz.com -tchilde.com -tchzt.com -tciplay.com -tcl.com -tcl.com.ru -tclbusiness.com -tclclouds.com -tclking.com -tcloudbase.com -tcloudbaseapp.com -tcloudfamily.com -tcloudlife.com -tcloudscdn.com -tcloudscdn.net -tcm100.com -tcmfrj.com -tcmygy.com -tcnews.cc -tcnvmms.com -tcp.hk -tcpspc.com -tcqccn.com -tcrcb.com -tcrcsc.com -tcs-y.com -tcsae.org -tcsdzz.com -tcshare.org -tcshuishou.com -tcsnake.com -tcstzg.com -tctd.net -tctip.com -tctong.com -tcxfpc-pcb.com -tcxw.cc -tcxx.info -tcy365.com -tcyl.pro -tcyl77.com -tcylgslb.com -tcz.name -td-tech.com -td22.com -td518.com -td776.com -td98.com -tdain.com -tdatamaster.com -tdbzcl.com -tddmp.com -tddspmall.com -tdfcw.com -tdict.com -tdimg.com -tdldz.com -tdnsv1.com -tdnsv2.com -tdnsv5.com -tdnsv6.com -tdpress.com -tdsx114.com -tduou.com -tdzyw.com -te5.com -te6.com -tea26.com -tea7.com -teach365.com -teachcn.net -teachercn.com -teacherhou.com -teacti.com -teakki.com -teaku.com -team.tt -teamall.cc -teambition.com -teambition.net -teambuy.cc -teamlogs.com -teamminus.com -teampareto.com -teamshub.com -teamtopgame.com -teamyi.com -teapic.com -teatreexy.com -teazhishi.com -tebaidu.com -teboncapital.com -tecbbs.com -tecenet.com -tech-domain.com -tech-food.com -tech-mx.com -tech-sonic.net -tech1024.com -tech110.net -tech126.com -tech2ipo.com -techan.com -techantong.net -techaxiang.net -techbrood.com -techeme.net -techenergize.com -techflow520.com -techgastronomy.com -techgogogo.com -techieliang.com -techkedu.com -techmiao.com -technode.com -techoke.com -techparty.org -techsir.com -techuangyi.com -techug.com -techvisum.com -techwalker.com -techxinwen.com -teclast.com -tecyle.com -tedaniu.com -teddymobile.net -tedx.net -tee7.com -teein.com -teeker.com -teemm.com -teemmm.com -teencn.com -teeqee.com -teeterstoop.store -tefl-china.net -tegjlxs.com -tegongji.com -tegoushe.com -tehon.org -tehui001.com -tehuituan.com -tejiabei.com -tejiaquan.com -tejiawang.com -tektea.com -tel7777777.com -telaideyouxue.com -telaslua.com -teld.net -telefen.com -telehr.com -teleinfoo.com -teleland.net -teliute.org -telking.com -tell520.com -telllove520.com -telnet404.com -telojob.com -telunsu.net -tem.pw -tem365.com -temaihui88.com -temaiku.com -temiscira.com -temox.com -temp.im -templet360.com -tencdns.net -tencent-blackboard.com -tencent-cloud.com -tencent-cloud.net -tencent-gf.com -tencent.com -tencent.com.hk -tencentads.com -tencentclb.com -tencentcloud.com -tencentcloudapi.com -tencentcs.com -tencentdba.com -tencentdevices.com -tencentipv6.com -tencentlog.com -tencentmind.com -tencentmusic.com -tencentsuite.com -tencentwm.com -tencentyun.com -tenchong.com -tendacn.com -tendawifi.com -tendcode.com -tenddata.com -tenganxinxi.com -tengattack.com -tengbai-it.com -tengbencdn.com -tengbo.cc -tengchu.com -tengdinggame.com -tengfang.net -tengfangyun.com -tengfeijob.com -tengfeizhida.com -tengfun.com -tenghen.com -tengma123.com -tengmed.com -tengshuodz.com -tengwen.com -tengwen001.com -tengxunmail.com -tengxunqiye.com -tengxunqiyeyou.com -tengxunyundaijinquan.com -tengxunyunyhw.com -tengyuejz.com -tenhot.net -teniucaijing.com -teniujinfu.com -tenlonstudio.com -tenlywu.com -tenmh.com -tennisworld.mobi -tennoo.com -tenpay.com -tenqent.com -tenshi.cc -tensorchip.com -tensornews.net -tensynad.com -tensynchina.com -tentrue.com -tentx.com -tenxapp.com -tenxcloud.com -tenxcloud.net -teown.com -tepcb.com -tepintehui.com -terabuy.com -terence2008.info -terencexie.com -teridge.com -terminus.io -terra-master.com -terransforce.com -terrehauteairfair.com -terrybook.net -teruide.net -tesadz.com -tese5.com -teshenqi.com -teslachezhu.com -tesolsh.com -tesoon.com -test-edu.net -test404.com -testbird.com -testcoo.com -testdao.com -testeb.com -testerhome.com -testerlife.com -testict.com -testip.xyz -testroad.org -testrust.com -testtao.com -testwo.com -testxy.com -tetimes.com -teto.cc -teuhui.com -tex68.com -texclo.net -text.wiki -tezhengma.com -tezhongzhuangbei.com -tezign.com -tf86.com -tfang.net -tfax.com -tfbcj.com -tfbrj.com -tfcaijing.com -tfcloud.com -tfclub.com -tfdccn.com -tfedu.net -tfg2.com -tfgame.vip -tfme.com -tfol.com -tfrl.net -tfsino.com -tfsmy.com -tftxw.com -tfxgt.com -tfyou.com -tfysw.com -tfyum.net -tfzcode.com -tg-vision.com -tg-vision.net -tg0123.com -tg1234.com -tg72.com -tgbus.com -tgcid.org -tghello.com -tgirl.cc -tgjh.com -tgking.net -tgljw.com -tglxh.com -tgnet.com -tgovcloud.com -tgshenghe.com -tgshiguan.com -tgsoso.com -tgyoo.com -tgyun.cc -th-gas.com -th123.com -th38.com -thaiyuehealth.com -thamco.com -thanhong.me -thanhtunghairsalon.com -thankbabe.com -thatsmags.com -thatsmandarin.com -thbattle.net -thcad.net -thcantech.com -the4can.com -the5fire.com -the9.com -thearenacapital.com -thearyong.com -theateliercouture.com -thebeastshop.com -thebeautools.com -thebeijinger.com -thebeijingnews.com -theblockbeats.com -thechihuo.com -thechois.cc -thecode.me -thecodeway.com -thedatasys.com -theduapp.com -thefatherofsalmon.com -thefifthera.com -thegbdc.com -thegiac.com -theguangdong.com -thehanshow.com -thehypermodern.com -theiei.com -thejamy.com -thejiangmen.com -thejoyrun.com -thelarkcloud.com -thelastsky.com -themebetter.com -themeforwp.net -themeila.com -themex.net -themez.cc -then9.com -thenburn.com -thenew123.com -theonemusic.net -theorychina.org -thepast.cc -thestack.net -thethirdmedia.com -thetigerhood.com -thetongji.com -thetype.cloud -thewowa.com -thexnode.com -theyun.com -thfdcsoft.com -thhome.net -thief.im -thinbug.com -thingjs.com -thingtry.com -thinkcmf.com -thinkdo3.com -thinkdream.com -thinkeridea.com -thinkhard.tech -thinkindrupal.com -thinkjs.org -thinkphpcode.com -thinksns.com -thinksrc.com -thinkymobi.com -thishealthsummit.com -thisim.net -thisisdongdongqiang.com -thmovie.com -thmz.com -thn21.com -thncycling.com -thoughtworkers.org -threadcn.com -threeol.com -threetong.com -ths123.com -ths8.com -thseoer.com -thstars.com -thstp.com -thtf.cc -thtfpc.com -thtxzyz.com -thumedialab.com -thundercdn.net -thunderflash.net -thunderobot.com -thunderurl.com -thunderx.hk -thunis.com -thunis.org -thunisoft.com -thunlp.org -thupdi.com -thwhisper.com -thwiki.cc -thxddb.com -thxedu.com -thxflt.com -thxxw.com -thyclub.com -thyoo.com -thyou.com -thyrsi.com -thzab.com -thzcb.com -thzer.com -thzhd.wang -thzxhm.com -ti-node.com -ti-solar.com -ti98.com -tian10.com -tianan-cyber.com -tiananmenlvyou.com -tianapi.com -tianbai.net -tianbaosi.com -tiancaiui.com -tiancaixing.com -tianchu.com -tiancipz.com -tiancity.com -tiancitycdn.com -tianda120.com -tiandaoedu.com -tiandi.com -tianditu.com -tianditu.org -tiandizw.com -tianduntech.com -tiandy.com -tianelian.com -tianfeiyu.com -tianfus.com -tianfusoftwarepark.com -tianfuw.com -tianhaijiaodai.com -tianhaohz.com -tianhejiayi.com -tianhongdiaosu.com -tianhongsunshine.com -tianhujy.com -tianji.com -tianjian.cc -tianjiegame.com -tianjieleather.com -tianjigame.com -tianjihr.com -tianjimedia.com -tianjin-air.com -tianjingrong.com -tianjinwe.com -tianjinxs.com -tianjinzs.com -tiankong.com -tiankong.info -tiankonguse.com -tiankongzudui.com -tianlaiedu.com -tianlaikge.com -tianlan.net -tianmao.com -tianmaying.com -tianmeng.org -tianmidian.com -tianmin789.com -tianmujiqi.com -tianmupe.com -tianmupr.com -tiann90.com -tianniu365.com -tianniuyouxi.com -tiannv.com -tianpeng.com -tianpinjie.com -tianqi.cc -tianqi.com -tianqi123.com -tianqi321.com -tianqi4.com -tianqi518.com -tianqiaojuyuan.com -tianqiaoyishuzhongxin.org -tianqiapi.com -tianqihoubao.com -tianqijun.com -tianqikb.com -tianqistatic.com -tianqiwang.org -tianrow.com -tianruixinxi.com -tianruiyun.com -tiansenjituan.com -tianshan277.com -tianshangrenjian123.com -tianshannet.com -tianshengdiyi.com -tianshi.info -tianshi2.net -tianshiaomei.com -tianshiyiyuan.com -tianshouzhi.com -tianshuge.com -tiansin.com -tiantailaw.com -tiantang6.com -tiantangyingshi.tv -tianti.com -tiantian.com -tiantian688.com -tiantian8.com -tiantianbianma.com -tiantianfm.com -tiantiangold.com -tiantianhr.com -tiantianleshuiguo.com -tiantianquce.com -tiantianqutao.com -tiantianring.com -tiantiansoft.com -tiantiantiao.com -tiantianxiaoshuo.com -tiantianxuexi.com -tiantk.com -tiantonglaw.com -tianvalue.com -tianwenhu.com -tianxia.la -tianxiadianjia.com -tianxiajiameng.com -tianxiang.com -tianxianle.com -tianxiawangxiao.com -tianxiaxiao.net -tianxiaxinyong.com -tianxinfan.com -tianxing.com -tianya.com -tianya.tv -tianya200.com -tianya999.com -tianyablog.com -tianyabook.com -tianyaclub.com -tianyaluedu.com -tianyancha.com -tianyant.com -tianyaruanwen.com -tianyatool.com -tianyaui.com -tianyecollege.com -tianyi1368.com -tianyibook.com -tianyihy.net -tianyiidc.com -tianyijue.com -tianyinzaixian.com -tianyiweiya.com -tianyuimg.com -tianzeba.com -tianzhao.net -tianzhilou.com -tianzhuo.com -tianzikj.com -tiaodao.com -tiaodou.tv -tiaoguangbolimo.com -tiaohao.com -tiaoliao.biz -tiaomu.com -tiaona.com -tiaooo.com -tiaotiaotang.net -tiaozhanbei.net -tiatiatoutiao.com -tibaitong.com -tibet3.com -tibet4wd.com -tibet9.com -tibetanbible.org -tibetannet.com -tibetcn.com -tibetcnr.com -tibetcul.com -tibetculture.net -tibetcyts.com -tibetinfor.com -ticket800.com -ticketdashi.com -ticketmars.com -ticstore.com -tictalk.com -tictalk.vip -ticwear.com -tida120.com -tidi.mobi -tiduyun.com -tieba.com -tieba01.com -tiebaimg.com -tiebamm.com -tiebaobei.com -tiebashop.com -tiedan2019.com -tiegu.com -tiejia123.com -tiejiang.org -tiejiong.com -tiejp.com -tieku001.com -tielemao.com -tielingcn.com -tielu.org -tiepishihu.com -tietie.la -tietuku.com -tietuku.pw -tieweishi.com -tieww.com -tiexie0.wang -tiexing.com -tiexing.net -tiexiuyugudao.com -tiexue.net -tieyou.com -tiezhima.com -tiezis.com -tigerbbs.com -tigerbrokers.com -tigerbrokers.net -tigeresop.com -tigerfintech.com -tigersecurities.com -tigeryun.com -tiimg.com -tijian001.com -tijian123.com -tijianbao.com -tijianka.cc -tijianshangmen.com -tijianzhuanjia.com -tijiyi.com -tikersport.com -tikikm.com -tikkausa.com -tikuol.com -timanetworks.com -timchen314.com -time-weekly.com -time-year.com -time.izatcloud.net -time2011.com -timecoo.com -timedg.com -timenote.cc -timeofdate.com -timeoutbeijing.com -timeoutcn.com -timepill.net -timeread.com -timeread.net -times-asia.com -timesawards.com -timeso.cc -timetw.com -timev.com -timing360.com -timipc.com -timitime.com -timjx.com -tinfinite.com -ting-tou.com -ting30.com -ting55.com -ting85.com -tingall.com -tingbook.com -tingcd.com -tingchewei.net -tingchina.com -tingclass.com -tingclass.net -tingfun.net -tingjiandan.com -tingke8.com -tinglanstg.com -tinglibaohuqi.com -tingliku.com -tingmall.com -tingmimi.net -tingroom.com -tingshubao.com -tingshucn.com -tingshuge.com -tingtao.net -tingwusun.com -tingyulou.com -tingyun.com -tingyunfenxi.com -tinkad.net -tinkerpatch.com -tinman798.net -tinsecret.com -tinsecret.org -tintinloan.com -tiny-calf.com -tiny4.org -tinyems.com -tinyflare.com -tinygroup.org -tinylab.org -tinyservices.net -tinysou.com -tinyyuan.com -tiodata.com -tipaipai.com -tipask.com -tipdm.com -tipray.com -tiprpress.com -tips1000.com -tiqiaa.com -tiqianhuandai.cc -tiqianle.com -tired.im -tiruna-cn.com -tisgame.com -tisino.com -tisiwi.com -tisohinge.com -tita.com -titan007.com -titan24.com -titanar.com -titapark.com -tixa.com -tixaapp.com -tixaclub.net -tiyalive.com -tiyanzhimei.com -tiye.me -tiyep.com -tiyii.com -tiyu008.com -tiyu68.com -tiyuansu.com -tiyudaka.com -tiyufeng.com -tiyule.com -tiyusaishi.com -tiyuxiu.com -tizi.com -tizi365.com -tizoinfo.com -tj-gangxin.com -tj-guangxin.com -tj-kingdee.com -tj-model.com -tj-un.com -tj-zt.com -tj0573.com -tj12580.com -tj20.com -tjaide.com -tjbearing.com -tjbh.com -tjbsq.com -tjbus.com -tjcamp.com -tjcondom.com -tjculture.com -tjdtdd.com -tjdyf.com -tjece.com -tjfer.com -tjflora.com -tjgangkouyiyuan.com -tjgcs.com -tjgdjn.com -tjhukou.com -tjinsuo.com -tjitrc.com -tjj.com -tjjapp.com -tjjingjie.com -tjjt360.com -tjkpzx.com -tjkx.com -tjkximg.com -tjkyhr.com -tjleidu.com -tjluohuzhijia.com -tjmama.com -tjmayo99.com -tjmhc.com -tjmuch.com -tjmzzk.com -tjorthop.org -tjpa-china.org -tjpma.org -tjptfhq.com -tjrge.com -tjscm.com -tjsjnxh.com -tjspiraxsarco.com -tjst.net -tjstats.com -tjufbase.com -tjupdi.com -tjvedu.com -tjwch.com -tjwch.org -tjwenjie.com -tjwj88.com -tjwmschool.net -tjwzy.com -tjxishuai.com -tjxmzd.com -tjxrm.com -tjxxcl.com -tjxz.cc -tjyouai.com -tjyun.com -tjyz.org -tjzcsj.com -tjzfcg.com -tjzhongyiyao.com -tjzyec.com -tk-rays.com -tk-xiong.com -tk163.com -tk2299.com -tkcm888.com -tkf.ink -tkg5.com -tkgame.com -tkhealthcare.com -tkimg.cc -tkoubei.com -tkplusemi.com -tkw.cc -tkxxd.net -tl-shida.com -tl-tek.com -tl-vogue.com -tl88.net -tlbaby.com -tlby120.com -tlbyx.com -tlcharity.com -tlfjw.com -tlfw.net -tlgslb.com -tlightsky.com -tljcw.com -tljob8001.com -tlkzs.com -tlllllll.com -tlmmgf.com -tlqwine.com -tlrcbk.com -tlsj-hd.com -tlstwy.com -tlte.com -tltesoft.com -tltuan.net -tltzg.com -tlwok.com -tlyy.cc -tlyy.tv -tlztb.com -tm312.com -tma-001.com -tmabike.com -tmaill.com -tmall.casa -tmall.com -tmall.hk -tmall.ru -tmallma.com -tmallvvv.com -tmasg.com -tmbbs.com -tmcdn.net -tmcore.com -tmd.cc -tmdm.com -tmechina.org -tmeiju.com -tmetb.com -tmetb.net -tmhvps.com -tmigoods.com -tmisp.com -tmjob88.com -tmjypx.com -tmkoo.com -tmmini.com -tmqmqj.com -tmrcw.com -tmscnz.com -tmsf.com -tmsgschool.com -tmtforum.com -tmtpost.com -tmtpost.net -tmuaih.com -tmuyun.com -tmwcn.com -tmxmall.com -tmxxw.com -tn2000.com -tn597.com -tnbz.com -tnccdn.com -tnet.hk -tngcjx.com -tnjyfc.com -tnkjmec.com -tnmb.org -tntdown.com -to-future.net -to4f.com -to8to.com -to9.org -to999.com -tobaccobid.com -tobaccochina.com -toberp.com -tobnews.com -tobosu.com -tobosu.net -tobshe.com -tobsnssdk.com -tochgo.com -tochinajob.com -tocosc.com -today36524.com -todaycache.net -todayidc.com -todayios.com -todayisp.net -todaynic.com -todaytex.com -todebug.com -todesk.com -todoen.com -todokeji.com -todonow.com -todosomeone.com -toec-gdgs.com -toec-iot.com -toec.com -toecsec.com -toecsoft.com -toecxy.com -togj.com -togln.com -togo666.com -togocareer.com -togogo.net -tohic.net -tohkalove.com -tohosting.com -tohosting.net -tohours.com -tohuo.com -toidea.com -tok9.com -token-ad.com -token.im -tokenglish.com -tokenlon.im -tokenpocket.pro -tokensky.net -tokenview.com -tokenworld.pro -tokimekiclub.org -tol24.com -tolur.org -tom.cat -tom.com -tom163.net -tom18.net -tom61.com -tomap.me -tomatolei.com -tomczhen.com -tomdiy.com -tomlgame.com -tomonline-inc.com -tomotoes.com -tompda.com -tomujiang.com -tomwx.net -tonbao.com -tonehk.com -tonewinner.com -tongbaigong.org -tongbanjie.com -tongbanjie.info -tongbaoyun.com -tongbiancha.com -tongbu.com -tongbulv.com -tongbupan.com -tongbusj.com -tongcaihulian.com -tongchaba.com -tongcheng.cc -tongda2000.com -tongdao.io -tongdaohui.com -tongdiaogs.com -tongdoutown.com -tongdun.net -tongfangpc.com -tongfengqu.com -tongfu.net -tonggao.info -tonghs.com -tonghua-holiday.com -tonghua5.com -tonghuiqiye.com -tongji.com -tongji.net -tongjitong.com -tongjiwo.com -tongleer.com -tongli-hrcc.net -tongliangrc.com -tongliaowang.com -tonglu-tour.com -tonglukuaijian.com -tongluyizhao.com -tongmengguo.com -tongmoe.com -tongpankt.com -tongshanbank.com -tongshuai.com -tongtech.com -tongtianta.site -tongtongli.com -tongtongxue.com -tongtool.com -tongwang.net -tongxiang.net -tongxin.com -tongxin.org -tongxinclub.com -tongxinghui.com -tongxinky.com -tongxinmao.com -tongxinteng.com -tongxiong.com -tongxue.com -tongxue365.com -tongyavisa.com -tongye.biz -tongyi.com -tongyidrying.com -tongyongji.net -tongyongpe.com -tongyuanos.com -tongyue.com -tongzhougongjin.com -tongzhousy.com -tongzhuo100.com -tonitech.com -tonnn.com -tonylit.me -tonysfarm.com -tooben.com -toobug.net -toocle.com -toodaylab.com -toohiphop.com -tool.cx -tool.la -tool.lu -tool77.com -toolbarqueries.google.com -toolinbox.net -toolmall.com -toolmao.com -toolnb.com -tools.google.com -tools.l.google.com -tooming.com -toomoss.com -toon.mobi -toonmax.com -toonmaxmedia.com -tooogooo.com -tooopen.com -tooseo.com -tootour.com -toouoo.com -top-iot.com -top100summit.com -top147.com -top1food.com -top263.net -top2fun.com -top301.com -top3456.com -topacg.com -topber.com -topbester.com -topbiz360.com -topbm.com -topbook.cc -topcfo.net -topcheer.com -topchitu.com -topciic.com -topcj.com -topcrab.com -topcsic.com -topdiaoyu.com -topdodo.com -tope365.com -topecsc.com -topeditsci.com -topeet.com -topeetboard.com -topenergy.org -topengroup.net -topflames.com -topfreeweb.net -topfungarden.com -topgeek.org -topgslb.com -topguo.com -topgus.com -tophant.com -tophold.com -tophr.net -tophub.fun -tophub.today -topide.com -topidea365.com -topit.me -topitme.com -topjoy.com -topjoycloud.com -topjuyi.com -topksw.com -topku.com -toplanit.com -toplee.com -toplife.com -toplinks.cc -toploong.com -topmba.mobi -topnews9.com -topomel.com -toppdu.com -toppiao.net -topproio.com -toprand.com -topsage.com -topscan.com -topsedu.com -topsounded.com -topswim.net -toptastewin.com -topthink.com -topthink.net -toptourservice.com -topu.com -topuc.com -topwalk.com -topwanwan.com -topway.org -topwaysoft.com -topxlc7.com -topys.com -topzj.com -torhea.org -toshiba-gtbs.com -toshiba-semicon-storage.com -toshiba-thpc.com -toshiba-tnis.com -toshow.com -tospur.com -tot.name -totalacg.com -tou360.com -tou70.com -toubang.tv -toucdn.com -touch4.me -touchev.com -touchpal.com -touchrom.com -touchsprite.com -touchsprite.net -touchstudio.net -touchxd.com -touclick.com -touduyu.com -toughcoder.net -tougub.com -touhou.cd -touhou.vote -touid.com -toujidao.com -touker.com -toumiao.com -toupb.com -toupiaoapp.com -touqikan.com -tour110.com -tourhr.com -tourjob.net -tourongjia.com -tourongzi.org -tourscool.com -toursforfun.com -tourye.com -toushibao.com -toutiao-xinwen.com -toutiao.com -toutiao.io -toutiao.org -toutiao11.com -toutiao12.com -toutiao13.com -toutiaoapi.com -toutiaoapp.com -toutiaobashi.com -toutiaobus.com -toutiaocdn.com -toutiaocdn.net -toutiaocloud.com -toutiaocloud.net -toutiaoimg.com -toutiaoimg.net -toutiaojc.com -toutiaolite.com -toutiaolite1.com -toutiaonanren.com -toutiaopage.com -toutiaovod.com -toutiaoyule.com -toutoufc.com -toutoupiao.com -touwenzi.com -touwho.com -touxiang.la -touxiang8.com -touxiangzhan.com -touying.com -touyouh.com -touyouquan.com -touzhibang.com -touzhijia.com -touzi.com -touzikuaibao.com -touzizn.com -tower.im -towinor.com -townsky.com -towntour.net -towords.com -towry.me -toxingwang.com -toybaba.com -toycloud.com -toyean.com -toysir.com -toysuperman.com -tp8.me -tpbar.com -tpbook.com -tpdoc.com -tpkey.com -tplife.com -tplm123.com -tplogincn.com -tpooo.com -tpoxiaozhan.com -tpsxs.com -tpturang.com -tpy10.net -tpy100.com -tpyboard.com -tpywlkj.net -tpyyes.com -tq163.com -tq321.com -tq520.net -tqcj.com -tqcto.com -tqedu.com -tqedu.net -tqiantu.com -tql.ink -tqle.com -tqmall.com -tqmdp.net -tqqa.com -tqqnbs.com -tqsafe.com -tqschool.net -tqxz.com -tqybw.net -tr-mail.ru -tr0y.wang -tr518.com -trace4me.com -tracefact.net -traceint.com -track-roller.com -trackingio.com -trackingmore.com -tracup.com -tracyclass.com -trade-plug.net -trade2cn.com -tradeask.com -tradehome.org -tradeidc.com -tradeknow.com -tradeleo.com -trademdj.com -traderwork.com -tradew.com -tradow.com -trainby.com -traineexp.com -trainingipv6.com -trait-wholesale.com -tranbanker.com -tranbbs.com -trans4e.com -transcn.org -transensesoft.com -transformer-cn.com -transfu.com -transfun.net -translate.googleapis.com -translation-dictionary.net -translationchina.com -transn.com -transnbox.com -transparcel.com -transplendor.com -transportjp.com -transrush.com -transtill.com -transwarp.io -transwiki.org -tratao.com -travel6.co.uk -traveldba.com -traveller2.com -travellingwithhotel.com -travelsky.com -travelsky.net -travelwuhan.com -travelyee.com -trc.com -trcoin.com -treation.com -treehousesub.com -treelib.com -treetwins.com -treeyee.com -trekin.space -trekiz.com -trend6.com -trendscar.com -trendsmen.com -trendtokyo.com -tretars.com -trhj.net -trhos.com -trhui.com -trinitigame.com -trinitigames.net -trioisobardev.com -trip8080.com -tripbaba.com -tripbe.com -tripc.net -tripdv.com -triphr.com -triplexservice.com -trippanda.com -tripren.com -tripsmc.com -tripvivid.com -tripwirechina.com -tripzm.com -triring.com -triumbest.net -trjcn.com -trjcn.net -trjggs.com -trkeyboard.com -troila.com -trojantesting.com -trojx.me -tronixin.com -trpcdn.net -trsoft.vip -trsoft.xin -trsol.com -trt.hk -trucy.org -trueart.com -truebuty.com -trueeyu.com -trueland.net -trueme.net -truemv.com -truerun.com -truesing.com -trufun.net -trusfort.com -trust-one.com -trust400.com -trustasia.com -trustedsign.com -trustexporter.com -trustkernel.com -trustlife.com -trustmover.com -trustmta.com -trustocean.com -trustsoc.com -trustutn.org -trwl.net -tryenough.com -tryfun.com -tryineapp.com -trylist.com -trylist.net -trymoka.com -trysenz.com -tryurbest.com -tryxue.com -ts-cooling.com -ts-juheng.com -ts100.com -ts166.net -ts168.net -ts16949px.com -ts16949rz.org -ts1889.com -ts95.com -tsciming.com -tscmjt.com -tsddu.com -tsdlp.com -tsdm.net -tsdmw.net -tsdxb.com -tsfucai.com -tsg-online.net -tsggwl.com -tshaisen.com -tshe.com -tshe.me -tshell.net -tshiny.com -tshmkj.com -tshtech.com -tsichuan.com -tsinghua-getinfo.com -tsinghuabook.com -tsinghuaic.com -tsinghuaicwx.com -tsinghuajournals.com -tsinghuan.com -tsinghuawoman.com -tsingj.com -tsingming.com -tsingoofoods.com -tsingpost.com -tsingtoo.com -tskscn.com -tskscn.org -tslapinshang.com -tsljzs.com -tslsmart.com -tsmtkj.com -tsmxs.com -tsnz.net -tsoo.me -tsov.net -tsp189.com -tspsy.com -tsqt.net -tsqw.com -tsrcw.com -tssakura.com -tsshunxin.com -tssns.net -tsstorry.com -tstdtz.com -tstrs.me -tsu.tw -tsw18.com -tswuby.com -tsxcx.xyz -tsxinx.com -tsying.com -tsyqb.com -tsyzm.com -tsz.com -tszckj.com -tszs360.com -tszww.net -tszyzx.com -tt-beian.com -tt-bike.com -tt-ly.com -tt-tz.com -tt116114.com -tt1386.com -tt1h.com -tt286.com -tt56w.com -tt65.org -tt711.com -tt86.com -tt96596.com -ttadm.com -ttaidu.com -ttbba.com -ttbbss.com -ttbc33.com -ttbcdn.com -ttcad.com -ttcdy.com -ttdailynews.com -ttdbj.com -ttdong.com -ttdown.com -ttdtweb.com -ttdytt.com -ttdytt.net -ttete.xyz -ttf5.net -ttfanwen.com -ttgjx.com -tth1688.com -tthbw.com -tthigo.com -ttic.cc -ttigame.com -ttime.com -ttionya.com -ttjd365.com -ttjianbao.com -ttjj.org -ttkdex.com -ttkefu.com -ttkkuu.com -ttkkv.com -ttkmj.net -ttkmj.org -ttkuan.com -ttkyy.net -ttll.cc -ttlqb.com -ttlsa.com -ttlutuan.com -ttmark.com -ttmd5.com -ttmeishi.com -ttmnq.com -ttmv.com -ttn8.com -ttoou.com -ttpaihang.com -ttpaper.com -ttpet.com -ttplayer.com -ttpod.com -ttpp.com -ttppq.com -ttq.com -ttrar.com -tts8.com -ttsfgyrj.com -ttshengbei.com -ttsmmwb.com -ttsq6.net -ttstream.com -ttsunion.com -ttsz8.com -ttthing.com -tttuangou.net -tttxf.com -tttz.com -ttufo.com -ttuku.com -ttunion.com -ttunion.info -ttuu.com -ttvdo.com -ttwanjia.com -ttwebview.com -ttwg.net -ttwoyun.com -ttwx.com -ttxn.com -ttxs123.net -ttxsapp.com -ttxspcx.com -ttxuanpai.com -ttxunta.com -ttxycdn.com -ttyingqiu.com -ttyjf.com -ttyl5.com -ttymq.com -ttyongche.com -ttyqm.com -ttys5.com -ttysq.com -ttyyuuoo.com -ttz.com -ttzhushou.com -ttzw.com -ttzw.tv -ttzx.tv -ttzyw.com -tu11.com -tu520.cc -tu6.la -tu8.cc -tu960.com -tuan001.com -tuan800.com -tuan800.net -tuanai.com -tuanche.com -tuancu.com -tuandai.com -tuanduishuo.com -tuangoutemai.com -tuanhuiwang.com -tuanidc.net -tuanimg.com -tuanjianjian.com -tuanjiebao.com -tuankezhan.com -tuanlego.com -tuanlin.net -tuanping.com -tuanshan.com -tuanxia.com -tuanxue360.com -tuanxue360.net -tuanyx.com -tubachina.com -tubangzhu.com -tubaobao.com -tubaobaoqm.com -tubaoveneer.com -tubaoyz.com -tubebbs.com -tubegetpro.com -tubiaoxiu.com -tuboshu.com -tubutu.com -tucao.tv -tucaojie.com -tuchong.com -tuchong.net -tuchuang.org -tuchuang001.com -tuchuang188.com -tucia.net -tucoo.com -tudai.cc -tudan.cc -tudou.com -tudou1238.com -tudouh5.com -tudoupe.com -tudouui.com -tudouxy01.com -tudouyx.com -tudown.com -tudu.com -tudu.im -tuer.me -tugou.com -tugouli.com -tuguaishou.com -tuguoabc.com -tuhaihe.com -tuhaokuai.com -tuhu.com -tuhu.org -tuhu.work -tuhusmart.com -tui-8.com -tui18.com -tui56.com -tuiabq.com -tuiapple.com -tuiar.com -tuiayonghu.com -tuibamboo.com -tuibat.com -tuibench.com -tuiberry.com -tuibit.com -tuicoco.com -tuicool.com -tuidc.com -tuideli.com -tuidove.com -tuidragon.com -tuifeiapi.com -tuifish.com -tuifrog.com -tuiguangdns.com -tuiguangpingtai.com -tuijianshu.net -tuijie.cc -tuili.com -tuili8.com -tuilidashi.xin -tuilie.com -tuilisr.com -tuiliu.net -tuiliw.com -tuilixy.net -tuimax.com -tuimob.com -tuimz.com -tuipeanut.com -tuipear.com -tuipenguin.com -tuipine.com -tuipink.com -tuiplay.com -tuipony.com -tuiq.net -tuirabbit.com -tuirice.com -tuishao.net -tuishark.com -tuishiben.com -tuishujun.com -tuisnake.com -tuistone.com -tuitiger.com -tuitui99.com -tuituifang.com -tuituitang.com -tuiwailian.com -tuixue.online -tuizx.com -tujia.com -tujian.com -tujidu.com -tujie8.com -tujiwar.com -tujixiazai.com -tukaxiu.com -tuke88.com -tukexiu.com -tukexw.com -tukkk.com -tukong123.com -tuku.cc -tuku.com -tukucc.com -tukumanhua.com -tukuppt.com -tukuwa.com -tulading.com -tulaoshi.com -tuliaohr.net -tuling123.com -tulinggame.com -tulingtec.com -tuliren.com -tuliu.com -tumajewelry.com -tumanyi.com -tumblr.cc -tumeinv.com -tumukeji.com -tumunity.com -tumuzhe.com -tunanchangban.com -tungshungroup.com -tungsten-alloy.com -tungsten-bar.com -tungsten-copper.com -tungsten-jewellery.com -tungsten-powder.com -tuniu.cc -tuniu.com -tuniu.net -tuniu.org -tuniucdn.com -tuniuglobal.com -tuniuins.com -tuniuops.net -tunynet.com -tuo-li.com -tuo-pan.com -tuodanyy.com -tuohuangzu.com -tuoluocaijing.com -tuoluozhuan.net -tuoniaox.com -tuotuozu.com -tuoweisi.com -tuoyundan.com -tuozhan028.com -tuozhe8.com -tupai.me -tupian114.com -tupian1234.com -tupian365.com -tupiancunchu.com -tupiankucdn.com -tupianzj.com -tupu360.com -tuputech.com -tupuw.com -tuquu.com -turangyq.com -turbomail.org -turingapi.com -turingbook.com -turingcat.com -turingdi.com -turingtopia.com -turnitin.org.in -turnitincn.com -turnitinuk.net -tusapi.com -tusay.net -tuscdn.com -tusdk.com -tushare.org -tushare.pro -tushifu.com -tushu001.com -tushu007.com -tushugu.com -tushuguan.cc -tushumi.com -tushupan.com -tushupdf.com -tushuu.com -tusij.com -tusooo.com -tuspass.com -tuspass.net -tusstar.com -tusuku.com -tutechanhb.com -tutorialdocs.com -tutraccoon.com -tutu001.com -tutuapp.com -tutucloud.com -tutuera.com -tutuge.me -tutuim.com -tutupan.com -tuwan.com -tuwan21.com -tuwandata.com -tuwangwang.com -tuwenba.com -tuweng.com -tuwenla.com -tuwenzhibo.com -tux.red -tuxiaobei.com -tuxiu.com -tuya.com -tuyacn.com -tuyansuo.com -tuyaya.com -tuyiqi.com -tuyitu.com -tuyiyi.com -tuyoo.com -tuyou.me -tuyoujp.com -tuyoumi.com -tuyuantech.com -tuzhan.com -tuzhan.net -tuzhanai.com -tuzhanh5.com -tuzhaozhao.com -tuzhizhijia.com -tuzi123.com -tuzi8.com -tuziyangzhi.com -tv0001.com -tv002.com -tv189.com -tv2stb.com -tv432.com -tv5box.com -tvandnet.com -tvapk.com -tvapk.net -tvb1.cc -tvbbj.com -tvblack.com -tvbwind.com -tvcbook.com -tventry.com -tvfanqie.com -tvflnet.com -tvfuwu.com -tvguo.tv -tvhome.com -tvhuan.com -tvjianshen.com -tvkou.com -tvkuai.com -tvlele.com -tvmao.com -tvmcloud.com -tvmining.com -tvn.cc -tvoao.com -tvos.com -tvroms.com -tvscn.com -tvsou.com -tvt.im -tvtsg.com -tvxio.com -tvyouxuan.com -tvzhe.com -tvzn.com -tw2sm.com -tw7s.com -twanxi.com -twapk.com -twcad.com -twcczhu.com -twd2.me -twd2.net -twdm.net -tweakcube.com -twguozao.com -twh5.com -twinkleunion.com -twinsenliang.net -twlkbt.com -twoarmy.com -twocucao.xyz -twofei.com -tworice.com -twotiger.com -twsapp.com -twtstudio.com -twtym.com -twwtn.com -twwtn.net -twyxi.com -tx-livetools.com -tx-livetools.wang -tx-trans.com -tx009.com -tx163.com -tx29.com -tx3ka.com -tx5d.com -txbapp.com -txbimg.com -txcbwgg.com -txcdns.com -txdai.com -txds888.com -txdy01.com -txdzs.com -txdzw.com -txfeiyu.com -txffp.com -txfund.com -txga.com -txianning.com -txip8.com -txitech.com -txjszz.com -txlt.com -txmeiju.com -txon.net -txooo.com -txrjy.com -txrzx.com -txsc100.com -txsdk.com -txslicai.com -txssw.com -txt07.com -txt321.com -txt66.com -txt81.com -txt909.com -txt97.com -txt99.cc -txt99.co -txt99.com -txtbbs.com -txtbook.net -txtduo.com -txtreader.org -txttool.com -txtuu.com -txtv97.com -txtwork.com -txtxz.com -txu.la -txwb.com -txweekly.com -txwestart.com -txwgame.com -txwy.com -txwy.com.tw -txxbxx.com -txxtw16.com -txy8.com -txyapp.com -txyes.com -txylab.com -txzad.com -txzdq.com -ty-im.com -ty2y.com -ty8866.com -tyalxx.com -tybai.com -tyc100.com -tychio.net -tychou.com -tycits.com -tycmbvb.com -tycqxs.com -tycredit.com -tyfo.com -tygasoft.com -tyhjzx.com -tyhtqc.com -tyhuoyun.com -tyi365.com -tyinstall.com -tyjinyun.com -tyjlwy.com -tyjmmy.com -tyjmqz.com -tyksl.com -tyldclub.com -tylll.com -tyloo3d.com -tymakerspace.com -tymcdn.com -tyn.cc -tyncar.com -tyouai.com -tyouquan.com -tyouwang.com -typany.com -type.so -typecho.me -typecho.wiki -typechodev.com -typecodes.com -tyr.gift -tyrad.cc -tyrantdb.com -tyread.com -tyriejl.com -tysj365.com -tysjyjy.com -tyst88.com -tysurl.com -tyswmp.com -tyswy.com -tyszy.com -tytlj.com -tytuyoo.com -tyust.net -tyuyan.com -tyuyan.net -tywbw.com -tywh.com -tywxw.la -tyy6.com -tyymt.com -tyzscl.com -tz-dsp.com -tz-wf.com -tz089.com -tz12306.com -tz1288.com -tz1980.com -tz8.com -tz911.com -tzbank.com -tzbank.net -tzbao.com -tzcul.com -tzdjzu.com -tzdkjr.com -tzesf.com -tzfdc.com -tzfeize.xyz -tzfuke.com -tzgcjie.com -tzhealth.com -tzhwcc.com -tzidc.com -tzidt.com -tzjxl.com -tzkameng.com -tzlib.net -tzm66.com -tzmauto.com -tzres.com -tzrl.com -tzsnw.com -tztusi.com -tzxgzk.com -tzxwzx.com -tzye123.com -tzyg.org -tzylczy.net -tzysbwg.com -u-cooler.com -u-jingling.com -u-link.org -u-om.com -u-qun.com -u-road.com -u-tide.com -u005.com -u14.com -u148.net -u17.com -u17i.com -u17t.com -u193.com -u21a.com -u22e.com -u2j2ha.com -u3dc.com -u3dol.com -u3v3.com -u51.com -u520.net -u5h5.com -u5wan.com -u69cn.com -u6idc.com -u6u.com -u77.com -u78.com -u7u9.com -u8sy.com -u8yx.com -u9game.net -u9h.com -u9time.com -u9u8.com -u9u9.com -u9youxi.com -ua.mk -ua168.com -uadrc.com -uadscc.com -uaedata.com -uao-online.com -uao.so -uauc.net -uavvv.com -uawnqe.com -uayangtze-volga.org -ub-os.com -ub.cc -ub555.cc -ub666.cc -uban.com -ubangmang.com -ubernihao.com -ubersz.com -ubestkid.com -ubetween.com -ubgame.com -ubicdn.com -ubijoy.com -ubismartparcel.com -ubja.vip -ubk22.com -ubmconlinereg.com -uboat100.com -ubooo.com -uboxol.com -uboxsale.com -ubs001.com -ubssdic.com -ubssdic.com.hk -ubtrobot.com -ubuntubar.com -ubuntukylin.com -ubuntukylin.org -ubuntuqa.com -ubuuk.com -uc-union.com -uc108.com -uc123.com -uc129.com -uc138.com -uc1z.com -uc23.net -uc56.com -uc669.com -ucai123.com -ucaiyuan.com -ucaiyun.com -ucancs.com -ucantech.com -ucantech.net -ucardpro.com -ucarinc.com -ucbug.com -uccastore.com -uccav.xyz -uccheck.net -uccvr.com -ucdchina.com -ucdok.com -ucdrs.net -ucfly.com -ucfpay.com -uchangdi.com -uchis.com -uchuanbo.com -uchuhimo.me -ucicq.com -ucjoy.com -uckendo.com -ucloudgda.com -ucly.net -ucnano.com -ucnest.com -ucoin.pw -ucpaas.com -ucpchina.com -ucpopo.com -ucren.com -uctrac.com -uctxt.com -ucuuc.com -ucweb.com -ucxinwen.com -ucxzz.com -ucying.com -uczhidao.com -ucziliao.com -uczzd.com -uczzd.net -udache.com -udalogistic.com -udamall.com -udangjia.com -udashi.com -udaxia.com -udbac.com -udcredit.com -uddtrip.com -udecig.com -udeepin.com -udfex.com -udonmai.com -udpis.com -udpwork.com -udrig.com -udsdown.xyz -ue2018ff.com -ue8898lj.com -ueadlian.com -uebao.com -uebilling.com -ued163.com -uedbox.com -uedhome.net -uedna.com -uedsc.com -uee.me -ueeen.com -ueeshop.com -uehtml.com -ueibo.com -uelike.com -uemo.net -uepei.com -ueren.com -uestcedu.com -uestcguoji.com -ueuz.com -ueview.com -uewaf.com -uf-crm.com -uf-tobacco.com -uf0088.vip -ufanw.com -ufbar.com -ufcap.com -ufenqi.com -ufhost.com -ufhosted.com -ufida-lcwy.com -ufidaoa.com -ufidawhy.com -ufileos.com -ufirefly.com -ufish.io -ufizl.com -uflowx.com -ufo.club -ufochn.com -ufoer.com -ufofxw.com -ufojia.com -ufojoy.com -ufotm.com -ufovps.com -ug888.com -ugainian.com -ugapi.com -ugbb.com -ugcar.com -ugdtimg.com -ugediao.com -uggas.com -uggd.com -ugirls.tv -ugkeji.club -ugmars.com -ugmjd.com -ugojp.com -ugong.com -ugoshop.com -ugslb.com -ugslb.info -ugslb.net -ugsnx.com -ugubl.net -uhdog.com -uhgal.com -uhomecp.com -uhomes.com -uhouzz.com -uhtao.com -uhuitong.com -ui001.com -ui100day.com -ui4app.com -ui63.com -ui879.com -uibaba.com -uibim.com -uibmm.com -uibobo.com -uibot123.com -uicmall.com -uicom.net -uicool123.com -uid75.com -uidec.com -uidev.tech -uigreat.com -uihacker.com -uiiiuiii.com -uileader.com -uilover.com -uimaker.com -uimix.com -uincall.com -uincall400.com -uincom400.com -uipower.com -uisdc.com -uisheji.com -uishijie.com -uisnetwork.com -uisrc.com -uiste.com -uiu.cc -uiwed.com -ujian.cc -ujifu.com -ujinbi.com -ujing.online -ujipin.com -ujiuye.com -ujwang.com -uk-edu.com -uk-odc.samsungapps.com -ukassignment.org -ukeban.com -ukelink.com -ukelink.net -uker.net -ukh5.com -ukongm.com -ukonline2000.com -ukoo.net -ukpass.org -ukpathway.com -ukraine-beauty.com -ukubang.com -ukui.org -ukulelecn.com -ukulelefan.com -ulaaq.com -ulandian.com -ulaojiu.com -ule.com -ule.hk -ule58.vip -uleapp.com -ulecdn.com -uleek.net -ulhat.com -uliaobao.com -ulikecam.com -ulinix.com -ulink.cc -ulpay.com -ultramanclub.com -ultramanol.com -ulucu.com -ulwgame.com -um88.com -umaman.com -umbpay.com -umcloud.com -umei.cc -umelady.com -umeng.co -umeng.com -umeng.online -umeng100.com -umengcloud.com -umenglog.com -umetrip.com -umi.im -umiall.com -umihome.com -umilu.com -umindex.com -uminehotel.com -umineiot.com -uminsky.com -umivi.net -umiwi.com -umjicanvas.com -umke.shop -uml-tech.com -umlchina.com -umlife.net -umlonline.org -umowang.com -umpay.com -umrhe.com -ums86.com -umsns.com -umtrack.com -umvsoft.com -umykang.com -un-bug.com -un10086.com -un1c0de.xyz -una-ad.com -unages.com -unbuyi.com -uncbd.com -unccr.com -uncle-ad.com -uncledesk.com -unclenoway.com -unclenowayapi.com -unclicks.com -undefined.ltd -underfill.cc -unfish.net -ungifts.com -uni-perfect.com -uni28.com -unicde.com -unicloud.com -unicomjnwy.com -unicomlife.com -unicompayment.com -unicomtest.com -unicon-hibar.com -unicornacg.com -unifull.com -unigress.com -unilz588.com -uninf.com -union-game.com -union-rnd.com -union-wifi.com -union178.com -union400.com -union555.com -union968.com -unionclouds.net -unioncyber.net -unionli.com -unionpay.com -unionpay95516.cc -unionpayintl.com -unionpaysecure.com -unionsy.com -uniontech.com -unionwebpay.com -unionzs.com -uniostay.com -uniow.com -uniplayad.com -uniproud.com -uniqueway.com -uniscope.com -unisedu.com -unisemicon.com -unisguard.com -unishy.com -unisoc.com -unisound.com -unispim.com -unisscan.com -unissoft.com -unistc.com -uniswdc.com -unitedmoney.com -unitek-it.com -uniteyun.com -unitop-apex.com -unity3d8.com -unitymanual.com -uniview.com -uniworldart.com -unix5.com -unixfbi.com -unixhot.com -unixidc.com -unixso.com -unizai.com -unjeep.com -unjmz.com -unjs.com -unlimax.com -unlimitedeos.com -unmsg.com -unnnnn.com -unnue.com -unohacha.com -unordered.org -unpcn.com -unqu.com -unsemi.com.tw -unspay.com -unsuv.com -unsv.com -untforo.com -unxmail.com -unzg.com -uo12.com -uodoo.com -uoeee.com -uofon.com -uoften.com -uohchina.com -uoj.ac -uoko.com -uomg.com -uono4521.com -uooconline.com -uooioo.com -uoolu.com -uooss.com -uooyoo.com -uoozi.com -uoschina.com -uoser.org -uouo123.com -uovz.com -up360.com -up4dev.com -up71.com -upai.com -upaidui.com -upairs.com -upaiyun.com -upan.cc -upanboot.com -upandashi.com -upanok.com -upanshadu.com -upanxitong.com -upbz.net -upcdn.net -upchina.com -upchinapro.com -upchinaproduct.com -upcyclemaster.com -upd.kaspersky.com -update.googleapis.com -updates-http.cdn-apple.com -updates-http.cdn-apple.com.akadns.net -updba.com -updrv.com -upecp.com -upesn.com -upho2015.com -upimgku.com -upin.com -upkao.com -upktv.com -uplinux.com -upliu.net -uploadlog.com -uplookedu.com -uplooking.com -upnb.com -uppsd.com -upqzfile.com -upqzfilebk.com -ups-huawei.net -ups.ksmobile.net -ups001.com -upsapp.com -upst86.com -upsunet.com -uptougu.com -upupbug.com -upupfile.com -upupoo.com -upupw.net -upwardsware.com -upwith.me -upx8.com -upyun.com -upzxt.com -uqche.com -uqd1.net -uqee.com -uqeegame.com -uqer.io -uqidong.com -uqidong.net -uqite.com -uqq2.com -uqseo.com -uqude.com -uqulive.com -uqybs.com -uqyqcuq.ml -urart.cc -urbanchina.org -urbanmatters.com -urbetter.com -urbetter.net -urcb.com -urcities.com -urgc.net -uri6.com -url-test.com -url.ms -url7.me -urlos.com -urlteam.org -urovo.com -urovoworld.com -ursb.me -urselect.com -urtrust.com -us-ex.com -us35.com -us7.com -usa-idc.com -usaas.net -usaedu.net -usagaa.com -usahaitao.com -usakongjian.net -usaliuxue.com -usaobb.com -usaphoenixnews.com -usashopcn.com -usbabyada.com -usbing.com -usbmi.com -usbxyz.com -uschinapress.com -uscnk.com -uscxm.com -usd-cny.com -usdxz1.com -usdxz1.net -use-trust.com -useaudio.com -usecubes.com -usee123.com -userhostting.com -userresearch.net -useso.com -usewo.com -usfcw.com -ushaqi.com -ushendu.com -ushengame.com -using.club -usingde.com -usingwin.com -usitour.com -usitrip.com -usjuw.com -usnook.com -usocialplus.com -usoftchina.com -usonetrip.com -uspard.com -ustack.com -ustalk.com -ustc.edu -ustcers.com -ustclug.org -ustui.com -usu8.com -usuredata.com -uszcn.com -ut7.com -ut8d.com -utan.com -utanbaby.com -utc-ic.com -utdandan.com -utecbj.com -utepo.com -utf8.hk -uthinks.com -utiankong.com -utkang.com -utogame.com -utom.design -utoper.com -utourworld.com -utovr.com -utransm.com -uu.cc -uu.me -uu08.net -uu1.com -uu1314.com -uu178.com -uu361cn.com -uu38.com -uu41.com -uu456.com -uu55.tv -uu66.com -uu89.com -uu898.com -uuaa.net -uuaoz.com -uubookwb.com -uuboos.com -uucolor.com -uudsp.com -uuecs.com -uuff.com -uufund.com -uugai.com -uugame.com -uugtv.com -uugu.org -uuhall.com -uuhimalayanqm.com -uuhy.com -uuid.online -uuimg.com -uukkuu.com -uulucky.com -uulux.com -uumachine.com -uumnt.cc -uumnt.com -uunice.com -uunt.com -uupaotui.com -uupark.com -uupee.com -uupei.com -uupoop.com -uupt.com -uuqupu.com -uuradio.com -uus8.com -uusama.com -uusee.com -uusky.com -uusoo.net -uusos.com -uustory.com -uustv.com -uusucai.com -uutop.com -uutuu.com -uuu9.com -uuudo.com -uuuo.com -uuutu.com -uuvisa.com -uuvps.com -uuwego.net -uuwhg.com -uuwow.com -uuwtq.com -uuxn.com -uuxs.net -uuyoyo.com -uuzhufu.com -uuzo.net -uuzu.com -uuzuonline.com -uuzuonline.net -uuzz.com -uvexperience.com -uvov.com -uvu.cc -uvuvv.com -uw3c.com -uw9.net -uwa4d.com -uwan.com -uwan5.com -uwenku.com -uwexp.com -uworter.com -uwowo.com -uwp.mobi -ux18.com -ux87.com -ux98.com -uxacn.com -uxahz.com -uxdc.net -uxdc.org -uxianhu.com -uxicp.com -uxigo.com -uxin.com -uxingroup.com -uxpi.net -uxxsn.com -uya100.com -uyan.cc -uyanip.com -uycnr.com -uyess.com -uyi2.com -uyou.com -uyouqu.com -uyshipin.com -uyuan.info -uyueread.com -uyunad.com -uyunbaby.com -uyuyao.com -uyyidc.com -uz178.com -uz73.com -uz73.net -uzai.com -uzaicdn.com -uzer.me -uzhongtou.com -uzing.net -uzise.com -uzones.com -uzshare.com -uzuzuz.com -uzzf.com -v-56.com -v-acfun.com -v-beautysalon.com -v-bilibili.com -v-danci.com -v-got.com -v-ka.com -v007.net -v114.com -v13299.com -v17go.com -v1bo.com -v1h5.com -v1lady.com -v1pin.com -v1tuan.com -v1tx.com -v2ambition.com -v2ex.cc -v2geek.com -v2kt.com -v2land.net -v2make.com -v2url.com -v3best.com -v3edu.org -v4.cc -v4dwkcv.com -v5.com -v54321.com -v58003.com -v58008.com -v5bjq.com -v5cam.com -v5cg.com -v5dun.net -v5fox.com -v5kf.com -v5music.com -v5pc.com -v5ppt.com -v5tv.com -v66666666.com -v6dp.com -v6ok.com -v7799.com -v78q.com -v86.org -v8d8.com -v977.com -v9b5n91.com -va-etong.com -va88.pw -vaakwe.com -vacmic.com -vaecn.com -vaeliu.com -vaikan.com -vakku.com -valid.apple.com -valid.origin-apple.com.akadns.net -validform.club -valinbl.com -valinresources.com -value500.com -valuecome.com -valuedshow.com -valuepr.net -valueq.com -valurise.com -vamachina.com -vamaker.com -van-u.com -vanbaolu.com -vance-commerce.com -vanch.net -vancharts.com -vanchhandheld.com -vanchiot.com -vanchip.com -vanchiptech.com -vanchu.com -vancir.com -vancl.com -vanclimg.com -vandream.com -vanfo.net -vanfun.com -vanggame.com -vanimg.com -vankang.com -vanke.com -vankeservice.com -vankeservice.mobi -vankeweekly.com -vanlos.com -vanmai.com -vanmatt.com -vanrui.com -vanterc.com -vants.org -vapee.com -vapejoin.com -vapps.me -vaptcha.com -vaptcha.net -varena.com -varhair.com -variflight.com -varmilo.com -vart.cc -vartcn.com -vas.ink -vasdaqh.com -vasee.com -vasoon.com -vauoo.com -vbanzs.com -vbbobo.com -vbidc.com -vbmcms.com -vboba.com -vbooking.net -vbsemi.com -vbsuvb.com -vbuge.com -vbuluo.com -vbuluo99.com -vc800.com -vcb-s.com -vcbeat.net -vcchar.com -vceshi.net -vcg.com -vchangyi.com -vchat5.com -vchatshow.com -vchello.com -vchelp.net -vchome.net -vcimg.com -vcinchina.com -vckai.com -vckbase.com -vcloudgtm.com -vclusters.com -vcneimenggu.com -vcode.cc -vcomic.com -vcomputes.com -vcooline.com -vcore.hk -vcorp.tech -vcpic.com -vcredit.com -vcsint.com -vdaye.com -vdfly.com -vdg.so -vdian.com -vdisk.me -vdncloud.com -vdndc.com -vdnplus.com -vdnsv.com -vdolady.com -vdongchina.com -ve001nz.com -vealandlamar.com -vearne.cc -vecentek.com -vechain.com -vechain.org -vedamobi.com -vedeng.com -veding.com -veedrin.com -veelink.com -veeqi.com -veer.com -veervr.tv -veesing.com -veeteam.com -veevlink.com -veguci.com -veikei.com -veilytech.com -veinbase.com -veken.com -velasx.com -veldkeuken.com -velep.com -velocaps.com -vemvm.com -ventoy.net -ventureinc.net -venucia.com -venustrain.com -vephp.com -verdareto.com -verisilicon.com -veritrans-link.com -verodillan.com -versaloon.com -versun.org -vertuonline.com -ververica.com -very9s.net -verybeaut.com -verycaca.com -verycd.com -verycdn.net -verydns.net -verydoc.net -verydz.com -veryen.org -veryevent.com -verygrass.com -verygslb.com -veryhappy.pw -veryide.com -veryitman.com -veryns.com -veryol.com -verypan.com -verysou.com -verysource.com -verystar.net -veryweibo.com -verywind.com -veryxiang.com -veryys.com -veryzhun.com -vesystem.com -vetchile.com -vexcdn.net -vexnic.net -vf5c.com -vfcsz.com -vfcwb.xyz -vfinemusic.com -vfocus.net -vftfishing.com -vfund.org -vfx123.com -vfxcg.net -vfxcx.com -vfxinfo.net -vg1234.com -vgabc.com -vgfav.com -vgjump.com -vglady.com -vglook.com -vgoapp.com -vgooo.com -vgoyun.com -vgtime.com -vhaey.com -vhall.com -vhallyun.com -vhao123.com -vhostgo.com -vhteam.com -vi21.net -vi586.com -via-cert.com -via-labs.com -via.com.tw -viabtc.com -viaeda.com -vial.cc -viatech.com -viatech.com.tw -viayoo.com -vibaike.com -vic18.com -vicchen.me -vichamp.com -vicigaming.com -vickn.com -vicovico.com -vicp.cc -vicp.net -vicrab.com -vicsdf.com -victory1999.com -vidaa.com -vidarsoft.com -viday.org -videaba.com -videer.net -videocc.net -videocdn.cc -videohupu.com -videoincloud.com -videoipdata.com -videojj.com -videoyi.com -videoyx.com -videozhishi.com -vidoadsplus.xyz -vienblog.com -viewones.com -viewstock.com -viewtool.com -viewtrans.com -viigee.com -viisan.com -viitalk.com -viixin.com -vijos.org -vikduo.com -vikecn.com -villaday.com -villafrancescatti.com -viltd.com -vim.ink -vimage1.com -vimage2.com -vimage4.com -vimge.com -vimicro.com -vimiix.com -vimiy.com -vimjc.com -vimlinux.com -vims04.com -vimsky.com -vimsucks.com -vin114.net -vince.xin -vinceok.com -vinchin.com -vinehoo.com -vinetreetents.com -vingoostation.com -vinjn.com -vinkdong.com -vinllen.com -vinnywang.com -vinoyang.com -vinuxhome.com -vioee.com -violetgo.com -violinerhu.com -violinww.com -vip-cdn.net -vip-wifi.com -vip.com -vip120.com -vip150.com -vip55333.com -vip800.com -vip8849.com -vip9982.net -vipbaihe.com -vipbla.com -vipbuluo.com -vipbxr.mobi -vipchina.com -vipcn.com -vipcto.com -vipdage.com -vipdy.cc -vipersaudio.com -vipfengfei.com -vipfengxiao.com -vipgslb.com -viphxw.com -vipjr.com -vipkaoyan.net -vipkdy.com -vipkid.com -vipkidresource.com -vipkidstatic.com -vipkj.net -vipkoudai.com -vipleyuan.com -vipliangmei.com -viplux.com -vipmaillist.com -vipmando.com -vipmro.com -vipmro.net -viponlyedu.com -vippluspai.com -vipqlz.com -vips100.com -vipshan.com -vipshop.com -vipshopyao.com -vipsinaapp.com -vipsmt.com -vipstatic.com -vipstore.com -viptail.com -viptarena.com -viptcn.com -viptest.net -viptijian.com -vipwaf.com -vipwaf.net -vipwm.cc -vipxap.com -vipxdns.com -vipxdns.info -vipxdns.net -vipyl.com -vipyooni.com -vipzhuanli.com -viqq.com -virbox.com -vircloud.net -virscan.org -virtualevent.net -virusdefender.net -visa160.com -visa800.com -visabao.com -visadeguo.com -visaforchina.org -visajz.com -visas.to -visaun.com -visbodyfit.com -viseator.com -vishining.com -visionbang.com -visionbbs.com -visioncloudapi.com -visionly.org -visionsoar.com -visionstar-tech.com -visionunion.com -visionvera.com -visitsz.com -viskem.com -vispp.net -vista123.com -vistai.net -vistakatipunan.com -vistastory.com -visualchina.com -visvachina.com -visweet.com -vitagou.com -vitagou.hk -vitamio.org -vitarn.com -vitechliu.com -vitian.vip -vivantecorp.com -vivcms.com -vividict.com -vivienrgs.com -vivifz.vip -vivijk.com -viviv.com -vivo.com -vivoglobal.com -vivokb.com -viweitui.com -viwik.com -vixue.com -vjia.com -vjiazu.com -vjie.com -vjshi.com -vjudge.net -vkaijiang.com -vkehu.com -vkelai.com -vkemai.com -vksoft.com -vkvr.net -vl520.com -vlambda.com -vlan9.com -vlandgroup.com -vlandhome.com -vlcms.com -vliang.com -vlightv.com -vlinkage.com -vlinke.com -vlong.tv -vlongbiz.com -vlwoo.com -vlzp.com -vm.sg -vmall.com -vmallres.com -vmanhua.com -vmaqinnews.com -vmartaw.com -vmate.in -vmdo.net -vmengblog.com -vmeti.com -vmfor.com -vmgirls.com -vmicloud.com -vmoiver.com -vmonkey.mobi -vmovier.cc -vmovier.com -vmoviercdn.com -vmsky.com -vmvps.com -vnet.mobi -vnoke.com -vnpie.com -vns5720.com -vnsdl.com -vnsiubvgs.com -vnsr6788.com -vnvshen.com -vnylzny0.com -vnzmi.com -voa365.com -vobao.com -vobao.mobi -vocalmiku.com -voccdn.com -vocinno.com -vodjk.com -vodxc.com -vodxc.tv -vohringer.com -voicedic.com -voicer.me -voidcc.com -voidcn.com -voidking.com -voidme.com -voiweb.com -vojs.tv -vokop.com -vol.moe -volchina.com -voldev.net -voldp.com -volit.com -volmoe.com -voltmemo.com -voltsky.com -volumes.cc -voluptuacity.com -von-sh.com -vona.xin -vonets.com -vonfry.name -vooec.com -voole.com -voole.net -voora.net -voovle.net -voovlive.com -voovmeeting.com -vortexfun.com -vote8.cc -vote8.com -vp3u.com -vpadn.com -vpal.com -vpalstatic.com -vpansou.com -vpbus.com -vpcs.com -vpeitu.com -vpesports.com -vpgame.com -vpgcdn.com -vpiaotong.com -vpie.net -vpimg1.com -vpimg2.com -vpimg3.com -vpimg4.com -vplayer.net -vpn39.com -vpnsoft.net -vps.im -vps.sh -vps234.com -vpsaa.com -vpsaa.net -vpscang.com -vpsdawanjia.com -vpsdx.com -vpser.net -vpskk.com -vpsmm.com -vpsor.com -vpsqb.com -vpsrb.com -vpsrr.com -vpssir.com -vpsss.net -vpsxxs.com -vpszh.com -vqs.com -vqudo.com -vqudochina.com -vqxfj.bar -vr-cat.com -vr1000.com -vr186.com -vr42.com -vr5008.com -vrbeing.com -vrbi.viveport.com -vrbig.com -vrbrothers.com -vrcfo.com -vrdou.com -vredian.com -vrerse.com -vrgame520.com -vrguancha.net -vrjibao.com -vrjie.com -vrlequ.com -vrmvip.com -vroan.com -vrpowder.com -vrsat.com -vrshendeng.com -vrwuhan.com -vrzb.com -vsaker.com -vsane.com -vsbclub.com -vsdhf.com -vsens.com -vshangdaili.com -vshare.com -vsharecloud.com -vsharing.com -vshengsu.com -vshouce.com -vshuoshuo.com -vslai.com -vsledclothes.com -vsnoon.com -vsnoon.net -vsnoon.org -vsnuf.com -vsochina.com -vsocloud.com -vspk.com -vspk.net -vsppt.com -vsread.com -vst5.com -vstab.com -vstart.net -vstecs.com -vstmv.com -vstou.com -vsuch.com -vsun.com -vsyo.com -vtache.com -vte8.com -vteamgroup.com -vtears.com -vtepai.com -vtepai.net -vtibet.com -vtoutiao.cc -vtrois.com -vtuzx.com -vue-js.com -vue5.com -vuejscaff.com -vuelaravel.net -vuevideo.net -vulbox.com -vulnhunt.com -vulogcn.com -vultr1.com -vultrcn.com -vultrer.com -vultrla.com -vultrvps.com -vunion.net -vutimes.com -vutoo.com -vuvps.com -vux.li -vv181.com -vv8.com -vv881.com -vv8yx.com -vv91.com -vv9vv.com -vvaii.com -vvbtc.com -vvdeal.com -vvdoit.com -vvebo.me -vvfeng.com -vvic.com -vvipcdn.com -vvjob.com -vvkaoyan.com -vvmeiju.com -vvo2o.com -vvpncdn.com -vvpool.com -vvtor.com -vvup.net -vvv.io -vvvcd.com -vvvdj.com -vvvfans.com -vvzero.com -vwanka.com -vweizhan.com -vwgem.com -vwvvwv.com -vwwmsd.com -vx.com -vx888.net -vxgua.com -vxia.net -vxiaocheng.com -vxiaoxin.com -vxinyou.com -vxplo.com -vxposed.com -vxsnk.com -vxuey.com -vycool.com -vyg.net -vyin.com -vyougame.com -vysj.com -vyuan8.com -vyun.com -vzan.cc -vzan.com -vzhang.net -vzhantong.com -vzhifu.net -vzhou.net -vzhuo.com -vzhushou.com -vzidc.com -vzkoo.com -vzmapp.com -vzuu.com -w-e.cc -w0lker.com -w10a.com -w10xitong.com -w10xz.com -w10zj.com -w123w.com -w1365.com -w17933.com -w18.net -w1989.com -w20.net -w218.com -w2bc.com -w2fzu.com -w2gou.com -w333.com -w351.com -w3cay.com -w3cbus.com -w3cfuns.com -w3chtml.com -w3cl.com -w3cplus.com -w3cschool.cc -w3cshare.com -w3ctalk.com -w3ctech.com -w3cui.com -w3cways.com -w3guo.com -w3h5.com -w3help.org -w3pop.com -w3tong.com -w3tt.com -w3xue.com -w7.cc -w7000.com -w8xitong.com -w918.com -wa-ai.com -wa5.com -wa5as4.com -waaaat.com -waakee.com -wabcw.info -wabi.com -wabuw.com -wacai.com -wacaiyun.com -wacaoren.net -wacdn.com -wacths.com -wadao.net -wader1714.com -wadmz.com -waduanzi.com -waerfa.com -waf.cx -wafcn.com -wafunny.com -waheaven.com -wahlap.com -wai-mao.org -waibao123.com -waibao12333.com -waibaodashi.com -waibo.wang -waig8.com -waigame.com -waigf.com -waiguofang.com -waihui50.com -waihui888.com -waihuigu.net -waihuo.com -wailaishop.com -wailianvisa.com -waima.com -waimao6.com -waimaolangtz.com -waiqin365.com -waisir.com -waitig.com -waitingfy.com -waitsun.com -waiwenfanyi.com -wajueji.com -wakatool.com -wakedata.com -waketu.com -wakeup.fun -walahe.com -walanwalan.com -walatao.com -walekan.com -wali.com -walibao.com -walidream.com -walimaker.com -walkerdu.com -walknode.com -walkthechat.com -wall321.com -wallba.com -wallcoo.com -wallcoo.net -walle-web.io -wallet.io -walletio.io -wallpapersking.com -wallstcn.com -wallstreetcn.com -wally.in -wamawama.com -wamila.com -wan.cc -wan.com -wan.wang -wan160.com -wan25.com -wan32.com -wan5d.com -wan68.com -wan7.xin -wan76.com -wan77.com -wan8.com -wan95.com -wana98.com -wanbang365.com -wanbaoju.com -wanbizu.com -wancai.com -wancaibb.com -wancaiinfo.com -wancaomei.com -wanche100.com -wancheng168.com -wanchengwenku.com -wanchenzg.com -wanchezhijia.com -wand6.com -wanda-cti.com -wanda-gh.com -wanda-group.com -wandacinemas.com -wandafilm.com -wandahotelinvestment.com -wandahotels.com -wandamoviepark.com -wandanqu.com -wandaplazas.com -wandarealm.com -wandasportstravel.com -wandavista.com -wandhi.com -wandianshenme.com -wandodo.com -wandoer.com -wandouip.com -wandoujia.com -wandouys.com -waneziyuan.com -wanfangdata.com -wanfangqikan.com -wanfangs.com -wanfangtech.com -wanfantian.com -wanfem.com -wanfn.com -wang-li.com -wang-nan.com -wang-russell.cc -wang1314.com -wang1314.net -wang13607.com -wang502.com -wanga.me -wangbixi.com -wangcaigu.com -wangcaio2o.com -wangcaiwang.com -wangchuan.wang -wangchujiang.com -wangchunsheng.com -wangcms.com -wangdaibus.com -wangdaicaifu.com -wangdaichina.com -wangdaidongfang.com -wangdaidp.com -wangdaijiamen.com -wangdaijianwen.com -wangdaijin.com -wangdaileida.com -wangdainengliang.com -wangdaishikong.com -wangdaizhijia.com -wangdalao.com -wangdali.net -wangdaodao.com -wangdian.wang -wangdianmaster.com -wangdongjie.com -wangeditor.com -wangejiba.com -wangfanwifi.com -wangfujing.com -wangfushipin.com -wanggou.com -wanggou236.com -wanggouyizu.com -wangguai.com -wanghaida.com -wanghairead.com -wanghongclub.net -wanghualang.com -wanghz.com -wangi.cc -wangid.com -wangjianshuo.com -wangjie.org -wangjinle.com -wangjubao.com -wangjunwei.com -wangkl.com -wangkx.xyz -wangle.com -wangleipeng.com -wanglibao.com -wanglids.com -wanglu.info -wangluojianshen.com -wangluoliuxing.com -wangluomeirongyuan.com -wanglutech.com -wanglv.com -wanglv.vip -wangman8.com -wangmeng.com -wangmingkuo.com -wangminping.com -wangmou.net -wangoudianzi.com -wangpan007.com -wangpengcufe.com -wangpiao.com -wangpiao.net -wangpu.net -wangpu365.com -wangpuzhi.com -wangqi.com -wangren.com -wangriyu.wang -wangrongbao.com -wangrunze.com -wangshangfayuan.com -wangshidi.com -wangshu.la -wangshuashua.com -wangshugu.com -wangsongxing.com -wangsu.com -wangsucloud.com -wangting.net -wangtingrui.com -wangtongtong.com -wangtouwang.com -wangtu.com -wangtuizhijia.com -wanguan.com -wangukcn.com -wanguoschool.net -wanguotong.com -wangwango.com -wangweicloud.com -wangwenda.com -wangwo.net -wangxc.club -wangxhr.com -wangxianyuan.com -wangxiao.com -wangxiao.net -wangxiao100.com -wangxiaobao.cc -wangxiaobao.com -wangxin2000.com -wangxingcs.com -wangxinhao.com -wangxinlicai.com -wangyajie.wang -wangyanpiano.com -wangye.com -wangyin.com -wangyingbao.com -wangyou.com -wangyou2.com -wangyq.com -wangyuan.com -wangyuegame.com -wangyutang.com -wangyuwang.com -wangzhan123.net -wangzhan360.com -wangzhan6.com -wangzhanbao.cc -wangzhanbianji.com -wangzhanchi.com -wangzhanmeng.com -wangzhe.com -wangzhengzhen.com -wangzhennan.com -wangziru.com -wanh5.com -wanhedoors.com -wanhenet.com -wanheweb.com -wanhi.com -wanhongji.com -wanhongrui.com -wanhu888.com -wanhuahai.com -wanhuajing.com -wanhui365.com -wanhunet.com -wanimal1983.org -wanjiajinfu.com -wanjiashe.com -wanjidao.com -wanjidashi.com -wanjiedata.com -wanjiedu.com -wanjuanba.com -wanjuhe.com -wanka5.com -wankacn.com -wanke123.com -wanke798.com -wankr100.com -wankukeji.com -wankuwl.com -wanlaiwang.com -wanli.com -wanli51.com -wanlianzhijia.com -wanlitong.com -wanliyouxuan.com -wanmei.com -wanmeila.com -wanmeilink.com -wanmeilr.com -wanmeiyueyu.com -wanmeiyunjiao.com -wanmi.cc -wannabe-online.net -wannaenergy.com -wannar.com -wannengxiaoge.com -wannengzj.com -wannianli.mobi -wannianli.net -wanning1.com -wannuoda.com -wanparks.com -wanplus.com -wanqianyun.com -wanquankan.com -wanredian.com -wanrenxing.net -wanshahao.com -wanshanshuju.com -wanshh.com -wanshhh.com -wanshifu.com -wanshitong.com -wanshouyou.net -wansongpu.com -wantattoo.com -wantexe.com -wantgame.net -wantiku.com -wantong-tech.net -wantouzi.net -wantowan.com -wantrack-nj.com -wantscart.com -wantshopping.ltd -wantumusic.com -wantxt.com -wanvi.net -wanvv.com -wanwanol.com -wanweipc.com -wanweixin.com -wanwudezhi.com -wanwushuo.com -wanwuxia.com -wanww.com -wanxiang100.com -wanxiangqihang.com -wanxm.com -wanyan.com -wanye.cc -wanyiwang.com -wanyixincheng.com -wanyol.com -wanyoo.com -wanyoucn.com -wanyouxi7.com -wanyuanxiang.com -wanyuenet.com -wanyuhudong.com -wanyumi.com -wanyunshuju.com -wanyuwang.com -wanyx.com -wanyxbox.com -wanzaidangxia.com -wanzhao.com -wanzhongcar.com -wanzhouhr.com -wanzhoumo.com -wanzhuang.com -wanzhuanhulian.com -wanzhuanlea.com -wanzhuanmobile.com -wanzhucdn.com -wanzhugs.com -wanzi.cc -wanzi.com -wanzui.com -wanzuile.com -waoo.cc -wap8.win -wapadv.com -waptt.com -waptw.com -wapzk.net -waqiang.com -war3we.net -warcraftchina.com -warestage.com -wargamecn.com -warmcolor.net -warstudy.com -warsu.com -warting.com -was-expo.com -wasair.com -waseeo.com -washpayer.com -wasoinfo.com -wasu.com -wasu.tv -watanabe-mayu.com -watch-life.net -watchleader.com -watchstor.com -watchtop.com -water520.com -watercubeart.com -watergasheat.com -watertek.com -watertu.com -wauee.com -wauee.net -wauzi.net -wave-game.com -wave-optics.com -waveshare.net -wavky.com -wavpub.com -wawa.fm -wawa114.com -wawayaya.net -waxrain.com -waxxh.me -way4ever.com -wayboosz.com -wayhu8.com -wayingyong.com -waylon.wang -waynetechs.com -wayos.com -wayoulegal.com -wayoutv.com -wayoxi.com -waytide.com -waytit.com -wayzim.com -wazhuti.com -wb0311.com -wb133.com -wb321.com -wb3399.vip -wb699.com -wbangdan.com -wbdacdn.com -wbiao.co -wbiao.com -wbiev.com -wbini.com -wbldjy.com -wbljjy.com -wbo529.com -wbolt.com -wbpluto.com -wbpvc.com -wbsp.net -wbsrf.com -wbsz.com -wbtech.com -wbucs.com -wbw.im -wbxgl.com -wbxs8.com -wbyweb.com -wbzol.com -wc44.com -wcaqq.com -wcarn.com -wcd.im -wcfang.com -wch-ic.com -wcjbb.com -wcloud.com -wcloudpay.com -wcmr0411.com -wcmrpx.com -wcsapi.com -wcsfa.com -wcwlmobi.com -wcxichenqi.com -wcyecs.com -wczf.net -wd0431.com -wd112.com -wd1266.com -wd6667.com -wdace.com -wdashi.com -wdaveh5game.com -wddcn.com -wddream.com -wddun.com -wdfangyi.com -wdfxw.net -wdghy.com -wdh518.com -wdinter.com -wdjimg.com -wdjky.com -wdjl.net -wdku.net -wdl.so -wdliuxue.com -wdmcake.com -wdmuz.com -wdqh.net -wdres.com -wdshouji.com -wdsjz.com -wdsrc.com -wdssmq.com -wdstory.com -wdszb.com -wdtcp.com -wdtianxia.com -wdtlfj.com -wduw.com -wdw6.com -wdw88.com -wdxmzy.com -wdxsk.com -wdxtub.com -wdy33.com -wdy44.com -wdyxgames.com -wdzj.com -wdzj.org -wdzjimages.com -wdzx.com -wdzzyjs.com -we.com -we.dji.com -we.game -we.tm -we1130.com -we12306.com -we2.name -we2255.com -we4399.com -we54.com -we7.cc -weachat.net -weakyon.com -wealink.com -wealinkcdn.com -weand.com -weaoo.com -weaponx.site -weapp.com -weapp.me -weappdev.com -wearefriendlyfires.com -weareqy.com -weartrends.com -weasing.com -weatherat.com -weathercn.com -weatherdt.com -weatherol.com -weaverdream.com -weaversoftware.com -weavi.com -weaview.com -web-tinker.com -web0518.com -web0898.net -web100.cc -web1800.com -web2060.com -web20share.com -web3.xin -web3389.com -web360.pw -web887.com -web89.net -web930.com -webacg.com -webaner.com -webank.com -webankcdn.net -webcname.net -webdissector.com -webdiyer.com -webfalse.com -webfont.com -webfoss.com -webfreecounter.com -webfuwu.com -webgame138.com -webgzs.com -webhek.com -webhivers.com -webjike.com -webjx.com -webkaka.com -webkf.net -webluker.com -webmagic.io -webmeng.net -webnovel.com -webofficeapi.com -webond.net -weboss.hk -webpackjs.com -webpiaoliang.com -webportal.cc -webpowerchina.com -webppd.com -webqxs.com -webrtc.win -webs.so -websbook.com -webseo9.com -webshao.com -webshu.com -webshu.net -websjx.com -websjy.com -websocket-test.com -websocket2.com -websocket5.com -websocket6.com -websoft9.com -webterren.com -webuy.vip -webview.tech -webxgame.com -webxin.com -webxmf.com -webxueyuan.com -webyang.net -wecash.net -wecatch.me -wecenter.com -weceshi.com -wechat-data-rescue.com -wechat.ba -wechat.com -wechat007.com -wechat500.com -wechatapp.com -wechatnet.com -wechatpay.com.hk -wechatpen.com -wechatrss.com -weclassroom.com -wecrm.com -wecycling.com -wecydia.com -wed027.com -wed6.com -wedate.me -weddingos.com -wedengta.com -wedfairy.com -wedn.net -wedo8.com -wedooapp.com -wedzjy.net -weebia.com -weedong.com -weefang.com -weeiy.com -weelv.com -weeqoo.com -weeyun.com -wefans.com -wefiler.com -wefinder.com -wefinger.club -wegame.com -wegamex.com.hk -wegene.com -wehefei.com -weherepost.com -wei2008.com -wei6.com -weiaokeji.com -weiba66.com -weibaiyue.com -weibaji.com -weibanan.com -weibangong.com -weibaoke.com -weibenchina.com -weibo.co -weibo.com -weibocdn.com -weibodangan.com -weiboi.com -weibopay.com -weibopie.com -weibovideo.com -weiboyi.com -weibusi.net -weica.net -weicaifu.com -weicanting.cc -weicewang.com -weichaishi.com -weichangdong.com -weiche.me -weichen.org -weiclicai.com -weico.cc -weico.com -weicot.com -weida888.com -weidanbai.com -weidanci.com -weidaohang.org -weidea.net -weidian.cc -weidian.com -weidian.gg -weidiancdn.com -weidiango.com -weidianyuedu.com -weidown.com -weiduhui.com -weidunewtab.com -weiengift.com -weifang168.com -weifangdajuyuan.com -weifangtm.com -weifei.me -weifenghr.com -weifengke.com -weifengou.com -weifengtang.com -weifengtianxia.com -weigang.com -weigongju.org -weigongxue.com -weihai.tv -weihai6.com -weihaicollege.com -weihaipoly.com -weihanli.xyz -weihaobang.com -weihaoyi.com -weihua2.com -weihuazs.com -weihubao.com -weihuijob.com -weihulian.com -weihz.net -weijifan.com -weijinsuo.com -weijinzhuanbb.com -weijinzhuancc.com -weijiu.org -weijiuxin.com -weijj.com -weiju.net -weijuju.com -weijuwhua.com -weikaowu.com -weikasen.com -weikd.com -weike.fm -weikebaba.net -weikefanli.com -weikeimg.com -weikejianghu.com -weikengtech.com -weikesucai.com -weikuo.cc -weikuw.com -weilaicaijing.com -weilaiguolv0008.com -weilairibao.com -weilaishidai.com -weilaithcdn.com -weilaitiku.com -weilanhaian.com -weilanliuxue.com -weile.com -weili-cn.com -weilingdi.com -weilinovel.net -weilitoutiao.net -weilongshipin.com -weimai.com -weimaisong.com -weimaqi.net -weimeiba.com -weimeicun.com -weimeifan.net -weimeihuo.com -weimeixi.com -weimiaocaishang.com -weimingcq.com -weimingedu.com -weimingkids.com -weimob.com -weimobdc.com -weimobqa.com -weimobwmc.com -weinc66.com -weinisongdu.com -weinovel.cc -weiot.net -weiphone.net -weiphp.com -weipinchu.com -weiping.com -weipu.com -weiq.com -weiqi.cc -weiqiaocy.com -weiqiaoyun.com -weiqibuy.com -weiqinfang.com -weiqingbao.cc -weiqitv.com -weiqudao.net -weiquyx.com -weiren.com -weisanyun.com -weisay.com -weishan.cc -weishang99.net -weishangagent.com -weishangchina.org -weishangshijie.com -weishangye.com -weishangzhonghe.com -weishengka.com -weishi.com -weishi100.com -weishu.me -weisiliang.com -weismarts.com -weistang.com -weisuyun.com -weitaoyu.com -weitehui.com -weitiaozhuan.com -weitiewang.com -weitip.com -weitoupiao.com -weitousuo.com -weituibao.com -weituitui.com -weituku.cc -weitunit.com -weituobang.net -weituoshepin.com -weitushe.com -weiwangpu.com -weiwangvip.com -weiwanhudong.com -weiwanjia.com -weiwee.com -weiwei123.com -weiweibox.com -weiweiwo.com -weiweixiao.net -weiweixiong.com -weiweiyi.com -weiwenjia.com -weiwuhui.com -weixiangshe.com -weixianmanbu.com -weixianzhuan.com -weixiaoduo.com -weixiaohan.com -weixiaotong.com -weixin-mpvip.com -weixin-tech.com -weixin.com -weixin008.com -weixin111.com -weixin12.com -weixin12315.com -weixinbang.com -weixinbridge.com -weixincall.com -weixingate.com -weixingmap.com -weixingon.com -weixingongzuoshi.com -weixingv.com -weixinhbs.com -weixinhost.com -weixinhow.com -weixinjia.net -weixinjiajia.com -weixinju.com -weixinkd.com -weixinmenu.com -weixinmuban.com -weixinmvp.com -weixinnu.com -weixinpy.com -weixinqing.com -weixinqn.com -weixinquanzi.com -weixinrensheng.com -weixinso.com -weixinsxy.com -weixinyidu.com -weixinyunduan.com -weixistyle.com -weixiu2.com -weixiuka.com -weixue100.com -weixuehao.com -weixueyuan.net -weixun.com -weixuncj.com -weixunyunduan.net -weixz8.com -weiyan.me -weiyangx.com -weiyapaper.com -weiye.me -weiyes.com -weiyi.com -weiyianws.com -weiyichina.org -weiyiminhenqiang.com -weiyingbao.com -weiyituku.com -weiyoou8.com -weiyoubot.com -weiyours.com -weiyui.com -weiyun.com -weiyun001.com -weiyunchong.com -weiyuntop.com -weiyunyong.com -weizhanabc.com -weizhangjilu.com -weizhangwang.com -weizhanle.com -weizhengbrand.com -weizhenwx.com -weizoom.com -wejianzhan.com -wejiazu.com -wejoydata.com -wekbo.com -wekuo.com -welansh.com -weldr.net -weldzy.com -welefen.com -weleve.com -weliads.com -welian.com -welife001.com -welife100.com -well8.com -wellant88.com -wellcoding.com -wellhope.net -wellphp.com -wellpie.com -wellsoon.com -wellssecurecnnect.com -wellssecureconncetl.com -wellssecureconnct.com -wellssecureconnctl.com -wellssecureconnect.com -wellstron.com -welove520.com -welovead.com -welqua.com -wemdsm.com -wemediacn.com -wemepi.com -wemomo.com -wemunc.org -wemvp.com -wen-lu.me -wenancehua.com -wenancn.com -wenangou.com -wenbita.net -wenbo.cc -wencaischool.com -wenchain.com -wenda100.net -wenda8.com -wendaifu.com -wendal.net -wendangdaquan.com -wendangku.net -wendangmao.net -wendangwang.com -wendangxiazai.com -wendasou.com -wendax.com -wendaxiaowu.com -wenday.com -wendian.com -wendns.com -wendoc.com -wendster.com -wendu.com -wenduedu.com -wendumao.com -wenfangjushe.com -wenfangnet.com -wenfu.net -wenfuxiang.com -wengbi.com -wengkui.com -wenguang.com -wenguangta.com -wenguanguoji.com -wenguo.com -wengzai.com -wenhaofan.com -wenhua.cc -wenhuabolan.com -wenhui.space -wenidc.com -wenjian.net -wenjiangs.com -wenjianjun.com -wenjingnetwork.com -wenjiwu.com -wenjuan.cc -wenjuan.com -wenjuan.in -wenjuan.link -wenjuan.ltd -wenjuan.net -wenjuan.pub -wenjuanba.com -wenjuanshow.com -wenjunjiang.win -wenjuntech.com -wenjx.com -wenku.net -wenku365.com -wenku7.com -wenku8.com -wenku8.net -wenkubao.vip -wenkudao.com -wenkudaquan.com -wenkumao.com -wenkuwenku.com -wenkuxiazai.net -wenlc.com -wenliku.com -wenmeng.com -wenneart.com -wenpie.com -wenrouge.com -wenryxu.com -wensang.com -wenshen.net -wenshen010.com -wenshen8.net -wenshenbj.com -wenshenku.com -wenshenlianmeng.club -wensheno.com -wenshenxiu.com -wenshibaowenbei.com -wenshitiandi.com -wenshuba.com -wensixuetang.com -wenten.net -wenteyangguangfang.com -wentong.me -wentu.io -wenwen.com -wenwentang.com -wenwo.com -wenwu8.com -wenwuchina.com -wenxi777.com -wenxiang.org -wenxiaoyou.com -wenxingfilter.com -wenxinshuge.com -wenxiu.com -wenxiu998.com -wenxiushop.com -wenxue100.com -wenxuedu.com -wenxuem.com -wenxuemi.com -wenxuemi6.com -wenxuemm.com -wenxuetiandi.com -wenyi001.com -wenyifan.net -wenyijcc.com -wenyinos.org -wenyoutai.com -wenyw.com -wenzaizhibo.com -wenzhaihui.com -wenzhangba.com -wenzhanghui.com -wenzhen8.com -wenzhengwenhua.com -wenzhousx.com -wenzidi.com -wepiao.com -wepie.com -weplaybubble.com -weplaymore.com -weplus.com -weplus.me -weqicheng.com -werewolf.mobi -werewolf.online -wesafesoft.com -wesai.com -wesane.com -wesdom.me -weshaketv.com -weshequ.com -weshineapp.com -weshop.com -wesiedu.com -west.xyz -west263.com -west999.com -westbund.com -westcy.com -weste.net -westengine.com -westleadfund.com -westonecloud.com -westsecu.com -westsummitcap.com -wesure100.com -wetherm.com -weti.me -wetogame.com -weton.net -wetouch.net -wetruetech.com -wetu.me -wetv.vip -wewean.com -wewen.io -wex5.com -wexin.com -wexlian.com -wey.com -weyee.com -weyhd.com -weyi.cc -weyman.me -weyo.me -weyou360.com -wezeit.com -wezgc.com -wezhan.hk -wezhan.us -wezhuiyi.com -wf.pub -wf163.com -wf66.com -wf99988.com -wfadpark.com -wfbbs.com -wfbrood.com -wfc805.com -wfc808.com -wfc809.com -wfc810.com -wfccb.com -wfchjk.com -wfdata.club -wfdmgz.com -wfeil.com -wfek.com -wff168.com -wffc120.com -wffengmailin.com -wffms.com -wfiltericf.com -wfilterngf.com -wfjimg.com -wfjuxing.com -wfkouyaji.com -wflgjx.com -wfluxin.com -wfsdf.com -wfun.com -wfuyu.com -wfwenshigongcheng.com -wfxspc.com -wfxz.com -wfyake.com -wfycjd.com -wfzbjx.com -wfzdmjg.com -wfzqhb.com -wfzssz.com -wfztg.com -wfzzz.com -wg900.com -wgcss.com -wgh.me -wghostk.com -wghpdi.com -wgimg.com -wglcxyms.vip -wglm.net -wgmf.com -wgos.com -wgpet.com -wgpsec.org -wgpwx.com -wgsptc.com -wgxcn.com -wgxdxx.com -wgxy.com -wgxy.net -wh-baidu.com -wh-charity.com -wh-china.com -wh-haipu.com -wh-motorshow.com -wh-mx.com -wh10000.com -wh100idc.com -wh111.com -wh119.com -wh12345szzx.com -wh20zx.com -wh2work.com -wh50.com -wh6z.com -wh702g.ren -whadexpo.com -whairport.com -whale8.com -whalecloud.com -whaledu.com -whaleunique.com -whalipaycs.com -whart.net -what21.com -whatbuytoday.com -whatsns.com -whatua.com -whbaishitong.com -whbbs.com -whbc2000.com -whbcrs.com -whbear.com -whbester.com -whbiobank.com -whbjdn.com -whbjyy.com -whbsybj.com -whbtel.com -whbts.com -whbtsj.com -whbwj.com -whcbank.com -whcbs.com -whccb.com -whcch802.com -whccwh.com -whcdc.org -whcfs.org -whcgtx.com -whchihuo.com -whchumei.com -whckxx.com -whcotton.com -whcrewin.com -whcst.com -whctv.com -whcyit.com -whdaring.com -whdayy.com -whdckj.com -whddgc.com -whdonde.com -whdqhj.com -whdrawing.com -whdsyy.com -whduanwu.com -whdydl.com -whecb.com -whecloud.com -whecn.com -whegj.com -whenchat.net -whenever-online.com -wherxian.com -whetc.com -whevt.com -whewash.com -whfangchanzx.com -whfangxun.com -whfazun.com -whfcsc.org -whfeiyou.com -whfengli.com -whfflz.com -whflfa.com -whgaodu.com -whgaopeng.com -whggbd.com -whggjk.com -whggjtjs.com -whggvc.net -whghfz.com -whghjt.com -whgjjtjx.com -whgk.com -whglory.com -whgmbwg.com -whgmq.com -whgmxy.com -whgszx.com -whgtgh.com -whguo.com -whgwbn.net -whgykg.com -whhbx.com -whhbxh.org -whhdcz.com -whhdgs.com -whhdmt.com -whhdsdq.com -whhexin.com -whhk520.com -whhkbyg.com -whhlhj.com -whhnkj.com -whhost.net -whhouse.com -whhpaccp.com -whhpyy120.com -whhsg.com -whhslndx.com -whhuatian.com -whhuiyu.com -whhxny.com -whhxts.com -whhyjj.com -whhysound.com -whhzhn.com -whhzyj.com -whib.com -whicec.com -whichk.com -whichmba.net -whidc.com -whidy.net -whiee.com -whinfo.net -whir.net -whisperto.net -whitebox.im -whitecat.com -whitegem.net -whitemedia-china.com -whitewolf.space -whitjy.com -whjbh.com -whjcba.com -whjcbus.com -whjclgs.com -whjdhy.com -whjfyz.com -whjfz.com -whjhcz.com -whjiaoy.com -whjjhbj.com -whjjyyjsb.com -whjm.com -whjmyc.com -whjpwz.com -whjtxx.com -whjuren.com -whjy.net -whjyx.com -whjzw.net -whjzy.net -whjzyxh.org -whkakaxi.com -whkangte.com -whkc.com -whkingdom.com -whkjz.com -whkpcnc.com -whkt.net -whkyjz.com -whland.com -whlawyer.net -whldsoft.com -whli010.com -whlido.com -whljyl.com -whlkwy.com -whlongre.com -whlrhd.com -whly56.com -whlybzh.com -whlynk.com -whmama.com -whmcwd.com -whmcxh.org -whmeigao.com -whmeiyugao.com -whmetroad.com -whmicrocredit.com -whmid.net -whmj.org -whmjx.net -whmlcy.net -whmlhhs.com -whmnrc.com -whmnx.com -whmoocs.com -whmrdqz.com -whmtyy.com -whmyjj.org -whmylike.cc -whmylikekq.com -whnatural.com -whnfc.com -whngd.org -who55.com -whoami.akamai.net -whoceansys.com -whocool.com -whoil.net -whoolala.com -whosedrop.com -whosgreen.com -whozen.com -whpantosoft.com -whpanva.com -whplmd.com -whptc.org -whpx.net -whqcbj.com -whqcsi.com -whqiansou027.com -whqtdjy.com -whqunyu.com -whr.cc -whrango.com -whrazf.com -whrcbank.com -whreadsoft.com -whrenai.com -whrenrenhui.com -whres.net -whrhkj.com -whrl.net -whrsip.com -whrsj.org -whrtmpay.com -whruipeng.com -whsdsyy.com -whsdxf.com -whseoclub.com -whshangceng.com -whsir.com -whsladz.com -whsladz.net -whsmk.com -whsmkg.com -whsoftway.com -whsql.org -whsqsoft.com -whsrc.com -whssxpx.com -whsunmap.com -whsw.net -whsxt.com -whsy.org -whsyy.net -whtbq.com -whtcm.com -whtcm.net -whtcsz.com -whtdcb.com -whtdsc.com -whtech-sonic.net -whtfzy.com -whtmhh.com -whtmwy.com -whtongyun.com -whtpi.com -whtqedu.net -whtran.com -whtryine.com -whtsw.org -whtto.com -whttsy.com -whtuff.com -whtxcloud.com -whtzb.org -whu.pt -whualong.com -whudfr.com -whuh.com -whuhzzs.com -whume.com -whusee.com -whusf.com -whuspark.com -whuss.com -whusu.org -whut-px.com -whutech.com -whutosa.com -whuwto.com -whuzy.com -whvcse.com -whwanshun.com -whwater.com -whwebsite.com -whweo.com -whwkzc.com -whwm.org -whwomensmarathon.com -whwxxy.com -whxc01.com -whxf315.org -whxh.com -whxinhuo.com -whxinxuan.com -whxsnsy.com -whxunw.com -whxxzh.com -whxy.net -whxyqb.com -whxysz.net -why123.org -whybh2015.com -whyec.com -whyenjoy.com -whyestar.com -whyfcm.com -whyfyc.com -whyicheng.com -whyimingkeji.com -whyinsheng.com -whyinzhimei.com -whyiqitong.com -whyldd.net -whylkf.com -whyqi.com -whysdomain.com -whysodiao.com -whysx.com -whyungu.com -whyyy.com -whyzrcw.com -whzb.com -whzblawson.com -whzbtb.com -whzc2008.com -whzdyy.com -whzglc.com -whzh-cw.com -whzhqsg.com -whzhtd.com -whzhzxmr.com -whzjjd.com -whzjyy.com -whzkb.com -whzlgm.com -whzlyy.com -whzph.com -whzsrc.com -whzwzk.com -whzwzs.com -whzxht.com -whzxzls.com -whzyblh.com -whzydz.com -whzyy.net -wiaapp.com -wibili.com -wiblog.net -wicep.com -wicp.net -wicp.vip -wicresoft.com -widuu.com -wifenxiao.com -wifi-master.com -wifi.com -wifi03.com -wifi0917.com -wifi188.com -wifi33.com -wifi8.com -wifibanlv.com -wifichain.com -wifidog.pro -wifidown.com -wifigushi.com -wifigx.com -wifiing.net -wifimsl.com -wifire.net -wifishenqi.com -wifiwx.com -wifizj.com -wiitrans.com -wiiyi.com -wiki8.com -wikielife.com -wikiimgs.com -wikimirror.org -wikimoe.com -wikiyuedu.com -wikore.com -wikore.net -wikore.org -wilddog.com -wildgun.net -will6.com -willcdn.com -willerce.com -willmao.com -willsemi.com -willsfitness.net -willsgym.com -willsun.net -willwin91.com -wiloon.com -wiloop.net -wimetro.com -wimiar.com -win-ke.com -win-man.com -win.hn -win007.com -win1032.com -win1064.com -win10cjb.com -win10com.com -win10gw.com -win10net.com -win10world.com -win10ww.com -win10xiazai.com -win10zjb.com -win10zyb.com -win2007.com -win4000.com -win71234.com -win732.com -win789.com -win7999.com -win7china.com -win7en.com -win7i.com -win7qijian.com -win7qjb.com -win7sky.com -win7w.com -win7xzb.com -win7zhijia.net -win7zhuangjiyuan.com -win8.net -win866.com -win8china.com -win8e.com -win8pc.com -win8xiazai.com -win9008.com -win9cn.com -winapp111.mobi -winasdaq.com -winbaicai.com -winbaoxian.com -winbic.com -winbjb.com -winbond-ic.com -winbons.com -winbosmart.com -wincheers.com -wincheers.net -wincn.com -wind.moe -windcoder.com -winddesktop.com -windever.com -windgreen.me -windin.com -windmsn.com -windows10.pro -windows10zj.com -windows7adobe.com -windows7en.com -windows7home.com -windowszj.com -windowszj.net -windrunner.me -winds.red -windsns.com -windtch.com -windworkshop.net -wine-world.com -wine9.com -winegame.net -wineln.com -winemagz.com -winenice.com -wines-info.com -winesinfo.com -winesou.com -wineworld.vip -winex-hk.com -winfang.com -winfanqie.com -winfreeinfo.com -wingconn.com -winglungbank.com -wingodata.com -wingsbook.com -wingsforwomentucson.org -wingstudio.org -wingtecher.com -winhong.com -winhyl.com -winicssec.com -winkey17.com -winkingworks.com -winksi.com -winmen.net -winndoo.com -winner9.com -winnermicro.com -winnet.cc -winning11cn.com -winotmk.com -winscollege.com -winsenseos.com -winshang.com -winshangdata.com -winsing.net -wintalent.com -winteam500.com -winterchen.com -wintimechina.com -wintooo.com -wintopedu.com -winvvv.com -winwebmail.com -winwin7.com -winxitong.com -winxp8.com -winxuan.com -winxuancdn.com -winxw.com -wio2o.com -wireless-driver.com -wirelesschina-summit.com -wisburg.com -wisder.net -wisdoing.com -wisdom-braun.com -wisdomcmmi.com -wisdontech.com -wisdr.com -wisdri.com -wise-iot.com -wiseah.com -wiseboke.com -wisecotech.com -wisedoo.com -wisedsp.net -wisedu.com -wiseimp.com -wiselong.com -wisenjoy.com -wiseuc.com -wisevector.com -wishbuild.com -wishcad.com -wishcalls.com -wishdown.com -wishisp.com -wisiyilink.com -wismom.com -wisrc.com -wistone.com -wiswonder.com -wit-parking.com -wit0.com -wit5.com -witchspring.com -witcp.com -with366.com -withae.com -withcdn.com -witheloov.com -withmedia.net -withpinbox.com -withsccdn.com -withsin.com -withubit.org -withzz.com -witkey.com -witmart.net -witnew.net -witontek.com -witown.com -witspring.com -wiwide.com -wiyeniao.com -wiz03.com -wizarcan.com -wj-hospital.com -wj-jd.com -wj001.com -wj0511.com -wj166.com -wjage.com -wjajw.com -wjasset.com -wjbb.com -wjbk.site -wjceo.com -wjdaily.com -wjdhcms.com -wjdiy.com -wjdiy.net -wjdr.net -wjgslb.com -wjhenglin.net -wjhouses.com -wjhtxx.com -wjiaxing.com -wjika.com -wjin.cc -wjjfjt.com -wjkwl.com -wjlkj.com -wjlxmedia.com -wjrcb.com -wjshu.com -wjshw.com -wjsou.com -wjsw.com -wjunjie.com -wjwux2.com -wjx.com -wjxcdn.com -wjyanghu.com -wjyh.com -wjyt-china.org -wjyw.com -wjz0098.me -wk-foryou.com -wk007.com -wk2.com -wk588.com -wk78.com -wkai.cc -wkanx.com -wkbins.com -wkcmall.com -wkderp.com -wkdty.com -wkecn.com -wkepu.com -wkhub.com -wkimg.com -wklken.me -wklm2018.com -wkmic.com -wkread.com -wksc.com -wkshipark.com -wkzf.com -wkzuche.com -wl.dlservice.microsoft.com -wl369.com -wlanadmin.com -wlanbanlv.com -wlanwifi.net -wlbaike.com -wlbqczk.vip -wlcbnews.com -wlcbw.com -wlclw.com -wlcxx.com -wld5.com -wldental.com -wldsb.com -wleye.com -wlhcd.com -wlim.pro -wlinfor.com -wlizi.com -wljy8.com -wljyyjy.com -wlkst.com -wlmq.com -wlmqgjj.com -wlmqwb.com -wlnh.net -wlphp.com -wlqtpolytheatre.com -wlread.com -wlrjy.com -wlsgjslgy.com -wlshw.com -wlski.com -wlsrenzaocaoping.com -wlstock.com -wlsvt.com -wltieyaoban.com -wlxmall.com -wlxww.com -wlyfw.com -wlyjbl.com -wlyscl.com -wlzni.com -wlzy.tv -wm-imotor.com -wm-motor.com -wm090.com -wm18.com -wm818.com -wmc-bj.net -wmcloud.com -wmcn.com -wmedias.com -wmgjd.com -wmgm.org -wmiao.com -wmiyx.com -wmjk.net -wmjrc.com -wmjygg.net -wmjyqd.net -wmjyszba.com -wmljw.com -wmlunwen.com -wmnetwork.cc -wmota.htcsense.com -wmp169.com -wmphp.com -wmpic.me -wmpvp.com -wmpyol.com -wmrzb.com -wms100.com -wmssedu.com -wmsub.com -wmton.com -wmtp.net -wmtxt.com -wmupd.com -wmvideo.com -wmxxgy.com -wmxxgz.com -wmxxwh.com -wmxxxj.com -wmy-ad.com -wmzhe.com -wn1998.com -wn3331.com -wn51.com -wn789.com -wnacg.xyz -wnbsq.com -wndhw.com -wndlkj.com -wnform.com -wnhuifu.com -wniecm.com -wnkj88.com -wnlbs.com -wnlpromain.com -wnlprozhanxing.com -wnlprozijia.com -wnmqchwl.com -wnn8.com -wnplayer.net -wnrb.net -wns1191.com -wnsjj.com -wnsqzonebk.com -wnssedu.com -wntool.com -wnw3d.com -wnwb.com -wnzc.com -wnzhuishu.com -wnzy.net -wo-xa.com -wo113.net -wo116114.com -wo123.com -wo186.tv -wo188.win -wo685.com -wo81.com -wo99.net -woaap.com -woai01.com -woaide.com -woaidu.org -woaifanyi.com -woaihuahua.com -woailuo.com -woaipj.com -woaipu.com -woair.com -woaishouban.com -woaixiao.com -woaixiazai.net -woaizuji.com -woaoo.net -wobenben.com -wobiquge.com -wobocn.com -woc88.com -wocai.de -wocaoseo.net -wochacha.com -wochaw.com -wodai.com -wodavip.com -wodcloud.com -wode.im -wode20.com -wodeabc.com -wodecrowd.com -wodedagong.com -wodefanwen.com -wodemeitu.com -wodeoffice.com -wodeshebao.com -wodeshucheng.com -wodiancan.net -wodidashi.com -wodingche.com -wodjob.com -wodocx.com -woduguo.com -wofang.com -wofang.net -wofangwang.com -wofficebox.com -wofjhs.com -wogame.net -wogoo.com -wohenizaiyiqi.com -wohenok.com -woi3d.com -woiyu.com -woji.net -wojiacloud.com -wojiaoni.com -wojilu.com -wokeji.com -woko.cc -wokugame.com -wolai.com -wolaidai.com -wolegou.net -wolezhibo.com -wolf.cc -wolfcstech.com -wolfgo.com -wolfogre.com -woliaoran.com -wolife.com -wolighting.com -woliuda.com -wolonge.com -wolongge.com -wolongyin.com -wolongyoule.com -wolongzy.net -wolwo.ltd -wolwobiotech.com -womai.com -womaiapp.com -woman91.com -womeime.com -womenaiyuedu.com -womenjie.com -wonder.wiki -wondercv.com -wonderful-pr.com -wonderfulsz.com -wonderjk.com -wonderkun.cc -wondermars.com -wondermole.com -wonderscloud.com -wondersgroup.com -wondershare.cc -wondershare.com -wondershare.net -wondersmemory.com -wonderstar027.com -wonei.com -wonerqu.com -wongcw.com -wonggang.com -wongpeace.com -woniu.com -woniu8.com -woniubaoxian.com -woniucloud.com -woniudichan.com -woniutrip.com -woniuwl.com -wonmay.com -wonmay.net -wonote.com -wonplug.net -wonter.net -wonxun.net -woo.im -wooaii.com -woocg.com -wooclouds.com -wood168.com -wood168.net -woodbunny.com -wooddb.com -woodnn.com -wooee.net -wooffice.net -woola.net -woolteam.com -wooolab.com -wooqx.com -woordee.com -wooshoes.com -woosmart.com -wooxhome.com -wooyun.org -woozooo.com -wopaiyi.com -wopaper.com -wopaw.com -wopeng.net -wopus.org -woqidege.com -woqu.com -woquge.com -word666.com -wordlm.com -wordpress.la -wordpresshy.com -wordscan.net -wordyt.com -work28.com -workchat.com -workec.com -workehr.com -workerman.net -workpcb.com -worksgz.com -worktile.com -worktilemail.com -workyun.com -world-pass.net -world-tour.org -world68.com -worldcps.com -worldgoodvoices.com -worldh5.com -worldhello.net -worldinout.com -worldlv.com -worldmall365.com -worldmr.net -worldmsports.com -worldofai.com -worldpathclinic.com -worldpia.net -worldpowerliftingchina.com -worldsocks.com -worlduc.com -worldwarner.com -worldwayhk.com -worldwu.com -worthytown.com -wosai-inc.com -wosaimg.com -woshao.com -woshipm.com -woshiqian.com -woshitv.com -woshizz.com -woshuo123.com -wosign.com -wosigndoc.com -wosijun.com -woskj2.com -wosku.com -wosn.net -woso100.com -wosouyun.com -wotougao.com -wotrus.com -wotucdn.com -wotula.com -wouju.com -wow-classic.com -wowant.com -wowar.com -wowcat.net -wowchina.com -wowdb.tw -wowenda.com -wowforex.com -wowodai.com -wowoit.com -wowoohr.com -wowops.com -wowoqq.com -wowoshijie.com -wowotech.net -wowotuan.com -wowoyoo.com -wowoyou.com -wowozs.com -wowphp.com -wowqu.cc -wowsai.com -wowys.com -woxian.com -woxiaoyun.com -woxihuan.com -woxiu.com -woxuexue.com -woxuyuan.com -woyao998.com -woyaobaoliang.com -woyaofanyi.com -woyaogexing.com -woyaoqingjia.com -woyaoqiudai.com -woyaozhan.com -woying.com -woyo365.com -woyoo.com -woyouche.com -woyoupu.com -woyouquan.net -wozaijia.com -wozhua.mobi -wozhuan.com -wozhuye.com -woziku.com -wp-china-yes.net -wp-h.com -wpabc.net -wpan123.com -wpceo.com -wpchina.org -wpcnzz.com -wpdaxue.com -wpengapp.com -wper.com -wpgdadatong.com -wpgdadawant.com -wphun.com -wpimg-wallstcn.com -wping.org -wpjam.com -wpk8.com -wplat.com -wpmee.com -wpmtp.com -wporder.com -wpscdn.com -wpsdns.com -wpsep.com -wpsgo.com -wpsmail.net -wpsoffice.com -wpsoso.com -wptao.com -wpweixin.com -wpxap.com -wpyou.com -wpzhiku.com -wq96f9.com -wqbook.com -wqc.so -wqchat.com -wqcms.com -wqdian.com -wqdian.net -wqeshop.com -wqetrip.com -wqge.cc -wqgp.com -wqhunqing.com -wqiis.com -wqingjian.com -wqketang.com -wqlin.com -wqrlink.tech -wqshui.com -wqxuetang.com -wqyunpan.com -wqzx.net -wrating.com -wrcdn.com -wrdxmz.com -wrfou.com -write-bug.com -writebp.com -wrjzj.com -wrltxt.com -wrmjk.com -wrpage.com -wrpotter.com -wrsa.net -wrsaea.com -wrtnode.cc -wrtnode.com -wrtsz.com -wrwugl.com -wrx319.com -ws-dla.com -ws.ksmobile.net -wsaf.net -wsamc.com -wsbuluo.com -wsbz008.com -wsc-expo.com -wscdns.com -wscdns.info -wscdns.org -wscloudcdn.com -wscloudcdn.org -wsclouddns.com -wscloudsec.com -wscont1.apps.microsoft.com -wscont2.apps.microsoft.com -wscrm.net -wscso.com -wscstrace.com -wscvdns.com -wscxy.com -wsdcasa.com -wsdccq.com -wsdipei.com -wsdns.cc -wsdvs.com -wsdvs.info -wsdvs.org -wse.me -wsecar.com -wseen.com -wselearning.com -wselearning.net -wsfdl.com -wsfdn.com -wsfff.com -wsfnk.com -wsfsy.com -wsgblw.com -wsgjp.com -wsglb0.com -wsglb0.info -wsglb0.org -wsglw.com -wsgxsp.com -wshang.com -wshangw.net -wshenm.com -wshili.com -wshost.cc -wshoto.com -wshtgame.com -wshttpdns.com -wsisp.com -wsisp.net -wsj186.com -wsjkbb.vip -wslcode.com -wslmf.com -wsloan.com -wsltt.com -wsmaoyi.com -wsmaoyi.net -wsmhw.com -wsonh.com -wsoso.com -wsound.cc -wsoversea.info -wsq.cool -wsssec.com -wssy128.com -wstdw.com -wstx.com -wsview.com -wswebcdn.com -wswebcdn.info -wswebcdn.org -wswebpic.com -wswebpic.info -wswebpic.org -wsxa.com -wsxc.me -wsxcme.com -wsxddg.com -wsyyxz.com -wszwh.org -wt-px.com -wt6669.com -wt8.com -wtango.com -wtapi.com -wtbds.com -wtdex.com -wtdlq.com -wtdms.com -wting.info -wtmbuy.com -wtmgc.com -wtmmn.com -wtn5.com -wtobag.com -wtoip.com -wtojob.com -wtoutiao.com -wts999.com -wtszx.com -wttms.com -wtwvision.com -wtxcdn.com -wtzw.com -wu-mart.com -wu-mi.com -wu35.com -wu37.com -wu7zhi.com -wuage.com -wuaiso.com -wubaiyi.com -wubaiyi.net -wubazx.online -wubiba.com -wubisheng.net -wubizi.net -wubizigen.net -wubolive.com -wubx.net -wucaiabc.com -wuchajian.com -wuchengkai.com -wuchenxu.com -wuchong.me -wuda-website.com -wudage.com -wudang.cc -wudangquan.net -wudangshan.com -wudao.com -wudaotv.com -wudejia.com -wudicdn.cc -wudku.com -wudusw.com -wueasy.com -wufafuwu.com -wufangbo.com -wufangzhai.com -wufazhuce.com -wufuba.com -wufun.net -wuguiyunwei.com -wuguoren.com -wuguyufen.com -wugx.net -wuhan-guide.com -wuhan-tour.net -wuhan-travel.com -wuhan.com -wuhan163.com -wuhananyu.com -wuhanart.com -wuhanauto.com -wuhanbaituo.com -wuhanbus.com -wuhancityofdesign.com -wuhandazhaxie.com -wuhaneca.org -wuhanfuke120.com -wuhanfukeyy.com -wuhanhengyi.com -wuhanins.com -wuhanjiaojing.com -wuhanjingce.com -wuhankb.com -wuhanly.com -wuhanmarathon.org -wuhanmeigao.com -wuhanmetro.com -wuhanopen.org -wuhanparking.com -wuhanpe.com -wuhanpep.com -wuhanport.com -wuhanrt.com -wuhanrx.com -wuhansailingclub.com -wuhantest.com -wuhantianqi114.com -wuhantianrun.com -wuhantskj.com -wuhanunion.com -wuhanxinfang.com -wuhanxingfuwan.com -wuhanxyz.com -wuhanzdq.com -wuhanzhongye.com -wuhao.me -wuhongsheng.com -wuhouhaodian.com -wuhu.cc -wuhuashe.com -wuhubtv.com -wuhulife.com -wuhusanlian.com -wuhuzhongao.com -wui5.com -wuji.com -wujiangtong.com -wujiayi.vip -wujiecaifu.com -wujiehd.com -wujiehuyu.com -wujiexiang.com -wujiexueyuan.com -wujiit.com -wujixiaoshuo.com -wujiyou.com -wujn.me -wukong.com -wukong.la -wukongapi.com -wukongfix.com -wukongkf.com -wukonglicai.com -wukongphp.com -wukongrom.com -wukongshuo.com -wukongtui.com -wukongtv.com -wukongwenda.com -wukongzhuishu.com -wukuiwang.com -wukypay.com -wul.ai -wulannews.com -wuliaoo.com -wuliaosi.com -wuliapi.com -wulicdn.com -wulinsoso.com -wuliujia2018.com -wulong365.com -wulongju.com -wulvxing.com -wumart.com -wumei5.com -wumeishebei.com -wumii.com -wumii.tv -wuming.com -wuqing.cc -wuqiong.info -wuqishike.com -wurenjifanzhi.com -wuruihong.com -wuruo8.com -wuse.com -wusen.net -wuseng.com -wuseng.net -wuseyun.com -wushang.com -wushangplaza.com -wushen.com -wushuangol.com -wushuangtech.com -wushuhenan.com -wusiwei.com -wusiyu.me -wusunjiance.net -wusuobuneng.com -wuta-cam.com -wutaishanfojiao.com -wutanyuhuatan.com -wutep.com -wutianqi.com -wutnews.net -wutongguo.com -wutongshanxia.com -wutongtec.com -wutongwan.org -wutongxiang.cc -wutos.com -wutui.pro -wutuojia.com -wutuxs.com -wuuxiang.com -wuweijob.com -wuweiyou.com -wuwenjun.net -wuwenliang.net -wuwii.com -wuwm-aprg.org -wuxiairport.com -wuxiamh.com -wuxiangxing.com -wuxianhaibao.com -wuxianlandao.com -wuxianlin.com -wuxiantu.com -wuxiaodi.com -wuxiatools.com -wuxibus.com -wuxijy.com -wuximarathon.com -wuximeidi.com -wuxin.info -wuxinban.com -wuxinews.com -wuxiwang.net -wuxu92.com -wuyang-honda.com -wuyazi.com -wuyecao.net -wuyehr.com -wuyida.com -wuyishan.net -wuyou.com -wuyou.net -wuyoufang.com -wuyouhui.net -wuyousy.com -wuyuan.cc -wuyuan168.com -wuyublog.com -wuyueit.com -wuyukang.com -wuyumin.com -wuyuncdn.com -wuzhaiba.com -wuzhenfestival.com -wuzhenpay.com -wuzhenwic.org -wuzhicms.com -wuzhiwei.net -wuzhouqianzheng.com -wuziya.com -wuzongping.com -wvbtech.com -wvshare.com -ww2bbs.net -wwaaffxx.com -wwc-blog.com -wwe008.com -wwenglish.com -wwenglish.org -wwfchina.org -wwggw.com -wwjia.com -wwjingtou.com -wwleww.com -wwmhdq.com -www-05.ibm.com -www-123490.com -www-13121.com -www-175345.com -www-222890.com -www-36344.com -www-434455.com -www-4620.com -www-63608.com -www-657000.com -www-689777.com -www-706705.com -www-api.ibm.com -www-googletagmanager.l.google.com -www.adobe.com -www.agoda.com -www.akamai.com -www.amd.com -www.analog.com -www.apple.com -www.apple.com.edgekey.net -www.apple.com.edgekey.net.globalredir.akadns.net -www.bing.com -www.cc -www.cg -www.com.my -www.dell-brand.com -www.dell.com -www.dji.com -www.djivideos.com -www.ericsson.com -www.gstatic.com -www.htc.com -www.htcsense.com -www.htcvive.com -www.ibm.com -www.kaspersky.com -www.linkedin.com -www.microsoft.com -www.nike.com -www.pandora.net -www.redhat.com -www.samsung.com -www.sl -www.st.com -www.sulwhasoo.com -www.thinkpad.com -www.tzoo-img.com -www.vive.com -www.viveport.com -www.volvocars.com -www000377.com -www045789.com -www1.djicdn.com -www2.djicdn.com -www2011india.com -www3.djicdn.com -www37430.com -www4.djicdn.com -www448809.com -www48-365365.com -www5.djicdn.com -www632159.com -www74455.com -www78966.cc -www8.hp.com -www81854.com -www996111.com -wwwbaidu.co -wwwbuild.net -wwwdeyi.com -wwwer.net -wwwic.net -wwwimages.adobe.com -wwwimages2.adobe.com -wwwku.com -wwwljw408.com -wwwtbk.com -wwwwang.com -wwwwww.vip -wwwwwwwwww.com -wwwzongyiyouxi.com -wwxcl.com -wwxwmw.com -wx-data.com -wx-youyan.net -wx.com -wx135.com -wx16999.com -wx42.com -wx6.org -wx84.com -wx8s.com -wx939.com -wxagame.com -wxang.com -wxaokai.com -wxapp-union.com -wxappclub.com -wxatech.com -wxavu.com -wxb.com -wxbady.com -wxbdfm.com -wxblockchain.com -wxbrandway.com -wxbsgc.com -wxcha.com -wxcsgd.com -wxdgjx.com -wxdh001.com -wxdldhg.com -wxdspt.com -wxeditor.com -wxfenxiao.com -wxfls.net -wxfsgj.com -wxgdb.com -wxguan.com -wxhand.com -wxhbts.com -wxhon.com -wxhu.net -wxhudong.com -wxianfeng.com -wxiao.net -wxjx123.com -wxjxyb.com -wxjyql.com -wxlagame.com -wxlongre.com -wxlss.com -wxlxg.com -wxmama.com -wxmcgz.com -wxmetro.net -wxmovie.com -wxnacy.com -wxngh.com -wxnmh.com -wxp114.com -wxphp.com -wxr999.com -wxrb.com -wxreallink.com -wxrrd.com -wxscreen.com -wxsell.com -wxshake.com -wxsky.net -wxsteed.com -wxsyedu.net -wxsywh.com -wxtj10086.com -wxtpb.com -wxtree.com -wxuse.com -wxw120.com -wxwzt.com -wxxnhdkj.com -wxy1314.com -wxyxrc.com -wxzzz.com -wy000.com -wy100.com -wy119.com -wy182000.com -wy213.com -wy28.com -wy2sf.com -wyaoqing.com -wyaq.com -wyb168.com -wybbao.com -wybgs.com -wyc1236.com -wycanyin.com -wycntv.com -wydbw.com -wydljx.com -wydns.com -wying360.com -wyins.net -wykefu.com -wykw.com -wykz.com -wymp4.net -wymp46.com -wyn88.com -wynnad.com -wyptk.com -wypxj.com -wyq9.com -wyqrks.com -wyr.me -wyrj.com -wys.net -wysaid.org -wysap.com -wysjy.com -wysls.com -wysww.vip -wytfsp.com -wytx.net -wytype.com -wyuetec.com -wywy6.com -wywyx.com -wyx365.com -wyxbc.com -wyydsb.xin -wyzc.com -wyzdg.com -wyzhifu.com -wyzlvyou.com -wyzxsd.com -wyzxwk.com -wz01.com -wz120.cc -wz132.com -wz16.net -wz5.com -wzaobao.com -wzcheshi.com -wzciming.com -wzdai.com -wzdjy.com -wzdress.com -wzdsb.net -wzexe.com -wzfw.ltd -wzhan.net -wzhealth.com -wzhekou.com -wzhenyun.com -wzhouhui.com -wzhouhui.net -wzhust.com -wzhxlx.com -wzi9.com -wzijia.com -wzime.com -wzits.com -wzj9.com -wzjmr.com -wzjxyq.com -wzkee.net -wzkouqiang.cc -wzksw.com -wzktys.com -wzlscf.com -wzlt8.com -wzms.com -wzplc.com -wzpo.net -wzpod.com -wzrhjr.com -wzright.com -wzsee.com -wzsky.net -wzssbs.com -wzstationery.com -wztf121.com -wzwoja.com -wzwqs.com -wzxycj.com -wzyestar.com -wzyun.net -wzz180809.net -wzz1809.com -wzzw.la -wzzww.com -x--w.com -x-cti.org -x-jishu.com -x-medex.com -x-mol.com -x-plans.com -x0431.com -x0769.com -x118.net -x12plus.com -x158.tv -x1997.net -x2279.com -x23qb.com -x23us.cc -x23us.me -x23us.us -x23wxw.com -x3366.com -x3china.com -x3cn.com -x431.com -x5dj.com -x64pro.com -x6d.com -x6kj.com -x6tuan.com -x6x8.com -x72y.com -x7sy.com -x81zw.com -x821.com -x83zw.com -x86android.com -xa-online.com -xa.com -xa189.net -xa9t.com -xabbp.com -xabbs.com -xabcdns.com -xabcloud.com -xacbank.com -xacnnic.com -xadamai.com -xadiannao.com -xaecong.com -xafc.com -xaffp.com -xafpz.com -xafzjy.com -xagxz.com -xahaosu.com -xahhc.com -xahhp.com -xahrly.com -xahunter.com -xahzm.com -xaidc.com -xaifin.com -xaigame.com -xainjo.com -xaislam.com -xaixs.org -xajhgg.com -xajjk.com -xajjwy.com -xajob.com -xajr.com -xajxpl.com -xalanq.com -xalawyer.net -xalhar.net -xalhlf.com -xamama.net -xamjx.com -xampp.cc -xanahotelle.com -xanbhx.com -xanet110.com -xank120.com -xany6.com -xaoji.com -xaonline.com -xaoyao.com -xapawn.com -xapcn.com -xaps2011.com -xaqdrs.com -xaqindao.com -xaqxs.com -xaredian.com -xargin.com -xasff.com -xashangwang.com -xasimonds.com -xasixiongdi.com -xaskm.com -xasqw.com -xasrc.com -xaszjf.com -xatao029.com -xatcm.org -xatielu.com -xatongsheng.net -xatvs.com -xatyaviation.com -xatyds.com -xatyyx.com -xatzj.com -xauat-hqc.com -xaudiopro.com -xavua.com -xawb.com -xawbb.com -xawdz.com -xawhz.com -xaxing05.com -xaxinghuo.com -xaybh.com -xayestar.com -xaytyy.com -xazcit.com -xaztdz.com -xazzg.com -xazzp.com -xazzs.com -xb.dlservice.microsoft.com -xb100.net -xb2s.com -xb5.cc -xb7r.com -xbaixing.com -xbaofun.com -xbaquge.com -xbase.cloud -xbatu.com -xbauto.com -xbbei.net -xbblfz.site -xbceo.com -xbdym.com -xbequge.com -xbeta.info -xbext.com -xbfnet.com -xbfqw.com -xbfzb.com -xbhb.net -xbhub.com -xbhy.com -xbhz.net -xbiao.com -xbidc.com -xbingoz.com -xbiquge.cc -xbiquge.com -xbiquge.la -xbiquge6.com -xbiqugew.com -xbirder.com -xbjianzhan.com -xblds.com -xblyw.com -xbmiaomu.com -xbniao.com -xbongbong.com -xbptc.com -xbriyu.com -xbrl-cn.org -xbrother.com -xbspace.com -xbsura.com -xbwbh.com -xbwebyun.com -xbxgame.com -xbxwx.net -xbxwx.org -xbxxb.com -xbxxz.com -xbzjwcn.com -xc-fc.com -xc123.net -xc16688.com -xc18.cc -xc829.com -xc88i3x.vip -xc940.com -xcabc.com -xcao.win -xcape.cc -xcar.com -xcarimg.com -xcb-family.com -xcbank.com -xcbcyjm.com -xccbank.com -xcczgm.com -xcdesign.net -xcexe.com -xcfee.com -xcfunds.com -xcggpt.com -xcgjj.com -xcgogo.club -xcgogo.site -xcgp.com -xcgui.com -xchjw.org -xchlxx.com -xchmai.com -xchrc.com -xchuandai.com -xchuxing.com -xcj.com -xcjd.net -xcjsgtoup.com -xcktsb.com -xclient.info -xcloudbase.com -xcmad.com -xcmg.com -xcmgmall.com -xcmh.cc -xcmh.com -xcn457.com -xcnchinese.com -xcnte.com -xcode.me -xcoder.in -xcodest.me -xcommon.com -xcoodir.com -xcos.cc -xcot.com -xcpapa.site -xcpapa.xyz -xcqq8.com -xcshaifen.com -xcsinsignia.com -xcstuido.com -xcsyxx.net -xctmr.com -xctsw.com -xcvgame.cc -xcvmbyte.com -xcxs222.com -xcxs520.com -xcxs9.com -xcxwo.com -xcxx28.com -xcxzl.com -xcy8.com -xcyg.net -xcyo.com -xczzs.com -xd-game.com -xd-tech.com -xd-world.com -xd.com -xd0.com -xd57.com -xda98.com -xdapp.com -xdbcb8.com -xdc.at -xdccpro.com -xdcdn.com -xdcdn.net -xddex.com -xddhy.com -xddpay.com -xddxs.cc -xddxx102.com -xde.com -xde6.net -xdfckjz.com -xdfkt.com -xdfpr.com -xdgalaxy.com -xdh0808.com -xdhbs.com -xdhcn.com -xdj-sz.com -xdja.com -xdjc.org -xdju.com -xdjy369.com -xdkb.net -xdkcw.com -xdkjchina.com -xdkjjy.com -xdkjpx.com -xdmnyy.com -xdmssp.com -xdnice.com -xdnote.com -xdnphb.com -xdocin.com -xdoor.cc -xdowns.com -xdplt.com -xdpvp.com -xdrig.com -xds04.com -xdsipo.com -xdtos.com -xduoo.com -xduph.com -xdusz.com -xdvps.com -xdwan.com -xdxd.love -xdxdsz.com -xdxiazai.com -xdxmwang.com -xdyqw.com -xdzdzl.com -xedaojia.com -xedaojia.net -xeeee.net -xeenho.com -xeeok.com -xefan.com -xege.org -xehedu.com -xeknow.com -xeltek-cn.com -xelz.info -xemean.net -xemh.com -xen0n.name -xender.com -xenium.mobi -xenvpser.com -xerlang.com -xesapp.com -xescdn.com -xesdns.com -xesee.com -xesimg.com -xesv5.com -xetimes.com -xetsg.com -xevd.co -xevddy.com -xeylon.com -xf-world.org -xf-yun.com -xf.com -xf0797.com -xf09.net -xf119.xin -xf120.com -xf1233.com -xf1433.com -xf24ms.com -xf3z.com -xf4hs.com -xf5z.com -xfabs.com -xfannix.com -xfb315.com -xfc888.com -xfcgs.com -xfconnect.com -xfdown.com -xfeng.me -xffcol.com -xfgc.cc -xfgjj.com -xfguo.org -xfhx.com -xfinfr.com -xfisher.com -xfisp.com -xfjunpin.com -xfjw.net -xfkou.com -xfliusheng.com -xfnano.com -xfocus.net -xfocus.org -xforceplus.com -xfpass.com -xfplay.com -xfplay.tv -xfsb119.com -xfsd.com -xfsub.com -xft123.com -xftclub.com -xfwi.com -xfxb.net -xfyousheng.com -xfyun.com -xfzhsf.com -xfztc.com -xgamevip.com -xgantt.net -xgbbb.com -xgbxg.com -xgcs618.com -xgcsczyc.com -xgcsyg.com -xgd666.com -xgdfz.com -xgdown.com -xgdq.com -xgfz.net -xggjj.com -xgh0st.com -xghylt.com -xgimi.com -xgj-info.com -xgjinrong.com -xgjxjy.com -xgkwx.com -xglpa.com -xgmeidiya.com -xgo.cc -xgqq.com -xgrc.com -xgres.com -xgsdk.com -xgslb.net -xgt2014.com -xgtex.com -xgv5.com -xgwx.net -xgxedu.com -xgxhy.com -xgz.cc -xgzx.org -xh456.com -xhangxian.com -xhay1122.com -xhbaihehang.com -xhbhr.com -xhblog.com -xhboke.com -xhby.net -xhbycm.net -xhcjtv.com -xhclub.net -xhcpas.com -xhd.org -xhdollar.com -xheditor.com -xhedu.net -xhengshui.com -xhg.com -xhgame.com -xhgm100.com -xhgongsi.com -xhhbjj.com -xhhd6.com -xhhfw.com -xhidc.com -xhj.com -xhj88.com -xhjingling.com -xhlgfsc.com -xhma.com -xhmyy.com -xhmzgbj.com -xhn888.com -xhnews.net -xhood.net -xhostserver.com -xhpfw.com -xhpiano.com -xhqqt.com -xhscdn.com -xhsd.com -xhsdjs.com -xhsfw.com -xhslink.com -xhspx.com -xhsyww.com -xht.com.hk -xhtjg.com -xhuojia.com -xhup.club -xhwhouse.com -xhxsw.com -xhxswz.com -xhxw.com -xhy.com -xhyd.com -xhytd.com -xhzgold.com -xhzyyu.com -xi-soft.com -xi5jie.com -xi9p.com -xia1ge.com -xiaa.net -xiabb.club -xiabingbao.com -xiabu.com -xiacai.com -xiacaipiao.com -xiache8.com -xiachufang.com -xiada.net -xiadele.com -xiadts.com -xiadu.com -xiagaoqing.com -xiaix.me -xiake.net -xiakeol.com -xiakeshan.com -xialaile.com -xialatong.com -xiald.com -xialingying.cc -xialv.com -xiamenair.com -xiamentianqi114.com -xiami.com -xiami.net -xiami001.com -xiami77.com -xiamiaopai.com -xiamoyun.com -xiamp4.com -xian-tourism.com -xianae.com -xianba.net -xianbai.me -xianbdj.com -xianbense.com -xianbey.com -xianchihuo.net -xiancn.com -xiandaiyuwen.com -xiandanjia.com -xiandaohu.net -xianfae.com -xianfeng.net -xianfengex.com -xianfengsg.com -xiang-le.com -xiang5.com -xiang578.com -xiangaiwang.com -xiangange.com -xianganquan.com -xianganyu.com -xiangbinmeigui.com -xiangbojiubo.com -xiangcaozhaopin.com -xiangcunxiaoshuo.com -xiangcunxiaoshuo.la -xiangdang.net -xiangfan.org -xiangguo.com -xiangguohe.com -xiangha.com -xianghui8.com -xianghunet.com -xiangjiaoapps.com -xiangkanzs.com -xiangkesi.com -xiangley.com -xianglute.com -xiangmaita.com -xiangmaojx.com -xiangmu.com -xiangni.com -xiangpeach.com -xiangpi.com -xiangqianpos.com -xiangqin7.com -xiangqinplus.com -xiangqiushi.com -xiangqu.com -xiangrikui.co -xiangrikui.com -xiangshang360.com -xiangshanpark.com -xiangshe.com -xiangshengbao.com -xiangshi.cc -xiangshi123.com -xiangshu.net -xiangshuiping.com -xiangsidi.com -xiangsw.com -xiangtatech.com -xiangtone.com -xiangtuan.xyz -xianguangergaozhi.com -xianguo.com -xiangw.com -xiangwangdesh.com -xiangwushuo.com -xiangyan6.com -xiangyang.net -xiangyiai.com -xiangyukj.com -xiangyun.so -xiangyunseo.com -xiangzhan.com -xiangzhiren.com -xiangzhuyuan.com -xianjian10.com -xianjichina.com -xianjincard.com -xianjj.com -xiankan.com -xiankankan.com -xianlaigame.com -xianlaihy.com -xianliao.me -xianlife.com -xianmin.org -xianms.com -xiannanyou.com -xiannvtu.com -xianpp.com -xianqiao.wang -xianruan.com -xianshiqiba.com -xianshu.com -xianshua.net -xianshuabao.com -xianshufang.com -xiantao.com -xianwangs.cc -xianxia.pro -xianxiadao.com -xianxiadao.net -xianxiajie.com -xianyang888.com -xianyin.net -xianyu.mobi -xianyuange.com -xianyugame.com -xianyugouwu.com -xianyuso.com -xianyuwang.com -xianyuyouxi.com -xianzhaiwang.com -xianzhanget.com -xianzhi.net -xianzhong.net -xianzhongwang.com -xiao-an.com -xiao-bo.com -xiao-new.com -xiao-sports.com -xiao6.tv -xiao84.com -xiao89.com -xiaoa.name -xiaoacha.com -xiaobai.com -xiaobaibk.com -xiaobaidj.com -xiaobaijidi.net -xiaobaipan.com -xiaobaishiji.com -xiaobaishixi.com -xiaobaiss.com -xiaobaiupin.com -xiaobaivr.com -xiaobaixitong.com -xiaobangbaoxian.com -xiaobao360.com -xiaobao8.com -xiaobaodt.com -xiaobaoonline.com -xiaobaostudio.com -xiaobd.net -xiaobenzi.com -xiaobingxitong.com -xiaobu121.com -xiaocaoo.com -xiaocaoyun.com -xiaocen.com -xiaoche001.com -xiaoche5.com -xiaochengxucms.com -xiaochiwang.org -xiaochunai.com -xiaocifang.com -xiaocms.com -xiaocong.tv -xiaodaiindustrial.com -xiaodaka.net -xiaodanyang.com -xiaodao.la -xiaodao360.com -xiaodaotv.com -xiaodaozhi.com -xiaodengta.com -xiaodengvip.com -xiaodian.com -xiaodian.in -xiaodian.so -xiaodianpu.com -xiaodianweb.com -xiaodigu.com -xiaodigufz.com -xiaodoubi.com -xiaodoushebao.com -xiaodouzhuan.net -xiaoduoai.com -xiaoduseo.com -xiaodutv.com -xiaody.com -xiaoe-tech.com -xiaoeknow.com -xiaoenai.com -xiaoeryi.com -xiaofangdeng.com -xiaofantian.com -xiaofany.com -xiaofeng.org -xiaogan.com -xiaogouh5.com -xiaogr.com -xiaoguikuaipao.com -xiaoguowenhua.com -xiaogushi.com -xiaoh.me -xiaohaiping.cc -xiaohansong.com -xiaohb.com -xiaohe666.com -xiaohe97.com -xiaohei.com -xiaoheima.com -xiaohongblog.com -xiaohongchun.com -xiaohongshu.com -xiaohuabaichu.com -xiaohuabuluo.com -xiaohuai.com -xiaohuangji.com -xiaohuaquye.com -xiaohudie.net -xiaohulu.com -xiaohuochai.cc -xiaohuochai.site -xiaohuwl.com -xiaoj.com -xiaoji.com -xiaoji001.com -xiaojian.site -xiaojianjian.net -xiaojiaoyar.com -xiaojiding.com -xiaojing360.com -xiaojiuwang.com -xiaojl.com -xiaojuchefu.com -xiaojudeng.com -xiaojukeji.com -xiaojun.org -xiaojunzi.com -xiaoka.tv -xiaokakeji.com -xiaokanba.com -xiaokanglongjiang.com -xiaokao.com -xiaokaxiu.com -xiaokcehui.com -xiaokeai.com -xiaokeduo.com -xiaokesoso.com -xiaokuihua.net -xiaokusha.com -xiaokyx.com -xiaolaba.xin -xiaolai.net -xiaolajiao.com -xiaolantiao.com -xiaolee.net -xiaoliangkou.com -xiaolin.in -xiaolinsi.com -xiaolinwl.com -xiaolinyuan.com -xiaolist.com -xiaolixiaoxue.com -xiaolizhuli.com -xiaolu123.com -xiaoluboke.com -xiaoluhaohuo.com -xiaoluyouxuan.com -xiaoma-school.com -xiaoma.com -xiaoma.net -xiaoma.wang -xiaomachuxing.com -xiaomagaojian.com -xiaomaigongkao.com -xiaomaiketang.com -xiaomantu.com -xiaomaowan.com -xiaomape.com -xiaomashijia.com -xiaomastack.com -xiaomav.com -xiaomaxitong.com -xiaomayi.co -xiaomayi88.com -xiaomei.cc -xiaomeiti.com -xiaomeme.com -xiaomi.com -xiaomi.hk -xiaomi.net -xiaomi.tw -xiaomian.net -xiaomiaozai.com -xiaomicp.com -xiaominet.com -xiaominfo.com -xiaoming.me -xiaomiquan.com -xiaomishu.com -xiaomiss.com -xiaomitv.cc -xiaomiwujiecao.com -xiaomiyoupin.com -xiaomlove.com -xiaomor.com -xiaomoyao.com -xiaomuji.info -xiaomy.net -xiaomyc.com -xiaomz.com -xiaonaodai.com -xiaonei.com -xiaoniba.com -xiaoniu66.com -xiaoniu88.com -xiaoniuapp.com -xiaoniudunkj.com -xiaononfu.com -xiaopan.cc -xiaopangyu.com -xiaopena.com -xiaopeng.com -xiaophy.com -xiaopi.com -xiaopin5.com -xiaopinw.com -xiaopiu.com -xiaopy.cc -xiaoqiandao.com -xiaoqiangge.com -xiaoqiaomm.com -xiaoqijj.com -xiaoqingtou.com -xiaoqiqiao.com -xiaoqugang.com -xiaoqukuaishou.com -xiaoquyijia.com -xiaorizi.me -xiaorui.cc -xiaoruibao.com -xiaoshengqi8.com -xiaoshentui.com -xiaoshijie.com -xiaoshikd.com -xiaoshitou123.com -xiaoshituina.vip -xiaoshoubang.org -xiaoshouhudong.com -xiaoshoukuaifa.com -xiaoshouyi.com -xiaoshouzhi.com -xiaoshu168.com -xiaoshujiang.com -xiaoshukaihua.com -xiaoshuo.com -xiaoshuo1-sm.com -xiaoshuo2016.com -xiaoshuo520.com -xiaoshuo530.com -xiaoshuo570.com -xiaoshuo77.com -xiaoshuoba.com -xiaoshuobi.cc -xiaoshuochen.com -xiaoshuodaquan.com -xiaoshuoli.com -xiaoshuoshu.org -xiaoshuotxt.com -xiaoshuotxt.org -xiaoshuoyd.com -xiaoshuozu.com -xiaoshuwu.vip -xiaoshuxiong.com -xiaositv.com -xiaoso.net -xiaoss.net -xiaot.com -xiaota.com -xiaotaiyang.org -xiaotee.com -xiaoten.com -xiaotengyouxi.com -xiaotuzhan.com -xiaou2014.com -xiaouguanjia.com -xiaouqyfw.com -xiaoushuo.com -xiaowang.net -xiaowangshen.com -xiaowangyun.com -xiaowanzhou.net -xiaowazi.com -xiaoweigod.com -xiaoweirobot.com -xiaoweizhibo.com -xiaowiba.com -xiaowm.com -xiaoxiaapi.com -xiaoxiangbz.com -xiaoxianggame.com -xiaoxiangxueyuan.com -xiaoxiangyoupin.com -xiaoxiansheng.com -xiaoxiao.com -xiaoxiao517.com -xiaoxiaohuajia.com -xiaoxiaoketang.com -xiaoxiaomo.com -xiaoxiaotong.org -xiaoxiaozi.com -xiaoxichangliu.com -xiaoxineye.com -xiaoxinrili.com -xiaoxintoutiao.com -xiaoxintuku.com -xiaoxiongyouhao.com -xiaoxue123.com -xiaoxuehelp.com -xiaoyantong.com -xiaoyaobi.com -xiaoyaoyou.com -xiaoyaoyou365.com -xiaoyatong.com -xiaoyayun.com -xiaoyeren.com -xiaoyewuliu.com -xiaoyi.com -xiaoyida.com -xiaoyida.net -xiaoying.co -xiaoying.com -xiaoying.tv -xiaoyiwo.net -xiaoyoucaip2p.com -xiaoyouxi100.com -xiaoyouxiqun.com -xiaoyu.com -xiaoyuan666.com -xiaoyuanjiu.com -xiaoyuanzhao.com -xiaoyuanzhaopin.net -xiaoyuer.com -xiaoyulog.com -xiaoyun.com -xiaoyunquegroup.com -xiaoyusan.com -xiaoyusanchou.com -xiaoyuxitong.com -xiaoyuzhoufm.com -xiaoyuzhuanqian.com -xiaoz.me -xiaoz123.com -xiaozaixiao.com -xiaozehuashi.com -xiaozhan.cc -xiaozhang365.com -xiaozhaolaila.com -xiaozhewz.com -xiaozhibaoxian.com -xiaozhibo.com -xiaozhichuangke.com -xiaozhiyun.com -xiaozhu.com -xiaozhu2.com -xiaozhua.com -xiaozhuanlan.com -xiaozhustatic1.com -xiaozhustatic2.com -xiaozhustatic3.com -xiaozhuvideo.com -xiaozhuyoupu.com -xiaozigame.com -xiaozuan8.com -xiaozuowen.net -xiappt.com -xiaqunfeng.cc -xiariboke.com -xiarikui.com -xiarj.com -xiashu.app -xiashu.la -xiashuwu.com -xiataoseo.com -xiatou.com -xiawan8.com -xiawu.com -xiaxiab8.com -xiayige.org -xiayiqu.com -xiayx.com -xiaz66.com -xiazai.com -xiazai163.com -xiazai9527.com -xiazaiba.com -xiazaicc.com -xiazaidb.com -xiazaidc.com -xiazaidown.com -xiazaiduo.com -xiazaijidi.com -xiazaima.com -xiazaimv.com -xiazaisoft.com -xiazaiziti.com -xibaiwang.com -xibao100.com -xibeicanyin.com -xibeidev.com -xibsteel.com -xibu168.com -xibub2b.com -xibulaobohui.com -xibutiyu.com -xicai89.com -xicaijing.com -xicaishe.com -xice.wang -xichu.net -xichuangzhu.com -xici.com -xici.net -xici800.com -xicidaili.com -xicp.net -xidao123.com -xidea-inc.com -xidesheng.com -xidian.cc -xidibuy.com -xidie.com -xidong.net -xidongv.com -xidoukeji.com -xiduobaby.com -xiduoil.com -xie-jue-tui-xiao.com -xieat.com -xiebao18.com -xieboke.net -xiechao.org -xieche.net -xiecheng.com -xiechuangw.com -xiecuo.com -xiedaimala.com -xieeku.com -xiefenxiang.com -xiehe.tv -xieheedu.com -xiehejx.com -xiehekjkf.com -xiejiahe.com -xiejianji.com -xiejiaxin.com -xiejing.com -xieliqun.com -xiesk.com -xieso.net -xietui.com -xiexiaoyuan.com -xiexiebang.com -xiexingcun.com -xiexingme.com -xieyangzhe.com -xieyinwang.com -xiezefan.me -xiezewen.com -xiezhenxian.net -xiezhenye.com -xiezixiansheng.com -xiezuocat.com -xifan.org -xifangw.com -xifatuan.com -xifenfei.com -xifenggroup.com -xifengjiuzhaoshang.com -xifuquan.com -xifuwa.com -xigeweb.com -xigo.tv -xigua-yingyin.com -xigua110.com -xigua15.cc -xigua15.com -xigua66.com -xiguabook.com -xiguaimg.com -xiguaji.com -xiguaplayer.com -xiguavideo.net -xiguayingyinbofangqi.net -xigulu.com -xigushan.com -xigushan.net -xihachina.com -xihaiannews.com -xihawan8.com -xihuan.me -xihuanfang.com -xihuanqian.com -xihuojie.com -xihusgh.com -xihustateguesthangzhou.com -xiiapp.com -xiimoon.com -xiji.com -xijiangtv.com -xijing01.com -xijucn.com -xikan.tv -xikii.com -xikuu.com -xiladaili.com -xilaiping.com -xilexuan.com -xileyougame.com -xilidou.com -xilin.com -xilinglong.net -xilinjie.com -xilinsi.org -xilish.com -xilu.com -xilvlaw.com -xima.org -xima.tv -ximalaya.com -ximalayaos.com -ximgs.net -ximiplay.com -ximiued.com -ximiyouxi.com -ximizi.com -ximopanda.com -ximuok.com -ximuw.com -xin.com -xin.xin -xin1234.com -xin3721.com -xin661.com -xinaigame.com -xinaitu.com -xinanidc.com -xinaoyun.com -xinbaby.com -xinbaicai.com -xinbajs.com -xinbalive.com -xinbaopos.com -xinbear.com -xinbqg.com -xincache.com -xincai.com -xincaiguan.com -xincailiao.com -xincainet.com -xincaitong.net -xincanshu.com -xinceyq.com -xincg.com -xincha.com -xinchacha.com -xinchangol.com -xinchao.com -xinchaoss.com -xinchaoyue.com -xinchego.com -xincheng.com -xincheping.com -xinchuguo.com -xinchukj.com -xindaifu.com -xindayunkeji.com -xindexuexi.com -xindie.net -xindingwealth.com -xindns.mobi -xindon.com -xindong.com -xinduihuan.com -xinduo.com -xinduoad.com -xineurope.com -xinfangsheng.com -xinfee.com -xinfei.com -xinfeijituan.com -xinfengit.com -xinfengxitong.net -xinfenlei.com -xinfu888.com -xinfushe.com -xing-yan.com -xing008.com -xing73.com -xingaiming.com -xingames.com -xingbangip.com -xingbo.tv -xingchenjia.com -xingchenw.com -xingcheshixian.com -xingchezu.com -xingdaoo.com -xingdatrip.com -xingdi.me -xingdongliu.com -xinge.com -xingfagroup.com -xingfaren.com -xingfudu.com -xingfufangdai.com -xingfunancun.com -xingfuu.com -xinggan.com -xinggan.net -xinghaixu.com -xinghengedu.com -xinghuankj.com -xinghuiyl.com -xinghuo100.com -xinghuo365.com -xinghuogroup.com -xinghuoxiaoshuo.com -xinghuozk.com -xingjuhe.com -xingkbjm.com -xingkeduo.com -xingkong.com -xingkongbook.com -xingkongmt.com -xingkongweishi.net -xingkoo.com -xingkuad.com -xinglai.com -xinglinpukang.com -xingmai58.com -xingmao.cc -xingmeihui.com -xingmima.com -xingming.com -xingming.net -xingpan.com -xingpin.com -xingqiu.tv -xingqu11.com -xingren.com -xingse.net -xingseapp.com -xingshangnet.com -xingshulin.com -xingshuo.net -xingtai123.com -xingtan001.com -xingtangzp.com -xingtouzi.com -xingtu.com -xingumin.net -xingxing.com -xingxingmeiyu.com -xingyi.com -xingyigz.com -xingyongli.com -xingyoucai.com -xingyuehuyu.com -xingyuhuwai.com -xingyunba.com -xingyunxc.com -xingyunxingqiu.wang -xingyusoft.net -xingyuyouxi.com -xingzhang.com -xingzhiedu.net -xingzhilian.net -xingzhiyue.com -xingzuo.com -xingzuo123.com -xingzuo8.com -xingzuo8090.com -xingzuoshu.com -xingzuowu.com -xinhaolian.com -xinhaoqi.net -xinhay.com -xinhehui.com -xinhexinli.com -xinhongru.com -xinhtz.com -xinhua-news.com -xinhua.org -xinhua08.com -xinhuaapp.com -xinhuacu.com -xinhuamm.net -xinhuanet.com -xinhuanet.ltd -xinhuaphoto.org -xinhuapo.com -xinhuaprs.com -xinhuapub.com -xinhuashe.org -xinhuatoupiao.com -xinhuawang.com -xinhuayimin.com -xinhuazhiyun.com -xinhuipihua.com -xinhushang.org -xiniu.com -xiniu1688.com -xiniu3d.com -xiniugushi.com -xiniuyun.com -xiniuz.com -xinji.org -xinjiadiy.com -xinjiance.com -xinjianggou.com -xinjiapolaowu.com -xinjiaxuan999.com -xinjimo.com -xinjingks.com -xinjisuan.net -xinjizhou.com -xinjunshi.net -xinjunshicn.net -xinkamai.com -xinkb.org -xinkeji2016.com -xinkuai.com -xinle366.com -xinli001.cc -xinli001.com -xinli001wx.com -xinliceping.com -xinlifudao.com -xinlimaoyi.com -xinling.fm -xinlinghuayuan.com -xinlingletu.com -xinlixue525.com -xinluex.com -xinluobo.com -xinlvtu.com -xinm123.com -xinmanduo.com -xinmanyuan.com -xinmei6.com -xinmeihu.com -xinmima.com -xinmuedu.com -xinnet.com -xinniangjie.com -xinnianhua.com -xinnong.com -xinnuoqian.com -xinouhk.com -xinpianchang.com -xinpianyugao.com -xinping.org -xinpinget.com -xinpujie.com -xinpure.com -xinqiannv.com -xinqigu.com -xinqing.com -xinqingdou.com -xinqishou.com -xinqixi.com -xinqiyejia.com -xinqiys.com -xinqtech.com -xinquanedu.com -xinquji.com -xinran1016.com -xinranliu.me -xinray.net -xinrenxinshi.com -xinrong.com -xinrong88.com -xinrui-games.com -xinrz.com -xinsanbanbao.com -xinsdn.com -xinshangmeng.com -xinshangshangxin.com -xinshiba.com -xinshipu.com -xinshishen.com -xinshiye.cc -xinshoucun.com -xinshouzhanzhang.com -xinshubao.net -xinshula.com -xinshulaile.com -xinshuru.com -xinsilu.com -xinsiyang.com -xinstall.com -xinstatic.com -xintaileju.com -xintaizhou.com -xintenseo.com -xintheme.com -xintian.org -xintiao100.com -xintiao80.com -xintiaoyouxi.com -xintongconference.com -xintudiy.com -xintuiwang.com -xintuofalv.com -xinwangcj.com -xinweiyun.com -xinwen365.com -xinwen520.net -xinwengao.net -xinwenlianbo.cc -xinwenlianbo.tv -xinwenlianbovip.com -xinwentoutiao.net -xinwo.com -xinxianghui.com -xinxianshilb.com -xinxiansk.com -xinxiaochina.com -xinxiaodian.com -xinxiaoqi.com -xinxic.com -xinxifabu.net -xinxilai.net -xinxinapp.net -xinxindai.com -xinxing.org -xinxing001.com -xinxing100.com -xinxingdaoju.com -xinxingjiaocheng.com -xinxingly.com -xinxingpump.com -xinxinjoy.com -xinxinkeji168.com -xinxinshukong.com -xinxisea.com -xinxunwang.com -xinyali.net -xinyan.com -xinyaoyao.com -xinyayk.com -xinyegang.com -xinyelianmeng.com -xinyicms.com -xinyifu.net -xinyisemi.com -xinyitt.com -xinyo100.com -xinyongbuy.com -xinyongqingdao.com -xinyou.com -xinyour.com -xinyouw.org -xinyu19.com -xinyuefei.com -xinyueseo.com -xinyukj99.com -xinyunfuwu.com -xinyunji.com -xinyuwanju.com -xinyuwen.com -xinzaoxing.com -xinzengwj.net -xinzhangyou.net -xinzheng.cc -xinzhenkj.com -xinzhongnews.com -xiong.ac -xionganflower.net -xionganzhuce.com -xiongdayq.com -xiongdong.com -xiongmao666.com -xiongmaojinku.com -xiongmaopan.com -xiongmaoxingyan.com -xiongyin.com -xiongying.com -xiongzhangad.com -xipushuju.net -xipuu.com -xiqb.com -xiqihe.com -xiqimi.com -xiqingji.com -xiqinrc.com -xirang.com -xirenxuan.com -xishanju.com -xishaoye.com -xishiqu.com -xishiwang.com -xishuai.com -xishuai.net -xishuiw.com -xisj.com -xitao88.com -xitaoinfo.com -xitek.com -xitek.net -xitie.com -xitieba.com -xitmi.com -xitong-tech.com -xitong110.com -xitong8.com -xitongbuluo.com -xitongcheng.cc -xitongcheng.com -xitongdaquan.net -xitonggho.com -xitonghe.com -xitonghuayuan.net -xitongiso.com -xitongjiaocheng.com -xitongku.cc -xitongle.com -xitongmen.com -xitongmonitor.com -xitongpe.com -xitongqingli.com -xitongtiandi.com -xitongtiandi.net -xitongtiankong.com -xitongtu.net -xitongwanjia.com -xitongxz.com -xitongxz.net -xitongzhijia.net -xitouwang.com -xitu.io -xituan.com -xituju.com -xiu.com -xiu8.com -xiuai.com -xiucai.com -xiuchuang.com -xiudodo.com -xiufaxing.com -xiugei.com -xiugu.com -xiuhome.com -xiuimg.com -xiujiadian.com -xiujukoo.com -xiukuba.com -xiulian.com -xiuluowang.com -xiulv.com -xiumb.com -xiumei.com -xiumi.com -xiumi.us -xiumius.com -xiumucn.com -xiuna.com -xiunian.wang -xiuno.com -xiupin.com -xiushao.com -xiusheji.com -xiusheji.net -xiushuang.com -xiushuitv.com -xiustatic.com -xiutuan.com -xiutv.com -xiuxian.org -xiuxiandou.com -xiuxiu.com -xiuzhan365.com -xiuzhanwang.com -xiuzilady.com -xiwang56.com -xiwangchina.com -xiwangd.com -xiwanglife.com -xiwenquan.com -xiwnn.com -xiwuji.com -xixi520.com -xixiaguoye.com -xixiaoyou.com -xixiarc.com -xixibobo.com -xixiclothing.com -xixihd.com -xixijiji.com -xixik.com -xixik.net -xixin123.com -xixing168.com -xixinv.com -xixipan.com -xixiqiu.com -xixisys.com -xixiwg.com -xiyijiang.com -xiyiqq.com -xiyogo.com -xiyoo.com -xiyou-g.com -xiyou360.net -xiyoucdn.com -xiyouchat.com -xiyoucts.net -xiyouence.com -xiyouji.com -xiyouo.com -xiyouquan.com -xiyousdk.com -xiyouwebgame.com -xiyow.com -xiyuan.tv -xiyuchou.com -xiyuege.com -xiyun.net -xiyurumen.com -xizanggl.com -xizangguolv.net -xizangqinglv.com -xizangzl.com -xizhang.com -xizhezhe.com -xizhi.com -xizhibei.me -xizi.com -xizike.com -xiziquan.com -xiziwang.net -xj-gr.com -xj-hao.com -xj-zp.com -xj120.com -xj123.info -xj169.com -xj474hos.com -xj7road.com -xj96596.com -xjabc.net -xjass.com -xjbaihua.com -xjbdf.net -xjbhyx.com -xjbmaker.com -xjbuluo.com -xjc18.com -xjcbt.com -xjcc.net -xjche365.com -xjcmtj.com -xjctc.net -xjdaily.com -xjdkctz.com -xjdpx.com -xjdsb.com -xjdwx.com -xjent.com -xjfda.com -xjfeiniu.com -xjfilm.net -xjflcp.com -xjfzb.com -xjggjy.com -xjgj.com -xjgqt.org -xjgsdm.com -xjgwy.org -xjh.me -xjhgame.net -xjhjsd.com -xjhr.com -xjietiao.com -xjishu.com -xjisme.com -xjiuai.com -xjjjb.com -xjjnjp.org -xjjxc.com -xjkwm.com -xjltp.com -xjlxw.com -xjlz365.com -xjmglr.com -xjmw.net -xjorsa.net -xjp.cc -xjpdf.com -xjphsd.com -xjpz.me -xjrb.net -xjrmyy.com -xjshift.com -xjtour.com -xjtsnews.com -xjttt.com -xjtuccjsj.com -xjtucompressor.com -xjtudlc.com -xjwljb.com -xjwork.com -xjwyglw.com -xjxbx.com -xjxsjyy.com -xjxy.com -xjy415.net -xjyaxin.com -xjyqly.com -xjytjt.com -xjzdjx.com -xjzkzx.com -xjzlyy.com -xjzsks.com -xk65.vip -xk8090.com -xk89.com -xk9l.com -xkb1.com -xkbsw.com -xkdmp.com -xker.com -xkhouse.com -xkpx.com -xkreading.com -xksafe.com -xkw.com -xkwe.com -xkyn.com -xkyn.net -xkzww.net -xkzzz.com -xl-ai.com -xl-soft.com -xl13.com -xl526.com -xl699.com -xlbinyi.com -xlcidc.com -xlctyd.com -xlcz.com -xldytt.com -xlfans.com -xlgao.com -xlgxapp.com -xlhb.com -xlimg.net -xlinclass.com -xlisp.net -xljnjy.com -xlkorganic.com -xlkty.com -xllxdg.com -xlm33.com -xlobo.com -xlpan.com -xlpz6.com -xlrocket.com -xlshou.com -xltkwj.com -xltrip.com -xltzgy.com -xluos.com -xlwdh.com -xlwxsw.com -xlxzikao.com -xlylf.com -xlyouxi.com -xlysauc.com -xlysoft.net -xlzd.me -xlzhao.com -xlzx.com -xlzx123.com -xlzxdc.com -xlzyyw.com -xm-ad.com -xm-chuang.com -xm-olympic-museum.org -xm0760.wang -xm680.com -xm909.com -xm9m.com -xmadx.net -xmamiga.com -xmanblog.net -xmantou.com -xmbankonline.com -xmbhw.com -xmbike.com -xmbwsm.com -xmccb.com -xmcdn.com -xmchong.com -xmcimg.com -xmcp.ml -xmcwh.com -xmcx.net -xmcymg.com -xmd5.com -xmdimeisi.com -xmeasygo.com -xmecard.com -xmedchain.com -xmeise.com -xmf.com -xmfc.com -xmferry.com -xmfish.com -xmfunny.com -xmgc360.com -xmgps.com -xmgsd.com -xmheitu.com -xmhitek.com -xmhouse.com -xmigc.com -xmindchina.net -xminfoport.com -xmisp.com -xmitic.com -xmj.app -xmjgjy.com -xmjhome.com -xmjim.com -xmjn.org -xmjslh.com -xmjyw.com -xmkanshu.com -xml-data.org -xmlanshu.com -xmlhifi.com -xmlicai.com -xmlure.com -xmlvbarcode.com -xmmade.com -xmmama.com -xmmtoys.com -xmnjdwx.com -xmnovel.com -xmonecode.com -xmpcba.com -xmqcly.com -xmrbi.com -xmsec.cc -xmshqh.com -xmsixian.com -xmsme.com -xmsmjk.com -xmsoft.com -xmspace.net -xmsunyoung.com -xmtbang.com -xmtekic.com -xmtiaozhuan.com -xmtnews.com -xmtyl.com -xmuchong.com -xmuli.tech -xmwan.com -xmwsrc.com -xmwzfcyy.com -xmxdev.com -xmxgame.com -xmxwl.net -xmxwz.com -xmydys.com -xmyeditor.com -xmyijing.com -xmyipin.com -xmylhy.com -xmyxoa.com -xmzdls.com -xmzylh.com -xn--0xv28g5vz8fs.com -xn--1lq8pg83a3pb4zr6m0c.com -xn--2krw29cdqai43k.com -xn--2qu92fhtx4ff.site -xn--2qux23c9ziyrq.club -xn--2qux23c9ziyrq.plus -xn--2qux23c9ziyrq.video -xn--2qux23confgml.club -xn--2qux23confgml.online -xn--3bs795g.link -xn--3bs795g.zone -xn--48s290ajcu2tzl891isd3anfh.com -xn--4gqqc629gbju.com -xn--4gqwb715dj2dewvbilsep42y.com -xn--6rt008ee0k3ua.com -xn--6rt008ee0k3ua.net -xn--7hv285el2dtof.com -xn--8tw.com -xn--9kq745jwng.ink -xn--ddua45lfy1c.ink -xn--dkr447bejn.com -xn--dkr447bejn.net -xn--e9qp53aepg.xn--ses554g -xn--ebr05n.com -xn--eqrt2g.xn--vuq861b -xn--fiq8ituh5mn9d1qbc28lu5dusc.xn--vuq861b -xn--fiqz7g67bsydx1ed00d.com -xn--fjqz50cv5q3so.ltd -xn--fjqz50cv5q3so.online -xn--glr604k.com -xn--hgvp6a86z.xn--6qq986b3xl -xn--i7qt52bvsr0u0a.com -xn--it-1r3f.com -xn--jvr53oiv5alxv.net -xn--mtso8sj6menhyil.online -xn--mtsr39cnql.video -xn--ntsp37j.net -xn--nyw032beqlm2f.com -xn--nyw032beqlm2f.net -xn--qp3ay7l.cc -xn--s4t325g.com -xn--tt-rv2cuk223byodtx8f.com -xn--vhquvr92a7u1b.com -xn--wlqw5ebvdhpi5hepihs3c.com -xn--wxt79hbyb675a.online -xn--wxtr9fwyxk9c.xn--55qx5d -xn--xhq9mt12cf5v.ink -xn--xhq9mt12cf5v.site -xn--xhqp98ceybfxgfm8a96y.com -xn--ygtp21bwyedsq.com -xn--zq2aw6m.xyz -xn-ck.com -xn121.com -xn97.com -xnaidog.com -xnapp.com -xnara.org -xnb.me -xncoding.com -xncoo.com -xncredit.com -xndm.tech -xndushu.com -xnguke.com -xnhdgame.com -xninja.org -xnipapp.com -xnjcw.com -xnjjob.com -xnjypt.com -xnlkj.com -xnnpc.com -xnongren.com -xnow.me -xnpic.com -xnrg.net -xns315.com -xnsdun.com -xnsla.com -xnsqc.com -xnszsjgyey.com -xntt.com -xntv.tv -xnw.com -xnwan.com -xnwx2014.net -xnxin.com -xny365.com -xnyauto.com -xnye.net -xnzjxx.com -xoao.com -xobobo.com -xocoder.com -xoliao.com -xooooa.com -xorpay.com -xoveskincare.com -xoxknct.com -xoxv.net -xoyo.com -xoyobox.com -xoyocdn.com -xoyq.net -xp002.com -xp5.com -xp6000.com -xp666.com -xp74.com -xp85.com -xp868.com -xp933.com -xp9365.com -xpaper.com -xpaper.net -xpaper.vip -xpath.org -xpc420.com -xpccdn.com -xpcha.com -xpgod.com -xpj-baidu.com -xpjcs7.com -xpjedu.com -xpjj.net -xpjm.net -xplian.net -xppmh104.com -xppmh52.com -xppmh94.com -xpsheying.com -xpsy.net -xptt.com -xpu93.com -xpw888.com -xpxt.net -xpyx.net -xq0356.com -xqanhui.com -xqb24.com -xqblog.com -xqbxz.com -xqchuxing.com -xqckg.com -xqfunds.com -xqggz.com -xqipu.com -xqishu.com -xqiushu.com -xqjmzc.com -xqjs.net -xqkqk.com -xqs360.com -xqsbw.com -xqship.com -xqspx.com -xqtesting.com -xqwww.com -xqyz.net -xrcch.com -xrccp.com -xreacloud.com -xredu.com -xrender.com -xrfood.com -xrichengapp.com -xrkapp.com -xrkcdn.com -xrkmonitor.com -xrso.com -xrswiv.bar -xrtcc.com -xrunda.com -xrwcn.com -xrwhcm.com -xs-dczx.com -xs-servers.com -xs163.net -xs222.tw -xs2500.com -xs321.com -xs386.com -xs3cnc.com -xs52.com -xs7.cc -xs7.la -xs74.com -xs82.net -xs880.com -xs91.net -xs963.com -xsasn.com -xsb.tw -xsb120.com -xsbashi.net -xsbiquge.com -xsbiqugew.com -xscbs.com -xschu.com -xsdwk.com -xsec.io -xsee.cc -xsery.net -xsesc.com -xsfaya.com -xsfc.com -xshapp.com -xshb.net -xshell.net -xshellcn.com -xshengyan.com -xshenshu.com -xshkvip.com -xshouyi.com -xshulin.com -xshuma.com -xshuoba.com -xshuotxt.com -xshwp.com -xshyhotel.com -xsina.net -xsj2020888.com -xsjedu.org -xsjsource.com -xsjtxt.com -xsjwyx.com -xsjx.net -xskhome.com -xsldh.net -xslou.com -xsmaofa.com -xsmnews.com -xsmore.com -xsnsyh.com -xsool.com -xspcf.com -xspic.com -xspliter.com -xsrjt.com -xsrtvu.com -xsshuku.com -xssk.net -xssousou.com -xsstomy.com -xssz.net -xsteach.com -xsti.net -xstqj.com -xstt5.com -xstx.info -xsu.cc -xsuimeng.com -xsvps.com -xswdcasting.com -xsxkzz.com -xsy668.com -xsyk021.com -xsyqmztg.com -xsyushan.com -xsyxsc.com -xszedu.com -xszp.cc -xszrcw.com -xszww.com -xszysc.com -xt-kp.com -xt-tattoo.com -xt12333.com -xt70.com -xt918.com -xtao.me -xtbank.com -xtc-edu.com -xtcaq.com -xtcrm.com -xtctp.com -xtdpye.com -xtea.org -xtedu.com -xteko.com -xtfcjt.com -xtfml.com -xtgreat.com -xthc999.com -xthinking.net -xtjc.com -xtjky.com -xtjxsb.com -xtlkgc.com -xtlog.com -xtmtrj.com -xtongs.com -xtrc.net -xtseo.com -xtt95511.bz -xttblog.com -xttianning.com -xttongcai.com -xttongji.com -xttsg.com -xttz.com -xtu2.com -xtuan.com -xtuo.net -xtutoring.com -xtyxdq.com -xtzhao.com -xu7b.com -xuanad.com -xuanbiaoqing.com -xuancaizi.com -xuanceo.com -xuancheng.org -xuandan.com -xuande99.com -xuandui.me -xuanfengge.com -xuanfengkeji.com -xuanfuwang.com -xuanhua8.com -xuanhuafb.com -xuanhuange.com -xuanhuange.net -xuanhuanmi.com -xuanjutong.com -xuanke.com -xuanlishi.com -xuanliwang.com -xuannaer.com -xuanquge.com -xuanqun.com -xuanruanjian.com -xuanshu.com -xuantaikeji.com -xuanwonainiu.com -xuanwu88.com -xuanwuhuijeushiwu.com -xuanwumobile.com -xuanxiu.cc -xuanxuan.com -xuanxuangame.com -xuanxuantemai.com -xuanxue.com -xuanyangxl.com -xuanyouwang.com -xuanyusong.com -xuanzhoubian.com -xubei.com -xubo.cc -xuchuang.com -xudan123.com -xudankeji.com -xudongfood.com -xudoodoo.com -xuduan.vip -xue163.net -xue3dmax.com -xue51.com -xue63.com -xueanquan.com -xueba100.com -xuebalib.com -xuebao365.com -xuebingsi.com -xuebuyuan.com -xuecaijie.com -xuecan.net -xueche8.com -xuechebu.com -xuechela.com -xuechenlei.com -xueda.com -xuedi.com -xuedong97.com -xueepay.com -xueersen.com -xueersi.com -xueerxing.com -xuefenxi.com -xuefo.net -xuegaogame.com -xuegeshui.com -xuegongkong.com -xueguoedu.net -xuehai.net -xuehaibjb.com -xuehaoba.com -xuehuahua.cc -xuehuahua.net -xuehui.com -xuehuile.com -xuehuiwang.com -xueit.com -xuejiehome.com -xuejiqiao.com -xuekeedu.com -xuekuaiji.com -xuekubao.com -xuelecn.com -xuelema.com -xueleyun.com -xueli9.com -xuelu.org -xueming.li -xuenb.com -xuepaijie.com -xuepojie.com -xueqiu.com -xueqiu360.com -xuerentang.net -xuesax.com -xueseo.com -xueshandai.com -xueshanlinghu.com -xueshen.net -xueshiboke.com -xueshiyun.com -xueshu.com -xueshu5.com -xueshuda.com -xuetangonline.com -xuetangx.com -xuetangzaixian.com -xueti.com -xuetimes.com -xuetu.net -xuetuwuyou.com -xueui.com -xueuisheji.com -xuewangshang.com -xuewangzhan.com -xuewangzhan.net -xuewei.net -xueweijiema.com -xuewennet.com -xuexb.com -xuexi.la -xuexi111.com -xuexi365.com -xuexiaodaquan.com -xuexiaodaquan.net -xuexiaozhaopin.com -xuexibao.com -xuexigang.com -xuexijilu.com -xuexila.com -xuexili.com -xuexilinux.com -xuexin365.com -xuexiniu.com -xuexitong.com -xuexivip.net -xueyanshe.com -xueyiyun.com -xueyou.org -xueyuanjun.com -xuezhoubaoa.com -xuezhouyi.com -xuezizhai.com -xugaoyang.com -xugucn.com -xuhangzj.com -xuhehuan.com -xuhot.com -xujianhua.com -xujun.org -xukai.xyz -xuliangwei.com -xulihang.me -xulizui6.com -xulonggame.com -xulv.net -xumenger.com -xuminggang.com -xumingxiang.com -xumurc.com -xun1688.com -xunbao178.com -xunbaozhifu.com -xunbibao.com -xunbin.com -xunbo.cc -xunbuy.com -xuncaoji.net -xunchabing.com -xundalm.com -xundayun.com -xundns.com -xundns.net -xundns.org -xundupdf.com -xunerjie.com -xunfang.com -xungou.com -xunhuoyi.com -xunhupay.com -xunjiecad.com -xunjiepdf.com -xunjieshipin.com -xunjietupian.com -xunkids.com -xunkoo.com -xunlei.com -xunlei.net -xunlei1.com -xunleigang.com -xunleige.com -xunleige520.com -xunleige88.com -xunleihao.com -xunleihuiyuan.net -xunleile.com -xunleimi.com -xunleimi.net -xunleimil.com -xunleiyy.com -xunlew.com -xunli.xyz -xunliandata.com -xunlong.net -xunlong.tv -xunlonghe.net -xunlongsoft.com -xunmb.com -xunmei.net -xunmeinet.com -xunmiweb.com -xunmzone.com -xunqianwang.com -xunqinet.com -xunruicms.com -xunsearch.com -xunsee.com -xunshou.com -xunshuba.com -xunsu.cc -xuntou.com -xuntuoguan.com -xunurl.com -xunwan.com -xunwangba.com -xunwei.org -xunwei.tm -xunxu.com -xunyixia.com -xunyou.com -xunyou.mobi -xunyun.com -xunzai.com -xunzi.cc -xuooo.com -xup168.com -xupu.name -xupu120.com -xuqyfw.com -xuriy.com -xuruowei.com -xuxian.com -xuxian.me -xuxueli.com -xuxusheng.com -xuyaokeji.com -xuyi.net -xuyilx.com -xuyimin.club -xuyongren.com -xuyuanyi.com -xuzhi.net -xuzhiwu.com -xuzhoujob.com -xv5b.com -xvdianchiwang.com -xvna.com -xvv.cc -xw-china.com -xw0371.com -xw1806.com -xw360.com -xwadv.com -xwartz.xyz -xwb8.com -xwbank.com -xwcms.net -xwcool.com -xwdsp.com -xwei.tv -xwhb.com -xwhb.net -xwhodesign.com -xwikichina.com -xwjqr.com -xwjr.com -xwjy.org -xwko.com -xwlmx.com -xwlunwen.com -xwlxw.com -xwn888.com -xwood.net -xwsj.org -xwtex.com -xwuad.com -xwxguan.com -xwyun.net -xwz999.com -xwzc.net -xwzxjy.com -xx007.com -xx144.com -xx4a.com -xx5.com -xxadc.com -xxb.me -xxbiquge.com -xxbmm.com -xxbodiyanliao.com -xxbt.com -xxcang.com -xxcig.com -xxcmw.com -xxd.io -xxdao.com -xxdhg.com -xxfzl.com -xxgzmlt.com -xxhd-tech.com -xxhh.com -xxhyzd.com -xxingclub.com -xxingqu.com -xxjcy.com -xxjr.com -xxjrjxc.com -xxjrqc.com -xxka.com -xxko.net -xxkt.org -xxlcn.com -xxlinux.com -xxliudsp.com -xxlwin.com -xxmac.com -xxmanhua.info -xxmh117.com -xxmh21.com -xxmh223.com -xxmh225.com -xxmh226.com -xxmh268.com -xxmh330.com -xxmh81.com -xxnets.net -xxnmcd.com -xxoojoke.com -xxorg.com -xxpie.com -xxptcs.com -xxqb5200.com -xxqipai.com -xxqun.com -xxrou.net -xxs74.com -xxs8.com -xxsb.com -xxsdfjx.com -xxshu.com -xxsy.net -xxtaotao.com -xxthemes.com -xxtiao.com -xxtjs.com -xxwenda.com -xxwolo.com -xxwygl.com -xxxfeng.com -xxxlbox.com -xxxmeng.com -xxxxxbbs.com -xxxzzlm.org -xxycw.com -xxyhzd.com -xxzdpf.com -xxzfgjj.com -xxzhushou.com -xxzs.tv -xy-365.com -xy-asia.com -xy.com -xy1212.com -xy1758.com -xy178.com -xy3000.com -xy48.net -xy50x.com -xy58.net -xy78.com -xy980.net -xyad3hada.com -xyb100.com -xybsyw.com -xybygw.com -xycaogen.com -xycareer.com -xycdn.com -xycloud.com -xyclouds.com -xyczero.com -xydcname.com -xydcname.net -xydhl.com -xydxcloud.com -xydxcs.com -xyfc.com -xyfcw.com -xyffsb.com -xyfw.org -xygjg.com -xygjx.com -xygmed.com -xygyhd.org -xyhc.com -xyhis.com -xyhlcd.com -xyhospital.com -xyhqsh.com -xyhtml5.com -xyhust-meri.com -xyimg.net -xyinzhe.com -xyj.link -xyj321.com -xyjrw.com -xyjt.org -xylink.com -xylmf.com -xymcp3.com -xymens.com -xymvip.com -xynbnb.com -xyniubi.com -xynsh.com -xyookj.com -xyous.com -xyppzx.com -xypsj.com -xyq.name -xyqb.com -xyqczy.com -xyqka.com -xyrdip.com -xyrtv.com -xysb.com -xyshu8.net -xysjk.com -xyssdzrmzf.com -xystatic.com -xystoy.com -xysy.com -xytianzi.com -xytjcpj.com -xytzg.com -xyun1.com -xyunqi.com -xyvend.com -xyvending.com -xyw.com -xywallet.com -xywxs.com -xywy.com -xywyfw.com -xywzs.com -xyx234.com -xyx521.com -xyxcables.com -xyxdie.com -xyxl.net -xyxsc.com -xyxsns.com -xyxy.com -xyxy.net -xyxy01.com -xyy001.com -xyyh.xyz -xyyksy.com -xyyx82.com -xyz-jm.com -xyz1001.xyz -xyz1412.net -xyz365.vip -xyz456.com -xyzcdn.net -xyzcn.com -xyzdict.com -xyzggg.com -xyzmdzs.com -xyzone.xyz -xyzs.com -xyzsq.com -xyzysmx.com -xz-juming.com -xz.com -xz577.com -xz6.com -xz6699.com -xz6d.com -xz7.com -xzapi56.com -xzbu.com -xzcblog.com -xzddx.com -xzfclub.com -xzfile.com -xzgjj.com -xzhichang.com -xzhizao.com -xzhwdz.com -xzji.com -xzjqx.date -xzkd.com -xzking.com -xzlkja.com -xzlogo.com -xzlres.com -xzltzc.com -xzlyt.com -xzm56.com -xzn56.com -xzokzyzy.com -xzper.com -xzr.kim -xzrj.cc -xzrm.com -xzsec.com -xzsnw.com -xzstatic.com -xztyhl.com -xztylfu.com -xzw.com -xzwwxn.com -xzx.com -xzxiaoshuo.com -xzxw.com -xzyhealth.com -xzymoe.com -xzz.me -xzzanggong.com -xzzp.net -y-os.net -y.to -y007.com -y0game.com -y1995.com -y2002.com -y261.com -y4dg.cc -y4dg.com -y500.me -y5000.com -y5663.com -y6162.com -y65b.com -y65c.com -y80s.com -y80s.net -y999.com -ya17.com -ya247.com -yaahe.com -yabet488.net -yabo242.com -yabo5807.com -yabo5826.com -yabodns.com -yabolive.com -yaboor.com -yabovip2029.com -yac8.com -yac8.net -yadgen.com -yadingchi.com -yadingtour.com -yadongnaicai.com -yaduo.com -yaeherhealth.com -yaersen.com -yafanpm.com -yafco.com -yafdev.com -yafeilinux.com -yahacode.com -yahaizi.com -yahei.net -yahoo001.com -yahuhost.com -yahui.hk -yaitest.com -yaiyuan.com -yajuke.com -yajxc.com -yakool.com -yakutv.cc -yalan888.com -yalewoo.com -yaliang.net -yalinfeng.com -yalishiyanji.com -yalixinli.com -yalongsi.com -yamadesignlab.com -yamadie.net -yameijie.com -yameisj.com -yamibo.com -yan-wei.net -yanbinghu.com -yanbm.com -yanboguoji.com -yanboyuan.com -yanche315.com -yanchebang.com -yanchengzx.com -yandianying.com -yandui.com -yanedu.com -yang16.com -yangbing.club -yangblink.com -yangcai168.com -yangchebao.cc -yangchenglianhe.com -yangchunjian.com -yangcong.com -yangcong345.com -yangcongbao.com -yangcongchufang.com -yangdongjia.com -yangerxiao.com -yangfannie.com -yangfawen.net -yangfd.com -yangfenzi.com -yangge.me -yangguanjun.com -yangguiweihuo.com -yanghengjun.com -yanghua.com -yanghuogo.com -yangjian.me -yangjie.li -yangju.vip -yangkatie.com -yangkeduo.com -yangki.net -yangkun.net -yanglajiao.com -yanglaocn.com -yanglaofuwu365.com -yanglaozhan.org -yanglee.com -yangli.com -yanglingxi.com -yanglong.pro -yangluojob.com -yangluoxw.com -yangmao.info -yangmaod.com -yangmaodang.org -yangmaohao.net -yangniupiju.com -yangqianguan.com -yangqimanhua.com -yangqq.com -yangqu.com -yangsam.com -yangsheng.com -yangshengliang.com -yangshengtt.com -yangshengzhu.com -yangshitianqi.com -yangtengfei.com -yangtianb.com -yangtianbao.com -yangtop.com -yangtse.com -yangtze-led.com -yangtze-volga.org -yangwang.pw -yangxiang.com -yangxiangming.com -yangxiaojia.me -yangxikun.com -yangxingzhen.com -yangxinlife.com -yangyangla.com -yangyanxing.com -yangyi.vip -yangyi02.com -yangyi08.com -yangyingming.com -yangyongquan.com -yangyq.net -yangzhe1991.org -yangzhi.net -yangzhiping.com -yangzhiriji.com -yangzhix.com -yangzhongchao.com -yangzhu6.com -yangzijiang.com -yangzw.vip -yanhaijing.com -yanhao.site -yanjiangwang.com -yanjiao.com -yanjiao.net -yanjiaoapp.com -yanjiaols.com -yanjiaoweixin.com -yanjinews.com -yanjingge.com -yanjiubaogao.com -yanjiushenglw.com -yanjunbo.com -yankanshu.net -yankanzw.com -yankay.com -yanlinghm.com -yanliu.org -yanlutong.com -yanmbjiage.com -yannv.com -yanoda.com -yanpk.com -yanpuzi.com -yanqiao.com -yanqing-888.net -yanqingzhan.net -yansedaquan.com -yanshihua.com -yanshishuo.com -yansudian.com -yantai-chuanpiao.com -yantaibank.net -yantaimarket.com -yantaitech.com -yantubao.com -yantuchina.com -yanue.net -yanunon.com -yanwenzi.com -yanxikm.com -yanxintong.com -yanxishe.com -yanxiu.com -yanxuezhang.net -yanyapeng.com -yanyib2b.com -yanyijingling.com -yanyiquan.com -yanyiwu.com -yanyuzw.com -yanzhiwu.com -yanzoujia.net -yao123.com -yao51.com -yaoao.net -yaobo.net -yaochixs.com -yaochufa.com -yaocsoft.com -yaodaojiao.com -yaodou.net -yaofangwang.com -yaofangwang.net -yaofx.net -yaoge123.com -yaoguo.com -yaohaixiao.com -yaohuiji.com -yaohuo.me -yaojiao.tv -yaojiedianzi.com -yaojingtang.com -yaokaihui.com -yaolaifen.com -yaolan.com -yaoliwang.com -yaomaiche.com -yaoman.net -yaomaner.com -yaonano.com -yaoning.me -yaooxx.space -yaopaiming.com -yaopinnet.com -yaoqingwo.com -yaoqmh.com -yaosai.com -yaowan.com -yaowei.info -yaoxianwu.com -yaoyedan.net -yaoying.vip -yaoyl.com -yaoyouke.com -yaoyuan.com -yaoyuanba.com -yaozh.com -yaozui.com -yareiot.com -yarnn.com -yashuseed.com -yasishuo.com -yasiyasi.com -yasking.org -yasn.com -yasuotu.com -yataishoes.com -yataiwujin.com -yatiku.com -yatiwang.com -yatsenglobal.com -yatsoft.com -yau-awards.science -yawancaiwu.com -yawenb.com -yawkj.com -yaxi.net -yaxige.com -yaxinde.com -yaxuntuhang.com -yayigou.net -yayihouse.com -yaypool.com -yayu.org -yazhifan.com -yazhougoufang.com -yazjy.com -yazuo.com -yazuo666.com -yb1518.com -yb1867.com -yb3.cc -yb411.app -yb559.com -yb5987.com -yb7962.com -yb983.com -ybaby.com -ybao.org -ybaoli.com -ybbgd.com -ybccb.com -ybccode.com -ybdudu.com -ybhdmob.com -ybi.net -ybin.cc -ybirds.com -ybj.com -ybjasb.com -ybjk.com -ybjtds.net -ybm100.com -ybren.com -ybrxl.com -ybs120.com -ybtest45.com -ybtoad.com -ybtvyun.com -ybtzjt.com -ybvipdns.com -ybvv.com -ybword.com -ybwzx.com -ybxww.com -ybzhao.com -ybzkb.com -yc.cc -yc123.com -yc370.com -yc38.com -yc717.com -yc999vip.com -ycathena.com -ycb.com -ycbright.com -ycbyzx.com -yccdn.com -ycdiaoke.com -ycdjy.com -ycdlfw.com -ycdongxu.com -yceshop.com -ycgj.cc -ycgjj.net -ycgslb.com -ychdzx.co -ychefu.com -ychmpw.com -ychromedgeie.com -ychxie.com -ychxiex.com -ycig.com -ycigilink.com -yciyun.com -ycjt2007.com -ycjtj.com -ycjyjt.com -ycku.com -ycl37.com -yclh6.com -yclunwen.com -ycmbcd.com -ycnuli.com -ycool.com -ycpack.net -ycpai.com -ycqedu.net -ycrh-tattoo.com -ycrusher.com -ycsecu.com -ycsgame.com -ycsystem.com -yct-tec.com -yctong.net -ycty.org -ycwalker.com -ycwb.com -ycwhys.com -ycxfgroup.com -ycxhdp.com -ycxjtd.com -ycyjkj.com -ycym.com -ycyui.com -yczihua.com -yd166.com -yda513.com -ydaobo.com -ydbimg.com -ydc360.com -ydcss.com -yddb88.com -ydfwgg.com -ydh.fun -ydl.com -ydl.wang -ydlbk.com -ydlcdn.com -ydm88.com -ydmel.com -ydmeng.com -ydmob.com -ydmsh.com -ydmwifi.com -ydn5.com -ydnewmedia.com -ydr.me -ydsaso.com -ydsjjs.com -ydstatic.com -ydsyxzx.com -ydtad.com -ydtnotary.com -ydtun.com -ydu6.com -yduav.com -yduedu.com -ydui.org -ydvip00ap.com -ydvip00as.com -ydx2.com -ydxlzy.com -ydxxt.com -ydy.com -ydybt.com -ydyeducation.com -ydyj.me -ydyy120.com -ye.com -ye1992.com -ye3.com -ye40.com -yea.im -yead.net -yeah.net -yeahka.com -yeahworld.com -yeai.com -yealink.com -yealinkvc.com -yeapcloud.com -yearnfar.com -yeastar.com -yeax.com -yebaike.com -yebangyu.org -yeboyzq.com -yecdn.com -yedingding.com -yedu123.com -yeeaoo.com -yeecall.com -yeecloud.com -yeedian365.com -yeefeitrip.com -yeefire.com -yeefx.net -yeekit.com -yeelight.com -yeelink.net -yeelogo.com -yeemiao.com -yeemiao.net -yeepay.com -yeepaycdn.com -yeepiao.com -yeeuu.com -yeeyan.com -yeeyan.org -yeeyk.com -yeezhe.com -yefu365.com -yegame.com -yegenyou.com -yegong.net -yehetang.com -yei02.com -yeidc.net -yejienet.com -yejing.biz -yejinye.com -yejuu.com -yelanxiaoyu.com -yelinmall.com -yelixiali.com -yelook.com -yemablog.com -yemacaijing.com -yemaili.com -yemaosheji.com -yemaosoft.com -yemayun.com -yemeihuoguo.com -yemet.com -yemi.me -yenisezonmodelleri.com -yeolar.com -yeoner.com -yeree.com -yerentan.com -yerhu.com -yes-chinese.com -yes515.com -yes58.net -yes88.com -yesacc.com -yesaha.com -yesapi.net -yesbt.cc -yesdat.com -yesdecor.com -yeseesports.com -yesense.com -yeseread.com -yeshen.com -yeshengarts.com -yeshigeek.com -yeshj.com -yeshu.com -yesidos.com -yeskn.com -yesky.com -yeslib.com -yeslicake.com -yesmryang.net -yesmyimg.com -yesmywine.com -yespearl.com -yestar.com -yestar1992.com -yestarm.com -yestarvip.com -yeston.net -yestone.com -yesudoo.com -yesuse.net -yeswan.com -yesxia.com -yesxun.com -yetang.com -yetdata.com -yetianzi.com -yetingjk.com -yetu.net -yewen.us -yewuyuan.com -yexinggroup.com -yeyaji9.com -yeyday.com -yeyetech.net -yeyezw.com -yeyimg.com -yeyo.cc -yeyou.com -yeyoucdn.com -yeyoujia.com -yeyulingfeng.com -yeyulx.com -yeyun.com -yezdm.com -yezhuwq.com -yezhuwuyou.com -yeziting.com -yezixigame.com -yfcache.com -yfcalc.com -yfcdn.net -yfcloud.com -yfcloud.io -yfcmf.net -yfcnn.com -yfdns.net -yfdts.net -yfdurl.com -yfdxs.com -yfdyf.com -yffe.com -yfgj68.com -yfhl.net -yfhxtech.com -yfiot.com -yfjiakao.com -yfjx.cc -yfklxz.com -yfmhw.com -yfp2p.net -yfpayment.com -yfscdn.com -yfscdn.net -yfservice.com -yftxt.com -yfvb.com -yfway.com -yfwnm.com -yfycrc.com -yg-dk.com -yg5.net -ygame.cc -ygc711iq.com -ygcnx.com -ygct.com -ygdy8.com -ygdy8.net -yge.me -ygei.com -yget.me -yghsh.com -ygibao.com -yginsight.com -ygjj.com -ygjoy.com -ygkmp.com -ygread.com -ygsdmedia.com -ygshangjie.com -ygsoft.com -ygtcpa.com -ygwenxue.com -ygycwx.com -ygym.org -yh05l.com -yh300.vip -yh31.com -yh596.com -yh598.com -yh88e.com -yh99.cc -yhachina.com -yhbimg.com -yhcko.com -yhcmovie.com -yhcqw.com -yhd.com -yhdm.io -yhdm.tv -yhdns.net -yhdtns.com -yhetent.com -yhfx.info -yhgo.wang -yhgo8.com -yhgyjt.com -yhhls.com -yhidc.com -yhj2000.com -yhj9.com -yhjbox.com -yhjdcom.com -yhkgas.com -yhkingdee.com -yhlbbs.com -yhm11.com -yhmh.vip -yhouse.com -yhq368.com -yhqdashi.com -yhqpd.com -yhquan365.com -yhqurl.com -yhrcb.com -yhres.com -yhrfly.com -yhrtvu.com -yhshapp.com -yhsms.com -yhspy.com -yhsrv.com -yhtools.cc -yhtower.com -yhtx.tv -yhurl.com -yhwgy.com -yhwomen.com -yhxuexiao.com -yhy50.com -yhyf.cc -yhyshop.com -yhz2000.com -yhz365.com -yhz66.com -yhzm.cc -yhzm.com -yhzml.com -yhzuche.com -yhzy365.com -yi-jy.com -yi-programmer.com -yi-you.org -yi114.com -yi2.net -yi23.net -yi588.com -yi6.com -yi7.com -yi958.com -yiaedu.com -yiai.me -yiaini.com -yianju.ltd -yiapp.com -yibaifen.com -yibaixun.com -yiban.io -yiban1314.com -yibaogao.com -yibei.com -yibencaijing.com -yibenmanhua.com -yibianxueyuan.com -yibite.com -yiboard.com -yibuzhiyao.com -yicai.com -yicaitangwangzhuan.com -yicamp.com -yichadan.com -yichangly.com -yiche.com -yichemall.com -yichengzhicheng.com -yichesafe.com -yichuyifan.com -yiclear.com -yicongfound.org -yicx.com -yidaba.com -yidai.com -yidaomobi.com -yidaservice.com -yideamobile.com -yidejia.com -yidejr.com -yidejr.net -yidengxuetang.com -yidexuan.net -yidian360.com -yidianchina.com -yidianer.com -yidianfenqi.com -yidianhulian.com -yidianling.com -yidianting.xin -yidianzhidao.com -yidianzixun.com -yidianzx.com -yidin.net -yidingsz.com -yidmall.com -yidonghua.com -yidonglin.com -yidoutang.com -yidu.cc -yidui.me -yidukindle.com -yiduks.com -yidumen.com -yidun.com -yiernews.com -yifabao.com -yifake.com -yifanmedia.net -yifatong.com -yifeisoft.com -yifeiyang.net -yifeiyuan.me -yifen.com -yifeng-mover.com -yifeng.com -yifenghudong.com -yifengke.com -yifengx.com -yifengxin.org -yifer.net -yifone.com -yifu.net -yifubao.com -yifucj.com -yifuls.com -yifutangvip.net -yifutu.com -yigao.com -yigaosu.com -yige.org -yigecun.com -yigeking.com -yigeqianbao.com -yigerlife.com -yigobg.com -yigood.net -yigoonet.com -yigouu.com -yiguanli.net -yigujin.wang -yiguo.com -yiguoimg.com -yihafo.com -yihai111.com -yihaikerry.net -yihangen.com -yihao01.com -yihaobc.com -yihaodian.com -yihaodianimg.com -yihaoduozhongduan.com -yihaohuoche.com -yihaojiaju.com -yihaomen.com -yihchina.com -yihe360.com -yihecloud.com -yihedoors.com -yihegold.com -yihong001.com -yihongmenye.com -yihu.com -yihuacomputer.com -yihuimg.com -yihun.com -yii-china.com -yiibai.com -yiibook.com -yiichina.com -yiiheng.com -yiihuu.com -yiii.net -yiiwoo.com -yijia-ai.com -yijia.com -yijiaer.com -yijian119.com -yijiangshan.net -yijianjiaoyu.com -yijianjiexi.com -yijianxiu.com -yijianzj.com -yijiaren888.com -yijie.com -yijiebuyi.com -yijiedai.com -yijiexiaomin.com -yijinghong.com -yijingji.com -yijingying.com -yijintong.net -yijirecovery.com -yijiupeixun.com -yijiupi.com -yikang1977.com -yikanxiaoshuo.com -yikanxs.com -yike.io -yikedou.com -yikehome.com -yiketalks.com -yikeweiqi.com -yikexue.com -yikeyz.com -yikm.net -yikuaide.com -yikuaiqu.com -yikun88.com -yikuns.com -yikuzy.com -yilan.io -yilan.tv -yilanok.com -yilanvaas.com -yile8.com -yilesz.com -yilewan.com -yileweb.com -yileyiqi.com -yileyoo.com -yileyunssp.com -yili.com -yilianmeiti.com -yilianyixue.com -yiliaotui.com -yilibabyclub.com -yilihuo.com -yilijet.com -yilingshop.com -yilinguoji.com -yilinweb.com -yilong.com -yilule.com -yiluzhuanqian.com -yiluzouhao.com -yilvcheng.com -yimaoip.com -yimashijie.com -yimashop.com -yimeima.com -yimenapp.com -yimeng.com -yimenghd.com -yimengmusic.com -yimenonline.com -yimenyun.net -yimi.com -yimianmian.com -yimiaozhongdemeng.com -yimidida.com -yimihaodi.com -yimikf.com -yimin.biz -yimin168.com -yiminchaoshi.com -yimingjuqiming.com -yimingzhi.net -yimininfo.com -yiminjiayuan.com -yiminw.com -yimisoft.com -yimitongxue.com -yimity.com -yimiyisu.com -yimizhibo.tv -yimoe.cc -yimutian.com -yinan9.com -yinar.com -yinbaitu.com -yinbiao5.com -yinbin.ink -yinchengpai.com -yindon.com -yindou.com -yinduabc.com -yindudigital.com -yinduzx.com -yineitong.com -yinfeiy.com -yinfos.com -ying-ji.com -yingbishufa.com -yingcankeji.com -yingchaozhibo.com -yingchengnet.com -yingchuang.com -yingchulawyer.com -yingci86.com -yingdev.com -yingdianzi.com -yinge.tech -yingerchela.com -yingfeiyun.com -yingfeng.me -yinghaicar.com -yinghaozs.com -yinghecloud.com -yinghezhong.com -yinghuahm.com -yinghualiu.com -yinghub.com -yingjia360.com -yingjiesheng.com -yingjiesheng.net -yingjimall.com -yingk.com -yingkelawyer.com -yingle.com -yinglou6.com -yinglunka.com -yingmei.me -yingmile.com -yingming.net -yingmishi.com -yingmoo.com -yingsheng.com -yingshengyl.com -yingshiborui.com -yingshiyou.com -yingsoo.com -yingsun.net -yingtai.com -yingtaoai.com -yingtaosiyue.com -yingtaoyun.com -yingucaifu.com -yingujr.com -yinguobing.com -yingupuhui.com -yingwenming.com -yingworks.com -yingwuyuzd.cc -yingxiahome.com -yingxiang.com -yingxiaogan.com -yingxiaoo.com -yingxintea.com -yingxiong.com -yingxuan.io -yingyinglicai.com -yingyongbei.com -yingyonghao8.com -yingyonghui.com -yingyongmiao.com -yingyu.com -yingyurumen.com -yingyushijie.com -yingyuweb.com -yingyuyingwen.com -yingyuzhushou.com -yingzaocms.com -yingzheng.com -yingzhongshare.com -yingzt.com -yinhai.com -yinhangchaxun.com -yinhangkadata.com -yinhangkahao.com -yinhangkaoshi.net -yinhanglilv.net -yinhangzhaopin.com -yinhe.com -yinheli.com -yinhengli.com -yinher.com -yinheyuedu.com -yinhu.com -yinhuocaifu.com -yini.me -yini.org -yinjiaji.com -yinjietd.com -yinka.co -yinke.com -yinker.com -yinlei.net -yinliuba.com -yinliuliang.com -yinmishu.com -yinongtouzi.com -yinpiao.com -yinsha.com -yinshua.cc -yinshua86.com -yinshuiyu.com -yintai.com -yintechi.com -yintop.com -yinuoedu.net -yinuosy.com -yinvmh.com -yinxi.net -yinxiang.com -yinxianggame.com -yinxiangma.com -yinxiangqingyang.com -yinxiao.com -yinxinbh.com -yinxing.com -yinxunbiao.com -yinyuegf.com -yinyueke.net -yinyuemeitu.com -yinyuetai.com -yinyueyouxi.com -yinzhijie.com -yinzhizhu.com -yinzifang.com -yinzige.com -yinziji.com -yinzipu.com -yinzuo100.com -yinzuojianshen.com -yioho.com -yioulai.com -yiovo.com -yipaipian.com -yipanhaocai.com -yiparts.com -yipemail.com -yipianxing.com -yipihuo.com -yipinhr.com -yipinread.com -yipinsucai.com -yipinxia.net -yipuju.com -yipuping.com -yipz2.com -yipz6.com -yipz7.com -yiqi.com -yiqianbao.com -yiqianlian.com -yiqiao88.com -yiqibazi.com -yiqibing.com -yiqibuduoduo.com -yiqifa.com -yiqifa.org -yiqifengtian.com -yiqifin.com -yiqiguanjia.com -yiqihao.com -yiqijixiang.com -yiqikanjia.com -yiqimaila.com -yiqioffice.com -yiqishai.com -yiqiso.com -yiqisoo.com -yiqisooimg.com -yiqisou.net -yiqiu.org -yiqiv.com -yiqixie.com -yiqixiegushi.com -yiqixxx.com -yiqiyou.com -yiquanhs.com -yiquanseo.com -yiqubook123.com -yiquhai.com -yiqujing.com -yiquxapp.com -yiren001.com -yirendai.com -yirentong.com -yirenzhushou.com -yirimao.com -yirlir.com -yiruantong.com -yiruanwang.com -yiruide.com -yiruikecorp.com -yiruituo.com -yisa.com -yisafe.co -yisanban.com -yisanwu.com -yisell.com -yishalai.com -yisharepdf.site -yishengfanyi.com -yishihui.com -yishion.com -yishion.net -yishixue.com -yishu.com -yishu168.com -yishujie.com -yishuliuxue.com -yishun.net -yishuweipen.com -yishuzhifa.com -yishuzi.com -yishuzi.org -yishuziti.com -yisier.com -yisou.com -yiss.com -yisu.com -yisu6.com -yisusoft.com -yit.com -yitaifang.com -yitang.org -yitel.com -yitesoft.com -yitianshidai.com -yitianxinda.com -yitongjiayou.com -yitongmedia.com -yitopapp.com -yitoutiao163.com -yituocn.com -yitutech.com -yiupin.com -yivian.com -yivicar.com -yivizd.com -yiwaiart.com -yiwan.com -yiwanggo.net -yiwangml.com -yiwanng.com -yiwanzhushou.com -yiweb.com -yiwei.li -yiweilaogumin.com -yiwenyida.com -yiwubuy.com -yiwufair.com -yiwugo.com -yiwugou.com -yiwuku.com -yiwutalk.com -yixao.com -yixi.tv -yixia.com -yixiaoba.com -yixiaoxi.com -yixie8.com -yixiekeji.com -yixieshi.com -yixiin.com -yixin.com -yixin.im -yixincao.com -yixinfinance.com -yixinfund.com -yixinfx.com -yixinhuinong.com -yixintui.com -yixinu.com -yixinxin.com -yixiu08.com -yixiuxueyuan.com -yixuan.net -yixue68.com -yixue99.com -yixueks.com -yixuelunwen.com -yixui.com -yixun.com -yiya520.com -yiyaha.com -yiyakq.com -yiyanfen.com -yiyangidc.com -yiyaojd.com -yiyaojie.com -yiyatuan.com -yiybb.com -yiye.ai -yiyebang.com -yiyebang.net -yiyefei.com -yiyewenxs.com -yiyiarts.com -yiyiarts.net -yiyihd.com -yiyimh.com -yiyingbk.com -yiyingt.com -yiyisoft.com -yiyituzi.com -yiyiwang.net -yiyiwawa.com -yiyongcad.com -yiyou.org -yiyou.tv -yiyoubbs.com -yiyouhbkj.com -yiyouliao.com -yiyoupay.net -yiyouqi.com -yiyu.com -yiyuanqiang.net -yiyuansoft.com -yiyuantian.com -yiyuanyi.org -yiyuetop.com -yiyult.com -yiyum.com -yiyunweb.com -yiyurumen.com -yiyuzw.com -yizaoyiwan.com -yizeijun.com -yizenb.com -yizhanzx.com -yizhchan.com -yizheyikou.com -yizhi-its.com -yizhibi.com -yizhibo.com -yizhidayu.com -yizhifubj.com -yizhikan.com -yizhishenbi.com -yizhixiaogame.com -yizimg.com -yizlife.com -yizu.org -yizuocity.com -yj-bank.com -yj-fun.com -yj.ink -yj3g.com -yj93zp.com -yjbys.com -yjcf360.com -yjcp.com -yjdatasos.com -yjegf.com -yjfs8.com -yjhyjl.com -yjihua.com -yjk.im -yjldp.com -yjlin4.com -yjopen.com -yjpal.com -yjq.cc -yjqiqi.com -yjrcyw.com -yjren3gc.tw -yjro.com -yjrzj.com -yjs-cdn.com -yjs-cdn10.com -yjs111.com -yjscloud.com -yjsjl.org -yjxitong.com -yjxqy.com -yjxsoft.com -yjyghb.com -yjyj95.com -yjz9.com -yjzwkj.com -yk08.com -yk1007.com -yk211.com -ykanxiaoshuo.com -ykccn.com -ykclass.com -ykdgd.com -ykdmsy.com -ykedu.net -ykimg.com -ykinvestment.com -ykjhdc.com -ykntv.com -ykpxxx.com -ykq.ink -ykqhsy.com -ykqnl.com -ykread.com -yks365.com -yksq.net -ykstarshine.com -yksuit.com -ykt.io -yktworld.com -yktz.net -ykyao.com -ykydxh.com -ykzr.com -yl1001.com -yl114.cc -yl177.com -yladm.com -ylallinone.com -ylbgw1.com -yld360.com -yldh.cc -ylfx.com -ylg877.com -ylghsj.com -ylgj.com -ylhaitao.com -ylhg2233.com -ylhh.net -ylhsrsrc.com -ylhzfc.com -ylife9.com -ylilai.com -ylimg.com -ylinux.org -yliyun.com -yljc888.com -yljnet.com -yljr.com -ylkc.net -ylkjgame.com -ylmf.cc -ylmf.com -ylmf.net -ylmf888.com -ylmfeng.com -ylmfwin100.com -ylmfwin100.net -ylmfwin8.com -ylnetworks.com -yloo.org -ylq.com -ylrb.com -ylrj.com -ylstatic.com -yltpcb.com -ylunion.com -yluu.com -ylw66.com -ylwl.cc -ylwpx8.com -ylws.net -ylwyw.com -ylxbxgtg.com -ylxdtww.com -ylxk.net -ylyk.com -ylzms.com -ym-trans.com -ym1998.com -ym68.cc -ym75168.com -ymailcampaign.com -ymall.com -ymanz.com -ymaojob.com -ymapp.com -ymark.cc -ymars.com -ymatou.com -ymatou.hk -ymcall.com -ymcn.org -ymd88.com -ymeme.com -ymexf.com -ymfe.org -ymfhbcj.net -ymfile.com -ymfile01.com -ymgmno.com -ymhudong.com -ymiot.net -ymjm.net -ymlfxp.com -ymlinks.com -ymlykj.com -ymm56.com -ymmfa.com -ymmzb.com -ymoxuan.com -ymoxuan.org -ympcb.com -ymq.com -ymraaa.com -yms7.com -ymsteam.com -ymt.com -ymt360.com -ymtc.com -ymtmt.com -ymvkt.com -ymwl111.com -ymwl234.com -ymxinxi.com -ymxxs.com -ymyun.com -ymyxzz.com -ymzer.com -ymzz.net -yn-tobacco.com -yn.com -yn1234.com -yn12396.com -yn56.com -yn58.com -yn86.com -ynairport.com -ynb2dca.com -ynbes.com -ynbike.net -ynbojie.com -yncuc.net -yncunguan.com -yndaily.com -yndkt.com -yndlrl.com -yneit.com -ynet.com -ynfabu.com -yngd016.com -yngehao.com -ynggzy.com -yngl666.com -yngp.com -ynguangsui.com -yngw518.com -ynhanfu.com -ynhjpf.com -ynhl.net -ynho.com -ynhouse.com -yni84.com -ynianyongheng.com -ynikon.com -ynit580.com -ynkcfc.com -ynkmjj.com -ynlibs.com -ynlyfw.com -ynmec.com -ynpxrz.com -ynrayy.com -ynshangji.com -ynshf.com -ynshijian.com -ynsjg.com -ynteng.com -yntsg.com -ynwin.com -ynxr.com -ynxxb.com -ynyes.com -ynyp.com -ynzczs.com -ynzg.org -ynzhby.com -ynzp.com -ynzy-tobacco.com -yo-yi.net -yo4399.com -yoagoa.com -yobangbang.com -yobbom.com -yobo360.com -yocajr.com -yocan.net -yochoi.com -yocyxc.com -yodak.net -yodakgroup.com -yodao.com -yodbank.com -yodo1.com -yodo1api.com -yoe365.com -yoexs.com -yofc.com -yofcjs.com -yofebearing.com -yofijoy.com -yofish.com -yofond.com -yofond.net -yofus.com -yogacn.net -yogeev.com -yogurtcat.com -yoher.com -yoho.org -yohoblk.com -yohoboys.com -yohobuy.com -yohogirls.com -yoholm.com -yohomars.com -yohoshow.com -yohui.com -yojochina.com -yoju360.com -yoju360.net -yoka.com -yokacdn.com -yokagames.com -yokmob.com -yoko66.com -yokobutu.com -yokong.com -yokowoo.com -yolanda.hk -yolao.com -yolewa.com -yolexi.com -yolinkmob.com -yoloboo.com -yoloho.com -yomiko.club -yomob.com -yomocode.com -yongche.name -yongche.org -yongchengren.com -yonggaofarming.com -yonghe1999.com -yongheng.online -yongheng0852.com -yonghongtech.com -yonghuigj.com -yonghuivip.com -yongkao.com -yonglang.co -yonglongdai.com -yongqianbao.com -yongqiaonews.com -yongqischool.net -yongshei.com -yongsheng-sl.com -yongshikj.com -yongsy.com -yongtu.net -yongxinby.com -yongxintex.com -yongzhentang.com -yonho.com -yonlive.com -yonyou.com -yonyouaud.com -yonyoubao.com -yonyouccs.com -yonyoucloud.com -yonyoufinancial.com -yonyoufintech.com -yonyougov.com -yonyouhit.com -yonyouny.com -yonyouoa.com -yonyouscf.com -yonyouup.com -yoo-hn.com -yoodb.com -yooek.com -yooerjia.com -yoohouse.com -yooknet.com -yooli.com -yoolin.cc -yoooooooooo.com -yoopu.me -yoouxi.com -yooxun.com -yooxuu.com -yooym.com -yooyoo360.com -yoozai.com -yoozhe.com -yoozword.com -yopai.com -yoperp.com -yopoint.cc -yopoint.com -yoptech.com -yopwefun.com -yopwork.com -yoqoo.com -yorentown.com -york33.com -yorunw.cc -yotta800.com -you-mi.net -you1ke.com -you200.com -you5168.com -youba.com -youba123.com -youban.com -youbangyun.com -youbbs.org -youbh.com -youbian.com -youbianku.com -youboy.com -youc.com -youcaizhushou.com -youcao.cc -youcash.com -youcha.net -youchedi.com -youcheyihou.com -youda8.com -youdaihe.com -youdaili.net -youdaiw.com -youdao.com -youdaojr.com -youdaolvshi.com -youdas.com -youdashidai.com -youdemai.com -youdiancms.com -youdnser.com -youdu.im -youease.net -youedata.com -youerwang.com -youeryun.com -youez.com -youfangw.com -youfangzx.com -youfen666.com -youfh.com -youfubao.vip -yougababy.com -youganghangmoguan.com -yougaoji.com -yougequn.com -yougo8.com.tw -yougou.com -yougu.tv -youguo.com -youguoquan.com -youguu.com -youhaodongxi.com -youhaosoft.com -youhaosuda.com -youhro.com -youhu.com -youhua.com -youhuaaa.com -youhuafuzhi.com -youhuangyouxi.xyz -youhuashu.com -youhugmedia.com -youhuiyanxuan.com -youhundao.com -youhuomeishi.com -youhutong.com -youideal.net -youinsh.com -youiv.com -youjiands.net -youjiangzhijia.com -youjiao.com -youjiaus.net -youjiaxiao.com -youjidi.net -youjiuhealth.com -youjk.com -youjoy.tv -youjuke.com -youjutuan.com -youka.la -youkake.com -youke.co -youke.com -youke365.site -youkecn.com -youked.com -youkego.com -youkelai.com -youkexueyuan.com -youkongwan.com -youku.com -youku778.com -youkua.net -youkudou.com -youkudown.com -youkutv.cc -youlanw.com -youle55.com -youleliwu.com -youlianyc.com -youlinyouke.com -youlishipin.com -youliv.com -youloft.com -youlong123.com -youlongciqing.com -youlongteng.com -youlu.com -youlu.net -youlu6.com -youlunlife.com -youluxe.com -youmacuifen.com -youmai.com -youmaolu.com -youmars.com -youme.im -youmeek.com -youmeng.me -youmenr.com -youmew.com -youmi.net -youmiad.com -youmingdifu.com -youmingdot.com -youminonline.com -youmobi.com -youmodou.com -youmooyouyoung.com -youmuyouxs.com -youneng.com -younet.com -younfor.com -young40.com -youngblog.cc -youngfunding.co.uk -youngor.com -youni.im -younihaokanxiaoshuo.com -youo.net -youoh.com -youonbike.com -youpanqidong.com -youpinppt.com -youpinyizu.com -youpinzhekou.com -youqichuyun.com -youqing8.com -youqinggong.com -youqiwu.com -youqizhan.com -youqo.com -youqu.in -youqu.net -youqudao.com -youranshare.com -yourbin.com -yourcollect.net -yourdream.cc -youren5.com -yourtion.com -youruncloud.com -yousc.com -youscm.com -yousee.com -yousenjiaoyu.com -youshang.com -youshanmeishi.com -yousheng8.com -yousheyoujia.com -youshifu.com -youshikoudai.com -youshixiu.com -youshu.cc -youshuba.cc -youshuge.com -yousuu.com -yousuyuan.com -youtaidoors.com -youtaidu.com -youtak.com -youthi.com -youtiandi.com -youtibao.com -youtoart.com -youtoupiao.com -youtu.com -youtuzi.com -youtx.com -youwei.com -youwinedu.com -youwo.com -youwoxing.net -youwoyou.com -youwugame.com -youxi.com -youxi01.com -youxi021.com -youxi186.com -youxi369.com -youxi377.com -youxi500.com -youxi528.com -youxi567.com -youxia.com -youxia.org -youxiacg.com -youxiaju.com -youxiake.com -youxiake.net -youxiamotors.com -youxiang03.com -youxiangke.com -youxiaoad.com -youxiaxiazai.com -youxibao.com -youxibaoku.com -youxicdn.com -youxichaguan.com -youxicheng.net -youxicitang.com -youxicity.com -youxicool.net -youxidaxue.com -youxidr.com -youxiduo.com -youxifan.com -youxigongchang.com -youxigonglue8.com -youxigt.com -youxigu.com -youxiguancha.com -youxih.com -youxihezi.net -youxihun.com -youxij.com -youxike.com -youxila.com -youximao.com -youximeng.com -youxin.com -youxingapp.com -youxiniao.com -youxinpai.com -youxipai.com -youxiping.com -youxiputao.com -youxiqiang.com -youxiqun.com -youxishiguang.com -youxishuo.com -youxitexiao.com -youxituoluo.com -youxiuhui.com -youxiula.com -youxiwangguo.com -youxiweixun.com -youxiwugui.com -youxixf.com -youxixj.com -youxizhan.com -youxizhongguo.com -youxuangu.com -youxueke.com -youyacao.com -youyanchu.com -youyannet.com -youyikeji666.com -youyilm.com -youyiqi.com -youyiqiaogou.com -youyirun.com -youyizhidao.com -youyo88.com -youyou234.com -youyou578.com -youyoudianqi.com -youyouii.com -youyouwin.com -youyuan.com -youyuanapp.com -youyuanw.com -youyudf.com -youyuegame.com -youyueke.com -youyur.com -youyuwei.com -youyuwo.com -youyy.com -youzan.com -youzanyun.com -youzhai.com -youzhan.org -youzhao.com -youzhei.com -youzhi.net -youzhicai.com -youzhidy.com -youzhiwk.com -youzhixueyuan.com -youzhuan.com -youzhuanhua.com -youzi02.com -youzibank.com -youzibuy.com -youzide.com -youzijie.com -youziku.com -youziqk.com -youzu.com -yovisun.com -yovocloud.com -yovole.com -yovyuan.com -yowhatsapp.net -yowooa.com -yowoworld.cc -yoxiha.com -yoximi.com -yoxiwo.com -yoxyok.com -yoya.com -yoyi.tv -yoyiapp.com -yoyo1900.com -yoyo99.com -yoyojacky.com -yoyojie.com -yoyokko.com -yoyokx.com -yoyone.net -yoyotown.com -yoyou.com -yoyou.net -yoyound.com -yoytang.com -yozodcs.com -yozodoc.com -yozodocs.com -yozooffice.com -yozosoft.com -yozrun.com -yozsc.com -yp007.net -yp1151.com -yp900.com -ypank.com -ypgyyq.com -yphuifu.com -ypicw.com -ypjiameng.com -yplady.com -yplcj.com -yplmzx.com -ypmob.com -ypppt.com -ypstech.com -ypxiaoshuo.com -ypzdw.com -ypzhushou.com -yq027.com -yq1751.com -yq51.com -yq6.cc -yqb.com -yqb920.com -yqbank.com -yqbdt.com -yqbimg.net -yqdown.com -yqfml.com -yqgytx.com -yqh.com -yqh5.com -yqhapp.com -yqhhy.cc -yqhlm.com -yqhy.org -yqie.com -yqjsj.com -yqjtgs.com -yqjuejin.com -yqkk.link -yqkqw.com -yqmb001.com -yqmh.com -yqphh.com -yqptzx.com -yqqlm.vip -yqsbz.com -yqscpt.com -yqsns.com -yqtc.com -yqtxzm.com -yqwyx.xyz -yqxhl.com -yqyanhong.com -yqzww.la -yqzww.net -yr-info.com -yrcbank.com -yrksd.com -yrmpay.com -yrom.net -yruan.com -yrucd.com -yrw.cc -yrw.com -yrwy.com -yryz.com -yrzjw.com -ys.cc -ys001.com -ys137.com -ys168.com -ys2345.com -ys666888.com -ys7.com -ys720.com -ys8.com -ysaedesign.com -ysali.com -yscase.com -yscb.net -ysch.cc -ysdome.com -ysdui.com -ysdyz.com -yse360.cc -ysedu.com -yseeker.com -ysepay.com -ysext.com -ysgang.com -ysgou.cc -ysgtg.com -ysgushi.com -yshp.net -yshsports.com -yshyqxx.com -ysicing.me -ysicing.net -ysiis.com -ysiss.com -ysjgames.com -ysjkgl.com -ysjpin.com -yslang.com -yslcw.com -yslow.net -yslqo.com -ysmiji.com -ysmine.com -ysoow.com -ysp68.com -yspenzui.com -ysplay.com -ysppj.com -ysrh.com -ysshipu.com -yssm.org -yssm.tv -yssp88.com -ysstech.com -ysszzs.com -ysszzx.com -yst100.net -yst3.com -ystinbox.com -ysug.com -ysw365.com -ysw68.com -yswebportal.cc -yswh.com -yswhy.com -yswlgame.com -yswpq.com -yswxcn.com -ysx8.com -ysx8.net -ysx8.vip -ysx9999.com -ysxs8.com -ysyhljt.vip -ysyycv.com -yszx99.com -yszyun.com -yszyz.com -yt1998.com -yt5099.com -yt698.com -yta-tech.com -ytaomb.com -ytaotao.net -ytb.io -ytbbs.com -ytcbh.com -ytcj.com -ytcm.net -ytcos.com -ytcutv.com -ytdaily.com -ytdiy8.net -ytdongsheng.com -ytdsdz.com -ytesting.com -ytet.org -ytfuzhen.com -ytghnb.com -ythouse.com -ytjcpj.com -ytkaituo.com -ytlangchao.com -ytlh120.com -ytlvbao.com -ytmer.com -ytmssy.com -ytmxny.com -ytnetgame.com -ytoexpress.com -ytoglobal.com -ytoxl.com -ytpp.com -ytrenyu.com -ytsanchuan.com -ytsjw.net -ytszg.com -ytud.net -ytxedu.com -ytxsc.com -ytxun.com -ytzhihui.com -ytzq.com -yu-fish.com -yu.gs -yu1u.org -yu72.com -yuan-ji.me -yuanbao.com -yuanbaobaoxian.com -yuanbaohui.com -yuanbaojiaozi.com -yuanbin.me -yuancailiao.net -yuancdn.com -yuancefund.com -yuanchengxiezuo.com -yuanchuangchi.com -yuandi.com -yuandiancredit.com -yuandingit.com -yuandongjixie.com -yuandonglirw.com -yuanfeng021.com -yuanfengyazhu.net -yuanfudao.com -yuanfudao.ws -yuangongbao.com -yuanhuikai.com -yuaniis.com -yuanjiaoshequ.com -yuanjie.org -yuanjisong.com -yuanjoy.com -yuanlai.com -yuanlai521.com -yuanlian365.com -yuanlianghong.com -yuanliao.info -yuanlin.com -yuanlin365.com -yuanlin8.com -yuanma.net -yuanmadian.com -yuanmait.com -yuanmas.com -yuanmatao.com -yuanmawu.net -yuanqi46.com -yuanqiao.net -yuanqingsh.com -yuanrenbang.com -yuanrengu.com -yuanrenxue.com -yuanrongbank.com -yuanseedu.com -yuansfer.com -yuanshanbx.com -yuanshen.com -yuanshichang.com -yuanshihui.com -yuansir-web.com -yuansouti.com -yuanss.com -yuantengfei.net -yuantengfei.org -yuantiku.com -yuantoushuo.com -yuantu8.com -yuanu.com -yuanxifu.net -yuanxin.ink -yuanxuxu.com -yuanyangaobei.com -yuanyi.biz -yuanyoutao.com -yuanz.cc -yuanzhexi.com -yuanzidai.com -yuanzige.com -yuanzun.fun -yuanzun5200.com -yuanzun888.com -yuanzunxs.cc -yuaoart.com -yuapt.com -yubangweb.com -yubeiwang.net -yubodata.com -yubohr.com -yuboinfo.com -yubosun.com -yuboyun.com -yucccc.com -yuchai.com -yuchen360.com -yuchengwang.com -yuchenjf.com -yuchenw.com -yuchk.com -yuchu3d.com -yuchuantech.com -yucl.com -yucongding.com -yucoolgame.com -yudaocha.com -yudianda.com -yudiangame.vip -yudouyudou.com -yudwl.com -yue365.com -yue7.com -yuebagu.com -yuebingcheng.com -yuebooemt.com -yuecheng.com -yuedaoec.com -yuedisk.com -yuedu.pro -yuedu88.com -yuedufang.com -yueduji.com -yuedun.wang -yuedunovel.com -yueduread.com -yuedusg.com -yueduwen.com -yuego.net -yuegowu.com -yuehuzhi.com -yueji.com -yuejiayan.com -yuejiewangluo.com -yuejuanbao.com -yuekenet.com -yuekeyun.com -yuelong.info -yueloo.com -yuelu.net -yuelun.com -yuelvxing.com -yueme.tv -yuemei.com -yuemeiw.com -yuenshui.com -yuenwooping-truelegend.com -yuepaijia.com -yuepaow.net -yuepinwang.com -yueqi.com -yueqiweixiu.com -yueqixuexi.com -yueque.com -yuer.com -yuerbao.com -yueru.com -yuese-qubo-jiujiujiu-12-tv.com -yuesehan.com -yuesir.com -yuesuoping.com -yuetu.tech -yuetuvip.net -yueweimusic.com -yuewen.com -yuexianck.com -yuexin.store -yuexing.com -yuexingfurniture.com -yuexinli.com -yuexinyouxi.com -yuexirc.com -yuexunedu.com -yueyaa.com -yueyat.net -yueye.org -yueyear.com -yueyin99.com -yueyouxs.com -yueyq.com -yueyu114.com -yueyuanzhiye.com -yueyuec.com -yueyuecms.com -yueyuedai.com -yueyues.com -yueyuevip.com -yueyueyingshi.com -yueyuez.com -yueyutattoo.com -yueyuxuan.com -yueyuzhushou.com -yueyv.com -yuez.me -yufankeji.net -yufengyangfan.com -yufu365.com -yufuid.com -yugasun.com -yuguo.us -yuguod.com -yuhaijidian.com -yuheii.com -yuheng.tech -yuhongsl.com -yuhuijob.com -yuiapi.com -yuike.com -yujia.com -yujiahui.com -yujunren.com -yujzw.com -yukai.space -yukhj.com -yukicomic.com -yukuai.com -yukunweb.com -yul8.com -yule0752.com -yule116.com -yule263.com -yuledaily.com -yulefm.com -yulehezi.com -yuleie.com -yulekan.com -yuleres.com -yuli.be -yuliechina.com -yulinapp.com -yulingtianxia.com -yulingw.com -yulongjun.com -yuloo.com -yulore.com -yulorepages.com -yulu1.com -yulu5.com -yulucn.com -yuluzhongde.com -yumain.com -yumaoshu.com -yumchina.com -yumengguan.com -yumenikki.info -yumi.cc -yumi.com -yumiaomiao.com -yumimobi.com -yuming.com -yumingguwen.com -yumingwan.com -yumixitong.com -yumstone.com -yun-gu.com -yun-idc.com -yun-img.com -yun-jinrong.com -yun-live.com -yun.pm -yun123.com -yun61.com -yunannet.com -yunaq.com -yunarm.com -yunaw.com -yunba.io -yunban.com -yunbang.net -yunbei.com -yunbeisoft.com -yunbeitech.com -yunbiao.tv -yunbiaowulian.com -yunbiji.com -yunbook.vip -yuncai5.com -yuncaijing.com -yuncdn.bid -yuncdn263.com -yuncdndun.com -yunceng.com -yuncheng.com -yunchong-powder.com -yunchou.com -yuncii.com -yuncity.com -yuncode.net -yunda56.com -yundaex.com -yundaex.us -yundangan.com -yundaohuodong.com -yundasys.com -yundianjia.com -yundianseo.com -yundiantech.com -yundns.vip -yundongfang.com -yundonghao.com -yundongit.com -yundousoft.com -yundui.cc -yunduimedia.com -yundun.com -yunduncdn.com -yunduncdns.com -yunduncname.com -yundunddos.com -yundundns.com -yunduns.com -yundunwaf.com -yundunwaf1.com -yundunwaf2.com -yundunwaf3.com -yundunwaf4.com -yundunwaf5.com -yunduocrm.com -yunduoke.net -yunduoketang.com -yundzh.com -yunews.net -yunfabiao.com -yunface.com -yunfaka.com -yunfalv.com -yunfan.com -yunfancdn.com -yunfandns.com -yunfangtan.com -yunfangyu6.com -yunfannet.com -yunfei89.com -yunfengdie.com -yunforum.net -yunfutech.com -yungangbj.com -yungao-ssp.com -yungongchang.com -yungoumi.com -yungouos.com -yungousj.net -yunguajibao.com -yungujia.com -yunhaicangshu.com -yunhaike.com -yunhaiqiao.com -yunhedata.com -yunheit.com -yunheka.com -yunhesanwan.com -yunhetong.com -yunhosting.com -yunhou.com -yunhuasheji.com -yunhulu.org -yunhuotong.net -yunhuzx.com -yunifang.com -yunify.com -yunio.com -yunip.com -yunipo.com -yunji.com -yunjiale.net -yunjiale.org -yunjian.com -yunjiasu-cdn.net -yunjiasu.com -yunjiasu360.com -yunjiasu666.com -yunjiazheng.com -yunjidns8.com -yunjifarm.com -yunjiglobal.com -yunjiweidian.com -yunjix.com -yunkangdoctor.com -yunkawulian.com -yunke.com -yunkeji.com -yunkezan.com -yunkongpingban.com -yunkucn.com -yunlebao.com -yunlianip.com -yunlianvps.com -yunliaoim.com -yunlie.net -yunlietou.com -yunliketech.com -yunmai.com -yunmayi.com -yunmeipai.com -yunmengnet.com -yunmiao.co -yunmishu365.com -yunmoseo.com -yunmoxing.com -yunnao.com -yunnex.com -yunnut.com -yunos-tv.com -yunos.com -yunpan.com -yunpankk.com -yunpansou.cc -yunpanx.com -yunpian.com -yunpiao.net -yunpigai.com -yunplus.io -yunpp.com -yunqi.org -yunqi2050.com -yunqiandai.com -yunqikecrm.com -yunqingugm.com -yunqishi.net -yunque360.com -yunque365.com -yunrg.com -yunrongu.com -yunrouter.com -yunsd.net -yunser.com -yunserver.com -yunshan.net -yunshangc.com -yunshanmeicai.com -yunshiketang.xyz -yunshipei.com -yunshipei.net -yunshouji123.com -yunshow.com -yunshuxie.com -yunshuyuan.cc -yunsom.com -yunsong.com -yunstu.net -yunsuan.org -yunsuanzi.com -yunsuo.com -yuntaigo.com -yuntask.com -yuntemai.com -yuntianti.com -yuntongbu.com -yuntongcloud.com -yuntongtech.com -yuntongxun.com -yuntouxiang.com -yuntu.io -yunvm.com -yunvs.com -yunwangke.com -yunwei8.com -yunweibang.com -yunweipai.com -yunwenxue.com -yunwins.com -yunwuxian.net -yunxi10.com -yunxiaoge.net -yunxin123.com -yunxindai.com -yunxinshi.com -yunxs.com -yunxuetang.com -yunxzb.com -yunyi-dd.com -yunyijk.com -yunyin.org -yunying166.com -yunyingdashu.com -yunyingketang.com -yunyingmiao.com -yunyingpai.com -yunyingxuetang.com -yunyingzhe.com -yunyingzhinan.com -yunyitiancheng.com -yunyiwangluo.com -yunyouni.com -yunyu123.com -yunyue.cc -yunyuh5.com -yunzhan365.com -yunzhangfang.com -yunzhanggui.net -yunzhanghu.com -yunzhijia.com -yunzhitai.com -yunzhixiyou.com -yunzhizao.net -yunzmall.com -yunzz.net -yupiao.info -yupoo.com -yupsky.com -yupu.com -yuqianshu.com -yuqiaolong.com -yuqinge.com -yuquanhosp.com -yuque.com -yureen.com -yurenty.com -yuriimg.com -yusa.me -yushanapp.com -yushexuetang.com -yushin88.com -yushiquanyang.com -yushu5.com -yushunews.com -yushuwu.com -yusi.com -yusi.tv -yusi123.com -yusidunzc.com -yutangqianxdc.com -yuteng.site -yutian.cc -yutianedu.com -yuttttttttttttttttrrrrrrhhhhhhvbhjgfhj.xyz -yutuwo.com -yuu1.com -yuuboo.net -yuucn.com -yuudnn.com -yuwan-game.com -yuwandian.com -yuwanshe.com -yuweixian.com -yuwell.com -yuwellgroup.com -yuwen360.com -yuwenchaoshi.com -yuwenkj.com -yuwenmi.com -yuwennews.com -yuwenxiandaihua.com -yuxianall.com -yuxiangrc.com -yuxiaolung.com -yuxiaor.com -yuxinba.com -yuxinews.com -yuxingqiu.com -yuxinzhilian.com -yuxip.com -yuxitech.com -yuxungs.com -yuxunzy.com -yuyancd.com -yuyanpingce.com -yuyicai.com -yuyin.tv -yuyoutuan.com -yuyu.com -yuyue111.com -yuyuema.com -yuyuhunter.com -yuyuntech.com -yuzeli.com -yuzhaimedia.com -yuzhainan.com -yuzhaiwuwang.com -yuzhaiwuww.com -yuzhenhai.com -yuzhike.com -yuzhong.net -yuzhongxxw.com -yuzhoutuofu.com -yuzhouwan.com -yuzhua.com -yuzhuagame.com -yuzhuan.com -yuzhulin.com -yuzhuquan.com -yuzi.net -yveqi.com -yvv.in -yw11.com -yw2005.com -ywart.com -ywb.so -ywbank.com -ywcbs.com -ywcec.com -ywdier.com -ywec.net -ywg7.com -ywies-shpd.com -ywindex.com -ywky.org -ywlist.com -ywlm.net -ywnds.com -ywnz.com -ywopt.com -ywpfjm.com -ywsawei.com -ywshouyou.com -ywsoftware.com -ywtlfishing.com -ywtx.cc -ywwx.com -ywxue.com -ywxzz.com -ywy7.com -ywyanxing.com -yx-g.com -yx-life.com -yx-s.com -yx-s.net -yx.com -yx.rs -yx0599.com -yx090.com -yx10011.com -yx129.com -yx129.net -yx231.com -yx5198.com -yx74.com -yx8u.com -yxad.com -yxadv.com -yxbao.com -yxbhhbkj.com -yxbox91.com -yxbs2017.com -yxbuluo.com -yxcax.com -yxcc.net -yxcshui.com -yxcuv.com -yxdaily.com -yxdd.com -yxdgc.com -yxdh.com -yxdm.tv -yxdown.com -yxdr.com -yxdsgs.com -yxduo.com -yxecg.com -yxen.net -yxfanfan.com -yxfw.com -yxfwai.com -yxgxsw.com -yxhenan.com -yxhhdl.com -yxhi.com -yxhqj.com -yxi.cc -yximgs.com -yxin18.com -yxinbao.com -yxit.net -yxixy.com -yxjbkyj.com -yxjedu02.com -yxjia.com -yxke12.com -yxkfw.com -yxkjlcd.com -yxlady.com -yxlady.net -yxlink.com -yxlmdl.net -yxm.com -yxmarkets.com -yxmspx.com -yxn.fun -yxool.com -yxou.com -yxpjw.net -yxpk.net -yxpopo.com -yxptfs.com -yxqiche.com -yxrank.com -yxrb.net -yxrczp.com -yxsc33.com -yxsea.com -yxshgwjy.com -yxsos.com -yxss.com -yxsss.com -yxstudy.net -yxt-tattoo.com -yxt.com -yxt521.com -yxtun.com -yxtvg.com -yxwoo.com -yxxurl.com -yxyfhgc.com -yxyun.com -yxyzjx.com -yxz.me -yxzr.com -yxzxgy.com -yy-xjy.com -yy.com -yy138.com -yy2169.com -yy2hd.com -yy4080.com -yy4138.com -yy4410kanba.com -yy591.com -yy6042.org -yy6080.org -yy845.com -yyangmob.com -yyasp.net -yybox.cc -yycaf.net -yyccia.com -yycec.com -yyclouds.com -yyclub.org -yycoin.com -yycqc.com -yydbzz.com -yydidai.com -yydzh.com -yyearth.com -yyestar.com -yyets.cc -yyetss.com -yyf5.com -yyfangchan.com -yyfax.com -yyfdcw.com -yyfensi.com -yyfq.com -yyfsb.com -yyg.com -yygjuu.club -yygold.com -yygrammar.com -yygzs.com -yyh.co -yyh.la -yyh2.com -yyhao.com -yyhh.com -yyhhaa.com -yyhn365.com -yyhomer.com -yyjzt.com -yyk100.com -yyk2.com -yykaoo.com -yykc.com -yykepu.com -yykj.org -yylending.com -yylm.org -yylmacro.com -yylmz.com -yylya.com -yymanhuawu.com -yymapp.com -yymchina.cc -yymedias.com -yyming2.com -yymoban.com -yyny.me -yynys.com -yypbao.com -yypcb.com -yypm.com -yypt.com -yyq.com -yyrtv.com -yyslate.com -yystatic.com -yyste.com -yysweb.com -yysycn.com -yytcdn.com -yytek.com -yytgjjk.com -yytingli.com -yytt2012.com -yytxt.com -yyuap.com -yyuasa.com -yywlsj.com -yywords.com -yywt.online -yywz123.com -yywzw.com -yyx168.com -yyx407.com -yyxfzy.com -yyxscn.com -yyxt.com -yyxtao.com -yyxwzx.com -yyxx100.com -yyxxgameyw.com -yyy85.com -yyyeee.com -yyzai.com -yyzhuishu.com -yyzsoft.com -yyzu.com -yyzw.com -yyzyytj.com -yyzzsem.com -yz-iot.com -yz-show.com -yz061.com -yz063.com -yz168.cc -yz360.cc -yz3g.net -yz868.com -yzbank.com -yzbo.tv -yzbqzx.net -yzcyjy.com -yzd.ink -yzdiaoyu.com -yzdn.net -yzfang.com -yzfc8.com -yzfjy.com -yzgjgs.com -yzgttm.com -yzgzgd.com -yzhbw.net -yzhli.com -yzhtidc.com -yzintelligence.com -yzinter.com -yzipi.com -yzjbh.com -yzjjw.net -yzjsxy.com -yzkjpcb.com -yzmcms.com -yzmcxx.com -yzmg.com -yzmiao03.com -yzmjw.com -yzmoney.com -yznano.com -yznn.com -yzracing.com -yzrb.com -yzrcfw.com -yzrom.com -yzs.com -yzskj.com -yzspdq.com -yzsqxx.com -yzssc.net -yzt-tools.com -yztcdn.com -yztown.club -yztz.com -yzw.cc -yzwb.com -yzwb.net -yzyp1.com -yzzks.com -yzzs.cc -yzzzn.com -z-bank.com -z-index.cc -z-inn.com -z-zhuji.com -z0.cc -z01.com -z0ukun.com -z1233.com -z12345.com -z2sci.com -z316.com -z3quant.com -z4bbs.com -z4m3.com -z5a.com -z5encrypt.com -z5z4.com -z6616.com -z7mitv10c.vip -z7xz.com -z7ys.com -z8g.ltd -z8q.cc -za-ad.cc -zablog.me -zac1993.com -zackku.com -zackxu.com -zaduonews.com -zadzs.com -zaeke.com -zahtb.com -zahuibaike.com -zahuishi.com -zaibei.net -zaibei.org -zaichengdu.com -zaidu.la -zaidudu.net -zaiduu.com -zaih.com -zaihua.me -zaihuangshi.com -zaihuwai.net -zaijia.com -zaijiawan.com -zailouxia.com -zaiminglvsuo.com -zaisd.com -zaitansuo.com -zaitong.net -zaitongxiang.com -zaitouwang.com -zaiwai.com -zaixian-fanyi.com -zaixianfanyi.com -zaixianjianli.com -zaixiankan.net -zaixs.com -zaixuchang.com -zaiyunli.com -zaizai8.com -zallcn.com -zallfuhui.com -zallgo.com -zallimg.com -zalljinfu.com -zampda.net -zampdmp.com -zampdsp.com -zamplink.net -zamplus.com -zampshare.com -zamptrak.com -zan-shang.com -zan86.com -zanba.com -zanbai.com -zanbot.com -zangaifamily.com -zanghaihuatxt.com -zanmeishi.com -zanpic.com -zantainet.com -zanyiba.com -zaobang.com -zaoche168.com -zaocom.com -zaodao.net -zaodin.com -zaodula.com -zaofabiao.com -zaofacai.com -zaogai.com -zaojiance.com -zaojiance.net -zaojiao.com -zaojiu.com -zaojv.com -zaole.net -zaopang.com -zaoshu.io -zaoshu.so -zaowandushu.com -zaoyang.org -zaoys.com -zaozhuanggo.com -zaozuo.com -zastatic.com -zasv.com -zasv.net -zat.cc -zatan.com -zatan8.cc -zatest.com -zatxt.com -zazhi.com -zazhipu.com -zazsz.com -zb-kc.com -zb1.org -zb2232.com -zb580.tv -zb7.com -zb8.com -zbai.net -zbapk.com -zbbar.net -zbbg.com -zbce.net -zbex.live -zbfilm.com -zbfjsj.com -zbgedu.com -zbgl.net -zbgsw.com -zbhouse.com -zbii.com -zbintel.com -zbird.com -zbj.com -zbjdev.com -zbjdr.com -zbjiangsu.com -zbjimg.com -zbjsaas.com -zbjwork.com -zbkszx.net -zbling.com -zblogcn.com -zbluqian.com -zblzm.xyz -zbmcjx.com -zbnews.net -zbnxs.com -zbopr.net -zbqlm.com -zbqzy.com -zbrushcn.com -zbuhe.com -zbusa.com -zbwbbs.com -zbwdj.com -zbwg.cc -zbxsoft.com -zbxyh.com -zby365.com -zbyongcheng.com -zbytb.com -zbyz.net -zbz.com -zbzaixian.com -zbzdm.com -zbzhandian.com -zbzw.com -zbzw.la -zc-ha.com -zc0.net -zc0317.com -zc181.com -zc532.com -zc600.com -zcaijing.com -zcbjs.com -zcccc.com -zccssz.com -zcdog.com -zcdsp.com -zcfc.com -zcfccs.com -zcff.net -zcfirst.com -zcfy.cc -zcgfgh.com -zcgsfy.com -zcifc.com -zciii.com -zcimg.com -zcitidc.com -zcitwf.com -zciv.com -zcjxedu.com -zcm99.com -zcmlc.com -zcmorefun.com -zcoa365.com -zcobrand.com -zcobrother.com -zcodc.com -zcom.com -zcoming.com -zcooler.com -zcosz.com -zcphp.com -zcppt.com -zcqh.com -zcqss.com -zcread.com -zcry007.com -zcs.cc -zcsbbs.com -zcsblog.com -zcskj.com -zctx.com -zculture.net -zcwxjx.com -zcwz.com -zcxn.com -zcyitang.com -zcyiyao.com -zczj.com -zczy001.com -zd-power.com -zd.hk -zd200572.com -zdao.com -zdapei.com -zdaye.com -zdb.io -zdcj.net -zdcjw18.com -zdcwss.com -zddhr.com -zdding.com -zdexe.com -zdface.com -zdfans.com -zdfans7.com -zdfx.net -zdfzls.com -zdh168.com -zdh1909.com -zdhaitao.com -zdhkyw.com -zdic.net -zdjyj.com -zdkqyy.com -zdlife.com -zdlink.com -zdlpk.net -zdmimg.com -zdmr.net -zdnscloud.biz -zdnscloud.com -zdnscloud.info -zdnscloud.net -zdomo.com -zdoz.net -zdpeanut.com -zdpvt.com -zdrcrx.com -zdrcw.com -zdsee.com -zdsr.net -zdubbs.com -zdwang.com -zdwfy.com -zdworks.com -zdworkscdn.com -zdwx.net -zdx.app -zdxyny.com -zdyrs.com -zdz.la -zdzdm.com -zdzwtesting.com -zdzxtech.com -ze13.com -ze3kr.com -ze5.com -zeakr.com -zealer.com -zeali.net -zealquest.com -zealsafe.net -zebred.com -zechoriah.com -zechunbengye.com -zeelis.com -zego.im -zeguoren.com -zeidei.com -zeisp.com -zeixihuan.com -zejiri.net -zeju.com -zemismart.com -zemuo.com -zendstudio.net -zengdefei.com -zengjunpeng.com -zengrong.net -zenha.net -zenixauto.com -zenoven.com -zensakura.com -zentao.net -zentaoms.com -zentaopm.com -zep8.com -zeperd.com -zeq366.net -zeroac.com -zerobreeze.com -zerobyw.com -zerobywps2.com -zerobywswit.com -zerocollege.com -zerodream.net -zerogfans.com -zerokeeper.com -zeroling.com -zeruns.tech -zerustech.com -zesmob.com -zeststore.com -zetast.com -zeus.dl.playstation.net -zeuux.com -zeuux.org -zexiaoqiao.com -zeyi.cc -zeyi5.com -zeyouquan.com -zeze.com -zf-8.com -zf0303.com -zf3d.com -zf503.com -zfancy.net -zfboke.com -zfcfy.com -zfcm.net -zfdmkj.com -zff888.com -zfhz.org -zfimg.com -zfl9.com -zfowed.com -zfrmt.com -zfrontier.com -zfsc.com -zfsoft.com -zft.com -zfvnet.com -zfw.net -zfwimg.com -zfyml.com -zfyyhb.com -zg-import.com -zg-imsoft.com -zg114w.com -zg163.net -zg3721.com -zg388.com -zg45.net -zga81.com -zgaxr.com -zgazxxw.com -zgbbtjt.com -zgbenrun.com -zgbigart.com -zgbmcl.com -zgboke.com -zgbywl.com -zgbzad.com -zgc-bigdata.org -zgc-dsa.org -zgcae.net -zgcahpw.com -zgcbank.com -zgcbb.com -zgcdcs.com -zgcdiy.com -zgchawang.com -zgchawang.net -zgchrx.com -zgcicc.com -zgcidsf.org -zgcindex.org -zgcjm.org -zgcjpx.com -zgclmc.com -zgcmlm.com -zgcsa.org -zgcshzz.org -zgcswhcbw.com -zgcups.com -zgddmx.com -zgdlbgg.com -zgdsw.com -zgdwzp.com -zgdxhbkf.com -zgdykeji.com -zgdzqw.com -zgeci.com -zgepsa.com -zgetzx.com -zgflzxzx.org -zgfwgj.com -zgfxnews.com -zgfznews.com -zgg.com -zgg55.com -zggbdsw.net -zggcks.com -zggdjj.com -zgghw.org -zggjgy.com -zgglkx.com -zggonglue.com -zggqzp.com -zggx.net -zggys.com -zghhzx.net -zghotnews.com -zghouse.net -zghtcd.com -zghtedu.com -zghtqk.com -zgjcks.com -zgjdxx.com -zgjf123.com -zgjf168.com -zgjhjy.com -zgjiemeng.com -zgjinsu.com -zgjjzyjy.org -zgjm.net -zgjm.org -zgjntq.com -zgjrzj.net -zgjsks.com -zgjtb.com -zgjxcad.com -zgjxf.com -zgjyjj.com -zgjzlw.com -zgjzxh.org -zgkao.com -zgkashi.com -zgkawah.com -zgkfzz.com -zgkjb.com -zgkjcx.com -zgkjw.org -zgkjxww.com -zgkjzx.com -zgkqw.com -zglb.org -zglbbs.com -zgldgbsdshyjy.com -zglipin.com -zgljl2012.com -zglqcjw.com -zglscom.com -zglww.net -zglxw.com -zglzb.com -zgmcxw.com -zgmdbw.com -zgmsbw.com -zgmsbweb.com -zgmxl.com -zgmzyx.com -zgncjr.com -zgnfys.com -zgnhzx.com -zgnt.net -zgong.com -zgpingshu.com -zgpj.net -zgpts.com -zgpyhst.com -zgpzz.com -zgqkk.com -zgqpgy.com -zgqw.com -zgqyhzfy.com -zgqywhcbw.com -zgqyzxw.com -zgrdnews.com -zgrlm.com -zgruisai.com -zgsc123.com -zgsclp.com -zgsd.net -zgsee.net -zgserver.com -zgsg114.com -zgshifu.com -zgshige.com -zgshjj.com -zgshoes.com -zgshq.com -zgshxfw.com -zgsj.com -zgslb.net -zgsmmhw.com -zgsof.com -zgsssss.com -zgsta.com -zgswcn.com -zgsydw.com -zgsynews.com -zgtcqw.com -zgtianqi.com -zgtjq.com -zgtlgs.com -zgtsm.com -zgtuku.com -zgtxw.com -zgtygg.com -zgui.com -zguonew.com -zgw.com -zgweimeng.com -zgwenku.com -zgwgfw.com -zgwhfe.com -zgwhw.com -zgwlmusic.com -zgwqgks.com -zgwrx.com -zgwt.co -zgwxbbs.com -zgwygl.org -zgxcfx.com -zgxga.com -zgxk.org -zgxqwqh.com -zgxrjy.com -zgxue.com -zgyaye.com -zgycgc.com -zgycsc.com -zgyeda.com -zgyey.com -zgygsy.com -zgyhys.org -zgyinpin.com -zgyizw.com -zgylqy.com -zgyongxin.com -zgys.net -zgyssyxh.com -zgyuwen.com -zgyxlzzs.com -zgyxsw.org -zgyygl.com -zgzcw.com -zgzcwy.com -zgzfwm.com -zgzhxcpx.com -zgzjzzs.com -zgzkw.com -zgznh.com -zgzpbz.com -zgzqzdcs.com -zgzsrc.com -zgzwl.com -zgzxwsg.com -zgzy.net -zgzyqccj.com -zgzyqcgw.com -zgzzs.com -zh-itone.com -zh.cc -zh.my -zh30.com -zh51home.com -zhai14.com -zhai6.com -zhaiba.com -zhaichaomi.com -zhaichong.com -zhaidehui.com -zhaidou.com -zhaifu.cc -zhaifu.tv -zhaihai.com -zhaiiker.com -zhaikexueyuan.com -zhainanba.net -zhainanbaw.com -zhainanfulishe.com -zhainanhuayuan.com -zhainanpindao.cc -zhaiqianfeng.com -zhairport.com -zhaixiaoniu.com -zhaji.org -zhan.com -zhandaren.com -zhandi.cc -zhandodo.com -zhang.ge -zhang365.com -zhang6.net -zhangbo.org -zhangchi.art -zhangdanyang.com -zhangdongshengtech.com -zhangdongxuan.com -zhangdu5.net -zhangdu520.com -zhange8.com -zhangfen.com -zhangfensir.com -zhanggang.net -zhanggao.club -zhanggaoyuan.com -zhangguibang.com -zhanghaijun.com -zhanghongliang.com -zhanghuanglong.com -zhangjh.me -zhangjieba.com -zhangjiexiong.com -zhangjinkun.com -zhangjunbk.com -zhangkai.red -zhangle.com -zhangli2015.com -zhangliziyun.com -zhanglun.xyz -zhangluya.com -zhanglvtong.com -zhangmen.com -zhangmen.org -zhangmenkid.com -zhangnan.xyz -zhangnq.com -zhangqiaokeyan.com -zhangqiongjie.com -zhangqiu.cc -zhangranfilm.com -zhangrunnan.com -zhangsenhao.com -zhangshengrong.com -zhangtielei.com -zhangtu.com -zhangu365.com -zhangweijie.net -zhangwenli.com -zhangxiaoyang.me -zhangxinhuichuan.com -zhangxinhulian.com -zhangxinxu.com -zhangxuefei.site -zhangyangjun.com -zhangyin.org -zhangyinglawyer.com -zhangyongjun.com -zhangyoubao.com -zhangyoushijie.com -zhangyu.com -zhangyue.com -zhangyue.net -zhangyue01.com -zhangyue02.com -zhangyue03.com -zhangyugg.com -zhangyulive.com -zhangyunling.com -zhangyuqing.me -zhangzhao.me -zhangzhengfan.com -zhangzhongpei.com -zhangzhongwang.com -zhangzhongyun.com -zhangzidao.com -zhangzifan.com -zhangziran.com -zhangzishi.net -zhanh.com -zhanhi.com -zhanjindong.com -zhankoo.com -zhanlingol.com -zhanmazj.com -zhanqi.net -zhanqi.tv -zhanqitv.com -zhanqu.im -zhanshaoyi.com -zhanshiren.com -zhanst.com -zhansu.com -zhantai.com -zhantuo.com -zhanwushuang.com -zhanxb.com -zhanyicg.com -zhanyouyun.com -zhanzhang.net -zhanzhangwo.com -zhao163.com -zhaoapple.com -zhaobeijing.com -zhaobiao.info -zhaobuxiu.com -zhaocaibb.com -zhaocaihr.com -zhaocait.com -zhaocaiyan.com -zhaochafa.com -zhaochangjixie.com -zhaocheyun.com -zhaoda.net -zhaodanji.com -zhaodatu.com -zhaodll.com -zhaofangbang.net -zhaofanguan.com -zhaofile.com -zhaofinger.com -zhaogang.com -zhaogangimg.com -zhaogepu.com -zhaoguoshu.net -zhaohaipeng.com -zhaoj.in -zhaojianpu.com -zhaojiao.net -zhaojiaoan.com -zhaojiaxiao.com -zhaokaifeng.com -zhaokao.net -zhaokeli.com -zhaokuaizhao.com -zhaoliangji.com -zhaoliming.net -zhaolongedu.com -zhaomengtu.com -zhaoming.biz -zhaomxd.com -zhaoneibuquan.com -zhaoniupai.com -zhaoonline.com -zhaopianzhibo.com -zhaopin.com -zhaopin33.com -zhaopingou.com -zhaopins.com -zhaoqianwang.com -zhaoqt.net -zhaoshang.net -zhaoshang01.com -zhaoshang100.com -zhaoshang800.com -zhaoshangbang.com -zhaoshangbao.com -zhaoshangdai.com -zhaoshayou.com -zhaosheng.com -zhaosheng365.com -zhaosifang.com -zhaosw.com -zhaotonghang.com -zhaouc.com -zhaouc.net -zhaowenxishi.com -zhaoxi.net -zhaoxi.org -zhaoxiaoshuo.com -zhaoxin.com -zhaoxitech.com -zhaoxiuyuan.com -zhaoyanblog.com -zhaoyangmao.com -zhaoyangsem.com -zhaoyangxueyuan.com -zhaoyaojd.com -zhaoyb.net -zhaoyingtian.com -zhaoyinqian.com -zhaoyuan365.com -zhaoyun.com -zhaozhaoqu.com -zhaozhishi.com -zhaozongjie.com -zhatoufa.com -zhazhi.com -zhbit.com -zhblawyer.com -zhcf001.com -zhcw.com -zhdba.com -zhdclink.com -zhdgps.com -zhdzsw.com -zhe.com -zhe28.com -zhe4000.com -zhe800.com -zhebei.com -zhedakaoyan.com -zhefengle.com -zhehen.com -zhejiangmuseum.com -zhejiangqinghe.com -zhejiangsanjiang.com -zhejie.com -zhekouo.com -zhelaoda.com -zheli.com -zheliyangsheng.com -zhen-ao.com -zhen.com -zhenai.com -zhenaoyaoye.com -zhenbi.com -zhenbizi.com -zhenchenglong.com -zhending-chicken.com -zhenfang.me -zhenfund.com -zhengcaimall.com -zhengcaishangcheng.com -zhengdabm.com -zhengdaotang.com -zhengdichaiqian.com -zhengfenduojin.com -zhengguzhishen.com -zhenghangyq.net -zhengjia.com -zhengjiantong.com -zhengjicn.com -zhengjie.com -zhengmeng.net -zhengpinle.com -zhengqingsong.com -zhengruioi.com -zhengshihf.com -zhengshuku.com -zhengtoon.com -zhenguo.com -zhengwutong.com -zhengxiaoling.com -zhengxinbao.com -zhengyaing.win -zhengyee.com -zhengyexing.com -zhengyifeng.com -zhengyinyong.com -zhengyounet.com -zhengzai.tv -zhengzhantianxia.net -zhengzhoubus.com -zhengzhoulvxing.com -zhengzi.me -zhengzihui.com -zhenhaojituan.com -zhenhaotao.com -zhenhaotv.com -zhenhong56.com -zhenhuajn.xin -zhenhuan888.com -zhenimg.com -zhenjiahuo.com -zhenjiang-marathon.com -zhenleishan.com -zhenlinxin.com -zhenlishen.com -zhenniu24.com -zhenpin.com -zhenren.com -zhenrenmm.com -zhenrongbao.com -zhensoushu.com -zhentan.la -zhenwu.com -zhenxian.fm -zhenxunkeji.com -zhenyouhuo.com -zhenyouliao.com -zhenyouweb.com -zhenyukj.com -zhenzanzixun.com -zhepic.com -zhesui.com -zhetao.com -zhetian.org -zhexi.tech -zhexinit.com -zheyangai.com -zheye.cc -zheye.com -zheyibu.com -zheyouquan.net -zheyouxinxi.com -zhezheai.com -zhezhekan.com -zhezhier.com -zhfc.com -zhfile.com -zhfund.com -zhgc.com -zhgjm.com -zhgl.com -zhgnj.com -zhgu.net -zhguoguo.com -zhh.me -zhhainiao.com -zhhs-china.com -zhhuahui.com -zhhy-oa.com -zhi-bo.net -zhi-ming.com -zhi-niao.com -zhi.hu -zhi12.com -zhiaikm.com -zhiaimusic.com -zhiaixin.com -zhiannet.com -zhiaxue.com -zhib.net -zhibiao8.com -zhibimo.com -zhiblue.com -zhibo.at -zhibo.co -zhibo.me -zhibo.tv -zhibo11.com -zhibo8.cc -zhibo8.com -zhiboba.com -zhiboba.org -zhiboqiao.com -zhiboyun.net -zhibs.net -zhibugongzuo.com -zhicaiwang.com -zhicall.com -zhicg.com -zhichanli.com -zhicheng.com -zhichengyidong.com -zhichenn.com -zhichikeji.com -zhichiwangluo.com -zhichiweiye.com -zhicho.com -zhichu100.com -zhicms.cc -zhidao91.com -zhidaoanli.com -zhidaoketang.com -zhideedu.com -zhidesoft.com -zhideyimai.com -zhidian3g.com -zhidieyun.com -zhidiy.com -zhidj.com -zhidmai.com -zhiduopc.com -zhidx.com -zhidzhushou.mobi -zhifa.cc -zhifang.com -zhifashengfa.com -zhifeishengwu.com -zhifoukeji.com -zhiftype.com -zhifufu.com -zhifujie.com -zhifure.com -zhifutui.com -zhifuzi.com -zhigao.org -zhigou.com -zhiguagua.com -zhiguang.me -zhigudata.com -zhiguo100.com -zhihe.mobi -zhihemobi.com -zhihengwangchen.com -zhihjf.com -zhihone.com -zhihu.co -zhihu.com -zhihu66.com -zhihudsp.com -zhihuiep.com -zhihuihuiwu.com -zhihuiji.com -zhihuinanzhan.com -zhihuirenshe.com -zhihuishitang.net -zhihuishu.com -zhihuiya.com -zhihuizhangyu.com -zhihuizp.com -zhihuoseo.com -zhiji.com -zhijia.com -zhijiang.biz -zhijiangames.com -zhijianhutong.com -zhijiaoyi.com -zhijiapro.com -zhijidoc.com -zhijieketang.com -zhijin.com -zhijinwang.com -zhijl.com -zhijuke.com -zhikao100.com -zhikaotong.net -zhikeonline.com -zhikubao.net -zhilandaren.com -zhilehuo.com -zhileng.com -zhili-hr.com -zhilian.com -zhilianfm.com -zhiliangren.com -zhilianhttp.com -zhilianka.com -zhiliaoke.com -zhilingshidai.com -zhilizazhi.com -zhilong.me -zhilongtech.com -zhiluo.net -zhimacangku.com -zhimantian.com -zhimaruanjian.com -zhimawenda.com -zhimax.com -zhimengzhe.com -zhimg.com -zhimi.com -zhimoe.com -zhineng6.com -zhinengdayi.com -zhinengshe.com -zhinengxia.com -zhinet.com -zhinews.com -zhiniaotec.com -zhinikefu.com -zhinin.com -zhiniu8.com -zhipan.net -zhipeix.com -zhipiaoduixian8.com -zhipin.com -zhipingke.com -zhiqiang.org -zhiqiapp.com -zhiqu.org -zhiquansheng.com -zhiquanxia.com -zhiquyuan.com -zhiread.com -zhiren.com -zhiren.ren -zhirenhr.com -zhiribao.com -zhiru.com -zhirui-inv.com -zhiruyi.com -zhisanzhao.com -zhisheji.com -zhishi.life -zhishichong.com -zhishifenzi.com -zhishihao.com -zhishikoo.com -zhishilin.com -zhishiniu.com -zhishisoft.com -zhishiwu.com -zhishizhan.net -zhishuedu.com -zhishutang.com -zhisiyun.com -zhitongcaijing.com -zhitoudsp.com -zhitouxing.com -zhituad.com -zhitui.com -zhiwei88.com -zhiweihl.com -zhiweilaijiaoyu.com -zhiwo.com -zhiwu55.com -zhiwuchina.com -zhiwuwang.com -zhixiaodashi.com -zhixiaohuoke.com -zhixiaoren.com -zhixiaorenurl.com -zhixingapp.com -zhixingbus.com -zhixuan.com -zhixue.com -zhixue.org -zhixueyun.com -zhiyanblog.com -zhiyangji08.com -zhiye.com -zhiyeapp.com -zhiyequan.com -zhiyi.com -zhiyicx.com -zhiyinghui.com -zhiyingtuan.com -zhiyinhao.com -zhiyinmedia.com -zhiyoo.com -zhiyoubao.com -zhiyoujie.com -zhiyoulxs.com -zhiyuanfuwu.com -zhiyuanhongda.com -zhiyuanit.com -zhiyuanyun.com -zhiyujit.com -zhiyun168.com -zhiyz.com -zhizaoye.net -zhizaoyun.com -zhizhang.com -zhizhebuyan.com -zhizhen.com -zhizhi88.com -zhizhibaike.com -zhizhihu.com -zhizhizhi.com -zhizhonghl.com -zhizhoukeji.com -zhizhucms.com -zhizhuwu.com -zhizhuyx.com -zhizihuan.com -zhizihuan.net -zhiziyun.com -zhizunbo.com -zhizuncn.com -zhizunlian.com -zhizunnews.com -zhizuobiao.com -zhizuobiaojiaoyu.com -zhizuoh5.com -zhizuotu.com -zhj9.com -zhjiameng.com -zhjj.org -zhjncb.com -zhjs.cc -zhjtong.com -zhjypco.com -zhk.me -zhku.com -zhl.com -zhld.com -zhlhh.com -zhliqi.com -zhlseo.com -zhlzw.com -zhmatou.com -zhmeiwen.com -zhmf.com -zhmold.com -zhmzqi.com -zhnjw.com -zhobang.com -zhong-lv.com -zhong.com -zhong100.com -zhongan.com -zhongan.io -zhongbaounion.com -zhongbowenwu.com -zhongchaoyinshua.com -zhongchebaolian.com -zhongchoujia.com -zhongchouke.com -zhongchoutx.com -zhongchouyan.com -zhongchuang365.com -zhongcj.com -zhongda021.com -zhongdaonet.com -zhongdeng.com -zhongdengwang.com -zhongdi168.com -zhongdoulicai.com -zhongfenxian.com -zhongfenxiang.com -zhongfu.net -zhongguancun.com -zhongguobaiyin.com -zhongguofeng.com -zhongguohao123.com -zhongguohuo.com -zhongguojie.org -zhongguojie.wang -zhongguojixiewang.com -zhongguomap.com -zhongguopeixun.net -zhongguose.com -zhongguoseo.net -zhongguosou.com -zhongguotiyucaipiao.com -zhongguowangshi.com -zhongguoxianhua.com -zhongguoyimin.net -zhongguoym.com -zhongh.com -zhonghaitech.com -zhonghhd.com -zhonghongwang.com -zhonghr.com -zhonghua-pe.com -zhonghuacar.com -zhonghuacpa.com -zhonghuadiancang.com -zhonghuaent.com -zhonghualunwen.com -zhonghuameiwang.com -zhonghuanus.com -zhonghuaqiming.com -zhonghuasuan.com -zhonghuawuxia.com -zhongjiangapp.com -zhongjie.com -zhongjijidian.com -zhongjinnews.com -zhongjintongsheng.com -zhongjitou.com -zhongkao.com -zhongkaohelp.com -zhongkerd.com -zhongkongban51.com -zhongkongbancn.com -zhongleny.com -zhonglewz.com -zhonglian.com -zhonglianfactoring.com -zhongliucls.com -zhongliuyiyuan.com -zhonglun.com -zhongman.com -zhongmeiart.com -zhongmian.com -zhongmingmao.me -zhongniu.com -zhongniunongmu.com -zhongpaiwang.com -zhongqixin360.com -zhongrenbang.cc -zhongrongjz.com -zhongruigang.com -zhongruihuacheng.com -zhongruitech.com -zhongshang114.com -zhongshanpark.com -zhongshanyinyuetang.org -zhongshengdai.com -zhongshucan.com -zhongso.com -zhongsou.com -zhongsou.net -zhongtaitrust.com -zhongtieyintong.com -zhongtoufa.net -zhongtuobang.com -zhongwcs.com -zhongwei-info.com -zhongweijy.com -zhongwenhexinqikan.com -zhongwucan.com -zhongxiangdichan.net -zhongxing123.com -zhongxinwanka.com -zhongxunrunda.com -zhongxuntv.com -zhongyao1.com -zhongyaobaike.net -zhongye.net -zhongyegongkao.com -zhongyemba.com -zhongyidiantong.com -zhongyiiot.com -zhongyiju360.com -zhongyishangwu.com -zhongyoo.com -zhongyougc.com -zhongyunjy.com -zhongzhao.com -zhongzhengzs.com -zhongzhide.com -zhongzhifaqian.com -zhongzhilin.com -zhongzhixin.com -zhongzhoutm.com -zhongzq.com -zhonyas.com -zhonzhu.com -zhopera.com -zhou1go.com -zhouao.com -zhoubochina.com -zhouchun.net -zhoudaosh.com -zhougong.com -zhouhoulin.com -zhoujiahong.com -zhoujianhui.com -zhoujiping.com -zhoulingjie.com -zhour.net -zhoushangren.com -zhouxiao.me -zhouxingchi.info -zhouxuanyu.com -zhouyi.biz -zhouyi.cc -zhouyi.org -zhouyi114.com -zhouyigw.com -zhouyiju.com -zhouyuanchao.com -zhouzhipeng.com -zhouzhuang.net -zhpanzi.com -zhpm.org -zhqyue.com -zhrczp.com -zhrtc.com -zhs6.com -zhsan.com -zhsho.com -zhshw.com -zhskw.com -zhsyb.cc -zhtelecom.com -zhtmid.com -zhtzvip.com -zhu.cm -zhu.vn -zhu360.com -zhu7jie.com -zhuainiu.com -zhuaishuan.com -zhuaji.org -zhuan16.com -zhuan8ke.com -zhuanfa.net -zhuanfou.com -zhuang520.com -zhuang666.com -zhuang99.com -zhuangji.net -zhuangjiba.com -zhuangjiyuan.com -zhuangku.com -zhuangle.cc -zhuangpeitu.com -zhuangpin.com -zhuangxiaomi.com -zhuangxiu.com -zhuangxiu22.com -zhuangxiu567.com -zhuangxiu6.com -zhuangxiubao.com -zhuangxiuzhai.com -zhuangyi.com -zhuangzhuang.cf -zhuangzhuang.net -zhuanhuanqi.com -zhuaniao.com -zhuanile.com -zhuankeba.org -zhuankela.com -zhuanlichaxun.net -zhuanmenmian.com -zhuannet.com -zhuanpinyin.com -zhuanqianer.com -zhuansong.pro -zhuansoo.com -zhuanstatic.com -zhuantilan.com -zhuanyejun.com -zhuanyepeixun.com -zhuanyes.com -zhuanyezhidao.com -zhuanyun.cc -zhuanyun123.com -zhuanyuntang.com -zhuanzfx.com -zhuanzhi.ai -zhuanzhi.net -zhuanzhuan.com -zhuanzhuantui.com -zhuanzhuvpn.com -zhuanzhuyuwin7.com -zhuashouru.com -zhuatang.com -zhuatongji.com -zhuax.com -zhuaxia.com -zhuaying.com -zhuayou.com -zhuayoukong.com -zhuazi.com -zhubaijia.com -zhubajie.com -zhubajie.la -zhubangbang.com -zhubao.com -zhubao668.com -zhubaodai.com -zhubaojizhen.com -zhubaoq.com -zhubenjie.com -zhubian.com -zhubiaoju.com -zhubijiao.com -zhubo123.com -zhubogu.com -zhuboqiang.com -zhuceshenzhengongsi.com -zhucexianggang.com -zhuceyou.com -zhucezn.com -zhuchao.cc -zhudai.com -zhufaner.com -zhufengpeixun.com -zhufenqi.com -zhufushuo.com -zhuge.com -zhugeapi.com -zhugeapi.net -zhugefang.com -zhugeio.com -zhugeliangcheng.com -zhuhaia.com -zhuhaily.com -zhuhaimy.com -zhuhd.win -zhuhongliang.com -zhuici.com -zhuici.net -zhuiguang.com -zhuihuodong.com -zhuimengyizu.com -zhuimengzhu.com -zhuinvsheng.com -zhuiqu.com -zhuishu.tw -zhuishu5.com -zhuishubang.com -zhuishushenqi.com -zhuishuwang.com -zhuiwan.org -zhuixinfan.com -zhuixingwang.com -zhuixue.net -zhuiyi.ai -zhuizhuiimg.com -zhuizhuiyoyo.com -zhuji.com -zhuji.la -zhuji.net -zhujia360.com -zhujiaimg.com -zhujiangbeer.com -zhujiange.com -zhujiangrc.com -zhujiangroad.com -zhujib.com -zhujibank.com -zhujibiji.com -zhujiceping.com -zhujiwiki.com -zhujiwu.com -zhuke.com -zhulang.com -zhulanli.com -zhuli.me -zhuliudai.com -zhuliuwu.com -zhulixiaolie.com -zhulogic.com -zhulong.com -zhulou.net -zhulu86.com -zhumengwl.com -zhumu.me -zhumuchina.com -zhuna.net -zhunc.vip -zhundao.net -zhuniu.com -zhunniao.com -zhuo.com -zhuobufan.com -zhuodown.com -zhuofan.net -zhuofansoft.com -zhuoguang.net -zhuohuamg.com -zhuojie.cc -zhuokearts.com -zhuoku.com -zhuoku.org -zhuolin.wang -zhuomian365.com -zhuomilicai.com -zhuomogroup.com -zhuoqinglobal.com -zhuoquapp.com -zhuoqun.info -zhuoshigroup.com -zhuoshixiong.com -zhuotingwl.com -zhuotujiaoyu.com -zhuoxue.cc -zhuoyi.com -zhuoyicp.com -zhuoyigame.com -zhuoyigame.site -zhuoyixuan.com -zhuoyou.com -zhuoyouba.net -zhuoyue.wang -zhuoyuebbs.com -zhuoyuechenxing.com -zhuozhengsoft.com -zhuozhoufangchan.com -zhupadns.com -zhuqinit.com -zhurht.com -zhushuiwen.com -zhust.com -zhuti.com -zhuticlub.com -zhutihome.net -zhutix.com -zhutix.net -zhutixiazai.com -zhutizhijia.net -zhutools.com -zhutou.com -zhutousan.net -zhuwang.cc -zhuwang360.com -zhuwona.com -zhuxianfei.com -zhuxiaobang.com -zhuxuejy.com -zhuye.kim -zhuyee.com -zhuyeshouhushen.com -zhuyitai.com -zhuyixie.com -zhuyouw.com -zhuyst.cc -zhuyuce.com -zhuyunfeng.com -zhuzhai.com -zhuzher.com -zhuzhichao.com -zhuzhouwang.com -zhuzi.me -zhw-island.com -zhw2101024.com -zhwangart.com -zhwdw.com -zhwen.org -zhwenku.com -zhwenxue.com -zhwlgzs.com -zhwrshg.com -zhxfei.com -zhxinuser.com -zhxuser.com -zhxww.net -zhxy1z.com -zhy333.com -zhybb.com -zhyccw.com -zhycn.com -zhyd.me -zhyfjj.com -zhyi828.com -zhyingxiao.com -zhyouliang.com -zhysj.net -zhyx707.com -zhyxcc.com -zhyxtg.com -zhyymall.com -zhyyz.com -zhzays.com -zhzjw.net -zhzyw.com -zhzyw.org -zhzzx.com -zi-han.net -zi.com -ziben365.com -ziboshishen.com -zibosky.com -zicaitou.com -zichabaogao.com -zichanzhihuan.com -zichenit.com -zidan.chat -zidanduanxin.com -zidanduanxin.net -zidian8.com -zidiantong.com -zidootv.com -zifandiaosu.com -zifeiwuya.com -zige365.com -zigeer.com -zigeerplus.com -ziguhonglan.com -zihai029.com -zihai0351.com -zihai0411.com -zihai0531.com -zihai0532.com -zihai0535.com -zihai0591.com -zihai0595.com -zihai0755.com -zihai24.com -zihexin.net -zihu.com -zihua01.com -ziiai.com -ziipoo.com -ziisp.com -ziji.cc -zijiayouly.com -zijie.com -zijiecdn.com -zijieimg.com -zijinfx.com -zijing.org -zijinji.com -zijinjubao.net -zijinsuo.com -zijiren.net -zijishanghui.com -zijizhang.com -zikao-zikao.com -zikao.gd -zikao365.com -zikao5.com -zikaocqi.com -zikaoshu.net -zikaoshu.vip -zikaosw.com -zike.com -zikeys.com -zikoo.com -ziku123.com -zikui-design.com -zikuinfo.com -zilanwl.com -zilhua.com -zilian8.com -ziliaoge.com -ziliaoh.com -zilongame.com -zilongshanren.com -ziluolanh.com -zimacaihang.com -zimilan.com -zimoapps.com -zimrilink.com -zimu.me -zimukeji.com -zimuku.net -zimushe.com -zimutiantang.com -zimuzimu.com -zimuzu.io -zimuzu.tv -zine.la -zinewow.com -zingke.com -zingqi.com -ziniao.com -ziningmeng.com -ziniusoft.com -zinmin01.wang -zintao.com -zintow.com -zip118.com -zip55.com -zipadc.com -zipjpg.com -ziq.com -ziqiangxuetang.com -ziqingge.com -ziranniang.com -ziranyixue.com -ziroom.com -ziroomapartment.com -ziroomstay.com -zisea.com -zisen.com -ziseyiliao.com -zisha.com -zishabo.com -zishahuyu.com -zishapot.com -zishu010.com -zishuo.com -zishuogif.com -zishuovideo.com -zisia.org -zisuo.com -ziti.so -ziti163.com -zitiao.org -zitiaonc.com -zitiba.com -zitichina.com -ziticq.com -zitiguanjia.com -zitijia.com -zitixiazai.org -zituo.net -zivers.com -zivoo.com -ziwanyouxi.com -ziweihuan.com -ziwojianding.net -ziwork.com -ziwoyou.net -ziwufang.com -zixia.com -zixiaomao.com -zixigua.com -zixijiaoshi.com -zixike.cc -zixuedao.com -zixuejie.com -zixuekaoshi.net -zixuephp.net -zixunkezhan.com -zixuntop.com -ziy.cc -ziyadiaoyu.com -ziyainfo.com -ziyan666.com -ziyawang.com -ziye114.com -ziyesy.com -ziyexing.com -ziyimall.com -ziyou.com -ziyou.studio -ziyoufa.com -ziyouwu.com -ziyuan.tv -ziyuan605.com -ziyuanbu.com -ziyuangou.com -ziyuanku.com -ziyuanm.com -ziyuantun.com -ziyuewentao.com -ziyun.com -ziyuyx.com -zizaike.com -zizhengjiankang.com -zizhuauto.com -zizhupark.com -zizisi.com -zizizizizi.com -zizzs.com -zj-hhcy.com -zj-idc.com -zj.com -zj01.com -zj123.com -zj186.com -zj31.net -zj32.com -zj42.com -zj93zp.com -zj96596.com -zjabank.com -zjautoparts.com -zjbiz.net -zjbles.com -zjbyte.com -zjca.org -zjcb.com -zjcbank.com -zjcdn.com -zjchina.org -zjchuguo.com -zjciming.com -zjcio.org -zjckw.org -zjcnbank.com -zjcpol.com -zjcrjzj.com -zjcuhb.com -zjcxbank.com -zjdashi.com -zjdata.net -zjdh.org -zjdomain.com -zjdybank.com -zjdydlc.com -zjdyjob.com -zje.com -zjedps.com -zjedu.org -zjfdc.net -zjft.com -zjgas.net -zjgfq.com -zjgjhx.com -zjgjj.com -zjgmsw.com -zjgqt.org -zjgrrb.com -zjgslb.com -zjgt.com -zjguji.com -zjgwy.org -zjgwyw.org -zjgxy.org -zjgzcpa.com -zjgzhaopin.com -zjhcbank.com -zjhee.com -zjhejiang.com -zjhim.com -zjhnrb.com -zjhui.net -zjhx520.com -zjhyrcb.com -zjhzyg.net -zji.net -zjiis.com -zjimpact.com -zjipc.com -zjj17u.com -zjj21.com -zjj588.com -zjj88888.com -zjjcts.com -zjjd.org -zjjdamuzhi.com -zjjgcyz.com -zjjhh.com -zjjkan.com -zjjlvxing.com -zjjlvyou8264.com -zjjmcly.com -zjjr.com -zjjsbank.com -zjjshenhuxi.com -zjjsit.com -zjjta.com -zjjubao.com -zjjushu.com -zjjy.com -zjjycz.com -zjjyuntian.com -zjjzyxh.com -zjkccb.com -zjkgjj.com -zjkings.com -zjknews.com -zjkonline.com -zjks.com -zjldrcb.com -zjlottery.com -zjlvjie.com -zjlxtx.com -zjmandi.com -zjmax.com -zjmi-mall.com -zjmobile.com -zjmoney.com -zjmrhpt.com -zjmzrc.com -zjnad.com -zjnrcb.com -zjolcdn.com -zjoldns.com -zjosm.com -zjpcedu.com -zjphrcb.com -zjpost.com -zjpubservice.com -zjqimeng.com -zjqk110.com -zjqyjy.com -zjrc.com -zjrc.net -zjrjks.org -zjsaisi.com -zjscdb.com -zjscs.com -zjsight.com -zjslpt.com -zjsr.com -zjstv.com -zjszbank.com -zjszboli.com -zjtcn.com -zjtlcb.com -zjtntd.com -zjtree.com -zjujournals.com -zjuqsc.com -zjut.cc -zjutkz.net -zjwater.com -zjwc168.com -zjwk.com -zjwmw.com -zjwxbank.com -zjxf119.com -zjxpp.com -zjxqyy.com -zjxsbank.com -zjyanxing.com -zjycpx.com -zjydt.com -zjygz.org -zjyiot.com -zjyiqiao.com -zjyunsha.com -zjyygy.com -zjzdgj.com -zjzffz.com -zjzg.com -zjzj.org -zjzjhotel.com -zjzs.net -zjzsxb.com -zk2013.com -zk528.com -zk5u.com -zk71.com -zkailun.com -zkbedu.com -zkbhj.com -zkck.com -zkcmg.com -zkcrm.com -zkcx.com -zkdt.net -zkdzxx.com -zkecopro.com -zkeli.com -zkeys.com -zkgjy.net -zkh360.com -zkhb.group -zkhcsoft.com -zkhcsy.com -zkhtqm.com -zkii.net -zkk7.com -zkl2333.com -zknysp.com -zkoffcn.com -zkread.com -zkroom.com -zksoftwaresz.com -zkteco.com -zkteco.xin -zktime5.com -zktimecube.com -zktw.com -zku.net -zkungfu.com -zkuyun.com -zkx.cc -zkxblog.com -zkxlkj.net -zkxsw.com -zkxww.com -zkyouxi.com -zkyxls.com -zkzhkj.com -zkzj.org -zl99.org -zlbaba.com -zlca.org -zlck.com -zlcool.com -zlfedu.com -zlfls.com -zlg.com -zlgmcu.com -zlgpy.com -zlgsj.com -zlhelp.com -zlhome.com -zlhui.com -zlibs.com -zlimg.com -zlink-e.com -zlkb.net -zllife.net -zllyun.com -zlml.net -zlog.cc -zlongad.com -zlongame.com -zlook.com -zlorz.com -zlqh.com -zlrapt.com -zlscn.net -zlservice.net -zlsin.com -zlsnet.com -zlsoft.com -zltianhen.com -zltkj.com -zluren.com -zlvod.com -zlw.so -zlygu.com -zm1717.com -zmapp.com -zmaxhotels.cc -zmccx.com -zmctc.com -zmdfdc.com -zmdhdyc.com -zmdz.com -zmeng.cc -zmeng123.com -zmengzhu.com -zmgov.com -zmgrcw.com -zmhkl.com -zmidc.com -zmifi.com -zmingcx.com -zmirrordemo.com -zmister.com -zmjiudian.com -zmlearn.com -zmmdn.com -zmmtu.com -zmndjm.com -zmnds.com -zmnedu.com -zmnoa.com -zmnrz.com -zmobuy.com -zmonster.me -zmpal.com -zmqlh.com -zmren.com -zmrenwu.com -zmrgame.com -zmsc.cc -zmsq.com -zmt.me -zmtiantang.com -zmtpc.com -zmtquan.com -zmumu.com -zmwo.com -zmxiaoqu.com -zmxiazai.com -zmxiu.com -zmye5vly.com -zmyj2c.com -zmz2019.com -zmzapi.com -zmzapi.net -zmzjk.com -zmzjstu.com -zn8.com -znba.net -znbo.com -zncaijing.com -znczz.com -zndata.com -znddd.com -zndns.com -znds.com -znds.net -zndsbbs.com -zndstec.com -zngm.com -znhospital.com -znhr.com -znimg.com -znj.com -znjchina.com -znjj.tv -znl.app -znlzd.com -znpin.com -znqnet.com -znshuru.com -znsxs.com -zntec.mobi -zntec.net -zntx.cc -znvren.com -znwb.com -znxy7.com -znyp.com -znyseo.com -znyshurufa.com -znyt.net -znyxb.com -znzbt.com -znznet.net -zo-l.net -zocai.com -zocodev.com -zodiac.wang -zoebon.com -zoform.com -zofund.com -zohead.com -zoioo.com -zoker.io -zokogo.com -zokstar.com -zol-img.com -zol.com -zollty.com -zolsky.com -zolyol.com -zombiescat.com -zomiu.com -zomvip.com -zomzone.com -zon100.com -zone139.com -zoneben.com -zoneidc.com -zoneker.com -zonemore.com -zonen-tech.com -zonepp.com -zoneve.com -zongcaidarentilihaoya.com -zonghangsl.com -zongheng.com -zonghengche.com -zonghengke.com -zongjie100.com -zonglai.mobi -zongliwei.com -zongming.net -zongs365.com -zongxiutang.net -zongyiconverge.com -zongyifile.com -zongyigame.com -zongyijia.com -zongyimobile.com -zongyionline.com -zongyiphone.com -zongyixun.com -zonhen.com -zooao.com -zoocer.com -zoofon.com -zoogooy.com -zookingsoft.com -zookparts.com -zoom-china.com -zoom.us -zoomeye.org -zoomlion.com -zoomnetcom.com -zoomquiet.org -zoopda.com -zoosnet.net -zoossoft.com -zoossoft.net -zootui.com -zooyoo.cc -zoroli.com -zorrowh.com -zotanwa.com -zou.la -zou114.com -zou114.net -zoubiao.com -zoucheng.cc -zoucz.com -zoues.com -zoujinvr.com -zoulj.xyz -zoutu.com -zouzhenzhong.com -zouzhiqiang.com -zowoyoo.com -zoyoo.net -zozoka.com -zp.do -zp0716.com -zp0737.com -zp365.com -zp515.com -zpad.cc -zpan.space -zpascal.net -zpaudit.com -zpedu.org -zpfdc.com -zph.mobi -zphj1987.com -zpidc.com -zplayworld.com -zpluz.com -zpm.so -zpm.wiki -zppk.net -zppxba.com -zptong.com -zpxw.vip -zpzyb.com -zq-car.com -zq-scm.com -zq12369.com -zq235.com -zq99y.com -zqbzs.cc -zqchuanyue.com -zqcloudgame.com -zqctqcz.com -zqfxj.com -zqgame.com -zqgreen.com -zqic.net -zqjjr.com -zqlian.com -zqlx.com -zqnf.com -zqsign.com -zqsos.com -zqtong.com -zqtoo.com -zqvip8.cc -zqwzc.com -zqxinxi.com -zqzj.org -zqzyxx.com -zrahh.com -zrblog.net -zrbx.com -zrcaifu.com -zrcbank.com -zrfan.com -zring.com -zrj96.com -zrjhwenhua.com -zrjinfu.com -zrmm.com -zrtg.com -zrthink.com -zrway.com -zrwjk.com -zrxss.com -zry97.com -zrzyb.net -zs-e.com -zs-lzlj.com -zs0572.com -zs310.com -zs516.com -zs666.com -zs6y.com -zs8q.com -zsaber.com -zsacg.com -zsafw.com -zsapp.info -zsaxi.com -zsb353.com -zsbeike.com -zsbit.com -zsc.io -zscm8.com -zsdk.cc -zsdlw.com -zsemall.com -zseoo.com -zsevent.com -zsezt.com -zsfund.com -zsgd.com -zsglrj.com -zsgoodlighting.com -zsh.com -zsh8.com -zshield.net -zshl.com -zshlife.com -zshuoshao.online -zsia.org -zsihuo.com -zsincer.com -zsite.com -zsj18.com -zsjingmi.com -zsjinqi.com -zsjuchuang.com -zskoubei.com -zsksw.net -zslady.com -zsld86.com -zslin.com -zslp021.com -zslyyn12.com -zslyzjj11.com -zsmama.com -zsnmwy.net -zsppsj.com -zsptdjy.com -zsr.cc -zsrk120.com -zsshuwu.com -zsso03.com -zssph.com -zstack.io -zstczx.com -zsucai.com -zsufivehos.com -zsujob.com -zsvsz.com -zswcn.com -zsweai.club -zsxq.com -zsxq100.com -zsxt91.com -zsythink.net -zszq.com -zt-express.com -zt-info.com -zt1f.com -ztautoparts.com -ztbest.com -ztcadx.com -ztcia.com -ztcj365.com -ztdad.com -zte.net -ztedevice.com -ztedevices.com -ztedu8.com -ztehn.com -ztemap.com -ztems.com -ztestin.com -ztfans.com -ztfssc.com -ztgame.com -ztgy.org -zthxcf.com -ztinfoga.com -ztjoin.com -ztjy61.com -ztjystore.com -ztkm.com -ztky.com -ztmao.com -ztms.net -ztnews.net -zto.com -zto.jp -zto56.com -ztpay.org -ztqqt.com -ztrhmall.com -ztrong.com -ztsafe.com -ztsfc.com -ztsfc.net -ztt.cc -zttx-exp.com -zttx.com -ztu-crm.com -ztupic.com -ztups.com -ztv.la -ztvcar.com -ztvx8.com -ztww.net -ztxdzx.com -ztxz.cc -ztzy.com -zuan-cheng.com -zuanbi8.com -zuanchuang.org -zuanke8.com -zuankezu.com -zuanshi.com -zuanshitoupiao.com -zuantao.cc -zuantou114.com -zuber.im -zubunet.com -zuche.com -zuchecdn.com -zuciwang.com -zucp.net -zudeapp.com -zudong.com -zufang.com -zufangbao.com -zufangpk.com -zufangzi.com -zugame.com -zugeliang01.com -zuhaoapp.com -zuhaofa.com -zuhaohao.com -zuhaowan.com -zuhaowan.net -zuhedaikuan.com -zuhuanhao.com -zui.com -zui365.com -zui88.com -zuiben.com -zuibook.com -zuichen.net -zuicool.com -zuidabao.com -zuidaima.com -zuidaziyuan.com -zuidh.com -zuidj.com -zuidongxi.com -zuifengyun.com -zuihaodaxue.com -zuihaomai.com -zuihuimai.com -zuihuimai.net -zuiidea.com -zuijiao.net -zuijunshi.com -zuikc.com -zuiku.com -zuikzy.com -zuilingxian.com -zuilot.com -zuimeia.com -zuimeiqidai.com -zuimeitianqi.com -zuimoban.com -zuiniuwang.com -zuiqiangyingyu.net -zuirede.com -zuishidai.com -zuitang.com -zuitu.com -zuiwan.net -zuixiaoyao.com -zuixinwx.com -zuixu.com -zuixue.com -zuiyou.com -zuiyougou.com -zuiyouxi.com -zuiyouzhi.com -zujuan.com -zujuanyi.com -zuk.com -zukang88.com -zuker.im -zulijian.com -zulinbao.com -zumbacn.com -zun.com -zun.gd -zun315.com -zun9.com -zunxiangqiming.com -zunxun.com -zunxun.net -zunzou.com -zuoancafe.com -zuobaike.net -zuobin.net -zuocd1.group -zuoche.com -zuocheng.net -zuocoin.com -zuodanye.com -zuodao.com -zuodashi.com -zuodia.com -zuofanwang.com -zuogj.com -zuohai120.com -zuohaotu.com -zuohuodong.com -zuoji-scm.com -zuojiachubanshe.com -zuojiaju.com -zuojiawang.com -zuojing.com -zuojj.com -zuopinj.com -zuoqu.com -zuoqudashi.net -zuosa.com -zuoshipin.com -zuoshitu.com -zuotishi.com -zuowen.com -zuowen8.com -zuowenck.com -zuowening.com -zuowenjun.com -zuowenku.net -zuowenren.com -zuowens.com -zuowenwang.net -zuowenxue.com -zuowenzhai.com -zuowenzhang.com -zuowenzhitiao.com -zuoxiaolong.com -zuoye5.com -zuoyebang.cc -zuoyebang.com -zuoyehezi.com -zuoyesou.com -zuoyewang.cc -zuoyexingchen.com -zupig.com -zupuk.com -zutianke.com -zutiyu.com -zuulee.com -zuxcgames.com -zuyunfei.com -zuyushop.com -zuzheyong.com -zuzhirenshi.com -zuzitech.com -zuzuche.com -zving.com -zvnjghj.com -zvv.me -zw110.com -zw3e.com -zw3w.com -zw808.com -zw885.com -zwads.com -zwbk.org -zwcad.com -zwcnw.com -zwcsm.com -zwda.com -zwdns.com -zwdsty.com -zwdu.app -zwdu.com -zwduxs.com -zwechat.com -zwenquan.com -zwfw.com -zwgeek.com -zwhz.com -zwie2003.com -zwjczx.com -zwjhl.com -zwjiasu.com -zwjk.com -zwjl.com -zwjl.net -zwjscl.com -zwkf.net -zwkj7.com -zwoptical.com -zwtianshangm.com -zwtkl8.com -zwtxipr.com -zwwdm.com -zwwltkl.com -zwwx.com -zwzsh.net -zwzsj.com -zwzyzx.com -zx-casting.com -zx-tour.com -zx0093.com -zx017.com -zx017.net -zx080.com -zx0818.com -zx100.com -zx10000.com -zx110.org -zx181.com -zx250.com -zx350zx.com -zx7b.com -zx8.cc -zx98.com -zxbaopeng.com -zxblinux.com -zxbzr.com -zxclqw.com -zxcmk.com -zxcoder.com -zxcuv.com -zxd.com -zxdb999.com -zxdoo.com -zxdu.net -zxdyo.com -zxdyw.com -zxe-china.com -zxerp.com -zxfvip.com -zxgjxx.com -zxgnz.com -zxgzs.com -zxh.site -zxhgroup.com -zxhong.com -zxhsd.com -zxiaoxiang.com -zxicrm.com -zxinc.org -zxip.com -zxjctz.com -zxjg66.com -zxjsq.net -zxlearning.com -zxlib.com -zxlmx.com -zxmall.com -zxmn2018.com -zxmseed.com -zxmxd.com -zxnic.net -zxopen.com -zxpmq.com -zxrtb.com -zxs-coffee.com -zxsg88.com -zxshe.com -zxsmd.com -zxswjx.com -zxsygs.com -zxt2007.com -zxtang.com -zxtjd.com -zxtnetwork.com -zxttax.com -zxtyonyou.com -zxtzx.com -zxw51.com -zxwcbj.com -zxwindow.com -zxwyouxi.com -zxxk.com -zxxww.com -zxxxkj.com -zxzhijia.com -zxzj.me -zxzjs.com -zxzlf.com -zxzyy.com -zy-cam.com -zy2071.com -zy728.com -zyan.cc -zyart.org -zybang.com -zybang1.com -zybfs.com -zybhw.com -zybird.com -zybuluo.com -zyc918.com -zycdnimg.com -zycits.com -zyclps.com -zycsc.com -zycsc.net -zyctd.com -zycultura.com -zyczym.com -zydhgm.com -zydsy.com -zydtrip.net -zye.cc -zyea.com -zyebang.com -zyexhibition.com -zyeye.net -zyfchina.com -zyfj.com -zygames.com -zyge.net -zygg.cc -zygj.net -zygx.wang -zyh365.com -zyhao.com -zyhh.me -zyhn.org -zyhot.com -zyiis.com -zyiis.net -zyip.com -zyjoygame.com -zyjyyun.com -zykjgame.com -zyku.net -zyl.me -zylm99.com -zyloushi.com -zymc1.com -zymkcdn.com -zymreal.com -zymxp.com -zynh.org -zyoffice.com -zyops.com -zyou100.com -zyoung.me -zyp-cdn.com -zyplayer.com -zyq366.com -zyqc.cc -zyqccs.com -zyrj.org -zyrmw.com -zyrykbiandao.com -zys.me -zysheji.net -zyt8.com -zytuozhan.com -zytxgame.com -zyu8.com -zyuan.wang -zyucan.com -zyue.com -zyw1040.com -zywjw.com -zywxpress.com -zyxr.com -zyxuan.org -zyxzcm.com -zyy1217.com -zyyda.com -zyyfy.com -zyytcz.com -zyzaojiao.com -zyzg.com -zyzhan.com -zyzhang.com -zyzhyl.com -zyzj.org -zyzj360.com -zyzjmz.org -zyzkb.net -zyzxgy.com -zyzxs.com -zz-news.com -zz-qq.com -zz-zigzag.com -zz04.net -zz06.net -zz21.com -zz314.com -zz618.com -zz91.com -zz96269.com -zzay.net -zzbaike.com -zzbbs.com -zzbd.org -zzbq.org -zzbs.org -zzbtv.com -zzcangzhou.com -zzccom.com -zzccyq1.com -zzcm1.com -zzcm2.com -zzcm5.com -zzcmjn.com -zzcodes.net -zzcomm.com -zzcszx.com -zzdengji.com -zzdh.net -zzdz666.com -zzenglish.net -zzetao.com -zzfcj.com -zzfcw.com -zzfk120.com -zzfly.net -zzfriend.com -zzfzkg.com -zzgdapp.com -zzgelidq.com -zzggmm.com -zzggzy.com -zzgjj.com -zzgm.net -zzhaofang.com -zzhaoz.com -zzhdm.com -zzhscdq.com -zzhunshasheying.com -zzidc.com -zzit.org -zzjaz.com -zzjc5.com -zzjunzhi.com -zzjunzhuo.com -zzkiss000.com -zzlawyer.org -zzlibangqi.com -zzliot.com -zzllq.com -zzloop.com -zzmama.net -zzmscg.com -zzn.me -zznah001.com -zzndns.com -zzobokj.com -zzoumai.com -zzpd8.com -zzpuke.com -zzpzero.com -zzqklm.com -zzqxs.com -zzrbl.com -zzrseng.com -zzsf.com -zzsggzy.com -zzsgjj.com -zzshenpai.com -zzssjx.com -zzsteel.com -zzstep.com -zzt9.com -zztline.com -zztoutiao.net -zztxkj.com -zzvips.com -zzwanshou.com -zzwenxue.com -zzwhtg.com -zzwljc.com -zzwms.com -zzwqqx.com -zzwro.com -zzwyglxh.com -zzxdc.com -zzxw.net -zzxy.net -zzyanhushi.com -zzyas.com -zzyb.org -zzydb.com -zzyedu.org -zzyftrade.com -zzyichen.net -zzyilou.com -zzyiquan.com -zzyjs.com -zzyjsmba.com -zzyzan.com -zzyzphoto.com -zzz4.com -zzzdm.com -zzzhisou.com -zzzj.com -zzzla.com -zzzsxx.com -zzzxmm.com -zzzyb.com -zzzyk.com -zzzzaaaa.com -zzzzhong.com -zzzzmall.com diff --git a/package/lienol/luci-app-passwall/root/usr/share/passwall/rules/chnroute b/package/lienol/luci-app-passwall/root/usr/share/passwall/rules/chnroute deleted file mode 100644 index 9fe886dd41..0000000000 --- a/package/lienol/luci-app-passwall/root/usr/share/passwall/rules/chnroute +++ /dev/null @@ -1,8611 +0,0 @@ -1.0.1.0/24 -1.0.2.0/23 -1.0.8.0/21 -1.0.32.0/19 -1.1.0.0/24 -1.1.2.0/23 -1.1.4.0/22 -1.1.8.0/24 -1.1.9.0/24 -1.1.10.0/23 -1.1.12.0/22 -1.1.16.0/20 -1.1.32.0/19 -1.2.0.0/23 -1.2.2.0/24 -1.2.4.0/24 -1.2.5.0/24 -1.2.6.0/23 -1.2.8.0/24 -1.2.9.0/24 -1.2.10.0/23 -1.2.12.0/22 -1.2.16.0/20 -1.2.32.0/19 -1.2.64.0/18 -1.3.0.0/16 -1.4.1.0/24 -1.4.2.0/23 -1.4.4.0/24 -1.4.5.0/24 -1.4.6.0/23 -1.4.8.0/21 -1.4.16.0/20 -1.4.32.0/19 -1.4.64.0/18 -1.8.0.0/16 -1.10.0.0/21 -1.10.8.0/23 -1.10.11.0/24 -1.10.12.0/22 -1.10.16.0/20 -1.10.32.0/19 -1.10.64.0/18 -1.12.0.0/14 -1.24.0.0/13 -1.45.0.0/16 -1.48.0.0/15 -1.50.0.0/16 -1.51.0.0/16 -1.56.0.0/13 -1.68.0.0/14 -1.80.0.0/13 -1.88.0.0/14 -1.92.0.0/15 -1.94.0.0/15 -1.116.0.0/15 -1.118.0.0/16 -1.119.0.0/17 -1.119.128.0/17 -1.180.0.0/14 -1.184.0.0/15 -1.188.0.0/14 -1.192.0.0/13 -1.202.0.0/15 -1.204.0.0/14 -14.0.0.0/21 -14.0.12.0/22 -14.1.0.0/22 -14.1.24.0/22 -14.1.96.0/22 -14.1.108.0/22 -14.16.0.0/12 -14.102.128.0/22 -14.102.156.0/22 -14.102.180.0/22 -14.103.0.0/16 -14.104.0.0/13 -14.112.0.0/12 -14.130.0.0/15 -14.134.0.0/15 -14.144.0.0/12 -14.192.60.0/22 -14.192.76.0/22 -14.196.0.0/15 -14.204.0.0/15 -14.208.0.0/12 -27.0.128.0/22 -27.0.132.0/22 -27.0.160.0/22 -27.0.164.0/22 -27.0.188.0/22 -27.0.204.0/22 -27.0.208.0/22 -27.0.212.0/22 -27.8.0.0/13 -27.16.0.0/12 -27.34.232.0/21 -27.36.0.0/14 -27.40.0.0/13 -27.50.40.0/21 -27.50.128.0/17 -27.54.72.0/21 -27.54.152.0/21 -27.54.192.0/18 -27.98.208.0/20 -27.98.224.0/19 -27.99.128.0/17 -27.103.0.0/16 -27.106.128.0/18 -27.106.204.0/22 -27.109.32.0/19 -27.109.124.0/22 -27.112.0.0/18 -27.112.80.0/20 -27.112.112.0/22 -27.112.116.0/22 -27.113.128.0/18 -27.115.0.0/17 -27.116.44.0/22 -27.121.72.0/21 -27.121.120.0/21 -27.128.0.0/15 -27.131.220.0/22 -27.144.0.0/16 -27.148.0.0/14 -27.152.0.0/13 -27.184.0.0/13 -27.192.0.0/11 -27.224.0.0/14 -36.0.0.0/22 -36.0.8.0/21 -36.0.16.0/20 -36.0.32.0/19 -36.0.64.0/18 -36.0.128.0/17 -36.1.0.0/16 -36.4.0.0/14 -36.16.0.0/12 -36.32.0.0/14 -36.36.0.0/16 -36.37.0.0/19 -36.37.36.0/23 -36.37.39.0/24 -36.37.40.0/21 -36.37.48.0/20 -36.40.0.0/13 -36.48.0.0/15 -36.51.0.0/16 -36.56.0.0/13 -36.96.0.0/11 -36.128.0.0/10 -36.192.0.0/11 -36.248.0.0/14 -36.254.0.0/16 -36.255.116.0/22 -36.255.128.0/22 -36.255.164.0/22 -36.255.172.0/22 -36.255.176.0/22 -39.0.0.0/24 -39.0.2.0/23 -39.0.4.0/22 -39.0.8.0/21 -39.0.16.0/20 -39.0.32.0/19 -39.0.64.0/18 -39.0.128.0/17 -39.64.0.0/11 -39.96.0.0/13 -39.104.0.0/14 -39.108.0.0/16 -39.128.0.0/10 -40.72.0.0/15 -40.125.128.0/17 -40.126.64.0/18 -42.0.0.0/22 -42.0.8.0/21 -42.0.16.0/21 -42.0.24.0/22 -42.0.32.0/19 -42.0.128.0/17 -42.1.0.0/19 -42.1.32.0/20 -42.1.48.0/21 -42.1.56.0/22 -42.1.128.0/17 -42.4.0.0/14 -42.48.0.0/15 -42.50.0.0/16 -42.51.0.0/16 -42.52.0.0/14 -42.56.0.0/14 -42.62.0.0/17 -42.62.128.0/19 -42.62.160.0/20 -42.62.180.0/22 -42.62.184.0/21 -42.63.0.0/16 -42.80.0.0/15 -42.83.64.0/20 -42.83.80.0/22 -42.83.88.0/21 -42.83.96.0/19 -42.83.128.0/17 -42.84.0.0/14 -42.88.0.0/13 -42.96.64.0/19 -42.96.96.0/21 -42.96.108.0/22 -42.96.112.0/20 -42.96.128.0/17 -42.97.0.0/16 -42.99.0.0/18 -42.99.64.0/19 -42.99.96.0/20 -42.99.112.0/22 -42.99.120.0/21 -42.100.0.0/14 -42.120.0.0/15 -42.122.0.0/16 -42.123.0.0/19 -42.123.36.0/22 -42.123.40.0/21 -42.123.48.0/20 -42.123.64.0/18 -42.123.128.0/17 -42.128.0.0/12 -42.156.0.0/19 -42.156.36.0/22 -42.156.40.0/21 -42.156.48.0/20 -42.156.64.0/18 -42.156.128.0/17 -42.157.0.0/16 -42.158.0.0/16 -42.159.0.0/16 -42.160.0.0/12 -42.176.0.0/13 -42.184.0.0/15 -42.186.0.0/16 -42.187.0.0/18 -42.187.64.0/19 -42.187.96.0/20 -42.187.112.0/21 -42.187.120.0/22 -42.187.128.0/17 -42.192.0.0/15 -42.194.0.0/21 -42.194.8.0/22 -42.194.12.0/22 -42.194.16.0/20 -42.194.32.0/19 -42.194.64.0/18 -42.194.128.0/17 -42.195.0.0/16 -42.196.0.0/14 -42.201.0.0/17 -42.202.0.0/15 -42.204.0.0/14 -42.208.0.0/12 -42.224.0.0/12 -42.240.0.0/17 -42.240.128.0/17 -42.242.0.0/15 -42.244.0.0/14 -42.248.0.0/13 -43.136.0.0/13 -43.144.0.0/12 -43.160.0.0/11 -43.224.12.0/22 -43.224.24.0/22 -43.224.44.0/22 -43.224.52.0/22 -43.224.56.0/22 -43.224.64.0/22 -43.224.68.0/22 -43.224.72.0/22 -43.224.80.0/22 -43.224.100.0/22 -43.224.144.0/22 -43.224.160.0/22 -43.224.176.0/22 -43.224.184.0/22 -43.224.200.0/22 -43.224.204.0/22 -43.224.208.0/22 -43.224.212.0/22 -43.224.216.0/22 -43.224.240.0/22 -43.225.76.0/22 -43.225.84.0/22 -43.225.120.0/22 -43.225.124.0/22 -43.225.140.0/22 -43.225.172.0/22 -43.225.180.0/22 -43.225.208.0/22 -43.225.216.0/22 -43.225.220.0/22 -43.225.224.0/22 -43.225.228.0/22 -43.225.232.0/22 -43.225.236.0/22 -43.225.240.0/22 -43.225.244.0/22 -43.225.252.0/22 -43.226.32.0/22 -43.226.36.0/22 -43.226.40.0/22 -43.226.44.0/22 -43.226.48.0/22 -43.226.52.0/22 -43.226.56.0/22 -43.226.60.0/22 -43.226.64.0/22 -43.226.68.0/22 -43.226.72.0/22 -43.226.76.0/22 -43.226.80.0/22 -43.226.84.0/22 -43.226.88.0/22 -43.226.92.0/22 -43.226.96.0/22 -43.226.100.0/22 -43.226.104.0/22 -43.226.108.0/22 -43.226.112.0/22 -43.226.116.0/22 -43.226.120.0/22 -43.226.128.0/22 -43.226.132.0/22 -43.226.136.0/22 -43.226.140.0/22 -43.226.144.0/22 -43.226.148.0/22 -43.226.152.0/22 -43.226.156.0/22 -43.226.160.0/22 -43.226.164.0/22 -43.226.168.0/22 -43.226.172.0/22 -43.226.176.0/22 -43.226.180.0/22 -43.226.184.0/22 -43.226.188.0/22 -43.226.192.0/22 -43.226.196.0/22 -43.226.200.0/22 -43.226.204.0/22 -43.226.208.0/22 -43.226.212.0/22 -43.226.236.0/22 -43.226.240.0/22 -43.226.244.0/22 -43.226.248.0/22 -43.226.252.0/22 -43.227.0.0/22 -43.227.4.0/22 -43.227.8.0/22 -43.227.32.0/22 -43.227.36.0/22 -43.227.40.0/22 -43.227.44.0/22 -43.227.48.0/22 -43.227.52.0/22 -43.227.56.0/22 -43.227.60.0/22 -43.227.64.0/22 -43.227.68.0/22 -43.227.72.0/22 -43.227.76.0/22 -43.227.80.0/22 -43.227.84.0/22 -43.227.88.0/22 -43.227.92.0/22 -43.227.96.0/22 -43.227.100.0/22 -43.227.104.0/22 -43.227.136.0/22 -43.227.140.0/22 -43.227.144.0/22 -43.227.152.0/22 -43.227.156.0/22 -43.227.160.0/22 -43.227.164.0/22 -43.227.168.0/22 -43.227.172.0/22 -43.227.176.0/22 -43.227.180.0/22 -43.227.188.0/22 -43.227.192.0/22 -43.227.196.0/22 -43.227.200.0/22 -43.227.204.0/22 -43.227.208.0/22 -43.227.212.0/22 -43.227.216.0/22 -43.227.220.0/22 -43.227.232.0/22 -43.227.248.0/22 -43.227.252.0/22 -43.228.0.0/22 -43.228.4.0/22 -43.228.8.0/22 -43.228.12.0/22 -43.228.16.0/22 -43.228.20.0/22 -43.228.24.0/22 -43.228.28.0/22 -43.228.32.0/22 -43.228.36.0/22 -43.228.40.0/22 -43.228.44.0/22 -43.228.48.0/22 -43.228.52.0/22 -43.228.56.0/22 -43.228.60.0/22 -43.228.64.0/22 -43.228.68.0/22 -43.228.76.0/22 -43.228.100.0/22 -43.228.116.0/22 -43.228.120.0/22 -43.228.132.0/22 -43.228.136.0/22 -43.228.148.0/22 -43.228.152.0/22 -43.228.188.0/22 -43.228.204.0/22 -43.228.240.0/22 -43.229.40.0/22 -43.229.48.0/22 -43.229.56.0/22 -43.229.96.0/22 -43.229.120.0/22 -43.229.136.0/22 -43.229.140.0/22 -43.229.144.0/22 -43.229.168.0/22 -43.229.172.0/22 -43.229.176.0/22 -43.229.180.0/22 -43.229.184.0/22 -43.229.188.0/22 -43.229.192.0/22 -43.229.196.0/22 -43.229.216.0/22 -43.229.220.0/22 -43.229.232.0/22 -43.229.236.0/22 -43.230.20.0/22 -43.230.32.0/22 -43.230.68.0/22 -43.230.72.0/22 -43.230.84.0/22 -43.230.124.0/22 -43.230.136.0/22 -43.230.220.0/22 -43.230.224.0/22 -43.230.228.0/22 -43.230.232.0/22 -43.230.236.0/22 -43.230.240.0/22 -43.230.244.0/22 -43.230.248.0/22 -43.230.252.0/22 -43.231.32.0/22 -43.231.36.0/22 -43.231.40.0/22 -43.231.44.0/22 -43.231.80.0/22 -43.231.84.0/22 -43.231.88.0/22 -43.231.92.0/22 -43.231.96.0/22 -43.231.100.0/22 -43.231.104.0/22 -43.231.108.0/22 -43.231.136.0/22 -43.231.140.0/22 -43.231.144.0/22 -43.231.148.0/22 -43.231.152.0/22 -43.231.156.0/22 -43.231.160.0/22 -43.231.164.0/22 -43.231.168.0/22 -43.231.172.0/22 -43.231.176.0/22 -43.231.180.0/22 -43.236.0.0/22 -43.236.4.0/22 -43.236.8.0/22 -43.236.12.0/22 -43.236.16.0/22 -43.236.20.0/22 -43.236.24.0/22 -43.236.28.0/22 -43.236.32.0/22 -43.236.36.0/22 -43.236.40.0/22 -43.236.44.0/22 -43.236.48.0/22 -43.236.52.0/22 -43.236.56.0/22 -43.236.60.0/22 -43.236.64.0/22 -43.236.68.0/22 -43.236.72.0/22 -43.236.76.0/22 -43.236.80.0/22 -43.236.84.0/22 -43.236.88.0/22 -43.236.92.0/22 -43.236.96.0/22 -43.236.100.0/22 -43.236.104.0/22 -43.236.108.0/22 -43.236.112.0/22 -43.236.116.0/22 -43.236.120.0/22 -43.236.124.0/22 -43.236.128.0/22 -43.236.132.0/22 -43.236.136.0/22 -43.236.140.0/22 -43.236.144.0/22 -43.236.148.0/22 -43.236.152.0/22 -43.236.156.0/22 -43.236.160.0/22 -43.236.164.0/22 -43.236.168.0/22 -43.236.172.0/22 -43.236.176.0/22 -43.236.180.0/22 -43.236.184.0/22 -43.236.188.0/22 -43.236.192.0/22 -43.236.196.0/22 -43.236.200.0/22 -43.236.204.0/22 -43.236.208.0/22 -43.236.212.0/22 -43.236.216.0/22 -43.236.220.0/22 -43.236.224.0/22 -43.236.228.0/22 -43.236.232.0/22 -43.236.236.0/22 -43.236.240.0/22 -43.236.244.0/22 -43.236.248.0/22 -43.236.252.0/22 -43.237.0.0/22 -43.237.4.0/22 -43.237.8.0/22 -43.237.12.0/22 -43.237.16.0/22 -43.237.20.0/22 -43.237.24.0/22 -43.237.28.0/22 -43.237.32.0/22 -43.237.36.0/22 -43.237.40.0/22 -43.237.44.0/22 -43.237.48.0/22 -43.237.52.0/22 -43.237.56.0/22 -43.237.60.0/22 -43.237.64.0/22 -43.237.68.0/22 -43.237.72.0/22 -43.237.76.0/22 -43.237.80.0/22 -43.237.84.0/22 -43.237.88.0/22 -43.237.92.0/22 -43.237.96.0/22 -43.237.100.0/22 -43.237.104.0/22 -43.237.108.0/22 -43.237.112.0/22 -43.237.116.0/22 -43.237.120.0/22 -43.237.124.0/22 -43.237.128.0/22 -43.237.132.0/22 -43.237.136.0/22 -43.237.140.0/22 -43.237.144.0/22 -43.237.148.0/22 -43.237.152.0/22 -43.237.156.0/22 -43.237.160.0/22 -43.237.164.0/22 -43.237.168.0/22 -43.237.172.0/22 -43.237.176.0/22 -43.237.180.0/22 -43.237.184.0/22 -43.237.188.0/22 -43.237.192.0/22 -43.237.196.0/22 -43.237.200.0/22 -43.237.204.0/22 -43.237.208.0/22 -43.237.212.0/22 -43.237.216.0/22 -43.237.220.0/22 -43.237.224.0/22 -43.237.228.0/22 -43.237.232.0/22 -43.237.236.0/22 -43.237.240.0/22 -43.237.244.0/22 -43.237.248.0/22 -43.237.252.0/22 -43.238.0.0/22 -43.238.4.0/22 -43.238.8.0/22 -43.238.12.0/22 -43.238.16.0/22 -43.238.20.0/22 -43.238.24.0/22 -43.238.28.0/22 -43.238.32.0/22 -43.238.36.0/22 -43.238.40.0/22 -43.238.44.0/22 -43.238.48.0/22 -43.238.52.0/22 -43.238.56.0/22 -43.238.60.0/22 -43.238.64.0/22 -43.238.68.0/22 -43.238.72.0/22 -43.238.76.0/22 -43.238.80.0/22 -43.238.84.0/22 -43.238.88.0/22 -43.238.92.0/22 -43.238.96.0/22 -43.238.100.0/22 -43.238.104.0/22 -43.238.108.0/22 -43.238.112.0/22 -43.238.116.0/22 -43.238.120.0/22 -43.238.124.0/22 -43.238.128.0/22 -43.238.132.0/22 -43.238.136.0/22 -43.238.140.0/22 -43.238.144.0/22 -43.238.148.0/22 -43.238.152.0/22 -43.238.156.0/22 -43.238.160.0/22 -43.238.164.0/22 -43.238.168.0/22 -43.238.172.0/22 -43.238.176.0/22 -43.238.180.0/22 -43.238.184.0/22 -43.238.188.0/22 -43.238.192.0/22 -43.238.196.0/22 -43.238.200.0/22 -43.238.204.0/22 -43.238.208.0/22 -43.238.212.0/22 -43.238.216.0/22 -43.238.220.0/22 -43.238.224.0/22 -43.238.228.0/22 -43.238.232.0/22 -43.238.236.0/22 -43.238.240.0/22 -43.238.244.0/22 -43.238.248.0/22 -43.238.252.0/22 -43.239.0.0/22 -43.239.4.0/22 -43.239.8.0/21 -43.239.16.0/22 -43.239.20.0/22 -43.239.24.0/22 -43.239.28.0/22 -43.239.32.0/22 -43.239.36.0/22 -43.239.40.0/22 -43.239.44.0/22 -43.239.48.0/22 -43.239.116.0/22 -43.239.120.0/22 -43.239.172.0/22 -43.239.176.0/22 -43.240.0.0/22 -43.240.56.0/22 -43.240.60.0/22 -43.240.68.0/22 -43.240.72.0/22 -43.240.76.0/22 -43.240.84.0/22 -43.240.124.0/22 -43.240.128.0/22 -43.240.132.0/22 -43.240.136.0/22 -43.240.144.0/22 -43.240.156.0/22 -43.240.160.0/22 -43.240.164.0/22 -43.240.168.0/22 -43.240.172.0/22 -43.240.176.0/22 -43.240.180.0/22 -43.240.184.0/22 -43.240.188.0/22 -43.240.192.0/22 -43.240.196.0/22 -43.240.200.0/22 -43.240.204.0/22 -43.240.208.0/22 -43.240.212.0/22 -43.240.216.0/22 -43.240.220.0/22 -43.240.236.0/22 -43.240.240.0/22 -43.240.244.0/22 -43.240.248.0/22 -43.240.252.0/22 -43.241.0.0/22 -43.241.4.0/22 -43.241.8.0/22 -43.241.12.0/22 -43.241.16.0/22 -43.241.20.0/22 -43.241.48.0/22 -43.241.76.0/22 -43.241.80.0/22 -43.241.84.0/22 -43.241.88.0/22 -43.241.92.0/22 -43.241.112.0/22 -43.241.168.0/22 -43.241.172.0/22 -43.241.176.0/22 -43.241.180.0/22 -43.241.184.0/22 -43.241.196.0/22 -43.241.208.0/22 -43.241.212.0/22 -43.241.216.0/22 -43.241.220.0/22 -43.241.224.0/22 -43.241.228.0/22 -43.241.232.0/22 -43.241.236.0/22 -43.241.240.0/22 -43.241.248.0/22 -43.241.252.0/22 -43.242.8.0/22 -43.242.12.0/22 -43.242.16.0/22 -43.242.20.0/22 -43.242.24.0/22 -43.242.28.0/22 -43.242.44.0/22 -43.242.48.0/22 -43.242.52.0/22 -43.242.56.0/22 -43.242.60.0/22 -43.242.64.0/22 -43.242.72.0/22 -43.242.76.0/22 -43.242.80.0/22 -43.242.84.0/22 -43.242.88.0/22 -43.242.92.0/22 -43.242.96.0/22 -43.242.144.0/22 -43.242.148.0/22 -43.242.152.0/22 -43.242.156.0/22 -43.242.160.0/22 -43.242.164.0/22 -43.242.168.0/22 -43.242.180.0/22 -43.242.188.0/22 -43.242.192.0/22 -43.242.196.0/22 -43.242.204.0/22 -43.242.216.0/22 -43.242.220.0/22 -43.242.252.0/22 -43.243.4.0/22 -43.243.8.0/22 -43.243.12.0/22 -43.243.16.0/22 -43.243.24.0/22 -43.243.88.0/22 -43.243.128.0/22 -43.243.136.0/22 -43.243.144.0/22 -43.243.148.0/22 -43.243.156.0/22 -43.243.180.0/22 -43.243.188.0/22 -43.243.228.0/22 -43.243.232.0/22 -43.243.244.0/22 -43.246.0.0/22 -43.246.4.0/22 -43.246.8.0/22 -43.246.12.0/22 -43.246.16.0/22 -43.246.20.0/22 -43.246.24.0/22 -43.246.28.0/22 -43.246.32.0/22 -43.246.36.0/22 -43.246.40.0/22 -43.246.44.0/22 -43.246.48.0/22 -43.246.52.0/22 -43.246.56.0/22 -43.246.60.0/22 -43.246.64.0/22 -43.246.68.0/22 -43.246.72.0/22 -43.246.76.0/22 -43.246.80.0/22 -43.246.84.0/22 -43.246.88.0/22 -43.246.92.0/22 -43.246.96.0/22 -43.246.112.0/22 -43.246.212.0/22 -43.246.228.0/22 -43.247.4.0/22 -43.247.8.0/22 -43.247.44.0/22 -43.247.48.0/22 -43.247.68.0/22 -43.247.76.0/22 -43.247.84.0/22 -43.247.88.0/22 -43.247.92.0/22 -43.247.96.0/22 -43.247.100.0/22 -43.247.108.0/22 -43.247.112.0/22 -43.247.148.0/22 -43.247.152.0/22 -43.247.176.0/22 -43.247.180.0/22 -43.247.184.0/22 -43.247.188.0/22 -43.247.196.0/22 -43.247.200.0/22 -43.247.204.0/22 -43.247.208.0/22 -43.247.212.0/22 -43.247.216.0/22 -43.247.220.0/22 -43.247.224.0/22 -43.247.228.0/22 -43.247.232.0/22 -43.247.236.0/22 -43.247.240.0/22 -43.247.244.0/22 -43.247.248.0/22 -43.247.252.0/22 -43.248.0.0/22 -43.248.4.0/22 -43.248.20.0/22 -43.248.28.0/22 -43.248.48.0/22 -43.248.76.0/22 -43.248.80.0/22 -43.248.84.0/22 -43.248.88.0/22 -43.248.92.0/22 -43.248.96.0/22 -43.248.100.0/22 -43.248.104.0/22 -43.248.108.0/22 -43.248.112.0/22 -43.248.116.0/22 -43.248.120.0/22 -43.248.124.0/22 -43.248.128.0/22 -43.248.132.0/22 -43.248.136.0/22 -43.248.140.0/22 -43.248.144.0/22 -43.248.148.0/22 -43.248.176.0/22 -43.248.180.0/22 -43.248.184.0/22 -43.248.188.0/22 -43.248.192.0/22 -43.248.196.0/22 -43.248.200.0/22 -43.248.204.0/22 -43.248.208.0/22 -43.248.228.0/22 -43.248.232.0/22 -43.248.244.0/22 -43.249.4.0/22 -43.249.8.0/22 -43.249.120.0/22 -43.249.132.0/22 -43.249.136.0/22 -43.249.144.0/22 -43.249.148.0/22 -43.249.152.0/22 -43.249.156.0/22 -43.249.160.0/22 -43.249.164.0/22 -43.249.168.0/22 -43.249.192.0/22 -43.249.236.0/22 -43.250.4.0/22 -43.250.12.0/22 -43.250.16.0/22 -43.250.20.0/22 -43.250.28.0/22 -43.250.32.0/22 -43.250.36.0/22 -43.250.72.0/22 -43.250.96.0/22 -43.250.100.0/22 -43.250.104.0/22 -43.250.108.0/22 -43.250.112.0/22 -43.250.116.0/22 -43.250.128.0/22 -43.250.144.0/22 -43.250.148.0/22 -43.250.160.0/22 -43.250.168.0/22 -43.250.172.0/22 -43.250.176.0/22 -43.250.200.0/22 -43.250.212.0/22 -43.250.216.0/22 -43.250.220.0/22 -43.250.236.0/22 -43.250.244.0/22 -43.251.4.0/22 -43.251.8.0/22 -43.251.36.0/22 -43.251.100.0/22 -43.251.116.0/22 -43.251.192.0/22 -43.251.232.0/22 -43.251.236.0/22 -43.251.244.0/22 -43.252.48.0/22 -43.252.56.0/22 -43.252.224.0/22 -43.254.0.0/22 -43.254.4.0/22 -43.254.8.0/22 -43.254.24.0/22 -43.254.36.0/22 -43.254.44.0/22 -43.254.52.0/22 -43.254.64.0/22 -43.254.72.0/22 -43.254.84.0/22 -43.254.88.0/22 -43.254.92.0/22 -43.254.100.0/22 -43.254.104.0/22 -43.254.112.0/22 -43.254.116.0/22 -43.254.128.0/22 -43.254.136.0/22 -43.254.140.0/22 -43.254.144.0/22 -43.254.148.0/22 -43.254.152.0/22 -43.254.156.0/22 -43.254.168.0/22 -43.254.172.0/22 -43.254.180.0/22 -43.254.184.0/22 -43.254.188.0/22 -43.254.192.0/22 -43.254.196.0/22 -43.254.200.0/22 -43.254.208.0/22 -43.254.220.0/22 -43.254.224.0/22 -43.254.228.0/22 -43.254.232.0/22 -43.254.236.0/22 -43.254.240.0/22 -43.254.248.0/22 -43.254.252.0/22 -43.255.0.0/22 -43.255.4.0/22 -43.255.8.0/22 -43.255.16.0/22 -43.255.48.0/22 -43.255.64.0/22 -43.255.68.0/22 -43.255.72.0/22 -43.255.76.0/22 -43.255.84.0/22 -43.255.96.0/22 -43.255.108.0/22 -43.255.144.0/22 -43.255.168.0/22 -43.255.176.0/22 -43.255.184.0/22 -43.255.192.0/22 -43.255.200.0/22 -43.255.204.0/22 -43.255.208.0/22 -43.255.212.0/22 -43.255.224.0/22 -43.255.228.0/22 -43.255.232.0/22 -43.255.244.0/22 -45.40.192.0/18 -45.65.16.0/22 -45.65.20.0/22 -45.65.24.0/22 -45.65.28.0/22 -45.112.132.0/22 -45.112.188.0/22 -45.112.208.0/22 -45.112.212.0/22 -45.112.216.0/22 -45.112.220.0/22 -45.112.228.0/22 -45.112.232.0/22 -45.112.236.0/22 -45.113.12.0/22 -45.113.16.0/22 -45.113.20.0/22 -45.113.24.0/22 -45.113.28.0/22 -45.113.40.0/22 -45.113.52.0/22 -45.113.56.0/22 -45.113.72.0/22 -45.113.144.0/22 -45.113.148.0/22 -45.113.168.0/22 -45.113.176.0/22 -45.113.184.0/22 -45.113.200.0/22 -45.113.204.0/22 -45.113.208.0/22 -45.113.212.0/22 -45.113.216.0/22 -45.113.220.0/22 -45.113.240.0/22 -45.113.252.0/22 -45.114.0.0/22 -45.114.12.0/22 -45.114.32.0/22 -45.114.40.0/22 -45.114.52.0/22 -45.114.96.0/22 -45.114.104.0/22 -45.114.124.0/22 -45.114.136.0/22 -45.114.196.0/22 -45.114.200.0/22 -45.114.228.0/22 -45.114.252.0/22 -45.115.44.0/22 -45.115.100.0/22 -45.115.120.0/22 -45.115.132.0/22 -45.115.144.0/22 -45.115.156.0/22 -45.115.164.0/22 -45.115.200.0/22 -45.115.212.0/22 -45.115.228.0/22 -45.115.236.0/22 -45.115.244.0/22 -45.115.248.0/22 -45.116.16.0/22 -45.116.24.0/22 -45.116.32.0/22 -45.116.36.0/22 -45.116.52.0/22 -45.116.96.0/22 -45.116.100.0/22 -45.116.140.0/22 -45.116.152.0/22 -45.116.208.0/22 -45.117.8.0/22 -45.117.20.0/22 -45.117.68.0/22 -45.117.124.0/22 -45.117.252.0/22 -45.119.52.0/22 -45.119.60.0/22 -45.119.64.0/22 -45.119.68.0/22 -45.119.72.0/22 -45.119.104.0/22 -45.119.116.0/22 -45.119.232.0/22 -45.120.100.0/22 -45.120.140.0/22 -45.120.164.0/22 -45.120.220.0/22 -45.120.240.0/22 -45.121.52.0/22 -45.121.64.0/22 -45.121.68.0/22 -45.121.72.0/22 -45.121.92.0/22 -45.121.96.0/22 -45.121.172.0/22 -45.121.176.0/22 -45.121.212.0/22 -45.121.240.0/22 -45.121.244.0/22 -45.121.248.0/22 -45.121.252.0/22 -45.122.0.0/22 -45.122.4.0/22 -45.122.8.0/22 -45.122.12.0/22 -45.122.16.0/22 -45.122.20.0/22 -45.122.24.0/22 -45.122.28.0/22 -45.122.32.0/22 -45.122.36.0/22 -45.122.40.0/22 -45.122.60.0/22 -45.122.64.0/22 -45.122.68.0/22 -45.122.72.0/22 -45.122.76.0/22 -45.122.80.0/22 -45.122.84.0/22 -45.122.88.0/22 -45.122.92.0/22 -45.122.96.0/21 -45.122.104.0/22 -45.122.108.0/22 -45.122.112.0/22 -45.122.116.0/22 -45.122.160.0/22 -45.122.164.0/22 -45.122.168.0/22 -45.122.172.0/22 -45.122.176.0/22 -45.122.180.0/22 -45.122.184.0/22 -45.122.188.0/22 -45.122.192.0/22 -45.122.196.0/22 -45.122.200.0/22 -45.122.204.0/22 -45.122.208.0/22 -45.122.212.0/22 -45.122.216.0/22 -45.123.28.0/22 -45.123.32.0/22 -45.123.36.0/22 -45.123.44.0/22 -45.123.48.0/22 -45.123.52.0/22 -45.123.56.0/22 -45.123.60.0/22 -45.123.64.0/22 -45.123.68.0/22 -45.123.72.0/22 -45.123.76.0/22 -45.123.80.0/22 -45.123.84.0/22 -45.123.88.0/22 -45.123.120.0/22 -45.123.128.0/22 -45.123.132.0/22 -45.123.136.0/22 -45.123.148.0/22 -45.123.152.0/22 -45.123.156.0/22 -45.123.164.0/22 -45.123.168.0/22 -45.123.172.0/22 -45.123.176.0/22 -45.123.180.0/22 -45.123.184.0/22 -45.123.204.0/22 -45.123.212.0/22 -45.123.224.0/22 -45.123.228.0/22 -45.123.232.0/22 -45.123.236.0/22 -45.123.240.0/22 -45.123.244.0/22 -45.123.248.0/22 -45.123.252.0/22 -45.124.0.0/22 -45.124.20.0/22 -45.124.28.0/22 -45.124.32.0/22 -45.124.36.0/22 -45.124.44.0/22 -45.124.68.0/22 -45.124.76.0/22 -45.124.80.0/22 -45.124.100.0/22 -45.124.124.0/22 -45.124.172.0/22 -45.124.176.0/22 -45.124.208.0/22 -45.124.248.0/22 -45.125.12.0/22 -45.125.16.0/22 -45.125.24.0/22 -45.125.28.0/22 -45.125.44.0/22 -45.125.52.0/22 -45.125.56.0/22 -45.125.76.0/22 -45.125.80.0/22 -45.125.84.0/22 -45.125.88.0/22 -45.125.92.0/22 -45.125.96.0/22 -45.125.100.0/22 -45.125.104.0/22 -45.125.136.0/22 -45.126.48.0/22 -45.126.52.0/22 -45.126.100.0/22 -45.126.108.0/22 -45.126.112.0/22 -45.126.116.0/22 -45.126.120.0/22 -45.126.212.0/22 -45.126.220.0/22 -45.127.8.0/22 -45.127.12.0/22 -45.127.96.0/22 -45.127.116.0/22 -45.127.128.0/22 -45.127.144.0/22 -45.127.148.0/22 -45.127.156.0/22 -45.127.216.0/22 -45.248.8.0/22 -45.248.80.0/22 -45.248.84.0/22 -45.248.88.0/22 -45.248.96.0/22 -45.248.100.0/22 -45.248.104.0/22 -45.248.108.0/22 -45.248.128.0/22 -45.248.132.0/22 -45.248.204.0/22 -45.248.208.0/22 -45.248.212.0/22 -45.248.216.0/22 -45.248.220.0/22 -45.248.224.0/22 -45.248.228.0/22 -45.248.232.0/22 -45.248.236.0/22 -45.248.240.0/22 -45.248.244.0/22 -45.248.248.0/22 -45.248.252.0/22 -45.249.0.0/22 -45.249.4.0/22 -45.249.12.0/22 -45.249.16.0/22 -45.249.20.0/22 -45.249.24.0/22 -45.249.28.0/22 -45.249.32.0/22 -45.249.36.0/22 -45.249.92.0/22 -45.249.112.0/22 -45.249.188.0/22 -45.249.192.0/22 -45.249.196.0/22 -45.249.200.0/22 -45.249.204.0/22 -45.249.208.0/22 -45.249.212.0/22 -45.250.12.0/22 -45.250.16.0/22 -45.250.28.0/22 -45.250.32.0/22 -45.250.36.0/22 -45.250.40.0/22 -45.250.76.0/22 -45.250.80.0/22 -45.250.84.0/22 -45.250.88.0/22 -45.250.92.0/22 -45.250.96.0/22 -45.250.104.0/22 -45.250.108.0/22 -45.250.112.0/22 -45.250.116.0/22 -45.250.120.0/22 -45.250.124.0/22 -45.250.128.0/22 -45.250.132.0/22 -45.250.136.0/22 -45.250.140.0/22 -45.250.144.0/22 -45.250.148.0/22 -45.250.152.0/22 -45.250.164.0/22 -45.250.180.0/22 -45.250.184.0/22 -45.250.188.0/22 -45.250.192.0/22 -45.251.0.0/22 -45.251.8.0/22 -45.251.16.0/22 -45.251.20.0/22 -45.251.52.0/22 -45.251.84.0/22 -45.251.88.0/22 -45.251.92.0/22 -45.251.96.0/22 -45.251.100.0/22 -45.251.120.0/22 -45.251.124.0/22 -45.251.136.0/22 -45.251.140.0/22 -45.251.144.0/22 -45.251.148.0/22 -45.251.152.0/22 -45.251.156.0/22 -45.251.160.0/22 -45.251.164.0/22 -45.251.168.0/22 -45.251.172.0/22 -45.251.176.0/22 -45.251.180.0/22 -45.251.184.0/22 -45.251.188.0/22 -45.251.192.0/22 -45.251.196.0/22 -45.251.200.0/22 -45.251.204.0/22 -45.251.208.0/22 -45.251.212.0/22 -45.251.216.0/22 -45.251.220.0/22 -45.251.224.0/22 -45.251.240.0/22 -45.252.0.0/22 -45.252.4.0/22 -45.252.8.0/22 -45.252.12.0/22 -45.252.16.0/22 -45.252.20.0/22 -45.252.24.0/22 -45.252.28.0/22 -45.252.32.0/22 -45.252.36.0/22 -45.252.40.0/22 -45.252.44.0/22 -45.252.48.0/22 -45.252.60.0/22 -45.252.84.0/22 -45.252.88.0/22 -45.252.92.0/22 -45.252.96.0/22 -45.252.100.0/22 -45.252.104.0/22 -45.252.108.0/22 -45.252.112.0/22 -45.252.116.0/22 -45.252.120.0/22 -45.252.124.0/22 -45.252.128.0/22 -45.252.132.0/22 -45.252.136.0/22 -45.252.140.0/22 -45.252.144.0/22 -45.252.148.0/22 -45.252.152.0/22 -45.252.156.0/22 -45.252.160.0/22 -45.252.164.0/22 -45.252.168.0/22 -45.252.172.0/22 -45.252.176.0/22 -45.252.192.0/22 -45.252.196.0/22 -45.252.200.0/22 -45.252.204.0/22 -45.252.208.0/22 -45.252.212.0/22 -45.252.216.0/22 -45.252.220.0/22 -45.252.224.0/22 -45.252.228.0/22 -45.252.232.0/22 -45.253.0.0/22 -45.253.4.0/22 -45.253.8.0/22 -45.253.12.0/22 -45.253.16.0/22 -45.253.20.0/22 -45.253.24.0/22 -45.253.28.0/22 -45.253.32.0/22 -45.253.36.0/22 -45.253.40.0/22 -45.253.44.0/22 -45.253.48.0/22 -45.253.52.0/22 -45.253.56.0/22 -45.253.60.0/22 -45.253.64.0/22 -45.253.68.0/22 -45.253.72.0/22 -45.253.76.0/22 -45.253.80.0/22 -45.253.84.0/22 -45.253.92.0/22 -45.253.96.0/22 -45.253.100.0/22 -45.253.104.0/22 -45.253.108.0/22 -45.253.112.0/22 -45.253.116.0/22 -45.253.120.0/22 -45.253.132.0/22 -45.253.136.0/22 -45.253.140.0/22 -45.253.144.0/22 -45.253.148.0/22 -45.253.152.0/22 -45.253.156.0/22 -45.253.160.0/22 -45.253.164.0/22 -45.253.168.0/22 -45.253.172.0/22 -45.253.176.0/22 -45.253.180.0/22 -45.253.184.0/22 -45.253.188.0/22 -45.253.192.0/22 -45.253.196.0/22 -45.253.200.0/22 -45.253.204.0/22 -45.253.208.0/22 -45.253.212.0/22 -45.253.216.0/22 -45.253.220.0/22 -45.253.224.0/22 -45.253.228.0/22 -45.253.232.0/22 -45.253.236.0/22 -45.253.240.0/22 -45.253.244.0/22 -45.254.0.0/22 -45.254.4.0/22 -45.254.8.0/22 -45.254.12.0/22 -45.254.16.0/22 -45.254.20.0/22 -45.254.24.0/22 -45.254.28.0/22 -45.254.40.0/22 -45.254.48.0/22 -45.254.52.0/22 -45.254.56.0/22 -45.254.60.0/22 -45.254.64.0/22 -45.254.68.0/22 -45.254.72.0/22 -45.254.76.0/22 -45.254.80.0/22 -45.254.84.0/22 -45.254.88.0/22 -45.254.92.0/22 -45.254.96.0/22 -45.254.100.0/22 -45.254.104.0/22 -45.254.108.0/22 -45.254.112.0/22 -45.254.116.0/22 -45.254.120.0/22 -45.254.124.0/22 -45.254.128.0/22 -45.254.132.0/22 -45.254.136.0/22 -45.254.140.0/22 -45.254.144.0/22 -45.254.148.0/22 -45.254.152.0/22 -45.254.156.0/22 -45.254.160.0/22 -45.254.164.0/22 -45.254.168.0/22 -45.254.172.0/22 -45.254.176.0/22 -45.254.180.0/22 -45.254.184.0/22 -45.254.188.0/22 -45.254.192.0/22 -45.254.196.0/22 -45.254.200.0/22 -45.254.204.0/22 -45.254.208.0/22 -45.254.212.0/22 -45.254.216.0/22 -45.254.220.0/22 -45.254.224.0/22 -45.254.228.0/22 -45.254.236.0/22 -45.254.240.0/22 -45.254.248.0/22 -45.255.0.0/22 -45.255.4.0/22 -45.255.8.0/22 -45.255.12.0/22 -45.255.16.0/22 -45.255.20.0/22 -45.255.24.0/22 -45.255.28.0/22 -45.255.32.0/22 -45.255.36.0/22 -45.255.40.0/22 -45.255.44.0/22 -45.255.48.0/22 -45.255.52.0/22 -45.255.56.0/22 -45.255.60.0/22 -45.255.64.0/22 -45.255.68.0/22 -45.255.72.0/22 -45.255.76.0/22 -45.255.80.0/22 -45.255.84.0/22 -45.255.88.0/22 -45.255.92.0/22 -45.255.96.0/22 -45.255.100.0/22 -45.255.104.0/22 -45.255.108.0/22 -45.255.112.0/22 -45.255.116.0/22 -45.255.120.0/22 -45.255.124.0/22 -45.255.132.0/22 -45.255.136.0/22 -45.255.140.0/22 -45.255.144.0/22 -45.255.148.0/22 -45.255.152.0/22 -45.255.156.0/22 -45.255.160.0/22 -45.255.164.0/22 -45.255.168.0/22 -45.255.172.0/22 -45.255.176.0/22 -45.255.180.0/22 -45.255.184.0/22 -45.255.188.0/22 -45.255.192.0/22 -45.255.196.0/22 -45.255.200.0/22 -45.255.204.0/22 -45.255.208.0/22 -45.255.212.0/22 -45.255.216.0/22 -45.255.220.0/22 -45.255.224.0/22 -45.255.228.0/22 -45.255.232.0/22 -45.255.236.0/22 -45.255.240.0/22 -45.255.244.0/22 -45.255.248.0/22 -47.92.0.0/14 -47.96.0.0/11 -49.4.0.0/14 -49.51.0.0/16 -49.52.0.0/14 -49.64.0.0/11 -49.112.0.0/13 -49.120.0.0/14 -49.128.0.0/24 -49.128.2.0/23 -49.128.4.0/22 -49.140.0.0/15 -49.152.0.0/14 -49.208.0.0/15 -49.210.0.0/15 -49.220.0.0/14 -49.232.0.0/14 -49.239.0.0/18 -49.239.192.0/18 -49.246.224.0/19 -52.80.0.0/15 -52.82.0.0/15 -52.130.0.0/15 -54.222.0.0/15 -58.14.0.0/15 -58.16.0.0/16 -58.17.0.0/17 -58.17.128.0/17 -58.18.0.0/16 -58.19.0.0/16 -58.20.0.0/16 -58.21.0.0/16 -58.22.0.0/15 -58.24.0.0/15 -58.30.0.0/15 -58.32.0.0/13 -58.40.0.0/15 -58.42.0.0/16 -58.43.0.0/16 -58.44.0.0/14 -58.48.0.0/13 -58.56.0.0/15 -58.58.0.0/16 -58.59.0.0/17 -58.59.128.0/17 -58.60.0.0/14 -58.65.232.0/21 -58.66.0.0/15 -58.68.128.0/17 -58.82.0.0/17 -58.83.0.0/17 -58.83.128.0/17 -58.87.64.0/18 -58.99.128.0/17 -58.100.0.0/15 -58.116.0.0/14 -58.128.0.0/13 -58.144.0.0/16 -58.154.0.0/15 -58.192.0.0/15 -58.194.0.0/15 -58.196.0.0/15 -58.198.0.0/15 -58.200.0.0/13 -58.208.0.0/12 -58.240.0.0/15 -58.242.0.0/15 -58.244.0.0/15 -58.246.0.0/15 -58.248.0.0/13 -59.32.0.0/13 -59.40.0.0/15 -59.42.0.0/16 -59.43.0.0/16 -59.44.0.0/14 -59.48.0.0/16 -59.49.0.0/17 -59.49.128.0/17 -59.50.0.0/16 -59.51.0.0/17 -59.51.128.0/17 -59.52.0.0/14 -59.56.0.0/14 -59.60.0.0/15 -59.62.0.0/15 -59.64.0.0/14 -59.68.0.0/14 -59.72.0.0/15 -59.74.0.0/15 -59.76.0.0/16 -59.77.0.0/16 -59.78.0.0/15 -59.80.0.0/15 -59.82.0.0/15 -59.107.0.0/17 -59.107.128.0/17 -59.108.0.0/15 -59.110.0.0/15 -59.151.0.0/17 -59.152.16.0/22 -59.152.20.0/22 -59.152.24.0/22 -59.152.28.0/22 -59.152.32.0/22 -59.152.36.0/22 -59.152.64.0/22 -59.152.68.0/22 -59.152.72.0/22 -59.152.76.0/22 -59.152.112.0/22 -59.152.116.0/22 -59.153.4.0/22 -59.153.32.0/22 -59.153.60.0/22 -59.153.64.0/22 -59.153.68.0/22 -59.153.72.0/22 -59.153.92.0/22 -59.153.116.0/22 -59.153.136.0/22 -59.153.152.0/22 -59.153.156.0/22 -59.153.164.0/22 -59.153.168.0/22 -59.153.172.0/22 -59.153.176.0/22 -59.153.180.0/22 -59.153.184.0/22 -59.153.188.0/22 -59.153.192.0/22 -59.155.0.0/16 -59.172.0.0/15 -59.174.0.0/15 -59.191.0.0/17 -59.192.0.0/10 -60.0.0.0/13 -60.8.0.0/15 -60.10.0.0/16 -60.11.0.0/16 -60.12.0.0/16 -60.13.0.0/18 -60.13.64.0/18 -60.13.128.0/17 -60.14.0.0/15 -60.16.0.0/13 -60.24.0.0/14 -60.28.0.0/15 -60.30.0.0/16 -60.31.0.0/16 -60.55.0.0/16 -60.63.0.0/16 -60.160.0.0/15 -60.162.0.0/15 -60.164.0.0/15 -60.166.0.0/15 -60.168.0.0/13 -60.176.0.0/12 -60.194.0.0/15 -60.200.0.0/14 -60.204.0.0/16 -60.205.0.0/16 -60.206.0.0/15 -60.208.0.0/13 -60.216.0.0/15 -60.218.0.0/15 -60.220.0.0/14 -60.232.0.0/15 -60.235.0.0/16 -60.245.128.0/17 -60.247.0.0/16 -60.252.0.0/16 -60.253.128.0/17 -60.255.0.0/16 -61.4.80.0/22 -61.4.84.0/22 -61.4.88.0/21 -61.4.176.0/20 -61.8.160.0/20 -61.14.212.0/22 -61.14.216.0/22 -61.14.220.0/22 -61.14.240.0/22 -61.14.244.0/22 -61.28.0.0/20 -61.28.16.0/20 -61.28.32.0/19 -61.28.64.0/18 -61.29.128.0/18 -61.29.192.0/19 -61.29.224.0/20 -61.29.240.0/21 -61.29.248.0/22 -61.29.254.0/23 -61.45.128.0/18 -61.45.224.0/20 -61.47.128.0/18 -61.48.0.0/14 -61.52.0.0/15 -61.54.0.0/16 -61.55.0.0/16 -61.87.192.0/18 -61.128.0.0/15 -61.130.0.0/15 -61.132.0.0/16 -61.133.0.0/17 -61.133.128.0/17 -61.134.0.0/18 -61.134.64.0/19 -61.134.96.0/19 -61.134.128.0/18 -61.134.192.0/18 -61.135.0.0/16 -61.136.0.0/18 -61.136.64.0/18 -61.136.128.0/17 -61.137.0.0/17 -61.137.128.0/17 -61.138.0.0/18 -61.138.64.0/18 -61.138.128.0/18 -61.138.192.0/18 -61.139.0.0/17 -61.139.128.0/18 -61.139.192.0/18 -61.140.0.0/14 -61.144.0.0/14 -61.148.0.0/15 -61.150.0.0/15 -61.152.0.0/16 -61.153.0.0/16 -61.154.0.0/15 -61.156.0.0/16 -61.157.0.0/16 -61.158.0.0/17 -61.158.128.0/17 -61.159.0.0/18 -61.159.64.0/18 -61.159.128.0/17 -61.160.0.0/16 -61.161.0.0/18 -61.161.64.0/18 -61.161.128.0/17 -61.162.0.0/16 -61.163.0.0/16 -61.164.0.0/16 -61.165.0.0/16 -61.166.0.0/16 -61.167.0.0/16 -61.168.0.0/16 -61.169.0.0/16 -61.170.0.0/15 -61.172.0.0/14 -61.176.0.0/16 -61.177.0.0/16 -61.178.0.0/16 -61.179.0.0/16 -61.180.0.0/17 -61.180.128.0/17 -61.181.0.0/16 -61.182.0.0/16 -61.183.0.0/16 -61.184.0.0/14 -61.188.0.0/16 -61.189.0.0/17 -61.189.128.0/17 -61.190.0.0/15 -61.232.0.0/14 -61.236.0.0/15 -61.240.0.0/14 -62.234.0.0/16 -68.79.0.0/18 -69.230.192.0/18 -69.231.128.0/18 -69.234.192.0/18 -69.235.128.0/18 -71.131.192.0/18 -71.132.0.0/18 -71.136.64.0/18 -71.137.0.0/18 -81.68.0.0/14 -82.156.0.0/15 -94.191.0.0/17 -101.0.0.0/22 -101.1.0.0/22 -101.2.172.0/22 -101.4.0.0/14 -101.16.0.0/12 -101.33.128.0/17 -101.34.0.0/15 -101.36.0.0/18 -101.36.64.0/19 -101.36.128.0/17 -101.37.0.0/16 -101.38.0.0/15 -101.40.0.0/15 -101.42.0.0/15 -101.44.0.0/14 -101.48.0.0/15 -101.50.8.0/22 -101.50.12.0/22 -101.50.56.0/22 -101.52.0.0/16 -101.53.100.0/22 -101.54.0.0/16 -101.55.224.0/21 -101.64.0.0/13 -101.72.0.0/14 -101.76.0.0/15 -101.78.0.0/22 -101.78.32.0/19 -101.80.0.0/12 -101.96.0.0/21 -101.96.8.0/22 -101.96.16.0/20 -101.96.128.0/17 -101.99.96.0/19 -101.101.64.0/19 -101.101.100.0/24 -101.101.102.0/23 -101.101.104.0/21 -101.101.112.0/20 -101.102.64.0/19 -101.102.100.0/23 -101.102.102.0/24 -101.102.104.0/21 -101.102.112.0/20 -101.104.0.0/14 -101.110.64.0/19 -101.110.96.0/20 -101.110.116.0/22 -101.110.120.0/21 -101.120.0.0/14 -101.124.0.0/15 -101.126.0.0/16 -101.128.0.0/22 -101.128.8.0/21 -101.128.16.0/20 -101.128.32.0/19 -101.129.0.0/16 -101.130.0.0/15 -101.132.0.0/14 -101.144.0.0/12 -101.192.0.0/14 -101.196.0.0/16 -101.197.0.0/16 -101.198.0.0/15 -101.200.0.0/15 -101.203.128.0/19 -101.203.160.0/21 -101.203.172.0/22 -101.203.176.0/20 -101.204.0.0/14 -101.224.0.0/13 -101.232.0.0/15 -101.234.64.0/21 -101.234.76.0/22 -101.234.80.0/20 -101.234.96.0/19 -101.236.0.0/14 -101.240.0.0/14 -101.244.0.0/16 -101.245.0.0/16 -101.246.0.0/15 -101.248.0.0/15 -101.251.0.0/22 -101.251.8.0/21 -101.251.16.0/20 -101.251.32.0/19 -101.251.64.0/18 -101.251.128.0/17 -101.252.0.0/15 -101.254.0.0/16 -103.1.8.0/22 -103.1.20.0/22 -103.1.24.0/22 -103.1.72.0/22 -103.1.88.0/22 -103.1.168.0/22 -103.2.108.0/22 -103.2.156.0/22 -103.2.164.0/22 -103.2.200.0/22 -103.2.204.0/22 -103.2.208.0/22 -103.2.212.0/22 -103.3.84.0/22 -103.3.88.0/22 -103.3.92.0/22 -103.3.96.0/22 -103.3.100.0/22 -103.3.104.0/22 -103.3.108.0/22 -103.3.112.0/22 -103.3.116.0/22 -103.3.120.0/22 -103.3.124.0/22 -103.3.128.0/22 -103.3.132.0/22 -103.3.136.0/22 -103.3.140.0/22 -103.3.148.0/22 -103.3.152.0/22 -103.3.156.0/22 -103.4.56.0/22 -103.4.168.0/22 -103.4.184.0/22 -103.4.224.0/22 -103.5.36.0/22 -103.5.52.0/22 -103.5.56.0/22 -103.5.152.0/22 -103.5.168.0/22 -103.5.192.0/22 -103.5.252.0/22 -103.6.76.0/22 -103.6.108.0/22 -103.6.220.0/22 -103.6.228.0/22 -103.7.4.0/22 -103.7.28.0/22 -103.7.140.0/22 -103.7.212.0/22 -103.7.216.0/22 -103.7.220.0/22 -103.8.0.0/22 -103.8.4.0/22 -103.8.8.0/22 -103.8.32.0/22 -103.8.52.0/22 -103.8.68.0/22 -103.8.108.0/22 -103.8.156.0/22 -103.8.200.0/22 -103.8.204.0/22 -103.8.220.0/22 -103.9.8.0/22 -103.9.24.0/22 -103.9.108.0/22 -103.9.152.0/22 -103.9.192.0/22 -103.9.248.0/22 -103.9.252.0/22 -103.10.0.0/22 -103.10.16.0/22 -103.10.84.0/22 -103.10.140.0/22 -103.11.16.0/22 -103.11.168.0/22 -103.11.180.0/22 -103.12.32.0/22 -103.12.68.0/22 -103.12.92.0/22 -103.12.136.0/22 -103.12.184.0/22 -103.12.232.0/22 -103.13.12.0/22 -103.13.124.0/22 -103.13.144.0/22 -103.13.196.0/22 -103.13.220.0/22 -103.13.244.0/22 -103.14.32.0/22 -103.14.84.0/22 -103.14.100.0/22 -103.14.132.0/22 -103.14.136.0/22 -103.14.156.0/22 -103.14.240.0/22 -103.15.4.0/22 -103.15.8.0/22 -103.15.16.0/22 -103.15.96.0/22 -103.15.200.0/22 -103.16.52.0/22 -103.16.80.0/22 -103.16.84.0/22 -103.16.88.0/22 -103.16.108.0/22 -103.16.124.0/22 -103.17.40.0/22 -103.17.64.0/22 -103.17.120.0/22 -103.17.136.0/22 -103.17.160.0/22 -103.17.204.0/22 -103.17.228.0/22 -103.18.192.0/22 -103.18.208.0/22 -103.18.212.0/22 -103.18.224.0/22 -103.19.12.0/22 -103.19.40.0/22 -103.19.44.0/22 -103.19.64.0/22 -103.19.68.0/22 -103.19.72.0/22 -103.19.232.0/22 -103.20.12.0/22 -103.20.32.0/22 -103.20.44.0/22 -103.20.68.0/22 -103.20.112.0/22 -103.20.128.0/22 -103.20.160.0/22 -103.20.248.0/22 -103.21.112.0/22 -103.21.116.0/22 -103.21.136.0/22 -103.21.140.0/22 -103.21.176.0/22 -103.21.208.0/22 -103.21.240.0/22 -103.22.0.0/22 -103.22.4.0/22 -103.22.8.0/22 -103.22.12.0/22 -103.22.16.0/22 -103.22.20.0/22 -103.22.24.0/22 -103.22.28.0/22 -103.22.32.0/22 -103.22.36.0/22 -103.22.40.0/22 -103.22.44.0/22 -103.22.48.0/22 -103.22.52.0/22 -103.22.56.0/22 -103.22.60.0/22 -103.22.64.0/22 -103.22.68.0/22 -103.22.72.0/22 -103.22.76.0/22 -103.22.80.0/22 -103.22.84.0/22 -103.22.88.0/22 -103.22.92.0/22 -103.22.100.0/22 -103.22.104.0/22 -103.22.108.0/22 -103.22.112.0/22 -103.22.116.0/22 -103.22.120.0/22 -103.22.124.0/22 -103.22.188.0/22 -103.22.228.0/22 -103.22.252.0/22 -103.23.8.0/22 -103.23.56.0/22 -103.23.160.0/22 -103.23.164.0/22 -103.23.176.0/22 -103.23.228.0/22 -103.24.24.0/22 -103.24.116.0/22 -103.24.128.0/22 -103.24.144.0/22 -103.24.176.0/22 -103.24.184.0/22 -103.24.220.0/22 -103.24.228.0/22 -103.24.248.0/22 -103.24.252.0/22 -103.25.8.0/23 -103.25.20.0/22 -103.25.24.0/22 -103.25.28.0/22 -103.25.32.0/22 -103.25.36.0/22 -103.25.40.0/22 -103.25.48.0/22 -103.25.64.0/22 -103.25.68.0/22 -103.25.148.0/22 -103.25.156.0/22 -103.25.216.0/22 -103.26.0.0/22 -103.26.64.0/22 -103.26.76.0/22 -103.26.132.0/22 -103.26.156.0/22 -103.26.160.0/22 -103.26.228.0/22 -103.26.240.0/22 -103.27.4.0/22 -103.27.12.0/22 -103.27.24.0/22 -103.27.56.0/22 -103.27.96.0/22 -103.27.184.0/22 -103.27.208.0/22 -103.27.212.0/22 -103.27.240.0/22 -103.28.4.0/22 -103.28.8.0/22 -103.28.184.0/22 -103.28.204.0/22 -103.28.212.0/22 -103.29.16.0/22 -103.29.128.0/22 -103.29.132.0/22 -103.29.136.0/22 -103.30.20.0/22 -103.30.96.0/22 -103.30.148.0/22 -103.30.200.0/22 -103.30.228.0/22 -103.30.236.0/22 -103.31.0.0/22 -103.31.48.0/22 -103.31.52.0/22 -103.31.56.0/22 -103.31.60.0/22 -103.31.64.0/22 -103.31.68.0/22 -103.31.148.0/22 -103.31.160.0/22 -103.31.168.0/22 -103.31.200.0/22 -103.31.236.0/22 -103.32.0.0/22 -103.32.4.0/22 -103.32.8.0/22 -103.32.12.0/22 -103.32.16.0/22 -103.32.20.0/22 -103.32.24.0/22 -103.32.28.0/22 -103.32.32.0/22 -103.32.36.0/22 -103.32.40.0/22 -103.32.44.0/22 -103.32.48.0/22 -103.32.52.0/22 -103.32.56.0/22 -103.32.60.0/22 -103.32.64.0/22 -103.32.68.0/22 -103.32.72.0/22 -103.32.76.0/22 -103.32.80.0/22 -103.32.84.0/22 -103.32.88.0/22 -103.32.92.0/22 -103.32.96.0/22 -103.32.100.0/22 -103.32.104.0/22 -103.32.108.0/22 -103.32.112.0/22 -103.32.116.0/22 -103.32.120.0/22 -103.32.124.0/22 -103.32.128.0/22 -103.32.132.0/22 -103.32.136.0/22 -103.32.140.0/22 -103.32.144.0/22 -103.32.148.0/22 -103.32.152.0/22 -103.32.156.0/22 -103.32.160.0/22 -103.32.164.0/22 -103.32.168.0/22 -103.32.172.0/22 -103.32.176.0/22 -103.32.180.0/22 -103.32.184.0/22 -103.32.188.0/22 -103.32.192.0/22 -103.32.196.0/22 -103.32.200.0/22 -103.32.204.0/22 -103.32.208.0/22 -103.32.212.0/22 -103.32.216.0/22 -103.32.220.0/22 -103.32.224.0/22 -103.32.228.0/22 -103.32.232.0/22 -103.32.236.0/22 -103.32.240.0/22 -103.32.244.0/22 -103.32.248.0/22 -103.32.252.0/22 -103.33.0.0/22 -103.33.4.0/22 -103.33.8.0/22 -103.33.12.0/22 -103.33.16.0/22 -103.33.20.0/22 -103.33.24.0/22 -103.33.28.0/22 -103.33.32.0/22 -103.33.36.0/22 -103.33.40.0/22 -103.33.44.0/22 -103.33.48.0/22 -103.33.52.0/22 -103.33.56.0/22 -103.33.60.0/22 -103.33.64.0/22 -103.33.68.0/22 -103.33.72.0/22 -103.33.76.0/22 -103.33.80.0/22 -103.33.84.0/22 -103.33.88.0/22 -103.33.92.0/22 -103.33.96.0/22 -103.33.100.0/22 -103.33.104.0/22 -103.33.108.0/22 -103.33.112.0/22 -103.33.116.0/22 -103.33.120.0/22 -103.33.124.0/22 -103.33.128.0/22 -103.33.132.0/22 -103.33.136.0/22 -103.33.140.0/22 -103.33.144.0/22 -103.33.148.0/22 -103.33.152.0/22 -103.33.156.0/22 -103.33.160.0/22 -103.33.164.0/22 -103.33.168.0/22 -103.33.172.0/22 -103.33.176.0/22 -103.33.180.0/22 -103.33.184.0/22 -103.33.188.0/22 -103.33.192.0/22 -103.33.196.0/22 -103.33.200.0/22 -103.33.204.0/22 -103.33.208.0/22 -103.33.212.0/22 -103.33.216.0/22 -103.33.220.0/22 -103.33.224.0/22 -103.33.228.0/22 -103.33.232.0/22 -103.33.236.0/22 -103.33.240.0/22 -103.33.244.0/22 -103.33.248.0/22 -103.33.252.0/22 -103.34.0.0/22 -103.34.4.0/22 -103.34.8.0/22 -103.34.12.0/22 -103.34.16.0/22 -103.34.20.0/22 -103.34.24.0/22 -103.34.28.0/22 -103.34.32.0/22 -103.34.36.0/22 -103.34.40.0/22 -103.34.44.0/22 -103.34.48.0/22 -103.34.52.0/22 -103.34.56.0/22 -103.34.60.0/22 -103.34.64.0/22 -103.34.68.0/22 -103.34.72.0/22 -103.34.76.0/22 -103.34.80.0/22 -103.34.84.0/22 -103.34.88.0/22 -103.34.92.0/22 -103.34.96.0/22 -103.34.100.0/22 -103.34.104.0/22 -103.34.108.0/22 -103.34.112.0/22 -103.34.116.0/22 -103.34.120.0/22 -103.34.124.0/22 -103.34.128.0/22 -103.34.132.0/22 -103.34.136.0/22 -103.34.140.0/22 -103.34.144.0/22 -103.34.148.0/22 -103.34.152.0/22 -103.34.156.0/22 -103.34.160.0/22 -103.34.164.0/22 -103.34.168.0/22 -103.34.172.0/22 -103.34.176.0/22 -103.34.180.0/22 -103.34.184.0/22 -103.34.188.0/22 -103.34.192.0/22 -103.34.196.0/22 -103.34.200.0/22 -103.34.204.0/22 -103.34.208.0/22 -103.34.212.0/22 -103.34.216.0/22 -103.34.220.0/22 -103.34.224.0/22 -103.34.228.0/22 -103.34.232.0/22 -103.34.236.0/22 -103.34.240.0/22 -103.34.244.0/22 -103.34.248.0/22 -103.34.252.0/22 -103.35.0.0/22 -103.35.4.0/22 -103.35.8.0/22 -103.35.12.0/22 -103.35.16.0/22 -103.35.20.0/22 -103.35.24.0/22 -103.35.28.0/22 -103.35.32.0/22 -103.35.36.0/22 -103.35.40.0/22 -103.35.44.0/22 -103.35.48.0/22 -103.35.104.0/22 -103.35.116.0/22 -103.35.180.0/22 -103.35.200.0/22 -103.35.220.0/22 -103.36.28.0/22 -103.36.36.0/22 -103.36.56.0/22 -103.36.60.0/22 -103.36.64.0/22 -103.36.72.0/22 -103.36.96.0/22 -103.36.132.0/22 -103.36.136.0/22 -103.36.160.0/22 -103.36.164.0/22 -103.36.168.0/22 -103.36.172.0/22 -103.36.176.0/22 -103.36.180.0/22 -103.36.184.0/22 -103.36.188.0/22 -103.36.192.0/22 -103.36.196.0/22 -103.36.200.0/22 -103.36.204.0/22 -103.36.208.0/22 -103.36.212.0/22 -103.36.216.0/22 -103.36.220.0/22 -103.36.224.0/22 -103.36.228.0/22 -103.36.232.0/22 -103.36.236.0/22 -103.36.240.0/22 -103.36.244.0/22 -103.37.0.0/22 -103.37.12.0/22 -103.37.16.0/22 -103.37.24.0/22 -103.37.44.0/22 -103.37.52.0/22 -103.37.56.0/22 -103.37.72.0/22 -103.37.100.0/22 -103.37.104.0/22 -103.37.124.0/22 -103.37.136.0/22 -103.37.140.0/22 -103.37.144.0/22 -103.37.148.0/22 -103.37.152.0/22 -103.37.156.0/22 -103.37.160.0/22 -103.37.164.0/22 -103.37.172.0/22 -103.37.176.0/22 -103.37.188.0/22 -103.37.208.0/22 -103.37.212.0/22 -103.37.216.0/22 -103.37.220.0/22 -103.37.248.0/22 -103.37.252.0/22 -103.38.0.0/22 -103.38.32.0/22 -103.38.40.0/22 -103.38.44.0/22 -103.38.56.0/22 -103.38.76.0/22 -103.38.84.0/22 -103.38.92.0/22 -103.38.96.0/22 -103.38.116.0/22 -103.38.132.0/22 -103.38.140.0/22 -103.38.224.0/22 -103.38.228.0/22 -103.38.232.0/22 -103.39.16.0/22 -103.39.64.0/22 -103.39.88.0/22 -103.39.100.0/22 -103.39.104.0/22 -103.39.108.0/22 -103.39.160.0/22 -103.39.164.0/22 -103.39.168.0/22 -103.39.172.0/22 -103.39.176.0/22 -103.39.180.0/22 -103.39.184.0/22 -103.39.188.0/22 -103.39.200.0/22 -103.39.204.0/22 -103.39.208.0/22 -103.39.212.0/22 -103.39.216.0/22 -103.39.220.0/22 -103.39.224.0/22 -103.39.228.0/22 -103.39.232.0/22 -103.40.12.0/22 -103.40.16.0/22 -103.40.20.0/22 -103.40.24.0/22 -103.40.28.0/22 -103.40.32.0/22 -103.40.36.0/22 -103.40.40.0/22 -103.40.44.0/22 -103.40.88.0/22 -103.40.100.0/22 -103.40.192.0/22 -103.40.212.0/22 -103.40.220.0/22 -103.40.228.0/22 -103.40.232.0/22 -103.40.236.0/22 -103.40.240.0/22 -103.40.244.0/22 -103.40.248.0/22 -103.40.252.0/22 -103.41.0.0/22 -103.41.16.0/22 -103.41.52.0/22 -103.41.116.0/22 -103.41.140.0/22 -103.41.148.0/22 -103.41.152.0/22 -103.41.160.0/22 -103.41.164.0/22 -103.41.220.0/22 -103.41.224.0/22 -103.41.228.0/22 -103.41.232.0/22 -103.42.8.0/22 -103.42.24.0/22 -103.42.28.0/22 -103.42.32.0/22 -103.42.64.0/22 -103.42.68.0/22 -103.42.76.0/22 -103.42.104.0/22 -103.42.180.0/22 -103.42.232.0/22 -103.43.16.0/22 -103.43.84.0/22 -103.43.96.0/22 -103.43.100.0/22 -103.43.104.0/22 -103.43.124.0/22 -103.43.184.0/22 -103.43.192.0/22 -103.43.196.0/22 -103.43.208.0/22 -103.43.220.0/22 -103.43.224.0/22 -103.43.240.0/22 -103.44.56.0/22 -103.44.80.0/22 -103.44.88.0/22 -103.44.120.0/22 -103.44.124.0/22 -103.44.132.0/22 -103.44.144.0/22 -103.44.168.0/22 -103.44.176.0/22 -103.44.180.0/22 -103.44.184.0/22 -103.44.188.0/22 -103.44.192.0/22 -103.44.196.0/22 -103.44.200.0/22 -103.44.204.0/22 -103.44.224.0/22 -103.44.236.0/22 -103.44.240.0/22 -103.44.244.0/22 -103.44.248.0/22 -103.44.252.0/22 -103.45.0.0/22 -103.45.4.0/22 -103.45.8.0/22 -103.45.12.0/22 -103.45.16.0/22 -103.45.20.0/22 -103.45.24.0/22 -103.45.28.0/22 -103.45.32.0/22 -103.45.36.0/22 -103.45.40.0/22 -103.45.44.0/22 -103.45.48.0/22 -103.45.52.0/22 -103.45.56.0/22 -103.45.60.0/22 -103.45.72.0/22 -103.45.76.0/22 -103.45.80.0/22 -103.45.84.0/22 -103.45.88.0/22 -103.45.92.0/22 -103.45.96.0/22 -103.45.100.0/22 -103.45.104.0/22 -103.45.108.0/22 -103.45.112.0/22 -103.45.116.0/22 -103.45.120.0/22 -103.45.124.0/22 -103.45.128.0/22 -103.45.132.0/22 -103.45.136.0/22 -103.45.140.0/22 -103.45.144.0/22 -103.45.148.0/22 -103.45.152.0/22 -103.45.156.0/22 -103.45.160.0/22 -103.45.164.0/22 -103.45.168.0/22 -103.45.172.0/22 -103.45.176.0/22 -103.45.180.0/22 -103.45.184.0/22 -103.45.188.0/22 -103.45.192.0/22 -103.45.196.0/22 -103.45.200.0/22 -103.45.204.0/22 -103.45.208.0/22 -103.45.212.0/22 -103.45.216.0/22 -103.45.220.0/22 -103.45.224.0/22 -103.45.248.0/22 -103.46.0.0/22 -103.46.12.0/22 -103.46.16.0/22 -103.46.20.0/22 -103.46.24.0/22 -103.46.28.0/22 -103.46.32.0/22 -103.46.36.0/22 -103.46.40.0/22 -103.46.44.0/22 -103.46.48.0/22 -103.46.52.0/22 -103.46.56.0/22 -103.46.60.0/22 -103.46.64.0/22 -103.46.68.0/22 -103.46.72.0/22 -103.46.76.0/22 -103.46.80.0/22 -103.46.84.0/22 -103.46.88.0/22 -103.46.92.0/22 -103.46.96.0/22 -103.46.100.0/22 -103.46.104.0/22 -103.46.108.0/22 -103.46.112.0/22 -103.46.116.0/22 -103.46.120.0/22 -103.46.124.0/22 -103.46.128.0/22 -103.46.132.0/22 -103.46.136.0/22 -103.46.152.0/22 -103.46.156.0/22 -103.46.160.0/22 -103.46.164.0/22 -103.46.168.0/22 -103.46.172.0/22 -103.46.176.0/22 -103.46.180.0/22 -103.46.244.0/22 -103.46.248.0/22 -103.47.4.0/22 -103.47.20.0/22 -103.47.36.0/22 -103.47.40.0/22 -103.47.48.0/22 -103.47.80.0/22 -103.47.96.0/22 -103.47.108.0/22 -103.47.116.0/22 -103.47.120.0/22 -103.47.136.0/22 -103.47.140.0/22 -103.47.212.0/22 -103.48.52.0/22 -103.48.92.0/22 -103.48.144.0/22 -103.48.148.0/22 -103.48.152.0/22 -103.48.156.0/22 -103.48.202.0/23 -103.48.216.0/22 -103.48.220.0/22 -103.48.224.0/22 -103.48.228.0/22 -103.48.232.0/22 -103.48.236.0/22 -103.48.240.0/22 -103.48.244.0/22 -103.49.12.0/22 -103.49.20.0/22 -103.49.72.0/22 -103.49.76.0/22 -103.49.92.0/22 -103.49.96.0/22 -103.49.108.0/22 -103.49.128.0/22 -103.49.176.0/22 -103.49.180.0/22 -103.49.196.0/22 -103.50.36.0/22 -103.50.44.0/22 -103.50.48.0/22 -103.50.52.0/22 -103.50.56.0/22 -103.50.60.0/22 -103.50.64.0/22 -103.50.68.0/22 -103.50.72.0/22 -103.50.108.0/22 -103.50.112.0/22 -103.50.116.0/22 -103.50.120.0/22 -103.50.124.0/22 -103.50.132.0/22 -103.50.136.0/22 -103.50.140.0/22 -103.50.172.0/22 -103.50.176.0/22 -103.50.180.0/22 -103.50.184.0/22 -103.50.188.0/22 -103.50.192.0/22 -103.50.196.0/22 -103.50.200.0/22 -103.50.220.0/22 -103.50.224.0/22 -103.50.228.0/22 -103.50.232.0/22 -103.50.236.0/22 -103.50.240.0/22 -103.50.244.0/22 -103.50.248.0/22 -103.52.40.0/22 -103.52.72.0/22 -103.52.76.0/22 -103.52.80.0/22 -103.52.84.0/22 -103.52.96.0/22 -103.52.100.0/22 -103.52.104.0/22 -103.52.160.0/22 -103.52.164.0/22 -103.52.172.0/22 -103.52.176.0/22 -103.52.184.0/22 -103.52.196.0/22 -103.53.64.0/22 -103.53.68.0/22 -103.53.92.0/22 -103.53.100.0/22 -103.53.124.0/22 -103.53.128.0/22 -103.53.132.0/22 -103.53.136.0/22 -103.53.140.0/22 -103.53.144.0/22 -103.53.180.0/22 -103.53.204.0/22 -103.53.208.0/22 -103.53.212.0/22 -103.53.216.0/22 -103.53.236.0/22 -103.53.248.0/22 -103.54.8.0/22 -103.54.48.0/22 -103.54.60.0/22 -103.54.160.0/22 -103.54.164.0/22 -103.54.212.0/22 -103.54.240.0/22 -103.55.24.0/22 -103.55.80.0/22 -103.55.120.0/22 -103.55.152.0/22 -103.55.172.0/22 -103.55.204.0/22 -103.55.208.0/22 -103.55.228.0/22 -103.55.236.0/22 -103.56.8.0/22 -103.56.16.0/22 -103.56.20.0/22 -103.56.32.0/22 -103.56.56.0/22 -103.56.60.0/22 -103.56.72.0/22 -103.56.76.0/22 -103.56.100.0/22 -103.56.104.0/22 -103.56.140.0/22 -103.56.152.0/22 -103.56.184.0/22 -103.56.200.0/22 -103.57.12.0/22 -103.57.52.0/22 -103.57.56.0/22 -103.57.76.0/22 -103.57.136.0/22 -103.57.196.0/22 -103.58.24.0/22 -103.59.76.0/22 -103.59.100.0/22 -103.59.112.0/22 -103.59.116.0/22 -103.59.120.0/22 -103.59.124.0/22 -103.59.128.0/22 -103.59.148.0/22 -103.59.164.0/22 -103.60.32.0/22 -103.60.44.0/22 -103.60.164.0/22 -103.60.228.0/22 -103.60.236.0/22 -103.61.60.0/22 -103.61.104.0/22 -103.61.140.0/22 -103.61.152.0/22 -103.61.156.0/22 -103.61.160.0/22 -103.61.172.0/22 -103.61.176.0/22 -103.61.188.0/22 -103.62.24.0/22 -103.62.52.0/22 -103.62.72.0/22 -103.62.76.0/22 -103.62.80.0/22 -103.62.84.0/22 -103.62.88.0/22 -103.62.96.0/22 -103.62.100.0/22 -103.62.104.0/22 -103.62.108.0/22 -103.62.112.0/22 -103.62.116.0/22 -103.62.120.0/22 -103.62.124.0/22 -103.62.128.0/22 -103.62.132.0/22 -103.62.156.0/22 -103.62.160.0/22 -103.62.164.0/22 -103.62.168.0/22 -103.62.172.0/22 -103.62.176.0/22 -103.62.180.0/22 -103.62.184.0/22 -103.62.188.0/22 -103.62.192.0/22 -103.62.204.0/22 -103.62.208.0/22 -103.62.212.0/22 -103.62.216.0/22 -103.62.220.0/22 -103.62.224.0/22 -103.63.32.0/22 -103.63.36.0/22 -103.63.40.0/22 -103.63.44.0/22 -103.63.48.0/22 -103.63.52.0/22 -103.63.56.0/22 -103.63.60.0/22 -103.63.64.0/22 -103.63.68.0/22 -103.63.72.0/22 -103.63.76.0/22 -103.63.80.0/22 -103.63.84.0/22 -103.63.88.0/22 -103.63.140.0/22 -103.63.144.0/22 -103.63.152.0/22 -103.63.160.0/22 -103.63.164.0/22 -103.63.168.0/22 -103.63.172.0/22 -103.63.176.0/22 -103.63.180.0/22 -103.63.184.0/22 -103.63.192.0/22 -103.63.196.0/22 -103.63.200.0/22 -103.63.204.0/22 -103.63.208.0/22 -103.63.240.0/22 -103.63.244.0/22 -103.63.248.0/22 -103.63.252.0/22 -103.64.0.0/22 -103.64.4.0/22 -103.64.24.0/22 -103.64.28.0/22 -103.64.32.0/22 -103.64.36.0/22 -103.64.40.0/22 -103.64.44.0/22 -103.64.48.0/22 -103.64.52.0/22 -103.64.56.0/22 -103.64.60.0/22 -103.64.64.0/22 -103.64.68.0/22 -103.64.72.0/22 -103.64.76.0/22 -103.64.80.0/22 -103.64.84.0/22 -103.64.88.0/22 -103.64.92.0/22 -103.64.96.0/22 -103.64.100.0/22 -103.64.104.0/22 -103.64.108.0/22 -103.64.112.0/22 -103.64.116.0/22 -103.64.120.0/22 -103.64.124.0/22 -103.64.140.0/22 -103.64.144.0/22 -103.64.152.0/22 -103.64.156.0/22 -103.64.160.0/22 -103.64.164.0/22 -103.64.168.0/22 -103.64.172.0/22 -103.64.176.0/22 -103.64.180.0/22 -103.64.184.0/22 -103.64.188.0/22 -103.64.192.0/22 -103.64.196.0/22 -103.64.200.0/22 -103.64.204.0/22 -103.64.208.0/22 -103.64.212.0/22 -103.64.216.0/22 -103.64.220.0/22 -103.64.224.0/22 -103.64.228.0/22 -103.64.232.0/22 -103.64.236.0/22 -103.64.240.0/22 -103.64.244.0/22 -103.64.248.0/22 -103.64.252.0/22 -103.65.0.0/22 -103.65.4.0/22 -103.65.8.0/22 -103.65.12.0/22 -103.65.16.0/22 -103.65.36.0/22 -103.65.40.0/22 -103.65.48.0/22 -103.65.52.0/22 -103.65.56.0/22 -103.65.60.0/22 -103.65.64.0/22 -103.65.68.0/22 -103.65.72.0/22 -103.65.76.0/22 -103.65.80.0/22 -103.65.84.0/22 -103.65.88.0/22 -103.65.92.0/22 -103.65.100.0/22 -103.65.104.0/22 -103.65.108.0/22 -103.65.112.0/22 -103.65.144.0/22 -103.65.148.0/22 -103.65.152.0/22 -103.65.156.0/22 -103.65.160.0/22 -103.65.164.0/22 -103.65.168.0/22 -103.65.172.0/22 -103.66.32.0/22 -103.66.40.0/22 -103.66.92.0/22 -103.66.108.0/22 -103.66.200.0/22 -103.66.216.0/22 -103.66.240.0/22 -103.66.244.0/22 -103.66.248.0/22 -103.66.252.0/22 -103.67.0.0/22 -103.67.4.0/22 -103.67.8.0/22 -103.67.100.0/22 -103.67.104.0/22 -103.67.108.0/22 -103.67.112.0/22 -103.67.116.0/22 -103.67.120.0/22 -103.67.124.0/22 -103.67.128.0/22 -103.67.132.0/22 -103.67.136.0/22 -103.67.140.0/22 -103.67.144.0/22 -103.67.148.0/22 -103.67.172.0/22 -103.67.192.0/22 -103.67.212.0/22 -103.67.252.0/22 -103.68.64.0/22 -103.68.88.0/22 -103.68.100.0/22 -103.68.128.0/22 -103.68.192.0/22 -103.69.16.0/22 -103.69.116.0/22 -103.69.132.0/22 -103.69.152.0/22 -103.69.212.0/22 -103.70.8.0/22 -103.70.148.0/22 -103.70.184.0/22 -103.70.220.0/22 -103.70.224.0/22 -103.70.236.0/22 -103.70.252.0/22 -103.71.0.0/22 -103.71.32.0/22 -103.71.48.0/22 -103.71.68.0/22 -103.71.72.0/22 -103.71.80.0/22 -103.71.84.0/22 -103.71.88.0/22 -103.71.120.0/22 -103.71.124.0/22 -103.71.128.0/22 -103.71.144.0/22 -103.71.196.0/22 -103.71.200.0/22 -103.71.232.0/22 -103.72.12.0/22 -103.72.16.0/22 -103.72.20.0/22 -103.72.24.0/22 -103.72.28.0/22 -103.72.32.0/22 -103.72.36.0/22 -103.72.40.0/22 -103.72.44.0/22 -103.72.48.0/22 -103.72.52.0/22 -103.72.112.0/22 -103.72.116.0/22 -103.72.120.0/22 -103.72.124.0/22 -103.72.128.0/22 -103.72.132.0/22 -103.72.144.0/22 -103.72.148.0/22 -103.72.172.0/22 -103.72.180.0/22 -103.72.224.0/22 -103.72.228.0/22 -103.72.232.0/22 -103.72.236.0/22 -103.72.240.0/22 -103.72.244.0/22 -103.72.248.0/22 -103.72.252.0/22 -103.73.0.0/22 -103.73.4.0/22 -103.73.8.0/22 -103.73.12.0/22 -103.73.16.0/22 -103.73.20.0/22 -103.73.24.0/22 -103.73.28.0/22 -103.73.48.0/22 -103.73.88.0/22 -103.73.96.0/22 -103.73.116.0/22 -103.73.120.0/22 -103.73.128.0/22 -103.73.132.0/22 -103.73.136.0/22 -103.73.140.0/22 -103.73.144.0/22 -103.73.168.0/22 -103.73.176.0/22 -103.73.204.0/22 -103.73.208.0/22 -103.73.240.0/22 -103.73.244.0/22 -103.73.248.0/22 -103.74.24.0/22 -103.74.28.0/22 -103.74.32.0/22 -103.74.36.0/22 -103.74.40.0/22 -103.74.44.0/22 -103.74.48.0/22 -103.74.56.0/22 -103.74.60.0/22 -103.74.80.0/22 -103.74.124.0/22 -103.74.148.0/22 -103.74.152.0/22 -103.74.156.0/22 -103.74.204.0/22 -103.74.232.0/22 -103.75.16.0/22 -103.75.88.0/22 -103.75.92.0/22 -103.75.104.0/22 -103.75.108.0/22 -103.75.112.0/22 -103.75.120.0/22 -103.75.128.0/22 -103.75.144.0/22 -103.75.152.0/22 -103.75.236.0/24 -103.76.60.0/22 -103.76.64.0/22 -103.76.68.0/22 -103.76.72.0/22 -103.76.84.0/22 -103.76.92.0/22 -103.76.216.0/22 -103.76.220.0/22 -103.76.224.0/22 -103.77.28.0/22 -103.77.52.0/22 -103.77.56.0/22 -103.77.72.0/22 -103.77.88.0/22 -103.77.92.0/22 -103.77.132.0/22 -103.77.148.0/22 -103.77.220.0/22 -103.78.56.0/22 -103.78.60.0/22 -103.78.64.0/22 -103.78.68.0/22 -103.78.124.0/22 -103.78.172.0/22 -103.78.176.0/22 -103.78.196.0/22 -103.78.228.0/22 -103.79.24.0/22 -103.79.28.0/22 -103.79.36.0/22 -103.79.40.0/22 -103.79.44.0/22 -103.79.52.0/22 -103.79.56.0/22 -103.79.60.0/22 -103.79.64.0/22 -103.79.68.0/22 -103.79.80.0/22 -103.79.84.0/22 -103.79.120.0/22 -103.79.136.0/22 -103.79.188.0/22 -103.79.192.0/22 -103.79.196.0/22 -103.79.200.0/22 -103.79.204.0/22 -103.79.208.0/22 -103.79.212.0/22 -103.79.240.0/22 -103.80.24.0/22 -103.80.28.0/22 -103.80.44.0/22 -103.80.72.0/22 -103.80.176.0/22 -103.80.180.0/22 -103.80.184.0/22 -103.80.192.0/22 -103.80.200.0/22 -103.80.232.0/22 -103.81.4.0/22 -103.81.8.0/22 -103.81.16.0/22 -103.81.20.0/22 -103.81.44.0/22 -103.81.48.0/22 -103.81.96.0/22 -103.81.120.0/22 -103.81.148.0/22 -103.81.164.0/22 -103.81.168.0/22 -103.81.183.0/24 -103.81.184.0/22 -103.81.200.0/22 -103.81.232.0/22 -103.82.52.0/22 -103.82.60.0/22 -103.82.68.0/22 -103.82.84.0/22 -103.82.104.0/22 -103.82.224.0/22 -103.82.236.0/22 -103.83.44.0/22 -103.83.52.0/22 -103.83.60.0/22 -103.83.64.0/22 -103.83.72.0/22 -103.83.112.0/22 -103.83.120.0/22 -103.83.180.0/22 -103.84.0.0/22 -103.84.12.0/22 -103.84.16.0/22 -103.84.20.0/22 -103.84.24.0/22 -103.84.28.0/22 -103.84.48.0/22 -103.84.64.0/22 -103.84.72.0/22 -103.84.92.0/22 -103.84.108.0/22 -103.84.136.0/22 -103.85.20.0/22 -103.85.24.0/22 -103.85.44.0/22 -103.85.48.0/22 -103.85.84.0/22 -103.85.136.0/22 -103.85.144.0/22 -103.85.164.0/22 -103.85.168.0/22 -103.85.172.0/22 -103.85.176.0/22 -103.85.224.0/22 -103.86.28.0/22 -103.86.32.0/22 -103.86.44.0/22 -103.86.60.0/22 -103.86.80.0/22 -103.86.84.0/22 -103.86.88.0/22 -103.86.204.0/22 -103.86.208.0/22 -103.86.212.0/22 -103.86.216.0/22 -103.86.220.0/22 -103.86.224.0/22 -103.86.228.0/22 -103.86.232.0/22 -103.86.236.0/22 -103.86.240.0/22 -103.86.244.0/22 -103.86.248.0/22 -103.86.252.0/22 -103.87.0.0/22 -103.87.4.0/22 -103.87.20.0/22 -103.87.32.0/22 -103.87.72.0/22 -103.87.96.0/22 -103.87.132.0/22 -103.87.180.0/22 -103.87.224.0/22 -103.88.4.0/22 -103.88.8.0/22 -103.88.12.0/22 -103.88.16.0/22 -103.88.20.0/22 -103.88.32.0/22 -103.88.36.0/22 -103.88.60.0/22 -103.88.64.0/22 -103.88.72.0/22 -103.88.96.0/22 -103.88.100.0/22 -103.88.164.0/22 -103.88.176.0/22 -103.88.184.0/22 -103.88.188.0/22 -103.88.212.0/22 -103.89.28.0/22 -103.89.96.0/22 -103.89.100.0/22 -103.89.104.0/22 -103.89.108.0/22 -103.89.112.0/22 -103.89.116.0/22 -103.89.148.0/22 -103.89.172.0/22 -103.89.184.0/22 -103.89.188.0/22 -103.89.192.0/22 -103.89.196.0/22 -103.89.200.0/22 -103.89.204.0/22 -103.89.208.0/22 -103.89.212.0/22 -103.89.216.0/22 -103.89.220.0/22 -103.89.224.0/22 -103.89.228.0/22 -103.90.52.0/22 -103.90.92.0/22 -103.90.100.0/22 -103.90.104.0/22 -103.90.108.0/22 -103.90.112.0/22 -103.90.116.0/22 -103.90.120.0/22 -103.90.124.0/22 -103.90.128.0/22 -103.90.132.0/22 -103.90.152.0/22 -103.90.168.0/22 -103.90.173.0/24 -103.90.176.0/22 -103.90.188.0/22 -103.90.192.0/22 -103.91.36.0/22 -103.91.40.0/22 -103.91.108.0/22 -103.91.152.0/22 -103.91.176.0/22 -103.91.200.0/22 -103.91.208.0/22 -103.91.212.0/22 -103.91.219.0/24 -103.91.236.0/22 -103.91.252.0/22 -103.92.0.0/22 -103.92.4.0/22 -103.92.8.0/22 -103.92.12.0/22 -103.92.48.0/22 -103.92.52.0/22 -103.92.56.0/22 -103.92.60.0/22 -103.92.64.0/22 -103.92.68.0/22 -103.92.72.0/22 -103.92.76.0/22 -103.92.80.0/22 -103.92.86.0/24 -103.92.88.0/22 -103.92.108.0/22 -103.92.124.0/22 -103.92.128.0/24 -103.92.132.0/22 -103.92.156.0/22 -103.92.164.0/22 -103.92.168.0/22 -103.92.172.0/22 -103.92.176.0/22 -103.92.180.0/22 -103.92.184.0/22 -103.92.188.0/22 -103.92.192.0/22 -103.92.236.0/22 -103.92.240.0/22 -103.92.244.0/22 -103.92.248.0/22 -103.92.252.0/22 -103.93.0.0/22 -103.93.4.0/22 -103.93.28.0/22 -103.93.76.0/22 -103.93.84.0/22 -103.93.152.0/22 -103.93.180.0/22 -103.93.204.0/22 -103.94.12.0/22 -103.94.20.0/22 -103.94.28.0/22 -103.94.32.0/22 -103.94.36.0/22 -103.94.40.0/22 -103.94.44.0/22 -103.94.72.0/22 -103.94.88.0/22 -103.94.116.0/22 -103.94.160.0/22 -103.94.180.0/22 -103.94.200.0/22 -103.95.28.0/22 -103.95.52.0/22 -103.95.64.0/22 -103.95.68.0/22 -103.95.88.0/22 -103.95.92.0/22 -103.95.116.0/22 -103.95.128.0/22 -103.95.136.0/22 -103.95.140.0/22 -103.95.144.0/22 -103.95.152.0/22 -103.95.207.0/24 -103.95.216.0/22 -103.95.220.0/22 -103.95.224.0/22 -103.95.236.0/22 -103.95.240.0/22 -103.95.244.0/22 -103.95.248.0/22 -103.95.252.0/22 -103.96.0.0/22 -103.96.8.0/22 -103.96.80.0/22 -103.96.124.0/22 -103.96.136.0/22 -103.96.140.0/24 -103.96.148.0/22 -103.96.152.0/22 -103.96.156.0/22 -103.96.160.0/22 -103.96.164.0/22 -103.96.168.0/22 -103.96.172.0/22 -103.96.176.0/22 -103.96.180.0/22 -103.96.184.0/22 -103.96.188.0/22 -103.96.192.0/22 -103.96.196.0/22 -103.96.200.0/22 -103.96.204.0/22 -103.96.208.0/22 -103.96.212.0/22 -103.96.216.0/22 -103.97.8.0/22 -103.97.12.0/22 -103.97.16.0/22 -103.97.20.0/22 -103.97.24.0/22 -103.97.28.0/22 -103.97.32.0/22 -103.97.36.0/22 -103.97.40.0/22 -103.97.56.0/22 -103.97.60.0/22 -103.97.64.0/22 -103.97.68.0/22 -103.97.72.0/22 -103.97.80.0/22 -103.97.112.0/22 -103.97.116.0/22 -103.97.128.0/22 -103.97.144.0/22 -103.97.148.0/22 -103.97.188.0/22 -103.97.192.0/22 -103.97.224.0/22 -103.97.228.0/23 -103.98.28.0/23 -103.98.40.0/22 -103.98.44.0/22 -103.98.48.0/22 -103.98.56.0/22 -103.98.80.0/22 -103.98.88.0/22 -103.98.92.0/22 -103.98.96.0/22 -103.98.100.0/22 -103.98.124.0/22 -103.98.136.0/22 -103.98.140.0/22 -103.98.144.0/22 -103.98.164.0/22 -103.98.168.0/22 -103.98.180.0/22 -103.98.196.0/22 -103.98.216.0/22 -103.98.220.0/22 -103.98.224.0/22 -103.98.228.0/22 -103.98.232.0/22 -103.98.240.0/22 -103.98.244.0/22 -103.98.248.0/22 -103.98.252.0/22 -103.99.40.0/23 -103.99.52.0/22 -103.99.56.0/22 -103.99.60.0/22 -103.99.76.0/22 -103.99.104.0/22 -103.99.116.0/22 -103.99.120.0/22 -103.99.152.0/22 -103.99.220.0/22 -103.99.232.0/22 -103.99.236.0/22 -103.100.0.0/22 -103.100.32.0/22 -103.100.40.0/22 -103.100.48.0/22 -103.100.52.0/22 -103.100.56.0/22 -103.100.60.0/22 -103.100.64.0/22 -103.100.68.0/22 -103.100.88.0/22 -103.100.116.0/22 -103.100.140.0/22 -103.100.144.0/22 -103.100.236.0/22 -103.100.240.0/22 -103.100.248.0/22 -103.100.252.0/22 -103.101.4.0/22 -103.101.8.0/22 -103.101.12.0/22 -103.101.28.0/22 -103.101.60.0/22 -103.101.120.0/22 -103.101.124.0/22 -103.101.144.0/22 -103.101.148.0/22 -103.101.153.0/24 -103.101.180.0/22 -103.101.184.0/22 -103.102.76.0/22 -103.102.80.0/22 -103.102.168.0/22 -103.102.172.0/22 -103.102.180.0/22 -103.102.184.0/22 -103.102.188.0/22 -103.102.192.0/22 -103.102.196.0/22 -103.102.200.0/22 -103.102.208.0/22 -103.102.212.0/22 -103.103.12.0/22 -103.103.16.0/22 -103.103.36.0/22 -103.103.68.0/22 -103.103.72.0/22 -103.103.176.0/22 -103.103.188.0/22 -103.103.200.0/22 -103.103.204.0/22 -103.103.220.0/22 -103.103.224.0/22 -103.103.228.0/22 -103.103.232.0/22 -103.103.248.0/22 -103.103.252.0/22 -103.104.0.0/22 -103.104.4.0/22 -103.104.36.0/22 -103.104.40.0/22 -103.104.64.0/22 -103.104.104.0/22 -103.104.152.0/22 -103.104.168.0/22 -103.104.172.0/22 -103.104.188.0/22 -103.104.198.0/23 -103.104.252.0/22 -103.105.0.0/22 -103.105.4.0/22 -103.105.12.0/22 -103.105.16.0/22 -103.105.23.0/24 -103.105.56.0/22 -103.105.60.0/22 -103.105.116.0/22 -103.105.132.0/22 -103.105.180.0/22 -103.105.184.0/22 -103.105.200.0/22 -103.105.204.0/22 -103.105.220.0/22 -103.106.36.0/22 -103.106.40.0/22 -103.106.44.0/22 -103.106.60.0/22 -103.106.68.0/22 -103.106.96.0/22 -103.106.120.0/22 -103.106.128.0/22 -103.106.132.0/22 -103.106.160.0/22 -103.106.188.0/22 -103.106.196.0/22 -103.106.202.0/23 -103.106.212.0/22 -103.106.244.0/22 -103.106.252.0/22 -103.107.0.0/22 -103.107.8.0/24 -103.107.28.0/22 -103.107.32.0/22 -103.107.44.0/22 -103.107.72.0/22 -103.107.108.0/22 -103.107.164.0/22 -103.107.168.0/22 -103.107.188.0/22 -103.107.192.0/22 -103.107.208.0/22 -103.107.212.0/22 -103.107.216.0/22 -103.107.220.0/22 -103.108.52.0/22 -103.108.64.0/22 -103.108.160.0/22 -103.108.164.0/22 -103.108.184.0/23 -103.108.188.0/23 -103.108.192.0/22 -103.108.196.0/22 -103.108.208.0/22 -103.108.212.0/22 -103.108.224.0/22 -103.108.244.0/22 -103.108.251.0/24 -103.109.20.0/22 -103.109.48.0/22 -103.109.88.0/22 -103.109.106.0/23 -103.109.248.0/22 -103.110.32.0/22 -103.110.80.0/23 -103.110.92.0/22 -103.110.100.0/22 -103.110.116.0/22 -103.110.127.0/24 -103.110.128.0/23 -103.110.131.0/24 -103.110.132.0/22 -103.110.136.0/22 -103.110.152.0/22 -103.110.156.0/22 -103.110.188.0/22 -103.110.204.0/22 -103.111.64.0/22 -103.111.172.0/22 -103.111.252.0/22 -103.112.28.0/22 -103.112.68.0/22 -103.112.72.0/22 -103.112.88.0/22 -103.112.92.0/22 -103.112.96.0/22 -103.112.108.0/22 -103.112.112.0/22 -103.112.116.0/22 -103.112.140.0/22 -103.112.172.0/22 -103.112.184.0/22 -103.112.208.0/22 -103.113.4.0/22 -103.113.92.0/22 -103.113.144.0/22 -103.113.220.0/22 -103.113.232.0/22 -103.113.236.0/22 -103.114.4.0/22 -103.114.28.0/22 -103.114.68.0/22 -103.114.72.0/22 -103.114.100.0/22 -103.114.132.0/22 -103.114.148.0/22 -103.114.156.0/22 -103.114.176.0/22 -103.114.212.0/22 -103.114.236.0/22 -103.114.240.0/22 -103.115.16.0/22 -103.115.40.0/22 -103.115.44.0/22 -103.115.48.0/22 -103.115.52.0/22 -103.115.56.0/22 -103.115.60.0/22 -103.115.64.0/22 -103.115.68.0/22 -103.115.92.0/22 -103.115.120.0/22 -103.115.148.0/22 -103.115.204.0/23 -103.115.248.0/22 -103.116.20.0/22 -103.116.40.0/22 -103.116.64.0/22 -103.116.72.0/22 -103.116.76.0/22 -103.116.92.0/22 -103.116.120.0/22 -103.116.128.0/22 -103.116.132.0/23 -103.116.148.0/22 -103.116.184.0/22 -103.116.206.0/23 -103.116.220.0/22 -103.116.224.0/22 -103.116.228.0/22 -103.117.16.0/22 -103.117.72.0/22 -103.117.88.0/22 -103.117.132.0/22 -103.117.136.0/22 -103.117.188.0/22 -103.117.220.0/22 -103.118.19.0/24 -103.118.36.0/22 -103.118.52.0/22 -103.118.56.0/22 -103.118.60.0/22 -103.118.64.0/22 -103.118.68.0/22 -103.118.72.0/22 -103.118.88.0/22 -103.118.173.0/24 -103.118.192.0/22 -103.118.196.0/22 -103.118.200.0/22 -103.118.204.0/22 -103.118.208.0/22 -103.118.212.0/22 -103.118.216.0/22 -103.118.220.0/22 -103.118.240.0/22 -103.118.244.0/22 -103.118.248.0/22 -103.118.252.0/22 -103.119.0.0/22 -103.119.12.0/22 -103.119.16.0/22 -103.119.28.0/22 -103.119.44.0/22 -103.119.104.0/22 -103.119.115.0/24 -103.119.156.0/22 -103.119.180.0/22 -103.119.200.0/22 -103.119.224.0/22 -103.120.52.0/22 -103.120.72.0/22 -103.120.88.0/22 -103.120.96.0/22 -103.120.100.0/22 -103.120.140.0/22 -103.120.196.0/22 -103.120.224.0/22 -103.121.52.0/22 -103.121.92.0/22 -103.121.160.0/22 -103.121.164.0/22 -103.121.250.0/24 -103.121.252.0/22 -103.122.48.0/22 -103.122.176.0/22 -103.122.192.0/22 -103.122.240.0/22 -103.123.4.0/22 -103.123.56.0/22 -103.123.88.0/22 -103.123.92.0/22 -103.123.116.0/22 -103.123.160.0/22 -103.123.176.0/22 -103.123.200.0/22 -103.123.204.0/22 -103.123.208.0/22 -103.123.212.0/22 -103.124.24.0/22 -103.124.48.0/22 -103.124.64.0/22 -103.124.212.0/22 -103.124.216.0/22 -103.125.20.0/22 -103.125.44.0/22 -103.125.132.0/22 -103.125.164.0/22 -103.125.196.0/22 -103.125.236.0/22 -103.125.248.0/22 -103.126.0.0/22 -103.126.16.0/22 -103.126.44.0/22 -103.126.100.0/22 -103.126.124.0/22 -103.126.128.0/22 -103.126.132.0/22 -103.126.208.0/22 -103.126.241.0/24 -103.129.52.0/22 -103.130.132.0/22 -103.130.152.0/24 -103.130.160.0/22 -103.130.228.0/22 -103.131.20.0/22 -103.131.36.0/22 -103.131.152.0/22 -103.131.168.0/22 -103.131.176.0/22 -103.131.224.0/22 -103.131.228.0/22 -103.131.240.0/22 -103.132.60.0/22 -103.132.64.0/22 -103.132.68.0/22 -103.132.72.0/22 -103.132.76.0/22 -103.132.80.0/22 -103.132.104.0/22 -103.132.108.0/22 -103.132.112.0/22 -103.132.116.0/22 -103.132.120.0/22 -103.132.160.0/22 -103.132.164.0/22 -103.132.188.0/22 -103.132.208.0/22 -103.132.212.0/22 -103.132.234.0/23 -103.133.12.0/22 -103.133.40.0/22 -103.133.128.0/22 -103.133.136.0/22 -103.133.176.0/22 -103.133.232.0/22 -103.134.12.0/24 -103.134.196.0/22 -103.135.80.0/22 -103.135.124.0/22 -103.135.148.0/22 -103.135.156.0/22 -103.135.160.0/22 -103.135.164.0/22 -103.135.176.0/22 -103.135.184.0/22 -103.135.192.0/22 -103.135.196.0/22 -103.135.236.0/22 -103.136.128.0/22 -103.136.232.0/22 -103.137.58.0/23 -103.137.60.0/24 -103.137.76.0/22 -103.137.136.0/23 -103.137.149.0/24 -103.137.180.0/22 -103.137.236.0/22 -103.138.2.0/23 -103.138.12.0/23 -103.138.80.0/22 -103.138.134.0/23 -103.138.156.0/23 -103.138.208.0/23 -103.138.220.0/23 -103.138.246.0/23 -103.138.248.0/23 -103.139.0.0/23 -103.139.2.0/23 -103.139.22.0/23 -103.139.113.0/24 -103.139.134.0/23 -103.139.136.0/23 -103.139.172.0/23 -103.139.200.0/23 -103.139.204.0/23 -103.139.212.0/23 -103.140.8.0/23 -103.140.14.0/23 -103.140.70.0/23 -103.140.126.0/23 -103.140.140.0/23 -103.140.144.0/23 -103.140.152.0/23 -103.140.192.0/23 -103.140.194.0/23 -103.140.228.0/23 -103.141.10.0/23 -103.141.36.0/23 -103.141.58.0/23 -103.141.128.0/23 -103.141.186.0/23 -103.141.242.0/23 -103.142.28.0/23 -103.142.58.0/23 -103.142.82.0/23 -103.142.96.0/23 -103.142.102.0/23 -103.142.122.0/23 -103.142.128.0/23 -103.142.140.0/23 -103.142.154.0/23 -103.142.156.0/23 -103.142.172.0/23 -103.142.180.0/23 -103.142.186.0/23 -103.142.190.0/23 -103.142.220.0/23 -103.142.230.0/24 -103.142.234.0/23 -103.142.238.0/23 -103.142.248.0/23 -103.143.16.0/23 -103.143.18.0/23 -103.143.31.0/24 -103.143.74.0/23 -103.143.120.0/23 -103.143.124.0/23 -103.143.132.0/23 -103.143.134.0/23 -103.143.174.0/23 -103.143.228.0/23 -103.144.40.0/23 -103.144.52.0/23 -103.144.66.0/23 -103.144.70.0/23 -103.144.72.0/23 -103.144.108.0/23 -103.144.136.0/23 -103.144.148.0/23 -103.144.158.0/23 -103.144.240.0/23 -103.145.38.0/23 -103.145.40.0/23 -103.145.42.0/23 -103.145.60.0/23 -103.145.72.0/23 -103.145.80.0/23 -103.145.86.0/23 -103.145.92.0/23 -103.145.94.0/23 -103.145.98.0/23 -103.145.106.0/23 -103.145.122.0/23 -103.145.188.0/23 -103.145.190.0/23 -103.146.6.0/23 -103.146.72.0/23 -103.146.88.0/23 -103.146.90.0/23 -103.146.124.0/23 -103.146.126.0/23 -103.146.138.0/23 -103.146.230.0/23 -103.146.236.0/23 -103.146.252.0/23 -103.147.12.0/23 -103.147.124.0/23 -103.147.198.0/23 -103.147.206.0/23 -103.148.174.0/23 -103.149.6.0/23 -103.149.17.0/24 -103.149.44.0/23 -103.149.110.0/23 -103.149.132.0/23 -103.149.144.0/23 -103.149.156.0/23 -103.149.181.0/24 -103.149.190.0/23 -103.149.210.0/23 -103.149.214.0/23 -103.149.220.0/23 -103.149.242.0/23 -103.149.244.0/23 -103.149.246.0/23 -103.149.248.0/23 -103.150.24.0/23 -103.150.66.0/23 -103.150.72.0/23 -103.150.122.0/23 -103.150.126.0/23 -103.150.128.0/23 -103.150.130.0/23 -103.150.146.0/23 -103.150.164.0/23 -103.150.172.0/23 -103.150.180.0/23 -103.150.200.0/23 -103.150.210.0/23 -103.150.214.0/23 -103.150.216.0/23 -103.150.244.0/23 -103.151.4.0/23 -103.151.44.0/23 -103.151.138.0/23 -103.151.142.0/23 -103.151.148.0/23 -103.151.150.0/23 -103.151.158.0/23 -103.151.178.0/23 -103.151.206.0/23 -103.151.216.0/23 -103.151.228.0/23 -103.152.14.0/23 -103.152.24.0/23 -103.152.28.0/23 -103.152.30.0/23 -103.152.56.0/23 -103.152.76.0/23 -103.152.80.0/23 -103.152.98.0/23 -103.152.112.0/23 -103.152.120.0/23 -103.152.122.0/23 -103.152.132.0/23 -103.152.152.0/23 -103.152.168.0/23 -103.152.170.0/23 -103.152.186.0/23 -103.152.190.0/23 -103.152.192.0/23 -103.152.200.0/23 -103.152.208.0/23 -103.152.224.0/23 -103.152.226.0/23 -103.152.246.0/23 -103.152.250.0/23 -103.153.4.0/23 -103.153.36.0/23 -103.153.98.0/23 -103.153.100.0/23 -103.153.114.0/23 -103.153.122.0/23 -103.153.128.0/23 -103.153.132.0/23 -103.153.138.0/23 -103.153.146.0/23 -103.153.160.0/23 -103.154.18.0/23 -103.154.30.0/23 -103.154.32.0/23 -103.154.40.0/23 -103.154.66.0/23 -103.154.162.0/23 -103.154.164.0/23 -103.154.168.0/23 -103.154.242.0/23 -103.155.14.0/23 -103.155.16.0/23 -103.155.34.0/23 -103.155.48.0/23 -103.155.76.0/23 -103.155.100.0/23 -103.155.110.0/23 -103.155.120.0/23 -103.155.214.0/23 -103.155.248.0/23 -103.156.24.0/23 -103.156.28.0/23 -103.156.68.0/23 -103.156.78.0/23 -103.156.104.0/23 -103.156.158.0/23 -103.156.166.0/23 -103.156.174.0/23 -103.156.186.0/23 -103.156.228.0/23 -103.157.30.0/23 -103.157.138.0/23 -103.157.174.0/23 -103.157.212.0/23 -103.157.234.0/23 -103.157.254.0/23 -103.158.0.0/23 -103.158.8.0/23 -103.158.13.0/24 -103.158.16.0/23 -103.158.190.0/23 -103.158.200.0/23 -103.158.224.0/23 -103.159.80.0/23 -103.159.122.0/23 -103.159.124.0/23 -103.159.134.0/23 -103.159.142.0/23 -103.160.32.0/23 -103.160.34.0/23 -103.160.112.0/23 -103.160.114.0/23 -103.160.244.0/23 -103.160.254.0/23 -103.161.14.0/23 -103.161.102.0/23 -103.161.138.0/23 -103.161.208.0/23 -103.161.220.0/23 -103.161.254.0/23 -103.162.10.0/23 -103.162.32.0/23 -103.162.38.0/23 -103.162.116.0/23 -103.163.28.0/23 -103.163.32.0/23 -103.163.46.0/23 -103.163.74.0/23 -103.163.180.0/23 -103.164.4.0/23 -103.164.32.0/23 -103.164.40.0/23 -103.164.42.0/23 -103.164.64.0/23 -103.164.76.0/23 -103.164.178.0/23 -103.192.0.0/22 -103.192.4.0/22 -103.192.8.0/22 -103.192.12.0/22 -103.192.16.0/22 -103.192.20.0/22 -103.192.24.0/22 -103.192.28.0/22 -103.192.48.0/22 -103.192.52.0/22 -103.192.56.0/22 -103.192.84.0/22 -103.192.88.0/22 -103.192.92.0/22 -103.192.96.0/22 -103.192.100.0/22 -103.192.104.0/22 -103.192.108.0/22 -103.192.112.0/22 -103.192.128.0/22 -103.192.132.0/22 -103.192.136.0/22 -103.192.140.0/22 -103.192.144.0/22 -103.192.164.0/22 -103.192.188.0/22 -103.192.208.0/22 -103.192.212.0/22 -103.192.216.0/22 -103.192.252.0/22 -103.193.40.0/22 -103.193.44.0/22 -103.193.120.0/22 -103.193.124.0/22 -103.193.140.0/22 -103.193.144.0/22 -103.193.160.0/22 -103.193.188.0/22 -103.193.192.0/22 -103.193.212.0/22 -103.193.216.0/22 -103.193.220.0/22 -103.193.224.0/22 -103.193.228.0/22 -103.193.232.0/22 -103.193.236.0/22 -103.193.240.0/22 -103.194.16.0/22 -103.195.104.0/22 -103.195.112.0/22 -103.195.136.0/22 -103.195.148.0/22 -103.195.152.0/22 -103.195.160.0/22 -103.196.64.0/22 -103.196.72.0/22 -103.196.88.0/22 -103.196.92.0/22 -103.196.96.0/22 -103.196.168.0/22 -103.196.204.0/22 -103.197.180.0/22 -103.197.228.0/22 -103.198.20.0/22 -103.198.60.0/22 -103.198.64.0/22 -103.198.72.0/22 -103.198.124.0/22 -103.198.156.0/22 -103.198.180.0/22 -103.198.196.0/22 -103.198.200.0/22 -103.198.216.0/22 -103.198.220.0/22 -103.198.224.0/22 -103.198.228.0/22 -103.198.232.0/22 -103.198.236.0/22 -103.198.240.0/22 -103.198.244.0/22 -103.199.164.0/22 -103.199.196.0/22 -103.199.228.0/22 -103.199.248.0/22 -103.199.252.0/22 -103.200.28.0/22 -103.200.52.0/22 -103.200.64.0/22 -103.200.68.0/22 -103.200.136.0/22 -103.200.140.0/22 -103.200.144.0/22 -103.200.148.0/22 -103.200.152.0/22 -103.200.156.0/22 -103.200.160.0/22 -103.200.164.0/22 -103.200.168.0/22 -103.200.172.0/22 -103.200.176.0/22 -103.200.180.0/22 -103.200.184.0/22 -103.200.188.0/22 -103.200.192.0/22 -103.200.220.0/22 -103.200.224.0/22 -103.200.228.0/22 -103.200.232.0/22 -103.200.236.0/22 -103.200.240.0/22 -103.200.244.0/22 -103.200.248.0/22 -103.200.252.0/22 -103.201.0.0/22 -103.201.4.0/22 -103.201.8.0/22 -103.201.12.0/22 -103.201.16.0/22 -103.201.20.0/22 -103.201.28.0/22 -103.201.32.0/22 -103.201.36.0/22 -103.201.40.0/22 -103.201.44.0/22 -103.201.48.0/22 -103.201.52.0/22 -103.201.56.0/22 -103.201.60.0/22 -103.201.64.0/22 -103.201.76.0/22 -103.201.80.0/22 -103.201.84.0/22 -103.201.88.0/22 -103.201.92.0/22 -103.201.96.0/22 -103.201.100.0/22 -103.201.104.0/22 -103.201.108.0/22 -103.201.112.0/22 -103.201.116.0/22 -103.201.120.0/22 -103.201.152.0/22 -103.201.156.0/22 -103.201.160.0/22 -103.201.164.0/22 -103.201.168.0/22 -103.201.172.0/22 -103.201.176.0/22 -103.201.180.0/22 -103.201.184.0/22 -103.201.188.0/22 -103.201.192.0/22 -103.201.196.0/22 -103.201.200.0/22 -103.201.204.0/22 -103.201.208.0/22 -103.201.212.0/22 -103.201.216.0/22 -103.201.220.0/22 -103.201.224.0/22 -103.201.228.0/22 -103.201.232.0/22 -103.201.236.0/22 -103.201.240.0/22 -103.201.244.0/22 -103.201.248.0/22 -103.201.252.0/22 -103.202.0.0/22 -103.202.4.0/22 -103.202.8.0/22 -103.202.12.0/22 -103.202.16.0/22 -103.202.20.0/22 -103.202.24.0/22 -103.202.28.0/22 -103.202.32.0/22 -103.202.36.0/22 -103.202.40.0/22 -103.202.44.0/22 -103.202.56.0/22 -103.202.60.0/22 -103.202.64.0/22 -103.202.68.0/22 -103.202.72.0/22 -103.202.76.0/22 -103.202.80.0/22 -103.202.84.0/22 -103.202.88.0/22 -103.202.92.0/22 -103.202.96.0/22 -103.202.100.0/22 -103.202.104.0/22 -103.202.108.0/22 -103.202.112.0/22 -103.202.116.0/22 -103.202.120.0/22 -103.202.124.0/22 -103.202.128.0/22 -103.202.132.0/22 -103.202.136.0/22 -103.202.140.0/22 -103.202.144.0/22 -103.202.152.0/22 -103.202.156.0/22 -103.202.160.0/22 -103.202.164.0/22 -103.202.168.0/22 -103.202.172.0/22 -103.202.176.0/22 -103.202.180.0/22 -103.202.184.0/22 -103.202.188.0/22 -103.202.192.0/22 -103.202.196.0/22 -103.202.200.0/21 -103.202.212.0/22 -103.202.228.0/22 -103.202.236.0/22 -103.202.240.0/22 -103.202.244.0/22 -103.202.248.0/22 -103.202.252.0/22 -103.203.0.0/22 -103.203.4.0/22 -103.203.8.0/22 -103.203.12.0/22 -103.203.16.0/22 -103.203.20.0/22 -103.203.24.0/22 -103.203.28.0/22 -103.203.32.0/22 -103.203.56.0/22 -103.203.96.0/22 -103.203.100.0/22 -103.203.104.0/22 -103.203.108.0/22 -103.203.112.0/22 -103.203.116.0/22 -103.203.120.0/22 -103.203.124.0/22 -103.203.128.0/22 -103.203.140.0/22 -103.203.164.0/22 -103.203.168.0/22 -103.203.192.0/22 -103.203.200.0/22 -103.203.212.0/22 -103.203.216.0/22 -103.204.24.0/22 -103.204.72.0/22 -103.204.88.0/22 -103.204.112.0/22 -103.204.136.0/22 -103.204.140.0/22 -103.204.144.0/22 -103.204.148.0/22 -103.204.152.0/22 -103.204.196.0/22 -103.204.232.0/22 -103.204.236.0/22 -103.205.4.0/22 -103.205.8.0/22 -103.205.40.0/22 -103.205.44.0/22 -103.205.52.0/22 -103.205.108.0/22 -103.205.116.0/22 -103.205.120.0/22 -103.205.136.0/22 -103.205.162.0/24 -103.205.188.0/22 -103.205.192.0/22 -103.205.196.0/22 -103.205.200.0/22 -103.205.236.0/22 -103.205.248.0/22 -103.205.252.0/22 -103.206.0.0/22 -103.206.44.0/22 -103.206.148.0/22 -103.207.48.0/22 -103.207.104.0/22 -103.207.164.0/22 -103.207.184.0/22 -103.207.188.0/22 -103.207.192.0/22 -103.207.196.0/22 -103.207.200.0/22 -103.207.204.0/22 -103.207.208.0/22 -103.207.212.0/22 -103.207.220.0/22 -103.207.228.0/22 -103.207.232.0/22 -103.208.12.0/22 -103.208.16.0/22 -103.208.28.0/22 -103.208.40.0/22 -103.208.44.0/22 -103.208.48.0/22 -103.208.148.0/22 -103.209.112.0/22 -103.209.136.0/22 -103.209.200.0/22 -103.209.208.0/22 -103.209.216.0/22 -103.210.0.0/22 -103.210.20.0/22 -103.210.96.0/22 -103.210.156.0/22 -103.210.160.0/22 -103.210.164.0/22 -103.210.168.0/22 -103.210.172.0/22 -103.210.176.0/22 -103.210.180.0/22 -103.210.184.0/22 -103.210.188.0/22 -103.210.216.0/22 -103.211.44.0/22 -103.211.96.0/22 -103.211.100.0/22 -103.211.156.0/22 -103.211.164.0/22 -103.211.192.0/22 -103.211.220.0/22 -103.211.224.0/22 -103.211.248.0/22 -103.212.0.0/22 -103.212.4.0/22 -103.212.8.0/22 -103.212.12.0/22 -103.212.32.0/22 -103.212.44.0/22 -103.212.48.0/22 -103.212.84.0/22 -103.212.100.0/22 -103.212.104.0/22 -103.212.108.0/22 -103.212.148.0/22 -103.212.164.0/22 -103.212.196.0/22 -103.212.200.0/22 -103.212.228.0/22 -103.212.252.0/22 -103.213.40.0/22 -103.213.44.0/22 -103.213.48.0/22 -103.213.52.0/22 -103.213.56.0/22 -103.213.60.0/22 -103.213.64.0/22 -103.213.68.0/22 -103.213.72.0/22 -103.213.76.0/22 -103.213.80.0/22 -103.213.84.0/22 -103.213.88.0/22 -103.213.92.0/22 -103.213.96.0/22 -103.213.132.0/22 -103.213.136.0/22 -103.213.140.0/22 -103.213.144.0/22 -103.213.148.0/22 -103.213.152.0/22 -103.213.156.0/22 -103.213.160.0/22 -103.213.164.0/22 -103.213.168.0/22 -103.213.172.0/22 -103.213.176.0/22 -103.213.180.0/22 -103.213.184.0/22 -103.213.188.0/22 -103.213.248.0/22 -103.214.32.0/22 -103.214.48.0/22 -103.214.84.0/22 -103.214.168.0/22 -103.214.212.0/22 -103.214.240.0/22 -103.214.244.0/22 -103.215.28.0/22 -103.215.32.0/22 -103.215.36.0/22 -103.215.44.0/22 -103.215.48.0/22 -103.215.100.0/22 -103.215.104.0/22 -103.215.108.0/22 -103.215.116.0/22 -103.215.120.0/22 -103.215.140.0/22 -103.215.228.0/22 -103.216.4.0/22 -103.216.8.0/22 -103.216.12.0/22 -103.216.16.0/22 -103.216.20.0/22 -103.216.24.0/22 -103.216.28.0/22 -103.216.32.0/22 -103.216.36.0/22 -103.216.40.0/22 -103.216.44.0/22 -103.216.64.0/22 -103.216.108.0/22 -103.216.136.0/22 -103.216.152.0/22 -103.216.224.0/22 -103.216.228.0/22 -103.216.240.0/22 -103.216.244.0/22 -103.216.248.0/22 -103.216.252.0/22 -103.217.0.0/22 -103.217.4.0/22 -103.217.8.0/22 -103.217.12.0/22 -103.217.16.0/22 -103.217.20.0/22 -103.217.24.0/22 -103.217.28.0/22 -103.217.32.0/22 -103.217.36.0/22 -103.217.40.0/22 -103.217.44.0/22 -103.217.48.0/22 -103.217.52.0/22 -103.217.56.0/22 -103.217.60.0/22 -103.217.168.0/22 -103.217.180.0/22 -103.217.184.0/22 -103.217.188.0/22 -103.217.192.0/22 -103.217.196.0/22 -103.217.200.0/22 -103.217.204.0/22 -103.218.0.0/22 -103.218.8.0/22 -103.218.12.0/22 -103.218.16.0/22 -103.218.20.0/22 -103.218.28.0/22 -103.218.32.0/22 -103.218.36.0/22 -103.218.40.0/22 -103.218.44.0/22 -103.218.48.0/22 -103.218.52.0/22 -103.218.56.0/22 -103.218.60.0/22 -103.218.64.0/22 -103.218.68.0/22 -103.218.72.0/22 -103.218.76.0/22 -103.218.80.0/22 -103.218.84.0/22 -103.218.88.0/22 -103.218.92.0/22 -103.218.192.0/22 -103.218.196.0/22 -103.218.200.0/22 -103.218.204.0/22 -103.218.208.0/22 -103.218.212.0/22 -103.218.216.0/22 -103.219.24.0/22 -103.219.28.0/22 -103.219.32.0/22 -103.219.36.0/22 -103.219.64.0/22 -103.219.84.0/22 -103.219.88.0/22 -103.219.92.0/22 -103.219.96.0/22 -103.219.100.0/22 -103.219.176.0/22 -103.219.184.0/22 -103.220.48.0/22 -103.220.52.0/22 -103.220.56.0/22 -103.220.60.0/22 -103.220.64.0/22 -103.220.92.0/22 -103.220.96.0/22 -103.220.100.0/22 -103.220.104.0/22 -103.220.108.0/22 -103.220.116.0/22 -103.220.120.0/22 -103.220.124.0/22 -103.220.128.0/22 -103.220.132.0/22 -103.220.136.0/22 -103.220.140.0/22 -103.220.144.0/22 -103.220.148.0/22 -103.220.152.0/22 -103.220.160.0/22 -103.220.164.0/22 -103.220.168.0/22 -103.220.172.0/22 -103.220.176.0/22 -103.220.180.0/22 -103.220.184.0/22 -103.220.188.0/22 -103.220.192.0/22 -103.220.196.0/22 -103.220.200.0/22 -103.220.240.0/22 -103.220.244.0/22 -103.220.248.0/22 -103.220.252.0/22 -103.221.0.0/22 -103.221.4.0/22 -103.221.8.0/22 -103.221.12.0/22 -103.221.16.0/22 -103.221.20.0/22 -103.221.24.0/22 -103.221.28.0/22 -103.221.32.0/22 -103.221.36.0/22 -103.221.40.0/22 -103.221.44.0/22 -103.221.48.0/22 -103.221.88.0/22 -103.221.92.0/22 -103.221.96.0/22 -103.221.100.0/22 -103.221.104.0/22 -103.221.108.0/22 -103.221.112.0/22 -103.221.116.0/22 -103.221.120.0/22 -103.221.124.0/22 -103.221.128.0/22 -103.221.132.0/22 -103.221.136.0/22 -103.221.140.0/22 -103.221.144.0/22 -103.221.148.0/22 -103.221.152.0/22 -103.221.156.0/22 -103.221.160.0/22 -103.221.164.0/22 -103.221.168.0/22 -103.221.172.0/22 -103.221.176.0/22 -103.221.180.0/22 -103.221.184.0/22 -103.221.188.0/22 -103.221.192.0/22 -103.221.196.0/22 -103.221.200.0/22 -103.221.204.0/22 -103.222.0.0/22 -103.222.4.0/22 -103.222.8.0/22 -103.222.12.0/22 -103.222.16.0/22 -103.222.24.0/22 -103.222.28.0/22 -103.222.32.0/22 -103.222.36.0/22 -103.222.40.0/22 -103.222.44.0/22 -103.222.48.0/22 -103.222.52.0/22 -103.222.56.0/22 -103.222.60.0/22 -103.222.64.0/22 -103.222.68.0/22 -103.222.72.0/22 -103.222.76.0/22 -103.222.80.0/22 -103.222.84.0/22 -103.222.88.0/22 -103.222.92.0/22 -103.222.96.0/22 -103.222.100.0/22 -103.222.104.0/22 -103.222.108.0/22 -103.222.112.0/22 -103.222.116.0/22 -103.222.120.0/22 -103.222.124.0/22 -103.222.128.0/22 -103.222.132.0/22 -103.222.136.0/22 -103.222.140.0/22 -103.222.144.0/22 -103.222.148.0/22 -103.222.152.0/22 -103.222.156.0/22 -103.222.160.0/22 -103.222.164.0/22 -103.222.168.0/22 -103.222.172.0/22 -103.222.176.0/22 -103.222.180.0/22 -103.222.184.0/22 -103.222.188.0/22 -103.222.192.0/22 -103.222.196.0/22 -103.222.200.0/22 -103.222.204.0/22 -103.222.208.0/22 -103.222.212.0/22 -103.222.216.0/22 -103.222.220.0/22 -103.222.224.0/22 -103.222.228.0/22 -103.222.232.0/22 -103.222.240.0/22 -103.222.244.0/22 -103.223.16.0/22 -103.223.20.0/22 -103.223.24.0/22 -103.223.28.0/22 -103.223.32.0/22 -103.223.36.0/22 -103.223.40.0/22 -103.223.44.0/22 -103.223.48.0/22 -103.223.52.0/22 -103.223.56.0/22 -103.223.60.0/22 -103.223.64.0/22 -103.223.68.0/22 -103.223.72.0/22 -103.223.76.0/22 -103.223.80.0/22 -103.223.84.0/22 -103.223.88.0/22 -103.223.92.0/22 -103.223.96.0/22 -103.223.100.0/22 -103.223.104.0/22 -103.223.108.0/22 -103.223.112.0/22 -103.223.116.0/22 -103.223.120.0/22 -103.223.124.0/22 -103.223.128.0/22 -103.223.132.0/22 -103.223.140.0/22 -103.223.144.0/22 -103.223.148.0/22 -103.223.152.0/22 -103.223.156.0/22 -103.223.160.0/22 -103.223.164.0/22 -103.223.168.0/22 -103.223.172.0/22 -103.223.176.0/22 -103.223.180.0/22 -103.223.188.0/22 -103.223.192.0/22 -103.223.196.0/22 -103.223.200.0/22 -103.223.204.0/22 -103.223.208.0/22 -103.223.212.0/22 -103.223.216.0/22 -103.223.220.0/22 -103.223.224.0/22 -103.223.228.0/22 -103.223.232.0/22 -103.223.236.0/22 -103.223.240.0/22 -103.223.244.0/22 -103.223.248.0/22 -103.223.252.0/22 -103.224.0.0/22 -103.224.40.0/22 -103.224.44.0/22 -103.224.60.0/22 -103.224.80.0/22 -103.224.220.0/22 -103.224.224.0/22 -103.224.228.0/22 -103.224.232.0/22 -103.225.84.0/22 -103.226.16.0/22 -103.226.40.0/22 -103.226.56.0/22 -103.226.60.0/22 -103.226.80.0/22 -103.226.132.0/22 -103.226.156.0/22 -103.226.180.0/22 -103.226.196.0/22 -103.227.48.0/22 -103.227.72.0/22 -103.227.76.0/22 -103.227.80.0/22 -103.227.100.0/22 -103.227.120.0/22 -103.227.132.0/22 -103.227.136.0/22 -103.227.196.0/22 -103.227.204.0/22 -103.227.212.0/22 -103.227.228.0/22 -103.228.12.0/22 -103.228.88.0/22 -103.228.128.0/22 -103.228.136.0/22 -103.228.160.0/22 -103.228.176.0/22 -103.228.204.0/22 -103.228.208.0/22 -103.228.228.0/22 -103.228.232.0/22 -103.229.20.0/22 -103.229.60.0/22 -103.229.136.0/22 -103.229.148.0/22 -103.229.172.0/22 -103.229.212.0/22 -103.229.216.0/22 -103.229.220.0/22 -103.229.228.0/22 -103.229.236.0/22 -103.229.240.0/22 -103.230.0.0/22 -103.230.28.0/22 -103.230.44.0/22 -103.230.96.0/22 -103.230.196.0/22 -103.230.200.0/22 -103.230.204.0/22 -103.230.212.0/22 -103.230.236.0/22 -103.231.16.0/22 -103.231.20.0/22 -103.231.64.0/22 -103.231.68.0/22 -103.231.144.0/22 -103.231.180.0/22 -103.231.184.0/22 -103.231.244.0/22 -103.232.4.0/22 -103.232.144.0/22 -103.232.188.0/22 -103.232.212.0/22 -103.233.4.0/22 -103.233.44.0/22 -103.233.52.0/22 -103.233.104.0/22 -103.233.128.0/22 -103.233.136.0/22 -103.233.228.0/22 -103.234.0.0/22 -103.234.20.0/22 -103.234.56.0/22 -103.234.128.0/22 -103.234.172.0/22 -103.234.180.0/22 -103.234.244.0/22 -103.235.16.0/22 -103.235.48.0/22 -103.235.56.0/22 -103.235.60.0/22 -103.235.80.0/22 -103.235.84.0/22 -103.235.128.0/22 -103.235.132.0/22 -103.235.136.0/22 -103.235.140.0/22 -103.235.144.0/22 -103.235.148.0/22 -103.235.184.0/22 -103.235.192.0/22 -103.235.200.0/22 -103.235.220.0/22 -103.235.224.0/22 -103.235.228.0/22 -103.235.232.0/22 -103.235.236.0/22 -103.235.240.0/22 -103.235.244.0/22 -103.235.248.0/22 -103.235.252.0/22 -103.236.0.0/22 -103.236.4.0/22 -103.236.8.0/22 -103.236.12.0/22 -103.236.16.0/22 -103.236.20.0/22 -103.236.24.0/22 -103.236.28.0/22 -103.236.32.0/22 -103.236.36.0/22 -103.236.40.0/22 -103.236.44.0/22 -103.236.48.0/22 -103.236.52.0/22 -103.236.56.0/22 -103.236.60.0/22 -103.236.64.0/22 -103.236.68.0/22 -103.236.72.0/22 -103.236.76.0/22 -103.236.80.0/22 -103.236.84.0/22 -103.236.88.0/22 -103.236.92.0/22 -103.236.96.0/22 -103.236.120.0/22 -103.236.184.0/22 -103.236.220.0/22 -103.236.232.0/22 -103.236.240.0/22 -103.236.244.0/22 -103.236.248.0/22 -103.236.252.0/22 -103.237.0.0/22 -103.237.4.0/22 -103.237.8.0/22 -103.237.12.0/22 -103.237.24.0/22 -103.237.28.0/22 -103.237.68.0/22 -103.237.88.0/22 -103.237.152.0/22 -103.237.176.0/22 -103.237.180.0/22 -103.237.184.0/22 -103.237.188.0/22 -103.237.192.0/22 -103.237.196.0/22 -103.237.200.0/22 -103.237.204.0/22 -103.237.208.0/22 -103.237.212.0/22 -103.237.216.0/22 -103.237.220.0/22 -103.237.224.0/22 -103.237.228.0/22 -103.237.232.0/22 -103.237.236.0/22 -103.237.240.0/22 -103.237.244.0/22 -103.237.248.0/22 -103.237.252.0/22 -103.238.0.0/22 -103.238.4.0/22 -103.238.16.0/22 -103.238.20.0/22 -103.238.24.0/22 -103.238.28.0/22 -103.238.32.0/22 -103.238.36.0/22 -103.238.40.0/22 -103.238.44.0/22 -103.238.48.0/22 -103.238.52.0/22 -103.238.56.0/22 -103.238.88.0/22 -103.238.92.0/22 -103.238.96.0/22 -103.238.132.0/22 -103.238.140.0/22 -103.238.144.0/22 -103.238.160.0/22 -103.238.164.0/22 -103.238.168.0/22 -103.238.172.0/22 -103.238.176.0/22 -103.238.180.0/22 -103.238.184.0/22 -103.238.188.0/22 -103.238.196.0/22 -103.238.204.0/22 -103.238.252.0/22 -103.239.0.0/22 -103.239.44.0/22 -103.239.68.0/22 -103.239.96.0/22 -103.239.152.0/22 -103.239.156.0/22 -103.239.176.0/22 -103.239.180.0/22 -103.239.184.0/22 -103.239.192.0/22 -103.239.196.0/22 -103.239.204.0/22 -103.239.208.0/22 -103.239.224.0/22 -103.239.244.0/22 -103.240.16.0/22 -103.240.36.0/22 -103.240.72.0/22 -103.240.84.0/22 -103.240.124.0/22 -103.240.156.0/22 -103.240.172.0/22 -103.240.188.0/22 -103.240.244.0/22 -103.241.12.0/22 -103.241.72.0/22 -103.241.92.0/22 -103.241.96.0/22 -103.241.160.0/22 -103.241.184.0/22 -103.241.188.0/22 -103.241.220.0/22 -103.242.64.0/22 -103.242.128.0/22 -103.242.132.0/22 -103.242.160.0/22 -103.242.168.0/22 -103.242.172.0/22 -103.242.176.0/22 -103.242.200.0/22 -103.242.212.0/22 -103.242.220.0/22 -103.242.240.0/22 -103.243.136.0/22 -103.243.252.0/22 -103.244.16.0/22 -103.244.58.0/23 -103.244.60.0/22 -103.244.64.0/22 -103.244.68.0/22 -103.244.72.0/22 -103.244.76.0/22 -103.244.80.0/22 -103.244.84.0/22 -103.244.116.0/22 -103.244.164.0/22 -103.244.232.0/22 -103.244.252.0/22 -103.245.23.0/24 -103.245.52.0/22 -103.245.60.0/22 -103.245.80.0/22 -103.245.124.0/22 -103.245.128.0/22 -103.246.8.0/22 -103.246.12.0/22 -103.246.120.0/22 -103.246.124.0/22 -103.246.132.0/22 -103.246.152.0/22 -103.246.156.0/22 -103.247.168.0/22 -103.247.172.0/22 -103.247.176.0/22 -103.247.200.0/22 -103.247.212.0/22 -103.248.0.0/23 -103.248.64.0/22 -103.248.100.0/22 -103.248.124.0/22 -103.248.152.0/22 -103.248.168.0/22 -103.248.192.0/22 -103.248.212.0/22 -103.248.220.0/22 -103.248.224.0/22 -103.249.8.0/22 -103.249.12.0/22 -103.249.52.0/22 -103.249.104.0/22 -103.249.128.0/22 -103.249.136.0/22 -103.249.144.0/22 -103.249.164.0/22 -103.249.168.0/22 -103.249.172.0/22 -103.249.176.0/22 -103.249.188.0/22 -103.249.192.0/22 -103.249.244.0/22 -103.249.252.0/22 -103.250.32.0/22 -103.250.104.0/22 -103.250.124.0/22 -103.250.180.0/22 -103.250.192.0/22 -103.250.216.0/22 -103.250.224.0/22 -103.250.236.0/22 -103.250.248.0/22 -103.250.252.0/22 -103.251.32.0/22 -103.251.84.0/22 -103.251.96.0/22 -103.251.124.0/22 -103.251.128.0/22 -103.251.160.0/22 -103.251.192.0/22 -103.251.204.0/22 -103.251.240.0/22 -103.252.28.0/22 -103.252.36.0/22 -103.252.64.0/22 -103.252.96.0/22 -103.252.104.0/22 -103.252.172.0/22 -103.252.204.0/22 -103.252.208.0/22 -103.252.232.0/22 -103.252.248.0/22 -103.253.4.0/22 -103.253.60.0/22 -103.253.204.0/22 -103.253.220.0/22 -103.253.224.0/22 -103.253.232.0/22 -103.254.8.0/22 -103.254.20.0/22 -103.254.64.0/22 -103.254.68.0/22 -103.254.72.0/22 -103.254.76.0/22 -103.254.112.0/22 -103.254.176.0/22 -103.254.188.0/22 -103.254.196.0/24 -103.254.220.0/22 -103.255.56.0/22 -103.255.68.0/22 -103.255.88.0/22 -103.255.92.0/22 -103.255.136.0/22 -103.255.140.0/22 -103.255.184.0/22 -103.255.200.0/22 -103.255.212.0/22 -103.255.228.0/22 -106.0.0.0/24 -106.0.2.0/23 -106.0.4.0/22 -106.0.8.0/21 -106.0.16.0/20 -106.0.44.0/22 -106.0.64.0/18 -106.2.0.0/15 -106.4.0.0/14 -106.8.0.0/15 -106.11.0.0/16 -106.12.0.0/14 -106.16.0.0/12 -106.32.0.0/12 -106.48.0.0/15 -106.50.0.0/16 -106.52.0.0/14 -106.56.0.0/13 -106.74.0.0/16 -106.75.0.0/16 -106.80.0.0/12 -106.108.0.0/14 -106.112.0.0/13 -106.120.0.0/13 -106.224.0.0/12 -109.244.0.0/16 -110.6.0.0/15 -110.16.0.0/14 -110.34.40.0/22 -110.34.44.0/22 -110.40.0.0/14 -110.44.12.0/22 -110.44.144.0/20 -110.48.0.0/16 -110.51.0.0/16 -110.52.0.0/15 -110.56.0.0/13 -110.64.0.0/15 -110.72.0.0/15 -110.75.0.0/17 -110.75.128.0/19 -110.75.160.0/19 -110.75.192.0/18 -110.76.0.0/19 -110.76.32.0/19 -110.76.132.0/22 -110.76.156.0/22 -110.76.184.0/22 -110.76.192.0/18 -110.77.0.0/17 -110.80.0.0/13 -110.88.0.0/14 -110.92.68.0/22 -110.93.32.0/19 -110.94.0.0/15 -110.96.0.0/11 -110.152.0.0/14 -110.156.0.0/15 -110.165.32.0/19 -110.166.0.0/15 -110.172.192.0/18 -110.173.0.0/19 -110.173.32.0/20 -110.173.64.0/19 -110.173.96.0/19 -110.173.192.0/19 -110.176.0.0/13 -110.184.0.0/13 -110.192.0.0/11 -110.228.0.0/14 -110.232.32.0/19 -110.236.0.0/15 -110.240.0.0/12 -111.0.0.0/10 -111.66.0.0/16 -111.67.192.0/20 -111.68.64.0/19 -111.72.0.0/13 -111.85.0.0/16 -111.91.192.0/19 -111.92.248.0/22 -111.92.252.0/22 -111.112.0.0/15 -111.114.0.0/15 -111.116.0.0/15 -111.118.200.0/21 -111.119.64.0/18 -111.119.128.0/19 -111.120.0.0/14 -111.124.0.0/16 -111.126.0.0/15 -111.128.0.0/11 -111.160.0.0/13 -111.170.0.0/16 -111.172.0.0/14 -111.176.0.0/13 -111.186.0.0/15 -111.192.0.0/12 -111.208.0.0/14 -111.212.0.0/14 -111.221.28.0/24 -111.221.128.0/17 -111.222.0.0/16 -111.223.4.0/22 -111.223.8.0/22 -111.223.12.0/22 -111.223.16.0/22 -111.223.240.0/22 -111.223.248.0/22 -111.224.0.0/14 -111.228.0.0/14 -111.235.96.0/19 -111.235.156.0/22 -111.235.160.0/19 -112.0.0.0/10 -112.64.0.0/15 -112.66.0.0/15 -112.73.0.0/16 -112.74.0.0/15 -112.80.0.0/13 -112.88.0.0/13 -112.96.0.0/15 -112.98.0.0/15 -112.100.0.0/14 -112.109.128.0/17 -112.111.0.0/16 -112.112.0.0/14 -112.116.0.0/15 -112.122.0.0/15 -112.124.0.0/14 -112.128.0.0/14 -112.132.0.0/16 -112.137.48.0/21 -112.192.0.0/14 -112.224.0.0/11 -113.0.0.0/13 -113.8.0.0/15 -113.11.192.0/19 -113.12.0.0/14 -113.16.0.0/15 -113.18.0.0/16 -113.21.232.0/22 -113.21.236.0/22 -113.24.0.0/14 -113.31.0.0/16 -113.44.0.0/14 -113.48.0.0/14 -113.52.160.0/19 -113.52.228.0/22 -113.54.0.0/15 -113.56.0.0/15 -113.58.0.0/16 -113.59.0.0/17 -113.59.224.0/22 -113.62.0.0/15 -113.64.0.0/11 -113.96.0.0/12 -113.112.0.0/13 -113.120.0.0/13 -113.128.0.0/15 -113.130.96.0/20 -113.130.112.0/21 -113.132.0.0/14 -113.136.0.0/13 -113.194.0.0/15 -113.197.100.0/22 -113.200.0.0/15 -113.202.0.0/16 -113.204.0.0/14 -113.208.96.0/19 -113.208.128.0/17 -113.209.0.0/16 -113.212.0.0/18 -113.212.88.0/22 -113.212.100.0/22 -113.212.184.0/21 -113.213.0.0/17 -113.214.0.0/15 -113.218.0.0/15 -113.220.0.0/14 -113.224.0.0/12 -113.240.0.0/13 -113.248.0.0/14 -114.28.0.0/16 -114.31.64.0/22 -114.31.68.0/22 -114.54.0.0/15 -114.60.0.0/14 -114.64.0.0/14 -114.68.0.0/16 -114.79.64.0/18 -114.80.0.0/12 -114.96.0.0/13 -114.104.0.0/14 -114.110.0.0/20 -114.110.64.0/18 -114.111.0.0/19 -114.111.160.0/19 -114.112.0.0/14 -114.116.0.0/16 -114.117.0.0/17 -114.117.128.0/17 -114.118.0.0/16 -114.119.0.0/17 -114.119.192.0/21 -114.119.200.0/22 -114.119.204.0/22 -114.119.208.0/20 -114.119.224.0/19 -114.132.0.0/16 -114.135.0.0/16 -114.138.0.0/15 -114.141.64.0/21 -114.141.80.0/22 -114.141.84.0/22 -114.141.128.0/18 -114.196.0.0/15 -114.198.248.0/21 -114.208.0.0/14 -114.212.0.0/15 -114.214.0.0/16 -114.215.0.0/16 -114.216.0.0/13 -114.224.0.0/12 -114.240.0.0/12 -115.24.0.0/14 -115.28.0.0/15 -115.31.64.0/22 -115.31.68.0/22 -115.31.72.0/22 -115.31.76.0/22 -115.32.0.0/14 -115.42.56.0/22 -115.44.0.0/15 -115.46.0.0/16 -115.47.0.0/16 -115.48.0.0/12 -115.69.64.0/20 -115.84.0.0/18 -115.84.192.0/19 -115.85.192.0/18 -115.100.0.0/14 -115.104.0.0/14 -115.120.0.0/14 -115.124.16.0/20 -115.148.0.0/14 -115.152.0.0/15 -115.154.0.0/15 -115.156.0.0/15 -115.158.0.0/16 -115.159.0.0/16 -115.166.64.0/19 -115.168.0.0/14 -115.172.0.0/14 -115.180.0.0/15 -115.182.0.0/16 -115.183.0.0/16 -115.187.0.0/22 -115.187.4.0/22 -115.187.8.0/22 -115.187.12.0/22 -115.190.0.0/15 -115.192.0.0/11 -115.224.0.0/12 -116.0.8.0/21 -116.0.24.0/21 -116.1.0.0/16 -116.2.0.0/15 -116.4.0.0/14 -116.8.0.0/14 -116.13.0.0/16 -116.16.0.0/12 -116.50.0.0/20 -116.52.0.0/14 -116.56.0.0/15 -116.58.128.0/20 -116.58.208.0/20 -116.60.0.0/14 -116.66.0.0/17 -116.66.176.0/22 -116.68.136.0/22 -116.68.140.0/22 -116.68.176.0/22 -116.68.180.0/22 -116.69.0.0/16 -116.70.0.0/17 -116.76.0.0/15 -116.78.0.0/15 -116.85.0.0/16 -116.89.144.0/20 -116.89.240.0/22 -116.90.80.0/20 -116.90.184.0/21 -116.95.0.0/16 -116.112.0.0/14 -116.116.0.0/15 -116.128.0.0/10 -116.192.0.0/16 -116.193.16.0/20 -116.193.32.0/19 -116.193.152.0/22 -116.193.164.0/22 -116.193.176.0/21 -116.194.0.0/15 -116.196.0.0/16 -116.197.160.0/22 -116.197.164.0/22 -116.198.0.0/16 -116.199.0.0/17 -116.199.128.0/19 -116.204.0.0/17 -116.204.132.0/22 -116.204.168.0/22 -116.204.216.0/22 -116.204.232.0/22 -116.205.0.0/16 -116.206.92.0/22 -116.206.176.0/22 -116.207.0.0/16 -116.208.0.0/14 -116.212.160.0/20 -116.213.44.0/22 -116.213.64.0/18 -116.213.128.0/17 -116.214.32.0/19 -116.214.64.0/20 -116.214.128.0/17 -116.215.0.0/16 -116.216.0.0/14 -116.224.0.0/12 -116.242.0.0/15 -116.244.0.0/15 -116.246.0.0/15 -116.248.0.0/15 -116.251.64.0/18 -116.252.0.0/15 -116.254.104.0/22 -116.254.108.0/22 -116.254.128.0/17 -116.255.128.0/17 -117.8.0.0/13 -117.21.0.0/16 -117.22.0.0/15 -117.24.0.0/13 -117.32.0.0/13 -117.40.0.0/14 -117.44.0.0/15 -117.48.0.0/14 -117.53.48.0/20 -117.53.176.0/20 -117.57.0.0/16 -117.58.0.0/17 -117.59.0.0/16 -117.60.0.0/14 -117.64.0.0/13 -117.72.0.0/15 -117.74.64.0/20 -117.74.80.0/20 -117.74.128.0/17 -117.75.0.0/16 -117.76.0.0/14 -117.80.0.0/12 -117.100.0.0/15 -117.103.16.0/20 -117.103.40.0/21 -117.103.72.0/21 -117.103.128.0/20 -117.104.168.0/21 -117.106.0.0/15 -117.112.0.0/13 -117.120.64.0/18 -117.120.128.0/17 -117.121.0.0/17 -117.121.128.0/18 -117.121.192.0/21 -117.122.128.0/17 -117.124.0.0/14 -117.128.0.0/10 -118.24.0.0/15 -118.26.0.0/19 -118.26.32.0/22 -118.26.40.0/21 -118.26.48.0/21 -118.26.56.0/21 -118.26.64.0/19 -118.26.96.0/21 -118.26.112.0/21 -118.26.120.0/21 -118.26.128.0/20 -118.26.160.0/19 -118.26.192.0/18 -118.28.0.0/15 -118.30.0.0/16 -118.31.0.0/16 -118.64.0.0/15 -118.66.0.0/16 -118.67.112.0/20 -118.72.0.0/13 -118.80.0.0/15 -118.84.0.0/15 -118.88.32.0/19 -118.88.64.0/18 -118.88.128.0/17 -118.89.0.0/16 -118.91.240.0/20 -118.102.16.0/20 -118.102.32.0/21 -118.103.164.0/22 -118.103.168.0/22 -118.103.172.0/22 -118.103.176.0/22 -118.107.180.0/22 -118.112.0.0/13 -118.120.0.0/14 -118.124.0.0/15 -118.126.0.0/16 -118.127.128.0/19 -118.132.0.0/14 -118.144.0.0/14 -118.178.0.0/16 -118.180.0.0/14 -118.184.0.0/17 -118.184.128.0/17 -118.186.0.0/15 -118.188.0.0/16 -118.190.0.0/16 -118.191.0.0/21 -118.191.8.0/22 -118.191.12.0/24 -118.191.16.0/21 -118.191.64.0/20 -118.191.80.0/22 -118.191.128.0/19 -118.191.176.0/20 -118.191.192.0/20 -118.191.208.0/24 -118.191.216.0/22 -118.191.223.0/24 -118.191.224.0/24 -118.191.240.0/20 -118.192.0.0/16 -118.193.0.0/21 -118.193.8.0/21 -118.193.48.0/21 -118.193.96.0/19 -118.193.128.0/17 -118.194.0.0/17 -118.194.128.0/18 -118.194.192.0/19 -118.194.224.0/22 -118.194.240.0/21 -118.195.0.0/17 -118.195.128.0/17 -118.196.0.0/14 -118.202.0.0/15 -118.204.0.0/14 -118.212.0.0/16 -118.213.0.0/16 -118.215.192.0/18 -118.224.0.0/14 -118.228.0.0/15 -118.230.0.0/16 -118.239.0.0/16 -118.242.0.0/16 -118.244.0.0/14 -118.248.0.0/13 -119.0.0.0/15 -119.2.0.0/19 -119.2.128.0/17 -119.3.0.0/16 -119.4.0.0/14 -119.10.0.0/17 -119.15.136.0/21 -119.16.0.0/16 -119.18.192.0/20 -119.18.208.0/21 -119.18.224.0/20 -119.18.240.0/20 -119.19.0.0/16 -119.20.0.0/14 -119.27.64.0/18 -119.27.128.0/19 -119.27.160.0/19 -119.27.192.0/18 -119.28.0.0/15 -119.30.48.0/20 -119.31.192.0/19 -119.32.0.0/14 -119.36.0.0/16 -119.37.0.0/17 -119.37.128.0/18 -119.37.192.0/18 -119.38.0.0/17 -119.38.128.0/18 -119.38.192.0/20 -119.38.208.0/20 -119.38.224.0/19 -119.39.0.0/16 -119.40.0.0/18 -119.40.64.0/20 -119.40.128.0/17 -119.41.0.0/16 -119.42.0.0/19 -119.42.52.0/22 -119.42.128.0/21 -119.42.136.0/21 -119.42.224.0/19 -119.44.0.0/15 -119.48.0.0/13 -119.57.0.0/16 -119.58.0.0/16 -119.59.128.0/17 -119.60.0.0/16 -119.61.0.0/16 -119.62.0.0/16 -119.63.32.0/19 -119.75.208.0/20 -119.78.0.0/15 -119.80.0.0/16 -119.82.208.0/20 -119.84.0.0/14 -119.88.0.0/14 -119.96.0.0/13 -119.108.0.0/15 -119.112.0.0/13 -119.120.0.0/13 -119.128.0.0/12 -119.144.0.0/14 -119.148.160.0/20 -119.148.176.0/20 -119.151.192.0/18 -119.160.200.0/21 -119.161.120.0/22 -119.161.124.0/22 -119.161.128.0/17 -119.162.0.0/15 -119.164.0.0/14 -119.176.0.0/12 -119.232.0.0/15 -119.235.128.0/18 -119.248.0.0/14 -119.252.96.0/21 -119.252.240.0/20 -119.253.0.0/16 -119.254.0.0/15 -120.0.0.0/12 -120.24.0.0/14 -120.30.0.0/16 -120.31.0.0/16 -120.32.0.0/13 -120.40.0.0/14 -120.44.0.0/15 -120.46.0.0/16 -120.47.0.0/16 -120.48.0.0/15 -120.52.0.0/16 -120.53.0.0/16 -120.54.0.0/15 -120.64.0.0/14 -120.68.0.0/14 -120.72.32.0/19 -120.72.128.0/17 -120.76.0.0/14 -120.80.0.0/13 -120.88.8.0/21 -120.90.0.0/15 -120.92.0.0/16 -120.94.0.0/16 -120.95.0.0/16 -120.128.0.0/14 -120.132.0.0/17 -120.132.128.0/17 -120.133.0.0/16 -120.134.0.0/15 -120.136.16.0/22 -120.136.20.0/22 -120.136.128.0/18 -120.137.0.0/17 -120.143.128.0/19 -120.192.0.0/10 -121.0.8.0/21 -121.0.16.0/20 -121.4.0.0/15 -121.8.0.0/13 -121.16.0.0/13 -121.24.0.0/14 -121.28.0.0/15 -121.30.0.0/16 -121.31.0.0/16 -121.32.0.0/14 -121.36.0.0/16 -121.37.0.0/16 -121.38.0.0/15 -121.40.0.0/14 -121.46.0.0/18 -121.46.76.0/22 -121.46.128.0/17 -121.47.0.0/16 -121.48.0.0/15 -121.50.8.0/21 -121.51.0.0/16 -121.52.160.0/19 -121.52.208.0/20 -121.52.224.0/19 -121.54.176.0/21 -121.54.188.0/22 -121.55.0.0/18 -121.56.0.0/15 -121.58.0.0/17 -121.58.136.0/21 -121.58.144.0/20 -121.58.160.0/21 -121.59.0.0/16 -121.60.0.0/14 -121.68.0.0/14 -121.76.0.0/15 -121.79.128.0/18 -121.89.0.0/16 -121.100.128.0/17 -121.101.0.0/18 -121.101.208.0/20 -121.192.0.0/16 -121.193.0.0/16 -121.194.0.0/15 -121.196.0.0/14 -121.200.192.0/21 -121.201.0.0/16 -121.204.0.0/14 -121.224.0.0/12 -121.248.0.0/14 -121.255.0.0/16 -122.0.64.0/18 -122.0.128.0/17 -122.4.0.0/14 -122.8.0.0/16 -122.9.0.0/16 -122.10.128.0/22 -122.10.132.0/23 -122.10.136.0/23 -122.10.164.0/22 -122.10.168.0/21 -122.10.176.0/20 -122.10.192.0/22 -122.10.200.0/21 -122.10.208.0/21 -122.10.216.0/22 -122.10.228.0/22 -122.10.232.0/21 -122.10.240.0/22 -122.11.0.0/17 -122.12.0.0/16 -122.13.0.0/16 -122.14.0.0/17 -122.14.128.0/18 -122.14.192.0/18 -122.48.0.0/16 -122.49.0.0/18 -122.51.0.0/16 -122.64.0.0/11 -122.96.0.0/15 -122.102.0.0/20 -122.102.64.0/20 -122.102.80.0/20 -122.112.0.0/18 -122.112.64.0/18 -122.112.128.0/17 -122.113.0.0/16 -122.114.0.0/16 -122.115.0.0/17 -122.115.128.0/19 -122.115.160.0/19 -122.115.192.0/19 -122.115.224.0/19 -122.119.0.0/16 -122.128.100.0/22 -122.128.120.0/21 -122.136.0.0/13 -122.144.128.0/17 -122.152.192.0/18 -122.156.0.0/14 -122.188.0.0/14 -122.192.0.0/14 -122.198.0.0/16 -122.200.40.0/22 -122.200.44.0/22 -122.200.64.0/18 -122.201.48.0/20 -122.204.0.0/14 -122.224.0.0/12 -122.240.0.0/13 -122.248.24.0/21 -122.248.48.0/20 -122.255.64.0/21 -123.0.128.0/18 -123.4.0.0/14 -123.8.0.0/13 -123.49.128.0/17 -123.50.160.0/19 -123.52.0.0/14 -123.56.0.0/15 -123.58.0.0/20 -123.58.16.0/20 -123.58.32.0/19 -123.58.64.0/19 -123.58.96.0/19 -123.58.128.0/18 -123.58.224.0/20 -123.58.240.0/20 -123.59.0.0/16 -123.60.0.0/16 -123.61.0.0/16 -123.62.0.0/16 -123.64.0.0/11 -123.96.0.0/15 -123.98.0.0/17 -123.99.128.0/17 -123.100.0.0/19 -123.101.0.0/16 -123.103.0.0/17 -123.108.128.0/20 -123.108.208.0/20 -123.112.0.0/12 -123.128.0.0/13 -123.136.80.0/20 -123.137.0.0/16 -123.138.0.0/15 -123.144.0.0/14 -123.148.0.0/16 -123.149.0.0/16 -123.150.0.0/15 -123.152.0.0/13 -123.160.0.0/14 -123.164.0.0/14 -123.168.0.0/14 -123.172.0.0/15 -123.174.0.0/15 -123.176.60.0/22 -123.176.80.0/20 -123.177.0.0/16 -123.178.0.0/15 -123.180.0.0/14 -123.184.0.0/14 -123.188.0.0/14 -123.196.0.0/15 -123.199.128.0/17 -123.206.0.0/15 -123.232.0.0/14 -123.242.0.0/17 -123.242.192.0/22 -123.242.196.0/22 -123.244.0.0/14 -123.249.0.0/16 -123.253.108.0/22 -123.253.240.0/22 -123.254.96.0/22 -123.254.100.0/22 -124.6.64.0/18 -124.14.0.0/15 -124.16.0.0/15 -124.20.0.0/16 -124.21.0.0/20 -124.21.16.0/20 -124.21.32.0/19 -124.21.64.0/18 -124.21.128.0/17 -124.22.0.0/15 -124.28.192.0/18 -124.29.0.0/17 -124.31.0.0/16 -124.40.112.0/20 -124.40.128.0/18 -124.40.192.0/19 -124.40.240.0/22 -124.42.0.0/17 -124.42.128.0/17 -124.47.0.0/18 -124.64.0.0/15 -124.66.0.0/17 -124.67.0.0/16 -124.68.0.0/14 -124.72.0.0/16 -124.73.0.0/16 -124.74.0.0/15 -124.76.0.0/14 -124.88.0.0/16 -124.89.0.0/17 -124.89.128.0/17 -124.90.0.0/15 -124.92.0.0/14 -124.108.8.0/21 -124.108.40.0/21 -124.109.96.0/21 -124.112.0.0/15 -124.114.0.0/15 -124.116.0.0/16 -124.117.0.0/16 -124.118.0.0/15 -124.126.0.0/15 -124.128.0.0/13 -124.147.128.0/17 -124.150.137.0/24 -124.151.0.0/16 -124.152.0.0/16 -124.160.0.0/16 -124.161.0.0/16 -124.162.0.0/16 -124.163.0.0/16 -124.164.0.0/14 -124.172.0.0/15 -124.174.0.0/15 -124.192.0.0/15 -124.196.0.0/16 -124.200.0.0/13 -124.220.0.0/14 -124.224.0.0/16 -124.225.0.0/16 -124.226.0.0/15 -124.228.0.0/14 -124.232.0.0/15 -124.234.0.0/15 -124.236.0.0/14 -124.240.0.0/17 -124.240.128.0/18 -124.242.0.0/16 -124.243.192.0/18 -124.248.0.0/17 -124.249.0.0/16 -124.250.0.0/15 -124.254.0.0/18 -125.31.192.0/18 -125.32.0.0/16 -125.33.0.0/16 -125.34.0.0/16 -125.35.0.0/17 -125.35.128.0/17 -125.36.0.0/14 -125.40.0.0/13 -125.58.128.0/17 -125.61.128.0/17 -125.62.0.0/18 -125.64.0.0/13 -125.72.0.0/16 -125.73.0.0/16 -125.74.0.0/15 -125.76.0.0/17 -125.76.128.0/17 -125.77.0.0/16 -125.78.0.0/15 -125.80.0.0/13 -125.88.0.0/13 -125.96.0.0/15 -125.98.0.0/16 -125.104.0.0/13 -125.112.0.0/12 -125.169.0.0/16 -125.171.0.0/16 -125.208.0.0/18 -125.210.0.0/16 -125.211.0.0/16 -125.213.0.0/17 -125.214.96.0/19 -125.215.0.0/18 -125.216.0.0/15 -125.218.0.0/16 -125.219.0.0/16 -125.220.0.0/15 -125.222.0.0/15 -125.254.128.0/18 -125.254.192.0/18 -128.108.0.0/16 -129.28.0.0/16 -129.204.0.0/16 -129.211.0.0/16 -132.232.0.0/16 -134.175.0.0/16 -137.59.59.0/24 -137.59.88.0/22 -139.5.56.0/22 -139.5.60.0/22 -139.5.80.0/22 -139.5.92.0/22 -139.5.108.0/22 -139.5.128.0/22 -139.5.160.0/22 -139.5.192.0/22 -139.5.204.0/22 -139.5.208.0/22 -139.5.212.0/22 -139.5.244.0/22 -139.9.0.0/16 -139.129.0.0/16 -139.148.0.0/16 -139.155.0.0/16 -139.159.0.0/16 -139.170.0.0/16 -139.176.0.0/16 -139.183.0.0/16 -139.186.0.0/16 -139.189.0.0/16 -139.196.0.0/14 -139.200.0.0/13 -139.208.0.0/13 -139.217.0.0/16 -139.219.0.0/16 -139.220.0.0/15 -139.224.0.0/16 -139.226.0.0/15 -140.75.0.0/16 -140.143.0.0/16 -140.179.0.0/16 -140.205.0.0/16 -140.206.0.0/15 -140.210.0.0/16 -140.224.0.0/16 -140.237.0.0/16 -140.240.0.0/16 -140.243.0.0/16 -140.246.0.0/16 -140.249.0.0/16 -140.250.0.0/16 -140.255.0.0/16 -142.70.0.0/16 -142.86.0.0/16 -144.0.0.0/16 -144.7.0.0/16 -144.12.0.0/16 -144.48.8.0/22 -144.48.64.0/22 -144.48.88.0/22 -144.48.156.0/22 -144.48.180.0/22 -144.48.184.0/22 -144.48.204.0/22 -144.48.208.0/22 -144.48.212.0/22 -144.48.220.0/22 -144.48.252.0/22 -144.52.0.0/16 -144.123.0.0/16 -144.255.0.0/16 -146.56.192.0/18 -146.196.56.0/22 -146.196.68.0/22 -146.196.72.0/22 -146.196.92.0/22 -146.196.112.0/22 -146.196.116.0/22 -146.196.124.0/22 -148.70.0.0/16 -149.41.0.0/16 -150.0.0.0/16 -150.115.0.0/16 -150.121.0.0/16 -150.122.0.0/16 -150.129.136.0/22 -150.129.192.0/22 -150.129.216.0/22 -150.129.252.0/22 -150.138.0.0/15 -150.158.0.0/16 -150.223.0.0/16 -150.242.0.0/22 -150.242.4.0/22 -150.242.8.0/22 -150.242.28.0/22 -150.242.44.0/22 -150.242.48.0/22 -150.242.52.0/22 -150.242.56.0/22 -150.242.76.0/22 -150.242.80.0/22 -150.242.92.0/22 -150.242.96.0/22 -150.242.112.0/22 -150.242.116.0/22 -150.242.120.0/22 -150.242.152.0/22 -150.242.156.0/22 -150.242.160.0/22 -150.242.164.0/22 -150.242.168.0/22 -150.242.184.0/22 -150.242.188.0/22 -150.242.192.0/22 -150.242.212.0/22 -150.242.224.0/22 -150.242.232.0/22 -150.242.236.0/22 -150.242.240.0/22 -150.242.244.0/22 -150.242.248.0/22 -150.248.0.0/16 -150.255.0.0/16 -152.104.128.0/17 -152.136.0.0/16 -153.0.0.0/16 -153.3.0.0/16 -153.34.0.0/15 -153.36.0.0/15 -153.99.0.0/16 -153.101.0.0/16 -153.118.0.0/15 -154.8.128.0/17 -156.59.0.0/16 -157.0.0.0/16 -157.18.0.0/16 -157.61.0.0/16 -157.119.0.0/22 -157.119.8.0/22 -157.119.12.0/22 -157.119.16.0/22 -157.119.28.0/22 -157.119.132.0/22 -157.119.136.0/22 -157.119.140.0/22 -157.119.144.0/22 -157.119.148.0/22 -157.119.152.0/22 -157.119.156.0/22 -157.119.160.0/22 -157.119.164.0/22 -157.119.172.0/22 -157.119.192.0/22 -157.119.196.0/22 -157.119.240.0/22 -157.119.252.0/22 -157.122.0.0/16 -157.148.0.0/16 -157.156.0.0/16 -157.255.0.0/16 -158.79.0.0/16 -159.27.0.0/16 -159.75.0.0/16 -159.226.0.0/16 -160.19.208.0/22 -160.19.212.0/22 -160.19.216.0/22 -160.20.48.0/22 -160.202.60.0/22 -160.202.148.0/22 -160.202.152.0/22 -160.202.168.0/22 -160.202.212.0/22 -160.202.216.0/22 -160.202.220.0/22 -160.202.224.0/22 -160.202.228.0/22 -160.202.232.0/22 -160.202.236.0/22 -160.202.240.0/22 -160.202.244.0/22 -160.202.248.0/22 -160.202.252.0/22 -160.238.64.0/22 -161.120.0.0/16 -161.189.0.0/16 -161.207.0.0/16 -162.14.0.0/16 -162.105.0.0/16 -163.0.0.0/16 -163.47.4.0/22 -163.53.0.0/22 -163.53.4.0/22 -163.53.8.0/22 -163.53.12.0/22 -163.53.36.0/22 -163.53.40.0/22 -163.53.44.0/22 -163.53.48.0/22 -163.53.52.0/22 -163.53.56.0/22 -163.53.60.0/22 -163.53.64.0/22 -163.53.88.0/22 -163.53.92.0/22 -163.53.96.0/22 -163.53.100.0/22 -163.53.104.0/22 -163.53.108.0/22 -163.53.112.0/22 -163.53.116.0/22 -163.53.120.0/22 -163.53.124.0/22 -163.53.128.0/22 -163.53.132.0/22 -163.53.136.0/22 -163.53.160.0/22 -163.53.164.0/22 -163.53.168.0/22 -163.53.172.0/22 -163.53.188.0/22 -163.53.220.0/22 -163.53.240.0/22 -163.125.0.0/16 -163.142.0.0/16 -163.177.0.0/16 -163.179.0.0/16 -163.204.0.0/16 -163.228.0.0/16 -164.52.0.0/17 -166.111.0.0/16 -167.139.0.0/16 -167.189.0.0/16 -167.220.244.0/22 -168.160.0.0/16 -170.179.0.0/16 -171.8.0.0/13 -171.34.0.0/15 -171.36.0.0/14 -171.40.0.0/13 -171.80.0.0/14 -171.84.0.0/14 -171.88.0.0/13 -171.104.0.0/13 -171.112.0.0/14 -171.116.0.0/14 -171.120.0.0/13 -171.208.0.0/12 -172.81.192.0/18 -175.0.0.0/12 -175.16.0.0/13 -175.24.0.0/16 -175.25.0.0/16 -175.26.0.0/16 -175.27.0.0/16 -175.30.0.0/15 -175.42.0.0/15 -175.44.0.0/16 -175.46.0.0/15 -175.48.0.0/12 -175.64.0.0/11 -175.102.0.0/16 -175.106.128.0/17 -175.111.144.0/22 -175.111.148.0/22 -175.111.152.0/22 -175.111.156.0/22 -175.111.160.0/22 -175.111.164.0/22 -175.111.168.0/22 -175.111.172.0/22 -175.111.184.0/22 -175.146.0.0/15 -175.148.0.0/14 -175.152.0.0/14 -175.158.96.0/22 -175.160.0.0/12 -175.176.156.0/22 -175.176.176.0/22 -175.176.188.0/22 -175.176.192.0/22 -175.178.0.0/16 -175.184.128.0/18 -175.185.0.0/16 -175.186.0.0/15 -175.188.0.0/14 -180.76.0.0/16 -180.77.0.0/16 -180.78.0.0/15 -180.84.0.0/15 -180.86.0.0/16 -180.88.0.0/14 -180.94.56.0/21 -180.94.96.0/20 -180.94.120.0/22 -180.94.124.0/22 -180.95.128.0/17 -180.96.0.0/11 -180.129.128.0/17 -180.130.0.0/16 -180.136.0.0/13 -180.148.16.0/21 -180.148.152.0/21 -180.148.216.0/21 -180.148.224.0/19 -180.149.128.0/19 -180.149.236.0/22 -180.150.160.0/19 -180.152.0.0/13 -180.160.0.0/12 -180.178.112.0/22 -180.178.116.0/22 -180.178.192.0/18 -180.184.0.0/15 -180.186.0.0/16 -180.187.0.0/16 -180.188.0.0/17 -180.189.148.0/22 -180.200.252.0/22 -180.201.0.0/16 -180.202.0.0/15 -180.208.0.0/15 -180.210.212.0/22 -180.210.224.0/19 -180.212.0.0/15 -180.222.224.0/19 -180.223.0.0/16 -180.233.0.0/18 -180.233.64.0/19 -180.233.144.0/22 -180.235.64.0/19 -180.235.112.0/22 -182.16.144.0/22 -182.16.148.0/22 -182.16.192.0/19 -182.18.0.0/17 -182.23.184.0/21 -182.23.200.0/21 -182.32.0.0/12 -182.48.96.0/19 -182.49.0.0/16 -182.50.0.0/20 -182.50.112.0/20 -182.51.0.0/16 -182.54.0.0/17 -182.54.244.0/22 -182.61.0.0/16 -182.80.0.0/14 -182.84.0.0/14 -182.88.0.0/14 -182.92.0.0/16 -182.96.0.0/12 -182.112.0.0/12 -182.128.0.0/12 -182.144.0.0/13 -182.157.0.0/16 -182.160.64.0/19 -182.174.0.0/15 -182.200.0.0/13 -182.236.128.0/17 -182.237.24.0/22 -182.237.28.0/22 -182.238.0.0/16 -182.239.0.0/19 -182.240.0.0/13 -182.254.0.0/16 -182.255.32.0/22 -182.255.36.0/22 -182.255.60.0/22 -183.0.0.0/10 -183.64.0.0/13 -183.78.160.0/22 -183.78.164.0/22 -183.78.180.0/22 -183.81.172.0/22 -183.81.180.0/22 -183.84.0.0/15 -183.91.128.0/22 -183.91.136.0/21 -183.91.144.0/20 -183.92.0.0/14 -183.128.0.0/11 -183.160.0.0/13 -183.168.0.0/15 -183.170.0.0/16 -183.172.0.0/14 -183.182.0.0/19 -183.184.0.0/13 -183.192.0.0/10 -185.203.36.0/22 -188.131.128.0/17 -192.51.188.0/24 -192.55.46.0/24 -192.55.68.0/22 -192.102.204.0/23 -192.124.154.0/24 -192.140.128.0/22 -192.140.132.0/22 -192.140.136.0/22 -192.140.156.0/22 -192.140.160.0/22 -192.140.164.0/22 -192.140.168.0/22 -192.140.172.0/22 -192.140.176.0/22 -192.140.180.0/22 -192.140.184.0/22 -192.140.188.0/22 -192.140.192.0/22 -192.140.196.0/22 -192.140.200.0/22 -192.140.204.0/22 -192.140.208.0/22 -192.140.212.0/22 -192.144.128.0/17 -192.197.113.0/24 -193.112.0.0/16 -198.175.100.0/22 -199.212.57.0/24 -202.0.100.0/23 -202.0.122.0/23 -202.0.176.0/22 -202.3.128.0/23 -202.3.134.0/24 -202.4.128.0/19 -202.4.252.0/22 -202.5.208.0/22 -202.5.212.0/22 -202.5.216.0/22 -202.6.6.0/23 -202.6.66.0/23 -202.6.72.0/23 -202.6.87.0/24 -202.6.88.0/23 -202.6.92.0/23 -202.6.103.0/24 -202.6.108.0/24 -202.6.110.0/23 -202.6.114.0/24 -202.6.176.0/20 -202.8.0.0/24 -202.8.2.0/23 -202.8.4.0/23 -202.8.12.0/24 -202.8.24.0/24 -202.8.77.0/24 -202.8.120.0/22 -202.8.128.0/19 -202.8.192.0/20 -202.9.32.0/24 -202.9.34.0/23 -202.9.48.0/23 -202.9.51.0/24 -202.9.52.0/23 -202.9.54.0/24 -202.9.57.0/24 -202.9.58.0/23 -202.10.64.0/20 -202.10.112.0/22 -202.10.116.0/22 -202.10.120.0/22 -202.10.124.0/22 -202.12.1.0/24 -202.12.2.0/24 -202.12.17.0/24 -202.12.18.0/24 -202.12.19.0/24 -202.12.72.0/24 -202.12.84.0/23 -202.12.96.0/24 -202.12.98.0/23 -202.12.106.0/24 -202.12.111.0/24 -202.12.116.0/24 -202.14.64.0/23 -202.14.69.0/24 -202.14.73.0/24 -202.14.74.0/23 -202.14.76.0/24 -202.14.78.0/23 -202.14.88.0/24 -202.14.97.0/24 -202.14.104.0/23 -202.14.108.0/23 -202.14.111.0/24 -202.14.114.0/23 -202.14.118.0/23 -202.14.124.0/23 -202.14.127.0/24 -202.14.129.0/24 -202.14.135.0/24 -202.14.136.0/24 -202.14.149.0/24 -202.14.151.0/24 -202.14.157.0/24 -202.14.158.0/23 -202.14.169.0/24 -202.14.170.0/23 -202.14.172.0/22 -202.14.176.0/24 -202.14.184.0/23 -202.14.208.0/23 -202.14.213.0/24 -202.14.219.0/24 -202.14.220.0/24 -202.14.222.0/23 -202.14.225.0/24 -202.14.226.0/23 -202.14.231.0/24 -202.14.235.0/24 -202.14.236.0/23 -202.14.238.0/24 -202.14.239.0/24 -202.14.246.0/24 -202.14.251.0/24 -202.20.66.0/24 -202.20.79.0/24 -202.20.87.0/24 -202.20.88.0/23 -202.20.90.0/24 -202.20.94.0/23 -202.20.114.0/24 -202.20.117.0/24 -202.20.120.0/24 -202.20.125.0/24 -202.20.126.0/24 -202.20.127.0/24 -202.21.48.0/22 -202.21.52.0/22 -202.21.56.0/22 -202.21.60.0/22 -202.21.131.0/24 -202.21.132.0/24 -202.21.141.0/24 -202.21.142.0/24 -202.21.147.0/24 -202.21.148.0/24 -202.21.150.0/23 -202.21.152.0/23 -202.21.154.0/24 -202.21.156.0/24 -202.22.248.0/22 -202.22.252.0/22 -202.27.12.0/24 -202.27.14.0/24 -202.27.136.0/23 -202.36.226.0/24 -202.38.0.0/23 -202.38.2.0/23 -202.38.8.0/21 -202.38.48.0/20 -202.38.64.0/19 -202.38.96.0/19 -202.38.128.0/23 -202.38.130.0/23 -202.38.132.0/23 -202.38.134.0/24 -202.38.135.0/24 -202.38.136.0/23 -202.38.138.0/24 -202.38.140.0/23 -202.38.142.0/23 -202.38.146.0/23 -202.38.149.0/24 -202.38.150.0/23 -202.38.152.0/23 -202.38.154.0/23 -202.38.156.0/24 -202.38.158.0/23 -202.38.160.0/23 -202.38.164.0/22 -202.38.168.0/23 -202.38.170.0/24 -202.38.171.0/24 -202.38.176.0/23 -202.38.184.0/21 -202.38.192.0/18 -202.40.4.0/23 -202.40.7.0/24 -202.40.15.0/24 -202.40.135.0/24 -202.40.136.0/24 -202.40.140.0/24 -202.40.143.0/24 -202.40.144.0/23 -202.40.150.0/24 -202.40.155.0/24 -202.40.156.0/24 -202.40.158.0/23 -202.40.162.0/24 -202.41.8.0/23 -202.41.11.0/24 -202.41.12.0/23 -202.41.128.0/24 -202.41.130.0/23 -202.41.152.0/21 -202.41.192.0/24 -202.41.196.0/22 -202.41.200.0/22 -202.41.240.0/20 -202.43.76.0/22 -202.43.144.0/20 -202.44.16.0/20 -202.44.48.0/22 -202.44.67.0/24 -202.44.74.0/24 -202.44.97.0/24 -202.44.129.0/24 -202.44.132.0/23 -202.44.146.0/23 -202.45.0.0/23 -202.45.2.0/24 -202.45.15.0/24 -202.45.16.0/20 -202.46.16.0/23 -202.46.18.0/24 -202.46.20.0/23 -202.46.32.0/19 -202.46.128.0/24 -202.46.224.0/20 -202.47.82.0/23 -202.47.96.0/22 -202.47.100.0/22 -202.47.104.0/22 -202.47.108.0/22 -202.47.126.0/24 -202.47.128.0/24 -202.47.130.0/23 -202.52.33.0/24 -202.52.34.0/24 -202.52.47.0/24 -202.52.143.0/24 -202.52.144.0/24 -202.53.140.0/24 -202.53.143.0/24 -202.57.192.0/22 -202.57.196.0/22 -202.57.200.0/22 -202.57.204.0/22 -202.57.212.0/22 -202.57.216.0/22 -202.57.240.0/20 -202.58.0.0/24 -202.58.101.0/24 -202.58.104.0/22 -202.58.112.0/22 -202.59.0.0/24 -202.59.1.0/24 -202.59.212.0/22 -202.59.236.0/24 -202.59.240.0/24 -202.60.48.0/21 -202.60.96.0/21 -202.60.112.0/20 -202.60.132.0/22 -202.60.136.0/21 -202.60.144.0/20 -202.61.68.0/22 -202.61.76.0/22 -202.61.88.0/22 -202.61.123.0/24 -202.61.127.0/24 -202.62.112.0/22 -202.62.248.0/22 -202.62.252.0/24 -202.62.255.0/24 -202.63.80.0/24 -202.63.81.0/24 -202.63.82.0/23 -202.63.84.0/22 -202.63.88.0/21 -202.63.160.0/19 -202.63.248.0/22 -202.63.253.0/24 -202.65.0.0/21 -202.65.8.0/23 -202.65.96.0/22 -202.65.100.0/22 -202.65.104.0/22 -202.65.108.0/22 -202.66.168.0/22 -202.67.0.0/22 -202.69.4.0/22 -202.69.16.0/20 -202.70.0.0/19 -202.70.96.0/20 -202.70.192.0/20 -202.71.32.0/22 -202.71.36.0/22 -202.71.40.0/22 -202.71.44.0/22 -202.72.40.0/21 -202.72.80.0/20 -202.72.112.0/22 -202.72.116.0/22 -202.72.120.0/22 -202.72.124.0/22 -202.73.128.0/22 -202.73.240.0/22 -202.73.244.0/22 -202.73.248.0/22 -202.73.252.0/22 -202.74.8.0/21 -202.74.36.0/24 -202.74.42.0/24 -202.74.52.0/24 -202.74.80.0/20 -202.74.232.0/22 -202.74.254.0/23 -202.75.208.0/20 -202.75.252.0/22 -202.76.252.0/22 -202.77.80.0/21 -202.77.92.0/22 -202.78.8.0/21 -202.79.224.0/21 -202.79.248.0/22 -202.80.192.0/21 -202.80.200.0/21 -202.81.0.0/22 -202.81.176.0/22 -202.81.180.0/22 -202.81.184.0/22 -202.81.188.0/22 -202.83.252.0/22 -202.84.0.0/22 -202.84.4.0/22 -202.84.8.0/21 -202.84.16.0/23 -202.84.22.0/24 -202.84.24.0/21 -202.85.208.0/20 -202.86.249.0/24 -202.86.252.0/22 -202.87.80.0/20 -202.88.32.0/22 -202.89.8.0/21 -202.89.96.0/22 -202.89.108.0/22 -202.89.119.0/24 -202.89.232.0/21 -202.90.0.0/22 -202.90.16.0/22 -202.90.20.0/22 -202.90.24.0/22 -202.90.28.0/22 -202.90.37.0/24 -202.90.96.0/22 -202.90.100.0/22 -202.90.104.0/22 -202.90.108.0/22 -202.90.112.0/20 -202.90.193.0/24 -202.90.196.0/24 -202.90.205.0/24 -202.90.224.0/20 -202.91.0.0/22 -202.91.36.0/22 -202.91.96.0/20 -202.91.128.0/22 -202.91.176.0/20 -202.91.224.0/19 -202.92.0.0/22 -202.92.8.0/21 -202.92.48.0/20 -202.92.252.0/22 -202.93.0.0/22 -202.93.252.0/22 -202.94.68.0/24 -202.94.74.0/24 -202.94.81.0/24 -202.94.92.0/22 -202.95.240.0/21 -202.95.252.0/22 -202.96.0.0/18 -202.96.64.0/21 -202.96.72.0/21 -202.96.80.0/20 -202.96.96.0/21 -202.96.104.0/21 -202.96.112.0/20 -202.96.128.0/21 -202.96.136.0/21 -202.96.144.0/20 -202.96.160.0/21 -202.96.168.0/21 -202.96.176.0/20 -202.96.192.0/21 -202.96.200.0/21 -202.96.208.0/20 -202.96.224.0/21 -202.96.232.0/21 -202.96.240.0/20 -202.97.0.0/21 -202.97.8.0/21 -202.97.16.0/20 -202.97.32.0/19 -202.97.64.0/19 -202.97.96.0/20 -202.97.112.0/20 -202.97.128.0/18 -202.97.192.0/19 -202.97.224.0/21 -202.97.232.0/21 -202.97.240.0/20 -202.98.0.0/21 -202.98.8.0/21 -202.98.16.0/20 -202.98.32.0/21 -202.98.40.0/21 -202.98.48.0/20 -202.98.64.0/19 -202.98.96.0/21 -202.98.104.0/21 -202.98.112.0/20 -202.98.128.0/19 -202.98.160.0/21 -202.98.168.0/21 -202.98.176.0/20 -202.98.192.0/21 -202.98.200.0/21 -202.98.208.0/20 -202.98.224.0/21 -202.98.232.0/21 -202.98.240.0/20 -202.99.0.0/18 -202.99.64.0/19 -202.99.96.0/21 -202.99.104.0/21 -202.99.112.0/20 -202.99.128.0/19 -202.99.160.0/21 -202.99.168.0/21 -202.99.176.0/20 -202.99.192.0/21 -202.99.200.0/21 -202.99.208.0/20 -202.99.224.0/21 -202.99.232.0/21 -202.99.240.0/20 -202.100.0.0/21 -202.100.8.0/21 -202.100.16.0/20 -202.100.32.0/19 -202.100.64.0/21 -202.100.72.0/21 -202.100.80.0/20 -202.100.96.0/21 -202.100.104.0/21 -202.100.112.0/20 -202.100.128.0/21 -202.100.136.0/21 -202.100.144.0/20 -202.100.160.0/21 -202.100.168.0/21 -202.100.176.0/20 -202.100.192.0/21 -202.100.200.0/21 -202.100.208.0/20 -202.100.224.0/19 -202.101.0.0/18 -202.101.64.0/19 -202.101.96.0/19 -202.101.128.0/18 -202.101.192.0/19 -202.101.224.0/21 -202.101.232.0/21 -202.101.240.0/20 -202.102.0.0/19 -202.102.32.0/19 -202.102.64.0/18 -202.102.128.0/21 -202.102.136.0/21 -202.102.144.0/20 -202.102.160.0/19 -202.102.192.0/21 -202.102.200.0/21 -202.102.208.0/20 -202.102.224.0/21 -202.102.232.0/21 -202.102.240.0/20 -202.103.0.0/21 -202.103.8.0/21 -202.103.16.0/20 -202.103.32.0/19 -202.103.64.0/19 -202.103.96.0/21 -202.103.104.0/21 -202.103.112.0/20 -202.103.128.0/18 -202.103.192.0/19 -202.103.224.0/21 -202.103.232.0/21 -202.103.240.0/20 -202.104.0.0/15 -202.106.0.0/16 -202.107.0.0/17 -202.107.128.0/17 -202.108.0.0/16 -202.109.0.0/16 -202.110.0.0/18 -202.110.64.0/18 -202.110.128.0/18 -202.110.192.0/18 -202.111.0.0/17 -202.111.128.0/19 -202.111.160.0/19 -202.111.192.0/18 -202.112.0.0/16 -202.113.0.0/20 -202.113.16.0/20 -202.113.32.0/19 -202.113.64.0/18 -202.113.128.0/18 -202.113.192.0/19 -202.113.224.0/20 -202.113.240.0/20 -202.114.0.0/19 -202.114.32.0/19 -202.114.64.0/18 -202.114.128.0/17 -202.115.0.0/19 -202.115.32.0/19 -202.115.64.0/18 -202.115.128.0/17 -202.116.0.0/19 -202.116.32.0/20 -202.116.48.0/20 -202.116.64.0/19 -202.116.96.0/19 -202.116.128.0/17 -202.117.0.0/18 -202.117.64.0/18 -202.117.128.0/17 -202.118.0.0/19 -202.118.32.0/19 -202.118.64.0/18 -202.118.128.0/17 -202.119.0.0/19 -202.119.32.0/19 -202.119.64.0/20 -202.119.80.0/20 -202.119.96.0/19 -202.119.128.0/17 -202.120.0.0/18 -202.120.64.0/18 -202.120.128.0/17 -202.121.0.0/16 -202.122.0.0/21 -202.122.32.0/21 -202.122.64.0/19 -202.122.112.0/21 -202.122.120.0/21 -202.122.128.0/24 -202.122.132.0/24 -202.123.96.0/20 -202.123.116.0/22 -202.123.120.0/22 -202.124.16.0/21 -202.124.24.0/22 -202.125.107.0/24 -202.125.109.0/24 -202.125.112.0/20 -202.125.176.0/20 -202.127.0.0/23 -202.127.2.0/24 -202.127.3.0/24 -202.127.4.0/24 -202.127.5.0/24 -202.127.6.0/23 -202.127.12.0/22 -202.127.16.0/20 -202.127.40.0/21 -202.127.48.0/20 -202.127.112.0/20 -202.127.128.0/20 -202.127.144.0/20 -202.127.160.0/21 -202.127.192.0/23 -202.127.194.0/23 -202.127.196.0/22 -202.127.200.0/21 -202.127.208.0/24 -202.127.209.0/24 -202.127.212.0/22 -202.127.216.0/21 -202.127.224.0/19 -202.129.208.0/24 -202.130.0.0/19 -202.130.39.0/24 -202.130.224.0/19 -202.131.16.0/21 -202.131.48.0/20 -202.131.208.0/20 -202.133.32.0/20 -202.134.58.0/24 -202.134.128.0/20 -202.134.208.0/22 -202.134.212.0/22 -202.134.216.0/22 -202.134.220.0/22 -202.136.48.0/20 -202.136.208.0/20 -202.136.224.0/20 -202.136.248.0/22 -202.137.231.0/24 -202.140.140.0/22 -202.140.144.0/22 -202.140.148.0/22 -202.140.152.0/22 -202.140.156.0/22 -202.141.160.0/19 -202.142.16.0/20 -202.143.4.0/22 -202.143.16.0/20 -202.143.32.0/20 -202.143.56.0/21 -202.143.100.0/22 -202.143.104.0/22 -202.144.196.0/22 -202.146.160.0/20 -202.146.186.0/24 -202.146.188.0/22 -202.146.196.0/22 -202.146.200.0/21 -202.147.144.0/20 -202.148.32.0/20 -202.148.64.0/19 -202.148.96.0/19 -202.149.32.0/19 -202.149.160.0/19 -202.149.224.0/19 -202.150.16.0/20 -202.150.32.0/20 -202.150.56.0/22 -202.150.192.0/20 -202.150.224.0/19 -202.151.0.0/22 -202.151.33.0/24 -202.151.128.0/19 -202.152.176.0/20 -202.153.0.0/22 -202.153.7.0/24 -202.153.48.0/20 -202.157.192.0/19 -202.158.160.0/19 -202.158.242.0/24 -202.160.140.0/22 -202.160.156.0/22 -202.160.176.0/20 -202.162.67.0/24 -202.162.75.0/24 -202.164.0.0/20 -202.164.96.0/19 -202.165.176.0/20 -202.165.208.0/20 -202.165.239.0/24 -202.165.240.0/23 -202.165.243.0/24 -202.165.245.0/24 -202.165.251.0/24 -202.165.252.0/22 -202.166.224.0/19 -202.168.80.0/22 -202.168.128.0/22 -202.168.132.0/22 -202.168.136.0/22 -202.168.140.0/22 -202.168.160.0/20 -202.168.176.0/20 -202.170.128.0/19 -202.170.216.0/21 -202.170.224.0/19 -202.171.216.0/21 -202.171.232.0/24 -202.171.235.0/24 -202.172.0.0/22 -202.172.7.0/24 -202.173.0.0/22 -202.173.6.0/24 -202.173.8.0/21 -202.173.112.0/22 -202.173.224.0/19 -202.174.64.0/20 -202.174.124.0/22 -202.176.224.0/19 -202.179.160.0/22 -202.179.164.0/22 -202.179.168.0/22 -202.179.172.0/22 -202.179.240.0/20 -202.180.128.0/19 -202.180.208.0/21 -202.181.8.0/22 -202.181.28.0/22 -202.181.112.0/20 -202.182.32.0/20 -202.182.192.0/19 -202.189.0.0/18 -202.189.80.0/20 -202.189.184.0/21 -202.191.0.0/24 -202.191.68.0/22 -202.191.72.0/21 -202.191.80.0/20 -202.192.0.0/13 -202.200.0.0/14 -202.204.0.0/14 -203.0.4.0/22 -203.0.10.0/23 -203.0.18.0/24 -203.0.24.0/24 -203.0.42.0/23 -203.0.45.0/24 -203.0.46.0/23 -203.0.81.0/24 -203.0.82.0/23 -203.0.90.0/23 -203.0.96.0/23 -203.0.104.0/21 -203.0.114.0/23 -203.0.122.0/24 -203.0.128.0/24 -203.0.130.0/23 -203.0.132.0/22 -203.0.137.0/24 -203.0.142.0/24 -203.0.144.0/24 -203.0.146.0/24 -203.0.148.0/24 -203.0.150.0/23 -203.0.152.0/24 -203.0.177.0/24 -203.0.224.0/24 -203.1.4.0/22 -203.1.18.0/24 -203.1.26.0/23 -203.1.65.0/24 -203.1.66.0/23 -203.1.70.0/23 -203.1.76.0/23 -203.1.90.0/24 -203.1.97.0/24 -203.1.98.0/23 -203.1.100.0/22 -203.1.108.0/24 -203.1.253.0/24 -203.1.254.0/24 -203.2.64.0/21 -203.2.73.0/24 -203.2.112.0/21 -203.2.126.0/23 -203.2.140.0/24 -203.2.150.0/24 -203.2.152.0/22 -203.2.156.0/23 -203.2.160.0/21 -203.2.180.0/23 -203.2.196.0/23 -203.2.209.0/24 -203.2.214.0/23 -203.2.226.0/23 -203.2.229.0/24 -203.2.236.0/23 -203.3.68.0/24 -203.3.72.0/23 -203.3.75.0/24 -203.3.80.0/21 -203.3.96.0/22 -203.3.105.0/24 -203.3.112.0/21 -203.3.120.0/24 -203.3.123.0/24 -203.3.135.0/24 -203.3.139.0/24 -203.3.143.0/24 -203.4.132.0/23 -203.4.134.0/24 -203.4.151.0/24 -203.4.152.0/22 -203.4.174.0/23 -203.4.180.0/24 -203.4.186.0/24 -203.4.205.0/24 -203.4.208.0/22 -203.4.227.0/24 -203.4.230.0/23 -203.5.4.0/23 -203.5.7.0/24 -203.5.8.0/23 -203.5.11.0/24 -203.5.21.0/24 -203.5.22.0/24 -203.5.44.0/24 -203.5.46.0/23 -203.5.52.0/22 -203.5.56.0/23 -203.5.60.0/23 -203.5.114.0/23 -203.5.118.0/24 -203.5.120.0/24 -203.5.172.0/24 -203.5.180.0/23 -203.5.182.0/24 -203.5.185.0/24 -203.5.186.0/24 -203.5.188.0/23 -203.5.190.0/24 -203.5.195.0/24 -203.5.214.0/23 -203.5.218.0/23 -203.6.131.0/24 -203.6.136.0/24 -203.6.138.0/23 -203.6.142.0/24 -203.6.150.0/23 -203.6.157.0/24 -203.6.159.0/24 -203.6.224.0/20 -203.6.248.0/23 -203.7.129.0/24 -203.7.138.0/23 -203.7.147.0/24 -203.7.150.0/23 -203.7.158.0/24 -203.7.192.0/23 -203.7.200.0/24 -203.8.0.0/24 -203.8.8.0/24 -203.8.23.0/24 -203.8.70.0/24 -203.8.82.0/24 -203.8.86.0/23 -203.8.91.0/24 -203.8.110.0/23 -203.8.115.0/24 -203.8.166.0/23 -203.8.169.0/24 -203.8.173.0/24 -203.8.184.0/24 -203.8.186.0/23 -203.8.190.0/23 -203.8.192.0/24 -203.8.197.0/24 -203.8.198.0/23 -203.8.203.0/24 -203.8.209.0/24 -203.8.210.0/23 -203.8.212.0/22 -203.8.217.0/24 -203.8.220.0/24 -203.9.32.0/24 -203.9.36.0/23 -203.9.57.0/24 -203.9.63.0/24 -203.9.65.0/24 -203.9.70.0/23 -203.9.72.0/24 -203.9.75.0/24 -203.9.76.0/23 -203.9.96.0/22 -203.9.100.0/23 -203.9.108.0/24 -203.9.158.0/24 -203.10.34.0/24 -203.10.56.0/24 -203.10.74.0/23 -203.10.84.0/22 -203.10.88.0/24 -203.10.95.0/24 -203.10.125.0/24 -203.11.70.0/24 -203.11.76.0/22 -203.11.82.0/24 -203.11.84.0/22 -203.11.100.0/22 -203.11.109.0/24 -203.11.117.0/24 -203.11.122.0/24 -203.11.126.0/24 -203.11.136.0/22 -203.11.141.0/24 -203.11.142.0/23 -203.11.180.0/22 -203.11.208.0/22 -203.12.16.0/24 -203.12.19.0/24 -203.12.24.0/24 -203.12.57.0/24 -203.12.65.0/24 -203.12.66.0/24 -203.12.70.0/23 -203.12.87.0/24 -203.12.100.0/23 -203.12.103.0/24 -203.12.114.0/24 -203.12.118.0/24 -203.12.130.0/24 -203.12.137.0/24 -203.12.196.0/22 -203.12.211.0/24 -203.12.219.0/24 -203.12.226.0/24 -203.12.240.0/22 -203.13.18.0/24 -203.13.24.0/24 -203.13.44.0/23 -203.13.88.0/23 -203.13.92.0/22 -203.13.173.0/24 -203.13.224.0/23 -203.13.227.0/24 -203.13.233.0/24 -203.14.24.0/22 -203.14.33.0/24 -203.14.56.0/24 -203.14.61.0/24 -203.14.62.0/24 -203.14.104.0/24 -203.14.114.0/23 -203.14.118.0/24 -203.14.162.0/24 -203.14.192.0/24 -203.14.194.0/23 -203.14.214.0/24 -203.14.231.0/24 -203.14.246.0/24 -203.15.0.0/20 -203.15.20.0/23 -203.15.22.0/24 -203.15.87.0/24 -203.15.88.0/23 -203.15.105.0/24 -203.15.112.0/21 -203.15.130.0/23 -203.15.149.0/24 -203.15.151.0/24 -203.15.156.0/22 -203.15.174.0/24 -203.15.227.0/24 -203.15.232.0/21 -203.15.240.0/23 -203.15.246.0/24 -203.16.10.0/24 -203.16.12.0/23 -203.16.16.0/21 -203.16.27.0/24 -203.16.38.0/24 -203.16.49.0/24 -203.16.50.0/23 -203.16.58.0/24 -203.16.63.0/24 -203.16.133.0/24 -203.16.161.0/24 -203.16.162.0/24 -203.16.186.0/23 -203.16.228.0/24 -203.16.238.0/24 -203.16.240.0/24 -203.16.245.0/24 -203.17.2.0/24 -203.17.18.0/24 -203.17.28.0/24 -203.17.39.0/24 -203.17.56.0/24 -203.17.74.0/23 -203.17.88.0/23 -203.17.136.0/24 -203.17.164.0/24 -203.17.187.0/24 -203.17.190.0/23 -203.17.231.0/24 -203.17.233.0/24 -203.17.248.0/24 -203.17.249.0/24 -203.17.255.0/24 -203.18.2.0/23 -203.18.4.0/24 -203.18.7.0/24 -203.18.31.0/24 -203.18.37.0/24 -203.18.48.0/23 -203.18.52.0/24 -203.18.72.0/22 -203.18.80.0/23 -203.18.87.0/24 -203.18.100.0/23 -203.18.105.0/24 -203.18.107.0/24 -203.18.110.0/24 -203.18.129.0/24 -203.18.131.0/24 -203.18.132.0/23 -203.18.144.0/24 -203.18.153.0/24 -203.18.199.0/24 -203.18.208.0/24 -203.18.211.0/24 -203.18.215.0/24 -203.19.1.0/24 -203.19.18.0/24 -203.19.24.0/24 -203.19.30.0/24 -203.19.32.0/21 -203.19.41.0/24 -203.19.44.0/23 -203.19.46.0/24 -203.19.58.0/24 -203.19.60.0/23 -203.19.64.0/24 -203.19.68.0/24 -203.19.72.0/24 -203.19.101.0/24 -203.19.111.0/24 -203.19.131.0/24 -203.19.133.0/24 -203.19.144.0/24 -203.19.147.0/24 -203.19.149.0/24 -203.19.156.0/24 -203.19.176.0/24 -203.19.178.0/23 -203.19.208.0/24 -203.19.228.0/22 -203.19.233.0/24 -203.19.242.0/24 -203.19.248.0/23 -203.19.255.0/24 -203.20.17.0/24 -203.20.40.0/23 -203.20.44.0/24 -203.20.48.0/24 -203.20.61.0/24 -203.20.65.0/24 -203.20.84.0/23 -203.20.89.0/24 -203.20.106.0/23 -203.20.115.0/24 -203.20.117.0/24 -203.20.118.0/23 -203.20.122.0/24 -203.20.126.0/23 -203.20.135.0/24 -203.20.136.0/21 -203.20.150.0/24 -203.20.230.0/24 -203.20.232.0/24 -203.20.236.0/24 -203.21.0.0/23 -203.21.2.0/24 -203.21.8.0/24 -203.21.10.0/24 -203.21.18.0/24 -203.21.33.0/24 -203.21.34.0/24 -203.21.41.0/24 -203.21.44.0/24 -203.21.68.0/24 -203.21.82.0/24 -203.21.96.0/22 -203.21.124.0/24 -203.21.136.0/23 -203.21.145.0/24 -203.21.206.0/24 -203.22.24.0/24 -203.22.28.0/23 -203.22.31.0/24 -203.22.68.0/24 -203.22.76.0/24 -203.22.78.0/24 -203.22.84.0/24 -203.22.87.0/24 -203.22.92.0/22 -203.22.99.0/24 -203.22.106.0/24 -203.22.122.0/23 -203.22.131.0/24 -203.22.163.0/24 -203.22.166.0/24 -203.22.170.0/24 -203.22.176.0/21 -203.22.194.0/24 -203.22.242.0/23 -203.22.245.0/24 -203.22.246.0/24 -203.22.252.0/23 -203.23.0.0/24 -203.23.47.0/24 -203.23.61.0/24 -203.23.62.0/23 -203.23.73.0/24 -203.23.85.0/24 -203.23.92.0/22 -203.23.98.0/24 -203.23.107.0/24 -203.23.112.0/24 -203.23.130.0/24 -203.23.140.0/23 -203.23.172.0/24 -203.23.182.0/24 -203.23.186.0/23 -203.23.192.0/24 -203.23.197.0/24 -203.23.198.0/24 -203.23.204.0/22 -203.23.224.0/24 -203.23.226.0/23 -203.23.228.0/22 -203.23.249.0/24 -203.23.251.0/24 -203.24.13.0/24 -203.24.18.0/24 -203.24.27.0/24 -203.24.43.0/24 -203.24.56.0/24 -203.24.58.0/24 -203.24.67.0/24 -203.24.74.0/24 -203.24.79.0/24 -203.24.80.0/23 -203.24.84.0/23 -203.24.86.0/24 -203.24.90.0/24 -203.24.111.0/24 -203.24.112.0/24 -203.24.116.0/24 -203.24.122.0/23 -203.24.145.0/24 -203.24.152.0/23 -203.24.157.0/24 -203.24.161.0/24 -203.24.167.0/24 -203.24.186.0/23 -203.24.199.0/24 -203.24.202.0/24 -203.24.212.0/23 -203.24.217.0/24 -203.24.219.0/24 -203.24.244.0/24 -203.25.19.0/24 -203.25.20.0/23 -203.25.46.0/24 -203.25.48.0/21 -203.25.64.0/23 -203.25.91.0/24 -203.25.99.0/24 -203.25.100.0/24 -203.25.106.0/24 -203.25.131.0/24 -203.25.135.0/24 -203.25.138.0/24 -203.25.147.0/24 -203.25.153.0/24 -203.25.154.0/23 -203.25.164.0/24 -203.25.166.0/24 -203.25.174.0/23 -203.25.180.0/24 -203.25.182.0/24 -203.25.191.0/24 -203.25.199.0/24 -203.25.200.0/24 -203.25.202.0/23 -203.25.208.0/20 -203.25.229.0/24 -203.25.235.0/24 -203.25.236.0/24 -203.25.242.0/24 -203.26.12.0/24 -203.26.34.0/24 -203.26.49.0/24 -203.26.50.0/24 -203.26.55.0/24 -203.26.56.0/23 -203.26.60.0/24 -203.26.65.0/24 -203.26.68.0/24 -203.26.76.0/24 -203.26.80.0/24 -203.26.84.0/24 -203.26.97.0/24 -203.26.102.0/23 -203.26.115.0/24 -203.26.116.0/24 -203.26.129.0/24 -203.26.143.0/24 -203.26.144.0/24 -203.26.148.0/23 -203.26.154.0/24 -203.26.158.0/23 -203.26.170.0/24 -203.26.173.0/24 -203.26.176.0/24 -203.26.185.0/24 -203.26.202.0/23 -203.26.210.0/24 -203.26.214.0/24 -203.26.222.0/24 -203.26.224.0/24 -203.26.228.0/24 -203.26.232.0/24 -203.27.0.0/24 -203.27.10.0/24 -203.27.15.0/24 -203.27.16.0/24 -203.27.20.0/24 -203.27.22.0/23 -203.27.40.0/24 -203.27.45.0/24 -203.27.53.0/24 -203.27.65.0/24 -203.27.66.0/24 -203.27.81.0/24 -203.27.88.0/24 -203.27.102.0/24 -203.27.109.0/24 -203.27.117.0/24 -203.27.121.0/24 -203.27.122.0/23 -203.27.125.0/24 -203.27.200.0/24 -203.27.202.0/24 -203.27.233.0/24 -203.27.241.0/24 -203.27.250.0/24 -203.28.10.0/24 -203.28.12.0/24 -203.28.33.0/24 -203.28.34.0/23 -203.28.43.0/24 -203.28.44.0/24 -203.28.54.0/24 -203.28.56.0/24 -203.28.73.0/24 -203.28.74.0/24 -203.28.76.0/24 -203.28.86.0/24 -203.28.88.0/24 -203.28.112.0/24 -203.28.131.0/24 -203.28.136.0/24 -203.28.140.0/24 -203.28.145.0/24 -203.28.165.0/24 -203.28.169.0/24 -203.28.170.0/24 -203.28.178.0/23 -203.28.185.0/24 -203.28.187.0/24 -203.28.196.0/24 -203.28.226.0/23 -203.28.239.0/24 -203.29.2.0/24 -203.29.8.0/23 -203.29.13.0/24 -203.29.14.0/24 -203.29.28.0/24 -203.29.46.0/24 -203.29.57.0/24 -203.29.61.0/24 -203.29.63.0/24 -203.29.69.0/24 -203.29.73.0/24 -203.29.81.0/24 -203.29.90.0/24 -203.29.95.0/24 -203.29.100.0/24 -203.29.103.0/24 -203.29.112.0/24 -203.29.120.0/22 -203.29.182.0/23 -203.29.187.0/24 -203.29.189.0/24 -203.29.190.0/24 -203.29.205.0/24 -203.29.210.0/24 -203.29.217.0/24 -203.29.227.0/24 -203.29.231.0/24 -203.29.233.0/24 -203.29.234.0/24 -203.29.248.0/24 -203.29.254.0/23 -203.30.16.0/23 -203.30.25.0/24 -203.30.27.0/24 -203.30.29.0/24 -203.30.66.0/24 -203.30.81.0/24 -203.30.87.0/24 -203.30.111.0/24 -203.30.121.0/24 -203.30.123.0/24 -203.30.152.0/24 -203.30.156.0/24 -203.30.162.0/24 -203.30.173.0/24 -203.30.175.0/24 -203.30.187.0/24 -203.30.194.0/24 -203.30.217.0/24 -203.30.220.0/24 -203.30.222.0/24 -203.30.232.0/23 -203.30.235.0/24 -203.30.240.0/23 -203.30.246.0/24 -203.30.250.0/23 -203.31.45.0/24 -203.31.46.0/24 -203.31.49.0/24 -203.31.51.0/24 -203.31.54.0/23 -203.31.69.0/24 -203.31.72.0/24 -203.31.80.0/24 -203.31.85.0/24 -203.31.97.0/24 -203.31.105.0/24 -203.31.106.0/24 -203.31.108.0/23 -203.31.124.0/24 -203.31.162.0/24 -203.31.174.0/24 -203.31.177.0/24 -203.31.181.0/24 -203.31.187.0/24 -203.31.189.0/24 -203.31.204.0/24 -203.31.220.0/24 -203.31.222.0/23 -203.31.225.0/24 -203.31.229.0/24 -203.31.248.0/23 -203.31.253.0/24 -203.32.20.0/24 -203.32.48.0/23 -203.32.56.0/24 -203.32.60.0/24 -203.32.62.0/24 -203.32.68.0/23 -203.32.76.0/24 -203.32.81.0/24 -203.32.84.0/23 -203.32.95.0/24 -203.32.102.0/24 -203.32.105.0/24 -203.32.130.0/24 -203.32.133.0/24 -203.32.140.0/24 -203.32.152.0/24 -203.32.186.0/23 -203.32.192.0/24 -203.32.196.0/24 -203.32.203.0/24 -203.32.204.0/23 -203.32.212.0/24 -203.33.4.0/24 -203.33.7.0/24 -203.33.8.0/21 -203.33.21.0/24 -203.33.26.0/24 -203.33.32.0/24 -203.33.63.0/24 -203.33.64.0/24 -203.33.67.0/24 -203.33.68.0/24 -203.33.73.0/24 -203.33.79.0/24 -203.33.100.0/24 -203.33.122.0/24 -203.33.129.0/24 -203.33.131.0/24 -203.33.145.0/24 -203.33.156.0/24 -203.33.158.0/23 -203.33.174.0/24 -203.33.185.0/24 -203.33.200.0/24 -203.33.202.0/23 -203.33.204.0/24 -203.33.206.0/23 -203.33.214.0/23 -203.33.224.0/23 -203.33.226.0/24 -203.33.233.0/24 -203.33.243.0/24 -203.33.250.0/24 -203.34.4.0/24 -203.34.21.0/24 -203.34.27.0/24 -203.34.39.0/24 -203.34.48.0/23 -203.34.54.0/24 -203.34.56.0/23 -203.34.67.0/24 -203.34.69.0/24 -203.34.76.0/24 -203.34.92.0/24 -203.34.106.0/24 -203.34.113.0/24 -203.34.147.0/24 -203.34.150.0/24 -203.34.152.0/23 -203.34.161.0/24 -203.34.162.0/24 -203.34.187.0/24 -203.34.192.0/21 -203.34.204.0/22 -203.34.232.0/24 -203.34.240.0/24 -203.34.242.0/24 -203.34.245.0/24 -203.34.251.0/24 -203.55.2.0/23 -203.55.4.0/24 -203.55.10.0/24 -203.55.13.0/24 -203.55.22.0/24 -203.55.30.0/24 -203.55.93.0/24 -203.55.101.0/24 -203.55.109.0/24 -203.55.110.0/24 -203.55.116.0/23 -203.55.119.0/24 -203.55.128.0/23 -203.55.146.0/23 -203.55.192.0/24 -203.55.196.0/24 -203.55.218.0/23 -203.55.221.0/24 -203.55.224.0/24 -203.56.1.0/24 -203.56.4.0/24 -203.56.12.0/24 -203.56.24.0/24 -203.56.38.0/24 -203.56.40.0/24 -203.56.46.0/24 -203.56.48.0/21 -203.56.68.0/23 -203.56.82.0/23 -203.56.84.0/23 -203.56.95.0/24 -203.56.110.0/24 -203.56.121.0/24 -203.56.161.0/24 -203.56.169.0/24 -203.56.172.0/23 -203.56.175.0/24 -203.56.183.0/24 -203.56.185.0/24 -203.56.187.0/24 -203.56.192.0/24 -203.56.198.0/24 -203.56.201.0/24 -203.56.208.0/23 -203.56.210.0/24 -203.56.214.0/24 -203.56.216.0/24 -203.56.227.0/24 -203.56.228.0/24 -203.56.231.0/24 -203.56.232.0/24 -203.56.240.0/24 -203.56.252.0/24 -203.56.254.0/24 -203.57.5.0/24 -203.57.6.0/24 -203.57.12.0/23 -203.57.28.0/24 -203.57.39.0/24 -203.57.46.0/24 -203.57.58.0/24 -203.57.61.0/24 -203.57.66.0/24 -203.57.69.0/24 -203.57.70.0/23 -203.57.73.0/24 -203.57.90.0/24 -203.57.101.0/24 -203.57.109.0/24 -203.57.123.0/24 -203.57.157.0/24 -203.57.200.0/24 -203.57.202.0/24 -203.57.206.0/24 -203.57.222.0/24 -203.57.224.0/20 -203.57.246.0/23 -203.57.249.0/24 -203.57.253.0/24 -203.57.254.0/23 -203.62.2.0/24 -203.62.131.0/24 -203.62.139.0/24 -203.62.161.0/24 -203.62.197.0/24 -203.62.228.0/22 -203.62.234.0/24 -203.62.246.0/24 -203.76.160.0/22 -203.76.168.0/22 -203.76.208.0/22 -203.76.212.0/22 -203.76.216.0/22 -203.76.240.0/22 -203.76.244.0/22 -203.77.180.0/22 -203.78.48.0/20 -203.78.156.0/22 -203.79.0.0/20 -203.79.32.0/20 -203.80.4.0/23 -203.80.32.0/20 -203.80.57.0/24 -203.80.129.0/24 -203.80.132.0/22 -203.80.136.0/21 -203.80.144.0/20 -203.81.0.0/21 -203.81.16.0/20 -203.81.244.0/22 -203.82.0.0/23 -203.82.16.0/21 -203.82.112.0/22 -203.82.116.0/22 -203.82.120.0/22 -203.82.124.0/22 -203.82.224.0/22 -203.82.228.0/22 -203.82.232.0/22 -203.82.236.0/22 -203.83.0.0/22 -203.83.8.0/22 -203.83.12.0/22 -203.83.56.0/21 -203.83.224.0/20 -203.86.0.0/19 -203.86.32.0/19 -203.86.64.0/20 -203.86.80.0/20 -203.86.96.0/19 -203.86.250.0/24 -203.86.254.0/23 -203.88.32.0/19 -203.88.100.0/22 -203.88.192.0/19 -203.89.0.0/22 -203.89.8.0/21 -203.89.100.0/22 -203.89.133.0/24 -203.89.136.0/22 -203.89.144.0/24 -203.90.0.0/22 -203.90.8.0/22 -203.90.12.0/22 -203.90.128.0/19 -203.90.160.0/19 -203.90.192.0/19 -203.91.32.0/19 -203.91.96.0/20 -203.91.120.0/21 -203.92.0.0/22 -203.92.6.0/24 -203.92.160.0/19 -203.93.0.0/22 -203.93.4.0/22 -203.93.8.0/24 -203.93.9.0/24 -203.93.10.0/23 -203.93.12.0/22 -203.93.16.0/20 -203.93.32.0/19 -203.93.64.0/18 -203.93.128.0/21 -203.93.136.0/22 -203.93.140.0/24 -203.93.141.0/24 -203.93.142.0/23 -203.93.144.0/20 -203.93.160.0/19 -203.93.192.0/18 -203.94.0.0/22 -203.94.4.0/22 -203.94.8.0/21 -203.94.16.0/20 -203.95.0.0/21 -203.95.96.0/20 -203.95.112.0/20 -203.95.128.0/18 -203.95.200.0/22 -203.95.204.0/22 -203.95.208.0/22 -203.95.224.0/19 -203.99.8.0/21 -203.99.16.0/20 -203.99.80.0/20 -203.100.32.0/20 -203.100.48.0/21 -203.100.58.0/24 -203.100.60.0/24 -203.100.63.0/24 -203.100.80.0/20 -203.100.96.0/19 -203.100.192.0/20 -203.104.32.0/20 -203.105.96.0/19 -203.105.128.0/19 -203.107.0.0/17 -203.110.160.0/19 -203.110.208.0/20 -203.110.232.0/23 -203.110.234.0/24 -203.114.80.0/22 -203.114.84.0/22 -203.114.88.0/22 -203.114.92.0/22 -203.114.244.0/22 -203.118.192.0/19 -203.118.241.0/24 -203.118.248.0/22 -203.119.24.0/21 -203.119.32.0/22 -203.119.80.0/22 -203.119.85.0/24 -203.119.113.0/24 -203.119.114.0/23 -203.119.116.0/22 -203.119.120.0/21 -203.119.128.0/17 -203.123.58.0/24 -203.128.32.0/19 -203.128.96.0/19 -203.128.224.0/21 -203.129.8.0/21 -203.130.32.0/19 -203.132.32.0/19 -203.134.240.0/21 -203.135.96.0/20 -203.135.112.0/20 -203.135.160.0/20 -203.142.219.0/24 -203.142.224.0/19 -203.144.96.0/19 -203.145.0.0/19 -203.148.0.0/18 -203.148.64.0/20 -203.148.80.0/22 -203.148.86.0/23 -203.149.92.0/22 -203.152.64.0/19 -203.152.128.0/19 -203.153.0.0/22 -203.156.192.0/18 -203.158.16.0/21 -203.160.52.0/22 -203.160.104.0/21 -203.160.129.0/24 -203.160.192.0/19 -203.161.0.0/22 -203.161.180.0/24 -203.161.183.0/24 -203.161.192.0/19 -203.166.160.0/19 -203.167.28.0/22 -203.168.0.0/19 -203.170.58.0/23 -203.171.0.0/22 -203.171.208.0/24 -203.171.224.0/20 -203.174.4.0/24 -203.174.6.0/24 -203.174.7.0/24 -203.174.96.0/19 -203.175.128.0/19 -203.175.192.0/18 -203.176.0.0/18 -203.176.64.0/19 -203.176.168.0/21 -203.184.80.0/20 -203.185.189.0/24 -203.187.160.0/19 -203.189.0.0/23 -203.189.6.0/23 -203.189.112.0/22 -203.189.192.0/19 -203.189.232.0/22 -203.189.240.0/22 -203.190.96.0/20 -203.190.249.0/24 -203.191.0.0/23 -203.191.2.0/24 -203.191.5.0/24 -203.191.7.0/24 -203.191.16.0/20 -203.191.64.0/18 -203.191.133.0/24 -203.191.144.0/21 -203.191.152.0/21 -203.192.0.0/19 -203.193.224.0/19 -203.194.120.0/21 -203.195.64.0/19 -203.195.112.0/21 -203.195.128.0/17 -203.196.0.0/21 -203.196.8.0/21 -203.196.28.0/22 -203.201.181.0/24 -203.201.182.0/24 -203.202.236.0/22 -203.205.64.0/19 -203.205.128.0/17 -203.207.64.0/20 -203.207.80.0/21 -203.207.88.0/22 -203.207.92.0/22 -203.207.96.0/20 -203.207.112.0/20 -203.207.128.0/18 -203.207.192.0/21 -203.207.200.0/21 -203.207.208.0/20 -203.207.224.0/19 -203.208.0.0/20 -203.208.16.0/22 -203.208.32.0/19 -203.209.224.0/19 -203.212.0.0/20 -203.212.80.0/20 -203.215.232.0/21 -203.217.164.0/22 -203.223.0.0/20 -203.223.16.0/21 -204.52.191.0/24 -210.2.0.0/20 -210.2.16.0/20 -210.5.0.0/19 -210.5.56.0/21 -210.5.128.0/20 -210.5.144.0/20 -210.7.56.0/22 -210.7.60.0/22 -210.12.0.0/18 -210.12.64.0/18 -210.12.128.0/18 -210.12.192.0/18 -210.13.0.0/18 -210.13.64.0/18 -210.13.128.0/17 -210.14.64.0/19 -210.14.112.0/20 -210.14.128.0/19 -210.14.160.0/19 -210.14.192.0/19 -210.14.224.0/19 -210.15.0.0/19 -210.15.32.0/19 -210.15.64.0/19 -210.15.96.0/19 -210.15.128.0/18 -210.16.104.0/22 -210.16.128.0/18 -210.21.0.0/17 -210.21.128.0/17 -210.22.0.0/16 -210.23.32.0/19 -210.25.0.0/16 -210.26.0.0/15 -210.28.0.0/14 -210.32.0.0/14 -210.36.0.0/14 -210.40.0.0/13 -210.51.0.0/16 -210.52.0.0/18 -210.52.64.0/18 -210.52.128.0/17 -210.53.0.0/17 -210.53.128.0/17 -210.56.192.0/19 -210.72.0.0/17 -210.72.128.0/19 -210.72.160.0/19 -210.72.192.0/18 -210.73.0.0/19 -210.73.32.0/19 -210.73.64.0/18 -210.73.128.0/17 -210.74.0.0/19 -210.74.32.0/19 -210.74.64.0/19 -210.74.96.0/19 -210.74.128.0/19 -210.74.160.0/19 -210.74.192.0/18 -210.75.0.0/16 -210.76.0.0/19 -210.76.32.0/19 -210.76.64.0/18 -210.76.128.0/17 -210.77.0.0/16 -210.78.0.0/19 -210.78.32.0/19 -210.78.64.0/18 -210.78.128.0/19 -210.78.160.0/19 -210.78.192.0/18 -210.79.64.0/18 -210.79.224.0/19 -210.82.0.0/15 -210.87.128.0/20 -210.87.144.0/20 -210.87.160.0/19 -210.185.192.0/18 -210.192.96.0/19 -211.64.0.0/14 -211.68.0.0/15 -211.70.0.0/15 -211.80.0.0/16 -211.81.0.0/16 -211.82.0.0/16 -211.83.0.0/16 -211.84.0.0/15 -211.86.0.0/15 -211.88.0.0/16 -211.89.0.0/16 -211.90.0.0/15 -211.92.0.0/15 -211.94.0.0/15 -211.96.0.0/15 -211.98.0.0/16 -211.99.0.0/18 -211.99.64.0/19 -211.99.96.0/19 -211.99.128.0/17 -211.100.0.0/16 -211.101.0.0/18 -211.101.64.0/18 -211.101.128.0/17 -211.102.0.0/16 -211.103.0.0/17 -211.103.128.0/17 -211.136.0.0/14 -211.140.0.0/15 -211.142.0.0/17 -211.142.128.0/17 -211.143.0.0/16 -211.144.0.0/15 -211.146.0.0/16 -211.147.0.0/16 -211.148.0.0/14 -211.152.0.0/15 -211.154.0.0/16 -211.155.0.0/18 -211.155.64.0/19 -211.155.96.0/19 -211.155.128.0/17 -211.156.0.0/14 -211.160.0.0/14 -211.164.0.0/14 -212.64.0.0/17 -212.129.128.0/17 -218.0.0.0/16 -218.1.0.0/16 -218.2.0.0/15 -218.4.0.0/15 -218.6.0.0/16 -218.7.0.0/16 -218.8.0.0/15 -218.10.0.0/16 -218.11.0.0/16 -218.12.0.0/16 -218.13.0.0/16 -218.14.0.0/15 -218.16.0.0/14 -218.20.0.0/16 -218.21.0.0/17 -218.21.128.0/17 -218.22.0.0/15 -218.24.0.0/15 -218.26.0.0/16 -218.27.0.0/16 -218.28.0.0/15 -218.30.0.0/15 -218.56.0.0/14 -218.60.0.0/15 -218.62.0.0/17 -218.62.128.0/17 -218.63.0.0/16 -218.64.0.0/15 -218.66.0.0/16 -218.67.0.0/17 -218.67.128.0/17 -218.68.0.0/15 -218.70.0.0/15 -218.72.0.0/14 -218.76.0.0/15 -218.78.0.0/15 -218.80.0.0/14 -218.84.0.0/14 -218.88.0.0/13 -218.96.0.0/15 -218.98.0.0/17 -218.98.128.0/18 -218.98.192.0/19 -218.98.224.0/19 -218.99.0.0/16 -218.100.88.0/21 -218.100.96.0/19 -218.100.128.0/17 -218.104.0.0/17 -218.104.128.0/19 -218.104.160.0/19 -218.104.192.0/21 -218.104.200.0/21 -218.104.208.0/20 -218.104.224.0/19 -218.105.0.0/16 -218.106.0.0/15 -218.108.0.0/16 -218.109.0.0/16 -218.185.192.0/19 -218.185.240.0/21 -218.192.0.0/16 -218.193.0.0/16 -218.194.0.0/16 -218.195.0.0/16 -218.196.0.0/14 -218.200.0.0/14 -218.204.0.0/15 -218.206.0.0/15 -218.240.0.0/14 -218.244.0.0/15 -218.246.0.0/15 -218.249.0.0/16 -219.72.0.0/16 -219.82.0.0/16 -219.83.128.0/17 -219.90.68.0/22 -219.90.72.0/22 -219.90.76.0/22 -219.128.0.0/12 -219.144.0.0/14 -219.148.0.0/16 -219.149.0.0/17 -219.149.128.0/18 -219.149.192.0/18 -219.150.0.0/19 -219.150.32.0/19 -219.150.64.0/19 -219.150.96.0/20 -219.150.112.0/20 -219.150.128.0/17 -219.151.0.0/19 -219.151.32.0/19 -219.151.64.0/18 -219.151.128.0/17 -219.152.0.0/15 -219.154.0.0/15 -219.156.0.0/15 -219.158.0.0/17 -219.158.128.0/17 -219.159.0.0/18 -219.159.64.0/18 -219.159.128.0/17 -219.216.0.0/15 -219.218.0.0/15 -219.220.0.0/16 -219.221.0.0/16 -219.222.0.0/15 -219.224.0.0/15 -219.226.0.0/16 -219.227.0.0/16 -219.228.0.0/15 -219.230.0.0/15 -219.232.0.0/14 -219.236.0.0/15 -219.238.0.0/15 -219.242.0.0/15 -219.244.0.0/14 -220.101.192.0/18 -220.112.0.0/14 -220.152.128.0/17 -220.154.0.0/15 -220.158.240.0/22 -220.160.0.0/11 -220.192.0.0/15 -220.194.0.0/15 -220.196.0.0/14 -220.200.0.0/13 -220.231.0.0/18 -220.231.128.0/17 -220.232.64.0/18 -220.234.0.0/16 -220.242.0.0/15 -220.247.136.0/21 -220.248.0.0/14 -220.252.0.0/16 -221.0.0.0/15 -221.2.0.0/16 -221.3.0.0/17 -221.3.128.0/17 -221.4.0.0/16 -221.5.0.0/17 -221.5.128.0/17 -221.6.0.0/16 -221.7.0.0/19 -221.7.32.0/19 -221.7.64.0/19 -221.7.96.0/19 -221.7.128.0/17 -221.8.0.0/15 -221.10.0.0/16 -221.11.0.0/17 -221.11.128.0/18 -221.11.192.0/19 -221.11.224.0/19 -221.12.0.0/17 -221.12.128.0/18 -221.13.0.0/18 -221.13.64.0/19 -221.13.96.0/19 -221.13.128.0/17 -221.14.0.0/15 -221.122.0.0/15 -221.128.128.0/17 -221.129.0.0/16 -221.130.0.0/15 -221.133.224.0/19 -221.136.0.0/16 -221.137.0.0/16 -221.172.0.0/14 -221.176.0.0/13 -221.192.0.0/15 -221.194.0.0/16 -221.195.0.0/16 -221.196.0.0/15 -221.198.0.0/16 -221.199.0.0/19 -221.199.32.0/20 -221.199.48.0/20 -221.199.64.0/18 -221.199.128.0/18 -221.199.192.0/20 -221.199.224.0/19 -221.200.0.0/14 -221.204.0.0/15 -221.206.0.0/16 -221.207.0.0/18 -221.207.64.0/18 -221.207.128.0/17 -221.208.0.0/14 -221.212.0.0/16 -221.213.0.0/16 -221.214.0.0/15 -221.216.0.0/13 -221.224.0.0/13 -221.232.0.0/14 -221.236.0.0/15 -221.238.0.0/16 -221.239.0.0/17 -221.239.128.0/17 -222.16.0.0/15 -222.18.0.0/15 -222.20.0.0/15 -222.22.0.0/16 -222.23.0.0/16 -222.24.0.0/15 -222.26.0.0/15 -222.28.0.0/14 -222.32.0.0/11 -222.64.0.0/13 -222.72.0.0/15 -222.74.0.0/16 -222.75.0.0/16 -222.76.0.0/14 -222.80.0.0/15 -222.82.0.0/16 -222.83.0.0/17 -222.83.128.0/17 -222.84.0.0/16 -222.85.0.0/17 -222.85.128.0/17 -222.86.0.0/15 -222.88.0.0/15 -222.90.0.0/15 -222.92.0.0/14 -222.125.0.0/16 -222.126.128.0/17 -222.128.0.0/14 -222.132.0.0/14 -222.136.0.0/13 -222.160.0.0/15 -222.162.0.0/16 -222.163.0.0/19 -222.163.32.0/19 -222.163.64.0/18 -222.163.128.0/17 -222.168.0.0/15 -222.170.0.0/15 -222.172.0.0/17 -222.172.128.0/17 -222.173.0.0/16 -222.174.0.0/15 -222.176.0.0/13 -222.184.0.0/13 -222.192.0.0/14 -222.196.0.0/15 -222.198.0.0/16 -222.199.0.0/16 -222.200.0.0/14 -222.204.0.0/15 -222.206.0.0/15 -222.208.0.0/13 -222.216.0.0/15 -222.218.0.0/16 -222.219.0.0/16 -222.220.0.0/15 -222.222.0.0/15 -222.240.0.0/13 -222.248.0.0/16 -222.249.0.0/17 -222.249.128.0/19 -222.249.160.0/20 -222.249.176.0/20 -222.249.192.0/18 -223.0.0.0/15 -223.2.0.0/15 -223.4.0.0/14 -223.8.0.0/13 -223.20.0.0/15 -223.27.184.0/22 -223.29.208.0/22 -223.29.252.0/22 -223.64.0.0/11 -223.96.0.0/12 -223.112.0.0/14 -223.116.0.0/15 -223.120.128.0/17 -223.121.128.0/17 -223.122.0.0/15 -223.124.0.0/14 -223.128.0.0/15 -223.144.0.0/12 -223.160.0.0/14 -223.166.0.0/15 -223.192.0.0/15 -223.198.0.0/15 -223.201.0.0/16 -223.202.0.0/15 -223.208.0.0/14 -223.212.0.0/15 -223.214.0.0/15 -223.220.0.0/15 -223.223.176.0/20 -223.223.192.0/20 -223.240.0.0/13 -223.248.0.0/14 -223.252.128.0/17 -223.254.0.0/16 -223.255.0.0/17 -223.255.236.0/22 -223.255.252.0/23 diff --git a/package/lienol/luci-app-passwall/root/usr/share/passwall/rules/chnroute6 b/package/lienol/luci-app-passwall/root/usr/share/passwall/rules/chnroute6 deleted file mode 100644 index f205f0695a..0000000000 --- a/package/lienol/luci-app-passwall/root/usr/share/passwall/rules/chnroute6 +++ /dev/null @@ -1,1924 +0,0 @@ -2001:250::/35 -2001:250:2000::/35 -2001:250:4000::/34 -2001:250:8000::/33 -2001:251::/32 -2001:252::/32 -2001:254::/32 -2001:256::/32 -2001:7fa:5::/48 -2001:7fa:10::/48 -2001:c68::/32 -2001:cc0::/32 -2001:da8::/32 -2001:da9::/32 -2001:daa::/32 -2001:dc7::/32 -2001:dd8:1::/48 -2001:dd8:5::/48 -2001:dd8:1a::/48 -2001:dd9::/48 -2001:df0:27e::/48 -2001:df0:423::/48 -2001:df0:2180::/48 -2001:df0:2d80::/48 -2001:df0:2e00::/48 -2001:df0:2e80::/48 -2001:df0:4500::/48 -2001:df0:5d00::/48 -2001:df0:5d01::/48 -2001:df0:9a00::/48 -2001:df0:b180::/48 -2001:df0:bf80::/48 -2001:df0:d180::/48 -2001:df0:d880::/48 -2001:df1:c80::/48 -2001:df1:4580::/48 -2001:df1:5280::/48 -2001:df1:5b80::/48 -2001:df1:6180::/48 -2001:df1:6b80::/48 -2001:df1:8b00::/48 -2001:df1:a100::/48 -2001:df1:bd80::/48 -2001:df1:c900::/48 -2001:df1:d100::/48 -2001:df1:d180::/48 -2001:df1:da00::/48 -2001:df1:e600::/48 -2001:df1:f480::/48 -2001:df1:f580::/48 -2001:df1:fd80::/48 -2001:df2:80::/48 -2001:df2:180::/48 -2001:df2:5200::/48 -2001:df2:5780::/48 -2001:df2:5a80::/48 -2001:df2:a580::/48 -2001:df3:1480::/48 -2001:df3:2a80::/48 -2001:df3:3a80::/48 -2001:df3:a680::/48 -2001:df3:b100::/48 -2001:df3:b380::/48 -2001:df3:c380::/48 -2001:df3:c680::/48 -2001:df3:d880::/48 -2001:df3:ed80::/48 -2001:df3:ef80::/48 -2001:df4:80::/48 -2001:df4:880::/48 -2001:df4:d80::/48 -2001:df4:1280::/48 -2001:df4:1500::/48 -2001:df4:1880::/48 -2001:df4:2780::/48 -2001:df4:2e80::/48 -2001:df4:2f00::/48 -2001:df4:3c80::/48 -2001:df4:3d80::/48 -2001:df4:4b80::/48 -2001:df4:4d80::/48 -2001:df4:5900::/48 -2001:df4:a680::/48 -2001:df4:a980::/48 -2001:df4:c180::/48 -2001:df4:c580::/48 -2001:df4:c780::/48 -2001:df4:cf00::/48 -2001:df4:de80::/48 -2001:df5:2080::/48 -2001:df5:5f80::/48 -2001:df5:7800::/48 -2001:df6:100::/48 -2001:df6:1c00::/48 -2001:df6:3d00::/48 -2001:df6:5d00::/48 -2001:df6:6800::/48 -2001:df6:df00::/48 -2001:df6:f400::/48 -2001:df7:5900::/48 -2001:df7:6600::/48 -2001:df7:ab00::/48 -2001:e08::/32 -2001:e18::/32 -2001:e80::/32 -2001:e88::/32 -2001:f38::/32 -2001:f88::/32 -2001:4438::/32 -2001:4510::/29 -2400:1040::/32 -2400:12c0::/32 -2400:1340::/32 -2400:1380::/32 -2400:15c0::/32 -2400:1640::/32 -2400:16c0::/32 -2400:1740::/32 -2400:17c0::/32 -2400:1840::/32 -2400:18c0::/32 -2400:1940::/32 -2400:19c0::/32 -2400:1a40::/32 -2400:1ac0::/32 -2400:1b40::/32 -2400:1cc0::/32 -2400:1d40::/32 -2400:1dc0::/32 -2400:1e40::/32 -2400:1ec0::/32 -2400:1f40::/32 -2400:1fc0::/32 -2400:3040::/32 -2400:3140::/32 -2400:31c0::/32 -2400:3200::/32 -2400:3280::/32 -2400:32c0::/32 -2400:3340::/32 -2400:33c0::/32 -2400:3440::/32 -2400:34c0::/32 -2400:3540::/32 -2400:35c0::/32 -2400:3600::/32 -2400:3640::/32 -2400:36c0::/32 -2400:38c0::/32 -2400:39c0::/32 -2400:3a00::/32 -2400:3a40::/32 -2400:3b40::/32 -2400:3bc0::/32 -2400:3c40::/32 -2400:3cc0::/32 -2400:3e00::/32 -2400:3f40::/32 -2400:3fc0::/32 -2400:4440::/32 -2400:44c0::/32 -2400:4540::/32 -2400:4600::/32 -2400:4640::/32 -2400:46c0::/32 -2400:4740::/32 -2400:4bc0::/32 -2400:4e00::/32 -2400:4e40::/32 -2400:5080::/32 -2400:5280::/32 -2400:5400::/32 -2400:5580::/32 -2400:55c0::/32 -2400:5600::/32 -2400:5640::/32 -2400:56c0::/32 -2400:57c0::/32 -2400:5840::/32 -2400:5a00::/32 -2400:5a40::/32 -2400:5ac0::/32 -2400:5b40::/32 -2400:5bc0::/32 -2400:5c40::/32 -2400:5c80::/32 -2400:5cc0::/32 -2400:5e80::/32 -2400:5fc0::/32 -2400:6000::/32 -2400:6040::/32 -2400:60c0::/32 -2400:61c0::/32 -2400:6200::/32 -2400:6600::/32 -2400:6640::/32 -2400:66c0::/32 -2400:6740::/32 -2400:67c0::/32 -2400:6840::/32 -2400:68c0::/32 -2400:6940::/32 -2400:69c0::/32 -2400:6a00::/32 -2400:6a40::/32 -2400:6ac0::/32 -2400:6b40::/32 -2400:6bc0::/32 -2400:6c40::/32 -2400:6cc0::/32 -2400:6d40::/32 -2400:6dc0::/32 -2400:6e00::/32 -2400:6e40::/32 -2400:6ec0::/32 -2400:6f40::/32 -2400:6f80::/32 -2400:6fc0::/32 -2400:7040::/32 -2400:7100::/32 -2400:7140::/32 -2400:71c0::/32 -2400:7200::/32 -2400:7240::/32 -2400:72c0::/32 -2400:7340::/32 -2400:73c0::/32 -2400:7440::/32 -2400:74c0::/32 -2400:7540::/32 -2400:75c0::/32 -2400:7640::/32 -2400:7680::/32 -2400:76c0::/32 -2400:7740::/32 -2400:77c0::/32 -2400:79c0::/32 -2400:7ac0::/32 -2400:7bc0::/32 -2400:7f80::/32 -2400:7fc0::/32 -2400:8080::/32 -2400:8200::/32 -2400:82c0::/32 -2400:8580::/32 -2400:8600::/32 -2400:8780::/32 -2400:87c0::/32 -2400:8840::/32 -2400:8980::/32 -2400:89c0::/32 -2400:8e00::/32 -2400:8f00::/32 -2400:8fc0::/32 -2400:9040::/32 -2400:9340::/32 -2400:9580::/32 -2400:95c0::/32 -2400:9600::/32 -2400:98c0::/32 -2400:9a00::/32 -2400:9dc0::/32 -2400:9e00::/32 -2400:a040::/32 -2400:a380::/32 -2400:a480::/32 -2400:a780::/32 -2400:a8c0::/32 -2400:a900::/32 -2400:a980::/32 -2400:a981::/32 -2400:a982::/31 -2400:a984::/30 -2400:abc0::/32 -2400:ae00::/32 -2400:b200::/32 -2400:b2c0::/32 -2400:b500::/32 -2400:b600::/32 -2400:b6c0::/32 -2400:b700::/32 -2400:b7c0::/32 -2400:b8c0::/32 -2400:b9c0::/32 -2400:ba00::/32 -2400:ba40::/32 -2400:ba41::/32 -2400:bac0::/32 -2400:bc40::/32 -2400:be00::/32 -2400:bf00::/32 -2400:c200::/32 -2400:c380::/32 -2400:c840::/32 -2400:c8c0::/32 -2400:c940::/32 -2400:c9c0::/32 -2400:ca40::/32 -2400:cac0::/32 -2400:cb40::/32 -2400:cb80::/32 -2400:cbc0::/32 -2400:cc40::/32 -2400:cc80::/32 -2400:ccc0::/32 -2400:cd40::/32 -2400:cdc0::/32 -2400:ce00::/32 -2400:ce40::/32 -2400:cf40::/32 -2400:cf80::/32 -2400:cfc0::/32 -2400:d0c0::/32 -2400:d100::/32 -2400:d1c0::/32 -2400:d200::/32 -2400:d300::/32 -2400:d440::/32 -2400:d600::/32 -2400:d6c0::/32 -2400:d780::/32 -2400:da00::/32 -2400:dd00::/28 -2400:dd40::/32 -2400:de00::/32 -2400:de80::/32 -2400:e0c0::/32 -2400:e140::/32 -2400:e5c0::/32 -2400:e680::/32 -2400:e880::/32 -2400:ebc0::/32 -2400:edc0::/32 -2400:ee00::/32 -2400:eec0::/32 -2400:ef40::/32 -2400:f480::/32 -2400:f5c0::/32 -2400:f7c0::/32 -2400:f840::/32 -2400:f980::/32 -2400:fac0::/32 -2400:fb40::/32 -2400:fbc0::/32 -2400:fc40::/32 -2400:fcc0::/32 -2400:fe00::/32 -2401:80::/32 -2401:140::/32 -2401:1c0::/32 -2401:540::/32 -2401:780::/32 -2401:7c0::/32 -2401:800::/32 -2401:9c0::/32 -2401:a00::/32 -2401:a40::/32 -2401:ac0::/32 -2401:b40::/32 -2401:bc0::/32 -2401:c40::/32 -2401:cc0::/32 -2401:d40::/32 -2401:e00::/32 -2401:1000::/32 -2401:11c0::/32 -2401:1200::/32 -2401:12c0::/32 -2401:15c0::/32 -2401:1740::/32 -2401:18c0::/32 -2401:1940::/32 -2401:19c0::/32 -2401:1a40::/32 -2401:1ac0::/32 -2401:1d40::/32 -2401:1dc0::/32 -2401:1e00::/32 -2401:1ec0::/32 -2401:1f40::/32 -2401:2040::/32 -2401:2080::/32 -2401:23c0::/32 -2401:2600::/32 -2401:2780::/32 -2401:2980::/32 -2401:2a00::/32 -2401:2b40::/32 -2401:2e00::/32 -2401:3100::/32 -2401:3380::/32 -2401:33c0::/32 -2401:3440::/32 -2401:3480::/32 -2401:34c0::/32 -2401:3640::/32 -2401:3780::/32 -2401:3800::/32 -2401:3880::/32 -2401:3980::/32 -2401:3a00::/32 -2401:3a80::/32 -2401:3b80::/32 -2401:3c80::/32 -2401:3d80::/32 -2401:3e80::/32 -2401:3f80::/32 -2401:4080::/32 -2401:4180::/32 -2401:4280::/32 -2401:4380::/32 -2401:4480::/32 -2401:4580::/32 -2401:4680::/32 -2401:4780::/32 -2401:4880::/32 -2401:4a80::/32 -2401:4b00::/32 -2401:4f80::/32 -2401:5180::/32 -2401:5680::/32 -2401:56c0::/32 -2401:59c0::/32 -2401:5b40::/32 -2401:5c80::/32 -2401:7180::/32 -2401:71c0::/32 -2401:7240::/32 -2401:7340::/32 -2401:7580::/32 -2401:7680::/32 -2401:7700::/32 -2401:7780::/32 -2401:7880::/32 -2401:7980::/32 -2401:7a00::/32 -2401:7a80::/32 -2401:7b80::/32 -2401:7bc0::/32 -2401:7c80::/32 -2401:7cc0::/32 -2401:7d40::/32 -2401:7d80::/32 -2401:7e00::/32 -2401:7f80::/32 -2401:8200::/32 -2401:82c0::/32 -2401:8380::/32 -2401:8540::/32 -2401:8600::/32 -2401:8680::/32 -2401:8840::/32 -2401:8d00::/32 -2401:8e40::/32 -2401:8f40::/32 -2401:8fc0::/32 -2401:9340::/32 -2401:9600::/32 -2401:96c0::/32 -2401:9740::/32 -2401:98c0::/32 -2401:9a00::/32 -2401:9ac0::/32 -2401:9b40::/32 -2401:9bc0::/32 -2401:9dc0::/32 -2401:9e40::/32 -2401:9f80::/32 -2401:a140::/32 -2401:a180::/32 -2401:a340::/32 -2401:a3c0::/32 -2401:a4c0::/32 -2401:a540::/32 -2401:a5c0::/32 -2401:a640::/32 -2401:a940::/32 -2401:a980::/32 -2401:aa00::/32 -2401:aa40::/32 -2401:acc0::/32 -2401:ad40::/32 -2401:adc0::/32 -2401:b040::/32 -2401:b180::/32 -2401:b340::/32 -2401:b400::/32 -2401:b480::/32 -2401:b4c0::/32 -2401:b540::/32 -2401:b580::/32 -2401:b600::/32 -2401:b680::/32 -2401:b6c0::/32 -2401:b7c0::/32 -2401:b940::/32 -2401:ba00::/32 -2401:ba40::/32 -2401:bb80::/32 -2401:be00::/32 -2401:c200::/32 -2401:c540::/32 -2401:c600::/32 -2401:c640::/32 -2401:c6c0::/32 -2401:c840::/32 -2401:c8c0::/32 -2401:ca00::/32 -2401:cb80::/32 -2401:cc00::/32 -2401:ce00::/32 -2401:cf40::/32 -2401:cfc0::/32 -2401:d0c0::/32 -2401:d140::/32 -2401:d180::/32 -2401:d2c0::/32 -2401:d340::/32 -2401:d780::/32 -2401:da00::/32 -2401:de00::/32 -2401:e080::/32 -2401:e0c0::/32 -2401:e140::/32 -2401:e240::/32 -2401:e2c0::/32 -2401:e340::/32 -2401:e6c0::/32 -2401:e840::/32 -2401:e8c0::/32 -2401:e940::/32 -2401:e9c0::/32 -2401:ec00::/32 -2401:ec40::/32 -2401:f300::/32 -2401:f7c0::/32 -2401:fa80::/32 -2401:fac0::/32 -2401:fb80::/32 -2401:fc80::/32 -2401:fe80::/32 -2401:ffc0::/32 -2402:440::/32 -2402:5c0::/32 -2402:840::/32 -2402:ac0::/32 -2402:e00::/32 -2402:fc0::/32 -2402:1000::/32 -2402:1440::/32 -2402:14c0::/32 -2402:1540::/32 -2402:1600::/32 -2402:1740::/32 -2402:19c0::/32 -2402:1ec0::/32 -2402:1f40::/32 -2402:1f80::/32 -2402:2000::/32 -2402:2280::/32 -2402:22c0::/32 -2402:2440::/32 -2402:24c0::/32 -2402:2540::/32 -2402:2640::/32 -2402:27c0::/32 -2402:2a00::/32 -2402:2b80::/32 -2402:2bc0::/32 -2402:2d00::/32 -2402:2d80::/32 -2402:2e80::/32 -2402:2f40::/32 -2402:3040::/32 -2402:3080::/32 -2402:3140::/32 -2402:3180::/32 -2402:31c0::/32 -2402:3240::/32 -2402:33c0::/32 -2402:39c0::/32 -2402:3a40::/32 -2402:3ac0::/32 -2402:3c00::/32 -2402:3e00::/32 -2402:3ec0::/32 -2402:3f40::/32 -2402:3f80::/32 -2402:4140::/32 -2402:42c0::/32 -2402:4340::/32 -2402:43c0::/32 -2402:4440::/32 -2402:4500::/32 -2402:4540::/32 -2402:4a00::/32 -2402:4a40::/32 -2402:4a80::/32 -2402:4ac0::/32 -2402:4b80::/32 -2402:4bc0::/32 -2402:4c40::/32 -2402:4d80::/32 -2402:4e00::/32 -2402:4ec0::/32 -2402:4f80::/32 -2402:50c0::/32 -2402:5140::/32 -2402:5180::/32 -2402:51c0::/32 -2402:5240::/32 -2402:52c0::/32 -2402:5340::/32 -2402:5880::/32 -2402:5940::/32 -2402:59c0::/32 -2402:5a40::/32 -2402:5b40::/32 -2402:5bc0::/32 -2402:5d00::/32 -2402:5e00::/32 -2402:5e40::/32 -2402:5ec0::/32 -2402:5f40::/32 -2402:6280::/32 -2402:62c0::/32 -2402:64c0::/32 -2402:65c0::/32 -2402:66c0::/32 -2402:6740::/32 -2402:67c0::/32 -2402:6a00::/32 -2402:6b40::/32 -2402:6bc0::/32 -2402:6e00::/32 -2402:6e80::/32 -2402:6ec0::/32 -2402:6f40::/32 -2402:6fc0::/32 -2402:7040::/32 -2402:7080::/32 -2402:70c0::/32 -2402:7140::/32 -2402:71c0::/32 -2402:7240::/32 -2402:72c0::/32 -2402:7540::/32 -2402:75c0::/32 -2402:7740::/32 -2402:7d00::/32 -2402:7d80::/32 -2402:8180::/32 -2402:8300::/32 -2402:8380::/32 -2402:85c0::/32 -2402:87c0::/32 -2402:8800::/32 -2402:8840::/32 -2402:8900::/32 -2402:8940::/32 -2402:89c0::/32 -2402:8b40::/32 -2402:8bc0::/32 -2402:8cc0::/32 -2402:8d40::/32 -2402:8f40::/32 -2402:8f80::/32 -2402:9240::/32 -2402:92c0::/32 -2402:93c0::/32 -2402:9440::/32 -2402:9480::/32 -2402:94c0::/32 -2402:9580::/32 -2402:95c0::/32 -2402:9680::/32 -2402:96c0::/32 -2402:9840::/32 -2402:98c0::/32 -2402:9940::/32 -2402:9a80::/32 -2402:9b80::/32 -2402:9f80::/32 -2402:9fc0::/32 -2402:a080::/32 -2402:a180::/32 -2402:a200::/32 -2402:a240::/32 -2402:a280::/32 -2402:a380::/32 -2402:a3c0::/32 -2402:a640::/32 -2402:a680::/32 -2402:a6c0::/32 -2402:a840::/32 -2402:a880::/32 -2402:a9c0::/32 -2402:aa80::/32 -2402:ab80::/32 -2402:ae00::/32 -2402:ae40::/32 -2402:aec0::/32 -2402:af80::/32 -2402:afc0::/32 -2402:b080::/32 -2402:b200::/32 -2402:b380::/32 -2402:b3c0::/32 -2402:b440::/32 -2402:b6c0::/32 -2402:b880::/32 -2402:b8c0::/32 -2402:b940::/32 -2402:b980::/32 -2402:ba80::/32 -2402:bac0::/32 -2402:bbc0::/32 -2402:bf80::/32 -2402:c280::/32 -2402:c3c0::/32 -2402:c5c0::/32 -2402:c9c0::/32 -2402:cbc0::/32 -2402:cc40::/32 -2402:cc80::/32 -2402:cf00::/32 -2402:cf40::/32 -2402:d040::/32 -2402:d140::/32 -2402:d2c0::/32 -2402:d300::/32 -2402:d340::/32 -2402:d380::/32 -2402:d5c0::/32 -2402:d6c0::/32 -2402:d740::/32 -2402:d780::/32 -2402:d880::/32 -2402:d980::/32 -2402:da40::/32 -2402:db40::/32 -2402:dcc0::/32 -2402:de40::/32 -2402:dec0::/32 -2402:df40::/32 -2402:dfc0::/32 -2402:e040::/32 -2402:e0c0::/32 -2402:e140::/32 -2402:e2c0::/32 -2402:e3c0::/32 -2402:e480::/32 -2402:e540::/32 -2402:e680::/32 -2402:e740::/32 -2402:e780::/32 -2402:e7c0::/32 -2402:e880::/32 -2402:e980::/32 -2402:eb80::/32 -2402:ec80::/32 -2402:ed80::/32 -2402:ef40::/32 -2402:ef80::/32 -2402:f000::/32 -2402:f140::/32 -2402:f340::/32 -2402:f3c0::/32 -2402:f480::/32 -2402:f540::/32 -2402:f580::/32 -2402:f740::/32 -2402:f780::/32 -2402:f8c0::/32 -2402:f980::/32 -2402:f9c0::/32 -2402:fac0::/32 -2402:fcc0::/32 -2402:ff40::/32 -2402:ffc0::/32 -2403:600::/32 -2403:700::/32 -2403:7c0::/32 -2403:800::/31 -2403:980::/32 -2403:a80::/32 -2403:b80::/32 -2403:c80::/32 -2403:d40::/32 -2403:d80::/32 -2403:e80::/32 -2403:f00::/32 -2403:f40::/32 -2403:f80::/32 -2403:fc0::/32 -2403:1180::/32 -2403:1340::/32 -2403:1440::/32 -2403:1580::/32 -2403:16c0::/32 -2403:17c0::/32 -2403:1980::/32 -2403:1a40::/32 -2403:1b80::/32 -2403:1c80::/32 -2403:1d80::/32 -2403:1dc0::/32 -2403:1e80::/32 -2403:1ec0::/32 -2403:1f80::/32 -2403:2040::/32 -2403:2080::/32 -2403:2180::/32 -2403:2240::/32 -2403:2280::/32 -2403:2380::/32 -2403:2440::/32 -2403:24c0::/32 -2403:2580::/32 -2403:25c0::/32 -2403:2680::/32 -2403:26c0::/32 -2403:2740::/32 -2403:2780::/32 -2403:28c0::/32 -2403:2940::/32 -2403:2a00::/32 -2403:2a40::/32 -2403:2ac0::/32 -2403:2b40::/32 -2403:2bc0::/32 -2403:2cc0::/32 -2403:2d80::/32 -2403:2f40::/32 -2403:2fc0::/32 -2403:3040::/32 -2403:30c0::/32 -2403:3140::/32 -2403:3280::/32 -2403:32c0::/32 -2403:3380::/32 -2403:3480::/32 -2403:3580::/32 -2403:3640::/32 -2403:3680::/32 -2403:36c0::/32 -2403:3740::/32 -2403:3780::/32 -2403:37c0::/32 -2403:3840::/32 -2403:3880::/32 -2403:38c0::/32 -2403:3940::/32 -2403:3980::/32 -2403:39c0::/32 -2403:3a40::/32 -2403:3b40::/32 -2403:3b80::/32 -2403:3bc0::/32 -2403:3c40::/32 -2403:3c80::/32 -2403:3cc0::/32 -2403:3d40::/32 -2403:3d80::/32 -2403:3dc0::/32 -2403:3e80::/32 -2403:3ec0::/32 -2403:3f40::/32 -2403:3f80::/32 -2403:4080::/32 -2403:4180::/32 -2403:4240::/32 -2403:4280::/32 -2403:4300::/32 -2403:4380::/32 -2403:4580::/32 -2403:4680::/32 -2403:4780::/32 -2403:4840::/32 -2403:4880::/32 -2403:4980::/32 -2403:4a40::/32 -2403:4a80::/32 -2403:4b40::/32 -2403:4b80::/32 -2403:4c80::/32 -2403:4cc0::/32 -2403:4d40::/32 -2403:4d80::/32 -2403:4ec0::/32 -2403:5040::/32 -2403:5080::/32 -2403:50c0::/32 -2403:5280::/32 -2403:5380::/32 -2403:54c0::/32 -2403:5540::/32 -2403:5580::/32 -2403:5640::/32 -2403:5780::/32 -2403:58c0::/32 -2403:5980::/32 -2403:5a80::/32 -2403:5b40::/32 -2403:5b80::/32 -2403:5c80::/32 -2403:5d80::/32 -2403:5e40::/32 -2403:5e80::/32 -2403:5ec0::/32 -2403:5f80::/32 -2403:5fc0::/32 -2403:6080::/32 -2403:6180::/32 -2403:6280::/32 -2403:62c0::/32 -2403:6380::/32 -2403:6580::/32 -2403:6680::/32 -2403:6740::/32 -2403:6780::/32 -2403:6880::/32 -2403:6980::/32 -2403:6a00::/32 -2403:6c80::/32 -2403:6d40::/32 -2403:6d80::/32 -2403:6e80::/32 -2403:6f40::/32 -2403:6fc0::/32 -2403:7040::/32 -2403:7080::/32 -2403:7180::/32 -2403:7280::/32 -2403:7380::/32 -2403:7480::/32 -2403:7540::/32 -2403:7580::/32 -2403:76c0::/32 -2403:7700::/32 -2403:7840::/32 -2403:78c0::/32 -2403:7a80::/32 -2403:7b00::/32 -2403:7d80::/32 -2403:7e80::/32 -2403:7f80::/32 -2403:8080::/32 -2403:8180::/32 -2403:8280::/32 -2403:8380::/32 -2403:83c0::/32 -2403:8480::/32 -2403:8580::/32 -2403:8880::/32 -2403:8900::/32 -2403:8980::/32 -2403:8a40::/32 -2403:8a80::/32 -2403:8b00::/32 -2403:8b80::/32 -2403:8c00::/32 -2403:8c80::/32 -2403:8d00::/32 -2403:8d80::/32 -2403:8f80::/32 -2403:9080::/32 -2403:9180::/32 -2403:9280::/32 -2403:9380::/32 -2403:9480::/32 -2403:9580::/32 -2403:9680::/32 -2403:9780::/32 -2403:9880::/32 -2403:9a80::/32 -2403:9ac0::/32 -2403:9b00::/32 -2403:9b40::/32 -2403:9b80::/32 -2403:9c80::/32 -2403:9d00::/32 -2403:9d80::/32 -2403:9e40::/32 -2403:9e80::/32 -2403:9ec0::/32 -2403:9f80::/32 -2403:a100::/32 -2403:a140::/32 -2403:a200::/32 -2403:a300::/32 -2403:a480::/32 -2403:a580::/32 -2403:a680::/32 -2403:a6c0::/32 -2403:a780::/32 -2403:a880::/32 -2403:a940::/32 -2403:a980::/32 -2403:a9c0::/32 -2403:aa40::/32 -2403:aa80::/32 -2403:ab80::/32 -2403:ac00::/32 -2403:af80::/32 -2403:b080::/32 -2403:b180::/32 -2403:b280::/32 -2403:b380::/32 -2403:b400::/32 -2403:b480::/32 -2403:b580::/32 -2403:b680::/32 -2403:b780::/32 -2403:b880::/32 -2403:b980::/32 -2403:ba40::/32 -2403:c040::/32 -2403:c080::/32 -2403:c100::/32 -2403:c140::/32 -2403:c180::/32 -2403:c3c0::/32 -2403:c440::/32 -2403:c480::/32 -2403:c4c0::/32 -2403:c980::/32 -2403:cdc0::/32 -2403:cec0::/32 -2403:cf80::/32 -2403:d080::/32 -2403:d180::/32 -2403:d280::/32 -2403:d2c0::/32 -2403:d380::/32 -2403:d400::/32 -2403:d440::/32 -2403:d480::/32 -2403:d580::/32 -2403:d680::/32 -2403:d780::/32 -2403:d7c0::/32 -2403:d880::/32 -2403:d980::/32 -2403:d9c0::/32 -2403:da80::/32 -2403:dac0::/32 -2403:db00::/32 -2403:db80::/32 -2403:dc80::/32 -2403:dd80::/32 -2403:de80::/32 -2403:df80::/32 -2403:e080::/32 -2403:e180::/32 -2403:e280::/32 -2403:e300::/32 -2403:e480::/32 -2403:e500::/32 -2403:e580::/32 -2403:e640::/32 -2403:e680::/32 -2403:e700::/32 -2403:e780::/32 -2403:e7c0::/32 -2403:e880::/32 -2403:e980::/32 -2403:ea80::/32 -2403:eac0::/32 -2403:eb80::/32 -2403:ec80::/32 -2403:ed00::/32 -2403:ed40::/32 -2403:ed80::/32 -2403:ee80::/32 -2403:ef80::/32 -2403:f080::/32 -2403:f100::/32 -2403:f180::/32 -2403:f240::/32 -2403:f280::/32 -2403:f300::/32 -2403:f380::/32 -2403:f4c0::/32 -2403:f580::/32 -2403:f740::/32 -2403:f8c0::/32 -2403:f980::/32 -2403:fb00::/32 -2403:fb80::/32 -2403:fc40::/32 -2403:fe40::/32 -2403:fe80::/32 -2403:fec0::/32 -2403:ff80::/32 -2403:ffc0::/32 -2404:100::/32 -2404:158::/32 -2404:240::/32 -2404:280::/32 -2404:440::/32 -2404:480::/32 -2404:680::/32 -2404:a80::/32 -2404:b80::/32 -2404:bc0::/32 -2404:c40::/32 -2404:d80::/32 -2404:f00::/32 -2404:f80::/32 -2404:1080::/32 -2404:10c0::/32 -2404:1180::/32 -2404:14c0::/32 -2404:1880::/32 -2404:1c80::/32 -2404:1cc0::/32 -2404:1d80::/32 -2404:1e80::/32 -2404:1f40::/32 -2404:21c0::/32 -2404:30c0::/32 -2404:3140::/32 -2404:31c0::/32 -2404:3240::/32 -2404:32c0::/32 -2404:3300::/32 -2404:3340::/32 -2404:3480::/32 -2404:35c0::/32 -2404:3640::/32 -2404:36c0::/32 -2404:3700::/32 -2404:3740::/32 -2404:37c0::/32 -2404:3840::/32 -2404:3940::/32 -2404:3b00::/32 -2404:3bc0::/32 -2404:3c40::/32 -2404:3f40::/32 -2404:4080::/32 -2404:41c0::/32 -2404:4540::/32 -2404:4740::/32 -2404:4bc0::/32 -2404:4d00::/32 -2404:4dc0::/32 -2404:51c0::/32 -2404:5640::/32 -2404:5a80::/32 -2404:5b00::/32 -2404:5d00::/32 -2404:5e80::/32 -2404:6000::/32 -2404:6100::/32 -2404:6380::/32 -2404:6500::/32 -2404:65c0::/32 -2404:6a40::/32 -2404:6f80::/32 -2404:7100::/32 -2404:7180::/32 -2404:71c0::/32 -2404:7240::/32 -2404:74c0::/32 -2404:7600::/32 -2404:7740::/32 -2404:7940::/32 -2404:7d00::/32 -2404:8040::/32 -2404:80c0::/32 -2404:8140::/32 -2404:81c0::/32 -2404:8480::/32 -2404:8580::/32 -2404:8700::/32 -2404:8880::/32 -2404:8a80::/32 -2404:8b00::/32 -2404:8dc0::/32 -2404:9340::/32 -2404:9880::/32 -2404:9b80::/32 -2404:9c80::/32 -2404:a000::/32 -2404:a080::/32 -2404:a0c0::/32 -2404:a180::/32 -2404:a240::/32 -2404:a740::/32 -2404:b100::/32 -2404:b340::/32 -2404:b3c0::/32 -2404:b440::/32 -2404:b4c0::/32 -2404:b900::/32 -2404:bbc0::/32 -2404:bc40::/32 -2404:c1c0::/32 -2404:c240::/32 -2404:c2c0::/32 -2404:c300::/32 -2404:c3c0::/32 -2404:c440::/32 -2404:c4c0::/32 -2404:c540::/32 -2404:c5c0::/32 -2404:c640::/32 -2404:c940::/32 -2404:c9c0::/32 -2404:cd00::/32 -2404:d040::/32 -2404:d080::/32 -2404:d140::/32 -2404:d280::/32 -2404:d3c0::/32 -2404:d480::/32 -2404:d640::/32 -2404:d6c0::/32 -2404:d780::/32 -2404:d7c0::/32 -2404:d840::/32 -2404:dd80::/32 -2404:df00::/32 -2404:e280::/32 -2404:e540::/32 -2404:e5c0::/32 -2404:e780::/32 -2404:e880::/32 -2404:e8c0::/32 -2404:eb40::/32 -2404:eb80::/32 -2404:ec40::/32 -2404:ecc0::/32 -2404:edc0::/32 -2404:f040::/32 -2404:f4c0::/32 -2404:f7c0::/32 -2405:80::/32 -2405:480::/32 -2405:580::/32 -2405:680::/32 -2405:6c0::/32 -2405:780::/32 -2405:880::/32 -2405:940::/32 -2405:980::/32 -2405:9c0::/32 -2405:a80::/32 -2405:b80::/32 -2405:c80::/32 -2405:d80::/32 -2405:e80::/32 -2405:f40::/32 -2405:f80::/32 -2405:1080::/32 -2405:1180::/32 -2405:1280::/32 -2405:1380::/32 -2405:1480::/32 -2405:1580::/32 -2405:1680::/32 -2405:18c0::/32 -2405:1c80::/32 -2405:1d80::/32 -2405:1e80::/32 -2405:1f80::/32 -2405:1fc0::/32 -2405:2080::/32 -2405:2180::/32 -2405:2280::/32 -2405:2340::/32 -2405:2380::/32 -2405:2480::/32 -2405:24c0::/32 -2405:2580::/32 -2405:2680::/32 -2405:2780::/32 -2405:2880::/32 -2405:2980::/32 -2405:2a80::/32 -2405:2b80::/32 -2405:2bc0::/32 -2405:2c80::/32 -2405:2d80::/32 -2405:2e80::/32 -2405:2ec0::/32 -2405:2f40::/32 -2405:2f80::/32 -2405:3140::/32 -2405:31c0::/32 -2405:37c0::/32 -2405:3880::/32 -2405:3980::/32 -2405:39c0::/32 -2405:3a80::/32 -2405:3ac0::/32 -2405:3b00::/32 -2405:3b80::/32 -2405:3bc0::/32 -2405:3c40::/32 -2405:3c80::/32 -2405:3d80::/32 -2405:3e80::/32 -2405:3f40::/32 -2405:3f80::/32 -2405:4080::/32 -2405:4140::/32 -2405:4180::/32 -2405:41c0::/32 -2405:4280::/32 -2405:4380::/32 -2405:4480::/32 -2405:44c0::/32 -2405:4540::/32 -2405:4580::/32 -2405:4680::/32 -2405:4780::/32 -2405:4880::/32 -2405:4980::/32 -2405:4a80::/32 -2405:4b80::/32 -2405:4d40::/32 -2405:4e80::/32 -2405:4f80::/32 -2405:5080::/32 -2405:5180::/32 -2405:5240::/32 -2405:5280::/32 -2405:52c0::/32 -2405:5380::/32 -2405:5480::/32 -2405:5580::/32 -2405:5680::/32 -2405:5780::/32 -2405:57c0::/32 -2405:5880::/32 -2405:5980::/32 -2405:5a80::/32 -2405:5b00::/32 -2405:5b80::/32 -2405:5c80::/32 -2405:5cc0::/32 -2405:5d40::/32 -2405:5d80::/32 -2405:5dc0::/32 -2405:5e80::/32 -2405:5f80::/32 -2405:6080::/32 -2405:6180::/32 -2405:6200::/32 -2405:66c0::/32 -2405:6880::/32 -2405:68c0::/32 -2405:6940::/32 -2405:69c0::/32 -2405:6a80::/32 -2405:6b80::/32 -2405:6c80::/32 -2405:6d80::/32 -2405:6e80::/32 -2405:6f00::/32 -2405:6f80::/32 -2405:7040::/32 -2405:7080::/32 -2405:7180::/32 -2405:7240::/32 -2405:7280::/32 -2405:7380::/32 -2405:7480::/32 -2405:7580::/32 -2405:7680::/32 -2405:7780::/32 -2405:7880::/32 -2405:78c0::/32 -2405:7980::/32 -2405:79c0::/32 -2405:7a80::/32 -2405:7b80::/32 -2405:7c80::/32 -2405:7d40::/32 -2405:7f40::/32 -2405:7fc0::/32 -2405:8280::/32 -2405:83c0::/32 -2405:8480::/32 -2405:84c0::/32 -2405:8580::/32 -2405:8680::/32 -2405:8780::/32 -2405:8880::/32 -2405:8980::/32 -2405:8a40::/32 -2405:8a80::/32 -2405:8ac0::/32 -2405:8b80::/32 -2405:8c80::/32 -2405:8d80::/32 -2405:8e80::/32 -2405:8f40::/32 -2405:8f80::/32 -2405:9080::/32 -2405:9180::/32 -2405:9280::/32 -2405:9300::/32 -2405:9340::/32 -2405:9380::/32 -2405:93c0::/32 -2405:9480::/32 -2405:94c0::/32 -2405:9580::/32 -2405:9680::/32 -2405:9700::/32 -2405:9780::/32 -2405:97c0::/32 -2405:9880::/32 -2405:9900::/32 -2405:9980::/32 -2405:99c0::/32 -2405:9a80::/32 -2405:9b00::/32 -2405:9b80::/32 -2405:9bc0::/32 -2405:9e00::/32 -2405:a240::/32 -2405:a3c0::/32 -2405:a500::/32 -2405:a680::/32 -2405:a900::/32 -2405:a980::/32 -2405:aa80::/32 -2405:ab00::/32 -2405:ad00::/32 -2405:af00::/32 -2405:b100::/32 -2405:b300::/32 -2405:b7c0::/32 -2405:b880::/32 -2405:b980::/32 -2405:bb00::/32 -2405:bd00::/32 -2405:bd80::/32 -2405:bdc0::/32 -2405:be80::/32 -2405:bf00::/32 -2405:c040::/32 -2405:c280::/32 -2405:c380::/32 -2405:c480::/32 -2405:c500::/32 -2405:c580::/32 -2405:c680::/32 -2405:c780::/32 -2405:c880::/32 -2405:c980::/32 -2405:ca80::/32 -2405:cb80::/32 -2405:cc80::/32 -2405:cd80::/32 -2405:ce80::/32 -2405:d280::/32 -2405:d4c0::/32 -2405:d700::/32 -2405:d740::/32 -2405:d900::/32 -2405:df40::/32 -2405:e000::/32 -2405:e040::/32 -2405:e1c0::/32 -2405:e600::/32 -2405:ed40::/32 -2405:ee80::/32 -2405:ef40::/30 -2405:f340::/32 -2405:f380::/32 -2405:f3c0::/32 -2405:f580::/32 -2405:f6c0::/32 -2405:f940::/32 -2405:fdc0::/32 -2405:fe80::/32 -2405:fec0::/32 -2405:ff80::/32 -2406:40::/32 -2406:80::/32 -2406:c0::/32 -2406:140::/32 -2406:280::/32 -2406:440::/32 -2406:4c0::/32 -2406:7c0::/32 -2406:840::/32 -2406:880::/32 -2406:8c0::/32 -2406:9c0::/32 -2406:d80::/32 -2406:e80::/32 -2406:f80::/32 -2406:1080::/32 -2406:1100::/32 -2406:1180::/32 -2406:1280::/32 -2406:1380::/32 -2406:1480::/32 -2406:1580::/32 -2406:15c0::/32 -2406:1680::/32 -2406:1780::/32 -2406:1880::/32 -2406:1980::/32 -2406:1a80::/32 -2406:1b80::/32 -2406:1c80::/32 -2406:1d80::/32 -2406:1e40::/32 -2406:1e80::/32 -2406:1f80::/32 -2406:2080::/32 -2406:2580::/32 -2406:2640::/32 -2406:2700::/32 -2406:2780::/32 -2406:2880::/32 -2406:2980::/32 -2406:2a80::/32 -2406:2b80::/32 -2406:2c40::/32 -2406:2c80::/32 -2406:2d80::/32 -2406:2e80::/32 -2406:2f80::/32 -2406:3080::/32 -2406:3180::/32 -2406:31c0::/32 -2406:3280::/32 -2406:3300::/32 -2406:3340::/32 -2406:3380::/32 -2406:3440::/32 -2406:3480::/32 -2406:34c0::/32 -2406:3580::/32 -2406:3640::/32 -2406:3680::/32 -2406:3700::/32 -2406:3780::/32 -2406:3880::/32 -2406:3980::/32 -2406:39c0::/32 -2406:3ac0::/32 -2406:3d80::/32 -2406:3e80::/32 -2406:3f80::/32 -2406:4080::/32 -2406:40c0::/32 -2406:4180::/32 -2406:4280::/32 -2406:42c0::/32 -2406:4340::/32 -2406:4380::/32 -2406:43c0::/32 -2406:4480::/32 -2406:4500::/32 -2406:4680::/32 -2406:4980::/32 -2406:4b80::/32 -2406:4c80::/32 -2406:4d00::/32 -2406:4d80::/32 -2406:4e80::/32 -2406:4f00::/32 -2406:4f80::/32 -2406:5080::/32 -2406:50c0::/32 -2406:5180::/32 -2406:5280::/32 -2406:52c0::/32 -2406:5340::/32 -2406:5380::/32 -2406:5480::/32 -2406:5580::/32 -2406:5680::/32 -2406:5780::/32 -2406:5840::/32 -2406:5880::/32 -2406:5940::/32 -2406:5980::/32 -2406:5a40::/32 -2406:5ac0::/32 -2406:5b40::/32 -2406:5d80::/32 -2406:5e80::/32 -2406:5f80::/32 -2406:6080::/32 -2406:6100::/32 -2406:6180::/32 -2406:61c0::/30 -2406:6280::/32 -2406:6300::/32 -2406:6340::/32 -2406:6380::/32 -2406:6480::/32 -2406:6500::/32 -2406:6580::/32 -2406:65c0::/32 -2406:6640::/32 -2406:6680::/32 -2406:6780::/32 -2406:6880::/32 -2406:6980::/32 -2406:6a80::/32 -2406:6b80::/32 -2406:6bc0::/32 -2406:6c80::/32 -2406:6d80::/32 -2406:6e80::/32 -2406:6f80::/32 -2406:7080::/32 -2406:7280::/32 -2406:7380::/32 -2406:7480::/32 -2406:7580::/32 -2406:7680::/32 -2406:7780::/32 -2406:7880::/32 -2406:7980::/32 -2406:7a80::/32 -2406:7b80::/32 -2406:7c80::/32 -2406:7cc0::/32 -2406:7d00::/32 -2406:7d80::/32 -2406:7e80::/32 -2406:7f80::/32 -2406:7fc0::/32 -2406:8080::/32 -2406:8180::/32 -2406:8280::/32 -2406:8380::/32 -2406:8480::/32 -2406:8500::/32 -2406:8580::/32 -2406:8780::/32 -2406:8880::/32 -2406:8980::/32 -2406:8a80::/32 -2406:8b80::/32 -2406:8bc0::/32 -2406:8c80::/32 -2406:8d80::/32 -2406:8e80::/32 -2406:8f40::/32 -2406:8f80::/32 -2406:9180::/32 -2406:9200::/32 -2406:9280::/32 -2406:9380::/32 -2406:9480::/32 -2406:94c0::/32 -2406:96c0::/32 -2406:9780::/32 -2406:9d80::/32 -2406:9e40::/32 -2406:9e80::/32 -2406:9f80::/32 -2406:a080::/32 -2406:a180::/32 -2406:a280::/32 -2406:a380::/32 -2406:a480::/32 -2406:a580::/32 -2406:a680::/32 -2406:a780::/32 -2406:a7c0::/32 -2406:a880::/32 -2406:a8c0::/32 -2406:a980::/32 -2406:aa80::/32 -2406:aac0::/32 -2406:ab80::/32 -2406:abc0::/32 -2406:ac80::/32 -2406:acc0::/32 -2406:ad40::/32 -2406:ad80::/32 -2406:ae80::/32 -2406:af80::/32 -2406:b080::/32 -2406:b640::/32 -2406:b880::/32 -2406:b980::/32 -2406:ba80::/32 -2406:bb80::/32 -2406:bc80::/32 -2406:bd40::/32 -2406:bd80::/32 -2406:bdc0::/32 -2406:be80::/32 -2406:bf80::/32 -2406:c080::/32 -2406:c180::/32 -2406:c280::/32 -2406:c340::/32 -2406:c480::/32 -2406:c580::/32 -2406:c680::/32 -2406:c780::/32 -2406:c880::/32 -2406:c900::/32 -2406:c980::/32 -2406:ca80::/32 -2406:cac0::/32 -2406:cb80::/32 -2406:cc80::/32 -2406:cd80::/32 -2406:ce80::/32 -2406:cf00::/32 -2406:cf01::/32 -2406:cf02::/31 -2406:cf80::/32 -2406:d080::/32 -2406:d140::/32 -2406:d180::/32 -2406:d280::/32 -2406:d2c0::/32 -2406:d380::/32 -2406:d440::/32 -2406:d480::/32 -2406:d580::/32 -2406:d680::/32 -2406:d780::/32 -2406:d880::/32 -2406:d980::/32 -2406:db80::/32 -2406:dc80::/32 -2406:dd00::/32 -2406:dd80::/32 -2406:de80::/32 -2406:df80::/32 -2406:e080::/32 -2406:e180::/32 -2406:e280::/32 -2406:e2c0::/32 -2406:e380::/32 -2406:e3c0::/32 -2406:e500::/32 -2406:e580::/32 -2406:e680::/32 -2406:e780::/32 -2406:e8c0::/32 -2406:ea40::/28 -2406:f280::/32 -2406:f300::/32 -2406:f4c0::/32 -2406:f7c0::/32 -2406:f980::/32 -2406:fc80::/32 -2406:fd80::/32 -2406:fe80::/32 -2406:ff00::/32 -2407:480::/32 -2407:580::/32 -2407:cc0::/32 -2407:f40::/32 -2407:1180::/32 -2407:17c0::/32 -2407:1900::/32 -2407:1d00::/32 -2407:1e80::/32 -2407:2280::/32 -2407:2380::/32 -2407:23c0::/32 -2407:2440::/32 -2407:2780::/32 -2407:2840::/32 -2407:2ac0::/32 -2407:31c0::/32 -2407:3340::/32 -2407:3540::/32 -2407:3700::/32 -2407:3740::/32 -2407:37c0::/32 -2407:3900::/32 -2407:3f40::/32 -2407:4580::/32 -2407:4680::/32 -2407:4880::/32 -2407:4980::/32 -2407:4a80::/32 -2407:4c80::/32 -2407:4d80::/32 -2407:4e80::/32 -2407:4f00::/32 -2407:5380::/32 -2407:5500::/32 -2407:5780::/32 -2407:6580::/32 -2407:6a80::/32 -2407:7680::/32 -2407:7780::/32 -2407:7880::/32 -2407:7980::/32 -2407:7c80::/32 -2407:7d00::/32 -2407:7d80::/32 -2407:7e80::/32 -2407:8880::/32 -2407:8b80::/32 -2407:9080::/32 -2407:9180::/32 -2407:9680::/32 -2407:9980::/32 -2407:9f00::/32 -2407:9f80::/32 -2407:a480::/32 -2407:a880::/32 -2407:ad80::/32 -2407:ae80::/32 -2407:af80::/32 -2407:b080::/32 -2407:b180::/32 -2407:b280::/32 -2407:b380::/32 -2407:b580::/32 -2407:b680::/32 -2407:b780::/32 -2407:b880::/32 -2407:b980::/32 -2407:ba00::/32 -2407:ba80::/32 -2407:bb80::/32 -2407:bc00::/32 -2407:bc80::/32 -2407:bd80::/32 -2407:be80::/32 -2407:bf80::/32 -2407:c080::/32 -2407:c380::/32 -2407:c400::/32 -2407:c480::/32 -2407:c580::/32 -2407:c680::/32 -2407:c780::/32 -2407:c880::/32 -2407:c900::/32 -2407:c980::/32 -2407:cb80::/32 -2407:cc80::/32 -2407:cd80::/32 -2407:ce80::/32 -2407:cf00::/32 -2407:cf80::/32 -2407:d480::/32 -2407:d580::/32 -2407:d680::/32 -2407:d780::/32 -2407:d880::/32 -2407:d980::/32 -2407:da80::/32 -2407:db80::/32 -2407:dc80::/32 -2407:dd80::/32 -2407:de80::/32 -2407:df80::/32 -2407:e080::/32 -2407:e180::/32 -2407:e280::/32 -2407:e380::/32 -2407:e480::/32 -2407:e580::/32 -2407:e680::/32 -2407:e780::/32 -2407:e800::/32 -2407:ea80::/32 -2407:eb80::/32 -2407:ec80::/32 -2407:ed80::/32 -2407:ee80::/32 -2407:ef80::/32 -2407:f080::/32 -2407:f180::/32 -2407:f280::/32 -2407:f380::/32 -2407:f480::/32 -2407:f580::/32 -2407:f680::/32 -2407:f780::/32 -2407:f880::/32 -2407:f980::/32 -2407:fa80::/32 -2407:fb80::/32 -2407:fc80::/32 -2407:fd80::/32 -2408:4000::/22 -2408:6000::/24 -2408:8000::/22 -2408:8400::/22 -2408:8800::/21 -2409:2000::/21 -2409:6000::/20 -2409:8000::/20 -240a:2000::/24 -240a:4000::/21 -240a:6000::/24 -240a:8000::/21 -240a:c000::/20 -240b:8000::/21 -240c::/28 -240c:4000::/22 -240c:8000::/21 -240c:c000::/20 -240d:4000::/21 -240d:8000::/24 -240e::/24 -240e:100::/24 -240e:200::/23 -240e:400::/22 -240e:800::/21 -240e:1000::/20 -240e:2000::/19 -240f:4000::/24 -240f:8000::/24 -240f:c000::/24 diff --git a/package/lienol/luci-app-passwall/root/usr/share/passwall/rules/direct_host b/package/lienol/luci-app-passwall/root/usr/share/passwall/rules/direct_host deleted file mode 100644 index 13105bdf7c..0000000000 --- a/package/lienol/luci-app-passwall/root/usr/share/passwall/rules/direct_host +++ /dev/null @@ -1,5 +0,0 @@ -apple.com -microsoft.com -dyndns.com -douyucdn.cn -douyucdn2.cn \ No newline at end of file diff --git a/package/lienol/luci-app-passwall/root/usr/share/passwall/rules/direct_ip b/package/lienol/luci-app-passwall/root/usr/share/passwall/rules/direct_ip deleted file mode 100644 index 5ea1a48e16..0000000000 --- a/package/lienol/luci-app-passwall/root/usr/share/passwall/rules/direct_ip +++ /dev/null @@ -1,11 +0,0 @@ -114.114.114.114 -114.114.115.115 -223.5.5.5 -223.6.6.6 -119.29.29.29 -182.254.116.116 -1.2.4.8 -210.2.4.8 -101.226.4.6 -218.30.118.6 -180.76.76.76 diff --git a/package/lienol/luci-app-passwall/root/usr/share/passwall/rules/gfwlist b/package/lienol/luci-app-passwall/root/usr/share/passwall/rules/gfwlist deleted file mode 100644 index 86e0656761..0000000000 --- a/package/lienol/luci-app-passwall/root/usr/share/passwall/rules/gfwlist +++ /dev/null @@ -1,5447 +0,0 @@ -gmhz.org -ameba.jp -proxydns.com -twitter.com -aliengu.com -timesofindia.indiatimes.com -internetdefenseleague.org -tuidang.net -taiwandaily.net -sixth.biz -savetibet.de -friendsoftibet.org -cosmic.monar.ch -churchinhongkong.org -londonchinese.ca -sapikachu.net -de-sci.org -shadowsocks9.com -seezone.net -igotmail.com.tw -vital247.org -gist.github.com -airconsole.com -twittbot.net -ienergy1.com -pornrapidshare.com -xxlmovies.com -dysfz.cc -qixianglu.cn -tibet.sk -microvpn.com -torrentz.eu -guardster.com -uderzo.it -pubu.com.tw -alhayat.com -livestream.com -dmhy.org -purplelotus.org -tokyo-porn-tube.com -gmbd.cn -trtc.com.tw -phayul.com -tparents.org -livedoor.jp -sokamonline.com -homeservershow.com -gamebase.com.tw -soup.io -youporngay.com -gaycn.net -falunpilipinas.net -weiquanwang.org -iportal.me -americangreencard.com -christianstudy.com -xpdo.net -shiksha.ws -truebuddha-md.org -vanpeople.com -falunart.org -amnesty.org -domains.google -d3c33hcgiwev3.cloudfront.net -hechaji.com -ippotv.com -wheelockslatin.com -dotplane.com -21join.com -tl.gd -video.foxbusiness.com -gtricks.com -documentingreality.com -cardinalkungfoundation.org -iyouport.org -gaeproxy.com -ronjoneswriter.com -ur7s.com -motherless.com -yibada.com -epochtimes.fr -radiovncr.com -lyfhk.net -mizzmona.com -zaobao.com -thebodyshop-usa.com -guangnianvpn.com -ai.google -tw-npo.org -bravotube.net -telesco.pe -meetav.com -cytode.us -new96.ca -legsjapan.com -nordstrom.com -taiwannation.50webs.com -my.pcloud.com -laoyang.info -coinbene.com -chinasoul.org -freedomcollection.org -nylon-angel.com -cleansite.info -google.ie -rigpa.org -presidentlee.tw -177pic.info -video.pbs.org -cbsnews.com -hotpornshow.com -devio.us -yong.hu -j.mp -apk.tw -huaglad.com -internet.org -wowporn.com -china-mmm.net -hilive.tv -forum.setty.com.tw -g0v.social -xys.dxiong.com -greenvpn.net -jgoodies.com -kanzhongguo.com -lotuslight.org.tw -991.com -jihadintel.meforum.org -bit.do -china18.org -discoins.com -experts-univers.com -lflinkup.net -cool18.com -im88.tw -blog.foolsmountain.com -chinahorizon.org -logiqx.com -illusionfactory.com -voatibetanenglish.com -prosciana.com -therock.net.nz -wiki.esu.im -twindexx.com -md-t.org -onlineyoutube.com -spankbang.com -pmates.com -tibetrelieffund.co.uk -bynet.co.il -proxyroad.com -bitsnoop.com -ccw.org.tw -tibet.a.se -jfqu37.xyz -wisevid.com -stc.com.sa -google.sn -uncyclopedia.hk -tibetanarts.org -mirrorbooks.com -nytimes.map.fastly.net -bcex.ca -thomasbernhard.org -msha.gov -persiankitty.com -letscorp.net -89-64.org -alanhou.com -fqok.org -my.mail.ru -shitaotv.org -fawanghuihui.org -finler.net -innermongolia.org -hizbuttahrir.org -ddns.us -spike.com -mojim.com -page2rss.com -avg.com -waveprotocol.org -trickip.org -tubegals.com -jamaat.org -yigeni.com -btc98.com -www1.american.edu -www.monlamit.org -pttvan.org -zhanlve.org -dongtaiwang.net -findyoutube.com -etizer.org -getmdl.io -mvg.jp -duckload.com -hkmap.live -rfaweb.org -fbcdn.net -cnbbnews.wordpress.com -chinese.donga.com -esmtp.biz -shodanhq.com -youlucky.com -globalrescue.net -alwaysdata.net -google.calstate.edu -yobit.net -fuyin.net -www.kindleren.com -freakshare.com -livingonline.us -civilmedia.tw -askynz.net -myftp.info -newcenturynews.com -kucoin.com -privateinternetaccess.com -tube.com -amnesty.tw -mastodon.host -ironbigfools.compython.net -hutianyi.net -statueofdemocracy.org -lipuman.com -jbtalks.cc -on.cc -fourthinternational.org -lflink.com -duplicati.com -appdownloader.net -placemix.com -pen.io -gaymap.cc -blog.lester850.info -theporndude.com -youtubeeducation.com -pixnet.net -oizoblog.com -iam.soy -fastssh.com -edgecastcdn.net -pwned.com -hkfront.org -tibetaid.org -hbo.com -pinterest.ca -xizang-zhiye.org -buy.yahoo.com.tw -amazonvideo.com -www.taup.org.tw -pinterest.dk -fanyue.info -hkchronicles.com -westkit.net -wikimapia.org -friendfeed-media.com -overplay.net -encyclopedia.com -lemonde.fr -fpmt-osel.org -certificate-transparency.org -ruyiseek.com -strongvpn.com -wo.tc -ddns.net -serveuser.com -lizhizhuangbi.com -goo.gl -twerkingbutt.com -globaltm.org -dhcp.biz -longmusic.com -tvants.com -tryheart.jp -vpnuk.info -unblockdmm.com -isaacmao.com -vpn.cmu.edu -easyca.ca -google.it -static.shemalez.com -dns2.us -chapm25.com -tibet.at -soc.mil -lerosua.org -lagranepoca.com -fdc64.org -appspot.com -get.app -csw.org.uk -go.sony.com -newgrounds.com -bitinka.com.ar -mrface.com -superfreevpn.com -tbcollege.org -gardennetworks.org -resilio.com -allgirlsallowed.org -myz.info -tigervpn.com -supervpn.net -315lz.com -dongtaiwang.com -51.ca -happy-vpn.com -frontlinedefenders.org -shat-tibet.com -imageshack.us -dalailama.ru -gaforum.org -hentai.to -laogai.org -newstamago.com -socrec.org -uwants.com -itweet.net -hkcmi.edu -amazon.com -dalailamacenter.org -mgoon.com -fpmtmexico.org -knowledgerush.com -godsimmediatecontact.com -tmi.me -jiaoyou8.com -foxdie.us -gather.com -pacificpoker.com -labiennale.org -tahr.org.tw -huaxiabao.org -ourhobby.com -twiends.com -padmanet.com -bibox.com -helplinfen.com -brandonhutchinson.com -dabr.eu -xinsheng.net -googledomains.com -cdn-images.mailchimp.com -bbs.mychat.to -proxy.org -cusu.hk -mohu.club -standupfortibet.org -popo.tw -nflximg.net -sketchappsources.com -filmingfortibet.org -softether.co.jp -tibetmuseum.org -getfoxyproxy.org -twtrland.com -pornmm.net -vod-abematv.akamaized.net -data.flurry.com -otcbtc.com -chinesedailynews.com -privatevpn.com -soupofmedia.com -convio.net -huhamhire.com -toh.info -chinman.net -coin2co.in -duanzhihu.com -blogblog.com -nokola.com -tibetanfeministcollective.org -news.omy.sg -macrovpn.com -roboforex.com -cnineu.com -orgasm.com -fc2blog.net -eroprofile.com -lionsroar.com -eyevio.jp -waymo.com -video.aol.com -mitao.com.tw -tibetcity.com -nytimg.com -hacg.red -line.me -i818hk.com -hegre-art.com -westernshugdensociety.org -pulse.yahoo.com -vatn.org -angela-merkel.de -chinasucks.net -hakkatv.org.tw -mx981.com -cecc.gov -eurekavpt.com -notify.dropboxapi.com -lefora.com -asia-gaming.com -pinoy-n.com -camfrog.com -weblagu.com -hjclub.info -politiscales.net -5299.tv -tcnynj.org -tibetcharity.dk -himemix.net -bonfoundation.org -tuo8.ninja -goodreads.com -ss7.vzw.com -vds.rightster.com -solidfiles.com -hk.frienddy.com -gmll.org -graphis.ne.jp -bbs.ecstart.com -jbtalks.my -tor.blingblingsquad.net -sitekreator.com -alwaysvpn.com -users.skynet.be -xn--p8j9a0d9c9a.xn--q9jyb4c -cnabc.com -chubun.com -uploadstation.com -me.me -apkpure.com -mynetav.org -now.com -rapbull.net -kba-tx.org -pinterest.fr -sacom.hk -on2.com -urbansurvival.com -abc.xyz -bastillepost.com -serveusers.com -metrolife.ca -freeopenvpn.com -www.owind.com -savetibetstore.org -vpnpop.com -cnex.org.cn -sstmlt.moe -4shared.com -2shared.com -minghui-a.org -uighur.nl -adultfriendfinder.com -hkgreenradio.org -isuntv.com -is.gd -get.page -freedomchina.info -tweeplike.me -gov.taipei -googlehosted.com -foxgay.com -jukujo-club.com -tfhub.dev -yorkbbs.ca -sourcewadio.com -pachosting.com -lidecheng.com -twitgether.com -soumo.info -freechal.com -mercatox.com -metart.com -tw.iqiyi.com -meltoday.com -sgzhan.com -tbsseattle.org -withyoutube.com -hao.news -kissbbao.cn -tw.gigacircle.com -share.ovi.com -lantosfoundation.org -vine.co -1mobile.com -cn.sandscotaicentral.com -bestgore.com -changeip.net -holyspiritspeaks.org -blog.soylent.com -etherdelta.com -ustream.tv -db.tt -archive.li -chinachange.org -8news.com.tw -hkjp.org -google.az -javseen.com -chinaworker.info -hotspotshield.com -wire.com -gvm.com.tw -video.aol.co.uk -fangeming.com -bolehvpn.net -khmusic.com.tw -sendspace.com -ismprofessional.net -alicejapan.co.jp -niu.moe -sukebei.nyaa.si -rconversation.blogs.com -nyti.ms -hulu.com -sadistic-v.com -weijingsheng.org -if.ttt -insidevoa.com -iphone4hongkong.com -vovo2000.com -fleursdeslettres.com -vpntraffic.com -hybrid-analysis.com -amnestyusa.org -dadazim.com -epochtimes.ie -usma.edu -geocities.co.jp -ugo.com -biliworld.com -furbo.org -ukliferadio.co.uk -thinkgeek.com -tweepmag.com -a5.com.ru -kinmen.travel -gs-discuss.com -fring.com -jingpin.org -sethwklein.net -organharvestinvestigation.net -istockphoto.com -hizb-ut-tahrir.info -activpn.com -changeip.name -deaftone.com -paljorpublications.com -fevernet.com -firearmsworld.net -bloomberg.cn -redtube.com -nexton-net.jp -tweetdeck.com -ivacy.com -commandarms.com -hk.myblog.yahoo.com -buzzhand.net -tibetonline.com -penchinese.net -myav.com.tw -pornsharing.com -openid.net -falunworld.net -unholyknight.com -googlesile.com -immoral.jp -cgst.edu -directcreative.com -h-china.org -islamtoday.net -jbtalks.com -go.nesnode.com -tweetymail.com -discordapp.com -fffff.at -tumutanzi.com -behindkink.com -dongyangjing.com -phncdn.com -dfn.org -talk853.com -x365x.com -beijingspring.com -hut2.ru -crazyshit.com -s1s1s1.com -avdb.tv -forum.my903.com -fscked.org -epochtimestr.com -2017.hk -hotvpn.com -icfcdn.com -shopping.com -mullvad.net -chubold.com -cgdepot.org -desipro.de -pornerbros.com -kzeng.info -paradisepoker.com -penisbot.com -freeilhamtohti.org -break.com -twitlonger.com -bbkz.com -tangben.com -inmediahk.net -cienen.com -cdninstagram.com -0914.global.ssl.fastly.net -vpn.cjb.net -feministteacher.com -tweettunnel.com -sstmlt.net -iptvbin.com -raremovie.net -funp.com -xxxy.info -ipfs.io -w3schools.com -berm.co.nz -flickr.com -duoweitimes.com -fucd.com -qvodzy.org -hclips.com -porntvblog.com -freenewscn.com -tube8.com -catholic.org.tw -wiki.phonegap.com -socks-proxy.net -tweetbackup.com -ablwang.com -tma.co.jp -to-porno.com -shinychan.com -delcamp.net -sijihuisuo.club -shadowsocks.asia -dougscripts.com -chrlawyers.hk -sipml5.org -istiqlalhewer.com -chithu.org -braze.com -gooddns.info -tibetfund.org -kodingen.com -mykomica.org -forum.mymaji.com -biantailajiao.com -hkhrm.org.hk -playboy.com -uberproxy.net -difangwenge.org -panamapapers.sueddeutsche.de -tibettimes.net -google.fr -vanemu.cn -greatfirewallofchina.net -gaopi.net -newspeak.cc -ihakka.net -cloudfunctions.net -chinacitynews.be -xcafe.in -kyohk.net -watchinese.com -pride.google -archive.fo -rmjdw132.info -fpmt.org -google.fm -provideocoalition.com -dalailamatrust.org -mihr.com -galstars.net -gfsale.com -unirule.cloud -wezhiyong.org -change.org -top10vpn.com -freegao.com -officeoftibet.com -globalmuseumoncommunism.org -zh.bitterwinter.org -liveleak.com -zonghexinwen.com -tibet.com -antiwave.net -tracfone.com -ipalter.com -sumrando.com -chinayouth.org.hk -nalandawest.org -gamer.com.tw -acmedia365.com -mobatek.net -twimg.com -google.ws -lobsangwangyal.com -raindrop.io -cling.omy.sg -alasbarricadas.org -ufreevpn.com -e-gold.com -ocry.com -e-hentaidb.com -lzmtnews.org -sadpanda.us -falundafaindia.org -cattt.com -sockslist.net -fireofliberty.org -g-queen.com -youtubegaming.com -ntdtv.com.tw -mk5000.com -sis.xxx -chinese.irib.ir -bbsmo.com -www.metro.taipei -epochtimes.co.kr -christiantimes.org.hk -maizhong.org -bloodshed.net -ifreewares.com -kechara.com -dynssl.com -spotify.com -pinterest.nl -shadow.ma -myfreecams.com -hk.yahoo.com -tibethouse.org -luke54.com -stboy.net -avcity.tv -chengmingmag.com -bbtoystore.com -beeg.com -galaxymacau.com -cn.shafaqna.com -blogs.yahoo.co.jp -hugoroy.eu -privatepaste.com -cdcparty.com -mefound.com -videodetective.com -zgzcjj.net -1949er.org -vft.com.tw -hka8964.wordpress.com -june4commemoration.org -ytimg.com -hk01.com -hulkshare.com -popyard.com -xys.org -233abc.com -twstar.net -fzlm.com -userapi.nytlog.com -x24hr.com -igmg.de -liuxiaotong.com -ai.binwang.me -mimivv.com -tarr.uspto.gov -yes.xxx -pinterest.se -go-pki.com -gclooney.com -junauza.com -jfqu36.club -baramangaonline.com -5i01.com -kobobooks.com -monitorchina.org -discord.com -whodns.xyz -casadeltibetbcn.org -googleblog.com -iphonehacks.com -october-review.org -janwongphoto.com -blog.jp -unblock.cn.com -allgirlmassage.com -tapatalk.com -nicovideo.jp -sis001.us -proxypy.net -clipfish.de -sex3.com -tono-oka.jp -soundofhope.kr -tafm.org -rule34.xxx -westpoint.edu -tngrnow.com -v2fly.org -carfax.com -udn.com -zinio.com -chinagfw.org -institut-tibetain.org -lrfz.com -aojiao.org -rarbgprx.org -ftchinese.com -etadult.com -atchinese.com -kineox.free.fr -tibetlibre.free.fr -tianlawoffice.com -dalailamavisit.org.nz -tn3.shemalez.com -unblocker.yt -developers.box.net -juliereyc.com -scramble.io -hutong9.net -api-secure.recaptcha.net -mattwilcox.net -joinmastodon.org -lhasocialwork.org -avoision.com -linuxtoy.org -mist.vip -freetcp.com -got-game.org -popyard.org -falungong.club -web2project.net -cdn1.lp.saboom.com -snowlionpub.com -setn.com -areca-backup.org -islamicpluralism.org -hkej.com -blog.excite.co.jp -rsf.org -yakbutterblues.com -latelinenews.com -tiny.cc -rxhj.net -google.tt -motiyun.com -hellouk.org -xlfmtalk.com -tw.myblog.yahoo.com -nzchinese.com -ozchinese.com -centauro.com.br -exmo.com -dyndns.org -ipjetable.net -collateralmurder.org -thaicn.com -tokyo-hot.com -wufi.org.tw -bithumb.com -archives.gov -guo.media -sexhuang.com -euronews.com -voa-11.akacast.akamaistream.net -warbler.iconfactory.net -epochtimes.se -fiddle.jshell.net -magic-net.info -renyurenquan.org -asdfg.jp -lightnovel.cn -broadpressinc.com -anti1984.com -etvonline.hk -chineseupress.com -freedomhouse.org -bitvise.com -switchvpn.net -www.s4miniarchive.com -admin.recaptcha.net -twittertim.es -persecutionblog.com -wexiaobo.org -mybet.com -mail-archive.com -hotpot.hk -jizzthis.com -cloakpoint.com -incapdns.net -tbsec.org -releaseinternational.org -homeperversion.com -chinapost.com.tw -matome-plus.com -inkui.com -timsah.com -deviantart.com -yayabay.com -android-x86.org -myddns.com -dl-laby.jp -ncn.org -voy.com -fileserve.com -echofon.com -dalailamaquotes.org -vraiesagesse.net -googlebot.com -bestpornstardb.com -douhokanko.net -googleinsidesearch.com -icams.com -newyorktimes.com -meripet.com -freealim.com -memehk.com -xcritic.com -twitpic.com -google.vu -chromercise.com -tcewf.org -dolc.de -pekingduck.org -jamyangnorbu.com -news.nationalgeographic.com -onthehunt.com -chinese-hermit.net -azurewebsites.net -popvote.hk -somee.com -play-asia.com -impp.mn -unseen.is -ssl443.org -piring.com -dns-stuff.com -free.fr -stupidvideos.com -twaud.io -twimbow.com -wsj.com -philly.com -cdef.org -geek-art.net -facebook.se -hk.search.yahoo.com -flickriver.com -hihistory.net -blockcn.com -36rain.com -wenzhao.ca -digitalnomadsproject.org -huyandex.com -quora.com -easternlightning.org -gospelherald.com -3proxy.ru -hotfrog.com.tw -pcanywhere.net -redhotlabs.com -falsefire.com -id.heroku.com -tngrnow.net -tnp.org -bigfools.com -wow-life.net -fdc89.jp -sftuk.org -disconnect.me -simpleproductivityblog.com -flgg.us -bfsh.hk -dupola.com -hkacg.net -sylfoundation.org -mahabodhi.org -uygur.org -bettween.com -hottg.com -lanterncn.cn -easypic.com -casinoking.com -gokbayrak.com -omnitalk.com -apigee.com -gcmasia.com -ddns.mobi -search.yahoo.co.jp -dadi360.com -kendatire.com -akow.org -t-g.com -dabr.mobi -panluan.net -himalayanglacier.com -steganos.net -feitian-california.org -streamingthe.net -castbox.fm -xiaochuncnjp.com -saintyculture.com -maruta.be -wuyanblog.com -cointiger.com -dogfartnetwork.com -h1n1china.org -naitik.net -alldrawnsex.com -breaking911.com -empfil.com -crocotube.com -nordstrommedia.com -emuparadise.me -bt95.com -hentaitube.tv -axureformac.com -port25.biz -sex.com -huhaitai.com -5aimiku.com -oex.com -yt.be -jex.com -kex.com -google.de -environment.google -idreamx.com -artstation.com -aex.com -bbs.qmzdd.com -binance.com -chinaeweekly.com -pentoy.hk -guangming.com.my -ns01.us -hecaitou.net -eyny.com -eastturkistangovernmentinexile.us -tew.org -feer.com -feitianacademy.org -proxpn.com -unitedsocialpress.com -gaozhisheng.net -taweet.com -greatzhonghua.org -kwongwah.com.my -cmcn.org -larsgeorge.com -google.dev -hqmovies.com -tsu.org.tw -yuvutu.com -kanzhongguo.eu -agro.hk -zaozon.com -xxxy.biz -twitcause.com -iuhrdf.org -twitvid.com -6parknews.com -kaotic.com -venetianmacao.com -livecoin.net -tw01.org -tw.mobi.yahoo.com -i2runner.com -bandwagonhost.com -times.hinet.net -sexbot.com -kir.jp -calgarychinese.net -proxylist.org.uk -nubiles.net -wildammo.com -futurechinaforum.org -livevideo.com -googlegroups.com -tibet.net -nflxso.net -dalailama.com -casino.williamhill.com -dynamicdns.co.uk -fbaddins.com -grammaly.com -bayvoice.net -allconnected.co -zeutch.com -wangafu.net -gettrials.com -schema.org -yobt.tv -facebookmail.com -archive.ph -filthdump.com -beric.me -video.fdbox.com -am730.com.hk -filmy.olabloga.pl -mpinews.com -www1.biz -psblog.name -ffvpn.com -gvlib.com -googleplay.com -mpfinance.com -zpn.im -pritunl.com -ozyoyo.com -x-berry.com -great-firewall.com -javakiba.org -teensinasia.com -idemocracy.asia -d-fukyu.com -falundafamuseum.org -faproxy.com -amtb-taipei.org -jobso.tv -rlcdn.com -jinpianwang.com -tbthouston.org -crucial.com -savemedia.com -kankan.today -blinkx.com -chinageeks.org -xyy69.com -clearsurance.com -thedalailamamovie.com -broadbook.com -googlearth.com -brkmd.com -iav19.com -sohcradio.com -dharmakara.net -usmc.mil -javlibrary.com -eastern-ark.com -ipoock.com -google.bg -counter.social -coinrail.co.kr -hidecloud.com -fbworkmail.com -nordvpn.com -tibetoffice.eu -telegram.me -marxist.net -imageflea.com -telecomspace.com -dontfilter.us -morningsun.org -dynu.com -ai-kan.net -s8forum.com -newschinacomment.org -njuice.com -d2pass.com -miroguide.com -rileyguide.com -epochtimes.it -eromon.net -asacp.org -porntubenews.com -wanderinghorse.net -cn6.eu -tabtter.jp -gekikame.com -definebabe.com -tibet-envoy.eu -gohappy.com.tw -effers.com -crossthewall.net -hk-pub.com -owl.li -kxsw.life -github.com -blog.goo.ne.jp -justicefortenzin.org -shenyun.com -tinc-vpn.org -home.so-net.net.tw -naweeklytimes.com -icoco.com -boxunblog.com -gotrusted.com -btbtav.com -1pondo.tv -hoxx.com -xiaohexie.com -dragonex.io -goldbetsports.com -tw.knowledge.yahoo.com -facebook.br -hk.geocities.com -ns01.biz -picacomic.com -wikileaks.com -aniscartujo.com -eeas.europa.eu -hkcoc.com -tibetanyouth.org -shenshou.org -hidden-advent.org -smchbooks.com -cfhks.org.hk -4dq.com -ff.im -tmdb.org -turntable.fm -hnjhj.com -franklc.com -kendincos.net -metroradio.com.hk -fail.hk -twistory.net -mastodon.social -socialwhale.com -qhigh.com -javmobile.net -doctorvoice.org -lers.google -kun.im -toythieves.com -musicade.net -google.sh -aiv-cdn.net.c.footprint.net -madewithcode.com -videomo.com -1000giri.net -static-economist.com -redditstatic.com -pki.goog -quannengshen.org -hqsbonline.wordpress.com -lflinkup.com -gizlen.net -listorious.com -nytchina.com -radiovaticana.org -premproxy.com -deviantart.net -tiltbrush.com -erktv.com -suoluo.org -freetibet.org -mimivip.com -mingpaovan.com -fanglizhi.info -frommel.net -icl-fi.org -gabocorp.com -exx.com -cfos.de -xxx.com -verybs.com -bgvpn.com -latibet.org -https443.org -hkchurch.org -dalianmeng.org -xbtce.com -spicevpn.com -zhao.jinhai.de -apiary.io -linear-abematv.akamaized.net -javtag.com -fux.com -alkasir.com -hexieshe.xyz -eevpn.com -atv-ext.amazon.com -rcinet.ca -kink.com -urlparser.com -fillthesquare.org -fuckcnnic.net -almasdarnews.com -tw.news.yahoo.com -a771.dscq.akamai.net -tbpic.info -ibvpn.com -gzone-anime.info -goldwave.com -qkshare.com -lvhai.org -amitabhafoundation.us -gayhub.com -devpn.com -google.com -www.idlcoyote.com -mingjingnews.com -koranmandarin.com -ntdtv.org -turbohide.com -bigjapanesesex.com -coolaler.com -ns01.info -npnt.me -djangosnippets.org -freetibet.net -insecam.org -chinahush.com -costco.com -hkacg.com -higfw.com -freenet-china.org -pandavpn-jp.com -kmuh.org.tw -uocn.org -disney-plus.net -gr8domain.biz -tech2.in.com -fb.watch -nfjtyd.com -fengzhenghu.net -kannewyork.com -from-pr.com -readingtimes.com.tw -api.pureapk.com -videopediaworld.com -putihome.org -www.citizenlab.org -freeman2.com -eporner.com -allcoin.com -thedw.us -tibetfocus.com -clb.org.hk -twicountry.org -3tui.net -mastodon.cloud -fanqiangdang.com -angularjs.org -wallornot.org -hrcir.com -blogimg.jp -shenzhoufilm.com -twitter.jp -dns04.com -extrabux.com -cdbook.org -2049bbs.xyz -v2ray.com -vjmedia.com.hk -hkgolden.com -money-link.com.tw -leafyvpn.net -yahoo.com.hk -blog.syx86.com -hk.news.yahoo.com -kindleren.com -generated.photos -ddns.info -zenmate.com -dwnews.com -igoogle.com -ntdtv.ca -www.klip.me -spideroak.com -eltondisney.com -shooshtime.com -xinmiao.com.hk -isasecret.com -fanqiangyakexi.net -flyvpn.com -chicagoncmtv.com -getastrill.com -linux.org.hk -minghui-school.org -online.recoveryversion.org -docs.cfw.lbyczf.com -hi-on.org.tw -mitbbs.com -vpn.sv.cmu.edu -kagyu.org -daxa.cn -home.sina.com -dunyabulteni.net -opus-gaming.com -tweetedtimes.com -lastcombat.com -cdn.seatguru.com -beijing1989.com -gatecoin.com -ezpc.tk -wqyd.org -bbs.morbell.com -epochweekly.com -cn.calameo.com -hdtvb.net -sciencenets.com -googlescholar.com -iownyour.org -gerefoundation.org -18board.com -chinesetalks.net -466453.com -gartlive.com -youdontcare.com -retweeteffect.com -erodoujinlog.com -beijingzx.org -shattered.io -mytizi.com -metrohk.com.hk -electionsmeter.com -discord.gg -blog.kangye.org -g.co -wiki.oauth.net -wozy.in -mike.cz.cc -shiatv.net -liwangyang.com -mimiai.net -ck101.com -wtfpeople.com -cathvoice.org.tw -news100.com.tw -fbsbx.com -focusvpn.com -mos.ru -cclife.ca -dalailama.usc.edu -avdb.in -oursogo.com -oculus.com -e-classical.com.tw -ccthere.net -zuo.la -hackthatphone.net -rlwlw.com -sakuralive.com -prism-break.org -jandyx.com -nexon.com -tibetalk.com -vmpsoft.com -creaders.net -0rz.tw -topbtc.com -palacemoon.com -clyp.it -vocativ.com -gvt1.com -mypicture.info -freewechat.com -phosphation13.rssing.com -boysmaster.com -instanthq.com -wforum.com -avgle.com -ixquick.com -post01.com -hdzog.com -webpass.net -yourlisten.com -ok.ru -aolchannels.aol.com -casinobellini.com -sinoants.com -solidaritetibet.org -korea.net -ebookee.com -vpndada.com -newcenturymc.com -avmoo.net -forum.sina.com.hk -ninth.biz -dynamicdns.org.uk -blog.google -zodgame.us -x-wall.org -twitterkr.com -niusnews.com -mummysgold.com -listentoyoutube.com -wsj.net -agoogleaday.com -redballoonsolidarity.org -luke54.org -freedominfonetweb.wordpress.com -kyofun.com -merlinblog.xyz -registry.google -kcoolonline.com -stories.google -firebaseio.com -privacybox.de -waikeung.org -mitbbsau.com -freeforums.org -nextmedia.com -postimg.org -vmixcore.com -yogichen.org -ulop.net -fc2cn.com -fochk.org -huluim.com -dpr.info -2008xianzhang.info -andygod.com -msa-it.org -voacantonese.com -wizcrafts.net -10musume.com -adsense.com -ss.pythonic.life -wha.la -bit-z.com -catch22.net -foxsub.com -hongkongfp.com -mthruf.com -hk.knowledge.yahoo.com -imagefap.com -threatchaos.com -dmcdn.net -stickam.com -aplusvpn.com -av.movie -javzz.com -coobay.com -coat.co.jp -epochweek.com -carmotorshow.com -138.com -oversea.istarshine.com -pao-pao.net -tweez.net -chinesenews.net.au -moby.to -ait.org.tw -hautelookcdn.com -chaoex.com -888.com -news.cnyes.com -fangeqiang.com -okayfreedom.com -avbody.tv -nradio.me -faydao.com -simplecd.org -huping.net -wattpad.com -civildisobediencemovement.org -bod.asia -greenfieldbookstore.com.hk -city365.ca -233v2.com -vpn4all.com -identi.ca -pokerstars.com -hqjapanesesex.com -tianhuayuan.com -keepandshare.com -bidswitch.net -moodyz.com -tiananmenuniv.net -crazys.cc -pttgame.com -gdbt.net -firetweet.io -ytht.net -dumb1.com -b0ne.com -hojemacau.com.mo -gyalwarinpoche.com -itaboo.info -tmpp.org -myforum.com.hk -gardennetworks.com -google.co.jp -wingy.site -archiveofourown.org -sinocism.com -rakuten.co.jp -uncyclomedia.org -bloomfortune.com -rthklive2-lh.akamaihd.net -hurgokbayrak.com -tsctv.net -thetibetpost.com -dropboxusercontent.com -telegram.dog -hkfreezone.com -whatsapp.com -kk-whys.co.jp -fxcm-chinese.com -emilylau.org.hk -compress.to -hklft.com -graphql.org -bandpage.com -jkb.cc -dafabet.com -superpages.com -pengyulong.com -sgwritings.com -exblog.jp -iownyour.biz -vietdaikynguyen.com -cobinhood.com -manicur4ik.ru -gatherproxy.com -i-part.com.tw -s-dragon.org -2-hand.info -paper.li -sexandsubmission.com -uukanshu.com -kompozer.net -grangorz.org -gaoming.net -oiktv.com -igfw.tech -webbang.net -megarotic.com -amnyemachen.org -newchen.com -app.smartmailcloud.com -cyberghostvpn.com -deepdiscount.com -hkhrc.org.hk -dynamicdns.biz -wolfax.com -securityinabox.org -qtrac.eu -cn.dayabook.com -gfbv.de -wikileaks.ch -etowns.net -ofile.org -mysite.verizon.net -zhongguotese.net -gcpnews.com -hanunyi.com -im.tv -lsm.org -matters.news -twitonmsn.com -karmapa-teachings.org -google.ru -lushstories.com -www.thechinastory.org -brucewang.net -videobam.com -mmmca.com -g6hentai.com -sugumiru18.com -jdwsy.com -sex-11.com -reddit.com -eroticsaloon.net -friends-of-tibet.org -blogger.com -fengzhenghu.com -makemymood.com -myreadingmanga.info -jjgirls.com -openvpn.net -64wiki.com -kinokuniya.com -obutu.com -apk-dl.com -dizhuzhishang.com -cldr.unicode.org -enewstree.com -newscn.org -michaelmarketl.com -its.caltech.edu -1e100.net -fhreports.net -favstar.fm -biantailajiao.in -google.sm -mofaxiehui.com -trimondi.de -pornhost.com -twitchcdn.net -twelve.today -chinanewscenter.com -kaiyuan.de -85st.com -oyax.com -eic-av.com -zacebook.com -fanswong.com -matsushimakaede.com -google.ci -dzze.com -daum.net -telegramdownload.com -usacn.com -hacg.in -googlevideo.com -bbs.hanminzu.org -cdp1989.org -codeskulptor.org -64museum.org -redditlist.com -idiomconnection.com -facebook.com -2waky.com -shireyishunjian.com -liangzhichuanmei.com -hxwk.org -hellotxt.com -businessinsider.com -freetibetanheroes.org -dns.google -voachinese.com -okk.tw -1dumb.com -hkzone.org -chinaaid.me -gaozhisheng.org -storm.mg -lsd.org.hk -cccat.co -youtubecn.com -tibetoffice.org -internetpopculture.com -forum.palmislife.com -jkub.com -cutscenes.net -changp.com -startuplivingchina.com -30boxes.com -tn1.shemalez.com -ecimg.tw -hkwcc.org.hk -pioneer-worker.forums-free.com -nytcn.me -rfi.my -ftv.com.tw -aiv-delivery.net -steganos.com -derekhsu.homeip.net -premeforwindows7.com -sneakme.net -cynscribe.com -google.es -tangren.us -reuters.com -iptv.com.tw -google.be -ct.org.tw -coolloud.org.tw -cipfg.org -cdn.registerdisney.go.com -google.gr -ruten.com.tw -hwayue.org.tw -fuyu.org.tw -radicalparty.org -cdpeu.org -smith.edu -fangong.forums-free.com -hung-ya.com -lama.com.tw -goldeneyevault.com -tw.mall.yahoo.com -chinagate.com -goagent.codeplex.com -flipboard.com -6park.com -javfor.me -casatibet.org.mx -dns-dns.com -mega.co.nz -betvictor.com -pbwiki.com -miniforum.org -singfortibet.com -actimes.com.au -edoors.com -uyghurstudies.org -proxy1.xyz -zhuichaguoji.org -hkreporter.loved.hk -dit-inc.us -43110.cf -hmv.co.jp -dfas.mil -drmingxia.org -www.gmiddle.net -ivpn.net -singtao.com -xijie.wordpress.com -mayimayi.com -bangbrosnetwork.com -hornytrip.com -pinterest.co.uk -sysresccd.org -himemix.com -eastturkistan-gov.org -flitto.com -blip.tv -cafepress.com -duping.net -hkbookcity.com -gopetition.com -twilightsex.com -news.singtao.ca -finchvpn.com -circlethebayfortibet.org -phapluan.org -archive.org -maildns.xyz -hkbf.org -tubeislam.com -humanrightsbriefing.org -ritter.vg -andfaraway.net -sidelinesnews.com -twaitter.com -riseup.net -sports.williamhill.com -cam4.com -book.com.tw -zh.pokerstrategy.com -meyul.com -fanhaodang.com -www.aolnews.com -perfectgirls.net -wiki.gamerp.jp -laod.cn -vpnforgame.net -d2bay.com -gsp.target.com -podictionary.com -sun1911.com -twilog.org -pct.org.tw -surrenderat20.net -66.ca -embr.in -ibiblio.org -manchukuo.net -staticflickr.com -vevo.com -whichav.com -goregrish.com -pinterest.jp -karmapa.org -load.to -spotflux.com -elpais.com -blog.calibre-ebook.com -nationsonline.org -dojin.com -line-scdn.net -feifeiss.com -netbirds.com -getsocialscope.com -google.co.kr -2.bahamut.com.tw -porntube.com -cn.freeones.com -angelfire.com -tuo8.fit -nvtongzhisheng.org -wiredbytes.com -freedl.org -atv-ps.amazon.com -21pron.com -edicypages.com -sharecool.org -gr8name.biz -jyxf.net -youporn.com -googlecode.com -4mydomain.com -showbiz.omy.sg -nbtvpn.com -jigong1024.com -darktech.org -issuu.com -faluninfo.net -ddns.name -zhanbin.net -newsdetox.ca -fullerconsideration.com -amazon.co.jp -shkspr.mobi -ecministry.net -brazzers.com -okex.com -mm-cg.com -usno.navy.mil -ucdc1998.org -justtristan.com -kagyunews.com.hk -youversion.com -huffingtonpost.com -funf.tw -myftp.name -webrush.net -tunsafe.com -tgstat.com -pandapow.co -bdsmvideos.net -141hongkong.com -creativelab5.com -juliepost.com -norbulingka.org -kobo.com -facebook.nl -hdlt.me -shutterstock.com -samair.ru -1bao.org -boxunclub.com -twbbs.net.tw -blog.workflow.is -sunta.com.tw -ac.jiruan.net -sonidodelaesperanza.org -allervpn.com -blackvpn.com -link-o-rama.com -nordstromrack.com -purepdf.com -soul-plus.net -thywords.com.tw -cochina.co -freedomhongkong.org -tuzaijidi.com -prosiben.de -gumroad.com -forum.cyberctm.com -twtkr.com -feedx.net -mefeedia.com -c100tibet.org -diigo.com -yeelou.com -hongzhi.li -omgili.com -atgfw.org -peoplebookcafe.com -ocreampies.com -api.linksalpha.com -kiwi.kz -lastfm.es -dyndns-ip.com -kebrum.com -justfreevpn.com -nuuvem.com -12vpn.com -yuanzhengtang.org -certificate.revocationcheck.com -teamamericany.com -w.wiki -mingpaonews.com -goodreaders.com -roodo.com -windowsphoneme.com -dorjeshugden.com -ixxx.com -islamhouse.com -cn.thegay.com -themoviedb.org -glorystar.me -xmovies.com -pandora.com -hardsextube.com -tianti.io -hootsuite.com -myfreepaysite.com -localdomain.ws -hacker.org -wango.org -shadowsocks.org -sejie.com -deepmind.com -www.oxid.it -navyreserve.navy.mil -otto.de -falundafa-dc.org -static01.nyt.com -networkedblogs.com -from-sd.com -1984bbs.com -rukor.org -doub.io -av-e-body.com -hurriyet.com.tr -cellulo.info -cbtc.org.hk -fangmincn.org -allfinegirls.com -chinamule.com -keontech.net -mingpaosf.com -hkupop.hku.hk -sesawe.net -pcstore.com.tw -initiativesforchina.org -xiezhua.com -gaytube.com -dstk.dk -network54.com -cuiweiping.net -nukistream.com -unification.org.tw -usmgtcg.ning.com -ticket.com.tw -azerbaycan.tv -androidify.com -tw.jiepang.com -meetup.com -btku.me -moneyhome.biz -e-traderland.net -rapidmoviez.com -gutteruncensored.com -feeds.fileforum.com -delicious.com -pandora.tv -media.nu.nl -taipeisociety.org -ironpython.net -suroot.com -juhuaren.com -izlesem.org -igvita.com -fofg.org -photofocus.com -maskedip.com -bbsfeed.com -vermonttibet.org -hola.com -tiandixing.org -gmodules.com -pts.org.tw -iask.ca -polymerhk.com -chinesedaily.com -cl.d0z.net -nownews.com -thetibetmuseum.org -freemoren.com -exmormon.org -ironsocket.com -tuo8.space -k-doujin.net -ntdtv.jp -8z1.net -anontext.com -nytco.com -toytractorshow.com -flnet.org -gamejolt.com -eulam.com -teck.in -dupola.net -turansam.org -liu-xiaobo.org -cochina.org -bloglovin.com -greatfire.org -githubusercontent.com -namgyal.org -books.com.tw -motor4ik.ru -berlintwitterwall.com -cn.giganews.com -dollf.com -myanniu.com -joymiihub.com -lhakar.org -javmoo.com -wufafangwen.com -twistar.cc -qoos.com -af.mil -farwestchina.com -5isotoi5.org -rangzen.net -chinalawandpolicy.com -findyoutube.net -longtermly.net -hacken.cc -tibetsites.com -pinterest.at -blogtd.org -belamionline.com -findmespot.com -china21.org -iask.bz -netflix.com -qpoe.com -www.antd.org -twitterrific.com -hyperrate.com -savetibet.nl -liaowangxizang.net -wikaba.com -puuko.com -blog.pathtosharepoint.com -dyndns.pro -uyghur-j.org -minghuiyw.wordpress.com -plus.codes -freeproxylists.net -freeoz.org -hikinggfw.org -mobileways.de -acgkj.com -allgravure.com -nlfreevpn.com -sinomontreal.ca -meridian-trust.org -news.tvbs.com.tw -mycnnews.com -moviefap.com -raremovie.cc -jinroukong.com -brainyquote.com -blewpass.com -1989report.hkja.org.hk -shipcamouflage.com -cuhkacs.org -underwoodammo.com -cacnw.com -ebtcbank.com -tineye.com -linkideo.com -dcard.tw -nf.id.au -blogs.icerocket.com -internetfreedom.org -duckduckgo-owned-server.yahoo.net -mh4u.org -doubmirror.cf -huaxia-news.com -handcraftedsoftware.org -danbooru.donmai.us -martau.com -e-zone.com.hk -azerimix.com -forum4hk.com -pds.nasa.gov -googleanalytics.com -epochtimes.de -giga-web.jp -ganges.com -facesofnyfw.com -changsa.net -barton.de -tibetancommunity.org -ctao.org -iredmail.org -art4tibet1998.org -dajusha.baywords.com -mymoe.moe -tiktok.com -blog.youxu.info -oopsforum.com -po2b.com -bnews.co -toypark.in -mrbasic.com -firstfivefollowers.com -tianyantong.org.cn -geekerhome.com -bbs.brockbbs.com -news.sina.com.tw -hotgoo.com -hexxeh.net -uhdwallpapers.org -s-cute.com -wav.tv -nighost.org -wlcnew.jigsy.com -duga.jp -otzo.com -edmontonservice.com -2000fun.com -twipple.jp -adcex.com -sino-monthly.com -12vpn.net -lamayeshe.com -gate.io -lookpic.com -minzhuzhongguo.org -wukangrui.net -hkci.org.hk -radioaustralia.net.au -livingstream.com -epochtimes-bg.com -tchrd.org -udn.com.tw -postadult.com -tiananmenduizhi.com -zkaip.com -magazines.sina.com.tw -piraattilahti.org -blog.ranxiang.com -t.me -cartoonmovement.com -riku.me -demo.opera-mini.net -facebook.net -hk.rd.yahoo.com -sorting-algorithms.com -pornhubdeutsch.net -goodtv.com.tw -logbot.net -killwall.com -googledrive.com -pornhub.com -jeanyim.com -barenakedislam.com -mychinese.news -cablegatesearch.net -hongmeimei.com -winwhispers.info -rtalabel.org -falungong.de -laqingdan.net -thetrotskymovie.com -gamer2-cds.cdn.hinet.net -freeviewmovies.com -woopie.tv -himalayan-foundation.org -3a5a.com -kalachakralugano.org -geocities.jp -giantessnight.com -secretsline.biz -zeronet.io -bwsj.hk -site90.net -heeact.edu.tw -wiki.keso.cn -shambhalasun.com -bbs.kimy.com.tw -pdetails.com -vpninja.net -cn.fmnnow.com -bbsdigest.com -www2.ohchr.org -appledaily.com.tw -anonymizer.com -apps.evozi.com -cchere.com -tibetanliberation.org -tistory.com -banana-vpn.com -isohunt.com -windscribe.com -stoporganharvesting.org -gfgold.com.hk -dw-world.de -fc2china.com -s1heng.com -helpster.de -player.fm -kurashsultan.com -lupm.org -trickip.net -pullfolio.com -porn2.com -heix.pp.ru -truthontour.org -images-gaytube.com -tuo8.blue -tibetwrites.org -dontmovetochina.com -unblocksit.es -techviz.net -duckduckgo.com -bwgyhw.com -about.google -m.plixi.com -soundofhope.org -ieasy5.com -fw.cm -highpeakspureearth.com -exchristian.hk -liangyou.net -kurtmunger.com -xgmyd.com -oyghan.com -djorz.com -geekheart.info -ss.levyhsu.com -freehongkong.org -cherrysave.com -1998cdp.org -wpoforum.com -baixing.me -ns2.name -kingstone.com.tw -blog.fizzik.com -btdigg.org -apkmonk.com -nrk.no -secretchina.com -daylife.com -thehots.info -nzchinese.net.nz -api.tenor.com -igcd.net -thinkingtaiwan.com -lsmchinese.org -ventureswell.com -picturedip.com -fuckgfw.org -faith100.org -plm.org.hk -greatfirewall.biz -greatroc.tw -idouga.com -girlbanker.com -demosisto.hk -isgreat.org -xfm.pp.ru -news.yahoo.com -wwitv.com -ihao.org -zannel.com -gnci.org.hk -forum.tvb.com -savethedate.foo -voagd.com -furl.net -nanyangpost.com -mobypicture.com -lovetvshow.com -imagezilla.net -hidemy.name -conoha.jp -pin-cong.com -dnscrypt.org -ftpserver.biz -renminbao.com -uchicago.edu -disqus.com -yasni.co.uk -xlfmwz.info -upcoming.yahoo.com -anpopo.com -nowtorrents.com -nutaku.net -99cn.info -ancsconf.org -ctitv.com.tw -rosechina.net -dictionary.goo.ne.jp -myactimes.com -blog.fuckgfw233.org -fulue.com -advanscene.com -goproxing.net -mamingzhe.com -dafoh.org -eastturkistancc.org -1mobile.tw -mixero.com -catfightpayperview.xxx -expecthim.com -clarionproject.org -rainbowplan.org -twit2d.com -apkdler.com -dailymail.co.uk -uvwxyz.xyz -g-area.org -x1949x.com -newlandmagazine.com.au -svsfx.com -eraysoft.com.tr -cmule.com -avmoo.pw -buugaa.com -suyangg.com -7capture.com -sspanel.net -3d-game.com -nuexpo.com -my-private-network.co.uk -forum.baby-kingdom.com -17t17p.com -nakido.com -pornhd.com -chenshan20042005.wordpress.com -vaticannews.va -networktunnel.net -ddns.ms -dtic.mil -gooday.xyz -orientaldaily.com.my -cleansite.biz -anobii.com -busu.org -videomega.tv -xxuz.com -autodraw.com -ismalltits.com -flecheinthepeche.fr -gvt3.com -appshopper.com -tbsn.org -pcij.org -linkuswell.com -sosreader.com -eksisozluk.com -qiangwaikan.com -anonymise.us -joachims.org -justpaste.it -blogspot.hk -icij.org -matainja.com -astrill.com -rangzen.com -xn--90wwvt03e.com -toonel.net -xn--oiq.cc -xn--i2ru8q2qg.com -www.hostloc.com -flgjustice.org -hkjc.com -twtr2src.ogaoga.org -avmo.pw -greatfire.us7.list-manage.com -xn--4gq171p.com -appspot-preview.com -wikimedia.org -cms.gov -mousebreaker.com -secureservercdn.net -2047.name -xn--czq75pvv1aj5c.org -pixiv.net -genius.com -jma.go.jp -getgom.com -gravatar.com -www.lamenhu.com -vpnintouch.com -onmypc.biz -redhat.com -dropbooks.tv -rixcloud.com -ub0.cc -steemit.com -tw.streetvoice.com -lsxszzg.com -cloudflare.com -c-span.org -greenpeace.org -xkiwi.tk -turbotwitter.com -foxnewsplayer-a.akamaihd.net -workerdemo.org.hk -cdnews.com.tw -news.ycombinator.com -skimresources.com -vpnfires.biz -fulione.com -nbcnews.com -greasespot.net -sockscap64.com -mosucloud.site -fast.wistia.com -hkbc.net -twttr.com -deja.com -twt.tl -versavpn.com -cumlouder.com -ebookbrowse.com -tweetboner.biz -classicalguitarblog.net -rocketcdn.me -wireguard.com -stweetly.com -line.naver.jp -download.ithome.com.tw -hopto.org -thepiratebay.ee -nypost.com -7cow.com -taconet.com.tw -velkaepocha.sk -inoreader.com -soh.tw -github.io -newsancai.com -travelinkcard.com -iconpaper.org -xxxx.com.au -tu8964.com -hrtsea.com -xxxfuckmom.com -evchk.wikia.org -wp.com -yam.org.tw -macts.com.tw -mobile01.com -crrev.com -hitomi.la -stephaniered.com -knowyourmeme.com -oursteps.com.au -heungkongdiscuss.com -lala.im -atc.org.au -asianews.it -ctwant.com -memes.tw -feedly.com -ns02.biz -gnews.org -china5000.us -v2mm.tech -paperb.us -redditmedia.com -whatbrowser.org -g.kfd.me -godns.work -wiki.kfd.me -ampproject.org -duyaoss.com -wearehairy.com -mypop3.org -flyzy2005.com -ss.carryzhou.com -dafagood.com -equinenow.com -alforattv.net -justmysocks.net -app.box.com -javdb.com -totalvpn.com -mydati.com -pems.dot.ca.gov -readmoo.com -app.cloudcone.com -newipnow.com -vegasred.com -figprayer.com -imageab.com -myiphider.com -psiphon3.com -jable.tv -puffin.com -zsdxzk.com -nchrd.org -biggo.com.tw -webevader.org -parts.blog.livedoor.jp -cq99.us -opml.radiotime.com -dabr.co.uk -webfreer.com -bannednews.org -clips4sale.com -ocsp.int-x3.letsencrypt.org -tibetsociety.com -time.com -xtube.com -see.xxx -share.america.gov -goliathguitartutorials.com -xvideos-cdn.com -saveliuxiaobo.com -getfreedur.com -pornbest.org -vpnhq.com -ywpw.com -ozxw.com -starfishfx.com -zyzc9.com -d100.net -zynaima.com -ulike.net -sfshibao.com -nga.mil -zuobiao.me -blog.istef.info -chinasmile.net -zsrhao.com -uproxy.org -tbtemple.org.uk -phprcdn.com -porn5.com -mytalkbox.com -bcast.co.nz -suppig.net -writer.zoho.com -xhamster.com -sleazydream.com -fdc64.de -hkhkhk.com -dnset.com -tibetcorps.org -zootool.com -antichristendom.com -holymountaincn.com -zoogvpn.com -philborges.com -wenyunchao.com -zonghexinwen.net -zomobo.net -leisurecafe.ca -zmw.cn -realforum.zkiz.com -thegly.com -ziporn.com -privatetunnel.com -mansion.com -tcsovi.org -ziddu.com -book.zi5.me -zhuatieba.com -dotgov.gov -nhk-ondemand.jp -uni.cc -pbworks.com -busayari.com -localbitcoins.com -zhoushuguang.com -zhongguorenquan.org -helpeachpeople.com -zhongguo.ca -skyxvpn.com -zhinengluyou.com -zhenxiang.biz -zhenlibu1984.com -zhenlibu.info -cahr.org.tw -zhengjian.org -yourlust.com -zhenghui.org -zhangtianliang.com -is-a-hunter.com -mcreasite.com -zhangboli.net -kone.com -zgsddh.com -whatsapp.net -h5galgame.me -chinamz.org -zfreet.com -zenmate.com.ru -zengjinyan.org -zello.com -hstt.net -zdnet.com.tw -zaobao.com.sg -zalmos.com -yzzk.com -hautelook.com -yx51.net -zzcartoon.com -showhaotu.com -vizvaz.com -yuntipub.com -tibet-initiative.de -dns05.com -makzhou.warehouse333.com -yuanming.net -youshun12.com -topic.youthwant.com.tw -share.youthwant.com.tw -chinesedemocracy.com -m-team.cc -bestforchina.org -blog.youthwant.com.tw -youthnetradio.org -yousendit.com -yourprivatevpn.com -minzhuhua.net -karayou.com -inote.tw -proyectoclubes.com -yourepeat.com -your-freedom.net -twifan.com -chinayuanmin.org -twskype.com -youngspiration.hk -youngpornvideos.com -dok-forum.net -youjizz.com -lamnia.co.uk -twitbrowser.net -youxu.info -yomiuri.co.jp -yolasite.com -topsy.com -soubory.com -cam4.jp -yinlei.org -softwarebychuck.com -yipub.com -h-moe.com -medium.com -cna.com.tw -yingsuoss.com -cdig.info -xa.yimg.com -luxebc.com -fleshbot.com -yilubbs.com -slideshare.net -rapidvpn.com -pandapow.net -yidio.com -efcc.org.hk -yibaochina.com -xskywalker.net -yhcw.net -liquidvpn.com -referer.us -gongm.in -xianba.net -yeyeclub.com -yespornplease.com -psiphontoday.com -weiming.info -crbug.com -google.gg -bjzc.org -yesasia.com -18p2p.com -yes123.com.tw -torrentproject.se -yegle.net -dalailamafellows.org -yeeyi.com -yecl.net -guancha.org -harunyahya.com -ydy.com -mhradio.org -yanghengjun.com -wordpress.com -dw.de -yam.com -xyy69.info -c-est-simple.com -xxxymovies.com -xxx.xxx -xxbbx.com -slyip.com -xvideos.es -xvideos.com -xvideo.cc -xuchao.net -minghui-b.org -biblesforamerica.org -xuzhiyong.net -xuite.net -hkgalden.com -roadshow.hk -dalailamaworld.com -xpud.org -skyking.com.tw -xnxx-cdn.com -xnxx.com -xml-training-guide.com -xjtravelguide.com -ninjaproxy.ninja -xjp.cc -xiuren.org -xiongpian.com -theportalwiki.com -economist.com -edupro.org -xinhuanet.org -51luoben.com -raidtalk.com.tw -cdp2006.org -javmoo.xyz -lpsg.com -xing.com -forum.xinbao.de -www.imdb.com -sinonet.ca -www.tablesgenerator.com -xihua.es -iuksky.com -xiaoma.org -isunaffairs.com -site2unblock.com -huobipro.com -ccim.org -ptt.cc -tibet.nu -xiaobaiwu.com -xianqiao.net -xianjian.tw -bbs.huasing.org -xianchawang.net -tibetswiss.ch -bangdream.space -rthk.org.hk -moeerolibrary.com -zoozle.net -btku.org -sspro.ml -www.dwheeler.com -vjav.com -destiny.xfiles.to -rocksdb.org -xerotica.com -tweetboard.com -allmovie.com -mediafreakcity.com -taiwantp.net -xcity.jp -abc.net.au -wheatseeds.org -jieshibaobao.com -facebook.design -vrsmash.com -expressvpn.com -tcsofbc.org -dw-world.com -cdpwu.org -i-scmp.com -xbabe.com -gongminliliang.com -xanga.com -cn2.streetvoice.com -x-art.com -myeasytv.com -wiki.jqueryui.com -realraptalk.com -3ren.ca -wujieliulan.com -settv.com.tw -api.dropboxapi.com -twitturly.com -zynamics.com -wtbn.org -wsjhk.com -wretch.cc -twyac.org -bewww.net -tunnelbear.com -wrchina.org -dafahao.com -pipii.tv -m.hkgalden.com -sunskyforum.com -woyaolian.org -tascn.com.au -lalulalu.com -npa.go.jp -tokyo-247.com -wowgirls.com -wowlegacy.ml -wow.com -mesotw.com -bitfinex.com -freekwonpyong.org -twibbon.com -depositphotos.com -whippedass.com -onion.city -sujiatun.wordpress.com -orn.jp -wo3ttt.wordpress.com -jobnewera.wordpress.com -raizoji.or.jp -u9un.com -hkanews.wordpress.com -chinaview.wordpress.com -worldvpn.net -worldjournal.com -91vps.club -srocket.us -bell.wiki -worldcat.org -workersthebig.net -clinica-tibet.ru -workerempowerment.org -ignitedetroit.net -workatruna.com -bb-chat.tv -aiweiweiblog.com -forum.slime.com.tw -woopie.jp -woolyss.com -bonbonme.com -wnacg.org -bamgrid.com -wnacg.com -tibetpolicy.eu -atlanta168.com -freenetproject.org -witopia.net -csuchen.de -witnessleeteaching.com -wisdompubs.org -wiredpen.com -iblist.com -milph.net -winning11.com -atlaspost.com -slutmoonbeam.com -willw.net -viu.com -9bis.net -wikiwiki.jp -wikivoyage.org -google.co.id -wikiquote.org -ninjacloak.com -wiktionary.org -blog.daum.net -wikisource.org -tibethouse.us -mediawiki.org -wikidata.org -lotsawahouse.org -wikipedia.org -wikinews.org -falundafa-florida.org -casinoriva.com -wikiwand.com -city9x.com -wikilivres.info -nobodycanstop.us -collateralmurder.com -bbs.hasi.wang -islamawareness.net -ae.org -williamhill.com -scieron.com -hotshame.com -google.ae -wikileaks.pl -blog.tiney.com -wikileaks.lu -comefromchina.com -wikileaks.eu -boomssr.com -wikileaks.de -falundafa.org -wikia.com -iphonix.fr -gwtproject.org -jingsim.org -hkip.org.uk -whyx.org -whylover.com -etokki.com -freechina.news -whotalking.com -whoer.net -abc.com -bbc.com -taiwantt.org.tw -sf.net -longhair.hk -onmoon.net -dvorak.org -wetplace.com -vijayatemple.org -wetpussygames.com -westernwolves.com -westca.com -wenxuecity.com -wenweipo.com -wenhui.ch -leeao.com.cn -wengewang.org -wengewang.com -wemigrate.org -ltn.com.tw -softether-download.com -news.sinchew.com.my -bcchinese.net -weisuo.ws -yesasia.com.hk -weihuo.org -weiboleak.com -wefong.com -shixiao.org -topshareware.com -wahas.com -simbolostwitter.com -webworkerdaily.com -yobt.com -iphonetaiwan.org -www.websnapr.com -hola.org -aiv-cdn.net -pinterest.com -websitepulse.com -media-amazon.com -webs-tv.net -webjb.org -cn.streetvoice.com -hudatoriq.web.id -chushigangdrug.ch -wearn.com -api.ai -wdf5.com -nationwide.com -api.recaptcha.net -googlesyndication.com -watch8x.com -googleearth.com -trialofccp.org -washeng.net -ezpeer.com -highrockmedia.com -tn2.shemalez.com -yulghun.com -bnn.co -crossvpn.net -advertfan.com -wapedia.mobi -www.skype.com -netsneak.com -episcopalchurch.org -want-daily.com -stoptibetcrisis.net -www.wangruowang.org -pythonhackers.com -mega.nz -wangruoshui.net -kyzyhello.com -wanglixiong.com -wangjinbo.org -4rbtv.com -flog.tw -goagentplus.com -www.wan-press.org -waltermartin.org -waltermartin.com -freedomsherald.org -udnbkk.com -tuo8.cc -kinghost.com -feelssh.com -thetvdb.com -thegioitinhoc.vn -domain.club.tw -wallpapercasa.com -psiphon.ca -wallmama.com -chn.chosun.com -scache.vzw.com -comic-mega.me -wailaike.net -huangyiyu.com -waigaobu.com -waffle1999.com -upholdjustice.org -englishforeveryone.org -christianfreedom.org -lists.w3.org -vuku.cc -vtunnel.com -plusbb.com -vporn.com -vpnworldwide.com -retweetist.com -tosh.comedycentral.com -vpnunlimitedapp.com -vpntunnel.com -localpresshk.com -avidemux.org -vinniev.com -daidostup.ru -vpnshieldapp.com -spankwire.com -fringenetwork.com -zippyshare.com -vpnreviewz.com -vpnreactor.com -vpnpronet.com -vpnpick.com -vpnjack.com -archive.is -naughtyamerica.com -bird.so -zapto.org -falunaz.net -vpnintouch.net -greenvpn.org -cftfc.com -pchome.com.tw -vpnmentor.com -cccat.cc -matome-plus.net -dsmtp.com -vpnmaster.com -cyberghost.natado.com -vpngratis.net -tw.voa.mobi -vpngate.net -vpngate.jp -uygur.fc2web.com -diaoyuislands.org -s-nbcnews.com -michaelanti.com -hsselite.com -mybbs.us -betternet.co -gotw.ca -vpnfan.com -gts-vpn.com -vpncoupons.com -bbsland.com -prayforchina.net -mychinanews.com -mychinanet.com -vpncomparison.org -minghui.or.kr -vpnaccount.org -vpn.ac -voxer.com -protonvpn.com -vot.org -slyip.net -web.dev -www.eastturkistan.net -slaytizle.com -voatibetan.com -ka-wai.com -quitccp.net -falun-ny.net -voachineseblog.com -goldbet.com -vnet.link -doubibackup.com -vllcs.org -vivthomas.com -html5rocks.com -thefrontier.hk -vivatube.com -ultravpn.fr -vivahentai4u.net -discuss4u.com -vegas.williamhill.com -visibletweets.com -ifan.cz.cc -virtualrealporn.com -fingerdaily.com -www.lib.virginia.edu -vpnsp.com -vincnd.com -vimperator.org -iamtopone.com -upwill.org -mikesoltys.com -dbc.hk -ygto.com -vimeocdn.com -deck.ly -vidinfo.org -videopress.com -bettervpn.com -hideipvpn.com -teeniefuck.net -vid.me -https443.net -vica.info -viber.com -thestandnews.com -hkday.net -extmatrix.com -tibetheritagefund.org -veoh.com -freevpn.nl -ilove80.be -venchina.com -pushchinawall.com -huiyi.in -backchina.com -media.org.hk -hkdf.org -venbbs.com -google.dj -adult-sex-games.com -dtdns.net -vansky.com -jitouch.com -vanilla-jp.com -van698.com -peopo.org -hstern.net -goagent.biz -uptodown.com -uymaarip.com -uyghurpress.com -falun.caltech.edu -chinese.engadget.com -mychinamyhome.com -funkyimg.com -uyghurcongress.org -skimtube.com -uyghurcanadiansociety.org -uyghuramerican.org -paste.ee -uyghur.co.uk -uwants.net -uu-gg.com -utopianpal.com -fofldfradio.org -usus.cc -pscp.tv -tsdr.uspto.gov -usocctn.com -quoracdn.net -greenpeace.com.tw -iipdigital.usembassy.gov -usaip.eu -bestvpn.com -us.to -mediafire.com -urlborg.com -canyu.org -familyfed.org -shwchurch3.com -breakgfw.com -ipobar.com -tor.cn.uptodown.com -zspeeder.me -upornia.com -faluninfo.de -upmedia.mg -a-normal-day.com -imb.org -uploaded.to -tbi.org.hk -xiaod.in -fgmtv.net -fling.com -livestation.com -untraceable.us -unpo.org -hrw.org -unodedos.com -maturejp.com -unknownspace.org -erights.net -unix100.com -unification.net -japantimes.co.jp -prozz.net -dphk.org -dajiyuan.com -greatfirewallofchina.org -hkcnews.com -trouw.nl -umich.edu -ultraxs.com -chinasocialdemocraticparty.com -onmypc.org -penchinese.com -zvereff.com -uighurbiz.net -pureconcepts.net -googleusercontent.com -gaybubble.com -uhrp.org -uforadio.com.tw -wallproxy.com -china.ucanews.com -mysecondarydns.com -srcf.ucam.org -uc-japan.org -ubddns.org -multiupload.com -hqsbnet.wordpress.com -contests.twilio.com -blogs.tampabay.com -legaltech.law.com -sjum.cn -maiio.net -typepad.com -research.jmsc.hku.hk -ift.tt -txxx.com -mash.to -24smile.org -youpai.org -taolun.info -twnorth.org.tw -twiyia.com -cdn.ampproject.org -bot.nu -ns02.info -twittermail.com -politicalconsultation.org -twittergadget.com -twitterfeed.com -twittercounter.com -twitter4j.org -fooooo.com -zyxel.com -parler.com -chinadigitaltimes.net -tweepguide.com -boysfood.com -pornsocket.com -tpi.org.tw -twitoaster.com -calebelston.com -twitiq.com -megurineluka.com -twitgoo.com -ourtv.hk -powerphoto.org -shapeservices.com -twiggit.org -chinatweeps.com -twisternow.com -jav101.com -twisterio.com -4irc.com -ifjc.org -cmi.org.tw -twishort.com -twip.me -tibetcollection.com -twicsy.com -twibs.com -gamez.com.tw -xinyubbs.net -twibase.com -twgreatdaily.com -git.io -putlocker.com -tweetwally.com -paltalk.com -revleft.com -tweetree.com -bitmex.com -63i.com -tweetphoto.com -tweetmylast.fm -mtw.tl -vimeo.com -cn.voa.mobi -51jav.org -famunion.com -code.jquery.com -tweepml.org -fakku.net -la-forum.org -foxtang.com -twbbs.tw -ladbrokes.com -m.me -jetos.com -twavi.com -skyvegas.com -twapperkeeper.com -ntdtv.ru -qanote.com -tw-blog.com -tvunetworks.com -google.no -sherabgyaltsen.com -tvmost.com.hk -zzcloud.me -hopedialogue.org -help.linksalpha.com -tvboxnow.com -whereiswerner.com -compileheart.com -imlive.com -joinclubhouse.com -globaljihad.net -guishan.org -alabout.com -coolder.com -community.windy.com -alphaporno.com -lecloud.net -tumblr.com -tuvpn.com -app.tutanota.com -tushycash.com -chinatown.com.au -design.google -tuitwit.com -movements.org -tuo8.pw -onedrive.live.com -6parker.com -cmp.hku.hk -inthenameofconfuciusmovie.com -fuq.com -tuo8.in -tuo8.hk -gobet.cc -tuo8.club -tunnelr.com -tunein.com -dropbox.com -have8.com -dalailama-archives.org -bbs.tuitui.info -ned.org -perfectvpn.net -tuidang.org -summify.com -gate-project.com -video.ap.org -tubewolf.com -tubestack.com -sto.cc -kyoyue.com -tube911.com -greenreadings.com -qusi8.net -thehun.net -tibet-munich.de -kenengba.com -hklts.org.hk -85cc.us -seesmic.com -tt1069.com -bullog.org -tsunagarumon.com -tsquare.tv -89.64.charter.constitutionalism.solutions -truveo.com -truth101.co.tv -pursuestar.com -le-vpn.com -twitmania.com -chinainperspective.com -unblock-us.com -blog.qooza.hk -huayuworld.org -transparency.org -piposay.com -traffichaus.com -towngain.com -google.as -appledaily.com.hk -lsmwebcast.com -toutiaoabc.com -nps.gov -liuxiaobo.net -torrenty.org -torrentprivacy.com -torproject.org -torcn.com -abc.pp.ru -tora.to -cnnews.chosun.com -toptip.ca -webwarper.net -weekmag.info -blog.martinoei.com -top.tv -straplessdildo.com -facesoftibetanselfimmolators.info -searchtruth.com -freessh.us -torguard.net -toppornsites.com -topnews.in -top81.ws -twitch.tv -helloandroid.com -itsky.it -bbc.co.uk -chromeenterprise.google -updates.tdesktop.com -jiangweiping.com -iblogserv-f.net -eu.org -xskywalker.com -blueangellive.com -tw.tomonews.net -tokyocn.com -wowrk.com -ra.gg -togetter.com -fpmt.tw -murmur.tw -xm.com -1eew.com -tnaflix.com -jinbushe.org -tmagazine.com -rferl.org -ipfire.org -tkcs-collins.com -playboyplus.com -noodlevpn.com -bjnewlife.org -x.company -islamicity.com -swissinfo.ch -cn-proxy.com -tinypaste.com -tinychat.com -tintuc101.com -wikileaks.org -timdir.com -google.kz -orzistic.org -cctongbao.com -hidein.net -china21.com -daliulian.org -hwadzan.tw -mycanadanow.com -tibetsupportgroup.org -ninecommentaries.com -tibetsun.com -googlefiber.net -wn.com -guaguass.com -tibetoralhistory.org -skybet.com -tibetonline.tv -adultkeep.net -sustainability.google -lianyue.net -tibetoffice.com.au -tibetoffice.ch -eromanga-kingdom.com -gmail.com -bt2mag.com -tibetnetwork.org -smhric.org -lightyearvpn.com -cn.ibtimes.com -tibetinfonet.net -ccue.com -wikiversity.org -chingcheong.com -goofind.com -tibethouse.jp -tibethaus.com -elgoog.im -idv.tw -tibetgermany.de -htkou.net -tibetgermany.com -qxbbs.org -tibetexpress.net -tibetchild.org -tibetcharity.in -my-formosa.com -tibetanwomen.org -tibetansports.org -gyatsostudio.com -tibetanreview.net -eastturkestan.com -tibetanphotoproject.com -ns02.us -cdn.helixstudios.net -googlepagecreator.com -efukt.com -hideme.nl -inxian.com -fc2.com -tibetanculture.org -androidplus.co -tibetancommunityuk.net -meansys.com -bbs.skykiwi.com -juoaa.com -twiffo.com -my03.com -mondex.org -kanshifang.com -swissvpn.net -ddhw.info -tibetanlanguage.org -tibetanbuddhistinstitute.org -daolan.net -ushuarencity.echainhost.com -tibetanjournal.com -shellfire.de -twbbs.org -quantumbooter.net -library.usc.cuhk.edu.hk -sm-miracle.com -red-lang.org -freelotto.com -bjs.org -tibetan.fr -com.google -gati.org.tw -tibetaction.net -blogspot.tw -thumbzilla.com -yunchao.net -smartdnsproxy.com -tibet-house-trust.co.uk -tibet-foundation.org -tibet.to -store.steampowered.com -squirly.info -hxwq.org -supchina.com -tibet.org.tw -jiehua.cz -anyporn.com -free-ss.site -earthvpn.com -upload4u.info -tibet.fr -tibet.ca -myspace.com -tianzhu.org -tiantibooks.org -tiananmenuniv.com -tiananmenmother.org -thywords.com -tibet3rdpole.org -youtube.com -sheikyermami.com -throughnightsfire.com -thongdreams.com -opendn.xyz -helpzhuling.org -post852.com -theync.com -next11.co.jp -thevivekspot.com -thetinhat.com -blinw.com -thetibetconnection.org -ruanyifeng.com -thespeeder.com -hidemycomp.com -muzi.net -thereallove.kr -twibble.de -bx.in.th -thepiratebay.org -thenewslens.com -bookepub.com -fb.me -relay.com.tw -bb.ttv.com.tw -chenpokong.com -martsangkagyuofficial.org -mycould.com -vpnsecure.me -erodaizensyu.com -vip-enterprise.com -blog.sogoo.org -cpj.org -gcc.org.hk -co.ao -dynu.net -thebcomplex.com -chinaxchina.com -sopcast.org -freewww.info -reflectivecode.com -theblemish.com -theatrum-belli.com -cachinese.com -nflxext.com -freefq.com -huaren.us -tenzinpalmo.com -gotgeeks.com -tenacy.com -telegraph.co.uk -tdm.com.mo -t35.com -konachan.com -tcpspeed.co -tccwonline.org -focustaiwan.tw -tbswd.org -buddhanet.com.tw -tbssqh.org -tbsmalaysia.org -tbskkinabalu.page.tl -tbs-rainbow.org -freebrowser.org -bfnn.org -greatroc.org -cleansite.us -tbjyt.org -mymediarom.com -dw.com -zattoo.com -tbicn.org -uploaded.net -disp.cc -urchin.com -hmonghot.com -taup.net -blog.taragana.com -extremetube.com -apidocs.linksalpha.com -tanc.org -budaedu.org -tamiaode.tk -hd.stheadline.com -android.com -talkonly.net -sopcast.com -sulian.me -gloryhole.com -talkcc.com -plunder.com -orient-doll.com -assets.bwbx.io -bbs.sina.com -boxun.com -www.taiwanonline.cc -taiwannews.com.tw -taiwanncf.org.tw -openleaks.org -taiwannation.com.tw -taiwannation.com -thewgo.org -post76.com -feedburner.com -taiwanjustice.com -pornvisit.com -edns.biz -taiwandc.org -google.co.ma -taiwancon.com -taiwanbible.com -tagwalk.com -www2.rocketbbs.com -purevpn.com -taedp.org.tw -religioustolerance.org -amazonaws.com -rotten.com -fangbinxing.com -globalvoicesonline.org -assembla.com -taaze.tw -taa-usa.org -partycasino.com -t66y.com -ggssl.com -sextvx.com -szbbs.net -blog.syx86.cn -syncback.com -appledaily.com -sydneytoday.com -ntdtv.com -surfeasy.com -suprememastertv.com -jintian.net -sunvpn.net -sunmedia.ca -sunporno.com -use.fontawesome.com -sugobbs.com -sugarsync.com -annatam.com -stumbleupon.com -studentsforafreetibet.org -drepung.org -strongwindpress.com -strikingly.com -tv.com -bbcchinese.com -stranabg.com -chinaelections.org -pictures.playboy.com -hiitch.com -stormmediagroup.com -iddddg.com -storify.com -storagenewsletter.com -tubecup.com -10.tt -stileproject.com -martincartoons.com -stickeraction.com -daiphapinfo.net -ny.stgloballink.com -msguancha.com -stepchina.com -steel-storm.com -startpage.com -sharpdaily.com.hk -starp2p.com -monster.com -instagram.com -usinfo.state.gov -ebook.hyread.com.tw -cdn.softlayer.net -stanford.edu -stage64.hk -maniash.com -tuo8.org -ssrshare.com -dailymotion.com -hkptu.org -bestvpnusa.com -ssh91.com -av.com -chinagonet.com -ssglobal.me -mlzs.work -freewww.biz -falun-co.org -wuw.red -ss-link.com -sproxy.info -sproutcore.com -spring4u.info -vpnvip.com -spencertipping.com -spem.at -speedify.com -speakerdeck.com -spb.com -vpnshazam.com -ecfa.org.tw -spankingtube.com -itemdb.com -wlx.sowiki.net -5maodang.com -edubridge.com -southnews.com.tw -btaia.com -wanz-factory.com -anonymouse.org -googlesource.com -sourceforge.net -soundcloud.com -soulcaliburhentai.net -bbs-tw.com -yizhihongxing.com -bbs.sou-tong.org -incredibox.fr -sos.org -gaywatch.com -sorazone.net -sonicbbs.cc -ismaelan.com -songjianjun.com -chinese.soifind.com -guaguass.org -sohfrance.org -sobees.com -sostibet.org -sokmil.com -4everproxy.com -page.bid.yahoo.com -safety.google -sogclub.com -oikos.com.tw -sod.co.jp -sndcdn.com -buddhistchannel.tv -snaptu.com -snapchat.com -smyxy.org -epochtimes.cz -islahhaber.net -tibetkomite.dk -smh.com.au -www.gmiddle.com -tibet-info.net -cosplayjav.pl -globalvoices.org -slutload.com -slickvpn.com -google.ca -slinkset.com -slheng.com -ikwb.com -google.ro -sexidude.com -m.slandr.net -china-review.com.ua -badiucao.com -getsync.com -tongil.or.kr -uyghurensemble.co.uk -david-kilgour.com -dssott.com.akamaized.net -abchinese.com -sjrt.org -wikibooks.org -free-hada-now.org -siteks.uk.to -sitebro.tw -www.gmll.org -myiphide.com -aenhancers.com -arlingtoncemetery.mil -myfreshnet.com -bnrmetal.com -duck.com -gu-chu-sum.org -sis001.com -uraban.me -aomiwang.com -crisisresponse.google -citytalk.tw -scache1.vzw.com -rfamobile.org -lamrim.com -lenwhite.com -sidelinessportseatery.com -sierrafriendsoftibet.org -dalailamainaustralia.org -anchorfree.com -cotweet.com -breakingtweets.com -sinoquebec.com -chinaaid.org -imdb.com -libertytimes.com.tw -cams.org.sg -discordapp.net -sinopitt.info -goldenfrog.com -nvdst.com -openervpn.in -animeshippuuden.com -huobi.pro -bunbunhk.com -alternativeto.net -singtaousa.com -sbs.com.au -singpao.com.hk -singaporepools.com.sg -sinchew.com.my -aisex.com -news.sina.com.hk -itshidden.com -proxyanonimo.es -dailynews.sina.com -limiao.net -i-cable.com -coinut.com -blog.sina.com.tw -washingtonpost.com -calgarychinese.ca -taiwanyes.com -readydown.com -ritouki.jp -globalmediaoutreach.com -gogotunnel.com -kspcoin.com -tibetanpoliticalreview.org -etools.ncol.com -silkbook.com -sijihuisuo.com -get.dev -offbeatchina.com -centurys.net -mrtweet.com -facebook.in -vcfbuilder.org -bbci.co.uk -leirentv.ca -siddharthasintent.org -javhd.com -democrats.org -myshare.url.com.tw -shwchurch.org -dragonsprings.org -rightbtc.com -emanna.com -yvesgeleyn.com -nytstyle.com -freevpn.me -gfw.org.ua -alarab.qa -incloak.com -ourdearamy.com -shop2000.com.tw -rutube.ru -successfn.com -fuyindiantai.org -discuss.com.hk -hide.me -wefightcensorship.org -data-vocabulary.org -i1.hk -shicheng.org -mediachinese.com -grotty-monday.com -hqcdp.org -backpackers.com.tw -shenyunperformingarts.org -tonyyan.net -sexinsex.net -drsunacademy.com -bloglines.com -dl.box.net -sharpdaily.tw -androidtv.com -streema.com -cctmweb.net -asianwomensfilm.de -sharebee.com -pixelqi.com -civilhrfront.org -12bet.com -shambalapost.com -shadowsocks-r.com -freeddns.com -jmscult.com -bowenpress.com -gunsandammo.com -ntrfun.com -journalofdemocracy.org -shadowsocks.com -api.proxlet.com -yyii.org -shadowsky.xyz -shadeyouvpn.com -usunitednews.com -openvpn.org -nic.cz.cc -lighti.me -in99.org -sfileydy.com -google.nu -vcf-online.org -whatblocked.com -free-proxy.cz -szetowah.org.hk -cclife.org -bullogger.com -falundafa-pa.net -sexhu.com -hanime.tv -old.honeynet.org -dailidaili.com -dalailama.mn -fanqiang.network -helloqueer.com -japanfirst.asianfreeforum.com -me.youthwant.com.tw -chinatopsex.com -taiwanus.net -japan-whores.com -sex8.cc -tw.answers.yahoo.com -chinaaid.net -bestvpnanalysis.com -bangchen.net -video.aol.ca -sevenload.com -wujie.net -hnntube.com -zim.vn -sesawe.org -artofpeacefoundation.org -kagyumonlam.org -bigsound.org -onmypc.info -periscope.tv -civiliangunner.com -21sextury.com -uku.im -amigobbs.net -gamer-cds.cdn.hinet.net -news.seehua.com -hgseav.com -usfk.mil -hacg.me -ipicture.ru -securitykiss.com -1984bbs.org -falunau.org -dscn.info -club1069.com -securetunnel.com -greenparty.org.tw -cdpa.url.tw -mingpaocanada.com -googleartproject.com -quranexplorer.com -game735.com -cnproxy.com -domainhelp.search.com -rocket-inc.net -scriptspot.com -dushi.ca -hideman.net -dynamic-dns.net -googleideas.com -ipredator.se -scmpchinese.com -javzoo.com -scmp.com -rebatesrule.net -bvpn.com -scasino.com -puffstore.com -blog.jackjia.com -sbme.me -bestvpnserver.com -hahlo.com -thechinabeat.org -savevid.com -geti2p.net -googlecommerce.com -141jj.com -bbs.cantonese.asia -fgmtv.org -fqrouter.com -4bluestones.biz -cari.com.my -fzh999.com -businessweek.com -fotile.me -savetibet.org -sakya.org -savetibet.fr -hrea.org -kkbox.com -falungong.org.uk -zhreader.com -savethesounds.info -xn--ngstr-lra8j.com -hhthesakyatrizin.org -kik.com -buzzhand.com -al-qimmah.net -sanmin.com.tw -sambhota.org -apkmirror.com -gfw.press -salvation.org.hk -secure.raxcdn.com -64tianwang.com -saiq.me -looktoronto.com -acnw.com.au -safervpn.com -zuola.com -bcrncdn.com -portablevpn.nl -madonna-av.com -sacks.com -chinarightsia.org -sendsmtp.com -sftindia.org -crchina.org -blog.de -galenwu.com -deutsche-welle.de -cclifefl.org -passiontimes.hk -vrmtr.com -redchinacn.net -busytrade.com -dotvpn.com -hotels.cn -webrtc.org -rushbee.com -ebony-beauty.com -lvv2.com -suissl.com -runbtx.com -thetibetcenter.org -mnewstv.com -rtycminnesota.org -rti.org.tw -aculo.us -rthk.hk -d1b183sg0nvnuh.cloudfront.net -rssmeme.com -botanwang.com -ifanqiang.com -cdp1998.org -clementine-player.org -rsgamen.org -files2me.com -caobian.info -akiba-online.com -briian.com -communitychoicecu.com -freewallpaper4.me -getoutline.org -10conditionsoflove.com -rojo.com -seapuff.com -ellawine.org -robustnessiskey.com -ksdl.org -mcadforums.com -rmjdw.com -citizenlab.org -onlytweets.com -hizb-ut-tahrir.org -dilber.se -google.tm -tttan.com -alwaysdata.com -chinese-leaders.org -withgoogle.com -aiph.net -tibetjustice.org -u15.info -blog.exblog.co.jp -google.at -dalailamaprotesters.info -answering-islam.org -golang.org -hec.su -bemywife.cc -iicns.com -chinainterimgov.org -plus28.com -shizhao.org -h5dm.com -rfachina.com -futuremessage.org -dastrassi.org -video.yahoo.com -hkatvnews.com -freeyoutubeproxy.net -national-lottery.co.uk -revver.com -retweetrank.com -spendee.com -izaobao.us -textnow.me -paldengyal.com -reutersmedia.net -app.heywire.com -photodharma.net -opendemocracy.net -rangwang.biz -subacme.rerouted.org -mcfog.com -ibros.org -tacem.org -eireinikotaerukai.com -gstatic.com -left21.hk -relaxbbs.com -domaintoday.com.au -btcbank.bank -clearwisdom.net -pornstarclub.com -epochtimes.ru -mrbonus.com -free4u.com.ar -kagyuoffice.org.tw -www.cmoinc.org -olumpo.com -taoism.net -recoveryversion.com.tw -alliance.org.hk -falunhr.org -occupytiananmen.com -hkheadline.com -dalailama80.org -duihuahrjournal.org -specxinzl.jigsy.com -jav.com -tbrc.org -coinex.com -gvt0.com -newtalk.tw -minghui.org -btsynckeys.com -recordhistory.org -lflinkup.org -mohu.ml -aamacau.com -memrijttm.org -booktopia.com.au -ssglobal.co -realcourage.org -backtotiananmen.com -meme.yahoo.com -kissjav.com -china-week.com -chinagreenparty.org -kusocity.com -read100.com -caribbeancom.com -dynupdate.no-ip.com -www.linksalpha.com -4sqi.net -razyboard.com -tibetan-alliance.org -jungleheart.com -cos-moe.com -www.americorps.gov -www.ajsands.com -rawgit.com -wezone.net -cws.conviva.com -bet365.com -ranyunfei.com -sytes.net -rangzen.org -picturesocial.com -faststone.org -investigating.wordpress.com -xinshijue.com -woeser.com -gaymenring.com -raidcall.com.tw -google.co.uk -dajiyuan.de -sss.camp -cts.com.tw -56cun04.jigsy.com -c-spanvideo.org -six-degrees.io -disneyplus.com -google.ms -radiohilight.net -rael.org -ai-wen.net -seed4.me -nemesis2.qx.net -dvdpac.com -panoramio.com -quran.com -scribd.com -vocn.tv -chinalaborwatch.org -watchmygf.net -zhengwunet.org -izles.net -googleplus.com -chuizi.net -blogcatalog.com -hihiforum.com -youtu.be -buzzorange.com -tvider.com -china-mmm.sa.com -falunasia.info -qstatus.com -efksoft.com -zyns.com -trendsmap.com -qiwen.lu -qienkuen.org -sitemaps.org -synergyse.com -qidian.ca -qiangyou.org -chaturbate.com -rawgithub.com -citizensradio.org -godsdirectcontact.org -band.us -google.jo -css.pixnet.in -centerforhumanreprod.com -ghut.org -download.cnet.com -wiki.cnitter.com -i.lithium.com -news.hk.msn.com -myca168.com -boardreader.com -softsmirror.cf -solarsystem.nasa.gov -heyzo.com -dipity.com -coolstuffinc.com -python.com -tuibeitu.net -trulyergonomic.com -bongacams.com -liujianshu.com -dowei.org -dagelijksestandaard.nl -tagwa.org.au -artsy.net -playpcesor.com -chinese-memorial.org -minzhuzhanxian.com -cmule.org -punyu.com -chrdnet.com -xiaolan.me -telegram.org -bizhat.com -googleweblight.com -packages.debian.org -code1984.com -hbg.com -poloniex.com -cam4.sg -peing.net -channel8news.sg -ch.shvoong.com -nikkei.com -eracom.com.tw -gzm.tv -zzux.com -google.ba -proxytunnel.net -chatnook.com -tsemtulku.com -ccvoice.ca -askstudent.com -oclp.hk -beyondfirewall.com -proxifier.com -anthonycalzadilla.com -softwaredownload.gitbooks.io -free-ssh.com -procopytips.com -merit-times.com.tw -cao.im -chenpokong.net -enlighten.org.tw -thefacebook.com -new-akiba.com -private.com -smarthide.com -redchinacn.org -brutaltgp.com -guruonline.hk -prisoneralert.com -prestige-av.com -itsaol.com -ifcss.org -presentationzen.com -avfantasy.com -myaudiocast.com -shadowsocks.com.hk -desc.se -fanqianghou.com -huanghuagang.org -666kb.com -lematin.ch -redd.it -rixcloud.us -csdparty.com -madthumbs.com -switch1.jp -softfamous.com -recovery.org.tw -power.com -earthcam.com -puffinbrowser.com -boyangu.com -gazotube.com -pureinsight.org -sogrady.me -chromeexperiments.com -omni7.jp -trt.net.tr -like.com -mylftv.com -furhhdl.org -pearlher.org -fofg-europe.net -putty.org -sellclassics.com -tensorflow.org -mpettis.com -boxpn.com -99btgc01.com -tubaholic.com -dtwang.org -proxfree.com -news.msn.com.tw -provpnaccounts.com -blacklogic.com -expatshield.com -chinalawtranslate.com -youmaker.com -googleapis.com -mynumber.org -koornk.com -communistcrimes.org -mydad.info -cdn.printfriendly.com -www.powerpointninja.com -netme.cc -milsurps.com -mgstage.com -powercx.com -potvpn.com -ktzhk.com -freemorenews.com -lotuslight.org.hk -hkepc.com -koolsolutions.com -xrentdvd.com -poskotanews.com -gluckman.com -airvpn.org -emule-ed2k.com -savetibet.ru -jinx.com -hkreporter.com -ccdtr.org -kwcg.ca -twitstat.com -hidemyass.com -ipvanish.com -pornhubpremium.com -mofos.com -playno1.com -bit.ly -tui.orzdream.com -alternate-tools.com -cn.uptodown.com -pornbase.org -pacopacomama.com -beaconevents.com -boobstagram.com -erabaru.net -google.lv -raggedbanner.com -porn.com -dyndns-pics.com -google.sk -chromestatus.com -qiandao.today -chinesegay.org -politicalchina.org -5278.cc -pokerstars.net -freefuckvids.com -teddysun.com -lihkg.com -9gag.com -bl-doujinsouko.com -pmatehunter.com -wikileaks-forum.com -plurk.com -brizzly.com -dtiblog.com -228.net.tw -rsdlmonitor.com -talkboxapp.com -plays.com.tw -akademiye.org -e-hentai.org -chinacomments.org -nyaa.eu -www.zensur.freerk.com -google.tk -chromium.org -stoweboyd.com -admob.com -acevpn.com -1991way.com -weiboscope.jmsc.hku.hk -qgirl.com.tw -maxing.jp -makkahnewspaper.com -123rf.com -centralnation.com -bmfinn.com -pinterest.de -evschool.net -bbchat.tv -commentshk.com -pinterest.co.kr -chinaway.org -xuehua.us -pinimg.com -ping.fm -pin6.com -picidae.net -picacomiccn.com -2lipstube.com -proxomitron.info -freeyellow.com -moonbbs.com -htl.li -pfd.org.hk -ministrybooks.org -tuidang.se -ddns.me.uk -civicparty.hk -friendfeed.com -percy.in -32red.com -google.dk -peoplenews.tw -penthouse.com -blog.pentalogic.net -organcare.org.tw -vultryhw.com -rfa.org -twitzap.com -phmsociety.org -8-d.com -bitcoinworld.com -pemulihan.or.id -mingpaomonthly.com -chinadialogue.net -gdzf.org -amnesty.org.hk -peeasian.com -beevpn.com -peacehall.com -1688.com.au -hrichina.org -e123.hk -newtaiwan.com.tw -christusrex.org -phuquocservices.com -dolf.org.hk -peace.ca -pdproxy.com -footwiball.com -laomiu.com -bitshare.com -flickrhivemind.net -deezer.com -aobo.com.au -bailandaily.com -bitc.bme.emory.edu -ntd.tv -dessci.com -jigglegifs.com -pbxes.org -rolia.net -pbxes.com -whitebear.freebearblog.org -dalailamahindi.com -cointobe.com -25u.com -erodoujinworld.com -getcloak.com -wzyboy.im -85cc.net -letou.com -duckmylife.com -flagsonline.it -api-verify.recaptcha.net -freechina.net -primevideo.com -chuang-yen.org -goodtv.tv -arte.tv -liberal.org.hk -news.hkpeanut.com -cnpolitics.org -metarthunter.com -pbs.org -bignews.org -dreamamateurs.com -justmysocks1.net -nexttv.com.tw -pastie.org -pastebin.com -kepard.com -nalandabodhi.org -blockless.com -passion.com -partypoker.com -fanqiangzhe.com -thecenter.mit.edu -3-a.net -epac.to -bwh1.net -mingpaotor.com -haproxy.org -mponline.hk -icu-project.org -newsdh.com -omnitalk.org -3arabtv.com -xbookcn.com -dynawebinc.com -chinaaid.us -bbnradio.org -packetix.net -meyou.jp -shangfang.org -ozvoice.org -bbs.ozchinese.com -ow.ly -mingjingtimes.com -my.opera.com -ht.ly -xinqimeng.over-blog.com -oursweb.net -urbandictionary.com -freemuse.org -contactmagazine.net -waselpro.com -cdpweb.org -catholic.org.hk -otnd.org -gamousa.com -91porn.com -spaces.hightail.com -grandtrial.org -xfinity.com -osfoora.com -tibettelegraph.com -citizenscommission.hk -rfalive1.akacast.akamaistream.net -googlezip.net -t.orzdream.com -no-ip.org -taiwan-sex.com -orgfree.com -www.orchidbbs.com -google.fi -bcc.com.tw -openwebster.com -lbank.info -coursehero.com -pobieramy.top -korenan2.com -helloss.pw -psiphon.civisec.org -4chan.com -darktoy.net -btctrade.im -dcmilitary.com -rapidgator.net -tmdfish.com -open.com.hk -onmoon.com -hrweb.org -bebo.com -onlinecha.com -iu45.com -servehttp.com -marxist.com -shadowsocks.be -hkvwet.com -debug.com -nic.google -hk.video.news.yahoo.com -forum.omy.sg -chinesepen.org -yes-news.com -epochtimes.co.il -hkcoc.weather.com.hk -wuguoguang.com -nytimes.com -myforum.com.uk -eslite.com -grow.google -drtuber.com -old-cat.net -tellme.pw -khabdha.org -epochtimes.jp -githubassets.com -asiatoday.us -hkdailynews.com.hk -hk.jiepang.com -881903.com -softether.org -ogate.org -material.io -ogaoga.org -faithfuleye.com -t.co -mypopescu.com -ocaspro.com -fileflyer.com -rcam.target.com -betfair.com -observechina.net -nflximg.com -nylonstockingsonline.com -tumview.com -corumcollege.com -lighten.org.tw -fsurf.com -mypop3.net -cbc.ca -nvquan.org -nuvid.com -badoo.com -potato.im -nurgo-software.com -hk32168.com -bannedbook.org -codeshare.io -fanqiang.tk -cbs.ntu.edu.tw -ntdtvla.com -login.target.com -appsto.re -lesoir.be -bartvpn.com -hket.com -avyahoo.com -babynet.com.hk -rfi.fr -widevine.com -meripet.biz -facebook.hu -w.idaiwan.com -airasia.com -liuhanyu.com -curvefish.com -akamaihd.net -ntdtv.co.kr -surfeasy.com.au -freexinwen.com -torvpn.com -noypf.com -news.now.com -novelasia.com -ddc.com.tw -gcr.io -juyuange.org -lrip.org -kinmen.org.tw -heqinglian.net -sharpdaily.hk -caochangqing.com -18onlygirls.com -newstapa.org -pussyspace.com -google-analytics.com -cloud.mail.ru -thlib.org -cdjp.org -gotdns.ch -athenaeizou.com -paradisehill.cc -njactb.org -taiwanyes.ning.com -nintendium.com -nextmag.com.tw -search.yahoo.com -secure.logmein.com -av.nightlife141.com -nhentai.net -ngensis.com -joyourself.com -proxynetwork.org.uk -zhao.1984.city -coinegg.com -co.ng.mil -globalvpn.net -aceros-de-hispania.com -taiwankiss.com -173ng.com -tor.updatestar.com -yeahteentube.com -adult.friendfinder.com -chinapress.com.my -newstarnet.com -secretgarden.no -adelaidebbs.com -daozhongxing.org -mywww.biz -aboluowang.com -cloudfront.net -888poker.com -pincong.rocks -twister.net.co -hudson.org -newnews.ca -apkplz.com -organiccrap.com -itasoftware.com -br.st -allowed.org -braumeister.org -huaxin.ph -acmetoy.com -new-3lunch.net -tweetcs.com -decodet.co -zillionk.com -pinkrod.com -ndr.de -istars.co.nz -dpp.org.tw -yangjianli.com -vpnbook.com -a248.e.akamai.net -nko.navy.mil -freechinaforum.org -navyfamily.navy.mil -comparitech.com -tibetanaidproject.org -hotav.tv -citypopulation.de -nat.moe -americanunfinished.com -lockestek.com -crwdcntrl.net -mo.nightlife141.com -muchosucko.com -questvisual.com -steamcommunity.com -ghostpath.com -avmoo.com -laptoplockdown.com -uighur.narod.ru -briefdream.com -naol.cc -naol.ca -ssr.tools -gigporno.ru -heavy-r.com -earlytibet.com -nakuz.com -flipkart.com -myspacecdn.com -hacg.li -mysinablog.com -news.tvb.com -googlechinawebmaster.com -dronedj.com -mymusic.net.tw -onedumb.com -search.aol.com -mymom.info -vpncup.com -pagodabox.com -emaga.com -turbobit.net -ithelp.ithome.com.tw -dnsrd.com -24hrs.ca -my-proxy.com -tibetanyouthcongress.org -realsexpass.com -hacg.club -muslimvideo.com -goldjizz.com -engagedaily.org -mingshengbao.com -tweets.seraph.me -avcool.com -multiproxy.org -adpl.org.hk -epochhk.com -geocities.com -qz.com -mswe1.org -karkhung.com -abematv.akamaized.net -huobi.com -peacefire.org -tw.bid.yahoo.com -hungerstrikeforaids.org -behance.net -gjczz.com -coingi.com -gojet.krtco.com.tw -mp3ye.eu -mp3buscador.com -btspread.com -atnext.com -dlyoutube.com -3boys2girls.com -9bis.com -anysex.com -tuo8.red -2du5.com -moroneta.com -c1522.mooo.com -dwnews.net -monocloud.me -jihadology.net -bangyoulater.com -mog.com -memorybbs.com -fromchinatousa.net -4pu.com -wego.here.com -myparagliding.com -exploader.net -citizencn.com -dailyview.tw -mihk.hk -mmaaxx.com -research.google -mlcool.com -mixx.com -mixpod.com -in-disguise.com -cristyli.com -imgchili.net -glock.com -nyaa.si -cams.com -free-gate.org -tycool.com -eisbb.com -minhhue.net -faiththedog.info -bigmoney.biz -twblogger.com -mingpaony.com -aofriend.com -calgarychinese.com -jpopforum.net -mingpao.com -mingjinglishi.com -vpnaccounts.com -mihua.org -eriversoft.com -englishpen.org -teachparentstech.org -mindrolling.org -mergersandinquisitions.org -nyt.com -entnt.com -hougaige.com -onmypc.us -middle-way.net -bbs.mikocon.com -boyfriendtv.com -now.im -mercyprophet.org -sunwinism.joinbbs.net -polymer-project.org -duihua.org -cuihua.org -meteorshowersonline.com -metacafe.com -asg.to -meshrep.com -memri.org -amoiist.com -wiki.moegirl.org -tw.yahoo.com -meirixiaochao.com -megavideo.com -chhongbi.org -bbg.gov -enfal.de -megaproxy.com -ns3.name -google.is -kawaiikawaii.jp -olympicwatch.org -mcaf.ee -webmproject.org -nflxvideo.net -bic2011.org -crd-net.org -emulefans.com -mathiew-badimon.com -mathable.io -marxists.org -dish.com -thehousenews.com -jav68.tv -stackoverflow.com -onejav.com -chinafreepress.org -fartit.com -google.mn -indiemerch.com -blogspot.com -theinitium.com -blog.expofutures.com -enanyang.my -marguerite.su -cineastentreff.de -marc.info -maplew.com -madrau.com -welovecock.com -international-news.newsmagazine.asia -boxun.tv -e-info.org.tw -lsmradio.com -getchu.com -appsocks.net -lsmkorean.org -shiksha.com -lsforum.net -scache2.vzw.com -sowers.org.hk -clearharmony.net -authorizeddns.us -godsdirectcontact.co.uk -cenews.eu -cmx.im -multiply.com -lkcn.net -google.am -d3rhr7kgmtrq1v.cloudfront.net -yourtrap.com -epochtimes.com -erepublik.com -liudejun.com -gmozomg.izihost.org -ettoday.net -nudezz.com -mjlsh.usc.cuhk.edu.hk -duckdns.org -cactusvpn.com -google.gl -culture.tw -mqxd.org -buffered.com -blogcity.me -blog.cnyes.com -linglingfa.com -line-apps.com -blogs.libraryinformationtechnology.com -neverforget8964.org -howtoforge.com -jav2be.com -telegra.ph -cdn.assets.lfpcontent.com -legalporno.com -dabr.me -ccue.ca -danke4china.net -eucasino.com -chenguangcheng.com -100ke.org -faqserv.com -carabinasypistolas.com -forum.idsam.com -woxinghuiguo.com -quitccp.org -google.nl -googleapps.com -ctfriend.net -cdw.com -kawase.com -chrome.com -waiwaier.com -cap.org.hk -big.one -kui.name -ice.audionow.com -godsdirectcontact.org.tw -ksnews.com.tw -actfortibet.org -binux.me -tcpspeed.com -sthoo.com -doujincafe.com -daftporn.com -chinachannel.hk -python.com.tw -authorizeddns.org -zorrovpn.com -mynetav.net -taiwanjustice.net -faceless.me -tweetrans.com -kagyu.org.za -godoc.org -etaiwannews.com -kichiku-doujinko.com -keezmovies.com -hkfaa.com -www.moztw.org -arctosia.com -tubepornclassic.com -dssott.com -kantie.org -army.mil -cw.com.tw -abitno.linpie.com -anonymitynetwork.com -hitbtc.com -xuchao.org -kagyuoffice.org -kingdomsalvation.org -voanews.com -asianspiss.com -jwmusic.org -juziyue.com -tibet.org -fb.com -bbs.junglobal.net -foreignpolicy.com -junefourth-20.net -jubushoushen.com -asiaharvest.org -bipic.net -journalchretien.net -javhip.com -cnd.org -dalailamajapanese.com -gelbooru.com -jkforum.net -cnn.com -hentaivideoworld.com -jtvnw.net -mrslove.com -openallweb.com -daodu14.jigsy.com -badjojo.com -zb.com -abebooks.com -qtweeter.com -pcdvd.com.tw -fflick.com -llss.me -guaneryu.com -gongwt.com -ukcdp.co.uk -fzh999.net -blogtd.net -bitcointalk.org -aiweiwei.com -alexlur.org -javbus.co -digisfera.com -myradio.hk -ttvnw.net -ftp1.biz -18virginsex.com -hhdcb3office.org -iyouport.com -getlantern.org -gun-world.net -iverycd.com -toodoc.com -italiatibet.org -google.sc -get.how -israbox.com -englishfromengland.co.uk -seevpn.com -c2cx.com -calameo.com -disneyplus.com.ssl.sc.omtrdc.net -malaysiakini.com -animecrazy.net -islam.org.hk -goldstep.net -dns2go.com -bodog88.com -pornoxo.com -chinesen.de -ezua.com -ns1.name -authorizeddns.net -ikstar.com -website.informer.com -cirosantilli.com -info-graf.fr -indiandefensenews.in -lingvodics.com -6parkbbs.com -impact.org.au -imkev.com -maiplus.com -imgur.com -google.rw -asiatgp.com -18board.info -img.ly -imagevenue.com -addictedtocoffee.de -exrates.me -igfw.net -alvinalexander.com -huaren4us.com -ied2k.net -canalporno.com -myeclipseide.com -say2.info -dharamsalanet.com -danwei.org -bestvpnservice.com -i2p2.de -javbus.com -bbsone.com -arethusa.su -almostmy.com -falundafa-sacramento.org -21andy.com -treemall.com.tw -huashangnews.com -you-get.org -falundafa-nc.org -student.tw -china101.com -facebookquotes4u.com -hua-yue.net -freeddns.org -hst.net.tw -vpnfire.com -hsjp.net -hrcchina.org -creadersnet.com -qi-gong.me -nydus.ca -hornygamer.com -www.sciencemag.org -drgan.net -google.cd -hkusu.net -alljackpotscasino.com -baijie.org -sl-reverse.com -bloomberg.de -tibetanpaintings.com -vidble.com -nwtca.org -theguardian.com -hexieshe.com -nokogiri.org -edmontonchina.cn -thisav.com -blog.inoreader.com -bcmorning.com -dalailamafilm.com -glass8.eu -d1c37gjwa26taa.cloudfront.net -picasaweb.com -gunsamerica.com -hk.gradconnection.com -electrek.co -nofile.io -expekt.com -gov.tw -allinfa.com -great-roc.org -oculuscdn.com -xysblogs.org -crackle.com -aptoide.com -dnssec.net -godfootsteps.org -van001.com -superzooi.com -china-mmm.jp.net -twftp.org -dajiyuan.eu -youtubekids.com -archive.today -twitturk.com -gifree.com -pk.com -getiton.com -wjbk.org -gongmeng.info -search.xxx -thebobs.com -coolncute.com -blogdns.org -furinkan.com -messenger.com -chinaaffairs.org -nobelprize.org -frootvpn.com -uncyclopedia.tw -asiansexdiary.com -freewebs.com -canadameet.com -tw.money.yahoo.com -fapdu.com -fourface.nodesnoop.com -en.favotter.net -avaaz.org -heartyit.com -wwe.com -fan-qiang.com -nobel.se -molihua.org -bloomberg.com -tvplayvideos.com -fangong.org -jiji.com -amiblockedornot.com -mad-ar.ch -twurl.nl -etowns.org -ggpht.com -namgyalmonastery.org -go141.com -onmypc.net -mansionpoker.com -etaa.org.au -thinkwithgoogle.com -kakao.com -hwinfo.com -businesstoday.com.tw -eromangadouzin.com -ernestmandel.org -bakgeekhome.tk -googlemashups.com -epochtimes-romania.com -entermap.com -showtime.jp -141tube.com -breakwall.net -bloombergview.com -changeip.org -al-islam.com -aofriend.com.au -wo3t.wordpress.com -dynamicdns.me.uk -dotsub.com -apetube.com -googlelabs.com -h528.com -dlsite.com -dizhidizhi.com -justdied.com -rsf-chinese.org -digiland.tw -ccthere.com -dns1.us -youtube-nocookie.com -fangongheike.com -muzi.com -googlemail.com -cdpusa.org -google.to -chromecast.com -dalailamafoundation.org -barnabu.co.uk -destroy-china.jp -manta.com -bx.tl -blogspot.jp -fatbtc.com diff --git a/package/lienol/luci-app-passwall/root/usr/share/passwall/rules/proxy_host b/package/lienol/luci-app-passwall/root/usr/share/passwall/rules/proxy_host deleted file mode 100644 index 70a21acf2c..0000000000 --- a/package/lienol/luci-app-passwall/root/usr/share/passwall/rules/proxy_host +++ /dev/null @@ -1,8 +0,0 @@ -googleapis.cn -googleapis.com -google.com.tw -google.com.hk -gstatic.com -xn--ngstr-lra8j.com -github.com -v2ex.com \ No newline at end of file diff --git a/package/lienol/luci-app-passwall/root/usr/share/passwall/rules/proxy_ip b/package/lienol/luci-app-passwall/root/usr/share/passwall/rules/proxy_ip deleted file mode 100644 index eecd323ecd..0000000000 --- a/package/lienol/luci-app-passwall/root/usr/share/passwall/rules/proxy_ip +++ /dev/null @@ -1,18 +0,0 @@ -149.154.160.0/20 -91.108.4.0/22 -91.108.56.0/24 -109.239.140.0/24 -67.198.55.0/24 -8.8.4.4 -8.8.8.8 -208.67.222.222 -208.67.220.220 -1.1.1.1 -1.0.0.1 -9.9.9.9 -149.112.112.112 -2001:67c:4e8::/48 -2001:b28:f23c::/48 -2001:b28:f23d::/48 -2001:b28:f23f::/48 -2001:b28:f242::/48 \ No newline at end of file diff --git a/package/lienol/luci-app-passwall/root/usr/share/passwall/subscribe.lua b/package/lienol/luci-app-passwall/root/usr/share/passwall/subscribe.lua deleted file mode 100755 index e298622960..0000000000 --- a/package/lienol/luci-app-passwall/root/usr/share/passwall/subscribe.lua +++ /dev/null @@ -1,1001 +0,0 @@ -#!/usr/bin/lua - ------------------------------------------------- --- @author William Chan ------------------------------------------------- -require 'nixio' -require 'luci.model.uci' -require 'luci.util' -require 'luci.jsonc' -require 'luci.sys' -local datatypes = require "luci.cbi.datatypes" -local api = require "luci.model.cbi.passwall.api.api" -local has_xray = api.is_finded("xray") - --- these global functions are accessed all the time by the event handler --- so caching them is worth the effort -local luci = luci -local tinsert = table.insert -local ssub, slen, schar, sbyte, sformat, sgsub = string.sub, string.len, string.char, string.byte, string.format, string.gsub -local jsonParse, jsonStringify = luci.jsonc.parse, luci.jsonc.stringify -local b64decode = nixio.bin.b64decode -local nodeResult = {} -- update result -local application = 'passwall' -local uciType = 'nodes' -local ucic2 = luci.model.uci.cursor() -local arg2 = arg[2] -local allowInsecure_default = ucic2:get_bool(application, "@global_subscribe[0]", "allowInsecure") -ucic2:revert(application) - -local log = function(...) - if arg2 then - local result = os.date("%Y-%m-%d %H:%M:%S: ") .. table.concat({...}, " ") - if arg2 == "log" then - local f, err = io.open("/var/log/passwall.log", "a") - if f and err == nil then - f:write(result .. "\n") - f:close() - end - elseif arg2 == "print" then - print(result) - end - end -end - --- 获取各项动态配置的当前服务器,可以用 get 和 set, get必须要获取到节点表 -local CONFIG = {} -do - local function import_config(protocol) - local name = string.upper(protocol) - local szType = "@global[0]" - local option = protocol .. "_node" - - local node_id = ucic2:get(application, szType, option) - CONFIG[#CONFIG + 1] = { - log = true, - remarks = name .. "节点", - currentNodeId = node_id, - currentNode = node_id and ucic2:get_all(application, node_id) or nil, - set = function(o, server) - ucic2:set(application, szType, option, server) - o.newNodeId = server - end - } - end - import_config("tcp") - import_config("udp") - - local i = 0 - ucic2:foreach(application, "socks", function(t) - i = i + 1 - local node_id = t.node - CONFIG[#CONFIG + 1] = { - log = true, - id = t[".name"], - remarks = "Socks节点列表[" .. i .. "]", - currentNodeId = node_id, - currentNode = node_id and ucic2:get_all(application, node_id) or nil, - set = function(o, server) - ucic2:set(application, t[".name"], "node", server) - o.newNodeId = server - end - } - end) - - local tcp_node_table = ucic2:get(application, "@auto_switch[0]", "tcp_node") - if tcp_node_table then - local nodes = {} - local new_nodes = {} - for k,node in ipairs(tcp_node_table) do - nodes[#nodes + 1] = { - log = true, - remarks = "TCP备用节点的列表[" .. k .. "]", - currentNodeId = node, - currentNode = node and ucic2:get_all(application, node) or nil, - set = function(o, server) - for kk, vv in pairs(CONFIG) do - if (vv.remarks == "TCP备用节点的列表") then - table.insert(vv.new_nodes, server) - end - end - end - } - end - CONFIG[#CONFIG + 1] = { - remarks = "TCP备用节点的列表", - nodes = nodes, - new_nodes = new_nodes, - set = function(o) - for kk, vv in pairs(CONFIG) do - if (vv.remarks == "TCP备用节点的列表") then - --log("刷新自动切换的TCP备用节点的列表") - ucic2:set_list(application, "@auto_switch[0]", "tcp_node", vv.new_nodes) - end - end - end - } - end - - ucic2:foreach(application, uciType, function(node) - if node.protocol and node.protocol == '_shunt' then - local node_id = node[".name"] - ucic2:foreach(application, "shunt_rules", function(e) - local _node_id = node[e[".name"]] or nil - CONFIG[#CONFIG + 1] = { - log = false, - currentNodeId = _node_id, - currentNode = _node_id and ucic2:get_all(application, _node_id) or nil, - remarks = "分流" .. e.remarks .. "节点", - set = function(o, server) - ucic2:set(application, node_id, e[".name"], server) - o.newNodeId = server - end - } - end) - - local default_node_id = node.default_node - CONFIG[#CONFIG + 1] = { - log = true, - currentNodeId = default_node_id, - currentNode = default_node_id and ucic2:get_all(application, default_node_id) or nil, - remarks = "分流默认节点", - set = function(o, server) - ucic2:set(application, node_id, "default_node", server) - o.newNodeId = server - end - } - - local main_node_id = node.main_node - CONFIG[#CONFIG + 1] = { - log = true, - currentNodeId = main_node_id, - currentNode = main_node_id and ucic2:get_all(application, main_node_id) or nil, - remarks = "分流默认前置代理节点", - set = function(o, server) - ucic2:set(application, node_id, "main_node", server) - o.newNodeId = server - end - } - elseif node.protocol and node.protocol == '_balancing' then - local node_id = node[".name"] - local nodes = {} - local new_nodes = {} - if node.balancing_node then - for k, node in pairs(node.balancing_node) do - nodes[#nodes + 1] = { - log = false, - node = node, - currentNode = node and ucic2:get_all(application, node) or nil, - remarks = node, - set = function(o, server) - for kk, vv in pairs(CONFIG) do - if (vv.remarks == "负载均衡节点列表" .. node_id) then - table.insert(vv.new_nodes, server) - end - end - end - } - end - end - CONFIG[#CONFIG + 1] = { - remarks = "负载均衡节点列表" .. node_id, - nodes = nodes, - new_nodes = new_nodes, - set = function(o) - for kk, vv in pairs(CONFIG) do - if (vv.remarks == "负载均衡节点列表" .. node_id) then - --log("刷新负载均衡节点列表") - ucic2:foreach(application, uciType, function(node2) - if node2[".name"] == node[".name"] then - local index = node2[".index"] - ucic2:set_list(application, "@nodes[" .. index .. "]", "balancing_node", vv.new_nodes) - end - end) - end - end - end - } - end - end) - - for k, v in pairs(CONFIG) do - if v.nodes and type(v.nodes) == "table" then - for kk, vv in pairs(v.nodes) do - if vv.currentNode == nil then - CONFIG[k].nodes[kk] = nil - end - end - else - if v.currentNode == nil then - CONFIG[k] = nil - end - end - end -end - --- 判断是否过滤节点关键字 -local filter_keyword_mode = ucic2:get(application, "@global_subscribe[0]", "filter_keyword_mode") or "0" -local filter_keyword_discard_list = ucic2:get(application, "@global_subscribe[0]", "filter_discard_list") or {} -local filter_keyword_keep_list = ucic2:get(application, "@global_subscribe[0]", "filter_keep_list") or {} -local function is_filter_keyword(value) - if filter_keyword_mode == "1" then - for k,v in ipairs(filter_keyword_discard_list) do - if value:find(v) then - return true - end - end - elseif filter_keyword_mode == "2" then - local result = true - for k,v in ipairs(filter_keyword_keep_list) do - if value:find(v) then - result = false - end - end - return result - end - return false -end - --- 分割字符串 -local function split(full, sep) - if full then - full = full:gsub("%z", "") -- 这里不是很清楚 有时候结尾带个\0 - local off, result = 1, {} - while true do - local nStart, nEnd = full:find(sep, off) - if not nEnd then - local res = ssub(full, off, slen(full)) - if #res > 0 then -- 过滤掉 \0 - tinsert(result, res) - end - break - else - tinsert(result, ssub(full, off, nStart - 1)) - off = nEnd + 1 - end - end - return result - end - return {} -end --- urlencode --- local function get_urlencode(c) return sformat("%%%02X", sbyte(c)) end - --- local function urlEncode(szText) --- local str = szText:gsub("([^0-9a-zA-Z ])", get_urlencode) --- str = str:gsub(" ", "+") --- return str --- end - -local function get_urldecode(h) return schar(tonumber(h, 16)) end -local function UrlDecode(szText) - return (szText and szText:gsub("+", " "):gsub("%%(%x%x)", get_urldecode)) or nil -end - --- trim -local function trim(text) - if not text or text == "" then return "" end - return (sgsub(text, "^%s*(.-)%s*$", "%1")) -end - --- base64 -local function base64Decode(text) - local raw = text - if not text then return '' end - text = text:gsub("%z", "") - text = text:gsub("_", "/") - text = text:gsub("-", "+") - local mod4 = #text % 4 - text = text .. string.sub('====', mod4 + 1) - local result = b64decode(text) - if result then - return result:gsub("%z", "") - else - return raw - end -end --- 处理数据 -local function processData(szType, content, add_mode) - --log(content, add_mode) - local result = { - timeout = 60, - add_mode = add_mode, - is_sub = add_mode == '导入' and 0 or 1 - } - if szType == 'ssr' then - local dat = split(content, "/%?") - local hostInfo = split(dat[1], ':') - result.type = "SSR" - result.address = hostInfo[1] - result.port = hostInfo[2] - result.protocol = hostInfo[3] - result.method = hostInfo[4] - result.obfs = hostInfo[5] - result.password = base64Decode(hostInfo[6]) - local params = {} - for _, v in pairs(split(dat[2], '&')) do - local t = split(v, '=') - params[t[1]] = t[2] - end - result.obfs_param = base64Decode(params.obfsparam) - result.protocol_param = base64Decode(params.protoparam) - local group = base64Decode(params.group) - if group then result.group = group end - result.remarks = base64Decode(params.remarks) - elseif szType == 'vmess' then - local info = jsonParse(content) - result.type = 'Xray' - result.address = info.add - result.port = info.port - result.protocol = 'vmess' - result.alter_id = info.aid - result.uuid = info.id - result.remarks = info.ps - -- result.mux = 1 - -- result.mux_concurrency = 8 - if info.net == 'ws' then - result.ws_host = info.host - result.ws_path = info.path - end - if info.net == 'h2' then - result.h2_host = info.host - result.h2_path = info.path - end - if info.net == 'tcp' then - if info.type and info.type ~= "http" then - info.type = "none" - end - result.tcp_guise = info.type - result.tcp_guise_http_host = info.host - result.tcp_guise_http_path = info.path - end - if info.net == 'kcp' or info.net == 'mkcp' then - info.net = "mkcp" - result.mkcp_guise = info.type - result.mkcp_mtu = 1350 - result.mkcp_tti = 50 - result.mkcp_uplinkCapacity = 5 - result.mkcp_downlinkCapacity = 20 - result.mkcp_readBufferSize = 2 - result.mkcp_writeBufferSize = 2 - end - if info.net == 'quic' then - result.quic_guise = info.type - result.quic_key = info.key - result.quic_security = info.securty - end - result.transport = info.net - if not info.security then result.security = "auto" end - if info.tls == "tls" or info.tls == "1" then - result.tls = "1" - result.tls_serverName = info.sni - result.tls_allowInsecure = allowInsecure_default and "1" or "0" - else - result.tls = "0" - end - elseif szType == "ss" then - local idx_sp = 0 - local alias = "" - if content:find("#") then - idx_sp = content:find("#") - alias = content:sub(idx_sp + 1, -1) - end - result.remarks = UrlDecode(alias) - local info = content:sub(1, idx_sp - 1) - local hostInfo = split(base64Decode(info), "@") - local hostInfoLen = #hostInfo - local host = nil - local userinfo = nil - if hostInfoLen > 2 then - host = split(hostInfo[hostInfoLen], ":") - userinfo = {} - for i = 1, hostInfoLen - 1 do - tinsert(userinfo, hostInfo[i]) - end - userinfo = table.concat(userinfo, '@') - else - host = split(hostInfo[2], ":") - userinfo = base64Decode(hostInfo[1]) - end - local method = userinfo:sub(1, userinfo:find(":") - 1) - local password = userinfo:sub(userinfo:find(":") + 1, #userinfo) - result.type = "SS" - result.address = host[1] - if host[2] and host[2]:find("/%?") then - local query = split(host[2], "/%?") - result.port = query[1] - local params = {} - for _, v in pairs(split(query[2], '&')) do - local t = split(v, '=') - params[t[1]] = t[2] - end - if params.plugin then - local plugin_info = UrlDecode(params.plugin) - local idx_pn = plugin_info:find(";") - if idx_pn then - result.plugin = plugin_info:sub(1, idx_pn - 1) - result.plugin_opts = - plugin_info:sub(idx_pn + 1, #plugin_info) - else - result.plugin = plugin_info - end - end - if result.plugin and result.plugin == "simple-obfs" then - result.plugin = "obfs-local" - end - else - result.port = host[2] - end - result.method = method - result.password = password - elseif szType == "trojan" then - local alias = "" - if content:find("#") then - local idx_sp = content:find("#") - alias = content:sub(idx_sp + 1, -1) - content = content:sub(0, idx_sp - 1) - end - result.remarks = UrlDecode(alias) - result.type = "Trojan-Plus" - if has_xray then - result.type = 'Xray' - result.protocol = 'trojan' - end - if content:find("@") then - local Info = split(content, "@") - result.password = UrlDecode(Info[1]) - local port = "443" - Info[2] = (Info[2] or ""):gsub("/%?", "?") - local hostInfo = nil - if Info[2]:find(":") then - hostInfo = split(Info[2], ":") - result.address = hostInfo[1] - local idx_port = 2 - if hostInfo[2]:find("?") then - hostInfo = split(hostInfo[2], "?") - idx_port = 1 - end - if hostInfo[idx_port] ~= "" then port = hostInfo[idx_port] end - else - if Info[2]:find("?") then - hostInfo = split(Info[2], "?") - end - result.address = hostInfo and hostInfo[1] or Info[2] - end - local peer, sni = nil, "" - local allowInsecure = allowInsecure_default - local query = split(Info[2], "?") - local params = {} - for _, v in pairs(split(query[2], '&')) do - local t = split(v, '=') - params[string.lower(t[1])] = UrlDecode(t[2]) - end - if params.allowinsecure then - allowInsecure = params.allowinsecure - end - if params.peer then peer = params.peer end - sni = params.sni and params.sni or "" - if params.ws and params.ws == "1" then - result.trojan_transport = "ws" - if params.wshost then result.ws_host = params.wshost end - if params.wspath then result.ws_path = params.wspath end - if sni == "" and params.wshost then sni = params.wshost end - end - if params.ss and params.ss == "1" then - result.ss_aead = "1" - if params.ssmethod then result.ss_aead_method = string.lower(params.ssmethod) end - if params.sspasswd then result.ss_aead_pwd = params.sspasswd end - end - result.port = port - if result.trojan_transport == "ws" or result.ss_aead then - result.type = "Trojan-Go" - result.fingerprint = "firefox" - result.mux = "1" - end - result.tls = '1' - result.tls_serverName = peer and peer or sni - result.tls_allowInsecure = allowInsecure and "1" or "0" - end - elseif szType == "trojan-go" then - local alias = "" - if content:find("#") then - local idx_sp = content:find("#") - alias = content:sub(idx_sp + 1, -1) - content = content:sub(0, idx_sp - 1) - end - result.remarks = UrlDecode(alias) - result.type = "Trojan-Go" - if content:find("@") then - local Info = split(content, "@") - result.password = UrlDecode(Info[1]) - local port = "443" - Info[2] = (Info[2] or ""):gsub("/%?", "?") - local hostInfo = nil - if Info[2]:find(":") then - hostInfo = split(Info[2], ":") - result.address = hostInfo[1] - local idx_port = 2 - if hostInfo[2]:find("?") then - hostInfo = split(hostInfo[2], "?") - idx_port = 1 - end - if hostInfo[idx_port] ~= "" then port = hostInfo[idx_port] end - else - if Info[2]:find("?") then - hostInfo = split(Info[2], "?") - end - result.address = hostInfo and hostInfo[1] or Info[2] - end - local peer, sni = nil, "" - local query = split(Info[2], "?") - local params = {} - for _, v in pairs(split(query[2], '&')) do - local t = split(v, '=') - params[string.lower(t[1])] = UrlDecode(t[2]) - end - if params.peer then peer = params.peer end - sni = params.sni and params.sni or "" - if params.type and params.type == "ws" then - result.trojan_transport = "ws" - if params.host then result.ws_host = params.host end - if params.path then result.ws_path = params.path end - if sni == "" and params.host then sni = params.host end - end - if params.encryption and params.encryption:match('^ss;[^;:]*[;:].*$') then - result.ss_aead = "1" - result.ss_aead_method, result.ss_aead_pwd = params.encryption:match('^ss;([^;:]*)[;:](.*)$') - result.ss_aead_method = string.lower(result.ss_aead_method) - end - result.port = port - result.fingerprint = "firefox" - result.tls = "1" - result.tls_serverName = peer and peer or sni - result.tls_allowInsecure = "0" - result.mux = "1" - end - elseif szType == "ssd" then - result.type = "SS" - result.address = content.server - result.port = content.port - result.password = content.password - result.method = content.encryption - result.plugin = content.plugin - result.plugin_opts = content.plugin_options - result.group = content.airport - result.remarks = content.remarks - elseif szType == "vless" then - result.type = "Xray" - result.protocol = "vless" - local alias = "" - if content:find("#") then - local idx_sp = content:find("#") - alias = content:sub(idx_sp + 1, -1) - content = content:sub(0, idx_sp - 1) - end - result.remarks = UrlDecode(alias) - if content:find("@") then - local Info = split(content, "@") - result.uuid = UrlDecode(Info[1]) - local port = "443" - Info[2] = (Info[2] or ""):gsub("/%?", "?") - local hostInfo = nil - if Info[2]:find(":") then - hostInfo = split(Info[2], ":") - result.address = hostInfo[1] - local idx_port = 2 - if hostInfo[2]:find("?") then - hostInfo = split(hostInfo[2], "?") - idx_port = 1 - end - if hostInfo[idx_port] ~= "" then port = hostInfo[idx_port] end - else - if Info[2]:find("?") then - hostInfo = split(Info[2], "?") - end - result.address = hostInfo and hostInfo[1] or Info[2] - end - - local query = split(Info[2], "?") - local params = {} - for _, v in pairs(split(query[2], '&')) do - local t = split(v, '=') - params[t[1]] = UrlDecode(t[2]) - end - - if params.type == 'ws' then - result.ws_host = params.host - result.ws_path = params.path - end - if params.type == 'h2' then - result.h2_host = params.host - result.h2_path = params.path - end - if params.type == 'tcp' then - result.tcp_guise = params.headerType or "none" - result.tcp_guise_http_host = params.host - result.tcp_guise_http_path = params.path - end - if params.type == 'kcp' or params.type == 'mkcp' then - params.type = "mkcp" - result.mkcp_guise = params.headerType or "none" - result.mkcp_mtu = 1350 - result.mkcp_tti = 50 - result.mkcp_uplinkCapacity = 5 - result.mkcp_downlinkCapacity = 20 - result.mkcp_readBufferSize = 2 - result.mkcp_writeBufferSize = 2 - end - if params.type == 'quic' then - result.quic_guise = params.headerType or "none" - result.quic_key = params.key - result.quic_security = params.quicSecurity or "none" - end - result.transport = params.type - - result.encryption = params.encryption or "none" - - result.tls = "0" - if params.security == "tls" or params.security == "xtls" then - result.tls = "1" - if params.security == "xtls" then - result.xtls = "1" - result.flow = params.flow or "xtls-rprx-direct" - end - if params.sni then - result.tls_serverName = params.sni - end - end - - result.port = port - result.tls_allowInsecure = allowInsecure_default and "1" or "0" - end - else - log('暂时不支持' .. szType .. "类型的节点订阅,跳过此节点。") - return nil - end - if not result.remarks or result.remarks == "" then - if result.address and result.port then - result.remarks = result.address .. ':' .. result.port - else - result.remarks = "NULL" - end - end - return result -end - --- curl -local function curl(url) - local ua = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36" - local stdout = luci.sys.exec('curl -sL --user-agent "' .. ua .. '" -k --retry 3 --connect-timeout 3 "' .. url .. '"') - return trim(stdout) -end - -local function truncate_nodes() - for _, config in pairs(CONFIG) do - if config.nodes and type(config.nodes) == "table" then - for kk, vv in pairs(config.nodes) do - if vv.currentNode.is_sub and vv.currentNode.is_sub == "1" then - else - vv.set(vv, vv.currentNodeId) - end - end - config.set(config) - else - if config.currentNode.is_sub and config.currentNode.is_sub == "1" then - config.set(config, "nil") - if config.id then - ucic2:delete(application, config.id) - end - end - end - end - ucic2:foreach(application, uciType, function(node) - if (node.is_sub or node.hashkey) and node.add_mode ~= '导入' then - ucic2:delete(application, node['.name']) - end - end) - ucic2:commit(application) - - log('在线订阅节点已全部删除') -end - -local function select_node(nodes, config) - local server - if config.currentNode then - -- 特别优先级 分流 + 备注 - if config.currentNode.protocol and config.currentNode.protocol == '_shunt' then - for index, node in pairs(nodes) do - if node.remarks == config.currentNode.remarks then - log('更新【' .. config.remarks .. '】分流匹配节点:' .. node.remarks) - server = node[".name"] - break - end - end - end - -- 特别优先级 负载均衡 + 备注 - if config.currentNode.protocol and config.currentNode.protocol == '_balancing' then - for index, node in pairs(nodes) do - if node.remarks == config.currentNode.remarks then - log('更新【' .. config.remarks .. '】负载均衡匹配节点:' .. node.remarks) - server = node[".name"] - break - end - end - end - -- 第一优先级 cfgid - if not server then - for index, node in pairs(nodes) do - if node[".name"] == config.currentNode['.name'] then - if config.log == nil or config.log == true then - log('更新【' .. config.remarks .. '】第一匹配节点:' .. node.remarks) - end - server = node[".name"] - break - end - end - end - -- 第二优先级 类型 + IP + 端口 - if not server then - for index, node in pairs(nodes) do - if config.currentNode.type and config.currentNode.address and config.currentNode.port then - if node.type and node.address and node.port then - if node.type == config.currentNode.type and (node.address .. ':' .. node.port == config.currentNode.address .. ':' .. config.currentNode.port) then - if config.log == nil or config.log == true then - log('更新【' .. config.remarks .. '】第二匹配节点:' .. node.remarks) - end - server = node[".name"] - break - end - end - end - end - end - -- 第三优先级 IP + 端口 - if not server then - for index, node in pairs(nodes) do - if config.currentNode.address and config.currentNode.port then - if node.address and node.port then - if node.address .. ':' .. node.port == config.currentNode.address .. ':' .. config.currentNode.port then - if config.log == nil or config.log == true then - log('更新【' .. config.remarks .. '】第三匹配节点:' .. node.remarks) - end - server = node[".name"] - break - end - end - end - end - end - -- 第四优先级 IP - if not server then - for index, node in pairs(nodes) do - if config.currentNode.address then - if node.address then - if node.address == config.currentNode.address then - if config.log == nil or config.log == true then - log('更新【' .. config.remarks .. '】第四匹配节点:' .. node.remarks) - end - server = node[".name"] - break - end - end - end - end - end - -- 第五优先级备注 - if not server then - for index, node in pairs(nodes) do - if config.currentNode.remarks then - if node.remarks then - if node.remarks == config.currentNode.remarks then - if config.log == nil or config.log == true then - log('更新【' .. config.remarks .. '】第五匹配节点:' .. node.remarks) - end - server = node[".name"] - break - end - end - end - end - end - end - -- 还不行 随便找一个 - if not server then - server = ucic2:get_all(application, '@' .. uciType .. '[0]') - if server then - if config.log == nil or config.log == true then - log('【' .. config.remarks .. '】' .. '无法找到最匹配的节点,当前已更换为:' .. server.remarks) - end - server = server[".name"] - end - end - if server then - config.set(config, server) - end -end - -local function update_node(manual) - if next(nodeResult) == nil then - log("更新失败,没有可用的节点信息") - return - end - -- delete all for subscribe nodes - ucic2:foreach(application, uciType, function(node) - -- 如果是手动导入的节点就不参与删除 - if manual == 0 and (node.is_sub or node.hashkey) and node.add_mode ~= '导入' then - ucic2:delete(application, node['.name']) - end - end) - for _, v in ipairs(nodeResult) do - for _, vv in ipairs(v) do - local uuid = api.gen_uuid() - local cfgid = ucic2:section(application, uciType, uuid) - cfgid = uuid - for kkk, vvv in pairs(vv) do - ucic2:set(application, cfgid, kkk, vvv) - end - end - end - ucic2:commit(application) - - if next(CONFIG) then - local nodes = {} - local ucic3 = luci.model.uci.cursor() - ucic3:foreach(application, uciType, function(node) - nodes[#nodes + 1] = node - end) - - for _, config in pairs(CONFIG) do - if config.nodes and type(config.nodes) == "table" then - for kk, vv in pairs(config.nodes) do - select_node(nodes, vv) - end - config.set(config) - else - select_node(nodes, config) - end - end - - --[[ - for k, v in pairs(CONFIG) do - if type(v.new_nodes) == "table" and #v.new_nodes > 0 then - local new_node_list = "" - for kk, vv in pairs(v.new_nodes) do - new_node_list = new_node_list .. vv .. " " - end - if new_node_list ~= "" then - print(v.remarks, new_node_list) - end - else - print(v.remarks, v.newNodeId) - end - end - ]]-- - - ucic2:commit(application) - end - luci.sys.call("/etc/init.d/" .. application .. " restart > /dev/null 2>&1 &") -end - -local function parse_link(raw, remark, manual) - if raw and #raw > 0 then - local add_mode - local nodes, szType - local all_nodes = {} - tinsert(nodeResult, all_nodes) - -- SSD 似乎是这种格式 ssd:// 开头的 - if raw:find('ssd://') then - szType = 'ssd' - add_mode = remark - local nEnd = select(2, raw:find('ssd://')) - nodes = base64Decode(raw:sub(nEnd + 1, #raw)) - nodes = jsonParse(nodes) - local extra = { - airport = nodes.airport, - port = nodes.port, - encryption = nodes.encryption, - password = nodes.password - } - local servers = {} - -- SS里面包着 干脆直接这样 - for _, server in ipairs(nodes.servers) do - tinsert(servers, setmetatable(server, { __index = extra })) - end - nodes = servers - else - -- ssd 外的格式 - if manual then - nodes = split(raw:gsub(" ", "\n"), "\n") - add_mode = '导入' - else - nodes = split(base64Decode(raw):gsub(" ", "\n"), "\n") - add_mode = remark - end - end - - for _, v in ipairs(nodes) do - if v then - local result - if szType == 'ssd' then - result = processData(szType, v, add_mode) - elseif not szType then - local node = trim(v) - local dat = split(node, "://") - if dat and dat[1] and dat[2] then - if dat[1] == 'ss' or dat[1] == 'trojan' or dat[1] == 'trojan-go' then - result = processData(dat[1], dat[2], add_mode) - else - result = processData(dat[1], base64Decode(dat[2]), add_mode) - end - end - else - log('跳过未知类型: ' .. szType) - end - -- log(result) - if result then - if (not manual and is_filter_keyword(result.remarks)) or - not result.address or - result.remarks == "NULL" or - (not datatypes.hostname(result.address) and not (datatypes.ipmask4(result.address) or datatypes.ipmask6(result.address))) - then - log('丢弃过滤节点: ' .. result.type .. ' 节点, ' .. result.remarks) - else - tinsert(all_nodes, result) - end - end - end - end - log('成功解析节点数量: ' .. #all_nodes) - else - if not manual then - log('获取到的节点内容为空...') - end - end -end - -local execute = function() - -- exec - do - ucic2:foreach(application, "subscribe_list", function(obj) - local enabled = obj.enabled or nil - if enabled and enabled == "1" then - local remark = obj.remark - local url = obj.url - log('正在订阅: ' .. url) - local raw = curl(url) - parse_link(raw, remark) - end - end) - -- diff - update_node(0) - end -end - -if arg[1] then - if arg[1] == "start" then - local count = luci.sys.exec("echo -n $(uci show " .. application .. " | grep @subscribe_list | grep -c \"enabled='1'\")") - if count and tonumber(count) > 0 then - log('开始订阅...') - xpcall(execute, function(e) - log(e) - log(debug.traceback()) - log('发生错误, 正在恢复服务') - end) - log('订阅完毕...') - else - log('未设置订阅或未启用订阅, 请检查设置...') - end - elseif arg[1] == "add" then - local f = assert(io.open("/tmp/links.conf", 'r')) - local content = f:read('*all') - f:close() - local nodes = split(content:gsub(" ", "\n"), "\n") - for _, raw in ipairs(nodes) do - parse_link(raw, nil, 1) - end - update_node(1) - luci.sys.call("rm -f /tmp/links.conf") - elseif arg[1] == "truncate" then - truncate_nodes() - end -end diff --git a/package/lienol/luci-app-passwall/root/usr/share/passwall/test.sh b/package/lienol/luci-app-passwall/root/usr/share/passwall/test.sh deleted file mode 100755 index 51f5f730fa..0000000000 --- a/package/lienol/luci-app-passwall/root/usr/share/passwall/test.sh +++ /dev/null @@ -1,169 +0,0 @@ -#!/bin/sh - -CONFIG=passwall -LOG_FILE=/var/log/$CONFIG.log - -echolog() { - local d="$(date "+%Y-%m-%d %H:%M:%S")" - #echo -e "$d: $1" - echo -e "$d: $1" >> $LOG_FILE -} - -config_n_get() { - local ret=$(uci -q get "${CONFIG}.${1}.${2}" 2>/dev/null) - echo "${ret:=$3}" -} - -config_t_get() { - local index=0 - [ -n "$4" ] && index=$4 - local ret=$(uci -q get $CONFIG.@$1[$index].$2 2>/dev/null) - echo ${ret:=$3} -} - -test_url() { - local url=$1 - local try=1 - [ -n "$2" ] && try=$2 - local timeout=2 - [ -n "$3" ] && timeout=$3 - local extra_params=$4 - status=$(/usr/bin/curl -I -o /dev/null -skL $extra_params --connect-timeout $timeout --retry $try -w %{http_code} "$url") - case "$status" in - 204|\ - 200) - status=200 - ;; - esac - echo $status -} - -test_proxy() { - local try=3 - result=0 - status=$(test_url "https://www.google.com/generate_204" $try) - if [ "$status" = "200" ]; then - result=0 - else - status2=$(test_url "https://www.baidu.com" $try) - if [ "$status2" = "200" ]; then - result=1 - else - result=2 - fi - fi - echo $result -} - -test_auto_switch() { - local TYPE=$1 - local b_tcp_nodes=$2 - local now_node - if [ -f "/var/etc/$CONFIG/id/${TYPE}" ]; then - now_node=$(cat /var/etc/$CONFIG/id/${TYPE}) - else - return 1 - fi - - status=$(test_proxy) - if [ "$status" == 2 ]; then - echolog "自动切换检测:无法连接到网络,请检查网络是否正常!" - return 2 - fi - - local restore_switch=$(config_t_get auto_switch restore_switch 0) - if [ "$restore_switch" == "1" ]; then - #检测主节点是否能使用 - local main_node=$(config_t_get global tcp_node nil) - if [ "$main_node" != "nil" ] && [ "$now_node" != "$main_node" ]; then - local node_type=$(echo $(config_n_get $main_node type) | tr 'A-Z' 'a-z') - if [ "$node_type" == "socks" ]; then - local node_address=$(config_n_get $main_node address) - local node_port=$(config_n_get $main_node port) - [ -n "$node_address" ] && [ -n "$node_port" ] && { - local curlx="socks5h://$node_address:$node_port" - local node_username=$(config_n_get $main_node username) - local node_password=$(config_n_get $main_node password) - [ -n "$node_username" ] && [ -n "$node_password" ] && curlx="socks5h://$node_username:$node_password@$node_address:$node_port" - } - else - local tmp_port=$(/usr/share/${CONFIG}/app.sh get_new_port 61080 tcp) - /usr/share/${CONFIG}/app.sh run_socks "auto_switch" "$main_node" "127.0.0.1" "$tmp_port" "/var/etc/${CONFIG}/test.json" - local curlx="socks5h://127.0.0.1:$tmp_port" - fi - sleep 9s - proxy_status=$(test_url "https://www.google.com/generate_204" 3 3 "-x $curlx") - top -bn1 | grep -v "grep" | grep "/var/etc/${CONFIG}/test.json" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 - rm -rf "/var/etc/${CONFIG}/test.json" - if [ "$proxy_status" -eq 200 ]; then - #主节点正常,切换到主节点 - echolog "自动切换检测:${TYPE}主节点正常,切换到主节点!" - /usr/share/${CONFIG}/app.sh node_switch ${TYPE} ${main_node} - return 0 - fi - fi - fi - - if [ "$status" == 0 ]; then - #echolog "自动切换检测:${TYPE}节点【$(config_n_get $now_node type) $(config_n_get $now_node remarks)】正常。" - return 0 - elif [ "$status" == 1 ]; then - echolog "自动切换检测:${TYPE}节点异常,开始切换节点!" - local new_node - in_backup_nodes=$(echo $b_tcp_nodes | grep $now_node) - # 判断当前节点是否存在于备用节点列表里 - if [ -z "$in_backup_nodes" ]; then - # 如果不存在,设置第一个节点为新的节点 - new_node=$(echo $b_tcp_nodes | awk -F ' ' '{print $1}') - else - # 如果存在,设置下一个备用节点为新的节点 - #local count=$(expr $(echo $b_tcp_nodes | grep -o ' ' | wc -l) + 1) - local next_node=$(echo $b_tcp_nodes | awk -F "$now_node" '{print $2}' | awk -F " " '{print $1}') - if [ -z "$next_node" ]; then - new_node=$(echo $b_tcp_nodes | awk -F ' ' '{print $1}') - else - new_node=$next_node - fi - fi - /usr/share/${CONFIG}/app.sh node_switch ${TYPE} ${new_node} - sleep 9s - # 切换节点后等待10秒后再检测一次,如果还是不通继续切,直到可用为止 - status2=$(test_proxy) - if [ "$status2" -eq 0 ]; then - echolog "自动切换检测:${TYPE}节点切换完毕!" - return 0 - elif [ "$status2" -eq 1 ]; then - test_auto_switch ${TYPE} "${b_tcp_nodes}" - elif [ "$status2" -eq 2 ]; then - return 2 - fi - fi -} - -start() { - ENABLED=$(config_t_get global enabled 0) - [ "$ENABLED" != 1 ] && return 1 - ENABLED=$(config_t_get auto_switch enable 0) - [ "$ENABLED" != 1 ] && return 1 - delay=$(config_t_get auto_switch testing_time 1) - #sleep ${delay}m - sleep 9s - while [ "$ENABLED" -eq 1 ] - do - TCP_NODE=$(config_t_get auto_switch tcp_node nil) - [ -n "$TCP_NODE" -a "$TCP_NODE" != "nil" ] && { - test_auto_switch TCP "$TCP_NODE" - } - delay=$(config_t_get auto_switch testing_time 1) - sleep ${delay}m - done -} - -case $1 in -test_url) - test_url $2 - ;; -*) - start - ;; -esac diff --git a/package/lienol/luci-app-pppoe-server/Makefile b/package/lienol/luci-app-pppoe-server/Makefile deleted file mode 100644 index 6801916277..0000000000 --- a/package/lienol/luci-app-pppoe-server/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (C) 2018-2020 Lienol -# -# This is free software, licensed under the Apache License, Version 2.0 . -# - -include $(TOPDIR)/rules.mk - -LUCI_TITLE:=LuCI support for PPPoE Server -LUCI_DEPENDS:=+rp-pppoe-common +rp-pppoe-server -LUCI_PKGARCH:=all -PKG_VERSION:=1 -PKG_RELEASE:=8-20200326 - -define Package/luci-app-pppoe-server/preinst -#!/bin/sh -rm -rf $${IPKG_INSTROOT}/etc/config/pppoe-server >/dev/null 2>&1 -rm -rf $${IPKG_INSTROOT}/etc/init.d/pppoe-server >/dev/null 2>&1 -exit 0 -endef - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature \ No newline at end of file diff --git a/package/lienol/luci-app-pppoe-server/luasrc/controller/pppoe-server.lua b/package/lienol/luci-app-pppoe-server/luasrc/controller/pppoe-server.lua deleted file mode 100644 index a3add48a1e..0000000000 --- a/package/lienol/luci-app-pppoe-server/luasrc/controller/pppoe-server.lua +++ /dev/null @@ -1,25 +0,0 @@ --- Copyright 2018-2019 Lienol -module("luci.controller.pppoe-server", package.seeall) - -function index() - if not nixio.fs.access("/etc/config/pppoe-server") then return end - - entry({"admin", "services", "pppoe-server"}, - alias("admin", "services", "pppoe-server", "settings"), - _("PPPoE Server"), 3) - entry({"admin", "services", "pppoe-server", "settings"}, - cbi("pppoe-server/settings"), _("General Settings"), 10).leaf = true - entry({"admin", "services", "pppoe-server", "users"}, - cbi("pppoe-server/users"), _("Users Manager"), 20).leaf = true - entry({"admin", "services", "pppoe-server", "online"}, - cbi("pppoe-server/online"), _("Online Users"), 30).leaf = true - entry({"admin", "services", "pppoe-server", "status"}, call("status")).leaf = - true -end - -function status() - local e = {} - e.status = luci.sys.call("pidof %s >/dev/null" % "pppoe-server") == 0 - luci.http.prepare_content("application/json") - luci.http.write_json(e) -end diff --git a/package/lienol/luci-app-pppoe-server/luasrc/model/cbi/pppoe-server/online.lua b/package/lienol/luci-app-pppoe-server/luasrc/model/cbi/pppoe-server/online.lua deleted file mode 100644 index f5fa646ee9..0000000000 --- a/package/lienol/luci-app-pppoe-server/luasrc/model/cbi/pppoe-server/online.lua +++ /dev/null @@ -1,36 +0,0 @@ -local e = {} -local o = require "luci.dispatcher" -local a = luci.util.execi( - "/bin/busybox top -bn1 | grep 'pppd plugin rp-pppoe.so' | grep -v 'grep'") -for t in a do - local a, n, h, s, o = t:match( - "^ *(%d+) +(%d+) +.+rp_pppoe_sess 1:+([A-Fa-f0-9]+:[A-Fa-f0-9]+:[A-Fa-f0-9]+:[A-Fa-f0-9]+:[A-Fa-f0-9]+:[A-Fa-f0-9]+[A-Fa-f0-9]) +.+options +(%S.-%S)%:(%S.-%S) ") - local t = tonumber(a) - if t then - e["%02i.%s" % {t, "online"}] = { - ['PID'] = a, - ['PPID'] = n, - ['MAC'] = h, - ['GATEWAY'] = s, - ['CIP'] = o, - ['BLACKLIST'] = 0 - } - end -end -f = SimpleForm("processes", translate("PPPoE Server")) -f.reset = false -f.submit = false -f.description = translate( - "The PPPoE server is a broadband access authentication server that prevents ARP spoofing.") -t = f:section(Table, e, translate("Online Users")) -t:option(DummyValue, "GATEWAY", translate("Server IP")) -t:option(DummyValue, "CIP", translate("IP address")) -t:option(DummyValue, "MAC", translate("MAC")) - -kill = t:option(Button, "_kill", translate("Forced offline")) -kill.inputstyle = "reset" -function kill.write(e, t) - null, e.tag_error[t] = luci.sys.process.signal(e.map:get(t, "PID"), 9) - luci.http.redirect(o.build_url("admin/services/pppoe-server/online")) -end -return f diff --git a/package/lienol/luci-app-pppoe-server/luasrc/model/cbi/pppoe-server/settings.lua b/package/lienol/luci-app-pppoe-server/luasrc/model/cbi/pppoe-server/settings.lua deleted file mode 100644 index d78315f8b9..0000000000 --- a/package/lienol/luci-app-pppoe-server/luasrc/model/cbi/pppoe-server/settings.lua +++ /dev/null @@ -1,82 +0,0 @@ -local s = require "luci.sys" -local net = require"luci.model.network".init() -local ifaces = s.net:devices() -local m, s, o -m = Map("pppoe-server", translate("PPPoE Server")) -m.description = translate( - "The PPPoE server is a broadband access authentication server that prevents ARP spoofing.") -m.template = "pppoe-server/index" -s = m:section(TypedSection, "service") -s.anonymous = true -o = s:option(DummyValue, "rp_pppoe_server_status", - translate("Current Condition")) -o.template = "pppoe-server/status" -o.value = translate("Collecting data...") -o = s:option(Flag, "enabled", translate("Enable"), - translate("Enable or disable the PPPoE server")) -o.rmempty = false -o = s:option(ListValue, "client_interface", translate("Client Interface"), - translate("Listen in this interface")) -for _, iface in ipairs(ifaces) do - if (iface:match("^br") or iface:match("^eth*") or iface:match("^pppoe*") or iface:match("wlan*")) then - local nets = net:get_interface(iface) - nets = nets and nets:get_networks() or {} - for k, v in pairs(nets) do nets[k] = nets[k].sid end - nets = table.concat(nets, ",") - o:value(iface, ((#nets > 0) and "%s (%s)" % {iface, nets} or iface)) - end -end -o.rmempty = true - -o = s:option(Value, "localip", translate("Server IP"), - translate("PPPoE Server IP address.default: 10.0.1.1")) -o.datatype = "ipaddr" -o.placeholder = translate("10.0.1.1") -o.rmempty = true -o.default = "10.0.1.1" -o = s:option(Value, "remoteip", translate("Client IP"), - translate("PPPoE Client IP address.default: 10.0.1.100-254")) -o.placeholder = translate("10.0.1.100-254") -o.rmempty = true -o.default = "10.0.1.100-254" -o = s:option(Value, "count", translate("Client upper limit"), translate( - "Specify how many clients can connect to the server simultaneously.")) -o.placeholder = translate("50") -o.rmempty = true -o.default = "50" -o = s:option(Value, "dns1", translate("DNS IP address1"), translate( - "Set the PPPoE server to default DNS server, which is not required.")) -o.placeholder = translate("10.0.1.1") -o.datatype = "ipaddr" -o.default = "10.0.1.1" -o = s:option(Value, "dns2", translate("DNS IP address2"), translate( - "Set the PPPoE server to default DNS server, which is not required.")) -o.placeholder = translate("119.29.29.29") -o.datatype = "ipaddr" -o.default = "119.29.29.29" -o = s:option(Value, "mru", translate("mru"), translate( - "You may not be able to access the Internet if you don't set it up properly.default: 1492")) -o.default = "1492" -o = s:option(Value, "mtu", translate("mtu"), translate( - "You may not be able to access the Internet if you don't set it up properly.default: 1492")) -o.default = "1492" -o = s:option(Flag, "is_nat", translate("is_nat")) -o.rmempty = false -o = s:option(ListValue, "export_interface", translate("Interface"), - translate("Specify interface forwarding traffic.")) -o:value("default", translate("default")) -for _, iface in ipairs(ifaces) do - if (iface:match("^br") or iface:match("^eth*") or iface:match("^pppoe*") or iface:match("wlan*")) then - local nets = net:get_interface(iface) - nets = nets and nets:get_networks() or {} - for k, v in pairs(nets) do nets[k] = nets[k].sid end - nets = table.concat(nets, ",") - o:value(iface, ((#nets > 0) and "%s (%s)" % {iface, nets} or iface)) - end -end -o:depends("is_nat", "1") -o = s:option(Value, "log", translate("Log"), - translate("Log save path, default: /var/log/pppoe-server.log")) -o.default = "/var/log/pppoe-server.log" -o.rmempty = false -return m diff --git a/package/lienol/luci-app-pppoe-server/luasrc/model/cbi/pppoe-server/users.lua b/package/lienol/luci-app-pppoe-server/luasrc/model/cbi/pppoe-server/users.lua deleted file mode 100644 index 08c3075253..0000000000 --- a/package/lienol/luci-app-pppoe-server/luasrc/model/cbi/pppoe-server/users.lua +++ /dev/null @@ -1,28 +0,0 @@ -m = Map("pppoe-server", translate("PPPoE Server")) -m.description = translate( - "The PPPoE server is a broadband access authentication server that prevents ARP spoofing.") -s = m:section(TypedSection, "user", translate("Users Manager")) -s.addremove = true -s.anonymous = true -s.template = "cbi/tblsection" - -o = s:option(Flag, "enabled", translate("Enabled")) -o.rmempty = false - -o = s:option(Value, "username", translate("User name")) -o.placeholder = translate("User name") -o.rmempty = true - -o = s:option(Value, "password", translate("Password")) -o.rmempty = true - -o = s:option(Value, "ipaddress", translate("IP address")) -o.placeholder = translate("Automatically") -o.datatype = "ipaddr" -o.rmempty = true -function o.cfgvalue(e, t) - value = e.map:get(t, "ipaddress") - return value == "*" and "" or value -end -function o.remove(e, t) Value.write(e, t, "*") end -return m diff --git a/package/lienol/luci-app-pppoe-server/luasrc/view/pppoe-server/index.htm b/package/lienol/luci-app-pppoe-server/luasrc/view/pppoe-server/index.htm deleted file mode 100644 index 817462e571..0000000000 --- a/package/lienol/luci-app-pppoe-server/luasrc/view/pppoe-server/index.htm +++ /dev/null @@ -1,13 +0,0 @@ -<% include("cbi/map") %> - diff --git a/package/lienol/luci-app-pppoe-server/luasrc/view/pppoe-server/status.htm b/package/lienol/luci-app-pppoe-server/luasrc/view/pppoe-server/status.htm deleted file mode 100644 index 4f937f0918..0000000000 --- a/package/lienol/luci-app-pppoe-server/luasrc/view/pppoe-server/status.htm +++ /dev/null @@ -1,3 +0,0 @@ -<%+cbi/valueheader%> -<%=pcdata(self:cfgvalue(section) or self.default or "")%> -<%+cbi/valuefooter%> diff --git a/package/lienol/luci-app-pppoe-server/po/zh-cn/pppoe-server.po b/package/lienol/luci-app-pppoe-server/po/zh-cn/pppoe-server.po deleted file mode 100644 index d48c2f9e04..0000000000 --- a/package/lienol/luci-app-pppoe-server/po/zh-cn/pppoe-server.po +++ /dev/null @@ -1,101 +0,0 @@ -msgid "PPPoE Server" -msgstr "PPPoE 服务器" - -msgid "The PPPoE server is a broadband access authentication server that prevents ARP spoofing." -msgstr "PPPoE服务器是一个宽带接入认证服务器,可以防止ARP欺骗." - -msgid "PPPoE Server status" -msgstr "PPPoE 服务器运行状态" - -msgid "Current Condition" -msgstr "当前状态" - -msgid "General settings" -msgstr "基本设置" - -msgid "Enable or disable the PPPoE server" -msgstr "启用或禁用PPPoE服务器" - -msgid "Client Interface" -msgstr "客户端接口" - -msgid "Listen in this interface" -msgstr "监听客户端接口" - -msgid "Server IP" -msgstr "服务器 IP 地址" - -msgid "PPPoE Server IP address.default: 10.0.1.1" -msgstr "PPPoE 服务器远程地址。默认:10.0.1.1" - -msgid "Client IP" -msgstr "客户端 IP 地址" - -msgid "PPPoE Client IP address.default: 10.0.1.100-254" -msgstr "分配给客户端的 IP 地址范围。默认:10.0.1.100-254" - -msgid "DNS IP address1" -msgstr "DNS 1" - -msgid "DNS IP address2" -msgstr "DNS 2" - -msgid "Set the PPPoE server to default DNS server, which is not required." -msgstr "设置 PPPoE 服务器第一个 DNS 服务器,该设置非必须。" - -msgid "Set the PPPoE server to default DNS server, which is not required." -msgstr "设置 PPPoE 服务器第二个 DNS 服务器,该设置非必须。" - -msgid "Client upper limit" -msgstr "客户端上限数" - -msgid "Specify how many clients can connect to the server simultaneously." -msgstr "指定有多少客户端可以同时连接到服务器" - -msgid "You may not be able to access the Internet if you don't set it up properly.default: 1492" -msgstr "如果设置不当,你可能无法访问互联网。默认:1492" - -msgid "is_nat" -msgstr "NAT转发" - -msgid "Interface" -msgstr "接口" - -msgid "Specify interface forwarding traffic." -msgstr "指定接口转发流量。" - -msgid "Log" -msgstr "日志" - -msgid "Log save path, default: /var/log/pppoe-server.log" -msgstr "日志保存路径,默认:/var/log/pppoe-server.log" - -msgid "Users Manager" -msgstr "用户管理" - -msgid "Enabled" -msgstr "启用" - -msgid "User name" -msgstr "用户名" - -msgid "Password" -msgstr "密码" - -msgid "IP address" -msgstr "IP 地址" - -msgid "Automatically" -msgstr "自动分配" - -msgid "Online Users"" -msgstr "在线用户" - -msgid "Forced offline" -msgstr "强制下线" - -msgid "NOT RUNNING" -msgstr "未运行" - -msgid "RUNNING" -msgstr "运行中" \ No newline at end of file diff --git a/package/lienol/luci-app-pppoe-server/root/etc/config/pppoe-server b/package/lienol/luci-app-pppoe-server/root/etc/config/pppoe-server deleted file mode 100644 index 971a56199b..0000000000 --- a/package/lienol/luci-app-pppoe-server/root/etc/config/pppoe-server +++ /dev/null @@ -1,21 +0,0 @@ - -config service - option localip '10.0.1.1' - option log '/var/log/pppoe-server.log' - option count '50' - option mru '1492' - option mtu '1492' - option remoteip '10.0.1.100-254' - option is_nat '1' - option export_interface 'default' - option client_interface 'eth0' - option enabled '0' - option dns1 '10.0.1.1' - option dns2 '192.168.0.2' - -config user - option enabled '1' - option ipaddress '*' - option username 'guest' - option password '123456' - diff --git a/package/lienol/luci-app-pppoe-server/root/etc/init.d/pppoe-server b/package/lienol/luci-app-pppoe-server/root/etc/init.d/pppoe-server deleted file mode 100755 index fb352afb5a..0000000000 --- a/package/lienol/luci-app-pppoe-server/root/etc/init.d/pppoe-server +++ /dev/null @@ -1,101 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2018-2020 Lienol - -START=99 - -CONFIG="pppoe-server" -CONFIG_FILE=/etc/ppp/$CONFIG-options -CHAP_SECRETS=/var/etc/chap-secrets -TEMP=/tmp/$CONFIG.tmp - -config_t_get() { - local index=0 - [ -n "$4" ] && index=$4 - local ret=$(uci -q get $CONFIG.@$1[$index].$2 2>/dev/null) - echo ${ret:=$3} -} - -setup_users() { - config_get enabled $1 enabled - [ "$enabled" -eq 0 ] && return 0 - config_get username $1 username - config_get password $1 password - config_get ipaddress $1 ipaddress - [ -n "$username" -a -n "$password" ] && echo "$username $CONFIG $password $ipaddress" >> $CHAP_SECRETS -} - -del_user() -{ - cat $CHAP_SECRETS | grep -v $CONFIG > $TEMP - cat $TEMP > $CHAP_SECRETS - rm $TEMP -} - -start() { - config_load pppoe-server - enabled=$(config_t_get service enabled) - [ "$enabled" -eq 0 ] && exit 0 - cat <<-EOF >$CONFIG_FILE -# PPP options for the PPPoE server -# LIC: GPL -name $CONFIG -login -require-mschap-v2 -refuse-chap -require-pap -lcp-echo-interval 10 -lcp-echo-failure 2 -mru $(config_t_get service mru 1492) -mtu $(config_t_get service mtu 1492) -ms-dns $(config_t_get service dns1 223.5.5.5) -ms-dns $(config_t_get service dns2 119.29.29.29) -logfile $(config_t_get service log /var/log/pppoe-server.log) -EOF - del_user - config_foreach setup_users user - ln -sfn $CHAP_SECRETS /etc/ppp/chap-secrets - local is_nat=$(config_t_get service is_nat) - local localip=$(config_t_get service localip) - if [ "$is_nat" -eq 1 ];then - local export_interface=$(config_t_get service export_interface) - if [ "$export_interface" != "default" ];then - iptables -t nat -A POSTROUTING -s ${localip%.*}.0/24 -o ${export_interface} -m comment --comment "PPPoE Server" -j MASQUERADE - else - iptables -t nat -A POSTROUTING -s ${localip%.*}.0/24 -m comment --comment "PPPoE Server" -j MASQUERADE - fi - iptables -A forwarding_rule -s ${localip%.*}.0/24 -m comment --comment "PPPoE Server" -j ACCEPT - fi - /usr/sbin/pppoe-server -k -I $(config_t_get service client_interface) -L $(config_t_get service localip) -R $(config_t_get service remoteip) -N $(config_t_get service count) -} - -stop() { - del_user - nums=$(iptables -t nat -n -L POSTROUTING 2>/dev/null | grep -c "PPPoE Server") - if [ -n "$nums" ]; then - until [ "$nums" = 0 ] - do - rules=$(iptables -t nat -n -L POSTROUTING --line-num 2>/dev/null | grep "PPPoE Server" | awk '{print $1}') - for rule in $rules - do - iptables -t nat -D POSTROUTING $rule 2> /dev/null - break - done - nums=$(expr $nums - 1) - done - fi - nums2=$(iptables -L forwarding_rule 2>/dev/null | grep -c "PPPoE Server") - if [ -n "$nums2" ]; then - until [ "$nums2" = 0 ] - do - rules=$(iptables -L forwarding_rule --line-num 2>/dev/null | grep "PPPoE Server" | awk '{print $1}') - for rule in $rules - do - iptables -D forwarding_rule $rule 2> /dev/null - break - done - nums2=$(expr $nums2 - 1) - done - fi - ps | grep "pppd plugin rp-pppoe.so" | grep -v "grep" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 & - killall -q -9 pppoe-server -} diff --git a/package/lienol/luci-app-pppoe-server/root/etc/uci-defaults/luci-app-pppoe-server b/package/lienol/luci-app-pppoe-server/root/etc/uci-defaults/luci-app-pppoe-server deleted file mode 100755 index 96c95887f3..0000000000 --- a/package/lienol/luci-app-pppoe-server/root/etc/uci-defaults/luci-app-pppoe-server +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@pppoe-server[-1] - add ucitrack pppoe-server - set ucitrack.@pppoe-server[-1].init=pppoe-server - commit ucitrack -EOF - -rm -f /tmp/luci-indexcache -exit 0 diff --git a/package/lienol/luci-app-socat/Makefile b/package/lienol/luci-app-socat/Makefile deleted file mode 100644 index 7fbcf2fd84..0000000000 --- a/package/lienol/luci-app-socat/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (C) 2020 Lienol -# -# This is free software, licensed under the GNU General Public License v3. -# - -include $(TOPDIR)/rules.mk - -LUCI_TITLE:=LuCI support for Socat -LUCI_DEPENDS:=+socat -LUCI_PKGARCH:=all -PKG_RELEASE:=3 -PKG_DATE:=20200824 - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature diff --git a/package/lienol/luci-app-socat/luasrc/controller/socat.lua b/package/lienol/luci-app-socat/luasrc/controller/socat.lua deleted file mode 100644 index 89b84c323b..0000000000 --- a/package/lienol/luci-app-socat/luasrc/controller/socat.lua +++ /dev/null @@ -1,19 +0,0 @@ --- Copyright 2020 Lienol -module("luci.controller.socat", package.seeall) -local http = require "luci.http" - -function index() - if not nixio.fs.access("/etc/config/socat") then return end - - entry({"admin", "network", "socat"}, cbi("socat/index"), _("Socat"), 100) - entry({"admin", "network", "socat", "config"}, cbi("socat/config")).leaf = true - entry({"admin", "network", "socat", "status"}, call("status")).leaf = true -end - -function status() - local e = {} - e.index = luci.http.formvalue("index") - e.status = luci.sys.call(string.format("ps -w | grep -v 'grep' | grep '/var/etc/socat/%s' >/dev/null", luci.http.formvalue("id"))) == 0 - http.prepare_content("application/json") - http.write_json(e) -end diff --git a/package/lienol/luci-app-socat/luasrc/model/cbi/socat/config.lua b/package/lienol/luci-app-socat/luasrc/model/cbi/socat/config.lua deleted file mode 100644 index afbc0849b2..0000000000 --- a/package/lienol/luci-app-socat/luasrc/model/cbi/socat/config.lua +++ /dev/null @@ -1,82 +0,0 @@ -local d = require "luci.dispatcher" - -m = Map("socat", translate("Socat Config")) -m.redirect = d.build_url("admin", "network", "socat") - -s = m:section(NamedSection, arg[1], "config", "") -s.addremove = false -s.dynamic = false - -o = s:option(Flag, "enable", translate("Enable")) -o.default = "1" -o.rmempty = false - -o = s:option(Value, "remarks", translate("Remarks")) -o.default = translate("Remarks") -o.rmempty = false - -o = s:option(ListValue, "protocol", translate("Protocol")) -o:value("port_forwards", translate("Port Forwards")) - -o = s:option(ListValue, "family", translate("Restrict to address family")) -o:value("", translate("IPv4 and IPv6")) -o:value("4", translate("IPv4 only")) -o:value("6", translate("IPv6 only")) -o:depends("protocol", "port_forwards") - -o = s:option(ListValue, "proto", translate("Protocol")) -o:value("tcp", "TCP") -o:value("udp", "UDP") -o:depends("protocol", "port_forwards") - -o = s:option(Value, "listen_port", translate("Listen port")) -o.datatype = "portrange" -o.rmempty = false -o:depends("protocol", "port_forwards") - -o = s:option(Flag, "reuseaddr", "reuseaddr", translate("Bind to a port local")) -o.default = "1" -o.rmempty = false - -o = s:option(ListValue, "dest_proto", translate("Destination Protocol")) -o:value("tcp4", "IPv4-TCP") -o:value("udp4", "IPv4-UDP") -o:value("tcp6", "IPv6-TCP") -o:value("udp6", "IPv6-UDP") -o:depends("protocol", "port_forwards") - -dest_ipv4 = s:option(Value, "dest_ipv4", translate("Destination address")) -luci.sys.net.ipv4_hints(function(ip, name) - dest_ipv4:value(ip, "%s (%s)" %{ ip, name }) -end) -function dest_ipv4.cfgvalue(self, section) - return m:get(section, "dest_ip") -end -function dest_ipv4.write(self, section, value) - m:set(section, "dest_ip", value) -end -dest_ipv4:depends("dest_proto", "tcp4") -dest_ipv4:depends("dest_proto", "udp4") - -dest_ipv6 = s:option(Value, "dest_ipv6", translate("Destination address")) -luci.sys.net.ipv6_hints(function(ip, name) - dest_ipv6:value(ip, "%s (%s)" %{ ip, name }) -end) -function dest_ipv6.cfgvalue(self, section) - return m:get(section, "dest_ip") -end -function dest_ipv6.write(self, section, value) - m:set(section, "dest_ip", value) -end -dest_ipv6:depends("dest_proto", "tcp6") -dest_ipv6:depends("dest_proto", "udp6") - -o = s:option(Value, "dest_port", translate("Destination port")) -o.datatype = "portrange" -o.rmempty = false - -o = s:option(Flag, "firewall_accept", translate("Open firewall port")) -o.default = "1" -o.rmempty = false - -return m diff --git a/package/lienol/luci-app-socat/luasrc/model/cbi/socat/index.lua b/package/lienol/luci-app-socat/luasrc/model/cbi/socat/index.lua deleted file mode 100644 index 0bc520e45c..0000000000 --- a/package/lienol/luci-app-socat/luasrc/model/cbi/socat/index.lua +++ /dev/null @@ -1,76 +0,0 @@ -local d = require "luci.dispatcher" -local e = luci.model.uci.cursor() - -m = Map("socat", translate("Socat"), translate("Socat is a versatile networking tool named after 'Socket CAT', which can be regarded as an N-fold enhanced version of NetCat")) - -s = m:section(NamedSection, "global", "global") -s.anonymous = true -s.addremove = false - -o = s:option(Flag, "enable", translate("Enable")) -o.rmempty = false - -s = m:section(TypedSection, "config", translate("Port Forwards")) -s.anonymous = true -s.addremove = true -s.template = "cbi/tblsection" -s.extedit = d.build_url("admin", "network", "socat", "config", "%s") -function s.filter(e, t) - if m:get(t, "protocol") == "port_forwards" then - return true - end -end -function s.create(e, t) - local uuid = string.gsub(luci.sys.exec("echo -n $(cat /proc/sys/kernel/random/uuid)"), "-", "") - t = uuid - TypedSection.create(e, t) - luci.http.redirect(e.extedit:format(t)) -end -function s.remove(e, t) - e.map.proceed = true - e.map:del(t) - luci.http.redirect(d.build_url("admin", "network", "socat")) -end - -o = s:option(Flag, "enable", translate("Enable")) -o.width = "5%" -o.rmempty = false - -o = s:option(DummyValue, "status", translate("Status")) -o.template = "socat/status" -o.value = translate("Collecting data...") - -o = s:option(DummyValue, "remarks", translate("Remarks")) - -o = s:option(DummyValue, "family", translate("Listen Protocol")) -o.cfgvalue = function(t, n) - local listen = Value.cfgvalue(t, n) or "" - local protocol = (m:get(n, "proto") or ""):upper() - if listen == "" then - return protocol - else - return "IPv" .. listen .. "-" .. protocol - end -end - -o = s:option(DummyValue, "listen_port", translate("Listen port")) - -o = s:option(DummyValue, "dest_proto", translate("Destination Protocol")) -o.cfgvalue = function(t, n) - local listen = Value.cfgvalue(t, n) - local protocol = listen:sub(0, #listen - 1):upper() - local ip_type = "IPv" .. listen:sub(#listen) - return ip_type .. "-" .. protocol -end - -o = s:option(DummyValue, "dest_ip", translate("Destination address")) - -o = s:option(DummyValue, "dest_port", translate("Destination port")) - -o = s:option(Flag, "firewall_accept", translate("Open firewall port")) -o.default = "1" -o.rmempty = false - -m:append(Template("socat/list_status")) -return m - diff --git a/package/lienol/luci-app-socat/luasrc/view/socat/list_status.htm b/package/lienol/luci-app-socat/luasrc/view/socat/list_status.htm deleted file mode 100644 index 8ffac828e0..0000000000 --- a/package/lienol/luci-app-socat/luasrc/view/socat/list_status.htm +++ /dev/null @@ -1,19 +0,0 @@ - \ No newline at end of file diff --git a/package/lienol/luci-app-socat/luasrc/view/socat/status.htm b/package/lienol/luci-app-socat/luasrc/view/socat/status.htm deleted file mode 100644 index 04193e8905..0000000000 --- a/package/lienol/luci-app-socat/luasrc/view/socat/status.htm +++ /dev/null @@ -1,3 +0,0 @@ -<%+cbi/valueheader%> --- -<%+cbi/valuefooter%> \ No newline at end of file diff --git a/package/lienol/luci-app-socat/po/zh-cn/socat.po b/package/lienol/luci-app-socat/po/zh-cn/socat.po deleted file mode 100644 index 9068b611fc..0000000000 --- a/package/lienol/luci-app-socat/po/zh-cn/socat.po +++ /dev/null @@ -1,50 +0,0 @@ -msgid "Socat" -msgstr "Socat" - -msgid "Socat is a versatile networking tool named after 'Socket CAT', which can be regarded as an N-fold enhanced version of NetCat" -msgstr "Socat 是 Linux 下的一个多功能的网络工具,名字来由是「Socket CAT」。其功能与有瑞士军刀之称的 Netcat 类似,可以看做是 Netcat 的加强版。" - -msgid "Socat Config" -msgstr "Socat 配置" - -msgid "Status" -msgstr "状态" - -msgid "Enabled" -msgstr "启用" - -msgid "Remarks" -msgstr "备注" - -msgid "Protocol" -msgstr "协议" - -msgid "IPv6 Only" -msgstr "仅IPv6" - -msgid "When checked, only IPv6 ports are listen for, otherwise IPv4 will also be listened for." -msgstr "当勾选时,仅监听IPv6,否则将会同时监听IPv4。" - -msgid "Port Forwards" -msgstr "端口转发" - -msgid "Listen Protocol" -msgstr "监听协议" - -msgid "Listen port" -msgstr "监听端口" - -msgid "Bind to a port local" -msgstr "绑定到本地端口" - -msgid "Destination Protocol" -msgstr "目标协议" - -msgid "Destination address" -msgstr "目标地址" - -msgid "Destination port" -msgstr "目标端口" - -msgid "Open firewall port" -msgstr "打开防火墙端口" diff --git a/package/lienol/luci-app-socat/root/etc/config/socat b/package/lienol/luci-app-socat/root/etc/config/socat deleted file mode 100644 index 04e4f87201..0000000000 --- a/package/lienol/luci-app-socat/root/etc/config/socat +++ /dev/null @@ -1,3 +0,0 @@ - -config global 'global' - option enable '0' diff --git a/package/lienol/luci-app-socat/root/etc/init.d/socat b/package/lienol/luci-app-socat/root/etc/init.d/socat deleted file mode 100755 index 579db57f54..0000000000 --- a/package/lienol/luci-app-socat/root/etc/init.d/socat +++ /dev/null @@ -1,119 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2020 Lienol - -START=99 - -CONFIG=socat -CONFIG_PATH=/var/etc/$CONFIG - -add_rule() { - iptables -N SOCAT - iptables -I INPUT -j SOCAT - ip6tables -N SOCAT - ip6tables -I INPUT -j SOCAT -} - -del_rule() { - iptables -D INPUT -j SOCAT 2>/dev/null - iptables -F SOCAT 2>/dev/null - iptables -X SOCAT 2>/dev/null - ip6tables -D INPUT -j SOCAT 2>/dev/null - ip6tables -F SOCAT 2>/dev/null - ip6tables -X SOCAT 2>/dev/null -} - -gen_include() { - echo '#!/bin/sh' > /var/etc/$CONFIG.include - extract_rules() { - local _ipt="iptables" - [ "$1" == "6" ] && _ipt="ip6tables" - - echo "*$2" - ${_ipt}-save -t $2 | grep "SOCAT" | \ - sed -e "s/^-A \(INPUT\)/-I \1 1/" - echo 'COMMIT' - } - cat <<-EOF >> /var/etc/$CONFIG.include - iptables-save -c | grep -v "SOCAT" | iptables-restore -c - iptables-restore -n <<-EOT - $(extract_rules 4 filter) - EOT - ip6tables-save -c | grep -v "SOCAT" | ip6tables-restore -c - ip6tables-restore -n <<-EOT - $(extract_rules 6 filter) - EOT - EOF - return 0 -} - -run_service() { - config_get enable $1 enable - [ "$enable" = "0" ] && return 0 - config_get remarks $1 remarks - config_get protocol $1 protocol - config_get family $1 family - config_get proto $1 proto - config_get listen_port $1 listen_port - config_get reuseaddr $1 reuseaddr - config_get dest_proto $1 dest_proto - config_get dest_ip $1 dest_ip - config_get dest_port $1 dest_port - config_get firewall_accept $1 firewall_accept - ln -s /usr/bin/socat ${CONFIG_PATH}/$1 - - if [ "$reuseaddr" == "1" ]; then - reuseaddr=",reuseaddr" - else - reuseaddr="" - fi - - if [ "$family" == "6" ]; then - ipv6only_params=",ipv6-v6only" - else - ipv6only_params="" - fi - - # 端口转发 - if [ "$protocol" == "port_forwards" ]; then - listen=${proto}${family} - [ "$family" == "" ] && listen=${proto}6 - ${CONFIG_PATH}/$1 ${listen}-listen:${listen_port}${ipv6only_params}${reuseaddr},fork ${dest_proto}:${dest_ip}:${dest_port} >/dev/null 2>&1 & - fi - - [ "$firewall_accept" == "1" ] && { - if [ -z "$family" ] || [ "$family" == "6" ]; then - ip6tables -A SOCAT -p $proto --dport $listen_port -m comment --comment "$remarks" -j ACCEPT - fi - if [ -z "$family" ] || [ "$family" == "4" ]; then - iptables -A SOCAT -p $proto --dport $listen_port -m comment --comment "$remarks" -j ACCEPT - fi - } -} - -stop_service() { - ps -w | grep "$CONFIG_PATH/" | grep -v "grep" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 & - del_rule - rm -rf $CONFIG_PATH /var/etc/$CONFIG.include -} - -start() { - enable=$(uci -q get $CONFIG.@global[0].enable) - if [ "$enable" = "0" ];then - stop_service - else - mkdir -p $CONFIG_PATH - add_rule - config_load $CONFIG - config_foreach run_service "config" - gen_include - fi -} - -stop() { - stop_service -} - -restart() { - stop - start -} \ No newline at end of file diff --git a/package/lienol/luci-app-socat/root/etc/uci-defaults/luci-app-socat b/package/lienol/luci-app-socat/root/etc/uci-defaults/luci-app-socat deleted file mode 100755 index 431f8756c3..0000000000 --- a/package/lienol/luci-app-socat/root/etc/uci-defaults/luci-app-socat +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete firewall.socat - set firewall.socat=include - set firewall.socat.type=script - set firewall.socat.path=/var/etc/socat.include - set firewall.socat.reload=1 -EOF - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@socat[-1] - add ucitrack socat - set ucitrack.@socat[-1].init=socat - commit ucitrack -EOF - -rm -rf /tmp/luci-*cache -exit 0 diff --git a/package/lienol/luci-app-ssr-libev-server/Makefile b/package/lienol/luci-app-ssr-libev-server/Makefile deleted file mode 100644 index 24ce3bf57f..0000000000 --- a/package/lienol/luci-app-ssr-libev-server/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (C) 2018-2020 Lienol -# -# This is free software, licensed under the Apache License, Version 2.0 . -# - -include $(TOPDIR)/rules.mk - -LUCI_TITLE:=LuCI support for SSR Libev Server -LUCI_DEPENDS:=+libsodium +shadowsocksr-libev-ssr-server -LUCI_PKGARCH:=all -PKG_VERSION:=1 -PKG_RELEASE:=8-20200326 - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature diff --git a/package/lienol/luci-app-ssr-libev-server/luasrc/controller/ssr_libev_server.lua b/package/lienol/luci-app-ssr-libev-server/luasrc/controller/ssr_libev_server.lua deleted file mode 100644 index 68829057b4..0000000000 --- a/package/lienol/luci-app-ssr-libev-server/luasrc/controller/ssr_libev_server.lua +++ /dev/null @@ -1,29 +0,0 @@ --- Copyright 2018-2019 Lienol -module("luci.controller.ssr_libev_server", package.seeall) -local http = require "luci.http" - -function index() - if not nixio.fs.access("/etc/config/ssr_libev_server") then return end - entry({"admin", "vpn"}, firstchild(), "VPN", 45).dependent = false - entry({"admin", "vpn", "ssr_libev_server"}, cbi("ssr_libev_server/index"), - _("SSR Libev Server"), 2).dependent = true - entry({"admin", "vpn", "ssr_libev_server", "config"}, - cbi("ssr_libev_server/config")).leaf = true - - entry({"admin", "vpn", "ssr_libev_server", "users_status"}, - call("ssr_libev_users_status")).leaf = true -end - -local function http_write_json(content) - http.prepare_content("application/json") - http.write_json(content or {code = 1}) -end - -function ssr_libev_users_status() - local e = {} - e.index = luci.http.formvalue("index") - e.status = luci.sys.call( - "ps -w| grep -v grep | grep '/var/etc/ssr_libev_server/" .. - luci.http.formvalue("id") .. "' >/dev/null") == 0 - http_write_json(e) -end diff --git a/package/lienol/luci-app-ssr-libev-server/luasrc/model/cbi/ssr_libev_server/config.lua b/package/lienol/luci-app-ssr-libev-server/luasrc/model/cbi/ssr_libev_server/config.lua deleted file mode 100644 index d8252f7735..0000000000 --- a/package/lienol/luci-app-ssr-libev-server/luasrc/model/cbi/ssr_libev_server/config.lua +++ /dev/null @@ -1,65 +0,0 @@ -local i = "ssr_libev_server" -local d = require "luci.dispatcher" -local a, t, e - -local encrypt_method = { - "table", "rc4", "rc4-md5", "aes-128-cfb", "aes-192-cfb", "aes-256-cfb", - "aes-128-ctr", "aes-192-ctr", "aes-256-ctr", "bf-cfb", "camellia-128-cfb", - "camellia-192-cfb", "camellia-256-cfb", "cast5-cfb", "des-cfb", "idea-cfb", - "rc2-cfb", "seed-cfb", "salsa20", "chacha20", "chacha20-ietf" -} - -local protocol = {"origin"} -local obfs = {"plain", "http_simple", "http_post"} - -a = Map(i, "ShadowsocksR Libev " .. translate("Server Config")) -a.redirect = d.build_url("admin", "vpn", "ssr_libev_server") - -t = a:section(NamedSection, arg[1], "user", "") -t.addremove = false -t.dynamic = false - -e = t:option(Flag, "enable", translate("Enable")) -e.default = "1" -e.rmempty = false - -e = t:option(Value, "remarks", translate("Remarks")) -e.default = translate("Remarks") -e.rmempty = false - -e = t:option(Value, "port", translate("Port")) -e.datatype = "port" -e.rmempty = false - -e = t:option(Value, "password", translate("Password")) -e.password = true -e.rmempty = false - -e = t:option(ListValue, "method", translate("Encrypt Method")) -for a, t in ipairs(encrypt_method) do e:value(t) end - -e = t:option(ListValue, "protocol", translate("Protocol")) -for a, t in ipairs(protocol) do e:value(t) end - -e = t:option(Value, "protocol_param", translate("Protocol Param")) - -e = t:option(ListValue, "obfs", translate("Obfs")) -for a, t in ipairs(obfs) do e:value(t) end - -e = t:option(Value, "obfs_param", translate("Obfs Param")) - -e = t:option(Value, "timeout", translate("Connection Timeout")) -e.datatype = "uinteger" -e.default = 300 -e.rmempty = false - -e = t:option(ListValue, "fast_open", translate("Fast Open")) -e:value("false") -e:value("true") -e.rmempty = false - -e = t:option(Flag, "udp_forward", translate("UDP Forward")) -e.default = "1" -e.rmempty = false - -return a diff --git a/package/lienol/luci-app-ssr-libev-server/luasrc/model/cbi/ssr_libev_server/index.lua b/package/lienol/luci-app-ssr-libev-server/luasrc/model/cbi/ssr_libev_server/index.lua deleted file mode 100644 index c97ba11238..0000000000 --- a/package/lienol/luci-app-ssr-libev-server/luasrc/model/cbi/ssr_libev_server/index.lua +++ /dev/null @@ -1,61 +0,0 @@ -local o = require "luci.dispatcher" -local fs = require "nixio.fs" -local sys = require "luci.sys" -local cursor = luci.model.uci.cursor() -local appname = "ssr_libev_server" -local a, t, e - -a = Map(appname, translate("ShadowsocksR Libev Server")) - -t = a:section(TypedSection, "global", translate("Global Settings")) -t.anonymous = true -t.addremove = false - -e = t:option(Flag, "enable", translate("Enable")) -e.rmempty = false - -t = a:section(TypedSection, "user", translate("Users Manager")) -t.anonymous = true -t.addremove = true -t.template = "cbi/tblsection" -t.extedit = o.build_url("admin", "vpn", appname, "config", "%s") - -function t.create(e, t) - local e = TypedSection.create(e, t) - luci.http.redirect(o.build_url("admin", "vpn", appname, "config", e)) -end - -function t.remove(t, a) - t.map.proceed = true - t.map:del(a) - luci.http.redirect(o.build_url("admin", "vpn", appname)) -end - -e = t:option(Flag, "enable", translate("Enable")) -e.width = "5%" -e.rmempty = false - -e = t:option(DummyValue, "status", translate("Status")) -e.template = "ssr_libev_server/users_status" - -e = t:option(DummyValue, "remarks", translate("Remarks")) -e.width = "15%" - -e = t:option(DummyValue, "port", translate("Port")) -e.width = "10%" - -e = t:option(DummyValue, "password", translate("Password")) -e.width = "15%" - -e = t:option(DummyValue, "method", translate("Encrypt Method")) -e.width = "15%" - -e = t:option(DummyValue, "protocol", translate("Protocol")) -e.width = "15%" - -e = t:option(DummyValue, "obfs", translate("Obfs")) -e.width = "15%" - -a:append(Template("ssr_libev_server/users_list_status")) - -return a diff --git a/package/lienol/luci-app-ssr-libev-server/luasrc/view/ssr_libev_server/users_list_status.htm b/package/lienol/luci-app-ssr-libev-server/luasrc/view/ssr_libev_server/users_list_status.htm deleted file mode 100644 index 7dcc12b9c0..0000000000 --- a/package/lienol/luci-app-ssr-libev-server/luasrc/view/ssr_libev_server/users_list_status.htm +++ /dev/null @@ -1,23 +0,0 @@ -<% -local dsp = require "luci.dispatcher" --%> - - \ No newline at end of file diff --git a/package/lienol/luci-app-ssr-libev-server/luasrc/view/ssr_libev_server/users_status.htm b/package/lienol/luci-app-ssr-libev-server/luasrc/view/ssr_libev_server/users_status.htm deleted file mode 100644 index 01c9d9d708..0000000000 --- a/package/lienol/luci-app-ssr-libev-server/luasrc/view/ssr_libev_server/users_status.htm +++ /dev/null @@ -1,3 +0,0 @@ -<%+cbi/valueheader%> --- -<%+cbi/valuefooter%> \ No newline at end of file diff --git a/package/lienol/luci-app-ssr-libev-server/po/zh-cn/ssr_libev_server.po b/package/lienol/luci-app-ssr-libev-server/po/zh-cn/ssr_libev_server.po deleted file mode 100644 index ab05bcbab2..0000000000 --- a/package/lienol/luci-app-ssr-libev-server/po/zh-cn/ssr_libev_server.po +++ /dev/null @@ -1,65 +0,0 @@ -msgid "ShadowsocksR Libev Server" -msgstr "ShadowsocksR Libev 服务器" - -msgid "SSR Libev Server" -msgstr "SSR Libev服务器" - -msgid "Global Settings" -msgstr "全局设置" - -msgid "Server Config" -msgstr "服务器配置" - -msgid "Users Manager" -msgstr "用户管理" - -msgid "Remarks" -msgstr "备注" - -msgid "Port" -msgstr "端口" - -msgid "Password" -msgstr "密码" - -msgid "Encrypt Method" -msgstr "加密" - -msgid "Protocol" -msgstr "协议" - -msgid "Protocol Param" -msgstr "协议参数" - -msgid "Obfs" -msgstr "混淆" - -msgid "Obfs Param" -msgstr "混淆参数" - -msgid "Connection Timeout" -msgstr "连接超时时间" - -msgid "redirect" -msgstr "重定向" - -msgid "Fast Open" -msgstr "快速打开" - -msgid "UDP Forward" -msgstr "UDP转发" - -msgid "Enabled" -msgstr "启用" - -msgid "Status" -msgstr "状态" - -msgid "Current Condition" -msgstr "当前状态" - -msgid "NOT RUNNING" -msgstr "未运行" - -msgid "RUNNING" -msgstr "运行中" \ No newline at end of file diff --git a/package/lienol/luci-app-ssr-libev-server/root/etc/config/ssr_libev_server b/package/lienol/luci-app-ssr-libev-server/root/etc/config/ssr_libev_server deleted file mode 100644 index 4c30f5eabe..0000000000 --- a/package/lienol/luci-app-ssr-libev-server/root/etc/config/ssr_libev_server +++ /dev/null @@ -1,16 +0,0 @@ - -config global - option enable '0' - -config user - option enable '1' - option remarks '备注2' - option port '10002' - option password '123456' - option method 'table' - option protocol 'origin' - option obfs 'plain' - option timeout '300' - option fast_open 'false' - option udp_forward '1' - diff --git a/package/lienol/luci-app-ssr-libev-server/root/etc/init.d/ssr_libev_server b/package/lienol/luci-app-ssr-libev-server/root/etc/init.d/ssr_libev_server deleted file mode 100755 index 6d26464fd1..0000000000 --- a/package/lienol/luci-app-ssr-libev-server/root/etc/init.d/ssr_libev_server +++ /dev/null @@ -1,73 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2018-2020 Lienol - -START=99 - -CONFIG=ssr_libev_server -CONFIG_PATH=/var/etc/$CONFIG - -gen_ssr_libev_config_file() { - config_get enable $1 enable - [ "$enable" = "0" ] && return 0 - config_get remarks $1 remarks - config_get port $1 port - config_get password $1 password - config_get method $1 method - config_get protocol $1 protocol - config_get protocol_param $1 protocol_param - config_get obfs $1 obfs - config_get obfs_param $1 obfs_param - config_get timeout $1 timeout - config_get fast_open $1 fast_open - config_get udp_forward $1 udp_forward - udp_param="" - [ "$udp_forward" = "1" ] && udp_param="-u" - - cat <<-EOF >$CONFIG_PATH/$1.json - { - "server": ["[::0]", "0.0.0.0"], - "server_port": $port, - "password": "$password", - "timeout": $timeout, - "method": "$method", - "protocol": "$protocol", - "protocol_param": "$protocol_param", - "obfs": "$obfs", - "obfs_param": "$obfs_param", - "fast_open": $fast_open - } - EOF - - /usr/bin/ssr-server -c $CONFIG_PATH/$1.json $udp_param >/dev/null 2>&1 & -} - -start_ssr_libev_server() { - config_foreach gen_ssr_libev_config_file "user" - fw3 reload >/dev/null 2>&1 & -} - -stop_ssr_libev_server() { - fw3 reload >/dev/null 2>&1 - ps -w | grep "$CONFIG_PATH/" | grep -v "grep" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 & -} - -start() { - config_load $CONFIG - enable=$(uci get $CONFIG.@global[0].enable) - if [ "$enable" = "0" ];then - stop_ssr_libev_server - else - mkdir -p $CONFIG_PATH - start_ssr_libev_server - fi -} - -stop() { - stop_ssr_libev_server - rm -rf $CONFIG_PATH -} - -restart() { - stop - start -} \ No newline at end of file diff --git a/package/lienol/luci-app-ssr-libev-server/root/etc/uci-defaults/luci-app-ssr-libev-server b/package/lienol/luci-app-ssr-libev-server/root/etc/uci-defaults/luci-app-ssr-libev-server deleted file mode 100755 index 20671c4194..0000000000 --- a/package/lienol/luci-app-ssr-libev-server/root/etc/uci-defaults/luci-app-ssr-libev-server +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete firewall.ssr_libev_server - set firewall.ssr_libev_server=include - set firewall.ssr_libev_server.type=script - set firewall.ssr_libev_server.path=/usr/share/ssr_libev_server/firewall.include - set firewall.ssr_libev_server.reload=1 -EOF - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@ssr_libev_server[-1] - add ucitrack ssr_libev_server - set ucitrack.@ssr_libev_server[-1].init=ssr_libev_server - commit ucitrack -EOF - -chmod a+x /usr/share/ssr_libev_server/* >/dev/null 2>&1 - -rm -f /tmp/luci-indexcache -exit 0 diff --git a/package/lienol/luci-app-ssr-libev-server/root/usr/share/ssr_libev_server/firewall.include b/package/lienol/luci-app-ssr-libev-server/root/usr/share/ssr_libev_server/firewall.include deleted file mode 100755 index b2cfbc158d..0000000000 --- a/package/lienol/luci-app-ssr-libev-server/root/usr/share/ssr_libev_server/firewall.include +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/sh - -count=$(iptables -n -L INPUT 2>/dev/null | grep -c "SSR_LIBEV-SERVER") -if [ -n "$count" ]; then - until [ "$count" = 0 ] - do - rules=$(iptables -n -L INPUT --line-num 2>/dev/null | grep "SSR_LIBEV-SERVER" | awk '{print $1}') - for rule in $rules - do - iptables -D INPUT $rule 2>/dev/null - break - done - count=$(expr $count - 1) - done -fi - -iptables -F SSR_LIBEV-SERVER 2>/dev/null && iptables -X SSR_LIBEV-SERVER 2>/dev/null - -enable=$(uci -q get ssr_libev_server.@global[0].enable) -if [ $enable -eq 1 ]; then - iptables -N SSR_LIBEV-SERVER - iptables -I INPUT -j SSR_LIBEV-SERVER - - count=$(uci show ssr_libev_server | grep "@user" | sed -n '$p' | cut -d '[' -f 2 | cut -d ']' -f 1) - [ -n "$count" ] && [ "$count" -ge 0 ] && { - u_get() { - local ret=$(uci -q get ssr_libev_server.@user[$1].$2) - echo ${ret:=$3} - } - for i in $(seq 0 $count); do - enable=$(u_get $i enable 0) - [ $enable -eq 0 ] && continue - remarks=$(u_get $i remarks) - port=$(u_get $i port) - udp_forward=$(u_get $i udp_forward) - iptables -A SSR_LIBEV-SERVER -p tcp --dport $port -m comment --comment "$remarks" -j ACCEPT - [ "$udp_forward" = "1" ] && iptables -A SSR_LIBEV-SERVER -p udp --dport $port -m comment --comment "$remarks" -j ACCEPT - done - } -fi diff --git a/package/lienol/luci-app-ssr-mudb-server/Makefile b/package/lienol/luci-app-ssr-mudb-server/Makefile deleted file mode 100644 index ba213ffb75..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (C) 2018-2020 Lienol -# -# This is free software, licensed under the GNU General Public License v3. -# - -include $(TOPDIR)/rules.mk - -LUCI_TITLE:=LuCI support for SSR Mudb Server -LUCI_DEPENDS:=+libsodium +luci-lib-jsonc +python3 -LUCI_PKGARCH:=all -PKG_VERSION:=10 -PKG_DATE:=20200619 - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature diff --git a/package/lienol/luci-app-ssr-mudb-server/htdocs/luci-static/resources/vue.min.js b/package/lienol/luci-app-ssr-mudb-server/htdocs/luci-static/resources/vue.min.js deleted file mode 100644 index 05e21102a0..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/htdocs/luci-static/resources/vue.min.js +++ /dev/null @@ -1,6 +0,0 @@ -/*! - * Vue.js v2.6.11 - * (c) 2014-2019 Evan You - * Released under the MIT License. - */ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).Vue=t()}(this,function(){"use strict";var e=Object.freeze({});function t(e){return null==e}function n(e){return null!=e}function r(e){return!0===e}function i(e){return"string"==typeof e||"number"==typeof e||"symbol"==typeof e||"boolean"==typeof e}function o(e){return null!==e&&"object"==typeof e}var a=Object.prototype.toString;function s(e){return"[object Object]"===a.call(e)}function c(e){var t=parseFloat(String(e));return t>=0&&Math.floor(t)===t&&isFinite(e)}function u(e){return n(e)&&"function"==typeof e.then&&"function"==typeof e.catch}function l(e){return null==e?"":Array.isArray(e)||s(e)&&e.toString===a?JSON.stringify(e,null,2):String(e)}function f(e){var t=parseFloat(e);return isNaN(t)?e:t}function p(e,t){for(var n=Object.create(null),r=e.split(","),i=0;i-1)return e.splice(n,1)}}var m=Object.prototype.hasOwnProperty;function y(e,t){return m.call(e,t)}function g(e){var t=Object.create(null);return function(n){return t[n]||(t[n]=e(n))}}var _=/-(\w)/g,b=g(function(e){return e.replace(_,function(e,t){return t?t.toUpperCase():""})}),$=g(function(e){return e.charAt(0).toUpperCase()+e.slice(1)}),w=/\B([A-Z])/g,C=g(function(e){return e.replace(w,"-$1").toLowerCase()});var x=Function.prototype.bind?function(e,t){return e.bind(t)}:function(e,t){function n(n){var r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}return n._length=e.length,n};function k(e,t){t=t||0;for(var n=e.length-t,r=new Array(n);n--;)r[n]=e[n+t];return r}function A(e,t){for(var n in t)e[n]=t[n];return e}function O(e){for(var t={},n=0;n0,Z=J&&J.indexOf("edge/")>0,G=(J&&J.indexOf("android"),J&&/iphone|ipad|ipod|ios/.test(J)||"ios"===K),X=(J&&/chrome\/\d+/.test(J),J&&/phantomjs/.test(J),J&&J.match(/firefox\/(\d+)/)),Y={}.watch,Q=!1;if(z)try{var ee={};Object.defineProperty(ee,"passive",{get:function(){Q=!0}}),window.addEventListener("test-passive",null,ee)}catch(e){}var te=function(){return void 0===B&&(B=!z&&!V&&"undefined"!=typeof global&&(global.process&&"server"===global.process.env.VUE_ENV)),B},ne=z&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__;function re(e){return"function"==typeof e&&/native code/.test(e.toString())}var ie,oe="undefined"!=typeof Symbol&&re(Symbol)&&"undefined"!=typeof Reflect&&re(Reflect.ownKeys);ie="undefined"!=typeof Set&&re(Set)?Set:function(){function e(){this.set=Object.create(null)}return e.prototype.has=function(e){return!0===this.set[e]},e.prototype.add=function(e){this.set[e]=!0},e.prototype.clear=function(){this.set=Object.create(null)},e}();var ae=S,se=0,ce=function(){this.id=se++,this.subs=[]};ce.prototype.addSub=function(e){this.subs.push(e)},ce.prototype.removeSub=function(e){h(this.subs,e)},ce.prototype.depend=function(){ce.target&&ce.target.addDep(this)},ce.prototype.notify=function(){for(var e=this.subs.slice(),t=0,n=e.length;t-1)if(o&&!y(i,"default"))a=!1;else if(""===a||a===C(e)){var c=Pe(String,i.type);(c<0||s0&&(st((u=e(u,(a||"")+"_"+c))[0])&&st(f)&&(s[l]=he(f.text+u[0].text),u.shift()),s.push.apply(s,u)):i(u)?st(f)?s[l]=he(f.text+u):""!==u&&s.push(he(u)):st(u)&&st(f)?s[l]=he(f.text+u.text):(r(o._isVList)&&n(u.tag)&&t(u.key)&&n(a)&&(u.key="__vlist"+a+"_"+c+"__"),s.push(u)));return s}(e):void 0}function st(e){return n(e)&&n(e.text)&&!1===e.isComment}function ct(e,t){if(e){for(var n=Object.create(null),r=oe?Reflect.ownKeys(e):Object.keys(e),i=0;i0,a=t?!!t.$stable:!o,s=t&&t.$key;if(t){if(t._normalized)return t._normalized;if(a&&r&&r!==e&&s===r.$key&&!o&&!r.$hasNormal)return r;for(var c in i={},t)t[c]&&"$"!==c[0]&&(i[c]=pt(n,c,t[c]))}else i={};for(var u in n)u in i||(i[u]=dt(n,u));return t&&Object.isExtensible(t)&&(t._normalized=i),R(i,"$stable",a),R(i,"$key",s),R(i,"$hasNormal",o),i}function pt(e,t,n){var r=function(){var e=arguments.length?n.apply(null,arguments):n({});return(e=e&&"object"==typeof e&&!Array.isArray(e)?[e]:at(e))&&(0===e.length||1===e.length&&e[0].isComment)?void 0:e};return n.proxy&&Object.defineProperty(e,t,{get:r,enumerable:!0,configurable:!0}),r}function dt(e,t){return function(){return e[t]}}function vt(e,t){var r,i,a,s,c;if(Array.isArray(e)||"string"==typeof e)for(r=new Array(e.length),i=0,a=e.length;idocument.createEvent("Event").timeStamp&&(sn=function(){return cn.now()})}function un(){var e,t;for(an=sn(),rn=!0,Qt.sort(function(e,t){return e.id-t.id}),on=0;onon&&Qt[n].id>e.id;)n--;Qt.splice(n+1,0,e)}else Qt.push(e);nn||(nn=!0,Ye(un))}}(this)},fn.prototype.run=function(){if(this.active){var e=this.get();if(e!==this.value||o(e)||this.deep){var t=this.value;if(this.value=e,this.user)try{this.cb.call(this.vm,e,t)}catch(e){Re(e,this.vm,'callback for watcher "'+this.expression+'"')}else this.cb.call(this.vm,e,t)}}},fn.prototype.evaluate=function(){this.value=this.get(),this.dirty=!1},fn.prototype.depend=function(){for(var e=this.deps.length;e--;)this.deps[e].depend()},fn.prototype.teardown=function(){if(this.active){this.vm._isBeingDestroyed||h(this.vm._watchers,this);for(var e=this.deps.length;e--;)this.deps[e].removeSub(this);this.active=!1}};var pn={enumerable:!0,configurable:!0,get:S,set:S};function dn(e,t,n){pn.get=function(){return this[t][n]},pn.set=function(e){this[t][n]=e},Object.defineProperty(e,n,pn)}function vn(e){e._watchers=[];var t=e.$options;t.props&&function(e,t){var n=e.$options.propsData||{},r=e._props={},i=e.$options._propKeys=[];e.$parent&&$e(!1);var o=function(o){i.push(o);var a=Me(o,t,n,e);xe(r,o,a),o in e||dn(e,"_props",o)};for(var a in t)o(a);$e(!0)}(e,t.props),t.methods&&function(e,t){e.$options.props;for(var n in t)e[n]="function"!=typeof t[n]?S:x(t[n],e)}(e,t.methods),t.data?function(e){var t=e.$options.data;s(t=e._data="function"==typeof t?function(e,t){le();try{return e.call(t,t)}catch(e){return Re(e,t,"data()"),{}}finally{fe()}}(t,e):t||{})||(t={});var n=Object.keys(t),r=e.$options.props,i=(e.$options.methods,n.length);for(;i--;){var o=n[i];r&&y(r,o)||(a=void 0,36!==(a=(o+"").charCodeAt(0))&&95!==a&&dn(e,"_data",o))}var a;Ce(t,!0)}(e):Ce(e._data={},!0),t.computed&&function(e,t){var n=e._computedWatchers=Object.create(null),r=te();for(var i in t){var o=t[i],a="function"==typeof o?o:o.get;r||(n[i]=new fn(e,a||S,S,hn)),i in e||mn(e,i,o)}}(e,t.computed),t.watch&&t.watch!==Y&&function(e,t){for(var n in t){var r=t[n];if(Array.isArray(r))for(var i=0;i-1:"string"==typeof e?e.split(",").indexOf(t)>-1:(n=e,"[object RegExp]"===a.call(n)&&e.test(t));var n}function An(e,t){var n=e.cache,r=e.keys,i=e._vnode;for(var o in n){var a=n[o];if(a){var s=xn(a.componentOptions);s&&!t(s)&&On(n,o,r,i)}}}function On(e,t,n,r){var i=e[t];!i||r&&i.tag===r.tag||i.componentInstance.$destroy(),e[t]=null,h(n,t)}!function(t){t.prototype._init=function(t){var n=this;n._uid=bn++,n._isVue=!0,t&&t._isComponent?function(e,t){var n=e.$options=Object.create(e.constructor.options),r=t._parentVnode;n.parent=t.parent,n._parentVnode=r;var i=r.componentOptions;n.propsData=i.propsData,n._parentListeners=i.listeners,n._renderChildren=i.children,n._componentTag=i.tag,t.render&&(n.render=t.render,n.staticRenderFns=t.staticRenderFns)}(n,t):n.$options=De($n(n.constructor),t||{},n),n._renderProxy=n,n._self=n,function(e){var t=e.$options,n=t.parent;if(n&&!t.abstract){for(;n.$options.abstract&&n.$parent;)n=n.$parent;n.$children.push(e)}e.$parent=n,e.$root=n?n.$root:e,e.$children=[],e.$refs={},e._watcher=null,e._inactive=null,e._directInactive=!1,e._isMounted=!1,e._isDestroyed=!1,e._isBeingDestroyed=!1}(n),function(e){e._events=Object.create(null),e._hasHookEvent=!1;var t=e.$options._parentListeners;t&&qt(e,t)}(n),function(t){t._vnode=null,t._staticTrees=null;var n=t.$options,r=t.$vnode=n._parentVnode,i=r&&r.context;t.$slots=ut(n._renderChildren,i),t.$scopedSlots=e,t._c=function(e,n,r,i){return Pt(t,e,n,r,i,!1)},t.$createElement=function(e,n,r,i){return Pt(t,e,n,r,i,!0)};var o=r&&r.data;xe(t,"$attrs",o&&o.attrs||e,null,!0),xe(t,"$listeners",n._parentListeners||e,null,!0)}(n),Yt(n,"beforeCreate"),function(e){var t=ct(e.$options.inject,e);t&&($e(!1),Object.keys(t).forEach(function(n){xe(e,n,t[n])}),$e(!0))}(n),vn(n),function(e){var t=e.$options.provide;t&&(e._provided="function"==typeof t?t.call(e):t)}(n),Yt(n,"created"),n.$options.el&&n.$mount(n.$options.el)}}(wn),function(e){var t={get:function(){return this._data}},n={get:function(){return this._props}};Object.defineProperty(e.prototype,"$data",t),Object.defineProperty(e.prototype,"$props",n),e.prototype.$set=ke,e.prototype.$delete=Ae,e.prototype.$watch=function(e,t,n){if(s(t))return _n(this,e,t,n);(n=n||{}).user=!0;var r=new fn(this,e,t,n);if(n.immediate)try{t.call(this,r.value)}catch(e){Re(e,this,'callback for immediate watcher "'+r.expression+'"')}return function(){r.teardown()}}}(wn),function(e){var t=/^hook:/;e.prototype.$on=function(e,n){var r=this;if(Array.isArray(e))for(var i=0,o=e.length;i1?k(t):t;for(var n=k(arguments,1),r='event handler for "'+e+'"',i=0,o=t.length;iparseInt(this.max)&&On(a,s[0],s,this._vnode)),t.data.keepAlive=!0}return t||e&&e[0]}}};!function(e){var t={get:function(){return F}};Object.defineProperty(e,"config",t),e.util={warn:ae,extend:A,mergeOptions:De,defineReactive:xe},e.set=ke,e.delete=Ae,e.nextTick=Ye,e.observable=function(e){return Ce(e),e},e.options=Object.create(null),M.forEach(function(t){e.options[t+"s"]=Object.create(null)}),e.options._base=e,A(e.options.components,Tn),function(e){e.use=function(e){var t=this._installedPlugins||(this._installedPlugins=[]);if(t.indexOf(e)>-1)return this;var n=k(arguments,1);return n.unshift(this),"function"==typeof e.install?e.install.apply(e,n):"function"==typeof e&&e.apply(null,n),t.push(e),this}}(e),function(e){e.mixin=function(e){return this.options=De(this.options,e),this}}(e),Cn(e),function(e){M.forEach(function(t){e[t]=function(e,n){return n?("component"===t&&s(n)&&(n.name=n.name||e,n=this.options._base.extend(n)),"directive"===t&&"function"==typeof n&&(n={bind:n,update:n}),this.options[t+"s"][e]=n,n):this.options[t+"s"][e]}})}(e)}(wn),Object.defineProperty(wn.prototype,"$isServer",{get:te}),Object.defineProperty(wn.prototype,"$ssrContext",{get:function(){return this.$vnode&&this.$vnode.ssrContext}}),Object.defineProperty(wn,"FunctionalRenderContext",{value:Tt}),wn.version="2.6.11";var En=p("style,class"),Nn=p("input,textarea,option,select,progress"),jn=function(e,t,n){return"value"===n&&Nn(e)&&"button"!==t||"selected"===n&&"option"===e||"checked"===n&&"input"===e||"muted"===n&&"video"===e},Dn=p("contenteditable,draggable,spellcheck"),Ln=p("events,caret,typing,plaintext-only"),Mn=function(e,t){return Hn(t)||"false"===t?"false":"contenteditable"===e&&Ln(t)?t:"true"},In=p("allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,default,defaultchecked,defaultmuted,defaultselected,defer,disabled,enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,required,reversed,scoped,seamless,selected,sortable,translate,truespeed,typemustmatch,visible"),Fn="http://www.w3.org/1999/xlink",Pn=function(e){return":"===e.charAt(5)&&"xlink"===e.slice(0,5)},Rn=function(e){return Pn(e)?e.slice(6,e.length):""},Hn=function(e){return null==e||!1===e};function Bn(e){for(var t=e.data,r=e,i=e;n(i.componentInstance);)(i=i.componentInstance._vnode)&&i.data&&(t=Un(i.data,t));for(;n(r=r.parent);)r&&r.data&&(t=Un(t,r.data));return function(e,t){if(n(e)||n(t))return zn(e,Vn(t));return""}(t.staticClass,t.class)}function Un(e,t){return{staticClass:zn(e.staticClass,t.staticClass),class:n(e.class)?[e.class,t.class]:t.class}}function zn(e,t){return e?t?e+" "+t:e:t||""}function Vn(e){return Array.isArray(e)?function(e){for(var t,r="",i=0,o=e.length;i-1?hr(e,t,n):In(t)?Hn(n)?e.removeAttribute(t):(n="allowfullscreen"===t&&"EMBED"===e.tagName?"true":t,e.setAttribute(t,n)):Dn(t)?e.setAttribute(t,Mn(t,n)):Pn(t)?Hn(n)?e.removeAttributeNS(Fn,Rn(t)):e.setAttributeNS(Fn,t,n):hr(e,t,n)}function hr(e,t,n){if(Hn(n))e.removeAttribute(t);else{if(q&&!W&&"TEXTAREA"===e.tagName&&"placeholder"===t&&""!==n&&!e.__ieph){var r=function(t){t.stopImmediatePropagation(),e.removeEventListener("input",r)};e.addEventListener("input",r),e.__ieph=!0}e.setAttribute(t,n)}}var mr={create:dr,update:dr};function yr(e,r){var i=r.elm,o=r.data,a=e.data;if(!(t(o.staticClass)&&t(o.class)&&(t(a)||t(a.staticClass)&&t(a.class)))){var s=Bn(r),c=i._transitionClasses;n(c)&&(s=zn(s,Vn(c))),s!==i._prevClass&&(i.setAttribute("class",s),i._prevClass=s)}}var gr,_r,br,$r,wr,Cr,xr={create:yr,update:yr},kr=/[\w).+\-_$\]]/;function Ar(e){var t,n,r,i,o,a=!1,s=!1,c=!1,u=!1,l=0,f=0,p=0,d=0;for(r=0;r=0&&" "===(h=e.charAt(v));v--);h&&kr.test(h)||(u=!0)}}else void 0===i?(d=r+1,i=e.slice(0,r).trim()):m();function m(){(o||(o=[])).push(e.slice(d,r).trim()),d=r+1}if(void 0===i?i=e.slice(0,r).trim():0!==d&&m(),o)for(r=0;r-1?{exp:e.slice(0,$r),key:'"'+e.slice($r+1)+'"'}:{exp:e,key:null};_r=e,$r=wr=Cr=0;for(;!zr();)Vr(br=Ur())?Jr(br):91===br&&Kr(br);return{exp:e.slice(0,wr),key:e.slice(wr+1,Cr)}}(e);return null===n.key?e+"="+t:"$set("+n.exp+", "+n.key+", "+t+")"}function Ur(){return _r.charCodeAt(++$r)}function zr(){return $r>=gr}function Vr(e){return 34===e||39===e}function Kr(e){var t=1;for(wr=$r;!zr();)if(Vr(e=Ur()))Jr(e);else if(91===e&&t++,93===e&&t--,0===t){Cr=$r;break}}function Jr(e){for(var t=e;!zr()&&(e=Ur())!==t;);}var qr,Wr="__r",Zr="__c";function Gr(e,t,n){var r=qr;return function i(){null!==t.apply(null,arguments)&&Qr(e,i,n,r)}}var Xr=Ve&&!(X&&Number(X[1])<=53);function Yr(e,t,n,r){if(Xr){var i=an,o=t;t=o._wrapper=function(e){if(e.target===e.currentTarget||e.timeStamp>=i||e.timeStamp<=0||e.target.ownerDocument!==document)return o.apply(this,arguments)}}qr.addEventListener(e,t,Q?{capture:n,passive:r}:n)}function Qr(e,t,n,r){(r||qr).removeEventListener(e,t._wrapper||t,n)}function ei(e,r){if(!t(e.data.on)||!t(r.data.on)){var i=r.data.on||{},o=e.data.on||{};qr=r.elm,function(e){if(n(e[Wr])){var t=q?"change":"input";e[t]=[].concat(e[Wr],e[t]||[]),delete e[Wr]}n(e[Zr])&&(e.change=[].concat(e[Zr],e.change||[]),delete e[Zr])}(i),rt(i,o,Yr,Qr,Gr,r.context),qr=void 0}}var ti,ni={create:ei,update:ei};function ri(e,r){if(!t(e.data.domProps)||!t(r.data.domProps)){var i,o,a=r.elm,s=e.data.domProps||{},c=r.data.domProps||{};for(i in n(c.__ob__)&&(c=r.data.domProps=A({},c)),s)i in c||(a[i]="");for(i in c){if(o=c[i],"textContent"===i||"innerHTML"===i){if(r.children&&(r.children.length=0),o===s[i])continue;1===a.childNodes.length&&a.removeChild(a.childNodes[0])}if("value"===i&&"PROGRESS"!==a.tagName){a._value=o;var u=t(o)?"":String(o);ii(a,u)&&(a.value=u)}else if("innerHTML"===i&&qn(a.tagName)&&t(a.innerHTML)){(ti=ti||document.createElement("div")).innerHTML=""+o+"";for(var l=ti.firstChild;a.firstChild;)a.removeChild(a.firstChild);for(;l.firstChild;)a.appendChild(l.firstChild)}else if(o!==s[i])try{a[i]=o}catch(e){}}}}function ii(e,t){return!e.composing&&("OPTION"===e.tagName||function(e,t){var n=!0;try{n=document.activeElement!==e}catch(e){}return n&&e.value!==t}(e,t)||function(e,t){var r=e.value,i=e._vModifiers;if(n(i)){if(i.number)return f(r)!==f(t);if(i.trim)return r.trim()!==t.trim()}return r!==t}(e,t))}var oi={create:ri,update:ri},ai=g(function(e){var t={},n=/:(.+)/;return e.split(/;(?![^(]*\))/g).forEach(function(e){if(e){var r=e.split(n);r.length>1&&(t[r[0].trim()]=r[1].trim())}}),t});function si(e){var t=ci(e.style);return e.staticStyle?A(e.staticStyle,t):t}function ci(e){return Array.isArray(e)?O(e):"string"==typeof e?ai(e):e}var ui,li=/^--/,fi=/\s*!important$/,pi=function(e,t,n){if(li.test(t))e.style.setProperty(t,n);else if(fi.test(n))e.style.setProperty(C(t),n.replace(fi,""),"important");else{var r=vi(t);if(Array.isArray(n))for(var i=0,o=n.length;i-1?t.split(yi).forEach(function(t){return e.classList.add(t)}):e.classList.add(t);else{var n=" "+(e.getAttribute("class")||"")+" ";n.indexOf(" "+t+" ")<0&&e.setAttribute("class",(n+t).trim())}}function _i(e,t){if(t&&(t=t.trim()))if(e.classList)t.indexOf(" ")>-1?t.split(yi).forEach(function(t){return e.classList.remove(t)}):e.classList.remove(t),e.classList.length||e.removeAttribute("class");else{for(var n=" "+(e.getAttribute("class")||"")+" ",r=" "+t+" ";n.indexOf(r)>=0;)n=n.replace(r," ");(n=n.trim())?e.setAttribute("class",n):e.removeAttribute("class")}}function bi(e){if(e){if("object"==typeof e){var t={};return!1!==e.css&&A(t,$i(e.name||"v")),A(t,e),t}return"string"==typeof e?$i(e):void 0}}var $i=g(function(e){return{enterClass:e+"-enter",enterToClass:e+"-enter-to",enterActiveClass:e+"-enter-active",leaveClass:e+"-leave",leaveToClass:e+"-leave-to",leaveActiveClass:e+"-leave-active"}}),wi=z&&!W,Ci="transition",xi="animation",ki="transition",Ai="transitionend",Oi="animation",Si="animationend";wi&&(void 0===window.ontransitionend&&void 0!==window.onwebkittransitionend&&(ki="WebkitTransition",Ai="webkitTransitionEnd"),void 0===window.onanimationend&&void 0!==window.onwebkitanimationend&&(Oi="WebkitAnimation",Si="webkitAnimationEnd"));var Ti=z?window.requestAnimationFrame?window.requestAnimationFrame.bind(window):setTimeout:function(e){return e()};function Ei(e){Ti(function(){Ti(e)})}function Ni(e,t){var n=e._transitionClasses||(e._transitionClasses=[]);n.indexOf(t)<0&&(n.push(t),gi(e,t))}function ji(e,t){e._transitionClasses&&h(e._transitionClasses,t),_i(e,t)}function Di(e,t,n){var r=Mi(e,t),i=r.type,o=r.timeout,a=r.propCount;if(!i)return n();var s=i===Ci?Ai:Si,c=0,u=function(){e.removeEventListener(s,l),n()},l=function(t){t.target===e&&++c>=a&&u()};setTimeout(function(){c0&&(n=Ci,l=a,f=o.length):t===xi?u>0&&(n=xi,l=u,f=c.length):f=(n=(l=Math.max(a,u))>0?a>u?Ci:xi:null)?n===Ci?o.length:c.length:0,{type:n,timeout:l,propCount:f,hasTransform:n===Ci&&Li.test(r[ki+"Property"])}}function Ii(e,t){for(;e.length1}function Ui(e,t){!0!==t.data.show&&Pi(t)}var zi=function(e){var o,a,s={},c=e.modules,u=e.nodeOps;for(o=0;ov?_(e,t(i[y+1])?null:i[y+1].elm,i,d,y,o):d>y&&$(r,p,v)}(p,h,y,o,l):n(y)?(n(e.text)&&u.setTextContent(p,""),_(p,null,y,0,y.length-1,o)):n(h)?$(h,0,h.length-1):n(e.text)&&u.setTextContent(p,""):e.text!==i.text&&u.setTextContent(p,i.text),n(v)&&n(d=v.hook)&&n(d=d.postpatch)&&d(e,i)}}}function k(e,t,i){if(r(i)&&n(e.parent))e.parent.data.pendingInsert=t;else for(var o=0;o-1,a.selected!==o&&(a.selected=o);else if(N(Wi(a),r))return void(e.selectedIndex!==s&&(e.selectedIndex=s));i||(e.selectedIndex=-1)}}function qi(e,t){return t.every(function(t){return!N(t,e)})}function Wi(e){return"_value"in e?e._value:e.value}function Zi(e){e.target.composing=!0}function Gi(e){e.target.composing&&(e.target.composing=!1,Xi(e.target,"input"))}function Xi(e,t){var n=document.createEvent("HTMLEvents");n.initEvent(t,!0,!0),e.dispatchEvent(n)}function Yi(e){return!e.componentInstance||e.data&&e.data.transition?e:Yi(e.componentInstance._vnode)}var Qi={model:Vi,show:{bind:function(e,t,n){var r=t.value,i=(n=Yi(n)).data&&n.data.transition,o=e.__vOriginalDisplay="none"===e.style.display?"":e.style.display;r&&i?(n.data.show=!0,Pi(n,function(){e.style.display=o})):e.style.display=r?o:"none"},update:function(e,t,n){var r=t.value;!r!=!t.oldValue&&((n=Yi(n)).data&&n.data.transition?(n.data.show=!0,r?Pi(n,function(){e.style.display=e.__vOriginalDisplay}):Ri(n,function(){e.style.display="none"})):e.style.display=r?e.__vOriginalDisplay:"none")},unbind:function(e,t,n,r,i){i||(e.style.display=e.__vOriginalDisplay)}}},eo={name:String,appear:Boolean,css:Boolean,mode:String,type:String,enterClass:String,leaveClass:String,enterToClass:String,leaveToClass:String,enterActiveClass:String,leaveActiveClass:String,appearClass:String,appearActiveClass:String,appearToClass:String,duration:[Number,String,Object]};function to(e){var t=e&&e.componentOptions;return t&&t.Ctor.options.abstract?to(zt(t.children)):e}function no(e){var t={},n=e.$options;for(var r in n.propsData)t[r]=e[r];var i=n._parentListeners;for(var o in i)t[b(o)]=i[o];return t}function ro(e,t){if(/\d-keep-alive$/.test(t.tag))return e("keep-alive",{props:t.componentOptions.propsData})}var io=function(e){return e.tag||Ut(e)},oo=function(e){return"show"===e.name},ao={name:"transition",props:eo,abstract:!0,render:function(e){var t=this,n=this.$slots.default;if(n&&(n=n.filter(io)).length){var r=this.mode,o=n[0];if(function(e){for(;e=e.parent;)if(e.data.transition)return!0}(this.$vnode))return o;var a=to(o);if(!a)return o;if(this._leaving)return ro(e,o);var s="__transition-"+this._uid+"-";a.key=null==a.key?a.isComment?s+"comment":s+a.tag:i(a.key)?0===String(a.key).indexOf(s)?a.key:s+a.key:a.key;var c=(a.data||(a.data={})).transition=no(this),u=this._vnode,l=to(u);if(a.data.directives&&a.data.directives.some(oo)&&(a.data.show=!0),l&&l.data&&!function(e,t){return t.key===e.key&&t.tag===e.tag}(a,l)&&!Ut(l)&&(!l.componentInstance||!l.componentInstance._vnode.isComment)){var f=l.data.transition=A({},c);if("out-in"===r)return this._leaving=!0,it(f,"afterLeave",function(){t._leaving=!1,t.$forceUpdate()}),ro(e,o);if("in-out"===r){if(Ut(a))return u;var p,d=function(){p()};it(c,"afterEnter",d),it(c,"enterCancelled",d),it(f,"delayLeave",function(e){p=e})}}return o}}},so=A({tag:String,moveClass:String},eo);function co(e){e.elm._moveCb&&e.elm._moveCb(),e.elm._enterCb&&e.elm._enterCb()}function uo(e){e.data.newPos=e.elm.getBoundingClientRect()}function lo(e){var t=e.data.pos,n=e.data.newPos,r=t.left-n.left,i=t.top-n.top;if(r||i){e.data.moved=!0;var o=e.elm.style;o.transform=o.WebkitTransform="translate("+r+"px,"+i+"px)",o.transitionDuration="0s"}}delete so.mode;var fo={Transition:ao,TransitionGroup:{props:so,beforeMount:function(){var e=this,t=this._update;this._update=function(n,r){var i=Zt(e);e.__patch__(e._vnode,e.kept,!1,!0),e._vnode=e.kept,i(),t.call(e,n,r)}},render:function(e){for(var t=this.tag||this.$vnode.data.tag||"span",n=Object.create(null),r=this.prevChildren=this.children,i=this.$slots.default||[],o=this.children=[],a=no(this),s=0;s-1?Gn[e]=t.constructor===window.HTMLUnknownElement||t.constructor===window.HTMLElement:Gn[e]=/HTMLUnknownElement/.test(t.toString())},A(wn.options.directives,Qi),A(wn.options.components,fo),wn.prototype.__patch__=z?zi:S,wn.prototype.$mount=function(e,t){return function(e,t,n){var r;return e.$el=t,e.$options.render||(e.$options.render=ve),Yt(e,"beforeMount"),r=function(){e._update(e._render(),n)},new fn(e,r,S,{before:function(){e._isMounted&&!e._isDestroyed&&Yt(e,"beforeUpdate")}},!0),n=!1,null==e.$vnode&&(e._isMounted=!0,Yt(e,"mounted")),e}(this,e=e&&z?Yn(e):void 0,t)},z&&setTimeout(function(){F.devtools&&ne&&ne.emit("init",wn)},0);var po=/\{\{((?:.|\r?\n)+?)\}\}/g,vo=/[-.*+?^${}()|[\]\/\\]/g,ho=g(function(e){var t=e[0].replace(vo,"\\$&"),n=e[1].replace(vo,"\\$&");return new RegExp(t+"((?:.|\\n)+?)"+n,"g")});var mo={staticKeys:["staticClass"],transformNode:function(e,t){t.warn;var n=Fr(e,"class");n&&(e.staticClass=JSON.stringify(n));var r=Ir(e,"class",!1);r&&(e.classBinding=r)},genData:function(e){var t="";return e.staticClass&&(t+="staticClass:"+e.staticClass+","),e.classBinding&&(t+="class:"+e.classBinding+","),t}};var yo,go={staticKeys:["staticStyle"],transformNode:function(e,t){t.warn;var n=Fr(e,"style");n&&(e.staticStyle=JSON.stringify(ai(n)));var r=Ir(e,"style",!1);r&&(e.styleBinding=r)},genData:function(e){var t="";return e.staticStyle&&(t+="staticStyle:"+e.staticStyle+","),e.styleBinding&&(t+="style:("+e.styleBinding+"),"),t}},_o=function(e){return(yo=yo||document.createElement("div")).innerHTML=e,yo.textContent},bo=p("area,base,br,col,embed,frame,hr,img,input,isindex,keygen,link,meta,param,source,track,wbr"),$o=p("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr,source"),wo=p("address,article,aside,base,blockquote,body,caption,col,colgroup,dd,details,dialog,div,dl,dt,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,legend,li,menuitem,meta,optgroup,option,param,rp,rt,source,style,summary,tbody,td,tfoot,th,thead,title,tr,track"),Co=/^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/,xo=/^\s*((?:v-[\w-]+:|@|:|#)\[[^=]+\][^\s"'<>\/=]*)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/,ko="[a-zA-Z_][\\-\\.0-9_a-zA-Z"+P.source+"]*",Ao="((?:"+ko+"\\:)?"+ko+")",Oo=new RegExp("^<"+Ao),So=/^\s*(\/?)>/,To=new RegExp("^<\\/"+Ao+"[^>]*>"),Eo=/^]+>/i,No=/^",""":'"',"&":"&"," ":"\n"," ":"\t","'":"'"},Io=/&(?:lt|gt|quot|amp|#39);/g,Fo=/&(?:lt|gt|quot|amp|#39|#10|#9);/g,Po=p("pre,textarea",!0),Ro=function(e,t){return e&&Po(e)&&"\n"===t[0]};function Ho(e,t){var n=t?Fo:Io;return e.replace(n,function(e){return Mo[e]})}var Bo,Uo,zo,Vo,Ko,Jo,qo,Wo,Zo=/^@|^v-on:/,Go=/^v-|^@|^:|^#/,Xo=/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/,Yo=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,Qo=/^\(|\)$/g,ea=/^\[.*\]$/,ta=/:(.*)$/,na=/^:|^\.|^v-bind:/,ra=/\.[^.\]]+(?=[^\]]*$)/g,ia=/^v-slot(:|$)|^#/,oa=/[\r\n]/,aa=/\s+/g,sa=g(_o),ca="_empty_";function ua(e,t,n){return{type:1,tag:e,attrsList:t,attrsMap:ma(t),rawAttrsMap:{},parent:n,children:[]}}function la(e,t){Bo=t.warn||Sr,Jo=t.isPreTag||T,qo=t.mustUseProp||T,Wo=t.getTagNamespace||T;t.isReservedTag;zo=Tr(t.modules,"transformNode"),Vo=Tr(t.modules,"preTransformNode"),Ko=Tr(t.modules,"postTransformNode"),Uo=t.delimiters;var n,r,i=[],o=!1!==t.preserveWhitespace,a=t.whitespace,s=!1,c=!1;function u(e){if(l(e),s||e.processed||(e=fa(e,t)),i.length||e===n||n.if&&(e.elseif||e.else)&&da(n,{exp:e.elseif,block:e}),r&&!e.forbidden)if(e.elseif||e.else)a=e,(u=function(e){var t=e.length;for(;t--;){if(1===e[t].type)return e[t];e.pop()}}(r.children))&&u.if&&da(u,{exp:a.elseif,block:a});else{if(e.slotScope){var o=e.slotTarget||'"default"';(r.scopedSlots||(r.scopedSlots={}))[o]=e}r.children.push(e),e.parent=r}var a,u;e.children=e.children.filter(function(e){return!e.slotScope}),l(e),e.pre&&(s=!1),Jo(e.tag)&&(c=!1);for(var f=0;f]*>)","i")),p=e.replace(f,function(e,n,r){return u=r.length,Do(l)||"noscript"===l||(n=n.replace(//g,"$1").replace(//g,"$1")),Ro(l,n)&&(n=n.slice(1)),t.chars&&t.chars(n),""});c+=e.length-p.length,e=p,A(l,c-u,c)}else{var d=e.indexOf("<");if(0===d){if(No.test(e)){var v=e.indexOf("--\x3e");if(v>=0){t.shouldKeepComment&&t.comment(e.substring(4,v),c,c+v+3),C(v+3);continue}}if(jo.test(e)){var h=e.indexOf("]>");if(h>=0){C(h+2);continue}}var m=e.match(Eo);if(m){C(m[0].length);continue}var y=e.match(To);if(y){var g=c;C(y[0].length),A(y[1],g,c);continue}var _=x();if(_){k(_),Ro(_.tagName,e)&&C(1);continue}}var b=void 0,$=void 0,w=void 0;if(d>=0){for($=e.slice(d);!(To.test($)||Oo.test($)||No.test($)||jo.test($)||(w=$.indexOf("<",1))<0);)d+=w,$=e.slice(d);b=e.substring(0,d)}d<0&&(b=e),b&&C(b.length),t.chars&&b&&t.chars(b,c-b.length,c)}if(e===n){t.chars&&t.chars(e);break}}function C(t){c+=t,e=e.substring(t)}function x(){var t=e.match(Oo);if(t){var n,r,i={tagName:t[1],attrs:[],start:c};for(C(t[0].length);!(n=e.match(So))&&(r=e.match(xo)||e.match(Co));)r.start=c,C(r[0].length),r.end=c,i.attrs.push(r);if(n)return i.unarySlash=n[1],C(n[0].length),i.end=c,i}}function k(e){var n=e.tagName,c=e.unarySlash;o&&("p"===r&&wo(n)&&A(r),s(n)&&r===n&&A(n));for(var u=a(n)||!!c,l=e.attrs.length,f=new Array(l),p=0;p=0&&i[a].lowerCasedTag!==s;a--);else a=0;if(a>=0){for(var u=i.length-1;u>=a;u--)t.end&&t.end(i[u].tag,n,o);i.length=a,r=a&&i[a-1].tag}else"br"===s?t.start&&t.start(e,[],!0,n,o):"p"===s&&(t.start&&t.start(e,[],!1,n,o),t.end&&t.end(e,n,o))}A()}(e,{warn:Bo,expectHTML:t.expectHTML,isUnaryTag:t.isUnaryTag,canBeLeftOpenTag:t.canBeLeftOpenTag,shouldDecodeNewlines:t.shouldDecodeNewlines,shouldDecodeNewlinesForHref:t.shouldDecodeNewlinesForHref,shouldKeepComment:t.comments,outputSourceRange:t.outputSourceRange,start:function(e,o,a,l,f){var p=r&&r.ns||Wo(e);q&&"svg"===p&&(o=function(e){for(var t=[],n=0;nc&&(s.push(o=e.slice(c,i)),a.push(JSON.stringify(o)));var u=Ar(r[1].trim());a.push("_s("+u+")"),s.push({"@binding":u}),c=i+r[0].length}return c-1"+("true"===o?":("+t+")":":_q("+t+","+o+")")),Mr(e,"change","var $$a="+t+",$$el=$event.target,$$c=$$el.checked?("+o+"):("+a+");if(Array.isArray($$a)){var $$v="+(r?"_n("+i+")":i)+",$$i=_i($$a,$$v);if($$el.checked){$$i<0&&("+Br(t,"$$a.concat([$$v])")+")}else{$$i>-1&&("+Br(t,"$$a.slice(0,$$i).concat($$a.slice($$i+1))")+")}}else{"+Br(t,"$$c")+"}",null,!0)}(e,r,i);else if("input"===o&&"radio"===a)!function(e,t,n){var r=n&&n.number,i=Ir(e,"value")||"null";Er(e,"checked","_q("+t+","+(i=r?"_n("+i+")":i)+")"),Mr(e,"change",Br(t,i),null,!0)}(e,r,i);else if("input"===o||"textarea"===o)!function(e,t,n){var r=e.attrsMap.type,i=n||{},o=i.lazy,a=i.number,s=i.trim,c=!o&&"range"!==r,u=o?"change":"range"===r?Wr:"input",l="$event.target.value";s&&(l="$event.target.value.trim()"),a&&(l="_n("+l+")");var f=Br(t,l);c&&(f="if($event.target.composing)return;"+f),Er(e,"value","("+t+")"),Mr(e,u,f,null,!0),(s||a)&&Mr(e,"blur","$forceUpdate()")}(e,r,i);else if(!F.isReservedTag(o))return Hr(e,r,i),!1;return!0},text:function(e,t){t.value&&Er(e,"textContent","_s("+t.value+")",t)},html:function(e,t){t.value&&Er(e,"innerHTML","_s("+t.value+")",t)}},isPreTag:function(e){return"pre"===e},isUnaryTag:bo,mustUseProp:jn,canBeLeftOpenTag:$o,isReservedTag:Wn,getTagNamespace:Zn,staticKeys:function(e){return e.reduce(function(e,t){return e.concat(t.staticKeys||[])},[]).join(",")}(ba)},xa=g(function(e){return p("type,tag,attrsList,attrsMap,plain,parent,children,attrs,start,end,rawAttrsMap"+(e?","+e:""))});function ka(e,t){e&&($a=xa(t.staticKeys||""),wa=t.isReservedTag||T,function e(t){t.static=function(e){if(2===e.type)return!1;if(3===e.type)return!0;return!(!e.pre&&(e.hasBindings||e.if||e.for||d(e.tag)||!wa(e.tag)||function(e){for(;e.parent;){if("template"!==(e=e.parent).tag)return!1;if(e.for)return!0}return!1}(e)||!Object.keys(e).every($a)))}(t);if(1===t.type){if(!wa(t.tag)&&"slot"!==t.tag&&null==t.attrsMap["inline-template"])return;for(var n=0,r=t.children.length;n|^function(?:\s+[\w$]+)?\s*\(/,Oa=/\([^)]*?\);*$/,Sa=/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['[^']*?']|\["[^"]*?"]|\[\d+]|\[[A-Za-z_$][\w$]*])*$/,Ta={esc:27,tab:9,enter:13,space:32,up:38,left:37,right:39,down:40,delete:[8,46]},Ea={esc:["Esc","Escape"],tab:"Tab",enter:"Enter",space:[" ","Spacebar"],up:["Up","ArrowUp"],left:["Left","ArrowLeft"],right:["Right","ArrowRight"],down:["Down","ArrowDown"],delete:["Backspace","Delete","Del"]},Na=function(e){return"if("+e+")return null;"},ja={stop:"$event.stopPropagation();",prevent:"$event.preventDefault();",self:Na("$event.target !== $event.currentTarget"),ctrl:Na("!$event.ctrlKey"),shift:Na("!$event.shiftKey"),alt:Na("!$event.altKey"),meta:Na("!$event.metaKey"),left:Na("'button' in $event && $event.button !== 0"),middle:Na("'button' in $event && $event.button !== 1"),right:Na("'button' in $event && $event.button !== 2")};function Da(e,t){var n=t?"nativeOn:":"on:",r="",i="";for(var o in e){var a=La(e[o]);e[o]&&e[o].dynamic?i+=o+","+a+",":r+='"'+o+'":'+a+","}return r="{"+r.slice(0,-1)+"}",i?n+"_d("+r+",["+i.slice(0,-1)+"])":n+r}function La(e){if(!e)return"function(){}";if(Array.isArray(e))return"["+e.map(function(e){return La(e)}).join(",")+"]";var t=Sa.test(e.value),n=Aa.test(e.value),r=Sa.test(e.value.replace(Oa,""));if(e.modifiers){var i="",o="",a=[];for(var s in e.modifiers)if(ja[s])o+=ja[s],Ta[s]&&a.push(s);else if("exact"===s){var c=e.modifiers;o+=Na(["ctrl","shift","alt","meta"].filter(function(e){return!c[e]}).map(function(e){return"$event."+e+"Key"}).join("||"))}else a.push(s);return a.length&&(i+=function(e){return"if(!$event.type.indexOf('key')&&"+e.map(Ma).join("&&")+")return null;"}(a)),o&&(i+=o),"function($event){"+i+(t?"return "+e.value+"($event)":n?"return ("+e.value+")($event)":r?"return "+e.value:e.value)+"}"}return t||n?e.value:"function($event){"+(r?"return "+e.value:e.value)+"}"}function Ma(e){var t=parseInt(e,10);if(t)return"$event.keyCode!=="+t;var n=Ta[e],r=Ea[e];return"_k($event.keyCode,"+JSON.stringify(e)+","+JSON.stringify(n)+",$event.key,"+JSON.stringify(r)+")"}var Ia={on:function(e,t){e.wrapListeners=function(e){return"_g("+e+","+t.value+")"}},bind:function(e,t){e.wrapData=function(n){return"_b("+n+",'"+e.tag+"',"+t.value+","+(t.modifiers&&t.modifiers.prop?"true":"false")+(t.modifiers&&t.modifiers.sync?",true":"")+")"}},cloak:S},Fa=function(e){this.options=e,this.warn=e.warn||Sr,this.transforms=Tr(e.modules,"transformCode"),this.dataGenFns=Tr(e.modules,"genData"),this.directives=A(A({},Ia),e.directives);var t=e.isReservedTag||T;this.maybeComponent=function(e){return!!e.component||!t(e.tag)},this.onceId=0,this.staticRenderFns=[],this.pre=!1};function Pa(e,t){var n=new Fa(t);return{render:"with(this){return "+(e?Ra(e,n):'_c("div")')+"}",staticRenderFns:n.staticRenderFns}}function Ra(e,t){if(e.parent&&(e.pre=e.pre||e.parent.pre),e.staticRoot&&!e.staticProcessed)return Ha(e,t);if(e.once&&!e.onceProcessed)return Ba(e,t);if(e.for&&!e.forProcessed)return za(e,t);if(e.if&&!e.ifProcessed)return Ua(e,t);if("template"!==e.tag||e.slotTarget||t.pre){if("slot"===e.tag)return function(e,t){var n=e.slotName||'"default"',r=qa(e,t),i="_t("+n+(r?","+r:""),o=e.attrs||e.dynamicAttrs?Ga((e.attrs||[]).concat(e.dynamicAttrs||[]).map(function(e){return{name:b(e.name),value:e.value,dynamic:e.dynamic}})):null,a=e.attrsMap["v-bind"];!o&&!a||r||(i+=",null");o&&(i+=","+o);a&&(i+=(o?"":",null")+","+a);return i+")"}(e,t);var n;if(e.component)n=function(e,t,n){var r=t.inlineTemplate?null:qa(t,n,!0);return"_c("+e+","+Va(t,n)+(r?","+r:"")+")"}(e.component,e,t);else{var r;(!e.plain||e.pre&&t.maybeComponent(e))&&(r=Va(e,t));var i=e.inlineTemplate?null:qa(e,t,!0);n="_c('"+e.tag+"'"+(r?","+r:"")+(i?","+i:"")+")"}for(var o=0;o>>0}(a):"")+")"}(e,e.scopedSlots,t)+","),e.model&&(n+="model:{value:"+e.model.value+",callback:"+e.model.callback+",expression:"+e.model.expression+"},"),e.inlineTemplate){var o=function(e,t){var n=e.children[0];if(n&&1===n.type){var r=Pa(n,t.options);return"inlineTemplate:{render:function(){"+r.render+"},staticRenderFns:["+r.staticRenderFns.map(function(e){return"function(){"+e+"}"}).join(",")+"]}"}}(e,t);o&&(n+=o+",")}return n=n.replace(/,$/,"")+"}",e.dynamicAttrs&&(n="_b("+n+',"'+e.tag+'",'+Ga(e.dynamicAttrs)+")"),e.wrapData&&(n=e.wrapData(n)),e.wrapListeners&&(n=e.wrapListeners(n)),n}function Ka(e){return 1===e.type&&("slot"===e.tag||e.children.some(Ka))}function Ja(e,t){var n=e.attrsMap["slot-scope"];if(e.if&&!e.ifProcessed&&!n)return Ua(e,t,Ja,"null");if(e.for&&!e.forProcessed)return za(e,t,Ja);var r=e.slotScope===ca?"":String(e.slotScope),i="function("+r+"){return "+("template"===e.tag?e.if&&n?"("+e.if+")?"+(qa(e,t)||"undefined")+":undefined":qa(e,t)||"undefined":Ra(e,t))+"}",o=r?"":",proxy:true";return"{key:"+(e.slotTarget||'"default"')+",fn:"+i+o+"}"}function qa(e,t,n,r,i){var o=e.children;if(o.length){var a=o[0];if(1===o.length&&a.for&&"template"!==a.tag&&"slot"!==a.tag){var s=n?t.maybeComponent(a)?",1":",0":"";return""+(r||Ra)(a,t)+s}var c=n?function(e,t){for(var n=0,r=0;r':'
',ts.innerHTML.indexOf(" ")>0}var os=!!z&&is(!1),as=!!z&&is(!0),ss=g(function(e){var t=Yn(e);return t&&t.innerHTML}),cs=wn.prototype.$mount;return wn.prototype.$mount=function(e,t){if((e=e&&Yn(e))===document.body||e===document.documentElement)return this;var n=this.$options;if(!n.render){var r=n.template;if(r)if("string"==typeof r)"#"===r.charAt(0)&&(r=ss(r));else{if(!r.nodeType)return this;r=r.innerHTML}else e&&(r=function(e){if(e.outerHTML)return e.outerHTML;var t=document.createElement("div");return t.appendChild(e.cloneNode(!0)),t.innerHTML}(e));if(r){var i=rs(r,{outputSourceRange:!1,shouldDecodeNewlines:os,shouldDecodeNewlinesForHref:as,delimiters:n.delimiters,comments:n.comments},this),o=i.render,a=i.staticRenderFns;n.render=o,n.staticRenderFns=a}}return cs.call(this,e,t)},wn.compile=rs,wn}); \ No newline at end of file diff --git a/package/lienol/luci-app-ssr-mudb-server/luasrc/controller/ssr_mudb_server.lua b/package/lienol/luci-app-ssr-mudb-server/luasrc/controller/ssr_mudb_server.lua deleted file mode 100644 index 3acadf4158..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/luasrc/controller/ssr_mudb_server.lua +++ /dev/null @@ -1,190 +0,0 @@ --- Copyright 2018-2020 Lienol -module("luci.controller.ssr_mudb_server", package.seeall) -local http = require "luci.http" -local jsonc = require "luci.jsonc" - -function index() - if not nixio.fs.access("/etc/config/ssr_mudb_server") then return end - entry({"admin", "vpn"}, firstchild(), "VPN", 45).dependent = false - if nixio.fs.access("/usr/share/ssr_mudb_server") then - entry({"admin", "vpn", "ssr_mudb_server"}, cbi("ssr_mudb_server/index"), _("SSR MuDB Server"), 2).dependent = true - end - - entry({"admin", "vpn", "ssr_mudb_server", "user"}, template("ssr_mudb_server/user")).leaf = true - entry({"admin", "vpn", "ssr_mudb_server", "config"}, cbi("ssr_mudb_server/config")).leaf = true - entry({"admin", "vpn", "ssr_mudb_server", "status"}, call("status")).leaf = true - entry({"admin", "vpn", "ssr_mudb_server", "user_save"}, call("user_save")).leaf = true - entry({"admin", "vpn", "ssr_mudb_server", "user_list"}, call("user_list")).leaf = true - entry({"admin", "vpn", "ssr_mudb_server", "user_get"}, call("user_get")).leaf = true - entry({"admin", "vpn", "ssr_mudb_server", "get_link"}, call("get_link")).leaf = true - entry({"admin", "vpn", "ssr_mudb_server", "clear_traffic"}, call("clear_traffic")).leaf = true - entry({"admin", "vpn", "ssr_mudb_server", "clear_traffic_all_users"}, call("clear_traffic_all_users")).leaf = true - entry({"admin", "vpn", "ssr_mudb_server", "remove_user"}, call("remove_user")).leaf = true - entry({"admin", "vpn", "ssr_mudb_server", "get_log"}, call("get_log")).leaf = true - entry({"admin", "vpn", "ssr_mudb_server", "clear_log"}, call("clear_log")).leaf = true -end - -local function http_write_json(content) - http.prepare_content("application/json") - http.write_json(content or {code = 1}) -end - -local function get_config_path() - return luci.sys.exec("echo -n $(cat /usr/share/ssr_mudb_server/userapiconfig.py | grep 'MUDB_FILE' | cut -d \"'\" -f 2)") -end - -local function get_config_json() - return luci.sys.exec("cat " .. get_config_path()) or "[]" -end - -function status() - local e = {} - e.status = luci.sys.call("ps -w | grep -v grep | grep '/usr/share/ssr_mudb_server/server.py' >/dev/null") == 0 - http_write_json(e) -end - -function get_link() - local e = {} - local link = luci.sys.exec("cd /usr/share/ssr_mudb_server && python3 mujson_mgr.py -l -p " .. luci.http.formvalue("port") .. " | sed -n '$p'"):gsub("^%s*(.-)%s*$", "%1") - if link ~= "" then e.link = link end - http_write_json(e) -end - -function clear_traffic() - local e = {} - e.status = luci.sys.call("cd /usr/share/ssr_mudb_server && python3 mujson_mgr.py -c -p '" .. luci.http.formvalue("port") .. "' >/dev/null") == 0 - http_write_json(e) -end - -function clear_traffic_all_users() - local e = {} - e.status = luci.sys.call("/usr/share/ssr_mudb_server/clear_traffic_all_users.sh >/dev/null") == 0 - http_write_json(e) -end - -function user_list() - luci.http.prepare_content("application/json") - luci.http.write(get_config_json()) -end - -function user_save() - local result = {code = 0} - local action = luci.http.formvalue("action") - local json_str = luci.http.formvalue("json") - if action and action == "add" or action == "edit" then - local user = jsonc.parse(json_str) - if user then - local json = jsonc.parse(get_config_json()) - if json then - local port = user.port - local is_exist_port = 0 - for index = 1, table.maxn(json) do - if json[index].port == tonumber(port) then - is_exist_port = 1 - if user.old_port and user.old_port == tonumber(port) then - is_exist_port = 0 - end - break - end - end - if is_exist_port == 0 then - if action == "add" then - local new_user = { - enable = tonumber(user.enable) or 0, - user = user.user or user.port, - port = tonumber(user.port), - passwd = user.passwd, - method = user.method, - protocol = user.protocol, - obfs = user.obfs, - protocol_param = user.protocol_param or "2", - speed_limit_per_con = tonumber(user.speed_limit_per_con) or 0, - speed_limit_per_user = tonumber(user.speed_limit_per_user) or 0, - forbidden_port = user.forbidden_port or "", - transfer_enable = tonumber(user.transfer_enable) or 1073741824, - d = 0, - u = 0 - } - table.insert(json, new_user) - elseif action == "edit" then - for index = 1, table.maxn(json) do - if json[index].port == tonumber(user.old_port) then - json[index].enable = tonumber(user.enable) or 0 - json[index].user = user.user - json[index].port = tonumber(user.port) - json[index].passwd = user.passwd - json[index].method = user.method - json[index].protocol = user.protocol - json[index].obfs = user.obfs - json[index].protocol_param = user.protocol_param - json[index].speed_limit_per_con = tonumber(user.speed_limit_per_con) - json[index].speed_limit_per_user = tonumber(user.speed_limit_per_user) - json[index].forbidden_port = user.forbidden_port - json[index].transfer_enable = tonumber(user.transfer_enable) - break - end - end - end - local f, err = io.open(get_config_path(), "w") - if f and err == nil then - f:write(jsonc.stringify(json, 1)) - f:close() - luci.sys.call("/etc/init.d/ssr_mudb_server restart") - result = {code = 1} - end - else - result.msg = "端口已存在!" - end - end - end - end - http_write_json(result) -end - -function user_get() - local result = {} - local port = luci.http.formvalue("port") - local str = get_config_json() - local json = jsonc.parse(str) - if port and str and json then - for index = 1, table.maxn(json) do - local o = json[index] - if o.port == tonumber(port) then - result = o - break - end - end - end - http_write_json(result) -end - -function remove_user() - local port = luci.http.formvalue("port") - local str = get_config_json() - local json = jsonc.parse(str) - if port and str and json then - for index = 1, table.maxn(json) do - local o = json[index] - if o.port == tonumber(port) then - json[index] = nil - break - end - end - local f, err = io.open(get_config_path(), "w") - if f and err == nil then - f:write(jsonc.stringify(json, 1)) - f:close() - end - luci.http.status = 200 - else - luci.http.status = 500 - end -end - -function get_log() - luci.http.write(luci.sys.exec("[ -f '/var/log/ssr_mudb_server.log' ] && cat /var/log/ssr_mudb_server.log")) -end - -function clear_log() - luci.sys.call("echo '' > /var/log/ssr_mudb_server.log") -end diff --git a/package/lienol/luci-app-ssr-mudb-server/luasrc/model/cbi/ssr_mudb_server/index.lua b/package/lienol/luci-app-ssr-mudb-server/luasrc/model/cbi/ssr_mudb_server/index.lua deleted file mode 100644 index e39b8860b4..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/luasrc/model/cbi/ssr_mudb_server/index.lua +++ /dev/null @@ -1,51 +0,0 @@ -local appname = "ssr_mudb_server" -local jsonc = require "luci.jsonc" - -a = Map(appname, translate("ShadowsocksR MuDB Server")) - -t = a:section(TypedSection, "global", translate("Global Settings")) -t.anonymous = true -t.addremove = false - -t:append(Template(appname .. "/status")) - -e = t:option(Flag, "enable", translate("Enable")) -e.rmempty = false - -e = t:option(Flag, "auto_clear_transfer", translate("Enable Auto Clear Traffic")) -e.default = 0 -e.rmempty = false - -e = t:option(Value, "auto_clear_transfer_time", translate("Clear Traffic Time Interval"), translate("*,*,*,*,* is Min Hour Day Mon Week")) -e.default = "0,2,1,*,*" -e:depends("auto_clear_transfer", 1) - -a:append(Template(appname .. "/users")) - -local apply = luci.http.formvalue("cbi.apply") -if apply then - for key, val in pairs(luci.http.formvalue()) do - if key:find("ssr_mudb_server_") == 1 then - local port = key:gsub("ssr_mudb_server_",""):gsub(".enable","") - local config_path = luci.sys.exec("echo -n $(cat /usr/share/ssr_mudb_server/userapiconfig.py | grep 'MUDB_FILE' | cut -d \"'\" -f 2)") - local str = luci.sys.exec("cat " .. config_path) or "[]" - local json = jsonc.parse(str) - if port and str and json then - for index = 1, table.maxn(json) do - local o = json[index] - if o.port == tonumber(port) then - json[index].enable = tonumber(val) - break - end - end - local f, err = io.open(config_path, "w") - if f and err == nil then - f:write(jsonc.stringify(json, 1)) - f:close() - end - end - end - end -end - -return a diff --git a/package/lienol/luci-app-ssr-mudb-server/luasrc/view/ssr_mudb_server/status.htm b/package/lienol/luci-app-ssr-mudb-server/luasrc/view/ssr_mudb_server/status.htm deleted file mode 100644 index d160214335..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/luasrc/view/ssr_mudb_server/status.htm +++ /dev/null @@ -1,26 +0,0 @@ -<% -local ipkg = require "luci.model.ipkg" --%> - -
- -
<%:Collecting data...%>
-
- - diff --git a/package/lienol/luci-app-ssr-mudb-server/luasrc/view/ssr_mudb_server/user.htm b/package/lienol/luci-app-ssr-mudb-server/luasrc/view/ssr_mudb_server/user.htm deleted file mode 100644 index 6d15f9e2c4..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/luasrc/view/ssr_mudb_server/user.htm +++ /dev/null @@ -1,258 +0,0 @@ -<%+header%> -<% --- Copyright (C) 2018-2020 Lienol -%> - -
-
-

ShadowsocksR MuDB {{title}}

-
-
- -
- -
- - -
-
- -
- -
- -
-
- -
- -
- - -
-
- -
- -
- -
-
- -
- -
- -
-
- -
- -
- -
-
- -
- -
- -
-
- -
- -
- -
-
- 同一时间能链接的客户端数量(多端口模式,每个端口都是独立计算),建议最少 2个。 -
-
-
- -
- -
- -
-
- 单线程的限速上限,多线程即无效。0代表不限速。(单位:KB/S) -
-
-
- -
- -
- -
-
- 总速度限速上限,单个端口整体限速。0代表不限速。(单位:KB/S) -
-
-
- -
- -
- -
-
- 例如不允许访问 25端口,用户就无法通过SSR代理访问邮件端口25了,如果禁止了 80,443 那么用户将无法正常访问 http/https 网站。
封禁单个端口格式: - 25
封禁多个端口格式: 23,465
封禁端口段格式: 233-266
封禁多种格式端口: 25,465,233-666 -
-
-
- -
- -
- -
-
- 可使用的总流量上限(单位: GB, 1-838868),0代表无限 -
-
-
-
-
-
-
-
- - -
-
-
- - -<%+footer%> \ No newline at end of file diff --git a/package/lienol/luci-app-ssr-mudb-server/luasrc/view/ssr_mudb_server/users.htm b/package/lienol/luci-app-ssr-mudb-server/luasrc/view/ssr_mudb_server/users.htm deleted file mode 100644 index 2365f46be9..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/luasrc/view/ssr_mudb_server/users.htm +++ /dev/null @@ -1,144 +0,0 @@ -<% --- Copyright (C) 2018-2020 Lienol -%> - -
-

{{title}}

-
- - - - - - - - - - - - - - - -
启用备注端口禁止端口设备数限制单线程限速总限速已用流量可用流量
-
- -
-
- 日志 - - -
-
- - \ No newline at end of file diff --git a/package/lienol/luci-app-ssr-mudb-server/po/zh-cn/ssr_mudb_server.po b/package/lienol/luci-app-ssr-mudb-server/po/zh-cn/ssr_mudb_server.po deleted file mode 100644 index bb02122cfd..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/po/zh-cn/ssr_mudb_server.po +++ /dev/null @@ -1,152 +0,0 @@ -msgid "ShadowsocksR MuDB Server" -msgstr "ShadowsocksR MuDB 服务器" - -msgid "SSR MuDB Server" -msgstr "SSR MuDB 服务器" - -msgid "Global Settings" -msgstr "全局设置" - -msgid "Server Config" -msgstr "服务器配置" - -msgid "Users Manager" -msgstr "用户管理" - -msgid "Remarks" -msgstr "备注" - -msgid "Port" -msgstr "端口" - -msgid "Password" -msgstr "密码" - -msgid "Encrypt Method" -msgstr "加密" - -msgid "Protocol" -msgstr "协议" - -msgid "Protocol Param" -msgstr "协议参数" - -msgid "Obfs" -msgstr "混淆" - -msgid "Obfs Param" -msgstr "混淆参数" - -msgid "Connection Timeout" -msgstr "连接超时时间" - -msgid "redirect" -msgstr "重定向" - -msgid "Fast Open" -msgstr "快速打开" - -msgid "UDP Forward" -msgstr "UDP转发" - -msgid "Null" -msgstr "无" - -msgid "No Speed Limit" -msgstr "不限速" - -msgid "Forbidden Port" -msgstr "禁止的端口" - -msgid "Device Limit" -msgstr "设备数限制" - -msgid "Speed Limit Per Con" -msgstr "单线程限速" - -msgid "Speed Limit Per User" -msgstr "总限速" - -msgid "Available Total Flow" -msgstr "可用总流量" - -msgid "Infinite" -msgstr "无限" - -msgid "Used Upload Traffic" -msgstr "已用上传流量" - -msgid "Used Download Traffic" -msgstr "已用下载流量" - -msgid "Used Total Traffic" -msgstr "已用总流量" - -msgid "SSR Link" -msgstr "SSR链接" - -msgid "GET" -msgstr "获取" - -msgid "Clear Traffic" -msgstr "清空流量" - -msgid "Clear All Users Traffic" -msgstr "清空所有用户流量" - -msgid "Enable Auto Clear Traffic" -msgstr "启用自动清空流量" - -msgid "Clear Traffic Time Interval" -msgstr "流量清空时间间隔" - -msgid "*,*,*,*,* is Min Hour Day Mon Week" -msgstr "*,*,*,*,* 分别对应 分钟 小时 日份 月份 星期
0,2,1,*,* 代表 每月1日2点0分
0,2,15,*,* 代表 每月15日2点0分
0,2,*/7,*,* 代表 每7天2点0分
0,2,*,*,0 代表 每个星期日(7)
0,2,*,*,3 代表 每个星期三(3)" - -msgid "Number of clients that can be linked at the same time (multi-port mode, each port is calculated independently), a minimum of 2 is recommended." -msgstr "同一时间能链接的客户端数量(多端口模式,每个端口都是独立计算),建议最少 2个。" - -msgid "Single thread speed limit upper limit, multithreading is invalid. Zero means no speed limit. (unit: KB/S)" -msgstr "单线程的限速上限,多线程即无效。0代表不限速。(单位:KB/S)" - -msgid "Total speed limit upper limit, single port overall speed limit. Zero means no speed limit. (unit: KB/S)" -msgstr "总速度限速上限,单个端口整体限速。0代表不限速。(单位:KB/S)" - -msgid "For example, if port 25 is not allowed, the user will not be able to access the mail port 25 through the SSR agent. If 80,443 is disabled, the user will not be able to access the HTTP/HTTPS website normally.
blocked single port format: 25
blocked multiple port format: 23,465
blocked port format: 233-266
blocked multiple port format: 25,465,233-666" -msgstr "例如不允许访问 25端口,用户就无法通过SSR代理访问邮件端口25了,如果禁止了 80,443 那么用户将无法正常访问 http/https 网站。
封禁单个端口格式: 25
封禁多个端口格式: 23,465
封禁端口段格式: 233-266
封禁多种格式端口: 25,465,233-666" - -msgid "Maximum amount of total traffic available (GB, 1-838868), Zero means infinite." -msgstr "可使用的总流量上限(单位: GB, 1-838868),0代表无限" - -msgid "Alter ID" -msgstr "额外ID(AlterID)" - -msgid "User Level" -msgstr "用户等级(Level)" - -msgid "Transport" -msgstr "传输方式" - -msgid "Camouflage Type" -msgstr "伪装类型" - -msgid "Enabled" -msgstr "启用" - -msgid "Status" -msgstr "状态" - -msgid "Current Condition" -msgstr "当前状态" - -msgid "please Install the python3" -msgstr "请安装python3环境" - -msgid "NOT INSTALLED" -msgstr "未安装" - -msgid "NOT RUNNING" -msgstr "未运行" - -msgid "RUNNING" -msgstr "运行中" \ No newline at end of file diff --git a/package/lienol/luci-app-ssr-mudb-server/root/etc/config/ssr_mudb_server b/package/lienol/luci-app-ssr-mudb-server/root/etc/config/ssr_mudb_server deleted file mode 100644 index 5d8a87c452..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/etc/config/ssr_mudb_server +++ /dev/null @@ -1,4 +0,0 @@ - -config global - option auto_clear_transfer '0' - option enable '0' diff --git a/package/lienol/luci-app-ssr-mudb-server/root/etc/config/ssr_mudb_server.json b/package/lienol/luci-app-ssr-mudb-server/root/etc/config/ssr_mudb_server.json deleted file mode 100644 index 9f29614013..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/etc/config/ssr_mudb_server.json +++ /dev/null @@ -1,18 +0,0 @@ -[ - { - "u": 0, - "method": "none", - "user": "test", - "enable": 1, - "forbidden_port": "", - "transfer_enable": 900727656415232, - "passwd": "123456", - "speed_limit_per_user": 0, - "port": 50005, - "d": 0, - "protocol": "auth_chain_a", - "obfs": "tls1.2_ticket_auth", - "protocol_param": "10", - "speed_limit_per_con": 0 - } - ] \ No newline at end of file diff --git a/package/lienol/luci-app-ssr-mudb-server/root/etc/init.d/ssr_mudb_server b/package/lienol/luci-app-ssr-mudb-server/root/etc/init.d/ssr_mudb_server deleted file mode 100755 index 70a5801438..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/etc/init.d/ssr_mudb_server +++ /dev/null @@ -1,104 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2018-2020 Lienol - -START=99 - -CONFIG=ssr_mudb_server -ssr_path=/usr/share/$CONFIG - -config_t_get() { - local index=0 - [ -n "$4" ] && index=$4 - local ret=$(uci -q get $CONFIG.@$1[$index].$2 2>/dev/null) - echo ${ret:=$3} -} - -add_rule() { - iptables -N SSR_MUDB-SERVER - iptables -I INPUT -j SSR_MUDB-SERVER - lua $ssr_path/firewall.lua -} - -del_rule() { - count=$(iptables -n -L INPUT 2>/dev/null | grep -c "SSR_MUDB-SERVER") - if [ -n "$count" ]; then - until [ "$count" = 0 ] - do - rules=$(iptables -n -L INPUT --line-num 2>/dev/null | grep "SSR_MUDB-SERVER" | awk '{print $1}') - for rule in $rules - do - iptables -D INPUT $rule 2>/dev/null - break - done - count=$(expr $count - 1) - done - fi - iptables -F SSR_MUDB-SERVER 2>/dev/null && iptables -X SSR_MUDB-SERVER 2>/dev/null -} - -gen_include() { - echo '#!/bin/sh' > /var/etc/$CONFIG.include - extract_rules() { - echo "*$1" - iptables-save -t $1 | grep "SSR_MUDB-SERVER" | \ - sed -e "s/^-A \(INPUT\)/-I \1 1/" - echo 'COMMIT' - } - cat <<-EOF >> /var/etc/$CONFIG.include - iptables-save -c | grep -v "SSR_MUDB-SERVER" | iptables-restore -c - iptables-restore -n <<-EOT - $(extract_rules filter) - EOT - EOF - return 0 -} - -set_ssr_python_crontab() { - if [ "$1" -eq 1 ];then - auto_clear_transfer=$(config_t_get global auto_clear_transfer 0) - if [ "$auto_clear_transfer" = "0" ];then - sed -i '/clear_traffic_all_users.sh/d' /etc/crontabs/root >/dev/null 2>&1 & - else - auto_clear_transfer_time=$(config_t_get global auto_clear_transfer_time) - [ -n "$auto_clear_transfer_time" ] && auto_clear_transfer_time=$(echo $auto_clear_transfer_time | tr ',' ' ') - echo "$auto_clear_transfer_time $ssr_path/clear_traffic_all_users.sh >/dev/null 2>&1" >> /etc/crontabs/root - fi - else - sed -i '/clear_traffic_all_users.sh/d' /etc/crontabs/root >/dev/null 2>&1 & - fi - /etc/init.d/cron restart -} - -start_ssr_python_server() { - /usr/bin/python3 $ssr_path/server.py >> /var/log/$CONFIG.log 2>&1 & - set_ssr_python_crontab 1 - add_rule - gen_include -} - -stop_ssr_python_server() { - ps -w | grep "$ssr_path/server.py" | grep -v "grep" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 & - set_ssr_python_crontab 0 - del_rule - rm -rf /var/log/$CONFIG.log /var/etc/$CONFIG.include -} - -start() { - enable=$(config_t_get global enable 0) - if [ "$enable" -eq 1 ];then - users_config=$(cat $ssr_path/userapiconfig.py | grep "MUDB_FILE" | cut -d "'" -f 2) - [ -n "$users_config" ] && cp -rf $users_config $ssr_path/mudb_backup.json - start_ssr_python_server - else - stop_ssr_python_server - fi -} - -stop() { - stop_ssr_python_server -} - -restart() { - stop - start -} \ No newline at end of file diff --git a/package/lienol/luci-app-ssr-mudb-server/root/etc/uci-defaults/luci-app-ssr-mudb-server b/package/lienol/luci-app-ssr-mudb-server/root/etc/uci-defaults/luci-app-ssr-mudb-server deleted file mode 100644 index 157e67d900..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/etc/uci-defaults/luci-app-ssr-mudb-server +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete firewall.ssr_mudb_server - set firewall.ssr_mudb_server=include - set firewall.ssr_mudb_server.type=script - set firewall.ssr_mudb_server.path=/var/etc/ssr_mudb_server.include - set firewall.ssr_mudb_server.reload=1 -EOF - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@ssr_mudb_server[-1] - add ucitrack ssr_mudb_server - set ucitrack.@ssr_mudb_server[-1].init=ssr_mudb_server - commit ucitrack -EOF - -chmod a+x /usr/share/ssr_mudb_server/* >/dev/null 2>&1 -cp -rf /usr/bin/python3 /usr/bin/python -rm -rf /tmp/luci-*cache -exit 0 diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/rpcd/acl.d/luci-app-ssr-mudb-server.json b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/rpcd/acl.d/luci-app-ssr-mudb-server.json deleted file mode 100644 index a03d0a18a2..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/rpcd/acl.d/luci-app-ssr-mudb-server.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "luci-app-ssr-mudb-server": { - "description": "Grant UCI access for luci-app-ssr-mudb-server", - "read": { - "uci": [ "ssr_mudb_server" ] - }, - "write": { - "uci": [ "ssr_mudb_server" ] - } - } -} diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/.travis.yml b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/.travis.yml deleted file mode 100644 index 3a1e734e3a..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/.travis.yml +++ /dev/null @@ -1,21 +0,0 @@ -language: python3 -python3: - - 2.6 - - 2.7 - - 3.3 - - 3.4 -cache: - directories: - - dante-1.4.0 -before_install: - - sudo apt-get update -qq - - sudo apt-get install -qq build-essential dnsutils iproute nginx bc - - sudo dd if=/dev/urandom of=/usr/share/nginx/www/file bs=1M count=10 - - sudo sh -c "echo '127.0.0.1 localhost' > /etc/hosts" - - sudo service nginx restart - - pip install pep8 pyflakes nose coverage PySocks cymysql - - sudo tests/socksify/install.sh - - sudo tests/libsodium/install.sh - - sudo tests/setup_tc.sh -script: - - tests/jenkins.sh diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/CHANGES b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/CHANGES deleted file mode 100644 index d1e813c63b..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/CHANGES +++ /dev/null @@ -1,342 +0,0 @@ -3.4.0 2017-07-27 -- add auth_chain_b -- add initmudbjson.sh -- allow set speed limit in runtime -- fix bugs & mem leak - -3.3.3 2017-06-03 -- add DNS cache -- add tls1.2_ticket_fastauth -- fix bugs - -3.3.2 2017-05-20 -- revert http reply -- refine tls1.2_ticket_auth error detector - -3.3.1 2017-05-18 -- fix stop script -- Async DNS query under UDP -- fix old version of OpenSSL -- http reply - -3.3.0 2017-05-11 -- connect_log include local addr & port -- fix auth_chain_a UDP bug -- add "additional_ports_only" -- add interface legendsockssr -- run with newest python3 version -- parse comment in hosts -- update mujson_mgr -- add cymysql setup script -- new speed tester -- fix leaks -- bugs fixed - -3.2.0 2017-04-27 -- add auth_chain_a -- remove auth_aes128, auth_sha1, auth_sha1_v2, verify_simple, auth_simple, verify_sha1 - -3.1.2 2017-04-07 -- display UID -- auto adjust TCP MSS - -3.1.1 2017-03-25 -- add "New session ticket" -- ignore bind 10.0.0.0/8 and 192.168.0.0/16 by default -- improve rand size under auth_aes128_* -- fix bugs - -3.1.0 2017-03-16 -- add "glzjinmod" interface -- rate limit -- add additional_ports in config - -3.0.4 2017-01-08 -- multi-user in single port - -3.0.1 2017-01-03 -- remove auth_aes128_*_compatible - -3.0.0 2016-12-23 -- http_simple fix bugs -- tls1.2_ticket_auth fix bug & defaule time diff set to 86400s - -2.9.7 2016-11-22 -- manage client with LRUCache -- catch bind error -- fix import error of resource on windows -- print RLIMIT_NOFILE -- always close cymysql objects -- add init script - -2.9.6 2016-10-17 -- tls1.2_ticket_auth random packet size - -2.9.5.1 2016-10-16 -- UDP bind address - -2.9.5 2016-10-13 -- add auth_aes128_md5 and auth_aes128_sha1 - -2.9.4 2016-10-11 -- sync client version - -2.6.13 2015-11-02 -- add protocol setting - -2.6.12 2015-10-27 -- IPv6 first -- Fix mem leaks -- auth_simple plugin -- remove FORCE_NEW_PROTOCOL -- optimize code - -2.6.11 2015-10-20 -- Obfs plugin -- Obfs parameters -- UDP over TCP -- TCP over UDP (experimental) -- Fix socket leaks -- Catch abnormal UDP package - -2.6.10 2015-06-08 -- Optimize LRU cache -- Refine logging - -2.6.9 2015-05-19 -- Fix a stability issue on Windows - -2.6.8 2015-02-10 -- Support multiple server ip on client side -- Support --version -- Minor fixes - -2.6.7 2015-02-02 -- Support --user -- Support CIDR format in --forbidden-ip -- Minor fixes - -2.6.6 2015-01-23 -- Fix a crash in forbidden list - -2.6.5 2015-01-18 -- Try both 32 bit and 64 bit dll on Windows - -2.6.4 2015-01-14 -- Also search lib* when searching libraries - -2.6.3 2015-01-12 -- Support --forbidden-ip to ban some IP, i.e. localhost -- Search OpenSSL and libsodium harder -- Now works on OpenWRT - -2.6.2 2015-01-03 -- Log client IP - -2.6.1 2014-12-26 -- Fix a problem with TCP Fast Open on local side -- Fix sometimes daemon_start returns wrong exit status - -2.6 2014-12-21 -- Add daemon support - -2.5 2014-12-11 -- Add salsa20 and chacha20 - -2.4.3 2014-11-10 -- Fix an issue on Python 3 -- Fix an issue with IPv6 - -2.4.2 2014-11-06 -- Fix command line arguments on Python 3 -- Support table on Python 3 -- Fix TCP Fast Open on Python 3 - -2.4.1 2014-11-01 -- Fix setup.py for non-utf8 locales on Python 3 - -2.4 2014-11-01 -- Python 3 support -- Performance improvement -- Fix LRU cache behavior - -2.3.2 2014-10-11 -- Fix OpenSSL on Windows - -2.3.1 2014-10-09 -- Does not require M2Crypto any more - -2.3 2014-09-23 -- Support CFB1, CFB8 and CTR mode of AES -- Do not require password config when using port_password -- Use SIGTERM instead of SIGQUIT on Windows - -2.2.2 2014-09-14 -- Fix when multiple DNS set, IPv6 only sites are broken - -2.2.1 2014-09-10 -- Support graceful shutdown -- Fix some bugs - -2.2.0 2014-09-09 -- Add RC4-MD5 encryption - -2.1.0 2014-08-10 -- Use only IPv4 DNS server -- Does not ship config.json -- Better error message - -2.0.12 2014-07-26 -- Support -q quiet mode -- Exit 0 when showing help with -h - -2.0.11 2014-07-12 -- Prefers IP addresses over hostnames, more friendly with socksify and openvpn - -2.0.10 2014-07-11 -- Fix UDP on local - -2.0.9 2014-07-06 -- Fix EWOULDBLOCK on Windows -- Fix Unicode config problem on some platforms - -2.0.8 2014-06-23 -- Use multiple DNS to query hostnames - -2.0.7 2014-06-21 -- Fix fastopen on local -- Fallback when fastopen is not available -- Add verbose logging mode -vv -- Verify if hostname is valid - -2.0.6 2014-06-19 -- Fix CPU 100% on POLL_HUP -- More friendly logging - -2.0.5 2014-06-18 -- Support a simple config format for multiple ports - -2.0.4 2014-06-12 -- Fix worker master - -2.0.3 2014-06-11 -- Fix table encryption with UDP - -2.0.2 2014-06-11 -- Add asynchronous DNS in TCP relay - -2.0.1 2014-06-05 -- Better logging -- Maybe fix bad file descriptor - -2.0 2014-06-05 -- Use a new event model -- Remove gevent -- Refuse to use default password -- Fix a problem when using multiple passwords with table encryption - -1.4.5 2014-05-24 -- Add timeout in TCP server -- Close sockets in master process - -1.4.4 2014-05-17 -- Support multiple workers - -1.4.3 2014-05-13 -- Fix Windows - -1.4.2 2014-05-10 -- Add salsa20-ctr cipher - -1.4.1 2014-05-03 -- Fix error log -- Fix EINPROGESS with some version of gevent - -1.4.0 2014-05-02 -- Adds UDP relay -- TCP fast open support on Linux 3.7+ - -1.3.7 2014-04-10 -- Fix a typo in help - -1.3.6 2014-04-10 -- Fix a typo in help - -1.3.5 2014-04-07 -- Add help -- Change default local binding address into 127.0.0.1 - -1.3.4 2014-02-17 -- Fix a bug when no config file exists -- Client now support multiple server ports and multiple server/port pairs -- Better error message with bad config.json format and wrong password - -1.3.3 2013-07-09 -- Fix default key length of rc2 - -1.3.2 2013-07-04 -- Server will listen at server IP specified in config -- Check config file and show some warning messages - -1.3.1 2013-06-29 -- Fix -c arg - -1.3.0 2013-06-22 -- Move to pypi - -1.2.3 2013-06-14 -- add bind address - -1.2.2 2013-05-31 -- local can listen at ::0 with -6 arg; bump 1.2.2 - -1.2.1 2013-05-23 -- Fix an OpenSSL crash - -1.2 2013-05-22 -- Use random iv, we finally have strong encryption - -1.1.1 2013-05-21 -- Add encryption, AES, blowfish, etc. - -1.1 2013-05-16 -- Support IPv6 addresses (type 4) -- Drop Python 2.5 support - -1.0 2013-04-03 -- Fix -6 IPv6 - -0.9.4 2013-03-04 -- Support Python 2.5 - -0.9.3 2013-01-14 -- Fix conn termination null data - -0.9.2 2013-01-05 -- Change default timeout - -0.9.1 2013-01-05 -- Add Travis-CI test - -0.9 2012-12-30 -- Replace send with sendall, fix FreeBSD - -0.6 2012-12-06 -- Support args - -0.5 2012-11-08 -- Fix encryption with negative md5sum - -0.4 2012-11-02 -- Move config into a JSON file -- Auto-detect config path - -0.3 2012-06-06 -- Move socks5 negotiation to local - -0.2 2012-05-11 -- Add -6 arg for IPv6 -- Fix socket.error - -0.1 2012-04-20 -- Initial version diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/CONTRIBUTING.md b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/CONTRIBUTING.md deleted file mode 100644 index fbdb9c11b2..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/CONTRIBUTING.md +++ /dev/null @@ -1,29 +0,0 @@ -How to Contribute -================= - -Pull Requests -------------- - -1. Pull requests are welcome. If you would like to add a large feature -or make a significant change, make sure to open an issue to discuss with -people first. -2. Follow PEP8. -3. Make sure to pass the unit tests. Write unit tests for new modules if -needed. - -Issues ------- - -1. Only bugs and feature requests are accepted here. -2. We'll only work on important features. If the feature you're asking only -benefits a few people, you'd better implement the feature yourself and send us -a pull request, or ask some of your friends to do so. -3. We don't answer questions of any other types here. Since very few people -are watching the issue tracker here, you'll probably get no help from here. -Read [Troubleshooting] and get help from forums or [mailing lists]. -4. Issues in languages other than English will be Google translated into English -later. - - -[Troubleshooting]: https://github.com/clowwindy/shadowsocks/wiki/Troubleshooting -[mailing lists]: https://groups.google.com/forum/#!forum/shadowsocks diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/Dockerfile b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/Dockerfile deleted file mode 100644 index 8ff409e2ba..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/Dockerfile +++ /dev/null @@ -1,31 +0,0 @@ -FROM alpine:3.6 - -ENV SERVER_ADDR 0.0.0.0 -ENV SERVER_PORT 51348 -ENV PASSWORD psw -ENV METHOD aes-128-ctr -ENV PROTOCOL auth_aes128_md5 -ENV PROTOCOLPARAM 32 -ENV OBFS tls1.2_ticket_auth_compatible -ENV TIMEOUT 300 -ENV DNS_ADDR 8.8.8.8 -ENV DNS_ADDR_2 8.8.4.4 - -ARG BRANCH=manyuser -ARG WORK=~ - - -RUN apk --no-cache add python3 \ - libsodium \ - wget - - -RUN mkdir -p $WORK && \ - wget -qO- --no-check-certificate https://github.com/shadowsocksr/shadowsocksr/archive/$BRANCH.tar.gz | tar -xzf - -C $WORK - - -WORKDIR $WORK/shadowsocksr-$BRANCH/shadowsocks - - -EXPOSE $SERVER_PORT -CMD python3 server.py -p $SERVER_PORT -k $PASSWORD -m $METHOD -O $PROTOCOL -o $OBFS -G $PROTOCOLPARAM diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/MANIFEST.in b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/MANIFEST.in deleted file mode 100644 index 1882dd7dce..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/MANIFEST.in +++ /dev/null @@ -1,3 +0,0 @@ -recursive-include shadowsocks *.py -include README.rst -include LICENSE diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/apiconfig.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/apiconfig.py deleted file mode 100644 index 682a0347c5..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/apiconfig.py +++ /dev/null @@ -1,15 +0,0 @@ -# Config -API_INTERFACE = 'sspanelv2' #mudbjson, sspanelv2, sspanelv3, sspanelv3ssr, glzjinmod, legendsockssr, muapiv2(not support) -UPDATE_TIME = 60 -SERVER_PUB_ADDR = '127.0.0.1' # mujson_mgr need this to generate ssr link - -#mudb -MUDB_FILE = '/etc/config/ssr_mudb_server.json' - -# Mysql -MYSQL_CONFIG = 'usermysql.json' - -# API -MUAPI_CONFIG = 'usermuapi.json' - - diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/asyncmgr.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/asyncmgr.py deleted file mode 100644 index 87f1c1bc28..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/asyncmgr.py +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -# Copyright (c) 2014 clowwindy -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -import time -import os -import socket -import struct -import re -import logging -from shadowsocks import common -from shadowsocks import lru_cache -from shadowsocks import eventloop -import server_pool -import Config - -class ServerMgr(object): - - def __init__(self): - self._loop = None - self._request_id = 1 - self._hosts = {} - self._hostname_status = {} - self._hostname_to_cb = {} - self._cb_to_hostname = {} - self._last_time = time.time() - self._sock = None - self._servers = None - - def add_to_loop(self, loop): - if self._loop: - raise Exception('already add to loop') - self._loop = loop - # TODO when dns server is IPv6 - self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, - socket.SOL_UDP) - self._sock.bind((Config.MANAGE_BIND_IP, Config.MANAGE_PORT)) - self._sock.setblocking(False) - loop.add(self._sock, eventloop.POLL_IN, self) - - def _handle_data(self, sock): - data, addr = sock.recvfrom(128) - #manage pwd:port:passwd:action - args = data.split(':') - if len(args) < 4: - return - if args[0] == Config.MANAGE_PASS: - if args[3] == '0': - server_pool.ServerPool.get_instance().cb_del_server(args[1]) - elif args[3] == '1': - server_pool.ServerPool.get_instance().new_server(args[1], args[2]) - - def handle_event(self, sock, fd, event): - if sock != self._sock: - return - if event & eventloop.POLL_ERR: - logging.error('mgr socket err') - self._loop.remove(self._sock) - self._sock.close() - # TODO when dns server is IPv6 - self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, - socket.SOL_UDP) - self._sock.setblocking(False) - self._loop.add(self._sock, eventloop.POLL_IN, self) - else: - self._handle_data(sock) - - def close(self): - if self._sock: - if self._loop: - self._loop.remove(self._sock) - self._sock.close() - self._sock = None - - -def test(): - pass - -if __name__ == '__main__': - test() diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/clear_traffic_all_users.sh b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/clear_traffic_all_users.sh deleted file mode 100755 index e4884372c9..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/clear_traffic_all_users.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -cd /usr/share/ssr_mudb_server -user_total=$(python3 mujson_mgr.py -l | wc -l) -[ $user_total -eq 0 ] && echo -e "没有发现用户,请检查 !" && exit 1 -for i in $(seq 1 $user_total) -do - port=$(python3 mujson_mgr.py -l | sed -n ${i}p | awk '{print $4}') - match_clear=$(python3 mujson_mgr.py -c -p "${port}") -done -exit diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/config.json b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/config.json deleted file mode 100644 index 55f12b5f4c..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/config.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "server": "0.0.0.0", - "server_ipv6": "::", - "server_port": 8388, - "local_address": "127.0.0.1", - "local_port": 1080, - - "password": "m", - "method": "aes-128-ctr", - "protocol": "auth_aes128_md5", - "protocol_param": "", - "obfs": "tls1.2_ticket_auth_compatible", - "obfs_param": "", - "speed_limit_per_con": 0, - "speed_limit_per_user": 0, - - "additional_ports" : {}, // only works under multi-user mode - "additional_ports_only" : false, // only works under multi-user mode - "timeout": 120, - "udp_timeout": 60, - "dns_ipv6": false, - "connect_verbose_info": 0, - "redirect": "", - "fast_open": false -} diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/configloader.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/configloader.py deleted file mode 100644 index cb0065e655..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/configloader.py +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/python3 -# -*- coding: UTF-8 -*- -import importloader - -g_config = None - -def load_config(): - global g_config - g_config = importloader.loads(['userapiconfig', 'apiconfig']) - -def get_config(): - return g_config - -load_config() - diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/db_transfer.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/db_transfer.py deleted file mode 100644 index 42098d738f..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/db_transfer.py +++ /dev/null @@ -1,631 +0,0 @@ -#!/usr/bin/python3 -# -*- coding: UTF-8 -*- - -import logging -import time -import sys -from server_pool import ServerPool -import traceback -from shadowsocks import common, shell, lru_cache, obfs -from configloader import load_config, get_config -import importloader - -switchrule = None -db_instance = None - -class TransferBase(object): - def __init__(self): - import threading - self.event = threading.Event() - self.key_list = ['port', 'u', 'd', 'transfer_enable', 'passwd', 'enable'] - self.last_get_transfer = {} #上一次的实际流量 - self.last_update_transfer = {} #上一次更新到的流量(小于等于实际流量) - self.force_update_transfer = set() #强制推入数据库的ID - self.port_uid_table = {} #端口到uid的映射(仅v3以上有用) - self.onlineuser_cache = lru_cache.LRUCache(timeout=60*30) #用户在线状态记录 - self.pull_ok = False #记录是否已经拉出过数据 - self.mu_ports = {} - - def load_cfg(self): - pass - - def push_db_all_user(self): - if self.pull_ok is False: - return - #更新用户流量到数据库 - last_transfer = self.last_update_transfer - curr_transfer = ServerPool.get_instance().get_servers_transfer() - #上次和本次的增量 - dt_transfer = {} - for id in self.force_update_transfer: #此表中的用户统计上次未计入的流量 - if id in self.last_get_transfer and id in last_transfer: - dt_transfer[id] = [self.last_get_transfer[id][0] - last_transfer[id][0], self.last_get_transfer[id][1] - last_transfer[id][1]] - - for id in curr_transfer.keys(): - if id in self.force_update_transfer or id in self.mu_ports: - continue - #算出与上次记录的流量差值,保存于dt_transfer表 - if id in last_transfer: - if curr_transfer[id][0] + curr_transfer[id][1] - last_transfer[id][0] - last_transfer[id][1] <= 0: - continue - dt_transfer[id] = [curr_transfer[id][0] - last_transfer[id][0], - curr_transfer[id][1] - last_transfer[id][1]] - else: - if curr_transfer[id][0] + curr_transfer[id][1] <= 0: - continue - dt_transfer[id] = [curr_transfer[id][0], curr_transfer[id][1]] - - #有流量的,先记录在线状态 - if id in self.last_get_transfer: - if curr_transfer[id][0] + curr_transfer[id][1] > self.last_get_transfer[id][0] + self.last_get_transfer[id][1]: - self.onlineuser_cache[id] = curr_transfer[id][0] + curr_transfer[id][1] - else: - self.onlineuser_cache[id] = curr_transfer[id][0] + curr_transfer[id][1] - - self.onlineuser_cache.sweep() - - update_transfer = self.update_all_user(dt_transfer) #返回有更新的表 - for id in update_transfer.keys(): #其增量加在此表 - if id not in self.force_update_transfer: #但排除在force_update_transfer内的 - last = self.last_update_transfer.get(id, [0,0]) - self.last_update_transfer[id] = [last[0] + update_transfer[id][0], last[1] + update_transfer[id][1]] - self.last_get_transfer = curr_transfer - for id in self.force_update_transfer: - if id in self.last_update_transfer: - del self.last_update_transfer[id] - if id in self.last_get_transfer: - del self.last_get_transfer[id] - self.force_update_transfer = set() - - def del_server_out_of_bound_safe(self, last_rows, rows): - #停止超流量的服务 - #启动没超流量的服务 - try: - switchrule = importloader.load('switchrule') - except Exception as e: - logging.error('load switchrule.py fail') - cur_servers = {} - new_servers = {} - allow_users = {} - mu_servers = {} - config = shell.get_config(False) - for row in rows: - try: - allow = switchrule.isTurnOn(row) and row['enable'] == 1 and row['u'] + row['d'] < row['transfer_enable'] - except Exception as e: - allow = False - - port = row['port'] - passwd = common.to_bytes(row['passwd']) - if hasattr(passwd, 'encode'): - passwd = passwd.encode('utf-8') - cfg = {'password': passwd} - if 'id' in row: - self.port_uid_table[row['port']] = row['id'] - - read_config_keys = ['method', 'obfs', 'obfs_param', 'protocol', 'protocol_param', 'forbidden_ip', 'forbidden_port', 'speed_limit_per_con', 'speed_limit_per_user'] - for name in read_config_keys: - if name in row and row[name]: - cfg[name] = row[name] - - merge_config_keys = ['password'] + read_config_keys - for name in cfg.keys(): - if hasattr(cfg[name], 'encode'): - try: - cfg[name] = cfg[name].encode('utf-8') - except Exception as e: - logging.warning('encode cfg key "%s" fail, val "%s"' % (name, cfg[name])) - - if port not in cur_servers: - cur_servers[port] = passwd - else: - logging.error('more than one user use the same port [%s]' % (port,)) - continue - - if 'protocol' in cfg and 'protocol_param' in cfg and common.to_str(cfg['protocol']) in obfs.mu_protocol(): - if '#' in common.to_str(cfg['protocol_param']): - mu_servers[port] = passwd - allow = True - - if allow: - if port not in mu_servers: - allow_users[port] = cfg - - cfgchange = False - if port in ServerPool.get_instance().tcp_servers_pool: - relay = ServerPool.get_instance().tcp_servers_pool[port] - for name in merge_config_keys: - if name in cfg and not self.cmp(cfg[name], relay._config[name]): - cfgchange = True - break - if not cfgchange and port in ServerPool.get_instance().tcp_ipv6_servers_pool: - relay = ServerPool.get_instance().tcp_ipv6_servers_pool[port] - for name in merge_config_keys: - if (name in cfg) and ((name not in relay._config) or not self.cmp(cfg[name], relay._config[name])): - cfgchange = True - break - - if port in mu_servers: - if ServerPool.get_instance().server_is_run(port) > 0: - if cfgchange: - logging.info('db stop server at port [%s] reason: config changed: %s' % (port, cfg)) - ServerPool.get_instance().cb_del_server(port) - self.force_update_transfer.add(port) - new_servers[port] = (passwd, cfg) - else: - self.new_server(port, passwd, cfg) - else: - if ServerPool.get_instance().server_is_run(port) > 0: - if config['additional_ports_only'] or not allow: - logging.info('db stop server at port [%s]' % (port,)) - ServerPool.get_instance().cb_del_server(port) - self.force_update_transfer.add(port) - else: - if cfgchange: - logging.info('db stop server at port [%s] reason: config changed: %s' % (port, cfg)) - ServerPool.get_instance().cb_del_server(port) - self.force_update_transfer.add(port) - new_servers[port] = (passwd, cfg) - - elif not config['additional_ports_only'] and allow and port > 0 and port < 65536 and ServerPool.get_instance().server_run_status(port) is False: - self.new_server(port, passwd, cfg) - - for row in last_rows: - if row['port'] in cur_servers: - pass - else: - logging.info('db stop server at port [%s] reason: port not exist' % (row['port'])) - ServerPool.get_instance().cb_del_server(row['port']) - self.clear_cache(row['port']) - if row['port'] in self.port_uid_table: - del self.port_uid_table[row['port']] - - if len(new_servers) > 0: - from shadowsocks import eventloop - self.event.wait(eventloop.TIMEOUT_PRECISION + eventloop.TIMEOUT_PRECISION / 2) - for port in new_servers.keys(): - passwd, cfg = new_servers[port] - self.new_server(port, passwd, cfg) - - logging.debug('db allow users %s \nmu_servers %s' % (allow_users, mu_servers)) - for port in mu_servers: - ServerPool.get_instance().update_mu_users(port, allow_users) - - self.mu_ports = mu_servers - - def clear_cache(self, port): - if port in self.force_update_transfer: del self.force_update_transfer[port] - if port in self.last_get_transfer: del self.last_get_transfer[port] - if port in self.last_update_transfer: del self.last_update_transfer[port] - - def new_server(self, port, passwd, cfg): - protocol = cfg.get('protocol', ServerPool.get_instance().config.get('protocol', 'origin')) - method = cfg.get('method', ServerPool.get_instance().config.get('method', 'None')) - obfs = cfg.get('obfs', ServerPool.get_instance().config.get('obfs', 'plain')) - logging.info('db start server at port [%s] pass [%s] protocol [%s] method [%s] obfs [%s]' % (port, passwd, protocol, method, obfs)) - ServerPool.get_instance().new_server(port, cfg) - - def cmp(self, val1, val2): - if type(val1) is bytes: - val1 = common.to_str(val1) - if type(val2) is bytes: - val2 = common.to_str(val2) - return val1 == val2 - - @staticmethod - def del_servers(): - for port in [v for v in ServerPool.get_instance().tcp_servers_pool.keys()]: - if ServerPool.get_instance().server_is_run(port) > 0: - ServerPool.get_instance().cb_del_server(port) - for port in [v for v in ServerPool.get_instance().tcp_ipv6_servers_pool.keys()]: - if ServerPool.get_instance().server_is_run(port) > 0: - ServerPool.get_instance().cb_del_server(port) - - @staticmethod - def thread_db(obj): - import socket - import time - global db_instance - timeout = 60 - socket.setdefaulttimeout(timeout) - last_rows = [] - db_instance = obj() - ServerPool.get_instance() - shell.log_shadowsocks_version() - - try: - import resource - logging.info('current process RLIMIT_NOFILE resource: soft %d hard %d' % resource.getrlimit(resource.RLIMIT_NOFILE)) - except: - pass - - try: - while True: - load_config() - db_instance.load_cfg() - try: - db_instance.push_db_all_user() - rows = db_instance.pull_db_all_user() - if rows: - db_instance.pull_ok = True - config = shell.get_config(False) - for port in config['additional_ports']: - val = config['additional_ports'][port] - val['port'] = int(port) - val['enable'] = 1 - val['transfer_enable'] = 1024 ** 7 - val['u'] = 0 - val['d'] = 0 - if "password" in val: - val["passwd"] = val["password"] - rows.append(val) - db_instance.del_server_out_of_bound_safe(last_rows, rows) - last_rows = rows - except Exception as e: - trace = traceback.format_exc() - logging.error(trace) - #logging.warn('db thread except:%s' % e) - if db_instance.event.wait(get_config().UPDATE_TIME) or not ServerPool.get_instance().thread.is_alive(): - break - except KeyboardInterrupt as e: - pass - db_instance.del_servers() - ServerPool.get_instance().stop() - db_instance = None - - @staticmethod - def thread_db_stop(): - global db_instance - db_instance.event.set() - -class DbTransfer(TransferBase): - def __init__(self): - super(DbTransfer, self).__init__() - self.user_pass = {} #记录更新此用户流量时被跳过多少次 - self.cfg = { - "host": "127.0.0.1", - "port": 3306, - "user": "ss", - "password": "pass", - "db": "shadowsocks", - "node_id": 0, - "transfer_mul": 1.0, - "ssl_enable": 0, - "ssl_ca": "", - "ssl_cert": "", - "ssl_key": ""} - self.load_cfg() - - def load_cfg(self): - import json - config_path = get_config().MYSQL_CONFIG - cfg = None - with open(config_path, 'rb+') as f: - cfg = json.loads(f.read().decode('utf8')) - - if cfg: - self.cfg.update(cfg) - - def update_all_user(self, dt_transfer): - import cymysql - update_transfer = {} - - query_head = 'UPDATE user' - query_sub_when = '' - query_sub_when2 = '' - query_sub_in = None - last_time = time.time() - - for id in dt_transfer.keys(): - transfer = dt_transfer[id] - #小于最低更新流量的先不更新 - update_trs = 1024 * (2048 - self.user_pass.get(id, 0) * 64) - if transfer[0] + transfer[1] < update_trs and id not in self.force_update_transfer: - self.user_pass[id] = self.user_pass.get(id, 0) + 1 - continue - if id in self.user_pass: - del self.user_pass[id] - - query_sub_when += ' WHEN %s THEN u+%s' % (id, int(transfer[0] * self.cfg["transfer_mul"])) - query_sub_when2 += ' WHEN %s THEN d+%s' % (id, int(transfer[1] * self.cfg["transfer_mul"])) - update_transfer[id] = transfer - - if query_sub_in is not None: - query_sub_in += ',%s' % id - else: - query_sub_in = '%s' % id - - if query_sub_when == '': - return update_transfer - query_sql = query_head + ' SET u = CASE port' + query_sub_when + \ - ' END, d = CASE port' + query_sub_when2 + \ - ' END, t = ' + str(int(last_time)) + \ - ' WHERE port IN (%s)' % query_sub_in - if self.cfg["ssl_enable"] == 1: - conn = cymysql.connect(host=self.cfg["host"], port=self.cfg["port"], - user=self.cfg["user"], passwd=self.cfg["password"], - db=self.cfg["db"], charset='utf8', - ssl={'ca':self.cfg["ssl_ca"],'cert':self.cfg["ssl_cert"],'key':self.cfg["ssl_key"]}) - else: - conn = cymysql.connect(host=self.cfg["host"], port=self.cfg["port"], - user=self.cfg["user"], passwd=self.cfg["password"], - db=self.cfg["db"], charset='utf8') - - try: - cur = conn.cursor() - try: - cur.execute(query_sql) - except Exception as e: - logging.error(e) - update_transfer = {} - - cur.close() - conn.commit() - except Exception as e: - logging.error(e) - update_transfer = {} - finally: - conn.close() - - return update_transfer - - def pull_db_all_user(self): - import cymysql - #数据库所有用户信息 - if self.cfg["ssl_enable"] == 1: - conn = cymysql.connect(host=self.cfg["host"], port=self.cfg["port"], - user=self.cfg["user"], passwd=self.cfg["password"], - db=self.cfg["db"], charset='utf8', - ssl={'ca':self.cfg["ssl_ca"],'cert':self.cfg["ssl_cert"],'key':self.cfg["ssl_key"]}) - else: - conn = cymysql.connect(host=self.cfg["host"], port=self.cfg["port"], - user=self.cfg["user"], passwd=self.cfg["password"], - db=self.cfg["db"], charset='utf8') - - try: - rows = self.pull_db_users(conn) - finally: - conn.close() - - if not rows: - logging.warn('no user in db') - return rows - - def pull_db_users(self, conn): - try: - switchrule = importloader.load('switchrule') - keys = switchrule.getKeys(self.key_list) - except Exception as e: - keys = self.key_list - - cur = conn.cursor() - cur.execute("SELECT " + ','.join(keys) + " FROM user") - rows = [] - for r in cur.fetchall(): - d = {} - for column in range(len(keys)): - d[keys[column]] = r[column] - rows.append(d) - cur.close() - return rows - -class Dbv3Transfer(DbTransfer): - def __init__(self): - super(Dbv3Transfer, self).__init__() - self.update_node_state = True if get_config().API_INTERFACE != 'legendsockssr' else False - if self.update_node_state: - self.key_list += ['id'] - self.key_list += ['method'] - if self.update_node_state: - self.ss_node_info_name = 'ss_node_info_log' - if get_config().API_INTERFACE == 'sspanelv3ssr': - self.key_list += ['obfs', 'protocol'] - if get_config().API_INTERFACE == 'glzjinmod': - self.key_list += ['obfs', 'protocol'] - self.ss_node_info_name = 'ss_node_info' - else: - self.key_list += ['obfs', 'protocol'] - self.start_time = time.time() - - def update_all_user(self, dt_transfer): - import cymysql - update_transfer = {} - - query_head = 'UPDATE user' - query_sub_when = '' - query_sub_when2 = '' - query_sub_in = None - last_time = time.time() - - alive_user_count = len(self.onlineuser_cache) - bandwidth_thistime = 0 - - if self.cfg["ssl_enable"] == 1: - conn = cymysql.connect(host=self.cfg["host"], port=self.cfg["port"], - user=self.cfg["user"], passwd=self.cfg["password"], - db=self.cfg["db"], charset='utf8', - ssl={'ca':self.cfg["ssl_ca"],'cert':self.cfg["ssl_cert"],'key':self.cfg["ssl_key"]}) - else: - conn = cymysql.connect(host=self.cfg["host"], port=self.cfg["port"], - user=self.cfg["user"], passwd=self.cfg["password"], - db=self.cfg["db"], charset='utf8') - conn.autocommit(True) - - for id in dt_transfer.keys(): - transfer = dt_transfer[id] - bandwidth_thistime = bandwidth_thistime + transfer[0] + transfer[1] - - update_trs = 1024 * (2048 - self.user_pass.get(id, 0) * 64) - if transfer[0] + transfer[1] < update_trs: - self.user_pass[id] = self.user_pass.get(id, 0) + 1 - continue - if id in self.user_pass: - del self.user_pass[id] - - query_sub_when += ' WHEN %s THEN u+%s' % (id, int(transfer[0] * self.cfg["transfer_mul"])) - query_sub_when2 += ' WHEN %s THEN d+%s' % (id, int(transfer[1] * self.cfg["transfer_mul"])) - update_transfer[id] = transfer - - if self.update_node_state: - cur = conn.cursor() - try: - if id in self.port_uid_table: - cur.execute("INSERT INTO `user_traffic_log` (`id`, `user_id`, `u`, `d`, `node_id`, `rate`, `traffic`, `log_time`) VALUES (NULL, '" + \ - str(self.port_uid_table[id]) + "', '" + str(transfer[0]) + "', '" + str(transfer[1]) + "', '" + \ - str(self.cfg["node_id"]) + "', '" + str(self.cfg["transfer_mul"]) + "', '" + \ - self.traffic_format((transfer[0] + transfer[1]) * self.cfg["transfer_mul"]) + "', unix_timestamp()); ") - except: - logging.warn('no `user_traffic_log` in db') - cur.close() - - if query_sub_in is not None: - query_sub_in += ',%s' % id - else: - query_sub_in = '%s' % id - - if query_sub_when != '': - query_sql = query_head + ' SET u = CASE port' + query_sub_when + \ - ' END, d = CASE port' + query_sub_when2 + \ - ' END, t = ' + str(int(last_time)) + \ - ' WHERE port IN (%s)' % query_sub_in - cur = conn.cursor() - try: - cur.execute(query_sql) - except Exception as e: - logging.error(e) - cur.close() - - if self.update_node_state: - try: - cur = conn.cursor() - try: - cur.execute("INSERT INTO `ss_node_online_log` (`id`, `node_id`, `online_user`, `log_time`) VALUES (NULL, '" + \ - str(self.cfg["node_id"]) + "', '" + str(alive_user_count) + "', unix_timestamp()); ") - except Exception as e: - logging.error(e) - cur.close() - - cur = conn.cursor() - try: - cur.execute("INSERT INTO `" + self.ss_node_info_name + "` (`id`, `node_id`, `uptime`, `load`, `log_time`) VALUES (NULL, '" + \ - str(self.cfg["node_id"]) + "', '" + str(self.uptime()) + "', '" + \ - str(self.load()) + "', unix_timestamp()); ") - except Exception as e: - logging.error(e) - cur.close() - except: - logging.warn('no `ss_node_online_log` or `" + self.ss_node_info_name + "` in db') - - conn.close() - return update_transfer - - def pull_db_users(self, conn): - try: - switchrule = importloader.load('switchrule') - keys = switchrule.getKeys(self.key_list) - except Exception as e: - keys = self.key_list - - cur = conn.cursor() - - if self.update_node_state: - node_info_keys = ['traffic_rate'] - try: - cur.execute("SELECT " + ','.join(node_info_keys) +" FROM ss_node where `id`='" + str(self.cfg["node_id"]) + "'") - nodeinfo = cur.fetchone() - except Exception as e: - logging.error(e) - nodeinfo = None - - if nodeinfo == None: - rows = [] - cur.close() - conn.commit() - logging.warn('None result when select node info from ss_node in db, maybe you set the incorrect node id') - return rows - cur.close() - - node_info_dict = {} - for column in range(len(nodeinfo)): - node_info_dict[node_info_keys[column]] = nodeinfo[column] - self.cfg['transfer_mul'] = float(node_info_dict['traffic_rate']) - - cur = conn.cursor() - try: - rows = [] - cur.execute("SELECT " + ','.join(keys) + " FROM user") - for r in cur.fetchall(): - d = {} - for column in range(len(keys)): - d[keys[column]] = r[column] - rows.append(d) - except Exception as e: - logging.error(e) - cur.close() - return rows - - def load(self): - import os - return os.popen("cat /proc/loadavg | awk '{ print $1\" \"$2\" \"$3 }'").readlines()[0] - - def uptime(self): - return time.time() - self.start_time - - def traffic_format(self, traffic): - if traffic < 1024 * 8: - return str(int(traffic)) + "B"; - - if traffic < 1024 * 1024 * 2: - return str(round((traffic / 1024.0), 2)) + "KB"; - - return str(round((traffic / 1048576.0), 2)) + "MB"; - -class MuJsonTransfer(TransferBase): - def __init__(self): - super(MuJsonTransfer, self).__init__() - - def update_all_user(self, dt_transfer): - import json - rows = None - - config_path = get_config().MUDB_FILE - with open(config_path, 'rb+') as f: - rows = json.loads(f.read().decode('utf8')) - for row in rows: - if "port" in row: - port = row["port"] - if port in dt_transfer: - row["u"] += dt_transfer[port][0] - row["d"] += dt_transfer[port][1] - - if rows: - output = json.dumps(rows, sort_keys=True, indent=4, separators=(',', ': ')) - with open(config_path, 'r+') as f: - f.write(output) - f.truncate() - - return dt_transfer - - def pull_db_all_user(self): - import json - rows = None - - config_path = get_config().MUDB_FILE - with open(config_path, 'rb+') as f: - rows = json.loads(f.read().decode('utf8')) - for row in rows: - try: - if 'forbidden_ip' in row: - row['forbidden_ip'] = common.IPNetwork(row['forbidden_ip']) - except Exception as e: - logging.error(e) - try: - if 'forbidden_port' in row: - row['forbidden_port'] = common.PortRange(row['forbidden_port']) - except Exception as e: - logging.error(e) - - if not rows: - logging.warn('no user in json file') - return rows - diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/firewall.lua b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/firewall.lua deleted file mode 100644 index b6514b481e..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/firewall.lua +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/lua - -require 'luci.sys' -local jsonc = require "luci.jsonc" - -local function get_config_path() - return luci.sys.exec("echo -n $(cat /usr/share/ssr_mudb_server/userapiconfig.py | grep 'MUDB_FILE' | cut -d \"'\" -f 2)") -end - -local function get_config_json() - return luci.sys.exec("cat " .. get_config_path()) or "[]" -end - -local json = jsonc.parse(get_config_json()) -if json then - for index = 1, table.maxn(json) do - local o = json[index] - if o.enable == 1 then - luci.sys.call(string.format("iptables -A SSR_MUDB-SERVER -p tcp --dport %s -m comment --comment %s -j ACCEPT", o.port, o.user)) - luci.sys.call(string.format("iptables -A SSR_MUDB-SERVER -p udp --dport %s -m comment --comment %s -j ACCEPT", o.port, o.user)) - end - end -end \ No newline at end of file diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/importloader.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/importloader.py deleted file mode 100644 index b26e180ed6..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/importloader.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/python3 -# -*- coding: UTF-8 -*- - -def load(name): - try: - obj = __import__(name) - reload(obj) - return obj - except: - pass - - try: - import importlib - obj = importlib.__import__(name) - importlib.reload(obj) - return obj - except: - pass - -def loads(namelist): - for name in namelist: - obj = load(name) - if obj is not None: - return obj diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/initcfg.bat b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/initcfg.bat deleted file mode 100644 index 6d0bce695a..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/initcfg.bat +++ /dev/null @@ -1,4 +0,0 @@ -@echo off -If Not Exist "userapiconfig.py" Copy "apiconfig.py" "userapiconfig.py" -If Not Exist "user-config.json" Copy "config.json" "user-config.json" -If Not Exist "usermysql.json" Copy "mysql.json" "usermysql.json" diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/initcfg.sh b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/initcfg.sh deleted file mode 100755 index 862d1abed1..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/initcfg.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -chmod +x *.sh -chmod +x shadowsocks/*.sh -cp -n apiconfig.py userapiconfig.py -cp -n config.json user-config.json -cp -n mysql.json usermysql.json - diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/initmudbjson.sh b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/initmudbjson.sh deleted file mode 100755 index 6c1851b457..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/initmudbjson.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -bash initcfg.sh -sed -i "s/API_INTERFACE = .\+\?\#/API_INTERFACE = \'mudbjson\' \#/g" userapiconfig.py -ip_addr=`ifconfig -a|grep inet|grep -v inet6|grep -v "127.0.0."|grep -v -e "192\.168\..[0-9]\+\.[0-9]\+"|grep -v -e "10\.[0-9]\+\.[0-9]\+\.[0-9]\+"|awk '{print $2}'|tr -d "addr:"` -ip_count=`echo $ip_addr|grep -e "^[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+$" -c` - -if [[ $ip_count == 1 ]]; then - ip_addr=`ip a|grep inet|grep -v inet6|grep -v "127.0.0."|grep -v -e "192\.168\..[0-9]\+\.[0-9]\+"|grep -v -e "10\.[0-9]\+\.[0-9]\+\.[0-9]\+"|awk '{print $2}'` - ip_addr=${ip_addr%/*} - ip_count=`echo $ip_addr|grep -e "^[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+$" -c` -fi -if [[ $ip_count == 1 ]]; then - echo "server IP is "${ip_addr} - sed -i "s/SERVER_PUB_ADDR = .\+/SERVER_PUB_ADDR = \'"${ip_addr}"\'/g" userapiconfig.py - user_count=`python3 mujson_mgr.py -l|grep -c -e "[0-9]"` - if [[ $user_count == 0 ]]; then - port=`python3 -c 'import random;print(random.randint(10000, 65536))'` - python3 mujson_mgr.py -a -p ${port} - fi -else - echo "unable to detect server IP" -fi - diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/logrun.sh b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/logrun.sh deleted file mode 100755 index 2952be3801..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/logrun.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -cd `dirname $0` -#python3_ver=$(ls /usr/bin|grep -e "^python[23]\.[1-9]\+$"|tail -1) -eval $(ps -ef | grep "[0-9] python3 server\\.py m" | awk '{print "kill "$2}') -ulimit -n 512000 -nohup python3 server.py m >> ssserver.log 2>&1 & - diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/mudb.json b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/mudb.json deleted file mode 100644 index 0637a088a0..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/mudb.json +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/mujson_mgr.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/mujson_mgr.py deleted file mode 100644 index 356eb93b78..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/mujson_mgr.py +++ /dev/null @@ -1,358 +0,0 @@ -#!/usr/bin/python3 -# -*- coding: UTF-8 -*- - -import traceback -from shadowsocks import shell, common -from configloader import load_config, get_config -import random -import getopt -import sys -import json -import base64 - - -class MuJsonLoader(object): - def __init__(self): - self.json = None - - def load(self, path): - l = "[]" - try: - with open(path, 'rb+') as f: - l = f.read().decode('utf8') - except: - pass - self.json = json.loads(l) - - def save(self, path): - if self.json is not None: - output = json.dumps(self.json, sort_keys=True, indent=4, separators=(',', ': ')) - with open(path, 'a'): - pass - with open(path, 'rb+') as f: - f.write(output.encode('utf8')) - f.truncate() - - -class MuMgr(object): - def __init__(self): - self.config_path = get_config().MUDB_FILE - try: - self.server_addr = get_config().SERVER_PUB_ADDR - except: - self.server_addr = '127.0.0.1' - self.data = MuJsonLoader() - - if self.server_addr == '127.0.0.1': - self.server_addr = self.getipaddr() - - def getipaddr(self, ifname='eth0'): - import socket - import struct - ret = '127.0.0.1' - try: - ret = socket.gethostbyname(socket.getfqdn(socket.gethostname())) - except: - pass - if ret == '127.0.0.1': - try: - import fcntl - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - ret = socket.inet_ntoa(fcntl.ioctl(s.fileno(), 0x8915, struct.pack('256s', ifname[:15]))[20:24]) - except: - pass - return ret - - def ssrlink(self, user, encode, muid): - protocol = user.get('protocol', '') - obfs = user.get('obfs', '') - protocol = protocol.replace("_compatible", "") - obfs = obfs.replace("_compatible", "") - protocol_param = '' - if muid is not None: - protocol_param_ = user.get('protocol_param', '') - param = protocol_param_.split('#') - if len(param) == 2: - for row in self.data.json: - if int(row['port']) == muid: - param = str(muid) + ':' + row['passwd'] - protocol_param = '/?protoparam=' + common.to_str(base64.urlsafe_b64encode(common.to_bytes(param))).replace("=", "") - break - link = ("%s:%s:%s:%s:%s:%s" % (self.server_addr, user['port'], protocol, user['method'], obfs, common.to_str(base64.urlsafe_b64encode(common.to_bytes(user['passwd']))).replace("=", ""))) + protocol_param - return "ssr://" + (encode and common.to_str(base64.urlsafe_b64encode(common.to_bytes(link))).replace("=", "") or link) - - def userinfo(self, user, muid = None): - ret = "" - key_list = ['user', 'port', 'method', 'passwd', 'protocol', 'protocol_param', 'obfs', 'obfs_param', 'transfer_enable', 'u', 'd'] - for key in sorted(user): - if key not in key_list: - key_list.append(key) - for key in key_list: - if key in ['enable'] or key not in user: - continue - ret += '\n' - if (muid is not None) and (key in ['protocol_param']): - for row in self.data.json: - if int(row['port']) == muid: - ret += " %s : %s" % (key, str(muid) + ':' + row['passwd']) - break - elif key in ['transfer_enable', 'u', 'd']: - if muid is not None: - for row in self.data.json: - if int(row['port']) == muid: - val = row[key] - break - else: - val = user[key] - if val / 1024 < 4: - ret += " %s : %s" % (key, val) - elif val / 1024 ** 2 < 4: - val /= float(1024) - ret += " %s : %s K Bytes" % (key, val) - elif val / 1024 ** 3 < 4: - val /= float(1024 ** 2) - ret += " %s : %s M Bytes" % (key, val) - else: - val /= float(1024 ** 3) - ret += " %s : %s G Bytes" % (key, val) - else: - ret += " %s : %s" % (key, user[key]) - ret += "\n " + self.ssrlink(user, False, muid) - ret += "\n " + self.ssrlink(user, True, muid) - return ret - - def rand_pass(self): - return ''.join([random.choice('''ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789~-_=+(){}[]^&%$@''') for i in range(8)]) - - def add(self, user): - up = {'enable': 1, 'u': 0, 'd': 0, 'method': "aes-128-ctr", - 'protocol': "auth_aes128_md5", - 'obfs': "tls1.2_ticket_auth_compatible", - 'transfer_enable': 9007199254740992} - up['passwd'] = self.rand_pass() - up.update(user) - - self.data.load(self.config_path) - for row in self.data.json: - match = False - if 'user' in user and row['user'] == user['user']: - match = True - if 'port' in user and row['port'] == user['port']: - match = True - if match: - print("user [%s] port [%s] already exist" % (row['user'], row['port'])) - return - self.data.json.append(up) - print("### add user info %s" % self.userinfo(up)) - self.data.save(self.config_path) - - def edit(self, user): - self.data.load(self.config_path) - for row in self.data.json: - match = True - if 'user' in user and row['user'] != user['user']: - match = False - if 'port' in user and row['port'] != user['port']: - match = False - if match: - print("edit user [%s]" % (row['user'],)) - row.update(user) - print("### new user info %s" % self.userinfo(row)) - break - self.data.save(self.config_path) - - def delete(self, user): - self.data.load(self.config_path) - index = 0 - for row in self.data.json: - match = True - if 'user' in user and row['user'] != user['user']: - match = False - if 'port' in user and row['port'] != user['port']: - match = False - if match: - print("delete user [%s]" % row['user']) - del self.data.json[index] - break - index += 1 - self.data.save(self.config_path) - - def clear_ud(self, user): - up = {'u': 0, 'd': 0} - self.data.load(self.config_path) - for row in self.data.json: - match = True - if 'user' in user and row['user'] != user['user']: - match = False - if 'port' in user and row['port'] != user['port']: - match = False - if match: - row.update(up) - print("clear user [%s]" % row['user']) - self.data.save(self.config_path) - - def list_user(self, user): - self.data.load(self.config_path) - if not user: - for row in self.data.json: - print("user [%s] port %s" % (row['user'], row['port'])) - return - for row in self.data.json: - match = True - if 'user' in user and row['user'] != user['user']: - match = False - if 'port' in user and row['port'] != user['port']: - match = False - if match: - muid = None - if 'muid' in user: - muid = user['muid'] - print("### user [%s] info %s" % (row['user'], self.userinfo(row, muid))) - - -def print_server_help(): - print('''usage: python3 mujson_manage.py -a|-d|-e|-c|-l [OPTION]... - -Actions: - -a add/edit a user - -d delete a user - -e edit a user - -c set u&d to zero - -l display a user infomation or all users infomation - -Options: - -u USER the user name - -p PORT server port (only this option must be set if add a user) - -k PASSWORD password - -m METHOD encryption method, default: aes-128-ctr - -O PROTOCOL protocol plugin, default: auth_aes128_md5 - -o OBFS obfs plugin, default: tls1.2_ticket_auth_compatible - -G PROTOCOL_PARAM protocol plugin param - -g OBFS_PARAM obfs plugin param - -t TRANSFER max transfer for G bytes, default: 8388608 (8 PB or 8192 TB) - -f FORBID set forbidden ports. Example (ban 1~79 and 81~100): -f "1-79,81-100" - -i MUID set sub id to display (only work with -l) - -s SPEED set speed_limit_per_con - -S SPEED set speed_limit_per_user - -General options: - -h, --help show this help message and exit -''') - - -def main(): - shortopts = 'adeclu:i:p:k:O:o:G:g:m:t:f:hs:S:' - longopts = ['help'] - action = None - user = {} - fast_set_obfs = {'0': 'plain', - '+1': 'http_simple_compatible', - '1': 'http_simple', - '+2': 'tls1.2_ticket_auth_compatible', - '2': 'tls1.2_ticket_auth'} - fast_set_protocol = {'0': 'origin', - 's4': 'auth_sha1_v4', - '+s4': 'auth_sha1_v4_compatible', - 'am': 'auth_aes128_md5', - 'as': 'auth_aes128_sha1', - 'ca': 'auth_chain_a', - } - fast_set_method = {'0': 'none', - 'a1c': 'aes-128-cfb', - 'a2c': 'aes-192-cfb', - 'a3c': 'aes-256-cfb', - 'r': 'rc4-md5', - 'r6': 'rc4-md5-6', - 'c': 'chacha20', - 'ci': 'chacha20-ietf', - 's': 'salsa20', - 'a1': 'aes-128-ctr', - 'a2': 'aes-192-ctr', - 'a3': 'aes-256-ctr'} - try: - optlist, args = getopt.getopt(sys.argv[1:], shortopts, longopts) - for key, value in optlist: - if key == '-a': - action = 1 - elif key == '-d': - action = 2 - elif key == '-e': - action = 3 - elif key == '-l': - action = 4 - elif key == '-c': - action = 0 - elif key == '-u': - user['user'] = value - elif key == '-i': - user['muid'] = int(value) - elif key == '-p': - user['port'] = int(value) - elif key == '-k': - user['passwd'] = value - elif key == '-o': - if value in fast_set_obfs: - user['obfs'] = fast_set_obfs[value] - else: - user['obfs'] = value - elif key == '-O': - if value in fast_set_protocol: - user['protocol'] = fast_set_protocol[value] - else: - user['protocol'] = value - elif key == '-g': - user['obfs_param'] = value - elif key == '-G': - user['protocol_param'] = value - elif key == '-s': - user['speed_limit_per_con'] = int(value) - elif key == '-S': - user['speed_limit_per_user'] = int(value) - elif key == '-m': - if value in fast_set_method: - user['method'] = fast_set_method[value] - else: - user['method'] = value - elif key == '-f': - user['forbidden_port'] = value - elif key == '-t': - val = float(value) - try: - val = int(value) - except: - pass - user['transfer_enable'] = int(val * 1024) * (1024 ** 2) - elif key in ('-h', '--help'): - print_server_help() - sys.exit(0) - except getopt.GetoptError as e: - print(e) - sys.exit(2) - - manage = MuMgr() - if action == 0: - manage.clear_ud(user) - elif action == 1: - if 'user' not in user and 'port' in user: - user['user'] = str(user['port']) - if 'user' in user and 'port' in user: - manage.add(user) - else: - print("You have to set the port with -p") - elif action == 2: - if 'user' in user or 'port' in user: - manage.delete(user) - else: - print("You have to set the user name or port with -u/-p") - elif action == 3: - if 'user' in user or 'port' in user: - manage.edit(user) - else: - print("You have to set the user name or port with -u/-p") - elif action == 4: - manage.list_user(user) - elif action is None: - print_server_help() - -if __name__ == '__main__': - main() diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/mysql.json b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/mysql.json deleted file mode 100644 index 1849e9e816..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/mysql.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "host": "127.0.0.1", - "port": 3306, - "user": "ss", - "password": "pass", - "db": "sspanel", - "node_id": 0, - "transfer_mul": 1.0, - "ssl_enable": 0, - "ssl_ca": "", - "ssl_cert": "", - "ssl_key": "" -} diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/run.sh b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/run.sh deleted file mode 100755 index 5a9ed0dada..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/run.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -cd `dirname $0` -#python3_ver=$(ls /usr/bin|grep -e "^python[23]\.[1-9]\+$"|tail -1) -eval $(ps -ef | grep "[0-9] python3 server\\.py m" | awk '{print "kill "$2}') -ulimit -n 512000 -nohup python3 server.py m>> /dev/null 2>&1 & - diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/server.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/server.py deleted file mode 100644 index 7da48114f2..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/server.py +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/python3 -# -*- coding: utf-8 -*- -# -# Copyright 2015 breakwall -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import time -import sys -import threading -import os - -if __name__ == '__main__': - import inspect - os.chdir(os.path.dirname(os.path.realpath(inspect.getfile(inspect.currentframe())))) - -import server_pool -import db_transfer -from shadowsocks import shell -from configloader import load_config, get_config - -class MainThread(threading.Thread): - def __init__(self, obj): - super(MainThread, self).__init__() - self.daemon = True - self.obj = obj - - def run(self): - self.obj.thread_db(self.obj) - - def stop(self): - self.obj.thread_db_stop() - -def main(): - shell.check_python3() - if False: - db_transfer.DbTransfer.thread_db() - else: - if get_config().API_INTERFACE == 'mudbjson': - thread = MainThread(db_transfer.MuJsonTransfer) - elif get_config().API_INTERFACE == 'sspanelv2': - thread = MainThread(db_transfer.DbTransfer) - else: - thread = MainThread(db_transfer.Dbv3Transfer) - thread.start() - try: - while thread.is_alive(): - thread.join(10.0) - except (KeyboardInterrupt, IOError, OSError) as e: - import traceback - traceback.print_exc() - thread.stop() - -if __name__ == '__main__': - main() - diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/server_pool.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/server_pool.py deleted file mode 100644 index d1db3b2bf4..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/server_pool.py +++ /dev/null @@ -1,293 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -# Copyright (c) 2014 clowwindy -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -import os -import logging -import struct -import time -from shadowsocks import shell, eventloop, tcprelay, udprelay, asyncdns, common -import threading -import sys -import traceback -from socket import * -from configloader import load_config, get_config - -class MainThread(threading.Thread): - def __init__(self, params): - super(MainThread, self).__init__() - self.params = params - - def run(self): - ServerPool._loop(*self.params) - -class ServerPool(object): - - instance = None - - def __init__(self): - shell.check_python3() - self.config = shell.get_config(False) - self.dns_resolver = asyncdns.DNSResolver() - if not self.config.get('dns_ipv6', False): - asyncdns.IPV6_CONNECTION_SUPPORT = False - - self.mgr = None #asyncmgr.ServerMgr() - - self.tcp_servers_pool = {} - self.tcp_ipv6_servers_pool = {} - self.udp_servers_pool = {} - self.udp_ipv6_servers_pool = {} - self.stat_counter = {} - - self.loop = eventloop.EventLoop() - self.thread = MainThread( (self.loop, self.dns_resolver, self.mgr) ) - self.thread.start() - - @staticmethod - def get_instance(): - if ServerPool.instance is None: - ServerPool.instance = ServerPool() - return ServerPool.instance - - def stop(self): - self.loop.stop() - - @staticmethod - def _loop(loop, dns_resolver, mgr): - try: - if mgr is not None: - mgr.add_to_loop(loop) - dns_resolver.add_to_loop(loop) - loop.run() - except (KeyboardInterrupt, IOError, OSError) as e: - logging.error(e) - traceback.print_exc() - os.exit(0) - except Exception as e: - logging.error(e) - traceback.print_exc() - - def server_is_run(self, port): - port = int(port) - ret = 0 - if port in self.tcp_servers_pool: - ret = 1 - if port in self.tcp_ipv6_servers_pool: - ret |= 2 - return ret - - def server_run_status(self, port): - if 'server' in self.config: - if port not in self.tcp_servers_pool: - return False - if 'server_ipv6' in self.config: - if port not in self.tcp_ipv6_servers_pool: - return False - return True - - def new_server(self, port, user_config): - ret = True - port = int(port) - ipv6_ok = False - - if 'server_ipv6' in self.config: - if port in self.tcp_ipv6_servers_pool: - logging.info("server already at %s:%d" % (self.config['server_ipv6'], port)) - return 'this port server is already running' - else: - a_config = self.config.copy() - a_config.update(user_config) - if len(a_config['server_ipv6']) > 2 and a_config['server_ipv6'][0] == "[" and a_config['server_ipv6'][-1] == "]": - a_config['server_ipv6'] = a_config['server_ipv6'][1:-1] - a_config['server'] = a_config['server_ipv6'] - a_config['server_port'] = port - a_config['max_connect'] = 128 - a_config['method'] = common.to_str(a_config['method']) - try: - logging.info("starting server at [%s]:%d" % (common.to_str(a_config['server']), port)) - - tcp_server = tcprelay.TCPRelay(a_config, self.dns_resolver, False, stat_counter=self.stat_counter) - tcp_server.add_to_loop(self.loop) - self.tcp_ipv6_servers_pool.update({port: tcp_server}) - - udp_server = udprelay.UDPRelay(a_config, self.dns_resolver, False, stat_counter=self.stat_counter) - udp_server.add_to_loop(self.loop) - self.udp_ipv6_servers_pool.update({port: udp_server}) - - if common.to_str(a_config['server_ipv6']) == "::": - ipv6_ok = True - except Exception as e: - logging.warn("IPV6 %s " % (e,)) - - if 'server' in self.config: - if port in self.tcp_servers_pool: - logging.info("server already at %s:%d" % (common.to_str(self.config['server']), port)) - return 'this port server is already running' - else: - a_config = self.config.copy() - a_config.update(user_config) - a_config['server_port'] = port - a_config['max_connect'] = 128 - a_config['method'] = common.to_str(a_config['method']) - try: - logging.info("starting server at %s:%d" % (common.to_str(a_config['server']), port)) - - tcp_server = tcprelay.TCPRelay(a_config, self.dns_resolver, False) - tcp_server.add_to_loop(self.loop) - self.tcp_servers_pool.update({port: tcp_server}) - - udp_server = udprelay.UDPRelay(a_config, self.dns_resolver, False) - udp_server.add_to_loop(self.loop) - self.udp_servers_pool.update({port: udp_server}) - - except Exception as e: - if not ipv6_ok: - logging.warn("IPV4 %s " % (e,)) - - return True - - def del_server(self, port): - port = int(port) - logging.info("del server at %d" % port) - try: - udpsock = socket(AF_INET, SOCK_DGRAM) - udpsock.sendto('%s:%s:0:0' % (get_config().MANAGE_PASS, port), (get_config().MANAGE_BIND_IP, get_config().MANAGE_PORT)) - udpsock.close() - except Exception as e: - logging.warn(e) - return True - - def cb_del_server(self, port): - port = int(port) - - if port not in self.tcp_servers_pool: - logging.info("stopped server at %s:%d already stop" % (self.config['server'], port)) - else: - logging.info("stopped server at %s:%d" % (self.config['server'], port)) - try: - self.tcp_servers_pool[port].close(True) - del self.tcp_servers_pool[port] - except Exception as e: - logging.warn(e) - try: - self.udp_servers_pool[port].close(True) - del self.udp_servers_pool[port] - except Exception as e: - logging.warn(e) - - if 'server_ipv6' in self.config: - if port not in self.tcp_ipv6_servers_pool: - logging.info("stopped server at [%s]:%d already stop" % (self.config['server_ipv6'], port)) - else: - logging.info("stopped server at [%s]:%d" % (self.config['server_ipv6'], port)) - try: - self.tcp_ipv6_servers_pool[port].close(True) - del self.tcp_ipv6_servers_pool[port] - except Exception as e: - logging.warn(e) - try: - self.udp_ipv6_servers_pool[port].close(True) - del self.udp_ipv6_servers_pool[port] - except Exception as e: - logging.warn(e) - - return True - - def update_mu_users(self, port, users): - port = int(port) - if port in self.tcp_servers_pool: - try: - self.tcp_servers_pool[port].update_users(users) - except Exception as e: - logging.warn(e) - try: - self.udp_servers_pool[port].update_users(users) - except Exception as e: - logging.warn(e) - if port in self.tcp_ipv6_servers_pool: - try: - self.tcp_ipv6_servers_pool[port].update_users(users) - except Exception as e: - logging.warn(e) - try: - self.udp_ipv6_servers_pool[port].update_users(users) - except Exception as e: - logging.warn(e) - - def get_server_transfer(self, port): - port = int(port) - uid = struct.pack(' 63: - return None - results.append(common.chr(l)) - results.append(label) - results.append(b'\0') - return b''.join(results) - - -def build_request(address, qtype): - request_id = os.urandom(2) - header = struct.pack('!BBHHHH', 1, 0, 1, 0, 0, 0) - addr = build_address(address) - qtype_qclass = struct.pack('!HH', qtype, QCLASS_IN) - return request_id + header + addr + qtype_qclass - - -def parse_ip(addrtype, data, length, offset): - if addrtype == QTYPE_A: - return socket.inet_ntop(socket.AF_INET, data[offset:offset + length]) - elif addrtype == QTYPE_AAAA: - return socket.inet_ntop(socket.AF_INET6, data[offset:offset + length]) - elif addrtype in [QTYPE_CNAME, QTYPE_NS]: - return parse_name(data, offset)[1] - else: - return data[offset:offset + length] - - -def parse_name(data, offset): - p = offset - labels = [] - l = common.ord(data[p]) - while l > 0: - if (l & (128 + 64)) == (128 + 64): - # pointer - pointer = struct.unpack('!H', data[p:p + 2])[0] - pointer &= 0x3FFF - r = parse_name(data, pointer) - labels.append(r[1]) - p += 2 - # pointer is the end - return p - offset, b'.'.join(labels) - else: - labels.append(data[p + 1:p + 1 + l]) - p += 1 + l - l = common.ord(data[p]) - return p - offset + 1, b'.'.join(labels) - - -# rfc1035 -# record -# 1 1 1 1 1 1 -# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 -# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -# | | -# / / -# / NAME / -# | | -# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -# | TYPE | -# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -# | CLASS | -# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -# | TTL | -# | | -# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -# | RDLENGTH | -# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| -# / RDATA / -# / / -# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ -def parse_record(data, offset, question=False): - nlen, name = parse_name(data, offset) - if not question: - record_type, record_class, record_ttl, record_rdlength = struct.unpack( - '!HHiH', data[offset + nlen:offset + nlen + 10] - ) - ip = parse_ip(record_type, data, record_rdlength, offset + nlen + 10) - return nlen + 10 + record_rdlength, \ - (name, ip, record_type, record_class, record_ttl) - else: - record_type, record_class = struct.unpack( - '!HH', data[offset + nlen:offset + nlen + 4] - ) - return nlen + 4, (name, None, record_type, record_class, None, None) - - -def parse_header(data): - if len(data) >= 12: - header = struct.unpack('!HBBHHHH', data[:12]) - res_id = header[0] - res_qr = header[1] & 128 - res_tc = header[1] & 2 - res_ra = header[2] & 128 - res_rcode = header[2] & 15 - # assert res_tc == 0 - # assert res_rcode in [0, 3] - res_qdcount = header[3] - res_ancount = header[4] - res_nscount = header[5] - res_arcount = header[6] - return (res_id, res_qr, res_tc, res_ra, res_rcode, res_qdcount, - res_ancount, res_nscount, res_arcount) - return None - - -def parse_response(data): - try: - if len(data) >= 12: - header = parse_header(data) - if not header: - return None - res_id, res_qr, res_tc, res_ra, res_rcode, res_qdcount, \ - res_ancount, res_nscount, res_arcount = header - - qds = [] - ans = [] - offset = 12 - for i in range(0, res_qdcount): - l, r = parse_record(data, offset, True) - offset += l - if r: - qds.append(r) - for i in range(0, res_ancount): - l, r = parse_record(data, offset) - offset += l - if r: - ans.append(r) - for i in range(0, res_nscount): - l, r = parse_record(data, offset) - offset += l - for i in range(0, res_arcount): - l, r = parse_record(data, offset) - offset += l - response = DNSResponse() - if qds: - response.hostname = qds[0][0] - for an in qds: - response.questions.append((an[1], an[2], an[3])) - for an in ans: - response.answers.append((an[1], an[2], an[3])) - return response - except Exception as e: - shell.print_exception(e) - return None - - -def is_valid_hostname(hostname): - if len(hostname) > 255: - return False - if hostname[-1] == b'.': - hostname = hostname[:-1] - return all(VALID_HOSTNAME.match(x) for x in hostname.split(b'.')) - - -class DNSResponse(object): - def __init__(self): - self.hostname = None - self.questions = [] # each: (addr, type, class) - self.answers = [] # each: (addr, type, class) - - def __str__(self): - return '%s: %s' % (self.hostname, str(self.answers)) - - -STATUS_IPV4 = 0 -STATUS_IPV6 = 1 - - -class DNSResolver(object): - - def __init__(self): - self._loop = None - self._hosts = {} - self._hostname_status = {} - self._hostname_to_cb = {} - self._cb_to_hostname = {} - self._cache = lru_cache.LRUCache(timeout=300) - self._sock = None - self._servers = None - self._parse_resolv() - self._parse_hosts() - # TODO monitor hosts change and reload hosts - # TODO parse /etc/gai.conf and follow its rules - - def _parse_resolv(self): - self._servers = [] - try: - with open('dns.conf', 'rb') as f: - content = f.readlines() - for line in content: - line = line.strip() - if line: - parts = line.split(b' ', 1) - if len(parts) >= 2: - server = parts[0] - port = int(parts[1]) - else: - server = parts[0] - port = 53 - if common.is_ip(server) == socket.AF_INET: - if type(server) != str: - server = server.decode('utf8') - self._servers.append((server, port)) - except IOError: - pass - if not self._servers: - try: - with open('/etc/resolv.conf', 'rb') as f: - content = f.readlines() - for line in content: - line = line.strip() - if line: - if line.startswith(b'nameserver'): - parts = line.split() - if len(parts) >= 2: - server = parts[1] - if common.is_ip(server) == socket.AF_INET: - if type(server) != str: - server = server.decode('utf8') - self._servers.append((server, 53)) - except IOError: - pass - if not self._servers: - self._servers = [('8.8.4.4', 53), ('8.8.8.8', 53)] - logging.info('dns server: %s' % (self._servers,)) - - def _parse_hosts(self): - etc_path = '/etc/hosts' - if 'WINDIR' in os.environ: - etc_path = os.environ['WINDIR'] + '/system32/drivers/etc/hosts' - try: - with open(etc_path, 'rb') as f: - for line in f.readlines(): - line = line.strip() - if b"#" in line: - line = line[:line.find(b'#')] - parts = line.split() - if len(parts) >= 2: - ip = parts[0] - if common.is_ip(ip): - for i in range(1, len(parts)): - hostname = parts[i] - if hostname: - self._hosts[hostname] = ip - except IOError: - self._hosts['localhost'] = '127.0.0.1' - - def add_to_loop(self, loop): - if self._loop: - raise Exception('already add to loop') - self._loop = loop - # TODO when dns server is IPv6 - self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, - socket.SOL_UDP) - self._sock.setblocking(False) - loop.add(self._sock, eventloop.POLL_IN, self) - loop.add_periodic(self.handle_periodic) - - def _call_callback(self, hostname, ip, error=None): - callbacks = self._hostname_to_cb.get(hostname, []) - for callback in callbacks: - if callback in self._cb_to_hostname: - del self._cb_to_hostname[callback] - if ip or error: - callback((hostname, ip), error) - else: - callback((hostname, None), - Exception('unable to parse hostname %s' % hostname)) - if hostname in self._hostname_to_cb: - del self._hostname_to_cb[hostname] - if hostname in self._hostname_status: - del self._hostname_status[hostname] - - def _handle_data(self, data): - response = parse_response(data) - if response and response.hostname: - hostname = response.hostname - ip = None - for answer in response.answers: - if answer[1] in (QTYPE_A, QTYPE_AAAA) and \ - answer[2] == QCLASS_IN: - ip = answer[0] - break - if IPV6_CONNECTION_SUPPORT: - if not ip and self._hostname_status.get(hostname, STATUS_IPV4) \ - == STATUS_IPV6: - self._hostname_status[hostname] = STATUS_IPV4 - self._send_req(hostname, QTYPE_A) - else: - if ip: - self._cache[hostname] = ip - self._call_callback(hostname, ip) - elif self._hostname_status.get(hostname, None) == STATUS_IPV4: - for question in response.questions: - if question[1] == QTYPE_A: - self._call_callback(hostname, None) - break - else: - if not ip and self._hostname_status.get(hostname, STATUS_IPV6) \ - == STATUS_IPV4: - self._hostname_status[hostname] = STATUS_IPV6 - self._send_req(hostname, QTYPE_AAAA) - else: - if ip: - self._cache[hostname] = ip - self._call_callback(hostname, ip) - elif self._hostname_status.get(hostname, None) == STATUS_IPV6: - for question in response.questions: - if question[1] == QTYPE_AAAA: - self._call_callback(hostname, None) - break - - def handle_event(self, sock, fd, event): - if sock != self._sock: - return - if event & eventloop.POLL_ERR: - logging.error('dns socket err') - self._loop.remove(self._sock) - self._sock.close() - # TODO when dns server is IPv6 - self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, - socket.SOL_UDP) - self._sock.setblocking(False) - self._loop.add(self._sock, eventloop.POLL_IN, self) - else: - data, addr = sock.recvfrom(1024) - if addr not in self._servers: - logging.warn('received a packet other than our dns') - return - self._handle_data(data) - - def handle_periodic(self): - self._cache.sweep() - - def remove_callback(self, callback): - hostname = self._cb_to_hostname.get(callback) - if hostname: - del self._cb_to_hostname[callback] - arr = self._hostname_to_cb.get(hostname, None) - if arr: - arr.remove(callback) - if not arr: - del self._hostname_to_cb[hostname] - if hostname in self._hostname_status: - del self._hostname_status[hostname] - - def _send_req(self, hostname, qtype): - req = build_request(hostname, qtype) - for server in self._servers: - logging.debug('resolving %s with type %d using server %s', - hostname, qtype, server) - self._sock.sendto(req, server) - - def resolve(self, hostname, callback): - if type(hostname) != bytes: - hostname = hostname.encode('utf8') - if not hostname: - callback(None, Exception('empty hostname')) - elif common.is_ip(hostname): - callback((hostname, hostname), None) - elif hostname in self._hosts: - logging.debug('hit hosts: %s', hostname) - ip = self._hosts[hostname] - callback((hostname, ip), None) - elif hostname in self._cache: - logging.debug('hit cache: %s', hostname) - ip = self._cache[hostname] - callback((hostname, ip), None) - else: - if not is_valid_hostname(hostname): - callback(None, Exception('invalid hostname: %s' % hostname)) - return - if False: - addrs = socket.getaddrinfo(hostname, 0, 0, - socket.SOCK_DGRAM, socket.SOL_UDP) - if addrs: - af, socktype, proto, canonname, sa = addrs[0] - logging.debug('DNS resolve %s %s' % (hostname, sa[0]) ) - self._cache[hostname] = sa[0] - callback((hostname, sa[0]), None) - return - arr = self._hostname_to_cb.get(hostname, None) - if not arr: - if IPV6_CONNECTION_SUPPORT: - self._hostname_status[hostname] = STATUS_IPV6 - self._send_req(hostname, QTYPE_AAAA) - else: - self._hostname_status[hostname] = STATUS_IPV4 - self._send_req(hostname, QTYPE_A) - self._hostname_to_cb[hostname] = [callback] - self._cb_to_hostname[callback] = hostname - else: - arr.append(callback) - # TODO send again only if waited too long - if IPV6_CONNECTION_SUPPORT: - self._send_req(hostname, QTYPE_AAAA) - else: - self._send_req(hostname, QTYPE_A) - - def close(self): - if self._sock: - if self._loop: - self._loop.remove_periodic(self.handle_periodic) - self._loop.remove(self._sock) - self._sock.close() - self._sock = None - - -def test(): - dns_resolver = DNSResolver() - loop = eventloop.EventLoop() - dns_resolver.add_to_loop(loop) - - global counter - counter = 0 - - def make_callback(): - global counter - - def callback(result, error): - global counter - # TODO: what can we assert? - print(result, error) - counter += 1 - if counter == 9: - dns_resolver.close() - loop.stop() - a_callback = callback - return a_callback - - assert(make_callback() != make_callback()) - - dns_resolver.resolve(b'google.com', make_callback()) - dns_resolver.resolve('google.com', make_callback()) - dns_resolver.resolve('example.com', make_callback()) - dns_resolver.resolve('ipv6.google.com', make_callback()) - dns_resolver.resolve('www.facebook.com', make_callback()) - dns_resolver.resolve('ns2.google.com', make_callback()) - dns_resolver.resolve('invalid.@!#$%^&$@.hostname', make_callback()) - dns_resolver.resolve('toooooooooooooooooooooooooooooooooooooooooooooooooo' - 'ooooooooooooooooooooooooooooooooooooooooooooooooooo' - 'long.hostname', make_callback()) - dns_resolver.resolve('toooooooooooooooooooooooooooooooooooooooooooooooooo' - 'ooooooooooooooooooooooooooooooooooooooooooooooooooo' - 'ooooooooooooooooooooooooooooooooooooooooooooooooooo' - 'ooooooooooooooooooooooooooooooooooooooooooooooooooo' - 'ooooooooooooooooooooooooooooooooooooooooooooooooooo' - 'ooooooooooooooooooooooooooooooooooooooooooooooooooo' - 'long.hostname', make_callback()) - - loop.run() - - -if __name__ == '__main__': - test() - diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/common.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/common.py deleted file mode 100644 index 6686c31602..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/common.py +++ /dev/null @@ -1,418 +0,0 @@ -#!/usr/bin/python3 -# -*- coding: utf-8 -*- -# -# Copyright 2013-2015 clowwindy -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import absolute_import, division, print_function, \ - with_statement - -import socket -import struct -import logging -import binascii -import re - -from shadowsocks import lru_cache - -def compat_ord(s): - if type(s) == int: - return s - return _ord(s) - - -def compat_chr(d): - if bytes == str: - return _chr(d) - return bytes([d]) - - -_ord = ord -_chr = chr -ord = compat_ord -chr = compat_chr - -connect_log = logging.debug - -def to_bytes(s): - if bytes != str: - if type(s) == str: - return s.encode('utf-8') - return s - - -def to_str(s): - if bytes != str: - if type(s) == bytes: - return s.decode('utf-8') - return s - -def int32(x): - if x > 0xFFFFFFFF or x < 0: - x &= 0xFFFFFFFF - if x > 0x7FFFFFFF: - x = int(0x100000000 - x) - if x < 0x80000000: - return -x - else: - return -2147483648 - return x - -def inet_ntop(family, ipstr): - if family == socket.AF_INET: - return to_bytes(socket.inet_ntoa(ipstr)) - elif family == socket.AF_INET6: - import re - v6addr = ':'.join(('%02X%02X' % (ord(i), ord(j))).lstrip('0') - for i, j in zip(ipstr[::2], ipstr[1::2])) - v6addr = re.sub('::+', '::', v6addr, count=1) - return to_bytes(v6addr) - - -def inet_pton(family, addr): - addr = to_str(addr) - if family == socket.AF_INET: - return socket.inet_aton(addr) - elif family == socket.AF_INET6: - if '.' in addr: # a v4 addr - v4addr = addr[addr.rindex(':') + 1:] - v4addr = socket.inet_aton(v4addr) - v4addr = ['%02X' % ord(x) for x in v4addr] - v4addr.insert(2, ':') - newaddr = addr[:addr.rindex(':') + 1] + ''.join(v4addr) - return inet_pton(family, newaddr) - dbyts = [0] * 8 # 8 groups - grps = addr.split(':') - for i, v in enumerate(grps): - if v: - dbyts[i] = int(v, 16) - else: - for j, w in enumerate(grps[::-1]): - if w: - dbyts[7 - j] = int(w, 16) - else: - break - break - return b''.join((chr(i // 256) + chr(i % 256)) for i in dbyts) - else: - raise RuntimeError("What family?") - - -def is_ip(address): - for family in (socket.AF_INET, socket.AF_INET6): - try: - if type(address) != str: - address = address.decode('utf8') - inet_pton(family, address) - return family - except (TypeError, ValueError, OSError, IOError): - pass - return False - - -def match_regex(regex, text): - regex = re.compile(regex) - for item in regex.findall(text): - return True - return False - - -def patch_socket(): - if not hasattr(socket, 'inet_pton'): - socket.inet_pton = inet_pton - - if not hasattr(socket, 'inet_ntop'): - socket.inet_ntop = inet_ntop - - -patch_socket() - - -ADDRTYPE_IPV4 = 1 -ADDRTYPE_IPV6 = 4 -ADDRTYPE_HOST = 3 - - -def pack_addr(address): - address_str = to_str(address) - for family in (socket.AF_INET, socket.AF_INET6): - try: - r = socket.inet_pton(family, address_str) - if family == socket.AF_INET6: - return b'\x04' + r - else: - return b'\x01' + r - except (TypeError, ValueError, OSError, IOError): - pass - if len(address) > 255: - address = address[:255] # TODO - return b'\x03' + chr(len(address)) + address - -def pre_parse_header(data): - if not data: - return None - datatype = ord(data[0]) - if datatype == 0x80: - if len(data) <= 2: - return None - rand_data_size = ord(data[1]) - if rand_data_size + 2 >= len(data): - logging.warn('header too short, maybe wrong password or ' - 'encryption method') - return None - data = data[rand_data_size + 2:] - elif datatype == 0x81: - data = data[1:] - elif datatype == 0x82: - if len(data) <= 3: - return None - rand_data_size = struct.unpack('>H', data[1:3])[0] - if rand_data_size + 3 >= len(data): - logging.warn('header too short, maybe wrong password or ' - 'encryption method') - return None - data = data[rand_data_size + 3:] - elif datatype == 0x88 or (~datatype & 0xff) == 0x88: - if len(data) <= 7 + 7: - return None - data_size = struct.unpack('>H', data[1:3])[0] - ogn_data = data - data = data[:data_size] - crc = binascii.crc32(data) & 0xffffffff - if crc != 0xffffffff: - logging.warn('uncorrect CRC32, maybe wrong password or ' - 'encryption method') - return None - start_pos = 3 + ord(data[3]) - data = data[start_pos:-4] - if data_size < len(ogn_data): - data += ogn_data[data_size:] - return data - -def parse_header(data): - addrtype = ord(data[0]) - dest_addr = None - dest_port = None - header_length = 0 - connecttype = (addrtype & 0x8) and 1 or 0 - addrtype &= ~0x8 - if addrtype == ADDRTYPE_IPV4: - if len(data) >= 7: - dest_addr = socket.inet_ntoa(data[1:5]) - dest_port = struct.unpack('>H', data[5:7])[0] - header_length = 7 - else: - logging.warn('header is too short') - elif addrtype == ADDRTYPE_HOST: - if len(data) > 2: - addrlen = ord(data[1]) - if len(data) >= 4 + addrlen: - dest_addr = data[2:2 + addrlen] - dest_port = struct.unpack('>H', data[2 + addrlen:4 + - addrlen])[0] - header_length = 4 + addrlen - else: - logging.warn('header is too short') - else: - logging.warn('header is too short') - elif addrtype == ADDRTYPE_IPV6: - if len(data) >= 19: - dest_addr = socket.inet_ntop(socket.AF_INET6, data[1:17]) - dest_port = struct.unpack('>H', data[17:19])[0] - header_length = 19 - else: - logging.warn('header is too short') - else: - logging.warn('unsupported addrtype %d, maybe wrong password or ' - 'encryption method' % addrtype) - if dest_addr is None: - return None - return connecttype, addrtype, to_bytes(dest_addr), dest_port, header_length - - -class IPNetwork(object): - ADDRLENGTH = {socket.AF_INET: 32, socket.AF_INET6: 128, False: 0} - - def __init__(self, addrs): - self.addrs_str = addrs - self._network_list_v4 = [] - self._network_list_v6 = [] - if type(addrs) == str: - addrs = addrs.split(',') - list(map(self.add_network, addrs)) - - def add_network(self, addr): - if addr is "": - return - block = addr.split('/') - addr_family = is_ip(block[0]) - addr_len = IPNetwork.ADDRLENGTH[addr_family] - if addr_family is socket.AF_INET: - ip, = struct.unpack("!I", socket.inet_aton(block[0])) - elif addr_family is socket.AF_INET6: - hi, lo = struct.unpack("!QQ", inet_pton(addr_family, block[0])) - ip = (hi << 64) | lo - else: - raise Exception("Not a valid CIDR notation: %s" % addr) - if len(block) is 1: - prefix_size = 0 - while (ip & 1) == 0 and ip is not 0: - ip >>= 1 - prefix_size += 1 - logging.warn("You did't specify CIDR routing prefix size for %s, " - "implicit treated as %s/%d" % (addr, addr, addr_len)) - elif block[1].isdigit() and int(block[1]) <= addr_len: - prefix_size = addr_len - int(block[1]) - ip >>= prefix_size - else: - raise Exception("Not a valid CIDR notation: %s" % addr) - if addr_family is socket.AF_INET: - self._network_list_v4.append((ip, prefix_size)) - else: - self._network_list_v6.append((ip, prefix_size)) - - def __contains__(self, addr): - addr_family = is_ip(addr) - if addr_family is socket.AF_INET: - ip, = struct.unpack("!I", socket.inet_aton(addr)) - return any(map(lambda n_ps: n_ps[0] == ip >> n_ps[1], - self._network_list_v4)) - elif addr_family is socket.AF_INET6: - hi, lo = struct.unpack("!QQ", inet_pton(addr_family, addr)) - ip = (hi << 64) | lo - return any(map(lambda n_ps: n_ps[0] == ip >> n_ps[1], - self._network_list_v6)) - else: - return False - - def __cmp__(self, other): - return cmp(self.addrs_str, other.addrs_str) - - def __eq__(self, other): - return self.addrs_str == other.addrs_str - - def __ne__(self, other): - return self.addrs_str != other.addrs_str - -class PortRange(object): - def __init__(self, range_str): - self.range_str = to_str(range_str) - self.range = set() - range_str = to_str(range_str).split(',') - for item in range_str: - try: - int_range = item.split('-') - if len(int_range) == 1: - if item: - self.range.add(int(item)) - elif len(int_range) == 2: - int_range[0] = int(int_range[0]) - int_range[1] = int(int_range[1]) - if int_range[0] < 0: - int_range[0] = 0 - if int_range[1] > 65535: - int_range[1] = 65535 - i = int_range[0] - while i <= int_range[1]: - self.range.add(i) - i += 1 - except Exception as e: - logging.error(e) - - def __contains__(self, val): - return val in self.range - - def __cmp__(self, other): - return cmp(self.range_str, other.range_str) - - def __eq__(self, other): - return self.range_str == other.range_str - - def __ne__(self, other): - return self.range_str != other.range_str - -class UDPAsyncDNSHandler(object): - dns_cache = lru_cache.LRUCache(timeout=1800) - def __init__(self, params): - self.params = params - self.remote_addr = None - self.call_back = None - - def resolve(self, dns_resolver, remote_addr, call_back): - if remote_addr in UDPAsyncDNSHandler.dns_cache: - if call_back: - call_back("", remote_addr, UDPAsyncDNSHandler.dns_cache[remote_addr], self.params) - else: - self.call_back = call_back - self.remote_addr = remote_addr - dns_resolver.resolve(remote_addr[0], self._handle_dns_resolved) - UDPAsyncDNSHandler.dns_cache.sweep() - - def _handle_dns_resolved(self, result, error): - if error: - logging.error("%s when resolve DNS" % (error,)) #drop - return self.call_back(error, self.remote_addr, None, self.params) - if result: - ip = result[1] - if ip: - return self.call_back("", self.remote_addr, ip, self.params) - logging.warning("can't resolve %s" % (self.remote_addr,)) - return self.call_back("fail to resolve", self.remote_addr, None, self.params) - -def test_inet_conv(): - ipv4 = b'8.8.4.4' - b = inet_pton(socket.AF_INET, ipv4) - assert inet_ntop(socket.AF_INET, b) == ipv4 - ipv6 = b'2404:6800:4005:805::1011' - b = inet_pton(socket.AF_INET6, ipv6) - assert inet_ntop(socket.AF_INET6, b) == ipv6 - - -def test_parse_header(): - assert parse_header(b'\x03\x0ewww.google.com\x00\x50') == \ - (0, b'www.google.com', 80, 18) - assert parse_header(b'\x01\x08\x08\x08\x08\x00\x35') == \ - (0, b'8.8.8.8', 53, 7) - assert parse_header((b'\x04$\x04h\x00@\x05\x08\x05\x00\x00\x00\x00\x00' - b'\x00\x10\x11\x00\x50')) == \ - (0, b'2404:6800:4005:805::1011', 80, 19) - - -def test_pack_header(): - assert pack_addr(b'8.8.8.8') == b'\x01\x08\x08\x08\x08' - assert pack_addr(b'2404:6800:4005:805::1011') == \ - b'\x04$\x04h\x00@\x05\x08\x05\x00\x00\x00\x00\x00\x00\x10\x11' - assert pack_addr(b'www.google.com') == b'\x03\x0ewww.google.com' - - -def test_ip_network(): - ip_network = IPNetwork('127.0.0.0/24,::ff:1/112,::1,192.168.1.1,192.0.2.0') - assert '127.0.0.1' in ip_network - assert '127.0.1.1' not in ip_network - assert ':ff:ffff' in ip_network - assert '::ffff:1' not in ip_network - assert '::1' in ip_network - assert '::2' not in ip_network - assert '192.168.1.1' in ip_network - assert '192.168.1.2' not in ip_network - assert '192.0.2.1' in ip_network - assert '192.0.3.1' in ip_network # 192.0.2.0 is treated as 192.0.2.0/23 - assert 'www.google.com' not in ip_network - - -if __name__ == '__main__': - test_inet_conv() - test_parse_header() - test_pack_header() - test_ip_network() diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/__init__.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/__init__.py deleted file mode 100644 index 2bc532d629..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright 2015 clowwindy -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import absolute_import, division, print_function, \ - with_statement diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/ctypes_libsodium.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/ctypes_libsodium.py deleted file mode 100644 index 826bc93c8b..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/ctypes_libsodium.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright (c) 2014 clowwindy -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -from __future__ import absolute_import, division, print_function, \ - with_statement - -import logging -from ctypes import CDLL, c_char_p, c_int, c_ulonglong, byref, \ - create_string_buffer, c_void_p - -__all__ = ['ciphers'] - -libsodium = None -loaded = False - -buf_size = 2048 - -# for salsa20 and chacha20 -BLOCK_SIZE = 64 - - -def load_libsodium(): - global loaded, libsodium, buf - - from ctypes.util import find_library - for p in ('sodium',): - libsodium_path = find_library(p) - if libsodium_path: - break - else: - raise Exception('libsodium not found') - logging.info('loading libsodium from %s', libsodium_path) - libsodium = CDLL(libsodium_path) - libsodium.sodium_init.restype = c_int - libsodium.crypto_stream_salsa20_xor_ic.restype = c_int - libsodium.crypto_stream_salsa20_xor_ic.argtypes = (c_void_p, c_char_p, - c_ulonglong, - c_char_p, c_ulonglong, - c_char_p) - libsodium.crypto_stream_chacha20_xor_ic.restype = c_int - libsodium.crypto_stream_chacha20_xor_ic.argtypes = (c_void_p, c_char_p, - c_ulonglong, - c_char_p, c_ulonglong, - c_char_p) - - libsodium.sodium_init() - - buf = create_string_buffer(buf_size) - loaded = True - - -class Salsa20Crypto(object): - def __init__(self, cipher_name, key, iv, op): - if not loaded: - load_libsodium() - self.key = key - self.iv = iv - self.key_ptr = c_char_p(key) - self.iv_ptr = c_char_p(iv) - if cipher_name == b'salsa20': - self.cipher = libsodium.crypto_stream_salsa20_xor_ic - elif cipher_name == b'chacha20': - self.cipher = libsodium.crypto_stream_chacha20_xor_ic - else: - raise Exception('Unknown cipher') - # byte counter, not block counter - self.counter = 0 - - def update(self, data): - global buf_size, buf - l = len(data) - - # we can only prepend some padding to make the encryption align to - # blocks - padding = self.counter % BLOCK_SIZE - if buf_size < padding + l: - buf_size = (padding + l) * 2 - buf = create_string_buffer(buf_size) - - if padding: - data = (b'\0' * padding) + data - self.cipher(byref(buf), c_char_p(data), padding + l, - self.iv_ptr, int(self.counter / BLOCK_SIZE), self.key_ptr) - self.counter += l - # buf is copied to a str object when we access buf.raw - # strip off the padding - return buf.raw[padding:padding + l] - - -ciphers = { - b'salsa20': (32, 8, Salsa20Crypto), - b'chacha20': (32, 8, Salsa20Crypto), -} - - -def test_salsa20(): - from shadowsocks.crypto import util - - cipher = Salsa20Crypto(b'salsa20', b'k' * 32, b'i' * 16, 1) - decipher = Salsa20Crypto(b'salsa20', b'k' * 32, b'i' * 16, 0) - - util.run_cipher(cipher, decipher) - - -def test_chacha20(): - from shadowsocks.crypto import util - - cipher = Salsa20Crypto(b'chacha20', b'k' * 32, b'i' * 16, 1) - decipher = Salsa20Crypto(b'chacha20', b'k' * 32, b'i' * 16, 0) - - util.run_cipher(cipher, decipher) - - -if __name__ == '__main__': - test_chacha20() - test_salsa20() diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/ctypes_openssl.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/ctypes_openssl.py deleted file mode 100644 index 486ba01b15..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/ctypes_openssl.py +++ /dev/null @@ -1,188 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright (c) 2014 clowwindy -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -from __future__ import absolute_import, division, print_function, \ - with_statement - -import logging -from ctypes import CDLL, c_char_p, c_int, c_long, byref,\ - create_string_buffer, c_void_p - -__all__ = ['ciphers'] - -libcrypto = None -loaded = False - -buf_size = 2048 - - -def load_openssl(): - global loaded, libcrypto, buf - - from ctypes.util import find_library - for p in ('crypto', 'eay32', 'libeay32'): - libcrypto_path = find_library(p) - if libcrypto_path: - break - else: - raise Exception('libcrypto(OpenSSL) not found') - logging.info('loading libcrypto from %s', libcrypto_path) - libcrypto = CDLL(libcrypto_path) - libcrypto.EVP_get_cipherbyname.restype = c_void_p - libcrypto.EVP_CIPHER_CTX_new.restype = c_void_p - - libcrypto.EVP_CipherInit_ex.argtypes = (c_void_p, c_void_p, c_char_p, - c_char_p, c_char_p, c_int) - - libcrypto.EVP_CipherUpdate.argtypes = (c_void_p, c_void_p, c_void_p, - c_char_p, c_int) - - libcrypto.EVP_CIPHER_CTX_cleanup.argtypes = (c_void_p,) - libcrypto.EVP_CIPHER_CTX_free.argtypes = (c_void_p,) - if hasattr(libcrypto, 'OpenSSL_add_all_ciphers'): - libcrypto.OpenSSL_add_all_ciphers() - - buf = create_string_buffer(buf_size) - loaded = True - - -def load_cipher(cipher_name): - func_name = b'EVP_' + cipher_name.replace(b'-', b'_') - if bytes != str: - func_name = str(func_name, 'utf-8') - cipher = getattr(libcrypto, func_name, None) - if cipher: - cipher.restype = c_void_p - return cipher() - return None - - -class CtypesCrypto(object): - def __init__(self, cipher_name, key, iv, op): - if not loaded: - load_openssl() - self._ctx = None - cipher = libcrypto.EVP_get_cipherbyname(cipher_name) - if not cipher: - cipher = load_cipher(cipher_name) - if not cipher: - raise Exception('cipher %s not found in libcrypto' % cipher_name) - key_ptr = c_char_p(key) - iv_ptr = c_char_p(iv) - self._ctx = libcrypto.EVP_CIPHER_CTX_new() - if not self._ctx: - raise Exception('can not create cipher context') - r = libcrypto.EVP_CipherInit_ex(self._ctx, cipher, None, - key_ptr, iv_ptr, c_int(op)) - if not r: - self.clean() - raise Exception('can not initialize cipher context') - - def update(self, data): - global buf_size, buf - cipher_out_len = c_long(0) - l = len(data) - if buf_size < l: - buf_size = l * 2 - buf = create_string_buffer(buf_size) - libcrypto.EVP_CipherUpdate(self._ctx, byref(buf), - byref(cipher_out_len), c_char_p(data), l) - # buf is copied to a str object when we access buf.raw - return buf.raw[:cipher_out_len.value] - - def __del__(self): - self.clean() - - def clean(self): - if self._ctx: - libcrypto.EVP_CIPHER_CTX_cleanup(self._ctx) - libcrypto.EVP_CIPHER_CTX_free(self._ctx) - - -ciphers = { - b'aes-128-cfb': (16, 16, CtypesCrypto), - b'aes-192-cfb': (24, 16, CtypesCrypto), - b'aes-256-cfb': (32, 16, CtypesCrypto), - b'aes-128-ofb': (16, 16, CtypesCrypto), - b'aes-192-ofb': (24, 16, CtypesCrypto), - b'aes-256-ofb': (32, 16, CtypesCrypto), - b'aes-128-ctr': (16, 16, CtypesCrypto), - b'aes-192-ctr': (24, 16, CtypesCrypto), - b'aes-256-ctr': (32, 16, CtypesCrypto), - b'aes-128-cfb8': (16, 16, CtypesCrypto), - b'aes-192-cfb8': (24, 16, CtypesCrypto), - b'aes-256-cfb8': (32, 16, CtypesCrypto), - b'aes-128-cfb1': (16, 16, CtypesCrypto), - b'aes-192-cfb1': (24, 16, CtypesCrypto), - b'aes-256-cfb1': (32, 16, CtypesCrypto), - b'bf-cfb': (16, 8, CtypesCrypto), - b'camellia-128-cfb': (16, 16, CtypesCrypto), - b'camellia-192-cfb': (24, 16, CtypesCrypto), - b'camellia-256-cfb': (32, 16, CtypesCrypto), - b'cast5-cfb': (16, 8, CtypesCrypto), - b'des-cfb': (8, 8, CtypesCrypto), - b'idea-cfb': (16, 8, CtypesCrypto), - b'rc2-cfb': (16, 8, CtypesCrypto), - b'rc4': (16, 0, CtypesCrypto), - b'seed-cfb': (16, 16, CtypesCrypto), -} - - -def run_method(method): - from shadowsocks.crypto import util - - cipher = CtypesCrypto(method, b'k' * 32, b'i' * 16, 1) - decipher = CtypesCrypto(method, b'k' * 32, b'i' * 16, 0) - - util.run_cipher(cipher, decipher) - - -def test_aes_128_cfb(): - run_method(b'aes-128-cfb') - - -def test_aes_256_cfb(): - run_method(b'aes-256-cfb') - - -def test_aes_128_cfb8(): - run_method(b'aes-128-cfb8') - - -def test_aes_256_ofb(): - run_method(b'aes-256-ofb') - - -def test_aes_256_ctr(): - run_method(b'aes-256-ctr') - - -def test_bf_cfb(): - run_method(b'bf-cfb') - - -def test_rc4(): - run_method(b'rc4') - - -if __name__ == '__main__': - test_aes_128_cfb() diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/openssl.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/openssl.py deleted file mode 100644 index 238db10c59..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/openssl.py +++ /dev/null @@ -1,199 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright 2015 clowwindy -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import absolute_import, division, print_function, \ - with_statement - -from ctypes import c_char_p, c_int, c_long, byref,\ - create_string_buffer, c_void_p - -from shadowsocks import common -from shadowsocks.crypto import util - -__all__ = ['ciphers'] - -libcrypto = None -loaded = False - -buf_size = 2048 - - -def load_openssl(): - global loaded, libcrypto, buf - - libcrypto = util.find_library(('crypto', 'eay32'), - 'EVP_get_cipherbyname', - 'libcrypto') - if libcrypto is None: - raise Exception('libcrypto(OpenSSL) not found') - - libcrypto.EVP_get_cipherbyname.restype = c_void_p - libcrypto.EVP_CIPHER_CTX_new.restype = c_void_p - - libcrypto.EVP_CipherInit_ex.argtypes = (c_void_p, c_void_p, c_char_p, - c_char_p, c_char_p, c_int) - - libcrypto.EVP_CipherUpdate.argtypes = (c_void_p, c_void_p, c_void_p, - c_char_p, c_int) - - if hasattr(libcrypto, "EVP_CIPHER_CTX_cleanup"): - libcrypto.EVP_CIPHER_CTX_cleanup.argtypes = (c_void_p,) - else: - libcrypto.EVP_CIPHER_CTX_reset.argtypes = (c_void_p,) - libcrypto.EVP_CIPHER_CTX_free.argtypes = (c_void_p,) - - libcrypto.RAND_bytes.restype = c_int - libcrypto.RAND_bytes.argtypes = (c_void_p, c_int) - - if hasattr(libcrypto, 'OpenSSL_add_all_ciphers'): - libcrypto.OpenSSL_add_all_ciphers() - - buf = create_string_buffer(buf_size) - loaded = True - - -def load_cipher(cipher_name): - func_name = 'EVP_' + cipher_name.replace('-', '_') - cipher = getattr(libcrypto, func_name, None) - if cipher: - cipher.restype = c_void_p - return cipher() - return None - -def rand_bytes(length): - if not loaded: - load_openssl() - buf = create_string_buffer(length) - r = libcrypto.RAND_bytes(buf, length) - if r <= 0: - raise Exception('RAND_bytes return error') - return buf.raw - -class OpenSSLCrypto(object): - def __init__(self, cipher_name, key, iv, op): - self._ctx = None - if not loaded: - load_openssl() - cipher = libcrypto.EVP_get_cipherbyname(common.to_bytes(cipher_name)) - if not cipher: - cipher = load_cipher(cipher_name) - if not cipher: - raise Exception('cipher %s not found in libcrypto' % cipher_name) - key_ptr = c_char_p(key) - iv_ptr = c_char_p(iv) - self._ctx = libcrypto.EVP_CIPHER_CTX_new() - if not self._ctx: - raise Exception('can not create cipher context') - r = libcrypto.EVP_CipherInit_ex(self._ctx, cipher, None, - key_ptr, iv_ptr, c_int(op)) - if not r: - self.clean() - raise Exception('can not initialize cipher context') - - def update(self, data): - global buf_size, buf - cipher_out_len = c_long(0) - l = len(data) - if buf_size < l: - buf_size = l * 2 - buf = create_string_buffer(buf_size) - libcrypto.EVP_CipherUpdate(self._ctx, byref(buf), - byref(cipher_out_len), c_char_p(data), l) - # buf is copied to a str object when we access buf.raw - return buf.raw[:cipher_out_len.value] - - def __del__(self): - self.clean() - - def clean(self): - if self._ctx: - if hasattr(libcrypto, "EVP_CIPHER_CTX_cleanup"): - libcrypto.EVP_CIPHER_CTX_cleanup(self._ctx) - else: - libcrypto.EVP_CIPHER_CTX_reset(self._ctx) - libcrypto.EVP_CIPHER_CTX_free(self._ctx) - - -ciphers = { - 'aes-128-cbc': (16, 16, OpenSSLCrypto), - 'aes-192-cbc': (24, 16, OpenSSLCrypto), - 'aes-256-cbc': (32, 16, OpenSSLCrypto), - 'aes-128-cfb': (16, 16, OpenSSLCrypto), - 'aes-192-cfb': (24, 16, OpenSSLCrypto), - 'aes-256-cfb': (32, 16, OpenSSLCrypto), - 'aes-128-ofb': (16, 16, OpenSSLCrypto), - 'aes-192-ofb': (24, 16, OpenSSLCrypto), - 'aes-256-ofb': (32, 16, OpenSSLCrypto), - 'aes-128-ctr': (16, 16, OpenSSLCrypto), - 'aes-192-ctr': (24, 16, OpenSSLCrypto), - 'aes-256-ctr': (32, 16, OpenSSLCrypto), - 'aes-128-cfb8': (16, 16, OpenSSLCrypto), - 'aes-192-cfb8': (24, 16, OpenSSLCrypto), - 'aes-256-cfb8': (32, 16, OpenSSLCrypto), - 'aes-128-cfb1': (16, 16, OpenSSLCrypto), - 'aes-192-cfb1': (24, 16, OpenSSLCrypto), - 'aes-256-cfb1': (32, 16, OpenSSLCrypto), - 'bf-cfb': (16, 8, OpenSSLCrypto), - 'camellia-128-cfb': (16, 16, OpenSSLCrypto), - 'camellia-192-cfb': (24, 16, OpenSSLCrypto), - 'camellia-256-cfb': (32, 16, OpenSSLCrypto), - 'cast5-cfb': (16, 8, OpenSSLCrypto), - 'des-cfb': (8, 8, OpenSSLCrypto), - 'idea-cfb': (16, 8, OpenSSLCrypto), - 'rc2-cfb': (16, 8, OpenSSLCrypto), - 'rc4': (16, 0, OpenSSLCrypto), - 'seed-cfb': (16, 16, OpenSSLCrypto), -} - - -def run_method(method): - - cipher = OpenSSLCrypto(method, b'k' * 32, b'i' * 16, 1) - decipher = OpenSSLCrypto(method, b'k' * 32, b'i' * 16, 0) - - util.run_cipher(cipher, decipher) - - -def test_aes_128_cfb(): - run_method('aes-128-cfb') - - -def test_aes_256_cfb(): - run_method('aes-256-cfb') - - -def test_aes_128_cfb8(): - run_method('aes-128-cfb8') - - -def test_aes_256_ofb(): - run_method('aes-256-ofb') - - -def test_aes_256_ctr(): - run_method('aes-256-ctr') - - -def test_bf_cfb(): - run_method('bf-cfb') - - -def test_rc4(): - run_method('rc4') - - -if __name__ == '__main__': - test_aes_128_cfb() diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/rc4_md5.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/rc4_md5.py deleted file mode 100644 index 397b2fffda..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/rc4_md5.py +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright 2015 clowwindy -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import absolute_import, division, print_function, \ - with_statement - -import hashlib - -from shadowsocks.crypto import openssl - -__all__ = ['ciphers'] - - -def create_cipher(alg, key, iv, op, key_as_bytes=0, d=None, salt=None, - i=1, padding=1): - md5 = hashlib.md5() - md5.update(key) - md5.update(iv) - rc4_key = md5.digest() - return openssl.OpenSSLCrypto(b'rc4', rc4_key, b'', op) - - -ciphers = { - 'rc4-md5': (16, 16, create_cipher), - 'rc4-md5-6': (16, 6, create_cipher), -} - - -def test(): - from shadowsocks.crypto import util - - cipher = create_cipher('rc4-md5', b'k' * 32, b'i' * 16, 1) - decipher = create_cipher('rc4-md5', b'k' * 32, b'i' * 16, 0) - - util.run_cipher(cipher, decipher) - - -if __name__ == '__main__': - test() diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/sodium.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/sodium.py deleted file mode 100644 index f1422da869..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/sodium.py +++ /dev/null @@ -1,140 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright 2015 clowwindy -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import absolute_import, division, print_function, \ - with_statement - -from ctypes import c_char_p, c_int, c_ulong, c_ulonglong, byref, \ - create_string_buffer, c_void_p - -from shadowsocks.crypto import util - -__all__ = ['ciphers'] - -libsodium = None -loaded = False - -buf_size = 2048 - -# for salsa20 and chacha20 and chacha20-ietf -BLOCK_SIZE = 64 - - -def load_libsodium(): - global loaded, libsodium, buf - - libsodium = util.find_library('sodium', 'crypto_stream_salsa20_xor_ic', - 'libsodium') - if libsodium is None: - raise Exception('libsodium not found') - - libsodium.crypto_stream_salsa20_xor_ic.restype = c_int - libsodium.crypto_stream_salsa20_xor_ic.argtypes = (c_void_p, c_char_p, - c_ulonglong, - c_char_p, c_ulonglong, - c_char_p) - libsodium.crypto_stream_chacha20_xor_ic.restype = c_int - libsodium.crypto_stream_chacha20_xor_ic.argtypes = (c_void_p, c_char_p, - c_ulonglong, - c_char_p, c_ulonglong, - c_char_p) - - try: - libsodium.crypto_stream_chacha20_ietf_xor_ic.restype = c_int - libsodium.crypto_stream_chacha20_ietf_xor_ic.argtypes = (c_void_p, c_char_p, - c_ulonglong, - c_char_p, c_ulong, - c_char_p) - except: - pass - - buf = create_string_buffer(buf_size) - loaded = True - - -class SodiumCrypto(object): - def __init__(self, cipher_name, key, iv, op): - if not loaded: - load_libsodium() - self.key = key - self.iv = iv - self.key_ptr = c_char_p(key) - self.iv_ptr = c_char_p(iv) - if cipher_name == 'salsa20': - self.cipher = libsodium.crypto_stream_salsa20_xor_ic - elif cipher_name == 'chacha20': - self.cipher = libsodium.crypto_stream_chacha20_xor_ic - elif cipher_name == 'chacha20-ietf': - self.cipher = libsodium.crypto_stream_chacha20_ietf_xor_ic - else: - raise Exception('Unknown cipher') - # byte counter, not block counter - self.counter = 0 - - def update(self, data): - global buf_size, buf - l = len(data) - - # we can only prepend some padding to make the encryption align to - # blocks - padding = self.counter % BLOCK_SIZE - if buf_size < padding + l: - buf_size = (padding + l) * 2 - buf = create_string_buffer(buf_size) - - if padding: - data = (b'\0' * padding) + data - self.cipher(byref(buf), c_char_p(data), padding + l, - self.iv_ptr, int(self.counter / BLOCK_SIZE), self.key_ptr) - self.counter += l - # buf is copied to a str object when we access buf.raw - # strip off the padding - return buf.raw[padding:padding + l] - - -ciphers = { - 'salsa20': (32, 8, SodiumCrypto), - 'chacha20': (32, 8, SodiumCrypto), - 'chacha20-ietf': (32, 12, SodiumCrypto), -} - - -def test_salsa20(): - cipher = SodiumCrypto('salsa20', b'k' * 32, b'i' * 16, 1) - decipher = SodiumCrypto('salsa20', b'k' * 32, b'i' * 16, 0) - - util.run_cipher(cipher, decipher) - - -def test_chacha20(): - - cipher = SodiumCrypto('chacha20', b'k' * 32, b'i' * 16, 1) - decipher = SodiumCrypto('chacha20', b'k' * 32, b'i' * 16, 0) - - util.run_cipher(cipher, decipher) - - -def test_chacha20_ietf(): - - cipher = SodiumCrypto('chacha20-ietf', b'k' * 32, b'i' * 16, 1) - decipher = SodiumCrypto('chacha20-ietf', b'k' * 32, b'i' * 16, 0) - - util.run_cipher(cipher, decipher) - -if __name__ == '__main__': - test_chacha20_ietf() - test_chacha20() - test_salsa20() diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/table.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/table.py deleted file mode 100644 index 9a96de6051..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/table.py +++ /dev/null @@ -1,181 +0,0 @@ -# !/usr/bin/env python3 -# -# Copyright 2015 clowwindy -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import absolute_import, division, print_function, \ - with_statement - -import string -import struct -import hashlib - - -__all__ = ['ciphers'] - -cached_tables = {} - -if hasattr(string, 'maketrans'): - maketrans = string.maketrans - translate = string.translate -else: - maketrans = bytes.maketrans - translate = bytes.translate - - -def get_table(key): - m = hashlib.md5() - m.update(key) - s = m.digest() - a, b = struct.unpack(' 0: - # parent waits for its child - time.sleep(5) - sys.exit(0) - - # child signals its parent to exit - ppid = os.getppid() - pid = os.getpid() - if write_pid_file(pid_file, pid) != 0: - os.kill(ppid, signal.SIGINT) - sys.exit(1) - - os.setsid() - signal.signal(signal.SIG_IGN, signal.SIGHUP) - - print('started') - os.kill(ppid, signal.SIGTERM) - - sys.stdin.close() - try: - freopen(log_file, 'a', sys.stdout) - freopen(log_file, 'a', sys.stderr) - except IOError as e: - shell.print_exception(e) - sys.exit(1) - - -def daemon_stop(pid_file): - import errno - try: - with open(pid_file) as f: - buf = f.read() - pid = common.to_str(buf) - if not buf: - logging.error('not running') - except IOError as e: - shell.print_exception(e) - if e.errno == errno.ENOENT: - # always exit 0 if we are sure daemon is not running - logging.error('not running') - return - sys.exit(1) - pid = int(pid) - if pid > 0: - try: - os.kill(pid, signal.SIGTERM) - except OSError as e: - if e.errno == errno.ESRCH: - logging.error('not running') - # always exit 0 if we are sure daemon is not running - return - shell.print_exception(e) - sys.exit(1) - else: - logging.error('pid is not positive: %d', pid) - - # sleep for maximum 10s - for i in range(0, 200): - try: - # query for the pid - os.kill(pid, 0) - except OSError as e: - if e.errno == errno.ESRCH: - break - time.sleep(0.05) - else: - logging.error('timed out when stopping pid %d', pid) - sys.exit(1) - print('stopped') - os.unlink(pid_file) - - -def set_user(username): - if username is None: - return - - import pwd - import grp - - try: - pwrec = pwd.getpwnam(username) - except KeyError: - logging.error('user not found: %s' % username) - raise - user = pwrec[0] - uid = pwrec[2] - gid = pwrec[3] - - cur_uid = os.getuid() - if uid == cur_uid: - return - if cur_uid != 0: - logging.error('can not set user as nonroot user') - # will raise later - - # inspired by supervisor - if hasattr(os, 'setgroups'): - groups = [grprec[2] for grprec in grp.getgrall() if user in grprec[3]] - groups.insert(0, gid) - os.setgroups(groups) - os.setgid(gid) - os.setuid(uid) diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/encrypt.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/encrypt.py deleted file mode 100644 index d6593d22f4..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/encrypt.py +++ /dev/null @@ -1,236 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright 2012-2015 clowwindy -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import absolute_import, division, print_function, \ - with_statement - -import os -import sys -import hashlib -import logging - -from shadowsocks import common -from shadowsocks.crypto import rc4_md5, openssl, sodium, table - - -method_supported = {} -method_supported.update(rc4_md5.ciphers) -method_supported.update(openssl.ciphers) -method_supported.update(sodium.ciphers) -method_supported.update(table.ciphers) - - -def random_string(length): - try: - return os.urandom(length) - except NotImplementedError as e: - return openssl.rand_bytes(length) - -cached_keys = {} - - -def try_cipher(key, method=None): - Encryptor(key, method) - - -def EVP_BytesToKey(password, key_len, iv_len): - # equivalent to OpenSSL's EVP_BytesToKey() with count 1 - # so that we make the same key and iv as nodejs version - if hasattr(password, 'encode'): - password = password.encode('utf-8') - cached_key = '%s-%d-%d' % (password, key_len, iv_len) - r = cached_keys.get(cached_key, None) - if r: - return r - m = [] - i = 0 - while len(b''.join(m)) < (key_len + iv_len): - md5 = hashlib.md5() - data = password - if i > 0: - data = m[i - 1] + password - md5.update(data) - m.append(md5.digest()) - i += 1 - ms = b''.join(m) - key = ms[:key_len] - iv = ms[key_len:key_len + iv_len] - cached_keys[cached_key] = (key, iv) - return key, iv - - -class Encryptor(object): - def __init__(self, key, method, iv = None): - self.key = key - self.method = method - self.iv = None - self.iv_sent = False - self.cipher_iv = b'' - self.iv_buf = b'' - self.cipher_key = b'' - self.decipher = None - method = method.lower() - self._method_info = self.get_method_info(method) - if self._method_info: - if iv is None or len(iv) != self._method_info[1]: - self.cipher = self.get_cipher(key, method, 1, - random_string(self._method_info[1])) - else: - self.cipher = self.get_cipher(key, method, 1, iv) - else: - logging.error('method %s not supported' % method) - sys.exit(1) - - def get_method_info(self, method): - method = method.lower() - m = method_supported.get(method) - return m - - def iv_len(self): - return len(self.cipher_iv) - - def get_cipher(self, password, method, op, iv): - password = common.to_bytes(password) - m = self._method_info - if m[0] > 0: - key, iv_ = EVP_BytesToKey(password, m[0], m[1]) - else: - # key_length == 0 indicates we should use the key directly - key, iv = password, b'' - - iv = iv[:m[1]] - if op == 1: - # this iv is for cipher not decipher - self.cipher_iv = iv[:m[1]] - self.cipher_key = key - return m[2](method, key, iv, op) - - def encrypt(self, buf): - if len(buf) == 0: - return buf - if self.iv_sent: - return self.cipher.update(buf) - else: - self.iv_sent = True - return self.cipher_iv + self.cipher.update(buf) - - def decrypt(self, buf): - if len(buf) == 0: - return buf - if self.decipher is not None: #optimize - return self.decipher.update(buf) - - decipher_iv_len = self._method_info[1] - if len(self.iv_buf) <= decipher_iv_len: - self.iv_buf += buf - if len(self.iv_buf) > decipher_iv_len: - decipher_iv = self.iv_buf[:decipher_iv_len] - self.decipher = self.get_cipher(self.key, self.method, 0, - iv=decipher_iv) - buf = self.iv_buf[decipher_iv_len:] - del self.iv_buf - return self.decipher.update(buf) - else: - return b'' - -def encrypt_all(password, method, op, data): - result = [] - method = method.lower() - (key_len, iv_len, m) = method_supported[method] - if key_len > 0: - key, _ = EVP_BytesToKey(password, key_len, iv_len) - else: - key = password - if op: - iv = random_string(iv_len) - result.append(iv) - else: - iv = data[:iv_len] - data = data[iv_len:] - cipher = m(method, key, iv, op) - result.append(cipher.update(data)) - return b''.join(result) - -def encrypt_key(password, method): - method = method.lower() - (key_len, iv_len, m) = method_supported[method] - if key_len > 0: - key, _ = EVP_BytesToKey(password, key_len, iv_len) - else: - key = password - return key - -def encrypt_iv_len(method): - method = method.lower() - (key_len, iv_len, m) = method_supported[method] - return iv_len - -def encrypt_new_iv(method): - method = method.lower() - (key_len, iv_len, m) = method_supported[method] - return random_string(iv_len) - -def encrypt_all_iv(key, method, op, data, ref_iv): - result = [] - method = method.lower() - (key_len, iv_len, m) = method_supported[method] - if op: - iv = ref_iv[0] - result.append(iv) - else: - iv = data[:iv_len] - data = data[iv_len:] - ref_iv[0] = iv - cipher = m(method, key, iv, op) - result.append(cipher.update(data)) - return b''.join(result) - - -CIPHERS_TO_TEST = [ - 'aes-128-cfb', - 'aes-256-cfb', - 'rc4-md5', - 'salsa20', - 'chacha20', - 'table', -] - - -def test_encryptor(): - from os import urandom - plain = urandom(10240) - for method in CIPHERS_TO_TEST: - logging.warn(method) - encryptor = Encryptor(b'key', method) - decryptor = Encryptor(b'key', method) - cipher = encryptor.encrypt(plain) - plain2 = decryptor.decrypt(cipher) - assert plain == plain2 - - -def test_encrypt_all(): - from os import urandom - plain = urandom(10240) - for method in CIPHERS_TO_TEST: - logging.warn(method) - cipher = encrypt_all(b'key', method, 1, plain) - plain2 = encrypt_all(b'key', method, 0, cipher) - assert plain == plain2 - - -if __name__ == '__main__': - test_encrypt_all() - test_encryptor() diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/eventloop.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/eventloop.py deleted file mode 100644 index 767a5f3f0f..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/eventloop.py +++ /dev/null @@ -1,258 +0,0 @@ -#!/usr/bin/python3 -# -*- coding: utf-8 -*- -# -# Copyright 2013-2015 clowwindy -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -# from ssloop -# https://github.com/clowwindy/ssloop - -from __future__ import absolute_import, division, print_function, \ - with_statement - -import os -import time -import socket -import select -import errno -import logging -from collections import defaultdict - -from shadowsocks import shell - - -__all__ = ['EventLoop', 'POLL_NULL', 'POLL_IN', 'POLL_OUT', 'POLL_ERR', - 'POLL_HUP', 'POLL_NVAL', 'EVENT_NAMES'] - -POLL_NULL = 0x00 -POLL_IN = 0x01 -POLL_OUT = 0x04 -POLL_ERR = 0x08 -POLL_HUP = 0x10 -POLL_NVAL = 0x20 - - -EVENT_NAMES = { - POLL_NULL: 'POLL_NULL', - POLL_IN: 'POLL_IN', - POLL_OUT: 'POLL_OUT', - POLL_ERR: 'POLL_ERR', - POLL_HUP: 'POLL_HUP', - POLL_NVAL: 'POLL_NVAL', -} - -# we check timeouts every TIMEOUT_PRECISION seconds -TIMEOUT_PRECISION = 2 - - -class KqueueLoop(object): - - MAX_EVENTS = 1024 - - def __init__(self): - self._kqueue = select.kqueue() - self._fds = {} - - def _control(self, fd, mode, flags): - events = [] - if mode & POLL_IN: - events.append(select.kevent(fd, select.KQ_FILTER_READ, flags)) - if mode & POLL_OUT: - events.append(select.kevent(fd, select.KQ_FILTER_WRITE, flags)) - for e in events: - self._kqueue.control([e], 0) - - def poll(self, timeout): - if timeout < 0: - timeout = None # kqueue behaviour - events = self._kqueue.control(None, KqueueLoop.MAX_EVENTS, timeout) - results = defaultdict(lambda: POLL_NULL) - for e in events: - fd = e.ident - if e.filter == select.KQ_FILTER_READ: - results[fd] |= POLL_IN - elif e.filter == select.KQ_FILTER_WRITE: - results[fd] |= POLL_OUT - return results.items() - - def register(self, fd, mode): - self._fds[fd] = mode - self._control(fd, mode, select.KQ_EV_ADD) - - def unregister(self, fd): - self._control(fd, self._fds[fd], select.KQ_EV_DELETE) - del self._fds[fd] - - def modify(self, fd, mode): - self.unregister(fd) - self.register(fd, mode) - - def close(self): - self._kqueue.close() - - -class SelectLoop(object): - - def __init__(self): - self._r_list = set() - self._w_list = set() - self._x_list = set() - - def poll(self, timeout): - r, w, x = select.select(self._r_list, self._w_list, self._x_list, - timeout) - results = defaultdict(lambda: POLL_NULL) - for p in [(r, POLL_IN), (w, POLL_OUT), (x, POLL_ERR)]: - for fd in p[0]: - results[fd] |= p[1] - return results.items() - - def register(self, fd, mode): - if mode & POLL_IN: - self._r_list.add(fd) - if mode & POLL_OUT: - self._w_list.add(fd) - if mode & POLL_ERR: - self._x_list.add(fd) - - def unregister(self, fd): - if fd in self._r_list: - self._r_list.remove(fd) - if fd in self._w_list: - self._w_list.remove(fd) - if fd in self._x_list: - self._x_list.remove(fd) - - def modify(self, fd, mode): - self.unregister(fd) - self.register(fd, mode) - - def close(self): - pass - - -class EventLoop(object): - def __init__(self): - if hasattr(select, 'epoll'): - self._impl = select.epoll() - model = 'epoll' - elif hasattr(select, 'kqueue'): - self._impl = KqueueLoop() - model = 'kqueue' - elif hasattr(select, 'select'): - self._impl = SelectLoop() - model = 'select' - else: - raise Exception('can not find any available functions in select ' - 'package') - self._fdmap = {} # (f, handler) - self._last_time = time.time() - self._periodic_callbacks = [] - self._stopping = False - logging.debug('using event model: %s', model) - - def poll(self, timeout=None): - events = self._impl.poll(timeout) - return [(self._fdmap[fd][0], fd, event) for fd, event in events] - - def add(self, f, mode, handler): - fd = f.fileno() - self._fdmap[fd] = (f, handler) - self._impl.register(fd, mode) - - def remove(self, f): - fd = f.fileno() - del self._fdmap[fd] - self._impl.unregister(fd) - - def removefd(self, fd): - del self._fdmap[fd] - self._impl.unregister(fd) - - def add_periodic(self, callback): - self._periodic_callbacks.append(callback) - - def remove_periodic(self, callback): - self._periodic_callbacks.remove(callback) - - def modify(self, f, mode): - fd = f.fileno() - self._impl.modify(fd, mode) - - def stop(self): - self._stopping = True - - def run(self): - events = [] - while not self._stopping: - asap = False - try: - events = self.poll(TIMEOUT_PRECISION) - except (OSError, IOError) as e: - if errno_from_exception(e) in (errno.EPIPE, errno.EINTR): - # EPIPE: Happens when the client closes the connection - # EINTR: Happens when received a signal - # handles them as soon as possible - asap = True - logging.debug('poll:%s', e) - else: - logging.error('poll:%s', e) - import traceback - traceback.print_exc() - continue - - handle = False - for sock, fd, event in events: - handler = self._fdmap.get(fd, None) - if handler is not None: - handler = handler[1] - try: - handle = handler.handle_event(sock, fd, event) or handle - except (OSError, IOError) as e: - shell.print_exception(e) - now = time.time() - if asap or now - self._last_time >= TIMEOUT_PRECISION: - for callback in self._periodic_callbacks: - callback() - self._last_time = now - if events and not handle: - time.sleep(0.001) - - def __del__(self): - self._impl.close() - - -# from tornado -def errno_from_exception(e): - """Provides the errno from an Exception object. - - There are cases that the errno attribute was not set so we pull - the errno out of the args but if someone instatiates an Exception - without any args you will get a tuple error. So this function - abstracts all that behavior to give you a safe way to get the - errno. - """ - - if hasattr(e, 'errno'): - return e.errno - elif e.args: - return e.args[0] - else: - return None - - -# from tornado -def get_sock_error(sock): - error_number = sock.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR) - return socket.error(error_number, os.strerror(error_number)) diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/local.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/local.py deleted file mode 100644 index e4768f0643..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/local.py +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# Copyright 2012-2015 clowwindy -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import absolute_import, division, print_function, \ - with_statement - -import sys -import os -import logging -import signal - -if __name__ == '__main__': - import inspect - file_path = os.path.dirname(os.path.realpath(inspect.getfile(inspect.currentframe()))) - sys.path.insert(0, os.path.join(file_path, '../')) - -from shadowsocks import shell, daemon, eventloop, tcprelay, udprelay, asyncdns - - -def main(): - shell.check_python3() - - # fix py2exe - if hasattr(sys, "frozen") and sys.frozen in \ - ("windows_exe", "console_exe"): - p = os.path.dirname(os.path.abspath(sys.executable)) - os.chdir(p) - - config = shell.get_config(True) - - if not config.get('dns_ipv6', False): - asyncdns.IPV6_CONNECTION_SUPPORT = False - - daemon.daemon_exec(config) - logging.info("local start with protocol[%s] password [%s] method [%s] obfs [%s] obfs_param [%s]" % - (config['protocol'], config['password'], config['method'], config['obfs'], config['obfs_param'])) - - try: - logging.info("starting local at %s:%d" % - (config['local_address'], config['local_port'])) - - dns_resolver = asyncdns.DNSResolver() - tcp_server = tcprelay.TCPRelay(config, dns_resolver, True) - udp_server = udprelay.UDPRelay(config, dns_resolver, True) - loop = eventloop.EventLoop() - dns_resolver.add_to_loop(loop) - tcp_server.add_to_loop(loop) - udp_server.add_to_loop(loop) - - def handler(signum, _): - logging.warn('received SIGQUIT, doing graceful shutting down..') - tcp_server.close(next_tick=True) - udp_server.close(next_tick=True) - signal.signal(getattr(signal, 'SIGQUIT', signal.SIGTERM), handler) - - def int_handler(signum, _): - sys.exit(1) - signal.signal(signal.SIGINT, int_handler) - - daemon.set_user(config.get('user', None)) - loop.run() - except Exception as e: - shell.print_exception(e) - sys.exit(1) - -if __name__ == '__main__': - main() diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/logrun.sh b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/logrun.sh deleted file mode 100755 index 286b4ec7e2..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/logrun.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -cd `dirname $0` -eval $(ps -ef | grep "[0-9] python3 server\\.py a" | awk '{print "kill "$2}') -ulimit -n 512000 -nohup python3 server.py a >> ssserver.log 2>&1 & diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/lru_cache.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/lru_cache.py deleted file mode 100644 index 4f2f03bea1..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/lru_cache.py +++ /dev/null @@ -1,179 +0,0 @@ -#!/usr/bin/python3 -# -*- coding: utf-8 -*- -# -# Copyright 2015 clowwindy -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import absolute_import, division, print_function, \ - with_statement - -import collections -import logging -import time - -if __name__ == '__main__': - import os, sys, inspect - file_path = os.path.dirname(os.path.realpath(inspect.getfile(inspect.currentframe()))) - sys.path.insert(0, os.path.join(file_path, '../')) - -try: - from collections import OrderedDict -except: - from shadowsocks.ordereddict import OrderedDict - -# this LRUCache is optimized for concurrency, not QPS -# n: concurrency, keys stored in the cache -# m: visits not timed out, proportional to QPS * timeout -# get & set is O(1), not O(n). thus we can support very large n -# sweep is O((n - m)) or O(1024) at most, -# no metter how large the cache or timeout value is - -SWEEP_MAX_ITEMS = 1024 - -class LRUCache(collections.MutableMapping): - """This class is not thread safe""" - - def __init__(self, timeout=60, close_callback=None, *args, **kwargs): - self.timeout = timeout - self.close_callback = close_callback - self._store = {} - self._keys_to_last_time = OrderedDict() - self.update(dict(*args, **kwargs)) # use the free update to set keys - - def __getitem__(self, key): - # O(1) - t = time.time() - last_t = self._keys_to_last_time[key] - del self._keys_to_last_time[key] - self._keys_to_last_time[key] = t - return self._store[key] - - def __setitem__(self, key, value): - # O(1) - t = time.time() - if key in self._keys_to_last_time: - del self._keys_to_last_time[key] - self._keys_to_last_time[key] = t - self._store[key] = value - - def __delitem__(self, key): - # O(1) - last_t = self._keys_to_last_time[key] - del self._store[key] - del self._keys_to_last_time[key] - - def __contains__(self, key): - return key in self._store - - def __iter__(self): - return iter(self._store) - - def __len__(self): - return len(self._store) - - def first(self): - if len(self._keys_to_last_time) > 0: - for key in self._keys_to_last_time: - return key - - def sweep(self, sweep_item_cnt = SWEEP_MAX_ITEMS): - # O(n - m) - now = time.time() - c = 0 - while c < sweep_item_cnt: - if len(self._keys_to_last_time) == 0: - break - for key in self._keys_to_last_time: - break - last_t = self._keys_to_last_time[key] - if now - last_t <= self.timeout: - break - value = self._store[key] - del self._store[key] - del self._keys_to_last_time[key] - if self.close_callback is not None: - self.close_callback(value) - c += 1 - if c: - logging.debug('%d keys swept' % c) - return c < SWEEP_MAX_ITEMS - - def clear(self, keep): - now = time.time() - c = 0 - while len(self._keys_to_last_time) > keep: - if len(self._keys_to_last_time) == 0: - break - for key in self._keys_to_last_time: - break - last_t = self._keys_to_last_time[key] - value = self._store[key] - if self.close_callback is not None: - self.close_callback(value) - del self._store[key] - del self._keys_to_last_time[key] - c += 1 - if c: - logging.debug('%d keys swept' % c) - return c < SWEEP_MAX_ITEMS - -def test(): - c = LRUCache(timeout=0.3) - - c['a'] = 1 - assert c['a'] == 1 - c['a'] = 1 - - time.sleep(0.5) - c.sweep() - assert 'a' not in c - - c['a'] = 2 - c['b'] = 3 - time.sleep(0.2) - c.sweep() - assert c['a'] == 2 - assert c['b'] == 3 - - time.sleep(0.2) - c.sweep() - c['b'] - time.sleep(0.2) - c.sweep() - assert 'a' not in c - assert c['b'] == 3 - - time.sleep(0.5) - c.sweep() - assert 'a' not in c - assert 'b' not in c - - global close_cb_called - close_cb_called = False - - def close_cb(t): - global close_cb_called - assert not close_cb_called - close_cb_called = True - - c = LRUCache(timeout=0.1, close_callback=close_cb) - c['s'] = 1 - c['s'] - time.sleep(0.1) - c['s'] - time.sleep(0.3) - c.sweep() - -if __name__ == '__main__': - test() diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/manager.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/manager.py deleted file mode 100644 index ac2a666469..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/manager.py +++ /dev/null @@ -1,291 +0,0 @@ -#!/usr/bin/python3 -# -*- coding: utf-8 -*- -# -# Copyright 2015 clowwindy -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import absolute_import, division, print_function, \ - with_statement - -import errno -import traceback -import socket -import logging -import json -import collections - -from shadowsocks import common, eventloop, tcprelay, udprelay, asyncdns, shell - - -BUF_SIZE = 1506 -STAT_SEND_LIMIT = 50 - - -class Manager(object): - - def __init__(self, config): - self._config = config - self._relays = {} # (tcprelay, udprelay) - self._loop = eventloop.EventLoop() - self._dns_resolver = asyncdns.DNSResolver() - self._dns_resolver.add_to_loop(self._loop) - - self._statistics = collections.defaultdict(int) - self._control_client_addr = None - try: - manager_address = common.to_str(config['manager_address']) - if ':' in manager_address: - addr = manager_address.rsplit(':', 1) - addr = addr[0], int(addr[1]) - addrs = socket.getaddrinfo(addr[0], addr[1]) - if addrs: - family = addrs[0][0] - else: - logging.error('invalid address: %s', manager_address) - exit(1) - else: - addr = manager_address - family = socket.AF_UNIX - self._control_socket = socket.socket(family, - socket.SOCK_DGRAM) - self._control_socket.bind(addr) - self._control_socket.setblocking(False) - except (OSError, IOError) as e: - logging.error(e) - logging.error('can not bind to manager address') - exit(1) - self._loop.add(self._control_socket, - eventloop.POLL_IN, self) - self._loop.add_periodic(self.handle_periodic) - - port_password = config['port_password'] - del config['port_password'] - for port, password in port_password.items(): - a_config = config.copy() - a_config['server_port'] = int(port) - a_config['password'] = password - self.add_port(a_config) - - def add_port(self, config): - port = int(config['server_port']) - servers = self._relays.get(port, None) - if servers: - logging.error("server already exists at %s:%d" % (config['server'], - port)) - return - logging.info("adding server at %s:%d" % (config['server'], port)) - t = tcprelay.TCPRelay(config, self._dns_resolver, False, - stat_callback=self.stat_callback) - u = udprelay.UDPRelay(config, self._dns_resolver, False, - stat_callback=self.stat_callback) - t.add_to_loop(self._loop) - u.add_to_loop(self._loop) - self._relays[port] = (t, u) - - def remove_port(self, config): - port = int(config['server_port']) - servers = self._relays.get(port, None) - if servers: - logging.info("removing server at %s:%d" % (config['server'], port)) - t, u = servers - t.close(next_tick=False) - u.close(next_tick=False) - del self._relays[port] - else: - logging.error("server not exist at %s:%d" % (config['server'], - port)) - - def handle_event(self, sock, fd, event): - if sock == self._control_socket and event == eventloop.POLL_IN: - data, self._control_client_addr = sock.recvfrom(BUF_SIZE) - parsed = self._parse_command(data) - if parsed: - command, config = parsed - a_config = self._config.copy() - if config: - # let the command override the configuration file - a_config.update(config) - if 'server_port' not in a_config: - logging.error('can not find server_port in config') - else: - if command == 'add': - self.add_port(a_config) - self._send_control_data(b'ok') - elif command == 'remove': - self.remove_port(a_config) - self._send_control_data(b'ok') - elif command == 'ping': - self._send_control_data(b'pong') - else: - logging.error('unknown command %s', command) - - def _parse_command(self, data): - # commands: - # add: {"server_port": 8000, "password": "foobar"} - # remove: {"server_port": 8000"} - data = common.to_str(data) - parts = data.split(':', 1) - if len(parts) < 2: - return data, None - command, config_json = parts - try: - config = shell.parse_json_in_str(config_json) - return command, config - except Exception as e: - logging.error(e) - return None - - def stat_callback(self, port, data_len): - self._statistics[port] += data_len - - def handle_periodic(self): - r = {} - i = 0 - - def send_data(data_dict): - if data_dict: - # use compact JSON format (without space) - data = common.to_bytes(json.dumps(data_dict, - separators=(',', ':'))) - self._send_control_data(b'stat: ' + data) - - for k, v in self._statistics.items(): - r[k] = v - i += 1 - # split the data into segments that fit in UDP packets - if i >= STAT_SEND_LIMIT: - send_data(r) - r.clear() - i = 0 - if len(r) > 0 : - send_data(r) - self._statistics.clear() - - def _send_control_data(self, data): - if self._control_client_addr: - try: - self._control_socket.sendto(data, self._control_client_addr) - except (socket.error, OSError, IOError) as e: - error_no = eventloop.errno_from_exception(e) - if error_no in (errno.EAGAIN, errno.EINPROGRESS, - errno.EWOULDBLOCK): - return - else: - shell.print_exception(e) - if self._config['verbose']: - traceback.print_exc() - - def run(self): - self._loop.run() - - -def run(config): - Manager(config).run() - - -def test(): - import time - import threading - import struct - from shadowsocks import encrypt - - logging.basicConfig(level=5, - format='%(asctime)s %(levelname)-8s %(message)s', - datefmt='%Y-%m-%d %H:%M:%S') - enc = [] - eventloop.TIMEOUT_PRECISION = 1 - - def run_server(): - config = shell.get_config(True) - config = config.copy() - a_config = { - 'server': '127.0.0.1', - 'local_port': 1081, - 'port_password': { - '8381': 'foobar1', - '8382': 'foobar2' - }, - 'method': 'aes-256-cfb', - 'manager_address': '127.0.0.1:6001', - 'timeout': 60, - 'fast_open': False, - 'verbose': 2 - } - config.update(a_config) - manager = Manager(config) - enc.append(manager) - manager.run() - - t = threading.Thread(target=run_server) - t.start() - time.sleep(1) - manager = enc[0] - cli = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - cli.connect(('127.0.0.1', 6001)) - - # test add and remove - time.sleep(1) - cli.send(b'add: {"server_port":7001, "password":"asdfadsfasdf"}') - time.sleep(1) - assert 7001 in manager._relays - data, addr = cli.recvfrom(1506) - assert b'ok' in data - - cli.send(b'remove: {"server_port":8381}') - time.sleep(1) - assert 8381 not in manager._relays - data, addr = cli.recvfrom(1506) - assert b'ok' in data - logging.info('add and remove test passed') - - # test statistics for TCP - header = common.pack_addr(b'google.com') + struct.pack('>H', 80) - data = encrypt.encrypt_all(b'asdfadsfasdf', 'aes-256-cfb', 1, - header + b'GET /\r\n\r\n') - tcp_cli = socket.socket() - tcp_cli.connect(('127.0.0.1', 7001)) - tcp_cli.send(data) - tcp_cli.recv(4096) - tcp_cli.close() - - data, addr = cli.recvfrom(1506) - data = common.to_str(data) - assert data.startswith('stat: ') - data = data.split('stat:')[1] - stats = shell.parse_json_in_str(data) - assert '7001' in stats - logging.info('TCP statistics test passed') - - # test statistics for UDP - header = common.pack_addr(b'127.0.0.1') + struct.pack('>H', 80) - data = encrypt.encrypt_all(b'foobar2', 'aes-256-cfb', 1, - header + b'test') - udp_cli = socket.socket(type=socket.SOCK_DGRAM) - udp_cli.sendto(data, ('127.0.0.1', 8382)) - tcp_cli.close() - - data, addr = cli.recvfrom(1506) - data = common.to_str(data) - assert data.startswith('stat: ') - data = data.split('stat:')[1] - stats = json.loads(data) - assert '8382' in stats - logging.info('UDP statistics test passed') - - manager._loop.stop() - t.join() - - -if __name__ == '__main__': - test() diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfs.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfs.py deleted file mode 100644 index dcc305f367..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfs.py +++ /dev/null @@ -1,114 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright 2015-2015 breakwa11 -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import absolute_import, division, print_function, \ - with_statement - -import os -import sys -import hashlib -import logging - -from shadowsocks import common -from shadowsocks.obfsplugin import plain, http_simple, obfs_tls, verify, auth, auth_chain - - -method_supported = {} -method_supported.update(plain.obfs_map) -method_supported.update(http_simple.obfs_map) -method_supported.update(obfs_tls.obfs_map) -method_supported.update(verify.obfs_map) -method_supported.update(auth.obfs_map) -method_supported.update(auth_chain.obfs_map) - -def mu_protocol(): - return ["auth_aes128_md5", "auth_aes128_sha1", "auth_chain_a"] - -class server_info(object): - def __init__(self, data): - self.data = data - -class obfs(object): - def __init__(self, method): - method = common.to_str(method) - self.method = method - self._method_info = self.get_method_info(method) - if self._method_info: - self.obfs = self.get_obfs(method) - else: - raise Exception('obfs plugin [%s] not supported' % method) - - def init_data(self): - return self.obfs.init_data() - - def set_server_info(self, server_info): - return self.obfs.set_server_info(server_info) - - def get_server_info(self): - return self.obfs.get_server_info() - - def get_method_info(self, method): - method = method.lower() - m = method_supported.get(method) - return m - - def get_obfs(self, method): - m = self._method_info - return m[0](method) - - def get_overhead(self, direction): - return self.obfs.get_overhead(direction) - - def client_pre_encrypt(self, buf): - return self.obfs.client_pre_encrypt(buf) - - def client_encode(self, buf): - return self.obfs.client_encode(buf) - - def client_decode(self, buf): - return self.obfs.client_decode(buf) - - def client_post_decrypt(self, buf): - return self.obfs.client_post_decrypt(buf) - - def server_pre_encrypt(self, buf): - return self.obfs.server_pre_encrypt(buf) - - def server_encode(self, buf): - return self.obfs.server_encode(buf) - - def server_decode(self, buf): - return self.obfs.server_decode(buf) - - def server_post_decrypt(self, buf): - return self.obfs.server_post_decrypt(buf) - - def client_udp_pre_encrypt(self, buf): - return self.obfs.client_udp_pre_encrypt(buf) - - def client_udp_post_decrypt(self, buf): - return self.obfs.client_udp_post_decrypt(buf) - - def server_udp_pre_encrypt(self, buf, uid): - return self.obfs.server_udp_pre_encrypt(buf, uid) - - def server_udp_post_decrypt(self, buf): - return self.obfs.server_udp_post_decrypt(buf) - - def dispose(self): - self.obfs.dispose() - del self.obfs - diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/__init__.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/__init__.py deleted file mode 100644 index 2bc532d629..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright 2015 clowwindy -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import absolute_import, division, print_function, \ - with_statement diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/auth.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/auth.py deleted file mode 100644 index d3d4743e29..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/auth.py +++ /dev/null @@ -1,787 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright 2015-2015 breakwa11 -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import absolute_import, division, print_function, \ - with_statement - -import os -import sys -import hashlib -import logging -import binascii -import base64 -import time -import datetime -import random -import math -import struct -import zlib -import hmac -import hashlib - -import shadowsocks -from shadowsocks import common, lru_cache, encrypt -from shadowsocks.obfsplugin import plain -from shadowsocks.common import to_bytes, to_str, ord, chr - -def create_auth_sha1_v4(method): - return auth_sha1_v4(method) - -def create_auth_aes128_md5(method): - return auth_aes128_sha1(method, hashlib.md5) - -def create_auth_aes128_sha1(method): - return auth_aes128_sha1(method, hashlib.sha1) - -obfs_map = { - 'auth_sha1_v4': (create_auth_sha1_v4,), - 'auth_sha1_v4_compatible': (create_auth_sha1_v4,), - 'auth_aes128_md5': (create_auth_aes128_md5,), - 'auth_aes128_sha1': (create_auth_aes128_sha1,), -} - -def match_begin(str1, str2): - if len(str1) >= len(str2): - if str1[:len(str2)] == str2: - return True - return False - -class auth_base(plain.plain): - def __init__(self, method): - super(auth_base, self).__init__(method) - self.method = method - self.no_compatible_method = '' - self.overhead = 7 - - def init_data(self): - return '' - - def get_overhead(self, direction): # direction: true for c->s false for s->c - return self.overhead - - def set_server_info(self, server_info): - self.server_info = server_info - - def client_encode(self, buf): - return buf - - def client_decode(self, buf): - return (buf, False) - - def server_encode(self, buf): - return buf - - def server_decode(self, buf): - return (buf, True, False) - - def not_match_return(self, buf): - self.raw_trans = True - self.overhead = 0 - if self.method == self.no_compatible_method: - return (b'E'*2048, False) - return (buf, False) - -class client_queue(object): - def __init__(self, begin_id): - self.front = begin_id - 64 - self.back = begin_id + 1 - self.alloc = {} - self.enable = True - self.last_update = time.time() - - def update(self): - self.last_update = time.time() - - def is_active(self): - return time.time() - self.last_update < 60 * 3 - - def re_enable(self, connection_id): - self.enable = True - self.front = connection_id - 64 - self.back = connection_id + 1 - self.alloc = {} - - def insert(self, connection_id): - if not self.enable: - logging.warn('obfs auth: not enable') - return False - if not self.is_active(): - self.re_enable(connection_id) - self.update() - if connection_id < self.front: - logging.warn('obfs auth: deprecated id, someone replay attack') - return False - if connection_id > self.front + 0x4000: - logging.warn('obfs auth: wrong id') - return False - if connection_id in self.alloc: - logging.warn('obfs auth: duplicate id, someone replay attack') - return False - if self.back <= connection_id: - self.back = connection_id + 1 - self.alloc[connection_id] = 1 - while (self.front in self.alloc) or self.front + 0x1000 < self.back: - if self.front in self.alloc: - del self.alloc[self.front] - self.front += 1 - return True - -class obfs_auth_v2_data(object): - def __init__(self): - self.client_id = lru_cache.LRUCache() - self.local_client_id = b'' - self.connection_id = 0 - self.set_max_client(64) # max active client count - - def update(self, client_id, connection_id): - if client_id in self.client_id: - self.client_id[client_id].update() - - def set_max_client(self, max_client): - self.max_client = max_client - self.max_buffer = max(self.max_client * 2, 1024) - - def insert(self, client_id, connection_id): - if self.client_id.get(client_id, None) is None or not self.client_id[client_id].enable: - if self.client_id.first() is None or len(self.client_id) < self.max_client: - if client_id not in self.client_id: - #TODO: check - self.client_id[client_id] = client_queue(connection_id) - else: - self.client_id[client_id].re_enable(connection_id) - return self.client_id[client_id].insert(connection_id) - - if not self.client_id[self.client_id.first()].is_active(): - del self.client_id[self.client_id.first()] - if client_id not in self.client_id: - #TODO: check - self.client_id[client_id] = client_queue(connection_id) - else: - self.client_id[client_id].re_enable(connection_id) - return self.client_id[client_id].insert(connection_id) - - logging.warn('auth_sha1_v2: no inactive client') - return False - else: - return self.client_id[client_id].insert(connection_id) - -class auth_sha1_v4(auth_base): - def __init__(self, method): - super(auth_sha1_v4, self).__init__(method) - self.recv_buf = b'' - self.unit_len = 8100 - self.decrypt_packet_num = 0 - self.raw_trans = False - self.has_sent_header = False - self.has_recv_header = False - self.client_id = 0 - self.connection_id = 0 - self.max_time_dif = 60 * 60 * 24 # time dif (second) setting - self.salt = b"auth_sha1_v4" - self.no_compatible_method = 'auth_sha1_v4' - - def init_data(self): - return obfs_auth_v2_data() - - def set_server_info(self, server_info): - self.server_info = server_info - try: - max_client = int(server_info.protocol_param) - except: - max_client = 64 - self.server_info.data.set_max_client(max_client) - - def rnd_data(self, buf_size): - if buf_size > 1200: - return b'\x01' - - if buf_size > 400: - rnd_data = os.urandom(common.ord(os.urandom(1)[0]) % 256) - else: - rnd_data = os.urandom(struct.unpack('>H', os.urandom(2))[0] % 512) - - if len(rnd_data) < 128: - return common.chr(len(rnd_data) + 1) + rnd_data - else: - return common.chr(255) + struct.pack('>H', len(rnd_data) + 3) + rnd_data - - def pack_data(self, buf): - data = self.rnd_data(len(buf)) + buf - data_len = len(data) + 8 - crc = binascii.crc32(struct.pack('>H', data_len)) & 0xFFFF - data = struct.pack('H', data_len) + data - adler32 = zlib.adler32(data) & 0xFFFFFFFF - data += struct.pack('H', data_len) + self.salt + self.server_info.key) & 0xFFFFFFFF - data = struct.pack('H', data_len) + data - data += hmac.new(self.server_info.iv + self.server_info.key, data, hashlib.sha1).digest()[:10] - return data - - def auth_data(self): - utc_time = int(time.time()) & 0xFFFFFFFF - if self.server_info.data.connection_id > 0xFF000000: - self.server_info.data.local_client_id = b'' - if not self.server_info.data.local_client_id: - self.server_info.data.local_client_id = os.urandom(4) - logging.debug("local_client_id %s" % (binascii.hexlify(self.server_info.data.local_client_id),)) - self.server_info.data.connection_id = struct.unpack(' self.unit_len: - ret += self.pack_data(buf[:self.unit_len]) - buf = buf[self.unit_len:] - ret += self.pack_data(buf) - return ret - - def client_post_decrypt(self, buf): - if self.raw_trans: - return buf - self.recv_buf += buf - out_buf = b'' - while len(self.recv_buf) > 4: - crc = struct.pack('H', self.recv_buf[:2])[0] - if length >= 8192 or length < 7: - self.raw_trans = True - self.recv_buf = b'' - raise Exception('client_post_decrypt data error') - if length > len(self.recv_buf): - break - - if struct.pack('H', self.recv_buf[5:7])[0] + 4 - out_buf += self.recv_buf[pos:length - 4] - self.recv_buf = self.recv_buf[length:] - - if out_buf: - self.decrypt_packet_num += 1 - return out_buf - - def server_pre_encrypt(self, buf): - if self.raw_trans: - return buf - ret = b'' - while len(buf) > self.unit_len: - ret += self.pack_data(buf[:self.unit_len]) - buf = buf[self.unit_len:] - ret += self.pack_data(buf) - return ret - - def server_post_decrypt(self, buf): - if self.raw_trans: - return (buf, False) - self.recv_buf += buf - out_buf = b'' - sendback = False - - if not self.has_recv_header: - if len(self.recv_buf) <= 6: - return (b'', False) - crc = struct.pack('H', self.recv_buf[:2])[0] - if length > len(self.recv_buf): - return (b'', False) - sha1data = hmac.new(self.server_info.recv_iv + self.server_info.key, self.recv_buf[:length - 10], hashlib.sha1).digest()[:10] - if sha1data != self.recv_buf[length - 10:length]: - logging.error('auth_sha1_v4 data uncorrect auth HMAC-SHA1') - return self.not_match_return(self.recv_buf) - pos = common.ord(self.recv_buf[6]) - if pos < 255: - pos += 6 - else: - pos = struct.unpack('>H', self.recv_buf[7:9])[0] + 6 - out_buf = self.recv_buf[pos:length - 10] - if len(out_buf) < 12: - logging.info('auth_sha1_v4: too short, data %s' % (binascii.hexlify(self.recv_buf),)) - return self.not_match_return(self.recv_buf) - utc_time = struct.unpack(' self.max_time_dif: - logging.info('auth_sha1_v4: wrong timestamp, time_dif %d, data %s' % (time_dif, binascii.hexlify(out_buf),)) - return self.not_match_return(self.recv_buf) - elif self.server_info.data.insert(client_id, connection_id): - self.has_recv_header = True - out_buf = out_buf[12:] - self.client_id = client_id - self.connection_id = connection_id - else: - logging.info('auth_sha1_v4: auth fail, data %s' % (binascii.hexlify(out_buf),)) - return self.not_match_return(self.recv_buf) - self.recv_buf = self.recv_buf[length:] - self.has_recv_header = True - sendback = True - - while len(self.recv_buf) > 4: - crc = struct.pack('H', self.recv_buf[:2])[0] - if length >= 8192 or length < 7: - self.raw_trans = True - self.recv_buf = b'' - if self.decrypt_packet_num == 0: - logging.info('auth_sha1_v4: over size') - return (b'E'*2048, False) - else: - raise Exception('server_post_decrype data error') - if length > len(self.recv_buf): - break - - if struct.pack('H', self.recv_buf[5:7])[0] + 4 - out_buf += self.recv_buf[pos:length - 4] - self.recv_buf = self.recv_buf[length:] - if pos == length - 4: - sendback = True - - if out_buf: - self.server_info.data.update(self.client_id, self.connection_id) - self.decrypt_packet_num += 1 - return (out_buf, sendback) - -class obfs_auth_mu_data(object): - def __init__(self): - self.user_id = {} - self.local_client_id = b'' - self.connection_id = 0 - self.set_max_client(64) # max active client count - - def update(self, user_id, client_id, connection_id): - if user_id not in self.user_id: - self.user_id[user_id] = lru_cache.LRUCache() - local_client_id = self.user_id[user_id] - - if client_id in local_client_id: - local_client_id[client_id].update() - - def set_max_client(self, max_client): - self.max_client = max_client - self.max_buffer = max(self.max_client * 2, 1024) - - def insert(self, user_id, client_id, connection_id): - if user_id not in self.user_id: - self.user_id[user_id] = lru_cache.LRUCache() - local_client_id = self.user_id[user_id] - - if local_client_id.get(client_id, None) is None or not local_client_id[client_id].enable: - if local_client_id.first() is None or len(local_client_id) < self.max_client: - if client_id not in local_client_id: - #TODO: check - local_client_id[client_id] = client_queue(connection_id) - else: - local_client_id[client_id].re_enable(connection_id) - return local_client_id[client_id].insert(connection_id) - - if not local_client_id[local_client_id.first()].is_active(): - del local_client_id[local_client_id.first()] - if client_id not in local_client_id: - #TODO: check - local_client_id[client_id] = client_queue(connection_id) - else: - local_client_id[client_id].re_enable(connection_id) - return local_client_id[client_id].insert(connection_id) - - logging.warn('auth_aes128: no inactive client') - return False - else: - return local_client_id[client_id].insert(connection_id) - -class auth_aes128_sha1(auth_base): - def __init__(self, method, hashfunc): - super(auth_aes128_sha1, self).__init__(method) - self.hashfunc = hashfunc - self.recv_buf = b'' - self.unit_len = 8100 - self.raw_trans = False - self.has_sent_header = False - self.has_recv_header = False - self.client_id = 0 - self.connection_id = 0 - self.max_time_dif = 60 * 60 * 24 # time dif (second) setting - self.salt = hashfunc == hashlib.md5 and b"auth_aes128_md5" or b"auth_aes128_sha1" - self.no_compatible_method = hashfunc == hashlib.md5 and "auth_aes128_md5" or 'auth_aes128_sha1' - self.extra_wait_size = struct.unpack('>H', os.urandom(2))[0] % 1024 - self.pack_id = 1 - self.recv_id = 1 - self.user_id = None - self.user_key = None - self.last_rnd_len = 0 - self.overhead = 9 - - def init_data(self): - return obfs_auth_mu_data() - - def get_overhead(self, direction): # direction: true for c->s false for s->c - return self.overhead - - def set_server_info(self, server_info): - self.server_info = server_info - try: - max_client = int(server_info.protocol_param.split('#')[0]) - except: - max_client = 64 - self.server_info.data.set_max_client(max_client) - - def trapezoid_random_float(self, d): - if d == 0: - return random.random() - s = random.random() - a = 1 - d - return (math.sqrt(a * a + 4 * d * s) - a) / (2 * d) - - def trapezoid_random_int(self, max_val, d): - v = self.trapezoid_random_float(d) - return int(v * max_val) - - def rnd_data_len(self, buf_size, full_buf_size): - if full_buf_size >= self.server_info.buffer_size: - return 0 - tcp_mss = self.server_info.tcp_mss - rev_len = tcp_mss - buf_size - 9 - if rev_len == 0: - return 0 - if rev_len < 0: - if rev_len > -tcp_mss: - return self.trapezoid_random_int(rev_len + tcp_mss, -0.3) - return common.ord(os.urandom(1)[0]) % 32 - if buf_size > 900: - return struct.unpack('>H', os.urandom(2))[0] % rev_len - return self.trapezoid_random_int(rev_len, -0.3) - - def rnd_data(self, buf_size, full_buf_size): - data_len = self.rnd_data_len(buf_size, full_buf_size) - - if data_len < 128: - return common.chr(data_len + 1) + os.urandom(data_len) - - return common.chr(255) + struct.pack(' 400: - rnd_len = struct.unpack(' 0xFF000000: - self.server_info.data.local_client_id = b'' - if not self.server_info.data.local_client_id: - self.server_info.data.local_client_id = os.urandom(4) - logging.debug("local_client_id %s" % (binascii.hexlify(self.server_info.data.local_client_id),)) - self.server_info.data.connection_id = struct.unpack(' self.unit_len: - ret += self.pack_data(buf[:self.unit_len], ogn_data_len) - buf = buf[self.unit_len:] - ret += self.pack_data(buf, ogn_data_len) - self.last_rnd_len = ogn_data_len - return ret - - def client_post_decrypt(self, buf): - if self.raw_trans: - return buf - self.recv_buf += buf - out_buf = b'' - while len(self.recv_buf) > 4: - mac_key = self.user_key + struct.pack('= 8192 or length < 7: - self.raw_trans = True - self.recv_buf = b'' - raise Exception('client_post_decrypt data error') - if length > len(self.recv_buf): - break - - if hmac.new(mac_key, self.recv_buf[:length - 4], self.hashfunc).digest()[:4] != self.recv_buf[length - 4:length]: - self.raw_trans = True - self.recv_buf = b'' - raise Exception('client_post_decrypt data uncorrect checksum') - - self.recv_id = (self.recv_id + 1) & 0xFFFFFFFF - pos = common.ord(self.recv_buf[4]) - if pos < 255: - pos += 4 - else: - pos = struct.unpack(' self.unit_len: - ret += self.pack_data(buf[:self.unit_len], ogn_data_len) - buf = buf[self.unit_len:] - ret += self.pack_data(buf, ogn_data_len) - self.last_rnd_len = ogn_data_len - return ret - - def server_post_decrypt(self, buf): - if self.raw_trans: - return (buf, False) - self.recv_buf += buf - out_buf = b'' - sendback = False - - if not self.has_recv_header: - if len(self.recv_buf) >= 7 or len(self.recv_buf) in [2, 3]: - recv_len = min(len(self.recv_buf), 7) - mac_key = self.server_info.recv_iv + self.server_info.key - sha1data = hmac.new(mac_key, self.recv_buf[:1], self.hashfunc).digest()[:recv_len - 1] - if sha1data != self.recv_buf[1:recv_len]: - return self.not_match_return(self.recv_buf) - - if len(self.recv_buf) < 31: - return (b'', False) - sha1data = hmac.new(mac_key, self.recv_buf[7:27], self.hashfunc).digest()[:4] - if sha1data != self.recv_buf[27:31]: - logging.error('%s data uncorrect auth HMAC-SHA1 from %s:%d, data %s' % (self.no_compatible_method, self.server_info.client, self.server_info.client_port, binascii.hexlify(self.recv_buf))) - if len(self.recv_buf) < 31 + self.extra_wait_size: - return (b'', False) - return self.not_match_return(self.recv_buf) - - uid = self.recv_buf[7:11] - if uid in self.server_info.users: - self.user_id = uid - self.user_key = self.hashfunc(self.server_info.users[uid]).digest() - self.server_info.update_user_func(uid) - else: - if not self.server_info.users: - self.user_key = self.server_info.key - else: - self.user_key = self.server_info.recv_iv - encryptor = encrypt.Encryptor(to_bytes(base64.b64encode(self.user_key)) + self.salt, 'aes-128-cbc') - head = encryptor.decrypt(b'\x00' * 16 + self.recv_buf[11:27] + b'\x00') # need an extra byte or recv empty - length = struct.unpack(' self.max_time_dif: - logging.info('%s: wrong timestamp, time_dif %d, data %s' % (self.no_compatible_method, time_dif, binascii.hexlify(head))) - return self.not_match_return(self.recv_buf) - elif self.server_info.data.insert(self.user_id, client_id, connection_id): - self.has_recv_header = True - out_buf = self.recv_buf[31 + rnd_len:length - 4] - self.client_id = client_id - self.connection_id = connection_id - else: - logging.info('%s: auth fail, data %s' % (self.no_compatible_method, binascii.hexlify(out_buf))) - return self.not_match_return(self.recv_buf) - self.recv_buf = self.recv_buf[length:] - self.has_recv_header = True - sendback = True - - while len(self.recv_buf) > 4: - mac_key = self.user_key + struct.pack('= 8192 or length < 7: - self.raw_trans = True - self.recv_buf = b'' - if self.recv_id == 0: - logging.info(self.no_compatible_method + ': over size') - return (b'E'*2048, False) - else: - raise Exception('server_post_decrype data error') - if length > len(self.recv_buf): - break - - if hmac.new(mac_key, self.recv_buf[:length - 4], self.hashfunc).digest()[:4] != self.recv_buf[length - 4:length]: - logging.info('%s: checksum error, data %s' % (self.no_compatible_method, binascii.hexlify(self.recv_buf[:length]))) - self.raw_trans = True - self.recv_buf = b'' - if self.recv_id == 0: - return (b'E'*2048, False) - else: - raise Exception('server_post_decrype data uncorrect checksum') - - self.recv_id = (self.recv_id + 1) & 0xFFFFFFFF - pos = common.ord(self.recv_buf[4]) - if pos < 255: - pos += 4 - else: - pos = struct.unpack('> 17) ^ (y >> 26)) & xorshift128plus.max_int - self.v1 = x - return (x + y) & xorshift128plus.max_int - - def init_from_bin(self, bin): - bin += b'\0' * 16 - self.v0 = struct.unpack('= len(str2): - if str1[:len(str2)] == str2: - return True - return False - -class auth_base(plain.plain): - def __init__(self, method): - super(auth_base, self).__init__(method) - self.method = method - self.no_compatible_method = '' - self.overhead = 4 - - def init_data(self): - return '' - - def get_overhead(self, direction): # direction: true for c->s false for s->c - return self.overhead - - def set_server_info(self, server_info): - self.server_info = server_info - - def client_encode(self, buf): - return buf - - def client_decode(self, buf): - return (buf, False) - - def server_encode(self, buf): - return buf - - def server_decode(self, buf): - return (buf, True, False) - - def not_match_return(self, buf): - self.raw_trans = True - self.overhead = 0 - if self.method == self.no_compatible_method: - return (b'E'*2048, False) - return (buf, False) - -class client_queue(object): - def __init__(self, begin_id): - self.front = begin_id - 64 - self.back = begin_id + 1 - self.alloc = {} - self.enable = True - self.last_update = time.time() - self.ref = 0 - - def update(self): - self.last_update = time.time() - - def addref(self): - self.ref += 1 - - def delref(self): - if self.ref > 0: - self.ref -= 1 - - def is_active(self): - return (self.ref > 0) and (time.time() - self.last_update < 60 * 10) - - def re_enable(self, connection_id): - self.enable = True - self.front = connection_id - 64 - self.back = connection_id + 1 - self.alloc = {} - - def insert(self, connection_id): - if not self.enable: - logging.warn('obfs auth: not enable') - return False - if not self.is_active(): - self.re_enable(connection_id) - self.update() - if connection_id < self.front: - logging.warn('obfs auth: deprecated id, someone replay attack') - return False - if connection_id > self.front + 0x4000: - logging.warn('obfs auth: wrong id') - return False - if connection_id in self.alloc: - logging.warn('obfs auth: duplicate id, someone replay attack') - return False - if self.back <= connection_id: - self.back = connection_id + 1 - self.alloc[connection_id] = 1 - while (self.front in self.alloc) or self.front + 0x1000 < self.back: - if self.front in self.alloc: - del self.alloc[self.front] - self.front += 1 - self.addref() - return True - -class obfs_auth_chain_data(object): - def __init__(self, name): - self.name = name - self.user_id = {} - self.local_client_id = b'' - self.connection_id = 0 - self.set_max_client(64) # max active client count - - def update(self, user_id, client_id, connection_id): - if user_id not in self.user_id: - self.user_id[user_id] = lru_cache.LRUCache() - local_client_id = self.user_id[user_id] - - if client_id in local_client_id: - local_client_id[client_id].update() - - def set_max_client(self, max_client): - self.max_client = max_client - self.max_buffer = max(self.max_client * 2, 1024) - - def insert(self, user_id, client_id, connection_id): - if user_id not in self.user_id: - self.user_id[user_id] = lru_cache.LRUCache() - local_client_id = self.user_id[user_id] - - if local_client_id.get(client_id, None) is None or not local_client_id[client_id].enable: - if local_client_id.first() is None or len(local_client_id) < self.max_client: - if client_id not in local_client_id: - #TODO: check - local_client_id[client_id] = client_queue(connection_id) - else: - local_client_id[client_id].re_enable(connection_id) - return local_client_id[client_id].insert(connection_id) - - if not local_client_id[local_client_id.first()].is_active(): - del local_client_id[local_client_id.first()] - if client_id not in local_client_id: - #TODO: check - local_client_id[client_id] = client_queue(connection_id) - else: - local_client_id[client_id].re_enable(connection_id) - return local_client_id[client_id].insert(connection_id) - - logging.warn(self.name + ': no inactive client') - return False - else: - return local_client_id[client_id].insert(connection_id) - - def remove(self, user_id, client_id): - if user_id in self.user_id: - local_client_id = self.user_id[user_id] - if client_id in local_client_id: - local_client_id[client_id].delref() - -class auth_chain_a(auth_base): - def __init__(self, method): - super(auth_chain_a, self).__init__(method) - self.hashfunc = hashlib.md5 - self.recv_buf = b'' - self.unit_len = 2800 - self.raw_trans = False - self.has_sent_header = False - self.has_recv_header = False - self.client_id = 0 - self.connection_id = 0 - self.max_time_dif = 60 * 60 * 24 # time dif (second) setting - self.salt = b"auth_chain_a" - self.no_compatible_method = 'auth_chain_a' - self.pack_id = 1 - self.recv_id = 1 - self.user_id = None - self.user_id_num = 0 - self.user_key = None - self.overhead = 4 - self.client_over_head = 4 - self.last_client_hash = b'' - self.last_server_hash = b'' - self.random_client = xorshift128plus() - self.random_server = xorshift128plus() - self.encryptor = None - - def init_data(self): - return obfs_auth_chain_data(self.method) - - def get_overhead(self, direction): # direction: true for c->s false for s->c - return self.overhead - - def set_server_info(self, server_info): - self.server_info = server_info - try: - max_client = int(server_info.protocol_param.split('#')[0]) - except: - max_client = 64 - self.server_info.data.set_max_client(max_client) - - def trapezoid_random_float(self, d): - if d == 0: - return random.random() - s = random.random() - a = 1 - d - return (math.sqrt(a * a + 4 * d * s) - a) / (2 * d) - - def trapezoid_random_int(self, max_val, d): - v = self.trapezoid_random_float(d) - return int(v * max_val) - - def rnd_data_len(self, buf_size, last_hash, random): - if buf_size > 1440: - return 0 - random.init_from_bin_len(last_hash, buf_size) - if buf_size > 1300: - return random.next() % 31 - if buf_size > 900: - return random.next() % 127 - if buf_size > 400: - return random.next() % 521 - return random.next() % 1021 - - def udp_rnd_data_len(self, last_hash, random): - random.init_from_bin(last_hash) - return random.next() % 127 - - def rnd_start_pos(self, rand_len, random): - if rand_len > 0: - return random.next() % 8589934609 % rand_len - return 0 - - def rnd_data(self, buf_size, buf, last_hash, random): - rand_len = self.rnd_data_len(buf_size, last_hash, random) - - rnd_data_buf = os.urandom(rand_len) - - if buf_size == 0: - return rnd_data_buf - else: - if rand_len > 0: - start_pos = self.rnd_start_pos(rand_len, random) - return rnd_data_buf[:start_pos] + buf + rnd_data_buf[start_pos:] - else: - return buf - - def pack_client_data(self, buf): - buf = self.encryptor.encrypt(buf) - data = self.rnd_data(len(buf), buf, self.last_client_hash, self.random_client) - data_len = len(data) + 8 - mac_key = self.user_key + struct.pack(' 0xFF000000: - self.server_info.data.local_client_id = b'' - if not self.server_info.data.local_client_id: - self.server_info.data.local_client_id = os.urandom(4) - logging.debug("local_client_id %s" % (binascii.hexlify(self.server_info.data.local_client_id),)) - self.server_info.data.connection_id = struct.unpack(' self.unit_len: - ret += self.pack_client_data(buf[:self.unit_len]) - buf = buf[self.unit_len:] - ret += self.pack_client_data(buf) - return ret - - def client_post_decrypt(self, buf): - if self.raw_trans: - return buf - self.recv_buf += buf - out_buf = b'' - while len(self.recv_buf) > 4: - mac_key = self.user_key + struct.pack('= 4096: - self.raw_trans = True - self.recv_buf = b'' - raise Exception('client_post_decrypt data error') - - if length + 4 > len(self.recv_buf): - break - - server_hash = hmac.new(mac_key, self.recv_buf[:length + 2], self.hashfunc).digest() - if server_hash[:2] != self.recv_buf[length + 2 : length + 4]: - logging.info('%s: checksum error, data %s' % (self.no_compatible_method, binascii.hexlify(self.recv_buf[:length]))) - self.raw_trans = True - self.recv_buf = b'' - raise Exception('client_post_decrypt data uncorrect checksum') - - pos = 2 - if data_len > 0 and rand_len > 0: - pos = 2 + self.rnd_start_pos(rand_len, self.random_server) - out_buf += self.encryptor.decrypt(self.recv_buf[pos : data_len + pos]) - self.last_server_hash = server_hash - if self.recv_id == 1: - self.server_info.tcp_mss = struct.unpack(' self.unit_len: - ret += self.pack_server_data(buf[:self.unit_len]) - buf = buf[self.unit_len:] - ret += self.pack_server_data(buf) - return ret - - def server_post_decrypt(self, buf): - if self.raw_trans: - return (buf, False) - self.recv_buf += buf - out_buf = b'' - sendback = False - - if not self.has_recv_header: - if len(self.recv_buf) >= 12 or len(self.recv_buf) in [7, 8]: - recv_len = min(len(self.recv_buf), 12) - mac_key = self.server_info.recv_iv + self.server_info.key - md5data = hmac.new(mac_key, self.recv_buf[:4], self.hashfunc).digest() - if md5data[:recv_len - 4] != self.recv_buf[4:recv_len]: - return self.not_match_return(self.recv_buf) - - if len(self.recv_buf) < 12 + 24: - return (b'', False) - - self.last_client_hash = md5data - uid = struct.unpack(' self.max_time_dif: - logging.info('%s: wrong timestamp, time_dif %d, data %s' % (self.no_compatible_method, time_dif, binascii.hexlify(head))) - return self.not_match_return(self.recv_buf) - elif self.server_info.data.insert(self.user_id, client_id, connection_id): - self.has_recv_header = True - self.client_id = client_id - self.connection_id = connection_id - else: - logging.info('%s: auth fail, data %s' % (self.no_compatible_method, binascii.hexlify(out_buf))) - return self.not_match_return(self.recv_buf) - - self.encryptor = encrypt.Encryptor(to_bytes(base64.b64encode(self.user_key)) + to_bytes(base64.b64encode(self.last_client_hash)), 'rc4') - self.recv_buf = self.recv_buf[36:] - self.has_recv_header = True - sendback = True - - while len(self.recv_buf) > 4: - mac_key = self.user_key + struct.pack('= 4096: - self.raw_trans = True - self.recv_buf = b'' - if self.recv_id == 0: - logging.info(self.no_compatible_method + ': over size') - return (b'E'*2048, False) - else: - raise Exception('server_post_decrype data error') - - if length + 4 > len(self.recv_buf): - break - - client_hash = hmac.new(mac_key, self.recv_buf[:length + 2], self.hashfunc).digest() - if client_hash[:2] != self.recv_buf[length + 2 : length + 4]: - logging.info('%s: checksum error, data %s' % (self.no_compatible_method, binascii.hexlify(self.recv_buf[:length]))) - self.raw_trans = True - self.recv_buf = b'' - if self.recv_id == 0: - return (b'E'*2048, False) - else: - raise Exception('server_post_decrype data uncorrect checksum') - - self.recv_id = (self.recv_id + 1) & 0xFFFFFFFF - pos = 2 - if data_len > 0 and rand_len > 0: - pos = 2 + self.rnd_start_pos(rand_len, self.random_client) - out_buf += self.encryptor.decrypt(self.recv_buf[pos : data_len + pos]) - self.last_client_hash = client_hash - self.recv_buf = self.recv_buf[length + 4:] - if data_len == 0: - sendback = True - - if out_buf: - self.server_info.data.update(self.user_id, self.client_id, self.connection_id) - return (out_buf, sendback) - - def client_udp_pre_encrypt(self, buf): - if self.user_key is None: - if b':' in to_bytes(self.server_info.protocol_param): - try: - items = to_bytes(self.server_info.protocol_param).split(':') - self.user_key = self.hashfunc(items[1]).digest() - self.user_id = struct.pack('= 1440: - return 0 - random.init_from_bin_len(last_hash, buf_size) - pos = bisect.bisect_left(self.data_size_list, buf_size + self.server_info.overhead) - final_pos = pos + random.next() % (len(self.data_size_list)) - if final_pos < len(self.data_size_list): - return self.data_size_list[final_pos] - buf_size - self.server_info.overhead - - pos = bisect.bisect_left(self.data_size_list2, buf_size + self.server_info.overhead) - final_pos = pos + random.next() % (len(self.data_size_list2)) - if final_pos < len(self.data_size_list2): - return self.data_size_list2[final_pos] - buf_size - self.server_info.overhead - if final_pos < pos + len(self.data_size_list2) - 1: - return 0 - - if buf_size > 1300: - return random.next() % 31 - if buf_size > 900: - return random.next() % 127 - if buf_size > 400: - return random.next() % 521 - return random.next() % 1021 - diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/http_simple.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/http_simple.py deleted file mode 100644 index c76bb63c95..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/http_simple.py +++ /dev/null @@ -1,314 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright 2015-2015 breakwa11 -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import absolute_import, division, print_function, \ - with_statement - -import os -import sys -import hashlib -import logging -import binascii -import struct -import base64 -import datetime -import random - -from shadowsocks import common -from shadowsocks.obfsplugin import plain -from shadowsocks.common import to_bytes, to_str, ord, chr - -def create_http_simple_obfs(method): - return http_simple(method) - -def create_http_post_obfs(method): - return http_post(method) - -def create_random_head_obfs(method): - return random_head(method) - -obfs_map = { - 'http_simple': (create_http_simple_obfs,), - 'http_simple_compatible': (create_http_simple_obfs,), - 'http_post': (create_http_post_obfs,), - 'http_post_compatible': (create_http_post_obfs,), - 'random_head': (create_random_head_obfs,), - 'random_head_compatible': (create_random_head_obfs,), -} - -def match_begin(str1, str2): - if len(str1) >= len(str2): - if str1[:len(str2)] == str2: - return True - return False - -class http_simple(plain.plain): - def __init__(self, method): - self.method = method - self.has_sent_header = False - self.has_recv_header = False - self.host = None - self.port = 0 - self.recv_buffer = b'' - self.user_agent = [b"Mozilla/5.0 (Windows NT 6.3; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0", - b"Mozilla/5.0 (Windows NT 6.3; WOW64; rv:40.0) Gecko/20100101 Firefox/44.0", - b"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36", - b"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.11 (KHTML, like Gecko) Ubuntu/11.10 Chromium/27.0.1453.93 Chrome/27.0.1453.93 Safari/537.36", - b"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:35.0) Gecko/20100101 Firefox/35.0", - b"Mozilla/5.0 (compatible; WOW64; MSIE 10.0; Windows NT 6.2)", - b"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27", - b"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.3; Trident/7.0; .NET4.0E; .NET4.0C)", - b"Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko", - b"Mozilla/5.0 (Linux; Android 4.4; Nexus 5 Build/BuildID) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36", - b"Mozilla/5.0 (iPad; CPU OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3", - b"Mozilla/5.0 (iPhone; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3"] - - def encode_head(self, buf): - hexstr = binascii.hexlify(buf) - chs = [] - for i in range(0, len(hexstr), 2): - chs.append(b"%" + hexstr[i:i+2]) - return b''.join(chs) - - def client_encode(self, buf): - if self.has_sent_header: - return buf - head_size = len(self.server_info.iv) + self.server_info.head_len - if len(buf) - head_size > 64: - headlen = head_size + random.randint(0, 64) - else: - headlen = len(buf) - headdata = buf[:headlen] - buf = buf[headlen:] - port = b'' - if self.server_info.port != 80: - port = b':' + to_bytes(str(self.server_info.port)) - body = None - hosts = (self.server_info.obfs_param or self.server_info.host) - pos = hosts.find("#") - if pos >= 0: - body = hosts[pos + 1:].replace("\n", "\r\n") - body = body.replace("\\n", "\r\n") - hosts = hosts[:pos] - hosts = hosts.split(',') - host = random.choice(hosts) - http_head = b"GET /" + self.encode_head(headdata) + b" HTTP/1.1\r\n" - http_head += b"Host: " + to_bytes(host) + port + b"\r\n" - if body: - http_head += body + "\r\n\r\n" - else: - http_head += b"User-Agent: " + random.choice(self.user_agent) + b"\r\n" - http_head += b"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nAccept-Language: en-US,en;q=0.8\r\nAccept-Encoding: gzip, deflate\r\nDNT: 1\r\nConnection: keep-alive\r\n\r\n" - self.has_sent_header = True - return http_head + buf - - def client_decode(self, buf): - if self.has_recv_header: - return (buf, False) - pos = buf.find(b'\r\n\r\n') - if pos >= 0: - self.has_recv_header = True - return (buf[pos + 4:], False) - else: - return (b'', False) - - def server_encode(self, buf): - if self.has_sent_header: - return buf - - header = b'HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nContent-Encoding: gzip\r\nContent-Type: text/html\r\nDate: ' - header += to_bytes(datetime.datetime.now().strftime('%a, %d %b %Y %H:%M:%S GMT')) - header += b'\r\nServer: nginx\r\nVary: Accept-Encoding\r\n\r\n' - self.has_sent_header = True - return header + buf - - def get_data_from_http_header(self, buf): - ret_buf = b'' - lines = buf.split(b'\r\n') - if lines and len(lines) > 1: - hex_items = lines[0].split(b'%') - if hex_items and len(hex_items) > 1: - for index in range(1, len(hex_items)): - if len(hex_items[index]) < 2: - ret_buf += binascii.unhexlify('0' + hex_items[index]) - break - elif len(hex_items[index]) > 2: - ret_buf += binascii.unhexlify(hex_items[index][:2]) - break - else: - ret_buf += binascii.unhexlify(hex_items[index]) - return ret_buf - return b'' - - def get_host_from_http_header(self, buf): - ret_buf = b'' - lines = buf.split(b'\r\n') - if lines and len(lines) > 1: - for line in lines: - if match_begin(line, b"Host: "): - return common.to_str(line[6:]) - - def not_match_return(self, buf): - self.has_sent_header = True - self.has_recv_header = True - if self.method == 'http_simple': - return (b'E'*2048, False, False) - return (buf, True, False) - - def error_return(self, buf): - self.has_sent_header = True - self.has_recv_header = True - return (b'E'*2048, False, False) - - def server_decode(self, buf): - if self.has_recv_header: - return (buf, True, False) - - self.recv_buffer += buf - buf = self.recv_buffer - if len(buf) > 10: - if match_begin(buf, b'GET ') or match_begin(buf, b'POST '): - if len(buf) > 65536: - self.recv_buffer = None - logging.warn('http_simple: over size') - return self.not_match_return(buf) - else: #not http header, run on original protocol - self.recv_buffer = None - logging.debug('http_simple: not match begin') - return self.not_match_return(buf) - else: - return (b'', True, False) - - if b'\r\n\r\n' in buf: - datas = buf.split(b'\r\n\r\n', 1) - ret_buf = self.get_data_from_http_header(buf) - host = self.get_host_from_http_header(buf) - if host and self.server_info.obfs_param: - pos = host.find(":") - if pos >= 0: - host = host[:pos] - hosts = self.server_info.obfs_param.split(',') - if host not in hosts: - return self.not_match_return(buf) - if len(ret_buf) < 4: - return self.error_return(buf) - if len(datas) > 1: - ret_buf += datas[1] - if len(ret_buf) >= 13: - self.has_recv_header = True - return (ret_buf, True, False) - return self.not_match_return(buf) - else: - return (b'', True, False) - -class http_post(http_simple): - def __init__(self, method): - super(http_post, self).__init__(method) - - def boundary(self): - return to_bytes(''.join([random.choice("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") for i in range(32)])) - - def client_encode(self, buf): - if self.has_sent_header: - return buf - head_size = len(self.server_info.iv) + self.server_info.head_len - if len(buf) - head_size > 64: - headlen = head_size + random.randint(0, 64) - else: - headlen = len(buf) - headdata = buf[:headlen] - buf = buf[headlen:] - port = b'' - if self.server_info.port != 80: - port = b':' + to_bytes(str(self.server_info.port)) - body = None - hosts = (self.server_info.obfs_param or self.server_info.host) - pos = hosts.find("#") - if pos >= 0: - body = hosts[pos + 1:].replace("\\n", "\r\n") - hosts = hosts[:pos] - hosts = hosts.split(',') - host = random.choice(hosts) - http_head = b"POST /" + self.encode_head(headdata) + b" HTTP/1.1\r\n" - http_head += b"Host: " + to_bytes(host) + port + b"\r\n" - if body: - http_head += body + "\r\n\r\n" - else: - http_head += b"User-Agent: " + random.choice(self.user_agent) + b"\r\n" - http_head += b"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nAccept-Language: en-US,en;q=0.8\r\nAccept-Encoding: gzip, deflate\r\n" - http_head += b"Content-Type: multipart/form-data; boundary=" + self.boundary() + b"\r\nDNT: 1\r\n" - http_head += b"Connection: keep-alive\r\n\r\n" - self.has_sent_header = True - return http_head + buf - - def not_match_return(self, buf): - self.has_sent_header = True - self.has_recv_header = True - if self.method == 'http_post': - return (b'E'*2048, False, False) - return (buf, True, False) - -class random_head(plain.plain): - def __init__(self, method): - self.method = method - self.has_sent_header = False - self.has_recv_header = False - self.raw_trans_sent = False - self.raw_trans_recv = False - self.send_buffer = b'' - - def client_encode(self, buf): - if self.raw_trans_sent: - return buf - self.send_buffer += buf - if not self.has_sent_header: - self.has_sent_header = True - data = os.urandom(common.ord(os.urandom(1)[0]) % 96 + 4) - crc = (0xffffffff - binascii.crc32(data)) & 0xffffffff - return data + struct.pack('= len(str2): - if str1[:len(str2)] == str2: - return True - return False - -class obfs_auth_data(object): - def __init__(self): - self.client_data = lru_cache.LRUCache(60 * 5) - self.client_id = os.urandom(32) - self.startup_time = int(time.time() - 60 * 30) & 0xFFFFFFFF - self.ticket_buf = {} - -class tls_ticket_auth(plain.plain): - def __init__(self, method): - self.method = method - self.handshake_status = 0 - self.send_buffer = b'' - self.recv_buffer = b'' - self.client_id = b'' - self.max_time_dif = 60 * 60 * 24 # time dif (second) setting - self.tls_version = b'\x03\x03' - self.overhead = 5 - - def init_data(self): - return obfs_auth_data() - - def get_overhead(self, direction): # direction: true for c->s false for s->c - return self.overhead - - def sni(self, url): - url = common.to_bytes(url) - data = b"\x00" + struct.pack('>H', len(url)) + url - data = b"\x00\x00" + struct.pack('>H', len(data) + 2) + struct.pack('>H', len(data)) + data - return data - - def pack_auth_data(self, client_id): - utc_time = int(time.time()) & 0xFFFFFFFF - data = struct.pack('>I', utc_time) + os.urandom(18) - data += hmac.new(self.server_info.key + client_id, data, hashlib.sha1).digest()[:10] - return data - - def client_encode(self, buf): - if self.handshake_status == -1: - return buf - if self.handshake_status == 8: - ret = b'' - while len(buf) > 2048: - size = min(struct.unpack('>H', os.urandom(2))[0] % 4096 + 100, len(buf)) - ret += b"\x17" + self.tls_version + struct.pack('>H', size) + buf[:size] - buf = buf[size:] - if len(buf) > 0: - ret += b"\x17" + self.tls_version + struct.pack('>H', len(buf)) + buf - return ret - if len(buf) > 0: - self.send_buffer += b"\x17" + self.tls_version + struct.pack('>H', len(buf)) + buf - if self.handshake_status == 0: - self.handshake_status = 1 - data = self.tls_version + self.pack_auth_data(self.server_info.data.client_id) + b"\x20" + self.server_info.data.client_id + binascii.unhexlify(b"001cc02bc02fcca9cca8cc14cc13c00ac014c009c013009c0035002f000a" + b"0100") - ext = binascii.unhexlify(b"ff01000100") - host = self.server_info.obfs_param or self.server_info.host - if host and host[-1] in string.digits: - host = '' - hosts = host.split(',') - host = random.choice(hosts) - ext += self.sni(host) - ext += b"\x00\x17\x00\x00" - if host not in self.server_info.data.ticket_buf: - self.server_info.data.ticket_buf[host] = os.urandom((struct.unpack('>H', os.urandom(2))[0] % 17 + 8) * 16) - ext += b"\x00\x23" + struct.pack('>H', len(self.server_info.data.ticket_buf[host])) + self.server_info.data.ticket_buf[host] - ext += binascii.unhexlify(b"000d001600140601060305010503040104030301030302010203") - ext += binascii.unhexlify(b"000500050100000000") - ext += binascii.unhexlify(b"00120000") - ext += binascii.unhexlify(b"75500000") - ext += binascii.unhexlify(b"000b00020100") - ext += binascii.unhexlify(b"000a0006000400170018") - data += struct.pack('>H', len(ext)) + ext - data = b"\x01\x00" + struct.pack('>H', len(data)) + data - data = b"\x16\x03\x01" + struct.pack('>H', len(data)) + data - return data - elif self.handshake_status == 1 and len(buf) == 0: - data = b"\x14" + self.tls_version + b"\x00\x01\x01" #ChangeCipherSpec - data += b"\x16" + self.tls_version + b"\x00\x20" + os.urandom(22) #Finished - data += hmac.new(self.server_info.key + self.server_info.data.client_id, data, hashlib.sha1).digest()[:10] - ret = data + self.send_buffer - self.send_buffer = b'' - self.handshake_status = 8 - return ret - return b'' - - def client_decode(self, buf): - if self.handshake_status == -1: - return (buf, False) - - if self.handshake_status == 8: - ret = b'' - self.recv_buffer += buf - while len(self.recv_buffer) > 5: - if ord(self.recv_buffer[0]) != 0x17: - logging.info("data = %s" % (binascii.hexlify(self.recv_buffer))) - raise Exception('server_decode appdata error') - size = struct.unpack('>H', self.recv_buffer[3:5])[0] - if len(self.recv_buffer) < size + 5: - break - buf = self.recv_buffer[5:size+5] - ret += buf - self.recv_buffer = self.recv_buffer[size+5:] - return (ret, False) - - if len(buf) < 11 + 32 + 1 + 32: - raise Exception('client_decode data error') - verify = buf[11:33] - if hmac.new(self.server_info.key + self.server_info.data.client_id, verify, hashlib.sha1).digest()[:10] != buf[33:43]: - raise Exception('client_decode data error') - if hmac.new(self.server_info.key + self.server_info.data.client_id, buf[:-10], hashlib.sha1).digest()[:10] != buf[-10:]: - raise Exception('client_decode data error') - return (b'', True) - - def server_encode(self, buf): - if self.handshake_status == -1: - return buf - if (self.handshake_status & 8) == 8: - ret = b'' - while len(buf) > 2048: - size = min(struct.unpack('>H', os.urandom(2))[0] % 4096 + 100, len(buf)) - ret += b"\x17" + self.tls_version + struct.pack('>H', size) + buf[:size] - buf = buf[size:] - if len(buf) > 0: - ret += b"\x17" + self.tls_version + struct.pack('>H', len(buf)) + buf - return ret - self.handshake_status |= 8 - data = self.tls_version + self.pack_auth_data(self.client_id) + b"\x20" + self.client_id + binascii.unhexlify(b"c02f000005ff01000100") - data = b"\x02\x00" + struct.pack('>H', len(data)) + data #server hello - data = b"\x16" + self.tls_version + struct.pack('>H', len(data)) + data - if random.randint(0, 8) < 1: - ticket = os.urandom((struct.unpack('>H', os.urandom(2))[0] % 164) * 2 + 64) - ticket = struct.pack('>H', len(ticket) + 4) + b"\x04\x00" + struct.pack('>H', len(ticket)) + ticket - data += b"\x16" + self.tls_version + ticket #New session ticket - data += b"\x14" + self.tls_version + b"\x00\x01\x01" #ChangeCipherSpec - finish_len = random.choice([32, 40]) - data += b"\x16" + self.tls_version + struct.pack('>H', finish_len) + os.urandom(finish_len - 10) #Finished - data += hmac.new(self.server_info.key + self.client_id, data, hashlib.sha1).digest()[:10] - if buf: - data += self.server_encode(buf) - return data - - def decode_error_return(self, buf): - self.handshake_status = -1 - if self.overhead > 0: - self.server_info.overhead -= self.overhead - self.overhead = 0 - if self.method in ['tls1.2_ticket_auth', 'tls1.2_ticket_fastauth']: - return (b'E'*2048, False, False) - return (buf, True, False) - - def server_decode(self, buf): - if self.handshake_status == -1: - return (buf, True, False) - - if (self.handshake_status & 4) == 4: - ret = b'' - self.recv_buffer += buf - while len(self.recv_buffer) > 5: - if ord(self.recv_buffer[0]) != 0x17 or ord(self.recv_buffer[1]) != 0x3 or ord(self.recv_buffer[2]) != 0x3: - logging.info("data = %s" % (binascii.hexlify(self.recv_buffer))) - raise Exception('server_decode appdata error') - size = struct.unpack('>H', self.recv_buffer[3:5])[0] - if len(self.recv_buffer) < size + 5: - break - ret += self.recv_buffer[5:size+5] - self.recv_buffer = self.recv_buffer[size+5:] - return (ret, True, False) - - if (self.handshake_status & 1) == 1: - self.recv_buffer += buf - buf = self.recv_buffer - verify = buf - if len(buf) < 11: - raise Exception('server_decode data error') - if not match_begin(buf, b"\x14" + self.tls_version + b"\x00\x01\x01"): #ChangeCipherSpec - raise Exception('server_decode data error') - buf = buf[6:] - if not match_begin(buf, b"\x16" + self.tls_version + b"\x00"): #Finished - raise Exception('server_decode data error') - verify_len = struct.unpack('>H', buf[3:5])[0] + 1 # 11 - 10 - if len(verify) < verify_len + 10: - return (b'', False, False) - if hmac.new(self.server_info.key + self.client_id, verify[:verify_len], hashlib.sha1).digest()[:10] != verify[verify_len:verify_len+10]: - raise Exception('server_decode data error') - self.recv_buffer = verify[verify_len + 10:] - status = self.handshake_status - self.handshake_status |= 4 - ret = self.server_decode(b'') - return ret; - - #raise Exception("handshake data = %s" % (binascii.hexlify(buf))) - self.recv_buffer += buf - buf = self.recv_buffer - ogn_buf = buf - if len(buf) < 3: - return (b'', False, False) - if not match_begin(buf, b'\x16\x03\x01'): - return self.decode_error_return(ogn_buf) - buf = buf[3:] - header_len = struct.unpack('>H', buf[:2])[0] - if header_len > len(buf) - 2: - return (b'', False, False) - - self.recv_buffer = self.recv_buffer[header_len + 5:] - self.handshake_status = 1 - buf = buf[2:header_len + 2] - if not match_begin(buf, b'\x01\x00'): #client hello - logging.info("tls_auth not client hello message") - return self.decode_error_return(ogn_buf) - buf = buf[2:] - if struct.unpack('>H', buf[:2])[0] != len(buf) - 2: - logging.info("tls_auth wrong message size") - return self.decode_error_return(ogn_buf) - buf = buf[2:] - if not match_begin(buf, self.tls_version): - logging.info("tls_auth wrong tls version") - return self.decode_error_return(ogn_buf) - buf = buf[2:] - verifyid = buf[:32] - buf = buf[32:] - sessionid_len = ord(buf[0]) - if sessionid_len < 32: - logging.info("tls_auth wrong sessionid_len") - return self.decode_error_return(ogn_buf) - sessionid = buf[1:sessionid_len + 1] - buf = buf[sessionid_len+1:] - self.client_id = sessionid - sha1 = hmac.new(self.server_info.key + sessionid, verifyid[:22], hashlib.sha1).digest()[:10] - utc_time = struct.unpack('>I', verifyid[:4])[0] - time_dif = common.int32((int(time.time()) & 0xffffffff) - utc_time) - if self.server_info.obfs_param: - try: - self.max_time_dif = int(self.server_info.obfs_param) - except: - pass - if self.max_time_dif > 0 and (time_dif < -self.max_time_dif or time_dif > self.max_time_dif \ - or common.int32(utc_time - self.server_info.data.startup_time) < -self.max_time_dif / 2): - logging.info("tls_auth wrong time") - return self.decode_error_return(ogn_buf) - if sha1 != verifyid[22:]: - logging.info("tls_auth wrong sha1") - return self.decode_error_return(ogn_buf) - if self.server_info.data.client_data.get(verifyid[:22]): - logging.info("replay attack detect, id = %s" % (binascii.hexlify(verifyid))) - return self.decode_error_return(ogn_buf) - self.server_info.data.client_data.sweep() - self.server_info.data.client_data[verifyid[:22]] = sessionid - if len(self.recv_buffer) >= 11: - ret = self.server_decode(b'') - return (ret[0], True, True) - # (buffer_to_recv, is_need_decrypt, is_need_to_encode_and_send_back) - return (b'', False, True) - diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/plain.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/plain.py deleted file mode 100644 index 5aa44cf35a..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/plain.py +++ /dev/null @@ -1,104 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright 2015-2015 breakwa11 -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import absolute_import, division, print_function, \ - with_statement - -import os -import sys -import hashlib -import logging - -from shadowsocks.common import ord - -def create_obfs(method): - return plain(method) - -obfs_map = { - 'plain': (create_obfs,), - 'origin': (create_obfs,), -} - -class plain(object): - def __init__(self, method): - self.method = method - self.server_info = None - - def init_data(self): - return b'' - - def get_overhead(self, direction): # direction: true for c->s false for s->c - return 0 - - def get_server_info(self): - return self.server_info - - def set_server_info(self, server_info): - self.server_info = server_info - - def client_pre_encrypt(self, buf): - return buf - - def client_encode(self, buf): - return buf - - def client_decode(self, buf): - # (buffer_to_recv, is_need_to_encode_and_send_back) - return (buf, False) - - def client_post_decrypt(self, buf): - return buf - - def server_pre_encrypt(self, buf): - return buf - - def server_encode(self, buf): - return buf - - def server_decode(self, buf): - # (buffer_to_recv, is_need_decrypt, is_need_to_encode_and_send_back) - return (buf, True, False) - - def server_post_decrypt(self, buf): - return (buf, False) - - def client_udp_pre_encrypt(self, buf): - return buf - - def client_udp_post_decrypt(self, buf): - return buf - - def server_udp_pre_encrypt(self, buf, uid): - return buf - - def server_udp_post_decrypt(self, buf): - return (buf, None) - - def dispose(self): - pass - - def get_head_size(self, buf, def_value): - if len(buf) < 2: - return def_value - head_type = ord(buf[0]) & 0x7 - if head_type == 1: - return 7 - if head_type == 4: - return 19 - if head_type == 3: - return 4 + ord(buf[1]) - return def_value - diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/verify.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/verify.py deleted file mode 100644 index 73257e2eb2..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/verify.py +++ /dev/null @@ -1,154 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright 2015-2015 breakwa11 -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import absolute_import, division, print_function, \ - with_statement - -import os -import sys -import hashlib -import logging -import binascii -import base64 -import time -import datetime -import random -import struct -import zlib -import hmac -import hashlib - -import shadowsocks -from shadowsocks import common -from shadowsocks.obfsplugin import plain -from shadowsocks.common import to_bytes, to_str, ord, chr - -def create_verify_deflate(method): - return verify_deflate(method) - -obfs_map = { - 'verify_deflate': (create_verify_deflate,), -} - -def match_begin(str1, str2): - if len(str1) >= len(str2): - if str1[:len(str2)] == str2: - return True - return False - -class obfs_verify_data(object): - def __init__(self): - pass - -class verify_base(plain.plain): - def __init__(self, method): - super(verify_base, self).__init__(method) - self.method = method - - def init_data(self): - return obfs_verify_data() - - def set_server_info(self, server_info): - self.server_info = server_info - - def client_encode(self, buf): - return buf - - def client_decode(self, buf): - return (buf, False) - - def server_encode(self, buf): - return buf - - def server_decode(self, buf): - return (buf, True, False) - -class verify_deflate(verify_base): - def __init__(self, method): - super(verify_deflate, self).__init__(method) - self.recv_buf = b'' - self.unit_len = 32700 - self.decrypt_packet_num = 0 - self.raw_trans = False - - def pack_data(self, buf): - if len(buf) == 0: - return b'' - data = zlib.compress(buf) - data = struct.pack('>H', len(data)) + data[2:] - return data - - def client_pre_encrypt(self, buf): - ret = b'' - while len(buf) > self.unit_len: - ret += self.pack_data(buf[:self.unit_len]) - buf = buf[self.unit_len:] - ret += self.pack_data(buf) - return ret - - def client_post_decrypt(self, buf): - if self.raw_trans: - return buf - self.recv_buf += buf - out_buf = b'' - while len(self.recv_buf) > 2: - length = struct.unpack('>H', self.recv_buf[:2])[0] - if length >= 32768 or length < 6: - self.raw_trans = True - self.recv_buf = b'' - raise Exception('client_post_decrypt data error') - if length > len(self.recv_buf): - break - - out_buf += zlib.decompress(b'x\x9c' + self.recv_buf[2:length]) - self.recv_buf = self.recv_buf[length:] - - if out_buf: - self.decrypt_packet_num += 1 - return out_buf - - def server_pre_encrypt(self, buf): - ret = b'' - while len(buf) > self.unit_len: - ret += self.pack_data(buf[:self.unit_len]) - buf = buf[self.unit_len:] - ret += self.pack_data(buf) - return ret - - def server_post_decrypt(self, buf): - if self.raw_trans: - return (buf, False) - self.recv_buf += buf - out_buf = b'' - while len(self.recv_buf) > 2: - length = struct.unpack('>H', self.recv_buf[:2])[0] - if length >= 32768 or length < 6: - self.raw_trans = True - self.recv_buf = b'' - if self.decrypt_packet_num == 0: - return (b'E'*2048, False) - else: - raise Exception('server_post_decrype data error') - if length > len(self.recv_buf): - break - - out_buf += zlib.decompress(b'\x78\x9c' + self.recv_buf[2:length]) - self.recv_buf = self.recv_buf[length:] - - if out_buf: - self.decrypt_packet_num += 1 - return (out_buf, False) - diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/ordereddict.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/ordereddict.py deleted file mode 100644 index e1918f5e02..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/ordereddict.py +++ /dev/null @@ -1,214 +0,0 @@ -import collections - -################################################################################ -### OrderedDict -################################################################################ - -class OrderedDict(dict): - 'Dictionary that remembers insertion order' - # An inherited dict maps keys to values. - # The inherited dict provides __getitem__, __len__, __contains__, and get. - # The remaining methods are order-aware. - # Big-O running times for all methods are the same as regular dictionaries. - - # The internal self.__map dict maps keys to links in a doubly linked list. - # The circular doubly linked list starts and ends with a sentinel element. - # The sentinel element never gets deleted (this simplifies the algorithm). - # Each link is stored as a list of length three: [PREV, NEXT, KEY]. - - def __init__(*args, **kwds): - '''Initialize an ordered dictionary. The signature is the same as - regular dictionaries, but keyword arguments are not recommended because - their insertion order is arbitrary. - - ''' - if not args: - raise TypeError("descriptor '__init__' of 'OrderedDict' object " - "needs an argument") - self = args[0] - args = args[1:] - if len(args) > 1: - raise TypeError('expected at most 1 arguments, got %d' % len(args)) - try: - self.__root - except AttributeError: - self.__root = root = [] # sentinel node - root[:] = [root, root, None] - self.__map = {} - self.__update(*args, **kwds) - - def __setitem__(self, key, value, dict_setitem=dict.__setitem__): - 'od.__setitem__(i, y) <==> od[i]=y' - # Setting a new item creates a new link at the end of the linked list, - # and the inherited dictionary is updated with the new key/value pair. - if key not in self: - root = self.__root - last = root[0] - last[1] = root[0] = self.__map[key] = [last, root, key] - return dict_setitem(self, key, value) - - def __delitem__(self, key, dict_delitem=dict.__delitem__): - 'od.__delitem__(y) <==> del od[y]' - # Deleting an existing item uses self.__map to find the link which gets - # removed by updating the links in the predecessor and successor nodes. - dict_delitem(self, key) - link_prev, link_next, _ = self.__map.pop(key) - link_prev[1] = link_next # update link_prev[NEXT] - link_next[0] = link_prev # update link_next[PREV] - - def __iter__(self): - 'od.__iter__() <==> iter(od)' - # Traverse the linked list in order. - root = self.__root - curr = root[1] # start at the first node - while curr is not root: - yield curr[2] # yield the curr[KEY] - curr = curr[1] # move to next node - - def __reversed__(self): - 'od.__reversed__() <==> reversed(od)' - # Traverse the linked list in reverse order. - root = self.__root - curr = root[0] # start at the last node - while curr is not root: - yield curr[2] # yield the curr[KEY] - curr = curr[0] # move to previous node - - def clear(self): - 'od.clear() -> None. Remove all items from od.' - root = self.__root - root[:] = [root, root, None] - self.__map.clear() - dict.clear(self) - - # -- the following methods do not depend on the internal structure -- - - def keys(self): - 'od.keys() -> list of keys in od' - return list(self) - - def values(self): - 'od.values() -> list of values in od' - return [self[key] for key in self] - - def items(self): - 'od.items() -> list of (key, value) pairs in od' - return [(key, self[key]) for key in self] - - def iterkeys(self): - 'od.iterkeys() -> an iterator over the keys in od' - return iter(self) - - def itervalues(self): - 'od.itervalues -> an iterator over the values in od' - for k in self: - yield self[k] - - def iteritems(self): - 'od.iteritems -> an iterator over the (key, value) pairs in od' - for k in self: - yield (k, self[k]) - - update = collections.MutableMapping.update - - __update = update # let subclasses override update without breaking __init__ - - __marker = object() - - def pop(self, key, default=__marker): - '''od.pop(k[,d]) -> v, remove specified key and return the corresponding - value. If key is not found, d is returned if given, otherwise KeyError - is raised. - - ''' - if key in self: - result = self[key] - del self[key] - return result - if default is self.__marker: - raise KeyError(key) - return default - - def setdefault(self, key, default=None): - 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od' - if key in self: - return self[key] - self[key] = default - return default - - def popitem(self, last=True): - '''od.popitem() -> (k, v), return and remove a (key, value) pair. - Pairs are returned in LIFO order if last is true or FIFO order if false. - - ''' - if not self: - raise KeyError('dictionary is empty') - key = next(reversed(self) if last else iter(self)) - value = self.pop(key) - return key, value - - def __repr__(self, _repr_running={}): - 'od.__repr__() <==> repr(od)' - call_key = id(self), _get_ident() - if call_key in _repr_running: - return '...' - _repr_running[call_key] = 1 - try: - if not self: - return '%s()' % (self.__class__.__name__,) - return '%s(%r)' % (self.__class__.__name__, self.items()) - finally: - del _repr_running[call_key] - - def __reduce__(self): - 'Return state information for pickling' - items = [[k, self[k]] for k in self] - inst_dict = vars(self).copy() - for k in vars(OrderedDict()): - inst_dict.pop(k, None) - if inst_dict: - return (self.__class__, (items,), inst_dict) - return self.__class__, (items,) - - def copy(self): - 'od.copy() -> a shallow copy of od' - return self.__class__(self) - - @classmethod - def fromkeys(cls, iterable, value=None): - '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S. - If not specified, the value defaults to None. - - ''' - self = cls() - for key in iterable: - self[key] = value - return self - - def __eq__(self, other): - '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive - while comparison to a regular mapping is order-insensitive. - - ''' - if isinstance(other, OrderedDict): - return dict.__eq__(self, other) and all(_imap(_eq, self, other)) - return dict.__eq__(self, other) - - def __ne__(self, other): - 'od.__ne__(y) <==> od!=y' - return not self == other - - # -- the following methods support python 3.x style dictionary views -- - - def viewkeys(self): - "od.viewkeys() -> a set-like object providing a view on od's keys" - return KeysView(self) - - def viewvalues(self): - "od.viewvalues() -> an object providing a view on od's values" - return ValuesView(self) - - def viewitems(self): - "od.viewitems() -> a set-like object providing a view on od's items" - return ItemsView(self) - diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/run.sh b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/run.sh deleted file mode 100755 index bf1591b3c5..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/run.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -cd `dirname $0` -eval $(ps -ef | grep "[0-9] python3 server\\.py a" | awk '{print "kill "$2}') -ulimit -n 512000 -nohup python3 server.py a >> /dev/null 2>&1 & diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/server.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/server.py deleted file mode 100644 index 5ceff6e370..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/server.py +++ /dev/null @@ -1,215 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# Copyright 2015 clowwindy -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import absolute_import, division, print_function, \ - with_statement - -import sys -import os -import logging -import signal - -if __name__ == '__main__': - import inspect - file_path = os.path.dirname(os.path.realpath(inspect.getfile(inspect.currentframe()))) - sys.path.insert(0, os.path.join(file_path, '../')) - -from shadowsocks import shell, daemon, eventloop, tcprelay, udprelay, \ - asyncdns, manager, common - - -def main(): - shell.check_python3() - - config = shell.get_config(False) - - shell.log_shadowsocks_version() - - daemon.daemon_exec(config) - - try: - import resource - logging.info('current process RLIMIT_NOFILE resource: soft %d hard %d' % resource.getrlimit(resource.RLIMIT_NOFILE)) - except ImportError: - pass - - if config['port_password']: - pass - else: - config['port_password'] = {} - server_port = config['server_port'] - if type(server_port) == list: - for a_server_port in server_port: - config['port_password'][a_server_port] = config['password'] - else: - config['port_password'][str(server_port)] = config['password'] - - if not config.get('dns_ipv6', False): - asyncdns.IPV6_CONNECTION_SUPPORT = False - - if config.get('manager_address', 0): - logging.info('entering manager mode') - manager.run(config) - return - - tcp_servers = [] - udp_servers = [] - dns_resolver = asyncdns.DNSResolver() - if int(config['workers']) > 1: - stat_counter_dict = None - else: - stat_counter_dict = {} - port_password = config['port_password'] - config_password = config.get('password', 'm') - del config['port_password'] - for port, password_obfs in port_password.items(): - method = config["method"] - protocol = config.get("protocol", 'origin') - protocol_param = config.get("protocol_param", '') - obfs = config.get("obfs", 'plain') - obfs_param = config.get("obfs_param", '') - bind = config.get("out_bind", '') - bindv6 = config.get("out_bindv6", '') - if type(password_obfs) == list: - password = password_obfs[0] - obfs = common.to_str(password_obfs[1]) - if len(password_obfs) > 2: - protocol = common.to_str(password_obfs[2]) - elif type(password_obfs) == dict: - password = password_obfs.get('password', config_password) - method = common.to_str(password_obfs.get('method', method)) - protocol = common.to_str(password_obfs.get('protocol', protocol)) - protocol_param = common.to_str(password_obfs.get('protocol_param', protocol_param)) - obfs = common.to_str(password_obfs.get('obfs', obfs)) - obfs_param = common.to_str(password_obfs.get('obfs_param', obfs_param)) - bind = password_obfs.get('out_bind', bind) - bindv6 = password_obfs.get('out_bindv6', bindv6) - else: - password = password_obfs - a_config = config.copy() - ipv6_ok = False - logging.info("server start with protocol[%s] password [%s] method [%s] obfs [%s] obfs_param [%s]" % - (protocol, password, method, obfs, obfs_param)) - if 'server_ipv6' in a_config: - try: - if len(a_config['server_ipv6']) > 2 and a_config['server_ipv6'][0] == "[" and a_config['server_ipv6'][-1] == "]": - a_config['server_ipv6'] = a_config['server_ipv6'][1:-1] - a_config['server_port'] = int(port) - a_config['password'] = password - a_config['method'] = method - a_config['protocol'] = protocol - a_config['protocol_param'] = protocol_param - a_config['obfs'] = obfs - a_config['obfs_param'] = obfs_param - a_config['out_bind'] = bind - a_config['out_bindv6'] = bindv6 - a_config['server'] = a_config['server_ipv6'] - logging.info("starting server at [%s]:%d" % - (a_config['server'], int(port))) - tcp_servers.append(tcprelay.TCPRelay(a_config, dns_resolver, False, stat_counter=stat_counter_dict)) - udp_servers.append(udprelay.UDPRelay(a_config, dns_resolver, False, stat_counter=stat_counter_dict)) - if a_config['server_ipv6'] == b"::": - ipv6_ok = True - except Exception as e: - shell.print_exception(e) - - try: - a_config = config.copy() - a_config['server_port'] = int(port) - a_config['password'] = password - a_config['method'] = method - a_config['protocol'] = protocol - a_config['protocol_param'] = protocol_param - a_config['obfs'] = obfs - a_config['obfs_param'] = obfs_param - a_config['out_bind'] = bind - a_config['out_bindv6'] = bindv6 - logging.info("starting server at %s:%d" % - (a_config['server'], int(port))) - tcp_servers.append(tcprelay.TCPRelay(a_config, dns_resolver, False, stat_counter=stat_counter_dict)) - udp_servers.append(udprelay.UDPRelay(a_config, dns_resolver, False, stat_counter=stat_counter_dict)) - except Exception as e: - if not ipv6_ok: - shell.print_exception(e) - - def run_server(): - def child_handler(signum, _): - logging.warn('received SIGQUIT, doing graceful shutting down..') - list(map(lambda s: s.close(next_tick=True), - tcp_servers + udp_servers)) - signal.signal(getattr(signal, 'SIGQUIT', signal.SIGTERM), - child_handler) - - def int_handler(signum, _): - sys.exit(1) - signal.signal(signal.SIGINT, int_handler) - - try: - loop = eventloop.EventLoop() - dns_resolver.add_to_loop(loop) - list(map(lambda s: s.add_to_loop(loop), tcp_servers + udp_servers)) - - daemon.set_user(config.get('user', None)) - loop.run() - except Exception as e: - shell.print_exception(e) - sys.exit(1) - - if int(config['workers']) > 1: - if os.name == 'posix': - children = [] - is_child = False - for i in range(0, int(config['workers'])): - r = os.fork() - if r == 0: - logging.info('worker started') - is_child = True - run_server() - break - else: - children.append(r) - if not is_child: - def handler(signum, _): - for pid in children: - try: - os.kill(pid, signum) - os.waitpid(pid, 0) - except OSError: # child may already exited - pass - sys.exit() - signal.signal(signal.SIGTERM, handler) - signal.signal(signal.SIGQUIT, handler) - signal.signal(signal.SIGINT, handler) - - # master - for a_tcp_server in tcp_servers: - a_tcp_server.close() - for a_udp_server in udp_servers: - a_udp_server.close() - dns_resolver.close() - - for child in children: - os.waitpid(child, 0) - else: - logging.warn('worker is only available on Unix/Linux') - run_server() - else: - run_server() - - -if __name__ == '__main__': - main() diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/shell.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/shell.py deleted file mode 100644 index f930881be5..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/shell.py +++ /dev/null @@ -1,445 +0,0 @@ -#!/usr/bin/python3 -# -*- coding: utf-8 -*- -# -# Copyright 2015 clowwindy -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import absolute_import, division, print_function, \ - with_statement - -import os -import json -import sys -import getopt -import logging -from shadowsocks.common import to_bytes, to_str, IPNetwork, PortRange -from shadowsocks import encrypt - - -VERBOSE_LEVEL = 5 - -verbose = 0 - - -def check_python3(): - info = sys.version_info - if info[0] == 2 and not info[1] >= 6: - print('Python 2.6+ required') - sys.exit(1) - elif info[0] == 3 and not info[1] >= 3: - print('Python 3.3+ required') - sys.exit(1) - elif info[0] not in [2, 3]: - print('Python version not supported') - sys.exit(1) - - -def print_exception(e): - global verbose - logging.error(e) - if verbose > 0: - import traceback - traceback.print_exc() - -def __version(): - version_str = '' - try: - import pkg_resources - version_str = pkg_resources.get_distribution('shadowsocks').version - except Exception: - try: - from shadowsocks import version - version_str = version.version() - except Exception: - pass - return version_str - -def print_shadowsocks(): - print('ShadowsocksR %s' % __version()) - -def log_shadowsocks_version(): - logging.info('ShadowsocksR %s' % __version()) - - -def find_config(): - user_config_path = 'user-config.json' - config_path = 'config.json' - - def sub_find(file_name): - if os.path.exists(file_name): - return file_name - file_name = os.path.join(os.path.abspath('..'), file_name) - return file_name if os.path.exists(file_name) else None - - return sub_find(user_config_path) or sub_find(config_path) - -def check_config(config, is_local): - if config.get('daemon', None) == 'stop': - # no need to specify configuration for daemon stop - return - - if is_local and not config.get('password', None): - logging.error('password not specified') - print_help(is_local) - sys.exit(2) - - if not is_local and not config.get('password', None) \ - and not config.get('port_password', None): - logging.error('password or port_password not specified') - print_help(is_local) - sys.exit(2) - - if 'local_port' in config: - config['local_port'] = int(config['local_port']) - - if 'server_port' in config and type(config['server_port']) != list: - config['server_port'] = int(config['server_port']) - - if config.get('local_address', '') in [b'0.0.0.0']: - logging.warning('warning: local set to listen on 0.0.0.0, it\'s not safe') - if config.get('server', '') in ['127.0.0.1', 'localhost']: - logging.warning('warning: server set to listen on %s:%s, are you sure?' % - (to_str(config['server']), config['server_port'])) - if config.get('timeout', 300) < 100: - logging.warning('warning: your timeout %d seems too short' % - int(config.get('timeout'))) - if config.get('timeout', 300) > 600: - logging.warning('warning: your timeout %d seems too long' % - int(config.get('timeout'))) - if config.get('password') in [b'mypassword']: - logging.error('DON\'T USE DEFAULT PASSWORD! Please change it in your ' - 'config.json!') - sys.exit(1) - if config.get('user', None) is not None: - if os.name != 'posix': - logging.error('user can be used only on Unix') - sys.exit(1) - - encrypt.try_cipher(config['password'], config['method']) - - -def get_config(is_local): - global verbose - config = {} - config_path = None - logging.basicConfig(level=logging.INFO, - format='%(levelname)-s: %(message)s') - if is_local: - shortopts = 'hd:s:b:p:k:l:m:O:o:G:g:c:t:vq' - longopts = ['help', 'fast-open', 'pid-file=', 'log-file=', 'user=', - 'version'] - else: - shortopts = 'hd:s:p:k:m:O:o:G:g:c:t:vq' - longopts = ['help', 'fast-open', 'pid-file=', 'log-file=', 'workers=', - 'forbidden-ip=', 'user=', 'manager-address=', 'version'] - try: - optlist, args = getopt.getopt(sys.argv[1:], shortopts, longopts) - for key, value in optlist: - if key == '-c': - config_path = value - elif key in ('-h', '--help'): - print_help(is_local) - sys.exit(0) - elif key == '--version': - print_shadowsocks() - sys.exit(0) - else: - continue - - if config_path is None: - config_path = find_config() - - - if config_path: - logging.debug('loading config from %s' % config_path) - with open(config_path, 'rb') as f: - try: - config = parse_json_in_str(remove_comment(f.read().decode('utf8'))) - except ValueError as e: - logging.error('found an error in config.json: %s', str(e)) - sys.exit(1) - - - v_count = 0 - for key, value in optlist: - if key == '-p': - config['server_port'] = int(value) - elif key == '-k': - config['password'] = to_bytes(value) - elif key == '-l': - config['local_port'] = int(value) - elif key == '-s': - config['server'] = to_str(value) - elif key == '-m': - config['method'] = to_str(value) - elif key == '-O': - config['protocol'] = to_str(value) - elif key == '-o': - config['obfs'] = to_str(value) - elif key == '-G': - config['protocol_param'] = to_str(value) - elif key == '-g': - config['obfs_param'] = to_str(value) - elif key == '-b': - config['local_address'] = to_str(value) - elif key == '-v': - v_count += 1 - # '-vv' turns on more verbose mode - config['verbose'] = v_count - elif key == '-t': - config['timeout'] = int(value) - elif key == '--fast-open': - config['fast_open'] = True - elif key == '--workers': - config['workers'] = int(value) - elif key == '--manager-address': - config['manager_address'] = value - elif key == '--user': - config['user'] = to_str(value) - elif key == '--forbidden-ip': - config['forbidden_ip'] = to_str(value) - - elif key == '-d': - config['daemon'] = to_str(value) - elif key == '--pid-file': - config['pid-file'] = to_str(value) - elif key == '--log-file': - config['log-file'] = to_str(value) - elif key == '-q': - v_count -= 1 - config['verbose'] = v_count - else: - continue - except getopt.GetoptError as e: - print(e, file=sys.stderr) - print_help(is_local) - sys.exit(2) - - if not config: - logging.error('config not specified') - print_help(is_local) - sys.exit(2) - - config['password'] = to_bytes(config.get('password', b'')) - config['method'] = to_str(config.get('method', 'aes-256-cfb')) - config['protocol'] = to_str(config.get('protocol', 'origin')) - config['protocol_param'] = to_str(config.get('protocol_param', '')) - config['obfs'] = to_str(config.get('obfs', 'plain')) - config['obfs_param'] = to_str(config.get('obfs_param', '')) - config['port_password'] = config.get('port_password', None) - config['additional_ports'] = config.get('additional_ports', {}) - config['additional_ports_only'] = config.get('additional_ports_only', False) - config['timeout'] = int(config.get('timeout', 300)) - config['udp_timeout'] = int(config.get('udp_timeout', 120)) - config['udp_cache'] = int(config.get('udp_cache', 64)) - config['fast_open'] = config.get('fast_open', False) - config['workers'] = config.get('workers', 1) - config['pid-file'] = config.get('pid-file', '/var/run/shadowsocksr.pid') - config['log-file'] = config.get('log-file', '/var/log/shadowsocksr.log') - config['verbose'] = config.get('verbose', False) - config['connect_verbose_info'] = config.get('connect_verbose_info', 0) - config['local_address'] = to_str(config.get('local_address', '127.0.0.1')) - config['local_port'] = config.get('local_port', 1080) - if is_local: - if config.get('server', None) is None: - logging.error('server addr not specified') - print_local_help() - sys.exit(2) - else: - config['server'] = to_str(config['server']) - else: - config['server'] = to_str(config.get('server', '0.0.0.0')) - try: - config['forbidden_ip'] = \ - IPNetwork(config.get('forbidden_ip', '127.0.0.0/8,::1/128')) - except Exception as e: - logging.error(e) - sys.exit(2) - try: - config['forbidden_port'] = PortRange(config.get('forbidden_port', '')) - except Exception as e: - logging.error(e) - sys.exit(2) - try: - config['ignore_bind'] = \ - IPNetwork(config.get('ignore_bind', '127.0.0.0/8,::1/128,10.0.0.0/8,192.168.0.0/16')) - except Exception as e: - logging.error(e) - sys.exit(2) - config['server_port'] = config.get('server_port', 8388) - - logging.getLogger('').handlers = [] - logging.addLevelName(VERBOSE_LEVEL, 'VERBOSE') - if config['verbose'] >= 2: - level = VERBOSE_LEVEL - elif config['verbose'] == 1: - level = logging.DEBUG - elif config['verbose'] == -1: - level = logging.WARN - elif config['verbose'] <= -2: - level = logging.ERROR - else: - level = logging.INFO - verbose = config['verbose'] - logging.basicConfig(level=level, - format='%(asctime)s %(levelname)-8s %(filename)s:%(lineno)s %(message)s', - datefmt='%Y-%m-%d %H:%M:%S') - - check_config(config, is_local) - - return config - - -def print_help(is_local): - if is_local: - print_local_help() - else: - print_server_help() - - -def print_local_help(): - print('''usage: sslocal [OPTION]... -A fast tunnel proxy that helps you bypass firewalls. - -You can supply configurations via either config file or command line arguments. - -Proxy options: - -c CONFIG path to config file - -s SERVER_ADDR server address - -p SERVER_PORT server port, default: 8388 - -b LOCAL_ADDR local binding address, default: 127.0.0.1 - -l LOCAL_PORT local port, default: 1080 - -k PASSWORD password - -m METHOD encryption method, default: aes-256-cfb - -o OBFS obfsplugin, default: http_simple - -t TIMEOUT timeout in seconds, default: 300 - --fast-open use TCP_FASTOPEN, requires Linux 3.7+ - -General options: - -h, --help show this help message and exit - -d start/stop/restart daemon mode - --pid-file PID_FILE pid file for daemon mode - --log-file LOG_FILE log file for daemon mode - --user USER username to run as - -v, -vv verbose mode - -q, -qq quiet mode, only show warnings/errors - --version show version information - -Online help: -''') - - -def print_server_help(): - print('''usage: ssserver [OPTION]... -A fast tunnel proxy that helps you bypass firewalls. - -You can supply configurations via either config file or command line arguments. - -Proxy options: - -c CONFIG path to config file - -s SERVER_ADDR server address, default: 0.0.0.0 - -p SERVER_PORT server port, default: 8388 - -k PASSWORD password - -m METHOD encryption method, default: aes-256-cfb - -o OBFS obfsplugin, default: http_simple - -t TIMEOUT timeout in seconds, default: 300 - --fast-open use TCP_FASTOPEN, requires Linux 3.7+ - --workers WORKERS number of workers, available on Unix/Linux - --forbidden-ip IPLIST comma seperated IP list forbidden to connect - --manager-address ADDR optional server manager UDP address, see wiki - -General options: - -h, --help show this help message and exit - -d start/stop/restart daemon mode - --pid-file PID_FILE pid file for daemon mode - --log-file LOG_FILE log file for daemon mode - --user USER username to run as - -v, -vv verbose mode - -q, -qq quiet mode, only show warnings/errors - --version show version information - -Online help: -''') - - -def _decode_list(data): - rv = [] - for item in data: - if hasattr(item, 'encode'): - item = item.encode('utf-8') - elif isinstance(item, list): - item = _decode_list(item) - elif isinstance(item, dict): - item = _decode_dict(item) - rv.append(item) - return rv - - -def _decode_dict(data): - rv = {} - for key, value in data.items(): - if hasattr(value, 'encode'): - value = value.encode('utf-8') - elif isinstance(value, list): - value = _decode_list(value) - elif isinstance(value, dict): - value = _decode_dict(value) - rv[key] = value - return rv - -class JSFormat: - def __init__(self): - self.state = 0 - - def push(self, ch): - ch = ord(ch) - if self.state == 0: - if ch == ord('"'): - self.state = 1 - return to_str(chr(ch)) - elif ch == ord('/'): - self.state = 3 - else: - return to_str(chr(ch)) - elif self.state == 1: - if ch == ord('"'): - self.state = 0 - return to_str(chr(ch)) - elif ch == ord('\\'): - self.state = 2 - return to_str(chr(ch)) - elif self.state == 2: - self.state = 1 - if ch == ord('"'): - return to_str(chr(ch)) - return "\\" + to_str(chr(ch)) - elif self.state == 3: - if ch == ord('/'): - self.state = 4 - else: - return "/" + to_str(chr(ch)) - elif self.state == 4: - if ch == ord('\n'): - self.state = 0 - return "\n" - return "" - -def remove_comment(json): - fmt = JSFormat() - return "".join([fmt.push(c) for c in json]) - - -def parse_json_in_str(data): - # parse json and convert everything from unicode to str - return json.loads(data, object_hook=_decode_dict) diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/stop.sh b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/stop.sh deleted file mode 100755 index 47f2dd0ca3..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/stop.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -#python3_ver=$(ls /usr/bin|grep -e "^python3[23]\.[1-9]\+$"|tail -1) -eval $(ps -ef | grep "[0-9] python3 server\\.py a" | awk '{print "kill "$2}') diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/tail.sh b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/tail.sh deleted file mode 100755 index aa37139396..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/tail.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -tail -f ssserver.log diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/tcprelay.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/tcprelay.py deleted file mode 100644 index a7711ae942..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/tcprelay.py +++ /dev/null @@ -1,1476 +0,0 @@ -#!/usr/bin/python3 -# -*- coding: utf-8 -*- -# -# Copyright 2015 clowwindy -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import absolute_import, division, print_function, \ - with_statement - -import time -import socket -import errno -import struct -import logging -import binascii -import traceback -import random -import platform -import threading - -from shadowsocks import encrypt, obfs, eventloop, shell, common, lru_cache, version -from shadowsocks.common import pre_parse_header, parse_header - -# we clear at most TIMEOUTS_CLEAN_SIZE timeouts each time -TIMEOUTS_CLEAN_SIZE = 512 - -MSG_FASTOPEN = 0x20000000 - -# SOCKS command definition -CMD_CONNECT = 1 -CMD_BIND = 2 -CMD_UDP_ASSOCIATE = 3 - -# for each opening port, we have a TCP Relay - -# for each connection, we have a TCP Relay Handler to handle the connection - -# for each handler, we have 2 sockets: -# local: connected to the client -# remote: connected to remote server - -# for each handler, it could be at one of several stages: - -# as sslocal: -# stage 0 SOCKS hello received from local, send hello to local -# stage 1 addr received from local, query DNS for remote -# stage 2 UDP assoc -# stage 3 DNS resolved, connect to remote -# stage 4 still connecting, more data from local received -# stage 5 remote connected, piping local and remote - -# as ssserver: -# stage 0 just jump to stage 1 -# stage 1 addr received from local, query DNS for remote -# stage 3 DNS resolved, connect to remote -# stage 4 still connecting, more data from local received -# stage 5 remote connected, piping local and remote - -STAGE_INIT = 0 -STAGE_ADDR = 1 -STAGE_UDP_ASSOC = 2 -STAGE_DNS = 3 -STAGE_CONNECTING = 4 -STAGE_STREAM = 5 -STAGE_DESTROYED = -1 - -# for each handler, we have 2 stream directions: -# upstream: from client to server direction -# read local and write to remote -# downstream: from server to client direction -# read remote and write to local - -STREAM_UP = 0 -STREAM_DOWN = 1 - -# for each stream, it's waiting for reading, or writing, or both -WAIT_STATUS_INIT = 0 -WAIT_STATUS_READING = 1 -WAIT_STATUS_WRITING = 2 -WAIT_STATUS_READWRITING = WAIT_STATUS_READING | WAIT_STATUS_WRITING - -NETWORK_MTU = 1500 -TCP_MSS = NETWORK_MTU - 40 -BUF_SIZE = 32 * 1024 -UDP_MAX_BUF_SIZE = 65536 - -class SpeedTester(object): - def __init__(self, max_speed = 0): - self.max_speed = max_speed * 1024 - self.last_time = time.time() - self.sum_len = 0 - - def update_limit(self, max_speed): - self.max_speed = max_speed * 1024 - - def add(self, data_len): - if self.max_speed > 0: - cut_t = time.time() - self.sum_len -= (cut_t - self.last_time) * self.max_speed - if self.sum_len < 0: - self.sum_len = 0 - self.last_time = cut_t - self.sum_len += data_len - - def isExceed(self): - if self.max_speed > 0: - cut_t = time.time() - self.sum_len -= (cut_t - self.last_time) * self.max_speed - if self.sum_len < 0: - self.sum_len = 0 - self.last_time = cut_t - return self.sum_len >= self.max_speed - return False - -class TCPRelayHandler(object): - def __init__(self, server, fd_to_handlers, loop, local_sock, config, - dns_resolver, is_local): - self._server = server - self._fd_to_handlers = fd_to_handlers - self._loop = loop - self._local_sock = local_sock - self._remote_sock = None - self._remote_sock_v6 = None - self._local_sock_fd = None - self._remote_sock_fd = None - self._remotev6_sock_fd = None - self._remote_udp = False - self._config = config - self._dns_resolver = dns_resolver - self._add_ref = 0 - if not self._create_encryptor(config): - return - - self._client_address = local_sock.getpeername()[:2] - self._accept_address = local_sock.getsockname()[:2] - self._user = None - self._user_id = server._listen_port - self._update_tcp_mss(local_sock) - - # TCP Relay works as either sslocal or ssserver - # if is_local, this is sslocal - self._is_local = is_local - self._encrypt_correct = True - self._obfs = obfs.obfs(config['obfs']) - self._protocol = obfs.obfs(config['protocol']) - self._overhead = self._obfs.get_overhead(self._is_local) + self._protocol.get_overhead(self._is_local) - self._recv_buffer_size = BUF_SIZE - self._overhead - - server_info = obfs.server_info(server.obfs_data) - server_info.host = config['server'] - server_info.port = server._listen_port - #server_info.users = server.server_users - #server_info.update_user_func = self._update_user - server_info.client = self._client_address[0] - server_info.client_port = self._client_address[1] - server_info.protocol_param = '' - server_info.obfs_param = config['obfs_param'] - server_info.iv = self._encryptor.cipher_iv - server_info.recv_iv = b'' - server_info.key_str = common.to_bytes(config['password']) - server_info.key = self._encryptor.cipher_key - server_info.head_len = 30 - server_info.tcp_mss = self._tcp_mss - server_info.buffer_size = self._recv_buffer_size - server_info.overhead = self._overhead - self._obfs.set_server_info(server_info) - - server_info = obfs.server_info(server.protocol_data) - server_info.host = config['server'] - server_info.port = server._listen_port - server_info.users = server.server_users - server_info.update_user_func = self._update_user - server_info.client = self._client_address[0] - server_info.client_port = self._client_address[1] - server_info.protocol_param = config['protocol_param'] - server_info.obfs_param = '' - server_info.iv = self._encryptor.cipher_iv - server_info.recv_iv = b'' - server_info.key_str = common.to_bytes(config['password']) - server_info.key = self._encryptor.cipher_key - server_info.head_len = 30 - server_info.tcp_mss = self._tcp_mss - server_info.buffer_size = self._recv_buffer_size - server_info.overhead = self._overhead - self._protocol.set_server_info(server_info) - - self._redir_list = config.get('redirect', ["*#0.0.0.0:0"]) - self._is_redirect = False - self._bind = config.get('out_bind', '') - self._bindv6 = config.get('out_bindv6', '') - self._ignore_bind_list = config.get('ignore_bind', []) - - self._fastopen_connected = False - self._data_to_write_to_local = [] - self._data_to_write_to_remote = [] - self._udp_data_send_buffer = b'' - self._upstream_status = WAIT_STATUS_READING - self._downstream_status = WAIT_STATUS_INIT - self._remote_address = None - - self._forbidden_iplist = config.get('forbidden_ip', None) - self._forbidden_portset = config.get('forbidden_port', None) - if is_local: - self._chosen_server = self._get_a_server() - - self.last_activity = 0 - self._update_activity() - self._server.add_connection(1) - self._server.stat_add(self._client_address[0], 1) - self._add_ref = 1 - self.speed_tester_u = SpeedTester(config.get("speed_limit_per_con", 0)) - self.speed_tester_d = SpeedTester(config.get("speed_limit_per_con", 0)) - self._recv_u_max_size = BUF_SIZE - self._recv_d_max_size = BUF_SIZE - self._recv_pack_id = 0 - self._udp_send_pack_id = 0 - self._udpv6_send_pack_id = 0 - - local_sock.setblocking(False) - local_sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1) - self._local_sock_fd = local_sock.fileno() - fd_to_handlers[self._local_sock_fd] = self - loop.add(local_sock, eventloop.POLL_IN | eventloop.POLL_ERR, self._server) - self._stage = STAGE_INIT - - def __hash__(self): - # default __hash__ is id / 16 - # we want to eliminate collisions - return id(self) - - @property - def remote_address(self): - return self._remote_address - - def _get_a_server(self): - server = self._config['server'] - server_port = self._config['server_port'] - if type(server_port) == list: - server_port = random.choice(server_port) - if type(server) == list: - server = random.choice(server) - logging.debug('chosen server: %s:%d', server, server_port) - return server, server_port - - def _update_tcp_mss(self, local_sock): - self._tcp_mss = TCP_MSS - try: - tcp_mss = local_sock.getsockopt(socket.SOL_TCP, socket.TCP_MAXSEG) - if tcp_mss > 500 and tcp_mss <= 1500: - self._tcp_mss = tcp_mss - logging.debug("TCP MSS = %d" % (self._tcp_mss,)) - except: - pass - - def _create_encryptor(self, config): - try: - self._encryptor = encrypt.Encryptor(config['password'], - config['method']) - return True - except Exception: - self._stage = STAGE_DESTROYED - logging.error('create encryptor fail at port %d', self._server._listen_port) - - def _update_user(self, user): - self._user = user - self._user_id = struct.unpack(' 6: - length = struct.unpack('>H', self._udp_data_send_buffer[:2])[0] - - if length > len(self._udp_data_send_buffer): - break - - data = self._udp_data_send_buffer[:length] - self._udp_data_send_buffer = self._udp_data_send_buffer[length:] - - frag = common.ord(data[2]) - if frag != 0: - logging.warn('drop a message since frag is %d' % (frag,)) - continue - else: - data = data[3:] - header_result = parse_header(data) - if header_result is None: - continue - connecttype, addrtype, dest_addr, dest_port, header_length = header_result - if (addrtype & 7) == 3: - af = common.is_ip(dest_addr) - if af == False: - handler = common.UDPAsyncDNSHandler(data[header_length:]) - handler.resolve(self._dns_resolver, (dest_addr, dest_port), self._handle_server_dns_resolved) - else: - return self._handle_server_dns_resolved("", (dest_addr, dest_port), dest_addr, data[header_length:]) - else: - return self._handle_server_dns_resolved("", (dest_addr, dest_port), dest_addr, data[header_length:]) - - except Exception as e: - #trace = traceback.format_exc() - #logging.error(trace) - error_no = eventloop.errno_from_exception(e) - if error_no in (errno.EAGAIN, errno.EINPROGRESS, - errno.EWOULDBLOCK): - uncomplete = True - else: - shell.print_exception(e) - logging.error("exception from %s:%d" % (self._client_address[0], self._client_address[1])) - self.destroy() - return False - return True - else: - try: - if self._encrypt_correct: - if sock == self._remote_sock: - self._server.add_transfer_u(self._user, len(data)) - self._update_activity(len(data)) - if data: - l = len(data) - s = sock.send(data) - if s < l: - data = data[s:] - uncomplete = True - else: - return - except (OSError, IOError) as e: - error_no = eventloop.errno_from_exception(e) - if error_no in (errno.EAGAIN, errno.EINPROGRESS, - errno.EWOULDBLOCK): - uncomplete = True - else: - #traceback.print_exc() - shell.print_exception(e) - logging.error("exception from %s:%d" % (self._client_address[0], self._client_address[1])) - self.destroy() - return False - except Exception as e: - shell.print_exception(e) - logging.error("exception from %s:%d" % (self._client_address[0], self._client_address[1])) - self.destroy() - return False - if uncomplete: - if sock == self._local_sock: - self._data_to_write_to_local.append(data) - self._update_stream(STREAM_DOWN, WAIT_STATUS_WRITING) - elif sock == self._remote_sock: - self._data_to_write_to_remote.append(data) - self._update_stream(STREAM_UP, WAIT_STATUS_WRITING) - else: - logging.error('write_all_to_sock:unknown socket from %s:%d' % (self._client_address[0], self._client_address[1])) - else: - if sock == self._local_sock: - self._update_stream(STREAM_DOWN, WAIT_STATUS_READING) - elif sock == self._remote_sock: - self._update_stream(STREAM_UP, WAIT_STATUS_READING) - else: - logging.error('write_all_to_sock:unknown socket from %s:%d' % (self._client_address[0], self._client_address[1])) - return True - - def _handle_server_dns_resolved(self, error, remote_addr, server_addr, data): - if error: - return - try: - addrs = socket.getaddrinfo(server_addr, remote_addr[1], 0, socket.SOCK_DGRAM, socket.SOL_UDP) - if not addrs: # drop - return - af, socktype, proto, canonname, sa = addrs[0] - if af == socket.AF_INET6: - self._remote_sock_v6.sendto(data, (server_addr, remote_addr[1])) - if self._udpv6_send_pack_id == 0: - addr, port = self._remote_sock_v6.getsockname()[:2] - common.connect_log('UDPv6 sendto %s(%s):%d from %s:%d by user %d' % - (common.to_str(remote_addr[0]), common.to_str(server_addr), remote_addr[1], addr, port, self._user_id)) - self._udpv6_send_pack_id += 1 - else: - self._remote_sock.sendto(data, (server_addr, remote_addr[1])) - if self._udp_send_pack_id == 0: - addr, port = self._remote_sock.getsockname()[:2] - common.connect_log('UDP sendto %s(%s):%d from %s:%d by user %d' % - (common.to_str(remote_addr[0]), common.to_str(server_addr), remote_addr[1], addr, port, self._user_id)) - self._udp_send_pack_id += 1 - return True - except Exception as e: - shell.print_exception(e) - logging.error("exception from %s:%d" % (self._client_address[0], self._client_address[1])) - - def _get_redirect_host(self, client_address, ogn_data): - host_list = self._redir_list or ["*#0.0.0.0:0"] - - if type(host_list) != list: - host_list = [host_list] - - items_sum = common.to_str(host_list[0]).rsplit('#', 1) - if len(items_sum) < 2: - hash_code = binascii.crc32(ogn_data) - addrs = socket.getaddrinfo(client_address[0], client_address[1], 0, socket.SOCK_STREAM, socket.SOL_TCP) - af, socktype, proto, canonname, sa = addrs[0] - address_bytes = common.inet_pton(af, sa[0]) - if af == socket.AF_INET6: - addr = struct.unpack('>Q', address_bytes[8:])[0] - elif af == socket.AF_INET: - addr = struct.unpack('>I', address_bytes)[0] - else: - addr = 0 - - host_port = [] - match_port = False - for host in host_list: - items = common.to_str(host).rsplit(':', 1) - if len(items) > 1: - try: - port = int(items[1]) - if port == self._server._listen_port: - match_port = True - host_port.append((items[0], port)) - except: - pass - else: - host_port.append((host, 80)) - - if match_port: - last_host_port = host_port - host_port = [] - for host in last_host_port: - if host[1] == self._server._listen_port: - host_port.append(host) - - return host_port[((hash_code & 0xffffffff) + addr) % len(host_port)] - - else: - host_port = [] - for host in host_list: - items_sum = common.to_str(host).rsplit('#', 1) - items_match = common.to_str(items_sum[0]).rsplit(':', 1) - items = common.to_str(items_sum[1]).rsplit(':', 1) - if len(items_match) > 1: - if items_match[1] != "*": - try: - if self._server._listen_port != int(items_match[1]) and int(items_match[1]) != 0: - continue - except: - pass - - if items_match[0] != "*" and common.match_regex( - items_match[0], ogn_data) == False: - continue - if len(items) > 1: - try: - port = int(items[1]) - return (items[0], port) - except: - pass - else: - return (items[0], 80) - - return ("0.0.0.0", 0) - - def _handel_protocol_error(self, client_address, ogn_data): - logging.warn("Protocol ERROR, TCP ogn data %s from %s:%d via port %d by UID %d" % (binascii.hexlify(ogn_data), client_address[0], client_address[1], self._server._listen_port, self._user_id)) - self._encrypt_correct = False - #create redirect or disconnect by hash code - host, port = self._get_redirect_host(client_address, ogn_data) - if port == 0: - raise Exception('can not parse header') - data = b"\x03" + common.to_bytes(common.chr(len(host))) + common.to_bytes(host) + struct.pack('>H', port) - self._is_redirect = True - logging.warn("TCP data redir %s:%d %s" % (host, port, binascii.hexlify(data))) - return data + ogn_data - - def _handle_stage_connecting(self, data): - if self._is_local: - if self._encryptor is not None: - data = self._protocol.client_pre_encrypt(data) - data = self._encryptor.encrypt(data) - data = self._obfs.client_encode(data) - if data: - self._data_to_write_to_remote.append(data) - if self._is_local and not self._fastopen_connected and \ - self._config['fast_open']: - # for sslocal and fastopen, we basically wait for data and use - # sendto to connect - try: - # only connect once - self._fastopen_connected = True - remote_sock = \ - self._create_remote_socket(self._chosen_server[0], - self._chosen_server[1]) - self._loop.add(remote_sock, eventloop.POLL_ERR, self._server) - data = b''.join(self._data_to_write_to_remote) - l = len(data) - s = remote_sock.sendto(data, MSG_FASTOPEN, self._chosen_server) - if s < l: - data = data[s:] - self._data_to_write_to_remote = [data] - else: - self._data_to_write_to_remote = [] - self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING) - except (OSError, IOError) as e: - if eventloop.errno_from_exception(e) == errno.EINPROGRESS: - # in this case data is not sent at all - self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING) - elif eventloop.errno_from_exception(e) == errno.ENOTCONN: - logging.error('fast open not supported on this OS') - self._config['fast_open'] = False - self.destroy() - else: - shell.print_exception(e) - if self._config['verbose']: - traceback.print_exc() - logging.error("exception from %s:%d" % (self._client_address[0], self._client_address[1])) - self.destroy() - - def _get_head_size(self, buf, def_value): - if len(buf) < 2: - return def_value - head_type = common.ord(buf[0]) & 0xF - if head_type == 1: - return 7 - if head_type == 4: - return 19 - if head_type == 3: - return 4 + common.ord(buf[1]) - return def_value - - def _handle_stage_addr(self, ogn_data, data): - try: - if self._is_local: - cmd = common.ord(data[1]) - if cmd == CMD_UDP_ASSOCIATE: - logging.debug('UDP associate') - if self._local_sock.family == socket.AF_INET6: - header = b'\x05\x00\x00\x04' - else: - header = b'\x05\x00\x00\x01' - addr, port = self._local_sock.getsockname()[:2] - addr_to_send = socket.inet_pton(self._local_sock.family, - addr) - port_to_send = struct.pack('>H', port) - self._write_to_sock(header + addr_to_send + port_to_send, - self._local_sock) - self._stage = STAGE_UDP_ASSOC - # just wait for the client to disconnect - return - elif cmd == CMD_CONNECT: - # just trim VER CMD RSV - data = data[3:] - else: - logging.error('invalid command %d', cmd) - self.destroy() - return - - before_parse_data = data - if self._is_local: - header_result = parse_header(data) - else: - data = pre_parse_header(data) - if data is None: - data = self._handel_protocol_error(self._client_address, ogn_data) - header_result = parse_header(data) - if header_result is not None: - try: - common.to_str(header_result[2]) - except Exception as e: - header_result = None - if header_result is None: - data = self._handel_protocol_error(self._client_address, ogn_data) - header_result = parse_header(data) - self._overhead = self._obfs.get_overhead(self._is_local) + self._protocol.get_overhead(self._is_local) - self._recv_buffer_size = BUF_SIZE - self._overhead - server_info = self._obfs.get_server_info() - server_info.buffer_size = self._recv_buffer_size - server_info = self._protocol.get_server_info() - server_info.buffer_size = self._recv_buffer_size - connecttype, addrtype, remote_addr, remote_port, header_length = header_result - if connecttype != 0: - pass - #common.connect_log('UDP over TCP by user %d' % - # (self._user_id, )) - else: - common.connect_log('TCP request %s:%d by user %d' % - (common.to_str(remote_addr), remote_port, self._user_id)) - self._remote_address = (common.to_str(remote_addr), remote_port) - self._remote_udp = (connecttype != 0) - # pause reading - self._update_stream(STREAM_UP, WAIT_STATUS_WRITING) - self._stage = STAGE_DNS - if self._is_local: - # forward address to remote - self._write_to_sock((b'\x05\x00\x00\x01' - b'\x00\x00\x00\x00\x10\x10'), - self._local_sock) - head_len = self._get_head_size(data, 30) - self._obfs.obfs.server_info.head_len = head_len - self._protocol.obfs.server_info.head_len = head_len - if self._encryptor is not None: - data = self._protocol.client_pre_encrypt(data) - data_to_send = self._encryptor.encrypt(data) - data_to_send = self._obfs.client_encode(data_to_send) - if data_to_send: - self._data_to_write_to_remote.append(data_to_send) - # notice here may go into _handle_dns_resolved directly - self._dns_resolver.resolve(self._chosen_server[0], - self._handle_dns_resolved) - else: - if len(data) > header_length: - self._data_to_write_to_remote.append(data[header_length:]) - # notice here may go into _handle_dns_resolved directly - self._dns_resolver.resolve(remote_addr, - self._handle_dns_resolved) - except Exception as e: - self._log_error(e) - if self._config['verbose']: - traceback.print_exc() - self.destroy() - - def _socket_bind_addr(self, sock, af): - bind_addr = '' - if self._bind and af == socket.AF_INET: - bind_addr = self._bind - elif self._bindv6 and af == socket.AF_INET6: - bind_addr = self._bindv6 - else: - bind_addr = self._accept_address[0] - - bind_addr = bind_addr.replace("::ffff:", "") - if bind_addr in self._ignore_bind_list: - bind_addr = None - if bind_addr: - local_addrs = socket.getaddrinfo(bind_addr, 0, 0, socket.SOCK_STREAM, socket.SOL_TCP) - if local_addrs[0][0] == af: - logging.debug("bind %s" % (bind_addr,)) - try: - sock.bind((bind_addr, 0)) - except Exception as e: - logging.warn("bind %s fail" % (bind_addr,)) - - def _create_remote_socket(self, ip, port): - if self._remote_udp: - addrs_v6 = socket.getaddrinfo("::", 0, 0, socket.SOCK_DGRAM, socket.SOL_UDP) - addrs = socket.getaddrinfo("0.0.0.0", 0, 0, socket.SOCK_DGRAM, socket.SOL_UDP) - else: - addrs = socket.getaddrinfo(ip, port, 0, socket.SOCK_STREAM, socket.SOL_TCP) - if len(addrs) == 0: - raise Exception("getaddrinfo failed for %s:%d" % (ip, port)) - af, socktype, proto, canonname, sa = addrs[0] - if not self._remote_udp and not self._is_redirect: - if self._forbidden_iplist: - if common.to_str(sa[0]) in self._forbidden_iplist: - if self._remote_address: - raise Exception('IP %s is in forbidden list, when connect to %s:%d via port %d by UID %d' % - (common.to_str(sa[0]), self._remote_address[0], self._remote_address[1], self._server._listen_port, self._user_id)) - raise Exception('IP %s is in forbidden list, reject' % - common.to_str(sa[0])) - if self._forbidden_portset: - if sa[1] in self._forbidden_portset: - if self._remote_address: - raise Exception('Port %d is in forbidden list, when connect to %s:%d via port %d by UID %d' % - (sa[1], self._remote_address[0], self._remote_address[1], self._server._listen_port, self._user_id)) - raise Exception('Port %d is in forbidden list, reject' % sa[1]) - remote_sock = socket.socket(af, socktype, proto) - self._remote_sock = remote_sock - self._remote_sock_fd = remote_sock.fileno() - self._fd_to_handlers[self._remote_sock_fd] = self - - if self._remote_udp: - af, socktype, proto, canonname, sa = addrs_v6[0] - remote_sock_v6 = socket.socket(af, socktype, proto) - self._remote_sock_v6 = remote_sock_v6 - self._remotev6_sock_fd = remote_sock_v6.fileno() - self._fd_to_handlers[self._remotev6_sock_fd] = self - - remote_sock.setblocking(False) - if self._remote_udp: - remote_sock_v6.setblocking(False) - - if not self._is_local: - self._socket_bind_addr(remote_sock, af) - self._socket_bind_addr(remote_sock_v6, af) - else: - remote_sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1) - if not self._is_local: - self._socket_bind_addr(remote_sock, af) - return remote_sock - - def _handle_dns_resolved(self, result, error): - if error: - self._log_error(error) - self.destroy() - return - if result: - ip = result[1] - if ip: - try: - self._stage = STAGE_CONNECTING - remote_addr = ip - if self._is_local: - remote_port = self._chosen_server[1] - else: - remote_port = self._remote_address[1] - - if self._is_local and self._config['fast_open']: - # for fastopen: - # wait for more data to arrive and send them in one SYN - self._stage = STAGE_CONNECTING - # we don't have to wait for remote since it's not - # created - self._update_stream(STREAM_UP, WAIT_STATUS_READING) - # TODO when there is already data in this packet - else: - # else do connect - remote_sock = self._create_remote_socket(remote_addr, - remote_port) - if self._remote_udp: - self._loop.add(remote_sock, - eventloop.POLL_IN, - self._server) - if self._remote_sock_v6: - self._loop.add(self._remote_sock_v6, - eventloop.POLL_IN, - self._server) - else: - try: - remote_sock.connect((remote_addr, remote_port)) - except (OSError, IOError) as e: - if eventloop.errno_from_exception(e) in (errno.EINPROGRESS, - errno.EWOULDBLOCK): - pass # always goto here - else: - raise e - addr, port = self._remote_sock.getsockname()[:2] - common.connect_log('TCP connecting %s(%s):%d from %s:%d by user %d' % - (common.to_str(self._remote_address[0]), common.to_str(remote_addr), remote_port, addr, port, self._user_id)) - - self._loop.add(remote_sock, - eventloop.POLL_ERR | eventloop.POLL_OUT, - self._server) - self._stage = STAGE_CONNECTING - self._update_stream(STREAM_UP, WAIT_STATUS_READWRITING) - self._update_stream(STREAM_DOWN, WAIT_STATUS_READING) - if self._remote_udp: - while self._data_to_write_to_remote: - data = self._data_to_write_to_remote[0] - del self._data_to_write_to_remote[0] - self._write_to_sock(data, self._remote_sock) - return - except Exception as e: - shell.print_exception(e) - if self._config['verbose']: - traceback.print_exc() - logging.error("exception from %s:%d" % (self._client_address[0], self._client_address[1])) - self.destroy() - - def _get_read_size(self, sock, recv_buffer_size, up): - if self._overhead == 0: - return recv_buffer_size - buffer_size = len(sock.recv(recv_buffer_size, socket.MSG_PEEK)) - frame_size = self._tcp_mss - self._overhead - if up: - buffer_size = min(buffer_size, self._recv_u_max_size) - self._recv_u_max_size = min(self._recv_u_max_size + frame_size, BUF_SIZE) - else: - buffer_size = min(buffer_size, self._recv_d_max_size) - self._recv_d_max_size = min(self._recv_d_max_size + frame_size, BUF_SIZE) - if buffer_size == recv_buffer_size: - return buffer_size - if buffer_size > frame_size: - buffer_size = int(buffer_size / frame_size) * frame_size - return buffer_size - - def _on_local_read(self): - # handle all local read events and dispatch them to methods for - # each stage - if not self._local_sock: - return - is_local = self._is_local - if is_local: - recv_buffer_size = self._get_read_size(self._local_sock, self._recv_buffer_size, True) - else: - recv_buffer_size = BUF_SIZE - data = None - try: - data = self._local_sock.recv(recv_buffer_size) - except (OSError, IOError) as e: - if eventloop.errno_from_exception(e) in \ - (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK): - return - if not data: - self.destroy() - return - - self.speed_tester_u.add(len(data)) - self._server.speed_tester_u(self._user_id).add(len(data)) - ogn_data = data - if not is_local: - if self._encryptor is not None: - if self._encrypt_correct: - try: - obfs_decode = self._obfs.server_decode(data) - if self._stage == STAGE_INIT: - self._overhead = self._obfs.get_overhead(self._is_local) + self._protocol.get_overhead(self._is_local) - server_info = self._protocol.get_server_info() - server_info.overhead = self._overhead - except Exception as e: - shell.print_exception(e) - logging.error("exception from %s:%d" % (self._client_address[0], self._client_address[1])) - self.destroy() - return - if obfs_decode[2]: - data = self._obfs.server_encode(b'') - try: - self._write_to_sock(data, self._local_sock) - except Exception as e: - shell.print_exception(e) - if self._config['verbose']: - traceback.print_exc() - logging.error("exception from %s:%d" % (self._client_address[0], self._client_address[1])) - self.destroy() - return - if obfs_decode[1]: - if not self._protocol.obfs.server_info.recv_iv: - iv_len = len(self._protocol.obfs.server_info.iv) - self._protocol.obfs.server_info.recv_iv = obfs_decode[0][:iv_len] - data = self._encryptor.decrypt(obfs_decode[0]) - else: - data = obfs_decode[0] - try: - data, sendback = self._protocol.server_post_decrypt(data) - if sendback: - backdata = self._protocol.server_pre_encrypt(b'') - backdata = self._encryptor.encrypt(backdata) - backdata = self._obfs.server_encode(backdata) - try: - self._write_to_sock(backdata, self._local_sock) - except Exception as e: - shell.print_exception(e) - if self._config['verbose']: - traceback.print_exc() - logging.error("exception from %s:%d" % (self._client_address[0], self._client_address[1])) - self.destroy() - return - except Exception as e: - shell.print_exception(e) - logging.error("exception from %s:%d" % (self._client_address[0], self._client_address[1])) - self.destroy() - return - else: - return - if not data: - return - if self._stage == STAGE_STREAM: - if self._is_local: - if self._encryptor is not None: - data = self._protocol.client_pre_encrypt(data) - data = self._encryptor.encrypt(data) - data = self._obfs.client_encode(data) - self._write_to_sock(data, self._remote_sock) - elif is_local and self._stage == STAGE_INIT: - # TODO check auth method - self._write_to_sock(b'\x05\00', self._local_sock) - self._stage = STAGE_ADDR - elif self._stage == STAGE_CONNECTING: - self._handle_stage_connecting(data) - elif (is_local and self._stage == STAGE_ADDR) or \ - (not is_local and self._stage == STAGE_INIT): - self._handle_stage_addr(ogn_data, data) - - def _on_remote_read(self, is_remote_sock): - # handle all remote read events - data = None - try: - if self._remote_udp: - if is_remote_sock: - data, addr = self._remote_sock.recvfrom(UDP_MAX_BUF_SIZE) - else: - data, addr = self._remote_sock_v6.recvfrom(UDP_MAX_BUF_SIZE) - port = struct.pack('>H', addr[1]) - try: - ip = socket.inet_aton(addr[0]) - data = b'\x00\x01' + ip + port + data - except Exception as e: - ip = socket.inet_pton(socket.AF_INET6, addr[0]) - data = b'\x00\x04' + ip + port + data - size = len(data) + 2 - data = struct.pack('>H', size) + data - #logging.info('UDP over TCP recvfrom %s:%d %d bytes to %s:%d' % (addr[0], addr[1], len(data), self._client_address[0], self._client_address[1])) - else: - if self._is_local: - recv_buffer_size = BUF_SIZE - else: - recv_buffer_size = self._get_read_size(self._remote_sock, self._recv_buffer_size, False) - data = self._remote_sock.recv(recv_buffer_size) - self._recv_pack_id += 1 - except (OSError, IOError) as e: - if eventloop.errno_from_exception(e) in \ - (errno.ETIMEDOUT, errno.EAGAIN, errno.EWOULDBLOCK, 10035): #errno.WSAEWOULDBLOCK - return - if not data: - self.destroy() - return - - self.speed_tester_d.add(len(data)) - self._server.speed_tester_d(self._user_id).add(len(data)) - if self._encryptor is not None: - if self._is_local: - try: - obfs_decode = self._obfs.client_decode(data) - except Exception as e: - shell.print_exception(e) - logging.error("exception from %s:%d" % (self._client_address[0], self._client_address[1])) - self.destroy() - return - if obfs_decode[1]: - send_back = self._obfs.client_encode(b'') - self._write_to_sock(send_back, self._remote_sock) - if not self._protocol.obfs.server_info.recv_iv: - iv_len = len(self._protocol.obfs.server_info.iv) - self._protocol.obfs.server_info.recv_iv = obfs_decode[0][:iv_len] - data = self._encryptor.decrypt(obfs_decode[0]) - try: - data = self._protocol.client_post_decrypt(data) - if self._recv_pack_id == 1: - self._tcp_mss = self._protocol.get_server_info().tcp_mss - except Exception as e: - shell.print_exception(e) - logging.error("exception from %s:%d" % (self._client_address[0], self._client_address[1])) - self.destroy() - return - else: - if self._encrypt_correct: - data = self._protocol.server_pre_encrypt(data) - data = self._encryptor.encrypt(data) - data = self._obfs.server_encode(data) - self._server.add_transfer_d(self._user, len(data)) - self._update_activity(len(data)) - else: - return - try: - self._write_to_sock(data, self._local_sock) - except Exception as e: - shell.print_exception(e) - if self._config['verbose']: - traceback.print_exc() - logging.error("exception from %s:%d" % (self._client_address[0], self._client_address[1])) - self.destroy() - - def _on_local_write(self): - # handle local writable event - if self._data_to_write_to_local: - data = b''.join(self._data_to_write_to_local) - self._data_to_write_to_local = [] - self._write_to_sock(data, self._local_sock) - else: - self._update_stream(STREAM_DOWN, WAIT_STATUS_READING) - - def _on_remote_write(self): - # handle remote writable event - self._stage = STAGE_STREAM - if self._data_to_write_to_remote: - data = b''.join(self._data_to_write_to_remote) - self._data_to_write_to_remote = [] - self._write_to_sock(data, self._remote_sock) - else: - self._update_stream(STREAM_UP, WAIT_STATUS_READING) - - def _on_local_error(self): - if self._local_sock: - err = eventloop.get_sock_error(self._local_sock) - if err.errno not in [errno.ECONNRESET, errno.EPIPE]: - logging.error(err) - logging.error("local error, exception from %s:%d" % (self._client_address[0], self._client_address[1])) - self.destroy() - - def _on_remote_error(self): - if self._remote_sock: - err = eventloop.get_sock_error(self._remote_sock) - if err.errno not in [errno.ECONNRESET]: - logging.error(err) - if self._remote_address: - logging.error("remote error, when connect to %s:%d" % (self._remote_address[0], self._remote_address[1])) - else: - logging.error("remote error, exception from %s:%d" % (self._client_address[0], self._client_address[1])) - self.destroy() - - def handle_event(self, sock, fd, event): - # handle all events in this handler and dispatch them to methods - handle = False - if self._stage == STAGE_DESTROYED: - logging.debug('ignore handle_event: destroyed') - return True - if self._user is not None and self._user not in self._server.server_users: - self.destroy() - return True - if fd == self._remote_sock_fd or fd == self._remotev6_sock_fd: - if event & eventloop.POLL_ERR: - handle = True - self._on_remote_error() - elif event & (eventloop.POLL_IN | eventloop.POLL_HUP): - if not self.speed_tester_d.isExceed() and not self._server.speed_tester_d(self._user_id).isExceed(): - handle = True - self._on_remote_read(sock == self._remote_sock) - else: - self._recv_d_max_size = self._tcp_mss - self._overhead - elif event & eventloop.POLL_OUT: - handle = True - self._on_remote_write() - elif fd == self._local_sock_fd: - if event & eventloop.POLL_ERR: - handle = True - self._on_local_error() - elif event & (eventloop.POLL_IN | eventloop.POLL_HUP): - if not self.speed_tester_u.isExceed() and not self._server.speed_tester_u(self._user_id).isExceed(): - handle = True - self._on_local_read() - else: - self._recv_u_max_size = self._tcp_mss - self._overhead - elif event & eventloop.POLL_OUT: - handle = True - self._on_local_write() - else: - logging.warn('unknown socket from %s:%d' % (self._client_address[0], self._client_address[1])) - try: - self._loop.removefd(fd) - except Exception as e: - shell.print_exception(e) - try: - del self._fd_to_handlers[fd] - except Exception as e: - shell.print_exception(e) - sock.close() - - return handle - - def _log_error(self, e): - logging.error('%s when handling connection from %s:%d' % - (e, self._client_address[0], self._client_address[1])) - - def stage(self): - return self._stage - - def destroy(self): - # destroy the handler and release any resources - # promises: - # 1. destroy won't make another destroy() call inside - # 2. destroy releases resources so it prevents future call to destroy - # 3. destroy won't raise any exceptions - # if any of the promises are broken, it indicates a bug has been - # introduced! mostly likely memory leaks, etc - if self._stage == STAGE_DESTROYED: - # this couldn't happen - logging.debug('already destroyed') - return - self._stage = STAGE_DESTROYED - if self._remote_address: - logging.debug('destroy: %s:%d' % - self._remote_address) - else: - logging.debug('destroy') - if self._remote_sock: - logging.debug('destroying remote') - try: - self._loop.removefd(self._remote_sock_fd) - except Exception as e: - shell.print_exception(e) - try: - if self._remote_sock_fd is not None: - del self._fd_to_handlers[self._remote_sock_fd] - except Exception as e: - shell.print_exception(e) - self._remote_sock.close() - self._remote_sock = None - if self._remote_sock_v6: - logging.debug('destroying remote_v6') - try: - self._loop.removefd(self._remotev6_sock_fd) - except Exception as e: - shell.print_exception(e) - try: - if self._remotev6_sock_fd is not None: - del self._fd_to_handlers[self._remotev6_sock_fd] - except Exception as e: - shell.print_exception(e) - self._remote_sock_v6.close() - self._remote_sock_v6 = None - if self._local_sock: - logging.debug('destroying local') - try: - self._loop.removefd(self._local_sock_fd) - except Exception as e: - shell.print_exception(e) - try: - if self._local_sock_fd is not None: - del self._fd_to_handlers[self._local_sock_fd] - except Exception as e: - shell.print_exception(e) - self._local_sock.close() - self._local_sock = None - if self._obfs: - self._obfs.dispose() - self._obfs = None - if self._protocol: - self._protocol.dispose() - self._protocol = None - self._encryptor = None - self._dns_resolver.remove_callback(self._handle_dns_resolved) - self._server.remove_handler(self) - if self._add_ref > 0: - self._server.add_connection(-1) - self._server.stat_add(self._client_address[0], -1) - -class TCPRelay(object): - def __init__(self, config, dns_resolver, is_local, stat_callback=None, stat_counter=None): - self._config = config - self._is_local = is_local - self._dns_resolver = dns_resolver - self._closed = False - self._eventloop = None - self._fd_to_handlers = {} - self.server_transfer_ul = 0 - self.server_transfer_dl = 0 - self.server_users = {} - self.server_users_cfg = {} - self.server_user_transfer_ul = {} - self.server_user_transfer_dl = {} - self.mu = False - self._speed_tester_u = {} - self._speed_tester_d = {} - self.server_connections = 0 - self.protocol_data = obfs.obfs(config['protocol']).init_data() - self.obfs_data = obfs.obfs(config['obfs']).init_data() - - if config.get('connect_verbose_info', 0) > 0: - common.connect_log = logging.info - - self._timeout = config['timeout'] - self._timeout_cache = lru_cache.LRUCache(timeout=self._timeout, - close_callback=self._close_tcp_client) - - if is_local: - listen_addr = config['local_address'] - listen_port = config['local_port'] - else: - listen_addr = config['server'] - listen_port = config['server_port'] - self._listen_port = listen_port - - if common.to_str(config['protocol']) in obfs.mu_protocol(): - self._update_users(None, None) - - addrs = socket.getaddrinfo(listen_addr, listen_port, 0, - socket.SOCK_STREAM, socket.SOL_TCP) - if len(addrs) == 0: - raise Exception("can't get addrinfo for %s:%d" % - (listen_addr, listen_port)) - af, socktype, proto, canonname, sa = addrs[0] - server_socket = socket.socket(af, socktype, proto) - server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - server_socket.bind(sa) - server_socket.setblocking(False) - if config['fast_open']: - try: - server_socket.setsockopt(socket.SOL_TCP, 23, 5) - except socket.error: - logging.error('warning: fast open is not available') - self._config['fast_open'] = False - server_socket.listen(config.get('max_connect', 1024)) - self._server_socket = server_socket - self._server_socket_fd = server_socket.fileno() - self._stat_counter = stat_counter - self._stat_callback = stat_callback - - def add_to_loop(self, loop): - if self._eventloop: - raise Exception('already add to loop') - if self._closed: - raise Exception('already closed') - self._eventloop = loop - self._eventloop.add(self._server_socket, - eventloop.POLL_IN | eventloop.POLL_ERR, self) - self._eventloop.add_periodic(self.handle_periodic) - - def remove_handler(self, client): - if hash(client) in self._timeout_cache: - del self._timeout_cache[hash(client)] - - def add_connection(self, val): - self.server_connections += val - logging.debug('server port %5d connections = %d' % (self._listen_port, self.server_connections,)) - - def get_ud(self): - return (self.server_transfer_ul, self.server_transfer_dl) - - def get_users_ud(self): - return (self.server_user_transfer_ul.copy(), self.server_user_transfer_dl.copy()) - - def _update_users(self, protocol_param, acl): - if protocol_param is None: - protocol_param = self._config['protocol_param'] - param = common.to_bytes(protocol_param).split(b'#') - if len(param) == 2: - self.mu = True - user_list = param[1].split(b',') - if user_list: - for user in user_list: - items = user.split(b':') - if len(items) == 2: - user_int_id = int(items[0]) - uid = struct.pack('= stat_dict.get(-1, 0) + connections_step: - logging.info('port %d connections up to %d' % (port, newval)) - stat_dict[-1] = stat_dict.get(-1, 0) + connections_step - elif newval <= stat_dict.get(-1, 0) - connections_step: - logging.info('port %d connections down to %d' % (port, newval)) - stat_dict[-1] = stat_dict.get(-1, 0) - connections_step - - def stat_add(self, local_addr, val): - if self._stat_counter is not None: - if self._listen_port not in self._stat_counter: - self._stat_counter[self._listen_port] = {} - newval = self._stat_counter[self._listen_port].get(local_addr, 0) + val - logging.debug('port %d addr %s connections %d' % (self._listen_port, local_addr, newval)) - self._stat_counter[self._listen_port][local_addr] = newval - self.update_stat(self._listen_port, self._stat_counter[self._listen_port], val) - if newval <= 0: - if local_addr in self._stat_counter[self._listen_port]: - del self._stat_counter[self._listen_port][local_addr] - - newval = self._stat_counter.get(0, 0) + val - self._stat_counter[0] = newval - logging.debug('Total connections %d' % newval) - - connections_step = 50 - if newval >= self._stat_counter.get(-1, 0) + connections_step: - logging.info('Total connections up to %d' % newval) - self._stat_counter[-1] = self._stat_counter.get(-1, 0) + connections_step - elif newval <= self._stat_counter.get(-1, 0) - connections_step: - logging.info('Total connections down to %d' % newval) - self._stat_counter[-1] = self._stat_counter.get(-1, 0) - connections_step - - def update_activity(self, client, data_len): - if data_len and self._stat_callback: - self._stat_callback(self._listen_port, data_len) - - self._timeout_cache[hash(client)] = client - - def _sweep_timeout(self): - self._timeout_cache.sweep() - - def _close_tcp_client(self, client): - if client.remote_address: - logging.debug('timed out: %s:%d' % - client.remote_address) - else: - logging.debug('timed out') - client.destroy() - - def handle_event(self, sock, fd, event): - # handle events and dispatch to handlers - handle = False - if sock: - logging.log(shell.VERBOSE_LEVEL, 'fd %d %s', fd, - eventloop.EVENT_NAMES.get(event, event)) - if sock == self._server_socket: - if event & eventloop.POLL_ERR: - # TODO - raise Exception('server_socket error') - handler = None - handle = True - try: - logging.debug('accept') - conn = self._server_socket.accept() - handler = TCPRelayHandler(self, self._fd_to_handlers, - self._eventloop, conn[0], self._config, - self._dns_resolver, self._is_local) - if handler.stage() == STAGE_DESTROYED: - conn[0].close() - except (OSError, IOError) as e: - error_no = eventloop.errno_from_exception(e) - if error_no in (errno.EAGAIN, errno.EINPROGRESS, - errno.EWOULDBLOCK): - return - else: - shell.print_exception(e) - if self._config['verbose']: - traceback.print_exc() - if handler: - handler.destroy() - else: - if sock: - handler = self._fd_to_handlers.get(fd, None) - if handler: - handle = handler.handle_event(sock, fd, event) - else: - logging.warn('unknown fd') - handle = True - try: - self._eventloop.removefd(fd) - except Exception as e: - shell.print_exception(e) - sock.close() - else: - logging.warn('poll removed fd') - handle = True - if fd in self._fd_to_handlers: - try: - del self._fd_to_handlers[fd] - except Exception as e: - shell.print_exception(e) - return handle - - def handle_periodic(self): - if self._closed: - if self._server_socket: - self._eventloop.removefd(self._server_socket_fd) - self._server_socket.close() - self._server_socket = None - logging.info('closed TCP port %d', self._listen_port) - for handler in list(self._fd_to_handlers.values()): - handler.destroy() - self._sweep_timeout() - - def close(self, next_tick=False): - logging.debug('TCP close') - self._closed = True - if not next_tick: - if self._eventloop: - self._eventloop.remove_periodic(self.handle_periodic) - self._eventloop.removefd(self._server_socket_fd) - self._server_socket.close() - for handler in list(self._fd_to_handlers.values()): - handler.destroy() diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/udprelay.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/udprelay.py deleted file mode 100644 index 5f2bcc2124..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/udprelay.py +++ /dev/null @@ -1,656 +0,0 @@ -#!/usr/bin/python3 -# -*- coding: utf-8 -*- -# -# Copyright 2015 clowwindy -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -# SOCKS5 UDP Request -# +----+------+------+----------+----------+----------+ -# |RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA | -# +----+------+------+----------+----------+----------+ -# | 2 | 1 | 1 | Variable | 2 | Variable | -# +----+------+------+----------+----------+----------+ - -# SOCKS5 UDP Response -# +----+------+------+----------+----------+----------+ -# |RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA | -# +----+------+------+----------+----------+----------+ -# | 2 | 1 | 1 | Variable | 2 | Variable | -# +----+------+------+----------+----------+----------+ - -# shadowsocks UDP Request (before encrypted) -# +------+----------+----------+----------+ -# | ATYP | DST.ADDR | DST.PORT | DATA | -# +------+----------+----------+----------+ -# | 1 | Variable | 2 | Variable | -# +------+----------+----------+----------+ - -# shadowsocks UDP Response (before encrypted) -# +------+----------+----------+----------+ -# | ATYP | DST.ADDR | DST.PORT | DATA | -# +------+----------+----------+----------+ -# | 1 | Variable | 2 | Variable | -# +------+----------+----------+----------+ - -# shadowsocks UDP Request and Response (after encrypted) -# +-------+--------------+ -# | IV | PAYLOAD | -# +-------+--------------+ -# | Fixed | Variable | -# +-------+--------------+ - -# HOW TO NAME THINGS -# ------------------ -# `dest` means destination server, which is from DST fields in the SOCKS5 -# request -# `local` means local server of shadowsocks -# `remote` means remote server of shadowsocks -# `client` means UDP clients that connects to other servers -# `server` means the UDP server that handles user requests - -from __future__ import absolute_import, division, print_function, \ - with_statement - -import time -import socket -import logging -import struct -import errno -import random -import binascii -import traceback -import threading - -from shadowsocks import encrypt, obfs, eventloop, lru_cache, common, shell -from shadowsocks.common import pre_parse_header, parse_header, pack_addr - -# for each handler, we have 2 stream directions: -# upstream: from client to server direction -# read local and write to remote -# downstream: from server to client direction -# read remote and write to local - -STREAM_UP = 0 -STREAM_DOWN = 1 - -# for each stream, it's waiting for reading, or writing, or both -WAIT_STATUS_INIT = 0 -WAIT_STATUS_READING = 1 -WAIT_STATUS_WRITING = 2 -WAIT_STATUS_READWRITING = WAIT_STATUS_READING | WAIT_STATUS_WRITING - -BUF_SIZE = 65536 -DOUBLE_SEND_BEG_IDS = 16 -POST_MTU_MIN = 500 -POST_MTU_MAX = 1400 -SENDING_WINDOW_SIZE = 8192 - -STAGE_INIT = 0 -STAGE_RSP_ID = 1 -STAGE_DNS = 2 -STAGE_CONNECTING = 3 -STAGE_STREAM = 4 -STAGE_DESTROYED = -1 - -CMD_CONNECT = 0 -CMD_RSP_CONNECT = 1 -CMD_CONNECT_REMOTE = 2 -CMD_RSP_CONNECT_REMOTE = 3 -CMD_POST = 4 -CMD_SYN_STATUS = 5 -CMD_POST_64 = 6 -CMD_SYN_STATUS_64 = 7 -CMD_DISCONNECT = 8 - -CMD_VER_STR = b"\x08" - -RSP_STATE_EMPTY = b"" -RSP_STATE_REJECT = b"\x00" -RSP_STATE_CONNECTED = b"\x01" -RSP_STATE_CONNECTEDREMOTE = b"\x02" -RSP_STATE_ERROR = b"\x03" -RSP_STATE_DISCONNECT = b"\x04" -RSP_STATE_REDIRECT = b"\x05" - -def client_key(source_addr, server_af): - # notice this is server af, not dest af - return '%s:%s:%d' % (source_addr[0], source_addr[1], server_af) - -class UDPRelay(object): - def __init__(self, config, dns_resolver, is_local, stat_callback=None, stat_counter=None): - self._config = config - if config.get('connect_verbose_info', 0) > 0: - common.connect_log = logging.info - if is_local: - self._listen_addr = config['local_address'] - self._listen_port = config['local_port'] - self._remote_addr = config['server'] - self._remote_port = config['server_port'] - else: - self._listen_addr = config['server'] - self._listen_port = config['server_port'] - self._remote_addr = None - self._remote_port = None - self._dns_resolver = dns_resolver - self._password = common.to_bytes(config['password']) - self._method = config['method'] - self._timeout = config['timeout'] - self._is_local = is_local - self._udp_cache_size = config['udp_cache'] - self._cache = lru_cache.LRUCache(timeout=config['udp_timeout'], - close_callback=self._close_client_pair) - self._cache_dns_client = lru_cache.LRUCache(timeout=10, - close_callback=self._close_client_pair) - self._client_fd_to_server_addr = {} - #self._dns_cache = lru_cache.LRUCache(timeout=1800) - self._eventloop = None - self._closed = False - self.server_transfer_ul = 0 - self.server_transfer_dl = 0 - self.server_users = {} - self.server_user_transfer_ul = {} - self.server_user_transfer_dl = {} - - if common.to_bytes(config['protocol']) in obfs.mu_protocol(): - self._update_users(None, None) - - self.protocol_data = obfs.obfs(config['protocol']).init_data() - self._protocol = obfs.obfs(config['protocol']) - server_info = obfs.server_info(self.protocol_data) - server_info.host = self._listen_addr - server_info.port = self._listen_port - server_info.users = self.server_users - server_info.protocol_param = config['protocol_param'] - server_info.obfs_param = '' - server_info.iv = b'' - server_info.recv_iv = b'' - server_info.key_str = common.to_bytes(config['password']) - server_info.key = encrypt.encrypt_key(self._password, self._method) - server_info.head_len = 30 - server_info.tcp_mss = 1452 - server_info.buffer_size = BUF_SIZE - server_info.overhead = 0 - self._protocol.set_server_info(server_info) - - self._sockets = set() - self._fd_to_handlers = {} - self._reqid_to_hd = {} - self._data_to_write_to_server_socket = [] - - self._timeout_cache = lru_cache.LRUCache(timeout=self._timeout, - close_callback=self._close_tcp_client) - - self._bind = config.get('out_bind', '') - self._bindv6 = config.get('out_bindv6', '') - self._ignore_bind_list = config.get('ignore_bind', []) - - if 'forbidden_ip' in config: - self._forbidden_iplist = config['forbidden_ip'] - else: - self._forbidden_iplist = None - if 'forbidden_port' in config: - self._forbidden_portset = config['forbidden_port'] - else: - self._forbidden_portset = None - - addrs = socket.getaddrinfo(self._listen_addr, self._listen_port, 0, - socket.SOCK_DGRAM, socket.SOL_UDP) - if len(addrs) == 0: - raise Exception("can't get addrinfo for %s:%d" % - (self._listen_addr, self._listen_port)) - af, socktype, proto, canonname, sa = addrs[0] - server_socket = socket.socket(af, socktype, proto) - server_socket.bind((self._listen_addr, self._listen_port)) - server_socket.setblocking(False) - self._server_socket = server_socket - self._stat_callback = stat_callback - - def _get_a_server(self): - server = self._config['server'] - server_port = self._config['server_port'] - if type(server_port) == list: - server_port = random.choice(server_port) - if type(server) == list: - server = random.choice(server) - logging.debug('chosen server: %s:%d', server, server_port) - return server, server_port - - def get_ud(self): - return (self.server_transfer_ul, self.server_transfer_dl) - - def get_users_ud(self): - ret = (self.server_user_transfer_ul.copy(), self.server_user_transfer_dl.copy()) - return ret - - def _update_users(self, protocol_param, acl): - if protocol_param is None: - protocol_param = self._config['protocol_param'] - param = common.to_bytes(protocol_param).split(b'#') - if len(param) == 2: - user_list = param[1].split(b',') - if user_list: - for user in user_list: - items = user.split(b':') - if len(items) == 2: - user_int_id = int(items[0]) - uid = struct.pack(' header_length + 13 and data[header_length + 4 : header_length + 12] == b"\x00\x01\x00\x00\x00\x00\x00\x00": - is_dns = True - else: - pass - if sa[1] == 53 and is_dns: #DNS - logging.debug("DNS query %s from %s:%d" % (common.to_str(sa[0]), r_addr[0], r_addr[1])) - self._cache_dns_client[key] = (client, uid) - else: - self._cache[key] = (client, uid) - self._client_fd_to_server_addr[client.fileno()] = (r_addr, af) - - self._sockets.add(client.fileno()) - self._eventloop.add(client, eventloop.POLL_IN, self) - - logging.debug('UDP port %5d sockets %d' % (self._listen_port, len(self._sockets))) - - if uid is not None: - user_id = struct.unpack(' 255: - # drop - return - data = pack_addr(r_addr[0]) + struct.pack('>H', r_addr[1]) + data - ref_iv = [encrypt.encrypt_new_iv(self._method)] - self._protocol.obfs.server_info.iv = ref_iv[0] - data = self._protocol.server_udp_pre_encrypt(data, client_uid) - response = encrypt.encrypt_all_iv(self._protocol.obfs.server_info.key, self._method, 1, - data, ref_iv) - if not response: - return - else: - ref_iv = [0] - data = encrypt.encrypt_all_iv(self._protocol.obfs.server_info.key, self._method, 0, - data, ref_iv) - if not data: - return - self._protocol.obfs.server_info.recv_iv = ref_iv[0] - data = self._protocol.client_udp_post_decrypt(data) - header_result = parse_header(data) - if header_result is None: - return - #connecttype, dest_addr, dest_port, header_length = header_result - #logging.debug('UDP handle_client %s:%d to %s:%d' % (common.to_str(r_addr[0]), r_addr[1], dest_addr, dest_port)) - - response = b'\x00\x00\x00' + data - - if client_addr: - if client_uid: - self.add_transfer_d(client_uid, len(response)) - else: - self.server_transfer_dl += len(response) - self.write_to_server_socket(response, client_addr[0]) - if client_dns_pair: - logging.debug("remove dns client %s:%d" % (client_addr[0][0], client_addr[0][1])) - del self._cache_dns_client[key] - self._close_client(client_dns_pair[0]) - else: - # this packet is from somewhere else we know - # simply drop that packet - pass - - def write_to_server_socket(self, data, addr): - uncomplete = False - retry = 0 - try: - self._server_socket.sendto(data, addr) - data = None - while self._data_to_write_to_server_socket: - data_buf = self._data_to_write_to_server_socket[0] - retry = data_buf[1] + 1 - del self._data_to_write_to_server_socket[0] - data, addr = data_buf[0] - self._server_socket.sendto(data, addr) - except (OSError, IOError) as e: - error_no = eventloop.errno_from_exception(e) - uncomplete = True - if error_no in (errno.EWOULDBLOCK,): - pass - else: - shell.print_exception(e) - return False - #if uncomplete and data is not None and retry < 3: - # self._data_to_write_to_server_socket.append([(data, addr), retry]) - #''' - - def add_to_loop(self, loop): - if self._eventloop: - raise Exception('already add to loop') - if self._closed: - raise Exception('already closed') - self._eventloop = loop - - server_socket = self._server_socket - self._eventloop.add(server_socket, - eventloop.POLL_IN | eventloop.POLL_ERR, self) - loop.add_periodic(self.handle_periodic) - - def remove_handler(self, client): - if hash(client) in self._timeout_cache: - del self._timeout_cache[hash(client)] - - def update_activity(self, client): - self._timeout_cache[hash(client)] = client - - def _sweep_timeout(self): - self._timeout_cache.sweep() - - def _close_tcp_client(self, client): - if client.remote_address: - logging.debug('timed out: %s:%d' % - client.remote_address) - else: - logging.debug('timed out') - client.destroy() - client.destroy_local() - - def handle_event(self, sock, fd, event): - if sock == self._server_socket: - if event & eventloop.POLL_ERR: - logging.error('UDP server_socket err') - try: - self._handle_server() - except Exception as e: - shell.print_exception(e) - if self._config['verbose']: - traceback.print_exc() - elif sock and (fd in self._sockets): - if event & eventloop.POLL_ERR: - logging.error('UDP client_socket err') - try: - self._handle_client(sock) - except Exception as e: - shell.print_exception(e) - if self._config['verbose']: - traceback.print_exc() - else: - if sock: - handler = self._fd_to_handlers.get(fd, None) - if handler: - handler.handle_event(sock, event) - else: - logging.warn('poll removed fd') - - def handle_periodic(self): - if self._closed: - self._cache.clear(0) - self._cache_dns_client.clear(0) - if self._eventloop: - self._eventloop.remove_periodic(self.handle_periodic) - self._eventloop.remove(self._server_socket) - if self._server_socket: - self._server_socket.close() - self._server_socket = None - logging.info('closed UDP port %d', self._listen_port) - else: - before_sweep_size = len(self._sockets) - self._cache.sweep() - self._cache_dns_client.sweep() - if before_sweep_size != len(self._sockets): - logging.debug('UDP port %5d sockets %d' % (self._listen_port, len(self._sockets))) - self._sweep_timeout() - - def close(self, next_tick=False): - logging.debug('UDP close') - self._closed = True - if not next_tick: - if self._eventloop: - self._eventloop.remove_periodic(self.handle_periodic) - self._eventloop.remove(self._server_socket) - self._server_socket.close() - self._cache.clear(0) - self._cache_dns_client.clear(0) diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/user.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/user.py deleted file mode 100644 index 3398934173..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/user.py +++ /dev/null @@ -1,240 +0,0 @@ -#coding:utf-8 - -import base64 -import re - -class miss: - def ssr4(self,ssrurl): - missing_padding = 4 - len(ssrurl) % 4 - if missing_padding: - ssrurl += b'='* missing_padding - return ssrurl - -def checkip(ip): - p = re.compile('^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$') - if p.match(ip): - return False - else: - print "输入错误请重新输入" - return True - -def checkport(port): - try: - if int(port)<0 or int(port)>65535: - print "输入错误请重新输入" - return True - return False - except: - print "输入错误请重新输入" - return True - -print ''' -请输入SSR地址码 -(就是ssr://XX,复制粘贴不嫌长您了就手打) -手动配置服务器信息请输入1''' - -error = True -while error: - ssrhead = raw_input() - if ssrhead == "1": - break - try: - ssrhead = re.split('[:/]',ssrhead) - ssrurl = miss() - ssrurl = ssrurl.ssr4(ssrhead[3]) - ssrurl = base64.urlsafe_b64decode(ssrurl) - ssrurl = re.split('[:/?&]',ssrurl) - serverip = ssrurl[0] - serverport = ssrurl[1] - password = ssrurl[5] - password = miss() - password = password.ssr4(ssrurl[5]) - password = base64.urlsafe_b64decode(password) - method = ssrurl[3] - protocol = ssrurl[2] - obfs = ssrurl[4] - error = False - except: - print "导入失败,请输入正确的SSR地址或输入1手动配置" - error = True - -if ssrhead == "1": - error = True - while error: - serverip = raw_input("请输入服务器IP地址:\n") - error = checkip(serverip) - error = True - while error: - serverport = raw_input("请输入服务器端口:\n") - error = checkport(serverport) - error = True - while error: - print "请输入本机代理地址,默认127.0.0.1,使用默认请回车" - localaddress = raw_input() - if localaddress == "": - localaddress = "127.0.0.1" - error = checkip(localaddress) - error = True - while error: - print "请输入本机代理端口,默认1080,使用默认请回车" - localport = raw_input() - if localport == "": - localport = "1080" - error = checkport(localport) - password = raw_input("请输入密码:\n") - - print ''' -0="NONE不加密" -1="table" -2="rc4" -3="rc4-md5" -4="rc4-md5-6" -5="aes-128-cfb" -6="aes-192-cfb" -7="aes-256-cfb" -8="aes-128-ctr" -9="aes-192-ctr" -10="aes-256-ctr" -11="bf-cfb" -12="camellia-128-cfb" -13="camellia-192-cfb" -14="camellia-256-cfb" -15="cast5-cfb" -16="des-cfb" -17="idea-cfb" -18="rc2-cfb" -19="seed-cfb" -20="salsa20" -21="chacha20" -22="chacha20-ietf" - -请输入对应的加密方式数字''' - method = ["","table","rc4","rc4-md5","rc4-md5-6","aes-128-cfb"\ -,"aes-192-cfb","aes-256-cfb","aes-128-ctr","aes-192-ctr","aes-256-ctr"\ -,"bf-cfb","camellia-128-cfb","camellia-192-cfb","camellia-256-cfb"\ -,"cast5-cfb","des-cfb","idea-cfb","rc2-cfb","seed-cfb","salsa20"\ -,"chacha20","chacha20-ietf"] - error = True - while error: - try: - num = input() - if num < 0: - num = "错误" - method = method[num] - error = False - except: - print "输入错误,请输入正确的数字" - error = True - - print ''' -1="origin" -2="verify_simple" -3="verify_sha1" -4="auth_sha1" -5="auth_sha1_v2" -6="auth_sha1_v4" -7="auth_aes128_sha1" -8="auth_aes128_md5" -9="auth_chain_a" -10="auth_chain_b" -11="auth_chain_c" -12="auth_chain_d" - -请输入对应的协议插件数字''' - protocol = ["origin","verify_simple","verify_sha1","auth_sha1","auth_sha1_v2","auth_sha1_v4"\ -,"auth_aes128_sha1","auth_aes128_md5","auth_chain_a","auth_chain_b","auth_chain_c","auth_chain_d"] - error = True - while error: - try: - num = input() - if num < 1: - num = "错误" - protocol = protocol[num-1] - error = False - except: - print "请输入正确的数字" - error = True - - protocolparam = raw_input("请输入协议参数,不使用参数请回车:\n") - - print ''' -1="plain" -2="http_simple" -3="http_post" -4="tls_simple" -5="tls1.2_ticket_auth" -6="tls1.2_ticket_fastauth" - -请输入对应的混淆参数的数字''' - obfs = ["plain","http_simple","http_post","tls_simple"\ -,"tls1.2_ticket_auth","tls1.2_ticket_fastauth"] - error = True - while error: - try: - num = input() - if num < 1: - num = "错误" - obfs = obfs[num-1] - error = False - except: - print "请输入正确的数字" - error = True - - print ''' -请输入混淆参数 -示例:baidu.com (不需要加http) -不使用参数请回车''' - obfsparam = raw_input() - -else: - error = True - while error: - print "请输入本机代理地址,默认127.0.0.1,使用默认请回车" - localaddress = raw_input() - if localaddress == "": - localaddress = "127.0.0.1" - error = checkip(localaddress) - error = True - while error: - print "请输入本机代理端口,默认1080,使用默认请回车" - localport = raw_input() - if localport == "": - localport = "1080" - error = checkport(localport) - protocolparam = raw_input("请输入协议参数,不使用参数请回车:\n") - print ''' -请输入混淆参数 -示例:baidu.com (不需要加http) -不使用参数请回车''' - obfsparam = raw_input() - -user='''{ - "server": "%s", - "server_ipv6": "::", - "server_port": %s, - "local_address": "%s", - "local_port": %s, - - "password": "%s", - "method": "%s", - "protocol": "%s", - "protocol_param": "%s", - "obfs": "%s", - "obfs_param": "%s", - "speed_limit_per_con": 0, - "speed_limit_per_user": 0, - - "additional_ports" : {}, - "timeout": 120, - "udp_timeout": 60, - "dns_ipv6": false, - "connect_verbose_info": 0, - "redirect": "", - "fast_open": false -} -'''%(serverip,serverport,localaddress,localport,\ -password,method,protocol,protocolparam,obfs,obfsparam) -with open('user-config.json','w') as f: - f.write(user.encode("utf-8")) -print user+"\n"+"请检查输入是否有误,若需要修改请重新执行程序。\ -\n启动ssr请在终端切换至shadowsocksr/shadowsocks目录执行python3 local.py -d start" diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/version.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/version.py deleted file mode 100644 index e7648f4a3f..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/version.py +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/python3 -# -*- coding: utf-8 -*- -# -# Copyright 2017 breakwa11 -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -def version(): - return '3.4.0 2017-07-27' - diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/stop.sh b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/stop.sh deleted file mode 100755 index f75cea0c83..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/stop.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -# python3_ver=$(ls /usr/bin|grep -e "^python[23]\.[1-9]\+$"|tail -1) -eval $(ps -ef | grep "[0-9] python3 server\\.py m" | awk '{print "kill "$2}') diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/switchrule.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/switchrule.py deleted file mode 100644 index 6687e12cfb..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/switchrule.py +++ /dev/null @@ -1,8 +0,0 @@ -def getKeys(key_list): - return key_list - #return key_list + ['plan'] # append the column name 'plan' - -def isTurnOn(row): - return True - #return row['plan'] == 'B' # then judge here - diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tail.sh b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tail.sh deleted file mode 100755 index f36f605eed..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tail.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -cd `dirname $0` -tail -f ssserver.log diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/aes-cfb1.json b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/aes-cfb1.json deleted file mode 100644 index 70ae6709d7..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/aes-cfb1.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "server":"127.0.0.1", - "server_port":8388, - "local_port":1081, - "password":"aes_password", - "timeout":60, - "method":"aes-256-cfb1", - "local_address":"127.0.0.1", - "fast_open":false -} diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/aes-cfb8.json b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/aes-cfb8.json deleted file mode 100644 index fe8b715855..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/aes-cfb8.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "server":"127.0.0.1", - "server_port":8388, - "local_port":1081, - "password":"aes_password", - "timeout":60, - "method":"aes-256-cfb8", - "local_address":"127.0.0.1", - "fast_open":false -} diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/aes-ctr.json b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/aes-ctr.json deleted file mode 100644 index 1f5a1d7e42..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/aes-ctr.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "server":"127.0.0.1", - "server_port":8388, - "local_port":1081, - "password":"aes_password", - "timeout":60, - "method":"aes-256-ctr", - "local_address":"127.0.0.1", - "fast_open":false -} diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/aes.json b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/aes.json deleted file mode 100644 index 2fc29f3af5..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/aes.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "server":"127.0.0.1", - "server_port":8388, - "local_port":1081, - "password":"aes_password", - "timeout":60, - "method":"aes-256-cfb", - "local_address":"127.0.0.1", - "fast_open":false -} diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/assert.sh b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/assert.sh deleted file mode 100755 index b0c679cbcd..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/assert.sh +++ /dev/null @@ -1,148 +0,0 @@ -#!/bin/bash -# assert.sh 1.0 - bash unit testing framework -# Copyright (C) 2009, 2010, 2011, 2012 Robert Lehmann -# -# http://github.com/lehmannro/assert.sh -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program. If not, see . - -export DISCOVERONLY=${DISCOVERONLY:-} -export DEBUG=${DEBUG:-} -export STOP=${STOP:-} -export INVARIANT=${INVARIANT:-} -export CONTINUE=${CONTINUE:-} - -args="$(getopt -n "$0" -l \ - verbose,help,stop,discover,invariant,continue vhxdic $*)" \ -|| exit -1 -for arg in $args; do - case "$arg" in - -h) - echo "$0 [-vxidc]" \ - "[--verbose] [--stop] [--invariant] [--discover] [--continue]" - echo "`sed 's/./ /g' <<< "$0"` [-h] [--help]" - exit 0;; - --help) - cat < [stdin] - (( tests_ran++ )) || : - [[ -n "$DISCOVERONLY" ]] && return || true - # printf required for formatting - printf -v expected "x${2:-}" # x required to overwrite older results - result="$(eval 2>/dev/null $1 <<< ${3:-})" || true - # Note: $expected is already decorated - if [[ "x$result" == "$expected" ]]; then - [[ -n "$DEBUG" ]] && echo -n . || true - return - fi - result="$(sed -e :a -e '$!N;s/\n/\\n/;ta' <<< "$result")" - [[ -z "$result" ]] && result="nothing" || result="\"$result\"" - [[ -z "$2" ]] && expected="nothing" || expected="\"$2\"" - _assert_fail "expected $expected${_indent}got $result" "$1" "$3" -} - -assert_raises() { - # assert_raises [stdin] - (( tests_ran++ )) || : - [[ -n "$DISCOVERONLY" ]] && return || true - status=0 - (eval $1 <<< ${3:-}) > /dev/null 2>&1 || status=$? - expected=${2:-0} - if [[ "$status" -eq "$expected" ]]; then - [[ -n "$DEBUG" ]] && echo -n . || true - return - fi - _assert_fail "program terminated with code $status instead of $expected" "$1" "$3" -} - -_assert_fail() { - # _assert_fail - [[ -n "$DEBUG" ]] && echo -n X - report="test #$tests_ran \"$2${3:+ <<< $3}\" failed:${_indent}$1" - if [[ -n "$STOP" ]]; then - [[ -n "$DEBUG" ]] && echo - echo "$report" - exit 1 - fi - tests_errors[$tests_failed]="$report" - (( tests_failed++ )) || : -} - -_assert_reset -: ${tests_suite_status:=0} # remember if any of the tests failed so far -_assert_cleanup() { - local status=$? - # modify exit code if it's not already non-zero - [[ $status -eq 0 && -z $CONTINUE ]] && exit $tests_suite_status -} -trap _assert_cleanup EXIT diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/chacha20.json b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/chacha20.json deleted file mode 100644 index fc2af8e571..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/chacha20.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "server":"127.0.0.1", - "server_port":8388, - "local_port":1081, - "password":"salsa20_password", - "timeout":60, - "method":"chacha20", - "local_address":"127.0.0.1", - "fast_open":false -} diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/client-multi-server-ip.json b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/client-multi-server-ip.json deleted file mode 100644 index 3050c113f6..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/client-multi-server-ip.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "server":["127.0.0.1", "127.0.0.1"], - "server_port":8388, - "local_port":1081, - "password":"aes_password", - "timeout":60, - "method":"aes-256-cfb", - "local_address":"127.0.0.1", - "fast_open":false -} diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/coverage_server.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/coverage_server.py deleted file mode 100644 index 4f6e753072..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/coverage_server.py +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright 2015 clowwindy -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -if __name__ == '__main__': - import tornado.ioloop - import tornado.web - import urllib - - class MainHandler(tornado.web.RequestHandler): - def get(self, project): - try: - with open('/tmp/%s-coverage' % project, 'rb') as f: - coverage = f.read().strip() - n = int(coverage.strip('%')) - if n >= 80: - color = 'brightgreen' - else: - color = 'yellow' - self.redirect(('https://img.shields.io/badge/' - 'coverage-%s-%s.svg' - '?style=flat') % - (urllib.quote(coverage), color)) - except IOError: - raise tornado.web.HTTPError(404) - - application = tornado.web.Application([ - (r"/([a-zA-Z0-9\-_]+)", MainHandler), - ]) - - if __name__ == "__main__": - application.listen(8888, address='127.0.0.1') - tornado.ioloop.IOLoop.instance().start() diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/fastopen.json b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/fastopen.json deleted file mode 100644 index b4f60d48e0..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/fastopen.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "server":"127.0.0.1", - "server_port":8388, - "local_port":1081, - "password":"fastopen_password", - "timeout":60, - "method":"aes-256-cfb", - "local_address":"127.0.0.1", - "fast_open":true -} diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/ipv6-client-side.json b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/ipv6-client-side.json deleted file mode 100644 index e14bb07872..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/ipv6-client-side.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "server":"::1", - "server_port":8388, - "local_port":1081, - "password":"aes_password", - "timeout":60, - "method":"aes-256-cfb", - "local_address":"127.0.0.1", - "fast_open":false -} diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/ipv6.json b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/ipv6.json deleted file mode 100644 index 18263ee404..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/ipv6.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "server":"::", - "server_port":8388, - "local_port":1081, - "password":"aes_password", - "timeout":60, - "method":"aes-256-cfb", - "local_address":"127.0.0.1", - "fast_open":false -} diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/jenkins.sh b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/jenkins.sh deleted file mode 100755 index 65a00004d5..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/jenkins.sh +++ /dev/null @@ -1,82 +0,0 @@ -#!/bin/bash - -result=0 - -function run_test { - printf '\e[0;36m' - echo "running test: $command $@" - printf '\e[0m' - - $command "$@" - status=$? - if [ $status -ne 0 ]; then - printf '\e[0;31m' - echo "test failed: $command $@" - printf '\e[0m' - echo - result=1 - else - printf '\e[0;32m' - echo OK - printf '\e[0m' - echo - fi - return 0 -} - -python3 --version -coverage erase -mkdir tmp -run_test pep8 --ignore=E402 . -run_test pyflakes . -run_test coverage run tests/nose_plugin.py -v -run_test python3 setup.py sdist -run_test tests/test_daemon.sh -run_test python3 tests/test.py --with-coverage -c tests/aes.json -run_test python3 tests/test.py --with-coverage -c tests/aes-ctr.json -run_test python3 tests/test.py --with-coverage -c tests/aes-cfb1.json -run_test python3 tests/test.py --with-coverage -c tests/aes-cfb8.json -run_test python3 tests/test.py --with-coverage -c tests/rc4-md5.json -run_test python3 tests/test.py --with-coverage -c tests/salsa20.json -run_test python3 tests/test.py --with-coverage -c tests/chacha20.json -run_test python3 tests/test.py --with-coverage -c tests/table.json -run_test python3 tests/test.py --with-coverage -c tests/server-multi-ports.json -run_test python3 tests/test.py --with-coverage -s tests/aes.json -c tests/client-multi-server-ip.json -run_test python3 tests/test.py --with-coverage -s tests/server-multi-passwd.json -c tests/server-multi-passwd-client-side.json -run_test python3 tests/test.py --with-coverage -c tests/workers.json -run_test python3 tests/test.py --with-coverage -s tests/ipv6.json -c tests/ipv6-client-side.json -run_test python3 tests/test.py --with-coverage -b "-m rc4-md5 -k testrc4 -s 127.0.0.1 -p 8388 -q" -a "-m rc4-md5 -k testrc4 -s 127.0.0.1 -p 8388 -l 1081 -vv" -run_test python3 tests/test.py --with-coverage -b "-m aes-256-cfb -k testrc4 -s 127.0.0.1 -p 8388 --workers 1" -a "-m aes-256-cfb -k testrc4 -s 127.0.0.1 -p 8388 -l 1081 -t 30 -qq -b 127.0.0.1" -run_test python3 tests/test.py --with-coverage --should-fail --url="http://127.0.0.1/" -b "-m aes-256-cfb -k testrc4 -s 127.0.0.1 -p 8388 --forbidden-ip=127.0.0.1,::1,8.8.8.8" -a "-m aes-256-cfb -k testrc4 -s 127.0.0.1 -p 8388 -l 1081 -t 30 -b 127.0.0.1" - -# test if DNS works -run_test python3 tests/test.py --with-coverage -c tests/aes.json --url="https://clients1.google.com/generate_204" - -# test localhost is in the forbidden list by default -run_test python3 tests/test.py --with-coverage --should-fail --tcp-only --url="http://127.0.0.1/" -b "-m aes-256-cfb -k testrc4 -s 127.0.0.1 -p 8388" -a "-m aes-256-cfb -k testrc4 -s 127.0.0.1 -p 8388 -l 1081 -t 30 -b 127.0.0.1" - -# test localhost is available when forbidden list is empty -run_test python3 tests/test.py --with-coverage --tcp-only --url="http://127.0.0.1/" -b "-m aes-256-cfb -k testrc4 -s 127.0.0.1 -p 8388 --forbidden-ip=" -a "-m aes-256-cfb -k testrc4 -s 127.0.0.1 -p 8388 -l 1081 -t 30 -b 127.0.0.1" - -if [ -f /proc/sys/net/ipv4/tcp_fastopen ] ; then - if [ 3 -eq `cat /proc/sys/net/ipv4/tcp_fastopen` ] ; then - # we have to run it twice: - # the first time there's no syn cookie - # the second time there is syn cookie - run_test python3 tests/test.py --with-coverage -c tests/fastopen.json - run_test python3 tests/test.py --with-coverage -c tests/fastopen.json - fi -fi - -run_test tests/test_large_file.sh -run_test tests/test_udp_src.sh -run_test tests/test_command.sh - -coverage combine && coverage report --include=shadowsocks/* -rm -rf htmlcov -rm -rf tmp -coverage html --include=shadowsocks/* - -coverage report --include=shadowsocks/* | tail -n1 | rev | cut -d' ' -f 1 | rev > /tmp/shadowsocks-coverage - -exit $result diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/libsodium/install.sh b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/libsodium/install.sh deleted file mode 100644 index b0e35fa131..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/libsodium/install.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -if [ ! -d libsodium-1.0.1 ]; then - wget https://github.com/jedisct1/libsodium/releases/download/1.0.1/libsodium-1.0.1.tar.gz || exit 1 - tar xf libsodium-1.0.1.tar.gz || exit 1 -fi -pushd libsodium-1.0.1 -./configure && make -j2 && make install || exit 1 -sudo ldconfig -popd diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/nose_plugin.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/nose_plugin.py deleted file mode 100644 index 3d01ec0e3f..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/nose_plugin.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright 2015 clowwindy -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import nose -from nose.plugins.base import Plugin - - -class ExtensionPlugin(Plugin): - - name = "ExtensionPlugin" - - def options(self, parser, env): - Plugin.options(self, parser, env) - - def configure(self, options, config): - Plugin.configure(self, options, config) - self.enabled = True - - def wantFile(self, file): - return file.endswith('.py') - - def wantDirectory(self, directory): - return True - - def wantModule(self, file): - return True - - -if __name__ == '__main__': - nose.main(addplugins=[ExtensionPlugin()]) diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/rc4-md5.json b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/rc4-md5.json deleted file mode 100644 index e69b433803..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/rc4-md5.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "server":"127.0.0.1", - "server_port":8388, - "local_port":1081, - "password":"aes_password", - "timeout":60, - "method":"rc4-md5", - "local_address":"127.0.0.1", - "fast_open":false -} diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/salsa20-ctr.json b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/salsa20-ctr.json deleted file mode 100644 index 8b77d07806..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/salsa20-ctr.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "server":"127.0.0.1", - "server_port":8388, - "local_port":1081, - "password":"salsa20_password", - "timeout":60, - "method":"salsa20-ctr", - "local_address":"127.0.0.1", - "fast_open":false -} diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/salsa20.json b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/salsa20.json deleted file mode 100644 index a4a664fd76..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/salsa20.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "server":"127.0.0.1", - "server_port":8388, - "local_port":1081, - "password":"salsa20_password", - "timeout":60, - "method":"salsa20", - "local_address":"127.0.0.1", - "fast_open":false -} diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/server-multi-passwd-client-side.json b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/server-multi-passwd-client-side.json deleted file mode 100644 index c822c98b9d..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/server-multi-passwd-client-side.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "server": "127.0.0.1", - "server_port": "8385", - "local_port": 1081, - "password": "foobar5", - "timeout": 60, - "method": "aes-256-cfb" -} diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/server-multi-passwd-table.json b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/server-multi-passwd-table.json deleted file mode 100644 index a2c0a80896..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/server-multi-passwd-table.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "server": "127.0.0.1", - "server_port": 8384, - "local_port": 1081, - "password": "foobar4", - "port_password": { - "8381": "foobar1", - "8382": "foobar2", - "8383": "foobar3", - "8384": "foobar4", - "8385": "foobar5", - "8386": "foobar6", - "8387": "foobar7", - "8388": "foobar8", - "8389": "foobar9" - }, - "timeout": 60, - "method": "table" -} diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/server-multi-passwd.json b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/server-multi-passwd.json deleted file mode 100644 index b1407f0a17..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/server-multi-passwd.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "server": "127.0.0.1", - "local_port": 1081, - "port_password": { - "8381": "foobar1", - "8382": "foobar2", - "8383": "foobar3", - "8384": "foobar4", - "8385": "foobar5", - "8386": "foobar6", - "8387": "foobar7", - "8388": "foobar8", - "8389": "foobar9" - }, - "timeout": 60, - "method": "aes-256-cfb" -} diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/server-multi-ports.json b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/server-multi-ports.json deleted file mode 100644 index 5bdbcab641..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/server-multi-ports.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "server": "127.0.0.1", - "server_port": [8384, 8345, 8346, 8347], - "local_port": 1081, - "password": "foobar4", - "timeout": 60, - "method": "aes-256-cfb" -} diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/setup_tc.sh b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/setup_tc.sh deleted file mode 100755 index 1a5fa208bf..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/setup_tc.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -DEV=lo -PORT=8388 -DELAY=100ms - -type tc 2> /dev/null && ( - tc qdisc add dev $DEV root handle 1: htb - tc class add dev $DEV parent 1: classid 1:1 htb rate 2mbps - tc class add dev $DEV parent 1:1 classid 1:6 htb rate 2mbps ceil 1mbps prio 0 - tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 6 fw flowid 1:6 - - tc filter add dev $DEV parent 1:0 protocol ip u32 match ip dport $PORT 0xffff flowid 1:6 - tc filter add dev $DEV parent 1:0 protocol ip u32 match ip sport $PORT 0xffff flowid 1:6 - - tc qdisc show dev lo -) - diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/socksify/install.sh b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/socksify/install.sh deleted file mode 100644 index 8eff72df08..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/socksify/install.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -if [ ! -d dante-1.4.0 ]; then - wget http://www.inet.no/dante/files/dante-1.4.0.tar.gz || exit 1 - tar xf dante-1.4.0.tar.gz || exit 1 -fi -pushd dante-1.4.0 -./configure && make -j4 && make install || exit 1 -popd -cp tests/socksify/socks.conf /etc/ || exit 1 diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/socksify/socks.conf b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/socksify/socks.conf deleted file mode 100644 index 13db772fd1..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/socksify/socks.conf +++ /dev/null @@ -1,5 +0,0 @@ -route { - from: 0.0.0.0/0 to: 0.0.0.0/0 via: 127.0.0.1 port = 1081 - proxyprotocol: socks_v5 - method: none -} \ No newline at end of file diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/table.json b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/table.json deleted file mode 100644 index 49c2c015d4..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/table.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "server":"127.0.0.1", - "server_port":8388, - "local_port":1081, - "password":"table_password", - "timeout":60, - "method":"table", - "local_address":"127.0.0.1", - "fast_open":false -} diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test.py deleted file mode 100644 index aa2d66ca5f..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test.py +++ /dev/null @@ -1,158 +0,0 @@ -#!/usr/bin/python3 -# -*- coding: utf-8 -*- -# -# Copyright 2015 clowwindy -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import absolute_import, division, print_function, \ - with_statement - -import sys -import os -import signal -import select -import time -import argparse -from subprocess import Popen, PIPE - -python3 = ['python3'] - -default_url = 'http://localhost/' - -parser = argparse.ArgumentParser(description='test Shadowsocks') -parser.add_argument('-c', '--client-conf', type=str, default=None) -parser.add_argument('-s', '--server-conf', type=str, default=None) -parser.add_argument('-a', '--client-args', type=str, default=None) -parser.add_argument('-b', '--server-args', type=str, default=None) -parser.add_argument('--with-coverage', action='store_true', default=None) -parser.add_argument('--should-fail', action='store_true', default=None) -parser.add_argument('--tcp-only', action='store_true', default=None) -parser.add_argument('--url', type=str, default=default_url) -parser.add_argument('--dns', type=str, default='8.8.8.8') - -config = parser.parse_args() - -if config.with_coverage: - python3 = ['coverage', 'run', '-p'] - -client_args = python3 + ['shadowsocks/local.py', '-v'] -server_args = python3 + ['shadowsocks/server.py', '-v'] - -if config.client_conf: - client_args.extend(['-c', config.client_conf]) - if config.server_conf: - server_args.extend(['-c', config.server_conf]) - else: - server_args.extend(['-c', config.client_conf]) -if config.client_args: - client_args.extend(config.client_args.split()) - if config.server_args: - server_args.extend(config.server_args.split()) - else: - server_args.extend(config.client_args.split()) -if config.url == default_url: - server_args.extend(['--forbidden-ip', '']) - -p1 = Popen(server_args, stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True) -p2 = Popen(client_args, stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True) -p3 = None -p4 = None -p3_fin = False -p4_fin = False - -# 1 shadowsocks started -# 2 curl started -# 3 curl finished -# 4 dig started -# 5 dig finished -stage = 1 - -try: - local_ready = False - server_ready = False - fdset = [p1.stdout, p2.stdout, p1.stderr, p2.stderr] - while True: - r, w, e = select.select(fdset, [], fdset) - if e: - break - - for fd in r: - line = fd.readline() - if not line: - if stage == 2 and fd == p3.stdout: - stage = 3 - if stage == 4 and fd == p4.stdout: - stage = 5 - if bytes != str: - line = str(line, 'utf8') - sys.stderr.write(line) - if line.find('starting local') >= 0: - local_ready = True - if line.find('starting server') >= 0: - server_ready = True - - if stage == 1: - time.sleep(2) - - p3 = Popen(['curl', config.url, '-v', '-L', - '--socks5-hostname', '127.0.0.1:1081', - '-m', '15', '--connect-timeout', '10'], - stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True) - if p3 is not None: - fdset.append(p3.stdout) - fdset.append(p3.stderr) - stage = 2 - else: - sys.exit(1) - - if stage == 3 and p3 is not None: - fdset.remove(p3.stdout) - fdset.remove(p3.stderr) - r = p3.wait() - if config.should_fail: - if r == 0: - sys.exit(1) - else: - if r != 0: - sys.exit(1) - if config.tcp_only: - break - p4 = Popen(['socksify', 'dig', '@%s' % config.dns, - 'www.google.com'], - stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True) - if p4 is not None: - fdset.append(p4.stdout) - fdset.append(p4.stderr) - stage = 4 - else: - sys.exit(1) - - if stage == 5: - r = p4.wait() - if config.should_fail: - if r == 0: - sys.exit(1) - print('test passed (expecting failure)') - else: - if r != 0: - sys.exit(1) - print('test passed') - break -finally: - for p in [p1, p2]: - try: - os.kill(p.pid, signal.SIGINT) - os.waitpid(p.pid, 0) - except OSError: - pass diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_command.sh b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_command.sh deleted file mode 100755 index a1a777b0d9..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_command.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash - -. tests/assert.sh - -PYTHON="coverage run -p" -LOCAL="$PYTHON shadowsocks/local.py" -SERVER="$PYTHON shadowsocks/server.py" - -assert "$LOCAL --version 2>&1 | grep Shadowsocks | awk -F\" \" '{print \$1}'" "Shadowsocks" -assert "$SERVER --version 2>&1 | grep Shadowsocks | awk -F\" \" '{print \$1}'" "Shadowsocks" - - -assert "$LOCAL 2>&1 -m rc4-md5 -k testrc4 -s 127.0.0.1 -p 8388 -d start | grep WARNING | awk -F\"WARNING\" '{print \$2}'" " warning: server set to listen on 127.0.0.1:8388, are you sure?" -$LOCAL 2>/dev/null 1>/dev/null -m rc4-md5 -k testrc4 -s 127.0.0.1 -p 8388 -d stop - -assert "$LOCAL 2>&1 -m rc4-md5 -k testrc4 -s 0.0.0.0 -p 8388 -t10 -d start | grep WARNING | awk -F\"WARNING\" '{print \$2}'" " warning: your timeout 10 seems too short" -$LOCAL 2>/dev/null 1>/dev/null -m rc4-md5 -k testrc4 -s 127.0.0.1 -p 8388 -d stop - -assert "$LOCAL 2>&1 -m rc4-md5 -k testrc4 -s 0.0.0.0 -p 8388 -t1000 -d start | grep WARNING | awk -F\"WARNING\" '{print \$2}'" " warning: your timeout 1000 seems too long" -$LOCAL 2>/dev/null 1>/dev/null -m rc4-md5 -k testrc4 -s 127.0.0.1 -p 8388 -d stop - -assert "$LOCAL 2>&1 -m rc4 -k testrc4 -s 0.0.0.0 -p 8388 -d start | grep WARNING | awk -F\"WARNING\" '{print \$2}'" " warning: RC4 is not safe; please use a safer cipher, like AES-256-CFB" -$LOCAL 2>/dev/null 1>/dev/null -m rc4-md5 -k testrc4 -s 127.0.0.1 -p 8388 -d stop - -assert "$LOCAL 2>&1 -m rc4-md5 -k mypassword -s 0.0.0.0 -p 8388 -d start | grep ERROR | awk -F\"ERROR\" '{print \$2}'" " DON'T USE DEFAULT PASSWORD! Please change it in your config.json!" -$LOCAL 2>/dev/null 1>/dev/null -m rc4-md5 -k testrc4 -s 127.0.0.1 -p 8388 -d stop - - -assert "$SERVER 2>&1 --forbidden-ip 127.0.0.1/4a -m rc4-md5 -k 12345 -p 8388 -s 0.0.0.0 -d start | grep ERROR | awk -F\"ERROR\" '{print \$2}'" ": Not a valid CIDR notation: 127.0.0.1/4a" -$LOCAL 2>/dev/null 1>/dev/null -m rc4-md5 -k testrc4 -s 127.0.0.1 -p 8388 -d stop - -assert_end command diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_daemon.sh b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_daemon.sh deleted file mode 100755 index 7a192bdb11..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_daemon.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash - -function run_test { - expected=$1 - shift - echo "running test: $command $@" - $command $@ - status=$? - if [ $status -ne $expected ]; then - echo "exit $status != $expected" - exit 1 - fi - echo "exit status $status == $expected" - echo OK - return -} - -for module in local server -do - -command="coverage run -p shadowsocks/$module.py" - -mkdir -p tmp - -run_test 0 -c tests/aes.json -d stop --pid-file tmp/shadowsocks.pid --log-file tmp/shadowsocks.log - -run_test 0 -c tests/aes.json -d start --pid-file tmp/shadowsocks.pid --log-file tmp/shadowsocks.log -run_test 0 -c tests/aes.json -d stop --pid-file tmp/shadowsocks.pid --log-file tmp/shadowsocks.log - -run_test 0 -c tests/aes.json -d start --pid-file tmp/shadowsocks.pid --log-file tmp/shadowsocks.log -run_test 1 -c tests/aes.json -d start --pid-file tmp/shadowsocks.pid --log-file tmp/shadowsocks.log -run_test 0 -c tests/aes.json -d stop --pid-file tmp/shadowsocks.pid --log-file tmp/shadowsocks.log - -run_test 0 -c tests/aes.json -d start --pid-file tmp/shadowsocks.pid --log-file tmp/shadowsocks.log -run_test 0 -c tests/aes.json -d restart --pid-file tmp/shadowsocks.pid --log-file tmp/shadowsocks.log -run_test 0 -c tests/aes.json -d stop --pid-file tmp/shadowsocks.pid --log-file tmp/shadowsocks.log - -run_test 0 -c tests/aes.json -d restart --pid-file tmp/shadowsocks.pid --log-file tmp/shadowsocks.log -run_test 0 -c tests/aes.json -d stop --pid-file tmp/shadowsocks.pid --log-file tmp/shadowsocks.log - -run_test 1 -c tests/aes.json -d start --pid-file tmp/not_exist/shadowsocks.pid --log-file tmp/shadowsocks.log - -done diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_large_file.sh b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_large_file.sh deleted file mode 100755 index 7a61caff14..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_large_file.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -PYTHON="coverage run -p" -URL=http://127.0.0.1/file - -mkdir -p tmp - -$PYTHON shadowsocks/local.py -c tests/aes.json & -LOCAL=$! - -$PYTHON shadowsocks/server.py -c tests/aes.json --forbidden-ip "" & -SERVER=$! - -sleep 3 - -time curl -o tmp/expected $URL -time curl -o tmp/result --socks5-hostname 127.0.0.1:1081 $URL - -kill -s SIGINT $LOCAL -kill -s SIGINT $SERVER - -sleep 2 - -diff tmp/expected tmp/result || exit 1 diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_udp_src.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_udp_src.py deleted file mode 100644 index e09d7eb249..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_udp_src.py +++ /dev/null @@ -1,83 +0,0 @@ -#!/usr/bin/python3 - -import socket -import socks - - -SERVER_IP = '127.0.0.1' -SERVER_PORT = 1081 - - -if __name__ == '__main__': - # Test 1: same source port IPv4 - sock_out = socks.socksocket(socket.AF_INET, socket.SOCK_DGRAM, - socket.SOL_UDP) - sock_out.set_proxy(socks.SOCKS5, SERVER_IP, SERVER_PORT) - sock_out.bind(('127.0.0.1', 9000)) - - sock_in1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, - socket.SOL_UDP) - sock_in2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, - socket.SOL_UDP) - - sock_in1.bind(('127.0.0.1', 9001)) - sock_in2.bind(('127.0.0.1', 9002)) - - sock_out.sendto(b'data', ('127.0.0.1', 9001)) - result1 = sock_in1.recvfrom(8) - - sock_out.sendto(b'data', ('127.0.0.1', 9002)) - result2 = sock_in2.recvfrom(8) - - sock_out.close() - sock_in1.close() - sock_in2.close() - - # make sure they're from the same source port - assert result1 == result2 - - # Test 2: same source port IPv6 - # try again from the same port but IPv6 - sock_out = socks.socksocket(socket.AF_INET, socket.SOCK_DGRAM, - socket.SOL_UDP) - sock_out.set_proxy(socks.SOCKS5, SERVER_IP, SERVER_PORT) - sock_out.bind(('127.0.0.1', 9000)) - - sock_in1 = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM, - socket.SOL_UDP) - sock_in2 = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM, - socket.SOL_UDP) - - sock_in1.bind(('::1', 9001)) - sock_in2.bind(('::1', 9002)) - - sock_out.sendto(b'data', ('::1', 9001)) - result1 = sock_in1.recvfrom(8) - - sock_out.sendto(b'data', ('::1', 9002)) - result2 = sock_in2.recvfrom(8) - - sock_out.close() - sock_in1.close() - sock_in2.close() - - # make sure they're from the same source port - assert result1 == result2 - - # Test 3: different source ports IPv6 - sock_out = socks.socksocket(socket.AF_INET, socket.SOCK_DGRAM, - socket.SOL_UDP) - sock_out.set_proxy(socks.SOCKS5, SERVER_IP, SERVER_PORT) - sock_out.bind(('127.0.0.1', 9003)) - - sock_in1 = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM, - socket.SOL_UDP) - sock_in1.bind(('::1', 9001)) - sock_out.sendto(b'data', ('::1', 9001)) - result3 = sock_in1.recvfrom(8) - - # make sure they're from different source ports - assert result1 != result3 - - sock_out.close() - sock_in1.close() diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_udp_src.sh b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_udp_src.sh deleted file mode 100755 index 12ec0217c9..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_udp_src.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -PYTHON="coverage run -p" - -mkdir -p tmp - -$PYTHON shadowsocks/local.py -c tests/aes.json -v & -LOCAL=$! - -$PYTHON shadowsocks/server.py -c tests/aes.json --forbidden-ip "" -v & -SERVER=$! - -sleep 3 - -python3 tests/test_udp_src.py -r=$? - -kill -s SIGINT $LOCAL -kill -s SIGINT $SERVER - -sleep 2 - -exit $r diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/workers.json b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/workers.json deleted file mode 100644 index 8e0943b285..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/workers.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "server":"127.0.0.1", - "server_port":8388, - "local_port":1081, - "password":"workers_password", - "timeout":60, - "method":"aes-256-cfb", - "local_address":"127.0.0.1", - "workers": 4 -} diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/user-config.json b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/user-config.json deleted file mode 100644 index e40cb0134c..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/user-config.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "server": "0.0.0.0", - "server_ipv6": "::", - "server_port": 8388, - "local_address": "127.0.0.1", - "local_port": 1080, - - "password": "m", - "method": "aes-128-ctr", - "protocol": "auth_aes128_md5", - "protocol_param": "", - "obfs": "tls1.2_ticket_auth_compatible", - "obfs_param": "", - "speed_limit_per_con": 0, - "speed_limit_per_user": 0, - - "additional_ports" : {}, - "additional_ports_only" : false, - "timeout": 120, - "udp_timeout": 60, - "dns_ipv6": false, - "connect_verbose_info": 0, - "redirect": "", - "fast_open": false -} diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/userapiconfig.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/userapiconfig.py deleted file mode 100644 index b1cba3a478..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/userapiconfig.py +++ /dev/null @@ -1,15 +0,0 @@ -# Config -API_INTERFACE = 'mudbjson' #mudbjson, sspanelv2, sspanelv3, sspanelv3ssr, glzjinmod, legendsockssr, muapiv2(not support) -UPDATE_TIME = 60 -SERVER_PUB_ADDR = '0.0.0.0' # mujson_mgr need this to generate ssr link - -#mudb -MUDB_FILE = '/etc/config/ssr_mudb_server.json' - -# Mysql -MYSQL_CONFIG = 'usermysql.json' - -# API -MUAPI_CONFIG = 'usermuapi.json' - - diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/usermysql.json b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/usermysql.json deleted file mode 100644 index 1849e9e816..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/usermysql.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "host": "127.0.0.1", - "port": 3306, - "user": "ss", - "password": "pass", - "db": "sspanel", - "node_id": 0, - "transfer_mul": 1.0, - "ssl_enable": 0, - "ssl_ca": "", - "ssl_cert": "", - "ssl_key": "" -} diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/utils/README.md b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/utils/README.md deleted file mode 100644 index f624309c72..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/utils/README.md +++ /dev/null @@ -1,9 +0,0 @@ -Useful Tools -=========== - -autoban.py ----------- - -Automatically ban IPs that try to brute force crack the server. - -See https://github.com/shadowsocks/shadowsocks/wiki/Ban-Brute-Force-Crackers diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/utils/autoban.py b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/utils/autoban.py deleted file mode 100644 index 148a00bd9f..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/utils/autoban.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/python3 -# -*- coding: utf-8 -*- - -# Copyright (c) 2015 clowwindy -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -from __future__ import absolute_import, division, print_function, \ - with_statement - -import os -import sys -import argparse - -if __name__ == '__main__': - parser = argparse.ArgumentParser(description='See README') - parser.add_argument('-c', '--count', default=3, type=int, - help='with how many failure times it should be ' - 'considered as an attack') - config = parser.parse_args() - ips = {} - banned = set() - for line in sys.stdin: - if 'can not parse header when' in line: - ip = line.split()[-1].split(':')[0] - if ip not in ips: - ips[ip] = 1 - print(ip) - sys.stdout.flush() - else: - ips[ip] += 1 - if ip not in banned and ips[ip] >= config.count: - banned.add(ip) - cmd = 'iptables -A INPUT -s %s -j DROP' % ip - print(cmd, file=sys.stderr) - sys.stderr.flush() - os.system(cmd) diff --git a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/utils/fail2ban/shadowsocks.conf b/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/utils/fail2ban/shadowsocks.conf deleted file mode 100644 index 9b1c7ec7aa..0000000000 --- a/package/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/utils/fail2ban/shadowsocks.conf +++ /dev/null @@ -1,5 +0,0 @@ -[Definition] - -_daemon = shadowsocks - -failregex = ^\s+ERROR\s+can not parse header when handling connection from :\d+$ diff --git a/package/lienol/luci-app-timecontrol/Makefile b/package/lienol/luci-app-timecontrol/Makefile deleted file mode 100644 index fe312a6a65..0000000000 --- a/package/lienol/luci-app-timecontrol/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright (C) 2020 Lienol -# -# This is free software, licensed under the GNU General Public License v3. -# - -include $(TOPDIR)/rules.mk - -LUCI_TITLE:=LuCI support for Time Control -LUCI_PKGARCH:=all -PKG_VERSION:=1.0 -PKG_RELEASE:=1-20200402 - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature diff --git a/package/lienol/luci-app-timecontrol/luasrc/controller/timecontrol.lua b/package/lienol/luci-app-timecontrol/luasrc/controller/timecontrol.lua deleted file mode 100644 index 161d51b60d..0000000000 --- a/package/lienol/luci-app-timecontrol/luasrc/controller/timecontrol.lua +++ /dev/null @@ -1,17 +0,0 @@ -module("luci.controller.timecontrol", package.seeall) - -function index() - if not nixio.fs.access("/etc/config/timecontrol") then return end - - entry({"admin", "control"}, firstchild(), "Control", 44).dependent = false - entry({"admin", "control", "timecontrol"}, cbi("timecontrol"), _("Internet Time Control"), 10).dependent = - true - entry({"admin", "control", "timecontrol", "status"}, call("status")).leaf = true -end - -function status() - local e = {} - e.status = luci.sys.call("iptables -L FORWARD | grep TIMECONTROL >/dev/null") == 0 - luci.http.prepare_content("application/json") - luci.http.write_json(e) -end diff --git a/package/lienol/luci-app-timecontrol/luasrc/model/cbi/timecontrol.lua b/package/lienol/luci-app-timecontrol/luasrc/model/cbi/timecontrol.lua deleted file mode 100644 index 9b127212c5..0000000000 --- a/package/lienol/luci-app-timecontrol/luasrc/model/cbi/timecontrol.lua +++ /dev/null @@ -1,57 +0,0 @@ -local o = require "luci.sys" -local a, t, e -a = Map("timecontrol", translate("Internet Time Control")) -a.template = "timecontrol/index" - -t = a:section(TypedSection, "basic") -t.anonymous = true - -e = t:option(DummyValue, "timecontrol_status", translate("Status")) -e.template = "timecontrol/timecontrol" -e.value = translate("Collecting data...") - -e = t:option(Flag, "enable", translate("Enabled")) -e.rmempty = false - -t = a:section(TypedSection, "macbind", translate("Client Settings")) -t.template = "cbi/tblsection" -t.anonymous = true -t.addremove = true - -e = t:option(Flag, "enable", translate("Enabled")) -e.rmempty = false - -e = t:option(Value, "macaddr", "MAC") -e.rmempty = true -o.net.mac_hints(function(t, a) e:value(t, "%s (%s)" % {t, a}) end) - -e = t:option(Value, "timeon", translate("No Internet start time")) -e.default = "00:00" -e.optional = false - -e = t:option(Value, "timeoff", translate("No Internet end time")) -e.default = "23:59" -e.optional = false - -e = t:option(Flag, "z1", translate("Monday")) -e.rmempty = true - -e = t:option(Flag, "z2", translate("Tuesday")) -e.rmempty = true - -e = t:option(Flag, "z3", translate("Wednesday")) -e.rmempty = true - -e = t:option(Flag, "z4", translate("Thursday")) -e.rmempty = true - -e = t:option(Flag, "z5", translate("Friday")) -e.rmempty = true - -e = t:option(Flag, "z6", translate("Saturday")) -e.rmempty = true - -e = t:option(Flag, "z7", translate("Sunday")) -e.rmempty = true - -return a diff --git a/package/lienol/luci-app-timecontrol/luasrc/view/timecontrol/index.htm b/package/lienol/luci-app-timecontrol/luasrc/view/timecontrol/index.htm deleted file mode 100644 index 3ff7a8452a..0000000000 --- a/package/lienol/luci-app-timecontrol/luasrc/view/timecontrol/index.htm +++ /dev/null @@ -1,12 +0,0 @@ -<% include("cbi/map") %> - \ No newline at end of file diff --git a/package/lienol/luci-app-timecontrol/luasrc/view/timecontrol/timecontrol.htm b/package/lienol/luci-app-timecontrol/luasrc/view/timecontrol/timecontrol.htm deleted file mode 100644 index e4d63fb5a5..0000000000 --- a/package/lienol/luci-app-timecontrol/luasrc/view/timecontrol/timecontrol.htm +++ /dev/null @@ -1,3 +0,0 @@ -<%+cbi/valueheader%> -<%=pcdata(self:cfgvalue(section) or self.default or "")%> -<%+cbi/valuefooter%> \ No newline at end of file diff --git a/package/lienol/luci-app-timecontrol/po/zh-cn/timecontrol.po b/package/lienol/luci-app-timecontrol/po/zh-cn/timecontrol.po deleted file mode 100644 index fc68f62021..0000000000 --- a/package/lienol/luci-app-timecontrol/po/zh-cn/timecontrol.po +++ /dev/null @@ -1,41 +0,0 @@ -msgid "Control" -msgstr "管控" - -msgid "Internet Time Control" -msgstr "上网时间控制" - -msgid "Status" -msgstr "状态" - -msgid "Enabled" -msgstr "启用" - -msgid "Client Settings" -msgstr "客户端设置" - -msgid "No Internet start time" -msgstr "禁止上网开始时间" - -msgid "No Internet end time" -msgstr "取消禁止上网时间" - -msgid "Monday" -msgstr "周一" - -msgid "Tuesday" -msgstr "周二" - -msgid "Wednesday" -msgstr "周三" - -msgid "Thursday" -msgstr "周四" - -msgid "Friday" -msgstr "周五" - -msgid "Saturday" -msgstr "周六" - -msgid "Sunday" -msgstr "周日" diff --git a/package/lienol/luci-app-timecontrol/root/etc/config/timecontrol b/package/lienol/luci-app-timecontrol/root/etc/config/timecontrol deleted file mode 100644 index 0c4c4f6bcd..0000000000 --- a/package/lienol/luci-app-timecontrol/root/etc/config/timecontrol +++ /dev/null @@ -1,3 +0,0 @@ - -config basic - option enable '0' diff --git a/package/lienol/luci-app-timecontrol/root/etc/init.d/timecontrol b/package/lienol/luci-app-timecontrol/root/etc/init.d/timecontrol deleted file mode 100755 index 17300b8f8e..0000000000 --- a/package/lienol/luci-app-timecontrol/root/etc/init.d/timecontrol +++ /dev/null @@ -1,80 +0,0 @@ -#!/bin/sh /etc/rc.common - -START=99 -CONFIG=timecontrol - -uci_get_by_type() { - local index=0 - [ -n $4 ] && index=$4 - local ret=$(uci -q get $CONFIG.@$1[$index].$2 2>/dev/null) - echo ${ret:=$3} -} - -add_rule(){ - local count=$(uci show $CONFIG | grep "@macbind" | sed -n '$p' | cut -d '[' -f 2 | cut -d ']' -f 1) - [ -n "$count" ] && [ "$count" -ge 0 ] && { - u_get() { - local ret=$(uci -q get $CONFIG.@macbind[$1].$2) - echo ${ret:=$3} - } - for i in $(seq 0 $count); do - local enable=$(u_get $i enable 0) - local macaddr=$(u_get $i macaddr) - local timeoff=$(u_get $i timeoff) - local timeon=$(u_get $i timeon) - local z1=$(u_get $i z1) - local z2=$(u_get $i z2) - local z3=$(u_get $i z3) - local z4=$(u_get $i z4) - local z5=$(u_get $i z5) - local z6=$(u_get $i z6) - local z7=$(u_get $i z7) - [ "$z1" == "1" ] && local Z1="Mon," - [ "$z2" == "1" ] && local Z2="Tue," - [ "$z3" == "1" ] && local Z3="Wed," - [ "$z4" == "1" ] && local Z4="Thu," - [ "$z5" == "1" ] && local Z5="Fri," - [ "$z6" == "1" ] && local Z6="Sat," - [ "$z7" == "1" ] && local Z7="Sun" - if [ -z $enable ] || [ -z $macaddr ] || [ -z $timeoff ] || [ -z $timeon ]; then - continue - fi - if [ "$enable" == "1" ]; then - iptables -t filter -I TIMECONTROL -m mac --mac-source $macaddr -m time --kerneltz --timestart $timeon --timestop $timeoff --weekdays $Z1$Z2$Z3$Z4$Z5$Z6$Z7 -j DROP - iptables -t nat -I PREROUTING 1 -m mac --mac-source $macaddr -m time --kerneltz --timestart $timeon --timestop $timeoff --weekdays $Z1$Z2$Z3$Z4$Z5$Z6$Z7 -m comment --comment "TIMECONTROL" -j RETURN - fi - done - } - echo "/etc/init.d/timecontrol restart" > "/var/etc/timecontrol.include" -} - -del_rule(){ - nums=$(iptables -t nat -n -L PREROUTING 2>/dev/null | grep -c "TIMECONTROL") - if [ -n "$nums" ]; then - until [ "$nums" = 0 ] - do - rules=$(iptables -t nat -n -L PREROUTING --line-num 2>/dev/null | grep "TIMECONTROL" | awk '{print $1}') - for rule in $rules - do - iptables -t nat -D PREROUTING $rule 2>/dev/null - break - done - nums=$(expr $nums - 1) - done - fi -} - -start(){ - ENABLED=$(uci_get_by_type basic enable 0) - [ "$ENABLED" != "1" ] && exit 0 - iptables -t filter -N TIMECONTROL - iptables -t filter -I FORWARD -j TIMECONTROL - add_rule -} - -stop(){ - iptables -t filter -D FORWARD -j TIMECONTROL 2>/dev/null - iptables -t filter -F TIMECONTROL 2>/dev/null - iptables -t filter -X TIMECONTROL 2>/dev/null - del_rule -} diff --git a/package/lienol/luci-app-timecontrol/root/etc/uci-defaults/luci-app-timecontrol b/package/lienol/luci-app-timecontrol/root/etc/uci-defaults/luci-app-timecontrol deleted file mode 100755 index c3fd6db944..0000000000 --- a/package/lienol/luci-app-timecontrol/root/etc/uci-defaults/luci-app-timecontrol +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete firewall.timecontrol - set firewall.timecontrol=include - set firewall.timecontrol.type=script - set firewall.timecontrol.path=/var/etc/timecontrol.include - set firewall.timecontrol.reload=1 -EOF - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@timecontrol[-1] - add ucitrack timecontrol - set ucitrack.@timecontrol[-1].init=timecontrol - commit ucitrack -EOF - -rm -rf /tmp/luci-*cache -exit 0 diff --git a/package/lienol/luci-app-timewol/Makefile b/package/lienol/luci-app-timewol/Makefile deleted file mode 100644 index 3de8bdaf90..0000000000 --- a/package/lienol/luci-app-timewol/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (C) 2016 Openwrt.org -# -# This is free software, licensed under the Apache License, Version 2.0 . -# - -include $(TOPDIR)/rules.mk - -LUCI_TITLE:=LuCI support for Timewol -LUCI_PKGARCH:=all -PKG_VERSION:=1.0 -PKG_RELEASE:=3-20190309 - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature - - diff --git a/package/lienol/luci-app-timewol/luasrc/controller/timewol.lua b/package/lienol/luci-app-timewol/luasrc/controller/timewol.lua deleted file mode 100644 index 67a18fd972..0000000000 --- a/package/lienol/luci-app-timewol/luasrc/controller/timewol.lua +++ /dev/null @@ -1,16 +0,0 @@ -module("luci.controller.timewol", package.seeall) - -function index() - if not nixio.fs.access("/etc/config/timewol") then return end - - entry({"admin", "control"}, firstchild(), "Control", 44).dependent = false - entry({"admin", "control", "timewol"}, cbi("timewol"), _("定时唤醒"), 95).dependent = true - entry({"admin", "control", "timewol", "status"}, call("status")).leaf = true -end - -function status() - local e = {} - e.status = luci.sys.call("cat /etc/crontabs/root |grep etherwake >/dev/null") == 0 - luci.http.prepare_content("application/json") - luci.http.write_json(e) -end diff --git a/package/lienol/luci-app-timewol/luasrc/model/cbi/timewol.lua b/package/lienol/luci-app-timewol/luasrc/model/cbi/timewol.lua deleted file mode 100644 index 54b2c010a2..0000000000 --- a/package/lienol/luci-app-timewol/luasrc/model/cbi/timewol.lua +++ /dev/null @@ -1,37 +0,0 @@ -local i = require "luci.sys" -local t, e, o -t = Map("timewol", translate("定时网络唤醒"), - translate("定时唤醒你的局域网设备")) -t.template = "timewol/index" -e = t:section(TypedSection, "basic", translate("Running Status")) -e.anonymous = true -o = e:option(DummyValue, "timewol_status", translate("当前状态")) -o.template = "timewol/timewol" -o.value = translate("Collecting data...") -e = t:section(TypedSection, "basic", translate("基本设置")) -e.anonymous = true -o = e:option(Flag, "enable", translate("开启")) -o.rmempty = false -e = t:section(TypedSection, "macclient", translate("客户端设置")) -e.template = "cbi/tblsection" -e.anonymous = true -e.addremove = true -nolimit_mac = e:option(Value, "macaddr", translate("客户端MAC")) -nolimit_mac.rmempty = false -i.net.mac_hints(function(e, t) nolimit_mac:value(e, "%s (%s)" % {e, t}) end) -nolimit_eth = e:option(Value, "maceth", translate("网络接口")) -nolimit_eth.rmempty = false -for t, e in ipairs(i.net.devices()) do if e ~= "lo" then nolimit_eth:value(e) end end -a = e:option(Value, "minute", translate("分钟")) -a.optional = false -a = e:option(Value, "hour", translate("小时")) -a.optional = false -a = e:option(Value, "day", translate("日")) -a.optional = false -a = e:option(Value, "month", translate("月")) -a.optional = false -a = e:option(Value, "weeks", translate("星期")) -a.optional = false -local e = luci.http.formvalue("cbi.apply") -if e then io.popen("/etc/init.d/timewol restart") end -return t diff --git a/package/lienol/luci-app-timewol/luasrc/view/timewol/index.htm b/package/lienol/luci-app-timewol/luasrc/view/timewol/index.htm deleted file mode 100644 index d11dc15823..0000000000 --- a/package/lienol/luci-app-timewol/luasrc/view/timewol/index.htm +++ /dev/null @@ -1,18 +0,0 @@ -<%# - Copyright 2016 Chen RuiWei - Licensed to the public under the Apache License 2.0. --%> - -<% include("cbi/map") %> - diff --git a/package/lienol/luci-app-timewol/luasrc/view/timewol/timewol.htm b/package/lienol/luci-app-timewol/luasrc/view/timewol/timewol.htm deleted file mode 100644 index 57e0aa4f98..0000000000 --- a/package/lienol/luci-app-timewol/luasrc/view/timewol/timewol.htm +++ /dev/null @@ -1,3 +0,0 @@ -<%+cbi/valueheader%> -<%=pcdata(self:cfgvalue(section) or self.default or "")%> -<%+cbi/valuefooter%> diff --git a/package/lienol/luci-app-timewol/po/zh-cn/timewol.po b/package/lienol/luci-app-timewol/po/zh-cn/timewol.po deleted file mode 100644 index a883cf73ab..0000000000 --- a/package/lienol/luci-app-timewol/po/zh-cn/timewol.po +++ /dev/null @@ -1,2 +0,0 @@ -msgid "Control" -msgstr "管控" diff --git a/package/lienol/luci-app-timewol/root/etc/config/timewol b/package/lienol/luci-app-timewol/root/etc/config/timewol deleted file mode 100644 index 0c4c4f6bcd..0000000000 --- a/package/lienol/luci-app-timewol/root/etc/config/timewol +++ /dev/null @@ -1,3 +0,0 @@ - -config basic - option enable '0' diff --git a/package/lienol/luci-app-timewol/root/etc/init.d/timewol b/package/lienol/luci-app-timewol/root/etc/init.d/timewol deleted file mode 100755 index 362c739574..0000000000 --- a/package/lienol/luci-app-timewol/root/etc/init.d/timewol +++ /dev/null @@ -1,74 +0,0 @@ -#!/bin/sh /etc/rc.common -# -# Copyright (C) 2015 OpenWrt-dist -# Copyright (C) 2016 fw867 -# -# This is free software, licensed under the GNU General Public License v3. -# See /LICENSE for more information. -# - -START=99 - -CONFIG=timewol - -uci_get_by_type() { - local index=0 - if [ -n $4 ]; then - index=$4 - fi - local ret=$(uci get $CONFIG.@$1[$index].$2 2>/dev/null) - echo ${ret:=$3} -} - -is_true() { - case $1 in - 1|on|true|yes|enabled) echo 0;; - *) echo 1;; - esac -} - -load_config() { - ENABLED=$(uci_get_by_type basic enable) - return $(is_true $ENABLED) -} - -add_rule(){ -sed -i '/etherwake/d' /etc/crontabs/root >/dev/null 2>&1 -for i in $(seq 0 100) - do - local macaddr=$(uci_get_by_type macclient macaddr '' $i) - local maceth=$(uci_get_by_type macclient maceth '' $i) - local minute=$(uci_get_by_type macclient minute '' $i) - local hour=$(uci_get_by_type macclient hour '' $i) - local day=$(uci_get_by_type macclient day '' $i) - local month=$(uci_get_by_type macclient month '' $i) - local weeks=$(uci_get_by_type macclient weeks '' $i) - if [ -z $macaddr ] || [ -z $maceth ]; then - break - fi - if [ -z $minute ] ; then - minute="0" - fi - if [ -z $hour ] ; then - hour="*" - fi - if [ -z $day ] ; then - day="*" - fi - if [ -z $month ] ; then - month="*" - fi - if [ -z $weeks ] ; then - weeks="*" - fi - echo "$minute $hour $day $month $weeks /usr/bin/etherwake -D -i $maceth $macaddr" >> /etc/crontabs/root -done -} - -start() { - ! load_config && exit 0 - add_rule -} -stop() { - sed -i '/etherwake/d' /etc/crontabs/root >/dev/null 2>&1 -} diff --git a/package/lienol/luci-app-timewol/root/etc/uci-defaults/luci-app-control-timewol b/package/lienol/luci-app-timewol/root/etc/uci-defaults/luci-app-control-timewol deleted file mode 100755 index 32595e12f0..0000000000 --- a/package/lienol/luci-app-timewol/root/etc/uci-defaults/luci-app-control-timewol +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@timewol[-1] - add ucitrack timewol - set ucitrack.@timewol[-1].init=timewol - commit ucitrack -EOF - -rm -f /tmp/luci-indexcache -exit 0 diff --git a/package/lienol/luci-app-trojan-server/Makefile b/package/lienol/luci-app-trojan-server/Makefile deleted file mode 100644 index 4a37de5257..0000000000 --- a/package/lienol/luci-app-trojan-server/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (C) 2019-2020 Lienol -# -# This is free software, licensed under the GNU General Public License v3. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=luci-app-trojan-server -LUCI_TITLE:=LuCI support for Trojan Server -LUCI_DEPENDS:=+luci-lib-jsonc +trojan -LUCI_PKGARCH:=all -PKG_VERSION:=1 -PKG_RELEASE:=3-20200326 - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature \ No newline at end of file diff --git a/package/lienol/luci-app-trojan-server/luasrc/controller/trojan_server.lua b/package/lienol/luci-app-trojan-server/luasrc/controller/trojan_server.lua deleted file mode 100644 index 48de9cd5ac..0000000000 --- a/package/lienol/luci-app-trojan-server/luasrc/controller/trojan_server.lua +++ /dev/null @@ -1,41 +0,0 @@ --- Copyright 2019 Lienol -module("luci.controller.trojan_server", package.seeall) -local http = require "luci.http" - -function index() - if not nixio.fs.access("/etc/config/trojan_server") then return end - entry({"admin", "vpn"}, firstchild(), "VPN", 45).dependent = false - entry({"admin", "vpn", "trojan_server"}, cbi("trojan_server/index"), - _("Trojan Server"), 3).dependent = true - entry({"admin", "vpn", "trojan_server", "config"}, - cbi("trojan_server/config")).leaf = true - - entry({"admin", "vpn", "trojan_server", "users_status"}, - call("trojan_users_status")).leaf = true - entry({"admin", "vpn", "trojan_server", "get_log"}, call("get_log")).leaf = - true - entry({"admin", "vpn", "trojan_server", "clear_log"}, call("clear_log")).leaf = - true -end - -local function http_write_json(content) - http.prepare_content("application/json") - http.write_json(content or {code = 1}) -end - -function trojan_users_status() - local e = {} - e.index = luci.http.formvalue("index") - e.status = luci.sys.call( - "ps -w| grep -v grep | grep '/var/etc/trojan_server/" .. - luci.http.formvalue("id") .. "' >/dev/null") == 0 - http_write_json(e) -end - -function get_log() - luci.http.write(luci.sys.exec( - "[ -f '/var/log/trojan_server/app.log' ] && cat /var/log/trojan_server/app.log")) -end - -function clear_log() luci.sys.call("echo '' > /var/log/trojan_server/app.log") end - diff --git a/package/lienol/luci-app-trojan-server/luasrc/model/cbi/trojan_server/api/gen_trojan_config_file.lua b/package/lienol/luci-app-trojan-server/luasrc/model/cbi/trojan_server/api/gen_trojan_config_file.lua deleted file mode 100644 index e4811085e1..0000000000 --- a/package/lienol/luci-app-trojan-server/luasrc/model/cbi/trojan_server/api/gen_trojan_config_file.lua +++ /dev/null @@ -1,40 +0,0 @@ -local ucursor = require"luci.model.uci".cursor() -local json = require "luci.jsonc" -local server_section = arg[1] -local server = ucursor:get_all("trojan_server", server_section) - -local trojan = { - run_type = "server", - local_addr = "0.0.0.0", - local_port = tonumber(server.port), - remote_addr = (server.remote_enable == "1" and server.remote_address) and - server.remote_address or nil, - remote_port = (server.remote_enable == "1" and server.remote_port) and - server.remote_port or nil, - password = server.password, - log_level = 1, - ssl = { - cert = server.ssl_certFile, - key = server.ssl_keyFile, - key_password = "", - cipher = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:AES128-SHA:AES256-SHA:DES-CBC3-SHA", - cipher_tls13 = "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384", - prefer_server_cipher = true, - alpn = {"http/1.1"}, - reuse_session = true, - session_ticket = false, - session_timeout = 600, - plain_http_response = "", - curves = "", - dhparam = "" - }, - tcp = { - prefer_ipv4 = false, - no_delay = true, - keep_alive = true, - reuse_port = false, - fast_open = (server.fast_open == "true") and true or false, - fast_open_qlen = 20 - } -} -print(json.stringify(trojan, 1)) diff --git a/package/lienol/luci-app-trojan-server/luasrc/model/cbi/trojan_server/config.lua b/package/lienol/luci-app-trojan-server/luasrc/model/cbi/trojan_server/config.lua deleted file mode 100644 index 060ce52d1e..0000000000 --- a/package/lienol/luci-app-trojan-server/luasrc/model/cbi/trojan_server/config.lua +++ /dev/null @@ -1,54 +0,0 @@ -local app_name = "trojan_server" -local d = require "luci.dispatcher" - -map = Map(app_name, "Trojan " .. translate("Server Config")) -map.redirect = d.build_url("admin", "vpn", "trojan_server") - -t = map:section(NamedSection, arg[1], "user", "") -t.addremove = false -t.dynamic = false - -enable = t:option(Flag, "enable", translate("Enable")) -enable.default = "1" -enable.rmempty = false - -remarks = t:option(Value, "remarks", translate("Remarks")) -remarks.default = translate("Remarks") -remarks.rmempty = false - -port = t:option(Value, "port", translate("Port")) -port.datatype = "port" -port.rmempty = false - -password = t:option(DynamicList, "password", translate("Password")) - -tcp_fast_open = t:option(ListValue, "tcp_fast_open", translate("TCP Fast Open"), - translate( - "Enable TCP fast open (kernel support required)")) -tcp_fast_open:value("false") -tcp_fast_open:value("true") - -remote_enable = t:option(Flag, "remote_enable", translate("Enable Remote"), - translate( - "You can forward to Nginx/Caddy/V2ray WebSocket and more.")) -remote_enable.default = "1" -remote_enable.rmempty = false - -remote_address = t:option(Value, "remote_address", translate("Remote Address")) -remote_address.default = "127.0.0.1" -remote_address:depends("remote_enable", 1) - -remote_port = t:option(Value, "remote_port", translate("Remote Port")) -remote_port.datatype = "port" -remote_port.default = "80" -remote_port:depends("remote_enable", 1) - -tls_certFile = t:option(Value, "ssl_certFile", - "HTTPS" .. translate("Public key absolute path"), - translate("as:") .. "/etc/ssl/fullchain.pem") - -tls_keyFile = t:option(Value, "ssl_keyFile", - "HTTPS" .. translate("Private key absolute path"), - translate("as:") .. "/etc/ssl/private.key") - -return map diff --git a/package/lienol/luci-app-trojan-server/luasrc/model/cbi/trojan_server/index.lua b/package/lienol/luci-app-trojan-server/luasrc/model/cbi/trojan_server/index.lua deleted file mode 100644 index a6348a786a..0000000000 --- a/package/lienol/luci-app-trojan-server/luasrc/model/cbi/trojan_server/index.lua +++ /dev/null @@ -1,58 +0,0 @@ -local i = require "luci.dispatcher" -local e = require "nixio.fs" -local e = require "luci.sys" -local e = luci.model.uci.cursor() -local o = "trojan_server" - -m = Map(o, translate("Trojan Server")) - -t = m:section(TypedSection, "global", translate("Global Settings")) -t.anonymous = true -t.addremove = false -e = t:option(Flag, "enable", translate("Enable")) -e.rmempty = false - -t = m:section(TypedSection, "user", translate("Users Manager")) -t.anonymous = true -t.addremove = true -t.template = "cbi/tblsection" -t.extedit = i.build_url("admin", "vpn", o, "config", "%s") -function t.create(t, e) - local e = TypedSection.create(t, e) - luci.http.redirect(i.build_url("admin", "vpn", o, "config", e)) -end -function t.remove(t, a) - t.map.proceed = true - t.map:del(a) - luci.http.redirect(i.build_url("admin", "vpn", o)) -end -e = t:option(Flag, "enable", translate("Enable")) -e.width = "5%" -e.rmempty = false -e = t:option(DummyValue, "status", translate("Status")) -e.template = "trojan_server/users_status" -e.value = translate("Collecting data...") -e = t:option(DummyValue, "remarks", translate("Remarks")) -e.width = "20%" -e = t:option(DummyValue, "port", translate("Port")) -e.width = "20%" - -e = t:option(DummyValue, "password", translate("Password")) -e.width = "30%" -e.cfgvalue = function(self, section) - local e = m:get(section, "password") or "" - local t = "" - if type(e) == "table" then - for a = 1, #e do t = t .. e[a] .. "," end - t = string.sub(t, 0, #t - 1) - else - t = e - end - return t -end - -m:append(Template("trojan_server/log")) - -m:append(Template("trojan_server/users_list_status")) -return m - diff --git a/package/lienol/luci-app-trojan-server/luasrc/view/trojan_server/log.htm b/package/lienol/luci-app-trojan-server/luasrc/view/trojan_server/log.htm deleted file mode 100644 index d1f752205e..0000000000 --- a/package/lienol/luci-app-trojan-server/luasrc/view/trojan_server/log.htm +++ /dev/null @@ -1,31 +0,0 @@ - -
- - <%:Logs%> - - - -
\ No newline at end of file diff --git a/package/lienol/luci-app-trojan-server/luasrc/view/trojan_server/users_list_status.htm b/package/lienol/luci-app-trojan-server/luasrc/view/trojan_server/users_list_status.htm deleted file mode 100644 index 7b9009b515..0000000000 --- a/package/lienol/luci-app-trojan-server/luasrc/view/trojan_server/users_list_status.htm +++ /dev/null @@ -1,23 +0,0 @@ -<% -local dsp = require "luci.dispatcher" --%> - - \ No newline at end of file diff --git a/package/lienol/luci-app-trojan-server/luasrc/view/trojan_server/users_status.htm b/package/lienol/luci-app-trojan-server/luasrc/view/trojan_server/users_status.htm deleted file mode 100644 index 73baddc1f6..0000000000 --- a/package/lienol/luci-app-trojan-server/luasrc/view/trojan_server/users_status.htm +++ /dev/null @@ -1,3 +0,0 @@ -<%+cbi/valueheader%> --- -<%+cbi/valuefooter%> \ No newline at end of file diff --git a/package/lienol/luci-app-trojan-server/po/zh-cn/trojan_server.po b/package/lienol/luci-app-trojan-server/po/zh-cn/trojan_server.po deleted file mode 100644 index 2111c944e8..0000000000 --- a/package/lienol/luci-app-trojan-server/po/zh-cn/trojan_server.po +++ /dev/null @@ -1,68 +0,0 @@ -msgid "Trojan Server" -msgstr "Trojan 服务器" - -msgid "Global Settings" -msgstr "全局设置" - -msgid "Server Config" -msgstr "服务器配置" - -msgid "Users Manager" -msgstr "用户管理" - -msgid "Remarks" -msgstr "备注" - -msgid "Port" -msgstr "端口" - -msgid "Password" -msgstr "密码" - -msgid "TCP Fast Open" -msgstr "TCP快速打开" - -msgid "Enable TCP fast open (kernel support required)" -msgstr "是否启用TCP快速打开(需要内核支持)" - -msgid "Enable Remote" -msgstr "启用转发" - -msgid "You can forward to Nginx/Caddy/V2ray WebSocket and more." -msgstr "您可以转发到Nginx/Caddy/V2ray WebSocket等。" - -msgid "Remote Address" -msgstr "远程地址" - -msgid "Remote Port" -msgstr "远程端口" - -msgid "as:" -msgstr "如:" - -msgid "Public key absolute path" -msgstr "公钥文件绝对路径" - -msgid "Private key absolute path" -msgstr "私钥文件绝对路径" - -msgid "Logs" -msgstr "日志" - -msgid "Clear logs" -msgstr "清空日志" - -msgid "Enabled" -msgstr "启用" - -msgid "Status" -msgstr "状态" - -msgid "Current Condition" -msgstr "当前状态" - -msgid "NOT RUNNING" -msgstr "未运行" - -msgid "RUNNING" -msgstr "运行中" \ No newline at end of file diff --git a/package/lienol/luci-app-trojan-server/root/etc/config/trojan_server b/package/lienol/luci-app-trojan-server/root/etc/config/trojan_server deleted file mode 100644 index cff3b91617..0000000000 --- a/package/lienol/luci-app-trojan-server/root/etc/config/trojan_server +++ /dev/null @@ -1,13 +0,0 @@ - -config global - option enable '0' - -config user - option enable '1' - option remarks '测试' - option port '45443' - option tcp_fast_open 'false' - option ssl_certFile '/etc/config/ssl/fullchain.pem' - option ssl_keyFile '/etc/config/ssl/private.key' - list password '123456' - diff --git a/package/lienol/luci-app-trojan-server/root/etc/init.d/trojan_server b/package/lienol/luci-app-trojan-server/root/etc/init.d/trojan_server deleted file mode 100755 index fb2bf361e9..0000000000 --- a/package/lienol/luci-app-trojan-server/root/etc/init.d/trojan_server +++ /dev/null @@ -1,60 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2019-2020 Lienol - -START=99 - -CONFIG=trojan_server -CONFIG_PATH=/var/etc/$CONFIG -LOG_PATH=/var/log/$CONFIG -LOG_APP_FILE=$LOG_PATH/app.log - -echolog() { - echo -e "$(date "+%Y-%m-%d %H:%M:%S"): $1" >> $LOG_APP_FILE -} - -gen_trojan_config_file() { - config_get enable $1 enable - [ "$enable" = "0" ] && return 0 - config_get remarks $1 remarks - config_get port $1 port - config_get ssl_certFile $1 ssl_certFile - config_get ssl_keyFile $1 ssl_keyFile - [ ! -f "$ssl_certFile" ] && echolog "$remarks $port 找不到HTTPS公钥文件,运行失败!" && exit - [ ! -f "$ssl_keyFile" ] && echolog "$remarks $port 找不到HTTPS私钥文件,运行失败!" && exit - lua /usr/lib/lua/luci/model/cbi/trojan_server/api/gen_trojan_config_file.lua $1 > $CONFIG_PATH/$1.json - echolog "$remarks $port 生成并运行 Trojan 配置文件 - $CONFIG_PATH/$1.json" - trojan -c $CONFIG_PATH/$1.json >/dev/null 2>&1 & -} - -start_trojan_server() { - mkdir -p $CONFIG_PATH $LOG_PATH - touch $LOG_APP_FILE - config_foreach gen_trojan_config_file "user" - fw3 reload >/dev/null 2>&1 & -} - -stop_trojan_server() { - fw3 reload >/dev/null 2>&1 - ps -w | grep "$CONFIG_PATH/" | grep -v "grep" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 & - rm -rf $CONFIG_PATH - rm -rf $LOG_PATH -} - -start() { - config_load $CONFIG - enable=$(uci get $CONFIG.@global[0].enable) - if [ "$enable" = "0" ];then - stop_trojan_server - else - start_trojan_server - fi -} - -stop() { - stop_trojan_server -} - -restart() { - stop - start -} \ No newline at end of file diff --git a/package/lienol/luci-app-trojan-server/root/etc/uci-defaults/luci-app-trojan-server b/package/lienol/luci-app-trojan-server/root/etc/uci-defaults/luci-app-trojan-server deleted file mode 100755 index 834f610525..0000000000 --- a/package/lienol/luci-app-trojan-server/root/etc/uci-defaults/luci-app-trojan-server +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete firewall.trojan_server - set firewall.trojan_server=include - set firewall.trojan_server.type=script - set firewall.trojan_server.path=/usr/share/trojan_server/firewall.include - set firewall.trojan_server.reload=1 -EOF - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@trojan_server[-1] - add ucitrack trojan_server - set ucitrack.@trojan_server[-1].init=trojan_server - commit ucitrack -EOF - -chmod a+x /usr/share/trojan_server/* >/dev/null 2>&1 - -rm -f /tmp/luci-indexcache -exit 0 diff --git a/package/lienol/luci-app-trojan-server/root/usr/share/trojan_server/firewall.include b/package/lienol/luci-app-trojan-server/root/usr/share/trojan_server/firewall.include deleted file mode 100755 index 462ad5b4c0..0000000000 --- a/package/lienol/luci-app-trojan-server/root/usr/share/trojan_server/firewall.include +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/sh - -count=$(iptables -n -L INPUT 2>/dev/null | grep -c "TROJAN-SERVER") -if [ -n "$count" ]; then - until [ "$count" = 0 ] - do - rules=$(iptables -n -L INPUT --line-num 2>/dev/null | grep "TROJAN-SERVER" | awk '{print $1}') - for rule in $rules - do - iptables -D INPUT $rule 2>/dev/null - break - done - count=$(expr $count - 1) - done -fi - -iptables -F TROJAN-SERVER 2>/dev/null && iptables -X TROJAN-SERVER 2>/dev/null - -enable=$(uci -q get trojan_server.@global[0].enable) -if [ $enable -eq 1 ]; then - iptables -N TROJAN-SERVER - iptables -I INPUT -j TROJAN-SERVER - - count=$(uci show trojan_server | grep "@user" | sed -n '$p' | cut -d '[' -f 2 | cut -d ']' -f 1) - [ -n "$count" ] && [ "$count" -ge 0 ] && { - u_get() { - local ret=$(uci -q get trojan_server.@user[$1].$2) - echo ${ret:=$3} - } - for i in $(seq 0 $count); do - enable=$(u_get $i enable 0) - [ $enable -eq 0 ] && continue - remarks=$(u_get $i remarks) - port=$(u_get $i port) - iptables -A TROJAN-SERVER -p tcp --dport $port -m comment --comment "$remarks" -j ACCEPT - iptables -A TROJAN-SERVER -p udp --dport $port -m comment --comment "$remarks" -j ACCEPT - done - } -fi diff --git a/package/lienol/luci-app-webrestriction/Makefile b/package/lienol/luci-app-webrestriction/Makefile deleted file mode 100644 index f3be31f748..0000000000 --- a/package/lienol/luci-app-webrestriction/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (C) 2016 Openwrt.org -# -# This is free software, licensed under the Apache License, Version 2.0 . -# - -include $(TOPDIR)/rules.mk - -LUCI_TITLE:=LuCI support for Webrestriction -LUCI_PKGARCH:=all -PKG_VERSION:=1.0 -PKG_RELEASE:=3-20190309 - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature - - diff --git a/package/lienol/luci-app-webrestriction/luasrc/controller/webrestriction.lua b/package/lienol/luci-app-webrestriction/luasrc/controller/webrestriction.lua deleted file mode 100644 index 4ab412fe05..0000000000 --- a/package/lienol/luci-app-webrestriction/luasrc/controller/webrestriction.lua +++ /dev/null @@ -1,16 +0,0 @@ -module("luci.controller.webrestriction", package.seeall) - -function index() - if not nixio.fs.access("/etc/config/webrestriction") then return end - - entry({"admin", "control"}, firstchild(), "Control", 44).dependent = false - entry({"admin", "control", "webrestriction"}, cbi("webrestriction"),_("访问限制"), 11).dependent = true - entry({"admin", "control", "webrestriction", "status"}, call("status")).leaf = true -end - -function status() - local e = {} - e.status = luci.sys.call("iptables -L FORWARD |grep WEB_RESTRICTION >/dev/null") == 0 - luci.http.prepare_content("application/json") - luci.http.write_json(e) -end diff --git a/package/lienol/luci-app-webrestriction/luasrc/model/cbi/webrestriction.lua b/package/lienol/luci-app-webrestriction/luasrc/model/cbi/webrestriction.lua deleted file mode 100644 index 8727a8ac41..0000000000 --- a/package/lienol/luci-app-webrestriction/luasrc/model/cbi/webrestriction.lua +++ /dev/null @@ -1,30 +0,0 @@ -local o = require "luci.sys" -local a, e, t -a = Map("webrestriction", translate("访问限制"), translate( - "使用黑名单或者白名单模式控制列表中的客户端是否能够连接到互联网。")) -a.template = "webrestriction/index" -e = a:section(TypedSection, "basic", translate("Running Status")) -e.anonymous = true -t = e:option(DummyValue, "webrestriction_status", translate("当前状态")) -t.template = "webrestriction/webrestriction" -t.value = translate("Collecting data...") -e = a:section(TypedSection, "basic", translate("全局设置")) -e.anonymous = true -t = e:option(Flag, "enable", translate("开启")) -t.rmempty = false -t = e:option(ListValue, "limit_type", translate("限制模式")) -t.default = "blacklist" -t:value("whitelist", translate("白名单")) -t:value("blacklist", translate("Blacklist")) -t.rmempty = false -e = a:section(TypedSection, "macbind", translate("名单设置"), translate( - "如果是黑名单模式,列表中的客户端将被禁止连接到互联网;白名单模式表示仅有列表中的客户端可以连接到互联网。")) -e.template = "cbi/tblsection" -e.anonymous = true -e.addremove = true -t = e:option(Flag, "enable", translate("开启控制")) -t.rmempty = false -t = e:option(Value, "macaddr", translate("MAC地址")) -t.rmempty = true -o.net.mac_hints(function(e, a) t:value(e, "%s (%s)" % {e, a}) end) -return a diff --git a/package/lienol/luci-app-webrestriction/luasrc/view/webrestriction/index.htm b/package/lienol/luci-app-webrestriction/luasrc/view/webrestriction/index.htm deleted file mode 100644 index 21f269e79d..0000000000 --- a/package/lienol/luci-app-webrestriction/luasrc/view/webrestriction/index.htm +++ /dev/null @@ -1,18 +0,0 @@ -<%# - Copyright 2016 Chen RuiWei - Licensed to the public under the Apache License 2.0. --%> - -<% include("cbi/map") %> - diff --git a/package/lienol/luci-app-webrestriction/luasrc/view/webrestriction/webrestriction.htm b/package/lienol/luci-app-webrestriction/luasrc/view/webrestriction/webrestriction.htm deleted file mode 100644 index 03702cf7e3..0000000000 --- a/package/lienol/luci-app-webrestriction/luasrc/view/webrestriction/webrestriction.htm +++ /dev/null @@ -1,3 +0,0 @@ -<%+cbi/valueheader%> -<%=pcdata(self:cfgvalue(section) or self.default or "")%> -<%+cbi/valuefooter%> diff --git a/package/lienol/luci-app-webrestriction/po/zh-cn/webrestriction.po b/package/lienol/luci-app-webrestriction/po/zh-cn/webrestriction.po deleted file mode 100644 index a883cf73ab..0000000000 --- a/package/lienol/luci-app-webrestriction/po/zh-cn/webrestriction.po +++ /dev/null @@ -1,2 +0,0 @@ -msgid "Control" -msgstr "管控" diff --git a/package/lienol/luci-app-webrestriction/root/etc/config/webrestriction b/package/lienol/luci-app-webrestriction/root/etc/config/webrestriction deleted file mode 100644 index 504593945b..0000000000 --- a/package/lienol/luci-app-webrestriction/root/etc/config/webrestriction +++ /dev/null @@ -1,5 +0,0 @@ - -config basic - option enable '0' - option limit_type 'blacklist' - diff --git a/package/lienol/luci-app-webrestriction/root/etc/init.d/webrestriction b/package/lienol/luci-app-webrestriction/root/etc/init.d/webrestriction deleted file mode 100755 index ab1d28cdbb..0000000000 --- a/package/lienol/luci-app-webrestriction/root/etc/init.d/webrestriction +++ /dev/null @@ -1,86 +0,0 @@ -#!/bin/sh /etc/rc.common -# -# Copyright (C) 2015 OpenWrt-dist -# Copyright (C) 2016 fw867 -# -# This is free software, licensed under the GNU General Public License v3. -# See /LICENSE for more information. -# - -START=99 - -CONFIG=webrestriction -limit_type=$(uci -q get webrestriction.@basic[0].limit_type) - -uci_get_by_type() { - local index=0 - if [ -n $4 ]; then - index=$4 - fi - local ret=$(uci get $CONFIG.@$1[$index].$2 2>/dev/null) - echo ${ret:=$3} -} - -is_true() { - case $1 in - 1|on|true|yes|enabled) echo 0;; - *) echo 1;; - esac -} - -load_config() { - ENABLED=$(uci_get_by_type basic enable) - return $(is_true $ENABLED) -} - - -add_rule(){ - action=$1 - for i in $(seq 0 100) - do - enable=$(uci_get_by_type macbind enable '' $i) - macaddr=$(uci_get_by_type macbind macaddr '' $i) - if [ -z $enable ] || [ -z $macaddr ]; then - break - fi - if [ "$enable" == "1" ]; then - iptables -t filter -A WEB_RESTRICTION -m mac --mac-source $macaddr -j $action - [ "$limit_type" == "blacklist" ] && iptables -t nat -A WEB_RESTRICTION -m mac --mac-source $macaddr -j RETURN - #unset "$macaddr" - fi - done -} - -start(){ - - ! load_config && exit 0 - [ "`iptables -L FORWARD|grep -c WEB_RESTRICTION`" -gt 0 ] && exit 0; - iptables -P FORWARD DROP - iptables -t filter -N WEB_RESTRICTION - if [ "$limit_type" == "blacklist" ]; then - iptables -t nat -N WEB_RESTRICTION - add_rule DROP - else - add_rule ACCEPT - iptables -t filter -A WEB_RESTRICTION -j DROP - fi - - #获取FORWARD ACCEPT规则行号 - FA_INDEX=`iptables -t filter -L FORWARD|tail -n +3|sed -n -e '/^ACCEPT/='` - if [ -n "$FA_INDEX" ]; then - let FA_INDEX+=1 - fi - #确保添加到FORWARD ACCEPT规则之后 - iptables -t filter -I FORWARD $FA_INDEX -m comment --comment "Rule For Control" -j WEB_RESTRICTION - [ "$limit_type" == "blacklist" ] && iptables -t nat -I PREROUTING 1 -m comment --comment "Rule For Control" -j WEB_RESTRICTION -} -stop(){ - [ "`iptables -t filter -L | grep -c WEB_RESTRICTION`" -gt 0 ] && { - iptables -t filter -D FORWARD -m comment --comment "Rule For Control" -j WEB_RESTRICTION - iptables -t nat -D PREROUTING -m comment --comment "Rule For Control" -j WEB_RESTRICTION - iptables -t filter -F WEB_RESTRICTION - iptables -t filter -X WEB_RESTRICTION - iptables -t nat -F WEB_RESTRICTION - iptables -t nat -X WEB_RESTRICTION - } -} \ No newline at end of file diff --git a/package/lienol/luci-app-webrestriction/root/etc/uci-defaults/luci-app-control-webrestriction b/package/lienol/luci-app-webrestriction/root/etc/uci-defaults/luci-app-control-webrestriction deleted file mode 100755 index 25ff88a9a6..0000000000 --- a/package/lienol/luci-app-webrestriction/root/etc/uci-defaults/luci-app-control-webrestriction +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@webrestriction[-1] - add ucitrack webrestriction - set ucitrack.@webrestriction[-1].init=webrestriction - commit ucitrack -EOF - -rm -f /tmp/luci-indexcache -exit 0 diff --git a/package/lienol/luci-app-weburl/Makefile b/package/lienol/luci-app-weburl/Makefile deleted file mode 100644 index 3bcf5fb205..0000000000 --- a/package/lienol/luci-app-weburl/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (C) 2016 Openwrt.org -# -# This is free software, licensed under the Apache License, Version 2.0 . -# - -include $(TOPDIR)/rules.mk - -LUCI_TITLE:=LuCI support for Weburl -LUCI_DEPENDS:=+iptables-mod-filter +kmod-ipt-filter -LUCI_PKGARCH:=all -PKG_VERSION:=1.0 -PKG_RELEASE:=3-20190309 - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature - - diff --git a/package/lienol/luci-app-weburl/luasrc/controller/weburl.lua b/package/lienol/luci-app-weburl/luasrc/controller/weburl.lua deleted file mode 100644 index 5036d18686..0000000000 --- a/package/lienol/luci-app-weburl/luasrc/controller/weburl.lua +++ /dev/null @@ -1,16 +0,0 @@ -module("luci.controller.weburl", package.seeall) - -function index() - if not nixio.fs.access("/etc/config/weburl") then return end - - entry({"admin", "control"}, firstchild(), "Control", 44).dependent = false - entry({"admin", "control", "weburl"}, cbi("weburl"), _("网址过滤"), 12).dependent = true - entry({"admin", "control", "weburl", "status"}, call("status")).leaf = true -end - -function status() - local e = {} - e.status = luci.sys.call("iptables -L FORWARD |grep WEBURL >/dev/null") == 0 - luci.http.prepare_content("application/json") - luci.http.write_json(e) -end diff --git a/package/lienol/luci-app-weburl/luasrc/model/cbi/weburl.lua b/package/lienol/luci-app-weburl/luasrc/model/cbi/weburl.lua deleted file mode 100644 index 699c97ab09..0000000000 --- a/package/lienol/luci-app-weburl/luasrc/model/cbi/weburl.lua +++ /dev/null @@ -1,36 +0,0 @@ -local o = require "luci.sys" -local a, t, e -a = Map("weburl", translate("网址过滤"), translate( - "在这里设置关键词过滤,可以是URL里任意字符,可以过滤如视频网站、QQ、迅雷、淘宝。。。")) -a.template = "weburl/index" -t = a:section(TypedSection, "basic", translate("Running Status")) -t.anonymous = true -e = t:option(DummyValue, "weburl_status", translate("当前状态")) -e.template = "weburl/weburl" -e.value = translate("Collecting data...") -t = a:section(TypedSection, "basic", translate("基本设置"), translate( - "一般来说普通过滤效果就很好了,强制过滤会使用更复杂的算法导致更高的CPU占用。")) -t.anonymous = true -e = t:option(Flag, "enable", translate("开启")) -e.rmempty = false -e = t:option(Flag, "algos", translate("强效过滤")) -e.rmempty = false -t = a:section(TypedSection, "macbind", translate("关键词设置"), translate( - "黑名单MAC不设置为全客户端过滤,如设置只过滤指定的客户端。过滤时间可不设置。")) -t.template = "cbi/tblsection" -t.anonymous = true -t.addremove = true -e = t:option(Flag, "enable", translate("开启控制")) -e.rmempty = false -e = t:option(Value, "macaddr", translate("黑名单MAC")) -e.rmempty = true -o.net.mac_hints(function(t, a) e:value(t, "%s (%s)" % {t, a}) end) -e = t:option(Value, "timeon", translate("开始过滤时间")) -e.placeholder = "00:00" -e.rmempty = true -e = t:option(Value, "timeoff", translate("取消过滤时间")) -e.placeholder = "23:59" -e.rmempty = true -e = t:option(Value, "keyword", translate("网址关键词")) -e.rmempty = false -return a diff --git a/package/lienol/luci-app-weburl/luasrc/view/weburl/index.htm b/package/lienol/luci-app-weburl/luasrc/view/weburl/index.htm deleted file mode 100644 index 47575a4241..0000000000 --- a/package/lienol/luci-app-weburl/luasrc/view/weburl/index.htm +++ /dev/null @@ -1,18 +0,0 @@ -<%# - Copyright 2016 Chen RuiWei - Licensed to the public under the Apache License 2.0. --%> - -<% include("cbi/map") %> - diff --git a/package/lienol/luci-app-weburl/luasrc/view/weburl/weburl.htm b/package/lienol/luci-app-weburl/luasrc/view/weburl/weburl.htm deleted file mode 100644 index a61ad9b89a..0000000000 --- a/package/lienol/luci-app-weburl/luasrc/view/weburl/weburl.htm +++ /dev/null @@ -1,3 +0,0 @@ -<%+cbi/valueheader%> -<%=pcdata(self:cfgvalue(section) or self.default or "")%> -<%+cbi/valuefooter%> diff --git a/package/lienol/luci-app-weburl/po/zh-cn/weburl.po b/package/lienol/luci-app-weburl/po/zh-cn/weburl.po deleted file mode 100644 index a883cf73ab..0000000000 --- a/package/lienol/luci-app-weburl/po/zh-cn/weburl.po +++ /dev/null @@ -1,2 +0,0 @@ -msgid "Control" -msgstr "管控" diff --git a/package/lienol/luci-app-weburl/root/etc/config/weburl b/package/lienol/luci-app-weburl/root/etc/config/weburl deleted file mode 100644 index 5d6d46e6e9..0000000000 --- a/package/lienol/luci-app-weburl/root/etc/config/weburl +++ /dev/null @@ -1,22 +0,0 @@ - -config basic - option enable '0' - option algos '0' - -config macbind - option keyword 'qq.com' - option enable '0' - option macaddr '00:0C:29:C8:99:9E' - -config macbind - option keyword 'taobao.com' - option enable '0' - -config macbind - option enable '0' - option keyword 'youku.com' - -config macbind - option enable '0' - option keyword 'www' - diff --git a/package/lienol/luci-app-weburl/root/etc/init.d/weburl b/package/lienol/luci-app-weburl/root/etc/init.d/weburl deleted file mode 100755 index 1785abf73d..0000000000 --- a/package/lienol/luci-app-weburl/root/etc/init.d/weburl +++ /dev/null @@ -1,88 +0,0 @@ -#!/bin/sh /etc/rc.common -# -# Copyright (C) 2015 OpenWrt-dist -# Copyright (C) 2016 fw867 -# -# This is free software, licensed under the GNU General Public License v3. -# See /LICENSE for more information. -# - -START=99 - -CONFIG=weburl - -uci_get_by_type() { - local index=0 - if [ -n $4 ]; then - index=$4 - fi - local ret=$(uci get $CONFIG.@$1[$index].$2 2>/dev/null) - echo ${ret:=$3} -} - -is_true() { - case $1 in - 1|on|true|yes|enabled) echo 0;; - *) echo 1;; - esac -} - -load_config() { - ENABLED=$(uci_get_by_type basic enable) - return $(is_true $ENABLED) -} - -get_algo_mode(){ - case "$1" in - 0) - echo "bm" - ;; - 1) - echo "kmp" - ;; - esac -} - -add_rule(){ - algos=$(uci_get_by_type basic algos) - for i in $(seq 0 100) - do - enable=$(uci_get_by_type macbind enable '' $i) - macaddr=$(uci_get_by_type macbind macaddr '' $i) - timeon=$(uci_get_by_type macbind timeon '' $i) - timeoff=$(uci_get_by_type macbind timeoff '' $i) - keyword=$(uci_get_by_type macbind keyword '' $i) - if [ -z $enable ] || [ -z $keyword ]; then - break - fi - - if [ -z $timeon ] || [ -z $timeoff ]; then - settime="" - else - settime="-m time --kerneltz --timestart $timeon --timestop $timeoff" - fi - - if [ "$enable" == "1" ]; then - if [ -z $macaddr ]; then - iptables -t filter -I WEBURL $settime -m string --string "$keyword" --algo $(get_algo_mode $algos) -j DROP - else - iptables -t filter -I WEBURL $settime -m mac --mac-source $macaddr -m string --string "$keyword" --algo $(get_algo_mode $algos) -j DROP - unset "$macaddr" - fi - fi - done -} - -start(){ - ! load_config && exit 0 - iptables -L FORWARD | grep -c WEBURL 2>/dev/null && [ $? -eq 0 ] && exit 0; - iptables -t filter -N WEBURL - iptables -t filter -I FORWARD -m comment --comment "Rule For Control" -j WEBURL - add_rule -} -stop(){ - iptables -t filter -D FORWARD -m comment --comment "Rule For Control" -j WEBURL - iptables -t filter -F WEBURL - iptables -t filter -X WEBURL -} - diff --git a/package/lienol/luci-app-weburl/root/etc/uci-defaults/luci-app-control-weburl b/package/lienol/luci-app-weburl/root/etc/uci-defaults/luci-app-control-weburl deleted file mode 100755 index fed8291979..0000000000 --- a/package/lienol/luci-app-weburl/root/etc/uci-defaults/luci-app-control-weburl +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@weburl[-1] - add ucitrack weburl - set ucitrack.@weburl[-1].init=weburl - commit ucitrack -EOF - -rm -f /tmp/luci-indexcache -exit 0 diff --git a/package/lienol/luci-theme-argon-dark-mod/Makefile b/package/lienol/luci-theme-argon-dark-mod/Makefile deleted file mode 100644 index 28459ee87b..0000000000 --- a/package/lienol/luci-theme-argon-dark-mod/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (C) 2008-2019 Jerrykuku -# Copyright (C) 2019-2020 Lienol -# -# This is free software, licensed under the Apache License, Version 2.0 . -# - -include $(TOPDIR)/rules.mk - -LUCI_TITLE:=Argon Dark Mod Theme -LUCI_DEPENDS:= -PKG_VERSION:=1.6 -PKG_RELEASE:=20200523 - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature diff --git a/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/css/purecss.css b/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/css/purecss.css deleted file mode 100644 index 0b2bf6426e..0000000000 --- a/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/css/purecss.css +++ /dev/null @@ -1,7 +0,0 @@ -/*! -Pure v1.0.1 -Copyright 2013 Yahoo! -Licensed under the BSD License. -https://github.com/pure-css/pure/blob/master/LICENSE.md -*/ -.pure-g{letter-spacing:-.31em;text-rendering:optimizespeed;font-family:FreeSans,Arimo,"Droid Sans",Helvetica,Arial,sans-serif;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-align-content:flex-start;-ms-flex-line-pack:start;align-content:flex-start}@media all and (-ms-high-contrast:none),(-ms-high-contrast:active){table .pure-g{display:block}}.opera-only :-o-prefocus,.pure-g{word-spacing:-.43em}.pure-u,.pure-u-1,.pure-u-1-1,.pure-u-1-12,.pure-u-1-2,.pure-u-1-24,.pure-u-1-3,.pure-u-1-4,.pure-u-1-5,.pure-u-1-6,.pure-u-1-8,.pure-u-10-24,.pure-u-11-12,.pure-u-11-24,.pure-u-12-24,.pure-u-13-24,.pure-u-14-24,.pure-u-15-24,.pure-u-16-24,.pure-u-17-24,.pure-u-18-24,.pure-u-19-24,.pure-u-2-24,.pure-u-2-3,.pure-u-2-5,.pure-u-20-24,.pure-u-21-24,.pure-u-22-24,.pure-u-23-24,.pure-u-24-24,.pure-u-3-24,.pure-u-3-4,.pure-u-3-5,.pure-u-3-8,.pure-u-4-24,.pure-u-4-5,.pure-u-5-12,.pure-u-5-24,.pure-u-5-5,.pure-u-5-6,.pure-u-5-8,.pure-u-6-24,.pure-u-7-12,.pure-u-7-24,.pure-u-7-8,.pure-u-8-24,.pure-u-9-24{display:inline-block;zoom:1;letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto}.pure-g [class*=pure-u]{font-family:sans-serif}.pure-u-1-24{width:4.1667%}.pure-u-1-12,.pure-u-2-24{width:8.3333%}.pure-u-1-8,.pure-u-3-24{width:12.5%}.pure-u-1-6,.pure-u-4-24{width:16.6667%}.pure-u-1-5{width:20%}.pure-u-5-24{width:20.8333%}.pure-u-1-4,.pure-u-6-24{width:25%}.pure-u-7-24{width:29.1667%}.pure-u-1-3,.pure-u-8-24{width:33.3333%}.pure-u-3-8,.pure-u-9-24{width:37.5%}.pure-u-2-5{width:40%}.pure-u-10-24,.pure-u-5-12{width:41.6667%}.pure-u-11-24{width:45.8333%}.pure-u-1-2,.pure-u-12-24{width:50%}.pure-u-13-24{width:54.1667%}.pure-u-14-24,.pure-u-7-12{width:58.3333%}.pure-u-3-5{width:60%}.pure-u-15-24,.pure-u-5-8{width:62.5%}.pure-u-16-24,.pure-u-2-3{width:66.6667%}.pure-u-17-24{width:70.8333%}.pure-u-18-24,.pure-u-3-4{width:75%}.pure-u-19-24{width:79.1667%}.pure-u-4-5{width:80%}.pure-u-20-24,.pure-u-5-6{width:83.3333%}.pure-u-21-24,.pure-u-7-8{width:87.5%}.pure-u-11-12,.pure-u-22-24{width:91.6667%}.pure-u-23-24{width:95.8333%}.pure-u-1,.pure-u-1-1,.pure-u-24-24,.pure-u-5-5{width:100%} \ No newline at end of file diff --git a/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/css/style.css b/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/css/style.css deleted file mode 100644 index 087b32cb3f..0000000000 --- a/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/css/style.css +++ /dev/null @@ -1,3837 +0,0 @@ -/** - * Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material and Argon Template - * - * luci-theme-argon - * Copyright 2019 Jerrykuku - * - * Have a bug? Please create an issue here on GitHub! - * https://github.com/jerrykuku/luci-theme-argon/issues - * - * luci-theme-bootstrap: - * Copyright 2008 Steven Barth - * Copyright 2008 Jo-Philipp Wich - * Copyright 2012 David Menting - * - * MUI: - * https://github.com/muicss/mui - * - * luci-theme-material: - * https://github.com/LuttyYang/luci-theme-material/ - * - * Agron Theme - * https://demos.creative-tim.com/argon-dashboard/index.html - * - * Login background - * https://unsplash.com/ - * - * Licensed to the public under the Apache License 2.0 - */ - -/* - * Font generate by Icomoon - * Mod again by Mask - * Mod again by Lienol - */ - -:root { - --blue: #5e72e4; - --indigo: #5603ad; - --purple: #8965e0; - --pink: #f3a4b5; - --red: #f5365c; - --orange: #fb6340; - --yellow: #ffd600; - --green: #2dce89; - --teal: #11cdef; - --cyan: #2bffc6; - --white: #fff; - --gray: #8898aa; - --gray-dark: #32325d; - --light: #ced4da; - --lighter: #e9ecef; - --primary: #5e72e4; - --secondary: #f7fafc; - --success: #2dce89; - --info: #11cdef; - --warning: #fb6340; - --danger: #f5365c; - --light: #adb5bd; - --dark: #212529; - --default: #172b4d; - --white: #fff; - --neutral: #fff; - --darker: black; - --breakpoint-xs: 0; - --breakpoint-sm: 576px; - --breakpoint-md: 768px; - --breakpoint-lg: 992px; - --breakpoint-xl: 1200px; - --font-family-sans-serif: Open Sans, sans-serif; - --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; -} - - - -@font-face { - font-family: 'icomoon'; - src: url('../fonts/font.eot'); - src: url('../fonts/font.eot') format('embedded-opentype'), - url('../fonts/font.ttf') format('truetype'), - url('../fonts/font.woff') format('woff'), - url('../fonts/font.svg') format('svg'); - font-weight: normal; - font-style: normal; -} - -@font-face { - font-family: 'ssr'; - src: url('../fonts/ssr.eot?5zoxsi'); - src: url('../fonts/ssr.eot?5zoxsi#iefix') format('embedded-opentype'), - url('../fonts/ssr.ttf?5zoxsi') format('truetype'), - url('../fonts/ssr.woff?5zoxsi') format('woff'), - url('../fonts/ssr.svg?5zoxsi#ssr') format('svg'); - font-weight: normal; - font-style: normal; -} - -@font-face { - font-family: 'TypoGraphica'; - src: url('../fonts/TypoGraphica.eot?#iefix') format('embedded-opentype'), url('../fonts/TypoGraphica.woff') format('woff'), url('../fonts/TypoGraphica.ttf') format('truetype'), url('../fonts/TypoGraphica.svg#TypoGraphica') format('svg'); - font-weight: normal; - font-style: normal; -} - -@font-face { - font-family: 'icomoon'; - src: url('../fonts/icomoon.eot?1peg26'); - src: url('../fonts/icomoon.eot?1peg26#iefix') format('embedded-opentype'), - url('../fonts/icomoon.ttf?1peg26') format('truetype'), - url('../fonts/icomoon.woff?1peg26') format('woff'), - url('../fonts/icomoon.svg?1peg26#icomoon') format('svg'); - font-weight: normal; - font-style: normal; -} - - - -[class^="icon-"], -[class*=" icon-"] { - /* use !important to prevent issues with browser extensions that change fonts */ - font-family: 'ssr' !important; - speak: none; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - - /* Better Font Rendering =========== */ - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -.icon-dashboard:before { - content: "\e906"; -} - -.icon-logout:before { - content: "\e907"; -} - -.icon-Network:before { - content: "\e908"; -} - -.icon-services:before { - content: "\e909"; -} - -.icon-system:before { - content: "\e90a"; -} - -.icon-vpn:before { - content: "\e90b"; -} - -.icon-storage:before { - content: "\e90c"; -} - -.icon-statistics:before { - content: "\e90d"; -} - -.icon-delete:before { - content: "\e900"; -} - -.icon-edit:before { - content: "\e901"; -} - -.icon-ok:before { - content: "\e902"; -} - -.icon-loading:before { - content: "\e903"; -} - -.icon-switch:before { - content: "\e904"; -} - -.icon-error:before { - content: "\e905"; -} - -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -.h1, -.h2, -.h3, -.h4, -.h5, -.h6, -h1, -h2, -h3, -h4, -h5, -h6 { - font-family: inherit; - font-weight: 400; - line-height: 1.1; - color: inherit; -} - -html { - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; -} - -body { - font-size: 0.8rem; - background-color: rgb(255, 255, 255); -} - -html, -body { - margin: 0px; - padding: 0px; - height: 100%; - font-family: Open Sans, sans-serif Microsoft Yahei, WenQuanYi Micro Hei, sans-serif, "Helvetica Neue", Helvetica, Hiragino Sans GB; -} - -body div { - line-height: 150%; -} - -/*** Main Loading ***/ - -.cbi-button-up, -.cbi-button-down, -.main>.loading { - - background: linear-gradient(87deg, #5e72e4 0, #5e72e4 100%) !important; -} - -.sk-folding-cube { - margin: 20px auto; - width: 40px; - height: 40px; - position: relative; - -webkit-transform: rotateZ(45deg); - transform: rotateZ(45deg); -} - -.sk-folding-cube .sk-cube { - float: left; - width: 50%; - height: 50%; - position: relative; - -webkit-transform: scale(1.1); - -ms-transform: scale(1.1); - transform: scale(1.1); -} - -.sk-folding-cube .sk-cube:before { - content: ''; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background-color: #fff; - -webkit-animation: sk-foldCubeAngle 2.4s infinite linear both; - animation: sk-foldCubeAngle 2.4s infinite linear both; - -webkit-transform-origin: 100% 100%; - -ms-transform-origin: 100% 100%; - transform-origin: 100% 100%; -} - -.sk-folding-cube .sk-cube2 { - -webkit-transform: scale(1.1) rotateZ(90deg); - transform: scale(1.1) rotateZ(90deg); -} - -.sk-folding-cube .sk-cube3 { - -webkit-transform: scale(1.1) rotateZ(180deg); - transform: scale(1.1) rotateZ(180deg); -} - -.sk-folding-cube .sk-cube4 { - -webkit-transform: scale(1.1) rotateZ(270deg); - transform: scale(1.1) rotateZ(270deg); -} - -.sk-folding-cube .sk-cube2:before { - -webkit-animation-delay: 0.3s; - animation-delay: 0.3s; -} - -.sk-folding-cube .sk-cube3:before { - -webkit-animation-delay: 0.6s; - animation-delay: 0.6s; -} - -.sk-folding-cube .sk-cube4:before { - -webkit-animation-delay: 0.9s; - animation-delay: 0.9s; -} - -@-webkit-keyframes sk-foldCubeAngle { - - 0%, - 10% { - -webkit-transform: perspective(140px) rotateX(-180deg); - transform: perspective(140px) rotateX(-180deg); - opacity: 0; - } - - 25%, - 75% { - -webkit-transform: perspective(140px) rotateX(0deg); - transform: perspective(140px) rotateX(0deg); - opacity: 1; - } - - 90%, - 100% { - -webkit-transform: perspective(140px) rotateY(180deg); - transform: perspective(140px) rotateY(180deg); - opacity: 0; - } -} - -@keyframes sk-foldCubeAngle { - - 0%, - 10% { - -webkit-transform: perspective(140px) rotateX(-180deg); - transform: perspective(140px) rotateX(-180deg); - opacity: 0; - } - - 25%, - 75% { - -webkit-transform: perspective(140px) rotateX(0deg); - transform: perspective(140px) rotateX(0deg); - opacity: 1; - } - - 90%, - 100% { - -webkit-transform: perspective(140px) rotateY(180deg); - transform: perspective(140px) rotateY(180deg); - opacity: 0; - } -} - - -.cbi-button-up, -.cbi-button-down, -.cbi-value-helpicon, -.showSide, -.main>.loading>span { - font-family: 'icomoon' !important; - speak: none; - font-style: normal !important; - font-weight: normal !important; - font-variant: normal !important; - text-transform: none !important; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - - - -select[multiple="multiple"] { - height: auto; -} - -code { - color: #0099CC; -} - -abbr { - color: #005470; - text-decoration: underline; - cursor: help; -} - -hr { - margin: 1rem 0; - border-color: #EEE; - opacity: 0.1; -} - - - -footer>a { - color: #aaa; - text-decoration: none; -} - -.main { - top: 4rem; - bottom: 0rem; - position: relative; - height: 100%; - height: calc(100% - 4rem); -} - -.main>.loading { - position: fixed; - width: 100%; - height: 100%; - z-index: 1000; - display: block; - background-color: rgb(240, 240, 240); - top: 0; -} - -.main>.loading>span { - display: block; - text-align: center; - margin-top: 2rem; - color: #888; - font-size: 1.2rem; -} - -.main>.loading>span>.loading-img:before { - content: "\e603"; -} - -.main>.loading>span>.loading-img { - animation: anim-rotate 2s infinite linear; - margin-right: 0.2rem; - display: inline-block; -} - -@keyframes anim-rotate { - 0% { - -webkit-transform: rotate(0); - -ms-transform: rotate(0); - transform: rotate(0); - } - - 100% { - -webkit-transform: rotate(360deg); - -ms-transform: rotate(360deg); - transform: rotate(360deg) - } -} - - - - -.pull-right { - float: right; - margin-top: 0.5rem; -} - -.pull-left { - float: left; -} - - - - - - -#maincontent>.container>div:nth-child(1).alert-message.warning>a { - font: inherit; - overflow: visible; - text-transform: none; - display: inline-block; - margin-bottom: 0; - font-weight: 400; - text-align: center; - white-space: nowrap; - vertical-align: middle; - touch-action: manipulation; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - background-image: none; - min-width: 6rem; - padding: 0.5rem 1rem; - font-size: 0.9rem; - line-height: 1.42857143; - color: #fff; - background-color: #5bc0de; - border-color: #46b8da; - margin-top: 2rem; - text-decoration: inherit; -} - -#maincontent>.container>p { - color: #fff; -} - -li { - list-style-type: none; -} - - - -.cbi-map-descr+fieldset { - margin-top: 1rem; -} - -.cbi-section>legend { - display: none !important; -} - -/* fix progress bar */ -#swaptotal>div, -#swapfree>div, -#swapcache>div, -#memfree>div, -#membuff>div, -#conns>div, -#memcache>div, -#memtotal>div, -#cpu_free>div, -.progress_bar>div { - width: 100% !important; - height: 1.6rem !important; - line-height: 1.6rem; - border-radius: .25rem; -} - -#swaptotal>div>div, -#swapfree>div>div, -#swapcache>div>div, -#memfree>div>div, -#membuff>div>div, -#conns>div>div, -#memcache>div>div, -#memtotal>div>div, -#cpu_free>div>div, -.progress_bar>div>div { - height: 100% !important; - border-radius: 5px; - background: linear-gradient(87deg, #5e72e4 0, #825ee4 100%)!important; -} - -/* fix multiple table */ - -table table, -.table .table { - border: none; -} - -.cbi-value-field table, -.cbi-value-field .table { - border: none; -} - -td>table>tbody>tr>td, -.td>.table>.tbody>.tr>.td { - border: none; -} - -.cbi-value-field>table>tbody>tr>td, -.cbi-value-field>.table>.tbody>.tr>.td { - border: none; -} - -/* button style */ - - - -.cbi-page-actions .cbi-button-apply, -.cbi-section-actions .cbi-button-edit, -.cbi-button-edit.important, -.cbi-button-apply.important, -.cbi-button-reload.important, -.cbi-button-action.important { - color: #fff; - background-color: #337ab7; - border: none; -} - -.cbi-page-actions .cbi-button-save, -.cbi-button-add.important, -.cbi-button-save.important, -.cbi-button-positive.important { - color: #fff; - background-color: #5bc0de; - border: none; -} - -.cbi-button-remove.important, -.cbi-button-reset.important, -.cbi-button-negative.important { - color: #fff; - background-color: #d9534f; - border: none; -} - -.cbi-button-find, -.cbi-button-link, -.cbi-button-neutral { - color: #fff !important; - background-color: #f0ad4e !important; - border: none; -} - -.cbi-button-edit, -.cbi-button-apply, -.cbi-button-reload, -.cbi-button-action { - color: #2e6da4; - background-color: transparent; - border: none; -} - -.cbi-page-actions .cbi-button-apply+.cbi-button-save, -.cbi-button-add, -.cbi-button-save, -.cbi-button-positive { - color: #46b8da; - background-color: transparent; - border: none; -} - -.cbi-section-remove>.cbi-button, -.cbi-button-remove, -.cbi-button-reset, -.cbi-button-negative { - color: #fff !important; - background-color: #fb6340 !important; - border: none; -} - -.cbi-page-actions .cbi-button-link:first-child { - float: left; -} - -.a-to-btn { - text-decoration: none; -} - -/* table */ - -.cbi-section-table .cbi-section-table-titles .cbi-section-table-cell { - width: auto; -} - -.td.cbi-section-actions { - /* text-align: right; */ - vertical-align: middle; -} - -.td.cbi-section-actions>* { - /* display: flex; */ -} - -.td.cbi-section-actions>*>*, -.td.cbi-section-actions>*>form>* { - flex: 1 1 4em; - margin: 0 1px; -} - -.td.cbi-section-actions>*>form { - display: inline-flex; - margin: 0; -} - -/* desc */ - -/* luci */ - -.hidden { - display: none -} - -.left, -.left::before { - text-align: left !important; -} - -.right, -.right::before { - text-align: right !important; -} - -.center, -.center::before { - text-align: center !important; -} - -.top { - align-self: flex-start !important; - vertical-align: top !important; -} - -.bottom { - align-self: flex-end !important; - vertical-align: bottom !important; -} - -.inline { - display: inline; -} - -.cbi-page-actions { - border-top: 1px solid #eee; - padding-top: 1rem; - text-align: right; -} - -/* input */ -.cbi-value input[type="password"], -.cbi-value input[type="text"] { - min-width: unset; -} - -select { - width: 15rem; - appearance: none; - -webkit-appearance: none; - background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB0PSIxNTY1MzQ4MDM3OTIyIiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjI1ODMiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCI+PGRlZnM+PHN0eWxlIHR5cGU9InRleHQvY3NzIj4qIHsgdGV4dC1zaGFkb3c6IHRyYW5zcGFyZW50IDBweCAwcHggMHB4LCByZ2JhKDAsIDAsIDAsIDAuNSkgMHB4IDBweCAwcHggIWltcG9ydGFudDsgfQo8L3N0eWxlPjwvZGVmcz48cGF0aCBkPSJNMjAuNDggMjQ1Ljc2aDk4My4wNEw1MTIgNzc4LjI0eiIgcC1pZD0iMjU4NCIgZmlsbD0iIzcwNzA3MCI+PC9wYXRoPjwvc3ZnPg==') !important; - background-position: 96%; - background-size: 8px; - background-repeat: no-repeat; - -} - -.th[data-type="button"], -.td[data-type="button"], -.th[data-type="fvalue"], -.td[data-type="fvalue"] { - flex: 1 1 2em; - text-align: center; -} - - - -/*textarea*/ - -.cbi-input-textarea { - width: 100%; - min-height: 14rem; - padding: 0.8rem; - font-size: 0.8rem; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - color: black; -} - - - -/* change */ - -.uci-change-list { - font-family: monospace; -} - -.uci-change-list ins, -.uci-change-legend-label ins { - text-decoration: none; - border: 1px solid #00FF00; - background-color: #CCFFCC; - display: block; - padding: 2px; -} - -.uci-change-list del, -.uci-change-legend-label del { - text-decoration: none; - border: 1px solid #FF0000; - background-color: #FFCCCC; - display: block; - font-style: normal; - padding: 2px; -} - -.uci-change-list var, -.uci-change-legend-label var { - text-decoration: none; - border: 1px solid #CCCCCC; - background-color: #EEEEEE; - display: block; - font-style: normal; - padding: 2px; -} - -.uci-change-list var ins, -.uci-change-list var del { - border: none; - white-space: pre; - font-style: normal; - padding: 0px; -} - -.uci-change-legend { - padding: 5px; -} - -.uci-change-legend-label { - width: 150px; - float: left; -} - -.uci-change-legend-label>ins, -.uci-change-legend-label>del, -.uci-change-legend-label>var { - float: left; - margin-right: 4px; - width: 10px; - height: 10px; - display: block; -} - -.uci-change-legend-label var ins, -.uci-change-legend-label var del { - line-height: 6px; - border: none; -} - -.uci-change-list var, -.uci-change-list del, -.uci-change-list ins { - padding: 0.5rem; -} - -/* other fix */ -input[type="checkbox"] { - appearance: none !important; - -webkit-appearance: none !important; - border: 1px solid #dee2e6; - - width: 16px !important; - height: 16px !important; - padding: 0; - cursor: pointer; - transition: all 0.2s; - margin: 0.25rem 0; -} - -input[type="checkbox"]:checked { - border: 1px solid #5e72e4; - background-image: url('data:image/svg+xml,%3csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 8 8\'%3e%3cpath fill=\'%23fff\' d=\'M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z\'/%3e%3c/svg%3e') !important; - background: #5e72e4; - background-size: 70%; - background-repeat: no-repeat; - background-position: center; -} - -ul li .cbi-input-checkbox { - margin-top: 0.5rem !important; -} - -.cbi-input-radio { - appearance: none !important; - -webkit-appearance: none !important; - border: 1px solid #dee2e6; - - width: 16px !important; - height: 16px !important; - padding: 0; - border-radius: 50%; - cursor: pointer; - transition: all 0.2s; - margin: 0.25rem 0; -} - -.cbi-input-radio:checked { - border: 1px solid #5e72e4; - background-image: url('data:image/svg+xml,%3csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'-4 -4 8 8\'%3e%3ccircle r=\'3\' fill=\'%23fff\'/%3e%3c/svg%3e') !important; - background-color: #5e72e4; - background-size: 70%; - background-repeat: no-repeat; - background-position: center; -} - - -.toggle { - position: relative; - display: block; - width: 40px; - height: 20px; - cursor: pointer; - -webkit-tap-highlight-color: transparent; - transform: translate3d(0, 0, 0); - margin: 1em 0; -} - -.toggle:before { - content: ""; - position: relative; - top: 3px; - left: 3px; - width: 34px; - height: 14px; - display: block; - background: #9A9999; - border-radius: 8px; - transition: background 0.2s ease; -} - -.toggle span { - position: absolute; - top: 0; - left: 0; - width: 20px; - height: 20px; - display: block; - background: white; - border-radius: 10px; - box-shadow: 0 3px 8px rgba(154, 153, 153, 0.5); - transition: all 0.2s ease; -} - -.toggle span:before { - content: ""; - position: absolute; - display: block; - margin: -18px; - width: 56px; - height: 56px; - background: rgba(79, 46, 220, 0.5); - border-radius: 50%; - transform: scale(0); - opacity: 1; - pointer-events: none; -} - -.cbi-input-checkbox:checked+.toggle:before { - background: #947ADA; -} - -.cbi-input-checkbox:checked+.toggle span { - background: #4F2EDC; - transform: translateX(20px); - transition: all 0.2s cubic-bezier(0.8, 0.4, 0.3, 1.25), background 0.15s ease; - box-shadow: 0 3px 8px rgba(79, 46, 220, 0.2); -} - -.cbi-input-checkbox:checked+.toggle span:before { - transform: scale(1); - opacity: 0; - transition: all 0.4s ease; -} - -.td .cbi-input-checkbox, -.td .cbi-input-radio { - margin-top: 0; -} - -.cbi-value-field>input+.cbi-value-description { - padding: 0; -} - -.cbi-value-field>ul>li { - display: flex; -} - -.cbi-value-field>ul>li>label { - margin-top: 0.5rem; -} - -.cbi-value-field>ul>li .ifacebadge { - background-color: #eee; - margin-left: 0.4rem; - margin-top: -0.5rem; -} - -.cbi-section-table-row>.cbi-value-field .cbi-dropdown { - min-width: 7rem; -} - -.cbi-section-create { - margin: .5rem -3px; - display: inline-flex; - align-items: center; -} - -.cbi-section-create>* { - margin: 0.5rem; -} - -.cbi-section-remove { - padding: 0.5rem; -} - -div.cbi-value var, -td.cbi-value-field var, -.td.cbi-value-field var { - font-style: italic; - color: #0069D6; -} - -small { - font-size: 90%; - white-space: normal; - line-height: 1.42857143; -} - -.cbi-button-up, -.cbi-button-down { - display: inline-block; - min-width: 0; - padding: 0.2rem 0.6rem; - font-size: 1.2rem; - color: #FFF !important; -} - -.cbi-optionals { - padding: 1rem 1rem 0 1rem; - border-top: 1px solid #CCC; -} - -.cbi-dropdown-container { - position: relative; -} - -.cbi-tooltip-container { - cursor: help; -} - -.cbi-tooltip { - position: absolute; - z-index: 1000; - left: -1000px; - opacity: 0; - transition: opacity .25s ease-out; - pointer-events: none; - box-shadow: 0 0 2px #444; -} - -.cbi-tooltip-container:hover .cbi-tooltip { - left: auto; - opacity: 1; - transition: opacity .25s ease-in; -} - -.zonebadge .cbi-tooltip { - padding: .25rem; - background: inherit; - margin: -1.5rem 0 0 -.5rem; -} - -.zonebadge-empty { - background: repeating-linear-gradient(45deg, rgba(204, 204, 204, 0.5), rgba(204, 204, 204, 0.5) 5px, rgba(255, 255, 255, 0.5) 5px, rgba(255, 255, 255, 0.5) 10px); - color: #404040; -} - -.zone-forwards { - display: flex; - min-width: 10rem; -} - -.zone-forwards>* { - flex: 1 1 45%; -} - -.zone-forwards>span { - flex-basis: 10%; - text-align: center; - padding: 0 .25rem; -} - -.zone-forwards .zone-src, -.zone-forwards .zone-dest { - display: flex; - flex-direction: column; -} - -#diag-rc-output>pre { - background-color: #fff; - display: block; - padding: 8.5px; - margin: 0 0 18px; - line-height: 1.5rem; - -moz-border-radius: 3px; - white-space: pre-wrap; - word-wrap: break-word; - font-size: 1.4rem; - color: #404040; -} - -input[name="ping"], -input[name="traceroute"], -input[name="nslookup"] { - width: 80%; -} - - -#xhr_poll_status { - display: inline-block; - -} - -#xhr_poll_status>.label.success { - background-color: #fff !important; - color: #32325d !important; -} - -.label { - padding: 0.3rem 0.8rem; - font-size: 0.8rem; - font-weight: bold; - color: #ffffff !important; - text-transform: uppercase; - white-space: nowrap; - background-color: #bfbfbf; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - text-shadow: none; - text-decoration: none; -} - -.notice { - background-color: #5BC0DE; -} - -.showSide { - display: none; -} - -.darkMask { - width: 100%; - height: 100%; - position: fixed; - background-color: rgba(0, 0, 0, 0.56); - content: ""; - z-index: 99; - display: none; -} - - -/* fix status overview */ - -.node-status-overview>.main fieldset:nth-child(4) .td:nth-child(2) { - white-space: normal; -} - -/* fix status processes */ - -.node-status-processes>.main .table .tr .td:nth-child(3) { - white-space: normal; -} - -.node-status-iptables>.main div>.cbi-map>form { - margin: 2rem 2rem 0 0; -} - -/* fix system reboot */ - -.node-system-reboot>.main>.main-right p, -.node-system-reboot>.main>.main-right h3 { - padding-left: 2rem; -} - -/* fix Services Network Shares*/ -.node-services-samba>.main .cbi-tabcontainer:nth-child(3) .cbi-value-title { - margin-bottom: 1rem; - width: auto; -} - -.node-services-samba>.main .cbi-tabcontainer:nth-child(3) .cbi-value-field { - display: list-item; -} - -.node-services-samba>.main .cbi-tabcontainer:nth-child(3) .cbi-value-description { - padding-top: 1rem; -} - -/* fix System Software*/ -.node-system-packages>.main table tr td:nth-child(1) { - width: auto !important; -} - -.node-system-packages>.main table tr td:nth-last-child(1) { - white-space: normal; - font-size: small; - color: #404040; -} - -.node-system-packages>.main .cbi-tabmenu>li>a, -.tabs>li>a { - padding: 0.5rem 0.8rem; -} - -.node-system-packages>.main .cbi-value>pre { - background-color: #eee; - padding: 0.5rem; - overflow: auto; -} - -.cbi-tabmenu+.cbi-section { - margin-top: 0; -} - -.node-status-iptables fieldset, -.node-system-packages fieldset, -.node-system-flashops fieldset { - margin-top: 0; -} - - -.node-system-flashops form.inline+form.inline { - margin-left: 0; -} - -#cbi-firewall-redirect table *, -#cbi-network-switch_vlan table *, -#cbi-firewall-zone table * { - font-size: small; -} - -#cbi-firewall-redirect table input[type="text"], -#cbi-network-switch_vlan table input[type="text"], -#cbi-firewall-zone table input[type="text"] { - width: 5rem; -} - -#cbi-firewall-redirect table select, -#cbi-network-switch_vlan table select, -#cbi-firewall-zone table select { - min-width: 3.5rem; -} - -#cbi-network-switch_vlan .th, -#cbi-network-switch_vlan .td { - flex-basis: 12%; -} - -/* language fix */ -body.lang_pl.node-main-login .cbi-value-title { - width: 12rem; -} - -/* applyreboot fix */ - -#applyreboot-container { - margin: 2rem; -} - -#applyreboot-section { - margin: 2rem; - line-height: 300%; -} - -.tr { - display: table-row; - border-bottom: 1px solid rgba(0, 0, 0, .05); -} - -.td, -.th { - vertical-align: middle; - text-align: center; - display: table-cell; - padding: 1rem; - white-space: nowrap; -} - -.cbi-section-table-row .td {} - -.th { - font-weight: bold; -} - -.tr.placeholder { - height: 4em; -} - -.tr.placeholder>.td { - position: absolute; - left: 0; - right: 0; - bottom: 0; - text-align: center; - background: inherit; -} - -.table[width="33%"], -.th[width="33%"], -.td[width="33%"] { - width: 33%; - padding-left: 1.5rem; - padding-right: 1.5rem -} - -.table[width="100%"], -.th[width="100%"], -.td[width="100%"] { - width: 100%; -} - -.table-titles .th { - padding: 0.75rem 1rem; - color: #8898aa; - background-color: #f6f9fc; -} - -.col-1 { - flex: 1 1 30px !important; - -webkit-flex: 1 1 30px !important; -} - -.col-2 { - flex: 2 2 60px !important; - -webkit-flex: 2 2 60px !important; -} - -.col-3 { - flex: 3 3 90px !important; - -webkit-flex: 3 3 90px !important; -} - -.col-4 { - flex: 4 4 120px !important; - -webkit-flex: 4 4 120px !important; -} - -.col-5 { - flex: 5 5 150px !important; - -webkit-flex: 5 5 150px !important; -} - -.col-6 { - flex: 6 6 180px !important; - -webkit-flex: 6 6 180px !important; -} - -.col-7 { - flex: 7 7 210px !important; - -webkit-flex: 7 7 210px !important; -} - -.col-8 { - flex: 8 8 240px !important; - -webkit-flex: 8 8 240px !important; -} - -.col-9 { - flex: 9 9 270px !important; - -webkit-flex: 9 9 270px !important; -} - -.col-10 { - flex: 10 10 300px !important; - -webkit-flex: 10 10 300px !important; - white-space: inherit; -} - - - -.cbi-rowstyle-2 .cbi-button-up, -.cbi-rowstyle-2 .cbi-button-down { - background-color: #FFF !important; -} - - - - -select { - padding: 0.36rem 0.8rem; - color: #555; - background-color: #fff; - background-image: none; - border: 1px solid #ccc; -} - -select, -input { - font-size: .875rem; - transition: all .15s ease-in-out; - /* line-height: 1.5; */ - height: calc(2rem); - padding: 0 .75rem; - color: #8898aa; - border: 1px solid #dee2e6; - border-radius: .25rem; - background-color: #fff; - background-clip: padding-box; - box-shadow: 0 3px 2px rgba(233, 236, 239, .05); - outline: none; - transition: box-shadow .15s ease; - margin: 0; -} - -select:not([multiple="multiple"]):focus, -input:focus { - border-color: #5e72e4; - outline: 0; - background-color: #fff; - box-shadow: 0 3px 9px rgba(50, 50, 9, 0), 3px 4px 8px rgba(94, 114, 228, .1); -} - -select[multiple="multiple"] { - height: auto; -} - -code { - color: #0099CC; -} - -abbr { - color: #005470; - text-decoration: underline; - cursor: help; -} - - -hr { - margin: 1rem 0; - border-color: #EEE; - opacity: 0.1; -} - -.bg-primary { - background: linear-gradient(87deg, #5e72e4 0, #825ee4 100%)!important; -} - -header, -.main { - width: 100%; -} - -header { - /* padding: 0 0 14rem 0; */ -} - -footer { - text-align: right; - /* padding: 1rem; */ - color: #aaa; - font-size: 0.8rem; - text-shadow: 0px 0px 2px #BBB; - padding: 2rem; -} - -footer>a { - color: #aaa; - text-decoration: none; -} - -.main { - top: 0rem; - bottom: 0rem; - position: relative; - height: 100%; - height: calc(100% - 4rem); -} - -.main>.loading { - position: fixed; - width: 100%; - height: 100%; - z-index: 2000; - display: flex; - align-items: center; - justify-content: center; - background-color: #f8f9fe; - top: 0; -} - -.main>.loading>span { - display: block; - text-align: center; - margin-top: 2rem; - color: #5e72e4; - font-size: 2rem; -} - -.main>.loading>span>.loading-img:before { - content: "\e603"; -} - -.main>.loading>span>.loading-img { - animation: anim-rotate 2s infinite linear; - margin-right: 0.4rem; - display: inline-block; -} - -.main>.main-right>.login-bg { - display: none; -} - -@keyframes anim-rotate { - 0% { - -webkit-transform: rotate(0); - -ms-transform: rotate(0); - transform: rotate(0); - } - - 100% { - -webkit-transform: rotate(360deg); - -ms-transform: rotate(360deg); - transform: rotate(360deg) - } -} - -[id^="cbi-apply-"] { - position: fixed; - z-index: 200; - width: 20rem; - margin-left: -10rem; - margin-top: -5rem; - height: 10rem; - left: 50%; - top: 50%; - font-size: 1.2rem; - border-color: #5e72e4; - text-align: center; -} - -[id^="cbi-apply-"]>.panel-title { - border-bottom: none; -} - -[id^="cbi-apply-"]>[id^="cbi-apply-"] { - position: initial; - width: auto; - height: auto; - font-size: 1rem; - margin-left: 0rem; - margin-top: .8rem; - display: block; -} - -.main-left { - float: left; - width: 15%; - width: calc(0% + 15rem); - height: 100%; - background-color: #172b4d !important; - box-shadow: 0 0 2rem 0 rgba(136, 152, 170, .15); - overflow-x: auto; - position: fixed; - z-index: 100; -} - -.main-left::-webkit-scrollbar { - width: 5px; - height: 1px; -} - -.main-left::-webkit-scrollbar-thumb { - background-color: #f6f9fc -} - -.main-left::-webkit-scrollbar-track { - background-color: #fff; -} - - -.main-right { - width: 85%; - width: calc(100% - 15rem); - float: right; - height: 100%; - background-color: #ffffff; -} - -.main-right>#maincontent { - position: relative; - z-index: 50; -} - -header>.container { - margin-top: 0.5rem; - padding: 0.5rem 1rem 0 1rem; -} - -.cbi-section>h3:first-child { - width: 100%; - display: block; - margin-bottom: 0; - padding: 0.5rem; - border-bottom: 1px solid rgba(0, 0, 0, .05); - background-color: #fff; - line-height: 1.5; - margin-bottom: 0rem; - letter-spacing: 0.1rem; - color: #32325d; - font-weight: bold; - font-size: 0.8rem; -} - -.panel-title { - font-size: 1.2rem; - width: 100%; - display: block; - margin-bottom: 0; - padding: 1.25rem 1.5rem; - border-bottom: 1px solid rgba(0, 0, 0, .05); - line-height: 1.5; - margin-bottom: 0rem; - letter-spacing: 0.1rem; - color: #32325d; - font-weight: bold; -} - -table { - border-spacing: 0; - border-collapse: collapse; -} - -table, -.table { - width: 100%; -} - -table>tbody>tr>td, -table>tbody>tr>th, -table>tfoot>tr>td, -table>tfoot>tr>th, -table>thead>tr>td, -table>thead>tr>th, -.table>.tbody>.tr>.td, -.table>.tbody>.tr>.th, -.table>.tfoot>.tr>.td, -.table>.tfoot>.tr>.th, -.table>.thead>.tr>.td, -.table>.thead>.tr>.th { - padding: .5rem; - border-top: 1px solid #ddd; - white-space: nowrap; -} - -.cbi-section-table-cell { - white-space: nowrap; - align-self: flex-end; - flex: 1 1 auto; -} - -.cbi-section-table { - border: none; - margin: 0 !important; -} - - -.cbi-section-table-row:last-child { - margin-bottom: 0; -} - -.cbi-section-table-row>.cbi-value-field .cbi-input-select, -.cbi-section-table-row>.cbi-value-field .cbi-input-text, -.cbi-section-table-row>.cbi-value-field .cbi-input-password, -.cbi-section-table-row>.cbi-value-field .cbi-dropdown { - width: 100%; -} - -.cbi-section-table-row>.cbi-value-field [data-dynlist]>input, -.cbi-section-table-row>.cbi-value-field input.cbi-input-password { - width: calc(100% - 1.5rem); -} - -div>table>tbody>tr:nth-of-type(2n), -div>.table>.tbody>.tr:nth-of-type(2n) { - /* background-color: #f9f9f9; */ -} - -div>table>tbody>tr:nth-of-type(2n), -div>.table>.tbody>.tr:nth-of-type(2n) { - /* background-color: #f9f9f9; */ -} - -.danger { - background-color: #f5365c !important; - color: #fff; -} - -.warning { - background-color: #ffd600 !important; - color: #f00; -} - -.notice { - background: linear-gradient(87deg, #5e72e4 0, #825ee4 100%) !important; - color: #fff !important; -} - -.success { - background-color: #ffffff !important; - color: #525f7f; -} - -.alert-message { - /* margin: 5rem 0 0 0 !important; - color: #5e72e4 !important; */ -} - -.errorbox, -.alert-message { - /* margin: 2rem 0 0 0; */ - padding: 2rem; - border: 0; - font-weight: normal; - font-style: normal; - line-height: 1.5em; - font-family: inherit; - min-width: inherit; - overflow: auto; - border-radius: 0.3rem; - background-color: #ffd600; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .16), 0 0 2px 0 rgba(0, 0, 0, .12); -} - -.errorbox { - color: #fff; - background-color: #f0ad4e; - border-color: #eea236; -} - -.error { - color: red; -} - -.main>.main-left>.sidenav-header { - padding: 1.5rem; -} - -.main>.main-left>.sidenav-header>.brand { - font-size: 1.8rem; - color: #5e72e4; - font-family: "TypoGraphica"; - text-decoration: none; - padding-left: 2rem; - cursor: default; - vertical-align: text-bottom; - white-space: nowrap; -} - -.main>.main-left>.nav { - margin-top: 0.5rem; -} - -.main>.main-left>.nav>li a { - color: #8898aa; - display: block; -} - -.main>.main-left>.nav>li:nth-last-child(1) { - margin-top: 2rem; - font-size: 1.2rem; -} - -.main>.main-left>.nav>li:nth-last-child(1)>.menu:after { - content: ""; -} - -.main>.main-left>.nav>li { - padding: 0.5rem 1rem; - cursor: pointer; -} - -.main>.main-left>.nav>.slide { - padding: 0; -} - -.main>.main-left>.nav>.slide>ul { - display: none; -} - -.main>.main-left>.nav>.slide>.menu { - display: block; - margin: 0.1rem .5rem 0.1rem .5rem; - padding: .675rem 0 .675rem 3rem; - border-radius: .375rem; - text-decoration: none; - cursor: default; - font-size: 1rem; - transition: all 0.2s; - position: relative; -} - -.main>.main-left>.nav>li:hover, -.main>.main-left>.nav>.slide>.menu:hover { - cursor: pointer; - color: #fff; -} - -.main>.main-left>.nav>.slide:hover { - background: none; - -} - -.main>.main-left>.nav>.slide>.menu:hover {} - -.main>.main-left>.nav>.slide>.menu:before { - font-family: 'ssr' !important; - speak: none; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - - /* Better Font Rendering =========== */ - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - position: absolute; - left: 1.3rem; - padding-top: 3px; -} - -.main>.main-left>.nav>.slide>.menu[data-title=Status]:before { - content: "\e906"; - color: #4fc352 !important; -} - -.main>.main-left>.nav>.slide>.menu[data-title=System]:before { - content: "\e90a"; - color: #fb6340 !important; -} - -.main>.main-left>.nav>.slide>.menu[data-title=Services]:before { - content: "\e909"; - color: #11cdef !important; -} - -.main>.main-left>.nav>.slide>.menu[data-title=NAS]:before { - content: "\e90c"; - color: #f3a4b5 !important; -} - -.main>.main-left>.nav>.slide>.menu[data-title=Control]:before { - content: "\e90e"; - color: #f3a4b5 !important; -} - -.main>.main-left>.nav>.slide>.menu[data-title=VPN]:before { - content: "\e90b"; - color: #172b4d !important; -} - -.main>.main-left>.nav>.slide>.menu[data-title=Network]:before { - content: "\e908"; - color: #8965e0 !important; -} - -.main>.main-left>.nav>.slide>.menu[data-title=Bandwidth_Monitor]:before { - content: "\e90d"; - color: #5e72e4 !important; -} - -.main>.main-left>.nav>.slide>.menu[data-title=Logout]:before { - content: "\e907"; - color: #32325d !important; -} - -.main>.main-left>.nav>.slide>.menu:after { - position: absolute; - right: 0.5rem; - top: 0.8rem; - font-family: 'icomoon' !important; - speak: none; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - - /* Better Font Rendering =========== */ - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - content: '\e900'; - transition: all .15s ease; - color: #ced4da; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - transition: all 0.3s; -} - -header>.fill { - padding: 0.8rem 0; -} - -header>.fill>.container { - height: 2rem; - padding: 0 1rem; - -} - -header>.fill>.container>.brand { - font-size: 1.5rem; - color: #fff; - font-family: "TypoGraphica"; - text-decoration: none; - padding-left: 1rem; - cursor: default; - vertical-align: text-bottom; - display: none; -} - -.main>.main-left>.nav>.slide>.menu.active { - color: #fff; - background: #7764e4; -} - -.main>.main-left>.nav>.slide>.menu.active:after { - color: #4fc352; - transform: rotate(90deg); -} - -.main>.main-left>.nav>.slide>.slide-menu>li {} - -.main>.main-left>.nav>.slide>.slide-menu>.active { -} - -.main>.main-left>.nav>.slide>.slide-menu>li>a { - margin: 0.1rem .5rem 0.1rem 0.5rem; - padding: 0.5rem 1.5rem 0.5rem 3rem; - text-decoration: none; - white-space: nowrap; - color: #8699ad; - transition: all 0.2s; - border-radius: .375rem; -} - -.main>.main-left>.nav>.slide>.slide-menu>.active>a { - background-color: #5e72e4; - color: #fff; -} - -.main>.main-left>.nav>.slide>.slide-menu>li>a:hover { - background-color: #5e72e4; - color: #fff; -} - -.main>.main-left>.nav>.slide>.slide-menu>.active>a:hover { - background-color: #5e72e4; - color: #fff; -} - -li { - list-style-type: none; -} - -#maincontent>.container { - margin: 0 2rem 1rem 2rem; -} - -h1 { - font-size: 2rem; - padding-bottom: 10px; - border-bottom: 1px solid #eee; -} - -h2 { - margin: 0 0 0 0; - font-size: 1.5rem; - padding: 1rem 0 !important; - color: #000; -} - -#cbi-dropbear h2, -#cbi-dropbear .cbi-map-descr, -#cbi-dropbear .cbi-map-descr abbr, -#cbi-rc h2, -#cbi-rc .cbi-map-descr, -#cbi-distfeedconf h2, -#cbi-distfeedconf .cbi-map-descr, -#cbi-customfeedconf h2, -#cbi-customfeedconf .cbi-map-descr { - color: #32325d !important; -} - -h3 { - font-size: 1.4rem; - width: 100%; - display: block; - margin-bottom: 0; - padding: 1.25rem 1.5rem; - padding-bottom: 10px; - line-height: 1.5; - margin-bottom: 0rem; - letter-spacing: 0.1rem; - color: #32325d; - font-weight: bold; -} - -h4 {} - -div.cbi-section, -fieldset { - margin: 10px 0; - padding: 1rem; - font-weight: normal; - font-style: normal; - line-height: 1; - font-family: inherit; - min-width: inherit; - /* overflow-x: auto; - overflow-y: hidden; */ - border: 1px solid rgba(0, 0, 0, .05); - border-radius: .375rem; - background-color: #fff; - box-shadow: 0 0 2rem 0 rgba(136, 152, 170, .15); - -webkit-overflow-scrolling: touch; -} - - - -fieldset>legend { - display: none !important; -} - -div.cbi-section>div.cbi-section, -fieldset>fieldset { - margin: 0; - padding: 0; - border: none; - box-shadow: none; -} - -fieldset.cbi-section p { - padding: 1em; -} - -.panel-title { - width: 100%; - display: block; - margin-bottom: 0; - padding: 0.5rem; - border-bottom: 1px solid rgba(0, 0, 0, .05); - background-color: #fff; - line-height: 1.5; - margin-bottom: 0rem; - letter-spacing: 0.1rem; - color: #32325d; - font-weight: bold; - font-size: 0.8rem; -} - -.table, -table { - border-spacing: 0; - border-collapse: collapse; - width: 100%; - border: 1px solid #eee; - display: table; - margin: 0 0 10px !important; - position: relative; -} - -.table>.tr>.td, -table>tbody>tr>td, -table>tfoot>tr>td, -table>thead>tr>td { - font-size: .8125rem; - white-space: nowrap; - color: #525f7f; - padding: 0.5rem; - border-top: 1px solid #f9f9f9; - white-space: nowrap; - line-height: 1.3; -} - -.table>.tr>.th, -table>tbody>tr>th, -table>tfoot>tr>th, -table>thead>tr>th { - - padding-right: 1.5rem; - padding-left: 1.5rem; - color: #8898aa; - background-color: #f6f9fc; - font-size: .65rem; - padding-top: .75rem; - padding-bottom: .75rem; - letter-spacing: 1px; - text-transform: uppercase; - border-bottom: 1px solid #e9ecef; -} - -.cbi-section-table-cell { - text-align: center; -} - -.cbi-section-table-row { - text-align: center; -} - -fieldset>table>tbody>tr:nth-of-type(2n) { - /* background-color: #f9f9f9; */ -} - -.cbi-section-create { - margin: .5rem -3px; - display: inline-flex; - align-items: center; - padding-left: 1rem; -} - -/* fix multiple table */ - -table table { - border: none; -} - -.cbi-value-field table { - border: none; -} - -td>table>tbody>tr>td { - border: none; -} - -.cbi-value-field>table>tbody>tr>td { - border: none; -} - - - -/* button style */ - -.cbi-button { - -webkit-appearance: none; - text-transform: uppercase; - /* height: 2.5rem; - line-height: 2.5rem; */ - color: rgba(0, 0, 0, 0.87); - background-color: #F0F0F0; - transition: all 0.2s ease-in-out; - display: inline-block; - padding: 0 0.8rem; - /* border: none; */ - border-radius: 0.2rem; - cursor: pointer; - -ms-touch-action: manipulation; - touch-action: manipulation; - background-image: none; - text-align: center; - vertical-align: middle; - white-space: nowrap; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - font-size: 0.8rem; - width: auto !important; - margin-left: 0.3em; -} - -.cbi-button:hover, -.cbi-button:focus, -.cbi-button:active { - outline: 0; - text-decoration: none; -} - -.cbi-button:hover, -.cbi-button:focus { - box-shadow: 0 0px 2px rgba(0, 0, 0, 0.12), 0 2px 2px rgba(0, 0, 0, 0.2); -} - -.cbi-button:active { - box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23); -} - -.cbi-button:disabled { - cursor: not-allowed; - pointer-events: none; - opacity: 0.60; - box-shadow: none; -} - -form.inline+form.inline, -.cbi-button+.cbi-button {} - -.cbi-button-reset, -.cbi-input-remove { - color: #fff !important; - background-color: #f0ad4e !important; - border-color: #eea236 !important; -} - -.cbi-input-find, -.cbi-input-save, -.cbi-button-add, -.cbi-button-save, -.cbi-button-find, -.cbi-input-reload, -.cbi-button-reload { - color: #fff !important; - background-color: #825ee4 !important; - border-color: #825ee4 !important; -} - -.cbi-value-field .cbi-input-apply, -.cbi-button-apply, -.cbi-button-edit { - color: #fff !important; - background: linear-gradient(87deg, #5e72e4 0, #825ee4 100%); -} - - -.cbi-section-remove>.cbi-button, -.cbi-button-remove { - color: #fff !important; - background-color: #fb6340 !important; - border-color: #fb6340 !important; -} - -.cbi-value-field .cbi-button-add, -.cbi-value-field .cbi-button-remove, -.cbi-value-field .cbi-button-neutral {} - -input[type="text"]+.cbi-button, -input[type="password"]+.cbi-button, -select+.cbi-button { - padding: 4px 8px; -} - - -/* table */ - -.tabs { - margin: 0.5rem 0rem; - padding-left: 1rem; - background-color: #FFFFFF; - border-radius: 0.375rem; -} - -.cbi-tabmenu>li, -.tabs>li { - font-size: 1rem; - /* border-top-left-radius:0.25rem; */ - /* border-top-right-radius:0.25rem; */ - display: inline-block; - padding: 0.6rem; -} - -.cbi-tabmenu>li { - background: #adb5bd; -} - -.cbi-tabmenu>li>a, -.tabs>li>a { - text-decoration: none; - color: #404040; - padding: 0.5rem 0.8rem; -} - -.cbi-tabmenu>li>a { - color: #fff; -} - -.cbi-dropdown { - display: inline-flex; - cursor: pointer; - position: relative; - padding: 0; - height: auto; -} - -.cbi-dropdown:focus { - outline: 2px solid #4b6e9b; -} - -.cbi-dropdown>ul { - margin: 0 !important; - padding: 0; - list-style: none; - overflow-x: hidden; - overflow-y: auto; - display: flex; - width: 100%; -} - -.cbi-dropdown>ul.preview { - display: none; -} - -.cbi-dropdown>.open { - border: 0px outset #eee; - flex-basis: 15px; - background: #fff; -} - -.cbi-dropdown>.open, -.cbi-dropdown>.more { - flex-grow: 0; - flex-shrink: 0; - display: flex; - flex-direction: column; - justify-content: center; - text-align: center; - line-height: 2em; - padding: 0 .25em; -} - -.cbi-dropdown>.more, -.cbi-dropdown>ul>li[placeholder] { - color: #777; - font-weight: bold; - text-shadow: 1px 1px 0px #fff; - display: none; -} - -.cbi-dropdown>ul>li { - display: none; - padding: .25em; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - flex-shrink: 1; - flex-grow: 1; - align-items: center; - align-self: center; - min-height: 20px; -} - -.cbi-dropdown>ul>li .hide-open { - display: initial; -} - -.cbi-dropdown>ul>li .hide-close { - display: none; -} - -.cbi-dropdown>ul>li[display]:not([display="0"]) { - border-left: 1px solid #ccc; -} - -.cbi-dropdown[empty]>ul { - max-width: 1px; -} - -.cbi-dropdown>ul>li>form { - display: none; - margin: 0; - padding: 0; - pointer-events: none; -} - -.cbi-dropdown>ul>li img { - vertical-align: middle; - margin-right: .25em; -} - -.cbi-dropdown>ul>li>form>input[type="checkbox"] { - margin: 0; - height: auto; -} - -.cbi-dropdown>ul>li input[type="text"] { - height: 20px; -} - -.cbi-dropdown[open] { - position: relative; - border-color: #5e72e4; -} - -.cbi-dropdown[open]>ul.dropdown { - display: block; - background: #fff; - position: absolute; - z-index: 1000; - max-width: none; - min-width: 100%; - width: auto; - box-shadow: 0 1px 3px rgba(50, 50, 93, .15), 0 1px 0 rgba(0, 0, 0, .05); -} - -.cbi-dropdown>ul>li[display], -.cbi-dropdown[open]>ul.preview, -.cbi-dropdown[open]>ul.dropdown>li, -.cbi-dropdown[multiple]>ul>li>label, -.cbi-dropdown[multiple][open]>ul.dropdown>li, -.cbi-dropdown[multiple][more]>.more, -.cbi-dropdown[multiple][empty]>.more { - flex-grow: 1; - display: flex; - align-items: center; -} - -.cbi-dropdown[empty]>ul>li, -.cbi-dropdown[optional][open]>ul.dropdown>li[placeholder], -.cbi-dropdown[multiple][open]>ul.dropdown>li>form { - display: block; -} - -.cbi-dropdown[open]>ul.dropdown>li .hide-open { - display: none; -} - -.cbi-dropdown[open]>ul.dropdown>li .hide-close { - display: initial; -} - -.cbi-dropdown[open]>ul.dropdown>li { - border-bottom: 1px solid #ccc; - color: #000; -} - -.cbi-dropdown[open]>ul.dropdown>li[selected] { - background: linear-gradient(87deg, #5e72e4 0, #825ee4 100%); -} - -.cbi-dropdown[open]>ul.dropdown>li.focus { - background: linear-gradient(90deg, #825ee4 0%, #5e72e4 100%); -} - -.cbi-dropdown[open]>ul.dropdown>li:last-child { - margin-bottom: 0; - border-bottom: none; -} - -.cbi-dropdown[disabled] { - pointer-events: none; - opacity: .6; -} - -.cbi-dropdown .zonebadge { - width: 100%; -} - -.cbi-dropdown[open] .zonebadge { - width: 100%; -} - -.cbi-dropdown { - font-size: .875rem; - transition: all .15s ease-in-out; - line-height: 1.5; - color: #8898aa; - border: 1px solid #dee2e6; - border-radius: .25rem; - background-color: #fff; - background-clip: padding-box; - box-shadow: 0 3px 2px rgba(233, 236, 239, .05); - margin: 0.25rem; -} - -.cbi-value-field .cbi-dropdown .zonebadge>.ifacebadge { - padding: 0rem 1rem; - margin: 0rem 0.3rem; - border: 1px solid #6C6C6C; -} - -select[multiple="multiple"] { - height: auto; -} - -.cbi-dropdown>ul { - margin: 0 !important; - padding: 0; - list-style: none; - overflow-x: hidden; - overflow-y: hidden; - display: flex; - width: 100%; -} - -/* select */ -.cbi-value-field .cbi-dropdown { - min-width: 15rem; -} - -.cbi-section>legend { - display: none !important; -} - -.tabs>li[class~="active"], -.tabs>li:hover { - cursor: pointer; - margin-bottom: 0; - background: linear-gradient(87deg, #5e72e4 0, #825ee4 100%); -} - -.tabs>li[class~="active"] > a, -.tabs>li:hover > a { - color: #fff; -} - -.cbi-tabmenu { - color: white; - /* padding: 0.5rem 1rem 0 1rem; */ -} - -.cbi-tabmenu>li:hover { - background-color: #F1F1F1; -} - -.cbi-tabmenu>li:hover>a { - color: #525f7f; -} - -.cbi-tabmenu>li[class~="cbi-tab"] { - background: linear-gradient(87deg, #5e72e4 0, #825ee4 100%); -} - -.cbi-tabmenu>li[class~="cbi-tab"]>a { - color: #fff; -} - - - -.cbi-section-remove:nth-of-type(2n), -.cbi-section-node:nth-of-type(2n) { - /* background-color: #f9f9f9; */ -} - -.cbi-section-node-tabbed { - padding: 0; - margin-top: 0; - -} - -.cbi-section-node { - background: #fff; - border: 0; - border-radius: .375rem; - margin-bottom: 0px; - box-shadow: 0 0 0rem 0 rgba(136, 152, 170, .15); - overflow-x: auto; - overflow-y: hidden; - padding: 0rem 0; -} - -#cbi-network-lan.cbi-section-node { - overflow-x: visible; - overflow-y: visible; -} - -#cbi-network .cbi-section, -#cbi-network .cbi-section .cbi-section-node {} - -.cbi-section-node .cbi-value { - /* padding: 0.3rem 0rem 0.3rem 1rem; -*/ -} - - -.cbi-tabcontainer>.cbi-value:nth-of-type(2n) { - /* background-color: #f9f9f9; */ -} - -.cbi-value-field { - display: table-cell; - /* line-height: 1.25; */ - padding-top: 0.5em; -} - -.cbi-value-helpicon>img { - display: none; -} - -.cbi-value-helpicon:before { - content: "\f059"; -} - -.cbi-value-description { - font-size: small; - opacity: 0.8; - display: unset; -} - -.cbi-value-title { - display: table-cell; - text-align: right; - width: 23rem; - line-height: unset; - padding-top: 0.5em; - margin-right: 1.5em; - float: left; - color: #404040; -} - -/* -.cbi-value-title { - word-wrap: break-word; - font-size: 0.875rem; - line-height: 1.6; - color: #525f7f; - padding: .7rem; - padding-left:0; - width: 23rem; - float: left; - text-align: right; - display: table-cell; -} -*/ - -.cbi-value { - /* margin-bottom: 0.1em; */ - display: inline-block; - width: 100%; - clear: both; -} - -.cbi-section-table-descr>.cbi-section-table-cell, -.cbi-section-table-titles>.cbi-section-table-cell { - border: none; -} - -.cbi-rowstyle-1 { - background-color: #fff; -} - -.cbi-rowstyle-2 { - background-color: #fefefe; -} - -/* desc */ -.cbi-section-descr { - padding: 1rem 0 1rem 2rem; - font-size: 0.7rem; - font-weight: 600; - color: #525f7f; -} - -.cbi-map-descr { - padding: 0rem 0 1rem 0rem; - color: #000; - font-size: small; -} - -/* luci */ - -.hidden { - display: none -} - -.left { - text-align: left !important; -} - -.right { - text-align: right !important; -} - -.inline { - display: inline; -} - -input[type="checkbox"] { - height: auto; -} - -/* select */ - - -.cbi-value-field .ifacebadge { - display: inline-flex; - /* border-bottom: 0px solid #CCCCCC; */ - padding: 0.5rem 1rem; - box-shadow: none; -} - -td>.ifacebadge { - background-color: #F0F0F0; - font-size: 0.9rem; -} - -.ifacebadge>img { - float: right; - margin: 0 0.3rem; -} - -/*textarea*/ - -.cbi-input-textarea { - width: 100%; - resize: none; - outline: none; - min-height: 14rem; - padding: 0.8rem; - font-size: 0.8rem; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - color: black; - border-radius: 0.25rem; -} - -#syslog { - width: 100%; - min-height: 15rem; - padding: 1rem; - font-size: small; - color: #5F5F5F; - border-radius: 0; - background-color: #FFF; - border: none; - outline: none; -} - -/* change */ - -.uci-change-list { - - font-family: monospace; -} - -.uci-change-list ins strong { - display: inline; -} - -.uci-change-list ins, -.uci-change-legend-label ins { - text-decoration: none; - border: 1px solid #00FF00; - background-color: #CCFFCC; - display: block; - padding: 0 1rem; - margin: 0.5rem 0; -} - -.uci-change-list del, -.uci-change-legend-label del { - text-decoration: none; - border: 1px solid #FF0000; - background-color: #FFCCCC; - display: block; - font-style: normal; - padding: 2px; -} - -.uci-change-list var, -.uci-change-legend-label var { - text-decoration: none; - border: 1px solid #CCCCCC; - background-color: #CCFFCC; - display: block; - font-style: normal; - padding: 2px; -} - -.uci-change-list var ins, -.uci-change-list var del { - border: none; - white-space: pre; - font-style: normal; - padding: 0px; -} - -.uci-change-legend { - padding: 5px 2rem; -} - - - - -.uci-change-legend-label var ins, -.uci-change-legend-label var del { - line-height: 6px; - border: none; -} - -.uci-change-list var, -.uci-change-list del, -.uci-change-list ins { - padding: 0.5rem; -} - -/* other fix */ - - -.ifacebadge { - display: inline-flex; - border-bottom: 1px solid #CCCCCC; - padding: 0.5rem 1rem; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -} - -td>.ifacebadge { - background-color: #F0F0F0; - font-size: 0.9rem; -} - -.ifacebadge>img { - float: right; - margin: 0 0.3rem; -} - -.ifacebox { - text-align: center; - margin-right: 60px; -} - -.ifacebox .ifacebox-head { - border-bottom: 1px solid #ccc; - padding: 2px; - background: #eee; -} - -.ifacebox .ifacebox-head.active { - background: linear-gradient(87deg, #5e72e4 0, #825ee4 100%)!important; - color: #fff; -} - -.ifacebox .ifacebox-body { - border: 2px solid #f2f2f2; - border-top: 0; - border-radius: 0 0 4px 4px; - padding: 2px 10px; -} - -.network-status-table .ifacebox-body { - display: flex; - flex-direction: column; - height: 100%; - text-align: left; -} - -.network-status-table .ifacebox { - margin: .5em; - flex-grow: 1; -} - -.ifacebox .ifacebox-body { - padding: .25em; -} - -.ifacebox { - background-color: #fff; - border: 1px solid #ccc; - margin: 0 10px; - text-align: center; - white-space: nowrap; - background-image: linear-gradient(#fff, #fff 25%, #f9f9f9); - text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); - border-radius: 4px; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - display: inline-flex; - flex-direction: column; - line-height: 1.2em; - min-width: 100px; -} - -.ifacebadge { - display: inline-block; - flex-direction: row; - white-space: nowrap; - background-color: #fff; - border: 1px solid #ccc; - padding: 2px; - background-image: linear-gradient(#fff, #fff 25%, #f9f9f9); - text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); - border-radius: 4px; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - cursor: default; - line-height: 1.2em; -} - -.ifacebadge.large, -.network-status-table .ifacebox-body .ifacebadge { - display: inline-flex; - flex: 1; - padding: .25em; - min-width: 220px; - margin: .125em; - float: left; -} - -.ifacebadge img { - width: 16px; - height: 16px; - vertical-align: middle; -} - -.ifacebadge>*, -.ifacebadge.large>* { - margin: 0 .125em; -} - -.ifacebadge>*, -.ifacebadge.large>* { - margin: 0 .125em; -} - -.network-status-table { - display: flex; - flex-wrap: wrap; -} - -.cbi-tooltip { - position: absolute; - z-index: 1000; - left: -1000px; - opacity: 0; - transition: opacity .25s ease-out; -} - -.cbi-image-button { - margin-left: 0.5rem; -} - -#iwsvg, -#iwsvg2, -#bwsvg { - border: none !important; - border-radius: 0.375rem; - box-shadow: 0 0 2rem 0 rgba(136, 152, 170, .15); - overflow: hidden; -} - - - -.cbi-image-button { - margin-left: 0.5rem; -} - -.zonebadge { - display: inline-block; - border-radius: 4px; - color: #000; - white-space: nowrap; - padding: 0 8px; - cursor: pointer; -} - -.zonebadge em, -.zonebadge strong { - margin: 0 5px; - color: #000; -} - -.zonebadge>.ifacebadge { - display: inline-block; - flex-direction: row; - white-space: nowrap; - background-color: #3c3a38; - border: 1px solid #ccc; - padding: 2px; - text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); - border-radius: 4px; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - cursor: default; - line-height: 1.2em; -} - -.zonebadge>input[type="text"] { - padding: 0.16rem 1rem; - min-width: 10rem; - margin-top: 0.3rem; -} - -.cbi-value-field .cbi-input-checkbox, -.cbi-value-field .cbi-input-radio { - /* margin-top: 0.9rem; */ - height: 1rem; -} - -input[type=checkbox], -input[type=radio] { - width: auto; - margin: 0; - vertical-align: middle; - cursor: pointer; -} - -.cbi-value-field>input+.cbi-value-description { - padding: 0; -} - -.cbi-value-field>ul>li { - display: flex; -} - -.cbi-value-field>ul>li>label { - margin-top: -0.1rem; -} - -.cbi-value-field>ul>li .ifacebadge { - background-color: #eee; - margin-left: 0.4rem; - margin-top: -0.5rem; -} - -.cbi-section-table-row>.cbi-value-field .cbi-input-select { - min-width: 7rem; -} - -.cbi-section-create>.cbi-button-add { - margin: 0.5rem; -} - -.cbi-section-remove { - padding: 0.5rem; -} - -div.cbi-value var, -td.cbi-value-field var { - font-style: italic; - color: #0069D6; -} - -small { - font-size: 90%; - white-space: normal; - line-height: 1.42857143; -} - - -.cbi-optionals { - padding: 1rem 1rem 0 1rem; - border-top: 1px solid #CCC; -} - - -input[name="ping"], -input[name="traceroute"], -input[name="nslookup"] { - width: 80%; -} - -header>.container>.pull-right>* { - position: relative; - top: 0.45rem; - cursor: pointer; -} - - -.label { - padding: 0.3rem 0.8rem; - font-size: 0.8rem; - font-weight: bold; - color: #fff !important; - text-transform: uppercase; - white-space: nowrap; - background-color: #32325d; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - text-shadow: none; - text-decoration: none; -} - - - -.showSide { - display: none; - color: #fff; - font-size: 1.4rem; -} - -.darkMask { - width: 100%; - height: 100%; - position: fixed; - background-color: rgba(0, 0, 0, 0.56); - z-index: 99; - left: 0; - top: 0; - display: none; -} - -/* fix Main Login*/ -.node-main-login>.main>.main-right>header { - background: none !important; - box-shadow: none !important; - display: none; -} - -.node-main-login>.main>.main-right>header>.fill>.container { - margin: 2rem auto; - max-width: 1140px; -} - -.node-main-login>.main>.main-right>header>.fill>.container>.brand { - font-size: 2rem; - color: #5e72e4; - display: none; - -} - -.node-main-login>.main { - top: 0; - height: 100% !important; -} - -.node-main-login>.main>.main-left { - display: none; -} - -.node-main-login>.main>.main-right { - width: 100%; -} - -.node-main-login>.main>.main-right>.login-bg { - display: block; - position: fixed; - width: 100%; - height: 100%; - left: 0px; - top: 0px; - background-size: cover; - background-color: #000; - background-position: top center; - transition: all 0.5s; -} - -.node-main-login>.main>.main-right>.login-bg.blur { - transform: scale(1.05); - -webkit-filter: blur(5px); - /* Chrome, Safari, Opera */ - filter: blur(5px); -} - -.node-main-login>.main>.main-right>#maincontent { - padding-top: 23vh; - height: 100%; - background-color: transparent !important; - margin-top: 0rem; -} - -.node-main-login>.main fieldset, -.node-main-login>.main .cbi-section, -.node-main-login>.main .cbi-section>.cbi-section-node { - padding: 0.5rem; - margin: 0rem; - /* display: inline; */ - background: none; - border: none; - box-shadow: none; - overflow: hidden; -} - -.node-main-login>.main .cbi-value-title { - font-size: 1rem; - line-height: 1.5; - color: #525f7f; - padding: .625rem; -} - -.node-main-login>.main #maincontent { - - text-align: center; -} - -.node-main-login>.main .container { - display: inline-block; - padding: 2rem 2rem; - position: relative; - margin-top: 2rem !important; - background-color: #f7fafc !important; - border-radius: .375rem; - box-shadow: 0 0 2rem 0 rgba(136, 152, 170, .15); - text-align: left; -} - -.node-main-login>.main .container h2 { - width: 120px; - height: 120px; - color: #fff; - text-align: center; - letter-spacing: 4px; - display: block; - margin: -100px auto 15px auto; - padding: 0; - text-indent: -500px; - overflow: hidden; - border-radius: 60px; - border: #fff 3px solid; - - background-image: url(../logo.png); - background-size: cover; - box-shadow: 0 4px 20px 0px rgba(0, 0, 0, 0.14), 0 7px 10px -5px rgba(156, 39, 176, 0.4); - -} - -.node-main-login>.main .container .cbi-map-descr { - text-align: center; - padding: 1rem; - color: #8898aa; -} - -.node-main-login>.main .container .cbi-section-node { - padding: 0; -} - - -.node-main-login>.main .container .cbi-value-field input { - font-size: 1rem; - line-height: 1.5; - display: block; - width: 100%; - height: calc(2.75rem + 2px); - padding: .625rem .75rem; - transition: all .15s cubic-bezier(.68, -.55, .265, 1.55); - color: #8898aa; - border: 0px solid #dee2e6; - border-radius: .25rem; - background-color: #fff; - background-clip: padding-box; - box-shadow: 0 3px 2px rgba(233, 236, 239, .05); -} - -.node-main-login>.main .container .cbi-value-field input:focus { - color: #8898aa; - - outline: 0; - background-color: #fff; - box-shadow: 0 3px 9px rgba(50, 50, 9, 0), 3px 4px 8px rgba(94, 114, 228, .1) -} - -.node-main-login>.main .container input.cbi-button { - font-size: 1rem; - height: auto; - position: relative; - transition: all .15s ease; - letter-spacing: .2em; - text-transform: none; - padding: .625rem 1.25rem; - will-change: transform; - line-height: 1.5em; -} - -.node-main-login>.main form>div:nth-last-child(1) { - text-align: center; - border-top: 0; - padding-top: 2rem; -} - -.node-main-login>.main .cbi-value { - display: block; - padding: 0; -} - - -.node-main-login>.main .cbi-value>* { - display: inline-block !important; -} - -.node-main-login>.main .cbi-value:first-child, -.node-main-login>.main .cbi-button-reset { - display: none !important; -} - - -.node-main-login>.main .cbi-value.cbi-value-last .cbi-value-title { - display: none !important; -} - -.node-main-login>.main .cbi-value.cbi-value-last .cbi-input-text { - box-shadow: 0 1px 3px rgba(50, 50, 93, .15), 0 1px 0 rgba(0, 0, 0, .02); - transition: box-shadow .15s ease; - border-radius: .375rem; - box-sizing: border-box; - padding-left: 3em; - margin: 0; -} - -.node-main-login>.main .cbi-value.cbi-value-last .cbi-input-password, -.node-main-login>.main .cbi-value.cbi-value-last .cbi-input-text[type="password"] { - box-shadow: 0 1px 3px rgba(50, 50, 93, .15), 0 1px 0 rgba(0, 0, 0, .02); - transition: box-shadow .15s ease; - border-radius: .375rem; - box-sizing: border-box; - padding-left: 3em; - margin: 0; -} - -.node-main-login>.main .cbi-value.cbi-value-last .cbi-value-field { - position: relative; - width: 20rem; -} - -.node-main-login>.main .cbi-value.cbi-value-last .cbi-value-field:before { - font-family: 'icomoon' !important; - speak: none; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - content: "\e901"; - color: #adb5bd; - font-size: 1.5rem; - position: absolute; - z-index: 100; - left: 10px; - top: 10px; -} - -.node-main-login>.main .cbi-input-user, -.node-main-login>.main .cbi-input-password, -.node-main-login>.main .cbi-input-text[type="user"], -.node-main-login>.main .cbi-input-text[type="password"] { - min-width: 15rem; -} - -.node-main-login .errorbox, -.node-main-login .alert-message.warning { - position: absolute; - color: #fff; - width: calc(100% - 4rem); - border-color: #eea236; - box-sizing: border-box; - margin-top: 8rem; - border-radius: 5px; - padding: 1rem 2rem; - text-align: center; - background-color: #8965e0 !important; - -} - -.node-main-login footer { - bottom: 0; - position: absolute; - width: 100%; - color: #fff; -} - -.node-main-login footer>a { - color: #fff; -} - -/* fix status overview */ - -.node-status-overview>.main fieldset:nth-child(4) td:nth-child(2) { - white-space: normal; -} - -/* fix status processes */ - -.node-status-processes>.main table tr td:nth-child(3) { - white-space: normal; -} - -.node-status-iptables>.main div>.cbi-map>form { - margin: 0.5rem 2rem 0 0; -} - -/* fix system reboot */ - -.node-system-reboot>.main>.main-right p, -.node-system-reboot>.main>.main-right h3 { - padding-left: 2rem; - color: #fff; -} - -/* fix Services Network Shares*/ -.node-services-samba>.main .cbi-tabcontainer:nth-child(3) .cbi-value-title { - margin-bottom: 1rem; - width: auto; -} - -.node-services-samba>.main .cbi-tabcontainer:nth-child(3) .cbi-value-field { - display: list-item; -} - -.node-services-samba>.main .cbi-tabcontainer:nth-child(3) .cbi-value-description { - padding-top: 1rem; -} - -/* fix System Software*/ -.node-system-packages>.main table tr td:nth-child(1) { - width: auto !important; -} - -.node-system-packages>.main table tr td:nth-last-child(1) { - white-space: normal; - font-size: small; - color: #404040; -} - -.node-system-packages>.main .cbi-tabmenu>li>a, -.tabs>li>a { - padding: 0.5rem 0.8rem; -} - -.node-system-packages>.main .cbi-value>pre { - background-color: #eee; - padding: 0.5rem; - overflow: auto; -} - -.cbi-tabmenu+.cbi-section { - margin-top: 0; -} - -.cbi-section { - /* background: #fff; - border: 0; - border-radius: .375rem; - margin-bottom: 30px; - box-shadow: 0 0 2rem 0 rgba(136,152,170,.15); - overflow-x: auto; - overflow-y:hidden; -*/ -} - -.cbi-section em { - padding: 0rem 1.5rem; - font-size: 0.7rem; - font-weight: 600; - color: #525f7f; -} - - -#cbi-system-led em { - /* padding :0.75rem 1.5rem; */ -} - -.cbi-section h4 { - /* padding :0.75rem 1.5rem; */ - font-size: 0.7rem; - font-weight: 600; - color: #525f7f; -} - -.node-main-login .cbi-section { - margin-bottom: 0px; - padding-bottom: 0px; -} - -#content_syslog { - border-radius: .375rem; - box-shadow: 0 0 2rem 0 rgba(136, 152, 170, .15); - overflow: hidden; -} - -.node-system-packages .cbi-section-node .cbi-value { - /* padding: 1rem 1rem; */ -} - -.node-system-packages br { - display: none; -} - -/* fix network firewall*/ -.node-network-firewall>.main .cbi-section-table-row>.cbi-value-field .cbi-input-select { - min-width: 4rem; -} - -.node-status-iptables fieldset, -.node-system-packages fieldset, -.node-system-flashops fieldset { - margin-top: 0; -} - -.node-status-iptables .cbi-tabmenu, -.node-system-packages .cbi-tabmenu, -.node-system-flashops .cbi-tabmenu { - border: none; - /* padding-left: 2rem; */ -} - -.node-system-flashops form.inline+form.inline { - margin-left: 0; -} - - - - -@media screen and (max-width: 1600px) { - .main-left { - width: calc(0% + 13rem); - } - - .main-right { - width: calc(100% - 13rem); - } - - .cbi-button { - /*padding: 0.3rem 1.5rem;*/ - font-size: 0.8rem; - } - - header>.container>.pull-right>* { - top: 0.35rem; - } - - .label { - padding: 0.2rem 0.6rem; - } - - .cbi-value-title { - width: 15rem; - padding-right: 0.6rem; - } - - fieldset { - padding: 0; - } - - .cbi-input-textarea { - font-size: small; - } - - .node-status-iptables>.main fieldset li>a { - padding: 0.3rem 0.6rem; - } -} - -@media screen and (max-width: 1280px) { - - header>.container { - margin-top: 0.25rem; - } - - - .main-left { - width: calc(0% + 13rem); - } - - .main-right { - width: calc(100% - 13rem); - } - - .cbi-tabmenu>li>a, - .tabs>li>a { - padding: 0.2rem 0.5rem; - } - - .panel-title { - font-size: 1.1rem; - padding-bottom: 1rem; - } - - .table, - table { - font-size: 0.7rem !important; - width: 100% !important; - } - - .main>.main-left>.nav>li, - .main>.main-left>.nav>li a, - .main>.main-left>.nav>.slide>.menu { - font-size: 0.9rem; - } - - .main>.main-left>.nav>.slide>.slide-menu>li>a { - font-size: 0.7rem; - } -} - -@media screen and (max-width: 992px) { - .main-left { - width: 0; - position: fixed; - z-index: 100; - } - - .main-right { - width: 100%; - } - - .showSide { - padding: 0.1rem; - position: relative; - z-index: 999; - display: inline-block; - } - - .showSide:before { - content: "\e20e"; - font-size: 1.7rem; - } - - .node-main-login .showSide { - display: none !important; - } - - header>.fill>.container>.brand { - display: inline-block; - } - - .cbi-value-title { - /* width: 9rem; - padding-right: 1rem; */ - } - - .node-network-diagnostics>.main .cbi-map fieldset>div * { - width: 100% !important; - } - - .node-network-diagnostics>.main .cbi-map fieldset>div input[type="text"] { - margin: 3rem 0 0 0 !important; - } - - .node-network-diagnostics>.main .cbi-map fieldset>div:nth-child(4) input[type="text"] { - margin: 0 !important; - } - - .node-network-diagnostics>.main .cbi-map fieldset>div select, - .node-network-diagnostics>.main .cbi-map fieldset>div input[type="button"] { - margin: 1rem 0 0 0; - } - - .node-network-diagnostics>.main .cbi-map fieldset>div { - width: 100% !important; - } - - #diag-rc-output>pre { - font-size: 1rem; - } - - .node-main-login>.main .cbi-value-title { - text-align: left; - } -} - -@media screen and (max-width: 480px) { - body { - font-size: 0.8rem; - } - - div.cbi-section, - fieldset { - padding: 0; - margin: 1rem 0 0 0; - overflow-x: auto; - } - - .tabs { - margin: 0.5rem 0rem - } - - .toggle { - margin: 0; - } - - #maincontent>.container { - margin: 0 1rem 1.5rem 1rem; - } - - .main>.main-left>.nav>.slide>.menu { - font-size: 1rem; - } - - .main>.main-left>.nav>.slide>.slide-menu>li>a { - font-size: 0.9rem; - } - - .main>.main-left>.nav>.slide>.menu:before { - padding-top: 5px; - } - - .main>.main-left>.nav>.slide>.menu:after { - top: 0.9rem; - } - - .cbi-value { - padding: 0.6em 0em; - } - - .cbi-value-title { - width: 40%; - min-width: 0rem !important; - text-align: left; - padding-left: 1em; - } - - - .cbi-value-field, - .cbi-value-description { - width: 95%; - } - - select, - input { - width: 95%; - min-width: unset; - } - - .cbi-value-field .cbi-input-select { - width: 95%; - min-width: unset; - } - - .cbi-value-field .cbi-input-textarea { - width: 95% !important; - min-width: unset; - } - - .cbi-value>.cbi-value-field { - /* display: inline-block; - padding-left: 1rem; */ - - display: table-cell; - width: 20em; - } - - .node-main-login .cbi-value>.cbi-value-field { - width: 18rem; - padding-left: 0rem; - } - - .cbi-tabmenu>li, - .tabs>li { - padding: 0.6rem 0rem; - } - - .cbi-tabmenu>li>a, - .tabs>li>a { - padding: 0.2rem 0.3rem; - font-size: 0.9rem; - } - - .cbi-page-actions>div>input { - display: none; - } - - - - .node-main-login>.main .container { - padding: 0.5rem 1rem 2rem 1rem; - margin: 0 auto !important; - } - - - - .node-main-login>.main form>div:nth-last-child(1) { - margin-top: 0rem; - } - - .node-main-login>.main .cbi-value-title { - width: 100% !important; - margin-top: 0rem; - font-size: 1rem; - margin-bottom: 0; - padding: 0 0.5rem; - } - - .node-main-login>.main fieldset { - margin: 0; - padding: 0.5rem; - } - - .node-main-login .alert-message.warning { - width: calc(100% - 2rem); - padding: 1rem 1rem; - font-size: 12px; - } - - - h2 { - font-size: 1.5rem; - - } - - .node-main-login>.main .container h2 { - - margin: -70px auto 15px auto; - - - } - - .tabs>li>a { - font-size: 0.9rem; - } - - select, - input { - font-size: 0.9rem; - } - - .mobile-hide { - display: none; - } - - .panel-title { - font-size: 1.4rem; - padding-bottom: 1rem; - } - - .node-system-packages>.main .cbi-value.cbi-value-last>div { - width: 100% !important; - } - - .node-system-packages .cbi-section-node .cbi-value { - padding: 0.3rem 1rem; - } - - .node-system-packages>.main .cbi-value .cbi-value-field input { - width: 100%; - } - - .node-status-iptables>.main div>.cbi-map>form { - position: static !important; - margin: 0 0 2rem 0; - padding: 2rem; - border: 0; - font-weight: normal; - font-style: normal; - line-height: 1; - font-family: inherit; - min-width: inherit; - overflow-x: auto; - overflow-y: hidden; - border-radius: 0.375rem; - background-color: #FFF; - box-shadow: 0 0 2rem 0 rgba(136, 152, 170, .15); - -webkit-overflow-scrolling: touch; - } - - .node-status-iptables>.main div>.cbi-map>form input[type="submit"] { - width: 100% !important; - margin: 0; - } - - .node-status-iptables>.main div>.cbi-map>form input[type="submit"]+input[type="submit"] { - margin-top: 1rem; - } -} - -@media screen and (min-width: 992px) { - - .cbi-value input[type="password"], - .cbi-value input[type="text"] { - min-width: 20rem; - } - - .cbi-value-field .cbi-input-select { - min-width: 20rem; - } -} - -@media screen and (min-width: 1280px) { - - .cbi-value input[type="password"], - .cbi-value input[type="text"] { - min-width: 22rem; - } - - .cbi-value-field .cbi-input-select { - min-width: 22rem; - } -} - -@media screen and (min-width: 1600px) { - - .cbi-value input[type="password"], - .cbi-value input[type="text"] { - min-width: 25rem; - } - - .cbi-value-field .cbi-input-select { - min-width: 25rem; - } -} \ No newline at end of file diff --git a/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/favicon.ico b/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/favicon.ico deleted file mode 100644 index 82faa6bf92c4e75e5e2e62a4a6345a0c2cda05f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31346 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 diff --git a/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/TypoGraphica.eot b/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/TypoGraphica.eot deleted file mode 100644 index efce636a84d6da92d5e40498fc945e93a90e4307..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33846 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 M>%j(UEQQ4X1Pp)(oB#j- diff --git a/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/TypoGraphica.svg b/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/TypoGraphica.svg deleted file mode 100644 index c555b7594f..0000000000 --- a/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/TypoGraphica.svg +++ /dev/null @@ -1,1191 +0,0 @@ - - - - -Created by FontForge 20090622 at Tue Jul 23 03:29:07 2019 - By deploy user -TypoGraphica ©Sharkshock Productions 2015. All Rights Reserved - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/TypoGraphica.ttf b/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/TypoGraphica.ttf deleted file mode 100644 index e11f89a0f749b95a9001e33de3100be7a0bb858e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33632 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 diff --git a/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/TypoGraphica.woff b/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/TypoGraphica.woff deleted file mode 100644 index fef38ca003e3d02372d80287057424843e6bd4f0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17816 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 P{|_V(EFb^?vO@>^k62-U diff --git a/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/font.eot b/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/font.eot deleted file mode 100644 index 9e6ffc9b826cb39a58e56359d6b8b922a4b07364..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1912 zcmah~Ur1Y582`?_x%Vc~T>r!*OpT4P8o`m;m_K$==`c84Z6{8{+A(HKZlhvuY>cgr zKFA)%(1*FfM*FnUZZIZ{J&ZBvpfZF#Y)@lIVSRG2hwi1Y4#u`F`<;8QXe6-ja?bgE zzwN>ij! zo>pmzGE@TNr8Jlltw75)0Xj=z>Nm6}M}y=6>u7^S>VN6wGm(a7S2vh%P-e4*%<|74 z-T45bcKGFdW@Q;|Bm8Z&_WaWN)fd`ZeusaHNO&->WpYaP$#+CHu8YruP`(wvhyN-3 z)ANP$nqL?8;r{@?cd3}o2=nYs_)p+_3z@ZLe9%0RR1ZI(XA0Ww7af1Ye-<&`S}v}X zF;AHMCGRIuyn~rYh<#h&Z+ypW*>5z!99(zI7^Yoq=ZPL)7I!PVbY4V3=V9`>F2E}z z8jskHKC=}KRXf?}74Xf-hKS{56ga3mP!HbyReXH8^0ZRngTXngI9B<^|Cj$y|Mga> z;R}pA9?uwniV?%;hGTu$Jc)CL^hp0d9A5GarZvNJ<6ufi3Gpco?d=T-GZmvH1`UH| zm}{8N!4f`UZ>U1NTNno5ddx?}-q;a0gdKdb1FJ*sPETj7DTdm^s|}H!LSzj^@e}6Xo3K zXf!%Jyy+jD4Tn>yMB=%*RO-r=RBGa)o-oe4%#d}+m|4=Q~$QQ44QKuG~z>i4Xv1q8Lj|COk&su!m zB#R{CF*mpnCZx!x7-pM@8!0(V$8jZ+b@ar1M!vd&d^FFaIShFeNRsTjU4j|Sd#3{Z zXChnUcGm@);*d_c-5qUSPhEZ6>5dLdQtxVZJDg384u_&VOeQt$##&BG!nEAl4Grj% zf?bkj$zHI_k|f*NMx?LL=UZ2u=WI$ybv3ANugm3X>D=4hK9vL(>`jZV6X?ab{kvf)^jN}pSC8R2xdumC)3 zVG%fPVH@zOg(aM_9t+FhFId=#{kw^X%;o^2qQ}GnaNfcq@UVq#z&9-{;jj-_SO!03 zVJAiDPgt_+pY=D^L-I_h!b%DZS?d0}MTT%Y6XQicBm D*A6pu diff --git a/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/font.svg b/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/font.svg deleted file mode 100644 index d38d057da3..0000000000 --- a/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/font.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - -Generated by IcoMoon - - - - - - - - - - - - \ No newline at end of file diff --git a/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/font.ttf b/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/font.ttf deleted file mode 100644 index 84669323e9ddfdca80c91416b6d4fe31ea1829ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1748 zcmah}U1%d!6h3n&Gn1cY`jbCwn>0i)RYHn=Nd(_}VjX(rt? z-ECzbiVq^~gR7wIJ}Ik$SP&mXgcU4O@Ijw^C=2dW1t0Wf!4*VZ<9BDKw5tWraPR%j zch0@%%sF?41R`?L28k4Z?)j66)(&?+m@hHriq*pM5AWT1he+s#-Y6GVma(=$zlqge zURuBMOt<$}=(mX2y^2;SDaD815ZSn2x&lJ^TKpFJN6=4Hs*Sav&i0^x2YqmLYKX+Z zh4)?i>i(NQi4QI{A2plC?(n|zF-~ay82lsnd+=JP)cPs*9gSyfz$B1>-K|G#j3{&3 za6R<@9}b5+fwX3MZ5)CURiZq_(cRrqHrq5-65u1iXN>y@0f&$Yu-(xnaWfkO;Qq)* z#NF5yH`q4b*n#elr`Ok;YENPI@o7V(M{qI++s^0z-kX`(%jfy~2$ZLw_^~)dT}1uS z0rN>EGwI<(fDgaVtH^j5jW5RI*{t6`F;QxqJJ%>pOeB+IW1GQ|xmYZh%VeIK&*d&( z&gJGW%*>3B-$2WWnmaZ^=Q=5cP!W|W1*=Ev4Ne;?! z)Dy)zd{P0UUVRb1o7d6YhB`8mB)e{xAja}mPdI)uu{C9PpS39tsmJ39b@_d+maY?_ zkmb_i?(jIA?QIT+qTJ7BHSPLZNy|dC(%N+m=)h}3M^?w~_ggCg@Q$N?gdbxG{B zx-Tq&<|jJo3a&GkgUE(rO)7n2#T7^aXXe0w=PWD&r!8y)UbV1p!rv)lfjj9+m((_t< zWuc~rPsQT+HZ`i#3LId-Ij1N_@nd%#OHOO$)ulomK{X`0N=sCr`mvsqHN6ooYr0l1 zG_+E9emy)@ter=0F`6`DHxRvyV{{{<0yVIfz|GS-<|*R^&YLfQ9MQz1E%`702g#=) A_5c6? diff --git a/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/font.woff b/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/font.woff deleted file mode 100644 index 00cf84ea037c9748eba8fced0acff7dd29c12b2f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1824 zcmah~U1%d!6h3z*Gn1dq^e2DXHffq}n?fO*P4m+=ZK*U=>UMvqZE#n_rpav5(j>cS zx@~12iVq^~gR7vpPs*;oSP-8?SivF%AM{D2EZCG7&Rrx~vs#LD8 z6G>0NAK>b*2>Z*`Jo2P*_+G9;iM>+Jt)s5=Jp7=pDwQg^vIY+G*{fXdJZt;odUXZ8 zDo8Q&L?BVT%Wji|-tGur!++fv+0Qh@Y&`XZu+|ff4#$ZeUJ-X2yEHCB!7-gTOi&;6 zDnMO`aoh#Vv%1Jayytdm1tWk99y$)y!#92uA6{uZZZr@haQ1(2tnt17cmHqxn;lZi z$L30U;t9iuVRnmN#h?YE)H%Ji~}l4#fh3$L$@8 zB@^+8(AyRp6H=J9PPd>@Tz*hhgR$y%{W5Pf*FI~Y9^ z+n%yI&s!9m)a`NwI=vppsm{}ZfSGd2+3vF0+gfclML9^PHEnIZprs*NVSP;l`k-u; zWLdJ7t+FJ^R<;=%9Q64%RQoxL5>}lps>|ziI$L`}{T`#RqrJ^xmt|E|ogPm| zCrxYtUNy0VFSW^2&zRUw zae99-UoBUw6lytn+NfbfFOmQN)fyX9!lt?3W89~`n{P6W=qf?y!XD}_xpZt z-n>7*ALD?6JDV@2dg6D;{J=I}uDUDP(!ZkvH#a&(D z*iB!J9hK#cPac2!>0k8M+2$5KcOgB0|93!p#JICaB5_^*1jtVMrx&Y@bra${`f53S z%YNC#&zPfsjlNlR*H>U*lKzMEt(sf)w%<0M(O2_-w&JfgxK0{3m2pVu4$KOG`kHF}jD@2NRQ-ryjC>LuJY0>O zwI^DCw^~7#wTA$U)^FJu^A67|AgD?m;&?emUkxPx>i&ll6Zk^g)&4*lFoZss7egcC zVpw%fF)K2?32k@(sd>gcXPP@ZCWm2Dbf--56LTw{Z?{ zaVv5cN1Rb7lN}J3M9~=@8n!uqLQj~2U3ySYAMedv$Q7N7$47=GVM+XYgk!|FBOGVp;EM`!b@DS2PGSUK zFO~hO@7LO^PsyvVF8MXiA%b+_RyShqH; usj`2AYqME5RJm*LFDfj6wV(*P^gS$)yM+z*Q$hK>5tUDyyRKgKf7m~e`O~8S diff --git a/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/icomoon.svg b/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/icomoon.svg deleted file mode 100644 index d5495c14aa..0000000000 --- a/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/icomoon.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - -Generated by IcoMoon - - - - - - - - \ No newline at end of file diff --git a/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/icomoon.ttf b/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/icomoon.ttf deleted file mode 100644 index ca364a1b69d5f15972c212182006f6535781726c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1312 zcmah}O=ufO7=5!Nt-Kq1Rn!Nh6)(~2Hk>W#dW4VKo( zvalhCKp_+#+8pakPC1tL)tsu+!G@Hdi2I6Y>)LNrzKLe>94CdLTy{0Vvj5#C zfGr_6+8daV>@=#g*lBhM)M~2t(-zG#^y)_fW7JJ_K;uuq-V*J<+U+pP-a?2)`;T0L zal7*h2zsS=X&NwkI&}HR?|(Egfv>eq?IkjRA@sq57#bND!)kC#Ig#y6X`9@a^yPg#OPW>C-U@6Ddfm)ukPM}`i|tp1J|92ysn7(FK#mg&_~IeBIq^H-;W1De@! z-RROf4-J%E_w2aqUeEQ3yyN7xmKuMTUFLnWOCHJQ^yJ%zij&y`gW}C+S633r8z1Oq z+88SoFZA?CdGKI)Z0wxpGb)Z6o}?{w|vLkd(?RT;d|iaswUTVGDT*NdSr>X3QIstP-}&XiCzrg zBEBb6cd6q-oO@@5&@CP;`b9S`kcuPJJ)|%b>yp@wae{a`#z}s$nHcNTKZ>!5x3H$( zTf(4X(Gp>exEfBy_!dRX9%@~^)!Nd7VPz!=O=21a_8he0x*>5b( z2X*^|Q$!g)8d#zO4a{=_4vKq5?J3^$tIG>sgNynsbQufq(Ad*+GN?E0s$cgTUelko yZ?D=@mEa0%bNIiZ)^2k3D$~@%iac^3v(#>5mE%;nfh*AlSYz~c@4l7);J*PNM8hrs diff --git a/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/icomoon.woff b/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/icomoon.woff deleted file mode 100644 index 7c3a2fee718eb4fd445180f9f14675ad83e1055a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1388 zcmah|O=uHQ5T3U$*|@9Sw6#f!*0QP6T7Nb*)@}W5)e@}QR;>mP6}zTuT1c{zrm=+{ z1VN++_29u?Jb4toc@PgR2qJj$Ab1lzNb#bAAc&3Md)aEif-lU>H{Z;>d2in4`cNuG zjIe?^S}(0B^jd3ZIFTe`>ku0i60Q&4$mE@C;Kt#f7ZOXqy`6O?1@{8J$Q4qX&COf| z_YyK9g5nHa;C6inNrIxKuw4V+ypJMnkYcsusSBC;K#^Z zVwGQ&3OLj*k;JU>F&6MEWB`g0LsnSsQsoq)uKlw0-~RvMSTEgC7L{)lA<~%Il3=Z! zJ*-VAI~ilqhLEzj{KeRA>^6*r1p}tdV6|a`Jp>DHyRoekVL6)@JTH7q_A5udGgNn4Mk-CQH-gwg9SJ&CPl}FW`tfjSwS*+^_ zLs_Ij4aNAuWttf5_cki}x-(jhvSCYe+O`k%*!G!NBa2&BTqz6vf!FBw^cub`8dHNi zwsfST8(Y}VOM}ya;Mt?99@e@O9ewrnoNwNo?(RO~Sn=gKGm$VEs+VWA+OS>@C!3qv zRqep8#`X>6mDxTRew?@*KJ=Z|2jryRj~sh0K-K!U72i6hEf?l5zXv?7SbT0}C+P~M zRwGqklm&?Of-6f#rv_@K6Z8b0cuSS~{JmE?$TVLW$g93MqmW-A-XTPzKF@(|9|wS^ zd>q8TKH_5){3##nw29`#_ZHB=7>HD{0-W_R2R`iM0Pw7jgA^sx$13=9KGvy|9!+Gt zyyq2Yf->Y$9^z3U?G`5|yn?yM>Yy~aRHR8HAb@@LkVPG9R;@{%bF))9r--I54mw3S za;UgwX38s+%&c2*i%!WMGq22;{TXinXR|0Jdza8Xi){+>L=Kf;$G}~o8R&j_fr07; Na7H}x>L>XZ{{|m9$O!-d diff --git a/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/ssr.eot b/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/ssr.eot deleted file mode 100644 index ad617b652beabc2a493c5905ee817e2e4bbedf1f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7232 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 diff --git a/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/ssr.svg b/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/ssr.svg deleted file mode 100644 index a9045e4ca6..0000000000 --- a/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/ssr.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - -Generated by IcoMoon - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/ssr.ttf b/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/fonts/ssr.ttf deleted file mode 100644 index f47f04d0aa4fb9cd564eb42fcba54248590d0856..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7084 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 H=cNAysw&>Q diff --git a/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/img/bg1.jpg b/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/img/bg1.jpg deleted file mode 100644 index ab7821c7f16d878ce2c1ed06cdf67aa304e6d73b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 169716 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%0A*-2l985zzZEc%({eq{FWRawDB)%W6 zJ3ISbkPWwjKe`q0Yg?D}?O~<5$#5w_lR`-YL~x=D^E12OjUoI>J$GrUq@H(%LXLQd z0Dp^ASDG5GEdwvmDRGO*VsD{bCjo^2+!mTdl{xNSUZx))Z2g(oll+n<|OTfT14 zuxQoeTC2-0=fG*cVf`AjGuyGXGG}v{v*p}gfClbvZCfo<42*(64z{KfQ|PMa$N^2i zHE}DrcF%Mx4-p=!)G&Es=IksbtM-_IHP_tYGJ;VMtS#^PPhG04J^7L~xyg6*ocaCL zT0T70?@DjwE#W}cbd3UU2FIKXYX;;Z<+${E^~Eo~dfIp4&65`v8@hMT1SY}47$l}* z7#XdQ5kAgNHIeF zRj_wlt6-H>dS2SAOP2W>2B)sr%oL}+47$p7O_lq)PhZdd_~W=LkrenKG70uqDqywr*Cguabb@jQv&!Jpjy3B;G#Z{jT~#hp*i-?d8}7zw%9iQI0Zj4fwa417WcNRIm< zimPwwuHU5r`mnwjpVxHSz_2I0+6;uxkR(iZ23PvbYeo8WFzhMQo{y}=uP4jw=fPWI zTwi(W$3Hm?#!P&{BQB>+*Ef_dZNkVB)`^wcde_WV_4s8%x@um&YFXYkeUQj{1%un` z?=0>^#rp*qzC+S9IcR7(onqTQ_bFPLJi9Uxm)!{5zXtw=)J%aZ_4-2-1p|-2zUf>Hq+N~rU+npZ_d%S^uk@V(q2r!}sZNOGv{P%N(m{Sbtzt|Fs2wnby#P!#dJG;MwiI|SDVAj+kM6( z0N=!Tv0zr(T!KoWP~ZwFpg@Yuc^pjgQ~FHkY<#I&RxRy4@NTTmQGH#_>e_c-+gw74 zcD{U+*;UF3QH0#8(Ljb2q%={0imffFg`fjWol;#&MdJ&>R0fYG%gV|ukdCooQkaq; zsa9t_M~r>o6Y^V@Fhpj)IrxA5qDfPb!Y$+P9N4@p47>`_i9WYYZYxzK{qzb;L88XFRu&Svkd6KpOK zaXG6dEP-?oWKaue*2^yY?#XJM9ajnXRJXt}#(2kCStVey97piOOEzbO+5#&w z#;1*8@J)XH)ZbhpTF#mBEmzJw5B9_sxFZUM2A@Z1aKNc)BZK4^$u=_D^WvbZ%;4;Z zt%w4KjBX8Ov=34ETezSw;;(laBU$ruI(l8SFfj#0z)aW0bW4n%B1|{uUE}=W@Rc`Q zKA6NS>8mZ@-**7A5b}iChcUkKvC3MX%e$h&h>@w$T`HDaKHuiXuf%Uzok&1bTJ8ju zFK1N}MPWqB=zqOWX>;&XJ-)QfztNINS_tDy5Dp@YHoqjvq_oi=h0wnaQ&FVK9?eYK zWPq_jUu{?kOIMed^jtc%-&OIJNEc?aNGcvMPTgCKq&;;T}D$8X7cENFzlI@xlSYZ8@XBh&S^IW5b}0 zpMrVKq|IU9)|{Q=htFf?p*j-us1Je?QJ;jO>MfF%SUWdTewrL9jj)O}XDl@g=I94g z;BiU_Y;};Slm6zWbqhpavy0Ru=p+Cw%ViQT!aZ<#I1&UKGP>3biOo7bLhB&~LiLqB z|M=6G1c5FvasV=bL^bsXYtC0^Yu$yZd~+=M>b-EdqmdTr%`3aU_-fOwj_=l-^+Sry zxFg{ZopyR?296EcZy^g4@bc_=mNUV2xf8l=jzOfVLHwO{p$Si+r zNnEQ0&fNm(IzE1S>eU~C7hgDHVyUjJW9CMG_Cw#Rr%%qm(@|V(96dcWMaHMW^rF%T zFk><$8v;7LoGvrne;2$p+A^iQlmO{GGqZcQ!c-aMwLUy1A@!XNAT;SSy3&J~^5E zMh|F}y?enyY#9C;^?FUq57usU%zdMF4jj?ok@0GM|ZbS6LoUeHl|0&Gu!ithO!`VcV*r7#N#)iO6k^9;_f zi?oh~j7kaVffy&GKAkakhb71z%r3Y%$%c8snBo_v{p)GdH3((#3r2^=>nU$YU3RV2 z`@DIUnY7a*5YwipX|s(LRPb)sR}TH~pKrOr+XMfe00HR+N;i+h@2!bf!S@SyfT9Ig zCI&DSm1sS3*!SwuftDX$DiGCVD$< zSp^P;*GGt1!)UVyI2lA6 zVF7rxHiR;e-JmglrRfLnL5>cb_V5d(K;`9EKUhm%fRutz5|RcBr?vGBz{JC6&sNM1 z+?oB*dG*g~n$FkwMaY6IDpGc$KygDlCA_#oFjwW1gQVpz35R#OO@t5tl=Um}) zOgf%)gM_MN)8mQDlOb^{ZJhM-;?iWnyafNsuq92CnMIt|ZOsU@Na3)bUjMdQkXg#^(rk^p-F zNc`OXA8%Vcz+~|H0#~hF*m$!a460Zmg9Rv!SWPg&oOy>ut*xlr^+h* z0ZYrd@>O#bHPi599RECL>%)}JV2tLwZ4(Wv~b`bAJYsX_n6ubZxz8+P$sYagy%fA#3erUl4nl>?ywm|QWx z6Q}@!XEGCGD$?em0Xn%Ypi5IUDajz&Q;-zesV>n|fV;ZdbsJ`g0Te81BLIQX>r-8= zd;#_firXNkYkgvPc}vobFdn_P-a}`iN{dba-?XHA_rwqxlcpiUc})@KMbI`TBxR8~ ziip%(R3QlhY!wh!oT%yYN23djNgIuBNRTlj6OcfOJ5`MKn`!w^@-9NLRzJ12{nB%} z`%Uht?;7%d5B}Qao+4(h$I>!`l-?_8UF)kie6Lmx%+A%!YFpbnDwYe$%NMScnBM?! zsG??6jpL=|ry*kC8q&vwvD0<>fZZTU(6SS=4@OdV!OVm?h!p8S;U@s=3f#~B%R>Y=h6D}aamhSRa61h?j z1+`#%?6bDyJHjh3SGwc(0C=2^H#w(W4t#h^8Z9y3yt;g=W3FcAA`V&F3pKC)Xnh_0 zXY-{*C}fB1h0}*9z=?W>3{ll70MJ$92ns3!%P32mmr?L4(fxXt$bqvDKuE3A8uM)} z*>7)AtM{kIDvz}JYEK+7S`Jflafq3v&}f^%jH71!eAuyC3i*}q%FU8ItZ-}Bk?`%i z2>c=Nf&ph{X~fJ~2zyN7O$VpCAaBMih|Dr$y2eK{_&RqU?0$TLK$4U$?F7z9GvsHT z)BNx(jHSkNj+Lo@{WKK=1qpw}DHsf#fnbU9xTPk=u(q~2;; z+jO@-?@WQsYuIP>Z{!3A7(XL*41-Jzs&4S>=Y6~H%GCGu9oOS&q&Bql7NQD^GJ(KY zWW%qey7n@axE7w^LAAHVWW+iM-+ zH9(gjXe7?E=h+}PslmaVSF2&_Hmb{2?S<_I^3l^F7wkkh-L5azmzVJViW>7M_==m; z=8fYG-73MUl}zht1kNLwqSC25?6wsWBp1fVn0$kH7}9+XNLyRa{Ov0)$uF-Bz*C{zB7y0qGJ8uV{w;*2cYxRN74N~X-x?BCoEpw4+(po_>G#axrRY^ zgh4X(8ziMbb?)+*og31(1!lhf^r>e|fN<6Gvhq=&Pk%lPTQ7z{T*A!i3BtoFZEp1? zyI)^zSQIFy&zrTznz}^ol-W1SnO85yO6C~XnF4*Q+41k2@~))2)0cO93_|^hl&e&h zOK_BA7F?r-@$Yx*zTb)J@w|7s6X-GsO`-QCy#Rr7flW`CeCNT8q^LB(GK`!>{B$el z!yvCgF+APLupp*Xrlh8EWfsMnK6BrMO zLxGAP8V$!GakVKNwfpJXiW*(hs7bH2>#JeNcfVZ@OK{o=FIA0}H27h1F+hj7@TxJi z!DV&pOE2l??Dqn>8wawdW2PI{Sx=*}SFvgt)5$CKIkPW*WkxqI5ezB?$f4eBSV9wE z>NFIVpc}bb>Qr@!bp%Or4&-)sF)BtPqHncIxK!@xR?U#`B!YO^ZNq-(e;L9!`Nnb7xOl&R%94bH*z!ER5!`PT&xzgh%t{OYC z9grDc%X5ddLRsC-(i5X?CwN7fcG%+*RbHKQl!W#CmP|y%;!`0-Q}O;mLU3-%40cFf zKp9y^sS0x7G>th0NPlG!4oUD3_fwe!SbLPF6GIwB3K$mQumAMVe&`C!y2Znlw{Nd) z_TA$zCxNiqS|^0?1mL)EJsVu|i%YD@1^L8Fj^#l}28pffn&h2PL%d2N%L&%552%qM zLgnr9C0HGyikgBpj zxSj;Ivvk6j%Q)NzY48gV6rAVh=UyegM3#$M#RZgMh z#h}74>**~-28P1{sfbxc)vHdTVbEm~=Uk*?sIJu022jOD`6%T6p{ylINv9CRizliL z_T3YRwBa0q3Nk~2Bwqv@M_3P})Go64AOcUFDI`Nl(lR+{gCs9fz<1sM^8YCV33+<* z)gPUX-v?3B_u(D`$dnUe$66r~mboA>bF8fLy8}2{UsHhF@~f$f>m192(Gd+8iX{2B&)zIJZ=Ae8Is^GqQ4Z6O!$C zbk#YPN)V(~RGd>*w{W3v-!5L1)2H?efB_3ELXtxtY2SU*hEXvL0rcS?*-9hGybLFZWt3Bqkgt;ho?oPFC_u7t*f6mSe!Y`` zEW6xzb^}P!0J2b|gXx%a24~gUQ)E z@)}TB+XvFI2mS-Gldr8ogj94)0h|^c2DO_o#lRw@7L6o;-_saNvxPk#2@!ln@ahP_ zc>p2DSaP}*(TmeaRU;Egwhj!QIXC8z(;nAK7x?3aSz=@unss75#zV|(4W@^{82B0S znNVz~&aT=V-L>aLH3a^4EA*x0*}HO``bvQ^%%B~$Y;KjSmom8BkugUL3D7EUoe6LN z7Y%=#5fCyBh^Q1qi5PkYLE`66zWC*NVHTJWa7oXr@YS*PZsnbqfl5eR0r7Q@-yKg8 z7^Hhqi=Ii?C}j*q_4AEtz2vcxSSSgpgic}{p!w@!HZE`;8--wJ2F52{IyWrxQtv4f zQlq)a`0Y848PqFa{vglzN*c`ZK!O!O#6jSf1zVDguLBD@iuUN~d*BT$nsu_VgXS1b?-49!gK+EWKx{t_hYtpFC(vWP}(7NKE-$9|2U-uY8v zxcTRQ_z(Dqc?}>45Q=5)WMR?$_)NItFyw$(Th7rONCG}#WsDFdGy^stBhSXKG;o-g zbjg-p(p~Vl_zm+K1z2=~fE;_wej8*x_@8dahyke?hYF|U>~?=FoxdUh36M8!F@2D% ztoJ9^`LC6mOUua_L`q&9ydheS40^9k-ec3hv2?L%bac4n$kPB71HN9;?Wl8Y0EOs{ zv`$~WN~^a*uuDXK+Nr+cZ$fpkQ@T53sez2iBPtq!%_?{Z>AaWo(OLmbeCES{_?Zi9 zIJ4K-2a!hzKkj$G_TBaxh`pJ^jZ8YoDWb#Y8^*wIH^Y`o2qy*7I*78SSOvujB@n2d zwDTK)Pl2}AZL*8_aH*@w*)m1}Dv?A{y~JX&X@n~qK%coof*ElbqUKxqYJ1X?@l1>VwQ+r?}LAGHWm0J;A}|VnBg0sOw91ki)DvGh_JbrtrCY!kg%l%5EA!-9 z-Z}7QUo7lRS%LdtT7XCM0GWUk1-=bzN%iJaMuz2K+k?2>6P^K&7Vf#lj#Z-r&?Yy~ zn*f*S;`sVoNE41}J@yMJRfK zePgS=qgXyT-0m!$P=cAIx0yFi*wnl4Vmd=WHV=V3WCzQrLJ9DhxB7fo4qlqfw)g3Y zV(S~QgHbOLBEW_gL~dKOqrG7-l4*q}FaPOZ{+HVX_~Gr4e!<_1RKk|nHP|wIGi{FU zgxu1_K;I2|c?oub7Ge&bNfwg*rV8sr%m>2&#m_>(4;~SH6uHt0g{J!jtlnaT^*gP> z5kt!%qdEqdI$-AN=z5j`OCiP!BnXS4jEc<&0)%sjMTUVb14^%S3ZTxjyDRiuW~{JB zfsIxubWEt7tuOBsS{G%QUA9rZ+B7K zK&lf%BLcr6N>p0x9hXHUVh?tbh%Pm%ueSt8aod3`E!m9pu?-$PHT% zCdxabYMODnBaVp%)9$935C5?H9pC=$9_NIfg(yl%ZfWcsY)3ib`IE$Ue zZXtl|UK>e9JuJ?uAazWkC7P)@TLd<0$g1l?fL^-4jZH@E#`XbO0x$O}CtKP**`k6GZAD!{+C| z`(I!AvE*9<&{qrl8eu72@c1_fIsBP`CBH8xje510>NEKnrRMA_EW+%^O{?ba6Yaz!zeCbX}pMK&tVggnUCz z2ZXCy3GfSsBmy9ZMH9f5Fuq&>SHU}AHzn2`fL;2NDvn(SWe9r_0Xgl9-Qjx=K-!0u)U072qaA^c>V03Rmm8e(aU+hVkZF#w}=g+TNSS_VUV)Kp5N zX;u(MlywNJcUL-_iNZ)wZjKGPPVFa9BAV2i1QzQAR}g`#_>5Y0YJVv7>i<^rPqTl` zAG`m-xBt^0HT~;1+JEq~|KR%YPm^FBAOi5@)S#x(YTu9Pdm2Iu~wwRjj z%Y5}4Uu|Cpsj;;J90a|B)DeOq0H8DaT2tUo0R|n0M9X$v!WvZQ7EC0gi;8(8=pLuh z!9e0mLktEEB$3Mtn|wiwjK>P%8Xzg4o|0&3(V$k*3dqJ8LKs46FsY`TDw+0>x@pur zgj*B_5v*zt27iIV=%4CQ!0hrP>1G*#BnF$;?eeA});owRQqkxrxJUq>sF%Rf4Zisq z%n6|C0$x_1_ep_oTg@3l~ zj8dkyV#{jMRANXoUiN=x|I>?4V%+=Od(Ziv@A;l{Z-KsmM+pTj1Z0saVcuR191f&q zA;)*q;E!(a;uip(+y=GvutHY%47t3Hl>vVLh1Q%~cOU~7AYz#0RhpZSt{hMWQBhXe zaS_uXOB5J`?Dw~CzFV}+NN9@F%+d*bb-4@!;}a7tbN( zSYJ_#+mQ10rQEV!r|i|Q`x;F-bA+2XkUo&ygmSDL5j4;+c|he7gjI*Rr%5`1ieRn$ z)d#!*;QN0w7s5XF1;nWECTKKZc^^Vhf;y{u zSm{F%xTQA-vGNRQfs^1+Ww596cLBbD5(pEU<%g0QQ+B{Qw{*c$uh}=HD)dptkL%V) ziS1v;id*_!daguI+sj?dKCx1^8w-oS=N_TF`0}}uxXd(PeveI=Y7q{N-?@^oQ zVeJQb^DF}P2YlWecqi-nN<#yKlgIuOl>71k($QU!2g6OoFw~h@AS+=-`X6jmW8r2_ zieSgoS5wXYVB}LmXpk1UchizE2#rl$BLH=SeaqkJ$>e81@qsl!P9rnUcMIb!Ml3!w z4QqpvUA|PSMrV>;oYgJ4ZBy$bspFNJi@DubLdUv_{zX2p0gf~^tK;-Pgx{@82xE27 z>d%7nkbqDE=vAnG!x)&E2pvPr3J!PU)VRLH>|O;pCMg$W|NIUsArkTP30AB1#htq$ z2H@WeFv*mfdgG+TkVJt^02Z*mG@_JncY_T9IvxPk_wu7b4i0W0)GR%lVHF@N0Q@XM zI8;lq(>Ro!Yz#s(!V4pyMhIN;vbnAl!itqwdk-Xe2m(iMFB!bG0i_lMK*(BKj=8x;erTdgaTODSO^@#iSsmJun zv#0O;ZZ2J4kYQ@+b{DEGAbfFiXIHo}7->wdJHmWTam&aloxbEN0o{;@2Te8CGK7b4 zFIM_}4yaqD^qPRnei!T>ThmI89IFn0QLxvXW9ss~dPBKk> zy+bSl=v<~JPXyFe0TQ_SBHB3$%MgKE<31}Gx zy#*kBlD{kc0^O_PoT~s&Cp~D~vQHHqagC~Wb+9bUhH!ORTaeKq7^K zwALcc%M2<$27z^lHWHA!1T*A>xDTpZo~Ya#v{tl304-bS#4@ z#p&)m!r0YxC)D!7E+=d6L23c4dlqdwND#t+$?>4uc#1H|bx$-WglAr3WmFM{(EsY^ zmVFPB(W3!q?oU=`>% z4a>^kHiw7m&7n{N%Gvf>9L-xsAkZ>$xas7qcT0OlNDwVUClEltA?YHXaN#nK>=1~D zK@pL^GwjY;j|@7&C7~1vdI7k4VGptNG$yhZ<_Up4OF#4zALKK6;MTTfNYnD^OqOY= zSu2(gRhQ=Uy{G_ti1ICJ54cl+Hp7wOMI3Fr|J@?j*?cHMn(gb(VN_K91R^kyJGXgc z`?CUA1y+NQ^?G2&1vAlFK!Fk!f14B9!s}hlTO4)kH7`bz{NwyyMBjDTru1lTzBFcE z-t*J+H|5=r-UR9sig(=akeOuCmsvqh!_x~%T5ar17<>-N$+8mV0Tr_BgUibge|}XD znLh!Y4*hn3W?p%`!gO~Sn_1f~+CC?uD4EvM{wpUZX|!ZYVb7Vp*sZ4zQ?{Agh@W z;2uv;{|oZ{84y!Kd$J0tX$U_Jy0WmgfHwyU7PdaWwH~D*CYnP)B8x4+ncl95O<@|C zdJ)|SAzzMRt~5z&sliWzl9GS#r1vIZ0VSZQbn`M>8JKN%HrOU|aHJ)pZDv-<%%VlQ zU7DLm=p{R11AFQxzI?^iYn*TR>#wPYV#TR(@9mFFmYiN?#m5ijnD8KKOFxPm3%veB zz~VxMO90)S%{FscFcH7$IuB4Fz(4q57*@csdRR}z5u}f#x2*#pId=iJB7Juj4xSX~ zzJN?A2~gz%-2hA~Y5^g`tD**U6xAyWz_#&xO$ic-M67f~;37Xu4xR_xk`dIa8EtbV z7zASAdsxo!i zX|4K1(fiOHJxvp#uaphOG9%LbWEvOJ~FhI{y zh9Nq^WHaEW{ROkEASJ$@);K6F&w4Nj%k^Q;Pw9%Hw9Q*nIfIW!OSZZ=s9Ul-b#)ze zMGgCw9Bv*<-aFBdlF>A+4oVGEiF@}Aj(_ejd9_^{(|jj`s7_-ZrQj4q1AQYUq@FFs zK|5`7K*I8yx}j?IN*9r!dVw=%upppWh6FK(52U`pkdSnB>qb;iU*jCuwH#}Jf*^L4 zL6QvizgE!4lQ5DTXyZLDjN%%sGXcO zw#a4ekhnWRJGtk{%niA%Ok-Hdp8GHB*ck#o6}V2SB_b$05f5f)(v5-A0hCKq!#%BT z5y1Bfn5dM2A*)Qpvqnrdg+N$_1S(m$cBkK@aS#b?94!o& zLJ>8jGPBCcm{bFxK+6a!2j>;!!va!pf^NhktTHJP1;@bb8^}28id!;E!b)<0Rv|PZ zAX2qFT5t?sb|Ahk_=}vG(02L26UP~k8~;r)zQtjQ;MB*59wvM>yjHcM|B-&}`jiaS z(%8pKL;J6@xr-0a4cC#pOhc)M3PKIFc~y9 z7)Hd0;o>v`;Y<%46OmLByfE#*h4TQ#xtAZ;)ODK(>oyiZUx-W)$ACCO)nMPC! zFxeOtnTViqMd?n45i$kLNQi_-Nv;6HMexQ(m?BKdL0k&QgICQ#(7|mBN@MiK*G?U= z)8&3XdezLbq?D?5PO(_ReE{T1~E%D>m`dxby zR!7NrZX)cM8_$eQHv!=ZR^ZE{v0C9U;nuvQ1!t5vl_wLKQ;@M6ge*9eLW)Qroern1f8nkO?>P zvH)g|=}C%MN1@#iW{n-%%|=wp&M=acbk89&XhtNR;Q2||6g%6~OD(c>xgQM_+36P0 zb;?DfNhQmpSUZ|7t=Ls^xc$7?Q~iFkxNofeWpVh+trsU!a;8(u%Uk+WetX-w5=kf# zepx*8G_;Jv;CI(%S=3sSGL!pQ9u*>$smZ%)^U?^Cz`zuk!0Hl+gd!@Kr-extNrT)s zOv3{iabc+gu*^y?HmJFvFAW@2l*YtGAOZoj3n{T`3`X z2s=uXRAf>?=nPvoq96}4B}P~_l&1k{2)p^G-@BYQp4K{V92s^_HPb4)J~#*GkJiM$ z3v1r+Nc??x?+N`!wv|oI{c+PDou8)PZD|^t&<}4;jk&A3bhcs3ZbZis4hI7ivRqQ= zy}cC43ev&Br}tQz%*4FXqEa`JCqfvOfq{ocxXC>>X$rmbz-XptTH++#8*4@2G&me; zfFCKN;vk`iS_GI;x}j300wInF6N#XRzSgdwgALrkf2Y|h zi|&r<*`$na_;)EE*%g^2b*)eb*6D2Lrue8+lCNt6Y3{ztPbr; z34b-3#evouMle>KOoMYL@+a6#rUk`=h7;B_LcqEk#sX6#<ELNf zh}d8h)AI~T8bsw}!XkTt>=0|kuJ0tEYYdiwi(m^dp$>w<0HBU_Gq8IV)m+5EE3qtS za*8M+$a4Pt<7*cCWU5_OJ#+c$?++V3)6E17sH1Pb?0lo>Q9M$-{K~n|L4RKT>aBBS zgY)kXoLY8|O`m!-78UhFSOkYGBPkJH7_}OnCKN(qc^AhS8N(I99f zVt_){NQeYRG7gf^U3ol;8)Z`l=|Sai^5CptU_#&>co@KR29F9O+r(j7nx%K3^jnBS zfwU$Pv4J@wWgKWn0+z#go%=DjZaCyeEiChx!U}{v@ZEM@V7a}X<4ed$sC(ZH?}t3q zzu!>|zWcDp{_nWRfe*ts)XhnOBZ;e$7x#zS_p9aQYWaD!{KAb_^B-!I<&P9g_kZqu z=f{^hr8%$D2B+XI$C?IjB=L3Q!1}?EOt8BV92}$gy5dLupm6~Yjt_+rLh-7! zHXK2CR%jN7#P06ee$48yv;*fc5rnU1sNvpi4_Hfo0dqE=M&;Gh&=f@WS@7p9lLaKxsgLs?CUi z1pxCx<75G};ADN$;S@+GEZrGQSSltDxe{4e77c@nd?_vh_yyHq-86rp8x1^|9~ZHX z!wkWS&{-7>Jk28yI&YDPCN*MKm^>i(M%AJQq32wb|G9huvu`JCIhomQwx7wz<5(nC6Rk zh-}i_6kw5|lvh!?Z;~s31ClMJ*m^|~ypk4hgj@o#QvQ1ZW zKIRwo)<#uj&Sa53d4)~?#vAhcKM#*BUY!uAkL*hd4n94YJhL=^BCg5D=XCbj|J9n1 zW>hdIaOTPkGsS(e3KCSJrXT$?Q{`b`?Z8TaURA_^Dh8&6E8^#|tkOdG1>71_cW4|U z66Q$>I)TsjU@)!tnOr1+-f9#tKP>$~J!qTEsW{J?#}hJYHXUGN9Za;4dpx~@B|=z_ zC3Y^4=Z;{~))GHd`y#70%?m*Vn#C5xA$W%4fm~s(^bjdL36Af_(W8nR#qm?)H*zA{ zUhH|@_j>q#+jL*Db9P}=`G9I@&GdBD=accVH#XiLk57plTjRnV9*HXv+kUbk;UXrP z^XYwnwN!?|{O~9y-JBZ25~sL^d~$m_@HI}WHUM7%_VUjZ?2TpillQwtO_{volrq%4OyjbKQ z3;b3!+paxl=w@T@l;*1Acumg}bP`1Ex@LN?3_l7-=Q`UGMPXBEtUS__7hYC_pQZQu6XIRCKrPofSAuG7xzNfoLd2uw!85#&#X~Ez5g*LY zrbAp%gwfm%ab%#Uz6k*~5C-eqG7W|o*dXZ~FAJK;fbMCC15g$0pCrSYhUkZ?f_BF3 zty&!Q`)8`0u;P8;LBGXnLdzSK<=tA%SdruOf_Z)Y;+E3(i*nnZ7rNB$k)*)PfP z+taFo;_Zlyp-i>}na=&s&j)}nVUvfCBItKoq-JH}{A@P@0l4-zon;Pvc<{h7ioY2L zr=f;0tOAoku{#fIWj62{031QR4#DvS2P!0J7MAW35yVnBiDgzm8rXv74GjS(02{!9 zSyPyt3SW1AHxpqHf|xP@cymPO=#aOdWq@K*fPsw`1u!T`1`WO-fG+#WPSFX=xHmNE za_^_T{;Ew;XNvV7hTg^ujjg#dy~3ttomvB@Q~xC4wR}a-jeoB7*=A3CNC{T`GkP`p z?p`a1(I`|efWJ`VLG!l~nL^ZuYIw-SdTdA9kKi6iMEc!E2+2-Dhcyx1-xG?iS)y~> zDv)p;KOHhA*!eu>mLFZYz_b#uGTbZ%JcGOnV9NnEusB?kOn}vfw4eu|Q=CTt-lIfh zVUW}?0xF7Ojf>WS!58rIs7wY4;UY$|(sn^^0=5P}--AZ|DkoA|932`M*Y9k1#I7Xv zL2-hAf6bASVQ2Ao3i-Wg&DfOVwC%j+ew%Cbe-ge;3cuR^4vg<7xAapb_IuXo?*O4p zL&TizKmwa1Nr07z7KR#F_jxQUv}I{Q!q2!w#Ni<{7n~+F{esnY$!!9crBOEddhn>g zNFh@bXmC-DN$AYd2p)xl9SxwnNuhui)kDK14n2g1j3Wf#VTo!UheU*w0uGk2%3||q zreRQMg)=yo6qpXgDgf%id&Ad&q>=?j2gm~`IYbPVt#hm*CtBNgIC631c2!X9kUFKy zemF++|7$4r1ta_J&Da`!tUR|r_s_&6amnPA%L2`4T=LY^m9DR?K@!BrFf$2Mmx3tW zydDn-N31_3!dn&eFqmR|+HMe&BR7%db`oP_vX!+WUnWL!SR$;z)h)}f6d6eZWTb_W zHA}=2QFy)(&cbL(Yw)13O3*jJ5FopQS*7wo)C(B9)C0UOk{ojl;X!L`!`?v%@Dq40 zM1ny#1TSE)(qW%h5~$5iamMilpt#7*P6MZFgYIbVcTJz)HvwQ^-qw`DLZ6Cfs#hPz z^&7UX4j4_0{ty-QyH=ih@Y%H#msxjj zQ2;$cgr(sKq+65-s)ZkuNs?Y1CIOosVr@*+U~tJ<5KE`IL*GYtSTKYj+X`tU_yxQ> zw0?(G<)`1X>PANY>#E)S?mg%baZHZvEy{`k``}8 zIjJgqTzF%0O-oT?lgmeMMy7^SUFMDCi0T<_2Q0&&@gvpSEyEiD+vG*rY*#_E29@lV z^%5|yjZEC^f)UjSM1v&kB;1=;jU-%>mWOBss5C-m3@xfEa15vn9>tr&mLb2=kbHtC zgZL6B362nokD(b&9)(j+Kxr{}Txi73GZW!_5ycx?>`D$12wqHS7U^q5nz}*C0-h9{ zXhsFYubu~CBww`c%IMu3?Lb0&WYGQsaFS09OIfsUB7S^AHwLc5`An`)C3wrmePd^* z-aeUGp&FbT=zsp$95!cF32IOKGecN%4H{l1N1;rze!ZanMU{j9rcmbJo&{DDq zZ$ofJGZmyEFD@$+%P<833gja|z_Y-!xUsS*2F9IB;js;<(u>Xknt;rpp&AYh2{wjd z{uYR9Nd#~_RmBl)jk;kUr-7XC(=Co~PL1tt*&+^(5(krmJwpz|uNwF1yPTZM3w`)e z*;UTAhN(V%J~jFHxh~2_+%=>OAgnMp7a1E_R3m-?0J^l}ezL&lH+kf$;}v(Lfw{Mw z0)LWaP~k{cP~5E$?|VGUCMs;esCL71bbia&Wem|kxr#~F2*(;Z;TV#Vh4^Isa ziF3!}|3&r_aV={m;+lPW21oTVJ?C3-g5pjE-6w_MgPjB68=z;FDdc@1+1+wX--x&s z2kQL+t{Dbi%QJjj*a~9?Q)4Xv%R;w+vqaMUTTwXlI%yR`!&>0mXcT}mjBta86d(p? z3xuT<1{`u!daC}@zpVU_5Tg=upB57PSE>LKxGI!3{R7jCt$O!achz; zILGp?bnHltB6sYW(wr&LH_aSrSz38_RDW$|Yf6=}uFv_N@pQ`^~f-CXRj|bUr5R@-ug0@EH4Wgk#JoA33(_X z315V*5}{cOW5WX+#_lQ;8eeUDeX2iapLVF{#qgtN@AW~p!Pg)ni*gBlEdDFfWvgvV z&S0Z2q)F!&}ZUIP+!3EeFHfi)pCrEixa)&X}2FL=OL_7XSbvHEeYn{?(snV(0<<9iX(u3o=q$N)r?22|VKpeZvb6b6dVN&Og zR$qj+RC#E-2xa@X@&8HL+9#C2pbf8u7C`hf{NZ8{#JtUr`V(;KiV#){*p=yq8iY8O zd8-XmtOQFkdmUij zFpCD!+%hj{#)Kp*q3{0vY6B`r+X?0so`?qod~^akAb{rpuQ@sYLG&@Zon;3+irbi!c8?{3-ty zWb#7&S~IFyA}XVPmL-;91&z>9IL1a{Hrx6YSG@@)wjKPh1orew6B?7k2&nenEdtzj z62=a}BaN0vL9EPr4$q2acA)epi!!SJCK~RwOh9At5L9YrLANXOv)_my>HOb|l0#Cw zVM|3|j|ha_f_gKO$uz@#8LTXlf@KN` z(4e_v0j9KU0TkaMvx4)uF%zrssQoKFohR@BEsO|Y6UUlI^CkQ&ExqXxNM@Z?aFn^d zz%W@T<2I?Fr5)$NA~WIq02f2yx0(`Iem=4WNJf-y0!VQmqJWcs=VgFoOlypUgv696$jl387V55zd=i2K^$fQv8Q9YDL`ob0I*7 zg8!5jq>C^wKfFLh%cRvCqD^1c@oruof^;lfDrB<-(lQ$Vx+{!33&d3Z>+z!qc`dj*ROs|BDTS2!6A}e{G zFa!hoFvkkIQGp*@YL$inw9+zJB9A${s}YTmLiRWhP#(tf_TsmaK&^04HW!ys+!2ta zG_YOhfDwt)-2hdAO=o(^P{SdPHR70h@&sIlshck*;vmS!U=*PzjTMjwn+TR(YF=yC zxwEZaJ5*Wn;_J?i$UR%5^$?>LPx=kL`Hyk98{OaYZfLwHVcN&0xo!Uq)zSqTZA$pt zcQbq6jwI!lcMk3wEcb6a3bjIJe?X@dD$^z=LuU9=3L(KoqRjdj#xAkm`iLOAaJ z|7KZwlvnCbA?RGlWkEnzN?1d(Fa4ow7PV5-QGu zl)AMDe5Xu=SqN^yBd@11Yk}~|JGV`Cpqk=d5698enguChDz2d==Jk^DqN&lfYF+*<$%DZ7fNBVn5G~-EECNB?Fo=y3#M?KZk|9ndM z^w|e_aABLKy+r+42C4-R<=zG+7H)n36((c=B#MO;u2q=rKQrgtK)vQl1ej%%g78XM zgQo$D;6awvlNBP|s)Ai(W_2hXIvn<(IC^yG zM*F3u^Zshw_w@6E{r*q(hX)nxe>G5EqbzUCnO^FYyqPvs1u&9e;z%%vqH159LC4*Fg+wWjO_&lm z78v$GS-!%iX-Ue|;?O-RP{WcPO*Dmbm@KIm1!5} zVmocg5tq}GO{oPb2Y=Q6i^6l&t92i)gwvtzf-AJW&NrM68v7iPRS)TR3{)JUqfr}v zqRGH6n200=z8+B10m39wDxkP}(LG5n6*qS4Ubc=yV{v?0@ZEnQN*H1YuntpK0dj*> z3*?3gD4yf-7|^z%6lZ`NWg`YGCn#+MbHX4d;{bd2Y`vT`-T3V5t{WhP)@jOsm%L0@T8UzK=eP`#=H75X=wXF1 zabGS8BhK*Oxqa61Lsn+cII7eTywV9T+(fp%pxcOPpq7s^unv^Tv@Rupc>?AFfRD)HT_i``9@q@^gtnn2>J4$b} z3qXwfvhHK0FuIc#1r?@59b1Tm9#Vt|T5UG;gM|A^!8=*!0WnF^!pv)g9(mjIGG$CQ zG9tdRkQ|C|gGxpydm})|;BQH6L00)7V~1i3Z=OjjYzo}plje`ef>zM&!tlUO7liu_ z1T@B~+RrY&5*YdI#ZFrzRpF76{m!TM_OvY0@9MvDb9&LD=`RcZMQ#JC*SfLs9Ze-q zW@bJ9XR2;&%~IIr!C$`A>aKlNHR#^8#qBny6x(FSs1>av0GGSDWza|Har1}^{Muf5%s<3q4-w=ew}+21D#24?X`YG z+K2tcM~c5~@v+l?W2^aAr760SB5f~!s@1&lR=;omBXN!RM9RT~TJiquf2N(IR-Ltb z0($2x%*`}Qv5cEpO*xJjTmhVDZp~3wYBh9-n5t~RE8z$e9M*r`ta~_R2C_=VMJtcN z`eU`Y0F}a3KIt&5?S|U#x05tnPW?7L3O?y)7E|gG(Nzgs7sr?app<0xg8#2W%NsC6*yfp^MrRV#pg> zL4iG@?3NPNSRTKXCd9My37RxZa;pLg@B{dy^>IHaowP~=1qa6OfVF|kw}iEPvsRJp zBHV(P*=fXp3o{W86@wy*$M?G^?!8|F9tY13ED3zXKCP1W*j)Zzc=@S8O^hrdeMJ$N zdRQ|kJF(jYQ$z`Y?kxn(FVDz?;OB39c3Li8A3xS~spOl^!LBCj;enc-zu|ZM@bi(D zS@sK43T^L8rxhjtqF>Z4y^Z@OH*9$unO*L3YFyWB4~l}Nskzt3<1Z&@|7f)eV|C+( zT9bXXFpaCmeFRifp%W(bEwe7B6Wh5a4$znc~uuA}DW-x2-lWwB3z5)?PDEs1T z3wj9lPnj`3o1fJ%hrsC(aBC9*z$%M0F_0TFlxeo$)3(5MoI4%0>(7I6q(^YFysbrG zNZ>hfcxHK2jD~pM;ddANt7gaE%z0+ZPxwrkQumSRl!w*T$o3B3zN%;Es61mIi;SpW)@X`fxWx3oT8d`$!)6HruDl#DhfcZgS zN`YoWVS-Gwv~ZvIGALxf1ws!~qQHNp6_ApY2)qo$yD)nxg}!MSBxd<=zY}E>)ESxL zX|53 zkhRGL3L#=HUrtxrii_il^hy7sB_;OGS4QMNIL(}x(2tH^8PyCG7k<-`*MWp|0!hQ+2gN?;2dk_jU#wcQ^|?MSVadN}Me5btEe~$k zH2sx+5)vz9`T^LpG=B!gK#E}bV9p>Z`jS1%0^p^IXuAYR`$}&Muv|2WEZ`(0pNuL6 z06i_kpwWo0paT?nA&_muBpF5!3v;AakbV$xjcUw)3QFo*9Mz?6SzQ>ElGqXSG`vTX zyH;+~b>ivy!7xCMNKms2u`19prggV56%y$Lv|3+o+-ZBdcxu8%{6+hvHr?b@|2%!; z@YBXgo2F*v-5W#Gi=FmNUD>bPA@yc={ADDl=b7`Ma`X|^z&(#4IQn1V zso>R)BQ-7a3w>-8!=_yvrz_#OZB)1T6g2xR_)=`gYLzHNIl=R;9K+~U=7DJfHd ziF>-PrJT^un@Tx&S3Q1hae_W{Pu(%E?c4JZ!IyF~0EM#Q#?@t1=rT?c9@yD0s~n`- zRVgvz;Ou9Q0SDTj`8%m3w@^EAL+n#lH#To7buCzuVbwqSV4qKXp7Khz- zFP)Aligp#+nb&=6<_^+X7*K~Nch>y%@h4TvXwB&2#H7@D{VwedRSECyoa^MaHN)*M zuSUP_nLB)1{6msHP_tvtSJ!R3!h;tSPkkTN{^EnN)M={!UXA>b!|+&D;$vknrBin# zyi>D8nGziTT07l-wR3EV+$DTZ{O~s&e1IM_ko_Xd?F26Av4kynX1M?nOAE*OtPDXc~Rlsrovn+@qMa zyUww5HoYov0b`?CnO#w1^Co-klPgK(^ZHi|jwMZ;zI#JG{2(X!qxH%AD-Ws?rdqyx zrPVt%M)gJ4eX(lwH)jXFG(L3U$I!4{;f}ZJ1q57zK+D{A!aHZKv>}Xf^XLEh5uUB; z!p^Sdn35UWgHg&geYu@e&AGph>QiErPnD^@=Vy-f=f0ZhUoq6&zw~j!RC9ld)0Q>` z$J&mQE~;2C|5Mec-X9+yF5I`PX2)m8Z?S3VG(WgQl5g_RWbN|UXQ8R4H!i7{M1kTn z*ypxxa!B1$dVjKO%Ef&=enxdy{r*aLXh2O*kbQy8gJU;smFnQni<36Rj-G5bKI;?h z;@Q>`JlJy2VXWz*PHjK%oF65_oWPkvqsmL2Yd& z$}l(@w!bOz7ku?~`;w@W#qmY@y#u>6Rm!#gWBZT12|wfic*mELAcr{Zg;o4-7VWxq z^J`o2Y3&BP&pYCv9cHr`-H!u9Qvv}kDz$W#Y-V=)=f7%iGwYSpN zQF9oc^Zh3O=H>RIYpzUvB5qMH30|vij#}FuKlx!Q;cZuQx!<&X%O?+=ntghw`)s?N zN`lGZ_DgY{D=W=JxaiN{=v5AzbM1e(5A1#UHfYkZ>X%4vn6J6VIoDm35U#l!qjlE& zgZ3{P$EP%%FQ*D`znZGNt@+SmpOUms|E0M5>d5qW4_-{qfAB(IGBr7Fvp?qi;8WJO zXPf5sAMKj4b=3JMdEP5|l9HngmTUWm0u!Rt@{GY$yF0o@C+ExhVISLb?|**pl#(*M zc3yLl-ae;cJH_JW&vsQ6z1ueKKHb?M$j)4OUa@1HtALvBjVzBH+hs9(`O3eq3~1jT z{+%sJFW?v&qe3~)xlK?^giLS}PPnxZ_iz?6ybO!GjLDO&BP?7^J^W6rWi~t8X^XB* zsh2eS*wi_WUF9rn*KO+R%cfe zT~)bRPNt(=LeHfg~G1V-tkrA>$d6H;Xbp942&%FB2>#?V#_oBTAJL4{^a&umGUHv3lx!-?$LU}3f@p*-v zcg3HJK0Z`?Cp(1vZT45^_EpuH{dGeBN z&$M&uJ;3J;V^9WWH7tzG@$j%ILG(syo&d-b+XDL0g<6?=y?d;9Oi zw0zR_;j2qNYnvUf1==S}O*e~O&OAO?+9Td@cIU^@ueO?K6$)E3?T){%Zfx-%i!FJ) zvd&lb(<1Aab;+l9JQJ(gMgk<5U^e7YC*@2QbKTPdO$Xn$|k8^6fCdukYr7h=7q!9hpNw; z?Unu4pFLh2^{{YgLM+oLhE_+vpWORKqx?a6uy`uhS-hgXC0B9QuV3=Z*~ecOg%_TN zP^Lp`_?@OmTBF~k?s?EQbENrFxr=P<=ZVDVVU2S2*Q$let)D4dRE0g`gRh56POq68 zrEc8!PusMIzBpWyFruH=bj_wn+Z#X7)zy?Ve5>t)_JTqan7F0AvT2`xSKOoiPVEqc zO#=hbL6fj;syf$-?FK?qmdF0{!_VGl1HYJa!9n$jO^NN27Q1%2Vnn0$>pxh$*IO0d zyHBk@c&2l5h5WX@zwY)#bFRx(RiW_L`6ioY8)rTL(dO4vkw=0olWxn!ZOy@-J13Ut zYFhmCodd5EqV*+B*GihMj2G{`X**Z7rvBxI&Tv`h#Olf~Ex+)W#!CkZvx3%Lh<;Ni zdr>mmUe_XSc|H>yJP_m)tS)j|vevmIFFAL8%Av;xhn9$4`V!)jefFfN*6U6GD)y}& zEWFXFTR%KdCoe3#=`ipxx4TBJ`Y=46;*=sT&^bh1SIcb|97}5c{f}X#VodiwA*t`u z8Kq`?@M+VVAHu&@&23IniBG@ijPD6_=v|SJsE2|ZwI+(yW%2i^wxH8uZ-WJXT$26G zqZ9vg7<>jk>%*!GCWD{H_7$s~PIXQ1cy#{7sb_6dQ&C;*8=|6ep%pPx%3`#D**(8&!H`99TwOM`WiR_|e89@bGK6k7rx-+Kim3@FguJ zfa+G9zN>9o-IeTgN27^#ZZCH^56I!#lGN{7mh2uFtdpk?Jbsomllw{T?#ul(OOBnq zvv;l7HorKovDv&iXwTuN5Bn>Nr?F|9y0NVelTHrrhrj9it}S@U*}CEJ!S|nkNSuz3 zE?2}1jXt@ejUF17KOJ70`1oM2e$C9Kpv`gGFx``=L5Emf%GRVi`-Yrz{q%iJ&4qHC z>ClXn;6)!&wl=TGO)XJhiwP=L)|}UW*7@!7rZti3x|WX|wHE3EXaY5I?Fp!W92$o^ z+L}DxDP1-uEANl1^_x>&G(lq9S4-sfkM}=&9aZw!&gMk#m7LipW2?TB1^Fip$yYg! zo^66U)V(do+I@=E*Zle+vD+hlnS6O#mFm*-exUz+%o3aZ&q7mviQU}YI6jfP*$)o) zwQ$Lu-)EHs&5^GJH8$-1&bIoCk7Hg(E-BI8T#C0}8fZ@4Jm4I>`Nd4i%ty{wrTWjq zUtfuyY+1YX>e$bdOV`?#X_OCplWDJixO+Bug*`NL*cPb{8|jK08+f}{{s6Yr2B#Ed z?uNHp|EF$FNgUnL?AR|F$~`vRUI;jIwQjoP$u(|h@~O?r&e7#fNt*UkqpRdrk-r5F zzVFdM+Y6hfYt2O$Bb}{P*~LSJ-Mz_AwG$J{zlL(x`e_>b!@jni9d+=C*j`z#94HqT zhc7w#*8lCWSl;x@@WRM7>e=>#F+=}Ezj+ZoG`>`>ix;khdb|w6O=JoU$fa)gNw_hT zC(1&f9>8yPaM+ZHOt^;?4>-v>wqVx$z{{TvX0Q8fbD@3VY8BW1^y|kvZmhN|GSn}hfiG2+#GmZ zw`d}4+~{Y;A5D!-?F(-#-eG(t>Ot4Fss2)VjQ@D-k*A9AqNFD+s{$RBb*e(u#534% zZDI>$xni$IE)JG;PA@p?vUd2!8z<+e;1=Q zdLH(sWGBsJ$4%JhZuEQ8yWhV|tCcT_Y&GoHmRXBN_rk$ATQ@eT9=jI5r%|_l-&Ezn z)b^$sdFSQ*y5{8nb&l=Qf2@9$Fgp3k+ND*)?L${%-tW(amMBS~i}|{kAV=LwUE8mh zY-MdN?t?9NfzsLFZ?^>Q|AU{}LYl zb+e8AXwsFbwKn~W6!M&$LEHM|AC&ip#dm)h92y%e(cZSr&-pNw7{4a*=Ml~1CwEhD zOVE+ILKmkD8gREvj+dm&s384#85K*XUWA4UpzAxkd`^{}jmgd1-)#Ex)~7ZV>QjS- zh4v+p^Zyt9LKoLxc%-PY_jcl!4eF{cu&q@}o8Y{*W_oUv^78%<|00*D)ww~<$xc&I zLxcKapK^`jW%3#)+qL3cxyxY}y8+eTm-ml;7$4KhQ-XOaJN1iqKSbos_m}=}t2U@A zcG&xE`}vaJ%7f~5X(I;*b>^dXB{NMk;!8`T%AHp`Zx;I$52|doIyVI0-7mg-RX3yT zc`?5F-9Vr77RL|HTbpMcjLIH-d`sO^8+^XkS$oO0PSbvGNO@D9uI|x-@mrJ|MHjDM zl{mk-tMiApx`U3RJDM8f&1~+!F6`;Lb|>;l+w@}J7q8;3DhtmKoO>1JvavaJr>gMb z_`ujT2YojbQ zx3{OW?cSuL^1;~P_|y1=)9UA)De(&VV3E_(5(r?DCX{xU$Lz$xXPsuAG-qG3O_aNA zjt9v2O=jx@n~d(Jk#qakUd%}jcA7ruG;QxRSu~-E8B*owKJ>SRrxuGpKKER+FiKq7 zl)&0|R;rbbz^~B-imLgu?mA1I)p3(cnyxK5F&ZmA-qjqwdZ2SGR$Mlu)Bp}>e$xDV zxouRri<>$&ddJj^{ktbuQ)1g&{)pE69W#{IJSE;5u7a*1#c}%N#;pTc!L}t+RZf@V z##QZdeax#FXer0RE|_f##N)Zt!{M;HkE)l@G#y z=z2W+Wc>1`*O7|0sixsy9sjWRuf1HC!XDT{ zyr%0l8B?fs49v&-ZOiRmD_*VLzR&;ej$eNE*OqrY8u%%y-z7@!;uH7Jnz@l}>YiWh z$4007>I`OX^BLvS$A#kaQw^~r5M*t(X<4Nx7w3$7j|C`IQA@ph#B0~bt+=5MrYq%l zVur5g`0rn|apj4sL-7_b{TMMnlC>%G-Bwg%_3Gd;x4<5bW>M$+d6YTpqchks# z{8nh{7e`8*W3M=MhQ6}PJ=f>_d;EkQ0HLShYvNZ0&5PB3=s%dF^Xs>XtqtDnuivWG zr!-yLJ&>telI;9ZVQ{v(=X#qi>^F_$#gext#`M}T$IwguFTXkYXF%AZ%^?LgzK>78 zQU|r!X+l#aB|+qPRv`bJ>yPum8ie%DiYsVO0#O?%p2{Z-Gi_}D3RVN?bTp{qe1?7GxH z{JutfQ6&x!@{3v=sn)6%IG>7-RYIENu}ko1787H7uRpY7xe*RmP#*K7U{nw2JZu^H zX+FCibPyb4fxGBpsA+fnBUN@z++{FZr|PPtW4i!wTs;-z{US8T#xZWOKJL^0{Nl*M zazHtYTU?Z>s}=IoIqKqsm5D2^hF?AR>ZkDVoZv;aH$tKQTX&-OwMNx;?Yu_Sb+zlM zx?7{HyTtw6Vd`GeHxOq}v={65zWqOrz6GA?{r|ty#py!dQsh#d6H&q#MpinfPOaGJ zxSMRbZHu|&G8yWeN={_Tb+#GhGGykmh#5IyF0(DhW>hLMj5>^pI_LL)_isIVJd_98 z`}2CgUa#l#`FcIA$fcKU;cvu^R4G;Nv?urt&dTMJaEKAiU{B)joxFGIhQu7rlRVo+x!t&4@(ajk@Whj!XF~krIJc!v_nfo{ZtAx`Sz3ve z*c%q&oG4Sz5?>_JVW)&$Waa&FM`uIQ+Ub^(lk-&?DqmYVe7zE0}c=XM2o(MfNlmjE`h387p z+K$8-m`ohJwf-rIC&4bkjuQt(YAz>50l}*uj<*!)CMqAqA$i!A*Sx8`cUb3m4m6_= z_|EJoipXzS$Qqk~ft=KCg!dOj$L+!~G zE4URm6?|cWtqv#aCLSp$^bJnBcB-kkwm6@;D#M2zpMFOz4!|||F!tQ21h+BN%{kHJ zt+=(!R)nD4H6(h+0U~{r~r?HjHRTvR4 z4~T8HH4ySM>E(vC?cTbFesC!lG(fjdjg44Hm#tfaF9^y@6=3yo_STTyVJ@LRZ0t*e zW=v_b{Y92n?i<6`PJuh^ujt!vCufd-dasmsM89+zSzTBF`zi|MH!0u54$ErnUVd0U zgJf5k(_s&=`5BcAzut_-QkWfrNPeJVW+JV`+JK!K$C5wqHaQ$5Bam@aryC;h2q-L8_*XTfRpT zgX5XzMLgdOqJ)};4e@yA*EbfOm7ZiW*2?myp_v8gH>-xjQ52KE8N z4)xIX`%Qb-CS$w4zH-0dU_XfWgF~5tEr{xPWSN84h`p)Gfp|je$G?~<=OHEZwXgrh zDObKxcYaG*{}ghgTh2>%pJPb9Z z9xh@BLun~5_c6~C-UBmmg^Kx0wLv*rJNjbx^9oH9;(gEhw6gevlcq!w*7kRlXlTgl zY`gYiKqe;v4fZ05^AwOB!u?0I;#j8MIXxrc1?Mp7jiTnL)>rtc;B!(dJ3g{IPEYY< zKC9|=X#Id_PKtk5ShpIj`tKK8lfJ!MA9i+5q6&MqDg?xkne-!aR%?w`3G!z|@5KC5_y7DR>@x#2r6TFAnnmyDtJ5$b+|&x2c#flVIL) z`D^S~n{{iE+GLHlmRwTA9cUdw8)}+os@?Q$E=OH{LS5NE$)~TUsAAp*e8a1k7`>9{ zlTQuJQzGfDBXq$adsddfDii(x)*Wjysd$W-MJQK8p-Sqb^aC9sn{ zZ>TxgxT0ytn$vqq+c!y_j?ar5sJAX3;|m>E?Nz64CGR`6oJ^=dpD*q>wq~;=)SR;2 zI?U75swB^Yc&IqAykd!sf5X`%IqsSBWb;^PI2XZcvscIxtWbEI)jCmdMQ0uXCQPAu;eV?#~5QlhDq4mU`2 zg%5_1z?Bn7Ox7AnbX7QA>_Q$D;eQBA&j3!uG?oe;l^n6ajkzhZvf$Tl`-ES0Xe{hVaT#K4Ql9X0X#lhqz_NvKx>kXB|qPnh%+I$%< zp~-Ie`u*cje1Nb6Y>Rb`pyJ|frG(R&S4D|x?EVhNF8>9wm~rC%*$?*geYddtU)d~* zdD9D&)naZj_nBv-vRO2vy`&8AST?8-1mH&E6e5CS`6xtNdOgVifUE0Cy^#b)8mSCE z{AA8;TxIL38-wn#vf!Bv^DDJuBLTicgE2AF3_Y$O(HBE{}@P($z)&Lul^KIwq+;Wgn) z5;F7ZL0Dq75`FWxemn8*%eA%3zm)Y(gK^hULN$N= zU&nQZQqESR)iinc^8fG0B#`gxBj7^#9DOD3dUaihLk9->em*g&H=V!cFF6nbQN&Sn zW)6DCF|$|9S6iQ5wi?E-Yn1hK1+8jWF~-#wUZXSMVCBkmeh~#B^)tXu-sLaeT{u}X zB$+*rd5*=sx$i`-5IQ`AuX3-O%sN-sktIM>=XBzPrY+~>$9oPr*f4V0Svjmo7Kbiv zDnw}4luCX>uRaAEjM+kXFI>tDFYxJNiF0F-b_%xO5-gLyq*N%;{qAtw2PzLsi>12v z6D;XZi&o*BWa$g1qboa0_Y-I8ei&%E0EHpDJ7NU?`^}2rFfM41cs*B}#yGin(b!Wk zqPCc_w)gq+^0(7M{JkHY=d9`u_N(erf;*hm1u5f+&9RJ~qbniOI)BOUi(FghftcR? z{F#={&SC!0K%DFeou+6*kKdW0{smW0PX$;^RF5!C7hdr{KQ)xVdq|2JPizB;DT|k* z+Hk#aCHAnoMgmgCVcXgUre6=K(1gp8cqpaZdIb0y#aP@s>Vp>z-xG)UcBx2!D9a`r ze?7hWe;aE z_z;tfR4eZgAWAo|Uwd7LF9$_*uGItbUnkq9!C@~<;*wDoQ?E%Mop`-9gcv9%;$w-y z5Hs%l#xw3|gyyQ@_552s4T(x&Ro{ZUnd+) zpZ8@k(-38Jtmj$Y3t$amnww9~Jr{&e5>J>_O;PVTP)Pa;DFMUWT}&!)D1hb3OnFlF z+{p83JibTb;26Ytf)*0YN+0D!IzSN6hc7}fX0tEXo#ki&VEs*A#3K9nvfxN=Qv3nk zXxIFkLM!bh;lFk3|F^}f-pbx6J9g;HuH)GEom;dEJ$JnTQ0dHx{x$JS- z4ci|{Z(B#?09p~QDlWmc3+A8cXN_CrT9jrDYp&10xRxomGPsd zl5I&yrJPD&5KO|jJ2rF*MEMhObLa^}lP(7@S&?c>8lo#0=QFr4cVc=4wLgvbtH!DDG;6SIl8@ruKhYD#GXagk@Kgac{An7L&+*R!(G^KUvxodOe~)x9)HG2#QumH0C|<_1dK!?sNkzR*fd$Q=EH+*5lf@#t`8of$ zA+qDyRI@$=xCeI+4zhk`{hDU;ZadDa)b9sW<~?_4!Ny(bIvdIY_&ICnNkCQi#HiNf z0FS4W+kYx1|NGOS-lzAniW+-fGS6d}gfo$-+5ubiewDJfFqU>;c-{SVyQ#3K3EC>- ziFOFcmAP2w&TxBX_UwU5kN5-7S)}SbCyC(Au%H(b;XBXG2pYuA1P`p88g~3ClUH0( z{P(ONF2MYaP_3grayRaP`(nw3l5^l-_RpCIN7>f85Ae-}`oh@|>{F+t!bxltnMcf!*pin&mz+Sq zeW~PbA7^U3H!x?$-<{2pwtS@4UMm##kqOyYm#aP*>5aVHCm-OO!>ENy*ruS7gkChS z0cMcn(ctE-u28!jf8j}ra&5v1ys9b=-J#bwvpXSpX;Qplgn`P7SZ%1q!kgxvd8;o! z6OT~a8XL#740ezD=VDUD&8FkukFekB*#B*a{tq0X;XY$qJH;iq~_~t*QD!E#*Fkm+QzY2V_w2NMU5oQXG-RwtK@ zP{+Q*RCS&wm`O#|e_NT7(n!Um>{78S=+TENtCE)2ZIo6eRubO<-$CEISKPYBb7vzy zOZ+jFhi1@!JuSN@P&D}aaf+L zm0WX6VlRP6;H`%{`^F>f8M%*=ja#pqT}NL(yJB9dG<3|`@=n||Q^7Kzf2PHCfEPWmGS8>9$Q z%N+N#I#J#kvk0UOL;nPv_*Mt$usT(o;LydqTBm(gAwD}E&ootsHDhT>Y7Tpr{E2K& zriZmEFkv$0U;gokevfxNH{x-&nypr4!}JY9g0gANJmcDA+(+uL(;m*CNT+ANhZ@Ni z3`TT$pzBrC7vL4a|BHgvNn9@qg6F>AN-rXuwk1^z5R2X(w|K`rUH`Ez@RR2#xI+Ij z`m+2bXRWC`U%SAI$4x9tYmtLawrry;3{^!ibi19>_D*qA63`sSf!5E%%VK{+SO08D zL!x}$E8-QJ;<6_ydwLdJou#8Z+@`hskuozPE)DXhnCeE3EOHyWV~|QwEdE_&R&Ip@ z?QW+u+EL=~i9V`5YU^N_S%!W%LOktS^CF5Grb*ltdSRH~3uWau*a86|$sp6j#L_E2 zJ#(LN5P#0?c0{P|E?p2&HaeQ9eOqOLNE-*maI_5+CTlb?3Jk{_aV*80|6I9n!%mll z=)y(Vx?Jeq9dwg}!5=#oN>;a& z_Qnr(`*q3dv1oR6%RKinJgYT{drf5Q9g7ByLLkGuS#sKGPs>ZbY8p9pFm|p!6i-7M zd+~<`!|XT}FM=}$27+5Q9UqUf7a;d+a;`><%~7ky3t46E8C(2nC_q$EV-o3>ugaDiy*uZz6$r;a}WNOdbSn$BEJ7cRAyf|CxqUrIup3v zBcpFD()Lg)u`1hWRG}}V-MkaL-BV8%&L$q7xU@shfO?vR!5dYb3;v-f((N{Tp3+lr z?9f@fC%nSMc$1DS95(NhV3;`%0e$4- zhQ7fjphP#AD!BX$e3|>q_Q3HN0CN?67l2TvCZ-(|)Z~vT?dt=|9_rNE%9jt{5Vj^6lWCOi;7HM^m`-#p+!We=KAng4T$cTC-HJ>iQAzkaN-94Yf8JtI0cNYX7`5&2%e! z;bo**#vH}`;Yi>XC@ldWfi|#sd-3G-;dYO8eR-Lc zSJ`P%HETw}SHY(uTK4z%2FR{(F~Nn|2?q!P(U_QlxExXblL3#?T9EOywmlre=ep9< z^$oM`jC-Ihe9oQrG&Y&ALXZ>;1#AdnCanIuTB#7?b@2?!0QJnW)uF2XYpki`ENE&- zpdLL_Th@i!=U$2l>>JQ9)i`_;r!e%jH8M40|83$YN`N4ASoI^U5fCV|)QHwX1B+?L z2x%x=MIJH~{VA}savUUbk5y+9turaZAM6<+@vZ6ca?4n>2%ozb;eN$mC)OUgWSs@p z-FADE2LmkjaUNm!#-i*VzEpFJkBX|$ry zGS@hCCHhX|gU-(G?(XMRws=!0)r2sfd%J-&N~*~cPv{4XPN|{0VpPV zH3YFv4ytBat z9-g@uZD(VPuNMdP;I%)T;BwZIZLe9{DIO0-C(d0YaN zN-PbbJx!P{<}c6dw7ibY?AH^RQI66ncvJlROPqoHbVZD|rluBtLm#+D08Fsi70=xc zOh^NIf;e9SQ>q*b&6Z!x#`%;cqCtO^ttO1$APfg_|u2=X@Z2ANQ$t- zhU&45?hR-TM|sR>)@}zo9cbA(?}PkBp)PHEf(kbVpis_%{kAs#7yc$eYOH@a1T58P zKHV=Fl*S0ES&ao<5O8|e57{|0csv2p$zv-4c)Bed2thSWd4OHSijq#x?Axji3R0HeteCeZs99I|uukx99cS zxVV!Vv24{d_($Z3?|btVNjbvkhO^IG7vsqJ8%$Y}D#(t3kvR_cr=H z7lSjD15jgecSe|__>!XvvkPr@p}whpE{k@}H88fwTZk|3q3s4^RGQPQnEZz>-FIxc zNBg!kj-)~xO^#Z;=#&xJE?#=FZRUpoYSM@^i=k>XP`7k<-!#hu&Zc+-0zu5a6UKEd z^m6$B4cVo`DJyvp+ld%)8)M*@pSnJ5muNUD?B>Z7D8@$35v`vvlvIQ z!5eOl2p_}4-kGCM8shW<=0{8kr-vX4k2%MM8E$cXBaPuISi45+?A&D1m-B`Q8?()< z=pG@ul4@b|L~9fZbuQZsB|R>($#^W{@KrCwZLDUY_-go7MSpc^dgD{)oHt>ZP#b$h zmrds`7K|f~pJ8v0qQ=eyhuaA>b_4%)m~2aJ+Ejdmjm=q$&XI5!2ZnnYg-OrXrU{?S zQ8`2wCawJa$Qy31rw95P(`Lmr@}3@xd#~EP#5J7(mnly zgKr<(ud<zeOYt>_P?WT} z1O^H)^1xX>TQh<+rhsUqDq%9+U@yU-mUjhAw$+Bxz;k7}>-xm5!X}y5T=D!*G3Z`= z#>h={p1?Zb*KIi?gM+~H%s-r4(5j_jN_;YQLGC~0?;L~j-7ELoJ{IYKkOpr1ek49+ zh7nQN!q=^)rj2_it-RWIG+T3s#~0pnz5M`J+BQAjde#-saI85;Y@`XUSi^jH>Dl~w zYH7f=_!3ZA}V^@YMSoW>8by%ATp!CEil%bMPKBzX#!u+8g3t8Ttrx z-_UC|3(7SqX=7ud+bqp;7AP!llt?hvt#peY{k;#2IcmW~0Dan}Ff1#z@3Dp+TMK1Buo-7P~ov=Gs1pv6oSq zG9VdbKX0O|Hrd9mo=3GBNS#@a8nK}Jz&#g%Z*m)RcdQNf3et5vjW=?o)+acWpr87@ z9;TppDGq3V#5C;N$`*lJLFa_i)sE+e`2jSOQa+5*Ye09=(1Z8XH5zp^nrRM6yIbL z7@Qq*q1BnbXumhzc#FQFmSB7=60TM5s*&2s>I$nbAaar&Rj!3J!Q8d!W)1G|nBi3` zj|EJ^6}NDyftJoAk{(S!^wcNGYOFEo9dIo{e*yxTE{^flXFaMP_dq=PJM;(k^M*!n z;TtW*x6kDosx#qvj?o*xebuH?( zi-Y8DNl(uVZZQZcxO|MLYQoKwSCxJ*=T<=M8acCjObWw;SahXhg;d)g5A0lZG`DI_1uxp`S3J^2 z-pvFVI}&GVT86&qnzlacmNCnHIKIcds#|O?Y zhDBQ0=|O()vE`x}ZK;i*Y1AKuq73mB`nA-fJ*54WmRHyS2QuCh5NwiW`sDfWKI6~` z8+K+0CJem0f`$y*rDk{txu^yGQ0hNG&=(e(gaEVRp&ufGTYNSHi{ZX)n&D`Z9vikO zyT0$NwKW^%{Hs?Vc*nsauLfGS4@Befs6RNp2f!qf)??$cH8?Q%G6v*b^iXMdh zg{@LH)aCSE1heMv9X~1?Iy67(jJ47j7Jb9y;V)$QZA#*oNnJq8<&1U<20hTIs={6; zeoT+m;W%L`z740)NAA(L;W`nV`u&LoSZDI|^MEqjV|@*0ely6(q@+p12{^M`gAD;? zVZ$VJ$6zk{p_2N$19~_?A+MGb&M`a;$~Ni8VX|9h;TEr|xI66Vt}&*KnbQL(bN5@+ z&?x&+S7NCnH9t{oMs`L1+#;xW5ynR93y?Sgv;YFVHE(A?+@7ATscF3BEQQ4G27bM$ zJDNB-KG*#Y(k#SeEQ*qbFs*^n7ZD!bVoUeE7Ti6CP@^tAL22edb<8=hev>nL6=vD> zzk(7_d&4#yaJ|is&7sjCF&A1mAfajSI#Z3_-!|#D%?QogqywsY?+f*R@9+%DYt`du zv<2hPra_zCf%)R^Igi0Y^#I>Z8$E1+*>`uU2~GFn`kwXsh0m2*C<|Gk&tWK64@{=* zAN~h9rM#g5MnZ3Bz^0Y{294m!l;OB%$+6!)k$`kp{cW8bupT?b(tGWBNsBH{79qcrCJqRj-R{|#D_y|BnD#h4Gat-b1#;71m zsxd5wXzfn_zzxg338r`61C`fz9!ee%PCZ>d>Zk1$1Zj;ImcoP?Q+k}oBjIe+g>V=` z8+^b;|7l~<2sNqimW6ZC6wO?i_?Xn#2z@KauiFC5bpu=8!a|vDU=WZ87`@D#W|{sx zFep97f@+@er~-K$bvit+qA~v{^>72K%;Zr}`W+(5eA5=eBNvbhXr||EZr;54=c91F z!khZ~wB1+zEC$DDd++LG=P37j)zeIDjHdJ;AQKC7LK~q~!M`2u`|r#3A0dC(1d>XsLP>`-(>bj0&>{muo*tv&WD8CJI`DU(2@AgoIlKK=3FcUq84Lfr?lO3qFU!hCaWW6u=KC01oemH{KX4mx>?8zIO1NH}Rr!d$s^}O9w-c5I7;Rw@ z&P3ZQv^4GxJI7+O>-F?Dg>^ht(AYy(Hp}4lId3ydb(zf~Nextc|Bj(}%mcobOrCO4 z-E9%x34)Wi$~zqK zUFZhiXBQ6N^%cGT2bGG7kDs34UyD9)N$`qbiL0g*KBzd&2KTrGWCGwst!<4>d_!Ma z``D?JE5CeRI{ELn52q+8Nh|8f3if(?%leHHhv-VtvpS2_bbq%iZ?W4_=2F%YaqmS# zu+(~%Gf(s>lI`Z1hShwHjuG`I7!pCG{@io*uCXl+Us&nbb1;fDGqXhSS0^0keT2Qk zgo|o-_wOHm3n5^VbdwC2JjuC;Mnt}nqCH0;rl+H(a0ERA<08S1dVs~;+#bbYz|HMs zadjv8OX4`;qj;nQ{OktvIyxK}vJ@K@k1WL?TD}iaQk`qB!VHXyG2jbyAAHH|&q?v99H59Z{tbl6~SainE$6Ws%HScBAHugDJe zfu`&3>K=tOo@uoI{vQg1LT~2#bw0O>5R zO9KOcvn6*l)1Ke4_Zb<~E2N=YCNE{?Jpf4=s=5|BkcB9hm`gQ2jl;zi^T(jyN0`3A`9srQ_NE;VToYcym^fzVgB<~A9`3v9a zpl``ge^*C9(&s5`$I`-j%InIy-U-$6$B$i>>hK_go!;Na08QQjiAl<<$O|mI&|bG` ze?ym*Cckk?A0iE^9~jsgqPI~x{zhZsghd3)#ojE zTWLPyeFB()$qB-e(&gkq~KL z;9s>}fp<0!2*Y^v10fVUQ)&$LLzXM4r*EQa%r#68A)IOXv^>Bm{QMi54U{o6k*-bI zH(3Fo`lQRx#-7)W-p_AfS+hehL=0j_Mjs156(8-u@C>SNve@St)|h@L$f%haCdcSB zAG&K(%L;{oLwZ5-J;%`1&LLddW4r~Zd~gm5>7`8Ebe0*}_-wg?aPAM@w~lstZzcch z*WMQ&4^Fz>xR1T=L?+0KFZH~JG|Eg_W*pZzKjfVz;3W@6nCcriM25k;-ix->%jWn0 zF#oGeqF#6Wa*dyy5Ib2_+#7{`TGKzdxD>zsjrRF1)h%Jr6@QzK#l5HIlW|JA+`=rI z9@;{8^Lt0laGdUmz_)2G^!0gVqKtL)58D-GD}~d&G)50l$%n>UdBhurqgjqrL{w|S z0q+S+LOi-Ljf>(hNvs@8?F?LF-(7eP#&^M?3`Agt_!D^ifZ|eashDDaxE9|c3xbrL z>PIc#C0#mIq_`(;wsZHCi+7&H{fc$WI4iiHuq>FZ!Vm#i3wz9lE z6xofUrh0|0{}zuCl*vdqRX?m=Jb-5q$xjS$)7UGWP0Wn+n?LXPeXss84R>Y)(ofIS z{AbT&EbTc*P`@#B}F^q{jAQZ-4Q1(c7j%>tTh#T%}^X)^XK)6C)Pvi z5*J2hQPZQ$rI1Rdu#VdMjM4S%$o~*0PsGQlUP&q|4>qr@7vFcd#_b(iTvE<2zkcaI z&=*Xno(6(XF<v#|bs2u#mTV%x z{B<@O)6WbJbF7#aNiE?!2UNA6A|A1&`5WgzSu?hf>2q$jO5A3IW0fNH!`ROD5@+qllXV zT3l=j#!3OW>N5gJ4g^vYwe5@^l4CR`Zgj!nr^C&pN zkLU_(9%OgRh=+rN1H(ZQbS77Hi<0(41{XE1HB2L?@&DkL1!VwFvlDV)1GdzZ_Vc0b z#L)vg_+zwrq$!tV3uX|&w77w(lp`LWw}nzn3!e{x=Y@EWa4rE2qASuSKpM%YIehQ2 zoxxykrDwC4J~(P+5sQ2T&0LuM<>I%CujZ&@;*P%@W>v3VJ7HTss3c{TPVHn~?2xpi zgilWDrN`ja>bbh&)sZ>MzvR!W%DLzRGjpVnl>O^#{5JBp$4 zMi#qXtdf(i7dsU{JMd8%KQmJB+a8ZOI|JXdJYN?TH6XY}7+jm_YA)G7JZG(ePrwtr z(!ucO54+OJ=*KJGU@e|lPy}jnec$sZy@&Z^zM=)$lvKkJ(ozFTye} zq+i8=9WxfO!pBC_hLlw)1}4R?zh*2<;umdQG=06|gr(R-C2ZHkrOX%Sx>qa&D z+L4#n$Q@oCHv)2IVFnb9LZHGd3tl-NDo<%&{%jS{uA#DR;D_)<`1wfLwfV^U-;T|? zl|2+$W1!_SUO%MFncX+bZ3G9)eWHSRt$H)@bx|QKV3@Fg5Y$iiGwl-O| zDE>E7H7WXhpGaQeh19X^Kkh6X;*-DjX7dxNr@Ug+uQ^VnxJg(nNqIjC!)#q|lTd=}+cVL1FsR0EP3(!ngVmXNFS&Yrw!?o#+&FH*y0&6?E z?*OSEnVg)QDQvK=YO36>8k_vU>U*_)$f>L9tZz+~<<-W2~YM z=`eEHjrby~VvdV%d>u1KN$w(xl?g1B%|m;`g;)B!09;C+mhnPPvnyRmiV2`~(|Mvm zvwS?X1NQChn*{x%s96&gvXN$(JGk~o)ko1PtDScJo|6-yh83l*K~KvPVI}71r4K22 zZ^TW@bJT+^ag)Wx7X!%ut`X!VW$bltsrd;2o(Yzf9sKA~(Wj6xuI#mw+spPp&X>qm z$=89g)zfEMuN(>NCZk{?kS(~p3G!o= zsH7&i1M{h4I7}D0`B#({QndeGKZF($1=kuagwc2Uy%W8omcVls;Y1cM;$=a-UGGVd z#;mtx)4~PXb6MWg)U!cHMG1zgYPhOYwAvw>Yi>qoqe499DF}@n>8QbBVfyyS+WyAs zRGureN)}Gtw6z;R%NX}sk}%y94py!WLUsdCWTq+2x$)@%GbzS&>KI^a0rI3Ta}Q@} zaJ|lrwVSFY`=jN>14%0SmwhPr~mBfi3G9*gO(BT(}NotZwrvOqE&QFxoB8*!YUe39g=b4FK; zhfa_j!ildFn@Vhen8ii{7aKZO^cqa|R$hcq4b{?am1ICAIgk1nD8F&A1nZP65Ctpl6#5hn0|t-xd@w>v(Ck25n~I&AiCwIt zx`9Dt$LnTE55j8ggJ~)!p9G@QxFl*xEg`G z38cG)C91)cCUyTy>h<_aS4Iu)H?J@|BnN7Vr?C=-5!K|W0*sByJrCceVu>Hmy2_$z ztDCu~j35I!`sQ5?_xgeI;Cfc~t4rH|3jpLmi;QSZ-DDuJhH-4({7S%2*wY?9hjH${ z2=~*Zq<8Rk=3d7mq0nup%*@QYg+Q1RWQh?>i_1fP2gLMQSs2y1nk3L@`g1(W!IXq@ zHN6dr`qLF81LN=DOk6x-$K7p2v>4p3w2t_z!d|QWSA|{sW7R^=CB~3ddy5?{B(j}B;w=doS-AW26U1%~(`Of`UxN#BroJ&H?yGFYXvwJPTp z4v#0%Ly!HcFX;L9?ER@4GJnEPA*!Asp0X^~A?sd6vj)rJ+a2Z6mY>vfZSdjZ1ohwi zxai{wN?>3!MgjiCtNpJ?=F?MY>bZ{x<*4LWcw11hbW2lg0csj-Bw@9Y5qWTs4^T+QK{r6D`E4@BTL;R@M z_R;z(`)RyJ#gNrW-l(DLDo@mm3+1|tV}(M72+~@PkA_=Jq6-=_H8n3Z*|Md^KL=i+ z((Qz|GAjlrFx!SMNh9$L*MbO}L#ezeoj+L!p}l@N)XTq50SEwSCJLp6uf7U30bO#& zyFks{ASUf$jtXW_<^evU0HD!zW}sAvb`I0E^f2AQ9)+|9<+YgyJ$QUe;kjp%7f^RcfJzETlCC)IQKg9uY_oz+o!Bf zVaW0`kzCNObHvGx6m#6H=sU%JuV`Vi`W2zNdg0?K8COMgdU}FnB5s2zs)pnC+mqLe z42qH^I>jku^klxIa^ERx@mKY;OAez{p8YL-Mj5$flD(=rRf0KiM%bX(6^*8*=BdPh zeOtRX+1lC~<5a42QCDxJz`9lUKQoUVXDAyx)e4DkLwFafIXTN?&N=HJpMl>X9 z&n4UB3ZO~vuX{*+1*G5b51e*F8Ck-D&PjF_GP>O3vgo2vGiD@eHbigt_RSlrnW3$; zO&d4-rgL`d7IyhSW9EfYj{AS;wf|MW;1h~FBFG7etM6W}B^B|+2_(hKc8>)yhg1wx zz~;`^7uPan5nS)08LnfJZSC^3fg8~dO^M`|f2ebjAjCok@7Cwwr*{@&NyVos@AKEd zIJ+Q*008#PMP@vh9iK%`SfS#P9S)2NF~*rCB;4StRHp?0{}1(I^udm`&nvwMZUL7< zgmJh!I`*=~smjDzl`v{4P5p2Nqz(&}MBHM_0kf%q(-p!u#s|ZtvNI zPJM{;MrdekJ%j|1Ckkckud;^zY-7)0kK>Qh6g0Z~(TYRgRbe*IIX)4#s0Ee}s1&wz z{~h!LkN_C}tO=qOlw_IvwsekMp`PVsp0-G98IG;f1ejnbs5@=`!T)oRID?V~L7_$Mq)mlIa73c7Maz8VUH{g9Fdx_32o88XMab z3e%51xM#G%>tSDYw(hTHe{@YATJ<-1i{1M6xGF<=4-_XPqND1BZ}>EmC~j5PI?5E+ zPfjL&mIMRs{5^Zao#{#HYeHjsizi@Dy@_m3T)bi=+FsVJYwf5K$x>V|{tvyh@YYeT z`O0Gs6Z_5&98`Pb=b6t!1!P)&q?lX~%aD%L;hY|Smd;tMI}yfTC$BP_Ed=#cgU%iu zFwF{jl8=i*$jhdcUVE<4>TpK_Y?^>YI4Gz5S&bAHQ2o|OTUVM+SWMyvnlITaMnRl9 z8PEbIED89q^m3)RWm?UxbAYS4wT^8&AJ4f8xeieiOacuwb9O>mJl~bGKGAe3L zLU1F0)K{H=Bq$mO2QB~*UhnUi9jMHk>9+#UY|QJc*3^o96YQc7lo4T#kApR9g7LI1 zx|eMpk`5vn?U|6JvF^g<)< z=>851qch$G2NE&R3KHiq$`yZS8f%tl0;KaH5^9!X92qwwQUbN|%hyGdF2pg>C;0?b zei`*qmej=jDi*!_So9kD`s#>aI<)%tKYvc!kxtnj8XCIC2uytEc|W{q60$4f7+Bs| zv3uL@n9DOqdjGv)+JGOQm%%?X>B=m%h_Ii(1BAIUU~E$NnvxLU$YVVPW0)=1O-ekj zpI(73SUrp{JYsnjtwc{N-YMRo-vq4b#>mcld}4wXJfk4!OcUZ>{^MI5E3}O(5Q@po ziOq>ViA~R2XVz`8g6PTvKiZJ(6AP{~%0{W<^iSLyx8duVs`=^lub_8e#Py`5lP zrmMfi3Y&sii&;M&_j#(W&MD!_aj;F)UfeAZKZIMcGE4y7)i%S|(WQwXz1b!e1-?RuqlE?3hK*6=$qFc65*yLvDzp zQ`&a}DXMg2l~i((1z(SwoS>eMa>68jCQVOvTyN|3;kMd5+I8+vz>0Z2NJXK1wl-ZT zhVwa~D!O-Z~@2Q&s=@7i}y+^(!+J;?rY{1M5xf%NN-9I%4HrzDUeU|^rPpe~I zT=?S1D(pToaZY9;F#+W**z_j1CxOsZVxvgYN^Akn`uu<7LoNJ7H$C7r!@`AW^6dN?=&a zIHBCC_8_}G>@g78L+zN2U(xbb#)50IzWfe*9^&qbakaJB9C4KT3-`@uz<9+Wv_w0Mlx#!K*8FFm>s1qLl*_D&vSl45N z=lUyfQ=mIcd&dclCpE9UzPab+)K@dmJ)76`m~@xeTidH6rgL29hn_T#4@ge)XPqbW z$EIe+rt&8yA9EjDwmOvM9#Xtzd<&Z5b_U*q1oLKbrR6GLLAaF829;`eGuhBUK}GJ= z%A>LpoFox1ntufIaNZaL(XZJ$6{@WBD{i4|-2L&KRmn;lMd(e+GS zYty{@FXQew?Z2P_4rxuF!>p9`o8s!3vA!nvi3V`LDXlxQb|$!=O1-{s_lnaJF}6<{ zR|NjD_4US^$;Ry1HxHIRq!D)*JS7}tC;v-S;u4i*gPWQetjJfL%7rF1Z$E0~20Cx> zDU>?lav~2%TOP)L(iE-UZBj#ohJY!$`8Mg%z4lY#vpf4uc1@r zR(~3rVU-2PI&QrqInP`gtQmx3kbhL~kZ=kOql>lzsV!zk{%W(TpoZ%y+a*36Bl<4$eumru!E+5OVmIl=BScLz-hhLgk(cQ z`>iib2v1sIDR#~}$xBfja~R950e9ZADJhK4 zZc0e-9PbTFNrqNTN^X;sS#q!Wk+`X~+)doD)QMPb?EqEBG1M_C(f9P0msYHgO@0^e zl73I{MiMyWXq|lV+=Z>5&g^prdc%J^syaSk5Lf@EU(HlTww08c;H}YgKlC-x zdDxootKqBReZP07T=EgN)RCXx^NQ5kTzfj*dc2*dwZ^COU4}lMkKHt$<##c0&L-My z-MWT^i_!OY9{rar{ISL0WAqY^`%w``oIi!XsWbHk6b-B{UWf9LdrkSQ!Z6=ey+9Q(6 zI=WOuPZpdZG5SiCWp7YrlBMdl?eR`MCS4|--8_Er4!6z@Yd^QT1T|+y(>b>d3~%K; z(v#xa;``7-?Pyj(vf4-DSa?owy)-R#tL18ukqX$He2M})2 z@oQ7rv33@!5_1pa*DcqxY-z+2b`_VsN+h%7L2t!a{KT^X@;} zL9+8Q8E}|!{%rCRocIBaeix?=J5uTfsOpY%YcJ>I2TC);I%}ZMj9SKEtDe*AiXxv@ zn&#A)ud(;4uqP}STz+H7>6lM)HT}g<4b=1Iw|+{hT^f8$=_&u=9OqceqV<#+bGwhUu3lVNo{TA zksU2BTn*bT;=bceaS!z6Sj9V)p{RM{1>Sr7k<%J!#~iI3e|4|PKhbe^G9ktIVWUgz zxf;vCMx6^W)0ergK59OO1M=aW1DcSe8tltSvm9vjQiTo^EeY%vRt_lLfgLT6581Q( ziLm9ltY!LIO|e1E6f(T4fsi6w#g;H4qH3@IqPKMkeJ?zuWKXuKjAdZ^LB)25+&B65 zZ}LB>Dg;y(O7ai#@=B;-f*u`cT&BaffG&x>bpvoR-!ZQkO?<_M-1IL!2BJ$(v&8ZRROskFce!}x4#^yzA zdK2eT8s7gIo-^geee8I!gBbroCHD`a&?@c;2>YT|m+gY#{4sqEJ#17X@srmX0G}aV;wA#0(CVjN!sbhlm zc~5#*|Ie1(-*zOoxW`R+D;2n8)DCEWFxtYk%W-p!3rnuq5oh}9=Q_@$3p z>PbeH1Fs-`zH1Y-pd)8$Nt+Z~2fsgWmE7BU{M`Gvfd`uV%Aw5ULS(LY{S`&xwiEYT zh|SgN>u)`aSFgX(YUMl?cORYc2!H*%d)ank(6idX{=EK1cc)$bQojy|zy9rml{9Qr zEL%{Qp&hP}{?^)I`7(XlNhg-;ka9HVb>Yaz9V6@967nnl+?Nig?^TwaU_`2@1$@Og zYh`%9Lh)7kV?2I)3yLS)6t8&mm8x8&$eQyv;mknpGxCYEvQYWiAEpvmd2?HId|T}J z{ZVq}O^(@(uGd{pCdWM|pETVjrCRm9c7Zut`cn$5$A+7798(+}AZF!QxRajV4v{ZS z)|$P6vgu^WaNqWHbRbA%gw?_Jwc##_8qqh}a=1Cy>ojBD_dyS!Q0)g@6m)v5(d^vk zO;Zz@Kd$Yscns|`?20I#q03z=$;Wl|OE^k7de*bibE+rNJtfZNdFtJR$sKpB>0b6j z(FK|VbuGki)Lq`!?R(2T;;PjDmL2yk?btauj{ebY05-XUAAgLp-qT~fXTpAh(iv-# zeWLQNdaL|Vx0W}M)R0$tr$)|Mr+R*8O}A%VI363pw5!<1<2^YPL@4`{!Q>A$$Yd@wxK>;6FWBkL9~ zMwNpm+ezmb*EgZzRh;QBCsrLjo%b^JYR;`V)wP@2qa%0T>}2ZhvhS(SvLxO$IAgg^ z<+s8816ooK9w)y(m2hQsP_zadArZ@SZ!oqWpBPEO&>47{4YC|{&; z*}bcGs-w@XqjwT|JiDGf_wai18J5gp=bCc$?hfmtZctxmeVLPRis(Ek@93A}%k>+3 zm+tz0I7f@J`2kxx8=|;5&gXI{Y`Gs0ai!rv51d3aKiE$Wxw96Mn`_2$N^bR(1a`ff zD3*st$TliT`{M`RGEYyY_wUP(V~@Zd|4vRH^ek-j9qMTOsP#B(w!4p>-jQDCU}3QI zltpaQ*AlWB>H*iEZ-GqvgJY>QLS_9^X^8`S58kJk-mq6qhXTeEhj{*DN#{Qw_3h#| zpP22rOWN=DI>D``u}Ip%;R5Q6ck+zJ_dB#B%eAGt)A^ygv_m~^Nz1vb$HTY2I-m1o z`g@O=r8C;Cw^2jVmpw&=Q&-)Rt=v`)+^KIE*1UTry(_0Cr~J*By7qa;+Bctak}RLq zHN3NC^>QqWE`#h`vz>ylYU<1M&jY#%iL936_wF609jiaSD>w1@CU&F46X*q_vFQ_2 z(^~a|+()SQt2v=wd3O0ksunb8x>E;5ES_2F@nc-oXbmWlZG8L4o^O|@y85O%20u^CT0QY9%DX%w50UJv#(VPZ+v~=mE&MwEpew)L zSJ!3T82R-T&F7jQNau=gCEn-$UI;A#?-u*UaSZBfC=c!IE#p*MT^iCM76r|`6IMK` zt&QF#nPug$V#Udbf$bT=ubiSbr(W;ZXyV2~moQdO(?q>ai8{2)->>82=iM7S%{-+e z<>hFZ^3#BMF+57<&;8K$m-E84XTY`R-Rs2R_~9{i_HTKT{$c$Pr*=Ip9}MXzB=N%1De{9Qg9Pd8Daonzd6u4ZdoW6_zy7R!Wh z&NREqtv$q;z*lJFySY)BQ90d2KbJ#2=lC5I)5SMhZxI*1m(NdxBKMX4zBU~F6ZH3MuCnws6FY8NZ-Q#&P2OL``vcSNBM_N1>D&MnT3h&Cu6@`euO5Aa6UUNSR+jo+CrV{ z%drot{>aGhdVglu{;!iXO`wh}&8>c52Q))eP|@USzEjV4+O=7ctjOp%JEAG&S@_n$ z)@40B{$x9icyNeucazCipgyW=FSwmO^QOjgq%XMQ4~KQ##P zj6)uim$?NV;C@*~9NJo2U)Sh1upuf7!qg-C{Tj3S!KlZ*)~wPeZ`-E$Eu?cZDHApK z4b-*-R2REK=SUx>Zb`z=Lwx_Fm;BEgKFa6}MK_rptDkT^oR;U^(V`p9O>Okc@t6sZ zpSzYqrDYQ53iCBxxSsjX$|EXaClw>!cpCNKfj))Mh_-3n{gIqk(2-=I@v@UvhI>mE zCB1a3=tJpcd%qP`l-%R5qN_4ISFW4Ez0i{$%E*H%|K#f2SXcRL$0l1ImUf%zYF~M# zdzycx`y78(d!6xVpG*g`>kD=y=Y(qu2Cl7p8CH8HVZ!7o#4kNL$E23D+_Fz^cge^OFB~Y? z=~_6|m2&gvnhdLypPEwK;0aeBT$+yC)~FRESe|>bHcTl_eJ$;$Ul>hi3VZio@%*Fi zXK+5YMV~8jh6puD|Bz)y?N+By-u0y`YH;(KV*pD&SzMp5uFd6=?|;nv;caz~m9t5wqm4#*k^(ogYydjL z>j$;yWE(@9Gk%CIbRT=b6A+3cACsIOzFRv!P@PkklVoD0e9X1c{cKLO<)=oE++C_2+sm!8hj*^aRm*$s5(f#@ zJyx7!)AEh(38^0wvfdQb)jVvm+VUdmiBzTbn~MCw;Wxc`<-59|vuEB=cw83r5ma8n zf8@zo<=paXgG13ibM2YfbJbdE8G?Ze7q@gKs(Ze?@6K`diiK`>4T;4$@6VlZajkqyUJ!KKzhlf<** z_xU~}pFF2{-&y&ILA&Cvrmnon(Mu&eob(+@cEyZh)(0ZrMJ>m^e#p@+PW5eE+Np>R z>H09o=2q%&ecU0<@!9bAeodLU)Pb6}ec=NMe{710iIJ_?cq_x&tsUHH&)d*>DXxG0 z%hD!h+&HflHGY6TrXK_Dosj z`R=>`4{L;|)`WfDd&v(~N;y*&j=<{c$ zV+z$gg?c=bdOU?>haSqPTJ9$D!T^ji&g^D$aQ2gJYW9St3&v#(mObFT<4w63g_)Lm4y=B8!WrcV?j^E zLp^T{6#qe?=kxQhU))P@D7rL2Dk8n?v7Wp5pdj3PS1x!jIz53P7&SRzYHy};lkPP7 z1#)*=^kp)=YaU2n}cf$7@e`-oov?0H}a5Qm=z+oqUL^mm6qHnZt zMv%Po6YYd#fApz0Uf-mU?vhNitth>wPO#T|2Q4WsP}DP4WJ7mx=-+*@8d96h5UQ_uWbiwBR&**@`E zP{Zwo<~(q8pg?C`V$RtkS@Dgv1AaSS$MupPde3lQjo=P7CB1R)nEdmJ_n*9(B2RbM z9*B`!)@PeCLY!+lI{Y_rGoSuE!iT5o&5Ou!GOvXVRQxIXnbxcNIXB5ESqB16bMO5^ zGf9^-Nyk%&LmhW5TkI{N{3HY(hO}2~;|c{q9<<|s)UO$t{78;1{!9bU==xn60<{Ja zEiRNTfiCf9%AA!#;V|ZDbxCW+N5RMUP7W8K>7~`dsUGX@i!W_wou}46@@Vu}o46q* zI`vLY&Vzz;!%(FC*s?!67E0fty<~RVX*l8AtH|1J=-4E1bP^oodj{ z2UR=GkGbCL+>ejV&hcei{;ttsefcHVm)Gj&_L3;Uv3B!x>uy>We-v@=rub;hG`q_V zpSy=*JEJR^@*XSg`gOc!w$8jB!1wOw8|hryaOP7>`v&>MeTi=IXX=iv(l>27cOH(S zrERZFR-rl1e3K0UMrpUqK6zlqW?3&p= zHtFipH=z8&wQKTE4_}f$^@V#!ziZd)!c*x#n{!F!4(Ne{-(4Q#H3g{m)MV_ieB-YC zYw=BJ>j)<@*B4&B?EpcqmRGKFvP990I2|Y0GWb1Dp*|ks48hZmG75_lIx;P*pV9;1 z!9<>Qd$-VUd))7emhyFfKh^T6*6B!mT9<<$MK|dyc-YwqErHDj=&}9Ba9)4Tsgrq* z$JKt%YaASTVDm4?84UYfN!DeiP?Lu^y|b4-7hIb18XxN8x=%c+h02wfOzDdOpj*a= z_#@x7CXJ1Np7PxFZtZY%v(A;qoW@3-x{f~RzzJ3?>GAjek8#H{Fbjg z32K+r*XLHbl&6mkXvfxvnXYU)^O|&UN?!7U+U^IrYt1Fs9r|r>r;;+6d+hZ(^_F{0 z>vA%U)=gc?{86)2HRBLBr{;A{Ce(`U8tll4sCRw3Gcl-$pH~Nuva0DasgmaYYnuBT z^I`NrjxXPPm0RtlmhPr7$N*e(jC4$JT%ICV;{a7D(0xa>A}CVQgw!zfT&=aLJU8bPbwj<@RdMqu<+S2t#ZOg&Djs&-ivc8-Lb<>V^IhGs}@?41} zYv6#eb6;1_;eN;DM~W7f={di%L6!IvIXZjo@QO{W7#p7CyqM~ml=qmm%Jb6Em~zs} zO-Oz8C|Tus0yMY>H>y>P^SFGxZz87kJ9Ya(XfISaWTwZZ9qPTzgs$`bnqxEj-}@H7 z_tixYdTKlpWO3+J_9LY;ELJ=Ozf$M4K#gQKI23F$D21G#(N~>KH$3ta$(>CJr0q|3 zJFD$DdIpZWltDo*J)*hZs<~0%bU|Isb?wSkSs&v19cIW+I&(O0_ez z-rMiJ);ktjl;3_~d8vADU1R>fHFYjrPyui2)6{Pef6BWI4SNnr?Q@B*h?F|>)@#dq z$F<@59T{30sy&o&!9a6G5d+#Md?4;{XD^q$F(k&4{Gb7lUw%jIF5RE z_b4$kRp;!C>`Z!VW<_z@+G!Ve^G)%Z@kgFJvK?=F#wPl5m#45%#N<+i(-zY^mI1*h zV>>KY)$}Gdcwc*XIaB}st4k@XF0}wpN`CwPva;7mbdtPJqHdB5^KM<&JJSoTRHGD} zc_t3bw|NT5#ABe50zuTC4XP!YKKzaizOklh(3e0S*9*b}zH_7Eh|ozymN zwmYvS^D1vzJ;})exZ%%z)Ao8w%Ww6BpK%j!j&ss1edToQ0+h4$*t5m9*E}WB!vxbi z+i5-;cfBs;>?*q+Rde&B^N>~Fn*`$qt0vv3l&nH;D^yrFqeE^;zmNwsCCyZ61mgV^r7oYs%J*F4}!t<#`XG$ApfsiIkF!b&JObpHH4 zIy-kq#+zoyS@6FPpBYx!HKh^mqBqeP$=;>H$y{FSz>U&9Yo^+U`9nVV7F*HtyBYcQ^9S2XozTQ*5zy#jA2CM6lEpv>1g(; zG49ZRjy^V!E_Lioj#W%@!S?u<$tTP;+?DJh-_cNWq9&k7$5`jy)TaKLpL#(38>X-w zf?7$x#|=Bo$~K*AbRPJ9O;u`-IotX?m;A*>#6dp4i5%O}6O_Ec|8s`l?@DlXg%6Ah=tx}#2w9-o=GLr>p~eNXlbb0A;0gn5fjlb_IvdnT{}%E-FW-ly~)xj}<#zv)0ks1vb2;*w?$K zrO?d@iW?oS1p72ksBri1ZL(B)?RH)@)g^j!w$nbtG_rze&C%c1uuPj=UFD5i9FL|L zocm#gl2Xo3zcsC{uDcccLuo1T%)=IkgHVA%_vnIsyUXv(_9a(sftre3lUO*2)OaEC zd|dd=;WyCT^he8~#+~3fs+~$W)&$RKyOrRn(ZnXLcdD!3Nu0R!$47Vbdx`hGV!5e> zUce$+9EXXQ$7S&9%>`+07k;N_?Z|<85OhE>pF96nMD#0oaQiZmQQe*i*$QgN?A>~J zvaURBbfTSE#|`xVj??2G9?luV)zfe^+$TJjIy%tB>4}+*nHO1s3-ymqN}|g7-2XT) z^2ugi5>u6>u^*bMlv1ZPMO?&g)p?Q(eB;Ha5Q9T)FnNP~ySqz$Boq*x9 zbF||gPr1{mQ@q$#JV-$-SJY_b#53+MFlP(w$7ITEB$yr4uW?2nIo&kbIkkSl_j7!AQk=ZZ+0omcGG%&$ zdV&ZUBmPw?hs2wDTOuAjdLy_&)Q0SN_t~5`4uC5ODUiA4Gf4_5>1=iBpT*H+Id3b- z3}1^1@+56uB+Y-BpPQfjl%F(}Z$5grr-WbLVQnxkvLm=nZ|t^MJ6T}POPLorSfX9X zEiJ4mEez3<@tV+Ob`>`ZO!yM7{59l5YiFZvCvJ;cFB^}p(;Lma8vK#dZnH(e;mh#c zCJq#@@kEE@w=WnR#<-<_!Gnjc)m< zzYpe5k^+m@$_vzx9clgqJGGJ_9p2ch{pt}tSx0lE5xa|Rb&fUh$+i-uvO%elY;POJ4D zr136h37!aQMyZThro1RQ3?o)J|#SEv;Ka^QXrBj2fLMK#dxOSNid>(V|f`3O- z01WRvPOT$pyHi!&x!uYW)6 zLiA*8#e;cA-sYFY6sppCE64&RYNWgk$7br{m`W)|t}dAXcM^QDllOQ$rNamg?R=uu z!#7rydc!u$#IpSM@ofT_clnteC9yMPKCZ2aeHq9s@Pb9#fI#`J@QETbVNM<{U`~Ud z7~H8RQ)zQ0sfzk6gIPLjQ9%t9sQOyW;+`^B`^ff|e2O+0dr`b} zZWA+i&gwI@jLb~K8I5+7<0SlFX5s~EgS7q%-OP#a%LJqjT@cQhVrE-L=)6ejjUa`~ znPp`3QAs^DN!O@hZV8nTJTJ1jF!WOi@AACJfJ&Zc632$+ACNR_z%S=5Yn~TbhErhH z&Wi|+fQ;~0lX!5w^sJ3Je>;gHUKnEao8H82v9jX5gEoP{(h8SvyXo;r9ho%>qSp5B zf!b-Ho_c`SyMO~1cpNVClo6a24WWZyt$B@ zC*X83qcB?4gIHHk=S9A=NnpkU5T8ij@=x1@K$d-?a-#V21dh#X3Y#WH!NRmlh5^q3 z)6`JhD#5Z2{~!F;h>e?!)l?SXuIp;@FQyIBWD!9)nc4zJ-Z!Js9R~_G+g!1^X1!X$ z=W_E*ak_6h4d*gSt*gSx3BKXye$pGgE!G840!tNE0))%8GeIIiVOEf*fKEV+G4kAZ zJ`^J#PxCNd>nFz!1+j|awSpxw`U-v;0_7gzMZg}pAagD}mmVgb#~lp;t+T#lJyId_ zBEhslU))h(CnQ}(%q)g)y03-c`yL}Y4_{8bf(Qe01jrK06B`|PARhd-@73AsS zMi5yZSeR<+dcplps{=rr7eS=8GKb-6H^7p3J~6~5#Fv`|lnjHB0d`Qp%nDG%y0BJ5 zScWVxZ3T7RNO)F*-x^qIFpv-+v-%CB0cLdvvFNpt7q!A(`AZ+!;T~WoxC+Mbf)U=JTZQk%gWm)AcX*r8AlPSaHY`vq!w8i<4NPDR2Cbjd zNyAlwu1Fh&(zPo#8h^i86s(PSfjH<<;RwMm#UAwM-*(j-w2>Ff73(r8^^*Z^CkjS# znd2dF5wIUXQMehF0dG1LT!l9d>5U*HEe?aALW{LtO*8*RI-P4mXXoiVMTg8K4qEFrij{-owciXAI6gakJ zOp=~2%xYC>mG(f!0A2KVKwtoUfTkae5t@SzMq6xdulB{-IZd9*XeG=o>pAz2? zySnuzNY657q^Z@w2O%)(f50uIX)mC1!3G`%HG`v*ycpTPk6$aN7SX;4q*2w)ex+6{dKzw%*`JmLNDhL{GD(Qp|pyilyR zu-B^Q6Q{~=#RQq*zw9%4%C{HEFoFgE#RkQOK}biVqOq`VLD2FS`4(Fb{K~%#zk*-> z#m#WF)q&ub2nGdU1sHEcZy3AZ+O17b&;j!JHSQMk*$kQaU0LDVWVnyg;49Cd7Kw|^bp$S9K0757MUBt45*Vg9aF_lRX6=0=6@rA<; zh)U=_guko>5};eHWS%0ZL6C!+(f8o~zzl^>aE#Qv5Lq84 zX~{|I3!=L-H~xW5MepRbU}z&N};R^z6T zgeqH#;+_bCf4Fd9nIk-Xgg~Jv0ZM{EZjc2OD=Pr>xFWg%n!ji~fal+&?%&=bntTDp z3S&h0pit}qFm6GzafBUP33_kZ8R{EL>hq#mZvHDo^+pxMs*BGKA}cB+DU5;Xez-IE zZGJ`wsJlfd5cYb}oWSzGeVIwfI6jKHrp@NRD zE_7-GS7FoJLX*+cNVLR?Jg~(tECiv2728!ZG_rO|6YsZOYq_W$WGs-b<1BMpM@)R$45zM=% z0DFzK{RPoSK3Ro60Jj}D{R1I#>C6PG@KK8s#?a0o7 zT)<$+#RJ(WI1v24psCtQyinziVDAK})EFB>@&4Xhc*%_+ilU>LzXZPz9>;xZtyy3@ z*e<*wrriO42^O0>;tt!8o(N;KM*ZF5`VzQhXg$O-z;)@yhx2#LG^aU(j00t_MyFsn*ynYS~UeD$#d`L{iB&*=U0B5g2RuBW+A zB%!iGw->e+=Ga|;9!X%ClKv)Va4wPDHT2@PKcHV=YYZ&$oc9#Sety z6oNS;n-?xF+#I8{l0jEagUtp=hN z5wL;zTSA`;_IlSa1RVhE!!B~Q!ezyiF_bHKMXxMaNTs5wU4`i$eAZv)QmAJ^09OO_ zGSBr!Gs-YLi3fK9Xry0CHUyDwJ=Qa<|*#>4t&<_JARO-nXU%_vtPzVu* z;KzYYh^b=4RMF|URbr(DP2~ubwK5gx4+Z?`T7;8%kzW7@7#p}nm@~3qc`(8{lTM%E#b+@FyF2AA=s7Q4qC+h1-6OI2og)WlC;`2^j)A92$OVjq-A<( z8S`qf;y8)79c0o^!*7e<8bS0}Cm?<^r7Yff;U`9E1>wrqaCP`^);q|8?Ft?*@-t!I z9$xGu%X!Hx@{{&+;za;P59}v=I*i>Gc(QusuMsO(Iplne3oQ1M5v&~t84VMA2Fwif z;+gv51U^1}N-F|S#z=sU0!3xN{D2u8-^%%VLnm>HXV4&493uo`k5%(h?;>ug!JZcyVUdyhvTicDQO1{=+pj z$rPu^6EVhgd71Vb#o(xR=?(gtS6Dmpk2G_@fuED)XM?hP1^@AQJTay!W8cA(wnj#s zG#;rdb6!N=SG;67u&>P7VVmWcW{xnXz&`@?GuuYSS5#21mvlsj%_;aTnm3bS8BZ!v&BKA znBuMAD9YRt;{XUc@E-#jqb9SIx(@g0Kt4%v#3sPE(q{BGtF&B?10{q)Kv{&DC58#b zJ=@e{Yen&GS%NL&#nZZ+<~d2;_iaQ@n^i5^J}Cu{HnqPfJ|sJbAv+Ong=TJ&y8|-z zIiK8(Tf^JIpk*vASvHlyo;XRq_kAxnp*>EX&pi?zbbK_8FV>Y=i7*5!0iVD)67&N+d7&zRS?#arr-A|omB5i% zu$P<|q>cEQPc*ePmFn>&(LIDnrGxwRJNN5X5hkHU3{Wi(IXDn9OW_%{)A+C_r14(z zFZ1qqTiLvM^!pMl_7 z8%zd>W3jVMI~^!S#!xW`^xPOAFlw0eUnVwA?(tv2@cX9Wa~1>Qg)AJ?*Ctr-O&4vv zM63_3YcdkAW+zw5I2j)K3Pdh%8-8vJbCmg1tp&%T3Es_%1Y#4|FaOz*9<@xgETm5d zaZKb2d^e{v2DpFA*S&(wxmRe(14;+%;i7LtVh9l{34kR$7Z>S^>$(9ufn2mF83W0B zNv)_ttF;5&pQS8$GKNqIvhM5@xkT61ohvvrhWw)UB}%ZV?*y$lFA|1`43dcCJ;D_D zwMhwsQf%zB%?h6*=|O>j_fR~JwUU}|ZlcWWm^meT#B{ePj2W-)>7bD15woDVRjjvb~U60@<ql3krJ0yTB2~%i!UI2(095V%tE6*J#rA?H4J51|GA+u7_Q}96` z+No*BR#xl^siZ4SP31qZkQHcJXDiNrvDYW-&)em2-MS z)=Ii%K$Y9>*>>@v(yIC_9frT0PillSr8b`XFf7P{#)6FvuEuXuD=d*^`y2;D8V{gl zh|^(Ir4<3Pv2_l4Wc;`oMALZ8vI=StXr3}s2!M-9c6B71a95 z&dO2jSy2v_>~p%$cE}ErYdMMp`WTf_yt+z5ilq^ar>Nl-VBynd0Jh%3Ea5kxkz)*N zJjn^?GUTtoEaNorIy$L0LDywXXEC#YH=_(;Naa)0*pL*8qEWlA?3@aYHU!~jQ?{Kw zJJG>=WsdGMwQaS})mAd>=)81@b>W_|l}xiKwF%dn4WF;CbyhS)c=N)Rhmeoi3mU-# zB5R+EyQzUQy4?_G#N2M=8NsW?U(>?Z%(Nj0Xktkf@SQ8jk%Uf*tW#euqc~G4xoXPR4zFhd%$omZ~N5Z{3$UY*HWoWvh>ZSy zS^ou~zd-x9SHK|}k!_c`jQc zEob{&)dKOYh25Ti!mMO^kBir4j8iJJex$=KarAYjY@-)u0CuJT&$??3=Klb07k+uBzI+X$iI*i-j_ zxKr?>wW8VnVa+L!C@BKh6dYAa8o~Gr5&=0UU?dRcJWLF+!7%h*B}ZX@L#37RTht;o z)FQV4W>{AZO>WV;QY59-1XLNuc$lC2T> zP$ZG!X>G(BLYt4_Ype8bk<9gA`(9%s*NC3p@TVhK1eU7xL39LFgF3 zW${3m$8=y_c(wJlE_h0}B_J~z)U(?9 zkV*telwJ3J$7VwZ4dBSKzp*zkG~%$DXx(RBRkby0s#TTo*BarN3ZY^Tq5%isskF+2NJ-t#m7M@a8b(76T?t>i%zn%e#88q8CVn;#* zg#aJbx{#X2LZ?iode1bksZmn9r)IrX!=EgD(eKk*#C4ArIr#V{iFf$ zDBA<^js><|&@4cFAxw;HHNfN+B@<~pHghEd!z{g$y?|?4AH@vzQ9wmt97975*-k_K zPOx+OofaJYN(L+yP{slq1^Q8qT+4tHW5{6H?KcPoXn`34Ky)kog^&5Kk~F(Rdig#sfYPEkHb3EZP)h zsXv`IAcc6Or$AGC)s5|RKGs9Pl9#uUte%2t>ig*%ZlURVj7 z|31YEH`D-qq{_&Kkq{nZx()5CDr*#-l?=bAX>g1HKY;{555}+yID(0hh)dz+LO-e)q3DrYD1^j^5Euc-u)#5rhYRf3U@4W;jU^5B9T5J3E+~eC zxEUsp#so#ku|N$W!-q-(69Zk51_Eb;rQvgw8p0W6Q;?Q@SV6&NMwkJLfdmjw2+aU8 zj<7b^Tx2OxXe>D?*3C%5H1`(p;~t3SmLthzVc$rD5e0UGXdEmCD1`9|Mp4|kr`r_7 z_1*PZgug8Vj0GrFJDTF2$n_z$S3z@N`xbA{QokXhBI8B>~7|)Q~|U zRMw5;4VWrVE*f+9~=3@-Hq3abMtrGW8)aHl{5kPvh_AjJ$^4Rax-b!sZY>nTiz zS2FJBjNZ*-J`z5~?}0i1M9I#6+QW*%bu|P2(?KN~gG$+N00Qm;HV?59Kmdz_;DHW|4K4^X8(~h8 zEbxFl8;XRqEzJ1^VUP*KJ`#Z3Ql;Pu)d~s%K#pQ(uLSa1r2)tS%CI$r;ErH1;P9$} zr7LMe{wrLqr6El%J7ZMqe+}~I{Q_10x#h^$R|L0!B_|F3J&dAs5QVlYOkqhb!->rs z1GSWk=Dvb=<}FJl#w|FF)bFKusiVetoCSWug|`AZt)RTP4>4_4o24Nq1Sax>&PgU= z`sq@i)IOaXyX6OIvVv_!mda@ms=KipCkG>T;>+djA`ErmTd2b!!Q_jI78w>$nwaV~ zR?ha`7^ofjQY`zMPQNqC*`oMt<9@*n7^`eH!rZH<-)cqM z`CvOP0I>UBV(14GQRnMnqIjm%pUwAgJ`EZh)N4R<#kvkg;CJV@=#c z84pEK{JcnoCCqFII7KSijLoc_Tkj517pMuL8}pZp2rm?@F15D6SIiVg_CWj=?%Nnh z73{;Z0Feu~>Q||a+I+%y=yoc2bS6RkR@)S&A9Yv(QDMubdr7ATGlHQw*okUxDD? zeA`b0G#ch(AtwTaJRX*qM3_vv9?ajOoHeIQ9ez<@?#0gmy@%ldj43iA5#F?pjPeGt z2ZAM#FIXaD@V)>_jGkwfk*YGvKUp6pcD;vm)nOPMtXCxmiUJ}`U4erXe6|CbM3EXc3_gfenBke?{9+}{C0c12yTW5upDo6>|NgDSL39(kAtdmQc+g>ky|>VB{l5sE& zCsDnv3TyC^eon>=h#PL& zyBhoW+XVnv0ciU8zr(YzkZl;E7olYQ?TX+2w%mn_58l^5tS9l)8Vt^V{Bi?87jnnK zB$terumAEQSIJmIymKnH)&Q zFA4s3VNuwhZ9o|S>!xs>tG6Eh3k&!6vgjDZ3Tw6=X6y~o6Tgm-|JQVgXc)SITGvAm z5f&sg-+CpIi57WYD|3OUjnLf5dfvumu9Yo%G7vP`=Lh9rm z78Xzvr_m98QV;&MMD*^`zq3m!N}r(%f&F0Q1yMkdKq}!srpGAz-$DA%i~sXFD0YIF z@qZZ?eFg|ce?nkOg0^Q^07DMkoMx!bv&uFF|HTk9LmDe9pi9NZ5U?{KOkdXXThJoM zr5?Nk)VLm^{|P1U{wb@FA%{}QFC`HFvB3WZoRG{0`il4U7ry?Bv=TyPLi*)@5DJzR z0+<0$(a`Q3{?s~ASQ>a1Xj=h39CGl%WvfCi3mZi?!OBv0(=%56d}`^x{^y7gJ{1c2 zUy85*s=@v@2>){=;TH?~MIS8=VMb{wrhSN^klTfiuwVa%vFo=a4&D*3k%sUCtSTG} zp}<}ed|ec_T?{^ft$+vu+SsFT6}yiiYkP_wB>Qv&sG)_rH&m{*I1AJ!EbBz|Y>OZK zf4usOHo}{FVGN|rgz#H$M(pxsG5`JwF~40E#e#u6wMwBI3Hvb=bI^S~gu+Q-!B~I@ zqmcu0>~$1ZUfNdnTuPK2s6B`bG_!KCno()l=nFIhDl_=|^8W9u!B}PyT2z7#!R&y= zl?0-qm4$czZAjo#$Rm2~22URC>(Cx0zV?yS!&y-j7CVJPg%Ck}=7I&S(1i@y-9fUu z=}U!yP)-9DceX`aSHztxT~{c{5C?+F5dW$FBc}417CjWO1hja3X8y&8bUk}a{|AGjbdI>_`apGF|ug?w-{zbTku5} zZ80W-q8?Ylm%M`kfEAhiAJ_IjK>JUltB)+t7qmdh2A~fp_t*NsbPFZ#%SG7bVp&ky zB+me6IC6`U@x}_+W`j3p3)_L2r_0fXKHLr>f5N~{S4|WOu`GD75Y2$C-C{&@A+)oS z#@npdyU3eg5Q^k)(PaLcZ2ukXzZUR+dG(Lw{cZ7!_ae8fKe!{pI6z{lxIV*Ab|V%V zsjLlyKm6+%g{I9L*dxP;zxD1?`Qdy!4RBI2-q2)kgeH%)GXA&4FZaxta1;KhFj zUT9VSi@9BdY~ePsJD5I~fHJS8sMc%A7kvGbM((J*E>Merb~_>AtarN0Az~m077Giv zVKMH-*c`T(#RBGXD741LEC5uu#}vP$G@-BaDEVI~1iy@pJ+m z_ose@S)eGQMIeb>{g%ZU+E0HWh z6c0H$4zM-En1s%PoCL+rHyuT!AgtX@VEgM_HrT2tie8Z=!_UU>5THuwYz!DAv>jKVIkq0YiY4~-2!20|)4 zN1#GMRuDpnukzES;=7mn5xpHBiQ?}9F(bTFis9VKb`+wZUL#E3#`FN%d*P*EK1t0g zfaf_gx1E*Kbd;w~b8bT^x{=+l&x&eT2wPSY+7@ z#ST0S6w`Vd0TPQyYOtq_v8N2_Oi>p2fD~h@9J99Ydn}HKoZ#98ZT@^vD34;oi9@C3 zB;k~bAA#SA$^lFOfY~;f;*Q{3-p`0W5FbpsQ2}CISry@!%LvrE`xILt^6}RQRU3rk zAix$m(e#`K0wauqLq-S7hzNgUY6^s2=&KTZ$2!o!%rR%T<@sQmf&bti+Y&(HmGfbVLc)y&EayvHwoTFe~42m5hnL#=OM4O0t#=<#K zj2w6ps^c&;KL>_+UZrFRkwKss3^Rzr_`o~qcGz27xOO@+@xTzw(n|PpR9LKwkyY%T zXVP;&0ujYc$At*O0%#EZ1QA*IL8=*EL&*Xg3qC{C1fU{fO7beoFhUdvmTqTHK#6ly zE{!12{TkOMCl9fbdPH1^T5{S0wL=hfC6+y!ZS0_&Y%-9cMd9F@z{#_+v#-TKC34kLsXZ@9bO>d~14)=nGo{cml#MME0m0>bu zFSJZT(nC4K_&rEQRwj013r8L@2u6f<4qmA94E6VLcqm%a3&qy>XQ1!cgru#&)p#iD z=)-;WIg9zon81SI*6iK%DX3D3Fr#~j!?6Kkr{YGv1yiedG6Iq~D2I&lUq2$|L}4h% z9brBlpg#(61O?IL3#y=ipT%$Hv_cu8p+3)|0(Mm>-$zEJ?3@KEqQnz&_Cg|*dv0T= zhLE#Il0sMm<(h$1On5i>#_pv)AoIo(Rk}y1Yhm*Mb{5+Tt$@9jgt#FAc4Npbg9;ow z<8VVPO$6++5D|kU6AIHov>P-pvH_qhARV@#Sh3OyOh`a?He%&U&+)Pqz*?ZU4K*Nj zBGt}@QWDIHEGFe@5t?!3P*V#>JVHx@yAXq++LovCVAR1j*rCAo<5xgyWsW?=d_l9Y z7J!D0F_ga`V@pny+yMi+7huoeIXp&lv_uq-gr z5J2!gRO88ma+YiYl-DBcB3u$^Ljdu;>II+|Y)v?dM;J?u9SCj@Pvb~HT$)fhQw1O| zK_TG~#bu4&zXs|aMI?V$`l$c)zUO#afAiW7`9jNg}ey%>26GdWeocJ52 zGU4cW0X{@9G-7Tyr3?t*2upBrSSOp^j zH-HsHvI%qJY>`$M!il}=gDu#iK@!4xYQbnou_*S0$PFvPBVjCvmWv|HVy+9wVCR06 z`i$5Eg9VC4poFzBhrPf;s7^Fm(VKWdiR2S`|10XfG*D6G}me z8-g66YN>1$+G{Pa3&Ic`FwX1(U+#mB%pP!#mkQ545c%MHBG3-CVW8n3feIB!AvO{M zwi^_rn^ny-kUK0$i4K=t)ueq#MEGHwwD_&iOp<^d}2K_+;KKUduT5mQNXk z6XC3T)v)y%sE@9 zXU55oTalku#Hrj8z{ zt!$${&#WpbH}m3!wk!B-=0W1`G)glG@S~*oc@YWSH4Sjoo#X1!F?av}arP|$QI}cY zuA-t)GGYNG4$dIBW+2c7Q6Oz(pjffiP23GpW{@`BeZAm~>kA6bD9$us3avp3Tb6t& zSnYa4l+ghpS!`9%O5~y^9Gt$rn71c49CZZZ~-Ph|eZP|Cn}p%aT$Q>UkP3Upw(Z z$xDx_4T{cyN5&k``t0$;FPJ9YM^@*nwXruYsmAE8#jzbg-{RoFY)F;1e8r^=i zS$aG`wkd4ST%SuJ?v0*SrqAjXcl%Cf_cxXvKm6Y(Ju&QMhL4g$H_7$dTo_v)2Rioz zruSzX9`0RGd(!4qf}<(U=yiQcNc-WD#)nObZAn3a&)+dUC>nSMx6)>w1c>wRXBrITyTI zmOKS@*V=}FE2tt^9jh%5G{*c85bJTSCZPb?$D_C8X#%`Wql{tscaWypE>7Dlt`9dD z|J)KV-RN15ni`T^2bV?HA{v1@^xX>M;X`*x5i@!odsLK>+_APUU|eTlI#v(z4Z)n> zzYzsIsPK!OZ(KDnbs$kY@P1s_nZ#D)ZV_NZ#Xp6bC^CXt zf0RI3N2-$dBAdp|t2Eabl|rG(>5<@awtU}a!<)^W6R?a zoerIf+fx%>?i4FbCm)ZvdRjAJV}yt4P?P6)hYE#BVw#j?L^aU-f#<~+lXoiaCq6iq ze7+)Z98JpG$tuVihaXMa`hcCK1BgF99&GEp#vc{=g|wp7}iM{;St*Q!o(_6*cT>$ko3~jBuUcy z#>%3Bc}b&9uh#T<;XeBF0av`Vr;L$HjIVgyX>sm&=$fZNP2tUm4&!!<v{oqicmf zucgPSMv!G-bg%Tn;}NqEWeObc(5xufB3>mvpN#_dx|^~>B~0vdNpb1^k&sLceFbWjK8ONfIu%SQ92m~_NTNBxI$c(GzM$|aYkEJETk)}fX zj=dN1QcZ;bE)Ycmj{=QqpJU ziy)<<{q!W0tEavMtq$5JTtsnALrF&R?nH58-kC^|F}pu+RqvrMP(}^Ds%|*E4U19@ zUFHZ<-swAC8aRhKlav-c9&x5R?q1%90k1YDKj$Y;vyQ+>T&-a|!QQk;AHe8}moz51 zcjPGu17r26fmh;Tk)xN&P0vh}YatwtT1pSl-%!(yvBU+$Cj1Tb>lJ^C85%h1E?Rta z=BaxEZr5l}^^_DUI*SIzZE;w4*I<06bMLygWe(tg?nL2Qz(0>nb{ z&TJI0AG%BUz*eHCP{sj+5|y9>zqMYr^gc@ej99zT-ayj3n!xA@I9y8YF+gUM=fI1s ztA!cJK9V17(d94;*$|1^L#D4@+ZJkXWtxN;T6q>6Ve~{Q)8RvH5C@=%yhfXEoSCeF zhtC3E+=_o4#Dk@%&{1(vfZ_6hH|!aNzVe`WQhNY&0}880WkA0;tqaNc(1~k$YX{zJ zr;ZjDP_dgrcK|tYd&6bzG4?y@&^5ry(2$%;+B50Vfx1-p2Oo& zh#`I_aJR`896WrG3R|d?=Z1;B01}{@Oy4!f_(b@?bmK@5%qIp&#DJ9&M zA<-~1fhaQ5&~d|nb>-oEaNY;O*;fU}s%`}wKmLd712a!QXR0oG6ma`y^1k`KGn3m_ zHJq`Eh3&d<0ola5ELW5Kp~KBcb+3cm_-cK!F1OAUe`mnH4Y^)z$xr)L==@z${i;ow zcLrWJW+aV)+)$WSKMH&Qe#Fjt6vNtFG&CnxCBI@Vv63vmFfO$K&g5jhp*eiub+N8D zFU90=d9&hT+O0fqyVKT0*IHq0^`ASc=HEFHZfI28HHBdgnttEwc}#mMBl(%0qJiHG zJY^J@M{Y|L@9Iv3IYy>4SPjVlGK8qy#<}M|9-&PXSAc=q!_j^x!kCv1_m2ztw_zJm zwP$9SsSpZq)#=A0#w+dSsi#xN59kT(-59903Q?=AHjBw| zgEP>PG?@gxr=Hl>sJ$6jMW-P5mU$SskxRKrWQ`3(XdhOin#52~s~(p75?Ah;B=<6T z(U6iJat-;+;c!QwYuC0wpS$M+dq1nu)_a*gMLzZIT5^#L7HyGBm8sYWO= zk4N0T@ol2`X5NR|_D~dau0|1zO^4v36MWoobDSs3*)^;b<(rR3R7dI)BiF;O6JN-2 zFCt2SZ5O)MFGNY+dD~!=SZYg4e4r~o!eaQmxcOf@bZW=l$g6n0HK2HdeZj}BEdd8+ zNheC7`4(Z0QlBx+=`%$Gf9`evLSjw+QA)^|BwgAq4)F`Q6n${tID_6)r4ax0M^mG* zeAz332KkvJU(6cm0dgg&9g&tIUb^S#T-y%s)Hs^1hReO-XnA%AR8V@_i_a|^T?=J! zo99`WNvjhaZopj|?y}Y15scy#6{9Y;{UlG1nIbk7-#uxoXb;?7GIKLlIqIcky6y-m z(2hxgggd=npW-yH_^A(Ktg@g;SUn!mwB*~w2l^6OLiEEWnR5$Kd)W)W(uP!PFZ|cC z`+1kTF>91z&Em$ZjShM+yGNF>7B<2k917)l z8thtCi-+7kox5#n(rB>bb6`-q95+Pl|3-= z@rd^K%=f{q=*iykwS8WXJZ@j^y`eNpznK$mcvx$wH8d|<0(a5l5%2bc|3)#o(w+U3 zt6y=->W%r{G!w1LUg&^!Sx;776hF;Q9?Wkq{WPd-MUHE?*44Dzb7TjM%l|sI`Nr90 zOire3X1YbGXC>;Z>j5zlk9lFsYghYtyO$5VlqA}ayleiw?FZg@C zjFAKzg3xC&z>O-EizdhEZ!T5kd7A#K>+dHs^N5hRNF*T;YH!{!^ zV`fpx4kDu=IY)5*#i$n9?N#UKIniC*S+gAH= za3k)thpZ3X1>Q(_q5Zob(>iZ=PRMsO7^7jie*mAvS03j;85d2tSC$h_PxrQV$&!NA z;HFbiM?cT4foTfy`<H=q2IAn6JBVPpG|uCnyK|7liXuW zp5^^{x5T@QdAqujC3EUi=PXaPRl=byFkKEhBD`vB?%2DkcS1dqJ|VTRk~*3m%;l#z*`al})E@jMa!E8TQ-UI;}w-oyWn*-}HFe+)vC%p0+XIcJ1+^M_%w# zUk9~f%^X-&yHXkUv9hmb@H%<7uH_rftoV@DR5#)*b%_dBhv-2JB97I`*F_rN014Gp+!-Bw@ zx{W1B67(-Z zX|SO_>DA7?%}XlKL@yk@G-2`F^e9YDjc7&syKU%lLm^tqVf~f(fyM;*%CHK>gXG^p zXAL|H&2_*B3ec(x1EYG|@MIILH8+y4t>7g-!E?~DS($})aVS%SLG6qsz%=3J{>|c5 z?WafeR-Z3<-Drz(ff$|Wm1Vxl*_*I*Zw|BA4#$YGIFt~_=xvv=WfVmDaXd_fp^I#nUP3D&>TVRhfAGC zvLDY6*xySY6F5Qq%*HS!9IT$__9sL)YE_1Mcm{D9oGxHyw zK5xhj92Mx6{Orlr&RO7ioHx&T=>F|*UO3nLk6!EcFpB*fYglNecjry$o7+6fDR-!a z^gcP**ebZH;NtJnSISJ|jQ>@?KWRbIG~?bJ=)Qk=SlhoO4hgIxt0?4sW~paQjg5TS z8eB~-ypN0I4V2kd=VKeuG_C<`&$Z7#Z+ zppnPstED&sC18^K$TcXl&$EB%>3zr0D4PdWYbxN9*%aEzQNrS)c0$~uVjt?bI=_fD6BTNYc#}ug<%G?tE*Zh4 z`+bqjs$#qtu^e(oY4;ieOKw4kLL2Q)k1s(NHM^6C4wyb-i6a{*kHWD*q1ITf3MgLV zU0R7Y07x)RXht_7WQN!Ux%p-kT7kL7~Z69<81Q zcmACG+aP;w$A`Eti$+<)gReK(PYzux9hn~P zRF8HB$W*44pWe_Aio`ZKROvg^A;YN2wzItS85opYw>5Y`*!yUUhhLE_YJA}vm-Dt> z7W4oteuiL35ELw+|H;4vCu6%ry&~Ss<}gm zeIc5K?hZH>6$+0UK`x|X*%ZYR{5A(@@q)K(kcyU{sE-qmKe6Xh1E@5NHhDiJE*KW; z(*2aGO{^-53UXaedC}u1Nk`6-j>3?6rCNnL&BMd(Q*hWm1?={A0cH$+%u?Ytq`Xpu z5j10os$SBGEFCw)`ii0usH1U(#80^r+K8JKK~5=Qlxa*no`zgy*rarnlH_=JM>#OZ&hUn+tPo48gsx^|*_k|t-&myf{BxH%tPaCJ-Cqu$AZhaR#guGZH5KTZ8 zxhg>&>a>P|7g&*gjaae(5l1+G4pO^6>TE+t@y6&uY&vWDLaX}dls(9;6=t7!X?Grb zLHQP`A-OK0S5A?4=|0M?-e(K2_Ps$rrOd~y+82^y4GR~!*82!N31~7)IubK_^mq|F zCk=m}D+hrxKpuw>Zy)R{Mp0OneoZ;P)}lB3v7Yf8ctb+_p7#QHX#WJKc zIy!cPNR=Q`%BFc%8=qHxRy~ zLVh?#>lyI6n-v5NvNcB6Y(%T%C}TNVGyR*0B23I@c>1&mIoE6w1WgNpgqR7$VRmLi zqCf`XX}H-8iHquvn(6@7P?9+bnUQN}-~>_1>+Jk}GB%g+-PdV3LB!`g_|O+jwrzQk z74abZixVL&bDYlXb2>wV!7L@ZE66FlrY{^5PBcP-H)CFshgs^kgwzwDPIrBq3YVcI zpj}aT&b(Qe50GFGm$X)-7Bpa_$NaJ4N@5JXf{I_(74}uri&3n8QO0;K%8Bh5r_+?d zXj(NaoCcBwW30*^Rvw^$KVu_6ZO+ps?$MveV!t4ShAFgY21(d67$#QKKn5L>k;gF^ zlSOkpOZ|HiloLON1c(7rQpn9U5O?EB8Iy5ZYw&=5Aq2#7tX-IP8No2r+cHBxAy&{c zo;1(m=|Q8xNiZ^fb3i3L;X_IR8kvS0;)Ro`NgNIkIf?5RP77ULs@H3ZG3}`h9nA_% z4H?!_yLlr4Dn@-ABb9O$Y*toCu*Mz7O7}DFXCHCj&)-I(5n!j=Vj6%6*3bZ9ZLwO> z+r;Q3R4s6Lc$Go{6SA|g;J>Ec3UZ;JRWKHxROvSa1o9JJV}bu|01l&!M@)2)o!R5I zIVXxuRJ{SEC1C%o6kklV>;@z?Amx7X=a2>vF9o7HG`}IiZc!8=9ZAv%!ytpi#R_Ym z;^JHW`W$r9j3EGbb1~yPiO6q1IoNRiwC#x{DNsqkKL_koK;Z`QDE4lkjOuGQ)TG^TJwumMC5l5e+CSE85~@-tzlEwl zpi%+Uk>E0+WhOBjmhg^$;cvE^72w2rEOA&TLQRrPmh={Gv>KMV;~A0?#4@zxsNX(- zY6i(1k=<03A%!VLS3=x?t6hn-b3g8OIsl~MTtN&#H94D^vh+Z^2hEu<{cX-e{px%V zQVWZa2zESP7;8K|&07EYTeu|cx-$TVdluU5QWTJ;Bp_U;9Z%q9CPkV2=*C5{)ONOH zuIN^7b4`L{?|YHkxvspMDIkBRxlYra{Ej$()6`8Ej}U(J(rF)E!o5h6Nk% zEE{)EyAK^)O}3(IeP`@Eio^7IW%Bw1)>|h-ATv!R#di|KEx~Ces?SU)s&nni?l7!3 z+Sh~7^{7i0dndhNnqhYWs=&@~{NxEp2JMlb$njY3!A%3|71@WTJ&k9V7AuL6KTd9R^wu4Nzu^PT9zY71IH^WRXkzSMT z=F3)ZNCT{5Onhxt=J`1GJM3_Y$PCl5ou@1GqA|YNxa%2F4d*TR(!9gI)lQU*u1{0~KdViFlSSff%fekW zb*_1a{b+gXIPkWE$#$NwjAITXJOc(edFbYWco$6tvQpD}!v1h+4jeuc9m?`jrr?2f z?hoJWwCPZ>ge#`V)0(E0pf_k~*n&&eZMpwOARnOt?d>pKtZbgB-9?k3FzV3V8a+;B z&wzI^FJM8?+)R~T#AQ>hHFfuvZTJy!vHj>e)&Otk8x9SNkdX`L>2wHeQYkdBvt?WI z+f|Vr!QdN*U7I8K1m1KojfZr>Jco(EWFsxH5O~_%C2#b;b$Rn%na82q`_Yf{=@M^K zszcKvAV@kriE&a#Gsb77;3G9g4fvzo>FJnqXp)w+C28trWWF?`#t1A9I5e)y+0sek ziPmR`TvhL(j-*yo zAED;hJE5|36&%N;y3LvnU5Q@P*dh)Z^p?A5=a_zPnuy+J`%E$kj3o#pdLkA9TFO=E zGH3E_Lv-WwWxmE225 z{K{trysddF2IS|nAOJG;kxE8sZfAT<=Jdc0&Gd>Cx;QCYD8j_#vl&kNQnb% zSh}B#%nsc_9OO+EvLY|a&5ssnRSA+ICWE#Vsa8lC=52X|#8vi($SUBBRzTDdNJtB` zq&2lw7<$m)rzeMGh(?2_@XIKV6NmPg)8T&UX1{WbxB{r7lMVf)3Pt*-aI7$E#UZIw z$b6@WvL;5vYo8D`*Qw=P)3J@uWY(B1cOd znbcdvN?PUxYfl0bHEXt8(D0cA`di+GlE~@CoTtps9`G4Le)y;8bj){ZRK_W{g7pv^ z#9hD#f1)j*q^S-J7#zc&!^W?YU4=nqcgD;IvKIUVOLvX?Qoo8T3yU|vM&LdSQnFCV zMovarc1SmOYzUILUie*RjN3Y1++;?EJ!J3=RSLonNM6H)GRwZ7oedy3ui_VBcnB(6 z3={*DfCSLyy9uAnv-4-S!#xC~=FcGIz(15U7uZRO9;EaWp23(d7oMLmu&MQU`6CO3nvr4DCxtLD!)4HmoZ_{~>Hc z7$WS2q!7wh3baK#&HwRwJv1+KR|7~vm>(Qk%n`GzfRt-To%71jf{UR|7em#66RZD; zC}_oI17a%e&;f9T)DkQp0yF^Q9m=N|0`7nRBqVv%aHc>I`)xE+{e{cGi!3`vdjJW^ z3>IiQDDd8lV(;YS4k>XYl^|(((U< z7eBc#(53}t4X(V%%MvX#3`(q0v{%0mV}!f|lnMf-kgv{El2d0n8Q0A0CXg{f;ElAq5tOCbKYU!A6mq52?JC-Y0!^mJ$Nse73-ZC)XCu1?y!>1gt3~2ZRG31^xd`1^}s+ z76C1)X<;q%g>e`*EpYco0a}EH5bKG#uuVc!f$SFsF`2rg*ryO&qze;L7BBJ~kXw+l zeK_cBV!)e=^U~!hgUiG{^8} zsL@FsO;m{1YL&2<-(9fgiQjMHv7zMhB%f!_wdG|?ZgE8nupXYYWd@QUy^o|JoD0=9 zAc~6(bihZ82j5BVW^Z%eQkF)NRmfLoX6p-PJ@YV;>463%a1tz*psC8|pfs8LDfm0Y zG9%rQQJ&E+)+bUUYrv`=88xIq+`H7laW+BwGviz-fkX z*Y`+X%ZF&DfNkIDIVc85p>#9!u{G1p(5SUxY>jl4}+*5s#fkNzNt*<9qk06dUch2O#cq z%Mss{=gKc7ERsh#a{d`YTKa5=3_bkN=6E1md6+(f z3)?hTzc;ndQ)j@1S;cy(U?&KG;c9y3R+8_1geXzjeQ$p6bc(LHU|X7_$fW?*9rc)$ z9*2;jjoEn|RdWPxUa}!JufJHFfjeT*?pA zG}lsHwu_32lBc`OCrDWQ2X1n&#zFiBd3yQ$2g_cjWG@;s?c6N?gY#PhseFCz@9U;0 z9I;!(iYO zOZl7Ph?NF%Za670)3kKM5F|9K6LaIh+!jhU^aTyk(RBM#8&USD964@bJ8ZTfo zK_pVMC4|)lo)1M~ZVS1paSNcIi&!CPii`FGLZ-Njf3pdJ05j+LB5EN_3P=|cFxw~> zaSGB~RNyg2KfVr3-6$c?8H?3<35&!abnkeXnk3STeMr73LRb5+3I=H}Bx8vUlBrSP zF9jtZRm*rThHKP9wtoXf|6mc3-KL_HJMx>QXp1S{LdgcCgzzO*_=5;hD)Jt+SoxeY zd6b@jqZN;W=w~z(8FB{Tw1Bx`0b}7j5d6;Z!)H8HSdLLO2v40MAv5e^sx^a;CMvj8 z0nc)jLZ!yW1F6Ukwu0^xPI?W!(J9caTEzV%9DUkwjOtOT+5_1P)12%vexd4DxrL21`pUnU72CVf{RwnSma;hAKu>} zucNj=&QbA-A{};-c(c|1x^vN$ITEqb@dJ5+O|hTe*m%bNy8RXR5@dC5GVF*KhqNVT zIlK9VZVZb>`m@qNgmGA^pYJY$(5Cnuz1e2BfHG34sy)!E8*rtT|75&cfjto-6E@9LYlG1kReK{gEW8!8iA@De zx=ViY;QL^?Dz!M({S>;sD#H}5_LtoAEi5geVK#{ZsBO6wxkvpol0sVi+3rTmvl9s# ztiVJYG?g1Bw)nS5>>iz`?8g|`Xj-q)UQy`he%6N&uq*W@u)^JPLi}I4#jbG}VTW`us)%P_;wZ~<#8r_vS zisOFzZp{&SFe4X(hRA~Imc*I>H?K#s{VecdxQt!{lQnWF5vXWIIdeDAAkGXxqhfDx z|JT}M*uL7n|2YofrCV4_VvJrR{Zmot>XsJ^*DW*s@4TPDi1`PAHiNCWq&E&jl& z&xqb$vj<)%Ry?CE^Ut~z7q&EYMb^k@Je&<4frDr)%NYYSuVdI&IriU@|5%aR+b-LD zwM^A6-+}UCd3dU{;B|?EQoaWyQnyT00VwS4R3yFAhZqr_)}_W!1FSwka<_5<%DD;? zX|oU+vz?!CVi8P-#7n;KJ8fGX(&BR^t_ta4J3gGWgGu(cHj*9%3vUVS0n zC*D_?W^R!d%7fD-c$bx@K`rZ$r@AIeg7DCS;99C~61=pux?&wF2u6`tVkBy9Q33gm z_qlXNAoj*x@UTSjO^mL#uBI8h1Vneg<9+!Db3*@T}XCW9NE#A|nANQP; zFkMsREb)_hiLB;}L|3HWIxCLpJPX5uFkW}da|?;|j6=H=PK=%3fnNx_bX{Y+%?rQw z*9s?LTddLwv?h5J_5eZnmRA4D!cAeT6PDEH?bzm-CLV25eq6Re)dGGfK#`Qon`e)E zl($Z?-h0JW4c|g8=I=W)q)!LIMM1GR2qhXA5;Ww#$6h@k2zIsNC?7#79Q_Yu3l-wr znBtg{xUksjrFr&f%XHlRrgu`5!#V9sTNWMH$0D&$7K;a8k)A_ljl$qu#Bl79btTsL zXF$wdaxVy5g^ja>xX z?iXUIV;O2j3G)cBVX%B7?no5tGL8tfe+Uw-AV2M^EdG`5MZivedMu<#PgpS08;&DQ zZp(o=OEh!ef~xh}HW_57JXkvkyC}A)By%Kw`i=5*KSOM+rWUv@U4hcPeoVkJr->H9 zP8Q){VIMXM^wvZ(l}EV36*@+fuITN&B$tAlmQEUcg(vXqjHE5w>t=cAp|-NDJ>;X2 z=q0rT`+$2nqj}1m6IgLl=f2f0dJE+ZNKlYW-H7J+8<9z4wLu*b4zWS*Xkv|DppZq7 z0uA1A2J7uH?D;G0jv~uYMCLg`pd$i4H>OaDjX{V>%LE5)Nu@ zRUFxQqr#MI&3Cqvnd76%|t)AvB{fVbHJ$LtdT& z0%IzrY-FLHJu_#sWosxZXc5+9B(eRLrt{A3&Dv0EIl{73nfo`{;WcQH_) zW@jEc=eO93J-^lYJLzz1nP3ruocQxJ*9ru93{p&W`kB*q*yQ2M0S{7R8Ug(KYO(x^ z`>C!JGEoU{%n`3ECtZQFU{FBDk%~-wgB&I1#L{gT#YhOL z0jc&!NgNh?Nt}Lv2AWq`-$T!y7SVP8$^rv53~K|=qUgBQu3s`oT0B?x1D1^fxpID+ z>OQ!1DoX8n8)3j_X-7$xN4OVa`5A>VDugbBxlM!uE!GjJsO^zbS0Cb5lBxt2Tson9 zoK|oFi8=i&9Ln_=_z8!wp}-;Nz3+It=OcII5!4Xqj^|}Pa^(h1-Gl6wS)LLkhN)WY zh?rnP?M~5k(G^sWT|wXVTFs#XXdI-G0Tl@W3C)aD#{=X?M*CWOE7G3!C=;oaKE)Ub zGSXx=&voJngn^Hc!yU>_324^meU3zW8_8TO3@}9G>zUop$m=vQKqnQG(g3GM`A^-6 zO9P&PLh~S^vY50R4;AHuqmRH$`D%H%<^%lOSqOSc{HTu?T#~98GE(6PNIH|C7N5Oop#nLtar*{ANhV(Aj=zg}rmul;5_88pZ27IU`_bNh+`aJBg-T(kZ>p5U@pr zPp6EGyFw5N9L%%}Z|vC|hl?QyU@^)s5$NC3lIgHiqlZozu2Jip;f6pDGH$#urj$(G z+*pkHuO~wQ_X~&PD~h~j%*{z|MwrfAX~y}4EXopKr@}HzCvz6&nx-OU%V+0NUrcQ) zh*IDXk_=2HA%O|K7eaephM2w%#;YOSv;=Zr8C;$Ty&mj?qI_%w361p;5*8H)>`q*z z&M8pCL=4=~Bn*gFSn$UKQi)fq-3e$Q(9{^1R#2M37$RHp{jel8Ze>8T2H-RSxh?4? znx%#(?vmnoJoW`~FHX?;M}h$k%?vp2OF3FJ*O>OQhxJdUZbvuZUI;OMbF22tBe9*i_M$#~2!fRpVI*8x(O z<9}GBz=5^)Vtfs3pzC5+pZy!K`7Nz0Qz@mEY)&}C8N~K={@-0vCSr!a6HX6jq-Gq> z)CO{57@C#U!MnY(Jgd;(b|gU!&$WlP*jpUmI`P#SVh?Xu)D#l9_@p55=C3&5URZi^ zI;uyo9uVP2A{rK}nnAluhor7RE@;AQv=%5ztlMDO3%ub1;3XX7FSDGNyx)PsMMWXz zAbHKZbL-mjta?Jb)NQ$0m*(6cfY~a=#94V00EW0AfB_R`B<%1^Y0*a955iwG@{S6F z?yv-kTR3TjkQY!_F&&}j>&Wc$(vfitF9;IS`tM;M0_%uF1#%e{1`-wefTEEiuR5w(*y|My=^K4)oVyosX z*PMwV{ww2GhO}38R~GwK!}SIH#c$e6u`wB!53N2;io4}H(|ejjUpOqdKHr&%)aQR|U2y_bAsGr2t9(gMSRBo`drB2daCT+7_!= z%?Ff{zB(2LPpzqq@mTcsI-bQqfoj+4rF(0-bEsiSoexYr3}a4<&*eShARdflG3wh^?1)tdn?#br=W9)E`ob`S`=6dta`jJ!#rOLKMDPzW=;3w4%~r4zyFFnge# znw2ITU}Cb2RwL|!#hOT>VIqh3sI=7^&KEcNWh|hi)~4h97H_W}Y;6@|fFjgU2Wz4o z{g`1Ck!G*ADR}MpmwH5HV3J|#%wTnAizAQ$t`}XI6W9(Wz>=U0MpLqN0fp*zXcU+` zh0OO2uwcIR!$lQ1-n}rmPfw-TL9b)JS}1sC$X^^igoMz_8T)y4VeqfS6vy9+r`mn9 z9d|$HUUmmWGWo1k^B+RASx1QM$dZ$sVyZ?QJjbBz268COfyGNJ43m@W4I1l}sgLws z;K3R!&2YGYpx`+*2wtAaC3C8|fS^Jn5vtb|LH95l2TvI)X9RCCj7e52e|evl)# zZ~?VF&Wz5Qo|EVn@0xq`2Bt!^y+4dvh}eLZ7XO`WrG~b_-D}V~uml1X6>StCL7YUT zg8ZSwXt#_d){)t%&`VoHb>zQz4M`!StZ>W_w#T3ywtAx#Op#b~#l2#bL{6$^r7)j? z2(&z?B$J=^D?-a!tWo)FWhy5%mGh6oOxmSz@Ei79q;D)8mkvT3>(05CTk#7 zsKc0zI?Nu}cBDE{vOaUg3651xY!#%ah>8H!w8UF4pm`udXc-?6zJP?o%*BG0$W~pp zv`!j7dL$@7&SFx55CDXj))a!V1MWay0npJ5LW}tIMjP!5hNtSF)dRf}*|ZQCMtuZq^Hj+~TTw!C$0%0aK17Vm%C5 zrUskiEzmkRi^)*AgY-S5`oQD^azK^oNQ)_bBo^O1imVWuwUURKBy)7QHE#d89m^Ww zL_3&v14SBd5GR5I?_kijOPRD9WVs<622s}!+k$q;HiVH)+R5N~>>fkA0ORKA(4ta* zD9mZ~smbyryJ+$}Q4MrVuI6)G2rwl4gBMA=;ys<1*Cxtwlp7OFdr5XKiE|9 z^dPFqU_Y`+i2MUKHSeTd7h%+6naZjuZ&NAdQA7;R5kQ%R)e$qqE7V$6dIAVDgQpv_ zl#sR$`Hbf#gyFUWHSix77cJF3xmeTn@i!L*=#wY7Q;;JTt;1b&76&^D=p3) zTI$pJQ(zZ83aCx7fvyJ|_uo@(3Sk7?S9k2Er5bH>52_%Z2$ef5PMLPe3Yz#`!{r{r zht^^+Lcfh39LB*@A-0(7 z77MAs$PfUD;q|x{D6v6g4jx>IuO!~tL2b#Ly}{CgEwDsMbZ~Rf(8%00BD-mqq(#=t zreoz}evB>!TSg?KQMeujQ%P+HwkH|QUX)fR6RDWD7r0SHINBhPG1TfaxL#ru1cn_N z0Ndf{;0*8}Uw`n6PiI*D(rUr2cR!`FT`Q$nG|{(tO1RiJIwiQ<<|iF$b|sIvZ$M4B<4Sh=d7IiK6$| zdHiQ`yzrCD952x7Dl8Z*kBU+pr4u2Br(r>2xWaBGAvRLP8rxIHd9s9gHr{m5n8w5` zTFQn#ab99jK_1b_k^Y*9eon6RjS!}d3jm3%C_~)_r$jb0nk(l;m8F1;zyy~G3obAM z!hB4bFb2LHBa#E8f02ylABY5`XtE(60*EHK#WYttVUdL(M#-Z@NQI?rQm9(AA^~A< zlE79nn@<-hh5ra|ooiQSTse(QIk6m}kLQx;v0X>&4dXO{>NEhsy6*SXcMUbd%IgaD z(-u&FcIpmFt~|_n_-Mh3xEH^eP(9KI&Ls+&2_VpcvjHD%VWOD%$;?`VR}h66Ti`ah zmkJ9H8c{$eVri^wIUz3?6kQU-@Y2Y!T_63Y_U0=Jq!RNnVe>y7yM^WLN)Z|3H-;Yr zQA#PqA4M)P#8m62r2Qed^`b){8y<0T0n?Zyl7I3L=S#W)XhXjc@&c0l590t9_7KKR zpflS{=81E0C7b(c)Y9lRnSz)LLrh~!j6XCI3|+HOH%kaeetw+O zh4`LWA2);LE(xY=X@F7?Ow4tshFygTZI2yUb0&s`z;DkI!?>P@%52hcxk633;WHMJ z)PlvT)_~p9Bs!>7NIZy&KS16qWIo|-VxL!!tOr>SiAd&=7NRTP6iB$P+ zxP35G5J_~BKn47v-NHjZE9e%+jyJ6&J(k-8C>j_{%0u@10pymVZG;(Vu1J$VM|Z`& z;Eh(Km>{EU&e|5Mjq)mGSKinG>M#%J0!Lw0hld&;Nn{DqhM)lKLz9orrEh~WbqG#i zf{nBoHXmT8ayo68kS3JWnY2BIwy-Ogq85_1B3~7^Y~Df{2eL{T*zOYx(2fNoHHZZ_ z&@fmYcQi#4is3|qXS2>(`i-AqPYi^Gwn%$C=6KR`7)_hTlAb}~h}b*vn|al-sISBf zqX8iFEHD6K_(r{7%`dWaP^$d1b7(?hf3ZZT6-Y~W^Fxb=NhBczX2Vnpn(kw zM}lSaqENyDC1N~sO~7}Xh;UCEJdy<)G`b(W1LrvQgVm5M(f--jU3^9}O9e4Awh|CB zwDMt~Xes*@*oFaY_Wf9*H8Ti3Zik&^Mv^U0PPE&5brf8J$Y}DaA&U&C0V{#AEUE+s zoeqK-4g2MV+7pW7bC92)slAtTcfhqfPb!K0C?@~zc~oeTQ>zGaptPQRmuwig&N(zt zY+iGC2HiVUd5qn*+5Stc5__iuZQaISI2UE)dL{TWT#-3M7Cx7-iq!cZ{lWhzdRxFy zW;G-~<1QEzPcj^_rblxfymZpyIf~-A>ct*r%6@TxhOnYWxXd}n_X^_Qgw5Zu$&-VW)yFd?q^X%Tjd32N3w?tYp3~}| z8PIYcpkngO!p+o9axMIrt;8KI; zMNfht6ci*g*H}y^^C32H%uB~h#s&T)YVd($MgMGTLBbJRR$+%9K8Ooc*r*4^YkHl9kPDGP;gjDLaV&`I+#fv9x~jFPwuvyRe$J0kGH~N*Kid z@z2lD1@gntMdRibLu@T@0PT88`}-~U<$JTu;046@h{JW-BAahqBJKc@SaJ=Kzm_P$ zyn8f^W^R`pU>1qsAcB-7S0`FQrh6PZ^$bua?7B#@afFrll! zyKZ;?kKR!5!9nTdfjAm!+Q%{MUxa4b%2^}3xCaTLj$#brR1 z^l5rPG$%Sc1mu2sHrryMCz&*yW5K}Y?V;H&r}%=6_ykcl^haO{Y>MXaOVqQawb`-q z>9M2O0JN#4O)@WVGocCK3+z}p2T^f5G?f=G!QN^9-#KT7_`naI(*akXo8!r&hz-|y zZ>I>lh6^iv^0;9uv_c)TC^gk*Jsp|TzI9?>Db(mtvT%T zx@H7VcJ850^Uamd;t!jt>zZ*We3*-nFKdFG190FRN{oUIyCuJ1gO(~V1tBhcLaHV_ z!DKwYP*|--@2)v+bF&(dm1XhX!O5-SF=qItyl zHnfAImG|f8!@k;Oi67fQ)rRe-i1}$Ayrw3G9Z<)uD|NKLAaS|VUa6$na_8tpHJMysX1@Xwvydo&0306}(i+*-LW2ll-A@{q8R8ZfdRpSJ+OQgx4l5l`e2Ov$ zRMwHu&%H8;FvoN|4&GOY|AN85a^hn#m{05m8+Uo~YJfI7PXvcmxv`k@HC$*bGJI~A*MqZlWKx1$)2L&{t#86{wB8+*{ zt)X-I*26o^7tjybyOrIEuEYN8#A|!Zlm`WV4Sn+|Or^sv!NfhoC{kDrkfSgC<@;Uxwk3z8_pGYL{=UZ*Xrf2!99L3E(J==+`SOi- z^W%dS2v4QQJ%Nod#zE0Q(L%Uckc|q0w|0q!uzI99$XTsIr(mpHzh7FW~PWVEhYzz@!3Q%sgmj7)}|Qe~|eK&Ydd^S-^6pVc<0u`M}aVQgr7Z)oGal}@_7>)<9hNE#Ek$874s5I}OT-3eqOvG6?I zjWHr0GfOfBE#Tb$^ATf&12zQPaHKe~g!O_gzf$j?T|W$e$S^F_=5s2lj?I~Hgew_O zh-n%Q2r@`>-H|6nICPI84iaX8`48B! zef5_;Ub?bdvX8ci+@5!G(z&A1ciJ`N#e3*OZK@}7EfLbsHX7O!iT_IQvEWI0g1MUM znIuBE5Fqlg$w15?u>ZLs_BTsiv%buy8KG&xaO_+45#bQ+>~78Uu{7LgNHr4{IZzDb zVRyJ~*4oTJK`Uj)-W7I-w;6m8$$EAXnB4)-!=UotfX%{{e-h<3{k1vB-Mu!*ea=TpQx8%fGvze);~&*~Q+dki6nv=3hv` z7c3u)#mYz-0=wampdqB=1869a_UA0fNCBGud~gBipn%~j9!aP{y9yK}#u`q`!9|i$ zY4F>B@_}wNjHJ~^I314-(>Jgbv)7XY$j79a|5*>vXXmW^%l8`jjL$r47vJuW%dP$~ zADhv1js5CTTXXzXzn^YDxEg=s#=%F1FCJxd5BzADP+QyB+4kq}t9+D7n*Cl~$`D>o z8BiFV4v!e)%Hd>U$4C*wT1&ba4Fb8*o)Ea^c>*=vSekN<^gA$%_j)_3eJaaE)e!tm#}l{s_LlO&(~aR{&!E( z`Om)YxzqFG-LO^nSB9;)w=zc8wlXI2NJYEuzAgPgQp3qovI_hRo)V@S zUyk_FJ2=^YjkKIFHW(0r1)t+q}E&>h6or75o0PIiv5VoT#{xpha=Hi*rBw&^zv; ztm5po#-P<@5?9(PE+Y{bgFc`IT*IU{51ZXoGQgP8EletA zSDD4ZpvY&MuArg_bBz5V0YO$NbPm|4gW|$s8V;x2>>*Ykq&?RXImynIlb?7_=iVxKqiOFZlDRy5$W~|)yD&$=frJH&X9lV)pe)l?ptNus&122+>a9fq-|^3 zgH*F9#hy*A6q;SMO7L3|ebzBXL5eJq>L^tHdF)`tFeVF;5hS~0*Y3*DUht1^So=* zz{S7LynR$th4G@*0|(Fj_qxikF-rpcrGzv@-nN*9us}%E?(0m-IeTOBfN@~b!_>EgD84}(ZtfcX@VFogYiKM%7|cpDktO<#HjK| ztl9LIvwP`@C1+5Q0q0E7H zdj>683*mrm&ZuIgfWi(vD2V8|VNV6ljMK2)Ylb2d6kuWh!C*0~x9dZ42#8>g9rMBD z;bAZ;o8DeOfxrD|)6u624Q72qP>_en zz!(_|$uP@z$X}Uewi)%VMuU*_GSj7VjEA;r(?#6`lV6dH;%lChXW3>VNFB>ysl_uSxv8^{2o2Cm)F!`_V=5i~AP- z-q)1={MxA`QR8a0MVM=X6YK-ZA+IayksLsfCgE8=x@JO<4$rxQ;1@J{Ci7<^g@-vM z>E|bOtp8-4HWP*qn#DIpD7q;lCS$uN&SAXYT$!_S-786_G&imu`#%2E?SD2+smyYJ zHOpO^<#th)SK~HU{qlpXpkCjPpN(B{wsx)0ODk8A*8>mWwBQ0o z(9?znwAuXJ4a?jZJObi;A^<)XJf|tcuVF+Z<&*d(8dC~v#%v&3qcvl23mp0Xa8`(hUZ+*vdl*mAfjP2JNAiWX3FssnYdt-5h#eC|L3v5?FJtDl>f`NCg~-p@tsB2{3dBETE&g14?k!l0n6<-h+eDJ6Wuf zSP3^|0@_TQJ;U$%pM9ed`f5++5CFK$468Xt#6iG`3 zcYTFvqN25_>}trND;1wz2{ClPy*6?2KF>e6kGfnn<@D9iDW|v3TJz64jjcidlu`aT zbkD0dVd0>y7AYzg5OHV-bav2*ixq%J9AQZW#ua3u8b*OySZ>V>P4GT>L(l+~1S_EO zgL(`(KE8xC7hhbc($PJ_qXlYAW(oolVx*Y7;`KCx(WQ)BZPRvPJ|lp zr}<{46!gPUbQ=9cFfg--1hjd`=@+)^0e(O9qF~N}6j$aJD#V$g^-ZhRUTm!GdH30P zarni^&sW|E>&N!UhVP#H>9?OI^e z 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�gGsRwNU>pO9qYTpVx_*(w zNWT!h@k`<+9|)Hc!d4VW>X$}0KW(3gB8ZuO8BOsUOrFWH`d{+g);!PaA)gJ)Dv;2A z=fRLmol$x-D|MR_#O_Bs?0(MItW=+<3L3k*9*wjsy-yM)4Bt4$$=F`v%#xC^@9H%p z&6Hz-aBlMIMX{iovX}V0L7p$LTAo*BEXhM!GpJE}iaB*%DOCi6%Ja_b8P3)SB%S^X z;tdAq3oPasVk`6ienSnww=$bS|BTs`C|QA4!j+mJsI_ZaTA9zJe-(mt0thP6n@{#R zpEa{(oU-hn8anlK-?hJ3aZymgAq)kuA(tWNBCc&QpI{3hX7+>2Wg`0R7x(M+@g5%q zyUXmUX3ZxzXUZc@rI%x&47OR89AgGuV6Ky#M7d##mJ_-o#*>YML9(gILg9{;)!1$$ zcg@LKdA69>!MC}X7w<3s=@NlCjw^kWdw+x;yu{-W(YE3=xC(>Z2@*ki*ywSEP}9R1 z0k<(I6QSl%!a=b}LOcwVjEk8JAfs}0&2L(9MytE)RV9?(Xryc!jol>5?Y^A9Iqom# zHMEjeh*rSp5RJ@g@+lq+n3VwUwAX{Ft0tg(+ss((b3g&$G=e2{08f zF^e#Z>UEcA?=jPs$ZM(r)256G@A9aq9$QU$)oCrFpHpH14+%gY`fusO&vSy3 znc#CuY#q2s(;x65r^P`4QrZXj1o-%JPTzNN1e?EW1?V5j5m~DxpH1`nvKOAG21p|Q zY#q{`y7EeciE#6=uoE`SKB63v9eFz_Z^<+qZr4l2}$<|3^!J3RphxzUxi(G!l7*y`W((P5$Zl5ybwb$gLW4plFiG z4Dd-fk|2%XC(X*+?+17uy;g4*gK_eCH8`o@OAtRX$F($R-}k_VafoClB8gTdraT0= zA$ZW)euz|kv6jJLUN878n_@gKS%rJP9|k6+}q$SZV<18u(MZ1urv&Wy$2*7w}!UKE(X_&Kyr%B0F^$dh)$O^92m zeKs{vu49&8|9A`H8wMKGq%s)Ktm-E#4pxBfBzZ)v$e+_CveTBD`Kb3tn*&R#iKAxn zqQEV_G2PUgw@-|A@WfUGn{!?3H+CLMD$zn`9MVBAs(lfjTfn{T@v3NPCIlqEh4}|K zuptH^$anwR^O1kHD=gg3@V}Y4=IM|!wccy ztM-HR44hp`XzLZ?h!msJPuii{7mB}f_@yBibPAwVMBP~_8G$!riUa2#DG z5@=nc%iXE_T&JZx4oQ8%dT& zkfry3i&GC-0F2cW0gx=R&egmE&H(|IQK-vwa*d=j?Yj{;2}uM8@okR^Gv703FsiqazNCEm@FP{a1CuCXzJ$zCfbWjLnE~7b6R!|3Lq(EtAOu?GM`qN+ z5b|&q5?>;O7>HpA)ZqUADoG)jywv)zuN9zwMjOa8%crO5}*az)qL_v zkHUVKTpCnL)+Jf!~J>w`H${47K!ln{zUCd=w@?%@&^ z=FouC-wb{VZ>jewKCWT#JxaJQaDhSLo}b_MRMx>M)KvTwc^WlMo_V_wjdUJD<};N3YH^wrNdjMaJaP&TXlR%HENN53nsng~XqMv0`T1NYPPn96fVDxc z7v?MWHv33q0d3GVT5gPoDwE;-3F<4tVKr?nQ|bTA%`K<$VmwgW*msZJ));E+%lLR8Oz(lPK_kJ z6!b_82K9bBr(*XX$x^{NMwwI$znDc!*u6ASh%PXZ+f9;6T4dFKF0*C0o1L*WMEXX= zc%E38DOYFJHRr_B@)Ky9DUBCh?q%!D`AK^z9F^kgA-bl#;2!6tF9>)|CpK|pA z{AWo$L~TO&V>b6XzXxw)%~Iftnlb_azKtFkJ#v}hs>w+^pBufe*udpEs!HH?iyjfH z5M*&Q2As*^icBuFRyHunG&}>mUO!NbU}Orx6%BNA1V>kaP&0_(ccQ7h=*nNhEu`sYfEWb0o~j15RZ}sEQ**uN!eaesnq!lnVbtn-JTSD}Yip(BoOWpTm~x zc2+m~*1Xpe0MwT{q=J&((!yXynDhqnc1Kj!&&DG!Xp(X=;O5g42QK{PR|l4}dLQ=Z zf$`-yS-)1;mZk3HLc~?y>1WC*hU%%OLvp7^4|fB|A!X<9H|uBT{Mfw$*yI$$Qg*oE z72viWx~c_QB^B;8F>VDj?2Zd|$NzGP;v-1Ovn34VDe_cVgP=Gw2P1h}GF8gz@Nj!j zs#h`-6if6f38|Utpk~U0yGpMv;@t(4*#J*Z>KaZ@6tl*1SK26)1e7LZ_dZ;sJk1=c zcv0Gbp(pvt%@b^+wHRrh35w zo2bDKu#fUPMako19%u6q+Uro(T3v@n?37Obr#2{z#);5TN_>@3h~J$?{IQ=y(ED)< zHu*s~lPg?u_U^mk`4l;|cRJDj?4U&Jbt+dRv!Oj)jQ!)RqcH?>_<)Cjj$h(fcz@5y&Wr+JlE%0sW?VhMy}jlVds}5%%&3nAjp0 zO{PAkfx*$m1}<5p!dODA)tzeFls@|%&6J;=DL`%rNxOslOnp8iKa+e2G1-$(iu(#mlR$?&oUuR0{c5L(g_&@;=RK@cxeL@9MfKPNIRVAlS# z?GkAhX+tBc75HJU)dxYn0ch%RttKJP!prB-{1JA88$iXbx{`#Wg-VTGC27ib{8f6?(q@wNQQkMgef!e1}RTv9hq zK^guwbT!s4(g4k$ID0-o!qc6p!65J2HPH;Pgt0}$D)Gm&{<-)Vg#82ImE+wCh%bJ2 zQD!hEV9FMm%*(a07!#?WtgXh5YkwI1Fls8}j9nMB0&Lo&$ka34smBz755>erIE{;VxIL$ zZP{!+iC*TqT~LxIlt5}VAHad%Uslta2s^KxGEvg7y`Rd%;TNQh>Xu$A$4 z$9O)F(%ZRX&#Jy0$=&!5$GZA@NB}=(ONx;0I=J=2?w*Cs&YiZMz1W=-9P8cew8NK; zdv}Bbno134{+tU&oN*hhF}Ks{%DlQ&$kIYX5KTYmzGr7o>2O1oP46 z8@-F08a}?1{gyu78f^batT|G>19M$ z1cj_R14L)s;Nj75UiT*@S7U@x+-RJk))IZcVdzk-onnuzWAYr;lj7ivR&p~SMzSZ0 zjh^2GTHwW~taRGxC6&I1`8;QQqq+Zdm=LUl!rs~F2t`r58mA}If@c3qx<^c|F3<_g zIMhE7_@sEeC&zW?4yKv*{2gIwG4=gmOxKS2r@-?4QnVVm%aoRC+U~!9{rUmK@cyl} zjvaSh-lF&&+va5hcTfrXSfW(j(^B52RNk+2&xm2imV?%#_z$lVn9^gzA0TDz|67m5 zg=;#7p_#zs2&~G5|CXclTBN)Y6lU^AQ~!Cp_2YJly3qaoLP1^^Zg|WpRjYCgT$DyG z1njl!fEJHDta60VdrW802+v}SS;q80+nVK=vgkYZOs*?_7Rd?vgQXKeto@@EjL zk0DA&l}<}n2E;k2p~2TdI1MD2;G1%1VTva{fj2|he7nWB-x#2;AXk*_2wYzQX-z#k zF_EU;&T%}KUH7hv)qyRBpEulQQoNM{+}P857T(wtCBiJJi~A(!|7cMUk$wd9lK!-e z!XS2W@yGdAE%z!~v9b^%^?0YnF=aum2+?xpL@?=~cL@7y}^aTwRN<2@f( z_c*nG`Dw4IShZ(7dljs#`)j9QK9=IUV8u6^Mei{GSEw(xQ=EV3_QiodC&y|DtIA z`&SBPx5{b9lRtWEORYpLW=B-}b}o*(zA*3iz$-vYPO+FjZu!*Q)_RmW1OIIn?h9En z8Edv%Z(uDzYv&FeX6kRu$>6-tJlBX%1Qp?YKBLSgS|;YB>`j8LXP z{P^f*Rr%h(zTNXqLXg+7eVh4GMXh$ub6tE9WFfToMl5o8{LP-G#4p@ao@NX^7V z3P5MW!bqq24p@VZeV!<@8E861bMsUowF>GvIYWz!mYnCDL3xyYxH6+xs+HuJkQFV& zONx{?4#0EQJgqf1jv|}@k5}kgFY}bQ!`AYr75`rYp56$AOq`Kd1`%E4;TwIpf($%l zxXbl8_ZUTmdqPWAlcHauGq=^+y_+rNkgXFKCfRgfH(<}xz%YKRY>kpUjpiav4_Z&H zW$lR)%P2yLIy%Vfr@F+WC;}(<&rk2<-1b6y;D6tkl`I&%;qbaraY%{Q(Gj1}nSf=O zkPsoDE_?~#t@7$&Ad#XT$pdm;(MM(-{&WkF2Ch22^+Ip_wT9%uOoe1!@vy!0#im2?e~pq^hqR*@rxa@~!G*an;{Oa?5j$p8X!1DiOKvGXY#BPC z_EkRRXU;CjO_&XD>^4+Wf+p+qm#JI3>r*}@C96AkJcwpPnjR)^{o3zcZCg&y{W~+2 zJ@PJcr93$N%C-Nc>#X0WcS6MuY(p3Nms8!Rl{Zp-OIEg;`!@rQHv3Q2H;*@pRaxLc zkc?3uQ8lU)Pyj{Ug?Ml6Oar_&s2pjElZ(RCwR%g>)MX&i_~U5=UadgBLcm^d#EDA% z4Pk?p8w9od2*{lmf-D3mVueBc@X$X$01{}eV6mQ_2SXkDT~^~;v<9M41F7<-b{=Lx zGh8}mXXPx1_sWaJNE^=%a%HmNDzjqa2gNjZ-8fl&A+Be$WN@J90kMm&F{-*z&^esjY^a!xNOo1eA z2L^TiP_LSYXi^m6*e6dtk7J)bqi&y=UvS`8s@4op8SvFVP{Dkqf;>RLSzvE5gB9zQ znt9((O@F#GNNRwz0OYqZS7maZ;ZySdyeg1_j%+ZM`4;|7fBF6L;~f{?qRT}bMRp1{ zBFo1cO?Pyn`>V|Q+1HDzb8TqnBnS)vt|(epZV6`Vhd#xDd$6;WCYE|xZ?tXwTjA17 z!#h^YCJ`zVRh#V)RP=a&*SJT(*2gC^x*(kb{2>rcQ3XZuUq_?J7O+)1L1l^StBmo% zy8ILk12e{0IBZDGy3XIL4rz5`x1q4Pl97`WvJYsXE%RT> zJ=`|s*yH@-?EF7oUATCNNI&4tK%AiS3h_#s0g6BLVcDPf>N8HW#~~DJq}2%={{Nfu zxqwZ%#Zg7+gc*+M=ttrrdU8Mve-Lns`@+JUBQ*7+EQ87E^K0)sj(_%Ky?yYLCo6%S z<+s)N zh)yRAYc#q(8`Rv<=E$>Ckki+r`gt`ah4(&L*OFLBwd!rTr@fcP!aGpvS4HxBZB;Do z*B`btH?rl^2O&j7r2e$W81K$OZ!@&pNM=FB8nZ0hS3> z|CtyTAeSS@7x?9ZC=%eF9~X2P6ht6bX#}tWks{|4-xi=DI~^i<*k1W+Er`(NW?;zU z3o=45G{xzvHQE<&4IFz>b!C&|gZsGPxc2ymMr~unLj#7(%0tMsV@4ic{4ui-8y-P= zxaja(N2pL{<#nKOPJz~iiUpGkW@#04!r*`tKkqIQC=z&X{fwCAu^|(X8FSN^GoJ66 zH<)tW?_eTb)cs($4quuvoiTn^v42!`Tep9&by^4LV*Ma74|*i6 zU}}v_cJU~t0l39yHj<46fYi#K;e-aMAn_DBz13n7uw0bQ1Xc>H^Hm9B zR@ckg-WuOJiDdIR7&$5r`GWTXGCX!&D+h`f)RG8ZfJ@%-<)6V8v;_?TiK6Shiuj5@ zRcjRRKBNr7xItUj{N4mlxs}_c$|v}PymyVs6w>U-mN4h0VA!SdTh zH}9E$hWoVC!ufCMTRP^l=m)))Z0J`v_1HvS!OZU!`n8>J$c2d9Bk?nmscJ@#s5g+6 zq{oK&Hd+E>3hLUSf{s?+!&_d2Am=Hr0MFbZ&5}XQk^#+lp?Ptfa zo;R_GtMAM5$dy=}YR(UKC~h5ZH$GZy#YB6C4-YK2Aoh1$-DWvrHJXpw>9g4w_1WZd zbJ^i0e&EI152|Jr8$ZT-7l2RELIJ31;QK1$rnFSEG7CYT5qj0IErPje3xu}V&!oKf zvk=vd z7V!H9T>6}QT>8YcB=Xg|9V?GS8UQICho8(VX>sAG^?y?85sKMcU{eT0^p~x0fU5l6 zd&m?hc4~jd$a~q?j){2z?B=C0#4`x$8DN%R4Eo`sYAjOB8U`Zq2!_T(9L9* z;(Xw^F_U;5`aA2A0n?tGb?_XE87;3~M z(gXISHS{k>@>KLL>ngtJU+OI!t3u*x=5D3h$E%T(#oPggGJen9 zX*X(9PY_-V&&r($QE%H|wCelOADHsEsAfnn?NxsNhMSbt2VY9Z%5K##xEfVeuJ1Ox znBCv{5;7>_bfuoAq2-77*3P9{6=gv_J=XvWKcp3XU*!C0adL@jb~c0YdclMEF!gEN zZ94*1`P45IZjW-oB6tuB^cq9`0-ExfAjk>w*5F)~g1Ux}L8RdjE5Hy{!VC$;5pXNc zLf5aC5+WKM;uBfS?yTAh*!xCa+i7CkibaAAS4>96fa3#1`2ml@s-A&nNg)E81{f5) zAu1k!yRcUP$eoTwLz=LZ&;l-JC$&7$Z5FLc+op2+vh|>WlgAfE0}Neft6XO~-H-n? zRAdrco_D3ide9hCOSFZAdNrGSv`4qLCANNf3{N+!OiqSH_aY+7G7=iSRvOeT6GC5E zQ>x|DX9LI?^u%aT$|~Q!#9*|rzuYPZvt^x@Sdz<;ci%6=uYBtbZ!s@4E`w;H%~zdh zq0vM~TFx``Ncn%9r}(Y@J~oxvfI>~5_B^UsCeen2Mr#B39OSr8@yE4j`YVbSY`W|n z^?FeiZ5O%2QJxam{I2tc?7W^4_1O!@cg+=kzuyNedR4=abG2>9$*yI`PW%NZp+7Kb zM1PYY<==n|vN#%Ba8Y0n7~2$_IU~T}(krseLTZFB9yJtiGkA~%d$zH~7?xm+w5-6+ zA>E?QkU!HzVxU|PELSM}GC(8CdAyXBF>%DvW7$(aQllj=B$LxAQ=-Y%+;n<>V zl4O+>wpd`)L9905Z2gfw(8mTNRE>B>?S%zE+CGBqb{}y3VQ2u?J-|(e6f*@43m|AB zQ(Zd@UUNIK z_(H$L!jXGdta|u%L--~iRyH#3z_L;$^eS1YNvMS^j5P9H&c2+@kt4Dg8JO6=7^#@V z)hG#(X?n^$khfcKXsKiQC~vU}Eti(JTZy8DC|IkN5S@?{Nsz*&)&z4Ml4q~Q0ZKf; zNiurbGi6+`G(j`XfCKZ6xUU!itC4^I8uafTnQR!U@;h{$eaGb~deF-&=WU_Uhu(|3 zE$zk89xa7cA1!oh((28>1^AR*#A_dYl7NL=LRmaUp4mEqJy>JpInpTXgJv-tYX(|} zVvsaZR#wLK3PRHtA|jlwWu+w^rU5py3k7#?A+{TM400hy+Lb1aqICjd!sv{e;*?^99X_1f81fiJEUClbe|z_**hK|4^LtFpeZ`;@sq!_Qm7AY|!qqw?i^-h6eM@NPDW zCOo_pQ#hDKC{k-ClKcklSr{ua@iJ&npZ?an{`jZkmLp70aUfC#BX3cW4y^PUC_f!x zTWMyN{K#>(UOID7U9>=9KyVRe#-pIBUtoKh@ycUx;JQ+ecyTYphk*z8BV`@DHR9a+ z68So*Idl(9QojnEL|cY|J1k-o+j8)}FRI$D;jYB=4j$yA`WLU5+_{5B|RQEQ2Bh25@iKzCa_ zzYm!FMuk4IyEyz!4}P>Tho`p|>IjI&HUVY4j$AU$oNX*H;#&E<{D~lLbNFBZBL9qI zEk2C*)>PJv=^bP*Na;O9v>A#<>7%guz%@8rnbl#`VT91$G$_vrL`?6of}xGtYinm%YUiHar;5OqcV*S38?q+Vm34jrgZ&F3KTj*Z5|xMz&&KWf zI#p~(Hk`6LgZib6B|zl_$FBu+cr@@wPNJZIIuB3jQAlA*88kE2eEc4&?1eS}LTUz{ z1juGBATvOGV&>6>IGArBdk*QhahB+m-odVzGrNrI`p^IU>s!I+Vk_0@NBZ9^>V~re zvENC*jXs4|e>B336o=SuW%HG&+di~^OH_B{wsWOkg}vsO^xMpjdu|9O0&OpmVt*+L zd8M=VX^L@{S}>AcmDy%$9sy0?9h2Wk)diJRkoT;6TINlo7E09)vS zp}-E^@$rsP>Hac5qdL*;V~ZxIx&`MEUpb1q2f?>O>!bttQhm zzMl(Cm;b@vTRT;-jPJdD6gKRrFn!{B$(tse73uEqrwC;8^)zK#G11XG_;^Kz__|tc z%4C&r2)Nd4Nq>hsV0<@)Tfl@D)yd8WY@gcVk{_7ZO;+xbg2@2PmC zr*)Syci7}q%%v}JHc^{!b-M$zlSOpduoU(A^sTRXzX`|s zhiJ~_fHYKY4bW-zO9|%Ph1cKA7CsvUz3C9swPsVD?xe6csf;=3E2%(5AY0!M5^&qY zW?hE1F3RopuR)nDo)q0Own#<&)H|Na_~yY>Y%}^rYGz@!aal8SJyunKsj%{hstcB> zh8yQ&HK!~ZFa5|u*uZMlU1RLoqen zu@t{-@n;z8@{{4_mFe!9Y8obz^yl&PXj7#gxQ(po`3d$Eg{hRC9QkVdV9vzORY-u- z#Aqf@IiL4I#?|6B?+)uBMCr(DSj=lE*zKMBh~=_Z$Ht``|MjP}WBpYH0`5G+Dv|GR z;WxT@N9&mrl8VtyLM-M}TXiE-e#G+g=EXflXr{KSMS>w$L8ynpD(_BEh6{vI?T&WQzxLoljn@n7$mp zm#mwZbxiqG(1Fuo>a+NhY)imB(Yt6+(tUZS0Kbv-wTWQTce3NUIdIOuvyTcOl0uy> zQ9YIu)sq}A#+fI+Uk`l!R=s{M=NG}Gs;+9i_j$2%bd0T0g44{Z&)q{C3O;0;!8IcV z4;HC6Xwtk76TJMzg6dFHX4onwpj^75sAIZ53Hiw%NL*r$lJ+_Tw$N1ai&QxdF9t_8 zo!F`v#y6?ng$u=e)?Pw;yzpV0;QcDP4G?3rBdRxXgZ2BRq*5R*fq=^6ROBB=lU}_j zLh~7XjYvBCL>u+sbGBPA@#5fntUJ7>*P{yBA<6g%ruNE?`roV+44VA#w=6zto+%VY zY}uh|L_`2^VTUq*VFN|J!%sBn5#noL>fB{~`AoI7Gx-1G>P-NWO27W`-kE8d(V1~t zl(9u~EhBTxtejk?#jPweO)?kCeK)l%BIKRQEX>HQ(o9FKEH_l#6>ZVnP}4F2Q7hL9 zaMFV62K~=-ZNBgK|Kqt_E*H4K^PJ^#&U4OrHudtt?R5SD)8TaiVA!qSEqtbaKG~Dh zV>@&V*40pIf{cJ^8`lTr-fSD6`W5kqhtzXIxA6cr;XU`uL%)&m?P3v2RW|q{wxuIb zDm*6+@r%`u56C|!7<^Ff{y}PO%C}Uj-}L5a?fa9C`)|IltB1ua4Nvok36Ln~Z62SY zVy=0Jr3c|0sEq3F^8@V0;&U7ZF>-`md)>qv7DVhL+LQFi!SBx0TwlDc;zvf`{(G5> z#}0raiu8&0?#K5i)vUn^fgp$`CdNbQ>c$6LRa+w67!TmXAgQ4f6MRfe{2kiUP4tQS zc16&D->(&0s9w-@4Fn;jyHjsbUH&)h_5OBgy>2;fmdUHE&N7-W+_%`DuFH5#V(0AV z>t1wNcp9G{)&Bn6-(e=yGU*8pejbZ#{>VlXp>FViOJ1oxd4vyCFL>u`rQ7S3?%(zy*&lDj6dMt38FF z6_qIK>MLXSKJF!5alXcg>fN&sElcmjg0%%y$21PZ5{Xdo1=12b1Um&gD@cPt@{cOp#31 z197|VV010o|E}5{GYWX5ogy`tx~74|cOWM-uPZy^LJ>{B`sDe!KTCg@$dY*1)v& zajkIMbTuKF!cLlBYb!M9GM!C4HA>z*&}ACE+v6d5Eo-&MnQp`J+b|e!Q?N6xQ`PtS! z&{fyfyL|C_pwD#eGK)2zT&?>mxBR-DV6S?UY?U1LW6!8wn8o7LC-qx=;J;ta@J*|D z=bDxF>if0DN-nn!4eUGb0?B3I=w4)ZZ2R^ds@D6a2JGKxmuAo)WN9q*6VcccYC-G! za?_KNlJ$#DcNm&+?LJm>H4 zAKKQgo+GjeZBO2!#ZRp6+basEapL@_oG8wu26@x@8y`OJD8Bc!Am~`Z;K{3xx-$xf z6MyKvt8+1Vv)Y-zqPdVyPPz<@;yDTZ87c@9gbk0+93&X#X7cb}^_V4Xe$s6k{qw2v z2DH);vE87}pbhd~C8iRC>dF|Mw)j%&g3?*7aO>k+J@4FZHwaqnm|L2m%HX-K>8J%N zjPoU`o0#YVrYP4f{IyO`V5P2iw4L#!uV|Ymqa@9t;OfD)LhYP{mCOgM&x;&KK|wF_ zjos-hF$h+w-T%=JJW>#WU}vzeFn8afHMxHnGsnoPAD{^G{`BOBkrN7vClu&sR& zhys5^yXio^(4+p`blp7Nji2gu!)dk8#F7kV^y02vhGE1=*&0?&LDlTz+PjUG?|qn+ zHk`Iz&Z_&v`G3{Slu5jWhU1j^n^K1j9|}U7!m9iS3H8}JYEshWjwq;06ggr?uhy=5?Wu>7 zJc(BHLNB*HPJ0|uhe^SH;Y0?vt^L@Qix-nD^biT-l#W9s=<@Ys`xTc5wK-qmUS)ba_4)>8y{M7l~Y5;Qzw>wJl7b+$_SZA zok+-t?=s{Xay5VVc#z2^t$xy;0_C!LLp2_@QIy0`VB^76Q3+AYEgejWni7W4bz3be zg?5*u+MAx9yxu0TOFhR^X*_g)`yNRG2kLDWez(M0>GOUAyJKe`_xg<#UFex4spKwN z1hXXK54L03hc^d3EHnr_R_1=M=;CD-#4dtnJwF57Q>k)Ds^V?3jTcv@vE2;y%i=zV zYeoCpwWI7w#KNFoCPG0QLW*H)q{y!7<>%9%Qvy~ut*!q3)FaEoviV#CuIWsdM;=*s zpmApykpfcX$yBCNbI*&lNQwSeZ^JnH`?k~c)V26mjzly?_*D_=N0f!r)14z5XV(kQ zUDdfV8emxcXsqhP7JgxJ->J3@vtQ;7KAXKBo1dn?J?veQTN)2v##3DlQgz85SDr#` zs5QD>QNiIy`57g|^1+o=6HGI&t$SRSjF)FVBySk#Hs~Sth-ID8f1i3~`G)X&{_jt? zn?JLe9X2I9(uVkAjZrQMYMX3K<+;wdzAQ^I@%OG%yYDr>6iI2d`(bJ?!p-wjXHc54FtulfxkAGSLds>34jL~cw&@zahIb%r)Q$1vnf1s& zEPv9t>W3+zTGUXy&juj!*3zmz>~DVC#;8Ms9UEs7W;&y;eO$%2Y^(h#Ul)prBJ$ZV zo#Hy`^`J^b+(6WKwAV}KrX#V^mCiQ7RU%IBI%qsDCS|PX9R6ibo7a<5MwB*-N3Tv5 zewoK+Z**(b7qP>IJF7mp1i9`TEXyNl6`pL|p1q61MjyL)cC7esNYyQFcc_!RPKR=A z(Eq3~*M9%pvsaEBe8@IWRF3o%v9y(<-1fK=jI)p7Efm`}ZbDxDq+_%2VIp@!R7aF` zqixM>8cM|;(&v;rABNP`vg; z+_=CM>DSkL*LuQQ$~?+~$PrG-Eq=O*mYdQefNkkIx{yp+0=^3(pgh-q{4a9(aP9Lm z>TDokup;qt+OVv4xY~=bZ9?Yn)h6A&(gp37?NY~b+SzqmJ^SDXrTN7k+G%~@Ga+*I z$^v`6wU@5Yro9JNJg2Ixl&S=y`foEoH>4b24Z{(&E5b*}lV&-Edh|dY8|0+?1Ai5iXh@@9sl6Z zP0QY_%W$t=kg#fTf@))CNc-+T4jR6e^mFujR#vH}>#VtubKn*bRB=n>hVJH{^$(sI zSaq>@%bT2%TPMjc->@Z?L;CamiDhBl!qM)Y(w;5Qmqh>o{fkAt?Pr*sK>v-6`B(-N?ep|F=&Za@)e2_2*N*Fr_ zR%LA!nW#Nth=~;?yEnh;?Jh23=dz!ZrMDFG|1UWom@E0Xtj>`_W9 zD|vLC&5UM7Z#P}fYH|^*U%#HV>ZW47y@f8oM3aqM*!uR#E4r{P(bd~z%g=jFr&2W> z>cg(?YL9*WY5eVn89Dve(YO0pIxeIe{NfAl{bIM17I)E~ddVZ^xGA+jffgv|4fcX+ zufdIY7w@x-I|e)`b>-GUOIRnid)((;;JM|-r)N9j_{Y~gFU~kwRq-xj^XD_RD?w07 z)cC}xtES|}LZ~drgB8I+2m|7xSeGJmGs~4SzXA^24@ixLRc)XYNI|R!+Lqm065YF~ z9TK(C4(95rv_UjA2g4LQ~T~))@YqJ_YTnf{8 z0tDHthAZVjHS8P>#jE(Juz6A#g z7bCjO+u#d;YFnARQd?zG$Wo`%tiG zQSzOf!pW_VHczk^jdI`Ao$GA?CZ?}UMA*lfW`qoLuAzbv@dDX^Z*@=UJA6V_N0U2IL8IOp|)x1>FH@;6{cSrFWTtq+OjT~2lc!0I&ne@2oJo* zPD123B5Wv=X)ulk0i=Aw;c;^i^0|UIsGnmzX+8-uo{}_an~4Ua$9N*(+6?4)7)+>* z!Fyn%*w!?T`p*We}Red8qUlPQcK2U;j3O zEOBK}i`$(s{%aDyBlhhc|H)ryWMZPqxGTPTWU4@5!r)!^{1rcJ>G$O z9CXW5isO3od|(V;O7A4R?!$%8A+B>YF)wnru9*c^gg$PmnN<^zeXqwXi!t%zQ_YV1 zhZge@*#wTl(x-_4?>eT{UP#R0J7Jj7R^y%&)*@TBiGW5V`QW%Dw6>hfNssB=Xyyy3 z7%EG@Ar_~h^^wb=kd#5u!1mp{zrPY(=AN!&%m>v4+6v_8283%(Y;c6@Q!}ma9{^r} zGHonzFcnrB;BZpBUg^sdT_izPYwpzkFgmk1wm!5`t>u!u-FbM{m?g68A#}<%i{8gd zjXn);en}RC$_5^7iI| z&!XM9?8k==w-~~bzIrFmTwx1dk?L=Eczh1ylI2SQ7JzQUB@+~O(?PurG70I0nJf^4 zNH;jQ&B-Trhan&^jjdrwF+FVCqE>NL5?birv0lJ?zwv~dXXt=UP@b)3S#Fo%mY=CR z!49&3D-ZhmJb54tKnRf|eoXNZh; zM$17}Mw#29OU+B}?#PW>yYC;Ql>|_=?ZL3&}2sBcaJNNEzQt6Q0A(=-*aq=j|A@xsaV1zg@8u^m@BRn ziS7fiuF1H@GYc4-8WH!hxUa3;(B81x%*jBS z!LtHGqn^$L!zB>P6Qh9{Logjk$D##1TUs+o(#s$1nhbT4diHztgcd~8-Umn1eeQ~^ zybCRu4aJw}HHBtg{mVE7X=0auXt|wFso(XGyE0}dCM>C8*MRg!Ri_}loc~~qA1aTy z?)&U5DjAM8>SEr!*K{2o?ek*xotG=S0m;X_~fl{ zf=vFl%G?U#4%gFA!0^|nzdSzp55@Z5@>e^d09JB6L!9KnJ#Gk|nF^|kj`_tIW@r{Z zPUF_qTiGe!4@X(clO3^xOu_!*#$MYk!ZoZA?3)}hJ+OIF!B@G8xn#2V>&?7mI!O}U zA#n$GNl`!8#nG&|`ugKXlK)%4I{ zdqBx}MdyiXoo=Stq_>cCR29{*)IvOqHZ&|~{}+BZ$40P+)4k!|0wj4sVdo+NX;=!o zf5{bA^(lucfBNbA4p(;R?rna)d%bng)b(xC{Rij!c7XQYRlDyyaQGKF?swY%TaL^A zOBe3I%x-V`m^oYoh6raMb3o^3c(^wtX?6AkSU2Ua>gv5kc0#oZwKD1z{(`iG5Mo)H z0M*!Z+YNQFc!uZvs{WL!@hlKvL~uMH2@TGIQhwbpBooyxX+iv|;ez_u7B`k?|3>WH zK)Gz>jYN*^5-J}0e*7}8%#))~bctj!{yic7;ZlbYkq66n=KXNj_$PQV?31N?<+0En za`nIs+Lw8Yb@*^rHgG@T6K7{)v~`y?#El>RBslpXF87drLM(-3;M~DqI3@shiXaZjD}0MYwt#BSO3A^|+H~*{ER`;m#@vF@ zSkw-)5Z*95wGHliN3W}!==*~rol~Z9(Z*<^54;aZ{2?<6oMT@lmie7IfbuWrqVe47 z0c%%id4MZY-PkQ1>EVd^p)d&wt`)Cc>qiXj8Na5gdal8sq|;+SSb6Q>YPv6i;DCV3 zTyPR+Z53|}6L*bmlbH)iqS%3NhpBH|g-rfhR;xU@>n%-OrO9*mqojv=C{!iU7Jh>x zZ;BFy?k<8Gy9ZYel@^8%mn06pFJ4FYdfI=Yz@Ymg?UwGu)b+5JvZ||2)SINC+{RZ+ zWOf4*Czen}03 zL?wtx54@-(6bAh-M#SYOlA#`#I$;1|)bJf*x48|l=GRRC&Vhf+k>b$U8sEoNDgy_? z2HFe>$2NC3Zw)6A3nJz_>=}RgIJgt^iK(?LRO%EeHlOnchbQADFD|NnrTb6Z9<4DG z)s}K4+(XwJ22dWMZ|j;l>}X=noizqh3DvkSMyLP{Cg58%n!q_NF~pn$Bz&gjauE@{ zW3aFfSn-F)Rjdl(%X)7!m99Z{iodzQ(rb>9E-QCk)@nhg~Lnb zFUTk2r?-%Ymsz}E4_}q#%g!}XMwruE-qQHZvQ>n^+mW1Hf2Mavf45Czu%DTqnKi|l zqK7x&zpuQ8_{|v_&Uwk}kbXojqQS$NZw#~_nuHlY4uyW_s{Fo$$u5L*<~DFTfQmy- zIW%H5XoD_?BC{Y-qjBvAW))I%4-hZfmOHfi0O08eGpM)?I%i0bWX6Rp`;D!QGn}p0iFgMI5H6|=t5klm`IgPi|M(t+;i~%0n zNj2`<)=v_Rc-8*Y;*Ff@e~d!jTKLVpw=941niCQd|N0iGFW-xlcK{!^_EQ9}%X&P(#D~e{I{i>bNqJxj5`W(iMuV<2YzOWj-3z zgv-F8_;}+8$==Hz(ZIiKJB4i5$GGrCwjH=7U@Tq^1NZ?v3Sbn3GAxgPYc61mr+{t8 zkLN_q2ZfB5V7hGh+VyRO<^4&u*>1zGtiuuBxPQB)aXtrz5-!4nkHfi#!uSSiYvX(z zJVUvQKX4oHFitrF6&2v?|~KvHe-MIKwY0p1Z%u2q8_A73+T!lgK_L1q}> zX0ReBGqD9c^C@a;1C_ZRzn;IvRMX0#&bW5zZ<#&e1yq%zc>=0mG=IkRNm`407}2^=!rl3wqUU^lYBIi)3JeiHb^?vFHT~?TAKY!r04V5))vVIA}7Z~ zxea5^nT%N{uV6obN@mKLNnS@)C%1Y)`gWmKk`Gz-5~p@%C)raN~U;;eeAP-a^rBCEUK^R?)cg- z^Y)MF!%mR*M0~)oQ^U3S;Oi6Zo9;hNZ|!w06g_9LL-Wg1$mRYlSTAYqfQUiWH}d6i z&REV`juO`FoY@(*`&3n;2X8~PV6&nt|B`2y4~^~SX6zni@JXyk&L?mqU9QT) zeS8RGgMNqAaBv?f&$v!aV~8YEEL->N1(iTOnaIz| zWpoZizFF>N;go;SdXaTe@_6V0toSZT%6UbS{c_M&ly%?rGt>V{kE587^4`e%y4*4I z2F=R&Fw|rpNa@@@zU#$|npe}w075VW({5}V5bgGA?ic+Wdv8Fb6x}h)nB6(6G{cwy zs~EMY-5!q;J*GBbYKauCT7@T2kGc!BhsP9StU6OHHAJT0bR;qM#S-aMK3opJL~w2v!2RG5Q4-nvGUqg* z+*WF*Xjc|!QFV=g40Y+gaiYr{h93>K(~Q}tq^xVT;~-uB@T73wfJg$0nWGVA1??sc zkqWWnUu}gRK~wl5BAWA2H7!(LN3Gd9h!d3%Rm_BlQ-Z6w&=c;S+UMuie$|k z2K^6tMG#iHx3m$o;KRu1&-TSufxUOUKfYa{t?uQy@ z)7uYV-QN4<^}IC$vWPI3FY^LrLFAO_t0{e0|CoG>FhAm{MGNj}@OZ8cYf~DU#Qdn8enIW)tU>t&M0NQZK21ovlp-VqLYC6>A z)t*PH@NWw3pvE{0*Jq7q$U99DvDmPV!mjD4GuU5xwEN^Eh!DnsB94%RX>g{Oe3Ue# zDzpCgz|Vs37{j1eI1lA!fmL8l>m$?=>g*I^l_BP^_V7Q|4Mx+-R5n)LC;|%f0<^L_ z_FX>5U|NaV>^!WU^>(RTU?53yJj%dQjgB%UPI7@&y{#;eRlkoTAk=S@*?Ea~TXdLW zXPpOg8~MtE+Kqfw>0MPRBS@6w=*@_JO3IAuLgYaMVIu9R0xJ1GjEeX@ZCp7Omn%s~ zycpm(Mte-t7sEX`cA#)T#H5I_56xypgCs!#G$~q9#QYJkT&PCO;=EE=ec%2Src4zyE4@)wf62S!t_MbjEce4E4GvA$!6i zx!CHcOsP^nJE9xQ$Ci*&u%$DfjCjucPo&1Hp91RkG^PyZmo)NyngqFx{acRE3bH-L zPR-H+B1nv`*n1#7a1r7KBIM^&vt;vuZqwP_r}{DJ2QUuH_3d8yLh zN&Id3>`2GJuGszzd2OL^Dd#>*m?3X>JmM@=mCeV61sr?>?f)f@G?^dmh2sh5;SBjJ z$CJ*W{BmWjvWL*xVn4*bt8Orqv`UzgILSc+$=?IhD+h4mXf&8+P+w+!&TlfsX33)Y zR)>h#Hw?vtyf5>%CB!})QZy%hnU`lx_aZz$l>a6F%j={cr9Ev@p9D&6Z|z-N!L@YT zu`HCc)}6HcQ2XBUBcP&g2bSsjhKCZZsGcfXGp%{uf!Yh2G5N!`Bi58Y(zR=~+aLf& zBf1++3}hWfUOBXZJ@Xd!5#DpK*hG}=uTnv)pfxk=km{tvZz!M#IAd!P_^za~ZPFhT z0F~YJXkK>^SBoI(Ft~0Yti5qxwotZE+WTMa@yEbZm1+~YpWh`mcHbGp7`M7*PYa|Y zWqlSsBA0*)nG1Wcr=&B|$lbl)wdnniI?qDwk9;&RG_OH58{aRJpN93OcNAiqYWL?) zdwpE>a&SucWDT;OCLjr!3KiEEUmC z8eO!1b5ofs;dhpC>I9p-xxdGh`aK99T>8LnGNX2)k+SC`v4_}W&|}bT&;<>Gd5BzM z7qN@5+2bwso5tpRPz*oEJ{=Gz#tH|-U9rOaYEVLebA?_)ujlyvIjaUKs2I{mCD!<-9(t%YOo#>J9<%60H0kQy@t!!=V5F7Ks4pY4whu{Miod%M0 z$CwW4gT}XMvf?GO7K@LLJf+wN&eC3k0?T+d)lJwMkv8 zLrD?-3DkqR!!Pet*B2O02Peedx2Kow{W7ojF-zo<5qsa&dBi2Zq41b&zaOo|jU2YG zvF{e`hP9}mMO1)@(l=hb#wx_ceb6O#I8SD3D>JpKy({l>lmw%H$S4CkV|s=i-iKz6b|iXM4O{79a0-S9PMXq|i$JI{htdh>`y z;xC)Zi$bJL>s($cUL633QgXu;XNZN%_;?W_Wg%pC zmSm3P9YRagZ?f*?ml~jh%oz}EFEjfZ`Wkwp7`bj09jEr5b{L@5bH%&gCA{_0J}G)*hGj-G=P0e#8l{zv&!>;?7564?+uDaf%40} zm{z`YJ4tkY0Mj811KD=Jf%F=yS8ug$Mro1ay$<#|d&EVd$dkQKh`pDXUFJeB zziGsG-k@ksZmS+!6UEL)6!$oS<&{sGZ zD|g`x$bZz6e3>^DD5bwMV9TXpZ|E@{!wE7a{wE{B>w!D++leQ?%;Vn~AV_ys7E0G_ zm!B)Em;Q09Tb^~7+9P;fh#eOfYK~Zi?T-D3SvpGTy!DMe$6>9dPe#;bR(s_s-@cC+ zEM*nRhe+;nu}_n%nI!A}>^QRWxkA2Rnc^=#xT#?#2<%$tQ}=Z_a||@iw{#Gzve-ls z15@k3)X@9%X#dMeAOaVtlf6m2`($q;KW*s|65j+f!HlVDbnh0?A+KgHSQ<8gw{hJG z&S_iePv}_;tIS)vR?)_SMGTV20ou|qWyA?=%#|M8BX*PLS+N7qcY8}OvMNKp`T@YD zNySTKKdZ{tdc8^*Dx+3!kR>jazbzbLlSGC~n|w@T+jXHpMXuDb729MBoLJJc zBwg+o3xj+p0_Lnkov6#IF;xBzO4JuMr~7jTQTO4^~5hNU@m$OY%eV`V#{==1_Jt9QDW9OaAdjC`4AQ?QYacvF!wLY8ao zVSd^cps7f7W`3DxUAXznymx*BIHVUn&iLa1Cgd`%GGke%*)lH_pT->;@$G)O1J1!rke6^iXdNOYf-e- z)PAN9=sG)T(>q@(^V6n?WAH3gX7x_lZMNxTWid+@vgIUeNW<%lEHL(r?CjOs@>hCq z=#-)(U*;VzJV-xQWHn^4JbNfaqf>VB)^ro)fP#h&;p@X@k5_<8UPM2KJFj+T9n}&;@3K=g zE86h($XfIp2l#|gY6V|*00`dy1=WUuIZ<6nf&@VYX>fzHaD($uh4V0*+!UBETAMEl zWr;3=h&A~#&#p(lj37GVEVW_8c09=!aakgig8d7+wOA9->1r$_G6a#*yD9U*q87OxA!c4Zlf zJwIqxYBWjn&S2XD2vXl?Ouq9$7>K)M-fL&+npF9@TULkeI?|lUoI(RhfwS-_tNJcE zG@TsG6bHKx_Aj&Ocd8$8y$w>$z&Q!qzpzc-cz#Ur$|b7lc!61VD_H-MQR8fE`fK!shd^duv^~q$xK9_>dJbeIL8-T(byLG5^0%;9#NUCBc&b` z(0v;|jqr=IZ_CU3EjCFm#ov{SZ@r<%#@&aqcgyLYzJVX~cu7>#l#)fZ{98F~db+&H zUp~Z-9l*k>G}*Baq*jsQA(1?#XMk!`{E9Z1^Sa5WlC(^E-6uj&6e`b!ft23RtZ-XS z7ZfFut2~Xs^@Pt9&qq$o+=g5*sE|1Ycmu~BK-mCAfNpV@j#nGrnicoFps`AEn$5b0 zQ}KVudF}vF`l75k0taqb2!0b^BVQ6<3+TUH8H{3U+GWmpX#We10aOlcn^YUxH_~q= z6SCrZ2xef|9I0&`vHXb4AJk-g8DatSgXASe{n&0dmNYn3ex+AIWP?PFhP!uDqgMzv z-VuvY@}~!^WCI%&n18Jm$1QVYh~+1;isD?Ni?5b(<;l-ZWm7`xsqSvCq^?;im6eX< z>9Fksimu>Hl|ixd8LYA((&}XShS*QQWz@hi#ivo8VnzT?#JYo>!?6P)EIKy7gxVA; zk;j|WTe^3~bp;Qz_CqSFz}yHG z+oX3CJXYmi^uDWPIJbkuZzqEbJ5H1`N9U`g|28DCn-wj}ylfu2C-8NUa}iQ4}qQJtv%q(PH8G@~w0 z$6Fpzyqx9VL3MQ=T%Yx_h4zF{A0Ts3yvi1`u`BdQ@8K6$q+QHGGgg&9>j=2xFR>CZ zWm|&O|B{t>Z?L>hl^%H-;whS9PB%5^kf-gQV0{~6-(9krUfqj5*r1qpCQJH>Smi!G z*5Z?d_3xWdU@jb{e7+8!{`k36^PMx2zCg_zyCdY^b0=cu{?S$^*=F>*;Z~wdnVp3B z@$02jc7*7ve-AG_R5oBJk@QGJq#@5Gva1Hul0?N%A(%Q)O^CfCJRef}1K^V<7pJ zQ%9)Y%c=90wt+9B-vrx14{^p^j6mP6p$Er_nPNxre9>c0u2rS2v`xX+9Ml2Fg%j0` zP+`YnCsB9AiPh!TO5u2UoaGD7W+Kwida` z8H7@BTTPC@?xl1-?V>W@m}-J;$5Fg~i^x_qZWXXVdIos(2uT25y!(a2FN5Ugex{dK z7zqw)ii?Sg7xSBVi2A= z8m)@cd=WjCZT4jz$gZ9t(a0(pk)47a6Gd4C)o)U?QD5D?*DWg3=>h&^9{ZqgM zgE1-0KHuNtv1H<2?IbUNAHXN*%@JJcq*xhERbKRX&~QK6x*NxhEj>xm0s^v!yxJ3Z zWoWvN#76@FQV?`J*Q+Z5$PSudn-?x)_90`ag;wuJYghsv_T~g(g0PL#F2@`B=p>ee zC=3V1E5RqUa~t9za#y5fTz8!*bD>qKgW)*5Ue%SSLH6rhX%J*LuYx zZqpy!YU8q*>zZ0+(*fyOJ`nanH0MHuK>`)I@E_N%^|;Nf>ZyTN*TM}DT6PBTU@9nq zB2|a!oSt&jT00`ccWs@!(5%a0B5ANI(+ zw4=nIZ#Ix}4HMDDCI5W5e)yk{-)Gqd&n#%u)JwR!VE8ZWH}lqXa12vgIAsxPQWSLp z(+(b2VEQp36=tx~rPn@&X+~y;C0y&NY3cHwD2qN&Tf{O;$RcHS%wDT~IjNil;LIX{ zXH5Ox=uivT90>&QA$fzI1$)|$R!9_I%~tP{FC#LDCTk6$wzn` zL=1Q%A04N{{7e^Z(3-|~r07|^BA@IfpENp28cu+gLw!U)*)r`WpW?hE)H`^+O&B%? za*{mv`bQzw9GYuLy6rQHA`R&qMH$7kg3q;0-e*;3D>FzCrpgu-O17|IMnDHU-8ilc z^8vrVkvJ12hgh`^tlD#&4nK>IZL%NoYwQ#+l;KT(QE$>=w&yaZ52t5Pp`i+qLKF-0 zMTRh6)QdgAda1qCQEXF9x^fWy<8D^Fda-G*5|h+TmkN=Wd4Aw)R?wl!6={v6( z766zr3T_drL%awX9@EJY;8OR7iJQ(en1;E=d4gu|kQ;p!+!5mrqVo(a|6eN5gvmb# zuPLu7R$VI4*9-YT!1MyipjDk!Em2a>igFgpyvA6yBBTxV=|_!X9&?^^1YkF?>K#}O zfvm5x>OQsE=mgjaKyz0tywe$cVY?rFESWhe<)RxIxaSUGsHQq-DY!yt| zy0%uL*epn?f}8^gmW2eVET0Y-gq$$*heCHs_@5s=70&_UqWMB)3YsF$0y=@=*ObvSYC2EpSRTl>s-hrqXI z1dh7{oD@QNG}(Wgy3xqLMf@8FoN^$ofgC^!B?thTBcy9X54H-X2jjLL2$fP!J)z25 z+A8~2Iw|EU1g+9%2pq+9U?+&;K|+mHEukg=Xha*@S^!03`E}khYl}fpR1)65LT66& zpnb$qP)daQ(AZZ@VU<;s`(OqAh*iWYKs7~PPZj+tf-;PxA~44Etq!$z2Mk%hk~uc? z!hb>S+Q;JTNMN$Oxmj6!P-aCigAbFm3wX9XTNvM?l$M5BG=Uo>JpK6$N+3T4vzg#f z%58v!DW`lp#!TbS)VrsmX1Vv{_HmVD z_sgL}`r_n>itC0$gPe^^Wn1^`(DXf(`#B|IRh4A>rU?2)G@vlD?Y?l3J2$@e>s7B+ z8HcJhQx;w;q5M{5($=E`X({ZvdKZwEheS#y3L8L?2$}G!A*cZR30uVrK#fn(Rw-Y% z%d(STkR6n8rKhT;(|f`=dMO0`nBob~$Fh$lWVCeqQHne!Xrt5FC$QFGaA8SlQaWe| zoc{x)KgG7>VQT2aL4-)Or49&xWb@e=q5%=2g6l|+6nVj{MKSKPO~CD(P~^2OBvh8k z3#}>xq(!kHGK{G|0p=)NU{&Qun{IpdWsC7mvVn#Hh}e&lCPdX+l0u@W?#a+DTmJd+ z+hL1`kdg&u%m+5|V(duPF%^cbnbg+WtHN+WSH0E8K6~ACbto~C{vS4k1QL9dF3x1_ zfEdBAxjz5Kg3aY)p=2zSd<;?>Lc}gY;gYfmKp8Q#b12pb0SpKmD2q}DFyV%`1GVd7 z@vs2H?4ay0n8`99saSeBc=je zfrJ@htbLLQSyK5cQNV=nsdIRT152XNSeq^7gFj#0DCD0o4F9MkMp+4CKJ|WL(wLZHz5~?uW^A1ikQh zvLsNWGz7!o6<KaUMW@_!LaQ=79W#evI$XTzv|C6gB+g zK%Wq0GA3goIyHo(eP4d#u4(g@O-qKIDG&#{fR7j(zQnrCvhAZ@t=>mHAX5q>!k_^r z#?F8&<61lvKskarIPjaq-Pg>a)F{u#VjK{X1SQ&U51Xkl=-Aqc@c=c7G zyN`cp$s^|=Pe@pUph^@H0V5M%Q#FHihWiNODpds?5@KxvB<1^XExx8Z-kH$~H9x~k zfbuAQH#s*e|87@$P^L}OeAGSd{bkbA5u4Un=5doTcY7Lh&S;d{jvQQZK*C z1CzPrKgg^)4;dM35Cs~~Aouo6MY5|H66<{+Q3S37_;4;~Q#sVItbD*W3G(uy>VHG| z2Jp>}#DC>W5d@`6nTJEJHe9XvIT=a^mAe00rRDj{%tp^n_?vz9x~vZS9VO-X-(z*d z!%6tp4i_)Lzr=5-#sp#j$Tfh>pYvVn>gsu4{{zbE9Ycj%^5E#=zYK(uuYf4vW03KS zzX(;fcrB1PS9YnTBtC{47vnnRs`d!7YH^BzUeai`h%4doSMUCjAy$S=KLk{O#2~xA ziy?x3X)U`nE^)h3Zeo7APOX`UD%Dnwf#1Ho9Sw?Nk-Y^xe)fgqxvlN%k;4TzfwMR4 z(4mQcDAW(Z{}L+E2ycUbsgKGxoZ+?lZ?s>FDsb_*csd4DA4pQq8Tw_kBKd5Ke_W)S zy3!;F2>4%fY;b)=y!U{05s$~$g%yGxZTF#n=7Epv^`ds)a@39ZZ-Z~hb^7|NzWylm zBjF0#zW?=HAC)zMpM}@Tve{m@qBX`B%2+Wb0!cd<&FGC=pi(dXy^tJG1}X!_0+r>2 zj31~5vVtdq*L~`se`-qNd~~#i=rRhre#(dT)yej&ijsH2m%;=3?*D9vl>dL5O}nmx zL-J0+ckQ~#wkHr^+>VAgS@m%V3@?7e$wG_Q7PI292>v)AOW#&+`lrxe&wrUWvshuE zn@oTB??vsh;rb->9dF@0%Ul()sL&|0#$fAe=I@`Hk$|Jj-9a^jzSVZh5>WkY7`|7>NfxIa1OSU~Hr zidy($wbo6V+1rF)YTxHET;5!AI{(bl_t3HLBA1`Bi=6%Dhn#z+56;~%o?JWAdM*3n z`goAAWQChteaLY)2h0E_s#pqs;i?VRNT;vu$xpM_+zNxwOD;>NiI>r;2}W zEU-WE$YM}MxyS6Ai+VXWwQp_RxW5l>>Adn&{Jz@wp6~Kg zdHl^k&sMz7oNV~}$=i5`vEvtQ&PYe&6=t^IHAJ7whGk+$4@5U8zI*QS>W8vN7Q;)% zE#J4+#cO8Jo>G4K-%ImHy z1Ap?+KGV~zWT_jW8NVX#r}z`izDJZc=UvBEj-GhDgz~=s zt;t${ZYv>9Y3V6m?2eC(CRwGItbe++YVoy0m-@zk+T}VWUhzN6ZIVh(%Bo^-zPjl1?L*Jm$@Ysn z>N1bt@BO1$5&NCw+!b&kwRT&ub7}pCW|`j~UXinc-DdgQ$Zy^I#+O*FQnC8&`QE;T zBR^|?Py1N@_=TG0C8ja+kG$Xdj%nVQPG8=$;Yi21%xzX@mg+Hnvt@2>9oCFmdi2rx zpvRU+gPGN4S-&$KD#}JLnK{4AvcKm`UrwFe5tXU*)51ra9&Ku0)@rx)+^Qo--oCa< z%syyNkv%_4y|ukH@u1eIOU~Pb)J^f(OYVHi)B5WL{_1bfZ?MmEXCE*v?Oj=yOKm-W zce*J5kr%o7ih8P<&Vdt;Hmq26$!yz}(XCro*cv}HoUZNcX-O=d)cM=EEj%%Y@&6I_ zCh$)OEG^a;m0g$^W0@K5hf>*POF~g9Br}F^ zTe6lVjICrDOSZWG*K|M6^Zou`|Nrmxd!;$f%$e(4=Y2lc`}6+1uj3p^FFMi_yGA-q zorJH>FJqd~J(c=v%x3ibk{AV@f_ayIFAs}&9=*dRDiMXr`uU-&pbt%AUli5CBs)jb zypeZ)6OHm-CZrxlss;70PH}|h)G#n?A4878HNyIy-DbngRg^YC(g(InJq(F zG@m+krswIMn%$}H{5G!5Da?Q_+Kjq;psYgEhCwHYR6nrLJ~JAH8EXZrYhe5qW<@x zOlTWP7r`C4y(>yl>-uWAtSivVIJ-jNf#7-}EulH5-!(n3?N3#kq=X8{(j}rhg3!5s z%akH0eT{(NVp`zlPM7+GcaF<4CenvsYdLKbzf-?j+rPXmAgyH~(mMC)%L;5+r@Mc} zwr#u><84l!Zk;M1_kDuhWRhR^YG$u^IOTj3a0u(muU@Xi<%9VsrOU&KJhyW#yTeo; zLcZli1bnUH4Q^xDlis)Fh0S*#raqOUI_Uq@@yN1YTfC$Mm}G0Ha6PNrVI>|~zWrx$ zky+#im@&)>hPg1~`W-EJ>++y7N-5g@rNNNxc3+0Z8ksG7_u~}dUu9m_p`5sE8-VF6T^#ndm`151~yWTKsh0@2%IvgQnosM86x;vPJTC_=y3g0m|rQC}k zT>mq~I(=M4*UNY;7~PX?ifz_0wjuF|B5fO)CW#5~jlBCYT(5gWr6AMs8g6A_TX@a3 zdQnIVwz>hV)XqB;|& z8%rleH7vYN-zC|%!M(VuP3?kQ%A%}3fPWKC<{W={t0O`|ddqg+qPdr4v zJ8JbpkMXBghM__QW{M+1F+12A@n*2m-zX=Stq*;l>t|VSI4_4SCZEX<=`nat(J$}N zvq)+$V~XWDV^8#lXY)vqA5H3)ezU3czN&xulU1IbX$F#p=+YoiP^k)-2NvtGgSvzx zEl8aq?4mADp6mV}w5UmH)EePFMSEzy?8H|1&D1qf6f(a}j{1!QCvAcwA12s;qo7E} z(pk2n;%yJfH?zzI%cVu@Cb9lGMKbdY($y5$QECH%7F-uol%xL4)_q=l7sN89>+D(I#rgj}G#iuG zZXwbQLw~%@NkLy{D|5GPo>UVzJ<};r=1%!`ea7ak075+}c=jkdLtU5iA}&6HP_dmj z3%fprsgmG?($#Z3sG=IuNobNezZ1zLoK%#o4izlt7r0FyX%9ZrNqML(mS>AOIi{Aa zFyCcuO3$7$wNRY0t{K(yI#f{P?@gMT6)Fl1 zOpw6qQ$2?Dyz;9*8R;+Zqcb2hxz*m@)}xYMLnO=}&HBESph`}nZ$|JbH&KSpnInef zn^NrDo5fVpi>!_?#fJu7&xA1S>E51wN$#_Jhm~zH4nY>zW%GZ2vMoZomrfv_sAn49 zP)6w-*Dnx7iF4e#rvjh5ouGUtwl@f!qsU%jFhkL>DGRpeu&C>Zb%-KyiL3AKH6mt7rN3jiMj}!~q25w=xlP@7 z=i}@5jvPIu31{y>HK_9TdwWEj`Hbd7Ua_NHv&EDJyMLCp@uTCN zH(dylCTLR=KCPZqU9#5_Tqd!NYvZU2OuNhz1@g zZ0&s21B|<%^o|tA2TeotzGr^A;Z5k4U`-PnH~2t zPldB%f@lE;?^b3~S0=X)ej+0P0oyxjlDwZ*@ECWtQ6%o#XJ55u@AeqnkNNV^U_w=G zGcx`sYlr7cpO#lB`9=V4ao8A4-FueqP|krPm6jNq?*|@FX+Eg3&}8~l@I>GkA4`kR z*;r*NT>w`dmB(D(EOU3(Z}C#<$k@q7x7gCb2UM%Ho#%ZC?x7!xtunm@r)IgrjqyO*Ai&hMtOO1D$iqmht1XU z^Tk%_Oz;AFRm3(Y3i?@Wm9<@N&uSQ8b$-KVRrTXg$W$`NG%0~2wm)A|eD0rCSWC?-VV(c%h}F)o#(ymm zlmGj>Y3u)b|KD3R@HRK_*I-YC8OPoMwWzC(G$vH!ef&*Q=B1~TFQyUX(Pt4j3D6Rb}ztolKkAra<_5)q?T znc90-u|p0U<&GNV)FDxT^}oOTKgap2vH$n+{a@EmtdRJ%m2XuJI{PG#S0-w**y>^3 z$I4q3;^1`mfne~sc)r+j`~TFIjo}p7Gp6;w$KrlLc3LTo>DU1p&hn+jdBgvJ@$VDIS~xHAL`>-)TNP|8#`gE0e|n<4{OckBvVx7Iw!=C3b)tx#H4v3ea-wYwL$$a5h_4qsA?{RjfFWAKvbCP`CM>7N6I zgT~UltfRKqDAVQVD~|z`!9%y;x#>*DHvn8w{Rl9s{v9Iaj+#&21zJ@%_)X?qXusts zy0KA#&oqdR*;*nB#y96KxO{X!=HtP;#g`J99#-Jur3%c>-i6e#VrzWq+O6{Q zRjGPDPScDwz8DLMCd$sPcIi)5<{%u&#N?Hr`R!H=ls^3%I2WT&6=ibs=jQz(jsxH{ zQ?f8wc^fT*%V<#)SKU{nr!9ugGguMnSlPk#)o4NffP*P;m~i1BQ!vqY_vHR53Q6i# zg)#W+7Ph|+wSYf!VVNK7Eb}A0Ilq5y+uTA?wxM<}V=wkAX_Z+Lt~hA;ErCaWP**W^ zttDZ3$8F7&Q&nO%B@v05gZ9*O*!@%n^}fir?CbbDMimoZjz8ozHO(%PeSFO}c>bd4 zVQR^bObM@ND2nKb;NDX1ZXFvw9L7PzJ*@jr>Y-!-=uD6VCQ7bvSf?XZ5gpd2M>)IJ z!`AL0WlqNkk*{)K<=&C5OFI21o^Q*PxbCnhdA+CDuy*fx@IA>+3bcA%j?mW{4j11} zJiA@`S6@6Z{2z#FwIF|1;rJk?&~@%D<1tvUv~Baxnqi&uk6ml`h`==QZoi!~MNZo6 z5QLxDV$1S;4?E-7OE$N8W7A9tvA&z$d?WSecG_C8O_y#5MTl0@g~%^pzy!;5Hp`Q_ z@>>N_N_XV<*-P}S&zE+q&8MN7^HUuE#H0CJIcx`PnN^4Jr-GF3xKAg*)QS$jzuWWV zjtt{|u2<}kZ4mW$b837LS2a@_i)KxnobZroj6#BHV z)($=x8gtQD3@%5d-Q@ZvjfZlC@R_Li8;X9T=oMX30)m0c9*a3V%ZZe0J&HuRlNI;` zh)nBA#`HZHYWYdTh1DsG{?)G*3U{Rx_*#%?a}HbcyYW~#st|)c&b{^L&>aUqL3C$} z!R6r}J8kY0A(?PQTo=gHC{vlK6w(p?yy30wYVwD5Zcn^2T%Ru4<65^7*~a6BUAM7h z$rVlsYgwBzZzHX+`5^Q8t_q#--J-cf2@@nD&YeNCW$iDSC)(88GqH^<&a@#(UAO!x z-k}bg#h%@fU@cc&wYvJtVEEJV8LAJaOfkxU-R*)ti( z(3{e>7`8$k6N(OFAs)NPm7kIqDyo$emrN1$(&MD39xX`ymW#DpB)^_S!x4}3lLZa) zTRY&0MaTCIhzIViM+_T&S;N|};-Xf=GG-ACtJWTsG;))YrK99vA# zQ*^xs(+Q?}*i9?nl1@i5J2EA`&eldGPOKC2$%@Z|kuoXw1YA8K?tKh`j?HkMkN8ct7gzLugY`l(Jj2&t@@3c^doLgGdW6bBFAx$1Y_;yV-iiU|zJF zIyRMt3%NQUu_%uR&DG{p(#`zp3=8Ar18j7aWVd@VpKb8_;}mUEI>?3n|`}}(t6|TCt_e~l;IBDDM42N`Y?H>Fb zjdZHdZ#}9b3RHL^M?~MEP4@La=3wb7$nL1{ejZ(~+3YGy%;~!@I-Y=frk1D1Rqewp zMSH~3BGx;?Ec&aFK7pbha3r|N9a<7XI7+zd> zY#ZLIo?U8e_cT9QT5P)win+B*uwNe8vun~ewIM^=ze2@~un}Z0yXG7E=A5cz3Zr?Lh@m*^}rF4P_p! z1~u;ke0QuB50RNfy4#&vZ*dFad?n|JSxNz*{w_q8*O0Awr%e@%!Js5-WzU|m{zTW4 zoyTV?;TROi%{1Kf0c6u&+PQ|Snl^X4^NcAb%jN;u`EL241zKYo=3Y7s zD=1*tj_DL}b)S~HnO$T0J^rSyDTy-(qn`8;u5HCt=WPTnAa+NV4x)D%4@GD7H;MMk zUNih&;#=_rNwk9JnmG`vw1jB+mfheAwHRwtDUrg*%W;cxOsN;rg>Fa0@6jRqKK+aE z!)^HNf)U%B%Y{^-6b{#ow)&ntEB%o>wm!_p?HBoF)4J@UYEJ{7=`=PY*5+Gv@rL>D zC}}~dipdd-ZqN7dpn1e!a8HToowjh(sg7)$sJ+%e!-6N9AYXJvCAaJNY}z2_xi-2L zD2Ij(mos${#^2$xyQF_#W|iiIXCgpP+ip>2mU{~!_JqsBIn@^ev}{zJml{~Jv5kGE$ZeXM`R~I z`^(V0`yl_94#ID2IXx^I(CEap6uVd}$|a_Tey;P~ocPyDcOujz+a$-!6=jT9fuqc0 zxOBQjr{JpkBe$*9dJj-LrDME&ZP}Y7gXudf6hSmhzXcN9`(^pvcrw?u5dQT1h0Wr5 zhq-V9V_v42CET1B-6Q+Y!tX>~NBZ%L6Ar#b@Dj+D-a8)WOW+<+uc(2RVQph47XR3# zhW=d5fY@g&B5P|kmJ;BeS{ULc=~l(>pTdS7MmknqsBo-0TitI2ueC`za6rzdGQz*0 zt>U2#KVKvb`wmt(R=OeRb^iLMbYwV5>B5`m6wMwqt_9K|TJGIv=#xiu^#a+zAk2;w z(j!&jR5-ZAwMi0Uez=%(FR>C{&J;tUg8GwuHW|XDZ0~>KKCAG=kVKkq>d^u1`yTvU zB&3=g*tJB5tp`*98KJ=8u+wozU!x&d>SkHN;>4q&=pBc7%HM~^^qaj58^Rde%wB)xhpMXj(IcR3a_>=aW)bQ zetP13>B~BQIDnx_viTN2?xPmHe#AM-ZqbG$-W^n6mFKWmqHi}%Q6sm1g$-3+Zs+<2 zvgCU{+i?52} z3rsOphPO@W7<~4u?_l+MS(NxLVo4OLv6p%s9xbvrLi=gCu0}p$Q{O>BN$WGfHaHSM zfUHh1l5pDc+iin>=PG!n-=Wub(KOpH2Nk!Hz^7A01E&4QPtOSFU0B?H_l7l?9vc5^qFij{!38$ zymo2}Qq7$IMLt6(o6KqKnJCnYz2)?^14cC-fUfeHAPeG5*@@B@UNMJk(rB;0!ZQ?5hhC(DT?_(V5G0zDb^JJ!&{-JD`;d$zB$`=rTGy zwZB=q(9-3DlSLqYC7@wN8w9bG_FS{SmC( zT~TQMtiU1iBd2^6eS_NlY5lR6lAE*8U{oRzxKB>8!HG{KCN`~`Tlqy6`Qz^9D2g;J z@x&Pg+S2vAd?kS9DI~};TE$@uak_-V-qY8nx98zVx*a{rl<28jIw_^T zJhDD5s?#BU=8SdFdTNkOHp8`c=e=+dFK+QzWWZ9TbEAEW=26m%v`LEQF}VJ;7T?{Y z6o_5MJk(l!IWEa(>yHtLF>IdO{&_EbwAJ@Qg=6BAKGUJPfH1d^Evf-$)Gl~Hxbbm{ z9yx0i9Uqh@x#Qm7t|e`Y%UB@&*edzFy&|`sedShnfAs>=A9|Fceo75_&35`89}tsp}4M%m=1wsCfA}M+)JWcopE2!Lbh}` zXO;OR+CHmASMg1>eUGZ{QMTiH)^V}8lIljzC8<05t33}$@1=xOa_%~4lzSHa86CbQ zG>_Nsb)AE*K&6gngul`8vKv?7L#e*1m21WbkO{N{Zs1WHOc!1w zOr~JCCsWBsW(C+XG_GR#c*XQg1=G=I#EP+^r&GNK)FpdlI@AQMUfCQPbhYg*I$PtF zJ*`JqUnMAXz;G+*uh|tr829PQ%=p^!<}0^MyWgjqvaeZ`d*YEAW$WxjnlDs3^|Yan z(UpRXX1Su$WtMkg5ROc^liYms!J;L=vZp!?9=Sn~F?WDDP&rx8V8$ZBMX?o1CJ zEqZ^4>#BfBA{MjKQ@LXM@uuDhd(4|;vdlc;)yHCNH+%T!u%mB)E#@TCi*?r^0R?lr zt={5p5-#>;$=FJh?}0~geMyoh~Ic#wIO{UTq*5}l%&kc#_ z2!|<90^#`kYQ5$^NF4qAO~*;rm-bcXxRS&j@3CM?qERf@8XOz8#WjQyJQZG%rSFq- zJ3jma?0oM8@~64ZiqVzt6kAX7v8QVL=t(4E#I`r=WZ3rg$xeYkeyX+CV`>ozcYb>X z<6JyxiD7?W`e&BrwOjo;M+Ea+Uu+_#bDgI_BJzH^7<<*~os|A+Q8l_nRE;LXY*kXD zJaDd zRX`y4=Q|-W@p;p^A;7uO>4|~Qu#)SlN#jtZ$;$@SlNi?(!N@@WZ&O$`tBs|4E&rr`-$Br1mHV)&?_SmKGw^S9-Vv3@K$kxE8avlU`x!g)43=g7yXpVE zFk{IKIP2v?dYKU5jVM6}T$Td3`p_Nr-Z<~X04rK|MbfeA zDtIq|b^eR1PTDE;ZC3spLmqGpKfua=u^cSV^o`p5=a^VW#DdU?xMlwCz_-qKbRVGA zpnBXbzxw-aMWg2 zfI;+XsQ#!)O1%8bpk!kM24&&k9fwjj10mfAIis&_gA(E=M$Id})_H$gsEgJ*xPSS= zT^E-!EH4|OitRPYjh#>9Wb6l3k2j=cRbrF2M|j{;dU0@U?#Z-V-rH?~gyT|8P}h)c zkDy#(4a>{o?szJMP%?=Ad}_JGb7-87;P3L_5DDhKgufvRKirI!nn34FpvRPt#4VTo zw(-a3LdP}FA?~o}dNoO7_+et*nEzbK=$|A)OON@J+1vz$1@o>KN+Gty-wy0V!X7Q1 z-VuJ4Z8nB?a?g?-4K__0y~*7o=Y)9qItixDO;Gf`p%Ey#O&e8a4&uh4M5qp1Wk?NPWefQ|ig^_!KYD&FLQ`tf30=NE+uekF75J z?LEhr-lfTqoI(uSnj4<})_g6i$tSyY?_ZiF-hO9kYgy?k-$HRSp?0r&b8~8^1B%P8 z7JR)TyWlI?A1CODu#yo+Q<;xYk792spW5JOEz@g0FVa57j@$YZ z(mu#my0$W-3AtJlR}|ypSJOv-tky5>1?xr0hiqH+$wr-ee`NK~lK9_r~4dO#k4B&8)RP%#D?yy0l*w_Y75CqPJErGxhFu!WnNkY|orhT)hO2S3IY$ z&10MnZ=qqc)A007*}Nx%MFC>h%`*Z{6@?|s_1`c{8?#JHdf<%@nkl?Kur%e#Eqz5; z-)Us&X*}hEu;xSv{VjQPWN9QsszG2RNSNJ;IQYf67>BCWtX74r0h==D8*Y4gne*VLb zFw;OkoAJ>{qrG2NUp{32^{>#4ZZM)Pt+p(4f>@T2SB)J%KOzX5i=ir-pQ$H2GJHY z7P2ZVs(j?Q=cBBM?}k?EFiW!jcep3b&hwPlL`mmg8IK#|^}N1^w6Q-&OQkn2C5^&3 zQhzurX8d(w5?#0?c9^+yJc-ZYnPMROE8l|A=5rsqsX=v|>1#A3ilIw_u!pP`!=#FSz#`PU+p5I4hHLj1Zf-^b{Q)ln@s=t{UV+`vYrxen z<5Lblb;0?H<&S}zr++aI$l-k+b>!5;HDS$Zc{5@{TL|M_(%5j$U(wSv?65Z@Wkxj( z1Yc&?r>+|Qcg1f%&Zd|saTTgUkmpJ^(;h`|KWH#}w(kDO;oOIIfkz%GIr_ycxNxv=?43o=85IFHP5uYR zpjYKk-%sDSogfqtNdeFtt`?#KBnf$+^b(6~3+N5Z z--pURni=LCWvmtcZpqE2AK1LKn$i7*?^N7Bq!Q+;IGUC#EYf0;;eUjgKF%Pu#gMh# zLbs9U>oG>XcLTtukbFr*wx7X|%MCm6sVJ_6M4b2h`;V-7#Y%+?eRd)J*VY#O@Itxk@vJ;qTO>)g3IlgK4&)1+^ zd$Bf28lA4G{=VA6c(F8v`}B*z0oL&($e54V;pXLpj!>#3)&5|awxQpe z^u)h#=j`PZ4@>;AIo7grvE1|OuH7p-ITP3k0Jzef@8+p%EJ_9RA~C7#bJ@`_r`F#% z+PhZn9`~EB{NLVdb2p!x7FMDCk<>O~%rX7jj9y3*KANL>iOd-&$cj^t)2_*1GYBOs zn=38_buYnQDIJhfiJLAdiwBAa?i^jt|8G4 zr_A-74giltsnvrg1<@{x^Rk)ik>}n`u1tqgMc&XBkmVE&WoLv*r>r@#30sjeOPb!{ zomD@Nv(qnW3GcGec{rzToLG*a#@>`DhxHj5{q7gF1cM zKB+A~2`l*lKmbx#C^jTJBB#85NiQr&&nu3_2T8Nw3O@EZ1Kvzt6Ykov0F!6G^+&6n zrTZm_+J)UL;7A&UUkCC+&TKI5$+hAx7P5&0OT=^>L8ILUc1q$cEkU&xo5KWms+x|u zF4Cl3=_!AnC&Xeyj}`TnlZqKXq?)jHf)*OTlO$2fR)~eRLBX>Qp4?{MzV4aR?rvJQ zCW@ShLjYl8Bn=NSpcg)g>>bJqM2K)`+2Xm`&{8iOw342`=WVRFEoAD|gR@!%d7b(~ zqQNXSO)p@n`8yK?FO`?vbM!gm#rsqBORH(QDpzU3-v#FM>T~)4&$>4`HqPI|=@li7 zg`Q&ig}vTTX(IA^*VVfjPSciCTi0lpPb_Ql&Z6{76fqf0E#7{Mv5z~bc)GL^alrGCvJXKs~nSseY1>S>#KMaT-|bs5l!;V_V`l98=19Ze;! zsHN$-CkB!^ud{xROXZ@$kE>#`$xHsAr)|GL9-mDbpH+X`DYm26P}8uyMqht}o(Q!F zNj~KeW!G*OR`xPLukdwFADs!}Hm{mFqfc9V9r)Qds|ow1)?t5Sf<@Hux5!9gUkfgO z;Vg(u_Sv&X-Aq;0MbdA0ro8KaG3finVpk+6+e`$X^e+EV+PR;F3L#uFc&9LYkSneI zT#JA8l8e8d7Xd&ntR9=5#h{?3TshBnMQe$jNETd1<1v%Z3B>BOYBBa}@n#|sGTFb$ zW0Z>43Is;LshZ&Q=ZH;{Oar<%;TfZz71{nVv*G(qm)DvwF*)fjV>WtTNuOpD<~Mgd z!bfL=o&7{Q-jaJxI%{QRMLgS}b0A4Va@f3L37Pn_K9xn+%q?p1ShGe;*jV?=B^yx|D32Ief8XZ*O);%j?9s-nSCs=DQ+R9Xw; zIrP$UjH?8j^2je$J z1(x*%mK8&Rz}x(co_nS(k+4ShZ2ge}F{eK8eIzotY>duIZ>M^qhwRv%+TWwboc{8$ zzRtUP1RtO+gU5*kJ=*1d&GGF0$$DdsNtw(s1y^g{UTe9ax!*c6DqJY}~Q-M!#y0)RWc8X*Om&pUxslP^oB?WZz*mnRo!YJxAfD?C6=> zlEunemMCE^cMF1CQ^uqtlLIgsZq9&DYbwKsAMr> zp73$L(6X0H$0OQtb9cM$SfOjg;u#B{)mqy%>zb4BXDc6zBxil#6DDW@*-ko!qk(AZRWHKem%DG$CV-XH2xE)v`!pb!IG{%aEOn z-nhM`>@@!s*Cs6II4Jx~{%BW!`(=seygZ*Z2$|F~V?ao8#J2qIA-i1aFE-DrE%^jS zJZd;%liXXV#Fl0|>;29THsE=*!ac%q$52HRj~e-{6-_ie&PJ;tc!CPKF!D0-mJ0mC{SGo2o|=NDe5g2RnkoN` zr?G*M$zTD}YDLIc4*kQHDiKJHD>1d~N1P>{)?ikHI_63U;O%bCt6d>&JY~5~vSmP< z&4gOK?Pk198mBD-)TQur5YA-uv{}TYdtq5=s0hHfm(F-|xY^DR$D8P8+TFMQ!{p^^ z@o|CLi>CbTEkxPm5BxftL2yVWzJ8UCO%lBOFjXNe z2`iKNxzNcQ&;1=xhdZA8QVW;D4Py?#yK)wZLeIP%6=lU9Hao9MXHA>2>gj4>_DEiy zWuS|&{68)38_URZFwXVTdm^geTWK{$|Ba=2}j!ssE__i#&T@RW47UQpi z&jYt&t3TL|0e7ldgv-Tj-3HoDD*ZLbT76>hoMPs$pvJ96ou43_Drgk4u|PxsSY?x- zLRJVfONC?4iS`^t6GYNk3kkxhLT)pQ&46O|=< z*4|IE5$9$gUbQ}Do%QGM<*4IHPp*{%r4Wh(NpUPZXUuw8OR6OqRA?bd5IKb~XfY^p zLw{c;=!qcSK*vIV$MVuHEp}as=ZzK zge<{6<;{|+M-;q*|Fwl4wRUa&GH~hJmESf*;znN!SwloV6U2|;fsZ46`1hsQ+~0B* z-P1f|Wo2Ypnq@d{6v9#9SM9uXJb3+haL#DPL8maFj^m-yU%+kX5PPx_r0`G8OQiOT z0rUzvxz8YWyKwuO&f*qwD0X&XZVL@Fyd8*A8#C`8Ab|ThO1QuJdYRgep9nOyTd@{( zNqa;CecuE41_9FsETk%~fRrF%@qlkSEQtXsaPPF-)56eTA>-E6R#E_5uNBlCAYhq# z714Ph{cB=4f6) z#%n(B8V;*ZXKkw;CQq%T8yvR_`q12P#qKq!%kSu`n40A_yNcSUge}PtUm;8GOVdu? znIj6gf|Fs7l($6iw?$BBAn+WuxlPPiWMGElZ*lVMedO&>i67D?HKHWm{}!@ZyHrs# zDtq*8SheWohvx<40sr0ym6l%+^(NG61k@lQbYPK8%A0-GKO$CrJZZdkc^WWs{lS7u z*}(#c+aAdQtXs%?^2nHO(1Wri(gJ{0?i-v?Pz;24+GMMBLBv~L%jtUY5r@QRN^_?besMFXqm3j*E-;0C$h zo83U|KsNVOz7~r4MZP#a^5Rx?VP*oimrS-<*Nf!aRt{LHUV4pQJ}Cd1mkHXDQiEO2 zD%OVe@BvK$lN8*>im|zsME_afQqkZ43(wckN$4E8+TP%&O?oh3RmE0OX9l(8zf|Pp zX`3c|*eNXYv%-y&L_h)4L4d8~F)$p$C7wkDX2wX9YwI^}h)MQ(yygn|9J1<`7|0>~ zxgfETN7)+Fdv4zMEz4SRmq+&wV4aBRWAfG`!-$u17Ps`x#pDLN=dT()hvtp)zNIWD z{-k_Q_@=BX1e}pE%Zd3bK}|$iNTWXpMo1YTt^}29YbcrcU@-6%Ukh`Y;cW*zjk%iX zgbib^N;MNDuKnJG$7V`2I9K08HxSfPwiE+OUPkPx!d&ZQLkB+Cbr^AfV+#K~w z1WAs#z$F`xifUhN-nOhlfGF@9=u*}TjIgHZ5oER4;i31HV=p0RAg5H?mvjQPzF4KO zv)Hw5W;qso+C17-XPDu?F`0NlGMOBWtl>DzA!~&z8QtmaC=o@)s6)yc{C?BALv;!o z{47J|mnA^KS>$2bDNQ>vPX^(+A#yD7NS4O{6fKD|cuQj~sT13V%0f$e_PEg-T{N<| zZQTSCR4_^6Ng}V}Mw>0CV$-!BFgFwe^{o5rmW2^1kX9n#{3ZaP;Ewb-_&?fcy_8&N z7MVc&**!9mcqM4V%go(V?ZZM_ABS9#OGBIp7~b;2#A9V<3=A#3FkG!A z|4HDgZbR+D_HtT&SqH?L-4vMlv%auoWHr?5s+i=t;(y7jxGobkS=qmr#)6NX*X4{| zLJ7hyx$ju}Z7EB;H^km2j(;D*)Ie`ap8h6v;)g`HS0w2Y!_ot!kyzlara_I%tj0aL zL9Pe%I0sVRKP*X12kR0r%dGX1v3QZV&uu`{BF2FDD5O~?iLlItmM8LNYa$(98&YVy zE=#VE5t(!tb~ubd`K~JRE;w)Wwap5+&Lze_5Qs*}fdNp!W4U4E_Q}X}5@f^N+gDOo zCf;4MiBJT2Q3NUTlouIhm%vHfFKC4JNvKU&$O~OXunTi(LhN3E?L3Ps-t$*<#8=2X zDy!rEg%mL{pbeOIvDu=pUz669StW3vIYCcgL2C5K6JD0tLM$BoYwcy9U#-3GdBz7! zodK^4d3FNiq5_gTz8Px?ObK@-udWw;9@iI4QXHPInDWKTnw>R(w8x7;8V7ur>|`(D zS;i0n>hXjD7Q*a&jz@5SM&!^8GH}*dBNf2K$s)hS1`>BeXSUg-e2_4jTVh2T<*97_ zHQ5ae%r0}cuSuZJt8TD4@i4b1T~6Mw_KQ27>lIdJa}r%sN&T!V@E`?Lu_yLx-hymh zy5r0eqir#ni($DY;ewFd@SA?50Zl6VNJK$JQQZ7xKS(4G|+l37rd3L`fkr^&z?RZe#XMAtENGC6t zMaZ=m>F^A+d=?o8IeJ=|xpHSW?<8CldXGV)8!5C2`2T7P8V!LkRPEx_cTc!~86s6HWnab??jU zAC)XP)?NdgX>L<;@$7~g4P2piSYF8UWExGVIXP9+kQS^3vl{#DV`qQn2`AyVW*!_> z$Mn41I6=Y9ayd8(rwC%4p(1aSzR;G*inkn@Uam*hvT9(s1>BDnSOnb1bU0|=_SWQd zic12^y*WaV16B+)h0VMtsm=fbcQDBIM-?nK5z}lg)vs*?Zh)zV2}`T@K$3G5$iDIz z2n>E1R3M|)>S(Ge_m!fgQgozXzucHrWU$6C`rpwhCj&qoc25`99FxcVQ291JH06T> zOha;)_w&wm5tCDRA*{)YTJW{r8ZmSVWX?BvNt1WxA1G&oCt_m${QFS){()1KeUo-s zuDzc9mPc5wlg#FXy!98PiC906)~?84p)#Ipc4Z+j!ljshC`&Nr!r>p*Cq-8NKhgE_o38z_7fEilt{$jeXfGqH|9YjmkV&7m^KT5G>ZR@(E;D&I?3YZH0bDcQ5M2L6(GehYJe*|Iobyo;cK@;!km(jGi&wpOFv))!bf z7@@URXh@XA6;cCBI4l*5iHZeJStLlLLW&m68A4WaulZ0UD1QzVx+{CeJ^)#$6r}PO ze|E+*PvAd*6E4DXdPG0>nLxs~7?1DcMuyRf>}s=Pi_8zVb`mj7zT8-qW0AC{eCNFly{;JhBhK{Fc>?AF z=2$sd{u&EHFgf!pFXIpw;2FQz6Sr=kRZ(}%5$R0oh|i*|yW?G+zlT{)hO9nGaxoK% zIG)9#pUX-kK$A^|?sx$^#OcI--z&TQFME{l6UA?>N2bEk;a4I_H#e6GKhjDx{AJB^ zQyhs0DG+BF!chfcyc1r?xNJuv(OKs1#fIdxA_;^2vcy6T%ku*$VH#p#P9cCbWGto- zvHwsD@H*!dv)7E|_j^7VdEA-lUU^NLj~Sz{zgzYS|FR|RGd}lYLN%i`^)DCB9nB!S z@9;tCgrZegI9c~v(YoEbo9X;_-6Y#_-#-Kr zt{6%D6OU~$9E}J@brJ-)AW0C!rMpRxHt7UyK(8#KEqlfnu{aI;bnk)AO(zKn%3#f}r@F=EQ959hzVQc_k{X|Fj^=L}4m0I}hi zlCd(fTUnYKs$^|_@}@BRbxh658Au67u*~mtVpboA8mj2Ju1K_)U>oQP3%{31vpPxh zDE)0`#jyuFzuoyGW$T*i_=7K7E&*+!<6r~>5XauVlWg6~no!N$2BWxb3l_oLf}4K8 zxb|@_fUFH7lH$f?q$!0~1rOgEe2pQCQLc-^aJ#*QK%;{!qimSr5~^xy@BKq?p(e}@ zO4i{CvBj$doqr|S1i<`_8Y=fxJ~|^NCVjD<#dN?aa%1lqi&&K|V+_ZxOQAm(ec=4_ z*un){@F`0tMtn91{YO*$hcm&KK=D7u`Yv-v*=a7=fFMGz=VqvYnj0Vt<}iSKy6Y6i zvIfv8us~ph`;5=Vm^Nuke}V-Xy-3lbvjC?J%av^FG^0?)#PIJ=A5=Y-*#fk2q^%gVhe(kj52yz9b-8xKY?jt1Pf|Ao}A)WQM`1SG=5DeTd|X3p48 zT5?Y-5_9EDo&uymSelqxdRQ~w06VMevPxU(DmI?(JU&K1;x2`OQup8*u)< zvAlmW`h>-<_CdnCVrf%53AF-30lk=*1_%-&kwyCI{Ka%bx}XA#*Kek8u0+oHJ$QEQ zb;{Ons$&nv=SlOS55I&p*|#RFJ$SPD9R2Wl9VX8X+!$bE&S*_K9Vg*sP7Dy!8y>;_ zv}ODi!IE+N*H~I{hzSHY!0KslvQsp)-{UH>_Trg{H1m^9@%9nH+7>CN>dANJG--Eu zZvC*6V+m!78)BoNEhoEE1r{-9a1(|Duc8UeNmcO)-+J(!GXgDV0%yYMwH%o_NAIKA#|&(Q78q_KCeB*}}B zfvyR$)e?Of{YomA&sDrfj+=0sC@3lLn)nxJN7xxz3>IokdTK%=+%p>aGSq063XqN8 zlQ@dL^m`W$?TR6WA#+7DkM$DPT>rAE1+Eusk_XH=L?^6?sf)?cLj+N6(rG_??*5to z=&yve8O+EH1g_+B!8M*!%+M5be|R(o?nO3GR%5|bne5S?ELNoW2e5ky#?L$RLyj_EDK5s(PzH; zZ6oOQ9r$a33rv>#DfyWGqsxcic?s%K5nDH=;_33BgXoL~N8U4r+mZD4Xl#uKCrymA z?R0C&*#610-k#I)$m(clnC*Wq0c3w6zcERLpFpsU72Ygv9zm>yh5AI+t~T3|?#)!Hz6+5`eEkU**jfuF z%U5`R_BcRAJDNI9RHTpc(?=(^4C-c4tN3;8pC675S*iD9q{Eof#8=^<_4VbEi;a5O zFRv9-B+Uu>AAAg)KN95*9#W>M4nV`9g(7LIy2Xjv;!$75-+pQXoFnAEzAF&g`aJE5 zM1R4rO)0cZy+VXx!$xY|dDLdWn9f#9J0AahvplT>IyP zrLFe198jO)7I<-k1-!H*eFRzIL0DfDL{DUA>_S-!luC zAR`Nv?9O}h)Ut9SllW7Hd%$PQ#)yR2_P;PJCswVH$F8wIm%c!IxRJJ&jyhDVdbc&nX z9q+tGeR!|HFAhCU!n<>?*>?$U!d(s1v@0pkgmvar^jC^KwG!vFi$s*VvfJ=&!ht2P zf+wsRE&gZytSceISlw_Y@nL3ycLd)oZWa;o5&m;*g^|2nCg7o(MNA{M0*Xh7S%1yn ze~4}@Z#E#<^lqJ49;LDyI}l*S5n)!YZ#g|A`bNFs;63wYoBdJ`bXw|TFd{+N-b1D{ z>Hc`^LB%EoO~^t{?Qm*-;7Itmv{7MZ#A5v~;c_;f#tFv)!c7DwEa>urwb=vYNipCxcy`m&Y1K{UPv{Fr$%8($YLEJl{wMN=qw5Cl?XTrvXTX(im z=nZvN_m9|XEFwxK@RFAS3`6Le)fXEfi;-Q^nw{eA<*h&IRj5y?-GSZ#&t7CSLf(1QJ>&whu{g*a-js?%`I%>rx1v%YUkD^XV zTcVvFC{~%foz3UL6^$I^RprzMuqM_VJs#Fr713S(EH%bdd`#|2P3w;Y5N5VbA-hq` z@gq7Zd_06`L6`H>r3@_zybmP#74rhVD^%W6)LvLNSnO|ssljJetr-LhpzrCaWDgHcBb?nl?7a?oIVV_E# zs}pm$VWTUNaoXCsKR4fRuk%~K&)d4|>(i_4WmDgn(;}VYg*VCun7gilJy+bxwdsN0 zNj}KN*=zpK{b5y)ES=*Z*M@78tqFp+?3(4ye%r|qMl;5QwNd>sFjGHF^y@!uVKJ%AK(P8WHU>d|7)xm^vLFWKo!n`Yt!w4x9hC>^~!b&<7y zYpaC~EGgY-bq7Y79P2^KaY*c-l131~X0&sXC16l*0E40$DgB0qO}tMXE@-XeOccEA zhe}^#`J~tW?r)>V`C?`pEnJeZ%5Q5ZIu?PdR#{@f>;yVi@|W`I%n;~+OxX+ft61i3 zNt|;jrd7)I@Mx$l>V?qnuSU)satV-V)f^wSg;`xeqYXDzh}>q7OLA#|{Y+7ouU|cA z=)hS_o-?%1XzqPqOK#ihvyRzw9wXz7B<76Pc^jn3H+TZG7KKl8d@lvblgWY4jU6%p zjqM#P6{8~Xb%YeD1>6wg8cokQHQukzCM~Nzg2zUY#$Jr*23-XMZJ)JO0p-8e`vf_i znBMte&yj9a#wMTEL!8&oDUx0m%r<6gH`ew^BywK01>Vzgmk%^thb?(5>Y6hgW5tB@ zDR`|W1Hff|M)XoMb$w{IBN6pV%_OuQL3j4Fz)-8!;vCd%pWM*VKoH8;2x5k;t=z5Z zW}Pi}gC7{wB?6jog_z3i~BNFqE|yxgng zmK!O3-FO*KbE?MS)5JdbZO2$vr*fiboWQLE&RqSd+?1r2-6QmT5M~$VGPm@!UgJNiqg}7 zD@dF)=F#Go1AtOhxAV}=%Kqmc6kD-b`%nG-rfvTIS^ zZ!NzS9}Chg_%de9FXv~Q#z3`pxr_Ed_JdUNs@AUbaMSuQ)6}XZ%pHHzC}|J~$7!c{px*UEXZ`x#Y{=F8GbL)yuAwDErXi$)J{8E$l0t{#MJX{s^J|$n6RL@ZR=i zpPurk`0Yi182xZkqLA9JRIU-HRf}|#C5PN|ylkI9=ko;!1w-vmrc0pZL3tZ_LB+x( zAa$#We==P1uybKo&ShmIn5LnL|3(?w(?aQgcoBhOZXtD1)h5NU>j8U&yQX23f5th9 zEZ6QS{!w1(rPmRbd?(H+Y@!~qa>wnM5|V_ACi{h)j%~n9)|msGFJ*j+Vldw_ zZ+^*>=)7j+<1p-ujOef00u9HpzGxEA*AR+>4CUI*moxcWskzAC?nOy!VWYg0TSyh= zeck0XnR$|Ci~3ia)+z({v2MU{ckz=MU!bW3)AJdpSC7mD(r+N*of>{tQ^z~T7T79=^r zL*|!C`2=?w^0zj3uUmL5BKvzt_Vm~e_z4#n;@Z0SdYE9v=wk4MXfJr4M;(u!vMV2X zin{#thiX3UvMHys^@PbO-dxrI9GnQ{fPWAixFf3Ul{9R?T6cd$if%c0w7&i({-9K0 zBcq48*6rLWG0RUa??JJ^`lHQ-Hdv=sm}=D(Tv8!(rzznoyrf?}r^`?3n!T@2oHMV% zumoXi8z*Tdi+FJ`57Xh|76FOsV)f6aG|c9(qX>`<-O5lTfrMgNs_yB-E6ujC-}e`e zAPlXdAdNrll?U2MObJpIgD$>iWF&qSe70PcuuJsp5rFOx_wO7RSkzO=~c^dAZ4S`?Uud}g@Qik+jvzC?dm&%m^y^*M6OEO*E!|q zYVH2*nG_z2Qu#9T8ai|WS|J&_@|QKe3xMq_9FP8Jkk8D=*uh3$_C z)uuXTSc*S4yPAO7^r~Cg zoHpe4sxOS5eH`JbBR9v7T{z9FE7AzgW!e(&*@jG%6~Z>H?N`(x(6z1dQtGdEohfRetll~9tp}Am{ zWonEqK(&9Cdd+Lne604O^Ah=%Q$88>Al=h?#^MAKy(}Sa>95h0im7HL@|bRkK|tqqLcrqT-}4gX@6nE`PvZrn_mQzMye0Z^W;=?tl> z-84%x8O;>7XwMQmMnRwZXr;hqFbNhEG=7B@>>-)Id)CDir%Y8`4J5(8)tTU%t-X>LVa&5+dQx=U5n{6osQG5 z?^SnPw)a&G)X~sSlr(xGIKEljKMGSfhrxGRNMAMZZ%-~Zs>H&{p#AF^ELno{ZUN^n}z(QgOHzfu?3gZs5{ zpX-oD#nDKFuRDlz<@W0cBATLh@YjsEkI>J~6zgo^KI{eAv^=6jBQrD2J||^-Ma7KD z++uhiTI;EhTSltY0{H*It#s>48oiLZxJ8fS!buK-v{MY&2CVX=aBohDgzIZx74t-6 zQO<#y;ZuTVlTqHc0_sVK%c8w#Jmircp~$5lVZ&yE&m&$ISXHiX-PVUto?6gFem762 zA0ZyX0>Iwm z4%6WVb4PhoW_BjN!b}$RO7u{+1$b!=hfg0@OF;(+-j>~5lCQU;I5D1wTZp%^;<}38>oL?k_(B%O*gwdIB^zQEu~^-^BfcA<8fDNjc{jf%2mFOK)>psb#{J zb_2=#to9vrDXjp)y%goM*0$3ZB)63 zoQ}mMzeIZS1d9{moGfX+Wk6g537p?HJ(}7dc&@^jwcLTu-g-GQ64<-lH;l?uDp>XI?eA{E{ljL@Zc2n%4ms+_pBy1q~d z$5D-tP?6V*#1JT4Jzlg`^^$U)M3%Z7sz2lr=A%5YX#tZdne1`1u70R|NVk4eI&{vg zi8@|(^~mMl_BN9w{rk)ELPhlMhydHM0Jo^VZwj;*V{RJ7c(&556Ah?>3BPpn2&w3O zVQ@QEdYKtTGlvhX_Mq?-f7MH*IU+RwlvC*VE*35sTA|- zW8@I9sWE5Z=i1( zVdK`1cAJQ(V2GU{uuL={$*V^2-y&~-Wdyqq;>Uu(vEANbhvhcR8X{_fxYqtr=D+4P z@C-JOz9)}kqOv=>O@WgTE>Ca`^8YmLheYIi#GV4}_owNYtRQROC;2N?Fqp<)?Q17Bs&%PKgIT>YEnJ=p#Y5OQ2j6hLRG?wNa4uy=gOrifG zyy>@#50dCtJ%RXecMZ$p&VkQb^_Nn|?g7s+*qA-QLtJds&voa9Z$>Ps;|6uM-Eo`& zw$ez6cPyB>AS*K-=U(tq=*lNDp7K1SHU3T1Rke8Te$c@1N#uGY>1?Ce31LIYs#cd> zhEL#n?;$A-wQNfOD{bav-%|?=@cf40`D^Ekk=~tCEFZEz^Qm90S4NZb zt@!3Fixv1RnB=ER_XaVBX_c-DzP1k0R4||*>4Ca^94>IWP=t@iFKP(omK}!WeDu6K zB4RzVRgtx1JdOa_)mP-?l`(@^5FL(Ze^dZzKz6N|ky%r>Q=6F6F{ji7Iyc+$mfBYh|TEhnn^w|v{GUpGGZU{F!h(Gt}Wg! zcWKz$-aV{|TJ^>+#4ITmmyiyGH@snJRl_)XOZcsjiwEsf7cTVfwm8dR^v&w5Tdld~ zAV0vL=21Si^C1*8z#@VN^AW^dwbsL#6UghLe=;NkIZJ}S_;yR!Z>#gDpTT!hDP(7A zRWG&b$s_LfuL|Wa#`M@H7_T`Y?u6?aka$riOO8+P2>D=e)URKDyV-f7Yk-&@4;Bxb*TVaBTJC@li+zxLyoGE+PthA@wWRDUth(hqzc<<`*tl$I)|; zPjn-Z=(c9F5$y1%vAs!=zJX9;(3LGD?>)I;wB2^nAPbTBaF$`+5ww%4qZ=UEf*rUK zmJn+rW*BG~Pw$Da4Po@b8fs7}QCJ&0Ug#&dx?vq*mo}EeOB0lIVQN1S&vUQZjMh#7 zhQk)mw`Oj`EzHeHQ_Ra&~fJQA_<3xkfuFMX{gUZjDv?O^p4~Dm1)N@pC19V0~gt!+7^@o`j9B!Gh7aW zthe7)6UzlcQ6P9yfcOmK(j}1BP;BrGlQ!c{)wXpbG4eJGY?(O3kt8BW?cAG9 zAkx(74+G$B3{Pp@e4-=q{?{QPg6iuTdPolFrvT+~}5{8zFCt=}0b;$YkT36*y-w@PFfc~4C_ z%+9UEkRyamUwo1yXTYH#xi8(F2C`=Hh@$Q{gd7CARzy(`X&tCLO>_*d^8L%hy7k{^ zI;J9Mbx%PsRcSK2D!{7}M)@l3oSory;CEEdTd;Z>}MrP}z zX6y3HUg!|Waohu*yecDhf-hD zSa2!$wPgiPb$Zy@rIO}4widB#BPVqr?4LmF9TBOolDy>JaN~+v-lqAZ%0Uqj=janr z%aUf|i1;y=Ew5DZ1IaX7m(!>A{ATLXdm$~YH{4333a~t) z%V-Am&~YZ?Ri=J?<_29|UGC$Y79LlFHp1vMjKBKaFt+?fmAY#q+}9t8uX+9}9;}c^ zOFoL&Go<>0Z^vC$CKmLo*d@BRbo6li0%lnLvmR+B8zPDyTe@upVmpZf^Dkly;R#WO z&wE!bp0wO;vg#w<8G!2T&K~?MXWRbfUY_i7Xr4I zzx+smsxywrV78EMlx(s!2rP-7(QAdm(lWy%FJcFpTVLOj9c*P{bFh2Pd#v+ty8jis zyr%U}t)H(;D0qebwcJx!+$1=xbz!aotrq6SOBNJ@<_K?KBxJCyED_w+7HQN zE*#D>+T!0JMxbs3W@cN-#Dyh4WA-K+gFr(aDrgKPlM6h`)V2nw? z+1y79?^*CZ^I7|~jjuG@#iUP}2z~})&G0$fchRsrEvfDE<$s>)pPmGIGGNi(^W@uF z-<_FL`u+$Nb$uqzQXKI$qWyPw{3ecAI-OnvCSM)f>BDi`nb<|M2spm)TyR>_`04e3V^&L@*(4QyfFc(v%aFI)rdH~j6N)3sN!Z0GwgJOUlrAgQLH&ajtT`?8uRIj~^YWD5^sm+nhzE{#BRXGWTPg zS0{%=p+o{XVGdcmm*v^Av4AA(yka6!Xrb_>(287lwohJEDkBpN_UpEeg{kVXd&OOz z7??L{kzm!9e0+B0;Ct$kACCgAFY01R4RR7{3slCy6Ais3#Ic`ZDmY?BIko?7)rJL?Y(Ai4f>FwJ=jzxwlJ$&%vfvWn|JJ9yM$@Q4JZWJ*2y zZGA?*__dhL;UgQoi(o>J?3yQ+AWLpqmxd;}0_QGJzPv}M?xYMY8ChFoW!t`t`R4j> zW_D#Nwj`)XKhgZQq%X(~!e(5b)qBd|8gA_lD(Kp!WbHh_B0WmPhM>6hiK^${&xA4V z+Cp|EgH3jt*(E`=CpDnBD=PaPZs*p5$iF^m+reh+m2ak_j=$AjE(DvYZD!61HyW}N+Zx`z>q>v~B+dS!yB+I#)aQ%j9{w_mf+UVC(xf$@@58Xj5C*TKvP z;#ruKau=-;Ue+f%@2^j;9Vg4-QL~YUMQZD?B6Ydpu^0m>^4TxEL+cBErYVvUSDiZo zQWn!icHtV^&Q=5Nrn7}l;`%DW1tz;zNxENcrwj?q&R<)I*B-1U?`PZi4nnhpnXsG~ zN8hzESW-p6AnAs|q@nn(EJGCjhLPID#JisMzwPPjazR#?`+0%(nK{XeO+t(|b|;v; z^vj577u^HGdi;v`_YQ6FgY7inQL6_#l>Az3|A&U>zxQ;+PRS)+f(Zf$vSJOFAYx`< zSx=T#6qT^zKkFQFe%nL-)sr}{veD2!CwdyLuZKl7EMy?Y9m_?DeFy|o(i?Bv)kU}T1ks$YKm%6u`t(aTKx zfrZf`dV7h6aiKjgvXrU>^BzKKEhQalq|!$?4zrulMjm!N`)8w$$0tfu2p$xsYo{dn zeZ8|KB~IK;jU|ZeJd(P@1Y1565q4nPwQEFg#XKNuN98{e9BvZg>9t>~9!9Dm6#Ha( z9}aHzl$eJBN9T_p6t_}WA-*FXF%!-*6JoxZ^wDD@HOBeOnPw3AmrE;goyY0iK&AD} zg-k~DmnybH{6+B;E-Ru0U3|kxec#Q(o7Zkm&=?0caWIXx3)1s^7z48L?N=f=_8LY> zZ6VMxvsPwlW({S3gW~kF zi&EnLZo!utGQHDQw=6P?$D}xW&Bt4biqSQL%q>n2KaJYmfiVCuaS!nN9FIB0#6ieaR4d1FaQ-1tcv@e6EWZNxoO;e?7q&+^E#U7VCW6tYo6J3-KG;m0O zsAfMh=PiXX6HH<9eY|Ehqfpnf_*c#m zCF9C_DonW;rD(Iy#9I&n&ws@O9Z3#vf~8pLF`c$y&)ajX&^W+%P^<0Q9+45`iqcR{7n)?8aCiqc%f{2tosa3-ah{ zgA?ZoY=;}kJ)fe?&fX2JC_OfMiYVs2m*{q`%x7trxT&0+oVYRjBE5j?Wjr-&kd=4O zjr_^S0Hj^9^Tq9l2#d2`#*2#e^`tWWd4nhgg8YV-5%=@5b(!@aL7T~Vy~_V2$^Q0l zy;v;x=J}KDh3Aw-tqoNSeJrdeVIZFm@l|4u_w1fCd)O}<*F(^_RugM$8m9@5-Aqb* z*PS>A0nhl$xM>{zaCYQ@0ePzf^FcrD?kN*mRQ{`P&o`d+WpD*v#ZA5><6 zAxIW+4b`dZx!q#kH}Wd?!7)<3{i}qdGT0%mbMT3A(|B=Hvho=5sqOXL*F?8qD5R}V zTsd!Y@#}=n7B+U$?QC+`Wb7+_WPPu0DiobSB%i;PdPs18X%~i)%?G*$GsKO5XW3yg zxf)>jbugSTu&J*ncMX7?womLl>`|LQ##6OP#U?9@J(>{#(c89^I)#2J&4eA^1q)qe z8*&#jso36#+W9k!=4F6Oz`0RM;>1edu>vOv?Or`CL)ip3BxQ*HiC}C03tl0U7PYHA z7D}OGDr(j39%(DLo8kV^L*@Ffgq(rIk6)Ep9d{)FU5CKD-Fe-l#o%6?ivB$neRb~) z#BpaW@Ls=zJ9Bk1Oi6Q)^ls8!w|IxM_f(|hkOg=!1+k%SL0S*jxFxt2FVbfGT!W4I zIsfoZds{2TCa^f|pbAJ#X9>!DI4 zZgwP8Wzr@cQ!l0?J|ij?A^UuABeS&}I#c-JjcLKj#90kJth?(Ix363fggVe9yr1TS z*A~Xb(yArb`JDwV$yn!eiCMeE1H4mWun|Nziq0*A?hv|u8S=3+v;BFRE`FpttcwwY z5w^6qiR}bidl8DT$F9uM>4ZZ0OPh>~6{SZ)4qq&dWgJq52XsrQkB6YP$h+mH;j?G_ z~qjv^+mx9|8t6W^;QQ%km#9&^tQ zXVy3eG(`=jY3u^SV3^L*V-LMa*C#9aZ;6vlqM!GilK4P+q{V57lPi$yruw&IC!&dw zrHJRkY*)6AX&$&T!4cH~gcZ7j@k_e0L1xl4E@zk0`l3bW_lS4n?c%N+?k%kxeRY@$ z8fj3CX%KPoz-)}s=0KM^&ou6udGp(WlL^^w2Gt%rinnjvw9zMX!@pC*-h|u=KrED- zgOlA7fJj^)mzq80IJTz6-B85KqLOKi8iF?fMx{vM#r8d!gDa+GZS%6-<74VH#G>0^?%LN1kBceXKg!v$gk5Zq%Y~aRbAi5yq_| z9wlxgItUeE-Ta^N4AH}ZWc6Bp2)~2$1O>YZR?HuVyx&gKNMCzWFgF0k<7T{&`dkB zGu=}-&?D8jc%6E|(q8a)P{jRrl`U$Abz`c+rajLqINWx~a3wUw=DZNysTC))m-8gB zGX!$<;D(`Yi8eb25#keS>Htu#J>{w4(^5pV1FQ&`DgsDLG_N$J9}&F3{<}r zKhr#OCDRu0N@K9iUFY}Y?!2B~YkBMXd8wm#?X{#srAWb|-kq=nNs+}ZrOFeX8VNMj zJ{AnJhyl5Hm#6?^8dM)+q*C5bL!=P6NcfmO?6e6=3t)OS@RI!EoFL$cqOcB>Sp;7rQ4Pg9~DBDFFGO8|0iT zT5-H&hA=~y)YHX=RO;vpg2@d>L|M4?ux)~t^agy1&SWyoyISkvXHXF>>8Ncktk(*} znzYGJkobSZ^WsjiV5{o8ny_?EGIg^u_lD1!?F6Y1zT}I+(j$2<*SvhjKDq6qb@j^_ zrrw~TLYuEWY4(gmg(W4^Hj~XLTa-(@n&v#i4oQCMnAwx46a(`+_taX%+>(g+Rx+G+ zPFSn9#!k~=RB%j_B|iF;%kP2q`6Ualr`KU3iuXGrBz>>Wf}ipmIK3uTZTnRV9gt<$ zliz;WyRGD(@*3&rsmeCL%>r^KlDDM)YZf8E4)fWv)nAMHL?=)x2d{Hy)nt-w%zU{c z173SI*r-}oe#m^qHJ~*1NFRcsT(eJ%5>2tIpDWwSyKZFMAA zJkWYzDgmYrY;lG}VKkU7O=Y!?xOh6`ZItc3_eEO}TSBg$L=_9lo3_N za5LpAiK3M6TvCEY`$SRc`}Izsv}K zr>b=p+7FCA91)Hx_tAxXqXWEl1{9)Taez?=8(*f$yZ)OT?Xfv|we4v)vRvBSJA#zh zbRRW0vLN3)vwGeW1O1uLkFcX5qesKvM>QKd|4D@z&BmkEzM$l&>8z_duI2v0IXlB> zChFH_wY(>%b{xcT%H(CWs?(}EcgSi>>iHg!O=tH%2%au`9^~h`(a%UC`W|jKh)|bI zPqD;Oy}F%}I)SvG-Rtr^W6<@uD*ppwa0a7kCpX?fbi16|vn!6lzC}=1wU`Nd!U4l< zf~isgv>KyDW))M+)!*ro>us>$P!cxi&|u8ONnD_r4q=!ew2W(no8r6Nq;KvSG?n<% zE|adMzVAkmJP?FgZ~;dz46s;1go|kBNgsovgrWn)=snFh4=g-lI8wO&hA_$ZgcId@{ZD7N za&}y(B1Y-^xEP7WQ8JTwZDjy_-wjr<5yU;+%dLEOIkgzkR*GD3SnKXh3O`V|Ve zhL}Nz%|C76y!ILYIcv z+n|~L@!ait2oARZI*759Pv~iH9hmT(iPkRaUGy>#GqYibWXKjvSn~V*(b;dxN}}Aa zDBimM6y_P;=_=0V3s!QZ(g!MUNcxw%UGGyUp2LW=*(WGTwq^_)UY@BeJz~@hmC6|3 z31+w6eqdEK@o;iS(0dJe$;ame)s;HT>XpPq(VELk8zV|i$egPycuSbgbJg7RU8G5{ za>7*(=_d-8%BgHIjO)9kO=@r$b!4T&VxJ-XqQG(+4jKqoG+1EjXsR3x%-0H)4OB~w zE~Ojth!3p_Wq0*qsw-GfveLy%tL1`I-^`Diu7arjTnli%v@n7VlVF0ouvAh*%JB0d$F4qH?0s!;E zf?UkBgZLnE#ciHze?x*0_=TQ~INl=V+8-8?>q9@taUugD0&_?tj}JH(y*B?CV$hBQ z{5u_9-N7{ulyZ->U11*K<1yHGB3dd5Xh9e{CQyzf8XdXe@gm6z13qiQr(?7WAcQVO7dxs&PHuW3MM1uj7vO@Z zzSO(8Rf$>Pym@OQTqQ{31U0`qO{G79#uiIaeVQ-6J53iG24czL;&(aNyzm1XLf<~w zY`KU#%6*z&vW;l}mH2irIWR>R|2OR?TFCkDto_Lgk5;r{s38MKMCOWI`DAkSbA#Fz zr(|J#);hR9GWpr-EM0aNgRhakO(6p8G zFg}nfXwSLW;MHE$$AX3Vq_8)aTEK&*rxWRRh6t+DQfK67H7~EP5MKAtUlC10{G-(` zCiGs6L;wAM{zVM{#rk5xFg{%XucdX96m%Y&j9MhXyV8In=rK9Pt1GxFVo2JEfoQo& z*gaV_KY*gJp66G4QrCR#h{G)pvQ(V29Nt(p|12d83l+F_ePCzb-h;IKW;M59HcFG; zb)EIA?N1Y`1`A4t9$V6UVvCPn*Y^GDwl@8p7nQ7P18pO=DXmwwTd-2nxFtRDSK|%yxw10m&4i=gF> zeDEOL*^@S~EFTYA2=xAEcU|mHq?4MDt1?>5s56M~2;{wK#N8Yp5ZBUd%+t-PCUBEc zLBe`%*J}G#7aORtUkwP#hEURS627ZUmW8M7? zkJW}Q!1q3RYQs|TqkIp)D=uMtwQ?hiP9RNSa~(H>@X-M9*zE?ZZ;<_Zm!P%j5&`7}ZnF?v1z-zc z=l`<7SyfK7xPvr`HW%p*T~L6G3DNO@LUTL2bg#e}Y;%K@V^P<*TyKMS7wsP%ub-64U`#N> zZV7Md667T-u7lA8#iRUV!^ka{ZJY^fi-7w8lHy=*hzMlv4Fz6@>E;gd*eZGk=fFA+ zIRUh0RQQPHpU+vPi@pJZ8Zt6?*H(WX<@9IN0M!Kv?uP)!c7@4^lx@UlY{)5#G>=Kb zZEol*KcLV44JB^yYqtXS5k3r$sf^8n2{JNOYf;|(6F3_q4Uo!wM1zN}zr^{g{qFl` zSPlF|zNFHxIKL3p^EkF6ai5SvJ_H1mk9y!0m(W$L#sCHE$C?)Zcc@p47d&{67H-$W z>@Nmpy@%p)!~MN5Lo2g8=k<14|y?j2&h9ii9J<2;j;8JqV0u(SJh}u$TMFfM*Rf+l8LX z^}j(Yo5C5>IsL&e=`Dauu~ET8Ct>s+;8XC?vvJhw>n`3U#+{i6Ied;9i+b;XLJ=K* z!!TaVFcyW!tJ}Q%tnhlH0s;55C>lQc@ZHXK`l>7MVMo>9Vbng^WW-FMZH&vY45+^= zb+-QVmb8Je_Nq73$`mmTA&d-GO^0LqV8L@zA@4G%-s_>;SG zyqTOtJ)~qio$}A%2|O>1m zaA--+Hg@l7yhlS@U)UC$6-ka$^%R7;NNVRp7mJ;_!Hx)#B8?$D2l&yCr+QT_WGdP z%}T&$FKX;`+m>#`Gn1D^9z{t^}O@!So)zHhY= zC2mpdl6>Q+A4+bC$J`zLPoQC=EurWoZk4nEmW zT2Zl8sgxkyI-()lTJC%8z|XGF2NpM!COS?1_dhUk5-e#j^1dMECb|h_f5s7IC2dh7 znVwFGm6_FdDH(s9LH}U%@VJrValQqN`#R@$!?DDPjnXCGxFS?V+-H?f`Cc6VniCO1 z6e~Hdz_fR_T`M|)JO!i>QZ=d(PB#^W`PWdz^?iWAy+5KS{(#aqe?`l+T4nFBWt$i2 zyy5n06=|F{`LtItr$gKMTQ3#|w78+Y8T&`Qp= zFK3b7-AhwUB-yU0+gmY3tgA;)fzA)}oXx>1UIvrD1|FE|rx{2pWYl;H;fU}K+f4?_ z3o+QZpkTJ!Dbax6DNgJdvqyAop?%N`Aau1K_&mCGkIuG&r+DhLky@8VNX?Gx&3aHG zLZB;41(VO#U+G7XBZ_e4)^V$J`7c()>V8wVGQw$WrYyr_R4(-H;pKFwFK~ZG&%hsD z&EU!)kpP2*g-M|2k3aFi1|muVsrlT#2C)!A7q5Rco4TQ!TAvAIK4LzDD@OF| z*P=*eW6IO{kSl{4w0c@cfi=wwQRPw3L!<*1 z8ab>;vdR7fH2~}YD`+X0lqMs0EgH=j4ouN ztF}{X{@>SfAn2_=uZLjM17;C$M}MjRORMKX>*i;xdE<)c3TS@!3t&I^LC;NiFD15=)68(2)|C`&jK~ zX4hx4zYVu__WdRv@y@^bWJw>s*&UE8pUl$HfQQtlEy+%4ZhaXM}`e1|xpM)w12l1<&ei4D} z88_0eOL@Ns4dPVB=HQ_Wzd!arq+k3^?F>+M`70~o!066ws=CvXnNF?@s7u~UPqZTP z%(PZ5c(jdj4BLe=4NR5|9-U>B>s6kNz)dhNsPm?U!mX>n+YZ{7CIxv~f8l+0&AyAy@@N)mE1jo~QGx-I70Vz+F~5k0Wj(;=eFKOFXl3 zZ5>;qozNWu)fJbJ!$e(c8Qq^L`q`|k#C9wQNrPq19lmA;`rn^08IsMnzm8lt1raiP zgR5bli%6i3Hgp%Uf5u^j&T9`eYRDS^6OH}4jC=A3)hiMBFx1x@Dh@=8f!q->PMT@m zX*-4_I|bI2G|xv-Zo2>Czv5fL@_e`(;Mo;U9q-ds5((L>|Z0UuU$~*abs+ z3*+OFCyIf9A*c0=0lPEpXVuo0%_%B@WU%tuTau0{Qg$Gnq>o%Tj7~Q z7phkDajjcm8rxS~?;XX68&(gGNE_KIvVg!#hXM9>7a5Kv$BV(-yhEK~JLhrw7J;!s ze`>E?yP{&=Bm}yt?z#F?nr23qQSGzZFx0~hCzpdi#`1V1YEI9c&(lxJoJ=Z??^9UL zx=h_i@BV(^XHTS_+b|*Q_p+Y5x5*67nAw&|z%rRwiXqbMlOMSlo$NzzCwz*up-mmxT z{CYm8kUW0L9VaA{CO7bVXMA@I)VE9C0bXFS_VZ0%KKruW#MWgQz0{Ew?1xrqQUpvm>Wkjb2K;NqIY>6I&tUBE5_~3 zhK7mHoqf&6?CjTcezDH4-KcuY^XQ&BsmCH&>yNv280A=gS15X|D_$;qwt1%HQMSL? zLxllls0M@=aPt~7PI39zJ>mCzZ?!KPu`b#o3aC)1XJA>I)E)#6}RuSJ?L=5HKPxM~v~VD|h* zSoo&%fnam26A?FYBW@#r1DqyJ?CAE`NGxpyY!`4+p_fMXM3&tqsSCh-xnAtRqS(UG^dA9cUK2@D1qt@kjCN5>e06?1 z>4$+&W=tC?5rH^71RYSJ=dQV5F{k80W6qI0(RGf50I=9LdNEQRPgTxu)@B${uPomB z2}uGZ-IiK=V#BoLi|gF|YNAyq*Ydi<_FoY>C|vfw_Z@xrnp$5N>d4+r@P`H^rU!Nv zUH2oj{i#ML{aP^wPZVn>J41S_a$~kJD#NMJ>V1i1MZxJ<+kD699pP&mR~g=~JJq;f z_R%&UU7(gjf}-l9f;Ce&bf+AlL}2-(=)l^dua)sk$lU_21WZgpybaUT0m!*QvgmcR zWZ4ZQs21wDc-3FEAm_A9m}&w~9j@XPnp|C&+=9-J&#QEfD8U4vIJvKOJ1qA{1N#}kOkbQC*2&$jacD$fd{!BS*ZBJmEq~i!R`}}4l8!zi2 zU^Bfw|HwA~quv`#%)GPS);f~p4HM@LJFmHuY@!ckJ^;!9(KWGl)$!#p+k8{fYS|U* z98j{)R&WmsOV`qy9k{^Rb>X;<{%)tbhu3RKafwkm%7-$O34W>%>oudbYhr`8mRtZs z4x_!ctsXbR3w%V795&Pxn085#e?5^rBHbJ+4df`%GG33au9I8)_uB2=29r;fKmqS5 znbVboj4l+NN*(^TMY;{N}_msUrA%~I8y-R^}#7Bcff z&oD0@)|!(3A-6i}(vGVxs?Tp^8#Kgsysz9OYy8<5nbG`vc_bB~*BEoZwMldYxss4q zk<|eQHA^oI{$0M|$vz=ZJ2hzGMARqn*Yrl7Pc8T?>_kuL4*bca7WN#3e|*>dqtV`| zE!p1tWT9{70$mk>bGc}6&_O3cY5MrR>X^0-fL@@NrCJ9KIFrB`P%E~<6RTIdTFoBG z3uOJ{`24>$$8yDYt&1M$36x6wM3lUAYOf*FPxRQ%4}OZ8^~|c!zx7g~kVlmUNIK z60tc=z+V^h`7B&WnLR#)FWa8+aWE80J@)16zW~Fi)PbjMZX*}7I_X;JRWCOmzO#8+ z??3CP!{*N-tlCL!QZZ)R+a-4ba7L86d%RM%tGt8Jo{z?*-eQhb?A_;mk1d!!i=*Q!mw6SEMg@ zP0YJfr>Jee7GUU*1XnMDg(BA%40}` z7|{I0>TT<$00#~jUZT2V2M;u>OY)2_ZNDgceoM|7ryFW%b*?!K9b!#k^i;PHGdMCMsH1iiduq z_qWC?3Dm9k9kj|iW+r)XI&1wab2-sRqE1%3Wj{XQ(RVa*&ZHj}S6t;oGC$AUcfIrz z)NN*7LF?U9%|u5=X0+-JUDNCNjmo<)b-qNF=l+<^ZmX@i7msW{rTXo7<&I-!KUDJ} z=ljCq!u^|)?$E@fWN8XfPS7hPWu_ogJOMfjW|ojY)Wio!dg8-IJJwH`v~8u3-yDE`>#yhUq|bV(4>Z2mWDU%82&LEG>5nT#gaU`u zzZt=(v9g!gTV?fd^LDrKwWcYq(>(|(Q4H3=wbSY%F|NDU3-9m-yP;CPE}?EG1Q*^c+M8y$_rayJ|5GhaQ* zGYJ*l_EE=o?x6kFb2&~I^1{~;Htcu^qrH&qi=RBy&i{Lt`-dCKlE%seBWUG#h*(LZ z__f!VtuP!v=}v%&?(-g5R`9wi-C^ymrZ4S^e#l_*?wiJMf*ayBEY~vM$0oi%@OUk_ zCb=pE6X|Q$f=;VOv%nW;I6z;*mczm?G9j*er=mU>GdBP{iN9%}6oK~mhypQE?D^i{ zvWK&=Tg4g_o@k{{pB*oYDW?PH@eX%@tjN*=Z&2F!!nC7qb)2;#@Iq}GiQi~b{lY5F z5-@>0j+>_WACZc238N;5-Q(=jqfFP!c02!CaTTiz;uC);GyjI+=1;oi56oJ+y>A~Z z{;OhMG`@6CoDNKYv^Lz%4UPA@bV^i9xC1&i3LJc*jc)cjo?Fn278e~;Hu3-r5J|%e z1fxWcO{{h~$bta^&RU;nQOqFr_*EHYUS&x@MoL z$p@hKeiP?AeRhNjq=k_4+o=~5x}&v&A+yyfY?D&ro4C;{2x9~wQ>ZeXdSs0v+D5eJ*^TP+X!Nw_JU z{MlQc@kz>LB7W?E_ZWPZs-=oAfyBQiVO*>qp5~rK<_8tomurHj@bSM`5!z4f!4vddw6Mos3;m=TQ_SGq>@tb%cyB0Bg! zSL(`kazdl^<@^gffhqUL0fBCI)cO&oaS1R{>zL;i?K>UaHq!U0v9jvvU#1qd?Xj0f za%n7B{VV;JvifH)~f+v_|5?AoL;7EVFa_JG}ic zkm+ZIN1G*9#Pn_q*{G~2wrS{X?TtcZ{R?s2JV}|;dbcx=kmGCk;%#oD2c<&W%6LaZP?-J7qKzNR13IZS92qX$OTLT+n zdyN-VG%Fl-G>hUTKL?F`(!Et5(^mdIBm2B~=*?-b>}}A!cDUDSe@wDb#FlXP*wurC zjoQMSdu=MsVi+G%d$j$wlVk|fWvBYmYknR8WRv-%>2G6q7>8gD?js-nlnMYc$%Vd(a@0DViUil%5YWs2~NfOiUv1J63JXKX! zBEOu|R8-=(#UD1kB0r+7|IZDf!#j?pA3FS>F&&06gQlv!gBWc&x9fIHl33#eH0v6L ziq(G#M3>Dnzm-2Ba23o~iEhxjlC%?klsKAKxeABxFpa0r&Rdx|&0i20uFl+Zs<&y| z4fio8)sctpPV-*c^@^E$sUz}v5r8$G6t&6doOAVE@HPI*ulrY0@>c(GadXkFMCA>d z`wc>6a`48{(}xCT zBT9l9CY<6k8TQYJf91MI`?Auz&{OriYC!3KNy-|4++m5CMD=MtFYs5DDBn6v7Kh}n|jW`KBNC~$p27wKE`%=Q| zHDVsCWj6pMuaUdK=FelXYo_1Cm;-TeX3dA%ozP^IQQ#waBs4Hd39Iy8ckK9TtG2kf z{5do3p`E(=X6K$&o*V;q3-u|gN~O#g?kBp8F1~)y*B8($*GyHkM_dU8M0w%FWm3?A zz@D(Y5`h61^Ws+Mq}jZPno+SiJM;&%;+7GpO3>B_Gh%FwBPp(SY1dlEC}wi>_Q+gD z)&^bXovik#Em<8|Z)zP&o^72)Xh2YEmuB>C=x?XG+;9)TIJ3YKofo&<^CY$HNh)<7 zMG(n`oU^QvM?BuhZ${>##N|7^(Vem*F&#GX#JA$1WudYoQ5bflmF)XkBV@6PG+b&NZa{{ui2^m0stll0cTwkSs?oy`L&b!f@ z4JHBGL*ZBoN%;&Ro%GO2p1udbhhhRnv4)WQ2)v_(CS+Ky&CwVH`GMU^3H?2LmT&FxP-I+78l5_!Cq+Xj_1WznB5N zLcH{R0)AZpT#1RJ(;E8BswzJbJ*gX8U+X8@Owxt*R&R~pKC$znSjQkw%7Y_D&9CelSc zt%jibx7?rU!82!G3l**E`fF|)x7q9`^-bH)gIHPM)QCr=LOwQ%FKusNopc7RN%=xw zHKULvOy~yZj3Aqf-s8i;+dz{S+O#fOH|t>iK)>#T<6dI#t5a)d4x4SMIkPEF_j;W~ z6e?Z9R}pLPCN&YVzFkf)IieWZWIEG+wE@Op$_- z%^wDitFL1vk4pV#^JwUZ*23IPNs*FA&6uIRd5_C+n8q(xA2LAq6uoBj$pzBlO-lVN zn)Py;_2*EvfBoq&&+=6h5ZOnkk5N@HF5<77q7@A$&?rZqTIN~e+`g;Be`oUA-2EGf z$qCtbY(jV04v6&BP+WKSa8A zWRCLe^?C-t{~jrF$BQ1zT!WT_5s(*G5~^C9d&64_QB1NkvgbK?B|eJ9&tym)uiW-8 zv`UX1+LsRlF_{y&Oef83iA_2ZyQXXMM7Qd^6&`_hKxhuSJeaX-vE|?Kx>>BUaPqWf zdpEyi9*e2v5iH(QFp;udF^jk66VmcWGv10=y*=!EKs1INRWTogCO#I)PD!Y;Ad{@` z482wfYG_~AbahO+bM<09ZKM?f~9 zABeb`W4&@=byN@_AzrG|L0Ie5kA_Q7(|kgH{1dZqy>4_g_Bv+ho1}TMfq^I` z&Q&U_SR1&1LJFy^#b)D)GfZT5T2%I4Z9(XFEkj;uq3N{UtC#NniHnpWg3)=j@hP_Kq@BL~809mMJxqPGYDNm_QpT*hO&D(XTvwU4 z-fobmoPFJ-qZTy}o{NZDD`#c;r#oeErGOyL-+NocyL)f)KkEQ6xSZUYtzif(E^+0O za~AXE5s|okKGJAlhP?X2ygMu?Nt?O%-yi2>%$@F#^AvTX8%vV-%X-zChE?4;Q}^ht zAAM1Y!U++(|uV)MN0oDM!-*mnp z(7;ZWV@bqr%4<$mObU(Htu^wFSF({KksoM0w>Q#LJTIjNm&!OUhG0E zgMSc0RX4c?{dq88Sgbvd`asQvUWy*PG^p2Ymw&BT33`5D{S$YaTL5$*qDf!dcqprE zgJz)VOgE*b1lfFGXD^{8-9d3wd>!8%}B2i%C?Ue7ZYd^DCnvpqP6%|Y++_BLN6qZz)wxPf2 zbgDbBb6Dws!2nDR?eZ3*9IuEe(9uK@Bup16$l8h=9i-7U1SqAEs#m8M%|6Fd$V+*l zgC4yvyvB5joVzYjE^OA95*g_p4!TXXlxSQ$*}wli?`e~8%fG`ex8_V7husBx3Pp&Y zQQpoyLKVo_OcIKfzk*_q;V-mxZVhjOoTTyKWriE5vz+= z(bk=aXyjNK;45YZB8VqYUO~6#Bpu{m@k+v%Q0GU~d=%c@5MsT0dw8?`hQZCU20spn z?K=EHmZ}??SVU}unLd==h@8QU)>UX|f(r>37c?i870^sf&(2?jF?M(bLmuSjj?7D# z*7DGPX6>p991bZc4RN|Puy}iReD4k@shW=25F{}GSR#D3o zz9kitgM=UG)xcvB;=lQHcMw9zh*`;hG7!k`rxNBDe^eD~4|^+3G=uLOv333v471xc zS_&04ZOG@1LA3{>Izo1iCItpca5UoR+OGC$5;;vVkJi`4o`D)(WxV&gb-TPvjYoD}EY%*c zPMgN6Zw4XfqnbD5FSgF_jb1j5huf$!`~E5Us_RU&$l_xG+cD9pjDs|m!$|e_Q)NE; zWu0Jh1o5*ST0Pn>4Hn)TyuU~>>r!59fr3~PH#|eW!N;GGQo$>M8CG^!UFf8^3=oU$ z1HQ>!bLnk_=STYvxE>%H)!hKSEO*iHZ9HRE7g+L|#9l1Rf6F-U%@iMHFJJx&K@0dw z=<>Z?0(51`sZvAJOud2s=nu-tRaOwwZLN{Zgq;8`51GKj1l}8+ zuuD!sCjO(EDyn>19XtHZC>H2Fjy#9Zb2$+QSLSB}`nIx!VYlNo(Un$T_p$tbVza0~ zQB@a$l9^mptc>jIm#E~$#4tI_J=cE_{$iSWZDx9g+*_JHX1N3Jl3B5MBP=ZcW5L8N zohT(U#{Lc;majq@*H%lnmk5K{5r%ZTJjk+o+LGqkfVyeYdCOv&JrXTf%4%hLGtK zxdyAMAiYabu|b$&7?{tOfaXDmacGw>HH$cWw}X9;)0@cOM{n%4PQE<`=N6#d@oKCn zz^p5=Jr@~#m-69BS(Z70(g1umvDil{V+YfD>Q#{Jds?&O-LDlIfQdI%lUVJUR_GGe z?_Pa+QFsV|z50PT;-dP&NyKRpL4Zmws%Ngd^N}p%QLx!(UM}8tbEMCFKCg`Mt^xJl zId5BOCtLVPaj4wdRW78P=T=8HA_z*@!HXWup(ud7v&N=f9+fqnbL zDiqO}*zZC~zuSn|m!Gqkz*b%<+?^kKyV&Bdc`HOhA|VVjG+N>JSzp0^xYHzRKhuD1 zb=>Ox+I|b*d?DfuH~V=w{Wvi5&toHx&~pWi|1oW%b5p^2&mT`l$&9x0z>`rnYgZRC zYNGzzB@2ofro~Cv`*6C1Q&G7E5h6}r5^gG_|3;t085-ZcUiT=kWY|)zpp(d~a*WOz z1#BI*Rhv^#NH`jx@PZ;5;^w^T7H{I^-tt}`?8Wa!@&QXAQrpY2^hqbsgs}a}j-)4@ zO=xEB9#Sty{{RM{qrTfq0rLsyt&BPrjP(lcER9kTM6H5poOSHOPNik|LvAXsDl!QS zBp@9L7zip4C8Gm@J>uX`I(G&0=HMx8uMY!TT#+>Tjxs)pHz8r1sSsz*3e9&Pxr$oER2~KjUDCtu{6&$pZU|xvds9YjBib^xS!?^m}jV^fJ=zIRKS}Z4&i_JPjgrveA01y>G>~W3)r#AB3lg#F4ufkhWjmD=jfxP`4 z@Dv5M%mgCzn!($UEP?%20HJ{aUd`YP3$5#TM8gQdTfCJJenwa#EDhB_R!(H66l~k6xvd%ObZKFxz3$M^V9K7csHVCA^jb)w1dkn~$dqCFYNt7t zCjPSuaJk(r_k>K_C^UG0pTEdphb>|ci`=#FPlG-(@Q~P7o4RMscuIMfz)1r0r4e46k-e#Q8slEYU~5chRuh|vMz;bQgt^)ffq_A$0#a1y zl(@YA$pr~<{1b@A&$16#)?M#B+5PB^hR!m)uD*ltQFPxy4U&=gtou9fttg0A3W0mqHnkZ*5o@5R>tnG#q#ptSRZ~<{5k>L<6c0X(s*$0o;gcj z01E+`4yx95&0tgqLX{1B07k}XWm1gpq7yPo)LJwQ(`%x!MY8i#Bc^lLv+}Lsv~8lztbeHu=CzxGTQ7l&c{)RFZ@&}>pW7~?iKmydjL3-G61_|R%P3kT- z_Gr1T0{9SpAAUkq<2lIGg;8|}6YWd;wEU0q&_r{#KgL~yLFldu&_YFNZJkf3%pc4+ z^^(X|<7D#`z)4QKzc}JEdz_y#AgZh|ZlFm1dOFPWtCRyCdU?5U{K{qO z!ND5Fjw1E1&gr!=ftT>b|9%us^sK(HZH+3;GnTFc{K22MXmC95wZqndb$Z38I# zGMJF71+WexP!0oX&@og~{^C5fD{cb-jD?~s<@2`T?E$1ra zlNevUswh(a2v52PatzoPuYA7hy=F*#tn>M%Nr5;aOW1zZFpv1AjqC85So~Mx^ep^0 z^!^I}qN&z-sv5>$V~JQqpyHD_)q_POylgR~{&zn60zA<`S(_}aSOEVP)`S4z*L6hN z@JWpQA7cD5B)rOy$t|;al--cU>{(*ssM7oM?FyN^LrPd>S!yG&J^}gys#z#?mK`qP zlJ_JmV_n1^B!O{i;?_?ye!^3zKL)3O9I`?dZ_j1&lWaH;4Vxkv=eJzo{RTtweQ$an z(cix9oJaZPxP?RU6z}UUfj@L#Vi+C%X+N?b zG9WeD4(n(>KzR!33y64J@yc9reX@Nm$dB^WID(^iI=#;{c9~ootkbZDvDK$i!&ZGq zpPrg0_5;gA2miPLjD8S=60w52Cw~qc@UHt7KgwFF=%YZhMY*r(<0Btd0#_mw0MZI~ z0R6OyOv`8G{?D6+YARq#tv;9OpE&sLH86;XF@GyXy8K;a?EnK6kU0T^7-AMMVgSym zfgIujDHU=HJ8`$|@iD>i})|?t(j?n4L<4rNMV>v`m3e zz5ParNL8Xghcu$mdhnhiAr}!#F>Do^Tfe zMs{Idn~<%5LZeD|?H96b4WTCTsjcBJ8DkpXFt5k!x{pE%m?9NM)N&6UM$+lvyJs+G zTX}q(3EO9)7>cE1c4WuUMcZUFSmB8Z|$5svw$o+h(g{Z zDMJ_ckRaVy@m z{e}ZIPJ_g1kt?$QNnhPTxidSp^s>QS&9-fJeR!*rMtg#DEt8Ck^aWv!EhN{8SLx3g z`SyQS`f@r>=^O5ncAK&p@A4>%e3!9gUz@kEXOxDN0pNG0f&uJdcL5PLHCXEeHB%S_ z1g{DdHNyh(JeW$9Z4-qPo@sv-v4DK@A)-|AGn6d_LsE04=RloBKulb`J|k5u2S*rX z7N0`2Jy&!6-?z0H(x352?jVoQ(>_9JoriAjyvGhsu-f^BD0~vU%k}6CYd+yA>|d3y zCSW<8N5H*v<|(Av=W;RbSHWiUGd8FJ`-If#UO+CXKH3+=cY@+n=ezC)IU;XA*TIrA z{*ux9%6%p@aNr`6S%--!>x@rB&V7+?>EppQzB5%5yqAjj2Mzf8MUye^t8d)0b)*Nh zYuuVGfN9PG!-$itkfG&?$N=ZSoQJYN2r zW%qUlSyn)w?oxrbdeCU?I2;?^G)$5l_JDVNVttUmJHHb^s#zdr!%UF30nZHc-}WB) zZwWjbSJIip??%lYOO2kif+Ba%jLM=wTAt%0l~TlMgUF`Ser@FfB7N}}aVALxvos2( z-HO1e=Hw(55YLEIQkCX;-~*@=0psW0$DM*>B7m5t#IS9@4|Te$xj|4$hd+(l z%Ads+SFC{>?%<1DaJ9P_zNJ6}BX9aVsE2VEIO{Y z^!iIde&O=C%IKsTSf4oda$XME?nJRlug%~3C~m7tzI~A+V(&i&?0Njt#v%NRW_%-W zq3YL)p%B5nKwWQ%Nr!dm89sKf_$^CE9#vvHhk-%$UCaJtLG+8q67SAuRG4Vo0s+tl z{haZ*FmU~lU3~!$S!Qd;!tgq7Q5_EW2mxN%r`4zK1_Mp$fgDQ+PpT6=lz{+A)6Xtk z+a96)w5c!q z6nrnt*5pXf*#$5+Ee%HjDIUjyNLZRLUDc&x<4RcA4S%|5(x9Xpr~(mDI!oD zPsBJC{xMF37nuMwzij86S;6Pdx-TA->U`72NZUq}q!V8BhTI>ep;VJ0L27X6b!3mmx@~3H%$-UYvWQ&;Y zRzHi@4iX!T924}TGd+;@5Tb)8;8ccpg!HJf)wobAImNkJM6SeTA`QQ&^9*=90YDrb- z6i#?Z1-!YI30|c)bLl&tZyy=i`)kE*KK9d`;@P(gDQ^x0hV-S(;PWOU>zCYSB3gd- z1%~vd(1w$W$iwV%snU?mROe^i- zcc#+VY6{1pKfF`xU=Es}^U~OSjFe6<=s_&UyIKoDJfaDf1*|2h7>8@=?!@7Yjs50u z&6~jaSMZ!96^mKR+AzB^UL$&Fa#>p>%Q}A#m6hv3i7?(!|dx`xQ}&Dml`sX%6jGRPKmV$*FnPj53xcs zoJ{j351M4VDvpk5L0HC1VvRcxky^$m#^1DU{g6iE5UP<^K{LW;xv51jSdhG_zUjnL zea^2H&KAvL@LLEinX~#vqu`TL0BK|TA~_MxF+nySXXc)(rE1<{PK4N@g8Y~J~*TD zIipT>V|^0Hc=Us#Nt4IX4WPbD|L-%ndm6QVh|XzYgEnsVgEXk1?$-)O@_?J;=Q;4w zx$4zihb3E)?^P*%`yzXidgOaeX4S)gR84RVi`B!E$KUnujb*3U%L84yx$SZis`+p4 zlBE{)I|9mFL<`7UP;bq1!SL+I{?IX{AYralxR8{|Ua(v^lRxr@3oy5~1j}EfSL|mQ1kS;T zrcX)m_i)NJ4yioOMavz0@Wn)cGJk|S{a>?bpZu-O4iLVdHMVvlf%(g>>a2hN7KHL0 zWQCV~l>%A`ju4XHfqW92(bGBP8+_efFU0={l%!uL6|Xua+3Z@Gi5WzaXLt6|;;p8n zKfmgH^T`y6QD9BM%8>^`-Zd`UJ9ke`9^2do(S#rh{oem)0WWyI;o0&L;lS`ANY!H3 zEu=a?H*;|8ocz`GbBC%-D%GhC@O%rbtFcJ~4lmbHzSIyqces+T__n2?zTGw`BN>j# zGv}VH@pnU``l^tk*-I$ipQjdpYt+`ToYWtd6^k5iLXaSr@!kDQK|7!34iUVa?O?lo;X%VCGBPNnYu2# z9~@?k^fVTcQ;sK15>)7*`#nE4hzN~CHk=ZhH2LedG@g`a)3P#d^7ry3@HY|JT$a+q zcsWE=O)~kr$tNyS1?2IP73^dqFw6()7H%?;R5kJ33 zc95=?8s_4!6-<*FSjYd}k1oB5K>k2$jtgS=7^E;RauOsOd7MaNB4)iMfNcksozW%9>cp9s=qJRFqir(A%Nm0^>fC`VOT=m z`{q9TzzCM2y4Lua;EW*t1^f{%@(oMUF81AV={Ou0`Vh&^fSxqo8s?Hs)w)7Nsw6+{ zHJXoyoYX6vg4zK1OzYXC3`?9z!2?A<@JU8M;T7ON8lPBdB++O$aTvYa=1q3S=Fg1n zIR$l{ZerFu5ZiuQ^S_QxZ!yak@m4;u4^*r?TRUmfpt|*8XPglM4UNT>b|#L#H8!Za zfICyy>5(56^e8&#L+7CeF=?^Kk6A-@RTr?&Q2tJA+tSXiW za!wtj|CWs{orG}-qZ6L@?RtP@mrN1e_0>aUqvGKd+%C()gfHgIjDenZZu2@pWUTX81ZqG^E$~2@Br!S4II1 z7$WJr<$K|u{<-NFvvKuId!$5;24_{pmI=xL?`+Wlc8sHVcUBmx!$`3bQG)#-jE0D4 zy`=JeB)%_;R{2sUc?mxh45E(iU%UY}wPvv_4rKGrYckk!JRbQLgZIiKHwW*mhnEsF z7O8A`_;dd6-y;9qFH(n+_;dV28L(}Btsrvo8u$e`Wp<=AJb@gT`fEit9}60E#t*+l z9d`V+Vp?$_1Vw@7#vY>=-CN6)@ zFgQ;85*%Zx1ug~nwLVo#El`47EI!)|V`Sz%fgxXE4PR- z4Hm7jk`_-GUO9vg6}hXgV4xMbQV+bZzho5}Z4v$2(b=%c{6@STIK`x<-p)?Y(fJ)QS|ID*+a;giTu5VCAt!gk zuAo7d5_gGkYWGYj1Q6zDM8?4Z)PRM)GF95C#4|S?e@oQCA&m>2NrldNV%C50?4uvX zpD8FfM!mJ^#9L#CUTJhS$#~bNXC7@L6coDVjFFfDgYKgUWtM_#<~#`eK|y^1twIuv zN8j!j!L<0_!Ly3lgCxu#JdT0jx}~=Z?+pI-AJ=->w3E&*d>bHEpRalOh4UhL5!C>G z$PxUmyCGOm*efESYp$|Wpz&J{Gd{O2X& zkhkD?#K+jV$U7?|dhtzLv?l5nVm=&$EoS%_>;U4dBD7QB`H{a-gKNS-JJ-OXV!0Ba zC65aP&x<9#moH_%_|5>CT4S;R3RD^qWJKJh$#Zb;yhP+U%t}lagEqEC6NhLSwuf3mF3 z4=HD00wRRk0J&pcN$?NMTj=;&WFO^8=_3gc+@)t+oImdTB!rL#Rp&@geL!LeHbq}K z@Wh#aI#qE2IRB&v1rV(H<4%(X3Q6U$;A9|jE@mxkY_)q1N7!KtnC|*PKBW}@pd@gb zcOdQw+68;s_{YFFFJ@Ps}ZvtU>&i-D}J!?V-WrLe~dJ zByR`Pl8(|SsUsvD;sQVX0Fh9N5{I61au1SNDu65uDDZf*K2n+pq=h{}q~Q=bVRU){ zjcacE?SMTz3#$HnMr9e2hM<$+6d(+$M0la{J6T;g+}S#akaj@GhsgF38n~Fnd};VD zid-)wokzm+l~v-aW{-~iIx$sUjSHHpho^XD!Se#3&|l#OhF7V--% z%}V51JS-Vla94^20qmOoOZihpfv&Y{?jhd?u!5wn&6*$y$7n#)oW%wF>uP zA1fcULZ8ll;J&GUqBd3EqN3R2j#q zj2n(0;6u5e2)(mN!aiy_@EG98!^aPF8$x!FgEJJegF*&FkitR0%MULtCKC=EFm$Zb zPk#(~AwB0Vl~YK92O`}Eg$Xy&yEQtYw8(|xhbxrcG}F+=wr#{>(GAB6ooRW~7>|xl z+!MXx3mss;tjxffjm~{n3o4Td8QbiVj>>M5(KnnT;gpZLmEOY+Dp2z2&#_GQi-i>S z$$|NY!fyfo?PlkMJsbc(IUnJ|f^4LUl>zde92|%l zc|D+wL2Pc(N)2zq`y-|s{0~3K zYpK|R>x($SPw{d~5Y$kcRCtjx{R{tpA%ow*vi^rCqp&?-*$@dz`V2QI4WH+_1W^ku zrIQPd#h@2KyE&4-b9)p&JIo@|^mgHTRUoYL4+!6jky9)ZhjZtsWvnAsT$uvDO{Y^C z-L%Rgh}Q8tpN?F^W&>hnkPQifg?*5BgzOSnk7i?YoB|21MR5|si1`?s$}=0k5{vy; z<|q&69s3|0_EeGUGnNDHlbG#Wu0*4o|H+X!yBq}M8%PN_crNsSDDhJ`Y8EKx!3(;uLC7(Jt@(T*x!I4BBJDU~w z>40PZFy1h&KrFVv0tgI~zNfjtD)20t!@UlI762)5`;Mp#DlX3VMTphi@|=K@^;MjWmL$X4H; zKLSPq{e(QM_zugc+|my(pUpy~15B`IT7Duvs6=ISuNT~1oPir}Q7CyK zmYM@Q-8_>Modc}|%Yuan#{VZF=8$gc(u%IkxVZ~2H-Uswn+A#nNquBXWLraMU*t9f zrW6d_lC4QI-~izY0L}tT#viKz8Jd2##F{`*4AoQQ0gfUK)C`VgDHsPu{g!(gL}5TJ zC57XVI%1bPnvUJ4w%plIRfPr+k*8828D^a9X8ng<`8+-vQsZh=`?W>RJdA-_SIoG* z>?25G2E!nY7P0S&RolM&0PT4re;}{m;r8&%ExHPp`TBrs;n77PMyk4uK$eFym;s54 z@#cJ-evKO1*bvmRzk-%YQkPN(6tSSdiAV)_t^vsjPoR0AH6W2w1Z5|8wJu+XnlCf~CQ?A`9l#P8t$ z7rC)P&nszhe)f`epOP}}xPc2Bs18v82X_8X*!8qw$RmUlMhKmuId?d+77*IM$g@tU1@r4JNttuYGGY#9BcRGK zG8`<$@Aa;3UtV=YRW7dwcsxa}uv8q+@>mf*{DzvyfFc0yV|}fS+k_{QnFrko(@xDM z%rr2po@82AnS|dfy=3*wi#AV~Kc0)r;|1qGy37VIe zCt^}Isy2=IK=?F8Gj{g7*RadS)Ib%COMf8naDMP*(hK!3 zBL6-#!I+46tQg)DeyC2gL!n#mhCrV*U{%DA`N{60a= zJ~AoC0a_0b{r?1;L9kY_45q3|g~IYe z-2p~*1e8=5l!0p#DciyhS)@@Q7tYb>=(OLRlLS2*IQ>qDc~x=7p(r~Jl&03`)7L_;wnQ8=LufwKX4tP8vbf&*!cYhk*Y2B8nNZm}8@B~Q zI^YLS9fy{HWHbLJI!sw~JU`#ARoYK%%-9#uQA zg%pLXMHu)3HH>!AtP&!y1315T4RZF{uyrs7col2p3r2f(flF2rav$_0bfF;|2|5ca z;dY4#?k8T>(s#LnRHRo3o2RuCe-mt|IXGJ(u-jmt*-W85>jHqK3g$jJB-@UTr)X>7 z=?RdjVsJDVH0aeErERg-E3$yTsf3$I%l;C91xf(z0`qNnr4Hm;cgbZ{4@C%2tS29P zjv^iQfl~}=+9A z<)P66QW*)+nH_xkm`rtt%>%nD1?6osFf4$Hja)KZdXRAR*NUH=BhX0*{cq3D16!&j zG&o&0|Rp#on0@yGpF9%HQ^H2l!>9%J%8J&UGYnRaK$(=RU{nB$tJ zI_5tj>OO_?FOcgo>%@C_r$XtDgQjKFe4fgs^BqS~*D=;(^BzN>=sIRPW;za%9V@tk zr4E^ngQXYde2+2Ib&%u8bUsI1%kwYHeAIN|5#?a(nCqD9G1gzM19>N@5)=dzE` z_My*l?c_M?GZG8H_8&SvOQt$ZbeVMN`5h3%dp8cHW zyoe{{ZJ7{{RX909D7Mlj=H5bK;Mw@`F)TBEFa{7nlD4^aaNpa_>jaq1Q3_De>%G z=)AsEI#BZ*erLy_&~zS3Jd}AT@=?=}^FD*~9%J&S;P@U$Jdk+~givowj+8wgCKO^m zL#Z6jidNFSC}EG2^}TwFR)eq+pa9djSkh|?N}&X*tm0HLlp_*a*g zm;Rp5OVH)Tc^>1*N08_`W>=@^-TFBC+DgdkkJbPt%A008j8r UA3yvIeNiL&+dUsA&;A$x*{&B5+W-In diff --git a/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/img/bg3.jpg b/package/lienol/luci-theme-argon-dark-mod/htdocs/luci-static/argon_dark/img/bg3.jpg deleted file mode 100644 index a614e1a98582890619be600dcdf074e51ba37862..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 248828 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

YDc;9wp|Umm{P6lPNqebR+6m02tvTIwQ9rDQh8n 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

","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:k.htmlSerialize?[0,"",""]:[1,"X
","
"]},sa=da(y),ta=sa.appendChild(y.createElement("div"));ra.optgroup=ra.option,ra.tbody=ra.tfoot=ra.colgroup=ra.caption=ra.thead,ra.th=ra.td;function ua(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ua(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function va(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wa(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xa(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function ya(a){var b=pa.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function za(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Aa(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Ba(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xa(b).text=a.text,ya(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!ga.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(ta.innerHTML=a.outerHTML,ta.removeChild(f=ta.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ua(f),h=ua(a),g=0;null!=(e=h[g]);++g)d[g]&&Ba(e,d[g]);if(b)if(c)for(h=h||ua(a),d=d||ua(f),g=0;null!=(e=h[g]);g++)Aa(e,d[g]);else Aa(a,f);return d=ua(f,"script"),d.length>0&&za(d,!i&&ua(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=da(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(la.test(f)){h=h||o.appendChild(b.createElement("div")),i=(ja.exec(f)||["",""])[1].toLowerCase(),l=ra[i]||ra._default,h.innerHTML=l[1]+f.replace(ia,"<$1>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&ha.test(f)&&p.push(b.createTextNode(ha.exec(f)[0])),!k.tbody){f="table"!==i||ka.test(f)?""!==l[1]||ka.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ua(p,"input"),va),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ua(o.appendChild(f),"script"),g&&za(h),c)){e=0;while(f=h[e++])oa.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wa(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wa(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ua(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&za(ua(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ua(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fa,""):void 0;if(!("string"!=typeof a||ma.test(a)||!k.htmlSerialize&&ga.test(a)||!k.leadingWhitespace&&ha.test(a)||ra[(ja.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ia,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ua(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ua(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&na.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ua(i,"script"),xa),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ua(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,ya),j=0;f>j;j++)d=g[j],oa.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qa,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Ca,Da={};function Ea(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fa(a){var b=y,c=Da[a];return c||(c=Ea(a,b),"none"!==c&&c||(Ca=(Ca||m("

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
C-_sqPw_e9^u|kYYY|X7}leeSYWn`CcyH()%>) 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 Lag}16Ir115f6I6Q#c#|1d00INvFb6n=u= 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[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b="length"in a&&a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,aa=/[+~]/,ba=/'|\\/g,ca=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),da=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ea=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fa){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(ba,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+ra(o[l]);w=aa.test(a)&&pa(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",ea,!1):e.attachEvent&&e.attachEvent("onunload",ea)),p=!f(g),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="
",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?la(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ca,da),a[3]=(a[3]||a[4]||a[5]||"").replace(ca,da),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ca,da).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(ca,da),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return W.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(ca,da).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:oa(function(){return[0]}),last:oa(function(a,b){return[b-1]}),eq:oa(function(a,b,c){return[0>c?c+b:c]}),even:oa(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:oa(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:oa(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:oa(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function sa(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function ta(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ua(a,b,c){for(var d=0,e=b.length;e>d;d++)ga(a,b[d],c);return c}function va(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wa(a,b,c,d,e,f){return d&&!d[u]&&(d=wa(d)),e&&!e[u]&&(e=wa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ua(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:va(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=va(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=va(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sa(function(a){return a===b},h,!0),l=sa(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sa(ta(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wa(i>1&&ta(m),i>1&&ra(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xa(a.slice(i,e)),f>e&&xa(a=a.slice(e)),f>e&&ra(a))}m.push(c)}return ta(m)}function ya(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=va(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&ga.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,ya(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ca,da),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ca,da),aa.test(j[0].type)&&pa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&ra(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,aa.test(a)&&pa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1; - -return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML="
a",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function aa(){return!0}function ba(){return!1}function ca(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h]","i"),ha=/^\s+/,ia=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,ja=/<([\w:]+)/,ka=/\s*$/g,ra={option:[1,""],legend:[1,"