From dca9df43b07ca9a22859619b365dac275760b052 Mon Sep 17 00:00:00 2001 From: ClayMoreBoy Date: Thu, 17 Feb 2022 15:31:22 +0800 Subject: [PATCH] init --- README.md | 24 - brook/Makefile | 72 + chinadns-ng/Makefile | 40 + dns2socks/Makefile | 53 + hysteria/Makefile | 80 + ipt2socks/Makefile | 43 + kcptun/Makefile | 76 + kcptun/files/kcptun.config | 43 + kcptun/files/kcptun.init | 174 + 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 - lienol/luci-app-filebrowser/Makefile | 17 - .../luasrc/controller/filebrowser.lua | 61 - .../luasrc/model/cbi/filebrowser/api.lua | 338 - .../luasrc/model/cbi/filebrowser/settings.lua | 37 - .../luasrc/view/filebrowser/download.htm | 169 - .../luasrc/view/filebrowser/log.htm | 31 - .../luasrc/view/filebrowser/status.htm | 29 - .../po/zh-cn/filebrowser.po | 107 - .../root/etc/config/filebrowser | 7 - .../root/etc/init.d/filebrowser | 38 - .../etc/uci-defaults/luci-app-filebrowser | 11 - .../rpcd/acl.d/luci-app-filebrowser.json | 11 - lienol/luci-app-guest-wifi/Makefile | 17 - .../luasrc/controller/guest-wifi.lua | 8 - .../luasrc/model/cbi/guest-wifi.lua | 67 - .../po/zh-cn/guest-wifi.po | 90 - .../root/etc/config/guest-wifi | 14 - .../root/etc/init.d/guest-wifi | 213 - .../root/etc/uci-defaults/luci-app-guest-wifi | 11 - .../share/rpcd/acl.d/luci-app-guest-wifi.json | 11 - .../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 | 127 - .../luci-app-ipsec-vpnserver-manyusers | 21 - .../luci-app-ipsec-vpnserver-manyusers.json | 11 - lienol/luci-app-kodexplorer/LICENSE | 674 - lienol/luci-app-kodexplorer/Makefile | 16 - .../luasrc/controller/kodexplorer.lua | 46 - .../luasrc/model/cbi/kodexplorer/api.lua | 170 - .../luasrc/model/cbi/kodexplorer/settings.lua | 96 - .../luasrc/view/kodexplorer/status.htm | 52 - .../luasrc/view/kodexplorer/version.htm | 188 - .../po/zh-cn/kodexplorer.po | 119 - .../root/etc/config/kodexplorer | 10 - .../root/etc/init.d/kodexplorer | 79 - .../root/etc/kodexplorer/nginx.conf.template | 38 - .../etc/kodexplorer/php-fpm.conf.template | 14 - .../root/etc/kodexplorer/php.ini.template | 56 - .../etc/uci-defaults/luci-app-kodexplorer | 12 - .../rpcd/acl.d/luci-app-kodexplorer.json | 11 - lienol/luci-app-nginx-pingos/Makefile | 101 - .../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 - .../rpcd/acl.d/luci-app-nginx-pingos.json | 11 - lienol/luci-app-passwall/LICENSE | 674 - lienol/luci-app-passwall/Makefile | 170 - lienol/luci-app-passwall/README.md | 2 - .../luasrc/controller/passwall.lua | 405 - .../luasrc/model/cbi/passwall/api/api.lua | 276 - .../luasrc/model/cbi/passwall/api/brook.lua | 133 - .../model/cbi/passwall/api/gen_naiveproxy.lua | 16 - .../cbi/passwall/api/gen_shadowsocks.lua | 34 - .../model/cbi/passwall/api/gen_v2ray.lua | 308 - .../cbi/passwall/api/gen_v2ray_proto.lua | 80 - .../luasrc/model/cbi/passwall/api/kcptun.lua | 205 - .../model/cbi/passwall/api/trojan_go.lua | 149 - .../luasrc/model/cbi/passwall/api/v2ray.lua | 166 - .../luasrc/model/cbi/passwall/client/acl.lua | 109 - .../model/cbi/passwall/client/app_update.lua | 47 - .../model/cbi/passwall/client/auto_switch.lua | 44 - .../model/cbi/passwall/client/global.lua | 352 - .../luasrc/model/cbi/passwall/client/log.lua | 5 - .../model/cbi/passwall/client/node_list.lua | 153 - .../cbi/passwall/client/node_subscribe.lua | 84 - .../luasrc/model/cbi/passwall/client/rule.lua | 64 - .../model/cbi/passwall/client/rule_list.lua | 167 - .../model/cbi/passwall/client/shunt_rules.lua | 43 - .../model/cbi/passwall/server/api/app.lua | 149 - .../luasrc/view/passwall/global/footer.htm | 33 - .../luasrc/view/passwall/global/status.htm | 391 - .../luasrc/view/passwall/global/tips.htm | 12 - .../luasrc/view/passwall/haproxy/status.htm | 20 - .../view/passwall/node_list/link_add_node.htm | 144 - .../view/passwall/rule/rule_version.htm | 70 - .../luasrc/view/passwall/server/log.htm | 31 - .../passwall/server/users_list_status.htm | 19 - .../root/etc/config/passwall | 106 - .../root/etc/init.d/passwall | 21 - .../root/etc/init.d/passwall_server | 16 - .../root/usr/share/passwall/app.sh | 1239 - .../root/usr/share/passwall/iptables.sh | 741 - .../root/usr/share/passwall/monitor.sh | 96 - .../root/usr/share/passwall/rule_update.lua | 342 - .../usr/share/passwall/rules/adblock.conf | 6105 ----- .../root/usr/share/passwall/rules/direct_host | 6 - .../usr/share/passwall/rules/gfwlist.conf | 10786 -------- .../root/usr/share/passwall/rules/proxy_host | 144 - .../root/usr/share/passwall/subscribe.lua | 935 - .../root/usr/share/passwall/test.sh | 193 - lienol/luci-app-pppoe-relay/Makefile | 16 - .../luasrc/controller/pppoe-relay.lua | 29 - .../luasrc/model/cbi/pppoe-relay.lua | 47 - .../luasrc/view/pppoe-relay/ajax.htm | 26 - .../luasrc/view/pppoe-relay/status.htm | 3 - .../po/zh-cn/pppoe-relay.po | 23 - .../root/etc/config/pppoe-relay | 1 - .../root/etc/init.d/pppoe-relay | 26 - .../etc/uci-defaults/luci-app-pppoe-relay | 11 - .../rpcd/acl.d/luci-app-pppoe-relay.json | 11 - 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 - .../rpcd/acl.d/luci-app-pppoe-server.json | 11 - .../Makefile | 16 - .../luasrc/controller/pptpd.lua | 24 - .../luasrc/model/cbi/pptpd/online.lua | 80 - .../luasrc/model/cbi/pptpd/settings.lua | 45 - .../luasrc/model/cbi/pptpd/users.lua | 19 - .../luasrc/view/pptpd/index.htm | 13 - .../luasrc/view/pptpd/status.htm | 3 - .../po/zh-cn/pptpd.po | 89 - .../root/etc/config/pptpd | 12 - .../root/etc/init.d/pptpd | 137 - .../luci-app-pptp-vpnserver-manyusers | 19 - .../luci-app-pptp-vpnserver-manyusers.json | 11 - lienol/luci-app-ramfree/Makefile | 17 - .../luasrc/controller/release_ram.lua | 9 - .../luci-app-ramfree/po/zh-cn/release_ram.po | 2 - 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 - lienol/luci-app-socat/root/etc/config/socat | 3 - lienol/luci-app-socat/root/etc/init.d/socat | 119 - .../root/etc/uci-defaults/luci-app-socat | 19 - .../usr/share/rpcd/acl.d/luci-app-socat.json | 11 - lienol/luci-app-softethervpn/Makefile | 16 - .../luasrc/controller/softethervpn.lua | 18 - .../luasrc/model/cbi/softethervpn.lua | 16 - .../luasrc/view/softethervpn/index.htm | 18 - .../luasrc/view/softethervpn/status.htm | 3 - .../po/zh-cn/softethervpn.po | 23 - .../root/etc/config/softethervpn | 4 - .../root/etc/init.d/softethervpn | 74 - .../etc/uci-defaults/luci-app-softethervpn | 23 - .../rpcd/acl.d/luci-app-softethervpn.json | 11 - lienol/luci-app-ssr-mudb-server/LICENSE | 674 - 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 - 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 - .../rpcd/acl.d/luci-app-timecontrol.json | 11 - luci-app-passwall/Makefile | 169 + .../luasrc/controller/passwall.lua | 524 + .../luasrc/model/cbi/passwall/api/api.lua | 597 + .../luasrc/model/cbi/passwall/api/brook.lua | 134 + .../model/cbi/passwall/api/gen_hysteria.lua | 61 + .../model/cbi/passwall/api/gen_naiveproxy.lua | 23 + .../cbi/passwall/api/gen_shadowsocks.lua | 69 + .../model/cbi/passwall/api/gen_trojan.lua | 57 +- .../model/cbi/passwall/api/gen_v2ray.lua | 681 + .../cbi/passwall/api/gen_v2ray_proto.lua | 111 + .../model/cbi/passwall/api/hysteria.lua | 134 + .../luasrc/model/cbi/passwall/api/kcptun.lua | 189 + .../model/cbi/passwall/api/trojan_go.lua | 183 + .../luasrc/model/cbi/passwall/api/v2ray.lua | 181 + .../luasrc/model/cbi/passwall/api/xray.lua | 181 + .../luasrc/model/cbi/passwall/client/acl.lua | 119 + .../model/cbi/passwall/client/acl_config.lua | 291 + .../model/cbi/passwall/client/app_update.lua | 49 + .../model/cbi/passwall/client/auto_switch.lua | 66 + .../model/cbi/passwall/client/global.lua | 471 + .../model/cbi/passwall/client/haproxy.lua | 73 +- .../luasrc/model/cbi/passwall/client/log.lua | 8 + .../model/cbi/passwall/client/node_config.lua | 489 +- .../model/cbi/passwall/client/node_list.lua | 145 + .../cbi/passwall/client/node_subscribe.lua | 142 + .../passwall/client/node_subscribe_config.lua | 110 + .../model/cbi/passwall/client/other.lua | 80 +- .../luasrc/model/cbi/passwall/client/rule.lua | 91 + .../model/cbi/passwall/client/rule_list.lua | 205 + .../model/cbi/passwall/client/shunt_rules.lua | 79 + .../model/cbi/passwall/server/api/app.lua | 197 + .../cbi/passwall/server/api/hysteria.lua | 24 + .../cbi/passwall/server/api/shadowsocks.lua | 0 .../model/cbi/passwall/server/api/trojan.lua | 53 +- .../model/cbi/passwall/server/api/v2ray.lua | 111 +- .../model/cbi/passwall/server/index.lua | 23 +- .../luasrc/model/cbi/passwall/server/user.lua | 323 +- .../passwall/app_update/brook_version.htm | 88 +- .../passwall/app_update/hysteria_version.htm | 159 + .../passwall/app_update/kcptun_version.htm | 70 +- .../passwall/app_update/trojan_go_version.htm | 72 +- .../passwall/app_update/v2ray_version.htm | 72 +- .../view/passwall/app_update/xray_version.htm | 175 + .../view/passwall/auto_switch/footer.htm | 22 + .../luasrc/view/passwall/global/faq.htm | 43 + .../luasrc/view/passwall/global/footer.htm | 155 + .../luasrc/view/passwall/global/status.htm | 351 + .../luasrc/view/passwall/global/status2.htm | 142 +- .../luasrc/view/passwall/haproxy/status.htm | 26 + .../luasrc/view/passwall/log/log.htm | 9 +- .../view/passwall/node_list/link_add_node.htm | 106 + .../passwall/node_list/link_share_man.htm | 525 +- .../view/passwall/node_list/node_list.htm | 213 +- .../view/passwall/rule/rule_version.htm | 76 + .../luasrc/view/passwall/server}/log.htm | 9 +- .../passwall/server/users_list_status.htm | 38 + .../po/zh-cn/passwall.po | 591 +- luci-app-passwall/po/zh_Hans | 1 + .../root/etc/config/passwall_server | 0 luci-app-passwall/root/etc/init.d/passwall | 80 + .../root/etc/init.d/passwall_server | 16 + .../root/etc/uci-defaults/luci-passwall | 10 +- .../root/usr/share/passwall/0_default_config | 150 + .../root/usr/share/passwall/app.sh | 1510 + .../root/usr/share/passwall/helper_dnsmasq.sh | 311 + .../usr/share/passwall/helper_smartdns.sh | 225 + .../root/usr/share/passwall/iptables.sh | 1196 + .../root/usr/share/passwall/monitor.sh | 107 + .../root/usr/share/passwall/rule_update.lua | 420 + .../root/usr/share/passwall/rules/block_host | 0 .../root/usr/share/passwall/rules/block_ip | 0 .../root/usr/share/passwall/rules/chnlist | 22849 ++++++---------- .../root/usr/share/passwall/rules/chnroute | 15205 +++++----- .../root/usr/share/passwall/rules/chnroute6 | 334 +- .../root/usr/share/passwall/rules/direct_host | 18 + .../root/usr/share/passwall/rules/direct_ip | 5 - .../root/usr/share/passwall/rules/gfwlist | 12011 ++++++++ .../usr/share/passwall/rules/lanlist_ipv4 | 9 + .../usr/share/passwall/rules/lanlist_ipv6 | 13 + .../root/usr/share/passwall/rules/proxy_host | 14 + .../root/usr/share/passwall/rules/proxy_ip | 6 + .../root/usr/share/passwall/subscribe.lua | 1199 + .../root/usr/share/passwall/test.sh | 243 + .../share/rpcd/acl.d/luci-app-passwall.json | 0 microsocks/Makefile | 43 + naiveproxy/Makefile | 131 + naiveproxy/src/init_env.sh | 96 + obsolete/luci-app-brook-server/LICENSE | 674 - obsolete/luci-app-brook-server/Makefile | 16 - .../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 - .../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 | 88 - .../etc/uci-defaults/luci-app-brook-server | 19 - .../rpcd/acl.d/luci-app-brook-server.json | 11 - obsolete/luci-app-ssr-libev-server/Makefile | 15 - .../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 | 104 - .../uci-defaults/luci-app-ssr-libev-server | 19 - .../rpcd/acl.d/luci-app-ssr-libev-server.json | 11 - obsolete/luci-app-trojan-server/LICENSE | 674 - obsolete/luci-app-trojan-server/Makefile | 16 - .../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 | 90 - .../etc/uci-defaults/luci-app-trojan-server | 19 - .../rpcd/acl.d/luci-app-trojan-server.json | 11 - obsolete/luci-app-v2ray-server/LICENSE | 674 - obsolete/luci-app-v2ray-server/Makefile | 16 - .../luasrc/controller/v2ray_server.lua | 56 - .../luasrc/model/cbi/v2ray_server/api/app.lua | 103 - .../model/cbi/v2ray_server/api/gen_config.lua | 184 - .../model/cbi/v2ray_server/api/v2ray.lua | 328 - .../luasrc/model/cbi/v2ray_server/index.lua | 57 - .../luasrc/model/cbi/v2ray_server/user.lua | 311 - .../luasrc/view/v2ray_server/log.htm | 31 - .../view/v2ray_server/users_list_status.htm | 19 - .../luasrc/view/v2ray_server/v2ray.htm | 184 - .../po/zh-cn/v2ray_server.po | 182 - .../root/etc/config/v2ray_server | 4 - .../root/etc/init.d/v2ray_server | 16 - .../etc/uci-defaults/luci-app-v2ray-server | 20 - .../rpcd/acl.d/luci-app-v2ray-server.json | 11 - others/luci-app-control-timewol/Makefile | 16 - .../luasrc/controller/timewol.lua | 19 - .../luasrc/model/cbi/timewol.lua | 37 - .../luasrc/view/timewol/index.htm | 18 - .../luasrc/view/timewol/timewol.htm | 3 - .../po/zh-cn/timewol.po | 2 - .../root/etc/config/timewol | 3 - .../root/etc/init.d/timewol | 74 - .../etc/uci-defaults/luci-app-control-timewol | 11 - .../rpcd/acl.d/luci-app-control-timewol.json | 11 - .../luci-app-control-webrestriction/Makefile | 17 - .../luasrc/controller/webrestriction.lua | 19 - .../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 - .../luci-app-control-webrestriction.json | 11 - others/luci-app-control-weburl/Makefile | 18 - .../luasrc/controller/weburl.lua | 17 - .../luasrc/model/cbi/weburl.lua | 36 - .../luasrc/view/weburl/index.htm | 18 - .../luasrc/view/weburl/weburl.htm | 3 - .../po/zh-cn/weburl.po | 2 - .../root/etc/config/weburl | 22 - .../root/etc/init.d/weburl | 88 - .../etc/uci-defaults/luci-app-control-weburl | 11 - .../rpcd/acl.d/luci-app-control-weburl.json | 11 - others/luci-app-kcptun/LICENSE | 202 - others/luci-app-kcptun/Makefile | 35 - others/luci-app-kcptun/README.md | 61 - .../luasrc/controller/kcptun.lua | 120 - .../model/cbi/kcptun/servers-detail.lua | 182 - .../luasrc/model/cbi/kcptun/servers.lua | 71 - .../luasrc/model/cbi/kcptun/settings.lua | 111 - .../luci-app-kcptun/luasrc/model/kcptun.lua | 486 - .../luasrc/view/kcptun/button.htm | 19 - .../luasrc/view/kcptun/log_view.htm | 74 - .../luasrc/view/kcptun/status.htm | 278 - .../luci-app-kcptun/po/templates/kcptun.pot | 344 - others/luci-app-kcptun/po/zh-cn/kcptun.po | 344 - others/luci-app-kcptun/root/etc/config/kcptun | 15 - others/luci-app-kcptun/root/etc/init.d/kcptun | 244 - .../root/etc/uci-defaults/40_luci-kcptun | 25 - .../usr/share/rpcd/acl.d/luci-app-kcptun.json | 11 - others/luci-app-syncthing/Makefile | 17 - .../luasrc/controller/syncthing.lua | 19 - .../luasrc/model/cbi/syncthing.lua | 19 - .../view/syncthing/syncthing_status.htm | 22 - .../luci-app-syncthing/po/zh-cn/syncthing.po | 11 - .../root/etc/config/syncthing | 4 - .../root/etc/init.d/syncthing | 43 - .../root/etc/uci-defaults/luci-syncthing | 12 - .../share/rpcd/acl.d/luci-app-syncthing.json | 11 - others/luci-app-verysync/Makefile | 16 - .../luasrc/controller/verysync.lua | 17 - .../luasrc/model/cbi/verysync.lua | 24 - .../luasrc/view/verysync/verysync_status.htm | 28 - others/luci-app-verysync/po/zh-cn/verysync.po | 8 - .../root/etc/config/verysync | 2 - .../root/etc/init.d/verysync | 17 - .../root/etc/uci-defaults/luci-verysync | 11 - .../share/rpcd/acl.d/luci-app-verysync.json | 11 - package/brook/Makefile | 79 - package/chinadns-ng/LICENSE | 674 - package/chinadns-ng/Makefile | 43 - package/dns2socks/Makefile | 66 - package/ipt2socks/Makefile | 39 - package/kcptun/Makefile | 65 - package/microsocks/Makefile | 38 - package/naiveproxy/Makefile | 127 - .../001-Remove-concurrency-limit.patch | 40 - ...-build-add-OpenWrt-staging-libraries.patch | 29 - ...101-build-drop-useless-deps-simd_asm.patch | 27 - package/naiveproxy/src/init_env.sh | 87 - package/openssl1.1/Makefile | 162 - .../1.1.1/100-Configure-afalg-support.patch | 25 - .../patches/1.1.1/110-openwrt_targets.patch | 63 - .../1.1.1/120-strip-cflags-from-binary.patch | 23 - .../1.1.1/130-dont-build-tests-fuzz.patch | 31 - .../1.1.1/140-allow-prefer-chacha20.patch | 82 - package/shadowsocksr-libev/Makefile | 67 - .../0001-Add-ss-server-and-ss-check.patch | 17186 ------------ package/simple-obfs/LICENSE | 622 - package/ssocks/Makefile | 51 - package/tcping/LICENSE | 280 - package/trojan-go/Makefile | 87 - package/v2ray-plugin/LICENSE | 622 - package/v2ray-plugin/Makefile | 74 - package/v2ray/Config.in | 136 - package/v2ray/Makefile | 319 - package/verysync/Makefile | 68 - {package/pdnsd-alt => pdnsd-alt}/Makefile | 36 +- .../pdnsd-alt => pdnsd-alt}/files/pdnsd.init | 0 ...d-alt-build-error-within-kernel_5.15.patch | 52 + shadowsocks-rust/Makefile | 85 + shadowsocksr-libev/Makefile | 64 + .../0001-Add-ss-server-and-ss-check.patch | 397 + ...Revert-verify_simple-and-auth_simple.patch | 8 +- .../patches/0003-Refine-Usage.patch | 13 +- .../patches/100-fix-gcc-10.patch | 20 + ...-Fix-Werror-sizeof-pointer-memaccess.patch | 2 +- .../102-Read-listening-mode-from-config.patch | 34 + .../patches/999-tcp-tproxy.patch | 154 + shadowsocksr-libev/src/server/Makefile.am | 55 + shadowsocksr-libev/src/server/Makefile.in | 919 + shadowsocksr-libev/src/server/README.md | 3 + shadowsocksr-libev/src/server/acl.c | 597 + shadowsocksr-libev/src/server/acl.h | 53 + shadowsocksr-libev/src/server/auth.c | 993 + shadowsocksr-libev/src/server/auth.h | 30 + shadowsocksr-libev/src/server/base64.c | 119 + shadowsocksr-libev/src/server/base64.h | 16 + shadowsocksr-libev/src/server/cache.c | 308 + shadowsocksr-libev/src/server/cache.h | 62 + shadowsocksr-libev/src/server/check.c | 236 + shadowsocksr-libev/src/server/common.h | 58 + shadowsocksr-libev/src/server/crc32.c | 97 + shadowsocksr-libev/src/server/encrypt.c | 1645 ++ shadowsocksr-libev/src/server/encrypt.h | 222 + shadowsocksr-libev/src/server/http.c | 152 + shadowsocksr-libev/src/server/http.h | 34 + shadowsocksr-libev/src/server/http_simple.c | 625 + shadowsocksr-libev/src/server/http_simple.h | 21 + shadowsocksr-libev/src/server/jconf.c | 260 + shadowsocksr-libev/src/server/jconf.h | 78 + shadowsocksr-libev/src/server/json.c | 1002 + shadowsocksr-libev/src/server/json.h | 249 + shadowsocksr-libev/src/server/list.c | 370 + shadowsocksr-libev/src/server/list.h | 61 + shadowsocksr-libev/src/server/netutils.c | 297 + shadowsocksr-libev/src/server/netutils.h | 98 + shadowsocksr-libev/src/server/obfs.c | 205 + shadowsocksr-libev/src/server/obfs.h | 100 + shadowsocksr-libev/src/server/obfsutil.c | 36 + shadowsocksr-libev/src/server/protocol.h | 34 + shadowsocksr-libev/src/server/resolv.c | 444 + shadowsocksr-libev/src/server/resolv.h | 50 + shadowsocksr-libev/src/server/rule.c | 137 + shadowsocksr-libev/src/server/rule.h | 58 + shadowsocksr-libev/src/server/server.c | 2209 ++ shadowsocksr-libev/src/server/server.h | 115 + shadowsocksr-libev/src/server/tls.c | 263 + shadowsocksr-libev/src/server/tls.h | 33 + shadowsocksr-libev/src/server/tls1.2_ticket.c | 609 + shadowsocksr-libev/src/server/tls1.2_ticket.h | 20 + shadowsocksr-libev/src/server/udprelay.c | 1452 + shadowsocksr-libev/src/server/udprelay.h | 95 + shadowsocksr-libev/src/server/uthash.h | 1074 + shadowsocksr-libev/src/server/utils.c | 448 + shadowsocksr-libev/src/server/utils.h | 232 + shadowsocksr-libev/src/server/verify.c | 188 + shadowsocksr-libev/src/server/verify.h | 19 + {package/simple-obfs => simple-obfs}/Makefile | 7 +- ssocks/Makefile | 77 + .../ssocks => ssocks}/patches/001-fix.patch | 0 .../ssocks => ssocks}/patches/002-gcc10.patch | 0 {package/tcping => tcping}/Makefile | 4 + trojan-go/Makefile | 77 + {package/trojan-plus => trojan-plus}/Makefile | 21 +- {package/trojan => trojan}/Makefile | 17 +- .../patches/001-force-openssl-version.patch | 0 v2ray-core/Makefile | 189 + v2ray-core/files/v2ray.conf | 11 + v2ray-core/files/v2ray.init | 56 + v2ray-geodata/Makefile | 79 + v2ray-plugin/Makefile | 74 + xray-core/Makefile | 126 + xray-core/files/config.json.example | 144 + xray-core/files/vpoint_socks_vmess.json | 25 + xray-core/files/vpoint_vmess_freedom.json | 31 + xray-core/files/xray.conf | 11 + xray-core/files/xray.init | 56 + xray-plugin/Makefile | 71 + 804 files changed, 61477 insertions(+), 168779 deletions(-) delete mode 100644 README.md create mode 100644 brook/Makefile create mode 100644 chinadns-ng/Makefile create mode 100644 dns2socks/Makefile create mode 100644 hysteria/Makefile create mode 100644 ipt2socks/Makefile create mode 100644 kcptun/Makefile create mode 100644 kcptun/files/kcptun.config create mode 100755 kcptun/files/kcptun.init delete mode 100755 lienol/luci-app-fileassistant/Makefile delete mode 100755 lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/fb.css delete mode 100755 lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/fb.js delete mode 100755 lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/file-icon.png delete mode 100755 lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/folder-icon.png delete mode 100755 lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/link-icon.png delete mode 100755 lienol/luci-app-fileassistant/luasrc/controller/fileassistant.lua delete mode 100755 lienol/luci-app-fileassistant/luasrc/view/fileassistant.htm delete mode 100755 lienol/luci-app-filebrowser/Makefile delete mode 100755 lienol/luci-app-filebrowser/luasrc/controller/filebrowser.lua delete mode 100755 lienol/luci-app-filebrowser/luasrc/model/cbi/filebrowser/api.lua delete mode 100755 lienol/luci-app-filebrowser/luasrc/model/cbi/filebrowser/settings.lua delete mode 100755 lienol/luci-app-filebrowser/luasrc/view/filebrowser/download.htm delete mode 100644 lienol/luci-app-filebrowser/luasrc/view/filebrowser/log.htm delete mode 100755 lienol/luci-app-filebrowser/luasrc/view/filebrowser/status.htm delete mode 100755 lienol/luci-app-filebrowser/po/zh-cn/filebrowser.po delete mode 100755 lienol/luci-app-filebrowser/root/etc/config/filebrowser delete mode 100755 lienol/luci-app-filebrowser/root/etc/init.d/filebrowser delete mode 100755 lienol/luci-app-filebrowser/root/etc/uci-defaults/luci-app-filebrowser delete mode 100644 lienol/luci-app-filebrowser/root/usr/share/rpcd/acl.d/luci-app-filebrowser.json delete mode 100755 lienol/luci-app-guest-wifi/Makefile delete mode 100755 lienol/luci-app-guest-wifi/luasrc/controller/guest-wifi.lua delete mode 100755 lienol/luci-app-guest-wifi/luasrc/model/cbi/guest-wifi.lua delete mode 100755 lienol/luci-app-guest-wifi/po/zh-cn/guest-wifi.po delete mode 100755 lienol/luci-app-guest-wifi/root/etc/config/guest-wifi delete mode 100755 lienol/luci-app-guest-wifi/root/etc/init.d/guest-wifi delete mode 100755 lienol/luci-app-guest-wifi/root/etc/uci-defaults/luci-app-guest-wifi delete mode 100644 lienol/luci-app-guest-wifi/root/usr/share/rpcd/acl.d/luci-app-guest-wifi.json delete mode 100755 lienol/luci-app-ipsec-vpnserver-manyusers/Makefile delete mode 100755 lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/controller/ipsec-server.lua delete mode 100755 lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/model/cbi/ipsec-server/settings.lua delete mode 100755 lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/model/cbi/ipsec-server/users.lua delete mode 100755 lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/view/ipsec-server/index.htm delete mode 100755 lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/view/ipsec-server/status.htm delete mode 100755 lienol/luci-app-ipsec-vpnserver-manyusers/po/zh-cn/ipsec.po delete mode 100755 lienol/luci-app-ipsec-vpnserver-manyusers/root/etc/config/ipsec delete mode 100755 lienol/luci-app-ipsec-vpnserver-manyusers/root/etc/init.d/ipsecvpn delete mode 100755 lienol/luci-app-ipsec-vpnserver-manyusers/root/etc/uci-defaults/luci-app-ipsec-vpnserver-manyusers delete mode 100644 lienol/luci-app-ipsec-vpnserver-manyusers/root/usr/share/rpcd/acl.d/luci-app-ipsec-vpnserver-manyusers.json delete mode 100644 lienol/luci-app-kodexplorer/LICENSE delete mode 100755 lienol/luci-app-kodexplorer/Makefile delete mode 100755 lienol/luci-app-kodexplorer/luasrc/controller/kodexplorer.lua delete mode 100755 lienol/luci-app-kodexplorer/luasrc/model/cbi/kodexplorer/api.lua delete mode 100755 lienol/luci-app-kodexplorer/luasrc/model/cbi/kodexplorer/settings.lua delete mode 100755 lienol/luci-app-kodexplorer/luasrc/view/kodexplorer/status.htm delete mode 100755 lienol/luci-app-kodexplorer/luasrc/view/kodexplorer/version.htm delete mode 100755 lienol/luci-app-kodexplorer/po/zh-cn/kodexplorer.po delete mode 100755 lienol/luci-app-kodexplorer/root/etc/config/kodexplorer delete mode 100755 lienol/luci-app-kodexplorer/root/etc/init.d/kodexplorer delete mode 100644 lienol/luci-app-kodexplorer/root/etc/kodexplorer/nginx.conf.template delete mode 100644 lienol/luci-app-kodexplorer/root/etc/kodexplorer/php-fpm.conf.template delete mode 100644 lienol/luci-app-kodexplorer/root/etc/kodexplorer/php.ini.template delete mode 100755 lienol/luci-app-kodexplorer/root/etc/uci-defaults/luci-app-kodexplorer delete mode 100644 lienol/luci-app-kodexplorer/root/usr/share/rpcd/acl.d/luci-app-kodexplorer.json delete mode 100644 lienol/luci-app-nginx-pingos/Makefile delete mode 100644 lienol/luci-app-nginx-pingos/luasrc/controller/pingos.lua delete mode 100644 lienol/luci-app-nginx-pingos/luasrc/model/cbi/pingos.lua delete mode 100644 lienol/luci-app-nginx-pingos/luasrc/view/pingos/status.htm delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-client-module/COPYRIGHT delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-client-module/config delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-client-module/ngx_client.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-client-module/ngx_client.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-client-module/ngx_http_client.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-client-module/ngx_http_client.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/config delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/nginx.conf delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/ngx_client_stat_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/ngx_client_test_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/ngx_http_client_test_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/tcpserver.go delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/COPYRIGHT delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/README.md delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/config delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/doc/ngx-http-broadcast-module.md delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/doc/ngx-stream-zone-module.md delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_event_multiport_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_http_broadcast_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_http_inner_proxy_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_multiport.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_multiport_misc.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_process_slot_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_stream_zone_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_stream_zone_module.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/config delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/nginx.conf delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/ngx_multiport_test_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/ngx_stream_zone_test_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/ngx_test_macro.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/AUTHORS delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/LICENSE delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/config delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/dash/ngx_rtmp_dash_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/dash/ngx_rtmp_mp4.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/dash/ngx_rtmp_mp4.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/hls/ngx_rtmp_hls_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/hls/ngx_rtmp_mpegts.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/hls/ngx_rtmp_mpegts.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/http/ngx_http_flv_live_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/http/ngx_http_set_header.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/http/ngx_http_set_header.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_hls_http_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_hls_live_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_hls_live_module.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_gop_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_gop_module.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_http_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_live_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_live_module.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_record.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_record.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_httpflv.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_inner.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_rtmp.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_simple.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_static.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_netcall.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_netcall.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_access_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_amf.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_amf.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_bandwidth.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_bandwidth.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_bitop.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_bitop.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_cmd_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_cmd_module.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_codec_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_codec_module.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_control_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_core_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_dynamic.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_dynamic.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_eval.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_eval.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_exec_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_gop_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_handler.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_handshake.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_init.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_limit_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_live_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_live_module.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_log_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_monitor_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_monitor_module.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_notify_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_notify_module.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_proxy_protocol.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_proxy_protocol.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_receive.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_record_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_record_module.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_send.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_shared_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_stat_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_streams.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_sys_stat_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_variables.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_variables.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_version.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/COPYRIGHT delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/README.md delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/config delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-dynamic-conf-module.md delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-dynamic-resolver-module.md delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-event-resolver-module.md delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-event-timer-module.md delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-map.md delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-poold.md delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-rbuf.md delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-toolkit-misc.md delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_dynamic_conf.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_dynamic_conf.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_dynamic_resolver.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_dynamic_resolver.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_event_resolver.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_event_resolver.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_event_timer_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_event_timer_module.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_http_dynamic.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_http_dynamic.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_http_trace_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_map.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_map.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_poold.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_poold.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_rbuf.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_rbuf.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_timerd.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_timerd.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_toolkit_misc.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_toolkit_misc.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/config delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/dns_install.sh delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/md5testfile delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/named.conf delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/nginx.conf delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/nginx_dynamic.conf delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_dynamic_conf_test_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_dynamic_resolver_test_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_event_resolver_test_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_event_timer_test_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_http_dynamic_test_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_map_test_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_poold_test_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_rbuf_test_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_test_macro.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_timerd_test_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_toolkit_misc_test_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/test.com.zone delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/test1.com.zone delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-ts-module/LICENSE delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-ts-module/README.rst delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-ts-module/config delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_http_ts_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_stream_ts_module.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_aac.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_aac.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_avc.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_avc.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_dash.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_dash.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_dash_mp4.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_hls.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_hls.h delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_stream.c delete mode 100644 lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_stream.h delete mode 100644 lienol/luci-app-nginx-pingos/patches/101-feature_test_fix.patch delete mode 100644 lienol/luci-app-nginx-pingos/patches/102-sizeof_test_fix.patch delete mode 100644 lienol/luci-app-nginx-pingos/patches/103-sys_nerr.patch delete mode 100644 lienol/luci-app-nginx-pingos/patches/104-endianness_fix.patch delete mode 100644 lienol/luci-app-nginx-pingos/patches/200-config.patch delete mode 100644 lienol/luci-app-nginx-pingos/patches/201-ignore-invalid-options.patch delete mode 100644 lienol/luci-app-nginx-pingos/po/zh-cn/pingos.po delete mode 100644 lienol/luci-app-nginx-pingos/root/etc/config/pingos delete mode 100644 lienol/luci-app-nginx-pingos/root/etc/init.d/pingos delete mode 100644 lienol/luci-app-nginx-pingos/root/etc/pingos.template delete mode 100644 lienol/luci-app-nginx-pingos/root/etc/uci-defaults/luci-app-nginx-pingos delete mode 100644 lienol/luci-app-nginx-pingos/root/resource/conf-template/nginx.conf delete mode 100644 lienol/luci-app-nginx-pingos/root/resource/crossdomain.xml delete mode 100644 lienol/luci-app-nginx-pingos/root/resource/stat.xsl delete mode 100644 lienol/luci-app-nginx-pingos/root/usr/share/rpcd/acl.d/luci-app-nginx-pingos.json delete mode 100644 lienol/luci-app-passwall/LICENSE delete mode 100644 lienol/luci-app-passwall/Makefile delete mode 100644 lienol/luci-app-passwall/README.md delete mode 100644 lienol/luci-app-passwall/luasrc/controller/passwall.lua delete mode 100644 lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/api.lua delete mode 100644 lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/brook.lua delete mode 100644 lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_naiveproxy.lua delete mode 100644 lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_shadowsocks.lua delete mode 100644 lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_v2ray.lua delete mode 100644 lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_v2ray_proto.lua delete mode 100644 lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/kcptun.lua delete mode 100644 lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/trojan_go.lua delete mode 100644 lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/v2ray.lua delete mode 100644 lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/acl.lua delete mode 100644 lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/app_update.lua delete mode 100644 lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/auto_switch.lua delete mode 100644 lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua delete mode 100644 lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/log.lua delete mode 100644 lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/node_list.lua delete mode 100644 lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe.lua delete mode 100644 lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/rule.lua delete mode 100644 lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/rule_list.lua delete mode 100644 lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/shunt_rules.lua delete mode 100644 lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/app.lua delete mode 100644 lienol/luci-app-passwall/luasrc/view/passwall/global/footer.htm delete mode 100644 lienol/luci-app-passwall/luasrc/view/passwall/global/status.htm delete mode 100644 lienol/luci-app-passwall/luasrc/view/passwall/global/tips.htm delete mode 100644 lienol/luci-app-passwall/luasrc/view/passwall/haproxy/status.htm delete mode 100644 lienol/luci-app-passwall/luasrc/view/passwall/node_list/link_add_node.htm delete mode 100644 lienol/luci-app-passwall/luasrc/view/passwall/rule/rule_version.htm delete mode 100644 lienol/luci-app-passwall/luasrc/view/passwall/server/log.htm delete mode 100644 lienol/luci-app-passwall/luasrc/view/passwall/server/users_list_status.htm delete mode 100644 lienol/luci-app-passwall/root/etc/config/passwall delete mode 100755 lienol/luci-app-passwall/root/etc/init.d/passwall delete mode 100755 lienol/luci-app-passwall/root/etc/init.d/passwall_server delete mode 100755 lienol/luci-app-passwall/root/usr/share/passwall/app.sh delete mode 100755 lienol/luci-app-passwall/root/usr/share/passwall/iptables.sh delete mode 100755 lienol/luci-app-passwall/root/usr/share/passwall/monitor.sh delete mode 100644 lienol/luci-app-passwall/root/usr/share/passwall/rule_update.lua delete mode 100644 lienol/luci-app-passwall/root/usr/share/passwall/rules/adblock.conf delete mode 100644 lienol/luci-app-passwall/root/usr/share/passwall/rules/direct_host delete mode 100644 lienol/luci-app-passwall/root/usr/share/passwall/rules/gfwlist.conf delete mode 100644 lienol/luci-app-passwall/root/usr/share/passwall/rules/proxy_host delete mode 100644 lienol/luci-app-passwall/root/usr/share/passwall/subscribe.lua delete mode 100755 lienol/luci-app-passwall/root/usr/share/passwall/test.sh delete mode 100755 lienol/luci-app-pppoe-relay/Makefile delete mode 100755 lienol/luci-app-pppoe-relay/luasrc/controller/pppoe-relay.lua delete mode 100755 lienol/luci-app-pppoe-relay/luasrc/model/cbi/pppoe-relay.lua delete mode 100755 lienol/luci-app-pppoe-relay/luasrc/view/pppoe-relay/ajax.htm delete mode 100755 lienol/luci-app-pppoe-relay/luasrc/view/pppoe-relay/status.htm delete mode 100755 lienol/luci-app-pppoe-relay/po/zh-cn/pppoe-relay.po delete mode 100755 lienol/luci-app-pppoe-relay/root/etc/config/pppoe-relay delete mode 100755 lienol/luci-app-pppoe-relay/root/etc/init.d/pppoe-relay delete mode 100755 lienol/luci-app-pppoe-relay/root/etc/uci-defaults/luci-app-pppoe-relay delete mode 100644 lienol/luci-app-pppoe-relay/root/usr/share/rpcd/acl.d/luci-app-pppoe-relay.json delete mode 100755 lienol/luci-app-pppoe-server/Makefile delete mode 100755 lienol/luci-app-pppoe-server/luasrc/controller/pppoe-server.lua delete mode 100755 lienol/luci-app-pppoe-server/luasrc/model/cbi/pppoe-server/online.lua delete mode 100755 lienol/luci-app-pppoe-server/luasrc/model/cbi/pppoe-server/settings.lua delete mode 100755 lienol/luci-app-pppoe-server/luasrc/model/cbi/pppoe-server/users.lua delete mode 100755 lienol/luci-app-pppoe-server/luasrc/view/pppoe-server/index.htm delete mode 100755 lienol/luci-app-pppoe-server/luasrc/view/pppoe-server/status.htm delete mode 100755 lienol/luci-app-pppoe-server/po/zh-cn/pppoe-server.po delete mode 100755 lienol/luci-app-pppoe-server/root/etc/config/pppoe-server delete mode 100755 lienol/luci-app-pppoe-server/root/etc/init.d/pppoe-server delete mode 100755 lienol/luci-app-pppoe-server/root/etc/uci-defaults/luci-app-pppoe-server delete mode 100644 lienol/luci-app-pppoe-server/root/usr/share/rpcd/acl.d/luci-app-pppoe-server.json delete mode 100755 lienol/luci-app-pptp-vpnserver-manyusers/Makefile delete mode 100755 lienol/luci-app-pptp-vpnserver-manyusers/luasrc/controller/pptpd.lua delete mode 100755 lienol/luci-app-pptp-vpnserver-manyusers/luasrc/model/cbi/pptpd/online.lua delete mode 100755 lienol/luci-app-pptp-vpnserver-manyusers/luasrc/model/cbi/pptpd/settings.lua delete mode 100755 lienol/luci-app-pptp-vpnserver-manyusers/luasrc/model/cbi/pptpd/users.lua delete mode 100755 lienol/luci-app-pptp-vpnserver-manyusers/luasrc/view/pptpd/index.htm delete mode 100755 lienol/luci-app-pptp-vpnserver-manyusers/luasrc/view/pptpd/status.htm delete mode 100755 lienol/luci-app-pptp-vpnserver-manyusers/po/zh-cn/pptpd.po delete mode 100755 lienol/luci-app-pptp-vpnserver-manyusers/root/etc/config/pptpd delete mode 100755 lienol/luci-app-pptp-vpnserver-manyusers/root/etc/init.d/pptpd delete mode 100755 lienol/luci-app-pptp-vpnserver-manyusers/root/etc/uci-defaults/luci-app-pptp-vpnserver-manyusers delete mode 100644 lienol/luci-app-pptp-vpnserver-manyusers/root/usr/share/rpcd/acl.d/luci-app-pptp-vpnserver-manyusers.json delete mode 100755 lienol/luci-app-ramfree/Makefile delete mode 100755 lienol/luci-app-ramfree/luasrc/controller/release_ram.lua delete mode 100755 lienol/luci-app-ramfree/po/zh-cn/release_ram.po delete mode 100644 lienol/luci-app-socat/Makefile delete mode 100644 lienol/luci-app-socat/luasrc/controller/socat.lua delete mode 100644 lienol/luci-app-socat/luasrc/model/cbi/socat/config.lua delete mode 100644 lienol/luci-app-socat/luasrc/model/cbi/socat/index.lua delete mode 100644 lienol/luci-app-socat/luasrc/view/socat/list_status.htm delete mode 100644 lienol/luci-app-socat/luasrc/view/socat/status.htm delete mode 100644 lienol/luci-app-socat/po/zh-cn/socat.po delete mode 100644 lienol/luci-app-socat/root/etc/config/socat delete mode 100755 lienol/luci-app-socat/root/etc/init.d/socat delete mode 100755 lienol/luci-app-socat/root/etc/uci-defaults/luci-app-socat delete mode 100644 lienol/luci-app-socat/root/usr/share/rpcd/acl.d/luci-app-socat.json delete mode 100755 lienol/luci-app-softethervpn/Makefile delete mode 100755 lienol/luci-app-softethervpn/luasrc/controller/softethervpn.lua delete mode 100755 lienol/luci-app-softethervpn/luasrc/model/cbi/softethervpn.lua delete mode 100755 lienol/luci-app-softethervpn/luasrc/view/softethervpn/index.htm delete mode 100755 lienol/luci-app-softethervpn/luasrc/view/softethervpn/status.htm delete mode 100755 lienol/luci-app-softethervpn/po/zh-cn/softethervpn.po delete mode 100755 lienol/luci-app-softethervpn/root/etc/config/softethervpn delete mode 100755 lienol/luci-app-softethervpn/root/etc/init.d/softethervpn delete mode 100755 lienol/luci-app-softethervpn/root/etc/uci-defaults/luci-app-softethervpn delete mode 100644 lienol/luci-app-softethervpn/root/usr/share/rpcd/acl.d/luci-app-softethervpn.json delete mode 100644 lienol/luci-app-ssr-mudb-server/LICENSE delete mode 100644 lienol/luci-app-ssr-mudb-server/Makefile delete mode 100644 lienol/luci-app-ssr-mudb-server/htdocs/luci-static/resources/vue.min.js delete mode 100644 lienol/luci-app-ssr-mudb-server/luasrc/controller/ssr_mudb_server.lua delete mode 100644 lienol/luci-app-ssr-mudb-server/luasrc/model/cbi/ssr_mudb_server/index.lua delete mode 100644 lienol/luci-app-ssr-mudb-server/luasrc/view/ssr_mudb_server/status.htm delete mode 100644 lienol/luci-app-ssr-mudb-server/luasrc/view/ssr_mudb_server/user.htm delete mode 100644 lienol/luci-app-ssr-mudb-server/luasrc/view/ssr_mudb_server/users.htm delete mode 100644 lienol/luci-app-ssr-mudb-server/po/zh-cn/ssr_mudb_server.po delete mode 100644 lienol/luci-app-ssr-mudb-server/root/etc/config/ssr_mudb_server delete mode 100644 lienol/luci-app-ssr-mudb-server/root/etc/config/ssr_mudb_server.json delete mode 100755 lienol/luci-app-ssr-mudb-server/root/etc/init.d/ssr_mudb_server delete mode 100644 lienol/luci-app-ssr-mudb-server/root/etc/uci-defaults/luci-app-ssr-mudb-server delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/rpcd/acl.d/luci-app-ssr-mudb-server.json delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/.travis.yml delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/CHANGES delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/CONTRIBUTING.md delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/Dockerfile delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/MANIFEST.in delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/apiconfig.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/asyncmgr.py delete mode 100755 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/clear_traffic_all_users.sh delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/config.json delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/configloader.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/db_transfer.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/firewall.lua delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/importloader.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/initcfg.bat delete mode 100755 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/initcfg.sh delete mode 100755 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/initmudbjson.sh delete mode 100755 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/logrun.sh delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/mudb.json delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/mujson_mgr.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/mysql.json delete mode 100755 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/run.sh delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/server.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/server_pool.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/setup.py delete mode 100755 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/setup_cymysql.sh delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/__init__.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/asyncdns.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/common.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/__init__.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/ctypes_libsodium.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/ctypes_openssl.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/openssl.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/rc4_md5.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/sodium.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/table.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/util.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/daemon.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/encrypt.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/eventloop.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/local.py delete mode 100755 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/logrun.sh delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/lru_cache.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/manager.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfs.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/__init__.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/auth.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/auth_chain.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/http_simple.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/obfs_tls.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/plain.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/verify.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/ordereddict.py delete mode 100755 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/run.sh delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/server.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/shell.py delete mode 100755 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/stop.sh delete mode 100755 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/tail.sh delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/tcprelay.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/udprelay.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/user.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/version.py delete mode 100755 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/stop.sh delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/switchrule.py delete mode 100755 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tail.sh delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/aes-cfb1.json delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/aes-cfb8.json delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/aes-ctr.json delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/aes.json delete mode 100755 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/assert.sh delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/chacha20.json delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/client-multi-server-ip.json delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/coverage_server.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/fastopen.json delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/ipv6-client-side.json delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/ipv6.json delete mode 100755 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/jenkins.sh delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/libsodium/install.sh delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/nose_plugin.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/rc4-md5.json delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/salsa20-ctr.json delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/salsa20.json delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/server-multi-passwd-client-side.json delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/server-multi-passwd-table.json delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/server-multi-passwd.json delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/server-multi-ports.json delete mode 100755 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/setup_tc.sh delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/socksify/install.sh delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/socksify/socks.conf delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/table.json delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test.py delete mode 100755 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_command.sh delete mode 100755 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_daemon.sh delete mode 100755 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_large_file.sh delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_udp_src.py delete mode 100755 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_udp_src.sh delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/workers.json delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/user-config.json delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/userapiconfig.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/usermysql.json delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/utils/README.md delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/utils/autoban.py delete mode 100644 lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/utils/fail2ban/shadowsocks.conf delete mode 100644 lienol/luci-app-timecontrol/Makefile delete mode 100644 lienol/luci-app-timecontrol/luasrc/controller/timecontrol.lua delete mode 100644 lienol/luci-app-timecontrol/luasrc/model/cbi/timecontrol.lua delete mode 100644 lienol/luci-app-timecontrol/luasrc/view/timecontrol/index.htm delete mode 100644 lienol/luci-app-timecontrol/luasrc/view/timecontrol/timecontrol.htm delete mode 100644 lienol/luci-app-timecontrol/po/zh-cn/timecontrol.po delete mode 100644 lienol/luci-app-timecontrol/root/etc/config/timecontrol delete mode 100755 lienol/luci-app-timecontrol/root/etc/init.d/timecontrol delete mode 100755 lienol/luci-app-timecontrol/root/etc/uci-defaults/luci-app-timecontrol delete mode 100644 lienol/luci-app-timecontrol/root/usr/share/rpcd/acl.d/luci-app-timecontrol.json create mode 100644 luci-app-passwall/Makefile create mode 100644 luci-app-passwall/luasrc/controller/passwall.lua create mode 100755 luci-app-passwall/luasrc/model/cbi/passwall/api/api.lua create mode 100644 luci-app-passwall/luasrc/model/cbi/passwall/api/brook.lua create mode 100644 luci-app-passwall/luasrc/model/cbi/passwall/api/gen_hysteria.lua create mode 100644 luci-app-passwall/luasrc/model/cbi/passwall/api/gen_naiveproxy.lua create mode 100644 luci-app-passwall/luasrc/model/cbi/passwall/api/gen_shadowsocks.lua rename {lienol/luci-app-passwall => luci-app-passwall}/luasrc/model/cbi/passwall/api/gen_trojan.lua (61%) create mode 100644 luci-app-passwall/luasrc/model/cbi/passwall/api/gen_v2ray.lua create mode 100644 luci-app-passwall/luasrc/model/cbi/passwall/api/gen_v2ray_proto.lua create mode 100644 luci-app-passwall/luasrc/model/cbi/passwall/api/hysteria.lua create mode 100644 luci-app-passwall/luasrc/model/cbi/passwall/api/kcptun.lua create mode 100644 luci-app-passwall/luasrc/model/cbi/passwall/api/trojan_go.lua create mode 100644 luci-app-passwall/luasrc/model/cbi/passwall/api/v2ray.lua create mode 100644 luci-app-passwall/luasrc/model/cbi/passwall/api/xray.lua create mode 100644 luci-app-passwall/luasrc/model/cbi/passwall/client/acl.lua create mode 100644 luci-app-passwall/luasrc/model/cbi/passwall/client/acl_config.lua create mode 100644 luci-app-passwall/luasrc/model/cbi/passwall/client/app_update.lua create mode 100644 luci-app-passwall/luasrc/model/cbi/passwall/client/auto_switch.lua create mode 100644 luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua rename {lienol/luci-app-passwall => luci-app-passwall}/luasrc/model/cbi/passwall/client/haproxy.lua (55%) create mode 100644 luci-app-passwall/luasrc/model/cbi/passwall/client/log.lua rename {lienol/luci-app-passwall => luci-app-passwall}/luasrc/model/cbi/passwall/client/node_config.lua (53%) create mode 100644 luci-app-passwall/luasrc/model/cbi/passwall/client/node_list.lua create mode 100644 luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe.lua create mode 100644 luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe_config.lua rename {lienol/luci-app-passwall => luci-app-passwall}/luasrc/model/cbi/passwall/client/other.lua (69%) create mode 100644 luci-app-passwall/luasrc/model/cbi/passwall/client/rule.lua create mode 100644 luci-app-passwall/luasrc/model/cbi/passwall/client/rule_list.lua create mode 100644 luci-app-passwall/luasrc/model/cbi/passwall/client/shunt_rules.lua create mode 100755 luci-app-passwall/luasrc/model/cbi/passwall/server/api/app.lua create mode 100644 luci-app-passwall/luasrc/model/cbi/passwall/server/api/hysteria.lua rename {lienol/luci-app-passwall => luci-app-passwall}/luasrc/model/cbi/passwall/server/api/shadowsocks.lua (100%) rename {lienol/luci-app-passwall => luci-app-passwall}/luasrc/model/cbi/passwall/server/api/trojan.lua (71%) rename {lienol/luci-app-passwall => luci-app-passwall}/luasrc/model/cbi/passwall/server/api/v2ray.lua (61%) rename {lienol/luci-app-passwall => luci-app-passwall}/luasrc/model/cbi/passwall/server/index.lua (71%) rename {lienol/luci-app-passwall => luci-app-passwall}/luasrc/model/cbi/passwall/server/user.lua (60%) rename {lienol/luci-app-passwall => luci-app-passwall}/luasrc/view/passwall/app_update/brook_version.htm (62%) create mode 100644 luci-app-passwall/luasrc/view/passwall/app_update/hysteria_version.htm rename {lienol/luci-app-passwall => luci-app-passwall}/luasrc/view/passwall/app_update/kcptun_version.htm (70%) rename {lienol/luci-app-passwall => luci-app-passwall}/luasrc/view/passwall/app_update/trojan_go_version.htm (68%) rename {lienol/luci-app-passwall => luci-app-passwall}/luasrc/view/passwall/app_update/v2ray_version.htm (69%) create mode 100644 luci-app-passwall/luasrc/view/passwall/app_update/xray_version.htm create mode 100644 luci-app-passwall/luasrc/view/passwall/auto_switch/footer.htm create mode 100644 luci-app-passwall/luasrc/view/passwall/global/faq.htm create mode 100644 luci-app-passwall/luasrc/view/passwall/global/footer.htm create mode 100644 luci-app-passwall/luasrc/view/passwall/global/status.htm rename {lienol/luci-app-passwall => luci-app-passwall}/luasrc/view/passwall/global/status2.htm (54%) create mode 100644 luci-app-passwall/luasrc/view/passwall/haproxy/status.htm rename {lienol/luci-app-passwall => luci-app-passwall}/luasrc/view/passwall/log/log.htm (72%) create mode 100644 luci-app-passwall/luasrc/view/passwall/node_list/link_add_node.htm rename {lienol/luci-app-passwall => luci-app-passwall}/luasrc/view/passwall/node_list/link_share_man.htm (51%) rename {lienol/luci-app-passwall => luci-app-passwall}/luasrc/view/passwall/node_list/node_list.htm (65%) create mode 100644 luci-app-passwall/luasrc/view/passwall/rule/rule_version.htm rename {obsolete/luci-app-brook-server/luasrc/view/brook_server => luci-app-passwall/luasrc/view/passwall/server}/log.htm (74%) create mode 100644 luci-app-passwall/luasrc/view/passwall/server/users_list_status.htm rename {lienol/luci-app-passwall => luci-app-passwall}/po/zh-cn/passwall.po (54%) create mode 120000 luci-app-passwall/po/zh_Hans rename {lienol/luci-app-passwall => luci-app-passwall}/root/etc/config/passwall_server (100%) create mode 100755 luci-app-passwall/root/etc/init.d/passwall create mode 100755 luci-app-passwall/root/etc/init.d/passwall_server rename lienol/luci-app-passwall/root/etc/uci-defaults/luci-app-passwall => luci-app-passwall/root/etc/uci-defaults/luci-passwall (73%) create mode 100644 luci-app-passwall/root/usr/share/passwall/0_default_config create mode 100755 luci-app-passwall/root/usr/share/passwall/app.sh create mode 100755 luci-app-passwall/root/usr/share/passwall/helper_dnsmasq.sh create mode 100755 luci-app-passwall/root/usr/share/passwall/helper_smartdns.sh create mode 100755 luci-app-passwall/root/usr/share/passwall/iptables.sh create mode 100755 luci-app-passwall/root/usr/share/passwall/monitor.sh create mode 100755 luci-app-passwall/root/usr/share/passwall/rule_update.lua create mode 100644 luci-app-passwall/root/usr/share/passwall/rules/block_host create mode 100644 luci-app-passwall/root/usr/share/passwall/rules/block_ip rename {lienol/luci-app-passwall => luci-app-passwall}/root/usr/share/passwall/rules/chnlist (81%) rename {lienol/luci-app-passwall => luci-app-passwall}/root/usr/share/passwall/rules/chnroute (98%) rename {lienol/luci-app-passwall => luci-app-passwall}/root/usr/share/passwall/rules/chnroute6 (95%) create mode 100644 luci-app-passwall/root/usr/share/passwall/rules/direct_host rename {lienol/luci-app-passwall => luci-app-passwall}/root/usr/share/passwall/rules/direct_ip (56%) create mode 100644 luci-app-passwall/root/usr/share/passwall/rules/gfwlist create mode 100644 luci-app-passwall/root/usr/share/passwall/rules/lanlist_ipv4 create mode 100644 luci-app-passwall/root/usr/share/passwall/rules/lanlist_ipv6 create mode 100644 luci-app-passwall/root/usr/share/passwall/rules/proxy_host rename {lienol/luci-app-passwall => luci-app-passwall}/root/usr/share/passwall/rules/proxy_ip (61%) create mode 100755 luci-app-passwall/root/usr/share/passwall/subscribe.lua create mode 100755 luci-app-passwall/root/usr/share/passwall/test.sh rename {lienol/luci-app-passwall => luci-app-passwall}/root/usr/share/rpcd/acl.d/luci-app-passwall.json (100%) create mode 100644 microsocks/Makefile create mode 100644 naiveproxy/Makefile create mode 100755 naiveproxy/src/init_env.sh delete mode 100644 obsolete/luci-app-brook-server/LICENSE delete mode 100644 obsolete/luci-app-brook-server/Makefile delete mode 100644 obsolete/luci-app-brook-server/luasrc/controller/brook_server.lua delete mode 100644 obsolete/luci-app-brook-server/luasrc/model/cbi/brook_server/api/brook.lua delete mode 100644 obsolete/luci-app-brook-server/luasrc/model/cbi/brook_server/config.lua delete mode 100644 obsolete/luci-app-brook-server/luasrc/model/cbi/brook_server/index.lua delete mode 100644 obsolete/luci-app-brook-server/luasrc/view/brook_server/brook.htm delete mode 100644 obsolete/luci-app-brook-server/luasrc/view/brook_server/users_list_status.htm delete mode 100644 obsolete/luci-app-brook-server/luasrc/view/brook_server/users_status.htm delete mode 100644 obsolete/luci-app-brook-server/po/zh-cn/brook_server.po delete mode 100644 obsolete/luci-app-brook-server/root/etc/config/brook_server delete mode 100755 obsolete/luci-app-brook-server/root/etc/init.d/brook_server delete mode 100755 obsolete/luci-app-brook-server/root/etc/uci-defaults/luci-app-brook-server delete mode 100644 obsolete/luci-app-brook-server/root/usr/share/rpcd/acl.d/luci-app-brook-server.json delete mode 100644 obsolete/luci-app-ssr-libev-server/Makefile delete mode 100644 obsolete/luci-app-ssr-libev-server/luasrc/controller/ssr_libev_server.lua delete mode 100644 obsolete/luci-app-ssr-libev-server/luasrc/model/cbi/ssr_libev_server/config.lua delete mode 100644 obsolete/luci-app-ssr-libev-server/luasrc/model/cbi/ssr_libev_server/index.lua delete mode 100644 obsolete/luci-app-ssr-libev-server/luasrc/view/ssr_libev_server/users_list_status.htm delete mode 100644 obsolete/luci-app-ssr-libev-server/luasrc/view/ssr_libev_server/users_status.htm delete mode 100644 obsolete/luci-app-ssr-libev-server/po/zh-cn/ssr_libev_server.po delete mode 100644 obsolete/luci-app-ssr-libev-server/root/etc/config/ssr_libev_server delete mode 100755 obsolete/luci-app-ssr-libev-server/root/etc/init.d/ssr_libev_server delete mode 100755 obsolete/luci-app-ssr-libev-server/root/etc/uci-defaults/luci-app-ssr-libev-server delete mode 100644 obsolete/luci-app-ssr-libev-server/root/usr/share/rpcd/acl.d/luci-app-ssr-libev-server.json delete mode 100644 obsolete/luci-app-trojan-server/LICENSE delete mode 100644 obsolete/luci-app-trojan-server/Makefile delete mode 100644 obsolete/luci-app-trojan-server/luasrc/controller/trojan_server.lua delete mode 100644 obsolete/luci-app-trojan-server/luasrc/model/cbi/trojan_server/api/gen_trojan_config_file.lua delete mode 100644 obsolete/luci-app-trojan-server/luasrc/model/cbi/trojan_server/config.lua delete mode 100644 obsolete/luci-app-trojan-server/luasrc/model/cbi/trojan_server/index.lua delete mode 100644 obsolete/luci-app-trojan-server/luasrc/view/trojan_server/log.htm delete mode 100644 obsolete/luci-app-trojan-server/luasrc/view/trojan_server/users_list_status.htm delete mode 100644 obsolete/luci-app-trojan-server/luasrc/view/trojan_server/users_status.htm delete mode 100644 obsolete/luci-app-trojan-server/po/zh-cn/trojan_server.po delete mode 100644 obsolete/luci-app-trojan-server/root/etc/config/trojan_server delete mode 100755 obsolete/luci-app-trojan-server/root/etc/init.d/trojan_server delete mode 100755 obsolete/luci-app-trojan-server/root/etc/uci-defaults/luci-app-trojan-server delete mode 100644 obsolete/luci-app-trojan-server/root/usr/share/rpcd/acl.d/luci-app-trojan-server.json delete mode 100644 obsolete/luci-app-v2ray-server/LICENSE delete mode 100644 obsolete/luci-app-v2ray-server/Makefile delete mode 100644 obsolete/luci-app-v2ray-server/luasrc/controller/v2ray_server.lua delete mode 100644 obsolete/luci-app-v2ray-server/luasrc/model/cbi/v2ray_server/api/app.lua delete mode 100644 obsolete/luci-app-v2ray-server/luasrc/model/cbi/v2ray_server/api/gen_config.lua delete mode 100644 obsolete/luci-app-v2ray-server/luasrc/model/cbi/v2ray_server/api/v2ray.lua delete mode 100644 obsolete/luci-app-v2ray-server/luasrc/model/cbi/v2ray_server/index.lua delete mode 100644 obsolete/luci-app-v2ray-server/luasrc/model/cbi/v2ray_server/user.lua delete mode 100644 obsolete/luci-app-v2ray-server/luasrc/view/v2ray_server/log.htm delete mode 100644 obsolete/luci-app-v2ray-server/luasrc/view/v2ray_server/users_list_status.htm delete mode 100644 obsolete/luci-app-v2ray-server/luasrc/view/v2ray_server/v2ray.htm delete mode 100644 obsolete/luci-app-v2ray-server/po/zh-cn/v2ray_server.po delete mode 100644 obsolete/luci-app-v2ray-server/root/etc/config/v2ray_server delete mode 100755 obsolete/luci-app-v2ray-server/root/etc/init.d/v2ray_server delete mode 100755 obsolete/luci-app-v2ray-server/root/etc/uci-defaults/luci-app-v2ray-server delete mode 100644 obsolete/luci-app-v2ray-server/root/usr/share/rpcd/acl.d/luci-app-v2ray-server.json delete mode 100755 others/luci-app-control-timewol/Makefile delete mode 100755 others/luci-app-control-timewol/luasrc/controller/timewol.lua delete mode 100755 others/luci-app-control-timewol/luasrc/model/cbi/timewol.lua delete mode 100755 others/luci-app-control-timewol/luasrc/view/timewol/index.htm delete mode 100755 others/luci-app-control-timewol/luasrc/view/timewol/timewol.htm delete mode 100755 others/luci-app-control-timewol/po/zh-cn/timewol.po delete mode 100755 others/luci-app-control-timewol/root/etc/config/timewol delete mode 100755 others/luci-app-control-timewol/root/etc/init.d/timewol delete mode 100755 others/luci-app-control-timewol/root/etc/uci-defaults/luci-app-control-timewol delete mode 100644 others/luci-app-control-timewol/root/usr/share/rpcd/acl.d/luci-app-control-timewol.json delete mode 100755 others/luci-app-control-webrestriction/Makefile delete mode 100755 others/luci-app-control-webrestriction/luasrc/controller/webrestriction.lua delete mode 100755 others/luci-app-control-webrestriction/luasrc/model/cbi/webrestriction.lua delete mode 100755 others/luci-app-control-webrestriction/luasrc/view/webrestriction/index.htm delete mode 100755 others/luci-app-control-webrestriction/luasrc/view/webrestriction/webrestriction.htm delete mode 100755 others/luci-app-control-webrestriction/po/zh-cn/webrestriction.po delete mode 100755 others/luci-app-control-webrestriction/root/etc/config/webrestriction delete mode 100755 others/luci-app-control-webrestriction/root/etc/init.d/webrestriction delete mode 100755 others/luci-app-control-webrestriction/root/etc/uci-defaults/luci-app-control-webrestriction delete mode 100644 others/luci-app-control-webrestriction/root/usr/share/rpcd/acl.d/luci-app-control-webrestriction.json delete mode 100755 others/luci-app-control-weburl/Makefile delete mode 100755 others/luci-app-control-weburl/luasrc/controller/weburl.lua delete mode 100755 others/luci-app-control-weburl/luasrc/model/cbi/weburl.lua delete mode 100755 others/luci-app-control-weburl/luasrc/view/weburl/index.htm delete mode 100755 others/luci-app-control-weburl/luasrc/view/weburl/weburl.htm delete mode 100755 others/luci-app-control-weburl/po/zh-cn/weburl.po delete mode 100755 others/luci-app-control-weburl/root/etc/config/weburl delete mode 100755 others/luci-app-control-weburl/root/etc/init.d/weburl delete mode 100755 others/luci-app-control-weburl/root/etc/uci-defaults/luci-app-control-weburl delete mode 100644 others/luci-app-control-weburl/root/usr/share/rpcd/acl.d/luci-app-control-weburl.json delete mode 100755 others/luci-app-kcptun/LICENSE delete mode 100755 others/luci-app-kcptun/Makefile delete mode 100755 others/luci-app-kcptun/README.md delete mode 100755 others/luci-app-kcptun/luasrc/controller/kcptun.lua delete mode 100755 others/luci-app-kcptun/luasrc/model/cbi/kcptun/servers-detail.lua delete mode 100755 others/luci-app-kcptun/luasrc/model/cbi/kcptun/servers.lua delete mode 100755 others/luci-app-kcptun/luasrc/model/cbi/kcptun/settings.lua delete mode 100755 others/luci-app-kcptun/luasrc/model/kcptun.lua delete mode 100755 others/luci-app-kcptun/luasrc/view/kcptun/button.htm delete mode 100755 others/luci-app-kcptun/luasrc/view/kcptun/log_view.htm delete mode 100755 others/luci-app-kcptun/luasrc/view/kcptun/status.htm delete mode 100755 others/luci-app-kcptun/po/templates/kcptun.pot delete mode 100755 others/luci-app-kcptun/po/zh-cn/kcptun.po delete mode 100755 others/luci-app-kcptun/root/etc/config/kcptun delete mode 100755 others/luci-app-kcptun/root/etc/init.d/kcptun delete mode 100755 others/luci-app-kcptun/root/etc/uci-defaults/40_luci-kcptun delete mode 100644 others/luci-app-kcptun/root/usr/share/rpcd/acl.d/luci-app-kcptun.json delete mode 100755 others/luci-app-syncthing/Makefile delete mode 100755 others/luci-app-syncthing/luasrc/controller/syncthing.lua delete mode 100755 others/luci-app-syncthing/luasrc/model/cbi/syncthing.lua delete mode 100755 others/luci-app-syncthing/luasrc/view/syncthing/syncthing_status.htm delete mode 100755 others/luci-app-syncthing/po/zh-cn/syncthing.po delete mode 100755 others/luci-app-syncthing/root/etc/config/syncthing delete mode 100755 others/luci-app-syncthing/root/etc/init.d/syncthing delete mode 100755 others/luci-app-syncthing/root/etc/uci-defaults/luci-syncthing delete mode 100644 others/luci-app-syncthing/root/usr/share/rpcd/acl.d/luci-app-syncthing.json delete mode 100644 others/luci-app-verysync/Makefile delete mode 100644 others/luci-app-verysync/luasrc/controller/verysync.lua delete mode 100644 others/luci-app-verysync/luasrc/model/cbi/verysync.lua delete mode 100644 others/luci-app-verysync/luasrc/view/verysync/verysync_status.htm delete mode 100644 others/luci-app-verysync/po/zh-cn/verysync.po delete mode 100644 others/luci-app-verysync/root/etc/config/verysync delete mode 100755 others/luci-app-verysync/root/etc/init.d/verysync delete mode 100755 others/luci-app-verysync/root/etc/uci-defaults/luci-verysync delete mode 100644 others/luci-app-verysync/root/usr/share/rpcd/acl.d/luci-app-verysync.json delete mode 100755 package/brook/Makefile delete mode 100644 package/chinadns-ng/LICENSE delete mode 100644 package/chinadns-ng/Makefile delete mode 100755 package/dns2socks/Makefile delete mode 100755 package/ipt2socks/Makefile delete mode 100644 package/kcptun/Makefile delete mode 100644 package/microsocks/Makefile delete mode 100644 package/naiveproxy/Makefile delete mode 100644 package/naiveproxy/patches/001-Remove-concurrency-limit.patch delete mode 100644 package/naiveproxy/patches/100-build-add-OpenWrt-staging-libraries.patch delete mode 100644 package/naiveproxy/patches/101-build-drop-useless-deps-simd_asm.patch delete mode 100755 package/naiveproxy/src/init_env.sh delete mode 100644 package/openssl1.1/Makefile delete mode 100644 package/openssl1.1/patches/1.1.1/100-Configure-afalg-support.patch delete mode 100644 package/openssl1.1/patches/1.1.1/110-openwrt_targets.patch delete mode 100644 package/openssl1.1/patches/1.1.1/120-strip-cflags-from-binary.patch delete mode 100644 package/openssl1.1/patches/1.1.1/130-dont-build-tests-fuzz.patch delete mode 100644 package/openssl1.1/patches/1.1.1/140-allow-prefer-chacha20.patch delete mode 100755 package/shadowsocksr-libev/Makefile delete mode 100755 package/shadowsocksr-libev/patches/0001-Add-ss-server-and-ss-check.patch delete mode 100644 package/simple-obfs/LICENSE delete mode 100644 package/ssocks/Makefile delete mode 100644 package/tcping/LICENSE delete mode 100644 package/trojan-go/Makefile delete mode 100644 package/v2ray-plugin/LICENSE delete mode 100644 package/v2ray-plugin/Makefile delete mode 100644 package/v2ray/Config.in delete mode 100755 package/v2ray/Makefile delete mode 100755 package/verysync/Makefile rename {package/pdnsd-alt => pdnsd-alt}/Makefile (65%) mode change 100755 => 100644 rename {package/pdnsd-alt => pdnsd-alt}/files/pdnsd.init (100%) mode change 100755 => 100644 create mode 100644 pdnsd-alt/patches/002-fix-pdnsd-alt-build-error-within-kernel_5.15.patch create mode 100644 shadowsocks-rust/Makefile create mode 100644 shadowsocksr-libev/Makefile create mode 100644 shadowsocksr-libev/patches/0001-Add-ss-server-and-ss-check.patch rename {package/shadowsocksr-libev => shadowsocksr-libev}/patches/0002-Revert-verify_simple-and-auth_simple.patch (81%) mode change 100755 => 100644 rename {package/shadowsocksr-libev => shadowsocksr-libev}/patches/0003-Refine-Usage.patch (92%) mode change 100755 => 100644 create mode 100644 shadowsocksr-libev/patches/100-fix-gcc-10.patch rename package/shadowsocksr-libev/patches/999-Fix-Werror-sizeof-pointer-memaccess.patch => shadowsocksr-libev/patches/101-Fix-Werror-sizeof-pointer-memaccess.patch (78%) mode change 100755 => 100644 create mode 100644 shadowsocksr-libev/patches/102-Read-listening-mode-from-config.patch create mode 100644 shadowsocksr-libev/patches/999-tcp-tproxy.patch create mode 100644 shadowsocksr-libev/src/server/Makefile.am create mode 100644 shadowsocksr-libev/src/server/Makefile.in create mode 100644 shadowsocksr-libev/src/server/README.md create mode 100644 shadowsocksr-libev/src/server/acl.c create mode 100644 shadowsocksr-libev/src/server/acl.h create mode 100644 shadowsocksr-libev/src/server/auth.c create mode 100644 shadowsocksr-libev/src/server/auth.h create mode 100644 shadowsocksr-libev/src/server/base64.c create mode 100644 shadowsocksr-libev/src/server/base64.h create mode 100644 shadowsocksr-libev/src/server/cache.c create mode 100644 shadowsocksr-libev/src/server/cache.h create mode 100644 shadowsocksr-libev/src/server/check.c create mode 100644 shadowsocksr-libev/src/server/common.h create mode 100644 shadowsocksr-libev/src/server/crc32.c create mode 100644 shadowsocksr-libev/src/server/encrypt.c create mode 100644 shadowsocksr-libev/src/server/encrypt.h create mode 100644 shadowsocksr-libev/src/server/http.c create mode 100644 shadowsocksr-libev/src/server/http.h create mode 100644 shadowsocksr-libev/src/server/http_simple.c create mode 100644 shadowsocksr-libev/src/server/http_simple.h create mode 100644 shadowsocksr-libev/src/server/jconf.c create mode 100644 shadowsocksr-libev/src/server/jconf.h create mode 100644 shadowsocksr-libev/src/server/json.c create mode 100644 shadowsocksr-libev/src/server/json.h create mode 100644 shadowsocksr-libev/src/server/list.c create mode 100644 shadowsocksr-libev/src/server/list.h create mode 100644 shadowsocksr-libev/src/server/netutils.c create mode 100644 shadowsocksr-libev/src/server/netutils.h create mode 100644 shadowsocksr-libev/src/server/obfs.c create mode 100644 shadowsocksr-libev/src/server/obfs.h create mode 100644 shadowsocksr-libev/src/server/obfsutil.c create mode 100644 shadowsocksr-libev/src/server/protocol.h create mode 100644 shadowsocksr-libev/src/server/resolv.c create mode 100644 shadowsocksr-libev/src/server/resolv.h create mode 100644 shadowsocksr-libev/src/server/rule.c create mode 100644 shadowsocksr-libev/src/server/rule.h create mode 100644 shadowsocksr-libev/src/server/server.c create mode 100644 shadowsocksr-libev/src/server/server.h create mode 100644 shadowsocksr-libev/src/server/tls.c create mode 100644 shadowsocksr-libev/src/server/tls.h create mode 100644 shadowsocksr-libev/src/server/tls1.2_ticket.c create mode 100644 shadowsocksr-libev/src/server/tls1.2_ticket.h create mode 100644 shadowsocksr-libev/src/server/udprelay.c create mode 100644 shadowsocksr-libev/src/server/udprelay.h create mode 100644 shadowsocksr-libev/src/server/uthash.h create mode 100644 shadowsocksr-libev/src/server/utils.c create mode 100644 shadowsocksr-libev/src/server/utils.h create mode 100644 shadowsocksr-libev/src/server/verify.c create mode 100644 shadowsocksr-libev/src/server/verify.h rename {package/simple-obfs => simple-obfs}/Makefile (92%) create mode 100644 ssocks/Makefile rename {package/ssocks => ssocks}/patches/001-fix.patch (100%) rename {package/ssocks => ssocks}/patches/002-gcc10.patch (100%) rename {package/tcping => tcping}/Makefile (87%) mode change 100755 => 100644 create mode 100644 trojan-go/Makefile rename {package/trojan-plus => trojan-plus}/Makefile (81%) rename {package/trojan => trojan}/Makefile (79%) rename {package/trojan => trojan}/patches/001-force-openssl-version.patch (100%) create mode 100644 v2ray-core/Makefile create mode 100644 v2ray-core/files/v2ray.conf create mode 100755 v2ray-core/files/v2ray.init create mode 100644 v2ray-geodata/Makefile create mode 100644 v2ray-plugin/Makefile create mode 100644 xray-core/Makefile create mode 100644 xray-core/files/config.json.example create mode 100644 xray-core/files/vpoint_socks_vmess.json create mode 100644 xray-core/files/vpoint_vmess_freedom.json create mode 100644 xray-core/files/xray.conf create mode 100755 xray-core/files/xray.init create mode 100644 xray-plugin/Makefile diff --git a/README.md b/README.md deleted file mode 100644 index c86cac5..0000000 --- a/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# openwrt-package - -[OpenWRT-Actions](https://github.com/Lienol/openwrt-actions/actions) - -This source code is only guaranteed to compile successfully on [myopenwrt](https://github.com/Lienol/openwrt), if you are using other source code compilation, error please solve yourself. - -Please do not send junk issue and junk PR, otherwise direct ban. - -When send issue, please say in detail and operating steps. If it's important information, please send email. - -If you don't like it, please uninstall it. - -Add "src-git lienol https://github.com/Lienol/openwrt-package" to feeds.conf.default. - -```bash -./scripts/feeds clean -./scripts/feeds update -a -./scripts/feeds install -a -``` - -Or download it yourself and put it in the package folder. -make after enjoy... - -If you use Luci-19 or higher, Please selected the "luci-compat" and "luci-lib-ipkg" before compile diff --git a/brook/Makefile b/brook/Makefile new file mode 100644 index 0000000..8994f54 --- /dev/null +++ b/brook/Makefile @@ -0,0 +1,72 @@ +# SPDX-License-Identifier: GPL-3.0-only +# +# Copyright (C) 2021 ImmortalWrt.org + +include $(TOPDIR)/rules.mk + +PKG_NAME:=brook +PKG_VERSION:=20210701 +PKG_RELEASE:=$(AUTORELEASE) + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=https://codeload.github.com/txthinking/brook/tar.gz/v$(PKG_VERSION)? +PKG_HASH:=92c2253349af05ea5aa7a45cddd39ca638c732b2ffdb5066a5f03d2df40cb0b5 + +PKG_MAINTAINER:=Tianling Shen +PKG_LICENSE:=GPL-3.0 +PKG_LICENSE_FILES:=LICENSE + +PKG_BUILD_DEPENDS:=golang/host +PKG_BUILD_PARALLEL:=1 +PKG_USE_MIPS16:=0 + +PKG_CONFIG_DEPENDS:= \ + CONFIG_BROOK_COMPRESS_GOPROXY \ + CONFIG_BROOK_COMPRESS_UPX + +GO_PKG:=github.com/txthinking/brook +GO_PKG_BUILD_PKG:=github.com/txthinking/brook/cli/brook +GO_PKG_LDFLAGS:=-s -w + +include $(INCLUDE_DIR)/package.mk +include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk + +define Package/brook + SECTION:=net + CATEGORY:=Network + SUBMENU:=Web Servers/Proxies + TITLE:=A cross-platform proxy software + DEPENDS:=$(GO_ARCH_DEPENDS) +ca-bundle + URL:=https://github.com/txthinking/brook +endef + +define Package/brook/description + Brook is a cross-platform strong encryption and not detectable proxy. + Zero-Configuration. +endef + +define Package/brook/config + config BROOK_COMPRESS_GOPROXY + bool "Compiling with GOPROXY proxy" + default n + + config BROOK_COMPRESS_UPX + bool "Compress executable files with UPX" + depends on !mips64 + default n +endef + +ifeq ($(CONFIG_BROOK_COMPRESS_GOPROXY),y) + export GO111MODULE=on + export GOPROXY=https://goproxy.baidu.com +endif + +define Build/Compile + $(call GoPackage/Build/Compile) +ifeq ($(CONFIG_BROOK_COMPRESS_UPX),y) + $(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DIR)/brook +endif +endef + +$(eval $(call GoBinPackage,brook)) +$(eval $(call BuildPackage,brook)) diff --git a/chinadns-ng/Makefile b/chinadns-ng/Makefile new file mode 100644 index 0000000..8158b4d --- /dev/null +++ b/chinadns-ng/Makefile @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: GPL-3.0-only +# +# Copyright (C) 2021 ImmortalWrt.org + +include $(TOPDIR)/rules.mk + +PKG_NAME:=chinadns-ng +PKG_VERSION:=1.0-beta.25 +PKG_RELEASE:=$(AUTORELEASE) + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/zfl9/chinadns-ng.git +PKG_SOURCE_DATE:=2021-05-08 +PKG_SOURCE_VERSION:=14cc6348d67b09cae37d9bce554c89c2c0e0b265 +PKG_MIRROR_HASH:=3b66fc0888d9488e3b8e39df3016d51fae1b43325d292381e94aa3c7d2318282 + +PKG_LICENSE:=AGPL-3.0-only +PKG_LICENSE_FILES:=LICENSE +PKG_MAINTAINER:=pexcn + +PKG_BUILD_PARALLEL:=1 +PKG_INSTALL:=1 + +include $(INCLUDE_DIR)/package.mk + +define Package/chinadns-ng + SECTION:=net + CATEGORY:=Network + SUBMENU:=IP Addresses and Names + TITLE:=ChinaDNS next generation, refactoring with epoll and ipset. + URL:=https://github.com/zfl9/chinadns-ng + DEPENDS:=+ipset +endef + +define Package/chinadns-ng/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/chinadns-ng $(1)/usr/bin +endef + +$(eval $(call BuildPackage,chinadns-ng)) diff --git a/dns2socks/Makefile b/dns2socks/Makefile new file mode 100644 index 0000000..47662fa --- /dev/null +++ b/dns2socks/Makefile @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: GPL-3.0-only +# +# Copyright (C) 2021 ImmortalWrt.org + +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 + +UNZIP_CMD:=unzip -q -d $(PKG_BUILD_DIR) $(DL_DIR)/$(PKG_SOURCE) + +define Package/dns2socks + SECTION:=net + CATEGORY:=Network + SUBMENU:=IP Addresses and Names + TITLE:=DNS to SOCKS or HTTP proxy + URL:=http://dns2socks.sourceforge.net/ + DEPENDS:=+libpthread +endef + +define Package/dns2socks/description + This is a command line utility to resolve DNS requests via + a SOCKS tunnel like Tor or a HTTP proxy. +endef + +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/hysteria/Makefile b/hysteria/Makefile new file mode 100644 index 0000000..4af6a84 --- /dev/null +++ b/hysteria/Makefile @@ -0,0 +1,80 @@ +# SPDX-License-Identifier: GPL-3.0-only +# +# Copyright (C) 2021 ImmortalWrt.org + +include $(TOPDIR)/rules.mk + +PKG_NAME:=hysteria +PKG_VERSION:=0.9.6 +PKG_RELEASE:=$(AUTORELEASE) + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=https://codeload.github.com/HyNetwork/hysteria/tar.gz/v$(PKG_VERSION)? +PKG_HASH:=f543cfef69fc396c15248262d084aa3f6fef48a8cd98bdd8fda113fd4f5bf94c + +PKG_LICENSE:=MIT +PKG_LICENSE_FILE:=LICENSE +PKG_MAINTAINER:=Tianling Shen + +PKG_CONFIG_DEPENDS:= \ + CONFIG_HYSTERIA_COMPRESS_GOPROXY \ + CONFIG_HYSTERIA_COMPRESS_UPX + +PKG_BUILD_DEPENDS:=golang/host +PKG_BUILD_PARALLEL:=1 +PKG_USE_MIPS16:=0 + +GO_PKG:=github.com/tobyxdd/hysteria +GO_PKG_BUILD_PKG:=github.com/tobyxdd/hysteria/cmd +GO_PKG_LDFLAGS:=-s -w +GO_PKG_LDFLAGS_X:=main.appVersion=$(PKG_VERSION) + +include $(INCLUDE_DIR)/package.mk +include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk + +define Package/hysteria + SECTION:=net + CATEGORY:=Network + TITLE:=A feature-packed network utility optimized for networks of poor quality + URL:=https://github.com/tobyxdd/hysteria + DEPENDS:=$(GO_ARCH_DEPENDS) +ca-bundle +endef + +define Package/hysteria/description + Hysteria is a feature-packed network utility optimized for networks + of poor quality (e.g. satellite connections, congested public Wi-Fi, + connecting from China to servers abroad) powered by a custom version + of QUIC protocol. +endef + +define Package/hysteria/config +config HYSTERIA_COMPRESS_GOPROXY + bool "Compiling with GOPROXY proxy" + default n + +config HYSTERIA_COMPRESS_UPX + bool "Compress executable files with UPX" + depends on !mips64 + default n +endef + +ifeq ($(CONFIG_HYSTERIA_COMPRESS_GOPROXY),y) + export GO111MODULE=on + export GOPROXY=https://goproxy.baidu.com +endif + +define Build/Compile + $(call GoPackage/Build/Compile) +ifeq ($(CONFIG_HYSTERIA_COMPRESS_UPX),y) + $(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DIR)/cmd +endif +endef + +define Package/hysteria/install + $(call GoPackage/Package/Install/Bin,$(PKG_INSTALL_DIR)) + $(INSTALL_DIR) $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/cmd $(1)/usr/bin/hysteria +endef + +$(eval $(call GoBinPackage,hysteria)) +$(eval $(call BuildPackage,hysteria)) diff --git a/ipt2socks/Makefile b/ipt2socks/Makefile new file mode 100644 index 0000000..75ee856 --- /dev/null +++ b/ipt2socks/Makefile @@ -0,0 +1,43 @@ +# SPDX-License-Identifier: GPL-3.0-only +# +# Copyright (C) 2021 ImmortalWrt.org + +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:=Convert iptables to socks5 + URL:=https://github.com/zfl9/ipt2socks + DEPENDS:=+libpthread +libuv +endef + +define Package/ipt2socks/description + Utility for converting iptables (redirect/tproxy) to socks5. +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/kcptun/Makefile b/kcptun/Makefile new file mode 100644 index 0000000..af5024c --- /dev/null +++ b/kcptun/Makefile @@ -0,0 +1,76 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=kcptun +PKG_VERSION:=20210922 +PKG_RELEASE:=$(AUTORELEASE) + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=https://codeload.github.com/xtaci/kcptun/tar.gz/v${PKG_VERSION}? +PKG_SOURCE_DATE:=2021-09-22 +PKG_HASH:=f6a08f0fe75fa85d15f9c0c28182c69a5ad909229b4c230a8cbe38f91ba2d038 + +PKG_MAINTAINER:=Dengfeng Liu , Chao Liu +PKG_LICENSE:=MIT +PKG_LICENSE_FILES:=LICENSE.md + +PKG_BUILD_DEPENDS:=golang/host +PKG_BUILD_PARALLEL:=1 +PKG_USE_MIPS16:=0 + +GO_PKG:=github.com/xtaci/kcptun + +GO_PKG_LDFLAGS_X:=main.VERSION=$(PKG_VERSION) + +include $(INCLUDE_DIR)/package.mk +include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk + +define Package/kcptun-config + SECTION:=net + CATEGORY:=Network + SUBMENU:=Web Servers/Proxies + TITLE:=Kcptun Config Scripts + URL:=https://github.com/xtaci/kcptun + DEPENDS:=$(GO_ARCH_DEPENDS) +endef + +define Package/kcptun-config/conffiles +/etc/config/kcptun +endef + +define Package/kcptun-config/install + $(INSTALL_DIR) $(1)/etc/config + $(INSTALL_CONF) ./files/kcptun.config $(1)/etc/config/kcptun + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/kcptun.init $(1)/etc/init.d/kcptun +endef + +define Package/kcptun/Default + define Package/kcptun-$(1) + SECTION:=net + CATEGORY:=Network + SUBMENU:=Web Servers/Proxies + TITLE:=KCP-based Secure Tunnel $(1) + URL:=https://github.com/xtaci/kcptun + DEPENDS:=+kcptun-config + endef + + define Package/kcptun-$(1)/description + kcptun is a Stable & Secure Tunnel Based On KCP with N:M Multiplexing. +This package only contains kcptun $(1). + endef + + define Package/kcptun-$(1)/install + $$(call GoPackage/Package/Install/Bin,$$(PKG_INSTALL_DIR)) + + $$(INSTALL_DIR) $$(1)/usr/bin + $$(INSTALL_BIN) $$(PKG_INSTALL_DIR)/usr/bin/$(1) $$(1)/usr/bin/kcptun-$(1) + endef +endef + +$(eval $(call BuildPackage,kcptun-config)) +KCPTUN_COMPONENTS:=server client +$(foreach component,$(KCPTUN_COMPONENTS), \ + $(eval $(call Package/kcptun/Default,$(component))) \ + $(eval $(call GoBinPackage,kcptun-$(component))) \ + $(eval $(call BuildPackage,kcptun-$(component))) \ +) diff --git a/kcptun/files/kcptun.config b/kcptun/files/kcptun.config new file mode 100644 index 0000000..06000b4 --- /dev/null +++ b/kcptun/files/kcptun.config @@ -0,0 +1,43 @@ +config server + option disabled 1 + option listen 29900 + option target '127.0.0.1' + option target_port 12948 + option crypt 'aes' + option key 'secret' + option mode 'fast' + option datashard 10 + option parityshard 3 + option dscp 46 + option nocomp 1 + option snmplog '/var/log/snmp.log' + option snmpperiod 60 + option pprof 1 + option quiet 1 + option syslog 1 + option user nobody + +config client + option disabled 1 + option bind_address '0.0.0.0' + option local_port 12948 + option server 'vps' + option server_port 29900 + option crypt 'aes' + option key 'secret' + option mode 'fast' + option conn 1 + option autoexpire 0 + option scavengettl 600 + option mtu 1350 + option sndwnd 128 + option rcvwnd 512 + option nocomp 1 + option sockbuf 4194304 + option smuxver 1 + option smuxbuf 4194304 + option streambuf 2097152 + option keepalive 10 + option quiet 1 + option gogc 20 + option user nobody diff --git a/kcptun/files/kcptun.init b/kcptun/files/kcptun.init new file mode 100755 index 0000000..b22f850 --- /dev/null +++ b/kcptun/files/kcptun.init @@ -0,0 +1,174 @@ +#!/bin/sh /etc/rc.common +# +# Copyright (C) 2019 Chao Liu +# +# This is free software, licensed under the GNU General Public License v3. +# See /LICENSE for more information. +# + +USE_PROCD=1 +START=99 + +confdir=/var/etc/kcptun +bindir=/usr/bin + +mkjson_server_conf() { + [ "$disabled" = 0 ] || return 1 + [ -n "$listen" ] || return 1 + [ -n "$target" ] || return 1 + [ -n "$target_port" ] || return 1 + json_add_string listen ":$listen" + json_add_string target "$target:$target_port" + json_add_boolean pprof "$pprof" +} + +mkjson_client_conf() { + [ "$disabled" = 0 ] || return 1 + [ -n "$local_port" ] || return 1 + [ -n "$server" ] || return 1 + [ -n "$server_port" ] || return 1 + json_add_string localaddr "$bind_address:$local_port" + json_add_string remoteaddr "$server:$server_port" + [ -z "$conn" ] || json_add_int conn "$conn" + [ -z "$autoexpire" ] || json_add_int autoexpire "$autoexpire" + [ -z "$scavengettl" ] || json_add_int scavengettl "$scavengettl" +} + +kcptun() { + local cfg="$1" + local cfgtype="$2" + local bin="$bindir/kcptun-$cfgtype" + local confjson="$confdir/$cfgtype.$cfg.json" + + [ -x "$bin" ] || return + eval "$("validate_${cfgtype}_section" "$cfg" validate_mklocal)" + "validate_${cfgtype}_section" "$cfg" || return + [ "$disabled" = 0 ] || return + + json_init + mkjson_${cfgtype}_conf || return + [ -z "$crypt" ] || json_add_string crypt "$crypt" + [ -z "$key" ] || json_add_string key "$key" + [ -z "$mode" ] || json_add_string mode "$mode" + [ -z "$mtu" ] || json_add_int mtu "$mtu" + [ -z "$sndwnd" ] || json_add_int sndwnd "$sndwnd" + [ -z "$rcvwnd" ] || json_add_int rcvwnd "$rcvwnd" + [ -z "$datashard" ] || json_add_int datashard "$datashard" + [ -z "$parityshard" ] || json_add_int parityshard "$parityshard" + [ -z "$dscp" ] || json_add_int dscp "$dscp" + json_add_boolean nocomp "$nocomp" + [ -z "$sockbuf" ] || json_add_int sockbuf "$sockbuf" + [ -z "$smuxver" ] || json_add_int smuxver "$smuxver" + [ -z "$smuxbuf" ] || json_add_int smuxbuf "$smuxbuf" + [ -z "$streambuf" ] || json_add_int streambuf "$streambuf" + [ -z "$keepalive" ] || json_add_int keepalive "$keepalive" + [ -z "$snmplog" ] || json_add_string snmplog "$snmplog" + [ -z "$snmpperiod" ] || json_add_int snmpperiod "$snmpperiod" + json_add_boolean quiet "$quiet" + json_dump -i > "$confjson" + + procd_open_instance "$cfgtype.$cfg" + procd_set_param command "$bin" -c "$confjson" + [ -z "$gogc" ] || procd_set_param env GOGC="$gogc" + [ -z "$syslog" ] || procd_set_param stderr 1 + [ -z "$user" ] || procd_set_param user "$user" + procd_set_param file "$confjson" + procd_set_param respawn + procd_close_instance +} + +start_service() { + local cfgtype + + mkdir -p "$confdir" + config_load kcptun + for cfgtype in server client; do + config_foreach kcptun "$cfgtype" "$cfgtype" + done +} + +stop_service() { + rm -rf "$confdir" +} + +service_triggers() { + procd_add_reload_interface_trigger wan + procd_add_reload_trigger kcptun + procd_open_validate + validate_server_section + validate_client_section + procd_close_validate +} + +validate_mklocal() { + local tuple opts + + shift 2 + for tuple in "$@"; do + opts="${tuple%%:*} $opts" + done + [ -z "$opts" ] || echo "local $opts" +} + +validate() { + uci_validate_section kcptun "$@" +} + +validate_common_options() { + local cfgtype="$1"; shift + local cfg="$1"; shift + local func="$1"; shift + local crypt_methods='"aes", "aes-128", "aes-192", "salsa20", "blowfish", "twofish", "cast5", "3des", "tea", "xtea", "xor", "sm4", "none"' + local mode_profiles='"fast3", "fast2", "fast", "normal", "manual"' + + "${func:-validate}" "$cfgtype" "$cfg" "$@" \ + 'disabled:bool:0' \ + 'key:string' \ + "crypt:or($crypt_methods)" \ + "mode:or($mode_profiles)" \ + 'mtu:uinteger' \ + 'sndwnd:uinteger' \ + 'rcvwnd:uinteger' \ + 'datashard:uinteger' \ + 'parityshard:uinteger' \ + 'dscp:uinteger' \ + 'nocomp:bool' \ + 'sockbuf:uinteger' \ + 'smuxver:uinteger' \ + 'smuxbuf:uinteger' \ + 'streambuf:uinteger' \ + 'keepalive:uinteger' \ + 'snmplog:string' \ + 'snmpperiod:uinteger' \ + 'quiet:bool' \ + 'gogc:uinteger' \ + 'syslog:bool:1' \ + 'user:string:nobody' +} + +validate_server_options() { + validate_common_options server "$@" \ + 'listen:port' \ + 'target:host' \ + 'target_port:port' \ + 'pprof:bool' +} + +validate_client_options() { + validate_common_options client "$@" \ + 'bind_address:ipaddr' \ + 'local_port:port' \ + 'server:host' \ + 'server_port:port' \ + 'conn:uinteger' \ + 'autoexpire:uinteger' \ + 'scavengettl:uinteger' +} + +validate_server_section() { + validate_server_options "$1" "$2" +} + +validate_client_section() { + validate_client_options "$1" "$2" +} diff --git a/lienol/luci-app-fileassistant/Makefile b/lienol/luci-app-fileassistant/Makefile deleted file mode 100755 index 5c16f43..0000000 --- a/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 \ No newline at end of file diff --git a/lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/fb.css b/lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/fb.css deleted file mode 100755 index 96cbbb3..0000000 --- a/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/lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/fb.js b/lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/fb.js deleted file mode 100755 index 2e3adde..0000000 --- a/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/lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/file-icon.png b/lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/file-icon.png deleted file mode 100755 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/lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/folder-icon.png b/lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/folder-icon.png deleted file mode 100755 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/lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/link-icon.png b/lienol/luci-app-fileassistant/htdocs/luci-static/resources/fileassistant/link-icon.png deleted file mode 100755 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/lienol/luci-app-fileassistant/luasrc/view/fileassistant.htm b/lienol/luci-app-fileassistant/luasrc/view/fileassistant.htm deleted file mode 100755 index 15f069b..0000000 --- a/lienol/luci-app-fileassistant/luasrc/view/fileassistant.htm +++ /dev/null @@ -1,20 +0,0 @@ -<%+header%> - - -

文件助手

-
- -
-
文件列表
- -
-
- - -
-
-
- - - -<%+footer%> diff --git a/lienol/luci-app-filebrowser/Makefile b/lienol/luci-app-filebrowser/Makefile deleted file mode 100755 index 19b02b6..0000000 --- a/lienol/luci-app-filebrowser/Makefile +++ /dev/null @@ -1,17 +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 FileBrowser -LUCI_PKGARCH:=all -PKG_VERSION:=1.1 -PKG_RELEASE:=1 - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature - - diff --git a/lienol/luci-app-filebrowser/luasrc/controller/filebrowser.lua b/lienol/luci-app-filebrowser/luasrc/controller/filebrowser.lua deleted file mode 100755 index 875f166..0000000 --- a/lienol/luci-app-filebrowser/luasrc/controller/filebrowser.lua +++ /dev/null @@ -1,61 +0,0 @@ --- Copyright 2018-2020 Lienol -module("luci.controller.filebrowser", package.seeall) - -local http = require "luci.http" -local api = require "luci.model.cbi.filebrowser.api" - -function index() - if not nixio.fs.access("/etc/config/filebrowser") then return end - - entry({"admin", "nas"}, firstchild(), "NAS", 44).dependent = false - entry({"admin", "nas", "filebrowser"}, cbi("filebrowser/settings"), - _("File Browser"), 2).dependent = true - - entry({"admin", "nas", "filebrowser", "check"}, call("action_check")).leaf = - true - entry({"admin", "nas", "filebrowser", "download"}, call("action_download")).leaf = - true - entry({"admin", "nas", "filebrowser", "status"}, call("act_status")).leaf = - true - entry({"admin", "nas", "filebrowser", "get_log"}, call("get_log")).leaf = - true - entry({"admin", "nas", "filebrowser", "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 act_status() - local e = {} - e.status = luci.sys.call( - "ps -w | grep -v grep | grep 'filebrowser -a 0.0.0.0' >/dev/null") == - 0 - http_write_json(e) -end - -function action_check() - local json = api.to_check() - http_write_json(json) -end - -function action_download() - local json = nil - local task = http.formvalue("task") - if task == "extract" then - json = api.to_extract(http.formvalue("file")) - elseif task == "move" then - json = api.to_move(http.formvalue("file")) - else - json = api.to_download(http.formvalue("url")) - end - http_write_json(json) -end - -function get_log() - luci.http.write(luci.sys.exec( - "[ -f '/var/log/filebrowser.log' ] && cat /var/log/filebrowser.log")) -end -function clear_log() luci.sys.call("echo '' > /var/log/filebrowser.log") end diff --git a/lienol/luci-app-filebrowser/luasrc/model/cbi/filebrowser/api.lua b/lienol/luci-app-filebrowser/luasrc/model/cbi/filebrowser/api.lua deleted file mode 100755 index 613f00b..0000000 --- a/lienol/luci-app-filebrowser/luasrc/model/cbi/filebrowser/api.lua +++ /dev/null @@ -1,338 +0,0 @@ -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" - -module("luci.model.cbi.filebrowser.api", package.seeall) - -local appname = "filebrowser" -local api_url = - "https://api.github.com/repos/filebrowser/filebrowser/releases/latest" - -local wget = "/usr/bin/wget" -local wget_args = { - "--no-check-certificate", "--quiet", "--timeout=10", "--tries=2" -} -local command_timeout = 300 - -local LEDE_BOARD = nil -local DISTRIB_TARGET = nil - -function uci_get_type(type, config, default) - 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 - -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 = "armv" - 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 - -local 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_version() return uci_get_type("global", "version", "0") 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 - - local json = get_api_json(api_url) - - 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 needs_update = compare_versions(get_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, - 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, - 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/filebrowser_download.*") - - local tmp_file = util.trim(util.exec( - "mktemp -u -t filebrowser_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_extract(file, subfix) - 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/filebrowser_extract.*") - local tmp_dir = util.trim(util.exec( - "mktemp -d -t filebrowser_extract.XXXXXX")) - - local output = {} - exec("/bin/tar", {"-C", tmp_dir, "-zxvf", file}, - function(chunk) output[#output + 1] = chunk end) - - local files = util.split(table.concat(output)) - - exec("/bin/rm", {"-f", file}) - - if not new_file then - for _, f in pairs(files) do - if f:match("filebrowser") then - new_file = tmp_dir .. "/" .. util.trim(f) - break - end - end - end - - if not new_file then - 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) - if not file or file == "" or not fs.access(file) then - sys.call("/bin/rm -rf /tmp/filebrowser_extract.*") - return {code = 1, error = i18n.translate("Client file is required.")} - end - local project_directory = - uci_get_type("global", "project_directory", "/tmp") - luci.sys.exec("mkdir -p " .. project_directory) - local client_path = project_directory .. "/" .. appname - local client_path_bak - - if fs.access(client_path) then - client_path_bak = "/tmp/" .. appname .. ".bak" - exec("/bin/mv", {"-f", client_path, client_path_bak}) - end - - local result = exec("/bin/mv", {"-f", file, client_path}, nil, - command_timeout) == 0 - - if not result or not fs.access(client_path) then - if client_path_bak then - exec("/bin/mv", {"-f", client_path_bak, client_path}) - end - return { - code = 1, - error = i18n.translatef("Can't move new file to path: %s", - client_path) - } - end - - exec("/bin/chmod", {"755", client_path}) - - if client_path_bak then exec("/bin/rm", {"-f", client_path_bak}) end - - sys.call("/bin/rm -rf /tmp/filebrowser_extract.*") - - return {code = 0} -end diff --git a/lienol/luci-app-filebrowser/luasrc/model/cbi/filebrowser/settings.lua b/lienol/luci-app-filebrowser/luasrc/model/cbi/filebrowser/settings.lua deleted file mode 100755 index a6f4717..0000000 --- a/lienol/luci-app-filebrowser/luasrc/model/cbi/filebrowser/settings.lua +++ /dev/null @@ -1,37 +0,0 @@ -m = Map("filebrowser", translate("FileBrowser"), translate( - "File explorer is software that creates your own cloud that you can install on a server, point it to a path, and then access your files through a beautiful web interface. You have many features available!")) -m:append(Template("filebrowser/status")) - -s = m:section(TypedSection, "global", translate("Global Settings")) -s.anonymous = true -s.addremove = false - -o = s:option(Flag, "enable", translate("Enable")) -o.rmempty = false - -o = s:option(Value, "port", translate("Listen port")) -o.datatype = "port" -o.default = 8088 -o.rmempty = false - -o = s:option(Value, "root_path", translate("Root path"), translate( - "Point to a path to access your files in the web interface, default is /")) -o.default = "/" -o.rmempty = false - -o = s:option(Value, "project_directory", translate("Project directory"), - translate( - "The file size is large, requiring at least 32M space. It is recommended to insert a usb flash drive or hard disk, or use it in the tmp directory
For example, /mnt/sda1
For example, /tmp")) -o.default = "/tmp" -o.rmempty = false - -o = s:option(Button, "_download", translate("Manually download"), translate( - "Make sure you have enough space.
Be sure to fill out the project storage directory the first time you run it, and then save the application. Then manually download, otherwise can not use!")) -o.template = "filebrowser/download" -o.inputstyle = "apply" -o.btnclick = "downloadClick(this);" -o.id = "download_btn" - -m:append(Template("filebrowser/log")) - -return m diff --git a/lienol/luci-app-filebrowser/luasrc/view/filebrowser/download.htm b/lienol/luci-app-filebrowser/luasrc/view/filebrowser/download.htm deleted file mode 100755 index 8addc7e..0000000 --- a/lienol/luci-app-filebrowser/luasrc/view/filebrowser/download.htm +++ /dev/null @@ -1,169 +0,0 @@ -<% -local dsp = require "luci.dispatcher" --%> - - - -<%+cbi/valueheader%> - <% if self:cfgvalue(section) ~= false then %> - " type="button"<%= - attr("name", cbid) .. - attr("id", self.id or cbid) .. - attr("value", self.inputtitle or self.title) .. - ifattr(self.btnclick, "onclick", self.btnclick) .. - ifattr(self.placeholder, "placeholder") - %> /> - - <% else %> - - - <% end %> -<%+cbi/valuefooter%> \ No newline at end of file diff --git a/lienol/luci-app-filebrowser/luasrc/view/filebrowser/log.htm b/lienol/luci-app-filebrowser/luasrc/view/filebrowser/log.htm deleted file mode 100644 index f131ab7..0000000 --- a/lienol/luci-app-filebrowser/luasrc/view/filebrowser/log.htm +++ /dev/null @@ -1,31 +0,0 @@ - -
- - <%:Logs%> - - - -
\ No newline at end of file diff --git a/lienol/luci-app-filebrowser/luasrc/view/filebrowser/status.htm b/lienol/luci-app-filebrowser/luasrc/view/filebrowser/status.htm deleted file mode 100755 index 12a921e..0000000 --- a/lienol/luci-app-filebrowser/luasrc/view/filebrowser/status.htm +++ /dev/null @@ -1,29 +0,0 @@ -<% -local dsp = require "luci.dispatcher" --%> - -
- <%:Running Status%> -
-
- -
<%:Collecting data...%>
-
-
-
- - \ No newline at end of file diff --git a/lienol/luci-app-filebrowser/po/zh-cn/filebrowser.po b/lienol/luci-app-filebrowser/po/zh-cn/filebrowser.po deleted file mode 100755 index 68f33e6..0000000 --- a/lienol/luci-app-filebrowser/po/zh-cn/filebrowser.po +++ /dev/null @@ -1,107 +0,0 @@ -msgid "File Browser" -msgstr "文件浏览器" - -msgid "File explorer is software that creates your own cloud that you can install on a server, point it to a path, and then access your files through a beautiful web interface. You have many features available!" -msgstr "文件浏览器是一种创建你自己的云的软件,你可以在服务器上安装它,将它指向一个路径,然后通过一个漂亮的web界面访问你的文件。您有许多可用的特性!" - -msgid "RUNNING" -msgstr "运行中" - -msgid "NOT RUNNING" -msgstr "未运行" - -msgid "Enter interface" -msgstr "进入界面" - -msgid "Global Settings" -msgstr "全局设置" - -msgid "Enable" -msgstr "启用" - -msgid "Listen port" -msgstr "监听端口" - -msgid "Root path" -msgstr "指向路径" - -msgid "Point to a path to access your files in the web interface, default is /" -msgstr "指向一个路径,可在web界面访问你的文件,默认为 /" - -msgid "Project directory" -msgstr "项目存放目录" - -msgid "The file size is large, requiring at least 32M space. It is recommended to insert a usb flash drive or hard disk, or use it in the tmp directory
For example, /mnt/sda1
For example, /tmp" -msgstr "文件较大,至少需要32M空间。建议插入U盘或硬盘,或放入tmp目录里使用
例如:/mnt/sda1
例如:/tmp" - -msgid "Manually download" -msgstr "手动下载" - -msgid "Make sure you have enough space.
Be sure to fill out the project storage directory the first time you run it, and then save the application. Then manually download, otherwise can not use!" -msgstr "请确保具有足够的空间。
第一次运行务必填好项目存放目录,然后保存应用。再手动下载,否则无法使用!" - -msgid "Logs" -msgstr "日志" - -msgid "Clear logs" -msgstr "清空日志" - -msgid "It is the latest version" -msgstr "已是最新版本" - -msgid "Download successful" -msgstr "下载成功" - -msgid "Click to download" -msgstr "点击下载" - -msgid "Updating..." -msgstr "更新中" - -msgid "Unexpected error" -msgstr "意外错误" - -msgid "Download, are you sure to close?" -msgstr "正在下载,你确认要关闭吗?" - -msgid "Downloading..." -msgstr "下载中" - -msgid "Unpacking..." -msgstr "解压中" - -msgid "Moving..." -msgstr "移动中" - -msgid "The latest version:" -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" diff --git a/lienol/luci-app-filebrowser/root/etc/config/filebrowser b/lienol/luci-app-filebrowser/root/etc/config/filebrowser deleted file mode 100755 index 8603b1f..0000000 --- a/lienol/luci-app-filebrowser/root/etc/config/filebrowser +++ /dev/null @@ -1,7 +0,0 @@ - -config global - option port '8088' - option root_path '/' - option project_directory '/tmp' - option enable '0' - diff --git a/lienol/luci-app-filebrowser/root/etc/init.d/filebrowser b/lienol/luci-app-filebrowser/root/etc/init.d/filebrowser deleted file mode 100755 index 312de62..0000000 --- a/lienol/luci-app-filebrowser/root/etc/init.d/filebrowser +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2018-2020 Lienol - -START=99 - -LOG_PATH="/var/log/filebrowser.log" - -echolog() { - echo -e "$(date "+%Y-%m-%d %H:%M:%S"): $1" >> $LOG_PATH -} - -config_t_get() { - local index=0 - [ -n "$4" ] && index=$4 - local ret=$(uci get filebrowser.@$1[$index].$2 2>/dev/null) - echo ${ret:=$3} -} -start() { - ENABLED=$(config_t_get global enable 0) - [ "$ENABLED" = "0" ] && return - PORT=$(config_t_get global port 8088) - ROOT_PATH=$(config_t_get global root_path /) - project_directory=$(config_t_get global project_directory /tmp) - [ ! -f "$project_directory/filebrowser" ] && echolog "在$project_directory找不到FileBrowser主程序,请下载。" && exit - export HOME="/root" - $project_directory/filebrowser -a 0.0.0.0 -p $PORT -r $ROOT_PATH -d ${ROOT_PATH}filebrowser.db -l $LOG_PATH >/dev/null 2>&1 & -} - -stop() { - ps -w | grep -v "grep" | grep "$project_directory/filebrowser -a 0.0.0.0" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 & - rm -rf $LOG_PATH -} - -restart() { - stop - sleep 1 - start -} \ No newline at end of file diff --git a/lienol/luci-app-filebrowser/root/etc/uci-defaults/luci-app-filebrowser b/lienol/luci-app-filebrowser/root/etc/uci-defaults/luci-app-filebrowser deleted file mode 100755 index df11e72..0000000 --- a/lienol/luci-app-filebrowser/root/etc/uci-defaults/luci-app-filebrowser +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@filebrowser[-1] - add ucitrack filebrowser - set ucitrack.@filebrowser[-1].init=filebrowser - commit ucitrack -EOF - -rm -f /tmp/luci-indexcache -exit 0 diff --git a/lienol/luci-app-filebrowser/root/usr/share/rpcd/acl.d/luci-app-filebrowser.json b/lienol/luci-app-filebrowser/root/usr/share/rpcd/acl.d/luci-app-filebrowser.json deleted file mode 100644 index e01bde3..0000000 --- a/lienol/luci-app-filebrowser/root/usr/share/rpcd/acl.d/luci-app-filebrowser.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "luci-app-filebrowser": { - "description": "Grant UCI access for luci-app-filebrowser", - "read": { - "uci": [ "filebrowser" ] - }, - "write": { - "uci": [ "filebrowser" ] - } - } -} diff --git a/lienol/luci-app-guest-wifi/Makefile b/lienol/luci-app-guest-wifi/Makefile deleted file mode 100755 index ee0f37f..0000000 --- a/lienol/luci-app-guest-wifi/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# -# Copyright (C) 2018 By-Ameng Openwrt.org -# -# This is free software, licensed under the Apache License, Version 2.0 . -# - -include $(TOPDIR)/rules.mk - -LUCI_TITLE:=luci-app-guest-wifi -LUCI_DEPENDS:= -LUCI_PKGARCH:=all -PKG_VERSION:=1.0 -PKG_RELEASE:=2 - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature diff --git a/lienol/luci-app-guest-wifi/luasrc/controller/guest-wifi.lua b/lienol/luci-app-guest-wifi/luasrc/controller/guest-wifi.lua deleted file mode 100755 index 45b5d8d..0000000 --- a/lienol/luci-app-guest-wifi/luasrc/controller/guest-wifi.lua +++ /dev/null @@ -1,8 +0,0 @@ -module("luci.controller.guest-wifi", package.seeall) - -function index() - if not nixio.fs.access("/etc/config/guest-wifi") then - return - end - entry({"admin","network","guest-wifi"}, cbi("guest-wifi"), translate("Guest-wifi"), 16) -end diff --git a/lienol/luci-app-guest-wifi/luasrc/model/cbi/guest-wifi.lua b/lienol/luci-app-guest-wifi/luasrc/model/cbi/guest-wifi.lua deleted file mode 100755 index b985ced..0000000 --- a/lienol/luci-app-guest-wifi/luasrc/model/cbi/guest-wifi.lua +++ /dev/null @@ -1,67 +0,0 @@ -require("luci.tools.webadmin") - -m = Map("guest-wifi", translate("Guest-wifi")) - -s = m:section(TypedSection, "guest-wifi", translate("Config"), translate("You can set guest wifi here. The wifi will be disconnected when enabling/disabling. When modifying the password, first disable the guest wifi, and then do the modification, save and apply. Finally check both Enable and Create, save and apply.")) -s.anonymous = true -s.addremove = false - -enable = s:option(Flag, "enable", translate("Enable"), translate("Enable or disable guest wifi")) -enable.default = false -enable.optional = false -enable.rmempty = false - -create = s:option(Flag, "create", translate("Create/Remove"), translate("Check to create guest wifi when enabled, or check to remove guest wifi when disabled.")) -create.default = false -create.optional = false -create.rmempty = false - -device = s:option(ListValue, "device", translate("Define device"), translate("Define device of guest wifi")) -device:value("radio0", "radio0") -device:value("radio1", "radio1") -device:value("radio2", "radio2") -device:value("ra", "ra") -device:value("rai", "rai") -device.default = "radio0" - -wifi_name = s:option(Value, "wifi_name", translate("Wifi name"), translate("Define the name of guest wifi")) -wifi_name.default = "Guest-WiFi" -wifi_name.rmempty = true - -interface_name = s:option(Value, "interface_name", translate("Interface name"), translate("Define the interface name of guest wifi")) -interface_name.default = "guest" -interface_name.rmempty = true - -interface_ip = s:option(Value, "interface_ip", translate("Interface IP address"), translate("Define IP address for guest wifi")) -interface_ip.datatype = "ip4addr" -interface_ip.default ="192.168.4.1" - -encryption = s:option(Value, "encryption", translate("Encryption"), translate("Define encryption of guest wifi")) -encryption:value("psk", "WPA-PSK") -encryption:value("psk2", "WPA2-PSK") -encryption:value("none", "No Encryption") -encryption.default = "psk2" -encryption.widget = "select" - -passwd = s:option(Value, "passwd", translate("Password"), translate("Define the password of guest wifi")) -passwd.password = true -passwd.default = "guestnetwork" - -isolate = s:option(ListValue, "isolate", translate("Isolation"), translate("Enalbe or disable isolation")) -isolate:value("1", translate("YES")) -isolate:value("0", translate("NO")) - -start = s:option(Value, "start", translate("Start address"), translate("Lowest leased address as offset from the network address")) -start.default = "50" -start.rmempty = true - -limit = s:option(Value, "limit", translate("Client Limit"), translate("Maximum number of leased addresses")) -limit.default = "200" -limit.rmempty = true - -leasetime = s:option(Value, "leasetime", translate("DHCP lease time"), translate("Expiry time of leased addresses, minimum is 2 minutes (2m)")) -leasetime.default = "1h" -leasetime.rmempty = true - -return m - diff --git a/lienol/luci-app-guest-wifi/po/zh-cn/guest-wifi.po b/lienol/luci-app-guest-wifi/po/zh-cn/guest-wifi.po deleted file mode 100755 index d5971e7..0000000 --- a/lienol/luci-app-guest-wifi/po/zh-cn/guest-wifi.po +++ /dev/null @@ -1,90 +0,0 @@ -msgid "guest-wifi" -msgstr "访客网络" - -msgid "Guest-wifi" -msgstr "访客网络" - -msgid "Config" -msgstr "设置" - -msgid "You can set guest wifi here. The wifi will be disconnected when enabling/disabling. When modifying the password, first disable the guest wifi, and then do the modification, save and apply. Finally check both Enable and Create, save and apply." -msgstr "在此可以设置访客网络。启用/禁用访客网络时wifi会断开。当修改访客名称密码时,先禁用访客网络并保存应用,然后修改后保存应用,最后同时勾选启用和创建并保存应用。" - -msgid "Enable" -msgstr "启用" - -msgid "Enable or disable guest wifi" -msgstr "启用/禁用访客网络" - -msgid "Create/Remove" -msgstr"创建/删除" - -msgid "Check to create guest wifi when enabled, or check to remove guest wifi when disabled." -msgstr "与启用同时勾选,可创建和启用访客网络;启用不勾选时勾选,可删除访客网络。" - -msgid "Define device" -msgstr "指定设备" - -msgid "Define device of guest wifi" -msgstr "指定用于访客网络的设备" - -msgid "Wifi name" -msgstr "无线名称" - -msgid "Define the name of guest wifi" -msgstr "指定访客网络的无线名称" - -msgid "Interface name" -msgstr "接口名称" - -msgid "Define the interface name of guest wifi" -msgstr "设置访客网络的接口名称" - -msgid "Interface IP address" -msgstr "接口IP地址" - -msgid "Define IP address for guest wifi" -msgstr "指定访客网络的IP地址(不能与其他LAN的IP地址段相同)" - -msgid "Encryption" -msgstr "加密" - -msgid "Define encryption of guest wifi" -msgstr "设置访客网络的无线加密方式" - -msgid "Password" -msgstr "密码" - -msgid "Define the password of guest wifi" -msgstr "设备访客网络的无线密码" - -msgid "Isolation" -msgstr "隔离" - -msgid "Enalbe or disable isolation" -msgstr "开启或关闭与其它LAN网段的隔离" - -msgid "Start address" -msgstr "起始地址" - -msgid "Lowest leased address as offset from the network address" -msgstr "网络地址分配的起始地址" - -msgid "Client Limit" -msgstr "客户端最大数目" - -msgid "Maximum number of leased addresses" -msgstr "最大地址分配数量" - -msgid "DHCP lease time" -msgstr "DHCP地址租用时间" - -msgid "Expiry time of leased addresses, minimum is 2 minutes (2m)" -msgstr "租用地址的到期时间,最短2分钟(2m)" - -msgid "YES" -msgstr "是" - -msgid "NO" -msgstr "否" - diff --git a/lienol/luci-app-guest-wifi/root/etc/config/guest-wifi b/lienol/luci-app-guest-wifi/root/etc/config/guest-wifi deleted file mode 100755 index d43f5f5..0000000 --- a/lienol/luci-app-guest-wifi/root/etc/config/guest-wifi +++ /dev/null @@ -1,14 +0,0 @@ - -config guest-wifi - option enable '0' - option wifi_name 'Guest-WiFi' - option interface_name 'guest' - option encryption 'psk2' - option passwd 'guestnetwork' - option interface_ip '192.168.4.1' - option isolate '1' - option start '50' - option limit '200' - option leasetime '1h' - option device 'radio0' - option create '0' diff --git a/lienol/luci-app-guest-wifi/root/etc/init.d/guest-wifi b/lienol/luci-app-guest-wifi/root/etc/init.d/guest-wifi deleted file mode 100755 index 82c702d..0000000 --- a/lienol/luci-app-guest-wifi/root/etc/init.d/guest-wifi +++ /dev/null @@ -1,213 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2015 -# Must keep author's information if you use this file. - -START=50 - -HISTORY_DIR="/etc/config/guest_wifi" -[ -e /etc/config/guest_wifi ] || mkdir -p /etc/config/guest_wifi - -enabled=$(uci get guest-wifi.@guest-wifi[0].enable) -wifi_name=$(uci get guest-wifi.@guest-wifi[0].wifi_name) -interface_name=$(uci get guest-wifi.@guest-wifi[0].interface_name) -encryption=$(uci get guest-wifi.@guest-wifi[0].encryption) -passwd=$(uci get guest-wifi.@guest-wifi[0].passwd) -interface_ip=$(uci get guest-wifi.@guest-wifi[0].interface_ip) -isolate=$(uci get guest-wifi.@guest-wifi[0].isolate) -start=$(uci get guest-wifi.@guest-wifi[0].start) -limit=$(uci get guest-wifi.@guest-wifi[0].limit) -leasetime=$(uci get guest-wifi.@guest-wifi[0].leasetime) -device=$(uci get guest-wifi.@guest-wifi[0].device) -create=$(uci get guest-wifi.@guest-wifi[0].create) - - -start() { - [ $enabled = 1 ] && { - [ $create = 1 ] && { - [ -f /etc/config/guest_wifi/guest_del ] || echo "#! /bin/sh" > ${HISTORY_DIR}/guest_del - chmod 0755 ${HISTORY_DIR}/guest_del - add_interface - add_ssid - mod_dhcp - mod_fw - /etc/init.d/network restart - } - uci set guest-wifi.@guest-wifi[0].create='0' - uci commit guest-wifi - uci del wireless.$interface_name.disabled - uci commit wireless - wifi - } -} - - -stop() { - [ $enabled = 0 ] && { - [ $create = 1 ] && { - ${HISTORY_DIR}/guest_del - rule_c=`uci show firewall |grep "Hide My LAN for $wifi_name"|grep -o "[0-9]*[0-9]"` - uci del firewall.@rule[$rule_c] - uci commit firewall - rule_b=`uci show firewall |grep "Allow DHCP request for $wifi_name"|grep -o "[0-9]*[0-9]"` - uci del firewall.@rule[$rule_b] - uci commit firewall - rule_a=`uci show firewall |grep "Allow DNS Queries for $wifi_name"|grep -o "[0-9]*[0-9]"` - uci del firewall.@rule[$rule_a] - uci commit firewall - /etc/config/guest_wifi/guest_del - rm -rf /etc/config/guest_wifi/guest_del - /etc/init.d/network restart - } - uci set guest-wifi.@guest-wifi[0].create='0' - uci commit guest-wifi - uci set wireless.$interface_name.disabled='1' - uci commit wireless - wifi - } -} - -restart() { - stop - sleep 2 - start -} - -add_interface() { - name=`uci show network |grep "$interface_ip"` - if [ $? = 1 ]; then - uci set network.$interface_name=interface - uci set network.$interface_name.proto='static' - uci set network.$interface_name.ipaddr="$interface_ip" - uci set network.$interface_name.netmask='255.255.255.0' - echo "uci del network.$interface_name" >> ${HISTORY_DIR}/guest_del - echo "uci commit network" >> ${HISTORY_DIR}/guest_del - uci commit network - fi -} - -add_ssid() { - check_name=`uci show wireless |grep "$wifi_name"` - if [ $? = 1 ]; then - uci set wireless.$interface_name=wifi-iface - uci set wireless.$interface_name.device="$device" - uci set wireless.$interface_name.mode='ap' - uci set wireless.$interface_name.network="$interface_name" - uci set wireless.$interface_name.ssid="$wifi_name" - uci set wireless.$interface_name.encryption="$encryption" - uci set wireless.$interface_name.isolate="$isolate" - if [ "$encryption" != "none" ]; then - uci set wireless.$interface_name.key="$passwd" - fi - echo "uci del wireless.$interface_name" >> ${HISTORY_DIR}/guest_del - echo "uci commit wireless" >> ${HISTORY_DIR}/guest_del - uci commit wireless - fi -} - -mod_dhcp() { - check_dhcp=`uci show dhcp |grep "$interface_name=dhcp"` - if [ $? = 1 ]; then - uci set dhcp.$interface_name=dhcp - uci set dhcp.$interface_name.interface="$interface_name" - uci set dhcp.$interface_name.start="$start" - uci set dhcp.$interface_name.limit="$limit" - uci set dhcp.$interface_name.leasetime="$leasetime" - echo "uci del dhcp.$interface_name" >> ${HISTORY_DIR}/guest_del - echo "uci commit dhcp" >> ${HISTORY_DIR}/guest_del - uci commit dhcp - fi -} - -mod_fw() { - num_a=`uci show firewall |grep '=zone' |wc -l` - num_b=`uci show firewall |grep '=forwarding' |wc -l` - - check_zone=`uci show firewall |grep "name=\'$interface_name\'"` - if [ $? = 1 ]; then - uci add firewall zone - echo "uci del firewall.@zone[$num_a]" >> ${HISTORY_DIR}/guest_del - echo "uci commit firewall" >> ${HISTORY_DIR}/guest_del - uci set firewall.@zone[$num_a]=zone - uci set firewall.@zone[$num_a].name="$interface_name" - uci set firewall.@zone[$num_a].network="$interface_name" - uci set firewall.@zone[$num_a].forward='REJECT' - uci set firewall.@zone[$num_a].output='ACCEPT' - uci set firewall.@zone[$num_a].input='REJECT' - uci commit firewall - fi - - check_forward=`uci show firewall |grep "forwarding\[.*\].src=\'"$interface_name\'""` - if [ $? = 1 ]; then - uci add firewall forwarding - echo "uci del firewall.@forwarding[$num_b]" >> ${HISTORY_DIR}/guest_del - echo "uci commit firewall" >> ${HISTORY_DIR}/guest_del - uci set firewall.@forwarding[$num_b]=forwarding - uci set firewall.@forwarding[$num_b].src="$interface_name" - uci set firewall.@forwarding[$num_b].dest='wan' - uci commit firewall - fi - - check_DNS=`uci show firewall |grep "Allow DNS Queries for $wifi_name"` - if [ $? = 1 ]; then - num_c=`uci show firewall |grep '=rule' |wc -l` - uci add firewall rule - uci set firewall.@rule[$num_c]=rule - uci set firewall.@rule[$num_c].name="Allow DNS Queries for $wifi_name" - uci set firewall.@rule[$num_c].src="$interface_name" - uci set firewall.@rule[$num_c].dest_port='53' - uci set firewall.@rule[$num_c].proto='tcpudp' - uci set firewall.@rule[$num_c].target='ACCEPT' - uci commit firewall - unset num_c - fi - - check_DHCP=`uci show firewall |grep "Allow DHCP request for $wifi_name"` - if [ $? = 1 ]; then - num_c=`uci show firewall |grep '=rule' |wc -l` - uci add firewall rule - uci set firewall.@rule[$num_c]=rule - uci set firewall.@rule[$num_c].name="Allow DHCP request for $wifi_name" - uci set firewall.@rule[$num_c].src="$interface_name" - uci set firewall.@rule[$num_c].src_port='67-68' - uci set firewall.@rule[$num_c].dest_port='67-68' - uci set firewall.@rule[$num_c].proto='udp' - uci set firewall.@rule[$num_c].target='ACCEPT' - uci commit firewall - unset num_c - fi - - check_HIDE=`uci show firewall |grep "Hide My LAN for $wifi_name"` - if [ $? = 1 ]; then - num_c=`uci show firewall |grep '=rule' |wc -l` - uci add firewall rule - uci set firewall.@rule[$num_c]=rule - uci set firewall.@rule[$num_c].enabled='1' - uci set firewall.@rule[$num_c].name="Hide My LAN for $wifi_name" - uci set firewall.@rule[$num_c].proto='all' - uci set firewall.@rule[$num_c].src="$interface_name" - #convert netmask to cidr - local lan_netmask=`uci get network.lan.netmask` - local nbits=0 - local IFS=. - for netmask_dec in $lan_netmask ; do - case $netmask_dec in - 255) let nbits+=8 ;; - 254) let nbits+=7 ;; - 252) let nbits+=6 ;; - 248) let nbits+=5 ;; - 240) let nbits+=4 ;; - 224) let nbits+=3 ;; - 192) let nbits+=2 ;; - 128) let nbits+=1 ;; - 0) ;; - *) echo "Error: $netmask_dec can not be recognised as netmask decimal." && exit 1 ;; - esac - done - unset netmask_dec - uci set firewall.@rule[$num_c].dest_ip="`uci get network.lan.ipaddr`/$nbits" - uci set firewall.@rule[$num_c].target='REJECT' - uci commit firewall - unset num_c - fi -} - diff --git a/lienol/luci-app-guest-wifi/root/etc/uci-defaults/luci-app-guest-wifi b/lienol/luci-app-guest-wifi/root/etc/uci-defaults/luci-app-guest-wifi deleted file mode 100755 index 02ad18b..0000000 --- a/lienol/luci-app-guest-wifi/root/etc/uci-defaults/luci-app-guest-wifi +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@guest-wifi[-1] - add ucitrack guest-wifi - set ucitrack.@guest-wifi[-1].init=guest-wifi - commit ucitrack -EOF - -rm -f /tmp/luci-indexcache -exit 0 diff --git a/lienol/luci-app-guest-wifi/root/usr/share/rpcd/acl.d/luci-app-guest-wifi.json b/lienol/luci-app-guest-wifi/root/usr/share/rpcd/acl.d/luci-app-guest-wifi.json deleted file mode 100644 index 7ab942b..0000000 --- a/lienol/luci-app-guest-wifi/root/usr/share/rpcd/acl.d/luci-app-guest-wifi.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "luci-app-guest-wifi": { - "description": "Grant UCI access for luci-app-guest-wifi", - "read": { - "uci": [ "guest-wifi" ] - }, - "write": { - "uci": [ "guest-wifi" ] - } - } -} diff --git a/lienol/luci-app-ipsec-vpnserver-manyusers/Makefile b/lienol/luci-app-ipsec-vpnserver-manyusers/Makefile deleted file mode 100755 index ff82ef9..0000000 --- a/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:=8-20200513 - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature diff --git a/lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/controller/ipsec-server.lua b/lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/controller/ipsec-server.lua deleted file mode 100755 index 33c7ec5..0000000 --- a/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/lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/model/cbi/ipsec-server/settings.lua b/lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/model/cbi/ipsec-server/settings.lua deleted file mode 100755 index d2415d5..0000000 --- a/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/lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/model/cbi/ipsec-server/users.lua b/lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/model/cbi/ipsec-server/users.lua deleted file mode 100755 index 3477448..0000000 --- a/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/lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/view/ipsec-server/index.htm b/lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/view/ipsec-server/index.htm deleted file mode 100755 index 017f042..0000000 --- a/lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/view/ipsec-server/index.htm +++ /dev/null @@ -1,13 +0,0 @@ -<% include("cbi/map") %> - diff --git a/lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/view/ipsec-server/status.htm b/lienol/luci-app-ipsec-vpnserver-manyusers/luasrc/view/ipsec-server/status.htm deleted file mode 100755 index 2c50928..0000000 --- a/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/lienol/luci-app-ipsec-vpnserver-manyusers/po/zh-cn/ipsec.po b/lienol/luci-app-ipsec-vpnserver-manyusers/po/zh-cn/ipsec.po deleted file mode 100755 index 349daca..0000000 --- a/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/lienol/luci-app-ipsec-vpnserver-manyusers/root/etc/config/ipsec b/lienol/luci-app-ipsec-vpnserver-manyusers/root/etc/config/ipsec deleted file mode 100755 index d837e09..0000000 --- a/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/lienol/luci-app-ipsec-vpnserver-manyusers/root/etc/init.d/ipsecvpn b/lienol/luci-app-ipsec-vpnserver-manyusers/root/etc/init.d/ipsecvpn deleted file mode 100755 index 40ed48f..0000000 --- a/lienol/luci-app-ipsec-vpnserver-manyusers/root/etc/init.d/ipsecvpn +++ /dev/null @@ -1,127 +0,0 @@ -#!/bin/sh /etc/rc.common - -START=99 - -IPSEC_SECRETS_FILE=/etc/ipsec.secrets -IPSEC_CONN_FILE=/etc/ipsec.conf - -add_rule() { - iptables -t nat -I POSTROUTING -s ${vt_clientip%.*}.0/24 -m comment --comment "IPSec VPN Server" -j MASQUERADE - iptables -I forwarding_rule -s ${vt_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 -} - -del_rule() { - 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 -} - -gen_include() { - echo '#!/bin/sh' > /var/etc/ipsecvpn.include - extract_rules() { - echo "*$1" - iptables-save -t $1 | grep "IPSec VPN Server" | \ - sed -e "s/^-A \(INPUT\)/-I \1 1/" - echo 'COMMIT' - } - cat <<-EOF >> /var/etc/ipsecvpn.include - iptables-save -c | grep -v "IPSec VPN Server" | iptables-restore -c - iptables-restore -n <<-EOT - $(extract_rules filter) - $(extract_rules nat) - EOT - EOF - return 0 -} - -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 & - gen_include -} - -stop() { - ps -w | grep "/usr/lib/ipsec" | grep -v "grep" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 - del_rule - rm -rf /var/etc/ipsecvpn.include -} \ No newline at end of file diff --git a/lienol/luci-app-ipsec-vpnserver-manyusers/root/etc/uci-defaults/luci-app-ipsec-vpnserver-manyusers b/lienol/luci-app-ipsec-vpnserver-manyusers/root/etc/uci-defaults/luci-app-ipsec-vpnserver-manyusers deleted file mode 100755 index a641d77..0000000 --- a/lienol/luci-app-ipsec-vpnserver-manyusers/root/etc/uci-defaults/luci-app-ipsec-vpnserver-manyusers +++ /dev/null @@ -1,21 +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=/var/etc/ipsecvpn.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 -rm -rf /tmp/luci-*cache -exit 0 diff --git a/lienol/luci-app-ipsec-vpnserver-manyusers/root/usr/share/rpcd/acl.d/luci-app-ipsec-vpnserver-manyusers.json b/lienol/luci-app-ipsec-vpnserver-manyusers/root/usr/share/rpcd/acl.d/luci-app-ipsec-vpnserver-manyusers.json deleted file mode 100644 index 0daa049..0000000 --- a/lienol/luci-app-ipsec-vpnserver-manyusers/root/usr/share/rpcd/acl.d/luci-app-ipsec-vpnserver-manyusers.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "luci-app-ipsec-vpnserver-manyusers": { - "description": "Grant UCI access for luci-app-ipsec-vpnserver-manyusers", - "read": { - "uci": [ "ipsec" ] - }, - "write": { - "uci": [ "ipsec" ] - } - } -} diff --git a/lienol/luci-app-kodexplorer/LICENSE b/lienol/luci-app-kodexplorer/LICENSE deleted file mode 100644 index e72bfdd..0000000 --- a/lienol/luci-app-kodexplorer/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. \ No newline at end of file diff --git a/lienol/luci-app-kodexplorer/Makefile b/lienol/luci-app-kodexplorer/Makefile deleted file mode 100755 index 69a834d..0000000 --- a/lienol/luci-app-kodexplorer/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 KodExplorer -LUCI_DEPENDS:=+nginx-ssl +unzip +zoneinfo-asia +php7 +php7-fastcgi +php7-fpm +php7-mod-curl +php7-mod-dom +php7-mod-gd +php7-mod-iconv +php7-mod-json +php7-mod-mbstring +php7-mod-opcache +php7-mod-session +php7-mod-zip +php7-mod-sqlite3 +php7-mod-pdo +php7-mod-pdo-sqlite +php7-mod-pdo-mysql -LUCI_PKGARCH:=all -PKG_RELEASE:=18 -PKG_DATE:=20200729 - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature diff --git a/lienol/luci-app-kodexplorer/luasrc/controller/kodexplorer.lua b/lienol/luci-app-kodexplorer/luasrc/controller/kodexplorer.lua deleted file mode 100755 index b8b2347..0000000 --- a/lienol/luci-app-kodexplorer/luasrc/controller/kodexplorer.lua +++ /dev/null @@ -1,46 +0,0 @@ --- Copyright 2018-2020 Lienol -module("luci.controller.kodexplorer", package.seeall) - -local http = require "luci.http" -local api = require "luci.model.cbi.kodexplorer.api" - -function index() - if not nixio.fs.access("/etc/config/kodexplorer") then return end - - entry({"admin", "nas"}, firstchild(), "NAS", 44).dependent = false - entry({"admin", "nas", "kodexplorer"}, cbi("kodexplorer/settings"), _("KodExplorer"), 3).dependent = true - - entry({"admin", "nas", "kodexplorer", "check"}, call("action_check")).leaf = true - entry({"admin", "nas", "kodexplorer", "download"}, call("action_download")).leaf = true - entry({"admin", "nas", "kodexplorer", "status"}, call("act_status")).leaf = true -end - -local function http_write_json(content) - http.prepare_content("application/json") - http.write_json(content or {code = 1}) -end - -function act_status() - local e = {} - e.nginx_status = luci.sys.call("ps -w | grep nginx | grep kodexplorer | grep -v grep > /dev/null") == 0 - e.php_status = luci.sys.call("ps -w | grep php | grep kodexplorer | grep -v grep > /dev/null") == 0 - http_write_json(e) -end - -function action_check() - local json = api.to_check() - http_write_json(json) -end - -function action_download() - local json = nil - local task = http.formvalue("task") - if task == "extract" then - json = api.to_extract(http.formvalue("file")) - elseif task == "move" then - json = api.to_move(http.formvalue("file")) - else - json = api.to_download(http.formvalue("url")) - end - http_write_json(json) -end diff --git a/lienol/luci-app-kodexplorer/luasrc/model/cbi/kodexplorer/api.lua b/lienol/luci-app-kodexplorer/luasrc/model/cbi/kodexplorer/api.lua deleted file mode 100755 index 949dd09..0000000 --- a/lienol/luci-app-kodexplorer/luasrc/model/cbi/kodexplorer/api.lua +++ /dev/null @@ -1,170 +0,0 @@ -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" - -module("luci.model.cbi.kodexplorer.api", package.seeall) - -local appname = "kodexplorer" -local api_url = "https://api.kodcloud.com/?app/version" - -local wget = "/usr/bin/wget" -local wget_args = { "--no-check-certificate", "--quiet", "--timeout=10", "--tries=2" } -local command_timeout = 300 - -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 - -function get_project_directory() - return uci:get(appname, "@global[0]", "project_directory") or "/tmp/kodcloud" -end - -function get_version() - local version = get_project_directory() .. "/config/version.php" - return sys.exec(string.format("echo -n $(cat %s 2>/dev/null | grep \"'KOD_VERSION'\" | cut -d \"'\" -f 4)", version)) -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 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 = 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 to_check() - local json = get_api_json(api_url) - return json -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/kodcloud_download.*") - - local tmp_file = util.trim(util.exec("mktemp -u -t kodcloud_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_extract(file) - 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/kodcloud_extract.*") - local tmp_dir = util.trim(util.exec("mktemp -d -t kodcloud_extract.XXXXXX")) - - local output = {} - exec("/usr/bin/unzip", {"-o", file, "-d", tmp_dir}, function(chunk) output[#output + 1] = chunk end) - - local files = util.split(table.concat(output)) - - exec("/bin/rm", {"-f", file}) - - return {code = 0, file = tmp_dir} -end - -function to_move(file) - if not file or file == "" or not fs.access(file) then - sys.call("/bin/rm -rf /tmp/kodcloud_extract.*") - return {code = 1, error = i18n.translate("Client file is required.")} - end - - local client_file = get_project_directory() - sys.call("mkdir -p " .. client_file) - sys.call("cp -R " .. file .. "/* " .. client_file) - sys.call("/bin/rm -rf /tmp/kodcloud_extract.*") - - return {code = 0} -end diff --git a/lienol/luci-app-kodexplorer/luasrc/model/cbi/kodexplorer/settings.lua b/lienol/luci-app-kodexplorer/luasrc/model/cbi/kodexplorer/settings.lua deleted file mode 100755 index 19f4c59..0000000 --- a/lienol/luci-app-kodexplorer/luasrc/model/cbi/kodexplorer/settings.lua +++ /dev/null @@ -1,96 +0,0 @@ -m = Map("kodexplorer", translate("KodExplorer"), translate("KodExplorer is a fast and efficient private cloud and online document management system that provides secure, controllable, easy-to-use and highly customizable private cloud products for personal websites, enterprise private cloud deployment, network storage, online document management, and online office. With Windows style interface and operation habits, it can be used quickly without adaptation. It supports online preview of hundreds of common file formats and is extensible and easy to customize.")) -m:append(Template("kodexplorer/status")) - -s = m:section(TypedSection, "global") -s.anonymous = true -s.addremove = false - -s:tab("global", translate("Global Settings")) -s:tab("template", translate("Edit Template")) - -php_fpm = s:taboption("template", Value, "_php_fpm", - translatef("Edit the template that is used for generating the %s configuration.", "php-fpm"), - translatef("This is the content of the file '%s'", "/etc/kodexplorer/php-fpm.conf.template") .. - translatef("Values enclosed by pipe symbols ('|') should not be changed. They get their values from the '%s' tab.", translate("Global Settings"))) -php_fpm.template = "cbi/tvalue" -php_fpm.rows = 10 - -function php_fpm.cfgvalue(self, section) - return nixio.fs.readfile("/etc/kodexplorer/php-fpm.conf.template") -end - -function php_fpm.write(self, section, value) - value = value:gsub("\r\n?", "\n") - nixio.fs.writefile("/etc/kodexplorer/php-fpm.conf.template", value) -end - -php = s:taboption("template", Value, "_php", - translatef("Edit the template that is used for generating the %s configuration.", "php"), - translatef("This is the content of the file '%s'", "/etc/kodexplorer/php.ini.template") .. - translatef("Values enclosed by pipe symbols ('|') should not be changed. They get their values from the '%s' tab.", translate("Global Settings"))) -php.template = "cbi/tvalue" -php.rows = 10 - -function php.cfgvalue(self, section) - return nixio.fs.readfile("/etc/kodexplorer/php.ini.template") -end - -function php.write(self, section, value) - value = value:gsub("\r\n?", "\n") - nixio.fs.writefile("/etc/kodexplorer/php.ini.template", value) -end - -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/kodexplorer/nginx.conf.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 = 10 - -function nginx.cfgvalue(self, section) - return nixio.fs.readfile("/etc/kodexplorer/nginx.conf.template") -end - -function nginx.write(self, section, value) - value = value:gsub("\r\n?", "\n") - nixio.fs.writefile("/etc/kodexplorer/nginx.conf.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, "port", translate("Nginx Port")) -o.datatype = "port" -o.default = 8081 -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, "memory_limit", translate("Maximum memory usage"), translate("If your device has a lot of memory, you can increase it.")) -o.default = "32M" -o.rmempty = false - -o = s:taboption("global", Value, "upload_max_filesize", translate("Maximum memory usage for uploading files")) -o.default = "32M" -o.rmempty = false - -o = s:taboption("global", DynamicList, "open_basedir", translate("Accessible directory")) -o.rmempty = false - -o = s:taboption("global", Value, "project_directory", translate("Project directory"), translate("It is recommended to insert a usb flash drive or hard disk and enter the path. For example, /mnt/sda1/kodexplorer")) -o.default = "/mnt/sda1/kodexplorer" -o.rmempty = false - -o = s:taboption("global", Button, "_update") -o.template = "kodexplorer/version" -return m diff --git a/lienol/luci-app-kodexplorer/luasrc/view/kodexplorer/status.htm b/lienol/luci-app-kodexplorer/luasrc/view/kodexplorer/status.htm deleted file mode 100755 index 31a6211..0000000 --- a/lienol/luci-app-kodexplorer/luasrc/view/kodexplorer/status.htm +++ /dev/null @@ -1,52 +0,0 @@ -
- <%:Running Status%> -
-
- -
<%:Collecting data...%>
-
-
- -
<%:Collecting data...%>
-
-
- -
- -
-
-
-
- - \ No newline at end of file diff --git a/lienol/luci-app-kodexplorer/luasrc/view/kodexplorer/version.htm b/lienol/luci-app-kodexplorer/luasrc/view/kodexplorer/version.htm deleted file mode 100755 index e54409e..0000000 --- a/lienol/luci-app-kodexplorer/luasrc/view/kodexplorer/version.htm +++ /dev/null @@ -1,188 +0,0 @@ -<% -local app_version = require "luci.model.cbi.kodexplorer.api".get_version() --%> - -<% if app_version and app_version ~= "" then %> -
- -
-
- 【 <%=app_version%> 】 -
-
-
-<% else %> -
- -
- - -
- <%:Make sure you have enough space.%> -
- - <%:Be sure to fill out the device path and store path for the first run, and then save the application. Then manually download, otherwise can not use!%> - -
-
-
-<% end %> - - \ No newline at end of file diff --git a/lienol/luci-app-kodexplorer/po/zh-cn/kodexplorer.po b/lienol/luci-app-kodexplorer/po/zh-cn/kodexplorer.po deleted file mode 100755 index 19f60c1..0000000 --- a/lienol/luci-app-kodexplorer/po/zh-cn/kodexplorer.po +++ /dev/null @@ -1,119 +0,0 @@ -msgid "KodExplorer" -msgstr "可道云" - -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 "KodExplorer is a fast and efficient private cloud and online document management system that provides secure, controllable, easy-to-use and highly customizable private cloud products for personal websites, enterprise private cloud deployment, network storage, online document management, and online office. With Windows style interface and operation habits, it can be used quickly without adaptation. It supports online preview of hundreds of common file formats and is extensible and easy to customize." -msgstr "KodExplorer是一款快捷高效的私有云和在线文档管理系统,为个人网站、企业私有云部署、网络存储、在线文档管理、在线办公等提供安全可控,简便易用、可高度定制的私有云产品。采用windows风格界面、操作习惯,无需适应即可快速上手,支持几百种常用文件格式的在线预览,可扩展易定制。" - -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 "Nginx Port" -msgstr "Nginx监听端口" - -msgid "Maximum memory usage" -msgstr "内存最大使用" - -msgid "If your device has a lot of memory, you can increase it." -msgstr "如果你的设备内存较大的话,可以适当增加。" - -msgid "Maximum memory usage for uploading files" -msgstr "上传文件最大使用内存" - -msgid "Accessible directory" -msgstr "可访问的目录" - -msgid "Project directory" -msgstr "项目存放目录" - -msgid "It is recommended to insert a usb flash drive or hard disk and enter the path. For example, /mnt/sda1/kodexplorer" -msgstr "建议插入U盘或硬盘,然后输入路径。例如:/mnt/sda1/kodexplorer" - -msgid "Make sure you have enough space." -msgstr "请确保具有足够的空间。" - -msgid "Be sure to fill out the device path and store path for the first run, and then save the application. Then manually download, otherwise can not use!" -msgstr "第一次运行务必填好设备路径和存放路径,然后保存应用。再手动下载,否则无法使用!" - -msgid "Manually 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 "The latest version:" -msgstr "最新版本:" - -msgid "Get remote version info failed." -msgstr "获取远程版本信息失败。" - -msgid "Download url is required." -msgstr "请指定下载地址。" - -msgid "File download failed or timed out: %s" -msgstr "文件下载失败或超时:%s" - -msgid "File path required." -msgstr "请指定文件路径。" - -msgid "Client file is required." -msgstr "请指定客户端文件。" - -msgid "Can't move new file to path: %s" -msgstr "无法移动新文件到:%s" diff --git a/lienol/luci-app-kodexplorer/root/etc/config/kodexplorer b/lienol/luci-app-kodexplorer/root/etc/config/kodexplorer deleted file mode 100755 index bd34b28..0000000 --- a/lienol/luci-app-kodexplorer/root/etc/config/kodexplorer +++ /dev/null @@ -1,10 +0,0 @@ - -config global - option port '8081' - option memory_limit '64M' - option upload_max_filesize '64M' - option project_directory '/mnt/sda1/kodexplorer' - list open_basedir '/' - option https '0' - option enable '0' - option ipv6 '1' diff --git a/lienol/luci-app-kodexplorer/root/etc/init.d/kodexplorer b/lienol/luci-app-kodexplorer/root/etc/init.d/kodexplorer deleted file mode 100755 index be98c9d..0000000 --- a/lienol/luci-app-kodexplorer/root/etc/init.d/kodexplorer +++ /dev/null @@ -1,79 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2018-2020 Lienol - -START=99 - -CONFIG="kodexplorer" - -TEMP_PATH="/var/etc/$CONFIG" -NGINX_CONFIG="$TEMP_PATH/nginx.conf" -PHP_CONFIG="$TEMP_PATH/php.ini" -PHP_FPM_CONFIG="$TEMP_PATH/php-fpm.conf" -PHP_FPM_SOCK="$TEMP_PATH/php-fpm.sock" - -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) - port=$(config_t_get global port) - [ "$(config_t_get global https 0)" == "1" ] && { - port="$port ssl" - ssl_certificate="ssl_certificate $(config_t_get global certificate);" - ssl_certificate_key="ssl_certificate_key $(config_t_get global key);" - } - sed -e "s#|PID|#$TEMP_PATH/nginx.pid#g" \ - -e "s#|PORT|#$port#g" \ - -e "s#|ssl_certificate|#$ssl_certificate#g" \ - -e "s#|ssl_certificate_key|#$ssl_certificate_key#g" \ - -e "s#|project_directory|#$project_directory#g" \ - -e "s#|SOCK|#$PHP_FPM_SOCK#g" \ - -e "s#|upload_max_filesize|#$upload_max_filesize#g" \ - -e "s#|temp_path|#$TEMP_PATH/temp#g" \ - /etc/$CONFIG/nginx.conf.template > $1 - - [ "$ipv6" = "0" ] && sed -i '/listen \[::\]:/d' $1 -} - -gen_php_config() { - sed -e "s#|project_directory|#$project_directory#g" \ - -e "s#|open_basedir|#$open_basedir#g" \ - -e "s#|memory_limit|#$memory_limit#g" \ - -e "s#|upload_max_filesize|#$upload_max_filesize#g" \ - /etc/$CONFIG/php.ini.template > $PHP_CONFIG - - sed -e "s#|PID|#$TEMP_PATH/php-fpm.pid#g" \ - -e "s#|ERROR_LOG|#$TEMP_PATH/php-fpm.log#g" \ - -e "s#|SOCK|#$PHP_FPM_SOCK#g" \ - /etc/$CONFIG/php-fpm.conf.template > $PHP_FPM_CONFIG -} - -start() { - ENABLED=$(config_t_get global enable 0) - [ "$ENABLED" = "0" ] && return 0 - mkdir -p $TEMP_PATH $TEMP_PATH/temp /var/log/nginx /var/lib/nginx - memory_limit=$(config_t_get global memory_limit 64M) - upload_max_filesize=$(config_t_get global upload_max_filesize 64M) - project_directory=$(config_t_get global project_directory) - open_basedir=$(config_t_get global open_basedir "/") - open_basedir=$(echo $open_basedir | sed "s/ /:/g") - gen_php_config - /usr/bin/php-fpm -c $PHP_CONFIG -R -y $PHP_FPM_CONFIG - gen_nginx_config $NGINX_CONFIG - /usr/sbin/nginx -c $NGINX_CONFIG >/dev/null 2>&1 & -} - -stop() { - /usr/sbin/nginx -c $NGINX_CONFIG -s stop >/dev/null 2>&1 - [ -f "$TEMP_PATH/php-fpm.pid" ] && kill -2 $(cat $TEMP_PATH/php-fpm.pid) >/dev/null 2>&1 - rm -rf $TEMP_PATH -} - -restart() { - stop - start -} \ No newline at end of file diff --git a/lienol/luci-app-kodexplorer/root/etc/kodexplorer/nginx.conf.template b/lienol/luci-app-kodexplorer/root/etc/kodexplorer/nginx.conf.template deleted file mode 100644 index 7a722a9..0000000 --- a/lienol/luci-app-kodexplorer/root/etc/kodexplorer/nginx.conf.template +++ /dev/null @@ -1,38 +0,0 @@ -user root root; -worker_processes auto; -pid |PID|; -events { - worker_connections 1024; -} -http { - include /etc/nginx/mime.types; - sendfile on; - keepalive_timeout 65; - server { - listen |PORT|; - listen [::]:|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; - server_name localhost; - root |project_directory|; - index index.html index.htm index.php; - location ~ \.php(.*) { - fastcgi_pass unix:|SOCK|; # 通过 Unix 套接字执行 PHP - fastcgi_index index.php; - fastcgi_split_path_info ^(.+\.php)(.*)$; - fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; # 修复 Nginx fastcgi 漏洞 - fastcgi_param PATH_INFO $fastcgi_path_info; - include /etc/nginx/fastcgi_params; - client_max_body_size |upload_max_filesize|; - client_body_temp_path |temp_path|; - client_body_timeout 3600s; - fastcgi_connect_timeout 3600s; - fastcgi_send_timeout 3600s; - fastcgi_read_timeout 3600s; - } - } -} diff --git a/lienol/luci-app-kodexplorer/root/etc/kodexplorer/php-fpm.conf.template b/lienol/luci-app-kodexplorer/root/etc/kodexplorer/php-fpm.conf.template deleted file mode 100644 index 509c7f4..0000000 --- a/lienol/luci-app-kodexplorer/root/etc/kodexplorer/php-fpm.conf.template +++ /dev/null @@ -1,14 +0,0 @@ -[global] -pid = |PID| -error_log = |ERROR_LOG| -[www] -user = root -listen = |SOCK| -listen.mode = 0666 -listen.allowed_clients = 127.0.0.1 -pm = dynamic -pm.max_children = 5 -pm.start_servers = 2 -pm.min_spare_servers = 1 -pm.max_spare_servers = 3 -chdir = / diff --git a/lienol/luci-app-kodexplorer/root/etc/kodexplorer/php.ini.template b/lienol/luci-app-kodexplorer/root/etc/kodexplorer/php.ini.template deleted file mode 100644 index d2283a8..0000000 --- a/lienol/luci-app-kodexplorer/root/etc/kodexplorer/php.ini.template +++ /dev/null @@ -1,56 +0,0 @@ -[PHP] -zend.ze1_compatibility_mode = Off -engine = On -precision = 12 -y2k_compliance = On -output_buffering = Off -zlib.output_compression = Off -implicit_flush = Off -unserialize_callback_func = -serialize_precision = 100 - -open_basedir = /tmp:|project_directory|:|open_basedir| -disable_functions = -disable_classes = -expose_php = On -max_execution_time = 3600 -max_input_time = 3600 -memory_limit = |memory_limit| -error_reporting = E_ALL & ~E_NOTICE & ~E_STRICT - -display_errors = On -display_startup_errors = Off -log_errors = Off -log_errors_max_len = 1024 -ignore_repeated_errors = Off -ignore_repeated_source = Off -report_memleaks = On -track_errors = Off - -variables_order = "EGPCS" -request_order = "GP" -register_globals = Off -register_long_arrays = Off -register_argc_argv = On -auto_globals_jit = On -post_max_size = |upload_max_filesize| -magic_quotes_runtime = Off -magic_quotes_sybase = Off -auto_prepend_file = -auto_append_file = -default_mimetype = "text/html" - -;doc_root = "/www" -user_dir = -extension_dir = "/usr/lib/php" -enable_dl = On -cgi.fix_pathinfo=1 - -file_uploads = On -upload_tmp_dir = "/tmp" -upload_max_filesize = |upload_max_filesize| -max_file_uploads = 1000 - -allow_url_fopen = On -allow_url_include = Off -default_socket_timeout = 60 diff --git a/lienol/luci-app-kodexplorer/root/etc/uci-defaults/luci-app-kodexplorer b/lienol/luci-app-kodexplorer/root/etc/uci-defaults/luci-app-kodexplorer deleted file mode 100755 index 4ac2bb5..0000000 --- a/lienol/luci-app-kodexplorer/root/etc/uci-defaults/luci-app-kodexplorer +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@kodexplorer[-1] - add ucitrack kodexplorer - set ucitrack.@kodexplorer[-1].init=kodexplorer - commit ucitrack -EOF - -/etc/init.d/php7-fpm disable && /etc/init.d/php7-fpm stop -rm -rf /tmp/luci-*cache -exit 0 diff --git a/lienol/luci-app-kodexplorer/root/usr/share/rpcd/acl.d/luci-app-kodexplorer.json b/lienol/luci-app-kodexplorer/root/usr/share/rpcd/acl.d/luci-app-kodexplorer.json deleted file mode 100644 index 96e28b0..0000000 --- a/lienol/luci-app-kodexplorer/root/usr/share/rpcd/acl.d/luci-app-kodexplorer.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "luci-app-kodexplorer": { - "description": "Grant UCI access for luci-app-kodexplorer", - "read": { - "uci": [ "kodexplorer" ] - }, - "write": { - "uci": [ "kodexplorer" ] - } - } -} diff --git a/lienol/luci-app-nginx-pingos/Makefile b/lienol/luci-app-nginx-pingos/Makefile deleted file mode 100644 index e19cc03..0000000 --- a/lienol/luci-app-nginx-pingos/Makefile +++ /dev/null @@ -1,101 +0,0 @@ -# Copyright (C) 2020 Lienol - -include $(TOPDIR)/rules.mk - -PKG_NAME:=luci-app-nginx-pingos -PKG_VERSION:=1.19.2 -PKG_RELEASE:=2 - -PKG_SOURCE:=nginx-$(PKG_VERSION).tar.gz -PKG_SOURCE_URL:=https://nginx.org/download/ -PKG_HASH:=7c1f7bb13e79433ee930c597d272a64bc6e30c356a48524f38fd34fa88d62473 - -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/rpcd/acl.d - cp -pR ./root/usr/share/rpcd/acl.d/* $(1)/usr/share/rpcd/acl.d - - $(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/lienol/luci-app-nginx-pingos/luasrc/controller/pingos.lua b/lienol/luci-app-nginx-pingos/luasrc/controller/pingos.lua deleted file mode 100644 index 7c7bc99..0000000 --- a/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/lienol/luci-app-nginx-pingos/luasrc/model/cbi/pingos.lua b/lienol/luci-app-nginx-pingos/luasrc/model/cbi/pingos.lua deleted file mode 100644 index 7f40a72..0000000 --- a/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/lienol/luci-app-nginx-pingos/luasrc/view/pingos/status.htm b/lienol/luci-app-nginx-pingos/luasrc/view/pingos/status.htm deleted file mode 100644 index d2b1a34..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-client-module/COPYRIGHT b/lienol/luci-app-nginx-pingos/modules/nginx-client-module/COPYRIGHT deleted file mode 100644 index 837a668..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-client-module/config b/lienol/luci-app-nginx-pingos/modules/nginx-client-module/config deleted file mode 100644 index 36352b8..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-client-module/ngx_client.c b/lienol/luci-app-nginx-pingos/modules/nginx-client-module/ngx_client.c deleted file mode 100644 index e18d4a0..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-client-module/ngx_client.h b/lienol/luci-app-nginx-pingos/modules/nginx-client-module/ngx_client.h deleted file mode 100644 index 7b67b7b..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-client-module/ngx_http_client.c b/lienol/luci-app-nginx-pingos/modules/nginx-client-module/ngx_http_client.c deleted file mode 100644 index 3a94803..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-client-module/ngx_http_client.h b/lienol/luci-app-nginx-pingos/modules/nginx-client-module/ngx_http_client.h deleted file mode 100644 index d06a620..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/config b/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/config deleted file mode 100644 index 0ac5274..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/nginx.conf b/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/nginx.conf deleted file mode 100644 index 081f032..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/ngx_client_stat_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/ngx_client_stat_module.c deleted file mode 100644 index bdfe2d1..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/ngx_client_test_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/ngx_client_test_module.c deleted file mode 100644 index db6c586..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/ngx_http_client_test_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/ngx_http_client_test_module.c deleted file mode 100644 index aacef52..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/tcpserver.go b/lienol/luci-app-nginx-pingos/modules/nginx-client-module/t/tcpserver.go deleted file mode 100644 index 2ed5d2d..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/COPYRIGHT b/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/COPYRIGHT deleted file mode 100644 index 837a668..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/README.md b/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/README.md deleted file mode 100644 index 6e16a90..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/config b/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/config deleted file mode 100644 index 36313b3..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/doc/ngx-http-broadcast-module.md b/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/doc/ngx-http-broadcast-module.md deleted file mode 100644 index 1c86a5b..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/doc/ngx-stream-zone-module.md b/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/doc/ngx-stream-zone-module.md deleted file mode 100644 index 9864558..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_event_multiport_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_event_multiport_module.c deleted file mode 100644 index 0c0e10a..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_http_broadcast_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_http_broadcast_module.c deleted file mode 100644 index 5bce05f..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_http_inner_proxy_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_http_inner_proxy_module.c deleted file mode 100644 index 2991b0e..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_multiport.h b/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_multiport.h deleted file mode 100644 index d3fc86b..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_multiport_misc.c b/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_multiport_misc.c deleted file mode 100644 index 98ec0eb..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_process_slot_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_process_slot_module.c deleted file mode 100644 index 201281b..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_stream_zone_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_stream_zone_module.c deleted file mode 100644 index 94c2df6..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_stream_zone_module.h b/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/ngx_stream_zone_module.h deleted file mode 100644 index ba2d082..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/config b/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/config deleted file mode 100644 index 134ede9..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/nginx.conf b/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/nginx.conf deleted file mode 100644 index 3745d42..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/ngx_multiport_test_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/ngx_multiport_test_module.c deleted file mode 100644 index b9c3025..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/ngx_stream_zone_test_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/ngx_stream_zone_test_module.c deleted file mode 100644 index 8adab4f..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/ngx_test_macro.h b/lienol/luci-app-nginx-pingos/modules/nginx-multiport-module/t/ngx_test_macro.h deleted file mode 100644 index 6da2f68..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/AUTHORS b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/AUTHORS deleted file mode 100644 index db7b2e4..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/LICENSE b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/LICENSE deleted file mode 100644 index 15cb1e0..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/config b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/config deleted file mode 100644 index 4bf0264..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/dash/ngx_rtmp_dash_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/dash/ngx_rtmp_dash_module.c deleted file mode 100644 index b494606..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/dash/ngx_rtmp_mp4.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/dash/ngx_rtmp_mp4.c deleted file mode 100644 index 98efe14..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/dash/ngx_rtmp_mp4.h b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/dash/ngx_rtmp_mp4.h deleted file mode 100644 index 697b6c8..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/hls/ngx_rtmp_hls_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/hls/ngx_rtmp_hls_module.c deleted file mode 100644 index 35f1c6e..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/hls/ngx_rtmp_mpegts.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/hls/ngx_rtmp_mpegts.c deleted file mode 100644 index 110dfca..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/hls/ngx_rtmp_mpegts.h b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/hls/ngx_rtmp_mpegts.h deleted file mode 100644 index a4a16a6..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/http/ngx_http_flv_live_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/http/ngx_http_flv_live_module.c deleted file mode 100644 index aa31ef2..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/http/ngx_http_set_header.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/http/ngx_http_set_header.c deleted file mode 100644 index ffef7aa..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/http/ngx_http_set_header.h b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/http/ngx_http_set_header.h deleted file mode 100644 index eca5f3e..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_hls_http_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_hls_http_module.c deleted file mode 100644 index 599a942..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_hls_live_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_hls_live_module.c deleted file mode 100644 index efab067..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_hls_live_module.h b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_hls_live_module.h deleted file mode 100644 index b019c88..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_gop_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_gop_module.c deleted file mode 100644 index 0827da9..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_gop_module.h b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_gop_module.h deleted file mode 100644 index 3b1ca53..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_http_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_http_module.c deleted file mode 100644 index ce2ac3c..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_live_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_live_module.c deleted file mode 100644 index 1bac711..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_live_module.h b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/mpegts/ngx_mpegts_live_module.h deleted file mode 100644 index 11c27d4..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live.c deleted file mode 100644 index 713f14a..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live.h b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live.h deleted file mode 100644 index 8fad169..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_record.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_record.c deleted file mode 100644 index 3ff27e2..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_record.h b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_record.h deleted file mode 100644 index 0d008c2..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay.c deleted file mode 100644 index 148c9ff..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay.h b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay.h deleted file mode 100644 index b52405b..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_httpflv.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_httpflv.c deleted file mode 100644 index 142e023..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_inner.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_inner.c deleted file mode 100644 index 235b3f1..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_rtmp.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_rtmp.c deleted file mode 100644 index f510991..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_simple.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_simple.c deleted file mode 100644 index 43c0e0f..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_static.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_live_relay_static.c deleted file mode 100644 index 6b63504..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_netcall.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_netcall.c deleted file mode 100644 index 277bd91..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_netcall.h b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_netcall.h deleted file mode 100644 index 3d55d41..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp.c deleted file mode 100644 index 2151b30..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp.h b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp.h deleted file mode 100644 index c5867d8..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_access_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_access_module.c deleted file mode 100644 index 55b5d03..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_amf.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_amf.c deleted file mode 100644 index 77521ec..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_amf.h b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_amf.h deleted file mode 100644 index 8f70a12..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_bandwidth.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_bandwidth.c deleted file mode 100644 index 82f9f0d..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_bandwidth.h b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_bandwidth.h deleted file mode 100644 index b498482..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_bitop.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_bitop.c deleted file mode 100644 index 855d425..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_bitop.h b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_bitop.h deleted file mode 100644 index c954a35..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_cmd_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_cmd_module.c deleted file mode 100644 index b29d002..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_cmd_module.h b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_cmd_module.h deleted file mode 100644 index 5bc3c03..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_codec_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_codec_module.c deleted file mode 100644 index 9fe27b6..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_codec_module.h b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_codec_module.h deleted file mode 100644 index 961d9cd..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_control_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_control_module.c deleted file mode 100644 index 4966ec5..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_core_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_core_module.c deleted file mode 100644 index 3396adf..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_dynamic.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_dynamic.c deleted file mode 100644 index fd92cad..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_dynamic.h b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_dynamic.h deleted file mode 100644 index f74c724..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_eval.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_eval.c deleted file mode 100644 index d79d647..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_eval.h b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_eval.h deleted file mode 100644 index b05d16b..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_exec_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_exec_module.c deleted file mode 100644 index 2d6c2fe..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_gop_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_gop_module.c deleted file mode 100644 index 771f292..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_handler.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_handler.c deleted file mode 100644 index 7503653..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_handshake.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_handshake.c deleted file mode 100644 index 352aa29..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_init.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_init.c deleted file mode 100644 index ef4c519..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_limit_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_limit_module.c deleted file mode 100644 index dae8143..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_live_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_live_module.c deleted file mode 100644 index 502bc8e..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_live_module.h b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_live_module.h deleted file mode 100644 index cd9896a..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_log_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_log_module.c deleted file mode 100644 index 80c978f..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_monitor_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_monitor_module.c deleted file mode 100644 index 0a8d29f..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_monitor_module.h b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_monitor_module.h deleted file mode 100644 index 1ba70cd..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_notify_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_notify_module.c deleted file mode 100644 index 14df5ab..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_notify_module.h b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_notify_module.h deleted file mode 100644 index 889d10b..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_proxy_protocol.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_proxy_protocol.c deleted file mode 100644 index 1b24055..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_proxy_protocol.h b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_proxy_protocol.h deleted file mode 100644 index e873c3c..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_receive.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_receive.c deleted file mode 100644 index dbf662a..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_record_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_record_module.c deleted file mode 100644 index 4cff47e..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_record_module.h b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_record_module.h deleted file mode 100644 index 6450dcb..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_send.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_send.c deleted file mode 100644 index cc54afc..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_shared_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_shared_module.c deleted file mode 100644 index cdbf5d0..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_stat_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_stat_module.c deleted file mode 100644 index 7a5aed0..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_streams.h b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_streams.h deleted file mode 100644 index d957b8e..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_sys_stat_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_sys_stat_module.c deleted file mode 100644 index 7c7fae7..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_variables.c b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_variables.c deleted file mode 100644 index fbb92ca..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_variables.h b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_variables.h deleted file mode 100644 index 3b85ee4..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_version.h b/lienol/luci-app-nginx-pingos/modules/nginx-rtmp-module/ngx_rtmp_version.h deleted file mode 100644 index 1bdce49..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/COPYRIGHT b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/COPYRIGHT deleted file mode 100644 index 837a668..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/README.md b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/README.md deleted file mode 100644 index 672e6a0..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/config b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/config deleted file mode 100644 index 6f476df..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-dynamic-conf-module.md b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-dynamic-conf-module.md deleted file mode 100644 index 31264bd..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-dynamic-resolver-module.md b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-dynamic-resolver-module.md deleted file mode 100644 index 4eeda28..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-event-resolver-module.md b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-event-resolver-module.md deleted file mode 100644 index 4f43e2f..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-event-timer-module.md b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-event-timer-module.md deleted file mode 100644 index 333d120..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-map.md b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-map.md deleted file mode 100644 index 52f094d..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-poold.md b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-poold.md deleted file mode 100644 index a631ffa..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-rbuf.md b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-rbuf.md deleted file mode 100644 index 84d2299..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-toolkit-misc.md b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/doc/ngx-toolkit-misc.md deleted file mode 100644 index 23e61be..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_dynamic_conf.c b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_dynamic_conf.c deleted file mode 100644 index fd8f15b..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_dynamic_conf.h b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_dynamic_conf.h deleted file mode 100644 index 3d2f6d1..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_dynamic_resolver.c b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_dynamic_resolver.c deleted file mode 100644 index 6f1592f..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_dynamic_resolver.h b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_dynamic_resolver.h deleted file mode 100644 index 4bce494..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_event_resolver.c b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_event_resolver.c deleted file mode 100644 index acd194e..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_event_resolver.h b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_event_resolver.h deleted file mode 100644 index 89668e4..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_event_timer_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_event_timer_module.c deleted file mode 100644 index c63787e..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_event_timer_module.h b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_event_timer_module.h deleted file mode 100644 index 9b02f71..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_http_dynamic.c b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_http_dynamic.c deleted file mode 100644 index 440e744..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_http_dynamic.h b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_http_dynamic.h deleted file mode 100644 index 04d2a96..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_http_trace_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_http_trace_module.c deleted file mode 100644 index 20fa12a..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_map.c b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_map.c deleted file mode 100644 index c41bc16..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_map.h b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_map.h deleted file mode 100644 index c7626d3..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_poold.c b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_poold.c deleted file mode 100644 index bab4634..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_poold.h b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_poold.h deleted file mode 100644 index 5882839..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_rbuf.c b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_rbuf.c deleted file mode 100644 index 6b80bd5..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_rbuf.h b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_rbuf.h deleted file mode 100644 index 7002d55..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_timerd.c b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_timerd.c deleted file mode 100644 index a28109b..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_timerd.h b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_timerd.h deleted file mode 100644 index 7c64d42..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_toolkit_misc.c b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_toolkit_misc.c deleted file mode 100644 index 8045460..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_toolkit_misc.h b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/ngx_toolkit_misc.h deleted file mode 100644 index eefeb77..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/config b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/config deleted file mode 100644 index 23541ea..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/dns_install.sh b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/dns_install.sh deleted file mode 100644 index 5ba6c24..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/md5testfile b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/md5testfile deleted file mode 100644 index 837a668..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/named.conf b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/named.conf deleted file mode 100644 index 79e0d0f..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/nginx.conf b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/nginx.conf deleted file mode 100644 index b7d89ce..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/nginx_dynamic.conf b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/nginx_dynamic.conf deleted file mode 100644 index 6bef7d5..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_dynamic_conf_test_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_dynamic_conf_test_module.c deleted file mode 100644 index ec24ad3..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_dynamic_resolver_test_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_dynamic_resolver_test_module.c deleted file mode 100644 index 4bd53c9..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_event_resolver_test_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_event_resolver_test_module.c deleted file mode 100644 index fbfcb98..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_event_timer_test_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_event_timer_test_module.c deleted file mode 100644 index 320b803..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_http_dynamic_test_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_http_dynamic_test_module.c deleted file mode 100644 index eb0f09a..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_map_test_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_map_test_module.c deleted file mode 100644 index d0762bf..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_poold_test_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_poold_test_module.c deleted file mode 100644 index da93021..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_rbuf_test_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_rbuf_test_module.c deleted file mode 100644 index 3a112ec..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_test_macro.h b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_test_macro.h deleted file mode 100644 index 6da2f68..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_timerd_test_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_timerd_test_module.c deleted file mode 100644 index df30649..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_toolkit_misc_test_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/ngx_toolkit_misc_test_module.c deleted file mode 100644 index 6c58f71..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/test.com.zone b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/test.com.zone deleted file mode 100644 index 6432d87..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/test1.com.zone b/lienol/luci-app-nginx-pingos/modules/nginx-toolkit-module/t/test1.com.zone deleted file mode 100644 index 27ed83c..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/LICENSE b/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/LICENSE deleted file mode 100644 index 2bc5ec2..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/README.rst b/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/README.rst deleted file mode 100644 index b32e846..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/config b/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/config deleted file mode 100644 index aebcdab..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_http_ts_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_http_ts_module.c deleted file mode 100644 index 316cf61..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_stream_ts_module.c b/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_stream_ts_module.c deleted file mode 100644 index aff1447..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_aac.c b/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_aac.c deleted file mode 100644 index b060694..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_aac.h b/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_aac.h deleted file mode 100644 index 4274021..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_avc.c b/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_avc.c deleted file mode 100644 index 6d22eed..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_avc.h b/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_avc.h deleted file mode 100644 index e1fe42e..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_dash.c b/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_dash.c deleted file mode 100644 index de8b55d..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_dash.h b/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_dash.h deleted file mode 100644 index 5a1a8f5..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_dash_mp4.c b/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_dash_mp4.c deleted file mode 100644 index 6ed34fa..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_hls.c b/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_hls.c deleted file mode 100644 index 8ce47e7..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_hls.h b/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_hls.h deleted file mode 100644 index 031f018..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_stream.c b/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_stream.c deleted file mode 100644 index b778040..0000000 --- a/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/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_stream.h b/lienol/luci-app-nginx-pingos/modules/nginx-ts-module/src/ngx_ts_stream.h deleted file mode 100644 index bd031ab..0000000 --- a/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/lienol/luci-app-nginx-pingos/patches/101-feature_test_fix.patch b/lienol/luci-app-nginx-pingos/patches/101-feature_test_fix.patch deleted file mode 100644 index b867c88..0000000 --- a/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/lienol/luci-app-nginx-pingos/patches/102-sizeof_test_fix.patch b/lienol/luci-app-nginx-pingos/patches/102-sizeof_test_fix.patch deleted file mode 100644 index 7d2430e..0000000 --- a/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/lienol/luci-app-nginx-pingos/patches/103-sys_nerr.patch b/lienol/luci-app-nginx-pingos/patches/103-sys_nerr.patch deleted file mode 100644 index 5f5d106..0000000 --- a/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/lienol/luci-app-nginx-pingos/patches/104-endianness_fix.patch b/lienol/luci-app-nginx-pingos/patches/104-endianness_fix.patch deleted file mode 100644 index 081bcdb..0000000 --- a/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/lienol/luci-app-nginx-pingos/patches/200-config.patch b/lienol/luci-app-nginx-pingos/patches/200-config.patch deleted file mode 100644 index f350095..0000000 --- a/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/lienol/luci-app-nginx-pingos/patches/201-ignore-invalid-options.patch b/lienol/luci-app-nginx-pingos/patches/201-ignore-invalid-options.patch deleted file mode 100644 index 88b5213..0000000 --- a/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/lienol/luci-app-nginx-pingos/po/zh-cn/pingos.po b/lienol/luci-app-nginx-pingos/po/zh-cn/pingos.po deleted file mode 100644 index 1b49421..0000000 --- a/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/lienol/luci-app-nginx-pingos/root/etc/config/pingos b/lienol/luci-app-nginx-pingos/root/etc/config/pingos deleted file mode 100644 index 128af52..0000000 --- a/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/lienol/luci-app-nginx-pingos/root/etc/init.d/pingos b/lienol/luci-app-nginx-pingos/root/etc/init.d/pingos deleted file mode 100644 index 979f2ee..0000000 --- a/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/lienol/luci-app-nginx-pingos/root/etc/pingos.template b/lienol/luci-app-nginx-pingos/root/etc/pingos.template deleted file mode 100644 index 9e94111..0000000 --- a/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/lienol/luci-app-nginx-pingos/root/etc/uci-defaults/luci-app-nginx-pingos b/lienol/luci-app-nginx-pingos/root/etc/uci-defaults/luci-app-nginx-pingos deleted file mode 100644 index cd6d3ff..0000000 --- a/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/lienol/luci-app-nginx-pingos/root/resource/conf-template/nginx.conf b/lienol/luci-app-nginx-pingos/root/resource/conf-template/nginx.conf deleted file mode 100644 index e22f688..0000000 --- a/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 4; -#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/lienol/luci-app-nginx-pingos/root/resource/crossdomain.xml b/lienol/luci-app-nginx-pingos/root/resource/crossdomain.xml deleted file mode 100644 index e5b559a..0000000 --- a/lienol/luci-app-nginx-pingos/root/resource/crossdomain.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/lienol/luci-app-nginx-pingos/root/resource/stat.xsl b/lienol/luci-app-nginx-pingos/root/resource/stat.xsl deleted file mode 100644 index 0e433c7..0000000 --- a/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/lienol/luci-app-nginx-pingos/root/usr/share/rpcd/acl.d/luci-app-nginx-pingos.json b/lienol/luci-app-nginx-pingos/root/usr/share/rpcd/acl.d/luci-app-nginx-pingos.json deleted file mode 100644 index 2998eac..0000000 --- a/lienol/luci-app-nginx-pingos/root/usr/share/rpcd/acl.d/luci-app-nginx-pingos.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "luci-app-nginx-pingos": { - "description": "Grant UCI access for luci-app-nginx-pingos", - "read": { - "uci": [ "pingos" ] - }, - "write": { - "uci": [ "pingos" ] - } - } -} diff --git a/lienol/luci-app-passwall/LICENSE b/lienol/luci-app-passwall/LICENSE deleted file mode 100644 index e72bfdd..0000000 --- a/lienol/luci-app-passwall/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. \ No newline at end of file diff --git a/lienol/luci-app-passwall/Makefile b/lienol/luci-app-passwall/Makefile deleted file mode 100644 index 394b636..0000000 --- a/lienol/luci-app-passwall/Makefile +++ /dev/null @@ -1,170 +0,0 @@ -# Copyright (C) 2018-2020 L-WRT Team -# -# This is free software, licensed under the GNU General Public License v3. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=luci-app-passwall -PKG_VERSION:=3.9 -PKG_RELEASE:=73 -PKG_DATE:=20201012 - -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_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_V2ray - bool "Include V2ray" - 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 y if i386||x86_64||arm||aarch64 - -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_https_dns_proxy - bool "Include Https DNS Proxy(DoH)" - default y - -config PACKAGE_$(PKG_NAME)_INCLUDE_dns2socks - bool "Include dns2socks" - default n - -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 \ - +ssocks \ - +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_Server:shadowsocks-libev-ss-server \ - +PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR:shadowsocksr-libev-alt \ - +PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR:shadowsocksr-libev-ssr-local \ - +PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Server:shadowsocksr-libev-server \ - +PACKAGE_$(PKG_NAME)_INCLUDE_V2ray:v2ray \ - +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_https_dns_proxy:https-dns-proxy \ - +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/proxy_host -/usr/share/passwall/rules/proxy_ip -/usr/share/passwall/rules/direct_host -/usr/share/passwall/rules/direct_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/share/rpcd/acl.d - cp -pR ./root/usr/share/rpcd/acl.d/* $(1)/usr/share/rpcd/acl.d - - $(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/lienol/luci-app-passwall/README.md b/lienol/luci-app-passwall/README.md deleted file mode 100644 index 966f50a..0000000 --- a/lienol/luci-app-passwall/README.md +++ /dev/null @@ -1,2 +0,0 @@ - - 没有教程,自己摸索。 - - 禁止套娃,后果自负,高手随意。 \ No newline at end of file diff --git a/lienol/luci-app-passwall/luasrc/controller/passwall.lua b/lienol/luci-app-passwall/luasrc/controller/passwall.lua deleted file mode 100644 index 85ab30b..0000000 --- a/lienol/luci-app-passwall/luasrc/controller/passwall.lua +++ /dev/null @@ -1,405 +0,0 @@ --- Copyright (C) 2018-2020 L-WRT Team -module("luci.controller.passwall", package.seeall) -local appname = "passwall" -local ucic = luci.model.uci.cursor() -local http = require "luci.http" -local util = require "luci.util" -local kcptun = require "luci.model.cbi.passwall.api.kcptun" -local brook = require "luci.model.cbi.passwall.api.brook" -local v2ray = require "luci.model.cbi.passwall.api.v2ray" -local trojan_go = require "luci.model.cbi.passwall.api.trojan_go" - -function index() - appname = "passwall" - 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_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_append_temp"}, call("link_append_temp")).leaf = true - entry({"admin", "services", appname, "link_load_temp"}, call("link_load_temp")).leaf = true - entry({"admin", "services", appname, "link_clear_temp"}, call("link_clear_temp")).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_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, "v2ray_check"}, call("v2ray_check")).leaf = true - entry({"admin", "services", appname, "v2ray_update"}, call("v2ray_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(luci.dispatcher.build_url("admin", "services", appname)) -end - -function show_menu() - luci.sys.call("touch /etc/config/passwall_show") - luci.http.redirect(luci.dispatcher.build_url("admin", "services", appname)) -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_append_temp() - local link = luci.http.formvalue("link") - local lfile = "/tmp/links.conf" - local ret, ldata="empty", {} - luci.sys.call('touch ' .. lfile .. ' && echo \'' .. link .. '\' >> ' .. lfile) - ret = luci.sys.exec([[awk -F'://' 'BEGIN{ all=0 } /.{2,9}:\/\/.{4,}$/ {gsub(/:\/\/.*$/,""); arr[$0]++; all++ } END { for(typ in arr) { printf("%s: %d, ", typ, arr[typ]) }; printf("\ntotal: %d", all) }' ]] .. lfile) - luci.http.prepare_content("application/json") - luci.http.write_json({counter = ret}) -end - -function link_load_temp() - local lfile = "/tmp/links.conf" - local ret, ldata="empty", {} - ldata[#ldata+1] = nixio.fs.readfile(lfile) or "_nofile_" - if ldata[1] == "" then - ldata[1] = "_nodata_" - else - ret = luci.sys.exec([[awk -F'://' 'BEGIN{ all=0 } /.{2,9}:\/\/.{4,}$/ {gsub(/:\/\/.*$/,""); arr[$0]++; all++ } END { for(typ in arr) { printf("%s: %d, ", typ, arr[typ]) }; printf("\ntotal: %d", all) }' ]] .. lfile) - end - luci.http.prepare_content("application/json") - luci.http.write_json({counter = ret, data = ldata}) -end - -function link_clear_temp() - local lfile = "/tmp/links.conf" - luci.sys.call('cat /dev/null > ' .. lfile) -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 tcp_node_num = ucic:get(appname, "@global_other[0]", "tcp_node_num") or 1 - e.tcp = tonumber(tcp_node_num) - for i = 1, tcp_node_num, 1 do - local data, code, msg = nixio.fs.readfile("/var/etc/passwall/id/TCP_" .. i) - if data then - e["TCP" .. i] = util.trim(data) - end - end - local udp_node_num = ucic:get(appname, "@global_other[0]", "udp_node_num") or 1 - e.udp = tonumber(udp_node_num) - for i = 1, udp_node_num, 1 do - local data, code, msg = nixio.fs.readfile("/var/etc/passwall/id/UDP_" .. i) - if data then - e["UDP" .. i] = util.trim(data) - end - end - luci.http.prepare_content("application/json") - luci.http.write_json(e) -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("ps -w | grep -v grep | grep '%s/bin/' | grep haproxy >/dev/null", appname)) == 0 - local tcp_node_num = ucic:get(appname, "@global_other[0]", "tcp_node_num") or 1 - for i = 1, tcp_node_num, 1 do - e["kcptun_tcp_node%s_status" % i] = luci.sys.call(string.format("ps -w | grep -v grep | grep '%s/bin/kcptun' | grep -i 'tcp_%s' >/dev/null", appname, i)) == 0 - e["tcp_node%s_status" % i] = luci.sys.call(string.format("ps -w | grep -v -E 'grep|kcptun' | grep '%s/bin/' | grep -i 'TCP_%s' >/dev/null", appname, i)) == 0 - end - - local udp_node_num = ucic:get(appname, "@global_other[0]", "udp_node_num") or 1 - for i = 1, udp_node_num, 1 do - if (ucic:get(appname, "@global[0]", "udp_node" .. i) or "nil") == "tcp" then - e["udp_node%s_status" % i] = e["tcp_node%s_status" % i] - else - e["udp_node%s_status" % i] = luci.sys.call(string.format("ps -w | grep -v grep | grep '%s/bin/' | grep -i 'UDP_%s' >/dev/null", appname, i)) == 0 - end - 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("ps -w | grep -v grep | grep '%s/bin/' | grep 'SOCKS_%s' > /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("ps -w | grep -v grep | grep '%s/bin/' | grep 'SOCKS2HTTP_%s' > /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}'") - e.use_time = string.format("%.2f", use_time * 1000) - 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 number = luci.http.formvalue("number") - local section = luci.http.formvalue("section") - ucic:set(appname, "@global[0]", protocol .. "_node" .. number, section) - ucic:commit(appname) - luci.sys.call("/etc/init.d/passwall restart > /dev/null 2>&1 &") - luci.http.redirect(luci.dispatcher.build_url("admin", "services", appname, "log")) -end - -function copy_node() - local e = {} - local section = luci.http.formvalue("section") - luci.http.prepare_content("application/json") - luci.http.write_json(e) -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") -end - -function check_port() - local node_name = "" - - local retstring = "
" - -- retstring = retstring .. "暂时不支持UDP检测
" - - retstring = retstring .. "检测端口可用性
" - 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.v2ray_transport and s.v2ray_transport == "mkcp" and s.port) then - else - local type = s.type - if type and type ~= "V2ray_balancing" and type ~= "V2ray_shunt" 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("ps -w | 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_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 v2ray_check() - local json = v2ray.to_check("") - http_write_json(json) -end - -function v2ray_update() - local json = nil - local task = http.formvalue("task") - if task == "extract" then - json = v2ray.to_extract(http.formvalue("file"), http.formvalue("subfix")) - elseif task == "move" then - json = v2ray.to_move(http.formvalue("file")) - else - json = v2ray.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/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/api.lua b/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/api.lua deleted file mode 100644 index 51061d5..0000000 --- a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/api.lua +++ /dev/null @@ -1,276 +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"} -wget = "/usr/bin/wget" -wget_args = {"--no-check-certificate", "--quiet", "--timeout=100", "--tries=3"} -command_timeout = 300 -LEDE_BOARD = nil -DISTRIB_TARGET = nil - -function get_valid_nodes() - local nodes = {} - uci:foreach(appname, "nodes", function(e) - if e.type and e.remarks then - if e.type == "V2ray" and (e.protocol == "_balancing" or e.protocol == "_shunt") then - e.remarks_name = "%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 address2 = address - if datatypes.ip6addr(address) then address2 = "[" .. address .. "]" end - e.remarks_name = "%s:[%s] %s:%s" % {e.type, e.remarks, address2, e.port} - if e.use_kcp and e.use_kcp == "1" then - e.remarks_name = "%s+%s:[%s] %s" % {e.type, "Kcptun", e.remarks, address2} - end - e.node_type = "normal" - nodes[#nodes + 1] = e - end - end - end - end) - return nodes -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 "%s/%s" -p "/usr/bin/v2ray/%s" "%s"' % {get_customed_path(e), e, e, e}) ~= "" and true or false -end - -function get_v2ray_path() - local path = uci_get_type("global_app", "v2ray_file") - return path .. "/v2ray" -end - -function get_v2ray_version(file) - if file == nil then file = get_v2ray_path() end - chmod_755(file) - if fs.access(file) then - return sys.exec("echo -n $(%s -version | awk '{print $2}' | sed -n 1P)" % file) - 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 - return sys.exec("echo -n $(%s -version | awk '{print $2}' | sed -n 1P)" % file) - 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 - return sys.exec("echo -n $(%s -v | awk '{print $3}')" % file) - 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 - return sys.exec("echo -n $(%s -v | awk '{print $3}')" % file) - end - return "" -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/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/brook.lua b/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/brook.lua deleted file mode 100644 index 3051858..0000000 --- a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/brook.lua +++ /dev/null @@ -1,133 +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) - 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) - 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) - 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 = api.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 = api.get_brook_path() - local client_file_bak - - if fs.access(client_file) then - client_file_bak = client_file .. ".bak" - api.exec("/bin/mv", {"-f", client_file, client_file_bak}) - end - - local result = api.exec("/bin/mv", {"-f", file, client_file}, nil, api.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 - api.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 - - api.exec("/bin/chmod", {"755", client_file}) - - if client_file_bak then api.exec("/bin/rm", {"-f", client_file_bak}) end - - sys.call("/bin/rm -rf /tmp/brook_download.*") - - return {code = 0} -end diff --git a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_naiveproxy.lua b/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_naiveproxy.lua deleted file mode 100644 index c6650b4..0000000 --- a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_naiveproxy.lua +++ /dev/null @@ -1,16 +0,0 @@ -local ucursor = require "luci.model.uci".cursor() -local jsonc = require "luci.jsonc" -local node_section = arg[1] -local run_type = arg[2] -local local_addr = arg[3] -local local_port = arg[4] -local server_host = arg[5] -local server_port = arg[6] -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/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_shadowsocks.lua b/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_shadowsocks.lua deleted file mode 100644 index 7ab2b32..0000000 --- a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_shadowsocks.lua +++ /dev/null @@ -1,34 +0,0 @@ -local ucursor = require "luci.model.uci".cursor() -local jsonc = require "luci.jsonc" -local node_section = arg[1] -local local_addr = arg[2] -local local_port = arg[3] -local server_host = arg[4] -local server_port = arg[5] -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/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_v2ray.lua b/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_v2ray.lua deleted file mode 100644 index 583428e..0000000 --- a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_v2ray.lua +++ /dev/null @@ -1,308 +0,0 @@ -module("luci.model.cbi.passwall.api.gen_v2ray", package.seeall) -local ucursor = require"luci.model.uci".cursor() -local sys = require "luci.sys" -local json = require "luci.jsonc" -local appname = "passwall" -local inbounds = {} -local outbounds = {} -local routing = nil - -local node_section = arg[1] or "nil" -local proto = arg[2] -local redir_port = arg[3] -local socks_proxy_port = arg[4] -local node = ucursor:get_all(appname, node_section) -local network = proto -local new_port - -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, relay_port) - local result = nil - if node then - local node_id = node[".name"] - if tag == nil then - tag = node_id - end - if node.type ~= "V2ray" then - if node.type == "Socks" then - node.protocol = "socks" - node.transport = "tcp" - else - local node_type = (proto and proto ~= "nil") and proto or "socks" - 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, - node_id, - "127.0.0.1", - new_port, - string.format("/var/etc/%s/v2_%s_%s.json", appname, node_type, node_id), - "0", - "nil", - "4", - relay_port and tostring(relay_port) or "" - ) - ) - node.protocol = "socks" - node.transport = "tcp" - node.address = "127.0.0.1" - end - node.stream_security = "none" - end - - if node.transport == "mkcp" or node.transport == "quic" then - node.stream_security = "none" - end - - result = { - tag = tag, - protocol = node.protocol, - mux = { - enabled = (node.mux == "1") and true or false, - concurrency = (node.mux_concurrency) and tonumber(node.mux_concurrency) or 8 - }, - -- 底层传输配置 - 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 - } 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 - } 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 = node.level and tonumber(node.level) or 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, - 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 then - if socks_proxy_port ~= "nil" then - table.insert(inbounds, { - listen = "0.0.0.0", - port = tonumber(socks_proxy_port), - protocol = "socks", - settings = {auth = "noauth", udp = true, ip = "127.0.0.1"} - }) - network = "tcp,udp" - end - - if redir_port ~= "nil" 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 - - if node.protocol == "_shunt" then - local rules = {} - ucursor:foreach(appname, "shunt_rules", function(e) - local name = e[".name"] - local _node_id = node[name] or nil - if _node_id and _node_id ~= "nil" then - local _node = ucursor:get_all(appname, _node_id) - local is_proxy = node[name .. "_proxy"] - local relay_port - if is_proxy and is_proxy == "1" then - new_port = get_new_port() - relay_port = 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 - end - local _outbound = gen_outbound(_node, name, relay_port) - if _outbound then - table.insert(outbounds, _outbound) - if is_proxy and is_proxy == "1" then - table.insert(rules, { - type = "field", - inboundTag = {"proxy_" .. name}, - outboundTag = "default" - }) - 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 = name, - domain = _domain - }) - 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 = name, - ip = _ip - }) - end - end - end - end) - - local default_node_id = node.default_node or nil - if default_node_id and default_node_id ~= "nil" then - local default_node = ucursor:get_all(appname, default_node_id) - local default_outbound = gen_outbound(default_node, "default") - if default_outbound then - table.insert(outbounds, default_outbound) - local rule = { - type = "field", - outboundTag = "default", - network = network - } - table.insert(rules, rule) - end - end - - routing = {domainStrategy = "IPOnDemand", 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 = "IPOnDemand", - 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 - - -- 额外传出连接 - table.insert(outbounds, {protocol = "freedom", tag = "direct", settings = {keep = ""}}) - - local v2ray = { - log = { - -- error = string.format("/var/etc/passwall/%s.log", node[".name"]), - loglevel = "warning" - }, - -- 传入连接 - inbounds = inbounds, - -- 传出连接 - outbounds = outbounds, - -- 路由 - routing = routing - } - print(json.stringify(v2ray, 1)) -end diff --git a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_v2ray_proto.lua b/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_v2ray_proto.lua deleted file mode 100644 index 2f26f3f..0000000 --- a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_v2ray_proto.lua +++ /dev/null @@ -1,80 +0,0 @@ -local json = require "luci.jsonc" -local inbounds = {} -local outbounds = {} -local routing = nil - -local local_proto = arg[1] -local local_address = arg[2] -local local_port = arg[3] -local server_proto = arg[4] -local server_address = arg[5] -local server_port = arg[6] -local server_username = arg[7] or "nil" -local server_password = arg[8] or "nil" - -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 ~= "nil" and password ~= "nil") 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 v2ray = { - log = { - -- error = string.format("/var/etc/passwall/%s.log", node[".name"]), - loglevel = "warning" - }, - -- 传入连接 - inbounds = inbounds, - -- 传出连接 - outbounds = outbounds, - -- 路由 - routing = routing -} -print(json.stringify(v2ray, 1)) diff --git a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/kcptun.lua b/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/kcptun.lua deleted file mode 100644 index 8ad20f8..0000000 --- a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/kcptun.lua +++ /dev/null @@ -1,205 +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 get_kcptun_file_path() - return api.uci_get_type("global_app", "kcptun_client_file") -end - -function get_kcptun_version(file) - if file == nil then file = get_kcptun_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] == "kcptun" and tb[3] or "" - end - end - - return "" -end - -function to_check(arch) - 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 remote_version = json.tag_name:match("[^v]+") - - local client_file = get_kcptun_file_path() - - local needs_update = api.compare_versions(get_kcptun_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("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 = get_kcptun_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_kcptun_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/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) - 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) - 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 version = get_kcptun_version(file) - if 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 client_file = get_kcptun_file_path() - local client_file_bak - - if fs.access(client_file) then - client_file_bak = client_file .. ".bak" - api.exec("/bin/mv", {"-f", client_file, client_file_bak}) - end - - local result = api.exec("/bin/mv", {"-f", file, client_file}, nil, - api.command_timeout) == 0 - - if not result or not fs.access(client_file) then - sys.call("/bin/rm -rf /tmp/kcptun_extract.*") - if client_file_bak then - api.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 - - api.exec("/bin/chmod", {"755", client_file}) - - if client_file_bak then api.exec("/bin/rm", {"-f", client_file_bak}) end - - sys.call("/bin/rm -rf /tmp/kcptun_extract.*") - - return {code = 0} -end diff --git a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/trojan_go.lua b/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/trojan_go.lua deleted file mode 100644 index 0ea54d4..0000000 --- a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/trojan_go.lua +++ /dev/null @@ -1,149 +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 ipkg = require("luci.model.ipkg") -local api = require "luci.model.cbi.passwall.api.api" - -local trojan_go_api = api.uci_get_type("global_app", "trojan_go_latest", "https://api.github.com/repos/trojan-gfw/trojan-go/releases/latest") - -function to_check(arch) - 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) - 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 isinstall_unzip = ipkg.installed("unzip") - if isinstall_unzip == nil then - ipkg.update() - ipkg.install("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) - 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 client_file = api.get_trojan_go_path() - local client_file_bak - - if fs.access(client_file) then - client_file_bak = client_file .. ".bak" - api.exec("/bin/mv", {"-f", client_file, client_file_bak}) - end - - local result = api.exec("/bin/mv", { "-f", file .. "/trojan-go", client_file }, nil, api.command_timeout) == 0 - sys.call("/bin/rm -rf /tmp/trojan-go_extract.*") - if not result or not fs.access(client_file) then - return { - code = 1, - error = i18n.translatef("Can't move new file to path: %s", client_file) - } - end - - api.exec("/bin/chmod", {"-R", "755", client_file}) - - return {code = 0} -end diff --git a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/v2ray.lua b/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/v2ray.lua deleted file mode 100644 index e5339ac..0000000 --- a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/v2ray.lua +++ /dev/null @@ -1,166 +0,0 @@ -module("luci.model.cbi.passwall.api.v2ray", package.seeall) -local fs = require "nixio.fs" -local sys = require "luci.sys" -local util = require "luci.util" -local i18n = require "luci.i18n" -local ipkg = require("luci.model.ipkg") -local api = require "luci.model.cbi.passwall.api.api" - -local v2ray_api = "https://api.github.com/repos/v2fly/v2ray-core/releases/latest" -local is_armv7 = false - -function get_v2ray_file_path() - return api.uci_get_type("global_app", "v2ray_file") -end - -function get_v2ray_version() - if get_v2ray_file_path() and get_v2ray_file_path() ~= "" then - if fs.access(get_v2ray_file_path() .. "/v2ray") then - return sys.exec("echo -n $(" .. get_v2ray_file_path() .. "/v2ray -version | awk '{print $2}' | sed -n 1P" .. ")") - end - end - return "" -end - -function to_check(arch) - 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 - - local json = api.get_api_json(v2ray_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 needs_update = api.compare_versions(get_v2ray_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 = get_v2ray_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 = get_v2ray_version(), - 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/v2ray_download.*") - - local tmp_file = util.trim(util.exec("mktemp -u -t v2ray_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 isinstall_unzip = ipkg.installed("unzip") - if isinstall_unzip == nil then - ipkg.update() - ipkg.install("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/v2ray_extract.*") - local tmp_dir = util.trim(util.exec("mktemp -d -t v2ray_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) - if not file or file == "" then - sys.call("/bin/rm -rf /tmp/v2ray_extract.*") - return {code = 1, error = i18n.translate("Client file is required.")} - end - - local client_file = get_v2ray_file_path() - - sys.call("mkdir -p " .. client_file) - - 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 - local result = nil - if is_armv7 and is_armv7 == true then - result = api.exec("/bin/mv", { - "-f", file .. "/v2ray_armv7", file .. "/v2ctl_armv7", client_file - }, nil, api.command_timeout) == 0 - else - result = api.exec("/bin/mv", { - "-f", file .. "/v2ray", file .. "/v2ctl", client_file - }, nil, api.command_timeout) == 0 - end - sys.call("/bin/rm -rf /tmp/v2ray_extract.*") - if not result or not fs.access(client_file) then - return { - code = 1, - error = i18n.translatef("Can't move new file to path: %s", client_file) - } - end - - api.exec("/bin/chmod", {"-R", "755", client_file}) - - return {code = 0} -end diff --git a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/acl.lua b/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/acl.lua deleted file mode 100644 index 78fc29f..0000000 --- a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/acl.lua +++ /dev/null @@ -1,109 +0,0 @@ -local sys = require "luci.sys" -local appname = "passwall" - -m = Map(appname) - --- [[ 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 Node -local tcp_node_num = m:get("@global_other[0]", "tcp_node_num") or 1 -if tonumber(tcp_node_num) > 1 then - o = s:option(ListValue, "tcp_node", translate("TCP Node")) - for i = 1, tcp_node_num, 1 do o:value(i, "TCP_" .. i) end -end - ----- UDP Node -local udp_node_num = m:get("@global_other[0]", "udp_node_num") or 1 -if tonumber(udp_node_num) > 1 then - o = s:option(ListValue, "udp_node", translate("UDP Node")) - for i = 1, udp_node_num, 1 do o:value(i, "UDP_" .. i) end -end - ----- TCP Proxy Mode -o = s:option(ListValue, "tcp_proxy_mode", "TCP" .. translate("Proxy Mode")) -o.default = "default" -o.rmempty = false -o:value("default", translate("Default")) -o:value("disable", translate("No Proxy")) -o:value("global", translate("Global Proxy")) -o:value("gfwlist", translate("GFW List")) -o:value("chnroute", translate("Not China List")) -o:value("returnhome", translate("China List")) - ----- UDP Proxy Mode -o = s:option(ListValue, "udp_proxy_mode", "UDP" .. translate("Proxy Mode")) -o.default = "default" -o.rmempty = false -o:value("default", translate("Default")) -o:value("disable", translate("No Proxy")) -o:value("global", translate("Global Proxy")) -o:value("gfwlist", translate("GFW List")) -o:value("chnroute", translate("Game Mode")) -o:value("returnhome", translate("China List")) - ----- 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/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/app_update.lua b/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/app_update.lua deleted file mode 100644 index 8a1713a..0000000 --- a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/app_update.lua +++ /dev/null @@ -1,47 +0,0 @@ -local d = require "luci.dispatcher" -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/v2ray_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")) - ----- V2ray Path -o = s:option(Value, "v2ray_file", translate("V2ray Path"), translatef("if you want to run from memory, change the path, such as %s, Then save the application and update it manually.", "/tmp/v2ray/")) -o.default = "/usr/bin/v2ray/" -o.rmempty = false - ----- Trojan-Go Path -o = s:option(Value, "trojan_go_file", translate("Trojan-Go Path"), translatef("if you want to run from memory, change the path, such as %s, Then save the application and update it manually.", "/tmp/trojan-go")) -o.default = "/usr/bin/trojan-go" -o.rmempty = false - -o = s:option(Value, "trojan_go_latest", translate("Trojan-Go Version API"), translate("alternate API URL for version checking")) -o.default = "https://api.github.com/repos/peter-tank/trojan-go/releases/latest" - ----- Kcptun client Path -o = s:option(Value, "kcptun_client_file", translate("Kcptun Client Path"), translatef("if you want to run from memory, change the path, such as %s, Then save the application and update it manually.", "/tmp/kcptun-client")) -o.default = "/usr/bin/kcptun-client" -o.rmempty = false - ---[[ -o = s:option(Button, "_check_kcptun", translate("Manually update"), translatef("Make sure there is enough space to install %s", "kcptun")) -o.template = appname .. "/kcptun" -o.inputstyle = "apply" -o.btnclick = "onBtnClick_kcptun(this);" -o.id = "_kcptun-check_btn"]] -- - ----- Brook Path -o = s:option(Value, "brook_file", translate("Brook Path"), translatef("if you want to run from memory, change the path, such as %s, Then save the application and update it manually.", "/tmp/brook")) -o.default = "/usr/bin/brook" -o.rmempty = false - -return m diff --git a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/auto_switch.lua b/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/auto_switch.lua deleted file mode 100644 index 2e70062..0000000 --- a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/auto_switch.lua +++ /dev/null @@ -1,44 +0,0 @@ -local uci = require"luci.model.uci".cursor() -local api = require "luci.model.cbi.passwall.api.api" -local appname = "passwall" - -local nodes_table = {} -for k, e in ipairs(api.get_valid_nodes()) do - nodes_table[#nodes_table + 1] = { - id = e[".name"], - remarks = e.remarks_name - } -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 = "3" - ----- TCP Node --- local tcp_node_num = tonumber(m:get("@global_other[0]", "tcp_node_num") or 1) --- 暂时只支持TCP1 -local tcp_node_num = 1 -for i = 1, tcp_node_num, 1 do - o = s:option(ListValue, "tcp_main" .. i, "TCP " .. i .. " " .. translate("Main node")) - for k, v in pairs(nodes_table) do - o:value(v.id, v.remarks) - end - - o = s:option(DynamicList, "tcp_node" .. i, "TCP " .. i .. " " .. translate("List of backup nodes")) - for k, v in pairs(nodes_table) do - o:value(v.id, v.remarks) - end -end - -return m diff --git a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua b/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua deleted file mode 100644 index 0c89f01..0000000 --- a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua +++ /dev/null @@ -1,352 +0,0 @@ -local o = require "luci.dispatcher" -local uci = require"luci.model.uci".cursor() -local api = require "luci.model.cbi.passwall.api.api" -local appname = "passwall" - -local nodes_table = {} -for k, e in ipairs(api.get_valid_nodes()) do - nodes_table[#nodes_table + 1] = { - id = e[".name"], - remarks = e.remarks_name - } -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)([1-9])$") - if same then - remarks = translatef("Same as the tcp %s node", i) - else - for k, n in pairs(nodes_table) do - if (s.node == n.id) then - remarks = n.remarks; break - end - end - end - id = "0.0.0.0" .. ":" .. 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 - -m = Map(appname) -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 -local tcp_node_num = tonumber(m:get("@global_other[0]", "tcp_node_num") or 1) -for i = 1, tcp_node_num, 1 do - if i == 1 then - o = s:taboption("Main", ListValue, "tcp_node" .. i, translate("TCP Node")) - o.description = translate("For proxy specific list.") - - if tonumber(m:get("@auto_switch[0]", "enable") or 0) == 1 then - local now_node = luci.sys.exec(string.format("[ -f '/var/etc/%s/id/TCP_%s' ] && echo -n $(cat /var/etc/%s/id/TCP_%s)", appname, i, appname, i)) - if now_node and now_node ~= "" then - local e = uci:get_all(appname, now_node) - if e then - local remarks = "" - if e.type == "V2ray" and (e.protocol == "_balancing" or e.protocol == "_shunt") then - remarks = "%s:[%s] " % {translatef(e.type .. e.protocol), e.remarks} - else - if e.use_kcp and e.use_kcp == "1" then - remarks = "%s+%s:[%s] %s" % {e.type, "Kcptun", e.remarks, e.address} - else - remarks = "%s:[%s] %s:%s" % {e.type, e.remarks, e.address, e.port} - end - end - o.description = o.description .. "
" ..translatef("Current node: %s", remarks) - end - end - end - else - o = s:taboption("Main", ListValue, "tcp_node" .. i, translate("TCP Node") .. " " .. i) - end - o:value("nil", translate("Close")) - for k, v in pairs(nodes_table) do o:value(v.id, v.remarks) end -end - ----- UDP Node -local udp_node_num = tonumber(m:get("@global_other[0]", "udp_node_num") or 1) -for i = 1, udp_node_num, 1 do - if i == 1 then - o = s:taboption("Main", ListValue, "udp_node" .. i, translate("UDP Node")) - o.description = translate("For proxy game network, DNS hijack etc.") .. translate(" The selected server will not use Kcptun.") - o:value("nil", translate("Close")) - o:value("tcp_", translate("Same as the tcp node")) - --o:value("tcp", translate("Same as the tcp node")) - --o:value("tcp_", translate("Same as the tcp node") .. "(" .. translate("New process") .. ")") - else - o = s:taboption("Main", ListValue, "udp_node" .. i, translate("UDP Node") .. " " .. i) - o:value("nil", translate("Close")) - end - for k, v in pairs(nodes_table) do o:value(v.id, v.remarks) end -end - -s:tab("DNS", translate("DNS")) - -if api.is_finded("chinadns-ng") then - o = s:taboption("DNS", Flag, "chinadns_ng", translate("Use ChinaDNS-NG"), translate("When checked, forced to be set to dnsmasq upstream DNS.")) - o.default = "0" - - o = s:taboption("DNS", Flag, "fair_mode", translate("ChinaDNS-NG Fair Mode")) - o.default = "1" - o:depends("chinadns_ng", "1") -end - -o = s:taboption("DNS", Value, "up_china_dns", translate("Resolver For Local/WhiteList Domains") .. "(UDP)") -o.description = translate("IP:Port mode acceptable, multi value split with english comma.") .. "
" .. translate("When the selection is not the default, this DNS is forced to be set to dnsmasq upstream DNS.") -o.default = "default" -o:value("default", translate("Default")) -if api.is_finded("https-dns-proxy") then - o:value("https-dns-proxy", "https-dns-proxy(DoH)") -end -o:value("223.5.5.5", "223.5.5.5 (" .. translate("Ali") .. "DNS)") -o:value("223.6.6.6", "223.6.6.6 (" .. translate("Ali") .. "DNS)") -o:value("114.114.114.114", "114.114.114.114 (114DNS)") -o:value("114.114.115.115", "114.114.115.115 (114DNS)") -o:value("119.29.29.29", "119.29.29.29 (DNSPOD DNS)") -o:value("182.254.116.116", "182.254.116.116 (DNSPOD DNS)") -o:value("1.2.4.8", "1.2.4.8 (CNNIC DNS)") -o:value("210.2.4.8", "210.2.4.8 (CNNIC DNS)") -o:value("180.76.76.76", "180.76.76.76 (" .. translate("Baidu") .. "DNS)") - ----- DoH -o = s:taboption("DNS", Value, "up_china_dns_doh", translate("DoH request address")) -o:value("https://dns.alidns.com/dns-query,223.5.5.5,223.6.6.6", "AliDNS") -o:value("https://doh.pub/dns-query,119.29.29.29,119.28.28.28", "DNSPod") -o.default = "https://dns.alidns.com/dns-query,223.5.5.5,223.6.6.6" -o.validate = doh_validate -o:depends("up_china_dns", "https-dns-proxy") - ----- DNS Forward Mode -o = s:taboption("DNS", ListValue, "dns_mode", translate("Filter Mode")) -o.rmempty = false -o:reset_values() -if api.is_finded("pdnsd") then - o:value("pdnsd", "pdnsd") -end -if api.is_finded("dns2socks") then - o:value("dns2socks", "dns2socks") -end -if api.is_finded("https-dns-proxy") then - o:value("https-dns-proxy", "https-dns-proxy(DoH)") -end -o:value("udp", translatef("Requery DNS By %s", translate("UDP Node"))) -o:value("nonuse", translate("No Filter")) -o:value("custom", translate("Custom DNS")) - ----- 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_pdnsd_dns", translate("Resolver For The List Proxied")) --- o.description = translate("You can use other resolving DNS services as trusted DNS, Example: dns2socks, dns-forwarder... 127.0.0.1#5353
Only use two at most, english comma separation, If you do not fill in the # and the following port, you are using port 53.") -o.default = "tcp" -o:value("tcp", translatef("Requery DNS By %s", translate("TCP Node"))) -o:value("udp", translatef("Requery DNS By %s", translate("UDP Node"))) -o:depends("dns_mode", "pdnsd") - -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", "https-dns-proxy") - -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 = "https-dns-proxy", 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,176.103.130.131", "AdGuard") -o:value("https://cloudflare-dns.com/dns-query,1.1.1.1,1.0.0.1", "Cloudflare") -o:value("https://security.cloudflare-dns.com/dns-query,1.1.1.2,1.0.0.2", "Cloudflare-Security") -o:value("https://doh.opendns.com/dns-query,208.67.222.222,208.67.220.220", "OpenDNS") -o:value("https://dns.google/dns-query,8.8.8.8,8.8.4.4", "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,149.112.112.112", "Quad9-Recommended") -o.default = "https://dns.google/dns-query,8.8.8.8,8.8.4.4" -o.validate = doh_validate -o:depends({dns_mode = "https-dns-proxy"}) - ----- DNS Forward -o = s:taboption("DNS", Value, "dns_forward", translate("Filtered DNS(For Proxied Domains)"), translate("IP:Port mode acceptable, the 1st for 'dns2socks' if split with english comma.")) -o.default = "8.8.4.4" -o:value("8.8.4.4", "8.8.4.4 (Google DNS)") -o:value("8.8.8.8", "8.8.8.8 (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", Flag, "use_chnlist", translate("Use ChinaList"), translate("Only useful in non-gfwlist mode.") .. "
" .. translate("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.")) -o.default = "0" - -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("/etc/init.d/" .. appname .. " stop && /usr/share/" .. appname .. "/iptables.sh flush_ipset && /etc/init.d/" .. appname .. " restart") -end - -s:tab("Proxy", translate("Mode")) - ----- TCP Default Proxy Mode -o = s:taboption("Proxy", ListValue, "tcp_proxy_mode", "TCP" .. translate("Default") .. translate("Proxy Mode")) --- o.description = translate("If not available, try clearing the cache.") -o.default = "chnroute" -o.rmempty = false -o:value("disable", translate("No Proxy")) -o:value("global", translate("Global Proxy")) -o:value("gfwlist", translate("GFW List")) -o:value("chnroute", translate("Not China List")) -o:value("returnhome", translate("China List")) - ----- UDP Default Proxy Mode -o = s:taboption("Proxy", ListValue, "udp_proxy_mode", "UDP" .. translate("Default") .. translate("Proxy Mode")) -o.default = "chnroute" -o.rmempty = false -o:value("disable", translate("No Proxy")) -o:value("global", translate("Global Proxy")) -o:value("gfwlist", translate("GFW List")) -o:value("chnroute", translate("Game Mode")) -o:value("returnhome", translate("China List")) - ----- Localhost TCP Proxy Mode -o = 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.") -o:value("default", translate("Default")) -o:value("global", translate("Global Proxy")) -o:value("gfwlist", translate("GFW List")) -o:value("chnroute", translate("Not China List")) -o:value("returnhome", translate("China List")) -o.default = "default" -o.rmempty = false - ----- Localhost UDP Proxy Mode -o = s:taboption("Proxy", ListValue, "localhost_udp_proxy_mode", translate("Router Localhost") .. "UDP" .. translate("Proxy Mode")) -o:value("default", translate("Default")) -o:value("global", translate("Global Proxy")) -o:value("gfwlist", translate("GFW List")) -o:value("chnroute", translate("Game Mode")) -o:value("returnhome", translate("China List")) -o:value("disable", translate("No Proxy")) -o.default = "default" -o.rmempty = false - -s:tab("tips", translate("Tips")) - -o = s:taboption("tips", DummyValue, "") -o.template = appname .. "/global/tips" - --- [[ Socks Server ]]-- -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 - -o = s:option(ListValue, "node", translate("Socks Node")) -local tcp_node_num = tonumber(m:get("@global_other[0]", "tcp_node_num") or 1) -for i = 1, tcp_node_num, 1 do - o:value("tcp" .. i, translatef("Same as the tcp %s node", i)) -end -for k, v in pairs(nodes_table) do o:value(v.id, v.remarks) end - -o = s:option(Value, "port", "Socks" .. translate("Listen Port")) -o.default = 9050 -o.datatype = "port" -o.rmempty = false - -if api.is_finded("v2ray") then - o = s:option(Value, "http_port", "HTTP" .. translate("Listen Port") .. " " .. translate("0 is not use")) - o.default = 0 - o.datatype = "port" -end - -m:append(Template(appname .. "/global/footer")) - ---[[ -local apply = luci.http.formvalue("cbi.apply") -if apply then -os.execute("/etc/init.d/" .. appname .." restart") -end ---]] - -return m diff --git a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/log.lua b/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/log.lua deleted file mode 100644 index 859079e..0000000 --- a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/log.lua +++ /dev/null @@ -1,5 +0,0 @@ -f = SimpleForm("passwall") -f.reset = false -f.submit = false -f:append(Template("passwall/log/log")) -return f diff --git a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/node_list.lua b/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/node_list.lua deleted file mode 100644 index 6575c25..0000000 --- a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/node_list.lua +++ /dev/null @@ -1,153 +0,0 @@ -local d = require "luci.dispatcher" -local _api = require "luci.model.cbi.passwall.api.api" -local appname = "passwall" - -m = Map(appname) - --- [[ Other Settings ]]-- -s = m:section(TypedSection, "global_other") -s.anonymous = true - -o = s:option(MultiValue, "nodes_ping", "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 = s:option(MultiValue, "nodes_display", translate("Operation")) -o:value("compact_display_nodes", translate("Concise display nodes")) -o:value("show_add_mode", translate("Show Add Mode")) -o:value("show_group", translate("Show Group")) - --- [[ 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 "" -local nodes_display = m:get("@global_other[0]", "nodes_display") or "" - --- [[ Node List ]]-- -s = m:section(TypedSection, "nodes") -s.anonymous = true -s.addremove = true -s.template = "cbi/tblsection" -s.extedit = d.build_url("admin", "services", appname, "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(d.build_url("admin", "services", appname, "node_list")) -end - -if nodes_display:find("show_group") then - show_group = s:option(DummyValue, "group", translate("Group")) - show_group.cfgvalue = function(t, n) - local group = m:get(n, "group") or "无" - return group ~= "" and group or "无" - end -end - -s.sortable = true --- 简洁模式 -if nodes_display:find("compact_display_nodes") then - if show_group then show_group.width = "25%" 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 == "V2ray" then - local protocol = m:get(n, "protocol") - if protocol == "_balancing" then - type = type .. " 负载均衡" - elseif protocol == "_shunt" then - type = type .. " 分流" - end - 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 datatypes.ip6addr(address) then - str = str .. string.format("([%s]:%s)", address, port) - else - str = str .. string.format("(%s:%s)", address, port) - end - str = str .. string.format("", appname, n, address) - str = str .. string.format("", appname, n, port) - end - return str - end -else - ---- Add Mode - if nodes_display:find("show_add_mode") then - o = s:option(DummyValue, "add_mode", translate("Add Mode")) - o.cfgvalue = function(t, n) - local v = Value.cfgvalue(t, n) - if v and v ~= '' then - return v - else - return '手动' - end - end - end - - ---- Type - o = s:option(DummyValue, "type", translate("Type")) - o.cfgvalue = function(t, n) - local result = "" - local v = Value.cfgvalue(t, n) - if v then - result = translate(v) - if v == "V2ray" then - local protocol = m:get(n, "protocol") - if protocol == "_balancing" then - result = result .. " 负载均衡" - elseif protocol == "_shunt" then - result = result .. " 分流" - end - end - end - return result - end - - ---- Remarks - o = s:option(DummyValue, "remarks", translate("Remarks")) - - ---- Address - o = s:option(DummyValue, "address", translate("Address")) - o.cfgvalue = function(t, n) - return Value.cfgvalue(t, n) or "---" - end - - ---- Port - o = s:option(DummyValue, "port", translate("Port")) - o.cfgvalue = function(t, n) - return Value.cfgvalue(t, n) or "---" - end -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/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe.lua b/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe.lua deleted file mode 100644 index 3cd6757..0000000 --- a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe.lua +++ /dev/null @@ -1,84 +0,0 @@ -local appname = "passwall" - -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", 1) - ----- 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", 1) - ----- 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(luci.dispatcher.build_url("admin", "services", appname, "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(luci.dispatcher.build_url("admin", "services", appname, "log")) -end - -filter_enabled = s:option(Flag, "filter_enabled", translate("Filter keyword switch"), translate("When checked, below options can only be take effect.")) -o.default = 1 -o.rmempty = false - -filter_keyword = s:option(DynamicList, "filter_keyword", translate("Filter keyword")) - -o = s:option(Flag, "filter_keyword_discarded", translate("Filter keyword discarded"), translate("When checked, the keywords in the list are discarded. Otherwise, it is not discarded.")) -o.default = "1" -o.rmempty = false - -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 - -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/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/rule.lua b/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/rule.lua deleted file mode 100644 index ccc0033..0000000 --- a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/rule.lua +++ /dev/null @@ -1,64 +0,0 @@ -local d = require "luci.dispatcher" -local appname = "passwall" - -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" - -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", 1) - ----- 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", 1) - -s = m:section(TypedSection, "shunt_rules", "V2ray" .. translate("Shunt") .. translate("Rule")) -s.template = "cbi/tblsection" -s.anonymous = false -s.addremove = true -s.extedit = d.build_url("admin", "services", appname, "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/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/rule_list.lua b/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/rule_list.lua deleted file mode 100644 index bd5ad35..0000000 --- a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/rule_list.lua +++ /dev/null @@ -1,167 +0,0 @@ -local fs = require "nixio.fs" -local appname = "passwall" - -m = Map(appname) - --- [[ 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("proxy_list2", translate("Proxy List") .. " 2") -s:tab("proxy_list3", translate("Proxy List") .. " 3") - ----- Direct Hosts -local direct_host = string.format("/usr/share/%s/rules/direct_host", appname) -o = s:taboption("direct_list", TextValue, "direct_hosts", "", "" .. 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 = string.format("/usr/share/%s/rules/direct_ip", appname) -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) then - return nil, ipmask .. " " .. translate("Not valid IP format, please re-enter!") - end - end - return value -end - ----- Proxy Hosts -local proxy_host = string.format("/usr/share/%s/rules/proxy_host", appname) -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 = string.format("/usr/share/%s/rules/proxy_ip", appname) -o = s:taboption("proxy_list", TextValue, "blacklist_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) then - return nil, ipmask .. " " .. translate("Not valid IP format, please re-enter!") - end - end - return value -end - ----- Proxy Hosts 2 -local proxy_host2 = string.format("/usr/share/%s/rules/proxy_host2", appname) -o = s:taboption("proxy_list2", TextValue, "proxy_host2", "", "" .. 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_host2) or "" end -o.write = function(self, section, value) fs.writefile(proxy_host2, value:gsub("\r\n", "\n")) end -o.remove = function(self, section, value) fs.writefile(proxy_host2, "") 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 2 -local proxy_ip2 = string.format("/usr/share/%s/rules/proxy_ip2", appname) -o = s:taboption("proxy_list2", TextValue, "blacklist_ip2", "", "" .. 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_ip2) or "" end -o.write = function(self, section, value) fs.writefile(proxy_ip2, value:gsub("\r\n", "\n")) end -o.remove = function(self, section, value) fs.writefile(proxy_ip2, "") 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) then - return nil, ipmask .. " " .. translate("Not valid IP format, please re-enter!") - end - end - return value -end - ----- Proxy Hosts 3 -local proxy_host3 = string.format("/usr/share/%s/rules/proxy_host3", appname) -o = s:taboption("proxy_list3", TextValue, "proxy_host3", "", "" .. 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_host3) or "" end -o.write = function(self, section, value) fs.writefile(proxy_host3, value:gsub("\r\n", "\n")) end -o.remove = function(self, section, value) fs.writefile(proxy_host3, "") 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 3 -local proxy_ip3 = string.format("/usr/share/%s/rules/proxy_ip3", appname) -o = s:taboption("proxy_list3", TextValue, "blacklist_ip3", "", "" .. 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_ip3) or "" end -o.write = function(self, section, value) fs.writefile(proxy_ip3, value:gsub("\r\n", "\n")) end -o.remove = function(self, section, value) fs.writefile(proxy_ip3, "") 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) then - return nil, ipmask .. " " .. translate("Not valid IP format, please re-enter!") - end - end - return value -end - -return m diff --git a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/shunt_rules.lua b/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/shunt_rules.lua deleted file mode 100644 index 2162634..0000000 --- a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/shunt_rules.lua +++ /dev/null @@ -1,43 +0,0 @@ -local d = require "luci.dispatcher" -local appname = "passwall" - -m = Map(appname, "V2ray" .. translate("Shunt") .. translate("Rule")) -m.redirect = d.build_url("admin", "services", appname) - -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 - -domain_list = s:option(TextValue, "domain_list", translate("Domain")) -domain_list.rows = 15 -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 - if not datatypes.hostname(host) then - return nil, host .. " " .. translate("Not valid domain name, please re-enter!") - end - end - return value -end - -ip_list = s:option(TextValue, "ip_list", "IP") -ip_list.rows = 15 -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 not datatypes.ipmask4(ipmask) then - return nil, ipmask .. " " .. translate("Not valid IP format, please re-enter!") - end - end - return value -end - -return m diff --git a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/app.lua b/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/app.lua deleted file mode 100644 index 39ca61e..0000000 --- a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/app.lua +++ /dev/null @@ -1,149 +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) - d = TMP_BIN_PATH .. "/" .. d - cmd(string.format('[ ! -f "%s" ] && ln -s %s %s 2>/dev/null', d, s, d)) - return string.format("%s >/dev/null 2>&1 &", d .. " " ..command) -end - -local function gen_include() - cmd(string.format("echo '#!/bin/sh' > /var/etc/%s.include", CONFIG)) - local function extract_rules(a) - local result = "*" .. a - result = result .. "\n" .. sys.exec('iptables-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("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") - ucic:foreach(CONFIG, "user", function(user) - local id = user[".name"] - local enable = user.enable - if enable and tonumber(enable) == 1 then - 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)) - 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) - elseif type == "V2ray" then - config = require("luci.model.cbi.passwall.server.api.v2ray").gen_config(user) - bin = ln_start(_api.get_v2ray_path(), "v2ray", "-config=" .. config_file) - 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) - 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) - 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) - 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)) - 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)) - if udp_forward == 1 then - cmd(string.format('iptables -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("ps -w | 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(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/lienol/luci-app-passwall/luasrc/view/passwall/global/footer.htm b/lienol/luci-app-passwall/luasrc/view/passwall/global/footer.htm deleted file mode 100644 index 9d7fc00..0000000 --- a/lienol/luci-app-passwall/luasrc/view/passwall/global/footer.htm +++ /dev/null @@ -1,33 +0,0 @@ - \ No newline at end of file diff --git a/lienol/luci-app-passwall/luasrc/view/passwall/global/status.htm b/lienol/luci-app-passwall/luasrc/view/passwall/global/status.htm deleted file mode 100644 index e6fb79e..0000000 --- a/lienol/luci-app-passwall/luasrc/view/passwall/global/status.htm +++ /dev/null @@ -1,391 +0,0 @@ -<% -local dsp = require "luci.dispatcher" -local api = require "luci.model.cbi.passwall.api.api" - -local tcp_node_num = api.uci_get_type("global_other", "tcp_node_num", 1) -local udp_node_num = api.uci_get_type("global_other", "udp_node_num", 1) - -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/lienol/luci-app-passwall/luasrc/view/passwall/global/tips.htm b/lienol/luci-app-passwall/luasrc/view/passwall/global/tips.htm deleted file mode 100644 index 78c15b9..0000000 --- a/lienol/luci-app-passwall/luasrc/view/passwall/global/tips.htm +++ /dev/null @@ -1,12 +0,0 @@ -
- -
- <%:You can use load balancing for failover.%> -
- <%:Restore the default configuration method. Input example in the address bar:%> http://192.168.1.1/cgi-bin/luci/admin/services/passwall/reset_config -
- <%:Hide menu method, input example in the address bar:%> http://192.168.1.1/cgi-bin/luci/admin/services/passwall/hide -
- <%:After the hidden to the display, input example in the address bar:%> http://192.168.1.1/cgi-bin/luci/admin/services/passwall/show -
-
diff --git a/lienol/luci-app-passwall/luasrc/view/passwall/haproxy/status.htm b/lienol/luci-app-passwall/luasrc/view/passwall/haproxy/status.htm deleted file mode 100644 index 7e36c4b..0000000 --- a/lienol/luci-app-passwall/luasrc/view/passwall/haproxy/status.htm +++ /dev/null @@ -1,20 +0,0 @@ -

- - \ No newline at end of file diff --git a/lienol/luci-app-passwall/luasrc/view/passwall/node_list/link_add_node.htm b/lienol/luci-app-passwall/luasrc/view/passwall/node_list/link_add_node.htm deleted file mode 100644 index 05c5357..0000000 --- a/lienol/luci-app-passwall/luasrc/view/passwall/node_list/link_add_node.htm +++ /dev/null @@ -1,144 +0,0 @@ -<% -function trim(s) - return (s:gsub("^%s*(.-)%s*$", "%1")) -end -local dsp = require "luci.dispatcher" --%> - - - - - - - -
- -
- - - - - -
-
\ No newline at end of file diff --git a/lienol/luci-app-passwall/luasrc/view/passwall/rule/rule_version.htm b/lienol/luci-app-passwall/luasrc/view/passwall/rule/rule_version.htm deleted file mode 100644 index 4b08a61..0000000 --- a/lienol/luci-app-passwall/luasrc/view/passwall/rule/rule_version.htm +++ /dev/null @@ -1,70 +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 "" --%> - - -
-
-
- -
-
- - - - - -
-
-
-
-
\ No newline at end of file diff --git a/lienol/luci-app-passwall/luasrc/view/passwall/server/log.htm b/lienol/luci-app-passwall/luasrc/view/passwall/server/log.htm deleted file mode 100644 index 826964c..0000000 --- a/lienol/luci-app-passwall/luasrc/view/passwall/server/log.htm +++ /dev/null @@ -1,31 +0,0 @@ - -
- - <%:Logs%> - - - -
\ No newline at end of file diff --git a/lienol/luci-app-passwall/luasrc/view/passwall/server/users_list_status.htm b/lienol/luci-app-passwall/luasrc/view/passwall/server/users_list_status.htm deleted file mode 100644 index e6616c4..0000000 --- a/lienol/luci-app-passwall/luasrc/view/passwall/server/users_list_status.htm +++ /dev/null @@ -1,19 +0,0 @@ - \ No newline at end of file diff --git a/lienol/luci-app-passwall/root/etc/config/passwall b/lienol/luci-app-passwall/root/etc/config/passwall deleted file mode 100644 index b95c030..0000000 --- a/lienol/luci-app-passwall/root/etc/config/passwall +++ /dev/null @@ -1,106 +0,0 @@ - -config global - option enabled '0' - option tcp_node1 'nil' - option udp_node1 'nil' - option dns_mode 'pdnsd' - option up_china_dns 'default' - option dns_forward '8.8.4.4' - option use_chnlist '0' - option use_tcp_node_resolve_dns '1' - option tcp_proxy_mode 'chnroute' - option udp_proxy_mode 'chnroute' - option localhost_tcp_proxy_mode 'gfwlist' - option localhost_udp_proxy_mode 'gfwlist' - option socks_server '0.0.0.0:1080' - -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 tcp_node_num '1' - option udp_node_num '1' - option status 'big_icon show_check_port show_ip111' - option nodes_ping 'auto_ping tcping' - option nodes_display 'compact_display_nodes show_add_mode' - -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' - -config global_app - option v2ray_file '/usr/bin/v2ray/' - option trojan_go_file '/usr/bin/trojan-go' - option kcptun_client_file '/usr/bin/kcptun-client' - option brook_file '/usr/bin/brook' - option trojan_go_latest 'https://api.github.com/repos/peter-tank/trojan-go/releases/latest' - -config global_subscribe - option subscribe_proxy '0' - option auto_update_subscribe '0' - option filter_enabled '1' - option filter_keyword_discarded '1' - option allowInsecure '1' - list filter_keyword '过期时间' - list filter_keyword '剩余流量' - list filter_keyword 'QQ群' - list filter_keyword '官网' - -config auto_switch - option testing_time '1' - option enable '0' - -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/lienol/luci-app-passwall/root/etc/init.d/passwall b/lienol/luci-app-passwall/root/etc/init.d/passwall deleted file mode 100755 index a8d7316..0000000 --- a/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/lienol/luci-app-passwall/root/etc/init.d/passwall_server b/lienol/luci-app-passwall/root/etc/init.d/passwall_server deleted file mode 100755 index 43504a8..0000000 --- a/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/lienol/luci-app-passwall/root/usr/share/passwall/app.sh b/lienol/luci-app-passwall/root/usr/share/passwall/app.sh deleted file mode 100755 index d964892..0000000 --- a/lienol/luci-app-passwall/root/usr/share/passwall/app.sh +++ /dev/null @@ -1,1239 +0,0 @@ -#!/bin/sh -# Copyright (C) 2018-2020 L-WRT Team - -. $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 -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 -RESOLVFILE=/tmp/resolv.conf.d/resolv.conf.auto -LOCAL_DOH_PORT=7912 -DNS_PORT=7913 -TUN_DNS="127.0.0.1#${DNS_PORT}" -IS_DEFAULT_DNS= -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_V2RAY=$LUA_API_PATH/gen_v2ray.lua -API_GEN_V2RAY_PROTO=$LUA_API_PATH/gen_v2ray_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}}" -} - -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 fwd_dns="${fwd_dns}" -v outf="${outf}" ' - BEGIN { - if(outf == "") outf="/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) >>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=$2 - 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}" -p "/usr/bin/v2ray/{path_name}" "$@" | head -n1 -} - -ln_start_bin() { - local file_func=${1} - local ln_name=${2} - - shift 2; - 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}"} "$@" >/dev/null 2>&1 & -} - -ENABLED=$(config_t_get global enabled 0) - -TCP_NODE_NUM=$(config_t_get global_other tcp_node_num 1) -for i in $(seq 1 $TCP_NODE_NUM); do - eval TCP_NODE$i=$(config_t_get global tcp_node$i nil) -done -TCP_REDIR_PORT1=$(config_t_get global_forwarding tcp_redir_port 1041) -TCP_REDIR_PORT2=$(expr $TCP_REDIR_PORT1 + 1) -TCP_REDIR_PORT3=$(expr $TCP_REDIR_PORT2 + 1) - -UDP_NODE_NUM=$(config_t_get global_other udp_node_num 1) -for i in $(seq 1 $UDP_NODE_NUM); do - eval UDP_NODE$i=$(config_t_get global udp_node$i nil) -done -UDP_REDIR_PORT1=$(config_t_get global_forwarding udp_redir_port 1051) -UDP_REDIR_PORT2=$(expr $UDP_REDIR_PORT1 + 1) -UDP_REDIR_PORT3=$(expr $UDP_REDIR_PORT2 + 1) - -[ "$UDP_NODE1" == "tcp_" ] && UDP_NODE1=$TCP_NODE1 -[ "$UDP_NODE1" == "tcp" ] && UDP_REDIR_PORT1=$TCP_REDIR_PORT1 - -# Dynamic variables (Used to record) -# TCP_NODE1_IP="" UDP_NODE1_IP="" TCP_NODE1_PORT="" UDP_NODE1_PORT="" TCP_NODE1_TYPE="" UDP_NODE1_TYPE="" - -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 - -load_config() { - local auto_switch_list=$(config_t_get auto_switch tcp_node1 nil) - [ -n "$auto_switch_list" -a "$auto_switch_list" != "nil" ] && { - for tmp in $auto_switch_list; do - tmp_id=$(config_n_get $tmp address nil) - [ "$tmp_id" == "nil" ] && { - uci -q del_list $CONFIG.@auto_switch[0].tcp_node1=$tmp - uci commit $CONFIG - } - done - } - - [ "$ENABLED" != 1 ] && NO_PROXY=1 - [ "$TCP_NODE1" == "nil" -a "$UDP_NODE1" == "nil" ] && { - echolog "没有选择节点!" - NO_PROXY=1 - } - - CHINADNS_NG=$(config_t_get global chinadns_ng 0) - 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 1) - USE_CHNLIST=$(config_t_get global use_chnlist 0) - process=1 - if [ "$(config_t_get global_forwarding process 0)" = "0" ]; then - process=$(cat /proc/cpuinfo | grep 'processor' | wc -l) - else - process=$(config_t_get global_forwarding process) - fi - LOCAL_DNS=$(config_t_get global up_china_dns default | sed 's/:/#/g') - [ -f "${RESOLVFILE}" ] && [ -s "${RESOLVFILE}" ] || RESOLVFILE=/tmp/resolv.conf.auto - 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 ' ' ',') - if [ "${LOCAL_DNS}" = "default" ]; then - IS_DEFAULT_DNS=1 - LOCAL_DNS="${DEFAULT_DNS:-119.29.29.29}" - fi - PROXY_IPV6=$(config_t_get global_forwarding proxy_ipv6 0) - mkdir -p /var/etc $TMP_PATH $TMP_BIN_PATH $TMP_ID_PATH $TMP_PORT_PATH - return 0 -} - -run_socks() { - local node=$1 - local bind=$2 - local socks_port=$3 - local config_file=$4 - local http_port=$5 - local http_config_file=$6 - local id=$7 - local relay_port=$8 - 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" == "v2ray" ] && ([ -n "$(config_n_get $node balancing_node)" ] || [ "$(config_n_get $node default_node)" != "nil" ]); 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) - _username=$(config_n_get $node username) - _password=$(config_n_get $node password) - [ -n "$_username" ] && [ -n "$_password" ] && local _auth="--uname $_username --passwd $_password" - ln_start_bin "$(first_type ssocks)" ssocks_SOCKS_$id --listen $socks_port --socks $server_host:$port $_auth - ;; - v2ray) - lua $API_GEN_V2RAY $node nil nil $socks_port > $config_file - ln_start_bin "$(first_type $(config_t_get global_app v2ray_file notset)/v2ray v2ray)" v2ray -config="$config_file" - ;; - trojan-go) - lua $API_GEN_TROJAN $node client $bind $socks_port $server_host $port > $config_file - ln_start_bin "$(first_type $(config_t_get global_app trojan_go_file notset) trojan-go)" trojan-go -config "$config_file" - ;; - trojan*) - lua $API_GEN_TROJAN $node client $bind $socks_port $server_host $port > $config_file - ln_start_bin "$(first_type ${type})" "${type}" -c "$config_file" - ;; - naiveproxy) - lua $API_GEN_NAIVE $node socks $bind $socks_port $server_host $port > $config_file - ln_start_bin "$(first_type naive)" naive "$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 notset) brook)" "brook_SOCKS_$id" "$protocol" --socks5 "$bind:$socks_port" -s "$server_host:$port" -p "$(config_n_get $node password)" - ;; - ss|ssr) - lua $API_GEN_SS $node "0.0.0.0" $socks_port $server_host $port > $config_file - ln_start_bin "$(first_type ${type}-local)" "${type}-local" -c "$config_file" -b "$bind" -u - ;; - esac - - # socks to http - [ "$http_port" != "0" ] && [ "$http_config_file" != "nil" ] && { - lua $API_GEN_V2RAY_PROTO http "0.0.0.0" $http_port socks "127.0.0.1" $socks_port $_username $_password > $http_config_file - ln_start_bin "$(first_type $(config_t_get global_app v2ray_file notset)/v2ray v2ray)" v2ray -config="$http_config_file" - } - unset _username _password _auth -} - -run_redir() { - local node=$1 - local bind=$2 - local local_port=$3 - local config_file=$4 - local redir_type=$5 - 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 "$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 - } - [ "$server_host" == "127.0.0.1" ] && process=1 - [ "$bind" != "127.0.0.1" ] && echolog "${redir_type}_${6}节点:$remarks,节点:${server_host}:${port},监听端口:$local_port" - } - eval ${redir_type}_NODE${6}_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$6 - ln_start_bin "$(first_type ipt2socks)" "ipt2socks_udp_$6" -U -l "$port" -b 0.0.0.0 -s "$node_address" -p "$node_port" -R - ;; - v2ray) - lua $API_GEN_V2RAY $node udp $local_port nil > $config_file - ln_start_bin "$(first_type $(config_t_get global_app v2ray_file notset)/v2ray v2ray)" v2ray -config="$config_file" - ;; - trojan-go) - lua $API_GEN_TROJAN $node nat "0.0.0.0" $local_port >$config_file - ln_start_bin "$(first_type $(config_t_get global_app trojan_go_file notset) trojan-go)" trojan-go -config "$config_file" - ;; - trojan*) - lua $API_GEN_TROJAN $node nat "0.0.0.0" $local_port >$config_file - ln_start_bin "$(first_type ${type})" "${type}" -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 notset) brook)" "brook_udp_$6" tproxy -l ":$local_port" -s "$server_host:$port" -p "$(config_n_get $node password)" - fi - ;; - ss|ssr) - lua $API_GEN_SS $node "0.0.0.0" $local_port > $config_file - ln_start_bin "$(first_type ${type}-redir)" "${type}-redir" -c "$config_file" -U - ;; - 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 notset) kcptun-client)" "kcptun_tcp_$6" $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) - ;; - v2ray) - local extra_param="tcp" - [ "$6" == 1 ] && [ "$UDP_NODE1" == "tcp" ] && extra_param="tcp,udp" - lua $API_GEN_V2RAY $node $extra_param $local_port nil > $config_file - ln_start_bin "$(first_type $(config_t_get global_app v2ray_file notset)/v2ray v2ray)" v2ray -config="$config_file" - ;; - trojan-go) - lua $API_GEN_TROJAN $node nat "0.0.0.0" $local_port > $config_file - ln_start_bin "$(first_type $(config_t_get global_app trojan_go_file notset) trojan-go)" trojan-go -config "$config_file" - ;; - trojan*) - lua $API_GEN_TROJAN $node nat "0.0.0.0" $local_port > $config_file - for k in $(seq 1 $process); do - ln_start_bin "$(first_type ${type})" "${type}" -c "$config_file" - done - ;; - naiveproxy) - lua $API_GEN_NAIVE $node redir "0.0.0.0" $local_port > $config_file - ln_start_bin "$(first_type naive)" naive "$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 notset) brook)" "brook_tcp_$6" 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转换透明代理!" - [ "$6" == 1 ] && [ "$UDP_NODE1" == "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 notset) brook)" "brook_tcp_$6" tproxy -l ":$local_port" -s "$server_ip:$port" -p "$(config_n_get $node password)" - fi - ;; - ss|ssr) - if [ "$kcptun_use" == "1" ]; then - lua $API_GEN_SS $node "0.0.0.0" $local_port "127.0.0.1" $KCPTUN_REDIR_PORT > $config_file - process=1 - [ "$6" == 1 ] && [ "$UDP_NODE1" == "tcp" ] && echolog "Kcptun不支持UDP转发!" - else - lua $API_GEN_SS $node "0.0.0.0" $local_port > $config_file - [ "$6" == 1 ] && [ "$UDP_NODE1" == "tcp" ] && extra_param="-u" - fi - for k in $(seq 1 $process); do - ln_start_bin "$(first_type ${type}-redir)" "${type}-redir" -c "$config_file" $extra_param - done - ;; - esac - if [ -n "$_socks_flag" ]; then - local extra_param="-T" - [ "$6" == 1 ] && [ "$UDP_NODE1" == "tcp" ] && extra_param="" - ln_start_bin "$(first_type ipt2socks)" "ipt2socks_tcp_$6" -l "$local_port" -b 0.0.0.0 -s "$_socks_address" -p "$_socks_port" -R $extra_param - fi - unset _socks_flag _socks_address _socks_port _socks_username _socks_password - ;; - esac - return 0 -} - -node_switch() { - local i=$3 - local node=$4 - [ -n "$1" -a -n "$2" -a -n "$3" -a -n "$4" ] && { - ps -w | grep -E "$TMP_PATH" | grep -i "${1}_${i}" | grep -v "grep" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 & - local config_file=$TMP_PATH/${1}_${i}.json - eval current_port=\$${1}_REDIR_PORT${i} - local port=$(cat $TMP_PORT_PATH/${1}_${i}) - run_redir $node "0.0.0.0" $port $config_file $1 $i - echo $node > $TMP_ID_PATH/${1}_${i} - #local node_net=$(echo $1 | tr 'A-Z' 'a-z') - #uci set $CONFIG.@global[0].${node_net}_node${i}=$node - #uci commit $CONFIG - /etc/init.d/dnsmasq restart >/dev/null 2>&1 - } -} - -start_redir() { - eval num=\$${1}_NODE_NUM - for i in $(seq 1 $num); do - eval node=\$${1}_NODE$i - [ "$node" != "nil" ] && { - TYPE=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z') - local config_file=$TMP_PATH/${1}_${i}.json - eval current_port=\$${1}_REDIR_PORT$i - local port=$(echo $(get_new_port $current_port $2)) - eval ${1}_REDIR${i}=$port - run_redir $node "0.0.0.0" $port $config_file $1 $i - #eval ip=\$${1}_NODE${i}_IP - echo $node > $TMP_ID_PATH/${1}_${i} - echo $port > $TMP_PORT_PATH/${1}_${i} - } - done -} - -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) - if [ "$(echo $node | grep ^tcp)" ]; then - local num=$(echo $node | sed "s/tcp//g") - eval node=\$TCP_NODE$num - fi - [ "$node" == "nil" ] && continue - local port=$(config_n_get $id port) - local config_file=$TMP_PATH/SOCKS_${id}.json - local http_port=$(config_n_get $id http_port 0) - local http_config_file=$TMP_PATH/SOCKS2HTTP_${id}.json - run_socks $node "0.0.0.0" $port $config_file $http_port $http_config_file $id - done -} - -clean_log() { - logsnum=$(cat $LOG_FILE 2>/dev/null | wc -l) - [ "$logsnum" -gt 1000 ] && { - echo "" > $LOG_FILE - echolog "日志文件过长,清空处理!" - } -} - -start_crontab() { - touch /etc/crontabs/root - sed -i "/$CONFIG/d" /etc/crontabs/root >/dev/null 2>&1 & - 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() { - touch /etc/crontabs/root - sed -i "/$CONFIG/d" /etc/crontabs/root >/dev/null 2>&1 & - ps | grep "$APP_PATH/test.sh" | grep -v "grep" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 & - /etc/init.d/cron restart - #echolog "清除定时执行命令。" -} - -start_dns() { - if [ "${LOCAL_DNS}" = "https-dns-proxy" ]; then - _doh=$(config_t_get global up_china_dns_doh "https://dns.alidns.com/dns-query,223.5.5.5,223.6.6.6,2400:3200::1,2400:3200:baba::1") - _doh_url=$(echo $_doh | awk -F ',' '{print $1}') - _doh_bootstrap=$(echo $_doh | cut -d ',' -sf 2-) - ln_start_bin "$(first_type https-dns-proxy)" https-dns-proxy -a 127.0.0.1 -p "${LOCAL_DOH_PORT}" -b "${_doh_bootstrap}" -r "${_doh_url}" -4 - LOCAL_DNS="127.0.0.1#${LOCAL_DOH_PORT}" - unset _doh _doh_url _doh_bootstrap - fi - - local pdnsd_forward other_port up_trust_pdnsd_dns msg - local global chnlist returnhome china_ng_chn china_ng_gfw chnlist_param gfwlist_param extra_mode - dns_listen_port=${DNS_PORT} - pdnsd_forward=${DNS_FORWARD} - other_port=$(expr $DNS_PORT + 1) - china_ng_gfw="127.0.0.1#${other_port}" - china_ng_chn="${LOCAL_DNS}" - returnhome=$(echo "${TCP_PROXY_MODE}${LOCALHOST_TCP_PROXY_MODE}${UDP_PROXY_MODE}${LOCALHOST_UDP_PROXY_MODE}" | grep "returnhome") - global=$(echo "${TCP_PROXY_MODE}${LOCALHOST_TCP_PROXY_MODE}${UDP_PROXY_MODE}${LOCALHOST_UDP_PROXY_MODE}" | grep "global") - chnlist=$(echo "${TCP_PROXY_MODE}${LOCALHOST_TCP_PROXY_MODE}${UDP_PROXY_MODE}${LOCALHOST_UDP_PROXY_MODE}" | grep "chnroute") - [ -n "${returnhome}" ] && china_ng_chn="${china_ng_gfw}" && china_ng_gfw="${LOCAL_DNS}" - sed -n 's/^ipset=\/\.\?\([^/]*\).*$/\1/p' "${RULES_PATH}/gfwlist.conf" | sort -u > "${TMP_PATH}/gfwlist.txt" - echolog "过滤服务配置:准备接管域名解析[$?]..." - - [ "$CHINADNS_NG" = "1" ] && { - echolog " | - (chinadns-ng) 只支持2~4级的域名过滤..." - [ -z "${global}${chnlist}" ] && echolog " | - (chinadns-ng) 此模式下,列表外的域名查询会同时发送给本地DNS(可切换到Pdnsd + TCP节点模式解决)..." - [ -n "${returnhome}" ] && msg="本地" || msg="代理" - [ -z "${global}${chnlist}" ] && echolog " | - (chinadns-ng) 列表外域名查询的结果,不在中国IP段内(chnroute/chnroute6)时,只采信${msg} DNS 的应答..." - echolog " | - (chinadns-ng) 上游 DNS (${china_ng_gfw}) 有一定概率会比 DNS (${china_ng_chn}) 先返回的话(比如 DNS 的本地查询缓存),启用 '公平模式' 可以优先接受${msg} DNS 的中国IP段内(chnroute/chnroute6)的应答..." - if [ "$DNS_MODE" = "pdnsd" ]; then - msg="pdnsd" - elif [ "$DNS_MODE" = "dns2socks" ]; then - #[ -n "${global}${chnlist}" ] && TUN_DNS=${china_ng_gfw} - msg="dns2socks" - elif [ "$DNS_MODE" = "https-dns-proxy" ]; then - msg="https-dns-proxy(DoH)" - elif [ "$DNS_MODE" = "udp" ]; then - use_udp_node_resolve_dns=1 - if [ -z "${returnhome}" ]; then - china_ng_gfw="${DNS_FORWARD}" - else - china_ng_chn="${DNS_FORWARD}" - fi - 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 - chnlist_param= - [ "$USE_CHNLIST" = "1" ] && { - cp -a "${RULES_PATH}/chnlist" "${TMP_PATH}/chnlist" - if [ -z "${returnhome}" ]; then - cat "${RULES_PATH}/direct_host" >> "${TMP_PATH}/chnlist" - echolog " | - [$?](chinadns-ng) 域名白名单合并到中国域名表" - cat "${RULES_PATH}/proxy_host" >> "${TMP_PATH}/gfwlist.txt" - [ -f "${RULES_PATH}/proxy_host2" ] && cat "${RULES_PATH}/proxy_host2" >> "${TMP_PATH}/gfwlist.txt" - [ -f "${RULES_PATH}/proxy_host3" ] && cat "${RULES_PATH}/proxy_host3" >> "${TMP_PATH}/gfwlist.txt" - echolog " | - [$?](chinadns-ng) 代理域名表合并到防火墙域名表" - gfwlist_param="${TMP_PATH}/gfwlist.txt" - else - echolog " | - (chinadns-ng) 白名单不与中国域名表合并" - cat "${RULES_PATH}/proxy_host" >> "${TMP_PATH}/chnlist" - [ -f "${RULES_PATH}/proxy_host2" ] && cat "${RULES_PATH}/proxy_host2" >> "${TMP_PATH}/chnlist" - [ -f "${RULES_PATH}/proxy_host3" ] && cat "${RULES_PATH}/proxy_host3" >> "${TMP_PATH}/chnlist" - echolog " | - [$?](chinadns-ng) 忽略防火墙域名表,代理域名表合并到中国域名表" - fi - chnlist_param="${TMP_PATH}/chnlist" - chnlist_param=${chnlist_param:+-m "${chnlist_param}" -M} - } - [ "$(config_t_get global fair_mode 1)" = "1" ] && extra_mode="-f" - ln_start_bin "$(first_type chinadns-ng)" chinadns-ng -l "${dns_listen_port}" ${china_ng_chn:+-c "${china_ng_chn}"} ${chnlist_param} ${china_ng_gfw:+-t "${china_ng_gfw}"} ${gfwlist_param:+-g "${gfwlist_param}"} $extra_mode - echolog " + 过滤服务:ChinaDNS-NG(:${dns_listen_port}${extra_mode}) + ${msg}:中国域名列表:${china_ng_chn:-D114.114.114.114},防火墙域名列表:${china_ng_gfw:-D8.8.8.8}" - #[ -n "${global}${chnlist}" ] && [ -z "${returnhome}" ] && TUN_DNS="${china_ng_gfw}" - dns_listen_port=${other_port} - } - - case "$DNS_MODE" in - nonuse) - echolog " - 被禁用,设置为非 '默认DNS' 并开启广告过滤可以按本插件内置的广告域名表进行过滤..." - TUN_DNS="" - ;; - dns2socks) - echolog " - 域名解析:dns2socks..." - ;; - https-dns-proxy) - 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 - echolog " - 域名解析 https-dns-proxy(DOH)..." - ;; - pdnsd) - up_trust_pdnsd_dns=$(config_t_get global up_trust_pdnsd_dns "nil") - if [ "$up_trust_pdnsd_dns" = "udp" ]; then - use_udp_node_resolve_dns=1 - msg="UDP节点" - elif [ "${up_trust_pdnsd_dns}" = "nil" ]; then - msg="TCP节点" - fi - echolog " - 域名解析:pdnsd + 使用(${msg})解析域名..." - ;; - udp) - use_udp_node_resolve_dns=1 - TUN_DNS=${DNS_FORWARD} - echolog " - 域名解析:直接使用UDP节点请求DNS($TUN_DNS)" - ;; - custom) - [ "$CHINADNS_NG" != "1" ] && { - custom_dns=$(config_t_get global custom_dns) - TUN_DNS="$(echo ${custom_dns} | sed 's/:/#/g')" - echolog " - 域名解析:直接使用UDP协议自定义DNS($TUN_DNS)解析..." - } - ;; - esac - if [ -n "$(echo ${DNS_MODE} | grep pdnsd)" ]; then - gen_pdnsd_config "${dns_listen_port}" "${pdnsd_forward}" - ln_start_bin "$(first_type pdnsd)" pdnsd --daemon -c "${TMP_PATH}/pdnsd/pdnsd.conf" -d - fi - if [ -n "$(echo ${DNS_MODE} | grep 'https-dns-proxy')" ]; then - up_trust_doh=$(config_t_get global up_trust_doh "https://dns.google/dns-query,8.8.8.8,8.8.4.4") - _doh_url=$(echo $up_trust_doh | awk -F ',' '{print $1}') - _doh_port=$(echo $_doh_url | sed "s/:\/\///g" | awk -F ':' '{print $2}'| awk -F '/' '{print $1}') - _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") - ln_start_bin "$(first_type https-dns-proxy)" https-dns-proxy -a 127.0.0.1 -p "${dns_listen_port}" -b "${_doh_bootstrap}" -r "${_doh_url}" -4 -t socks5h://${socks_server} - 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 - ln_start_bin "$(first_type https-dns-proxy)" https-dns-proxy -a 127.0.0.1 -p "${dns_listen_port}" -b "${_doh_bootstrap}" -r "${_doh_url}" -4 - unset _dns _doh_bootstrap_dns - fi - unset _doh_url _doh_port _doh_bootstrap - fi - if [ -n "$(echo ${DNS_MODE}${up_trust_pdnsd_dns} | grep dns2socks)" ]; then - 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 "$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-D46.182.19.48:53}" - #[ "$CHINADNS_NG" = "1" ] && [ -n "${global}${chnlist}" ] && [ -z "${returnhome}" ] && TUN_DNS=$(echo "${dns_listen_port}" | sed 's/:/#/g') - fi - [ "${use_udp_node_resolve_dns}" = "1" ] && echolog " * 要求代理 DNS 请求,如上游 DNS 非直连地址,确保 UDP 代理打开,并且已经正确转发!" - [ "${use_tcp_node_resolve_dns}" = "1" ] && echolog " * 请确认上游 DNS 支持 TCP 查询,如非直连地址,确保 TCP 代理打开,并且已经正确转发!" -} - -add_dnsmasq() { - local global returnhome chnlist gfwlist 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 - 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") - - if [ "${USE_CHNLIST}" = "1" ] && [ -n "${gfwlist}" ]; then - USE_CHNLIST=0 - fi - - #始终用国内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" "${fwd_dns}" "${TMP_DNSMASQ_PATH}/01-vpsiplist_host.conf" - echolog " - [$?]节点列表中的域名(vpsiplist):${fwd_dns:-默认}" - - #始终用国内DNS解析直连(白名单)列表 - fwd_dns="${LOCAL_DNS}" - #如果使用ChinaDNS-NG则直接交给它处理 - [ "$CHINADNS_NG" = "1" ] && unset fwd_dns - #如果没使用chnlist直接使用默认DNS - [ "${USE_CHNLIST}" = "0" ] && unset fwd_dns - sort -u "${RULES_PATH}/direct_host" | gen_dnsmasq_items "whitelist" "${fwd_dns}" "${TMP_DNSMASQ_PATH}/00-direct_host.conf" - echolog " - [$?]域名白名单(whitelist):${fwd_dns:-默认}" - - #当勾选使用chnlist,仅当使用大陆白名单或回国模式 - [ "${USE_CHNLIST}" = "1" ] && { - fwd_dns="${LOCAL_DNS}" - [ -n "${returnhome}" ] || [ -n "${chnlist}" ] && { - [ -n "${global}" ] && unset fwd_dns - #如果使用Chinadns-NG直接交给它处理 - [ "$CHINADNS_NG" = "1" ] && unset fwd_dns - #如果使用回国模式,设置DNS为远程DNS。 - [ -n "${returnhome}" ] && fwd_dns="${TUN_DNS}" - sort -u "${RULES_PATH}/chnlist" | gen_dnsmasq_items "chnroute" "${fwd_dns}" "${TMP_DNSMASQ_PATH}/chinalist_host.conf" - echolog " - [$?]中国域名表(chnroute):${fwd_dns:-默认}" - } - } - - #分流规则 - fwd_dns="${TUN_DNS}" - #如果使用chnlist直接使用默认DNS - [ "${USE_CHNLIST}" = "1" ] && unset fwd_dns - local shunt_ids=$(uci show $CONFIG | grep "=shunt_rules" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}') - for shunt_id in $shunt_ids; do - config_n_get $shunt_id domain_list | tr -s "\r\n" "\n" | gen_dnsmasq_items "shuntlist" "${fwd_dns}" "${TMP_DNSMASQ_PATH}/shunt_host.conf" - echolog " - [$?]$shunt_id分流规则(shuntlist):${fwd_dns:-默认}" - done - - #始终使用远程DNS解析代理(黑名单)列表 - fwd_dns="${TUN_DNS}" - #如果使用Chinadns-NG直接交给它处理 - [ "$CHINADNS_NG" = "1" ] && unset fwd_dns - #如果使用chnlist直接使用默认DNS - [ "${USE_CHNLIST}" = "1" ] && unset fwd_dns - sort -u "${RULES_PATH}/proxy_host" | gen_dnsmasq_items "blacklist" "${fwd_dns}" "${TMP_DNSMASQ_PATH}/12-proxy_host.conf" - [ "2" -le "$TCP_NODE_NUM" ] && sort -u "${RULES_PATH}/proxy_host2" | gen_dnsmasq_items "blacklist2" "${fwd_dns}" "${TMP_DNSMASQ_PATH}/11-proxy_host2.conf" - [ "3" -le "$TCP_NODE_NUM" ] && sort -u "${RULES_PATH}/proxy_host3" | gen_dnsmasq_items "blacklist3" "${fwd_dns}" "${TMP_DNSMASQ_PATH}/10-proxy_host3.conf" - echolog " - [$?]代理域名表(blacklist):${fwd_dns:-默认}" - - #如果没有使用回国模式 - [ -z "${returnhome}" ] && { - fwd_dns="${TUN_DNS}" - #如果使用Chinadns-NG直接交给它处理 - [ "$CHINADNS_NG" = "1" ] && unset fwd_dns - #如果使用chnlist直接使用默认DNS - [ "${USE_CHNLIST}" = "1" ] && unset fwd_dns - sort -u "${TMP_PATH}/gfwlist.txt" | gen_dnsmasq_items "gfwlist" "${fwd_dns}" "${TMP_DNSMASQ_PATH}/gfwlist.conf" - #sort -u "${TMP_PATH}/gfwlist.txt" | gen_dnsmasq_items "gfwlist,gfwlist6" "${fwd_dns}" "${TMP_DNSMASQ_PATH}/gfwlist.conf" - echolog " - [$?]防火墙域名表(gfwlist):${fwd_dns:-默认}" - } - - #如果开启了通过代理订阅 - [ "$(config_t_get global_subscribe subscribe_proxy 0)" = "1" ] && { - fwd_dns="${TUN_DNS}" - #如果使用Chinadns-NG直接交给它处理 - [ "$CHINADNS_NG" = "1" ] && unset fwd_dns - #如果使用chnlist直接使用默认DNS - [ "${USE_CHNLIST}" = "1" ] && unset fwd_dns - items=$(get_enabled_anonymous_secs "@subscribe_list") - for item in ${items}; do - host_from_url "$(config_n_get ${item} url)" | gen_dnsmasq_items "blacklist" "${fwd_dns}" "${TMP_DNSMASQ_PATH}/subscribe.conf" - echolog " - [$?]节点订阅域名,$(host_from_url $(config_n_get ${item} url)):${fwd_dns:-默认}" - done - } - fi - - if [ "${DNS_MODE}" != "nouse" ] || [ "${IS_DEFAULT_DNS}" != "1" ]; then - msg="ISP" - servers="${LOCAL_DNS}" - echo "conf-dir=${TMP_DNSMASQ_PATH}" > "/var/dnsmasq.d/dnsmasq-${CONFIG}.conf" - #兼容旧版dnsmasq - echo "conf-dir=${TMP_DNSMASQ_PATH}" > "${DNSMASQ_PATH}/dnsmasq-${CONFIG}.conf" - - [ "${USE_CHNLIST}" = "1" ] && [ -z "${returnhome}" ] && [ -n "${chnlist}" ] && servers="${TUN_DNS}" - [ -n "${chnlist}" ] && msg="中国列表以外" - [ -n "${returnhome}" ] && msg="中国列表" - [ -n "${global}" ] && msg="全局" - if [ "$CHINADNS_NG" = "1" ]; then - #直接交给Chinadns-ng处理 - servers="${TUN_DNS}" && msg="chinadns-ng" - else - [ "${IS_DEFAULT_DNS}" = "1" ] && [ "${USE_CHNLIST}" = "0" ] && { - echolog " - 不强制设置默认DNS(上级分配)!" - return - } - fi - 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}" - else - echolog " - 从系统 dnsmasq 自行手动处理..." - [ -z "$DEFAULT_DNS" ] && { - local tmp=$(get_host_ip ipv4 www.baidu.com 1) - [ -z "$tmp" ] && { - cat <<-EOF > /var/dnsmasq.d/dnsmasq-$CONFIG.conf - server=$(get_first_dns LOCAL_DNS 53) - no-poll - no-resolv - EOF - echolog " - [$?]发现暂时无法解析度娘域名,临时接管并设置默认上游DNS:$(get_first_dns LOCAL_DNS 53)" - return 99 - } - } - 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; - } - 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 -} - -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 /usr/bin - maxconn 60000 - stats socket ${haproxy_path}/haproxy.sock - user root - 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 - unset msg - failcount=0 - while [ "$failcount" -lt "3" ]; do - ubus list network.interface.${export} >/dev/null 2>&1 - if [ $? -ne 0 ]; then - let "failcount++" - echolog " - 找不到出口接口:$export,1分钟后再重试(${failcount}/3),${bip}" - [ "$failcount" -ge 3 ] && exit 0 - sleep 1m - else - route add -host ${bip} dev ${export} - msg="[$?] 从 ${export} 接口路由," - echo "$bip" >>/tmp/balancing_ip - break - fi - done - fi - echolog " | - ${msg}出口节点:${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 -f "${haproxy_file}" - echolog " * 控制台端口:${console_port}/,${auth:-公开}" -} - -kill_all() { - kill -9 $(pidof "$@") >/dev/null 2>&1 & -} - -force_stop() { - stop - exit 0 -} - -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() { - load_config - start_socks - start_haproxy - [ "$NO_PROXY" == 1 ] || { - start_redir TCP tcp - start_redir UDP udp - start_dns - add_dnsmasq - source $APP_PATH/iptables.sh start - /etc/init.d/dnsmasq restart >/dev/null 2>&1 - echolog "重启 dnsmasq 服务[$?]" - } - start_crontab - echolog "运行完成!\n" -} - -stop() { - clean_log - source $APP_PATH/iptables.sh stop - kill_all v2ray-plugin obfs-local - ps -w | grep -v "grep" | grep $CONFIG/test.sh | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 & - ps -w | grep -v "grep" | grep $CONFIG/monitor.sh | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 & - ps -w | grep -v -E "grep|${TMP_PATH}_server" | grep -E "$TMP_PATH" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 & - ps -w | grep -v "grep" | grep "sleep 1m" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 & - rm -rf $TMP_DNSMASQ_PATH $TMP_PATH - stop_crontab - del_dnsmasq - /etc/init.d/dnsmasq restart >/dev/null 2>&1 - echolog "重启 dnsmasq 服务[$?]" - echolog "清空并关闭相关程序和缓存完成。" -} - -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/lienol/luci-app-passwall/root/usr/share/passwall/iptables.sh b/lienol/luci-app-passwall/root/usr/share/passwall/iptables.sh deleted file mode 100755 index 3ec658c..0000000 --- a/lienol/luci-app-passwall/root/usr/share/passwall/iptables.sh +++ /dev/null @@ -1,741 +0,0 @@ -#!/bin/sh - -IPSET_LANIPLIST="laniplist" -IPSET_VPSIPLIST="vpsiplist" -IPSET_SHUNTLIST="shuntlist" -IPSET_GFW="gfwlist" -#IPSET_GFW6="gfwlist6" -IPSET_CHN="chnroute" -IPSET_CHN6="chnroute6" -IPSET_BLACKLIST="blacklist" -IPSET_BLACKLIST2="blacklist2" -IPSET_BLACKLIST3="blacklist3" -IPSET_WHITELIST="whitelist" - -FORCE_INDEX=2 - -ipt_n="iptables -t nat" -ipt_m="iptables -t mangle" -ip6t_n="ip6tables -t nat" -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() { - echo "-m comment --comment '$1'" -} - -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" | sed -n '$p' | 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_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 -} - -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_node=${tcp_node:-1} - udp_node=${udp_node:-1} - 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_node" -gt "$TCP_NODE_NUM" ] && tcp_node=1 - [ "$udp_node" -gt "$UDP_NODE_NUM" ] && udp_node=1 - [ "$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 - eval TCP_NODE=\$TCP_NODE$tcp_node - eval UDP_NODE=\$UDP_NODE$udp_node - - #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" ] && { - eval tcp_port=\$TCP_REDIR_PORT$tcp_node - 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节点${tcp_node} [$(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 - 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") $(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) - } - echolog " - ${msg2}" - } - $ipt_tmp -A PSW $(comment "$remarks") $(factor $ip "-s") $(factor $mac "-m mac --mac-source") -p tcp -j RETURN - - [ "$udp_proxy_mode" != "disable" ] && { - msg2="${msg}使用UDP节点${udp_node} [$(get_action_chain_name $udp_proxy_mode)]" - [ "$UDP_NODE" != "nil" ] && { - eval udp_port=\$UDP_REDIR_PORT$udp_node - 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 - 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") $(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) - } - echolog " - ${msg2}" - } - $ipt_m -A PSW $(comment "$remarks") $(factor $ip "-s") $(factor $mac "-m mac --mac-source") -p udp -j RETURN - done - } - - # 加载TCP默认代理模式 - local ipt_tmp=$ipt_n - local is_tproxy msg - unset 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 - ipt_tmp=$ipt_n - unset is_tproxy msg - [ "3" -le "$TCP_NODE_NUM" ] && [ "$TCP_NODE3" != "nil" ] && { - local TCP_NODE3_TYPE=$(echo $(config_n_get $TCP_NODE3 type) | tr 'A-Z' 'a-z') - [ "$TCP_NODE3_TYPE" == "brook" ] && [ "$(config_n_get $TCP_NODE3 protocol client)" == "client" ] && is_tproxy=1 - #[ "$TCP_NODE3_TYPE" == "trojan-go" ] && is_tproxy=1 - msg="TCP代理列表3:使用TCP节点3" - if [ -n "$is_tproxy" ]; then - ipt_tmp=$ipt_m && is_tproxy="TPROXY" - msg="${msg}(TPROXY:${TCP_REDIR_PORT3})代理" - else - msg="${msg}(REDIRECT:${TCP_REDIR_PORT3})代理" - fi - [ "$TCP_NO_REDIR_PORTS" != "disable" ] && msg="${msg}除${TCP_NO_REDIR_PORTS}外的" - msg="${msg}所有端口" - $ipt_tmp -A PSW $(comment "列表3") -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport") $(dst $IPSET_BLACKLIST3) $(REDIRECT $TCP_REDIR_PORT3 $is_tproxy) - echolog "${msg}" - } - ipt_tmp=$ipt_n - unset is_tproxy msg - [ "2" -le "$TCP_NODE_NUM" ] && [ "$TCP_NODE2" != "nil" ] && { - local TCP_NODE2_TYPE=$(echo $(config_n_get $TCP_NODE2 type) | tr 'A-Z' 'a-z') - [ "$TCP_NODE2_TYPE" == "brook" ] && [ "$(config_n_get $TCP_NODE2 protocol client)" == "client" ] && is_tproxy=1 - #[ "$TCP_NODE2_TYPE" == "trojan-go" ] && is_tproxy=1 - msg="TCP代理列表2:使用TCP节点2" - if [ -n "$is_tproxy" ]; then - ipt_tmp=$ipt_m && is_tproxy="TPROXY" - msg="${msg}(TPROXY:${TCP_REDIR_PORT2})代理" - else - msg="${msg}(REDIRECT:${TCP_REDIR_PORT2})代理" - fi - [ "$TCP_NO_REDIR_PORTS" != "disable" ] && msg="${msg}除${TCP_NO_REDIR_PORTS}外的" - msg="${msg}所有端口" - $ipt_tmp -A PSW $(comment "列表2") -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport") $(dst $IPSET_BLACKLIST2) $(REDIRECT $TCP_REDIR_PORT2 $is_tproxy) - echolog "${msg}" - } - ipt_tmp=$ipt_n - unset is_tproxy msg - [ "$TCP_NODE1" != "nil" ] && { - local TCP_NODE1_TYPE=$(echo $(config_n_get $TCP_NODE1 type) | tr 'A-Z' 'a-z') - [ "$TCP_NODE1_TYPE" == "brook" ] && [ "$(config_n_get $TCP_NODE1 protocol client)" == "client" ] && is_tproxy=1 - #[ "$TCP_NODE1_TYPE" == "trojan-go" ] && is_tproxy=1 - msg="TCP默认代理:使用TCP节点1 [$(get_action_chain_name $TCP_PROXY_MODE)]" - if [ -n "$is_tproxy" ]; then - ipt_tmp=$ipt_m && is_tproxy="TPROXY" - msg="${msg}(TPROXY:${TCP_REDIR_PORT1})代理" - else - msg="${msg}(REDIRECT:${TCP_REDIR_PORT1})代理" - fi - [ "$TCP_NO_REDIR_PORTS" != "disable" ] && msg="${msg}除${TCP_NO_REDIR_PORTS}外的" - msg="${msg}所有端口" - $ipt_tmp -A PSW $(comment "默认") -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport") $(dst $IPSET_SHUNTLIST) $(REDIRECT $TCP_REDIR_PORT1 $is_tproxy) - $ipt_tmp -A PSW $(comment "默认") -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport") $(dst $IPSET_BLACKLIST) $(REDIRECT $TCP_REDIR_PORT1 $is_tproxy) - $ipt_tmp -A PSW $(comment "默认") -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport") $(get_redirect_ipt $TCP_PROXY_MODE $TCP_REDIR_PORT1 $is_tproxy) - echolog "${msg}" - } - fi - $ipt_n -A PSW $(comment "默认") -p tcp -j RETURN - $ipt_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 - [ "3" -le "$UDP_NODE_NUM" ] && [ "$UDP_NODE3" != "nil" ] && { - msg="UDP代理列表3:使用UDP节点3 (TPROXY:${UDP_REDIR_PORT3})代理" - [ "$UDP_NO_REDIR_PORTS" != "disable" ] && msg="${msg}除${TCP_NO_REDIR_PORTS}外的" - msg="${msg}所有端口" - $ipt_m -A PSW $(comment "列表3") -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") $(dst $IPSET_BLACKLIST3) $(REDIRECT $UDP_REDIR_PORT3 TPROXY) - echolog "${msg}" - } - [ "2" -le "$UDP_NODE_NUM" ] && [ "$UDP_NODE2" != "nil" ] && { - msg="UDP代理列表2:使用UDP节点2 (TPROXY:${UDP_REDIR_PORT2})代理" - [ "$UDP_NO_REDIR_PORTS" != "disable" ] && msg="${msg}除${TCP_NO_REDIR_PORTS}外的" - msg="${msg}所有端口" - $ipt_m -A PSW $(comment "列表2") -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") $(dst $IPSET_BLACKLIST2) $(REDIRECT $UDP_REDIR_PORT2 TPROXY) - echolog "${msg}" - } - [ "$UDP_NODE1" != "nil" ] && { - msg="UDP默认代理:使用UDP节点1 [$(get_action_chain_name $UDP_PROXY_MODE)](TPROXY:${UDP_REDIR_PORT1})代理" - [ "$UDP_NO_REDIR_PORTS" != "disable" ] && msg="${msg}除${TCP_NO_REDIR_PORTS}外的" - msg="${msg}所有端口" - $ipt_m -A PSW $(comment "默认") -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") $(dst $IPSET_SHUNTLIST) $(REDIRECT $UDP_REDIR_PORT1 TPROXY) - $ipt_m -A PSW $(comment "默认") -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") $(dst $IPSET_BLACKLIST) $(REDIRECT $UDP_REDIR_PORT1 TPROXY) - $ipt_m -A PSW $(comment "默认") -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") $(get_redirect_ipt $UDP_PROXY_MODE $UDP_REDIR_PORT1 TPROXY) - echolog "${msg}" - } - fi - $ipt_m -A PSW $(comment "默认") -p udp -j RETURN -} - -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-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}])" | sed -e "/^$/d" | sed -e "s/^/add $IPSET_VPSIP6LIST &/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R - echolog "过滤所有节点直接 IP 地址完成[$?]" -} - -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_n - [ "$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 -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 nil) - filter_rules $default_node $stream -:</dev/null 2>&1 & - } - - local ISP_DNS=$(cat $RESOLVFILE 2>/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 - } - - # 过滤所有节点IP - filter_vpsip - - $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 -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_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 -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 - - ip rule add fwmark 1 lookup 100 - ip route add local 0.0.0.0/0 dev lo table 100 - - # 加载路由器自身代理 TCP - if [ "$TCP_NODE1" != "nil" ]; then - local ipt_tmp=$ipt_n - local dns_l="PSW_OUTPUT" - local dns_r=$(REDIRECT $TCP_REDIR_PORT1) - local blist_r=$(REDIRECT $TCP_REDIR_PORT1) - local p_r=$(get_redirect_ipt $LOCALHOST_TCP_PROXY_MODE $TCP_REDIR_PORT1) - TCP_NODE1_TYPE=$(echo $(config_n_get $TCP_NODE1 type) | tr 'A-Z' 'a-z') - echolog "加载路由器自身 TCP 代理..." - if [ "$TCP_NODE1_TYPE" == "brook" ] && [ "$(config_n_get $TCP_NODE1 protocol client)" == "client" ]; then - echolog " - 启用 TPROXY 模式" - ipt_tmp=$ipt_m - dns_l="PSW" - dns_r="$(REDIRECT $TCP_REDIR_PORT1 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 test $IPSET_LANIPLIST ${2} 2>/dev/null - [ $? -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 - echolog " - [$?]不代理TCP 端口:$TCP_NO_REDIR_PORTS" - } - $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 - fi - - local PR_INDEX=$(RULE_LAST_INDEX "$ipt_n" PREROUTING ADBYBY) - if [ "$PR_INDEX" == "0" ]; then - PR_INDEX=$(RULE_LAST_INDEX "$ipt_n" PREROUTING prerouting_rule) - else - echolog "发现 adbyby 规则链,adbyby 规则优先..." - fi - PR_INDEX=$((PR_INDEX + 1)) - $ipt_n -I PREROUTING $PR_INDEX -p tcp -j PSW - echolog "使用链表 PREROUTING 排列索引${PR_INDEX}[$?]" - - $ip6t_n -N PSW - $ip6t_n -A PREROUTING -j PSW - $ip6t_n -N PSW_OUTPUT - $ip6t_n -A OUTPUT -p tcp -j PSW_OUTPUT - - $ip6t_m -N PSW - $ip6t_m -A PREROUTING -j PSW - $ip6t_m -N PSW_OUTPUT - $ip6t_m -A OUTPUT -p tcp -j PSW_OUTPUT - [ -n "$lan_ifname" ] && { - lan_ipv6=$(ip address show $lan_ifname | grep -w "inet6" | awk '{print $2}') #当前LAN IPv6段 - [ -n "$lan_ipv6" ] && { - for ip in $lan_ipv6; do - $ip6t_n -A PSW -d $ip -j RETURN - $ip6t_n -A PSW_OUTPUT -d $ip -j RETURN - done - } - } - - if [ "$PROXY_IPV6" == "1" ]; then - local msg="IPv6 配置不当,无法代理" - $ip6t_n -A PSW -p tcp $(REDIRECT $TCP_REDIR_PORT1) - $ip6t_n -A PSW_OUTPUT -p tcp $(REDIRECT $TCP_REDIR_PORT1) - msg="${msg},转发 IPv6 TCP 流量到节点1[$?]" - echolog "$msg" - fi - - # 过滤Socks节点 - 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 - num=$(echo $node | sed "s/tcp//g") - eval "node=\${TCP_NODE$num}" - msg="${msg} 使用与 TCP 代理自动切换${num} 相同的节点,延后处理" - else - filter_node $node TCP - filter_node $node UDP - fi - echolog " - ${msg}" - done - - # 处理轮换节点的分流或套娃 - local node port stream switch - for stream in TCP UDP; do - for switch in $(eval "seq 1 \${${stream}_NODE_NUM}"); do - eval "node=\${${stream}_NODE$switch}" - eval "port=\${${stream}_REDIR_PORT$switch}" - echolog "分析 $stream 代理自动切换$switch..." - [ "$node" == "tcp" ] && [ "$stream" == "UDP" ] && { - eval "node=\${TCP_NODE$switch}" - eval "port=\${TCP_REDIR_PORT$switch}" - echolog " - 采用 TCP 代理的配置" - } - - if [ "$node" != "nil" ]; then - filter_node $node $stream $port - else - echolog " - 忽略无效的 $stream 代理自动切换$switch" - fi - done - done - - # 加载路由器自身代理 UDP - if [ "$UDP_NODE1" != "nil" ]; then - echolog "加载路由器自身 UDP 代理..." - local UDP_NODE1_TYPE=$(echo $(config_n_get $UDP_NODE1 type) | tr 'A-Z' 'a-z') - local ADD_INDEX=$FORCE_INDEX - _proxy_udp_access() { - [ -n "${2}" ] || return 0 - ipset test $IPSET_LANIPLIST ${2} 2>/dev/null - [ $? == 0 ] && { - echolog " - 上游 DNS 服务器 ${2} 已在直接访问的列表中,不强制向 UDP 代理转发对该服务器 UDP/${3} 端口的访问" - return 0 - } - $ipt_m -I PSW $ADD_INDEX -p udp -d ${2} --dport ${3} $(REDIRECT $UDP_REDIR_PORT1 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 - echolog " - [$?]不代理 UDP 端口:$UDP_NO_REDIR_PORTS" - } - $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) - fi - - $ipt_m -A PREROUTING -j PSW - - # 加载ACLS - load_acl - - # dns_hijack "force" - - echolog "防火墙规则加载完成!" -} - -del_firewall_rule() { - $ipt_n -D PREROUTING -p tcp -j PSW 2>/dev/null - $ipt_n -D OUTPUT -p tcp -j PSW_OUTPUT 2>/dev/null - $ipt_n -F PSW 2>/dev/null && $ipt_n -X PSW 2>/dev/null - $ipt_n -F PSW_OUTPUT 2>/dev/null && $ipt_n -X PSW_OUTPUT 2>/dev/null - - $ipt_m -D PREROUTING -j PSW 2>/dev/null - $ipt_m -D OUTPUT -p tcp -j PSW_OUTPUT 2>/dev/null - $ipt_m -D OUTPUT -p udp -j PSW_OUTPUT 2>/dev/null - $ipt_m -F PSW 2>/dev/null && $ipt_m -X PSW 2>/dev/null - $ipt_m -F PSW_OUTPUT 2>/dev/null && $ipt_m -X PSW_OUTPUT 2>/dev/null - - $ip6t_n -D PREROUTING -j PSW 2>/dev/null - $ip6t_n -D OUTPUT -p tcp -j PSW_OUTPUT 2>/dev/null - $ip6t_n -F PSW 2>/dev/null && $ip6t_n -X PSW 2>/dev/null - $ip6t_n -F PSW_OUTPUT 2>/dev/null && $ip6t_n -X PSW_OUTPUT 2>/dev/null - - $ip6t_m -D PREROUTING -j PSW 2>/dev/null - $ip6t_m -D OUTPUT -p tcp -j PSW_OUTPUT 2>/dev/null - $ip6t_m -F PSW 2>/dev/null && $ip6t_m -X PSW 2>/dev/null - $ip6t_m -F PSW_OUTPUT 2>/dev/null && $ip6t_m -X PSW_OUTPUT 2>/dev/null - - 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 - - ipset -F $IPSET_LANIPLIST >/dev/null 2>&1 && ipset -X $IPSET_LANIPLIST >/dev/null 2>&1 & - ipset -F $IPSET_VPSIPLIST >/dev/null 2>&1 && ipset -X $IPSET_VPSIPLIST >/dev/null 2>&1 & - #ipset -F $IPSET_SHUNTLIST >/dev/null 2>&1 && ipset -X $IPSET_SHUNTLIST >/dev/null 2>&1 & - #ipset -F $IPSET_GFW >/dev/null 2>&1 && ipset -X $IPSET_GFW >/dev/null 2>&1 & - #ipset -F $IPSET_GFW6 >/dev/null 2>&1 && ipset -X $IPSET_GFW6 >/dev/null 2>&1 & - #ipset -F $IPSET_CHN >/dev/null 2>&1 && ipset -X $IPSET_CHN >/dev/null 2>&1 & - #ipset -F $IPSET_CHN6 >/dev/null 2>&1 && ipset -X $IPSET_CHN6 >/dev/null 2>&1 & - #ipset -F $IPSET_BLACKLIST >/dev/null 2>&1 && ipset -X $IPSET_BLACKLIST >/dev/null 2>&1 & - #ipset -F $IPSET_BLACKLIST2 >/dev/null 2>&1 && ipset -X $IPSET_BLACKLIST2 >/dev/null 2>&1 & - #ipset -F $IPSET_BLACKLIST3 >/dev/null 2>&1 && ipset -X $IPSET_BLACKLIST3 >/dev/null 2>&1 & - ipset -F $IPSET_WHITELIST >/dev/null 2>&1 && ipset -X $IPSET_WHITELIST >/dev/null 2>&1 & - #echolog "删除相关防火墙规则完成。" -} - -flush_ipset() { - ipset -F $IPSET_LANIPLIST >/dev/null 2>&1 && ipset -X $IPSET_LANIPLIST >/dev/null 2>&1 & - ipset -F $IPSET_VPSIPLIST >/dev/null 2>&1 && ipset -X $IPSET_VPSIPLIST >/dev/null 2>&1 & - ipset -F $IPSET_SHUNTLIST >/dev/null 2>&1 && ipset -X $IPSET_SHUNTLIST >/dev/null 2>&1 & - ipset -F $IPSET_GFW >/dev/null 2>&1 && ipset -X $IPSET_GFW >/dev/null 2>&1 & - #ipset -F $IPSET_GFW6 >/dev/null 2>&1 && ipset -X $IPSET_GFW6 >/dev/null 2>&1 & - ipset -F $IPSET_CHN >/dev/null 2>&1 && ipset -X $IPSET_CHN >/dev/null 2>&1 & - ipset -F $IPSET_CHN6 >/dev/null 2>&1 && ipset -X $IPSET_CHN6 >/dev/null 2>&1 & - ipset -F $IPSET_BLACKLIST >/dev/null 2>&1 && ipset -X $IPSET_BLACKLIST >/dev/null 2>&1 & - ipset -F $IPSET_BLACKLIST2 >/dev/null 2>&1 && ipset -X $IPSET_BLACKLIST2 >/dev/null 2>&1 & - ipset -F $IPSET_BLACKLIST3 >/dev/null 2>&1 && ipset -X $IPSET_BLACKLIST3 >/dev/null 2>&1 & - ipset -F $IPSET_WHITELIST >/dev/null 2>&1 && ipset -X $IPSET_WHITELIST >/dev/null 2>&1 & -} - -flush_include() { - echo '#!/bin/sh' >$FWI -} - -gen_include() { - flush_include - extract_rules() { - local _ipt="iptables" - [ "$1" == "6" ] && _ipt="ip6tables" - - echo "*$2" - ${_ipt}-save -t $2 | grep PSW | \ - sed -e "s/^-A \(OUTPUT\|PREROUTING\)/-I \1 1/" - echo 'COMMIT' - } - cat <<-EOF >>$FWI - iptables-save -c | grep -v "PSW" | iptables-restore -c - iptables-restore -n <<-EOT - $(extract_rules 4 nat) - $(extract_rules 4 mangle) - EOT - ip6tables-save -c | grep -v "PSW" | ip6tables-restore -c - ip6tables-restore -n <<-EOT - $(extract_rules 6 nat) - $(extract_rules 6 mangle) - EOT - 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/lienol/luci-app-passwall/root/usr/share/passwall/monitor.sh b/lienol/luci-app-passwall/root/usr/share/passwall/monitor.sh deleted file mode 100755 index 877beed..0000000 --- a/lienol/luci-app-passwall/root/usr/share/passwall/monitor.sh +++ /dev/null @@ -1,96 +0,0 @@ -#!/bin/sh - -CONFIG=passwall -RUN_BIN_PATH=/var/etc/${CONFIG}/bin - -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 [ "$(ps -w | grep -v grep | grep $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 1m -while [ "$ENABLED" -eq 1 ] -do - TCP_NODE_NUM=$(config_t_get global_other tcp_node_num 1) - for i in $(seq 1 $TCP_NODE_NUM); do - eval TCP_NODE$i=$(config_t_get global tcp_node$i nil) - done - - UDP_NODE_NUM=$(config_t_get global_other udp_node_num 1) - for i in $(seq 1 $UDP_NODE_NUM); do - eval UDP_NODE$i=$(config_t_get global udp_node$i nil) - done - - dns_mode=$(config_t_get global dns_mode) - use_haproxy=$(config_t_get global_haproxy balancing_enable 0) - - #tcp - for i in $(seq 1 $TCP_NODE_NUM); do - eval tmp_node=\$TCP_NODE$i - if [ "$tmp_node" != "nil" ]; then - #kcptun - use_kcp=$(config_n_get $tmp_node use_kcp 0) - if [ $use_kcp -gt 0 ]; then - icount=$(ps -w | grep -v grep | grep "$RUN_BIN_PATH/kcptun" | grep -i "tcp_${i}" | wc -l) - if [ $icount = 0 ]; then - /etc/init.d/passwall restart - exit 0 - fi - fi - icount=$(ps -w | grep -v -E 'grep|kcptun' | grep "$RUN_BIN_PATH" | grep -i "TCP_${i}" | wc -l) - if [ $icount = 0 ]; then - /etc/init.d/passwall restart - exit 0 - fi - fi - done - - #udp - for i in $(seq 1 $UDP_NODE_NUM); do - eval tmp_node=\$UDP_NODE$i - if [ "$tmp_node" != "nil" ]; then - [ "$tmp_node" == "tcp" ] && continue - [ "$tmp_node" == "tcp_" ] && tmp_node=$TCP_NODE1 - icount=$(ps -w | grep -v grep | grep "$RUN_BIN_PATH" | grep -i "UDP_${i}" | wc -l) - if [ $icount = 0 ]; then - /etc/init.d/passwall restart - exit 0 - fi - fi - done - - #dns - if [ "$dns_mode" != "nonuse" ] && [ "$dns_mode" != "custom" ]; then - icount=$(netstat -apn | grep 7913 | wc -l) - if [ $icount = 0 ]; then - /etc/init.d/passwall restart - exit 0 - fi - fi - - #haproxy - if [ $use_haproxy -gt 0 ]; then - icount=$(ps -w | grep -v grep | grep "$RUN_BIN_PATH/haproxy" | wc -l) - if [ $icount = 0 ]; then - /etc/init.d/passwall restart - exit 0 - fi - fi - - sleep 1m -done diff --git a/lienol/luci-app-passwall/root/usr/share/passwall/rule_update.lua b/lienol/luci-app-passwall/root/usr/share/passwall/rule_update.lua deleted file mode 100644 index 9e92dd2..0000000 --- a/lienol/luci-app-passwall/root/usr/share/passwall/rule_update.lua +++ /dev/null @@ -1,342 +0,0 @@ -#!/usr/bin/lua - -require 'luci.sys' -local luci = luci -local ucic = luci.model.uci.cursor() -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 - --- match comments/title/whitelist/ip address/excluded_domain -local comment_pattern = "^[!\\[@]+" -local ip_pattern = "^%d+%.%d+%.%d+%.%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"} - --- gfwlist parameter -local mydnsip = '127.0.0.1' -local mydnsport = '7913' -local ipsetname = 'gfwlist' - --- custom url -local enable_custom_url = 1 -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_1 = 'https://cdn.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/accelerated-domains.china.conf' -local chnlist_url_2 = 'https://cdn.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/apple.china.conf' -local chnlist_url_3 = 'https://cdn.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/google.china.conf' - -local bc='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' - --- base64decoding -local function base64_dec(data) - 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 - -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 - --- trim -local function trim(text) - if not text or text == "" then return "" end - return (string.gsub(text, "^%s*(.-)%s*$", "%1")) -end - --- wget -local function wget(url, file) - local cmd = "/usr/bin/wget --no-check-certificate -t 3 -T 10 -O" - if file then - cmd = cmd .. " " .. file .. " " .. url - else - cmd = cmd .. "- " .. url - end - local stdout = luci.sys.exec(cmd) - return trim(stdout) -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 - ---获取gfwlist -local function fetch_gfwlist() - --请求gfwlist - local sret = curl(gfwlist_url, "/tmp/gfwlist.txt") - if sret == 200 then - --解码gfwlist - local gfwlist = io.open("/tmp/gfwlist.txt", "r") - local decode = base64_dec(gfwlist:read("*all")) - gfwlist:close() - --写回gfwlist - gfwlist = io.open("/tmp/gfwlist.txt", "w") - gfwlist:write(decode) - gfwlist:close() - end - - return sret; -end - ---获取chnroute -local function fetch_chnroute() - --请求chnroute - local sret = curl(chnroute_url, "/tmp/chnroute_tmp") - return sret; -end - ---获取chnroute6 -local function fetch_chnroute6() - --请求chnroute6 - local sret = curl(chnroute6_url, "/tmp/chnroute6_tmp") - return sret; -end - ---获取chnlist -local function fetch_chnlist() - --请求chnlist - local sret = 0 - local sret1 = curl(chnlist_url_1, "/tmp/chnlist_1") - local sret2 = curl(chnlist_url_2, "/tmp/chnlist_2") - local sret3 = curl(chnlist_url_3, "/tmp/chnlist_3") - - if sret1 == 200 and sret2 ==200 and sret3 == 200 then - sret=200 - end - return sret; -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 - ---gfwlist转码至dnsmasq格式 -local function generate_gfwlist() - local domains = {} - local out = io.open("/tmp/gfwlist_tmp", "w") - - for line in io.lines("/tmp/gfwlist.txt") 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 - - for k,v in pairs(domains) do - out:write(string.format("server=/.%s/%s#%s\n", k,mydnsip,mydnsport)) - out:write(string.format("ipset=/.%s/%s\n", k,ipsetname)) - end - - out:close() -end - ---处理合并chnlist列表 -local function generate_chnlist() - local domains = {} - local out = io.open("/tmp/cdn_tmp", "w") - - for line in io.lines("/tmp/chnlist_1") do - local start, finish, match = string.find(line, domain_pattern) - if (start) then - domains[match] = true - end - end - - for line in io.lines("/tmp/chnlist_2") do - local start, finish, match = string.find(line, domain_pattern) - if (start) then - domains[match] = true - end - end - - for line in io.lines("/tmp/chnlist_3") do - local start, finish, match = string.find(line, domain_pattern) - if (start) then - domains[match] = true - end - end - - --写入临时文件 - 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") -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 -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) -end -if gfwlist_update == 0 and chnroute_update == 0 and chnroute6_update == 0 and chnlist_update == 0 then - os.exit(0) -end - -log("开始更新规则...") -if tonumber(enable_custom_url) == 1 then - local new_version = os.date("%Y-%m-%d") - log("已启用自定义规则地址...") - if tonumber(gfwlist_update) == 1 then - log("开始更新gfwlist...") - local old_md5 = luci.sys.exec("echo -n $(md5sum " .. rule_path .. "/gfwlist.conf | awk '{print $1}')") - local status = fetch_gfwlist() - if status == 200 then - generate_gfwlist() - 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.conf") - ucic:set(name, ucic:get_first(name, 'global_rules'), "gfwlist_version", new_version) - reboot = 1 - log("更新gfwlist成功...") - else - log("gfwlist版本一致,不用更新。") - end - else - log("gfwlist文件下载失败!") - end - os.remove("/tmp/gfwlist.txt") - 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") - ucic:set(name, ucic:get_first(name, 'global_rules'), "chnroute_version", new_version) - 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") - ucic:set(name, ucic:get_first(name, 'global_rules'), "chnroute6_version", new_version) - 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 - generate_chnlist() - 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") - ucic:set(name, ucic:get_first(name, 'global_rules'), "chnlist_version", new_version) - reboot = 1 - log("更新chnlist成功...") - else - log("chnlist版本一致,不用更新。") - end - else - log("chnlist文件下载失败!") - end - os.remove("/tmp/chnlist_1") - os.remove("/tmp/chnlist_2") - os.remove("/tmp/chnlist_3") - os.remove("/tmp/cdn_tmp") - os.remove("/tmp/chnlist_tmp") - end -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:save(name) -luci.sys.call("uci commit " .. name) - -if reboot == 1 then - log("重启服务,应用新的规则。") - luci.sys.call("/usr/share/" .. name .. "/iptables.sh flush_ipset && /etc/init.d/" .. name .. " restart") -end -log("规则脚本执行完毕...") \ No newline at end of file diff --git a/lienol/luci-app-passwall/root/usr/share/passwall/rules/adblock.conf b/lienol/luci-app-passwall/root/usr/share/passwall/rules/adblock.conf deleted file mode 100644 index 524806b..0000000 --- a/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/lienol/luci-app-passwall/root/usr/share/passwall/rules/direct_host b/lienol/luci-app-passwall/root/usr/share/passwall/rules/direct_host deleted file mode 100644 index 2e6d801..0000000 --- a/lienol/luci-app-passwall/root/usr/share/passwall/rules/direct_host +++ /dev/null @@ -1,6 +0,0 @@ -apple.com -microsoft.com -dyndns.com -rrys.tv -douyucdn.cn -douyucdn2.cn \ No newline at end of file diff --git a/lienol/luci-app-passwall/root/usr/share/passwall/rules/gfwlist.conf b/lienol/luci-app-passwall/root/usr/share/passwall/rules/gfwlist.conf deleted file mode 100644 index 49eceb9..0000000 --- a/lienol/luci-app-passwall/root/usr/share/passwall/rules/gfwlist.conf +++ /dev/null @@ -1,10786 +0,0 @@ -server=/.gmhz.org/127.0.0.1#7913 -ipset=/.gmhz.org/gfwlist -server=/.ameba.jp/127.0.0.1#7913 -ipset=/.ameba.jp/gfwlist -server=/.proxydns.com/127.0.0.1#7913 -ipset=/.proxydns.com/gfwlist -server=/.twitter.com/127.0.0.1#7913 -ipset=/.twitter.com/gfwlist -server=/.aliengu.com/127.0.0.1#7913 -ipset=/.aliengu.com/gfwlist -server=/.timesofindia.indiatimes.com/127.0.0.1#7913 -ipset=/.timesofindia.indiatimes.com/gfwlist -server=/.internetdefenseleague.org/127.0.0.1#7913 -ipset=/.internetdefenseleague.org/gfwlist -server=/.tuidang.net/127.0.0.1#7913 -ipset=/.tuidang.net/gfwlist -server=/.taiwandaily.net/127.0.0.1#7913 -ipset=/.taiwandaily.net/gfwlist -server=/.sixth.biz/127.0.0.1#7913 -ipset=/.sixth.biz/gfwlist -server=/.savetibet.de/127.0.0.1#7913 -ipset=/.savetibet.de/gfwlist -server=/.friendsoftibet.org/127.0.0.1#7913 -ipset=/.friendsoftibet.org/gfwlist -server=/.cosmic.monar.ch/127.0.0.1#7913 -ipset=/.cosmic.monar.ch/gfwlist -server=/.churchinhongkong.org/127.0.0.1#7913 -ipset=/.churchinhongkong.org/gfwlist -server=/.londonchinese.ca/127.0.0.1#7913 -ipset=/.londonchinese.ca/gfwlist -server=/.sapikachu.net/127.0.0.1#7913 -ipset=/.sapikachu.net/gfwlist -server=/.de-sci.org/127.0.0.1#7913 -ipset=/.de-sci.org/gfwlist -server=/.discordapp.net/127.0.0.1#7913 -ipset=/.discordapp.net/gfwlist -server=/.seezone.net/127.0.0.1#7913 -ipset=/.seezone.net/gfwlist -server=/.igotmail.com.tw/127.0.0.1#7913 -ipset=/.igotmail.com.tw/gfwlist -server=/.vital247.org/127.0.0.1#7913 -ipset=/.vital247.org/gfwlist -server=/.gist.github.com/127.0.0.1#7913 -ipset=/.gist.github.com/gfwlist -server=/.airconsole.com/127.0.0.1#7913 -ipset=/.airconsole.com/gfwlist -server=/.twittbot.net/127.0.0.1#7913 -ipset=/.twittbot.net/gfwlist -server=/.alternativeto.net/127.0.0.1#7913 -ipset=/.alternativeto.net/gfwlist -server=/.pornrapidshare.com/127.0.0.1#7913 -ipset=/.pornrapidshare.com/gfwlist -server=/.xxlmovies.com/127.0.0.1#7913 -ipset=/.xxlmovies.com/gfwlist -server=/.dysfz.cc/127.0.0.1#7913 -ipset=/.dysfz.cc/gfwlist -server=/.qixianglu.cn/127.0.0.1#7913 -ipset=/.qixianglu.cn/gfwlist -server=/.tibet.sk/127.0.0.1#7913 -ipset=/.tibet.sk/gfwlist -server=/.microvpn.com/127.0.0.1#7913 -ipset=/.microvpn.com/gfwlist -server=/.torrentz.eu/127.0.0.1#7913 -ipset=/.torrentz.eu/gfwlist -server=/.guardster.com/127.0.0.1#7913 -ipset=/.guardster.com/gfwlist -server=/.uderzo.it/127.0.0.1#7913 -ipset=/.uderzo.it/gfwlist -server=/.pubu.com.tw/127.0.0.1#7913 -ipset=/.pubu.com.tw/gfwlist -server=/.alhayat.com/127.0.0.1#7913 -ipset=/.alhayat.com/gfwlist -server=/.livestream.com/127.0.0.1#7913 -ipset=/.livestream.com/gfwlist -server=/.dmhy.org/127.0.0.1#7913 -ipset=/.dmhy.org/gfwlist -server=/.purplelotus.org/127.0.0.1#7913 -ipset=/.purplelotus.org/gfwlist -server=/.tokyo-porn-tube.com/127.0.0.1#7913 -ipset=/.tokyo-porn-tube.com/gfwlist -server=/.gmbd.cn/127.0.0.1#7913 -ipset=/.gmbd.cn/gfwlist -server=/.trtc.com.tw/127.0.0.1#7913 -ipset=/.trtc.com.tw/gfwlist -server=/.phayul.com/127.0.0.1#7913 -ipset=/.phayul.com/gfwlist -server=/.tparents.org/127.0.0.1#7913 -ipset=/.tparents.org/gfwlist -server=/.livedoor.jp/127.0.0.1#7913 -ipset=/.livedoor.jp/gfwlist -server=/.sokamonline.com/127.0.0.1#7913 -ipset=/.sokamonline.com/gfwlist -server=/.homeservershow.com/127.0.0.1#7913 -ipset=/.homeservershow.com/gfwlist -server=/.gamebase.com.tw/127.0.0.1#7913 -ipset=/.gamebase.com.tw/gfwlist -server=/.soup.io/127.0.0.1#7913 -ipset=/.soup.io/gfwlist -server=/.youporngay.com/127.0.0.1#7913 -ipset=/.youporngay.com/gfwlist -server=/.gaycn.net/127.0.0.1#7913 -ipset=/.gaycn.net/gfwlist -server=/.falunpilipinas.net/127.0.0.1#7913 -ipset=/.falunpilipinas.net/gfwlist -server=/.weiquanwang.org/127.0.0.1#7913 -ipset=/.weiquanwang.org/gfwlist -server=/.iportal.me/127.0.0.1#7913 -ipset=/.iportal.me/gfwlist -server=/.americangreencard.com/127.0.0.1#7913 -ipset=/.americangreencard.com/gfwlist -server=/.christianstudy.com/127.0.0.1#7913 -ipset=/.christianstudy.com/gfwlist -server=/.xpdo.net/127.0.0.1#7913 -ipset=/.xpdo.net/gfwlist -server=/.shiksha.ws/127.0.0.1#7913 -ipset=/.shiksha.ws/gfwlist -server=/.truebuddha-md.org/127.0.0.1#7913 -ipset=/.truebuddha-md.org/gfwlist -server=/.vanpeople.com/127.0.0.1#7913 -ipset=/.vanpeople.com/gfwlist -server=/.wsgzao.github.io/127.0.0.1#7913 -ipset=/.wsgzao.github.io/gfwlist -server=/.amnesty.org/127.0.0.1#7913 -ipset=/.amnesty.org/gfwlist -server=/.domains.google/127.0.0.1#7913 -ipset=/.domains.google/gfwlist -server=/.d3c33hcgiwev3.cloudfront.net/127.0.0.1#7913 -ipset=/.d3c33hcgiwev3.cloudfront.net/gfwlist -server=/.hechaji.com/127.0.0.1#7913 -ipset=/.hechaji.com/gfwlist -server=/.ippotv.com/127.0.0.1#7913 -ipset=/.ippotv.com/gfwlist -server=/.wheelockslatin.com/127.0.0.1#7913 -ipset=/.wheelockslatin.com/gfwlist -server=/.dotplane.com/127.0.0.1#7913 -ipset=/.dotplane.com/gfwlist -server=/.21join.com/127.0.0.1#7913 -ipset=/.21join.com/gfwlist -server=/.tl.gd/127.0.0.1#7913 -ipset=/.tl.gd/gfwlist -server=/.video.foxbusiness.com/127.0.0.1#7913 -ipset=/.video.foxbusiness.com/gfwlist -server=/.gtricks.com/127.0.0.1#7913 -ipset=/.gtricks.com/gfwlist -server=/.documentingreality.com/127.0.0.1#7913 -ipset=/.documentingreality.com/gfwlist -server=/.cardinalkungfoundation.org/127.0.0.1#7913 -ipset=/.cardinalkungfoundation.org/gfwlist -server=/.iyouport.org/127.0.0.1#7913 -ipset=/.iyouport.org/gfwlist -server=/.gaeproxy.com/127.0.0.1#7913 -ipset=/.gaeproxy.com/gfwlist -server=/.ronjoneswriter.com/127.0.0.1#7913 -ipset=/.ronjoneswriter.com/gfwlist -server=/.ur7s.com/127.0.0.1#7913 -ipset=/.ur7s.com/gfwlist -server=/.motherless.com/127.0.0.1#7913 -ipset=/.motherless.com/gfwlist -server=/.yibada.com/127.0.0.1#7913 -ipset=/.yibada.com/gfwlist -server=/.epochtimes.fr/127.0.0.1#7913 -ipset=/.epochtimes.fr/gfwlist -server=/.radiovncr.com/127.0.0.1#7913 -ipset=/.radiovncr.com/gfwlist -server=/.lyfhk.net/127.0.0.1#7913 -ipset=/.lyfhk.net/gfwlist -server=/.mizzmona.com/127.0.0.1#7913 -ipset=/.mizzmona.com/gfwlist -server=/.zaobao.com/127.0.0.1#7913 -ipset=/.zaobao.com/gfwlist -server=/.thebodyshop-usa.com/127.0.0.1#7913 -ipset=/.thebodyshop-usa.com/gfwlist -server=/.guangnianvpn.com/127.0.0.1#7913 -ipset=/.guangnianvpn.com/gfwlist -server=/.ai.google/127.0.0.1#7913 -ipset=/.ai.google/gfwlist -server=/.tw-npo.org/127.0.0.1#7913 -ipset=/.tw-npo.org/gfwlist -server=/.bravotube.net/127.0.0.1#7913 -ipset=/.bravotube.net/gfwlist -server=/.telesco.pe/127.0.0.1#7913 -ipset=/.telesco.pe/gfwlist -server=/.meetav.com/127.0.0.1#7913 -ipset=/.meetav.com/gfwlist -server=/.cytode.us/127.0.0.1#7913 -ipset=/.cytode.us/gfwlist -server=/.new96.ca/127.0.0.1#7913 -ipset=/.new96.ca/gfwlist -server=/.legsjapan.com/127.0.0.1#7913 -ipset=/.legsjapan.com/gfwlist -server=/.nordstrom.com/127.0.0.1#7913 -ipset=/.nordstrom.com/gfwlist -server=/.hanime.tv/127.0.0.1#7913 -ipset=/.hanime.tv/gfwlist -server=/.dailidaili.com/127.0.0.1#7913 -ipset=/.dailidaili.com/gfwlist -server=/.laoyang.info/127.0.0.1#7913 -ipset=/.laoyang.info/gfwlist -server=/.coinbene.com/127.0.0.1#7913 -ipset=/.coinbene.com/gfwlist -server=/.chinasoul.org/127.0.0.1#7913 -ipset=/.chinasoul.org/gfwlist -server=/.freedomcollection.org/127.0.0.1#7913 -ipset=/.freedomcollection.org/gfwlist -server=/.nylon-angel.com/127.0.0.1#7913 -ipset=/.nylon-angel.com/gfwlist -server=/.cleansite.info/127.0.0.1#7913 -ipset=/.cleansite.info/gfwlist -server=/.google.ie/127.0.0.1#7913 -ipset=/.google.ie/gfwlist -server=/.rigpa.org/127.0.0.1#7913 -ipset=/.rigpa.org/gfwlist -server=/.presidentlee.tw/127.0.0.1#7913 -ipset=/.presidentlee.tw/gfwlist -server=/.177pic.info/127.0.0.1#7913 -ipset=/.177pic.info/gfwlist -server=/.video.pbs.org/127.0.0.1#7913 -ipset=/.video.pbs.org/gfwlist -server=/.cbsnews.com/127.0.0.1#7913 -ipset=/.cbsnews.com/gfwlist -server=/.hotpornshow.com/127.0.0.1#7913 -ipset=/.hotpornshow.com/gfwlist -server=/.redchinacn.net/127.0.0.1#7913 -ipset=/.redchinacn.net/gfwlist -server=/.yong.hu/127.0.0.1#7913 -ipset=/.yong.hu/gfwlist -server=/.j.mp/127.0.0.1#7913 -ipset=/.j.mp/gfwlist -server=/.apk.tw/127.0.0.1#7913 -ipset=/.apk.tw/gfwlist -server=/.huaglad.com/127.0.0.1#7913 -ipset=/.huaglad.com/gfwlist -server=/.internet.org/127.0.0.1#7913 -ipset=/.internet.org/gfwlist -server=/.wowporn.com/127.0.0.1#7913 -ipset=/.wowporn.com/gfwlist -server=/.china-mmm.net/127.0.0.1#7913 -ipset=/.china-mmm.net/gfwlist -server=/.hilive.tv/127.0.0.1#7913 -ipset=/.hilive.tv/gfwlist -server=/.forum.setty.com.tw/127.0.0.1#7913 -ipset=/.forum.setty.com.tw/gfwlist -server=/.g0v.social/127.0.0.1#7913 -ipset=/.g0v.social/gfwlist -server=/.xys.dxiong.com/127.0.0.1#7913 -ipset=/.xys.dxiong.com/gfwlist -server=/.greenvpn.net/127.0.0.1#7913 -ipset=/.greenvpn.net/gfwlist -server=/.jgoodies.com/127.0.0.1#7913 -ipset=/.jgoodies.com/gfwlist -server=/.kanzhongguo.com/127.0.0.1#7913 -ipset=/.kanzhongguo.com/gfwlist -server=/.lotuslight.org.tw/127.0.0.1#7913 -ipset=/.lotuslight.org.tw/gfwlist -server=/.991.com/127.0.0.1#7913 -ipset=/.991.com/gfwlist -server=/.jihadintel.meforum.org/127.0.0.1#7913 -ipset=/.jihadintel.meforum.org/gfwlist -server=/.bit.do/127.0.0.1#7913 -ipset=/.bit.do/gfwlist -server=/.china18.org/127.0.0.1#7913 -ipset=/.china18.org/gfwlist -server=/.discoins.com/127.0.0.1#7913 -ipset=/.discoins.com/gfwlist -server=/.experts-univers.com/127.0.0.1#7913 -ipset=/.experts-univers.com/gfwlist -server=/.lflinkup.net/127.0.0.1#7913 -ipset=/.lflinkup.net/gfwlist -server=/.cool18.com/127.0.0.1#7913 -ipset=/.cool18.com/gfwlist -server=/.im88.tw/127.0.0.1#7913 -ipset=/.im88.tw/gfwlist -server=/.blog.foolsmountain.com/127.0.0.1#7913 -ipset=/.blog.foolsmountain.com/gfwlist -server=/.chinahorizon.org/127.0.0.1#7913 -ipset=/.chinahorizon.org/gfwlist -server=/.logiqx.com/127.0.0.1#7913 -ipset=/.logiqx.com/gfwlist -server=/.illusionfactory.com/127.0.0.1#7913 -ipset=/.illusionfactory.com/gfwlist -server=/.voatibetanenglish.com/127.0.0.1#7913 -ipset=/.voatibetanenglish.com/gfwlist -server=/.therock.net.nz/127.0.0.1#7913 -ipset=/.therock.net.nz/gfwlist -server=/.wiki.esu.im/127.0.0.1#7913 -ipset=/.wiki.esu.im/gfwlist -server=/.twindexx.com/127.0.0.1#7913 -ipset=/.twindexx.com/gfwlist -server=/.md-t.org/127.0.0.1#7913 -ipset=/.md-t.org/gfwlist -server=/.onlineyoutube.com/127.0.0.1#7913 -ipset=/.onlineyoutube.com/gfwlist -server=/.spankbang.com/127.0.0.1#7913 -ipset=/.spankbang.com/gfwlist -server=/.pmates.com/127.0.0.1#7913 -ipset=/.pmates.com/gfwlist -server=/.tibetrelieffund.co.uk/127.0.0.1#7913 -ipset=/.tibetrelieffund.co.uk/gfwlist -server=/.bynet.co.il/127.0.0.1#7913 -ipset=/.bynet.co.il/gfwlist -server=/.proxyroad.com/127.0.0.1#7913 -ipset=/.proxyroad.com/gfwlist -server=/.rightbtc.com/127.0.0.1#7913 -ipset=/.rightbtc.com/gfwlist -server=/.ccw.org.tw/127.0.0.1#7913 -ipset=/.ccw.org.tw/gfwlist -server=/.tibet.a.se/127.0.0.1#7913 -ipset=/.tibet.a.se/gfwlist -server=/.jfqu37.xyz/127.0.0.1#7913 -ipset=/.jfqu37.xyz/gfwlist -server=/.wisevid.com/127.0.0.1#7913 -ipset=/.wisevid.com/gfwlist -server=/.stc.com.sa/127.0.0.1#7913 -ipset=/.stc.com.sa/gfwlist -server=/.141jj.com/127.0.0.1#7913 -ipset=/.141jj.com/gfwlist -server=/.uncyclopedia.hk/127.0.0.1#7913 -ipset=/.uncyclopedia.hk/gfwlist -server=/.tibetanarts.org/127.0.0.1#7913 -ipset=/.tibetanarts.org/gfwlist -server=/.4bluestones.biz/127.0.0.1#7913 -ipset=/.4bluestones.biz/gfwlist -server=/.nytimes.map.fastly.net/127.0.0.1#7913 -ipset=/.nytimes.map.fastly.net/gfwlist -server=/.bcex.ca/127.0.0.1#7913 -ipset=/.bcex.ca/gfwlist -server=/.thomasbernhard.org/127.0.0.1#7913 -ipset=/.thomasbernhard.org/gfwlist -server=/.msha.gov/127.0.0.1#7913 -ipset=/.msha.gov/gfwlist -server=/.persiankitty.com/127.0.0.1#7913 -ipset=/.persiankitty.com/gfwlist -server=/.letscorp.net/127.0.0.1#7913 -ipset=/.letscorp.net/gfwlist -server=/.89-64.org/127.0.0.1#7913 -ipset=/.89-64.org/gfwlist -server=/.alanhou.com/127.0.0.1#7913 -ipset=/.alanhou.com/gfwlist -server=/.fqok.org/127.0.0.1#7913 -ipset=/.fqok.org/gfwlist -server=/.my.mail.ru/127.0.0.1#7913 -ipset=/.my.mail.ru/gfwlist -server=/.shitaotv.org/127.0.0.1#7913 -ipset=/.shitaotv.org/gfwlist -server=/.fawanghuihui.org/127.0.0.1#7913 -ipset=/.fawanghuihui.org/gfwlist -server=/.finler.net/127.0.0.1#7913 -ipset=/.finler.net/gfwlist -server=/.innermongolia.org/127.0.0.1#7913 -ipset=/.innermongolia.org/gfwlist -server=/.hizbuttahrir.org/127.0.0.1#7913 -ipset=/.hizbuttahrir.org/gfwlist -server=/.ddns.us/127.0.0.1#7913 -ipset=/.ddns.us/gfwlist -server=/.spike.com/127.0.0.1#7913 -ipset=/.spike.com/gfwlist -server=/.mojim.com/127.0.0.1#7913 -ipset=/.mojim.com/gfwlist -server=/.page2rss.com/127.0.0.1#7913 -ipset=/.page2rss.com/gfwlist -server=/.enlighten.org.tw/127.0.0.1#7913 -ipset=/.enlighten.org.tw/gfwlist -server=/.waveprotocol.org/127.0.0.1#7913 -ipset=/.waveprotocol.org/gfwlist -server=/.trickip.org/127.0.0.1#7913 -ipset=/.trickip.org/gfwlist -server=/.tubegals.com/127.0.0.1#7913 -ipset=/.tubegals.com/gfwlist -server=/.jamaat.org/127.0.0.1#7913 -ipset=/.jamaat.org/gfwlist -server=/.yigeni.com/127.0.0.1#7913 -ipset=/.yigeni.com/gfwlist -server=/.btc98.com/127.0.0.1#7913 -ipset=/.btc98.com/gfwlist -server=/.www1.american.edu/127.0.0.1#7913 -ipset=/.www1.american.edu/gfwlist -server=/.www.monlamit.org/127.0.0.1#7913 -ipset=/.www.monlamit.org/gfwlist -server=/.pttvan.org/127.0.0.1#7913 -ipset=/.pttvan.org/gfwlist -server=/.zhanlve.org/127.0.0.1#7913 -ipset=/.zhanlve.org/gfwlist -server=/.dongtaiwang.net/127.0.0.1#7913 -ipset=/.dongtaiwang.net/gfwlist -server=/.findyoutube.com/127.0.0.1#7913 -ipset=/.findyoutube.com/gfwlist -server=/.etizer.org/127.0.0.1#7913 -ipset=/.etizer.org/gfwlist -server=/.getmdl.io/127.0.0.1#7913 -ipset=/.getmdl.io/gfwlist -server=/.mvg.jp/127.0.0.1#7913 -ipset=/.mvg.jp/gfwlist -server=/.duckload.com/127.0.0.1#7913 -ipset=/.duckload.com/gfwlist -server=/.rfaweb.org/127.0.0.1#7913 -ipset=/.rfaweb.org/gfwlist -server=/.fbcdn.net/127.0.0.1#7913 -ipset=/.fbcdn.net/gfwlist -server=/.cnbbnews.wordpress.com/127.0.0.1#7913 -ipset=/.cnbbnews.wordpress.com/gfwlist -server=/.chinese.donga.com/127.0.0.1#7913 -ipset=/.chinese.donga.com/gfwlist -server=/.esmtp.biz/127.0.0.1#7913 -ipset=/.esmtp.biz/gfwlist -server=/.shodanhq.com/127.0.0.1#7913 -ipset=/.shodanhq.com/gfwlist -server=/.youlucky.com/127.0.0.1#7913 -ipset=/.youlucky.com/gfwlist -server=/.globalrescue.net/127.0.0.1#7913 -ipset=/.globalrescue.net/gfwlist -server=/.alwaysdata.net/127.0.0.1#7913 -ipset=/.alwaysdata.net/gfwlist -server=/.google.calstate.edu/127.0.0.1#7913 -ipset=/.google.calstate.edu/gfwlist -server=/.yobit.net/127.0.0.1#7913 -ipset=/.yobit.net/gfwlist -server=/.fuyin.net/127.0.0.1#7913 -ipset=/.fuyin.net/gfwlist -server=/.freemorenews.com/127.0.0.1#7913 -ipset=/.freemorenews.com/gfwlist -server=/.freakshare.com/127.0.0.1#7913 -ipset=/.freakshare.com/gfwlist -server=/.caobian.info/127.0.0.1#7913 -ipset=/.caobian.info/gfwlist -server=/.civilmedia.tw/127.0.0.1#7913 -ipset=/.civilmedia.tw/gfwlist -server=/.gunsandammo.com/127.0.0.1#7913 -ipset=/.gunsandammo.com/gfwlist -server=/.myftp.info/127.0.0.1#7913 -ipset=/.myftp.info/gfwlist -server=/.newcenturynews.com/127.0.0.1#7913 -ipset=/.newcenturynews.com/gfwlist -server=/.kucoin.com/127.0.0.1#7913 -ipset=/.kucoin.com/gfwlist -server=/.privateinternetaccess.com/127.0.0.1#7913 -ipset=/.privateinternetaccess.com/gfwlist -server=/.tube.com/127.0.0.1#7913 -ipset=/.tube.com/gfwlist -server=/.amnesty.tw/127.0.0.1#7913 -ipset=/.amnesty.tw/gfwlist -server=/.mastodon.host/127.0.0.1#7913 -ipset=/.mastodon.host/gfwlist -server=/.ironbigfools.compython.net/127.0.0.1#7913 -ipset=/.ironbigfools.compython.net/gfwlist -server=/.hutianyi.net/127.0.0.1#7913 -ipset=/.hutianyi.net/gfwlist -server=/.statueofdemocracy.org/127.0.0.1#7913 -ipset=/.statueofdemocracy.org/gfwlist -server=/.lipuman.com/127.0.0.1#7913 -ipset=/.lipuman.com/gfwlist -server=/.jbtalks.cc/127.0.0.1#7913 -ipset=/.jbtalks.cc/gfwlist -server=/.on.cc/127.0.0.1#7913 -ipset=/.on.cc/gfwlist -server=/.fourthinternational.org/127.0.0.1#7913 -ipset=/.fourthinternational.org/gfwlist -server=/.lflink.com/127.0.0.1#7913 -ipset=/.lflink.com/gfwlist -server=/.duplicati.com/127.0.0.1#7913 -ipset=/.duplicati.com/gfwlist -server=/.appdownloader.net/127.0.0.1#7913 -ipset=/.appdownloader.net/gfwlist -server=/.placemix.com/127.0.0.1#7913 -ipset=/.placemix.com/gfwlist -server=/.pen.io/127.0.0.1#7913 -ipset=/.pen.io/gfwlist -server=/.gaymap.cc/127.0.0.1#7913 -ipset=/.gaymap.cc/gfwlist -server=/.blog.lester850.info/127.0.0.1#7913 -ipset=/.blog.lester850.info/gfwlist -server=/.theporndude.com/127.0.0.1#7913 -ipset=/.theporndude.com/gfwlist -server=/.youtubeeducation.com/127.0.0.1#7913 -ipset=/.youtubeeducation.com/gfwlist -server=/.pixnet.net/127.0.0.1#7913 -ipset=/.pixnet.net/gfwlist -server=/.oizoblog.com/127.0.0.1#7913 -ipset=/.oizoblog.com/gfwlist -server=/.iam.soy/127.0.0.1#7913 -ipset=/.iam.soy/gfwlist -server=/.fastssh.com/127.0.0.1#7913 -ipset=/.fastssh.com/gfwlist -server=/.edgecastcdn.net/127.0.0.1#7913 -ipset=/.edgecastcdn.net/gfwlist -server=/.pwned.com/127.0.0.1#7913 -ipset=/.pwned.com/gfwlist -server=/.hkfront.org/127.0.0.1#7913 -ipset=/.hkfront.org/gfwlist -server=/.tibetaid.org/127.0.0.1#7913 -ipset=/.tibetaid.org/gfwlist -server=/.hbo.com/127.0.0.1#7913 -ipset=/.hbo.com/gfwlist -server=/.pinterest.ca/127.0.0.1#7913 -ipset=/.pinterest.ca/gfwlist -server=/.xizang-zhiye.org/127.0.0.1#7913 -ipset=/.xizang-zhiye.org/gfwlist -server=/.buy.yahoo.com.tw/127.0.0.1#7913 -ipset=/.buy.yahoo.com.tw/gfwlist -server=/.www.taup.org.tw/127.0.0.1#7913 -ipset=/.www.taup.org.tw/gfwlist -server=/.pinterest.dk/127.0.0.1#7913 -ipset=/.pinterest.dk/gfwlist -server=/.fanyue.info/127.0.0.1#7913 -ipset=/.fanyue.info/gfwlist -server=/.westkit.net/127.0.0.1#7913 -ipset=/.westkit.net/gfwlist -server=/.wikimapia.org/127.0.0.1#7913 -ipset=/.wikimapia.org/gfwlist -server=/.friendfeed-media.com/127.0.0.1#7913 -ipset=/.friendfeed-media.com/gfwlist -server=/.overplay.net/127.0.0.1#7913 -ipset=/.overplay.net/gfwlist -server=/.encyclopedia.com/127.0.0.1#7913 -ipset=/.encyclopedia.com/gfwlist -server=/.lemonde.fr/127.0.0.1#7913 -ipset=/.lemonde.fr/gfwlist -server=/.fpmt-osel.org/127.0.0.1#7913 -ipset=/.fpmt-osel.org/gfwlist -server=/.certificate-transparency.org/127.0.0.1#7913 -ipset=/.certificate-transparency.org/gfwlist -server=/.ruyiseek.com/127.0.0.1#7913 -ipset=/.ruyiseek.com/gfwlist -server=/.strongvpn.com/127.0.0.1#7913 -ipset=/.strongvpn.com/gfwlist -server=/.wo.tc/127.0.0.1#7913 -ipset=/.wo.tc/gfwlist -server=/.ddns.net/127.0.0.1#7913 -ipset=/.ddns.net/gfwlist -server=/.serveuser.com/127.0.0.1#7913 -ipset=/.serveuser.com/gfwlist -server=/.lizhizhuangbi.com/127.0.0.1#7913 -ipset=/.lizhizhuangbi.com/gfwlist -server=/.goo.gl/127.0.0.1#7913 -ipset=/.goo.gl/gfwlist -server=/.twerkingbutt.com/127.0.0.1#7913 -ipset=/.twerkingbutt.com/gfwlist -server=/.globaltm.org/127.0.0.1#7913 -ipset=/.globaltm.org/gfwlist -server=/.dhcp.biz/127.0.0.1#7913 -ipset=/.dhcp.biz/gfwlist -server=/.longmusic.com/127.0.0.1#7913 -ipset=/.longmusic.com/gfwlist -server=/.tvants.com/127.0.0.1#7913 -ipset=/.tvants.com/gfwlist -server=/.tryheart.jp/127.0.0.1#7913 -ipset=/.tryheart.jp/gfwlist -server=/.vpnuk.info/127.0.0.1#7913 -ipset=/.vpnuk.info/gfwlist -server=/.unblockdmm.com/127.0.0.1#7913 -ipset=/.unblockdmm.com/gfwlist -server=/.isaacmao.com/127.0.0.1#7913 -ipset=/.isaacmao.com/gfwlist -server=/.vpn.cmu.edu/127.0.0.1#7913 -ipset=/.vpn.cmu.edu/gfwlist -server=/.easyca.ca/127.0.0.1#7913 -ipset=/.easyca.ca/gfwlist -server=/.google.it/127.0.0.1#7913 -ipset=/.google.it/gfwlist -server=/.static.shemalez.com/127.0.0.1#7913 -ipset=/.static.shemalez.com/gfwlist -server=/.dns2.us/127.0.0.1#7913 -ipset=/.dns2.us/gfwlist -server=/.chapm25.com/127.0.0.1#7913 -ipset=/.chapm25.com/gfwlist -server=/.tibet.at/127.0.0.1#7913 -ipset=/.tibet.at/gfwlist -server=/.soc.mil/127.0.0.1#7913 -ipset=/.soc.mil/gfwlist -server=/.lerosua.org/127.0.0.1#7913 -ipset=/.lerosua.org/gfwlist -server=/.lagranepoca.com/127.0.0.1#7913 -ipset=/.lagranepoca.com/gfwlist -server=/.fdc64.org/127.0.0.1#7913 -ipset=/.fdc64.org/gfwlist -server=/.appspot.com/127.0.0.1#7913 -ipset=/.appspot.com/gfwlist -server=/.get.app/127.0.0.1#7913 -ipset=/.get.app/gfwlist -server=/.csw.org.uk/127.0.0.1#7913 -ipset=/.csw.org.uk/gfwlist -server=/.newgrounds.com/127.0.0.1#7913 -ipset=/.newgrounds.com/gfwlist -server=/.bitinka.com.ar/127.0.0.1#7913 -ipset=/.bitinka.com.ar/gfwlist -server=/.mrface.com/127.0.0.1#7913 -ipset=/.mrface.com/gfwlist -server=/.superfreevpn.com/127.0.0.1#7913 -ipset=/.superfreevpn.com/gfwlist -server=/.tbcollege.org/127.0.0.1#7913 -ipset=/.tbcollege.org/gfwlist -server=/.gardennetworks.org/127.0.0.1#7913 -ipset=/.gardennetworks.org/gfwlist -server=/.resilio.com/127.0.0.1#7913 -ipset=/.resilio.com/gfwlist -server=/.allgirlsallowed.org/127.0.0.1#7913 -ipset=/.allgirlsallowed.org/gfwlist -server=/.myz.info/127.0.0.1#7913 -ipset=/.myz.info/gfwlist -server=/.tigervpn.com/127.0.0.1#7913 -ipset=/.tigervpn.com/gfwlist -server=/.supervpn.net/127.0.0.1#7913 -ipset=/.supervpn.net/gfwlist -server=/.315lz.com/127.0.0.1#7913 -ipset=/.315lz.com/gfwlist -server=/.dongtaiwang.com/127.0.0.1#7913 -ipset=/.dongtaiwang.com/gfwlist -server=/.51.ca/127.0.0.1#7913 -ipset=/.51.ca/gfwlist -server=/.happy-vpn.com/127.0.0.1#7913 -ipset=/.happy-vpn.com/gfwlist -server=/.frontlinedefenders.org/127.0.0.1#7913 -ipset=/.frontlinedefenders.org/gfwlist -server=/.shat-tibet.com/127.0.0.1#7913 -ipset=/.shat-tibet.com/gfwlist -server=/.imageshack.us/127.0.0.1#7913 -ipset=/.imageshack.us/gfwlist -server=/.dalailama.ru/127.0.0.1#7913 -ipset=/.dalailama.ru/gfwlist -server=/.gaforum.org/127.0.0.1#7913 -ipset=/.gaforum.org/gfwlist -server=/.hentai.to/127.0.0.1#7913 -ipset=/.hentai.to/gfwlist -server=/.laogai.org/127.0.0.1#7913 -ipset=/.laogai.org/gfwlist -server=/.newstamago.com/127.0.0.1#7913 -ipset=/.newstamago.com/gfwlist -server=/.socrec.org/127.0.0.1#7913 -ipset=/.socrec.org/gfwlist -server=/.uwants.com/127.0.0.1#7913 -ipset=/.uwants.com/gfwlist -server=/.itweet.net/127.0.0.1#7913 -ipset=/.itweet.net/gfwlist -server=/.cahr.org.tw/127.0.0.1#7913 -ipset=/.cahr.org.tw/gfwlist -server=/.amazon.com/127.0.0.1#7913 -ipset=/.amazon.com/gfwlist -server=/.dalailamacenter.org/127.0.0.1#7913 -ipset=/.dalailamacenter.org/gfwlist -server=/.mgoon.com/127.0.0.1#7913 -ipset=/.mgoon.com/gfwlist -server=/.fpmtmexico.org/127.0.0.1#7913 -ipset=/.fpmtmexico.org/gfwlist -server=/.chuizi.net/127.0.0.1#7913 -ipset=/.chuizi.net/gfwlist -server=/.godsimmediatecontact.com/127.0.0.1#7913 -ipset=/.godsimmediatecontact.com/gfwlist -server=/.tmi.me/127.0.0.1#7913 -ipset=/.tmi.me/gfwlist -server=/.jiaoyou8.com/127.0.0.1#7913 -ipset=/.jiaoyou8.com/gfwlist -server=/.foxdie.us/127.0.0.1#7913 -ipset=/.foxdie.us/gfwlist -server=/.gather.com/127.0.0.1#7913 -ipset=/.gather.com/gfwlist -server=/.pacificpoker.com/127.0.0.1#7913 -ipset=/.pacificpoker.com/gfwlist -server=/.labiennale.org/127.0.0.1#7913 -ipset=/.labiennale.org/gfwlist -server=/.tahr.org.tw/127.0.0.1#7913 -ipset=/.tahr.org.tw/gfwlist -server=/.huaxiabao.org/127.0.0.1#7913 -ipset=/.huaxiabao.org/gfwlist -server=/.ourhobby.com/127.0.0.1#7913 -ipset=/.ourhobby.com/gfwlist -server=/.twiends.com/127.0.0.1#7913 -ipset=/.twiends.com/gfwlist -server=/.padmanet.com/127.0.0.1#7913 -ipset=/.padmanet.com/gfwlist -server=/.bibox.com/127.0.0.1#7913 -ipset=/.bibox.com/gfwlist -server=/.helplinfen.com/127.0.0.1#7913 -ipset=/.helplinfen.com/gfwlist -server=/.brandonhutchinson.com/127.0.0.1#7913 -ipset=/.brandonhutchinson.com/gfwlist -server=/.dabr.eu/127.0.0.1#7913 -ipset=/.dabr.eu/gfwlist -server=/.xinsheng.net/127.0.0.1#7913 -ipset=/.xinsheng.net/gfwlist -server=/.googledomains.com/127.0.0.1#7913 -ipset=/.googledomains.com/gfwlist -server=/.cdn-images.mailchimp.com/127.0.0.1#7913 -ipset=/.cdn-images.mailchimp.com/gfwlist -server=/.bbs.mychat.to/127.0.0.1#7913 -ipset=/.bbs.mychat.to/gfwlist -server=/.proxy.org/127.0.0.1#7913 -ipset=/.proxy.org/gfwlist -server=/.centerforhumanreprod.com/127.0.0.1#7913 -ipset=/.centerforhumanreprod.com/gfwlist -server=/.mohu.club/127.0.0.1#7913 -ipset=/.mohu.club/gfwlist -server=/.standupfortibet.org/127.0.0.1#7913 -ipset=/.standupfortibet.org/gfwlist -server=/.popo.tw/127.0.0.1#7913 -ipset=/.popo.tw/gfwlist -server=/.nflximg.net/127.0.0.1#7913 -ipset=/.nflximg.net/gfwlist -server=/.sketchappsources.com/127.0.0.1#7913 -ipset=/.sketchappsources.com/gfwlist -server=/.filmingfortibet.org/127.0.0.1#7913 -ipset=/.filmingfortibet.org/gfwlist -server=/.softether.co.jp/127.0.0.1#7913 -ipset=/.softether.co.jp/gfwlist -server=/.tibetmuseum.org/127.0.0.1#7913 -ipset=/.tibetmuseum.org/gfwlist -server=/.getfoxyproxy.org/127.0.0.1#7913 -ipset=/.getfoxyproxy.org/gfwlist -server=/.twtrland.com/127.0.0.1#7913 -ipset=/.twtrland.com/gfwlist -server=/.playpcesor.com/127.0.0.1#7913 -ipset=/.playpcesor.com/gfwlist -server=/.vod-abematv.akamaized.net/127.0.0.1#7913 -ipset=/.vod-abematv.akamaized.net/gfwlist -server=/.data.flurry.com/127.0.0.1#7913 -ipset=/.data.flurry.com/gfwlist -server=/.otcbtc.com/127.0.0.1#7913 -ipset=/.otcbtc.com/gfwlist -server=/.chinesedailynews.com/127.0.0.1#7913 -ipset=/.chinesedailynews.com/gfwlist -server=/.privatevpn.com/127.0.0.1#7913 -ipset=/.privatevpn.com/gfwlist -server=/.soupofmedia.com/127.0.0.1#7913 -ipset=/.soupofmedia.com/gfwlist -server=/.convio.net/127.0.0.1#7913 -ipset=/.convio.net/gfwlist -server=/.huhamhire.com/127.0.0.1#7913 -ipset=/.huhamhire.com/gfwlist -server=/.toh.info/127.0.0.1#7913 -ipset=/.toh.info/gfwlist -server=/.chinman.net/127.0.0.1#7913 -ipset=/.chinman.net/gfwlist -server=/.coin2co.in/127.0.0.1#7913 -ipset=/.coin2co.in/gfwlist -server=/.duanzhihu.com/127.0.0.1#7913 -ipset=/.duanzhihu.com/gfwlist -server=/.blogblog.com/127.0.0.1#7913 -ipset=/.blogblog.com/gfwlist -server=/.nokola.com/127.0.0.1#7913 -ipset=/.nokola.com/gfwlist -server=/.tibetanfeministcollective.org/127.0.0.1#7913 -ipset=/.tibetanfeministcollective.org/gfwlist -server=/.news.omy.sg/127.0.0.1#7913 -ipset=/.news.omy.sg/gfwlist -server=/.macrovpn.com/127.0.0.1#7913 -ipset=/.macrovpn.com/gfwlist -server=/.roboforex.com/127.0.0.1#7913 -ipset=/.roboforex.com/gfwlist -server=/.cnineu.com/127.0.0.1#7913 -ipset=/.cnineu.com/gfwlist -server=/.hideman.net/127.0.0.1#7913 -ipset=/.hideman.net/gfwlist -server=/.fc2blog.net/127.0.0.1#7913 -ipset=/.fc2blog.net/gfwlist -server=/.eroprofile.com/127.0.0.1#7913 -ipset=/.eroprofile.com/gfwlist -server=/.lionsroar.com/127.0.0.1#7913 -ipset=/.lionsroar.com/gfwlist -server=/.rg3.github.io/127.0.0.1#7913 -ipset=/.rg3.github.io/gfwlist -server=/.waymo.com/127.0.0.1#7913 -ipset=/.waymo.com/gfwlist -server=/.video.aol.com/127.0.0.1#7913 -ipset=/.video.aol.com/gfwlist -server=/.mitao.com.tw/127.0.0.1#7913 -ipset=/.mitao.com.tw/gfwlist -server=/.tibetcity.com/127.0.0.1#7913 -ipset=/.tibetcity.com/gfwlist -server=/.nytimg.com/127.0.0.1#7913 -ipset=/.nytimg.com/gfwlist -server=/.hacg.red/127.0.0.1#7913 -ipset=/.hacg.red/gfwlist -server=/.line.me/127.0.0.1#7913 -ipset=/.line.me/gfwlist -server=/.i818hk.com/127.0.0.1#7913 -ipset=/.i818hk.com/gfwlist -server=/.hegre-art.com/127.0.0.1#7913 -ipset=/.hegre-art.com/gfwlist -server=/.westernshugdensociety.org/127.0.0.1#7913 -ipset=/.westernshugdensociety.org/gfwlist -server=/.pulse.yahoo.com/127.0.0.1#7913 -ipset=/.pulse.yahoo.com/gfwlist -server=/.vatn.org/127.0.0.1#7913 -ipset=/.vatn.org/gfwlist -server=/.angela-merkel.de/127.0.0.1#7913 -ipset=/.angela-merkel.de/gfwlist -server=/.chinasucks.net/127.0.0.1#7913 -ipset=/.chinasucks.net/gfwlist -server=/.ndr.de/127.0.0.1#7913 -ipset=/.ndr.de/gfwlist -server=/.mx981.com/127.0.0.1#7913 -ipset=/.mx981.com/gfwlist -server=/.cecc.gov/127.0.0.1#7913 -ipset=/.cecc.gov/gfwlist -server=/.eurekavpt.com/127.0.0.1#7913 -ipset=/.eurekavpt.com/gfwlist -server=/.notify.dropboxapi.com/127.0.0.1#7913 -ipset=/.notify.dropboxapi.com/gfwlist -server=/.lefora.com/127.0.0.1#7913 -ipset=/.lefora.com/gfwlist -server=/.asia-gaming.com/127.0.0.1#7913 -ipset=/.asia-gaming.com/gfwlist -server=/.pinoy-n.com/127.0.0.1#7913 -ipset=/.pinoy-n.com/gfwlist -server=/.camfrog.com/127.0.0.1#7913 -ipset=/.camfrog.com/gfwlist -server=/.weblagu.com/127.0.0.1#7913 -ipset=/.weblagu.com/gfwlist -server=/.hjclub.info/127.0.0.1#7913 -ipset=/.hjclub.info/gfwlist -server=/.politiscales.net/127.0.0.1#7913 -ipset=/.politiscales.net/gfwlist -server=/.5299.tv/127.0.0.1#7913 -ipset=/.5299.tv/gfwlist -server=/.tcnynj.org/127.0.0.1#7913 -ipset=/.tcnynj.org/gfwlist -server=/.tibetcharity.dk/127.0.0.1#7913 -ipset=/.tibetcharity.dk/gfwlist -server=/.himemix.net/127.0.0.1#7913 -ipset=/.himemix.net/gfwlist -server=/.bonfoundation.org/127.0.0.1#7913 -ipset=/.bonfoundation.org/gfwlist -server=/.tuo8.ninja/127.0.0.1#7913 -ipset=/.tuo8.ninja/gfwlist -server=/.goodreads.com/127.0.0.1#7913 -ipset=/.goodreads.com/gfwlist -server=/.ss7.vzw.com/127.0.0.1#7913 -ipset=/.ss7.vzw.com/gfwlist -server=/.vds.rightster.com/127.0.0.1#7913 -ipset=/.vds.rightster.com/gfwlist -server=/.solidfiles.com/127.0.0.1#7913 -ipset=/.solidfiles.com/gfwlist -server=/.hk.frienddy.com/127.0.0.1#7913 -ipset=/.hk.frienddy.com/gfwlist -server=/.gmll.org/127.0.0.1#7913 -ipset=/.gmll.org/gfwlist -server=/.graphis.ne.jp/127.0.0.1#7913 -ipset=/.graphis.ne.jp/gfwlist -server=/.bbs.ecstart.com/127.0.0.1#7913 -ipset=/.bbs.ecstart.com/gfwlist -server=/.jbtalks.my/127.0.0.1#7913 -ipset=/.jbtalks.my/gfwlist -server=/.mynumber.org/127.0.0.1#7913 -ipset=/.mynumber.org/gfwlist -server=/.sitekreator.com/127.0.0.1#7913 -ipset=/.sitekreator.com/gfwlist -server=/.alwaysvpn.com/127.0.0.1#7913 -ipset=/.alwaysvpn.com/gfwlist -server=/.users.skynet.be/127.0.0.1#7913 -ipset=/.users.skynet.be/gfwlist -server=/.xn--p8j9a0d9c9a.xn--q9jyb4c/127.0.0.1#7913 -ipset=/.xn--p8j9a0d9c9a.xn--q9jyb4c/gfwlist -server=/.cnabc.com/127.0.0.1#7913 -ipset=/.cnabc.com/gfwlist -server=/.chubun.com/127.0.0.1#7913 -ipset=/.chubun.com/gfwlist -server=/.uploadstation.com/127.0.0.1#7913 -ipset=/.uploadstation.com/gfwlist -server=/.me.me/127.0.0.1#7913 -ipset=/.me.me/gfwlist -server=/.apkpure.com/127.0.0.1#7913 -ipset=/.apkpure.com/gfwlist -server=/.mynetav.org/127.0.0.1#7913 -ipset=/.mynetav.org/gfwlist -server=/.now.com/127.0.0.1#7913 -ipset=/.now.com/gfwlist -server=/.rapbull.net/127.0.0.1#7913 -ipset=/.rapbull.net/gfwlist -server=/.kba-tx.org/127.0.0.1#7913 -ipset=/.kba-tx.org/gfwlist -server=/.pinterest.fr/127.0.0.1#7913 -ipset=/.pinterest.fr/gfwlist -server=/.sacom.hk/127.0.0.1#7913 -ipset=/.sacom.hk/gfwlist -server=/.on2.com/127.0.0.1#7913 -ipset=/.on2.com/gfwlist -server=/.urbansurvival.com/127.0.0.1#7913 -ipset=/.urbansurvival.com/gfwlist -server=/.abc.xyz/127.0.0.1#7913 -ipset=/.abc.xyz/gfwlist -server=/.bastillepost.com/127.0.0.1#7913 -ipset=/.bastillepost.com/gfwlist -server=/.serveusers.com/127.0.0.1#7913 -ipset=/.serveusers.com/gfwlist -server=/.metrolife.ca/127.0.0.1#7913 -ipset=/.metrolife.ca/gfwlist -server=/.freeopenvpn.com/127.0.0.1#7913 -ipset=/.freeopenvpn.com/gfwlist -server=/.www.owind.com/127.0.0.1#7913 -ipset=/.www.owind.com/gfwlist -server=/.savetibetstore.org/127.0.0.1#7913 -ipset=/.savetibetstore.org/gfwlist -server=/.vpnpop.com/127.0.0.1#7913 -ipset=/.vpnpop.com/gfwlist -server=/.cnex.org.cn/127.0.0.1#7913 -ipset=/.cnex.org.cn/gfwlist -server=/.sstmlt.moe/127.0.0.1#7913 -ipset=/.sstmlt.moe/gfwlist -server=/.4shared.com/127.0.0.1#7913 -ipset=/.4shared.com/gfwlist -server=/.2shared.com/127.0.0.1#7913 -ipset=/.2shared.com/gfwlist -server=/.minghui-a.org/127.0.0.1#7913 -ipset=/.minghui-a.org/gfwlist -server=/.uighur.nl/127.0.0.1#7913 -ipset=/.uighur.nl/gfwlist -server=/.freeyellow.com/127.0.0.1#7913 -ipset=/.freeyellow.com/gfwlist -server=/.hkgreenradio.org/127.0.0.1#7913 -ipset=/.hkgreenradio.org/gfwlist -server=/.isuntv.com/127.0.0.1#7913 -ipset=/.isuntv.com/gfwlist -server=/.is.gd/127.0.0.1#7913 -ipset=/.is.gd/gfwlist -server=/.get.page/127.0.0.1#7913 -ipset=/.get.page/gfwlist -server=/.erabaru.net/127.0.0.1#7913 -ipset=/.erabaru.net/gfwlist -server=/.tweeplike.me/127.0.0.1#7913 -ipset=/.tweeplike.me/gfwlist -server=/.gov.taipei/127.0.0.1#7913 -ipset=/.gov.taipei/gfwlist -server=/.googlehosted.com/127.0.0.1#7913 -ipset=/.googlehosted.com/gfwlist -server=/.foxgay.com/127.0.0.1#7913 -ipset=/.foxgay.com/gfwlist -server=/.jukujo-club.com/127.0.0.1#7913 -ipset=/.jukujo-club.com/gfwlist -server=/.tfhub.dev/127.0.0.1#7913 -ipset=/.tfhub.dev/gfwlist -server=/.yorkbbs.ca/127.0.0.1#7913 -ipset=/.yorkbbs.ca/gfwlist -server=/.sourcewadio.com/127.0.0.1#7913 -ipset=/.sourcewadio.com/gfwlist -server=/.pachosting.com/127.0.0.1#7913 -ipset=/.pachosting.com/gfwlist -server=/.lidecheng.com/127.0.0.1#7913 -ipset=/.lidecheng.com/gfwlist -server=/.twitgether.com/127.0.0.1#7913 -ipset=/.twitgether.com/gfwlist -server=/.soumo.info/127.0.0.1#7913 -ipset=/.soumo.info/gfwlist -server=/.freechal.com/127.0.0.1#7913 -ipset=/.freechal.com/gfwlist -server=/.geocities.com/127.0.0.1#7913 -ipset=/.geocities.com/gfwlist -server=/.metart.com/127.0.0.1#7913 -ipset=/.metart.com/gfwlist -server=/.tw.iqiyi.com/127.0.0.1#7913 -ipset=/.tw.iqiyi.com/gfwlist -server=/.akademiye.org/127.0.0.1#7913 -ipset=/.akademiye.org/gfwlist -server=/.sgzhan.com/127.0.0.1#7913 -ipset=/.sgzhan.com/gfwlist -server=/.tbsseattle.org/127.0.0.1#7913 -ipset=/.tbsseattle.org/gfwlist -server=/.withyoutube.com/127.0.0.1#7913 -ipset=/.withyoutube.com/gfwlist -server=/.hao.news/127.0.0.1#7913 -ipset=/.hao.news/gfwlist -server=/.kissbbao.cn/127.0.0.1#7913 -ipset=/.kissbbao.cn/gfwlist -server=/.tw.gigacircle.com/127.0.0.1#7913 -ipset=/.tw.gigacircle.com/gfwlist -server=/.share.ovi.com/127.0.0.1#7913 -ipset=/.share.ovi.com/gfwlist -server=/.lantosfoundation.org/127.0.0.1#7913 -ipset=/.lantosfoundation.org/gfwlist -server=/.vine.co/127.0.0.1#7913 -ipset=/.vine.co/gfwlist -server=/.1mobile.com/127.0.0.1#7913 -ipset=/.1mobile.com/gfwlist -server=/.cn.sandscotaicentral.com/127.0.0.1#7913 -ipset=/.cn.sandscotaicentral.com/gfwlist -server=/.bestgore.com/127.0.0.1#7913 -ipset=/.bestgore.com/gfwlist -server=/.changeip.net/127.0.0.1#7913 -ipset=/.changeip.net/gfwlist -server=/.holyspiritspeaks.org/127.0.0.1#7913 -ipset=/.holyspiritspeaks.org/gfwlist -server=/.blog.soylent.com/127.0.0.1#7913 -ipset=/.blog.soylent.com/gfwlist -server=/.etherdelta.com/127.0.0.1#7913 -ipset=/.etherdelta.com/gfwlist -server=/.ustream.tv/127.0.0.1#7913 -ipset=/.ustream.tv/gfwlist -server=/.vlog.xuite.net/127.0.0.1#7913 -ipset=/.vlog.xuite.net/gfwlist -server=/.db.tt/127.0.0.1#7913 -ipset=/.db.tt/gfwlist -server=/.archive.li/127.0.0.1#7913 -ipset=/.archive.li/gfwlist -server=/.chinachange.org/127.0.0.1#7913 -ipset=/.chinachange.org/gfwlist -server=/.8news.com.tw/127.0.0.1#7913 -ipset=/.8news.com.tw/gfwlist -server=/.hkjp.org/127.0.0.1#7913 -ipset=/.hkjp.org/gfwlist -server=/.google.az/127.0.0.1#7913 -ipset=/.google.az/gfwlist -server=/.javseen.com/127.0.0.1#7913 -ipset=/.javseen.com/gfwlist -server=/.chinaworker.info/127.0.0.1#7913 -ipset=/.chinaworker.info/gfwlist -server=/.hotspotshield.com/127.0.0.1#7913 -ipset=/.hotspotshield.com/gfwlist -server=/.wire.com/127.0.0.1#7913 -ipset=/.wire.com/gfwlist -server=/.gvm.com.tw/127.0.0.1#7913 -ipset=/.gvm.com.tw/gfwlist -server=/.blog.xuite.net/127.0.0.1#7913 -ipset=/.blog.xuite.net/gfwlist -server=/.video.aol.co.uk/127.0.0.1#7913 -ipset=/.video.aol.co.uk/gfwlist -server=/.citypopulation.de/127.0.0.1#7913 -ipset=/.citypopulation.de/gfwlist -server=/.bolehvpn.net/127.0.0.1#7913 -ipset=/.bolehvpn.net/gfwlist -server=/.khmusic.com.tw/127.0.0.1#7913 -ipset=/.khmusic.com.tw/gfwlist -server=/.sendspace.com/127.0.0.1#7913 -ipset=/.sendspace.com/gfwlist -server=/.ismprofessional.net/127.0.0.1#7913 -ipset=/.ismprofessional.net/gfwlist -server=/.alicejapan.co.jp/127.0.0.1#7913 -ipset=/.alicejapan.co.jp/gfwlist -server=/.niu.moe/127.0.0.1#7913 -ipset=/.niu.moe/gfwlist -server=/.sukebei.nyaa.si/127.0.0.1#7913 -ipset=/.sukebei.nyaa.si/gfwlist -server=/.rconversation.blogs.com/127.0.0.1#7913 -ipset=/.rconversation.blogs.com/gfwlist -server=/.nyti.ms/127.0.0.1#7913 -ipset=/.nyti.ms/gfwlist -server=/.hulu.com/127.0.0.1#7913 -ipset=/.hulu.com/gfwlist -server=/.sadistic-v.com/127.0.0.1#7913 -ipset=/.sadistic-v.com/gfwlist -server=/.weijingsheng.org/127.0.0.1#7913 -ipset=/.weijingsheng.org/gfwlist -server=/.if.ttt/127.0.0.1#7913 -ipset=/.if.ttt/gfwlist -server=/.insidevoa.com/127.0.0.1#7913 -ipset=/.insidevoa.com/gfwlist -server=/.iphone4hongkong.com/127.0.0.1#7913 -ipset=/.iphone4hongkong.com/gfwlist -server=/.vovo2000.com/127.0.0.1#7913 -ipset=/.vovo2000.com/gfwlist -server=/.fleursdeslettres.com/127.0.0.1#7913 -ipset=/.fleursdeslettres.com/gfwlist -server=/.vpntraffic.com/127.0.0.1#7913 -ipset=/.vpntraffic.com/gfwlist -server=/.hybrid-analysis.com/127.0.0.1#7913 -ipset=/.hybrid-analysis.com/gfwlist -server=/.amnestyusa.org/127.0.0.1#7913 -ipset=/.amnestyusa.org/gfwlist -server=/.dadazim.com/127.0.0.1#7913 -ipset=/.dadazim.com/gfwlist -server=/.epochtimes.ie/127.0.0.1#7913 -ipset=/.epochtimes.ie/gfwlist -server=/.usma.edu/127.0.0.1#7913 -ipset=/.usma.edu/gfwlist -server=/.geocities.co.jp/127.0.0.1#7913 -ipset=/.geocities.co.jp/gfwlist -server=/.ugo.com/127.0.0.1#7913 -ipset=/.ugo.com/gfwlist -server=/.biliworld.com/127.0.0.1#7913 -ipset=/.biliworld.com/gfwlist -server=/.furbo.org/127.0.0.1#7913 -ipset=/.furbo.org/gfwlist -server=/.ukliferadio.co.uk/127.0.0.1#7913 -ipset=/.ukliferadio.co.uk/gfwlist -server=/.thinkgeek.com/127.0.0.1#7913 -ipset=/.thinkgeek.com/gfwlist -server=/.tweepmag.com/127.0.0.1#7913 -ipset=/.tweepmag.com/gfwlist -server=/.a5.com.ru/127.0.0.1#7913 -ipset=/.a5.com.ru/gfwlist -server=/.kinmen.travel/127.0.0.1#7913 -ipset=/.kinmen.travel/gfwlist -server=/.gs-discuss.com/127.0.0.1#7913 -ipset=/.gs-discuss.com/gfwlist -server=/.fring.com/127.0.0.1#7913 -ipset=/.fring.com/gfwlist -server=/.api-verify.recaptcha.net/127.0.0.1#7913 -ipset=/.api-verify.recaptcha.net/gfwlist -server=/.sethwklein.net/127.0.0.1#7913 -ipset=/.sethwklein.net/gfwlist -server=/.freechina.net/127.0.0.1#7913 -ipset=/.freechina.net/gfwlist -server=/.istockphoto.com/127.0.0.1#7913 -ipset=/.istockphoto.com/gfwlist -server=/.hizb-ut-tahrir.info/127.0.0.1#7913 -ipset=/.hizb-ut-tahrir.info/gfwlist -server=/.activpn.com/127.0.0.1#7913 -ipset=/.activpn.com/gfwlist -server=/.changeip.name/127.0.0.1#7913 -ipset=/.changeip.name/gfwlist -server=/.deaftone.com/127.0.0.1#7913 -ipset=/.deaftone.com/gfwlist -server=/.paljorpublications.com/127.0.0.1#7913 -ipset=/.paljorpublications.com/gfwlist -server=/.fevernet.com/127.0.0.1#7913 -ipset=/.fevernet.com/gfwlist -server=/.firearmsworld.net/127.0.0.1#7913 -ipset=/.firearmsworld.net/gfwlist -server=/.blockless.com/127.0.0.1#7913 -ipset=/.blockless.com/gfwlist -server=/.redtube.com/127.0.0.1#7913 -ipset=/.redtube.com/gfwlist -server=/.nexton-net.jp/127.0.0.1#7913 -ipset=/.nexton-net.jp/gfwlist -server=/.tweetdeck.com/127.0.0.1#7913 -ipset=/.tweetdeck.com/gfwlist -server=/.ivacy.com/127.0.0.1#7913 -ipset=/.ivacy.com/gfwlist -server=/.commandarms.com/127.0.0.1#7913 -ipset=/.commandarms.com/gfwlist -server=/.hk.myblog.yahoo.com/127.0.0.1#7913 -ipset=/.hk.myblog.yahoo.com/gfwlist -server=/.buzzhand.net/127.0.0.1#7913 -ipset=/.buzzhand.net/gfwlist -server=/.tibetonline.com/127.0.0.1#7913 -ipset=/.tibetonline.com/gfwlist -server=/.penchinese.net/127.0.0.1#7913 -ipset=/.penchinese.net/gfwlist -server=/.myav.com.tw/127.0.0.1#7913 -ipset=/.myav.com.tw/gfwlist -server=/.pornsharing.com/127.0.0.1#7913 -ipset=/.pornsharing.com/gfwlist -server=/.openid.net/127.0.0.1#7913 -ipset=/.openid.net/gfwlist -server=/.falunworld.net/127.0.0.1#7913 -ipset=/.falunworld.net/gfwlist -server=/.unholyknight.com/127.0.0.1#7913 -ipset=/.unholyknight.com/gfwlist -server=/.googlesile.com/127.0.0.1#7913 -ipset=/.googlesile.com/gfwlist -server=/.immoral.jp/127.0.0.1#7913 -ipset=/.immoral.jp/gfwlist -server=/.cgst.edu/127.0.0.1#7913 -ipset=/.cgst.edu/gfwlist -server=/.directcreative.com/127.0.0.1#7913 -ipset=/.directcreative.com/gfwlist -server=/.h-china.org/127.0.0.1#7913 -ipset=/.h-china.org/gfwlist -server=/.islamtoday.net/127.0.0.1#7913 -ipset=/.islamtoday.net/gfwlist -server=/.jbtalks.com/127.0.0.1#7913 -ipset=/.jbtalks.com/gfwlist -server=/.go.nesnode.com/127.0.0.1#7913 -ipset=/.go.nesnode.com/gfwlist -server=/.tweetymail.com/127.0.0.1#7913 -ipset=/.tweetymail.com/gfwlist -server=/.discordapp.com/127.0.0.1#7913 -ipset=/.discordapp.com/gfwlist -server=/.fffff.at/127.0.0.1#7913 -ipset=/.fffff.at/gfwlist -server=/.tumutanzi.com/127.0.0.1#7913 -ipset=/.tumutanzi.com/gfwlist -server=/.behindkink.com/127.0.0.1#7913 -ipset=/.behindkink.com/gfwlist -server=/.dongyangjing.com/127.0.0.1#7913 -ipset=/.dongyangjing.com/gfwlist -server=/.phncdn.com/127.0.0.1#7913 -ipset=/.phncdn.com/gfwlist -server=/.dfn.org/127.0.0.1#7913 -ipset=/.dfn.org/gfwlist -server=/.talk853.com/127.0.0.1#7913 -ipset=/.talk853.com/gfwlist -server=/.x365x.com/127.0.0.1#7913 -ipset=/.x365x.com/gfwlist -server=/.beijingspring.com/127.0.0.1#7913 -ipset=/.beijingspring.com/gfwlist -server=/.hut2.ru/127.0.0.1#7913 -ipset=/.hut2.ru/gfwlist -server=/.crazyshit.com/127.0.0.1#7913 -ipset=/.crazyshit.com/gfwlist -server=/.s1s1s1.com/127.0.0.1#7913 -ipset=/.s1s1s1.com/gfwlist -server=/.avdb.tv/127.0.0.1#7913 -ipset=/.avdb.tv/gfwlist -server=/.forum.my903.com/127.0.0.1#7913 -ipset=/.forum.my903.com/gfwlist -server=/.crossvpn.net/127.0.0.1#7913 -ipset=/.crossvpn.net/gfwlist -server=/.epochtimestr.com/127.0.0.1#7913 -ipset=/.epochtimestr.com/gfwlist -server=/.2017.hk/127.0.0.1#7913 -ipset=/.2017.hk/gfwlist -server=/.hotvpn.com/127.0.0.1#7913 -ipset=/.hotvpn.com/gfwlist -server=/.icfcdn.com/127.0.0.1#7913 -ipset=/.icfcdn.com/gfwlist -server=/.shopping.com/127.0.0.1#7913 -ipset=/.shopping.com/gfwlist -server=/.mullvad.net/127.0.0.1#7913 -ipset=/.mullvad.net/gfwlist -server=/.chubold.com/127.0.0.1#7913 -ipset=/.chubold.com/gfwlist -server=/.cgdepot.org/127.0.0.1#7913 -ipset=/.cgdepot.org/gfwlist -server=/.desipro.de/127.0.0.1#7913 -ipset=/.desipro.de/gfwlist -server=/.pornerbros.com/127.0.0.1#7913 -ipset=/.pornerbros.com/gfwlist -server=/.kzeng.info/127.0.0.1#7913 -ipset=/.kzeng.info/gfwlist -server=/.paradisepoker.com/127.0.0.1#7913 -ipset=/.paradisepoker.com/gfwlist -server=/.penisbot.com/127.0.0.1#7913 -ipset=/.penisbot.com/gfwlist -server=/.freeilhamtohti.org/127.0.0.1#7913 -ipset=/.freeilhamtohti.org/gfwlist -server=/.break.com/127.0.0.1#7913 -ipset=/.break.com/gfwlist -server=/.twitlonger.com/127.0.0.1#7913 -ipset=/.twitlonger.com/gfwlist -server=/.bbkz.com/127.0.0.1#7913 -ipset=/.bbkz.com/gfwlist -server=/.tangben.com/127.0.0.1#7913 -ipset=/.tangben.com/gfwlist -server=/.inmediahk.net/127.0.0.1#7913 -ipset=/.inmediahk.net/gfwlist -server=/.cienen.com/127.0.0.1#7913 -ipset=/.cienen.com/gfwlist -server=/.cdninstagram.com/127.0.0.1#7913 -ipset=/.cdninstagram.com/gfwlist -server=/.0914.global.ssl.fastly.net/127.0.0.1#7913 -ipset=/.0914.global.ssl.fastly.net/gfwlist -server=/.vpn.cjb.net/127.0.0.1#7913 -ipset=/.vpn.cjb.net/gfwlist -server=/.feministteacher.com/127.0.0.1#7913 -ipset=/.feministteacher.com/gfwlist -server=/.tweettunnel.com/127.0.0.1#7913 -ipset=/.tweettunnel.com/gfwlist -server=/.sstmlt.net/127.0.0.1#7913 -ipset=/.sstmlt.net/gfwlist -server=/.iptvbin.com/127.0.0.1#7913 -ipset=/.iptvbin.com/gfwlist -server=/.raremovie.net/127.0.0.1#7913 -ipset=/.raremovie.net/gfwlist -server=/.funp.com/127.0.0.1#7913 -ipset=/.funp.com/gfwlist -server=/.xxxy.info/127.0.0.1#7913 -ipset=/.xxxy.info/gfwlist -server=/.ipfs.io/127.0.0.1#7913 -ipset=/.ipfs.io/gfwlist -server=/.w3schools.com/127.0.0.1#7913 -ipset=/.w3schools.com/gfwlist -server=/.berm.co.nz/127.0.0.1#7913 -ipset=/.berm.co.nz/gfwlist -server=/.flickr.com/127.0.0.1#7913 -ipset=/.flickr.com/gfwlist -server=/.duoweitimes.com/127.0.0.1#7913 -ipset=/.duoweitimes.com/gfwlist -server=/.fucd.com/127.0.0.1#7913 -ipset=/.fucd.com/gfwlist -server=/.qvodzy.org/127.0.0.1#7913 -ipset=/.qvodzy.org/gfwlist -server=/.hclips.com/127.0.0.1#7913 -ipset=/.hclips.com/gfwlist -server=/.porntvblog.com/127.0.0.1#7913 -ipset=/.porntvblog.com/gfwlist -server=/.freenewscn.com/127.0.0.1#7913 -ipset=/.freenewscn.com/gfwlist -server=/.tube8.com/127.0.0.1#7913 -ipset=/.tube8.com/gfwlist -server=/.catholic.org.tw/127.0.0.1#7913 -ipset=/.catholic.org.tw/gfwlist -server=/.wiki.phonegap.com/127.0.0.1#7913 -ipset=/.wiki.phonegap.com/gfwlist -server=/.socks-proxy.net/127.0.0.1#7913 -ipset=/.socks-proxy.net/gfwlist -server=/.tweetbackup.com/127.0.0.1#7913 -ipset=/.tweetbackup.com/gfwlist -server=/.hideme.nl/127.0.0.1#7913 -ipset=/.hideme.nl/gfwlist -server=/.tma.co.jp/127.0.0.1#7913 -ipset=/.tma.co.jp/gfwlist -server=/.to-porno.com/127.0.0.1#7913 -ipset=/.to-porno.com/gfwlist -server=/.shinychan.com/127.0.0.1#7913 -ipset=/.shinychan.com/gfwlist -server=/.delcamp.net/127.0.0.1#7913 -ipset=/.delcamp.net/gfwlist -server=/.sijihuisuo.club/127.0.0.1#7913 -ipset=/.sijihuisuo.club/gfwlist -server=/.shadowsocks.asia/127.0.0.1#7913 -ipset=/.shadowsocks.asia/gfwlist -server=/.dougscripts.com/127.0.0.1#7913 -ipset=/.dougscripts.com/gfwlist -server=/.chrlawyers.hk/127.0.0.1#7913 -ipset=/.chrlawyers.hk/gfwlist -server=/.sipml5.org/127.0.0.1#7913 -ipset=/.sipml5.org/gfwlist -server=/.istiqlalhewer.com/127.0.0.1#7913 -ipset=/.istiqlalhewer.com/gfwlist -server=/.chithu.org/127.0.0.1#7913 -ipset=/.chithu.org/gfwlist -server=/.s3.amazonaws.com/127.0.0.1#7913 -ipset=/.s3.amazonaws.com/gfwlist -server=/.gooddns.info/127.0.0.1#7913 -ipset=/.gooddns.info/gfwlist -server=/.tibetfund.org/127.0.0.1#7913 -ipset=/.tibetfund.org/gfwlist -server=/.kodingen.com/127.0.0.1#7913 -ipset=/.kodingen.com/gfwlist -server=/.mykomica.org/127.0.0.1#7913 -ipset=/.mykomica.org/gfwlist -server=/.forum.mymaji.com/127.0.0.1#7913 -ipset=/.forum.mymaji.com/gfwlist -server=/.biantailajiao.com/127.0.0.1#7913 -ipset=/.biantailajiao.com/gfwlist -server=/.hkhrm.org.hk/127.0.0.1#7913 -ipset=/.hkhrm.org.hk/gfwlist -server=/.playboy.com/127.0.0.1#7913 -ipset=/.playboy.com/gfwlist -server=/.uberproxy.net/127.0.0.1#7913 -ipset=/.uberproxy.net/gfwlist -server=/.difangwenge.org/127.0.0.1#7913 -ipset=/.difangwenge.org/gfwlist -server=/.panamapapers.sueddeutsche.de/127.0.0.1#7913 -ipset=/.panamapapers.sueddeutsche.de/gfwlist -server=/.tibettimes.net/127.0.0.1#7913 -ipset=/.tibettimes.net/gfwlist -server=/.google.fr/127.0.0.1#7913 -ipset=/.google.fr/gfwlist -server=/.vanemu.cn/127.0.0.1#7913 -ipset=/.vanemu.cn/gfwlist -server=/.greatfirewallofchina.net/127.0.0.1#7913 -ipset=/.greatfirewallofchina.net/gfwlist -server=/.gaopi.net/127.0.0.1#7913 -ipset=/.gaopi.net/gfwlist -server=/.newspeak.cc/127.0.0.1#7913 -ipset=/.newspeak.cc/gfwlist -server=/.ihakka.net/127.0.0.1#7913 -ipset=/.ihakka.net/gfwlist -server=/.chinacitynews.be/127.0.0.1#7913 -ipset=/.chinacitynews.be/gfwlist -server=/.xcafe.in/127.0.0.1#7913 -ipset=/.xcafe.in/gfwlist -server=/.kyohk.net/127.0.0.1#7913 -ipset=/.kyohk.net/gfwlist -server=/.watchinese.com/127.0.0.1#7913 -ipset=/.watchinese.com/gfwlist -server=/.limbopro.github.io/127.0.0.1#7913 -ipset=/.limbopro.github.io/gfwlist -server=/.pride.google/127.0.0.1#7913 -ipset=/.pride.google/gfwlist -server=/.archive.fo/127.0.0.1#7913 -ipset=/.archive.fo/gfwlist -server=/.rmjdw132.info/127.0.0.1#7913 -ipset=/.rmjdw132.info/gfwlist -server=/.fpmt.org/127.0.0.1#7913 -ipset=/.fpmt.org/gfwlist -server=/.google.fm/127.0.0.1#7913 -ipset=/.google.fm/gfwlist -server=/.provideocoalition.com/127.0.0.1#7913 -ipset=/.provideocoalition.com/gfwlist -server=/.dalailamatrust.org/127.0.0.1#7913 -ipset=/.dalailamatrust.org/gfwlist -server=/.mihr.com/127.0.0.1#7913 -ipset=/.mihr.com/gfwlist -server=/.galstars.net/127.0.0.1#7913 -ipset=/.galstars.net/gfwlist -server=/.gfsale.com/127.0.0.1#7913 -ipset=/.gfsale.com/gfwlist -server=/.unirule.cloud/127.0.0.1#7913 -ipset=/.unirule.cloud/gfwlist -server=/.wezhiyong.org/127.0.0.1#7913 -ipset=/.wezhiyong.org/gfwlist -server=/.change.org/127.0.0.1#7913 -ipset=/.change.org/gfwlist -server=/.top10vpn.com/127.0.0.1#7913 -ipset=/.top10vpn.com/gfwlist -server=/.freegao.com/127.0.0.1#7913 -ipset=/.freegao.com/gfwlist -server=/.officeoftibet.com/127.0.0.1#7913 -ipset=/.officeoftibet.com/gfwlist -server=/.globalmuseumoncommunism.org/127.0.0.1#7913 -ipset=/.globalmuseumoncommunism.org/gfwlist -server=/.zh.bitterwinter.org/127.0.0.1#7913 -ipset=/.zh.bitterwinter.org/gfwlist -server=/.liveleak.com/127.0.0.1#7913 -ipset=/.liveleak.com/gfwlist -server=/.zonghexinwen.com/127.0.0.1#7913 -ipset=/.zonghexinwen.com/gfwlist -server=/.tibet.com/127.0.0.1#7913 -ipset=/.tibet.com/gfwlist -server=/.antiwave.net/127.0.0.1#7913 -ipset=/.antiwave.net/gfwlist -server=/.tracfone.com/127.0.0.1#7913 -ipset=/.tracfone.com/gfwlist -server=/.ipalter.com/127.0.0.1#7913 -ipset=/.ipalter.com/gfwlist -server=/.sumrando.com/127.0.0.1#7913 -ipset=/.sumrando.com/gfwlist -server=/.chinayouth.org.hk/127.0.0.1#7913 -ipset=/.chinayouth.org.hk/gfwlist -server=/.nalandawest.org/127.0.0.1#7913 -ipset=/.nalandawest.org/gfwlist -server=/.gamer.com.tw/127.0.0.1#7913 -ipset=/.gamer.com.tw/gfwlist -server=/.acmedia365.com/127.0.0.1#7913 -ipset=/.acmedia365.com/gfwlist -server=/.mobatek.net/127.0.0.1#7913 -ipset=/.mobatek.net/gfwlist -server=/.aofriend.com/127.0.0.1#7913 -ipset=/.aofriend.com/gfwlist -server=/.google.ws/127.0.0.1#7913 -ipset=/.google.ws/gfwlist -server=/.lobsangwangyal.com/127.0.0.1#7913 -ipset=/.lobsangwangyal.com/gfwlist -server=/.raindrop.io/127.0.0.1#7913 -ipset=/.raindrop.io/gfwlist -server=/.cling.omy.sg/127.0.0.1#7913 -ipset=/.cling.omy.sg/gfwlist -server=/.alasbarricadas.org/127.0.0.1#7913 -ipset=/.alasbarricadas.org/gfwlist -server=/.ufreevpn.com/127.0.0.1#7913 -ipset=/.ufreevpn.com/gfwlist -server=/.e-gold.com/127.0.0.1#7913 -ipset=/.e-gold.com/gfwlist -server=/.ocry.com/127.0.0.1#7913 -ipset=/.ocry.com/gfwlist -server=/.e-hentaidb.com/127.0.0.1#7913 -ipset=/.e-hentaidb.com/gfwlist -server=/.lzmtnews.org/127.0.0.1#7913 -ipset=/.lzmtnews.org/gfwlist -server=/.sadpanda.us/127.0.0.1#7913 -ipset=/.sadpanda.us/gfwlist -server=/.falundafaindia.org/127.0.0.1#7913 -ipset=/.falundafaindia.org/gfwlist -server=/.cattt.com/127.0.0.1#7913 -ipset=/.cattt.com/gfwlist -server=/.sockslist.net/127.0.0.1#7913 -ipset=/.sockslist.net/gfwlist -server=/.fireofliberty.org/127.0.0.1#7913 -ipset=/.fireofliberty.org/gfwlist -server=/.g-queen.com/127.0.0.1#7913 -ipset=/.g-queen.com/gfwlist -server=/.youtubegaming.com/127.0.0.1#7913 -ipset=/.youtubegaming.com/gfwlist -server=/.mk5000.com/127.0.0.1#7913 -ipset=/.mk5000.com/gfwlist -server=/.sis.xxx/127.0.0.1#7913 -ipset=/.sis.xxx/gfwlist -server=/.hrweb.org/127.0.0.1#7913 -ipset=/.hrweb.org/gfwlist -server=/.bbsmo.com/127.0.0.1#7913 -ipset=/.bbsmo.com/gfwlist -server=/.www.metro.taipei/127.0.0.1#7913 -ipset=/.www.metro.taipei/gfwlist -server=/.epochtimes.co.kr/127.0.0.1#7913 -ipset=/.epochtimes.co.kr/gfwlist -server=/.christiantimes.org.hk/127.0.0.1#7913 -ipset=/.christiantimes.org.hk/gfwlist -server=/.maizhong.org/127.0.0.1#7913 -ipset=/.maizhong.org/gfwlist -server=/.bloodshed.net/127.0.0.1#7913 -ipset=/.bloodshed.net/gfwlist -server=/.ifreewares.com/127.0.0.1#7913 -ipset=/.ifreewares.com/gfwlist -server=/.kechara.com/127.0.0.1#7913 -ipset=/.kechara.com/gfwlist -server=/.dynssl.com/127.0.0.1#7913 -ipset=/.dynssl.com/gfwlist -server=/.spotify.com/127.0.0.1#7913 -ipset=/.spotify.com/gfwlist -server=/.pinterest.nl/127.0.0.1#7913 -ipset=/.pinterest.nl/gfwlist -server=/.shadow.ma/127.0.0.1#7913 -ipset=/.shadow.ma/gfwlist -server=/.myfreecams.com/127.0.0.1#7913 -ipset=/.myfreecams.com/gfwlist -server=/.hk.yahoo.com/127.0.0.1#7913 -ipset=/.hk.yahoo.com/gfwlist -server=/.tibethouse.org/127.0.0.1#7913 -ipset=/.tibethouse.org/gfwlist -server=/.luke54.com/127.0.0.1#7913 -ipset=/.luke54.com/gfwlist -server=/.stboy.net/127.0.0.1#7913 -ipset=/.stboy.net/gfwlist -server=/.avcity.tv/127.0.0.1#7913 -ipset=/.avcity.tv/gfwlist -server=/.chengmingmag.com/127.0.0.1#7913 -ipset=/.chengmingmag.com/gfwlist -server=/.bbtoystore.com/127.0.0.1#7913 -ipset=/.bbtoystore.com/gfwlist -server=/.beeg.com/127.0.0.1#7913 -ipset=/.beeg.com/gfwlist -server=/.galaxymacau.com/127.0.0.1#7913 -ipset=/.galaxymacau.com/gfwlist -server=/.cn.shafaqna.com/127.0.0.1#7913 -ipset=/.cn.shafaqna.com/gfwlist -server=/.blogs.yahoo.co.jp/127.0.0.1#7913 -ipset=/.blogs.yahoo.co.jp/gfwlist -server=/.hugoroy.eu/127.0.0.1#7913 -ipset=/.hugoroy.eu/gfwlist -server=/.privatepaste.com/127.0.0.1#7913 -ipset=/.privatepaste.com/gfwlist -server=/.cdcparty.com/127.0.0.1#7913 -ipset=/.cdcparty.com/gfwlist -server=/.freewallpaper4.me/127.0.0.1#7913 -ipset=/.freewallpaper4.me/gfwlist -server=/.videodetective.com/127.0.0.1#7913 -ipset=/.videodetective.com/gfwlist -server=/.zgzcjj.net/127.0.0.1#7913 -ipset=/.zgzcjj.net/gfwlist -server=/.1949er.org/127.0.0.1#7913 -ipset=/.1949er.org/gfwlist -server=/.vft.com.tw/127.0.0.1#7913 -ipset=/.vft.com.tw/gfwlist -server=/.hka8964.wordpress.com/127.0.0.1#7913 -ipset=/.hka8964.wordpress.com/gfwlist -server=/.june4commemoration.org/127.0.0.1#7913 -ipset=/.june4commemoration.org/gfwlist -server=/.ytimg.com/127.0.0.1#7913 -ipset=/.ytimg.com/gfwlist -server=/.hk01.com/127.0.0.1#7913 -ipset=/.hk01.com/gfwlist -server=/.hulkshare.com/127.0.0.1#7913 -ipset=/.hulkshare.com/gfwlist -server=/.popyard.com/127.0.0.1#7913 -ipset=/.popyard.com/gfwlist -server=/.xys.org/127.0.0.1#7913 -ipset=/.xys.org/gfwlist -server=/.233abc.com/127.0.0.1#7913 -ipset=/.233abc.com/gfwlist -server=/.twstar.net/127.0.0.1#7913 -ipset=/.twstar.net/gfwlist -server=/.fzlm.com/127.0.0.1#7913 -ipset=/.fzlm.com/gfwlist -server=/.userapi.nytlog.com/127.0.0.1#7913 -ipset=/.userapi.nytlog.com/gfwlist -server=/.x24hr.com/127.0.0.1#7913 -ipset=/.x24hr.com/gfwlist -server=/.jinbushe.org/127.0.0.1#7913 -ipset=/.jinbushe.org/gfwlist -server=/.liuxiaotong.com/127.0.0.1#7913 -ipset=/.liuxiaotong.com/gfwlist -server=/.ai.binwang.me/127.0.0.1#7913 -ipset=/.ai.binwang.me/gfwlist -server=/.mimivv.com/127.0.0.1#7913 -ipset=/.mimivv.com/gfwlist -server=/.tarr.uspto.gov/127.0.0.1#7913 -ipset=/.tarr.uspto.gov/gfwlist -server=/.yes.xxx/127.0.0.1#7913 -ipset=/.yes.xxx/gfwlist -server=/.pinterest.se/127.0.0.1#7913 -ipset=/.pinterest.se/gfwlist -server=/.go-pki.com/127.0.0.1#7913 -ipset=/.go-pki.com/gfwlist -server=/.gclooney.com/127.0.0.1#7913 -ipset=/.gclooney.com/gfwlist -server=/.junauza.com/127.0.0.1#7913 -ipset=/.junauza.com/gfwlist -server=/.jfqu36.club/127.0.0.1#7913 -ipset=/.jfqu36.club/gfwlist -server=/.baramangaonline.com/127.0.0.1#7913 -ipset=/.baramangaonline.com/gfwlist -server=/.5i01.com/127.0.0.1#7913 -ipset=/.5i01.com/gfwlist -server=/.kobobooks.com/127.0.0.1#7913 -ipset=/.kobobooks.com/gfwlist -server=/.monitorchina.org/127.0.0.1#7913 -ipset=/.monitorchina.org/gfwlist -server=/.tubewolf.com/127.0.0.1#7913 -ipset=/.tubewolf.com/gfwlist -server=/.whodns.xyz/127.0.0.1#7913 -ipset=/.whodns.xyz/gfwlist -server=/.casadeltibetbcn.org/127.0.0.1#7913 -ipset=/.casadeltibetbcn.org/gfwlist -server=/.googleblog.com/127.0.0.1#7913 -ipset=/.googleblog.com/gfwlist -server=/.iphonehacks.com/127.0.0.1#7913 -ipset=/.iphonehacks.com/gfwlist -server=/.october-review.org/127.0.0.1#7913 -ipset=/.october-review.org/gfwlist -server=/.janwongphoto.com/127.0.0.1#7913 -ipset=/.janwongphoto.com/gfwlist -server=/.blog.jp/127.0.0.1#7913 -ipset=/.blog.jp/gfwlist -server=/.unblock.cn.com/127.0.0.1#7913 -ipset=/.unblock.cn.com/gfwlist -server=/.allgirlmassage.com/127.0.0.1#7913 -ipset=/.allgirlmassage.com/gfwlist -server=/.tapatalk.com/127.0.0.1#7913 -ipset=/.tapatalk.com/gfwlist -server=/.nicovideo.jp/127.0.0.1#7913 -ipset=/.nicovideo.jp/gfwlist -server=/.sis001.us/127.0.0.1#7913 -ipset=/.sis001.us/gfwlist -server=/.proxypy.net/127.0.0.1#7913 -ipset=/.proxypy.net/gfwlist -server=/.clipfish.de/127.0.0.1#7913 -ipset=/.clipfish.de/gfwlist -server=/.sex3.com/127.0.0.1#7913 -ipset=/.sex3.com/gfwlist -server=/.tono-oka.jp/127.0.0.1#7913 -ipset=/.tono-oka.jp/gfwlist -server=/.soundofhope.kr/127.0.0.1#7913 -ipset=/.soundofhope.kr/gfwlist -server=/.tafm.org/127.0.0.1#7913 -ipset=/.tafm.org/gfwlist -server=/.rule34.xxx/127.0.0.1#7913 -ipset=/.rule34.xxx/gfwlist -server=/.westpoint.edu/127.0.0.1#7913 -ipset=/.westpoint.edu/gfwlist -server=/.tngrnow.com/127.0.0.1#7913 -ipset=/.tngrnow.com/gfwlist -server=/.v2fly.org/127.0.0.1#7913 -ipset=/.v2fly.org/gfwlist -server=/.carfax.com/127.0.0.1#7913 -ipset=/.carfax.com/gfwlist -server=/.udn.com/127.0.0.1#7913 -ipset=/.udn.com/gfwlist -server=/.zinio.com/127.0.0.1#7913 -ipset=/.zinio.com/gfwlist -server=/.chinagfw.org/127.0.0.1#7913 -ipset=/.chinagfw.org/gfwlist -server=/.institut-tibetain.org/127.0.0.1#7913 -ipset=/.institut-tibetain.org/gfwlist -server=/.lrfz.com/127.0.0.1#7913 -ipset=/.lrfz.com/gfwlist -server=/.aojiao.org/127.0.0.1#7913 -ipset=/.aojiao.org/gfwlist -server=/.rarbgprx.org/127.0.0.1#7913 -ipset=/.rarbgprx.org/gfwlist -server=/.ftchinese.com/127.0.0.1#7913 -ipset=/.ftchinese.com/gfwlist -server=/.etadult.com/127.0.0.1#7913 -ipset=/.etadult.com/gfwlist -server=/.atchinese.com/127.0.0.1#7913 -ipset=/.atchinese.com/gfwlist -server=/.kineox.free.fr/127.0.0.1#7913 -ipset=/.kineox.free.fr/gfwlist -server=/.tibetlibre.free.fr/127.0.0.1#7913 -ipset=/.tibetlibre.free.fr/gfwlist -server=/.tianlawoffice.com/127.0.0.1#7913 -ipset=/.tianlawoffice.com/gfwlist -server=/.dalailamavisit.org.nz/127.0.0.1#7913 -ipset=/.dalailamavisit.org.nz/gfwlist -server=/.tn3.shemalez.com/127.0.0.1#7913 -ipset=/.tn3.shemalez.com/gfwlist -server=/.unblocker.yt/127.0.0.1#7913 -ipset=/.unblocker.yt/gfwlist -server=/.developers.box.net/127.0.0.1#7913 -ipset=/.developers.box.net/gfwlist -server=/.juliereyc.com/127.0.0.1#7913 -ipset=/.juliereyc.com/gfwlist -server=/.scramble.io/127.0.0.1#7913 -ipset=/.scramble.io/gfwlist -server=/.hutong9.net/127.0.0.1#7913 -ipset=/.hutong9.net/gfwlist -server=/.w.idaiwan.com/127.0.0.1#7913 -ipset=/.w.idaiwan.com/gfwlist -server=/.mattwilcox.net/127.0.0.1#7913 -ipset=/.mattwilcox.net/gfwlist -server=/.joinmastodon.org/127.0.0.1#7913 -ipset=/.joinmastodon.org/gfwlist -server=/.lhasocialwork.org/127.0.0.1#7913 -ipset=/.lhasocialwork.org/gfwlist -server=/.avoision.com/127.0.0.1#7913 -ipset=/.avoision.com/gfwlist -server=/.linuxtoy.org/127.0.0.1#7913 -ipset=/.linuxtoy.org/gfwlist -server=/.mist.vip/127.0.0.1#7913 -ipset=/.mist.vip/gfwlist -server=/.freetcp.com/127.0.0.1#7913 -ipset=/.freetcp.com/gfwlist -server=/.got-game.org/127.0.0.1#7913 -ipset=/.got-game.org/gfwlist -server=/.popyard.org/127.0.0.1#7913 -ipset=/.popyard.org/gfwlist -server=/.falungong.club/127.0.0.1#7913 -ipset=/.falungong.club/gfwlist -server=/.web2project.net/127.0.0.1#7913 -ipset=/.web2project.net/gfwlist -server=/.cdn1.lp.saboom.com/127.0.0.1#7913 -ipset=/.cdn1.lp.saboom.com/gfwlist -server=/.snowlionpub.com/127.0.0.1#7913 -ipset=/.snowlionpub.com/gfwlist -server=/.setn.com/127.0.0.1#7913 -ipset=/.setn.com/gfwlist -server=/.areca-backup.org/127.0.0.1#7913 -ipset=/.areca-backup.org/gfwlist -server=/.islamicpluralism.org/127.0.0.1#7913 -ipset=/.islamicpluralism.org/gfwlist -server=/.hkej.com/127.0.0.1#7913 -ipset=/.hkej.com/gfwlist -server=/.dlyoutube.com/127.0.0.1#7913 -ipset=/.dlyoutube.com/gfwlist -server=/.rsf.org/127.0.0.1#7913 -ipset=/.rsf.org/gfwlist -server=/.yakbutterblues.com/127.0.0.1#7913 -ipset=/.yakbutterblues.com/gfwlist -server=/.latelinenews.com/127.0.0.1#7913 -ipset=/.latelinenews.com/gfwlist -server=/.tiny.cc/127.0.0.1#7913 -ipset=/.tiny.cc/gfwlist -server=/.rxhj.net/127.0.0.1#7913 -ipset=/.rxhj.net/gfwlist -server=/.google.tt/127.0.0.1#7913 -ipset=/.google.tt/gfwlist -server=/.motiyun.com/127.0.0.1#7913 -ipset=/.motiyun.com/gfwlist -server=/.hellouk.org/127.0.0.1#7913 -ipset=/.hellouk.org/gfwlist -server=/.xlfmtalk.com/127.0.0.1#7913 -ipset=/.xlfmtalk.com/gfwlist -server=/.tw.myblog.yahoo.com/127.0.0.1#7913 -ipset=/.tw.myblog.yahoo.com/gfwlist -server=/.recordhistory.org/127.0.0.1#7913 -ipset=/.recordhistory.org/gfwlist -server=/.ozchinese.com/127.0.0.1#7913 -ipset=/.ozchinese.com/gfwlist -server=/.centauro.com.br/127.0.0.1#7913 -ipset=/.centauro.com.br/gfwlist -server=/.exmo.com/127.0.0.1#7913 -ipset=/.exmo.com/gfwlist -server=/.dyndns.org/127.0.0.1#7913 -ipset=/.dyndns.org/gfwlist -server=/.ipjetable.net/127.0.0.1#7913 -ipset=/.ipjetable.net/gfwlist -server=/.collateralmurder.org/127.0.0.1#7913 -ipset=/.collateralmurder.org/gfwlist -server=/.thaicn.com/127.0.0.1#7913 -ipset=/.thaicn.com/gfwlist -server=/.tokyo-hot.com/127.0.0.1#7913 -ipset=/.tokyo-hot.com/gfwlist -server=/.wufi.org.tw/127.0.0.1#7913 -ipset=/.wufi.org.tw/gfwlist -server=/.cbc.ca/127.0.0.1#7913 -ipset=/.cbc.ca/gfwlist -server=/.archives.gov/127.0.0.1#7913 -ipset=/.archives.gov/gfwlist -server=/.guo.media/127.0.0.1#7913 -ipset=/.guo.media/gfwlist -server=/.sexhuang.com/127.0.0.1#7913 -ipset=/.sexhuang.com/gfwlist -server=/.euronews.com/127.0.0.1#7913 -ipset=/.euronews.com/gfwlist -server=/.voa-11.akacast.akamaistream.net/127.0.0.1#7913 -ipset=/.voa-11.akacast.akamaistream.net/gfwlist -server=/.warbler.iconfactory.net/127.0.0.1#7913 -ipset=/.warbler.iconfactory.net/gfwlist -server=/.epochtimes.se/127.0.0.1#7913 -ipset=/.epochtimes.se/gfwlist -server=/.fiddle.jshell.net/127.0.0.1#7913 -ipset=/.fiddle.jshell.net/gfwlist -server=/.magic-net.info/127.0.0.1#7913 -ipset=/.magic-net.info/gfwlist -server=/.renyurenquan.org/127.0.0.1#7913 -ipset=/.renyurenquan.org/gfwlist -server=/.asdfg.jp/127.0.0.1#7913 -ipset=/.asdfg.jp/gfwlist -server=/.lightnovel.cn/127.0.0.1#7913 -ipset=/.lightnovel.cn/gfwlist -server=/.broadpressinc.com/127.0.0.1#7913 -ipset=/.broadpressinc.com/gfwlist -server=/.anti1984.com/127.0.0.1#7913 -ipset=/.anti1984.com/gfwlist -server=/.etvonline.hk/127.0.0.1#7913 -ipset=/.etvonline.hk/gfwlist -server=/.chineseupress.com/127.0.0.1#7913 -ipset=/.chineseupress.com/gfwlist -server=/.freedomhouse.org/127.0.0.1#7913 -ipset=/.freedomhouse.org/gfwlist -server=/.bitvise.com/127.0.0.1#7913 -ipset=/.bitvise.com/gfwlist -server=/.switchvpn.net/127.0.0.1#7913 -ipset=/.switchvpn.net/gfwlist -server=/.www.s4miniarchive.com/127.0.0.1#7913 -ipset=/.www.s4miniarchive.com/gfwlist -server=/.admin.recaptcha.net/127.0.0.1#7913 -ipset=/.admin.recaptcha.net/gfwlist -server=/.twittertim.es/127.0.0.1#7913 -ipset=/.twittertim.es/gfwlist -server=/.persecutionblog.com/127.0.0.1#7913 -ipset=/.persecutionblog.com/gfwlist -server=/.wexiaobo.org/127.0.0.1#7913 -ipset=/.wexiaobo.org/gfwlist -server=/.mybet.com/127.0.0.1#7913 -ipset=/.mybet.com/gfwlist -server=/.mail-archive.com/127.0.0.1#7913 -ipset=/.mail-archive.com/gfwlist -server=/.hotpot.hk/127.0.0.1#7913 -ipset=/.hotpot.hk/gfwlist -server=/.jizzthis.com/127.0.0.1#7913 -ipset=/.jizzthis.com/gfwlist -server=/.cloakpoint.com/127.0.0.1#7913 -ipset=/.cloakpoint.com/gfwlist -server=/.incapdns.net/127.0.0.1#7913 -ipset=/.incapdns.net/gfwlist -server=/.tbsec.org/127.0.0.1#7913 -ipset=/.tbsec.org/gfwlist -server=/.releaseinternational.org/127.0.0.1#7913 -ipset=/.releaseinternational.org/gfwlist -server=/.homeperversion.com/127.0.0.1#7913 -ipset=/.homeperversion.com/gfwlist -server=/.compileheart.com/127.0.0.1#7913 -ipset=/.compileheart.com/gfwlist -server=/.matome-plus.com/127.0.0.1#7913 -ipset=/.matome-plus.com/gfwlist -server=/.inkui.com/127.0.0.1#7913 -ipset=/.inkui.com/gfwlist -server=/.timsah.com/127.0.0.1#7913 -ipset=/.timsah.com/gfwlist -server=/.yayabay.com/127.0.0.1#7913 -ipset=/.yayabay.com/gfwlist -server=/.android-x86.org/127.0.0.1#7913 -ipset=/.android-x86.org/gfwlist -server=/.myddns.com/127.0.0.1#7913 -ipset=/.myddns.com/gfwlist -server=/.dl-laby.jp/127.0.0.1#7913 -ipset=/.dl-laby.jp/gfwlist -server=/.ncn.org/127.0.0.1#7913 -ipset=/.ncn.org/gfwlist -server=/.voy.com/127.0.0.1#7913 -ipset=/.voy.com/gfwlist -server=/.fileserve.com/127.0.0.1#7913 -ipset=/.fileserve.com/gfwlist -server=/.echofon.com/127.0.0.1#7913 -ipset=/.echofon.com/gfwlist -server=/.mediachinese.com/127.0.0.1#7913 -ipset=/.mediachinese.com/gfwlist -server=/.vraiesagesse.net/127.0.0.1#7913 -ipset=/.vraiesagesse.net/gfwlist -server=/.googlebot.com/127.0.0.1#7913 -ipset=/.googlebot.com/gfwlist -server=/.bestpornstardb.com/127.0.0.1#7913 -ipset=/.bestpornstardb.com/gfwlist -server=/.douhokanko.net/127.0.0.1#7913 -ipset=/.douhokanko.net/gfwlist -server=/.googleinsidesearch.com/127.0.0.1#7913 -ipset=/.googleinsidesearch.com/gfwlist -server=/.icams.com/127.0.0.1#7913 -ipset=/.icams.com/gfwlist -server=/.newyorktimes.com/127.0.0.1#7913 -ipset=/.newyorktimes.com/gfwlist -server=/.meripet.com/127.0.0.1#7913 -ipset=/.meripet.com/gfwlist -server=/.freealim.com/127.0.0.1#7913 -ipset=/.freealim.com/gfwlist -server=/.memehk.com/127.0.0.1#7913 -ipset=/.memehk.com/gfwlist -server=/.xcritic.com/127.0.0.1#7913 -ipset=/.xcritic.com/gfwlist -server=/.twitpic.com/127.0.0.1#7913 -ipset=/.twitpic.com/gfwlist -server=/.google.vu/127.0.0.1#7913 -ipset=/.google.vu/gfwlist -server=/.chromercise.com/127.0.0.1#7913 -ipset=/.chromercise.com/gfwlist -server=/.tcewf.org/127.0.0.1#7913 -ipset=/.tcewf.org/gfwlist -server=/.dolc.de/127.0.0.1#7913 -ipset=/.dolc.de/gfwlist -server=/.pekingduck.org/127.0.0.1#7913 -ipset=/.pekingduck.org/gfwlist -server=/.jamyangnorbu.com/127.0.0.1#7913 -ipset=/.jamyangnorbu.com/gfwlist -server=/.news.nationalgeographic.com/127.0.0.1#7913 -ipset=/.news.nationalgeographic.com/gfwlist -server=/.onthehunt.com/127.0.0.1#7913 -ipset=/.onthehunt.com/gfwlist -server=/.chinese-hermit.net/127.0.0.1#7913 -ipset=/.chinese-hermit.net/gfwlist -server=/.azurewebsites.net/127.0.0.1#7913 -ipset=/.azurewebsites.net/gfwlist -server=/.popvote.hk/127.0.0.1#7913 -ipset=/.popvote.hk/gfwlist -server=/.somee.com/127.0.0.1#7913 -ipset=/.somee.com/gfwlist -server=/.play-asia.com/127.0.0.1#7913 -ipset=/.play-asia.com/gfwlist -server=/.impp.mn/127.0.0.1#7913 -ipset=/.impp.mn/gfwlist -server=/.www.gmiddle.com/127.0.0.1#7913 -ipset=/.www.gmiddle.com/gfwlist -server=/.ssl443.org/127.0.0.1#7913 -ipset=/.ssl443.org/gfwlist -server=/.terminus2049.github.io/127.0.0.1#7913 -ipset=/.terminus2049.github.io/gfwlist -server=/.gcc.org.hk/127.0.0.1#7913 -ipset=/.gcc.org.hk/gfwlist -server=/.free.fr/127.0.0.1#7913 -ipset=/.free.fr/gfwlist -server=/.stupidvideos.com/127.0.0.1#7913 -ipset=/.stupidvideos.com/gfwlist -server=/.twaud.io/127.0.0.1#7913 -ipset=/.twaud.io/gfwlist -server=/.twimbow.com/127.0.0.1#7913 -ipset=/.twimbow.com/gfwlist -server=/.wsj.com/127.0.0.1#7913 -ipset=/.wsj.com/gfwlist -server=/.philly.com/127.0.0.1#7913 -ipset=/.philly.com/gfwlist -server=/.cdef.org/127.0.0.1#7913 -ipset=/.cdef.org/gfwlist -server=/.geek-art.net/127.0.0.1#7913 -ipset=/.geek-art.net/gfwlist -server=/.facebook.se/127.0.0.1#7913 -ipset=/.facebook.se/gfwlist -server=/.hk.search.yahoo.com/127.0.0.1#7913 -ipset=/.hk.search.yahoo.com/gfwlist -server=/.flickriver.com/127.0.0.1#7913 -ipset=/.flickriver.com/gfwlist -server=/.chinafreepress.org/127.0.0.1#7913 -ipset=/.chinafreepress.org/gfwlist -server=/.blockcn.com/127.0.0.1#7913 -ipset=/.blockcn.com/gfwlist -server=/.36rain.com/127.0.0.1#7913 -ipset=/.36rain.com/gfwlist -server=/.wenzhao.ca/127.0.0.1#7913 -ipset=/.wenzhao.ca/gfwlist -server=/.digitalnomadsproject.org/127.0.0.1#7913 -ipset=/.digitalnomadsproject.org/gfwlist -server=/.huyandex.com/127.0.0.1#7913 -ipset=/.huyandex.com/gfwlist -server=/.quora.com/127.0.0.1#7913 -ipset=/.quora.com/gfwlist -server=/.easternlightning.org/127.0.0.1#7913 -ipset=/.easternlightning.org/gfwlist -server=/.gospelherald.com/127.0.0.1#7913 -ipset=/.gospelherald.com/gfwlist -server=/.3proxy.ru/127.0.0.1#7913 -ipset=/.3proxy.ru/gfwlist -server=/.hotfrog.com.tw/127.0.0.1#7913 -ipset=/.hotfrog.com.tw/gfwlist -server=/.pcanywhere.net/127.0.0.1#7913 -ipset=/.pcanywhere.net/gfwlist -server=/.redhotlabs.com/127.0.0.1#7913 -ipset=/.redhotlabs.com/gfwlist -server=/.falsefire.com/127.0.0.1#7913 -ipset=/.falsefire.com/gfwlist -server=/.id.heroku.com/127.0.0.1#7913 -ipset=/.id.heroku.com/gfwlist -server=/.tngrnow.net/127.0.0.1#7913 -ipset=/.tngrnow.net/gfwlist -server=/.tnp.org/127.0.0.1#7913 -ipset=/.tnp.org/gfwlist -server=/.bigfools.com/127.0.0.1#7913 -ipset=/.bigfools.com/gfwlist -server=/.wow-life.net/127.0.0.1#7913 -ipset=/.wow-life.net/gfwlist -server=/.fdc89.jp/127.0.0.1#7913 -ipset=/.fdc89.jp/gfwlist -server=/.sftuk.org/127.0.0.1#7913 -ipset=/.sftuk.org/gfwlist -server=/.disconnect.me/127.0.0.1#7913 -ipset=/.disconnect.me/gfwlist -server=/.simpleproductivityblog.com/127.0.0.1#7913 -ipset=/.simpleproductivityblog.com/gfwlist -server=/.flgg.us/127.0.0.1#7913 -ipset=/.flgg.us/gfwlist -server=/.bfsh.hk/127.0.0.1#7913 -ipset=/.bfsh.hk/gfwlist -server=/.dupola.com/127.0.0.1#7913 -ipset=/.dupola.com/gfwlist -server=/.hkacg.net/127.0.0.1#7913 -ipset=/.hkacg.net/gfwlist -server=/.sylfoundation.org/127.0.0.1#7913 -ipset=/.sylfoundation.org/gfwlist -server=/.mahabodhi.org/127.0.0.1#7913 -ipset=/.mahabodhi.org/gfwlist -server=/.uygur.org/127.0.0.1#7913 -ipset=/.uygur.org/gfwlist -server=/.bettween.com/127.0.0.1#7913 -ipset=/.bettween.com/gfwlist -server=/.hottg.com/127.0.0.1#7913 -ipset=/.hottg.com/gfwlist -server=/.lanterncn.cn/127.0.0.1#7913 -ipset=/.lanterncn.cn/gfwlist -server=/.easypic.com/127.0.0.1#7913 -ipset=/.easypic.com/gfwlist -server=/.casinoking.com/127.0.0.1#7913 -ipset=/.casinoking.com/gfwlist -server=/.gokbayrak.com/127.0.0.1#7913 -ipset=/.gokbayrak.com/gfwlist -server=/.omnitalk.com/127.0.0.1#7913 -ipset=/.omnitalk.com/gfwlist -server=/.falunasia.info/127.0.0.1#7913 -ipset=/.falunasia.info/gfwlist -server=/.gcmasia.com/127.0.0.1#7913 -ipset=/.gcmasia.com/gfwlist -server=/.ddns.mobi/127.0.0.1#7913 -ipset=/.ddns.mobi/gfwlist -server=/.search.yahoo.co.jp/127.0.0.1#7913 -ipset=/.search.yahoo.co.jp/gfwlist -server=/.dadi360.com/127.0.0.1#7913 -ipset=/.dadi360.com/gfwlist -server=/.korenan2.com/127.0.0.1#7913 -ipset=/.korenan2.com/gfwlist -server=/.akow.org/127.0.0.1#7913 -ipset=/.akow.org/gfwlist -server=/.t-g.com/127.0.0.1#7913 -ipset=/.t-g.com/gfwlist -server=/.dabr.mobi/127.0.0.1#7913 -ipset=/.dabr.mobi/gfwlist -server=/.panluan.net/127.0.0.1#7913 -ipset=/.panluan.net/gfwlist -server=/.himalayanglacier.com/127.0.0.1#7913 -ipset=/.himalayanglacier.com/gfwlist -server=/.steganos.net/127.0.0.1#7913 -ipset=/.steganos.net/gfwlist -server=/.feitian-california.org/127.0.0.1#7913 -ipset=/.feitian-california.org/gfwlist -server=/.streamingthe.net/127.0.0.1#7913 -ipset=/.streamingthe.net/gfwlist -server=/.castbox.fm/127.0.0.1#7913 -ipset=/.castbox.fm/gfwlist -server=/.xiaochuncnjp.com/127.0.0.1#7913 -ipset=/.xiaochuncnjp.com/gfwlist -server=/.saintyculture.com/127.0.0.1#7913 -ipset=/.saintyculture.com/gfwlist -server=/.maruta.be/127.0.0.1#7913 -ipset=/.maruta.be/gfwlist -server=/.wuyanblog.com/127.0.0.1#7913 -ipset=/.wuyanblog.com/gfwlist -server=/.cointiger.com/127.0.0.1#7913 -ipset=/.cointiger.com/gfwlist -server=/.dogfartnetwork.com/127.0.0.1#7913 -ipset=/.dogfartnetwork.com/gfwlist -server=/.h1n1china.org/127.0.0.1#7913 -ipset=/.h1n1china.org/gfwlist -server=/.naitik.net/127.0.0.1#7913 -ipset=/.naitik.net/gfwlist -server=/.alldrawnsex.com/127.0.0.1#7913 -ipset=/.alldrawnsex.com/gfwlist -server=/.breaking911.com/127.0.0.1#7913 -ipset=/.breaking911.com/gfwlist -server=/.empfil.com/127.0.0.1#7913 -ipset=/.empfil.com/gfwlist -server=/.crocotube.com/127.0.0.1#7913 -ipset=/.crocotube.com/gfwlist -server=/.nordstrommedia.com/127.0.0.1#7913 -ipset=/.nordstrommedia.com/gfwlist -server=/.emuparadise.me/127.0.0.1#7913 -ipset=/.emuparadise.me/gfwlist -server=/.bt95.com/127.0.0.1#7913 -ipset=/.bt95.com/gfwlist -server=/.hentaitube.tv/127.0.0.1#7913 -ipset=/.hentaitube.tv/gfwlist -server=/.axureformac.com/127.0.0.1#7913 -ipset=/.axureformac.com/gfwlist -server=/.port25.biz/127.0.0.1#7913 -ipset=/.port25.biz/gfwlist -server=/.sex.com/127.0.0.1#7913 -ipset=/.sex.com/gfwlist -server=/.huhaitai.com/127.0.0.1#7913 -ipset=/.huhaitai.com/gfwlist -server=/.5aimiku.com/127.0.0.1#7913 -ipset=/.5aimiku.com/gfwlist -server=/.oex.com/127.0.0.1#7913 -ipset=/.oex.com/gfwlist -server=/.flipkart.com/127.0.0.1#7913 -ipset=/.flipkart.com/gfwlist -server=/.d3rhr7kgmtrq1v.cloudfront.net/127.0.0.1#7913 -ipset=/.d3rhr7kgmtrq1v.cloudfront.net/gfwlist -server=/.kex.com/127.0.0.1#7913 -ipset=/.kex.com/gfwlist -server=/.google.de/127.0.0.1#7913 -ipset=/.google.de/gfwlist -server=/.environment.google/127.0.0.1#7913 -ipset=/.environment.google/gfwlist -server=/.idreamx.com/127.0.0.1#7913 -ipset=/.idreamx.com/gfwlist -server=/.research.jmsc.hku.hk/127.0.0.1#7913 -ipset=/.research.jmsc.hku.hk/gfwlist -server=/.aex.com/127.0.0.1#7913 -ipset=/.aex.com/gfwlist -server=/.bbs.qmzdd.com/127.0.0.1#7913 -ipset=/.bbs.qmzdd.com/gfwlist -server=/.binance.com/127.0.0.1#7913 -ipset=/.binance.com/gfwlist -server=/.chinaeweekly.com/127.0.0.1#7913 -ipset=/.chinaeweekly.com/gfwlist -server=/.pentoy.hk/127.0.0.1#7913 -ipset=/.pentoy.hk/gfwlist -server=/.guangming.com.my/127.0.0.1#7913 -ipset=/.guangming.com.my/gfwlist -server=/.ns01.us/127.0.0.1#7913 -ipset=/.ns01.us/gfwlist -server=/.hecaitou.net/127.0.0.1#7913 -ipset=/.hecaitou.net/gfwlist -server=/.eyny.com/127.0.0.1#7913 -ipset=/.eyny.com/gfwlist -server=/.eastturkistangovernmentinexile.us/127.0.0.1#7913 -ipset=/.eastturkistangovernmentinexile.us/gfwlist -server=/.tew.org/127.0.0.1#7913 -ipset=/.tew.org/gfwlist -server=/.feer.com/127.0.0.1#7913 -ipset=/.feer.com/gfwlist -server=/.feitianacademy.org/127.0.0.1#7913 -ipset=/.feitianacademy.org/gfwlist -server=/.cnproxy.com/127.0.0.1#7913 -ipset=/.cnproxy.com/gfwlist -server=/.unitedsocialpress.com/127.0.0.1#7913 -ipset=/.unitedsocialpress.com/gfwlist -server=/.gaozhisheng.net/127.0.0.1#7913 -ipset=/.gaozhisheng.net/gfwlist -server=/.taweet.com/127.0.0.1#7913 -ipset=/.taweet.com/gfwlist -server=/.greatzhonghua.org/127.0.0.1#7913 -ipset=/.greatzhonghua.org/gfwlist -server=/.kwongwah.com.my/127.0.0.1#7913 -ipset=/.kwongwah.com.my/gfwlist -server=/.cmcn.org/127.0.0.1#7913 -ipset=/.cmcn.org/gfwlist -server=/.larsgeorge.com/127.0.0.1#7913 -ipset=/.larsgeorge.com/gfwlist -server=/.google.dev/127.0.0.1#7913 -ipset=/.google.dev/gfwlist -server=/.hqmovies.com/127.0.0.1#7913 -ipset=/.hqmovies.com/gfwlist -server=/.tsu.org.tw/127.0.0.1#7913 -ipset=/.tsu.org.tw/gfwlist -server=/.yuvutu.com/127.0.0.1#7913 -ipset=/.yuvutu.com/gfwlist -server=/.kanzhongguo.eu/127.0.0.1#7913 -ipset=/.kanzhongguo.eu/gfwlist -server=/.agro.hk/127.0.0.1#7913 -ipset=/.agro.hk/gfwlist -server=/.zaozon.com/127.0.0.1#7913 -ipset=/.zaozon.com/gfwlist -server=/.xxxy.biz/127.0.0.1#7913 -ipset=/.xxxy.biz/gfwlist -server=/.twitcause.com/127.0.0.1#7913 -ipset=/.twitcause.com/gfwlist -server=/.iuhrdf.org/127.0.0.1#7913 -ipset=/.iuhrdf.org/gfwlist -server=/.twitvid.com/127.0.0.1#7913 -ipset=/.twitvid.com/gfwlist -server=/.6parknews.com/127.0.0.1#7913 -ipset=/.6parknews.com/gfwlist -server=/.kaotic.com/127.0.0.1#7913 -ipset=/.kaotic.com/gfwlist -server=/.venetianmacao.com/127.0.0.1#7913 -ipset=/.venetianmacao.com/gfwlist -server=/.livecoin.net/127.0.0.1#7913 -ipset=/.livecoin.net/gfwlist -server=/.tw01.org/127.0.0.1#7913 -ipset=/.tw01.org/gfwlist -server=/.tw.mobi.yahoo.com/127.0.0.1#7913 -ipset=/.tw.mobi.yahoo.com/gfwlist -server=/.i2runner.com/127.0.0.1#7913 -ipset=/.i2runner.com/gfwlist -server=/.bandwagonhost.com/127.0.0.1#7913 -ipset=/.bandwagonhost.com/gfwlist -server=/.times.hinet.net/127.0.0.1#7913 -ipset=/.times.hinet.net/gfwlist -server=/.sexbot.com/127.0.0.1#7913 -ipset=/.sexbot.com/gfwlist -server=/.kir.jp/127.0.0.1#7913 -ipset=/.kir.jp/gfwlist -server=/.calgarychinese.net/127.0.0.1#7913 -ipset=/.calgarychinese.net/gfwlist -server=/.proxylist.org.uk/127.0.0.1#7913 -ipset=/.proxylist.org.uk/gfwlist -server=/.nubiles.net/127.0.0.1#7913 -ipset=/.nubiles.net/gfwlist -server=/.wildammo.com/127.0.0.1#7913 -ipset=/.wildammo.com/gfwlist -server=/.futurechinaforum.org/127.0.0.1#7913 -ipset=/.futurechinaforum.org/gfwlist -server=/.livevideo.com/127.0.0.1#7913 -ipset=/.livevideo.com/gfwlist -server=/.freefuckvids.com/127.0.0.1#7913 -ipset=/.freefuckvids.com/gfwlist -server=/.tibet.net/127.0.0.1#7913 -ipset=/.tibet.net/gfwlist -server=/.nflxso.net/127.0.0.1#7913 -ipset=/.nflxso.net/gfwlist -server=/.google.sk/127.0.0.1#7913 -ipset=/.google.sk/gfwlist -server=/.casino.williamhill.com/127.0.0.1#7913 -ipset=/.casino.williamhill.com/gfwlist -server=/.dynamicdns.co.uk/127.0.0.1#7913 -ipset=/.dynamicdns.co.uk/gfwlist -server=/.fbaddins.com/127.0.0.1#7913 -ipset=/.fbaddins.com/gfwlist -server=/.grammaly.com/127.0.0.1#7913 -ipset=/.grammaly.com/gfwlist -server=/.bayvoice.net/127.0.0.1#7913 -ipset=/.bayvoice.net/gfwlist -server=/.allconnected.co/127.0.0.1#7913 -ipset=/.allconnected.co/gfwlist -server=/.zeutch.com/127.0.0.1#7913 -ipset=/.zeutch.com/gfwlist -server=/.wangafu.net/127.0.0.1#7913 -ipset=/.wangafu.net/gfwlist -server=/.gettrials.com/127.0.0.1#7913 -ipset=/.gettrials.com/gfwlist -server=/.schema.org/127.0.0.1#7913 -ipset=/.schema.org/gfwlist -server=/.yobt.tv/127.0.0.1#7913 -ipset=/.yobt.tv/gfwlist -server=/.facebookmail.com/127.0.0.1#7913 -ipset=/.facebookmail.com/gfwlist -server=/.archive.ph/127.0.0.1#7913 -ipset=/.archive.ph/gfwlist -server=/.ctfriend.net/127.0.0.1#7913 -ipset=/.ctfriend.net/gfwlist -server=/.beric.me/127.0.0.1#7913 -ipset=/.beric.me/gfwlist -server=/.video.fdbox.com/127.0.0.1#7913 -ipset=/.video.fdbox.com/gfwlist -server=/.am730.com.hk/127.0.0.1#7913 -ipset=/.am730.com.hk/gfwlist -server=/.filmy.olabloga.pl/127.0.0.1#7913 -ipset=/.filmy.olabloga.pl/gfwlist -server=/.mpinews.com/127.0.0.1#7913 -ipset=/.mpinews.com/gfwlist -server=/.www1.biz/127.0.0.1#7913 -ipset=/.www1.biz/gfwlist -server=/.psblog.name/127.0.0.1#7913 -ipset=/.psblog.name/gfwlist -server=/.ffvpn.com/127.0.0.1#7913 -ipset=/.ffvpn.com/gfwlist -server=/.gvlib.com/127.0.0.1#7913 -ipset=/.gvlib.com/gfwlist -server=/.googleplay.com/127.0.0.1#7913 -ipset=/.googleplay.com/gfwlist -server=/.mpfinance.com/127.0.0.1#7913 -ipset=/.mpfinance.com/gfwlist -server=/.zpn.im/127.0.0.1#7913 -ipset=/.zpn.im/gfwlist -server=/.pritunl.com/127.0.0.1#7913 -ipset=/.pritunl.com/gfwlist -server=/.epochtimes.ru/127.0.0.1#7913 -ipset=/.epochtimes.ru/gfwlist -server=/.x-berry.com/127.0.0.1#7913 -ipset=/.x-berry.com/gfwlist -server=/.doujincafe.com/127.0.0.1#7913 -ipset=/.doujincafe.com/gfwlist -server=/.gelbooru.com/127.0.0.1#7913 -ipset=/.gelbooru.com/gfwlist -server=/.teensinasia.com/127.0.0.1#7913 -ipset=/.teensinasia.com/gfwlist -server=/.idemocracy.asia/127.0.0.1#7913 -ipset=/.idemocracy.asia/gfwlist -server=/.d-fukyu.com/127.0.0.1#7913 -ipset=/.d-fukyu.com/gfwlist -server=/.falundafamuseum.org/127.0.0.1#7913 -ipset=/.falundafamuseum.org/gfwlist -server=/.faproxy.com/127.0.0.1#7913 -ipset=/.faproxy.com/gfwlist -server=/.amtb-taipei.org/127.0.0.1#7913 -ipset=/.amtb-taipei.org/gfwlist -server=/.jobso.tv/127.0.0.1#7913 -ipset=/.jobso.tv/gfwlist -server=/.jinpianwang.com/127.0.0.1#7913 -ipset=/.jinpianwang.com/gfwlist -server=/.tbthouston.org/127.0.0.1#7913 -ipset=/.tbthouston.org/gfwlist -server=/.crucial.com/127.0.0.1#7913 -ipset=/.crucial.com/gfwlist -server=/.savemedia.com/127.0.0.1#7913 -ipset=/.savemedia.com/gfwlist -server=/.kankan.today/127.0.0.1#7913 -ipset=/.kankan.today/gfwlist -server=/.blinkx.com/127.0.0.1#7913 -ipset=/.blinkx.com/gfwlist -server=/.chinageeks.org/127.0.0.1#7913 -ipset=/.chinageeks.org/gfwlist -server=/.xyy69.com/127.0.0.1#7913 -ipset=/.xyy69.com/gfwlist -server=/.clearsurance.com/127.0.0.1#7913 -ipset=/.clearsurance.com/gfwlist -server=/.thedalailamamovie.com/127.0.0.1#7913 -ipset=/.thedalailamamovie.com/gfwlist -server=/.broadbook.com/127.0.0.1#7913 -ipset=/.broadbook.com/gfwlist -server=/.googlearth.com/127.0.0.1#7913 -ipset=/.googlearth.com/gfwlist -server=/.btspread.com/127.0.0.1#7913 -ipset=/.btspread.com/gfwlist -server=/.iav19.com/127.0.0.1#7913 -ipset=/.iav19.com/gfwlist -server=/.sohcradio.com/127.0.0.1#7913 -ipset=/.sohcradio.com/gfwlist -server=/.dharmakara.net/127.0.0.1#7913 -ipset=/.dharmakara.net/gfwlist -server=/.usmc.mil/127.0.0.1#7913 -ipset=/.usmc.mil/gfwlist -server=/.biblesforamerica.org/127.0.0.1#7913 -ipset=/.biblesforamerica.org/gfwlist -server=/.eastern-ark.com/127.0.0.1#7913 -ipset=/.eastern-ark.com/gfwlist -server=/.ipoock.com/127.0.0.1#7913 -ipset=/.ipoock.com/gfwlist -server=/.google.bg/127.0.0.1#7913 -ipset=/.google.bg/gfwlist -server=/.counter.social/127.0.0.1#7913 -ipset=/.counter.social/gfwlist -server=/.lsmkorean.org/127.0.0.1#7913 -ipset=/.lsmkorean.org/gfwlist -server=/.hidecloud.com/127.0.0.1#7913 -ipset=/.hidecloud.com/gfwlist -server=/.fbworkmail.com/127.0.0.1#7913 -ipset=/.fbworkmail.com/gfwlist -server=/.nordvpn.com/127.0.0.1#7913 -ipset=/.nordvpn.com/gfwlist -server=/.tibetoffice.eu/127.0.0.1#7913 -ipset=/.tibetoffice.eu/gfwlist -server=/.telegram.me/127.0.0.1#7913 -ipset=/.telegram.me/gfwlist -server=/.marxist.net/127.0.0.1#7913 -ipset=/.marxist.net/gfwlist -server=/.imageflea.com/127.0.0.1#7913 -ipset=/.imageflea.com/gfwlist -server=/.telecomspace.com/127.0.0.1#7913 -ipset=/.telecomspace.com/gfwlist -server=/.raizoji.or.jp/127.0.0.1#7913 -ipset=/.raizoji.or.jp/gfwlist -server=/.morningsun.org/127.0.0.1#7913 -ipset=/.morningsun.org/gfwlist -server=/.dynu.com/127.0.0.1#7913 -ipset=/.dynu.com/gfwlist -server=/.ai-kan.net/127.0.0.1#7913 -ipset=/.ai-kan.net/gfwlist -server=/.s8forum.com/127.0.0.1#7913 -ipset=/.s8forum.com/gfwlist -server=/.newschinacomment.org/127.0.0.1#7913 -ipset=/.newschinacomment.org/gfwlist -server=/.njuice.com/127.0.0.1#7913 -ipset=/.njuice.com/gfwlist -server=/.d2pass.com/127.0.0.1#7913 -ipset=/.d2pass.com/gfwlist -server=/.miroguide.com/127.0.0.1#7913 -ipset=/.miroguide.com/gfwlist -server=/.rileyguide.com/127.0.0.1#7913 -ipset=/.rileyguide.com/gfwlist -server=/.epochtimes.it/127.0.0.1#7913 -ipset=/.epochtimes.it/gfwlist -server=/.eromon.net/127.0.0.1#7913 -ipset=/.eromon.net/gfwlist -server=/.asacp.org/127.0.0.1#7913 -ipset=/.asacp.org/gfwlist -server=/.porntubenews.com/127.0.0.1#7913 -ipset=/.porntubenews.com/gfwlist -server=/.wanderinghorse.net/127.0.0.1#7913 -ipset=/.wanderinghorse.net/gfwlist -server=/.cn6.eu/127.0.0.1#7913 -ipset=/.cn6.eu/gfwlist -server=/.tabtter.jp/127.0.0.1#7913 -ipset=/.tabtter.jp/gfwlist -server=/.gekikame.com/127.0.0.1#7913 -ipset=/.gekikame.com/gfwlist -server=/.definebabe.com/127.0.0.1#7913 -ipset=/.definebabe.com/gfwlist -server=/.tibet-envoy.eu/127.0.0.1#7913 -ipset=/.tibet-envoy.eu/gfwlist -server=/.gohappy.com.tw/127.0.0.1#7913 -ipset=/.gohappy.com.tw/gfwlist -server=/.effers.com/127.0.0.1#7913 -ipset=/.effers.com/gfwlist -server=/.crossthewall.net/127.0.0.1#7913 -ipset=/.crossthewall.net/gfwlist -server=/.hk-pub.com/127.0.0.1#7913 -ipset=/.hk-pub.com/gfwlist -server=/.owl.li/127.0.0.1#7913 -ipset=/.owl.li/gfwlist -server=/.kxsw.life/127.0.0.1#7913 -ipset=/.kxsw.life/gfwlist -server=/.blog.goo.ne.jp/127.0.0.1#7913 -ipset=/.blog.goo.ne.jp/gfwlist -server=/.justicefortenzin.org/127.0.0.1#7913 -ipset=/.justicefortenzin.org/gfwlist -server=/.shenyun.com/127.0.0.1#7913 -ipset=/.shenyun.com/gfwlist -server=/.tinc-vpn.org/127.0.0.1#7913 -ipset=/.tinc-vpn.org/gfwlist -server=/.home.so-net.net.tw/127.0.0.1#7913 -ipset=/.home.so-net.net.tw/gfwlist -server=/.naweeklytimes.com/127.0.0.1#7913 -ipset=/.naweeklytimes.com/gfwlist -server=/.icoco.com/127.0.0.1#7913 -ipset=/.icoco.com/gfwlist -server=/.boxunblog.com/127.0.0.1#7913 -ipset=/.boxunblog.com/gfwlist -server=/.gotrusted.com/127.0.0.1#7913 -ipset=/.gotrusted.com/gfwlist -server=/.btbtav.com/127.0.0.1#7913 -ipset=/.btbtav.com/gfwlist -server=/.1pondo.tv/127.0.0.1#7913 -ipset=/.1pondo.tv/gfwlist -server=/.onmypc.org/127.0.0.1#7913 -ipset=/.onmypc.org/gfwlist -server=/.xiaohexie.com/127.0.0.1#7913 -ipset=/.xiaohexie.com/gfwlist -server=/.dragonex.io/127.0.0.1#7913 -ipset=/.dragonex.io/gfwlist -server=/.bitcointalk.org/127.0.0.1#7913 -ipset=/.bitcointalk.org/gfwlist -server=/.tw.knowledge.yahoo.com/127.0.0.1#7913 -ipset=/.tw.knowledge.yahoo.com/gfwlist -server=/.facebook.br/127.0.0.1#7913 -ipset=/.facebook.br/gfwlist -server=/.hk.geocities.com/127.0.0.1#7913 -ipset=/.hk.geocities.com/gfwlist -server=/.ns01.biz/127.0.0.1#7913 -ipset=/.ns01.biz/gfwlist -server=/.picacomic.com/127.0.0.1#7913 -ipset=/.picacomic.com/gfwlist -server=/.wikileaks.com/127.0.0.1#7913 -ipset=/.wikileaks.com/gfwlist -server=/.aniscartujo.com/127.0.0.1#7913 -ipset=/.aniscartujo.com/gfwlist -server=/.eeas.europa.eu/127.0.0.1#7913 -ipset=/.eeas.europa.eu/gfwlist -server=/.hkcoc.com/127.0.0.1#7913 -ipset=/.hkcoc.com/gfwlist -server=/.tibetanyouth.org/127.0.0.1#7913 -ipset=/.tibetanyouth.org/gfwlist -server=/.shenshou.org/127.0.0.1#7913 -ipset=/.shenshou.org/gfwlist -server=/.hidden-advent.org/127.0.0.1#7913 -ipset=/.hidden-advent.org/gfwlist -server=/.smchbooks.com/127.0.0.1#7913 -ipset=/.smchbooks.com/gfwlist -server=/.cfhks.org.hk/127.0.0.1#7913 -ipset=/.cfhks.org.hk/gfwlist -server=/.4dq.com/127.0.0.1#7913 -ipset=/.4dq.com/gfwlist -server=/.ff.im/127.0.0.1#7913 -ipset=/.ff.im/gfwlist -server=/.tmdb.org/127.0.0.1#7913 -ipset=/.tmdb.org/gfwlist -server=/.turntable.fm/127.0.0.1#7913 -ipset=/.turntable.fm/gfwlist -server=/.hnjhj.com/127.0.0.1#7913 -ipset=/.hnjhj.com/gfwlist -server=/.franklc.com/127.0.0.1#7913 -ipset=/.franklc.com/gfwlist -server=/.kendincos.net/127.0.0.1#7913 -ipset=/.kendincos.net/gfwlist -server=/.metroradio.com.hk/127.0.0.1#7913 -ipset=/.metroradio.com.hk/gfwlist -server=/.fail.hk/127.0.0.1#7913 -ipset=/.fail.hk/gfwlist -server=/.twistory.net/127.0.0.1#7913 -ipset=/.twistory.net/gfwlist -server=/.mastodon.social/127.0.0.1#7913 -ipset=/.mastodon.social/gfwlist -server=/.socialwhale.com/127.0.0.1#7913 -ipset=/.socialwhale.com/gfwlist -server=/.qhigh.com/127.0.0.1#7913 -ipset=/.qhigh.com/gfwlist -server=/.javmobile.net/127.0.0.1#7913 -ipset=/.javmobile.net/gfwlist -server=/.doctorvoice.org/127.0.0.1#7913 -ipset=/.doctorvoice.org/gfwlist -server=/.lers.google/127.0.0.1#7913 -ipset=/.lers.google/gfwlist -server=/.kun.im/127.0.0.1#7913 -ipset=/.kun.im/gfwlist -server=/.toythieves.com/127.0.0.1#7913 -ipset=/.toythieves.com/gfwlist -server=/.musicade.net/127.0.0.1#7913 -ipset=/.musicade.net/gfwlist -server=/.google.sh/127.0.0.1#7913 -ipset=/.google.sh/gfwlist -server=/.calameo.com/127.0.0.1#7913 -ipset=/.calameo.com/gfwlist -server=/.madewithcode.com/127.0.0.1#7913 -ipset=/.madewithcode.com/gfwlist -server=/.videomo.com/127.0.0.1#7913 -ipset=/.videomo.com/gfwlist -server=/.1000giri.net/127.0.0.1#7913 -ipset=/.1000giri.net/gfwlist -server=/.static-economist.com/127.0.0.1#7913 -ipset=/.static-economist.com/gfwlist -server=/.dns2go.com/127.0.0.1#7913 -ipset=/.dns2go.com/gfwlist -server=/.pki.goog/127.0.0.1#7913 -ipset=/.pki.goog/gfwlist -server=/.quannengshen.org/127.0.0.1#7913 -ipset=/.quannengshen.org/gfwlist -server=/.hqsbonline.wordpress.com/127.0.0.1#7913 -ipset=/.hqsbonline.wordpress.com/gfwlist -server=/.ezua.com/127.0.0.1#7913 -ipset=/.ezua.com/gfwlist -server=/.gizlen.net/127.0.0.1#7913 -ipset=/.gizlen.net/gfwlist -server=/.listorious.com/127.0.0.1#7913 -ipset=/.listorious.com/gfwlist -server=/.nytchina.com/127.0.0.1#7913 -ipset=/.nytchina.com/gfwlist -server=/.radiovaticana.org/127.0.0.1#7913 -ipset=/.radiovaticana.org/gfwlist -server=/.authorizeddns.net/127.0.0.1#7913 -ipset=/.authorizeddns.net/gfwlist -server=/.tiltbrush.com/127.0.0.1#7913 -ipset=/.tiltbrush.com/gfwlist -server=/.erktv.com/127.0.0.1#7913 -ipset=/.erktv.com/gfwlist -server=/.suoluo.org/127.0.0.1#7913 -ipset=/.suoluo.org/gfwlist -server=/.freetibet.org/127.0.0.1#7913 -ipset=/.freetibet.org/gfwlist -server=/.mimivip.com/127.0.0.1#7913 -ipset=/.mimivip.com/gfwlist -server=/.mingpaovan.com/127.0.0.1#7913 -ipset=/.mingpaovan.com/gfwlist -server=/.fanglizhi.info/127.0.0.1#7913 -ipset=/.fanglizhi.info/gfwlist -server=/.frommel.net/127.0.0.1#7913 -ipset=/.frommel.net/gfwlist -server=/.icl-fi.org/127.0.0.1#7913 -ipset=/.icl-fi.org/gfwlist -server=/.gabocorp.com/127.0.0.1#7913 -ipset=/.gabocorp.com/gfwlist -server=/.exx.com/127.0.0.1#7913 -ipset=/.exx.com/gfwlist -server=/.cfos.de/127.0.0.1#7913 -ipset=/.cfos.de/gfwlist -server=/.xxx.com/127.0.0.1#7913 -ipset=/.xxx.com/gfwlist -server=/.verybs.com/127.0.0.1#7913 -ipset=/.verybs.com/gfwlist -server=/.bgvpn.com/127.0.0.1#7913 -ipset=/.bgvpn.com/gfwlist -server=/.latibet.org/127.0.0.1#7913 -ipset=/.latibet.org/gfwlist -server=/.https443.org/127.0.0.1#7913 -ipset=/.https443.org/gfwlist -server=/.hkchurch.org/127.0.0.1#7913 -ipset=/.hkchurch.org/gfwlist -server=/.dalianmeng.org/127.0.0.1#7913 -ipset=/.dalianmeng.org/gfwlist -server=/.xbtce.com/127.0.0.1#7913 -ipset=/.xbtce.com/gfwlist -server=/.spicevpn.com/127.0.0.1#7913 -ipset=/.spicevpn.com/gfwlist -server=/.jiehua.cz/127.0.0.1#7913 -ipset=/.jiehua.cz/gfwlist -server=/.apiary.io/127.0.0.1#7913 -ipset=/.apiary.io/gfwlist -server=/.linear-abematv.akamaized.net/127.0.0.1#7913 -ipset=/.linear-abematv.akamaized.net/gfwlist -server=/.javtag.com/127.0.0.1#7913 -ipset=/.javtag.com/gfwlist -server=/.fux.com/127.0.0.1#7913 -ipset=/.fux.com/gfwlist -server=/.alkasir.com/127.0.0.1#7913 -ipset=/.alkasir.com/gfwlist -server=/.hexieshe.xyz/127.0.0.1#7913 -ipset=/.hexieshe.xyz/gfwlist -server=/.eevpn.com/127.0.0.1#7913 -ipset=/.eevpn.com/gfwlist -server=/.imgur.com/127.0.0.1#7913 -ipset=/.imgur.com/gfwlist -server=/.rcinet.ca/127.0.0.1#7913 -ipset=/.rcinet.ca/gfwlist -server=/.kink.com/127.0.0.1#7913 -ipset=/.kink.com/gfwlist -server=/.urlparser.com/127.0.0.1#7913 -ipset=/.urlparser.com/gfwlist -server=/.fillthesquare.org/127.0.0.1#7913 -ipset=/.fillthesquare.org/gfwlist -server=/.fuckcnnic.net/127.0.0.1#7913 -ipset=/.fuckcnnic.net/gfwlist -server=/.annatam.com/127.0.0.1#7913 -ipset=/.annatam.com/gfwlist -server=/.tw.news.yahoo.com/127.0.0.1#7913 -ipset=/.tw.news.yahoo.com/gfwlist -server=/.a771.dscq.akamai.net/127.0.0.1#7913 -ipset=/.a771.dscq.akamai.net/gfwlist -server=/.tbpic.info/127.0.0.1#7913 -ipset=/.tbpic.info/gfwlist -server=/.ibvpn.com/127.0.0.1#7913 -ipset=/.ibvpn.com/gfwlist -server=/.website.informer.com/127.0.0.1#7913 -ipset=/.website.informer.com/gfwlist -server=/.goldwave.com/127.0.0.1#7913 -ipset=/.goldwave.com/gfwlist -server=/.qkshare.com/127.0.0.1#7913 -ipset=/.qkshare.com/gfwlist -server=/.lvhai.org/127.0.0.1#7913 -ipset=/.lvhai.org/gfwlist -server=/.amitabhafoundation.us/127.0.0.1#7913 -ipset=/.amitabhafoundation.us/gfwlist -server=/.gayhub.com/127.0.0.1#7913 -ipset=/.gayhub.com/gfwlist -server=/.devpn.com/127.0.0.1#7913 -ipset=/.devpn.com/gfwlist -server=/.google.com/127.0.0.1#7913 -ipset=/.google.com/gfwlist -server=/.www.idlcoyote.com/127.0.0.1#7913 -ipset=/.www.idlcoyote.com/gfwlist -server=/.mingjingnews.com/127.0.0.1#7913 -ipset=/.mingjingnews.com/gfwlist -server=/.koranmandarin.com/127.0.0.1#7913 -ipset=/.koranmandarin.com/gfwlist -server=/.ntdtv.org/127.0.0.1#7913 -ipset=/.ntdtv.org/gfwlist -server=/.turbohide.com/127.0.0.1#7913 -ipset=/.turbohide.com/gfwlist -server=/.bigjapanesesex.com/127.0.0.1#7913 -ipset=/.bigjapanesesex.com/gfwlist -server=/.coolaler.com/127.0.0.1#7913 -ipset=/.coolaler.com/gfwlist -server=/.ns01.info/127.0.0.1#7913 -ipset=/.ns01.info/gfwlist -server=/.npnt.me/127.0.0.1#7913 -ipset=/.npnt.me/gfwlist -server=/.djangosnippets.org/127.0.0.1#7913 -ipset=/.djangosnippets.org/gfwlist -server=/.freetibet.net/127.0.0.1#7913 -ipset=/.freetibet.net/gfwlist -server=/.insecam.org/127.0.0.1#7913 -ipset=/.insecam.org/gfwlist -server=/.chinahush.com/127.0.0.1#7913 -ipset=/.chinahush.com/gfwlist -server=/.costco.com/127.0.0.1#7913 -ipset=/.costco.com/gfwlist -server=/.hkacg.com/127.0.0.1#7913 -ipset=/.hkacg.com/gfwlist -server=/.higfw.com/127.0.0.1#7913 -ipset=/.higfw.com/gfwlist -server=/.freenet-china.org/127.0.0.1#7913 -ipset=/.freenet-china.org/gfwlist -server=/.pandavpn-jp.com/127.0.0.1#7913 -ipset=/.pandavpn-jp.com/gfwlist -server=/.kmuh.org.tw/127.0.0.1#7913 -ipset=/.kmuh.org.tw/gfwlist -server=/.uocn.org/127.0.0.1#7913 -ipset=/.uocn.org/gfwlist -server=/.rebatesrule.net/127.0.0.1#7913 -ipset=/.rebatesrule.net/gfwlist -server=/.tech2.in.com/127.0.0.1#7913 -ipset=/.tech2.in.com/gfwlist -server=/.nfjtyd.com/127.0.0.1#7913 -ipset=/.nfjtyd.com/gfwlist -server=/.fengzhenghu.net/127.0.0.1#7913 -ipset=/.fengzhenghu.net/gfwlist -server=/.kannewyork.com/127.0.0.1#7913 -ipset=/.kannewyork.com/gfwlist -server=/.from-pr.com/127.0.0.1#7913 -ipset=/.from-pr.com/gfwlist -server=/.readingtimes.com.tw/127.0.0.1#7913 -ipset=/.readingtimes.com.tw/gfwlist -server=/.api.pureapk.com/127.0.0.1#7913 -ipset=/.api.pureapk.com/gfwlist -server=/.videopediaworld.com/127.0.0.1#7913 -ipset=/.videopediaworld.com/gfwlist -server=/.putihome.org/127.0.0.1#7913 -ipset=/.putihome.org/gfwlist -server=/.www.citizenlab.org/127.0.0.1#7913 -ipset=/.www.citizenlab.org/gfwlist -server=/.freeman2.com/127.0.0.1#7913 -ipset=/.freeman2.com/gfwlist -server=/.eporner.com/127.0.0.1#7913 -ipset=/.eporner.com/gfwlist -server=/.allcoin.com/127.0.0.1#7913 -ipset=/.allcoin.com/gfwlist -server=/.thedw.us/127.0.0.1#7913 -ipset=/.thedw.us/gfwlist -server=/.tibetfocus.com/127.0.0.1#7913 -ipset=/.tibetfocus.com/gfwlist -server=/.clb.org.hk/127.0.0.1#7913 -ipset=/.clb.org.hk/gfwlist -server=/.twicountry.org/127.0.0.1#7913 -ipset=/.twicountry.org/gfwlist -server=/.3tui.net/127.0.0.1#7913 -ipset=/.3tui.net/gfwlist -server=/.mastodon.cloud/127.0.0.1#7913 -ipset=/.mastodon.cloud/gfwlist -server=/.fanqiangdang.com/127.0.0.1#7913 -ipset=/.fanqiangdang.com/gfwlist -server=/.angularjs.org/127.0.0.1#7913 -ipset=/.angularjs.org/gfwlist -server=/.wallornot.org/127.0.0.1#7913 -ipset=/.wallornot.org/gfwlist -server=/.hrcir.com/127.0.0.1#7913 -ipset=/.hrcir.com/gfwlist -server=/.blogimg.jp/127.0.0.1#7913 -ipset=/.blogimg.jp/gfwlist -server=/.shenzhoufilm.com/127.0.0.1#7913 -ipset=/.shenzhoufilm.com/gfwlist -server=/.twitter.jp/127.0.0.1#7913 -ipset=/.twitter.jp/gfwlist -server=/.savethesounds.info/127.0.0.1#7913 -ipset=/.savethesounds.info/gfwlist -server=/.extrabux.com/127.0.0.1#7913 -ipset=/.extrabux.com/gfwlist -server=/.cdbook.org/127.0.0.1#7913 -ipset=/.cdbook.org/gfwlist -server=/.2049bbs.xyz/127.0.0.1#7913 -ipset=/.2049bbs.xyz/gfwlist -server=/.v2ray.com/127.0.0.1#7913 -ipset=/.v2ray.com/gfwlist -server=/.vjmedia.com.hk/127.0.0.1#7913 -ipset=/.vjmedia.com.hk/gfwlist -server=/.hkgolden.com/127.0.0.1#7913 -ipset=/.hkgolden.com/gfwlist -server=/.money-link.com.tw/127.0.0.1#7913 -ipset=/.money-link.com.tw/gfwlist -server=/.leafyvpn.net/127.0.0.1#7913 -ipset=/.leafyvpn.net/gfwlist -server=/.yahoo.com.hk/127.0.0.1#7913 -ipset=/.yahoo.com.hk/gfwlist -server=/.blog.syx86.com/127.0.0.1#7913 -ipset=/.blog.syx86.com/gfwlist -server=/.hk.news.yahoo.com/127.0.0.1#7913 -ipset=/.hk.news.yahoo.com/gfwlist -server=/.kindleren.com/127.0.0.1#7913 -ipset=/.kindleren.com/gfwlist -server=/.ddns.info/127.0.0.1#7913 -ipset=/.ddns.info/gfwlist -server=/.zenmate.com/127.0.0.1#7913 -ipset=/.zenmate.com/gfwlist -server=/.dwnews.com/127.0.0.1#7913 -ipset=/.dwnews.com/gfwlist -server=/.zim.vn/127.0.0.1#7913 -ipset=/.zim.vn/gfwlist -server=/.ntdtv.ca/127.0.0.1#7913 -ipset=/.ntdtv.ca/gfwlist -server=/.www.klip.me/127.0.0.1#7913 -ipset=/.www.klip.me/gfwlist -server=/.spideroak.com/127.0.0.1#7913 -ipset=/.spideroak.com/gfwlist -server=/.eltondisney.com/127.0.0.1#7913 -ipset=/.eltondisney.com/gfwlist -server=/.shooshtime.com/127.0.0.1#7913 -ipset=/.shooshtime.com/gfwlist -server=/.xinmiao.com.hk/127.0.0.1#7913 -ipset=/.xinmiao.com.hk/gfwlist -server=/.isasecret.com/127.0.0.1#7913 -ipset=/.isasecret.com/gfwlist -server=/.baijie.org/127.0.0.1#7913 -ipset=/.baijie.org/gfwlist -server=/.flyvpn.com/127.0.0.1#7913 -ipset=/.flyvpn.com/gfwlist -server=/.chicagoncmtv.com/127.0.0.1#7913 -ipset=/.chicagoncmtv.com/gfwlist -server=/.getastrill.com/127.0.0.1#7913 -ipset=/.getastrill.com/gfwlist -server=/.linux.org.hk/127.0.0.1#7913 -ipset=/.linux.org.hk/gfwlist -server=/.minghui-school.org/127.0.0.1#7913 -ipset=/.minghui-school.org/gfwlist -server=/.online.recoveryversion.org/127.0.0.1#7913 -ipset=/.online.recoveryversion.org/gfwlist -server=/.hi-on.org.tw/127.0.0.1#7913 -ipset=/.hi-on.org.tw/gfwlist -server=/.mitbbs.com/127.0.0.1#7913 -ipset=/.mitbbs.com/gfwlist -server=/.vpn.sv.cmu.edu/127.0.0.1#7913 -ipset=/.vpn.sv.cmu.edu/gfwlist -server=/.kagyu.org/127.0.0.1#7913 -ipset=/.kagyu.org/gfwlist -server=/.daxa.cn/127.0.0.1#7913 -ipset=/.daxa.cn/gfwlist -server=/.home.sina.com/127.0.0.1#7913 -ipset=/.home.sina.com/gfwlist -server=/.dunyabulteni.net/127.0.0.1#7913 -ipset=/.dunyabulteni.net/gfwlist -server=/.opus-gaming.com/127.0.0.1#7913 -ipset=/.opus-gaming.com/gfwlist -server=/.tweetedtimes.com/127.0.0.1#7913 -ipset=/.tweetedtimes.com/gfwlist -server=/.lastcombat.com/127.0.0.1#7913 -ipset=/.lastcombat.com/gfwlist -server=/.cdn.seatguru.com/127.0.0.1#7913 -ipset=/.cdn.seatguru.com/gfwlist -server=/.beijing1989.com/127.0.0.1#7913 -ipset=/.beijing1989.com/gfwlist -server=/.gatecoin.com/127.0.0.1#7913 -ipset=/.gatecoin.com/gfwlist -server=/.ezpc.tk/127.0.0.1#7913 -ipset=/.ezpc.tk/gfwlist -server=/.wqyd.org/127.0.0.1#7913 -ipset=/.wqyd.org/gfwlist -server=/.bbs.morbell.com/127.0.0.1#7913 -ipset=/.bbs.morbell.com/gfwlist -server=/.epochweekly.com/127.0.0.1#7913 -ipset=/.epochweekly.com/gfwlist -server=/.cn.calameo.com/127.0.0.1#7913 -ipset=/.cn.calameo.com/gfwlist -server=/.hdtvb.net/127.0.0.1#7913 -ipset=/.hdtvb.net/gfwlist -server=/.sciencenets.com/127.0.0.1#7913 -ipset=/.sciencenets.com/gfwlist -server=/.googlescholar.com/127.0.0.1#7913 -ipset=/.googlescholar.com/gfwlist -server=/.iownyour.org/127.0.0.1#7913 -ipset=/.iownyour.org/gfwlist -server=/.gerefoundation.org/127.0.0.1#7913 -ipset=/.gerefoundation.org/gfwlist -server=/.18board.com/127.0.0.1#7913 -ipset=/.18board.com/gfwlist -server=/.chinesetalks.net/127.0.0.1#7913 -ipset=/.chinesetalks.net/gfwlist -server=/.466453.com/127.0.0.1#7913 -ipset=/.466453.com/gfwlist -server=/.gartlive.com/127.0.0.1#7913 -ipset=/.gartlive.com/gfwlist -server=/.youdontcare.com/127.0.0.1#7913 -ipset=/.youdontcare.com/gfwlist -server=/.retweeteffect.com/127.0.0.1#7913 -ipset=/.retweeteffect.com/gfwlist -server=/.t.co/127.0.0.1#7913 -ipset=/.t.co/gfwlist -server=/.uku.im/127.0.0.1#7913 -ipset=/.uku.im/gfwlist -server=/.shattered.io/127.0.0.1#7913 -ipset=/.shattered.io/gfwlist -server=/.mytizi.com/127.0.0.1#7913 -ipset=/.mytizi.com/gfwlist -server=/.metrohk.com.hk/127.0.0.1#7913 -ipset=/.metrohk.com.hk/gfwlist -server=/.greatroc.org/127.0.0.1#7913 -ipset=/.greatroc.org/gfwlist -server=/.dalailama-archives.org/127.0.0.1#7913 -ipset=/.dalailama-archives.org/gfwlist -server=/.blog.kangye.org/127.0.0.1#7913 -ipset=/.blog.kangye.org/gfwlist -server=/.g.co/127.0.0.1#7913 -ipset=/.g.co/gfwlist -server=/.wiki.oauth.net/127.0.0.1#7913 -ipset=/.wiki.oauth.net/gfwlist -server=/.enfal.de/127.0.0.1#7913 -ipset=/.enfal.de/gfwlist -server=/.mike.cz.cc/127.0.0.1#7913 -ipset=/.mike.cz.cc/gfwlist -server=/.shiatv.net/127.0.0.1#7913 -ipset=/.shiatv.net/gfwlist -server=/.liwangyang.com/127.0.0.1#7913 -ipset=/.liwangyang.com/gfwlist -server=/.mimiai.net/127.0.0.1#7913 -ipset=/.mimiai.net/gfwlist -server=/.ck101.com/127.0.0.1#7913 -ipset=/.ck101.com/gfwlist -server=/.wtfpeople.com/127.0.0.1#7913 -ipset=/.wtfpeople.com/gfwlist -server=/.cathvoice.org.tw/127.0.0.1#7913 -ipset=/.cathvoice.org.tw/gfwlist -server=/.news100.com.tw/127.0.0.1#7913 -ipset=/.news100.com.tw/gfwlist -server=/.fbsbx.com/127.0.0.1#7913 -ipset=/.fbsbx.com/gfwlist -server=/.focusvpn.com/127.0.0.1#7913 -ipset=/.focusvpn.com/gfwlist -server=/.mos.ru/127.0.0.1#7913 -ipset=/.mos.ru/gfwlist -server=/.cclife.ca/127.0.0.1#7913 -ipset=/.cclife.ca/gfwlist -server=/.dalailama.usc.edu/127.0.0.1#7913 -ipset=/.dalailama.usc.edu/gfwlist -server=/.avdb.in/127.0.0.1#7913 -ipset=/.avdb.in/gfwlist -server=/.oursogo.com/127.0.0.1#7913 -ipset=/.oursogo.com/gfwlist -server=/.oculus.com/127.0.0.1#7913 -ipset=/.oculus.com/gfwlist -server=/.e-classical.com.tw/127.0.0.1#7913 -ipset=/.e-classical.com.tw/gfwlist -server=/.ccthere.net/127.0.0.1#7913 -ipset=/.ccthere.net/gfwlist -server=/.zuo.la/127.0.0.1#7913 -ipset=/.zuo.la/gfwlist -server=/.hackthatphone.net/127.0.0.1#7913 -ipset=/.hackthatphone.net/gfwlist -server=/.rlwlw.com/127.0.0.1#7913 -ipset=/.rlwlw.com/gfwlist -server=/.sakuralive.com/127.0.0.1#7913 -ipset=/.sakuralive.com/gfwlist -server=/.prism-break.org/127.0.0.1#7913 -ipset=/.prism-break.org/gfwlist -server=/.jandyx.com/127.0.0.1#7913 -ipset=/.jandyx.com/gfwlist -server=/.nexon.com/127.0.0.1#7913 -ipset=/.nexon.com/gfwlist -server=/.tibetalk.com/127.0.0.1#7913 -ipset=/.tibetalk.com/gfwlist -server=/.vmpsoft.com/127.0.0.1#7913 -ipset=/.vmpsoft.com/gfwlist -server=/.creaders.net/127.0.0.1#7913 -ipset=/.creaders.net/gfwlist -server=/.0rz.tw/127.0.0.1#7913 -ipset=/.0rz.tw/gfwlist -server=/.topbtc.com/127.0.0.1#7913 -ipset=/.topbtc.com/gfwlist -server=/.palacemoon.com/127.0.0.1#7913 -ipset=/.palacemoon.com/gfwlist -server=/.clyp.it/127.0.0.1#7913 -ipset=/.clyp.it/gfwlist -server=/.vocativ.com/127.0.0.1#7913 -ipset=/.vocativ.com/gfwlist -server=/.gvt1.com/127.0.0.1#7913 -ipset=/.gvt1.com/gfwlist -server=/.mypicture.info/127.0.0.1#7913 -ipset=/.mypicture.info/gfwlist -server=/.freewechat.com/127.0.0.1#7913 -ipset=/.freewechat.com/gfwlist -server=/.phosphation13.rssing.com/127.0.0.1#7913 -ipset=/.phosphation13.rssing.com/gfwlist -server=/.boysmaster.com/127.0.0.1#7913 -ipset=/.boysmaster.com/gfwlist -server=/.eastturkestan.com/127.0.0.1#7913 -ipset=/.eastturkestan.com/gfwlist -server=/.wforum.com/127.0.0.1#7913 -ipset=/.wforum.com/gfwlist -server=/.avgle.com/127.0.0.1#7913 -ipset=/.avgle.com/gfwlist -server=/.ixquick.com/127.0.0.1#7913 -ipset=/.ixquick.com/gfwlist -server=/.post01.com/127.0.0.1#7913 -ipset=/.post01.com/gfwlist -server=/.hdzog.com/127.0.0.1#7913 -ipset=/.hdzog.com/gfwlist -server=/.yourlisten.com/127.0.0.1#7913 -ipset=/.yourlisten.com/gfwlist -server=/.ok.ru/127.0.0.1#7913 -ipset=/.ok.ru/gfwlist -server=/.aolchannels.aol.com/127.0.0.1#7913 -ipset=/.aolchannels.aol.com/gfwlist -server=/.casinobellini.com/127.0.0.1#7913 -ipset=/.casinobellini.com/gfwlist -server=/.sinoants.com/127.0.0.1#7913 -ipset=/.sinoants.com/gfwlist -server=/.solidaritetibet.org/127.0.0.1#7913 -ipset=/.solidaritetibet.org/gfwlist -server=/.korea.net/127.0.0.1#7913 -ipset=/.korea.net/gfwlist -server=/.ebookee.com/127.0.0.1#7913 -ipset=/.ebookee.com/gfwlist -server=/.vpndada.com/127.0.0.1#7913 -ipset=/.vpndada.com/gfwlist -server=/.newcenturymc.com/127.0.0.1#7913 -ipset=/.newcenturymc.com/gfwlist -server=/.avmoo.net/127.0.0.1#7913 -ipset=/.avmoo.net/gfwlist -server=/.forum.sina.com.hk/127.0.0.1#7913 -ipset=/.forum.sina.com.hk/gfwlist -server=/.ninth.biz/127.0.0.1#7913 -ipset=/.ninth.biz/gfwlist -server=/.dynamicdns.org.uk/127.0.0.1#7913 -ipset=/.dynamicdns.org.uk/gfwlist -server=/.blog.google/127.0.0.1#7913 -ipset=/.blog.google/gfwlist -server=/.zodgame.us/127.0.0.1#7913 -ipset=/.zodgame.us/gfwlist -server=/.x-wall.org/127.0.0.1#7913 -ipset=/.x-wall.org/gfwlist -server=/.twitterkr.com/127.0.0.1#7913 -ipset=/.twitterkr.com/gfwlist -server=/.niusnews.com/127.0.0.1#7913 -ipset=/.niusnews.com/gfwlist -server=/.mummysgold.com/127.0.0.1#7913 -ipset=/.mummysgold.com/gfwlist -server=/.listentoyoutube.com/127.0.0.1#7913 -ipset=/.listentoyoutube.com/gfwlist -server=/.wsj.net/127.0.0.1#7913 -ipset=/.wsj.net/gfwlist -server=/.agoogleaday.com/127.0.0.1#7913 -ipset=/.agoogleaday.com/gfwlist -server=/.redballoonsolidarity.org/127.0.0.1#7913 -ipset=/.redballoonsolidarity.org/gfwlist -server=/.luke54.org/127.0.0.1#7913 -ipset=/.luke54.org/gfwlist -server=/.freedominfonetweb.wordpress.com/127.0.0.1#7913 -ipset=/.freedominfonetweb.wordpress.com/gfwlist -server=/.kyofun.com/127.0.0.1#7913 -ipset=/.kyofun.com/gfwlist -server=/.registry.google/127.0.0.1#7913 -ipset=/.registry.google/gfwlist -server=/.kcoolonline.com/127.0.0.1#7913 -ipset=/.kcoolonline.com/gfwlist -server=/.stories.google/127.0.0.1#7913 -ipset=/.stories.google/gfwlist -server=/.firebaseio.com/127.0.0.1#7913 -ipset=/.firebaseio.com/gfwlist -server=/.privacybox.de/127.0.0.1#7913 -ipset=/.privacybox.de/gfwlist -server=/.waikeung.org/127.0.0.1#7913 -ipset=/.waikeung.org/gfwlist -server=/.mitbbsau.com/127.0.0.1#7913 -ipset=/.mitbbsau.com/gfwlist -server=/.china-mmm.jp.net/127.0.0.1#7913 -ipset=/.china-mmm.jp.net/gfwlist -server=/.nextmedia.com/127.0.0.1#7913 -ipset=/.nextmedia.com/gfwlist -server=/.postimg.org/127.0.0.1#7913 -ipset=/.postimg.org/gfwlist -server=/.vmixcore.com/127.0.0.1#7913 -ipset=/.vmixcore.com/gfwlist -server=/.yogichen.org/127.0.0.1#7913 -ipset=/.yogichen.org/gfwlist -server=/.ulop.net/127.0.0.1#7913 -ipset=/.ulop.net/gfwlist -server=/.fc2cn.com/127.0.0.1#7913 -ipset=/.fc2cn.com/gfwlist -server=/.fochk.org/127.0.0.1#7913 -ipset=/.fochk.org/gfwlist -server=/.huluim.com/127.0.0.1#7913 -ipset=/.huluim.com/gfwlist -server=/.dpr.info/127.0.0.1#7913 -ipset=/.dpr.info/gfwlist -server=/.2008xianzhang.info/127.0.0.1#7913 -ipset=/.2008xianzhang.info/gfwlist -server=/.andygod.com/127.0.0.1#7913 -ipset=/.andygod.com/gfwlist -server=/.msa-it.org/127.0.0.1#7913 -ipset=/.msa-it.org/gfwlist -server=/.voacantonese.com/127.0.0.1#7913 -ipset=/.voacantonese.com/gfwlist -server=/.bot.nu/127.0.0.1#7913 -ipset=/.bot.nu/gfwlist -server=/.10musume.com/127.0.0.1#7913 -ipset=/.10musume.com/gfwlist -server=/.adsense.com/127.0.0.1#7913 -ipset=/.adsense.com/gfwlist -server=/.ss.pythonic.life/127.0.0.1#7913 -ipset=/.ss.pythonic.life/gfwlist -server=/.wha.la/127.0.0.1#7913 -ipset=/.wha.la/gfwlist -server=/.bit-z.com/127.0.0.1#7913 -ipset=/.bit-z.com/gfwlist -server=/.catch22.net/127.0.0.1#7913 -ipset=/.catch22.net/gfwlist -server=/.foxsub.com/127.0.0.1#7913 -ipset=/.foxsub.com/gfwlist -server=/.hongkongfp.com/127.0.0.1#7913 -ipset=/.hongkongfp.com/gfwlist -server=/.mthruf.com/127.0.0.1#7913 -ipset=/.mthruf.com/gfwlist -server=/.hk.knowledge.yahoo.com/127.0.0.1#7913 -ipset=/.hk.knowledge.yahoo.com/gfwlist -server=/.imagefap.com/127.0.0.1#7913 -ipset=/.imagefap.com/gfwlist -server=/.threatchaos.com/127.0.0.1#7913 -ipset=/.threatchaos.com/gfwlist -server=/.dmcdn.net/127.0.0.1#7913 -ipset=/.dmcdn.net/gfwlist -server=/.stickam.com/127.0.0.1#7913 -ipset=/.stickam.com/gfwlist -server=/.aplusvpn.com/127.0.0.1#7913 -ipset=/.aplusvpn.com/gfwlist -server=/.av.movie/127.0.0.1#7913 -ipset=/.av.movie/gfwlist -server=/.javzz.com/127.0.0.1#7913 -ipset=/.javzz.com/gfwlist -server=/.coobay.com/127.0.0.1#7913 -ipset=/.coobay.com/gfwlist -server=/.coat.co.jp/127.0.0.1#7913 -ipset=/.coat.co.jp/gfwlist -server=/.epochweek.com/127.0.0.1#7913 -ipset=/.epochweek.com/gfwlist -server=/.carmotorshow.com/127.0.0.1#7913 -ipset=/.carmotorshow.com/gfwlist -server=/.138.com/127.0.0.1#7913 -ipset=/.138.com/gfwlist -server=/.oversea.istarshine.com/127.0.0.1#7913 -ipset=/.oversea.istarshine.com/gfwlist -server=/.pao-pao.net/127.0.0.1#7913 -ipset=/.pao-pao.net/gfwlist -server=/.tweez.net/127.0.0.1#7913 -ipset=/.tweez.net/gfwlist -server=/.chinesenews.net.au/127.0.0.1#7913 -ipset=/.chinesenews.net.au/gfwlist -server=/.moby.to/127.0.0.1#7913 -ipset=/.moby.to/gfwlist -server=/.ait.org.tw/127.0.0.1#7913 -ipset=/.ait.org.tw/gfwlist -server=/.hautelookcdn.com/127.0.0.1#7913 -ipset=/.hautelookcdn.com/gfwlist -server=/.chaoex.com/127.0.0.1#7913 -ipset=/.chaoex.com/gfwlist -server=/.888.com/127.0.0.1#7913 -ipset=/.888.com/gfwlist -server=/.news.cnyes.com/127.0.0.1#7913 -ipset=/.news.cnyes.com/gfwlist -server=/.fangeqiang.com/127.0.0.1#7913 -ipset=/.fangeqiang.com/gfwlist -server=/.okayfreedom.com/127.0.0.1#7913 -ipset=/.okayfreedom.com/gfwlist -server=/.avbody.tv/127.0.0.1#7913 -ipset=/.avbody.tv/gfwlist -server=/.nradio.me/127.0.0.1#7913 -ipset=/.nradio.me/gfwlist -server=/.faydao.com/127.0.0.1#7913 -ipset=/.faydao.com/gfwlist -server=/.simplecd.org/127.0.0.1#7913 -ipset=/.simplecd.org/gfwlist -server=/.huping.net/127.0.0.1#7913 -ipset=/.huping.net/gfwlist -server=/.wattpad.com/127.0.0.1#7913 -ipset=/.wattpad.com/gfwlist -server=/.civildisobediencemovement.org/127.0.0.1#7913 -ipset=/.civildisobediencemovement.org/gfwlist -server=/.bod.asia/127.0.0.1#7913 -ipset=/.bod.asia/gfwlist -server=/.greenfieldbookstore.com.hk/127.0.0.1#7913 -ipset=/.greenfieldbookstore.com.hk/gfwlist -server=/.city365.ca/127.0.0.1#7913 -ipset=/.city365.ca/gfwlist -server=/.vpn4all.com/127.0.0.1#7913 -ipset=/.vpn4all.com/gfwlist -server=/.identi.ca/127.0.0.1#7913 -ipset=/.identi.ca/gfwlist -server=/.pokerstars.com/127.0.0.1#7913 -ipset=/.pokerstars.com/gfwlist -server=/.hqjapanesesex.com/127.0.0.1#7913 -ipset=/.hqjapanesesex.com/gfwlist -server=/.tianhuayuan.com/127.0.0.1#7913 -ipset=/.tianhuayuan.com/gfwlist -server=/.keepandshare.com/127.0.0.1#7913 -ipset=/.keepandshare.com/gfwlist -server=/.moodyz.com/127.0.0.1#7913 -ipset=/.moodyz.com/gfwlist -server=/.tiananmenuniv.net/127.0.0.1#7913 -ipset=/.tiananmenuniv.net/gfwlist -server=/.crazys.cc/127.0.0.1#7913 -ipset=/.crazys.cc/gfwlist -server=/.pttgame.com/127.0.0.1#7913 -ipset=/.pttgame.com/gfwlist -server=/.gdbt.net/127.0.0.1#7913 -ipset=/.gdbt.net/gfwlist -server=/.firetweet.io/127.0.0.1#7913 -ipset=/.firetweet.io/gfwlist -server=/.ytht.net/127.0.0.1#7913 -ipset=/.ytht.net/gfwlist -server=/.dumb1.com/127.0.0.1#7913 -ipset=/.dumb1.com/gfwlist -server=/.1991way.com/127.0.0.1#7913 -ipset=/.1991way.com/gfwlist -server=/.hojemacau.com.mo/127.0.0.1#7913 -ipset=/.hojemacau.com.mo/gfwlist -server=/.gyalwarinpoche.com/127.0.0.1#7913 -ipset=/.gyalwarinpoche.com/gfwlist -server=/.itaboo.info/127.0.0.1#7913 -ipset=/.itaboo.info/gfwlist -server=/.tmpp.org/127.0.0.1#7913 -ipset=/.tmpp.org/gfwlist -server=/.myforum.com.hk/127.0.0.1#7913 -ipset=/.myforum.com.hk/gfwlist -server=/.gardennetworks.com/127.0.0.1#7913 -ipset=/.gardennetworks.com/gfwlist -server=/.google.co.jp/127.0.0.1#7913 -ipset=/.google.co.jp/gfwlist -server=/.onionhacker.github.io/127.0.0.1#7913 -ipset=/.onionhacker.github.io/gfwlist -server=/.archiveofourown.org/127.0.0.1#7913 -ipset=/.archiveofourown.org/gfwlist -server=/.sinocism.com/127.0.0.1#7913 -ipset=/.sinocism.com/gfwlist -server=/.rakuten.co.jp/127.0.0.1#7913 -ipset=/.rakuten.co.jp/gfwlist -server=/.uncyclomedia.org/127.0.0.1#7913 -ipset=/.uncyclomedia.org/gfwlist -server=/.bloomfortune.com/127.0.0.1#7913 -ipset=/.bloomfortune.com/gfwlist -server=/.rthklive2-lh.akamaihd.net/127.0.0.1#7913 -ipset=/.rthklive2-lh.akamaihd.net/gfwlist -server=/.hurgokbayrak.com/127.0.0.1#7913 -ipset=/.hurgokbayrak.com/gfwlist -server=/.tsctv.net/127.0.0.1#7913 -ipset=/.tsctv.net/gfwlist -server=/.thetibetpost.com/127.0.0.1#7913 -ipset=/.thetibetpost.com/gfwlist -server=/.dropboxusercontent.com/127.0.0.1#7913 -ipset=/.dropboxusercontent.com/gfwlist -server=/.telegram.dog/127.0.0.1#7913 -ipset=/.telegram.dog/gfwlist -server=/.hkfreezone.com/127.0.0.1#7913 -ipset=/.hkfreezone.com/gfwlist -server=/.whatsapp.com/127.0.0.1#7913 -ipset=/.whatsapp.com/gfwlist -server=/.kk-whys.co.jp/127.0.0.1#7913 -ipset=/.kk-whys.co.jp/gfwlist -server=/.fxcm-chinese.com/127.0.0.1#7913 -ipset=/.fxcm-chinese.com/gfwlist -server=/.emilylau.org.hk/127.0.0.1#7913 -ipset=/.emilylau.org.hk/gfwlist -server=/.compress.to/127.0.0.1#7913 -ipset=/.compress.to/gfwlist -server=/.hklft.com/127.0.0.1#7913 -ipset=/.hklft.com/gfwlist -server=/.graphql.org/127.0.0.1#7913 -ipset=/.graphql.org/gfwlist -server=/.bandpage.com/127.0.0.1#7913 -ipset=/.bandpage.com/gfwlist -server=/.jkb.cc/127.0.0.1#7913 -ipset=/.jkb.cc/gfwlist -server=/.dafabet.com/127.0.0.1#7913 -ipset=/.dafabet.com/gfwlist -server=/.superpages.com/127.0.0.1#7913 -ipset=/.superpages.com/gfwlist -server=/.pengyulong.com/127.0.0.1#7913 -ipset=/.pengyulong.com/gfwlist -server=/.sgwritings.com/127.0.0.1#7913 -ipset=/.sgwritings.com/gfwlist -server=/.exblog.jp/127.0.0.1#7913 -ipset=/.exblog.jp/gfwlist -server=/.iownyour.biz/127.0.0.1#7913 -ipset=/.iownyour.biz/gfwlist -server=/.vietdaikynguyen.com/127.0.0.1#7913 -ipset=/.vietdaikynguyen.com/gfwlist -server=/.cobinhood.com/127.0.0.1#7913 -ipset=/.cobinhood.com/gfwlist -server=/.manicur4ik.ru/127.0.0.1#7913 -ipset=/.manicur4ik.ru/gfwlist -server=/.gatherproxy.com/127.0.0.1#7913 -ipset=/.gatherproxy.com/gfwlist -server=/.i-part.com.tw/127.0.0.1#7913 -ipset=/.i-part.com.tw/gfwlist -server=/.s-dragon.org/127.0.0.1#7913 -ipset=/.s-dragon.org/gfwlist -server=/.2-hand.info/127.0.0.1#7913 -ipset=/.2-hand.info/gfwlist -server=/.paper.li/127.0.0.1#7913 -ipset=/.paper.li/gfwlist -server=/.sexandsubmission.com/127.0.0.1#7913 -ipset=/.sexandsubmission.com/gfwlist -server=/.uukanshu.com/127.0.0.1#7913 -ipset=/.uukanshu.com/gfwlist -server=/.kompozer.net/127.0.0.1#7913 -ipset=/.kompozer.net/gfwlist -server=/.grangorz.org/127.0.0.1#7913 -ipset=/.grangorz.org/gfwlist -server=/.gaoming.net/127.0.0.1#7913 -ipset=/.gaoming.net/gfwlist -server=/.oiktv.com/127.0.0.1#7913 -ipset=/.oiktv.com/gfwlist -server=/.betfair.com/127.0.0.1#7913 -ipset=/.betfair.com/gfwlist -server=/.webbang.net/127.0.0.1#7913 -ipset=/.webbang.net/gfwlist -server=/.megarotic.com/127.0.0.1#7913 -ipset=/.megarotic.com/gfwlist -server=/.amnyemachen.org/127.0.0.1#7913 -ipset=/.amnyemachen.org/gfwlist -server=/.newchen.com/127.0.0.1#7913 -ipset=/.newchen.com/gfwlist -server=/.app.smartmailcloud.com/127.0.0.1#7913 -ipset=/.app.smartmailcloud.com/gfwlist -server=/.cyberghostvpn.com/127.0.0.1#7913 -ipset=/.cyberghostvpn.com/gfwlist -server=/.deepdiscount.com/127.0.0.1#7913 -ipset=/.deepdiscount.com/gfwlist -server=/.hkhrc.org.hk/127.0.0.1#7913 -ipset=/.hkhrc.org.hk/gfwlist -server=/.dynamicdns.biz/127.0.0.1#7913 -ipset=/.dynamicdns.biz/gfwlist -server=/.wolfax.com/127.0.0.1#7913 -ipset=/.wolfax.com/gfwlist -server=/.securityinabox.org/127.0.0.1#7913 -ipset=/.securityinabox.org/gfwlist -server=/.qtrac.eu/127.0.0.1#7913 -ipset=/.qtrac.eu/gfwlist -server=/.cn.dayabook.com/127.0.0.1#7913 -ipset=/.cn.dayabook.com/gfwlist -server=/.gfbv.de/127.0.0.1#7913 -ipset=/.gfbv.de/gfwlist -server=/.wikileaks.ch/127.0.0.1#7913 -ipset=/.wikileaks.ch/gfwlist -server=/.etowns.net/127.0.0.1#7913 -ipset=/.etowns.net/gfwlist -server=/.ofile.org/127.0.0.1#7913 -ipset=/.ofile.org/gfwlist -server=/.mysite.verizon.net/127.0.0.1#7913 -ipset=/.mysite.verizon.net/gfwlist -server=/.zhongguotese.net/127.0.0.1#7913 -ipset=/.zhongguotese.net/gfwlist -server=/.gcpnews.com/127.0.0.1#7913 -ipset=/.gcpnews.com/gfwlist -server=/.hanunyi.com/127.0.0.1#7913 -ipset=/.hanunyi.com/gfwlist -server=/.im.tv/127.0.0.1#7913 -ipset=/.im.tv/gfwlist -server=/.lsm.org/127.0.0.1#7913 -ipset=/.lsm.org/gfwlist -server=/.matters.news/127.0.0.1#7913 -ipset=/.matters.news/gfwlist -server=/.twitonmsn.com/127.0.0.1#7913 -ipset=/.twitonmsn.com/gfwlist -server=/.karmapa-teachings.org/127.0.0.1#7913 -ipset=/.karmapa-teachings.org/gfwlist -server=/.google.ru/127.0.0.1#7913 -ipset=/.google.ru/gfwlist -server=/.lushstories.com/127.0.0.1#7913 -ipset=/.lushstories.com/gfwlist -server=/.www.thechinastory.org/127.0.0.1#7913 -ipset=/.www.thechinastory.org/gfwlist -server=/.brucewang.net/127.0.0.1#7913 -ipset=/.brucewang.net/gfwlist -server=/.videobam.com/127.0.0.1#7913 -ipset=/.videobam.com/gfwlist -server=/.mmmca.com/127.0.0.1#7913 -ipset=/.mmmca.com/gfwlist -server=/.asianspiss.com/127.0.0.1#7913 -ipset=/.asianspiss.com/gfwlist -server=/.sugumiru18.com/127.0.0.1#7913 -ipset=/.sugumiru18.com/gfwlist -server=/.jdwsy.com/127.0.0.1#7913 -ipset=/.jdwsy.com/gfwlist -server=/.sex-11.com/127.0.0.1#7913 -ipset=/.sex-11.com/gfwlist -server=/.reddit.com/127.0.0.1#7913 -ipset=/.reddit.com/gfwlist -server=/.eroticsaloon.net/127.0.0.1#7913 -ipset=/.eroticsaloon.net/gfwlist -server=/.friends-of-tibet.org/127.0.0.1#7913 -ipset=/.friends-of-tibet.org/gfwlist -server=/.onmypc.net/127.0.0.1#7913 -ipset=/.onmypc.net/gfwlist -server=/.fengzhenghu.com/127.0.0.1#7913 -ipset=/.fengzhenghu.com/gfwlist -server=/.makemymood.com/127.0.0.1#7913 -ipset=/.makemymood.com/gfwlist -server=/.myreadingmanga.info/127.0.0.1#7913 -ipset=/.myreadingmanga.info/gfwlist -server=/.jjgirls.com/127.0.0.1#7913 -ipset=/.jjgirls.com/gfwlist -server=/.openvpn.net/127.0.0.1#7913 -ipset=/.openvpn.net/gfwlist -server=/.64wiki.com/127.0.0.1#7913 -ipset=/.64wiki.com/gfwlist -server=/.kinokuniya.com/127.0.0.1#7913 -ipset=/.kinokuniya.com/gfwlist -server=/.obutu.com/127.0.0.1#7913 -ipset=/.obutu.com/gfwlist -server=/.apk-dl.com/127.0.0.1#7913 -ipset=/.apk-dl.com/gfwlist -server=/.dizhuzhishang.com/127.0.0.1#7913 -ipset=/.dizhuzhishang.com/gfwlist -server=/.cldr.unicode.org/127.0.0.1#7913 -ipset=/.cldr.unicode.org/gfwlist -server=/.enewstree.com/127.0.0.1#7913 -ipset=/.enewstree.com/gfwlist -server=/.newscn.org/127.0.0.1#7913 -ipset=/.newscn.org/gfwlist -server=/.michaelmarketl.com/127.0.0.1#7913 -ipset=/.michaelmarketl.com/gfwlist -server=/.its.caltech.edu/127.0.0.1#7913 -ipset=/.its.caltech.edu/gfwlist -server=/.1e100.net/127.0.0.1#7913 -ipset=/.1e100.net/gfwlist -server=/.fhreports.net/127.0.0.1#7913 -ipset=/.fhreports.net/gfwlist -server=/.favstar.fm/127.0.0.1#7913 -ipset=/.favstar.fm/gfwlist -server=/.biantailajiao.in/127.0.0.1#7913 -ipset=/.biantailajiao.in/gfwlist -server=/.google.sm/127.0.0.1#7913 -ipset=/.google.sm/gfwlist -server=/.mofaxiehui.com/127.0.0.1#7913 -ipset=/.mofaxiehui.com/gfwlist -server=/.trimondi.de/127.0.0.1#7913 -ipset=/.trimondi.de/gfwlist -server=/.pornhost.com/127.0.0.1#7913 -ipset=/.pornhost.com/gfwlist -server=/.twitchcdn.net/127.0.0.1#7913 -ipset=/.twitchcdn.net/gfwlist -server=/.twelve.today/127.0.0.1#7913 -ipset=/.twelve.today/gfwlist -server=/.chinanewscenter.com/127.0.0.1#7913 -ipset=/.chinanewscenter.com/gfwlist -server=/.kaiyuan.de/127.0.0.1#7913 -ipset=/.kaiyuan.de/gfwlist -server=/.85st.com/127.0.0.1#7913 -ipset=/.85st.com/gfwlist -server=/.oyax.com/127.0.0.1#7913 -ipset=/.oyax.com/gfwlist -server=/.eic-av.com/127.0.0.1#7913 -ipset=/.eic-av.com/gfwlist -server=/.zacebook.com/127.0.0.1#7913 -ipset=/.zacebook.com/gfwlist -server=/.fanswong.com/127.0.0.1#7913 -ipset=/.fanswong.com/gfwlist -server=/.matsushimakaede.com/127.0.0.1#7913 -ipset=/.matsushimakaede.com/gfwlist -server=/.google.ci/127.0.0.1#7913 -ipset=/.google.ci/gfwlist -server=/.dzze.com/127.0.0.1#7913 -ipset=/.dzze.com/gfwlist -server=/.daum.net/127.0.0.1#7913 -ipset=/.daum.net/gfwlist -server=/.telegramdownload.com/127.0.0.1#7913 -ipset=/.telegramdownload.com/gfwlist -server=/.usacn.com/127.0.0.1#7913 -ipset=/.usacn.com/gfwlist -server=/.hacg.in/127.0.0.1#7913 -ipset=/.hacg.in/gfwlist -server=/.googlevideo.com/127.0.0.1#7913 -ipset=/.googlevideo.com/gfwlist -server=/.bbs.hanminzu.org/127.0.0.1#7913 -ipset=/.bbs.hanminzu.org/gfwlist -server=/.cdp1989.org/127.0.0.1#7913 -ipset=/.cdp1989.org/gfwlist -server=/.codeskulptor.org/127.0.0.1#7913 -ipset=/.codeskulptor.org/gfwlist -server=/.goldbet.com/127.0.0.1#7913 -ipset=/.goldbet.com/gfwlist -server=/.redditlist.com/127.0.0.1#7913 -ipset=/.redditlist.com/gfwlist -server=/.idiomconnection.com/127.0.0.1#7913 -ipset=/.idiomconnection.com/gfwlist -server=/.facebook.com/127.0.0.1#7913 -ipset=/.facebook.com/gfwlist -server=/.lighti.me/127.0.0.1#7913 -ipset=/.lighti.me/gfwlist -server=/.shireyishunjian.com/127.0.0.1#7913 -ipset=/.shireyishunjian.com/gfwlist -server=/.liangzhichuanmei.com/127.0.0.1#7913 -ipset=/.liangzhichuanmei.com/gfwlist -server=/.hxwk.org/127.0.0.1#7913 -ipset=/.hxwk.org/gfwlist -server=/.hellotxt.com/127.0.0.1#7913 -ipset=/.hellotxt.com/gfwlist -server=/.businessinsider.com/127.0.0.1#7913 -ipset=/.businessinsider.com/gfwlist -server=/.freetibetanheroes.org/127.0.0.1#7913 -ipset=/.freetibetanheroes.org/gfwlist -server=/.dns.google/127.0.0.1#7913 -ipset=/.dns.google/gfwlist -server=/.voachinese.com/127.0.0.1#7913 -ipset=/.voachinese.com/gfwlist -server=/.okk.tw/127.0.0.1#7913 -ipset=/.okk.tw/gfwlist -server=/.redditmedia.com/127.0.0.1#7913 -ipset=/.redditmedia.com/gfwlist -server=/.hkzone.org/127.0.0.1#7913 -ipset=/.hkzone.org/gfwlist -server=/.chinaaid.me/127.0.0.1#7913 -ipset=/.chinaaid.me/gfwlist -server=/.gaozhisheng.org/127.0.0.1#7913 -ipset=/.gaozhisheng.org/gfwlist -server=/.storm.mg/127.0.0.1#7913 -ipset=/.storm.mg/gfwlist -server=/.lsd.org.hk/127.0.0.1#7913 -ipset=/.lsd.org.hk/gfwlist -server=/.cccat.co/127.0.0.1#7913 -ipset=/.cccat.co/gfwlist -server=/.youtubecn.com/127.0.0.1#7913 -ipset=/.youtubecn.com/gfwlist -server=/.tibetoffice.org/127.0.0.1#7913 -ipset=/.tibetoffice.org/gfwlist -server=/.internetpopculture.com/127.0.0.1#7913 -ipset=/.internetpopculture.com/gfwlist -server=/.forum.palmislife.com/127.0.0.1#7913 -ipset=/.forum.palmislife.com/gfwlist -server=/.jkub.com/127.0.0.1#7913 -ipset=/.jkub.com/gfwlist -server=/.cutscenes.net/127.0.0.1#7913 -ipset=/.cutscenes.net/gfwlist -server=/.changp.com/127.0.0.1#7913 -ipset=/.changp.com/gfwlist -server=/.startuplivingchina.com/127.0.0.1#7913 -ipset=/.startuplivingchina.com/gfwlist -server=/.30boxes.com/127.0.0.1#7913 -ipset=/.30boxes.com/gfwlist -server=/.tn1.shemalez.com/127.0.0.1#7913 -ipset=/.tn1.shemalez.com/gfwlist -server=/.ecimg.tw/127.0.0.1#7913 -ipset=/.ecimg.tw/gfwlist -server=/.hkwcc.org.hk/127.0.0.1#7913 -ipset=/.hkwcc.org.hk/gfwlist -server=/.pioneer-worker.forums-free.com/127.0.0.1#7913 -ipset=/.pioneer-worker.forums-free.com/gfwlist -server=/.nytcn.me/127.0.0.1#7913 -ipset=/.nytcn.me/gfwlist -server=/.rfi.my/127.0.0.1#7913 -ipset=/.rfi.my/gfwlist -server=/.ftv.com.tw/127.0.0.1#7913 -ipset=/.ftv.com.tw/gfwlist -server=/.steganos.com/127.0.0.1#7913 -ipset=/.steganos.com/gfwlist -server=/.derekhsu.homeip.net/127.0.0.1#7913 -ipset=/.derekhsu.homeip.net/gfwlist -server=/.premeforwindows7.com/127.0.0.1#7913 -ipset=/.premeforwindows7.com/gfwlist -server=/.sneakme.net/127.0.0.1#7913 -ipset=/.sneakme.net/gfwlist -server=/.cynscribe.com/127.0.0.1#7913 -ipset=/.cynscribe.com/gfwlist -server=/.google.es/127.0.0.1#7913 -ipset=/.google.es/gfwlist -server=/.tangren.us/127.0.0.1#7913 -ipset=/.tangren.us/gfwlist -server=/.reuters.com/127.0.0.1#7913 -ipset=/.reuters.com/gfwlist -server=/.iptv.com.tw/127.0.0.1#7913 -ipset=/.iptv.com.tw/gfwlist -server=/.google.be/127.0.0.1#7913 -ipset=/.google.be/gfwlist -server=/.ct.org.tw/127.0.0.1#7913 -ipset=/.ct.org.tw/gfwlist -server=/.dynamicdns.me.uk/127.0.0.1#7913 -ipset=/.dynamicdns.me.uk/gfwlist -server=/.cipfg.org/127.0.0.1#7913 -ipset=/.cipfg.org/gfwlist -server=/.google.gr/127.0.0.1#7913 -ipset=/.google.gr/gfwlist -server=/.ruten.com.tw/127.0.0.1#7913 -ipset=/.ruten.com.tw/gfwlist -server=/.hwayue.org.tw/127.0.0.1#7913 -ipset=/.hwayue.org.tw/gfwlist -server=/.fuyu.org.tw/127.0.0.1#7913 -ipset=/.fuyu.org.tw/gfwlist -server=/.radicalparty.org/127.0.0.1#7913 -ipset=/.radicalparty.org/gfwlist -server=/.cdpeu.org/127.0.0.1#7913 -ipset=/.cdpeu.org/gfwlist -server=/.smith.edu/127.0.0.1#7913 -ipset=/.smith.edu/gfwlist -server=/.fangong.forums-free.com/127.0.0.1#7913 -ipset=/.fangong.forums-free.com/gfwlist -server=/.hung-ya.com/127.0.0.1#7913 -ipset=/.hung-ya.com/gfwlist -server=/.lama.com.tw/127.0.0.1#7913 -ipset=/.lama.com.tw/gfwlist -server=/.goldeneyevault.com/127.0.0.1#7913 -ipset=/.goldeneyevault.com/gfwlist -server=/.tw.mall.yahoo.com/127.0.0.1#7913 -ipset=/.tw.mall.yahoo.com/gfwlist -server=/.chinagate.com/127.0.0.1#7913 -ipset=/.chinagate.com/gfwlist -server=/.goagent.codeplex.com/127.0.0.1#7913 -ipset=/.goagent.codeplex.com/gfwlist -server=/.flipboard.com/127.0.0.1#7913 -ipset=/.flipboard.com/gfwlist -server=/.research.google/127.0.0.1#7913 -ipset=/.research.google/gfwlist -server=/.javfor.me/127.0.0.1#7913 -ipset=/.javfor.me/gfwlist -server=/.casatibet.org.mx/127.0.0.1#7913 -ipset=/.casatibet.org.mx/gfwlist -server=/.dns-dns.com/127.0.0.1#7913 -ipset=/.dns-dns.com/gfwlist -server=/.betvictor.com/127.0.0.1#7913 -ipset=/.betvictor.com/gfwlist -server=/.pbwiki.com/127.0.0.1#7913 -ipset=/.pbwiki.com/gfwlist -server=/.miniforum.org/127.0.0.1#7913 -ipset=/.miniforum.org/gfwlist -server=/.singfortibet.com/127.0.0.1#7913 -ipset=/.singfortibet.com/gfwlist -server=/.actimes.com.au/127.0.0.1#7913 -ipset=/.actimes.com.au/gfwlist -server=/.edoors.com/127.0.0.1#7913 -ipset=/.edoors.com/gfwlist -server=/.uyghurstudies.org/127.0.0.1#7913 -ipset=/.uyghurstudies.org/gfwlist -server=/.proxy1.xyz/127.0.0.1#7913 -ipset=/.proxy1.xyz/gfwlist -server=/.zhuichaguoji.org/127.0.0.1#7913 -ipset=/.zhuichaguoji.org/gfwlist -server=/.hkreporter.loved.hk/127.0.0.1#7913 -ipset=/.hkreporter.loved.hk/gfwlist -server=/.dit-inc.us/127.0.0.1#7913 -ipset=/.dit-inc.us/gfwlist -server=/.43110.cf/127.0.0.1#7913 -ipset=/.43110.cf/gfwlist -server=/.hmv.co.jp/127.0.0.1#7913 -ipset=/.hmv.co.jp/gfwlist -server=/.dfas.mil/127.0.0.1#7913 -ipset=/.dfas.mil/gfwlist -server=/.drmingxia.org/127.0.0.1#7913 -ipset=/.drmingxia.org/gfwlist -server=/.www.gmiddle.net/127.0.0.1#7913 -ipset=/.www.gmiddle.net/gfwlist -server=/.ivpn.net/127.0.0.1#7913 -ipset=/.ivpn.net/gfwlist -server=/.singtao.com/127.0.0.1#7913 -ipset=/.singtao.com/gfwlist -server=/.xijie.wordpress.com/127.0.0.1#7913 -ipset=/.xijie.wordpress.com/gfwlist -server=/.mayimayi.com/127.0.0.1#7913 -ipset=/.mayimayi.com/gfwlist -server=/.dalailamafoundation.org/127.0.0.1#7913 -ipset=/.dalailamafoundation.org/gfwlist -server=/.hornytrip.com/127.0.0.1#7913 -ipset=/.hornytrip.com/gfwlist -server=/.pinterest.co.uk/127.0.0.1#7913 -ipset=/.pinterest.co.uk/gfwlist -server=/.sysresccd.org/127.0.0.1#7913 -ipset=/.sysresccd.org/gfwlist -server=/.himemix.com/127.0.0.1#7913 -ipset=/.himemix.com/gfwlist -server=/.eastturkistan-gov.org/127.0.0.1#7913 -ipset=/.eastturkistan-gov.org/gfwlist -server=/.flitto.com/127.0.0.1#7913 -ipset=/.flitto.com/gfwlist -server=/.blip.tv/127.0.0.1#7913 -ipset=/.blip.tv/gfwlist -server=/.cafepress.com/127.0.0.1#7913 -ipset=/.cafepress.com/gfwlist -server=/.duping.net/127.0.0.1#7913 -ipset=/.duping.net/gfwlist -server=/.hkbookcity.com/127.0.0.1#7913 -ipset=/.hkbookcity.com/gfwlist -server=/.gopetition.com/127.0.0.1#7913 -ipset=/.gopetition.com/gfwlist -server=/.twilightsex.com/127.0.0.1#7913 -ipset=/.twilightsex.com/gfwlist -server=/.news.singtao.ca/127.0.0.1#7913 -ipset=/.news.singtao.ca/gfwlist -server=/.finchvpn.com/127.0.0.1#7913 -ipset=/.finchvpn.com/gfwlist -server=/.circlethebayfortibet.org/127.0.0.1#7913 -ipset=/.circlethebayfortibet.org/gfwlist -server=/.phapluan.org/127.0.0.1#7913 -ipset=/.phapluan.org/gfwlist -server=/.archive.org/127.0.0.1#7913 -ipset=/.archive.org/gfwlist -server=/.maildns.xyz/127.0.0.1#7913 -ipset=/.maildns.xyz/gfwlist -server=/.hkbf.org/127.0.0.1#7913 -ipset=/.hkbf.org/gfwlist -server=/.tubeislam.com/127.0.0.1#7913 -ipset=/.tubeislam.com/gfwlist -server=/.humanrightsbriefing.org/127.0.0.1#7913 -ipset=/.humanrightsbriefing.org/gfwlist -server=/.ritter.vg/127.0.0.1#7913 -ipset=/.ritter.vg/gfwlist -server=/.andfaraway.net/127.0.0.1#7913 -ipset=/.andfaraway.net/gfwlist -server=/.sidelinesnews.com/127.0.0.1#7913 -ipset=/.sidelinesnews.com/gfwlist -server=/.twaitter.com/127.0.0.1#7913 -ipset=/.twaitter.com/gfwlist -server=/.riseup.net/127.0.0.1#7913 -ipset=/.riseup.net/gfwlist -server=/.sports.williamhill.com/127.0.0.1#7913 -ipset=/.sports.williamhill.com/gfwlist -server=/.cam4.com/127.0.0.1#7913 -ipset=/.cam4.com/gfwlist -server=/.book.com.tw/127.0.0.1#7913 -ipset=/.book.com.tw/gfwlist -server=/.zh.pokerstrategy.com/127.0.0.1#7913 -ipset=/.zh.pokerstrategy.com/gfwlist -server=/.meyul.com/127.0.0.1#7913 -ipset=/.meyul.com/gfwlist -server=/.fanhaodang.com/127.0.0.1#7913 -ipset=/.fanhaodang.com/gfwlist -server=/.www.aolnews.com/127.0.0.1#7913 -ipset=/.www.aolnews.com/gfwlist -server=/.perfectgirls.net/127.0.0.1#7913 -ipset=/.perfectgirls.net/gfwlist -server=/.wiki.gamerp.jp/127.0.0.1#7913 -ipset=/.wiki.gamerp.jp/gfwlist -server=/.laod.cn/127.0.0.1#7913 -ipset=/.laod.cn/gfwlist -server=/.vpnforgame.net/127.0.0.1#7913 -ipset=/.vpnforgame.net/gfwlist -server=/.d2bay.com/127.0.0.1#7913 -ipset=/.d2bay.com/gfwlist -server=/.gsp.target.com/127.0.0.1#7913 -ipset=/.gsp.target.com/gfwlist -server=/.podictionary.com/127.0.0.1#7913 -ipset=/.podictionary.com/gfwlist -server=/.sun1911.com/127.0.0.1#7913 -ipset=/.sun1911.com/gfwlist -server=/.twilog.org/127.0.0.1#7913 -ipset=/.twilog.org/gfwlist -server=/.pct.org.tw/127.0.0.1#7913 -ipset=/.pct.org.tw/gfwlist -server=/.surrenderat20.net/127.0.0.1#7913 -ipset=/.surrenderat20.net/gfwlist -server=/.66.ca/127.0.0.1#7913 -ipset=/.66.ca/gfwlist -server=/.embr.in/127.0.0.1#7913 -ipset=/.embr.in/gfwlist -server=/.ibiblio.org/127.0.0.1#7913 -ipset=/.ibiblio.org/gfwlist -server=/.manchukuo.net/127.0.0.1#7913 -ipset=/.manchukuo.net/gfwlist -server=/.staticflickr.com/127.0.0.1#7913 -ipset=/.staticflickr.com/gfwlist -server=/.vevo.com/127.0.0.1#7913 -ipset=/.vevo.com/gfwlist -server=/.whichav.com/127.0.0.1#7913 -ipset=/.whichav.com/gfwlist -server=/.goregrish.com/127.0.0.1#7913 -ipset=/.goregrish.com/gfwlist -server=/.pinterest.jp/127.0.0.1#7913 -ipset=/.pinterest.jp/gfwlist -server=/.karmapa.org/127.0.0.1#7913 -ipset=/.karmapa.org/gfwlist -server=/.load.to/127.0.0.1#7913 -ipset=/.load.to/gfwlist -server=/.spotflux.com/127.0.0.1#7913 -ipset=/.spotflux.com/gfwlist -server=/.elpais.com/127.0.0.1#7913 -ipset=/.elpais.com/gfwlist -server=/.blog.calibre-ebook.com/127.0.0.1#7913 -ipset=/.blog.calibre-ebook.com/gfwlist -server=/.nationsonline.org/127.0.0.1#7913 -ipset=/.nationsonline.org/gfwlist -server=/.dojin.com/127.0.0.1#7913 -ipset=/.dojin.com/gfwlist -server=/.line-scdn.net/127.0.0.1#7913 -ipset=/.line-scdn.net/gfwlist -server=/.feifeiss.com/127.0.0.1#7913 -ipset=/.feifeiss.com/gfwlist -server=/.netbirds.com/127.0.0.1#7913 -ipset=/.netbirds.com/gfwlist -server=/.getsocialscope.com/127.0.0.1#7913 -ipset=/.getsocialscope.com/gfwlist -server=/.google.co.kr/127.0.0.1#7913 -ipset=/.google.co.kr/gfwlist -server=/.2.bahamut.com.tw/127.0.0.1#7913 -ipset=/.2.bahamut.com.tw/gfwlist -server=/.porntube.com/127.0.0.1#7913 -ipset=/.porntube.com/gfwlist -server=/.cn.freeones.com/127.0.0.1#7913 -ipset=/.cn.freeones.com/gfwlist -server=/.angelfire.com/127.0.0.1#7913 -ipset=/.angelfire.com/gfwlist -server=/.tuo8.fit/127.0.0.1#7913 -ipset=/.tuo8.fit/gfwlist -server=/.nvtongzhisheng.org/127.0.0.1#7913 -ipset=/.nvtongzhisheng.org/gfwlist -server=/.wiredbytes.com/127.0.0.1#7913 -ipset=/.wiredbytes.com/gfwlist -server=/.freedl.org/127.0.0.1#7913 -ipset=/.freedl.org/gfwlist -server=/.coolncute.com/127.0.0.1#7913 -ipset=/.coolncute.com/gfwlist -server=/.21pron.com/127.0.0.1#7913 -ipset=/.21pron.com/gfwlist -server=/.edicypages.com/127.0.0.1#7913 -ipset=/.edicypages.com/gfwlist -server=/.sharecool.org/127.0.0.1#7913 -ipset=/.sharecool.org/gfwlist -server=/.gr8name.biz/127.0.0.1#7913 -ipset=/.gr8name.biz/gfwlist -server=/.jyxf.net/127.0.0.1#7913 -ipset=/.jyxf.net/gfwlist -server=/.youporn.com/127.0.0.1#7913 -ipset=/.youporn.com/gfwlist -server=/.googlecode.com/127.0.0.1#7913 -ipset=/.googlecode.com/gfwlist -server=/.4mydomain.com/127.0.0.1#7913 -ipset=/.4mydomain.com/gfwlist -server=/.showbiz.omy.sg/127.0.0.1#7913 -ipset=/.showbiz.omy.sg/gfwlist -server=/.nbtvpn.com/127.0.0.1#7913 -ipset=/.nbtvpn.com/gfwlist -server=/.jigong1024.com/127.0.0.1#7913 -ipset=/.jigong1024.com/gfwlist -server=/.darktech.org/127.0.0.1#7913 -ipset=/.darktech.org/gfwlist -server=/.issuu.com/127.0.0.1#7913 -ipset=/.issuu.com/gfwlist -server=/.faluninfo.net/127.0.0.1#7913 -ipset=/.faluninfo.net/gfwlist -server=/.ddns.name/127.0.0.1#7913 -ipset=/.ddns.name/gfwlist -server=/.zhanbin.net/127.0.0.1#7913 -ipset=/.zhanbin.net/gfwlist -server=/.newsdetox.ca/127.0.0.1#7913 -ipset=/.newsdetox.ca/gfwlist -server=/.fullerconsideration.com/127.0.0.1#7913 -ipset=/.fullerconsideration.com/gfwlist -server=/.amazon.co.jp/127.0.0.1#7913 -ipset=/.amazon.co.jp/gfwlist -server=/.shkspr.mobi/127.0.0.1#7913 -ipset=/.shkspr.mobi/gfwlist -server=/.ecministry.net/127.0.0.1#7913 -ipset=/.ecministry.net/gfwlist -server=/.brazzers.com/127.0.0.1#7913 -ipset=/.brazzers.com/gfwlist -server=/.okex.com/127.0.0.1#7913 -ipset=/.okex.com/gfwlist -server=/.mm-cg.com/127.0.0.1#7913 -ipset=/.mm-cg.com/gfwlist -server=/.usno.navy.mil/127.0.0.1#7913 -ipset=/.usno.navy.mil/gfwlist -server=/.ucdc1998.org/127.0.0.1#7913 -ipset=/.ucdc1998.org/gfwlist -server=/.justtristan.com/127.0.0.1#7913 -ipset=/.justtristan.com/gfwlist -server=/.kagyunews.com.hk/127.0.0.1#7913 -ipset=/.kagyunews.com.hk/gfwlist -server=/.youversion.com/127.0.0.1#7913 -ipset=/.youversion.com/gfwlist -server=/.huffingtonpost.com/127.0.0.1#7913 -ipset=/.huffingtonpost.com/gfwlist -server=/.funf.tw/127.0.0.1#7913 -ipset=/.funf.tw/gfwlist -server=/.myftp.name/127.0.0.1#7913 -ipset=/.myftp.name/gfwlist -server=/.webrush.net/127.0.0.1#7913 -ipset=/.webrush.net/gfwlist -server=/.tgstat.com/127.0.0.1#7913 -ipset=/.tgstat.com/gfwlist -server=/.pandapow.co/127.0.0.1#7913 -ipset=/.pandapow.co/gfwlist -server=/.bdsmvideos.net/127.0.0.1#7913 -ipset=/.bdsmvideos.net/gfwlist -server=/.googlechrome.github.io/127.0.0.1#7913 -ipset=/.googlechrome.github.io/gfwlist -server=/.creativelab5.com/127.0.0.1#7913 -ipset=/.creativelab5.com/gfwlist -server=/.juliepost.com/127.0.0.1#7913 -ipset=/.juliepost.com/gfwlist -server=/.norbulingka.org/127.0.0.1#7913 -ipset=/.norbulingka.org/gfwlist -server=/.kobo.com/127.0.0.1#7913 -ipset=/.kobo.com/gfwlist -server=/.crisisresponse.google/127.0.0.1#7913 -ipset=/.crisisresponse.google/gfwlist -server=/.hdlt.me/127.0.0.1#7913 -ipset=/.hdlt.me/gfwlist -server=/.shutterstock.com/127.0.0.1#7913 -ipset=/.shutterstock.com/gfwlist -server=/.samair.ru/127.0.0.1#7913 -ipset=/.samair.ru/gfwlist -server=/.1bao.org/127.0.0.1#7913 -ipset=/.1bao.org/gfwlist -server=/.boxunclub.com/127.0.0.1#7913 -ipset=/.boxunclub.com/gfwlist -server=/.twbbs.net.tw/127.0.0.1#7913 -ipset=/.twbbs.net.tw/gfwlist -server=/.blog.workflow.is/127.0.0.1#7913 -ipset=/.blog.workflow.is/gfwlist -server=/.sunta.com.tw/127.0.0.1#7913 -ipset=/.sunta.com.tw/gfwlist -server=/.ac.jiruan.net/127.0.0.1#7913 -ipset=/.ac.jiruan.net/gfwlist -server=/.sonidodelaesperanza.org/127.0.0.1#7913 -ipset=/.sonidodelaesperanza.org/gfwlist -server=/.allervpn.com/127.0.0.1#7913 -ipset=/.allervpn.com/gfwlist -server=/.blackvpn.com/127.0.0.1#7913 -ipset=/.blackvpn.com/gfwlist -server=/.link-o-rama.com/127.0.0.1#7913 -ipset=/.link-o-rama.com/gfwlist -server=/.nordstromrack.com/127.0.0.1#7913 -ipset=/.nordstromrack.com/gfwlist -server=/.purepdf.com/127.0.0.1#7913 -ipset=/.purepdf.com/gfwlist -server=/.soul-plus.net/127.0.0.1#7913 -ipset=/.soul-plus.net/gfwlist -server=/.thywords.com.tw/127.0.0.1#7913 -ipset=/.thywords.com.tw/gfwlist -server=/.cochina.co/127.0.0.1#7913 -ipset=/.cochina.co/gfwlist -server=/.tuzaijidi.com/127.0.0.1#7913 -ipset=/.tuzaijidi.com/gfwlist -server=/.prosiben.de/127.0.0.1#7913 -ipset=/.prosiben.de/gfwlist -server=/.gumroad.com/127.0.0.1#7913 -ipset=/.gumroad.com/gfwlist -server=/.forum.cyberctm.com/127.0.0.1#7913 -ipset=/.forum.cyberctm.com/gfwlist -server=/.twtkr.com/127.0.0.1#7913 -ipset=/.twtkr.com/gfwlist -server=/.feedx.net/127.0.0.1#7913 -ipset=/.feedx.net/gfwlist -server=/.mefeedia.com/127.0.0.1#7913 -ipset=/.mefeedia.com/gfwlist -server=/.c100tibet.org/127.0.0.1#7913 -ipset=/.c100tibet.org/gfwlist -server=/.diigo.com/127.0.0.1#7913 -ipset=/.diigo.com/gfwlist -server=/.yeelou.com/127.0.0.1#7913 -ipset=/.yeelou.com/gfwlist -server=/.hongzhi.li/127.0.0.1#7913 -ipset=/.hongzhi.li/gfwlist -server=/.omgili.com/127.0.0.1#7913 -ipset=/.omgili.com/gfwlist -server=/.atgfw.org/127.0.0.1#7913 -ipset=/.atgfw.org/gfwlist -server=/.peoplebookcafe.com/127.0.0.1#7913 -ipset=/.peoplebookcafe.com/gfwlist -server=/.ocreampies.com/127.0.0.1#7913 -ipset=/.ocreampies.com/gfwlist -server=/.api.linksalpha.com/127.0.0.1#7913 -ipset=/.api.linksalpha.com/gfwlist -server=/.kiwi.kz/127.0.0.1#7913 -ipset=/.kiwi.kz/gfwlist -server=/.lastfm.es/127.0.0.1#7913 -ipset=/.lastfm.es/gfwlist -server=/.dyndns-ip.com/127.0.0.1#7913 -ipset=/.dyndns-ip.com/gfwlist -server=/.kebrum.com/127.0.0.1#7913 -ipset=/.kebrum.com/gfwlist -server=/.justfreevpn.com/127.0.0.1#7913 -ipset=/.justfreevpn.com/gfwlist -server=/.nuuvem.com/127.0.0.1#7913 -ipset=/.nuuvem.com/gfwlist -server=/.12vpn.com/127.0.0.1#7913 -ipset=/.12vpn.com/gfwlist -server=/.yuanzhengtang.org/127.0.0.1#7913 -ipset=/.yuanzhengtang.org/gfwlist -server=/.certificate.revocationcheck.com/127.0.0.1#7913 -ipset=/.certificate.revocationcheck.com/gfwlist -server=/.teamamericany.com/127.0.0.1#7913 -ipset=/.teamamericany.com/gfwlist -server=/.w.wiki/127.0.0.1#7913 -ipset=/.w.wiki/gfwlist -server=/.mingpaonews.com/127.0.0.1#7913 -ipset=/.mingpaonews.com/gfwlist -server=/.goodreaders.com/127.0.0.1#7913 -ipset=/.goodreaders.com/gfwlist -server=/.roodo.com/127.0.0.1#7913 -ipset=/.roodo.com/gfwlist -server=/.windowsphoneme.com/127.0.0.1#7913 -ipset=/.windowsphoneme.com/gfwlist -server=/.dorjeshugden.com/127.0.0.1#7913 -ipset=/.dorjeshugden.com/gfwlist -server=/.ixxx.com/127.0.0.1#7913 -ipset=/.ixxx.com/gfwlist -server=/.islamhouse.com/127.0.0.1#7913 -ipset=/.islamhouse.com/gfwlist -server=/.cn.thegay.com/127.0.0.1#7913 -ipset=/.cn.thegay.com/gfwlist -server=/.themoviedb.org/127.0.0.1#7913 -ipset=/.themoviedb.org/gfwlist -server=/.ssr.tools/127.0.0.1#7913 -ipset=/.ssr.tools/gfwlist -server=/.xmovies.com/127.0.0.1#7913 -ipset=/.xmovies.com/gfwlist -server=/.pandora.com/127.0.0.1#7913 -ipset=/.pandora.com/gfwlist -server=/.hardsextube.com/127.0.0.1#7913 -ipset=/.hardsextube.com/gfwlist -server=/.tianti.io/127.0.0.1#7913 -ipset=/.tianti.io/gfwlist -server=/.hootsuite.com/127.0.0.1#7913 -ipset=/.hootsuite.com/gfwlist -server=/.myfreepaysite.com/127.0.0.1#7913 -ipset=/.myfreepaysite.com/gfwlist -server=/.localdomain.ws/127.0.0.1#7913 -ipset=/.localdomain.ws/gfwlist -server=/.hacker.org/127.0.0.1#7913 -ipset=/.hacker.org/gfwlist -server=/.wango.org/127.0.0.1#7913 -ipset=/.wango.org/gfwlist -server=/.shadowsocks.org/127.0.0.1#7913 -ipset=/.shadowsocks.org/gfwlist -server=/.sejie.com/127.0.0.1#7913 -ipset=/.sejie.com/gfwlist -server=/.deepmind.com/127.0.0.1#7913 -ipset=/.deepmind.com/gfwlist -server=/.www.oxid.it/127.0.0.1#7913 -ipset=/.www.oxid.it/gfwlist -server=/.navyreserve.navy.mil/127.0.0.1#7913 -ipset=/.navyreserve.navy.mil/gfwlist -server=/.otto.de/127.0.0.1#7913 -ipset=/.otto.de/gfwlist -server=/.falundafa-dc.org/127.0.0.1#7913 -ipset=/.falundafa-dc.org/gfwlist -server=/.static01.nyt.com/127.0.0.1#7913 -ipset=/.static01.nyt.com/gfwlist -server=/.networkedblogs.com/127.0.0.1#7913 -ipset=/.networkedblogs.com/gfwlist -server=/.from-sd.com/127.0.0.1#7913 -ipset=/.from-sd.com/gfwlist -server=/.1984bbs.com/127.0.0.1#7913 -ipset=/.1984bbs.com/gfwlist -server=/.rukor.org/127.0.0.1#7913 -ipset=/.rukor.org/gfwlist -server=/.doub.io/127.0.0.1#7913 -ipset=/.doub.io/gfwlist -server=/.av-e-body.com/127.0.0.1#7913 -ipset=/.av-e-body.com/gfwlist -server=/.hurriyet.com.tr/127.0.0.1#7913 -ipset=/.hurriyet.com.tr/gfwlist -server=/.cellulo.info/127.0.0.1#7913 -ipset=/.cellulo.info/gfwlist -server=/.cbtc.org.hk/127.0.0.1#7913 -ipset=/.cbtc.org.hk/gfwlist -server=/.fangmincn.org/127.0.0.1#7913 -ipset=/.fangmincn.org/gfwlist -server=/.hautelook.com/127.0.0.1#7913 -ipset=/.hautelook.com/gfwlist -server=/.chinamule.com/127.0.0.1#7913 -ipset=/.chinamule.com/gfwlist -server=/.keontech.net/127.0.0.1#7913 -ipset=/.keontech.net/gfwlist -server=/.mingpaosf.com/127.0.0.1#7913 -ipset=/.mingpaosf.com/gfwlist -server=/.hkupop.hku.hk/127.0.0.1#7913 -ipset=/.hkupop.hku.hk/gfwlist -server=/.sesawe.net/127.0.0.1#7913 -ipset=/.sesawe.net/gfwlist -server=/.pcstore.com.tw/127.0.0.1#7913 -ipset=/.pcstore.com.tw/gfwlist -server=/.initiativesforchina.org/127.0.0.1#7913 -ipset=/.initiativesforchina.org/gfwlist -server=/.xiezhua.com/127.0.0.1#7913 -ipset=/.xiezhua.com/gfwlist -server=/.gaytube.com/127.0.0.1#7913 -ipset=/.gaytube.com/gfwlist -server=/.dstk.dk/127.0.0.1#7913 -ipset=/.dstk.dk/gfwlist -server=/.network54.com/127.0.0.1#7913 -ipset=/.network54.com/gfwlist -server=/.cuiweiping.net/127.0.0.1#7913 -ipset=/.cuiweiping.net/gfwlist -server=/.nukistream.com/127.0.0.1#7913 -ipset=/.nukistream.com/gfwlist -server=/.unification.org.tw/127.0.0.1#7913 -ipset=/.unification.org.tw/gfwlist -server=/.usmgtcg.ning.com/127.0.0.1#7913 -ipset=/.usmgtcg.ning.com/gfwlist -server=/.ticket.com.tw/127.0.0.1#7913 -ipset=/.ticket.com.tw/gfwlist -server=/.toutyrater.github.io/127.0.0.1#7913 -ipset=/.toutyrater.github.io/gfwlist -server=/.azerbaycan.tv/127.0.0.1#7913 -ipset=/.azerbaycan.tv/gfwlist -server=/.gifree.com/127.0.0.1#7913 -ipset=/.gifree.com/gfwlist -server=/.tw.jiepang.com/127.0.0.1#7913 -ipset=/.tw.jiepang.com/gfwlist -server=/.meetup.com/127.0.0.1#7913 -ipset=/.meetup.com/gfwlist -server=/.btku.me/127.0.0.1#7913 -ipset=/.btku.me/gfwlist -server=/.moneyhome.biz/127.0.0.1#7913 -ipset=/.moneyhome.biz/gfwlist -server=/.e-traderland.net/127.0.0.1#7913 -ipset=/.e-traderland.net/gfwlist -server=/.rapidmoviez.com/127.0.0.1#7913 -ipset=/.rapidmoviez.com/gfwlist -server=/.gutteruncensored.com/127.0.0.1#7913 -ipset=/.gutteruncensored.com/gfwlist -server=/.feeds.fileforum.com/127.0.0.1#7913 -ipset=/.feeds.fileforum.com/gfwlist -server=/.hahaxixi.github.io/127.0.0.1#7913 -ipset=/.hahaxixi.github.io/gfwlist -server=/.delicious.com/127.0.0.1#7913 -ipset=/.delicious.com/gfwlist -server=/.pandora.tv/127.0.0.1#7913 -ipset=/.pandora.tv/gfwlist -server=/.media.nu.nl/127.0.0.1#7913 -ipset=/.media.nu.nl/gfwlist -server=/.taipeisociety.org/127.0.0.1#7913 -ipset=/.taipeisociety.org/gfwlist -server=/.ironpython.net/127.0.0.1#7913 -ipset=/.ironpython.net/gfwlist -server=/.suroot.com/127.0.0.1#7913 -ipset=/.suroot.com/gfwlist -server=/.juhuaren.com/127.0.0.1#7913 -ipset=/.juhuaren.com/gfwlist -server=/.izlesem.org/127.0.0.1#7913 -ipset=/.izlesem.org/gfwlist -server=/.igvita.com/127.0.0.1#7913 -ipset=/.igvita.com/gfwlist -server=/.fofg.org/127.0.0.1#7913 -ipset=/.fofg.org/gfwlist -server=/.photofocus.com/127.0.0.1#7913 -ipset=/.photofocus.com/gfwlist -server=/.maskedip.com/127.0.0.1#7913 -ipset=/.maskedip.com/gfwlist -server=/.bbsfeed.com/127.0.0.1#7913 -ipset=/.bbsfeed.com/gfwlist -server=/.vermonttibet.org/127.0.0.1#7913 -ipset=/.vermonttibet.org/gfwlist -server=/.hola.com/127.0.0.1#7913 -ipset=/.hola.com/gfwlist -server=/.tiandixing.org/127.0.0.1#7913 -ipset=/.tiandixing.org/gfwlist -server=/.gmodules.com/127.0.0.1#7913 -ipset=/.gmodules.com/gfwlist -server=/.pts.org.tw/127.0.0.1#7913 -ipset=/.pts.org.tw/gfwlist -server=/.iask.ca/127.0.0.1#7913 -ipset=/.iask.ca/gfwlist -server=/.polymerhk.com/127.0.0.1#7913 -ipset=/.polymerhk.com/gfwlist -server=/.chinesedaily.com/127.0.0.1#7913 -ipset=/.chinesedaily.com/gfwlist -server=/.cl.d0z.net/127.0.0.1#7913 -ipset=/.cl.d0z.net/gfwlist -server=/.nownews.com/127.0.0.1#7913 -ipset=/.nownews.com/gfwlist -server=/.thetibetmuseum.org/127.0.0.1#7913 -ipset=/.thetibetmuseum.org/gfwlist -server=/.freemoren.com/127.0.0.1#7913 -ipset=/.freemoren.com/gfwlist -server=/.exmormon.org/127.0.0.1#7913 -ipset=/.exmormon.org/gfwlist -server=/.ironsocket.com/127.0.0.1#7913 -ipset=/.ironsocket.com/gfwlist -server=/.tuo8.space/127.0.0.1#7913 -ipset=/.tuo8.space/gfwlist -server=/.k-doujin.net/127.0.0.1#7913 -ipset=/.k-doujin.net/gfwlist -server=/.8z1.net/127.0.0.1#7913 -ipset=/.8z1.net/gfwlist -server=/.anontext.com/127.0.0.1#7913 -ipset=/.anontext.com/gfwlist -server=/.nytco.com/127.0.0.1#7913 -ipset=/.nytco.com/gfwlist -server=/.toytractorshow.com/127.0.0.1#7913 -ipset=/.toytractorshow.com/gfwlist -server=/.flnet.org/127.0.0.1#7913 -ipset=/.flnet.org/gfwlist -server=/.gamejolt.com/127.0.0.1#7913 -ipset=/.gamejolt.com/gfwlist -server=/.eulam.com/127.0.0.1#7913 -ipset=/.eulam.com/gfwlist -server=/.teck.in/127.0.0.1#7913 -ipset=/.teck.in/gfwlist -server=/.dupola.net/127.0.0.1#7913 -ipset=/.dupola.net/gfwlist -server=/.turansam.org/127.0.0.1#7913 -ipset=/.turansam.org/gfwlist -server=/.liu-xiaobo.org/127.0.0.1#7913 -ipset=/.liu-xiaobo.org/gfwlist -server=/.cochina.org/127.0.0.1#7913 -ipset=/.cochina.org/gfwlist -server=/.bloglovin.com/127.0.0.1#7913 -ipset=/.bloglovin.com/gfwlist -server=/.greatfire.org/127.0.0.1#7913 -ipset=/.greatfire.org/gfwlist -server=/.namgyal.org/127.0.0.1#7913 -ipset=/.namgyal.org/gfwlist -server=/.books.com.tw/127.0.0.1#7913 -ipset=/.books.com.tw/gfwlist -server=/.motor4ik.ru/127.0.0.1#7913 -ipset=/.motor4ik.ru/gfwlist -server=/.berlintwitterwall.com/127.0.0.1#7913 -ipset=/.berlintwitterwall.com/gfwlist -server=/.cn.giganews.com/127.0.0.1#7913 -ipset=/.cn.giganews.com/gfwlist -server=/.dollf.com/127.0.0.1#7913 -ipset=/.dollf.com/gfwlist -server=/.myanniu.com/127.0.0.1#7913 -ipset=/.myanniu.com/gfwlist -server=/.joymiihub.com/127.0.0.1#7913 -ipset=/.joymiihub.com/gfwlist -server=/.bbs.cantonese.asia/127.0.0.1#7913 -ipset=/.bbs.cantonese.asia/gfwlist -server=/.javmoo.com/127.0.0.1#7913 -ipset=/.javmoo.com/gfwlist -server=/.wufafangwen.com/127.0.0.1#7913 -ipset=/.wufafangwen.com/gfwlist -server=/.twistar.cc/127.0.0.1#7913 -ipset=/.twistar.cc/gfwlist -server=/.qoos.com/127.0.0.1#7913 -ipset=/.qoos.com/gfwlist -server=/.af.mil/127.0.0.1#7913 -ipset=/.af.mil/gfwlist -server=/.farwestchina.com/127.0.0.1#7913 -ipset=/.farwestchina.com/gfwlist -server=/.5isotoi5.org/127.0.0.1#7913 -ipset=/.5isotoi5.org/gfwlist -server=/.rangzen.net/127.0.0.1#7913 -ipset=/.rangzen.net/gfwlist -server=/.chinalawandpolicy.com/127.0.0.1#7913 -ipset=/.chinalawandpolicy.com/gfwlist -server=/.aamacau.com/127.0.0.1#7913 -ipset=/.aamacau.com/gfwlist -server=/.longtermly.net/127.0.0.1#7913 -ipset=/.longtermly.net/gfwlist -server=/.hacken.cc/127.0.0.1#7913 -ipset=/.hacken.cc/gfwlist -server=/.tibetsites.com/127.0.0.1#7913 -ipset=/.tibetsites.com/gfwlist -server=/.pinterest.at/127.0.0.1#7913 -ipset=/.pinterest.at/gfwlist -server=/.blogtd.org/127.0.0.1#7913 -ipset=/.blogtd.org/gfwlist -server=/.belamionline.com/127.0.0.1#7913 -ipset=/.belamionline.com/gfwlist -server=/.findmespot.com/127.0.0.1#7913 -ipset=/.findmespot.com/gfwlist -server=/.china21.org/127.0.0.1#7913 -ipset=/.china21.org/gfwlist -server=/.iask.bz/127.0.0.1#7913 -ipset=/.iask.bz/gfwlist -server=/.netflix.com/127.0.0.1#7913 -ipset=/.netflix.com/gfwlist -server=/.qpoe.com/127.0.0.1#7913 -ipset=/.qpoe.com/gfwlist -server=/.www.antd.org/127.0.0.1#7913 -ipset=/.www.antd.org/gfwlist -server=/.twitterrific.com/127.0.0.1#7913 -ipset=/.twitterrific.com/gfwlist -server=/.hyperrate.com/127.0.0.1#7913 -ipset=/.hyperrate.com/gfwlist -server=/.savetibet.nl/127.0.0.1#7913 -ipset=/.savetibet.nl/gfwlist -server=/.liaowangxizang.net/127.0.0.1#7913 -ipset=/.liaowangxizang.net/gfwlist -server=/.wikaba.com/127.0.0.1#7913 -ipset=/.wikaba.com/gfwlist -server=/.puuko.com/127.0.0.1#7913 -ipset=/.puuko.com/gfwlist -server=/.blog.pathtosharepoint.com/127.0.0.1#7913 -ipset=/.blog.pathtosharepoint.com/gfwlist -server=/.dyndns.pro/127.0.0.1#7913 -ipset=/.dyndns.pro/gfwlist -server=/.uyghur-j.org/127.0.0.1#7913 -ipset=/.uyghur-j.org/gfwlist -server=/.minghuiyw.wordpress.com/127.0.0.1#7913 -ipset=/.minghuiyw.wordpress.com/gfwlist -server=/.plus.codes/127.0.0.1#7913 -ipset=/.plus.codes/gfwlist -server=/.freeproxylists.net/127.0.0.1#7913 -ipset=/.freeproxylists.net/gfwlist -server=/.freeoz.org/127.0.0.1#7913 -ipset=/.freeoz.org/gfwlist -server=/.crchina.org/127.0.0.1#7913 -ipset=/.crchina.org/gfwlist -server=/.mobileways.de/127.0.0.1#7913 -ipset=/.mobileways.de/gfwlist -server=/.blog.de/127.0.0.1#7913 -ipset=/.blog.de/gfwlist -server=/.allgravure.com/127.0.0.1#7913 -ipset=/.allgravure.com/gfwlist -server=/.nlfreevpn.com/127.0.0.1#7913 -ipset=/.nlfreevpn.com/gfwlist -server=/.sinomontreal.ca/127.0.0.1#7913 -ipset=/.sinomontreal.ca/gfwlist -server=/.meridian-trust.org/127.0.0.1#7913 -ipset=/.meridian-trust.org/gfwlist -server=/.news.tvbs.com.tw/127.0.0.1#7913 -ipset=/.news.tvbs.com.tw/gfwlist -server=/.mycnnews.com/127.0.0.1#7913 -ipset=/.mycnnews.com/gfwlist -server=/.moviefap.com/127.0.0.1#7913 -ipset=/.moviefap.com/gfwlist -server=/.raremovie.cc/127.0.0.1#7913 -ipset=/.raremovie.cc/gfwlist -server=/.jinroukong.com/127.0.0.1#7913 -ipset=/.jinroukong.com/gfwlist -server=/.brainyquote.com/127.0.0.1#7913 -ipset=/.brainyquote.com/gfwlist -server=/.d1b183sg0nvnuh.cloudfront.net/127.0.0.1#7913 -ipset=/.d1b183sg0nvnuh.cloudfront.net/gfwlist -server=/.1989report.hkja.org.hk/127.0.0.1#7913 -ipset=/.1989report.hkja.org.hk/gfwlist -server=/.shipcamouflage.com/127.0.0.1#7913 -ipset=/.shipcamouflage.com/gfwlist -server=/.cuhkacs.org/127.0.0.1#7913 -ipset=/.cuhkacs.org/gfwlist -server=/.underwoodammo.com/127.0.0.1#7913 -ipset=/.underwoodammo.com/gfwlist -server=/.cacnw.com/127.0.0.1#7913 -ipset=/.cacnw.com/gfwlist -server=/.ebtcbank.com/127.0.0.1#7913 -ipset=/.ebtcbank.com/gfwlist -server=/.tineye.com/127.0.0.1#7913 -ipset=/.tineye.com/gfwlist -server=/.linkideo.com/127.0.0.1#7913 -ipset=/.linkideo.com/gfwlist -server=/.dcard.tw/127.0.0.1#7913 -ipset=/.dcard.tw/gfwlist -server=/.nf.id.au/127.0.0.1#7913 -ipset=/.nf.id.au/gfwlist -server=/.blogs.icerocket.com/127.0.0.1#7913 -ipset=/.blogs.icerocket.com/gfwlist -server=/.internetfreedom.org/127.0.0.1#7913 -ipset=/.internetfreedom.org/gfwlist -server=/.duckduckgo-owned-server.yahoo.net/127.0.0.1#7913 -ipset=/.duckduckgo-owned-server.yahoo.net/gfwlist -server=/.mh4u.org/127.0.0.1#7913 -ipset=/.mh4u.org/gfwlist -server=/.doubmirror.cf/127.0.0.1#7913 -ipset=/.doubmirror.cf/gfwlist -server=/.huaxia-news.com/127.0.0.1#7913 -ipset=/.huaxia-news.com/gfwlist -server=/.handcraftedsoftware.org/127.0.0.1#7913 -ipset=/.handcraftedsoftware.org/gfwlist -server=/.danbooru.donmai.us/127.0.0.1#7913 -ipset=/.danbooru.donmai.us/gfwlist -server=/.martau.com/127.0.0.1#7913 -ipset=/.martau.com/gfwlist -server=/.e-zone.com.hk/127.0.0.1#7913 -ipset=/.e-zone.com.hk/gfwlist -server=/.azerimix.com/127.0.0.1#7913 -ipset=/.azerimix.com/gfwlist -server=/.forum4hk.com/127.0.0.1#7913 -ipset=/.forum4hk.com/gfwlist -server=/.pds.nasa.gov/127.0.0.1#7913 -ipset=/.pds.nasa.gov/gfwlist -server=/.googleanalytics.com/127.0.0.1#7913 -ipset=/.googleanalytics.com/gfwlist -server=/.epochtimes.de/127.0.0.1#7913 -ipset=/.epochtimes.de/gfwlist -server=/.giga-web.jp/127.0.0.1#7913 -ipset=/.giga-web.jp/gfwlist -server=/.ganges.com/127.0.0.1#7913 -ipset=/.ganges.com/gfwlist -server=/.facesofnyfw.com/127.0.0.1#7913 -ipset=/.facesofnyfw.com/gfwlist -server=/.changsa.net/127.0.0.1#7913 -ipset=/.changsa.net/gfwlist -server=/.barton.de/127.0.0.1#7913 -ipset=/.barton.de/gfwlist -server=/.tibetancommunity.org/127.0.0.1#7913 -ipset=/.tibetancommunity.org/gfwlist -server=/.ctao.org/127.0.0.1#7913 -ipset=/.ctao.org/gfwlist -server=/.iredmail.org/127.0.0.1#7913 -ipset=/.iredmail.org/gfwlist -server=/.art4tibet1998.org/127.0.0.1#7913 -ipset=/.art4tibet1998.org/gfwlist -server=/.dajusha.baywords.com/127.0.0.1#7913 -ipset=/.dajusha.baywords.com/gfwlist -server=/.mymoe.moe/127.0.0.1#7913 -ipset=/.mymoe.moe/gfwlist -server=/.tiktok.com/127.0.0.1#7913 -ipset=/.tiktok.com/gfwlist -server=/.blog.youxu.info/127.0.0.1#7913 -ipset=/.blog.youxu.info/gfwlist -server=/.oopsforum.com/127.0.0.1#7913 -ipset=/.oopsforum.com/gfwlist -server=/.po2b.com/127.0.0.1#7913 -ipset=/.po2b.com/gfwlist -server=/.golang.org/127.0.0.1#7913 -ipset=/.golang.org/gfwlist -server=/.toypark.in/127.0.0.1#7913 -ipset=/.toypark.in/gfwlist -server=/.mrbasic.com/127.0.0.1#7913 -ipset=/.mrbasic.com/gfwlist -server=/.firstfivefollowers.com/127.0.0.1#7913 -ipset=/.firstfivefollowers.com/gfwlist -server=/.tianyantong.org.cn/127.0.0.1#7913 -ipset=/.tianyantong.org.cn/gfwlist -server=/.geekerhome.com/127.0.0.1#7913 -ipset=/.geekerhome.com/gfwlist -server=/.bbs.brockbbs.com/127.0.0.1#7913 -ipset=/.bbs.brockbbs.com/gfwlist -server=/.news.sina.com.tw/127.0.0.1#7913 -ipset=/.news.sina.com.tw/gfwlist -server=/.hotgoo.com/127.0.0.1#7913 -ipset=/.hotgoo.com/gfwlist -server=/.hexxeh.net/127.0.0.1#7913 -ipset=/.hexxeh.net/gfwlist -server=/.uhdwallpapers.org/127.0.0.1#7913 -ipset=/.uhdwallpapers.org/gfwlist -server=/.s-cute.com/127.0.0.1#7913 -ipset=/.s-cute.com/gfwlist -server=/.wav.tv/127.0.0.1#7913 -ipset=/.wav.tv/gfwlist -server=/.nighost.org/127.0.0.1#7913 -ipset=/.nighost.org/gfwlist -server=/.wlcnew.jigsy.com/127.0.0.1#7913 -ipset=/.wlcnew.jigsy.com/gfwlist -server=/.duga.jp/127.0.0.1#7913 -ipset=/.duga.jp/gfwlist -server=/.otzo.com/127.0.0.1#7913 -ipset=/.otzo.com/gfwlist -server=/.edmontonservice.com/127.0.0.1#7913 -ipset=/.edmontonservice.com/gfwlist -server=/.2000fun.com/127.0.0.1#7913 -ipset=/.2000fun.com/gfwlist -server=/.twipple.jp/127.0.0.1#7913 -ipset=/.twipple.jp/gfwlist -server=/.adcex.com/127.0.0.1#7913 -ipset=/.adcex.com/gfwlist -server=/.sino-monthly.com/127.0.0.1#7913 -ipset=/.sino-monthly.com/gfwlist -server=/.12vpn.net/127.0.0.1#7913 -ipset=/.12vpn.net/gfwlist -server=/.lamayeshe.com/127.0.0.1#7913 -ipset=/.lamayeshe.com/gfwlist -server=/.gate.io/127.0.0.1#7913 -ipset=/.gate.io/gfwlist -server=/.lookpic.com/127.0.0.1#7913 -ipset=/.lookpic.com/gfwlist -server=/.minzhuzhongguo.org/127.0.0.1#7913 -ipset=/.minzhuzhongguo.org/gfwlist -server=/.wukangrui.net/127.0.0.1#7913 -ipset=/.wukangrui.net/gfwlist -server=/.hkci.org.hk/127.0.0.1#7913 -ipset=/.hkci.org.hk/gfwlist -server=/.radioaustralia.net.au/127.0.0.1#7913 -ipset=/.radioaustralia.net.au/gfwlist -server=/.livingstream.com/127.0.0.1#7913 -ipset=/.livingstream.com/gfwlist -server=/.epochtimes-bg.com/127.0.0.1#7913 -ipset=/.epochtimes-bg.com/gfwlist -server=/.tchrd.org/127.0.0.1#7913 -ipset=/.tchrd.org/gfwlist -server=/.udn.com.tw/127.0.0.1#7913 -ipset=/.udn.com.tw/gfwlist -server=/.postadult.com/127.0.0.1#7913 -ipset=/.postadult.com/gfwlist -server=/.tiananmenduizhi.com/127.0.0.1#7913 -ipset=/.tiananmenduizhi.com/gfwlist -server=/.zkaip.com/127.0.0.1#7913 -ipset=/.zkaip.com/gfwlist -server=/.magazines.sina.com.tw/127.0.0.1#7913 -ipset=/.magazines.sina.com.tw/gfwlist -server=/.piraattilahti.org/127.0.0.1#7913 -ipset=/.piraattilahti.org/gfwlist -server=/.blog.ranxiang.com/127.0.0.1#7913 -ipset=/.blog.ranxiang.com/gfwlist -server=/.t.me/127.0.0.1#7913 -ipset=/.t.me/gfwlist -server=/.cartoonmovement.com/127.0.0.1#7913 -ipset=/.cartoonmovement.com/gfwlist -server=/.riku.me/127.0.0.1#7913 -ipset=/.riku.me/gfwlist -server=/.demo.opera-mini.net/127.0.0.1#7913 -ipset=/.demo.opera-mini.net/gfwlist -server=/.facebook.net/127.0.0.1#7913 -ipset=/.facebook.net/gfwlist -server=/.hk.rd.yahoo.com/127.0.0.1#7913 -ipset=/.hk.rd.yahoo.com/gfwlist -server=/.sorting-algorithms.com/127.0.0.1#7913 -ipset=/.sorting-algorithms.com/gfwlist -server=/.pornhubdeutsch.net/127.0.0.1#7913 -ipset=/.pornhubdeutsch.net/gfwlist -server=/.goodtv.com.tw/127.0.0.1#7913 -ipset=/.goodtv.com.tw/gfwlist -server=/.logbot.net/127.0.0.1#7913 -ipset=/.logbot.net/gfwlist -server=/.killwall.com/127.0.0.1#7913 -ipset=/.killwall.com/gfwlist -server=/.googledrive.com/127.0.0.1#7913 -ipset=/.googledrive.com/gfwlist -server=/.pornhub.com/127.0.0.1#7913 -ipset=/.pornhub.com/gfwlist -server=/.jeanyim.com/127.0.0.1#7913 -ipset=/.jeanyim.com/gfwlist -server=/.coingi.com/127.0.0.1#7913 -ipset=/.coingi.com/gfwlist -server=/.mychinese.news/127.0.0.1#7913 -ipset=/.mychinese.news/gfwlist -server=/.cablegatesearch.net/127.0.0.1#7913 -ipset=/.cablegatesearch.net/gfwlist -server=/.hongmeimei.com/127.0.0.1#7913 -ipset=/.hongmeimei.com/gfwlist -server=/.winwhispers.info/127.0.0.1#7913 -ipset=/.winwhispers.info/gfwlist -server=/.rtalabel.org/127.0.0.1#7913 -ipset=/.rtalabel.org/gfwlist -server=/.falungong.de/127.0.0.1#7913 -ipset=/.falungong.de/gfwlist -server=/.laqingdan.net/127.0.0.1#7913 -ipset=/.laqingdan.net/gfwlist -server=/.thetrotskymovie.com/127.0.0.1#7913 -ipset=/.thetrotskymovie.com/gfwlist -server=/.gamer2-cds.cdn.hinet.net/127.0.0.1#7913 -ipset=/.gamer2-cds.cdn.hinet.net/gfwlist -server=/.freeviewmovies.com/127.0.0.1#7913 -ipset=/.freeviewmovies.com/gfwlist -server=/.woopie.tv/127.0.0.1#7913 -ipset=/.woopie.tv/gfwlist -server=/.himalayan-foundation.org/127.0.0.1#7913 -ipset=/.himalayan-foundation.org/gfwlist -server=/.3a5a.com/127.0.0.1#7913 -ipset=/.3a5a.com/gfwlist -server=/.kalachakralugano.org/127.0.0.1#7913 -ipset=/.kalachakralugano.org/gfwlist -server=/.geocities.jp/127.0.0.1#7913 -ipset=/.geocities.jp/gfwlist -server=/.giantessnight.com/127.0.0.1#7913 -ipset=/.giantessnight.com/gfwlist -server=/.secretsline.biz/127.0.0.1#7913 -ipset=/.secretsline.biz/gfwlist -server=/.zeronet.io/127.0.0.1#7913 -ipset=/.zeronet.io/gfwlist -server=/.bwsj.hk/127.0.0.1#7913 -ipset=/.bwsj.hk/gfwlist -server=/.site90.net/127.0.0.1#7913 -ipset=/.site90.net/gfwlist -server=/.heeact.edu.tw/127.0.0.1#7913 -ipset=/.heeact.edu.tw/gfwlist -server=/.wiki.keso.cn/127.0.0.1#7913 -ipset=/.wiki.keso.cn/gfwlist -server=/.shambhalasun.com/127.0.0.1#7913 -ipset=/.shambhalasun.com/gfwlist -server=/.bbs.kimy.com.tw/127.0.0.1#7913 -ipset=/.bbs.kimy.com.tw/gfwlist -server=/.pdetails.com/127.0.0.1#7913 -ipset=/.pdetails.com/gfwlist -server=/.vpninja.net/127.0.0.1#7913 -ipset=/.vpninja.net/gfwlist -server=/.cn.fmnnow.com/127.0.0.1#7913 -ipset=/.cn.fmnnow.com/gfwlist -server=/.bbsdigest.com/127.0.0.1#7913 -ipset=/.bbsdigest.com/gfwlist -server=/.www2.ohchr.org/127.0.0.1#7913 -ipset=/.www2.ohchr.org/gfwlist -server=/.appledaily.com.tw/127.0.0.1#7913 -ipset=/.appledaily.com.tw/gfwlist -server=/.anonymizer.com/127.0.0.1#7913 -ipset=/.anonymizer.com/gfwlist -server=/.apps.evozi.com/127.0.0.1#7913 -ipset=/.apps.evozi.com/gfwlist -server=/.cchere.com/127.0.0.1#7913 -ipset=/.cchere.com/gfwlist -server=/.tibetanliberation.org/127.0.0.1#7913 -ipset=/.tibetanliberation.org/gfwlist -server=/.tistory.com/127.0.0.1#7913 -ipset=/.tistory.com/gfwlist -server=/.banana-vpn.com/127.0.0.1#7913 -ipset=/.banana-vpn.com/gfwlist -server=/.army.mil/127.0.0.1#7913 -ipset=/.army.mil/gfwlist -server=/.windscribe.com/127.0.0.1#7913 -ipset=/.windscribe.com/gfwlist -server=/.stoporganharvesting.org/127.0.0.1#7913 -ipset=/.stoporganharvesting.org/gfwlist -server=/.gfgold.com.hk/127.0.0.1#7913 -ipset=/.gfgold.com.hk/gfwlist -server=/.dw-world.de/127.0.0.1#7913 -ipset=/.dw-world.de/gfwlist -server=/.fc2china.com/127.0.0.1#7913 -ipset=/.fc2china.com/gfwlist -server=/.s1heng.com/127.0.0.1#7913 -ipset=/.s1heng.com/gfwlist -server=/.helpster.de/127.0.0.1#7913 -ipset=/.helpster.de/gfwlist -server=/.player.fm/127.0.0.1#7913 -ipset=/.player.fm/gfwlist -server=/.kurashsultan.com/127.0.0.1#7913 -ipset=/.kurashsultan.com/gfwlist -server=/.softsmirror.cf/127.0.0.1#7913 -ipset=/.softsmirror.cf/gfwlist -server=/.trickip.net/127.0.0.1#7913 -ipset=/.trickip.net/gfwlist -server=/.pullfolio.com/127.0.0.1#7913 -ipset=/.pullfolio.com/gfwlist -server=/.porn2.com/127.0.0.1#7913 -ipset=/.porn2.com/gfwlist -server=/.heix.pp.ru/127.0.0.1#7913 -ipset=/.heix.pp.ru/gfwlist -server=/.truthontour.org/127.0.0.1#7913 -ipset=/.truthontour.org/gfwlist -server=/.images-gaytube.com/127.0.0.1#7913 -ipset=/.images-gaytube.com/gfwlist -server=/.tuo8.blue/127.0.0.1#7913 -ipset=/.tuo8.blue/gfwlist -server=/.tibetwrites.org/127.0.0.1#7913 -ipset=/.tibetwrites.org/gfwlist -server=/.dontmovetochina.com/127.0.0.1#7913 -ipset=/.dontmovetochina.com/gfwlist -server=/.haoel.github.io/127.0.0.1#7913 -ipset=/.haoel.github.io/gfwlist -server=/.unblocksit.es/127.0.0.1#7913 -ipset=/.unblocksit.es/gfwlist -server=/.techviz.net/127.0.0.1#7913 -ipset=/.techviz.net/gfwlist -server=/.duckduckgo.com/127.0.0.1#7913 -ipset=/.duckduckgo.com/gfwlist -server=/.bwgyhw.com/127.0.0.1#7913 -ipset=/.bwgyhw.com/gfwlist -server=/.gunsamerica.com/127.0.0.1#7913 -ipset=/.gunsamerica.com/gfwlist -server=/.m.plixi.com/127.0.0.1#7913 -ipset=/.m.plixi.com/gfwlist -server=/.soundofhope.org/127.0.0.1#7913 -ipset=/.soundofhope.org/gfwlist -server=/.ieasy5.com/127.0.0.1#7913 -ipset=/.ieasy5.com/gfwlist -server=/.fw.cm/127.0.0.1#7913 -ipset=/.fw.cm/gfwlist -server=/.highpeakspureearth.com/127.0.0.1#7913 -ipset=/.highpeakspureearth.com/gfwlist -server=/.exchristian.hk/127.0.0.1#7913 -ipset=/.exchristian.hk/gfwlist -server=/.liangyou.net/127.0.0.1#7913 -ipset=/.liangyou.net/gfwlist -server=/.kurtmunger.com/127.0.0.1#7913 -ipset=/.kurtmunger.com/gfwlist -server=/.xgmyd.com/127.0.0.1#7913 -ipset=/.xgmyd.com/gfwlist -server=/.oyghan.com/127.0.0.1#7913 -ipset=/.oyghan.com/gfwlist -server=/.sodatea.github.io/127.0.0.1#7913 -ipset=/.sodatea.github.io/gfwlist -server=/.djorz.com/127.0.0.1#7913 -ipset=/.djorz.com/gfwlist -server=/.geekheart.info/127.0.0.1#7913 -ipset=/.geekheart.info/gfwlist -server=/.ss.levyhsu.com/127.0.0.1#7913 -ipset=/.ss.levyhsu.com/gfwlist -server=/.freehongkong.org/127.0.0.1#7913 -ipset=/.freehongkong.org/gfwlist -server=/.cherrysave.com/127.0.0.1#7913 -ipset=/.cherrysave.com/gfwlist -server=/.1998cdp.org/127.0.0.1#7913 -ipset=/.1998cdp.org/gfwlist -server=/.wpoforum.com/127.0.0.1#7913 -ipset=/.wpoforum.com/gfwlist -server=/.baixing.me/127.0.0.1#7913 -ipset=/.baixing.me/gfwlist -server=/.ns2.name/127.0.0.1#7913 -ipset=/.ns2.name/gfwlist -server=/.kingstone.com.tw/127.0.0.1#7913 -ipset=/.kingstone.com.tw/gfwlist -server=/.blog.fizzik.com/127.0.0.1#7913 -ipset=/.blog.fizzik.com/gfwlist -server=/.btdigg.org/127.0.0.1#7913 -ipset=/.btdigg.org/gfwlist -server=/.apkmonk.com/127.0.0.1#7913 -ipset=/.apkmonk.com/gfwlist -server=/.nrk.no/127.0.0.1#7913 -ipset=/.nrk.no/gfwlist -server=/.secretchina.com/127.0.0.1#7913 -ipset=/.secretchina.com/gfwlist -server=/.daylife.com/127.0.0.1#7913 -ipset=/.daylife.com/gfwlist -server=/.thehots.info/127.0.0.1#7913 -ipset=/.thehots.info/gfwlist -server=/.nzchinese.net.nz/127.0.0.1#7913 -ipset=/.nzchinese.net.nz/gfwlist -server=/.api.tenor.com/127.0.0.1#7913 -ipset=/.api.tenor.com/gfwlist -server=/.earthcam.com/127.0.0.1#7913 -ipset=/.earthcam.com/gfwlist -server=/.thinkingtaiwan.com/127.0.0.1#7913 -ipset=/.thinkingtaiwan.com/gfwlist -server=/.lsmchinese.org/127.0.0.1#7913 -ipset=/.lsmchinese.org/gfwlist -server=/.ventureswell.com/127.0.0.1#7913 -ipset=/.ventureswell.com/gfwlist -server=/.picturedip.com/127.0.0.1#7913 -ipset=/.picturedip.com/gfwlist -server=/.fuckgfw.org/127.0.0.1#7913 -ipset=/.fuckgfw.org/gfwlist -server=/.faith100.org/127.0.0.1#7913 -ipset=/.faith100.org/gfwlist -server=/.plm.org.hk/127.0.0.1#7913 -ipset=/.plm.org.hk/gfwlist -server=/.greatfirewall.biz/127.0.0.1#7913 -ipset=/.greatfirewall.biz/gfwlist -server=/.greatroc.tw/127.0.0.1#7913 -ipset=/.greatroc.tw/gfwlist -server=/.idouga.com/127.0.0.1#7913 -ipset=/.idouga.com/gfwlist -server=/.a248.e.akamai.net/127.0.0.1#7913 -ipset=/.a248.e.akamai.net/gfwlist -server=/.demosisto.hk/127.0.0.1#7913 -ipset=/.demosisto.hk/gfwlist -server=/.isgreat.org/127.0.0.1#7913 -ipset=/.isgreat.org/gfwlist -server=/.xfm.pp.ru/127.0.0.1#7913 -ipset=/.xfm.pp.ru/gfwlist -server=/.news.yahoo.com/127.0.0.1#7913 -ipset=/.news.yahoo.com/gfwlist -server=/.wwitv.com/127.0.0.1#7913 -ipset=/.wwitv.com/gfwlist -server=/.ihao.org/127.0.0.1#7913 -ipset=/.ihao.org/gfwlist -server=/.zannel.com/127.0.0.1#7913 -ipset=/.zannel.com/gfwlist -server=/.gnci.org.hk/127.0.0.1#7913 -ipset=/.gnci.org.hk/gfwlist -server=/.forum.tvb.com/127.0.0.1#7913 -ipset=/.forum.tvb.com/gfwlist -server=/.savethedate.foo/127.0.0.1#7913 -ipset=/.savethedate.foo/gfwlist -server=/.voagd.com/127.0.0.1#7913 -ipset=/.voagd.com/gfwlist -server=/.furl.net/127.0.0.1#7913 -ipset=/.furl.net/gfwlist -server=/.nanyangpost.com/127.0.0.1#7913 -ipset=/.nanyangpost.com/gfwlist -server=/.mobypicture.com/127.0.0.1#7913 -ipset=/.mobypicture.com/gfwlist -server=/.lovetvshow.com/127.0.0.1#7913 -ipset=/.lovetvshow.com/gfwlist -server=/.imagezilla.net/127.0.0.1#7913 -ipset=/.imagezilla.net/gfwlist -server=/.hidemy.name/127.0.0.1#7913 -ipset=/.hidemy.name/gfwlist -server=/.conoha.jp/127.0.0.1#7913 -ipset=/.conoha.jp/gfwlist -server=/.pin-cong.com/127.0.0.1#7913 -ipset=/.pin-cong.com/gfwlist -server=/.dnscrypt.org/127.0.0.1#7913 -ipset=/.dnscrypt.org/gfwlist -server=/.ftpserver.biz/127.0.0.1#7913 -ipset=/.ftpserver.biz/gfwlist -server=/.renminbao.com/127.0.0.1#7913 -ipset=/.renminbao.com/gfwlist -server=/.uchicago.edu/127.0.0.1#7913 -ipset=/.uchicago.edu/gfwlist -server=/.disqus.com/127.0.0.1#7913 -ipset=/.disqus.com/gfwlist -server=/.yasni.co.uk/127.0.0.1#7913 -ipset=/.yasni.co.uk/gfwlist -server=/.xlfmwz.info/127.0.0.1#7913 -ipset=/.xlfmwz.info/gfwlist -server=/.upcoming.yahoo.com/127.0.0.1#7913 -ipset=/.upcoming.yahoo.com/gfwlist -server=/.anpopo.com/127.0.0.1#7913 -ipset=/.anpopo.com/gfwlist -server=/.nowtorrents.com/127.0.0.1#7913 -ipset=/.nowtorrents.com/gfwlist -server=/.nutaku.net/127.0.0.1#7913 -ipset=/.nutaku.net/gfwlist -server=/.99cn.info/127.0.0.1#7913 -ipset=/.99cn.info/gfwlist -server=/.ancsconf.org/127.0.0.1#7913 -ipset=/.ancsconf.org/gfwlist -server=/.ctitv.com.tw/127.0.0.1#7913 -ipset=/.ctitv.com.tw/gfwlist -server=/.rosechina.net/127.0.0.1#7913 -ipset=/.rosechina.net/gfwlist -server=/.dictionary.goo.ne.jp/127.0.0.1#7913 -ipset=/.dictionary.goo.ne.jp/gfwlist -server=/.myactimes.com/127.0.0.1#7913 -ipset=/.myactimes.com/gfwlist -server=/.blog.fuckgfw233.org/127.0.0.1#7913 -ipset=/.blog.fuckgfw233.org/gfwlist -server=/.fulue.com/127.0.0.1#7913 -ipset=/.fulue.com/gfwlist -server=/.advanscene.com/127.0.0.1#7913 -ipset=/.advanscene.com/gfwlist -server=/.goproxing.net/127.0.0.1#7913 -ipset=/.goproxing.net/gfwlist -server=/.mamingzhe.com/127.0.0.1#7913 -ipset=/.mamingzhe.com/gfwlist -server=/.dafoh.org/127.0.0.1#7913 -ipset=/.dafoh.org/gfwlist -server=/.eastturkistancc.org/127.0.0.1#7913 -ipset=/.eastturkistancc.org/gfwlist -server=/.1mobile.tw/127.0.0.1#7913 -ipset=/.1mobile.tw/gfwlist -server=/.mixero.com/127.0.0.1#7913 -ipset=/.mixero.com/gfwlist -server=/.boobstagram.com/127.0.0.1#7913 -ipset=/.boobstagram.com/gfwlist -server=/.expecthim.com/127.0.0.1#7913 -ipset=/.expecthim.com/gfwlist -server=/.google.co.uk/127.0.0.1#7913 -ipset=/.google.co.uk/gfwlist -server=/.rainbowplan.org/127.0.0.1#7913 -ipset=/.rainbowplan.org/gfwlist -server=/.twit2d.com/127.0.0.1#7913 -ipset=/.twit2d.com/gfwlist -server=/.apkdler.com/127.0.0.1#7913 -ipset=/.apkdler.com/gfwlist -server=/.dailymail.co.uk/127.0.0.1#7913 -ipset=/.dailymail.co.uk/gfwlist -server=/.uvwxyz.xyz/127.0.0.1#7913 -ipset=/.uvwxyz.xyz/gfwlist -server=/.g-area.org/127.0.0.1#7913 -ipset=/.g-area.org/gfwlist -server=/.x1949x.com/127.0.0.1#7913 -ipset=/.x1949x.com/gfwlist -server=/.newlandmagazine.com.au/127.0.0.1#7913 -ipset=/.newlandmagazine.com.au/gfwlist -server=/.svsfx.com/127.0.0.1#7913 -ipset=/.svsfx.com/gfwlist -server=/.eraysoft.com.tr/127.0.0.1#7913 -ipset=/.eraysoft.com.tr/gfwlist -server=/.lihkg.com/127.0.0.1#7913 -ipset=/.lihkg.com/gfwlist -server=/.avmoo.pw/127.0.0.1#7913 -ipset=/.avmoo.pw/gfwlist -server=/.buugaa.com/127.0.0.1#7913 -ipset=/.buugaa.com/gfwlist -server=/.suyangg.com/127.0.0.1#7913 -ipset=/.suyangg.com/gfwlist -server=/.7capture.com/127.0.0.1#7913 -ipset=/.7capture.com/gfwlist -server=/.sspanel.net/127.0.0.1#7913 -ipset=/.sspanel.net/gfwlist -server=/.3d-game.com/127.0.0.1#7913 -ipset=/.3d-game.com/gfwlist -server=/.nuexpo.com/127.0.0.1#7913 -ipset=/.nuexpo.com/gfwlist -server=/.my-private-network.co.uk/127.0.0.1#7913 -ipset=/.my-private-network.co.uk/gfwlist -server=/.forum.baby-kingdom.com/127.0.0.1#7913 -ipset=/.forum.baby-kingdom.com/gfwlist -server=/.17t17p.com/127.0.0.1#7913 -ipset=/.17t17p.com/gfwlist -server=/.nakido.com/127.0.0.1#7913 -ipset=/.nakido.com/gfwlist -server=/.pornhd.com/127.0.0.1#7913 -ipset=/.pornhd.com/gfwlist -server=/.chenshan20042005.wordpress.com/127.0.0.1#7913 -ipset=/.chenshan20042005.wordpress.com/gfwlist -server=/.vaticannews.va/127.0.0.1#7913 -ipset=/.vaticannews.va/gfwlist -server=/.networktunnel.net/127.0.0.1#7913 -ipset=/.networktunnel.net/gfwlist -server=/.admob.com/127.0.0.1#7913 -ipset=/.admob.com/gfwlist -server=/.dtic.mil/127.0.0.1#7913 -ipset=/.dtic.mil/gfwlist -server=/.gooday.xyz/127.0.0.1#7913 -ipset=/.gooday.xyz/gfwlist -server=/.orientaldaily.com.my/127.0.0.1#7913 -ipset=/.orientaldaily.com.my/gfwlist -server=/.cleansite.biz/127.0.0.1#7913 -ipset=/.cleansite.biz/gfwlist -server=/.anobii.com/127.0.0.1#7913 -ipset=/.anobii.com/gfwlist -server=/.busu.org/127.0.0.1#7913 -ipset=/.busu.org/gfwlist -server=/.videomega.tv/127.0.0.1#7913 -ipset=/.videomega.tv/gfwlist -server=/.xxuz.com/127.0.0.1#7913 -ipset=/.xxuz.com/gfwlist -server=/.kik.com/127.0.0.1#7913 -ipset=/.kik.com/gfwlist -server=/.ismalltits.com/127.0.0.1#7913 -ipset=/.ismalltits.com/gfwlist -server=/.flecheinthepeche.fr/127.0.0.1#7913 -ipset=/.flecheinthepeche.fr/gfwlist -server=/.gvt3.com/127.0.0.1#7913 -ipset=/.gvt3.com/gfwlist -server=/.appshopper.com/127.0.0.1#7913 -ipset=/.appshopper.com/gfwlist -server=/.tbsn.org/127.0.0.1#7913 -ipset=/.tbsn.org/gfwlist -server=/.pcij.org/127.0.0.1#7913 -ipset=/.pcij.org/gfwlist -server=/.linkuswell.com/127.0.0.1#7913 -ipset=/.linkuswell.com/gfwlist -server=/.sosreader.com/127.0.0.1#7913 -ipset=/.sosreader.com/gfwlist -server=/.eksisozluk.com/127.0.0.1#7913 -ipset=/.eksisozluk.com/gfwlist -server=/.qiangwaikan.com/127.0.0.1#7913 -ipset=/.qiangwaikan.com/gfwlist -server=/.anonymise.us/127.0.0.1#7913 -ipset=/.anonymise.us/gfwlist -server=/.joachims.org/127.0.0.1#7913 -ipset=/.joachims.org/gfwlist -server=/.justpaste.it/127.0.0.1#7913 -ipset=/.justpaste.it/gfwlist -server=/.blogspot.hk/127.0.0.1#7913 -ipset=/.blogspot.hk/gfwlist -server=/.icij.org/127.0.0.1#7913 -ipset=/.icij.org/gfwlist -server=/.matainja.com/127.0.0.1#7913 -ipset=/.matainja.com/gfwlist -server=/.astrill.com/127.0.0.1#7913 -ipset=/.astrill.com/gfwlist -server=/.rangzen.com/127.0.0.1#7913 -ipset=/.rangzen.com/gfwlist -server=/.toonel.net/127.0.0.1#7913 -ipset=/.toonel.net/gfwlist -server=/.flgjustice.org/127.0.0.1#7913 -ipset=/.flgjustice.org/gfwlist -server=/.hkjc.com/127.0.0.1#7913 -ipset=/.hkjc.com/gfwlist -server=/.twtr2src.ogaoga.org/127.0.0.1#7913 -ipset=/.twtr2src.ogaoga.org/gfwlist -server=/.avmo.pw/127.0.0.1#7913 -ipset=/.avmo.pw/gfwlist -server=/.greatfire.us7.list-manage.com/127.0.0.1#7913 -ipset=/.greatfire.us7.list-manage.com/gfwlist -server=/.wikimedia.org/127.0.0.1#7913 -ipset=/.wikimedia.org/gfwlist -server=/.cms.gov/127.0.0.1#7913 -ipset=/.cms.gov/gfwlist -server=/.xn--czq75pvv1aj5c.org/127.0.0.1#7913 -ipset=/.xn--czq75pvv1aj5c.org/gfwlist -server=/.pixiv.net/127.0.0.1#7913 -ipset=/.pixiv.net/gfwlist -server=/.jma.go.jp/127.0.0.1#7913 -ipset=/.jma.go.jp/gfwlist -server=/.getgom.com/127.0.0.1#7913 -ipset=/.getgom.com/gfwlist -server=/.www.lamenhu.com/127.0.0.1#7913 -ipset=/.www.lamenhu.com/gfwlist -server=/.onmypc.biz/127.0.0.1#7913 -ipset=/.onmypc.biz/gfwlist -server=/.rixcloud.com/127.0.0.1#7913 -ipset=/.rixcloud.com/gfwlist -server=/.ub0.cc/127.0.0.1#7913 -ipset=/.ub0.cc/gfwlist -server=/.steemit.com/127.0.0.1#7913 -ipset=/.steemit.com/gfwlist -server=/.lsxszzg.com/127.0.0.1#7913 -ipset=/.lsxszzg.com/gfwlist -server=/.greenpeace.org/127.0.0.1#7913 -ipset=/.greenpeace.org/gfwlist -server=/.xkiwi.tk/127.0.0.1#7913 -ipset=/.xkiwi.tk/gfwlist -server=/.workerdemo.org.hk/127.0.0.1#7913 -ipset=/.workerdemo.org.hk/gfwlist -server=/.cdnews.com.tw/127.0.0.1#7913 -ipset=/.cdnews.com.tw/gfwlist -server=/.fulione.com/127.0.0.1#7913 -ipset=/.fulione.com/gfwlist -server=/.greasespot.net/127.0.0.1#7913 -ipset=/.greasespot.net/gfwlist -server=/.sockscap64.com/127.0.0.1#7913 -ipset=/.sockscap64.com/gfwlist -server=/.fast.wistia.com/127.0.0.1#7913 -ipset=/.fast.wistia.com/gfwlist -server=/.hkbc.net/127.0.0.1#7913 -ipset=/.hkbc.net/gfwlist -server=/.deja.com/127.0.0.1#7913 -ipset=/.deja.com/gfwlist -server=/.twt.tl/127.0.0.1#7913 -ipset=/.twt.tl/gfwlist -server=/.versavpn.com/127.0.0.1#7913 -ipset=/.versavpn.com/gfwlist -server=/.cumlouder.com/127.0.0.1#7913 -ipset=/.cumlouder.com/gfwlist -server=/.ebookbrowse.com/127.0.0.1#7913 -ipset=/.ebookbrowse.com/gfwlist -server=/.classicalguitarblog.net/127.0.0.1#7913 -ipset=/.classicalguitarblog.net/gfwlist -server=/.rocketcdn.me/127.0.0.1#7913 -ipset=/.rocketcdn.me/gfwlist -server=/.download.ithome.com.tw/127.0.0.1#7913 -ipset=/.download.ithome.com.tw/gfwlist -server=/.hopto.org/127.0.0.1#7913 -ipset=/.hopto.org/gfwlist -server=/.7cow.com/127.0.0.1#7913 -ipset=/.7cow.com/gfwlist -server=/.taconet.com.tw/127.0.0.1#7913 -ipset=/.taconet.com.tw/gfwlist -server=/.velkaepocha.sk/127.0.0.1#7913 -ipset=/.velkaepocha.sk/gfwlist -server=/.soh.tw/127.0.0.1#7913 -ipset=/.soh.tw/gfwlist -server=/.newsancai.com/127.0.0.1#7913 -ipset=/.newsancai.com/gfwlist -server=/.iconpaper.org/127.0.0.1#7913 -ipset=/.iconpaper.org/gfwlist -server=/.xxxx.com.au/127.0.0.1#7913 -ipset=/.xxxx.com.au/gfwlist -server=/.tu8964.com/127.0.0.1#7913 -ipset=/.tu8964.com/gfwlist -server=/.hrtsea.com/127.0.0.1#7913 -ipset=/.hrtsea.com/gfwlist -server=/.xxxfuckmom.com/127.0.0.1#7913 -ipset=/.xxxfuckmom.com/gfwlist -server=/.xn--90wwvt03e.com/127.0.0.1#7913 -ipset=/.xn--90wwvt03e.com/gfwlist -server=/.xn--oiq.cc/127.0.0.1#7913 -ipset=/.xn--oiq.cc/gfwlist -server=/.bitshare.com/127.0.0.1#7913 -ipset=/.bitshare.com/gfwlist -server=/.xn--i2ru8q2qg.com/127.0.0.1#7913 -ipset=/.xn--i2ru8q2qg.com/gfwlist -server=/.crrev.com/127.0.0.1#7913 -ipset=/.crrev.com/gfwlist -server=/.hitomi.la/127.0.0.1#7913 -ipset=/.hitomi.la/gfwlist -server=/.xn--4gq171p.com/127.0.0.1#7913 -ipset=/.xn--4gq171p.com/gfwlist -server=/.stweetly.com/127.0.0.1#7913 -ipset=/.stweetly.com/gfwlist -server=/.allowed.org/127.0.0.1#7913 -ipset=/.allowed.org/gfwlist -server=/.heungkongdiscuss.com/127.0.0.1#7913 -ipset=/.heungkongdiscuss.com/gfwlist -server=/.thepiratebay.ee/127.0.0.1#7913 -ipset=/.thepiratebay.ee/gfwlist -server=/.atc.org.au/127.0.0.1#7913 -ipset=/.atc.org.au/gfwlist -server=/.asianews.it/127.0.0.1#7913 -ipset=/.asianews.it/gfwlist -server=/.nypost.com/127.0.0.1#7913 -ipset=/.nypost.com/gfwlist -server=/.inoreader.com/127.0.0.1#7913 -ipset=/.inoreader.com/gfwlist -server=/.travelinkcard.com/127.0.0.1#7913 -ipset=/.travelinkcard.com/gfwlist -server=/.ns02.biz/127.0.0.1#7913 -ipset=/.ns02.biz/gfwlist -server=/.evchk.wikia.org/127.0.0.1#7913 -ipset=/.evchk.wikia.org/gfwlist -server=/.china5000.us/127.0.0.1#7913 -ipset=/.china5000.us/gfwlist -server=/.wp.com/127.0.0.1#7913 -ipset=/.wp.com/gfwlist -server=/.paperb.us/127.0.0.1#7913 -ipset=/.paperb.us/gfwlist -server=/.yespornplease.com/127.0.0.1#7913 -ipset=/.yespornplease.com/gfwlist -server=/.e-hentai.org/127.0.0.1#7913 -ipset=/.e-hentai.org/gfwlist -server=/.nat.moe/127.0.0.1#7913 -ipset=/.nat.moe/gfwlist -server=/.godns.work/127.0.0.1#7913 -ipset=/.godns.work/gfwlist -server=/.hideipvpn.com/127.0.0.1#7913 -ipset=/.hideipvpn.com/gfwlist -server=/.ampproject.org/127.0.0.1#7913 -ipset=/.ampproject.org/gfwlist -server=/.knowyourmeme.com/127.0.0.1#7913 -ipset=/.knowyourmeme.com/gfwlist -server=/.wearehairy.com/127.0.0.1#7913 -ipset=/.wearehairy.com/gfwlist -server=/.mypop3.org/127.0.0.1#7913 -ipset=/.mypop3.org/gfwlist -server=/.flyzy2005.com/127.0.0.1#7913 -ipset=/.flyzy2005.com/gfwlist -server=/.91porn.com/127.0.0.1#7913 -ipset=/.91porn.com/gfwlist -server=/.hexieshe.com/127.0.0.1#7913 -ipset=/.hexieshe.com/gfwlist -server=/.equinenow.com/127.0.0.1#7913 -ipset=/.equinenow.com/gfwlist -server=/.alforattv.net/127.0.0.1#7913 -ipset=/.alforattv.net/gfwlist -server=/.lala.im/127.0.0.1#7913 -ipset=/.lala.im/gfwlist -server=/.app.box.com/127.0.0.1#7913 -ipset=/.app.box.com/gfwlist -server=/.ctwant.com/127.0.0.1#7913 -ipset=/.ctwant.com/gfwlist -server=/.totalvpn.com/127.0.0.1#7913 -ipset=/.totalvpn.com/gfwlist -server=/.memes.tw/127.0.0.1#7913 -ipset=/.memes.tw/gfwlist -server=/.feedly.com/127.0.0.1#7913 -ipset=/.feedly.com/gfwlist -server=/.gnews.org/127.0.0.1#7913 -ipset=/.gnews.org/gfwlist -server=/.v2mm.tech/127.0.0.1#7913 -ipset=/.v2mm.tech/gfwlist -server=/.newipnow.com/127.0.0.1#7913 -ipset=/.newipnow.com/gfwlist -server=/.vegasred.com/127.0.0.1#7913 -ipset=/.vegasred.com/gfwlist -server=/.figprayer.com/127.0.0.1#7913 -ipset=/.figprayer.com/gfwlist -server=/.imageab.com/127.0.0.1#7913 -ipset=/.imageab.com/gfwlist -server=/.adpl.org.hk/127.0.0.1#7913 -ipset=/.adpl.org.hk/gfwlist -server=/.g.kfd.me/127.0.0.1#7913 -ipset=/.g.kfd.me/gfwlist -server=/.wiki.kfd.me/127.0.0.1#7913 -ipset=/.wiki.kfd.me/gfwlist -server=/.duyaoss.com/127.0.0.1#7913 -ipset=/.duyaoss.com/gfwlist -server=/.wiki.jqueryui.com/127.0.0.1#7913 -ipset=/.wiki.jqueryui.com/gfwlist -server=/.justmysocks.net/127.0.0.1#7913 -ipset=/.justmysocks.net/gfwlist -server=/.javdb.com/127.0.0.1#7913 -ipset=/.javdb.com/gfwlist -server=/.webevader.org/127.0.0.1#7913 -ipset=/.webevader.org/gfwlist -server=/.mydati.com/127.0.0.1#7913 -ipset=/.mydati.com/gfwlist -server=/.cq99.us/127.0.0.1#7913 -ipset=/.cq99.us/gfwlist -server=/.opml.radiotime.com/127.0.0.1#7913 -ipset=/.opml.radiotime.com/gfwlist -server=/.dabr.co.uk/127.0.0.1#7913 -ipset=/.dabr.co.uk/gfwlist -server=/.webfreer.com/127.0.0.1#7913 -ipset=/.webfreer.com/gfwlist -server=/.bannednews.org/127.0.0.1#7913 -ipset=/.bannednews.org/gfwlist -server=/.pems.dot.ca.gov/127.0.0.1#7913 -ipset=/.pems.dot.ca.gov/gfwlist -server=/.megavideo.com/127.0.0.1#7913 -ipset=/.megavideo.com/gfwlist -server=/.app.cloudcone.com/127.0.0.1#7913 -ipset=/.app.cloudcone.com/gfwlist -server=/.time.com/127.0.0.1#7913 -ipset=/.time.com/gfwlist -server=/.xtube.com/127.0.0.1#7913 -ipset=/.xtube.com/gfwlist -server=/.myiphider.com/127.0.0.1#7913 -ipset=/.myiphider.com/gfwlist -server=/.share.america.gov/127.0.0.1#7913 -ipset=/.share.america.gov/gfwlist -server=/.pursuestar.com/127.0.0.1#7913 -ipset=/.pursuestar.com/gfwlist -server=/.jable.tv/127.0.0.1#7913 -ipset=/.jable.tv/gfwlist -server=/.saveliuxiaobo.com/127.0.0.1#7913 -ipset=/.saveliuxiaobo.com/gfwlist -server=/.getfreedur.com/127.0.0.1#7913 -ipset=/.getfreedur.com/gfwlist -server=/.puffin.com/127.0.0.1#7913 -ipset=/.puffin.com/gfwlist -server=/.vpnhq.com/127.0.0.1#7913 -ipset=/.vpnhq.com/gfwlist -server=/.zsdxzk.com/127.0.0.1#7913 -ipset=/.zsdxzk.com/gfwlist -server=/.ozxw.com/127.0.0.1#7913 -ipset=/.ozxw.com/gfwlist -server=/.starfishfx.com/127.0.0.1#7913 -ipset=/.starfishfx.com/gfwlist -server=/.nchrd.org/127.0.0.1#7913 -ipset=/.nchrd.org/gfwlist -server=/.left21.hk/127.0.0.1#7913 -ipset=/.left21.hk/gfwlist -server=/.biggo.com.tw/127.0.0.1#7913 -ipset=/.biggo.com.tw/gfwlist -server=/.parts.blog.livedoor.jp/127.0.0.1#7913 -ipset=/.parts.blog.livedoor.jp/gfwlist -server=/.sfshibao.com/127.0.0.1#7913 -ipset=/.sfshibao.com/gfwlist -server=/.clips4sale.com/127.0.0.1#7913 -ipset=/.clips4sale.com/gfwlist -server=/.ocsp.int-x3.letsencrypt.org/127.0.0.1#7913 -ipset=/.ocsp.int-x3.letsencrypt.org/gfwlist -server=/.blog.istef.info/127.0.0.1#7913 -ipset=/.blog.istef.info/gfwlist -server=/.chinaaid.us/127.0.0.1#7913 -ipset=/.chinaaid.us/gfwlist -server=/.tinypaste.com/127.0.0.1#7913 -ipset=/.tinypaste.com/gfwlist -server=/.see.xxx/127.0.0.1#7913 -ipset=/.see.xxx/gfwlist -server=/.tbtemple.org.uk/127.0.0.1#7913 -ipset=/.tbtemple.org.uk/gfwlist -server=/.phprcdn.com/127.0.0.1#7913 -ipset=/.phprcdn.com/gfwlist -server=/.porn5.com/127.0.0.1#7913 -ipset=/.porn5.com/gfwlist -server=/.mytalkbox.com/127.0.0.1#7913 -ipset=/.mytalkbox.com/gfwlist -server=/.goliathguitartutorials.com/127.0.0.1#7913 -ipset=/.goliathguitartutorials.com/gfwlist -server=/.suppig.net/127.0.0.1#7913 -ipset=/.suppig.net/gfwlist -server=/.xvideos-cdn.com/127.0.0.1#7913 -ipset=/.xvideos-cdn.com/gfwlist -server=/.pornbest.org/127.0.0.1#7913 -ipset=/.pornbest.org/gfwlist -server=/.sleazydream.com/127.0.0.1#7913 -ipset=/.sleazydream.com/gfwlist -server=/.fdc64.de/127.0.0.1#7913 -ipset=/.fdc64.de/gfwlist -server=/.hkhkhk.com/127.0.0.1#7913 -ipset=/.hkhkhk.com/gfwlist -server=/.dnset.com/127.0.0.1#7913 -ipset=/.dnset.com/gfwlist -server=/.tibetcorps.org/127.0.0.1#7913 -ipset=/.tibetcorps.org/gfwlist -server=/.zgsddh.com/127.0.0.1#7913 -ipset=/.zgsddh.com/gfwlist -server=/.antichristendom.com/127.0.0.1#7913 -ipset=/.antichristendom.com/gfwlist -server=/.holymountaincn.com/127.0.0.1#7913 -ipset=/.holymountaincn.com/gfwlist -server=/.zyzc9.com/127.0.0.1#7913 -ipset=/.zyzc9.com/gfwlist -server=/.philborges.com/127.0.0.1#7913 -ipset=/.philborges.com/gfwlist -server=/.wenyunchao.com/127.0.0.1#7913 -ipset=/.wenyunchao.com/gfwlist -server=/.zynaima.com/127.0.0.1#7913 -ipset=/.zynaima.com/gfwlist -server=/.unodedos.com/127.0.0.1#7913 -ipset=/.unodedos.com/gfwlist -server=/.leisurecafe.ca/127.0.0.1#7913 -ipset=/.leisurecafe.ca/gfwlist -server=/.savetibet.fr/127.0.0.1#7913 -ipset=/.savetibet.fr/gfwlist -server=/.zuobiao.me/127.0.0.1#7913 -ipset=/.zuobiao.me/gfwlist -server=/.zsrhao.com/127.0.0.1#7913 -ipset=/.zsrhao.com/gfwlist -server=/.tsdr.uspto.gov/127.0.0.1#7913 -ipset=/.tsdr.uspto.gov/gfwlist -server=/.privatetunnel.com/127.0.0.1#7913 -ipset=/.privatetunnel.com/gfwlist -server=/.googlegroups.com/127.0.0.1#7913 -ipset=/.googlegroups.com/gfwlist -server=/.tcsovi.org/127.0.0.1#7913 -ipset=/.tcsovi.org/gfwlist -server=/.writer.zoho.com/127.0.0.1#7913 -ipset=/.writer.zoho.com/gfwlist -server=/.forum.xinbao.de/127.0.0.1#7913 -ipset=/.forum.xinbao.de/gfwlist -server=/.zootool.com/127.0.0.1#7913 -ipset=/.zootool.com/gfwlist -server=/.dotgov.gov/127.0.0.1#7913 -ipset=/.dotgov.gov/gfwlist -server=/.nhk-ondemand.jp/127.0.0.1#7913 -ipset=/.nhk-ondemand.jp/gfwlist -server=/.uni.cc/127.0.0.1#7913 -ipset=/.uni.cc/gfwlist -server=/.zoogvpn.com/127.0.0.1#7913 -ipset=/.zoogvpn.com/gfwlist -server=/.busayari.com/127.0.0.1#7913 -ipset=/.busayari.com/gfwlist -server=/.localbitcoins.com/127.0.0.1#7913 -ipset=/.localbitcoins.com/gfwlist -server=/.zonghexinwen.net/127.0.0.1#7913 -ipset=/.zonghexinwen.net/gfwlist -server=/.zomobo.net/127.0.0.1#7913 -ipset=/.zomobo.net/gfwlist -server=/.helpeachpeople.com/127.0.0.1#7913 -ipset=/.helpeachpeople.com/gfwlist -server=/.zmw.cn/127.0.0.1#7913 -ipset=/.zmw.cn/gfwlist -server=/.skyxvpn.com/127.0.0.1#7913 -ipset=/.skyxvpn.com/gfwlist -server=/.realforum.zkiz.com/127.0.0.1#7913 -ipset=/.realforum.zkiz.com/gfwlist -server=/.plusbb.com/127.0.0.1#7913 -ipset=/.plusbb.com/gfwlist -server=/.ziporn.com/127.0.0.1#7913 -ipset=/.ziporn.com/gfwlist -server=/.hacg.me/127.0.0.1#7913 -ipset=/.hacg.me/gfwlist -server=/.ziddu.com/127.0.0.1#7913 -ipset=/.ziddu.com/gfwlist -server=/.book.zi5.me/127.0.0.1#7913 -ipset=/.book.zi5.me/gfwlist -server=/.yourlust.com/127.0.0.1#7913 -ipset=/.yourlust.com/gfwlist -server=/.zhuatieba.com/127.0.0.1#7913 -ipset=/.zhuatieba.com/gfwlist -server=/.scmpchinese.com/127.0.0.1#7913 -ipset=/.scmpchinese.com/gfwlist -server=/.is-a-hunter.com/127.0.0.1#7913 -ipset=/.is-a-hunter.com/gfwlist -server=/.mcreasite.com/127.0.0.1#7913 -ipset=/.mcreasite.com/gfwlist -server=/.zhoushuguang.com/127.0.0.1#7913 -ipset=/.zhoushuguang.com/gfwlist -server=/.kone.com/127.0.0.1#7913 -ipset=/.kone.com/gfwlist -server=/.zhongguorenquan.org/127.0.0.1#7913 -ipset=/.zhongguorenquan.org/gfwlist -server=/.whatsapp.net/127.0.0.1#7913 -ipset=/.whatsapp.net/gfwlist -server=/.h5galgame.me/127.0.0.1#7913 -ipset=/.h5galgame.me/gfwlist -server=/.chinamz.org/127.0.0.1#7913 -ipset=/.chinamz.org/gfwlist -server=/.zhongguo.ca/127.0.0.1#7913 -ipset=/.zhongguo.ca/gfwlist -server=/.zhinengluyou.com/127.0.0.1#7913 -ipset=/.zhinengluyou.com/gfwlist -server=/.zhenxiang.biz/127.0.0.1#7913 -ipset=/.zhenxiang.biz/gfwlist -server=/.zhenlibu1984.com/127.0.0.1#7913 -ipset=/.zhenlibu1984.com/gfwlist -server=/.hstt.net/127.0.0.1#7913 -ipset=/.hstt.net/gfwlist -server=/.zhenlibu.info/127.0.0.1#7913 -ipset=/.zhenlibu.info/gfwlist -server=/.googleplus.com/127.0.0.1#7913 -ipset=/.googleplus.com/gfwlist -server=/.zhengjian.org/127.0.0.1#7913 -ipset=/.zhengjian.org/gfwlist -server=/.zhenghui.org/127.0.0.1#7913 -ipset=/.zhenghui.org/gfwlist -server=/.zhangtianliang.com/127.0.0.1#7913 -ipset=/.zhangtianliang.com/gfwlist -server=/.zhangboli.net/127.0.0.1#7913 -ipset=/.zhangboli.net/gfwlist -server=/.zzcartoon.com/127.0.0.1#7913 -ipset=/.zzcartoon.com/gfwlist -server=/.zfreet.com/127.0.0.1#7913 -ipset=/.zfreet.com/gfwlist -server=/.vizvaz.com/127.0.0.1#7913 -ipset=/.vizvaz.com/gfwlist -server=/.zenmate.com.ru/127.0.0.1#7913 -ipset=/.zenmate.com.ru/gfwlist -server=/.zengjinyan.org/127.0.0.1#7913 -ipset=/.zengjinyan.org/gfwlist -server=/.dns05.com/127.0.0.1#7913 -ipset=/.dns05.com/gfwlist -server=/.zello.com/127.0.0.1#7913 -ipset=/.zello.com/gfwlist -server=/.zdnet.com.tw/127.0.0.1#7913 -ipset=/.zdnet.com.tw/gfwlist -server=/.zaobao.com.sg/127.0.0.1#7913 -ipset=/.zaobao.com.sg/gfwlist -server=/.zalmos.com/127.0.0.1#7913 -ipset=/.zalmos.com/gfwlist -server=/.yzzk.com/127.0.0.1#7913 -ipset=/.yzzk.com/gfwlist -server=/.chinesedemocracy.com/127.0.0.1#7913 -ipset=/.chinesedemocracy.com/gfwlist -server=/.m-team.cc/127.0.0.1#7913 -ipset=/.m-team.cc/gfwlist -server=/.allfinegirls.com/127.0.0.1#7913 -ipset=/.allfinegirls.com/gfwlist -server=/.yx51.net/127.0.0.1#7913 -ipset=/.yx51.net/gfwlist -server=/.ywpw.com/127.0.0.1#7913 -ipset=/.ywpw.com/gfwlist -server=/.greenreadings.com/127.0.0.1#7913 -ipset=/.greenreadings.com/gfwlist -server=/.yuntipub.com/127.0.0.1#7913 -ipset=/.yuntipub.com/gfwlist -server=/.psiphon.civisec.org/127.0.0.1#7913 -ipset=/.psiphon.civisec.org/gfwlist -server=/.karayou.com/127.0.0.1#7913 -ipset=/.karayou.com/gfwlist -server=/.inote.tw/127.0.0.1#7913 -ipset=/.inote.tw/gfwlist -server=/.proyectoclubes.com/127.0.0.1#7913 -ipset=/.proyectoclubes.com/gfwlist -server=/.acmetoy.com/127.0.0.1#7913 -ipset=/.acmetoy.com/gfwlist -server=/.webs-tv.net/127.0.0.1#7913 -ipset=/.webs-tv.net/gfwlist -server=/.twifan.com/127.0.0.1#7913 -ipset=/.twifan.com/gfwlist -server=/.chinayuanmin.org/127.0.0.1#7913 -ipset=/.chinayuanmin.org/gfwlist -server=/.yuanming.net/127.0.0.1#7913 -ipset=/.yuanming.net/gfwlist -server=/.youshun12.com/127.0.0.1#7913 -ipset=/.youshun12.com/gfwlist -server=/.topic.youthwant.com.tw/127.0.0.1#7913 -ipset=/.topic.youthwant.com.tw/gfwlist -server=/.share.youthwant.com.tw/127.0.0.1#7913 -ipset=/.share.youthwant.com.tw/gfwlist -server=/.japanfirst.asianfreeforum.com/127.0.0.1#7913 -ipset=/.japanfirst.asianfreeforum.com/gfwlist -server=/.lamnia.co.uk/127.0.0.1#7913 -ipset=/.lamnia.co.uk/gfwlist -server=/.twitbrowser.net/127.0.0.1#7913 -ipset=/.twitbrowser.net/gfwlist -server=/.blog.youthwant.com.tw/127.0.0.1#7913 -ipset=/.blog.youthwant.com.tw/gfwlist -server=/.youthnetradio.org/127.0.0.1#7913 -ipset=/.youthnetradio.org/gfwlist -server=/.yousendit.com/127.0.0.1#7913 -ipset=/.yousendit.com/gfwlist -server=/.yourprivatevpn.com/127.0.0.1#7913 -ipset=/.yourprivatevpn.com/gfwlist -server=/.yourepeat.com/127.0.0.1#7913 -ipset=/.yourepeat.com/gfwlist -server=/.cam4.jp/127.0.0.1#7913 -ipset=/.cam4.jp/gfwlist -server=/.your-freedom.net/127.0.0.1#7913 -ipset=/.your-freedom.net/gfwlist -server=/.softwarebychuck.com/127.0.0.1#7913 -ipset=/.softwarebychuck.com/gfwlist -server=/.ubddns.org/127.0.0.1#7913 -ipset=/.ubddns.org/gfwlist -server=/.h-moe.com/127.0.0.1#7913 -ipset=/.h-moe.com/gfwlist -server=/.medium.com/127.0.0.1#7913 -ipset=/.medium.com/gfwlist -server=/.maxing.jp/127.0.0.1#7913 -ipset=/.maxing.jp/gfwlist -server=/.youngspiration.hk/127.0.0.1#7913 -ipset=/.youngspiration.hk/gfwlist -server=/.cdig.info/127.0.0.1#7913 -ipset=/.cdig.info/gfwlist -server=/.youngpornvideos.com/127.0.0.1#7913 -ipset=/.youngpornvideos.com/gfwlist -server=/.chinesepen.org/127.0.0.1#7913 -ipset=/.chinesepen.org/gfwlist -server=/.fleshbot.com/127.0.0.1#7913 -ipset=/.fleshbot.com/gfwlist -server=/.tor.blingblingsquad.net/127.0.0.1#7913 -ipset=/.tor.blingblingsquad.net/gfwlist -server=/.slideshare.net/127.0.0.1#7913 -ipset=/.slideshare.net/gfwlist -server=/.rapidvpn.com/127.0.0.1#7913 -ipset=/.rapidvpn.com/gfwlist -server=/.pandapow.net/127.0.0.1#7913 -ipset=/.pandapow.net/gfwlist -server=/.youjizz.com/127.0.0.1#7913 -ipset=/.youjizz.com/gfwlist -server=/.efcc.org.hk/127.0.0.1#7913 -ipset=/.efcc.org.hk/gfwlist -server=/.youxu.info/127.0.0.1#7913 -ipset=/.youxu.info/gfwlist -server=/.xskywalker.net/127.0.0.1#7913 -ipset=/.xskywalker.net/gfwlist -server=/.yomiuri.co.jp/127.0.0.1#7913 -ipset=/.yomiuri.co.jp/gfwlist -server=/.liquidvpn.com/127.0.0.1#7913 -ipset=/.liquidvpn.com/gfwlist -server=/.referer.us/127.0.0.1#7913 -ipset=/.referer.us/gfwlist -server=/.gongm.in/127.0.0.1#7913 -ipset=/.gongm.in/gfwlist -server=/.xianba.net/127.0.0.1#7913 -ipset=/.xianba.net/gfwlist -server=/.yolasite.com/127.0.0.1#7913 -ipset=/.yolasite.com/gfwlist -server=/.wemigrate.org/127.0.0.1#7913 -ipset=/.wemigrate.org/gfwlist -server=/.psiphontoday.com/127.0.0.1#7913 -ipset=/.psiphontoday.com/gfwlist -server=/.spankingtube.com/127.0.0.1#7913 -ipset=/.spankingtube.com/gfwlist -server=/.crbug.com/127.0.0.1#7913 -ipset=/.crbug.com/gfwlist -server=/.google.gg/127.0.0.1#7913 -ipset=/.google.gg/gfwlist -server=/.asiatoday.us/127.0.0.1#7913 -ipset=/.asiatoday.us/gfwlist -server=/.yinlei.org/127.0.0.1#7913 -ipset=/.yinlei.org/gfwlist -server=/.18p2p.com/127.0.0.1#7913 -ipset=/.18p2p.com/gfwlist -server=/.yipub.com/127.0.0.1#7913 -ipset=/.yipub.com/gfwlist -server=/.torrentproject.se/127.0.0.1#7913 -ipset=/.torrentproject.se/gfwlist -server=/.yingsuoss.com/127.0.0.1#7913 -ipset=/.yingsuoss.com/gfwlist -server=/.dalailamafellows.org/127.0.0.1#7913 -ipset=/.dalailamafellows.org/gfwlist -server=/.xa.yimg.com/127.0.0.1#7913 -ipset=/.xa.yimg.com/gfwlist -server=/.yilubbs.com/127.0.0.1#7913 -ipset=/.yilubbs.com/gfwlist -server=/.guancha.org/127.0.0.1#7913 -ipset=/.guancha.org/gfwlist -server=/.yidio.com/127.0.0.1#7913 -ipset=/.yidio.com/gfwlist -server=/.yibaochina.com/127.0.0.1#7913 -ipset=/.yibaochina.com/gfwlist -server=/.yhcw.net/127.0.0.1#7913 -ipset=/.yhcw.net/gfwlist -server=/.yeyeclub.com/127.0.0.1#7913 -ipset=/.yeyeclub.com/gfwlist -server=/.wordpress.com/127.0.0.1#7913 -ipset=/.wordpress.com/gfwlist -server=/.dw.de/127.0.0.1#7913 -ipset=/.dw.de/gfwlist -server=/.westernwolves.com/127.0.0.1#7913 -ipset=/.westernwolves.com/gfwlist -server=/.yesasia.com/127.0.0.1#7913 -ipset=/.yesasia.com/gfwlist -server=/.yes123.com.tw/127.0.0.1#7913 -ipset=/.yes123.com.tw/gfwlist -server=/.yegle.net/127.0.0.1#7913 -ipset=/.yegle.net/gfwlist -server=/.yeeyi.com/127.0.0.1#7913 -ipset=/.yeeyi.com/gfwlist -server=/.yecl.net/127.0.0.1#7913 -ipset=/.yecl.net/gfwlist -server=/.slyip.com/127.0.0.1#7913 -ipset=/.slyip.com/gfwlist -server=/.zhao.1984.city/127.0.0.1#7913 -ipset=/.zhao.1984.city/gfwlist -server=/.ydy.com/127.0.0.1#7913 -ipset=/.ydy.com/gfwlist -server=/.newtalk.tw/127.0.0.1#7913 -ipset=/.newtalk.tw/gfwlist -server=/.yanghengjun.com/127.0.0.1#7913 -ipset=/.yanghengjun.com/gfwlist -server=/.minghui-b.org/127.0.0.1#7913 -ipset=/.minghui-b.org/gfwlist -server=/.yam.org.tw/127.0.0.1#7913 -ipset=/.yam.org.tw/gfwlist -server=/.yam.com/127.0.0.1#7913 -ipset=/.yam.com/gfwlist -server=/.xyy69.info/127.0.0.1#7913 -ipset=/.xyy69.info/gfwlist -server=/.helpzhuling.org/127.0.0.1#7913 -ipset=/.helpzhuling.org/gfwlist -server=/.roadshow.hk/127.0.0.1#7913 -ipset=/.roadshow.hk/gfwlist -server=/.dalailamaworld.com/127.0.0.1#7913 -ipset=/.dalailamaworld.com/gfwlist -server=/.xxxymovies.com/127.0.0.1#7913 -ipset=/.xxxymovies.com/gfwlist -server=/.skyking.com.tw/127.0.0.1#7913 -ipset=/.skyking.com.tw/gfwlist -server=/.xxx.xxx/127.0.0.1#7913 -ipset=/.xxx.xxx/gfwlist -server=/.xxbbx.com/127.0.0.1#7913 -ipset=/.xxbbx.com/gfwlist -server=/.xvideos.es/127.0.0.1#7913 -ipset=/.xvideos.es/gfwlist -server=/.xvideos.com/127.0.0.1#7913 -ipset=/.xvideos.com/gfwlist -server=/.ninjaproxy.ninja/127.0.0.1#7913 -ipset=/.ninjaproxy.ninja/gfwlist -server=/.xvideo.cc/127.0.0.1#7913 -ipset=/.xvideo.cc/gfwlist -server=/.xuchao.net/127.0.0.1#7913 -ipset=/.xuchao.net/gfwlist -server=/.ksnews.com.tw/127.0.0.1#7913 -ipset=/.ksnews.com.tw/gfwlist -server=/.xuzhiyong.net/127.0.0.1#7913 -ipset=/.xuzhiyong.net/gfwlist -server=/.economist.com/127.0.0.1#7913 -ipset=/.economist.com/gfwlist -server=/.edupro.org/127.0.0.1#7913 -ipset=/.edupro.org/gfwlist -server=/.airvpn.org/127.0.0.1#7913 -ipset=/.airvpn.org/gfwlist -server=/.51luoben.com/127.0.0.1#7913 -ipset=/.51luoben.com/gfwlist -server=/.xpud.org/127.0.0.1#7913 -ipset=/.xpud.org/gfwlist -server=/.cdp2006.org/127.0.0.1#7913 -ipset=/.cdp2006.org/gfwlist -server=/.blog.jackjia.com/127.0.0.1#7913 -ipset=/.blog.jackjia.com/gfwlist -server=/.lpsg.com/127.0.0.1#7913 -ipset=/.lpsg.com/gfwlist -server=/.xnxx.com/127.0.0.1#7913 -ipset=/.xnxx.com/gfwlist -server=/.xml-training-guide.com/127.0.0.1#7913 -ipset=/.xml-training-guide.com/gfwlist -server=/.www.imdb.com/127.0.0.1#7913 -ipset=/.www.imdb.com/gfwlist -server=/.sinonet.ca/127.0.0.1#7913 -ipset=/.sinonet.ca/gfwlist -server=/.www.tablesgenerator.com/127.0.0.1#7913 -ipset=/.www.tablesgenerator.com/gfwlist -server=/.xjtravelguide.com/127.0.0.1#7913 -ipset=/.xjtravelguide.com/gfwlist -server=/.iuksky.com/127.0.0.1#7913 -ipset=/.iuksky.com/gfwlist -server=/.xjp.cc/127.0.0.1#7913 -ipset=/.xjp.cc/gfwlist -server=/.hk32168.com/127.0.0.1#7913 -ipset=/.hk32168.com/gfwlist -server=/.site2unblock.com/127.0.0.1#7913 -ipset=/.site2unblock.com/gfwlist -server=/.evschool.net/127.0.0.1#7913 -ipset=/.evschool.net/gfwlist -server=/.ccim.org/127.0.0.1#7913 -ipset=/.ccim.org/gfwlist -server=/.xiuren.org/127.0.0.1#7913 -ipset=/.xiuren.org/gfwlist -server=/.xiongpian.com/127.0.0.1#7913 -ipset=/.xiongpian.com/gfwlist -server=/.twitgoo.com/127.0.0.1#7913 -ipset=/.twitgoo.com/gfwlist -server=/.xinhuanet.org/127.0.0.1#7913 -ipset=/.xinhuanet.org/gfwlist -server=/.rawgit.com/127.0.0.1#7913 -ipset=/.rawgit.com/gfwlist -server=/.bbs.huasing.org/127.0.0.1#7913 -ipset=/.bbs.huasing.org/gfwlist -server=/.xing.com/127.0.0.1#7913 -ipset=/.xing.com/gfwlist -server=/.tibetswiss.ch/127.0.0.1#7913 -ipset=/.tibetswiss.ch/gfwlist -server=/.bangdream.space/127.0.0.1#7913 -ipset=/.bangdream.space/gfwlist -server=/.rthk.org.hk/127.0.0.1#7913 -ipset=/.rthk.org.hk/gfwlist -server=/.moeerolibrary.com/127.0.0.1#7913 -ipset=/.moeerolibrary.com/gfwlist -server=/.zoozle.net/127.0.0.1#7913 -ipset=/.zoozle.net/gfwlist -server=/.btku.org/127.0.0.1#7913 -ipset=/.btku.org/gfwlist -server=/.sspro.ml/127.0.0.1#7913 -ipset=/.sspro.ml/gfwlist -server=/.www.dwheeler.com/127.0.0.1#7913 -ipset=/.www.dwheeler.com/gfwlist -server=/.vjav.com/127.0.0.1#7913 -ipset=/.vjav.com/gfwlist -server=/.xihua.es/127.0.0.1#7913 -ipset=/.xihua.es/gfwlist -server=/.facebook.hu/127.0.0.1#7913 -ipset=/.facebook.hu/gfwlist -server=/.xiaoma.org/127.0.0.1#7913 -ipset=/.xiaoma.org/gfwlist -server=/.tweetboard.com/127.0.0.1#7913 -ipset=/.tweetboard.com/gfwlist -server=/.allmovie.com/127.0.0.1#7913 -ipset=/.allmovie.com/gfwlist -server=/.mediafreakcity.com/127.0.0.1#7913 -ipset=/.mediafreakcity.com/gfwlist -server=/.taiwantp.net/127.0.0.1#7913 -ipset=/.taiwantp.net/gfwlist -server=/.about.google/127.0.0.1#7913 -ipset=/.about.google/gfwlist -server=/.abc.net.au/127.0.0.1#7913 -ipset=/.abc.net.au/gfwlist -server=/.wheatseeds.org/127.0.0.1#7913 -ipset=/.wheatseeds.org/gfwlist -server=/.jieshibaobao.com/127.0.0.1#7913 -ipset=/.jieshibaobao.com/gfwlist -server=/.facebook.design/127.0.0.1#7913 -ipset=/.facebook.design/gfwlist -server=/.vrsmash.com/127.0.0.1#7913 -ipset=/.vrsmash.com/gfwlist -server=/.expressvpn.com/127.0.0.1#7913 -ipset=/.expressvpn.com/gfwlist -server=/.tcsofbc.org/127.0.0.1#7913 -ipset=/.tcsofbc.org/gfwlist -server=/.us.to/127.0.0.1#7913 -ipset=/.us.to/gfwlist -server=/.cdpwu.org/127.0.0.1#7913 -ipset=/.cdpwu.org/gfwlist -server=/.i-scmp.com/127.0.0.1#7913 -ipset=/.i-scmp.com/gfwlist -server=/.xiaobaiwu.com/127.0.0.1#7913 -ipset=/.xiaobaiwu.com/gfwlist -server=/.gongminliliang.com/127.0.0.1#7913 -ipset=/.gongminliliang.com/gfwlist -server=/.xianqiao.net/127.0.0.1#7913 -ipset=/.xianqiao.net/gfwlist -server=/.cn2.streetvoice.com/127.0.0.1#7913 -ipset=/.cn2.streetvoice.com/gfwlist -server=/.xianjian.tw/127.0.0.1#7913 -ipset=/.xianjian.tw/gfwlist -server=/.myeasytv.com/127.0.0.1#7913 -ipset=/.myeasytv.com/gfwlist -server=/.xianchawang.net/127.0.0.1#7913 -ipset=/.xianchawang.net/gfwlist -server=/.xhamster.com/127.0.0.1#7913 -ipset=/.xhamster.com/gfwlist -server=/.3ren.ca/127.0.0.1#7913 -ipset=/.3ren.ca/gfwlist -server=/.destiny.xfiles.to/127.0.0.1#7913 -ipset=/.destiny.xfiles.to/gfwlist -server=/.xerotica.com/127.0.0.1#7913 -ipset=/.xerotica.com/gfwlist -server=/.xcity.jp/127.0.0.1#7913 -ipset=/.xcity.jp/gfwlist -server=/.twitturly.com/127.0.0.1#7913 -ipset=/.twitturly.com/gfwlist -server=/.zynamics.com/127.0.0.1#7913 -ipset=/.zynamics.com/gfwlist -server=/.passion.com/127.0.0.1#7913 -ipset=/.passion.com/gfwlist -server=/.xbabe.com/127.0.0.1#7913 -ipset=/.xbabe.com/gfwlist -server=/.xanga.com/127.0.0.1#7913 -ipset=/.xanga.com/gfwlist -server=/.twyac.org/127.0.0.1#7913 -ipset=/.twyac.org/gfwlist -server=/.getiton.com/127.0.0.1#7913 -ipset=/.getiton.com/gfwlist -server=/.tunnelbear.com/127.0.0.1#7913 -ipset=/.tunnelbear.com/gfwlist -server=/.x-art.com/127.0.0.1#7913 -ipset=/.x-art.com/gfwlist -server=/.dafahao.com/127.0.0.1#7913 -ipset=/.dafahao.com/gfwlist -server=/.pipii.tv/127.0.0.1#7913 -ipset=/.pipii.tv/gfwlist -server=/.m.hkgalden.com/127.0.0.1#7913 -ipset=/.m.hkgalden.com/gfwlist -server=/.sunskyforum.com/127.0.0.1#7913 -ipset=/.sunskyforum.com/gfwlist -server=/.peacehall.com/127.0.0.1#7913 -ipset=/.peacehall.com/gfwlist -server=/.tascn.com.au/127.0.0.1#7913 -ipset=/.tascn.com.au/gfwlist -server=/.stanford.edu/127.0.0.1#7913 -ipset=/.stanford.edu/gfwlist -server=/.npa.go.jp/127.0.0.1#7913 -ipset=/.npa.go.jp/gfwlist -server=/.wujieliulan.com/127.0.0.1#7913 -ipset=/.wujieliulan.com/gfwlist -server=/.devio.us/127.0.0.1#7913 -ipset=/.devio.us/gfwlist -server=/.onmoon.net/127.0.0.1#7913 -ipset=/.onmoon.net/gfwlist -server=/.wtbn.org/127.0.0.1#7913 -ipset=/.wtbn.org/gfwlist -server=/.mesotw.com/127.0.0.1#7913 -ipset=/.mesotw.com/gfwlist -server=/.google-analytics.com/127.0.0.1#7913 -ipset=/.google-analytics.com/gfwlist -server=/.freekwonpyong.org/127.0.0.1#7913 -ipset=/.freekwonpyong.org/gfwlist -server=/.twibbon.com/127.0.0.1#7913 -ipset=/.twibbon.com/gfwlist -server=/.depositphotos.com/127.0.0.1#7913 -ipset=/.depositphotos.com/gfwlist -server=/.whippedass.com/127.0.0.1#7913 -ipset=/.whippedass.com/gfwlist -server=/.onion.city/127.0.0.1#7913 -ipset=/.onion.city/gfwlist -server=/.wsjhk.com/127.0.0.1#7913 -ipset=/.wsjhk.com/gfwlist -server=/.orn.jp/127.0.0.1#7913 -ipset=/.orn.jp/gfwlist -server=/.wretch.cc/127.0.0.1#7913 -ipset=/.wretch.cc/gfwlist -server=/.wrchina.org/127.0.0.1#7913 -ipset=/.wrchina.org/gfwlist -server=/.woyaolian.org/127.0.0.1#7913 -ipset=/.woyaolian.org/gfwlist -server=/.ettoday.net/127.0.0.1#7913 -ipset=/.ettoday.net/gfwlist -server=/.toppornsites.com/127.0.0.1#7913 -ipset=/.toppornsites.com/gfwlist -server=/.wowgirls.com/127.0.0.1#7913 -ipset=/.wowgirls.com/gfwlist -server=/.wowlegacy.ml/127.0.0.1#7913 -ipset=/.wowlegacy.ml/gfwlist -server=/.wow.com/127.0.0.1#7913 -ipset=/.wow.com/gfwlist -server=/.91vps.club/127.0.0.1#7913 -ipset=/.91vps.club/gfwlist -server=/.srocket.us/127.0.0.1#7913 -ipset=/.srocket.us/gfwlist -server=/.bell.wiki/127.0.0.1#7913 -ipset=/.bell.wiki/gfwlist -server=/.sujiatun.wordpress.com/127.0.0.1#7913 -ipset=/.sujiatun.wordpress.com/gfwlist -server=/.wo3ttt.wordpress.com/127.0.0.1#7913 -ipset=/.wo3ttt.wordpress.com/gfwlist -server=/.clinica-tibet.ru/127.0.0.1#7913 -ipset=/.clinica-tibet.ru/gfwlist -server=/.jobnewera.wordpress.com/127.0.0.1#7913 -ipset=/.jobnewera.wordpress.com/gfwlist -server=/.ignitedetroit.net/127.0.0.1#7913 -ipset=/.ignitedetroit.net/gfwlist -server=/.heqinglian.net/127.0.0.1#7913 -ipset=/.heqinglian.net/gfwlist -server=/.blog.exblog.co.jp/127.0.0.1#7913 -ipset=/.blog.exblog.co.jp/gfwlist -server=/.aiweiweiblog.com/127.0.0.1#7913 -ipset=/.aiweiweiblog.com/gfwlist -server=/.forum.slime.com.tw/127.0.0.1#7913 -ipset=/.forum.slime.com.tw/gfwlist -server=/.ulike.net/127.0.0.1#7913 -ipset=/.ulike.net/gfwlist -server=/.hkanews.wordpress.com/127.0.0.1#7913 -ipset=/.hkanews.wordpress.com/gfwlist -server=/.chinaview.wordpress.com/127.0.0.1#7913 -ipset=/.chinaview.wordpress.com/gfwlist -server=/.worldvpn.net/127.0.0.1#7913 -ipset=/.worldvpn.net/gfwlist -server=/.theync.com/127.0.0.1#7913 -ipset=/.theync.com/gfwlist -server=/.worldjournal.com/127.0.0.1#7913 -ipset=/.worldjournal.com/gfwlist -server=/.worldcat.org/127.0.0.1#7913 -ipset=/.worldcat.org/gfwlist -server=/.atlanta168.com/127.0.0.1#7913 -ipset=/.atlanta168.com/gfwlist -server=/.workersthebig.net/127.0.0.1#7913 -ipset=/.workersthebig.net/gfwlist -server=/.workerempowerment.org/127.0.0.1#7913 -ipset=/.workerempowerment.org/gfwlist -server=/.csuchen.de/127.0.0.1#7913 -ipset=/.csuchen.de/gfwlist -server=/.workatruna.com/127.0.0.1#7913 -ipset=/.workatruna.com/gfwlist -server=/.woopie.jp/127.0.0.1#7913 -ipset=/.woopie.jp/gfwlist -server=/.woolyss.com/127.0.0.1#7913 -ipset=/.woolyss.com/gfwlist -server=/.iblist.com/127.0.0.1#7913 -ipset=/.iblist.com/gfwlist -server=/.milph.net/127.0.0.1#7913 -ipset=/.milph.net/gfwlist -server=/.organharvestinvestigation.net/127.0.0.1#7913 -ipset=/.organharvestinvestigation.net/gfwlist -server=/.imagevenue.com/127.0.0.1#7913 -ipset=/.imagevenue.com/gfwlist -server=/.wnacg.org/127.0.0.1#7913 -ipset=/.wnacg.org/gfwlist -server=/.wnacg.com/127.0.0.1#7913 -ipset=/.wnacg.com/gfwlist -server=/.tinychat.com/127.0.0.1#7913 -ipset=/.tinychat.com/gfwlist -server=/.9bis.net/127.0.0.1#7913 -ipset=/.9bis.net/gfwlist -server=/.crackle.com/127.0.0.1#7913 -ipset=/.crackle.com/gfwlist -server=/.witopia.net/127.0.0.1#7913 -ipset=/.witopia.net/gfwlist -server=/.google.co.id/127.0.0.1#7913 -ipset=/.google.co.id/gfwlist -server=/.witnessleeteaching.com/127.0.0.1#7913 -ipset=/.witnessleeteaching.com/gfwlist -server=/.ninjacloak.com/127.0.0.1#7913 -ipset=/.ninjacloak.com/gfwlist -server=/.wisdompubs.org/127.0.0.1#7913 -ipset=/.wisdompubs.org/gfwlist -server=/.wiredpen.com/127.0.0.1#7913 -ipset=/.wiredpen.com/gfwlist -server=/.winning11.com/127.0.0.1#7913 -ipset=/.winning11.com/gfwlist -server=/.wingy.site/127.0.0.1#7913 -ipset=/.wingy.site/gfwlist -server=/.twavi.com/127.0.0.1#7913 -ipset=/.twavi.com/gfwlist -server=/.willw.net/127.0.0.1#7913 -ipset=/.willw.net/gfwlist -server=/.lotsawahouse.org/127.0.0.1#7913 -ipset=/.lotsawahouse.org/gfwlist -server=/.clarionproject.org/127.0.0.1#7913 -ipset=/.clarionproject.org/gfwlist -server=/.wikiwiki.jp/127.0.0.1#7913 -ipset=/.wikiwiki.jp/gfwlist -server=/.falundafa-florida.org/127.0.0.1#7913 -ipset=/.falundafa-florida.org/gfwlist -server=/.casinoriva.com/127.0.0.1#7913 -ipset=/.casinoriva.com/gfwlist -server=/.wikivoyage.org/127.0.0.1#7913 -ipset=/.wikivoyage.org/gfwlist -server=/.city9x.com/127.0.0.1#7913 -ipset=/.city9x.com/gfwlist -server=/.wikiquote.org/127.0.0.1#7913 -ipset=/.wikiquote.org/gfwlist -server=/.nobodycanstop.us/127.0.0.1#7913 -ipset=/.nobodycanstop.us/gfwlist -server=/.wiktionary.org/127.0.0.1#7913 -ipset=/.wiktionary.org/gfwlist -server=/.bbs.hasi.wang/127.0.0.1#7913 -ipset=/.bbs.hasi.wang/gfwlist -server=/.islamawareness.net/127.0.0.1#7913 -ipset=/.islamawareness.net/gfwlist -server=/.ae.org/127.0.0.1#7913 -ipset=/.ae.org/gfwlist -server=/.slheng.com/127.0.0.1#7913 -ipset=/.slheng.com/gfwlist -server=/.scieron.com/127.0.0.1#7913 -ipset=/.scieron.com/gfwlist -server=/.wikisource.org/127.0.0.1#7913 -ipset=/.wikisource.org/gfwlist -server=/.google.ae/127.0.0.1#7913 -ipset=/.google.ae/gfwlist -server=/.tibetoralhistory.org/127.0.0.1#7913 -ipset=/.tibetoralhistory.org/gfwlist -server=/.mediawiki.org/127.0.0.1#7913 -ipset=/.mediawiki.org/gfwlist -server=/.wikidata.org/127.0.0.1#7913 -ipset=/.wikidata.org/gfwlist -server=/.comefromchina.com/127.0.0.1#7913 -ipset=/.comefromchina.com/gfwlist -server=/.wikipedia.org/127.0.0.1#7913 -ipset=/.wikipedia.org/gfwlist -server=/.boomssr.com/127.0.0.1#7913 -ipset=/.boomssr.com/gfwlist -server=/.wikinews.org/127.0.0.1#7913 -ipset=/.wikinews.org/gfwlist -server=/.falundafa.org/127.0.0.1#7913 -ipset=/.falundafa.org/gfwlist -server=/.wikiwand.com/127.0.0.1#7913 -ipset=/.wikiwand.com/gfwlist -server=/.iphonix.fr/127.0.0.1#7913 -ipset=/.iphonix.fr/gfwlist -server=/.gwtproject.org/127.0.0.1#7913 -ipset=/.gwtproject.org/gfwlist -server=/.myaudiocast.com/127.0.0.1#7913 -ipset=/.myaudiocast.com/gfwlist -server=/.hkip.org.uk/127.0.0.1#7913 -ipset=/.hkip.org.uk/gfwlist -server=/.wikilivres.info/127.0.0.1#7913 -ipset=/.wikilivres.info/gfwlist -server=/.collateralmurder.com/127.0.0.1#7913 -ipset=/.collateralmurder.com/gfwlist -server=/.etokki.com/127.0.0.1#7913 -ipset=/.etokki.com/gfwlist -server=/.freechina.news/127.0.0.1#7913 -ipset=/.freechina.news/gfwlist -server=/.williamhill.com/127.0.0.1#7913 -ipset=/.williamhill.com/gfwlist -server=/.brizzly.com/127.0.0.1#7913 -ipset=/.brizzly.com/gfwlist -server=/.abc.com/127.0.0.1#7913 -ipset=/.abc.com/gfwlist -server=/.bbc.com/127.0.0.1#7913 -ipset=/.bbc.com/gfwlist -server=/.taiwantt.org.tw/127.0.0.1#7913 -ipset=/.taiwantt.org.tw/gfwlist -server=/.wikileaks.pl/127.0.0.1#7913 -ipset=/.wikileaks.pl/gfwlist -server=/.longhair.hk/127.0.0.1#7913 -ipset=/.longhair.hk/gfwlist -server=/.togetter.com/127.0.0.1#7913 -ipset=/.togetter.com/gfwlist -server=/.organiccrap.com/127.0.0.1#7913 -ipset=/.organiccrap.com/gfwlist -server=/.wikileaks.lu/127.0.0.1#7913 -ipset=/.wikileaks.lu/gfwlist -server=/.vijayatemple.org/127.0.0.1#7913 -ipset=/.vijayatemple.org/gfwlist -server=/.wikileaks.eu/127.0.0.1#7913 -ipset=/.wikileaks.eu/gfwlist -server=/.wikileaks.de/127.0.0.1#7913 -ipset=/.wikileaks.de/gfwlist -server=/.wikia.com/127.0.0.1#7913 -ipset=/.wikia.com/gfwlist -server=/.whyx.org/127.0.0.1#7913 -ipset=/.whyx.org/gfwlist -server=/.whylover.com/127.0.0.1#7913 -ipset=/.whylover.com/gfwlist -server=/.whotalking.com/127.0.0.1#7913 -ipset=/.whotalking.com/gfwlist -server=/.leeao.com.cn/127.0.0.1#7913 -ipset=/.leeao.com.cn/gfwlist -server=/.whoer.net/127.0.0.1#7913 -ipset=/.whoer.net/gfwlist -server=/.adult-sex-games.com/127.0.0.1#7913 -ipset=/.adult-sex-games.com/gfwlist -server=/.realraptalk.com/127.0.0.1#7913 -ipset=/.realraptalk.com/gfwlist -server=/.wetplace.com/127.0.0.1#7913 -ipset=/.wetplace.com/gfwlist -server=/.softether-download.com/127.0.0.1#7913 -ipset=/.softether-download.com/gfwlist -server=/.news.sinchew.com.my/127.0.0.1#7913 -ipset=/.news.sinchew.com.my/gfwlist -server=/.bcchinese.net/127.0.0.1#7913 -ipset=/.bcchinese.net/gfwlist -server=/.wetpussygames.com/127.0.0.1#7913 -ipset=/.wetpussygames.com/gfwlist -server=/.yesasia.com.hk/127.0.0.1#7913 -ipset=/.yesasia.com.hk/gfwlist -server=/.westca.com/127.0.0.1#7913 -ipset=/.westca.com/gfwlist -server=/.wenxuecity.com/127.0.0.1#7913 -ipset=/.wenxuecity.com/gfwlist -server=/.wenweipo.com/127.0.0.1#7913 -ipset=/.wenweipo.com/gfwlist -server=/.wenhui.ch/127.0.0.1#7913 -ipset=/.wenhui.ch/gfwlist -server=/.wengewang.org/127.0.0.1#7913 -ipset=/.wengewang.org/gfwlist -server=/.wahas.com/127.0.0.1#7913 -ipset=/.wahas.com/gfwlist -server=/.simbolostwitter.com/127.0.0.1#7913 -ipset=/.simbolostwitter.com/gfwlist -server=/.wengewang.com/127.0.0.1#7913 -ipset=/.wengewang.com/gfwlist -server=/.yobt.com/127.0.0.1#7913 -ipset=/.yobt.com/gfwlist -server=/.iphonetaiwan.org/127.0.0.1#7913 -ipset=/.iphonetaiwan.org/gfwlist -server=/.mathable.io/127.0.0.1#7913 -ipset=/.mathable.io/gfwlist -server=/.hola.org/127.0.0.1#7913 -ipset=/.hola.org/gfwlist -server=/.chinese.soifind.com/127.0.0.1#7913 -ipset=/.chinese.soifind.com/gfwlist -server=/.pinterest.com/127.0.0.1#7913 -ipset=/.pinterest.com/gfwlist -server=/.weisuo.ws/127.0.0.1#7913 -ipset=/.weisuo.ws/gfwlist -server=/.weiming.info/127.0.0.1#7913 -ipset=/.weiming.info/gfwlist -server=/.weihuo.org/127.0.0.1#7913 -ipset=/.weihuo.org/gfwlist -server=/.weiboleak.com/127.0.0.1#7913 -ipset=/.weiboleak.com/gfwlist -server=/.cn.streetvoice.com/127.0.0.1#7913 -ipset=/.cn.streetvoice.com/gfwlist -server=/.wefong.com/127.0.0.1#7913 -ipset=/.wefong.com/gfwlist -server=/.shwchurch.org/127.0.0.1#7913 -ipset=/.shwchurch.org/gfwlist -server=/.toutiaoabc.com/127.0.0.1#7913 -ipset=/.toutiaoabc.com/gfwlist -server=/.api.ai/127.0.0.1#7913 -ipset=/.api.ai/gfwlist -server=/.webworkerdaily.com/127.0.0.1#7913 -ipset=/.webworkerdaily.com/gfwlist -server=/.nationwide.com/127.0.0.1#7913 -ipset=/.nationwide.com/gfwlist -server=/.api.recaptcha.net/127.0.0.1#7913 -ipset=/.api.recaptcha.net/gfwlist -server=/.towngain.com/127.0.0.1#7913 -ipset=/.towngain.com/gfwlist -server=/.www.websnapr.com/127.0.0.1#7913 -ipset=/.www.websnapr.com/gfwlist -server=/.googleearth.com/127.0.0.1#7913 -ipset=/.googleearth.com/gfwlist -server=/.trialofccp.org/127.0.0.1#7913 -ipset=/.trialofccp.org/gfwlist -server=/.websitepulse.com/127.0.0.1#7913 -ipset=/.websitepulse.com/gfwlist -server=/.ezpeer.com/127.0.0.1#7913 -ipset=/.ezpeer.com/gfwlist -server=/.highrockmedia.com/127.0.0.1#7913 -ipset=/.highrockmedia.com/gfwlist -server=/.tn2.shemalez.com/127.0.0.1#7913 -ipset=/.tn2.shemalez.com/gfwlist -server=/.yulghun.com/127.0.0.1#7913 -ipset=/.yulghun.com/gfwlist -server=/.bnn.co/127.0.0.1#7913 -ipset=/.bnn.co/gfwlist -server=/.webjb.org/127.0.0.1#7913 -ipset=/.webjb.org/gfwlist -server=/.advertfan.com/127.0.0.1#7913 -ipset=/.advertfan.com/gfwlist -server=/.hudatoriq.web.id/127.0.0.1#7913 -ipset=/.hudatoriq.web.id/gfwlist -server=/.www.skype.com/127.0.0.1#7913 -ipset=/.www.skype.com/gfwlist -server=/.netsneak.com/127.0.0.1#7913 -ipset=/.netsneak.com/gfwlist -server=/.episcopalchurch.org/127.0.0.1#7913 -ipset=/.episcopalchurch.org/gfwlist -server=/.onmoon.com/127.0.0.1#7913 -ipset=/.onmoon.com/gfwlist -server=/.stoptibetcrisis.net/127.0.0.1#7913 -ipset=/.stoptibetcrisis.net/gfwlist -server=/.wearn.com/127.0.0.1#7913 -ipset=/.wearn.com/gfwlist -server=/.pythonhackers.com/127.0.0.1#7913 -ipset=/.pythonhackers.com/gfwlist -server=/.mega.nz/127.0.0.1#7913 -ipset=/.mega.nz/gfwlist -server=/.wdf5.com/127.0.0.1#7913 -ipset=/.wdf5.com/gfwlist -server=/.kyzyhello.com/127.0.0.1#7913 -ipset=/.kyzyhello.com/gfwlist -server=/.dvorak.org/127.0.0.1#7913 -ipset=/.dvorak.org/gfwlist -server=/.watch8x.com/127.0.0.1#7913 -ipset=/.watch8x.com/gfwlist -server=/.4rbtv.com/127.0.0.1#7913 -ipset=/.4rbtv.com/gfwlist -server=/.flog.tw/127.0.0.1#7913 -ipset=/.flog.tw/gfwlist -server=/.goagentplus.com/127.0.0.1#7913 -ipset=/.goagentplus.com/gfwlist -server=/.washeng.net/127.0.0.1#7913 -ipset=/.washeng.net/gfwlist -server=/.makzhou.warehouse333.com/127.0.0.1#7913 -ipset=/.makzhou.warehouse333.com/gfwlist -server=/.erodoujinlog.com/127.0.0.1#7913 -ipset=/.erodoujinlog.com/gfwlist -server=/.freedomsherald.org/127.0.0.1#7913 -ipset=/.freedomsherald.org/gfwlist -server=/.wapedia.mobi/127.0.0.1#7913 -ipset=/.wapedia.mobi/gfwlist -server=/.tuo8.cc/127.0.0.1#7913 -ipset=/.tuo8.cc/gfwlist -server=/.kinghost.com/127.0.0.1#7913 -ipset=/.kinghost.com/gfwlist -server=/.feelssh.com/127.0.0.1#7913 -ipset=/.feelssh.com/gfwlist -server=/.thetvdb.com/127.0.0.1#7913 -ipset=/.thetvdb.com/gfwlist -server=/.thegioitinhoc.vn/127.0.0.1#7913 -ipset=/.thegioitinhoc.vn/gfwlist -server=/.domain.club.tw/127.0.0.1#7913 -ipset=/.domain.club.tw/gfwlist -server=/.want-daily.com/127.0.0.1#7913 -ipset=/.want-daily.com/gfwlist -server=/.psiphon.ca/127.0.0.1#7913 -ipset=/.psiphon.ca/gfwlist -server=/.www.wangruowang.org/127.0.0.1#7913 -ipset=/.www.wangruowang.org/gfwlist -server=/.wangruoshui.net/127.0.0.1#7913 -ipset=/.wangruoshui.net/gfwlist -server=/.scache.vzw.com/127.0.0.1#7913 -ipset=/.scache.vzw.com/gfwlist -server=/.comic-mega.me/127.0.0.1#7913 -ipset=/.comic-mega.me/gfwlist -server=/.wanglixiong.com/127.0.0.1#7913 -ipset=/.wanglixiong.com/gfwlist -server=/.huangyiyu.com/127.0.0.1#7913 -ipset=/.huangyiyu.com/gfwlist -server=/.wangjinbo.org/127.0.0.1#7913 -ipset=/.wangjinbo.org/gfwlist -server=/.www.wan-press.org/127.0.0.1#7913 -ipset=/.www.wan-press.org/gfwlist -server=/.upholdjustice.org/127.0.0.1#7913 -ipset=/.upholdjustice.org/gfwlist -server=/.englishforeveryone.org/127.0.0.1#7913 -ipset=/.englishforeveryone.org/gfwlist -server=/.christianfreedom.org/127.0.0.1#7913 -ipset=/.christianfreedom.org/gfwlist -server=/.waltermartin.org/127.0.0.1#7913 -ipset=/.waltermartin.org/gfwlist -server=/.waltermartin.com/127.0.0.1#7913 -ipset=/.waltermartin.com/gfwlist -server=/.sikaozhe1997.github.io/127.0.0.1#7913 -ipset=/.sikaozhe1997.github.io/gfwlist -server=/.wallpapercasa.com/127.0.0.1#7913 -ipset=/.wallpapercasa.com/gfwlist -server=/.wallmama.com/127.0.0.1#7913 -ipset=/.wallmama.com/gfwlist -server=/.fapdu.com/127.0.0.1#7913 -ipset=/.fapdu.com/gfwlist -server=/.wailaike.net/127.0.0.1#7913 -ipset=/.wailaike.net/gfwlist -server=/.tosh.comedycentral.com/127.0.0.1#7913 -ipset=/.tosh.comedycentral.com/gfwlist -server=/.waigaobu.com/127.0.0.1#7913 -ipset=/.waigaobu.com/gfwlist -server=/.waffle1999.com/127.0.0.1#7913 -ipset=/.waffle1999.com/gfwlist -server=/.localpresshk.com/127.0.0.1#7913 -ipset=/.localpresshk.com/gfwlist -server=/.avidemux.org/127.0.0.1#7913 -ipset=/.avidemux.org/gfwlist -server=/.lists.w3.org/127.0.0.1#7913 -ipset=/.lists.w3.org/gfwlist -server=/.daidostup.ru/127.0.0.1#7913 -ipset=/.daidostup.ru/gfwlist -server=/.vuku.cc/127.0.0.1#7913 -ipset=/.vuku.cc/gfwlist -server=/.vtunnel.com/127.0.0.1#7913 -ipset=/.vtunnel.com/gfwlist -server=/.fringenetwork.com/127.0.0.1#7913 -ipset=/.fringenetwork.com/gfwlist -server=/.zippyshare.com/127.0.0.1#7913 -ipset=/.zippyshare.com/gfwlist -server=/.vporn.com/127.0.0.1#7913 -ipset=/.vporn.com/gfwlist -server=/.vpnworldwide.com/127.0.0.1#7913 -ipset=/.vpnworldwide.com/gfwlist -server=/.ssh91.com/127.0.0.1#7913 -ipset=/.ssh91.com/gfwlist -server=/.vpnunlimitedapp.com/127.0.0.1#7913 -ipset=/.vpnunlimitedapp.com/gfwlist -server=/.vpntunnel.com/127.0.0.1#7913 -ipset=/.vpntunnel.com/gfwlist -server=/.archive.is/127.0.0.1#7913 -ipset=/.archive.is/gfwlist -server=/.naughtyamerica.com/127.0.0.1#7913 -ipset=/.naughtyamerica.com/gfwlist -server=/.bird.so/127.0.0.1#7913 -ipset=/.bird.so/gfwlist -server=/.zapto.org/127.0.0.1#7913 -ipset=/.zapto.org/gfwlist -server=/.adult.friendfinder.com/127.0.0.1#7913 -ipset=/.adult.friendfinder.com/gfwlist -server=/.twibase.com/127.0.0.1#7913 -ipset=/.twibase.com/gfwlist -server=/.greenvpn.org/127.0.0.1#7913 -ipset=/.greenvpn.org/gfwlist -server=/.cftfc.com/127.0.0.1#7913 -ipset=/.cftfc.com/gfwlist -server=/.pchome.com.tw/127.0.0.1#7913 -ipset=/.pchome.com.tw/gfwlist -server=/.vpnshieldapp.com/127.0.0.1#7913 -ipset=/.vpnshieldapp.com/gfwlist -server=/.cccat.cc/127.0.0.1#7913 -ipset=/.cccat.cc/gfwlist -server=/.matome-plus.net/127.0.0.1#7913 -ipset=/.matome-plus.net/gfwlist -server=/.dsmtp.com/127.0.0.1#7913 -ipset=/.dsmtp.com/gfwlist -server=/.spring4u.info/127.0.0.1#7913 -ipset=/.spring4u.info/gfwlist -server=/.cyberghost.natado.com/127.0.0.1#7913 -ipset=/.cyberghost.natado.com/gfwlist -server=/.thereallove.kr/127.0.0.1#7913 -ipset=/.thereallove.kr/gfwlist -server=/.tw.voa.mobi/127.0.0.1#7913 -ipset=/.tw.voa.mobi/gfwlist -server=/.vpnreviewz.com/127.0.0.1#7913 -ipset=/.vpnreviewz.com/gfwlist -server=/.vpnreactor.com/127.0.0.1#7913 -ipset=/.vpnreactor.com/gfwlist -server=/.uygur.fc2web.com/127.0.0.1#7913 -ipset=/.uygur.fc2web.com/gfwlist -server=/.diaoyuislands.org/127.0.0.1#7913 -ipset=/.diaoyuislands.org/gfwlist -server=/.vpnpronet.com/127.0.0.1#7913 -ipset=/.vpnpronet.com/gfwlist -server=/.michaelanti.com/127.0.0.1#7913 -ipset=/.michaelanti.com/gfwlist -server=/.vpnpick.com/127.0.0.1#7913 -ipset=/.vpnpick.com/gfwlist -server=/.mybbs.us/127.0.0.1#7913 -ipset=/.mybbs.us/gfwlist -server=/.betternet.co/127.0.0.1#7913 -ipset=/.betternet.co/gfwlist -server=/.gotw.ca/127.0.0.1#7913 -ipset=/.gotw.ca/gfwlist -server=/.vpnjack.com/127.0.0.1#7913 -ipset=/.vpnjack.com/gfwlist -server=/.jiangweiping.com/127.0.0.1#7913 -ipset=/.jiangweiping.com/gfwlist -server=/.vpnintouch.net/127.0.0.1#7913 -ipset=/.vpnintouch.net/gfwlist -server=/.vpnintouch.com/127.0.0.1#7913 -ipset=/.vpnintouch.com/gfwlist -server=/.prayforchina.net/127.0.0.1#7913 -ipset=/.prayforchina.net/gfwlist -server=/.vpnmentor.com/127.0.0.1#7913 -ipset=/.vpnmentor.com/gfwlist -server=/.mychinanet.com/127.0.0.1#7913 -ipset=/.mychinanet.com/gfwlist -server=/.vpnmaster.com/127.0.0.1#7913 -ipset=/.vpnmaster.com/gfwlist -server=/.vpngratis.net/127.0.0.1#7913 -ipset=/.vpngratis.net/gfwlist -server=/.vpngate.net/127.0.0.1#7913 -ipset=/.vpngate.net/gfwlist -server=/.vpngate.jp/127.0.0.1#7913 -ipset=/.vpngate.jp/gfwlist -server=/.vpnfires.biz/127.0.0.1#7913 -ipset=/.vpnfires.biz/gfwlist -server=/.protonvpn.com/127.0.0.1#7913 -ipset=/.protonvpn.com/gfwlist -server=/.hungerstrikeforaids.org/127.0.0.1#7913 -ipset=/.hungerstrikeforaids.org/gfwlist -server=/.vpnfan.com/127.0.0.1#7913 -ipset=/.vpnfan.com/gfwlist -server=/.web.dev/127.0.0.1#7913 -ipset=/.web.dev/gfwlist -server=/.www.eastturkistan.net/127.0.0.1#7913 -ipset=/.www.eastturkistan.net/gfwlist -server=/.slaytizle.com/127.0.0.1#7913 -ipset=/.slaytizle.com/gfwlist -server=/.vpncoupons.com/127.0.0.1#7913 -ipset=/.vpncoupons.com/gfwlist -server=/.ka-wai.com/127.0.0.1#7913 -ipset=/.ka-wai.com/gfwlist -server=/.quitccp.net/127.0.0.1#7913 -ipset=/.quitccp.net/gfwlist -server=/.itasoftware.com/127.0.0.1#7913 -ipset=/.itasoftware.com/gfwlist -server=/.naol.ca/127.0.0.1#7913 -ipset=/.naol.ca/gfwlist -server=/.vpncomparison.org/127.0.0.1#7913 -ipset=/.vpncomparison.org/gfwlist -server=/.mmaaxx.com/127.0.0.1#7913 -ipset=/.mmaaxx.com/gfwlist -server=/.doubibackup.com/127.0.0.1#7913 -ipset=/.doubibackup.com/gfwlist -server=/.vpnaccount.org/127.0.0.1#7913 -ipset=/.vpnaccount.org/gfwlist -server=/.vpn.ac/127.0.0.1#7913 -ipset=/.vpn.ac/gfwlist -server=/.html5rocks.com/127.0.0.1#7913 -ipset=/.html5rocks.com/gfwlist -server=/.thefrontier.hk/127.0.0.1#7913 -ipset=/.thefrontier.hk/gfwlist -server=/.voxer.com/127.0.0.1#7913 -ipset=/.voxer.com/gfwlist -server=/.ultravpn.fr/127.0.0.1#7913 -ipset=/.ultravpn.fr/gfwlist -server=/.vot.org/127.0.0.1#7913 -ipset=/.vot.org/gfwlist -server=/.discuss4u.com/127.0.0.1#7913 -ipset=/.discuss4u.com/gfwlist -server=/.vegas.williamhill.com/127.0.0.1#7913 -ipset=/.vegas.williamhill.com/gfwlist -server=/.voatibetan.com/127.0.0.1#7913 -ipset=/.voatibetan.com/gfwlist -server=/.apidocs.linksalpha.com/127.0.0.1#7913 -ipset=/.apidocs.linksalpha.com/gfwlist -server=/.daftporn.com/127.0.0.1#7913 -ipset=/.daftporn.com/gfwlist -server=/.fingerdaily.com/127.0.0.1#7913 -ipset=/.fingerdaily.com/gfwlist -server=/.voachineseblog.com/127.0.0.1#7913 -ipset=/.voachineseblog.com/gfwlist -server=/.vpnsp.com/127.0.0.1#7913 -ipset=/.vpnsp.com/gfwlist -server=/.vnet.link/127.0.0.1#7913 -ipset=/.vnet.link/gfwlist -server=/.vllcs.org/127.0.0.1#7913 -ipset=/.vllcs.org/gfwlist -server=/.iamtopone.com/127.0.0.1#7913 -ipset=/.iamtopone.com/gfwlist -server=/.upwill.org/127.0.0.1#7913 -ipset=/.upwill.org/gfwlist -server=/.mikesoltys.com/127.0.0.1#7913 -ipset=/.mikesoltys.com/gfwlist -server=/.dbc.hk/127.0.0.1#7913 -ipset=/.dbc.hk/gfwlist -server=/.ygto.com/127.0.0.1#7913 -ipset=/.ygto.com/gfwlist -server=/.vivthomas.com/127.0.0.1#7913 -ipset=/.vivthomas.com/gfwlist -server=/.vivatube.com/127.0.0.1#7913 -ipset=/.vivatube.com/gfwlist -server=/.vivahentai4u.net/127.0.0.1#7913 -ipset=/.vivahentai4u.net/gfwlist -server=/.viu.com/127.0.0.1#7913 -ipset=/.viu.com/gfwlist -server=/.i2p2.de/127.0.0.1#7913 -ipset=/.i2p2.de/gfwlist -server=/.visibletweets.com/127.0.0.1#7913 -ipset=/.visibletweets.com/gfwlist -server=/.teeniefuck.net/127.0.0.1#7913 -ipset=/.teeniefuck.net/gfwlist -server=/.virtualrealporn.com/127.0.0.1#7913 -ipset=/.virtualrealporn.com/gfwlist -server=/.https443.net/127.0.0.1#7913 -ipset=/.https443.net/gfwlist -server=/.www.lib.virginia.edu/127.0.0.1#7913 -ipset=/.www.lib.virginia.edu/gfwlist -server=/.vinniev.com/127.0.0.1#7913 -ipset=/.vinniev.com/gfwlist -server=/.thestandnews.com/127.0.0.1#7913 -ipset=/.thestandnews.com/gfwlist -server=/.hkday.net/127.0.0.1#7913 -ipset=/.hkday.net/gfwlist -server=/.extmatrix.com/127.0.0.1#7913 -ipset=/.extmatrix.com/gfwlist -server=/.tibetheritagefund.org/127.0.0.1#7913 -ipset=/.tibetheritagefund.org/gfwlist -server=/.vincnd.com/127.0.0.1#7913 -ipset=/.vincnd.com/gfwlist -server=/.freevpn.nl/127.0.0.1#7913 -ipset=/.freevpn.nl/gfwlist -server=/.ilove80.be/127.0.0.1#7913 -ipset=/.ilove80.be/gfwlist -server=/.vimperator.org/127.0.0.1#7913 -ipset=/.vimperator.org/gfwlist -server=/.pushchinawall.com/127.0.0.1#7913 -ipset=/.pushchinawall.com/gfwlist -server=/.huiyi.in/127.0.0.1#7913 -ipset=/.huiyi.in/gfwlist -server=/.backchina.com/127.0.0.1#7913 -ipset=/.backchina.com/gfwlist -server=/.media.org.hk/127.0.0.1#7913 -ipset=/.media.org.hk/gfwlist -server=/.hkdf.org/127.0.0.1#7913 -ipset=/.hkdf.org/gfwlist -server=/.calgarychinese.ca/127.0.0.1#7913 -ipset=/.calgarychinese.ca/gfwlist -server=/.vidinfo.org/127.0.0.1#7913 -ipset=/.vidinfo.org/gfwlist -server=/.videopress.com/127.0.0.1#7913 -ipset=/.videopress.com/gfwlist -server=/.dtdns.net/127.0.0.1#7913 -ipset=/.dtdns.net/gfwlist -server=/.hqcdp.org/127.0.0.1#7913 -ipset=/.hqcdp.org/gfwlist -server=/.jitouch.com/127.0.0.1#7913 -ipset=/.jitouch.com/gfwlist -server=/.vid.me/127.0.0.1#7913 -ipset=/.vid.me/gfwlist -server=/.vica.info/127.0.0.1#7913 -ipset=/.vica.info/gfwlist -server=/.peopo.org/127.0.0.1#7913 -ipset=/.peopo.org/gfwlist -server=/.hstern.net/127.0.0.1#7913 -ipset=/.hstern.net/gfwlist -server=/.viber.com/127.0.0.1#7913 -ipset=/.viber.com/gfwlist -server=/.veoh.com/127.0.0.1#7913 -ipset=/.veoh.com/gfwlist -server=/.venchina.com/127.0.0.1#7913 -ipset=/.venchina.com/gfwlist -server=/.venbbs.com/127.0.0.1#7913 -ipset=/.venbbs.com/gfwlist -server=/.falun.caltech.edu/127.0.0.1#7913 -ipset=/.falun.caltech.edu/gfwlist -server=/.chinese.engadget.com/127.0.0.1#7913 -ipset=/.chinese.engadget.com/gfwlist -server=/.mychinamyhome.com/127.0.0.1#7913 -ipset=/.mychinamyhome.com/gfwlist -server=/.bbsland.com/127.0.0.1#7913 -ipset=/.bbsland.com/gfwlist -server=/.news.sina.com.hk/127.0.0.1#7913 -ipset=/.news.sina.com.hk/gfwlist -server=/.radiohilight.net/127.0.0.1#7913 -ipset=/.radiohilight.net/gfwlist -server=/.vansky.com/127.0.0.1#7913 -ipset=/.vansky.com/gfwlist -server=/.vanilla-jp.com/127.0.0.1#7913 -ipset=/.vanilla-jp.com/gfwlist -server=/.paste.ee/127.0.0.1#7913 -ipset=/.paste.ee/gfwlist -server=/.van698.com/127.0.0.1#7913 -ipset=/.van698.com/gfwlist -server=/.cam4.sg/127.0.0.1#7913 -ipset=/.cam4.sg/gfwlist -server=/.uptodown.com/127.0.0.1#7913 -ipset=/.uptodown.com/gfwlist -server=/.uymaarip.com/127.0.0.1#7913 -ipset=/.uymaarip.com/gfwlist -server=/.fofldfradio.org/127.0.0.1#7913 -ipset=/.fofldfradio.org/gfwlist -server=/.uyghurpress.com/127.0.0.1#7913 -ipset=/.uyghurpress.com/gfwlist -server=/.uyghurcongress.org/127.0.0.1#7913 -ipset=/.uyghurcongress.org/gfwlist -server=/.slutload.com/127.0.0.1#7913 -ipset=/.slutload.com/gfwlist -server=/.uyghurcanadiansociety.org/127.0.0.1#7913 -ipset=/.uyghurcanadiansociety.org/gfwlist -server=/.uyghuramerican.org/127.0.0.1#7913 -ipset=/.uyghuramerican.org/gfwlist -server=/.greenpeace.com.tw/127.0.0.1#7913 -ipset=/.greenpeace.com.tw/gfwlist -server=/.uyghur.co.uk/127.0.0.1#7913 -ipset=/.uyghur.co.uk/gfwlist -server=/.uwants.net/127.0.0.1#7913 -ipset=/.uwants.net/gfwlist -server=/.bestvpn.com/127.0.0.1#7913 -ipset=/.bestvpn.com/gfwlist -server=/.uu-gg.com/127.0.0.1#7913 -ipset=/.uu-gg.com/gfwlist -server=/.mediafire.com/127.0.0.1#7913 -ipset=/.mediafire.com/gfwlist -server=/.utopianpal.com/127.0.0.1#7913 -ipset=/.utopianpal.com/gfwlist -server=/.canyu.org/127.0.0.1#7913 -ipset=/.canyu.org/gfwlist -server=/.familyfed.org/127.0.0.1#7913 -ipset=/.familyfed.org/gfwlist -server=/.usus.cc/127.0.0.1#7913 -ipset=/.usus.cc/gfwlist -server=/.breakgfw.com/127.0.0.1#7913 -ipset=/.breakgfw.com/gfwlist -server=/.ipobar.com/127.0.0.1#7913 -ipset=/.ipobar.com/gfwlist -server=/.pscp.tv/127.0.0.1#7913 -ipset=/.pscp.tv/gfwlist -server=/.zspeeder.me/127.0.0.1#7913 -ipset=/.zspeeder.me/gfwlist -server=/.usocctn.com/127.0.0.1#7913 -ipset=/.usocctn.com/gfwlist -server=/.faluninfo.de/127.0.0.1#7913 -ipset=/.faluninfo.de/gfwlist -server=/.lhakar.org/127.0.0.1#7913 -ipset=/.lhakar.org/gfwlist -server=/.a-normal-day.com/127.0.0.1#7913 -ipset=/.a-normal-day.com/gfwlist -server=/.imb.org/127.0.0.1#7913 -ipset=/.imb.org/gfwlist -server=/.iipdigital.usembassy.gov/127.0.0.1#7913 -ipset=/.iipdigital.usembassy.gov/gfwlist -server=/.usaip.eu/127.0.0.1#7913 -ipset=/.usaip.eu/gfwlist -server=/.xiaod.in/127.0.0.1#7913 -ipset=/.xiaod.in/gfwlist -server=/.fgmtv.net/127.0.0.1#7913 -ipset=/.fgmtv.net/gfwlist -server=/.urlborg.com/127.0.0.1#7913 -ipset=/.urlborg.com/gfwlist -server=/.livestation.com/127.0.0.1#7913 -ipset=/.livestation.com/gfwlist -server=/.dailynews.sina.com/127.0.0.1#7913 -ipset=/.dailynews.sina.com/gfwlist -server=/.tor.cn.uptodown.com/127.0.0.1#7913 -ipset=/.tor.cn.uptodown.com/gfwlist -server=/.cristyli.com/127.0.0.1#7913 -ipset=/.cristyli.com/gfwlist -server=/.uproxy.org/127.0.0.1#7913 -ipset=/.uproxy.org/gfwlist -server=/.maturejp.com/127.0.0.1#7913 -ipset=/.maturejp.com/gfwlist -server=/.upornia.com/127.0.0.1#7913 -ipset=/.upornia.com/gfwlist -server=/.erights.net/127.0.0.1#7913 -ipset=/.erights.net/gfwlist -server=/.upmedia.mg/127.0.0.1#7913 -ipset=/.upmedia.mg/gfwlist -server=/.uploaded.to/127.0.0.1#7913 -ipset=/.uploaded.to/gfwlist -server=/.tbssqh.org/127.0.0.1#7913 -ipset=/.tbssqh.org/gfwlist -server=/.prozz.net/127.0.0.1#7913 -ipset=/.prozz.net/gfwlist -server=/.dphk.org/127.0.0.1#7913 -ipset=/.dphk.org/gfwlist -server=/.dajiyuan.com/127.0.0.1#7913 -ipset=/.dajiyuan.com/gfwlist -server=/.greatfirewallofchina.org/127.0.0.1#7913 -ipset=/.greatfirewallofchina.org/gfwlist -server=/.hkcnews.com/127.0.0.1#7913 -ipset=/.hkcnews.com/gfwlist -server=/.tibet.nu/127.0.0.1#7913 -ipset=/.tibet.nu/gfwlist -server=/.bbs.junglobal.net/127.0.0.1#7913 -ipset=/.bbs.junglobal.net/gfwlist -server=/.untraceable.us/127.0.0.1#7913 -ipset=/.untraceable.us/gfwlist -server=/.chinasocialdemocraticparty.com/127.0.0.1#7913 -ipset=/.chinasocialdemocraticparty.com/gfwlist -server=/.unpo.org/127.0.0.1#7913 -ipset=/.unpo.org/gfwlist -server=/.penchinese.com/127.0.0.1#7913 -ipset=/.penchinese.com/gfwlist -server=/.zvereff.com/127.0.0.1#7913 -ipset=/.zvereff.com/gfwlist -server=/.unknownspace.org/127.0.0.1#7913 -ipset=/.unknownspace.org/gfwlist -server=/.pureconcepts.net/127.0.0.1#7913 -ipset=/.pureconcepts.net/gfwlist -server=/.googleusercontent.com/127.0.0.1#7913 -ipset=/.googleusercontent.com/gfwlist -server=/.gaybubble.com/127.0.0.1#7913 -ipset=/.gaybubble.com/gfwlist -server=/.unix100.com/127.0.0.1#7913 -ipset=/.unix100.com/gfwlist -server=/.unification.net/127.0.0.1#7913 -ipset=/.unification.net/gfwlist -server=/.wallproxy.com/127.0.0.1#7913 -ipset=/.wallproxy.com/gfwlist -server=/.rssmeme.com/127.0.0.1#7913 -ipset=/.rssmeme.com/gfwlist -server=/.mysecondarydns.com/127.0.0.1#7913 -ipset=/.mysecondarydns.com/gfwlist -server=/.umich.edu/127.0.0.1#7913 -ipset=/.umich.edu/gfwlist -server=/.ultraxs.com/127.0.0.1#7913 -ipset=/.ultraxs.com/gfwlist -server=/.juyuange.org/127.0.0.1#7913 -ipset=/.juyuange.org/gfwlist -server=/.multiupload.com/127.0.0.1#7913 -ipset=/.multiupload.com/gfwlist -server=/.hqsbnet.wordpress.com/127.0.0.1#7913 -ipset=/.hqsbnet.wordpress.com/gfwlist -server=/.uighurbiz.net/127.0.0.1#7913 -ipset=/.uighurbiz.net/gfwlist -server=/.uhrp.org/127.0.0.1#7913 -ipset=/.uhrp.org/gfwlist -server=/.uforadio.com.tw/127.0.0.1#7913 -ipset=/.uforadio.com.tw/gfwlist -server=/.sjum.cn/127.0.0.1#7913 -ipset=/.sjum.cn/gfwlist -server=/.udnbkk.com/127.0.0.1#7913 -ipset=/.udnbkk.com/gfwlist -server=/.raw.githubusercontent.com/127.0.0.1#7913 -ipset=/.raw.githubusercontent.com/gfwlist -server=/.china.ucanews.com/127.0.0.1#7913 -ipset=/.china.ucanews.com/gfwlist -server=/.ift.tt/127.0.0.1#7913 -ipset=/.ift.tt/gfwlist -server=/.srcf.ucam.org/127.0.0.1#7913 -ipset=/.srcf.ucam.org/gfwlist -server=/.mash.to/127.0.0.1#7913 -ipset=/.mash.to/gfwlist -server=/.uc-japan.org/127.0.0.1#7913 -ipset=/.uc-japan.org/gfwlist -server=/.youpai.org/127.0.0.1#7913 -ipset=/.youpai.org/gfwlist -server=/.taolun.info/127.0.0.1#7913 -ipset=/.taolun.info/gfwlist -server=/.u9un.com/127.0.0.1#7913 -ipset=/.u9un.com/gfwlist -server=/.contests.twilio.com/127.0.0.1#7913 -ipset=/.contests.twilio.com/gfwlist -server=/.blogs.tampabay.com/127.0.0.1#7913 -ipset=/.blogs.tampabay.com/gfwlist -server=/.legaltech.law.com/127.0.0.1#7913 -ipset=/.legaltech.law.com/gfwlist -server=/.ns02.info/127.0.0.1#7913 -ipset=/.ns02.info/gfwlist -server=/.unseen.is/127.0.0.1#7913 -ipset=/.unseen.is/gfwlist -server=/.politicalconsultation.org/127.0.0.1#7913 -ipset=/.politicalconsultation.org/gfwlist -server=/.typepad.com/127.0.0.1#7913 -ipset=/.typepad.com/gfwlist -server=/.monocloud.me/127.0.0.1#7913 -ipset=/.monocloud.me/gfwlist -server=/.txxx.com/127.0.0.1#7913 -ipset=/.txxx.com/gfwlist -server=/.binux.me/127.0.0.1#7913 -ipset=/.binux.me/gfwlist -server=/.fooooo.com/127.0.0.1#7913 -ipset=/.fooooo.com/gfwlist -server=/.twskype.com/127.0.0.1#7913 -ipset=/.twskype.com/gfwlist -server=/.twnorth.org.tw/127.0.0.1#7913 -ipset=/.twnorth.org.tw/gfwlist -server=/.chinadigitaltimes.net/127.0.0.1#7913 -ipset=/.chinadigitaltimes.net/gfwlist -server=/.twiyia.com/127.0.0.1#7913 -ipset=/.twiyia.com/gfwlist -server=/.boysfood.com/127.0.0.1#7913 -ipset=/.boysfood.com/gfwlist -server=/.chinadialogue.net/127.0.0.1#7913 -ipset=/.chinadialogue.net/gfwlist -server=/.tpi.org.tw/127.0.0.1#7913 -ipset=/.tpi.org.tw/gfwlist -server=/.expekt.com/127.0.0.1#7913 -ipset=/.expekt.com/gfwlist -server=/.twittermail.com/127.0.0.1#7913 -ipset=/.twittermail.com/gfwlist -server=/.twittergadget.com/127.0.0.1#7913 -ipset=/.twittergadget.com/gfwlist -server=/.megurineluka.com/127.0.0.1#7913 -ipset=/.megurineluka.com/gfwlist -server=/.twitterfeed.com/127.0.0.1#7913 -ipset=/.twitterfeed.com/gfwlist -server=/.ourtv.hk/127.0.0.1#7913 -ipset=/.ourtv.hk/gfwlist -server=/.powerphoto.org/127.0.0.1#7913 -ipset=/.powerphoto.org/gfwlist -server=/.shapeservices.com/127.0.0.1#7913 -ipset=/.shapeservices.com/gfwlist -server=/.twittercounter.com/127.0.0.1#7913 -ipset=/.twittercounter.com/gfwlist -server=/.chinatweeps.com/127.0.0.1#7913 -ipset=/.chinatweeps.com/gfwlist -server=/.twitter4j.org/127.0.0.1#7913 -ipset=/.twitter4j.org/gfwlist -server=/.jav101.com/127.0.0.1#7913 -ipset=/.jav101.com/gfwlist -server=/.twttr.com/127.0.0.1#7913 -ipset=/.twttr.com/gfwlist -server=/.turbotwitter.com/127.0.0.1#7913 -ipset=/.turbotwitter.com/gfwlist -server=/.ifjc.org/127.0.0.1#7913 -ipset=/.ifjc.org/gfwlist -server=/.cmi.org.tw/127.0.0.1#7913 -ipset=/.cmi.org.tw/gfwlist -server=/.tweepguide.com/127.0.0.1#7913 -ipset=/.tweepguide.com/gfwlist -server=/.powercx.com/127.0.0.1#7913 -ipset=/.powercx.com/gfwlist -server=/.twitoaster.com/127.0.0.1#7913 -ipset=/.twitoaster.com/gfwlist -server=/.sacks.com/127.0.0.1#7913 -ipset=/.sacks.com/gfwlist -server=/.twitiq.com/127.0.0.1#7913 -ipset=/.twitiq.com/gfwlist -server=/.gamez.com.tw/127.0.0.1#7913 -ipset=/.gamez.com.tw/gfwlist -server=/.xinyubbs.net/127.0.0.1#7913 -ipset=/.xinyubbs.net/gfwlist -server=/.twiggit.org/127.0.0.1#7913 -ipset=/.twiggit.org/gfwlist -server=/.twisternow.com/127.0.0.1#7913 -ipset=/.twisternow.com/gfwlist -server=/.twisterio.com/127.0.0.1#7913 -ipset=/.twisterio.com/gfwlist -server=/.putlocker.com/127.0.0.1#7913 -ipset=/.putlocker.com/gfwlist -server=/.mywww.biz/127.0.0.1#7913 -ipset=/.mywww.biz/gfwlist -server=/.paltalk.com/127.0.0.1#7913 -ipset=/.paltalk.com/gfwlist -server=/.revleft.com/127.0.0.1#7913 -ipset=/.revleft.com/gfwlist -server=/.twishort.com/127.0.0.1#7913 -ipset=/.twishort.com/gfwlist -server=/.twip.me/127.0.0.1#7913 -ipset=/.twip.me/gfwlist -server=/.63i.com/127.0.0.1#7913 -ipset=/.63i.com/gfwlist -server=/.tibetansports.org/127.0.0.1#7913 -ipset=/.tibetansports.org/gfwlist -server=/.twicsy.com/127.0.0.1#7913 -ipset=/.twicsy.com/gfwlist -server=/.twibs.com/127.0.0.1#7913 -ipset=/.twibs.com/gfwlist -server=/.vimeo.com/127.0.0.1#7913 -ipset=/.vimeo.com/gfwlist -server=/.cn.voa.mobi/127.0.0.1#7913 -ipset=/.cn.voa.mobi/gfwlist -server=/.51jav.org/127.0.0.1#7913 -ipset=/.51jav.org/gfwlist -server=/.famunion.com/127.0.0.1#7913 -ipset=/.famunion.com/gfwlist -server=/.twgreatdaily.com/127.0.0.1#7913 -ipset=/.twgreatdaily.com/gfwlist -server=/.foxtang.com/127.0.0.1#7913 -ipset=/.foxtang.com/gfwlist -server=/.fakku.net/127.0.0.1#7913 -ipset=/.fakku.net/gfwlist -server=/.la-forum.org/127.0.0.1#7913 -ipset=/.la-forum.org/gfwlist -server=/.tweetwally.com/127.0.0.1#7913 -ipset=/.tweetwally.com/gfwlist -server=/.tweetree.com/127.0.0.1#7913 -ipset=/.tweetree.com/gfwlist -server=/.ladbrokes.com/127.0.0.1#7913 -ipset=/.ladbrokes.com/gfwlist -server=/.100ke.org/127.0.0.1#7913 -ipset=/.100ke.org/gfwlist -server=/.jetos.com/127.0.0.1#7913 -ipset=/.jetos.com/gfwlist -server=/.tweetphoto.com/127.0.0.1#7913 -ipset=/.tweetphoto.com/gfwlist -server=/.skyvegas.com/127.0.0.1#7913 -ipset=/.skyvegas.com/gfwlist -server=/.tweetmylast.fm/127.0.0.1#7913 -ipset=/.tweetmylast.fm/gfwlist -server=/.ntdtv.ru/127.0.0.1#7913 -ipset=/.ntdtv.ru/gfwlist -server=/.qanote.com/127.0.0.1#7913 -ipset=/.qanote.com/gfwlist -server=/.mtw.tl/127.0.0.1#7913 -ipset=/.mtw.tl/gfwlist -server=/.deck.ly/127.0.0.1#7913 -ipset=/.deck.ly/gfwlist -server=/.next11.co.jp/127.0.0.1#7913 -ipset=/.next11.co.jp/gfwlist -server=/.sherabgyaltsen.com/127.0.0.1#7913 -ipset=/.sherabgyaltsen.com/gfwlist -server=/.tweetboner.biz/127.0.0.1#7913 -ipset=/.tweetboner.biz/gfwlist -server=/.tweepml.org/127.0.0.1#7913 -ipset=/.tweepml.org/gfwlist -server=/.hopedialogue.org/127.0.0.1#7913 -ipset=/.hopedialogue.org/gfwlist -server=/.help.linksalpha.com/127.0.0.1#7913 -ipset=/.help.linksalpha.com/gfwlist -server=/.imgchili.net/127.0.0.1#7913 -ipset=/.imgchili.net/gfwlist -server=/.whereiswerner.com/127.0.0.1#7913 -ipset=/.whereiswerner.com/gfwlist -server=/.twbbs.tw/127.0.0.1#7913 -ipset=/.twbbs.tw/gfwlist -server=/.imlive.com/127.0.0.1#7913 -ipset=/.imlive.com/gfwlist -server=/.tibetanphotoproject.com/127.0.0.1#7913 -ipset=/.tibetanphotoproject.com/gfwlist -server=/.globaljihad.net/127.0.0.1#7913 -ipset=/.globaljihad.net/gfwlist -server=/.guishan.org/127.0.0.1#7913 -ipset=/.guishan.org/gfwlist -server=/.carabinasypistolas.com/127.0.0.1#7913 -ipset=/.carabinasypistolas.com/gfwlist -server=/.coolder.com/127.0.0.1#7913 -ipset=/.coolder.com/gfwlist -server=/.community.windy.com/127.0.0.1#7913 -ipset=/.community.windy.com/gfwlist -server=/.alphaporno.com/127.0.0.1#7913 -ipset=/.alphaporno.com/gfwlist -server=/.twapperkeeper.com/127.0.0.1#7913 -ipset=/.twapperkeeper.com/gfwlist -server=/.tw-blog.com/127.0.0.1#7913 -ipset=/.tw-blog.com/gfwlist -server=/.tvunetworks.com/127.0.0.1#7913 -ipset=/.tvunetworks.com/gfwlist -server=/.futuremessage.org/127.0.0.1#7913 -ipset=/.futuremessage.org/gfwlist -server=/.tvmost.com.hk/127.0.0.1#7913 -ipset=/.tvmost.com.hk/gfwlist -server=/.chinatown.com.au/127.0.0.1#7913 -ipset=/.chinatown.com.au/gfwlist -server=/.china-mmm.sa.com/127.0.0.1#7913 -ipset=/.china-mmm.sa.com/gfwlist -server=/.tvboxnow.com/127.0.0.1#7913 -ipset=/.tvboxnow.com/gfwlist -server=/.hoxx.com/127.0.0.1#7913 -ipset=/.hoxx.com/gfwlist -server=/.sugarsync.com/127.0.0.1#7913 -ipset=/.sugarsync.com/gfwlist -server=/.onedrive.live.com/127.0.0.1#7913 -ipset=/.onedrive.live.com/gfwlist -server=/.6parker.com/127.0.0.1#7913 -ipset=/.6parker.com/gfwlist -server=/.cmp.hku.hk/127.0.0.1#7913 -ipset=/.cmp.hku.hk/gfwlist -server=/.slutmoonbeam.com/127.0.0.1#7913 -ipset=/.slutmoonbeam.com/gfwlist -server=/.fuq.com/127.0.0.1#7913 -ipset=/.fuq.com/gfwlist -server=/.lecloud.net/127.0.0.1#7913 -ipset=/.lecloud.net/gfwlist -server=/.tumblr.com/127.0.0.1#7913 -ipset=/.tumblr.com/gfwlist -server=/.gobet.cc/127.0.0.1#7913 -ipset=/.gobet.cc/gfwlist -server=/.tuvpn.com/127.0.0.1#7913 -ipset=/.tuvpn.com/gfwlist -server=/.app.tutanota.com/127.0.0.1#7913 -ipset=/.app.tutanota.com/gfwlist -server=/.tushycash.com/127.0.0.1#7913 -ipset=/.tushycash.com/gfwlist -server=/.dropbox.com/127.0.0.1#7913 -ipset=/.dropbox.com/gfwlist -server=/.have8.com/127.0.0.1#7913 -ipset=/.have8.com/gfwlist -server=/.nakuz.com/127.0.0.1#7913 -ipset=/.nakuz.com/gfwlist -server=/.tuitwit.com/127.0.0.1#7913 -ipset=/.tuitwit.com/gfwlist -server=/.ned.org/127.0.0.1#7913 -ipset=/.ned.org/gfwlist -server=/.muslimvideo.com/127.0.0.1#7913 -ipset=/.muslimvideo.com/gfwlist -server=/.tuo8.pw/127.0.0.1#7913 -ipset=/.tuo8.pw/gfwlist -server=/.summify.com/127.0.0.1#7913 -ipset=/.summify.com/gfwlist -server=/.gate-project.com/127.0.0.1#7913 -ipset=/.gate-project.com/gfwlist -server=/.steel-storm.com/127.0.0.1#7913 -ipset=/.steel-storm.com/gfwlist -server=/.tuo8.in/127.0.0.1#7913 -ipset=/.tuo8.in/gfwlist -server=/.tuo8.hk/127.0.0.1#7913 -ipset=/.tuo8.hk/gfwlist -server=/.tuo8.club/127.0.0.1#7913 -ipset=/.tuo8.club/gfwlist -server=/.kyoyue.com/127.0.0.1#7913 -ipset=/.kyoyue.com/gfwlist -server=/.tunnelr.com/127.0.0.1#7913 -ipset=/.tunnelr.com/gfwlist -server=/.tunein.com/127.0.0.1#7913 -ipset=/.tunein.com/gfwlist -server=/.qusi8.net/127.0.0.1#7913 -ipset=/.qusi8.net/gfwlist -server=/.fsurf.com/127.0.0.1#7913 -ipset=/.fsurf.com/gfwlist -server=/.tibet-munich.de/127.0.0.1#7913 -ipset=/.tibet-munich.de/gfwlist -server=/.kenengba.com/127.0.0.1#7913 -ipset=/.kenengba.com/gfwlist -server=/.hklts.org.hk/127.0.0.1#7913 -ipset=/.hklts.org.hk/gfwlist -server=/.bbs.tuitui.info/127.0.0.1#7913 -ipset=/.bbs.tuitui.info/gfwlist -server=/.seesmic.com/127.0.0.1#7913 -ipset=/.seesmic.com/gfwlist -server=/.picturesocial.com/127.0.0.1#7913 -ipset=/.picturesocial.com/gfwlist -server=/.bullog.org/127.0.0.1#7913 -ipset=/.bullog.org/gfwlist -server=/.tuidang.org/127.0.0.1#7913 -ipset=/.tuidang.org/gfwlist -server=/.artsy.net/127.0.0.1#7913 -ipset=/.artsy.net/gfwlist -server=/.tubestack.com/127.0.0.1#7913 -ipset=/.tubestack.com/gfwlist -server=/.tw.streetvoice.com/127.0.0.1#7913 -ipset=/.tw.streetvoice.com/gfwlist -server=/.tube911.com/127.0.0.1#7913 -ipset=/.tube911.com/gfwlist -server=/.maiio.net/127.0.0.1#7913 -ipset=/.maiio.net/gfwlist -server=/.le-vpn.com/127.0.0.1#7913 -ipset=/.le-vpn.com/gfwlist -server=/.twitmania.com/127.0.0.1#7913 -ipset=/.twitmania.com/gfwlist -server=/.chinainperspective.com/127.0.0.1#7913 -ipset=/.chinainperspective.com/gfwlist -server=/.unblock-us.com/127.0.0.1#7913 -ipset=/.unblock-us.com/gfwlist -server=/.tt1069.com/127.0.0.1#7913 -ipset=/.tt1069.com/gfwlist -server=/.tsunagarumon.com/127.0.0.1#7913 -ipset=/.tsunagarumon.com/gfwlist -server=/.tsquare.tv/127.0.0.1#7913 -ipset=/.tsquare.tv/gfwlist -server=/.piposay.com/127.0.0.1#7913 -ipset=/.piposay.com/gfwlist -server=/.ccvoice.ca/127.0.0.1#7913 -ipset=/.ccvoice.ca/gfwlist -server=/.truveo.com/127.0.0.1#7913 -ipset=/.truveo.com/gfwlist -server=/.google.as/127.0.0.1#7913 -ipset=/.google.as/gfwlist -server=/.appledaily.com.hk/127.0.0.1#7913 -ipset=/.appledaily.com.hk/gfwlist -server=/.lsmwebcast.com/127.0.0.1#7913 -ipset=/.lsmwebcast.com/gfwlist -server=/.truth101.co.tv/127.0.0.1#7913 -ipset=/.truth101.co.tv/gfwlist -server=/.google.sc/127.0.0.1#7913 -ipset=/.google.sc/gfwlist -server=/.liuxiaobo.net/127.0.0.1#7913 -ipset=/.liuxiaobo.net/gfwlist -server=/.sellclassics.com/127.0.0.1#7913 -ipset=/.sellclassics.com/gfwlist -server=/.trouw.nl/127.0.0.1#7913 -ipset=/.trouw.nl/gfwlist -server=/.quranexplorer.com/127.0.0.1#7913 -ipset=/.quranexplorer.com/gfwlist -server=/.ienergy1.com/127.0.0.1#7913 -ipset=/.ienergy1.com/gfwlist -server=/.abc.pp.ru/127.0.0.1#7913 -ipset=/.abc.pp.ru/gfwlist -server=/.transparency.org/127.0.0.1#7913 -ipset=/.transparency.org/gfwlist -server=/.cnnews.chosun.com/127.0.0.1#7913 -ipset=/.cnnews.chosun.com/gfwlist -server=/.traffichaus.com/127.0.0.1#7913 -ipset=/.traffichaus.com/gfwlist -server=/.webwarper.net/127.0.0.1#7913 -ipset=/.webwarper.net/gfwlist -server=/.weekmag.info/127.0.0.1#7913 -ipset=/.weekmag.info/gfwlist -server=/.blog.martinoei.com/127.0.0.1#7913 -ipset=/.blog.martinoei.com/gfwlist -server=/.nvquan.org/127.0.0.1#7913 -ipset=/.nvquan.org/gfwlist -server=/.straplessdildo.com/127.0.0.1#7913 -ipset=/.straplessdildo.com/gfwlist -server=/.facesoftibetanselfimmolators.info/127.0.0.1#7913 -ipset=/.facesoftibetanselfimmolators.info/gfwlist -server=/.searchtruth.com/127.0.0.1#7913 -ipset=/.searchtruth.com/gfwlist -server=/.freessh.us/127.0.0.1#7913 -ipset=/.freessh.us/gfwlist -server=/.torrenty.org/127.0.0.1#7913 -ipset=/.torrenty.org/gfwlist -server=/.torrentprivacy.com/127.0.0.1#7913 -ipset=/.torrentprivacy.com/gfwlist -server=/.torproject.org/127.0.0.1#7913 -ipset=/.torproject.org/gfwlist -server=/.torcn.com/127.0.0.1#7913 -ipset=/.torcn.com/gfwlist -server=/.twitch.tv/127.0.0.1#7913 -ipset=/.twitch.tv/gfwlist -server=/.helloandroid.com/127.0.0.1#7913 -ipset=/.helloandroid.com/gfwlist -server=/.tora.to/127.0.0.1#7913 -ipset=/.tora.to/gfwlist -server=/.bbc.co.uk/127.0.0.1#7913 -ipset=/.bbc.co.uk/gfwlist -server=/.toptip.ca/127.0.0.1#7913 -ipset=/.toptip.ca/gfwlist -server=/.updates.tdesktop.com/127.0.0.1#7913 -ipset=/.updates.tdesktop.com/gfwlist -server=/.topsy.com/127.0.0.1#7913 -ipset=/.topsy.com/gfwlist -server=/.iblogserv-f.net/127.0.0.1#7913 -ipset=/.iblogserv-f.net/gfwlist -server=/.eu.org/127.0.0.1#7913 -ipset=/.eu.org/gfwlist -server=/.topshareware.com/127.0.0.1#7913 -ipset=/.topshareware.com/gfwlist -server=/.blueangellive.com/127.0.0.1#7913 -ipset=/.blueangellive.com/gfwlist -server=/.top.tv/127.0.0.1#7913 -ipset=/.top.tv/gfwlist -server=/.torguard.net/127.0.0.1#7913 -ipset=/.torguard.net/gfwlist -server=/.wowrk.com/127.0.0.1#7913 -ipset=/.wowrk.com/gfwlist -server=/.ra.gg/127.0.0.1#7913 -ipset=/.ra.gg/gfwlist -server=/.topnews.in/127.0.0.1#7913 -ipset=/.topnews.in/gfwlist -server=/.fpmt.tw/127.0.0.1#7913 -ipset=/.fpmt.tw/gfwlist -server=/.murmur.tw/127.0.0.1#7913 -ipset=/.murmur.tw/gfwlist -server=/.xm.com/127.0.0.1#7913 -ipset=/.xm.com/gfwlist -server=/.1eew.com/127.0.0.1#7913 -ipset=/.1eew.com/gfwlist -server=/.top81.ws/127.0.0.1#7913 -ipset=/.top81.ws/gfwlist -server=/.zhao.jinhai.de/127.0.0.1#7913 -ipset=/.zhao.jinhai.de/gfwlist -server=/.drsunacademy.com/127.0.0.1#7913 -ipset=/.drsunacademy.com/gfwlist -server=/.rferl.org/127.0.0.1#7913 -ipset=/.rferl.org/gfwlist -server=/.ipfire.org/127.0.0.1#7913 -ipset=/.ipfire.org/gfwlist -server=/.smartdnsproxy.com/127.0.0.1#7913 -ipset=/.smartdnsproxy.com/gfwlist -server=/.playboyplus.com/127.0.0.1#7913 -ipset=/.playboyplus.com/gfwlist -server=/.noodlevpn.com/127.0.0.1#7913 -ipset=/.noodlevpn.com/gfwlist -server=/.bjnewlife.org/127.0.0.1#7913 -ipset=/.bjnewlife.org/gfwlist -server=/.x.company/127.0.0.1#7913 -ipset=/.x.company/gfwlist -server=/.islamicity.com/127.0.0.1#7913 -ipset=/.islamicity.com/gfwlist -server=/.swissinfo.ch/127.0.0.1#7913 -ipset=/.swissinfo.ch/gfwlist -server=/.cn-proxy.com/127.0.0.1#7913 -ipset=/.cn-proxy.com/gfwlist -server=/.tw.tomonews.net/127.0.0.1#7913 -ipset=/.tw.tomonews.net/gfwlist -server=/.tokyocn.com/127.0.0.1#7913 -ipset=/.tokyocn.com/gfwlist -server=/.tokyo-247.com/127.0.0.1#7913 -ipset=/.tokyo-247.com/gfwlist -server=/.wikileaks.org/127.0.0.1#7913 -ipset=/.wikileaks.org/gfwlist -server=/.tnaflix.com/127.0.0.1#7913 -ipset=/.tnaflix.com/gfwlist -server=/.google.kz/127.0.0.1#7913 -ipset=/.google.kz/gfwlist -server=/.orient-doll.com/127.0.0.1#7913 -ipset=/.orient-doll.com/gfwlist -server=/.cctongbao.com/127.0.0.1#7913 -ipset=/.cctongbao.com/gfwlist -server=/.hidein.net/127.0.0.1#7913 -ipset=/.hidein.net/gfwlist -server=/.china21.com/127.0.0.1#7913 -ipset=/.china21.com/gfwlist -server=/.daliulian.org/127.0.0.1#7913 -ipset=/.daliulian.org/gfwlist -server=/.hwadzan.tw/127.0.0.1#7913 -ipset=/.hwadzan.tw/gfwlist -server=/.mycanadanow.com/127.0.0.1#7913 -ipset=/.mycanadanow.com/gfwlist -server=/.tmagazine.com/127.0.0.1#7913 -ipset=/.tmagazine.com/gfwlist -server=/.ninecommentaries.com/127.0.0.1#7913 -ipset=/.ninecommentaries.com/gfwlist -server=/.tkcs-collins.com/127.0.0.1#7913 -ipset=/.tkcs-collins.com/gfwlist -server=/.googlefiber.net/127.0.0.1#7913 -ipset=/.googlefiber.net/gfwlist -server=/.wn.com/127.0.0.1#7913 -ipset=/.wn.com/gfwlist -server=/.guaguass.com/127.0.0.1#7913 -ipset=/.guaguass.com/gfwlist -server=/.tintuc101.com/127.0.0.1#7913 -ipset=/.tintuc101.com/gfwlist -server=/.skybet.com/127.0.0.1#7913 -ipset=/.skybet.com/gfwlist -server=/.blog.tiney.com/127.0.0.1#7913 -ipset=/.blog.tiney.com/gfwlist -server=/.shiksha.com/127.0.0.1#7913 -ipset=/.shiksha.com/gfwlist -server=/.sustainability.google/127.0.0.1#7913 -ipset=/.sustainability.google/gfwlist -server=/.lianyue.net/127.0.0.1#7913 -ipset=/.lianyue.net/gfwlist -server=/.timdir.com/127.0.0.1#7913 -ipset=/.timdir.com/gfwlist -server=/.video.aol.ca/127.0.0.1#7913 -ipset=/.video.aol.ca/gfwlist -server=/.faithfuleye.com/127.0.0.1#7913 -ipset=/.faithfuleye.com/gfwlist -server=/.gmail.com/127.0.0.1#7913 -ipset=/.gmail.com/gfwlist -server=/.bt2mag.com/127.0.0.1#7913 -ipset=/.bt2mag.com/gfwlist -server=/.tibetsupportgroup.org/127.0.0.1#7913 -ipset=/.tibetsupportgroup.org/gfwlist -server=/.tibetsun.com/127.0.0.1#7913 -ipset=/.tibetsun.com/gfwlist -server=/.tibetsociety.com/127.0.0.1#7913 -ipset=/.tibetsociety.com/gfwlist -server=/.cn.ibtimes.com/127.0.0.1#7913 -ipset=/.cn.ibtimes.com/gfwlist -server=/.tibetpolicy.eu/127.0.0.1#7913 -ipset=/.tibetpolicy.eu/gfwlist -server=/.ccue.com/127.0.0.1#7913 -ipset=/.ccue.com/gfwlist -server=/.wikiversity.org/127.0.0.1#7913 -ipset=/.wikiversity.org/gfwlist -server=/.chingcheong.com/127.0.0.1#7913 -ipset=/.chingcheong.com/gfwlist -server=/.goofind.com/127.0.0.1#7913 -ipset=/.goofind.com/gfwlist -server=/.tibetonline.tv/127.0.0.1#7913 -ipset=/.tibetonline.tv/gfwlist -server=/.tibetoffice.com.au/127.0.0.1#7913 -ipset=/.tibetoffice.com.au/gfwlist -server=/.elgoog.im/127.0.0.1#7913 -ipset=/.elgoog.im/gfwlist -server=/.idv.tw/127.0.0.1#7913 -ipset=/.idv.tw/gfwlist -server=/.tibetoffice.ch/127.0.0.1#7913 -ipset=/.tibetoffice.ch/gfwlist -server=/.htkou.net/127.0.0.1#7913 -ipset=/.htkou.net/gfwlist -server=/.tibetnetwork.org/127.0.0.1#7913 -ipset=/.tibetnetwork.org/gfwlist -server=/.qxbbs.org/127.0.0.1#7913 -ipset=/.qxbbs.org/gfwlist -server=/.ablwang.com/127.0.0.1#7913 -ipset=/.ablwang.com/gfwlist -server=/.alwaysdata.com/127.0.0.1#7913 -ipset=/.alwaysdata.com/gfwlist -server=/.tibetinfonet.net/127.0.0.1#7913 -ipset=/.tibetinfonet.net/gfwlist -server=/.tibethouse.us/127.0.0.1#7913 -ipset=/.tibethouse.us/gfwlist -server=/.tibethouse.jp/127.0.0.1#7913 -ipset=/.tibethouse.jp/gfwlist -server=/.tibethaus.com/127.0.0.1#7913 -ipset=/.tibethaus.com/gfwlist -server=/.gyatsostudio.com/127.0.0.1#7913 -ipset=/.gyatsostudio.com/gfwlist -server=/.tibetgermany.de/127.0.0.1#7913 -ipset=/.tibetgermany.de/gfwlist -server=/.tibetgermany.com/127.0.0.1#7913 -ipset=/.tibetgermany.com/gfwlist -server=/.tibetexpress.net/127.0.0.1#7913 -ipset=/.tibetexpress.net/gfwlist -server=/.ns02.us/127.0.0.1#7913 -ipset=/.ns02.us/gfwlist -server=/.cdn.helixstudios.net/127.0.0.1#7913 -ipset=/.cdn.helixstudios.net/gfwlist -server=/.googlepagecreator.com/127.0.0.1#7913 -ipset=/.googlepagecreator.com/gfwlist -server=/.efukt.com/127.0.0.1#7913 -ipset=/.efukt.com/gfwlist -server=/.tibetchild.org/127.0.0.1#7913 -ipset=/.tibetchild.org/gfwlist -server=/.inxian.com/127.0.0.1#7913 -ipset=/.inxian.com/gfwlist -server=/.fc2.com/127.0.0.1#7913 -ipset=/.fc2.com/gfwlist -server=/.tibetcharity.in/127.0.0.1#7913 -ipset=/.tibetcharity.in/gfwlist -server=/.androidplus.co/127.0.0.1#7913 -ipset=/.androidplus.co/gfwlist -server=/.mypopescu.com/127.0.0.1#7913 -ipset=/.mypopescu.com/gfwlist -server=/.tibetanwomen.org/127.0.0.1#7913 -ipset=/.tibetanwomen.org/gfwlist -server=/.bbs.skykiwi.com/127.0.0.1#7913 -ipset=/.bbs.skykiwi.com/gfwlist -server=/.juoaa.com/127.0.0.1#7913 -ipset=/.juoaa.com/gfwlist -server=/.twiffo.com/127.0.0.1#7913 -ipset=/.twiffo.com/gfwlist -server=/.my03.com/127.0.0.1#7913 -ipset=/.my03.com/gfwlist -server=/.mondex.org/127.0.0.1#7913 -ipset=/.mondex.org/gfwlist -server=/.kanshifang.com/127.0.0.1#7913 -ipset=/.kanshifang.com/gfwlist -server=/.swissvpn.net/127.0.0.1#7913 -ipset=/.swissvpn.net/gfwlist -server=/.ddhw.info/127.0.0.1#7913 -ipset=/.ddhw.info/gfwlist -server=/.tibetanreview.net/127.0.0.1#7913 -ipset=/.tibetanreview.net/gfwlist -server=/.tibetanbuddhistinstitute.org/127.0.0.1#7913 -ipset=/.tibetanbuddhistinstitute.org/gfwlist -server=/.daolan.net/127.0.0.1#7913 -ipset=/.daolan.net/gfwlist -server=/.ushuarencity.echainhost.com/127.0.0.1#7913 -ipset=/.ushuarencity.echainhost.com/gfwlist -server=/.singtaousa.com/127.0.0.1#7913 -ipset=/.singtaousa.com/gfwlist -server=/.shellfire.de/127.0.0.1#7913 -ipset=/.shellfire.de/gfwlist -server=/.twbbs.org/127.0.0.1#7913 -ipset=/.twbbs.org/gfwlist -server=/.quantumbooter.net/127.0.0.1#7913 -ipset=/.quantumbooter.net/gfwlist -server=/.library.usc.cuhk.edu.hk/127.0.0.1#7913 -ipset=/.library.usc.cuhk.edu.hk/gfwlist -server=/.sm-miracle.com/127.0.0.1#7913 -ipset=/.sm-miracle.com/gfwlist -server=/.red-lang.org/127.0.0.1#7913 -ipset=/.red-lang.org/gfwlist -server=/.mjlsh.usc.cuhk.edu.hk/127.0.0.1#7913 -ipset=/.mjlsh.usc.cuhk.edu.hk/gfwlist -server=/.bjs.org/127.0.0.1#7913 -ipset=/.bjs.org/gfwlist -server=/.freeforums.org/127.0.0.1#7913 -ipset=/.freeforums.org/gfwlist -server=/.com.google/127.0.0.1#7913 -ipset=/.com.google/gfwlist -server=/.gati.org.tw/127.0.0.1#7913 -ipset=/.gati.org.tw/gfwlist -server=/.tibetanculture.org/127.0.0.1#7913 -ipset=/.tibetanculture.org/gfwlist -server=/.blogspot.tw/127.0.0.1#7913 -ipset=/.blogspot.tw/gfwlist -server=/.tibetancommunityuk.net/127.0.0.1#7913 -ipset=/.tibetancommunityuk.net/gfwlist -server=/.yunchao.net/127.0.0.1#7913 -ipset=/.yunchao.net/gfwlist -server=/.tibetcollection.com/127.0.0.1#7913 -ipset=/.tibetcollection.com/gfwlist -server=/.tibetanlanguage.org/127.0.0.1#7913 -ipset=/.tibetanlanguage.org/gfwlist -server=/.tibetanjournal.com/127.0.0.1#7913 -ipset=/.tibetanjournal.com/gfwlist -server=/.www.americorps.gov/127.0.0.1#7913 -ipset=/.www.americorps.gov/gfwlist -server=/.store.steampowered.com/127.0.0.1#7913 -ipset=/.store.steampowered.com/gfwlist -server=/.squirly.info/127.0.0.1#7913 -ipset=/.squirly.info/gfwlist -server=/.hxwq.org/127.0.0.1#7913 -ipset=/.hxwq.org/gfwlist -server=/.supchina.com/127.0.0.1#7913 -ipset=/.supchina.com/gfwlist -server=/.tibetan.fr/127.0.0.1#7913 -ipset=/.tibetan.fr/gfwlist -server=/.tibetaction.net/127.0.0.1#7913 -ipset=/.tibetaction.net/gfwlist -server=/.anyporn.com/127.0.0.1#7913 -ipset=/.anyporn.com/gfwlist -server=/.free-ss.site/127.0.0.1#7913 -ipset=/.free-ss.site/gfwlist -server=/.earthvpn.com/127.0.0.1#7913 -ipset=/.earthvpn.com/gfwlist -server=/.upload4u.info/127.0.0.1#7913 -ipset=/.upload4u.info/gfwlist -server=/.tibet-initiative.de/127.0.0.1#7913 -ipset=/.tibet-initiative.de/gfwlist -server=/.snaptu.com/127.0.0.1#7913 -ipset=/.snaptu.com/gfwlist -server=/.myspace.com/127.0.0.1#7913 -ipset=/.myspace.com/gfwlist -server=/.tibet-house-trust.co.uk/127.0.0.1#7913 -ipset=/.tibet-house-trust.co.uk/gfwlist -server=/.tibet-foundation.org/127.0.0.1#7913 -ipset=/.tibet-foundation.org/gfwlist -server=/.tibet.to/127.0.0.1#7913 -ipset=/.tibet.to/gfwlist -server=/.tibet.org.tw/127.0.0.1#7913 -ipset=/.tibet.org.tw/gfwlist -server=/.konachan.com/127.0.0.1#7913 -ipset=/.konachan.com/gfwlist -server=/.tibet3rdpole.org/127.0.0.1#7913 -ipset=/.tibet3rdpole.org/gfwlist -server=/.youtube.com/127.0.0.1#7913 -ipset=/.youtube.com/gfwlist -server=/.sheikyermami.com/127.0.0.1#7913 -ipset=/.sheikyermami.com/gfwlist -server=/.tibet.fr/127.0.0.1#7913 -ipset=/.tibet.fr/gfwlist -server=/.tibet.ca/127.0.0.1#7913 -ipset=/.tibet.ca/gfwlist -server=/.tianzhu.org/127.0.0.1#7913 -ipset=/.tianzhu.org/gfwlist -server=/.tiantibooks.org/127.0.0.1#7913 -ipset=/.tiantibooks.org/gfwlist -server=/.post852.com/127.0.0.1#7913 -ipset=/.post852.com/gfwlist -server=/.tiananmenuniv.com/127.0.0.1#7913 -ipset=/.tiananmenuniv.com/gfwlist -server=/.tiananmenmother.org/127.0.0.1#7913 -ipset=/.tiananmenmother.org/gfwlist -server=/.thywords.com/127.0.0.1#7913 -ipset=/.thywords.com/gfwlist -server=/.thumbzilla.com/127.0.0.1#7913 -ipset=/.thumbzilla.com/gfwlist -server=/.blinw.com/127.0.0.1#7913 -ipset=/.blinw.com/gfwlist -server=/.throughnightsfire.com/127.0.0.1#7913 -ipset=/.throughnightsfire.com/gfwlist -server=/.thongdreams.com/127.0.0.1#7913 -ipset=/.thongdreams.com/gfwlist -server=/.ntdtv.com/127.0.0.1#7913 -ipset=/.ntdtv.com/gfwlist -server=/.hidemycomp.com/127.0.0.1#7913 -ipset=/.hidemycomp.com/gfwlist -server=/.muzi.net/127.0.0.1#7913 -ipset=/.muzi.net/gfwlist -server=/.igoogle.com/127.0.0.1#7913 -ipset=/.igoogle.com/gfwlist -server=/.twibble.de/127.0.0.1#7913 -ipset=/.twibble.de/gfwlist -server=/.bx.in.th/127.0.0.1#7913 -ipset=/.bx.in.th/gfwlist -server=/.thevivekspot.com/127.0.0.1#7913 -ipset=/.thevivekspot.com/gfwlist -server=/.thetinhat.com/127.0.0.1#7913 -ipset=/.thetinhat.com/gfwlist -server=/.goldjizz.com/127.0.0.1#7913 -ipset=/.goldjizz.com/gfwlist -server=/.thetibetconnection.org/127.0.0.1#7913 -ipset=/.thetibetconnection.org/gfwlist -server=/.relay.com.tw/127.0.0.1#7913 -ipset=/.relay.com.tw/gfwlist -server=/.bb.ttv.com.tw/127.0.0.1#7913 -ipset=/.bb.ttv.com.tw/gfwlist -server=/.chenpokong.com/127.0.0.1#7913 -ipset=/.chenpokong.com/gfwlist -server=/.thespeeder.com/127.0.0.1#7913 -ipset=/.thespeeder.com/gfwlist -server=/.mycould.com/127.0.0.1#7913 -ipset=/.mycould.com/gfwlist -server=/.vpnsecure.me/127.0.0.1#7913 -ipset=/.vpnsecure.me/gfwlist -server=/.danke4china.net/127.0.0.1#7913 -ipset=/.danke4china.net/gfwlist -server=/.vip-enterprise.com/127.0.0.1#7913 -ipset=/.vip-enterprise.com/gfwlist -server=/.blog.sogoo.org/127.0.0.1#7913 -ipset=/.blog.sogoo.org/gfwlist -server=/.theportalwiki.com/127.0.0.1#7913 -ipset=/.theportalwiki.com/gfwlist -server=/.thepiratebay.org/127.0.0.1#7913 -ipset=/.thepiratebay.org/gfwlist -server=/.co.ao/127.0.0.1#7913 -ipset=/.co.ao/gfwlist -server=/.dynu.net/127.0.0.1#7913 -ipset=/.dynu.net/gfwlist -server=/.thenewslens.com/127.0.0.1#7913 -ipset=/.thenewslens.com/gfwlist -server=/.chinaxchina.com/127.0.0.1#7913 -ipset=/.chinaxchina.com/gfwlist -server=/.sopcast.org/127.0.0.1#7913 -ipset=/.sopcast.org/gfwlist -server=/.freewww.info/127.0.0.1#7913 -ipset=/.freewww.info/gfwlist -server=/.reflectivecode.com/127.0.0.1#7913 -ipset=/.reflectivecode.com/gfwlist -server=/.google.is/127.0.0.1#7913 -ipset=/.google.is/gfwlist -server=/.thehun.net/127.0.0.1#7913 -ipset=/.thehun.net/gfwlist -server=/.cachinese.com/127.0.0.1#7913 -ipset=/.cachinese.com/gfwlist -server=/.nflxext.com/127.0.0.1#7913 -ipset=/.nflxext.com/gfwlist -server=/.freefq.com/127.0.0.1#7913 -ipset=/.freefq.com/gfwlist -server=/.huaren.us/127.0.0.1#7913 -ipset=/.huaren.us/gfwlist -server=/.bbg.gov/127.0.0.1#7913 -ipset=/.bbg.gov/gfwlist -server=/.gotgeeks.com/127.0.0.1#7913 -ipset=/.gotgeeks.com/gfwlist -server=/.thegly.com/127.0.0.1#7913 -ipset=/.thegly.com/gfwlist -server=/.securetunnel.com/127.0.0.1#7913 -ipset=/.securetunnel.com/gfwlist -server=/.godsdirectcontact.co.uk/127.0.0.1#7913 -ipset=/.godsdirectcontact.co.uk/gfwlist -server=/.t35.com/127.0.0.1#7913 -ipset=/.t35.com/gfwlist -server=/.thebcomplex.com/127.0.0.1#7913 -ipset=/.thebcomplex.com/gfwlist -server=/.theblemish.com/127.0.0.1#7913 -ipset=/.theblemish.com/gfwlist -server=/.theatrum-belli.com/127.0.0.1#7913 -ipset=/.theatrum-belli.com/gfwlist -server=/.focustaiwan.tw/127.0.0.1#7913 -ipset=/.focustaiwan.tw/gfwlist -server=/.tenzinpalmo.com/127.0.0.1#7913 -ipset=/.tenzinpalmo.com/gfwlist -server=/.buddhanet.com.tw/127.0.0.1#7913 -ipset=/.buddhanet.com.tw/gfwlist -server=/.tenacy.com/127.0.0.1#7913 -ipset=/.tenacy.com/gfwlist -server=/.telegraph.co.uk/127.0.0.1#7913 -ipset=/.telegraph.co.uk/gfwlist -server=/.tdm.com.mo/127.0.0.1#7913 -ipset=/.tdm.com.mo/gfwlist -server=/.bookepub.com/127.0.0.1#7913 -ipset=/.bookepub.com/gfwlist -server=/.freebrowser.org/127.0.0.1#7913 -ipset=/.freebrowser.org/gfwlist -server=/.bfnn.org/127.0.0.1#7913 -ipset=/.bfnn.org/gfwlist -server=/.tcpspeed.co/127.0.0.1#7913 -ipset=/.tcpspeed.co/gfwlist -server=/.cleansite.us/127.0.0.1#7913 -ipset=/.cleansite.us/gfwlist -server=/.tccwonline.org/127.0.0.1#7913 -ipset=/.tccwonline.org/gfwlist -server=/.mymediarom.com/127.0.0.1#7913 -ipset=/.mymediarom.com/gfwlist -server=/.dw.com/127.0.0.1#7913 -ipset=/.dw.com/gfwlist -server=/.zattoo.com/127.0.0.1#7913 -ipset=/.zattoo.com/gfwlist -server=/.tbswd.org/127.0.0.1#7913 -ipset=/.tbswd.org/gfwlist -server=/.uploaded.net/127.0.0.1#7913 -ipset=/.uploaded.net/gfwlist -server=/.disp.cc/127.0.0.1#7913 -ipset=/.disp.cc/gfwlist -server=/.urchin.com/127.0.0.1#7913 -ipset=/.urchin.com/gfwlist -server=/.hmonghot.com/127.0.0.1#7913 -ipset=/.hmonghot.com/gfwlist -server=/.tbsmalaysia.org/127.0.0.1#7913 -ipset=/.tbsmalaysia.org/gfwlist -server=/.tbskkinabalu.page.tl/127.0.0.1#7913 -ipset=/.tbskkinabalu.page.tl/gfwlist -server=/.extremetube.com/127.0.0.1#7913 -ipset=/.extremetube.com/gfwlist -server=/.tbs-rainbow.org/127.0.0.1#7913 -ipset=/.tbs-rainbow.org/gfwlist -server=/.jav.com/127.0.0.1#7913 -ipset=/.jav.com/gfwlist -server=/.budaedu.org/127.0.0.1#7913 -ipset=/.budaedu.org/gfwlist -server=/.tbjyt.org/127.0.0.1#7913 -ipset=/.tbjyt.org/gfwlist -server=/.hd.stheadline.com/127.0.0.1#7913 -ipset=/.hd.stheadline.com/gfwlist -server=/.android.com/127.0.0.1#7913 -ipset=/.android.com/gfwlist -server=/.tbicn.org/127.0.0.1#7913 -ipset=/.tbicn.org/gfwlist -server=/.sopcast.com/127.0.0.1#7913 -ipset=/.sopcast.com/gfwlist -server=/.sulian.me/127.0.0.1#7913 -ipset=/.sulian.me/gfwlist -server=/.gloryhole.com/127.0.0.1#7913 -ipset=/.gloryhole.com/gfwlist -server=/.tbi.org.hk/127.0.0.1#7913 -ipset=/.tbi.org.hk/gfwlist -server=/.taup.net/127.0.0.1#7913 -ipset=/.taup.net/gfwlist -server=/.blog.taragana.com/127.0.0.1#7913 -ipset=/.blog.taragana.com/gfwlist -server=/.assets.bwbx.io/127.0.0.1#7913 -ipset=/.assets.bwbx.io/gfwlist -server=/.retweetrank.com/127.0.0.1#7913 -ipset=/.retweetrank.com/gfwlist -server=/.tanc.org/127.0.0.1#7913 -ipset=/.tanc.org/gfwlist -server=/.tamiaode.tk/127.0.0.1#7913 -ipset=/.tamiaode.tk/gfwlist -server=/.talkonly.net/127.0.0.1#7913 -ipset=/.talkonly.net/gfwlist -server=/.talkcc.com/127.0.0.1#7913 -ipset=/.talkcc.com/gfwlist -server=/.openleaks.org/127.0.0.1#7913 -ipset=/.openleaks.org/gfwlist -server=/.ddns.ms/127.0.0.1#7913 -ipset=/.ddns.ms/gfwlist -server=/.ourdearamy.com/127.0.0.1#7913 -ipset=/.ourdearamy.com/gfwlist -server=/.thewgo.org/127.0.0.1#7913 -ipset=/.thewgo.org/gfwlist -server=/.post76.com/127.0.0.1#7913 -ipset=/.post76.com/gfwlist -server=/.feedburner.com/127.0.0.1#7913 -ipset=/.feedburner.com/gfwlist -server=/.chinatopsex.com/127.0.0.1#7913 -ipset=/.chinatopsex.com/gfwlist -server=/.pornvisit.com/127.0.0.1#7913 -ipset=/.pornvisit.com/gfwlist -server=/.daiphapinfo.net/127.0.0.1#7913 -ipset=/.daiphapinfo.net/gfwlist -server=/.www.taiwanonline.cc/127.0.0.1#7913 -ipset=/.www.taiwanonline.cc/gfwlist -server=/.google.co.ma/127.0.0.1#7913 -ipset=/.google.co.ma/gfwlist -server=/.taiwannews.com.tw/127.0.0.1#7913 -ipset=/.taiwannews.com.tw/gfwlist -server=/.taiwanncf.org.tw/127.0.0.1#7913 -ipset=/.taiwanncf.org.tw/gfwlist -server=/.taiwannation.com.tw/127.0.0.1#7913 -ipset=/.taiwannation.com.tw/gfwlist -server=/.www2.rocketbbs.com/127.0.0.1#7913 -ipset=/.www2.rocketbbs.com/gfwlist -server=/.taiwannation.com/127.0.0.1#7913 -ipset=/.taiwannation.com/gfwlist -server=/.opendn.xyz/127.0.0.1#7913 -ipset=/.opendn.xyz/gfwlist -server=/.taiwanjustice.com/127.0.0.1#7913 -ipset=/.taiwanjustice.com/gfwlist -server=/.bcast.co.nz/127.0.0.1#7913 -ipset=/.bcast.co.nz/gfwlist -server=/.rotten.com/127.0.0.1#7913 -ipset=/.rotten.com/gfwlist -server=/.fangbinxing.com/127.0.0.1#7913 -ipset=/.fangbinxing.com/gfwlist -server=/.globalvoicesonline.org/127.0.0.1#7913 -ipset=/.globalvoicesonline.org/gfwlist -server=/.assembla.com/127.0.0.1#7913 -ipset=/.assembla.com/gfwlist -server=/.taiwandc.org/127.0.0.1#7913 -ipset=/.taiwandc.org/gfwlist -server=/.taiwancon.com/127.0.0.1#7913 -ipset=/.taiwancon.com/gfwlist -server=/.partycasino.com/127.0.0.1#7913 -ipset=/.partycasino.com/gfwlist -server=/.taiwanbible.com/127.0.0.1#7913 -ipset=/.taiwanbible.com/gfwlist -server=/.ggssl.com/127.0.0.1#7913 -ipset=/.ggssl.com/gfwlist -server=/.tagwalk.com/127.0.0.1#7913 -ipset=/.tagwalk.com/gfwlist -server=/.9gag.com/127.0.0.1#7913 -ipset=/.9gag.com/gfwlist -server=/.taedp.org.tw/127.0.0.1#7913 -ipset=/.taedp.org.tw/gfwlist -server=/.bnews.co/127.0.0.1#7913 -ipset=/.bnews.co/gfwlist -server=/.onmypc.info/127.0.0.1#7913 -ipset=/.onmypc.info/gfwlist -server=/.taaze.tw/127.0.0.1#7913 -ipset=/.taaze.tw/gfwlist -server=/.taa-usa.org/127.0.0.1#7913 -ipset=/.taa-usa.org/gfwlist -server=/.t66y.com/127.0.0.1#7913 -ipset=/.t66y.com/gfwlist -server=/.shambalapost.com/127.0.0.1#7913 -ipset=/.shambalapost.com/gfwlist -server=/.szbbs.net/127.0.0.1#7913 -ipset=/.szbbs.net/gfwlist -server=/.blog.syx86.cn/127.0.0.1#7913 -ipset=/.blog.syx86.cn/gfwlist -server=/.syncback.com/127.0.0.1#7913 -ipset=/.syncback.com/gfwlist -server=/.sydneytoday.com/127.0.0.1#7913 -ipset=/.sydneytoday.com/gfwlist -server=/.cenews.eu/127.0.0.1#7913 -ipset=/.cenews.eu/gfwlist -server=/.surfeasy.com/127.0.0.1#7913 -ipset=/.surfeasy.com/gfwlist -server=/.suprememastertv.com/127.0.0.1#7913 -ipset=/.suprememastertv.com/gfwlist -server=/.64tianwang.com/127.0.0.1#7913 -ipset=/.64tianwang.com/gfwlist -server=/.sunvpn.net/127.0.0.1#7913 -ipset=/.sunvpn.net/gfwlist -server=/.sunmedia.ca/127.0.0.1#7913 -ipset=/.sunmedia.ca/gfwlist -server=/.sunporno.com/127.0.0.1#7913 -ipset=/.sunporno.com/gfwlist -server=/.njactb.org/127.0.0.1#7913 -ipset=/.njactb.org/gfwlist -server=/.sugobbs.com/127.0.0.1#7913 -ipset=/.sugobbs.com/gfwlist -server=/.tv.com/127.0.0.1#7913 -ipset=/.tv.com/gfwlist -server=/.igcd.net/127.0.0.1#7913 -ipset=/.igcd.net/gfwlist -server=/.stumbleupon.com/127.0.0.1#7913 -ipset=/.stumbleupon.com/gfwlist -server=/.chinaelections.org/127.0.0.1#7913 -ipset=/.chinaelections.org/gfwlist -server=/.studentsforafreetibet.org/127.0.0.1#7913 -ipset=/.studentsforafreetibet.org/gfwlist -server=/.hiitch.com/127.0.0.1#7913 -ipset=/.hiitch.com/gfwlist -server=/.gr8domain.biz/127.0.0.1#7913 -ipset=/.gr8domain.biz/gfwlist -server=/.iddddg.com/127.0.0.1#7913 -ipset=/.iddddg.com/gfwlist -server=/.strongwindpress.com/127.0.0.1#7913 -ipset=/.strongwindpress.com/gfwlist -server=/.strikingly.com/127.0.0.1#7913 -ipset=/.strikingly.com/gfwlist -server=/.tubecup.com/127.0.0.1#7913 -ipset=/.tubecup.com/gfwlist -server=/.10.tt/127.0.0.1#7913 -ipset=/.10.tt/gfwlist -server=/.hikinggfw.org/127.0.0.1#7913 -ipset=/.hikinggfw.org/gfwlist -server=/.martincartoons.com/127.0.0.1#7913 -ipset=/.martincartoons.com/gfwlist -server=/.stranabg.com/127.0.0.1#7913 -ipset=/.stranabg.com/gfwlist -server=/.pmatehunter.com/127.0.0.1#7913 -ipset=/.pmatehunter.com/gfwlist -server=/.stormmediagroup.com/127.0.0.1#7913 -ipset=/.stormmediagroup.com/gfwlist -server=/.msguancha.com/127.0.0.1#7913 -ipset=/.msguancha.com/gfwlist -server=/.storify.com/127.0.0.1#7913 -ipset=/.storify.com/gfwlist -server=/.storagenewsletter.com/127.0.0.1#7913 -ipset=/.storagenewsletter.com/gfwlist -server=/.sto.cc/127.0.0.1#7913 -ipset=/.sto.cc/gfwlist -server=/.sharpdaily.com.hk/127.0.0.1#7913 -ipset=/.sharpdaily.com.hk/gfwlist -server=/.stileproject.com/127.0.0.1#7913 -ipset=/.stileproject.com/gfwlist -server=/.monster.com/127.0.0.1#7913 -ipset=/.monster.com/gfwlist -server=/.instagram.com/127.0.0.1#7913 -ipset=/.instagram.com/gfwlist -server=/.stickeraction.com/127.0.0.1#7913 -ipset=/.stickeraction.com/gfwlist -server=/.ebook.hyread.com.tw/127.0.0.1#7913 -ipset=/.ebook.hyread.com.tw/gfwlist -server=/.cdn.softlayer.net/127.0.0.1#7913 -ipset=/.cdn.softlayer.net/gfwlist -server=/.ccue.ca/127.0.0.1#7913 -ipset=/.ccue.ca/gfwlist -server=/.ny.stgloballink.com/127.0.0.1#7913 -ipset=/.ny.stgloballink.com/gfwlist -server=/.stepchina.com/127.0.0.1#7913 -ipset=/.stepchina.com/gfwlist -server=/.tuo8.org/127.0.0.1#7913 -ipset=/.tuo8.org/gfwlist -server=/.startpage.com/127.0.0.1#7913 -ipset=/.startpage.com/gfwlist -server=/.dailymotion.com/127.0.0.1#7913 -ipset=/.dailymotion.com/gfwlist -server=/.hkptu.org/127.0.0.1#7913 -ipset=/.hkptu.org/gfwlist -server=/.bestvpnusa.com/127.0.0.1#7913 -ipset=/.bestvpnusa.com/gfwlist -server=/.starp2p.com/127.0.0.1#7913 -ipset=/.starp2p.com/gfwlist -server=/.av.com/127.0.0.1#7913 -ipset=/.av.com/gfwlist -server=/.chinagonet.com/127.0.0.1#7913 -ipset=/.chinagonet.com/gfwlist -server=/.usinfo.state.gov/127.0.0.1#7913 -ipset=/.usinfo.state.gov/gfwlist -server=/.mlzs.work/127.0.0.1#7913 -ipset=/.mlzs.work/gfwlist -server=/.freewww.biz/127.0.0.1#7913 -ipset=/.freewww.biz/gfwlist -server=/.falun-co.org/127.0.0.1#7913 -ipset=/.falun-co.org/gfwlist -server=/.wuw.red/127.0.0.1#7913 -ipset=/.wuw.red/gfwlist -server=/.stage64.hk/127.0.0.1#7913 -ipset=/.stage64.hk/gfwlist -server=/.meripet.biz/127.0.0.1#7913 -ipset=/.meripet.biz/gfwlist -server=/.filthdump.com/127.0.0.1#7913 -ipset=/.filthdump.com/gfwlist -server=/.ssrshare.com/127.0.0.1#7913 -ipset=/.ssrshare.com/gfwlist -server=/.vpnvip.com/127.0.0.1#7913 -ipset=/.vpnvip.com/gfwlist -server=/.ssglobal.me/127.0.0.1#7913 -ipset=/.ssglobal.me/gfwlist -server=/.freexinwen.com/127.0.0.1#7913 -ipset=/.freexinwen.com/gfwlist -server=/.ss-link.com/127.0.0.1#7913 -ipset=/.ss-link.com/gfwlist -server=/.sproxy.info/127.0.0.1#7913 -ipset=/.sproxy.info/gfwlist -server=/.sproutcore.com/127.0.0.1#7913 -ipset=/.sproutcore.com/gfwlist -server=/.vpnshazam.com/127.0.0.1#7913 -ipset=/.vpnshazam.com/gfwlist -server=/.ecfa.org.tw/127.0.0.1#7913 -ipset=/.ecfa.org.tw/gfwlist -server=/.robustnessiskey.com/127.0.0.1#7913 -ipset=/.robustnessiskey.com/gfwlist -server=/.nyt.com/127.0.0.1#7913 -ipset=/.nyt.com/gfwlist -server=/.spencertipping.com/127.0.0.1#7913 -ipset=/.spencertipping.com/gfwlist -server=/.5maodang.com/127.0.0.1#7913 -ipset=/.5maodang.com/gfwlist -server=/.spem.at/127.0.0.1#7913 -ipset=/.spem.at/gfwlist -server=/.speedify.com/127.0.0.1#7913 -ipset=/.speedify.com/gfwlist -server=/.btaia.com/127.0.0.1#7913 -ipset=/.btaia.com/gfwlist -server=/.wanz-factory.com/127.0.0.1#7913 -ipset=/.wanz-factory.com/gfwlist -server=/.anonymouse.org/127.0.0.1#7913 -ipset=/.anonymouse.org/gfwlist -server=/.googlesource.com/127.0.0.1#7913 -ipset=/.googlesource.com/gfwlist -server=/.speakerdeck.com/127.0.0.1#7913 -ipset=/.speakerdeck.com/gfwlist -server=/.spb.com/127.0.0.1#7913 -ipset=/.spb.com/gfwlist -server=/.spankwire.com/127.0.0.1#7913 -ipset=/.spankwire.com/gfwlist -server=/.bbs-tw.com/127.0.0.1#7913 -ipset=/.bbs-tw.com/gfwlist -server=/.yizhihongxing.com/127.0.0.1#7913 -ipset=/.yizhihongxing.com/gfwlist -server=/.wlx.sowiki.net/127.0.0.1#7913 -ipset=/.wlx.sowiki.net/gfwlist -server=/.incredibox.fr/127.0.0.1#7913 -ipset=/.incredibox.fr/gfwlist -server=/.enanyang.my/127.0.0.1#7913 -ipset=/.enanyang.my/gfwlist -server=/.cnn.com/127.0.0.1#7913 -ipset=/.cnn.com/gfwlist -server=/.southnews.com.tw/127.0.0.1#7913 -ipset=/.southnews.com.tw/gfwlist -server=/.sourceforge.net/127.0.0.1#7913 -ipset=/.sourceforge.net/gfwlist -server=/.ismaelan.com/127.0.0.1#7913 -ipset=/.ismaelan.com/gfwlist -server=/.soundcloud.com/127.0.0.1#7913 -ipset=/.soundcloud.com/gfwlist -server=/.soulcaliburhentai.net/127.0.0.1#7913 -ipset=/.soulcaliburhentai.net/gfwlist -server=/.guaguass.org/127.0.0.1#7913 -ipset=/.guaguass.org/gfwlist -server=/.soubory.com/127.0.0.1#7913 -ipset=/.soubory.com/gfwlist -server=/.bbs.sou-tong.org/127.0.0.1#7913 -ipset=/.bbs.sou-tong.org/gfwlist -server=/.sos.org/127.0.0.1#7913 -ipset=/.sos.org/gfwlist -server=/.sorazone.net/127.0.0.1#7913 -ipset=/.sorazone.net/gfwlist -server=/.4everproxy.com/127.0.0.1#7913 -ipset=/.4everproxy.com/gfwlist -server=/.page.bid.yahoo.com/127.0.0.1#7913 -ipset=/.page.bid.yahoo.com/gfwlist -server=/.safety.google/127.0.0.1#7913 -ipset=/.safety.google/gfwlist -server=/.sonicbbs.cc/127.0.0.1#7913 -ipset=/.sonicbbs.cc/gfwlist -server=/.songjianjun.com/127.0.0.1#7913 -ipset=/.songjianjun.com/gfwlist -server=/.sohfrance.org/127.0.0.1#7913 -ipset=/.sohfrance.org/gfwlist -server=/.sobees.com/127.0.0.1#7913 -ipset=/.sobees.com/gfwlist -server=/.buddhistchannel.tv/127.0.0.1#7913 -ipset=/.buddhistchannel.tv/gfwlist -server=/.sostibet.org/127.0.0.1#7913 -ipset=/.sostibet.org/gfwlist -server=/.sokmil.com/127.0.0.1#7913 -ipset=/.sokmil.com/gfwlist -server=/.sogclub.com/127.0.0.1#7913 -ipset=/.sogclub.com/gfwlist -server=/.epochtimes.cz/127.0.0.1#7913 -ipset=/.epochtimes.cz/gfwlist -server=/.islahhaber.net/127.0.0.1#7913 -ipset=/.islahhaber.net/gfwlist -server=/.tibetkomite.dk/127.0.0.1#7913 -ipset=/.tibetkomite.dk/gfwlist -server=/.sod.co.jp/127.0.0.1#7913 -ipset=/.sod.co.jp/gfwlist -server=/.sndcdn.com/127.0.0.1#7913 -ipset=/.sndcdn.com/gfwlist -server=/.tibet-info.net/127.0.0.1#7913 -ipset=/.tibet-info.net/gfwlist -server=/.cosplayjav.pl/127.0.0.1#7913 -ipset=/.cosplayjav.pl/gfwlist -server=/.globalvoices.org/127.0.0.1#7913 -ipset=/.globalvoices.org/gfwlist -server=/.snapchat.com/127.0.0.1#7913 -ipset=/.snapchat.com/gfwlist -server=/.smyxy.org/127.0.0.1#7913 -ipset=/.smyxy.org/gfwlist -server=/.google.ca/127.0.0.1#7913 -ipset=/.google.ca/gfwlist -server=/.smhric.org/127.0.0.1#7913 -ipset=/.smhric.org/gfwlist -server=/.smh.com.au/127.0.0.1#7913 -ipset=/.smh.com.au/gfwlist -server=/.ikwb.com/127.0.0.1#7913 -ipset=/.ikwb.com/gfwlist -server=/.google.ro/127.0.0.1#7913 -ipset=/.google.ro/gfwlist -server=/.sexidude.com/127.0.0.1#7913 -ipset=/.sexidude.com/gfwlist -server=/.proxytunnel.net/127.0.0.1#7913 -ipset=/.proxytunnel.net/gfwlist -server=/.china-review.com.ua/127.0.0.1#7913 -ipset=/.china-review.com.ua/gfwlist -server=/.badiucao.com/127.0.0.1#7913 -ipset=/.badiucao.com/gfwlist -server=/.getsync.com/127.0.0.1#7913 -ipset=/.getsync.com/gfwlist -server=/.tongil.or.kr/127.0.0.1#7913 -ipset=/.tongil.or.kr/gfwlist -server=/.uyghurensemble.co.uk/127.0.0.1#7913 -ipset=/.uyghurensemble.co.uk/gfwlist -server=/.david-kilgour.com/127.0.0.1#7913 -ipset=/.david-kilgour.com/gfwlist -server=/.slickvpn.com/127.0.0.1#7913 -ipset=/.slickvpn.com/gfwlist -server=/.abchinese.com/127.0.0.1#7913 -ipset=/.abchinese.com/gfwlist -server=/.slinkset.com/127.0.0.1#7913 -ipset=/.slinkset.com/gfwlist -server=/.wikibooks.org/127.0.0.1#7913 -ipset=/.wikibooks.org/gfwlist -server=/.free-hada-now.org/127.0.0.1#7913 -ipset=/.free-hada-now.org/gfwlist -server=/.m.slandr.net/127.0.0.1#7913 -ipset=/.m.slandr.net/gfwlist -server=/.xskywalker.com/127.0.0.1#7913 -ipset=/.xskywalker.com/gfwlist -server=/.www.gmll.org/127.0.0.1#7913 -ipset=/.www.gmll.org/gfwlist -server=/.myiphide.com/127.0.0.1#7913 -ipset=/.myiphide.com/gfwlist -server=/.glock.com/127.0.0.1#7913 -ipset=/.glock.com/gfwlist -server=/.arlingtoncemetery.mil/127.0.0.1#7913 -ipset=/.arlingtoncemetery.mil/gfwlist -server=/.141hongkong.com/127.0.0.1#7913 -ipset=/.141hongkong.com/gfwlist -server=/.bnrmetal.com/127.0.0.1#7913 -ipset=/.bnrmetal.com/gfwlist -server=/.duck.com/127.0.0.1#7913 -ipset=/.duck.com/gfwlist -server=/.gu-chu-sum.org/127.0.0.1#7913 -ipset=/.gu-chu-sum.org/gfwlist -server=/.lkcn.net/127.0.0.1#7913 -ipset=/.lkcn.net/gfwlist -server=/.uraban.me/127.0.0.1#7913 -ipset=/.uraban.me/gfwlist -server=/.aomiwang.com/127.0.0.1#7913 -ipset=/.aomiwang.com/gfwlist -server=/.facebook.nl/127.0.0.1#7913 -ipset=/.facebook.nl/gfwlist -server=/.citytalk.tw/127.0.0.1#7913 -ipset=/.citytalk.tw/gfwlist -server=/.scache1.vzw.com/127.0.0.1#7913 -ipset=/.scache1.vzw.com/gfwlist -server=/.rfamobile.org/127.0.0.1#7913 -ipset=/.rfamobile.org/gfwlist -server=/.lamrim.com/127.0.0.1#7913 -ipset=/.lamrim.com/gfwlist -server=/.lenwhite.com/127.0.0.1#7913 -ipset=/.lenwhite.com/gfwlist -server=/.sidelinessportseatery.com/127.0.0.1#7913 -ipset=/.sidelinessportseatery.com/gfwlist -server=/.dalailamainaustralia.org/127.0.0.1#7913 -ipset=/.dalailamainaustralia.org/gfwlist -server=/.googlemail.com/127.0.0.1#7913 -ipset=/.googlemail.com/gfwlist -server=/.anchorfree.com/127.0.0.1#7913 -ipset=/.anchorfree.com/gfwlist -server=/.cotweet.com/127.0.0.1#7913 -ipset=/.cotweet.com/gfwlist -server=/.breakingtweets.com/127.0.0.1#7913 -ipset=/.breakingtweets.com/gfwlist -server=/.libertytimes.com.tw/127.0.0.1#7913 -ipset=/.libertytimes.com.tw/gfwlist -server=/.aiweiwei.com/127.0.0.1#7913 -ipset=/.aiweiwei.com/gfwlist -server=/.imdb.com/127.0.0.1#7913 -ipset=/.imdb.com/gfwlist -server=/.shadowsocks9.com/127.0.0.1#7913 -ipset=/.shadowsocks9.com/gfwlist -server=/.cams.org.sg/127.0.0.1#7913 -ipset=/.cams.org.sg/gfwlist -server=/.skimtube.com/127.0.0.1#7913 -ipset=/.skimtube.com/gfwlist -server=/.efksoft.com/127.0.0.1#7913 -ipset=/.efksoft.com/gfwlist -server=/.goldenfrog.com/127.0.0.1#7913 -ipset=/.goldenfrog.com/gfwlist -server=/.mirrorbooks.com/127.0.0.1#7913 -ipset=/.mirrorbooks.com/gfwlist -server=/.openervpn.in/127.0.0.1#7913 -ipset=/.openervpn.in/gfwlist -server=/.sjrt.org/127.0.0.1#7913 -ipset=/.sjrt.org/gfwlist -server=/.animeshippuuden.com/127.0.0.1#7913 -ipset=/.animeshippuuden.com/gfwlist -server=/.huobi.pro/127.0.0.1#7913 -ipset=/.huobi.pro/gfwlist -server=/.bunbunhk.com/127.0.0.1#7913 -ipset=/.bunbunhk.com/gfwlist -server=/.dizhidizhi.com/127.0.0.1#7913 -ipset=/.dizhidizhi.com/gfwlist -server=/.sbs.com.au/127.0.0.1#7913 -ipset=/.sbs.com.au/gfwlist -server=/.siteks.uk.to/127.0.0.1#7913 -ipset=/.siteks.uk.to/gfwlist -server=/.sitebro.tw/127.0.0.1#7913 -ipset=/.sitebro.tw/gfwlist -server=/.myspacecdn.com/127.0.0.1#7913 -ipset=/.myspacecdn.com/gfwlist -server=/.sis001.com/127.0.0.1#7913 -ipset=/.sis001.com/gfwlist -server=/.sierrafriendsoftibet.org/127.0.0.1#7913 -ipset=/.sierrafriendsoftibet.org/gfwlist -server=/.itshidden.com/127.0.0.1#7913 -ipset=/.itshidden.com/gfwlist -server=/.proxyanonimo.es/127.0.0.1#7913 -ipset=/.proxyanonimo.es/gfwlist -server=/.sinoquebec.com/127.0.0.1#7913 -ipset=/.sinoquebec.com/gfwlist -server=/.limiao.net/127.0.0.1#7913 -ipset=/.limiao.net/gfwlist -server=/.avfantasy.com/127.0.0.1#7913 -ipset=/.avfantasy.com/gfwlist -server=/.coinut.com/127.0.0.1#7913 -ipset=/.coinut.com/gfwlist -server=/.sinopitt.info/127.0.0.1#7913 -ipset=/.sinopitt.info/gfwlist -server=/.oclp.hk/127.0.0.1#7913 -ipset=/.oclp.hk/gfwlist -server=/.washingtonpost.com/127.0.0.1#7913 -ipset=/.washingtonpost.com/gfwlist -server=/.taiwanyes.com/127.0.0.1#7913 -ipset=/.taiwanyes.com/gfwlist -server=/.readydown.com/127.0.0.1#7913 -ipset=/.readydown.com/gfwlist -server=/.ritouki.jp/127.0.0.1#7913 -ipset=/.ritouki.jp/gfwlist -server=/.globalmediaoutreach.com/127.0.0.1#7913 -ipset=/.globalmediaoutreach.com/gfwlist -server=/.gogotunnel.com/127.0.0.1#7913 -ipset=/.gogotunnel.com/gfwlist -server=/.kspcoin.com/127.0.0.1#7913 -ipset=/.kspcoin.com/gfwlist -server=/.tibetanpoliticalreview.org/127.0.0.1#7913 -ipset=/.tibetanpoliticalreview.org/gfwlist -server=/.singpao.com.hk/127.0.0.1#7913 -ipset=/.singpao.com.hk/gfwlist -server=/.singaporepools.com.sg/127.0.0.1#7913 -ipset=/.singaporepools.com.sg/gfwlist -server=/.sinchew.com.my/127.0.0.1#7913 -ipset=/.sinchew.com.my/gfwlist -server=/.get.dev/127.0.0.1#7913 -ipset=/.get.dev/gfwlist -server=/.google.dj/127.0.0.1#7913 -ipset=/.google.dj/gfwlist -server=/.leirentv.ca/127.0.0.1#7913 -ipset=/.leirentv.ca/gfwlist -server=/.mrtweet.com/127.0.0.1#7913 -ipset=/.mrtweet.com/gfwlist -server=/.facebook.in/127.0.0.1#7913 -ipset=/.facebook.in/gfwlist -server=/.vcfbuilder.org/127.0.0.1#7913 -ipset=/.vcfbuilder.org/gfwlist -server=/.bbci.co.uk/127.0.0.1#7913 -ipset=/.bbci.co.uk/gfwlist -server=/.democrats.org/127.0.0.1#7913 -ipset=/.democrats.org/gfwlist -server=/.realcourage.org/127.0.0.1#7913 -ipset=/.realcourage.org/gfwlist -server=/.javhd.com/127.0.0.1#7913 -ipset=/.javhd.com/gfwlist -server=/.dragonsprings.org/127.0.0.1#7913 -ipset=/.dragonsprings.org/gfwlist -server=/.myshare.url.com.tw/127.0.0.1#7913 -ipset=/.myshare.url.com.tw/gfwlist -server=/.blog.sina.com.tw/127.0.0.1#7913 -ipset=/.blog.sina.com.tw/gfwlist -server=/.bbs.sina.com/127.0.0.1#7913 -ipset=/.bbs.sina.com/gfwlist -server=/.gfw.org.ua/127.0.0.1#7913 -ipset=/.gfw.org.ua/gfwlist -server=/.fromchinatousa.net/127.0.0.1#7913 -ipset=/.fromchinatousa.net/gfwlist -server=/.yvesgeleyn.com/127.0.0.1#7913 -ipset=/.yvesgeleyn.com/gfwlist -server=/.nytstyle.com/127.0.0.1#7913 -ipset=/.nytstyle.com/gfwlist -server=/.freevpn.me/127.0.0.1#7913 -ipset=/.freevpn.me/gfwlist -server=/.silkbook.com/127.0.0.1#7913 -ipset=/.silkbook.com/gfwlist -server=/.alarab.qa/127.0.0.1#7913 -ipset=/.alarab.qa/gfwlist -server=/.incloak.com/127.0.0.1#7913 -ipset=/.incloak.com/gfwlist -server=/.sijihuisuo.com/127.0.0.1#7913 -ipset=/.sijihuisuo.com/gfwlist -server=/.data-vocabulary.org/127.0.0.1#7913 -ipset=/.data-vocabulary.org/gfwlist -server=/.coolloud.org.tw/127.0.0.1#7913 -ipset=/.coolloud.org.tw/gfwlist -server=/.successfn.com/127.0.0.1#7913 -ipset=/.successfn.com/gfwlist -server=/.fuyindiantai.org/127.0.0.1#7913 -ipset=/.fuyindiantai.org/gfwlist -server=/.discuss.com.hk/127.0.0.1#7913 -ipset=/.discuss.com.hk/gfwlist -server=/.shwchurch3.com/127.0.0.1#7913 -ipset=/.shwchurch3.com/gfwlist -server=/.wefightcensorship.org/127.0.0.1#7913 -ipset=/.wefightcensorship.org/gfwlist -server=/.glorystar.me/127.0.0.1#7913 -ipset=/.glorystar.me/gfwlist -server=/.i1.hk/127.0.0.1#7913 -ipset=/.i1.hk/gfwlist -server=/.grotty-monday.com/127.0.0.1#7913 -ipset=/.grotty-monday.com/gfwlist -server=/.falunart.org/127.0.0.1#7913 -ipset=/.falunart.org/gfwlist -server=/.showhaotu.com/127.0.0.1#7913 -ipset=/.showhaotu.com/gfwlist -server=/.bbs.ozchinese.com/127.0.0.1#7913 -ipset=/.bbs.ozchinese.com/gfwlist -server=/.backpackers.com.tw/127.0.0.1#7913 -ipset=/.backpackers.com.tw/gfwlist -server=/.shop2000.com.tw/127.0.0.1#7913 -ipset=/.shop2000.com.tw/gfwlist -server=/.tonyyan.net/127.0.0.1#7913 -ipset=/.tonyyan.net/gfwlist -server=/.bloglines.com/127.0.0.1#7913 -ipset=/.bloglines.com/gfwlist -server=/.dl.box.net/127.0.0.1#7913 -ipset=/.dl.box.net/gfwlist -server=/.saiq.me/127.0.0.1#7913 -ipset=/.saiq.me/gfwlist -server=/.acgkj.com/127.0.0.1#7913 -ipset=/.acgkj.com/gfwlist -server=/.aiph.net/127.0.0.1#7913 -ipset=/.aiph.net/gfwlist -server=/.shixiao.org/127.0.0.1#7913 -ipset=/.shixiao.org/gfwlist -server=/.streema.com/127.0.0.1#7913 -ipset=/.streema.com/gfwlist -server=/.cctmweb.net/127.0.0.1#7913 -ipset=/.cctmweb.net/gfwlist -server=/.bbcchinese.com/127.0.0.1#7913 -ipset=/.bbcchinese.com/gfwlist -server=/.asianwomensfilm.de/127.0.0.1#7913 -ipset=/.asianwomensfilm.de/gfwlist -server=/.pixelqi.com/127.0.0.1#7913 -ipset=/.pixelqi.com/gfwlist -server=/.shicheng.org/127.0.0.1#7913 -ipset=/.shicheng.org/gfwlist -server=/.meltoday.com/127.0.0.1#7913 -ipset=/.meltoday.com/gfwlist -server=/.hrw.org/127.0.0.1#7913 -ipset=/.hrw.org/gfwlist -server=/.shenyunperformingarts.org/127.0.0.1#7913 -ipset=/.shenyunperformingarts.org/gfwlist -server=/.hkreporter.com/127.0.0.1#7913 -ipset=/.hkreporter.com/gfwlist -server=/.javakiba.org/127.0.0.1#7913 -ipset=/.javakiba.org/gfwlist -server=/.bowenpress.com/127.0.0.1#7913 -ipset=/.bowenpress.com/gfwlist -server=/.freeddns.com/127.0.0.1#7913 -ipset=/.freeddns.com/gfwlist -server=/.ntrfun.com/127.0.0.1#7913 -ipset=/.ntrfun.com/gfwlist -server=/.journalofdemocracy.org/127.0.0.1#7913 -ipset=/.journalofdemocracy.org/gfwlist -server=/.jmscult.com/127.0.0.1#7913 -ipset=/.jmscult.com/gfwlist -server=/.livingonline.us/127.0.0.1#7913 -ipset=/.livingonline.us/gfwlist -server=/.yyii.org/127.0.0.1#7913 -ipset=/.yyii.org/gfwlist -server=/.sharpdaily.tw/127.0.0.1#7913 -ipset=/.sharpdaily.tw/gfwlist -server=/.mingshengbao.com/127.0.0.1#7913 -ipset=/.mingshengbao.com/gfwlist -server=/.usunitednews.com/127.0.0.1#7913 -ipset=/.usunitednews.com/gfwlist -server=/.openvpn.org/127.0.0.1#7913 -ipset=/.openvpn.org/gfwlist -server=/.sharebee.com/127.0.0.1#7913 -ipset=/.sharebee.com/gfwlist -server=/.nic.cz.cc/127.0.0.1#7913 -ipset=/.nic.cz.cc/gfwlist -server=/.in99.org/127.0.0.1#7913 -ipset=/.in99.org/gfwlist -server=/.shangfang.org/127.0.0.1#7913 -ipset=/.shangfang.org/gfwlist -server=/.google.nu/127.0.0.1#7913 -ipset=/.google.nu/gfwlist -server=/.vcf-online.org/127.0.0.1#7913 -ipset=/.vcf-online.org/gfwlist -server=/.whatblocked.com/127.0.0.1#7913 -ipset=/.whatblocked.com/gfwlist -server=/.free-proxy.cz/127.0.0.1#7913 -ipset=/.free-proxy.cz/gfwlist -server=/.szetowah.org.hk/127.0.0.1#7913 -ipset=/.szetowah.org.hk/gfwlist -server=/.cclife.org/127.0.0.1#7913 -ipset=/.cclife.org/gfwlist -server=/.shadowsocks-r.com/127.0.0.1#7913 -ipset=/.shadowsocks-r.com/gfwlist -server=/.falundafa-pa.net/127.0.0.1#7913 -ipset=/.falundafa-pa.net/gfwlist -server=/.bullogger.com/127.0.0.1#7913 -ipset=/.bullogger.com/gfwlist -server=/.stephaniered.com/127.0.0.1#7913 -ipset=/.stephaniered.com/gfwlist -server=/.old.honeynet.org/127.0.0.1#7913 -ipset=/.old.honeynet.org/gfwlist -server=/.taiwannation.50webs.com/127.0.0.1#7913 -ipset=/.taiwannation.50webs.com/gfwlist -server=/.my.pcloud.com/127.0.0.1#7913 -ipset=/.my.pcloud.com/gfwlist -server=/.shadowsocks.com/127.0.0.1#7913 -ipset=/.shadowsocks.com/gfwlist -server=/.helloqueer.com/127.0.0.1#7913 -ipset=/.helloqueer.com/gfwlist -server=/.old-cat.net/127.0.0.1#7913 -ipset=/.old-cat.net/gfwlist -server=/.me.youthwant.com.tw/127.0.0.1#7913 -ipset=/.me.youthwant.com.tw/gfwlist -server=/.bestforchina.org/127.0.0.1#7913 -ipset=/.bestforchina.org/gfwlist -server=/.taiwanus.net/127.0.0.1#7913 -ipset=/.taiwanus.net/gfwlist -server=/.japan-whores.com/127.0.0.1#7913 -ipset=/.japan-whores.com/gfwlist -server=/.boxun.com/127.0.0.1#7913 -ipset=/.boxun.com/gfwlist -server=/.shadowsky.xyz/127.0.0.1#7913 -ipset=/.shadowsky.xyz/gfwlist -server=/.tw.answers.yahoo.com/127.0.0.1#7913 -ipset=/.tw.answers.yahoo.com/gfwlist -server=/.chinaaid.net/127.0.0.1#7913 -ipset=/.chinaaid.net/gfwlist -server=/.bangchen.net/127.0.0.1#7913 -ipset=/.bangchen.net/gfwlist -server=/.bestvpnanalysis.com/127.0.0.1#7913 -ipset=/.bestvpnanalysis.com/gfwlist -server=/.shadeyouvpn.com/127.0.0.1#7913 -ipset=/.shadeyouvpn.com/gfwlist -server=/.wujie.net/127.0.0.1#7913 -ipset=/.wujie.net/gfwlist -server=/.hnntube.com/127.0.0.1#7913 -ipset=/.hnntube.com/gfwlist -server=/.mansion.com/127.0.0.1#7913 -ipset=/.mansion.com/gfwlist -server=/.pastebin.com/127.0.0.1#7913 -ipset=/.pastebin.com/gfwlist -server=/.sfileydy.com/127.0.0.1#7913 -ipset=/.sfileydy.com/gfwlist -server=/.kagyumonlam.org/127.0.0.1#7913 -ipset=/.kagyumonlam.org/gfwlist -server=/.bigsound.org/127.0.0.1#7913 -ipset=/.bigsound.org/gfwlist -server=/.sf.net/127.0.0.1#7913 -ipset=/.sf.net/gfwlist -server=/.sextvx.com/127.0.0.1#7913 -ipset=/.sextvx.com/gfwlist -server=/.artofpeacefoundation.org/127.0.0.1#7913 -ipset=/.artofpeacefoundation.org/gfwlist -server=/.21sextury.com/127.0.0.1#7913 -ipset=/.21sextury.com/gfwlist -server=/.sexinsex.net/127.0.0.1#7913 -ipset=/.sexinsex.net/gfwlist -server=/.amigobbs.net/127.0.0.1#7913 -ipset=/.amigobbs.net/gfwlist -server=/.gamer-cds.cdn.hinet.net/127.0.0.1#7913 -ipset=/.gamer-cds.cdn.hinet.net/gfwlist -server=/.civiliangunner.com/127.0.0.1#7913 -ipset=/.civiliangunner.com/gfwlist -server=/.sexhu.com/127.0.0.1#7913 -ipset=/.sexhu.com/gfwlist -server=/.usfk.mil/127.0.0.1#7913 -ipset=/.usfk.mil/gfwlist -server=/.exrates.me/127.0.0.1#7913 -ipset=/.exrates.me/gfwlist -server=/.ipicture.ru/127.0.0.1#7913 -ipset=/.ipicture.ru/gfwlist -server=/.sex8.cc/127.0.0.1#7913 -ipset=/.sex8.cc/gfwlist -server=/.quoracdn.net/127.0.0.1#7913 -ipset=/.quoracdn.net/gfwlist -server=/.artstation.com/127.0.0.1#7913 -ipset=/.artstation.com/gfwlist -server=/.1984bbs.org/127.0.0.1#7913 -ipset=/.1984bbs.org/gfwlist -server=/.secure.logmein.com/127.0.0.1#7913 -ipset=/.secure.logmein.com/gfwlist -server=/.dscn.info/127.0.0.1#7913 -ipset=/.dscn.info/gfwlist -server=/.greenparty.org.tw/127.0.0.1#7913 -ipset=/.greenparty.org.tw/gfwlist -server=/.slyip.net/127.0.0.1#7913 -ipset=/.slyip.net/gfwlist -server=/.mingpaocanada.com/127.0.0.1#7913 -ipset=/.mingpaocanada.com/gfwlist -server=/.googleartproject.com/127.0.0.1#7913 -ipset=/.googleartproject.com/gfwlist -server=/.club1069.com/127.0.0.1#7913 -ipset=/.club1069.com/gfwlist -server=/.game735.com/127.0.0.1#7913 -ipset=/.game735.com/gfwlist -server=/.sevenload.com/127.0.0.1#7913 -ipset=/.sevenload.com/gfwlist -server=/.settv.com.tw/127.0.0.1#7913 -ipset=/.settv.com.tw/gfwlist -server=/.isunaffairs.com/127.0.0.1#7913 -ipset=/.isunaffairs.com/gfwlist -server=/.sesawe.org/127.0.0.1#7913 -ipset=/.sesawe.org/gfwlist -server=/.dushi.ca/127.0.0.1#7913 -ipset=/.dushi.ca/gfwlist -server=/.picacomiccn.com/127.0.0.1#7913 -ipset=/.picacomiccn.com/gfwlist -server=/.dynamic-dns.net/127.0.0.1#7913 -ipset=/.dynamic-dns.net/gfwlist -server=/.googleideas.com/127.0.0.1#7913 -ipset=/.googleideas.com/gfwlist -server=/.ipredator.se/127.0.0.1#7913 -ipset=/.ipredator.se/gfwlist -server=/.contactmagazine.net/127.0.0.1#7913 -ipset=/.contactmagazine.net/gfwlist -server=/.javzoo.com/127.0.0.1#7913 -ipset=/.javzoo.com/gfwlist -server=/.news.seehua.com/127.0.0.1#7913 -ipset=/.news.seehua.com/gfwlist -server=/.dns04.com/127.0.0.1#7913 -ipset=/.dns04.com/gfwlist -server=/.securitykiss.com/127.0.0.1#7913 -ipset=/.securitykiss.com/gfwlist -server=/.bvpn.com/127.0.0.1#7913 -ipset=/.bvpn.com/gfwlist -server=/.puffstore.com/127.0.0.1#7913 -ipset=/.puffstore.com/gfwlist -server=/.fanqiang.network/127.0.0.1#7913 -ipset=/.fanqiang.network/gfwlist -server=/.bitsnoop.com/127.0.0.1#7913 -ipset=/.bitsnoop.com/gfwlist -server=/.bestvpnserver.com/127.0.0.1#7913 -ipset=/.bestvpnserver.com/gfwlist -server=/.hahlo.com/127.0.0.1#7913 -ipset=/.hahlo.com/gfwlist -server=/.thechinabeat.org/127.0.0.1#7913 -ipset=/.thechinabeat.org/gfwlist -server=/.raidcall.com.tw/127.0.0.1#7913 -ipset=/.raidcall.com.tw/gfwlist -server=/.geti2p.net/127.0.0.1#7913 -ipset=/.geti2p.net/gfwlist -server=/.googlecommerce.com/127.0.0.1#7913 -ipset=/.googlecommerce.com/gfwlist -server=/.cpj.org/127.0.0.1#7913 -ipset=/.cpj.org/gfwlist -server=/.google.sn/127.0.0.1#7913 -ipset=/.google.sn/gfwlist -server=/.fgmtv.org/127.0.0.1#7913 -ipset=/.fgmtv.org/gfwlist -server=/.bestvpnservice.com/127.0.0.1#7913 -ipset=/.bestvpnservice.com/gfwlist -server=/.domainhelp.search.com/127.0.0.1#7913 -ipset=/.domainhelp.search.com/gfwlist -server=/.rtycminnesota.org/127.0.0.1#7913 -ipset=/.rtycminnesota.org/gfwlist -server=/.dharamsalanet.com/127.0.0.1#7913 -ipset=/.dharamsalanet.com/gfwlist -server=/.businessweek.com/127.0.0.1#7913 -ipset=/.businessweek.com/gfwlist -server=/.fotile.me/127.0.0.1#7913 -ipset=/.fotile.me/gfwlist -server=/.scriptspot.com/127.0.0.1#7913 -ipset=/.scriptspot.com/gfwlist -server=/.hihistory.net/127.0.0.1#7913 -ipset=/.hihistory.net/gfwlist -server=/.kkbox.com/127.0.0.1#7913 -ipset=/.kkbox.com/gfwlist -server=/.hrea.org/127.0.0.1#7913 -ipset=/.hrea.org/gfwlist -server=/.pbworks.com/127.0.0.1#7913 -ipset=/.pbworks.com/gfwlist -server=/.falungong.org.uk/127.0.0.1#7913 -ipset=/.falungong.org.uk/gfwlist -server=/.zhreader.com/127.0.0.1#7913 -ipset=/.zhreader.com/gfwlist -server=/.scmp.com/127.0.0.1#7913 -ipset=/.scmp.com/gfwlist -server=/.xn--ngstr-lra8j.com/127.0.0.1#7913 -ipset=/.xn--ngstr-lra8j.com/gfwlist -server=/.hhthesakyatrizin.org/127.0.0.1#7913 -ipset=/.hhthesakyatrizin.org/gfwlist -server=/.buzzhand.com/127.0.0.1#7913 -ipset=/.buzzhand.com/gfwlist -server=/.al-qimmah.net/127.0.0.1#7913 -ipset=/.al-qimmah.net/gfwlist -server=/.chinainterimgov.org/127.0.0.1#7913 -ipset=/.chinainterimgov.org/gfwlist -server=/.scasino.com/127.0.0.1#7913 -ipset=/.scasino.com/gfwlist -server=/.ernestmandel.org/127.0.0.1#7913 -ipset=/.ernestmandel.org/gfwlist -server=/.apkmirror.com/127.0.0.1#7913 -ipset=/.apkmirror.com/gfwlist -server=/.gfw.press/127.0.0.1#7913 -ipset=/.gfw.press/gfwlist -server=/.sbme.me/127.0.0.1#7913 -ipset=/.sbme.me/gfwlist -server=/.secure.raxcdn.com/127.0.0.1#7913 -ipset=/.secure.raxcdn.com/gfwlist -server=/.avg.com/127.0.0.1#7913 -ipset=/.avg.com/gfwlist -server=/.savevid.com/127.0.0.1#7913 -ipset=/.savevid.com/gfwlist -server=/.www.powerpointninja.com/127.0.0.1#7913 -ipset=/.www.powerpointninja.com/gfwlist -server=/.acnw.com.au/127.0.0.1#7913 -ipset=/.acnw.com.au/gfwlist -server=/.savetibet.org/127.0.0.1#7913 -ipset=/.savetibet.org/gfwlist -server=/.zuola.com/127.0.0.1#7913 -ipset=/.zuola.com/gfwlist -server=/.bcrncdn.com/127.0.0.1#7913 -ipset=/.bcrncdn.com/gfwlist -server=/.knowledgerush.com/127.0.0.1#7913 -ipset=/.knowledgerush.com/gfwlist -server=/.madonna-av.com/127.0.0.1#7913 -ipset=/.madonna-av.com/gfwlist -server=/.chinarightsia.org/127.0.0.1#7913 -ipset=/.chinarightsia.org/gfwlist -server=/.sanmin.com.tw/127.0.0.1#7913 -ipset=/.sanmin.com.tw/gfwlist -server=/.sendsmtp.com/127.0.0.1#7913 -ipset=/.sendsmtp.com/gfwlist -server=/.sftindia.org/127.0.0.1#7913 -ipset=/.sftindia.org/gfwlist -server=/.sambhota.org/127.0.0.1#7913 -ipset=/.sambhota.org/gfwlist -server=/.salvation.org.hk/127.0.0.1#7913 -ipset=/.salvation.org.hk/gfwlist -server=/.galenwu.com/127.0.0.1#7913 -ipset=/.galenwu.com/gfwlist -server=/.deutsche-welle.de/127.0.0.1#7913 -ipset=/.deutsche-welle.de/gfwlist -server=/.cclifefl.org/127.0.0.1#7913 -ipset=/.cclifefl.org/gfwlist -server=/.sakya.org/127.0.0.1#7913 -ipset=/.sakya.org/gfwlist -server=/.vrmtr.com/127.0.0.1#7913 -ipset=/.vrmtr.com/gfwlist -server=/.hakkatv.org.tw/127.0.0.1#7913 -ipset=/.hakkatv.org.tw/gfwlist -server=/.busytrade.com/127.0.0.1#7913 -ipset=/.busytrade.com/gfwlist -server=/.safervpn.com/127.0.0.1#7913 -ipset=/.safervpn.com/gfwlist -server=/.hotels.cn/127.0.0.1#7913 -ipset=/.hotels.cn/gfwlist -server=/.webrtc.org/127.0.0.1#7913 -ipset=/.webrtc.org/gfwlist -server=/.dropbooks.tv/127.0.0.1#7913 -ipset=/.dropbooks.tv/gfwlist -server=/.ebony-beauty.com/127.0.0.1#7913 -ipset=/.ebony-beauty.com/gfwlist -server=/.lvv2.com/127.0.0.1#7913 -ipset=/.lvv2.com/gfwlist -server=/.suissl.com/127.0.0.1#7913 -ipset=/.suissl.com/gfwlist -server=/.aisex.com/127.0.0.1#7913 -ipset=/.aisex.com/gfwlist -server=/.thetibetcenter.org/127.0.0.1#7913 -ipset=/.thetibetcenter.org/gfwlist -server=/.mnewstv.com/127.0.0.1#7913 -ipset=/.mnewstv.com/gfwlist -server=/.aculo.us/127.0.0.1#7913 -ipset=/.aculo.us/gfwlist -server=/.blewpass.com/127.0.0.1#7913 -ipset=/.blewpass.com/gfwlist -server=/.fourface.nodesnoop.com/127.0.0.1#7913 -ipset=/.fourface.nodesnoop.com/gfwlist -server=/.retweetist.com/127.0.0.1#7913 -ipset=/.retweetist.com/gfwlist -server=/.botanwang.com/127.0.0.1#7913 -ipset=/.botanwang.com/gfwlist -server=/.dontfilter.us/127.0.0.1#7913 -ipset=/.dontfilter.us/gfwlist -server=/.reutersmedia.net/127.0.0.1#7913 -ipset=/.reutersmedia.net/gfwlist -server=/.ifanqiang.com/127.0.0.1#7913 -ipset=/.ifanqiang.com/gfwlist -server=/.cdp1998.org/127.0.0.1#7913 -ipset=/.cdp1998.org/gfwlist -server=/.rutube.ru/127.0.0.1#7913 -ipset=/.rutube.ru/gfwlist -server=/.redditstatic.com/127.0.0.1#7913 -ipset=/.redditstatic.com/gfwlist -server=/.files2me.com/127.0.0.1#7913 -ipset=/.files2me.com/gfwlist -server=/.askynz.net/127.0.0.1#7913 -ipset=/.askynz.net/gfwlist -server=/.communitychoicecu.com/127.0.0.1#7913 -ipset=/.communitychoicecu.com/gfwlist -server=/.briian.com/127.0.0.1#7913 -ipset=/.briian.com/gfwlist -server=/.rushbee.com/127.0.0.1#7913 -ipset=/.rushbee.com/gfwlist -server=/.runbtx.com/127.0.0.1#7913 -ipset=/.runbtx.com/gfwlist -server=/.getoutline.org/127.0.0.1#7913 -ipset=/.getoutline.org/gfwlist -server=/.10conditionsoflove.com/127.0.0.1#7913 -ipset=/.10conditionsoflove.com/gfwlist -server=/.ruanyifeng.com/127.0.0.1#7913 -ipset=/.ruanyifeng.com/gfwlist -server=/.seapuff.com/127.0.0.1#7913 -ipset=/.seapuff.com/gfwlist -server=/.rti.org.tw/127.0.0.1#7913 -ipset=/.rti.org.tw/gfwlist -server=/.ellawine.org/127.0.0.1#7913 -ipset=/.ellawine.org/gfwlist -server=/.ksdl.org/127.0.0.1#7913 -ipset=/.ksdl.org/gfwlist -server=/.mcadforums.com/127.0.0.1#7913 -ipset=/.mcadforums.com/gfwlist -server=/.nzchinese.com/127.0.0.1#7913 -ipset=/.nzchinese.com/gfwlist -server=/.citizenlab.org/127.0.0.1#7913 -ipset=/.citizenlab.org/gfwlist -server=/.onlytweets.com/127.0.0.1#7913 -ipset=/.onlytweets.com/gfwlist -server=/.hizb-ut-tahrir.org/127.0.0.1#7913 -ipset=/.hizb-ut-tahrir.org/gfwlist -server=/.dilber.se/127.0.0.1#7913 -ipset=/.dilber.se/gfwlist -server=/.rthk.hk/127.0.0.1#7913 -ipset=/.rthk.hk/gfwlist -server=/.tttan.com/127.0.0.1#7913 -ipset=/.tttan.com/gfwlist -server=/.hk.gradconnection.com/127.0.0.1#7913 -ipset=/.hk.gradconnection.com/gfwlist -server=/.periscope.tv/127.0.0.1#7913 -ipset=/.periscope.tv/gfwlist -server=/.rsgamen.org/127.0.0.1#7913 -ipset=/.rsgamen.org/gfwlist -server=/.nudezz.com/127.0.0.1#7913 -ipset=/.nudezz.com/gfwlist -server=/.tibetjustice.org/127.0.0.1#7913 -ipset=/.tibetjustice.org/gfwlist -server=/.u15.info/127.0.0.1#7913 -ipset=/.u15.info/gfwlist -server=/.italiatibet.org/127.0.0.1#7913 -ipset=/.italiatibet.org/gfwlist -server=/.chinese-leaders.org/127.0.0.1#7913 -ipset=/.chinese-leaders.org/gfwlist -server=/.dalailamaprotesters.info/127.0.0.1#7913 -ipset=/.dalailamaprotesters.info/gfwlist -server=/.answering-islam.org/127.0.0.1#7913 -ipset=/.answering-islam.org/gfwlist -server=/.fscked.org/127.0.0.1#7913 -ipset=/.fscked.org/gfwlist -server=/.hec.su/127.0.0.1#7913 -ipset=/.hec.su/gfwlist -server=/.bemywife.cc/127.0.0.1#7913 -ipset=/.bemywife.cc/gfwlist -server=/.iicns.com/127.0.0.1#7913 -ipset=/.iicns.com/gfwlist -server=/.withgoogle.com/127.0.0.1#7913 -ipset=/.withgoogle.com/gfwlist -server=/.plus28.com/127.0.0.1#7913 -ipset=/.plus28.com/gfwlist -server=/.shizhao.org/127.0.0.1#7913 -ipset=/.shizhao.org/gfwlist -server=/.h5dm.com/127.0.0.1#7913 -ipset=/.h5dm.com/gfwlist -server=/.lightyearvpn.com/127.0.0.1#7913 -ipset=/.lightyearvpn.com/gfwlist -server=/.google.at/127.0.0.1#7913 -ipset=/.google.at/gfwlist -server=/.rojo.com/127.0.0.1#7913 -ipset=/.rojo.com/gfwlist -server=/.video.yahoo.com/127.0.0.1#7913 -ipset=/.video.yahoo.com/gfwlist -server=/.hkatvnews.com/127.0.0.1#7913 -ipset=/.hkatvnews.com/gfwlist -server=/.freeyoutubeproxy.net/127.0.0.1#7913 -ipset=/.freeyoutubeproxy.net/gfwlist -server=/.national-lottery.co.uk/127.0.0.1#7913 -ipset=/.national-lottery.co.uk/gfwlist -server=/.hide.me/127.0.0.1#7913 -ipset=/.hide.me/gfwlist -server=/.rocket-inc.net/127.0.0.1#7913 -ipset=/.rocket-inc.net/gfwlist -server=/.spendee.com/127.0.0.1#7913 -ipset=/.spendee.com/gfwlist -server=/.dastrassi.org/127.0.0.1#7913 -ipset=/.dastrassi.org/gfwlist -server=/.textnow.me/127.0.0.1#7913 -ipset=/.textnow.me/gfwlist -server=/.rmjdw.com/127.0.0.1#7913 -ipset=/.rmjdw.com/gfwlist -server=/.catfightpayperview.xxx/127.0.0.1#7913 -ipset=/.catfightpayperview.xxx/gfwlist -server=/.app.heywire.com/127.0.0.1#7913 -ipset=/.app.heywire.com/gfwlist -server=/.photodharma.net/127.0.0.1#7913 -ipset=/.photodharma.net/gfwlist -server=/.izaobao.us/127.0.0.1#7913 -ipset=/.izaobao.us/gfwlist -server=/.dotvpn.com/127.0.0.1#7913 -ipset=/.dotvpn.com/gfwlist -server=/.paldengyal.com/127.0.0.1#7913 -ipset=/.paldengyal.com/gfwlist -server=/.mcfog.com/127.0.0.1#7913 -ipset=/.mcfog.com/gfwlist -server=/.ibros.org/127.0.0.1#7913 -ipset=/.ibros.org/gfwlist -server=/.tacem.org/127.0.0.1#7913 -ipset=/.tacem.org/gfwlist -server=/.eireinikotaerukai.com/127.0.0.1#7913 -ipset=/.eireinikotaerukai.com/gfwlist -server=/.gstatic.com/127.0.0.1#7913 -ipset=/.gstatic.com/gfwlist -server=/.fanqiangyakexi.net/127.0.0.1#7913 -ipset=/.fanqiangyakexi.net/gfwlist -server=/.rfachina.com/127.0.0.1#7913 -ipset=/.rfachina.com/gfwlist -server=/.cointobe.com/127.0.0.1#7913 -ipset=/.cointobe.com/gfwlist -server=/.domaintoday.com.au/127.0.0.1#7913 -ipset=/.domaintoday.com.au/gfwlist -server=/.clearwisdom.net/127.0.0.1#7913 -ipset=/.clearwisdom.net/gfwlist -server=/.pornstarclub.com/127.0.0.1#7913 -ipset=/.pornstarclub.com/gfwlist -server=/.btcbank.bank/127.0.0.1#7913 -ipset=/.btcbank.bank/gfwlist -server=/.mrbonus.com/127.0.0.1#7913 -ipset=/.mrbonus.com/gfwlist -server=/.revver.com/127.0.0.1#7913 -ipset=/.revver.com/gfwlist -server=/.kagyuoffice.org.tw/127.0.0.1#7913 -ipset=/.kagyuoffice.org.tw/gfwlist -server=/.free4u.com.ar/127.0.0.1#7913 -ipset=/.free4u.com.ar/gfwlist -server=/.www.cmoinc.org/127.0.0.1#7913 -ipset=/.www.cmoinc.org/gfwlist -server=/.taoism.net/127.0.0.1#7913 -ipset=/.taoism.net/gfwlist -server=/.dw-world.com/127.0.0.1#7913 -ipset=/.dw-world.com/gfwlist -server=/.razyboard.com/127.0.0.1#7913 -ipset=/.razyboard.com/gfwlist -server=/.falunhr.org/127.0.0.1#7913 -ipset=/.falunhr.org/gfwlist -server=/.occupytiananmen.com/127.0.0.1#7913 -ipset=/.occupytiananmen.com/gfwlist -server=/.subacme.rerouted.org/127.0.0.1#7913 -ipset=/.subacme.rerouted.org/gfwlist -server=/.dalailama80.org/127.0.0.1#7913 -ipset=/.dalailama80.org/gfwlist -server=/.duihuahrjournal.org/127.0.0.1#7913 -ipset=/.duihuahrjournal.org/gfwlist -server=/.specxinzl.jigsy.com/127.0.0.1#7913 -ipset=/.specxinzl.jigsy.com/gfwlist -server=/.alliance.org.hk/127.0.0.1#7913 -ipset=/.alliance.org.hk/gfwlist -server=/.tbrc.org/127.0.0.1#7913 -ipset=/.tbrc.org/gfwlist -server=/.coinex.com/127.0.0.1#7913 -ipset=/.coinex.com/gfwlist -server=/.gvt0.com/127.0.0.1#7913 -ipset=/.gvt0.com/gfwlist -server=/.globalvpn.net/127.0.0.1#7913 -ipset=/.globalvpn.net/gfwlist -server=/.minghui.org/127.0.0.1#7913 -ipset=/.minghui.org/gfwlist -server=/.btsynckeys.com/127.0.0.1#7913 -ipset=/.btsynckeys.com/gfwlist -server=/.religioustolerance.org/127.0.0.1#7913 -ipset=/.religioustolerance.org/gfwlist -server=/.lflinkup.org/127.0.0.1#7913 -ipset=/.lflinkup.org/gfwlist -server=/.mohu.ml/127.0.0.1#7913 -ipset=/.mohu.ml/gfwlist -server=/.mingpaony.com/127.0.0.1#7913 -ipset=/.mingpaony.com/gfwlist -server=/.memrijttm.org/127.0.0.1#7913 -ipset=/.memrijttm.org/gfwlist -server=/.booktopia.com.au/127.0.0.1#7913 -ipset=/.booktopia.com.au/gfwlist -server=/.ssglobal.co/127.0.0.1#7913 -ipset=/.ssglobal.co/gfwlist -server=/.relaxbbs.com/127.0.0.1#7913 -ipset=/.relaxbbs.com/gfwlist -server=/.backtotiananmen.com/127.0.0.1#7913 -ipset=/.backtotiananmen.com/gfwlist -server=/.meme.yahoo.com/127.0.0.1#7913 -ipset=/.meme.yahoo.com/gfwlist -server=/.kissjav.com/127.0.0.1#7913 -ipset=/.kissjav.com/gfwlist -server=/.china-week.com/127.0.0.1#7913 -ipset=/.china-week.com/gfwlist -server=/.chinagreenparty.org/127.0.0.1#7913 -ipset=/.chinagreenparty.org/gfwlist -server=/.kusocity.com/127.0.0.1#7913 -ipset=/.kusocity.com/gfwlist -server=/.dowei.org/127.0.0.1#7913 -ipset=/.dowei.org/gfwlist -server=/.caribbeancom.com/127.0.0.1#7913 -ipset=/.caribbeancom.com/gfwlist -server=/.dynupdate.no-ip.com/127.0.0.1#7913 -ipset=/.dynupdate.no-ip.com/gfwlist -server=/.www.linksalpha.com/127.0.0.1#7913 -ipset=/.www.linksalpha.com/gfwlist -server=/.4sqi.net/127.0.0.1#7913 -ipset=/.4sqi.net/gfwlist -server=/.m.me/127.0.0.1#7913 -ipset=/.m.me/gfwlist -server=/.tibetan-alliance.org/127.0.0.1#7913 -ipset=/.tibetan-alliance.org/gfwlist -server=/.jungleheart.com/127.0.0.1#7913 -ipset=/.jungleheart.com/gfwlist -server=/.cos-moe.com/127.0.0.1#7913 -ipset=/.cos-moe.com/gfwlist -server=/.www.ajsands.com/127.0.0.1#7913 -ipset=/.www.ajsands.com/gfwlist -server=/.recoveryversion.com.tw/127.0.0.1#7913 -ipset=/.recoveryversion.com.tw/gfwlist -server=/.gun-world.net/127.0.0.1#7913 -ipset=/.gun-world.net/gfwlist -server=/.wezone.net/127.0.0.1#7913 -ipset=/.wezone.net/gfwlist -server=/.bloomberg.de/127.0.0.1#7913 -ipset=/.bloomberg.de/gfwlist -server=/.bet365.com/127.0.0.1#7913 -ipset=/.bet365.com/gfwlist -server=/.godfootsteps.org/127.0.0.1#7913 -ipset=/.godfootsteps.org/gfwlist -server=/.sytes.net/127.0.0.1#7913 -ipset=/.sytes.net/gfwlist -server=/.readmoo.com/127.0.0.1#7913 -ipset=/.readmoo.com/gfwlist -server=/.read100.com/127.0.0.1#7913 -ipset=/.read100.com/gfwlist -server=/.faststone.org/127.0.0.1#7913 -ipset=/.faststone.org/gfwlist -server=/.investigating.wordpress.com/127.0.0.1#7913 -ipset=/.investigating.wordpress.com/gfwlist -server=/.xinshijue.com/127.0.0.1#7913 -ipset=/.xinshijue.com/gfwlist -server=/.woeser.com/127.0.0.1#7913 -ipset=/.woeser.com/gfwlist -server=/.gaymenring.com/127.0.0.1#7913 -ipset=/.gaymenring.com/gfwlist -server=/.barenakedislam.com/127.0.0.1#7913 -ipset=/.barenakedislam.com/gfwlist -server=/.bonbonme.com/127.0.0.1#7913 -ipset=/.bonbonme.com/gfwlist -server=/.dajiyuan.de/127.0.0.1#7913 -ipset=/.dajiyuan.de/gfwlist -server=/.sss.camp/127.0.0.1#7913 -ipset=/.sss.camp/gfwlist -server=/.cts.com.tw/127.0.0.1#7913 -ipset=/.cts.com.tw/gfwlist -server=/.56cun04.jigsy.com/127.0.0.1#7913 -ipset=/.56cun04.jigsy.com/gfwlist -server=/.c-spanvideo.org/127.0.0.1#7913 -ipset=/.c-spanvideo.org/gfwlist -server=/.six-degrees.io/127.0.0.1#7913 -ipset=/.six-degrees.io/gfwlist -server=/.ranyunfei.com/127.0.0.1#7913 -ipset=/.ranyunfei.com/gfwlist -server=/.google.ms/127.0.0.1#7913 -ipset=/.google.ms/gfwlist -server=/.rangzen.org/127.0.0.1#7913 -ipset=/.rangzen.org/gfwlist -server=/.ai-wen.net/127.0.0.1#7913 -ipset=/.ai-wen.net/gfwlist -server=/.rangwang.biz/127.0.0.1#7913 -ipset=/.rangwang.biz/gfwlist -server=/.seed4.me/127.0.0.1#7913 -ipset=/.seed4.me/gfwlist -server=/.no-ip.org/127.0.0.1#7913 -ipset=/.no-ip.org/gfwlist -server=/.dvdpac.com/127.0.0.1#7913 -ipset=/.dvdpac.com/gfwlist -server=/.panoramio.com/127.0.0.1#7913 -ipset=/.panoramio.com/gfwlist -server=/.raidtalk.com.tw/127.0.0.1#7913 -ipset=/.raidtalk.com.tw/gfwlist -server=/.scribd.com/127.0.0.1#7913 -ipset=/.scribd.com/gfwlist -server=/.vocn.tv/127.0.0.1#7913 -ipset=/.vocn.tv/gfwlist -server=/.chinalaborwatch.org/127.0.0.1#7913 -ipset=/.chinalaborwatch.org/gfwlist -server=/.watchmygf.net/127.0.0.1#7913 -ipset=/.watchmygf.net/gfwlist -server=/.zhengwunet.org/127.0.0.1#7913 -ipset=/.zhengwunet.org/gfwlist -server=/.izles.net/127.0.0.1#7913 -ipset=/.izles.net/gfwlist -server=/.jwmusic.org/127.0.0.1#7913 -ipset=/.jwmusic.org/gfwlist -server=/.zzcloud.me/127.0.0.1#7913 -ipset=/.zzcloud.me/gfwlist -server=/.blogcatalog.com/127.0.0.1#7913 -ipset=/.blogcatalog.com/gfwlist -server=/.hihiforum.com/127.0.0.1#7913 -ipset=/.hihiforum.com/gfwlist -server=/.youtu.be/127.0.0.1#7913 -ipset=/.youtu.be/gfwlist -server=/.liudejun.com/127.0.0.1#7913 -ipset=/.liudejun.com/gfwlist -server=/.tvider.com/127.0.0.1#7913 -ipset=/.tvider.com/gfwlist -server=/.rael.org/127.0.0.1#7913 -ipset=/.rael.org/gfwlist -server=/.macts.com.tw/127.0.0.1#7913 -ipset=/.macts.com.tw/gfwlist -server=/.nemesis2.qx.net/127.0.0.1#7913 -ipset=/.nemesis2.qx.net/gfwlist -server=/.open.com.hk/127.0.0.1#7913 -ipset=/.open.com.hk/gfwlist -server=/.zyns.com/127.0.0.1#7913 -ipset=/.zyns.com/gfwlist -server=/.trendsmap.com/127.0.0.1#7913 -ipset=/.trendsmap.com/gfwlist -server=/.quran.com/127.0.0.1#7913 -ipset=/.quran.com/gfwlist -server=/.blog.daum.net/127.0.0.1#7913 -ipset=/.blog.daum.net/gfwlist -server=/.sitemaps.org/127.0.0.1#7913 -ipset=/.sitemaps.org/gfwlist -server=/.citizensradio.org/127.0.0.1#7913 -ipset=/.citizensradio.org/gfwlist -server=/.google.jo/127.0.0.1#7913 -ipset=/.google.jo/gfwlist -server=/.cusu.hk/127.0.0.1#7913 -ipset=/.cusu.hk/gfwlist -server=/.dafagood.com/127.0.0.1#7913 -ipset=/.dafagood.com/gfwlist -server=/.rawgithub.com/127.0.0.1#7913 -ipset=/.rawgithub.com/gfwlist -server=/.qstatus.com/127.0.0.1#7913 -ipset=/.qstatus.com/gfwlist -server=/.godsdirectcontact.org/127.0.0.1#7913 -ipset=/.godsdirectcontact.org/gfwlist -server=/.akiba-online.com/127.0.0.1#7913 -ipset=/.akiba-online.com/gfwlist -server=/.heyzo.com/127.0.0.1#7913 -ipset=/.heyzo.com/gfwlist -server=/.blog.qooza.hk/127.0.0.1#7913 -ipset=/.blog.qooza.hk/gfwlist -server=/.igmg.de/127.0.0.1#7913 -ipset=/.igmg.de/gfwlist -server=/.video.ap.org/127.0.0.1#7913 -ipset=/.video.ap.org/gfwlist -server=/.download.cnet.com/127.0.0.1#7913 -ipset=/.download.cnet.com/gfwlist -server=/.wiki.cnitter.com/127.0.0.1#7913 -ipset=/.wiki.cnitter.com/gfwlist -server=/.i.lithium.com/127.0.0.1#7913 -ipset=/.i.lithium.com/gfwlist -server=/.news.hk.msn.com/127.0.0.1#7913 -ipset=/.news.hk.msn.com/gfwlist -server=/.myca168.com/127.0.0.1#7913 -ipset=/.myca168.com/gfwlist -server=/.boardreader.com/127.0.0.1#7913 -ipset=/.boardreader.com/gfwlist -server=/.qiwen.lu/127.0.0.1#7913 -ipset=/.qiwen.lu/gfwlist -server=/.qienkuen.org/127.0.0.1#7913 -ipset=/.qienkuen.org/gfwlist -server=/.qidian.ca/127.0.0.1#7913 -ipset=/.qidian.ca/gfwlist -server=/.dipity.com/127.0.0.1#7913 -ipset=/.dipity.com/gfwlist -server=/.qiangyou.org/127.0.0.1#7913 -ipset=/.qiangyou.org/gfwlist -server=/.huayuworld.org/127.0.0.1#7913 -ipset=/.huayuworld.org/gfwlist -server=/.tuibeitu.net/127.0.0.1#7913 -ipset=/.tuibeitu.net/gfwlist -server=/.trulyergonomic.com/127.0.0.1#7913 -ipset=/.trulyergonomic.com/gfwlist -server=/.bongacams.com/127.0.0.1#7913 -ipset=/.bongacams.com/gfwlist -server=/.liujianshu.com/127.0.0.1#7913 -ipset=/.liujianshu.com/gfwlist -server=/.mysinablog.com/127.0.0.1#7913 -ipset=/.mysinablog.com/gfwlist -server=/.dagelijksestandaard.nl/127.0.0.1#7913 -ipset=/.dagelijksestandaard.nl/gfwlist -server=/.tagwa.org.au/127.0.0.1#7913 -ipset=/.tagwa.org.au/gfwlist -server=/.nko.navy.mil/127.0.0.1#7913 -ipset=/.nko.navy.mil/gfwlist -server=/.hbg.com/127.0.0.1#7913 -ipset=/.hbg.com/gfwlist -server=/.chinese-memorial.org/127.0.0.1#7913 -ipset=/.chinese-memorial.org/gfwlist -server=/.desc.se/127.0.0.1#7913 -ipset=/.desc.se/gfwlist -server=/.cmule.org/127.0.0.1#7913 -ipset=/.cmule.org/gfwlist -server=/.python.com/127.0.0.1#7913 -ipset=/.python.com/gfwlist -server=/.chrdnet.com/127.0.0.1#7913 -ipset=/.chrdnet.com/gfwlist -server=/.xiaolan.me/127.0.0.1#7913 -ipset=/.xiaolan.me/gfwlist -server=/.telegram.org/127.0.0.1#7913 -ipset=/.telegram.org/gfwlist -server=/.bizhat.com/127.0.0.1#7913 -ipset=/.bizhat.com/gfwlist -server=/.d1c37gjwa26taa.cloudfront.net/127.0.0.1#7913 -ipset=/.d1c37gjwa26taa.cloudfront.net/gfwlist -server=/.packages.debian.org/127.0.0.1#7913 -ipset=/.packages.debian.org/gfwlist -server=/.code1984.com/127.0.0.1#7913 -ipset=/.code1984.com/gfwlist -server=/.googleweblight.com/127.0.0.1#7913 -ipset=/.googleweblight.com/gfwlist -server=/.poloniex.com/127.0.0.1#7913 -ipset=/.poloniex.com/gfwlist -server=/.free-gate.org/127.0.0.1#7913 -ipset=/.free-gate.org/gfwlist -server=/.peing.net/127.0.0.1#7913 -ipset=/.peing.net/gfwlist -server=/.channel8news.sg/127.0.0.1#7913 -ipset=/.channel8news.sg/gfwlist -server=/.ch.shvoong.com/127.0.0.1#7913 -ipset=/.ch.shvoong.com/gfwlist -server=/.89.64.charter.constitutionalism.solutions/127.0.0.1#7913 -ipset=/.89.64.charter.constitutionalism.solutions/gfwlist -server=/.eracom.com.tw/127.0.0.1#7913 -ipset=/.eracom.com.tw/gfwlist -server=/.gzm.tv/127.0.0.1#7913 -ipset=/.gzm.tv/gfwlist -server=/.zzux.com/127.0.0.1#7913 -ipset=/.zzux.com/gfwlist -server=/.google.ba/127.0.0.1#7913 -ipset=/.google.ba/gfwlist -server=/.purevpn.com/127.0.0.1#7913 -ipset=/.purevpn.com/gfwlist -server=/.chatnook.com/127.0.0.1#7913 -ipset=/.chatnook.com/gfwlist -server=/.tsemtulku.com/127.0.0.1#7913 -ipset=/.tsemtulku.com/gfwlist -server=/.mlcool.com/127.0.0.1#7913 -ipset=/.mlcool.com/gfwlist -server=/.punyu.com/127.0.0.1#7913 -ipset=/.punyu.com/gfwlist -server=/.siddharthasintent.org/127.0.0.1#7913 -ipset=/.siddharthasintent.org/gfwlist -server=/.api.dropboxapi.com/127.0.0.1#7913 -ipset=/.api.dropboxapi.com/gfwlist -server=/.anthonycalzadilla.com/127.0.0.1#7913 -ipset=/.anthonycalzadilla.com/gfwlist -server=/.ptt.cc/127.0.0.1#7913 -ipset=/.ptt.cc/gfwlist -server=/.softwaredownload.gitbooks.io/127.0.0.1#7913 -ipset=/.softwaredownload.gitbooks.io/gfwlist -server=/.free-ssh.com/127.0.0.1#7913 -ipset=/.free-ssh.com/gfwlist -server=/.huanghuagang.org/127.0.0.1#7913 -ipset=/.huanghuagang.org/gfwlist -server=/.merit-times.com.tw/127.0.0.1#7913 -ipset=/.merit-times.com.tw/gfwlist -server=/.cao.im/127.0.0.1#7913 -ipset=/.cao.im/gfwlist -server=/.chenpokong.net/127.0.0.1#7913 -ipset=/.chenpokong.net/gfwlist -server=/.eyevio.jp/127.0.0.1#7913 -ipset=/.eyevio.jp/gfwlist -server=/.thefacebook.com/127.0.0.1#7913 -ipset=/.thefacebook.com/gfwlist -server=/.psiphon3.com/127.0.0.1#7913 -ipset=/.psiphon3.com/gfwlist -server=/.orzistic.org/127.0.0.1#7913 -ipset=/.orzistic.org/gfwlist -server=/.smarthide.com/127.0.0.1#7913 -ipset=/.smarthide.com/gfwlist -server=/.redchinacn.org/127.0.0.1#7913 -ipset=/.redchinacn.org/gfwlist -server=/.brutaltgp.com/127.0.0.1#7913 -ipset=/.brutaltgp.com/gfwlist -server=/.guruonline.hk/127.0.0.1#7913 -ipset=/.guruonline.hk/gfwlist -server=/.itsaol.com/127.0.0.1#7913 -ipset=/.itsaol.com/gfwlist -server=/.ifcss.org/127.0.0.1#7913 -ipset=/.ifcss.org/gfwlist -server=/.proxpn.com/127.0.0.1#7913 -ipset=/.proxpn.com/gfwlist -server=/.new-3lunch.net/127.0.0.1#7913 -ipset=/.new-3lunch.net/gfwlist -server=/.api.proxlet.com/127.0.0.1#7913 -ipset=/.api.proxlet.com/gfwlist -server=/.proxifier.com/127.0.0.1#7913 -ipset=/.proxifier.com/gfwlist -server=/.666kb.com/127.0.0.1#7913 -ipset=/.666kb.com/gfwlist -server=/.shadowsocks.com.hk/127.0.0.1#7913 -ipset=/.shadowsocks.com.hk/gfwlist -server=/.gov.tw/127.0.0.1#7913 -ipset=/.gov.tw/gfwlist -server=/.fanqianghou.com/127.0.0.1#7913 -ipset=/.fanqianghou.com/gfwlist -server=/.dabr.me/127.0.0.1#7913 -ipset=/.dabr.me/gfwlist -server=/.redd.it/127.0.0.1#7913 -ipset=/.redd.it/gfwlist -server=/.lematin.ch/127.0.0.1#7913 -ipset=/.lematin.ch/gfwlist -server=/.switch1.jp/127.0.0.1#7913 -ipset=/.switch1.jp/gfwlist -server=/.rixcloud.us/127.0.0.1#7913 -ipset=/.rixcloud.us/gfwlist -server=/.csdparty.com/127.0.0.1#7913 -ipset=/.csdparty.com/gfwlist -server=/.procopytips.com/127.0.0.1#7913 -ipset=/.procopytips.com/gfwlist -server=/.puffinbrowser.com/127.0.0.1#7913 -ipset=/.puffinbrowser.com/gfwlist -server=/.softfamous.com/127.0.0.1#7913 -ipset=/.softfamous.com/gfwlist -server=/.recovery.org.tw/127.0.0.1#7913 -ipset=/.recovery.org.tw/gfwlist -server=/.boyangu.com/127.0.0.1#7913 -ipset=/.boyangu.com/gfwlist -server=/.freedomchina.info/127.0.0.1#7913 -ipset=/.freedomchina.info/gfwlist -server=/.private.com/127.0.0.1#7913 -ipset=/.private.com/gfwlist -server=/.mylftv.com/127.0.0.1#7913 -ipset=/.mylftv.com/gfwlist -server=/.gazotube.com/127.0.0.1#7913 -ipset=/.gazotube.com/gfwlist -server=/.pureinsight.org/127.0.0.1#7913 -ipset=/.pureinsight.org/gfwlist -server=/.prisoneralert.com/127.0.0.1#7913 -ipset=/.prisoneralert.com/gfwlist -server=/.chromeexperiments.com/127.0.0.1#7913 -ipset=/.chromeexperiments.com/gfwlist -server=/.omni7.jp/127.0.0.1#7913 -ipset=/.omni7.jp/gfwlist -server=/.trt.net.tr/127.0.0.1#7913 -ipset=/.trt.net.tr/gfwlist -server=/.like.com/127.0.0.1#7913 -ipset=/.like.com/gfwlist -server=/.prestige-av.com/127.0.0.1#7913 -ipset=/.prestige-av.com/gfwlist -server=/.furhhdl.org/127.0.0.1#7913 -ipset=/.furhhdl.org/gfwlist -server=/.pearlher.org/127.0.0.1#7913 -ipset=/.pearlher.org/gfwlist -server=/.fofg-europe.net/127.0.0.1#7913 -ipset=/.fofg-europe.net/gfwlist -server=/.boxpn.com/127.0.0.1#7913 -ipset=/.boxpn.com/gfwlist -server=/.presentationzen.com/127.0.0.1#7913 -ipset=/.presentationzen.com/gfwlist -server=/.tensorflow.org/127.0.0.1#7913 -ipset=/.tensorflow.org/gfwlist -server=/.mpettis.com/127.0.0.1#7913 -ipset=/.mpettis.com/gfwlist -server=/.dtwang.org/127.0.0.1#7913 -ipset=/.dtwang.org/gfwlist -server=/.99btgc01.com/127.0.0.1#7913 -ipset=/.99btgc01.com/gfwlist -server=/.tubaholic.com/127.0.0.1#7913 -ipset=/.tubaholic.com/gfwlist -server=/.power.com/127.0.0.1#7913 -ipset=/.power.com/gfwlist -server=/.fan-qiang.com/127.0.0.1#7913 -ipset=/.fan-qiang.com/gfwlist -server=/.news.msn.com.tw/127.0.0.1#7913 -ipset=/.news.msn.com.tw/gfwlist -server=/.blacklogic.com/127.0.0.1#7913 -ipset=/.blacklogic.com/gfwlist -server=/.expatshield.com/127.0.0.1#7913 -ipset=/.expatshield.com/gfwlist -server=/.dok-forum.net/127.0.0.1#7913 -ipset=/.dok-forum.net/gfwlist -server=/.chinalawtranslate.com/127.0.0.1#7913 -ipset=/.chinalawtranslate.com/gfwlist -server=/.youmaker.com/127.0.0.1#7913 -ipset=/.youmaker.com/gfwlist -server=/.googleapis.com/127.0.0.1#7913 -ipset=/.googleapis.com/gfwlist -server=/.communistcrimes.org/127.0.0.1#7913 -ipset=/.communistcrimes.org/gfwlist -server=/.koornk.com/127.0.0.1#7913 -ipset=/.koornk.com/gfwlist -server=/.sogrady.me/127.0.0.1#7913 -ipset=/.sogrady.me/gfwlist -server=/.mydad.info/127.0.0.1#7913 -ipset=/.mydad.info/gfwlist -server=/.milsurps.com/127.0.0.1#7913 -ipset=/.milsurps.com/gfwlist -server=/.calebelston.com/127.0.0.1#7913 -ipset=/.calebelston.com/gfwlist -server=/.netme.cc/127.0.0.1#7913 -ipset=/.netme.cc/gfwlist -server=/.putty.org/127.0.0.1#7913 -ipset=/.putty.org/gfwlist -server=/.hkgalden.com/127.0.0.1#7913 -ipset=/.hkgalden.com/gfwlist -server=/.falunaz.net/127.0.0.1#7913 -ipset=/.falunaz.net/gfwlist -server=/.proxfree.com/127.0.0.1#7913 -ipset=/.proxfree.com/gfwlist -server=/.ktzhk.com/127.0.0.1#7913 -ipset=/.ktzhk.com/gfwlist -server=/.provpnaccounts.com/127.0.0.1#7913 -ipset=/.provpnaccounts.com/gfwlist -server=/.lotuslight.org.hk/127.0.0.1#7913 -ipset=/.lotuslight.org.hk/gfwlist -server=/.hkepc.com/127.0.0.1#7913 -ipset=/.hkepc.com/gfwlist -server=/.youtube-nocookie.com/127.0.0.1#7913 -ipset=/.youtube-nocookie.com/gfwlist -server=/.xrentdvd.com/127.0.0.1#7913 -ipset=/.xrentdvd.com/gfwlist -server=/.cari.com.my/127.0.0.1#7913 -ipset=/.cari.com.my/gfwlist -server=/.gluckman.com/127.0.0.1#7913 -ipset=/.gluckman.com/gfwlist -server=/.cdn.printfriendly.com/127.0.0.1#7913 -ipset=/.cdn.printfriendly.com/gfwlist -server=/.emule-ed2k.com/127.0.0.1#7913 -ipset=/.emule-ed2k.com/gfwlist -server=/.savetibet.ru/127.0.0.1#7913 -ipset=/.savetibet.ru/gfwlist -server=/.jinx.com/127.0.0.1#7913 -ipset=/.jinx.com/gfwlist -server=/.mindrolling.org/127.0.0.1#7913 -ipset=/.mindrolling.org/gfwlist -server=/.ccdtr.org/127.0.0.1#7913 -ipset=/.ccdtr.org/gfwlist -server=/.kwcg.ca/127.0.0.1#7913 -ipset=/.kwcg.ca/gfwlist -server=/.twitstat.com/127.0.0.1#7913 -ipset=/.twitstat.com/gfwlist -server=/.hidemyass.com/127.0.0.1#7913 -ipset=/.hidemyass.com/gfwlist -server=/.potvpn.com/127.0.0.1#7913 -ipset=/.potvpn.com/gfwlist -server=/.bloomberg.cn/127.0.0.1#7913 -ipset=/.bloomberg.cn/gfwlist -server=/.mofos.com/127.0.0.1#7913 -ipset=/.mofos.com/gfwlist -server=/.linglingfa.com/127.0.0.1#7913 -ipset=/.linglingfa.com/gfwlist -server=/.gzone-anime.info/127.0.0.1#7913 -ipset=/.gzone-anime.info/gfwlist -server=/.adultfriendfinder.com/127.0.0.1#7913 -ipset=/.adultfriendfinder.com/gfwlist -server=/.bit.ly/127.0.0.1#7913 -ipset=/.bit.ly/gfwlist -server=/.cn.uptodown.com/127.0.0.1#7913 -ipset=/.cn.uptodown.com/gfwlist -server=/.poskotanews.com/127.0.0.1#7913 -ipset=/.poskotanews.com/gfwlist -server=/.alternate-tools.com/127.0.0.1#7913 -ipset=/.alternate-tools.com/gfwlist -server=/.beaconevents.com/127.0.0.1#7913 -ipset=/.beaconevents.com/gfwlist -server=/.portablevpn.nl/127.0.0.1#7913 -ipset=/.portablevpn.nl/gfwlist -server=/.goldbetsports.com/127.0.0.1#7913 -ipset=/.goldbetsports.com/gfwlist -server=/.google.lv/127.0.0.1#7913 -ipset=/.google.lv/gfwlist -server=/.raggedbanner.com/127.0.0.1#7913 -ipset=/.raggedbanner.com/gfwlist -server=/.cams.com/127.0.0.1#7913 -ipset=/.cams.com/gfwlist -server=/.dyndns-pics.com/127.0.0.1#7913 -ipset=/.dyndns-pics.com/gfwlist -server=/.pornsocket.com/127.0.0.1#7913 -ipset=/.pornsocket.com/gfwlist -server=/.band.us/127.0.0.1#7913 -ipset=/.band.us/gfwlist -server=/.qiandao.today/127.0.0.1#7913 -ipset=/.qiandao.today/gfwlist -server=/.chinesegay.org/127.0.0.1#7913 -ipset=/.chinesegay.org/gfwlist -server=/.pornmm.net/127.0.0.1#7913 -ipset=/.pornmm.net/gfwlist -server=/.pornhubpremium.com/127.0.0.1#7913 -ipset=/.pornhubpremium.com/gfwlist -server=/.5278.cc/127.0.0.1#7913 -ipset=/.5278.cc/gfwlist -server=/.cmule.com/127.0.0.1#7913 -ipset=/.cmule.com/gfwlist -server=/.teddysun.com/127.0.0.1#7913 -ipset=/.teddysun.com/gfwlist -server=/.pornbase.org/127.0.0.1#7913 -ipset=/.pornbase.org/gfwlist -server=/.falun-ny.net/127.0.0.1#7913 -ipset=/.falun-ny.net/gfwlist -server=/.google.mn/127.0.0.1#7913 -ipset=/.google.mn/gfwlist -server=/.porn.com/127.0.0.1#7913 -ipset=/.porn.com/gfwlist -server=/.wikileaks-forum.com/127.0.0.1#7913 -ipset=/.wikileaks-forum.com/gfwlist -server=/.politicalchina.org/127.0.0.1#7913 -ipset=/.politicalchina.org/gfwlist -server=/.centurys.net/127.0.0.1#7913 -ipset=/.centurys.net/gfwlist -server=/.dtiblog.com/127.0.0.1#7913 -ipset=/.dtiblog.com/gfwlist -server=/.228.net.tw/127.0.0.1#7913 -ipset=/.228.net.tw/gfwlist -server=/.rsdlmonitor.com/127.0.0.1#7913 -ipset=/.rsdlmonitor.com/gfwlist -server=/.talkboxapp.com/127.0.0.1#7913 -ipset=/.talkboxapp.com/gfwlist -server=/.pokerstars.net/127.0.0.1#7913 -ipset=/.pokerstars.net/gfwlist -server=/.freenetproject.org/127.0.0.1#7913 -ipset=/.freenetproject.org/gfwlist -server=/.findyoutube.net/127.0.0.1#7913 -ipset=/.findyoutube.net/gfwlist -server=/.chinacomments.org/127.0.0.1#7913 -ipset=/.chinacomments.org/gfwlist -server=/.autodraw.com/127.0.0.1#7913 -ipset=/.autodraw.com/gfwlist -server=/.www.zensur.freerk.com/127.0.0.1#7913 -ipset=/.www.zensur.freerk.com/gfwlist -server=/.google.tk/127.0.0.1#7913 -ipset=/.google.tk/gfwlist -server=/.chromium.org/127.0.0.1#7913 -ipset=/.chromium.org/gfwlist -server=/.stoweboyd.com/127.0.0.1#7913 -ipset=/.stoweboyd.com/gfwlist -server=/.123rf.com/127.0.0.1#7913 -ipset=/.123rf.com/gfwlist -server=/.acevpn.com/127.0.0.1#7913 -ipset=/.acevpn.com/gfwlist -server=/.hrcchina.org/127.0.0.1#7913 -ipset=/.hrcchina.org/gfwlist -server=/.weiboscope.jmsc.hku.hk/127.0.0.1#7913 -ipset=/.weiboscope.jmsc.hku.hk/gfwlist -server=/.qgirl.com.tw/127.0.0.1#7913 -ipset=/.qgirl.com.tw/gfwlist -server=/.plurk.com/127.0.0.1#7913 -ipset=/.plurk.com/gfwlist -server=/.plunder.com/127.0.0.1#7913 -ipset=/.plunder.com/gfwlist -server=/.plays.com.tw/127.0.0.1#7913 -ipset=/.plays.com.tw/gfwlist -server=/.bmfinn.com/127.0.0.1#7913 -ipset=/.bmfinn.com/gfwlist -server=/.playno1.com/127.0.0.1#7913 -ipset=/.playno1.com/gfwlist -server=/.luxebc.com/127.0.0.1#7913 -ipset=/.luxebc.com/gfwlist -server=/.edubridge.com/127.0.0.1#7913 -ipset=/.edubridge.com/gfwlist -server=/.bbchat.tv/127.0.0.1#7913 -ipset=/.bbchat.tv/gfwlist -server=/.chinaway.org/127.0.0.1#7913 -ipset=/.chinaway.org/gfwlist -server=/.curvefish.com/127.0.0.1#7913 -ipset=/.curvefish.com/gfwlist -server=/.xuehua.us/127.0.0.1#7913 -ipset=/.xuehua.us/gfwlist -server=/.css.pixnet.in/127.0.0.1#7913 -ipset=/.css.pixnet.in/gfwlist -server=/.piring.com/127.0.0.1#7913 -ipset=/.piring.com/gfwlist -server=/.maniash.com/127.0.0.1#7913 -ipset=/.maniash.com/gfwlist -server=/.askstudent.com/127.0.0.1#7913 -ipset=/.askstudent.com/gfwlist -server=/.chinasmile.net/127.0.0.1#7913 -ipset=/.chinasmile.net/gfwlist -server=/.pinterest.de/127.0.0.1#7913 -ipset=/.pinterest.de/gfwlist -server=/.2lipstube.com/127.0.0.1#7913 -ipset=/.2lipstube.com/gfwlist -server=/.proxomitron.info/127.0.0.1#7913 -ipset=/.proxomitron.info/gfwlist -server=/.pinterest.co.kr/127.0.0.1#7913 -ipset=/.pinterest.co.kr/gfwlist -server=/.moonbbs.com/127.0.0.1#7913 -ipset=/.moonbbs.com/gfwlist -server=/.pinimg.com/127.0.0.1#7913 -ipset=/.pinimg.com/gfwlist -server=/.ping.fm/127.0.0.1#7913 -ipset=/.ping.fm/gfwlist -server=/.pin6.com/127.0.0.1#7913 -ipset=/.pin6.com/gfwlist -server=/.tuidang.se/127.0.0.1#7913 -ipset=/.tuidang.se/gfwlist -server=/.ddns.me.uk/127.0.0.1#7913 -ipset=/.ddns.me.uk/gfwlist -server=/.friendfeed.com/127.0.0.1#7913 -ipset=/.friendfeed.com/gfwlist -server=/.picidae.net/127.0.0.1#7913 -ipset=/.picidae.net/gfwlist -server=/.google.dk/127.0.0.1#7913 -ipset=/.google.dk/gfwlist -server=/.32red.com/127.0.0.1#7913 -ipset=/.32red.com/gfwlist -server=/.vultryhw.com/127.0.0.1#7913 -ipset=/.vultryhw.com/gfwlist -server=/.avaaz.org/127.0.0.1#7913 -ipset=/.avaaz.org/gfwlist -server=/.cdn.ampproject.org/127.0.0.1#7913 -ipset=/.cdn.ampproject.org/gfwlist -server=/.phmsociety.org/127.0.0.1#7913 -ipset=/.phmsociety.org/gfwlist -server=/.bitcoinworld.com/127.0.0.1#7913 -ipset=/.bitcoinworld.com/gfwlist -server=/.pfd.org.hk/127.0.0.1#7913 -ipset=/.pfd.org.hk/gfwlist -server=/.rfa.org/127.0.0.1#7913 -ipset=/.rfa.org/gfwlist -server=/.twitzap.com/127.0.0.1#7913 -ipset=/.twitzap.com/gfwlist -server=/.amnesty.org.hk/127.0.0.1#7913 -ipset=/.amnesty.org.hk/gfwlist -server=/.8-d.com/127.0.0.1#7913 -ipset=/.8-d.com/gfwlist -server=/.mixpod.com/127.0.0.1#7913 -ipset=/.mixpod.com/gfwlist -server=/.perfectvpn.net/127.0.0.1#7913 -ipset=/.perfectvpn.net/gfwlist -server=/.mingpaomonthly.com/127.0.0.1#7913 -ipset=/.mingpaomonthly.com/gfwlist -server=/.percy.in/127.0.0.1#7913 -ipset=/.percy.in/gfwlist -server=/.gdzf.org/127.0.0.1#7913 -ipset=/.gdzf.org/gfwlist -server=/.jingpin.org/127.0.0.1#7913 -ipset=/.jingpin.org/gfwlist -server=/.peoplenews.tw/127.0.0.1#7913 -ipset=/.peoplenews.tw/gfwlist -server=/.beevpn.com/127.0.0.1#7913 -ipset=/.beevpn.com/gfwlist -server=/.ggpht.com/127.0.0.1#7913 -ipset=/.ggpht.com/gfwlist -server=/.1688.com.au/127.0.0.1#7913 -ipset=/.1688.com.au/gfwlist -server=/.hrichina.org/127.0.0.1#7913 -ipset=/.hrichina.org/gfwlist -server=/.e123.hk/127.0.0.1#7913 -ipset=/.e123.hk/gfwlist -server=/.newtaiwan.com.tw/127.0.0.1#7913 -ipset=/.newtaiwan.com.tw/gfwlist -server=/.flickrhivemind.net/127.0.0.1#7913 -ipset=/.flickrhivemind.net/gfwlist -server=/.phuquocservices.com/127.0.0.1#7913 -ipset=/.phuquocservices.com/gfwlist -server=/.dolf.org.hk/127.0.0.1#7913 -ipset=/.dolf.org.hk/gfwlist -server=/.aobo.com.au/127.0.0.1#7913 -ipset=/.aobo.com.au/gfwlist -server=/.penthouse.com/127.0.0.1#7913 -ipset=/.penthouse.com/gfwlist -server=/.footwiball.com/127.0.0.1#7913 -ipset=/.footwiball.com/gfwlist -server=/.laomiu.com/127.0.0.1#7913 -ipset=/.laomiu.com/gfwlist -server=/.blog.pentalogic.net/127.0.0.1#7913 -ipset=/.blog.pentalogic.net/gfwlist -server=/.hentaivideoworld.com/127.0.0.1#7913 -ipset=/.hentaivideoworld.com/gfwlist -server=/.deezer.com/127.0.0.1#7913 -ipset=/.deezer.com/gfwlist -server=/.pemulihan.or.id/127.0.0.1#7913 -ipset=/.pemulihan.or.id/gfwlist -server=/.bailandaily.com/127.0.0.1#7913 -ipset=/.bailandaily.com/gfwlist -server=/.bitc.bme.emory.edu/127.0.0.1#7913 -ipset=/.bitc.bme.emory.edu/gfwlist -server=/.ntd.tv/127.0.0.1#7913 -ipset=/.ntd.tv/gfwlist -server=/.fanqiangzhe.com/127.0.0.1#7913 -ipset=/.fanqiangzhe.com/gfwlist -server=/.whatbrowser.org/127.0.0.1#7913 -ipset=/.whatbrowser.org/gfwlist -server=/.flagsonline.it/127.0.0.1#7913 -ipset=/.flagsonline.it/gfwlist -server=/.rolia.net/127.0.0.1#7913 -ipset=/.rolia.net/gfwlist -server=/.peeasian.com/127.0.0.1#7913 -ipset=/.peeasian.com/gfwlist -server=/.whitebear.freebearblog.org/127.0.0.1#7913 -ipset=/.whitebear.freebearblog.org/gfwlist -server=/.dalailamahindi.com/127.0.0.1#7913 -ipset=/.dalailamahindi.com/gfwlist -server=/.great-firewall.com/127.0.0.1#7913 -ipset=/.great-firewall.com/gfwlist -server=/.25u.com/127.0.0.1#7913 -ipset=/.25u.com/gfwlist -server=/.erodoujinworld.com/127.0.0.1#7913 -ipset=/.erodoujinworld.com/gfwlist -server=/.getcloak.com/127.0.0.1#7913 -ipset=/.getcloak.com/gfwlist -server=/.wzyboy.im/127.0.0.1#7913 -ipset=/.wzyboy.im/gfwlist -server=/.85cc.net/127.0.0.1#7913 -ipset=/.85cc.net/gfwlist -server=/.letou.com/127.0.0.1#7913 -ipset=/.letou.com/gfwlist -server=/.duckmylife.com/127.0.0.1#7913 -ipset=/.duckmylife.com/gfwlist -server=/.chuang-yen.org/127.0.0.1#7913 -ipset=/.chuang-yen.org/gfwlist -server=/.peace.ca/127.0.0.1#7913 -ipset=/.peace.ca/gfwlist -server=/.cnpolitics.org/127.0.0.1#7913 -ipset=/.cnpolitics.org/gfwlist -server=/.chromestatus.com/127.0.0.1#7913 -ipset=/.chromestatus.com/gfwlist -server=/.pdproxy.com/127.0.0.1#7913 -ipset=/.pdproxy.com/gfwlist -server=/.goodtv.tv/127.0.0.1#7913 -ipset=/.goodtv.tv/gfwlist -server=/.bignews.org/127.0.0.1#7913 -ipset=/.bignews.org/gfwlist -server=/.liberal.org.hk/127.0.0.1#7913 -ipset=/.liberal.org.hk/gfwlist -server=/.news.hkpeanut.com/127.0.0.1#7913 -ipset=/.news.hkpeanut.com/gfwlist -server=/.ss.carryzhou.com/127.0.0.1#7913 -ipset=/.ss.carryzhou.com/gfwlist -server=/.metarthunter.com/127.0.0.1#7913 -ipset=/.metarthunter.com/gfwlist -server=/.pbxes.org/127.0.0.1#7913 -ipset=/.pbxes.org/gfwlist -server=/.pbxes.com/127.0.0.1#7913 -ipset=/.pbxes.com/gfwlist -server=/.dreamamateurs.com/127.0.0.1#7913 -ipset=/.dreamamateurs.com/gfwlist -server=/.justmysocks1.net/127.0.0.1#7913 -ipset=/.justmysocks1.net/gfwlist -server=/.nexttv.com.tw/127.0.0.1#7913 -ipset=/.nexttv.com.tw/gfwlist -server=/.epac.to/127.0.0.1#7913 -ipset=/.epac.to/gfwlist -server=/.mp3buscador.com/127.0.0.1#7913 -ipset=/.mp3buscador.com/gfwlist -server=/.kepard.com/127.0.0.1#7913 -ipset=/.kepard.com/gfwlist -server=/.nalandabodhi.org/127.0.0.1#7913 -ipset=/.nalandabodhi.org/gfwlist -server=/.dnssec.net/127.0.0.1#7913 -ipset=/.dnssec.net/gfwlist -server=/.bwh1.net/127.0.0.1#7913 -ipset=/.bwh1.net/gfwlist -server=/.icu-project.org/127.0.0.1#7913 -ipset=/.icu-project.org/gfwlist -server=/.d100.net/127.0.0.1#7913 -ipset=/.d100.net/gfwlist -server=/.thecenter.mit.edu/127.0.0.1#7913 -ipset=/.thecenter.mit.edu/gfwlist -server=/.3-a.net/127.0.0.1#7913 -ipset=/.3-a.net/gfwlist -server=/.pbs.org/127.0.0.1#7913 -ipset=/.pbs.org/gfwlist -server=/.pastie.org/127.0.0.1#7913 -ipset=/.pastie.org/gfwlist -server=/.mingpaotor.com/127.0.0.1#7913 -ipset=/.mingpaotor.com/gfwlist -server=/.haproxy.org/127.0.0.1#7913 -ipset=/.haproxy.org/gfwlist -server=/.mponline.hk/127.0.0.1#7913 -ipset=/.mponline.hk/gfwlist -server=/.passiontimes.hk/127.0.0.1#7913 -ipset=/.passiontimes.hk/gfwlist -server=/.newsdh.com/127.0.0.1#7913 -ipset=/.newsdh.com/gfwlist -server=/.dynawebinc.com/127.0.0.1#7913 -ipset=/.dynawebinc.com/gfwlist -server=/.3arabtv.com/127.0.0.1#7913 -ipset=/.3arabtv.com/gfwlist -server=/.xbookcn.com/127.0.0.1#7913 -ipset=/.xbookcn.com/gfwlist -server=/.partypoker.com/127.0.0.1#7913 -ipset=/.partypoker.com/gfwlist -server=/.fling.com/127.0.0.1#7913 -ipset=/.fling.com/gfwlist -server=/.civilhrfront.org/127.0.0.1#7913 -ipset=/.civilhrfront.org/gfwlist -server=/.2waky.com/127.0.0.1#7913 -ipset=/.2waky.com/gfwlist -server=/.meyou.jp/127.0.0.1#7913 -ipset=/.meyou.jp/gfwlist -server=/.etools.ncol.com/127.0.0.1#7913 -ipset=/.etools.ncol.com/gfwlist -server=/.solarsystem.nasa.gov/127.0.0.1#7913 -ipset=/.solarsystem.nasa.gov/gfwlist -server=/.pacopacomama.com/127.0.0.1#7913 -ipset=/.pacopacomama.com/gfwlist -server=/.packetix.net/127.0.0.1#7913 -ipset=/.packetix.net/gfwlist -server=/.ozyoyo.com/127.0.0.1#7913 -ipset=/.ozyoyo.com/gfwlist -server=/.my.opera.com/127.0.0.1#7913 -ipset=/.my.opera.com/gfwlist -server=/.ozvoice.org/127.0.0.1#7913 -ipset=/.ozvoice.org/gfwlist -server=/.cdpweb.org/127.0.0.1#7913 -ipset=/.cdpweb.org/gfwlist -server=/.ow.ly/127.0.0.1#7913 -ipset=/.ow.ly/gfwlist -server=/.urbandictionary.com/127.0.0.1#7913 -ipset=/.urbandictionary.com/gfwlist -server=/.freemuse.org/127.0.0.1#7913 -ipset=/.freemuse.org/gfwlist -server=/.commentshk.com/127.0.0.1#7913 -ipset=/.commentshk.com/gfwlist -server=/.waselpro.com/127.0.0.1#7913 -ipset=/.waselpro.com/gfwlist -server=/.minzhuhua.net/127.0.0.1#7913 -ipset=/.minzhuhua.net/gfwlist -server=/.catholic.org.hk/127.0.0.1#7913 -ipset=/.catholic.org.hk/gfwlist -server=/.htl.li/127.0.0.1#7913 -ipset=/.htl.li/gfwlist -server=/.gamousa.com/127.0.0.1#7913 -ipset=/.gamousa.com/gfwlist -server=/.ht.ly/127.0.0.1#7913 -ipset=/.ht.ly/gfwlist -server=/.spaces.hightail.com/127.0.0.1#7913 -ipset=/.spaces.hightail.com/gfwlist -server=/.grandtrial.org/127.0.0.1#7913 -ipset=/.grandtrial.org/gfwlist -server=/.xfinity.com/127.0.0.1#7913 -ipset=/.xfinity.com/gfwlist -server=/.fb.me/127.0.0.1#7913 -ipset=/.fb.me/gfwlist -server=/.tibettelegraph.com/127.0.0.1#7913 -ipset=/.tibettelegraph.com/gfwlist -server=/.citizenscommission.hk/127.0.0.1#7913 -ipset=/.citizenscommission.hk/gfwlist -server=/.rfalive1.akacast.akamaistream.net/127.0.0.1#7913 -ipset=/.rfalive1.akacast.akamaistream.net/gfwlist -server=/.googlezip.net/127.0.0.1#7913 -ipset=/.googlezip.net/gfwlist -server=/.oursweb.net/127.0.0.1#7913 -ipset=/.oursweb.net/gfwlist -server=/.oursteps.com.au/127.0.0.1#7913 -ipset=/.oursteps.com.au/gfwlist -server=/.taiwan-sex.com/127.0.0.1#7913 -ipset=/.taiwan-sex.com/gfwlist -server=/.otnd.org/127.0.0.1#7913 -ipset=/.otnd.org/gfwlist -server=/.lbank.info/127.0.0.1#7913 -ipset=/.lbank.info/gfwlist -server=/.google.fi/127.0.0.1#7913 -ipset=/.google.fi/gfwlist -server=/.bcc.com.tw/127.0.0.1#7913 -ipset=/.bcc.com.tw/gfwlist -server=/.osfoora.com/127.0.0.1#7913 -ipset=/.osfoora.com/gfwlist -server=/.4chan.com/127.0.0.1#7913 -ipset=/.4chan.com/gfwlist -server=/.coursehero.com/127.0.0.1#7913 -ipset=/.coursehero.com/gfwlist -server=/.pobieramy.top/127.0.0.1#7913 -ipset=/.pobieramy.top/gfwlist -server=/.tui.orzdream.com/127.0.0.1#7913 -ipset=/.tui.orzdream.com/gfwlist -server=/.helloss.pw/127.0.0.1#7913 -ipset=/.helloss.pw/gfwlist -server=/.t.orzdream.com/127.0.0.1#7913 -ipset=/.t.orzdream.com/gfwlist -server=/.novelasia.com/127.0.0.1#7913 -ipset=/.novelasia.com/gfwlist -server=/.darktoy.net/127.0.0.1#7913 -ipset=/.darktoy.net/gfwlist -server=/.btctrade.im/127.0.0.1#7913 -ipset=/.btctrade.im/gfwlist -server=/.dcmilitary.com/127.0.0.1#7913 -ipset=/.dcmilitary.com/gfwlist -server=/.rapidgator.net/127.0.0.1#7913 -ipset=/.rapidgator.net/gfwlist -server=/.tmdfish.com/127.0.0.1#7913 -ipset=/.tmdfish.com/gfwlist -server=/.orgfree.com/127.0.0.1#7913 -ipset=/.orgfree.com/gfwlist -server=/.orgasm.com/127.0.0.1#7913 -ipset=/.orgasm.com/gfwlist -server=/.organcare.org.tw/127.0.0.1#7913 -ipset=/.organcare.org.tw/gfwlist -server=/.bebo.com/127.0.0.1#7913 -ipset=/.bebo.com/gfwlist -server=/.www.orchidbbs.com/127.0.0.1#7913 -ipset=/.www.orchidbbs.com/gfwlist -server=/.iu45.com/127.0.0.1#7913 -ipset=/.iu45.com/gfwlist -server=/.openwebster.com/127.0.0.1#7913 -ipset=/.openwebster.com/gfwlist -server=/.hkvwet.com/127.0.0.1#7913 -ipset=/.hkvwet.com/gfwlist -server=/.12bet.com/127.0.0.1#7913 -ipset=/.12bet.com/gfwlist -server=/.cna.com.tw/127.0.0.1#7913 -ipset=/.cna.com.tw/gfwlist -server=/.epochtimes.co.il/127.0.0.1#7913 -ipset=/.epochtimes.co.il/gfwlist -server=/.nic.google/127.0.0.1#7913 -ipset=/.nic.google/gfwlist -server=/.hk.video.news.yahoo.com/127.0.0.1#7913 -ipset=/.hk.video.news.yahoo.com/gfwlist -server=/.chushigangdrug.ch/127.0.0.1#7913 -ipset=/.chushigangdrug.ch/gfwlist -server=/.opendemocracy.net/127.0.0.1#7913 -ipset=/.opendemocracy.net/gfwlist -server=/.yes-news.com/127.0.0.1#7913 -ipset=/.yes-news.com/gfwlist -server=/.dalailama.mn/127.0.0.1#7913 -ipset=/.dalailama.mn/gfwlist -server=/.hkcoc.weather.com.hk/127.0.0.1#7913 -ipset=/.hkcoc.weather.com.hk/gfwlist -server=/.wuguoguang.com/127.0.0.1#7913 -ipset=/.wuguoguang.com/gfwlist -server=/.nytimes.com/127.0.0.1#7913 -ipset=/.nytimes.com/gfwlist -server=/.myforum.com.uk/127.0.0.1#7913 -ipset=/.myforum.com.uk/gfwlist -server=/.eslite.com/127.0.0.1#7913 -ipset=/.eslite.com/gfwlist -server=/.grow.google/127.0.0.1#7913 -ipset=/.grow.google/gfwlist -server=/.drtuber.com/127.0.0.1#7913 -ipset=/.drtuber.com/gfwlist -server=/.epochtimes.jp/127.0.0.1#7913 -ipset=/.epochtimes.jp/gfwlist -server=/.tellme.pw/127.0.0.1#7913 -ipset=/.tellme.pw/gfwlist -server=/.khabdha.org/127.0.0.1#7913 -ipset=/.khabdha.org/gfwlist -server=/.bjzc.org/127.0.0.1#7913 -ipset=/.bjzc.org/gfwlist -server=/.jubushoushen.com/127.0.0.1#7913 -ipset=/.jubushoushen.com/gfwlist -server=/.onlinecha.com/127.0.0.1#7913 -ipset=/.onlinecha.com/gfwlist -server=/.hkdailynews.com.hk/127.0.0.1#7913 -ipset=/.hkdailynews.com.hk/gfwlist -server=/.hk.jiepang.com/127.0.0.1#7913 -ipset=/.hk.jiepang.com/gfwlist -server=/.881903.com/127.0.0.1#7913 -ipset=/.881903.com/gfwlist -server=/.softether.org/127.0.0.1#7913 -ipset=/.softether.org/gfwlist -server=/.forum.omy.sg/127.0.0.1#7913 -ipset=/.forum.omy.sg/gfwlist -server=/.gotdns.ch/127.0.0.1#7913 -ipset=/.gotdns.ch/gfwlist -server=/.omnitalk.org/127.0.0.1#7913 -ipset=/.omnitalk.org/gfwlist -server=/.cdpusa.org/127.0.0.1#7913 -ipset=/.cdpusa.org/gfwlist -server=/.olumpo.com/127.0.0.1#7913 -ipset=/.olumpo.com/gfwlist -server=/.arte.tv/127.0.0.1#7913 -ipset=/.arte.tv/gfwlist -server=/.civicparty.hk/127.0.0.1#7913 -ipset=/.civicparty.hk/gfwlist -server=/.fileflyer.com/127.0.0.1#7913 -ipset=/.fileflyer.com/gfwlist -server=/.rcam.target.com/127.0.0.1#7913 -ipset=/.rcam.target.com/gfwlist -server=/.nflximg.com/127.0.0.1#7913 -ipset=/.nflximg.com/gfwlist -server=/.oikos.com.tw/127.0.0.1#7913 -ipset=/.oikos.com.tw/gfwlist -server=/.ogate.org/127.0.0.1#7913 -ipset=/.ogate.org/gfwlist -server=/.ogaoga.org/127.0.0.1#7913 -ipset=/.ogaoga.org/gfwlist -server=/.tumview.com/127.0.0.1#7913 -ipset=/.tumview.com/gfwlist -server=/.offbeatchina.com/127.0.0.1#7913 -ipset=/.offbeatchina.com/gfwlist -server=/.lighten.org.tw/127.0.0.1#7913 -ipset=/.lighten.org.tw/gfwlist -server=/.javmoo.xyz/127.0.0.1#7913 -ipset=/.javmoo.xyz/gfwlist -server=/.mypop3.net/127.0.0.1#7913 -ipset=/.mypop3.net/gfwlist -server=/.tw.money.yahoo.com/127.0.0.1#7913 -ipset=/.tw.money.yahoo.com/gfwlist -server=/.hkusu.net/127.0.0.1#7913 -ipset=/.hkusu.net/gfwlist -server=/.ocaspro.com/127.0.0.1#7913 -ipset=/.ocaspro.com/gfwlist -server=/.badoo.com/127.0.0.1#7913 -ipset=/.badoo.com/gfwlist -server=/.potato.im/127.0.0.1#7913 -ipset=/.potato.im/gfwlist -server=/.bannedbook.org/127.0.0.1#7913 -ipset=/.bannedbook.org/gfwlist -server=/.huobipro.com/127.0.0.1#7913 -ipset=/.huobipro.com/gfwlist -server=/.codeshare.io/127.0.0.1#7913 -ipset=/.codeshare.io/gfwlist -server=/.androidify.com/127.0.0.1#7913 -ipset=/.androidify.com/gfwlist -server=/.fanqiang.tk/127.0.0.1#7913 -ipset=/.fanqiang.tk/gfwlist -server=/.observechina.net/127.0.0.1#7913 -ipset=/.observechina.net/gfwlist -server=/.nylonstockingsonline.com/127.0.0.1#7913 -ipset=/.nylonstockingsonline.com/gfwlist -server=/.login.target.com/127.0.0.1#7913 -ipset=/.login.target.com/gfwlist -server=/.appsto.re/127.0.0.1#7913 -ipset=/.appsto.re/gfwlist -server=/.lesoir.be/127.0.0.1#7913 -ipset=/.lesoir.be/gfwlist -server=/.bartvpn.com/127.0.0.1#7913 -ipset=/.bartvpn.com/gfwlist -server=/.hket.com/127.0.0.1#7913 -ipset=/.hket.com/gfwlist -server=/.avyahoo.com/127.0.0.1#7913 -ipset=/.avyahoo.com/gfwlist -server=/.babynet.com.hk/127.0.0.1#7913 -ipset=/.babynet.com.hk/gfwlist -server=/.rfi.fr/127.0.0.1#7913 -ipset=/.rfi.fr/gfwlist -server=/.widevine.com/127.0.0.1#7913 -ipset=/.widevine.com/gfwlist -server=/.china101.com/127.0.0.1#7913 -ipset=/.china101.com/gfwlist -server=/.bithumb.com/127.0.0.1#7913 -ipset=/.bithumb.com/gfwlist -server=/.rocksdb.org/127.0.0.1#7913 -ipset=/.rocksdb.org/gfwlist -server=/.airasia.com/127.0.0.1#7913 -ipset=/.airasia.com/gfwlist -server=/.liuhanyu.com/127.0.0.1#7913 -ipset=/.liuhanyu.com/gfwlist -server=/.asiaharvest.org/127.0.0.1#7913 -ipset=/.asiaharvest.org/gfwlist -server=/.nyaa.eu/127.0.0.1#7913 -ipset=/.nyaa.eu/gfwlist -server=/.akamaihd.net/127.0.0.1#7913 -ipset=/.akamaihd.net/gfwlist -server=/.surfeasy.com.au/127.0.0.1#7913 -ipset=/.surfeasy.com.au/gfwlist -server=/.bitfinex.com/127.0.0.1#7913 -ipset=/.bitfinex.com/gfwlist -server=/.torvpn.com/127.0.0.1#7913 -ipset=/.torvpn.com/gfwlist -server=/.nvdst.com/127.0.0.1#7913 -ipset=/.nvdst.com/gfwlist -server=/.nuvid.com/127.0.0.1#7913 -ipset=/.nuvid.com/gfwlist -server=/.nurgo-software.com/127.0.0.1#7913 -ipset=/.nurgo-software.com/gfwlist -server=/.ddc.com.tw/127.0.0.1#7913 -ipset=/.ddc.com.tw/gfwlist -server=/.gcr.io/127.0.0.1#7913 -ipset=/.gcr.io/gfwlist -server=/.blogger.com/127.0.0.1#7913 -ipset=/.blogger.com/gfwlist -server=/.cbs.ntu.edu.tw/127.0.0.1#7913 -ipset=/.cbs.ntu.edu.tw/gfwlist -server=/.debug.com/127.0.0.1#7913 -ipset=/.debug.com/gfwlist -server=/.ntdtvla.com/127.0.0.1#7913 -ipset=/.ntdtvla.com/gfwlist -server=/.sharpdaily.hk/127.0.0.1#7913 -ipset=/.sharpdaily.hk/gfwlist -server=/.caochangqing.com/127.0.0.1#7913 -ipset=/.caochangqing.com/gfwlist -server=/.18onlygirls.com/127.0.0.1#7913 -ipset=/.18onlygirls.com/gfwlist -server=/.changeip.org/127.0.0.1#7913 -ipset=/.changeip.org/gfwlist -server=/.pussyspace.com/127.0.0.1#7913 -ipset=/.pussyspace.com/gfwlist -server=/.ntdtv.co.kr/127.0.0.1#7913 -ipset=/.ntdtv.co.kr/gfwlist -server=/.kinmen.org.tw/127.0.0.1#7913 -ipset=/.kinmen.org.tw/gfwlist -server=/.thlib.org/127.0.0.1#7913 -ipset=/.thlib.org/gfwlist -server=/.cdjp.org/127.0.0.1#7913 -ipset=/.cdjp.org/gfwlist -server=/.androidtv.com/127.0.0.1#7913 -ipset=/.androidtv.com/gfwlist -server=/.athenaeizou.com/127.0.0.1#7913 -ipset=/.athenaeizou.com/gfwlist -server=/.paradisehill.cc/127.0.0.1#7913 -ipset=/.paradisehill.cc/gfwlist -server=/.nps.gov/127.0.0.1#7913 -ipset=/.nps.gov/gfwlist -server=/.cloud.mail.ru/127.0.0.1#7913 -ipset=/.cloud.mail.ru/gfwlist -server=/.noypf.com/127.0.0.1#7913 -ipset=/.noypf.com/gfwlist -server=/.news.now.com/127.0.0.1#7913 -ipset=/.news.now.com/gfwlist -server=/.kagyuoffice.org/127.0.0.1#7913 -ipset=/.kagyuoffice.org/gfwlist -server=/.adultkeep.net/127.0.0.1#7913 -ipset=/.adultkeep.net/gfwlist -server=/.hornygamer.com/127.0.0.1#7913 -ipset=/.hornygamer.com/gfwlist -server=/.nga.mil/127.0.0.1#7913 -ipset=/.nga.mil/gfwlist -server=/.archive.today/127.0.0.1#7913 -ipset=/.archive.today/gfwlist -server=/.joyourself.com/127.0.0.1#7913 -ipset=/.joyourself.com/gfwlist -server=/.proxynetwork.org.uk/127.0.0.1#7913 -ipset=/.proxynetwork.org.uk/gfwlist -server=/.mp3ye.eu/127.0.0.1#7913 -ipset=/.mp3ye.eu/gfwlist -server=/.coinegg.com/127.0.0.1#7913 -ipset=/.coinegg.com/gfwlist -server=/.bb-chat.tv/127.0.0.1#7913 -ipset=/.bb-chat.tv/gfwlist -server=/.servehttp.com/127.0.0.1#7913 -ipset=/.servehttp.com/gfwlist -server=/.search.yahoo.com/127.0.0.1#7913 -ipset=/.search.yahoo.com/gfwlist -server=/.taiwankiss.com/127.0.0.1#7913 -ipset=/.taiwankiss.com/gfwlist -server=/.173ng.com/127.0.0.1#7913 -ipset=/.173ng.com/gfwlist -server=/.tor.updatestar.com/127.0.0.1#7913 -ipset=/.tor.updatestar.com/gfwlist -server=/.yeahteentube.com/127.0.0.1#7913 -ipset=/.yeahteentube.com/gfwlist -server=/.taiwanyes.ning.com/127.0.0.1#7913 -ipset=/.taiwanyes.ning.com/gfwlist -server=/.nintendium.com/127.0.0.1#7913 -ipset=/.nintendium.com/gfwlist -server=/.aceros-de-hispania.com/127.0.0.1#7913 -ipset=/.aceros-de-hispania.com/gfwlist -server=/.secretgarden.no/127.0.0.1#7913 -ipset=/.secretgarden.no/gfwlist -server=/.adelaidebbs.com/127.0.0.1#7913 -ipset=/.adelaidebbs.com/gfwlist -server=/.daozhongxing.org/127.0.0.1#7913 -ipset=/.daozhongxing.org/gfwlist -server=/.av.nightlife141.com/127.0.0.1#7913 -ipset=/.av.nightlife141.com/gfwlist -server=/.harunyahya.com/127.0.0.1#7913 -ipset=/.harunyahya.com/gfwlist -server=/.nhentai.net/127.0.0.1#7913 -ipset=/.nhentai.net/gfwlist -server=/.chinapress.com.my/127.0.0.1#7913 -ipset=/.chinapress.com.my/gfwlist -server=/.ngensis.com/127.0.0.1#7913 -ipset=/.ngensis.com/gfwlist -server=/.twister.net.co/127.0.0.1#7913 -ipset=/.twister.net.co/gfwlist -server=/.hudson.org/127.0.0.1#7913 -ipset=/.hudson.org/gfwlist -server=/.co.ng.mil/127.0.0.1#7913 -ipset=/.co.ng.mil/gfwlist -server=/.apkplz.com/127.0.0.1#7913 -ipset=/.apkplz.com/gfwlist -server=/.aboluowang.com/127.0.0.1#7913 -ipset=/.aboluowang.com/gfwlist -server=/.888poker.com/127.0.0.1#7913 -ipset=/.888poker.com/gfwlist -server=/.google.tm/127.0.0.1#7913 -ipset=/.google.tm/gfwlist -server=/.jingsim.org/127.0.0.1#7913 -ipset=/.jingsim.org/gfwlist -server=/.braumeister.org/127.0.0.1#7913 -ipset=/.braumeister.org/gfwlist -server=/.huaxin.ph/127.0.0.1#7913 -ipset=/.huaxin.ph/gfwlist -server=/.4irc.com/127.0.0.1#7913 -ipset=/.4irc.com/gfwlist -server=/.nextmag.com.tw/127.0.0.1#7913 -ipset=/.nextmag.com.tw/gfwlist -server=/.tweetcs.com/127.0.0.1#7913 -ipset=/.tweetcs.com/gfwlist -server=/.decodet.co/127.0.0.1#7913 -ipset=/.decodet.co/gfwlist -server=/.zillionk.com/127.0.0.1#7913 -ipset=/.zillionk.com/gfwlist -server=/.pinkrod.com/127.0.0.1#7913 -ipset=/.pinkrod.com/gfwlist -server=/.mgstage.com/127.0.0.1#7913 -ipset=/.mgstage.com/gfwlist -server=/.istars.co.nz/127.0.0.1#7913 -ipset=/.istars.co.nz/gfwlist -server=/.dpp.org.tw/127.0.0.1#7913 -ipset=/.dpp.org.tw/gfwlist -server=/.yangjianli.com/127.0.0.1#7913 -ipset=/.yangjianli.com/gfwlist -server=/.vpnbook.com/127.0.0.1#7913 -ipset=/.vpnbook.com/gfwlist -server=/.newstarnet.com/127.0.0.1#7913 -ipset=/.newstarnet.com/gfwlist -server=/.br.st/127.0.0.1#7913 -ipset=/.br.st/gfwlist -server=/.freechinaforum.org/127.0.0.1#7913 -ipset=/.freechinaforum.org/gfwlist -server=/.newstapa.org/127.0.0.1#7913 -ipset=/.newstapa.org/gfwlist -server=/.comparitech.com/127.0.0.1#7913 -ipset=/.comparitech.com/gfwlist -server=/.tibetanaidproject.org/127.0.0.1#7913 -ipset=/.tibetanaidproject.org/gfwlist -server=/.mefound.com/127.0.0.1#7913 -ipset=/.mefound.com/gfwlist -server=/.blog.excite.co.jp/127.0.0.1#7913 -ipset=/.blog.excite.co.jp/gfwlist -server=/.newnews.ca/127.0.0.1#7913 -ipset=/.newnews.ca/gfwlist -server=/.americanunfinished.com/127.0.0.1#7913 -ipset=/.americanunfinished.com/gfwlist -server=/.lockestek.com/127.0.0.1#7913 -ipset=/.lockestek.com/gfwlist -server=/.new-akiba.com/127.0.0.1#7913 -ipset=/.new-akiba.com/gfwlist -server=/.mo.nightlife141.com/127.0.0.1#7913 -ipset=/.mo.nightlife141.com/gfwlist -server=/.muchosucko.com/127.0.0.1#7913 -ipset=/.muchosucko.com/gfwlist -server=/.edns.biz/127.0.0.1#7913 -ipset=/.edns.biz/gfwlist -server=/.minghui.or.kr/127.0.0.1#7913 -ipset=/.minghui.or.kr/gfwlist -server=/.crwdcntrl.net/127.0.0.1#7913 -ipset=/.crwdcntrl.net/gfwlist -server=/.questvisual.com/127.0.0.1#7913 -ipset=/.questvisual.com/gfwlist -server=/.laptoplockdown.com/127.0.0.1#7913 -ipset=/.laptoplockdown.com/gfwlist -server=/.steamcommunity.com/127.0.0.1#7913 -ipset=/.steamcommunity.com/gfwlist -server=/.briefdream.com/127.0.0.1#7913 -ipset=/.briefdream.com/gfwlist -server=/.ghostpath.com/127.0.0.1#7913 -ipset=/.ghostpath.com/gfwlist -server=/.avmoo.com/127.0.0.1#7913 -ipset=/.avmoo.com/gfwlist -server=/.bettervpn.com/127.0.0.1#7913 -ipset=/.bettervpn.com/gfwlist -server=/.gigporno.ru/127.0.0.1#7913 -ipset=/.gigporno.ru/gfwlist -server=/.heavy-r.com/127.0.0.1#7913 -ipset=/.heavy-r.com/gfwlist -server=/.navyfamily.navy.mil/127.0.0.1#7913 -ipset=/.navyfamily.navy.mil/gfwlist -server=/.line.naver.jp/127.0.0.1#7913 -ipset=/.line.naver.jp/gfwlist -server=/.bewww.net/127.0.0.1#7913 -ipset=/.bewww.net/gfwlist -server=/.earlytibet.com/127.0.0.1#7913 -ipset=/.earlytibet.com/gfwlist -server=/.hacg.li/127.0.0.1#7913 -ipset=/.hacg.li/gfwlist -server=/.meirixiaochao.com/127.0.0.1#7913 -ipset=/.meirixiaochao.com/gfwlist -server=/.news.tvb.com/127.0.0.1#7913 -ipset=/.news.tvb.com/gfwlist -server=/.myfreshnet.com/127.0.0.1#7913 -ipset=/.myfreshnet.com/gfwlist -server=/.dronedj.com/127.0.0.1#7913 -ipset=/.dronedj.com/gfwlist -server=/.uighur.narod.ru/127.0.0.1#7913 -ipset=/.uighur.narod.ru/gfwlist -server=/.onedumb.com/127.0.0.1#7913 -ipset=/.onedumb.com/gfwlist -server=/.search.aol.com/127.0.0.1#7913 -ipset=/.search.aol.com/gfwlist -server=/.naol.cc/127.0.0.1#7913 -ipset=/.naol.cc/gfwlist -server=/.vpncup.com/127.0.0.1#7913 -ipset=/.vpncup.com/gfwlist -server=/.pagodabox.com/127.0.0.1#7913 -ipset=/.pagodabox.com/gfwlist -server=/.googlechinawebmaster.com/127.0.0.1#7913 -ipset=/.googlechinawebmaster.com/gfwlist -server=/.turbobit.net/127.0.0.1#7913 -ipset=/.turbobit.net/gfwlist -server=/.ithelp.ithome.com.tw/127.0.0.1#7913 -ipset=/.ithelp.ithome.com.tw/gfwlist -server=/.dnsrd.com/127.0.0.1#7913 -ipset=/.dnsrd.com/gfwlist -server=/.hgseav.com/127.0.0.1#7913 -ipset=/.hgseav.com/gfwlist -server=/.synergyse.com/127.0.0.1#7913 -ipset=/.synergyse.com/gfwlist -server=/.tibetanyouthcongress.org/127.0.0.1#7913 -ipset=/.tibetanyouthcongress.org/gfwlist -server=/.realsexpass.com/127.0.0.1#7913 -ipset=/.realsexpass.com/gfwlist -server=/.mymom.info/127.0.0.1#7913 -ipset=/.mymom.info/gfwlist -server=/.mymusic.net.tw/127.0.0.1#7913 -ipset=/.mymusic.net.tw/gfwlist -server=/.daodu14.jigsy.com/127.0.0.1#7913 -ipset=/.daodu14.jigsy.com/gfwlist -server=/.bbnradio.org/127.0.0.1#7913 -ipset=/.bbnradio.org/gfwlist -server=/.emaga.com/127.0.0.1#7913 -ipset=/.emaga.com/gfwlist -server=/.tweets.seraph.me/127.0.0.1#7913 -ipset=/.tweets.seraph.me/gfwlist -server=/.avcool.com/127.0.0.1#7913 -ipset=/.avcool.com/gfwlist -server=/.cirosantilli.com/127.0.0.1#7913 -ipset=/.cirosantilli.com/gfwlist -server=/.christusrex.org/127.0.0.1#7913 -ipset=/.christusrex.org/gfwlist -server=/.design.google/127.0.0.1#7913 -ipset=/.design.google/gfwlist -server=/.24hrs.ca/127.0.0.1#7913 -ipset=/.24hrs.ca/gfwlist -server=/.qz.com/127.0.0.1#7913 -ipset=/.qz.com/gfwlist -server=/.gts-vpn.com/127.0.0.1#7913 -ipset=/.gts-vpn.com/gfwlist -server=/.karkhung.com/127.0.0.1#7913 -ipset=/.karkhung.com/gfwlist -server=/.abematv.akamaized.net/127.0.0.1#7913 -ipset=/.abematv.akamaized.net/gfwlist -server=/.huobi.com/127.0.0.1#7913 -ipset=/.huobi.com/gfwlist -server=/.peacefire.org/127.0.0.1#7913 -ipset=/.peacefire.org/gfwlist -server=/.mychinanews.com/127.0.0.1#7913 -ipset=/.mychinanews.com/gfwlist -server=/.hacg.club/127.0.0.1#7913 -ipset=/.hacg.club/gfwlist -server=/.api-secure.recaptcha.net/127.0.0.1#7913 -ipset=/.api-secure.recaptcha.net/gfwlist -server=/.gjczz.com/127.0.0.1#7913 -ipset=/.gjczz.com/gfwlist -server=/.engagedaily.org/127.0.0.1#7913 -ipset=/.engagedaily.org/gfwlist -server=/.googlesyndication.com/127.0.0.1#7913 -ipset=/.googlesyndication.com/gfwlist -server=/.my-proxy.com/127.0.0.1#7913 -ipset=/.my-proxy.com/gfwlist -server=/.ifan.cz.cc/127.0.0.1#7913 -ipset=/.ifan.cz.cc/gfwlist -server=/.my-formosa.com/127.0.0.1#7913 -ipset=/.my-formosa.com/gfwlist -server=/.buzzorange.com/127.0.0.1#7913 -ipset=/.buzzorange.com/gfwlist -server=/.64museum.org/127.0.0.1#7913 -ipset=/.64museum.org/gfwlist -server=/.tw.bid.yahoo.com/127.0.0.1#7913 -ipset=/.tw.bid.yahoo.com/gfwlist -server=/.9bis.com/127.0.0.1#7913 -ipset=/.9bis.com/gfwlist -server=/.anysex.com/127.0.0.1#7913 -ipset=/.anysex.com/gfwlist -server=/.tuo8.red/127.0.0.1#7913 -ipset=/.tuo8.red/gfwlist -server=/.behance.net/127.0.0.1#7913 -ipset=/.behance.net/gfwlist -server=/.multiproxy.org/127.0.0.1#7913 -ipset=/.multiproxy.org/gfwlist -server=/.marguerite.su/127.0.0.1#7913 -ipset=/.marguerite.su/gfwlist -server=/.dwnews.net/127.0.0.1#7913 -ipset=/.dwnews.net/gfwlist -server=/.girlbanker.com/127.0.0.1#7913 -ipset=/.girlbanker.com/gfwlist -server=/.jihadology.net/127.0.0.1#7913 -ipset=/.jihadology.net/gfwlist -server=/.mswe1.org/127.0.0.1#7913 -ipset=/.mswe1.org/gfwlist -server=/.85cc.us/127.0.0.1#7913 -ipset=/.85cc.us/gfwlist -server=/.atnext.com/127.0.0.1#7913 -ipset=/.atnext.com/gfwlist -server=/.3boys2girls.com/127.0.0.1#7913 -ipset=/.3boys2girls.com/gfwlist -server=/.iverycd.com/127.0.0.1#7913 -ipset=/.iverycd.com/gfwlist -server=/.wego.here.com/127.0.0.1#7913 -ipset=/.wego.here.com/gfwlist -server=/.myparagliding.com/127.0.0.1#7913 -ipset=/.myparagliding.com/gfwlist -server=/.exploader.net/127.0.0.1#7913 -ipset=/.exploader.net/gfwlist -server=/.funkyimg.com/127.0.0.1#7913 -ipset=/.funkyimg.com/gfwlist -server=/.lalulalu.com/127.0.0.1#7913 -ipset=/.lalulalu.com/gfwlist -server=/.mihk.hk/127.0.0.1#7913 -ipset=/.mihk.hk/gfwlist -server=/.movements.org/127.0.0.1#7913 -ipset=/.movements.org/gfwlist -server=/.mousebreaker.com/127.0.0.1#7913 -ipset=/.mousebreaker.com/gfwlist -server=/.moroneta.com/127.0.0.1#7913 -ipset=/.moroneta.com/gfwlist -server=/.hkcmi.edu/127.0.0.1#7913 -ipset=/.hkcmi.edu/gfwlist -server=/.4pu.com/127.0.0.1#7913 -ipset=/.4pu.com/gfwlist -server=/.in-disguise.com/127.0.0.1#7913 -ipset=/.in-disguise.com/gfwlist -server=/.c1522.mooo.com/127.0.0.1#7913 -ipset=/.c1522.mooo.com/gfwlist -server=/.freelotto.com/127.0.0.1#7913 -ipset=/.freelotto.com/gfwlist -server=/.hotav.tv/127.0.0.1#7913 -ipset=/.hotav.tv/gfwlist -server=/.nyaa.si/127.0.0.1#7913 -ipset=/.nyaa.si/gfwlist -server=/.citizencn.com/127.0.0.1#7913 -ipset=/.citizencn.com/gfwlist -server=/.dailyview.tw/127.0.0.1#7913 -ipset=/.dailyview.tw/gfwlist -server=/.tycool.com/127.0.0.1#7913 -ipset=/.tycool.com/gfwlist -server=/.eisbb.com/127.0.0.1#7913 -ipset=/.eisbb.com/gfwlist -server=/.mog.com/127.0.0.1#7913 -ipset=/.mog.com/gfwlist -server=/.shadowsocks.be/127.0.0.1#7913 -ipset=/.shadowsocks.be/gfwlist -server=/.mingjingtimes.com/127.0.0.1#7913 -ipset=/.mingjingtimes.com/gfwlist -server=/.twblogger.com/127.0.0.1#7913 -ipset=/.twblogger.com/gfwlist -server=/.fzh999.com/127.0.0.1#7913 -ipset=/.fzh999.com/gfwlist -server=/.corumcollege.com/127.0.0.1#7913 -ipset=/.corumcollege.com/gfwlist -server=/.calgarychinese.com/127.0.0.1#7913 -ipset=/.calgarychinese.com/gfwlist -server=/.jpopforum.net/127.0.0.1#7913 -ipset=/.jpopforum.net/gfwlist -server=/.mobile01.com/127.0.0.1#7913 -ipset=/.mobile01.com/gfwlist -server=/.material.io/127.0.0.1#7913 -ipset=/.material.io/gfwlist -server=/.vpnaccounts.com/127.0.0.1#7913 -ipset=/.vpnaccounts.com/gfwlist -server=/.mihua.org/127.0.0.1#7913 -ipset=/.mihua.org/gfwlist -server=/.eriversoft.com/127.0.0.1#7913 -ipset=/.eriversoft.com/gfwlist -server=/.englishpen.org/127.0.0.1#7913 -ipset=/.englishpen.org/gfwlist -server=/.teachparentstech.org/127.0.0.1#7913 -ipset=/.teachparentstech.org/gfwlist -server=/.mixx.com/127.0.0.1#7913 -ipset=/.mixx.com/gfwlist -server=/.mergersandinquisitions.org/127.0.0.1#7913 -ipset=/.mergersandinquisitions.org/gfwlist -server=/.goagent.biz/127.0.0.1#7913 -ipset=/.goagent.biz/gfwlist -server=/.entnt.com/127.0.0.1#7913 -ipset=/.entnt.com/gfwlist -server=/.faiththedog.info/127.0.0.1#7913 -ipset=/.faiththedog.info/gfwlist -server=/.onmypc.us/127.0.0.1#7913 -ipset=/.onmypc.us/gfwlist -server=/.bigmoney.biz/127.0.0.1#7913 -ipset=/.bigmoney.biz/gfwlist -server=/.minzhuzhanxian.com/127.0.0.1#7913 -ipset=/.minzhuzhanxian.com/gfwlist -server=/.ministrybooks.org/127.0.0.1#7913 -ipset=/.ministrybooks.org/gfwlist -server=/.minhhue.net/127.0.0.1#7913 -ipset=/.minhhue.net/gfwlist -server=/.mercyprophet.org/127.0.0.1#7913 -ipset=/.mercyprophet.org/gfwlist -server=/.sunwinism.joinbbs.net/127.0.0.1#7913 -ipset=/.sunwinism.joinbbs.net/gfwlist -server=/.polymer-project.org/127.0.0.1#7913 -ipset=/.polymer-project.org/gfwlist -server=/.duihua.org/127.0.0.1#7913 -ipset=/.duihua.org/gfwlist -server=/.cuihua.org/127.0.0.1#7913 -ipset=/.cuihua.org/gfwlist -server=/.g6hentai.com/127.0.0.1#7913 -ipset=/.g6hentai.com/gfwlist -server=/.mingpao.com/127.0.0.1#7913 -ipset=/.mingpao.com/gfwlist -server=/.asg.to/127.0.0.1#7913 -ipset=/.asg.to/gfwlist -server=/.chinapost.com.tw/127.0.0.1#7913 -ipset=/.chinapost.com.tw/gfwlist -server=/.hougaige.com/127.0.0.1#7913 -ipset=/.hougaige.com/gfwlist -server=/.amoiist.com/127.0.0.1#7913 -ipset=/.amoiist.com/gfwlist -server=/.wiki.moegirl.org/127.0.0.1#7913 -ipset=/.wiki.moegirl.org/gfwlist -server=/.mingjinglishi.com/127.0.0.1#7913 -ipset=/.mingjinglishi.com/gfwlist -server=/.boyfriendtv.com/127.0.0.1#7913 -ipset=/.boyfriendtv.com/gfwlist -server=/.twimg.com/127.0.0.1#7913 -ipset=/.twimg.com/gfwlist -server=/.chhongbi.org/127.0.0.1#7913 -ipset=/.chhongbi.org/gfwlist -server=/.dalailamaquotes.org/127.0.0.1#7913 -ipset=/.dalailamaquotes.org/gfwlist -server=/.now.im/127.0.0.1#7913 -ipset=/.now.im/gfwlist -server=/.coinrail.co.kr/127.0.0.1#7913 -ipset=/.coinrail.co.kr/gfwlist -server=/.middle-way.net/127.0.0.1#7913 -ipset=/.middle-way.net/gfwlist -server=/.bbs.mikocon.com/127.0.0.1#7913 -ipset=/.bbs.mikocon.com/gfwlist -server=/.kawaiikawaii.jp/127.0.0.1#7913 -ipset=/.kawaiikawaii.jp/gfwlist -server=/.olympicwatch.org/127.0.0.1#7913 -ipset=/.olympicwatch.org/gfwlist -server=/.mhradio.org/127.0.0.1#7913 -ipset=/.mhradio.org/gfwlist -server=/.webmproject.org/127.0.0.1#7913 -ipset=/.webmproject.org/gfwlist -server=/.fqrouter.com/127.0.0.1#7913 -ipset=/.fqrouter.com/gfwlist -server=/.almostmy.com/127.0.0.1#7913 -ipset=/.almostmy.com/gfwlist -server=/.crd-net.org/127.0.0.1#7913 -ipset=/.crd-net.org/gfwlist -server=/.tw.yahoo.com/127.0.0.1#7913 -ipset=/.tw.yahoo.com/gfwlist -server=/.meteorshowersonline.com/127.0.0.1#7913 -ipset=/.meteorshowersonline.com/gfwlist -server=/.metacafe.com/127.0.0.1#7913 -ipset=/.metacafe.com/gfwlist -server=/.meshrep.com/127.0.0.1#7913 -ipset=/.meshrep.com/gfwlist -server=/.dish.com/127.0.0.1#7913 -ipset=/.dish.com/gfwlist -server=/.thehousenews.com/127.0.0.1#7913 -ipset=/.thehousenews.com/gfwlist -server=/.jav68.tv/127.0.0.1#7913 -ipset=/.jav68.tv/gfwlist -server=/.stackoverflow.com/127.0.0.1#7913 -ipset=/.stackoverflow.com/gfwlist -server=/.onejav.com/127.0.0.1#7913 -ipset=/.onejav.com/gfwlist -server=/.memri.org/127.0.0.1#7913 -ipset=/.memri.org/gfwlist -server=/.fartit.com/127.0.0.1#7913 -ipset=/.fartit.com/gfwlist -server=/.memorybbs.com/127.0.0.1#7913 -ipset=/.memorybbs.com/gfwlist -server=/.megaproxy.com/127.0.0.1#7913 -ipset=/.megaproxy.com/gfwlist -server=/.ns3.name/127.0.0.1#7913 -ipset=/.ns3.name/gfwlist -server=/.theinitium.com/127.0.0.1#7913 -ipset=/.theinitium.com/gfwlist -server=/.blog.expofutures.com/127.0.0.1#7913 -ipset=/.blog.expofutures.com/gfwlist -server=/.nflxvideo.net/127.0.0.1#7913 -ipset=/.nflxvideo.net/gfwlist -server=/.bic2011.org/127.0.0.1#7913 -ipset=/.bic2011.org/gfwlist -server=/.cineastentreff.de/127.0.0.1#7913 -ipset=/.cineastentreff.de/gfwlist -server=/.meansys.com/127.0.0.1#7913 -ipset=/.meansys.com/gfwlist -server=/.mcaf.ee/127.0.0.1#7913 -ipset=/.mcaf.ee/gfwlist -server=/.mathiew-badimon.com/127.0.0.1#7913 -ipset=/.mathiew-badimon.com/gfwlist -server=/.welovecock.com/127.0.0.1#7913 -ipset=/.welovecock.com/gfwlist -server=/.international-news.newsmagazine.asia/127.0.0.1#7913 -ipset=/.international-news.newsmagazine.asia/gfwlist -server=/.dotsub.com/127.0.0.1#7913 -ipset=/.dotsub.com/gfwlist -server=/.e-info.org.tw/127.0.0.1#7913 -ipset=/.e-info.org.tw/gfwlist -server=/.indiemerch.com/127.0.0.1#7913 -ipset=/.indiemerch.com/gfwlist -server=/.getchu.com/127.0.0.1#7913 -ipset=/.getchu.com/gfwlist -server=/.appsocks.net/127.0.0.1#7913 -ipset=/.appsocks.net/gfwlist -server=/.blogspot.com/127.0.0.1#7913 -ipset=/.blogspot.com/gfwlist -server=/.marxists.org/127.0.0.1#7913 -ipset=/.marxists.org/gfwlist -server=/.marxist.com/127.0.0.1#7913 -ipset=/.marxist.com/gfwlist -server=/.martsangkagyuofficial.org/127.0.0.1#7913 -ipset=/.martsangkagyuofficial.org/gfwlist -server=/.sowers.org.hk/127.0.0.1#7913 -ipset=/.sowers.org.hk/gfwlist -server=/.clearharmony.net/127.0.0.1#7913 -ipset=/.clearharmony.net/gfwlist -server=/.authorizeddns.us/127.0.0.1#7913 -ipset=/.authorizeddns.us/gfwlist -server=/.marc.info/127.0.0.1#7913 -ipset=/.marc.info/gfwlist -server=/.pincong.rocks/127.0.0.1#7913 -ipset=/.pincong.rocks/gfwlist -server=/.wizcrafts.net/127.0.0.1#7913 -ipset=/.wizcrafts.net/gfwlist -server=/.multiply.com/127.0.0.1#7913 -ipset=/.multiply.com/gfwlist -server=/.makkahnewspaper.com/127.0.0.1#7913 -ipset=/.makkahnewspaper.com/gfwlist -server=/.apigee.com/127.0.0.1#7913 -ipset=/.apigee.com/gfwlist -server=/.madthumbs.com/127.0.0.1#7913 -ipset=/.madthumbs.com/gfwlist -server=/.yourtrap.com/127.0.0.1#7913 -ipset=/.yourtrap.com/gfwlist -server=/.epochtimes.com/127.0.0.1#7913 -ipset=/.epochtimes.com/gfwlist -server=/.madrau.com/127.0.0.1#7913 -ipset=/.madrau.com/gfwlist -server=/.kendatire.com/127.0.0.1#7913 -ipset=/.kendatire.com/gfwlist -server=/.gmozomg.izihost.org/127.0.0.1#7913 -ipset=/.gmozomg.izihost.org/gfwlist -server=/.scache2.vzw.com/127.0.0.1#7913 -ipset=/.scache2.vzw.com/gfwlist -server=/.pictures.playboy.com/127.0.0.1#7913 -ipset=/.pictures.playboy.com/gfwlist -server=/.lupm.org/127.0.0.1#7913 -ipset=/.lupm.org/gfwlist -server=/.ltn.com.tw/127.0.0.1#7913 -ipset=/.ltn.com.tw/gfwlist -server=/.cactusvpn.com/127.0.0.1#7913 -ipset=/.cactusvpn.com/gfwlist -server=/.google.gl/127.0.0.1#7913 -ipset=/.google.gl/gfwlist -server=/.lsmradio.com/127.0.0.1#7913 -ipset=/.lsmradio.com/gfwlist -server=/.mqxd.org/127.0.0.1#7913 -ipset=/.mqxd.org/gfwlist -server=/.lsforum.net/127.0.0.1#7913 -ipset=/.lsforum.net/gfwlist -server=/.blogcity.me/127.0.0.1#7913 -ipset=/.blogcity.me/gfwlist -server=/.bangyoulater.com/127.0.0.1#7913 -ipset=/.bangyoulater.com/gfwlist -server=/.lrip.org/127.0.0.1#7913 -ipset=/.lrip.org/gfwlist -server=/.eromanga-kingdom.com/127.0.0.1#7913 -ipset=/.eromanga-kingdom.com/gfwlist -server=/.epochhk.com/127.0.0.1#7913 -ipset=/.epochhk.com/gfwlist -server=/.neverforget8964.org/127.0.0.1#7913 -ipset=/.neverforget8964.org/gfwlist -server=/.howtoforge.com/127.0.0.1#7913 -ipset=/.howtoforge.com/gfwlist -server=/.jav2be.com/127.0.0.1#7913 -ipset=/.jav2be.com/gfwlist -server=/.looktoronto.com/127.0.0.1#7913 -ipset=/.looktoronto.com/gfwlist -server=/.cdn.assets.lfpcontent.com/127.0.0.1#7913 -ipset=/.cdn.assets.lfpcontent.com/gfwlist -server=/.legalporno.com/127.0.0.1#7913 -ipset=/.legalporno.com/gfwlist -server=/.google.am/127.0.0.1#7913 -ipset=/.google.am/gfwlist -server=/.yt.be/127.0.0.1#7913 -ipset=/.yt.be/gfwlist -server=/.jex.com/127.0.0.1#7913 -ipset=/.jex.com/gfwlist -server=/.eucasino.com/127.0.0.1#7913 -ipset=/.eucasino.com/gfwlist -server=/.erepublik.com/127.0.0.1#7913 -ipset=/.erepublik.com/gfwlist -server=/.cmx.im/127.0.0.1#7913 -ipset=/.cmx.im/gfwlist -server=/.faqserv.com/127.0.0.1#7913 -ipset=/.faqserv.com/gfwlist -server=/.coolstuffinc.com/127.0.0.1#7913 -ipset=/.coolstuffinc.com/gfwlist -server=/.forum.idsam.com/127.0.0.1#7913 -ipset=/.forum.idsam.com/gfwlist -server=/.woxinghuiguo.com/127.0.0.1#7913 -ipset=/.woxinghuiguo.com/gfwlist -server=/.quitccp.org/127.0.0.1#7913 -ipset=/.quitccp.org/gfwlist -server=/.duckdns.org/127.0.0.1#7913 -ipset=/.duckdns.org/gfwlist -server=/.culture.tw/127.0.0.1#7913 -ipset=/.culture.tw/gfwlist -server=/.buffered.com/127.0.0.1#7913 -ipset=/.buffered.com/gfwlist -server=/.cdw.com/127.0.0.1#7913 -ipset=/.cdw.com/gfwlist -server=/.blog.cnyes.com/127.0.0.1#7913 -ipset=/.blog.cnyes.com/gfwlist -server=/.chrome.com/127.0.0.1#7913 -ipset=/.chrome.com/gfwlist -server=/.waiwaier.com/127.0.0.1#7913 -ipset=/.waiwaier.com/gfwlist -server=/.cap.org.hk/127.0.0.1#7913 -ipset=/.cap.org.hk/gfwlist -server=/.big.one/127.0.0.1#7913 -ipset=/.big.one/gfwlist -server=/.hkheadline.com/127.0.0.1#7913 -ipset=/.hkheadline.com/gfwlist -server=/.mercatox.com/127.0.0.1#7913 -ipset=/.mercatox.com/gfwlist -server=/.telegra.ph/127.0.0.1#7913 -ipset=/.telegra.ph/gfwlist -server=/.line-apps.com/127.0.0.1#7913 -ipset=/.line-apps.com/gfwlist -server=/.nikkei.com/127.0.0.1#7913 -ipset=/.nikkei.com/gfwlist -server=/.blogs.libraryinformationtechnology.com/127.0.0.1#7913 -ipset=/.blogs.libraryinformationtechnology.com/gfwlist -server=/.tcpspeed.com/127.0.0.1#7913 -ipset=/.tcpspeed.com/gfwlist -server=/.sthoo.com/127.0.0.1#7913 -ipset=/.sthoo.com/gfwlist -server=/.erodaizensyu.com/127.0.0.1#7913 -ipset=/.erodaizensyu.com/gfwlist -server=/.clementine-player.org/127.0.0.1#7913 -ipset=/.clementine-player.org/gfwlist -server=/.chinachannel.hk/127.0.0.1#7913 -ipset=/.chinachannel.hk/gfwlist -server=/.python.com.tw/127.0.0.1#7913 -ipset=/.python.com.tw/gfwlist -server=/.authorizeddns.org/127.0.0.1#7913 -ipset=/.authorizeddns.org/gfwlist -server=/.zorrovpn.com/127.0.0.1#7913 -ipset=/.zorrovpn.com/gfwlist -server=/.mynetav.net/127.0.0.1#7913 -ipset=/.mynetav.net/gfwlist -server=/.taiwanjustice.net/127.0.0.1#7913 -ipset=/.taiwanjustice.net/gfwlist -server=/.chenguangcheng.com/127.0.0.1#7913 -ipset=/.chenguangcheng.com/gfwlist -server=/.tweetrans.com/127.0.0.1#7913 -ipset=/.tweetrans.com/gfwlist -server=/.dalailama.com/127.0.0.1#7913 -ipset=/.dalailama.com/gfwlist -server=/.godoc.org/127.0.0.1#7913 -ipset=/.godoc.org/gfwlist -server=/.etaiwannews.com/127.0.0.1#7913 -ipset=/.etaiwannews.com/gfwlist -server=/.googleapps.com/127.0.0.1#7913 -ipset=/.googleapps.com/gfwlist -server=/.chn.chosun.com/127.0.0.1#7913 -ipset=/.chn.chosun.com/gfwlist -server=/.hkfaa.com/127.0.0.1#7913 -ipset=/.hkfaa.com/gfwlist -server=/.www.moztw.org/127.0.0.1#7913 -ipset=/.www.moztw.org/gfwlist -server=/.arctosia.com/127.0.0.1#7913 -ipset=/.arctosia.com/gfwlist -server=/.ice.audionow.com/127.0.0.1#7913 -ipset=/.ice.audionow.com/gfwlist -server=/.godsdirectcontact.org.tw/127.0.0.1#7913 -ipset=/.godsdirectcontact.org.tw/gfwlist -server=/.actfortibet.org/127.0.0.1#7913 -ipset=/.actfortibet.org/gfwlist -server=/.kui.name/127.0.0.1#7913 -ipset=/.kui.name/gfwlist -server=/.cw.com.tw/127.0.0.1#7913 -ipset=/.cw.com.tw/gfwlist -server=/.abitno.linpie.com/127.0.0.1#7913 -ipset=/.abitno.linpie.com/gfwlist -server=/.anonymitynetwork.com/127.0.0.1#7913 -ipset=/.anonymitynetwork.com/gfwlist -server=/.hitbtc.com/127.0.0.1#7913 -ipset=/.hitbtc.com/gfwlist -server=/.xuchao.org/127.0.0.1#7913 -ipset=/.xuchao.org/gfwlist -server=/.gojet.krtco.com.tw/127.0.0.1#7913 -ipset=/.gojet.krtco.com.tw/gfwlist -server=/.kingdomsalvation.org/127.0.0.1#7913 -ipset=/.kingdomsalvation.org/gfwlist -server=/.voanews.com/127.0.0.1#7913 -ipset=/.voanews.com/gfwlist -server=/.faceless.me/127.0.0.1#7913 -ipset=/.faceless.me/gfwlist -server=/.great-roc.org/127.0.0.1#7913 -ipset=/.great-roc.org/gfwlist -server=/.koolsolutions.com/127.0.0.1#7913 -ipset=/.koolsolutions.com/gfwlist -server=/.tibet.org/127.0.0.1#7913 -ipset=/.tibet.org/gfwlist -server=/.fb.com/127.0.0.1#7913 -ipset=/.fb.com/gfwlist -server=/.appledaily.com/127.0.0.1#7913 -ipset=/.appledaily.com/gfwlist -server=/.foreignpolicy.com/127.0.0.1#7913 -ipset=/.foreignpolicy.com/gfwlist -server=/.img.ly/127.0.0.1#7913 -ipset=/.img.ly/gfwlist -server=/.www.kindleren.com/127.0.0.1#7913 -ipset=/.www.kindleren.com/gfwlist -server=/.kichiku-doujinko.com/127.0.0.1#7913 -ipset=/.kichiku-doujinko.com/gfwlist -server=/.bipic.net/127.0.0.1#7913 -ipset=/.bipic.net/gfwlist -server=/.brkmd.com/127.0.0.1#7913 -ipset=/.brkmd.com/gfwlist -server=/.javhip.com/127.0.0.1#7913 -ipset=/.javhip.com/gfwlist -server=/.cnd.org/127.0.0.1#7913 -ipset=/.cnd.org/gfwlist -server=/.dalailamajapanese.com/127.0.0.1#7913 -ipset=/.dalailamajapanese.com/gfwlist -server=/.tubepornclassic.com/127.0.0.1#7913 -ipset=/.tubepornclassic.com/gfwlist -server=/.keezmovies.com/127.0.0.1#7913 -ipset=/.keezmovies.com/gfwlist -server=/.kawase.com/127.0.0.1#7913 -ipset=/.kawase.com/gfwlist -server=/.javlibrary.com/127.0.0.1#7913 -ipset=/.javlibrary.com/gfwlist -server=/.jtvnw.net/127.0.0.1#7913 -ipset=/.jtvnw.net/gfwlist -server=/.kantie.org/127.0.0.1#7913 -ipset=/.kantie.org/gfwlist -server=/.openallweb.com/127.0.0.1#7913 -ipset=/.openallweb.com/gfwlist -server=/.google.nl/127.0.0.1#7913 -ipset=/.google.nl/gfwlist -server=/.impact.org.au/127.0.0.1#7913 -ipset=/.impact.org.au/gfwlist -server=/.zb.com/127.0.0.1#7913 -ipset=/.zb.com/gfwlist -server=/.kagyu.org.za/127.0.0.1#7913 -ipset=/.kagyu.org.za/gfwlist -server=/.qtweeter.com/127.0.0.1#7913 -ipset=/.qtweeter.com/gfwlist -server=/.pcdvd.com.tw/127.0.0.1#7913 -ipset=/.pcdvd.com.tw/gfwlist -server=/.juziyue.com/127.0.0.1#7913 -ipset=/.juziyue.com/gfwlist -server=/.llss.me/127.0.0.1#7913 -ipset=/.llss.me/gfwlist -server=/.guaneryu.com/127.0.0.1#7913 -ipset=/.guaneryu.com/gfwlist -server=/.gongwt.com/127.0.0.1#7913 -ipset=/.gongwt.com/gfwlist -server=/.ukcdp.co.uk/127.0.0.1#7913 -ipset=/.ukcdp.co.uk/gfwlist -server=/.itemdb.com/127.0.0.1#7913 -ipset=/.itemdb.com/gfwlist -server=/.blogtd.net/127.0.0.1#7913 -ipset=/.blogtd.net/gfwlist -server=/.junefourth-20.net/127.0.0.1#7913 -ipset=/.junefourth-20.net/gfwlist -server=/.6parkbbs.com/127.0.0.1#7913 -ipset=/.6parkbbs.com/gfwlist -server=/.alexlur.org/127.0.0.1#7913 -ipset=/.alexlur.org/gfwlist -server=/.atlaspost.com/127.0.0.1#7913 -ipset=/.atlaspost.com/gfwlist -server=/.digisfera.com/127.0.0.1#7913 -ipset=/.digisfera.com/gfwlist -server=/.myradio.hk/127.0.0.1#7913 -ipset=/.myradio.hk/gfwlist -server=/.ttvnw.net/127.0.0.1#7913 -ipset=/.ttvnw.net/gfwlist -server=/.ftp1.biz/127.0.0.1#7913 -ipset=/.ftp1.biz/gfwlist -server=/.mrslove.com/127.0.0.1#7913 -ipset=/.mrslove.com/gfwlist -server=/.journalchretien.net/127.0.0.1#7913 -ipset=/.journalchretien.net/gfwlist -server=/.jkforum.net/127.0.0.1#7913 -ipset=/.jkforum.net/gfwlist -server=/.dns-stuff.com/127.0.0.1#7913 -ipset=/.dns-stuff.com/gfwlist -server=/.badjojo.com/127.0.0.1#7913 -ipset=/.badjojo.com/gfwlist -server=/.abebooks.com/127.0.0.1#7913 -ipset=/.abebooks.com/gfwlist -server=/.toodoc.com/127.0.0.1#7913 -ipset=/.toodoc.com/gfwlist -server=/.fflick.com/127.0.0.1#7913 -ipset=/.fflick.com/gfwlist -server=/.aenhancers.com/127.0.0.1#7913 -ipset=/.aenhancers.com/gfwlist -server=/.jigglegifs.com/127.0.0.1#7913 -ipset=/.jigglegifs.com/gfwlist -server=/.chinaaid.org/127.0.0.1#7913 -ipset=/.chinaaid.org/gfwlist -server=/.englishfromengland.co.uk/127.0.0.1#7913 -ipset=/.englishfromengland.co.uk/gfwlist -server=/.seevpn.com/127.0.0.1#7913 -ipset=/.seevpn.com/gfwlist -server=/.c2cx.com/127.0.0.1#7913 -ipset=/.c2cx.com/gfwlist -server=/.falunau.org/127.0.0.1#7913 -ipset=/.falunau.org/gfwlist -server=/.xinqimeng.over-blog.com/127.0.0.1#7913 -ipset=/.xinqimeng.over-blog.com/gfwlist -server=/.malaysiakini.com/127.0.0.1#7913 -ipset=/.malaysiakini.com/gfwlist -server=/.18virginsex.com/127.0.0.1#7913 -ipset=/.18virginsex.com/gfwlist -server=/.javbus.co/127.0.0.1#7913 -ipset=/.javbus.co/gfwlist -server=/.bbsone.com/127.0.0.1#7913 -ipset=/.bbsone.com/gfwlist -server=/.getlantern.org/127.0.0.1#7913 -ipset=/.getlantern.org/gfwlist -server=/.iyouport.com/127.0.0.1#7913 -ipset=/.iyouport.com/gfwlist -server=/.pornoxo.com/127.0.0.1#7913 -ipset=/.pornoxo.com/gfwlist -server=/.chinesen.de/127.0.0.1#7913 -ipset=/.chinesen.de/gfwlist -server=/.itsky.it/127.0.0.1#7913 -ipset=/.itsky.it/gfwlist -server=/.ns1.name/127.0.0.1#7913 -ipset=/.ns1.name/gfwlist -server=/.get.how/127.0.0.1#7913 -ipset=/.get.how/gfwlist -server=/.ikstar.com/127.0.0.1#7913 -ipset=/.ikstar.com/gfwlist -server=/.animecrazy.net/127.0.0.1#7913 -ipset=/.animecrazy.net/gfwlist -server=/.manta.com/127.0.0.1#7913 -ipset=/.manta.com/gfwlist -server=/.goldstep.net/127.0.0.1#7913 -ipset=/.goldstep.net/gfwlist -server=/.israbox.com/127.0.0.1#7913 -ipset=/.israbox.com/gfwlist -server=/.lingvodics.com/127.0.0.1#7913 -ipset=/.lingvodics.com/gfwlist -server=/.bodog88.com/127.0.0.1#7913 -ipset=/.bodog88.com/gfwlist -server=/.isohunt.com/127.0.0.1#7913 -ipset=/.isohunt.com/gfwlist -server=/.islam.org.hk/127.0.0.1#7913 -ipset=/.islam.org.hk/gfwlist -server=/.maiplus.com/127.0.0.1#7913 -ipset=/.maiplus.com/gfwlist -server=/.lflinkup.com/127.0.0.1#7913 -ipset=/.lflinkup.com/gfwlist -server=/.google.rw/127.0.0.1#7913 -ipset=/.google.rw/gfwlist -server=/.asiatgp.com/127.0.0.1#7913 -ipset=/.asiatgp.com/gfwlist -server=/.chinese.irib.ir/127.0.0.1#7913 -ipset=/.chinese.irib.ir/gfwlist -server=/.ipvanish.com/127.0.0.1#7913 -ipset=/.ipvanish.com/gfwlist -server=/.premproxy.com/127.0.0.1#7913 -ipset=/.premproxy.com/gfwlist -server=/.inthenameofconfuciusmovie.com/127.0.0.1#7913 -ipset=/.inthenameofconfuciusmovie.com/gfwlist -server=/.info-graf.fr/127.0.0.1#7913 -ipset=/.info-graf.fr/gfwlist -server=/.18board.info/127.0.0.1#7913 -ipset=/.18board.info/gfwlist -server=/.indiandefensenews.in/127.0.0.1#7913 -ipset=/.indiandefensenews.in/gfwlist -server=/.imkev.com/127.0.0.1#7913 -ipset=/.imkev.com/gfwlist -server=/.addictedtocoffee.de/127.0.0.1#7913 -ipset=/.addictedtocoffee.de/gfwlist -server=/.ghut.org/127.0.0.1#7913 -ipset=/.ghut.org/gfwlist -server=/.myeclipseide.com/127.0.0.1#7913 -ipset=/.myeclipseide.com/gfwlist -server=/.say2.info/127.0.0.1#7913 -ipset=/.say2.info/gfwlist -server=/.cdpa.url.tw/127.0.0.1#7913 -ipset=/.cdpa.url.tw/gfwlist -server=/.danwei.org/127.0.0.1#7913 -ipset=/.danwei.org/gfwlist -server=/.almasdarnews.com/127.0.0.1#7913 -ipset=/.almasdarnews.com/gfwlist -server=/.alvinalexander.com/127.0.0.1#7913 -ipset=/.alvinalexander.com/gfwlist -server=/.javbus.com/127.0.0.1#7913 -ipset=/.javbus.com/gfwlist -server=/.igfw.tech/127.0.0.1#7913 -ipset=/.igfw.tech/gfwlist -server=/.canalporno.com/127.0.0.1#7913 -ipset=/.canalporno.com/gfwlist -server=/.igfw.net/127.0.0.1#7913 -ipset=/.igfw.net/gfwlist -server=/.falundafa-sacramento.org/127.0.0.1#7913 -ipset=/.falundafa-sacramento.org/gfwlist -server=/.21andy.com/127.0.0.1#7913 -ipset=/.21andy.com/gfwlist -server=/.treemall.com.tw/127.0.0.1#7913 -ipset=/.treemall.com.tw/gfwlist -server=/.ied2k.net/127.0.0.1#7913 -ipset=/.ied2k.net/gfwlist -server=/.you-get.org/127.0.0.1#7913 -ipset=/.you-get.org/gfwlist -server=/.falundafa-nc.org/127.0.0.1#7913 -ipset=/.falundafa-nc.org/gfwlist -server=/.student.tw/127.0.0.1#7913 -ipset=/.student.tw/gfwlist -server=/.i-cable.com/127.0.0.1#7913 -ipset=/.i-cable.com/gfwlist -server=/.facebookquotes4u.com/127.0.0.1#7913 -ipset=/.facebookquotes4u.com/gfwlist -server=/.arethusa.su/127.0.0.1#7913 -ipset=/.arethusa.su/gfwlist -server=/.freeddns.org/127.0.0.1#7913 -ipset=/.freeddns.org/gfwlist -server=/.centralnation.com/127.0.0.1#7913 -ipset=/.centralnation.com/gfwlist -server=/.vpnfire.com/127.0.0.1#7913 -ipset=/.vpnfire.com/gfwlist -server=/.24smile.org/127.0.0.1#7913 -ipset=/.24smile.org/gfwlist -server=/.drepung.org/127.0.0.1#7913 -ipset=/.drepung.org/gfwlist -server=/.creadersnet.com/127.0.0.1#7913 -ipset=/.creadersnet.com/gfwlist -server=/.qi-gong.me/127.0.0.1#7913 -ipset=/.qi-gong.me/gfwlist -server=/.nydus.ca/127.0.0.1#7913 -ipset=/.nydus.ca/gfwlist -server=/.huashangnews.com/127.0.0.1#7913 -ipset=/.huashangnews.com/gfwlist -server=/.www.sciencemag.org/127.0.0.1#7913 -ipset=/.www.sciencemag.org/gfwlist -server=/.drgan.net/127.0.0.1#7913 -ipset=/.drgan.net/gfwlist -server=/.google.cd/127.0.0.1#7913 -ipset=/.google.cd/gfwlist -server=/.huaren4us.com/127.0.0.1#7913 -ipset=/.huaren4us.com/gfwlist -server=/.hua-yue.net/127.0.0.1#7913 -ipset=/.hua-yue.net/gfwlist -server=/.hst.net.tw/127.0.0.1#7913 -ipset=/.hst.net.tw/gfwlist -server=/.hsselite.com/127.0.0.1#7913 -ipset=/.hsselite.com/gfwlist -server=/.hsjp.net/127.0.0.1#7913 -ipset=/.hsjp.net/gfwlist -server=/.tibetanpaintings.com/127.0.0.1#7913 -ipset=/.tibetanpaintings.com/gfwlist -server=/.vidble.com/127.0.0.1#7913 -ipset=/.vidble.com/gfwlist -server=/.nwtca.org/127.0.0.1#7913 -ipset=/.nwtca.org/gfwlist -server=/.chaturbate.com/127.0.0.1#7913 -ipset=/.chaturbate.com/gfwlist -server=/.hotshame.com/127.0.0.1#7913 -ipset=/.hotshame.com/gfwlist -server=/.nokogiri.org/127.0.0.1#7913 -ipset=/.nokogiri.org/gfwlist -server=/.edmontonchina.cn/127.0.0.1#7913 -ipset=/.edmontonchina.cn/gfwlist -server=/.thisav.com/127.0.0.1#7913 -ipset=/.thisav.com/gfwlist -server=/.blog.inoreader.com/127.0.0.1#7913 -ipset=/.blog.inoreader.com/gfwlist -server=/.alljackpotscasino.com/127.0.0.1#7913 -ipset=/.alljackpotscasino.com/gfwlist -server=/.dalailamafilm.com/127.0.0.1#7913 -ipset=/.dalailamafilm.com/gfwlist -server=/.sl-reverse.com/127.0.0.1#7913 -ipset=/.sl-reverse.com/gfwlist -server=/.freewebs.com/127.0.0.1#7913 -ipset=/.freewebs.com/gfwlist -server=/.picasaweb.com/127.0.0.1#7913 -ipset=/.picasaweb.com/gfwlist -server=/.alabout.com/127.0.0.1#7913 -ipset=/.alabout.com/gfwlist -server=/.theguardian.com/127.0.0.1#7913 -ipset=/.theguardian.com/gfwlist -server=/.electrek.co/127.0.0.1#7913 -ipset=/.electrek.co/gfwlist -server=/.hhdcb3office.org/127.0.0.1#7913 -ipset=/.hhdcb3office.org/gfwlist -server=/.beijingzx.org/127.0.0.1#7913 -ipset=/.beijingzx.org/gfwlist -server=/.electionsmeter.com/127.0.0.1#7913 -ipset=/.electionsmeter.com/gfwlist -server=/.allinfa.com/127.0.0.1#7913 -ipset=/.allinfa.com/gfwlist -server=/.bcmorning.com/127.0.0.1#7913 -ipset=/.bcmorning.com/gfwlist -server=/.breakwall.net/127.0.0.1#7913 -ipset=/.breakwall.net/gfwlist -server=/.xysblogs.org/127.0.0.1#7913 -ipset=/.xysblogs.org/gfwlist -server=/.glass8.eu/127.0.0.1#7913 -ipset=/.glass8.eu/gfwlist -server=/.aptoide.com/127.0.0.1#7913 -ipset=/.aptoide.com/gfwlist -server=/.emanna.com/127.0.0.1#7913 -ipset=/.emanna.com/gfwlist -server=/.bitmex.com/127.0.0.1#7913 -ipset=/.bitmex.com/gfwlist -server=/.van001.com/127.0.0.1#7913 -ipset=/.van001.com/gfwlist -server=/.superzooi.com/127.0.0.1#7913 -ipset=/.superzooi.com/gfwlist -server=/.beyondfirewall.com/127.0.0.1#7913 -ipset=/.beyondfirewall.com/gfwlist -server=/.twftp.org/127.0.0.1#7913 -ipset=/.twftp.org/gfwlist -server=/.nofile.io/127.0.0.1#7913 -ipset=/.nofile.io/gfwlist -server=/.maplew.com/127.0.0.1#7913 -ipset=/.maplew.com/gfwlist -server=/.wozy.in/127.0.0.1#7913 -ipset=/.wozy.in/gfwlist -server=/.twitturk.com/127.0.0.1#7913 -ipset=/.twitturk.com/gfwlist -server=/.instanthq.com/127.0.0.1#7913 -ipset=/.instanthq.com/gfwlist -server=/.pk.com/127.0.0.1#7913 -ipset=/.pk.com/gfwlist -server=/.c-est-simple.com/127.0.0.1#7913 -ipset=/.c-est-simple.com/gfwlist -server=/.wjbk.org/127.0.0.1#7913 -ipset=/.wjbk.org/gfwlist -server=/.gongmeng.info/127.0.0.1#7913 -ipset=/.gongmeng.info/gfwlist -server=/.oculuscdn.com/127.0.0.1#7913 -ipset=/.oculuscdn.com/gfwlist -server=/.thebobs.com/127.0.0.1#7913 -ipset=/.thebobs.com/gfwlist -server=/.jintian.net/127.0.0.1#7913 -ipset=/.jintian.net/gfwlist -server=/.blogdns.org/127.0.0.1#7913 -ipset=/.blogdns.org/gfwlist -server=/.dajiyuan.eu/127.0.0.1#7913 -ipset=/.dajiyuan.eu/gfwlist -server=/.messenger.com/127.0.0.1#7913 -ipset=/.messenger.com/gfwlist -server=/.chinaaffairs.org/127.0.0.1#7913 -ipset=/.chinaaffairs.org/gfwlist -server=/.nobelprize.org/127.0.0.1#7913 -ipset=/.nobelprize.org/gfwlist -server=/.bl-doujinsouko.com/127.0.0.1#7913 -ipset=/.bl-doujinsouko.com/gfwlist -server=/.uncyclopedia.tw/127.0.0.1#7913 -ipset=/.uncyclopedia.tw/gfwlist -server=/.cthlo.github.io/127.0.0.1#7913 -ipset=/.cthlo.github.io/gfwlist -server=/.search.xxx/127.0.0.1#7913 -ipset=/.search.xxx/gfwlist -server=/.canadameet.com/127.0.0.1#7913 -ipset=/.canadameet.com/gfwlist -server=/.git.io/127.0.0.1#7913 -ipset=/.git.io/gfwlist -server=/.fangong.org/127.0.0.1#7913 -ipset=/.fangong.org/gfwlist -server=/.ccthere.com/127.0.0.1#7913 -ipset=/.ccthere.com/gfwlist -server=/.gaywatch.com/127.0.0.1#7913 -ipset=/.gaywatch.com/gfwlist -server=/.fzh999.net/127.0.0.1#7913 -ipset=/.fzh999.net/gfwlist -server=/.heartyit.com/127.0.0.1#7913 -ipset=/.heartyit.com/gfwlist -server=/.wwe.com/127.0.0.1#7913 -ipset=/.wwe.com/gfwlist -server=/.japantimes.co.jp/127.0.0.1#7913 -ipset=/.japantimes.co.jp/gfwlist -server=/.nobel.se/127.0.0.1#7913 -ipset=/.nobel.se/gfwlist -server=/.molihua.org/127.0.0.1#7913 -ipset=/.molihua.org/gfwlist -server=/.bloomberg.com/127.0.0.1#7913 -ipset=/.bloomberg.com/gfwlist -server=/.tvplayvideos.com/127.0.0.1#7913 -ipset=/.tvplayvideos.com/gfwlist -server=/.furinkan.com/127.0.0.1#7913 -ipset=/.furinkan.com/gfwlist -server=/.asiansexdiary.com/127.0.0.1#7913 -ipset=/.asiansexdiary.com/gfwlist -server=/.amiblockedornot.com/127.0.0.1#7913 -ipset=/.amiblockedornot.com/gfwlist -server=/.mad-ar.ch/127.0.0.1#7913 -ipset=/.mad-ar.ch/gfwlist -server=/.twurl.nl/127.0.0.1#7913 -ipset=/.twurl.nl/gfwlist -server=/.dessci.com/127.0.0.1#7913 -ipset=/.dessci.com/gfwlist -server=/.frootvpn.com/127.0.0.1#7913 -ipset=/.frootvpn.com/gfwlist -server=/.namgyalmonastery.org/127.0.0.1#7913 -ipset=/.namgyalmonastery.org/gfwlist -server=/.b0ne.com/127.0.0.1#7913 -ipset=/.b0ne.com/gfwlist -server=/.s3-ap-southeast-2.amazonaws.com/127.0.0.1#7913 -ipset=/.s3-ap-southeast-2.amazonaws.com/gfwlist -server=/.mansionpoker.com/127.0.0.1#7913 -ipset=/.mansionpoker.com/gfwlist -server=/.google.no/127.0.0.1#7913 -ipset=/.google.no/gfwlist -server=/.thinkwithgoogle.com/127.0.0.1#7913 -ipset=/.thinkwithgoogle.com/gfwlist -server=/.kakao.com/127.0.0.1#7913 -ipset=/.kakao.com/gfwlist -server=/.hwinfo.com/127.0.0.1#7913 -ipset=/.hwinfo.com/gfwlist -server=/.businesstoday.com.tw/127.0.0.1#7913 -ipset=/.businesstoday.com.tw/gfwlist -server=/.en.favotter.net/127.0.0.1#7913 -ipset=/.en.favotter.net/gfwlist -server=/.jiji.com/127.0.0.1#7913 -ipset=/.jiji.com/gfwlist -server=/.etowns.org/127.0.0.1#7913 -ipset=/.etowns.org/gfwlist -server=/.fangeming.com/127.0.0.1#7913 -ipset=/.fangeming.com/gfwlist -server=/.epochtimes-romania.com/127.0.0.1#7913 -ipset=/.epochtimes-romania.com/gfwlist -server=/.go141.com/127.0.0.1#7913 -ipset=/.go141.com/gfwlist -server=/.showtime.jp/127.0.0.1#7913 -ipset=/.showtime.jp/gfwlist -server=/.bakgeekhome.tk/127.0.0.1#7913 -ipset=/.bakgeekhome.tk/gfwlist -server=/.etaa.org.au/127.0.0.1#7913 -ipset=/.etaa.org.au/gfwlist -server=/.bloombergview.com/127.0.0.1#7913 -ipset=/.bloombergview.com/gfwlist -server=/.eromangadouzin.com/127.0.0.1#7913 -ipset=/.eromangadouzin.com/gfwlist -server=/.al-islam.com/127.0.0.1#7913 -ipset=/.al-islam.com/gfwlist -server=/.aofriend.com.au/127.0.0.1#7913 -ipset=/.aofriend.com.au/gfwlist -server=/.wo3t.wordpress.com/127.0.0.1#7913 -ipset=/.wo3t.wordpress.com/gfwlist -server=/.googlemashups.com/127.0.0.1#7913 -ipset=/.googlemashups.com/gfwlist -server=/.entermap.com/127.0.0.1#7913 -ipset=/.entermap.com/gfwlist -server=/.apetube.com/127.0.0.1#7913 -ipset=/.apetube.com/gfwlist -server=/.googlelabs.com/127.0.0.1#7913 -ipset=/.googlelabs.com/gfwlist -server=/.h528.com/127.0.0.1#7913 -ipset=/.h528.com/gfwlist -server=/.141tube.com/127.0.0.1#7913 -ipset=/.141tube.com/gfwlist -server=/.emulefans.com/127.0.0.1#7913 -ipset=/.emulefans.com/gfwlist -server=/.justdied.com/127.0.0.1#7913 -ipset=/.justdied.com/gfwlist -server=/.rsf-chinese.org/127.0.0.1#7913 -ipset=/.rsf-chinese.org/gfwlist -server=/.1dumb.com/127.0.0.1#7913 -ipset=/.1dumb.com/gfwlist -server=/.boxun.tv/127.0.0.1#7913 -ipset=/.boxun.tv/gfwlist -server=/.dns1.us/127.0.0.1#7913 -ipset=/.dns1.us/gfwlist -server=/.6park.com/127.0.0.1#7913 -ipset=/.6park.com/gfwlist -server=/.fangongheike.com/127.0.0.1#7913 -ipset=/.fangongheike.com/gfwlist -server=/.muzi.com/127.0.0.1#7913 -ipset=/.muzi.com/gfwlist -server=/.dlsite.com/127.0.0.1#7913 -ipset=/.dlsite.com/gfwlist -server=/.digiland.tw/127.0.0.1#7913 -ipset=/.digiland.tw/gfwlist -server=/.google.to/127.0.0.1#7913 -ipset=/.google.to/gfwlist -server=/.chromecast.com/127.0.0.1#7913 -ipset=/.chromecast.com/gfwlist -server=/.bangbrosnetwork.com/127.0.0.1#7913 -ipset=/.bangbrosnetwork.com/gfwlist -server=/.barnabu.co.uk/127.0.0.1#7913 -ipset=/.barnabu.co.uk/gfwlist -server=/.destroy-china.jp/127.0.0.1#7913 -ipset=/.destroy-china.jp/gfwlist -server=/.bx.tl/127.0.0.1#7913 -ipset=/.bx.tl/gfwlist -server=/.s3-ap-northeast-1.amazonaws.com/127.0.0.1#7913 -ipset=/.s3-ap-northeast-1.amazonaws.com/gfwlist -server=/.blogspot.jp/127.0.0.1#7913 -ipset=/.blogspot.jp/gfwlist -server=/.fatbtc.com/127.0.0.1#7913 -ipset=/.fatbtc.com/gfwlist diff --git a/lienol/luci-app-passwall/root/usr/share/passwall/rules/proxy_host b/lienol/luci-app-passwall/root/usr/share/passwall/rules/proxy_host deleted file mode 100644 index a47f8d8..0000000 --- a/lienol/luci-app-passwall/root/usr/share/passwall/rules/proxy_host +++ /dev/null @@ -1,144 +0,0 @@ -abc.com -abema.tv -acast.com -adblockplus.org -adswizz.com -agkn.com -akadns.net -akam.net -akamai.com -akamai.net -akamaiedge.net -akamaihd.net -akamaistream.net -akamaitech.net -akamaitechnologies.com -akamaitechnologies.fr -akamaized.net -amazon-adsystem.com -amazon.co.jp -amazon.co.uk -amazon.com -amazon.de -amazonvideo.com -amctv.com -bahamut.com.tw -beinsportsconnect.net -beinsportsconnect.tv -blinkbox.com -brightcove.com -caddyserver.com -cbs.com -cloudflare-dns.com -cloudfront.net -conviva.com -crackle.com -crunchyroll.com -crwdcntrl.net -cwtv.com -disney.com -disneyjunior.com -dns.google -dns.quad9.net -easylist-downloads.adblockplus.org -edgecastcdn.net -edgekey.net -edgesuite.net -fast.com -fig.bbc.co.uk -footprint.net -formyip.com -fox.com -gamer.com.tw -gandi.net -ggpht.com -github-production-release-asset-2e65be.s3.amazonaws.com -github.com -github.io -githubapp.com -githubassets.com -githubusercontent.com -gnews.org -go.com -google.com -google.com.hk -google.com.tw -googleapis.com -googletagmanager.com -googleusercontent.com -googlevideo.com -gstatic.com -gvt2.com -happyon.jp -hbo.com -hbogo.com -hbonow.com -hinet.net -hulu.com -hulu.jp -huluad.com -huluim.com -hulustream.com -ifconfig.co -imrworldwide.com -ip2location.com -justmysocks.net -level3.net -line.me -llnwd.net -lovefilm.com -maxmind.com -mog.com -movetv.com -msi.com -mtv.com -mtvnservices.com -mytvsuper.com -naver.com -naver.jp -nbc.com -nbcuni.com -netflix.com -netflix.net -nflxext.com -nflximg.com -nflximg.net -nflxso.net -nflxvideo.net -omtrdc.net -one.one.one.one -open.live.bbc.co.uk -openwrt.proxy.ustclug.org -openx.net -optus.com.au -optusnet.com.au -pandora.com -pbs.org -playstation.net -primevideo.com -pubmatic.com -radiotime.com -sa.bbc.co.uk -sho.com -sling.com -southpark.cc.com -spike.com -srip.net -stripe.com -theplatform.com -ttvnw.net -turner.com -turnin.com -tvb.com -twitch.tv -uplynk.com -v2fly.org -vudu.com -warnerbros.com -wdtvlive.com -www.bbc.co.uk -xboxlive.com -youtu.be -youtube.com -ytimg.com -zerotier.com diff --git a/lienol/luci-app-passwall/root/usr/share/passwall/subscribe.lua b/lienol/luci-app-passwall/root/usr/share/passwall/subscribe.lua deleted file mode 100644 index 8eeb439..0000000 --- a/lienol/luci-app-passwall/root/usr/share/passwall/subscribe.lua +++ /dev/null @@ -1,935 +0,0 @@ -#!/usr/bin/lua - ------------------------------------------------- --- @author William Chan ------------------------------------------------- -require 'nixio' -require 'luci.model.uci' -require 'luci.util' -require 'luci.jsonc' -require 'luci.sys' -local api = require "luci.model.cbi.passwall.api.api" - --- 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 node_num = ucic2:get(application, "@global_other[0]", protocol .. "_node_num") or 1 - for i = 1, node_num, 1 do - local name = string.upper(protocol) - local szType = "@global[0]" - local option = protocol .. "_node" .. i - - local node = ucic2:get(application, szType, option) - local currentNode - if node then - currentNode = ucic2:get_all(application, node) - end - CONFIG[#CONFIG + 1] = { - log = true, - remarks = name .. "节点" .. i, - node = node, - currentNode = currentNode, - set = function(server) - ucic2:set(application, szType, option, server) - end - } - end - end - import_config("tcp") - import_config("udp") - - ucic2:foreach(application, "socks", function(t) - local node = t.node - local currentNode - if node then - currentNode = ucic2:get_all(application, node) - end - CONFIG[#CONFIG + 1] = { - log = true, - remarks = "Socks节点" .. t[".name"], - currentNode = currentNode, - set = function(server) - ucic2:set(application, t[".name"], "node", server) - end - } - end) - - local tcp_main1 = ucic2:get(application, "@auto_switch[0]", "tcp_main1") or "nil" - CONFIG[#CONFIG + 1] = { - log = false, - remarks = "自动切换TCP_1主节点", - currentNode = ucic2:get_all(application, tcp_main1), - set = function(server) - ucic2:set(application, "@auto_switch[0]", "tcp_main1", server) - end - } - - local tcp_node1_table = ucic2:get(application, "@auto_switch[0]", "tcp_node1") - if tcp_node1_table then - local nodes = {} - local new_nodes = {} - for k,v in ipairs(tcp_node1_table) do - local node = v - local currentNode - if node then - currentNode = ucic2:get_all(application, node) - end - nodes[#nodes + 1] = { - log = false, - node = node, - currentNode = currentNode, - remarks = node, - set = function(server) - for kk, vv in pairs(CONFIG) do - if (vv.remarks == "自动切换TCP_1节点列表") then - table.insert(vv.new_nodes, server) - end - end - end - } - end - CONFIG[#CONFIG + 1] = { - remarks = "自动切换TCP_1节点列表", - nodes = nodes, - new_nodes = new_nodes, - set = function() - for kk, vv in pairs(CONFIG) do - if (vv.remarks == "自动切换TCP_1节点列表") then - log("刷新自动切换列表") - ucic2:set_list(application, "@auto_switch[0]", "tcp_node1", vv.new_nodes) - end - end - end - } - end - - ucic2:foreach(application, uciType, function(node) - if node.type == 'V2ray' 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 - local _node - if _node_id then - _node = ucic2:get_all(application, _node_id) - end - CONFIG[#CONFIG + 1] = { - log = false, - currentNode = _node, - remarks = "V2ray分流" .. e.remarks .. "节点", - set = function(server) - ucic2:set(application, node_id, e[".name"], server) - end - } - end) - - local default_node_id = node.default_node - local default_node - if default_node_id then - default_node = ucic2:get_all(application, default_node_id) - end - CONFIG[#CONFIG + 1] = { - log = false, - currentNode = default_node, - remarks = "V2ray分流默认节点", - set = function(server) - ucic2:set(application, node_id, "default_node", server) - end - } - elseif node.type == 'V2ray' and node.protocol == '_balancing' then - local node_id = node[".name"] - local nodes = {} - local new_nodes = {} - if node.balancing_node then - for k, v in pairs(node.balancing_node) do - local node = v - local currentNode - if node then - currentNode = ucic2:get_all(application, node) - end - nodes[#nodes + 1] = { - log = false, - node = node, - currentNode = currentNode, - remarks = node, - set = function(server) - for kk, vv in pairs(CONFIG) do - if (vv.remarks == "V2ray负载均衡节点列表" .. node_id) then - table.insert(vv.new_nodes, server) - end - end - end - } - end - end - CONFIG[#CONFIG + 1] = { - remarks = "V2ray负载均衡节点列表" .. node_id, - nodes = nodes, - new_nodes = new_nodes, - set = function() - for kk, vv in pairs(CONFIG) do - if (vv.remarks == "V2ray负载均衡节点列表" .. node_id) then - log("刷新V2ray负载均衡节点列表") - 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_enabled = ucic2:get(application, "@global_subscribe[0]", "filter_enabled") -local filter_keyword_table = ucic2:get(application, "@global_subscribe[0]", "filter_keyword") -local filter_keyword_discarded = ucic2:get(application, "@global_subscribe[0]", "filter_keyword_discarded") -local function is_filter_keyword(value) - if filter_keyword_enabled and filter_keyword_enabled == "1" then - if filter_keyword_table then - if filter_keyword_discarded and filter_keyword_discarded == "1" then - for k,v in ipairs(filter_keyword_table) do - if value:find(v) then - return true - end - end - else - local result = true - for k,v in ipairs(filter_keyword_table) do - if value:find(v) then - result = false - end - end - return result - end - end - 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 = 'V2ray' - result.address = info.add - result.port = info.port - result.protocol = 'vmess' - result.transport = info.net - 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' then - 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 - if not info.security then result.security = "auto" end - if info.tls == "tls" or info.tls == "1" then - result.stream_security = "tls" - result.tls_serverName = info.host - result.tls_allowInsecure = allowInsecure_default and "1" or "0" - else - result.stream_security = "none" - 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 - 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.remarks = UrlDecode(alias) - 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.type = "Trojan-Plus" - result.remarks = UrlDecode(alias) - 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.mux and params.mux == "1" then result.mux = "1" end - 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.mux or result.trojan_transport == "ws" or result.ss_aead then - result.type = "Trojan-Go" - result.fingerprint = "firefox" - end - result.stream_security = 'tls' - 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.type = "Trojan-Go" - result.remarks = UrlDecode(alias) - 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.mux and params.mux == "1" then result.mux = "1" end - 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.stream_security = 'tls' - result.tls_serverName = peer and peer or sni - result.tls_allowInsecure = allowInsecure and "1" or "0" - 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 - 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() - local is_stop = 0 - local function clear(type) - local node_num = ucic2:get(application, "@global_other[0]", type .. "_node_num") or 1 - for i = 1, node_num, 1 do - local node = ucic2:get(application, "@global[0]", type .. "_node" .. i) - if node then - local is_sub_node = ucic2:get(application, node, "is_sub") or 0 - if is_sub_node == "1" then - is_stop = 1 - ucic2:set(application, '@global[0]', type .. "_node" .. i, "nil") - end - end - end - end - clear("tcp") - clear("udp") - - ucic2:foreach(application, "socks", function(t) - local node = t.node - if node then - local is_sub_node = ucic2:get(application, node, "is_sub") or 0 - if is_sub_node == "1" then - is_stop = 1 - ucic2:set(application, t[".name"], "node", "nil") - 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) - - if is_stop == 1 then - luci.sys.call("/etc/init.d/" .. application .. " restart > /dev/null 2>&1 &") -- 不加&的话日志会出现的更早 - end - log('在线订阅节点已全部删除') -end - -local function select_node(nodes, config) - local server - if config.currentNode then - -- 特别优先级 V2ray分流 + 备注 - if config.currentNode.type == 'V2ray' and config.currentNode.protocol == '_shunt' then - for id, node in pairs(nodes) do - if node.remarks == config.currentNode.remarks then - log('选择【' .. config.remarks .. '】V2ray分流匹配节点:' .. node.remarks) - server = id - break - end - end - end - -- 特别优先级 V2ray负载均衡 + 备注 - if config.currentNode.type == 'V2ray' and config.currentNode.protocol == '_balancing' then - for id, node in pairs(nodes) do - if node.remarks == config.currentNode.remarks then - log('选择【' .. config.remarks .. '】V2ray负载均衡匹配节点:' .. node.remarks) - server = id - break - end - end - end - -- 第一优先级 cfgid - if not server then - for id, node in pairs(nodes) do - if id == config.currentNode['.name'] then - if config.log == nil or config.log == true then - log('选择【' .. config.remarks .. '】第一匹配节点:' .. node.remarks) - end - server = id - break - end - end - end - -- 第二优先级 类型 + IP + 端口 - if not server then - for id, node in pairs(nodes) do - 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 = id - break - end - end - end - end - -- 第三优先级 IP + 端口 - if not server then - for id, node in pairs(nodes) do - 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 = id - break - end - end - end - end - -- 第四优先级 IP - if not server then - for id, node in pairs(nodes) do - 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 = id - break - end - end - end - end - -- 第五优先级备注 - if not server then - for id, node in pairs(nodes) do - 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 = id - break - 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(server) - end -end - -local function update_node(manual) - if next(nodeResult) == nil then - log("更新失败,没有可用的节点信息") - return - end - -- delet 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[node['.name']] = 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() - 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 - for kk, vv in pairs(v.new_nodes) do - print(vv) - end - else - print(v.new_nodes) - end - end - ]]-- - - ucic2:commit(application) - luci.sys.call("/etc/init.d/" .. application .. " restart > /dev/null 2>&1 &") -- 不加&的话日志会出现的更早 - end -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 - result.address:match("[^0-9a-zA-Z%-%_%.%s]") or -- 中文做地址的 也没有人拿中文域名搞,就算中文域也有Puny Code SB 机场 - not result.address:find("%.") or -- 虽然没有.也算域,不过应该没有人会这样干吧 - result.address:sub(#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/lienol/luci-app-passwall/root/usr/share/passwall/test.sh b/lienol/luci-app-passwall/root/usr/share/passwall/test.sh deleted file mode 100755 index 8baca8a..0000000 --- a/lienol/luci-app-passwall/root/usr/share/passwall/test.sh +++ /dev/null @@ -1,193 +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 index=$3 - local b_tcp_nodes=$4 - local now_node - if [ -f "/var/etc/$CONFIG/id/${type}_${index}" ]; then - now_node=$(cat /var/etc/$CONFIG/id/${type}_${index}) - else - return 1 - fi - - status=$(test_proxy) - if [ "$status" == 0 ]; then - echolog "自动切换检测:${type}_${index}节点$(config_n_get $now_node type) $(config_n_get $now_node address) $(config_n_get $now_node port)正常。" - #检测主节点是否能使用 - local main_node=$(config_t_get auto_switch tcp_main1) - if [ "$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" - else - local tmp_port=$(/usr/share/passwall/app.sh get_new_port 61080 tcp) - /usr/share/passwall/app.sh run_socks "$main_node" "127.0.0.1" "$tmp_port" "/var/etc/passwall/auto_switch_$index.json" "10" - local curlx="socks5h://127.0.0.1:$tmp_port" - fi - sleep 10s - proxy_status=$(test_url "https://www.google.com/generate_204" 3 3 "-x $curlx") - ps -w | grep -v "grep" | grep "/var/etc/passwall/auto_switch_$index.json" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 - if [ "$proxy_status" -eq 200 ]; then - #主节点正常,切换到主节点 - echolog "自动切换检测:${type}_${index}主节点正常,切换到主节点!" - /usr/share/passwall/app.sh node_switch $type $2 $index $main_node - return 0 - fi - fi - return 0 - elif [ "$status" == 2 ]; then - echolog "自动切换检测:无法连接到网络,请检查网络是否正常!" - return 2 - elif [ "$status" == 1 ]; then - echolog "自动切换检测:${type}_${index}节点异常,开始切换节点!" - - #检测主节点是否能使用 - local main_node=$(config_t_get auto_switch tcp_main1) - if [ "$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" - else - local tmp_port=$(/usr/share/passwall/app.sh get_new_port 61080 tcp) - /usr/share/passwall/app.sh run_socks "$main_node" "127.0.0.1" "$tmp_port" "/var/etc/passwall/auto_switch_$index.json" "10" - local curlx="socks5h://127.0.0.1:$tmp_port" - fi - sleep 10s - proxy_status=$(test_url "https://www.google.com/generate_204" 3 3 "-x $curlx") - ps -w | grep -v "grep" | grep "/var/etc/passwall/auto_switch_$index.json" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 - if [ "$proxy_status" -eq 200 ]; then - #主节点正常,切换到主节点 - echolog "自动切换检测:${type}_${index}主节点正常,切换到主节点!" - /usr/share/passwall/app.sh node_switch $type $2 $index $main_node - return 0 - fi - fi - - 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/passwall/app.sh node_switch $type $2 $index $new_node - sleep 10s - # 切换节点后等待10秒后再检测一次,如果还是不通继续切,直到可用为止 - status2=$(test_proxy) - if [ "$status2" -eq 0 ]; then - echolog "自动切换检测:${type}_${index}节点切换完毕!" - return 0 - elif [ "$status2" -eq 1 ]; then - test_auto_switch $1 $2 $3 "$4" - elif [ "$status2" -eq 2 ]; then - return 2 - fi - fi -} - -start() { - ( - flock -xn 200 - [ "$?" != "0" ] && exit 0 - - 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 - while [ "$ENABLED" -eq 1 ] - do - # TCP_NODE_NUM=$(config_t_get global_other tcp_node_num 1) - # 暂时只能检测TCP1 - TCP_NODE_NUM=1 - for i in $(seq 1 $TCP_NODE_NUM); do - eval TCP_NODE$i=\"$(config_t_get auto_switch tcp_node$i nil)\" - eval tmp=\$TCP_NODE$i - [ -n "$tmp" -a "$tmp" != "nil" ] && { - test_auto_switch TCP tcp $i "$tmp" - } - done - delay=$(config_t_get auto_switch testing_time 1) - sleep ${delay}m - done - ) 200>"/var/lock/passwall_auto_switch.lock" -} - -case $1 in -test_url) - test_url $2 - ;; -*) - start - ;; -esac diff --git a/lienol/luci-app-pppoe-relay/Makefile b/lienol/luci-app-pppoe-relay/Makefile deleted file mode 100755 index b144c1c..0000000 --- a/lienol/luci-app-pppoe-relay/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 PPPoE Relay -LUCI_DEPENDS:=+rp-pppoe-common +rp-pppoe-relay -LUCI_PKGARCH:=all -PKG_VERSION:=1 -PKG_RELEASE:=2-20200326 - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature diff --git a/lienol/luci-app-pppoe-relay/luasrc/controller/pppoe-relay.lua b/lienol/luci-app-pppoe-relay/luasrc/controller/pppoe-relay.lua deleted file mode 100755 index 6b3598d..0000000 --- a/lienol/luci-app-pppoe-relay/luasrc/controller/pppoe-relay.lua +++ /dev/null @@ -1,29 +0,0 @@ --- Copyright 2018-2019 Lienol -module("luci.controller.pppoe-relay", package.seeall) -local uci = require"luci.model.uci".cursor() - -function index() - if not nixio.fs.access("/etc/config/pppoe-relay") then return end - entry({"admin", "services", "pppoe-relay"}, cbi("pppoe-relay"), - _("PPPoE Relay"), 2).dependent = true - entry({"admin", "services", "pppoe-relay", "get_status"}, call("get_status")).leaf = - true -end - -function get_status() - local json = {} - json.status = false - json.index = luci.http.formvalue("index") - local section = luci.http.formvalue("section") - local server_interface = uci:get("pppoe-relay", section, "server_interface") - local client_interface = uci:get("pppoe-relay", section, "client_interface") - if server_interface and client_interface then - status = luci.sys.call("ps | grep '/usr/sbin/pppoe-relay -S " .. - server_interface .. " -C " .. - client_interface .. - "' | grep -v 'grep' >/dev/null") - if status == 0 then json.status = true end - end - luci.http.prepare_content("application/json") - luci.http.write_json(json) -end diff --git a/lienol/luci-app-pppoe-relay/luasrc/model/cbi/pppoe-relay.lua b/lienol/luci-app-pppoe-relay/luasrc/model/cbi/pppoe-relay.lua deleted file mode 100755 index 81382c6..0000000 --- a/lienol/luci-app-pppoe-relay/luasrc/model/cbi/pppoe-relay.lua +++ /dev/null @@ -1,47 +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-relay", translate("PPPoE Relay")) -m.description = translate( - "Opening the PPPoE relay allows devices in the Intranet to create a separate PPPoE connection that can cross NAT.") - -s = m:section(TypedSection, "service") -s.addremove = true -s.anonymous = true -s.template = "cbi/tblsection" - -o = s:option(Flag, "enabled", translate("Enabled")) -o.rmempty = false - -o = s:option(DummyValue, "status", translate("Current Condition")) -o.template = "pppoe-relay/status" - -o = s:option(ListValue, "server_interface", translate("Server Interface")) -for _, iface in ipairs(ifaces) do - if not (iface == "lo" or iface:match("^ifb.*") or iface:match("gre*")) 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(ListValue, "client_interface", translate("Client Interface")) -for _, iface in ipairs(ifaces) do - if not (iface == "lo" or iface:match("^ifb.*") or iface:match("gre*")) 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 - -m:append(Template("pppoe-relay/ajax")) - -return m diff --git a/lienol/luci-app-pppoe-relay/luasrc/view/pppoe-relay/ajax.htm b/lienol/luci-app-pppoe-relay/luasrc/view/pppoe-relay/ajax.htm deleted file mode 100755 index 569ff61..0000000 --- a/lienol/luci-app-pppoe-relay/luasrc/view/pppoe-relay/ajax.htm +++ /dev/null @@ -1,26 +0,0 @@ -<% -local dsp = require "luci.dispatcher" --%> - - \ No newline at end of file diff --git a/lienol/luci-app-pppoe-relay/luasrc/view/pppoe-relay/status.htm b/lienol/luci-app-pppoe-relay/luasrc/view/pppoe-relay/status.htm deleted file mode 100755 index c4ade2b..0000000 --- a/lienol/luci-app-pppoe-relay/luasrc/view/pppoe-relay/status.htm +++ /dev/null @@ -1,3 +0,0 @@ -<%+cbi/valueheader%> -<%=pcdata(self:cfgvalue(section) or self.default or "")%> -<%+cbi/valuefooter%> diff --git a/lienol/luci-app-pppoe-relay/po/zh-cn/pppoe-relay.po b/lienol/luci-app-pppoe-relay/po/zh-cn/pppoe-relay.po deleted file mode 100755 index e1a0c10..0000000 --- a/lienol/luci-app-pppoe-relay/po/zh-cn/pppoe-relay.po +++ /dev/null @@ -1,23 +0,0 @@ -msgid "PPPoE Relay" -msgstr "PPPoE 穿透" - -msgid "Opening the PPPoE relay allows devices in the Intranet to create a separate PPPoE connection that can cross NAT." -msgstr "开启 PPPoE 中继允许内网中的设备创建一个可穿过 NAT 的独立 PPPoE 连接" - -msgid "Enable or disable the PPPoE Relay" -msgstr "启用或禁用PPPoE穿透" - -msgid "Server Interface" -msgstr "服务端接口" - -msgid "Specify the PPPoE server interface" -msgstr "指定PPPoE服务器接口" - -msgid "Client Interface" -msgstr "客户端接口" - -msgid "Specify the PPPoE client interface" -msgstr "指定PPPoE客户端接口" - -msgid "Enabled" -msgstr "启用" \ No newline at end of file diff --git a/lienol/luci-app-pppoe-relay/root/etc/config/pppoe-relay b/lienol/luci-app-pppoe-relay/root/etc/config/pppoe-relay deleted file mode 100755 index 8b13789..0000000 --- a/lienol/luci-app-pppoe-relay/root/etc/config/pppoe-relay +++ /dev/null @@ -1 +0,0 @@ - diff --git a/lienol/luci-app-pppoe-relay/root/etc/init.d/pppoe-relay b/lienol/luci-app-pppoe-relay/root/etc/init.d/pppoe-relay deleted file mode 100755 index 0cdd6ea..0000000 --- a/lienol/luci-app-pppoe-relay/root/etc/init.d/pppoe-relay +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2018-2020 Lienol - -START=99 - -CONFIG="pppoe-relay" - -setup_service() { - config_get enabled $1 enabled - [ "$enabled" -eq 0 ] && return 0 - config_get server_interface $1 server_interface - config_get client_interface $1 client_interface - [ -n "$server_interface" -a -n "$client_interface" ] && { - is_run=$(ps | grep "/usr/sbin/pppoe-relay -S $server_interface -C $client_interface" | grep -v "grep") - [ -z "$is_run" ] && /usr/sbin/pppoe-relay -S $server_interface -C $client_interface - } -} - -start() { - config_load $CONFIG - config_foreach setup_service service -} - -stop() { - killall -q -9 pppoe-relay -} diff --git a/lienol/luci-app-pppoe-relay/root/etc/uci-defaults/luci-app-pppoe-relay b/lienol/luci-app-pppoe-relay/root/etc/uci-defaults/luci-app-pppoe-relay deleted file mode 100755 index 287888b..0000000 --- a/lienol/luci-app-pppoe-relay/root/etc/uci-defaults/luci-app-pppoe-relay +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@pppoe-relay[-1] - add ucitrack pppoe-relay - set ucitrack.@pppoe-relay[-1].init=pppoe-relay - commit ucitrack -EOF - -rm -f /tmp/luci-indexcache -exit 0 diff --git a/lienol/luci-app-pppoe-relay/root/usr/share/rpcd/acl.d/luci-app-pppoe-relay.json b/lienol/luci-app-pppoe-relay/root/usr/share/rpcd/acl.d/luci-app-pppoe-relay.json deleted file mode 100644 index 0d7f329..0000000 --- a/lienol/luci-app-pppoe-relay/root/usr/share/rpcd/acl.d/luci-app-pppoe-relay.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "luci-app-pppoe-relay": { - "description": "Grant UCI access for luci-app-pppoe-relay", - "read": { - "uci": [ "pppoe-relay" ] - }, - "write": { - "uci": [ "pppoe-relay" ] - } - } -} diff --git a/lienol/luci-app-pppoe-server/Makefile b/lienol/luci-app-pppoe-server/Makefile deleted file mode 100755 index 6801916..0000000 --- a/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/lienol/luci-app-pppoe-server/luasrc/controller/pppoe-server.lua b/lienol/luci-app-pppoe-server/luasrc/controller/pppoe-server.lua deleted file mode 100755 index a3add48..0000000 --- a/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/lienol/luci-app-pppoe-server/luasrc/model/cbi/pppoe-server/online.lua b/lienol/luci-app-pppoe-server/luasrc/model/cbi/pppoe-server/online.lua deleted file mode 100755 index f5fa646..0000000 --- a/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/lienol/luci-app-pppoe-server/luasrc/model/cbi/pppoe-server/settings.lua b/lienol/luci-app-pppoe-server/luasrc/model/cbi/pppoe-server/settings.lua deleted file mode 100755 index d78315f..0000000 --- a/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/lienol/luci-app-pppoe-server/luasrc/model/cbi/pppoe-server/users.lua b/lienol/luci-app-pppoe-server/luasrc/model/cbi/pppoe-server/users.lua deleted file mode 100755 index 08c3075..0000000 --- a/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/lienol/luci-app-pppoe-server/luasrc/view/pppoe-server/index.htm b/lienol/luci-app-pppoe-server/luasrc/view/pppoe-server/index.htm deleted file mode 100755 index 817462e..0000000 --- a/lienol/luci-app-pppoe-server/luasrc/view/pppoe-server/index.htm +++ /dev/null @@ -1,13 +0,0 @@ -<% include("cbi/map") %> - diff --git a/lienol/luci-app-pppoe-server/luasrc/view/pppoe-server/status.htm b/lienol/luci-app-pppoe-server/luasrc/view/pppoe-server/status.htm deleted file mode 100755 index 4f937f0..0000000 --- a/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/lienol/luci-app-pppoe-server/po/zh-cn/pppoe-server.po b/lienol/luci-app-pppoe-server/po/zh-cn/pppoe-server.po deleted file mode 100755 index d48c2f9..0000000 --- a/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/lienol/luci-app-pppoe-server/root/etc/config/pppoe-server b/lienol/luci-app-pppoe-server/root/etc/config/pppoe-server deleted file mode 100755 index 971a561..0000000 --- a/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/lienol/luci-app-pppoe-server/root/etc/init.d/pppoe-server b/lienol/luci-app-pppoe-server/root/etc/init.d/pppoe-server deleted file mode 100755 index fb352af..0000000 --- a/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/lienol/luci-app-pppoe-server/root/etc/uci-defaults/luci-app-pppoe-server b/lienol/luci-app-pppoe-server/root/etc/uci-defaults/luci-app-pppoe-server deleted file mode 100755 index 96c9588..0000000 --- a/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/lienol/luci-app-pppoe-server/root/usr/share/rpcd/acl.d/luci-app-pppoe-server.json b/lienol/luci-app-pppoe-server/root/usr/share/rpcd/acl.d/luci-app-pppoe-server.json deleted file mode 100644 index 529c92c..0000000 --- a/lienol/luci-app-pppoe-server/root/usr/share/rpcd/acl.d/luci-app-pppoe-server.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "luci-app-pppoe-server": { - "description": "Grant UCI access for luci-app-pppoe-server", - "read": { - "uci": [ "pppoe-server" ] - }, - "write": { - "uci": [ "pppoe-server" ] - } - } -} diff --git a/lienol/luci-app-pptp-vpnserver-manyusers/Makefile b/lienol/luci-app-pptp-vpnserver-manyusers/Makefile deleted file mode 100755 index 08d8bcd..0000000 --- a/lienol/luci-app-pptp-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 PPTP VPN Server -LUCI_DEPENDS:=+pptpd +kmod-mppe +ppp -LUCI_PKGARCH:=all -PKG_VERSION:=1 -PKG_RELEASE:=5-20200608 - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature diff --git a/lienol/luci-app-pptp-vpnserver-manyusers/luasrc/controller/pptpd.lua b/lienol/luci-app-pptp-vpnserver-manyusers/luasrc/controller/pptpd.lua deleted file mode 100755 index 4877186..0000000 --- a/lienol/luci-app-pptp-vpnserver-manyusers/luasrc/controller/pptpd.lua +++ /dev/null @@ -1,24 +0,0 @@ --- Copyright 2018-2019 Lienol -module("luci.controller.pptpd", package.seeall) - -function index() - if not nixio.fs.access("/etc/config/pptpd") then return end - - entry({"admin", "vpn"}, firstchild(), "VPN", 45).dependent = false - entry({"admin", "vpn", "pptpd"}, alias("admin", "vpn", "pptpd", "settings"), - _("PPTP VPN Server"), 48) - entry({"admin", "vpn", "pptpd", "settings"}, cbi("pptpd/settings"), - _("General Settings"), 10).leaf = true - entry({"admin", "vpn", "pptpd", "users"}, cbi("pptpd/users"), - _("Users Manager"), 20).leaf = true - entry({"admin", "vpn", "pptpd", "online"}, cbi("pptpd/online"), - _("Online Users"), 30).leaf = true - entry({"admin", "vpn", "pptpd", "status"}, call("status")).leaf = true -end - -function status() - local e = {} - e.status = luci.sys.call("pidof %s >/dev/null" % "pptpd") == 0 - luci.http.prepare_content("application/json") - luci.http.write_json(e) -end diff --git a/lienol/luci-app-pptp-vpnserver-manyusers/luasrc/model/cbi/pptpd/online.lua b/lienol/luci-app-pptp-vpnserver-manyusers/luasrc/model/cbi/pptpd/online.lua deleted file mode 100755 index e365492..0000000 --- a/lienol/luci-app-pptp-vpnserver-manyusers/luasrc/model/cbi/pptpd/online.lua +++ /dev/null @@ -1,80 +0,0 @@ -local e = {} -local o = require "luci.dispatcher" -local a = luci.util.execi("/bin/busybox top -bn1 | grep '/usr/sbin/pppd'") -for t in a do - local a, n, h, s, o, i = t:match( - "^ *(%d+) +(%d+) +.+options%.pptpd +(%d+) +(%S.-%S)%:(%S.-%S) +.+ +(.+)") - local t = tonumber(a) - if t then - e["%02i.%s" % {t, "online"}] = { - ['PID'] = a, - ['PPID'] = n, - ['SPEED'] = h, - ['GATEWAY'] = s, - ['VIP'] = o, - ['CIP'] = i, - ['BLACKLIST'] = 0 - } - end -end -local a = luci.util.execi("sed = /etc/firewall.user | sed 'N;s/\\n/:/'") -for t in a do - local t, a = t:match("^ *(%d+)%:.+%#%# pptpd%-blacklist%-(.+)") - local t = tonumber(t) - if t then - e["%02i.%s" % {t, "blacklist"}] = - { - ['PID'] = "-1", - ['PPID'] = "-1", - ['SPEED'] = "-1", - ['GATEWAY'] = "-", - ['VIP'] = "-", - ['CIP'] = a, - ['BLACKLIST'] = 1 - } - end -end -f = SimpleForm("processes", translate("PPTP VPN Server")) -f.reset = false -f.submit = false -f.description = translate( - "Simple, quick and convenient PPTP VPN, universal across the platform") -t = f:section(Table, e, translate("Online Users")) -t:option(DummyValue, "GATEWAY", translate("Server IP")) -t:option(DummyValue, "VIP", translate("Client IP")) -t:option(DummyValue, "CIP", translate("IP address")) -blacklist = t:option(Button, "_blacklist", translate("Blacklist")) -function blacklist.render(e, t, a) - if e.map:get(t, "BLACKLIST") == 0 then - e.title = translate("Add to Blacklist") - e.inputstyle = "remove" - else - e.title = translate("Remove from Blacklist") - e.inputstyle = "apply" - end - Button.render(e, t, a) -end -function blacklist.write(t, a) - local e = t.map:get(a, "CIP") - if t.map:get(a, "BLACKLIST") == 0 then - luci.util.execi( - "echo 'iptables -A input_rule -s %s -p tcp --dport 1723 -j DROP ## pptpd-blacklist-%s' >> /etc/firewall.user" % - {e, e}) - luci.util.execi( - "iptables -A input_rule -s %s -p tcp --dport 1723 -j DROP" % {e}) - null, t.tag_error[a] = luci.sys.process.signal(t.map:get(a, "PID"), 9) - else - luci.util.execi( - "sed -i -e '/## pptpd-blacklist-%s/d' /etc/firewall.user" % {e}) - luci.util.execi( - "iptables -D input_rule -s %s -p tcp --dport 1723 -j DROP" % {e}) - end - luci.http.redirect(o.build_url("admin/vpn/pptpd/online")) -end -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/vpn/pptpd/online")) -end -return f diff --git a/lienol/luci-app-pptp-vpnserver-manyusers/luasrc/model/cbi/pptpd/settings.lua b/lienol/luci-app-pptp-vpnserver-manyusers/luasrc/model/cbi/pptpd/settings.lua deleted file mode 100755 index b34b1eb..0000000 --- a/lienol/luci-app-pptp-vpnserver-manyusers/luasrc/model/cbi/pptpd/settings.lua +++ /dev/null @@ -1,45 +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("pptpd", translate("PPTP VPN Server")) -m.description = translate( - "Simple, quick and convenient PPTP VPN, universal across the platform") -m.template = "pptpd/index" - -s = m:section(TypedSection, "service") -s.anonymous = true - -o = s:option(DummyValue, "pptpd_status", translate("Current Condition")) -o.template = "pptpd/status" -o.value = translate("Collecting data...") - -o = s:option(Flag, "enabled", translate("Enable VPN Server")) -o.rmempty = false - -o = s:option(Value, "localip", translate("Server IP"), - translate("VPN Server IP address, it not required.")) -o.datatype = "ipaddr" -o.placeholder = translate("192.168.1.2") -o.rmempty = true -o.default = "192.168.1.2" - -o = s:option(Value, "remoteip", translate("Client IP"), - translate("VPN Client IP address, it not required.")) -o.placeholder = translate("192.168.1.10-20") -o.rmempty = true -o.default = "192.168.1.10-20" - ---[[ -o = s:option(Value, "dns", translate("DNS IP address"), - translate("This will be sent to the client, it not required.")) -o.placeholder = translate("192.168.1.1") -o.datatype = "ipaddr" -o.rmempty = true -o.default = "192.168.1.1" -]]-- - -o = s:option(Flag, "mppe", translate("Enable MPPE Encryption"), - translate("Allows 128-bit encrypted connection.")) -o.rmempty = false -return m diff --git a/lienol/luci-app-pptp-vpnserver-manyusers/luasrc/model/cbi/pptpd/users.lua b/lienol/luci-app-pptp-vpnserver-manyusers/luasrc/model/cbi/pptpd/users.lua deleted file mode 100755 index e01c35c..0000000 --- a/lienol/luci-app-pptp-vpnserver-manyusers/luasrc/model/cbi/pptpd/users.lua +++ /dev/null @@ -1,19 +0,0 @@ -m = Map("pptpd", translate("PPTP VPN Server")) -m.description = translate( - "Simple, quick and convenient PPTP VPN, universal across the platform") -s = m:section(TypedSection, "users", 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 -return m diff --git a/lienol/luci-app-pptp-vpnserver-manyusers/luasrc/view/pptpd/index.htm b/lienol/luci-app-pptp-vpnserver-manyusers/luasrc/view/pptpd/index.htm deleted file mode 100755 index ac1f295..0000000 --- a/lienol/luci-app-pptp-vpnserver-manyusers/luasrc/view/pptpd/index.htm +++ /dev/null @@ -1,13 +0,0 @@ -<% include("cbi/map") %> - diff --git a/lienol/luci-app-pptp-vpnserver-manyusers/luasrc/view/pptpd/status.htm b/lienol/luci-app-pptp-vpnserver-manyusers/luasrc/view/pptpd/status.htm deleted file mode 100755 index 2811858..0000000 --- a/lienol/luci-app-pptp-vpnserver-manyusers/luasrc/view/pptpd/status.htm +++ /dev/null @@ -1,3 +0,0 @@ -<%+cbi/valueheader%> -<%=pcdata(self:cfgvalue(section) or self.default or "")%> -<%+cbi/valuefooter%> diff --git a/lienol/luci-app-pptp-vpnserver-manyusers/po/zh-cn/pptpd.po b/lienol/luci-app-pptp-vpnserver-manyusers/po/zh-cn/pptpd.po deleted file mode 100755 index 0b766d5..0000000 --- a/lienol/luci-app-pptp-vpnserver-manyusers/po/zh-cn/pptpd.po +++ /dev/null @@ -1,89 +0,0 @@ -msgid "PPTP VPN Server" -msgstr "PPTP VPN 服务器" - -msgid "Simple, quick and convenient PPTP VPN, universal across the platform" -msgstr "简单快捷方便的PPTP VPN,全平台通用。" - -msgid "PPTP VPN Server status" -msgstr "PPTP VPN 服务器运行状态" - -msgid "Current Condition" -msgstr "当前状态" - -msgid "General settings" -msgstr "基本设置" - -msgid "Enable VPN Server" -msgstr "启用 VPN 服务器" - -msgid "Server IP" -msgstr "服务器 IP 地址" - -msgid "VPN Server IP address, it not required." -msgstr "VPN 服务器远程地址,留空将自动设置。" - -msgid "Client IP" -msgstr "客户端 IP 地址" - -msgid "VPN Client IP address, it not required." -msgstr "分配给客户端的 IP 地址范围,留空将自动设置。" - -msgid "DNS IP address" -msgstr "DNS IP 地址" - -msgid "This will be sent to the client, it not required." -msgstr "设置 VPN 服务器默认 DNS 服务器,该设置非必须。" - -msgid "Enable MPPE Encryption" -msgstr "启用MPPE 加密" - -msgid "Allows 128-bit encrypted connection." -msgstr "允许使用 128 位加密连接。" - -msgid "is_nat" -msgstr "NAT转发" - -msgid "Interface" -msgstr "接口" - -msgid "Specify interface forwarding traffic." -msgstr "指定接口转发流量。" - -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 "Blacklist" -msgstr "黑名单" - -msgid "Add to Blacklist" -msgstr "加入黑名单" - -msgid "Remove from Blacklist" -msgstr "移出黑名单" - -msgid "Forced offline" -msgstr "强制下线" - -msgid "NOT RUNNING" -msgstr "未运行" - -msgid "RUNNING" -msgstr "运行中" \ No newline at end of file diff --git a/lienol/luci-app-pptp-vpnserver-manyusers/root/etc/config/pptpd b/lienol/luci-app-pptp-vpnserver-manyusers/root/etc/config/pptpd deleted file mode 100755 index 849d209..0000000 --- a/lienol/luci-app-pptp-vpnserver-manyusers/root/etc/config/pptpd +++ /dev/null @@ -1,12 +0,0 @@ - -config service 'pptpd' - option mppe '1' - option localip '192.168.2.1' - option remoteip '192.168.2.10-20' - option enabled '0' - -config users - option enabled '1' - option username 'guest' - option password '123456' - diff --git a/lienol/luci-app-pptp-vpnserver-manyusers/root/etc/init.d/pptpd b/lienol/luci-app-pptp-vpnserver-manyusers/root/etc/init.d/pptpd deleted file mode 100755 index 74efb75..0000000 --- a/lienol/luci-app-pptp-vpnserver-manyusers/root/etc/init.d/pptpd +++ /dev/null @@ -1,137 +0,0 @@ -#!/bin/sh /etc/rc.common - -START=99 -CONFIG=pptpd -CONFIG_FILE=/var/etc/$CONFIG.conf -RUN_D=/var/run -CHAP_SECRETS=/var/etc/chap-secrets -SERVER_NAME="pptp-server" -TEMP=/tmp/pptpd.tmp - -add_rule() { - iptables -t nat -I POSTROUTING -s ${localip%.*}.0/24 -m comment --comment "PPTP VPN Server" -j MASQUERADE - iptables -I forwarding_rule -s ${localip%.*}.0/24 -m comment --comment "PPTP VPN Server" -j ACCEPT - iptables -I INPUT -p tcp --dport 1723 -m comment --comment "PPTP VPN Server" -j ACCEPT 2>/dev/null -} - -del_rule() { - iptables -D INPUT -p tcp --dport 1723 -m comment --comment "PPTP VPN Server" -j ACCEPT 2> /dev/null - pptp_nums=$(iptables -t nat -n -L POSTROUTING 2>/dev/null | grep -c "PPTP VPN Server") - if [ -n "$pptp_nums" ]; then - until [ "$pptp_nums" = 0 ] - do - pptp_rules=$(iptables -t nat -n -L POSTROUTING --line-num 2>/dev/null | grep "PPTP VPN Server" | awk '{print $1}') - for pptp_rule in $pptp_rules - do - iptables -t nat -D POSTROUTING $pptp_rule 2> /dev/null - break - done - pptp_nums=$(expr $pptp_nums - 1) - done - fi - nums=$(iptables -n -L forwarding_rule 2>/dev/null | grep -c "PPTP VPN Server") - if [ -n "$nums" ]; then - until [ "$nums" = 0 ] - do - rules=$(iptables -n -L forwarding_rule --line-num 2>/dev/null | grep "PPTP 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 -} - -gen_include() { - echo '#!/bin/sh' > /var/etc/$CONFIG.include - extract_rules() { - echo "*$1" - iptables-save -t $1 | grep "PPTP VPN Server" | \ - sed -e "s/^-A \(INPUT\)/-I \1 1/" - echo 'COMMIT' - } - cat <<-EOF >> /var/etc/$CONFIG.include - iptables-save -c | grep -v "PPTP VPN Server" | iptables-restore -c - iptables-restore -n <<-EOT - $(extract_rules filter) - $(extract_rules nat) - EOT - EOF - return 0 -} - -setup_login() { - config_get enabled $1 enabled - [ "$enabled" -eq 0 ] && return 0 - config_get ipaddress $1 ipaddress - [ -n "$ipaddress" ] || local ipaddress="*" - config_get username $1 username - config_get password $1 password - [ -n "$username" ] || return 0 - [ -n "$password" ] || return 0 - echo "$username $SERVER_NAME $password $ipaddress" >> $CHAP_SECRETS -} - -setup_config() { - config_get enabled $1 enabled - [ "$enabled" -eq 0 ] && return 1 - - mkdir -p /var/etc - cp /etc/pptpd.conf $CONFIG_FILE - - config_get localip $1 localip - config_get remoteip $1 remoteip - [ -z "$localip" ] && localip="172.16.100.1" - [ -z "$remoteip" ] && remoteip="172.16.100.10-20" - [ -n "$localip" ] && echo "localip $localip" >> $CONFIG_FILE - [ -n "$remoteip" ] && echo "remoteip $remoteip" >> $CONFIG_FILE - echo "option /etc/ppp/options.pptpd" >> $CONFIG_FILE - - sed -i '/mppe/d' /etc/ppp/options.pptpd - config_get mppe $1 mppe - [ -n "$mppe" ] && [ "$mppe" -eq 1 ] && echo "mppe required,no40,no56,stateless" >> /etc/ppp/options.pptpd - - sed -i '/ms-dns/d' /etc/ppp/options.pptpd - config_get dns $1 dns - [ -z "$dns" ] && dns="8.8.4.4" - echo "ms-dns $dns">>/etc/ppp/options.pptpd - - return 0 -} - -start_pptpd() { - mkdir -p $RUN_D - for m in arc4 sha1_generic slhc crc-ccitt ppp_generic ppp_async ppp_mppe; do - insmod $m >/dev/null 2>&1 - done - ln -sfn $CHAP_SECRETS /etc/ppp/chap-secrets - chmod 600 /etc/ppp/*-secrets - /usr/sbin/$CONFIG -c $CONFIG_FILE -} - -del_user() -{ - cat $CHAP_SECRETS | grep -v $SERVER_NAME > $TEMP - cat $TEMP > $CHAP_SECRETS - rm -rf $TEMP -} - -start() { - config_load $CONFIG - setup_config $CONFIG || return - del_user - add_rule - config_foreach setup_login users - start_pptpd - gen_include -} - -stop() { - ps -w | grep "$CONFIG_FILE" | grep -v "grep" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 - ps -w | grep "pppd local" | grep -v "grep" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 - del_user - del_rule - rm -rf /var/etc/$CONFIG.include -} diff --git a/lienol/luci-app-pptp-vpnserver-manyusers/root/etc/uci-defaults/luci-app-pptp-vpnserver-manyusers b/lienol/luci-app-pptp-vpnserver-manyusers/root/etc/uci-defaults/luci-app-pptp-vpnserver-manyusers deleted file mode 100755 index 07c18e1..0000000 --- a/lienol/luci-app-pptp-vpnserver-manyusers/root/etc/uci-defaults/luci-app-pptp-vpnserver-manyusers +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete firewall.pptpd - set firewall.pptpd=include - set firewall.pptpd.type=script - set firewall.pptpd.path=/var/etc/pptpd.include - set firewall.pptpd.reload=1 -EOF - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@pptpd[-1] - add ucitrack pptpd - set ucitrack.@pptpd[-1].init=pptpd - commit ucitrack -EOF - -rm -rf /tmp/luci-*cache -exit 0 diff --git a/lienol/luci-app-pptp-vpnserver-manyusers/root/usr/share/rpcd/acl.d/luci-app-pptp-vpnserver-manyusers.json b/lienol/luci-app-pptp-vpnserver-manyusers/root/usr/share/rpcd/acl.d/luci-app-pptp-vpnserver-manyusers.json deleted file mode 100644 index a286297..0000000 --- a/lienol/luci-app-pptp-vpnserver-manyusers/root/usr/share/rpcd/acl.d/luci-app-pptp-vpnserver-manyusers.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "luci-app-pptp-vpnserver-manyusers": { - "description": "Grant UCI access for luci-app-pptp-vpnserver-manyusers", - "read": { - "uci": [ "pptpd" ] - }, - "write": { - "uci": [ "pptpd" ] - } - } -} diff --git a/lienol/luci-app-ramfree/Makefile b/lienol/luci-app-ramfree/Makefile deleted file mode 100755 index 944a621..0000000 --- a/lienol/luci-app-ramfree/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (C) 2018 Lienol -# -# This is free software, licensed under the Apache License, Version 2.0 . -# - -include $(TOPDIR)/rules.mk - -LUCI_TITLE:=Add Release RAM Button -LUCI_PKGARCH:=all -PKG_VERSION:=1.0 -PKG_RELEASE:=1 - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature - - diff --git a/lienol/luci-app-ramfree/luasrc/controller/release_ram.lua b/lienol/luci-app-ramfree/luasrc/controller/release_ram.lua deleted file mode 100755 index 17e95ce..0000000 --- a/lienol/luci-app-ramfree/luasrc/controller/release_ram.lua +++ /dev/null @@ -1,9 +0,0 @@ -module("luci.controller.release_ram",package.seeall) - -function index() - entry({"admin","status","release_ram"}, call("release_ram"), _("Release Ram"), 9999) -end -function release_ram() - luci.sys.call("sync && echo 3 > /proc/sys/vm/drop_caches") - luci.http.redirect(luci.dispatcher.build_url("admin/status")) -end diff --git a/lienol/luci-app-ramfree/po/zh-cn/release_ram.po b/lienol/luci-app-ramfree/po/zh-cn/release_ram.po deleted file mode 100755 index cff6f02..0000000 --- a/lienol/luci-app-ramfree/po/zh-cn/release_ram.po +++ /dev/null @@ -1,2 +0,0 @@ -msgid "Release Ram" -msgstr "释放内存" diff --git a/lienol/luci-app-socat/Makefile b/lienol/luci-app-socat/Makefile deleted file mode 100644 index 7fbcf2f..0000000 --- a/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/lienol/luci-app-socat/luasrc/controller/socat.lua b/lienol/luci-app-socat/luasrc/controller/socat.lua deleted file mode 100644 index 89b84c3..0000000 --- a/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/lienol/luci-app-socat/luasrc/model/cbi/socat/config.lua b/lienol/luci-app-socat/luasrc/model/cbi/socat/config.lua deleted file mode 100644 index afbc084..0000000 --- a/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/lienol/luci-app-socat/luasrc/model/cbi/socat/index.lua b/lienol/luci-app-socat/luasrc/model/cbi/socat/index.lua deleted file mode 100644 index 0bc520e..0000000 --- a/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/lienol/luci-app-socat/luasrc/view/socat/list_status.htm b/lienol/luci-app-socat/luasrc/view/socat/list_status.htm deleted file mode 100644 index 8ffac82..0000000 --- a/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/lienol/luci-app-socat/luasrc/view/socat/status.htm b/lienol/luci-app-socat/luasrc/view/socat/status.htm deleted file mode 100644 index 04193e8..0000000 --- a/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/lienol/luci-app-socat/po/zh-cn/socat.po b/lienol/luci-app-socat/po/zh-cn/socat.po deleted file mode 100644 index 9068b61..0000000 --- a/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/lienol/luci-app-socat/root/etc/config/socat b/lienol/luci-app-socat/root/etc/config/socat deleted file mode 100644 index 04e4f87..0000000 --- a/lienol/luci-app-socat/root/etc/config/socat +++ /dev/null @@ -1,3 +0,0 @@ - -config global 'global' - option enable '0' diff --git a/lienol/luci-app-socat/root/etc/init.d/socat b/lienol/luci-app-socat/root/etc/init.d/socat deleted file mode 100755 index 579db57..0000000 --- a/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/lienol/luci-app-socat/root/etc/uci-defaults/luci-app-socat b/lienol/luci-app-socat/root/etc/uci-defaults/luci-app-socat deleted file mode 100755 index 431f875..0000000 --- a/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/lienol/luci-app-socat/root/usr/share/rpcd/acl.d/luci-app-socat.json b/lienol/luci-app-socat/root/usr/share/rpcd/acl.d/luci-app-socat.json deleted file mode 100644 index a79e14a..0000000 --- a/lienol/luci-app-socat/root/usr/share/rpcd/acl.d/luci-app-socat.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "luci-app-socat": { - "description": "Grant UCI access for luci-app-socat", - "read": { - "uci": [ "socat" ] - }, - "write": { - "uci": [ "socat" ] - } - } -} diff --git a/lienol/luci-app-softethervpn/Makefile b/lienol/luci-app-softethervpn/Makefile deleted file mode 100755 index a83f558..0000000 --- a/lienol/luci-app-softethervpn/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 SoftEtherVPN -LUCI_DEPENDS:=+zlib +libpthread +librt +libreadline +libncurses +libiconv-full +kmod-tun +libopenssl +softethervpn5-bridge +softethervpn5-client +softethervpn5-server -LUCI_PKGARCH:=all -PKG_VERSION:=1 -PKG_RELEASE:=12-20200513 - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature diff --git a/lienol/luci-app-softethervpn/luasrc/controller/softethervpn.lua b/lienol/luci-app-softethervpn/luasrc/controller/softethervpn.lua deleted file mode 100755 index d4ec9bc..0000000 --- a/lienol/luci-app-softethervpn/luasrc/controller/softethervpn.lua +++ /dev/null @@ -1,18 +0,0 @@ -module("luci.controller.softethervpn",package.seeall) - -function index() - if not nixio.fs.access("/etc/config/softethervpn")then - return - end - - entry({"admin","vpn"}, firstchild(), "VPN", 45).dependent = false - entry({"admin","vpn","softethervpn"},cbi("softethervpn"),_("SoftEther VPN"),50).dependent=true - entry({"admin","vpn","softethervpn","status"},call("status")).leaf=true -end - -function status() - local e={} - e.status=luci.sys.call("pidof %s >/dev/null"%"vpnserver")==0 - luci.http.prepare_content("application/json") - luci.http.write_json(e) -end diff --git a/lienol/luci-app-softethervpn/luasrc/model/cbi/softethervpn.lua b/lienol/luci-app-softethervpn/luasrc/model/cbi/softethervpn.lua deleted file mode 100755 index 68cb239..0000000 --- a/lienol/luci-app-softethervpn/luasrc/model/cbi/softethervpn.lua +++ /dev/null @@ -1,16 +0,0 @@ -local s = require "luci.sys" -local m, s, o -m = Map("softethervpn", translate("SoftEther VPN")) -m.description = translate( - "SoftEther VPN is an open source, cross-platform, multi-protocol virtual private network solution developed by university of tsukuba graduate student Daiyuu Nobori for master's thesis.
can easily set up OpenVPN, IPsec, L2TP, ms-sstp, L2TPv3 and EtherIP servers on the router using the console.") -m.template = "softethervpn/index" -s = m:section(TypedSection, "softether") -s.anonymous = true -o = s:option(DummyValue, "softethervpn_status", translate("Current Condition")) -o.template = "softethervpn/status" -o.value = translate("Collecting data...") -o = s:option(Flag, "enable", translate("Enabled")) -o.rmempty = false -o = s:option(DummyValue, "moreinfo", translate( - "控制台下载:
Windows-x86_x64-intel.exe

macos-x86-32bit.pkg
")) -return m diff --git a/lienol/luci-app-softethervpn/luasrc/view/softethervpn/index.htm b/lienol/luci-app-softethervpn/luasrc/view/softethervpn/index.htm deleted file mode 100755 index 273f604..0000000 --- a/lienol/luci-app-softethervpn/luasrc/view/softethervpn/index.htm +++ /dev/null @@ -1,18 +0,0 @@ -<%# - Copyright (C) 2018-2019 Lienol - Licensed to the public under the Apache License 2.0. --%> - -<% include("cbi/map") %> - diff --git a/lienol/luci-app-softethervpn/luasrc/view/softethervpn/status.htm b/lienol/luci-app-softethervpn/luasrc/view/softethervpn/status.htm deleted file mode 100755 index 055b112..0000000 --- a/lienol/luci-app-softethervpn/luasrc/view/softethervpn/status.htm +++ /dev/null @@ -1,3 +0,0 @@ -<%+cbi/valueheader%> -<%=pcdata(self:cfgvalue(section) or self.default or "")%> -<%+cbi/valuefooter%> diff --git a/lienol/luci-app-softethervpn/po/zh-cn/softethervpn.po b/lienol/luci-app-softethervpn/po/zh-cn/softethervpn.po deleted file mode 100755 index 8d17b15..0000000 --- a/lienol/luci-app-softethervpn/po/zh-cn/softethervpn.po +++ /dev/null @@ -1,23 +0,0 @@ -msgid "SoftEther VPN" -msgstr "SoftEther VPN 服务器" - -msgid "SoftEther VPN is an open source, cross-platform, multi-protocol virtual private network solution developed by university of tsukuba graduate student Daiyuu Nobori for master's thesis.
can easily set up OpenVPN, IPsec, L2TP, ms-sstp, L2TPv3 and EtherIP servers on the router using the console." -msgstr "SoftEther VPN是由筑波大学研究生Daiyuu Nobori因硕士论文开发的开源,跨平台,多重协定的虚拟私人网路方案。
使用控制台可以轻松在路由器上搭建OpenVPN, IPsec, L2TP, MS-SSTP, L2TPv3 和 EtherIP服务器。" - -msgid "PPTP VPN Server status" -msgstr "PPTP VPN 服务器运行状态" - -msgid "Current Condition" -msgstr "当前状态" - -msgid "Enabled" -msgstr "启用" - -msgid "Open L2TP/IPSec firewall" -msgstr "开启L2TP/IPSec防火墙" - -msgid "Open the MS-SSTP firewall" -msgstr "开启MS-SSTP防火墙" - -msgid "Open the OpenVPN firewall" -msgstr "开启OpenVPN防火墙" \ No newline at end of file diff --git a/lienol/luci-app-softethervpn/root/etc/config/softethervpn b/lienol/luci-app-softethervpn/root/etc/config/softethervpn deleted file mode 100755 index 90732c5..0000000 --- a/lienol/luci-app-softethervpn/root/etc/config/softethervpn +++ /dev/null @@ -1,4 +0,0 @@ - -config softether - option enable '0' - diff --git a/lienol/luci-app-softethervpn/root/etc/init.d/softethervpn b/lienol/luci-app-softethervpn/root/etc/init.d/softethervpn deleted file mode 100755 index d0500db..0000000 --- a/lienol/luci-app-softethervpn/root/etc/init.d/softethervpn +++ /dev/null @@ -1,74 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2016 Chen RuiWei - -START=99 -STOP=10 - -CONFIG=softethervpn - -add_rule() { - openvpnport=$(cat /usr/libexec/softethervpn/vpn_server.config 2>/dev/null | grep OpenVPN_UdpPortList | awk -F " " '{print $3}') - [ -z "$openvpnport" ] && openvpnport=1194 - - iptables -N SOFTETHER_VPN-SERVER - iptables -I INPUT -j SOFTETHER_VPN-SERVER - - iptables -A SOFTETHER_VPN-SERVER -p udp -m multiport --dports 500,1701,4500 -m comment --comment "L2TP/IPSec" -j ACCEPT - iptables -A SOFTETHER_VPN-SERVER -p udp --dport $openvpnport -m comment --comment "OpenVPN" -j ACCEPT - iptables -A SOFTETHER_VPN-SERVER -p tcp --dport $openvpnport -m comment --comment "OpenVPN" -j ACCEPT - iptables -A SOFTETHER_VPN-SERVER -p tcp --dport 5555 -j ACCEPT - iptables -A SOFTETHER_VPN-SERVER -p tcp --dport 8888 -j ACCEPT - iptables -A SOFTETHER_VPN-SERVER -p tcp --dport 992 -j ACCEPT -} - -del_rule() { - count=$(iptables -n -L INPUT 2>/dev/null | grep -c "SOFTETHER_VPN-SERVER") - if [ -n "$count" ]; then - until [ "$count" = 0 ] - do - rules=$(iptables -n -L INPUT --line-num 2>/dev/null | grep "SOFTETHER_VPN-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 SOFTETHER_VPN-SERVER 2>/dev/null - iptables -X SOFTETHER_VPN-SERVER 2>/dev/null -} - -gen_include() { - echo '#!/bin/sh' > /var/etc/$CONFIG.include - extract_rules() { - echo "*$1" - iptables-save -t $1 | grep "SOFTETHER_VPN-SERVER" | \ - sed -e "s/^-A \(INPUT\)/-I \1 1/" - echo 'COMMIT' - } - cat <<-EOF >> /var/etc/$CONFIG.include - iptables-save -c | grep -v "SOFTETHER_VPN-SERVER" | iptables-restore -c - iptables-restore -n <<-EOT - $(extract_rules filter) - EOT - EOF - return 0 -} - -start() -{ - enable=$(uci -q get $CONFIG.@softether[0].enable) - [ $enable -ne 1 ] && exit 0 - /usr/bin/env LANG=en_US.UTF-8 /usr/libexec/softethervpn/vpnserver start > /dev/null 2>&1 - add_rule - gen_include -} - -stop() -{ - /usr/bin/env LANG=en_US.UTF-8 /usr/libexec/softethervpn/vpnserver stop > /dev/null 2>&1 - del_rule - rm -rf /var/etc/$CONFIG.include -} diff --git a/lienol/luci-app-softethervpn/root/etc/uci-defaults/luci-app-softethervpn b/lienol/luci-app-softethervpn/root/etc/uci-defaults/luci-app-softethervpn deleted file mode 100755 index 51d06f5..0000000 --- a/lienol/luci-app-softethervpn/root/etc/uci-defaults/luci-app-softethervpn +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete firewall.softethervpn - set firewall.softethervpn=include - set firewall.softethervpn.type=script - set firewall.softethervpn.path=/var/etc/softethervpn.include - set firewall.softethervpn.reload=1 -EOF - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@softethervpn[-1] - add ucitrack softethervpn - set ucitrack.@softethervpn[-1].init=softethervpn - commit ucitrack -EOF - -/etc/init.d/softethervpnbridge disable && /etc/init.d/softethervpnbridge stop -/etc/init.d/softethervpnclient disable && /etc/init.d/softethervpnclient stop -/etc/init.d/softethervpnserver disable && /etc/init.d/softethervpnserver stop - -rm -rf /tmp/luci-*cache -exit 0 diff --git a/lienol/luci-app-softethervpn/root/usr/share/rpcd/acl.d/luci-app-softethervpn.json b/lienol/luci-app-softethervpn/root/usr/share/rpcd/acl.d/luci-app-softethervpn.json deleted file mode 100644 index bf0d26d..0000000 --- a/lienol/luci-app-softethervpn/root/usr/share/rpcd/acl.d/luci-app-softethervpn.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "luci-app-softethervpn": { - "description": "Grant UCI access for luci-app-softethervpn", - "read": { - "uci": [ "softethervpn" ] - }, - "write": { - "uci": [ "softethervpn" ] - } - } -} diff --git a/lienol/luci-app-ssr-mudb-server/LICENSE b/lienol/luci-app-ssr-mudb-server/LICENSE deleted file mode 100644 index e72bfdd..0000000 --- a/lienol/luci-app-ssr-mudb-server/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. \ No newline at end of file diff --git a/lienol/luci-app-ssr-mudb-server/Makefile b/lienol/luci-app-ssr-mudb-server/Makefile deleted file mode 100644 index ba213ff..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/htdocs/luci-static/resources/vue.min.js b/lienol/luci-app-ssr-mudb-server/htdocs/luci-static/resources/vue.min.js deleted file mode 100644 index 05e2110..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/luasrc/controller/ssr_mudb_server.lua b/lienol/luci-app-ssr-mudb-server/luasrc/controller/ssr_mudb_server.lua deleted file mode 100644 index 3acadf4..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/luasrc/model/cbi/ssr_mudb_server/index.lua b/lienol/luci-app-ssr-mudb-server/luasrc/model/cbi/ssr_mudb_server/index.lua deleted file mode 100644 index e39b886..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/luasrc/view/ssr_mudb_server/status.htm b/lienol/luci-app-ssr-mudb-server/luasrc/view/ssr_mudb_server/status.htm deleted file mode 100644 index d160214..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/luasrc/view/ssr_mudb_server/user.htm b/lienol/luci-app-ssr-mudb-server/luasrc/view/ssr_mudb_server/user.htm deleted file mode 100644 index 6d15f9e..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/luasrc/view/ssr_mudb_server/users.htm b/lienol/luci-app-ssr-mudb-server/luasrc/view/ssr_mudb_server/users.htm deleted file mode 100644 index 2365f46..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/po/zh-cn/ssr_mudb_server.po b/lienol/luci-app-ssr-mudb-server/po/zh-cn/ssr_mudb_server.po deleted file mode 100644 index bb02122..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/etc/config/ssr_mudb_server b/lienol/luci-app-ssr-mudb-server/root/etc/config/ssr_mudb_server deleted file mode 100644 index 5d8a87c..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/etc/config/ssr_mudb_server.json b/lienol/luci-app-ssr-mudb-server/root/etc/config/ssr_mudb_server.json deleted file mode 100644 index 9f29614..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/etc/init.d/ssr_mudb_server b/lienol/luci-app-ssr-mudb-server/root/etc/init.d/ssr_mudb_server deleted file mode 100755 index 70a5801..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/etc/uci-defaults/luci-app-ssr-mudb-server b/lienol/luci-app-ssr-mudb-server/root/etc/uci-defaults/luci-app-ssr-mudb-server deleted file mode 100644 index 157e67d..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/rpcd/acl.d/luci-app-ssr-mudb-server.json b/lienol/luci-app-ssr-mudb-server/root/usr/share/rpcd/acl.d/luci-app-ssr-mudb-server.json deleted file mode 100644 index a03d0a1..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/.travis.yml b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/.travis.yml deleted file mode 100644 index 014fa07..0000000 --- a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/.travis.yml +++ /dev/null @@ -1,21 +0,0 @@ -language: python -python: - - 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/CHANGES b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/CHANGES deleted file mode 100644 index 0cd9176..0000000 --- a/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 python 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/CONTRIBUTING.md b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/CONTRIBUTING.md deleted file mode 100644 index fbdb9c1..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/Dockerfile b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/Dockerfile deleted file mode 100644 index ec7b2c6..0000000 --- a/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 python \ - 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 python server.py -p $SERVER_PORT -k $PASSWORD -m $METHOD -O $PROTOCOL -o $OBFS -G $PROTOCOLPARAM diff --git a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/MANIFEST.in b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/MANIFEST.in deleted file mode 100644 index 1882dd7..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/apiconfig.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/apiconfig.py deleted file mode 100644 index 682a034..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/asyncmgr.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/asyncmgr.py deleted file mode 100644 index 9bf4d09..0000000 --- a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/asyncmgr.py +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env python -# -*- 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/clear_traffic_all_users.sh b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/clear_traffic_all_users.sh deleted file mode 100755 index e488437..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/config.json b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/config.json deleted file mode 100644 index 55f12b5..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/configloader.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/configloader.py deleted file mode 100644 index cf9d619..0000000 --- a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/configloader.py +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/python -# -*- 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/db_transfer.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/db_transfer.py deleted file mode 100644 index 67bda60..0000000 --- a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/db_transfer.py +++ /dev/null @@ -1,631 +0,0 @@ -#!/usr/bin/python -# -*- 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/firewall.lua b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/firewall.lua deleted file mode 100644 index b6514b4..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/importloader.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/importloader.py deleted file mode 100644 index c917cb7..0000000 --- a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/importloader.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/python -# -*- 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/initcfg.bat b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/initcfg.bat deleted file mode 100644 index 6d0bce6..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/initcfg.sh b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/initcfg.sh deleted file mode 100755 index 862d1ab..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/initmudbjson.sh b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/initmudbjson.sh deleted file mode 100755 index 09b07f3..0000000 --- a/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=`python mujson_mgr.py -l|grep -c -e "[0-9]"` - if [[ $user_count == 0 ]]; then - port=`python -c 'import random;print(random.randint(10000, 65536))'` - python mujson_mgr.py -a -p ${port} - fi -else - echo "unable to detect server IP" -fi - diff --git a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/logrun.sh b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/logrun.sh deleted file mode 100755 index b5f4c6e..0000000 --- a/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` -#python_ver=$(ls /usr/bin|grep -e "^python[23]\.[1-9]\+$"|tail -1) -eval $(ps -ef | grep "[0-9] python server\\.py m" | awk '{print "kill "$2}') -ulimit -n 512000 -nohup python server.py m >> ssserver.log 2>&1 & - diff --git a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/mudb.json b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/mudb.json deleted file mode 100644 index 0637a08..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/mujson_mgr.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/mujson_mgr.py deleted file mode 100644 index 2eb05d5..0000000 --- a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/mujson_mgr.py +++ /dev/null @@ -1,358 +0,0 @@ -#!/usr/bin/python -# -*- 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: python 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/mysql.json b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/mysql.json deleted file mode 100644 index 1849e9e..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/run.sh b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/run.sh deleted file mode 100755 index 8366c8c..0000000 --- a/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` -#python_ver=$(ls /usr/bin|grep -e "^python[23]\.[1-9]\+$"|tail -1) -eval $(ps -ef | grep "[0-9] python server\\.py m" | awk '{print "kill "$2}') -ulimit -n 512000 -nohup python server.py m>> /dev/null 2>&1 & - diff --git a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/server.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/server.py deleted file mode 100644 index ba863b6..0000000 --- a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/server.py +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/python -# -*- 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_python() - 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/server_pool.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/server_pool.py deleted file mode 100644 index d159817..0000000 --- a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/server_pool.py +++ /dev/null @@ -1,293 +0,0 @@ -#!/usr/bin/env python -# -*- 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_python() - 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/common.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/common.py deleted file mode 100644 index c4484c0..0000000 --- a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/common.py +++ /dev/null @@ -1,418 +0,0 @@ -#!/usr/bin/python -# -*- 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/__init__.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/__init__.py deleted file mode 100644 index 401c7b7..0000000 --- a/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 python -# -# 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/ctypes_libsodium.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/ctypes_libsodium.py deleted file mode 100644 index efecfd4..0000000 --- a/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 python - -# 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/ctypes_openssl.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/ctypes_openssl.py deleted file mode 100644 index 0ef8ce0..0000000 --- a/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 python - -# 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/openssl.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/openssl.py deleted file mode 100644 index 0a8ca53..0000000 --- a/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 python -# -# 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/rc4_md5.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/rc4_md5.py deleted file mode 100644 index b0105ec..0000000 --- a/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 python -# -# 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/sodium.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/sodium.py deleted file mode 100644 index 51d476b..0000000 --- a/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 python -# -# 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/table.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/crypto/table.py deleted file mode 100644 index 60c2f24..0000000 --- a/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 python -# -# 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/encrypt.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/encrypt.py deleted file mode 100644 index 44f9052..0000000 --- a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/encrypt.py +++ /dev/null @@ -1,236 +0,0 @@ -#!/usr/bin/env python -# -# 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/eventloop.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/eventloop.py deleted file mode 100644 index 341620e..0000000 --- a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/eventloop.py +++ /dev/null @@ -1,258 +0,0 @@ -#!/usr/bin/python -# -*- 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/local.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/local.py deleted file mode 100644 index 9f54d93..0000000 --- a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/local.py +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env python -# -*- 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_python() - - # 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/logrun.sh b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/logrun.sh deleted file mode 100755 index dfd0fcf..0000000 --- a/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] python server\\.py a" | awk '{print "kill "$2}') -ulimit -n 512000 -nohup python server.py a >> ssserver.log 2>&1 & diff --git a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/lru_cache.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/lru_cache.py deleted file mode 100644 index ab0d210..0000000 --- a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/lru_cache.py +++ /dev/null @@ -1,179 +0,0 @@ -#!/usr/bin/python -# -*- 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/manager.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/manager.py deleted file mode 100644 index 80d0a32..0000000 --- a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/manager.py +++ /dev/null @@ -1,291 +0,0 @@ -#!/usr/bin/python -# -*- 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfs.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfs.py deleted file mode 100644 index 3dfdb14..0000000 --- a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfs.py +++ /dev/null @@ -1,114 +0,0 @@ -#!/usr/bin/env python -# -# 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/__init__.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/__init__.py deleted file mode 100644 index 401c7b7..0000000 --- a/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 python -# -# 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/auth.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/auth.py deleted file mode 100644 index a745e09..0000000 --- a/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 python -# -# 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/http_simple.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/http_simple.py deleted file mode 100644 index 6f1a05e..0000000 --- a/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 python -# -# 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/plain.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/plain.py deleted file mode 100644 index 8c6355c..0000000 --- a/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 python -# -# 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/verify.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/obfsplugin/verify.py deleted file mode 100644 index 0dc0ca6..0000000 --- a/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 python -# -# 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/ordereddict.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/ordereddict.py deleted file mode 100644 index e1918f5..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/run.sh b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/run.sh deleted file mode 100755 index 227335f..0000000 --- a/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] python server\\.py a" | awk '{print "kill "$2}') -ulimit -n 512000 -nohup python server.py a >> /dev/null 2>&1 & diff --git a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/server.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/server.py deleted file mode 100644 index c18ad1c..0000000 --- a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/server.py +++ /dev/null @@ -1,215 +0,0 @@ -#!/usr/bin/env python -# -*- 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_python() - - 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/shell.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/shell.py deleted file mode 100644 index 6246d98..0000000 --- a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/shell.py +++ /dev/null @@ -1,445 +0,0 @@ -#!/usr/bin/python -# -*- 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_python(): - 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/stop.sh b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/stop.sh deleted file mode 100755 index 513c7a0..0000000 --- a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/stop.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -#python_ver=$(ls /usr/bin|grep -e "^python[23]\.[1-9]\+$"|tail -1) -eval $(ps -ef | grep "[0-9] python server\\.py a" | awk '{print "kill "$2}') diff --git a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/tail.sh b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/tail.sh deleted file mode 100755 index aa37139..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/tcprelay.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/tcprelay.py deleted file mode 100644 index 595e2be..0000000 --- a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/tcprelay.py +++ /dev/null @@ -1,1476 +0,0 @@ -#!/usr/bin/python -# -*- 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/udprelay.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/udprelay.py deleted file mode 100644 index b9606cd..0000000 --- a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/udprelay.py +++ /dev/null @@ -1,656 +0,0 @@ -#!/usr/bin/python -# -*- 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/user.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/user.py deleted file mode 100644 index 7806fac..0000000 --- a/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目录执行python local.py -d start" diff --git a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/version.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/version.py deleted file mode 100644 index f3e1ef7..0000000 --- a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/shadowsocks/version.py +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/python -# -*- 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/stop.sh b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/stop.sh deleted file mode 100755 index 66672c7..0000000 --- a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/stop.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -# python_ver=$(ls /usr/bin|grep -e "^python[23]\.[1-9]\+$"|tail -1) -eval $(ps -ef | grep "[0-9] python server\\.py m" | awk '{print "kill "$2}') diff --git a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/switchrule.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/switchrule.py deleted file mode 100644 index 6687e12..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tail.sh b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tail.sh deleted file mode 100755 index f36f605..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/aes-cfb1.json b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/aes-cfb1.json deleted file mode 100644 index 70ae670..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/aes-cfb8.json b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/aes-cfb8.json deleted file mode 100644 index fe8b715..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/aes-ctr.json b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/aes-ctr.json deleted file mode 100644 index 1f5a1d7..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/aes.json b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/aes.json deleted file mode 100644 index 2fc29f3..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/assert.sh b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/assert.sh deleted file mode 100755 index b0c679c..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/chacha20.json b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/chacha20.json deleted file mode 100644 index fc2af8e..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/client-multi-server-ip.json b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/client-multi-server-ip.json deleted file mode 100644 index 3050c11..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/coverage_server.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/coverage_server.py deleted file mode 100644 index 23cc8cd..0000000 --- a/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 python -# -# 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/fastopen.json b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/fastopen.json deleted file mode 100644 index b4f60d4..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/ipv6-client-side.json b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/ipv6-client-side.json deleted file mode 100644 index e14bb07..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/ipv6.json b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/ipv6.json deleted file mode 100644 index 18263ee..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/jenkins.sh b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/jenkins.sh deleted file mode 100755 index ea5c163..0000000 --- a/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 -} - -python --version -coverage erase -mkdir tmp -run_test pep8 --ignore=E402 . -run_test pyflakes . -run_test coverage run tests/nose_plugin.py -v -run_test python setup.py sdist -run_test tests/test_daemon.sh -run_test python tests/test.py --with-coverage -c tests/aes.json -run_test python tests/test.py --with-coverage -c tests/aes-ctr.json -run_test python tests/test.py --with-coverage -c tests/aes-cfb1.json -run_test python tests/test.py --with-coverage -c tests/aes-cfb8.json -run_test python tests/test.py --with-coverage -c tests/rc4-md5.json -run_test python tests/test.py --with-coverage -c tests/salsa20.json -run_test python tests/test.py --with-coverage -c tests/chacha20.json -run_test python tests/test.py --with-coverage -c tests/table.json -run_test python tests/test.py --with-coverage -c tests/server-multi-ports.json -run_test python tests/test.py --with-coverage -s tests/aes.json -c tests/client-multi-server-ip.json -run_test python tests/test.py --with-coverage -s tests/server-multi-passwd.json -c tests/server-multi-passwd-client-side.json -run_test python tests/test.py --with-coverage -c tests/workers.json -run_test python tests/test.py --with-coverage -s tests/ipv6.json -c tests/ipv6-client-side.json -run_test python 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 python 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 python 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 python 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 python 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 python 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 python tests/test.py --with-coverage -c tests/fastopen.json - run_test python 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/libsodium/install.sh b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/libsodium/install.sh deleted file mode 100644 index b0e35fa..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/nose_plugin.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/nose_plugin.py deleted file mode 100644 index 86b1a86..0000000 --- a/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 python -# -# 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/rc4-md5.json b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/rc4-md5.json deleted file mode 100644 index e69b433..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/salsa20-ctr.json b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/salsa20-ctr.json deleted file mode 100644 index 8b77d07..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/salsa20.json b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/salsa20.json deleted file mode 100644 index a4a664f..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/server-multi-passwd-client-side.json b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/server-multi-passwd-client-side.json deleted file mode 100644 index c822c98..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/server-multi-passwd-table.json b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/server-multi-passwd-table.json deleted file mode 100644 index a2c0a80..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/server-multi-passwd.json b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/server-multi-passwd.json deleted file mode 100644 index b1407f0..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/server-multi-ports.json b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/server-multi-ports.json deleted file mode 100644 index 5bdbcab..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/setup_tc.sh b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/setup_tc.sh deleted file mode 100755 index 1a5fa20..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/socksify/install.sh b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/socksify/install.sh deleted file mode 100644 index 8eff72d..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/socksify/socks.conf b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/socksify/socks.conf deleted file mode 100644 index 13db772..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/table.json b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/table.json deleted file mode 100644 index 49c2c01..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test.py deleted file mode 100644 index 4083401..0000000 --- a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test.py +++ /dev/null @@ -1,158 +0,0 @@ -#!/usr/bin/python -# -*- 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 - -python = ['python'] - -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: - python = ['coverage', 'run', '-p'] - -client_args = python + ['shadowsocks/local.py', '-v'] -server_args = python + ['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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_command.sh b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_command.sh deleted file mode 100755 index a1a777b..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_daemon.sh b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_daemon.sh deleted file mode 100755 index 7a192bd..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_large_file.sh b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_large_file.sh deleted file mode 100755 index 7a61caf..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_udp_src.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_udp_src.py deleted file mode 100644 index e8fa505..0000000 --- a/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/python - -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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_udp_src.sh b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/test_udp_src.sh deleted file mode 100755 index 6a778ab..0000000 --- a/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 - -python tests/test_udp_src.py -r=$? - -kill -s SIGINT $LOCAL -kill -s SIGINT $SERVER - -sleep 2 - -exit $r diff --git a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/workers.json b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/tests/workers.json deleted file mode 100644 index 8e0943b..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/user-config.json b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/user-config.json deleted file mode 100644 index e40cb01..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/userapiconfig.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/userapiconfig.py deleted file mode 100644 index b1cba3a..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/usermysql.json b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/usermysql.json deleted file mode 100644 index 1849e9e..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/utils/README.md b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/utils/README.md deleted file mode 100644 index f624309..0000000 --- a/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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/utils/autoban.py b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/utils/autoban.py deleted file mode 100644 index 1bbb65c..0000000 --- a/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/utils/autoban.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/python -# -*- 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/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/utils/fail2ban/shadowsocks.conf b/lienol/luci-app-ssr-mudb-server/root/usr/share/ssr_mudb_server/utils/fail2ban/shadowsocks.conf deleted file mode 100644 index 9b1c7ec..0000000 --- a/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/lienol/luci-app-timecontrol/Makefile b/lienol/luci-app-timecontrol/Makefile deleted file mode 100644 index fe312a6..0000000 --- a/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/lienol/luci-app-timecontrol/luasrc/controller/timecontrol.lua b/lienol/luci-app-timecontrol/luasrc/controller/timecontrol.lua deleted file mode 100644 index 161d51b..0000000 --- a/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/lienol/luci-app-timecontrol/luasrc/model/cbi/timecontrol.lua b/lienol/luci-app-timecontrol/luasrc/model/cbi/timecontrol.lua deleted file mode 100644 index 9b12721..0000000 --- a/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/lienol/luci-app-timecontrol/luasrc/view/timecontrol/index.htm b/lienol/luci-app-timecontrol/luasrc/view/timecontrol/index.htm deleted file mode 100644 index 3ff7a84..0000000 --- a/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/lienol/luci-app-timecontrol/luasrc/view/timecontrol/timecontrol.htm b/lienol/luci-app-timecontrol/luasrc/view/timecontrol/timecontrol.htm deleted file mode 100644 index e4d63fb..0000000 --- a/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/lienol/luci-app-timecontrol/po/zh-cn/timecontrol.po b/lienol/luci-app-timecontrol/po/zh-cn/timecontrol.po deleted file mode 100644 index fc68f62..0000000 --- a/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/lienol/luci-app-timecontrol/root/etc/config/timecontrol b/lienol/luci-app-timecontrol/root/etc/config/timecontrol deleted file mode 100644 index 0c4c4f6..0000000 --- a/lienol/luci-app-timecontrol/root/etc/config/timecontrol +++ /dev/null @@ -1,3 +0,0 @@ - -config basic - option enable '0' diff --git a/lienol/luci-app-timecontrol/root/etc/init.d/timecontrol b/lienol/luci-app-timecontrol/root/etc/init.d/timecontrol deleted file mode 100755 index 17300b8..0000000 --- a/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/lienol/luci-app-timecontrol/root/etc/uci-defaults/luci-app-timecontrol b/lienol/luci-app-timecontrol/root/etc/uci-defaults/luci-app-timecontrol deleted file mode 100755 index c3fd6db..0000000 --- a/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/lienol/luci-app-timecontrol/root/usr/share/rpcd/acl.d/luci-app-timecontrol.json b/lienol/luci-app-timecontrol/root/usr/share/rpcd/acl.d/luci-app-timecontrol.json deleted file mode 100644 index 2ff0fab..0000000 --- a/lienol/luci-app-timecontrol/root/usr/share/rpcd/acl.d/luci-app-timecontrol.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "luci-app-timecontrol": { - "description": "Grant UCI access for luci-app-timecontrol", - "read": { - "uci": [ "timecontrol" ] - }, - "write": { - "uci": [ "timecontrol" ] - } - } -} diff --git a/luci-app-passwall/Makefile b/luci-app-passwall/Makefile new file mode 100644 index 0000000..9a5490f --- /dev/null +++ b/luci-app-passwall/Makefile @@ -0,0 +1,169 @@ +# 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.49 +PKG_RELEASE:=1 +#20220207 + +PKG_CONFIG_DEPENDS:= \ + CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Brook \ + CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_ChinaDNS_NG \ + CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Haproxy \ + CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Hysteria \ + CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Kcptun \ + CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy \ + CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_PDNSD \ + CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Client \ + CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Server \ + CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Rust_Client \ + CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Rust_Server \ + CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Client \ + CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Server \ + CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Simple_Obfs \ + CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Trojan_GO \ + CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Trojan_Plus \ + CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_V2ray \ + CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_Plugin \ + CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Xray \ + CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Xray_Plugin \ + CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_IPv6_Nat + +LUCI_TITLE:=LuCI support for PassWall +LUCI_PKGARCH:=all +LUCI_DEPENDS:=+coreutils +coreutils-base64 +coreutils-nohup +curl \ + +dnsmasq-full +luci-compat +dns2socks +ipset +ip-full +ipt2socks +iptables-mod-tproxy +iptables-mod-iprange \ + +libuci-lua +lua +luci-lib-jsonc +microsocks +tcping +resolveip \ + +unzip \ + +PACKAGE_$(PKG_NAME)_INCLUDE_Brook:brook \ + +PACKAGE_$(PKG_NAME)_INCLUDE_ChinaDNS_NG:chinadns-ng \ + +PACKAGE_$(PKG_NAME)_INCLUDE_Haproxy:haproxy \ + +PACKAGE_$(PKG_NAME)_INCLUDE_Hysteria:hysteria \ + +PACKAGE_$(PKG_NAME)_INCLUDE_Kcptun:kcptun-client \ + +PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy:naiveproxy \ + +PACKAGE_$(PKG_NAME)_INCLUDE_PDNSD:pdnsd-alt \ + +PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Client:shadowsocks-libev-ss-local \ + +PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Client:shadowsocks-libev-ss-redir \ + +PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Server:shadowsocks-libev-ss-server \ + +PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Rust_Client:shadowsocks-rust-sslocal \ + +PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Client:shadowsocksr-libev-ssr-local \ + +PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Client:shadowsocksr-libev-ssr-redir \ + +PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Server:shadowsocksr-libev-ssr-server \ + +PACKAGE_$(PKG_NAME)_INCLUDE_Simple_Obfs:simple-obfs \ + +PACKAGE_$(PKG_NAME)_INCLUDE_Trojan_GO:trojan-go \ + +PACKAGE_$(PKG_NAME)_INCLUDE_Trojan_Plus:trojan-plus \ + +PACKAGE_$(PKG_NAME)_INCLUDE_V2ray:v2ray-core \ + +PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_Plugin:v2ray-plugin \ + +PACKAGE_$(PKG_NAME)_INCLUDE_Xray:xray-core \ + +PACKAGE_$(PKG_NAME)_INCLUDE_Xray_Plugin:xray-plugin \ + +PACKAGE_$(PKG_NAME)_INCLUDE_IPv6_Nat:ip6tables-mod-nat + +define Package/$(PKG_NAME)/config +menu "Configuration" + +config PACKAGE_$(PKG_NAME)_INCLUDE_Brook + bool "Include Brook" + default n + +config PACKAGE_$(PKG_NAME)_INCLUDE_ChinaDNS_NG + bool "Include ChinaDNS-NG" + default y + +config PACKAGE_$(PKG_NAME)_INCLUDE_Haproxy + bool "Include Haproxy" + default y if aarch64||arm||i386||x86_64 + +config PACKAGE_$(PKG_NAME)_INCLUDE_Hysteria + bool "Include Hysteria" + default n + +config PACKAGE_$(PKG_NAME)_INCLUDE_Kcptun + bool "Include Kcptun" + default n + +config PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy + bool "Include NaiveProxy" + depends on !(arc||(arm&&TARGET_gemini)||armeb||mips||mips64||powerpc) + default n + +config PACKAGE_$(PKG_NAME)_INCLUDE_PDNSD + bool "Include PDNSD" + default y + +config PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Client + bool "Include Shadowsocks Libev Client" + default y + +config PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Server + bool "Include Shadowsocks Libev Server" + default y if aarch64||arm||i386||x86_64 + +config PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Rust_Client + bool "Include Shadowsocks Rust Client" + depends on aarch64||arm||i386||mips||mipsel||x86_64 + default y if aarch64 + +config PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Client + bool "Include ShadowsocksR Libev Client" + default y + +config PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Server + bool "Include ShadowsocksR Libev Server" + default n + +config PACKAGE_$(PKG_NAME)_INCLUDE_Simple_Obfs + bool "Include Simple-Obfs (Shadowsocks Plugin)" + default y + +config PACKAGE_$(PKG_NAME)_INCLUDE_Trojan_GO + bool "Include Trojan-GO" + default n + +config PACKAGE_$(PKG_NAME)_INCLUDE_Trojan_Plus + bool "Include Trojan-Plus" + default y + +config PACKAGE_$(PKG_NAME)_INCLUDE_V2ray + bool "Include V2ray" + default y if aarch64||arm||i386||x86_64 + +config PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_Plugin + bool "Include V2ray-Plugin (Shadowsocks Plugin)" + default y if aarch64||arm||i386||x86_64 + +config PACKAGE_$(PKG_NAME)_INCLUDE_Xray + bool "Include Xray" + default y if aarch64||arm||i386||x86_64 + +config PACKAGE_$(PKG_NAME)_INCLUDE_Xray_Plugin + bool "Include Xray-Plugin (Shadowsocks Plugin)" + default n + +config PACKAGE_$(PKG_NAME)_INCLUDE_IPv6_Nat + depends on PACKAGE_ip6tables + bool "Include IPv6 Nat" + default n + +endmenu +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 +/usr/share/passwall/rules/block_host +/usr/share/passwall/rules/block_ip +/usr/share/passwall/rules/lanlist_ipv4 +/usr/share/passwall/rules/lanlist_ipv6 +endef + +include $(TOPDIR)/feeds/luci/luci.mk + +# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-passwall/luasrc/controller/passwall.lua b/luci-app-passwall/luasrc/controller/passwall.lua new file mode 100644 index 0000000..eb71c82 --- /dev/null +++ b/luci-app-passwall/luasrc/controller/passwall.lua @@ -0,0 +1,524 @@ +-- 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 v2ray = require("luci.model.cbi." .. appname ..".api.v2ray") +local xray = require("luci.model.cbi." .. appname ..".api.xray") +local trojan_go = require("luci.model.cbi." .. appname ..".api.trojan_go") +local hysteria = require("luci.model.cbi." .. appname ..".api.hysteria") + +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 + e = entry({"admin", "services", appname}, alias("admin", "services", appname, "settings"), _("Pass Wall"), -1) + e.dependent = true + e.acl_depends = { "luci-app-passwall" } + 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, "node_subscribe"}, cbi(appname .. "/client/node_subscribe"), _("Node Subscribe"), 3).dependent = true + entry({"admin", "services", appname, "auto_switch"}, cbi(appname .. "/client/auto_switch"), _("Auto Switch"), 4).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, "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"), 97).leaf = true + entry({"admin", "services", appname, "node_subscribe_config"}, cbi(appname .. "/client/node_subscribe_config")).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, "acl_config"}, cbi(appname .. "/client/acl_config")).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, "autoswitch_add_node"}, call("autoswitch_add_node")).leaf = true + entry({"admin", "services", appname, "autoswitch_remove_node"}, call("autoswitch_remove_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, "haproxy_status"}, call("haproxy_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, "v2ray_check"}, call("v2ray_check")).leaf = true + entry({"admin", "services", appname, "v2ray_update"}, call("v2ray_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 + entry({"admin", "services", appname, "hysteria_check"}, call("hysteria_check")).leaf = true + entry({"admin", "services", appname, "hysteria_update"}, call("hysteria_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('/etc/init.d/passwall stop') + luci.sys.call('[ -f "/usr/share/passwall/0_default_config" ] && cp -f /usr/share/passwall/0_default_config /etc/config/passwall') + luci.http.redirect(api.url()) +end + +function show_menu() + luci.sys.call("touch /etc/config/passwall_show") + luci.sys.call("rm -rf /tmp/luci-*") + luci.sys.call("/etc/init.d/rpcd restart >/dev/null") + luci.http.redirect(api.url()) +end + +function hide_menu() + luci.sys.call("rm -rf /etc/config/passwall_show") + luci.sys.call("rm -rf /tmp/luci-*") + luci.sys.call("/etc/init.d/rpcd restart >/dev/null") + 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 autoswitch_add_node() + local key = luci.http.formvalue("key") + if key and key ~= "" then + for k, e in ipairs(api.get_valid_nodes()) do + if e.node_type == "normal" and e["remark"]:find(key) then + luci.sys.call(string.format("uci -q del_list passwall.@auto_switch[0].tcp_node='%s' && uci -q add_list passwall.@auto_switch[0].tcp_node='%s'", e.id, e.id)) + end + end + end + luci.http.redirect(api.url("auto_switch")) +end + +function autoswitch_remove_node() + local key = luci.http.formvalue("key") + if key and key ~= "" then + for k, e in ipairs(ucic:get(appname, "@auto_switch[0]", "tcp_node") or {}) do + if e and (ucic:get(appname, e, "remarks") or ""):find(key) then + luci.sys.call(string.format("uci -q del_list passwall.@auto_switch[0].tcp_node='%s'", e)) + end + end + end + luci.http.redirect(api.url("auto_switch")) +end + +function get_now_use_node() + local e = {} + local data, code, msg = nixio.fs.readfile("/tmp/etc/passwall/id/TCP") + if data then + e["TCP"] = util.trim(data) + end + local data, code, msg = nixio.fs.readfile("/tmp/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() + if proto == "UDP" and (ucic:get(appname, "@global[0]", "udp_node") or "nil") == "tcp" and not nixio.fs.access("/tmp/etc/passwall/" .. proto .. ".log") then + proto = "TCP" + end + if nixio.fs.access("/tmp/etc/passwall/" .. proto .. ".log") then + local content = luci.sys.exec("cat /tmp/etc/passwall/" .. proto .. ".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 /tmp/log/passwall.log ] && sed '1!G;h;$!d' /tmp/log/passwall.log > /tmp/log/passwall_show.log") + luci.http.write(luci.sys.exec("[ -f '/tmp/log/passwall.log' ] && cat /tmp/log/passwall.log")) +end + +function clear_log() + luci.sys.call("echo '' > /tmp/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["tcp_node_status"] = luci.sys.call(string.format("top -bn1 | grep -v -E 'grep|acl/|acl_' | 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 -E 'grep|acl/|acl_' | grep '%s/bin/' | grep -i 'UDP' >/dev/null", appname)) == 0 + end + luci.http.prepare_content("application/json") + luci.http.write_json(e) +end + +function haproxy_status() + local e = luci.sys.call(string.format("top -bn1 | grep -v grep | grep '%s/bin/' | grep haproxy >/dev/null", appname)) == 0 + 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 -E 'grep|acl/|acl_' | 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 -E 'grep|acl/|acl_' | 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:delete(appname, uuid, "add_from") + ucic:set(appname, uuid, "add_mode", 1) + ucic:commit(appname) + luci.http.redirect(api.url("node_config", uuid)) +end + +function clear_all_nodes() + ucic:set(appname, '@global[0]', "enabled", "0") + ucic:set(appname, '@global[0]', "tcp_node", "nil") + ucic:set(appname, '@global[0]', "udp_node", "nil") + ucic:set_list(appname, "@auto_switch[0]", "tcp_node", {}) + ucic:foreach(appname, "socks", function(t) + ucic:delete(appname, t[".name"]) + end) + ucic:foreach(appname, "haproxy_config", function(t) + ucic:delete(appname, t[".name"]) + end) + ucic:foreach(appname, "acl_rule", function(t) + ucic:set(appname, t[".name"], "tcp_node", "default") + ucic:set(appname, t[".name"], "udp_node", "default") + end) + ucic:foreach(appname, "nodes", function(node) + ucic:delete(appname, node['.name']) + end) + + ucic:commit(appname) + luci.sys.call("/etc/init.d/" .. appname .. " stop") +end + +function delete_select_nodes() + local ids = luci.http.formvalue("ids") + local auto_switch_tcp_node_list = ucic:get(appname, "@auto_switch[0]", "tcp_node") or {} + string.gsub(ids, '[^' .. "," .. ']+', function(w) + for k, v in ipairs(auto_switch_tcp_node_list) do + if v == w then + luci.sys.call(string.format("uci -q del_list passwall.@auto_switch[0].tcp_node='%s'", w)) + end + end + if (ucic:get(appname, "@global[0]", "tcp_node") or "nil") == w then + ucic:set(appname, '@global[0]', "tcp_node", "nil") + end + if (ucic:get(appname, "@global[0]", "udp_node") or "nil") == w then + ucic:set(appname, '@global[0]', "udp_node", "nil") + end + ucic:foreach(appname, "socks", function(t) + if t["node"] == w then + ucic:delete(appname, t[".name"]) + end + end) + ucic:foreach(appname, "haproxy_config", function(t) + if t["lbss"] == w then + ucic:delete(appname, t[".name"]) + end + end) + ucic:foreach(appname, "acl_rule", function(t) + if t["tcp_node"] == w then + ucic:set(appname, t[".name"], "tcp_node", "default") + end + if t["udp_node"] == w then + ucic:set(appname, t[".name"], "udp_node", "default") + end + end) + ucic:delete(appname, w) + end) + ucic:commit(appname) + luci.sys.call("/etc/init.d/" .. appname .. " restart > /dev/null 2>&1 &") +end + +function check_port() + function socket_connect(type, address, port) + local socket = nixio.socket(type, "stream") + socket:setopt("socket", "rcvtimeo", 3) + socket:setopt("socket", "sndtimeo", 3) + local ret = socket:connect(address, port) + if socket then socket:close() end + if tostring(ret) == "true" then + return true + end + return false + end + local result = {} + ucic:foreach(appname, "nodes", function(s) + 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 + local ip_type = api.get_ip_type(s.address) + local o = {} + o.remark = "%s:[%s] %s:%s" % {s.type, s.remarks, ip_type == "6" and '[' .. s.address .. ']' or s.address, s.port} + o.flag = socket_connect(ip_type == "6" and "inet6" or "inet", s.address, s.port) + if not o.flag and ip_type == "" then + o.flag = socket_connect("inet6", s.address, s.port) + end + result[#result + 1] = o + end + end + end) + luci.http.prepare_content("application/json") + luci.http.write_json(result) +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 &") + http_write_json() +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("/tmp/etc/passwall_server/" .. id .. ".log") then + local content = luci.sys.exec("cat /tmp/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 '/tmp/log/passwall_server.log' ] && cat /tmp/log/passwall_server.log")) +end + +function server_clear_log() + luci.sys.call("echo '' > /tmp/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"), http.formvalue("size")) + 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"), http.formvalue("size")) + end + + http_write_json(json) +end + +function v2ray_check() + local json = v2ray.to_check("") + http_write_json(json) +end + +function v2ray_update() + local json = nil + local task = http.formvalue("task") + if task == "extract" then + json = v2ray.to_extract(http.formvalue("file"), http.formvalue("subfix")) + elseif task == "move" then + json = v2ray.to_move(http.formvalue("file")) + else + json = v2ray.to_download(http.formvalue("url"), http.formvalue("size")) + 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"), http.formvalue("size")) + 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"), http.formvalue("size")) + end + + http_write_json(json) +end + +function hysteria_check() + local json = hysteria.to_check("") + http_write_json(json) +end + +function hysteria_update() + local json = nil + local task = http.formvalue("task") + if task == "move" then + json = hysteria.to_move(http.formvalue("file")) + else + json = hysteria.to_download(http.formvalue("url"), http.formvalue("size")) + end + + http_write_json(json) +end + diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/api/api.lua b/luci-app-passwall/luasrc/model/cbi/passwall/api/api.lua new file mode 100755 index 0000000..4c62a8d --- /dev/null +++ b/luci-app-passwall/luasrc/model/cbi/passwall/api/api.lua @@ -0,0 +1,597 @@ +module("luci.model.cbi.passwall.api.api", package.seeall) +fs = require "nixio.fs" +sys = require "luci.sys" +uci = require"luci.model.uci".cursor() +util = require "luci.util" +datatypes = require "luci.cbi.datatypes" +jsonc = require "luci.jsonc" +i18n = require "luci.i18n" + +appname = "passwall" +curl = "/usr/bin/curl" +curl_args = {"-skfL", "--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 repeat_exist(table, value) + local count = 0 + for index, k in ipairs(table) do + if k:find("-") and k == value then + count = count + 1 + end + end + if count > 1 then + return true + end + return false +end + +function get_args(arg) + local var = {} + for i, arg_k in pairs(arg) do + if i > 0 then + local v = arg[i + 1] + if v then + if repeat_exist(arg, v) == false then + var[arg_k] = v + end + end + end + end + return var +end + +function strToTable(str) + if str == nil or type(str) ~= "string" then + return {} + end + + return loadstring("return " .. str)() +end + +function is_normal_node(e) + if e and e.type and e.protocol and (e.protocol == "_balancing" or e.protocol == "_shunt") then + return false + end + return true +end + +function is_special_node(e) + return is_normal_node(e) == false +end + +function is_ip(val) + return datatypes.ipaddr(val) +end + +function is_ipv6(val) + local str = val + local address = val:match('%[(.*)%]') + if address then + str = address + end + if datatypes.ip6addr(str) then + return true + end + return false +end + +function is_ipv6addrport(val) + if is_ipv6(val) then + local address, port = val:match('%[(.*)%]:([^:]+)$') + if port then + return datatypes.port(port) + end + end + return false +end + +function get_ip_type(val) + if is_ipv6(val) then + return "6" + elseif datatypes.ip4addr(val) then + return "4" + end + return "" +end + +function is_mac(val) + return datatypes.macaddr(val) +end + +function ip_or_mac(val) + if val then + if get_ip_type(val) == "4" then + return "ip" + end + if is_mac(val) then + return "mac" + end + end + return "" +end + +function iprange(val) + if val then + local ipStart, ipEnd = val:match("^([^/]+)-([^/]+)$") + if (ipStart and datatypes.ip4addr(ipStart)) and (ipEnd and datatypes.ip4addr(ipEnd)) then + return true + end + end + return false +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 == "V2ray" or 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 == "V2ray" or 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_bin_version_cache(file, cmd) + sys.call("mkdir -p /tmp/etc/passwall_tmp") + if fs.access(file) then + chmod_755(file) + local md5 = sys.exec("echo -n $(md5sum " .. file .. " | awk '{print $1}')") + if fs.access("/tmp/etc/passwall_tmp/" .. md5) then + return sys.exec("echo -n $(cat /tmp/etc/passwall_tmp/%s)" % md5) + else + local version = sys.exec(string.format("echo -n $(%s %s)", file, cmd)) + sys.call("echo '" .. version .. "' > " .. "/tmp/etc/passwall_tmp/" .. md5) + return version + end + end + return "" +end + +function get_v2ray_path() + local path = uci_get_type("global_app", "v2ray_file") + return path +end + +function get_v2ray_version(file) + if file == nil then file = get_v2ray_path() end + local cmd = "-version | awk '{print $2}' | sed -n 1P" + return get_bin_version_cache(file, cmd) +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 + local cmd = "-version | awk '{print $2}' | sed -n 1P" + return get_bin_version_cache(file, cmd) +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 + local cmd = "-version | awk '{print $2}' | sed -n 1P" + return get_bin_version_cache(file, cmd) +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 + local cmd = "-v | awk '{print $3}'" + return get_bin_version_cache(file, cmd) +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 + local cmd = "-v | awk '{print $3}'" + return get_bin_version_cache(file, cmd) +end + +function get_hysteria_path() + local path = uci_get_type("global_app", "hysteria_file") + return path +end + +function get_hysteria_version(file) + if file == nil then file = get_hysteria_path() end + local cmd = "-v | awk '{print $3}'" + return get_bin_version_cache(file, cmd) +end + +function is_file(path) + if path and #path > 1 then + if sys.exec('[ -f "%s" ] && echo -n 1' % path) == "1" then + return true + end + end + return nil +end + +function is_dir(path) + if path and #path > 1 then + if sys.exec('[ -d "%s" ] && echo -n 1' % path) == "1" then + return true + end + end + return nil +end + +function get_final_dir(path) + if is_dir(path) then + return path + else + return get_final_dir(fs.dirname(path)) + end +end + +function get_free_space(dir) + if dir == nil then dir = "/" end + if sys.call("df -k " .. dir .. " >/dev/null 2>&1") == 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 + + if not ver1 then ver1 = "" end + if not ver2 then ver2 = "" end + + 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 = tonumber(av1[i] or 0) or 0 + local s2 = tonumber(av2[i] or 0) or 0 + + 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 + +function common_to_check(api_url, local_version, match_file_name) + local json = get_api_json(api_url) + + if #json > 0 then + json = json[1] + end + + if json.tag_name == nil then + return { + code = 1, + error = i18n.translate("Get remote version info failed.") + } + end + + local remote_version = json.tag_name + local has_update = compare_versions(local_version:match("[^v]+"), "<", remote_version:match("[^v]+")) + + if not has_update then + return { + code = 0, + local_version = local_version, + remote_version = remote_version + } + end + + local asset = {} + for _, v in ipairs(json.assets) do + if v.name and v.name:match(match_file_name) then + asset = v + break + end + end + if not asset.browser_download_url then + return { + code = 1, + local_version = local_version, + remote_version = remote_version, + html_url = json.html_url, + data = asset, + error = i18n.translate("New version found, but failed to get new version download url.") + } + end + + return { + code = 0, + has_update = true, + local_version = local_version, + remote_version = remote_version, + html_url = json.html_url, + data = asset + } +end \ No newline at end of file diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/api/brook.lua b/luci-app-passwall/luasrc/model/cbi/passwall/api/brook.lua new file mode 100644 index 0000000..8941b66 --- /dev/null +++ b/luci-app-passwall/luasrc/model/cbi/passwall/api/brook.lua @@ -0,0 +1,134 @@ +module("luci.model.cbi.passwall.api.brook", package.seeall) +local api = require "luci.model.cbi.passwall.api.api" +local fs = api.fs +local sys = api.sys +local util = api.util +local i18n = api.i18n + +local pre_release_url = "https://api.github.com/repos/txthinking/brook/releases?per_page=1" +local release_url = "https://api.github.com/repos/txthinking/brook/releases/latest" +local api_url = release_url +local app_path = api.get_brook_path() or "" + +function check_path() + 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 + return { + code = 0 + } +end + +function to_check(arch) + local result = check_path() + if result.code ~= 0 then + return result + 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 + + return api.common_to_check(api_url, api.get_brook_version(), "linux_" .. file_tree .. sub_version) +end + +function to_download(url, size) + local result = check_path() + if result.code ~= 0 then + return result + 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")) + + if size then + local kb1 = api.get_free_space("/tmp") + if tonumber(size) > tonumber(kb1) then + return {code = 1, error = i18n.translatef("%s not enough space.", "/tmp")} + end + end + + 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 result = check_path() + if result.code ~= 0 then + return result + 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 flag = sys.call('pgrep -af "passwall/.*brook" >/dev/null') + if flag == 0 then + sys.call("/etc/init.d/passwall stop") + end + + local old_app_size = 0 + if fs.access(app_path) then + old_app_size = api.get_file_space(app_path) + end + local new_app_size = api.get_file_space(file) + local final_dir = api.get_final_dir(app_path) + local final_dir_free_size = api.get_free_space(final_dir) + if final_dir_free_size > 0 then + final_dir_free_size = final_dir_free_size + old_app_size + if new_app_size > final_dir_free_size then + sys.call("/bin/rm -rf /tmp/brook_download.*") + return {code = 1, error = i18n.translatef("%s not enough space.", final_dir)} + end + end + + result = api.exec("/bin/mv", {"-f", file, app_path}, nil, api.command_timeout) == 0 + + sys.call("/bin/rm -rf /tmp/brook_download.*") + if flag == 0 then + sys.call("/etc/init.d/passwall restart >/dev/null 2>&1 &") + end + + 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 + + return {code = 0} +end diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_hysteria.lua b/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_hysteria.lua new file mode 100644 index 0000000..d1d646f --- /dev/null +++ b/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_hysteria.lua @@ -0,0 +1,61 @@ +local api = require "luci.model.cbi.passwall.api.api" +local uci = api.uci +local jsonc = api.jsonc + +local var = api.get_args(arg) +local node_section = var["-node"] +if not node_section then + print("-node 不能为空") + return +end +local local_tcp_redir_port = var["-local_tcp_redir_port"] +local local_udp_redir_port = var["-local_udp_redir_port"] +local local_socks_address = var["-local_socks_address"] or "0.0.0.0" +local local_socks_port = var["-local_socks_port"] +local local_socks_username = var["-local_socks_username"] +local local_socks_password = var["-local_socks_password"] +local local_http_address = var["-local_http_address"] or "0.0.0.0" +local local_http_port = var["-local_http_port"] +local local_http_username = var["-local_http_username"] +local local_http_password = var["-local_http_password"] +local node = uci:get_all("passwall", node_section) + +local config = { + server = node.address .. ":" .. node.port, + protocol = node.protocol or "udp", + obfs = node.hysteria_obfs, + auth = (node.hysteria_auth_type == "base64") and node.hysteria_auth_password or nil, + auth_str = (node.hysteria_auth_type == "string") and node.hysteria_auth_password or nil, + alpn = node.hysteria_alpn or nil, + server_name = node.tls_serverName, + insecure = (node.tls_allowInsecure == "1") and true or false, + up_mbps = tonumber(node.hysteria_up_mbps) or 10, + down_mbps = tonumber(node.hysteria_down_mbps) or 50, + recv_window_conn = (node.hysteria_recv_window_conn) and tonumber(node.hysteria_recv_window_conn) or nil, + recv_window = (node.hysteria_recv_window) and tonumber(node.hysteria_recv_window) or nil, + disable_mtu_discovery = (node.hysteria_disable_mtu_discovery) and true or false, + socks5 = (local_socks_address and local_socks_port) and { + listen = local_socks_address .. ":" .. local_socks_port, + timeout = 300, + disable_udp = false, + user = (local_socks_username and local_socks_password) and local_socks_username, + password = (local_socks_username and local_socks_password) and local_socks_password, + } or nil, + http = (local_http_address and local_http_port) and { + listen = local_http_address .. ":" .. local_http_port, + timeout = 300, + disable_udp = false, + user = (local_http_username and local_http_password) and local_http_username, + password = (local_http_username and local_http_password) and local_http_password, + } or nil, + tproxy_tcp = (local_tcp_redir_port) and { + listen = "0.0.0.0:" .. local_tcp_redir_port, + timeout = 300 + } or nil, + tproxy_udp = (local_udp_redir_port) and { + listen = "0.0.0.0:" .. local_udp_redir_port, + timeout = 60 + } or nil +} + +print(jsonc.stringify(config, 1)) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_naiveproxy.lua b/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_naiveproxy.lua new file mode 100644 index 0000000..dec0710 --- /dev/null +++ b/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_naiveproxy.lua @@ -0,0 +1,23 @@ +local api = require "luci.model.cbi.passwall.api.api" +local uci = api.uci +local jsonc = api.jsonc + +local var = api.get_args(arg) +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 = uci: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/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_shadowsocks.lua b/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_shadowsocks.lua new file mode 100644 index 0000000..cc7c95a --- /dev/null +++ b/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_shadowsocks.lua @@ -0,0 +1,69 @@ +local api = require "luci.model.cbi.passwall.api.api" +local uci = api.uci +local jsonc = api.jsonc + +local var = api.get_args(arg) +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 protocol = var["-protocol"] +local mode = var["-mode"] +local node = uci: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, + tcp_tproxy = var["-tcp_tproxy"] and true or nil +} + +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 + config.mode = mode +elseif node.type == "SS-Rust" then + config = { + servers = { + { + address = server_host or node.address, + port = tonumber(server_port) or tonumber(node.port), + method = node.method, + password = node.password, + timeout = tonumber(node.timeout), + plugin = (node.plugin and node.plugin ~= "none") and node.plugin or nil, + plugin_opts = (node.plugin and node.plugin ~= "none") and node.plugin_opts or nil + } + }, + locals = { + { + protocol = protocol, + local_address = local_addr, + local_port = tonumber(local_port), + mode = mode, + tcp_redir = var["-tcp_tproxy"] and "tproxy" or nil + } + }, + fast_open = (node.tcp_fast_open and node.tcp_fast_open == "true") and true or false + } +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/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_trojan.lua b/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_trojan.lua similarity index 61% rename from lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_trojan.lua rename to luci-app-passwall/luasrc/model/cbi/passwall/api/gen_trojan.lua index 6940ce8..ff7957b 100644 --- a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_trojan.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_trojan.lua @@ -1,12 +1,20 @@ -local ucursor = require"luci.model.uci".cursor() -local json = require "luci.jsonc" -local node_section = arg[1] -local run_type = arg[2] -local local_addr = arg[3] -local local_port = arg[4] -local server_host = arg[5] -local server_port = arg[6] -local node = ucursor:get_all("passwall", node_section) +local api = require "luci.model.cbi.passwall.api.api" +local uci = api.uci +local json = api.jsonc + +local var = api.get_args(arg) +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 = uci: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" @@ -17,11 +25,11 @@ local trojan = { remote_addr = server_host or node.address, remote_port = tonumber(server_port) or tonumber(node.port), password = {node.password}, - log_level = 1, + log_level = tonumber(loglevel), ssl = { verify = (node.tls_allowInsecure ~= "1") and true or false, verify_hostname = true, - cert = node.trojan_cert_path, + cert = nil, cipher = cipher, cipher_tls13 = cipher13, sni = node.tls_serverName or node.address, @@ -31,12 +39,8 @@ local trojan = { curves = "" }, udp_timeout = 60, - mux = (node.mux == "1") and { - enabled = true, - concurrency = tonumber(node.mux_concurrency), - idle_timeout = 60, - } or nil, tcp = { + use_tproxy = (node.type == "Trojan-Plus" and var["-use_tproxy"]) and true or nil, no_delay = true, keep_alive = true, reuse_port = true, @@ -45,12 +49,12 @@ local trojan = { } } 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.stream_security ~= "tls" and node.trojan_transport == "original" then trojan.ssl = nil end - trojan.transport_plugin = node.stream_security == "none" and node.trojan_transport == "original" and { + trojan.ssl.cipher = nil + trojan.ssl.cipher_tls13 = nil + trojan.ssl.fingerprint = (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, @@ -58,15 +62,20 @@ if node.type == "Trojan-Go" then 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 { + trojan.websocket = (node.trojan_transport == '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", + method = node.ss_aead_method or "aes_128_gcm", password = node.ss_aead_pwd or "" } or nil + trojan.mux = (node.smux == "1") and { + enabled = true, + concurrency = tonumber(node.mux_concurrency), + idle_timeout = tonumber(node.smux_idle_timeout) + } or nil end print(json.stringify(trojan, 1)) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_v2ray.lua b/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_v2ray.lua new file mode 100644 index 0000000..32a611a --- /dev/null +++ b/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_v2ray.lua @@ -0,0 +1,681 @@ +module("luci.model.cbi.passwall.api.gen_v2ray", package.seeall) +local api = require "luci.model.cbi.passwall.api.api" + +local var = api.get_args(arg) +local node_section = var["-node"] +local proto = var["-proto"] +local proxy_way = var["-proxy_way"] +local redir_port = var["-redir_port"] +local route_only = var["-route_only"] +local local_socks_address = var["-local_socks_address"] or "0.0.0.0" +local local_socks_port = var["-local_socks_port"] +local local_socks_username = var["-local_socks_username"] +local local_socks_password = var["-local_socks_password"] +local local_http_address = var["-local_http_address"] or "0.0.0.0" +local local_http_port = var["-local_http_port"] +local local_http_username = var["-local_http_username"] +local local_http_password = var["-local_http_password"] +local dns_listen_port = var["-dns_listen_port"] +local dns_server = var["-dns_server"] +local dns_tcp_server = var["-dns_tcp_server"] +local dns_cache = var["-dns_cache"] +local doh_url = var["-doh_url"] +local doh_host = var["-doh_host"] +local dns_client_ip = var["-dns_client_ip"] +local dns_query_strategy = var["-dns_query_strategy"] +local dns_socks_address = var["-dns_socks_address"] +local dns_socks_port = var["-dns_socks_port"] +local dns_fakedns = var["-dns_fakedns"] +local loglevel = var["-loglevel"] or "warning" +local network = proto +local new_port + +local uci = api.uci +local sys = api.sys +local jsonc = api.jsonc +local appname = api.appname +local dns = nil +local fakedns = 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, proxy_table) + local proxy = 0 + local proxy_tag = "nil" + if proxy_table ~= nil and type(proxy_table) == "table" then + proxy = proxy_table.proxy or 0 + proxy_tag = proxy_table.tag or "nil" + end + local result = nil + if node and node ~= "nil" then + local node_id = node[".name"] + if tag == nil then + tag = node_id + end + + if node.type == "V2ray" or node.type == "Xray" then + proxy = 0 + if proxy_tag ~= "nil" then + node.proxySettings = { + tag = proxy_tag, + transportLayer = true + } + end + end + + if node.type ~= "V2ray" and node.type ~= "Xray" 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"> /dev/null', + appname, + string.format("flag=%s node=%s bind=%s socks_port=%s config_file=%s relay_port=%s", + new_port, --flag + node_id, --node + "127.0.0.1", --bind + new_port, --socks port + string.format("/tmp/etc/%s/v2_%s_%s_%s.json", appname, node_type, node_id, new_port), --config file + (proxy == 1 and proxy_tag ~= "nil" 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.type == "Xray" and node.xtls and node.xtls == "1" then + node.stream_security = "xtls" + end + end + end + + result = { + _flag_tag = node_id, + _flag_proxy = proxy, + _flag_proxy_tag = proxy_tag, + 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.type == "Xray" and 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 or "none", + 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, + maxEarlyData = tonumber(node.ws_maxEarlyData) or nil + } or nil, + httpSettings = (node.transport == "h2") and { + path = node.h2_path, + host = node.h2_host, + read_idle_timeout = tonumber(node.h2_read_idle_timeout) or nil, + health_check_timeout = tonumber(node.h2_health_check_timeout) or nil + } 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, + multiMode = (node.grpc_mode == "multi") and true or nil, + idle_timeout = tonumber(node.grpc_idle_timeout) or nil, + health_check_timeout = tonumber(node.grpc_health_check_timeout) or nil, + permit_without_stream = (node.grpc_permit_without_stream == "1") and true or nil, + initial_windows_size = tonumber(node.grpc_initial_windows_size) or nil + } 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, + 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, + ivCheck = (node.iv_check == "1") and true or false, + password = node.password or "", + users = (node.username and node.password) and { + { + user = node.username, + pass = node.password + } + } or nil + } + } or nil + } + } + local alpn = {} + if node.alpn and node.alpn ~= "default" then + string.gsub(node.alpn, '[^' .. "," .. ']+', function(w) + table.insert(alpn, w) + end) + end + if alpn and #alpn > 0 then + if result.streamSettings.tlsSettings then + result.streamSettings.tlsSettings.alpn = alpn + end + if result.streamSettings.xtlsSettings then + result.streamSettings.xtlsSettings.alpn = alpn + end + end + end + return result +end + +if node_section then + local node = uci:get_all(appname, node_section) + if local_socks_port then + local inbound = { + listen = local_socks_address, + port = tonumber(local_socks_port), + protocol = "socks", + settings = {auth = "noauth", udp = true}, + sniffing = {enabled = true, destOverride = {"http", "tls"}} + } + if local_socks_username and local_socks_password and local_socks_username ~= "" and local_socks_password ~= "" then + inbound.settings.auth = "password" + inbound.settings.accounts = { + { + user = local_socks_username, + pass = local_socks_password + } + } + end + table.insert(inbounds, inbound) + network = "tcp,udp" + end + if local_http_port then + local inbound = { + listen = local_http_address, + port = tonumber(local_http_port), + protocol = "http", + settings = {allowTransparent = false} + } + if local_http_username and local_http_password and local_http_username ~= "" and local_http_password ~= "" then + inbound.settings.accounts = { + { + user = local_http_username, + pass = local_http_password + } + } + end + table.insert(inbounds, inbound) + end + + if redir_port then + table.insert(inbounds, { + port = tonumber(redir_port), + protocol = "dokodemo-door", + settings = {network = proto, followRedirect = true}, + streamSettings = {sockopt = {tproxy = proxy_way}}, + sniffing = {enabled = true, destOverride = {"http", "tls", (dns_fakedns) and "fakedns"}, metadataOnly = false, routeOnly = route_only and true or nil} + }) + end + + local up_trust_doh = uci: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 + table.insert(outbounds, { + protocol = "freedom", + tag = "direct", + settings = { + domainStrategy = "UseIPv4" + }, + streamSettings = { + sockopt = { + mark = 255 + } + } + }) + table.insert(outbounds, { + protocol = "blackhole", + tag = "blackhole" + }) + 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 = uci:get_all(appname, default_node_id) + local main_node_id = node.main_node or "nil" + local proxy = 0 + local proxy_tag + if main_node_id ~= "nil" then + local main_node = uci:get_all(appname, main_node_id) + if main_node and api.is_normal_node(main_node) and main_node_id ~= default_node_id then + local main_node_outbound = gen_outbound(main_node, "main") + if main_node_outbound then + table.insert(outbounds, main_node_outbound) + proxy = 1 + proxy_tag = "main" + if default_node.type ~= "V2ray" and default_node.type ~= "Xray" 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 + if default_node and api.is_normal_node(default_node) then + local default_outbound = gen_outbound(default_node, "default", { proxy = proxy, tag = proxy_tag }) + if default_outbound then + table.insert(outbounds, default_outbound) + default_outboundTag = "default" + end + end + end + + uci:foreach(appname, "shunt_rules", function(e) + local name = e[".name"] + local _node_id = node[name] or "nil" + local proxy_tag = node[name .. "_proxy_tag"] or "nil" + 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 _node = uci:get_all(appname, _node_id) + if _node and api.is_normal_node(_node) then + local new_outbound + for index, value in ipairs(outbounds) do + if value["_flag_tag"] == _node_id and value["_flag_proxy_tag"] == proxy_tag then + new_outbound = api.clone(value) + break + end + end + if new_outbound then + new_outbound["tag"] = name + table.insert(outbounds, new_outbound) + outboundTag = name + else + if _node.type ~= "V2ray" and _node.type ~= "Xray" then + if proxy_tag ~= "nil" 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 = proxy_tag + }) + end + end + local _outbound = gen_outbound(_node, name, { proxy = (proxy_tag ~= "nil") and 1 or 0, tag = (proxy_tag ~= "nil") and proxy_tag or nil }) + if _outbound then + table.insert(outbounds, _outbound) + outboundTag = name + end + 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", + domainMatcher = node.domainMatcher or "hybrid", + 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 = uci: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", + domainMatcher = node.domainMatcher or "hybrid", + 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 + routing = { + domainStrategy = "AsIs", + domainMatcher = "hybrid", + rules = {} + } + end +end + +if dns_server or dns_fakedns then + table.insert(outbounds, { + protocol = "dns", + tag = "dns-out" + }) + local rules = {} + + dns = { + tag = "dns-in1", + disableCache = (dns_cache and dns_cache == "0") and true or false, + servers = { + dns_server + }, + clientIp = (dns_client_ip and dns_client_ip ~= "") and dns_client_ip or nil, + queryStrategy = (dns_query_strategy and dns_query_strategy ~= "") and dns_query_strategy or nil + } + if doh_url and doh_host then + dns.hosts = { + [doh_host] = dns_server + } + if not redir_port and not dns_socks_port then + doh_url = doh_url:gsub("https://", "https+local://") + end + dns.servers = { + doh_url + } + end + + if dns_tcp_server then + if not redir_port and not dns_socks_port then + dns_tcp_server = dns_tcp_server:gsub("tcp://", "tcp+local://") + end + dns.servers = { + dns_tcp_server + } + end + + if dns_fakedns then + fakedns = {} + fakedns[#fakedns + 1] = { + ipPool = "198.18.0.0/16", + poolSize = 65535 + } + dns_server = "1.1.1.1" + dns.servers = { + "fakedns" + } + 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 = "tcp,udp" + } + }) + end + + table.insert(rules, { + type = "field", + inboundTag = { + "dns-in" + }, + outboundTag = "dns-out" + }) + + if dns_socks_address and dns_socks_port then + table.insert(outbounds, 1, { + tag = "out", + protocol = "socks", + streamSettings = { + network = "tcp", + security = "none" + }, + settings = { + servers = { + { + address = dns_socks_address, + port = tonumber(dns_socks_port) + } + } + } + }) + local outboundTag = "out" + table.insert(rules, { + type = "field", + inboundTag = { + "dns-in1" + }, + outboundTag = outboundTag + }) + end + + if node_section and (proto and proto:find("tcp")) and redir_port and not dns_fakedns then + local outboundTag = node_section + local node = uci:get_all(appname, node_section) + if node.protocol == "_shunt" then + outboundTag = "default" + end + table.insert(rules, { + type = "field", + inboundTag = { + "dns-in1" + }, + outboundTag = outboundTag + }) + end + + if not routing then + routing = { + domainStrategy = "IPOnDemand", + rules = rules + } + else + for index, value in ipairs(rules) do + table.insert(routing.rules, 1, value) + end + end +end + +if inbounds or outbounds then + local config = { + log = { + -- error = string.format("/tmp/etc/%s/%s.log", appname, node[".name"]), + loglevel = loglevel + }, + -- DNS + dns = dns, + fakedns = fakedns, + -- 传入连接 + 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(jsonc.stringify(config, 1)) +end diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_v2ray_proto.lua b/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_v2ray_proto.lua new file mode 100644 index 0000000..54c383f --- /dev/null +++ b/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_v2ray_proto.lua @@ -0,0 +1,111 @@ +local api = require "luci.model.cbi.passwall.api.api" +local jsonc = api.jsonc +local inbounds = {} +local outbounds = {} +local routing = nil + +local var = api.get_args(arg) +local local_socks_address = var["-local_socks_address"] or "0.0.0.0" +local local_socks_port = var["-local_socks_port"] +local local_socks_username = var["-local_socks_username"] +local local_socks_password = var["-local_socks_password"] +local local_http_address = var["-local_http_address"] or "0.0.0.0" +local local_http_port = var["-local_http_port"] +local local_http_username = var["-local_http_username"] +local local_http_password = var["-local_http_password"] +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_socks_address and local_socks_port then + local inbound = { + listen = local_socks_address, + port = tonumber(local_socks_port), + protocol = "socks", + settings = { + udp = true, + auth = "noauth" + } + } + if local_socks_username and local_socks_password and local_socks_username ~= "" and local_socks_password ~= "" then + inbound.settings.auth = "password" + inbound.settings.accounts = { + { + user = local_socks_username, + pass = local_socks_password + } + } + end + table.insert(inbounds, inbound) +end + +if local_http_address and local_http_port then + local inbound = { + listen = local_http_address, + port = tonumber(local_http_port), + protocol = "http", + settings = { + allowTransparent = false + } + } + if local_http_username and local_http_password and local_http_username ~= "" and local_http_password ~= "" then + inbound.settings.accounts = { + { + user = local_http_username, + pass = local_http_password + } + } + 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 config = { + log = { + -- error = string.format("/tmp/etc/passwall/%s.log", node[".name"]), + loglevel = "warning" + }, + -- 传入连接 + inbounds = inbounds, + -- 传出连接 + outbounds = outbounds, + -- 路由 + routing = routing +} +print(jsonc.stringify(config, 1)) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/api/hysteria.lua b/luci-app-passwall/luasrc/model/cbi/passwall/api/hysteria.lua new file mode 100644 index 0000000..2d2e361 --- /dev/null +++ b/luci-app-passwall/luasrc/model/cbi/passwall/api/hysteria.lua @@ -0,0 +1,134 @@ +module("luci.model.cbi.passwall.api.hysteria", package.seeall) +local api = require "luci.model.cbi.passwall.api.api" +local fs = api.fs +local sys = api.sys +local util = api.util +local i18n = api.i18n + +local pre_release_url = "https://api.github.com/repos/HyNetwork/hysteria/releases?per_page=1" +local release_url = "https://api.github.com/repos/HyNetwork/hysteria/releases/latest" +local api_url = release_url +local app_path = api.get_hysteria_path() or "" + +function check_path() + 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.", "hysteria") + } + end + return { + code = 0 + } +end + +function to_check(arch) + local result = check_path() + if result.code ~= 0 then + return result + 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 + + return api.common_to_check(api_url, api.get_hysteria_version(), "linux%-" .. file_tree .. sub_version) +end + +function to_download(url, size) + local result = check_path() + if result.code ~= 0 then + return result + end + + if not url or url == "" then + return {code = 1, error = i18n.translate("Download url is required.")} + end + + sys.call("/bin/rm -f /tmp/hysteria_download.*") + + local tmp_file = util.trim(util.exec("mktemp -u -t hysteria_download.XXXXXX")) + + if size then + local kb1 = api.get_free_space("/tmp") + if tonumber(size) > tonumber(kb1) then + return {code = 1, error = i18n.translatef("%s not enough space.", "/tmp")} + end + end + + 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 result = check_path() + if result.code ~= 0 then + return result + end + + if not file or file == "" or not fs.access(file) then + sys.call("/bin/rm -rf /tmp/hysteria_download.*") + return {code = 1, error = i18n.translate("Client file is required.")} + end + + local new_version = api.get_hysteria_version(file) + if new_version == "" then + sys.call("/bin/rm -rf /tmp/hysteria_download.*") + return { + code = 1, + error = i18n.translate("The client file is not suitable for current device.") + } + end + + local flag = sys.call('pgrep -af "passwall/.*hysteria" >/dev/null') + if flag == 0 then + sys.call("/etc/init.d/passwall stop") + end + + local old_app_size = 0 + if fs.access(app_path) then + old_app_size = api.get_file_space(app_path) + end + local new_app_size = api.get_file_space(file) + local final_dir = api.get_final_dir(app_path) + local final_dir_free_size = api.get_free_space(final_dir) + if final_dir_free_size > 0 then + final_dir_free_size = final_dir_free_size + old_app_size + if new_app_size > final_dir_free_size then + sys.call("/bin/rm -rf /tmp/hysteria_download.*") + return {code = 1, error = i18n.translatef("%s not enough space.", final_dir)} + end + end + + result = api.exec("/bin/mv", {"-f", file, app_path}, nil, api.command_timeout) == 0 + + sys.call("/bin/rm -rf /tmp/hysteria_download.*") + if flag == 0 then + sys.call("/etc/init.d/passwall restart >/dev/null 2>&1 &") + end + + 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 + + return {code = 0} +end diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/api/kcptun.lua b/luci-app-passwall/luasrc/model/cbi/passwall/api/kcptun.lua new file mode 100644 index 0000000..54abbda --- /dev/null +++ b/luci-app-passwall/luasrc/model/cbi/passwall/api/kcptun.lua @@ -0,0 +1,189 @@ +module("luci.model.cbi.passwall.api.kcptun", package.seeall) +local api = require "luci.model.cbi.passwall.api.api" +local fs = api.fs +local sys = api.sys +local util = api.util +local i18n = api.i18n + +local pre_release_url = "https://api.github.com/repos/xtaci/kcptun/releases?per_page=1" +local release_url = "https://api.github.com/repos/xtaci/kcptun/releases/latest" +local api_url = release_url +local app_path = api.get_kcptun_path() or "" + +function check_path() + 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 + return { + code = 0 + } +end + +function to_check(arch) + local result = check_path() + if result.code ~= 0 then + return result + 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 + + return api.common_to_check(api_url, api.get_kcptun_version(), "linux%-" .. file_tree .. sub_version) +end + +function to_download(url, size) + local result = check_path() + if result.code ~= 0 then + return result + 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")) + + if size then + local kb1 = api.get_free_space("/tmp") + if tonumber(size) > tonumber(kb1) then + return {code = 1, error = i18n.translatef("%s not enough space.", "/tmp")} + end + end + + 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 result = check_path() + if result.code ~= 0 then + return result + 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 new_file_size = api.get_file_space(file) + local tmp_free_size = api.get_free_space("/tmp") + if tmp_free_size <= 0 or tmp_free_size <= new_file_size then + return {code = 1, error = i18n.translatef("%s not enough space.", "/tmp")} + end + + 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 result = check_path() + if result.code ~= 0 then + return result + 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 flag = sys.call('pgrep -af "passwall/.*kcptun" >/dev/null') + if flag == 0 then + sys.call("/etc/init.d/passwall stop") + end + + local old_app_size = 0 + if fs.access(app_path) then + old_app_size = api.get_file_space(app_path) + end + local new_app_size = api.get_file_space(file) + local final_dir = api.get_final_dir(app_path) + local final_dir_free_size = api.get_free_space(final_dir) + if final_dir_free_size > 0 then + final_dir_free_size = final_dir_free_size + old_app_size + if new_app_size > final_dir_free_size then + sys.call("/bin/rm -rf /tmp/kcptun_extract.*") + return {code = 1, error = i18n.translatef("%s not enough space.", final_dir)} + end + end + + result = api.exec("/bin/mv", {"-f", file, app_path}, nil, api.command_timeout) == 0 + + sys.call("/bin/rm -rf /tmp/kcptun_extract.*") + if flag == 0 then + sys.call("/etc/init.d/passwall restart >/dev/null 2>&1 &") + end + + 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 + + return {code = 0} +end diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/api/trojan_go.lua b/luci-app-passwall/luasrc/model/cbi/passwall/api/trojan_go.lua new file mode 100644 index 0000000..4f8b484 --- /dev/null +++ b/luci-app-passwall/luasrc/model/cbi/passwall/api/trojan_go.lua @@ -0,0 +1,183 @@ +module("luci.model.cbi.passwall.api.trojan_go", package.seeall) +local api = require "luci.model.cbi.passwall.api.api" +local fs = api.fs +local sys = api.sys +local util = api.util +local i18n = api.i18n + +local pre_release_url = "https://api.github.com/repos/p4gefau1t/trojan-go/releases?per_page=1" +local release_url = "https://api.github.com/repos/p4gefau1t/trojan-go/releases/latest" +local api_url = release_url +local app_path = api.get_trojan_go_path() or "" + +function check_path() + 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 + return { + code = 0 + } +end + +function to_check(arch) + local result = check_path() + if result.code ~= 0 then + return result + 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 + + return api.common_to_check(api_url, api.get_trojan_go_version(), "linux%-" .. file_tree .. "%.zip") +end + +function to_download(url, size) + local result = check_path() + if result.code ~= 0 then + return result + 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")) + + if size then + local kb1 = api.get_free_space("/tmp") + if tonumber(size) > tonumber(kb1) then + return {code = 1, error = i18n.translatef("%s not enough space.", "/tmp")} + end + end + + 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 result = check_path() + if result.code ~= 0 then + return result + 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/trojan-go_extract.*") + + local new_file_size = api.get_file_space(file) + local tmp_free_size = api.get_free_space("/tmp") + if tmp_free_size <= 0 or tmp_free_size <= new_file_size then + return {code = 1, error = i18n.translatef("%s not enough space.", "/tmp")} + end + + 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 result = check_path() + if result.code ~= 0 then + return result + 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 bin_path = file .. "/trojan-go" + + local new_version = api.get_trojan_go_version(bin_path) + if new_version == "" then + sys.call("/bin/rm -rf /tmp/trojan-go_extract.*") + return { + code = 1, + error = i18n.translate("The client file is not suitable for current device.") + } + end + + local flag = sys.call('pgrep -af "passwall/.*trojan-go" >/dev/null') + if flag == 0 then + sys.call("/etc/init.d/passwall stop") + end + + local old_app_size = 0 + if fs.access(app_path) then + old_app_size = api.get_file_space(app_path) + end + local new_app_size = api.get_file_space(bin_path) + local final_dir = api.get_final_dir(app_path) + local final_dir_free_size = api.get_free_space(final_dir) + if final_dir_free_size > 0 then + final_dir_free_size = final_dir_free_size + old_app_size + if new_app_size > final_dir_free_size then + sys.call("/bin/rm -rf /tmp/trojan-go_extract.*") + return {code = 1, error = i18n.translatef("%s not enough space.", final_dir)} + end + end + + result = api.exec("/bin/mv", { "-f", bin_path, app_path }, nil, api.command_timeout) == 0 + + sys.call("/bin/rm -rf /tmp/trojan-go_extract.*") + if flag == 0 then + sys.call("/etc/init.d/passwall restart >/dev/null 2>&1 &") + end + + 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 + + return {code = 0} +end diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/api/v2ray.lua b/luci-app-passwall/luasrc/model/cbi/passwall/api/v2ray.lua new file mode 100644 index 0000000..c00bf14 --- /dev/null +++ b/luci-app-passwall/luasrc/model/cbi/passwall/api/v2ray.lua @@ -0,0 +1,181 @@ +module("luci.model.cbi.passwall.api.v2ray", package.seeall) +local api = require "luci.model.cbi.passwall.api.api" +local fs = api.fs +local sys = api.sys +local util = api.util +local i18n = api.i18n + +local pre_release_url = "https://api.github.com/repos/v2fly/v2ray-core/releases?per_page=1" +local release_url = "https://api.github.com/repos/v2fly/v2ray-core/releases/latest" +local api_url = release_url +local app_path = api.get_v2ray_path() or "" + +function check_path() + 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.", "V2ray") + } + end + return { + code = 0 + } +end + +function to_check(arch) + local result = check_path() + if result.code ~= 0 then + return result + 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 == "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 + if file_tree == "arm" then file_tree = "arm32" end + + return api.common_to_check(api_url, api.get_v2ray_version(), "linux%-" .. file_tree .. (sub_version ~= "" and ".+" .. sub_version or "")) +end + +function to_download(url, size) + local result = check_path() + if result.code ~= 0 then + return result + end + + if not url or url == "" then + return {code = 1, error = i18n.translate("Download url is required.")} + end + + sys.call("/bin/rm -f /tmp/v2ray_download.*") + + local tmp_file = util.trim(util.exec("mktemp -u -t v2ray_download.XXXXXX")) + + if size then + local kb1 = api.get_free_space("/tmp") + if tonumber(size) > tonumber(kb1) then + return {code = 1, error = i18n.translatef("%s not enough space.", "/tmp")} + end + end + + 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 result = check_path() + if result.code ~= 0 then + return result + 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/v2ray_extract.*") + + local new_file_size = api.get_file_space(file) + local tmp_free_size = api.get_free_space("/tmp") + if tmp_free_size <= 0 or tmp_free_size <= new_file_size then + return {code = 1, error = i18n.translatef("%s not enough space.", "/tmp")} + end + + local tmp_dir = util.trim(util.exec("mktemp -d -t v2ray_extract.XXXXXX")) + + local output = {} + api.exec("/usr/bin/unzip", {"-o", file, "v2ray", "-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 result = check_path() + if result.code ~= 0 then + return result + end + + if not file or file == "" then + sys.call("/bin/rm -rf /tmp/v2ray_extract.*") + return {code = 1, error = i18n.translate("Client file is required.")} + end + + local bin_path = file .. "/v2ray" + + local new_version = api.get_v2ray_version(bin_path) + if new_version == "" then + sys.call("/bin/rm -rf /tmp/v2ray_extract.*") + return { + code = 1, + error = i18n.translate("The client file is not suitable for current device.") + } + end + + local flag = sys.call('pgrep -af "passwall/.*v2ray" >/dev/null') + if flag == 0 then + sys.call("/etc/init.d/passwall stop") + end + + local old_app_size = 0 + if fs.access(app_path) then + old_app_size = api.get_file_space(app_path) + end + local new_app_size = api.get_file_space(bin_path) + local final_dir = api.get_final_dir(app_path) + local final_dir_free_size = api.get_free_space(final_dir) + if final_dir_free_size > 0 then + final_dir_free_size = final_dir_free_size + old_app_size + if new_app_size > final_dir_free_size then + sys.call("/bin/rm -rf /tmp/v2ray_extract.*") + return {code = 1, error = i18n.translatef("%s not enough space.", final_dir)} + end + end + + result = api.exec("/bin/mv", { "-f", bin_path, app_path }, nil, api.command_timeout) == 0 + + sys.call("/bin/rm -rf /tmp/v2ray_extract.*") + if flag == 0 then + sys.call("/etc/init.d/passwall restart >/dev/null 2>&1 &") + end + + 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 + + return {code = 0} +end diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/api/xray.lua b/luci-app-passwall/luasrc/model/cbi/passwall/api/xray.lua new file mode 100644 index 0000000..d56ab29 --- /dev/null +++ b/luci-app-passwall/luasrc/model/cbi/passwall/api/xray.lua @@ -0,0 +1,181 @@ +module("luci.model.cbi.passwall.api.xray", package.seeall) +local api = require "luci.model.cbi.passwall.api.api" +local fs = api.fs +local sys = api.sys +local util = api.util +local i18n = api.i18n + +local pre_release_url = "https://api.github.com/repos/XTLS/Xray-core/releases?per_page=1" +local release_url = "https://api.github.com/repos/XTLS/Xray-core/releases/latest" +local api_url = release_url +local app_path = api.get_xray_path() or "" + +function check_path() + 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 + return { + code = 0 + } +end + +function to_check(arch) + local result = check_path() + if result.code ~= 0 then + return result + 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 == "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 + if file_tree == "arm" then file_tree = "arm32" end + + return api.common_to_check(api_url, api.get_xray_version(), "linux%-" .. file_tree .. (sub_version ~= "" and ".+" .. sub_version or "")) +end + +function to_download(url, size) + local result = check_path() + if result.code ~= 0 then + return result + 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")) + + if size then + local kb1 = api.get_free_space("/tmp") + if tonumber(size) > tonumber(kb1) then + return {code = 1, error = i18n.translatef("%s not enough space.", "/tmp")} + end + end + + 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 result = check_path() + if result.code ~= 0 then + return result + 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 new_file_size = api.get_file_space(file) + local tmp_free_size = api.get_free_space("/tmp") + if tmp_free_size <= 0 or tmp_free_size <= new_file_size then + return {code = 1, error = i18n.translatef("%s not enough space.", "/tmp")} + end + + local tmp_dir = util.trim(util.exec("mktemp -d -t xray_extract.XXXXXX")) + + local output = {} + api.exec("/usr/bin/unzip", {"-o", file, "xray", "-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 result = check_path() + if result.code ~= 0 then + return result + 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 + + local bin_path = file .. "/xray" + + local new_version = api.get_xray_version(bin_path) + if new_version == "" then + sys.call("/bin/rm -rf /tmp/xray_extract.*") + return { + code = 1, + error = i18n.translate("The client file is not suitable for current device.") + } + end + + local flag = sys.call('pgrep -af "passwall/.*xray" >/dev/null') + if flag == 0 then + sys.call("/etc/init.d/passwall stop") + end + + local old_app_size = 0 + if fs.access(app_path) then + old_app_size = api.get_file_space(app_path) + end + local new_app_size = api.get_file_space(bin_path) + local final_dir = api.get_final_dir(app_path) + local final_dir_free_size = api.get_free_space(final_dir) + if final_dir_free_size > 0 then + final_dir_free_size = final_dir_free_size + old_app_size + if new_app_size > final_dir_free_size then + sys.call("/bin/rm -rf /tmp/xray_extract.*") + return {code = 1, error = i18n.translatef("%s not enough space.", final_dir)} + end + end + + result = api.exec("/bin/mv", { "-f", bin_path, app_path }, nil, api.command_timeout) == 0 + + sys.call("/bin/rm -rf /tmp/xray_extract.*") + if flag == 0 then + sys.call("/etc/init.d/passwall restart >/dev/null 2>&1 &") + end + + 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 + + return {code = 0} +end diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/acl.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/acl.lua new file mode 100644 index 0000000..4a9dd67 --- /dev/null +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/acl.lua @@ -0,0 +1,119 @@ +local api = require "luci.model.cbi.passwall.api.api" +local appname = api.appname +local sys = api.sys +local has_chnlist = api.fs.access("/usr/share/passwall/rules/chnlist") + +m = Map(appname) + +local global_proxy_mode = (m:get("@global[0]", "tcp_proxy_mode") or "") .. (m:get("@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.") .. "") +s.template = "cbi/tblsection" +s.sortable = true +s.anonymous = true +s.addremove = true +s.extedit = api.url("acl_config", "%s") +function s.create(e, t) + t = TypedSection.create(e, t) + luci.http.redirect(e.extedit:format(t)) +end + +---- 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 + +local mac_t = {} +sys.net.mac_hints(function(e, t) + mac_t[e] = { + ip = t, + mac = e + } +end) + +o = s:option(DummyValue, "sources", translate("Source")) +o.rawhtml = true +o.cfgvalue = function(t, n) + local e = '' + local v = Value.cfgvalue(t, n) or '' + string.gsub(v, '[^' .. " " .. ']+', function(w) + local a = w + if mac_t[w] then + a = a .. ' (' .. mac_t[w].ip .. ')' + end + if #e > 0 then + e = e .. "
" + end + e = e .. a + end) + return e +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 has_chnlist and 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 +tcp_proxy_mode:value("direct/proxy", translate("Only use direct/proxy list")) + +---- 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 has_chnlist and 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("Not China List")) +end +udp_proxy_mode:value("direct/proxy", translate("Only use direct/proxy list")) + +--[[ +---- 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/luci-app-passwall/luasrc/model/cbi/passwall/client/acl_config.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/acl_config.lua new file mode 100644 index 0000000..bee1882 --- /dev/null +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/acl_config.lua @@ -0,0 +1,291 @@ +local api = require "luci.model.cbi.passwall.api.api" +local appname = api.appname +local sys = api.sys +local has_v2ray = api.is_finded("v2ray") +local has_xray = api.is_finded("xray") +local has_chnlist = api.fs.access("/usr/share/passwall/rules/chnlist") + +m = Map(appname) + +local nodes_table = {} +for k, e in ipairs(api.get_valid_nodes()) do + nodes_table[#nodes_table + 1] = e +end + +local global_proxy_mode = (m:get("@global[0]", "tcp_proxy_mode") or "") .. (m:get("@global[0]", "udp_proxy_mode") or "") + +local dynamicList_write = function(self, section, value) + local t = {} + local t2 = {} + if type(value) == "table" then + local x + for _, x in ipairs(value) do + if x and #x > 0 then + if not t2[x] then + t2[x] = x + t[#t+1] = x + end + end + end + else + t = { value } + end + t = table.concat(t, " ") + return DynamicList.write(self, section, t) +end + +-- [[ ACLs Settings ]]-- +s = m:section(NamedSection, arg[1], translate("ACLs"), translate("ACLs")) +s.addremove = false +s.dynamic = false + +---- Enable +o = s:option(Flag, "enabled", translate("Enable")) +o.default = 1 +o.rmempty = false + +---- Remarks +o = s:option(Value, "remarks", translate("Remarks")) +o.default = arg[1] +o.rmempty = true + +local mac_t = {} +sys.net.mac_hints(function(e, t) + mac_t[#mac_t + 1] = { + ip = t, + mac = e + } +end) +table.sort(mac_t, function(a,b) + if #a.ip < #b.ip then + return true + elseif #a.ip == #b.ip then + if a.ip < b.ip then + return true + else + return #a.ip < #b.ip + end + end + return false +end) + +---- Source +sources = s:option(DynamicList, "sources", translate("Source")) +sources.description = "
  • " .. translate("Example:") +.. "
  • " .. translate("MAC") .. ": 00:00:00:FF:FF:FF" +.. "
  • " .. translate("IP") .. ": 192.168.1.100" +.. "
  • " .. translate("IP CIDR") .. ": 192.168.1.0/24" +.. "
  • " .. translate("IP range") .. ": 192.168.1.100-192.168.1.200" +.. "
  • " .. translate("IPSet") .. ": ipset:lanlist" +.. "
" +sources.cast = "string" +for _, key in pairs(mac_t) do + sources:value(key.mac, "%s (%s)" % {key.mac, key.ip}) +end +sources.cfgvalue = function(self, section) + local value + if self.tag_error[section] then + value = self:formvalue(section) + else + value = self.map:get(section, self.option) + if type(value) == "string" then + local value2 = {} + string.gsub(value, '[^' .. " " .. ']+', function(w) table.insert(value2, w) end) + value = value2 + end + end + return value +end +sources.validate = function(self, value, t) + local err = {} + for _, v in ipairs(value) do + local flag = false + if v:find("ipset:") and v:find("ipset:") == 1 then + local ipset = v:gsub("ipset:", "") + if ipset and ipset ~= "" then + flag = true + end + end + + if flag == false and datatypes.macaddr(v) then + flag = true + end + + if flag == false and datatypes.ip4addr(v) then + flag = true + end + + if flag == false and api.iprange(v) then + flag = true + end + + if flag == false then + err[#err + 1] = v + end + end + + if #err > 0 then + self:add_error(t, "invalid", translate("Not true format, please re-enter!")) + for _, v in ipairs(err) do + self:add_error(t, "invalid", v) + end + end + + return value +end +sources.write = dynamicList_write + +---- 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 has_chnlist and 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 +tcp_proxy_mode:value("direct/proxy", translate("Only use direct/proxy list")) + +---- 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 has_chnlist and 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("Not China List")) +end +udp_proxy_mode:value("direct/proxy", translate("Only use direct/proxy list")) + +---- 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") + +tcp_node = s:option(ListValue, "tcp_node", "" .. translate("TCP Node") .. "") +tcp_node.default = "default" +tcp_node:value("default", translate("Default")) + +udp_node = s:option(ListValue, "udp_node", "" .. translate("UDP Node") .. "") +udp_node.default = "default" +udp_node:value("default", translate("Default")) +udp_node:value("tcp", translate("Same as the tcp node")) + +for k, v in pairs(nodes_table) do + tcp_node:value(v.id, v["remark"]) + udp_node:value(v.id, v["remark"]) +end + +---- DNS Forward Mode +o = s:option(ListValue, "dns_mode", translate("Filter Mode")) +o:depends({ tcp_node = "default", ['!reverse'] = true }) +if api.is_finded("dns2socks") then + o:value("dns2socks", "dns2socks") +end +if has_v2ray then + o:value("v2ray", "V2ray") +end +if has_xray then + o:value("xray", "Xray") +end + +o = s:option(ListValue, "v2ray_dns_mode", " ") +o:value("tcp", "TCP") +o:value("doh", "DoH") +o:depends("dns_mode", "v2ray") +o:depends("dns_mode", "xray") + +---- DNS Forward +o = s:option(Value, "dns_forward", translate("Remote DNS")) +o.default = "1.1.1.1" +o:value("1.1.1.1", "1.1.1.1 (CloudFlare DNS)") +o:value("1.1.1.2", "1.1.1.2 (CloudFlare DNS)") +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("v2ray_dns_mode", "tcp") + +if has_v2ray or has_xray then +---- DoH +o = s:option(Value, "dns_doh", translate("DoH request address")) +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:value("https://dns.adguard.com/dns-query,176.103.130.130", "AdGuard") +o.default = "https://cloudflare-dns.com/dns-query,1.1.1.1" +o.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 api.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 +o:depends("v2ray_dns_mode", "doh") +end + +o = s:option(Value, "dns_client_ip", translate("EDNS Client Subnet")) +o.datatype = "ipaddr" +o:depends("v2ray_dns_mode", "doh") + +o = s:option(ListValue, "dns_query_strategy", translate("Query Strategy")) +o.default = "UseIPv4" +o:value("UseIPv4") +o:value("UseIPv6") +o:value("UseIP") +o:depends("dns_mode", "v2ray") +o:depends("dns_mode", "xray") + +return m diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/app_update.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/app_update.lua new file mode 100644 index 0000000..206a34e --- /dev/null +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/app_update.lua @@ -0,0 +1,49 @@ +local api = require "luci.model.cbi.passwall.api.api" +local appname = api.appname + +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/v2ray_version")) +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")) +s:append(Template(appname .. "/app_update/hysteria_version")) + +o = s:option(Value, "v2ray_file", translatef("%s App Path", "V2ray")) +o.default = "/usr/bin/v2ray" +o.rmempty = false + +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(Value, "hysteria_file", translatef("%s App Path", "Hysteria")) +o.default = "/usr/bin/hysteria" +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/luci-app-passwall/luasrc/model/cbi/passwall/client/auto_switch.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/auto_switch.lua new file mode 100644 index 0000000..221de29 --- /dev/null +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/auto_switch.lua @@ -0,0 +1,66 @@ +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 + +o = s:option(Value, "testing_time", translate("How often to test"), translate("Units:minutes")) +o.datatype = "uinteger" +o.default = 1 + +o = s:option(Value, "connect_timeout", translate("Timeout seconds"), translate("Units:seconds")) +o.datatype = "uinteger" +o.default = 3 + +o = s:option(Value, "retry_num", translate("Timeout retry num")) +o.datatype = "uinteger" +o.default = 3 + +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 +function o.write(self, section, value) + local t = {} + local t2 = {} + if type(value) == "table" then + local x + for _, x in ipairs(value) do + if x and #x > 0 then + if not t2[x] then + t2[x] = x + t[#t+1] = x + end + end + end + else + t = { value } + end + return DynamicList.write(self, section, t) +end + +o = s:option(Flag, "restore_switch", "TCP " .. translate("Restore Switch"), translate("When detects main node is available, switch back to the main node.")) + +o = s:option(ListValue, "shunt_logic", "TCP " .. translate("If the main node is V2ray/Xray shunt")) +o:value("0", translate("Switch it")) +o:value("1", translate("Applying to the default node")) +o:value("2", translate("Applying to the default preproxy node")) + +m:append(Template(appname .. "/auto_switch/footer")) + +return m diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua new file mode 100644 index 0000000..8a191ed --- /dev/null +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua @@ -0,0 +1,471 @@ +local api = require "luci.model.cbi.passwall.api.api" +local appname = api.appname +local uci = api.uci +local datatypes = api.datatypes +local has_v2ray = api.is_finded("v2ray") +local has_xray = api.is_finded("xray") +local has_chnlist = api.fs.access("/usr/share/passwall/rules/chnlist") + +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 '/tmp/etc/%s/id/TCP' ] && echo -n $(cat /tmp/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_v2ray or 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.protocol 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, string.format('* %s', 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, string.format('* %s', translate("Default Preproxy")), translate("When using, localhost will connect this node first and then use this node to connect the default node.")) + 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")) + +s:tab("DNS", translate("DNS")) + +if api.is_finded("smartdns") then + dns_shunt = s:taboption("DNS", ListValue, "dns_shunt", translate("DNS Shunt")) + dns_shunt:value("dnsmasq", "Dnsmasq") + dns_shunt:value("smartdns", "SmartDNS") + + group_domestic = s:taboption("DNS", Value, "group_domestic", translate("Domestic group name")) + group_domestic.placeholder = "local" + group_domestic:depends("dns_shunt", "smartdns") + group_domestic.description = translate("You only need to configure domestic DNS packets in SmartDNS and set it redirect or as Dnsmasq upstream, and fill in the domestic DNS group name here.") +end + +o = s:taboption("DNS", Flag, "filter_proxy_ipv6", translate("Filter Proxy Host IPv6"), translate("Experimental feature.")) +o.default = "0" + +---- DNS Forward Mode +dns_mode = s:taboption("DNS", ListValue, "dns_mode", translate("Filter Mode")) +dns_mode.rmempty = false +dns_mode:reset_values() +if api.is_finded("pdnsd") then + dns_mode:value("pdnsd", "pdnsd " .. translatef("Requery DNS By %s", translate("TCP Node"))) +end +if api.is_finded("dns2socks") then + dns_mode:value("dns2socks", "dns2socks") +end +if has_v2ray then + dns_mode:value("v2ray", "V2ray") +end +if has_xray then + dns_mode:value("xray", "Xray") +end +dns_mode:value("udp", translatef("Requery DNS By %s", "UDP")) + +o = s:taboption("DNS", ListValue, "v2ray_dns_mode", " ") +o:value("tcp", "TCP") +o:value("doh", "DoH") +o:value("fakedns", "FakeDNS") +o:depends("dns_mode", "v2ray") +o:depends("dns_mode", "xray") +o.validate = function(self, value, t) + if value == "fakedns" then + local _dns_mode = dns_mode:formvalue(t) + local _tcp_node = tcp_node:formvalue(t) + if m:get(_tcp_node, "type"):lower() ~= _dns_mode then + return nil, translatef("TCP node must be '%s' type to use FakeDNS.", _dns_mode) + end + end + return value +end + +o = s:taboption("DNS", ListValue, "dns_by", 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("v2ray_dns_mode", "tcp") +o:depends("v2ray_dns_mode", "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_by = "socks"}) + +---- DoH +o = s:taboption("DNS", Value, "up_trust_doh", translate("DoH request address")) +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:value("https://dns.adguard.com/dns-query,176.103.130.130", "AdGuard") +o.default = "https://cloudflare-dns.com/dns-query,1.1.1.1" +o.validate = doh_validate +o:depends("v2ray_dns_mode", "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.datatype = "or(ipaddr,ipaddrport)" +o.default = "1.1.1.1" +o:value("1.1.1.1", "1.1.1.1 (CloudFlare DNS)") +o:value("1.1.1.2", "1.1.1.2 (CloudFlare DNS)") +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:depends({v2ray_dns_mode = "tcp"}) + +o = s:taboption("DNS", Value, "dns_client_ip", translate("EDNS Client Subnet")) +o.description = translate("Notify the DNS server when the DNS query is notified, the location of the client (cannot be a private IP address).") .. "
" .. + translate("This feature requires the DNS server to support the Edns Client Subnet (RFC7871).") +o.datatype = "ipaddr" +o:depends("v2ray_dns_mode", "tcp") +o:depends("v2ray_dns_mode", "doh") + +o = s:taboption("DNS", ListValue, "dns_query_strategy", translate("Query Strategy")) +o.default = "UseIPv4" +o:value("UseIPv4") +o:value("UseIPv6") +o:value("UseIP") +o:depends({dns_mode = "v2ray", v2ray_dns_mode = "tcp"}) +o:depends({dns_mode = "v2ray", v2ray_dns_mode = "doh"}) +o:depends({dns_mode = "xray", v2ray_dns_mode = "tcp"}) +o:depends({dns_mode = "xray", v2ray_dns_mode = "doh"}) + +o = s:taboption("DNS", Flag, "dns_cache", translate("Cache Resolved")) +o.default = "1" +o:depends({dns_mode = "dns2socks"}) +o:depends({dns_mode = "pdnsd"}) +o:depends({dns_mode = "v2ray", v2ray_dns_mode = "tcp"}) +o:depends({dns_mode = "v2ray", v2ray_dns_mode = "doh"}) +o:depends({dns_mode = "xray", v2ray_dns_mode = "tcp"}) +o:depends({dns_mode = "xray", v2ray_dns_mode = "doh"}) +o.rmempty = false + +if has_chnlist and api.is_finded("chinadns-ng") then + o = s:taboption("DNS", Flag, "chinadns_ng", translate("ChinaDNS-NG"), translate("The effect is better, but will increase the memory.")) + o.default = "0" + o:depends({dns_mode = "dns2socks"}) + o:depends({dns_mode = "pdnsd"}) + o:depends({dns_mode = "v2ray", v2ray_dns_mode = "tcp"}) + o:depends({dns_mode = "v2ray", v2ray_dns_mode = "doh"}) + o:depends({dns_mode = "xray", v2ray_dns_mode = "tcp"}) + o:depends({dns_mode = "xray", v2ray_dns_mode = "doh"}) + o:depends({dns_mode = "udp"}) +end + +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 &") + luci.http.redirect(api.url("log")) +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")) +if has_chnlist then + tcp_proxy_mode:value("returnhome", translate("China List")) +end +tcp_proxy_mode:value("direct/proxy", translate("Only use direct/proxy 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("Not China List")) +if has_chnlist then + udp_proxy_mode:value("returnhome", translate("China List")) +end +udp_proxy_mode:value("direct/proxy", translate("Only use direct/proxy 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", translatef("Same as the %s default proxy mode", "TCP")) +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")) +if has_chnlist then + localhost_tcp_proxy_mode:value("returnhome", translate("China List")) +end +localhost_tcp_proxy_mode:value("disable", translate("No Proxy")) +localhost_tcp_proxy_mode:value("direct/proxy", translate("Only use direct/proxy 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", translatef("Same as the %s default proxy mode", "UDP")) +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("Not China List")) +if has_chnlist then + localhost_udp_proxy_mode:value("returnhome", translate("China List")) +end +localhost_udp_proxy_mode:value("disable", translate("No Proxy")) +localhost_udp_proxy_mode:value("direct/proxy", translate("Only use direct/proxy list")) +localhost_udp_proxy_mode.default = "default" +localhost_udp_proxy_mode.validate = redir_mode_validate + +tips = s:taboption("Proxy", DummyValue, "tips", " ") +tips.rawhtml = true +tips.cfgvalue = function(t, n) + return string.format('%s', api.url("acl"), translate("Want different devices to use different proxy modes/ports/nodes? Please use access control.")) +end + +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", "V2ray/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("faq", "FAQ") + +o = s:taboption("faq", DummyValue, "") +o.template = appname .. "/global/faq" + +-- [[ 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")) + +local n = 0 +uci:foreach(appname, "socks", function(s) + if s[".name"] == section then + return false + end + n = n + 1 +end) + +o = s:option(Value, "port", "Socks " .. translate("Listen Port")) +o.default = n + 1080 +o.datatype = "port" +o.rmempty = false + +if has_v2ray or 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_v2ray or 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/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/haproxy.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/haproxy.lua similarity index 55% rename from lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/haproxy.lua rename to luci-app-passwall/luasrc/model/cbi/passwall/client/haproxy.lua index d2ddedf..a127008 100644 --- a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/haproxy.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/haproxy.lua @@ -1,8 +1,8 @@ -local e = require "luci.sys" -local net = require "luci.model.network".init() -local uci = require "luci.model.uci".cursor() local api = require "luci.model.cbi.passwall.api.api" -local appname = "passwall" +local appname = api.appname +local sys = api.sys +local net = require "luci.model.network".init() +local datatypes = api.datatypes local nodes_table = {} for k, e in ipairs(api.get_valid_nodes()) do @@ -10,7 +10,7 @@ for k, e in ipairs(api.get_valid_nodes()) do nodes_table[#nodes_table + 1] = { id = e[".name"], obj = e, - remarks = e.remarks_name + remarks = e["remark"] } end end @@ -31,28 +31,43 @@ o.default = false ---- Console Username o = s:option(Value, "console_user", translate("Console Username")) o.default = "" -o:depends("balancing_enable", 1) +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", 1) +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", 1) +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.").."") + "" .. + 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 +s.create = function(e, t) + TypedSection.create(e, api.gen_uuid()) +end + +s.remove = function(self, section) + for k, v in pairs(self.children) do + v.rmempty = true + v.validate = nil + end + TypedSection.remove(self, section) +end + ---- Enable o = s:option(Flag, "enabled", translate("Enable")) o.default = 1 @@ -60,38 +75,40 @@ 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" +for k, v in pairs(nodes_table) do o:value(v.id, v.remarks) end o.rmempty = false +o.validate = function(self, value) + if not value then return nil end + local t = m:get(value) or nil + if t and t[".type"] == "nodes" then + return value + end + if datatypes.hostport(value) or datatypes.ip4addrport(value) then + return value + end + if api.is_ipv6addrport(value) then + return value + end + return nil, value +end ---- Haproxy Port o = s:option(Value, "haproxy_port", translate("Haproxy Port")) -o.default = "1181" +o.datatype = "port" +o.default = 1181 o.rmempty = false ---- Node Weight o = s:option(Value, "lbweight", translate("Node Weight")) -o.default = "5" +o.datatype = "uinteger" +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 +local wa = require "luci.tools.webadmin" +wa.cbi_add_networks(o) o.default = 0 o.rmempty = false diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/log.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/log.lua new file mode 100644 index 0000000..5580e17 --- /dev/null +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/log.lua @@ -0,0 +1,8 @@ +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/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/node_config.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_config.lua similarity index 53% rename from lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/node_config.lua rename to luci-app-passwall/luasrc/model/cbi/passwall/client/node_config.lua index a14a6f2..20134b1 100644 --- a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/node_config.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_config.lua @@ -1,17 +1,19 @@ -local d = require "luci.dispatcher" -local uci = require"luci.model.uci".cursor() local api = require "luci.model.cbi.passwall.api.api" -local appname = "passwall" +local appname = api.appname +local uci = api.uci 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-192-ctr", "aes-256-ctr", "bf-cfb", "salsa20", "chacha20", "chacha20-ietf", "aes-128-gcm", "aes-192-gcm", "aes-256-gcm", "chacha20-ietf-poly1305", "xchacha20-ietf-poly1305" } +local ss_rust_encrypt_method_list = { + "plain", "none", + "aes-128-gcm", "aes-256-gcm", "chacha20-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", @@ -32,35 +34,32 @@ local ssr_obfs_list = { } 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" + "aes-128-gcm", "aes-256-gcm", "chacha20-poly1305" } -local security_list = {"none", "auto", "aes-128-gcm", "chacha20-poly1305"} +local x_ss_encrypt_method_list = { + "aes-128-gcm", "aes-256-gcm", "chacha20-poly1305", "xchacha20-poly1305" +} + +local security_list = {"none", "auto", "aes-128-gcm", "chacha20-poly1305", "zero"} 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 = d.build_url("admin", "services", appname) +m.redirect = api.url() s = m:section(NamedSection, arg[1], "nodes", "") s.addremove = false s.dynamic = false -share = s:option(DummyValue, "passwall", translate("Share Current")) +share = s:option(DummyValue, "passwall", " ") share.rawhtml = true share.template = "passwall/node_list/link_share_man" share.value = arg[1] @@ -74,14 +73,20 @@ if api.is_finded("ipt2socks") then type:value("Socks", translate("Socks")) end if api.is_finded("ss-redir") then - type:value("SS", translate("Shadowsocks")) + type:value("SS", translate("Shadowsocks Libev")) +end +if api.is_finded("sslocal") then + type:value("SS-Rust", translate("Shadowsocks Rust")) end if api.is_finded("ssr-redir") then - type:value("SSR", translate("ShadowsocksR")) + type:value("SSR", translate("ShadowsocksR Libev")) end if api.is_finded("v2ray") then type:value("V2ray", translate("V2ray")) 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 @@ -99,6 +104,9 @@ end if api.is_finded("naive") then type:value("Naiveproxy", translate("NaiveProxy")) end +if api.is_finded("hysteria") then + type:value("Hysteria", translate("Hysteria")) +end protocol = s:option(ListValue, "protocol", translate("Protocol")) protocol:value("vmess", translate("Vmess")) @@ -110,13 +118,14 @@ protocol:value("trojan", translate("Trojan")) protocol:value("_balancing", translate("Balancing")) protocol:value("_shunt", translate("Shunt")) protocol:depends("type", "V2ray") +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.remarks_name + remarks = e["remark"] } end end @@ -128,21 +137,68 @@ balancing_node:depends("protocol", "_balancing") -- 分流 uci:foreach(appname, "shunt_rules", function(e) - o = s:option(ListValue, e[".name"], translate(e.remarks)) + o = s:option(ListValue, e[".name"], string.format('* %s', api.url("shunt_rules", e[".name"]), translate(e.remarks))) o:value("nil", translate("Close")) - for k, v in pairs(nodes_table) do o:value(v.id, v.remarks) end + o:value("_default", translate("Default")) + o:value("_direct", translate("Direct Connection")) + o:value("_blackhole", translate("Blackhole")) o:depends("protocol", "_shunt") - o = s:option(Flag, e[".name"] .. "_proxy", translate(e.remarks) .. translate("Preproxy"), translate("Use the default node for the transit.")) - o.default = 0 - o:depends("protocol", "_shunt") + if #nodes_table > 0 then + _proxy_tag = s:option(ListValue, e[".name"] .. "_proxy_tag", string.format('* %s', translate(e.remarks) .. " " .. translate("Preproxy"))) + _proxy_tag:value("nil", translate("Close")) + _proxy_tag:value("default", translate("Default")) + _proxy_tag:value("main", translate("Default Preproxy")) + _proxy_tag.default = "nil" + + for k, v in pairs(nodes_table) do + o:value(v.id, v.remarks) + _proxy_tag:depends(e[".name"], v.id) + end + end end) -default_node = s:option(ListValue, "default_node", translate("Default") .. " " .. translate("Node")) -default_node:value("nil", translate("Close")) +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", string.format('* %s', translate("Default"))) +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", string.format('* %s', translate("Default Preproxy")), translate("When using, localhost will connect this node first and then use this node to connect 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.default = "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") + +domainMatcher = s:option(ListValue, "domainMatcher", translate("Domain matcher")) +domainMatcher:value("hybrid") +domainMatcher:value("linear") +domainMatcher:depends("protocol", "_balancing") +domainMatcher:depends("protocol", "_shunt") + + -- Brook协议 brook_protocol = s:option(ListValue, "brook_protocol", translate("Protocol")) brook_protocol:value("client", translate("Brook")) @@ -174,35 +230,51 @@ address = s:option(Value, "address", translate("Address (Support Domain Name)")) address.rmempty = false address:depends("type", "Socks") address:depends("type", "SS") +address:depends("type", "SS-Rust") 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", "Hysteria") address:depends({ type = "V2ray", protocol = "vmess" }) address:depends({ type = "V2ray", protocol = "vless" }) address:depends({ type = "V2ray", protocol = "http" }) address:depends({ type = "V2ray", protocol = "socks" }) address:depends({ type = "V2ray", protocol = "shadowsocks" }) address:depends({ type = "V2ray", protocol = "trojan" }) +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", "SS-Rust") 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", "Hysteria") use_ipv6:depends({ type = "V2ray", protocol = "vmess" }) use_ipv6:depends({ type = "V2ray", protocol = "vless" }) use_ipv6:depends({ type = "V2ray", protocol = "http" }) use_ipv6:depends({ type = "V2ray", protocol = "socks" }) use_ipv6:depends({ type = "V2ray", protocol = "shadowsocks" }) use_ipv6:depends({ type = "V2ray", protocol = "trojan" }) +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")) @@ -210,29 +282,40 @@ port.datatype = "port" port.rmempty = false port:depends("type", "Socks") port:depends("type", "SS") +port:depends("type", "SS-Rust") 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", "Hysteria") port:depends({ type = "V2ray", protocol = "vmess" }) port:depends({ type = "V2ray", protocol = "vless" }) port:depends({ type = "V2ray", protocol = "http" }) port:depends({ type = "V2ray", protocol = "socks" }) port:depends({ type = "V2ray", protocol = "shadowsocks" }) port:depends({ type = "V2ray", protocol = "trojan" }) +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 = "V2ray", protocol = "http" }) username:depends({ type = "V2ray", protocol = "socks" }) +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", "SS-Rust") password:depends("type", "SSR") password:depends("type", "Brook") password:depends("type", "Trojan") @@ -243,8 +326,41 @@ password:depends({ type = "V2ray", protocol = "http" }) password:depends({ type = "V2ray", protocol = "socks" }) password:depends({ type = "V2ray", protocol = "shadowsocks" }) password:depends({ type = "V2ray", protocol = "trojan" }) +password:depends({ type = "Xray", protocol = "http" }) +password:depends({ type = "Xray", protocol = "socks" }) +password:depends({ type = "Xray", protocol = "shadowsocks" }) +password:depends({ type = "Xray", protocol = "trojan" }) + +hysteria_protocol = s:option(ListValue, "hysteria_protocol", translate("Protocol")) +hysteria_protocol:value("udp", "UDP") +hysteria_protocol:value("faketcp", "faketcp") +hysteria_protocol:value("wechat-video", "wechat-video") +hysteria_protocol:depends("type", "Hysteria") +function hysteria_protocol.cfgvalue(self, section) + return m:get(section, "protocol") +end +function hysteria_protocol.write(self, section, value) + m:set(section, "protocol", value) +end + +hysteria_obfs = s:option(Value, "hysteria_obfs", translate("Obfs Password")) +hysteria_obfs:depends("type", "Hysteria") -ss_encrypt_method = s:option(ListValue, "ss_encrypt_method", translate("Encrypt Method")) +hysteria_auth_type = s:option(ListValue, "hysteria_auth_type", translate("Auth Type")) +hysteria_auth_type:value("disable", translate("Disable")) +hysteria_auth_type:value("string", translate("STRING")) +hysteria_auth_type:value("base64", translate("BASE64")) +hysteria_auth_type:depends("type", "Hysteria") + +hysteria_auth_password = s:option(Value, "hysteria_auth_password", translate("Auth Password")) +hysteria_auth_password.password = true +hysteria_auth_password:depends("hysteria_auth_type", "string") +hysteria_auth_password:depends("hysteria_auth_type", "base64") + +hysteria_alpn = s:option(Value, "hysteria_alpn", translate("QUIC TLS ALPN")) +hysteria_alpn:depends("type", "Hysteria") + +ss_encrypt_method = s:option(Value, "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) @@ -254,7 +370,17 @@ 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")) +ss_rust_encrypt_method = s:option(Value, "ss_rust_encrypt_method", translate("Encrypt Method")) +for a, t in ipairs(ss_rust_encrypt_method_list) do ss_rust_encrypt_method:value(t) end +ss_rust_encrypt_method:depends("type", "SS-Rust") +function ss_rust_encrypt_method.cfgvalue(self, section) + return m:get(section, "method") +end +function ss_rust_encrypt_method.write(self, section, value) + m:set(section, "method", value) +end + +ssr_encrypt_method = s:option(Value, "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) @@ -267,14 +393,17 @@ end security = s:option(ListValue, "security", translate("Encrypt Method")) for a, t in ipairs(security_list) do security:value(t) end security:depends({ type = "V2ray", protocol = "vmess" }) +security:depends({ type = "Xray", protocol = "vmess" }) encryption = s:option(Value, "encryption", translate("Encrypt Method")) encryption.default = "none" +encryption:value("none") encryption:depends({ type = "V2ray", protocol = "vless" }) +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") +v_ss_encrypt_method:depends({ type = "V2ray", protocol = "shadowsocks" }) function v_ss_encrypt_method.cfgvalue(self, section) return m:get(section, "method") end @@ -282,7 +411,21 @@ function v_ss_encrypt_method.write(self, section, value) m:set(section, "method", value) end -ssr_protocol = s:option(ListValue, "ssr_protocol", translate("Protocol")) +x_ss_encrypt_method = s:option(ListValue, "x_ss_encrypt_method", translate("Encrypt Method")) +for a, t in ipairs(x_ss_encrypt_method_list) do x_ss_encrypt_method:value(t) end +x_ss_encrypt_method:depends({ type = "Xray", protocol = "shadowsocks" }) +function x_ss_encrypt_method.cfgvalue(self, section) + return m:get(section, "method") +end +function x_ss_encrypt_method.write(self, section, value) + m:set(section, "method", value) +end + +iv_check = s:option(Flag, "iv_check", translate("IV Check")) +iv_check:depends({ type = "V2ray", protocol = "shadowsocks" }) +iv_check:depends({ type = "Xray", protocol = "shadowsocks" }) + +ssr_protocol = s:option(Value, "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) @@ -295,7 +438,7 @@ end protocol_param = s:option(Value, "protocol_param", translate("Protocol_param")) protocol_param:depends("type", "SSR") -obfs = s:option(ListValue, "obfs", translate("Obfs")) +obfs = s:option(Value, "obfs", translate("Obfs")) for a, t in ipairs(ssr_obfs_list) do obfs:value(t) end obfs:depends("type", "SSR") @@ -306,12 +449,14 @@ timeout = s:option(Value, "timeout", translate("Connection Timeout")) timeout.datatype = "uinteger" timeout.default = 300 timeout:depends("type", "SS") +timeout:depends("type", "SS-Rust") 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", "SS-Rust") tcp_fast_open:depends("type", "SSR") tcp_fast_open:depends("type", "Trojan") tcp_fast_open:depends("type", "Trojan-Plus") @@ -319,9 +464,11 @@ 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("xray-plugin") then ss_plugin:value("xray-plugin") end 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") +ss_plugin:depends("type", "SS-Rust") function ss_plugin.cfgvalue(self, section) return m:get(section, "plugin") end @@ -330,6 +477,7 @@ function ss_plugin.write(self, section, value) end ss_plugin_opts = s:option(Value, "ss_plugin_opts", translate("opts")) +ss_plugin_opts:depends("ss_plugin", "xray-plugin") ss_plugin_opts:depends("ss_plugin", "v2ray-plugin") ss_plugin_opts:depends("ss_plugin", "obfs-local") function ss_plugin_opts.cfgvalue(self, section) @@ -339,12 +487,12 @@ 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"), +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", "SS-Rust") 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") @@ -362,85 +510,115 @@ uuid = s:option(Value, "uuid", translate("ID")) uuid.password = true uuid:depends({ type = "V2ray", protocol = "vmess" }) uuid:depends({ type = "V2ray", protocol = "vless" }) - -alter_id = s:option(Value, "alter_id", translate("Alter ID")) -alter_id:depends("protocol", "vmess") - -level = s:option(Value, "level", translate("User Level")) -level.default = 1 -level:depends({ type = "V2ray", protocol = "vmess" }) -level:depends({ type = "V2ray", protocol = "vless" }) -level:depends({ type = "V2ray", protocol = "trojan" }) - -flow = s:option(Value, "flow", translate("flow")) -flow.placeholder = "xtls-rprx-origin" ---flow:value("xtls-rprx-origin") ---flow:value("xtls-rprx-origin-udp443") ---flow:value("xtls-rprx-direct") ---flow:value("xtls-rprx-direct-udp443") -flow:depends({ type = "V2ray", protocol = "vless" }) - -stream_security = s:option(ListValue, "stream_security", translate("Transport Layer Encryption"), translate('Whether or not transport layer encryption is enabled, "none" for unencrypted, "tls" for using TLS, "xtls" for using XTLS.')) -stream_security:value("none", "none") -stream_security:value("tls", "tls") -stream_security:value("xtls", "xtls") -stream_security.default = "tls" -stream_security:depends({ type = "V2ray", protocol = "vmess" }) -stream_security:depends({ type = "V2ray", protocol = "vless" }) -stream_security:depends({ type = "V2ray", protocol = "socks" }) -stream_security:depends({ type = "V2ray", protocol = "shadowsocks" }) -stream_security:depends({ type = "V2ray", protocol = "trojan" }) -stream_security:depends("type", "Trojan") -stream_security:depends("type", "Trojan-Plus") -stream_security:depends("type", "Trojan-Go") -stream_security.validate = function(self, value) - if value == "none" and (type:formvalue(arg[1]) == "Trojan" or type:formvalue(arg[1]) == "Trojan-Plus") then - return nil, translate("'none' not supported for original Trojan, please choose 'tls'.") +uuid:depends({ type = "Xray", protocol = "vmess" }) +uuid:depends({ type = "Xray", protocol = "vless" }) + +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 - return value end +tls:depends({ type = "V2ray", protocol = "vmess" }) +tls:depends({ type = "V2ray", protocol = "vless" }) +tls:depends({ type = "V2ray", protocol = "socks" }) +tls:depends({ type = "V2ray", protocol = "trojan" }) +tls:depends({ type = "V2ray", protocol = "shadowsocks" }) +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) + +alpn = s:option(ListValue, "alpn", translate("alpn")) +alpn.default = "default" +alpn:value("default", translate("Default")) +alpn:value("h2,http/1.1") +alpn:value("h2") +alpn:value("http/1.1") +alpn:depends({ type = "V2ray", tls = true }) +alpn:depends({ type = "Xray", tls = true }) -- [[ TLS部分 ]] -- tls_sessionTicket = s:option(Flag, "tls_sessionTicket", translate("Session Ticket")) tls_sessionTicket.default = "0" -tls_sessionTicket:depends({ type = "Trojan", stream_security = "tls" }) -tls_sessionTicket:depends({ type = "Trojan-Plus", stream_security = "tls" }) -tls_sessionTicket:depends({ type = "Trojan-Go", stream_security = "tls" }) - --- [[ Trojan TLS ]]-- -trojan_force_fp = s:option(ListValue, "fingerprint", translate("Finger Print")) -for a, t in ipairs(force_fp) do trojan_force_fp:value(t) end -trojan_force_fp.default = "firefox" -trojan_force_fp:depends({ type = "Trojan-Go", stream_security = "tls" }) +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")) +trojan_go_fingerprint:value("disable", translate("Disable")) +trojan_go_fingerprint:value("firefox") +trojan_go_fingerprint:value("chrome") +trojan_go_fingerprint:value("ios") +trojan_go_fingerprint.default = "disable" +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("stream_security", "tls") -tls_serverName:depends("stream_security", "xtls") +tls_serverName:depends("tls", true) +tls_serverName:depends("type", "Hysteria") 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("stream_security", "tls") -tls_allowInsecure:depends("stream_security", "xtls") - --- [[ Trojan Cert ]]-- -trojan_cert_path = s:option(Value, "trojan_cert_path", translate("Trojan Cert Path")) -trojan_cert_path.default = "" -trojan_cert_path:depends({ stream_security = "tls", tls_allowInsecure = false }) +tls_allowInsecure:depends("tls", true) +tls_allowInsecure:depends("type", "Hysteria") + +xray_fingerprint = s:option(ListValue, "xray_fingerprint", translate("Finger Print")) +xray_fingerprint:value("disable", translate("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 }) +function xray_fingerprint.cfgvalue(self, section) + return m:get(section, "fingerprint") +end +function xray_fingerprint.write(self, section, value) + m:set(section, "fingerprint", value) +end trojan_transport = s:option(ListValue, "trojan_transport", translate("Transport")) -trojan_transport:value("original", "Original") +trojan_transport:value("original", translate("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 = s:option(ListValue, "plugin_type", translate("Transport Plugin")) trojan_plugin:value("plaintext", "Plain Text") trojan_plugin:value("shadowsocks", "ShadowSocks") trojan_plugin:value("other", "Other") trojan_plugin.default = "plaintext" -trojan_plugin:depends({ stream_security = "none", trojan_transport = "original" }) +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" @@ -464,11 +642,17 @@ transport:value("ws", "WebSocket") transport:value("h2", "HTTP/2") transport:value("ds", "DomainSocket") transport:value("quic", "QUIC") +transport:value("grpc", "gRPC") transport:depends({ type = "V2ray", protocol = "vmess" }) transport:depends({ type = "V2ray", protocol = "vless" }) transport:depends({ type = "V2ray", protocol = "socks" }) transport:depends({ type = "V2ray", protocol = "shadowsocks" }) transport:depends({ type = "V2ray", protocol = "trojan" }) +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")) @@ -476,6 +660,7 @@ ss_transport:value("ws", "WebSocket") ss_transport:value("h2", "HTTP/2") ss_transport:value("h2+ws", "HTTP/2 & WebSocket") ss_transport:depends({ type = "V2ray", protocol = "shadowsocks" }) +ss_transport:depends({ type = "Xray", protocol = "shadowsocks" }) ]]-- -- [[ TCP部分 ]]-- @@ -534,30 +719,49 @@ mkcp_seed:depends("transport", "mkcp") 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") +ws_path:depends({ type = "Brook", brook_protocol = "wsclient" }) + +ws_enableEarlyData = s:option(Flag, "ws_enableEarlyData", translate("Enable early data")) +ws_enableEarlyData:depends("transport", "ws") + +ws_maxEarlyData = s:option(Value, "ws_maxEarlyData", translate("Early data length")) +ws_maxEarlyData.default = "1024" +ws_maxEarlyData:depends("ws_enableEarlyData", true) +function ws_maxEarlyData.cfgvalue(self, section) + return m:get(section, "ws_maxEarlyData") +end +function ws_maxEarlyData.write(self, section, value) + m:set(section, "ws_maxEarlyData", value) +end -- [[ 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") + +h2_health_check = s:option(Flag, "h2_health_check", translate("Health check")) +h2_health_check:depends({ type = "Xray", transport = "h2"}) + +h2_read_idle_timeout = s:option(Value, "h2_read_idle_timeout", translate("Idle timeout")) +h2_read_idle_timeout.default = "10" +h2_read_idle_timeout:depends("h2_health_check", true) + +h2_health_check_timeout = s:option(Value, "h2_health_check_timeout", translate("Health check timeout")) +h2_health_check_timeout.default = "15" +h2_health_check_timeout:depends("h2_health_check", true) -- [[ DomainSocket部分 ]]-- -ds_path = s:option(Value, "ds_path", "Path", translate("A legal file path. This file must not exist before running V2Ray.")) +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部分 ]]-- @@ -574,55 +778,92 @@ 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") + +grpc_mode = s:option(ListValue, "grpc_mode", "gRPC " .. translate("Transfer mode")) +grpc_mode:value("gun") +grpc_mode:value("multi") +grpc_mode:depends({ type = "Xray", transport = "grpc"}) + +grpc_health_check = s:option(Flag, "grpc_health_check", translate("Health check")) +grpc_health_check:depends({ type = "Xray", transport = "grpc"}) + +grpc_idle_timeout = s:option(Value, "grpc_idle_timeout", translate("Idle timeout")) +grpc_idle_timeout.default = "10" +grpc_idle_timeout:depends("grpc_health_check", true) + +grpc_health_check_timeout = s:option(Value, "grpc_health_check_timeout", translate("Health check timeout")) +grpc_health_check_timeout.default = "20" +grpc_health_check_timeout:depends("grpc_health_check", true) + +grpc_permit_without_stream = s:option(Flag, "grpc_permit_without_stream", translate("Permit without stream")) +grpc_permit_without_stream.default = "0" +grpc_permit_without_stream:depends("grpc_health_check", true) + +grpc_initial_windows_size = s:option(Value, "grpc_initial_windows_size", translate("Initial Windows Size")) +grpc_initial_windows_size.default = "0" +grpc_initial_windows_size:depends({ type = "Xray", transport = "grpc"}) + -- [[ Trojan-Go Shadowsocks2 ]] -- -ss_aead = s:option(Flag, "ss_aead", translate("Shadowsocks2")) +ss_aead = s:option(Flag, "ss_aead", translate("Shadowsocks secondary encryption")) 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.default = "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") +-- [[ Trojan-Go Mux ]]-- +mux = s:option(Flag, "smux", translate("Smux")) +mux:depends("type", "Trojan-Go") + -- [[ Mux ]]-- mux = s:option(Flag, "mux", translate("Mux")) mux:depends({ type = "V2ray", protocol = "vmess" }) -mux:depends({ type = "V2ray", protocol = "vless" }) +mux:depends({ type = "V2ray", protocol = "vless", xtls = false }) mux:depends({ type = "V2ray", protocol = "http" }) mux:depends({ type = "V2ray", protocol = "socks" }) mux:depends({ type = "V2ray", protocol = "shadowsocks" }) -mux:depends("type", "Trojan-Go") - -mux_concurrency = s:option(Value, "mux_concurrency", translate("Mux Concurrency")) +mux:depends({ type = "V2ray", protocol = "trojan" }) +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 = "Xray", protocol = "trojan" }) + +mux_concurrency = s:option(Value, "mux_concurrency", translate("Mux concurrency")) mux_concurrency.default = 8 -mux_concurrency:depends("mux", "1") +mux_concurrency:depends("mux", true) +mux_concurrency:depends("smux", true) --- [[ 当作为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", "V2ray") +smux_idle_timeout = s:option(Value, "smux_idle_timeout", translate("Mux idle timeout")) +smux_idle_timeout.default = 60 +smux_idle_timeout:depends("smux", true) -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") +hysteria_up_mbps = s:option(Value, "hysteria_up_mbps", translate("Max upload Mbps")) +hysteria_up_mbps.default = "10" +hysteria_up_mbps:depends("type", "Hysteria") -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") +hysteria_down_mbps = s:option(Value, "hysteria_down_mbps", translate("Max download Mbps")) +hysteria_down_mbps.default = "50" +hysteria_down_mbps:depends("type", "Hysteria") -tcp_socks_auth_username = s:option(Value, "tcp_socks_auth_username", "Socks " .. translate("Username")) -tcp_socks_auth_username:depends("tcp_socks_auth", "password") +hysteria_recv_window_conn = s:option(Value, "hysteria_recv_window_conn", translate("QUIC stream receive window")) +hysteria_recv_window_conn:depends("type", "Hysteria") -tcp_socks_auth_password = s:option(Value, "tcp_socks_auth_password", "Socks " .. translate("Password")) -tcp_socks_auth_password:depends("tcp_socks_auth", "password") ---]] +hysteria_recv_window = s:option(Value, "hysteria_recv_window", translate("QUIC connection receive window")) +hysteria_recv_window:depends("type", "Hysteria") + +hysteria_disable_mtu_discovery = s:option(Flag, "hysteria_disable_mtu_discovery", translate("Disable MTU detection")) +hysteria_disable_mtu_discovery:depends("type", "Hysteria") protocol.validate = function(self, value) if value == "_shunt" or value == "_balancing" then diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/node_list.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_list.lua new file mode 100644 index 0000000..ccf5ee6 --- /dev/null +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_list.lua @@ -0,0 +1,145 @@ +local api = require "luci.model.cbi.passwall.api.api" +local appname = api.appname +local sys = api.sys +local datatypes = api.datatypes + +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) + m.uci:foreach(appname, "socks", function(s) + if s["node"] == t then + m:del(s[".name"]) + end + end) + m.uci:foreach(appname, "haproxy_config", function(s) + if s["lbss"] and s["lbss"] == t then + m:del(s[".name"]) + end + end) + m.uci:foreach(appname, "acl_rule", function(s) + if s["tcp_node"] and s["tcp_node"] == t then + m:set(s[".name"], "tcp_node", "default") + end + if s["udp_node"] and s["udp_node"] == t then + m:set(s[".name"], "udp_node", "default") + end + end) + for k, v in ipairs(m:get("@auto_switch[0]", "tcp_node") or {}) do + if v and v == t then + sys.call(string.format("uci -q del_list %s.@auto_switch[0].tcp_node='%s'", appname, v)) + end + end + TypedSection.remove(e, t) + local new_node = "nil" + local node0 = m:get("@nodes[0]") or nil + if node0 then + new_node = node0[".name"] + end + if (m:get("@global[0]", "tcp_node") or "nil") == t then + m:set('@global[0]', "tcp_node", new_node) + end + if (m:get("@global[0]", "udp_node") or "nil") == t then + m:set('@global[0]', "udp_node", new_node) + end +end + +s.sortable = true +-- 简洁模式 +o = s:option(DummyValue, "add_from", "") +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 == "V2ray" or 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") +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/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe.lua new file mode 100644 index 0000000..71be3cc --- /dev/null +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe.lua @@ -0,0 +1,142 @@ +local api = require "luci.model.cbi.passwall.api.api" +local appname = api.appname +local has_ss = api.is_finded("ss-redir") +local has_ss_rust = api.is_finded("sslocal") +local has_trojan_plus = api.is_finded("trojan-plus") +local has_v2ray = api.is_finded("v2ray") +local has_xray = api.is_finded("xray") +local has_trojan_go = api.is_finded("trojan-go") +local ss_aead_type = {} +local trojan_type = {} +if has_ss then + ss_aead_type[#ss_aead_type + 1] = "shadowsocks-libev" +end +if has_ss_rust then + ss_aead_type[#ss_aead_type + 1] = "shadowsocks-rust" +end +if has_trojan_plus then + trojan_type[#trojan_type + 1] = "trojan-plus" +end +if has_v2ray then + trojan_type[#trojan_type + 1] = "v2ray" + ss_aead_type[#ss_aead_type + 1] = "v2ray" +end +if has_xray then + trojan_type[#trojan_type + 1] = "xray" + ss_aead_type[#ss_aead_type + 1] = "xray" +end +if has_trojan_go then + trojan_type[#trojan_type + 1] = "trojan-go" +end + +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 + +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:value("3", translate("Discard List,But Keep List First")) +o:value("4", translate("Keep List,But Discard List First")) + +o = s:option(DynamicList, "filter_discard_list", translate("Discard List")) + +o = s:option(DynamicList, "filter_keep_list", translate("Keep List")) + +if #ss_aead_type > 0 then + o = s:option(ListValue, "ss_aead_type", translate("SS AEAD Node Use Type")) + for key, value in pairs(ss_aead_type) do + o:value(value, translate(value:gsub("^%l",string.upper))) + end +end + +if #trojan_type > 0 then + o = s:option(ListValue, "trojan_type", translate("Trojan Node Use Type")) + for key, value in pairs(trojan_type) do + o:value(value, translate(value:gsub("^%l",string.upper))) + end +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 > /dev/null 2>&1") +end + +o = s:option(Button, "_update", translate("Manual subscription All")) +o.inputstyle = "apply" +function o.write(t, n) + luci.sys.call("lua /usr/share/" .. appname .. "/subscribe.lua start > /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 manual subscription.") .. "") +s.addremove = true +s.anonymous = true +s.sortable = true +s.template = "cbi/tblsection" +s.extedit = api.url("node_subscribe_config", "%s") +function s.create(e, t) + local id = TypedSection.create(e, t) + luci.http.redirect(e.extedit:format(id)) +end + +o = s:option(Value, "remark", translate("Remarks")) +o.width = "auto" +o.rmempty = false +o.validate = function(self, value, t) + if value then + local count = 0 + m.uci:foreach(appname, "subscribe_list", function(e) + if e[".name"] ~= t and e["remark"] == value then + count = count + 1 + end + end) + if count > 0 then + return nil, translate("This remark already exists, please change a new remark.") + end + return value + end +end + +o = s:option(DummyValue, "_node_count") +o.rawhtml = true +o.cfgvalue = function(t, n) + local remark = m:get(n, "remark") or "" + local num = 0 + m.uci:foreach(appname, "nodes", function(s) + if s["add_from"] ~= "" and s["add_from"] == remark then + num = num + 1 + end + end) + return string.format("%s", remark .. " " .. translate("Node num") .. ": " .. num, num) +end + +o = s:option(Value, "url", translate("Subscribe URL")) +o.width = "auto" +o.rmempty = false + +o = s:option(Button, "_remove", translate("Delete the subscribed node")) +o.inputstyle = "remove" +function o.write(t, n) + local remark = m:get(n, "remark") or "" + luci.sys.call("lua /usr/share/" .. appname .. "/subscribe.lua truncate " .. remark .. " > /dev/null 2>&1") +end + +o = s:option(Button, "_update", translate("Manual subscription")) +o.inputstyle = "apply" +function o.write(t, n) + luci.sys.call("lua /usr/share/" .. appname .. "/subscribe.lua start " .. n .. " > /dev/null 2>&1 &") + luci.http.redirect(api.url("log")) +end + +return m diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe_config.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe_config.lua new file mode 100644 index 0000000..402ba48 --- /dev/null +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe_config.lua @@ -0,0 +1,110 @@ +local api = require "luci.model.cbi.passwall.api.api" +local appname = api.appname +local sys = api.sys +local has_ss = api.is_finded("ss-redir") +local has_ss_rust = api.is_finded("sslocal") +local has_trojan_plus = api.is_finded("trojan-plus") +local has_v2ray = api.is_finded("v2ray") +local has_xray = api.is_finded("xray") +local has_trojan_go = api.is_finded("trojan-go") +local ss_aead_type = {} +local trojan_type = {} +if has_ss then + ss_aead_type[#ss_aead_type + 1] = "shadowsocks-libev" +end +if has_ss_rust then + ss_aead_type[#ss_aead_type + 1] = "shadowsocks-rust" +end +if has_trojan_plus then + trojan_type[#trojan_type + 1] = "trojan-plus" +end +if has_v2ray then + trojan_type[#trojan_type + 1] = "v2ray" + ss_aead_type[#ss_aead_type + 1] = "v2ray" +end +if has_xray then + trojan_type[#trojan_type + 1] = "xray" + ss_aead_type[#ss_aead_type + 1] = "xray" +end +if has_trojan_go then + trojan_type[#trojan_type + 1] = "trojan-go" +end + +m = Map(appname) +m.redirect = api.url("node_subscribe") + +s = m:section(NamedSection, arg[1]) +s.addremove = false +s.dynamic = false + +o = s:option(Value, "remark", translate("Subscribe Remark")) +o.rmempty = false + +o = s:option(TextValue, "url", translate("Subscribe URL")) +o.rows = 5 +o.rmempty = false + +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 + +o = s:option(ListValue, "filter_keyword_mode", translate("Filter keyword Mode")) +o.default = "5" +o:value("0", translate("Close")) +o:value("1", translate("Discard List")) +o:value("2", translate("Keep List")) +o:value("3", translate("Discard List,But Keep List First")) +o:value("4", translate("Keep List,But Discard List First")) +o:value("5", translate("Use global config")) + +o = s:option(DynamicList, "filter_discard_list", translate("Discard List")) +o:depends("filter_keyword_mode", "1") +o:depends("filter_keyword_mode", "3") +o:depends("filter_keyword_mode", "4") + +o = s:option(DynamicList, "filter_keep_list", translate("Keep List")) +o:depends("filter_keyword_mode", "2") +o:depends("filter_keyword_mode", "3") +o:depends("filter_keyword_mode", "4") + +if #ss_aead_type > 0 then + o = s:option(ListValue, "ss_aead_type", translate("SS AEAD Node Use Type")) + o.default = "global" + o:value("global", translate("Use global config")) + for key, value in pairs(ss_aead_type) do + o:value(value, translate(value:gsub("^%l",string.upper))) + end +end + +if #trojan_type > 0 then + o = s:option(ListValue, "trojan_type", translate("Trojan Node Use Type")) + o.default = "global" + o:value("global", translate("Use global config")) + for key, value in pairs(trojan_type) do + o:value(value, translate(value:gsub("^%l",string.upper))) + end +end + +---- Enable auto update subscribe +o = s:option(Flag, "auto_update", translate("Enable auto update subscribe")) +o.default = 0 +o.rmempty = false + +---- Week update rules +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) + +---- Day update rules +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, "user_agent", translate("User-Agent")) +o.default = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36" + +return m diff --git a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/other.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/other.lua similarity index 69% rename from lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/other.lua rename to luci-app-passwall/luasrc/model/cbi/passwall/client/other.lua index e9eddc1..e92fc8f 100644 --- a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/other.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/other.lua @@ -1,5 +1,5 @@ -local uci = require"luci.model.uci".cursor() -local appname = "passwall" +local api = require "luci.model.cbi.passwall.api.api" +local appname = api.appname m = Map(appname) @@ -28,21 +28,21 @@ 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", "1") +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", "1") +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", "1") +o:depends("auto_on", true) o:value(nil, translate("Disable")) for e = 0, 23 do o:value(e, e .. translate("oclock")) end --]] @@ -70,9 +70,9 @@ 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.default = "22,25,53,143,465,587,853,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("22,25,53,143,465,587,853,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")) @@ -83,22 +83,39 @@ o.default = "1:65535" o:value("1:65535", translate("All")) o:value("53", "DNS") ----- Multi SS/SSR Process Option -o = s:option(Value, "process", translate("Multi Process Option")) -o.default = "0" -o.rmempty = false -o:value("0", translate("Auto")) -o:value("1", translate("1 Process")) -o:value("2", "2 " .. translate("Process")) -o:value("3", "3 " .. translate("Process")) -o:value("4", "4 " .. translate("Process")) +if os.execute("lsmod | grep -i REDIRECT >/dev/null") == 0 and os.execute("lsmod | grep -i TPROXY >/dev/null") == 0 then + o = s:option(ListValue, "tcp_proxy_way", translate("TCP Proxy Way")) + o.default = "redirect" + o:value("redirect", "REDIRECT") + o:value("tproxy", "TPROXY") + o:depends("ipv6_tproxy", false) + + o = s:option(ListValue, "_tcp_proxy_way", translate("TCP Proxy Way")) + o.default = "tproxy" + o:value("tproxy", "TPROXY") + o:depends("ipv6_tproxy", true) + o.write = function(self, section, value) + return self.map:set(section, "tcp_proxy_way", value) + end + + ---- 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 +end + +o = s:option(Flag, "accept_icmp", translate("Hijacking ICMP (PING)")) +o.default = 0 ---[[ ----- Proxy IPv6 -o = s:option(Flag, "proxy_ipv6", translate("Proxy IPv6"), - translate("The IPv6 traffic can be proxyed when selected")) +o = s:option(Flag, "accept_icmpv6", translate("Hijacking ICMPv6 (IPv6 PING)")) +o:depends("ipv6_tproxy", true) o.default = 0 ---]] + +o = s:option(Flag, "route_only", translate("Sniffing Route Only (V2Ray/Xray)")) +o.default = "1" --[[ ---- TCP Redir Port @@ -121,29 +138,10 @@ o.rmempty = true --]] -- [[ Other Settings ]]-- -s = m:section(TypedSection, "global_other", translate("Other Settings"), - "" .. translatef( - "You can only set up a maximum of %s nodes for the time being, Used for access control.", - "3") .. "") +s = m:section(TypedSection, "global_other", translate("Other Settings")) s.anonymous = true s.addremove = false ----- TCP Node Number Option -o = s:option(ListValue, "tcp_node_num", "TCP" .. translate("Node Number")) -o.default = "1" -o.rmempty = false -o:value("1") -o:value("2") -o:value("3") - ----- UDP Node Number Option -o = s:option(ListValue, "udp_node_num", "UDP" .. translate("Node Number")) -o.default = "1" -o.rmempty = false -o:value("1") -o:value("2") -o:value("3") - o = s:option(MultiValue, "status", translate("Status info")) o:value("big_icon", translate("Big icon")) -- 大图标 o:value("show_check_port", translate("Show node check")) -- 显示节点检测 diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/rule.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/rule.lua new file mode 100644 index 0000000..1303ce6 --- /dev/null +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/rule.lua @@ -0,0 +1,91 @@ +local api = require "luci.model.cbi.passwall.api.api" +local appname = api.appname +local has_v2ray = api.is_finded("v2ray") +local has_xray = api.is_finded("xray") + +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(DynamicList, "gfwlist_url", translate("GFW domains(gfwlist) Update URL")) +o:value("https://cdn.jsdelivr.net/gh/YW5vbnltb3Vz/domain-list-community@release/gfwlist.txt", translate("v2fly/domain-list-community")) +o:value("https://cdn.jsdelivr.net/gh/Loyalsoldier/v2ray-rules-dat@release/gfw.txt", translate("Loyalsoldier/v2ray-rules-dat")) +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(DynamicList, "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:value("https://cdn.jsdelivr.net/gh/soffchen/GeoIP2-CN@release/CN-ip-cidr.txt", translate("soffchen/GeoIP2-CN")) +o:value("https://cdn.jsdelivr.net/gh/Hackl0us/GeoIP2-CN@release/CN-ip-cidr.txt", translate("Hackl0us/GeoIP2-CN")) +o.default = "https://ispip.clang.cn/all_cn.txt" + +----chnroute6 URL +o = s:option(DynamicList, "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")) +o:value("https://cdn.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/accelerated-domains.china.conf", translate("felixonmars/domains.china")) +o:value("https://cdn.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/apple.china.conf", translate("felixonmars/apple.china")) +o:value("https://cdn.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/google.china.conf", translate("felixonmars/google.china")) + +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) + +if has_v2ray or has_xray then + o = s:option(Value, "v2ray_location_asset", translate("Location of V2ray/Xray asset"), translate("This variable specifies a directory where geoip.dat and geosite.dat files are.")) + o.default = "/usr/share/v2ray/" + o.rmempty = false + + s = m:section(TypedSection, "shunt_rules", "V2ray/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 + function s.remove(e, t) + m.uci:foreach(appname, "nodes", function(s) + if s["protocol"] and s["protocol"] == "_shunt" then + m:del(s[".name"], t) + end + end) + TypedSection.remove(e, t) + end + + o = s:option(DummyValue, "remarks", translate("Remarks")) +end + +return m diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/rule_list.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/rule_list.lua new file mode 100644 index 0000000..b2bfdf7 --- /dev/null +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/rule_list.lua @@ -0,0 +1,205 @@ +local api = require "luci.model.cbi.passwall.api.api" +local appname = api.appname +local fs = api.fs +local datatypes = api.datatypes +local path = string.format("/usr/share/%s/rules/", appname) +local route_hosts_path = "/etc/" + +m = Map(appname) + +-- [[ 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")) +s:tab("lan_ip_list", translate("Lan IP List")) +s:tab("route_hosts", translate("Route Hosts")) + +---- 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 host:find("#") and host:find("#") == 1 then + return value + end + 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 ipmask:find("#") and ipmask:find("#") == 1 then + return value + end + 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 host:find("#") and host:find("#") == 1 then + return value + end + 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 ipmask:find("#") and ipmask:find("#") == 1 then + return value + end + 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 host:find("#") and host:find("#") == 1 then + return value + end + 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 ipmask:find("#") and ipmask:find("#") == 1 then + return value + end + 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 + +---- Lan IPv4 +local lanlist_ipv4 = path .. "lanlist_ipv4" +o = s:taboption("lan_ip_list", TextValue, "lanlist_ipv4", "", "" .. translate("The list is the IPv4 LAN IP list, which represents the direct connection IP of the LAN. If you need the LAN IP in the proxy list, please clear it from the list. Do not modify this list by default.") .. "") +o.rows = 15 +o.wrap = "off" +o.cfgvalue = function(self, section) return fs.readfile(lanlist_ipv4) or "" end +o.write = function(self, section, value) fs.writefile(lanlist_ipv4, value:gsub("\r\n", "\n")) end +o.remove = function(self, section, value) fs.writefile(lanlist_ipv4, "") 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 ipmask:find("#") and ipmask:find("#") == 1 then + return value + end + if not datatypes.ipmask4(ipmask) then + return nil, ipmask .. " " .. translate("Not valid IPv4 format, please re-enter!") + end + end + return value +end + +---- Lan IPv6 +local lanlist_ipv6 = path .. "lanlist_ipv6" +o = s:taboption("lan_ip_list", TextValue, "lanlist_ipv6", "", "" .. translate("The list is the IPv6 LAN IP list, which represents the direct connection IP of the LAN. If you need the LAN IP in the proxy list, please clear it from the list. Do not modify this list by default.") .. "") +o.rows = 15 +o.wrap = "off" +o.cfgvalue = function(self, section) return fs.readfile(lanlist_ipv6) or "" end +o.write = function(self, section, value) fs.writefile(lanlist_ipv6, value:gsub("\r\n", "\n")) end +o.remove = function(self, section, value) fs.writefile(lanlist_ipv6, "") 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 ipmask:find("#") and ipmask:find("#") == 1 then + return value + end + if not datatypes.ipmask6(ipmask) then + return nil, ipmask .. " " .. translate("Not valid IPv6 format, please re-enter!") + end + end + return value +end + +---- Route Hosts +local hosts = route_hosts_path .. "hosts" +o = s:taboption("route_hosts", TextValue, "hosts", "", "" .. translate("Configure routing etc/hosts file, if you don't know what you are doing, please don't change the content.") .. "") +o.rows = 15 +o.wrap = "off" +o.cfgvalue = function(self, section) return fs.readfile(hosts) or "" end +o.write = function(self, section, value) fs.writefile(hosts, value:gsub("\r\n", "\n")) end +o.remove = function(self, section, value) fs.writefile(hosts, "") end + +return m diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/shunt_rules.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/shunt_rules.lua new file mode 100644 index 0000000..b2e9a8f --- /dev/null +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/shunt_rules.lua @@ -0,0 +1,79 @@ +local api = require "luci.model.cbi.passwall.api.api" +local appname = api.appname +local datatypes = api.datatypes + +m = Map(appname, "V2ray/Xray " .. translate("Shunt 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/luci-app-passwall/luasrc/model/cbi/passwall/server/api/app.lua b/luci-app-passwall/luasrc/model/cbi/passwall/server/api/app.lua new file mode 100755 index 0000000..a61412f --- /dev/null +++ b/luci-app-passwall/luasrc/model/cbi/passwall/server/api/app.lua @@ -0,0 +1,197 @@ +#!/usr/bin/lua + +local action = arg[1] +local api = require "luci.model.cbi.passwall.api.api" +local sys = api.sys +local uci = api.uci +local jsonc = api.jsonc + +local CONFIG = "passwall_server" +local CONFIG_PATH = "/tmp/etc/" .. CONFIG +local LOG_APP_FILE = "/tmp/log/" .. CONFIG .. ".log" +local TMP_BIN_PATH = CONFIG_PATH .. "/bin" +local require_dir = "luci.model.cbi.passwall.server.api." + +local ipt_bin = sys.exec("echo -n $(/usr/share/passwall/iptables.sh get_ipt_bin)") +local ip6t_bin = sys.exec("echo -n $(/usr/share/passwall/iptables.sh get_ip6t_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 ipt(arg) + cmd(ipt_bin .. " -w " .. arg) +end + +local function ip6t(arg) + cmd(ip6t_bin .. " -w " .. arg) +end + +local function ln_run(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' > /tmp/etc/%s.include", CONFIG)) + local function extract_rules(n, a) + local _ipt = ipt_bin + if n == "6" then + _ipt = ip6t_bin + 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("/tmp/etc/" .. CONFIG .. ".include", "a") + if f and err == nil then + f:write(ipt_bin .. '-save -c | grep -v "PSW-SERVER" | ' .. ipt_bin .. '-restore -c' .. "\n") + f:write(ipt_bin .. '-restore -n <<-EOT' .. "\n") + f:write(extract_rules("4", "filter") .. "\n") + f:write("EOT" .. "\n") + f:write(ip6t_bin .. '-save -c | grep -v "PSW-SERVER" | ' .. ip6t_bin .. '-restore -c' .. "\n") + f:write(ip6t_bin .. '-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(uci: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)) + ipt("-N PSW-SERVER") + ipt("-I INPUT -j PSW-SERVER") + ip6t("-N PSW-SERVER") + ip6t("-I INPUT -j PSW-SERVER") + uci: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_run("/usr/bin/microsocks", "microsocks_" .. id, string.format("-i :: -p %s %s", port, auth), log_path) + elseif type == "SS" or type == "SSR" then + config = require(require_dir .. "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_run("/usr/bin/" .. type .. "-server", type .. "-server", "-c " .. config_file .. " " .. udp_param, log_path) + elseif type == "V2ray" then + config = require(require_dir .. "v2ray").gen_config(user) + bin = ln_run(api.get_v2ray_path(), "v2ray", "-config=" .. config_file, log_path) + elseif type == "Xray" then + config = require(require_dir .. "v2ray").gen_config(user) + bin = ln_run(api.get_xray_path(), "xray", "-config=" .. config_file, log_path) + elseif type == "Trojan" then + config = require(require_dir .. "trojan").gen_config(user) + bin = ln_run("/usr/sbin/trojan", "trojan", "-c " .. config_file, log_path) + elseif type == "Trojan-Plus" then + config = require(require_dir .. "trojan").gen_config(user) + bin = ln_run("/usr/sbin/trojan-plus", "trojan-plus", "-c " .. config_file, log_path) + elseif type == "Trojan-Go" then + config = require(require_dir .. "trojan").gen_config(user) + bin = ln_run(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 + local brook_path = user.ws_path or "/ws" + local brook_path_arg = "" + if brook_protocol == "wsserver" and brook_path then + brook_path_arg = " --path " .. brook_path + end + bin = ln_run(api.get_brook_path(), "brook_" .. id, string.format("--debug %s -l :%s -p %s%s", brook_protocol, port, brook_password, brook_path_arg), log_path) + elseif type == "Hysteria" then + config = require(require_dir .. "hysteria").gen_config(user) + bin = ln_run(api.get_hysteria_path(), "hysteria", "-c " .. config_file .. " server", 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 + ipt(string.format('-A PSW-SERVER -p tcp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks)) + ip6t(string.format('-A PSW-SERVER -p tcp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks)) + if udp_forward == 1 then + ipt(string.format('-A PSW-SERVER -p udp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks)) + ip6t(string.format('-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)) + ipt("-D INPUT -j PSW-SERVER 2>/dev/null") + ipt("-F PSW-SERVER 2>/dev/null") + ipt("-X PSW-SERVER 2>/dev/null") + ip6t("-D INPUT -j PSW-SERVER 2>/dev/null") + ip6t("-F PSW-SERVER 2>/dev/null") + ip6t("-X PSW-SERVER 2>/dev/null") + cmd(string.format("rm -rf %s %s /tmp/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/luci-app-passwall/luasrc/model/cbi/passwall/server/api/hysteria.lua b/luci-app-passwall/luasrc/model/cbi/passwall/server/api/hysteria.lua new file mode 100644 index 0000000..0fdf893 --- /dev/null +++ b/luci-app-passwall/luasrc/model/cbi/passwall/server/api/hysteria.lua @@ -0,0 +1,24 @@ +module("luci.model.cbi.passwall.server.api.hysteria", package.seeall) +function gen_config(user) + local config = { + listen = ":" .. user.port, + protocol = user.protocol or "udp", + obfs = user.hysteria_obfs, + cert = user.tls_certificateFile, + key = user.tls_keyFile, + auth = (user.hysteria_auth_type == "string") and { + mode = "password", + config = { + password = user.hysteria_auth_password + } + } or nil, + disable_udp = (user.hysteria_udp == "0") and true or false, + alpn = user.hysteria_alpn or nil, + up_mbps = tonumber(user.hysteria_up_mbps) or 10, + down_mbps = tonumber(user.hysteria_down_mbps) or 50, + recv_window_conn = (user.hysteria_recv_window_conn) and tonumber(user.hysteria_recv_window_conn) or nil, + recv_window = (user.hysteria_recv_window) and tonumber(user.hysteria_recv_window) or nil, + disable_mtu_discovery = (user.hysteria_disable_mtu_discovery) and true or false + } + return config +end diff --git a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/shadowsocks.lua b/luci-app-passwall/luasrc/model/cbi/passwall/server/api/shadowsocks.lua similarity index 100% rename from lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/shadowsocks.lua rename to luci-app-passwall/luasrc/model/cbi/passwall/server/api/shadowsocks.lua diff --git a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/trojan.lua b/luci-app-passwall/luasrc/model/cbi/passwall/server/api/trojan.lua similarity index 71% rename from lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/trojan.lua rename to luci-app-passwall/luasrc/model/cbi/passwall/server/api/trojan.lua index 6ad664f..466d120 100644 --- a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/trojan.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/server/api/trojan.lua @@ -9,52 +9,53 @@ function gen_config(user) 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 = 1, + 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 = user.tls_serverName, - verify = (user.tls_allowInsecure ~= "1") and true or false, - verify_hostname = false, + cipher = cipher, + cipher_tls13 = cipher13, + prefer_server_cipher = true, 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 { + 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 + } + } + if user.type == "Trojan-Go" then + config.ssl.cipher = nil + config.ssl.cipher_tls13 = nil + config.udp_timeout = 60 + config.disable_http_check = true + config.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 { + } or nil + config.websocket = (user.trojan_transport == 'ws') and { enabled = true, path = user.ws_path or "/", - host = user.ws_host or (user.tls_serverName or user.address) - } or nil, - shadowsocks = (user.ss_aead == "1") and { + host = user.ws_host or "" + } or nil + config.shadowsocks = (user.ss_aead == "1") and { enabled = true, - method = user.ss_aead_method or "aead_aes_128_gcm", + method = user.ss_aead_method or "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 - } - } + } or nil + end return config end \ No newline at end of file diff --git a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/v2ray.lua b/luci-app-passwall/luasrc/model/cbi/passwall/server/api/v2ray.lua similarity index 61% rename from lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/v2ray.lua rename to luci-app-passwall/luasrc/model/cbi/passwall/server/api/v2ray.lua index dcd1ec7..729d9f2 100644 --- a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/api/v2ray.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/server/api/v2ray.lua @@ -1,5 +1,5 @@ module("luci.model.cbi.passwall.server.api.v2ray", package.seeall) -local ucic = require"luci.model.uci".cursor() +local uci = require"luci.model.uci".cursor() function gen_config(user) local settings = nil @@ -14,9 +14,7 @@ function gen_config(user) for i = 1, #user.uuid do clients[i] = { id = user.uuid[i], - flow = (user.xtls and user.xtls == "1") and user.flow or nil, - level = tonumber(user.level), - alterId = tonumber(user.alter_id) + flow = ("1" == user.xtls) and user.flow or nil } end settings = { @@ -26,23 +24,24 @@ function gen_config(user) end elseif user.protocol == "socks" then settings = { - auth = (user.auth and user.auth == "1") and "password" or "noauth", - accounts = (user.auth and user.auth == "1") and { + udp = ("1" == user.udp_forward) and true or false, + auth = ("1" == user.auth) and "password" or "noauth", + accounts = ("1" == user.auth) and { { user = user.username, pass = user.password } - } + } or nil } elseif user.protocol == "http" then settings = { allowTransparent = false, - accounts = (user.auth and user.auth == "1") and { + accounts = ("1" == user.auth) and { { user = user.username, pass = user.password } - } + } or nil } user.transport = "tcp" user.tcp_guise = "none" @@ -50,7 +49,7 @@ function gen_config(user) settings = { method = user.method, password = user.password, - level = tonumber(user.level) or 1, + ivCheck = ("1" == user.iv_check) and true or false, network = user.ss_network or "TCP,UDP" } elseif user.protocol == "trojan" then @@ -58,8 +57,8 @@ function gen_config(user) local clients = {} for i = 1, #user.uuid do clients[i] = { + flow = ("1" == user.xtls) and user.flow or nil, password = user.uuid[i], - level = tonumber(user.level) } end settings = { @@ -70,11 +69,41 @@ function gen_config(user) settings = { users = { { - level = tonumber(user.level) or 1, secret = (user.password == nil) and "" or user.password } } } + elseif user.protocol == "dokodemo-door" then + settings = { + network = user.d_protocol, + address = user.d_address, + port = tonumber(user.d_port) + } + 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 = { @@ -89,15 +118,28 @@ function gen_config(user) } if user.transit_node and user.transit_node ~= "nil" then - local gen_v2ray = require("luci.model.cbi.passwall.api.gen_v2ray") - local client = gen_v2ray.gen_outbound(ucic:get_all("passwall", user.transit_node), "transit") - table.insert(outbounds, 1, client) + local transit_node_t = uci:get_all("passwall", user.transit_node) + if user.transit_node == "_socks" or user.transit_node == "_http" then + transit_node_t = { + type = user.type, + 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 outbound = require("luci.model.cbi.passwall.api.gen_v2ray").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 = "warning" + -- error = "/tmp/etc/passwall_server/log/" .. user[".name"] .. ".log", + loglevel = ("1" == user.log) and user.loglevel or "none" }, -- 传入连接 inbounds = { @@ -109,8 +151,7 @@ function gen_config(user) streamSettings = { network = user.transport, security = "none", - xtlsSettings = (user.tls and user.tls == "1" and user.xtls and user.xtls == "1") and { - --alpn = {"http/1.1"}, + xtlsSettings = ("1" == user.tls and "1" == user.xtls) and { disableSystemRoot = false, certificates = { { @@ -119,7 +160,7 @@ function gen_config(user) } } } or nil, - tlsSettings = (user.tls and user.tls == "1") and { + tlsSettings = ("1" == user.tls) and { disableSystemRoot = false, certificates = { { @@ -129,6 +170,7 @@ function gen_config(user) } } 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 { @@ -151,7 +193,7 @@ function gen_config(user) header = {type = user.mkcp_guise} } or nil, wsSettings = (user.transport == "ws") and { - acceptProxyProtocol = false, + 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, @@ -165,6 +207,9 @@ function gen_config(user) 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 } } @@ -174,18 +219,28 @@ function gen_config(user) routing = routing } - if user.tls and user.tls == "1" then + local alpn = {} + if user.alpn then + string.gsub(user.alpn, '[^' .. "," .. ']+', function(w) + table.insert(alpn, w) + end) + end + if alpn and #alpn > 0 then + if config.inbounds[1].streamSettings.tlsSettings then + config.inbounds[1].streamSettings.tlsSettings.alpn = alpn + end + if config.inbounds[1].streamSettings.xtlsSettings then + config.inbounds[1].streamSettings.xtlsSettings.alpn = alpn + end + end + + if "1" == user.tls then config.inbounds[1].streamSettings.security = "tls" - if user.xtls and user.xtls == "1" then + if user.type == "Xray" and user.xtls and user.xtls == "1" then config.inbounds[1].streamSettings.security = "xtls" config.inbounds[1].streamSettings.tlsSettings = nil end end - if user.transport == "mkcp" or user.transport == "quic" then - config.inbounds[1].streamSettings.security = "none" - config.inbounds[1].streamSettings.tlsSettings = nil - end - return config end diff --git a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/index.lua b/luci-app-passwall/luasrc/model/cbi/passwall/server/index.lua similarity index 71% rename from lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/index.lua rename to luci-app-passwall/luasrc/model/cbi/passwall/server/index.lua index 2825a30..042ff09 100644 --- a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/index.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/server/index.lua @@ -1,6 +1,4 @@ -local d = require "luci.dispatcher" -local _api = require "luci.model.cbi.passwall.api.api" -local e = luci.model.uci.cursor() +local api = require "luci.model.cbi.passwall.api.api" m = Map("passwall_server", translate("Server-Side")) @@ -16,9 +14,9 @@ t.anonymous = true t.addremove = true t.sortable = true t.template = "cbi/tblsection" -t.extedit = d.build_url("admin", "services", "passwall", "server_user", "%s") +t.extedit = api.url("server_user", "%s") function t.create(e, t) - local uuid = _api.gen_uuid() + local uuid = api.gen_uuid() t = uuid TypedSection.create(e, t) luci.http.redirect(e.extedit:format(t)) @@ -26,7 +24,7 @@ end function t.remove(e, t) e.map.proceed = true e.map:del(t) - luci.http.redirect(d.build_url("admin", "services", "passwall", "server")) + luci.http.redirect(api.url("server")) end e = t:option(Flag, "enable", translate("Enable")) @@ -47,8 +45,15 @@ e = t:option(DummyValue, "type", translate("Type")) e.cfgvalue = function(t, n) local v = Value.cfgvalue(t, n) if v then - if v == "V2ray" then + if v == "V2ray" or 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 @@ -57,6 +62,10 @@ 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")) diff --git a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/user.lua b/luci-app-passwall/luasrc/model/cbi/passwall/server/user.lua similarity index 60% rename from lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/user.lua rename to luci-app-passwall/luasrc/model/cbi/passwall/server/user.lua index 94c9941..0bf1883 100644 --- a/lienol/luci-app-passwall/luasrc/model/cbi/passwall/server/user.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/server/user.lua @@ -1,5 +1,3 @@ -local d = require "luci.dispatcher" -local uci = require"luci.model.uci".cursor() local api = require "luci.model.cbi.passwall.api.api" local ss_encrypt_method_list = { @@ -31,7 +29,11 @@ local ssr_obfs_list = { } 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" + "aes-128-gcm", "aes-256-gcm", "chacha20-poly1305" +} + +local x_ss_encrypt_method_list = { + "aes-128-gcm", "aes-256-gcm", "chacha20-poly1305", "xchacha20-poly1305" } local header_type_list = { @@ -39,27 +41,18 @@ local header_type_list = { } 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 = d.build_url("admin", "services", "passwall", "server") +m.redirect = api.url("server") s = m:section(NamedSection, arg[1], "user", "") s.addremove = false s.dynamic = false -share = s:option(DummyValue, "passwall_server", translate("Share Current")) -share.rawhtml = true -share.template = "passwall/node_list/link_share_man" -share.value = arg[1] - enable = s:option(Flag, "enable", translate("Enable")) enable.default = "1" enable.rmempty = false @@ -81,6 +74,9 @@ end if api.is_finded("v2ray") then type:value("V2ray", translate("V2ray")) 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 @@ -95,6 +91,9 @@ end if api.is_finded("trojan-go") then type:value("Trojan-Go", translate("Trojan-Go")) end +if api.is_finded("hysteria") then + type:value("Hysteria", translate("Hysteria")) +end protocol = s:option(ListValue, "protocol", translate("Protocol")) protocol:value("vmess", "Vmess") @@ -104,7 +103,9 @@ protocol:value("socks", "Socks") protocol:value("shadowsocks", "Shadowsocks") protocol:value("trojan", "Trojan") protocol:value("mtproto", "MTProto") +protocol:value("dokodemo-door", "dokodemo-door") protocol:depends("type", "V2ray") +protocol:depends("type", "Xray") -- Brook协议 brook_protocol = s:option(ListValue, "brook_protocol", translate("Protocol")) @@ -118,10 +119,10 @@ 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") +--brook_tls = s:option(Flag, "brook_tls", translate("Use TLS")) +--brook_tls:depends("brook_protocol", "wsserver") -port = s:option(Value, "port", translate("Port")) +port = s:option(Value, "port", translate("Listen Port")) port.datatype = "port" port.rmempty = false @@ -139,20 +140,24 @@ end auth:depends("type", "Socks") auth:depends({ type = "V2ray", protocol = "socks" }) auth:depends({ type = "V2ray", protocol = "http" }) +auth:depends({ type = "Xray", protocol = "socks" }) +auth:depends({ type = "Xray", protocol = "http" }) username = s:option(Value, "username", translate("Username")) -username:depends("auth", "1") +username:depends("auth", true) password = s:option(Value, "password", translate("Password")) password.password = true -password:depends("auth", "1") +password:depends("auth", true) password:depends("type", "SS") password:depends("type", "SSR") password:depends("type", "Brook") password:depends({ type = "V2ray", protocol = "shadowsocks" }) +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 = "V2ray", protocol = "mtproto" }) +mtproto_password:depends({ type = "Xray", protocol = "mtproto" }) mtproto_password.default = arg[1] function mtproto_password.cfgvalue(self, section) return m:get(section, "password") @@ -161,9 +166,74 @@ function mtproto_password.write(self, section, value) m:set(section, "password", value) end +d_protocol = s:option(ListValue, "d_protocol", translate("Destination protocol")) +d_protocol:value("tcp", "TCP") +d_protocol:value("udp", "UDP") +d_protocol:value("tcp,udp", "TCP,UDP") +d_protocol:depends({ type = "V2ray", protocol = "dokodemo-door" }) +d_protocol:depends({ type = "Xray", protocol = "dokodemo-door" }) + +d_address = s:option(Value, "d_address", translate("Destination address")) +d_address:depends({ type = "V2ray", protocol = "dokodemo-door" }) +d_address:depends({ type = "Xray", protocol = "dokodemo-door" }) + +d_port = s:option(Value, "d_port", translate("Destination port")) +d_port.datatype = "port" +d_port:depends({ type = "V2ray", protocol = "dokodemo-door" }) +d_port:depends({ type = "Xray", protocol = "dokodemo-door" }) + decryption = s:option(Value, "decryption", translate("Encrypt Method")) decryption.default = "none" decryption:depends({ type = "V2ray", protocol = "vless" }) +decryption:depends({ type = "Xray", protocol = "vless" }) + +hysteria_protocol = s:option(ListValue, "hysteria_protocol", translate("Protocol")) +hysteria_protocol:value("udp", "UDP") +hysteria_protocol:value("faketcp", "faketcp") +hysteria_protocol:value("wechat-video", "wechat-video") +hysteria_protocol:depends("type", "Hysteria") +function hysteria_protocol.cfgvalue(self, section) + return m:get(section, "protocol") +end +function hysteria_protocol.write(self, section, value) + m:set(section, "protocol", value) +end + +hysteria_obfs = s:option(Value, "hysteria_obfs", translate("Obfs Password")) +hysteria_obfs:depends("type", "Hysteria") + +hysteria_auth_type = s:option(ListValue, "hysteria_auth_type", translate("Auth Type")) +hysteria_auth_type:value("disable", translate("Disable")) +hysteria_auth_type:value("string", translate("STRING")) +hysteria_auth_type:depends("type", "Hysteria") + +hysteria_auth_password = s:option(Value, "hysteria_auth_password", translate("Auth Password")) +hysteria_auth_password.password = true +hysteria_auth_password:depends("hysteria_auth_type", "string") + +hysteria_alpn = s:option(Value, "hysteria_alpn", translate("QUIC TLS ALPN")) +hysteria_alpn:depends("type", "Hysteria") + +hysteria_udp = s:option(Flag, "hysteria_udp", translate("UDP")) +hysteria_udp.default = "1" +hysteria_udp:depends("type", "Hysteria") + +hysteria_up_mbps = s:option(Value, "hysteria_up_mbps", translate("Max upload Mbps")) +hysteria_up_mbps.default = "10" +hysteria_up_mbps:depends("type", "Hysteria") + +hysteria_down_mbps = s:option(Value, "hysteria_down_mbps", translate("Max download Mbps")) +hysteria_down_mbps.default = "50" +hysteria_down_mbps:depends("type", "Hysteria") + +hysteria_recv_window_conn = s:option(Value, "hysteria_recv_window_conn", translate("QUIC stream receive window")) +hysteria_recv_window_conn:depends("type", "Hysteria") + +hysteria_recv_window = s:option(Value, "hysteria_recv_window", translate("QUIC connection receive window")) +hysteria_recv_window:depends("type", "Hysteria") + +hysteria_disable_mtu_discovery = s:option(Flag, "hysteria_disable_mtu_discovery", translate("Disable MTU detection")) +hysteria_disable_mtu_discovery:depends("type", "Hysteria") 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 @@ -195,12 +265,27 @@ function v_ss_encrypt_method.write(self, section, value) m:set(section, "method", value) end +x_ss_encrypt_method = s:option(ListValue, "x_ss_encrypt_method", translate("Encrypt Method")) +for a, t in ipairs(x_ss_encrypt_method_list) do x_ss_encrypt_method:value(t) end +x_ss_encrypt_method:depends({ type = "Xray", protocol = "shadowsocks" }) +function x_ss_encrypt_method.cfgvalue(self, section) + return m:get(section, "method") +end +function x_ss_encrypt_method.write(self, section, value) + m:set(section, "method", value) +end + +iv_check = s:option(Flag, "iv_check", translate("IV Check")) +iv_check:depends({ type = "V2ray", protocol = "shadowsocks" }) +iv_check:depends({ type = "Xray", protocol = "shadowsocks" }) + 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 = "V2ray", protocol = "shadowsocks" }) +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 @@ -232,6 +317,8 @@ udp_forward = s:option(Flag, "udp_forward", translate("UDP Forward")) udp_forward.default = "1" udp_forward.rmempty = false udp_forward:depends("type", "SSR") +udp_forward:depends({ type = "V2ray", protocol = "socks" }) +udp_forward:depends({ type = "Xray", protocol = "socks" }) uuid = s:option(DynamicList, "uuid", translate("ID") .. "/" .. translate("Password")) for i = 1, 3 do @@ -240,22 +327,13 @@ end uuid:depends({ type = "V2ray", protocol = "vmess" }) uuid:depends({ type = "V2ray", protocol = "vless" }) uuid:depends({ type = "V2ray", protocol = "trojan" }) +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.default = 16 -alter_id:depends({ type = "V2ray", protocol = "vmess" }) - -level = s:option(Value, "level", translate("User Level")) -level.default = 1 -level:depends({ type = "V2ray", protocol = "vmess" }) -level:depends({ type = "V2ray", protocol = "vless" }) -level:depends({ type = "V2ray", protocol = "shadowsocks" }) -level:depends({ type = "V2ray", protocol = "trojan" }) -level:depends({ type = "V2ray", protocol = "mtproto" }) - tls = s:option(Flag, "tls", translate("TLS")) tls.default = 0 tls.validate = function(self, value, t) @@ -278,32 +356,40 @@ tls:depends({ type = "V2ray", protocol = "vmess" }) tls:depends({ type = "V2ray", protocol = "vless" }) tls:depends({ type = "V2ray", protocol = "socks" }) tls:depends({ type = "V2ray", protocol = "shadowsocks" }) +tls:depends({ type = "V2ray", protocol = "trojan" }) +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 = "V2ray", protocol = "vless", tls = "1" }) +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-origin" +flow.default = "xtls-rprx-direct" flow:value("xtls-rprx-origin") flow:value("xtls-rprx-origin-udp443") -flow:depends("xtls", "1") +flow:value("xtls-rprx-direct") +flow:value("xtls-rprx-direct-udp443") +flow:depends("xtls", true) + +alpn = s:option(ListValue, "alpn", translate("alpn")) +alpn.default = "h2,http/1.1" +alpn:value("h2,http/1.1") +alpn:value("h2") +alpn:value("http/1.1") +alpn:depends({ type = "V2ray", tls = true }) +alpn:depends({ type = "Xray", tls = 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 = "1" }) -tls_allowInsecure:depends({ type = "Trojan-Plus", tls = "1" }) -tls_allowInsecure:depends({ type = "Trojan-Go", tls = "1" }) - -tls_serverName = s:option(Value, "tls_serverName", translate("Domain")) -tls_serverName:depends("tls", "1") - -tls_certificateFile = s:option(Value, "tls_certificateFile", translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem") +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 @@ -314,9 +400,11 @@ tls_certificateFile.validate = function(self, value, t) end return nil end -tls_certificateFile:depends("tls", "1") +tls_certificateFile.default = "/etc/config/ssl/" .. arg[1] .. ".pem" +tls_certificateFile:depends("tls", true) +tls_certificateFile:depends("type", "Hysteria") -tls_keyFile = s:option(Value, "tls_keyFile", translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key") +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 @@ -327,13 +415,15 @@ tls_keyFile.validate = function(self, value, t) end return nil end -tls_keyFile:depends("tls", "1") +tls_keyFile.default = "/etc/config/ssl/" .. arg[1] .. ".key" +tls_keyFile:depends("tls", true) +tls_keyFile:depends("type", "Hysteria") tls_sessionTicket = s:option(Flag, "tls_sessionTicket", translate("Session Ticket")) tls_sessionTicket.default = "0" -tls_sessionTicket:depends({ type = "Trojan", tls = "1" }) -tls_sessionTicket:depends({ type = "Trojan-Plus", tls = "1" }) -tls_sessionTicket:depends({ type = "Trojan-Go", tls = "1" }) +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") @@ -342,26 +432,30 @@ transport:value("ws", "WebSocket") transport:value("h2", "HTTP/2") transport:value("ds", "DomainSocket") transport:value("quic", "QUIC") +transport:value("grpc", "gRPC") transport:depends({ type = "V2ray", protocol = "vmess" }) transport:depends({ type = "V2ray", protocol = "vless" }) transport:depends({ type = "V2ray", protocol = "socks" }) transport:depends({ type = "V2ray", protocol = "shadowsocks" }) transport:depends({ type = "V2ray", protocol = "trojan" }) +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("original", translate("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.default = "original" trojan_transport:depends("type", "Trojan-Go") -trojan_plugin = s:option(ListValue, "plugin_type", translate("Plugin Type")) +trojan_plugin = s:option(ListValue, "plugin_type", translate("Transport Plugin")) trojan_plugin:value("plaintext", "Plain Text") trojan_plugin:value("shadowsocks", "ShadowSocks") trojan_plugin:value("other", "Other") trojan_plugin.default = "plaintext" -trojan_plugin:depends({ tls = "0", trojan_transport = "original" }) +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" @@ -383,27 +477,24 @@ trojan_plugin_arg:depends({ plugin_type = "other" }) 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") +ws_path:depends({ type = "Brook", brook_protocol = "wsserver" }) -- [[ 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部分 ]]-- @@ -460,7 +551,7 @@ 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 V2Ray.")) +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部分 ]]-- @@ -477,37 +568,53 @@ 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") --- [[ VLESS Fallback部分 ]]-- ---[[ +-- [[ 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 = "V2ray", transport = "tcp" }) +acceptProxyProtocol:depends({ type = "V2ray", transport = "ws" }) +acceptProxyProtocol:depends({ type = "Xray", transport = "tcp" }) +acceptProxyProtocol:depends({ type = "Xray", transport = "ws" }) + +-- [[ Fallback部分 ]]-- fallback = s:option(Flag, "fallback", translate("Fallback")) -fallback:depends({ type = "V2ray", protocol = "vless", transport = "tcp", tls = "1" }) +fallback:depends({ type = "V2ray", protocol = "vless", transport = "tcp" }) +fallback:depends({ type = "V2ray", protocol = "trojan", transport = "tcp" }) +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", "1") +fallback_alpn:depends("fallback", true) fallback_path = s:option(Value, "fallback_path", "Fallback path") -fallback_path:depends("fallback", "1") +fallback_path:depends("fallback", true) fallback_dest = s:option(Value, "fallback_dest", "Fallback dest") -fallback_dest:depends("fallback", "1") +fallback_dest:depends("fallback", true) fallback_xver = s:option(Value, "fallback_xver", "Fallback xver") fallback_xver.default = 0 -fallback_xver:depends("fallback", "1") +fallback_xver:depends("fallback", true) ]]-- -ss_aead = s:option(Flag, "ss_aead", translate("Shadowsocks2")) +fallback_list = s:option(DynamicList, "fallback_list", "Fallback", translate("dest,path")) +fallback_list:depends("fallback", true) + +ss_aead = s:option(Flag, "ss_aead", translate("Shadowsocks secondary encryption")) 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_method.default = "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", "1") +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" @@ -517,7 +624,7 @@ 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/V2ray WebSocket and more.")) +remote_enable = s:option(Flag, "remote_enable", translate("Enable Remote"), translate("You can forward to Nginx/Caddy/V2ray/Xray WebSocket and more.")) remote_enable.default = "1" remote_enable.rmempty = false remote_enable:depends("type", "Trojan") @@ -533,29 +640,91 @@ 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.")) +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", "V2ray") +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", "V2ray") +accept_lan:depends({ type = "V2ray", protocol = "vmess" }) +accept_lan:depends({ type = "V2ray", protocol = "vless" }) +accept_lan:depends({ type = "V2ray", protocol = "http" }) +accept_lan:depends({ type = "V2ray", protocol = "socks" }) +accept_lan:depends({ type = "V2ray", protocol = "shadowsocks" }) +accept_lan:depends({ type = "V2ray", protocol = "trojan" }) +accept_lan:depends({ type = "Xray", protocol = "vmess" }) +accept_lan:depends({ type = "Xray", protocol = "vless" }) +accept_lan:depends({ type = "Xray", protocol = "http" }) +accept_lan:depends({ type = "Xray", protocol = "socks" }) +accept_lan:depends({ type = "Xray", protocol = "shadowsocks" }) +accept_lan:depends({ type = "Xray", protocol = "trojan" }) local nodes_table = {} for k, e in ipairs(api.get_valid_nodes()) do - if e.node_type == "normal" and e.type == "V2ray" then + if e.node_type == "normal" and (e.type == "V2ray" or e.type == "Xray") then nodes_table[#nodes_table + 1] = { id = e[".name"], - remarks = e.remarks_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", "V2ray") +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 = "V2ray", log = true }) +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/lienol/luci-app-passwall/luasrc/view/passwall/app_update/brook_version.htm b/luci-app-passwall/luasrc/view/passwall/app_update/brook_version.htm similarity index 62% rename from lienol/luci-app-passwall/luasrc/view/passwall/app_update/brook_version.htm rename to luci-app-passwall/luasrc/view/passwall/app_update/brook_version.htm index 96956cf..9a72880 100644 --- a/lienol/luci-app-passwall/luasrc/view/passwall/app_update/brook_version.htm +++ b/luci-app-passwall/luasrc/view/passwall/app_update/brook_version.htm @@ -1,11 +1,13 @@ <% -local brook_version = require "luci.model.cbi.passwall.api.api".get_brook_version() +local api = require "luci.model.cbi.passwall.api.api" +local brook_version = api.get_brook_version() -%>
@@ -147,8 +150,9 @@
- 【 <%=brook_version%> 】 - + 【 <%=brook_version ~="" and brook_version or translate("Null") %> 】 +
diff --git a/luci-app-passwall/luasrc/view/passwall/app_update/hysteria_version.htm b/luci-app-passwall/luasrc/view/passwall/app_update/hysteria_version.htm new file mode 100644 index 0000000..7201994 --- /dev/null +++ b/luci-app-passwall/luasrc/view/passwall/app_update/hysteria_version.htm @@ -0,0 +1,159 @@ +<% +local api = require "luci.model.cbi.passwall.api.api" +local hysteria_version = api.get_hysteria_version() +-%> + + + +
+ +
+
+ 【 <%=hysteria_version ~="" and hysteria_version or translate("Null") %> 】 + + +
+
+
\ No newline at end of file diff --git a/lienol/luci-app-passwall/luasrc/view/passwall/app_update/kcptun_version.htm b/luci-app-passwall/luasrc/view/passwall/app_update/kcptun_version.htm similarity index 70% rename from lienol/luci-app-passwall/luasrc/view/passwall/app_update/kcptun_version.htm rename to luci-app-passwall/luasrc/view/passwall/app_update/kcptun_version.htm index 3abf588..fdc12df 100644 --- a/lienol/luci-app-passwall/luasrc/view/passwall/app_update/kcptun_version.htm +++ b/luci-app-passwall/luasrc/view/passwall/app_update/kcptun_version.htm @@ -1,11 +1,13 @@ <% -local kcptun_version = require "luci.model.cbi.passwall.api.api".get_kcptun_version() +local api = require "luci.model.cbi.passwall.api.api" +local kcptun_version = api.get_kcptun_version() -%>
@@ -163,8 +166,9 @@
- 【 <%=kcptun_version%> 】 - + 【 <%=kcptun_version ~="" and kcptun_version or translate("Null") %> 】 +
diff --git a/lienol/luci-app-passwall/luasrc/view/passwall/app_update/trojan_go_version.htm b/luci-app-passwall/luasrc/view/passwall/app_update/trojan_go_version.htm similarity index 68% rename from lienol/luci-app-passwall/luasrc/view/passwall/app_update/trojan_go_version.htm rename to luci-app-passwall/luasrc/view/passwall/app_update/trojan_go_version.htm index d6d2c44..b7b181c 100644 --- a/lienol/luci-app-passwall/luasrc/view/passwall/app_update/trojan_go_version.htm +++ b/luci-app-passwall/luasrc/view/passwall/app_update/trojan_go_version.htm @@ -1,11 +1,13 @@ <% -local trojan_go_version = require "luci.model.cbi.passwall.api.api".get_trojan_go_version() +local api = require "luci.model.cbi.passwall.api.api" +local trojan_go_version = api.get_trojan_go_version() -%>
@@ -163,8 +166,9 @@
- 【 <%=trojan_go_version%> 】 - + 【 <%=trojan_go_version ~="" and trojan_go_version or translate("Null") %> 】 +
diff --git a/lienol/luci-app-passwall/luasrc/view/passwall/app_update/v2ray_version.htm b/luci-app-passwall/luasrc/view/passwall/app_update/v2ray_version.htm similarity index 69% rename from lienol/luci-app-passwall/luasrc/view/passwall/app_update/v2ray_version.htm rename to luci-app-passwall/luasrc/view/passwall/app_update/v2ray_version.htm index a2694c3..ef46b9e 100644 --- a/lienol/luci-app-passwall/luasrc/view/passwall/app_update/v2ray_version.htm +++ b/luci-app-passwall/luasrc/view/passwall/app_update/v2ray_version.htm @@ -1,11 +1,13 @@ <% -local v2ray_version = require "luci.model.cbi.passwall.api.api".get_v2ray_version() +local api = require "luci.model.cbi.passwall.api.api" +local v2ray_version = api.get_v2ray_version() -%>
@@ -163,8 +166,9 @@
- 【 <%=v2ray_version%> 】 - + 【 <%=v2ray_version ~="" and v2ray_version or translate("Null") %> 】 +
diff --git a/luci-app-passwall/luasrc/view/passwall/app_update/xray_version.htm b/luci-app-passwall/luasrc/view/passwall/app_update/xray_version.htm new file mode 100644 index 0000000..06d706c --- /dev/null +++ b/luci-app-passwall/luasrc/view/passwall/app_update/xray_version.htm @@ -0,0 +1,175 @@ +<% +local api = require "luci.model.cbi.passwall.api.api" +local xray_version = api.get_xray_version() +-%> + + + +
+ +
+
+ 【 <%=xray_version ~="" and xray_version or translate("Null") %> 】 + + +
+
+
\ No newline at end of file diff --git a/luci-app-passwall/luasrc/view/passwall/auto_switch/footer.htm b/luci-app-passwall/luasrc/view/passwall/auto_switch/footer.htm new file mode 100644 index 0000000..cf672e2 --- /dev/null +++ b/luci-app-passwall/luasrc/view/passwall/auto_switch/footer.htm @@ -0,0 +1,22 @@ +<% +local api = require "luci.model.cbi.passwall.api.api" +-%> + + + + \ No newline at end of file diff --git a/luci-app-passwall/luasrc/view/passwall/global/faq.htm b/luci-app-passwall/luasrc/view/passwall/global/faq.htm new file mode 100644 index 0000000..14a1933 --- /dev/null +++ b/luci-app-passwall/luasrc/view/passwall/global/faq.htm @@ -0,0 +1,43 @@ +<% +local api = require "luci.model.cbi.passwall.api.api" +-%> +
+
+
    <%:About DNS issues:%> +
  • 1. <%:Some browsers may have built-in DNS, be sure to close. Example: Chrome. Settings - Security and Privacy - Security - Use secure DNS disabled.%>
  • +
  • 2. <%:Sometimes after restart, you can not internet, especially the GFW mode. At this time, close all browsers (important), Windows Client, please `ipconfig / flushdns`. Please close the WiFi on the phone, cut the flight mode and then cut back.%>
  • +
  • 3. <%:The client DNS and the default gateway must point to this router.%>
  • +
  • 4. <%:If you have a wrong DNS process, the consequences are at your own risk!%>
  • +
+
+
+
+ + \ No newline at end of file diff --git a/luci-app-passwall/luasrc/view/passwall/global/footer.htm b/luci-app-passwall/luasrc/view/passwall/global/footer.htm new file mode 100644 index 0000000..6fd10b5 --- /dev/null +++ b/luci-app-passwall/luasrc/view/passwall/global/footer.htm @@ -0,0 +1,155 @@ +<% +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/luci-app-passwall/luasrc/view/passwall/global/status.htm b/luci-app-passwall/luasrc/view/passwall/global/status.htm new file mode 100644 index 0000000..90c5c20 --- /dev/null +++ b/luci-app-passwall/luasrc/view/passwall/global/status.htm @@ -0,0 +1,351 @@ +<% +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%>

+
+
+
+
+
+
+
+ +
+
+
+

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

+
+
+
+
+
+
+
+ +
+
+
+

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

+
+
+
+
+
+
+
+ +
+
+
+

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

+
+
+
+
+
+
+
+ +
+
+
+

<%:Instagram Connection%>
<%:Touch Check%>

+
+
+
+ <% if status:find("show_check_port") then %> +
check" onclick="check_port(this)"> +
+
+
+ +
+
+
+

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

+ +
+
+
+ <% end %> + <% if status:find("show_ip111") then %> +
check" onclick="javascript:window.open('http://www.ip111.cn/','target');"> +
+
+
+ +
+
+
+

IP111.cn
<%:Touch Check%>

+
+
+
+ <% end %> +
+ +
diff --git a/lienol/luci-app-passwall/luasrc/view/passwall/global/status2.htm b/luci-app-passwall/luasrc/view/passwall/global/status2.htm similarity index 54% rename from lienol/luci-app-passwall/luasrc/view/passwall/global/status2.htm rename to luci-app-passwall/luasrc/view/passwall/global/status2.htm index 2bd4690..abbabff 100644 --- a/lienol/luci-app-passwall/luasrc/view/passwall/global/status2.htm +++ b/luci-app-passwall/luasrc/view/passwall/global/status2.htm @@ -1,10 +1,5 @@ <% -local dsp = require "luci.dispatcher" local api = require "luci.model.cbi.passwall.api.api" - -local tcp_node_num = api.uci_get_type("global_other", "tcp_node_num", 1) -local udp_node_num = api.uci_get_type("global_other", "udp_node_num", 1) - local status = api.uci_get_type("global_other", "status", "") -%> @@ -71,17 +66,6 @@
- <% if api.is_finded("kcptun-client") then %> -
- -
- <%:Collecting data...%> -
-
- <% end %> - <% if api.is_finded("haproxy") then %>
- +
@@ -116,7 +100,7 @@ <%:Google Connection%>
- +
@@ -125,19 +109,28 @@ <%:GitHub Connection%>
- +
+
+ +
+ + +
+
<% if status:find("show_check_port") then %>
- + - +
<% end %> @@ -145,7 +138,7 @@
- +
<% end %> @@ -156,73 +149,29 @@ //', null, + XHR.poll(3, '<%=api.url("status")%>', null, function(x, json) { if (x && x.status == 200) { var tcp_node_status = document.getElementById('_tcp_node_status'); if (tcp_node_status) { - var tcp_node_num = <%=tcp_node_num%>; - if (tcp_node_num >= 1) { + if (true) { var text = ''; - if (tcp_node_num == 1) { - if (json["tcp_node1_status"]) - text += '<%:RUNNING%> ✓'; - else - text += '<%:NOT RUNNING%> X'; - } else { - for(var i = 0; i < tcp_node_num; i++) { - var k = i + 1; - if (json["tcp_node" + k + "_status"]) - text += ''; - else - text += ' X'; - } - } + if (json["tcp_node_status"]) + text += '<%:RUNNING%> ✓'; + else + text += '<%:NOT RUNNING%> X'; tcp_node_status.innerHTML = text; - - var kcptun_tcp_node_status = document.getElementById('_kcptun_tcp_node_status'); - text = ""; - if (tcp_node_num == 1) { - if (json["kcptun_tcp_node1_status"]) - text += '<%:RUNNING%> ✓'; - else - text += '<%:NOT RUNNING%> X'; - } else { - for(var i = 0; i < tcp_node_num; i++) { - var k = i + 1; - if (json["tcp_node" + k + "_status"]) - text += ''; - else - text += ' X'; - } - } - if(kcptun_tcp_node_status) - kcptun_tcp_node_status.innerHTML = text; } } var udp_node_status = document.getElementById('_udp_node_status'); if (udp_node_status) { - var udp_node_num = <%=udp_node_num%>; - if (udp_node_num >= 1) { + if (true) { var text = ''; - if (udp_node_num == 1) { - if (json["udp_node1_status"]) - text += '<%:RUNNING%> ✓'; - else - text += '<%:NOT RUNNING%> X'; - } else { - for(var i = 0; i < udp_node_num; i++) { - var k = i + 1; - if (json["udp_node" + k + "_status"]) - text += ''; - else - text += ' X'; - } - } + if (json["udp_node_status"]) + text += '<%:RUNNING%> ✓'; + else + text += '<%:NOT RUNNING%> X'; udp_node_status.innerHTML = text; } } @@ -237,7 +186,7 @@ btn.disabled = true; btn.value = '<%:Check...%>'; var sendDate = (new Date()).getTime(); - XHR.get('<%=dsp.build_url("admin/services/passwall/connect_status")%>', { + XHR.get('<%=api.url("connect_status")%>', { type: type, url: url }, @@ -254,20 +203,18 @@ } else { color = "red"; } - //s.setAttribute("color", color); - btn.setAttribute("style","color: " + color + " !important"); - btn.value = use_time + " ms";; + s.setAttribute("color", color); + s.innerHTML = use_time + " ms"; } else if (rv.status) { - btn.setAttribute("style","color: green !important"); - btn.value = "<%:Working...%>"; + s.setAttribute("color", "green"); + s.innerHTML = "<%:Working...%>"; } else { - //s.setAttribute("color", "red"); - btn.setAttribute("style","color: red !important"); - btn.value = '<%:Problem detected!%> X'; + s.setAttribute("color", "red"); + s.innerHTML = '<%:Problem detected!%> X'; } } btn.disabled = false; - //btn.value = '<%:Check%>'; + btn.value = '<%:Check%>'; } ); return false; @@ -276,16 +223,25 @@ function check_port(btn) { btn.disabled = true; btn.value = '<%:Check...%>'; - XHR.get('<%=dsp.build_url("admin/services/passwall/check_port")%>', null, + XHR.get('<%=api.url("check_port")%>', null, function(x, rv) { - var s = document.getElementById('_node_status'); - if (s) { - s.innerHTML = rv.ret; + if (x && x.status == 200) { + var str = '
'; + for (var i = 0; i < rv.length; i++) { + var obj = rv[i]; + if (obj.flag) { + str += '' + obj.remark + ' OK.'; + } else { + str += '' + obj.remark + ' Error.'; + } + str += '
'; + } + document.getElementById('_node_status').innerHTML = str; var clear_btn = document.getElementById('clear_check_port_btn'); clear_btn.style.display = "inline-block"; + btn.disabled = false; + btn.value = '<%:Check%>'; } - btn.disabled = false; - btn.value = '<%:Check%>'; } ); return false; diff --git a/luci-app-passwall/luasrc/view/passwall/haproxy/status.htm b/luci-app-passwall/luasrc/view/passwall/haproxy/status.htm new file mode 100644 index 0000000..91fcf1e --- /dev/null +++ b/luci-app-passwall/luasrc/view/passwall/haproxy/status.htm @@ -0,0 +1,26 @@ +<% +local api = require "luci.model.cbi.passwall.api.api" +local console_port = api.uci_get_type("global_haproxy", "console_port", "") +-%> +

+ + diff --git a/lienol/luci-app-passwall/luasrc/view/passwall/log/log.htm b/luci-app-passwall/luasrc/view/passwall/log/log.htm similarity index 72% rename from lienol/luci-app-passwall/luasrc/view/passwall/log/log.htm rename to luci-app-passwall/luasrc/view/passwall/log/log.htm index c9af2f6..fcf8166 100644 --- a/lienol/luci-app-passwall/luasrc/view/passwall/log/log.htm +++ b/luci-app-passwall/luasrc/view/passwall/log/log.htm @@ -1,7 +1,10 @@ +<% +local api = require "luci.model.cbi.passwall.api.api" +-%>
- +
diff --git a/luci-app-passwall/luasrc/view/passwall/node_list/link_add_node.htm b/luci-app-passwall/luasrc/view/passwall/node_list/link_add_node.htm new file mode 100644 index 0000000..6894947 --- /dev/null +++ b/luci-app-passwall/luasrc/view/passwall/node_list/link_add_node.htm @@ -0,0 +1,106 @@ +<% +local api = require "luci.model.cbi.passwall.api.api" +-%> + + + + + + + +
+ +
+ + + + + + +
+
+
\ No newline at end of file diff --git a/lienol/luci-app-passwall/luasrc/view/passwall/node_list/link_share_man.htm b/luci-app-passwall/luasrc/view/passwall/node_list/link_share_man.htm similarity index 51% rename from lienol/luci-app-passwall/luasrc/view/passwall/node_list/link_share_man.htm rename to luci-app-passwall/luasrc/view/passwall/node_list/link_share_man.htm index 2c2f6ef..1fdcda5 100644 --- a/lienol/luci-app-passwall/luasrc/view/passwall/node_list/link_share_man.htm +++ b/luci-app-passwall/luasrc/view/passwall/node_list/link_share_man.htm @@ -1,6 +1,8 @@ <%+cbi/valueheader%> <% -local dsp = require "luci.dispatcher" +local api = require "luci.model.cbi.passwall.api.api" +local has_v2ray = api.is_finded("v2ray") +local has_xray = api.is_finded("xray") -%> - - - + + <%+cbi/valuefooter%> diff --git a/lienol/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm b/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm similarity index 65% rename from lienol/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm rename to luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm index c25be62..e51c574 100644 --- a/lienol/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm +++ b/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm @@ -1,11 +1,7 @@ <% - -- Copyright (C) 2018-2020 L-WRT Team - local api = require "luci.model.cbi.passwall.api.api" - local dsp = require "luci.dispatcher" - - local tcp_node_num = api.uci_get_type("global_other", "tcp_node_num", 1) - local udp_node_num = api.uci_get_type("global_other", "udp_node_num", 1) - local nodes_display = api.uci_get_type("global_other", "nodes_display", "") +-- Copyright (C) 2018-2020 L-WRT Team +-- Copyright (C) 2021 xiaorouji +local api = require "luci.model.cbi.passwall.api.api" -%> diff --git a/others/luci-app-kcptun/po/templates/kcptun.pot b/others/luci-app-kcptun/po/templates/kcptun.pot deleted file mode 100755 index 3888cc7..0000000 --- a/others/luci-app-kcptun/po/templates/kcptun.pot +++ /dev/null @@ -1,344 +0,0 @@ -msgid "" -msgstr "Content-Type: text/plain; charset=UTF-8" - -msgid "2nd ACK" -msgstr "" - -msgid "Alias" -msgstr "" - -msgid "Auto" -msgstr "" - -msgid "" -"Auto expiration time(in seconds) for a single UDP connection, 0 to disable." -msgstr "" - -msgid "CPU Architecture" -msgstr "" - -msgid "Can't determine ARCH, or ARCH not supported. Please select manually." -msgstr "" - -msgid "Can't find client in file: %s" -msgstr "" - -msgid "Can't move new file to path: %s" -msgstr "" - -msgid "Check Kcptun Update" -msgstr "" - -msgid "Check LuCI Update" -msgstr "" - -msgid "Clear Log File" -msgstr "" - -msgid "Click to Update" -msgstr "" - -msgid "Client File" -msgstr "" - -msgid "Client Status" -msgstr "" - -msgid "Client Version" -msgstr "" - -msgid "Client file is required." -msgstr "" - -msgid "Collecting data..." -msgstr "" - -msgid "DSCP(6bit)" -msgstr "" - -msgid "Disable" -msgstr "" - -msgid "Disable Compression" -msgstr "" - -msgid "Disable Compression?" -msgstr "" - -msgid "Download url is required." -msgstr "" - -msgid "Downloading..." -msgstr "" - -msgid "Edit Server" -msgstr "" - -msgid "Embedded Mode" -msgstr "" - -msgid "Enable Logging" -msgstr "" - -msgid "Enable nodelay Mode." -msgstr "" - -msgid "Encrypt Method" -msgstr "" - -msgid "Error get log data." -msgstr "" - -msgid "Extracting..." -msgstr "" - -msgid "False" -msgstr "" - -msgid "File download failed or timed out: %s" -msgstr "" - -msgid "File path required." -msgstr "" - -msgid "General Settings" -msgstr "" - -msgid "Get remote version info failed." -msgstr "" - -msgid "How long an expired connection can live(in sec), -1 to disable." -msgstr "" - -msgid "Invalid Client File." -msgstr "" - -msgid "Kcptun" -msgstr "" - -msgid "Kcptun Client" -msgstr "" - -msgid "Key" -msgstr "" - -msgid "Last 50 lines of log file:" -msgstr "" - -msgid "Last 50 lines of syslog:" -msgstr "" - -msgid "Listen Address" -msgstr "" - -msgid "Loading" -msgstr "" - -msgid "Local Listen Host" -msgstr "" - -msgid "Local Listen Port." -msgstr "" - -msgid "Local Port" -msgstr "" - -msgid "Local listen host." -msgstr "" - -msgid "Log" -msgstr "" - -msgid "Log Data" -msgstr "" - -msgid "Log Folder" -msgstr "" - -msgid "LuCI Version" -msgstr "" - -msgid "Make sure that the 'Client File' dictionary has enough space." -msgstr "" - -msgid "Maximum transmission unit of UDP packets." -msgstr "" - -msgid "Moving..." -msgstr "" - -msgid "" -"NAT keepalive interval to prevent your router from removing port mapping, " -"default unit is seconds." -msgstr "" - -msgid "New version found, but failed to get new version download url." -msgstr "" - -msgid "No Update Found" -msgstr "" - -msgid "No log data." -msgstr "" - -msgid "None" -msgstr "" - -msgid "Not Running" -msgstr "" - -msgid "Number of UDP connections to server." -msgstr "" - -msgid "Off" -msgstr "" - -msgid "On" -msgstr "" - -msgid "Package update failed." -msgstr "" - -msgid "Pre-shared secret for client and server." -msgstr "" - -msgid "Processing..." -msgstr "" - -msgid "Receive Window Size(num of packets)." -msgstr "" - -msgid "Reed-solomon Erasure Coding - datashard." -msgstr "" - -msgid "Reed-solomon Erasure Coding - parityshard." -msgstr "" - -msgid "Refresh every 5 seconds." -msgstr "" - -msgid "Run Daemon as User" -msgstr "" - -msgid "Running" -msgstr "" - -msgid "Running Status" -msgstr "" - -msgid "SNMP collect period, in seconds" -msgstr "" - -msgid "Save Config File" -msgstr "" - -msgid "Save config file while upgrade LuCI." -msgstr "" - -msgid "Send Window Size(num of packets)." -msgstr "" - -msgid "Send/secv buffer size of udp sockets, default unit is MB." -msgstr "" - -msgid "Server" -msgstr "" - -msgid "Server Address" -msgstr "" - -msgid "Server List" -msgstr "" - -msgid "Server Manage" -msgstr "" - -msgid "Server Port" -msgstr "" - -msgid "Settings" -msgstr "" - -msgid "The ARCH for checking updates." -msgstr "" - -msgid "" -"The client file is not suitable for current device. Please reselect ARCH." -msgstr "" - -msgid "True" -msgstr "" - -msgid "Update Success." -msgstr "" - -msgid "Update in progress. Are you sure to close window?" -msgstr "" - -msgid "" -"You may need to reload current page after update LuCI. Note that translation " -"will not be updated." -msgstr "" - -msgid "acknodelay" -msgstr "" - -msgid "autoexpire" -msgstr "" - -msgid "conn" -msgstr "" - -msgid "crypt" -msgstr "" - -msgid "datashard" -msgstr "" - -msgid "dscp" -msgstr "" - -msgid "interval" -msgstr "" - -msgid "keepalive" -msgstr "" - -msgid "mode" -msgstr "" - -msgid "mtu" -msgstr "" - -msgid "nc" -msgstr "" - -msgid "nocomp" -msgstr "" - -msgid "nodelay" -msgstr "" - -msgid "optional" -msgstr "" - -msgid "parityshard" -msgstr "" - -msgid "rcvwnd" -msgstr "" - -msgid "resend" -msgstr "" - -msgid "scavengettl" -msgstr "" - -msgid "sndwnd" -msgstr "" - -msgid "snmpperiod" -msgstr "" - -msgid "sockbuf" -msgstr "" diff --git a/others/luci-app-kcptun/po/zh-cn/kcptun.po b/others/luci-app-kcptun/po/zh-cn/kcptun.po deleted file mode 100755 index 9ceca96..0000000 --- a/others/luci-app-kcptun/po/zh-cn/kcptun.po +++ /dev/null @@ -1,344 +0,0 @@ -msgid "" -msgstr "Content-Type: text/plain; charset=UTF-8\n" - -msgid "2nd ACK" -msgstr "2次 ACK 跨越重传" - -msgid "Alias" -msgstr "别名" - -msgid "Auto" -msgstr "自动" - -msgid "" -"Auto expiration time(in seconds) for a single UDP connection, 0 to disable." -msgstr "单个 UDP 连接的自动过期时间(秒),设置 0 来禁用" - -msgid "CPU Architecture" -msgstr "CPU 架构" - -msgid "Can't determine ARCH, or ARCH not supported. Please select manually." -msgstr "无法自动确定 ARCH,或者不支持该 ARCH,请手动重新选择。" - -msgid "Can't find client in file: %s" -msgstr "无法在文件中找到客户端:%s" - -msgid "Can't move new file to path: %s" -msgstr "无法移动新文件到:%s" - -msgid "Check Kcptun Update" -msgstr "检查 Kcptun 更新" - -msgid "Check LuCI Update" -msgstr "检查 LuCI 更新" - -msgid "Clear Log File" -msgstr "清理日志文件" - -msgid "Click to Update" -msgstr "点击更新" - -msgid "Client File" -msgstr "客户端文件" - -msgid "Client Status" -msgstr "客户端状态" - -msgid "Client Version" -msgstr "客户端版本" - -msgid "Client file is required." -msgstr "请指定客户端文件。" - -msgid "Collecting data..." -msgstr "正在收集数据..." - -msgid "DSCP(6bit)" -msgstr "DSCP(6bit)" - -msgid "Disable" -msgstr "禁用" - -msgid "Disable Compression" -msgstr "禁用压缩" - -msgid "Disable Compression?" -msgstr "是否禁用压缩?" - -msgid "Download url is required." -msgstr "请指定下载链接。" - -msgid "Downloading..." -msgstr "正在下载..." - -msgid "Edit Server" -msgstr "编辑服务端" - -msgid "Embedded Mode" -msgstr "内置模式" - -msgid "Enable Logging" -msgstr "启用日志记录" - -msgid "Enable nodelay Mode." -msgstr "启用 nodelay 模式" - -msgid "Encrypt Method" -msgstr "加密方式" - -msgid "Error get log data." -msgstr "获取日志数据失败。" - -msgid "Extracting..." -msgstr "正在解压..." - -msgid "False" -msgstr "否" - -msgid "File download failed or timed out: %s" -msgstr "文件下载失败或超时:%s" - -msgid "File path required." -msgstr "请指定文件路径。" - -msgid "General Settings" -msgstr "基本设置" - -msgid "Get remote version info failed." -msgstr "获取远程版本信息失败。" - -msgid "How long an expired connection can live(in sec), -1 to disable." -msgstr "过期连接保留多长时间(秒),设置 -1 来禁用" - -msgid "Invalid Client File." -msgstr "客户端文件配置有误" - -msgid "Kcptun" -msgstr "" - -msgid "Kcptun Client" -msgstr "Kcptun 客户端" - -msgid "Key" -msgstr "密码" - -msgid "Last 50 lines of log file:" -msgstr "日志文件的最新 50 行:" - -msgid "Last 50 lines of syslog:" -msgstr "系统日志的最新 50 行:" - -msgid "Listen Address" -msgstr "监听地址" - -msgid "Loading" -msgstr "正在加载..." - -msgid "Local Listen Host" -msgstr "本地监听地址" - -msgid "Local Listen Port." -msgstr "本地监听端口" - -msgid "Local Port" -msgstr "本地端口" - -msgid "Local listen host." -msgstr "本地监听主机" - -msgid "Log" -msgstr "日志" - -msgid "Log Data" -msgstr "日志数据" - -msgid "Log Folder" -msgstr "日志文件夹" - -msgid "LuCI Version" -msgstr "LuCI 版本" - -msgid "Make sure that the 'Client File' dictionary has enough space." -msgstr "请确保“客户端文件”所在的文件夹具有足够的空间。" - -msgid "Maximum transmission unit of UDP packets." -msgstr "UDP数据包的最大传输单元" - -msgid "Moving..." -msgstr "正在移动..." - -msgid "" -"NAT keepalive interval to prevent your router from removing port mapping, " -"default unit is seconds." -msgstr "NAT Keepalive 包间隔时间(秒), 防止路由器删除端口映射" - -msgid "New version found, but failed to get new version download url." -msgstr "发现新版本,但是获取下载地址失败。" - -msgid "No Update Found" -msgstr "未发现更新" - -msgid "No log data." -msgstr "无日志数据。" - -msgid "None" -msgstr "无" - -msgid "Not Running" -msgstr "未运行" - -msgid "Number of UDP connections to server." -msgstr "到服务端的UDP连接数量" - -msgid "Off" -msgstr "关闭" - -msgid "On" -msgstr "开启" - -msgid "Package update failed." -msgstr "软件包升级失败。" - -msgid "Pre-shared secret for client and server." -msgstr "客户端和服务端的通信密码" - -msgid "Processing..." -msgstr "正在操作..." - -msgid "Receive Window Size(num of packets)." -msgstr "接收窗口大小 (数据包数量)" - -msgid "Reed-solomon Erasure Coding - datashard." -msgstr "前向纠错 - datashard" - -msgid "Reed-solomon Erasure Coding - parityshard." -msgstr "前向纠错 - parityshard" - -msgid "Refresh every 5 seconds." -msgstr "每 5 秒刷新。" - -msgid "Run Daemon as User" -msgstr "以该用户启动" - -msgid "Running" -msgstr "运行中" - -msgid "Running Status" -msgstr "运行状态" - -msgid "SNMP collect period, in seconds" -msgstr "SNMP采集周期(秒)" - -msgid "Save Config File" -msgstr "保留配置文件" - -msgid "Save config file while upgrade LuCI." -msgstr "在更新 LuCI 时保留配置文件" - -msgid "Send Window Size(num of packets)." -msgstr "发送窗口大小 (数据包数量)" - -msgid "Send/secv buffer size of udp sockets, default unit is MB." -msgstr "发送/接收UDP数据包的缓冲区大小(MB)" - -msgid "Server" -msgstr "服务端地址" - -msgid "Server Address" -msgstr "服务端地址" - -msgid "Server List" -msgstr "服务端列表" - -msgid "Server Manage" -msgstr "服务端管理" - -msgid "Server Port" -msgstr "服务端端口" - -msgid "Settings" -msgstr "设置" - -msgid "The ARCH for checking updates." -msgstr "用于检查更新的 ARCH。" - -msgid "" -"The client file is not suitable for current device. Please reselect ARCH." -msgstr "客户端文件不适用于当前设备,请重新选择 ARCH。" - -msgid "True" -msgstr "是" - -msgid "Update Success." -msgstr "更新成功!" - -msgid "Update in progress. Are you sure to close window?" -msgstr "正在更新,确定关闭窗口?" - -msgid "" -"You may need to reload current page after update LuCI. Note that translation " -"will not be updated." -msgstr "更新 LuCI 之后你可能需要手动刷新当前页面。注意:翻译不会被更新" - -msgid "acknodelay" -msgstr "" - -msgid "autoexpire" -msgstr "" - -msgid "conn" -msgstr "" - -msgid "crypt" -msgstr "" - -msgid "datashard" -msgstr "" - -msgid "dscp" -msgstr "" - -msgid "interval" -msgstr "" - -msgid "keepalive" -msgstr "" - -msgid "mode" -msgstr "" - -msgid "mtu" -msgstr "" - -msgid "nc" -msgstr "" - -msgid "nocomp" -msgstr "" - -msgid "nodelay" -msgstr "" - -msgid "optional" -msgstr "可选" - -msgid "parityshard" -msgstr "" - -msgid "rcvwnd" -msgstr "" - -msgid "resend" -msgstr "" - -msgid "scavengettl" -msgstr "" - -msgid "sndwnd" -msgstr "" - -msgid "snmpperiod" -msgstr "" - -msgid "sockbuf" -msgstr "" diff --git a/others/luci-app-kcptun/root/etc/config/kcptun b/others/luci-app-kcptun/root/etc/config/kcptun deleted file mode 100755 index 0c7be8e..0000000 --- a/others/luci-app-kcptun/root/etc/config/kcptun +++ /dev/null @@ -1,15 +0,0 @@ - -config general 'general' - option server '' - option client_file '/usr/bin/kcptun-client' - option daemon_user 'root' - option enable_logging '1' - -config servers 'default' - option server_addr '' - option server_port '29900' - option listen_addr '0.0.0.0' - option listen_port '12948' - option crypt 'aes' - option mode 'fast' - option nocomp 'false' diff --git a/others/luci-app-kcptun/root/etc/init.d/kcptun b/others/luci-app-kcptun/root/etc/init.d/kcptun deleted file mode 100755 index c8bc3dc..0000000 --- a/others/luci-app-kcptun/root/etc/init.d/kcptun +++ /dev/null @@ -1,244 +0,0 @@ -#!/bin/sh /etc/rc.common -# -# Copyright 2016-2017 Xingwang Liao -# -# 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. -# - -START=99 -USE_PROCD=1 - -KCPTUN=kcptun -CONFIG_FOLDER=/var/etc/$KCPTUN - -if [ -r /usr/share/libubox/jshn.sh ]; then - . /usr/share/libubox/jshn.sh -elif [ -r /lib/functions/jshn.sh ]; then - . /lib/functions/jshn.sh -else - logger -p daemon.err -t "$KCPTUN" \ - "Package required: jshn." - exit 1 -fi - -_log() { - local level="$1" - local msg="$2" - - logger -p "daemon.${level}" -t "$KCPTUN" "$msg" -} - -gen_client_config_file() { - local config_file="$1" - - json_init - json_add_string "remoteaddr" "${server_addr}:${server_port}" - json_add_string "localaddr" "${listen_addr}:${listen_port}" - - add_configs() { - local type="$1"; shift - local k v - - for k in "$@"; do - v="$(eval echo "\$$k")" - - if [ -n "$v" ]; then - if [ "$type" = "string" ]; then - json_add_string "$k" "$v" - elif [ "$type" = "int" ]; then - json_add_int "$k" "$v" - elif [ "$type" = "boolean" ]; then - if [ "$v" = "true" ]; then - json_add_boolean "$k" "1" - else - json_add_boolean "$k" "0" - fi - fi - fi - done - } - - add_configs "string" key crypt mode - add_configs "int" conn autoexpire mtu sndwnd rcvwnd datashard parityshard dscp \ - nodelay interval resend nc sockbuf keepalive scavengettl snmpperiod - add_configs "boolean" nocomp acknodelay - - if [ -n "$log_file" ]; then - json_add_string "log" "$log_file" - fi - - json_close_object - - json_dump -i >"$config_file" -} - -setup_iptables_chain() { - if ! ( iptables -nL "$KCPTUN" >/dev/null 2>&1 ); then - iptables -N "$KCPTUN" 2>/dev/null - fi - - iptables -C OUTPUT -j "$KCPTUN" 2>/dev/null || \ - iptables -A OUTPUT -j "$KCPTUN" 2>/dev/null - iptables -C INPUT -j "$KCPTUN" 2>/dev/null || \ - iptables -A INPUT -j "$KCPTUN" 2>/dev/null -} - -clear_iptables_chain() { - iptables -F "$KCPTUN" >/dev/null 2>&1 -} - -add_iptables_rule() { - local port="$1" - local type="$2" - - if [ "$type" = "client" ]; then - ( iptables -C "$KCPTUN" -p tcp --dport "$port" -m comment \ - --comment "$type" -j ACCEPT 2>/dev/null ) && return 0 - - iptables -A "$KCPTUN" -p tcp --dport "$port" -m comment \ - --comment "$type" -j ACCEPT 2>/dev/null - elif [ "$type" = "server" ]; then - ( iptables -C "$KCPTUN" -p udp --dport "$port" -m comment \ - --comment "$type" -j ACCEPT 2>/dev/null ) && return 0 - - iptables -A "$KCPTUN" -p udp --dport "$port" -m comment \ - --comment "$type" -j ACCEPT 2>/dev/null - fi -} - -validate_config_section() { - uci_validate_section "$KCPTUN" general "$1" \ - 'server:uciname' \ - 'client_file:string' \ - 'daemon_user:string:root' \ - 'enable_logging:bool:0' \ - 'log_folder:directory:/var/log/kcptun' -} - -validate_server_section() { - uci_validate_section "$KCPTUN" servers "$1" \ - 'server_addr:host' \ - 'server_port:port:29900' \ - 'listen_addr:host:0.0.0.0' \ - 'listen_port:port:12948' \ - 'key:string' \ - 'crypt:string:aes' \ - 'mode:or("normal","fast","fast2","fast3","manual"):fast' \ - 'conn:min(1)' \ - 'autoexpire:uinteger' \ - 'scavengettl:min(-1)' \ - 'mtu:range(64,9200)' \ - 'sndwnd:min(1)' \ - 'rcvwnd:min(1)' \ - 'datashard:uinteger' \ - 'parityshard:uinteger' \ - 'dscp:uinteger' \ - 'nocomp:or("true", "false")' \ - 'nodelay:bool' \ - 'interval:uinteger' \ - 'resend:range(0,2)' \ - 'nc:bool' \ - 'acknodelay:or("true", "false")' \ - 'sockbuf:uinteger' \ - 'keepalive:uinteger' \ - 'snmpperiod:min(1)' -} - -validate_client_file() { - local file="$1" - - if [ ! -f "$file" ]; then - return 1 - fi - - [ -x "$file" ] || chmod 755 "$file" - - ( $file -v 2>/dev/null | grep -q "$KCPTUN" ) -} - -start_kcptun_instance() { - local section="$1" - - if ! validate_config_section "$section" ; then - _log "err" "Config validate failed." - return 1 - fi - - if [ -z "$server" ] || [ "$server" = "nil" ]; then - _log "info" "No server selected, Client will stop." - return 0 - elif ! validate_server_section "$server"; then - _log "err" "Server config validation failed." - return 1 - elif [ -z "$server_addr" ] || [ -z "$listen_port" ]; then - _log "err" "Server config validation failed." - return 1 - fi - - if [ -z "$client_file" ]; then - _log "err" "Please set client file path, or use auto download." - return 1; - elif ! validate_client_file "$client_file"; then - _log "err" "Client file validation failed." - return 1 - fi - - is_ipv6_address() { - echo "$1" | grep -q ":" - } - - is_ipv6_address "$server_addr" && server_addr="[${server_addr}]" - is_ipv6_address "$listen_addr" && listen_addr="[${listen_addr}]" - - [ -d "$CONFIG_FOLDER" ] || mkdir -p "$CONFIG_FOLDER" - - log_file="" - if [ "$enable_logging" = "1" ]; then - mkdir -p "$log_folder" - chown -R "$daemon_user" "$log_folder" - log_file="${log_folder}/client.${section}.log" - fi - - local config_file=${CONFIG_FOLDER}/client.${section}.json - - if ! ( gen_client_config_file "$config_file" ); then - _log "err" "Can't create config file". - return 1 - fi - - add_iptables_rule "$listen_port" "client" - - procd_open_instance - procd_set_param command "$client_file" - procd_append_param command -c "$config_file" - procd_set_param respawn - procd_set_param user "$daemon_user" - procd_set_param file "$config_file" - procd_close_instance -} - -service_triggers() { - procd_add_reload_trigger "$KCPTUN" -} - -start_service() { - clear_iptables_chain - setup_iptables_chain - - config_load "$KCPTUN" - config_foreach start_kcptun_instance "general" -} - -stop_service() { - clear_iptables_chain -} diff --git a/others/luci-app-kcptun/root/etc/uci-defaults/40_luci-kcptun b/others/luci-app-kcptun/root/etc/uci-defaults/40_luci-kcptun deleted file mode 100755 index c759ba1..0000000 --- a/others/luci-app-kcptun/root/etc/uci-defaults/40_luci-kcptun +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@kcptun[-1] - add ucitrack kcptun - set ucitrack.@kcptun[-1].init=kcptun - commit ucitrack -EOF - -general=$(uci -q get kcptun.@general[-1]) - -if [ -z "$general" ]; then - uci -q add kcptun general -fi - -if [ ."$general" != ."general" ]; then - uci -q batch <<-EOF >/dev/null - rename kcptun.@general[-1]="general" - set kcptun.general.server="" - commit kcptun - EOF -fi - -rm -rf /tmp/luci-indexcache /tmp/luci-modulecache -exit 0 diff --git a/others/luci-app-kcptun/root/usr/share/rpcd/acl.d/luci-app-kcptun.json b/others/luci-app-kcptun/root/usr/share/rpcd/acl.d/luci-app-kcptun.json deleted file mode 100644 index 79dbf33..0000000 --- a/others/luci-app-kcptun/root/usr/share/rpcd/acl.d/luci-app-kcptun.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "luci-app-kcptun": { - "description": "Grant UCI access for luci-app-kcptun", - "read": { - "uci": [ "kcptun" ] - }, - "write": { - "uci": [ "kcptun" ] - } - } -} diff --git a/others/luci-app-syncthing/Makefile b/others/luci-app-syncthing/Makefile deleted file mode 100755 index 90985e5..0000000 --- a/others/luci-app-syncthing/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 syncthing -LUCI_DEPENDS:=+syncthing -LUCI_PKGARCH:=all -PKG_VERSION:=1.0 -PKG_RELEASE:=2 - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature - diff --git a/others/luci-app-syncthing/luasrc/controller/syncthing.lua b/others/luci-app-syncthing/luasrc/controller/syncthing.lua deleted file mode 100755 index c5cf022..0000000 --- a/others/luci-app-syncthing/luasrc/controller/syncthing.lua +++ /dev/null @@ -1,19 +0,0 @@ - -module("luci.controller.syncthing", package.seeall) - -function index() - if not nixio.fs.access("/etc/config/syncthing") then - return - end - - entry({"admin", "nas"}, firstchild(), "NAS", 44).dependent = false - entry({"admin", "nas", "syncthing"}, cbi("syncthing"), _("Syncthing"), 10).dependent = true - entry({"admin","nas","syncthing","status"},call("act_status")).leaf=true -end - -function act_status() - local e={} - e.running=luci.sys.call("pgrep syncthing >/dev/null")==0 - luci.http.prepare_content("application/json") - luci.http.write_json(e) -end diff --git a/others/luci-app-syncthing/luasrc/model/cbi/syncthing.lua b/others/luci-app-syncthing/luasrc/model/cbi/syncthing.lua deleted file mode 100755 index a85c101..0000000 --- a/others/luci-app-syncthing/luasrc/model/cbi/syncthing.lua +++ /dev/null @@ -1,19 +0,0 @@ --- Copyright 2008 Yanira --- Licensed to the public under the Apache License 2.0. - -require("nixio.fs") - -m = Map("syncthing", translate("SyncThing Synchronization Tool")) - -m:section(SimpleSection).template = "syncthing/syncthing_status" - -s = m:section(TypedSection, "setting", translate("Settings")) -s.anonymous = true - -s:option(Flag, "enabled", translate("Enable")) - -s:option(Value, "port", translate("port")).default = 8384 -s.rmempty = true - - -return m diff --git a/others/luci-app-syncthing/luasrc/view/syncthing/syncthing_status.htm b/others/luci-app-syncthing/luasrc/view/syncthing/syncthing_status.htm deleted file mode 100755 index bd21486..0000000 --- a/others/luci-app-syncthing/luasrc/view/syncthing/syncthing_status.htm +++ /dev/null @@ -1,22 +0,0 @@ - - -
-

- <%:Collecting data...%> -

-
diff --git a/others/luci-app-syncthing/po/zh-cn/syncthing.po b/others/luci-app-syncthing/po/zh-cn/syncthing.po deleted file mode 100755 index 2949c40..0000000 --- a/others/luci-app-syncthing/po/zh-cn/syncthing.po +++ /dev/null @@ -1,11 +0,0 @@ -msgid "Syncthing" -msgstr "储存同步" - -msgid "SyncThing Synchronization Tool" -msgstr "syncthing同步工具" - - - - - - diff --git a/others/luci-app-syncthing/root/etc/config/syncthing b/others/luci-app-syncthing/root/etc/config/syncthing deleted file mode 100755 index 8aa9069..0000000 --- a/others/luci-app-syncthing/root/etc/config/syncthing +++ /dev/null @@ -1,4 +0,0 @@ - -config setting 'config' - option enabled '0' - option port '8384' diff --git a/others/luci-app-syncthing/root/etc/init.d/syncthing b/others/luci-app-syncthing/root/etc/init.d/syncthing deleted file mode 100755 index e43569d..0000000 --- a/others/luci-app-syncthing/root/etc/init.d/syncthing +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/sh /etc/rc.common -START=50 - -run_syncthing() -{ - local enabled - config_get_bool enabled $1 enabled - if [ $enabled = 1 ]; then - local port - config_get port $1 port - state=`pgrep syncthing | wc -l` - if [ $state = 0 ] ; then - export HOME="/root" - syncthing -gui-address="0.0.0.0:$port" -logfile="/var/log/syncthing.log" -no-browser >/dev/null & - echo "启动中..." - start=`pgrep syncthing | wc -l` - if [ $start = 0 ] ; then - echo "启动失败" - else - echo "启动成功" - fi - else - echo "已在运行" - fi - fi -} - -start() -{ - config_load syncthing - config_foreach run_syncthing setting -} - -stop() -{ - kill -9 `pgrep syncthing` - stop=`pgrep syncthing | wc -l` - if [ $stop = 0 ] ; then - echo "已停止运行" - else - echo "未停止运行" - fi -} diff --git a/others/luci-app-syncthing/root/etc/uci-defaults/luci-syncthing b/others/luci-app-syncthing/root/etc/uci-defaults/luci-syncthing deleted file mode 100755 index fe2f1f1..0000000 --- a/others/luci-app-syncthing/root/etc/uci-defaults/luci-syncthing +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh -touch /etc/config/syncthing - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@syncthing[-1] - add ucitrack syncthing - set ucitrack.@syncthing[-1].exec='/etc/init.d/syncthing restart' - commit ucitrack -EOF -# remove LuCI cache -rm -f /tmp/luci* -exit 0 diff --git a/others/luci-app-syncthing/root/usr/share/rpcd/acl.d/luci-app-syncthing.json b/others/luci-app-syncthing/root/usr/share/rpcd/acl.d/luci-app-syncthing.json deleted file mode 100644 index 9fc9cc5..0000000 --- a/others/luci-app-syncthing/root/usr/share/rpcd/acl.d/luci-app-syncthing.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "luci-app-syncthing": { - "description": "Grant UCI access for luci-app-syncthing", - "read": { - "uci": [ "syncthing" ] - }, - "write": { - "uci": [ "syncthing" ] - } - } -} diff --git a/others/luci-app-verysync/Makefile b/others/luci-app-verysync/Makefile deleted file mode 100644 index 67d9a43..0000000 --- a/others/luci-app-verysync/Makefile +++ /dev/null @@ -1,16 +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 Verysync -LUCI_DEPENDS:=+verysync -LUCI_PKGARCH:=all -PKG_VERSION:=1.0 -PKG_RELEASE:=5 - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature diff --git a/others/luci-app-verysync/luasrc/controller/verysync.lua b/others/luci-app-verysync/luasrc/controller/verysync.lua deleted file mode 100644 index 04518d5..0000000 --- a/others/luci-app-verysync/luasrc/controller/verysync.lua +++ /dev/null @@ -1,17 +0,0 @@ -module("luci.controller.verysync", package.seeall) - -function index() - if not nixio.fs.access("/etc/config/verysync") then - return - end - - entry({"admin", "nas", "verysync"}, cbi("verysync"), _("Verysync"), 10).dependent = true - entry({"admin","nas","verysync","status"},call("act_status")).leaf=true -end - -function act_status() - local e={} - e.running=luci.sys.call("pgrep verysync >/dev/null")==0 - luci.http.prepare_content("application/json") - luci.http.write_json(e) -end diff --git a/others/luci-app-verysync/luasrc/model/cbi/verysync.lua b/others/luci-app-verysync/luasrc/model/cbi/verysync.lua deleted file mode 100644 index f8bfd26..0000000 --- a/others/luci-app-verysync/luasrc/model/cbi/verysync.lua +++ /dev/null @@ -1,24 +0,0 @@ --- Copyright 2008 Yanira --- Copyright 2020 KFERMercer --- Licensed to the public under the Apache License 2.0. - -m = Map("verysync") -m.title = translate("Verysync") -m.description = translate("Simple and easy-to-use multi-platform file synchronization software, astonishing transmission speed is different from the greatest advantage of other products. Micro-force synchronization of intelligent P2P technology to accelerate synchronization, will split the file into several KB-only data synchronization, and the file will be AES encryption processing.") - -m:section(SimpleSection).template = "verysync/verysync_status" - -s = m:section(TypedSection, "verysync") -s.addremove = false -s.anonymous = true - -o = s:option(Flag, "enabled", translate("Enable")) -o.rmempty = false - -o = s:option(Value, "port", translate("Port")) -o.datatype = "port" -o.placeholder = "8886" -o.default = "8886" -o.rmempty = false - -return m diff --git a/others/luci-app-verysync/luasrc/view/verysync/verysync_status.htm b/others/luci-app-verysync/luasrc/view/verysync/verysync_status.htm deleted file mode 100644 index 16f0288..0000000 --- a/others/luci-app-verysync/luasrc/view/verysync/verysync_status.htm +++ /dev/null @@ -1,28 +0,0 @@ - - -
-

- <%:Collecting data...%> -

-
diff --git a/others/luci-app-verysync/po/zh-cn/verysync.po b/others/luci-app-verysync/po/zh-cn/verysync.po deleted file mode 100644 index 30b23ea..0000000 --- a/others/luci-app-verysync/po/zh-cn/verysync.po +++ /dev/null @@ -1,8 +0,0 @@ -msgid "Verysync" -msgstr "微力同步" - -msgid "Simple and easy-to-use multi-platform file synchronization software, astonishing transmission speed is different from the greatest advantage of other products. Micro-force synchronization of intelligent P2P technology to accelerate synchronization, will split the file into several KB-only data synchronization, and the file will be AES encryption processing." -msgstr "简单易用的多平台文件同步软件, 惊人的传输速度是不同于其他产品的最大优势. 微力同步的智能 P2P 加速同步技术会将文件分割成若干份仅 KB 的数据进行传输, 同时会使用 AES 加密处理." - -msgid "Open Verysync page" -msgstr "打开微力同步页面" diff --git a/others/luci-app-verysync/root/etc/config/verysync b/others/luci-app-verysync/root/etc/config/verysync deleted file mode 100644 index 7d6720e..0000000 --- a/others/luci-app-verysync/root/etc/config/verysync +++ /dev/null @@ -1,2 +0,0 @@ - -config verysync 'config' diff --git a/others/luci-app-verysync/root/etc/init.d/verysync b/others/luci-app-verysync/root/etc/init.d/verysync deleted file mode 100755 index a3a5bcc..0000000 --- a/others/luci-app-verysync/root/etc/init.d/verysync +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh /etc/rc.common - -START=50 -STOP=10 - -start() { - local enabled="$(uci get verysync.config.enabled)" - local port="$(uci get verysync.config.port)" - stop - [ "${enabled}" == "1" ] || exit 0 - export HOME="/root/" - verysync -gui-address="0.0.0.0:${port}" -logfile="/var/log/verysync.log" -home="/etc/verysync/" -no-browser >/dev/null 2>&1 & -} - -stop() { - kill -9 `pgrep verysync` >/dev/null 2>&1 -} diff --git a/others/luci-app-verysync/root/etc/uci-defaults/luci-verysync b/others/luci-app-verysync/root/etc/uci-defaults/luci-verysync deleted file mode 100755 index 52e9dbf..0000000 --- a/others/luci-app-verysync/root/etc/uci-defaults/luci-verysync +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@verysync[-1] - add ucitrack verysync - set ucitrack.@verysync[-1].init=verysync - commit ucitrack -EOF - -rm -f /tmp/luci-indexcache -exit 0 diff --git a/others/luci-app-verysync/root/usr/share/rpcd/acl.d/luci-app-verysync.json b/others/luci-app-verysync/root/usr/share/rpcd/acl.d/luci-app-verysync.json deleted file mode 100644 index f900200..0000000 --- a/others/luci-app-verysync/root/usr/share/rpcd/acl.d/luci-app-verysync.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "luci-app-verysync": { - "description": "Grant UCI access for luci-app-verysync", - "read": { - "uci": [ "verysync" ] - }, - "write": { - "uci": [ "verysync" ] - } - } -} diff --git a/package/brook/Makefile b/package/brook/Makefile deleted file mode 100755 index 939c23f..0000000 --- a/package/brook/Makefile +++ /dev/null @@ -1,79 +0,0 @@ -# Copyright (C) 2020 xiaorouji -# -# This is free software, licensed under the GNU General Public License v3. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=brook -PKG_VERSION:=20200909 -PKG_RELEASE:=1 - -ifeq ($(ARCH),i386) - PKG_ARCH:=386 -endif -ifeq ($(ARCH),x86_64) - PKG_ARCH:=amd64 -endif -ifeq ($(ARCH),mipsel) - PKG_ARCH:=mipsle -endif -ifeq ($(ARCH),mips) - PKG_ARCH:=mips -endif -ifeq ($(ARCH),arm) - PKG_ARCH:=arm7 -endif -ifeq ($(BOARD),bcm53xx) - PKG_ARCH:=arm6 -endif -ifeq ($(BOARD),kirkwood) - PKG_ARCH:=arm5 -endif -ifeq ($(ARCH),arm64) - PKG_ARCH:=arm64 -endif -ifeq ($(ARCH),aarch64) - PKG_ARCH:=arm64 -endif - -PKG_FILE:=$(PKG_NAME)_$(PKG_VERSION)_$(PKG_ARCH) -PKG_URL:=https://github.com/txthinking/brook/releases/download/v$(PKG_VERSION)/$(PKG_NAME)_linux_$(PKG_ARCH) -PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)/$(PKG_VERSION) -PKG_HASH:=skip - -include $(INCLUDE_DIR)/package.mk - -define Package/$(PKG_NAME) - SECTION:=net - CATEGORY:=Network - TITLE:=Brook is a cross-platform proxy software - DEPENDS:= - URL:=https://github.com/txthinking/brook -endef - -define Package/$(PKG_NAME)/description - Brook is a cross-platform proxy software -endef - -define Build/Prepare - if [ ! -f $(DL_DIR)/$(PKG_FILE) ] ; then \ - curl -f --connect-timeout 20 --retry 5 --location --insecure $(PKG_URL) -o $(DL_DIR)/$(PKG_FILE); \ - fi - rm -r $(PKG_BUILD_DIR) - mkdir -p $(PKG_BUILD_DIR) - cp -f $(DL_DIR)/$(PKG_FILE) $(PKG_BUILD_DIR)/$(PKG_NAME) -endef - -define Build/Configure -endef - -define Build/Compile -endef - -define Package/$(PKG_NAME)/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/$(PKG_NAME) $(1)/usr/bin/brook -endef - -$(eval $(call BuildPackage,$(PKG_NAME))) diff --git a/package/chinadns-ng/LICENSE b/package/chinadns-ng/LICENSE deleted file mode 100644 index 94a9ed0..0000000 --- a/package/chinadns-ng/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/package/chinadns-ng/Makefile b/package/chinadns-ng/Makefile deleted file mode 100644 index d400024..0000000 --- a/package/chinadns-ng/Makefile +++ /dev/null @@ -1,43 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=chinadns-ng -PKG_VERSION:=1.0-beta.22 -PKG_RELEASE:=2 - -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://github.com/zfl9/chinadns-ng.git -PKG_SOURCE_VERSION:=90e9f263fa6b4954d52dfa2f36948968269bc73b -PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION) -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz -PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)/$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION) - -PKG_BUILD_PARALLEL:=1 -PKG_USE_MIPS16:=0 - -PKG_LICENSE:=GPLv3 -PKG_LICENSE_FILES:=LICENSE -PKG_MAINTAINER:=pexcn - -include $(INCLUDE_DIR)/package.mk - -define Package/chinadns-ng - SECTION:=net - CATEGORY:=Network - TITLE:=ChinaDNS next generation, refactoring with epoll and ipset - URL:=https://github.com/zfl9/chinadns-ng - DEPENDS:=+ipset -endef - -define Package/chinadns-ng/description -ChinaDNS next generation, refactoring with epoll and ipset. -endef - -define Package/chinadns-ng/conffiles -endef - -define Package/chinadns-ng/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/chinadns-ng $(1)/usr/bin -endef - -$(eval $(call BuildPackage,chinadns-ng)) diff --git a/package/dns2socks/Makefile b/package/dns2socks/Makefile deleted file mode 100755 index 051b693..0000000 --- a/package/dns2socks/Makefile +++ /dev/null @@ -1,66 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=dns2socks -PKG_VERSION:=2.1 -PKG_RELEASE:=20200218 - -PKG_SOURCE:=SourceCode.zip -PKG_SOURCE_SUBDIR:=DNS2SOCKS -PKG_SOURCE_URL:=@SF/dns2socks -PKG_MD5SUM:=ec82de936ad004cc940502cd2a1bff5b - -PKG_MAINTAINER:=ghostmaker -PKG_LICENSE:=BSD-3-Clause - -PKG_BUILD_DIR:=$(BUILD_DIR)/$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION) - -PKG_INSTALL:=1 -PKG_USE_MIPS16:=0 -PKG_BUILD_PARALLEL:=1 - -include $(INCLUDE_DIR)/package.mk - -define Package/dns2socks/Default - 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 - $(call Package/dns2socks/Default) -endef - -define Package/dns2socks/description - This is a utility to resolve DNS requests via a SOCKS5 tunnel and caches the answers. -endef - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) - unzip $(DL_DIR)/$(PKG_SOURCE) -d $(PKG_BUILD_DIR) -endef - -define Build/Compile - $(TARGET_CC) \ - $(TARGET_CFLAGS) \ - $(TARGET_CPPFLAGS) \ - $(FPIC) \ - -o $(PKG_BUILD_DIR)/$(PKG_SOURCE_SUBDIR)/$(PKG_NAME) \ - $(PKG_BUILD_DIR)/$(PKG_SOURCE_SUBDIR)/DNS2SOCKS.c \ - $(TARGET_LDFLAGS) -pthread -endef - -define Build/Install -endef - -define Package/dns2socks/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/$(PKG_SOURCE_SUBDIR)/$(PKG_NAME) $(1)/usr/bin/dns2socks -endef - -#$(shell $(RM) $(DL_DIR)/$(PKG_SOURCE)) - -$(eval $(call BuildPackage,dns2socks)) diff --git a/package/ipt2socks/Makefile b/package/ipt2socks/Makefile deleted file mode 100755 index a79f1fa..0000000 --- a/package/ipt2socks/Makefile +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright (C) 2014 OpenWrt-dist -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=ipt2socks -PKG_VERSION:=1.1.3 -PKG_RELEASE:=1 - -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://github.com/zfl9/ipt2socks.git -PKG_SOURCE_VERSION:=384dab4bae5ed9402e07ec1950e502c05812bc26 -PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION) -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz -PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)/$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION) - -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 -endef - -define Package/ipt2socks/description -Utility for converting iptables (REDIRECT/TPROXY) to SOCKS5. -endef - -define Package/ipt2socks/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/ipt2socks $(1)/usr/bin -endef - -$(eval $(call BuildPackage,ipt2socks)) diff --git a/package/kcptun/Makefile b/package/kcptun/Makefile deleted file mode 100644 index 7ebf46f..0000000 --- a/package/kcptun/Makefile +++ /dev/null @@ -1,65 +0,0 @@ -# -# Copyright (C) 2019 Xingwang Liao -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=kcptun -PKG_VERSION:=20201010 -PKG_RELEASE:=1 - -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz -PKG_SOURCE_URL:=https://codeload.github.com/xtaci/kcptun/tar.gz/v$(PKG_VERSION)? -PKG_HASH:=afab2a087b787e59e129c7d4fbc578e1131d264c0da1ce23cd1282321fc3c189 - -PKG_LICENSE:=MIT -PKG_LICENSE_FILES:=LICENSE.md -PKG_MAINTAINER:=Xingwang Liao - -PKG_BUILD_DEPENDS:=golang/host -PKG_BUILD_PARALLEL:=1 -PKG_USE_MIPS16:=0 - -GO_PKG:=github.com/xtaci/kcptun - -GO_PKG_LDFLAGS:=-s -w -X 'main.VERSION=$(PKG_VERSION)-$(PKG_RELEASE) for OpenWrt' - -# Can't use GO_PKG_LDFLAGS_X to define X args with space - -include $(INCLUDE_DIR)/package.mk -include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk - -define Package/kcptun/Default - define Package/kcptun-$(1) - SECTION:=net - CATEGORY:=Network - SUBMENU:=Web Servers/Proxies - DEPENDS:=$$(GO_ARCH_DEPENDS) - TITLE:=Simple UDP Tunnel Based On KCP ($1) - URL:=https://github.com/xtaci/kcptun - endef - - define Package/kcptun-$(1)/description - A Stable & Secure Tunnel Based On KCP with N:M Multiplexing. - - This package contains the kcptun $(1). - endef - - define Package/kcptun-$(1)/install - $$(call GoPackage/Package/Install/Bin,$$(PKG_INSTALL_DIR)) - - $$(INSTALL_DIR) $$(1)/usr/bin - $$(INSTALL_BIN) $$(PKG_INSTALL_DIR)/usr/bin/$(1) $$(1)/usr/bin/kcptun-$(1) - endef -endef - -KCPTUN_COMPONENTS:=client server - -$(foreach component,$(KCPTUN_COMPONENTS), \ - $(eval $(call Package/kcptun/Default,$(component))) \ - $(eval $(call GoBinPackage,kcptun-$(component))) \ - $(eval $(call BuildPackage,kcptun-$(component))) \ -) diff --git a/package/microsocks/Makefile b/package/microsocks/Makefile deleted file mode 100644 index 44ecedf..0000000 --- a/package/microsocks/Makefile +++ /dev/null @@ -1,38 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=microsocks -PKG_VERSION=1.0 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=lean -PKG_LICENSE:=MIT -PKG_LICENSE_FILES:=LICENSE - -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://github.com/rofl0r/microsocks.git -PKG_SOURCE_VERSION:=5795a84c4fbd61685690a8cd6d43969efc083614 - -PKG_SOURCE_SUBDIR:=$(PKG_NAME) -PKG_SOURCE:=$(PKG_NAME).$(PKG_VERSION).$(PKG_RELEASE).tar.gz -PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_SOURCE_SUBDIR) -PKG_BUILD_PARALLEL:=1 - -include $(INCLUDE_DIR)/package.mk - -define Package/microsocks - SECTION:=net - CATEGORY:=Network - TITLE:=microsocks for OpenWRT - DEPENDS:= -endef - -define Package/microsocks/description - microsocks is a Tiny Proxy in C. -endef - -define Package/microsocks/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/microsocks $(1)/usr/bin/microsocks -endef - -$(eval $(call BuildPackage,microsocks)) diff --git a/package/naiveproxy/Makefile b/package/naiveproxy/Makefile deleted file mode 100644 index d6556a5..0000000 --- a/package/naiveproxy/Makefile +++ /dev/null @@ -1,127 +0,0 @@ -# -# Copyright (C) 2020 Project OpenWrt -# -# This is free software, licensed under the GNU General Public License v3. -# See /LICENSE for more information. -# -include $(TOPDIR)/rules.mk - -PKG_NAME:=naiveproxy -PKG_VERSION:=86.0.4240.75-1 -PKG_RELEASE:=3 - -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz -PKG_SOURCE_URL:=https://codeload.github.com/klzgrad/naiveproxy/tar.gz/v$(PKG_VERSION)? -PKG_HASH:=91f946e137565115649bc5787788a6889d84e0a20e9878553a832b89c0cb161f -PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) - -PKG_LICENSE:=BSD 3-Clause -PKG_LICENSE_FILES:=LICENSE -PKG_MAINTAINER:=CN_SZTL - -PKG_BUILD_DEPENDS:=ncurses/host ninja/host python3/host -PKG_USE_MIPS16:=0 -PKG_BUILD_PARALLEL:=1 - -ifneq ($(CONFIG_CPU_TYPE)," ") - CPU_TYPE:=$(word 1, $(subst +," ,$(CONFIG_CPU_TYPE))) - CPU_SUBTYPE:=$(word 2, $(subst +, ",$(CONFIG_CPU_TYPE))) - ifeq ($(CPU_SUBTYPE),) - CPU_SUBTYPE:="" - endif -else - CPU_TYPE:="" - CPU_SUBTYPE:="" -endif - -include $(INCLUDE_DIR)/package.mk - -define Package/naiveproxy/config - depends on !(arc||armeb||mips||mips64||powerpc) -endef - -define Package/naiveproxy - SECTION:=net - CATEGORY:=Network - SUBMENU:=Web Servers/Proxies - URL:=https://github.com/klzgrad/naiveproxy - TITLE:=Make a fortune quietly - DEPENDS:=+libatomic +libnss -endef - -define Package/naiveproxy/description - NaïveProxy uses Chrome's network stack to camouflage traffic with strong - censorship resistance and low detectability. Reusing Chrome's stack also - ensures best practices in performance and security. -endef - -ifneq ($(CONFIG_CCACHE),) - export CCACHE_SLOPPINESS=time_macros - export CCACHE_BASEDIR=$(PKG_BUILD_DIR)/src - export CCACHE_CPP2=yes - export naive_ccache_flags=cc_wrapper="ccache" -endif - -AFDO_VER:=86.0.4237.0_rc-r1-merged -AFDO_FILE:=chromeos-chrome-amd64-$(AFDO_VER).afdo.bz2 -define Download/AFDO_PROF - URL:=https://storage.googleapis.com.cnpmjs.org/chromeos-prebuilt/afdo-job/llvm \ - https://storage.googleapis.com/chromeos-prebuilt/afdo-job/llvm - URL_FILE:=$(AFDO_FILE) - FILE:=$(AFDO_FILE) - HASH:=d5730bd681766bcf4fd22c0e560ad500b2d6eb09164a9b80146cc327a156c98c -endef - -CLANG_VER:=llvmorg-12-init-3492-ga1caa302-1 -CLANG_FILE:=clang-$(CLANG_VER).tgz -define Download/CLANG - URL:=https://commondatastorage.googleapis.com/chromium-browser-clang/Linux_x64 - URL_FILE:=$(CLANG_FILE) - FILE:=$(CLANG_FILE) - HASH:=05df154999115386fb390a5ec7e6ca9e28aeae2ea1cbf76435247c0eee5b9ef3 -endef - -GN_VER:=e327ffdc503815916db2543ec000226a8df45163 -GN_FILE:=gn-git_revision_$(GN_VER).zip -define Download/GN_TOOL - URL:=https://chrome-infra-packages.appspot.com/dl/gn/gn/linux-amd64/+ - URL_FILE:=git_revision:$(GN_VER) - FILE:=$(GN_FILE) - HASH:=6d141b84a541e31ed7d3cd4d938987fdfa7988d5081d3089bc1509a43d6b742f -endef - -define Build/Prepare - $(call Build/Prepare/Default) - - ( \ - cd $(PKG_BUILD_DIR)/src ; \ - bzip2 -cd > "chrome/android/profiles/afdo.prof" < $(DL_DIR)/$(AFDO_FILE) ; \ - mkdir -p "third_party/llvm-build/Release+Asserts" ; \ - $(TAR) -xzf $(DL_DIR)/$(CLANG_FILE) -C "third_party/llvm-build/Release+Asserts" ; \ - mkdir -p "gn/out" ; \ - unzip -o $(DL_DIR)/$(GN_FILE) -d "gn/out" ; \ - ) -endef - -define Build/Compile -( \ - cd $(PKG_BUILD_DIR)/src ; \ - . ../init_env.sh "$(ARCH)" "$(BOARD)" $(CPU_TYPE) $(CPU_SUBTYPE) "$(TOOLCHAIN_DIR)" ; \ - export naive_flags="$$$${naive_flags} $$$${naive_ccache_flags}" ; \ - export OP_STAGING_DIR="$(STAGING_DIR)" ; \ - mkdir -p out ; \ - ./gn/out/gn gen "out/Release" --args="$$$${naive_flags}" --script-executable="$(STAGING_DIR_HOSTPKG)/bin/python3" ; \ - $(STAGING_DIR_HOSTPKG)/bin/ninja -C "out/Release" naive ; \ -) -endef - -define Package/naiveproxy/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/out/Release/naive $(1)/usr/bin/naive -endef - -$(eval $(call Download,AFDO_PROF)) -$(eval $(call Download,CLANG)) -$(eval $(call Download,GN_TOOL)) - -$(eval $(call BuildPackage,naiveproxy)) diff --git a/package/naiveproxy/patches/001-Remove-concurrency-limit.patch b/package/naiveproxy/patches/001-Remove-concurrency-limit.patch deleted file mode 100644 index 5ccb834..0000000 --- a/package/naiveproxy/patches/001-Remove-concurrency-limit.patch +++ /dev/null @@ -1,40 +0,0 @@ -From f1a49736010170a70123db07ca41256ba92c0002 Mon Sep 17 00:00:00 2001 -From: klzgrad -Date: Sat, 3 Oct 2020 08:54:59 +0800 -Subject: [PATCH] Remove concurrency limit - ---- - src/net/tools/naive/naive_proxy.cc | 3 +-- - src/net/tools/naive/naive_proxy_bin.cc | 2 +- - 2 files changed, 2 insertions(+), 3 deletions(-) - ---- a/src/net/tools/naive/naive_proxy.cc -+++ b/src/net/tools/naive/naive_proxy.cc -@@ -5,7 +5,6 @@ - - #include "net/tools/naive/naive_proxy.h" - --#include - #include - - #include "base/bind.h" -@@ -35,7 +34,7 @@ NaiveProxy::NaiveProxy(std::unique_ptrconcurrency) || -- params->concurrency < 1 || params->concurrency > 4) { -+ params->concurrency < 1) { - std::cerr << "Invalid concurrency" << std::endl; - return false; - } diff --git a/package/naiveproxy/patches/100-build-add-OpenWrt-staging-libraries.patch b/package/naiveproxy/patches/100-build-add-OpenWrt-staging-libraries.patch deleted file mode 100644 index b386626..0000000 --- a/package/naiveproxy/patches/100-build-add-OpenWrt-staging-libraries.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 5b476d92f8dbee8b83061faa8cd18a46e5ab4aae Mon Sep 17 00:00:00 2001 -From: CN_SZTL -Date: Tue, 18 Aug 2020 20:36:39 +0000 -Subject: [PATCH] build: add OpenWrt staging libraries - ---- - src/build/config/posix/BUILD.gn | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/src/build/config/posix/BUILD.gn -+++ b/src/build/config/posix/BUILD.gn -@@ -28,6 +28,9 @@ config("runtime_library") { - if (!is_mac && !is_ios && sysroot != "") { - # Pass the sysroot to all C compiler variants, the assembler, and linker. - sysroot_flags = [ "--sysroot=" + rebase_path(sysroot, root_build_dir) ] -+ sysroot_flags += [ "-I" + getenv("OP_STAGING_DIR") + "/usr/include" ] -+ sysroot_flags += [ "-I" + getenv("OP_STAGING_DIR") + "/usr/include/nss" ] -+ sysroot_flags += [ "-I" + getenv("OP_STAGING_DIR") + "/usr/include/nspr" ] - if (is_linux || is_chromeos) { - # This is here so that all files get recompiled after a sysroot roll and - # when turning the sysroot on or off. (defines are passed via the command -@@ -57,6 +60,7 @@ config("runtime_library") { - cflags_objcc += sysroot_flags - - # Need to get some linker flags out of the sysroot. -+ ldflags += [ "-L" + getenv("OP_STAGING_DIR") + "/usr/lib" ] - ld_paths = exec_script("sysroot_ld_path.py", - [ - rebase_path("//build/linux/sysroot_ld_path.sh", diff --git a/package/naiveproxy/patches/101-build-drop-useless-deps-simd_asm.patch b/package/naiveproxy/patches/101-build-drop-useless-deps-simd_asm.patch deleted file mode 100644 index 036002f..0000000 --- a/package/naiveproxy/patches/101-build-drop-useless-deps-simd_asm.patch +++ /dev/null @@ -1,27 +0,0 @@ -From dd07b78f561914ccc6cbe076ae66c380304bf92c Mon Sep 17 00:00:00 2001 -From: CN_SZTL -Date: Wed, 19 Aug 2020 12:42:45 +0000 -Subject: [PATCH] build: drop useless deps simd_asm - -libjpeg_turbo itself has alreadly set the dependency "simd_asm", -and this will cause cross-compile failed: -``` -ERROR Unresolved dependencies. -//:gn_all(//build/toolchain/linux:clang_arm64_openwrt) - needs //third_party/libjpeg_turbo:simd_asm(//build/toolchain/linux:clang_arm64_openwrt) -``` -So, let's drop it in global build file. ---- - src/BUILD.gn | 1 - - 1 file changed, 1 deletion(-) - ---- a/src/BUILD.gn -+++ b/src/BUILD.gn -@@ -751,7 +751,6 @@ group("gn_all") { - if (enable_nacl) { - deps += [ "//native_client/src/trusted/platform_qualify:vcpuid" ] - } -- deps += [ "//third_party/libjpeg_turbo:simd_asm" ] - } - if ((is_linux || is_chromeos) && current_toolchain == host_toolchain) { - deps += [ "//v8:v8_shell" ] diff --git a/package/naiveproxy/src/init_env.sh b/package/naiveproxy/src/init_env.sh deleted file mode 100755 index 628145d..0000000 --- a/package/naiveproxy/src/init_env.sh +++ /dev/null @@ -1,87 +0,0 @@ -#!/bin/bash -# [CTCGFW] Project-OpenWrt -# Use it under GPLv3. -# -------------------------------------------------------- -# Init build dependencies for naiveproxy - -# Read args from shell -target_arch="$1" -target_board="$2" -cpu_type="$3" -cpu_subtype="$4" -toolchain_dir="$5" - -# Set arch info -naive_arch="${target_arch}" -[ "${target_arch}" == "i386" ] && naive_arch="x86" -[ "${target_arch}" == "x86_64" ] && naive_arch="x64" -[ "${target_arch}" == "aarch64" ] && naive_arch="arm64" -ldso_path="/lib/$(find "${toolchain_dir}/" | grep -Eo "ld-musl-[a-z0-9_-]+\\.so\\.1")" - -# OS detection -[ "$(uname)" != "Linux" -o "$(uname -m)" != "x86_64" ] && { echo -e "Support Linux AMD64 only."; exit 1; } - -# Set ENV -export DEPOT_TOOLS_WIN_TOOLCHAIN=0 -export naive_flags=" -is_official_build=true -exclude_unwind_tables=true -enable_resource_whitelist_generation=false -symbol_level=0 -is_clang=true -use_sysroot=false - -use_allocator=\"none\" -use_allocator_shim=false - -fatal_linker_warnings=false -treat_warnings_as_errors=false - -fieldtrial_testing_like_official_build=true - -enable_base_tracing=false -enable_nacl=false -enable_print_preview=false -enable_remoting=false -use_alsa=false -use_cups=false -use_dbus=false -use_gio=false -use_platform_icu_alternatives=true -use_gtk=false -use_system_libdrm=false -use_gnome_keyring=false -use_libpci=false -use_pangocairo=false -use_glib=false -use_pulseaudio=false -use_udev=false - -disable_file_support=true -enable_websockets=false -disable_ftp_support=true -use_kerberos=false -enable_mdns=false -enable_reporting=false -include_transport_security_state_preload_list=false -rtc_use_pipewire=false - -use_xkbcommon=false -use_ozone=true -ozone_auto_platforms=false -ozone_platform=\"headless\" -ozone_platform_headless=true - -current_os=\"linux\" -current_cpu=\"${naive_arch}\" -sysroot=\"${toolchain_dir}\" -custom_toolchain=\"//build/toolchain/linux:clang_${naive_arch}_openwrt\" -ldso_path=\"${ldso_path}\"" -[ "${target_arch}" == "arm" ] && { - naive_flags="${naive_flags} arm_version=0 arm_cpu=\"${cpu_type}\"" - [ -n "${cpu_subtype}" ] && { echo "${cpu_subtype}" | grep -q "neon" && neon_flag="arm_use_neon=true" || neon_flag="arm_use_neon=false"; naive_flags="${naive_flags} arm_fpu=\"${cpu_subtype}\" arm_float_abi=\"hard\" ${neon_flag}"; } || naive_flags="${naive_flags} arm_float_abi=\"soft\" arm_use_neon=false" -} -[[ "mips mips64 mipsel mips64el" =~ (^|[[:space:]])"${target_arch}"($|[[:space:]]) ]] && { - naive_flags="${naive_flags} use_gold=false is_cfi=false use_cfi_icall=false use_thin_lto=false mips_arch_variant=\"r2\"" - [[ "${target_arch}" =~ ^"mips"$|^"mipsel"$ ]] && naive_flags="${naive_flags} mips_float_abi=\"soft\" mips_tune=\"${cpu_type}\"" -} diff --git a/package/openssl1.1/Makefile b/package/openssl1.1/Makefile deleted file mode 100644 index 72f7f1b..0000000 --- a/package/openssl1.1/Makefile +++ /dev/null @@ -1,162 +0,0 @@ -# -# Copyright (C) 2006-2016 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -### Modified by wongsyrone to fit need of trojan-gfw/trojan - -include $(TOPDIR)/rules.mk - -PKG_NAME:=openssl1.1 - -PKG_BASE:=1.1.1 -PKG_BUGFIX:=g -PKG_VERSION:=$(PKG_BASE)$(PKG_BUGFIX) -PKG_HASH:=ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46 -ENGINES_DIR=engines-1.1 - - -PKG_RELEASE:=1 -PKG_USE_MIPS16:=0 -PATCH_DIR=./patches/$(PKG_BASE) - -PKG_BUILD_PARALLEL:=0 -PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)/openssl-$(PKG_VERSION) - -PKG_SOURCE:=openssl-$(PKG_VERSION).tar.gz -PKG_SOURCE_URL:= \ - http://ftp.fi.muni.cz/pub/openssl/source/ \ - http://ftp.linux.hr/pub/openssl/source/ \ - ftp://ftp.pca.dfn.de/pub/tools/net/openssl/source/ \ - http://www.openssl.org/source/ \ - http://www.openssl.org/source/old/$(PKG_BASE)/ - -PKG_LICENSE:=OpenSSL -PKG_LICENSE_FILES:=LICENSE -PKG_CPE_ID:=cpe:/a:openssl:openssl - -include $(INCLUDE_DIR)/package.mk - -ifneq ($(CONFIG_CCACHE),) -HOSTCC=$(HOSTCC_NOCACHE) -HOSTCXX=$(HOSTCXX_NOCACHE) -endif - -define Package/$(PKG_NAME)/Default - TITLE:=Open source SSL toolkit - URL:=http://www.openssl.org/ - SECTION:=libs - CATEGORY:=Libraries -endef - -define Package/openssl1.1/Default/description -The OpenSSL Project is a collaborative effort to develop a robust, -commercial-grade, full-featured, and Open Source toolkit implementing the -Transport Layer Security (TLS) and Secure Sockets Layer (SSL) protocols as well -as a full-strength general-purpose cryptography library. -endef - -define Package/libopenssl1.1 -$(call Package/openssl1.1/Default) - SUBMENU:=SSL - TITLE+= (libraries) - ABI_VERSION:=$(PKG_VERSION) - MENU:=1 -endef - -define Package/libopenssl1.1/description -$(call Package/openssl/Default/description) -This package contains the OpenSSL shared libraries, needed by other programs. -endef - - -define Package/libopenssl1.1/conffiles -/etc/ssl/openssl.cnf -endef - -# do NOT interfere original openssl staging dir -MY_PKG_STAGING_DIR:=$(BUILD_DIR)/openssl1.1_staging_dir - -OPENSSL_OPTIONS:= no-shared no-ssl3-method - -# https://github.com/openssl/openssl/issues/1607 -# it seems musl-libc doesn't support this -OPENSSL_OPTIONS += no-async - -OPENSSL_OPTIONS += no-sm2 no-sm3 no-sm4 - -OPENSSL_OPTIONS += no-idea - -OPENSSL_OPTIONS += no-seed - -OPENSSL_OPTIONS += no-whirlpool - -OPENSSL_OPTIONS += no-deprecated - -TARGET_CFLAGS := $(filter-out -O%,$(TARGET_CFLAGS)) -O0 -g3 - - - -OPENSSL_TARGET:=linux-$(call qstrip,$(CONFIG_ARCH))-openwrt - - -STAMP_CONFIGURED := $(STAMP_CONFIGURED)_$(shell echo $(OPENSSL_OPTIONS) | mkhash md5) - -define Build/Configure - [ -f $(STAMP_CONFIGURED) ] || { \ - rm -f $(PKG_BUILD_DIR)/*.so.* $(PKG_BUILD_DIR)/*.a; \ - find $(PKG_BUILD_DIR) -name \*.o | xargs rm -f; \ - rm -rf $(MY_PKG_STAGING_DIR); \ - } - (cd $(PKG_BUILD_DIR); \ - ./Configure $(OPENSSL_TARGET) \ - --prefix=/usr \ - --openssldir=/etc/ssl \ - --libdir=lib \ - $(TARGET_CPPFLAGS) \ - $(TARGET_LDFLAGS) \ - $(OPENSSL_OPTIONS) && \ - { [ -f $(STAMP_CONFIGURED) ] || make clean; } \ - ) - -endef - -#$(FPIC) -TARGET_CFLAGS += -ffunction-sections -fdata-sections -TARGET_LDFLAGS += -Wl,--gc-sections - -define Build/Compile - +$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) \ - CROSS_COMPILE="$(TARGET_CROSS)" \ - CC="$(TARGET_CC)" \ - SOURCE_DATE_EPOCH=$(SOURCE_DATE_EPOCH) \ - OPENWRT_OPTIMIZATION_FLAGS="$(TARGET_CFLAGS)" \ - $(OPENSSL_MAKEFLAGS) \ - all - $(MAKE) -C $(PKG_BUILD_DIR) \ - CROSS_COMPILE="$(TARGET_CROSS)" \ - CC="$(TARGET_CC)" \ - DESTDIR="$(PKG_INSTALL_DIR)" \ - $(OPENSSL_MAKEFLAGS) \ - install_sw install_ssldirs -endef - -define Build/InstallDev - $(INSTALL_DIR) $(MY_PKG_STAGING_DIR)/usr/include - $(CP) $(PKG_INSTALL_DIR)/usr/include/openssl $(MY_PKG_STAGING_DIR)/usr/include/ - $(INSTALL_DIR) $(MY_PKG_STAGING_DIR)/usr/lib/ - $(CP) $(PKG_INSTALL_DIR)/usr/lib/lib{crypto,ssl}.a $(MY_PKG_STAGING_DIR)/usr/lib/ -endef - -define Build/Clean - rm -rf $(MY_PKG_STAGING_DIR) - $(call Build/Clean/Default) -endef - -define Package/libopenssl1.1/install -true -endef - -$(eval $(call BuildPackage,libopenssl1.1)) diff --git a/package/openssl1.1/patches/1.1.1/100-Configure-afalg-support.patch b/package/openssl1.1/patches/1.1.1/100-Configure-afalg-support.patch deleted file mode 100644 index 0f91a9d..0000000 --- a/package/openssl1.1/patches/1.1.1/100-Configure-afalg-support.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 559fbff13af9ce2fbc0b9bc5727a7323e1db6217 Mon Sep 17 00:00:00 2001 -From: Eneas U de Queiroz -Date: Thu, 27 Sep 2018 08:29:21 -0300 -Subject: Do not use host kernel version to disable AFALG - -This patch prevents the Configure script from using the host kernel -version to disable building the AFALG engine on openwrt targets. - -Signed-off-by: Eneas U de Queiroz - -diff --git a/Configure b/Configure -index 5a699836f3..74d057c219 100755 ---- a/Configure -+++ b/Configure -@@ -1532,7 +1532,9 @@ unless ($disabled{"crypto-mdebug-backtrace"}) - - unless ($disabled{afalgeng}) { - $config{afalgeng}=""; -- if (grep { $_ eq 'afalgeng' } @{$target{enable}}) { -+ if ($target =~ m/openwrt$/) { -+ push @{$config{engdirs}}, "afalg"; -+ } elsif (grep { $_ eq 'afalgeng' } @{$target{enable}}) { - my $minver = 4*10000 + 1*100 + 0; - if ($config{CROSS_COMPILE} eq "") { - my $verstr = `uname -r`; diff --git a/package/openssl1.1/patches/1.1.1/110-openwrt_targets.patch b/package/openssl1.1/patches/1.1.1/110-openwrt_targets.patch deleted file mode 100644 index d0530b4..0000000 --- a/package/openssl1.1/patches/1.1.1/110-openwrt_targets.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 3d43acc6068f00dbfc0c9a06355e2c8f7d302d0f Mon Sep 17 00:00:00 2001 -From: Eneas U de Queiroz -Date: Thu, 27 Sep 2018 08:30:24 -0300 -Subject: Add openwrt targets - -Targets are named: linux-$(CONFIG_ARCH)-openwrt - -Signed-off-by: Eneas U de Queiroz - -diff --git a/Configurations/25-openwrt.conf b/Configurations/25-openwrt.conf -new file mode 100644 -index 0000000000..86a86d31e4 ---- /dev/null -+++ b/Configurations/25-openwrt.conf -@@ -0,0 +1,48 @@ -+## Openwrt "CONFIG_ARCH" matching targets. -+ -+# The targets need to end in '-openwrt' for the AFALG patch to work -+ -+my %targets = ( -+ "openwrt" => { -+ template => 1, -+ CFLAGS => add("\$(OPENWRT_OPTIMIZATION_FLAGS)"), -+ }, -+ "linux-aarch64-openwrt" => { -+ inherit_from => [ "linux-aarch64", "openwrt" ], -+ }, -+ "linux-arc-openwrt" => { -+ inherit_from => [ "linux-generic32", "openwrt" ], -+ }, -+ "linux-arm-openwrt" => { -+ inherit_from => [ "linux-armv4", "openwrt" ], -+ }, -+ "linux-armeb-openwrt" => { -+ inherit_from => [ "linux-armv4", "openwrt" ], -+ }, -+ "linux-i386-openwrt" => { -+ inherit_from => [ "linux-x86", "openwrt" ], -+ }, -+ "linux-mips-openwrt" => { -+ inherit_from => [ "linux-mips32", "openwrt" ], -+ }, -+ "linux-mips64-openwrt" => { -+ inherit_from => [ "linux64-mips64", "openwrt" ], -+ }, -+ "linux-mips64el-openwrt" => { -+ inherit_from => [ "linux64-mips64", "openwrt" ], -+ }, -+ "linux-mipsel-openwrt" => { -+ inherit_from => [ "linux-mips32", "openwrt" ], -+ }, -+ "linux-powerpc-openwrt" => { -+ inherit_from => [ "linux-ppc", "openwrt" ], -+ }, -+ "linux-x86_64-openwrt" => { -+ inherit_from => [ "linux-x86_64", "openwrt" ], -+ }, -+ -+### Basic default option -+ "linux-generic32-openwrt" => { -+ inherit_from => [ "linux-generic32", "openwrt" ], -+ }, -+); diff --git a/package/openssl1.1/patches/1.1.1/120-strip-cflags-from-binary.patch b/package/openssl1.1/patches/1.1.1/120-strip-cflags-from-binary.patch deleted file mode 100644 index 7faec9a..0000000 --- a/package/openssl1.1/patches/1.1.1/120-strip-cflags-from-binary.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 4ad8f2fe6bf3b91df7904fcbe960e5fdfca36336 Mon Sep 17 00:00:00 2001 -From: Eneas U de Queiroz -Date: Thu, 27 Sep 2018 08:31:38 -0300 -Subject: Avoid exposing build directories - -The CFLAGS contain the build directories, and are shown by calling -OpenSSL_version(OPENSSL_CFLAGS), or running openssl version -a - -Signed-off-by: Eneas U de Queiroz - -diff --git a/crypto/build.info b/crypto/build.info -index 2c619c62e8..893128345a 100644 ---- a/crypto/build.info -+++ b/crypto/build.info -@@ -10,7 +10,7 @@ EXTRA= ../ms/uplink-x86.pl ../ms/uplink.c ../ms/applink.c \ - ppccpuid.pl pariscid.pl alphacpuid.pl arm64cpuid.pl armv4cpuid.pl - - DEPEND[cversion.o]=buildinf.h --GENERATE[buildinf.h]=../util/mkbuildinf.pl "$(CC) $(LIB_CFLAGS) $(CPPFLAGS_Q)" "$(PLATFORM)" -+GENERATE[buildinf.h]=../util/mkbuildinf.pl "$(filter-out -I% -iremap% -fmacro-prefix-map% -ffile-prefix-map%,$(CC) $(LIB_CFLAGS) $(CPPFLAGS_Q))" "$(PLATFORM)" - DEPEND[buildinf.h]=../configdata.pm - - GENERATE[uplink-x86.s]=../ms/uplink-x86.pl $(PERLASM_SCHEME) diff --git a/package/openssl1.1/patches/1.1.1/130-dont-build-tests-fuzz.patch b/package/openssl1.1/patches/1.1.1/130-dont-build-tests-fuzz.patch deleted file mode 100644 index fa79cc6..0000000 --- a/package/openssl1.1/patches/1.1.1/130-dont-build-tests-fuzz.patch +++ /dev/null @@ -1,31 +0,0 @@ -From ba2fe646f2d9104a18b066e43582154049e9ffcb Mon Sep 17 00:00:00 2001 -From: Eneas U de Queiroz -Date: Thu, 27 Sep 2018 08:34:38 -0300 -Subject: Do not build tests and fuzz directories - -This shortens build time. - -Signed-off-by: Eneas U de Queiroz - -diff --git a/Configure b/Configure -index 74d057c219..5813e9f8fe 100755 ---- a/Configure -+++ b/Configure -@@ -296,7 +296,7 @@ my $auto_threads=1; # enable threads automatically? true by default - my $default_ranlib; - - # Top level directories to build --$config{dirs} = [ "crypto", "ssl", "engines", "apps", "test", "util", "tools", "fuzz" ]; -+$config{dirs} = [ "crypto", "ssl", "engines", "apps", "util", "tools" ]; - # crypto/ subdirectories to build - $config{sdirs} = [ - "objects", -@@ -308,7 +308,7 @@ $config{sdirs} = [ - "cms", "ts", "srp", "cmac", "ct", "async", "kdf", "store" - ]; - # test/ subdirectories to build --$config{tdirs} = [ "ossl_shim" ]; -+$config{tdirs} = []; - - # Known TLS and DTLS protocols - my @tls = qw(ssl3 tls1 tls1_1 tls1_2 tls1_3); diff --git a/package/openssl1.1/patches/1.1.1/140-allow-prefer-chacha20.patch b/package/openssl1.1/patches/1.1.1/140-allow-prefer-chacha20.patch deleted file mode 100644 index b293db2..0000000 --- a/package/openssl1.1/patches/1.1.1/140-allow-prefer-chacha20.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 4f7ab2040bb71f03a8f8388911144559aa2a5b60 Mon Sep 17 00:00:00 2001 -From: Eneas U de Queiroz -Date: Thu, 27 Sep 2018 08:44:39 -0300 -Subject: Add OPENSSL_PREFER_CHACHA_OVER_GCM option - -This enables a compile-time option to prefer ChaCha20-Poly1305 over -AES-GCM in the openssl default ciphersuite, which is useful in systems -without AES specific CPU instructions. -OPENSSL_PREFER_CHACHA_OVER_GCM must be defined to enable it. - -Note that this does not have the same effect as the -SL_OP_PRIORITIZE_CHACHA option, which prioritizes ChaCha20-Poly1305 only -when the client has it on top of its ciphersuite preference. - -Signed-off-by: Eneas U de Queiroz - -diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h -index 6724ccf2d2..96d959427e 100644 ---- a/include/openssl/ssl.h -+++ b/include/openssl/ssl.h -@@ -173,9 +173,15 @@ extern "C" { - # define SSL_DEFAULT_CIPHER_LIST "ALL:!COMPLEMENTOFDEFAULT:!eNULL" - /* This is the default set of TLSv1.3 ciphersuites */ - # if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305) --# define TLS_DEFAULT_CIPHERSUITES "TLS_AES_256_GCM_SHA384:" \ -- "TLS_CHACHA20_POLY1305_SHA256:" \ -- "TLS_AES_128_GCM_SHA256" -+# ifdef OPENSSL_PREFER_CHACHA_OVER_GCM -+# define TLS_DEFAULT_CIPHERSUITES "TLS_CHACHA20_POLY1305_SHA256:" \ -+ "TLS_AES_256_GCM_SHA384:" \ -+ "TLS_AES_128_GCM_SHA256" -+# else -+# define TLS_DEFAULT_CIPHERSUITES "TLS_AES_256_GCM_SHA384:" \ -+ "TLS_CHACHA20_POLY1305_SHA256:" \ -+ "TLS_AES_128_GCM_SHA256" -+# endif - # else - # define TLS_DEFAULT_CIPHERSUITES "TLS_AES_256_GCM_SHA384:" \ - "TLS_AES_128_GCM_SHA256" -diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c -index 27a1b2ec68..7039811323 100644 ---- a/ssl/ssl_ciph.c -+++ b/ssl/ssl_ciph.c -@@ -1467,11 +1467,29 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, - ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_DEL, -1, &head, - &tail); - -+ /* -+ * If OPENSSL_PREFER_CHACHA_OVER_GCM is defined, ChaCha20_Poly1305 -+ * will be placed before AES-256. Otherwise, the default behavior of -+ * preferring GCM over CHACHA is used. -+ * This is useful for systems that do not have AES-specific CPU -+ * instructions, where ChaCha20-Poly1305 is 3 times faster than AES. -+ * Note that this does not have the same effect as the SSL_OP_PRIORITIZE_CHACHA -+ * option, which prioritizes ChaCha20-Poly1305 only when the client has it on top -+ * of its ciphersuite preference. -+ */ -+ -+#ifdef OPENSSL_PREFER_CHACHA_OVER_GCM -+ ssl_cipher_apply_rule(0, 0, 0, SSL_CHACHA20, 0, 0, 0, CIPHER_ADD, -1, -+ &head, &tail); -+ ssl_cipher_apply_rule(0, 0, 0, SSL_AESGCM, 0, 0, 0, CIPHER_ADD, -1, -+ &head, &tail); -+#else - /* Within each strength group, we prefer GCM over CHACHA... */ - ssl_cipher_apply_rule(0, 0, 0, SSL_AESGCM, 0, 0, 0, CIPHER_ADD, -1, - &head, &tail); - ssl_cipher_apply_rule(0, 0, 0, SSL_CHACHA20, 0, 0, 0, CIPHER_ADD, -1, - &head, &tail); -+#endif - - /* - * ...and generally, our preferred cipher is AES. -@@ -1527,7 +1545,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, - * Within each group, ciphers remain sorted by strength and previous - * preference, i.e., - * 1) ECDHE > DHE -- * 2) GCM > CHACHA -+ * 2) GCM > CHACHA, reversed if OPENSSL_PREFER_CHACHA_OVER_GCM is defined - * 3) AES > rest - * 4) TLS 1.2 > legacy - * diff --git a/package/shadowsocksr-libev/Makefile b/package/shadowsocksr-libev/Makefile deleted file mode 100755 index 759b0f0..0000000 --- a/package/shadowsocksr-libev/Makefile +++ /dev/null @@ -1,67 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=shadowsocksr-libev -PKG_VERSION:=2.5.6 -PKG_RELEASE:=5 - -PKG_SOURCE_PROTO:=git -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.xz -PKG_SOURCE_URL:=https://github.com/shadowsocksrr/shadowsocksr-libev -PKG_SOURCE_VERSION:=d63ff863800a5645aca4309d5dd5962bd1e95543 -PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION) - -PKG_LICENSE:=GPLv3 -PKG_LICENSE_FILES:=LICENSE - -PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)/$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION) - -PKG_INSTALL:=1 -PKG_FIXUP:=autoreconf -PKG_USE_MIPS16:=0 -PKG_BUILD_PARALLEL:=1 - -include $(INCLUDE_DIR)/package.mk - -define Package/shadowsocksr-libev - SECTION:=net - CATEGORY:=Network - TITLE:=Lightweight Secured Socks5 Proxy - URL:=https://github.com/shadowsocksrr/shadowsocksr-libev - DEPENDS:=+libopenssl +libpthread +libpcre +zlib -endef - -Package/shadowsocksr-libev-server = $(Package/shadowsocksr-libev) -Package/shadowsocksr-libev-alt = $(Package/shadowsocksr-libev) -Package/shadowsocksr-libev-ssr-local = $(Package/shadowsocksr-libev) - -CONFIGURE_ARGS += --disable-documentation --disable-ssp --disable-assert - -define Package/shadowsocksr-libev/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/ss-redir $(1)/usr/bin/ssr-redir - $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/ss-local $(1)/usr/bin/ssr-local - $(LN) ssr-local $(1)/usr/bin/ssr-tunnel - $(INSTALL_BIN) $(PKG_BUILD_DIR)/server/ss-check $(1)/usr/bin/ssr-check -endef - -define Package/shadowsocksr-libev-alt/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/ss-redir $(1)/usr/bin/ssr-redir - $(INSTALL_BIN) $(PKG_BUILD_DIR)/server/ss-check $(1)/usr/bin/ssr-check -endef - -define Package/shadowsocksr-libev-server/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/server/ss-server $(1)/usr/bin/ssr-server -endef - -define Package/shadowsocksr-libev-ssr-local/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/ss-local $(1)/usr/bin/ssr-local - $(LN) ssr-local $(1)/usr/bin/ssr-tunnel -endef - -$(eval $(call BuildPackage,shadowsocksr-libev)) -$(eval $(call BuildPackage,shadowsocksr-libev-alt)) -$(eval $(call BuildPackage,shadowsocksr-libev-server)) -$(eval $(call BuildPackage,shadowsocksr-libev-ssr-local)) diff --git a/package/shadowsocksr-libev/patches/0001-Add-ss-server-and-ss-check.patch b/package/shadowsocksr-libev/patches/0001-Add-ss-server-and-ss-check.patch deleted file mode 100755 index 50a4e6a..0000000 --- a/package/shadowsocksr-libev/patches/0001-Add-ss-server-and-ss-check.patch +++ /dev/null @@ -1,17186 +0,0 @@ -diff --git a/.gitignore b/.gitignore -index 4eab18e..64b8d9f 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -2,6 +2,7 @@ build/ - .deps/ - /Makefile - src/Makefile -+server/Makefile - libev/Makefile - libudns/Makefile - libcork/Makefile -diff --git a/Makefile.am b/Makefile.am -index 690af43..75e158e 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -1,7 +1,7 @@ - if USE_SYSTEM_SHARED_LIB --SUBDIRS = libcork libipset src -+SUBDIRS = libcork libipset src server - else --SUBDIRS = libsodium libcork libipset libudns libev src -+SUBDIRS = libsodium libcork libipset libudns libev src server - endif - - if ENABLE_DOCUMENTATION -diff --git a/Makefile.in b/Makefile.in -index 4cb3deb..e210bc0 100644 ---- a/Makefile.in -+++ b/Makefile.in -@@ -195,7 +195,7 @@ am__define_uniq_tagged_files = \ - ETAGS = etags - CTAGS = ctags - CSCOPE = cscope --DIST_SUBDIRS = libsodium libcork libipset libudns libev src doc -+DIST_SUBDIRS = libsodium libcork libipset libudns libev src server doc - am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \ - $(srcdir)/shadowsocks-libev.pc.in $(top_srcdir)/auto/ar-lib \ - $(top_srcdir)/auto/compile $(top_srcdir)/auto/config.guess \ -@@ -377,8 +377,9 @@ top_build_prefix = @top_build_prefix@ - top_builddir = @top_builddir@ - top_srcdir = @top_srcdir@ - @USE_SYSTEM_SHARED_LIB_FALSE@SUBDIRS = libsodium libcork libipset \ --@USE_SYSTEM_SHARED_LIB_FALSE@ libudns libev src $(am__append_1) --@USE_SYSTEM_SHARED_LIB_TRUE@SUBDIRS = libcork libipset src \ -+@USE_SYSTEM_SHARED_LIB_FALSE@ libudns libev src server \ -+@USE_SYSTEM_SHARED_LIB_FALSE@ $(am__append_1) -+@USE_SYSTEM_SHARED_LIB_TRUE@SUBDIRS = libcork libipset src server \ - @USE_SYSTEM_SHARED_LIB_TRUE@ $(am__append_1) - ACLOCAL_AMFLAGS = -I m4 - pkgconfiglibdir = $(libdir)/pkgconfig -diff --git a/configure b/configure -index 7d854c4..01d66ab 100755 ---- a/configure -+++ b/configure -@@ -649,7 +649,6 @@ PTHREAD_CC - ax_pthread_config - INET_NTOP_LIB - MV --RM - GZIP - XMLTO - ASCIIDOC -@@ -757,6 +756,7 @@ infodir - docdir - oldincludedir - includedir -+runstatedir - localstatedir - sharedstatedir - sysconfdir -@@ -857,6 +857,7 @@ datadir='${datarootdir}' - sysconfdir='${prefix}/etc' - sharedstatedir='${prefix}/com' - localstatedir='${prefix}/var' -+runstatedir='${localstatedir}/run' - includedir='${prefix}/include' - oldincludedir='/usr/include' - docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' -@@ -1109,6 +1110,15 @@ do - | -silent | --silent | --silen | --sile | --sil) - silent=yes ;; - -+ -runstatedir | --runstatedir | --runstatedi | --runstated \ -+ | --runstate | --runstat | --runsta | --runst | --runs \ -+ | --run | --ru | --r) -+ ac_prev=runstatedir ;; -+ -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ -+ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ -+ | --run=* | --ru=* | --r=*) -+ runstatedir=$ac_optarg ;; -+ - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) - ac_prev=sbindir ;; - -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ -@@ -1246,7 +1256,7 @@ fi - for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ - datadir sysconfdir sharedstatedir localstatedir includedir \ - oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ -- libdir localedir mandir -+ libdir localedir mandir runstatedir - do - eval ac_val=\$$ac_var - # Remove trailing slashes. -@@ -1399,6 +1409,7 @@ Fine tuning of the installation directories: - --sysconfdir=DIR read-only single-machine data [PREFIX/etc] - --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] - --localstatedir=DIR modifiable single-machine data [PREFIX/var] -+ --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] - --libdir=DIR object code libraries [EPREFIX/lib] - --includedir=DIR C header files [PREFIX/include] - --oldincludedir=DIR C header files for non-gcc [/usr/include] -@@ -2472,8 +2483,8 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. - - - --# expand $ac_aux_dir to an absolute path --am_aux_dir=`cd $ac_aux_dir && pwd` -+# Expand $ac_aux_dir to an absolute path. -+am_aux_dir=`cd "$ac_aux_dir" && pwd` - - ac_ext=c - ac_cpp='$CPP $CPPFLAGS' -@@ -3783,7 +3794,7 @@ $as_echo "$ac_cv_safe_to_define___extensions__" >&6; } - - - --am__api_version='1.14' -+am__api_version='1.15' - - # Find a good install program. We prefer a C program (faster), - # so one script is as good as another. But avoid the broken or -@@ -3972,7 +3983,7 @@ else - $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} - fi - --if test x"${install_sh}" != xset; then -+if test x"${install_sh+set}" != xset; then - case $am_aux_dir in - *\ * | *\ *) - install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; -@@ -4363,8 +4374,8 @@ MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} - # - mkdir_p='$(MKDIR_P)' - --# We need awk for the "check" target. The system "awk" is bad on --# some platforms. -+# We need awk for the "check" target (and possibly the TAP driver). The -+# system "awk" is bad on some platforms. - # Always define AMTAR for backward compatibility. Yes, it's still used - # in the wild :-( We should find a proper way to deprecate it ... - AMTAR='$${TAR-tar}' -@@ -4549,6 +4560,7 @@ END - as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 - fi - fi -+ - if test -n "$ac_tool_prefix"; then - for ac_prog in ar lib "link -lib" - do -@@ -12494,47 +12506,6 @@ $as_echo "no" >&6; } - fi - - -- # Extract the first word of "rm", so it can be a program name with args. --set dummy rm; ac_word=$2 --{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 --$as_echo_n "checking for $ac_word... " >&6; } --if ${ac_cv_path_RM+:} false; then : -- $as_echo_n "(cached) " >&6 --else -- case $RM in -- [\\/]* | ?:[\\/]*) -- ac_cv_path_RM="$RM" # Let the user override the test with a path. -- ;; -- *) -- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR --for as_dir in $PATH --do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do -- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then -- ac_cv_path_RM="$as_dir/$ac_word$ac_exec_ext" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 -- fi --done -- done --IFS=$as_save_IFS -- -- test -z "$ac_cv_path_RM" && ac_cv_path_RM="rm" -- ;; --esac --fi --RM=$ac_cv_path_RM --if test -n "$RM"; then -- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RM" >&5 --$as_echo "$RM" >&6; } --else -- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 --$as_echo "no" >&6; } --fi -- -- - # Extract the first word of "mv", so it can be a program name with args. - set dummy mv; ac_word=$2 - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -@@ -16204,15 +16175,162 @@ $as_echo "#define HAVE_IPv6 1" >>confdefs.h - - - if test -z "$USE_SYSTEM_SHARED_LIB_TRUE"; then : -- else -+ -+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sodium_init in -lsodium" >&5 -+$as_echo_n "checking for sodium_init in -lsodium... " >&6; } -+if ${ac_cv_lib_sodium_sodium_init+:} false; then : -+ $as_echo_n "(cached) " >&6 -+else -+ ac_check_lib_save_LIBS=$LIBS -+LIBS="-lsodium $LIBS" -+cat confdefs.h - <<_ACEOF >conftest.$ac_ext -+/* end confdefs.h. */ -+ -+/* Override any GCC internal prototype to avoid an error. -+ Use char because int might match the return type of a GCC -+ builtin and then its argument prototype would still apply. */ -+#ifdef __cplusplus -+extern "C" -+#endif -+char sodium_init (); -+int -+main () -+{ -+return sodium_init (); -+ ; -+ return 0; -+} -+_ACEOF -+if ac_fn_c_try_link "$LINENO"; then : -+ ac_cv_lib_sodium_sodium_init=yes -+else -+ ac_cv_lib_sodium_sodium_init=no -+fi -+rm -f core conftest.err conftest.$ac_objext \ -+ conftest$ac_exeext conftest.$ac_ext -+LIBS=$ac_check_lib_save_LIBS -+fi -+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sodium_sodium_init" >&5 -+$as_echo "$ac_cv_lib_sodium_sodium_init" >&6; } -+if test "x$ac_cv_lib_sodium_sodium_init" = xyes; then : -+ cat >>confdefs.h <<_ACEOF -+#define HAVE_LIBSODIUM 1 -+_ACEOF -+ -+ LIBS="-lsodium $LIBS" -+ -+else -+ -+ as_fn_error $? "Couldn't find libsodium. Try installing libsodium-dev[el]." "$LINENO" 5 -+ -+fi -+ -+ -+else - subdirs="$subdirs libsodium" - - fi - --ac_config_files="$ac_config_files shadowsocks-libev.pc Makefile libcork/Makefile libipset/Makefile src/Makefile" -+ac_config_files="$ac_config_files shadowsocks-libev.pc Makefile libcork/Makefile libipset/Makefile src/Makefile server/Makefile" - - if test -z "$USE_SYSTEM_SHARED_LIB_TRUE"; then : -- else -+ -+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dns_dnlen in -ludns" >&5 -+$as_echo_n "checking for dns_dnlen in -ludns... " >&6; } -+if ${ac_cv_lib_udns_dns_dnlen+:} false; then : -+ $as_echo_n "(cached) " >&6 -+else -+ ac_check_lib_save_LIBS=$LIBS -+LIBS="-ludns $LIBS" -+cat confdefs.h - <<_ACEOF >conftest.$ac_ext -+/* end confdefs.h. */ -+ -+/* Override any GCC internal prototype to avoid an error. -+ Use char because int might match the return type of a GCC -+ builtin and then its argument prototype would still apply. */ -+#ifdef __cplusplus -+extern "C" -+#endif -+char dns_dnlen (); -+int -+main () -+{ -+return dns_dnlen (); -+ ; -+ return 0; -+} -+_ACEOF -+if ac_fn_c_try_link "$LINENO"; then : -+ ac_cv_lib_udns_dns_dnlen=yes -+else -+ ac_cv_lib_udns_dns_dnlen=no -+fi -+rm -f core conftest.err conftest.$ac_objext \ -+ conftest$ac_exeext conftest.$ac_ext -+LIBS=$ac_check_lib_save_LIBS -+fi -+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_udns_dns_dnlen" >&5 -+$as_echo "$ac_cv_lib_udns_dns_dnlen" >&6; } -+if test "x$ac_cv_lib_udns_dns_dnlen" = xyes; then : -+ cat >>confdefs.h <<_ACEOF -+#define HAVE_LIBUDNS 1 -+_ACEOF -+ -+ LIBS="-ludns $LIBS" -+ -+else -+ as_fn_error $? "Couldn't find libudns. Try installing libudns-dev or udns-devel." "$LINENO" 5 -+fi -+ -+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ev_loop_destroy in -lev" >&5 -+$as_echo_n "checking for ev_loop_destroy in -lev... " >&6; } -+if ${ac_cv_lib_ev_ev_loop_destroy+:} false; then : -+ $as_echo_n "(cached) " >&6 -+else -+ ac_check_lib_save_LIBS=$LIBS -+LIBS="-lev $LIBS" -+cat confdefs.h - <<_ACEOF >conftest.$ac_ext -+/* end confdefs.h. */ -+ -+/* Override any GCC internal prototype to avoid an error. -+ Use char because int might match the return type of a GCC -+ builtin and then its argument prototype would still apply. */ -+#ifdef __cplusplus -+extern "C" -+#endif -+char ev_loop_destroy (); -+int -+main () -+{ -+return ev_loop_destroy (); -+ ; -+ return 0; -+} -+_ACEOF -+if ac_fn_c_try_link "$LINENO"; then : -+ ac_cv_lib_ev_ev_loop_destroy=yes -+else -+ ac_cv_lib_ev_ev_loop_destroy=no -+fi -+rm -f core conftest.err conftest.$ac_objext \ -+ conftest$ac_exeext conftest.$ac_ext -+LIBS=$ac_check_lib_save_LIBS -+fi -+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ev_ev_loop_destroy" >&5 -+$as_echo "$ac_cv_lib_ev_ev_loop_destroy" >&6; } -+if test "x$ac_cv_lib_ev_ev_loop_destroy" = xyes; then : -+ cat >>confdefs.h <<_ACEOF -+#define HAVE_LIBEV 1 -+_ACEOF -+ -+ LIBS="-lev $LIBS" -+ -+else -+ as_fn_error $? "Couldn't find libev. Try installing libev-dev[el]." "$LINENO" 5 -+fi -+ -+ -+else - ac_config_files="$ac_config_files libudns/Makefile libev/Makefile" - - fi -@@ -17258,6 +17376,7 @@ do - "libcork/Makefile") CONFIG_FILES="$CONFIG_FILES libcork/Makefile" ;; - "libipset/Makefile") CONFIG_FILES="$CONFIG_FILES libipset/Makefile" ;; - "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; -+ "server/Makefile") CONFIG_FILES="$CONFIG_FILES server/Makefile" ;; - "libudns/Makefile") CONFIG_FILES="$CONFIG_FILES libudns/Makefile" ;; - "libev/Makefile") CONFIG_FILES="$CONFIG_FILES libev/Makefile" ;; - "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; -@@ -17958,8 +18077,8 @@ $as_echo X"$file" | - fi - - cfgfile="${ofile}T" -- trap "$RM -f \"$cfgfile\"; exit 1" 1 2 15 -- $RM -f "$cfgfile" -+ trap "$RM \"$cfgfile\"; exit 1" 1 2 15 -+ $RM "$cfgfile" - - cat <<_LT_EOF >> "$cfgfile" - #! $SHELL -diff --git a/configure.ac b/configure.ac -index 6586f2b..f9c51ab 100755 ---- a/configure.ac -+++ b/configure.ac -@@ -315,7 +315,8 @@ AC_CONFIG_FILES([ shadowsocks-libev.pc - Makefile - libcork/Makefile - libipset/Makefile -- src/Makefile]) -+ src/Makefile -+ server/Makefile]) - AM_COND_IF([USE_SYSTEM_SHARED_LIB],[ - AC_CHECK_LIB([udns], [dns_dnlen], ,[AC_MSG_ERROR([Couldn't find libudns. Try installing libudns-dev or udns-devel.])]) - AC_CHECK_LIB([ev], [ev_loop_destroy], ,[AC_MSG_ERROR([Couldn't find libev. Try installing libev-dev@<:@el@:>@.])]) -diff --git a/server/Makefile.am b/server/Makefile.am -new file mode 100644 -index 0000000..3ae8bc2 ---- /dev/null -+++ b/server/Makefile.am -@@ -0,0 +1,55 @@ -+VERSION_INFO = 2:0:0 -+ -+AM_CFLAGS = -g -O2 -Wall -Werror -Wno-deprecated-declarations -fno-strict-aliasing -std=gnu99 -D_GNU_SOURCE -+AM_CFLAGS += $(PTHREAD_CFLAGS) -+if !USE_SYSTEM_SHARED_LIB -+AM_CFLAGS += -I$(top_srcdir)/libev -+AM_CFLAGS += -I$(top_srcdir)/libudns -+AM_CFLAGS += -I$(top_srcdir)/libsodium/src/libsodium/include -+endif -+AM_CFLAGS += -I$(top_srcdir)/libipset/include -+AM_CFLAGS += -I$(top_srcdir)/libcork/include -+AM_CFLAGS += $(LIBPCRE_CFLAGS) -+ -+SS_COMMON_LIBS = $(top_builddir)/libipset/libipset.la \ -+ $(top_builddir)/libcork/libcork.la \ -+ $(INET_NTOP_LIB) $(LIBPCRE_LIBS) -+if USE_SYSTEM_SHARED_LIB -+SS_COMMON_LIBS += -lev -lsodium -lm -+else -+SS_COMMON_LIBS += $(top_builddir)/libev/libev.la \ -+ $(top_builddir)/libsodium/src/libsodium/libsodium.la -+endif -+ -+bin_PROGRAMS = ss-server ss-check -+ -+sni_src = http.c \ -+ tls.c \ -+ rule.c -+ -+ss_check_SOURCES = check.c -+ -+ss_server_SOURCES = utils.c \ -+ netutils.c \ -+ jconf.c \ -+ json.c \ -+ encrypt.c \ -+ udprelay.c \ -+ cache.c \ -+ acl.c \ -+ resolv.c \ -+ server.c \ -+ $(sni_src) -+ -+ -+ss_check_LDADD = $(SS_COMMON_LIBS) -+ss_server_LDADD = $(SS_COMMON_LIBS) -+ -+if USE_SYSTEM_SHARED_LIB -+ss_server_LDADD += -ludns -+else -+ss_server_LDADD += $(top_builddir)/libudns/libudns.la -+endif -+ -+ss_check_CFLAGS = $(AM_CFLAGS) -+ss_server_CFLAGS = $(AM_CFLAGS) -DMODULE_REMOTE -diff --git a/server/Makefile.in b/server/Makefile.in -new file mode 100644 -index 0000000..3bfa53e ---- /dev/null -+++ b/server/Makefile.in -@@ -0,0 +1,919 @@ -+# Makefile.in generated by automake 1.15 from Makefile.am. -+# @configure_input@ -+ -+# Copyright (C) 1994-2014 Free Software Foundation, Inc. -+ -+# This Makefile.in is free software; the Free Software Foundation -+# gives unlimited permission to copy and/or distribute it, -+# with or without modifications, as long as this notice is preserved. -+ -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -+# PARTICULAR PURPOSE. -+ -+@SET_MAKE@ -+ -+VPATH = @srcdir@ -+am__is_gnu_make = { \ -+ if test -z '$(MAKELEVEL)'; then \ -+ false; \ -+ elif test -n '$(MAKE_HOST)'; then \ -+ true; \ -+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ -+ true; \ -+ else \ -+ false; \ -+ fi; \ -+} -+am__make_running_with_option = \ -+ case $${target_option-} in \ -+ ?) ;; \ -+ *) echo "am__make_running_with_option: internal error: invalid" \ -+ "target option '$${target_option-}' specified" >&2; \ -+ exit 1;; \ -+ esac; \ -+ has_opt=no; \ -+ sane_makeflags=$$MAKEFLAGS; \ -+ if $(am__is_gnu_make); then \ -+ sane_makeflags=$$MFLAGS; \ -+ else \ -+ case $$MAKEFLAGS in \ -+ *\\[\ \ ]*) \ -+ bs=\\; \ -+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ -+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ -+ esac; \ -+ fi; \ -+ skip_next=no; \ -+ strip_trailopt () \ -+ { \ -+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ -+ }; \ -+ for flg in $$sane_makeflags; do \ -+ test $$skip_next = yes && { skip_next=no; continue; }; \ -+ case $$flg in \ -+ *=*|--*) continue;; \ -+ -*I) strip_trailopt 'I'; skip_next=yes;; \ -+ -*I?*) strip_trailopt 'I';; \ -+ -*O) strip_trailopt 'O'; skip_next=yes;; \ -+ -*O?*) strip_trailopt 'O';; \ -+ -*l) strip_trailopt 'l'; skip_next=yes;; \ -+ -*l?*) strip_trailopt 'l';; \ -+ -[dEDm]) skip_next=yes;; \ -+ -[JT]) skip_next=yes;; \ -+ esac; \ -+ case $$flg in \ -+ *$$target_option*) has_opt=yes; break;; \ -+ esac; \ -+ done; \ -+ test $$has_opt = yes -+am__make_dryrun = (target_option=n; $(am__make_running_with_option)) -+am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) -+pkgdatadir = $(datadir)/@PACKAGE@ -+pkgincludedir = $(includedir)/@PACKAGE@ -+pkglibdir = $(libdir)/@PACKAGE@ -+pkglibexecdir = $(libexecdir)/@PACKAGE@ -+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -+install_sh_DATA = $(install_sh) -c -m 644 -+install_sh_PROGRAM = $(install_sh) -c -+install_sh_SCRIPT = $(install_sh) -c -+INSTALL_HEADER = $(INSTALL_DATA) -+transform = $(program_transform_name) -+NORMAL_INSTALL = : -+PRE_INSTALL = : -+POST_INSTALL = : -+NORMAL_UNINSTALL = : -+PRE_UNINSTALL = : -+POST_UNINSTALL = : -+build_triplet = @build@ -+host_triplet = @host@ -+@USE_SYSTEM_SHARED_LIB_FALSE@am__append_1 = -I$(top_srcdir)/libev \ -+@USE_SYSTEM_SHARED_LIB_FALSE@ -I$(top_srcdir)/libudns \ -+@USE_SYSTEM_SHARED_LIB_FALSE@ -I$(top_srcdir)/libsodium/src/libsodium/include -+@USE_SYSTEM_SHARED_LIB_TRUE@am__append_2 = -lev -lsodium -lm -+@USE_SYSTEM_SHARED_LIB_FALSE@am__append_3 = $(top_builddir)/libev/libev.la \ -+@USE_SYSTEM_SHARED_LIB_FALSE@ $(top_builddir)/libsodium/src/libsodium/libsodium.la -+ -+bin_PROGRAMS = ss-server$(EXEEXT) ss-check$(EXEEXT) -+@USE_SYSTEM_SHARED_LIB_TRUE@am__append_4 = -ludns -+@USE_SYSTEM_SHARED_LIB_FALSE@am__append_5 = $(top_builddir)/libudns/libudns.la -+subdir = server -+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_pthread.m4 \ -+ $(top_srcdir)/m4/ax_tls.m4 $(top_srcdir)/m4/inet_ntop.m4 \ -+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ -+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ -+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/mbedtls.m4 \ -+ $(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/pcre.m4 \ -+ $(top_srcdir)/m4/polarssl.m4 \ -+ $(top_srcdir)/m4/stack-protector.m4 $(top_srcdir)/m4/zlib.m4 \ -+ $(top_srcdir)/libev/libev.m4 $(top_srcdir)/configure.ac -+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ -+ $(ACLOCAL_M4) -+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) -+mkinstalldirs = $(install_sh) -d -+CONFIG_HEADER = $(top_builddir)/config.h -+CONFIG_CLEAN_FILES = -+CONFIG_CLEAN_VPATH_FILES = -+am__installdirs = "$(DESTDIR)$(bindir)" -+PROGRAMS = $(bin_PROGRAMS) -+am_ss_check_OBJECTS = ss_check-check.$(OBJEXT) -+ss_check_OBJECTS = $(am_ss_check_OBJECTS) -+am__DEPENDENCIES_1 = -+am__DEPENDENCIES_2 = $(top_builddir)/libipset/libipset.la \ -+ $(top_builddir)/libcork/libcork.la $(am__DEPENDENCIES_1) \ -+ $(am__DEPENDENCIES_1) $(am__append_3) -+ss_check_DEPENDENCIES = $(am__DEPENDENCIES_2) -+AM_V_lt = $(am__v_lt_@AM_V@) -+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -+am__v_lt_0 = --silent -+am__v_lt_1 = -+ss_check_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ -+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(ss_check_CFLAGS) \ -+ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -+am__objects_1 = ss_server-http.$(OBJEXT) ss_server-tls.$(OBJEXT) \ -+ ss_server-rule.$(OBJEXT) -+am_ss_server_OBJECTS = ss_server-utils.$(OBJEXT) \ -+ ss_server-netutils.$(OBJEXT) ss_server-jconf.$(OBJEXT) \ -+ ss_server-json.$(OBJEXT) ss_server-encrypt.$(OBJEXT) \ -+ ss_server-udprelay.$(OBJEXT) ss_server-cache.$(OBJEXT) \ -+ ss_server-acl.$(OBJEXT) ss_server-resolv.$(OBJEXT) \ -+ ss_server-server.$(OBJEXT) $(am__objects_1) -+ss_server_OBJECTS = $(am_ss_server_OBJECTS) -+ss_server_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \ -+ $(am__append_5) -+ss_server_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ -+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(ss_server_CFLAGS) \ -+ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -+AM_V_P = $(am__v_P_@AM_V@) -+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -+am__v_P_0 = false -+am__v_P_1 = : -+AM_V_GEN = $(am__v_GEN_@AM_V@) -+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -+am__v_GEN_0 = @echo " GEN " $@; -+am__v_GEN_1 = -+AM_V_at = $(am__v_at_@AM_V@) -+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -+am__v_at_0 = @ -+am__v_at_1 = -+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -+depcomp = $(SHELL) $(top_srcdir)/auto/depcomp -+am__depfiles_maybe = depfiles -+am__mv = mv -f -+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ -+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ -+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ -+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ -+ $(AM_CFLAGS) $(CFLAGS) -+AM_V_CC = $(am__v_CC_@AM_V@) -+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) -+am__v_CC_0 = @echo " CC " $@; -+am__v_CC_1 = -+CCLD = $(CC) -+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ -+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ -+ $(AM_LDFLAGS) $(LDFLAGS) -o $@ -+AM_V_CCLD = $(am__v_CCLD_@AM_V@) -+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) -+am__v_CCLD_0 = @echo " CCLD " $@; -+am__v_CCLD_1 = -+SOURCES = $(ss_check_SOURCES) $(ss_server_SOURCES) -+DIST_SOURCES = $(ss_check_SOURCES) $(ss_server_SOURCES) -+am__can_run_installinfo = \ -+ case $$AM_UPDATE_INFO_DIR in \ -+ n|no|NO) false;; \ -+ *) (install-info --version) >/dev/null 2>&1;; \ -+ esac -+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) -+# Read a list of newline-separated strings from the standard input, -+# and print each of them once, without duplicates. Input order is -+# *not* preserved. -+am__uniquify_input = $(AWK) '\ -+ BEGIN { nonempty = 0; } \ -+ { items[$$0] = 1; nonempty = 1; } \ -+ END { if (nonempty) { for (i in items) print i; }; } \ -+' -+# Make sure the list of sources is unique. This is necessary because, -+# e.g., the same source file might be shared among _SOURCES variables -+# for different programs/libraries. -+am__define_uniq_tagged_files = \ -+ list='$(am__tagged_files)'; \ -+ unique=`for i in $$list; do \ -+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ -+ done | $(am__uniquify_input)` -+ETAGS = etags -+CTAGS = ctags -+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/auto/depcomp -+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -+ACLOCAL = @ACLOCAL@ -+AMTAR = @AMTAR@ -+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -+AR = @AR@ -+ASCIIDOC = @ASCIIDOC@ -+AUTOCONF = @AUTOCONF@ -+AUTOHEADER = @AUTOHEADER@ -+AUTOMAKE = @AUTOMAKE@ -+AWK = @AWK@ -+CC = @CC@ -+CCDEPMODE = @CCDEPMODE@ -+CFLAGS = @CFLAGS@ -+CPP = @CPP@ -+CPPFLAGS = @CPPFLAGS@ -+CYGPATH_W = @CYGPATH_W@ -+DEFS = @DEFS@ -+DEPDIR = @DEPDIR@ -+DLLTOOL = @DLLTOOL@ -+DSYMUTIL = @DSYMUTIL@ -+DUMPBIN = @DUMPBIN@ -+ECHO_C = @ECHO_C@ -+ECHO_N = @ECHO_N@ -+ECHO_T = @ECHO_T@ -+EGREP = @EGREP@ -+EXEEXT = @EXEEXT@ -+FGREP = @FGREP@ -+GREP = @GREP@ -+GZIP = @GZIP@ -+INET_NTOP_LIB = @INET_NTOP_LIB@ -+INSTALL = @INSTALL@ -+INSTALL_DATA = @INSTALL_DATA@ -+INSTALL_PROGRAM = @INSTALL_PROGRAM@ -+INSTALL_SCRIPT = @INSTALL_SCRIPT@ -+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -+LD = @LD@ -+LDFLAGS = @LDFLAGS@ -+LIBOBJS = @LIBOBJS@ -+LIBPCRE = @LIBPCRE@ -+LIBS = @LIBS@ -+LIBTOOL = @LIBTOOL@ -+LIPO = @LIPO@ -+LN_S = @LN_S@ -+LTLIBOBJS = @LTLIBOBJS@ -+MAINT = @MAINT@ -+MAKEINFO = @MAKEINFO@ -+MANIFEST_TOOL = @MANIFEST_TOOL@ -+MKDIR_P = @MKDIR_P@ -+MV = @MV@ -+NM = @NM@ -+NMEDIT = @NMEDIT@ -+OBJDUMP = @OBJDUMP@ -+OBJEXT = @OBJEXT@ -+OTOOL = @OTOOL@ -+OTOOL64 = @OTOOL64@ -+PACKAGE = @PACKAGE@ -+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -+PACKAGE_NAME = @PACKAGE_NAME@ -+PACKAGE_STRING = @PACKAGE_STRING@ -+PACKAGE_TARNAME = @PACKAGE_TARNAME@ -+PACKAGE_URL = @PACKAGE_URL@ -+PACKAGE_VERSION = @PACKAGE_VERSION@ -+PATH_SEPARATOR = @PATH_SEPARATOR@ -+PCRE_CONFIG = @PCRE_CONFIG@ -+PTHREAD_CC = @PTHREAD_CC@ -+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ -+PTHREAD_LIBS = @PTHREAD_LIBS@ -+RANLIB = @RANLIB@ -+SED = @SED@ -+SET_MAKE = @SET_MAKE@ -+SHELL = @SHELL@ -+STRIP = @STRIP@ -+VERSION = @VERSION@ -+XMLTO = @XMLTO@ -+abs_builddir = @abs_builddir@ -+abs_srcdir = @abs_srcdir@ -+abs_top_builddir = @abs_top_builddir@ -+abs_top_srcdir = @abs_top_srcdir@ -+ac_ct_AR = @ac_ct_AR@ -+ac_ct_CC = @ac_ct_CC@ -+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -+am__include = @am__include@ -+am__leading_dot = @am__leading_dot@ -+am__quote = @am__quote@ -+am__tar = @am__tar@ -+am__untar = @am__untar@ -+ax_pthread_config = @ax_pthread_config@ -+bindir = @bindir@ -+build = @build@ -+build_alias = @build_alias@ -+build_cpu = @build_cpu@ -+build_os = @build_os@ -+build_vendor = @build_vendor@ -+builddir = @builddir@ -+datadir = @datadir@ -+datarootdir = @datarootdir@ -+docdir = @docdir@ -+dvidir = @dvidir@ -+exec_prefix = @exec_prefix@ -+host = @host@ -+host_alias = @host_alias@ -+host_cpu = @host_cpu@ -+host_os = @host_os@ -+host_vendor = @host_vendor@ -+htmldir = @htmldir@ -+includedir = @includedir@ -+infodir = @infodir@ -+install_sh = @install_sh@ -+libdir = @libdir@ -+libexecdir = @libexecdir@ -+localedir = @localedir@ -+localstatedir = @localstatedir@ -+mandir = @mandir@ -+mkdir_p = @mkdir_p@ -+oldincludedir = @oldincludedir@ -+pcre_pcreh = @pcre_pcreh@ -+pcreh = @pcreh@ -+pdfdir = @pdfdir@ -+prefix = @prefix@ -+program_transform_name = @program_transform_name@ -+psdir = @psdir@ -+runstatedir = @runstatedir@ -+sbindir = @sbindir@ -+sharedstatedir = @sharedstatedir@ -+srcdir = @srcdir@ -+subdirs = @subdirs@ -+sysconfdir = @sysconfdir@ -+target_alias = @target_alias@ -+top_build_prefix = @top_build_prefix@ -+top_builddir = @top_builddir@ -+top_srcdir = @top_srcdir@ -+VERSION_INFO = 2:0:0 -+AM_CFLAGS = -g -O2 -Wall -Werror -Wno-deprecated-declarations \ -+ -fno-strict-aliasing -std=gnu99 -D_GNU_SOURCE \ -+ $(PTHREAD_CFLAGS) $(am__append_1) \ -+ -I$(top_srcdir)/libipset/include \ -+ -I$(top_srcdir)/libcork/include $(LIBPCRE_CFLAGS) -+SS_COMMON_LIBS = $(top_builddir)/libipset/libipset.la \ -+ $(top_builddir)/libcork/libcork.la $(INET_NTOP_LIB) \ -+ $(LIBPCRE_LIBS) $(am__append_2) $(am__append_3) -+sni_src = http.c \ -+ tls.c \ -+ rule.c -+ -+ss_check_SOURCES = check.c -+ss_server_SOURCES = utils.c \ -+ netutils.c \ -+ jconf.c \ -+ json.c \ -+ encrypt.c \ -+ udprelay.c \ -+ cache.c \ -+ acl.c \ -+ resolv.c \ -+ server.c \ -+ $(sni_src) -+ -+ss_check_LDADD = $(SS_COMMON_LIBS) -+ss_server_LDADD = $(SS_COMMON_LIBS) $(am__append_4) $(am__append_5) -+ss_check_CFLAGS = $(AM_CFLAGS) -+ss_server_CFLAGS = $(AM_CFLAGS) -DMODULE_REMOTE -+all: all-am -+ -+.SUFFIXES: -+.SUFFIXES: .c .lo .o .obj -+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) -+ @for dep in $?; do \ -+ case '$(am__configure_deps)' in \ -+ *$$dep*) \ -+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ -+ && { if test -f $@; then exit 0; else break; fi; }; \ -+ exit 1;; \ -+ esac; \ -+ done; \ -+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign server/Makefile'; \ -+ $(am__cd) $(top_srcdir) && \ -+ $(AUTOMAKE) --foreign server/Makefile -+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status -+ @case '$?' in \ -+ *config.status*) \ -+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ -+ *) \ -+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ -+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ -+ esac; -+ -+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) -+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -+ -+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) -+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) -+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -+$(am__aclocal_m4_deps): -+install-binPROGRAMS: $(bin_PROGRAMS) -+ @$(NORMAL_INSTALL) -+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ -+ if test -n "$$list"; then \ -+ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ -+ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ -+ fi; \ -+ for p in $$list; do echo "$$p $$p"; done | \ -+ sed 's/$(EXEEXT)$$//' | \ -+ while read p p1; do if test -f $$p \ -+ || test -f $$p1 \ -+ ; then echo "$$p"; echo "$$p"; else :; fi; \ -+ done | \ -+ sed -e 'p;s,.*/,,;n;h' \ -+ -e 's|.*|.|' \ -+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ -+ sed 'N;N;N;s,\n, ,g' | \ -+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ -+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ -+ if ($$2 == $$4) files[d] = files[d] " " $$1; \ -+ else { print "f", $$3 "/" $$4, $$1; } } \ -+ END { for (d in files) print "f", d, files[d] }' | \ -+ while read type dir files; do \ -+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ -+ test -z "$$files" || { \ -+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ -+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ -+ } \ -+ ; done -+ -+uninstall-binPROGRAMS: -+ @$(NORMAL_UNINSTALL) -+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ -+ files=`for p in $$list; do echo "$$p"; done | \ -+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -+ -e 's/$$/$(EXEEXT)/' \ -+ `; \ -+ test -n "$$list" || exit 0; \ -+ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ -+ cd "$(DESTDIR)$(bindir)" && rm -f $$files -+ -+clean-binPROGRAMS: -+ @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ -+ echo " rm -f" $$list; \ -+ rm -f $$list || exit $$?; \ -+ test -n "$(EXEEXT)" || exit 0; \ -+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ -+ echo " rm -f" $$list; \ -+ rm -f $$list -+ -+ss-check$(EXEEXT): $(ss_check_OBJECTS) $(ss_check_DEPENDENCIES) $(EXTRA_ss_check_DEPENDENCIES) -+ @rm -f ss-check$(EXEEXT) -+ $(AM_V_CCLD)$(ss_check_LINK) $(ss_check_OBJECTS) $(ss_check_LDADD) $(LIBS) -+ -+ss-server$(EXEEXT): $(ss_server_OBJECTS) $(ss_server_DEPENDENCIES) $(EXTRA_ss_server_DEPENDENCIES) -+ @rm -f ss-server$(EXEEXT) -+ $(AM_V_CCLD)$(ss_server_LINK) $(ss_server_OBJECTS) $(ss_server_LDADD) $(LIBS) -+ -+mostlyclean-compile: -+ -rm -f *.$(OBJEXT) -+ -+distclean-compile: -+ -rm -f *.tab.c -+ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_check-check.Po@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-acl.Po@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-cache.Po@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-encrypt.Po@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-http.Po@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-jconf.Po@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-json.Po@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-netutils.Po@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-resolv.Po@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-rule.Po@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-server.Po@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-tls.Po@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-udprelay.Po@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-utils.Po@am__quote@ -+ -+.c.o: -+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ -+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ -+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< -+ -+.c.obj: -+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ -+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ -+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` -+ -+.c.lo: -+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ -+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ -+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< -+ -+ss_check-check.o: check.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_check_CFLAGS) $(CFLAGS) -MT ss_check-check.o -MD -MP -MF $(DEPDIR)/ss_check-check.Tpo -c -o ss_check-check.o `test -f 'check.c' || echo '$(srcdir)/'`check.c -+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_check-check.Tpo $(DEPDIR)/ss_check-check.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='check.c' object='ss_check-check.o' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_check_CFLAGS) $(CFLAGS) -c -o ss_check-check.o `test -f 'check.c' || echo '$(srcdir)/'`check.c -+ -+ss_check-check.obj: check.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_check_CFLAGS) $(CFLAGS) -MT ss_check-check.obj -MD -MP -MF $(DEPDIR)/ss_check-check.Tpo -c -o ss_check-check.obj `if test -f 'check.c'; then $(CYGPATH_W) 'check.c'; else $(CYGPATH_W) '$(srcdir)/check.c'; fi` -+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_check-check.Tpo $(DEPDIR)/ss_check-check.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='check.c' object='ss_check-check.obj' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_check_CFLAGS) $(CFLAGS) -c -o ss_check-check.obj `if test -f 'check.c'; then $(CYGPATH_W) 'check.c'; else $(CYGPATH_W) '$(srcdir)/check.c'; fi` -+ -+ss_server-utils.o: utils.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-utils.o -MD -MP -MF $(DEPDIR)/ss_server-utils.Tpo -c -o ss_server-utils.o `test -f 'utils.c' || echo '$(srcdir)/'`utils.c -+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-utils.Tpo $(DEPDIR)/ss_server-utils.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='utils.c' object='ss_server-utils.o' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-utils.o `test -f 'utils.c' || echo '$(srcdir)/'`utils.c -+ -+ss_server-utils.obj: utils.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-utils.obj -MD -MP -MF $(DEPDIR)/ss_server-utils.Tpo -c -o ss_server-utils.obj `if test -f 'utils.c'; then $(CYGPATH_W) 'utils.c'; else $(CYGPATH_W) '$(srcdir)/utils.c'; fi` -+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-utils.Tpo $(DEPDIR)/ss_server-utils.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='utils.c' object='ss_server-utils.obj' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-utils.obj `if test -f 'utils.c'; then $(CYGPATH_W) 'utils.c'; else $(CYGPATH_W) '$(srcdir)/utils.c'; fi` -+ -+ss_server-netutils.o: netutils.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-netutils.o -MD -MP -MF $(DEPDIR)/ss_server-netutils.Tpo -c -o ss_server-netutils.o `test -f 'netutils.c' || echo '$(srcdir)/'`netutils.c -+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-netutils.Tpo $(DEPDIR)/ss_server-netutils.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netutils.c' object='ss_server-netutils.o' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-netutils.o `test -f 'netutils.c' || echo '$(srcdir)/'`netutils.c -+ -+ss_server-netutils.obj: netutils.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-netutils.obj -MD -MP -MF $(DEPDIR)/ss_server-netutils.Tpo -c -o ss_server-netutils.obj `if test -f 'netutils.c'; then $(CYGPATH_W) 'netutils.c'; else $(CYGPATH_W) '$(srcdir)/netutils.c'; fi` -+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-netutils.Tpo $(DEPDIR)/ss_server-netutils.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netutils.c' object='ss_server-netutils.obj' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-netutils.obj `if test -f 'netutils.c'; then $(CYGPATH_W) 'netutils.c'; else $(CYGPATH_W) '$(srcdir)/netutils.c'; fi` -+ -+ss_server-jconf.o: jconf.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-jconf.o -MD -MP -MF $(DEPDIR)/ss_server-jconf.Tpo -c -o ss_server-jconf.o `test -f 'jconf.c' || echo '$(srcdir)/'`jconf.c -+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-jconf.Tpo $(DEPDIR)/ss_server-jconf.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='jconf.c' object='ss_server-jconf.o' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-jconf.o `test -f 'jconf.c' || echo '$(srcdir)/'`jconf.c -+ -+ss_server-jconf.obj: jconf.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-jconf.obj -MD -MP -MF $(DEPDIR)/ss_server-jconf.Tpo -c -o ss_server-jconf.obj `if test -f 'jconf.c'; then $(CYGPATH_W) 'jconf.c'; else $(CYGPATH_W) '$(srcdir)/jconf.c'; fi` -+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-jconf.Tpo $(DEPDIR)/ss_server-jconf.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='jconf.c' object='ss_server-jconf.obj' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-jconf.obj `if test -f 'jconf.c'; then $(CYGPATH_W) 'jconf.c'; else $(CYGPATH_W) '$(srcdir)/jconf.c'; fi` -+ -+ss_server-json.o: json.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-json.o -MD -MP -MF $(DEPDIR)/ss_server-json.Tpo -c -o ss_server-json.o `test -f 'json.c' || echo '$(srcdir)/'`json.c -+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-json.Tpo $(DEPDIR)/ss_server-json.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='json.c' object='ss_server-json.o' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-json.o `test -f 'json.c' || echo '$(srcdir)/'`json.c -+ -+ss_server-json.obj: json.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-json.obj -MD -MP -MF $(DEPDIR)/ss_server-json.Tpo -c -o ss_server-json.obj `if test -f 'json.c'; then $(CYGPATH_W) 'json.c'; else $(CYGPATH_W) '$(srcdir)/json.c'; fi` -+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-json.Tpo $(DEPDIR)/ss_server-json.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='json.c' object='ss_server-json.obj' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-json.obj `if test -f 'json.c'; then $(CYGPATH_W) 'json.c'; else $(CYGPATH_W) '$(srcdir)/json.c'; fi` -+ -+ss_server-encrypt.o: encrypt.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-encrypt.o -MD -MP -MF $(DEPDIR)/ss_server-encrypt.Tpo -c -o ss_server-encrypt.o `test -f 'encrypt.c' || echo '$(srcdir)/'`encrypt.c -+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-encrypt.Tpo $(DEPDIR)/ss_server-encrypt.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='encrypt.c' object='ss_server-encrypt.o' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-encrypt.o `test -f 'encrypt.c' || echo '$(srcdir)/'`encrypt.c -+ -+ss_server-encrypt.obj: encrypt.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-encrypt.obj -MD -MP -MF $(DEPDIR)/ss_server-encrypt.Tpo -c -o ss_server-encrypt.obj `if test -f 'encrypt.c'; then $(CYGPATH_W) 'encrypt.c'; else $(CYGPATH_W) '$(srcdir)/encrypt.c'; fi` -+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-encrypt.Tpo $(DEPDIR)/ss_server-encrypt.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='encrypt.c' object='ss_server-encrypt.obj' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-encrypt.obj `if test -f 'encrypt.c'; then $(CYGPATH_W) 'encrypt.c'; else $(CYGPATH_W) '$(srcdir)/encrypt.c'; fi` -+ -+ss_server-udprelay.o: udprelay.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-udprelay.o -MD -MP -MF $(DEPDIR)/ss_server-udprelay.Tpo -c -o ss_server-udprelay.o `test -f 'udprelay.c' || echo '$(srcdir)/'`udprelay.c -+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-udprelay.Tpo $(DEPDIR)/ss_server-udprelay.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='udprelay.c' object='ss_server-udprelay.o' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-udprelay.o `test -f 'udprelay.c' || echo '$(srcdir)/'`udprelay.c -+ -+ss_server-udprelay.obj: udprelay.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-udprelay.obj -MD -MP -MF $(DEPDIR)/ss_server-udprelay.Tpo -c -o ss_server-udprelay.obj `if test -f 'udprelay.c'; then $(CYGPATH_W) 'udprelay.c'; else $(CYGPATH_W) '$(srcdir)/udprelay.c'; fi` -+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-udprelay.Tpo $(DEPDIR)/ss_server-udprelay.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='udprelay.c' object='ss_server-udprelay.obj' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-udprelay.obj `if test -f 'udprelay.c'; then $(CYGPATH_W) 'udprelay.c'; else $(CYGPATH_W) '$(srcdir)/udprelay.c'; fi` -+ -+ss_server-cache.o: cache.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-cache.o -MD -MP -MF $(DEPDIR)/ss_server-cache.Tpo -c -o ss_server-cache.o `test -f 'cache.c' || echo '$(srcdir)/'`cache.c -+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-cache.Tpo $(DEPDIR)/ss_server-cache.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cache.c' object='ss_server-cache.o' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-cache.o `test -f 'cache.c' || echo '$(srcdir)/'`cache.c -+ -+ss_server-cache.obj: cache.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-cache.obj -MD -MP -MF $(DEPDIR)/ss_server-cache.Tpo -c -o ss_server-cache.obj `if test -f 'cache.c'; then $(CYGPATH_W) 'cache.c'; else $(CYGPATH_W) '$(srcdir)/cache.c'; fi` -+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-cache.Tpo $(DEPDIR)/ss_server-cache.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cache.c' object='ss_server-cache.obj' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-cache.obj `if test -f 'cache.c'; then $(CYGPATH_W) 'cache.c'; else $(CYGPATH_W) '$(srcdir)/cache.c'; fi` -+ -+ss_server-acl.o: acl.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-acl.o -MD -MP -MF $(DEPDIR)/ss_server-acl.Tpo -c -o ss_server-acl.o `test -f 'acl.c' || echo '$(srcdir)/'`acl.c -+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-acl.Tpo $(DEPDIR)/ss_server-acl.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='acl.c' object='ss_server-acl.o' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-acl.o `test -f 'acl.c' || echo '$(srcdir)/'`acl.c -+ -+ss_server-acl.obj: acl.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-acl.obj -MD -MP -MF $(DEPDIR)/ss_server-acl.Tpo -c -o ss_server-acl.obj `if test -f 'acl.c'; then $(CYGPATH_W) 'acl.c'; else $(CYGPATH_W) '$(srcdir)/acl.c'; fi` -+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-acl.Tpo $(DEPDIR)/ss_server-acl.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='acl.c' object='ss_server-acl.obj' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-acl.obj `if test -f 'acl.c'; then $(CYGPATH_W) 'acl.c'; else $(CYGPATH_W) '$(srcdir)/acl.c'; fi` -+ -+ss_server-resolv.o: resolv.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-resolv.o -MD -MP -MF $(DEPDIR)/ss_server-resolv.Tpo -c -o ss_server-resolv.o `test -f 'resolv.c' || echo '$(srcdir)/'`resolv.c -+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-resolv.Tpo $(DEPDIR)/ss_server-resolv.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='resolv.c' object='ss_server-resolv.o' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-resolv.o `test -f 'resolv.c' || echo '$(srcdir)/'`resolv.c -+ -+ss_server-resolv.obj: resolv.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-resolv.obj -MD -MP -MF $(DEPDIR)/ss_server-resolv.Tpo -c -o ss_server-resolv.obj `if test -f 'resolv.c'; then $(CYGPATH_W) 'resolv.c'; else $(CYGPATH_W) '$(srcdir)/resolv.c'; fi` -+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-resolv.Tpo $(DEPDIR)/ss_server-resolv.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='resolv.c' object='ss_server-resolv.obj' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-resolv.obj `if test -f 'resolv.c'; then $(CYGPATH_W) 'resolv.c'; else $(CYGPATH_W) '$(srcdir)/resolv.c'; fi` -+ -+ss_server-server.o: server.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-server.o -MD -MP -MF $(DEPDIR)/ss_server-server.Tpo -c -o ss_server-server.o `test -f 'server.c' || echo '$(srcdir)/'`server.c -+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-server.Tpo $(DEPDIR)/ss_server-server.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server.c' object='ss_server-server.o' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-server.o `test -f 'server.c' || echo '$(srcdir)/'`server.c -+ -+ss_server-server.obj: server.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-server.obj -MD -MP -MF $(DEPDIR)/ss_server-server.Tpo -c -o ss_server-server.obj `if test -f 'server.c'; then $(CYGPATH_W) 'server.c'; else $(CYGPATH_W) '$(srcdir)/server.c'; fi` -+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-server.Tpo $(DEPDIR)/ss_server-server.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server.c' object='ss_server-server.obj' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-server.obj `if test -f 'server.c'; then $(CYGPATH_W) 'server.c'; else $(CYGPATH_W) '$(srcdir)/server.c'; fi` -+ -+ss_server-http.o: http.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-http.o -MD -MP -MF $(DEPDIR)/ss_server-http.Tpo -c -o ss_server-http.o `test -f 'http.c' || echo '$(srcdir)/'`http.c -+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-http.Tpo $(DEPDIR)/ss_server-http.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='http.c' object='ss_server-http.o' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-http.o `test -f 'http.c' || echo '$(srcdir)/'`http.c -+ -+ss_server-http.obj: http.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-http.obj -MD -MP -MF $(DEPDIR)/ss_server-http.Tpo -c -o ss_server-http.obj `if test -f 'http.c'; then $(CYGPATH_W) 'http.c'; else $(CYGPATH_W) '$(srcdir)/http.c'; fi` -+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-http.Tpo $(DEPDIR)/ss_server-http.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='http.c' object='ss_server-http.obj' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-http.obj `if test -f 'http.c'; then $(CYGPATH_W) 'http.c'; else $(CYGPATH_W) '$(srcdir)/http.c'; fi` -+ -+ss_server-tls.o: tls.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-tls.o -MD -MP -MF $(DEPDIR)/ss_server-tls.Tpo -c -o ss_server-tls.o `test -f 'tls.c' || echo '$(srcdir)/'`tls.c -+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-tls.Tpo $(DEPDIR)/ss_server-tls.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tls.c' object='ss_server-tls.o' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-tls.o `test -f 'tls.c' || echo '$(srcdir)/'`tls.c -+ -+ss_server-tls.obj: tls.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-tls.obj -MD -MP -MF $(DEPDIR)/ss_server-tls.Tpo -c -o ss_server-tls.obj `if test -f 'tls.c'; then $(CYGPATH_W) 'tls.c'; else $(CYGPATH_W) '$(srcdir)/tls.c'; fi` -+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-tls.Tpo $(DEPDIR)/ss_server-tls.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tls.c' object='ss_server-tls.obj' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-tls.obj `if test -f 'tls.c'; then $(CYGPATH_W) 'tls.c'; else $(CYGPATH_W) '$(srcdir)/tls.c'; fi` -+ -+ss_server-rule.o: rule.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-rule.o -MD -MP -MF $(DEPDIR)/ss_server-rule.Tpo -c -o ss_server-rule.o `test -f 'rule.c' || echo '$(srcdir)/'`rule.c -+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-rule.Tpo $(DEPDIR)/ss_server-rule.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rule.c' object='ss_server-rule.o' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-rule.o `test -f 'rule.c' || echo '$(srcdir)/'`rule.c -+ -+ss_server-rule.obj: rule.c -+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-rule.obj -MD -MP -MF $(DEPDIR)/ss_server-rule.Tpo -c -o ss_server-rule.obj `if test -f 'rule.c'; then $(CYGPATH_W) 'rule.c'; else $(CYGPATH_W) '$(srcdir)/rule.c'; fi` -+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-rule.Tpo $(DEPDIR)/ss_server-rule.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rule.c' object='ss_server-rule.obj' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-rule.obj `if test -f 'rule.c'; then $(CYGPATH_W) 'rule.c'; else $(CYGPATH_W) '$(srcdir)/rule.c'; fi` -+ -+mostlyclean-libtool: -+ -rm -f *.lo -+ -+clean-libtool: -+ -rm -rf .libs _libs -+ -+ID: $(am__tagged_files) -+ $(am__define_uniq_tagged_files); mkid -fID $$unique -+tags: tags-am -+TAGS: tags -+ -+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) -+ set x; \ -+ here=`pwd`; \ -+ $(am__define_uniq_tagged_files); \ -+ shift; \ -+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ -+ test -n "$$unique" || unique=$$empty_fix; \ -+ if test $$# -gt 0; then \ -+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ -+ "$$@" $$unique; \ -+ else \ -+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ -+ $$unique; \ -+ fi; \ -+ fi -+ctags: ctags-am -+ -+CTAGS: ctags -+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) -+ $(am__define_uniq_tagged_files); \ -+ test -z "$(CTAGS_ARGS)$$unique" \ -+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ -+ $$unique -+ -+GTAGS: -+ here=`$(am__cd) $(top_builddir) && pwd` \ -+ && $(am__cd) $(top_srcdir) \ -+ && gtags -i $(GTAGS_ARGS) "$$here" -+cscopelist: cscopelist-am -+ -+cscopelist-am: $(am__tagged_files) -+ list='$(am__tagged_files)'; \ -+ case "$(srcdir)" in \ -+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ -+ *) sdir=$(subdir)/$(srcdir) ;; \ -+ esac; \ -+ for i in $$list; do \ -+ if test -f "$$i"; then \ -+ echo "$(subdir)/$$i"; \ -+ else \ -+ echo "$$sdir/$$i"; \ -+ fi; \ -+ done >> $(top_builddir)/cscope.files -+ -+distclean-tags: -+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -+ -+distdir: $(DISTFILES) -+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ -+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ -+ list='$(DISTFILES)'; \ -+ dist_files=`for file in $$list; do echo $$file; done | \ -+ sed -e "s|^$$srcdirstrip/||;t" \ -+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ -+ case $$dist_files in \ -+ */*) $(MKDIR_P) `echo "$$dist_files" | \ -+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ -+ sort -u` ;; \ -+ esac; \ -+ for file in $$dist_files; do \ -+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ -+ if test -d $$d/$$file; then \ -+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ -+ if test -d "$(distdir)/$$file"; then \ -+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ -+ fi; \ -+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ -+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ -+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ -+ fi; \ -+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ -+ else \ -+ test -f "$(distdir)/$$file" \ -+ || cp -p $$d/$$file "$(distdir)/$$file" \ -+ || exit 1; \ -+ fi; \ -+ done -+check-am: all-am -+check: check-am -+all-am: Makefile $(PROGRAMS) -+installdirs: -+ for dir in "$(DESTDIR)$(bindir)"; do \ -+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ -+ done -+install: install-am -+install-exec: install-exec-am -+install-data: install-data-am -+uninstall: uninstall-am -+ -+install-am: all-am -+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am -+ -+installcheck: installcheck-am -+install-strip: -+ if test -z '$(STRIP)'; then \ -+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ -+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ -+ install; \ -+ else \ -+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ -+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ -+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ -+ fi -+mostlyclean-generic: -+ -+clean-generic: -+ -+distclean-generic: -+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -+ -+maintainer-clean-generic: -+ @echo "This command is intended for maintainers to use" -+ @echo "it deletes files that may require special tools to rebuild." -+clean: clean-am -+ -+clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am -+ -+distclean: distclean-am -+ -rm -rf ./$(DEPDIR) -+ -rm -f Makefile -+distclean-am: clean-am distclean-compile distclean-generic \ -+ distclean-tags -+ -+dvi: dvi-am -+ -+dvi-am: -+ -+html: html-am -+ -+html-am: -+ -+info: info-am -+ -+info-am: -+ -+install-data-am: -+ -+install-dvi: install-dvi-am -+ -+install-dvi-am: -+ -+install-exec-am: install-binPROGRAMS -+ -+install-html: install-html-am -+ -+install-html-am: -+ -+install-info: install-info-am -+ -+install-info-am: -+ -+install-man: -+ -+install-pdf: install-pdf-am -+ -+install-pdf-am: -+ -+install-ps: install-ps-am -+ -+install-ps-am: -+ -+installcheck-am: -+ -+maintainer-clean: maintainer-clean-am -+ -rm -rf ./$(DEPDIR) -+ -rm -f Makefile -+maintainer-clean-am: distclean-am maintainer-clean-generic -+ -+mostlyclean: mostlyclean-am -+ -+mostlyclean-am: mostlyclean-compile mostlyclean-generic \ -+ mostlyclean-libtool -+ -+pdf: pdf-am -+ -+pdf-am: -+ -+ps: ps-am -+ -+ps-am: -+ -+uninstall-am: uninstall-binPROGRAMS -+ -+.MAKE: install-am install-strip -+ -+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ -+ clean-binPROGRAMS clean-generic clean-libtool cscopelist-am \ -+ ctags ctags-am distclean distclean-compile distclean-generic \ -+ distclean-libtool distclean-tags distdir dvi dvi-am html \ -+ html-am info info-am install install-am install-binPROGRAMS \ -+ install-data install-data-am install-dvi install-dvi-am \ -+ install-exec install-exec-am install-html install-html-am \ -+ install-info install-info-am install-man install-pdf \ -+ install-pdf-am install-ps install-ps-am install-strip \ -+ installcheck installcheck-am installdirs maintainer-clean \ -+ maintainer-clean-generic mostlyclean mostlyclean-compile \ -+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ -+ tags tags-am uninstall uninstall-am uninstall-binPROGRAMS -+ -+.PRECIOUS: Makefile -+ -+ -+# Tell versions [3.59,3.63) of GNU make to not export all variables. -+# Otherwise a system limit (for SysV at least) may be exceeded. -+.NOEXPORT: -diff --git a/server/README.md b/server/README.md -new file mode 100644 -index 0000000..ef6a20e ---- /dev/null -+++ b/server/README.md -@@ -0,0 +1,3 @@ -+# server -+ -+`ss-server` and `ss-check` from https://github.com/ywb94/shadowsocks-libev -diff --git a/server/acl.c b/server/acl.c -new file mode 100644 -index 0000000..60d4b72 ---- /dev/null -+++ b/server/acl.c -@@ -0,0 +1,597 @@ -+/* -+ * acl.c - Manage the ACL (Access Control List) -+ * -+ * Copyright (C) 2013 - 2016, Max Lv -+ * -+ * This file is part of the shadowsocks-libev. -+ * -+ * shadowsocks-libev is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * shadowsocks-libev 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 General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with shadowsocks-libev; see the file COPYING. If not, see -+ * . -+ */ -+ -+#include -+#include -+ -+#include "rule.h" -+#include "utils.h" -+#include "cache.h" -+#include "acl.h" -+ -+static struct ip_set white_list_ipv4; -+static struct ip_set white_list_ipv6; -+ -+static struct ip_set black_list_ipv4; -+static struct ip_set black_list_ipv6; -+ -+static struct cork_dllist black_list_rules; -+static struct cork_dllist white_list_rules; -+ -+static int acl_mode = BLACK_LIST; -+ -+static struct cache *block_list; -+ -+static struct ip_set outbound_block_list_ipv4; -+static struct ip_set outbound_block_list_ipv6; -+static struct cork_dllist outbound_block_list_rules; -+ -+#ifdef __linux__ -+ -+#include -+#include -+ -+#define NO_FIREWALL_MODE 0 -+#define IPTABLES_MODE 1 -+#define FIREWALLD_MODE 2 -+ -+static FILE *shell_stdin; -+static int mode = NO_FIREWALL_MODE; -+ -+static char chain_name[64]; -+static char *iptables_init_chain = -+ "iptables -N %s; iptables -F %s; iptables -A OUTPUT -p tcp --tcp-flags RST RST -j %s"; -+static char *iptables_remove_chain = -+ "iptables -D OUTPUT -p tcp --tcp-flags RST RST -j %s; iptables -F %s; iptables -X %s"; -+static char *iptables_add_rule = "iptables -A %s -d %s -j DROP"; -+static char *iptables_remove_rule = "iptables -D %s -d %s -j DROP"; -+ -+static char *ip6tables_init_chain = -+ "ip6tables -N %s; ip6tables -F %s; ip6tables -A OUTPUT -p tcp --tcp-flags RST RST -j %s"; -+static char *ip6tables_remove_chain = -+ "ip6tables -D OUTPUT -p tcp --tcp-flags RST RST -j %s; ip6tables -F %s; ip6tables -X %s"; -+static char *ip6tables_add_rule = "ip6tables -A %s -d %s -j DROP"; -+static char *ip6tables_remove_rule = "ip6tables -D %s -d %s -j DROP"; -+ -+static char *firewalld_init_chain = -+ "firewall-cmd --direct --add-chain ipv4 filter %s; \ -+ firewall-cmd --direct --passthrough ipv4 -F %s; \ -+ firewall-cmd --direct --passthrough ipv4 -A OUTPUT -p tcp --tcp-flags RST RST -j %s"; -+static char *firewalld_remove_chain = -+ "firewall-cmd --direct --passthrough ipv4 -D OUTPUT -p tcp --tcp-flags RST RST -j %s; \ -+ firewall-cmd --direct --passthrough ipv4 -F %s; \ -+ firewall-cmd --direct --remove-chain ipv4 filter %s"; -+static char *firewalld_add_rule = "firewall-cmd --direct --passthrough ipv4 -A %s -d %s -j DROP"; -+static char *firewalld_remove_rule = "firewall-cmd --direct --passthrough ipv4 -D %s -d %s -j DROP"; -+ -+static char *firewalld6_init_chain = -+ "firewall-cmd --direct --add-chain ipv6 filter %s; \ -+ firewall-cmd --direct --passthrough ipv6 -F %s; \ -+ firewall-cmd --direct --passthrough ipv6 -A OUTPUT -p tcp --tcp-flags RST RST -j %s"; -+static char *firewalld6_remove_chain = -+ "firewall-cmd --direct --passthrough ipv6 -D OUTPUT -p tcp --tcp-flags RST RST -j %s; \ -+ firewall-cmd --direct --passthrough ipv6 -F %s; \ -+ firewall-cmd --direct --remove-chain ipv6 filter %s"; -+static char *firewalld6_add_rule = "firewall-cmd --direct --passthrough ipv6 -A %s -d %s -j DROP"; -+static char *firewalld6_remove_rule = "firewall-cmd --direct --passthrough ipv6 -D %s -d %s -j DROP"; -+ -+static int -+run_cmd(const char *cmd) -+{ -+ int ret = 0; -+ char cmdstring[256]; -+ -+ sprintf(cmdstring, "%s\n", cmd); -+ size_t len = strlen(cmdstring); -+ -+ if (shell_stdin != NULL) { -+ ret = fwrite(cmdstring, 1, len, shell_stdin); -+ fflush(shell_stdin); -+ } -+ -+ return ret == len; -+} -+ -+static int -+init_firewall() -+{ -+ int ret = 0; -+ char cli[256]; -+ FILE *fp; -+ -+ if (getuid() != 0) -+ return -1; -+ -+ sprintf(cli, "firewall-cmd --version 2>&1"); -+ fp = popen(cli, "r"); -+ -+ if (fp == NULL) -+ return -1; -+ -+ if (pclose(fp) == 0) { -+ mode = FIREWALLD_MODE; -+ } else { -+ /* Check whether we have permission to operate iptables. -+ * Note that checking `iptables --version` is insufficient: -+ * eg, running within a child user namespace. -+ */ -+ sprintf(cli, "iptables -L 2>&1"); -+ fp = popen(cli, "r"); -+ if (fp == NULL) -+ return -1; -+ if (pclose(fp) == 0) -+ mode = IPTABLES_MODE; -+ } -+ -+ sprintf(chain_name, "SHADOWSOCKS_LIBEV_%d", getpid()); -+ -+ if (mode == FIREWALLD_MODE) { -+ sprintf(cli, firewalld6_init_chain, chain_name, chain_name, chain_name); -+ ret |= system(cli); -+ sprintf(cli, firewalld_init_chain, chain_name, chain_name, chain_name); -+ ret |= system(cli); -+ } else if (mode == IPTABLES_MODE) { -+ sprintf(cli, ip6tables_init_chain, chain_name, chain_name, chain_name); -+ ret |= system(cli); -+ sprintf(cli, iptables_init_chain, chain_name, chain_name, chain_name); -+ ret |= system(cli); -+ } -+ -+ shell_stdin = popen("/bin/sh", "w"); -+ -+ return ret; -+} -+ -+static int -+reset_firewall() -+{ -+ int ret = 0; -+ char cli[256]; -+ -+ if (getuid() != 0) -+ return -1; -+ -+ if (mode == IPTABLES_MODE) { -+ sprintf(cli, ip6tables_remove_chain, chain_name, chain_name, chain_name); -+ ret |= system(cli); -+ sprintf(cli, iptables_remove_chain, chain_name, chain_name, chain_name); -+ ret |= system(cli); -+ } else if (mode == FIREWALLD_MODE) { -+ sprintf(cli, firewalld6_remove_chain, chain_name, chain_name, chain_name); -+ ret |= system(cli); -+ sprintf(cli, firewalld_remove_chain, chain_name, chain_name, chain_name); -+ ret |= system(cli); -+ } -+ -+ if (shell_stdin != NULL) { -+ run_cmd("exit 0"); -+ pclose(shell_stdin); -+ } -+ -+ return ret; -+} -+ -+static int -+set_firewall_rule(char *addr, int add) -+{ -+ char cli[256]; -+ struct cork_ip ip; -+ -+ if (getuid() != 0) -+ return -1; -+ -+ if (cork_ip_init(&ip, addr)) -+ return -1; -+ -+ if (add) { -+ if (mode == IPTABLES_MODE) -+ sprintf(cli, ip.version == 4 ? iptables_add_rule : ip6tables_add_rule, -+ chain_name, addr); -+ else if (mode == FIREWALLD_MODE) -+ sprintf(cli, ip.version == 4 ? firewalld_add_rule : firewalld6_add_rule, -+ chain_name, addr); -+ return run_cmd(cli); -+ } else { -+ if (mode == IPTABLES_MODE) -+ sprintf(cli, ip.version == 4 ? iptables_remove_rule : ip6tables_remove_rule, -+ chain_name, addr); -+ else if (mode == FIREWALLD_MODE) -+ sprintf(cli, ip.version == 4 ? firewalld_remove_rule : firewalld6_remove_rule, -+ chain_name, addr); -+ return run_cmd(cli); -+ } -+ -+ return 0; -+} -+ -+static void -+free_firewall_rule(void *key, void *element) -+{ -+ if (key == NULL) -+ return; -+ char *addr = (char *)key; -+ set_firewall_rule(addr, 0); -+ ss_free(element); -+} -+ -+#endif -+ -+void -+init_block_list(int firewall) -+{ -+ // Initialize cache -+#ifdef __linux__ -+ if (firewall) -+ init_firewall(); -+ else -+ mode = NO_FIREWALL_MODE; -+ cache_create(&block_list, 256, free_firewall_rule); -+#else -+ cache_create(&block_list, 256, NULL); -+#endif -+} -+ -+void -+free_block_list() -+{ -+#ifdef __linux__ -+ if (mode != NO_FIREWALL_MODE) -+ reset_firewall(); -+#endif -+ cache_clear(block_list, 0); // Remove all items -+} -+ -+int -+remove_from_block_list(char *addr) -+{ -+ size_t addr_len = strlen(addr); -+ return cache_remove(block_list, addr, addr_len); -+} -+ -+void -+clear_block_list() -+{ -+ cache_clear(block_list, 3600); // Clear items older than 1 hour -+} -+ -+int -+check_block_list(char *addr) -+{ -+ size_t addr_len = strlen(addr); -+ -+ if (cache_key_exist(block_list, addr, addr_len)) { -+ int *count = NULL; -+ cache_lookup(block_list, addr, addr_len, &count); -+ -+ if (count != NULL && *count > MAX_TRIES) -+ return 1; -+ } -+ -+ return 0; -+} -+ -+int -+update_block_list(char *addr, int err_level) -+{ -+ size_t addr_len = strlen(addr); -+ -+ if (cache_key_exist(block_list, addr, addr_len)) { -+ int *count = NULL; -+ cache_lookup(block_list, addr, addr_len, &count); -+ if (count != NULL) { -+ if (*count > MAX_TRIES) -+ return 1; -+ (*count) += err_level; -+ } -+ } else if (err_level > 0) { -+ int *count = (int *)ss_malloc(sizeof(int)); -+ *count = 1; -+ cache_insert(block_list, addr, addr_len, count); -+#ifdef __linux__ -+ if (mode != NO_FIREWALL_MODE) -+ set_firewall_rule(addr, 1); -+#endif -+ } -+ -+ return 0; -+} -+ -+static void -+parse_addr_cidr(const char *str, char *host, int *cidr) -+{ -+ int ret = -1, n = 0; -+ char *pch; -+ -+ pch = strchr(str, '/'); -+ while (pch != NULL) { -+ n++; -+ ret = pch - str; -+ pch = strchr(pch + 1, '/'); -+ } -+ if (ret == -1) { -+ strcpy(host, str); -+ *cidr = -1; -+ } else { -+ memcpy(host, str, ret); -+ host[ret] = '\0'; -+ *cidr = atoi(str + ret + 1); -+ } -+} -+ -+char * -+trimwhitespace(char *str) -+{ -+ char *end; -+ -+ // Trim leading space -+ while (isspace(*str)) -+ str++; -+ -+ if (*str == 0) // All spaces? -+ return str; -+ -+ // Trim trailing space -+ end = str + strlen(str) - 1; -+ while (end > str && isspace(*end)) -+ end--; -+ -+ // Write new null terminator -+ *(end + 1) = 0; -+ -+ return str; -+} -+ -+int -+init_acl(const char *path) -+{ -+ // initialize ipset -+ ipset_init_library(); -+ -+ ipset_init(&white_list_ipv4); -+ ipset_init(&white_list_ipv6); -+ ipset_init(&black_list_ipv4); -+ ipset_init(&black_list_ipv6); -+ ipset_init(&outbound_block_list_ipv4); -+ ipset_init(&outbound_block_list_ipv6); -+ -+ cork_dllist_init(&black_list_rules); -+ cork_dllist_init(&white_list_rules); -+ cork_dllist_init(&outbound_block_list_rules); -+ -+ struct ip_set *list_ipv4 = &black_list_ipv4; -+ struct ip_set *list_ipv6 = &black_list_ipv6; -+ struct cork_dllist *rules = &black_list_rules; -+ -+ FILE *f = fopen(path, "r"); -+ if (f == NULL) { -+ LOGE("Invalid acl path."); -+ return -1; -+ } -+ -+ char buf[257]; -+ while (!feof(f)) -+ if (fgets(buf, 256, f)) { -+ // Trim the newline -+ int len = strlen(buf); -+ if (len > 0 && buf[len - 1] == '\n') { -+ buf[len - 1] = '\0'; -+ } -+ -+ char *line = trimwhitespace(buf); -+ -+ // Skip comments -+ if (line[0] == '#') { -+ continue; -+ } -+ -+ if (strlen(line) == 0) { -+ continue; -+ } -+ -+ if (strcmp(line, "[outbound_block_list]") == 0) { -+ list_ipv4 = &outbound_block_list_ipv4; -+ list_ipv6 = &outbound_block_list_ipv6; -+ rules = &outbound_block_list_rules; -+ continue; -+ } else if (strcmp(line, "[black_list]") == 0 -+ || strcmp(line, "[bypass_list]") == 0) { -+ list_ipv4 = &black_list_ipv4; -+ list_ipv6 = &black_list_ipv6; -+ rules = &black_list_rules; -+ continue; -+ } else if (strcmp(line, "[white_list]") == 0 -+ || strcmp(line, "[proxy_list]") == 0) { -+ list_ipv4 = &white_list_ipv4; -+ list_ipv6 = &white_list_ipv6; -+ rules = &white_list_rules; -+ continue; -+ } else if (strcmp(line, "[reject_all]") == 0 -+ || strcmp(line, "[bypass_all]") == 0) { -+ acl_mode = WHITE_LIST; -+ continue; -+ } else if (strcmp(line, "[accept_all]") == 0 -+ || strcmp(line, "[proxy_all]") == 0) { -+ acl_mode = BLACK_LIST; -+ continue; -+ } -+ -+ char host[257]; -+ int cidr; -+ parse_addr_cidr(line, host, &cidr); -+ -+ struct cork_ip addr; -+ int err = cork_ip_init(&addr, host); -+ if (!err) { -+ if (addr.version == 4) { -+ if (cidr >= 0) { -+ ipset_ipv4_add_network(list_ipv4, &(addr.ip.v4), cidr); -+ } else { -+ ipset_ipv4_add(list_ipv4, &(addr.ip.v4)); -+ } -+ } else if (addr.version == 6) { -+ if (cidr >= 0) { -+ ipset_ipv6_add_network(list_ipv6, &(addr.ip.v6), cidr); -+ } else { -+ ipset_ipv6_add(list_ipv6, &(addr.ip.v6)); -+ } -+ } -+ } else { -+ rule_t *rule = new_rule(); -+ accept_rule_arg(rule, line); -+ init_rule(rule); -+ add_rule(rules, rule); -+ } -+ } -+ -+ fclose(f); -+ -+ return 0; -+} -+ -+void -+free_rules(struct cork_dllist *rules) -+{ -+ struct cork_dllist_item *iter; -+ while ((iter = cork_dllist_head(rules)) != NULL) { -+ rule_t *rule = cork_container_of(iter, rule_t, entries); -+ remove_rule(rule); -+ } -+} -+ -+void -+free_acl(void) -+{ -+ ipset_done(&black_list_ipv4); -+ ipset_done(&black_list_ipv6); -+ ipset_done(&white_list_ipv4); -+ ipset_done(&white_list_ipv6); -+ -+ free_rules(&black_list_rules); -+ free_rules(&white_list_rules); -+} -+ -+int -+get_acl_mode(void) -+{ -+ return acl_mode; -+} -+ -+/* -+ * Return 0, if not match. -+ * Return 1, if match black list. -+ * Return -1, if match white list. -+ */ -+int -+acl_match_host(const char *host) -+{ -+ struct cork_ip addr; -+ int ret = 0; -+ int err = cork_ip_init(&addr, host); -+ -+ if (err) { -+ int host_len = strlen(host); -+ if (lookup_rule(&black_list_rules, host, host_len) != NULL) -+ ret = 1; -+ else if (lookup_rule(&white_list_rules, host, host_len) != NULL) -+ ret = -1; -+ return ret; -+ } -+ -+ if (addr.version == 4) { -+ if (ipset_contains_ipv4(&black_list_ipv4, &(addr.ip.v4))) -+ ret = 1; -+ else if (ipset_contains_ipv4(&white_list_ipv4, &(addr.ip.v4))) -+ ret = -1; -+ } else if (addr.version == 6) { -+ if (ipset_contains_ipv6(&black_list_ipv6, &(addr.ip.v6))) -+ ret = 1; -+ else if (ipset_contains_ipv6(&white_list_ipv6, &(addr.ip.v6))) -+ ret = -1; -+ } -+ -+ return ret; -+} -+ -+int -+acl_add_ip(const char *ip) -+{ -+ struct cork_ip addr; -+ int err = cork_ip_init(&addr, ip); -+ if (err) { -+ return -1; -+ } -+ -+ if (addr.version == 4) { -+ ipset_ipv4_add(&black_list_ipv4, &(addr.ip.v4)); -+ } else if (addr.version == 6) { -+ ipset_ipv6_add(&black_list_ipv6, &(addr.ip.v6)); -+ } -+ -+ return 0; -+} -+ -+int -+acl_remove_ip(const char *ip) -+{ -+ struct cork_ip addr; -+ int err = cork_ip_init(&addr, ip); -+ if (err) { -+ return -1; -+ } -+ -+ if (addr.version == 4) { -+ ipset_ipv4_remove(&black_list_ipv4, &(addr.ip.v4)); -+ } else if (addr.version == 6) { -+ ipset_ipv6_remove(&black_list_ipv6, &(addr.ip.v6)); -+ } -+ -+ return 0; -+} -+ -+/* -+ * Return 0, if not match. -+ * Return 1, if match black list. -+ */ -+int -+outbound_block_match_host(const char *host) -+{ -+ struct cork_ip addr; -+ int ret = 0; -+ int err = cork_ip_init(&addr, host); -+ -+ if (err) { -+ int host_len = strlen(host); -+ if (lookup_rule(&outbound_block_list_rules, host, host_len) != NULL) -+ ret = 1; -+ return ret; -+ } -+ -+ if (addr.version == 4) { -+ if (ipset_contains_ipv4(&outbound_block_list_ipv4, &(addr.ip.v4))) -+ ret = 1; -+ } else if (addr.version == 6) { -+ if (ipset_contains_ipv6(&outbound_block_list_ipv6, &(addr.ip.v6))) -+ ret = 1; -+ } -+ -+ return ret; -+} -diff --git a/server/acl.h b/server/acl.h -new file mode 100644 -index 0000000..d6f18b8 ---- /dev/null -+++ b/server/acl.h -@@ -0,0 +1,53 @@ -+/* -+ * acl.h - Define the ACL interface -+ * -+ * Copyright (C) 2013 - 2016, Max Lv -+ * -+ * This file is part of the shadowsocks-libev. -+ * -+ * shadowsocks-libev is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * shadowsocks-libev 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 General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with shadowsocks-libev; see the file COPYING. If not, see -+ * . -+ */ -+ -+#ifndef _ACL_H -+#define _ACL_H -+ -+#define BLACK_LIST 0 -+#define WHITE_LIST 1 -+ -+#define MAX_TRIES 64 -+#define MALICIOUS 8 -+#define SUSPICIOUS 4 -+#define BAD 2 -+#define MALFORMED 1 -+ -+int init_acl(const char *path); -+void free_acl(void); -+void clear_block_list(void); -+ -+int acl_match_host(const char *ip); -+int acl_add_ip(const char *ip); -+int acl_remove_ip(const char *ip); -+ -+int get_acl_mode(void); -+ -+void init_block_list(int firewall); -+void free_block_list(); -+int check_block_list(char *addr); -+int update_block_list(char *addr, int err_level); -+int remove_from_block_list(char *addr); -+ -+int outbound_block_match_host(const char *host); -+ -+#endif // _ACL_H -diff --git a/server/auth.c b/server/auth.c -new file mode 100644 -index 0000000..a36257a ---- /dev/null -+++ b/server/auth.c -@@ -0,0 +1,993 @@ -+ -+#include "auth.h" -+ -+static int auth_simple_pack_unit_size = 2000; -+typedef int (*hmac_with_key_func)(char *auth, char *msg, int msg_len, uint8_t *auth_key, int key_len); -+typedef int (*hash_func)(char *auth, char *msg, int msg_len); -+ -+typedef struct auth_simple_global_data { -+ uint8_t local_client_id[8]; -+ uint32_t connection_id; -+}auth_simple_global_data; -+ -+typedef struct auth_simple_local_data { -+ int has_sent_header; -+ char * recv_buffer; -+ int recv_buffer_size; -+ uint32_t recv_id; -+ uint32_t pack_id; -+ char * salt; -+ uint8_t * user_key; -+ char uid[4]; -+ int user_key_len; -+ hmac_with_key_func hmac; -+ hash_func hash; -+ int hash_len; -+}auth_simple_local_data; -+ -+void auth_simple_local_data_init(auth_simple_local_data* local) { -+ local->has_sent_header = 0; -+ local->recv_buffer = (char*)malloc(16384); -+ local->recv_buffer_size = 0; -+ local->recv_id = 1; -+ local->pack_id = 1; -+ local->salt = ""; -+ local->user_key = 0; -+ local->user_key_len = 0; -+ local->hmac = 0; -+ local->hash = 0; -+ local->hash_len = 0; -+ local->salt = ""; -+} -+ -+void * auth_simple_init_data() { -+ auth_simple_global_data *global = (auth_simple_global_data*)malloc(sizeof(auth_simple_global_data)); -+ rand_bytes(global->local_client_id, 8); -+ rand_bytes((uint8_t*)&global->connection_id, 4); -+ global->connection_id &= 0xFFFFFF; -+ return global; -+} -+ -+obfs * auth_simple_new_obfs() { -+ obfs * self = new_obfs(); -+ self->l_data = malloc(sizeof(auth_simple_local_data)); -+ auth_simple_local_data_init((auth_simple_local_data*)self->l_data); -+ return self; -+} -+ -+obfs * auth_aes128_md5_new_obfs() { -+ obfs * self = new_obfs(); -+ self->l_data = malloc(sizeof(auth_simple_local_data)); -+ auth_simple_local_data_init((auth_simple_local_data*)self->l_data); -+ ((auth_simple_local_data*)self->l_data)->hmac = ss_md5_hmac_with_key; -+ ((auth_simple_local_data*)self->l_data)->hash = ss_md5_hash_func; -+ ((auth_simple_local_data*)self->l_data)->hash_len = 16; -+ ((auth_simple_local_data*)self->l_data)->salt = "auth_aes128_md5"; -+ return self; -+} -+ -+obfs * auth_aes128_sha1_new_obfs() { -+ obfs * self = new_obfs(); -+ self->l_data = malloc(sizeof(auth_simple_local_data)); -+ auth_simple_local_data_init((auth_simple_local_data*)self->l_data); -+ ((auth_simple_local_data*)self->l_data)->hmac = ss_sha1_hmac_with_key; -+ ((auth_simple_local_data*)self->l_data)->hash = ss_sha1_hash_func; -+ ((auth_simple_local_data*)self->l_data)->hash_len = 20; -+ ((auth_simple_local_data*)self->l_data)->salt = "auth_aes128_sha1"; -+ return self; -+} -+ -+void auth_simple_dispose(obfs *self) { -+ auth_simple_local_data *local = (auth_simple_local_data*)self->l_data; -+ if (local->recv_buffer != NULL) { -+ free(local->recv_buffer); -+ local->recv_buffer = NULL; -+ } -+ if (local->user_key != NULL) { -+ free(local->user_key); -+ local->user_key = NULL; -+ } -+ free(local); -+ self->l_data = NULL; -+ dispose_obfs(self); -+} -+ -+int auth_simple_pack_data(char *data, int datalength, char *outdata) { -+ unsigned char rand_len = (xorshift128plus() & 0xF) + 1; -+ int out_size = rand_len + datalength + 6; -+ outdata[0] = out_size >> 8; -+ outdata[1] = out_size; -+ outdata[2] = rand_len; -+ memmove(outdata + rand_len + 2, data, datalength); -+ fillcrc32((unsigned char *)outdata, out_size); -+ return out_size; -+} -+ -+void memintcopy_lt(void *mem, uint32_t val) { -+ ((uint8_t *)mem)[0] = val; -+ ((uint8_t *)mem)[1] = val >> 8; -+ ((uint8_t *)mem)[2] = val >> 16; -+ ((uint8_t *)mem)[3] = val >> 24; -+} -+ -+int auth_simple_pack_auth_data(auth_simple_global_data *global, char *data, int datalength, char *outdata) { -+ unsigned char rand_len = (xorshift128plus() & 0xF) + 1; -+ int out_size = rand_len + datalength + 6 + 12; -+ outdata[0] = out_size >> 8; -+ outdata[1] = out_size; -+ outdata[2] = rand_len; -+ ++global->connection_id; -+ if (global->connection_id > 0xFF000000) { -+ rand_bytes(global->local_client_id, 8); -+ rand_bytes((uint8_t*)&global->connection_id, 4); -+ global->connection_id &= 0xFFFFFF; -+ } -+ time_t t = time(NULL); -+ memintcopy_lt(outdata + rand_len + 2, t); -+ memmove(outdata + rand_len + 2 + 4, global->local_client_id, 4); -+ memintcopy_lt(outdata + rand_len + 2 + 8, global->connection_id); -+ memmove(outdata + rand_len + 2 + 12, data, datalength); -+ fillcrc32((unsigned char *)outdata, out_size); -+ return out_size; -+} -+ -+int auth_simple_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) { -+ char *plaindata = *pplaindata; -+ auth_simple_local_data *local = (auth_simple_local_data*)self->l_data; -+ char * out_buffer = (char*)malloc(datalength * 2 + 64); -+ char * buffer = out_buffer; -+ char * data = plaindata; -+ int len = datalength; -+ int pack_len; -+ if (len > 0 && local->has_sent_header == 0) { -+ int head_size = get_head_size(plaindata, datalength, 30); -+ if (head_size > datalength) -+ head_size = datalength; -+ pack_len = auth_simple_pack_auth_data((auth_simple_global_data *)self->server.g_data, data, head_size, buffer); -+ buffer += pack_len; -+ data += head_size; -+ len -= head_size; -+ local->has_sent_header = 1; -+ } -+ while ( len > auth_simple_pack_unit_size ) { -+ pack_len = auth_simple_pack_data(data, auth_simple_pack_unit_size, buffer); -+ buffer += pack_len; -+ data += auth_simple_pack_unit_size; -+ len -= auth_simple_pack_unit_size; -+ } -+ if (len > 0) { -+ pack_len = auth_simple_pack_data(data, len, buffer); -+ buffer += pack_len; -+ } -+ len = buffer - out_buffer; -+ if (*capacity < len) { -+ *pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2); -+ plaindata = *pplaindata; -+ } -+ memmove(plaindata, out_buffer, len); -+ free(out_buffer); -+ return len; -+} -+ -+int auth_simple_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) { -+ char *plaindata = *pplaindata; -+ auth_simple_local_data *local = (auth_simple_local_data*)self->l_data; -+ uint8_t * recv_buffer = (uint8_t *)local->recv_buffer; -+ if (local->recv_buffer_size + datalength > 16384) -+ return -1; -+ memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength); -+ local->recv_buffer_size += datalength; -+ -+ char * out_buffer = (char*)malloc(local->recv_buffer_size); -+ char * buffer = out_buffer; -+ while (local->recv_buffer_size > 2) { -+ int length = ((int)recv_buffer[0] << 8) | recv_buffer[1]; -+ if (length >= 8192 || length < 7) { -+ free(out_buffer); -+ local->recv_buffer_size = 0; -+ return -1; -+ } -+ if (length > local->recv_buffer_size) -+ break; -+ -+ int crc = crc32((unsigned char*)recv_buffer, length); -+ if (crc != -1) { -+ free(out_buffer); -+ local->recv_buffer_size = 0; -+ return -1; -+ } -+ int data_size = length - recv_buffer[2] - 6; -+ memmove(buffer, recv_buffer + 2 + recv_buffer[2], data_size); -+ buffer += data_size; -+ memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length); -+ } -+ int len = buffer - out_buffer; -+ if (*capacity < len) { -+ *pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2); -+ plaindata = *pplaindata; -+ } -+ memmove(plaindata, out_buffer, len); -+ free(out_buffer); -+ return len; -+} -+ -+ -+int auth_sha1_pack_data(char *data, int datalength, char *outdata) { -+ unsigned char rand_len = (xorshift128plus() & 0xF) + 1; -+ int out_size = rand_len + datalength + 6; -+ outdata[0] = out_size >> 8; -+ outdata[1] = out_size; -+ outdata[2] = rand_len; -+ memmove(outdata + rand_len + 2, data, datalength); -+ filladler32((unsigned char *)outdata, out_size); -+ return out_size; -+} -+ -+int auth_sha1_pack_auth_data(auth_simple_global_data *global, server_info *server, char *data, int datalength, char *outdata) { -+ unsigned char rand_len = (xorshift128plus() & 0x7F) + 1; -+ int data_offset = rand_len + 4 + 2; -+ int out_size = data_offset + datalength + 12 + OBFS_HMAC_SHA1_LEN; -+ fillcrc32to((unsigned char *)server->key, server->key_len, (unsigned char *)outdata); -+ outdata[4] = out_size >> 8; -+ outdata[5] = out_size; -+ outdata[6] = rand_len; -+ ++global->connection_id; -+ if (global->connection_id > 0xFF000000) { -+ rand_bytes(global->local_client_id, 8); -+ rand_bytes((uint8_t*)&global->connection_id, 4); -+ global->connection_id &= 0xFFFFFF; -+ } -+ time_t t = time(NULL); -+ memintcopy_lt(outdata + data_offset, t); -+ memmove(outdata + data_offset + 4, global->local_client_id, 4); -+ memintcopy_lt(outdata + data_offset + 8, global->connection_id); -+ memmove(outdata + data_offset + 12, data, datalength); -+ char hash[ONETIMEAUTH_BYTES * 2]; -+ ss_sha1_hmac(hash, outdata, out_size - OBFS_HMAC_SHA1_LEN, server->iv); -+ memcpy(outdata + out_size - OBFS_HMAC_SHA1_LEN, hash, OBFS_HMAC_SHA1_LEN); -+ return out_size; -+} -+ -+int auth_sha1_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) { -+ char *plaindata = *pplaindata; -+ auth_simple_local_data *local = (auth_simple_local_data*)self->l_data; -+ char * out_buffer = (char*)malloc(datalength * 2 + 256); -+ char * buffer = out_buffer; -+ char * data = plaindata; -+ int len = datalength; -+ int pack_len; -+ if (len > 0 && local->has_sent_header == 0) { -+ int head_size = get_head_size(plaindata, datalength, 30); -+ if (head_size > datalength) -+ head_size = datalength; -+ pack_len = auth_sha1_pack_auth_data((auth_simple_global_data *)self->server.g_data, &self->server, data, head_size, buffer); -+ buffer += pack_len; -+ data += head_size; -+ len -= head_size; -+ local->has_sent_header = 1; -+ } -+ while ( len > auth_simple_pack_unit_size ) { -+ pack_len = auth_sha1_pack_data(data, auth_simple_pack_unit_size, buffer); -+ buffer += pack_len; -+ data += auth_simple_pack_unit_size; -+ len -= auth_simple_pack_unit_size; -+ } -+ if (len > 0) { -+ pack_len = auth_sha1_pack_data(data, len, buffer); -+ buffer += pack_len; -+ } -+ len = buffer - out_buffer; -+ if (*capacity < len) { -+ *pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2); -+ plaindata = *pplaindata; -+ } -+ memmove(plaindata, out_buffer, len); -+ free(out_buffer); -+ return len; -+} -+ -+int auth_sha1_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) { -+ char *plaindata = *pplaindata; -+ auth_simple_local_data *local = (auth_simple_local_data*)self->l_data; -+ uint8_t * recv_buffer = (uint8_t *)local->recv_buffer; -+ if (local->recv_buffer_size + datalength > 16384) -+ return -1; -+ memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength); -+ local->recv_buffer_size += datalength; -+ -+ char * out_buffer = (char*)malloc(local->recv_buffer_size); -+ char * buffer = out_buffer; -+ while (local->recv_buffer_size > 2) { -+ int length = ((int)recv_buffer[0] << 8) | recv_buffer[1]; -+ if (length >= 8192 || length < 7) { -+ free(out_buffer); -+ local->recv_buffer_size = 0; -+ return -1; -+ } -+ if (length > local->recv_buffer_size) -+ break; -+ -+ if (checkadler32((unsigned char*)recv_buffer, length) == 0) { -+ free(out_buffer); -+ local->recv_buffer_size = 0; -+ return -1; -+ } -+ int pos = recv_buffer[2] + 2; -+ int data_size = length - pos - 4; -+ memmove(buffer, recv_buffer + pos, data_size); -+ buffer += data_size; -+ memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length); -+ } -+ int len = buffer - out_buffer; -+ if (*capacity < len) { -+ *pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2); -+ plaindata = *pplaindata; -+ } -+ memmove(plaindata, out_buffer, len); -+ free(out_buffer); -+ return len; -+} -+ -+int auth_sha1_v2_pack_data(char *data, int datalength, char *outdata) { -+ unsigned int rand_len = (datalength > 1300 ? 0 : datalength > 400 ? (xorshift128plus() & 0x7F) : (xorshift128plus() & 0x3FF)) + 1; -+ int out_size = rand_len + datalength + 6; -+ outdata[0] = out_size >> 8; -+ outdata[1] = out_size; -+ if (rand_len < 128) -+ { -+ outdata[2] = rand_len; -+ } -+ else -+ { -+ outdata[2] = 0xFF; -+ outdata[3] = rand_len >> 8; -+ outdata[4] = rand_len; -+ } -+ memmove(outdata + rand_len + 2, data, datalength); -+ filladler32((unsigned char *)outdata, out_size); -+ return out_size; -+} -+ -+int auth_sha1_v2_pack_auth_data(auth_simple_global_data *global, server_info *server, char *data, int datalength, char *outdata) { -+ unsigned int rand_len = (datalength > 1300 ? 0 : datalength > 400 ? (xorshift128plus() & 0x7F) : (xorshift128plus() & 0x3FF)) + 1; -+ int data_offset = rand_len + 4 + 2; -+ int out_size = data_offset + datalength + 12 + OBFS_HMAC_SHA1_LEN; -+ const char* salt = "auth_sha1_v2"; -+ int salt_len = strlen(salt); -+ unsigned char *crc_salt = (unsigned char*)malloc(salt_len + server->key_len); -+ memcpy(crc_salt, salt, salt_len); -+ memcpy(crc_salt + salt_len, server->key, server->key_len); -+ fillcrc32to(crc_salt, salt_len + server->key_len, (unsigned char *)outdata); -+ free(crc_salt); -+ outdata[4] = out_size >> 8; -+ outdata[5] = out_size; -+ if (rand_len < 128) -+ { -+ outdata[6] = rand_len; -+ } -+ else -+ { -+ outdata[6] = 0xFF; -+ outdata[7] = rand_len >> 8; -+ outdata[8] = rand_len; -+ } -+ ++global->connection_id; -+ if (global->connection_id > 0xFF000000) { -+ rand_bytes(global->local_client_id, 8); -+ rand_bytes((uint8_t*)&global->connection_id, 4); -+ global->connection_id &= 0xFFFFFF; -+ } -+ memmove(outdata + data_offset, global->local_client_id, 8); -+ memintcopy_lt(outdata + data_offset + 8, global->connection_id); -+ memmove(outdata + data_offset + 12, data, datalength); -+ char hash[ONETIMEAUTH_BYTES * 2]; -+ ss_sha1_hmac(hash, outdata, out_size - OBFS_HMAC_SHA1_LEN, server->iv); -+ memcpy(outdata + out_size - OBFS_HMAC_SHA1_LEN, hash, OBFS_HMAC_SHA1_LEN); -+ return out_size; -+} -+ -+int auth_sha1_v2_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) { -+ char *plaindata = *pplaindata; -+ auth_simple_local_data *local = (auth_simple_local_data*)self->l_data; -+ char * out_buffer = (char*)malloc(datalength * 2 + 4096); -+ char * buffer = out_buffer; -+ char * data = plaindata; -+ int len = datalength; -+ int pack_len; -+ if (len > 0 && local->has_sent_header == 0) { -+ int head_size = get_head_size(plaindata, datalength, 30); -+ if (head_size > datalength) -+ head_size = datalength; -+ pack_len = auth_sha1_v2_pack_auth_data((auth_simple_global_data *)self->server.g_data, &self->server, data, head_size, buffer); -+ buffer += pack_len; -+ data += head_size; -+ len -= head_size; -+ local->has_sent_header = 1; -+ } -+ while ( len > auth_simple_pack_unit_size ) { -+ pack_len = auth_sha1_v2_pack_data(data, auth_simple_pack_unit_size, buffer); -+ buffer += pack_len; -+ data += auth_simple_pack_unit_size; -+ len -= auth_simple_pack_unit_size; -+ } -+ if (len > 0) { -+ pack_len = auth_sha1_v2_pack_data(data, len, buffer); -+ buffer += pack_len; -+ } -+ len = buffer - out_buffer; -+ if (*capacity < len) { -+ *pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2); -+ plaindata = *pplaindata; -+ } -+ memmove(plaindata, out_buffer, len); -+ free(out_buffer); -+ return len; -+} -+ -+int auth_sha1_v2_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) { -+ char *plaindata = *pplaindata; -+ auth_simple_local_data *local = (auth_simple_local_data*)self->l_data; -+ uint8_t * recv_buffer = (uint8_t *)local->recv_buffer; -+ if (local->recv_buffer_size + datalength > 16384) -+ return -1; -+ memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength); -+ local->recv_buffer_size += datalength; -+ -+ char * out_buffer = (char*)malloc(local->recv_buffer_size); -+ char * buffer = out_buffer; -+ char error = 0; -+ while (local->recv_buffer_size > 2) { -+ int length = ((int)recv_buffer[0] << 8) | recv_buffer[1]; -+ if (length >= 8192 || length < 7) { -+ local->recv_buffer_size = 0; -+ error = 1; -+ break; -+ } -+ if (length > local->recv_buffer_size) -+ break; -+ -+ if (checkadler32((unsigned char*)recv_buffer, length) == 0) { -+ local->recv_buffer_size = 0; -+ error = 1; -+ break; -+ } -+ int pos = recv_buffer[2]; -+ if (pos < 255) -+ { -+ pos += 2; -+ } -+ else -+ { -+ pos = ((recv_buffer[3] << 8) | recv_buffer[4]) + 2; -+ } -+ int data_size = length - pos - 4; -+ memmove(buffer, recv_buffer + pos, data_size); -+ buffer += data_size; -+ memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length); -+ } -+ int len; -+ if (error == 0) { -+ len = buffer - out_buffer; -+ if (*capacity < len) { -+ *pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2); -+ plaindata = *pplaindata; -+ } -+ memmove(plaindata, out_buffer, len); -+ } else { -+ len = -1; -+ } -+ free(out_buffer); -+ return len; -+} -+ -+int auth_sha1_v4_pack_data(char *data, int datalength, char *outdata) { -+ unsigned int rand_len = (datalength > 1300 ? 0 : datalength > 400 ? (xorshift128plus() & 0x7F) : (xorshift128plus() & 0x3FF)) + 1; -+ int out_size = rand_len + datalength + 8; -+ outdata[0] = out_size >> 8; -+ outdata[1] = out_size; -+ uint32_t crc_val = crc32((unsigned char*)outdata, 2); -+ outdata[2] = crc_val; -+ outdata[3] = crc_val >> 8; -+ if (rand_len < 128) -+ { -+ outdata[4] = rand_len; -+ } -+ else -+ { -+ outdata[4] = 0xFF; -+ outdata[5] = rand_len >> 8; -+ outdata[6] = rand_len; -+ } -+ memmove(outdata + rand_len + 4, data, datalength); -+ filladler32((unsigned char *)outdata, out_size); -+ return out_size; -+} -+ -+int auth_sha1_v4_pack_auth_data(auth_simple_global_data *global, server_info *server, char *data, int datalength, char *outdata) { -+ unsigned int rand_len = (datalength > 1300 ? 0 : datalength > 400 ? (xorshift128plus() & 0x7F) : (xorshift128plus() & 0x3FF)) + 1; -+ int data_offset = rand_len + 4 + 2; -+ int out_size = data_offset + datalength + 12 + OBFS_HMAC_SHA1_LEN; -+ const char* salt = "auth_sha1_v4"; -+ int salt_len = strlen(salt); -+ unsigned char *crc_salt = (unsigned char*)malloc(salt_len + server->key_len + 2); -+ crc_salt[0] = outdata[0] = out_size >> 8; -+ crc_salt[1] = outdata[1] = out_size; -+ -+ memcpy(crc_salt + 2, salt, salt_len); -+ memcpy(crc_salt + salt_len + 2, server->key, server->key_len); -+ fillcrc32to(crc_salt, salt_len + server->key_len + 2, (unsigned char *)outdata + 2); -+ free(crc_salt); -+ if (rand_len < 128) -+ { -+ outdata[6] = rand_len; -+ } -+ else -+ { -+ outdata[6] = 0xFF; -+ outdata[7] = rand_len >> 8; -+ outdata[8] = rand_len; -+ } -+ ++global->connection_id; -+ if (global->connection_id > 0xFF000000) { -+ rand_bytes(global->local_client_id, 8); -+ rand_bytes((uint8_t*)&global->connection_id, 4); -+ global->connection_id &= 0xFFFFFF; -+ } -+ time_t t = time(NULL); -+ memintcopy_lt(outdata + data_offset, t); -+ memmove(outdata + data_offset + 4, global->local_client_id, 4); -+ memintcopy_lt(outdata + data_offset + 8, global->connection_id); -+ memmove(outdata + data_offset + 12, data, datalength); -+ char hash[ONETIMEAUTH_BYTES * 2]; -+ ss_sha1_hmac(hash, outdata, out_size - OBFS_HMAC_SHA1_LEN, server->iv); -+ memcpy(outdata + out_size - OBFS_HMAC_SHA1_LEN, hash, OBFS_HMAC_SHA1_LEN); -+ return out_size; -+} -+ -+int auth_sha1_v4_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) { -+ char *plaindata = *pplaindata; -+ auth_simple_local_data *local = (auth_simple_local_data*)self->l_data; -+ char * out_buffer = (char*)malloc(datalength * 2 + 4096); -+ char * buffer = out_buffer; -+ char * data = plaindata; -+ int len = datalength; -+ int pack_len; -+ if (len > 0 && local->has_sent_header == 0) { -+ int head_size = get_head_size(plaindata, datalength, 30); -+ if (head_size > datalength) -+ head_size = datalength; -+ pack_len = auth_sha1_v4_pack_auth_data((auth_simple_global_data *)self->server.g_data, &self->server, data, head_size, buffer); -+ buffer += pack_len; -+ data += head_size; -+ len -= head_size; -+ local->has_sent_header = 1; -+ } -+ while ( len > auth_simple_pack_unit_size ) { -+ pack_len = auth_sha1_v4_pack_data(data, auth_simple_pack_unit_size, buffer); -+ buffer += pack_len; -+ data += auth_simple_pack_unit_size; -+ len -= auth_simple_pack_unit_size; -+ } -+ if (len > 0) { -+ pack_len = auth_sha1_v4_pack_data(data, len, buffer); -+ buffer += pack_len; -+ } -+ len = buffer - out_buffer; -+ if (*capacity < len) { -+ *pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2); -+ plaindata = *pplaindata; -+ } -+ memmove(plaindata, out_buffer, len); -+ free(out_buffer); -+ return len; -+} -+ -+int auth_sha1_v4_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) { -+ char *plaindata = *pplaindata; -+ auth_simple_local_data *local = (auth_simple_local_data*)self->l_data; -+ uint8_t * recv_buffer = (uint8_t *)local->recv_buffer; -+ if (local->recv_buffer_size + datalength > 16384) -+ return -1; -+ memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength); -+ local->recv_buffer_size += datalength; -+ -+ char * out_buffer = (char*)malloc(local->recv_buffer_size); -+ char * buffer = out_buffer; -+ char error = 0; -+ while (local->recv_buffer_size > 4) { -+ uint32_t crc_val = crc32((unsigned char*)recv_buffer, 2); -+ if ((((uint32_t)recv_buffer[3] << 8) | recv_buffer[2]) != (crc_val & 0xffff)) { -+ local->recv_buffer_size = 0; -+ error = 1; -+ break; -+ } -+ int length = ((int)recv_buffer[0] << 8) | recv_buffer[1]; -+ if (length >= 8192 || length < 7) { -+ local->recv_buffer_size = 0; -+ error = 1; -+ break; -+ } -+ if (length > local->recv_buffer_size) -+ break; -+ -+ if (checkadler32((unsigned char*)recv_buffer, length) == 0) { -+ local->recv_buffer_size = 0; -+ error = 1; -+ break; -+ } -+ int pos = recv_buffer[4]; -+ if (pos < 255) -+ { -+ pos += 4; -+ } -+ else -+ { -+ pos = (((int)recv_buffer[5] << 8) | recv_buffer[6]) + 4; -+ } -+ int data_size = length - pos - 4; -+ memmove(buffer, recv_buffer + pos, data_size); -+ buffer += data_size; -+ memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length); -+ } -+ int len; -+ if (error == 0) { -+ len = buffer - out_buffer; -+ if (*capacity < len) { -+ *pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2); -+ plaindata = *pplaindata; -+ } -+ memmove(plaindata, out_buffer, len); -+ } else { -+ len = -1; -+ } -+ free(out_buffer); -+ return len; -+} -+ -+ -+int auth_aes128_sha1_pack_data(char *data, int datalength, char *outdata, auth_simple_local_data *local, server_info *server) { -+ unsigned int rand_len = (datalength > 1200 ? 0 : local->pack_id > 4 ? (xorshift128plus() & 0x20) : datalength > 900 ? (xorshift128plus() & 0x80) : (xorshift128plus() & 0x200)) + 1; -+ int out_size = rand_len + datalength + 8; -+ memcpy(outdata + rand_len + 4, data, datalength); -+ outdata[0] = out_size; -+ outdata[1] = out_size >> 8; -+ uint8_t key_len = local->user_key_len + 4; -+ uint8_t *key = (uint8_t*)malloc(key_len); -+ memcpy(key, local->user_key, local->user_key_len); -+ memintcopy_lt(key + key_len - 4, local->pack_id); -+ -+ { -+ uint8_t rnd_data[rand_len]; -+ rand_bytes(rnd_data, rand_len); -+ memcpy(outdata + 4, rnd_data, rand_len); -+ } -+ -+ { -+ char hash[20]; -+ local->hmac(hash, outdata, 2, key, key_len); -+ memcpy(outdata + 2, hash, 2); -+ } -+ -+ if (rand_len < 128) -+ { -+ outdata[4] = rand_len; -+ } -+ else -+ { -+ outdata[4] = 0xFF; -+ outdata[5] = rand_len; -+ outdata[6] = rand_len >> 8; -+ } -+ ++local->pack_id; -+ -+ { -+ char hash[20]; -+ local->hmac(hash, outdata, out_size - 4, key, key_len); -+ memcpy(outdata + out_size - 4, hash, 4); -+ } -+ free(key); -+ -+ return out_size; -+} -+ -+int auth_aes128_sha1_pack_auth_data(auth_simple_global_data *global, server_info *server, auth_simple_local_data *local, char *data, int datalength, char *outdata) { -+ unsigned int rand_len = (datalength > 400 ? (xorshift128plus() & 0x200) : (xorshift128plus() & 0x400)); -+ int data_offset = rand_len + 16 + 4 + 4 + 7; -+ int out_size = data_offset + datalength + 4; -+ -+ char encrypt[24]; -+ char encrypt_data[16]; -+ -+ uint8_t *key = (uint8_t*)malloc(server->iv_len + server->key_len); -+ uint8_t key_len = server->iv_len + server->key_len; -+ memcpy(key, server->iv, server->iv_len); -+ memcpy(key + server->iv_len, server->key, server->key_len); -+ -+ { -+ uint8_t rnd_data[rand_len]; -+ rand_bytes(rnd_data, rand_len); -+ memcpy(outdata + data_offset - rand_len, rnd_data, rand_len); -+ } -+ -+ ++global->connection_id; -+ if (global->connection_id > 0xFF000000) { -+ rand_bytes(global->local_client_id, 8); -+ rand_bytes((uint8_t*)&global->connection_id, 4); -+ global->connection_id &= 0xFFFFFF; -+ } -+ time_t t = time(NULL); -+ memintcopy_lt(encrypt, t); -+ memcpy(encrypt + 4, global->local_client_id, 4); -+ memintcopy_lt(encrypt + 8, global->connection_id); -+ encrypt[12] = out_size; -+ encrypt[13] = out_size >> 8; -+ encrypt[14] = rand_len; -+ encrypt[15] = rand_len >> 8; -+ -+ { -+ -+ if (local->user_key == NULL) { -+ if(server->param != NULL && server->param[0] != 0) { -+ char *param = server->param; -+ char *delim = strchr(param, ':'); -+ if(delim != NULL) { -+ char uid_str[16] = {}; -+ strncpy(uid_str, param, delim - param); -+ char key_str[128]; -+ strcpy(key_str, delim + 1); -+ long uid_long = strtol(uid_str, NULL, 10); -+ memintcopy_lt(local->uid, uid_long); -+ -+ char hash[21] = {0}; -+ local->hash(hash, key_str, strlen(key_str)); -+ -+ local->user_key_len = local->hash_len; -+ local->user_key = (uint8_t*)malloc(local->user_key_len); -+ memcpy(local->user_key, hash, local->hash_len); -+ } -+ } -+ if (local->user_key == NULL) { -+ rand_bytes((uint8_t *)local->uid, 4); -+ -+ local->user_key_len = server->key_len; -+ local->user_key = (uint8_t*)malloc(local->user_key_len); -+ memcpy(local->user_key, server->key, local->user_key_len); -+ } -+ } -+ -+ char encrypt_key_base64[256] = {0}; -+ unsigned char encrypt_key[local->user_key_len]; -+ memcpy(encrypt_key, local->user_key, local->user_key_len); -+ base64_encode(encrypt_key, local->user_key_len, encrypt_key_base64); -+ -+ int base64_len; -+ base64_len = (local->user_key_len + 2) / 3 * 4; -+ memcpy(encrypt_key_base64 + base64_len, local->salt, strlen(local->salt)); -+ -+ char enc_key[16]; -+ int enc_key_len = base64_len + strlen(local->salt); -+ bytes_to_key_with_size(encrypt_key_base64, enc_key_len, (uint8_t*)enc_key, 16); -+ ss_aes_128_cbc(encrypt, encrypt_data, enc_key); -+ memcpy(encrypt + 4, encrypt_data, 16); -+ memcpy(encrypt, local->uid, 4); -+ } -+ -+ { -+ char hash[20]; -+ local->hmac(hash, encrypt, 20, key, key_len); -+ memcpy(encrypt + 20, hash, 4); -+ } -+ -+ { -+ uint8_t rnd[1]; -+ rand_bytes(rnd, 1); -+ memcpy(outdata, rnd, 1); -+ char hash[20]; -+ local->hmac(hash, (char *)rnd, 1, key, key_len); -+ memcpy(outdata + 1, hash, 6); -+ } -+ -+ memcpy(outdata + 7, encrypt, 24); -+ memcpy(outdata + data_offset, data, datalength); -+ -+ { -+ char hash[20]; -+ local->hmac(hash, outdata, out_size - 4, local->user_key, local->user_key_len); -+ memmove(outdata + out_size - 4, hash, 4); -+ } -+ free(key); -+ -+ return out_size; -+} -+ -+int auth_aes128_sha1_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) { -+ char *plaindata = *pplaindata; -+ auth_simple_local_data *local = (auth_simple_local_data*)self->l_data; -+ char * out_buffer = (char*)malloc(datalength * 2 + 4096); -+ char * buffer = out_buffer; -+ char * data = plaindata; -+ int len = datalength; -+ int pack_len; -+ if (len > 0 && local->has_sent_header == 0) { -+ int head_size = 1200; -+ if (head_size > datalength) -+ head_size = datalength; -+ pack_len = auth_aes128_sha1_pack_auth_data((auth_simple_global_data *)self->server.g_data, &self->server, local, data, head_size, buffer); -+ buffer += pack_len; -+ data += head_size; -+ len -= head_size; -+ local->has_sent_header = 1; -+ } -+ while ( len > auth_simple_pack_unit_size ) { -+ pack_len = auth_aes128_sha1_pack_data(data, auth_simple_pack_unit_size, buffer, local, &self->server); -+ buffer += pack_len; -+ data += auth_simple_pack_unit_size; -+ len -= auth_simple_pack_unit_size; -+ } -+ if (len > 0) { -+ pack_len = auth_aes128_sha1_pack_data(data, len, buffer, local, &self->server); -+ buffer += pack_len; -+ } -+ len = buffer - out_buffer; -+ if (*capacity < len) { -+ *pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2); -+ plaindata = *pplaindata; -+ } -+ memmove(plaindata, out_buffer, len); -+ free(out_buffer); -+ return len; -+} -+ -+int auth_aes128_sha1_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) { -+ char *plaindata = *pplaindata; -+ auth_simple_local_data *local = (auth_simple_local_data*)self->l_data; -+ //server_info *server = (server_info*)&self->server; -+ uint8_t * recv_buffer = (uint8_t *)local->recv_buffer; -+ if (local->recv_buffer_size + datalength > 16384) -+ return -1; -+ memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength); -+ local->recv_buffer_size += datalength; -+ -+ int key_len = local->user_key_len + 4; -+ uint8_t *key = (uint8_t*)malloc(key_len); -+ memcpy(key, local->user_key, local->user_key_len); -+ -+ char * out_buffer = (char*)malloc(local->recv_buffer_size); -+ char * buffer = out_buffer; -+ char error = 0; -+ while (local->recv_buffer_size > 4) { -+ memintcopy_lt(key + key_len - 4, local->recv_id); -+ -+ { -+ char hash[20]; -+ local->hmac(hash, (char*)recv_buffer, 2, key, key_len); -+ -+ if (memcmp(hash, recv_buffer + 2, 2)) { -+ local->recv_buffer_size = 0; -+ error = 1; -+ break; -+ } -+ } -+ -+ int length = ((int)recv_buffer[1] << 8) + recv_buffer[0]; -+ if (length >= 8192 || length < 8) { -+ local->recv_buffer_size = 0; -+ error = 1; -+ break; -+ } -+ if (length > local->recv_buffer_size) -+ break; -+ -+ { -+ char hash[20]; -+ local->hmac(hash, (char *)recv_buffer, length - 4, key, key_len); -+ if (memcmp(hash, recv_buffer + length - 4, 4)) -+ { -+ local->recv_buffer_size = 0; -+ error = 1; -+ break; -+ } -+ } -+ -+ ++local->recv_id; -+ int pos = recv_buffer[4]; -+ if (pos < 255) -+ { -+ pos += 4; -+ } -+ else -+ { -+ pos = (((int)recv_buffer[6] << 8) | recv_buffer[5]) + 4; -+ } -+ int data_size = length - pos - 4; -+ memmove(buffer, recv_buffer + pos, data_size); -+ buffer += data_size; -+ memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length); -+ } -+ int len; -+ if (error == 0) { -+ len = buffer - out_buffer; -+ if (*capacity < len) { -+ *pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2); -+ plaindata = *pplaindata; -+ } -+ memmove(plaindata, out_buffer, len); -+ } else { -+ len = -1; -+ } -+ free(out_buffer); -+ free(key); -+ return len; -+} -+ -+int auth_aes128_sha1_client_udp_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) { -+ char *plaindata = *pplaindata; -+ auth_simple_local_data *local = (auth_simple_local_data*)self->l_data; -+ char * out_buffer = (char*)malloc(datalength + 8); -+ -+ if (local->user_key == NULL) { -+ if(self->server.param != NULL && self->server.param[0] != 0) { -+ char *param = self->server.param; -+ char *delim = strchr(param, ':'); -+ if(delim != NULL) { -+ char uid_str[16] = {}; -+ strncpy(uid_str, param, delim - param); -+ char key_str[128]; -+ strcpy(key_str, delim + 1); -+ long uid_long = strtol(uid_str, NULL, 10); -+ memintcopy_lt(local->uid, uid_long); -+ -+ char hash[21] = {0}; -+ local->hash(hash, key_str, strlen(key_str)); -+ -+ local->user_key_len = local->hash_len; -+ local->user_key = (uint8_t*)malloc(local->user_key_len); -+ memcpy(local->user_key, hash, local->hash_len); -+ } -+ } -+ if (local->user_key == NULL) { -+ rand_bytes((uint8_t *)local->uid, 4); -+ -+ local->user_key_len = self->server.key_len; -+ local->user_key = (uint8_t*)malloc(local->user_key_len); -+ memcpy(local->user_key, self->server.key, local->user_key_len); -+ } -+ } -+ -+ int outlength = datalength + 8; -+ memmove(out_buffer, plaindata, datalength); -+ memmove(out_buffer + datalength, local->uid, 4); -+ -+ { -+ char hash[20]; -+ local->hmac(hash, out_buffer, outlength - 4, local->user_key, local->user_key_len); -+ memmove(out_buffer + outlength - 4, hash, 4); -+ } -+ -+ if (*capacity < outlength) { -+ *pplaindata = (char*)realloc(*pplaindata, *capacity = outlength * 2); -+ plaindata = *pplaindata; -+ } -+ memmove(plaindata, out_buffer, outlength); -+ -+ free(out_buffer); -+ return outlength; -+} -+ -+int auth_aes128_sha1_client_udp_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) { -+ if (datalength <= 4) -+ return 0; -+ -+ char *plaindata = *pplaindata; -+ auth_simple_local_data *local = (auth_simple_local_data*)self->l_data; -+ -+ char hash[20]; -+ local->hmac(hash, plaindata, datalength - 4, self->server.key, self->server.key_len); -+ -+ if (memcmp(hash, plaindata + datalength - 4, 4)) -+ { -+ return 0; -+ } -+ -+ return datalength - 4; -+} -diff --git a/server/auth.h b/server/auth.h -new file mode 100644 -index 0000000..f7730df ---- /dev/null -+++ b/server/auth.h -@@ -0,0 +1,30 @@ -+/* -+ * auth.h - Define shadowsocksR server's buffers and callbacks -+ * -+ * Copyright (C) 2015 - 2016, Break Wa11 -+ */ -+ -+#ifndef _AUTH_H -+#define _AUTH_H -+ -+void * auth_simple_init_data(); -+obfs * auth_simple_new_obfs(); -+void auth_simple_dispose(obfs *self); -+ -+int auth_simple_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); -+int auth_simple_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); -+ -+ -+int auth_sha1_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); -+int auth_sha1_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); -+ -+int auth_sha1_v2_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); -+int auth_sha1_v2_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); -+ -+int auth_sha1_v4_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); -+int auth_sha1_v4_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); -+ -+int auth_aes128_sha1_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); -+int auth_aes128_sha1_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); -+ -+#endif // _AUTH_H -diff --git a/server/base64.c b/server/base64.c -new file mode 100644 -index 0000000..7cf9552 ---- /dev/null -+++ b/server/base64.c -@@ -0,0 +1,119 @@ -+#include "base64.h" -+ -+/* BASE 64 encode table */ -+static const char base64en[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -+ -+#define BASE64_PAD '=' -+ -+#define BASE64DE_FIRST '+' -+#define BASE64DE_LAST 'z' -+ -+/* ASCII order for BASE 64 decode, -1 in unused character */ -+static const signed char base64de[] = { -+ -1, -1, -1, -1, -1, -1, -1, -1, -+ -1, -1, -1, -1, -1, -1, -1, -1, -+ -1, -1, -1, -1, -1, -1, -1, -1, -+ -1, -1, -1, -1, -1, -1, -1, -1, -+ -1, -1, -1, -1, -1, -1, -1, -1, -+ /* '+', ',', '-', '.', '/', */ -+ -1, -1, -1, 62, -1, -1, -1, 63, -+ /* '0', '1', '2', '3', '4', '5', '6', '7', */ -+ 52, 53, 54, 55, 56, 57, 58, 59, -+ /* '8', '9', ':', ';', '<', '=', '>', '?', */ -+ 60, 61, -1, -1, -1, -1, -1, -1, -+ /* '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', */ -+ -1, 0, 1, 2, 3, 4, 5, 6, -+ /* 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', */ -+ 7, 8, 9, 10, 11, 12, 13, 14, -+ /* 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', */ -+ 15, 16, 17, 18, 19, 20, 21, 22, -+ /* 'X', 'Y', 'Z', '[', '\', ']', '^', '_', */ -+ 23, 24, 25, -1, -1, -1, -1, -1, -+ /* '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', */ -+ -1, 26, 27, 28, 29, 30, 31, 32, -+ /* 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', */ -+ 33, 34, 35, 36, 37, 38, 39, 40, -+ /* 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', */ -+ 41, 42, 43, 44, 45, 46, 47, 48, -+ /* 'x', 'y', 'z', */ -+ 49, 50, 51, -+}; -+ -+int -+base64_encode(const unsigned char *in, unsigned int inlen, char *out) -+{ -+ unsigned int i, j; -+ -+ for (i = j = 0; i < inlen; i++) { -+ int s = i % 3; /* from 6/gcd(6, 8) */ -+ -+ switch (s) { -+ case 0: -+ out[j++] = base64en[(in[i] >> 2) & 0x3F]; -+ continue; -+ case 1: -+ out[j++] = base64en[((in[i-1] & 0x3) << 4) + ((in[i] >> 4) & 0xF)]; -+ continue; -+ case 2: -+ out[j++] = base64en[((in[i-1] & 0xF) << 2) + ((in[i] >> 6) & 0x3)]; -+ out[j++] = base64en[in[i] & 0x3F]; -+ } -+ } -+ -+ /* move back */ -+ i -= 1; -+ -+ /* check the last and add padding */ -+ if ((i % 3) == 0) { -+ out[j++] = base64en[(in[i] & 0x3) << 4]; -+ out[j++] = BASE64_PAD; -+ out[j++] = BASE64_PAD; -+ } else if ((i % 3) == 1) { -+ out[j++] = base64en[(in[i] & 0xF) << 2]; -+ out[j++] = BASE64_PAD; -+ } -+ -+ return BASE64_OK; -+} -+ -+int -+base64_decode(const char *in, unsigned int inlen, unsigned char *out) -+{ -+ unsigned int i, j; -+ -+ for (i = j = 0; i < inlen; i++) { -+ int c; -+ int s = i % 4; /* from 8/gcd(6, 8) */ -+ -+ if (in[i] == '=') -+ return BASE64_OK; -+ -+ if (in[i] < BASE64DE_FIRST || in[i] > BASE64DE_LAST || -+ (c = base64de[(int)in[i]]) == -1) -+ return BASE64_INVALID; -+ -+ switch (s) { -+ case 0: -+ out[j] = ((unsigned int)c << 2) & 0xFF; -+ continue; -+ case 1: -+ out[j++] += ((unsigned int)c >> 4) & 0x3; -+ -+ /* if not last char with padding */ -+ if (i < (inlen - 3) || in[inlen - 2] != '=') -+ out[j] = ((unsigned int)c & 0xF) << 4; -+ continue; -+ case 2: -+ out[j++] += ((unsigned int)c >> 2) & 0xF; -+ -+ /* if not last char with padding */ -+ if (i < (inlen - 2) || in[inlen - 1] != '=') -+ out[j] = ((unsigned int)c & 0x3) << 6; -+ continue; -+ case 3: -+ out[j++] += (unsigned char)c; -+ } -+ } -+ -+ return BASE64_OK; -+} -diff --git a/server/base64.h b/server/base64.h -new file mode 100644 -index 0000000..6432ba3 ---- /dev/null -+++ b/server/base64.h -@@ -0,0 +1,16 @@ -+#ifndef __BASE64_H__ -+#define __BASE64_H__ -+ -+enum {BASE64_OK = 0, BASE64_INVALID}; -+ -+#define BASE64_ENCODE_OUT_SIZE(s) (((s) + 2) / 3 * 4) -+#define BASE64_DECODE_OUT_SIZE(s) (((s)) / 4 * 3) -+ -+int -+base64_encode(const unsigned char *in, unsigned int inlen, char *out); -+ -+int -+base64_decode(const char *in, unsigned int inlen, unsigned char *out); -+ -+ -+#endif /* __BASE64_H__ */ -diff --git a/server/cache.c b/server/cache.c -new file mode 100644 -index 0000000..c1a2995 ---- /dev/null -+++ b/server/cache.c -@@ -0,0 +1,308 @@ -+/* -+ * cache.c - Manage the connection cache for UDPRELAY -+ * -+ * Copyright (C) 2013 - 2016, Max Lv -+ * -+ * This file is part of the shadowsocks-libev. -+ * -+ * shadowsocks-libev is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * shadowsocks-libev 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 General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with shadowsocks-libev; see the file COPYING. If not, see -+ * . -+ */ -+ -+/* -+ * Original Author: Oliver Lorenz (ol), olli@olorenz.org, https://olorenz.org -+ * License: This is licensed under the same terms as uthash itself -+ */ -+ -+#include -+#include -+ -+#include "cache.h" -+#include "utils.h" -+ -+#ifdef __MINGW32__ -+#include "win32.h" -+#endif -+ -+/** Creates a new cache object -+ * -+ * @param dst -+ * Where the newly allocated cache object will be stored in -+ * -+ * @param capacity -+ * The maximum number of elements this cache object can hold -+ * -+ * @return EINVAL if dst is NULL, ENOMEM if malloc fails, 0 otherwise -+ */ -+int -+cache_create(struct cache **dst, const size_t capacity, -+ void (*free_cb)(void *key, void *element)) -+{ -+ struct cache *new = NULL; -+ -+ if (!dst) { -+ return EINVAL; -+ } -+ -+ if ((new = malloc(sizeof(*new))) == NULL) { -+ return ENOMEM; -+ } -+ -+ new->max_entries = capacity; -+ new->entries = NULL; -+ new->free_cb = free_cb; -+ *dst = new; -+ return 0; -+} -+ -+/** Frees an allocated cache object -+ * -+ * @param cache -+ * The cache object to free -+ * -+ * @param keep_data -+ * Whether to free contained data or just delete references to it -+ * -+ * @return EINVAL if cache is NULL, 0 otherwise -+ */ -+int -+cache_delete(struct cache *cache, int keep_data) -+{ -+ struct cache_entry *entry, *tmp; -+ -+ if (!cache) { -+ return EINVAL; -+ } -+ -+ if (keep_data) { -+ HASH_CLEAR(hh, cache->entries); -+ } else { -+ HASH_ITER(hh, cache->entries, entry, tmp){ -+ HASH_DEL(cache->entries, entry); -+ if (entry->data != NULL) { -+ if (cache->free_cb) { -+ cache->free_cb(entry->key, entry->data); -+ } else { -+ ss_free(entry->data); -+ } -+ } -+ ss_free(entry->key); -+ ss_free(entry); -+ } -+ } -+ -+ ss_free(cache); -+ return 0; -+} -+ -+/** Clear old cache object -+ * -+ * @param cache -+ * The cache object to clear -+ * -+ * @param age -+ * Clear only objects older than the age (sec) -+ * -+ * @return EINVAL if cache is NULL, 0 otherwise -+ */ -+int -+cache_clear(struct cache *cache, ev_tstamp age) -+{ -+ struct cache_entry *entry, *tmp; -+ -+ if (!cache) { -+ return EINVAL; -+ } -+ -+ ev_tstamp now = ev_time(); -+ -+ HASH_ITER(hh, cache->entries, entry, tmp){ -+ if (now - entry->ts > age) { -+ HASH_DEL(cache->entries, entry); -+ if (entry->data != NULL) { -+ if (cache->free_cb) { -+ cache->free_cb(entry->key, entry->data); -+ } else { -+ ss_free(entry->data); -+ } -+ } -+ ss_free(entry->key); -+ ss_free(entry); -+ } -+ } -+ -+ return 0; -+} -+ -+/** Removes a cache entry -+ * -+ * @param cache -+ * The cache object -+ * -+ * @param key -+ * The key of the entry to remove -+ * -+ * @param key_len -+ * The length of key -+ * -+ * @return EINVAL if cache is NULL, 0 otherwise -+ */ -+int -+cache_remove(struct cache *cache, char *key, size_t key_len) -+{ -+ struct cache_entry *tmp; -+ -+ if (!cache || !key) { -+ return EINVAL; -+ } -+ -+ HASH_FIND(hh, cache->entries, key, key_len, tmp); -+ -+ if (tmp) { -+ HASH_DEL(cache->entries, tmp); -+ if (tmp->data != NULL) { -+ if (cache->free_cb) { -+ cache->free_cb(tmp->key, tmp->data); -+ } else { -+ ss_free(tmp->data); -+ } -+ } -+ ss_free(tmp->key); -+ ss_free(tmp); -+ } -+ -+ return 0; -+} -+ -+/** Checks if a given key is in the cache -+ * -+ * @param cache -+ * The cache object -+ * -+ * @param key -+ * The key to look-up -+ * -+ * @param key_len -+ * The length of key -+ * -+ * @param result -+ * Where to store the result if key is found. -+ * -+ * A warning: Even though result is just a pointer, -+ * you have to call this function with a **ptr, -+ * otherwise this will blow up in your face. -+ * -+ * @return EINVAL if cache is NULL, 0 otherwise -+ */ -+int -+cache_lookup(struct cache *cache, char *key, size_t key_len, void *result) -+{ -+ struct cache_entry *tmp = NULL; -+ char **dirty_hack = result; -+ -+ if (!cache || !key || !result) { -+ return EINVAL; -+ } -+ -+ HASH_FIND(hh, cache->entries, key, key_len, tmp); -+ if (tmp) { -+ HASH_DELETE(hh, cache->entries, tmp); -+ tmp->ts = ev_time(); -+ HASH_ADD_KEYPTR(hh, cache->entries, tmp->key, key_len, tmp); -+ *dirty_hack = tmp->data; -+ } else { -+ *dirty_hack = result = NULL; -+ } -+ -+ return 0; -+} -+ -+int -+cache_key_exist(struct cache *cache, char *key, size_t key_len) -+{ -+ struct cache_entry *tmp = NULL; -+ -+ if (!cache || !key) { -+ return 0; -+ } -+ -+ HASH_FIND(hh, cache->entries, key, key_len, tmp); -+ if (tmp) { -+ HASH_DELETE(hh, cache->entries, tmp); -+ tmp->ts = ev_time(); -+ HASH_ADD_KEYPTR(hh, cache->entries, tmp->key, key_len, tmp); -+ return 1; -+ } else { -+ return 0; -+ } -+ -+ return 0; -+} -+ -+/** Inserts a given pair into the cache -+ * -+ * @param cache -+ * The cache object -+ * -+ * @param key -+ * The key that identifies -+ * -+ * @param key_len -+ * The length of key -+ * -+ * @param data -+ * Data associated with -+ * -+ * @return EINVAL if cache is NULL, ENOMEM if malloc fails, 0 otherwise -+ */ -+int -+cache_insert(struct cache *cache, char *key, size_t key_len, void *data) -+{ -+ struct cache_entry *entry = NULL; -+ struct cache_entry *tmp_entry = NULL; -+ -+ if (!cache) { -+ return EINVAL; -+ } -+ -+ if ((entry = malloc(sizeof(*entry))) == NULL) { -+ return ENOMEM; -+ } -+ -+ entry->key = ss_malloc(key_len + 1); -+ memcpy(entry->key, key, key_len); -+ entry->key[key_len] = 0; -+ -+ entry->data = data; -+ entry->ts = ev_time(); -+ HASH_ADD_KEYPTR(hh, cache->entries, entry->key, key_len, entry); -+ -+ if (HASH_COUNT(cache->entries) >= cache->max_entries) { -+ HASH_ITER(hh, cache->entries, entry, tmp_entry){ -+ HASH_DELETE(hh, cache->entries, entry); -+ if (entry->data != NULL) { -+ if (cache->free_cb) { -+ cache->free_cb(entry->key, entry->data); -+ } else { -+ ss_free(entry->data); -+ } -+ } -+ ss_free(entry->key); -+ ss_free(entry); -+ break; -+ } -+ } -+ -+ return 0; -+} -diff --git a/server/cache.h b/server/cache.h -new file mode 100644 -index 0000000..0ec98f5 ---- /dev/null -+++ b/server/cache.h -@@ -0,0 +1,62 @@ -+/* -+ * cache.h - Define the cache manager interface -+ * -+ * Copyright (C) 2013 - 2016, Max Lv -+ * -+ * This file is part of the shadowsocks-libev. -+ * -+ * shadowsocks-libev is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * shadowsocks-libev 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 General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with shadowsocks-libev; see the file COPYING. If not, see -+ * . -+ */ -+ -+/* -+ * Original Author: Oliver Lorenz (ol), olli@olorenz.org, https://olorenz.org -+ * License: This is licensed under the same terms as uthash itself -+ */ -+ -+#ifndef _CACHE_ -+#define _CACHE_ -+ -+#include "uthash.h" -+#include "ev.h" -+ -+/** -+ * A cache entry -+ */ -+struct cache_entry { -+ char *key; /** -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+//#define __DEBUG__ -+#ifdef __DEBUG__ -+#define DEBUG(format,...) printf("File: "__FILE__", Line: %05d: "format"/n", __LINE__, ##__VA_ARGS__) -+#else -+#define DEBUG(format,...) -+#endif -+ -+static sigjmp_buf jmpbuf; -+static void alarm_func() -+{ -+ siglongjmp(jmpbuf, 1); -+} -+ -+static struct hostent *timeGethostbyname(const char *domain, int timeout) -+{ -+ struct hostent *ipHostent = NULL; -+ signal(SIGALRM, alarm_func); -+ if(sigsetjmp(jmpbuf, 1) != 0) -+ { -+ alarm(0);//timout -+ signal(SIGALRM, SIG_IGN); -+ return NULL; -+ } -+ alarm(timeout);//setting alarm -+ ipHostent = gethostbyname(domain); -+ signal(SIGALRM, SIG_IGN); -+ return ipHostent; -+} -+ -+ -+#define MY_HTTP_DEFAULT_PORT 80 -+#define BUFFER_SIZE 1024 -+#define HTTP_POST "POST /%s HTTP/1.1\r\nHOST: %s:%d\r\nAccept: */*\r\n"\ -+ "Content-Type:application/x-www-form-urlencoded\r\nContent-Length: %d\r\n\r\n%s" -+#define HTTP_GET "GET /%s HTTP/1.1\r\nHOST: %s:%d\r\nAccept: */*\r\n\r\n" -+ -+static int http_parse_url(const char *url,char *host,char *file,int *port) -+{ -+ char *ptr1,*ptr2; -+ int len = 0; -+ if(!url || !host || !file || !port){ -+ return 1; -+ } -+ -+ ptr1 = (char *)url; -+ -+ if(!strncmp(ptr1,"http://",strlen("http://"))){ -+ ptr1 += strlen("http://"); -+ }else{ -+ return 1; -+ } -+ -+ ptr2 = strchr(ptr1,'/'); -+ if(ptr2){ -+ len = strlen(ptr1) - strlen(ptr2); -+ memcpy(host,ptr1,len); -+ host[len] = '\0'; -+ if(*(ptr2 + 1)){ -+ memcpy(file,ptr2 + 1,strlen(ptr2) - 1 ); -+ file[strlen(ptr2) - 1] = '\0'; -+ } -+ }else{ -+ memcpy(host,ptr1,strlen(ptr1)); -+ host[strlen(ptr1)] = '\0'; -+ } -+ //get host and ip -+ ptr1 = strchr(host,':'); -+ if(ptr1){ -+ *ptr1++ = '\0'; -+ *port = atoi(ptr1); -+ }else{ -+ *port = MY_HTTP_DEFAULT_PORT; -+ } -+ -+ return 0; -+} -+ -+ -+static int http_tcpclient_recv(int socket,char *lpbuff){ -+ int recvnum = 0; -+ -+ recvnum = recv(socket, lpbuff,BUFFER_SIZE*4,0); -+ -+ return recvnum; -+} -+ -+static int http_tcpclient_send(int socket,char *buff,int size){ -+ int sent=0,tmpres=0; -+ -+ while(sent < size){ -+ tmpres = send(socket,buff+sent,size-sent,0); -+ if(tmpres == -1){ -+ return 1; -+ } -+ sent += tmpres; -+ } -+ return sent; -+} -+ -+ -+ -+ -+ -+int http_get(const char *url,int socket_fd) -+{ -+ char lpbuf[BUFFER_SIZE*4] = {'\0'}; -+ -+ char host_addr[BUFFER_SIZE] = {'\0'}; -+ char file[BUFFER_SIZE] = {'\0'}; -+ int port = 0; -+ -+ -+ if(!url){ -+ DEBUG(" failed!\n"); -+ return 1; -+ } -+ -+ if(http_parse_url(url,host_addr,file,&port)){ -+ DEBUG("http_parse_url failed!\n"); -+ return 1; -+ } -+ DEBUG("url: %s\thost_addr : %s\tfile:%s\t,%d\n",url,host_addr,file,port); -+ -+ -+ if(socket_fd < 0){ -+ DEBUG("http_tcpclient_create failed\n"); -+ return 1; -+ } -+ -+ sprintf(lpbuf,HTTP_GET,file,host_addr,port); -+ -+ if(http_tcpclient_send(socket_fd,lpbuf,strlen(lpbuf)) < 0){ -+ DEBUG("http_tcpclient_send failed..\n"); -+ return 1; -+ } -+ DEBUG("request:\n%s\n",lpbuf); -+ -+ if(http_tcpclient_recv(socket_fd,lpbuf) <= 0){ -+ DEBUG("http_tcpclient_recv failed\n"); -+ close(socket_fd); -+ return 1; -+ } -+ DEBUG("rec:\n%s\n",lpbuf); -+ close(socket_fd); -+ -+ //return http_parse_result(lpbuf); -+return 0; -+} -+ -+ -+ -+int main(int argc, char *argv[]) -+{ -+ int fd,http_flag=0,http_ret=1; -+ struct sockaddr_in addr; -+ struct hostent *host; -+ struct timeval timeo = {3, 0}; -+ socklen_t len = sizeof(timeo); -+ -+ char http_url[100]="http://"; -+ -+ -+ -+ fd = socket(AF_INET, SOCK_STREAM, 0); -+ if (argc >= 4) -+ timeo.tv_sec = atoi(argv[3]); -+ if (argc>=5) -+ http_flag=1; -+ -+ if((host=timeGethostbyname(argv[1],timeo.tv_sec)) == NULL) { -+ DEBUG("gethostbyname err\n"); -+ return 1; -+ } -+ if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeo, len) == -1) -+ { -+ -+ DEBUG("setsockopt send err\n"); -+ return 1; -+ } -+ -+ if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeo, len) == -1) -+ { -+ -+ DEBUG("setsockopt recv err\n"); -+ return 1; -+ } -+ -+ addr.sin_family = AF_INET; -+ addr.sin_addr = *((struct in_addr *)host->h_addr); -+ //addr.sin_addr.s_addr = inet_addr(argv[1]); -+ addr.sin_port = htons(atoi(argv[2])); -+if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) -+ { -+ if (errno == EINPROGRESS) -+ { -+ DEBUG("timeout err\n"); -+ return 1; -+ } -+ DEBUG("connect err\n"); -+ return 1; -+ } -+if(http_flag==0) -+{ -+ close(fd); -+ return 0; -+} -+strcat(http_url,argv[1]); -+http_ret=http_get(http_url,fd); -+if(http_ret==1) -+{ -+DEBUG("recv err"); -+ return 1; -+} -+else -+{ -+DEBUG("recv ok"); -+ -+ return 0; -+} -+ -+} -\ No newline at end of file -diff --git a/server/common.h b/server/common.h -new file mode 100644 -index 0000000..000f084 ---- /dev/null -+++ b/server/common.h -@@ -0,0 +1,58 @@ -+/* -+ * common.h - Provide global definitions -+ * -+ * Copyright (C) 2013 - 2016, Max Lv -+ * -+ * This file is part of the shadowsocks-libev. -+ * shadowsocks-libev is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * shadowsocks-libev 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 General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with shadowsocks-libev; see the file COPYING. If not, see -+ * . -+ */ -+ -+#ifndef _COMMON_H -+#define _COMMON_H -+ -+#define DEFAULT_CONF_PATH "/etc/shadowsocks-libev/config.json" -+ -+#ifndef SOL_TCP -+#define SOL_TCP IPPROTO_TCP -+#endif -+ -+#if defined(MODULE_TUNNEL) || defined(MODULE_REDIR) -+#define MODULE_LOCAL -+#endif -+ -+int init_udprelay(const char *server_host, const char *server_port, -+#ifdef MODULE_LOCAL -+ const struct sockaddr *remote_addr, const int remote_addr_len, -+#ifdef MODULE_TUNNEL -+ const ss_addr_t tunnel_addr, -+#endif -+#endif -+ int mtu, int method, int auth, int timeout, const char *iface, const char *protocol, const char *protocol_param); -+ -+void free_udprelay(void); -+ -+#ifdef ANDROID -+int protect_socket(int fd); -+int send_traffic_stat(uint64_t tx, uint64_t rx); -+#endif -+ -+#define STAGE_ERROR -1 /* Error detected */ -+#define STAGE_INIT 0 /* Initial stage */ -+#define STAGE_HANDSHAKE 1 /* Handshake with client */ -+#define STAGE_PARSE 2 /* Parse the header */ -+#define STAGE_RESOLVE 4 /* Resolve the hostname */ -+#define STAGE_STREAM 5 /* Stream between client and server */ -+ -+#endif // _COMMON_H -diff --git a/server/crc32.c b/server/crc32.c -new file mode 100644 -index 0000000..6d328d2 ---- /dev/null -+++ b/server/crc32.c -@@ -0,0 +1,97 @@ -+static uint32_t crc32_table[256] = {0}; -+ -+void init_crc32_table(void) { -+ uint32_t c, i, j; -+ if (crc32_table[0] == 0) { -+ for (i = 0; i < 256; i++) { -+ c = i; -+ for (j = 0; j < 8; j++) { -+ if (c & 1) -+ c = 0xedb88320L ^ (c >> 1); -+ else -+ c = c >> 1; -+ } -+ crc32_table[i] = c; -+ } -+ } -+} -+ -+uint32_t crc32(unsigned char *buffer, unsigned int size) { -+ uint32_t crc = 0xFFFFFFFF; -+ unsigned int i; -+ for (i = 0; i < size; i++) { -+ crc = crc32_table[(crc ^ buffer[i]) & 0xFF] ^ (crc >> 8); -+ } -+ return crc ^ 0xFFFFFFFF; -+} -+ -+void fillcrc32to(unsigned char *buffer, unsigned int size, unsigned char *outbuffer) { -+ uint32_t crc = 0xFFFFFFFF; -+ unsigned int i; -+ for (i = 0; i < size; i++) { -+ crc = crc32_table[(crc ^ buffer[i]) & 0xff] ^ (crc >> 8); -+ } -+ crc ^= 0xFFFFFFFF; -+ outbuffer[0] = crc; -+ outbuffer[1] = crc >> 8; -+ outbuffer[2] = crc >> 16; -+ outbuffer[3] = crc >> 24; -+} -+ -+void fillcrc32(unsigned char *buffer, unsigned int size) { -+ uint32_t crc = 0xFFFFFFFF; -+ unsigned int i; -+ size -= 4; -+ for (i = 0; i < size; i++) { -+ crc = crc32_table[(crc ^ buffer[i]) & 0xff] ^ (crc >> 8); -+ } -+ buffer += size; -+ buffer[0] = crc; -+ buffer[1] = crc >> 8; -+ buffer[2] = crc >> 16; -+ buffer[3] = crc >> 24; -+} -+ -+void adler32_short(unsigned char *buffer, unsigned int size, uint32_t *a, uint32_t *b) { -+ for (int i = 0; i < size; i++) { -+ *a += buffer[i]; -+ *b += *a; -+ } -+ *a %= 65521; -+ *b %= 65521; -+} -+ -+#define NMAX 5552 -+uint32_t adler32(unsigned char *buffer, unsigned int size) { -+ uint32_t a = 1; -+ uint32_t b = 0; -+ while ( size >= NMAX ) { -+ adler32_short(buffer, NMAX, &a, &b); -+ buffer += NMAX; -+ size -= NMAX; -+ } -+ adler32_short(buffer, size, &a, &b); -+ return (b << 16) + a; -+} -+#undef NMAX -+ -+void filladler32(unsigned char *buffer, unsigned int size) { -+ size -= 4; -+ uint32_t checksum = adler32(buffer, size); -+ buffer += size; -+ buffer[0] = checksum; -+ buffer[1] = checksum >> 8; -+ buffer[2] = checksum >> 16; -+ buffer[3] = checksum >> 24; -+} -+ -+int checkadler32(unsigned char *buffer, unsigned int size) { -+ size -= 4; -+ uint32_t checksum = adler32(buffer, size); -+ buffer += size; -+ return checksum == (((uint32_t)buffer[3] << 24) -+ | ((uint32_t)buffer[2] << 16) -+ | ((uint32_t)buffer[1] << 8) -+ | (uint32_t)buffer[0]); -+} -+ -diff --git a/server/encrypt.c b/server/encrypt.c -new file mode 100644 -index 0000000..37dd5cd ---- /dev/null -+++ b/server/encrypt.c -@@ -0,0 +1,1645 @@ -+/* -+ * encrypt.c - Manage the global encryptor -+ * -+ * Copyright (C) 2013 - 2016, Max Lv -+ * -+ * This file is part of the shadowsocks-libev. -+ * -+ * shadowsocks-libev is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * shadowsocks-libev 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 General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with shadowsocks-libev; see the file COPYING. If not, see -+ * . -+ */ -+ -+#include -+ -+#ifdef HAVE_CONFIG_H -+#include "config.h" -+#endif -+ -+#if defined(USE_CRYPTO_OPENSSL) -+ -+#include -+#include -+#include -+#include -+ -+#elif defined(USE_CRYPTO_POLARSSL) -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#define CIPHER_UNSUPPORTED "unsupported" -+ -+#include -+#ifdef _WIN32 -+#include -+#include -+#else -+#include -+#endif -+ -+#elif defined(USE_CRYPTO_MBEDTLS) -+ -+#include -+#include -+#include -+#include -+#include -+#define CIPHER_UNSUPPORTED "unsupported" -+ -+#include -+#ifdef _WIN32 -+#include -+#include -+#else -+#include -+#endif -+ -+#endif -+ -+#include -+ -+#ifndef __MINGW32__ -+#include -+#endif -+ -+#include "cache.h" -+#include "encrypt.h" -+#include "utils.h" -+ -+#define OFFSET_ROL(p, o) ((uint64_t)(*(p + o)) << (8 * o)) -+ -+static uint8_t *enc_table; -+static uint8_t *dec_table; -+static uint8_t enc_key[MAX_KEY_LENGTH]; -+static int enc_key_len; -+static int enc_iv_len; -+static int enc_method; -+ -+static struct cache *iv_cache; -+ -+#ifdef DEBUG -+static void -+dump(char *tag, char *text, int len) -+{ -+ int i; -+ printf("%s: ", tag); -+ for (i = 0; i < len; i++) -+ printf("0x%02x ", (uint8_t)text[i]); -+ printf("\n"); -+} -+ -+#endif -+ -+static const char *supported_ciphers[CIPHER_NUM] = { -+ "table", -+ "rc4", -+ "rc4-md5-6", -+ "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" -+}; -+ -+#ifdef USE_CRYPTO_POLARSSL -+static const char *supported_ciphers_polarssl[CIPHER_NUM] = { -+ "table", -+ "ARC4-128", -+ "ARC4-128", -+ "ARC4-128", -+ "AES-128-CFB128", -+ "AES-192-CFB128", -+ "AES-256-CFB128", -+ "AES-128-CTR", -+ "AES-192-CTR", -+ "AES-256-CTR", -+ "BLOWFISH-CFB64", -+ "CAMELLIA-128-CFB128", -+ "CAMELLIA-192-CFB128", -+ "CAMELLIA-256-CFB128", -+ CIPHER_UNSUPPORTED, -+ CIPHER_UNSUPPORTED, -+ CIPHER_UNSUPPORTED, -+ CIPHER_UNSUPPORTED, -+ CIPHER_UNSUPPORTED, -+ "salsa20", -+ "chacha20", -+ "chacha20-ietf" -+}; -+#endif -+ -+#ifdef USE_CRYPTO_MBEDTLS -+static const char *supported_ciphers_mbedtls[CIPHER_NUM] = { -+ "table", -+ "ARC4-128", -+ "ARC4-128", -+ "ARC4-128", -+ "AES-128-CFB128", -+ "AES-192-CFB128", -+ "AES-256-CFB128", -+ "AES-128-CTR", -+ "AES-192-CTR", -+ "AES-256-CTR", -+ "BLOWFISH-CFB64", -+ "CAMELLIA-128-CFB128", -+ "CAMELLIA-192-CFB128", -+ "CAMELLIA-256-CFB128", -+ CIPHER_UNSUPPORTED, -+ CIPHER_UNSUPPORTED, -+ CIPHER_UNSUPPORTED, -+ CIPHER_UNSUPPORTED, -+ CIPHER_UNSUPPORTED, -+ "salsa20", -+ "chacha20", -+ "chacha20-ietf" -+}; -+#endif -+ -+#ifdef USE_CRYPTO_APPLECC -+static const CCAlgorithm supported_ciphers_applecc[CIPHER_NUM] = { -+ kCCAlgorithmInvalid, -+ kCCAlgorithmRC4, -+ kCCAlgorithmRC4, -+ kCCAlgorithmRC4, -+ kCCAlgorithmAES, -+ kCCAlgorithmAES, -+ kCCAlgorithmAES, -+ kCCAlgorithmAES, -+ kCCAlgorithmAES, -+ kCCAlgorithmAES, -+ kCCAlgorithmBlowfish, -+ kCCAlgorithmInvalid, -+ kCCAlgorithmInvalid, -+ kCCAlgorithmInvalid, -+ kCCAlgorithmCAST, -+ kCCAlgorithmDES, -+ kCCAlgorithmInvalid, -+ kCCAlgorithmRC2, -+ kCCAlgorithmInvalid, -+ kCCAlgorithmInvalid, -+ kCCAlgorithmInvalid, -+ kCCAlgorithmInvalid -+}; -+ -+static const CCMode supported_modes_applecc[CIPHER_NUM] = { -+ kCCAlgorithmInvalid, -+ kCCAlgorithmInvalid, -+ kCCModeRC4, -+ kCCModeRC4, -+ kCCModeCFB, -+ kCCModeCFB, -+ kCCModeCFB, -+ kCCModeCTR, -+ kCCModeCTR, -+ kCCModeCTR, -+ kCCModeCFB, -+ kCCAlgorithmInvalid, -+ kCCAlgorithmInvalid, -+ kCCAlgorithmInvalid, -+ kCCModeCFB, -+ kCCModeCFB, -+ kCCModeCFB, -+ kCCModeCFB, -+ kCCAlgorithmInvalid, -+ kCCAlgorithmInvalid, -+ kCCAlgorithmInvalid, -+ kCCAlgorithmInvalid -+}; -+#endif -+ -+static const int supported_ciphers_iv_size[CIPHER_NUM] = { -+ 0, 0, 6, 16, 16, 16, 16, 16, 16, 16, 8, 16, 16, 16, 8, 8, 8, 8, 16, 8, 8, 12 -+}; -+ -+static const int supported_ciphers_key_size[CIPHER_NUM] = { -+ 0, 16, 16, 16, 16, 24, 32, 16, 24, 32, 16, 16, 24, 32, 16, 8, 16, 16, 16, 32, 32, 32 -+}; -+ -+static int -+safe_memcmp(const void *s1, const void *s2, size_t n) -+{ -+ const unsigned char *_s1 = (const unsigned char *)s1; -+ const unsigned char *_s2 = (const unsigned char *)s2; -+ int ret = 0; -+ size_t i; -+ for (i = 0; i < n; i++) -+ ret |= _s1[i] ^ _s2[i]; -+ return !!ret; -+} -+ -+int -+balloc(buffer_t *ptr, size_t capacity) -+{ -+ sodium_memzero(ptr, sizeof(buffer_t)); -+ ptr->array = ss_malloc(capacity); -+ ptr->capacity = capacity; -+ return capacity; -+} -+ -+int -+brealloc(buffer_t *ptr, size_t len, size_t capacity) -+{ -+ if (ptr == NULL) -+ return -1; -+ size_t real_capacity = max(len, capacity); -+ if (ptr->capacity < real_capacity) { -+ ptr->array = ss_realloc(ptr->array, real_capacity); -+ ptr->capacity = real_capacity; -+ } -+ return real_capacity; -+} -+ -+void -+bfree(buffer_t *ptr) -+{ -+ if (ptr == NULL) -+ return; -+ ptr->idx = 0; -+ ptr->len = 0; -+ ptr->capacity = 0; -+ if (ptr->array != NULL) { -+ ss_free(ptr->array); -+ } -+} -+ -+static int -+crypto_stream_xor_ic(uint8_t *c, const uint8_t *m, uint64_t mlen, -+ const uint8_t *n, uint64_t ic, const uint8_t *k, -+ int method) -+{ -+ switch (method) { -+ case SALSA20: -+ return crypto_stream_salsa20_xor_ic(c, m, mlen, n, ic, k); -+ case CHACHA20: -+ return crypto_stream_chacha20_xor_ic(c, m, mlen, n, ic, k); -+ case CHACHA20IETF: -+ return crypto_stream_chacha20_ietf_xor_ic(c, m, mlen, n, (uint32_t)ic, k); -+ } -+ // always return 0 -+ return 0; -+} -+ -+static int -+random_compare(const void *_x, const void *_y, uint32_t i, -+ uint64_t a) -+{ -+ uint8_t x = *((uint8_t *)_x); -+ uint8_t y = *((uint8_t *)_y); -+ return a % (x + i) - a % (y + i); -+} -+ -+static void -+merge(uint8_t *left, int llength, uint8_t *right, -+ int rlength, uint32_t salt, uint64_t key) -+{ -+ uint8_t *ltmp = (uint8_t *)malloc(llength * sizeof(uint8_t)); -+ uint8_t *rtmp = (uint8_t *)malloc(rlength * sizeof(uint8_t)); -+ -+ uint8_t *ll = ltmp; -+ uint8_t *rr = rtmp; -+ -+ uint8_t *result = left; -+ -+ memcpy(ltmp, left, llength * sizeof(uint8_t)); -+ memcpy(rtmp, right, rlength * sizeof(uint8_t)); -+ -+ while (llength > 0 && rlength > 0) { -+ if (random_compare(ll, rr, salt, key) <= 0) { -+ *result = *ll; -+ ++ll; -+ --llength; -+ } else { -+ *result = *rr; -+ ++rr; -+ --rlength; -+ } -+ ++result; -+ } -+ -+ if (llength > 0) { -+ while (llength > 0) { -+ *result = *ll; -+ ++result; -+ ++ll; -+ --llength; -+ } -+ } else { -+ while (rlength > 0) { -+ *result = *rr; -+ ++result; -+ ++rr; -+ --rlength; -+ } -+ } -+ -+ ss_free(ltmp); -+ ss_free(rtmp); -+} -+ -+static void -+merge_sort(uint8_t array[], int length, -+ uint32_t salt, uint64_t key) -+{ -+ uint8_t middle; -+ uint8_t *left, *right; -+ int llength; -+ -+ if (length <= 1) { -+ return; -+ } -+ -+ middle = length / 2; -+ -+ llength = length - middle; -+ -+ left = array; -+ right = array + llength; -+ -+ merge_sort(left, llength, salt, key); -+ merge_sort(right, middle, salt, key); -+ merge(left, llength, right, middle, salt, key); -+} -+ -+int -+enc_get_iv_len() -+{ -+ return enc_iv_len; -+} -+ -+uint8_t* enc_get_key() -+{ -+ return enc_key; -+} -+ -+int enc_get_key_len() -+{ -+ return enc_key_len; -+} -+ -+unsigned char *enc_md5(const unsigned char *d, size_t n, unsigned char *md) -+{ -+#if defined(USE_CRYPTO_OPENSSL) -+ return MD5(d, n, md); -+#elif defined(USE_CRYPTO_POLARSSL) -+ static unsigned char m[16]; -+ if (md == NULL) { -+ md = m; -+ } -+ md5(d, n, md); -+ return md; -+#elif defined(USE_CRYPTO_MBEDTLS) -+ static unsigned char m[16]; -+ if (md == NULL) { -+ md = m; -+ } -+ mbedtls_md5(d, n, md); -+ return md; -+#endif -+} -+ -+void -+enc_table_init(const char *pass) -+{ -+ uint32_t i; -+ uint64_t key = 0; -+ uint8_t *digest; -+ -+ enc_table = ss_malloc(256); -+ dec_table = ss_malloc(256); -+ -+ digest = enc_md5((const uint8_t *)pass, strlen(pass), NULL); -+ -+ for (i = 0; i < 8; i++) -+ key += OFFSET_ROL(digest, i); -+ -+ for (i = 0; i < 256; ++i) -+ enc_table[i] = i; -+ for (i = 1; i < 1024; ++i) -+ merge_sort(enc_table, 256, i, key); -+ for (i = 0; i < 256; ++i) -+ // gen decrypt table from encrypt table -+ dec_table[enc_table[i]] = i; -+} -+ -+int -+cipher_iv_size(const cipher_t *cipher) -+{ -+#if defined(USE_CRYPTO_OPENSSL) -+ if (cipher->info == NULL) -+ return cipher->iv_len; -+ else -+ return EVP_CIPHER_iv_length(cipher->info); -+#elif defined(USE_CRYPTO_POLARSSL) || defined(USE_CRYPTO_MBEDTLS) -+ if (cipher == NULL) { -+ return 0; -+ } -+ return cipher->info->iv_size; -+#endif -+} -+ -+int -+cipher_key_size(const cipher_t *cipher) -+{ -+#if defined(USE_CRYPTO_OPENSSL) -+ if (cipher->info == NULL) -+ return cipher->key_len; -+ else -+ return EVP_CIPHER_key_length(cipher->info); -+#elif defined(USE_CRYPTO_POLARSSL) -+ if (cipher == NULL) { -+ return 0; -+ } -+ /* Override PolarSSL 32 bit default key size with sane 128 bit default */ -+ if (cipher->info->base != NULL && POLARSSL_CIPHER_ID_BLOWFISH == -+ cipher->info->base->cipher) { -+ return 128 / 8; -+ } -+ return cipher->info->key_length / 8; -+#elif defined(USE_CRYPTO_MBEDTLS) -+ /* -+ * Semi-API changes (technically public, morally private) -+ * Renamed a few headers to include _internal in the name. Those headers are -+ * not supposed to be included by users. -+ * Changed md_info_t into an opaque structure (use md_get_xxx() accessors). -+ * Changed pk_info_t into an opaque structure. -+ * Changed cipher_base_t into an opaque structure. -+ */ -+ if (cipher == NULL) { -+ return 0; -+ } -+ /* From Version 1.2.7 released 2013-04-13 Default Blowfish keysize is now 128-bits */ -+ return cipher->info->key_bitlen / 8; -+#endif -+} -+ -+void -+bytes_to_key_with_size(const char *pass, size_t len, uint8_t *md, size_t md_size) -+{ -+ uint8_t result[128]; -+ enc_md5((const unsigned char *)pass, len, result); -+ memcpy(md, result, 16); -+ int i = 16; -+ for (; i < md_size; i += 16) { -+ memcpy(result + 16, pass, len); -+ enc_md5(result, 16 + len, result); -+ memcpy(md + i, result, 16); -+ } -+} -+ -+int -+bytes_to_key(const cipher_t *cipher, const digest_type_t *md, -+ const uint8_t *pass, uint8_t *key) -+{ -+ size_t datal; -+ datal = strlen((const char *)pass); -+ -+#if defined(USE_CRYPTO_OPENSSL) -+ -+ MD5_CTX c; -+ unsigned char md_buf[MAX_MD_SIZE]; -+ int nkey; -+ int addmd; -+ unsigned int i, j, mds; -+ -+ mds = 16; -+ nkey = cipher_key_size(cipher); -+ if (pass == NULL) -+ return nkey; -+ memset(&c, 0, sizeof(MD5_CTX)); -+ -+ for (j = 0, addmd = 0; j < nkey; addmd++) { -+ MD5_Init(&c); -+ if (addmd) { -+ MD5_Update(&c, md_buf, mds); -+ } -+ MD5_Update(&c, pass, datal); -+ MD5_Final(md_buf, &c); -+ -+ for (i = 0; i < mds; i++, j++) { -+ if (j >= nkey) -+ break; -+ key[j] = md_buf[i]; -+ } -+ } -+ -+ return nkey; -+ -+#elif defined(USE_CRYPTO_POLARSSL) -+ md_context_t c; -+ unsigned char md_buf[MAX_MD_SIZE]; -+ int nkey; -+ int addmd; -+ unsigned int i, j, mds; -+ -+ nkey = cipher_key_size(cipher); -+ mds = md_get_size(md); -+ memset(&c, 0, sizeof(md_context_t)); -+ -+ if (pass == NULL) -+ return nkey; -+ if (md_init_ctx(&c, md)) -+ return 0; -+ -+ for (j = 0, addmd = 0; j < nkey; addmd++) { -+ md_starts(&c); -+ if (addmd) { -+ md_update(&c, md_buf, mds); -+ } -+ md_update(&c, pass, datal); -+ md_finish(&c, md_buf); -+ -+ for (i = 0; i < mds; i++, j++) { -+ if (j >= nkey) -+ break; -+ key[j] = md_buf[i]; -+ } -+ } -+ -+ md_free_ctx(&c); -+ return nkey; -+ -+#elif defined(USE_CRYPTO_MBEDTLS) -+ -+ mbedtls_md_context_t c; -+ unsigned char md_buf[MAX_MD_SIZE]; -+ int nkey; -+ int addmd; -+ unsigned int i, j, mds; -+ -+ nkey = cipher_key_size(cipher); -+ mds = mbedtls_md_get_size(md); -+ memset(&c, 0, sizeof(mbedtls_md_context_t)); -+ -+ if (pass == NULL) -+ return nkey; -+ if (mbedtls_md_setup(&c, md, 1)) -+ return 0; -+ -+ for (j = 0, addmd = 0; j < nkey; addmd++) { -+ mbedtls_md_starts(&c); -+ if (addmd) { -+ mbedtls_md_update(&c, md_buf, mds); -+ } -+ mbedtls_md_update(&c, pass, datal); -+ mbedtls_md_finish(&c, &(md_buf[0])); -+ -+ for (i = 0; i < mds; i++, j++) { -+ if (j >= nkey) -+ break; -+ key[j] = md_buf[i]; -+ } -+ } -+ -+ mbedtls_md_free(&c); -+ return nkey; -+#endif -+} -+ -+int -+rand_bytes(uint8_t *output, int len) -+{ -+ randombytes_buf(output, len); -+ // always return success -+ return 0; -+} -+ -+const cipher_kt_t * -+get_cipher_type(int method) -+{ -+ if (method <= TABLE || method >= CIPHER_NUM) { -+ LOGE("get_cipher_type(): Illegal method"); -+ return NULL; -+ } -+ -+ if (method == RC4_MD5 || method == RC4_MD5_6) { -+ method = RC4; -+ } -+ -+ if (method >= SALSA20) { -+ return NULL; -+ } -+ -+ const char *ciphername = supported_ciphers[method]; -+#if defined(USE_CRYPTO_OPENSSL) -+ return EVP_get_cipherbyname(ciphername); -+#elif defined(USE_CRYPTO_POLARSSL) -+ const char *polarname = supported_ciphers_polarssl[method]; -+ if (strcmp(polarname, CIPHER_UNSUPPORTED) == 0) { -+ LOGE("Cipher %s currently is not supported by PolarSSL library", -+ ciphername); -+ return NULL; -+ } -+ return cipher_info_from_string(polarname); -+#elif defined(USE_CRYPTO_MBEDTLS) -+ const char *mbedtlsname = supported_ciphers_mbedtls[method]; -+ if (strcmp(mbedtlsname, CIPHER_UNSUPPORTED) == 0) { -+ LOGE("Cipher %s currently is not supported by mbed TLS library", -+ ciphername); -+ return NULL; -+ } -+ return mbedtls_cipher_info_from_string(mbedtlsname); -+#endif -+} -+ -+const digest_type_t * -+get_digest_type(const char *digest) -+{ -+ if (digest == NULL) { -+ LOGE("get_digest_type(): Digest name is null"); -+ return NULL; -+ } -+ -+#if defined(USE_CRYPTO_OPENSSL) -+ return EVP_get_digestbyname(digest); -+#elif defined(USE_CRYPTO_POLARSSL) -+ return md_info_from_string(digest); -+#elif defined(USE_CRYPTO_MBEDTLS) -+ return mbedtls_md_info_from_string(digest); -+#endif -+} -+ -+void -+cipher_context_init(cipher_ctx_t *ctx, int method, int enc) -+{ -+ if (method <= TABLE || method >= CIPHER_NUM) { -+ LOGE("cipher_context_init(): Illegal method"); -+ return; -+ } -+ -+ if (method >= SALSA20) { -+ enc_iv_len = supported_ciphers_iv_size[method]; -+ return; -+ } -+ -+ const char *ciphername = supported_ciphers[method]; -+#if defined(USE_CRYPTO_APPLECC) -+ cipher_cc_t *cc = &ctx->cc; -+ cc->cryptor = NULL; -+ cc->cipher = supported_ciphers_applecc[method]; -+ if (cc->cipher == kCCAlgorithmInvalid) { -+ cc->valid = kCCContextInvalid; -+ } else { -+ cc->valid = kCCContextValid; -+ if (cc->cipher == kCCAlgorithmRC4) { -+ cc->mode = supported_modes_applecc[method]; -+ cc->padding = ccNoPadding; -+ } else { -+ cc->mode = supported_modes_applecc[method]; -+ if (cc->mode == kCCModeCTR) { -+ cc->padding = ccNoPadding; -+ } else { -+ cc->padding = ccPKCS7Padding; -+ } -+ } -+ return; -+ } -+#endif -+ -+ const cipher_kt_t *cipher = get_cipher_type(method); -+ -+#if defined(USE_CRYPTO_OPENSSL) -+ ctx->evp = EVP_CIPHER_CTX_new(); -+ cipher_evp_t *evp = ctx->evp; -+ -+ if (cipher == NULL) { -+ LOGE("Cipher %s not found in OpenSSL library", ciphername); -+ FATAL("Cannot initialize cipher"); -+ } -+ if (!EVP_CipherInit_ex(evp, cipher, NULL, NULL, NULL, enc)) { -+ LOGE("Cannot initialize cipher %s", ciphername); -+ exit(EXIT_FAILURE); -+ } -+ if (!EVP_CIPHER_CTX_set_key_length(evp, enc_key_len)) { -+ EVP_CIPHER_CTX_cleanup(evp); -+ LOGE("Invalid key length: %d", enc_key_len); -+ exit(EXIT_FAILURE); -+ } -+ if (method > RC4_MD5) { -+ EVP_CIPHER_CTX_set_padding(evp, 1); -+ } -+#elif defined(USE_CRYPTO_POLARSSL) -+ ctx->evp = (cipher_evp_t *)ss_malloc(sizeof(cipher_evp_t)); -+ cipher_evp_t *evp = ctx->evp; -+ -+ if (cipher == NULL) { -+ LOGE("Cipher %s not found in PolarSSL library", ciphername); -+ FATAL("Cannot initialize PolarSSL cipher"); -+ } -+ if (cipher_init_ctx(evp, cipher) != 0) { -+ FATAL("Cannot initialize PolarSSL cipher context"); -+ } -+#elif defined(USE_CRYPTO_MBEDTLS) -+ ctx->evp = (cipher_evp_t *)ss_malloc(sizeof(cipher_evp_t)); -+ cipher_evp_t *evp = ctx->evp; -+ -+ if (cipher == NULL) { -+ LOGE("Cipher %s not found in mbed TLS library", ciphername); -+ FATAL("Cannot initialize mbed TLS cipher"); -+ } -+ mbedtls_cipher_init(evp); -+ if (mbedtls_cipher_setup(evp, cipher) != 0) { -+ FATAL("Cannot initialize mbed TLS cipher context"); -+ } -+#endif -+} -+ -+void -+cipher_context_set_iv(cipher_ctx_t *ctx, uint8_t *iv, size_t iv_len, -+ int enc) -+{ -+ const unsigned char *true_key; -+ -+ if (iv == NULL) { -+ LOGE("cipher_context_set_iv(): IV is null"); -+ return; -+ } -+ -+ if (!enc) { -+ memcpy(ctx->iv, iv, iv_len); -+ } -+ -+ if (enc_method >= SALSA20) { -+ return; -+ } -+ -+ if (enc_method == RC4_MD5 || enc_method == RC4_MD5_6) { -+ unsigned char key_iv[32]; -+ memcpy(key_iv, enc_key, 16); -+ memcpy(key_iv + 16, iv, iv_len); -+ true_key = enc_md5(key_iv, 16 + iv_len, NULL); -+ iv_len = 0; -+ } else { -+ true_key = enc_key; -+ } -+ -+#ifdef USE_CRYPTO_APPLECC -+ cipher_cc_t *cc = &ctx->cc; -+ if (cc->valid == kCCContextValid) { -+ memcpy(cc->iv, iv, iv_len); -+ memcpy(cc->key, true_key, enc_key_len); -+ cc->iv_len = iv_len; -+ cc->key_len = enc_key_len; -+ cc->encrypt = enc ? kCCEncrypt : kCCDecrypt; -+ if (cc->cryptor != NULL) { -+ CCCryptorRelease(cc->cryptor); -+ cc->cryptor = NULL; -+ } -+ -+ CCCryptorStatus ret; -+ ret = CCCryptorCreateWithMode( -+ cc->encrypt, -+ cc->mode, -+ cc->cipher, -+ cc->padding, -+ cc->iv, cc->key, cc->key_len, -+ NULL, 0, 0, kCCModeOptionCTR_BE, -+ &cc->cryptor); -+ if (ret != kCCSuccess) { -+ if (cc->cryptor != NULL) { -+ CCCryptorRelease(cc->cryptor); -+ cc->cryptor = NULL; -+ } -+ FATAL("Cannot set CommonCrypto key and IV"); -+ } -+ return; -+ } -+#endif -+ -+ cipher_evp_t *evp = ctx->evp; -+ if (evp == NULL) { -+ LOGE("cipher_context_set_iv(): Cipher context is null"); -+ return; -+ } -+#if defined(USE_CRYPTO_OPENSSL) -+ if (!EVP_CipherInit_ex(evp, NULL, NULL, true_key, iv, enc)) { -+ EVP_CIPHER_CTX_cleanup(evp); -+ FATAL("Cannot set key and IV"); -+ } -+#elif defined(USE_CRYPTO_POLARSSL) -+ // XXX: PolarSSL 1.3.11: cipher_free_ctx deprecated, Use cipher_free() instead. -+ if (cipher_setkey(evp, true_key, enc_key_len * 8, enc) != 0) { -+ cipher_free_ctx(evp); -+ FATAL("Cannot set PolarSSL cipher key"); -+ } -+#if POLARSSL_VERSION_NUMBER >= 0x01030000 -+ if (cipher_set_iv(evp, iv, iv_len) != 0) { -+ cipher_free_ctx(evp); -+ FATAL("Cannot set PolarSSL cipher IV"); -+ } -+ if (cipher_reset(evp) != 0) { -+ cipher_free_ctx(evp); -+ FATAL("Cannot finalize PolarSSL cipher context"); -+ } -+#else -+ if (cipher_reset(evp, iv) != 0) { -+ cipher_free_ctx(evp); -+ FATAL("Cannot set PolarSSL cipher IV"); -+ } -+#endif -+#elif defined(USE_CRYPTO_MBEDTLS) -+ if (mbedtls_cipher_setkey(evp, true_key, enc_key_len * 8, enc) != 0) { -+ mbedtls_cipher_free(evp); -+ FATAL("Cannot set mbed TLS cipher key"); -+ } -+ -+ if (mbedtls_cipher_set_iv(evp, iv, iv_len) != 0) { -+ mbedtls_cipher_free(evp); -+ FATAL("Cannot set mbed TLS cipher IV"); -+ } -+ if (mbedtls_cipher_reset(evp) != 0) { -+ mbedtls_cipher_free(evp); -+ FATAL("Cannot finalize mbed TLS cipher context"); -+ } -+#endif -+ -+#ifdef DEBUG -+ dump("IV", (char *)iv, iv_len); -+#endif -+} -+ -+void -+cipher_context_release(cipher_ctx_t *ctx) -+{ -+ if (enc_method >= SALSA20) { -+ return; -+ } -+ -+#ifdef USE_CRYPTO_APPLECC -+ cipher_cc_t *cc = &ctx->cc; -+ if (cc->cryptor != NULL) { -+ CCCryptorRelease(cc->cryptor); -+ cc->cryptor = NULL; -+ } -+ if (cc->valid == kCCContextValid) { -+ return; -+ } -+#endif -+ -+#if defined(USE_CRYPTO_OPENSSL) -+ EVP_CIPHER_CTX_free(ctx->evp); -+#elif defined(USE_CRYPTO_POLARSSL) -+// NOTE: cipher_free_ctx deprecated in PolarSSL 1.3.11 -+ cipher_free_ctx(ctx->evp); -+ ss_free(ctx->evp); -+#elif defined(USE_CRYPTO_MBEDTLS) -+// NOTE: cipher_free_ctx deprecated -+ mbedtls_cipher_free(ctx->evp); -+ ss_free(ctx->evp); -+#endif -+} -+ -+static int -+cipher_context_update(cipher_ctx_t *ctx, uint8_t *output, size_t *olen, -+ const uint8_t *input, size_t ilen) -+{ -+#ifdef USE_CRYPTO_APPLECC -+ cipher_cc_t *cc = &ctx->cc; -+ if (cc->valid == kCCContextValid) { -+ CCCryptorStatus ret; -+ ret = CCCryptorUpdate(cc->cryptor, input, ilen, output, -+ ilen, olen); -+ return (ret == kCCSuccess) ? 1 : 0; -+ } -+#endif -+ cipher_evp_t *evp = ctx->evp; -+#if defined(USE_CRYPTO_OPENSSL) -+ int err = 0, tlen = *olen; -+ err = EVP_CipherUpdate(evp, (uint8_t *)output, &tlen, -+ (const uint8_t *)input, ilen); -+ *olen = tlen; -+ return err; -+#elif defined(USE_CRYPTO_POLARSSL) -+ return !cipher_update(evp, (const uint8_t *)input, ilen, -+ (uint8_t *)output, olen); -+#elif defined(USE_CRYPTO_MBEDTLS) -+ return !mbedtls_cipher_update(evp, (const uint8_t *)input, ilen, -+ (uint8_t *)output, olen); -+#endif -+} -+int ss_md5_hmac(char *auth, char *msg, int msg_len, uint8_t *iv) -+{ -+ uint8_t hash[MD5_BYTES]; -+ uint8_t auth_key[MAX_IV_LENGTH + MAX_KEY_LENGTH]; -+ memcpy(auth_key, iv, enc_iv_len); -+ memcpy(auth_key + enc_iv_len, enc_key, enc_key_len); -+ -+#if defined(USE_CRYPTO_OPENSSL) -+ HMAC(EVP_md5(), auth_key, enc_iv_len + enc_key_len, (uint8_t *)msg, msg_len, (uint8_t *)hash, NULL); -+#elif defined(USE_CRYPTO_MBEDTLS) -+ mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_MD5), auth_key, enc_iv_len + enc_key_len, (uint8_t *)msg, msg_len, (uint8_t *)hash); -+#else -+ md5_hmac(auth_key, enc_iv_len + enc_key_len, (uint8_t *)msg, msg_len, (uint8_t *)hash); -+#endif -+ -+ memcpy(auth, hash, MD5_BYTES); -+ -+ return 0; -+} -+ -+int ss_md5_hmac_with_key(char *auth, char *msg, int msg_len, uint8_t *auth_key, int key_len) -+{ -+ uint8_t hash[MD5_BYTES]; -+ -+#if defined(USE_CRYPTO_OPENSSL) -+ HMAC(EVP_md5(), auth_key, key_len, (uint8_t *)msg, msg_len, (uint8_t *)hash, NULL); -+#elif defined(USE_CRYPTO_MBEDTLS) -+ mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_MD5), auth_key, key_len, (uint8_t *)msg, msg_len, (uint8_t *)hash); -+#else -+ md5_hmac(auth_key, key_len, (uint8_t *)msg, msg_len, (uint8_t *)hash); -+#endif -+ -+ memcpy(auth, hash, MD5_BYTES); -+ -+ return 0; -+} -+ -+int ss_md5_hash_func(char *auth, char *msg, int msg_len) -+{ -+ uint8_t hash[MD5_BYTES]; -+ -+#if defined(USE_CRYPTO_OPENSSL) -+ MD5((uint8_t *)msg, msg_len, (uint8_t *)hash); -+#elif defined(USE_CRYPTO_MBEDTLS) -+ mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_MD5), (uint8_t *)msg, msg_len, (uint8_t *)hash); -+#else -+ md5((uint8_t *)msg, msg_len, (uint8_t *)hash); -+#endif -+ -+ memcpy(auth, hash, MD5_BYTES); -+ -+ return 0; -+} -+ -+int ss_sha1_hmac(char *auth, char *msg, int msg_len, uint8_t *iv) -+{ -+ uint8_t hash[SHA1_BYTES]; -+ uint8_t auth_key[MAX_IV_LENGTH + MAX_KEY_LENGTH]; -+ memcpy(auth_key, iv, enc_iv_len); -+ memcpy(auth_key + enc_iv_len, enc_key, enc_key_len); -+ -+#if defined(USE_CRYPTO_OPENSSL) -+ HMAC(EVP_sha1(), auth_key, enc_iv_len + enc_key_len, (uint8_t *)msg, msg_len, (uint8_t *)hash, NULL); -+#elif defined(USE_CRYPTO_MBEDTLS) -+ mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), auth_key, enc_iv_len + enc_key_len, (uint8_t *)msg, msg_len, (uint8_t *)hash); -+#else -+ sha1_hmac(auth_key, enc_iv_len + enc_key_len, (uint8_t *)msg, msg_len, (uint8_t *)hash); -+#endif -+ -+ memcpy(auth, hash, SHA1_BYTES); -+ -+ return 0; -+} -+ -+int ss_sha1_hmac_with_key(char *auth, char *msg, int msg_len, uint8_t *auth_key, int key_len) -+{ -+ uint8_t hash[SHA1_BYTES]; -+ -+#if defined(USE_CRYPTO_OPENSSL) -+ HMAC(EVP_sha1(), auth_key, key_len, (uint8_t *)msg, msg_len, (uint8_t *)hash, NULL); -+#elif defined(USE_CRYPTO_MBEDTLS) -+ mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), auth_key, key_len, (uint8_t *)msg, msg_len, (uint8_t *)hash); -+#else -+ sha1_hmac(auth_key, key_len, (uint8_t *)msg, msg_len, (uint8_t *)hash); -+#endif -+ -+ memcpy(auth, hash, SHA1_BYTES); -+ -+ return 0; -+} -+ -+int ss_sha1_hash_func(char *auth, char *msg, int msg_len) -+{ -+ uint8_t hash[SHA1_BYTES]; -+#if defined(USE_CRYPTO_OPENSSL) -+ SHA1((uint8_t *)msg, msg_len, (uint8_t *)hash); -+#elif defined(USE_CRYPTO_MBEDTLS) -+ mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), (uint8_t *)msg, msg_len, (uint8_t *)hash); -+#else -+ sha1((uint8_t *)msg, msg_len, (uint8_t *)hash); -+#endif -+ -+ memcpy(auth, hash, SHA1_BYTES); -+ -+ return 0; -+} -+ -+int ss_aes_128_cbc(char *encrypt, char *out_data, char *key) -+{ -+ unsigned char iv[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -+ -+#if defined(USE_CRYPTO_OPENSSL) -+ AES_KEY aes; -+ AES_set_encrypt_key((unsigned char*)key, 128, &aes); -+ AES_cbc_encrypt((const unsigned char *)encrypt, (unsigned char *)out_data, 16, &aes, iv, AES_ENCRYPT); -+ -+#elif defined(USE_CRYPTO_MBEDTLS) -+ mbedtls_aes_context aes; -+ -+ unsigned char output[16]; -+ -+ mbedtls_aes_setkey_enc( &aes, (unsigned char *)key, 128 ); -+ mbedtls_aes_crypt_cbc( &aes, MBEDTLS_AES_ENCRYPT, 16, iv, (unsigned char *)encrypt, output ); -+ -+ memcpy(out_data, output, 16); -+#else -+ -+ aes_context aes; -+ -+ unsigned char output[16]; -+ -+ aes_setkey_enc( &aes, (unsigned char *)key, 128 ); -+ aes_crypt_cbc( &aes, AES_ENCRYPT, 16, iv, (unsigned char *)encrypt, output ); -+ -+ memcpy(out_data, output, 16); -+#endif -+ -+ return 0; -+} -+ -+int ss_onetimeauth(buffer_t *buf, uint8_t *iv, size_t capacity) -+{ -+ uint8_t hash[ONETIMEAUTH_BYTES * 2]; -+ uint8_t auth_key[MAX_IV_LENGTH + MAX_KEY_LENGTH]; -+ memcpy(auth_key, iv, enc_iv_len); -+ memcpy(auth_key + enc_iv_len, enc_key, enc_key_len); -+ -+ brealloc(buf, ONETIMEAUTH_BYTES + buf->len, capacity); -+ -+#if defined(USE_CRYPTO_OPENSSL) -+ HMAC(EVP_sha1(), auth_key, enc_iv_len + enc_key_len, (uint8_t *)buf->array, buf->len, (uint8_t *)hash, NULL); -+#elif defined(USE_CRYPTO_MBEDTLS) -+ mbedtls_md_hmac(mbedtls_md_info_from_type( -+ MBEDTLS_MD_SHA1), auth_key, enc_iv_len + enc_key_len, (uint8_t *)buf->array, buf->len, -+ (uint8_t *)hash); -+#else -+ sha1_hmac(auth_key, enc_iv_len + enc_key_len, (uint8_t *)buf->array, buf->len, (uint8_t *)hash); -+#endif -+ -+ memcpy(buf->array + buf->len, hash, ONETIMEAUTH_BYTES); -+ buf->len += ONETIMEAUTH_BYTES; -+ -+ return 0; -+} -+ -+int -+ss_onetimeauth_verify(buffer_t *buf, uint8_t *iv) -+{ -+ uint8_t hash[ONETIMEAUTH_BYTES * 2]; -+ uint8_t auth_key[MAX_IV_LENGTH + MAX_KEY_LENGTH]; -+ memcpy(auth_key, iv, enc_iv_len); -+ memcpy(auth_key + enc_iv_len, enc_key, enc_key_len); -+ size_t len = buf->len - ONETIMEAUTH_BYTES; -+ -+#if defined(USE_CRYPTO_OPENSSL) -+ HMAC(EVP_sha1(), auth_key, enc_iv_len + enc_key_len, (uint8_t *)buf->array, len, hash, NULL); -+#elif defined(USE_CRYPTO_MBEDTLS) -+ mbedtls_md_hmac(mbedtls_md_info_from_type( -+ MBEDTLS_MD_SHA1), auth_key, enc_iv_len + enc_key_len, (uint8_t *)buf->array, len, hash); -+#else -+ sha1_hmac(auth_key, enc_iv_len + enc_key_len, (uint8_t *)buf->array, len, hash); -+#endif -+ -+ return safe_memcmp(buf->array + len, hash, ONETIMEAUTH_BYTES); -+} -+ -+int -+ss_encrypt_all(buffer_t *plain, int method, int auth, size_t capacity) -+{ -+ if (method > TABLE) { -+ cipher_ctx_t evp; -+ cipher_context_init(&evp, method, 1); -+ -+ size_t iv_len = enc_iv_len; -+ int err = 1; -+ -+ static buffer_t tmp = { 0, 0, 0, NULL }; -+ brealloc(&tmp, iv_len + plain->len, capacity); -+ buffer_t *cipher = &tmp; -+ cipher->len = plain->len; -+ -+ uint8_t iv[MAX_IV_LENGTH]; -+ -+ rand_bytes(iv, iv_len); -+ cipher_context_set_iv(&evp, iv, iv_len, 1); -+ memcpy(cipher->array, iv, iv_len); -+ -+ if (auth) { -+ ss_onetimeauth(plain, iv, capacity); -+ cipher->len = plain->len; -+ } -+ -+ if (method >= SALSA20) { -+ crypto_stream_xor_ic((uint8_t *)(cipher->array + iv_len), -+ (const uint8_t *)plain->array, (uint64_t)(plain->len), -+ (const uint8_t *)iv, -+ 0, enc_key, method); -+ } else { -+ err = cipher_context_update(&evp, (uint8_t *)(cipher->array + iv_len), -+ &cipher->len, (const uint8_t *)plain->array, -+ plain->len); -+ } -+ -+ if (!err) { -+ bfree(plain); -+ cipher_context_release(&evp); -+ return -1; -+ } -+ -+#ifdef DEBUG -+ dump("PLAIN", plain->array, plain->len); -+ dump("CIPHER", cipher->array + iv_len, cipher->len); -+#endif -+ -+ cipher_context_release(&evp); -+ -+ brealloc(plain, iv_len + cipher->len, capacity); -+ memcpy(plain->array, cipher->array, iv_len + cipher->len); -+ plain->len = iv_len + cipher->len; -+ -+ return 0; -+ } else { -+ char *begin = plain->array; -+ char *ptr = plain->array; -+ while (ptr < begin + plain->len) { -+ *ptr = (char)enc_table[(uint8_t)*ptr]; -+ ptr++; -+ } -+ return 0; -+ } -+} -+ -+int -+ss_encrypt(buffer_t *plain, enc_ctx_t *ctx, size_t capacity) -+{ -+ if (ctx != NULL) { -+ static buffer_t tmp = { 0, 0, 0, NULL }; -+ -+ int err = 1; -+ size_t iv_len = 0; -+ if (!ctx->init) { -+ iv_len = enc_iv_len; -+ } -+ -+ brealloc(&tmp, iv_len + plain->len, capacity); -+ buffer_t *cipher = &tmp; -+ cipher->len = plain->len; -+ -+ if (!ctx->init) { -+ cipher_context_set_iv(&ctx->evp, ctx->evp.iv, iv_len, 1); -+ memcpy(cipher->array, ctx->evp.iv, iv_len); -+ ctx->counter = 0; -+ ctx->init = 1; -+ } -+ -+ if (enc_method >= SALSA20) { -+ int padding = ctx->counter % SODIUM_BLOCK_SIZE; -+ brealloc(cipher, iv_len + (padding + cipher->len) * 2, capacity); -+ if (padding) { -+ brealloc(plain, plain->len + padding, capacity); -+ memmove(plain->array + padding, plain->array, plain->len); -+ sodium_memzero(plain->array, padding); -+ } -+ crypto_stream_xor_ic((uint8_t *)(cipher->array + iv_len), -+ (const uint8_t *)plain->array, -+ (uint64_t)(plain->len + padding), -+ (const uint8_t *)ctx->evp.iv, -+ ctx->counter / SODIUM_BLOCK_SIZE, enc_key, -+ enc_method); -+ ctx->counter += plain->len; -+ if (padding) { -+ memmove(cipher->array + iv_len, -+ cipher->array + iv_len + padding, cipher->len); -+ } -+ } else { -+ err = -+ cipher_context_update(&ctx->evp, -+ (uint8_t *)(cipher->array + iv_len), -+ &cipher->len, (const uint8_t *)plain->array, -+ plain->len); -+ if (!err) { -+ return -1; -+ } -+ } -+ -+#ifdef DEBUG -+ dump("PLAIN", plain->array, plain->len); -+ dump("CIPHER", cipher->array + iv_len, cipher->len); -+#endif -+ -+ brealloc(plain, iv_len + cipher->len, capacity); -+ memcpy(plain->array, cipher->array, iv_len + cipher->len); -+ plain->len = iv_len + cipher->len; -+ -+ return 0; -+ } else { -+ char *begin = plain->array; -+ char *ptr = plain->array; -+ while (ptr < begin + plain->len) { -+ *ptr = (char)enc_table[(uint8_t)*ptr]; -+ ptr++; -+ } -+ return 0; -+ } -+} -+ -+int -+ss_decrypt_all(buffer_t *cipher, int method, int auth, size_t capacity) -+{ -+ if (method > TABLE) { -+ size_t iv_len = enc_iv_len; -+ int ret = 1; -+ -+ if (cipher->len <= iv_len) { -+ return -1; -+ } -+ -+ cipher_ctx_t evp; -+ cipher_context_init(&evp, method, 0); -+ -+ static buffer_t tmp = { 0, 0, 0, NULL }; -+ brealloc(&tmp, cipher->len, capacity); -+ buffer_t *plain = &tmp; -+ plain->len = cipher->len - iv_len; -+ -+ uint8_t iv[MAX_IV_LENGTH]; -+ memcpy(iv, cipher->array, iv_len); -+ cipher_context_set_iv(&evp, iv, iv_len, 0); -+ -+ if (method >= SALSA20) { -+ crypto_stream_xor_ic((uint8_t *)plain->array, -+ (const uint8_t *)(cipher->array + iv_len), -+ (uint64_t)(cipher->len - iv_len), -+ (const uint8_t *)iv, 0, enc_key, method); -+ } else { -+ ret = cipher_context_update(&evp, (uint8_t *)plain->array, &plain->len, -+ (const uint8_t *)(cipher->array + iv_len), -+ cipher->len - iv_len); -+ } -+ -+ if (auth || (plain->array[0] & ONETIMEAUTH_FLAG)) { -+ if (plain->len > ONETIMEAUTH_BYTES) { -+ ret = !ss_onetimeauth_verify(plain, iv); -+ if (ret) { -+ plain->len -= ONETIMEAUTH_BYTES; -+ } -+ } else { -+ ret = 0; -+ } -+ } -+ -+ if (!ret) { -+ bfree(cipher); -+ cipher_context_release(&evp); -+ return -1; -+ } -+ -+#ifdef DEBUG -+ dump("PLAIN", plain->array, plain->len); -+ dump("CIPHER", cipher->array + iv_len, cipher->len - iv_len); -+#endif -+ -+ cipher_context_release(&evp); -+ -+ brealloc(cipher, plain->len, capacity); -+ memcpy(cipher->array, plain->array, plain->len); -+ cipher->len = plain->len; -+ -+ return 0; -+ } else { -+ char *begin = cipher->array; -+ char *ptr = cipher->array; -+ while (ptr < begin + cipher->len) { -+ *ptr = (char)dec_table[(uint8_t)*ptr]; -+ ptr++; -+ } -+ return 0; -+ } -+} -+ -+int -+ss_decrypt(buffer_t *cipher, enc_ctx_t *ctx, size_t capacity) -+{ -+ if (ctx != NULL) { -+ static buffer_t tmp = { 0, 0, 0, NULL }; -+ -+ size_t iv_len = 0; -+ int err = 1; -+ -+ brealloc(&tmp, cipher->len, capacity); -+ buffer_t *plain = &tmp; -+ plain->len = cipher->len; -+ -+ if (!ctx->init) { -+ uint8_t iv[MAX_IV_LENGTH]; -+ iv_len = enc_iv_len; -+ plain->len -= iv_len; -+ -+ memcpy(iv, cipher->array, iv_len); -+ cipher_context_set_iv(&ctx->evp, iv, iv_len, 0); -+ ctx->counter = 0; -+ ctx->init = 1; -+ -+ if (enc_method > RC4) { -+ if (cache_key_exist(iv_cache, (char *)iv, iv_len)) { -+ bfree(cipher); -+ return -1; -+ } else { -+ cache_insert(iv_cache, (char *)iv, iv_len, NULL); -+ } -+ } -+ } -+ -+ if (enc_method >= SALSA20) { -+ int padding = ctx->counter % SODIUM_BLOCK_SIZE; -+ brealloc(plain, (plain->len + padding) * 2, capacity); -+ -+ if (padding) { -+ brealloc(cipher, cipher->len + padding, capacity); -+ memmove(cipher->array + iv_len + padding, cipher->array + iv_len, -+ cipher->len - iv_len); -+ sodium_memzero(cipher->array + iv_len, padding); -+ } -+ crypto_stream_xor_ic((uint8_t *)plain->array, -+ (const uint8_t *)(cipher->array + iv_len), -+ (uint64_t)(cipher->len - iv_len + padding), -+ (const uint8_t *)ctx->evp.iv, -+ ctx->counter / SODIUM_BLOCK_SIZE, enc_key, -+ enc_method); -+ ctx->counter += cipher->len - iv_len; -+ if (padding) { -+ memmove(plain->array, plain->array + padding, plain->len); -+ } -+ } else { -+ err = cipher_context_update(&ctx->evp, (uint8_t *)plain->array, &plain->len, -+ (const uint8_t *)(cipher->array + iv_len), -+ cipher->len - iv_len); -+ } -+ -+ if (!err) { -+ bfree(cipher); -+ return -1; -+ } -+ -+#ifdef DEBUG -+ dump("PLAIN", plain->array, plain->len); -+ dump("CIPHER", cipher->array + iv_len, cipher->len - iv_len); -+#endif -+ -+ brealloc(cipher, plain->len, capacity); -+ memcpy(cipher->array, plain->array, plain->len); -+ cipher->len = plain->len; -+ -+ return 0; -+ } else { -+ char *begin = cipher->array; -+ char *ptr = cipher->array; -+ while (ptr < begin + cipher->len) { -+ *ptr = (char)dec_table[(uint8_t)*ptr]; -+ ptr++; -+ } -+ return 0; -+ } -+} -+ -+void -+enc_ctx_init(int method, enc_ctx_t *ctx, int enc) -+{ -+ sodium_memzero(ctx, sizeof(enc_ctx_t)); -+ cipher_context_init(&ctx->evp, method, enc); -+ -+ if (enc) { -+ rand_bytes(ctx->evp.iv, enc_iv_len); -+ } -+} -+ -+void -+enc_key_init(int method, const char *pass) -+{ -+ if (method <= TABLE || method >= CIPHER_NUM) { -+ LOGE("enc_key_init(): Illegal method"); -+ return; -+ } -+ -+ // Initialize cache -+ cache_create(&iv_cache, 256, NULL); -+ -+#if defined(USE_CRYPTO_OPENSSL) -+ OpenSSL_add_all_algorithms(); -+#else -+ cipher_kt_t cipher_info; -+#endif -+ -+ cipher_t cipher; -+ memset(&cipher, 0, sizeof(cipher_t)); -+ -+ // Initialize sodium for random generator -+ if (sodium_init() == -1) { -+ FATAL("Failed to initialize sodium"); -+ } -+ -+ if (method == SALSA20 || method == CHACHA20 || method == CHACHA20IETF) { -+#if defined(USE_CRYPTO_OPENSSL) -+ cipher.info = NULL; -+ cipher.key_len = supported_ciphers_key_size[method]; -+ cipher.iv_len = supported_ciphers_iv_size[method]; -+#endif -+#if defined(USE_CRYPTO_POLARSSL) -+ cipher.info = &cipher_info; -+ cipher.info->base = NULL; -+ cipher.info->key_length = supported_ciphers_key_size[method] * 8; -+ cipher.info->iv_size = supported_ciphers_iv_size[method]; -+#endif -+#if defined(USE_CRYPTO_MBEDTLS) -+ // XXX: key_length changed to key_bitlen in mbed TLS 2.0.0 -+ cipher.info = &cipher_info; -+ cipher.info->base = NULL; -+ cipher.info->key_bitlen = supported_ciphers_key_size[method] * 8; -+ cipher.info->iv_size = supported_ciphers_iv_size[method]; -+#endif -+ } else { -+ cipher.info = (cipher_kt_t *)get_cipher_type(method); -+ } -+ -+ if (cipher.info == NULL && cipher.key_len == 0) { -+ do { -+#if defined(USE_CRYPTO_POLARSSL) && defined(USE_CRYPTO_APPLECC) -+ if (supported_ciphers_applecc[method] != kCCAlgorithmInvalid) { -+ cipher_info.base = NULL; -+ cipher_info.key_length = supported_ciphers_key_size[method] * 8; -+ cipher_info.iv_size = supported_ciphers_iv_size[method]; -+ cipher.info = (cipher_kt_t *)&cipher_info; -+ break; -+ } -+#endif -+#if defined(USE_CRYPTO_MBEDTLS) && defined(USE_CRYPTO_APPLECC) -+ // XXX: key_length changed to key_bitlen in mbed TLS 2.0.0 -+ if (supported_ciphers_applecc[method] != kCCAlgorithmInvalid) { -+ cipher_info.base = NULL; -+ cipher_info.key_bitlen = supported_ciphers_key_size[method] * 8; -+ cipher_info.iv_size = supported_ciphers_iv_size[method]; -+ cipher.info = (cipher_kt_t *)&cipher_info; -+ break; -+ } -+#endif -+ LOGE("Cipher %s not found in crypto library", supported_ciphers[method]); -+ FATAL("Cannot initialize cipher"); -+ } while (0); -+ } -+ -+ const digest_type_t *md = get_digest_type("MD5"); -+ if (md == NULL) { -+ FATAL("MD5 Digest not found in crypto library"); -+ } -+ -+ enc_key_len = bytes_to_key(&cipher, md, (const uint8_t *)pass, enc_key); -+ -+ if (enc_key_len == 0) { -+ FATAL("Cannot generate key and IV"); -+ } -+ if (method == RC4_MD5 || method == RC4_MD5_6) { -+ enc_iv_len = supported_ciphers_iv_size[method]; -+ } else { -+ enc_iv_len = cipher_iv_size(&cipher); -+ } -+ enc_method = method; -+} -+ -+int -+enc_init(const char *pass, const char *method) -+{ -+ int m = TABLE; -+ if (method != NULL) { -+ for (m = TABLE; m < CIPHER_NUM; m++) -+ if (strcmp(method, supported_ciphers[m]) == 0) { -+ break; -+ } -+ if (m >= CIPHER_NUM) { -+ LOGE("Invalid cipher name: %s, use rc4-md5 instead", method); -+ m = RC4_MD5; -+ } -+ } -+ if (m == TABLE) { -+ enc_table_init(pass); -+ } else { -+ enc_key_init(m, pass); -+ } -+ return m; -+} -+ -+int -+ss_check_hash(buffer_t *buf, chunk_t *chunk, enc_ctx_t *ctx, size_t capacity) -+{ -+ int i, j, k; -+ ssize_t blen = buf->len; -+ uint32_t cidx = chunk->idx; -+ -+ brealloc(chunk->buf, chunk->len + blen, capacity); -+ brealloc(buf, chunk->len + blen, capacity); -+ -+ for (i = 0, j = 0, k = 0; i < blen; i++) { -+ chunk->buf->array[cidx++] = buf->array[k++]; -+ -+ if (cidx == CLEN_BYTES) { -+ uint16_t clen = ntohs(*((uint16_t *)chunk->buf->array)); -+ brealloc(chunk->buf, clen + AUTH_BYTES, capacity); -+ chunk->len = clen; -+ } -+ -+ if (cidx == chunk->len + AUTH_BYTES) { -+ // Compare hash -+ uint8_t hash[ONETIMEAUTH_BYTES * 2]; -+ uint8_t key[MAX_IV_LENGTH + sizeof(uint32_t)]; -+ -+ uint32_t c = htonl(chunk->counter); -+ memcpy(key, ctx->evp.iv, enc_iv_len); -+ memcpy(key + enc_iv_len, &c, sizeof(uint32_t)); -+#if defined(USE_CRYPTO_OPENSSL) -+ HMAC(EVP_sha1(), key, enc_iv_len + sizeof(uint32_t), -+ (uint8_t *)chunk->buf->array + AUTH_BYTES, chunk->len, hash, NULL); -+#elif defined(USE_CRYPTO_MBEDTLS) -+ mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), key, enc_iv_len + sizeof(uint32_t), -+ (uint8_t *)chunk->buf->array + AUTH_BYTES, chunk->len, hash); -+#else -+ sha1_hmac(key, enc_iv_len + sizeof(uint32_t), -+ (uint8_t *)chunk->buf->array + AUTH_BYTES, chunk->len, hash); -+#endif -+ -+ if (safe_memcmp(hash, chunk->buf->array + CLEN_BYTES, ONETIMEAUTH_BYTES) != 0) { -+ return 0; -+ } -+ -+ // Copy chunk back to buffer -+ memmove(buf->array + j + chunk->len, buf->array + k, blen - i - 1); -+ memcpy(buf->array + j, chunk->buf->array + AUTH_BYTES, chunk->len); -+ -+ // Reset the base offset -+ j += chunk->len; -+ k = j; -+ cidx = 0; -+ chunk->counter++; -+ } -+ } -+ -+ buf->len = j; -+ chunk->idx = cidx; -+ return 1; -+} -+ -+int -+ss_gen_hash(buffer_t *buf, uint32_t *counter, enc_ctx_t *ctx, size_t capacity) -+{ -+ ssize_t blen = buf->len; -+ uint16_t chunk_len = htons((uint16_t)blen); -+ uint8_t hash[ONETIMEAUTH_BYTES * 2]; -+ uint8_t key[MAX_IV_LENGTH + sizeof(uint32_t)]; -+ uint32_t c = htonl(*counter); -+ -+ brealloc(buf, AUTH_BYTES + blen, capacity); -+ memcpy(key, ctx->evp.iv, enc_iv_len); -+ memcpy(key + enc_iv_len, &c, sizeof(uint32_t)); -+#if defined(USE_CRYPTO_OPENSSL) -+ HMAC(EVP_sha1(), key, enc_iv_len + sizeof(uint32_t), (uint8_t *)buf->array, blen, hash, NULL); -+#elif defined(USE_CRYPTO_MBEDTLS) -+ mbedtls_md_hmac(mbedtls_md_info_from_type( -+ MBEDTLS_MD_SHA1), key, enc_iv_len + sizeof(uint32_t), (uint8_t *)buf->array, blen, hash); -+#else -+ sha1_hmac(key, enc_iv_len + sizeof(uint32_t), (uint8_t *)buf->array, blen, hash); -+#endif -+ -+ memmove(buf->array + AUTH_BYTES, buf->array, blen); -+ memcpy(buf->array + CLEN_BYTES, hash, ONETIMEAUTH_BYTES); -+ memcpy(buf->array, &chunk_len, CLEN_BYTES); -+ -+ *counter = *counter + 1; -+ buf->len = blen + AUTH_BYTES; -+ -+ return 0; -+} -diff --git a/server/encrypt.h b/server/encrypt.h -new file mode 100644 -index 0000000..3bb7940 ---- /dev/null -+++ b/server/encrypt.h -@@ -0,0 +1,222 @@ -+/* -+ * encrypt.h - Define the enryptor's interface -+ * -+ * Copyright (C) 2013 - 2016, Max Lv -+ * -+ * This file is part of the shadowsocks-libev. -+ * -+ * shadowsocks-libev is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * shadowsocks-libev 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 General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with shadowsocks-libev; see the file COPYING. If not, see -+ * . -+ */ -+ -+#ifndef _ENCRYPT_H -+#define _ENCRYPT_H -+ -+#ifndef __MINGW32__ -+#include -+#else -+ -+#ifdef max -+#undef max -+#endif -+ -+#ifdef min -+#undef min -+#endif -+ -+#endif -+ -+#include -+#include -+#include -+#include -+ -+#if defined(USE_CRYPTO_OPENSSL) -+ -+#include -+#include -+#include -+typedef EVP_CIPHER cipher_kt_t; -+typedef EVP_CIPHER_CTX cipher_evp_t; -+typedef EVP_MD digest_type_t; -+#define MAX_KEY_LENGTH EVP_MAX_KEY_LENGTH -+#define MAX_IV_LENGTH EVP_MAX_IV_LENGTH -+#define MAX_MD_SIZE EVP_MAX_MD_SIZE -+ -+#elif defined(USE_CRYPTO_POLARSSL) -+ -+#include -+#include -+typedef cipher_info_t cipher_kt_t; -+typedef cipher_context_t cipher_evp_t; -+typedef md_info_t digest_type_t; -+#define MAX_KEY_LENGTH 64 -+#define MAX_IV_LENGTH POLARSSL_MAX_IV_LENGTH -+#define MAX_MD_SIZE POLARSSL_MD_MAX_SIZE -+ -+#elif defined(USE_CRYPTO_MBEDTLS) -+ -+#include -+#include -+typedef mbedtls_cipher_info_t cipher_kt_t; -+typedef mbedtls_cipher_context_t cipher_evp_t; -+typedef mbedtls_md_info_t digest_type_t; -+#define MAX_KEY_LENGTH 64 -+#define MAX_IV_LENGTH MBEDTLS_MAX_IV_LENGTH -+#define MAX_MD_SIZE MBEDTLS_MD_MAX_SIZE -+ -+/* we must have MBEDTLS_CIPHER_MODE_CFB defined */ -+#if !defined(MBEDTLS_CIPHER_MODE_CFB) -+#error Cipher Feedback mode a.k.a CFB not supported by your mbed TLS. -+#endif -+ -+#endif -+ -+#ifdef USE_CRYPTO_APPLECC -+ -+#include -+ -+#define kCCAlgorithmInvalid UINT32_MAX -+#define kCCContextValid 0 -+#define kCCContextInvalid -1 -+ -+typedef struct { -+ CCCryptorRef cryptor; -+ int valid; -+ CCOperation encrypt; -+ CCAlgorithm cipher; -+ CCMode mode; -+ CCPadding padding; -+ uint8_t iv[MAX_IV_LENGTH]; -+ uint8_t key[MAX_KEY_LENGTH]; -+ size_t iv_len; -+ size_t key_len; -+} cipher_cc_t; -+ -+#endif -+ -+typedef struct { -+ cipher_evp_t *evp; -+#ifdef USE_CRYPTO_APPLECC -+ cipher_cc_t cc; -+#endif -+ uint8_t iv[MAX_IV_LENGTH]; -+} cipher_ctx_t; -+ -+typedef struct { -+ cipher_kt_t *info; -+ size_t iv_len; -+ size_t key_len; -+} cipher_t; -+ -+#ifdef HAVE_STDINT_H -+#include -+#elif HAVE_INTTYPES_H -+#include -+#endif -+ -+#define SODIUM_BLOCK_SIZE 64 -+ -+enum crpher_index { -+ NONE = -1, -+ TABLE = 0, -+ RC4, -+ RC4_MD5_6, -+ 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, -+ CHACHA20IETF, -+ CIPHER_NUM, -+}; -+ -+#define ONETIMEAUTH_FLAG 0x10 -+#define ADDRTYPE_MASK 0xEF -+ -+#define ONETIMEAUTH_BYTES 10U -+#define MD5_BYTES 16U -+#define SHA1_BYTES 20U -+#define CLEN_BYTES 2U -+#define AUTH_BYTES (ONETIMEAUTH_BYTES + CLEN_BYTES) -+ -+#define min(a, b) (((a) < (b)) ? (a) : (b)) -+#define max(a, b) (((a) > (b)) ? (a) : (b)) -+ -+typedef struct buffer { -+ size_t idx; -+ size_t len; -+ size_t capacity; -+ char *array; -+} buffer_t; -+ -+typedef struct chunk { -+ uint32_t idx; -+ uint32_t len; -+ uint32_t counter; -+ buffer_t *buf; -+} chunk_t; -+ -+typedef struct enc_ctx { -+ uint8_t init; -+ uint64_t counter; -+ cipher_ctx_t evp; -+} enc_ctx_t; -+ -+void bytes_to_key_with_size(const char *pass, size_t len, uint8_t *md, size_t md_size); -+ -+int ss_encrypt_all(buffer_t *plaintext, int method, int auth, size_t capacity); -+int ss_decrypt_all(buffer_t *ciphertext, int method, int auth, size_t capacity); -+int ss_encrypt(buffer_t *plaintext, enc_ctx_t *ctx, size_t capacity); -+int ss_decrypt(buffer_t *ciphertext, enc_ctx_t *ctx, size_t capacity); -+ -+void enc_ctx_init(int method, enc_ctx_t *ctx, int enc); -+int enc_init(const char *pass, const char *method); -+int enc_get_iv_len(void); -+uint8_t* enc_get_key(void); -+int enc_get_key_len(void); -+void cipher_context_release(cipher_ctx_t *evp); -+unsigned char *enc_md5(const unsigned char *d, size_t n, unsigned char *md); -+ -+int ss_md5_hmac(char *auth, char *msg, int msg_len, uint8_t *iv); -+int ss_md5_hmac_with_key(char *auth, char *msg, int msg_len, uint8_t *auth_key, int key_len); -+int ss_md5_hash_func(char *auth, char *msg, int msg_len); -+int ss_sha1_hmac(char *auth, char *msg, int msg_len, uint8_t *iv); -+int ss_sha1_hmac_with_key(char *auth, char *msg, int msg_len, uint8_t *auth_key, int key_len); -+int ss_sha1_hash_func(char *auth, char *msg, int msg_len); -+int ss_aes_128_cbc(char *encrypt, char *out_data, char *key); -+int ss_onetimeauth(buffer_t *buf, uint8_t *iv, size_t capacity); -+int ss_onetimeauth_verify(buffer_t *buf, uint8_t *iv); -+ -+int ss_check_hash(buffer_t *buf, chunk_t *chunk, enc_ctx_t *ctx, size_t capacity); -+int ss_gen_hash(buffer_t *buf, uint32_t *counter, enc_ctx_t *ctx, size_t capacity); -+ -+int balloc(buffer_t *ptr, size_t capacity); -+int brealloc(buffer_t *ptr, size_t len, size_t capacity); -+void bfree(buffer_t *ptr); -+ -+#endif // _ENCRYPT_H -diff --git a/server/http.c b/server/http.c -new file mode 100644 -index 0000000..3bd4a32 ---- /dev/null -+++ b/server/http.c -@@ -0,0 +1,152 @@ -+/* -+ * Copyright (c) 2011 and 2012, Dustin Lundquist -+ * 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 HOLDER 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. -+ */ -+ -+#ifdef HAVE_CONFIG_H -+#include "config.h" -+#endif -+ -+#include -+#include /* malloc() */ -+#include /* strncpy() */ -+#include /* strncasecmp() */ -+#include /* isblank() */ -+ -+#include "http.h" -+#include "protocol.h" -+ -+#define SERVER_NAME_LEN 256 -+ -+static int parse_http_header(const char *, size_t, char **); -+static int get_header(const char *, const char *, int, char **); -+static int next_header(const char **, int *); -+ -+static const protocol_t http_protocol_st = { -+ .default_port = 80, -+ .parse_packet = &parse_http_header, -+}; -+const protocol_t *const http_protocol = &http_protocol_st; -+ -+/* -+ * Parses a HTTP request for the Host: header -+ * -+ * Returns: -+ * >=0 - length of the hostname and updates *hostname -+ * caller is responsible for freeing *hostname -+ * -1 - Incomplete request -+ * -2 - No Host header included in this request -+ * -3 - Invalid hostname pointer -+ * -4 - malloc failure -+ * < -4 - Invalid HTTP request -+ * -+ */ -+static int -+parse_http_header(const char *data, size_t data_len, char **hostname) -+{ -+ int result, i; -+ -+ if (hostname == NULL) -+ return -3; -+ -+ if (data_len == 0) -+ return -1; -+ -+ result = get_header("Host:", data, data_len, hostname); -+ if (result < 0) -+ return result; -+ -+ /* -+ * if the user specifies the port in the request, it is included here. -+ * Host: example.com:80 -+ * so we trim off port portion -+ */ -+ for (i = result - 1; i >= 0; i--) -+ if ((*hostname)[i] == ':') { -+ (*hostname)[i] = '\0'; -+ result = i; -+ break; -+ } -+ -+ return result; -+} -+ -+static int -+get_header(const char *header, const char *data, int data_len, char **value) -+{ -+ int len, header_len; -+ -+ header_len = strlen(header); -+ -+ /* loop through headers stopping at first blank line */ -+ while ((len = next_header(&data, &data_len)) != 0) -+ if (len > header_len && strncasecmp(header, data, header_len) == 0) { -+ /* Eat leading whitespace */ -+ while (header_len < len && isblank(data[header_len])) -+ header_len++; -+ -+ *value = malloc(len - header_len + 1); -+ if (*value == NULL) -+ return -4; -+ -+ strncpy(*value, data + header_len, len - header_len); -+ (*value)[len - header_len] = '\0'; -+ -+ return len - header_len; -+ } -+ -+ /* If there is no data left after reading all the headers then we do not -+ * have a complete HTTP request, there must be a blank line */ -+ if (data_len == 0) -+ return -1; -+ -+ return -2; -+} -+ -+static int -+next_header(const char **data, int *len) -+{ -+ int header_len; -+ -+ /* perhaps we can optimize this to reuse the value of header_len, rather -+ * than scanning twice. -+ * Walk our data stream until the end of the header */ -+ while (*len > 2 && (*data)[0] != '\r' && (*data)[1] != '\n') { -+ (*len)--; -+ (*data)++; -+ } -+ -+ /* advanced past the pair */ -+ *data += 2; -+ *len -= 2; -+ -+ /* Find the length of the next header */ -+ header_len = 0; -+ while (*len > header_len + 1 -+ && (*data)[header_len] != '\r' -+ && (*data)[header_len + 1] != '\n') -+ header_len++; -+ -+ return header_len; -+} -diff --git a/server/http.h b/server/http.h -new file mode 100644 -index 0000000..914815a ---- /dev/null -+++ b/server/http.h -@@ -0,0 +1,34 @@ -+/* -+ * Copyright (c) 2011 and 2012, Dustin Lundquist -+ * 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 HOLDER 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. -+ */ -+#ifndef HTTP_H -+#define HTTP_H -+ -+#include -+#include "protocol.h" -+ -+const protocol_t *const http_protocol; -+ -+#endif -diff --git a/server/http_simple.c b/server/http_simple.c -new file mode 100644 -index 0000000..c1e34ee ---- /dev/null -+++ b/server/http_simple.c -@@ -0,0 +1,625 @@ -+ -+#include "http_simple.h" -+ -+static char* g_useragent[] = { -+ "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0", -+ "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:40.0) Gecko/20100101 Firefox/44.0", -+ "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36", -+ "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", -+ "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:35.0) Gecko/20100101 Firefox/35.0", -+ "Mozilla/5.0 (compatible; WOW64; MSIE 10.0; Windows NT 6.2)", -+ "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", -+ "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.3; Trident/7.0; .NET4.0E; .NET4.0C)", -+ "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko", -+ "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", -+ "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", -+ "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", -+}; -+ -+static int g_useragent_index = -1; -+ -+typedef struct http_simple_local_data { -+ int has_sent_header; -+ int has_recv_header; -+ char *encode_buffer; -+ int host_matched; -+ char *recv_buffer; -+ int recv_buffer_size; -+}http_simple_local_data; -+ -+void http_simple_local_data_init(http_simple_local_data* local) { -+ local->has_sent_header = 0; -+ local->has_recv_header = 0; -+ local->encode_buffer = NULL; -+ -+ local->recv_buffer = malloc(0); -+ local->recv_buffer_size = 0; -+ -+ local->host_matched = 0; -+ -+ if (g_useragent_index == -1) { -+ g_useragent_index = xorshift128plus() % (sizeof(g_useragent) / sizeof(*g_useragent)); -+ } -+} -+ -+obfs * http_simple_new_obfs() { -+ obfs * self = new_obfs(); -+ self->l_data = malloc(sizeof(http_simple_local_data)); -+ http_simple_local_data_init((http_simple_local_data*)self->l_data); -+ return self; -+} -+ -+void http_simple_dispose(obfs *self) { -+ http_simple_local_data *local = (http_simple_local_data*)self->l_data; -+ if (local->encode_buffer != NULL) { -+ free(local->encode_buffer); -+ local->encode_buffer = NULL; -+ } -+ free(local); -+ dispose_obfs(self); -+} -+ -+char http_simple_hex(char c) { -+ if (c < 10) return c + '0'; -+ return c - 10 + 'a'; -+} -+ -+int get_data_from_http_header(char *data, char **outdata) { -+ char *delim = "\r\n"; -+ char *delim_hex = "%"; -+ int outlength = 0; -+ -+ char *buf = *outdata; -+ char *p_line; -+ p_line = strtok(data, delim); -+ -+ //while(p_line) -+ { -+ char *p_hex; -+ -+ p_hex = strtok(p_line, delim_hex); -+ -+ while((p_hex = strtok(NULL, delim_hex))) -+ { -+ char hex = 0; -+ -+ if(strlen(p_hex) <= 0) -+ { -+ continue; -+ } -+ -+ if(strlen(p_hex) > 2) -+ { -+ char *c_hex = (char*)malloc(2); -+ memcpy(c_hex, p_hex, 2); -+ hex = (char)strtol(c_hex, NULL, 16); -+ free(c_hex); -+ } -+ else -+ { -+ hex = (char)strtol(p_hex, NULL, 16); -+ } -+ -+ outlength += 1; -+ buf = (char*)realloc(buf, outlength); -+ buf[outlength - 1] = hex; -+ } -+ -+ //p_line = strtok(p_line, delim); -+ } -+ return outlength; -+} -+ -+void get_host_from_http_header(char *data, char **host) { -+ char* data_begin = strstr(data, "Host: "); -+ -+ if(data_begin == NULL) -+ { -+ return; -+ } -+ -+ data_begin += 6; -+ char* data_end = strstr(data_begin, "\r\n"); -+ char* data_end_port = strstr(data_begin, ":"); -+ -+ int host_length = 0; -+ -+ if(data_end_port != NULL) -+ { -+ host_length = data_end_port - data_begin; -+ } -+ else -+ { -+ host_length = data_end - data_begin; -+ } -+ -+ if(host_length <= 0) -+ { -+ return; -+ } -+ -+ memset(*host, 0x00, 1024); -+ memcpy(*host, data_begin, host_length); -+} -+ -+void http_simple_encode_head(http_simple_local_data *local, char *data, int datalength) { -+ if (local->encode_buffer == NULL) { -+ local->encode_buffer = (char*)malloc(datalength * 3 + 1); -+ } -+ int pos = 0; -+ for (; pos < datalength; ++pos) { -+ local->encode_buffer[pos * 3] = '%'; -+ local->encode_buffer[pos * 3 + 1] = http_simple_hex(((unsigned char)data[pos] >> 4)); -+ local->encode_buffer[pos * 3 + 2] = http_simple_hex(data[pos] & 0xF); -+ } -+ local->encode_buffer[pos * 3] = 0; -+} -+ -+int http_simple_client_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity) { -+ char *encryptdata = *pencryptdata; -+ http_simple_local_data *local = (http_simple_local_data*)self->l_data; -+ if (local->has_sent_header) { -+ return datalength; -+ } -+ char hosts[1024]; -+ char * phost[128]; -+ int host_num = 0; -+ int pos; -+ char hostport[128]; -+ int head_size = self->server.head_len + (xorshift128plus() & 0x3F); -+ int outlength; -+ char * out_buffer = (char*)malloc(datalength + 2048); -+ char * body_buffer = NULL; -+ if (head_size > datalength) -+ head_size = datalength; -+ http_simple_encode_head(local, encryptdata, head_size); -+ if (self->server.param && strlen(self->server.param) == 0) -+ self->server.param = NULL; -+ strncpy(hosts, self->server.param ? self->server.param : self->server.host, sizeof hosts); -+ phost[host_num++] = hosts; -+ for (pos = 0; hosts[pos]; ++pos) { -+ if (hosts[pos] == ',') { -+ phost[host_num++] = &hosts[pos + 1]; -+ hosts[pos] = 0; -+ } else if (hosts[pos] == '#') { -+ char * body_pointer = &hosts[pos + 1]; -+ char * p; -+ int trans_char = 0; -+ p = body_buffer = (char*)malloc(2048); -+ for ( ; *body_pointer; ++body_pointer) { -+ if (*body_pointer == '\\') { -+ trans_char = 1; -+ continue; -+ } else if (*body_pointer == '\n') { -+ *p = '\r'; -+ *++p = '\n'; -+ continue; -+ } -+ if (trans_char) { -+ if (*body_pointer == '\\' ) { -+ *p = '\\'; -+ } else if (*body_pointer == 'n' ) { -+ *p = '\r'; -+ *++p = '\n'; -+ } else { -+ *p = '\\'; -+ *p = *body_pointer; -+ } -+ trans_char = 0; -+ } else { -+ *p = *body_pointer; -+ } -+ ++p; -+ } -+ *p = 0; -+ hosts[pos] = 0; -+ break; -+ } -+ } -+ host_num = xorshift128plus() % host_num; -+ if (self->server.port == 80) -+ sprintf(hostport, "%s", phost[host_num]); -+ else -+ sprintf(hostport, "%s:%d", phost[host_num], self->server.port); -+ if (body_buffer) { -+ sprintf(out_buffer, -+ "GET /%s HTTP/1.1\r\n" -+ "Host: %s\r\n" -+ "%s\r\n\r\n", -+ local->encode_buffer, -+ hostport, -+ body_buffer); -+ } else { -+ sprintf(out_buffer, -+ "GET /%s HTTP/1.1\r\n" -+ "Host: %s\r\n" -+ "User-Agent: %s\r\n" -+ "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" -+ "Accept-Language: en-US,en;q=0.8\r\n" -+ "Accept-Encoding: gzip, deflate\r\n" -+ "DNT: 1\r\n" -+ "Connection: keep-alive\r\n" -+ "\r\n", -+ local->encode_buffer, -+ hostport, -+ g_useragent[g_useragent_index] -+ ); -+ } -+ //LOGI("http header: %s", out_buffer); -+ outlength = strlen(out_buffer); -+ memmove(out_buffer + outlength, encryptdata + head_size, datalength - head_size); -+ outlength += datalength - head_size; -+ local->has_sent_header = 1; -+ if (*capacity < outlength) { -+ *pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2); -+ encryptdata = *pencryptdata; -+ } -+ memmove(encryptdata, out_buffer, outlength); -+ free(out_buffer); -+ if (body_buffer != NULL) -+ free(body_buffer); -+ if (local->encode_buffer != NULL) { -+ free(local->encode_buffer); -+ local->encode_buffer = NULL; -+ } -+ return outlength; -+} -+ -+int http_simple_server_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity) { -+ char *encryptdata = *pencryptdata; -+ http_simple_local_data *local = (http_simple_local_data*)self->l_data; -+ if (local->has_sent_header) { -+ return datalength; -+ } -+ int outlength; -+ char * out_buffer = (char*)malloc(datalength + 2048); -+ -+ time_t now; -+ struct tm *tm_now; -+ char datetime[200]; -+ -+ time(&now); -+ tm_now = localtime(&now); -+ strftime(datetime, 200, "%a, %d %b %Y %H:%M:%S GMT", tm_now); -+ -+ sprintf(out_buffer, -+ "HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nContent-Encoding: gzip\r\nContent-Type: text/html\r\nDate: " -+ "%s" -+ "\r\nServer: nginx\r\nVary: Accept-Encoding\r\n\r\n", -+ datetime); -+ -+ outlength = strlen(out_buffer); -+ memmove(out_buffer + outlength, encryptdata, datalength); -+ outlength += datalength; -+ -+ local->has_sent_header = 1; -+ if (*capacity < outlength) { -+ *pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2); -+ encryptdata = *pencryptdata; -+ } -+ memmove(encryptdata, out_buffer, outlength); -+ free(out_buffer); -+ return outlength; -+} -+ -+int http_simple_client_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback) { -+ char *encryptdata = *pencryptdata; -+ http_simple_local_data *local = (http_simple_local_data*)self->l_data; -+ *needsendback = 0; -+ if (local->has_recv_header) { -+ return datalength; -+ } -+ char* data_begin = strstr(encryptdata, "\r\n\r\n"); -+ if (data_begin) { -+ int outlength; -+ data_begin += 4; -+ local->has_recv_header = 1; -+ outlength = datalength - (data_begin - encryptdata); -+ memmove(encryptdata, data_begin, outlength); -+ return outlength; -+ } else { -+ return 0; -+ } -+} -+ -+int http_simple_server_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback) { -+ char *encryptdata = *pencryptdata; -+ http_simple_local_data *local = (http_simple_local_data*)self->l_data; -+ *needsendback = 0; -+ if (local->has_recv_header) { -+ return datalength; -+ } -+ -+ if(datalength != 0) -+ { -+ local->recv_buffer = (char*)realloc(local->recv_buffer, local->recv_buffer_size + datalength); -+ memmove(local->recv_buffer + local->recv_buffer_size, encryptdata, datalength); -+ local->recv_buffer_size += datalength; -+ -+ int outlength = local->recv_buffer_size; -+ if (*capacity < outlength) { -+ *pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2); -+ encryptdata = *pencryptdata; -+ } -+ memcpy(encryptdata, local->recv_buffer, local->recv_buffer_size); -+ } -+ -+ if(local->recv_buffer_size > 10) -+ { -+ if(strstr(local->recv_buffer, "GET /") == local->recv_buffer || strstr(local->recv_buffer, "POST /") == local->recv_buffer) -+ { -+ if(local->recv_buffer_size > 65536) -+ { -+ free(local->recv_buffer); -+ local->recv_buffer = malloc(0); -+ local->recv_buffer_size = 0; -+ local->has_sent_header = 1; -+ local->has_recv_header = 1; -+ LOGE("http_simple: over size"); -+ return -1; -+ } -+ } -+ else -+ { -+ free(local->recv_buffer); -+ local->recv_buffer = malloc(0); -+ local->recv_buffer_size = 0; -+ local->has_sent_header = 1; -+ local->has_recv_header = 1; -+ LOGE("http_simple: not match begin"); -+ return -1; -+ } -+ } -+ else -+ { -+ LOGE("http_simple: too short"); -+ local->has_sent_header = 1; -+ local->has_recv_header = 1; -+ return -1; -+ } -+ -+ char* data_begin = strstr(encryptdata, "\r\n\r\n"); -+ if (data_begin) { -+ int outlength; -+ char *ret_buf = (char*)malloc(*capacity); -+ memset(ret_buf, 0x00, *capacity); -+ int ret_buf_len = 0; -+ ret_buf_len = get_data_from_http_header(encryptdata, &ret_buf); -+ -+ if (self->server.param && strlen(self->server.param) == 0) -+ { -+ self->server.param = NULL; -+ } -+ else -+ { -+ if(local->host_matched == 0) -+ { -+ char *host = (char*)malloc(1024); -+ get_host_from_http_header(local->recv_buffer, &host); -+ char hosts[1024]; -+ char * phost[128]; -+ int host_num = 0; -+ int pos = 0; -+ int is_match = 0; -+ char * body_buffer = NULL; -+ strncpy(hosts, self->server.param, sizeof hosts); -+ phost[host_num++] = hosts; -+ -+ for (pos = 0; hosts[pos]; ++pos) { -+ if (hosts[pos] == ',') { -+ phost[host_num++] = &hosts[pos + 1]; -+ hosts[pos] = 0; -+ } else if (hosts[pos] == '#') { -+ char * body_pointer = &hosts[pos + 1]; -+ char * p; -+ int trans_char = 0; -+ p = body_buffer = (char*)malloc(2048); -+ for ( ; *body_pointer; ++body_pointer) { -+ if (*body_pointer == '\\') { -+ trans_char = 1; -+ continue; -+ } else if (*body_pointer == '\n') { -+ *p = '\r'; -+ *++p = '\n'; -+ continue; -+ } -+ if (trans_char) { -+ if (*body_pointer == '\\' ) { -+ *p = '\\'; -+ } else if (*body_pointer == 'n' ) { -+ *p = '\r'; -+ *++p = '\n'; -+ } else { -+ *p = '\\'; -+ *p = *body_pointer; -+ } -+ trans_char = 0; -+ } else { -+ *p = *body_pointer; -+ } -+ ++p; -+ } -+ *p = 0; -+ hosts[pos] = 0; -+ break; -+ } -+ } -+ -+ -+ for(pos = 0; pos < host_num; pos++) -+ { -+ if(strcmp(phost[pos], host) == 0) -+ { -+ is_match = 1; -+ local->host_matched = 1; -+ } -+ } -+ -+ if(is_match == 0) -+ { -+ free(local->recv_buffer); -+ local->recv_buffer = malloc(0); -+ local->recv_buffer_size = 0; -+ local->has_sent_header = 1; -+ local->has_recv_header = 1; -+ LOGE("http_simple: not match host, host: %s", host); -+ return -1; -+ } -+ -+ free(host); -+ } -+ } -+ -+ if(ret_buf_len <= 0) -+ { -+ return -1; -+ } -+ -+ data_begin += 4; -+ local->has_recv_header = 1; -+ -+ ret_buf = (char*)realloc(ret_buf, ret_buf_len + datalength - (data_begin - encryptdata)); -+ outlength = ret_buf_len + datalength - (data_begin - encryptdata); -+ -+ memcpy(ret_buf + ret_buf_len, data_begin, datalength - (data_begin - encryptdata)); -+ -+ if (*capacity < outlength) { -+ *pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2); -+ encryptdata = *pencryptdata; -+ } -+ -+ memcpy(encryptdata, ret_buf, outlength); -+ free(ret_buf); -+ return outlength; -+ } else { -+ return 0; -+ } -+} -+ -+void boundary(char result[]) -+{ -+ char *str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; -+ int i,lstr; -+ char ss[3] = {0}; -+ lstr = strlen(str); -+ srand((unsigned int)time((time_t *)NULL)); -+ for(i = 0; i < 32; ++i) -+ { -+ sprintf(ss, "%c", str[(rand()%lstr)]); -+ strcat(result, ss); -+ } -+} -+ -+int http_post_client_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity) { -+ char *encryptdata = *pencryptdata; -+ http_simple_local_data *local = (http_simple_local_data*)self->l_data; -+ if (local->has_sent_header) { -+ return datalength; -+ } -+ char hosts[1024]; -+ char * phost[128]; -+ int host_num = 0; -+ int pos; -+ char hostport[128]; -+ int head_size = self->server.head_len + (xorshift128plus() & 0x3F); -+ int outlength; -+ char * out_buffer = (char*)malloc(datalength + 2048); -+ char * body_buffer = NULL; -+ if (head_size > datalength) -+ head_size = datalength; -+ http_simple_encode_head(local, encryptdata, head_size); -+ if (self->server.param && strlen(self->server.param) == 0) -+ self->server.param = NULL; -+ strncpy(hosts, self->server.param ? self->server.param : self->server.host, sizeof hosts); -+ phost[host_num++] = hosts; -+ for (pos = 0; hosts[pos]; ++pos) { -+ if (hosts[pos] == ',') { -+ phost[host_num++] = &hosts[pos + 1]; -+ hosts[pos] = 0; -+ } else if (hosts[pos] == '#') { -+ char * body_pointer = &hosts[pos + 1]; -+ char * p; -+ int trans_char = 0; -+ p = body_buffer = (char*)malloc(2048); -+ for ( ; *body_pointer; ++body_pointer) { -+ if (*body_pointer == '\\') { -+ trans_char = 1; -+ continue; -+ } else if (*body_pointer == '\n') { -+ *p = '\r'; -+ *++p = '\n'; -+ continue; -+ } -+ if (trans_char) { -+ if (*body_pointer == '\\' ) { -+ *p = '\\'; -+ } else if (*body_pointer == 'n' ) { -+ *p = '\r'; -+ *++p = '\n'; -+ } else { -+ *p = '\\'; -+ *p = *body_pointer; -+ } -+ trans_char = 0; -+ } else { -+ *p = *body_pointer; -+ } -+ ++p; -+ } -+ *p = 0; -+ hosts[pos] = 0; -+ break; -+ } -+ } -+ host_num = xorshift128plus() % host_num; -+ if (self->server.port == 80) -+ sprintf(hostport, "%s", phost[host_num]); -+ else -+ sprintf(hostport, "%s:%d", phost[host_num], self->server.port); -+ if (body_buffer) { -+ sprintf(out_buffer, -+ "POST /%s HTTP/1.1\r\n" -+ "Host: %s\r\n" -+ "%s\r\n\r\n", -+ local->encode_buffer, -+ hostport, -+ body_buffer); -+ } else { -+ char result[33] = {0}; -+ boundary(result); -+ sprintf(out_buffer, -+ "POST /%s HTTP/1.1\r\n" -+ "Host: %s\r\n" -+ "User-Agent: %s\r\n" -+ "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" -+ "Accept-Language: en-US,en;q=0.8\r\n" -+ "Accept-Encoding: gzip, deflate\r\n" -+ "Content-Type: multipart/form-data; boundary=%s\r\n" -+ "DNT: 1\r\n" -+ "Connection: keep-alive\r\n" -+ "\r\n", -+ local->encode_buffer, -+ hostport, -+ g_useragent[g_useragent_index], -+ result -+ ); -+ } -+ //LOGI("http header: %s", out_buffer); -+ outlength = strlen(out_buffer); -+ memmove(out_buffer + outlength, encryptdata + head_size, datalength - head_size); -+ outlength += datalength - head_size; -+ local->has_sent_header = 1; -+ if (*capacity < outlength) { -+ *pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2); -+ encryptdata = *pencryptdata; -+ } -+ memmove(encryptdata, out_buffer, outlength); -+ free(out_buffer); -+ if (body_buffer != NULL) -+ free(body_buffer); -+ if (local->encode_buffer != NULL) { -+ free(local->encode_buffer); -+ local->encode_buffer = NULL; -+ } -+ return outlength; -+} -diff --git a/server/http_simple.h b/server/http_simple.h -new file mode 100644 -index 0000000..cce24cc ---- /dev/null -+++ b/server/http_simple.h -@@ -0,0 +1,21 @@ -+/* -+ * http_simple.h - Define shadowsocksR server's buffers and callbacks -+ * -+ * Copyright (C) 2015 - 2016, Break Wa11 -+ */ -+ -+#ifndef _HTTP_SIMPLE_H -+#define _HTTP_SIMPLE_H -+ -+obfs * http_simple_new_obfs(); -+void http_simple_dispose(obfs *self); -+ -+int http_simple_client_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity); -+int http_simple_client_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback); -+ -+int http_post_client_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity); -+ -+int http_simple_server_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity); -+int http_simple_server_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback); -+ -+#endif // _HTTP_SIMPLE_H -diff --git a/server/jconf.c b/server/jconf.c -new file mode 100644 -index 0000000..494aa5f ---- /dev/null -+++ b/server/jconf.c -@@ -0,0 +1,260 @@ -+/* -+ * jconf.c - Parse the JSON format config file -+ * -+ * Copyright (C) 2013 - 2016, Max Lv -+ * -+ * This file is part of the shadowsocks-libev. -+ * shadowsocks-libev is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * shadowsocks-libev 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 General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with shadowsocks-libev; see the file COPYING. If not, see -+ * . -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "utils.h" -+#include "jconf.h" -+#include "json.h" -+#include "string.h" -+ -+#include -+ -+#define check_json_value_type(value, expected_type, message) \ -+ do { \ -+ if ((value)->type != (expected_type)) \ -+ FATAL((message)); \ -+ } while(0) -+ -+static char * -+to_string(const json_value *value) -+{ -+ if (value->type == json_string) { -+ return ss_strndup(value->u.string.ptr, value->u.string.length); -+ } else if (value->type == json_integer) { -+ return strdup(ss_itoa(value->u.integer)); -+ } else if (value->type == json_null) { -+ return "null"; -+ } else { -+ LOGE("%d", value->type); -+ FATAL("Invalid config format."); -+ } -+ return 0; -+} -+ -+void -+free_addr(ss_addr_t *addr) -+{ -+ ss_free(addr->host); -+ ss_free(addr->port); -+} -+ -+void -+parse_addr(const char *str, ss_addr_t *addr) -+{ -+ int ipv6 = 0, ret = -1, n = 0; -+ char *pch; -+ -+ struct cork_ip ip; -+ if (cork_ip_init(&ip, str) != -1) { -+ addr->host = strdup(str); -+ addr->port = NULL; -+ return; -+ } -+ -+ pch = strchr(str, ':'); -+ while (pch != NULL) { -+ n++; -+ ret = pch - str; -+ pch = strchr(pch + 1, ':'); -+ } -+ if (n > 1) { -+ ipv6 = 1; -+ if (str[ret - 1] != ']') { -+ ret = -1; -+ } -+ } -+ -+ if (ret == -1) { -+ if (ipv6) { -+ addr->host = ss_strndup(str + 1, strlen(str) - 2); -+ } else { -+ addr->host = strdup(str); -+ } -+ addr->port = NULL; -+ } else { -+ if (ipv6) { -+ addr->host = ss_strndup(str + 1, ret - 2); -+ } else { -+ addr->host = ss_strndup(str, ret); -+ } -+ addr->port = strdup(str + ret + 1); -+ } -+} -+ -+jconf_t * -+read_jconf(const char *file) -+{ -+ static jconf_t conf; -+ -+ memset(&conf, 0, sizeof(jconf_t)); -+ -+ char *buf; -+ json_value *obj; -+ -+ FILE *f = fopen(file, "rb"); -+ if (f == NULL) { -+ FATAL("Invalid config path."); -+ } -+ -+ fseek(f, 0, SEEK_END); -+ long pos = ftell(f); -+ fseek(f, 0, SEEK_SET); -+ -+ if (pos >= MAX_CONF_SIZE) { -+ FATAL("Too large config file."); -+ } -+ -+ buf = ss_malloc(pos + 1); -+ if (buf == NULL) { -+ FATAL("No enough memory."); -+ } -+ -+ int nread = fread(buf, pos, 1, f); -+ if (!nread) { -+ FATAL("Failed to read the config file."); -+ } -+ fclose(f); -+ -+ buf[pos] = '\0'; // end of string -+ -+ json_settings settings = { 0UL, 0, NULL, NULL, NULL }; -+ char error_buf[512]; -+ obj = json_parse_ex(&settings, buf, pos, error_buf); -+ -+ if (obj == NULL) { -+ FATAL(error_buf); -+ } -+ -+ if (obj->type == json_object) { -+ unsigned int i, j; -+ for (i = 0; i < obj->u.object.length; i++) { -+ char *name = obj->u.object.values[i].name; -+ json_value *value = obj->u.object.values[i].value; -+ if (strcmp(name, "server") == 0) { -+ if (value->type == json_array) { -+ for (j = 0; j < value->u.array.length; j++) { -+ if (j >= MAX_REMOTE_NUM) { -+ break; -+ } -+ json_value *v = value->u.array.values[j]; -+ char *addr_str = to_string(v); -+ parse_addr(addr_str, conf.remote_addr + j); -+ ss_free(addr_str); -+ conf.remote_num = j + 1; -+ } -+ } else if (value->type == json_string) { -+ conf.remote_addr[0].host = to_string(value); -+ conf.remote_addr[0].port = NULL; -+ conf.remote_num = 1; -+ } -+ } else if (strcmp(name, "port_password") == 0) { -+ if (value->type == json_object) { -+ for (j = 0; j < value->u.object.length; j++) { -+ if (j >= MAX_PORT_NUM) { -+ break; -+ } -+ json_value *v = value->u.object.values[j].value; -+ if (v->type == json_string) { -+ conf.port_password[j].port = ss_strndup(value->u.object.values[j].name, -+ value->u.object.values[j].name_length); -+ conf.port_password[j].password = to_string(v); -+ conf.port_password_num = j + 1; -+ } -+ } -+ } -+ } else if (strcmp(name, "server_port") == 0) { -+ conf.remote_port = to_string(value); -+ } else if (strcmp(name, "local_address") == 0) { -+ conf.local_addr = to_string(value); -+ } else if (strcmp(name, "local_port") == 0) { -+ conf.local_port = to_string(value); -+ } else if (strcmp(name, "password") == 0) { -+ conf.password = to_string(value); -+ } else if (strcmp(name, "protocol") == 0) { // SSR -+ conf.protocol = to_string(value); -+ } else if (strcmp(name, "protocol_param") == 0) { // SSR -+ conf.protocol_param = to_string(value); -+ } else if (strcmp(name, "method") == 0) { -+ conf.method = to_string(value); -+ } else if (strcmp(name, "obfs") == 0) { // SSR -+ conf.obfs = to_string(value); -+ } else if (strcmp(name, "obfs_param") == 0) { // SSR -+ conf.obfs_param = to_string(value); -+ } else if (strcmp(name, "timeout") == 0) { -+ conf.timeout = to_string(value); -+ } else if (strcmp(name, "user") == 0) { -+ conf.user = to_string(value); -+ } else if (strcmp(name, "fast_open") == 0) { -+ check_json_value_type(value, json_boolean, -+ "invalid config file: option 'fast_open' must be a boolean"); -+ conf.fast_open = value->u.boolean; -+ } else if (strcmp(name, "auth") == 0) { -+ check_json_value_type(value, json_boolean, -+ "invalid config file: option 'auth' must be a boolean"); -+ conf.auth = value->u.boolean; -+ } else if (strcmp(name, "nofile") == 0) { -+ check_json_value_type(value, json_integer, -+ "invalid config file: option 'nofile' must be an integer"); -+ conf.nofile = value->u.integer; -+ } else if (strcmp(name, "nameserver") == 0) { -+ conf.nameserver = to_string(value); -+ } else if (strcmp(name, "tunnel_address") == 0) { -+ conf.tunnel_address = to_string(value); -+ } else if (strcmp(name, "mode") == 0) { -+ char *mode_str = to_string(value); -+ -+ if (strcmp(mode_str, "tcp_only") == 0) -+ conf.mode = TCP_ONLY; -+ else if (strcmp(mode_str, "tcp_and_udp") == 0) -+ conf.mode = TCP_AND_UDP; -+ else if (strcmp(mode_str, "udp_only") == 0) -+ conf.mode = UDP_ONLY; -+ else -+ LOGI("ignore unknown mode: %s, use tcp_only as fallback", -+ mode_str); -+ ss_free(mode_str); -+ } else if (strcmp(name, "mtu") == 0) { -+ check_json_value_type(value, json_integer, -+ "invalid config file: option 'mtu' must be an integer"); -+ conf.mtu = value->u.integer; -+ } else if (strcmp(name, "mptcp") == 0) { -+ check_json_value_type(value, json_boolean, -+ "invalid config file: option 'mptcp' must be a boolean"); -+ conf.mptcp = value->u.boolean; -+ } else if (strcmp(name, "ipv6_first") == 0) { -+ check_json_value_type(value, json_boolean, -+ "invalid config file: option 'ipv6_first' must be a boolean"); -+ conf.ipv6_first = value->u.boolean; -+ } -+ } -+ } else { -+ FATAL("Invalid config file"); -+ } -+ -+ ss_free(buf); -+ json_value_free(obj); -+ return &conf; -+} -diff --git a/server/jconf.h b/server/jconf.h -new file mode 100644 -index 0000000..9a7e5e3 ---- /dev/null -+++ b/server/jconf.h -@@ -0,0 +1,78 @@ -+/* -+ * jconf.h - Define the config data structure -+ * -+ * Copyright (C) 2013 - 2016, Max Lv -+ * -+ * This file is part of the shadowsocks-libev. -+ * shadowsocks-libev is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * shadowsocks-libev 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 General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with shadowsocks-libev; see the file COPYING. If not, see -+ * . -+ */ -+ -+#ifndef _JCONF_H -+#define _JCONF_H -+ -+#define MAX_PORT_NUM 1024 -+#define MAX_REMOTE_NUM 10 -+#define MAX_CONF_SIZE 128 * 1024 -+#define MAX_DNS_NUM 4 -+#define MAX_CONNECT_TIMEOUT 10 -+#define MAX_REQUEST_TIMEOUT 60 -+#define MIN_UDP_TIMEOUT 10 -+ -+#define TCP_ONLY 0 -+#define TCP_AND_UDP 1 -+#define UDP_ONLY 3 -+ -+typedef struct { -+ char *host; -+ char *port; -+} ss_addr_t; -+ -+typedef struct { -+ char *port; -+ char *password; -+} ss_port_password_t; -+ -+typedef struct { -+ int remote_num; -+ ss_addr_t remote_addr[MAX_REMOTE_NUM]; -+ int port_password_num; -+ ss_port_password_t port_password[MAX_PORT_NUM]; -+ char *remote_port; -+ char *local_addr; -+ char *local_port; -+ char *password; -+ char *protocol; // SSR -+ char *protocol_param; // SSR -+ char *method; -+ char *obfs; // SSR -+ char *obfs_param; // SSR -+ char *timeout; -+ char *user; -+ int auth; -+ int fast_open; -+ int nofile; -+ char *nameserver; -+ char *tunnel_address; -+ int mode; -+ int mtu; -+ int mptcp; -+ int ipv6_first; -+} jconf_t; -+ -+jconf_t *read_jconf(const char *file); -+void parse_addr(const char *str, ss_addr_t *addr); -+void free_addr(ss_addr_t *addr); -+ -+#endif // _JCONF_H -diff --git a/server/json.c b/server/json.c -new file mode 100644 -index 0000000..18e95ef ---- /dev/null -+++ b/server/json.c -@@ -0,0 +1,1002 @@ -+/* vim: set et ts=3 sw=3 sts=3 ft=c: -+ * -+ * Copyright (C) 2012, 2013, 2014 James McLaughlin et al. All rights reserved. -+ * https://github.com/udp/json-parser -+ * -+ * 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. -+ */ -+ -+#include "json.h" -+#include "utils.h" -+ -+#ifdef _MSC_VER -+#ifndef _CRT_SECURE_NO_WARNINGS -+#define _CRT_SECURE_NO_WARNINGS -+#endif -+#endif -+ -+#ifdef __cplusplus -+const struct _json_value json_value_none; /* zero-d by ctor */ -+#else -+const struct _json_value json_value_none = { NULL, 0, { 0 }, { NULL } }; -+#endif -+ -+#include -+#include -+#include -+#include -+ -+typedef unsigned short json_uchar; -+ -+static unsigned char -+hex_value(json_char c) -+{ -+ if (isdigit((uint8_t)c)) { -+ return c - '0'; -+ } -+ -+ switch (c) { -+ case 'a': -+ case 'A': -+ return 0x0A; -+ case 'b': -+ case 'B': -+ return 0x0B; -+ case 'c': -+ case 'C': -+ return 0x0C; -+ case 'd': -+ case 'D': -+ return 0x0D; -+ case 'e': -+ case 'E': -+ return 0x0E; -+ case 'f': -+ case 'F': -+ return 0x0F; -+ default: -+ return 0xFF; -+ } -+} -+ -+typedef struct { -+ unsigned long used_memory; -+ -+ unsigned int uint_max; -+ unsigned long ulong_max; -+ -+ json_settings settings; -+ int first_pass; -+} json_state; -+ -+static void * -+default_alloc(size_t size, int zero, void *user_data) -+{ -+ return zero ? calloc(1, size) : ss_malloc(size); -+} -+ -+static void -+default_free(void *ptr, void *user_data) -+{ -+ ss_free(ptr); -+} -+ -+static void * -+json_alloc(json_state *state, unsigned long size, int zero) -+{ -+ if ((state->ulong_max - state->used_memory) < size) { -+ return 0; -+ } -+ -+ if (state->settings.max_memory -+ && (state->used_memory += size) > state->settings.max_memory) { -+ return 0; -+ } -+ -+ return state->settings.mem_alloc(size, zero, state->settings.user_data); -+} -+ -+static int -+new_value(json_state *state, json_value **top, json_value **root, -+ json_value **alloc, json_type type) -+{ -+ json_value *value; -+ int values_size; -+ -+ if (!state->first_pass) { -+ value = *top = *alloc; -+ *alloc = (*alloc)->_reserved.next_alloc; -+ -+ if (!*root) { -+ *root = value; -+ } -+ -+ switch (value->type) { -+ case json_array: -+ -+ if (!(value->u.array.values = (json_value **)json_alloc -+ (state, value->u.array.length * -+ sizeof(json_value *), 0))) { -+ return 0; -+ } -+ -+ value->u.array.length = 0; -+ break; -+ -+ case json_object: -+ -+ values_size = sizeof(*value->u.object.values) * -+ value->u.object.length; -+ -+ if (!((*(void **)&value->u.object.values) = json_alloc -+ (state, -+ values_size + -+ ((size_t)value->u. -+ object.values), -+ 0))) { -+ return 0; -+ } -+ -+ value->_reserved.object_mem = (*(char **)&value->u.object.values) + -+ values_size; -+ -+ value->u.object.length = 0; -+ break; -+ -+ case json_string: -+ -+ if (!(value->u.string.ptr = (json_char *)json_alloc -+ (state, -+ (value->u.string.length + -+ 1) * sizeof(json_char), 0))) { -+ return 0; -+ } -+ -+ value->u.string.length = 0; -+ break; -+ -+ default: -+ break; -+ } -+ -+ return 1; -+ } -+ -+ value = (json_value *)json_alloc(state, sizeof(json_value), 1); -+ -+ if (!value) { -+ return 0; -+ } -+ -+ if (!*root) { -+ *root = value; -+ } -+ -+ value->type = type; -+ value->parent = *top; -+ -+ if (*alloc) { -+ (*alloc)->_reserved.next_alloc = value; -+ } -+ -+ *alloc = *top = value; -+ -+ return 1; -+} -+ -+#define e_off \ -+ ((int)(i - cur_line_begin)) -+ -+#define whitespace \ -+case '\n': \ -+ ++cur_line; cur_line_begin = i; \ -+case ' ': \ -+case '\t': \ -+case '\r' -+ -+#define string_add(b) \ -+ do { if (!state.first_pass) { string[string_length] = b; \ -+ } ++string_length; } while (0) -+ -+static const long -+ flag_next = 1 << 0, -+ flag_reproc = 1 << 1, -+ flag_need_comma = 1 << 2, -+ flag_seek_value = 1 << 3, -+ flag_escaped = 1 << 4, -+ flag_string = 1 << 5, -+ flag_need_colon = 1 << 6, -+ flag_done = 1 << 7, -+ flag_num_negative = 1 << 8, -+ flag_num_zero = 1 << 9, -+ flag_num_e = 1 << 10, -+ flag_num_e_got_sign = 1 << 11, -+ flag_num_e_negative = 1 << 12, -+ flag_line_comment = 1 << 13, -+ flag_block_comment = 1 << 14; -+ -+json_value * -+json_parse_ex(json_settings *settings, -+ const json_char *json, -+ size_t length, -+ char *error_buf) -+{ -+ json_char error[json_error_max]; -+ int cur_line; -+ const json_char *cur_line_begin, *i, *end; -+ json_value *top, *root, *alloc = 0; -+ json_state state = { 0UL, 0U, 0UL, { 0UL, 0, NULL, NULL, NULL }, 0 }; -+ long flags; -+ long num_digits = 0, num_e = 0; -+ json_int_t num_fraction = 0; -+ -+ /* Skip UTF-8 BOM -+ */ -+ if (length >= 3 && ((unsigned char)json[0]) == 0xEF -+ && ((unsigned char)json[1]) == 0xBB -+ && ((unsigned char)json[2]) == 0xBF) { -+ json += 3; -+ length -= 3; -+ } -+ -+ error[0] = '\0'; -+ end = (json + length); -+ -+ memcpy(&state.settings, settings, sizeof(json_settings)); -+ -+ if (!state.settings.mem_alloc) { -+ state.settings.mem_alloc = default_alloc; -+ } -+ -+ if (!state.settings.mem_free) { -+ state.settings.mem_free = default_free; -+ } -+ -+ memset(&state.uint_max, 0xFF, sizeof(state.uint_max)); -+ memset(&state.ulong_max, 0xFF, sizeof(state.ulong_max)); -+ -+ state.uint_max -= 8; /* limit of how much can be added before next check */ -+ state.ulong_max -= 8; -+ -+ for (state.first_pass = 1; state.first_pass >= 0; --state.first_pass) { -+ json_uchar uchar; -+ unsigned char uc_b1, uc_b2, uc_b3, uc_b4; -+ json_char *string = 0; -+ unsigned int string_length = 0; -+ -+ top = root = 0; -+ flags = flag_seek_value; -+ -+ cur_line = 1; -+ cur_line_begin = json; -+ -+ for (i = json;; ++i) { -+ json_char b = (i == end ? 0 : *i); -+ -+ if (flags & flag_string) { -+ if (!b) { -+ sprintf(error, "Unexpected EOF in string (at %d:%d)", -+ cur_line, e_off); -+ goto e_failed; -+ } -+ -+ if (string_length > state.uint_max) { -+ goto e_overflow; -+ } -+ -+ if (flags & flag_escaped) { -+ flags &= ~flag_escaped; -+ -+ switch (b) { -+ case 'b': -+ string_add('\b'); -+ break; -+ case 'f': -+ string_add('\f'); -+ break; -+ case 'n': -+ string_add('\n'); -+ break; -+ case 'r': -+ string_add('\r'); -+ break; -+ case 't': -+ string_add('\t'); -+ break; -+ case 'u': -+ -+ if (end - i < 4 || -+ (uc_b1 = hex_value(*++i)) == 0xFF || -+ (uc_b2 = hex_value(*++i)) == 0xFF -+ || (uc_b3 = hex_value(*++i)) == 0xFF || -+ (uc_b4 = hex_value(*++i)) == 0xFF) { -+ sprintf(error, -+ "Invalid character value `%c` (at %d:%d)", -+ b, cur_line, e_off); -+ goto e_failed; -+ } -+ -+ uc_b1 = uc_b1 * 16 + uc_b2; -+ uc_b2 = uc_b3 * 16 + uc_b4; -+ -+ uchar = ((json_char)uc_b1) * 256 + uc_b2; -+ -+ if (sizeof(json_char) >= sizeof(json_uchar) || -+ (uc_b1 == 0 && uc_b2 <= 0x7F)) { -+ string_add((json_char)uchar); -+ break; -+ } -+ -+ if (uchar <= 0x7FF) { -+ if (state.first_pass) { -+ string_length += 2; -+ } else { -+ string[string_length++] = 0xC0 | -+ ((uc_b2 & -+ 0xC0) >> -+ 6) | -+ ((uc_b1 & 0x7) << 2); -+ string[string_length++] = 0x80 | -+ (uc_b2 & 0x3F); -+ } -+ -+ break; -+ } -+ -+ if (state.first_pass) { -+ string_length += 3; -+ } else { -+ string[string_length++] = 0xE0 | -+ ((uc_b1 & 0xF0) >> 4); -+ string[string_length++] = 0x80 | -+ ((uc_b1 & -+ 0xF) << -+ 2) | -+ ((uc_b2 & 0xC0) >> 6); -+ string[string_length++] = 0x80 | (uc_b2 & 0x3F); -+ } -+ -+ break; -+ -+ default: -+ string_add(b); -+ } -+ -+ continue; -+ } -+ -+ if (b == '\\') { -+ flags |= flag_escaped; -+ continue; -+ } -+ -+ if (b == '"') { -+ if (!state.first_pass) { -+ string[string_length] = 0; -+ } -+ -+ flags &= ~flag_string; -+ string = 0; -+ -+ switch (top->type) { -+ case json_string: -+ -+ top->u.string.length = string_length; -+ flags |= flag_next; -+ -+ break; -+ -+ case json_object: -+ -+ if (state.first_pass) { -+ (*(json_char **)&top->u.object.values) += -+ string_length + 1; -+ } else { -+ top->u.object.values[top->u.object.length].name -+ = (json_char *)top->_reserved.object_mem; -+ -+ top->u.object.values[top->u.object.length]. -+ name_length -+ = string_length; -+ -+ (*(json_char **)&top->_reserved.object_mem) += -+ string_length + 1; -+ } -+ -+ flags |= flag_seek_value | flag_need_colon; -+ continue; -+ -+ default: -+ break; -+ } -+ } else { -+ string_add(b); -+ continue; -+ } -+ } -+ -+ if (state.settings.settings & json_enable_comments) { -+ if (flags & (flag_line_comment | flag_block_comment)) { -+ if (flags & flag_line_comment) { -+ if (b == '\r' || b == '\n' || !b) { -+ flags &= ~flag_line_comment; -+ --i; /* so null can be reproc'd */ -+ } -+ -+ continue; -+ } -+ -+ if (flags & flag_block_comment) { -+ if (!b) { -+ sprintf(error, -+ "%d:%d: Unexpected EOF in block comment", -+ cur_line, e_off); -+ goto e_failed; -+ } -+ -+ if (b == '*' && i < (end - 1) && i[1] == '/') { -+ flags &= ~flag_block_comment; -+ ++i; /* skip closing sequence */ -+ } -+ -+ continue; -+ } -+ } else if (b == '/') { -+ if (!(flags & (flag_seek_value | flag_done)) && top->type != -+ json_object) { -+ sprintf(error, "%d:%d: Comment not allowed here", -+ cur_line, e_off); -+ goto e_failed; -+ } -+ -+ if (++i == end) { -+ sprintf(error, "%d:%d: EOF unexpected", cur_line, -+ e_off); -+ goto e_failed; -+ } -+ -+ switch (b = *i) { -+ case '/': -+ flags |= flag_line_comment; -+ continue; -+ -+ case '*': -+ flags |= flag_block_comment; -+ continue; -+ -+ default: -+ sprintf(error, -+ "%d:%d: Unexpected `%c` in comment opening sequence", cur_line, e_off, -+ b); -+ goto e_failed; -+ } -+ } -+ } -+ -+ if (flags & flag_done) { -+ if (!b) { -+ break; -+ } -+ -+ switch (b) { -+whitespace: -+ continue; -+ -+ default: -+ sprintf(error, "%d:%d: Trailing garbage: `%c`", cur_line, -+ e_off, b); -+ goto e_failed; -+ } -+ } -+ -+ if (flags & flag_seek_value) { -+ switch (b) { -+whitespace: -+ continue; -+ -+ case ']': -+ -+ if (top->type == json_array) { -+ flags = -+ (flags & -+ ~(flag_need_comma | flag_seek_value)) | flag_next; -+ } else { -+ sprintf(error, "%d:%d: Unexpected ]", cur_line, e_off); -+ goto e_failed; -+ } -+ -+ break; -+ -+ default: -+ -+ if (flags & flag_need_comma) { -+ if (b == ',') { -+ flags &= ~flag_need_comma; -+ continue; -+ } else { -+ sprintf(error, "%d:%d: Expected , before %c", -+ cur_line, e_off, b); -+ goto e_failed; -+ } -+ } -+ -+ if (flags & flag_need_colon) { -+ if (b == ':') { -+ flags &= ~flag_need_colon; -+ continue; -+ } else { -+ sprintf(error, "%d:%d: Expected : before %c", -+ cur_line, e_off, b); -+ goto e_failed; -+ } -+ } -+ -+ flags &= ~flag_seek_value; -+ -+ switch (b) { -+ case '{': -+ -+ if (!new_value(&state, &top, &root, &alloc, -+ json_object)) { -+ goto e_alloc_failure; -+ } -+ -+ continue; -+ -+ case '[': -+ -+ if (!new_value(&state, &top, &root, &alloc, -+ json_array)) { -+ goto e_alloc_failure; -+ } -+ -+ flags |= flag_seek_value; -+ continue; -+ -+ case '"': -+ -+ if (!new_value(&state, &top, &root, &alloc, -+ json_string)) { -+ goto e_alloc_failure; -+ } -+ -+ flags |= flag_string; -+ -+ string = top->u.string.ptr; -+ string_length = 0; -+ -+ continue; -+ -+ case 't': -+ -+ if ((end - i) < 3 || *(++i) != 'r' || *(++i) != 'u' || -+ *(++i) != 'e') { -+ goto e_unknown_value; -+ } -+ -+ if (!new_value(&state, &top, &root, &alloc, -+ json_boolean)) { -+ goto e_alloc_failure; -+ } -+ -+ top->u.boolean = 1; -+ -+ flags |= flag_next; -+ break; -+ -+ case 'f': -+ -+ if ((end - i) < 4 || *(++i) != 'a' || *(++i) != 'l' || -+ *(++i) != 's' || *(++i) != 'e') { -+ goto e_unknown_value; -+ } -+ -+ if (!new_value(&state, &top, &root, &alloc, -+ json_boolean)) { -+ goto e_alloc_failure; -+ } -+ -+ flags |= flag_next; -+ break; -+ -+ case 'n': -+ -+ if ((end - i) < 3 || *(++i) != 'u' || *(++i) != 'l' || -+ *(++i) != 'l') { -+ goto e_unknown_value; -+ } -+ -+ if (!new_value(&state, &top, &root, &alloc, -+ json_null)) { -+ goto e_alloc_failure; -+ } -+ -+ flags |= flag_next; -+ break; -+ -+ default: -+ -+ if (isdigit((uint8_t)b) || b == '-') { -+ if (!new_value(&state, &top, &root, &alloc, -+ json_integer)) { -+ goto e_alloc_failure; -+ } -+ -+ if (!state.first_pass) { -+ while (isdigit((uint8_t)b) || b == '+' || b == -+ '-' -+ || b == 'e' || b == 'E' || b == '.') { -+ if ((++i) == end) { -+ b = 0; -+ break; -+ } -+ -+ b = *i; -+ } -+ -+ flags |= flag_next | flag_reproc; -+ break; -+ } -+ -+ flags &= ~(flag_num_negative | flag_num_e | -+ flag_num_e_got_sign | -+ flag_num_e_negative | -+ flag_num_zero); -+ -+ num_digits = 0; -+ num_fraction = 0; -+ num_e = 0; -+ -+ if (b != '-') { -+ flags |= flag_reproc; -+ break; -+ } -+ -+ flags |= flag_num_negative; -+ continue; -+ } else { -+ sprintf(error, -+ "%d:%d: Unexpected %c when seeking value", -+ cur_line, e_off, b); -+ goto e_failed; -+ } -+ } -+ } -+ } else { -+ switch (top->type) { -+ case json_object: -+ -+ switch (b) { -+whitespace: -+ continue; -+ -+ case '"': -+ -+ if (flags & flag_need_comma) { -+ sprintf(error, "%d:%d: Expected , before \"", -+ cur_line, e_off); -+ goto e_failed; -+ } -+ -+ flags |= flag_string; -+ -+ string = (json_char *)top->_reserved.object_mem; -+ string_length = 0; -+ -+ break; -+ -+ case '}': -+ -+ flags = (flags & ~flag_need_comma) | flag_next; -+ break; -+ -+ case ',': -+ -+ if (flags & flag_need_comma) { -+ flags &= ~flag_need_comma; -+ break; -+ } -+ -+ default: -+ -+ sprintf(error, "%d:%d: Unexpected `%c` in object", -+ cur_line, e_off, b); -+ goto e_failed; -+ } -+ -+ break; -+ -+ case json_integer: -+ case json_double: -+ -+ if (isdigit((uint8_t)b)) { -+ ++num_digits; -+ -+ if (top->type == json_integer || flags & flag_num_e) { -+ if (!(flags & flag_num_e)) { -+ if (flags & flag_num_zero) { -+ sprintf(error, -+ "%d:%d: Unexpected `0` before `%c`", -+ cur_line, e_off, b); -+ goto e_failed; -+ } -+ -+ if (num_digits == 1 && b == '0') { -+ flags |= flag_num_zero; -+ } -+ } else { -+ flags |= flag_num_e_got_sign; -+ num_e = (num_e * 10) + (b - '0'); -+ continue; -+ } -+ -+ top->u.integer = (top->u.integer * 10) + (b - '0'); -+ continue; -+ } -+ -+ num_fraction = (num_fraction * 10) + (b - '0'); -+ continue; -+ } -+ -+ if (b == '+' || b == '-') { -+ if ((flags & flag_num_e) && -+ !(flags & flag_num_e_got_sign)) { -+ flags |= flag_num_e_got_sign; -+ -+ if (b == '-') { -+ flags |= flag_num_e_negative; -+ } -+ -+ continue; -+ } -+ } else if (b == '.' && top->type == json_integer) { -+ if (!num_digits) { -+ sprintf(error, "%d:%d: Expected digit before `.`", -+ cur_line, e_off); -+ goto e_failed; -+ } -+ -+ top->type = json_double; -+ top->u.dbl = (double)top->u.integer; -+ -+ num_digits = 0; -+ continue; -+ } -+ -+ if (!(flags & flag_num_e)) { -+ if (top->type == json_double) { -+ if (!num_digits) { -+ sprintf(error, -+ "%d:%d: Expected digit after `.`", -+ cur_line, e_off); -+ goto e_failed; -+ } -+ -+ top->u.dbl += ((double)num_fraction) / -+ (pow(10, (double)num_digits)); -+ } -+ -+ if (b == 'e' || b == 'E') { -+ flags |= flag_num_e; -+ -+ if (top->type == json_integer) { -+ top->type = json_double; -+ top->u.dbl = (double)top->u.integer; -+ } -+ -+ num_digits = 0; -+ flags &= ~flag_num_zero; -+ -+ continue; -+ } -+ } else { -+ if (!num_digits) { -+ sprintf(error, "%d:%d: Expected digit after `e`", -+ cur_line, e_off); -+ goto e_failed; -+ } -+ -+ top->u.dbl *= -+ pow(10, -+ (double)((flags & -+ flag_num_e_negative) ? -num_e : num_e)); -+ } -+ -+ if (flags & flag_num_negative) { -+ if (top->type == json_integer) { -+ top->u.integer = -top->u.integer; -+ } else { -+ top->u.dbl = -top->u.dbl; -+ } -+ } -+ -+ flags |= flag_next | flag_reproc; -+ break; -+ -+ default: -+ break; -+ } -+ } -+ -+ if (flags & flag_reproc) { -+ flags &= ~flag_reproc; -+ --i; -+ } -+ -+ if (flags & flag_next) { -+ flags = (flags & ~flag_next) | flag_need_comma; -+ -+ if (!top->parent) { -+ /* root value done */ -+ -+ flags |= flag_done; -+ continue; -+ } -+ -+ if (top->parent->type == json_array) { -+ flags |= flag_seek_value; -+ } -+ -+ if (!state.first_pass) { -+ json_value *parent = top->parent; -+ -+ switch (parent->type) { -+ case json_object: -+ -+ parent->u.object.values -+ [parent->u.object.length].value = top; -+ -+ break; -+ -+ case json_array: -+ -+ parent->u.array.values -+ [parent->u.array.length] = top; -+ -+ break; -+ -+ default: -+ break; -+ } -+ } -+ -+ if ((++top->parent->u.array.length) > state.uint_max) { -+ goto e_overflow; -+ } -+ -+ top = top->parent; -+ -+ continue; -+ } -+ } -+ -+ alloc = root; -+ } -+ -+ return root; -+ -+e_unknown_value: -+ -+ sprintf(error, "%d:%d: Unknown value", cur_line, e_off); -+ goto e_failed; -+ -+e_alloc_failure: -+ -+ strcpy(error, "Memory allocation failure"); -+ goto e_failed; -+ -+e_overflow: -+ -+ sprintf(error, "%d:%d: Too long (caught overflow)", cur_line, e_off); -+ goto e_failed; -+ -+e_failed: -+ -+ if (error_buf) { -+ if (*error) { -+ strcpy(error_buf, error); -+ } else { -+ strcpy(error_buf, "Unknown error"); -+ } -+ } -+ -+ if (state.first_pass) { -+ alloc = root; -+ } -+ -+ while (alloc) { -+ top = alloc->_reserved.next_alloc; -+ state.settings.mem_free(alloc, state.settings.user_data); -+ alloc = top; -+ } -+ -+ if (!state.first_pass) { -+ json_value_free_ex(&state.settings, root); -+ } -+ -+ return 0; -+} -+ -+json_value * -+json_parse(const json_char *json, size_t length) -+{ -+ json_settings settings = { 0UL, 0, NULL, NULL, NULL }; -+ return json_parse_ex(&settings, json, length, 0); -+} -+ -+void -+json_value_free_ex(json_settings *settings, json_value *value) -+{ -+ json_value *cur_value; -+ -+ if (!value) { -+ return; -+ } -+ -+ value->parent = 0; -+ -+ while (value) { -+ switch (value->type) { -+ case json_array: -+ -+ if (!value->u.array.length) { -+ settings->mem_free(value->u.array.values, settings->user_data); -+ break; -+ } -+ -+ value = value->u.array.values[--value->u.array.length]; -+ continue; -+ -+ case json_object: -+ -+ if (!value->u.object.length) { -+ settings->mem_free(value->u.object.values, settings->user_data); -+ break; -+ } -+ -+ value = value->u.object.values[--value->u.object.length].value; -+ continue; -+ -+ case json_string: -+ -+ settings->mem_free(value->u.string.ptr, settings->user_data); -+ break; -+ -+ default: -+ break; -+ } -+ -+ cur_value = value; -+ value = value->parent; -+ settings->mem_free(cur_value, settings->user_data); -+ } -+} -+ -+void -+json_value_free(json_value *value) -+{ -+ json_settings settings = { 0UL, 0, NULL, NULL, NULL }; -+ settings.mem_free = default_free; -+ json_value_free_ex(&settings, value); -+} -diff --git a/server/json.h b/server/json.h -new file mode 100644 -index 0000000..016fc5a ---- /dev/null -+++ b/server/json.h -@@ -0,0 +1,249 @@ -+/* vim: set et ts=3 sw=3 sts=3 ft=c: -+ * -+ * Copyright (C) 2012, 2013, 2014 James McLaughlin et al. All rights reserved. -+ * https://github.com/udp/json-parser -+ * -+ * 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. -+ */ -+ -+#ifndef _JSON_H -+#define _JSON_H -+ -+#ifndef json_char -+#define json_char char -+#endif -+ -+#ifndef json_int_t -+#ifndef _MSC_VER -+#include -+#define json_int_t int64_t -+#else -+#define json_int_t __int64 -+#endif -+#endif -+ -+#include -+ -+#ifdef __cplusplus -+ -+#include -+ -+extern "C" -+{ -+#endif -+ -+typedef struct { -+ unsigned long max_memory; -+ int settings; -+ -+ /* Custom allocator support (leave null to use malloc/free) -+ */ -+ -+ void * (*mem_alloc)(size_t, int zero, void *user_data); -+ void (*mem_free)(void *, void *user_data); -+ -+ void *user_data; /* will be passed to mem_alloc and mem_free */ -+} json_settings; -+ -+#define json_enable_comments 0x01 -+ -+typedef enum { -+ json_none, -+ json_object, -+ json_array, -+ json_integer, -+ json_double, -+ json_string, -+ json_boolean, -+ json_null -+} json_type; -+ -+extern const struct _json_value json_value_none; -+ -+typedef struct _json_value { -+ struct _json_value *parent; -+ -+ json_type type; -+ -+ union { -+ int boolean; -+ json_int_t integer; -+ double dbl; -+ -+ struct { -+ unsigned int length; -+ json_char *ptr; /* null terminated */ -+ } string; -+ -+ struct { -+ unsigned int length; -+ -+ struct { -+ json_char *name; -+ unsigned int name_length; -+ -+ struct _json_value *value; -+ } *values; -+ -+#if defined(__cplusplus) && __cplusplus >= 201103L -+ decltype(values) begin() const -+ { -+ return values; -+ } -+ decltype(values) end() const -+ { -+ return values + length; -+ } -+#endif -+ } object; -+ -+ struct { -+ unsigned int length; -+ struct _json_value **values; -+ -+#if defined(__cplusplus) && __cplusplus >= 201103L -+ decltype(values) begin() const -+ { -+ return values; -+ } -+ decltype(values) end() const -+ { -+ return values + length; -+ } -+#endif -+ } array; -+ } u; -+ -+ union { -+ struct _json_value *next_alloc; -+ void *object_mem; -+ } _reserved; -+ -+ /* Some C++ operator sugar */ -+ -+#ifdef __cplusplus -+ -+public: -+ -+ inline _json_value(){ -+ memset(this, 0, sizeof(_json_value)); -+ } -+ -+ inline const struct _json_value &operator [] (int index) const { -+ if (type != json_array || index < 0 -+ || ((unsigned int)index) >= u.array.length) { -+ return json_value_none; -+ } -+ -+ return *u.array.values[index]; -+ } -+ -+ inline const struct _json_value &operator [] (const char *index) const { -+ if (type != json_object) { -+ return json_value_none; -+ } -+ -+ for (unsigned int i = 0; i < u.object.length; ++i) -+ if (!strcmp(u.object.values[i].name, index)) { -+ return *u.object.values[i].value; -+ } -+ -+ return json_value_none; -+ } -+ -+ inline operator const char * () const -+ { -+ switch (type) { -+ case json_string: -+ return u.string.ptr; -+ -+ default: -+ return ""; -+ } -+ } -+ -+ inline operator -+ json_int_t() const -+ { -+ switch (type) { -+ case json_integer: -+ return u.integer; -+ -+ case json_double: -+ return (json_int_t)u.dbl; -+ -+ default: -+ return 0; -+ } -+ } -+ -+ inline operator -+ bool() const -+ { -+ if (type != json_boolean) { -+ return false; -+ } -+ -+ return u.boolean != 0; -+ } -+ -+ inline operator double () const -+ { -+ switch (type) { -+ case json_integer: -+ return (double)u.integer; -+ -+ case json_double: -+ return u.dbl; -+ -+ default: -+ return 0; -+ } -+ } -+ -+#endif -+} json_value; -+ -+json_value *json_parse(const json_char *json, -+ size_t length); -+ -+#define json_error_max 128 -+json_value *json_parse_ex(json_settings *settings, -+ const json_char *json, -+ size_t length, -+ char *error); -+ -+void json_value_free(json_value *); -+ -+/* Not usually necessary, unless you used a custom mem_alloc and now want to -+ * use a custom mem_free. -+ */ -+void json_value_free_ex(json_settings *settings, -+ json_value *); -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif -diff --git a/server/list.c b/server/list.c -new file mode 100644 -index 0000000..dde085d ---- /dev/null -+++ b/server/list.c -@@ -0,0 +1,370 @@ -+#include "list.h" -+ -+/// 文件:list_impl.c -+/// 功能:实现链表的基本操作 -+/// 作者:bluewind -+/// 完成时间:2011.5.29 -+/// 修改时间:2011.5.31, 2011.7.2 -+/// 修改备注:在头节点处添加一个空节点,可以优化添加、删除节点代码 -+/// 再次修改,链表增加节点数据data_size,限制数据大小,修改了 -+/// 添加复制数据代码,修正重复添加节点后释放节点的Bug,添加了前 -+/// 插、排序和遍历功能,7.3 添加tail尾指针,改进后插法性能,并改名 -+/// -------------------------------------------------------------- -+ -+void swap_data(Node n1, Node n2); -+ -+/// -------------------------------------------------------------- -+// 函数名:list_init -+// 功能: 链表初始化 -+// 参数: 无 -+// 返回值:已初始化链表指针 -+// 备注: 链表本身动态分配,由list_destroy函数管理释放 -+/// -------------------------------------------------------------- -+List list_init(unsigned int data_size) -+{ -+ List list = (List) malloc(sizeof(struct clist)); -+ if(list != NULL) //内存分配成功 -+ { -+ list->head = (Node) malloc(sizeof(node)); //为头节点分配内存 -+ if(list->head) //内存分配成功 -+ { -+ list->head->data = NULL; //初始化头节点 -+ list->head->next = NULL; -+ list->data_size = data_size; -+ list->tail = list->head; -+ list->size = 0; -+ -+ list->add_back = list_add_back; //初始化成员函数 -+ list->add_front = list_add_front; -+ list->delete_node = list_delete_node; -+ list->delete_at = list_delete_at; -+ list->modify_at = list_modify_at; -+ list->have_same = list_have_same; -+ list->have_same_cmp = list_have_same_cmp; -+ list->foreach = list_foreach; -+ list->clear = list_clear; -+ list->sort = list_sort; -+ list->destroy = list_destroy; -+ } -+ } -+ return list; -+} -+ -+/// -------------------------------------------------------------- -+// 函数名:list_add_back -+// 功能: 添加链表结点 (后插法) -+// 参数: l--链表指针,data--链表数据指针,可为任意类型 -+// 返回值:int型,为1表示添加成功,为0表示添加失败 -+// 备注: 如果链表本身为空或是分配节点内存失败,将返回0 -+/// -------------------------------------------------------------- -+int list_add_back(List l, void *data) -+{ -+ Node new_node = (Node) malloc(sizeof(node)); -+ -+ if(l != NULL && new_node != NULL) //链表本身不为空,且内存申请成功 -+ { -+ new_node->data = malloc(l->data_size); -+ memcpy(new_node->data, data, l->data_size); -+ new_node->next = NULL; -+ -+ l->tail->next = new_node; //添加节点 -+ l->tail = new_node; //记录尾节点位置 -+ l->size ++; //链表元素总数加1 -+ -+ return 1; -+ } -+ -+ return 0; -+} -+ -+/// -------------------------------------------------------------- -+// 函数名:list_add_front -+// 功能: 添加链表结点 (前插法) -+// 参数: l--链表指针,data--链表数据指针,可为任意类型 -+// 返回值:int型,为1表示添加成功,为0表示添加失败 -+// 备注: 如果链表本身为空或是分配节点内存失败,将返回0 -+/// -------------------------------------------------------------- -+int list_add_front(List l, void *data) -+{ -+ Node new_node = (Node) malloc(sizeof(node)); -+ -+ if(l != NULL && new_node != NULL) -+ { -+ new_node->data = malloc(l->data_size); -+ memcpy(new_node->data, data, l->data_size); -+ new_node->next = l->head->next; -+ -+ l->head->next = new_node; -+ if(!l->size) //记录尾指针位置 -+ l->tail = new_node; -+ l->size ++; -+ -+ return 1; -+ } -+ -+ return 0; -+} -+ -+/// -------------------------------------------------------------- -+// 函数名:list_delete_node -+// 功能:删除链表结点 -+// 参数:l--链表指针,data--链表数据指针,可为任意类型 -+// *pfunc为指向一个数据类型比较的函数指针 -+// 返回值:int型,为1表示删除成功,为0表示没有找到匹配数据 -+// 备注:*pfunc函数接口参数ndata为节点数据,data为比较数据,返回为真表示匹配数据 -+/// -------------------------------------------------------------- -+int list_delete_node(List l, void *data, int (*pfunc)(void *ndata, void *data)) -+{ -+ if(l != NULL) -+ { -+ Node prev = l->head; //前一个节点 -+ Node curr = l->head->next; //当前节点 -+ -+ while(curr != NULL) -+ { -+ if(pfunc(curr->data, data)) //如果找到匹配数据 -+ { -+ if(curr == l->tail) //如果是删除尾节点 -+ l->tail = prev; -+ -+ prev->next = prev->next->next; //修改前节点next指针指向下下个节点 -+ -+ free(curr->data); //释放节点数据 -+ free(curr); //释放节点 -+ -+ l->size--; //链表元素总数减1 -+ return 1; //返回真值 -+ } -+ prev = prev->next; //没有找到匹配时移动前节点和当前节点 -+ curr = curr->next; -+ } -+ } -+ -+ return 0; //没有找到匹配数据 -+} -+ -+/// -------------------------------------------------------------- -+// 函数名:list_delete_at -+// 功能: 修改链表节点元素值 -+// 参数: l--链表指针,index--索引值, 范围(0 -- size-1) -+// 返回值:int型,为1表示删除成功,为0表示删除失败 -+// 备注: 如果链表本身为空或是index为非法值,将返回0 -+/// -------------------------------------------------------------- -+int list_delete_at(List l, unsigned int index) -+{ -+ unsigned int cindex = 0; -+ -+ if(l != NULL && index >= 0 && index < l->size) -+ { -+ Node prev = l->head; //前一个节点 -+ Node curr = l->head->next; //当前节点 -+ -+ while(cindex != index) -+ { -+ prev = prev->next; -+ curr = curr->next; -+ cindex ++; -+ } -+ -+ if(index == (l->size) - 1) -+ l->tail = prev; -+ -+ prev->next = prev->next->next; -+ free(curr->data); -+ free(curr); -+ l->size --; -+ -+ return 1; -+ } -+ -+ return 0; -+} -+ -+/// -------------------------------------------------------------- -+// 函数名:list_modify_at -+// 功能: 修改链表节点元素值 -+// 参数: l--链表指针,index--索引值, 范围(0 -- size-1) -+// data--链表数据指针 -+// 返回值:int型,为1表示修改成功,为0表示修改失败 -+// 备注: 如果链表本身为空或是index为非法值,将返回0 -+/// -------------------------------------------------------------- -+int list_modify_at(List l, unsigned int index, void *new_data) -+{ -+ unsigned int cindex = 0; -+ -+ if(l != NULL && index >= 0 && index < l->size ) //非空链表,并且index值合法 -+ { -+ Node curr = l->head->next; -+ while(cindex != index) -+ { -+ curr = curr->next; -+ cindex ++; -+ } -+ memcpy(curr->data, new_data, l->data_size); -+ return 1; -+ } -+ -+ return 0; -+} -+ -+/// -------------------------------------------------------------- -+// 函数名:list_sort -+// 功能: 链表排序 -+// 参数: l--链表指针,*pfunc为指向一个数据类型比较的函数指针 -+// 返回值:无 -+// 备注: 使用简单选择排序法,相比冒泡法每次交换,效率高一点 -+/// -------------------------------------------------------------- -+void list_sort(List l, compare pfunc) -+{ -+ if(l != NULL) -+ { -+ Node min, icurr, jcurr; -+ -+ icurr = l->head->next; -+ while(icurr) -+ { -+ min = icurr; //记录最小值 -+ jcurr = icurr->next; //内循环指向下一个节点 -+ while(jcurr) -+ { -+ if(pfunc(min->data, jcurr->data)) //如果找到n+1到最后一个元素最小值 -+ min = jcurr; //记录下最小值的位置 -+ -+ jcurr = jcurr->next; -+ } -+ -+ if(min != icurr) //当最小值位置和n+1元素位置不相同时 -+ { -+ swap_data(min, icurr); //才进行交换,减少交换次数 -+ } -+ -+ icurr = icurr->next; -+ } -+ } -+} -+ -+void swap_data(Node n1, Node n2) -+{ -+ void *temp; -+ -+ temp = n2->data; -+ n2->data = n1->data; -+ n1->data = temp; -+} -+ -+ -+int list_have_same(List l, void *data, int (*pfunc)(void *ndata, void *data)) -+{ -+ if(l != NULL) -+ { -+ Node curr; -+ -+ for(curr = l->head->next; curr != NULL; curr = curr->next) -+ { -+ if(pfunc(curr->data, data)) -+ { -+ return 1; -+ } -+ } -+ } -+ -+ return 0; -+} -+ -+int list_have_same_cmp(List l, void *data) -+{ -+ if(l != NULL) -+ { -+ Node curr; -+ -+ for(curr = l->head->next; curr != NULL; curr = curr->next) -+ { -+ if(memcmp(curr->data, data, l->data_size)) -+ { -+ return 1; -+ } -+ } -+ } -+ -+ return 0; -+} -+ -+/// -------------------------------------------------------------- -+// 函数名:list_foreach -+// 功能: 遍历链表元素 -+// 参数: l--链表指针,doit为指向一个处理数据的函数指针 -+// 返回值:无 -+// 备注: doit申明为void (*dofunc)(void *ndata)原型 -+/// -------------------------------------------------------------- -+void list_foreach(List l, dofunc doit) -+{ -+ if(l != NULL) -+ { -+ Node curr; -+ -+ for(curr = l->head->next; curr != NULL; curr = curr->next) -+ { -+ doit(curr->data); -+ } -+ } -+} -+ -+/// -------------------------------------------------------------- -+// 函数名:list_clear -+// 功能: 清空链表元素 -+// 参数: l--链表指针 -+// 返回值:无 -+// 备注: 没有使用先Destroy再Init链表的办法,直接实现 -+/// -------------------------------------------------------------- -+void list_clear(List l) -+{ -+ if(l != NULL) -+ { -+ Node temp; -+ Node curr = l->head->next; -+ -+ while(curr != NULL) -+ { -+ temp = curr->next; -+ -+ free(curr->data); //释放节点和数据 -+ free(curr); -+ -+ curr = temp; -+ } -+ -+ l->size = 0; //重置链表数据 -+ l->head->next = NULL; -+ l->tail = l->head; -+ } -+} -+ -+/// -------------------------------------------------------------- -+// 函数名:list_destroy -+// 功能: 释放链表 -+// 参数: l--链表指针 -+// 返回值:空链表指针 -+/// -------------------------------------------------------------- -+List list_destroy(List l) -+{ -+ if(l != NULL) -+ { -+ Node temp; -+ -+ while(l->head) -+ { -+ temp = l->head->next; -+ -+ if(l->head->data != NULL) //如果是头节点就不释放数据空间 -+ free(l->head->data); //先释放节点数据(但是节点数据里也有指针?) -+ free(l->head); //再释放节点 -+ -+ l->head = temp; -+ } -+ -+ free(l); //释放链表本身占用空间 -+ l = NULL; -+ } -+ -+ return l; -+} -diff --git a/server/list.h b/server/list.h -new file mode 100644 -index 0000000..ab49720 ---- /dev/null -+++ b/server/list.h -@@ -0,0 +1,61 @@ -+#ifndef LIST_H_H -+#define LIST_H_H -+ -+#include -+#include -+#include -+ -+typedef struct clist *List; -+ -+typedef int (*compare)(void *ndata, void *data); -+typedef void (*dofunc)(void *ndata); -+ -+typedef int (*lpf0)(List l, void *data); -+typedef int (*lpf1)(List l, void *data, compare pfunc); -+typedef List (*lpf2)(List l); -+typedef void (*lpf3)(List l); -+typedef void (*lpf4)(List l, dofunc pfunc); -+typedef int (*lpf5)(List l, unsigned int index, void *new_data); -+typedef void (*lpf6)(List l, compare pfunc); -+typedef int (*lpf7)(List l, unsigned int index); -+ -+typedef struct cnode -+{ -+ void *data; -+ struct cnode *next; -+}node, *Node; -+ -+typedef struct clist -+{ -+ Node head; -+ Node tail; -+ unsigned int size; -+ unsigned int data_size; -+ lpf0 add_back; -+ lpf0 add_front; -+ lpf1 delete_node; -+ lpf1 have_same; -+ lpf0 have_same_cmp; -+ lpf4 foreach; -+ lpf3 clear; -+ lpf2 destroy; -+ lpf5 modify_at; -+ lpf6 sort; -+ lpf7 delete_at; -+}list; -+ -+//初始化链表 -+List list_init(unsigned int data_size); -+int list_add_back(List l, void *data); -+int list_add_front(List l, void *data); -+int list_delete_node(List l, void *data, compare pfunc); -+int list_delete_at(List l, unsigned int index); -+int list_modify_at(List l, unsigned int index, void *new_data); -+int list_have_same(List l, void *data, compare pfunc); -+int list_have_same_cmp(List l, void *data); -+void list_foreach(List l, dofunc doit); -+void list_sort(List l, compare pfunc); -+void list_clear(List l); -+//释放链表 -+List list_destroy(List l); -+#endif -diff --git a/server/netutils.c b/server/netutils.c -new file mode 100644 -index 0000000..3a32b4d ---- /dev/null -+++ b/server/netutils.c -@@ -0,0 +1,297 @@ -+/* -+ * netutils.c - Network utilities -+ * -+ * Copyright (C) 2013 - 2016, Max Lv -+ * -+ * This file is part of the shadowsocks-libev. -+ * -+ * shadowsocks-libev is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * shadowsocks-libev 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 General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with shadowsocks-libev; see the file COPYING. If not, see -+ * . -+ */ -+ -+#include -+ -+#include -+#include -+ -+#ifdef HAVE_CONFIG_H -+#include "config.h" -+#endif -+ -+#ifdef __MINGW32__ -+#include "win32.h" -+#define sleep(n) Sleep(1000 * (n)) -+#else -+#include -+#include -+#include -+#include -+#endif -+ -+#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_NET_IF_H) && defined(__linux__) -+#include -+#include -+#define SET_INTERFACE -+#endif -+ -+#include "netutils.h" -+#include "utils.h" -+ -+#ifndef SO_REUSEPORT -+#define SO_REUSEPORT 15 -+#endif -+ -+extern int verbose; -+ -+static const char valid_label_bytes[] = -+ "-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"; -+ -+#if defined(MODULE_LOCAL) -+extern int keep_resolving; -+#endif -+ -+int -+set_reuseport(int socket) -+{ -+ int opt = 1; -+ return setsockopt(socket, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)); -+} -+ -+size_t -+get_sockaddr_len(struct sockaddr *addr) -+{ -+ if (addr->sa_family == AF_INET) { -+ return sizeof(struct sockaddr_in); -+ } else if (addr->sa_family == AF_INET6) { -+ return sizeof(struct sockaddr_in6); -+ } -+ return 0; -+} -+ -+#ifdef SET_INTERFACE -+int -+setinterface(int socket_fd, const char *interface_name) -+{ -+ struct ifreq interface; -+ memset(&interface, 0, sizeof(struct ifreq)); -+ strncpy(interface.ifr_name, interface_name, IFNAMSIZ); -+ int res = setsockopt(socket_fd, SOL_SOCKET, SO_BINDTODEVICE, &interface, -+ sizeof(struct ifreq)); -+ return res; -+} -+ -+#endif -+ -+int -+bind_to_address(int socket_fd, const char *host) -+{ -+ if (host != NULL) { -+ struct cork_ip ip; -+ struct sockaddr_storage storage; -+ memset(&storage, 0, sizeof(struct sockaddr_storage)); -+ if (cork_ip_init(&ip, host) != -1) { -+ if (ip.version == 4) { -+ struct sockaddr_in *addr = (struct sockaddr_in *)&storage; -+ dns_pton(AF_INET, host, &addr->sin_addr); -+ addr->sin_family = AF_INET; -+ return bind(socket_fd, (struct sockaddr *)addr, sizeof(struct sockaddr_in)); -+ } else if (ip.version == 6) { -+ struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&storage; -+ dns_pton(AF_INET6, host, &addr->sin6_addr); -+ addr->sin6_family = AF_INET6; -+ return bind(socket_fd, (struct sockaddr *)addr, sizeof(struct sockaddr_in6)); -+ } -+ } -+ } -+ return -1; -+} -+ -+ssize_t -+get_sockaddr(char *host, char *port, -+ struct sockaddr_storage *storage, int block, -+ int ipv6first) -+{ -+ struct cork_ip ip; -+ if (cork_ip_init(&ip, host) != -1) { -+ if (ip.version == 4) { -+ struct sockaddr_in *addr = (struct sockaddr_in *)storage; -+ addr->sin_family = AF_INET; -+ dns_pton(AF_INET, host, &(addr->sin_addr)); -+ if (port != NULL) { -+ addr->sin_port = htons(atoi(port)); -+ } -+ } else if (ip.version == 6) { -+ struct sockaddr_in6 *addr = (struct sockaddr_in6 *)storage; -+ addr->sin6_family = AF_INET6; -+ dns_pton(AF_INET6, host, &(addr->sin6_addr)); -+ if (port != NULL) { -+ addr->sin6_port = htons(atoi(port)); -+ } -+ } -+ return 0; -+ } else { -+ struct addrinfo hints; -+ struct addrinfo *result, *rp; -+ -+ memset(&hints, 0, sizeof(struct addrinfo)); -+ hints.ai_family = AF_UNSPEC; /* Return IPv4 and IPv6 choices */ -+ hints.ai_socktype = SOCK_STREAM; /* We want a TCP socket */ -+ -+ int err, i; -+ -+ for (i = 1; i < 8; i++) { -+ err = getaddrinfo(host, port, &hints, &result); -+#if defined(MODULE_LOCAL) -+ if (!keep_resolving) -+ break; -+#endif -+ if ((!block || !err)) { -+ break; -+ } else { -+ sleep(pow(2, i)); -+ LOGE("failed to resolve server name, wait %.0f seconds", pow(2, i)); -+ } -+ } -+ -+ if (err != 0) { -+ LOGE("getaddrinfo: %s", gai_strerror(err)); -+ return -1; -+ } -+ -+ int prefer_af = ipv6first ? AF_INET6 : AF_INET; -+ for (rp = result; rp != NULL; rp = rp->ai_next) -+ if (rp->ai_family == prefer_af) { -+ if (rp->ai_family == AF_INET) -+ memcpy(storage, rp->ai_addr, sizeof(struct sockaddr_in)); -+ else if (rp->ai_family == AF_INET6) -+ memcpy(storage, rp->ai_addr, sizeof(struct sockaddr_in6)); -+ break; -+ } -+ -+ if (rp == NULL) { -+ for (rp = result; rp != NULL; rp = rp->ai_next) { -+ if (rp->ai_family == AF_INET) -+ memcpy(storage, rp->ai_addr, sizeof(struct sockaddr_in)); -+ else if (rp->ai_family == AF_INET6) -+ memcpy(storage, rp->ai_addr, sizeof(struct sockaddr_in6)); -+ break; -+ } -+ } -+ -+ if (rp == NULL) { -+ LOGE("failed to resolve remote addr"); -+ return -1; -+ } -+ -+ freeaddrinfo(result); -+ return 0; -+ } -+ -+ return -1; -+} -+ -+int -+sockaddr_cmp(struct sockaddr_storage *addr1, -+ struct sockaddr_storage *addr2, socklen_t len) -+{ -+ struct sockaddr_in *p1_in = (struct sockaddr_in *)addr1; -+ struct sockaddr_in *p2_in = (struct sockaddr_in *)addr2; -+ struct sockaddr_in6 *p1_in6 = (struct sockaddr_in6 *)addr1; -+ struct sockaddr_in6 *p2_in6 = (struct sockaddr_in6 *)addr2; -+ if (p1_in->sin_family < p2_in->sin_family) -+ return -1; -+ if (p1_in->sin_family > p2_in->sin_family) -+ return 1; -+ /* compare ip4 */ -+ if (p1_in->sin_family == AF_INET) { -+ /* just order it, ntohs not required */ -+ if (p1_in->sin_port < p2_in->sin_port) -+ return -1; -+ if (p1_in->sin_port > p2_in->sin_port) -+ return 1; -+ return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE); -+ } else if (p1_in6->sin6_family == AF_INET6) { -+ /* just order it, ntohs not required */ -+ if (p1_in6->sin6_port < p2_in6->sin6_port) -+ return -1; -+ if (p1_in6->sin6_port > p2_in6->sin6_port) -+ return 1; -+ return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr, -+ INET6_SIZE); -+ } else { -+ /* eek unknown type, perform this comparison for sanity. */ -+ return memcmp(addr1, addr2, len); -+ } -+} -+ -+int -+sockaddr_cmp_addr(struct sockaddr_storage *addr1, -+ struct sockaddr_storage *addr2, socklen_t len) -+{ -+ struct sockaddr_in *p1_in = (struct sockaddr_in *)addr1; -+ struct sockaddr_in *p2_in = (struct sockaddr_in *)addr2; -+ struct sockaddr_in6 *p1_in6 = (struct sockaddr_in6 *)addr1; -+ struct sockaddr_in6 *p2_in6 = (struct sockaddr_in6 *)addr2; -+ if (p1_in->sin_family < p2_in->sin_family) -+ return -1; -+ if (p1_in->sin_family > p2_in->sin_family) -+ return 1; -+ /* compare ip4 */ -+ if (p1_in->sin_family == AF_INET) { -+ return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE); -+ } else if (p1_in6->sin6_family == AF_INET6) { -+ return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr, -+ INET6_SIZE); -+ } else { -+ /* eek unknown type, perform this comparison for sanity. */ -+ return memcmp(addr1, addr2, len); -+ } -+} -+ -+int -+validate_hostname(const char *hostname, const int hostname_len) -+{ -+ if (hostname == NULL) -+ return 0; -+ -+ if (hostname_len < 1 || hostname_len > 255) -+ return 0; -+ -+ if (hostname[0] == '.') -+ return 0; -+ -+ const char *label = hostname; -+ while (label < hostname + hostname_len) { -+ size_t label_len = hostname_len - (label - hostname); -+ char *next_dot = strchr(label, '.'); -+ if (next_dot != NULL) -+ label_len = next_dot - label; -+ -+ if (label + label_len > hostname + hostname_len) -+ return 0; -+ -+ if (label_len > 63 || label_len < 1) -+ return 0; -+ -+ if (label[0] == '-' || label[label_len - 1] == '-') -+ return 0; -+ -+ if (strspn(label, valid_label_bytes) < label_len) -+ return 0; -+ -+ label += label_len + 1; -+ } -+ -+ return 1; -+} -diff --git a/server/netutils.h b/server/netutils.h -new file mode 100644 -index 0000000..0725592 ---- /dev/null -+++ b/server/netutils.h -@@ -0,0 +1,98 @@ -+/* -+ * netutils.h - Network utilities -+ * -+ * Copyright (C) 2013 - 2016, Max Lv -+ * -+ * This file is part of the shadowsocks-libev. -+ * -+ * shadowsocks-libev is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * shadowsocks-libev 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 General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with shadowsocks-libev; see the file COPYING. If not, see -+ * . -+ */ -+ -+#ifndef _NETUTILS_H -+#define _NETUTILS_H -+ -+#if defined(__linux__) -+#include -+#elif !defined(__MINGW32__) -+#include -+#endif -+ -+// only enable TCP_FASTOPEN on linux -+#if defined(__linux__) -+#include -+/* conditional define for TCP_FASTOPEN */ -+#ifndef TCP_FASTOPEN -+#define TCP_FASTOPEN 23 -+#endif -+/* conditional define for MSG_FASTOPEN */ -+#ifndef MSG_FASTOPEN -+#define MSG_FASTOPEN 0x20000000 -+#endif -+#elif !defined(__APPLE__) -+#ifdef TCP_FASTOPEN -+#undef TCP_FASTOPEN -+#endif -+#endif -+ -+/* Backward compatibility for MPTCP_ENABLED between kernel 3 & 4 */ -+#ifndef MPTCP_ENABLED -+#ifdef TCP_CC_INFO -+#define MPTCP_ENABLED 42 -+#else -+#define MPTCP_ENABLED 26 -+#endif -+#endif -+ -+/** byte size of ip4 address */ -+#define INET_SIZE 4 -+/** byte size of ip6 address */ -+#define INET6_SIZE 16 -+ -+size_t get_sockaddr_len(struct sockaddr *addr); -+ssize_t get_sockaddr(char *host, char *port, -+ struct sockaddr_storage *storage, int block, -+ int ipv6first); -+int set_reuseport(int socket); -+ -+#ifdef SET_INTERFACE -+int setinterface(int socket_fd, const char *interface_name); -+#endif -+ -+int bind_to_address(int socket_fd, const char *address); -+ -+/** -+ * Compare two sockaddrs. Imposes an ordering on the addresses. -+ * Compares address and port. -+ * @param addr1: address 1. -+ * @param addr2: address 2. -+ * @param len: lengths of addr. -+ * @return: 0 if addr1 == addr2. -1 if addr1 is smaller, +1 if larger. -+ */ -+int sockaddr_cmp(struct sockaddr_storage *addr1, -+ struct sockaddr_storage *addr2, socklen_t len); -+ -+/** -+ * Compare two sockaddrs. Compares address, not the port. -+ * @param addr1: address 1. -+ * @param addr2: address 2. -+ * @param len: lengths of addr. -+ * @return: 0 if addr1 == addr2. -1 if addr1 is smaller, +1 if larger. -+ */ -+int sockaddr_cmp_addr(struct sockaddr_storage *addr1, -+ struct sockaddr_storage *addr2, socklen_t len); -+ -+int validate_hostname(const char *hostname, const int hostname_len); -+ -+#endif -diff --git a/server/obfs.c b/server/obfs.c -new file mode 100644 -index 0000000..5c885bf ---- /dev/null -+++ b/server/obfs.c -@@ -0,0 +1,205 @@ -+#include -+#include -+ -+#include "utils.h" -+#include "obfs.h" -+ -+int rand_bytes(uint8_t *output, int len); -+#define OBFS_HMAC_SHA1_LEN 10 -+ -+#include "obfsutil.c" -+#include "crc32.c" -+#include "base64.c" -+#include "http_simple.c" -+#include "tls1.2_ticket.c" -+#include "verify.c" -+#include "auth.c" -+ -+void * init_data() { -+ return malloc(1); -+} -+ -+obfs * new_obfs() { -+ obfs * self = (obfs*)malloc(sizeof(obfs)); -+ self->l_data = NULL; -+ return self; -+} -+ -+void set_server_info(obfs *self, server_info *server) { -+ memmove(&self->server, server, sizeof(server_info)); -+} -+ -+void get_server_info(obfs *self, server_info *server) { -+ memmove(server, &self->server, sizeof(server_info)); -+} -+ -+void dispose_obfs(obfs *self) { -+ free(self); -+} -+ -+obfs_class * new_obfs_class(char *plugin_name) -+{ -+ if (plugin_name == NULL) -+ return NULL; -+ if (strcmp(plugin_name, "origin") == 0) -+ return NULL; -+ if (strcmp(plugin_name, "plain") == 0) -+ return NULL; -+ init_crc32_table(); -+ init_shift128plus(); -+ if (strcmp(plugin_name, "http_simple") == 0) { -+ obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs)); -+ plugin->init_data = init_data; -+ plugin->new_obfs = http_simple_new_obfs; -+ plugin->get_server_info = get_server_info; -+ plugin->set_server_info = set_server_info; -+ plugin->dispose = http_simple_dispose; -+ -+ plugin->client_encode = http_simple_client_encode; -+ plugin->client_decode = http_simple_client_decode; -+ -+ plugin->server_encode = http_simple_server_encode; -+ plugin->server_decode = http_simple_server_decode; -+ -+ return plugin; -+ } else if (strcmp(plugin_name, "http_post") == 0) { -+ obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs)); -+ plugin->init_data = init_data; -+ plugin->new_obfs = http_simple_new_obfs; -+ plugin->get_server_info = get_server_info; -+ plugin->set_server_info = set_server_info; -+ plugin->dispose = http_simple_dispose; -+ -+ plugin->client_encode = http_post_client_encode; -+ plugin->client_decode = http_simple_client_decode; -+ -+ plugin->server_encode = http_simple_server_encode; -+ plugin->server_decode = http_simple_server_decode; -+ -+ return plugin; -+ } else if (strcmp(plugin_name, "tls1.2_ticket_auth") == 0) { -+ obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs)); -+ plugin->init_data = tls12_ticket_auth_init_data; -+ plugin->new_obfs = tls12_ticket_auth_new_obfs; -+ plugin->get_server_info = get_server_info; -+ plugin->set_server_info = set_server_info; -+ plugin->dispose = tls12_ticket_auth_dispose; -+ -+ plugin->client_encode = tls12_ticket_auth_client_encode; -+ plugin->client_decode = tls12_ticket_auth_client_decode; -+ -+ plugin->server_encode = tls12_ticket_auth_server_encode; -+ plugin->server_decode = tls12_ticket_auth_server_decode; -+ -+ return plugin; -+ } else if (strcmp(plugin_name, "verify_simple") == 0) { -+ obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs)); -+ plugin->init_data = init_data; -+ plugin->new_obfs = verify_simple_new_obfs; -+ plugin->get_server_info = get_server_info; -+ plugin->set_server_info = set_server_info; -+ plugin->dispose = verify_simple_dispose; -+ -+ plugin->client_pre_encrypt = verify_simple_client_pre_encrypt; -+ plugin->client_post_decrypt = verify_simple_client_post_decrypt; -+ plugin->client_udp_pre_encrypt = NULL; -+ plugin->client_udp_post_decrypt = NULL; -+ -+ plugin->server_pre_encrypt = verify_simple_server_pre_encrypt; -+ plugin->server_post_decrypt = verify_simple_server_post_decrypt; -+ plugin->server_udp_pre_encrypt = NULL; -+ plugin->server_udp_post_decrypt = NULL; -+ -+ return plugin; -+ } else if (strcmp(plugin_name, "auth_simple") == 0) { -+ obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs)); -+ plugin->init_data = auth_simple_init_data; -+ plugin->new_obfs = auth_simple_new_obfs; -+ plugin->get_server_info = get_server_info; -+ plugin->set_server_info = set_server_info; -+ plugin->dispose = auth_simple_dispose; -+ -+ plugin->client_pre_encrypt = auth_simple_client_pre_encrypt; -+ plugin->client_post_decrypt = auth_simple_client_post_decrypt; -+ plugin->client_udp_pre_encrypt = NULL; -+ plugin->client_udp_post_decrypt = NULL; -+ -+ return plugin; -+ } else if (strcmp(plugin_name, "auth_sha1") == 0) { -+ obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs)); -+ plugin->init_data = auth_simple_init_data; -+ plugin->new_obfs = auth_simple_new_obfs; -+ plugin->get_server_info = get_server_info; -+ plugin->set_server_info = set_server_info; -+ plugin->dispose = auth_simple_dispose; -+ -+ plugin->client_pre_encrypt = auth_sha1_client_pre_encrypt; -+ plugin->client_post_decrypt = auth_sha1_client_post_decrypt; -+ plugin->client_udp_pre_encrypt = NULL; -+ plugin->client_udp_post_decrypt = NULL; -+ -+ return plugin; -+ } else if (strcmp(plugin_name, "auth_sha1_v2") == 0) { -+ obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs)); -+ plugin->init_data = auth_simple_init_data; -+ plugin->new_obfs = auth_simple_new_obfs; -+ plugin->get_server_info = get_server_info; -+ plugin->set_server_info = set_server_info; -+ plugin->dispose = auth_simple_dispose; -+ -+ plugin->client_pre_encrypt = auth_sha1_v2_client_pre_encrypt; -+ plugin->client_post_decrypt = auth_sha1_v2_client_post_decrypt; -+ plugin->client_udp_pre_encrypt = NULL; -+ plugin->client_udp_post_decrypt = NULL; -+ -+ return plugin; -+ } else if (strcmp(plugin_name, "auth_sha1_v4") == 0) { -+ obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs)); -+ plugin->init_data = auth_simple_init_data; -+ plugin->new_obfs = auth_simple_new_obfs; -+ plugin->get_server_info = get_server_info; -+ plugin->set_server_info = set_server_info; -+ plugin->dispose = auth_simple_dispose; -+ -+ plugin->client_pre_encrypt = auth_sha1_v4_client_pre_encrypt; -+ plugin->client_post_decrypt = auth_sha1_v4_client_post_decrypt; -+ plugin->client_udp_pre_encrypt = NULL; -+ plugin->client_udp_post_decrypt = NULL; -+ -+ return plugin; -+ } else if (strcmp(plugin_name, "auth_aes128_md5") == 0) { -+ obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs)); -+ plugin->init_data = auth_simple_init_data; -+ plugin->new_obfs = auth_aes128_md5_new_obfs; -+ plugin->get_server_info = get_server_info; -+ plugin->set_server_info = set_server_info; -+ plugin->dispose = auth_simple_dispose; -+ -+ plugin->client_pre_encrypt = auth_aes128_sha1_client_pre_encrypt; -+ plugin->client_post_decrypt = auth_aes128_sha1_client_post_decrypt; -+ plugin->client_udp_pre_encrypt = auth_aes128_sha1_client_udp_pre_encrypt; -+ plugin->client_udp_post_decrypt = auth_aes128_sha1_client_udp_post_decrypt; -+ -+ return plugin; -+ } else if (strcmp(plugin_name, "auth_aes128_sha1") == 0) { -+ obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs)); -+ plugin->init_data = auth_simple_init_data; -+ plugin->new_obfs = auth_aes128_sha1_new_obfs; -+ plugin->get_server_info = get_server_info; -+ plugin->set_server_info = set_server_info; -+ plugin->dispose = auth_simple_dispose; -+ -+ plugin->client_pre_encrypt = auth_aes128_sha1_client_pre_encrypt; -+ plugin->client_post_decrypt = auth_aes128_sha1_client_post_decrypt; -+ plugin->client_udp_pre_encrypt = auth_aes128_sha1_client_udp_pre_encrypt; -+ plugin->client_udp_post_decrypt = auth_aes128_sha1_client_udp_post_decrypt; -+ -+ return plugin; -+ } -+ LOGE("Load obfs '%s' failed", plugin_name); -+ return NULL; -+} -+ -+void free_obfs_class(obfs_class *plugin) { -+ free(plugin); -+} -diff --git a/server/obfs.h b/server/obfs.h -new file mode 100644 -index 0000000..74c60c9 ---- /dev/null -+++ b/server/obfs.h -@@ -0,0 +1,100 @@ -+/* -+ * obfs.h - Define shadowsocksR server's buffers and callbacks -+ * -+ * Copyright (C) 2015 - 2016, Break Wa11 -+ */ -+ -+#ifndef _OBFS_H -+#define _OBFS_H -+ -+#include -+#include -+ -+typedef struct server_info { -+ char host[64]; -+ uint16_t port; -+ char *param; -+ void *g_data; -+ uint8_t *iv; -+ size_t iv_len; -+ uint8_t *recv_iv; -+ size_t recv_iv_len; -+ uint8_t *key; -+ size_t key_len; -+ int head_len; -+ size_t tcp_mss; -+}server_info; -+ -+typedef struct obfs { -+ server_info server; -+ void *l_data; -+}obfs; -+ -+typedef struct obfs_class { -+ void * (*init_data)(); -+ obfs * (*new_obfs)(); -+ void (*get_server_info)(obfs *self, server_info *server); -+ void (*set_server_info)(obfs *self, server_info *server); -+ void (*dispose)(obfs *self); -+ -+ int (*client_pre_encrypt)(obfs *self, -+ char **pplaindata, -+ int datalength, -+ size_t* capacity); -+ int (*client_encode)(obfs *self, -+ char **pencryptdata, -+ int datalength, -+ size_t* capacity); -+ int (*client_decode)(obfs *self, -+ char **pencryptdata, -+ int datalength, -+ size_t* capacity, -+ int *needsendback); -+ int (*client_post_decrypt)(obfs *self, -+ char **pplaindata, -+ int datalength, -+ size_t* capacity); -+ int (*client_udp_pre_encrypt)(obfs *self, -+ char **pplaindata, -+ int datalength, -+ size_t* capacity); -+ int (*client_udp_post_decrypt)(obfs *self, -+ char **pplaindata, -+ int datalength, -+ size_t* capacity); -+ int (*server_pre_encrypt)(obfs *self, -+ char **pplaindata, -+ int datalength, -+ size_t* capacity); -+ int (*server_post_decrypt)(obfs *self, -+ char **pplaindata, -+ int datalength, -+ size_t* capacity); -+ int (*server_udp_pre_encrypt)(obfs *self, -+ char **pplaindata, -+ int datalength, -+ size_t* capacity); -+ int (*server_udp_post_decrypt)(obfs *self, -+ char **pplaindata, -+ int datalength, -+ size_t* capacity); -+ int (*server_encode)(obfs *self, -+ char **pencryptdata, -+ int datalength, -+ size_t* capacity); -+ int (*server_decode)(obfs *self, -+ char **pencryptdata, -+ int datalength, -+ size_t* capacity, -+ int *needsendback); -+}obfs_class; -+ -+obfs_class * new_obfs_class(char *plugin_name); -+void free_obfs_class(obfs_class *plugin); -+ -+void set_server_info(obfs *self, server_info *server); -+void get_server_info(obfs *self, server_info *server); -+obfs * new_obfs(); -+void dispose_obfs(obfs *self); -+ -+#endif // _OBFS_H -diff --git a/server/obfsutil.c b/server/obfsutil.c -new file mode 100644 -index 0000000..d00959b ---- /dev/null -+++ b/server/obfsutil.c -@@ -0,0 +1,36 @@ -+int get_head_size(char *plaindata, int size, int def_size) { -+ if (plaindata == NULL || size < 2) -+ return def_size; -+ int head_type = plaindata[0] & 0x7; -+ if (head_type == 1) -+ return 7; -+ if (head_type == 4) -+ return 19; -+ if (head_type == 3) -+ return 4 + plaindata[1]; -+ return def_size; -+} -+ -+static int shift128plus_init_flag = 0; -+static uint64_t shift128plus_s[2] = {0x10000000, 0xFFFFFFFF}; -+ -+void init_shift128plus(void) { -+ if (shift128plus_init_flag == 0) { -+ shift128plus_init_flag = 1; -+ uint32_t seed = time(NULL); -+ shift128plus_s[0] = seed | 0x100000000L; -+ shift128plus_s[1] = ((uint64_t)seed << 32) | 0x1; -+ } -+} -+ -+uint64_t xorshift128plus(void) { -+ uint64_t x = shift128plus_s[0]; -+ uint64_t const y = shift128plus_s[1]; -+ shift128plus_s[0] = y; -+ x ^= x << 23; // a -+ x ^= x >> 17; // b -+ x ^= y ^ (y >> 26); // c -+ shift128plus_s[1] = x; -+ return x + y; -+} -+ -diff --git a/server/protocol.h b/server/protocol.h -new file mode 100644 -index 0000000..eaa866e ---- /dev/null -+++ b/server/protocol.h -@@ -0,0 +1,34 @@ -+/* -+ * Copyright (c) 2014, Dustin Lundquist -+ * 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 HOLDER 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. -+ */ -+#ifndef PROTOCOL_H -+#define PROTOCOL_H -+ -+typedef struct protocol { -+ const int default_port; -+ int(*const parse_packet)(const char *, size_t, char **); -+} protocol_t; -+ -+#endif -diff --git a/server/resolv.c b/server/resolv.c -new file mode 100644 -index 0000000..f580d06 ---- /dev/null -+++ b/server/resolv.c -@@ -0,0 +1,444 @@ -+/* -+ * Copyright (c) 2014, Dustin Lundquist -+ * 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 HOLDER 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. -+ */ -+ -+#ifdef HAVE_CONFIG_H -+#include "config.h" -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef __MINGW32__ -+#include "win32.h" -+#else -+#include -+#include -+#include -+#include -+#endif -+ -+#include "resolv.h" -+#include "utils.h" -+#include "netutils.h" -+ -+/* -+ * Implement DNS resolution interface using libudns -+ */ -+ -+struct ResolvQuery { -+ void (*client_cb)(struct sockaddr *, void *); -+ void (*client_free_cb)(void *); -+ void *client_cb_data; -+ struct dns_query *queries[2]; -+ size_t response_count; -+ struct sockaddr **responses; -+ uint16_t port; -+}; -+ -+extern int verbose; -+ -+static struct ev_io resolv_io_watcher; -+static struct ev_timer resolv_timeout_watcher; -+static const int MODE_IPV4_ONLY = 0; -+static const int MODE_IPV6_ONLY = 1; -+static const int MODE_IPV4_FIRST = 2; -+static const int MODE_IPV6_FIRST = 3; -+static int resolv_mode = 0; -+ -+static void resolv_sock_cb(struct ev_loop *, struct ev_io *, int); -+static void resolv_timeout_cb(struct ev_loop *, struct ev_timer *, int); -+static void dns_query_v4_cb(struct dns_ctx *, struct dns_rr_a4 *, void *); -+static void dns_query_v6_cb(struct dns_ctx *, struct dns_rr_a6 *, void *); -+static void dns_timer_setup_cb(struct dns_ctx *, int, void *); -+static void process_client_callback(struct ResolvQuery *); -+static inline int all_queries_are_null(struct ResolvQuery *); -+static struct sockaddr *choose_ipv4_first(struct ResolvQuery *); -+static struct sockaddr *choose_ipv6_first(struct ResolvQuery *); -+static struct sockaddr *choose_any(struct ResolvQuery *); -+ -+int -+resolv_init(struct ev_loop *loop, char **nameservers, int nameserver_num, int ipv6first) -+{ -+ if (ipv6first) -+ resolv_mode = MODE_IPV6_FIRST; -+ else -+ resolv_mode = MODE_IPV4_FIRST; -+ -+ struct dns_ctx *ctx = &dns_defctx; -+ if (nameservers == NULL) { -+ /* Nameservers not specified, use system resolver config */ -+ dns_init(ctx, 0); -+ } else { -+ dns_reset(ctx); -+ -+ for (int i = 0; i < nameserver_num; i++) { -+ char *server = nameservers[i]; -+ dns_add_serv(ctx, server); -+ } -+ } -+ -+ int sockfd = dns_open(ctx); -+ if (sockfd < 0) { -+ FATAL("Failed to open DNS resolver socket"); -+ } -+ -+ if (nameserver_num == 1 && nameservers != NULL) { -+ if (strncmp("127.0.0.1", nameservers[0], 9) == 0 -+ || strncmp("::1", nameservers[0], 3) == 0) { -+ if (verbose) { -+ LOGI("bind UDP resolver to %s", nameservers[0]); -+ } -+ if (bind_to_address(sockfd, nameservers[0]) == -1) -+ ERROR("bind_to_address"); -+ } -+ } -+ -+#ifdef __MINGW32__ -+ setnonblocking(sockfd); -+#else -+ int flags = fcntl(sockfd, F_GETFL, 0); -+ fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); -+#endif -+ -+ ev_io_init(&resolv_io_watcher, resolv_sock_cb, sockfd, EV_READ); -+ resolv_io_watcher.data = ctx; -+ -+ ev_io_start(loop, &resolv_io_watcher); -+ -+ ev_timer_init(&resolv_timeout_watcher, resolv_timeout_cb, 0.0, 0.0); -+ resolv_timeout_watcher.data = ctx; -+ -+ dns_set_tmcbck(ctx, dns_timer_setup_cb, loop); -+ -+ return sockfd; -+} -+ -+void -+resolv_shutdown(struct ev_loop *loop) -+{ -+ struct dns_ctx *ctx = (struct dns_ctx *)resolv_io_watcher.data; -+ -+ ev_io_stop(loop, &resolv_io_watcher); -+ -+ if (ev_is_active(&resolv_timeout_watcher)) { -+ ev_timer_stop(loop, &resolv_timeout_watcher); -+ } -+ -+ dns_close(ctx); -+} -+ -+struct ResolvQuery * -+resolv_query(const char *hostname, void (*client_cb)(struct sockaddr *, void *), -+ void (*client_free_cb)(void *), void *client_cb_data, -+ uint16_t port) -+{ -+ struct dns_ctx *ctx = (struct dns_ctx *)resolv_io_watcher.data; -+ -+ /* -+ * Wrap udns's call back in our own -+ */ -+ struct ResolvQuery *cb_data = ss_malloc(sizeof(struct ResolvQuery)); -+ if (cb_data == NULL) { -+ LOGE("Failed to allocate memory for DNS query callback data."); -+ return NULL; -+ } -+ memset(cb_data, 0, sizeof(struct ResolvQuery)); -+ -+ cb_data->client_cb = client_cb; -+ cb_data->client_free_cb = client_free_cb; -+ cb_data->client_cb_data = client_cb_data; -+ memset(cb_data->queries, 0, sizeof(cb_data->queries)); -+ cb_data->response_count = 0; -+ cb_data->responses = NULL; -+ cb_data->port = port; -+ -+ /* Submit A and AAAA queries */ -+ if (resolv_mode != MODE_IPV6_ONLY) { -+ cb_data->queries[0] = dns_submit_a4(ctx, -+ hostname, 0, -+ dns_query_v4_cb, cb_data); -+ if (cb_data->queries[0] == NULL) { -+ LOGE("Failed to submit DNS query: %s", -+ dns_strerror(dns_status(ctx))); -+ } -+ } -+ -+ if (resolv_mode != MODE_IPV4_ONLY) { -+ cb_data->queries[1] = dns_submit_a6(ctx, -+ hostname, 0, -+ dns_query_v6_cb, cb_data); -+ if (cb_data->queries[1] == NULL) { -+ LOGE("Failed to submit DNS query: %s", -+ dns_strerror(dns_status(ctx))); -+ } -+ } -+ -+ if (all_queries_are_null(cb_data)) { -+ if (cb_data->client_free_cb != NULL) { -+ cb_data->client_free_cb(cb_data->client_cb_data); -+ } -+ ss_free(cb_data); -+ } -+ -+ return cb_data; -+} -+ -+void -+resolv_cancel(struct ResolvQuery *query_handle) -+{ -+ struct ResolvQuery *cb_data = (struct ResolvQuery *)query_handle; -+ struct dns_ctx *ctx = (struct dns_ctx *)resolv_io_watcher.data; -+ -+ for (int i = 0; i < sizeof(cb_data->queries) / sizeof(cb_data->queries[0]); -+ i++) -+ if (cb_data->queries[i] != NULL) { -+ dns_cancel(ctx, cb_data->queries[i]); -+ ss_free(cb_data->queries[i]); -+ } -+ -+ if (cb_data->client_free_cb != NULL) { -+ cb_data->client_free_cb(cb_data->client_cb_data); -+ } -+ -+ ss_free(cb_data); -+} -+ -+/* -+ * DNS UDP socket activity callback -+ */ -+static void -+resolv_sock_cb(struct ev_loop *loop, struct ev_io *w, int revents) -+{ -+ struct dns_ctx *ctx = (struct dns_ctx *)w->data; -+ -+ if (revents & EV_READ) { -+ dns_ioevent(ctx, ev_now(loop)); -+ } -+} -+ -+/* -+ * Wrapper for client callback we provide to udns -+ */ -+static void -+dns_query_v4_cb(struct dns_ctx *ctx, struct dns_rr_a4 *result, void *data) -+{ -+ struct ResolvQuery *cb_data = (struct ResolvQuery *)data; -+ -+ if (result == NULL) { -+ if (verbose) { -+ LOGI("IPv4 resolv: %s", dns_strerror(dns_status(ctx))); -+ } -+ } else if (result->dnsa4_nrr > 0) { -+ struct sockaddr **new_responses = ss_realloc(cb_data->responses, -+ (cb_data->response_count + -+ result->dnsa4_nrr) * -+ sizeof(struct sockaddr *)); -+ if (new_responses == NULL) { -+ LOGE("Failed to allocate memory for additional DNS responses"); -+ } else { -+ cb_data->responses = new_responses; -+ -+ for (int i = 0; i < result->dnsa4_nrr; i++) { -+ struct sockaddr_in *sa = -+ (struct sockaddr_in *)ss_malloc(sizeof(struct sockaddr_in)); -+ sa->sin_family = AF_INET; -+ sa->sin_port = cb_data->port; -+ sa->sin_addr = result->dnsa4_addr[i]; -+ -+ cb_data->responses[cb_data->response_count] = -+ (struct sockaddr *)sa; -+ if (cb_data->responses[cb_data->response_count] == NULL) { -+ LOGE( -+ "Failed to allocate memory for DNS query result address"); -+ } else { -+ cb_data->response_count++; -+ } -+ } -+ } -+ } -+ -+ ss_free(result); -+ cb_data->queries[0] = NULL; /* mark A query as being completed */ -+ -+ /* Once all queries have completed, call client callback */ -+ if (all_queries_are_null(cb_data)) { -+ return process_client_callback(cb_data); -+ } -+} -+ -+static void -+dns_query_v6_cb(struct dns_ctx *ctx, struct dns_rr_a6 *result, void *data) -+{ -+ struct ResolvQuery *cb_data = (struct ResolvQuery *)data; -+ -+ if (result == NULL) { -+ if (verbose) { -+ LOGI("IPv6 resolv: %s", dns_strerror(dns_status(ctx))); -+ } -+ } else if (result->dnsa6_nrr > 0) { -+ struct sockaddr **new_responses = ss_realloc(cb_data->responses, -+ (cb_data->response_count + -+ result->dnsa6_nrr) * -+ sizeof(struct sockaddr *)); -+ if (new_responses == NULL) { -+ LOGE("Failed to allocate memory for additional DNS responses"); -+ } else { -+ cb_data->responses = new_responses; -+ -+ for (int i = 0; i < result->dnsa6_nrr; i++) { -+ struct sockaddr_in6 *sa = -+ (struct sockaddr_in6 *)ss_malloc(sizeof(struct sockaddr_in6)); -+ sa->sin6_family = AF_INET6; -+ sa->sin6_port = cb_data->port; -+ sa->sin6_addr = result->dnsa6_addr[i]; -+ -+ cb_data->responses[cb_data->response_count] = -+ (struct sockaddr *)sa; -+ if (cb_data->responses[cb_data->response_count] == NULL) { -+ LOGE( -+ "Failed to allocate memory for DNS query result address"); -+ } else { -+ cb_data->response_count++; -+ } -+ } -+ } -+ } -+ -+ ss_free(result); -+ cb_data->queries[1] = NULL; /* mark AAAA query as being completed */ -+ -+ /* Once all queries have completed, call client callback */ -+ if (all_queries_are_null(cb_data)) { -+ return process_client_callback(cb_data); -+ } -+} -+ -+/* -+ * Called once all queries have been completed -+ */ -+static void -+process_client_callback(struct ResolvQuery *cb_data) -+{ -+ struct sockaddr *best_address = NULL; -+ -+ if (resolv_mode == MODE_IPV4_FIRST) { -+ best_address = choose_ipv4_first(cb_data); -+ } else if (resolv_mode == MODE_IPV6_FIRST) { -+ best_address = choose_ipv6_first(cb_data); -+ } else { -+ best_address = choose_any(cb_data); -+ } -+ -+ cb_data->client_cb(best_address, cb_data->client_cb_data); -+ -+ for (int i = 0; i < cb_data->response_count; i++) -+ ss_free(cb_data->responses[i]); -+ -+ ss_free(cb_data->responses); -+ if (cb_data->client_free_cb != NULL) { -+ cb_data->client_free_cb(cb_data->client_cb_data); -+ } -+ ss_free(cb_data); -+} -+ -+static struct sockaddr * -+choose_ipv4_first(struct ResolvQuery *cb_data) -+{ -+ for (int i = 0; i < cb_data->response_count; i++) -+ if (cb_data->responses[i]->sa_family == AF_INET) { -+ return cb_data->responses[i]; -+ } -+ -+ return choose_any(cb_data); -+} -+ -+static struct sockaddr * -+choose_ipv6_first(struct ResolvQuery *cb_data) -+{ -+ for (int i = 0; i < cb_data->response_count; i++) -+ if (cb_data->responses[i]->sa_family == AF_INET6) { -+ return cb_data->responses[i]; -+ } -+ -+ return choose_any(cb_data); -+} -+ -+static struct sockaddr * -+choose_any(struct ResolvQuery *cb_data) -+{ -+ if (cb_data->response_count >= 1) { -+ return cb_data->responses[0]; -+ } -+ -+ return NULL; -+} -+ -+/* -+ * DNS timeout callback -+ */ -+static void -+resolv_timeout_cb(struct ev_loop *loop, struct ev_timer *w, int revents) -+{ -+ struct dns_ctx *ctx = (struct dns_ctx *)w->data; -+ -+ if (revents & EV_TIMER) { -+ dns_timeouts(ctx, 30, ev_now(loop)); -+ } -+} -+ -+/* -+ * Callback to setup DNS timeout callback -+ */ -+static void -+dns_timer_setup_cb(struct dns_ctx *ctx, int timeout, void *data) -+{ -+ struct ev_loop *loop = (struct ev_loop *)data; -+ -+ if (ev_is_active(&resolv_timeout_watcher)) { -+ ev_timer_stop(loop, &resolv_timeout_watcher); -+ } -+ -+ if (ctx != NULL && timeout >= 0) { -+ ev_timer_set(&resolv_timeout_watcher, timeout, 0.0); -+ ev_timer_start(loop, &resolv_timeout_watcher); -+ } -+} -+ -+static inline int -+all_queries_are_null(struct ResolvQuery *cb_data) -+{ -+ int result = 1; -+ -+ for (int i = 0; i < sizeof(cb_data->queries) / sizeof(cb_data->queries[0]); -+ i++) -+ result = result && cb_data->queries[i] == NULL; -+ -+ return result; -+} -diff --git a/server/resolv.h b/server/resolv.h -new file mode 100644 -index 0000000..0552922 ---- /dev/null -+++ b/server/resolv.h -@@ -0,0 +1,50 @@ -+/* -+ * Copyright (c) 2014, Dustin Lundquist -+ * 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 HOLDER 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. -+ */ -+#ifndef RESOLV_H -+#define RESOLV_H -+ -+#ifdef HAVE_CONFIG_H -+#include "config.h" -+#endif -+ -+#include -+ -+#ifdef __MINGW32__ -+#include "win32.h" -+#else -+#include -+#endif -+ -+struct ResolvQuery; -+ -+int resolv_init(struct ev_loop *, char **, int, int); -+struct ResolvQuery *resolv_query(const char *, void (*)(struct sockaddr *, -+ void *), void (*)( -+ void *), void *, uint16_t); -+void resolv_cancel(struct ResolvQuery *); -+void resolv_shutdown(struct ev_loop *); -+ -+#endif -diff --git a/server/rule.c b/server/rule.c -new file mode 100644 -index 0000000..8aae04e ---- /dev/null -+++ b/server/rule.c -@@ -0,0 +1,137 @@ -+/* -+ * Copyright (c) 2011 and 2012, Dustin Lundquist -+ * Copyright (c) 2011 Manuel Kasper -+ * 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 HOLDER 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. -+ */ -+ -+#ifdef HAVE_CONFIG_H -+#include "config.h" -+#endif -+ -+#include -+#include -+ -+#ifdef __MINGW32__ -+extern void ss_error(const char *s); -+#endif -+ -+#include "rule.h" -+#include "utils.h" -+ -+static void free_rule(rule_t *); -+ -+rule_t * -+new_rule() -+{ -+ rule_t *rule; -+ -+ rule = calloc(1, sizeof(rule_t)); -+ if (rule == NULL) { -+ ERROR("malloc"); -+ return NULL; -+ } -+ -+ return rule; -+} -+ -+int -+accept_rule_arg(rule_t *rule, const char *arg) -+{ -+ if (rule->pattern == NULL) { -+ rule->pattern = strdup(arg); -+ if (rule->pattern == NULL) { -+ ERROR("strdup failed"); -+ return -1; -+ } -+ } else { -+ LOGE("Unexpected table rule argument: %s", arg); -+ return -1; -+ } -+ -+ return 1; -+} -+ -+void -+add_rule(struct cork_dllist *rules, rule_t *rule) -+{ -+ cork_dllist_add(rules, &rule->entries); -+} -+ -+int -+init_rule(rule_t *rule) -+{ -+ if (rule->pattern_re == NULL) { -+ const char *reerr; -+ int reerroffset; -+ -+ rule->pattern_re = -+ pcre_compile(rule->pattern, 0, &reerr, &reerroffset, NULL); -+ if (rule->pattern_re == NULL) { -+ LOGE("Regex compilation of \"%s\" failed: %s, offset %d", -+ rule->pattern, reerr, reerroffset); -+ return 0; -+ } -+ } -+ -+ return 1; -+} -+ -+rule_t * -+lookup_rule(const struct cork_dllist *rules, const char *name, size_t name_len) -+{ -+ struct cork_dllist_item *curr, *next; -+ -+ if (name == NULL) { -+ name = ""; -+ name_len = 0; -+ } -+ -+ cork_dllist_foreach_void(rules, curr, next) { -+ rule_t *rule = cork_container_of(curr, rule_t, entries); -+ if (pcre_exec(rule->pattern_re, NULL, -+ name, name_len, 0, 0, NULL, 0) >= 0) -+ return rule; -+ } -+ -+ return NULL; -+} -+ -+void -+remove_rule(rule_t *rule) -+{ -+ cork_dllist_remove(&rule->entries); -+ free_rule(rule); -+} -+ -+static void -+free_rule(rule_t *rule) -+{ -+ if (rule == NULL) -+ return; -+ -+ ss_free(rule->pattern); -+ if (rule->pattern_re != NULL) -+ pcre_free(rule->pattern_re); -+ ss_free(rule); -+} -diff --git a/server/rule.h b/server/rule.h -new file mode 100644 -index 0000000..015bc42 ---- /dev/null -+++ b/server/rule.h -@@ -0,0 +1,58 @@ -+/* -+ * Copyright (c) 2011 and 2012, Dustin Lundquist -+ * Copyright (c) 2011 Manuel Kasper -+ * 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 HOLDER 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. -+ */ -+#ifndef RULE_H -+#define RULE_H -+ -+#ifdef HAVE_CONFIG_H -+#include "config.h" -+#endif -+ -+#include -+ -+#ifdef HAVE_PCRE_H -+#include -+#elif HAVE_PCRE_PCRE_H -+#include -+#endif -+ -+typedef struct rule { -+ char *pattern; -+ -+ /* Runtime fields */ -+ pcre *pattern_re; -+ -+ struct cork_dllist_item entries; -+} rule_t; -+ -+void add_rule(struct cork_dllist *, rule_t *); -+int init_rule(rule_t *); -+rule_t *lookup_rule(const struct cork_dllist *, const char *, size_t); -+void remove_rule(rule_t *); -+rule_t *new_rule(); -+int accept_rule_arg(rule_t *, const char *); -+ -+#endif -diff --git a/server/server.c b/server/server.c -new file mode 100644 -index 0000000..65b0e42 ---- /dev/null -+++ b/server/server.c -@@ -0,0 +1,2209 @@ -+/* -+ * server.c - Provide shadowsocks service -+ * -+ * Copyright (C) 2013 - 2016, Max Lv -+ * -+ * This file is part of the shadowsocks-libev. -+ * -+ * shadowsocks-libev is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * shadowsocks-libev 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 General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with shadowsocks-libev; see the file COPYING. If not, see -+ * . -+ */ -+ -+#ifdef HAVE_CONFIG_H -+#include "config.h" -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifndef __MINGW32__ -+#include -+#include -+#include -+#include -+#include -+#include -+#endif -+ -+#include -+#include -+ -+#ifdef __MINGW32__ -+#include "win32.h" -+#endif -+ -+#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_NET_IF_H) && defined(__linux__) -+#include -+#include -+#define SET_INTERFACE -+#endif -+ -+#include "netutils.h" -+#include "utils.h" -+#include "acl.h" -+#include "server.h" -+ -+#include "obfs.c" // I don't want to modify makefile -+ -+#ifndef EAGAIN -+#define EAGAIN EWOULDBLOCK -+#endif -+ -+#ifndef EWOULDBLOCK -+#define EWOULDBLOCK EAGAIN -+#endif -+ -+#ifndef BUF_SIZE -+#define BUF_SIZE 2048 -+#endif -+ -+#ifndef SSMAXCONN -+#define SSMAXCONN 1024 -+#endif -+ -+#ifndef UPDATE_INTERVAL -+#define UPDATE_INTERVAL 30 -+#endif -+ -+static void signal_cb(EV_P_ ev_signal *w, int revents); -+static void accept_cb(EV_P_ ev_io *w, int revents); -+static void server_send_cb(EV_P_ ev_io *w, int revents); -+static void server_recv_cb(EV_P_ ev_io *w, int revents); -+static void remote_recv_cb(EV_P_ ev_io *w, int revents); -+static void remote_send_cb(EV_P_ ev_io *w, int revents); -+static void server_timeout_cb(EV_P_ ev_timer *watcher, int revents); -+static void block_list_clear_cb(EV_P_ ev_timer *watcher, int revents); -+ -+static remote_t *new_remote(int fd); -+static server_t *new_server(int fd, listen_ctx_t *listener); -+static remote_t *connect_to_remote(EV_P_ struct addrinfo *res, -+ server_t *server); -+ -+static void free_remote(remote_t *remote); -+static void close_and_free_remote(EV_P_ remote_t *remote); -+static void free_server(server_t *server); -+static void close_and_free_server(EV_P_ server_t *server); -+static void server_resolve_cb(struct sockaddr *addr, void *data); -+static void query_free_cb(void *data); -+ -+static size_t parse_header_len(const char atyp, const char *data, size_t offset); -+static int is_header_complete(const buffer_t *buf); -+ -+int verbose = 0; -+ -+static int acl = 0; -+static int mode = TCP_ONLY; -+static int auth = 0; -+static int ipv6first = 0; -+ -+static int protocol_compatible = 0;//SSR -+static int obfs_compatible = 0;//SSR -+ -+static int fast_open = 0; -+#ifdef HAVE_SETRLIMIT -+static int nofile = 0; -+#endif -+static int remote_conn = 0; -+static int server_conn = 0; -+ -+static char *bind_address = NULL; -+static char *server_port = NULL; -+static char *manager_address = NULL; -+uint64_t tx = 0; -+uint64_t rx = 0; -+ev_timer stat_update_watcher; -+ev_timer block_list_watcher; -+ -+static struct cork_dllist connections; -+ -+static void -+stat_update_cb(EV_P_ ev_timer *watcher, int revents) -+{ -+ struct sockaddr_un svaddr, claddr; -+ int sfd = -1; -+ size_t msgLen; -+ char resp[BUF_SIZE]; -+ -+ if (verbose) { -+ LOGI("update traffic stat: tx: %" PRIu64 " rx: %" PRIu64 "", tx, rx); -+ } -+ -+ snprintf(resp, BUF_SIZE, "stat: {\"%s\":%" PRIu64 "}", server_port, tx + rx); -+ msgLen = strlen(resp) + 1; -+ -+ ss_addr_t ip_addr = { .host = NULL, .port = NULL }; -+ parse_addr(manager_address, &ip_addr); -+ -+ if (ip_addr.host == NULL || ip_addr.port == NULL) { -+ sfd = socket(AF_UNIX, SOCK_DGRAM, 0); -+ if (sfd == -1) { -+ ERROR("stat_socket"); -+ return; -+ } -+ -+ memset(&claddr, 0, sizeof(struct sockaddr_un)); -+ claddr.sun_family = AF_UNIX; -+ snprintf(claddr.sun_path, sizeof(claddr.sun_path), "/tmp/shadowsocks.%s", server_port); -+ -+ unlink(claddr.sun_path); -+ -+ if (bind(sfd, (struct sockaddr *)&claddr, sizeof(struct sockaddr_un)) == -1) { -+ ERROR("stat_bind"); -+ close(sfd); -+ return; -+ } -+ -+ memset(&svaddr, 0, sizeof(struct sockaddr_un)); -+ svaddr.sun_family = AF_UNIX; -+ strncpy(svaddr.sun_path, manager_address, sizeof(svaddr.sun_path) - 1); -+ -+ if (sendto(sfd, resp, strlen(resp) + 1, 0, (struct sockaddr *)&svaddr, -+ sizeof(struct sockaddr_un)) != msgLen) { -+ ERROR("stat_sendto"); -+ close(sfd); -+ return; -+ } -+ -+ unlink(claddr.sun_path); -+ } else { -+ struct sockaddr_storage storage; -+ memset(&storage, 0, sizeof(struct sockaddr_storage)); -+ if (get_sockaddr(ip_addr.host, ip_addr.port, &storage, 0, ipv6first) == -1) { -+ ERROR("failed to parse the manager addr"); -+ return; -+ } -+ -+ sfd = socket(storage.ss_family, SOCK_DGRAM, 0); -+ -+ if (sfd == -1) { -+ ERROR("stat_socket"); -+ return; -+ } -+ -+ size_t addr_len = get_sockaddr_len((struct sockaddr *)&storage); -+ if (sendto(sfd, resp, strlen(resp) + 1, 0, (struct sockaddr *)&storage, -+ addr_len) != msgLen) { -+ ERROR("stat_sendto"); -+ close(sfd); -+ return; -+ } -+ } -+ -+ close(sfd); -+} -+ -+static void -+free_connections(struct ev_loop *loop) -+{ -+ struct cork_dllist_item *curr, *next; -+ cork_dllist_foreach_void(&connections, curr, next) { -+ server_t *server = cork_container_of(curr, server_t, entries); -+ remote_t *remote = server->remote; -+ close_and_free_server(loop, server); -+ close_and_free_remote(loop, remote); -+ } -+} -+ -+static size_t -+parse_header_len(const char atyp, const char *data, size_t offset) -+{ -+ size_t len = 0; -+ if ((atyp & ADDRTYPE_MASK) == 1) { -+ // IP V4 -+ len += sizeof(struct in_addr); -+ } else if ((atyp & ADDRTYPE_MASK) == 3) { -+ // Domain name -+ uint8_t name_len = *(uint8_t *)(data + offset); -+ len += name_len + 1; -+ } else if ((atyp & ADDRTYPE_MASK) == 4) { -+ // IP V6 -+ len += sizeof(struct in6_addr); -+ } else { -+ return 0; -+ } -+ len += 2; -+ return len; -+} -+ -+static int -+is_header_complete(const buffer_t *buf) -+{ -+ size_t header_len = 0; -+ size_t buf_len = buf->len; -+ -+ char atyp = buf->array[header_len]; -+ -+ // 1 byte for atyp -+ header_len++; -+ -+ if ((atyp & ADDRTYPE_MASK) == 1) { -+ // IP V4 -+ header_len += sizeof(struct in_addr); -+ } else if ((atyp & ADDRTYPE_MASK) == 3) { -+ // Domain name -+ // domain len + len of domain -+ if (buf_len < header_len + 1) -+ return 0; -+ uint8_t name_len = *(uint8_t *)(buf->array + header_len); -+ header_len += name_len + 1; -+ } else if ((atyp & ADDRTYPE_MASK) == 4) { -+ // IP V6 -+ header_len += sizeof(struct in6_addr); -+ } else { -+ return -1; -+ } -+ -+ // len of port -+ header_len += 2; -+ -+ // size of ONETIMEAUTH_BYTES -+ if (auth || (atyp & ONETIMEAUTH_FLAG)) { -+ header_len += ONETIMEAUTH_BYTES; -+ } -+ -+ return buf_len >= header_len ? 1 : 0; -+} -+ -+static char * -+get_peer_name(int fd) -+{ -+ static char peer_name[INET6_ADDRSTRLEN] = { 0 }; -+ struct sockaddr_storage addr; -+ socklen_t len = sizeof(struct sockaddr_storage); -+ memset(&addr, 0, len); -+ memset(peer_name, 0, INET6_ADDRSTRLEN); -+ int err = getpeername(fd, (struct sockaddr *)&addr, &len); -+ if (err == 0) { -+ if (addr.ss_family == AF_INET) { -+ struct sockaddr_in *s = (struct sockaddr_in *)&addr; -+ dns_ntop(AF_INET, &s->sin_addr, peer_name, INET_ADDRSTRLEN); -+ } else if (addr.ss_family == AF_INET6) { -+ struct sockaddr_in6 *s = (struct sockaddr_in6 *)&addr; -+ dns_ntop(AF_INET6, &s->sin6_addr, peer_name, INET6_ADDRSTRLEN); -+ } -+ } else { -+ return NULL; -+ } -+ return peer_name; -+} -+ -+#ifdef __linux__ -+static void -+set_linger(int fd) -+{ -+ struct linger so_linger; -+ memset(&so_linger, 0, sizeof(struct linger)); -+ so_linger.l_onoff = 1; -+ so_linger.l_linger = 0; -+ setsockopt(fd, SOL_SOCKET, SO_LINGER, &so_linger, sizeof so_linger); -+} -+#endif -+ -+static void -+reset_addr(int fd) -+{ -+ char *peer_name; -+ peer_name = get_peer_name(fd); -+ if (peer_name != NULL) { -+ remove_from_block_list(peer_name); -+ } -+} -+ -+static void -+report_addr(int fd, int err_level) -+{ -+#ifdef __linux__ -+ set_linger(fd); -+#endif -+ -+ char *peer_name; -+ peer_name = get_peer_name(fd); -+ if (peer_name != NULL) { -+ LOGE("failed to handshake with %s", peer_name); -+ update_block_list(peer_name, err_level); -+ } -+} -+ -+int -+setfastopen(int fd) -+{ -+ int s = 0; -+#ifdef TCP_FASTOPEN -+ if (fast_open) { -+#ifdef __APPLE__ -+ int opt = 1; -+#else -+ int opt = 5; -+#endif -+ s = setsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN, &opt, sizeof(opt)); -+ -+ if (s == -1) { -+ if (errno == EPROTONOSUPPORT || errno == ENOPROTOOPT) { -+ LOGE("fast open is not supported on this platform"); -+ fast_open = 0; -+ } else { -+ ERROR("setsockopt"); -+ } -+ } -+ } -+#endif -+ return s; -+} -+ -+#ifndef __MINGW32__ -+int -+setnonblocking(int fd) -+{ -+ int flags; -+ if (-1 == (flags = fcntl(fd, F_GETFL, 0))) { -+ flags = 0; -+ } -+ return fcntl(fd, F_SETFL, flags | O_NONBLOCK); -+} -+ -+#endif -+ -+int -+create_and_bind(const char *host, const char *port, int mptcp) -+{ -+ struct addrinfo hints; -+ struct addrinfo *result, *rp, *ipv4v6bindall; -+ int s, listen_sock; -+ -+ memset(&hints, 0, sizeof(struct addrinfo)); -+ hints.ai_family = AF_UNSPEC; /* Return IPv4 and IPv6 choices */ -+ hints.ai_socktype = SOCK_STREAM; /* We want a TCP socket */ -+ hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; /* For wildcard IP address */ -+ hints.ai_protocol = IPPROTO_TCP; -+ -+ for (int i = 1; i < 8; i++) { -+ s = getaddrinfo(host, port, &hints, &result); -+ if (s == 0) { -+ break; -+ } else { -+ sleep(pow(2, i)); -+ LOGE("failed to resolve server name, wait %.0f seconds", pow(2, i)); -+ } -+ } -+ -+ if (s != 0) { -+ LOGE("getaddrinfo: %s", gai_strerror(s)); -+ return -1; -+ } -+ -+ rp = result; -+ -+ /* -+ * On Linux, with net.ipv6.bindv6only = 0 (the default), getaddrinfo(NULL) with -+ * AI_PASSIVE returns 0.0.0.0 and :: (in this order). AI_PASSIVE was meant to -+ * return a list of addresses to listen on, but it is impossible to listen on -+ * 0.0.0.0 and :: at the same time, if :: implies dualstack mode. -+ */ -+ if (!host) { -+ ipv4v6bindall = result; -+ -+ /* Loop over all address infos found until a IPV6 address is found. */ -+ while (ipv4v6bindall) { -+ if (ipv4v6bindall->ai_family == AF_INET6) { -+ rp = ipv4v6bindall; /* Take first IPV6 address available */ -+ break; -+ } -+ ipv4v6bindall = ipv4v6bindall->ai_next; /* Get next address info, if any */ -+ } -+ } -+ -+ for (/*rp = result*/; rp != NULL; rp = rp->ai_next) { -+ listen_sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); -+ if (listen_sock == -1) { -+ continue; -+ } -+ -+ if (rp->ai_family == AF_INET6) { -+ int ipv6only = host ? 1 : 0; -+ setsockopt(listen_sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, sizeof(ipv6only)); -+ } -+ -+ int opt = 1; -+ setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); -+#ifdef SO_NOSIGPIPE -+ setsockopt(listen_sock, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); -+#endif -+ int err = set_reuseport(listen_sock); -+ if (err == 0) { -+ LOGI("tcp port reuse enabled"); -+ } -+ -+ if (mptcp == 1) { -+ int err = setsockopt(listen_sock, SOL_TCP, MPTCP_ENABLED, &opt, sizeof(opt)); -+ if (err == -1) { -+ ERROR("failed to enable multipath TCP"); -+ } -+ } -+ -+ s = bind(listen_sock, rp->ai_addr, rp->ai_addrlen); -+ if (s == 0) { -+ /* We managed to bind successfully! */ -+ break; -+ } else { -+ ERROR("bind"); -+ } -+ -+ close(listen_sock); -+ } -+ -+ if (rp == NULL) { -+ LOGE("Could not bind"); -+ return -1; -+ } -+ -+ freeaddrinfo(result); -+ -+ return listen_sock; -+} -+ -+static remote_t * -+connect_to_remote(EV_P_ struct addrinfo *res, -+ server_t *server) -+{ -+ int sockfd; -+#ifdef SET_INTERFACE -+ const char *iface = server->listen_ctx->iface; -+#endif -+ -+ if (acl) { -+ char ipstr[INET6_ADDRSTRLEN]; -+ memset(ipstr, 0, INET6_ADDRSTRLEN); -+ -+ if (res->ai_addr->sa_family == AF_INET) { -+ struct sockaddr_in *s = (struct sockaddr_in *)res->ai_addr; -+ dns_ntop(AF_INET, &s->sin_addr, ipstr, INET_ADDRSTRLEN); -+ } else if (res->ai_addr->sa_family == AF_INET6) { -+ struct sockaddr_in6 *s = (struct sockaddr_in6 *)res->ai_addr; -+ dns_ntop(AF_INET6, &s->sin6_addr, ipstr, INET6_ADDRSTRLEN); -+ } -+ -+ if (outbound_block_match_host(ipstr) == 1) { -+ if (verbose) -+ LOGI("outbound blocked %s", ipstr); -+ return NULL; -+ } -+ } -+ -+ // initialize remote socks -+ sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); -+ if (sockfd == -1) { -+ ERROR("socket"); -+ close(sockfd); -+ return NULL; -+ } -+ -+ int opt = 1; -+ setsockopt(sockfd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt)); -+#ifdef SO_NOSIGPIPE -+ setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); -+#endif -+ setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); -+ -+ // setup remote socks -+ -+ if (setnonblocking(sockfd) == -1) -+ ERROR("setnonblocking"); -+ -+ if (bind_address != NULL) -+ if (bind_to_address(sockfd, bind_address) == -1) { -+ ERROR("bind_to_address"); -+ close(sockfd); -+ return NULL; -+ } -+ -+#ifdef SET_INTERFACE -+ if (iface) { -+ if (setinterface(sockfd, iface) == -1) { -+ ERROR("setinterface"); -+ close(sockfd); -+ return NULL; -+ } -+ } -+#endif -+ -+ remote_t *remote = new_remote(sockfd); -+ -+#ifdef TCP_FASTOPEN -+ if (fast_open) { -+#ifdef __APPLE__ -+ ((struct sockaddr_in *)(res->ai_addr))->sin_len = sizeof(struct sockaddr_in); -+ sa_endpoints_t endpoints; -+ memset((char *)&endpoints, 0, sizeof(endpoints)); -+ endpoints.sae_dstaddr = res->ai_addr; -+ endpoints.sae_dstaddrlen = res->ai_addrlen; -+ -+ struct iovec iov; -+ iov.iov_base = server->buf->array + server->buf->idx; -+ iov.iov_len = server->buf->len; -+ size_t len; -+ int s = connectx(sockfd, &endpoints, SAE_ASSOCID_ANY, CONNECT_DATA_IDEMPOTENT, -+ &iov, 1, &len, NULL); -+ if (s == 0) { -+ s = len; -+ } -+#else -+ ssize_t s = sendto(sockfd, server->buf->array + server->buf->idx, -+ server->buf->len, MSG_FASTOPEN, res->ai_addr, -+ res->ai_addrlen); -+#endif -+ if (s == -1) { -+ if (errno == CONNECT_IN_PROGRESS || errno == EAGAIN -+ || errno == EWOULDBLOCK) { -+ // The remote server doesn't support tfo or it's the first connection to the server. -+ // It will automatically fall back to conventional TCP. -+ } else if (errno == EOPNOTSUPP || errno == EPROTONOSUPPORT || -+ errno == ENOPROTOOPT) { -+ // Disable fast open as it's not supported -+ fast_open = 0; -+ LOGE("fast open is not supported on this platform"); -+ } else { -+ ERROR("sendto"); -+ } -+ } else if (s <= server->buf->len) { -+ server->buf->idx += s; -+ server->buf->len -= s; -+ } else { -+ server->buf->idx = 0; -+ server->buf->len = 0; -+ } -+ } -+#endif -+ -+ if (!fast_open) { -+ int r = connect(sockfd, res->ai_addr, res->ai_addrlen); -+ -+ if (r == -1 && errno != CONNECT_IN_PROGRESS) { -+ ERROR("connect"); -+ close_and_free_remote(EV_A_ remote); -+ return NULL; -+ } -+ } -+ -+ return remote; -+} -+ -+static void -+server_recv_cb(EV_P_ ev_io *w, int revents) -+{ -+ server_ctx_t *server_recv_ctx = (server_ctx_t *)w; -+ server_t *server = server_recv_ctx->server; -+ remote_t *remote = NULL; -+ -+ int len = server->buf->len; -+ buffer_t *buf = server->buf; -+ -+ if (server->stage > STAGE_PARSE) { -+ remote = server->remote; -+ buf = remote->buf; -+ len = 0; -+ -+ ev_timer_again(EV_A_ & server->recv_ctx->watcher); -+ } -+ -+ if (len > BUF_SIZE) { -+ ERROR("out of recv buffer"); -+ close_and_free_remote(EV_A_ remote); -+ close_and_free_server(EV_A_ server); -+ return; -+ } -+ -+ ssize_t r = recv(server->fd, buf->array + len, BUF_SIZE - len, 0); -+ -+ if (r == 0) { -+ // connection closed -+ if (verbose) { -+ LOGI("server_recv close the connection"); -+ } -+ close_and_free_remote(EV_A_ remote); -+ close_and_free_server(EV_A_ server); -+ return; -+ } else if (r == -1) { -+ if (errno == EAGAIN || errno == EWOULDBLOCK) { -+ // no data -+ // continue to wait for recv -+ return; -+ } else { -+ ERROR("server recv"); -+ close_and_free_remote(EV_A_ remote); -+ close_and_free_server(EV_A_ server); -+ return; -+ } -+ } -+ -+ tx += r; -+ -+ if (server->stage == STAGE_ERROR) { -+ server->buf->len = 0; -+ server->buf->idx = 0; -+ return; -+ } -+ -+ // handle incomplete header part 1 -+ if (server->stage == STAGE_INIT) { -+ buf->len += r; -+ if (buf->len <= enc_get_iv_len() + 1) { -+ // wait for more -+ return; -+ } -+ } else { -+ buf->len = r; -+ } -+ -+ // SSR beg -+ -+ if (server->obfs_plugin) { -+ obfs_class *obfs_plugin = server->obfs_plugin; -+ if (obfs_plugin->server_decode) { -+ int needsendback = 0; -+ -+ if(obfs_compatible == 1) -+ { -+ char *back_buf = (char*)malloc(sizeof(buffer_t)); -+ memcpy(back_buf, buf, sizeof(buffer_t)); -+ buf->len = obfs_plugin->server_decode(server->obfs, &buf->array, buf->len, &buf->capacity, &needsendback); -+ -+ if ((int)buf->len < 0) -+ { -+ LOGE("obfs_compatible"); -+ memcpy(buf, back_buf, sizeof(buffer_t)); -+ free(back_buf); -+ server->obfs_compatible_state = 1; -+ } -+ } -+ else -+ { -+ buf->len = obfs_plugin->server_decode(server->obfs, &buf->array, buf->len, &buf->capacity, &needsendback); -+ if ((int)buf->len < 0) { -+ LOGE("server_decode"); -+ close_and_free_remote(EV_A_ remote); -+ close_and_free_server(EV_A_ server); -+ return; -+ } -+ } -+ -+ if (needsendback) { -+ size_t capacity = BUF_SIZE; -+ char *sendback_buf = (char*)malloc(capacity); -+ obfs_class *obfs_plugin = server->obfs_plugin; -+ if (obfs_plugin->server_encode) { -+ int len = obfs_plugin->server_encode(server->obfs, &sendback_buf, 0, &capacity); -+ send(server->fd, sendback_buf, len, 0); -+ } -+ free(sendback_buf); -+ return; -+ } -+ } -+ } -+ -+ int err = ss_decrypt(buf, server->d_ctx, BUF_SIZE); -+ -+ if (err) { -+ report_addr(server->fd, MALICIOUS); -+ close_and_free_remote(EV_A_ remote); -+ close_and_free_server(EV_A_ server); -+ return; -+ } -+ -+ if (server->protocol_plugin) { -+ obfs_class *protocol_plugin = server->protocol_plugin; -+ if (protocol_plugin->server_post_decrypt) { -+ -+ if(protocol_compatible == 1) -+ { -+ char *back_buf = (char*)malloc(sizeof(buffer_t)); -+ memcpy(back_buf, buf, sizeof(buffer_t)); -+ buf->len = protocol_plugin->server_post_decrypt(server->protocol, &buf->array, buf->len, &buf->capacity); -+ -+ if ((int)buf->len < 0) { -+ LOGE("protocol_compatible"); -+ memcpy(buf, back_buf, sizeof(buffer_t)); -+ free(back_buf); -+ server->protocol_compatible_state = 1; -+ } -+ if ( buf->len == 0 ) -+ { -+ LOGE("protocol_compatible"); -+ memcpy(buf, back_buf, sizeof(buffer_t)); -+ free(back_buf); -+ server->protocol_compatible_state = 1; -+ } -+ } -+ else -+ { -+ buf->len = protocol_plugin->server_post_decrypt(server->protocol, &buf->array, buf->len, &buf->capacity); -+ if ((int)buf->len < 0) { -+ LOGE("server_post_decrypt"); -+ close_and_free_remote(EV_A_ remote); -+ close_and_free_server(EV_A_ server); -+ return; -+ } -+ if ( buf->len == 0 ) -+ { -+ LOGE("server_post_decrypt"); -+ return; -+ } -+ } -+ } -+ } -+ // SSR end -+ -+ // handle incomplete header part 2 -+ if (server->stage == STAGE_INIT) { -+ int ret = is_header_complete(server->buf); -+ if (ret == 1) { -+ bfree(server->header_buf); -+ ss_free(server->header_buf); -+ server->stage = STAGE_PARSE; -+ } else if (ret == -1) { -+ server->stage = STAGE_ERROR; -+ report_addr(server->fd, MALFORMED); -+ server->buf->len = 0; -+ server->buf->idx = 0; -+ return; -+ } else { -+ server->stage = STAGE_HANDSHAKE; -+ } -+ } -+ -+ if (server->stage == STAGE_HANDSHAKE) { -+ size_t header_len = server->header_buf->len; -+ brealloc(server->header_buf, server->buf->len + header_len, BUF_SIZE); -+ memcpy(server->header_buf->array + header_len, -+ server->buf->array, server->buf->len); -+ server->header_buf->len = server->buf->len + header_len; -+ -+ int ret = is_header_complete(server->buf); -+ -+ if (ret == 1) { -+ brealloc(server->buf, server->header_buf->len, BUF_SIZE); -+ memcpy(server->buf->array, server->header_buf->array, server->header_buf->len); -+ server->buf->len = server->header_buf->len; -+ bfree(server->header_buf); -+ ss_free(server->header_buf); -+ server->stage = STAGE_PARSE; -+ } else { -+ if (ret == -1) -+ server->stage = STAGE_ERROR; -+ server->buf->len = 0; -+ server->buf->idx = 0; -+ return; -+ } -+ } -+ -+ // handshake and transmit data -+ if (server->stage == STAGE_STREAM) { -+ if (server->auth && !ss_check_hash(remote->buf, server->chunk, server->d_ctx, BUF_SIZE)) { -+ LOGE("hash error"); -+ report_addr(server->fd, BAD); -+ close_and_free_server(EV_A_ server); -+ close_and_free_remote(EV_A_ remote); -+ return; -+ } -+ -+ int s = send(remote->fd, remote->buf->array, remote->buf->len, 0); -+ if (s == -1) { -+ if (errno == EAGAIN || errno == EWOULDBLOCK) { -+ // no data, wait for send -+ remote->buf->idx = 0; -+ ev_io_stop(EV_A_ & server_recv_ctx->io); -+ ev_io_start(EV_A_ & remote->send_ctx->io); -+ } else { -+ ERROR("server_recv_send"); -+ close_and_free_remote(EV_A_ remote); -+ close_and_free_server(EV_A_ server); -+ } -+ } else if (s < remote->buf->len) { -+ remote->buf->len -= s; -+ remote->buf->idx = s; -+ ev_io_stop(EV_A_ & server_recv_ctx->io); -+ ev_io_start(EV_A_ & remote->send_ctx->io); -+ } -+ return; -+ } else if (server->stage == STAGE_PARSE) { -+ /* -+ * Shadowsocks TCP Relay Header: -+ * -+ * +------+----------+----------+----------------+ -+ * | ATYP | DST.ADDR | DST.PORT | HMAC-SHA1 | -+ * +------+----------+----------+----------------+ -+ * | 1 | Variable | 2 | 10 | -+ * +------+----------+----------+----------------+ -+ * -+ * If ATYP & ONETIMEAUTH_FLAG(0x10) != 0, Authentication (HMAC-SHA1) is enabled. -+ * -+ * The key of HMAC-SHA1 is (IV + KEY) and the input is the whole header. -+ * The output of HMAC-SHA is truncated to 10 bytes (leftmost bits). -+ */ -+ -+ /* -+ * Shadowsocks Request's Chunk Authentication for TCP Relay's payload -+ * (No chunk authentication for response's payload): -+ * -+ * +------+-----------+-------------+------+ -+ * | LEN | HMAC-SHA1 | DATA | ... -+ * +------+-----------+-------------+------+ -+ * | 2 | 10 | Variable | ... -+ * +------+-----------+-------------+------+ -+ * -+ * The key of HMAC-SHA1 is (IV + CHUNK ID) -+ * The output of HMAC-SHA is truncated to 10 bytes (leftmost bits). -+ */ -+ -+ int offset = 0; -+ int need_query = 0; -+ char atyp = server->buf->array[offset++]; -+ char host[257] = { 0 }; -+ uint16_t port = 0; -+ struct addrinfo info; -+ struct sockaddr_storage storage; -+ memset(&info, 0, sizeof(struct addrinfo)); -+ memset(&storage, 0, sizeof(struct sockaddr_storage)); -+ -+ if (auth || (atyp & ONETIMEAUTH_FLAG)) { -+ size_t header_len = parse_header_len(atyp, server->buf->array, offset); -+ size_t len = server->buf->len; -+ -+ if (header_len == 0 || len < offset + header_len + ONETIMEAUTH_BYTES) { -+ report_addr(server->fd, MALFORMED); -+ close_and_free_server(EV_A_ server); -+ return; -+ } -+ -+ server->buf->len = offset + header_len + ONETIMEAUTH_BYTES; -+ if (ss_onetimeauth_verify(server->buf, server->d_ctx->evp.iv)) { -+ report_addr(server->fd, BAD); -+ close_and_free_server(EV_A_ server); -+ return; -+ } -+ -+ server->buf->len = len; -+ server->auth = 1; -+ } -+ -+ // get remote addr and port -+ if ((atyp & ADDRTYPE_MASK) == 1) { -+ // IP V4 -+ struct sockaddr_in *addr = (struct sockaddr_in *)&storage; -+ size_t in_addr_len = sizeof(struct in_addr); -+ addr->sin_family = AF_INET; -+ if (server->buf->len >= in_addr_len + 3) { -+ addr->sin_addr = *(struct in_addr *)(server->buf->array + offset); -+ dns_ntop(AF_INET, (const void *)(server->buf->array + offset), -+ host, INET_ADDRSTRLEN); -+ offset += in_addr_len; -+ } else { -+ LOGE("invalid header with addr type %d", atyp); -+ report_addr(server->fd, MALFORMED); -+ close_and_free_server(EV_A_ server); -+ return; -+ } -+ addr->sin_port = *(uint16_t *)(server->buf->array + offset); -+ info.ai_family = AF_INET; -+ info.ai_socktype = SOCK_STREAM; -+ info.ai_protocol = IPPROTO_TCP; -+ info.ai_addrlen = sizeof(struct sockaddr_in); -+ info.ai_addr = (struct sockaddr *)addr; -+ } else if ((atyp & ADDRTYPE_MASK) == 3) { -+ // Domain name -+ uint8_t name_len = *(uint8_t *)(server->buf->array + offset); -+ if (name_len + 4 <= server->buf->len) { -+ memcpy(host, server->buf->array + offset + 1, name_len); -+ offset += name_len + 1; -+ } else { -+ LOGE("invalid name length: %d", name_len); -+ report_addr(server->fd, MALFORMED); -+ close_and_free_server(EV_A_ server); -+ return; -+ } -+ if (acl && outbound_block_match_host(host) == 1) { -+ if (verbose) -+ LOGI("outbound blocked %s", host); -+ close_and_free_server(EV_A_ server); -+ return; -+ } -+ struct cork_ip ip; -+ if (cork_ip_init(&ip, host) != -1) { -+ info.ai_socktype = SOCK_STREAM; -+ info.ai_protocol = IPPROTO_TCP; -+ if (ip.version == 4) { -+ struct sockaddr_in *addr = (struct sockaddr_in *)&storage; -+ dns_pton(AF_INET, host, &(addr->sin_addr)); -+ addr->sin_port = *(uint16_t *)(server->buf->array + offset); -+ addr->sin_family = AF_INET; -+ info.ai_family = AF_INET; -+ info.ai_addrlen = sizeof(struct sockaddr_in); -+ info.ai_addr = (struct sockaddr *)addr; -+ } else if (ip.version == 6) { -+ struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&storage; -+ dns_pton(AF_INET6, host, &(addr->sin6_addr)); -+ addr->sin6_port = *(uint16_t *)(server->buf->array + offset); -+ addr->sin6_family = AF_INET6; -+ info.ai_family = AF_INET6; -+ info.ai_addrlen = sizeof(struct sockaddr_in6); -+ info.ai_addr = (struct sockaddr *)addr; -+ } -+ } else { -+ if (!validate_hostname(host, name_len)) { -+ LOGE("invalid host name"); -+ report_addr(server->fd, MALFORMED); -+ close_and_free_server(EV_A_ server); -+ return; -+ } -+ need_query = 1; -+ } -+ } else if ((atyp & ADDRTYPE_MASK) == 4) { -+ // IP V6 -+ struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&storage; -+ size_t in6_addr_len = sizeof(struct in6_addr); -+ addr->sin6_family = AF_INET6; -+ if (server->buf->len >= in6_addr_len + 3) { -+ addr->sin6_addr = *(struct in6_addr *)(server->buf->array + offset); -+ dns_ntop(AF_INET6, (const void *)(server->buf->array + offset), -+ host, INET6_ADDRSTRLEN); -+ offset += in6_addr_len; -+ } else { -+ LOGE("invalid header with addr type %d", atyp); -+ report_addr(server->fd, MALFORMED); -+ close_and_free_server(EV_A_ server); -+ return; -+ } -+ addr->sin6_port = *(uint16_t *)(server->buf->array + offset); -+ info.ai_family = AF_INET6; -+ info.ai_socktype = SOCK_STREAM; -+ info.ai_protocol = IPPROTO_TCP; -+ info.ai_addrlen = sizeof(struct sockaddr_in6); -+ info.ai_addr = (struct sockaddr *)addr; -+ } -+ -+ if (offset == 1) { -+ LOGE("invalid header with addr type %d", atyp); -+ report_addr(server->fd, MALFORMED); -+ close_and_free_server(EV_A_ server); -+ return; -+ } -+ -+ port = (*(uint16_t *)(server->buf->array + offset)); -+ -+ offset += 2; -+ -+ if (server->auth) { -+ offset += ONETIMEAUTH_BYTES; -+ } -+ -+ if (server->buf->len < offset) { -+ report_addr(server->fd, MALFORMED); -+ close_and_free_server(EV_A_ server); -+ return; -+ } else { -+ server->buf->len -= offset; -+ memmove(server->buf->array, server->buf->array + offset, server->buf->len); -+ } -+ -+ if (verbose) { -+ if ((atyp & ADDRTYPE_MASK) == 4) -+ LOGI("connect to [%s]:%d", host, ntohs(port)); -+ else -+ LOGI("connect to %s:%d", host, ntohs(port)); -+ } -+ -+ if (server->auth && !ss_check_hash(server->buf, server->chunk, server->d_ctx, BUF_SIZE)) { -+ LOGE("hash error"); -+ report_addr(server->fd, BAD); -+ close_and_free_server(EV_A_ server); -+ return; -+ } -+ -+ -+ if (!need_query) { -+ remote_t *remote = connect_to_remote(EV_A_ &info, server); -+ -+ if (remote == NULL) { -+ LOGE("connect error"); -+ close_and_free_server(EV_A_ server); -+ return; -+ } else { -+ server->remote = remote; -+ remote->server = server; -+ -+ // XXX: should handle buffer carefully -+ if (server->buf->len > 0) { -+ memcpy(remote->buf->array, server->buf->array, server->buf->len); -+ remote->buf->len = server->buf->len; -+ remote->buf->idx = 0; -+ server->buf->len = 0; -+ server->buf->idx = 0; -+ } -+ -+ // waiting on remote connected event -+ ev_io_stop(EV_A_ & server_recv_ctx->io); -+ ev_io_start(EV_A_ & remote->send_ctx->io); -+ } -+ } else { -+ query_t *query = (query_t *)ss_malloc(sizeof(query_t)); -+ query->server = server; -+ snprintf(query->hostname, 256, "%s", host); -+ -+ server->stage = STAGE_RESOLVE; -+ server->query = resolv_query(host, server_resolve_cb, -+ query_free_cb, query, port); -+ -+ ev_io_stop(EV_A_ & server_recv_ctx->io); -+ } -+ -+ return; -+ } -+ // should not reach here -+ FATAL("server context error"); -+} -+ -+static void -+server_send_cb(EV_P_ ev_io *w, int revents) -+{ -+ server_ctx_t *server_send_ctx = (server_ctx_t *)w; -+ server_t *server = server_send_ctx->server; -+ remote_t *remote = server->remote; -+ -+ if (remote == NULL) { -+ LOGE("invalid server"); -+ close_and_free_server(EV_A_ server); -+ return; -+ } -+ -+ if (server->buf->len == 0) { -+ // close and free -+ if (verbose) { -+ LOGI("server_send close the connection"); -+ } -+ close_and_free_remote(EV_A_ remote); -+ close_and_free_server(EV_A_ server); -+ return; -+ } else { -+ // has data to send -+ ssize_t s = send(server->fd, server->buf->array + server->buf->idx, -+ server->buf->len, 0); -+ if (s == -1) { -+ if (errno != EAGAIN && errno != EWOULDBLOCK) { -+ ERROR("server_send_send"); -+ close_and_free_remote(EV_A_ remote); -+ close_and_free_server(EV_A_ server); -+ } -+ return; -+ } else if (s < server->buf->len) { -+ // partly sent, move memory, wait for the next time to send -+ server->buf->len -= s; -+ server->buf->idx += s; -+ return; -+ } else { -+ // all sent out, wait for reading -+ server->buf->len = 0; -+ server->buf->idx = 0; -+ ev_io_stop(EV_A_ & server_send_ctx->io); -+ if (remote != NULL) { -+ ev_io_start(EV_A_ & remote->recv_ctx->io); -+ return; -+ } else { -+ LOGE("invalid remote"); -+ close_and_free_remote(EV_A_ remote); -+ close_and_free_server(EV_A_ server); -+ return; -+ } -+ } -+ } -+} -+ -+static void -+block_list_clear_cb(EV_P_ ev_timer *watcher, int revents) -+{ -+ clear_block_list(); -+} -+ -+static void -+server_timeout_cb(EV_P_ ev_timer *watcher, int revents) -+{ -+ server_ctx_t *server_ctx -+ = cork_container_of(watcher, server_ctx_t, watcher); -+ server_t *server = server_ctx->server; -+ remote_t *remote = server->remote; -+ -+ if (verbose) { -+ LOGI("TCP connection timeout"); -+ } -+ -+ if (server->stage < STAGE_PARSE) { -+ if (verbose) { -+ size_t len = server->stage ? -+ server->header_buf->len : server->buf->len; -+#ifdef __MINGW32__ -+ LOGI("incomplete header: %u", len); -+#else -+ LOGI("incomplete header: %zu", len); -+#endif -+ } -+ report_addr(server->fd, SUSPICIOUS); -+ } -+ -+ close_and_free_remote(EV_A_ remote); -+ close_and_free_server(EV_A_ server); -+} -+ -+static void -+query_free_cb(void *data) -+{ -+ if (data != NULL) { -+ ss_free(data); -+ } -+} -+ -+static void -+server_resolve_cb(struct sockaddr *addr, void *data) -+{ -+ query_t *query = (query_t *)data; -+ server_t *server = query->server; -+ struct ev_loop *loop = server->listen_ctx->loop; -+ -+ server->query = NULL; -+ -+ if (addr == NULL) { -+ LOGE("unable to resolve %s", query->hostname); -+ close_and_free_server(EV_A_ server); -+ } else { -+ if (verbose) { -+ LOGI("successfully resolved %s", query->hostname); -+ } -+ -+ struct addrinfo info; -+ memset(&info, 0, sizeof(struct addrinfo)); -+ info.ai_socktype = SOCK_STREAM; -+ info.ai_protocol = IPPROTO_TCP; -+ info.ai_addr = addr; -+ -+ if (addr->sa_family == AF_INET) { -+ info.ai_family = AF_INET; -+ info.ai_addrlen = sizeof(struct sockaddr_in); -+ } else if (addr->sa_family == AF_INET6) { -+ info.ai_family = AF_INET6; -+ info.ai_addrlen = sizeof(struct sockaddr_in6); -+ } -+ -+ remote_t *remote = connect_to_remote(EV_A_ &info, server); -+ -+ if (remote == NULL) { -+ close_and_free_server(EV_A_ server); -+ } else { -+ server->remote = remote; -+ remote->server = server; -+ -+ // XXX: should handle buffer carefully -+ if (server->buf->len > 0) { -+ memcpy(remote->buf->array, server->buf->array + server->buf->idx, -+ server->buf->len); -+ remote->buf->len = server->buf->len; -+ remote->buf->idx = 0; -+ server->buf->len = 0; -+ server->buf->idx = 0; -+ } -+ -+ // listen to remote connected event -+ ev_io_start(EV_A_ & remote->send_ctx->io); -+ } -+ } -+} -+ -+static void -+remote_recv_cb(EV_P_ ev_io *w, int revents) -+{ -+ remote_ctx_t *remote_recv_ctx = (remote_ctx_t *)w; -+ remote_t *remote = remote_recv_ctx->remote; -+ server_t *server = remote->server; -+ -+ if (server == NULL) { -+ LOGE("invalid server"); -+ close_and_free_remote(EV_A_ remote); -+ return; -+ } -+ -+ ev_timer_again(EV_A_ & server->recv_ctx->watcher); -+ -+ ssize_t r = recv(remote->fd, server->buf->array, BUF_SIZE, 0); -+ -+ if (r == 0) { -+ // connection closed -+ if (verbose) { -+ LOGI("remote_recv close the connection"); -+ } -+ close_and_free_remote(EV_A_ remote); -+ close_and_free_server(EV_A_ server); -+ return; -+ } else if (r == -1) { -+ if (errno == EAGAIN || errno == EWOULDBLOCK) { -+ // no data -+ // continue to wait for recv -+ return; -+ } else { -+ ERROR("remote recv"); -+ close_and_free_remote(EV_A_ remote); -+ close_and_free_server(EV_A_ server); -+ return; -+ } -+ } -+ -+ rx += r; -+ -+ server->buf->len = r; -+ -+ // SSR beg -+ server_info _server_info; -+ if (server->obfs_plugin) { -+ server->obfs_plugin->get_server_info(server->obfs, &_server_info); -+ _server_info.head_len = get_head_size(server->buf->array, server->buf->len, 30); -+ server->obfs_plugin->set_server_info(server->obfs, &_server_info); -+ } -+ -+ if (server->protocol_plugin && server->obfs_compatible_state == 0) { -+ obfs_class *protocol_plugin = server->protocol_plugin; -+ if (protocol_plugin->server_pre_encrypt) { -+ server->buf->len = protocol_plugin->server_pre_encrypt(server->protocol, &server->buf->array, server->buf->len, &server->buf->capacity); -+ } -+ } -+ -+ int err = ss_encrypt(server->buf, server->e_ctx, BUF_SIZE); -+ -+ if (err) { -+ LOGE("invalid password or cipher"); -+ close_and_free_remote(EV_A_ remote); -+ close_and_free_server(EV_A_ server); -+ return; -+ } -+ -+ if (server->obfs_plugin && server->obfs_compatible_state == 0) { -+ obfs_class *obfs_plugin = server->obfs_plugin; -+ if (obfs_plugin->server_encode) { -+ server->buf->len = obfs_plugin->server_encode(server->obfs, &server->buf->array, server->buf->len, &server->buf->capacity); -+ } -+ } -+ // SSR end -+ -+ int s = send(server->fd, server->buf->array, server->buf->len, 0); -+ -+ if (s == -1) { -+ if (errno == EAGAIN || errno == EWOULDBLOCK) { -+ // no data, wait for send -+ server->buf->idx = 0; -+ ev_io_stop(EV_A_ & remote_recv_ctx->io); -+ ev_io_start(EV_A_ & server->send_ctx->io); -+ } else { -+ ERROR("remote_recv_send"); -+ close_and_free_remote(EV_A_ remote); -+ close_and_free_server(EV_A_ server); -+ return; -+ } -+ } else if (s < server->buf->len) { -+ server->buf->len -= s; -+ server->buf->idx = s; -+ ev_io_stop(EV_A_ & remote_recv_ctx->io); -+ ev_io_start(EV_A_ & server->send_ctx->io); -+ } -+ -+ // Disable TCP_NODELAY after the first response are sent -+ if (!remote->recv_ctx->connected) { -+ int opt = 0; -+ setsockopt(server->fd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt)); -+ setsockopt(remote->fd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt)); -+ remote->recv_ctx->connected = 1; -+ } -+} -+ -+static void -+remote_send_cb(EV_P_ ev_io *w, int revents) -+{ -+ remote_ctx_t *remote_send_ctx = (remote_ctx_t *)w; -+ remote_t *remote = remote_send_ctx->remote; -+ server_t *server = remote->server; -+ -+ if (server == NULL) { -+ LOGE("invalid server"); -+ close_and_free_remote(EV_A_ remote); -+ return; -+ } -+ -+ if (!remote_send_ctx->connected) { -+ struct sockaddr_storage addr; -+ socklen_t len = sizeof(struct sockaddr_storage); -+ memset(&addr, 0, len); -+ int r = getpeername(remote->fd, (struct sockaddr *)&addr, &len); -+ if (r == 0) { -+ if (verbose) { -+ LOGI("remote connected"); -+ } -+ remote_send_ctx->connected = 1; -+ -+ // Clear the state of this address in the block list -+ reset_addr(server->fd); -+ -+ if (remote->buf->len == 0) { -+ server->stage = STAGE_STREAM; -+ ev_io_stop(EV_A_ & remote_send_ctx->io); -+ ev_io_start(EV_A_ & server->recv_ctx->io); -+ ev_io_start(EV_A_ & remote->recv_ctx->io); -+ return; -+ } -+ } else { -+ ERROR("getpeername"); -+ // not connected -+ close_and_free_remote(EV_A_ remote); -+ close_and_free_server(EV_A_ server); -+ return; -+ } -+ } -+ -+ if (remote->buf->len == 0) { -+ // close and free -+ if (verbose) { -+ LOGI("remote_send close the connection"); -+ } -+ close_and_free_remote(EV_A_ remote); -+ close_and_free_server(EV_A_ server); -+ return; -+ } else { -+ // has data to send -+ ssize_t s = send(remote->fd, remote->buf->array + remote->buf->idx, -+ remote->buf->len, 0); -+ if (s == -1) { -+ if (errno != EAGAIN && errno != EWOULDBLOCK) { -+ ERROR("remote_send_send"); -+ // close and free -+ close_and_free_remote(EV_A_ remote); -+ close_and_free_server(EV_A_ server); -+ } -+ return; -+ } else if (s < remote->buf->len) { -+ // partly sent, move memory, wait for the next time to send -+ remote->buf->len -= s; -+ remote->buf->idx += s; -+ return; -+ } else { -+ // all sent out, wait for reading -+ remote->buf->len = 0; -+ remote->buf->idx = 0; -+ ev_io_stop(EV_A_ & remote_send_ctx->io); -+ if (server != NULL) { -+ ev_io_start(EV_A_ & server->recv_ctx->io); -+ if (server->stage != STAGE_STREAM) { -+ server->stage = STAGE_STREAM; -+ ev_io_start(EV_A_ & remote->recv_ctx->io); -+ } -+ } else { -+ LOGE("invalid server"); -+ close_and_free_remote(EV_A_ remote); -+ close_and_free_server(EV_A_ server); -+ } -+ return; -+ } -+ } -+} -+ -+static remote_t * -+new_remote(int fd) -+{ -+ if (verbose) { -+ remote_conn++; -+ } -+ -+ remote_t *remote; -+ -+ remote = ss_malloc(sizeof(remote_t)); -+ remote->recv_ctx = ss_malloc(sizeof(remote_ctx_t)); -+ remote->send_ctx = ss_malloc(sizeof(remote_ctx_t)); -+ remote->buf = ss_malloc(sizeof(buffer_t)); -+ remote->fd = fd; -+ remote->recv_ctx->remote = remote; -+ remote->recv_ctx->connected = 0; -+ remote->send_ctx->remote = remote; -+ remote->send_ctx->connected = 0; -+ remote->server = NULL; -+ -+ ev_io_init(&remote->recv_ctx->io, remote_recv_cb, fd, EV_READ); -+ ev_io_init(&remote->send_ctx->io, remote_send_cb, fd, EV_WRITE); -+ -+ balloc(remote->buf, BUF_SIZE); -+ -+ return remote; -+} -+ -+static void -+free_remote(remote_t *remote) -+{ -+ if (remote->server != NULL) { -+ remote->server->remote = NULL; -+ } -+ if (remote->buf != NULL) { -+ bfree(remote->buf); -+ ss_free(remote->buf); -+ } -+ ss_free(remote->recv_ctx); -+ ss_free(remote->send_ctx); -+ ss_free(remote); -+} -+ -+static void -+close_and_free_remote(EV_P_ remote_t *remote) -+{ -+ if (remote != NULL) { -+ ev_io_stop(EV_A_ & remote->send_ctx->io); -+ ev_io_stop(EV_A_ & remote->recv_ctx->io); -+ close(remote->fd); -+ free_remote(remote); -+ if (verbose) { -+ remote_conn--; -+ LOGI("current remote connection: %d", remote_conn); -+ } -+ } -+} -+ -+static server_t * -+new_server(int fd, listen_ctx_t *listener) -+{ -+ if (verbose) { -+ server_conn++; -+ } -+ -+ server_t *server; -+ server = ss_malloc(sizeof(server_t)); -+ -+ memset(server, 0, sizeof(server_t)); -+ -+ server->recv_ctx = ss_malloc(sizeof(server_ctx_t)); -+ server->send_ctx = ss_malloc(sizeof(server_ctx_t)); -+ server->buf = ss_malloc(sizeof(buffer_t)); -+ server->header_buf = ss_malloc(sizeof(buffer_t)); -+ server->fd = fd; -+ server->recv_ctx->server = server; -+ server->recv_ctx->connected = 0; -+ server->send_ctx->server = server; -+ server->send_ctx->connected = 0; -+ server->stage = STAGE_INIT; -+ server->query = NULL; -+ server->listen_ctx = listener; -+ server->remote = NULL; -+ -+ if (listener->method) { -+ server->e_ctx = ss_malloc(sizeof(enc_ctx_t)); -+ server->d_ctx = ss_malloc(sizeof(enc_ctx_t)); -+ enc_ctx_init(listener->method, server->e_ctx, 1); -+ enc_ctx_init(listener->method, server->d_ctx, 0); -+ } else { -+ server->e_ctx = NULL; -+ server->d_ctx = NULL; -+ } -+ -+ int request_timeout = min(MAX_REQUEST_TIMEOUT, listener->timeout) -+ + rand() % MAX_REQUEST_TIMEOUT; -+ -+ ev_io_init(&server->recv_ctx->io, server_recv_cb, fd, EV_READ); -+ ev_io_init(&server->send_ctx->io, server_send_cb, fd, EV_WRITE); -+ ev_timer_init(&server->recv_ctx->watcher, server_timeout_cb, -+ request_timeout, listener->timeout); -+ -+ balloc(server->buf, BUF_SIZE); -+ balloc(server->header_buf, BUF_SIZE); -+ -+ server->chunk = (chunk_t *)malloc(sizeof(chunk_t)); -+ memset(server->chunk, 0, sizeof(chunk_t)); -+ server->chunk->buf = ss_malloc(sizeof(buffer_t)); -+ memset(server->chunk->buf, 0, sizeof(buffer_t)); -+ -+ cork_dllist_add(&connections, &server->entries); -+ -+ return server; -+} -+ -+static void -+free_server(server_t *server) -+{ -+ cork_dllist_remove(&server->entries); -+ -+ if (server->chunk != NULL) { -+ if (server->chunk->buf != NULL) { -+ bfree(server->chunk->buf); -+ ss_free(server->chunk->buf); -+ } -+ ss_free(server->chunk); -+ } -+ if (server->remote != NULL) { -+ server->remote->server = NULL; -+ } -+ if (server->e_ctx != NULL) { -+ cipher_context_release(&server->e_ctx->evp); -+ ss_free(server->e_ctx); -+ } -+ if (server->d_ctx != NULL) { -+ cipher_context_release(&server->d_ctx->evp); -+ ss_free(server->d_ctx); -+ } -+ if (server->buf != NULL) { -+ bfree(server->buf); -+ ss_free(server->buf); -+ } -+ if (server->header_buf != NULL) { -+ bfree(server->header_buf); -+ ss_free(server->header_buf); -+ } -+ -+ ss_free(server->recv_ctx); -+ ss_free(server->send_ctx); -+ ss_free(server); -+} -+ -+static void -+close_and_free_server(EV_P_ server_t *server) -+{ -+ if (server != NULL) { -+ if (server->query != NULL) { -+ resolv_cancel(server->query); -+ server->query = NULL; -+ } -+ ev_io_stop(EV_A_ & server->send_ctx->io); -+ ev_io_stop(EV_A_ & server->recv_ctx->io); -+ ev_timer_stop(EV_A_ & server->recv_ctx->watcher); -+ close(server->fd); -+ free_server(server); -+ if (verbose) { -+ server_conn--; -+ LOGI("current server connection: %d", server_conn); -+ } -+ } -+} -+ -+static void -+signal_cb(EV_P_ ev_signal *w, int revents) -+{ -+ if (revents & EV_SIGNAL) { -+ switch (w->signum) { -+ case SIGINT: -+ case SIGTERM: -+ ev_unloop(EV_A_ EVUNLOOP_ALL); -+ } -+ } -+} -+ -+static void -+accept_cb(EV_P_ ev_io *w, int revents) -+{ -+ listen_ctx_t *listener = (listen_ctx_t *)w; -+ int serverfd = accept(listener->fd, NULL, NULL); -+ if (serverfd == -1) { -+ ERROR("accept"); -+ return; -+ } -+ -+ char *peer_name = get_peer_name(serverfd); -+ if (peer_name != NULL) { -+ int in_white_list = 0; -+ if (acl) { -+ if ((get_acl_mode() == BLACK_LIST && acl_match_host(peer_name) == 1) -+ || (get_acl_mode() == WHITE_LIST && acl_match_host(peer_name) >= 0)) { -+ LOGE("Access denied from %s", peer_name); -+ close(serverfd); -+ return; -+ } else if (acl_match_host(peer_name) == -1) { -+ in_white_list = 1; -+ } -+ } -+ if (!in_white_list && check_block_list(peer_name)) { -+ LOGE("block all requests from %s", peer_name); -+#ifdef __linux__ -+ set_linger(serverfd); -+#endif -+ close(serverfd); -+ return; -+ } -+ } -+ -+ int opt = 1; -+ setsockopt(serverfd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt)); -+#ifdef SO_NOSIGPIPE -+ setsockopt(serverfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); -+#endif -+ setnonblocking(serverfd); -+ -+ if (verbose) { -+ LOGI("accept a connection"); -+ } -+ -+ server_t *server = new_server(serverfd, listener); -+ -+ // SSR beg -+ server->obfs_plugin = new_obfs_class(server->listen_ctx->obfs_name); -+ if (server->obfs_plugin) { -+ server->obfs = server->obfs_plugin->new_obfs(); -+ server->obfs_compatible_state = 0; -+ } -+ server->protocol_plugin = new_obfs_class(server->listen_ctx->protocol_name); -+ if (server->protocol_plugin) { -+ server->protocol = server->protocol_plugin->new_obfs(); -+ server->protocol_compatible_state = 0; -+ } -+ server_info _server_info; -+ memset(&_server_info, 0, sizeof(server_info)); -+ _server_info.param = server->listen_ctx->obfs_param; -+ if(server->obfs_plugin) -+ _server_info.g_data = server->obfs_plugin->init_data(); -+ _server_info.head_len = 7; -+ _server_info.iv = server->e_ctx->evp.iv; -+ _server_info.iv_len = enc_get_iv_len(); -+ _server_info.key = enc_get_key(); -+ _server_info.key_len = enc_get_key_len(); -+ _server_info.tcp_mss = 1460; -+ -+ if (server->obfs_plugin) -+ server->obfs_plugin->set_server_info(server->obfs, &_server_info); -+ -+ _server_info.param = server->listen_ctx->protocol_param; -+ if (server->protocol_plugin) -+ _server_info.g_data = server->protocol_plugin->init_data(); -+ -+ if (server->protocol_plugin) -+ server->protocol_plugin->set_server_info(server->protocol, &_server_info); -+ // SSR end -+ -+ ev_io_start(EV_A_ & server->recv_ctx->io); -+ ev_timer_start(EV_A_ & server->recv_ctx->watcher); -+} -+ -+int -+main(int argc, char **argv) -+{ -+ int i, c; -+ int pid_flags = 0; -+ int mptcp = 0; -+ int firewall = 0; -+ int mtu = 0; -+ char *user = NULL; -+ char *password = NULL; -+ char *timeout = NULL; -+ char *protocol = NULL; // SSR -+ char *protocol_param = NULL; // SSR -+ char *method = NULL; -+ char *obfs = NULL; // SSR -+ char *obfs_param = NULL; // SSR -+ char *pid_path = NULL; -+ char *conf_path = NULL; -+ char *iface = NULL; -+ -+ int server_num = 0; -+ const char *server_host[MAX_REMOTE_NUM]; -+ -+ char *nameservers[MAX_DNS_NUM + 1]; -+ int nameserver_num = 0; -+ -+ int option_index = 0; -+ static struct option long_options[] = { -+ { "fast-open", no_argument, 0, 0 }, -+ { "acl", required_argument, 0, 0 }, -+ { "manager-address", required_argument, 0, 0 }, -+ { "mtu", required_argument, 0, 0 }, -+ { "help", no_argument, 0, 0 }, -+#ifdef __linux__ -+ { "mptcp", no_argument, 0, 0 }, -+ { "firewall", no_argument, 0, 0 }, -+#endif -+ { 0, 0, 0, 0 } -+ }; -+ -+ opterr = 0; -+ -+ USE_TTY(); -+ -+ while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:b:c:i:d:a:n:O:o:G:g:huUvA6", -+ long_options, &option_index)) != -1) { -+ switch (c) { -+ case 0: -+ if (option_index == 0) { -+ fast_open = 1; -+ } else if (option_index == 1) { -+ LOGI("initializing acl..."); -+ acl = !init_acl(optarg); -+ } else if (option_index == 2) { -+ manager_address = optarg; -+ } else if (option_index == 3) { -+ mtu = atoi(optarg); -+ LOGI("set MTU to %d", mtu); -+ } else if (option_index == 4) { -+ usage(); -+ exit(EXIT_SUCCESS); -+ } else if (option_index == 5) { -+ mptcp = 1; -+ LOGI("enable multipath TCP"); -+ } else if (option_index == 6) { -+ firewall = 1; -+ LOGI("enable firewall rules"); -+ } -+ break; -+ case 's': -+ if (server_num < MAX_REMOTE_NUM) { -+ server_host[server_num++] = optarg; -+ } -+ break; -+ case 'b': -+ bind_address = optarg; -+ break; -+ case 'p': -+ server_port = optarg; -+ break; -+ case 'k': -+ password = optarg; -+ break; -+ case 'f': -+ pid_flags = 1; -+ pid_path = optarg; -+ break; -+ case 't': -+ timeout = optarg; -+ break; -+ // SSR beg -+ case 'O': -+ protocol = optarg; -+ break; -+ case 'm': -+ method = optarg; -+ break; -+ case 'o': -+ obfs = optarg; -+ break; -+ case 'G': -+ protocol_param = optarg; -+ break; -+ case 'g': -+ obfs_param = optarg; -+ break; -+ // SSR end -+ case 'c': -+ conf_path = optarg; -+ break; -+ case 'i': -+ iface = optarg; -+ break; -+ case 'd': -+ if (nameserver_num < MAX_DNS_NUM) { -+ nameservers[nameserver_num++] = optarg; -+ } -+ break; -+ case 'a': -+ user = optarg; -+ break; -+#ifdef HAVE_SETRLIMIT -+ case 'n': -+ nofile = atoi(optarg); -+ break; -+#endif -+ case 'u': -+ mode = TCP_AND_UDP; -+ break; -+ case 'U': -+ mode = UDP_ONLY; -+ break; -+ case 'v': -+ verbose = 1; -+ break; -+ case 'h': -+ usage(); -+ exit(EXIT_SUCCESS); -+ case 'A': -+ auth = 1; -+ break; -+ case '6': -+ ipv6first = 1; -+ break; -+ case '?': -+ // The option character is not recognized. -+ LOGE("Unrecognized option: %s", optarg); -+ opterr = 1; -+ break; -+ } -+ } -+ -+ if (opterr) { -+ usage(); -+ exit(EXIT_FAILURE); -+ } -+ -+ if (argc == 1) { -+ if (conf_path == NULL) { -+ conf_path = DEFAULT_CONF_PATH; -+ } -+ } -+ -+ if (conf_path != NULL) { -+ jconf_t *conf = read_jconf(conf_path); -+ if (server_num == 0) { -+ server_num = conf->remote_num; -+ for (i = 0; i < server_num; i++) -+ server_host[i] = conf->remote_addr[i].host; -+ } -+ if (server_port == NULL) { -+ server_port = conf->remote_port; -+ } -+ if (password == NULL) { -+ password = conf->password; -+ } -+ // SSR beg -+ if (protocol == NULL) { -+ protocol = conf->protocol; -+ LOGI("protocol %s", protocol); -+ } -+ if (protocol_param == NULL) { -+ protocol_param = conf->protocol_param; -+ LOGI("protocol_param %s", obfs_param); -+ } -+ if (method == NULL) { -+ method = conf->method; -+ LOGI("method %s", method); -+ } -+ if (obfs == NULL) { -+ obfs = conf->obfs; -+ LOGI("obfs %s", obfs); -+ } -+ if (obfs_param == NULL) { -+ obfs_param = conf->obfs_param; -+ LOGI("obfs_param %s", obfs_param); -+ } -+ // SSR end -+ if (timeout == NULL) { -+ timeout = conf->timeout; -+ } -+ if (user == NULL) { -+ user = conf->user; -+ } -+ if (auth == 0) { -+ auth = conf->auth; -+ } -+ if (mode == TCP_ONLY) { -+ mode = conf->mode; -+ } -+ if (mtu == 0) { -+ mtu = conf->mtu; -+ } -+ if (mptcp == 0) { -+ mptcp = conf->mptcp; -+ } -+#ifdef TCP_FASTOPEN -+ if (fast_open == 0) { -+ fast_open = conf->fast_open; -+ } -+#endif -+#ifdef HAVE_SETRLIMIT -+ if (nofile == 0) { -+ nofile = conf->nofile; -+ } -+#endif -+ if (conf->nameserver != NULL) { -+ nameservers[nameserver_num++] = conf->nameserver; -+ } -+ if (ipv6first == 0) { -+ ipv6first = conf->ipv6_first; -+ } -+ } -+ -+ //_compatible -+ if(strlen(protocol)>11) -+ { -+ char *text; -+ text = (char*)malloc(12); -+ memcpy(text, protocol + strlen(protocol) - 11, 12); -+ -+ if(strcmp(text, "_compatible") == 0) -+ { -+ free(text); -+ text = (char*)malloc(strlen(protocol) - 11); -+ memcpy(text, protocol, strlen(protocol) - 11); -+ int length = strlen(protocol) - 11; -+ free(protocol); -+ obfs = (char*)malloc(length); -+ memset(protocol, 0x00, length); -+ memcpy(protocol, text, length); -+ LOGI("protocol compatible enable, %s", protocol); -+ free(text); -+ protocol_compatible = 1; -+ } -+ } -+ -+ if(strlen(obfs)>11) -+ { -+ char *text; -+ text = (char*)malloc(12); -+ memcpy(text, obfs + strlen(obfs) - 11, 12); -+ -+ if(strcmp(text, "_compatible") == 0) -+ { -+ free(text); -+ text = (char*)malloc(strlen(obfs) - 11); -+ memcpy(text, obfs, strlen(obfs) - 11); -+ int length = strlen(obfs) - 11; -+ free(obfs); -+ obfs = (char*)malloc(length); -+ memset(obfs, 0x00, length); -+ memcpy(obfs, text, length); -+ LOGI("obfs compatible enable, %s", obfs); -+ free(text); -+ obfs_compatible = 1; -+ } -+ } -+ -+ -+ if (server_num == 0) { -+ server_host[server_num++] = NULL; -+ } -+ -+ if (server_num == 0 || server_port == NULL || password == NULL) { -+ usage(); -+ exit(EXIT_FAILURE); -+ } -+ -+ if (protocol && strcmp(protocol, "verify_sha1") == 0) { -+ auth = 1; -+ protocol = NULL; -+ } -+ -+ if (method == NULL) { -+ method = "rc4-md5"; -+ } -+ -+ if (timeout == NULL) { -+ timeout = "60"; -+ } -+ -+#ifdef HAVE_SETRLIMIT -+ /* -+ * no need to check the return value here since we will show -+ * the user an error message if setrlimit(2) fails -+ */ -+ if (nofile > 1024) { -+ if (verbose) { -+ LOGI("setting NOFILE to %d", nofile); -+ } -+ set_nofile(nofile); -+ } -+#endif -+ -+ if (pid_flags) { -+ USE_SYSLOG(argv[0]); -+ daemonize(pid_path); -+ } -+ -+ if (ipv6first) { -+ LOGI("resolving hostname to IPv6 address first"); -+ } -+ -+ if (fast_open == 1) { -+#ifdef TCP_FASTOPEN -+ LOGI("using tcp fast open"); -+#else -+ LOGE("tcp fast open is not supported by this environment"); -+ fast_open = 0; -+#endif -+ } -+ -+ if (auth) { -+ LOGI("onetime authentication enabled"); -+ } -+ -+ if (mode != TCP_ONLY) { -+ LOGI("UDP relay enabled"); -+ } -+ -+ if (mode == UDP_ONLY) { -+ LOGI("TCP relay disabled"); -+ } -+ -+#ifdef __MINGW32__ -+ winsock_init(); -+#else -+ // ignore SIGPIPE -+ signal(SIGPIPE, SIG_IGN); -+ signal(SIGCHLD, SIG_IGN); -+ signal(SIGABRT, SIG_IGN); -+#endif -+ -+ struct ev_signal sigint_watcher; -+ struct ev_signal sigterm_watcher; -+ ev_signal_init(&sigint_watcher, signal_cb, SIGINT); -+ ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM); -+ ev_signal_start(EV_DEFAULT, &sigint_watcher); -+ ev_signal_start(EV_DEFAULT, &sigterm_watcher); -+ -+ // setup keys -+ LOGI("initializing ciphers... %s", method); -+ int m = enc_init(password, method); -+ -+ // initialize ev loop -+ struct ev_loop *loop = EV_DEFAULT; -+ -+ // setup udns -+ if (nameserver_num == 0) { -+#ifdef __MINGW32__ -+ nameservers[nameserver_num++] = "8.8.8.8"; -+ resolv_init(loop, nameservers, nameserver_num, ipv6first); -+#else -+ resolv_init(loop, NULL, 0, ipv6first); -+#endif -+ } else { -+ resolv_init(loop, nameservers, nameserver_num, ipv6first); -+ } -+ -+ for (int i = 0; i < nameserver_num; i++) -+ LOGI("using nameserver: %s", nameservers[i]); -+ -+ // initialize listen context -+ listen_ctx_t listen_ctx_list[server_num]; -+ -+ // bind to each interface -+ while (server_num > 0) { -+ int index = --server_num; -+ const char *host = server_host[index]; -+ -+ if (mode != UDP_ONLY) { -+ // Bind to port -+ int listenfd; -+ listenfd = create_and_bind(host, server_port, mptcp); -+ if (listenfd == -1) { -+ FATAL("bind() error"); -+ } -+ if (listen(listenfd, SSMAXCONN) == -1) { -+ FATAL("listen() error"); -+ } -+ setfastopen(listenfd); -+ setnonblocking(listenfd); -+ listen_ctx_t *listen_ctx = &listen_ctx_list[index]; -+ -+ // Setup proxy context -+ listen_ctx->timeout = atoi(timeout); -+ listen_ctx->fd = listenfd; -+ listen_ctx->method = m; -+ listen_ctx->iface = iface; -+ -+ // SSR beg -+ listen_ctx->protocol_name = protocol; -+ listen_ctx->protocol_param = protocol_param; -+ listen_ctx->method = m; -+ listen_ctx->obfs_name = obfs; -+ listen_ctx->obfs_param = obfs_param; -+ listen_ctx->list_protocol_global = malloc(sizeof(void *)); -+ listen_ctx->list_obfs_global = malloc(sizeof(void *)); -+ memset(listen_ctx->list_protocol_global, 0, sizeof(void *)); -+ memset(listen_ctx->list_obfs_global, 0, sizeof(void *)); -+ // SSR end -+ -+ listen_ctx->loop = loop; -+ -+ ev_io_init(&listen_ctx->io, accept_cb, listenfd, EV_READ); -+ ev_io_start(loop, &listen_ctx->io); -+ } -+ -+ // Setup UDP -+ if (mode != TCP_ONLY) { -+ init_udprelay(server_host[index], server_port, mtu, m, -+ auth, atoi(timeout), iface, protocol, protocol_param); -+ } -+ -+ if (host && strcmp(host, ":") > 0) -+ LOGI("listening at [%s]:%s", host, server_port); -+ else -+ LOGI("listening at %s:%s", host ? host : "*", server_port); -+ } -+ -+ if (manager_address != NULL) { -+ ev_timer_init(&stat_update_watcher, stat_update_cb, UPDATE_INTERVAL, UPDATE_INTERVAL); -+ ev_timer_start(EV_DEFAULT, &stat_update_watcher); -+ } -+ -+ ev_timer_init(&block_list_watcher, block_list_clear_cb, UPDATE_INTERVAL, UPDATE_INTERVAL); -+ ev_timer_start(EV_DEFAULT, &block_list_watcher); -+ -+ // setuid -+ if (user != NULL && ! run_as(user)) { -+ FATAL("failed to switch user"); -+ } -+ -+#ifndef __MINGW32__ -+ if (geteuid() == 0){ -+ LOGI("running from root user"); -+ } else if (firewall) { -+ LOGE("firewall setup requires running from root user"); -+ exit(-1); -+ } -+#endif -+ -+ // init block list -+ init_block_list(firewall); -+ -+ // Init connections -+ cork_dllist_init(&connections); -+ -+ // start ev loop -+ ev_run(loop, 0); -+ -+ if (verbose) { -+ LOGI("closed gracefully"); -+ } -+ -+ // Free block list -+ free_block_list(); -+ -+ if (manager_address != NULL) { -+ ev_timer_stop(EV_DEFAULT, &stat_update_watcher); -+ } -+ ev_timer_stop(EV_DEFAULT, &block_list_watcher); -+ -+ // Clean up -+ for (int i = 0; i <= server_num; i++) { -+ listen_ctx_t *listen_ctx = &listen_ctx_list[i]; -+ if (mode != UDP_ONLY) { -+ ev_io_stop(loop, &listen_ctx->io); -+ close(listen_ctx->fd); -+ } -+ } -+ -+ if (mode != UDP_ONLY) { -+ free_connections(loop); -+ } -+ -+ if (mode != TCP_ONLY) { -+ free_udprelay(); -+ } -+ -+ resolv_shutdown(loop); -+ -+#ifdef __MINGW32__ -+ winsock_cleanup(); -+#endif -+ -+ ev_signal_stop(EV_DEFAULT, &sigint_watcher); -+ ev_signal_stop(EV_DEFAULT, &sigterm_watcher); -+ -+ return 0; -+} -diff --git a/server/server.h b/server/server.h -new file mode 100644 -index 0000000..4cd3cf6 ---- /dev/null -+++ b/server/server.h -@@ -0,0 +1,115 @@ -+/* -+ * server.h - Define shadowsocks server's buffers and callbacks -+ * -+ * Copyright (C) 2013 - 2016, Max Lv -+ * -+ * This file is part of the shadowsocks-libev. -+ * -+ * shadowsocks-libev is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * shadowsocks-libev 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 General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with shadowsocks-libev; see the file COPYING. If not, see -+ * . -+ */ -+ -+#ifndef _SERVER_H -+#define _SERVER_H -+ -+#include -+#include -+#include -+ -+#include "encrypt.h" -+#include "jconf.h" -+#include "resolv.h" -+#include "obfs.h" -+#include "protocol.h" -+ -+#include "common.h" -+ -+typedef struct listen_ctx { -+ ev_io io; -+ int fd; -+ int timeout; -+ int method; -+ char *iface; -+ struct ev_loop *loop; -+ -+ // SSR -+ char *protocol_name; -+ char *protocol_param; -+ char *obfs_name; -+ char *obfs_param; -+ void **list_protocol_global; -+ void **list_obfs_global; -+} listen_ctx_t; -+ -+typedef struct server_ctx { -+ ev_io io; -+ ev_timer watcher; -+ int connected; -+ struct server *server; -+} server_ctx_t; -+ -+typedef struct server { -+ int fd; -+ int stage; -+ buffer_t *buf; -+ ssize_t buf_capacity; -+ buffer_t *header_buf; -+ -+ int auth; -+ struct chunk *chunk; -+ -+ struct enc_ctx *e_ctx; -+ struct enc_ctx *d_ctx; -+ struct server_ctx *recv_ctx; -+ struct server_ctx *send_ctx; -+ struct listen_ctx *listen_ctx; -+ struct remote *remote; -+ -+ struct ResolvQuery *query; -+ -+ struct cork_dllist_item entries; -+ -+ // SSR -+ obfs *protocol; -+ obfs *obfs; -+ obfs_class *protocol_plugin; -+ obfs_class *obfs_plugin; -+ int obfs_compatible_state; -+ int protocol_compatible_state; -+} server_t; -+ -+typedef struct query { -+ server_t *server; -+ char hostname[257]; -+} query_t; -+ -+typedef struct remote_ctx { -+ ev_io io; -+ int connected; -+ struct remote *remote; -+} remote_ctx_t; -+ -+typedef struct remote { -+ int fd; -+ buffer_t *buf; -+ ssize_t buf_capacity; -+ struct remote_ctx *recv_ctx; -+ struct remote_ctx *send_ctx; -+ struct server *server; -+ -+ // SSR -+ int remote_index; -+} remote_t; -+ -+#endif // _SERVER_H -diff --git a/server/tls.c b/server/tls.c -new file mode 100644 -index 0000000..5c42216 ---- /dev/null -+++ b/server/tls.c -@@ -0,0 +1,263 @@ -+/* -+ * Copyright (c) 2011 and 2012, Dustin Lundquist -+ * 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 HOLDER 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. -+ */ -+/* -+ * This is a minimal TLS implementation intended only to parse the server name -+ * extension. This was created based primarily on Wireshark dissection of a -+ * TLS handshake and RFC4366. -+ */ -+ -+#ifdef HAVE_CONFIG_H -+#include "config.h" -+#endif -+ -+#include -+#include /* malloc() */ -+#include /* strncpy() */ -+ -+#ifndef __MINGW32__ -+#include -+#else -+#include -+#endif -+ -+#include "tls.h" -+#include "protocol.h" -+#include "utils.h" -+ -+#define SERVER_NAME_LEN 256 -+#define TLS_HEADER_LEN 5 -+#define TLS_HANDSHAKE_CONTENT_TYPE 0x16 -+#define TLS_HANDSHAKE_TYPE_CLIENT_HELLO 0x01 -+ -+#ifndef MIN -+#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) -+#endif -+ -+extern int verbose; -+ -+static int parse_tls_header(const char *, size_t, char **); -+static int parse_extensions(const char *, size_t, char **); -+static int parse_server_name_extension(const char *, size_t, char **); -+ -+static const protocol_t tls_protocol_st = { -+ .default_port = 443, -+ .parse_packet = &parse_tls_header, -+}; -+const protocol_t *const tls_protocol = &tls_protocol_st; -+ -+/* Parse a TLS packet for the Server Name Indication extension in the client -+ * hello handshake, returning the first servername found (pointer to static -+ * array) -+ * -+ * Returns: -+ * >=0 - length of the hostname and updates *hostname -+ * caller is responsible for freeing *hostname -+ * -1 - Incomplete request -+ * -2 - No Host header included in this request -+ * -3 - Invalid hostname pointer -+ * -4 - malloc failure -+ * < -4 - Invalid TLS client hello -+ */ -+static int -+parse_tls_header(const char *data, size_t data_len, char **hostname) -+{ -+ char tls_content_type; -+ char tls_version_major; -+ char tls_version_minor; -+ size_t pos = TLS_HEADER_LEN; -+ size_t len; -+ -+ if (hostname == NULL) -+ return -3; -+ -+ /* Check that our TCP payload is at least large enough for a TLS header */ -+ if (data_len < TLS_HEADER_LEN) -+ return -1; -+ -+ /* SSL 2.0 compatible Client Hello -+ * -+ * High bit of first byte (length) and content type is Client Hello -+ * -+ * See RFC5246 Appendix E.2 -+ */ -+ if (data[0] & 0x80 && data[2] == 1) { -+ if (verbose) -+ LOGI("Received SSL 2.0 Client Hello which can not support SNI."); -+ return -2; -+ } -+ -+ tls_content_type = data[0]; -+ if (tls_content_type != TLS_HANDSHAKE_CONTENT_TYPE) { -+ if (verbose) -+ LOGI("Request did not begin with TLS handshake."); -+ return -5; -+ } -+ -+ tls_version_major = data[1]; -+ tls_version_minor = data[2]; -+ if (tls_version_major < 3) { -+ if (verbose) -+ LOGI("Received SSL %d.%d handshake which can not support SNI.", -+ tls_version_major, tls_version_minor); -+ -+ return -2; -+ } -+ -+ /* TLS record length */ -+ len = ((unsigned char)data[3] << 8) + -+ (unsigned char)data[4] + TLS_HEADER_LEN; -+ data_len = MIN(data_len, len); -+ -+ /* Check we received entire TLS record length */ -+ if (data_len < len) -+ return -1; -+ -+ /* -+ * Handshake -+ */ -+ if (pos + 1 > data_len) { -+ return -5; -+ } -+ if (data[pos] != TLS_HANDSHAKE_TYPE_CLIENT_HELLO) { -+ if (verbose) -+ LOGI("Not a client hello"); -+ -+ return -5; -+ } -+ -+ /* Skip past fixed length records: -+ * 1 Handshake Type -+ * 3 Length -+ * 2 Version (again) -+ * 32 Random -+ * to Session ID Length -+ */ -+ pos += 38; -+ -+ /* Session ID */ -+ if (pos + 1 > data_len) -+ return -5; -+ len = (unsigned char)data[pos]; -+ pos += 1 + len; -+ -+ /* Cipher Suites */ -+ if (pos + 2 > data_len) -+ return -5; -+ len = ((unsigned char)data[pos] << 8) + (unsigned char)data[pos + 1]; -+ pos += 2 + len; -+ -+ /* Compression Methods */ -+ if (pos + 1 > data_len) -+ return -5; -+ len = (unsigned char)data[pos]; -+ pos += 1 + len; -+ -+ if (pos == data_len && tls_version_major == 3 && tls_version_minor == 0) { -+ if (verbose) -+ LOGI("Received SSL 3.0 handshake without extensions"); -+ return -2; -+ } -+ -+ /* Extensions */ -+ if (pos + 2 > data_len) -+ return -5; -+ len = ((unsigned char)data[pos] << 8) + (unsigned char)data[pos + 1]; -+ pos += 2; -+ -+ if (pos + len > data_len) -+ return -5; -+ return parse_extensions(data + pos, len, hostname); -+} -+ -+static int -+parse_extensions(const char *data, size_t data_len, char **hostname) -+{ -+ size_t pos = 0; -+ size_t len; -+ -+ /* Parse each 4 bytes for the extension header */ -+ while (pos + 4 <= data_len) { -+ /* Extension Length */ -+ len = ((unsigned char)data[pos + 2] << 8) + -+ (unsigned char)data[pos + 3]; -+ -+ /* Check if it's a server name extension */ -+ if (data[pos] == 0x00 && data[pos + 1] == 0x00) { -+ /* There can be only one extension of each type, so we break -+ * our state and move p to beinnging of the extension here */ -+ if (pos + 4 + len > data_len) -+ return -5; -+ return parse_server_name_extension(data + pos + 4, len, hostname); -+ } -+ pos += 4 + len; /* Advance to the next extension header */ -+ } -+ /* Check we ended where we expected to */ -+ if (pos != data_len) -+ return -5; -+ -+ return -2; -+} -+ -+static int -+parse_server_name_extension(const char *data, size_t data_len, -+ char **hostname) -+{ -+ size_t pos = 2; /* skip server name list length */ -+ size_t len; -+ -+ while (pos + 3 < data_len) { -+ len = ((unsigned char)data[pos + 1] << 8) + -+ (unsigned char)data[pos + 2]; -+ -+ if (pos + 3 + len > data_len) -+ return -5; -+ -+ switch (data[pos]) { /* name type */ -+ case 0x00: /* host_name */ -+ *hostname = malloc(len + 1); -+ if (*hostname == NULL) { -+ ERROR("malloc() failure"); -+ return -4; -+ } -+ -+ strncpy(*hostname, data + pos + 3, len); -+ -+ (*hostname)[len] = '\0'; -+ -+ return len; -+ default: -+ if (verbose) -+ LOGI("Unknown server name extension name type: %d", -+ data[pos]); -+ } -+ pos += 3 + len; -+ } -+ /* Check we ended where we expected to */ -+ if (pos != data_len) -+ return -5; -+ -+ return -2; -+} -diff --git a/server/tls.h b/server/tls.h -new file mode 100644 -index 0000000..3998913 ---- /dev/null -+++ b/server/tls.h -@@ -0,0 +1,33 @@ -+/* -+ * Copyright (c) 2011 and 2012, Dustin Lundquist -+ * 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 HOLDER 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. -+ */ -+#ifndef TLS_H -+#define TLS_H -+ -+#include "protocol.h" -+ -+const protocol_t *const tls_protocol; -+ -+#endif -diff --git a/server/tls1.2_ticket.c b/server/tls1.2_ticket.c -new file mode 100644 -index 0000000..88970c0 ---- /dev/null -+++ b/server/tls1.2_ticket.c -@@ -0,0 +1,609 @@ -+ -+#include "tls1.2_ticket.h" -+#include "list.c" -+ -+typedef struct tls12_ticket_auth_global_data { -+ uint8_t local_client_id[32]; -+ List client_data; -+ time_t startup_time; -+}tls12_ticket_auth_global_data; -+ -+typedef struct tls12_ticket_auth_local_data { -+ int handshake_status; -+ char *send_buffer; -+ int send_buffer_size; -+ char *recv_buffer; -+ int recv_buffer_size; -+}tls12_ticket_auth_local_data; -+ -+void tls12_ticket_auth_local_data_init(tls12_ticket_auth_local_data* local) { -+ local->handshake_status = 0; -+ local->send_buffer = malloc(0); -+ local->send_buffer_size = 0; -+ local->recv_buffer = malloc(0); -+ local->recv_buffer_size = 0; -+} -+ -+void * tls12_ticket_auth_init_data() { -+ tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)malloc(sizeof(tls12_ticket_auth_global_data)); -+ rand_bytes(global->local_client_id, 32); -+ global->client_data = list_init(22); -+ global->startup_time = time(NULL); -+ return global; -+} -+ -+obfs * tls12_ticket_auth_new_obfs() { -+ obfs * self = new_obfs(); -+ self->l_data = malloc(sizeof(tls12_ticket_auth_local_data)); -+ tls12_ticket_auth_local_data_init((tls12_ticket_auth_local_data*)self->l_data); -+ return self; -+} -+ -+void tls12_ticket_auth_dispose(obfs *self) { -+ tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data; -+ if (local->send_buffer != NULL) { -+ free(local->send_buffer); -+ local->send_buffer = NULL; -+ } -+ if (local->recv_buffer != NULL) { -+ free(local->recv_buffer); -+ local->recv_buffer = NULL; -+ } -+ free(local); -+ dispose_obfs(self); -+} -+ -+int tls12_ticket_pack_auth_data(tls12_ticket_auth_global_data *global, server_info *server, char *outdata) { -+ int out_size = 32; -+ time_t t = time(NULL); -+ outdata[0] = t >> 24; -+ outdata[1] = t >> 16; -+ outdata[2] = t >> 8; -+ outdata[3] = t; -+ rand_bytes((uint8_t*)outdata + 4, 18); -+ -+ uint8_t *key = (uint8_t*)malloc(server->key_len + 32); -+ char hash[ONETIMEAUTH_BYTES * 2]; -+ memcpy(key, server->key, server->key_len); -+ memcpy(key + server->key_len, global->local_client_id, 32); -+ ss_sha1_hmac_with_key(hash, outdata, out_size - OBFS_HMAC_SHA1_LEN, key, server->key_len + 32); -+ free(key); -+ memcpy(outdata + out_size - OBFS_HMAC_SHA1_LEN, hash, OBFS_HMAC_SHA1_LEN); -+ return out_size; -+} -+ -+void tls12_ticket_auth_pack_data(char *encryptdata, int datalength, int start, int len, char *out_buffer, int outlength) { -+ out_buffer[outlength] = 0x17; -+ out_buffer[outlength + 1] = 0x3; -+ out_buffer[outlength + 2] = 0x3; -+ out_buffer[outlength + 3] = len >> 8; -+ out_buffer[outlength + 4] = len; -+ memcpy(out_buffer + outlength + 5, encryptdata + start, len); -+} -+ -+int tls12_ticket_auth_client_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity) { -+ char *encryptdata = *pencryptdata; -+ tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data; -+ tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)self->server.g_data; -+ char * out_buffer = NULL; -+ -+ if (local->handshake_status == 8) { -+ if (datalength < 1024) { -+ if (*capacity < datalength + 5) { -+ *pencryptdata = (char*)realloc(*pencryptdata, *capacity = (datalength + 5) * 2); -+ encryptdata = *pencryptdata; -+ } -+ memmove(encryptdata + 5, encryptdata, datalength); -+ encryptdata[0] = 0x17; -+ encryptdata[1] = 0x3; -+ encryptdata[2] = 0x3; -+ encryptdata[3] = datalength >> 8; -+ encryptdata[4] = datalength; -+ return datalength + 5; -+ } else { -+ out_buffer = (char*)malloc(datalength + 2048); -+ int start = 0; -+ int outlength = 0; -+ int len; -+ while (datalength - start > 2048) { -+ len = xorshift128plus() % 4096 + 100; -+ if (len > datalength - start) -+ len = datalength - start; -+ tls12_ticket_auth_pack_data(encryptdata, datalength, start, len, out_buffer, outlength); -+ outlength += len + 5; -+ start += len; -+ } -+ if (datalength - start > 0) { -+ len = datalength - start; -+ tls12_ticket_auth_pack_data(encryptdata, datalength, start, len, out_buffer, outlength); -+ outlength += len + 5; -+ } -+ if (*capacity < outlength) { -+ *pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2); -+ encryptdata = *pencryptdata; -+ } -+ memcpy(encryptdata, out_buffer, outlength); -+ free(out_buffer); -+ return outlength; -+ } -+ } -+ local->send_buffer = (char*)realloc(local->send_buffer, local->send_buffer_size + datalength + 5); -+ memcpy(local->send_buffer + local->send_buffer_size + 5, encryptdata, datalength); -+ local->send_buffer[local->send_buffer_size] = 0x17; -+ local->send_buffer[local->send_buffer_size + 1] = 0x3; -+ local->send_buffer[local->send_buffer_size + 2] = 0x3; -+ local->send_buffer[local->send_buffer_size + 3] = datalength >> 8; -+ local->send_buffer[local->send_buffer_size + 4] = datalength; -+ local->send_buffer_size += datalength + 5; -+ -+ if (local->handshake_status == 0) { -+#define CSTR_DECL(name, len, str) const char* name = str; const int len = sizeof(str) - 1; -+ CSTR_DECL(tls_data0, tls_data0_len, "\x00\x1c\xc0\x2b\xc0\x2f\xcc\xa9\xcc\xa8\xcc\x14\xcc\x13\xc0\x0a\xc0\x14\xc0\x09\xc0\x13\x00\x9c\x00\x35\x00\x2f\x00\x0a\x01\x00" -+ ); -+ CSTR_DECL(tls_data1, tls_data1_len, "\xff\x01\x00\x01\x00" -+ ); -+ CSTR_DECL(tls_data2, tls_data2_len, "\x00\x17\x00\x00\x00\x23\x00\xd0"); -+ CSTR_DECL(tls_data3, tls_data3_len, "\x00\x0d\x00\x16\x00\x14\x06\x01\x06\x03\x05\x01\x05\x03\x04\x01\x04\x03\x03\x01\x03\x03\x02\x01\x02\x03\x00\x05\x00\x05\x01\x00\x00\x00\x00\x00\x12\x00\x00\x75\x50\x00\x00\x00\x0b\x00\x02\x01\x00\x00\x0a\x00\x06\x00\x04\x00\x17\x00\x18" -+ //"00150066000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" // padding -+ ); -+ uint8_t tls_data[2048]; -+ int tls_data_len = 0; -+ memcpy(tls_data, tls_data1, tls_data1_len); -+ tls_data_len += tls_data1_len; -+ -+ char hosts[1024]; -+ char * phost[128]; -+ int host_num = 0; -+ int pos; -+ -+ char sni[256] = {0}; -+ if (self->server.param && strlen(self->server.param) == 0) -+ self->server.param = NULL; -+ strncpy(hosts, self->server.param ? self->server.param : self->server.host, sizeof hosts); -+ phost[host_num++] = hosts; -+ for (pos = 0; hosts[pos]; ++pos) { -+ if (hosts[pos] == ',') { -+ phost[host_num++] = &hosts[pos + 1]; -+ } -+ } -+ host_num = xorshift128plus() % host_num; -+ -+ sprintf(sni, "%s", phost[host_num]); -+ int sni_len = strlen(sni); -+ if (sni_len > 0 && sni[sni_len - 1] >= '0' && sni[sni_len - 1] <= '9') -+ sni_len = 0; -+ tls_data[tls_data_len] = '\0'; -+ tls_data[tls_data_len + 1] = '\0'; -+ tls_data[tls_data_len + 2] = (sni_len + 5) >> 8; -+ tls_data[tls_data_len + 3] = (sni_len + 5); -+ tls_data[tls_data_len + 4] = (sni_len + 3) >> 8; -+ tls_data[tls_data_len + 5] = (sni_len + 3); -+ tls_data[tls_data_len + 6] = '\0'; -+ tls_data[tls_data_len + 7] = sni_len >> 8; -+ tls_data[tls_data_len + 8] = sni_len; -+ memcpy(tls_data + tls_data_len + 9, sni, sni_len); -+ tls_data_len += 9 + sni_len; -+ memcpy(tls_data + tls_data_len, tls_data2, tls_data2_len); -+ tls_data_len += tls_data2_len; -+ rand_bytes(tls_data + tls_data_len, 208); -+ tls_data_len += 208; -+ memcpy(tls_data + tls_data_len, tls_data3, tls_data3_len); -+ tls_data_len += tls_data3_len; -+ -+ datalength = 11 + 32 + 1 + 32 + tls_data0_len + 2 + tls_data_len; -+ out_buffer = (char*)malloc(datalength); -+ char *pdata = out_buffer + datalength - tls_data_len; -+ int len = tls_data_len; -+ memcpy(pdata, tls_data, tls_data_len); -+ pdata[-1] = tls_data_len; -+ pdata[-2] = tls_data_len >> 8; -+ pdata -= 2; len += 2; -+ memcpy(pdata - tls_data0_len, tls_data0, tls_data0_len); -+ pdata -= tls_data0_len; len += tls_data0_len; -+ memcpy(pdata - 32, global->local_client_id, 32); -+ pdata -= 32; len += 32; -+ pdata[-1] = 0x20; -+ pdata -= 1; len += 1; -+ tls12_ticket_pack_auth_data(global, &self->server, pdata - 32); -+ pdata -= 32; len += 32; -+ pdata[-1] = 0x3; -+ pdata[-2] = 0x3; // tls version -+ pdata -= 2; len += 2; -+ pdata[-1] = len; -+ pdata[-2] = len >> 8; -+ pdata[-3] = 0; -+ pdata[-4] = 1; -+ pdata -= 4; len += 4; -+ -+ pdata[-1] = len; -+ pdata[-2] = len >> 8; -+ pdata -= 2; len += 2; -+ pdata[-1] = 0x1; -+ pdata[-2] = 0x3; // tls version -+ pdata -= 2; len += 2; -+ pdata[-1] = 0x16; // tls handshake -+ pdata -= 1; len += 1; -+ -+ local->handshake_status = 1; -+ } else if (datalength == 0) { -+ datalength = local->send_buffer_size + 43; -+ out_buffer = (char*)malloc(datalength); -+ char *pdata = out_buffer; -+ memcpy(pdata, "\x14\x03\x03\x00\x01\x01", 6); -+ pdata += 6; -+ memcpy(pdata, "\x16\x03\x03\x00\x20", 5); -+ pdata += 5; -+ rand_bytes((uint8_t*)pdata, 22); -+ pdata += 22; -+ -+ uint8_t *key = (uint8_t*)malloc(self->server.key_len + 32); -+ char hash[ONETIMEAUTH_BYTES * 2]; -+ memcpy(key, self->server.key, self->server.key_len); -+ memcpy(key + self->server.key_len, global->local_client_id, 32); -+ ss_sha1_hmac_with_key(hash, out_buffer, pdata - out_buffer, key, self->server.key_len + 32); -+ free(key); -+ memcpy(pdata, hash, OBFS_HMAC_SHA1_LEN); -+ -+ pdata += OBFS_HMAC_SHA1_LEN; -+ memcpy(pdata, local->send_buffer, local->send_buffer_size); -+ free(local->send_buffer); -+ local->send_buffer = NULL; -+ -+ local->handshake_status = 8; -+ } else { -+ return 0; -+ } -+ if (*capacity < datalength) { -+ *pencryptdata = (char*)realloc(*pencryptdata, *capacity = datalength * 2); -+ encryptdata = *pencryptdata; -+ } -+ memmove(encryptdata, out_buffer, datalength); -+ free(out_buffer); -+ return datalength; -+} -+ -+int tls12_ticket_auth_server_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity) { -+ char *encryptdata = *pencryptdata; -+ tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data; -+ tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)self->server.g_data; -+ char * out_buffer = NULL; -+ -+ if (local->handshake_status == 8) { -+ if (datalength < 1024) { -+ if (*capacity < datalength + 5) { -+ *pencryptdata = (char*)realloc(*pencryptdata, *capacity = (datalength + 5) * 2); -+ encryptdata = *pencryptdata; -+ } -+ memmove(encryptdata + 5, encryptdata, datalength); -+ encryptdata[0] = 0x17; -+ encryptdata[1] = 0x3; -+ encryptdata[2] = 0x3; -+ encryptdata[3] = datalength >> 8; -+ encryptdata[4] = datalength; -+ return datalength + 5; -+ } else { -+ out_buffer = (char*)malloc(datalength + 2048); -+ int start = 0; -+ int outlength = 0; -+ int len; -+ while (datalength - start > 2048) { -+ len = xorshift128plus() % 4096 + 100; -+ if (len > datalength - start) -+ len = datalength - start; -+ tls12_ticket_auth_pack_data(encryptdata, datalength, start, len, out_buffer, outlength); -+ outlength += len + 5; -+ start += len; -+ } -+ if (datalength - start > 0) { -+ len = datalength - start; -+ tls12_ticket_auth_pack_data(encryptdata, datalength, start, len, out_buffer, outlength); -+ outlength += len + 5; -+ } -+ if (*capacity < outlength) { -+ *pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2); -+ encryptdata = *pencryptdata; -+ } -+ memcpy(encryptdata, out_buffer, outlength); -+ free(out_buffer); -+ return outlength; -+ } -+ } -+ -+ local->handshake_status = 3; -+ -+ out_buffer = (char*)malloc(43 + 86); -+ int data_len = 0; -+ char *p_data = out_buffer + 86; -+ -+ memcpy(p_data - 10, "\xc0\x2f\x00\x00\x05\xff\x01\x00\x01\x00", 10); -+ p_data -= 10;data_len += 10; -+ -+ memcpy(p_data - 32, global->local_client_id, 32); -+ p_data -= 32;data_len += 32; -+ -+ p_data[-1] = 0x20; -+ p_data -= 1;data_len += 1; -+ -+ tls12_ticket_pack_auth_data(global, &self->server, p_data - 32); -+ p_data -= 32;data_len += 32; -+ -+ p_data[-1] = 0x3; -+ p_data[-2] = 0x3; // tls version -+ p_data -= 2;data_len += 2; -+ -+ p_data[-1] = data_len; -+ p_data[-2] = data_len >> 8; -+ p_data[-3] = 0x00; -+ p_data[-4] = 0x02; -+ p_data -= 4; data_len += 4; -+ -+ p_data[-1] = data_len; -+ p_data[-2] = data_len >> 8; -+ p_data[-3] = 0x03; -+ p_data[-4] = 0x03; -+ p_data[-5] = 0x16; -+ p_data -= 5; data_len += 5; -+ -+ memcpy(out_buffer, p_data, data_len); -+ char *pdata = out_buffer + 86; -+ -+ memcpy(pdata, "\x14\x03\x03\x00\x01\x01", 6); -+ pdata += 6; -+ memcpy(pdata, "\x16\x03\x03\x00\x20", 5); -+ pdata += 5; -+ rand_bytes((uint8_t*)pdata, 22); -+ pdata += 22; -+ -+ uint8_t *key = (uint8_t*)malloc(self->server.key_len + 32); -+ char hash[ONETIMEAUTH_BYTES * 2]; -+ memcpy(key, self->server.key, self->server.key_len); -+ memcpy(key + self->server.key_len, global->local_client_id, 32); -+ ss_sha1_hmac_with_key(hash, out_buffer, 43 + 86, key, self->server.key_len + 32); -+ free(key); -+ memcpy(pdata, hash, OBFS_HMAC_SHA1_LEN); -+ -+ memmove(encryptdata, out_buffer, 43 + 86); -+ free(out_buffer); -+ return 43 + 86; -+} -+ -+int tls12_ticket_auth_client_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback) { -+ char *encryptdata = *pencryptdata; -+ tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data; -+ tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)self->server.g_data; -+ -+ *needsendback = 0; -+ -+ if (local->handshake_status == 8) { -+ local->recv_buffer_size += datalength; -+ local->recv_buffer = (char*)realloc(local->recv_buffer, local->recv_buffer_size); -+ memcpy(local->recv_buffer + local->recv_buffer_size - datalength, encryptdata, datalength); -+ datalength = 0; -+ while (local->recv_buffer_size > 5) { -+ if (local->recv_buffer[0] != 0x17) -+ return -1; -+ int size = ((int)(unsigned char)local->recv_buffer[3] << 8) + (unsigned char)local->recv_buffer[4]; -+ if (size + 5 > local->recv_buffer_size) -+ break; -+ if (*capacity < datalength + size) { -+ *pencryptdata = (char*)realloc(*pencryptdata, *capacity = (datalength + size) * 2); -+ encryptdata = *pencryptdata; -+ } -+ memcpy(encryptdata + datalength, local->recv_buffer + 5, size); -+ datalength += size; -+ local->recv_buffer_size -= 5 + size; -+ memmove(local->recv_buffer, local->recv_buffer + 5 + size, local->recv_buffer_size); -+ } -+ return datalength; -+ } -+ if (datalength < 11 + 32 + 1 + 32) { -+ return -1; -+ } -+ -+ uint8_t *key = (uint8_t*)malloc(self->server.key_len + 32); -+ char hash[ONETIMEAUTH_BYTES * 2]; -+ memcpy(key, self->server.key, self->server.key_len); -+ memcpy(key + self->server.key_len, global->local_client_id, 32); -+ ss_sha1_hmac_with_key(hash, encryptdata + 11, 22, key, self->server.key_len + 32); -+ free(key); -+ -+ if (memcmp(encryptdata + 33, hash, OBFS_HMAC_SHA1_LEN)) { -+ return -1; -+ } -+ -+ *needsendback = 1; -+ return 0; -+} -+ -+int tls12_ticket_auth_server_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback) { -+ char *encryptdata = *pencryptdata; -+ tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data; -+ tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)self->server.g_data; -+ -+ *needsendback = 0; -+ -+ if (local->handshake_status == 8) { -+ if(datalength != 0) -+ { -+ local->recv_buffer = (char*)realloc(local->recv_buffer, local->recv_buffer_size + datalength); -+ memmove(local->recv_buffer + local->recv_buffer_size, encryptdata, datalength); -+ local->recv_buffer_size += datalength; -+ } -+ datalength = 0; -+ -+ while (local->recv_buffer_size > 5) { -+ if (local->recv_buffer[0] != 0x17 || local->recv_buffer[1] != 0x03 || local->recv_buffer[2] != 0x03) -+ { -+ LOGE("server_decode data error, wrong tls version 3"); -+ return -1; -+ } -+ int size = ((int)(unsigned char)local->recv_buffer[3] << 8) + (unsigned char)local->recv_buffer[4]; -+ if (size + 5 > local->recv_buffer_size) -+ break; -+ if (*capacity < local->recv_buffer_size + size) { -+ *pencryptdata = (char*)realloc(*pencryptdata, *capacity = (local->recv_buffer_size + size) * 2); -+ encryptdata = *pencryptdata; -+ } -+ memcpy(encryptdata + datalength, local->recv_buffer + 5, size); -+ datalength += size; -+ local->recv_buffer_size -= 5 + size; -+ memmove(local->recv_buffer, local->recv_buffer + 5 + size, local->recv_buffer_size); -+ } -+ return datalength; -+ } -+ -+ if (local->handshake_status == 3) { -+ -+ char *verify = encryptdata; -+ -+ if(datalength < 43) -+ { -+ LOGE("server_decode data error, too short:%d", (int)datalength); -+ return -1; -+ } -+ -+ if(encryptdata[0] != 0x14 || encryptdata[1] != 0x03 || encryptdata[2] != 0x03 || encryptdata[3] != 0x00 || encryptdata[4] != 0x01 || encryptdata[5] != 0x01) -+ { -+ LOGE("server_decode data error, wrong tls version"); -+ return -1; -+ } -+ -+ encryptdata += 6; -+ -+ if(encryptdata[0] != 0x16 || encryptdata[1] != 0x03 || encryptdata[2] != 0x03 || encryptdata[3] != 0x00 || encryptdata[4] != 0x20) -+ { -+ LOGE("server_decode data error, wrong tls version 2"); -+ return -1; -+ } -+ -+ uint8_t *key = (uint8_t*)malloc(self->server.key_len + 32); -+ char hash[ONETIMEAUTH_BYTES * 2]; -+ memcpy(key, self->server.key, self->server.key_len); -+ memcpy(key + self->server.key_len, global->local_client_id, 32); -+ ss_sha1_hmac_with_key(hash, verify, 33, key, self->server.key_len + 32); -+ free(key); -+ -+ if (memcmp(verify + 33, hash, OBFS_HMAC_SHA1_LEN) != 0) { -+ LOGE("server_decode data error, hash Mismatch %d",(int)memcmp(verify + 33, hash, OBFS_HMAC_SHA1_LEN)); -+ return -1; -+ } -+ -+ local->recv_buffer_size = datalength - 43; -+ local->recv_buffer = (char*)realloc(local->recv_buffer, local->recv_buffer_size); -+ memmove(local->recv_buffer, encryptdata + 37, datalength - 43); -+ -+ local->handshake_status = 8; -+ return tls12_ticket_auth_server_decode(self, pencryptdata, 0, capacity, needsendback); -+ } -+ -+ local->handshake_status = 2; -+ if(encryptdata[0] != 0x16 || encryptdata[1] != 0x03 || encryptdata[2] != 0x01) -+ { -+ return -1; -+ } -+ -+ encryptdata += 3; -+ -+ { -+ int size = ((int)(unsigned char)encryptdata[0] << 8) + (unsigned char)encryptdata[1]; -+ if(size != datalength - 5) -+ { -+ LOGE("tls_auth wrong tls head size"); -+ return -1; -+ } -+ } -+ -+ encryptdata += 2; -+ -+ if(encryptdata[0] != 0x01 || encryptdata[1] != 0x00) -+ { -+ LOGE("tls_auth not client hello message"); -+ return -1; -+ } -+ -+ encryptdata += 2; -+ -+ { -+ int size = ((int)(unsigned char)encryptdata[0] << 8) + (unsigned char)encryptdata[1]; -+ if(size != datalength - 9) -+ { -+ LOGE("tls_auth wrong message size"); -+ return -1; -+ } -+ } -+ -+ encryptdata += 2; -+ -+ if(encryptdata[0] != 0x03 || encryptdata[1] != 0x03) -+ { -+ LOGE("tls_auth wrong tls version"); -+ return -1; -+ } -+ -+ encryptdata += 2; -+ -+ char *verifyid = encryptdata; -+ -+ encryptdata += 32; -+ -+ int sessionid_len = encryptdata[0]; -+ if(sessionid_len < 32) -+ { -+ LOGE("tls_auth wrong sessionid_len"); -+ return -1; -+ } -+ -+ char *sessionid = encryptdata + 1; -+ memcpy(global->local_client_id , sessionid, sessionid_len); -+ -+ uint8_t *key = (uint8_t*)malloc(self->server.key_len + sessionid_len); -+ char hash[ONETIMEAUTH_BYTES * 2]; -+ memcpy(key, self->server.key, self->server.key_len); -+ memcpy(key + self->server.key_len, global->local_client_id, sessionid_len); -+ ss_sha1_hmac_with_key(hash, verifyid, 22, key, self->server.key_len + sessionid_len); -+ free(key); -+ -+ encryptdata += (sessionid_len + 1); -+ -+ long utc_time = ((int)(unsigned char)verifyid[0] << 24) + ((int)(unsigned char)verifyid[1] << 16) + ((int)(unsigned char)verifyid[2] << 8) + (unsigned char)verifyid[3]; -+ time_t t = time(NULL); -+ -+ -+ if (self->server.param && strlen(self->server.param) == 0) -+ { -+ self->server.param = NULL; -+ } -+ -+ int max_time_dif = 0; -+ int time_dif = utc_time - t; -+ if(self->server.param) -+ { -+ max_time_dif = atoi(self->server.param); -+ } -+ -+ if(max_time_dif > 0 && (time_dif < -max_time_dif || time_dif > max_time_dif || utc_time - global->startup_time < -max_time_dif / 2)) -+ { -+ LOGE("tls_auth wrong time"); -+ return -1; -+ } -+ -+ if (memcmp(verifyid + 22, hash, OBFS_HMAC_SHA1_LEN)) { -+ LOGE("tls_auth wrong sha1"); -+ return -1; -+ } -+ -+ int search_result = global->client_data->have_same_cmp(global->client_data, verifyid); -+ if(search_result != 0) -+ { -+ LOGE("replay attack detect!"); -+ return -1; -+ } -+ -+ global->client_data->add_back(global->client_data, verifyid); -+ -+ encryptdata += 48; -+ -+ *needsendback = 1; -+ -+ return 0; -+} -diff --git a/server/tls1.2_ticket.h b/server/tls1.2_ticket.h -new file mode 100644 -index 0000000..10a57c9 ---- /dev/null -+++ b/server/tls1.2_ticket.h -@@ -0,0 +1,20 @@ -+/* -+ * http_simple.h - Define shadowsocksR server's buffers and callbacks -+ * -+ * Copyright (C) 2015 - 2016, Break Wa11 -+ */ -+ -+#ifndef _TLS1_2_TICKET_H -+#define _TLS1_2_TICKET_H -+ -+void * tls12_ticket_auth_init_data(); -+obfs * tls12_ticket_auth_new_obfs(); -+void tls12_ticket_auth_dispose(obfs *self); -+ -+int tls12_ticket_auth_client_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity); -+int tls12_ticket_auth_client_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback); -+ -+int tls12_ticket_auth_server_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity); -+int tls12_ticket_auth_server_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback); -+ -+#endif // _TLS1_2_TICKET_H -diff --git a/server/udprelay.c b/server/udprelay.c -new file mode 100644 -index 0000000..d9251ee ---- /dev/null -+++ b/server/udprelay.c -@@ -0,0 +1,1452 @@ -+/* -+ * udprelay.c - Setup UDP relay for both client and server -+ * -+ * Copyright (C) 2013 - 2016, Max Lv -+ * -+ * This file is part of the shadowsocks-libev. -+ * -+ * shadowsocks-libev is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * shadowsocks-libev 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 General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with shadowsocks-libev; see the file COPYING. If not, see -+ * . -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifndef __MINGW32__ -+#include -+#include -+#include -+#include -+#include -+#endif -+ -+#ifdef HAVE_CONFIG_H -+#include "config.h" -+#endif -+ -+#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_NET_IF_H) && defined(__linux__) -+#include -+#include -+#define SET_INTERFACE -+#endif -+ -+#ifdef __MINGW32__ -+#include "win32.h" -+#endif -+ -+#include -+#include -+ -+#include "utils.h" -+#include "netutils.h" -+#include "cache.h" -+#include "udprelay.h" -+ -+#ifdef MODULE_REMOTE -+#define MAX_UDP_CONN_NUM 512 -+#else -+#define MAX_UDP_CONN_NUM 256 -+#endif -+ -+#ifdef MODULE_REMOTE -+#ifdef MODULE_ -+#error "MODULE_REMOTE and MODULE_LOCAL should not be both defined" -+#endif -+#endif -+ -+#ifndef EAGAIN -+#define EAGAIN EWOULDBLOCK -+#endif -+ -+#ifndef EWOULDBLOCK -+#define EWOULDBLOCK EAGAIN -+#endif -+ -+static void server_recv_cb(EV_P_ ev_io *w, int revents); -+static void remote_recv_cb(EV_P_ ev_io *w, int revents); -+static void remote_timeout_cb(EV_P_ ev_timer *watcher, int revents); -+ -+static char *hash_key(const int af, const struct sockaddr_storage *addr); -+#ifdef MODULE_REMOTE -+static void query_resolve_cb(struct sockaddr *addr, void *data); -+#endif -+static void close_and_free_remote(EV_P_ remote_ctx_t *ctx); -+static remote_ctx_t *new_remote(int fd, server_ctx_t *server_ctx); -+ -+#ifdef ANDROID -+extern uint64_t tx; -+extern uint64_t rx; -+extern int vpn; -+#endif -+ -+extern int verbose; -+#ifdef MODULE_REMOTE -+extern uint64_t tx; -+extern uint64_t rx; -+#endif -+ -+static int packet_size = DEFAULT_PACKET_SIZE; -+static int buf_size = DEFAULT_PACKET_SIZE * 2; -+static int server_num = 0; -+static server_ctx_t *server_ctx_list[MAX_REMOTE_NUM] = { NULL }; -+ -+#ifndef __MINGW32__ -+static int -+setnonblocking(int fd) -+{ -+ int flags; -+ if (-1 == (flags = fcntl(fd, F_GETFL, 0))) { -+ flags = 0; -+ } -+ return fcntl(fd, F_SETFL, flags | O_NONBLOCK); -+} -+ -+#endif -+ -+#if defined(MODULE_REMOTE) && defined(SO_BROADCAST) -+static int -+set_broadcast(int socket_fd) -+{ -+ int opt = 1; -+ return setsockopt(socket_fd, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt)); -+} -+ -+#endif -+ -+#ifdef SO_NOSIGPIPE -+static int -+set_nosigpipe(int socket_fd) -+{ -+ int opt = 1; -+ return setsockopt(socket_fd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); -+} -+ -+#endif -+ -+#ifdef MODULE_REDIR -+ -+#ifndef IP_TRANSPARENT -+#define IP_TRANSPARENT 19 -+#endif -+ -+#ifndef IP_RECVORIGDSTADDR -+#define IP_RECVORIGDSTADDR 20 -+#endif -+ -+static int -+get_dstaddr(struct msghdr *msg, struct sockaddr_storage *dstaddr) -+{ -+ struct cmsghdr *cmsg; -+ -+ for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { -+ if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVORIGDSTADDR) { -+ memcpy(dstaddr, CMSG_DATA(cmsg), sizeof(struct sockaddr_in)); -+ dstaddr->ss_family = AF_INET; -+ return 0; -+ } else if (cmsg->cmsg_level == SOL_IPV6 && cmsg->cmsg_type == IP_RECVORIGDSTADDR) { -+ memcpy(dstaddr, CMSG_DATA(cmsg), sizeof(struct sockaddr_in6)); -+ dstaddr->ss_family = AF_INET6; -+ return 0; -+ } -+ } -+ -+ return 1; -+} -+ -+#endif -+ -+#define HASH_KEY_LEN sizeof(struct sockaddr_storage) + sizeof(int) -+static char * -+hash_key(const int af, const struct sockaddr_storage *addr) -+{ -+ size_t addr_len = sizeof(struct sockaddr_storage); -+ static char key[HASH_KEY_LEN]; -+ -+ memset(key, 0, HASH_KEY_LEN); -+ memcpy(key, &af, sizeof(int)); -+ memcpy(key + sizeof(int), (const uint8_t *)addr, addr_len); -+ -+ return key; -+} -+ -+#if defined(MODULE_REDIR) || defined(MODULE_REMOTE) -+static int -+construct_udprealy_header(const struct sockaddr_storage *in_addr, -+ char *addr_header) -+{ -+ int addr_header_len = 0; -+ if (in_addr->ss_family == AF_INET) { -+ struct sockaddr_in *addr = (struct sockaddr_in *)in_addr; -+ size_t addr_len = sizeof(struct in_addr); -+ addr_header[addr_header_len++] = 1; -+ memcpy(addr_header + addr_header_len, &addr->sin_addr, addr_len); -+ addr_header_len += addr_len; -+ memcpy(addr_header + addr_header_len, &addr->sin_port, 2); -+ addr_header_len += 2; -+ } else if (in_addr->ss_family == AF_INET6) { -+ struct sockaddr_in6 *addr = (struct sockaddr_in6 *)in_addr; -+ size_t addr_len = sizeof(struct in6_addr); -+ addr_header[addr_header_len++] = 4; -+ memcpy(addr_header + addr_header_len, &addr->sin6_addr, addr_len); -+ addr_header_len += addr_len; -+ memcpy(addr_header + addr_header_len, &addr->sin6_port, 2); -+ addr_header_len += 2; -+ } else { -+ return 0; -+ } -+ return addr_header_len; -+} -+ -+#endif -+ -+static int -+parse_udprealy_header(const char *buf, const size_t buf_len, -+ char *host, char *port, struct sockaddr_storage *storage) -+{ -+ const uint8_t atyp = *(uint8_t *)buf; -+ int offset = 1; -+ -+ // get remote addr and port -+ if ((atyp & ADDRTYPE_MASK) == 1) { -+ // IP V4 -+ size_t in_addr_len = sizeof(struct in_addr); -+ if (buf_len >= in_addr_len + 3) { -+ if (storage != NULL) { -+ struct sockaddr_in *addr = (struct sockaddr_in *)storage; -+ addr->sin_family = AF_INET; -+ addr->sin_addr = *(struct in_addr *)(buf + offset); -+ addr->sin_port = *(uint16_t *)(buf + offset + in_addr_len); -+ } -+ if (host != NULL) { -+ dns_ntop(AF_INET, (const void *)(buf + offset), -+ host, INET_ADDRSTRLEN); -+ } -+ offset += in_addr_len; -+ } -+ } else if ((atyp & ADDRTYPE_MASK) == 3) { -+ // Domain name -+ uint8_t name_len = *(uint8_t *)(buf + offset); -+ if (name_len + 4 <= buf_len) { -+ if (storage != NULL) { -+ char tmp[257] = { 0 }; -+ struct cork_ip ip; -+ memcpy(tmp, buf + offset + 1, name_len); -+ if (cork_ip_init(&ip, tmp) != -1) { -+ if (ip.version == 4) { -+ struct sockaddr_in *addr = (struct sockaddr_in *)storage; -+ dns_pton(AF_INET, tmp, &(addr->sin_addr)); -+ addr->sin_port = *(uint16_t *)(buf + offset + 1 + name_len); -+ addr->sin_family = AF_INET; -+ } else if (ip.version == 6) { -+ struct sockaddr_in6 *addr = (struct sockaddr_in6 *)storage; -+ dns_pton(AF_INET, tmp, &(addr->sin6_addr)); -+ addr->sin6_port = *(uint16_t *)(buf + offset + 1 + name_len); -+ addr->sin6_family = AF_INET6; -+ } -+ } -+ } -+ if (host != NULL) { -+ memcpy(host, buf + offset + 1, name_len); -+ } -+ offset += 1 + name_len; -+ } -+ } else if ((atyp & ADDRTYPE_MASK) == 4) { -+ // IP V6 -+ size_t in6_addr_len = sizeof(struct in6_addr); -+ if (buf_len >= in6_addr_len + 3) { -+ if (storage != NULL) { -+ struct sockaddr_in6 *addr = (struct sockaddr_in6 *)storage; -+ addr->sin6_family = AF_INET6; -+ addr->sin6_addr = *(struct in6_addr *)(buf + offset); -+ addr->sin6_port = *(uint16_t *)(buf + offset + in6_addr_len); -+ } -+ if (host != NULL) { -+ dns_ntop(AF_INET6, (const void *)(buf + offset), -+ host, INET6_ADDRSTRLEN); -+ } -+ offset += in6_addr_len; -+ } -+ } -+ -+ if (offset == 1) { -+ LOGE("[udp] invalid header with addr type %d", atyp); -+ return 0; -+ } -+ -+ if (port != NULL) { -+ sprintf(port, "%d", ntohs(*(uint16_t *)(buf + offset))); -+ } -+ offset += 2; -+ -+ return offset; -+} -+ -+static char * -+get_addr_str(const struct sockaddr *sa) -+{ -+ static char s[SS_ADDRSTRLEN]; -+ memset(s, 0, SS_ADDRSTRLEN); -+ char addr[INET6_ADDRSTRLEN] = { 0 }; -+ char port[PORTSTRLEN] = { 0 }; -+ uint16_t p; -+ -+ switch (sa->sa_family) { -+ case AF_INET: -+ dns_ntop(AF_INET, &(((struct sockaddr_in *)sa)->sin_addr), -+ addr, INET_ADDRSTRLEN); -+ p = ntohs(((struct sockaddr_in *)sa)->sin_port); -+ sprintf(port, "%d", p); -+ break; -+ -+ case AF_INET6: -+ dns_ntop(AF_INET6, &(((struct sockaddr_in6 *)sa)->sin6_addr), -+ addr, INET6_ADDRSTRLEN); -+ p = ntohs(((struct sockaddr_in *)sa)->sin_port); -+ sprintf(port, "%d", p); -+ break; -+ -+ default: -+ strncpy(s, "Unknown AF", SS_ADDRSTRLEN); -+ } -+ -+ int addr_len = strlen(addr); -+ int port_len = strlen(port); -+ memcpy(s, addr, addr_len); -+ memcpy(s + addr_len + 1, port, port_len); -+ s[addr_len] = ':'; -+ -+ return s; -+} -+ -+int -+create_remote_socket(int ipv6) -+{ -+ int remote_sock; -+ -+ if (ipv6) { -+ // Try to bind IPv6 first -+ struct sockaddr_in6 addr; -+ memset(&addr, 0, sizeof(struct sockaddr_in6)); -+ addr.sin6_family = AF_INET6; -+ addr.sin6_addr = in6addr_any; -+ addr.sin6_port = 0; -+ remote_sock = socket(AF_INET6, SOCK_DGRAM, 0); -+ if (remote_sock == -1) { -+ ERROR("[udp] cannot create socket"); -+ return -1; -+ } -+ if (bind(remote_sock, (struct sockaddr *)&addr, sizeof(addr)) != 0) { -+ FATAL("[udp] cannot bind remote"); -+ return -1; -+ } -+ } else { -+ // Or else bind to IPv4 -+ struct sockaddr_in addr; -+ memset(&addr, 0, sizeof(struct sockaddr_in)); -+ addr.sin_family = AF_INET; -+ addr.sin_addr.s_addr = INADDR_ANY; -+ addr.sin_port = 0; -+ remote_sock = socket(AF_INET, SOCK_DGRAM, 0); -+ if (remote_sock == -1) { -+ ERROR("[udp] cannot create socket"); -+ return -1; -+ } -+ -+ if (bind(remote_sock, (struct sockaddr *)&addr, sizeof(addr)) != 0) { -+ FATAL("[udp] cannot bind remote"); -+ return -1; -+ } -+ } -+ return remote_sock; -+} -+ -+int -+create_server_socket(const char *host, const char *port) -+{ -+ struct addrinfo hints; -+ struct addrinfo *result, *rp, *ipv4v6bindall; -+ int s, server_sock; -+ -+ memset(&hints, 0, sizeof(struct addrinfo)); -+ hints.ai_family = AF_UNSPEC; /* Return IPv4 and IPv6 choices */ -+ hints.ai_socktype = SOCK_DGRAM; /* We want a UDP socket */ -+ hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; /* For wildcard IP address */ -+ hints.ai_protocol = IPPROTO_UDP; -+ -+ s = getaddrinfo(host, port, &hints, &result); -+ if (s != 0) { -+ LOGE("[udp] getaddrinfo: %s", gai_strerror(s)); -+ return -1; -+ } -+ -+ rp = result; -+ -+ /* -+ * On Linux, with net.ipv6.bindv6only = 0 (the default), getaddrinfo(NULL) with -+ * AI_PASSIVE returns 0.0.0.0 and :: (in this order). AI_PASSIVE was meant to -+ * return a list of addresses to listen on, but it is impossible to listen on -+ * 0.0.0.0 and :: at the same time, if :: implies dualstack mode. -+ */ -+ if (!host) { -+ ipv4v6bindall = result; -+ -+ /* Loop over all address infos found until a IPV6 address is found. */ -+ while (ipv4v6bindall) { -+ if (ipv4v6bindall->ai_family == AF_INET6) { -+ rp = ipv4v6bindall; /* Take first IPV6 address available */ -+ break; -+ } -+ ipv4v6bindall = ipv4v6bindall->ai_next; /* Get next address info, if any */ -+ } -+ } -+ -+ for (/*rp = result*/; rp != NULL; rp = rp->ai_next) { -+ server_sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); -+ if (server_sock == -1) { -+ continue; -+ } -+ -+ if (rp->ai_family == AF_INET6) { -+ int ipv6only = host ? 1 : 0; -+ setsockopt(server_sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, sizeof(ipv6only)); -+ } -+ -+ int opt = 1; -+ setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); -+#ifdef SO_NOSIGPIPE -+ set_nosigpipe(server_sock); -+#endif -+ int err = set_reuseport(server_sock); -+ if (err == 0) { -+ LOGI("udp port reuse enabled"); -+ } -+#ifdef IP_TOS -+ // Set QoS flag -+ int tos = 46; -+ setsockopt(server_sock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); -+#endif -+ -+#ifdef MODULE_REDIR -+ if (setsockopt(server_sock, SOL_IP, IP_TRANSPARENT, &opt, sizeof(opt))) { -+ ERROR("[udp] setsockopt IP_TRANSPARENT"); -+ exit(EXIT_FAILURE); -+ } -+ if (setsockopt(server_sock, IPPROTO_IP, IP_RECVORIGDSTADDR, &opt, sizeof(opt))) { -+ FATAL("[udp] setsockopt IP_RECVORIGDSTADDR"); -+ } -+#endif -+ -+ s = bind(server_sock, rp->ai_addr, rp->ai_addrlen); -+ if (s == 0) { -+ /* We managed to bind successfully! */ -+ break; -+ } else { -+ ERROR("[udp] bind"); -+ } -+ -+ close(server_sock); -+ } -+ -+ if (rp == NULL) { -+ LOGE("[udp] cannot bind"); -+ return -1; -+ } -+ -+ freeaddrinfo(result); -+ -+ return server_sock; -+} -+ -+remote_ctx_t * -+new_remote(int fd, server_ctx_t *server_ctx) -+{ -+ remote_ctx_t *ctx = ss_malloc(sizeof(remote_ctx_t)); -+ memset(ctx, 0, sizeof(remote_ctx_t)); -+ -+ ctx->fd = fd; -+ ctx->server_ctx = server_ctx; -+ -+ ev_io_init(&ctx->io, remote_recv_cb, fd, EV_READ); -+ ev_timer_init(&ctx->watcher, remote_timeout_cb, server_ctx->timeout, -+ server_ctx->timeout); -+ -+ return ctx; -+} -+ -+server_ctx_t * -+new_server_ctx(int fd) -+{ -+ server_ctx_t *ctx = ss_malloc(sizeof(server_ctx_t)); -+ memset(ctx, 0, sizeof(server_ctx_t)); -+ -+ ctx->fd = fd; -+ -+ ev_io_init(&ctx->io, server_recv_cb, fd, EV_READ); -+ -+ return ctx; -+} -+ -+#ifdef MODULE_REMOTE -+struct query_ctx * -+new_query_ctx(char *buf, size_t len) -+{ -+ struct query_ctx *ctx = ss_malloc(sizeof(struct query_ctx)); -+ memset(ctx, 0, sizeof(struct query_ctx)); -+ ctx->buf = ss_malloc(sizeof(buffer_t)); -+ balloc(ctx->buf, len); -+ memcpy(ctx->buf->array, buf, len); -+ ctx->buf->len = len; -+ return ctx; -+} -+ -+void -+close_and_free_query(EV_P_ struct query_ctx *ctx) -+{ -+ if (ctx != NULL) { -+ if (ctx->query != NULL) { -+ resolv_cancel(ctx->query); -+ ctx->query = NULL; -+ } -+ if (ctx->buf != NULL) { -+ bfree(ctx->buf); -+ ss_free(ctx->buf); -+ } -+ ss_free(ctx); -+ } -+} -+ -+#endif -+ -+void -+close_and_free_remote(EV_P_ remote_ctx_t *ctx) -+{ -+ if (ctx != NULL) { -+ ev_timer_stop(EV_A_ & ctx->watcher); -+ ev_io_stop(EV_A_ & ctx->io); -+ close(ctx->fd); -+ ss_free(ctx); -+ } -+} -+ -+static void -+remote_timeout_cb(EV_P_ ev_timer *watcher, int revents) -+{ -+ remote_ctx_t *remote_ctx -+ = cork_container_of(watcher, remote_ctx_t, watcher); -+ -+ if (verbose) { -+ LOGI("[udp] connection timeout"); -+ } -+ -+ char *key = hash_key(remote_ctx->af, &remote_ctx->src_addr); -+ cache_remove(remote_ctx->server_ctx->conn_cache, key, HASH_KEY_LEN); -+} -+ -+#ifdef MODULE_REMOTE -+static void -+query_resolve_cb(struct sockaddr *addr, void *data) -+{ -+ struct query_ctx *query_ctx = (struct query_ctx *)data; -+ struct ev_loop *loop = query_ctx->server_ctx->loop; -+ -+ if (verbose) { -+ LOGI("[udp] udns resolved"); -+ } -+ -+ query_ctx->query = NULL; -+ -+ if (addr == NULL) { -+ LOGE("[udp] udns returned an error"); -+ } else { -+ remote_ctx_t *remote_ctx = query_ctx->remote_ctx; -+ int cache_hit = 0; -+ -+ // Lookup in the conn cache -+ if (remote_ctx == NULL) { -+ char *key = hash_key(AF_UNSPEC, &query_ctx->src_addr); -+ cache_lookup(query_ctx->server_ctx->conn_cache, key, HASH_KEY_LEN, (void *)&remote_ctx); -+ } -+ -+ if (remote_ctx == NULL) { -+ int remotefd = create_remote_socket(addr->sa_family == AF_INET6); -+ if (remotefd != -1) { -+ setnonblocking(remotefd); -+#ifdef SO_BROADCAST -+ set_broadcast(remotefd); -+#endif -+#ifdef SO_NOSIGPIPE -+ set_nosigpipe(remotefd); -+#endif -+#ifdef IP_TOS -+ // Set QoS flag -+ int tos = 46; -+ setsockopt(remotefd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); -+#endif -+#ifdef SET_INTERFACE -+ if (query_ctx->server_ctx->iface) { -+ if (setinterface(remotefd, query_ctx->server_ctx->iface) == -1) -+ ERROR("setinterface"); -+ } -+#endif -+ remote_ctx = new_remote(remotefd, query_ctx->server_ctx); -+ remote_ctx->src_addr = query_ctx->src_addr; -+ remote_ctx->server_ctx = query_ctx->server_ctx; -+ remote_ctx->addr_header_len = query_ctx->addr_header_len; -+ memcpy(remote_ctx->addr_header, query_ctx->addr_header, -+ query_ctx->addr_header_len); -+ } else { -+ ERROR("[udp] bind() error"); -+ } -+ } else { -+ cache_hit = 1; -+ } -+ -+ if (remote_ctx != NULL) { -+ memcpy(&remote_ctx->dst_addr, addr, sizeof(struct sockaddr_storage)); -+ -+ size_t addr_len = get_sockaddr_len(addr); -+ int s = sendto(remote_ctx->fd, query_ctx->buf->array, query_ctx->buf->len, -+ 0, addr, addr_len); -+ -+ if (s == -1) { -+ ERROR("[udp] sendto_remote"); -+ if (!cache_hit) { -+ close_and_free_remote(EV_A_ remote_ctx); -+ } -+ } else { -+ if (!cache_hit) { -+ // Add to conn cache -+ char *key = hash_key(AF_UNSPEC, &remote_ctx->src_addr); -+ cache_insert(query_ctx->server_ctx->conn_cache, key, HASH_KEY_LEN, (void *)remote_ctx); -+ ev_io_start(EV_A_ & remote_ctx->io); -+ ev_timer_start(EV_A_ & remote_ctx->watcher); -+ } -+ } -+ } -+ } -+ -+ // clean up -+ close_and_free_query(EV_A_ query_ctx); -+} -+ -+#endif -+ -+static void -+remote_recv_cb(EV_P_ ev_io *w, int revents) -+{ -+ ssize_t r; -+ remote_ctx_t *remote_ctx = (remote_ctx_t *)w; -+ server_ctx_t *server_ctx = remote_ctx->server_ctx; -+ -+ // server has been closed -+ if (server_ctx == NULL) { -+ LOGE("[udp] invalid server"); -+ close_and_free_remote(EV_A_ remote_ctx); -+ return; -+ } -+ -+ struct sockaddr_storage src_addr; -+ socklen_t src_addr_len = sizeof(struct sockaddr_storage); -+ memset(&src_addr, 0, src_addr_len); -+ -+ buffer_t *buf = ss_malloc(sizeof(buffer_t)); -+ balloc(buf, buf_size); -+ -+ // recv -+ r = recvfrom(remote_ctx->fd, buf->array, buf_size, 0, (struct sockaddr *)&src_addr, &src_addr_len); -+ -+ if (r == -1) { -+ // error on recv -+ // simply drop that packet -+ ERROR("[udp] remote_recv_recvfrom"); -+ goto CLEAN_UP; -+ } else if (r > packet_size) { -+ LOGE("[udp] remote_recv_recvfrom fragmentation"); -+ goto CLEAN_UP; -+ } -+ -+ buf->len = r; -+ -+#ifdef MODULE_LOCAL -+ int err = ss_decrypt_all(buf, server_ctx->method, 0, buf_size); -+ if (err) { -+ // drop the packet silently -+ goto CLEAN_UP; -+ } -+ -+ //SSR beg -+ if (server_ctx->protocol_plugin) { -+ obfs_class *protocol_plugin = server_ctx->protocol_plugin; -+ if (protocol_plugin->client_udp_post_decrypt) { -+ buf->len = protocol_plugin->client_udp_post_decrypt(server_ctx->protocol, &buf->array, buf->len, &buf->capacity); -+ if ((int)buf->len < 0) { -+ LOGE("client_udp_post_decrypt"); -+ close_and_free_remote(EV_A_ remote_ctx); -+ return; -+ } -+ if ( buf->len == 0 ) -+ return; -+ } -+ } -+ // SSR end -+ -+#ifdef MODULE_REDIR -+ struct sockaddr_storage dst_addr; -+ memset(&dst_addr, 0, sizeof(struct sockaddr_storage)); -+ int len = parse_udprealy_header(buf->array, buf->len, NULL, NULL, &dst_addr); -+ -+ if (dst_addr.ss_family != AF_INET && dst_addr.ss_family != AF_INET6) { -+ LOGI("[udp] ss-redir does not support domain name"); -+ goto CLEAN_UP; -+ } -+ -+ if (verbose) { -+ char src[SS_ADDRSTRLEN]; -+ char dst[SS_ADDRSTRLEN]; -+ strcpy(src, get_addr_str((struct sockaddr *)&src_addr)); -+ strcpy(dst, get_addr_str((struct sockaddr *)&dst_addr)); -+ LOGI("[udp] recv %s via %s", dst, src); -+ } -+#else -+ int len = parse_udprealy_header(buf->array, buf->len, NULL, NULL, NULL); -+#endif -+ -+ if (len == 0) { -+ LOGI("[udp] error in parse header"); -+ // error in parse header -+ goto CLEAN_UP; -+ } -+ -+ // server may return using a different address type other than the type we -+ // have used during sending -+#if defined(MODULE_TUNNEL) || defined(MODULE_REDIR) -+ // Construct packet -+ buf->len -= len; -+ memmove(buf->array, buf->array + len, buf->len); -+#else -+#ifdef ANDROID -+ rx += buf->len; -+#endif -+ // Construct packet -+ brealloc(buf, buf->len + 3, buf_size); -+ memmove(buf->array + 3, buf->array, buf->len); -+ memset(buf->array, 0, 3); -+ buf->len += 3; -+#endif -+ -+#endif -+ -+#ifdef MODULE_REMOTE -+ -+ rx += buf->len; -+ -+ char addr_header_buf[512]; -+ char *addr_header = remote_ctx->addr_header; -+ int addr_header_len = remote_ctx->addr_header_len; -+ -+ if (remote_ctx->af == AF_INET || remote_ctx->af == AF_INET6) { -+ addr_header_len = construct_udprealy_header(&src_addr, addr_header_buf); -+ addr_header = addr_header_buf; -+ } -+ -+ // Construct packet -+ brealloc(buf, buf->len + addr_header_len, buf_size); -+ memmove(buf->array + addr_header_len, buf->array, buf->len); -+ memcpy(buf->array, addr_header, addr_header_len); -+ buf->len += addr_header_len; -+ -+ int err = ss_encrypt_all(buf, server_ctx->method, 0, buf_size); -+ if (err) { -+ // drop the packet silently -+ goto CLEAN_UP; -+ } -+ -+#endif -+ -+ if (buf->len > packet_size) { -+ LOGE("[udp] remote_recv_sendto fragmentation"); -+ goto CLEAN_UP; -+ } -+ -+ size_t remote_src_addr_len = get_sockaddr_len((struct sockaddr *)&remote_ctx->src_addr); -+ -+#ifdef MODULE_REDIR -+ -+ size_t remote_dst_addr_len = get_sockaddr_len((struct sockaddr *)&dst_addr); -+ -+ int src_fd = socket(remote_ctx->src_addr.ss_family, SOCK_DGRAM, 0); -+ if (src_fd < 0) { -+ ERROR("[udp] remote_recv_socket"); -+ goto CLEAN_UP; -+ } -+ int opt = 1; -+ if (setsockopt(src_fd, SOL_IP, IP_TRANSPARENT, &opt, sizeof(opt))) { -+ ERROR("[udp] remote_recv_setsockopt"); -+ close(src_fd); -+ goto CLEAN_UP; -+ } -+ if (setsockopt(src_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) { -+ ERROR("[udp] remote_recv_setsockopt"); -+ close(src_fd); -+ goto CLEAN_UP; -+ } -+#ifdef IP_TOS -+ // Set QoS flag -+ int tos = 46; -+ setsockopt(src_fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); -+#endif -+ if (bind(src_fd, (struct sockaddr *)&dst_addr, remote_dst_addr_len) != 0) { -+ ERROR("[udp] remote_recv_bind"); -+ close(src_fd); -+ goto CLEAN_UP; -+ } -+ -+ int s = sendto(src_fd, buf->array, buf->len, 0, -+ (struct sockaddr *)&remote_ctx->src_addr, remote_src_addr_len); -+ if (s == -1) { -+ ERROR("[udp] remote_recv_sendto"); -+ close(src_fd); -+ goto CLEAN_UP; -+ } -+ close(src_fd); -+ -+#else -+ -+ int s = sendto(server_ctx->fd, buf->array, buf->len, 0, -+ (struct sockaddr *)&remote_ctx->src_addr, remote_src_addr_len); -+ if (s == -1) { -+ ERROR("[udp] remote_recv_sendto"); -+ goto CLEAN_UP; -+ } -+ -+#endif -+ -+ // handle the UDP packet successfully, -+ // triger the timer -+ ev_timer_again(EV_A_ & remote_ctx->watcher); -+ -+CLEAN_UP: -+ -+ bfree(buf); -+ ss_free(buf); -+} -+ -+static void -+server_recv_cb(EV_P_ ev_io *w, int revents) -+{ -+ server_ctx_t *server_ctx = (server_ctx_t *)w; -+ struct sockaddr_storage src_addr; -+ memset(&src_addr, 0, sizeof(struct sockaddr_storage)); -+ -+ buffer_t *buf = ss_malloc(sizeof(buffer_t)); -+ balloc(buf, buf_size); -+ -+ socklen_t src_addr_len = sizeof(struct sockaddr_storage); -+ unsigned int offset = 0; -+ -+#ifdef MODULE_REDIR -+ char control_buffer[64] = { 0 }; -+ struct msghdr msg; -+ memset(&msg, 0, sizeof(struct msghdr)); -+ struct iovec iov[1]; -+ struct sockaddr_storage dst_addr; -+ memset(&dst_addr, 0, sizeof(struct sockaddr_storage)); -+ -+ msg.msg_name = &src_addr; -+ msg.msg_namelen = src_addr_len; -+ msg.msg_control = control_buffer; -+ msg.msg_controllen = sizeof(control_buffer); -+ -+ iov[0].iov_base = buf->array; -+ iov[0].iov_len = buf_size; -+ msg.msg_iov = iov; -+ msg.msg_iovlen = 1; -+ -+ buf->len = recvmsg(server_ctx->fd, &msg, 0); -+ if (buf->len == -1) { -+ ERROR("[udp] server_recvmsg"); -+ goto CLEAN_UP; -+ } else if (buf->len > packet_size) { -+ ERROR("[udp] UDP server_recv_recvmsg fragmentation"); -+ goto CLEAN_UP; -+ } -+ -+ if (get_dstaddr(&msg, &dst_addr)) { -+ LOGE("[udp] unable to get dest addr"); -+ goto CLEAN_UP; -+ } -+ -+ src_addr_len = msg.msg_namelen; -+#else -+ ssize_t r; -+ r = recvfrom(server_ctx->fd, buf->array, buf_size, -+ 0, (struct sockaddr *)&src_addr, &src_addr_len); -+ -+ if (r == -1) { -+ // error on recv -+ // simply drop that packet -+ ERROR("[udp] server_recv_recvfrom"); -+ goto CLEAN_UP; -+ } else if (r > packet_size) { -+ ERROR("[udp] server_recv_recvfrom fragmentation"); -+ goto CLEAN_UP; -+ } -+ -+ buf->len = r; -+#endif -+ -+#ifdef MODULE_REMOTE -+ tx += buf->len; -+ -+ int err = ss_decrypt_all(buf, server_ctx->method, server_ctx->auth, buf_size); -+ if (err) { -+ // drop the packet silently -+ goto CLEAN_UP; -+ } -+#endif -+ -+#ifdef MODULE_LOCAL -+#if !defined(MODULE_TUNNEL) && !defined(MODULE_REDIR) -+#ifdef ANDROID -+ tx += buf->len; -+#endif -+ uint8_t frag = *(uint8_t *)(buf->array + 2); -+ offset += 3; -+#endif -+#endif -+ -+ /* -+ * -+ * 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 | HMAC-SHA1 | -+ * +------+----------+----------+----------+-------------+ -+ * | 1 | Variable | 2 | Variable | 10 | -+ * +------+----------+----------+----------+-------------+ -+ * -+ * If ATYP & ONETIMEAUTH_FLAG(0x10) != 0, Authentication (HMAC-SHA1) is enabled. -+ * -+ * The key of HMAC-SHA1 is (IV + KEY) and the input is the whole packet. -+ * The output of HMAC-SHA is truncated to 10 bytes (leftmost bits). -+ * -+ * 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 | -+ * +-------+--------------+ -+ * -+ */ -+ -+#ifdef MODULE_REDIR -+ if (verbose) { -+ char src[SS_ADDRSTRLEN]; -+ char dst[SS_ADDRSTRLEN]; -+ strcpy(src, get_addr_str((struct sockaddr *)&src_addr)); -+ strcpy(dst, get_addr_str((struct sockaddr *)&dst_addr)); -+ LOGI("[udp] redir to %s from %s", dst, src); -+ } -+ -+ char addr_header[512] = { 0 }; -+ int addr_header_len = construct_udprealy_header(&dst_addr, addr_header); -+ -+ if (addr_header_len == 0) { -+ LOGE("[udp] failed to parse tproxy addr"); -+ goto CLEAN_UP; -+ } -+ -+ // reconstruct the buffer -+ brealloc(buf, buf->len + addr_header_len, buf_size); -+ memmove(buf->array + addr_header_len, buf->array, buf->len); -+ memcpy(buf->array, addr_header, addr_header_len); -+ buf->len += addr_header_len; -+ -+#elif MODULE_TUNNEL -+ -+ char addr_header[512] = { 0 }; -+ char *host = server_ctx->tunnel_addr.host; -+ char *port = server_ctx->tunnel_addr.port; -+ uint16_t port_num = (uint16_t)atoi(port); -+ uint16_t port_net_num = htons(port_num); -+ int addr_header_len = 0; -+ -+ struct cork_ip ip; -+ if (cork_ip_init(&ip, host) != -1) { -+ if (ip.version == 4) { -+ // send as IPv4 -+ struct in_addr host_addr; -+ memset(&host_addr, 0, sizeof(struct in_addr)); -+ int host_len = sizeof(struct in_addr); -+ -+ if (dns_pton(AF_INET, host, &host_addr) == -1) { -+ FATAL("IP parser error"); -+ } -+ addr_header[addr_header_len++] = 1; -+ memcpy(addr_header + addr_header_len, &host_addr, host_len); -+ addr_header_len += host_len; -+ } else if (ip.version == 6) { -+ // send as IPv6 -+ struct in6_addr host_addr; -+ memset(&host_addr, 0, sizeof(struct in6_addr)); -+ int host_len = sizeof(struct in6_addr); -+ -+ if (dns_pton(AF_INET6, host, &host_addr) == -1) { -+ FATAL("IP parser error"); -+ } -+ addr_header[addr_header_len++] = 4; -+ memcpy(addr_header + addr_header_len, &host_addr, host_len); -+ addr_header_len += host_len; -+ } else { -+ FATAL("IP parser error"); -+ } -+ } else { -+ // send as domain -+ int host_len = strlen(host); -+ -+ addr_header[addr_header_len++] = 3; -+ addr_header[addr_header_len++] = host_len; -+ memcpy(addr_header + addr_header_len, host, host_len); -+ addr_header_len += host_len; -+ } -+ memcpy(addr_header + addr_header_len, &port_net_num, 2); -+ addr_header_len += 2; -+ -+ // reconstruct the buffer -+ brealloc(buf, buf->len + addr_header_len, buf_size); -+ memmove(buf->array + addr_header_len, buf->array, buf->len); -+ memcpy(buf->array, addr_header, addr_header_len); -+ buf->len += addr_header_len; -+ -+#else -+ -+ char host[257] = { 0 }; -+ char port[64] = { 0 }; -+ struct sockaddr_storage dst_addr; -+ memset(&dst_addr, 0, sizeof(struct sockaddr_storage)); -+ -+ int addr_header_len = parse_udprealy_header(buf->array + offset, buf->len - offset, -+ host, port, &dst_addr); -+ if (addr_header_len == 0) { -+ // error in parse header -+ goto CLEAN_UP; -+ } -+ -+ char *addr_header = buf->array + offset; -+#endif -+ -+#ifdef MODULE_LOCAL -+ char *key = hash_key(server_ctx->remote_addr->sa_family, &src_addr); -+#else -+ char *key = hash_key(dst_addr.ss_family, &src_addr); -+#endif -+ -+ struct cache *conn_cache = server_ctx->conn_cache; -+ -+ remote_ctx_t *remote_ctx = NULL; -+ cache_lookup(conn_cache, key, HASH_KEY_LEN, (void *)&remote_ctx); -+ -+ if (remote_ctx != NULL) { -+ if (sockaddr_cmp(&src_addr, &remote_ctx->src_addr, sizeof(src_addr))) { -+ remote_ctx = NULL; -+ } -+ } -+ -+ // reset the timer -+ if (remote_ctx != NULL) { -+ ev_timer_again(EV_A_ & remote_ctx->watcher); -+ } -+ -+ if (remote_ctx == NULL) { -+ if (verbose) { -+#ifdef MODULE_REDIR -+ char src[SS_ADDRSTRLEN]; -+ char dst[SS_ADDRSTRLEN]; -+ strcpy(src, get_addr_str((struct sockaddr *)&src_addr)); -+ strcpy(dst, get_addr_str((struct sockaddr *)&dst_addr)); -+ LOGI("[udp] cache miss: %s <-> %s", dst, src); -+#else -+ LOGI("[udp] cache miss: %s:%s <-> %s", host, port, -+ get_addr_str((struct sockaddr *)&src_addr)); -+#endif -+ } -+ } else { -+ if (verbose) { -+#ifdef MODULE_REDIR -+ char src[SS_ADDRSTRLEN]; -+ char dst[SS_ADDRSTRLEN]; -+ strcpy(src, get_addr_str((struct sockaddr *)&src_addr)); -+ strcpy(dst, get_addr_str((struct sockaddr *)&dst_addr)); -+ LOGI("[udp] cache hit: %s <-> %s", dst, src); -+#else -+ LOGI("[udp] cache hit: %s:%s <-> %s", host, port, -+ get_addr_str((struct sockaddr *)&src_addr)); -+#endif -+ } -+ } -+ -+#ifdef MODULE_LOCAL -+ -+#if !defined(MODULE_TUNNEL) && !defined(MODULE_REDIR) -+ if (frag) { -+ LOGE("[udp] drop a message since frag is not 0, but %d", frag); -+ goto CLEAN_UP; -+ } -+#endif -+ -+ const struct sockaddr *remote_addr = server_ctx->remote_addr; -+ const int remote_addr_len = server_ctx->remote_addr_len; -+ -+ if (remote_ctx == NULL) { -+ // Bind to any port -+ int remotefd = create_remote_socket(remote_addr->sa_family == AF_INET6); -+ if (remotefd < 0) { -+ ERROR("[udp] udprelay bind() error"); -+ goto CLEAN_UP; -+ } -+ setnonblocking(remotefd); -+ -+#ifdef SO_NOSIGPIPE -+ set_nosigpipe(remotefd); -+#endif -+#ifdef IP_TOS -+ // Set QoS flag -+ int tos = 46; -+ setsockopt(remotefd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); -+#endif -+#ifdef SET_INTERFACE -+ if (server_ctx->iface) { -+ if (setinterface(remotefd, server_ctx->iface) == -1) -+ ERROR("setinterface"); -+ } -+#endif -+ -+#ifdef ANDROID -+ if (vpn) { -+ if (protect_socket(remotefd) == -1) { -+ ERROR("protect_socket"); -+ close(remotefd); -+ goto CLEAN_UP; -+ } -+ } -+#endif -+ -+ // Init remote_ctx -+ remote_ctx = new_remote(remotefd, server_ctx); -+ remote_ctx->src_addr = src_addr; -+ remote_ctx->af = remote_addr->sa_family; -+ remote_ctx->addr_header_len = addr_header_len; -+ memcpy(remote_ctx->addr_header, addr_header, addr_header_len); -+ -+ // Add to conn cache -+ cache_insert(conn_cache, key, HASH_KEY_LEN, (void *)remote_ctx); -+ -+ // Start remote io -+ ev_io_start(EV_A_ & remote_ctx->io); -+ ev_timer_start(EV_A_ & remote_ctx->watcher); -+ } -+ -+ if (offset > 0) { -+ buf->len -= offset; -+ memmove(buf->array, buf->array + offset, buf->len); -+ } -+ -+ if (server_ctx->auth) { -+ buf->array[0] |= ONETIMEAUTH_FLAG; -+ } -+ -+ // SSR beg -+ if (server_ctx->protocol_plugin) { -+ obfs_class *protocol_plugin = server_ctx->protocol_plugin; -+ if (protocol_plugin->client_udp_pre_encrypt) { -+ buf->len = protocol_plugin->client_udp_pre_encrypt(server_ctx->protocol, &buf->array, buf->len, &buf->capacity); -+ } -+ } -+ //SSR end -+ -+ int err = ss_encrypt_all(buf, server_ctx->method, server_ctx->auth, buf->len); -+ -+ if (err) { -+ // drop the packet silently -+ goto CLEAN_UP; -+ } -+ -+ if (buf->len > packet_size) { -+ LOGE("[udp] server_recv_sendto fragmentation"); -+ goto CLEAN_UP; -+ } -+ -+ int s = sendto(remote_ctx->fd, buf->array, buf->len, 0, remote_addr, remote_addr_len); -+ -+ if (s == -1) { -+ ERROR("[udp] server_recv_sendto"); -+ } -+ -+#else -+ -+ int cache_hit = 0; -+ int need_query = 0; -+ -+ if (buf->len - addr_header_len > packet_size) { -+ LOGE("[udp] server_recv_sendto fragmentation"); -+ goto CLEAN_UP; -+ } -+ -+ if (remote_ctx != NULL) { -+ cache_hit = 1; -+ // detect destination mismatch -+ if (remote_ctx->addr_header_len != addr_header_len -+ || memcmp(addr_header, remote_ctx->addr_header, addr_header_len) != 0) { -+ if (dst_addr.ss_family != AF_INET && dst_addr.ss_family != AF_INET6) { -+ need_query = 1; -+ } -+ } else { -+ memcpy(&dst_addr, &remote_ctx->dst_addr, sizeof(struct sockaddr_storage)); -+ } -+ } else { -+ if (dst_addr.ss_family == AF_INET || dst_addr.ss_family == AF_INET6) { -+ int remotefd = create_remote_socket(dst_addr.ss_family == AF_INET6); -+ if (remotefd != -1) { -+ setnonblocking(remotefd); -+#ifdef SO_BROADCAST -+ set_broadcast(remotefd); -+#endif -+#ifdef SO_NOSIGPIPE -+ set_nosigpipe(remotefd); -+#endif -+#ifdef IP_TOS -+ // Set QoS flag -+ int tos = 46; -+ setsockopt(remotefd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); -+#endif -+#ifdef SET_INTERFACE -+ if (server_ctx->iface) { -+ if (setinterface(remotefd, server_ctx->iface) == -1) -+ ERROR("setinterface"); -+ } -+#endif -+ remote_ctx = new_remote(remotefd, server_ctx); -+ remote_ctx->src_addr = src_addr; -+ remote_ctx->server_ctx = server_ctx; -+ remote_ctx->addr_header_len = addr_header_len; -+ memcpy(remote_ctx->addr_header, addr_header, addr_header_len); -+ memcpy(&remote_ctx->dst_addr, &dst_addr, sizeof(struct sockaddr_storage)); -+ } else { -+ ERROR("[udp] bind() error"); -+ goto CLEAN_UP; -+ } -+ } -+ } -+ -+ if (remote_ctx != NULL && !need_query) { -+ size_t addr_len = get_sockaddr_len((struct sockaddr *)&dst_addr); -+ int s = sendto(remote_ctx->fd, buf->array + addr_header_len, -+ buf->len - addr_header_len, 0, -+ (struct sockaddr *)&dst_addr, addr_len); -+ -+ if (s == -1) { -+ ERROR("[udp] sendto_remote"); -+ if (!cache_hit) { -+ close_and_free_remote(EV_A_ remote_ctx); -+ } -+ } else { -+ if (!cache_hit) { -+ // Add to conn cache -+ remote_ctx->af = dst_addr.ss_family; -+ char *key = hash_key(remote_ctx->af, &remote_ctx->src_addr); -+ cache_insert(server_ctx->conn_cache, key, HASH_KEY_LEN, (void *)remote_ctx); -+ -+ ev_io_start(EV_A_ & remote_ctx->io); -+ ev_timer_start(EV_A_ & remote_ctx->watcher); -+ } -+ } -+ } else { -+ struct addrinfo hints; -+ memset(&hints, 0, sizeof(struct addrinfo)); -+ hints.ai_family = AF_UNSPEC; -+ hints.ai_socktype = SOCK_DGRAM; -+ hints.ai_protocol = IPPROTO_UDP; -+ -+ struct query_ctx *query_ctx = new_query_ctx(buf->array + addr_header_len, -+ buf->len - addr_header_len); -+ query_ctx->server_ctx = server_ctx; -+ query_ctx->addr_header_len = addr_header_len; -+ query_ctx->src_addr = src_addr; -+ memcpy(query_ctx->addr_header, addr_header, addr_header_len); -+ -+ if (need_query) { -+ query_ctx->remote_ctx = remote_ctx; -+ } -+ -+ struct ResolvQuery *query = resolv_query(host, query_resolve_cb, -+ NULL, query_ctx, htons(atoi(port))); -+ if (query == NULL) { -+ ERROR("[udp] unable to create DNS query"); -+ close_and_free_query(EV_A_ query_ctx); -+ goto CLEAN_UP; -+ } -+ query_ctx->query = query; -+ } -+#endif -+ -+CLEAN_UP: -+ bfree(buf); -+ ss_free(buf); -+} -+ -+void -+free_cb(void *key, void *element) -+{ -+ remote_ctx_t *remote_ctx = (remote_ctx_t *)element; -+ -+ if (verbose) { -+ LOGI("[udp] one connection freed"); -+ } -+ -+ close_and_free_remote(EV_DEFAULT, remote_ctx); -+} -+ -+int -+init_udprelay(const char *server_host, const char *server_port, -+#ifdef MODULE_LOCAL -+ const struct sockaddr *remote_addr, const int remote_addr_len, -+#ifdef MODULE_TUNNEL -+ const ss_addr_t tunnel_addr, -+#endif -+#endif -+ int mtu, int method, int auth, int timeout, const char *iface, const char *protocol, const char *protocol_param) -+{ -+ // Initialize ev loop -+ struct ev_loop *loop = EV_DEFAULT; -+ -+ // Initialize MTU -+ if (mtu > 0) { -+ packet_size = mtu - 1 - 28 - 2 - 64; -+ buf_size = packet_size * 2; -+ } -+ -+ // Initialize cache -+ struct cache *conn_cache; -+ cache_create(&conn_cache, MAX_UDP_CONN_NUM, free_cb); -+ -+ // //////////////////////////////////////////////// -+ // Setup server context -+ -+ // Bind to port -+ int serverfd = create_server_socket(server_host, server_port); -+ if (serverfd < 0) { -+ FATAL("[udp] bind() error"); -+ } -+ setnonblocking(serverfd); -+ if (protocol != NULL && strcmp(protocol, "verify_sha1") == 0) { -+ auth = 1; -+ protocol = NULL; -+ } -+ -+ server_ctx_t *server_ctx = new_server_ctx(serverfd); -+#ifdef MODULE_REMOTE -+ server_ctx->loop = loop; -+#endif -+ server_ctx->auth = auth; -+ server_ctx->timeout = max(timeout, MIN_UDP_TIMEOUT); -+ server_ctx->method = method; -+ server_ctx->iface = iface; -+ server_ctx->conn_cache = conn_cache; -+#ifdef MODULE_LOCAL -+ server_ctx->remote_addr = remote_addr; -+ server_ctx->remote_addr_len = remote_addr_len; -+ //SSR beg -+ server_ctx->protocol_plugin = new_obfs_class((char *)protocol); -+ if (server_ctx->protocol_plugin) { -+ server_ctx->protocol = server_ctx->protocol_plugin->new_obfs(); -+ server_ctx->protocol_global = server_ctx->protocol_plugin->init_data(); -+ } -+ -+ server_info _server_info; -+ memset(&_server_info, 0, sizeof(server_info)); -+ strcpy(_server_info.host, inet_ntoa(((struct sockaddr_in*)remote_addr)->sin_addr)); -+ _server_info.port = ((struct sockaddr_in*)remote_addr)->sin_port; -+ _server_info.port = _server_info.port >> 8 | _server_info.port << 8; -+ _server_info.g_data = server_ctx->protocol_global; -+ _server_info.param = (char *)protocol_param; -+ _server_info.key = enc_get_key(); -+ _server_info.key_len = enc_get_key_len(); -+ -+ if (server_ctx->protocol_plugin) -+ server_ctx->protocol_plugin->set_server_info(server_ctx->protocol, &_server_info); -+ //SSR end -+#ifdef MODULE_TUNNEL -+ server_ctx->tunnel_addr = tunnel_addr; -+#endif -+#endif -+ -+ ev_io_start(loop, &server_ctx->io); -+ -+ server_ctx_list[server_num++] = server_ctx; -+ -+ return 0; -+} -+ -+void -+free_udprelay() -+{ -+ struct ev_loop *loop = EV_DEFAULT; -+ while (server_num-- > 0) { -+ server_ctx_t *server_ctx = server_ctx_list[server_num]; -+ -+#ifdef MODULE_LOCAL -+ //SSR beg -+ if (server_ctx->protocol_plugin) { -+ server_ctx->protocol_plugin->dispose(server_ctx->protocol); -+ server_ctx->protocol = NULL; -+ free_obfs_class(server_ctx->protocol_plugin); -+ server_ctx->protocol_plugin = NULL; -+ } -+ //SSR end -+#endif -+ -+ ev_io_stop(loop, &server_ctx->io); -+ close(server_ctx->fd); -+ cache_delete(server_ctx->conn_cache, 0); -+ ss_free(server_ctx); -+ server_ctx_list[server_num] = NULL; -+ } -+} -diff --git a/server/udprelay.h b/server/udprelay.h -new file mode 100644 -index 0000000..89876d4 ---- /dev/null -+++ b/server/udprelay.h -@@ -0,0 +1,95 @@ -+/* -+ * udprelay.h - Define UDP relay's buffers and callbacks -+ * -+ * Copyright (C) 2013 - 2016, Max Lv -+ * -+ * This file is part of the shadowsocks-libev. -+ * -+ * shadowsocks-libev is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * shadowsocks-libev 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 General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with shadowsocks-libev; see the file COPYING. If not, see -+ * . -+ */ -+ -+#ifndef _UDPRELAY_H -+#define _UDPRELAY_H -+ -+#include -+#include -+ -+#include "encrypt.h" -+#include "jconf.h" -+#include "obfs.h" -+ -+#ifdef MODULE_REMOTE -+#include "resolv.h" -+#endif -+ -+#include "cache.h" -+ -+#include "common.h" -+ -+#define MAX_UDP_PACKET_SIZE (65507) -+ -+#define DEFAULT_PACKET_SIZE 1397 // 1492 - 1 - 28 - 2 - 64 = 1397, the default MTU for UDP relay -+ -+typedef struct server_ctx { -+ ev_io io; -+ int fd; -+ int method; -+ int auth; -+ int timeout; -+ const char *iface; -+ struct cache *conn_cache; -+#ifdef MODULE_LOCAL -+ const struct sockaddr *remote_addr; -+ int remote_addr_len; -+#ifdef MODULE_TUNNEL -+ ss_addr_t tunnel_addr; -+#endif -+#endif -+#ifdef MODULE_REMOTE -+ struct ev_loop *loop; -+#endif -+ // SSR -+ obfs *protocol; -+ obfs_class *protocol_plugin; -+ void *protocol_global; -+} server_ctx_t; -+ -+#ifdef MODULE_REMOTE -+typedef struct query_ctx { -+ struct ResolvQuery *query; -+ struct sockaddr_storage src_addr; -+ buffer_t *buf; -+ int addr_header_len; -+ char addr_header[384]; -+ struct server_ctx *server_ctx; -+ struct remote_ctx *remote_ctx; -+} query_ctx_t; -+#endif -+ -+typedef struct remote_ctx { -+ ev_io io; -+ ev_timer watcher; -+ int af; -+ int fd; -+ int addr_header_len; -+ char addr_header[384]; -+ struct sockaddr_storage src_addr; -+#ifdef MODULE_REMOTE -+ struct sockaddr_storage dst_addr; -+#endif -+ struct server_ctx *server_ctx; -+} remote_ctx_t; -+ -+#endif // _UDPRELAY_H -diff --git a/server/uthash.h b/server/uthash.h -new file mode 100644 -index 0000000..45d1f9f ---- /dev/null -+++ b/server/uthash.h -@@ -0,0 +1,1074 @@ -+/* -+Copyright (c) 2003-2016, Troy D. Hanson http://troydhanson.github.com/uthash/ -+All rights reserved. -+ -+Redistribution and use in source and binary forms, with or without -+modification, are permitted provided that the following conditions are met: -+ -+ * Redistributions of source code must retain the above copyright -+ notice, this list of conditions and the following disclaimer. -+ -+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. -+*/ -+ -+#ifndef UTHASH_H -+#define UTHASH_H -+ -+#define UTHASH_VERSION 2.0.1 -+ -+#include /* memcmp,strlen */ -+#include /* ptrdiff_t */ -+#include /* exit() */ -+ -+/* These macros use decltype or the earlier __typeof GNU extension. -+ As decltype is only available in newer compilers (VS2010 or gcc 4.3+ -+ when compiling c++ source) this code uses whatever method is needed -+ or, for VS2008 where neither is available, uses casting workarounds. */ -+#if defined(_MSC_VER) /* MS compiler */ -+#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ -+#define DECLTYPE(x) (decltype(x)) -+#else /* VS2008 or older (or VS2010 in C mode) */ -+#define NO_DECLTYPE -+#define DECLTYPE(x) -+#endif -+#elif defined(__BORLANDC__) || defined(__LCC__) || defined(__WATCOMC__) -+#define NO_DECLTYPE -+#define DECLTYPE(x) -+#else /* GNU, Sun and other compilers */ -+#define DECLTYPE(x) (__typeof(x)) -+#endif -+ -+#ifdef NO_DECLTYPE -+#define DECLTYPE_ASSIGN(dst,src) \ -+do { \ -+ char **_da_dst = (char**)(&(dst)); \ -+ *_da_dst = (char*)(src); \ -+} while (0) -+#else -+#define DECLTYPE_ASSIGN(dst,src) \ -+do { \ -+ (dst) = DECLTYPE(dst)(src); \ -+} while (0) -+#endif -+ -+/* a number of the hash function use uint32_t which isn't defined on Pre VS2010 */ -+#if defined(_WIN32) -+#if defined(_MSC_VER) && _MSC_VER >= 1600 -+#include -+#elif defined(__WATCOMC__) || defined(__MINGW32__) || defined(__CYGWIN__) -+#include -+#else -+typedef unsigned int uint32_t; -+typedef unsigned char uint8_t; -+#endif -+#elif defined(__GNUC__) && !defined(__VXWORKS__) -+#include -+#else -+typedef unsigned int uint32_t; -+typedef unsigned char uint8_t; -+#endif -+ -+#ifndef uthash_fatal -+#define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */ -+#endif -+#ifndef uthash_malloc -+#define uthash_malloc(sz) malloc(sz) /* malloc fcn */ -+#endif -+#ifndef uthash_free -+#define uthash_free(ptr,sz) free(ptr) /* free fcn */ -+#endif -+#ifndef uthash_strlen -+#define uthash_strlen(s) strlen(s) -+#endif -+#ifndef uthash_memcmp -+#define uthash_memcmp(a,b,n) memcmp(a,b,n) -+#endif -+ -+#ifndef uthash_noexpand_fyi -+#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */ -+#endif -+#ifndef uthash_expand_fyi -+#define uthash_expand_fyi(tbl) /* can be defined to log expands */ -+#endif -+ -+/* initial number of buckets */ -+#define HASH_INITIAL_NUM_BUCKETS 32U /* initial number of buckets */ -+#define HASH_INITIAL_NUM_BUCKETS_LOG2 5U /* lg2 of initial number of buckets */ -+#define HASH_BKT_CAPACITY_THRESH 10U /* expand when bucket count reaches */ -+ -+/* calculate the element whose hash handle address is hhp */ -+#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho))) -+/* calculate the hash handle from element address elp */ -+#define HH_FROM_ELMT(tbl,elp) ((UT_hash_handle *)(((char*)(elp)) + ((tbl)->hho))) -+ -+#define HASH_VALUE(keyptr,keylen,hashv) \ -+do { \ -+ HASH_FCN(keyptr, keylen, hashv); \ -+} while (0) -+ -+#define HASH_FIND_BYHASHVALUE(hh,head,keyptr,keylen,hashval,out) \ -+do { \ -+ (out) = NULL; \ -+ if (head) { \ -+ unsigned _hf_bkt; \ -+ HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _hf_bkt); \ -+ if (HASH_BLOOM_TEST((head)->hh.tbl, hashval) != 0) { \ -+ HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], keyptr, keylen, hashval, out); \ -+ } \ -+ } \ -+} while (0) -+ -+#define HASH_FIND(hh,head,keyptr,keylen,out) \ -+do { \ -+ unsigned _hf_hashv; \ -+ HASH_VALUE(keyptr, keylen, _hf_hashv); \ -+ HASH_FIND_BYHASHVALUE(hh, head, keyptr, keylen, _hf_hashv, out); \ -+} while (0) -+ -+#ifdef HASH_BLOOM -+#define HASH_BLOOM_BITLEN (1UL << HASH_BLOOM) -+#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8UL) + (((HASH_BLOOM_BITLEN%8UL)!=0UL) ? 1UL : 0UL) -+#define HASH_BLOOM_MAKE(tbl) \ -+do { \ -+ (tbl)->bloom_nbits = HASH_BLOOM; \ -+ (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \ -+ if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \ -+ memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \ -+ (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \ -+} while (0) -+ -+#define HASH_BLOOM_FREE(tbl) \ -+do { \ -+ uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ -+} while (0) -+ -+#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8U] |= (1U << ((idx)%8U))) -+#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8U] & (1U << ((idx)%8U))) -+ -+#define HASH_BLOOM_ADD(tbl,hashv) \ -+ HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1U))) -+ -+#define HASH_BLOOM_TEST(tbl,hashv) \ -+ HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1U))) -+ -+#else -+#define HASH_BLOOM_MAKE(tbl) -+#define HASH_BLOOM_FREE(tbl) -+#define HASH_BLOOM_ADD(tbl,hashv) -+#define HASH_BLOOM_TEST(tbl,hashv) (1) -+#define HASH_BLOOM_BYTELEN 0U -+#endif -+ -+#define HASH_MAKE_TABLE(hh,head) \ -+do { \ -+ (head)->hh.tbl = (UT_hash_table*)uthash_malloc( \ -+ sizeof(UT_hash_table)); \ -+ if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \ -+ memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \ -+ (head)->hh.tbl->tail = &((head)->hh); \ -+ (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \ -+ (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \ -+ (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \ -+ (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \ -+ HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ -+ if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \ -+ memset((head)->hh.tbl->buckets, 0, \ -+ HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ -+ HASH_BLOOM_MAKE((head)->hh.tbl); \ -+ (head)->hh.tbl->signature = HASH_SIGNATURE; \ -+} while (0) -+ -+#define HASH_REPLACE_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,replaced,cmpfcn) \ -+do { \ -+ (replaced) = NULL; \ -+ HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ -+ if (replaced) { \ -+ HASH_DELETE(hh, head, replaced); \ -+ } \ -+ HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn); \ -+} while (0) -+ -+#define HASH_REPLACE_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add,replaced) \ -+do { \ -+ (replaced) = NULL; \ -+ HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ -+ if (replaced) { \ -+ HASH_DELETE(hh, head, replaced); \ -+ } \ -+ HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add); \ -+} while (0) -+ -+#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced) \ -+do { \ -+ unsigned _hr_hashv; \ -+ HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ -+ HASH_REPLACE_BYHASHVALUE(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced); \ -+} while (0) -+ -+#define HASH_REPLACE_INORDER(hh,head,fieldname,keylen_in,add,replaced,cmpfcn) \ -+do { \ -+ unsigned _hr_hashv; \ -+ HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ -+ HASH_REPLACE_BYHASHVALUE_INORDER(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced, cmpfcn); \ -+} while (0) -+ -+#define HASH_APPEND_LIST(hh, head, add) \ -+do { \ -+ (add)->hh.next = NULL; \ -+ (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \ -+ (head)->hh.tbl->tail->next = (add); \ -+ (head)->hh.tbl->tail = &((add)->hh); \ -+} while (0) -+ -+#define HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh,head,keyptr,keylen_in,hashval,add,cmpfcn) \ -+do { \ -+ unsigned _ha_bkt; \ -+ (add)->hh.hashv = (hashval); \ -+ (add)->hh.key = (char*) (keyptr); \ -+ (add)->hh.keylen = (unsigned) (keylen_in); \ -+ if (!(head)) { \ -+ (add)->hh.next = NULL; \ -+ (add)->hh.prev = NULL; \ -+ (head) = (add); \ -+ HASH_MAKE_TABLE(hh, head); \ -+ } else { \ -+ struct UT_hash_handle *_hs_iter = &(head)->hh; \ -+ (add)->hh.tbl = (head)->hh.tbl; \ -+ do { \ -+ if (cmpfcn(DECLTYPE(head) ELMT_FROM_HH((head)->hh.tbl, _hs_iter), add) > 0) \ -+ break; \ -+ } while ((_hs_iter = _hs_iter->next)); \ -+ if (_hs_iter) { \ -+ (add)->hh.next = _hs_iter; \ -+ if (((add)->hh.prev = _hs_iter->prev)) { \ -+ HH_FROM_ELMT((head)->hh.tbl, _hs_iter->prev)->next = (add); \ -+ } else { \ -+ (head) = (add); \ -+ } \ -+ _hs_iter->prev = (add); \ -+ } else { \ -+ HASH_APPEND_LIST(hh, head, add); \ -+ } \ -+ } \ -+ (head)->hh.tbl->num_items++; \ -+ HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ -+ HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], &(add)->hh); \ -+ HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ -+ HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ -+ HASH_FSCK(hh, head); \ -+} while (0) -+ -+#define HASH_ADD_KEYPTR_INORDER(hh,head,keyptr,keylen_in,add,cmpfcn) \ -+do { \ -+ unsigned _hs_hashv; \ -+ HASH_VALUE(keyptr, keylen_in, _hs_hashv); \ -+ HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, keyptr, keylen_in, _hs_hashv, add, cmpfcn); \ -+} while (0) -+ -+#define HASH_ADD_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,cmpfcn) \ -+ HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn) -+ -+#define HASH_ADD_INORDER(hh,head,fieldname,keylen_in,add,cmpfcn) \ -+ HASH_ADD_KEYPTR_INORDER(hh, head, &((add)->fieldname), keylen_in, add, cmpfcn) -+ -+#define HASH_ADD_KEYPTR_BYHASHVALUE(hh,head,keyptr,keylen_in,hashval,add) \ -+do { \ -+ unsigned _ha_bkt; \ -+ (add)->hh.hashv = (hashval); \ -+ (add)->hh.key = (char*) (keyptr); \ -+ (add)->hh.keylen = (unsigned) (keylen_in); \ -+ if (!(head)) { \ -+ (add)->hh.next = NULL; \ -+ (add)->hh.prev = NULL; \ -+ (head) = (add); \ -+ HASH_MAKE_TABLE(hh, head); \ -+ } else { \ -+ (add)->hh.tbl = (head)->hh.tbl; \ -+ HASH_APPEND_LIST(hh, head, add); \ -+ } \ -+ (head)->hh.tbl->num_items++; \ -+ HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ -+ HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], &(add)->hh); \ -+ HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ -+ HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ -+ HASH_FSCK(hh, head); \ -+} while (0) -+ -+#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \ -+do { \ -+ unsigned _ha_hashv; \ -+ HASH_VALUE(keyptr, keylen_in, _ha_hashv); \ -+ HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, keyptr, keylen_in, _ha_hashv, add); \ -+} while (0) -+ -+#define HASH_ADD_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add) \ -+ HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add) -+ -+#define HASH_ADD(hh,head,fieldname,keylen_in,add) \ -+ HASH_ADD_KEYPTR(hh, head, &((add)->fieldname), keylen_in, add) -+ -+#define HASH_TO_BKT(hashv,num_bkts,bkt) \ -+do { \ -+ bkt = ((hashv) & ((num_bkts) - 1U)); \ -+} while (0) -+ -+/* delete "delptr" from the hash table. -+ * "the usual" patch-up process for the app-order doubly-linked-list. -+ * The use of _hd_hh_del below deserves special explanation. -+ * These used to be expressed using (delptr) but that led to a bug -+ * if someone used the same symbol for the head and deletee, like -+ * HASH_DELETE(hh,users,users); -+ * We want that to work, but by changing the head (users) below -+ * we were forfeiting our ability to further refer to the deletee (users) -+ * in the patch-up process. Solution: use scratch space to -+ * copy the deletee pointer, then the latter references are via that -+ * scratch pointer rather than through the repointed (users) symbol. -+ */ -+#define HASH_DELETE(hh,head,delptr) \ -+do { \ -+ struct UT_hash_handle *_hd_hh_del; \ -+ if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \ -+ uthash_free((head)->hh.tbl->buckets, \ -+ (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \ -+ HASH_BLOOM_FREE((head)->hh.tbl); \ -+ uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ -+ head = NULL; \ -+ } else { \ -+ unsigned _hd_bkt; \ -+ _hd_hh_del = &((delptr)->hh); \ -+ if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \ -+ (head)->hh.tbl->tail = \ -+ (UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \ -+ (head)->hh.tbl->hho); \ -+ } \ -+ if ((delptr)->hh.prev != NULL) { \ -+ ((UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \ -+ (head)->hh.tbl->hho))->next = (delptr)->hh.next; \ -+ } else { \ -+ DECLTYPE_ASSIGN(head,(delptr)->hh.next); \ -+ } \ -+ if (_hd_hh_del->next != NULL) { \ -+ ((UT_hash_handle*)((ptrdiff_t)_hd_hh_del->next + \ -+ (head)->hh.tbl->hho))->prev = \ -+ _hd_hh_del->prev; \ -+ } \ -+ HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ -+ HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \ -+ (head)->hh.tbl->num_items--; \ -+ } \ -+ HASH_FSCK(hh,head); \ -+} while (0) -+ -+ -+/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */ -+#define HASH_FIND_STR(head,findstr,out) \ -+ HASH_FIND(hh,head,findstr,(unsigned)uthash_strlen(findstr),out) -+#define HASH_ADD_STR(head,strfield,add) \ -+ HASH_ADD(hh,head,strfield[0],(unsigned)uthash_strlen(add->strfield),add) -+#define HASH_REPLACE_STR(head,strfield,add,replaced) \ -+ HASH_REPLACE(hh,head,strfield[0],(unsigned)uthash_strlen(add->strfield),add,replaced) -+#define HASH_FIND_INT(head,findint,out) \ -+ HASH_FIND(hh,head,findint,sizeof(int),out) -+#define HASH_ADD_INT(head,intfield,add) \ -+ HASH_ADD(hh,head,intfield,sizeof(int),add) -+#define HASH_REPLACE_INT(head,intfield,add,replaced) \ -+ HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced) -+#define HASH_FIND_PTR(head,findptr,out) \ -+ HASH_FIND(hh,head,findptr,sizeof(void *),out) -+#define HASH_ADD_PTR(head,ptrfield,add) \ -+ HASH_ADD(hh,head,ptrfield,sizeof(void *),add) -+#define HASH_REPLACE_PTR(head,ptrfield,add,replaced) \ -+ HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced) -+#define HASH_DEL(head,delptr) \ -+ HASH_DELETE(hh,head,delptr) -+ -+/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined. -+ * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined. -+ */ -+#ifdef HASH_DEBUG -+#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0) -+#define HASH_FSCK(hh,head) \ -+do { \ -+ struct UT_hash_handle *_thh; \ -+ if (head) { \ -+ unsigned _bkt_i; \ -+ unsigned _count; \ -+ char *_prev; \ -+ _count = 0; \ -+ for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \ -+ unsigned _bkt_count = 0; \ -+ _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \ -+ _prev = NULL; \ -+ while (_thh) { \ -+ if (_prev != (char*)(_thh->hh_prev)) { \ -+ HASH_OOPS("invalid hh_prev %p, actual %p\n", \ -+ _thh->hh_prev, _prev ); \ -+ } \ -+ _bkt_count++; \ -+ _prev = (char*)(_thh); \ -+ _thh = _thh->hh_next; \ -+ } \ -+ _count += _bkt_count; \ -+ if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \ -+ HASH_OOPS("invalid bucket count %u, actual %u\n", \ -+ (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \ -+ } \ -+ } \ -+ if (_count != (head)->hh.tbl->num_items) { \ -+ HASH_OOPS("invalid hh item count %u, actual %u\n", \ -+ (head)->hh.tbl->num_items, _count ); \ -+ } \ -+ /* traverse hh in app order; check next/prev integrity, count */ \ -+ _count = 0; \ -+ _prev = NULL; \ -+ _thh = &(head)->hh; \ -+ while (_thh) { \ -+ _count++; \ -+ if (_prev !=(char*)(_thh->prev)) { \ -+ HASH_OOPS("invalid prev %p, actual %p\n", \ -+ _thh->prev, _prev ); \ -+ } \ -+ _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \ -+ _thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \ -+ (head)->hh.tbl->hho) : NULL ); \ -+ } \ -+ if (_count != (head)->hh.tbl->num_items) { \ -+ HASH_OOPS("invalid app item count %u, actual %u\n", \ -+ (head)->hh.tbl->num_items, _count ); \ -+ } \ -+ } \ -+} while (0) -+#else -+#define HASH_FSCK(hh,head) -+#endif -+ -+/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to -+ * the descriptor to which this macro is defined for tuning the hash function. -+ * The app can #include to get the prototype for write(2). */ -+#ifdef HASH_EMIT_KEYS -+#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \ -+do { \ -+ unsigned _klen = fieldlen; \ -+ write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \ -+ write(HASH_EMIT_KEYS, keyptr, (unsigned long)fieldlen); \ -+} while (0) -+#else -+#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) -+#endif -+ -+/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */ -+#ifdef HASH_FUNCTION -+#define HASH_FCN HASH_FUNCTION -+#else -+#define HASH_FCN HASH_JEN -+#endif -+ -+/* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */ -+#define HASH_BER(key,keylen,hashv) \ -+do { \ -+ unsigned _hb_keylen=(unsigned)keylen; \ -+ const unsigned char *_hb_key=(const unsigned char*)(key); \ -+ (hashv) = 0; \ -+ while (_hb_keylen-- != 0U) { \ -+ (hashv) = (((hashv) << 5) + (hashv)) + *_hb_key++; \ -+ } \ -+} while (0) -+ -+ -+/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at -+ * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */ -+#define HASH_SAX(key,keylen,hashv) \ -+do { \ -+ unsigned _sx_i; \ -+ const unsigned char *_hs_key=(const unsigned char*)(key); \ -+ hashv = 0; \ -+ for(_sx_i=0; _sx_i < keylen; _sx_i++) { \ -+ hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \ -+ } \ -+} while (0) -+/* FNV-1a variation */ -+#define HASH_FNV(key,keylen,hashv) \ -+do { \ -+ unsigned _fn_i; \ -+ const unsigned char *_hf_key=(const unsigned char*)(key); \ -+ hashv = 2166136261U; \ -+ for(_fn_i=0; _fn_i < keylen; _fn_i++) { \ -+ hashv = hashv ^ _hf_key[_fn_i]; \ -+ hashv = hashv * 16777619U; \ -+ } \ -+} while (0) -+ -+#define HASH_OAT(key,keylen,hashv) \ -+do { \ -+ unsigned _ho_i; \ -+ const unsigned char *_ho_key=(const unsigned char*)(key); \ -+ hashv = 0; \ -+ for(_ho_i=0; _ho_i < keylen; _ho_i++) { \ -+ hashv += _ho_key[_ho_i]; \ -+ hashv += (hashv << 10); \ -+ hashv ^= (hashv >> 6); \ -+ } \ -+ hashv += (hashv << 3); \ -+ hashv ^= (hashv >> 11); \ -+ hashv += (hashv << 15); \ -+} while (0) -+ -+#define HASH_JEN_MIX(a,b,c) \ -+do { \ -+ a -= b; a -= c; a ^= ( c >> 13 ); \ -+ b -= c; b -= a; b ^= ( a << 8 ); \ -+ c -= a; c -= b; c ^= ( b >> 13 ); \ -+ a -= b; a -= c; a ^= ( c >> 12 ); \ -+ b -= c; b -= a; b ^= ( a << 16 ); \ -+ c -= a; c -= b; c ^= ( b >> 5 ); \ -+ a -= b; a -= c; a ^= ( c >> 3 ); \ -+ b -= c; b -= a; b ^= ( a << 10 ); \ -+ c -= a; c -= b; c ^= ( b >> 15 ); \ -+} while (0) -+ -+#define HASH_JEN(key,keylen,hashv) \ -+do { \ -+ unsigned _hj_i,_hj_j,_hj_k; \ -+ unsigned const char *_hj_key=(unsigned const char*)(key); \ -+ hashv = 0xfeedbeefu; \ -+ _hj_i = _hj_j = 0x9e3779b9u; \ -+ _hj_k = (unsigned)(keylen); \ -+ while (_hj_k >= 12U) { \ -+ _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \ -+ + ( (unsigned)_hj_key[2] << 16 ) \ -+ + ( (unsigned)_hj_key[3] << 24 ) ); \ -+ _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \ -+ + ( (unsigned)_hj_key[6] << 16 ) \ -+ + ( (unsigned)_hj_key[7] << 24 ) ); \ -+ hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \ -+ + ( (unsigned)_hj_key[10] << 16 ) \ -+ + ( (unsigned)_hj_key[11] << 24 ) ); \ -+ \ -+ HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ -+ \ -+ _hj_key += 12; \ -+ _hj_k -= 12U; \ -+ } \ -+ hashv += (unsigned)(keylen); \ -+ switch ( _hj_k ) { \ -+ case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); /* FALLTHROUGH */ \ -+ case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); /* FALLTHROUGH */ \ -+ case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); /* FALLTHROUGH */ \ -+ case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); /* FALLTHROUGH */ \ -+ case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); /* FALLTHROUGH */ \ -+ case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); /* FALLTHROUGH */ \ -+ case 5: _hj_j += _hj_key[4]; /* FALLTHROUGH */ \ -+ case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); /* FALLTHROUGH */ \ -+ case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); /* FALLTHROUGH */ \ -+ case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); /* FALLTHROUGH */ \ -+ case 1: _hj_i += _hj_key[0]; \ -+ } \ -+ HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ -+} while (0) -+ -+/* The Paul Hsieh hash function */ -+#undef get16bits -+#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ -+ || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) -+#define get16bits(d) (*((const uint16_t *) (d))) -+#endif -+ -+#if !defined (get16bits) -+#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \ -+ +(uint32_t)(((const uint8_t *)(d))[0]) ) -+#endif -+#define HASH_SFH(key,keylen,hashv) \ -+do { \ -+ unsigned const char *_sfh_key=(unsigned const char*)(key); \ -+ uint32_t _sfh_tmp, _sfh_len = (uint32_t)keylen; \ -+ \ -+ unsigned _sfh_rem = _sfh_len & 3U; \ -+ _sfh_len >>= 2; \ -+ hashv = 0xcafebabeu; \ -+ \ -+ /* Main loop */ \ -+ for (;_sfh_len > 0U; _sfh_len--) { \ -+ hashv += get16bits (_sfh_key); \ -+ _sfh_tmp = ((uint32_t)(get16bits (_sfh_key+2)) << 11) ^ hashv; \ -+ hashv = (hashv << 16) ^ _sfh_tmp; \ -+ _sfh_key += 2U*sizeof (uint16_t); \ -+ hashv += hashv >> 11; \ -+ } \ -+ \ -+ /* Handle end cases */ \ -+ switch (_sfh_rem) { \ -+ case 3: hashv += get16bits (_sfh_key); \ -+ hashv ^= hashv << 16; \ -+ hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)]) << 18; \ -+ hashv += hashv >> 11; \ -+ break; \ -+ case 2: hashv += get16bits (_sfh_key); \ -+ hashv ^= hashv << 11; \ -+ hashv += hashv >> 17; \ -+ break; \ -+ case 1: hashv += *_sfh_key; \ -+ hashv ^= hashv << 10; \ -+ hashv += hashv >> 1; \ -+ } \ -+ \ -+ /* Force "avalanching" of final 127 bits */ \ -+ hashv ^= hashv << 3; \ -+ hashv += hashv >> 5; \ -+ hashv ^= hashv << 4; \ -+ hashv += hashv >> 17; \ -+ hashv ^= hashv << 25; \ -+ hashv += hashv >> 6; \ -+} while (0) -+ -+#ifdef HASH_USING_NO_STRICT_ALIASING -+/* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads. -+ * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error. -+ * MurmurHash uses the faster approach only on CPU's where we know it's safe. -+ * -+ * Note the preprocessor built-in defines can be emitted using: -+ * -+ * gcc -m64 -dM -E - < /dev/null (on gcc) -+ * cc -## a.c (where a.c is a simple test file) (Sun Studio) -+ */ -+#if (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86)) -+#define MUR_GETBLOCK(p,i) p[i] -+#else /* non intel */ -+#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 3UL) == 0UL) -+#define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 3UL) == 1UL) -+#define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 3UL) == 2UL) -+#define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 3UL) == 3UL) -+#define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL)) -+#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__)) -+#define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24)) -+#define MUR_TWO_TWO(p) ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16)) -+#define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >> 8)) -+#else /* assume little endian non-intel */ -+#define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24)) -+#define MUR_TWO_TWO(p) ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16)) -+#define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) << 8)) -+#endif -+#define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) : \ -+ (MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \ -+ (MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) : \ -+ MUR_ONE_THREE(p)))) -+#endif -+#define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r)))) -+#define MUR_FMIX(_h) \ -+do { \ -+ _h ^= _h >> 16; \ -+ _h *= 0x85ebca6bu; \ -+ _h ^= _h >> 13; \ -+ _h *= 0xc2b2ae35u; \ -+ _h ^= _h >> 16; \ -+} while (0) -+ -+#define HASH_MUR(key,keylen,hashv) \ -+do { \ -+ const uint8_t *_mur_data = (const uint8_t*)(key); \ -+ const int _mur_nblocks = (int)(keylen) / 4; \ -+ uint32_t _mur_h1 = 0xf88D5353u; \ -+ uint32_t _mur_c1 = 0xcc9e2d51u; \ -+ uint32_t _mur_c2 = 0x1b873593u; \ -+ uint32_t _mur_k1 = 0; \ -+ const uint8_t *_mur_tail; \ -+ const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+(_mur_nblocks*4)); \ -+ int _mur_i; \ -+ for(_mur_i = -_mur_nblocks; _mur_i!=0; _mur_i++) { \ -+ _mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i); \ -+ _mur_k1 *= _mur_c1; \ -+ _mur_k1 = MUR_ROTL32(_mur_k1,15); \ -+ _mur_k1 *= _mur_c2; \ -+ \ -+ _mur_h1 ^= _mur_k1; \ -+ _mur_h1 = MUR_ROTL32(_mur_h1,13); \ -+ _mur_h1 = (_mur_h1*5U) + 0xe6546b64u; \ -+ } \ -+ _mur_tail = (const uint8_t*)(_mur_data + (_mur_nblocks*4)); \ -+ _mur_k1=0; \ -+ switch((keylen) & 3U) { \ -+ case 3: _mur_k1 ^= (uint32_t)_mur_tail[2] << 16; /* FALLTHROUGH */ \ -+ case 2: _mur_k1 ^= (uint32_t)_mur_tail[1] << 8; /* FALLTHROUGH */ \ -+ case 1: _mur_k1 ^= (uint32_t)_mur_tail[0]; \ -+ _mur_k1 *= _mur_c1; \ -+ _mur_k1 = MUR_ROTL32(_mur_k1,15); \ -+ _mur_k1 *= _mur_c2; \ -+ _mur_h1 ^= _mur_k1; \ -+ } \ -+ _mur_h1 ^= (uint32_t)(keylen); \ -+ MUR_FMIX(_mur_h1); \ -+ hashv = _mur_h1; \ -+} while (0) -+#endif /* HASH_USING_NO_STRICT_ALIASING */ -+ -+/* iterate over items in a known bucket to find desired item */ -+#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,hashval,out) \ -+do { \ -+ if ((head).hh_head != NULL) { \ -+ DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (head).hh_head)); \ -+ } else { \ -+ (out) = NULL; \ -+ } \ -+ while ((out) != NULL) { \ -+ if ((out)->hh.hashv == (hashval) && (out)->hh.keylen == (keylen_in)) { \ -+ if (uthash_memcmp((out)->hh.key, keyptr, keylen_in) == 0) { \ -+ break; \ -+ } \ -+ } \ -+ if ((out)->hh.hh_next != NULL) { \ -+ DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (out)->hh.hh_next)); \ -+ } else { \ -+ (out) = NULL; \ -+ } \ -+ } \ -+} while (0) -+ -+/* add an item to a bucket */ -+#define HASH_ADD_TO_BKT(head,addhh) \ -+do { \ -+ head.count++; \ -+ (addhh)->hh_next = head.hh_head; \ -+ (addhh)->hh_prev = NULL; \ -+ if (head.hh_head != NULL) { (head).hh_head->hh_prev = (addhh); } \ -+ (head).hh_head=addhh; \ -+ if ((head.count >= ((head.expand_mult+1U) * HASH_BKT_CAPACITY_THRESH)) \ -+ && ((addhh)->tbl->noexpand != 1U)) { \ -+ HASH_EXPAND_BUCKETS((addhh)->tbl); \ -+ } \ -+} while (0) -+ -+/* remove an item from a given bucket */ -+#define HASH_DEL_IN_BKT(hh,head,hh_del) \ -+ (head).count--; \ -+ if ((head).hh_head == hh_del) { \ -+ (head).hh_head = hh_del->hh_next; \ -+ } \ -+ if (hh_del->hh_prev) { \ -+ hh_del->hh_prev->hh_next = hh_del->hh_next; \ -+ } \ -+ if (hh_del->hh_next) { \ -+ hh_del->hh_next->hh_prev = hh_del->hh_prev; \ -+ } -+ -+/* Bucket expansion has the effect of doubling the number of buckets -+ * and redistributing the items into the new buckets. Ideally the -+ * items will distribute more or less evenly into the new buckets -+ * (the extent to which this is true is a measure of the quality of -+ * the hash function as it applies to the key domain). -+ * -+ * With the items distributed into more buckets, the chain length -+ * (item count) in each bucket is reduced. Thus by expanding buckets -+ * the hash keeps a bound on the chain length. This bounded chain -+ * length is the essence of how a hash provides constant time lookup. -+ * -+ * The calculation of tbl->ideal_chain_maxlen below deserves some -+ * explanation. First, keep in mind that we're calculating the ideal -+ * maximum chain length based on the *new* (doubled) bucket count. -+ * In fractions this is just n/b (n=number of items,b=new num buckets). -+ * Since the ideal chain length is an integer, we want to calculate -+ * ceil(n/b). We don't depend on floating point arithmetic in this -+ * hash, so to calculate ceil(n/b) with integers we could write -+ * -+ * ceil(n/b) = (n/b) + ((n%b)?1:0) -+ * -+ * and in fact a previous version of this hash did just that. -+ * But now we have improved things a bit by recognizing that b is -+ * always a power of two. We keep its base 2 log handy (call it lb), -+ * so now we can write this with a bit shift and logical AND: -+ * -+ * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0) -+ * -+ */ -+#define HASH_EXPAND_BUCKETS(tbl) \ -+do { \ -+ unsigned _he_bkt; \ -+ unsigned _he_bkt_i; \ -+ struct UT_hash_handle *_he_thh, *_he_hh_nxt; \ -+ UT_hash_bucket *_he_new_buckets, *_he_newbkt; \ -+ _he_new_buckets = (UT_hash_bucket*)uthash_malloc( \ -+ 2UL * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ -+ if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \ -+ memset(_he_new_buckets, 0, \ -+ 2UL * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ -+ tbl->ideal_chain_maxlen = \ -+ (tbl->num_items >> (tbl->log2_num_buckets+1U)) + \ -+ (((tbl->num_items & ((tbl->num_buckets*2U)-1U)) != 0U) ? 1U : 0U); \ -+ tbl->nonideal_items = 0; \ -+ for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \ -+ { \ -+ _he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \ -+ while (_he_thh != NULL) { \ -+ _he_hh_nxt = _he_thh->hh_next; \ -+ HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2U, _he_bkt); \ -+ _he_newbkt = &(_he_new_buckets[ _he_bkt ]); \ -+ if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \ -+ tbl->nonideal_items++; \ -+ _he_newbkt->expand_mult = _he_newbkt->count / \ -+ tbl->ideal_chain_maxlen; \ -+ } \ -+ _he_thh->hh_prev = NULL; \ -+ _he_thh->hh_next = _he_newbkt->hh_head; \ -+ if (_he_newbkt->hh_head != NULL) { _he_newbkt->hh_head->hh_prev = \ -+ _he_thh; } \ -+ _he_newbkt->hh_head = _he_thh; \ -+ _he_thh = _he_hh_nxt; \ -+ } \ -+ } \ -+ uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \ -+ tbl->num_buckets *= 2U; \ -+ tbl->log2_num_buckets++; \ -+ tbl->buckets = _he_new_buckets; \ -+ tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \ -+ (tbl->ineff_expands+1U) : 0U; \ -+ if (tbl->ineff_expands > 1U) { \ -+ tbl->noexpand=1; \ -+ uthash_noexpand_fyi(tbl); \ -+ } \ -+ uthash_expand_fyi(tbl); \ -+} while (0) -+ -+ -+/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */ -+/* Note that HASH_SORT assumes the hash handle name to be hh. -+ * HASH_SRT was added to allow the hash handle name to be passed in. */ -+#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn) -+#define HASH_SRT(hh,head,cmpfcn) \ -+do { \ -+ unsigned _hs_i; \ -+ unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \ -+ struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \ -+ if (head != NULL) { \ -+ _hs_insize = 1; \ -+ _hs_looping = 1; \ -+ _hs_list = &((head)->hh); \ -+ while (_hs_looping != 0U) { \ -+ _hs_p = _hs_list; \ -+ _hs_list = NULL; \ -+ _hs_tail = NULL; \ -+ _hs_nmerges = 0; \ -+ while (_hs_p != NULL) { \ -+ _hs_nmerges++; \ -+ _hs_q = _hs_p; \ -+ _hs_psize = 0; \ -+ for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \ -+ _hs_psize++; \ -+ _hs_q = (UT_hash_handle*)((_hs_q->next != NULL) ? \ -+ ((void*)((char*)(_hs_q->next) + \ -+ (head)->hh.tbl->hho)) : NULL); \ -+ if (! (_hs_q) ) { break; } \ -+ } \ -+ _hs_qsize = _hs_insize; \ -+ while ((_hs_psize > 0U) || ((_hs_qsize > 0U) && (_hs_q != NULL))) {\ -+ if (_hs_psize == 0U) { \ -+ _hs_e = _hs_q; \ -+ _hs_q = (UT_hash_handle*)((_hs_q->next != NULL) ? \ -+ ((void*)((char*)(_hs_q->next) + \ -+ (head)->hh.tbl->hho)) : NULL); \ -+ _hs_qsize--; \ -+ } else if ( (_hs_qsize == 0U) || (_hs_q == NULL) ) { \ -+ _hs_e = _hs_p; \ -+ if (_hs_p != NULL){ \ -+ _hs_p = (UT_hash_handle*)((_hs_p->next != NULL) ? \ -+ ((void*)((char*)(_hs_p->next) + \ -+ (head)->hh.tbl->hho)) : NULL); \ -+ } \ -+ _hs_psize--; \ -+ } else if (( \ -+ cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \ -+ DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \ -+ ) <= 0) { \ -+ _hs_e = _hs_p; \ -+ if (_hs_p != NULL){ \ -+ _hs_p = (UT_hash_handle*)((_hs_p->next != NULL) ? \ -+ ((void*)((char*)(_hs_p->next) + \ -+ (head)->hh.tbl->hho)) : NULL); \ -+ } \ -+ _hs_psize--; \ -+ } else { \ -+ _hs_e = _hs_q; \ -+ _hs_q = (UT_hash_handle*)((_hs_q->next != NULL) ? \ -+ ((void*)((char*)(_hs_q->next) + \ -+ (head)->hh.tbl->hho)) : NULL); \ -+ _hs_qsize--; \ -+ } \ -+ if ( _hs_tail != NULL ) { \ -+ _hs_tail->next = ((_hs_e != NULL) ? \ -+ ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \ -+ } else { \ -+ _hs_list = _hs_e; \ -+ } \ -+ if (_hs_e != NULL) { \ -+ _hs_e->prev = ((_hs_tail != NULL) ? \ -+ ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \ -+ } \ -+ _hs_tail = _hs_e; \ -+ } \ -+ _hs_p = _hs_q; \ -+ } \ -+ if (_hs_tail != NULL){ \ -+ _hs_tail->next = NULL; \ -+ } \ -+ if ( _hs_nmerges <= 1U ) { \ -+ _hs_looping=0; \ -+ (head)->hh.tbl->tail = _hs_tail; \ -+ DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \ -+ } \ -+ _hs_insize *= 2U; \ -+ } \ -+ HASH_FSCK(hh,head); \ -+ } \ -+} while (0) -+ -+/* This function selects items from one hash into another hash. -+ * The end result is that the selected items have dual presence -+ * in both hashes. There is no copy of the items made; rather -+ * they are added into the new hash through a secondary hash -+ * hash handle that must be present in the structure. */ -+#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \ -+do { \ -+ unsigned _src_bkt, _dst_bkt; \ -+ void *_last_elt=NULL, *_elt; \ -+ UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \ -+ ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \ -+ if (src != NULL) { \ -+ for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \ -+ for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \ -+ _src_hh != NULL; \ -+ _src_hh = _src_hh->hh_next) { \ -+ _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \ -+ if (cond(_elt)) { \ -+ _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \ -+ _dst_hh->key = _src_hh->key; \ -+ _dst_hh->keylen = _src_hh->keylen; \ -+ _dst_hh->hashv = _src_hh->hashv; \ -+ _dst_hh->prev = _last_elt; \ -+ _dst_hh->next = NULL; \ -+ if (_last_elt_hh != NULL) { _last_elt_hh->next = _elt; } \ -+ if (dst == NULL) { \ -+ DECLTYPE_ASSIGN(dst,_elt); \ -+ HASH_MAKE_TABLE(hh_dst,dst); \ -+ } else { \ -+ _dst_hh->tbl = (dst)->hh_dst.tbl; \ -+ } \ -+ HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \ -+ HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \ -+ (dst)->hh_dst.tbl->num_items++; \ -+ _last_elt = _elt; \ -+ _last_elt_hh = _dst_hh; \ -+ } \ -+ } \ -+ } \ -+ } \ -+ HASH_FSCK(hh_dst,dst); \ -+} while (0) -+ -+#define HASH_CLEAR(hh,head) \ -+do { \ -+ if (head != NULL) { \ -+ uthash_free((head)->hh.tbl->buckets, \ -+ (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \ -+ HASH_BLOOM_FREE((head)->hh.tbl); \ -+ uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ -+ (head)=NULL; \ -+ } \ -+} while (0) -+ -+#define HASH_OVERHEAD(hh,head) \ -+ ((head != NULL) ? ( \ -+ (size_t)(((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \ -+ ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \ -+ sizeof(UT_hash_table) + \ -+ (HASH_BLOOM_BYTELEN))) : 0U) -+ -+#ifdef NO_DECLTYPE -+#define HASH_ITER(hh,head,el,tmp) \ -+for(((el)=(head)), ((*(char**)(&(tmp)))=(char*)((head!=NULL)?(head)->hh.next:NULL)); \ -+ (el) != NULL; ((el)=(tmp)), ((*(char**)(&(tmp)))=(char*)((tmp!=NULL)?(tmp)->hh.next:NULL))) -+#else -+#define HASH_ITER(hh,head,el,tmp) \ -+for(((el)=(head)), ((tmp)=DECLTYPE(el)((head!=NULL)?(head)->hh.next:NULL)); \ -+ (el) != NULL; ((el)=(tmp)), ((tmp)=DECLTYPE(el)((tmp!=NULL)?(tmp)->hh.next:NULL))) -+#endif -+ -+/* obtain a count of items in the hash */ -+#define HASH_COUNT(head) HASH_CNT(hh,head) -+#define HASH_CNT(hh,head) ((head != NULL)?((head)->hh.tbl->num_items):0U) -+ -+typedef struct UT_hash_bucket { -+ struct UT_hash_handle *hh_head; -+ unsigned count; -+ -+ /* expand_mult is normally set to 0. In this situation, the max chain length -+ * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If -+ * the bucket's chain exceeds this length, bucket expansion is triggered). -+ * However, setting expand_mult to a non-zero value delays bucket expansion -+ * (that would be triggered by additions to this particular bucket) -+ * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH. -+ * (The multiplier is simply expand_mult+1). The whole idea of this -+ * multiplier is to reduce bucket expansions, since they are expensive, in -+ * situations where we know that a particular bucket tends to be overused. -+ * It is better to let its chain length grow to a longer yet-still-bounded -+ * value, than to do an O(n) bucket expansion too often. -+ */ -+ unsigned expand_mult; -+ -+} UT_hash_bucket; -+ -+/* random signature used only to find hash tables in external analysis */ -+#define HASH_SIGNATURE 0xa0111fe1u -+#define HASH_BLOOM_SIGNATURE 0xb12220f2u -+ -+typedef struct UT_hash_table { -+ UT_hash_bucket *buckets; -+ unsigned num_buckets, log2_num_buckets; -+ unsigned num_items; -+ struct UT_hash_handle *tail; /* tail hh in app order, for fast append */ -+ ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */ -+ -+ /* in an ideal situation (all buckets used equally), no bucket would have -+ * more than ceil(#items/#buckets) items. that's the ideal chain length. */ -+ unsigned ideal_chain_maxlen; -+ -+ /* nonideal_items is the number of items in the hash whose chain position -+ * exceeds the ideal chain maxlen. these items pay the penalty for an uneven -+ * hash distribution; reaching them in a chain traversal takes >ideal steps */ -+ unsigned nonideal_items; -+ -+ /* ineffective expands occur when a bucket doubling was performed, but -+ * afterward, more than half the items in the hash had nonideal chain -+ * positions. If this happens on two consecutive expansions we inhibit any -+ * further expansion, as it's not helping; this happens when the hash -+ * function isn't a good fit for the key domain. When expansion is inhibited -+ * the hash will still work, albeit no longer in constant time. */ -+ unsigned ineff_expands, noexpand; -+ -+ uint32_t signature; /* used only to find hash tables in external analysis */ -+#ifdef HASH_BLOOM -+ uint32_t bloom_sig; /* used only to test bloom exists in external analysis */ -+ uint8_t *bloom_bv; -+ uint8_t bloom_nbits; -+#endif -+ -+} UT_hash_table; -+ -+typedef struct UT_hash_handle { -+ struct UT_hash_table *tbl; -+ void *prev; /* prev element in app order */ -+ void *next; /* next element in app order */ -+ struct UT_hash_handle *hh_prev; /* previous hh in bucket order */ -+ struct UT_hash_handle *hh_next; /* next hh in bucket order */ -+ void *key; /* ptr to enclosing struct's key */ -+ unsigned keylen; /* enclosing struct's key len */ -+ unsigned hashv; /* result of hash-fcn(key) */ -+} UT_hash_handle; -+ -+#endif /* UTHASH_H */ -diff --git a/server/utils.c b/server/utils.c -new file mode 100644 -index 0000000..14a60c7 ---- /dev/null -+++ b/server/utils.c -@@ -0,0 +1,448 @@ -+/* -+ * utils.c - Misc utilities -+ * -+ * Copyright (C) 2013 - 2016, Max Lv -+ * -+ * This file is part of the shadowsocks-libev. -+ * -+ * shadowsocks-libev is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * shadowsocks-libev 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 General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with shadowsocks-libev; see the file COPYING. If not, see -+ * . -+ */ -+ -+#ifdef HAVE_CONFIG_H -+#include "config.h" -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#ifndef __MINGW32__ -+#include -+#include -+#endif -+ -+#include -+#include -+ -+#include "utils.h" -+ -+#ifdef HAVE_SETRLIMIT -+#include -+#include -+#endif -+ -+#define INT_DIGITS 19 /* enough for 64 bit integer */ -+ -+#ifdef LIB_ONLY -+FILE *logfile; -+#endif -+ -+#ifdef HAS_SYSLOG -+int use_syslog = 0; -+#endif -+ -+#ifndef __MINGW32__ -+void -+ERROR(const char *s) -+{ -+ char *msg = strerror(errno); -+ LOGE("%s: %s", s, msg); -+} -+ -+#endif -+ -+int use_tty = 1; -+ -+char * -+ss_itoa(int i) -+{ -+ /* Room for INT_DIGITS digits, - and '\0' */ -+ static char buf[INT_DIGITS + 2]; -+ char *p = buf + INT_DIGITS + 1; /* points to terminating '\0' */ -+ if (i >= 0) { -+ do { -+ *--p = '0' + (i % 10); -+ i /= 10; -+ } while (i != 0); -+ return p; -+ } else { /* i < 0 */ -+ do { -+ *--p = '0' - (i % 10); -+ i /= 10; -+ } while (i != 0); -+ *--p = '-'; -+ } -+ return p; -+} -+ -+int -+ss_isnumeric(const char *s) { -+ if (!s || !*s) -+ return 0; -+ while (isdigit(*s)) -+ ++s; -+ return *s == '\0'; -+} -+ -+/* -+ * setuid() and setgid() for a specified user. -+ */ -+int -+run_as(const char *user) -+{ -+#ifndef __MINGW32__ -+ if (user[0]) { -+ /* Convert user to a long integer if it is a non-negative number. -+ * -1 means it is a user name. */ -+ long uid = -1; -+ if (ss_isnumeric(user)) { -+ errno = 0; -+ char *endptr; -+ uid = strtol(user, &endptr, 10); -+ if (errno || endptr == user) -+ uid = -1; -+ } -+ -+#ifdef HAVE_GETPWNAM_R -+ struct passwd pwdbuf, *pwd; -+ memset(&pwdbuf, 0, sizeof(struct passwd)); -+ size_t buflen; -+ int err; -+ -+ for (buflen = 128;; buflen *= 2) { -+ char buf[buflen]; /* variable length array */ -+ -+ /* Note that we use getpwnam_r() instead of getpwnam(), -+ * which returns its result in a statically allocated buffer and -+ * cannot be considered thread safe. */ -+ err = uid >= 0 ? getpwuid_r((uid_t)uid, &pwdbuf, buf, buflen, &pwd) -+ : getpwnam_r(user, &pwdbuf, buf, buflen, &pwd); -+ -+ if (err == 0 && pwd) { -+ /* setgid first, because we may not be allowed to do it anymore after setuid */ -+ if (setgid(pwd->pw_gid) != 0) { -+ LOGE( -+ "Could not change group id to that of run_as user '%s': %s", -+ pwd->pw_name, strerror(errno)); -+ return 0; -+ } -+ -+ if (initgroups(pwd->pw_name, pwd->pw_gid) == -1) { -+ LOGE("Could not change supplementary groups for user '%s'.", pwd->pw_name); -+ return 0; -+ } -+ -+ if (setuid(pwd->pw_uid) != 0) { -+ LOGE( -+ "Could not change user id to that of run_as user '%s': %s", -+ pwd->pw_name, strerror(errno)); -+ return 0; -+ } -+ break; -+ } else if (err != ERANGE) { -+ if (err) { -+ LOGE("run_as user '%s' could not be found: %s", user, -+ strerror(err)); -+ } else { -+ LOGE("run_as user '%s' could not be found.", user); -+ } -+ return 0; -+ } else if (buflen >= 16 * 1024) { -+ /* If getpwnam_r() seems defective, call it quits rather than -+ * keep on allocating ever larger buffers until we crash. */ -+ LOGE( -+ "getpwnam_r() requires more than %u bytes of buffer space.", -+ (unsigned)buflen); -+ return 0; -+ } -+ /* Else try again with larger buffer. */ -+ } -+#else -+ /* No getpwnam_r() :-( We'll use getpwnam() and hope for the best. */ -+ struct passwd *pwd; -+ -+ if (!(pwd = uid >=0 ? getpwuid((uid_t)uid) : getpwnam(user))) { -+ LOGE("run_as user %s could not be found.", user); -+ return 0; -+ } -+ /* setgid first, because we may not allowed to do it anymore after setuid */ -+ if (setgid(pwd->pw_gid) != 0) { -+ LOGE("Could not change group id to that of run_as user '%s': %s", -+ pwd->pw_name, strerror(errno)); -+ return 0; -+ } -+ if (initgroups(pwd->pw_name, pwd->pw_gid) == -1) { -+ LOGE("Could not change supplementary groups for user '%s'.", pwd->pw_name); -+ return 0; -+ } -+ if (setuid(pwd->pw_uid) != 0) { -+ LOGE("Could not change user id to that of run_as user '%s': %s", -+ pwd->pw_name, strerror(errno)); -+ return 0; -+ } -+#endif -+ } -+ -+#endif // __MINGW32__ -+ return 1; -+} -+ -+char * -+ss_strndup(const char *s, size_t n) -+{ -+ size_t len = strlen(s); -+ char *ret; -+ -+ if (len <= n) { -+ return strdup(s); -+ } -+ -+ ret = ss_malloc(n + 1); -+ strncpy(ret, s, n); -+ ret[n] = '\0'; -+ return ret; -+} -+ -+void -+FATAL(const char *msg) -+{ -+ LOGE("%s", msg); -+ exit(-1); -+} -+ -+void * -+ss_malloc(size_t size) -+{ -+ void *tmp = malloc(size); -+ if (tmp == NULL) -+ exit(EXIT_FAILURE); -+ return tmp; -+} -+ -+void * -+ss_realloc(void *ptr, size_t new_size) -+{ -+ void *new = realloc(ptr, new_size); -+ if (new == NULL) { -+ free(ptr); -+ ptr = NULL; -+ exit(EXIT_FAILURE); -+ } -+ return new; -+} -+ -+void -+usage() -+{ -+ printf("\n"); -+ printf("shadowsocks-libev %s with %s\n\n", VERSION, USING_CRYPTO); -+ printf( -+ " maintained by Max Lv and Linus Yang \n\n"); -+ printf(" usage:\n\n"); -+#ifdef MODULE_LOCAL -+ printf(" ss-local\n"); -+#elif MODULE_REMOTE -+ printf(" ss-server\n"); -+#elif MODULE_TUNNEL -+ printf(" ss-tunnel\n"); -+#elif MODULE_REDIR -+ printf(" ss-redir\n"); -+#elif MODULE_MANAGER -+ printf(" ss-manager\n"); -+#endif -+ printf("\n"); -+ printf( -+ " -s Host name or IP address of your remote server.\n"); -+ printf( -+ " -p Port number of your remote server.\n"); -+ printf( -+ " -l Port number of your local server.\n"); -+ printf( -+ " -k Password of your remote server.\n"); -+ printf( -+ " -m Encrypt method: table, rc4, rc4-md5,\n"); -+ printf( -+ " aes-128-cfb, aes-192-cfb, aes-256-cfb,\n"); -+ printf( -+ " aes-128-ctr, aes-192-ctr, aes-256-ctr,\n"); -+ printf( -+ " bf-cfb, camellia-128-cfb, camellia-192-cfb,\n"); -+ printf( -+ " camellia-256-cfb, cast5-cfb, des-cfb,\n"); -+ printf( -+ " idea-cfb, rc2-cfb, seed-cfb, salsa20,\n"); -+ printf( -+ " chacha20 and chacha20-ietf.\n"); -+ printf( -+ " The default cipher is rc4-md5.\n"); -+ printf("\n"); -+ printf( -+ " [-a ] Run as another user.\n"); -+ printf( -+ " [-f ] The file path to store pid.\n"); -+ printf( -+ " [-t ] Socket timeout in seconds.\n"); -+ printf( -+ " [-c ] The path to config file.\n"); -+#ifdef HAVE_SETRLIMIT -+ printf( -+ " [-n ] Max number of open files.\n"); -+#endif -+#ifndef MODULE_REDIR -+ printf( -+ " [-i ] Network interface to bind.\n"); -+#endif -+ printf( -+ " [-b ] Local address to bind.\n"); -+ printf("\n"); -+ printf( -+ " [-u] Enable UDP relay.\n"); -+#ifdef MODULE_REDIR -+ printf( -+ " TPROXY is required in redir mode.\n"); -+#endif -+ printf( -+ " [-U] Enable UDP relay and disable TCP relay.\n"); -+ printf( -+ " [-A] Enable onetime authentication.\n"); -+#ifdef MODULE_REMOTE -+ printf( -+ " [-6] Resovle hostname to IPv6 address first.\n"); -+#endif -+ printf("\n"); -+#ifdef MODULE_TUNNEL -+ printf( -+ " [-L :] Destination server address and port\n"); -+ printf( -+ " for local port forwarding.\n"); -+#endif -+#ifdef MODULE_REMOTE -+ printf( -+ " [-d ] Name servers for internal DNS resolver.\n"); -+#endif -+#if defined(MODULE_REMOTE) || defined(MODULE_LOCAL) -+ printf( -+ " [--fast-open] Enable TCP fast open.\n"); -+ printf( -+ " with Linux kernel > 3.7.0.\n"); -+ printf( -+ " [--acl ] Path to ACL (Access Control List).\n"); -+#endif -+#if defined(MODULE_REMOTE) || defined(MODULE_MANAGER) -+ printf( -+ " [--manager-address ] UNIX domain socket address.\n"); -+#endif -+#ifdef MODULE_MANAGER -+ printf( -+ " [--executable ] Path to the executable of ss-server.\n"); -+#endif -+ printf( -+ " [--mtu ] MTU of your network interface.\n"); -+#ifdef __linux__ -+ printf( -+ " [--mptcp] Enable Multipath TCP on MPTCP Kernel.\n"); -+#ifdef MODULE_REMOTE -+ printf( -+ " [--firewall] Setup firewall rules for auto blocking.\n"); -+#endif -+#endif -+ printf("\n"); -+ printf( -+ " [-v] Verbose mode.\n"); -+ printf( -+ " [-h, --help] Print this message.\n"); -+ printf("\n"); -+} -+ -+void -+daemonize(const char *path) -+{ -+#ifndef __MINGW32__ -+ /* Our process ID and Session ID */ -+ pid_t pid, sid; -+ -+ /* Fork off the parent process */ -+ pid = fork(); -+ if (pid < 0) { -+ exit(EXIT_FAILURE); -+ } -+ -+ /* If we got a good PID, then -+ * we can exit the parent process. */ -+ if (pid > 0) { -+ FILE *file = fopen(path, "w"); -+ if (file == NULL) { -+ FATAL("Invalid pid file\n"); -+ } -+ -+ fprintf(file, "%d", (int)pid); -+ fclose(file); -+ exit(EXIT_SUCCESS); -+ } -+ -+ /* Change the file mode mask */ -+ umask(0); -+ -+ /* Open any logs here */ -+ -+ /* Create a new SID for the child process */ -+ sid = setsid(); -+ if (sid < 0) { -+ /* Log the failure */ -+ exit(EXIT_FAILURE); -+ } -+ -+ /* Change the current working directory */ -+ if ((chdir("/")) < 0) { -+ /* Log the failure */ -+ exit(EXIT_FAILURE); -+ } -+ -+ /* Close out the standard file descriptors */ -+ close(STDIN_FILENO); -+ close(STDOUT_FILENO); -+ close(STDERR_FILENO); -+#endif -+} -+ -+#ifdef HAVE_SETRLIMIT -+int -+set_nofile(int nofile) -+{ -+ struct rlimit limit = { nofile, nofile }; /* set both soft and hard limit */ -+ -+ if (nofile <= 0) { -+ FATAL("nofile must be greater than 0\n"); -+ } -+ -+ if (setrlimit(RLIMIT_NOFILE, &limit) < 0) { -+ if (errno == EPERM) { -+ LOGE( -+ "insufficient permission to change NOFILE, not starting as root?"); -+ return -1; -+ } else if (errno == EINVAL) { -+ LOGE("invalid nofile, decrease nofile and try again"); -+ return -1; -+ } else { -+ LOGE("setrlimit failed: %s", strerror(errno)); -+ return -1; -+ } -+ } -+ -+ return 0; -+} -+ -+#endif -diff --git a/server/utils.h b/server/utils.h -new file mode 100644 -index 0000000..0fb7f5a ---- /dev/null -+++ b/server/utils.h -@@ -0,0 +1,232 @@ -+/* -+ * utils.h - Misc utilities -+ * -+ * Copyright (C) 2013 - 2016, Max Lv -+ * -+ * This file is part of the shadowsocks-libev. -+ * -+ * shadowsocks-libev is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * shadowsocks-libev 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 General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with shadowsocks-libev; see the file COPYING. If not, see -+ * . -+ */ -+ -+#if defined(USE_CRYPTO_OPENSSL) -+ -+#include -+#define USING_CRYPTO OPENSSL_VERSION_TEXT -+ -+#elif defined(USE_CRYPTO_POLARSSL) -+#include -+#define USING_CRYPTO POLARSSL_VERSION_STRING_FULL -+ -+#elif defined(USE_CRYPTO_MBEDTLS) -+#include -+#define USING_CRYPTO MBEDTLS_VERSION_STRING_FULL -+ -+#endif -+ -+#ifndef _UTILS_H -+#define _UTILS_H -+ -+#include -+#include -+#include -+#include -+ -+#define PORTSTRLEN 16 -+#define SS_ADDRSTRLEN (INET6_ADDRSTRLEN + PORTSTRLEN + 1) -+ -+#ifdef ANDROID -+ -+#include -+ -+#define USE_TTY() -+#define USE_SYSLOG(ident) -+#define LOGI(...) \ -+ ((void)__android_log_print(ANDROID_LOG_DEBUG, "shadowsocks", \ -+ __VA_ARGS__)) -+#define LOGE(...) \ -+ ((void)__android_log_print(ANDROID_LOG_ERROR, "shadowsocks", \ -+ __VA_ARGS__)) -+ -+#else -+ -+#define STR(x) # x -+#define TOSTR(x) STR(x) -+ -+#ifdef LIB_ONLY -+ -+extern FILE *logfile; -+ -+#define TIME_FORMAT "%Y-%m-%d %H:%M:%S" -+ -+#define USE_TTY() -+ -+#define USE_SYSLOG(ident) -+ -+#define USE_LOGFILE(ident) \ -+ do { \ -+ if (ident != NULL) { logfile = fopen(ident, "w+"); } } \ -+ while (0) -+ -+#define CLOSE_LOGFILE \ -+ do { \ -+ if (logfile != NULL) { fclose(logfile); } } \ -+ while (0) -+ -+#define LOGI(format, ...) \ -+ do { \ -+ if (logfile != NULL) { \ -+ time_t now = time(NULL); \ -+ char timestr[20]; \ -+ strftime(timestr, 20, TIME_FORMAT, localtime(&now)); \ -+ fprintf(logfile, " %s INFO: " format "\n", timestr, ## __VA_ARGS__); \ -+ fflush(logfile); } \ -+ } \ -+ while (0) -+ -+#define LOGE(format, ...) \ -+ do { \ -+ if (logfile != NULL) { \ -+ time_t now = time(NULL); \ -+ char timestr[20]; \ -+ strftime(timestr, 20, TIME_FORMAT, localtime(&now)); \ -+ fprintf(logfile, " %s ERROR: " format "\n", timestr, \ -+ ## __VA_ARGS__); \ -+ fflush(logfile); } \ -+ } \ -+ while (0) -+ -+#elif defined(_WIN32) -+ -+#define TIME_FORMAT "%Y-%m-%d %H:%M:%S" -+ -+#define USE_TTY() -+ -+#define USE_SYSLOG(ident) -+ -+#define LOGI(format, ...) \ -+ do { \ -+ time_t now = time(NULL); \ -+ char timestr[20]; \ -+ strftime(timestr, 20, TIME_FORMAT, localtime(&now)); \ -+ fprintf(stderr, " %s INFO: " format "\n", timestr, ## __VA_ARGS__); \ -+ fflush(stderr); } \ -+ while (0) -+ -+#define LOGE(format, ...) \ -+ do { \ -+ time_t now = time(NULL); \ -+ char timestr[20]; \ -+ strftime(timestr, 20, TIME_FORMAT, localtime(&now)); \ -+ fprintf(stderr, " %s ERROR: " format "\n", timestr, ## __VA_ARGS__); \ -+ fflush(stderr); } \ -+ while (0) -+ -+#else -+ -+#include -+ -+extern int use_tty; -+#define USE_TTY() \ -+ do { \ -+ use_tty = isatty(STDERR_FILENO); \ -+ } while (0) \ -+ -+#define HAS_SYSLOG -+extern int use_syslog; -+ -+#define TIME_FORMAT "%F %T" -+ -+#define USE_SYSLOG(ident) \ -+ do { \ -+ use_syslog = 1; \ -+ openlog((ident), LOG_CONS | LOG_PID, 0); } \ -+ while (0) -+ -+#define LOGI(format, ...) \ -+ do { \ -+ if (use_syslog) { \ -+ syslog(LOG_INFO, format, ## __VA_ARGS__); \ -+ } else { \ -+ time_t now = time(NULL); \ -+ char timestr[20]; \ -+ strftime(timestr, 20, TIME_FORMAT, localtime(&now)); \ -+ if (use_tty) { \ -+ fprintf(stderr, "\e[01;32m %s INFO: \e[0m" format "\n", timestr, \ -+ ## __VA_ARGS__); \ -+ } else { \ -+ fprintf(stderr, " %s INFO: " format "\n", timestr, \ -+ ## __VA_ARGS__); \ -+ } \ -+ } \ -+ } \ -+ while (0) -+ -+#define LOGE(format, ...) \ -+ do { \ -+ if (use_syslog) { \ -+ syslog(LOG_ERR, format, ## __VA_ARGS__); \ -+ } else { \ -+ time_t now = time(NULL); \ -+ char timestr[20]; \ -+ strftime(timestr, 20, TIME_FORMAT, localtime(&now)); \ -+ if (use_tty) { \ -+ fprintf(stderr, "\e[01;35m %s ERROR: \e[0m" format "\n", timestr, \ -+ ## __VA_ARGS__); \ -+ } else { \ -+ fprintf(stderr, " %s ERROR: " format "\n", timestr, \ -+ ## __VA_ARGS__); \ -+ } \ -+ } } \ -+ while (0) -+ -+#endif -+/* _WIN32 */ -+ -+#endif -+ -+#ifdef __MINGW32__ -+ -+#ifdef ERROR -+#undef ERROR -+#endif -+#define ERROR(s) ss_error(s) -+ -+#else -+ -+void ERROR(const char *s); -+ -+#endif -+ -+char *ss_itoa(int i); -+int ss_isnumeric(const char *s); -+int run_as(const char *user); -+void FATAL(const char *msg); -+void usage(void); -+void daemonize(const char *path); -+char *ss_strndup(const char *s, size_t n); -+#ifdef HAVE_SETRLIMIT -+int set_nofile(int nofile); -+#endif -+ -+void *ss_malloc(size_t size); -+void *ss_realloc(void *ptr, size_t new_size); -+ -+#define ss_free(ptr) \ -+ do { \ -+ free(ptr); \ -+ ptr = NULL; \ -+ } while (0) -+ -+#endif // _UTILS_H -diff --git a/server/verify.c b/server/verify.c -new file mode 100644 -index 0000000..9e7393d ---- /dev/null -+++ b/server/verify.c -@@ -0,0 +1,188 @@ -+ -+#include "verify.h" -+ -+static int verify_simple_pack_unit_size = 2000; -+ -+typedef struct verify_simple_local_data { -+ char * recv_buffer; -+ int recv_buffer_size; -+}verify_simple_local_data; -+ -+void verify_simple_local_data_init(verify_simple_local_data* local) { -+ local->recv_buffer = (char*)malloc(16384); -+ local->recv_buffer_size = 0; -+} -+ -+obfs * verify_simple_new_obfs() { -+ obfs * self = new_obfs(); -+ self->l_data = malloc(sizeof(verify_simple_local_data)); -+ verify_simple_local_data_init((verify_simple_local_data*)self->l_data); -+ return self; -+} -+ -+void verify_simple_dispose(obfs *self) { -+ verify_simple_local_data *local = (verify_simple_local_data*)self->l_data; -+ if (local->recv_buffer != NULL) { -+ free(local->recv_buffer); -+ local->recv_buffer = NULL; -+ } -+ free(local); -+ self->l_data = NULL; -+ dispose_obfs(self); -+} -+ -+int verify_simple_pack_data(char *data, int datalength, char *outdata) { -+ unsigned char rand_len = (xorshift128plus() & 0xF) + 1; -+ int out_size = rand_len + datalength + 6; -+ outdata[0] = out_size >> 8; -+ outdata[1] = out_size; -+ outdata[2] = rand_len; -+ memmove(outdata + rand_len + 2, data, datalength); -+ fillcrc32((unsigned char *)outdata, out_size); -+ return out_size; -+} -+ -+int verify_simple_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t *capacity) { -+ char *plaindata = *pplaindata; -+ //verify_simple_local_data *local = (verify_simple_local_data*)self->l_data; -+ char * out_buffer = (char*)malloc(datalength * 2 + 32); -+ char * buffer = out_buffer; -+ char * data = plaindata; -+ int len = datalength; -+ int pack_len; -+ while ( len > verify_simple_pack_unit_size ) { -+ pack_len = verify_simple_pack_data(data, verify_simple_pack_unit_size, buffer); -+ buffer += pack_len; -+ data += verify_simple_pack_unit_size; -+ len -= verify_simple_pack_unit_size; -+ } -+ if (len > 0) { -+ pack_len = verify_simple_pack_data(data, len, buffer); -+ buffer += pack_len; -+ } -+ len = buffer - out_buffer; -+ if (*capacity < len) { -+ *pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2); -+ plaindata = *pplaindata; -+ } -+ memmove(plaindata, out_buffer, len); -+ free(out_buffer); -+ return len; -+} -+ -+int verify_simple_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t *capacity) { -+ char *plaindata = *pplaindata; -+ verify_simple_local_data *local = (verify_simple_local_data*)self->l_data; -+ uint8_t * recv_buffer = (uint8_t *)local->recv_buffer; -+ if (local->recv_buffer_size + datalength > 16384) -+ return -1; -+ memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength); -+ local->recv_buffer_size += datalength; -+ -+ char * out_buffer = (char*)malloc(local->recv_buffer_size); -+ char * buffer = out_buffer; -+ while (local->recv_buffer_size > 2) { -+ int length = ((int)recv_buffer[0] << 8) | recv_buffer[1]; -+ if (length >= 8192 || length < 7) { -+ free(out_buffer); -+ local->recv_buffer_size = 0; -+ return -1; -+ } -+ if (length > local->recv_buffer_size) -+ break; -+ -+ int crc = crc32((unsigned char*)recv_buffer, length); -+ if (crc != -1) { -+ free(out_buffer); -+ local->recv_buffer_size = 0; -+ return -1; -+ } -+ int data_size = length - recv_buffer[2] - 6; -+ memmove(buffer, recv_buffer + 2 + recv_buffer[2], data_size); -+ buffer += data_size; -+ memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length); -+ } -+ int len = buffer - out_buffer; -+ if (*capacity < len) { -+ *pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2); -+ plaindata = *pplaindata; -+ } -+ memmove(plaindata, out_buffer, len); -+ free(out_buffer); -+ return len; -+} -+ -+int verify_simple_server_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t *capacity) { -+ char *plaindata = *pplaindata; -+ //verify_simple_local_data *local = (verify_simple_local_data*)self->l_data; -+ char * out_buffer = (char*)malloc(datalength * 2 + 32); -+ char * buffer = out_buffer; -+ char * data = plaindata; -+ int len = datalength; -+ int pack_len; -+ while ( len > verify_simple_pack_unit_size ) { -+ pack_len = verify_simple_pack_data(data, verify_simple_pack_unit_size, buffer); -+ buffer += pack_len; -+ data += verify_simple_pack_unit_size; -+ len -= verify_simple_pack_unit_size; -+ } -+ if (len > 0) { -+ pack_len = verify_simple_pack_data(data, len, buffer); -+ buffer += pack_len; -+ } -+ len = buffer - out_buffer; -+ if (*capacity < len) { -+ *pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2); -+ plaindata = *pplaindata; -+ } -+ memmove(plaindata, out_buffer, len); -+ free(out_buffer); -+ return len; -+} -+ -+int verify_simple_server_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t *capacity) { -+ char *plaindata = *pplaindata; -+ verify_simple_local_data *local = (verify_simple_local_data*)self->l_data; -+ uint8_t * recv_buffer = (uint8_t *)local->recv_buffer; -+ if (local->recv_buffer_size + datalength > 16384) -+ { -+ LOGE("verify_simple: wrong buf length %d", local->recv_buffer_size + datalength); -+ return -1; -+ } -+ memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength); -+ local->recv_buffer_size += datalength; -+ -+ char * out_buffer = (char*)malloc(local->recv_buffer_size); -+ char * buffer = out_buffer; -+ while (local->recv_buffer_size > 2) { -+ int length = ((int)recv_buffer[0] << 8) | recv_buffer[1]; -+ if (length >= 8192 || length < 7) { -+ free(out_buffer); -+ local->recv_buffer_size = 0; -+ LOGE("verify_simple: wrong length %d", length); -+ return -1; -+ } -+ if (length > local->recv_buffer_size) -+ break; -+ -+ int crc = crc32((unsigned char*)recv_buffer, length); -+ if (crc != -1) { -+ free(out_buffer); -+ local->recv_buffer_size = 0; -+ LOGE("verify_simple: wrong crc"); -+ return -1; -+ } -+ int data_size = length - recv_buffer[2] - 6; -+ memmove(buffer, recv_buffer + 2 + recv_buffer[2], data_size); -+ buffer += data_size; -+ memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length); -+ } -+ int len = buffer - out_buffer; -+ if (*capacity < len) { -+ *pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2); -+ plaindata = *pplaindata; -+ } -+ memmove(plaindata, out_buffer, len); -+ free(out_buffer); -+ return len; -+} -diff --git a/server/verify.h b/server/verify.h -new file mode 100644 -index 0000000..57c6ff9 ---- /dev/null -+++ b/server/verify.h -@@ -0,0 +1,19 @@ -+/* -+ * verify.h - Define shadowsocksR server's buffers and callbacks -+ * -+ * Copyright (C) 2015 - 2016, Break Wa11 -+ */ -+ -+#ifndef _VERIFY_H -+#define _VERIFY_H -+ -+obfs * verify_simple_new_obfs(); -+void verify_simple_dispose(obfs *self); -+ -+int verify_simple_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); -+int verify_simple_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); -+ -+int verify_simple_server_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); -+int verify_simple_server_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); -+ -+#endif // _VERIFY_H --- -2.19.1 - diff --git a/package/simple-obfs/LICENSE b/package/simple-obfs/LICENSE deleted file mode 100644 index e963df8..0000000 --- a/package/simple-obfs/LICENSE +++ /dev/null @@ -1,622 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - diff --git a/package/ssocks/Makefile b/package/ssocks/Makefile deleted file mode 100644 index 163d56a..0000000 --- a/package/ssocks/Makefile +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright (C) 2020 xiaorouji -# -# This is free software, licensed under the GNU General Public License v3. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=ssocks -PKG_VERSION:=0.0.14 -PKG_RELEASE:=1 - -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://github.com/tostercx/ssocks.git -PKG_SOURCE_VERSION:=c2024789c1ee076d171fd6061d7c133302216ea7 -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz - -include $(INCLUDE_DIR)/package.mk -include $(INCLUDE_DIR)/cmake.mk - -CMAKE_INSTALL:=1 - -define Package/$(PKG_NAME) - SECTION:=net - CATEGORY:=Network - TITLE:=sSocks Relay - URL:=https://github.com/tostercx/ssocks - DEPENDS:=+libopenssl -endef - -define Package/$(PKG_NAME)/description -sSocks is a package which contains: a socks5 server implements RFC 1928 (SOCKS V5) and RFC 1929 (Authentication for SOCKS V5), a reverse socks server and client, a netcat like tool and a socks5 relay. -endef - -define Package/$(PKG_NAME)d - $(call Package/$(PKG_NAME)) - TITLE:=sSocks Server -endef - -Package/$(PKG_NAME)d/description = $(Package/$(PKG_NAME)/description) - -define Package/$(PKG_NAME)/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/$(PKG_NAME)$(2) $(1)/usr/bin/ -endef - -define Package/$(PKG_NAME)d/install - $(call Package/$(PKG_NAME)/install,$(1),d) -endef - -$(eval $(call BuildPackage,$(PKG_NAME))) -$(eval $(call BuildPackage,$(PKG_NAME)d)) \ No newline at end of file diff --git a/package/tcping/LICENSE b/package/tcping/LICENSE deleted file mode 100644 index 034d072..0000000 --- a/package/tcping/LICENSE +++ /dev/null @@ -1,280 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/package/trojan-go/Makefile b/package/trojan-go/Makefile deleted file mode 100644 index 586649c..0000000 --- a/package/trojan-go/Makefile +++ /dev/null @@ -1,87 +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.2 -PKG_RELEASE:=1 - -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://github.com/p4gefau1t/trojan-go.git -PKG_SOURCE_VERSION:=d051cf4c8852d708769ca1c4e514306a88da830b -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz -PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION) - -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_TAG:=-tags full -GO_PKG_LDFLAGS:=-s -w -GO_PKG_LDFLAGS_X:= \ - $(GO_PKG)/constant.Version=$(PKG_VERSION) \ - $(GO_PKG)/constant.Commit=$(PKG_SOURCE_VERSION) - -include $(INCLUDE_DIR)/package.mk -include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk - -define Package/$(PKG_NAME) - SECTION:=net - CATEGORY:=Network - 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 -#export GOPROXY=https://mirrors.aliyun.com/goproxy/ -endif - -define Build/Prepare - tar -zxvf $(DL_DIR)/$(PKG_SOURCE) -C $(PKG_BUILD_DIR) --strip-components 1 -endef - -define Build/Compile - $(eval GO_PKG_BUILD_PKG:=$(GO_PKG)) - $(call GoPackage/Build/Configure) - $(call GoPackage/Build/Compile,$(GO_PKG_TAG)) -ifeq ($(CONFIG_TROJAN_GO_COMPRESS_UPX),y) - $(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DIR)/$(PKG_NAME) -endif -endef - -define Package/$(PKG_NAME)/install - $(call GoPackage/Package/Install/Bin,$(PKG_INSTALL_DIR)) - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(GO_PKG_BUILD_BIN_DIR)/$(PKG_NAME) $(1)/usr/bin/$(PKG_NAME) -endef - -$(eval $(call GoBinPackage,$(PKG_NAME))) -$(eval $(call BuildPackage,$(PKG_NAME))) diff --git a/package/v2ray-plugin/LICENSE b/package/v2ray-plugin/LICENSE deleted file mode 100644 index e963df8..0000000 --- a/package/v2ray-plugin/LICENSE +++ /dev/null @@ -1,622 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - diff --git a/package/v2ray-plugin/Makefile b/package/v2ray-plugin/Makefile deleted file mode 100644 index cc99fd3..0000000 --- a/package/v2ray-plugin/Makefile +++ /dev/null @@ -1,74 +0,0 @@ -# -# Copyright (C) 2020 SharerMax -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=v2ray-plugin -PKG_VERSION:=1.7.0 -PKG_RELEASE:=1 -PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) - -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz -PKG_SOURCE_URL:=https://codeload.github.com/teddysun/v2ray-plugin/tar.gz/v$(PKG_VERSION)? -PKG_HASH:=5a8e1912a9902daa64a0aa1ea60ff367d4e806ce4443ba08b4a6e98b0d1515f0 - -PKG_LICENSE:=MIT -PKG_LICENSE_FILES:=LICENSE -PKG_MAINTAINER:=madeye - -PKG_BUILD_DEPENDS:=golang/host -PKG_BUILD_PARALLEL:=1 -PKG_USE_MIPS16:=0 - -GO_PKG:=github.com/shadowsocks/v2ray-plugin -GO_PKG_LDFLAGS:=-s -w -PKG_CONFIG_DEPENDS := CONFIG_$(PKG_NAME)_INCLUDE_GOPROXY - -include $(INCLUDE_DIR)/package.mk -include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk - -define Package/$(PKG_NAME)/config -config $(PKG_NAME)_INCLUDE_GOPROXY - bool "Compiling with GOPROXY proxy" - default y - -endef - -ifeq ($(CONFIG_$(PKG_NAME)_INCLUDE_GOPROXY),y) -export GO111MODULE=on -export GOPROXY=https://goproxy.io -#export GOPROXY=https://mirrors.aliyun.com/goproxy/ -endif - -define Package/$(PKG_NAME) - SECTION:=net - CATEGORY:=Network - SUBMENU:=Project V - TITLE:=SIP003 plugin for shadowsocks, based on v2ray - URL:=https://github.com/shadowsocks/v2ray-plugin - DEPENDS:=$(GO_ARCH_DEPENDS) +ca-certificates -endef - -define Package/$(PKG_NAME)/description - Yet another SIP003 plugin for shadowsocks, based on v2ray -endef - -define Build/Prepare - $(call Build/Prepare/Default) -endef - -define Build/Compile - $(call GoPackage/Build/Compile) - $(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DIR)/v2ray-plugin -endef - -define Package/$(PKG_NAME)/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(GO_PKG_BUILD_BIN_DIR)/v2ray-plugin $(1)/usr/bin/v2ray-plugin -endef -$(eval $(call GoBinPackage,$(PKG_NAME))) -$(eval $(call BuildPackage,$(PKG_NAME))) diff --git a/package/v2ray/Config.in b/package/v2ray/Config.in deleted file mode 100644 index f7ce07a..0000000 --- a/package/v2ray/Config.in +++ /dev/null @@ -1,136 +0,0 @@ -menu "V2Ray Configuration" - depends on PACKAGE_v2ray - -choice - prompt "JSON Config Support" - default V2RAY_JSON_INTERNAL - - config V2RAY_JSON_INTERNAL - bool "Load JSON Internally" - - config V2RAY_JSON_V2CTL - bool "Load JSON from V2Ctl" - - config V2RAY_JSON_NONE - bool "None" - -endchoice - -config V2RAY_COMPRESS_GOPROXY - bool "Compiling with GOPROXY proxy" - default n - -config V2RAY_EXCLUDE_V2CTL - bool "Exclude V2Ctl" - depends on V2RAY_JSON_INTERNAL || V2RAY_JSON_NONE - default y - -config V2RAY_EXCLUDE_ASSETS - bool "Exclude geoip.dat & geosite.dat" - default y - -config V2RAY_COMPRESS_UPX - bool "Compress executable files with UPX" - default y - -config V2RAY_CUSTOM_FEATURES - bool "Custom Features" - default n - -menu "Features Configuration" - depends on V2RAY_CUSTOM_FEATURES - -config V2RAY_WITHOUT_DNS - bool "Without Internal DNS Support" - default n - -config V2RAY_WITHOUT_LOG - bool "Without Log Support" - default n - -config V2RAY_WITHOUT_TLS - bool "Without TLS Support" - default n - -config V2RAY_WITHOUT_UDP - bool "Without UDP Support" - default n - -config V2RAY_WITHOUT_POLICY - bool "Without Local Policy Support" - default n - -config V2RAY_WITHOUT_REVERSE - bool "Without Reverse Proxy Support" - default n - -config V2RAY_WITHOUT_ROUTING - bool "Without Internal Routing Support" - default n - -config V2RAY_WITHOUT_STATISTICS - bool "Without Statistics Support" - default n - -config V2RAY_WITHOUT_BLACKHOLE_PROTO - bool "Without Blackhole Protocol" - default n - -config V2RAY_WITHOUT_DNS_PROXY - bool "Without DNS Proxy" - default n - -config V2RAY_WITHOUT_DOKODEMO_PROTO - bool "Without Dokodemo-door Protocol" - default n - -config V2RAY_WITHOUT_FREEDOM_PROTO - bool "Without Freedom Protocol" - default n - -config V2RAY_WITHOUT_MTPROTO_PROXY - bool "Without MTProto Proxy" - default n - -config V2RAY_WITHOUT_HTTP_PROTO - bool "Without HTTP Protocol" - default n - -config V2RAY_WITHOUT_SHADOWSOCKS_PROTO - bool "Without Shadowsocks Protocol" - default n - -config V2RAY_WITHOUT_SOCKS_PROTO - bool "Without Socks Protocol" - default n - -config V2RAY_WITHOUT_VMESS_PROTO - bool "Without VMess Protocol" - default n - -config V2RAY_WITHOUT_TCP_TRANS - bool "Without TCP Transport" - default n - -config V2RAY_WITHOUT_MKCP_TRANS - bool "Without mKCP Transport" - default n - -config V2RAY_WITHOUT_WEBSOCKET_TRANS - bool "Without WebSocket Transport" - default n - -config V2RAY_WITHOUT_HTTP2_TRANS - bool "Without HTTP/2 Transport" - default n - -config V2RAY_WITHOUT_DOMAIN_SOCKET_TRANS - bool "Without Domain Socket Transport" - default n - -config V2RAY_WITHOUT_QUIC_TRANS - bool "Without QUIC Transport" - default n - -endmenu -endmenu diff --git a/package/v2ray/Makefile b/package/v2ray/Makefile deleted file mode 100755 index fadf787..0000000 --- a/package/v2ray/Makefile +++ /dev/null @@ -1,319 +0,0 @@ -# -# Copyright (C) 2019-2020 Xingwang Liao -# Copyright (C) 2019-2020 Mattraks -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=v2ray -PKG_VERSION:=4.32.1 -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:=f5553ffd04ff226573e8132d9beaa63f4d8f4882eba047225b33620848bc6917 - -PKG_LICENSE:=MIT -PKG_LICENSE_FILES:=LICENSE -PKG_MAINTAINER:=Xingwang Liao - -PKG_CONFIG_DEPENDS:= \ - CONFIG_V2RAY_JSON_V2CTL \ - CONFIG_V2RAY_JSON_INTERNAL \ - CONFIG_V2RAY_JSON_NONE \ - CONFIG_V2RAY_EXCLUDE_V2CTL \ - CONFIG_V2RAY_EXCLUDE_ASSETS \ - CONFIG_V2RAY_COMPRESS_GOPROXY \ - CONFIG_V2RAY_COMPRESS_UPX \ - CONFIG_V2RAY_CUSTOM_FEATURES \ - CONFIG_V2RAY_WITHOUT_DNS \ - CONFIG_V2RAY_WITHOUT_LOG \ - CONFIG_V2RAY_WITHOUT_TLS \ - CONFIG_V2RAY_WITHOUT_UDP \ - CONFIG_V2RAY_WITHOUT_POLICY \ - CONFIG_V2RAY_WITHOUT_REVERSE \ - CONFIG_V2RAY_WITHOUT_ROUTING \ - CONFIG_V2RAY_WITHOUT_STATISTICS \ - CONFIG_V2RAY_WITHOUT_BLACKHOLE_PROTO \ - CONFIG_V2RAY_WITHOUT_DNS_PROXY \ - CONFIG_V2RAY_WITHOUT_DOKODEMO_PROTO \ - CONFIG_V2RAY_WITHOUT_FREEDOM_PROTO \ - CONFIG_V2RAY_WITHOUT_MTPROTO_PROXY \ - CONFIG_V2RAY_WITHOUT_HTTP_PROTO \ - CONFIG_V2RAY_WITHOUT_SHADOWSOCKS_PROTO \ - CONFIG_V2RAY_WITHOUT_SOCKS_PROTO \ - CONFIG_V2RAY_WITHOUT_VMESS_PROTO \ - CONFIG_V2RAY_WITHOUT_TCP_TRANS \ - CONFIG_V2RAY_WITHOUT_MKCP_TRANS \ - CONFIG_V2RAY_WITHOUT_WEBSOCKET_TRANS \ - CONFIG_V2RAY_WITHOUT_HTTP2_TRANS \ - CONFIG_V2RAY_WITHOUT_DOMAIN_SOCKET_TRANS \ - CONFIG_V2RAY_WITHOUT_QUIC_TRANS - -PKG_BUILD_DEPENDS:=golang/host -PKG_BUILD_PARALLEL:=1 -PKG_USE_MIPS16:=0 - -GO_PKG:=v2ray.com/core -GO_PKG_LDFLAGS:=-s -w -GO_PKG_LDFLAGS_X:= \ - v2ray.com/core.version=$(PKG_VERSION) \ - v2ray.com/core.build=Lean \ - v2ray.com/core.codename=OpenWrt - -include $(INCLUDE_DIR)/package.mk -include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk - -define Package/$(PKG_NAME) - TITLE:=A platform for building proxies - URL:=https://www.v2fly.org - SECTION:=net - CATEGORY:=Network - SUBMENU:=Project V - DEPENDS:=$(GO_ARCH_DEPENDS) +ca-certificates -endef - -define Package/$(PKG_NAME)/config - source "$(SOURCE)/Config.in" -endef - -define Package/$(PKG_NAME)/description -Project V is a set of network tools that help you to build your own computer network. -It secures your network connections and thus protects your privacy. - - This package contains v2ray, v2ctl, geoip.dat and geosite.dat. -endef - -ifeq ($(CONFIG_V2RAY_COMPRESS_GOPROXY),y) -export GO111MODULE=on -export GOPROXY=https://goproxy.io -#export GOPROXY=https://mirrors.aliyun.com/goproxy/ -endif - -V2RAY_SED_ARGS:= - -ifeq ($(CONFIG_V2RAY_JSON_INTERNAL),y) -V2RAY_SED_ARGS += \ - s,_ "v2ray.com/core/main/json",// &,; \ - s,// \(_ "v2ray.com/core/main/jsonem"\),\1,; -else ifeq ($(CONFIG_V2RAY_JSON_NONE),y) -V2RAY_SED_ARGS += \ - s,_ "v2ray.com/core/main/json",// &,; -endif - -ifeq ($(CONFIG_V2RAY_CUSTOM_FEATURES),y) - -ifeq ($(CONFIG_V2RAY_WITHOUT_DNS),y) -V2RAY_SED_ARGS += \ - s,_ "v2ray.com/core/app/dns",// &,; -endif - -ifeq ($(CONFIG_V2RAY_WITHOUT_LOG),y) -V2RAY_SED_ARGS += \ - s,_ "v2ray.com/core/app/log",// &,; \ - s,_ "v2ray.com/core/app/log/command",// &,; -endif - -ifeq ($(CONFIG_V2RAY_WITHOUT_TLS),y) -V2RAY_SED_ARGS += \ - s,_ "v2ray.com/core/transport/internet/tls",// &,; -endif - -ifeq ($(CONFIG_V2RAY_WITHOUT_UDP),y) -V2RAY_SED_ARGS += \ - s,_ "v2ray.com/core/transport/internet/udp",// &,; -endif - -ifeq ($(CONFIG_V2RAY_WITHOUT_POLICY),y) -V2RAY_SED_ARGS += \ - s,_ "v2ray.com/core/app/policy",// &,; -endif - -ifeq ($(CONFIG_V2RAY_WITHOUT_REVERSE),y) -V2RAY_SED_ARGS += \ - s,_ "v2ray.com/core/app/reverse",// &,; -endif - -ifeq ($(CONFIG_V2RAY_WITHOUT_ROUTING),y) -V2RAY_SED_ARGS += \ - s,_ "v2ray.com/core/app/router",// &,; -endif - -ifeq ($(CONFIG_V2RAY_WITHOUT_STATISTICS),y) -V2RAY_SED_ARGS += \ - s,_ "v2ray.com/core/app/stats",// &,; \ - s,_ "v2ray.com/core/app/stats/command",// &,; -endif - -ifeq ($(CONFIG_V2RAY_WITHOUT_BLACKHOLE_PROTO),y) -V2RAY_SED_ARGS += \ - s,_ "v2ray.com/core/proxy/blackhole",// &,; -endif - -ifeq ($(CONFIG_V2RAY_WITHOUT_DNS_PROXY),y) -V2RAY_SED_ARGS += \ - s,_ "v2ray.com/core/proxy/dns",// &,; -endif - -ifeq ($(CONFIG_V2RAY_WITHOUT_DOKODEMO_PROTO),y) -V2RAY_SED_ARGS += \ - s,_ "v2ray.com/core/proxy/dokodemo",// &,; -endif - -ifeq ($(CONFIG_V2RAY_WITHOUT_FREEDOM_PROTO),y) -V2RAY_SED_ARGS += \ - s,_ "v2ray.com/core/proxy/freedom",// &,; -endif - -ifeq ($(CONFIG_V2RAY_WITHOUT_MTPROTO_PROXY),y) -V2RAY_SED_ARGS += \ - s,_ "v2ray.com/core/proxy/mtproto",// &,; -endif - -ifeq ($(CONFIG_V2RAY_WITHOUT_HTTP_PROTO),y) -V2RAY_SED_ARGS += \ - s,_ "v2ray.com/core/proxy/http",// &,; -endif - -ifeq ($(CONFIG_V2RAY_WITHOUT_SHADOWSOCKS_PROTO),y) -V2RAY_SED_ARGS += \ - s,_ "v2ray.com/core/proxy/shadowsocks",// &,; -endif - -ifeq ($(CONFIG_V2RAY_WITHOUT_SOCKS_PROTO),y) -V2RAY_SED_ARGS += \ - s,_ "v2ray.com/core/proxy/socks",// &,; -endif - -ifeq ($(CONFIG_V2RAY_WITHOUT_VMESS_PROTO),y) -V2RAY_SED_ARGS += \ - s,_ "v2ray.com/core/proxy/vmess/inbound",// &,; \ - s,_ "v2ray.com/core/proxy/vmess/outbound",// &,; -endif - -ifeq ($(CONFIG_V2RAY_WITHOUT_TCP_TRANS),y) -V2RAY_SED_ARGS += \ - s,_ "v2ray.com/core/transport/internet/tcp",// &,; -endif - -ifeq ($(CONFIG_V2RAY_WITHOUT_MKCP_TRANS),y) -V2RAY_SED_ARGS += \ - s,_ "v2ray.com/core/transport/internet/kcp",// &,; -endif - -ifeq ($(CONFIG_V2RAY_WITHOUT_WEBSOCKET_TRANS),y) -V2RAY_SED_ARGS += \ - s,_ "v2ray.com/core/transport/internet/websocket",// &,; -endif - -ifeq ($(CONFIG_V2RAY_WITHOUT_HTTP2_TRANS),y) -V2RAY_SED_ARGS += \ - s,_ "v2ray.com/core/transport/internet/http",// &,; \ - s,_ "v2ray.com/core/transport/internet/headers/http",// &,; -endif - -ifeq ($(CONFIG_V2RAY_WITHOUT_DOMAIN_SOCKET_TRANS),y) -V2RAY_SED_ARGS += \ - s,_ "v2ray.com/core/transport/internet/domainsocket",// &,; -endif - -ifeq ($(CONFIG_V2RAY_WITHOUT_QUIC_TRANS),y) -V2RAY_SED_ARGS += \ - s,_ "v2ray.com/core/transport/internet/quic",// &,; -endif - -ifeq ($(CONFIG_V2RAY_WITHOUT_MKCP_TRANS)$(CONFIG_V2RAY_WITHOUT_QUIC_TRANS),yy) -V2RAY_SED_ARGS += \ - s,_ "v2ray.com/core/transport/internet/headers/noop",// &,; \ - s,_ "v2ray.com/core/transport/internet/headers/srtp",// &,; \ - s,_ "v2ray.com/core/transport/internet/headers/tls",// &,; \ - s,_ "v2ray.com/core/transport/internet/headers/utp",// &,; \ - s,_ "v2ray.com/core/transport/internet/headers/wechat",// &,; \ - s,_ "v2ray.com/core/transport/internet/headers/wireguard",// &,; -endif - -endif # custom features - -GEOIP_VER:=latest -GEOIP_FILE:=geoip-$(GEOIP_VER).dat - -define Download/geoip.dat - URL:=https://github.com/v2fly/geoip/releases/$(GEOIP_VER)/download - URL_FILE:=geoip.dat - FILE:=$(GEOIP_FILE) - HASH:=skip -endef - -GEOSITE_VER:=latest -GEOSITE_FILE:=geosite-$(GEOSITE_VER).dat - -define Download/geosite.dat - URL:=https://github.com/v2fly/domain-list-community/releases/$(GEOSITE_VER)/download - URL_FILE:=dlc.dat - FILE:=$(GEOSITE_FILE) - HASH:=skip -endef - -define Build/Prepare - $(call Build/Prepare/Default) - -ifneq ($(CONFIG_V2RAY_EXCLUDE_ASSETS),y) - # move file to make sure download new file every build - mv -f $(DL_DIR)/$(GEOIP_FILE) $(PKG_BUILD_DIR)/release/config/geoip.dat - mv -f $(DL_DIR)/$(GEOSITE_FILE) $(PKG_BUILD_DIR)/release/config/geosite.dat -endif - -ifneq ($(V2RAY_SED_ARGS),) - ( \ - $(SED) \ - '$(V2RAY_SED_ARGS)' \ - $(PKG_BUILD_DIR)/main/distro/all/all.go ; \ - ) -endif -endef - -define Build/Compile - $(eval GO_PKG_BUILD_PKG:=v2ray.com/core/main) - $(call GoPackage/Build/Compile) - mv -f $(GO_PKG_BUILD_BIN_DIR)/main $(GO_PKG_BUILD_BIN_DIR)/v2ray - -ifeq ($(CONFIG_V2RAY_COMPRESS_UPX),y) - $(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DIR)/v2ray || true -endif - -ifneq ($(CONFIG_V2RAY_EXCLUDE_V2CTL),y) - $(eval GO_PKG_BUILD_PKG:=v2ray.com/core/infra/control/main) - $(call GoPackage/Build/Compile) - mv -f $(GO_PKG_BUILD_BIN_DIR)/main $(GO_PKG_BUILD_BIN_DIR)/v2ctl - -ifeq ($(CONFIG_V2RAY_COMPRESS_UPX),y) - $(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DIR)/v2ctl || true -endif -endif -endef - -define Package/$(PKG_NAME)/install - $(INSTALL_DIR) $(1)/usr/bin/v2ray - - $(INSTALL_BIN) $(GO_PKG_BUILD_BIN_DIR)/v2ray $(1)/usr/bin/v2ray - -ifneq ($(CONFIG_V2RAY_EXCLUDE_V2CTL),y) - $(INSTALL_BIN) $(GO_PKG_BUILD_BIN_DIR)/v2ctl $(1)/usr/bin/v2ray -endif - -ifneq ($(CONFIG_V2RAY_EXCLUDE_ASSETS),y) - $(INSTALL_DATA) $(PKG_BUILD_DIR)/release/config/{geoip,geosite}.dat $(1)/usr/bin/v2ray -endif -endef - -ifneq ($(CONFIG_V2RAY_EXCLUDE_ASSETS),y) -$(eval $(call Download,geoip.dat)) -$(eval $(call Download,geosite.dat)) -endif - -$(eval $(call GoBinPackage,$(PKG_NAME))) -$(eval $(call BuildPackage,$(PKG_NAME))) diff --git a/package/verysync/Makefile b/package/verysync/Makefile deleted file mode 100755 index 9957b21..0000000 --- a/package/verysync/Makefile +++ /dev/null @@ -1,68 +0,0 @@ -# -# Copyright (C) 2015-2016 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v3. -# - -include $(TOPDIR)/rules.mk - -ifeq ($(ARCH),x86_64) - PKG_ARCH_VERYSYNC:=amd64 -endif -ifeq ($(ARCH),mipsel) - PKG_ARCH_VERYSYNC:=mipsle -endif -ifeq ($(ARCH),mips) - PKG_ARCH_VERYSYNC:=mips -endif -ifeq ($(ARCH),i386) - PKG_ARCH_VERYSYNC:=386 -endif -ifeq ($(ARCH),arm) - PKG_ARCH_VERYSYNC:=arm -endif -ifeq ($(ARCH),aarch64) - PKG_ARCH_VERYSYNC:=arm64 -endif -ifeq ($(ARCH),powerpc64) - PKG_ARCH_VERYSYNC:=ppc64 -endif - -PKG_NAME:=verysync -PKG_VERSION:=v1.4.4 -PKG_RELEASE:=1 -PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) -PKG_SOURCE:=$(PKG_NAME)-linux-$(PKG_ARCH_VERYSYNC)-$(PKG_VERSION).tar.gz -PKG_SOURCE_URL:=http://releases-cdn.verysync.com/releases/$(PKG_VERSION)/ -PKG_HASH:=skip - -include $(INCLUDE_DIR)/package.mk - -define Package/$(PKG_NAME) - SECTION:=net - CATEGORY:=Network - TITLE:=A efficient data transmission tool - DEPENDS:= - URL:=http://www.verysync.com -endef - -define Package/$(PKG_NAME)/description - Verysync is a efficient data transmission tool. -endef - -define Build/Prepare - tar -xzvf $(DL_DIR)/$(PKG_SOURCE) -C $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile -endef - -define Package/$(PKG_NAME)/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/$(PKG_NAME)-linux-$(PKG_ARCH_VERYSYNC)-$(PKG_VERSION)/verysync $(1)/usr/bin/verysync -endef - -$(eval $(call BuildPackage,$(PKG_NAME))) diff --git a/package/pdnsd-alt/Makefile b/pdnsd-alt/Makefile old mode 100755 new mode 100644 similarity index 65% rename from package/pdnsd-alt/Makefile rename to pdnsd-alt/Makefile index 1d69a96..f6b1765 --- a/package/pdnsd-alt/Makefile +++ b/pdnsd-alt/Makefile @@ -1,25 +1,30 @@ +# SPDX-License-Identifier: GPL-3.0-only +# +# Copyright (C) 2021 ImmortalWrt.org + include $(TOPDIR)/rules.mk PKG_NAME:=pdnsd PKG_VERSION:=1.2.9b-par -PKG_RELEASE=$(PKG_SOURCE_VERSION) +PKG_RELEASE:=2 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/shadowsocks/pdnsd.git -PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE_DATE:=2012-04-26 PKG_SOURCE_VERSION:=a8e46ccba7b0fa2230d6c42ab6dcd92926f6c21d -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz -# PKG_MIRROR_MD5SUM:= -# CMAKE_INSTALL:=1 +PKG_MIRROR_HASH:=e3e9c56cf91b12d8db73def2c247be2f726a052bed012f7a1e48946375f8e478 + +PKG_BUILD_PARALLEL:=1 +PKG_INSTALL:=1 include $(INCLUDE_DIR)/package.mk define Package/pdnsd-alt SECTION:=net CATEGORY:=Network - SUBMENU:=Web Servers/Proxies - DEPENDS:=+libpthread + SUBMENU:=IP Addresses and Names TITLE:=Proxy DNS Server + DEPENDS:=+libpthread endef define Package/pdnsd-alt/description @@ -33,23 +38,20 @@ define Package/pdnsd-alt/description endef TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include -#TARGET_CFLAGS += -ggdb3 - -CMAKE_OPTIONS += -DDEBUG=1 CONFIGURE_ARGS += \ - --with-cachedir=/var/pdnsd \ - --with-target=Linux + --with-cachedir=/var/pdnsd \ + --with-target=Linux define Package/pdnsd-alt/install $(INSTALL_DIR) $(1)/usr/sbin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/pdnsd $(1)/usr/sbin/ - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/pdnsd-ctl/pdnsd-ctl $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/pdnsd $(1)/usr/sbin/pdnsd + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/pdnsd-ctl $(1)/usr/sbin/pdnsd-ctl + + #$(INSTALL_DIR) $(1)/etc + #$(INSTALL_CONF) $(PKG_INSTALL_DIR)/etc/pdnsd.conf.sample $(1)/etc/pdnsd.conf #$(INSTALL_DIR) $(1)/etc/init.d #$(INSTALL_BIN) ./files/pdnsd.init $(1)/etc/init.d/pdnsd - $(INSTALL_DIR) $(1)/etc - $(INSTALL_CONF) $(PKG_BUILD_DIR)/doc/pdnsd.conf $(1)/etc/ endef $(eval $(call BuildPackage,pdnsd-alt)) diff --git a/package/pdnsd-alt/files/pdnsd.init b/pdnsd-alt/files/pdnsd.init old mode 100755 new mode 100644 similarity index 100% rename from package/pdnsd-alt/files/pdnsd.init rename to pdnsd-alt/files/pdnsd.init diff --git a/pdnsd-alt/patches/002-fix-pdnsd-alt-build-error-within-kernel_5.15.patch b/pdnsd-alt/patches/002-fix-pdnsd-alt-build-error-within-kernel_5.15.patch new file mode 100644 index 0000000..d24521c --- /dev/null +++ b/pdnsd-alt/patches/002-fix-pdnsd-alt-build-error-within-kernel_5.15.patch @@ -0,0 +1,52 @@ +From 09171eef574503a82342a8b23d4a55b8a5286724 Mon Sep 17 00:00:00 2001 +From: W_Y_CPP <383152993@qq.com> +Date: Sat, 1 Jan 2022 13:05:37 +0900 +Subject: [PATCH] fix pdnsd alt build error with kernel_5.15 + +--- + src/conff.h | 2 +- + src/dns.h | 2 +- + src/netdev.c | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/conff.h b/src/conff.h +index a07b1561b..c66d210aa 100644 +--- a/src/conff.h ++++ b/src/conff.h +@@ -32,7 +32,7 @@ + #include + #include + #include +-#include ++#include + #include "ipvers.h" + #include "list.h" + +diff --git a/src/dns.h b/src/dns.h +index 0f6a4ac1e..ecc9680b2 100644 +--- a/src/dns.h ++++ b/src/dns.h +@@ -27,7 +27,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + #include "rr_types.h" +diff --git a/src/netdev.c b/src/netdev.c +index bd5f8c451..bfd5046df 100644 +--- a/src/netdev.c ++++ b/src/netdev.c +@@ -59,7 +59,7 @@ + #include "ipvers.h" + #include + #include +-#include ++#include + #include + #include + #include +-- +2.17.1 diff --git a/shadowsocks-rust/Makefile b/shadowsocks-rust/Makefile new file mode 100644 index 0000000..e3fc4f0 --- /dev/null +++ b/shadowsocks-rust/Makefile @@ -0,0 +1,85 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Copyright (C) 2017-2020 Yousong Zhou +# Copyright (C) 2021 ImmortalWrt.org + +include $(TOPDIR)/rules.mk + +PKG_NAME:=shadowsocks-rust +PKG_VERSION:=1.13.2 +PKG_RELEASE:=$(AUTORELEASE) + +PKG_SOURCE_HEADER:=shadowsocks-v$(PKG_VERSION) +PKG_SOURCE_BODY:=unknown-linux-musl +PKG_SOURCE_FOOTER:=tar.xz +PKG_SOURCE_URL:=https://github.com/shadowsocks/shadowsocks-rust/releases/download/v$(PKG_VERSION)/ + +ifeq ($(ARCH),aarch64) + PKG_SOURCE:=$(PKG_SOURCE_HEADER).aarch64-$(PKG_SOURCE_BODY).$(PKG_SOURCE_FOOTER) + PKG_HASH:=1e61d747d6d5ea9dd4067bd19031a44e6a174d6235de82c8d309b42eb4fe0075 +else ifeq ($(ARCH),arm) + # Referred to golang/golang-values.mk + ARM_CPU_FEATURES:=$(word 2,$(subst +,$(space),$(call qstrip,$(CONFIG_CPU_TYPE)))) + ifeq ($(ARM_CPU_FEATURES),) + PKG_SOURCE:=$(PKG_SOURCE_HEADER).arm-$(PKG_SOURCE_BODY)eabi.$(PKG_SOURCE_FOOTER) + PKG_HASH:=b47b2215907fa071ae80abd0410b465dc4252e532cb343300fbd1fa88941e9c0 + else + PKG_SOURCE:=$(PKG_SOURCE_HEADER).arm-$(PKG_SOURCE_BODY)eabihf.$(PKG_SOURCE_FOOTER) + PKG_HASH:=92c3e631e442a71083d1bd9caedc40c0d2946e9d448a937d7e5d0961bcf62e72 + endif +else ifeq ($(ARCH),i386) + PKG_SOURCE:=$(PKG_SOURCE_HEADER).i686-$(PKG_SOURCE_BODY).$(PKG_SOURCE_FOOTER) + PKG_HASH:=78cc0444feda392a8a0b2cadac48ea358850c28bec3ebde5beb3f7e40b645b13 +else ifeq ($(ARCH),mips) + PKG_SOURCE:=$(PKG_SOURCE_HEADER).mips-$(PKG_SOURCE_BODY).$(PKG_SOURCE_FOOTER) + PKG_HASH:=11a3426646a2010ed679a10ae3d1c2d4f52c2c7d9c19127eeefd37fae51207b0 +else ifeq ($(ARCH),mipsel) + PKG_SOURCE:=$(PKG_SOURCE_HEADER).mipsel-$(PKG_SOURCE_BODY).$(PKG_SOURCE_FOOTER) + PKG_HASH:=77315b64be6a8ebc1ff65f2def0f912b03517e6384ebad10fe17d4924760da30 +else ifeq ($(ARCH),x86_64) + PKG_SOURCE:=$(PKG_SOURCE_HEADER).x86_64-$(PKG_SOURCE_BODY).$(PKG_SOURCE_FOOTER) + PKG_HASH:=155d37398d5b595068e4faed7220e6868537866b6e948f2d7b3adb077df6b0d5 +# Set the default value to make OpenWrt Package Checker happy +else + PKG_SOURCE:=dummy + PKG_HASH:=dummy +endif + +PKG_MAINTAINER:=Tianling Shen +PKG_LICENSE:=MIT +PKG_LICENSE_FILES:=LICENSE + +include $(INCLUDE_DIR)/package.mk + +TAR_CMD:=$(HOST_TAR) -C $(PKG_BUILD_DIR) $(TAR_OPTIONS) + +define Package/shadowsocks-rust/Default + define Package/shadowsocks-rust-$(1) + SECTION:=net + CATEGORY:=Network + SUBMENU:=Web Servers/Proxies + TITLE:=shadowsocks-rust $(1) + URL:=https://github.com/shadowsocks/shadowsocks-rust + DEPENDS:=@USE_MUSL @(aarch64||arm||i386||mips||mipsel||x86_64) @!(TARGET_x86_geode||TARGET_x86_legacy) + endef + + define Package/shadowsocks-rust-$(1)/install + $$(INSTALL_DIR) $$(1)/usr/bin + $$(INSTALL_BIN) $$(PKG_BUILD_DIR)/$(1) $$(1)/usr/bin + endef +endef + +SHADOWSOCKS_COMPONENTS:=sslocal ssmanager ssserver ssurl ssservice +define shadowsocks-rust/templates + $(foreach component,$(SHADOWSOCKS_COMPONENTS), + $(call Package/shadowsocks-rust/Default,$(component)) + ) +endef +$(eval $(call shadowsocks-rust/templates)) + +define Build/Compile +endef + +$(foreach component,$(SHADOWSOCKS_COMPONENTS), \ + $(eval $(call BuildPackage,shadowsocks-rust-$(component))) \ +) diff --git a/shadowsocksr-libev/Makefile b/shadowsocksr-libev/Makefile new file mode 100644 index 0000000..53612b2 --- /dev/null +++ b/shadowsocksr-libev/Makefile @@ -0,0 +1,64 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Copyright (C) 2017-2020 Yousong Zhou +# Copyright (C) 2018 Lean +# Copyright (C) 2021 ImmortalWrt.org + +include $(TOPDIR)/rules.mk + +PKG_NAME:=shadowsocksr-libev +PKG_VERSION:=2.5.6 +PKG_RELEASE:=9 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/shadowsocksrr/shadowsocksr-libev +PKG_SOURCE_DATE:=2018-03-07 +PKG_SOURCE_VERSION:=d63ff863800a5645aca4309d5dd5962bd1e95543 +PKG_MIRROR_HASH:=34308ed827a5dd4f4e35619914102d55b00604faa44fda051d1d25fb4a319325 + +PKG_LICENSE:=GPL-3.0 +PKG_LICENSE_FILES:=LICENSE + +PKG_FIXUP:=autoreconf +PKG_USE_MIPS16:=0 +PKG_BUILD_PARALLEL:=1 +PKG_INSTALL:=1 + +include $(INCLUDE_DIR)/package.mk + +define Package/shadowsocksr-libev/Default + define Package/shadowsocksr-libev-ssr-$(1) + SECTION:=net + CATEGORY:=Network + SUBMENU:=Web Servers/Proxies + TITLE:=shadowsocksr-libev ssr-$(1) + URL:=https://github.com/shadowsocksrr/shadowsocksr-libev + DEPENDS:=+libev +libsodium +libopenssl +libpthread +libpcre +libudns +zlib + endef + + define Package/shadowsocksr-libev-ssr-$(1)/install + $$(INSTALL_DIR) $$(1)/usr/bin + $$(INSTALL_BIN) $$(PKG_INSTALL_DIR)/usr/bin/ss-$(1) $$(1)/usr/bin/ssr-$(1) + endef +endef + +SHADOWSOCKSR_COMPONENTS:=check local nat redir server +define shadowsocksr-libev/templates + $(foreach component,$(SHADOWSOCKSR_COMPONENTS), + $(call Package/shadowsocksr-libev/Default,$(component)) + ) +endef +$(eval $(call shadowsocksr-libev/templates)) + +CONFIGURE_ARGS += \ + --disable-documentation \ + --disable-ssp \ + --disable-assert \ + --enable-system-shared-lib + +TARGET_CFLAGS += -flto +TARGET_LDFLAGS += -Wl,--gc-sections,--as-needed + +$(foreach component,$(SHADOWSOCKSR_COMPONENTS), \ + $(eval $(call BuildPackage,shadowsocksr-libev-ssr-$(component))) \ +) diff --git a/shadowsocksr-libev/patches/0001-Add-ss-server-and-ss-check.patch b/shadowsocksr-libev/patches/0001-Add-ss-server-and-ss-check.patch new file mode 100644 index 0000000..290ede5 --- /dev/null +++ b/shadowsocksr-libev/patches/0001-Add-ss-server-and-ss-check.patch @@ -0,0 +1,397 @@ +--- a/.gitignore ++++ b/.gitignore +@@ -2,6 +2,7 @@ build/ + .deps/ + /Makefile + src/Makefile ++server/Makefile + libev/Makefile + libudns/Makefile + libcork/Makefile +--- a/Makefile.am ++++ b/Makefile.am +@@ -1,7 +1,7 @@ + if USE_SYSTEM_SHARED_LIB +-SUBDIRS = libcork libipset src ++SUBDIRS = libcork libipset src server + else +-SUBDIRS = libsodium libcork libipset libudns libev src ++SUBDIRS = libsodium libcork libipset libudns libev src server + endif + + if ENABLE_DOCUMENTATION +--- a/Makefile.in ++++ b/Makefile.in +@@ -195,7 +195,7 @@ am__define_uniq_tagged_files = \ + ETAGS = etags + CTAGS = ctags + CSCOPE = cscope +-DIST_SUBDIRS = libsodium libcork libipset libudns libev src doc ++DIST_SUBDIRS = libsodium libcork libipset libudns libev src server doc + am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \ + $(srcdir)/shadowsocks-libev.pc.in $(top_srcdir)/auto/ar-lib \ + $(top_srcdir)/auto/compile $(top_srcdir)/auto/config.guess \ +@@ -377,8 +377,9 @@ top_build_prefix = @top_build_prefix@ + top_builddir = @top_builddir@ + top_srcdir = @top_srcdir@ + @USE_SYSTEM_SHARED_LIB_FALSE@SUBDIRS = libsodium libcork libipset \ +-@USE_SYSTEM_SHARED_LIB_FALSE@ libudns libev src $(am__append_1) +-@USE_SYSTEM_SHARED_LIB_TRUE@SUBDIRS = libcork libipset src \ ++@USE_SYSTEM_SHARED_LIB_FALSE@ libudns libev src server \ ++@USE_SYSTEM_SHARED_LIB_FALSE@ $(am__append_1) ++@USE_SYSTEM_SHARED_LIB_TRUE@SUBDIRS = libcork libipset src server \ + @USE_SYSTEM_SHARED_LIB_TRUE@ $(am__append_1) + ACLOCAL_AMFLAGS = -I m4 + pkgconfiglibdir = $(libdir)/pkgconfig +--- a/configure ++++ b/configure +@@ -649,7 +649,6 @@ PTHREAD_CC + ax_pthread_config + INET_NTOP_LIB + MV +-RM + GZIP + XMLTO + ASCIIDOC +@@ -757,6 +756,7 @@ infodir + docdir + oldincludedir + includedir ++runstatedir + localstatedir + sharedstatedir + sysconfdir +@@ -857,6 +857,7 @@ datadir='${datarootdir}' + sysconfdir='${prefix}/etc' + sharedstatedir='${prefix}/com' + localstatedir='${prefix}/var' ++runstatedir='${localstatedir}/run' + includedir='${prefix}/include' + oldincludedir='/usr/include' + docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +@@ -1109,6 +1110,15 @@ do + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + ++ -runstatedir | --runstatedir | --runstatedi | --runstated \ ++ | --runstate | --runstat | --runsta | --runst | --runs \ ++ | --run | --ru | --r) ++ ac_prev=runstatedir ;; ++ -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ ++ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ ++ | --run=* | --ru=* | --r=*) ++ runstatedir=$ac_optarg ;; ++ + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ +@@ -1246,7 +1256,7 @@ fi + for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ +- libdir localedir mandir ++ libdir localedir mandir runstatedir + do + eval ac_val=\$$ac_var + # Remove trailing slashes. +@@ -1399,6 +1409,7 @@ Fine tuning of the installation director + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] ++ --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] +@@ -2472,8 +2483,8 @@ ac_configure="$SHELL $ac_aux_dir/configu + + + +-# expand $ac_aux_dir to an absolute path +-am_aux_dir=`cd $ac_aux_dir && pwd` ++# Expand $ac_aux_dir to an absolute path. ++am_aux_dir=`cd "$ac_aux_dir" && pwd` + + ac_ext=c + ac_cpp='$CPP $CPPFLAGS' +@@ -3783,7 +3794,7 @@ $as_echo "$ac_cv_safe_to_define___extens + + + +-am__api_version='1.14' ++am__api_version='1.15' + + # Find a good install program. We prefer a C program (faster), + # so one script is as good as another. But avoid the broken or +@@ -3972,7 +3983,7 @@ else + $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} + fi + +-if test x"${install_sh}" != xset; then ++if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; +@@ -4363,8 +4374,8 @@ MAKEINFO=${MAKEINFO-"${am_missing_run}ma + # + mkdir_p='$(MKDIR_P)' + +-# We need awk for the "check" target. The system "awk" is bad on +-# some platforms. ++# We need awk for the "check" target (and possibly the TAP driver). The ++# system "awk" is bad on some platforms. + # Always define AMTAR for backward compatibility. Yes, it's still used + # in the wild :-( We should find a proper way to deprecate it ... + AMTAR='$${TAR-tar}' +@@ -4549,6 +4560,7 @@ END + as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 + fi + fi ++ + if test -n "$ac_tool_prefix"; then + for ac_prog in ar lib "link -lib" + do +@@ -12494,47 +12506,6 @@ $as_echo "no" >&6; } + fi + + +- # Extract the first word of "rm", so it can be a program name with args. +-set dummy rm; ac_word=$2 +-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +-$as_echo_n "checking for $ac_word... " >&6; } +-if ${ac_cv_path_RM+:} false; then : +- $as_echo_n "(cached) " >&6 +-else +- case $RM in +- [\\/]* | ?:[\\/]*) +- ac_cv_path_RM="$RM" # Let the user override the test with a path. +- ;; +- *) +- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +-for as_dir in $PATH +-do +- IFS=$as_save_IFS +- test -z "$as_dir" && as_dir=. +- for ac_exec_ext in '' $ac_executable_extensions; do +- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then +- ac_cv_path_RM="$as_dir/$ac_word$ac_exec_ext" +- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 +- break 2 +- fi +-done +- done +-IFS=$as_save_IFS +- +- test -z "$ac_cv_path_RM" && ac_cv_path_RM="rm" +- ;; +-esac +-fi +-RM=$ac_cv_path_RM +-if test -n "$RM"; then +- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RM" >&5 +-$as_echo "$RM" >&6; } +-else +- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +-$as_echo "no" >&6; } +-fi +- +- + # Extract the first word of "mv", so it can be a program name with args. + set dummy mv; ac_word=$2 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +@@ -16204,15 +16175,162 @@ $as_echo "#define HAVE_IPv6 1" >>confdef + + + if test -z "$USE_SYSTEM_SHARED_LIB_TRUE"; then : +- else ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sodium_init in -lsodium" >&5 ++$as_echo_n "checking for sodium_init in -lsodium... " >&6; } ++if ${ac_cv_lib_sodium_sodium_init+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ac_check_lib_save_LIBS=$LIBS ++LIBS="-lsodium $LIBS" ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++/* Override any GCC internal prototype to avoid an error. ++ Use char because int might match the return type of a GCC ++ builtin and then its argument prototype would still apply. */ ++#ifdef __cplusplus ++extern "C" ++#endif ++char sodium_init (); ++int ++main () ++{ ++return sodium_init (); ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_link "$LINENO"; then : ++ ac_cv_lib_sodium_sodium_init=yes ++else ++ ac_cv_lib_sodium_sodium_init=no ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++LIBS=$ac_check_lib_save_LIBS ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sodium_sodium_init" >&5 ++$as_echo "$ac_cv_lib_sodium_sodium_init" >&6; } ++if test "x$ac_cv_lib_sodium_sodium_init" = xyes; then : ++ cat >>confdefs.h <<_ACEOF ++#define HAVE_LIBSODIUM 1 ++_ACEOF ++ ++ LIBS="-lsodium $LIBS" ++ ++else ++ ++ as_fn_error $? "Couldn't find libsodium. Try installing libsodium-dev[el]." "$LINENO" 5 ++ ++fi ++ ++ ++else + subdirs="$subdirs libsodium" + + fi + +-ac_config_files="$ac_config_files shadowsocks-libev.pc Makefile libcork/Makefile libipset/Makefile src/Makefile" ++ac_config_files="$ac_config_files shadowsocks-libev.pc Makefile libcork/Makefile libipset/Makefile src/Makefile server/Makefile" + + if test -z "$USE_SYSTEM_SHARED_LIB_TRUE"; then : +- else ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dns_dnlen in -ludns" >&5 ++$as_echo_n "checking for dns_dnlen in -ludns... " >&6; } ++if ${ac_cv_lib_udns_dns_dnlen+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ac_check_lib_save_LIBS=$LIBS ++LIBS="-ludns $LIBS" ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++/* Override any GCC internal prototype to avoid an error. ++ Use char because int might match the return type of a GCC ++ builtin and then its argument prototype would still apply. */ ++#ifdef __cplusplus ++extern "C" ++#endif ++char dns_dnlen (); ++int ++main () ++{ ++return dns_dnlen (); ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_link "$LINENO"; then : ++ ac_cv_lib_udns_dns_dnlen=yes ++else ++ ac_cv_lib_udns_dns_dnlen=no ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++LIBS=$ac_check_lib_save_LIBS ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_udns_dns_dnlen" >&5 ++$as_echo "$ac_cv_lib_udns_dns_dnlen" >&6; } ++if test "x$ac_cv_lib_udns_dns_dnlen" = xyes; then : ++ cat >>confdefs.h <<_ACEOF ++#define HAVE_LIBUDNS 1 ++_ACEOF ++ ++ LIBS="-ludns $LIBS" ++ ++else ++ as_fn_error $? "Couldn't find libudns. Try installing libudns-dev or udns-devel." "$LINENO" 5 ++fi ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ev_loop_destroy in -lev" >&5 ++$as_echo_n "checking for ev_loop_destroy in -lev... " >&6; } ++if ${ac_cv_lib_ev_ev_loop_destroy+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ ac_check_lib_save_LIBS=$LIBS ++LIBS="-lev $LIBS" ++cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++ ++/* Override any GCC internal prototype to avoid an error. ++ Use char because int might match the return type of a GCC ++ builtin and then its argument prototype would still apply. */ ++#ifdef __cplusplus ++extern "C" ++#endif ++char ev_loop_destroy (); ++int ++main () ++{ ++return ev_loop_destroy (); ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_link "$LINENO"; then : ++ ac_cv_lib_ev_ev_loop_destroy=yes ++else ++ ac_cv_lib_ev_ev_loop_destroy=no ++fi ++rm -f core conftest.err conftest.$ac_objext \ ++ conftest$ac_exeext conftest.$ac_ext ++LIBS=$ac_check_lib_save_LIBS ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ev_ev_loop_destroy" >&5 ++$as_echo "$ac_cv_lib_ev_ev_loop_destroy" >&6; } ++if test "x$ac_cv_lib_ev_ev_loop_destroy" = xyes; then : ++ cat >>confdefs.h <<_ACEOF ++#define HAVE_LIBEV 1 ++_ACEOF ++ ++ LIBS="-lev $LIBS" ++ ++else ++ as_fn_error $? "Couldn't find libev. Try installing libev-dev[el]." "$LINENO" 5 ++fi ++ ++ ++else + ac_config_files="$ac_config_files libudns/Makefile libev/Makefile" + + fi +@@ -17258,6 +17376,7 @@ do + "libcork/Makefile") CONFIG_FILES="$CONFIG_FILES libcork/Makefile" ;; + "libipset/Makefile") CONFIG_FILES="$CONFIG_FILES libipset/Makefile" ;; + "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; ++ "server/Makefile") CONFIG_FILES="$CONFIG_FILES server/Makefile" ;; + "libudns/Makefile") CONFIG_FILES="$CONFIG_FILES libudns/Makefile" ;; + "libev/Makefile") CONFIG_FILES="$CONFIG_FILES libev/Makefile" ;; + "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; +@@ -17958,8 +18077,8 @@ $as_echo X"$file" | + fi + + cfgfile="${ofile}T" +- trap "$RM -f \"$cfgfile\"; exit 1" 1 2 15 +- $RM -f "$cfgfile" ++ trap "$RM \"$cfgfile\"; exit 1" 1 2 15 ++ $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" + #! $SHELL +--- a/configure.ac ++++ b/configure.ac +@@ -315,7 +315,8 @@ AC_CONFIG_FILES([ shadowsocks-libev.pc + Makefile + libcork/Makefile + libipset/Makefile +- src/Makefile]) ++ src/Makefile ++ server/Makefile]) + AM_COND_IF([USE_SYSTEM_SHARED_LIB],[ + AC_CHECK_LIB([udns], [dns_dnlen], ,[AC_MSG_ERROR([Couldn't find libudns. Try installing libudns-dev or udns-devel.])]) + AC_CHECK_LIB([ev], [ev_loop_destroy], ,[AC_MSG_ERROR([Couldn't find libev. Try installing libev-dev@<:@el@:>@.])]) diff --git a/package/shadowsocksr-libev/patches/0002-Revert-verify_simple-and-auth_simple.patch b/shadowsocksr-libev/patches/0002-Revert-verify_simple-and-auth_simple.patch old mode 100755 new mode 100644 similarity index 81% rename from package/shadowsocksr-libev/patches/0002-Revert-verify_simple-and-auth_simple.patch rename to shadowsocksr-libev/patches/0002-Revert-verify_simple-and-auth_simple.patch index 72ee333..0f81146 --- a/package/shadowsocksr-libev/patches/0002-Revert-verify_simple-and-auth_simple.patch +++ b/shadowsocksr-libev/patches/0002-Revert-verify_simple-and-auth_simple.patch @@ -1,8 +1,6 @@ -diff --git a/src/obfs/obfs.c b/src/obfs/obfs.c -index 463359f..4cd750a 100644 --- a/src/obfs/obfs.c +++ b/src/obfs/obfs.c -@@ -88,7 +88,7 @@ +@@ -88,7 +88,7 @@ obfs_class *new_obfs_class(const char *p plugin->client_decode = tls12_ticket_auth_client_decode; return plugin; @@ -11,7 +9,7 @@ index 463359f..4cd750a 100644 obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs_class)); plugin->init_data = init_data; plugin->new_obfs = verify_simple_new_obfs; -@@ -115,7 +115,7 @@ +@@ -115,7 +115,7 @@ obfs_class *new_obfs_class(const char *p plugin->client_udp_pre_encrypt = NULL; plugin->client_udp_post_decrypt = NULL; @@ -19,4 +17,4 @@ index 463359f..4cd750a 100644 + return plugin; } else if (strcmp(plugin_name, "auth_sha1") == 0) { obfs_class *plugin = (obfs_class *) malloc(sizeof(obfs_class)); - plugin->init_data = auth_simple_init_data; \ No newline at end of file + plugin->init_data = auth_simple_init_data; diff --git a/package/shadowsocksr-libev/patches/0003-Refine-Usage.patch b/shadowsocksr-libev/patches/0003-Refine-Usage.patch old mode 100755 new mode 100644 similarity index 92% rename from package/shadowsocksr-libev/patches/0003-Refine-Usage.patch rename to shadowsocksr-libev/patches/0003-Refine-Usage.patch index 85aa0f1..dd44f58 --- a/package/shadowsocksr-libev/patches/0003-Refine-Usage.patch +++ b/shadowsocksr-libev/patches/0003-Refine-Usage.patch @@ -1,5 +1,3 @@ -diff --git a/src/utils.c b/src/utils.c -index 94f8a83..01bcbac 100644 --- a/src/utils.c +++ b/src/utils.c @@ -258,8 +258,6 @@ usage() @@ -11,11 +9,10 @@ index 94f8a83..01bcbac 100644 printf(" usage:\n\n"); #ifdef MODULE_LOCAL printf(" ss-local\n"); -@@ -298,6 +296,25 @@ usage() - printf( +@@ -299,6 +297,25 @@ usage() " The default cipher is rc4-md5.\n"); printf("\n"); -+ printf( + printf( + " -o Obfs of your remote server: plain,\n"); + printf( + " http_simple, http_post and tls1.2_ticket_auth.\n"); @@ -34,9 +31,7 @@ index 94f8a83..01bcbac 100644 + printf( + " -G Protocol-Param of your remote server.\n"); + printf("\n"); - printf( ++ printf( " [-a ] Run as another user.\n"); printf( --- -2.19.1 - + " [-f ] The file path to store pid.\n"); diff --git a/shadowsocksr-libev/patches/100-fix-gcc-10.patch b/shadowsocksr-libev/patches/100-fix-gcc-10.patch new file mode 100644 index 0000000..1049fc2 --- /dev/null +++ b/shadowsocksr-libev/patches/100-fix-gcc-10.patch @@ -0,0 +1,20 @@ +--- a/src/http.h ++++ b/src/http.h +@@ -29,6 +29,6 @@ + #include + #include "protocol.h" + +-const protocol_t *const http_protocol; ++extern const protocol_t *const http_protocol; + + #endif +--- a/src/tls.h ++++ b/src/tls.h +@@ -28,6 +28,6 @@ + + #include "protocol.h" + +-const protocol_t *const tls_protocol; ++extern const protocol_t *const tls_protocol; + + #endif diff --git a/package/shadowsocksr-libev/patches/999-Fix-Werror-sizeof-pointer-memaccess.patch b/shadowsocksr-libev/patches/101-Fix-Werror-sizeof-pointer-memaccess.patch old mode 100755 new mode 100644 similarity index 78% rename from package/shadowsocksr-libev/patches/999-Fix-Werror-sizeof-pointer-memaccess.patch rename to shadowsocksr-libev/patches/101-Fix-Werror-sizeof-pointer-memaccess.patch index 9da0c52..1db501a --- a/package/shadowsocksr-libev/patches/999-Fix-Werror-sizeof-pointer-memaccess.patch +++ b/shadowsocksr-libev/patches/101-Fix-Werror-sizeof-pointer-memaccess.patch @@ -1,6 +1,6 @@ --- a/src/local.c +++ b/src/local.c -@@ -718,7 +718,7 @@ +@@ -718,7 +718,7 @@ server_recv_cb(EV_P_ ev_io *w, int reven ss_free(hostname); } else { diff --git a/shadowsocksr-libev/patches/102-Read-listening-mode-from-config.patch b/shadowsocksr-libev/patches/102-Read-listening-mode-from-config.patch new file mode 100644 index 0000000..57f6f76 --- /dev/null +++ b/shadowsocksr-libev/patches/102-Read-listening-mode-from-config.patch @@ -0,0 +1,34 @@ +--- a/src/jconf.c ++++ b/src/jconf.c +@@ -259,6 +259,19 @@ read_jconf(const char *file) + conf.server_legacy.obfs = to_string(value); + } else if (strcmp(name, "obfs_param") == 0) { // SSR + conf.server_legacy.obfs_param = to_string(value); ++ } else if (strcmp(name, "mode") == 0) { ++ char *mode_str = to_string(value); ++ ++ if (strcmp(mode_str, "tcp_only") == 0) ++ conf.mode = TCP_ONLY; ++ else if (strcmp(mode_str, "tcp_and_udp") == 0) ++ conf.mode = TCP_AND_UDP; ++ else if (strcmp(mode_str, "udp_only") == 0) ++ conf.mode = UDP_ONLY; ++ else ++ LOGI("ignore unknown mode: %s, use tcp_only as fallback", ++ mode_str); ++ ss_free(mode_str); + } else { + match = 0; + } +--- a/src/redir.c ++++ b/src/redir.c +@@ -1252,6 +1252,9 @@ main(int argc, char **argv) + if (user == NULL) { + user = conf->user; + } ++ if (mode == TCP_ONLY) { ++ mode = conf->mode; ++ } + if (mtu == 0) { + mtu = conf->mtu; + } diff --git a/shadowsocksr-libev/patches/999-tcp-tproxy.patch b/shadowsocksr-libev/patches/999-tcp-tproxy.patch new file mode 100644 index 0000000..c73536d --- /dev/null +++ b/shadowsocksr-libev/patches/999-tcp-tproxy.patch @@ -0,0 +1,154 @@ +--- a/completions/bash/ss-redir ++++ b/completions/bash/ss-redir +@@ -2,7 +2,7 @@ + { + local cur prev opts ciphers + ciphers='rc4-md5 table rc4 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 and chacha20-ietf' +- opts='-s -b -p -k -f -t -m -c -a -n -u -U -v -h -A --mtu --help --mptcp -l' ++ opts='-s -b -p -k -f -t -m -c -a -n -u -U -T -v -h -A --mtu --help --mptcp -l' + cur=${COMP_WORDS[COMP_CWORD]} + prev="${COMP_WORDS[COMP_CWORD-1]}" + case "$prev" in +--- a/src/jconf.c ++++ b/src/jconf.c +@@ -338,7 +338,11 @@ + check_json_value_type(value, json_boolean, + "invalid config file: option 'ipv6_first' must be a boolean"); + conf.ipv6_first = value->u.boolean; +- } ++ } else if (strcmp(name, "tcp_tproxy") == 0) { ++ check_json_value_type(value, json_boolean, ++ "invalid config file: option 'tcp_tproxy' must be a boolean"); ++ conf.tcp_tproxy = value->u.boolean; ++ } + } + } + } else { +--- a/src/jconf.h ++++ b/src/jconf.h +@@ -105,6 +105,7 @@ + int mtu; + int mptcp; + int ipv6_first; ++ int tcp_tproxy; + } jconf_t; + + jconf_t *read_jconf(const char *file); +--- a/src/redir.c ++++ b/src/redir.c +@@ -71,6 +71,14 @@ + #define IP6T_SO_ORIGINAL_DST 80 + #endif + ++#ifndef IP_TRANSPARENT ++#define IP_TRANSPARENT 19 ++#endif ++ ++#ifndef IPV6_TRANSPARENT ++#define IPV6_TRANSPARENT 75 ++#endif ++ + #include "includeobfs.h" // I don't want to modify makefile + #include "jconf.h" + +@@ -101,18 +109,28 @@ + static listen_ctx_t *current_profile; + static struct cork_dllist all_connections; + ++static int tcp_tproxy = 0; /* use tproxy instead of redirect (for tcp) */ ++ + int + getdestaddr(int fd, struct sockaddr_storage *destaddr) + { + socklen_t socklen = sizeof(*destaddr); + int error = 0; + +- error = getsockopt(fd, SOL_IPV6, IP6T_SO_ORIGINAL_DST, destaddr, &socklen); +- if (error) { // Didn't find a proper way to detect IP version. +- error = getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, destaddr, &socklen); +- if (error) { +- return -1; +- } ++ if (tcp_tproxy) { ++ error = getsockname(fd, (void *)destaddr, &socklen); ++ } else { ++ error = getsockopt(fd, SOL_IPV6, IP6T_SO_ORIGINAL_DST, destaddr, &socklen); ++ if (error) { // Didn't find a proper way to detect IP version. ++ error = getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, destaddr, &socklen); ++ if (error) { ++ return -1; ++ } ++ } ++ } ++ ++ if (error) { ++ return -1; + } + return 0; + } +@@ -164,6 +182,23 @@ + if (err == 0) { + LOGI("tcp port reuse enabled"); + } ++ ++ if (tcp_tproxy) { ++ int level = 0, optname = 0; ++ if (rp->ai_family == AF_INET) { ++ level = IPPROTO_IP; ++ optname = IP_TRANSPARENT; ++ } else { ++ level = IPPROTO_IPV6; ++ optname = IPV6_TRANSPARENT; ++ } ++ ++ if (setsockopt(listen_sock, level, optname, &opt, sizeof(opt)) != 0) { ++ ERROR("setsockopt IP_TRANSPARENT"); ++ exit(EXIT_FAILURE); ++ } ++ LOGI("tcp tproxy mode enabled"); ++ } + + s = bind(listen_sock, rp->ai_addr, rp->ai_addrlen); + if (s == 0) { +@@ -1094,7 +1129,7 @@ + + USE_TTY(); + +- while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:c:b:a:n:huUvA6" ++ while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:c:b:a:n:huUTvA6" + "O:o:G:g:", + long_options, &option_index)) != -1) { + switch (c) { +@@ -1169,6 +1204,9 @@ + case 'U': + mode = UDP_ONLY; + break; ++ case 'T': ++ tcp_tproxy = 1; ++ break; + case 'v': + verbose = 1; + break; +@@ -1255,6 +1293,9 @@ + if (mode == TCP_ONLY) { + mode = conf->mode; + } ++ if (tcp_tproxy == 0) { ++ tcp_tproxy = conf->tcp_tproxy; ++ } + if (mtu == 0) { + mtu = conf->mtu; + } +--- a/src/utils.c ++++ b/src/utils.c +@@ -342,6 +342,10 @@ + #endif + printf( + " [-U] Enable UDP relay and disable TCP relay.\n"); ++#ifdef MODULE_REDIR ++ printf( ++ " [-T] Use tproxy instead of redirect (for tcp).\n"); ++#endif + #ifdef MODULE_REMOTE + printf( + " [-6] Resovle hostname to IPv6 address first.\n"); diff --git a/shadowsocksr-libev/src/server/Makefile.am b/shadowsocksr-libev/src/server/Makefile.am new file mode 100644 index 0000000..3ae8bc2 --- /dev/null +++ b/shadowsocksr-libev/src/server/Makefile.am @@ -0,0 +1,55 @@ +VERSION_INFO = 2:0:0 + +AM_CFLAGS = -g -O2 -Wall -Werror -Wno-deprecated-declarations -fno-strict-aliasing -std=gnu99 -D_GNU_SOURCE +AM_CFLAGS += $(PTHREAD_CFLAGS) +if !USE_SYSTEM_SHARED_LIB +AM_CFLAGS += -I$(top_srcdir)/libev +AM_CFLAGS += -I$(top_srcdir)/libudns +AM_CFLAGS += -I$(top_srcdir)/libsodium/src/libsodium/include +endif +AM_CFLAGS += -I$(top_srcdir)/libipset/include +AM_CFLAGS += -I$(top_srcdir)/libcork/include +AM_CFLAGS += $(LIBPCRE_CFLAGS) + +SS_COMMON_LIBS = $(top_builddir)/libipset/libipset.la \ + $(top_builddir)/libcork/libcork.la \ + $(INET_NTOP_LIB) $(LIBPCRE_LIBS) +if USE_SYSTEM_SHARED_LIB +SS_COMMON_LIBS += -lev -lsodium -lm +else +SS_COMMON_LIBS += $(top_builddir)/libev/libev.la \ + $(top_builddir)/libsodium/src/libsodium/libsodium.la +endif + +bin_PROGRAMS = ss-server ss-check + +sni_src = http.c \ + tls.c \ + rule.c + +ss_check_SOURCES = check.c + +ss_server_SOURCES = utils.c \ + netutils.c \ + jconf.c \ + json.c \ + encrypt.c \ + udprelay.c \ + cache.c \ + acl.c \ + resolv.c \ + server.c \ + $(sni_src) + + +ss_check_LDADD = $(SS_COMMON_LIBS) +ss_server_LDADD = $(SS_COMMON_LIBS) + +if USE_SYSTEM_SHARED_LIB +ss_server_LDADD += -ludns +else +ss_server_LDADD += $(top_builddir)/libudns/libudns.la +endif + +ss_check_CFLAGS = $(AM_CFLAGS) +ss_server_CFLAGS = $(AM_CFLAGS) -DMODULE_REMOTE diff --git a/shadowsocksr-libev/src/server/Makefile.in b/shadowsocksr-libev/src/server/Makefile.in new file mode 100644 index 0000000..3bfa53e --- /dev/null +++ b/shadowsocksr-libev/src/server/Makefile.in @@ -0,0 +1,919 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@USE_SYSTEM_SHARED_LIB_FALSE@am__append_1 = -I$(top_srcdir)/libev \ +@USE_SYSTEM_SHARED_LIB_FALSE@ -I$(top_srcdir)/libudns \ +@USE_SYSTEM_SHARED_LIB_FALSE@ -I$(top_srcdir)/libsodium/src/libsodium/include +@USE_SYSTEM_SHARED_LIB_TRUE@am__append_2 = -lev -lsodium -lm +@USE_SYSTEM_SHARED_LIB_FALSE@am__append_3 = $(top_builddir)/libev/libev.la \ +@USE_SYSTEM_SHARED_LIB_FALSE@ $(top_builddir)/libsodium/src/libsodium/libsodium.la + +bin_PROGRAMS = ss-server$(EXEEXT) ss-check$(EXEEXT) +@USE_SYSTEM_SHARED_LIB_TRUE@am__append_4 = -ludns +@USE_SYSTEM_SHARED_LIB_FALSE@am__append_5 = $(top_builddir)/libudns/libudns.la +subdir = server +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_pthread.m4 \ + $(top_srcdir)/m4/ax_tls.m4 $(top_srcdir)/m4/inet_ntop.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/mbedtls.m4 \ + $(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/pcre.m4 \ + $(top_srcdir)/m4/polarssl.m4 \ + $(top_srcdir)/m4/stack-protector.m4 $(top_srcdir)/m4/zlib.m4 \ + $(top_srcdir)/libev/libev.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +am_ss_check_OBJECTS = ss_check-check.$(OBJEXT) +ss_check_OBJECTS = $(am_ss_check_OBJECTS) +am__DEPENDENCIES_1 = +am__DEPENDENCIES_2 = $(top_builddir)/libipset/libipset.la \ + $(top_builddir)/libcork/libcork.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__append_3) +ss_check_DEPENDENCIES = $(am__DEPENDENCIES_2) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +ss_check_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(ss_check_CFLAGS) \ + $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +am__objects_1 = ss_server-http.$(OBJEXT) ss_server-tls.$(OBJEXT) \ + ss_server-rule.$(OBJEXT) +am_ss_server_OBJECTS = ss_server-utils.$(OBJEXT) \ + ss_server-netutils.$(OBJEXT) ss_server-jconf.$(OBJEXT) \ + ss_server-json.$(OBJEXT) ss_server-encrypt.$(OBJEXT) \ + ss_server-udprelay.$(OBJEXT) ss_server-cache.$(OBJEXT) \ + ss_server-acl.$(OBJEXT) ss_server-resolv.$(OBJEXT) \ + ss_server-server.$(OBJEXT) $(am__objects_1) +ss_server_OBJECTS = $(am_ss_server_OBJECTS) +ss_server_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \ + $(am__append_5) +ss_server_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(ss_server_CFLAGS) \ + $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/auto/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(ss_check_SOURCES) $(ss_server_SOURCES) +DIST_SOURCES = $(ss_check_SOURCES) $(ss_server_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/auto/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +ASCIIDOC = @ASCIIDOC@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +GZIP = @GZIP@ +INET_NTOP_LIB = @INET_NTOP_LIB@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBPCRE = @LIBPCRE@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MV = @MV@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PCRE_CONFIG = @PCRE_CONFIG@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +XMLTO = @XMLTO@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pcre_pcreh = @pcre_pcreh@ +pcreh = @pcreh@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +VERSION_INFO = 2:0:0 +AM_CFLAGS = -g -O2 -Wall -Werror -Wno-deprecated-declarations \ + -fno-strict-aliasing -std=gnu99 -D_GNU_SOURCE \ + $(PTHREAD_CFLAGS) $(am__append_1) \ + -I$(top_srcdir)/libipset/include \ + -I$(top_srcdir)/libcork/include $(LIBPCRE_CFLAGS) +SS_COMMON_LIBS = $(top_builddir)/libipset/libipset.la \ + $(top_builddir)/libcork/libcork.la $(INET_NTOP_LIB) \ + $(LIBPCRE_LIBS) $(am__append_2) $(am__append_3) +sni_src = http.c \ + tls.c \ + rule.c + +ss_check_SOURCES = check.c +ss_server_SOURCES = utils.c \ + netutils.c \ + jconf.c \ + json.c \ + encrypt.c \ + udprelay.c \ + cache.c \ + acl.c \ + resolv.c \ + server.c \ + $(sni_src) + +ss_check_LDADD = $(SS_COMMON_LIBS) +ss_server_LDADD = $(SS_COMMON_LIBS) $(am__append_4) $(am__append_5) +ss_check_CFLAGS = $(AM_CFLAGS) +ss_server_CFLAGS = $(AM_CFLAGS) -DMODULE_REMOTE +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign server/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign server/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +ss-check$(EXEEXT): $(ss_check_OBJECTS) $(ss_check_DEPENDENCIES) $(EXTRA_ss_check_DEPENDENCIES) + @rm -f ss-check$(EXEEXT) + $(AM_V_CCLD)$(ss_check_LINK) $(ss_check_OBJECTS) $(ss_check_LDADD) $(LIBS) + +ss-server$(EXEEXT): $(ss_server_OBJECTS) $(ss_server_DEPENDENCIES) $(EXTRA_ss_server_DEPENDENCIES) + @rm -f ss-server$(EXEEXT) + $(AM_V_CCLD)$(ss_server_LINK) $(ss_server_OBJECTS) $(ss_server_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_check-check.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-acl.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-cache.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-encrypt.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-http.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-jconf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-json.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-netutils.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-resolv.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-rule.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-server.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-tls.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-udprelay.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-utils.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +ss_check-check.o: check.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_check_CFLAGS) $(CFLAGS) -MT ss_check-check.o -MD -MP -MF $(DEPDIR)/ss_check-check.Tpo -c -o ss_check-check.o `test -f 'check.c' || echo '$(srcdir)/'`check.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_check-check.Tpo $(DEPDIR)/ss_check-check.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='check.c' object='ss_check-check.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_check_CFLAGS) $(CFLAGS) -c -o ss_check-check.o `test -f 'check.c' || echo '$(srcdir)/'`check.c + +ss_check-check.obj: check.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_check_CFLAGS) $(CFLAGS) -MT ss_check-check.obj -MD -MP -MF $(DEPDIR)/ss_check-check.Tpo -c -o ss_check-check.obj `if test -f 'check.c'; then $(CYGPATH_W) 'check.c'; else $(CYGPATH_W) '$(srcdir)/check.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_check-check.Tpo $(DEPDIR)/ss_check-check.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='check.c' object='ss_check-check.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_check_CFLAGS) $(CFLAGS) -c -o ss_check-check.obj `if test -f 'check.c'; then $(CYGPATH_W) 'check.c'; else $(CYGPATH_W) '$(srcdir)/check.c'; fi` + +ss_server-utils.o: utils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-utils.o -MD -MP -MF $(DEPDIR)/ss_server-utils.Tpo -c -o ss_server-utils.o `test -f 'utils.c' || echo '$(srcdir)/'`utils.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-utils.Tpo $(DEPDIR)/ss_server-utils.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='utils.c' object='ss_server-utils.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-utils.o `test -f 'utils.c' || echo '$(srcdir)/'`utils.c + +ss_server-utils.obj: utils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-utils.obj -MD -MP -MF $(DEPDIR)/ss_server-utils.Tpo -c -o ss_server-utils.obj `if test -f 'utils.c'; then $(CYGPATH_W) 'utils.c'; else $(CYGPATH_W) '$(srcdir)/utils.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-utils.Tpo $(DEPDIR)/ss_server-utils.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='utils.c' object='ss_server-utils.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-utils.obj `if test -f 'utils.c'; then $(CYGPATH_W) 'utils.c'; else $(CYGPATH_W) '$(srcdir)/utils.c'; fi` + +ss_server-netutils.o: netutils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-netutils.o -MD -MP -MF $(DEPDIR)/ss_server-netutils.Tpo -c -o ss_server-netutils.o `test -f 'netutils.c' || echo '$(srcdir)/'`netutils.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-netutils.Tpo $(DEPDIR)/ss_server-netutils.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netutils.c' object='ss_server-netutils.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-netutils.o `test -f 'netutils.c' || echo '$(srcdir)/'`netutils.c + +ss_server-netutils.obj: netutils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-netutils.obj -MD -MP -MF $(DEPDIR)/ss_server-netutils.Tpo -c -o ss_server-netutils.obj `if test -f 'netutils.c'; then $(CYGPATH_W) 'netutils.c'; else $(CYGPATH_W) '$(srcdir)/netutils.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-netutils.Tpo $(DEPDIR)/ss_server-netutils.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netutils.c' object='ss_server-netutils.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-netutils.obj `if test -f 'netutils.c'; then $(CYGPATH_W) 'netutils.c'; else $(CYGPATH_W) '$(srcdir)/netutils.c'; fi` + +ss_server-jconf.o: jconf.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-jconf.o -MD -MP -MF $(DEPDIR)/ss_server-jconf.Tpo -c -o ss_server-jconf.o `test -f 'jconf.c' || echo '$(srcdir)/'`jconf.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-jconf.Tpo $(DEPDIR)/ss_server-jconf.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='jconf.c' object='ss_server-jconf.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-jconf.o `test -f 'jconf.c' || echo '$(srcdir)/'`jconf.c + +ss_server-jconf.obj: jconf.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-jconf.obj -MD -MP -MF $(DEPDIR)/ss_server-jconf.Tpo -c -o ss_server-jconf.obj `if test -f 'jconf.c'; then $(CYGPATH_W) 'jconf.c'; else $(CYGPATH_W) '$(srcdir)/jconf.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-jconf.Tpo $(DEPDIR)/ss_server-jconf.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='jconf.c' object='ss_server-jconf.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-jconf.obj `if test -f 'jconf.c'; then $(CYGPATH_W) 'jconf.c'; else $(CYGPATH_W) '$(srcdir)/jconf.c'; fi` + +ss_server-json.o: json.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-json.o -MD -MP -MF $(DEPDIR)/ss_server-json.Tpo -c -o ss_server-json.o `test -f 'json.c' || echo '$(srcdir)/'`json.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-json.Tpo $(DEPDIR)/ss_server-json.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='json.c' object='ss_server-json.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-json.o `test -f 'json.c' || echo '$(srcdir)/'`json.c + +ss_server-json.obj: json.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-json.obj -MD -MP -MF $(DEPDIR)/ss_server-json.Tpo -c -o ss_server-json.obj `if test -f 'json.c'; then $(CYGPATH_W) 'json.c'; else $(CYGPATH_W) '$(srcdir)/json.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-json.Tpo $(DEPDIR)/ss_server-json.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='json.c' object='ss_server-json.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-json.obj `if test -f 'json.c'; then $(CYGPATH_W) 'json.c'; else $(CYGPATH_W) '$(srcdir)/json.c'; fi` + +ss_server-encrypt.o: encrypt.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-encrypt.o -MD -MP -MF $(DEPDIR)/ss_server-encrypt.Tpo -c -o ss_server-encrypt.o `test -f 'encrypt.c' || echo '$(srcdir)/'`encrypt.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-encrypt.Tpo $(DEPDIR)/ss_server-encrypt.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='encrypt.c' object='ss_server-encrypt.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-encrypt.o `test -f 'encrypt.c' || echo '$(srcdir)/'`encrypt.c + +ss_server-encrypt.obj: encrypt.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-encrypt.obj -MD -MP -MF $(DEPDIR)/ss_server-encrypt.Tpo -c -o ss_server-encrypt.obj `if test -f 'encrypt.c'; then $(CYGPATH_W) 'encrypt.c'; else $(CYGPATH_W) '$(srcdir)/encrypt.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-encrypt.Tpo $(DEPDIR)/ss_server-encrypt.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='encrypt.c' object='ss_server-encrypt.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-encrypt.obj `if test -f 'encrypt.c'; then $(CYGPATH_W) 'encrypt.c'; else $(CYGPATH_W) '$(srcdir)/encrypt.c'; fi` + +ss_server-udprelay.o: udprelay.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-udprelay.o -MD -MP -MF $(DEPDIR)/ss_server-udprelay.Tpo -c -o ss_server-udprelay.o `test -f 'udprelay.c' || echo '$(srcdir)/'`udprelay.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-udprelay.Tpo $(DEPDIR)/ss_server-udprelay.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='udprelay.c' object='ss_server-udprelay.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-udprelay.o `test -f 'udprelay.c' || echo '$(srcdir)/'`udprelay.c + +ss_server-udprelay.obj: udprelay.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-udprelay.obj -MD -MP -MF $(DEPDIR)/ss_server-udprelay.Tpo -c -o ss_server-udprelay.obj `if test -f 'udprelay.c'; then $(CYGPATH_W) 'udprelay.c'; else $(CYGPATH_W) '$(srcdir)/udprelay.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-udprelay.Tpo $(DEPDIR)/ss_server-udprelay.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='udprelay.c' object='ss_server-udprelay.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-udprelay.obj `if test -f 'udprelay.c'; then $(CYGPATH_W) 'udprelay.c'; else $(CYGPATH_W) '$(srcdir)/udprelay.c'; fi` + +ss_server-cache.o: cache.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-cache.o -MD -MP -MF $(DEPDIR)/ss_server-cache.Tpo -c -o ss_server-cache.o `test -f 'cache.c' || echo '$(srcdir)/'`cache.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-cache.Tpo $(DEPDIR)/ss_server-cache.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cache.c' object='ss_server-cache.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-cache.o `test -f 'cache.c' || echo '$(srcdir)/'`cache.c + +ss_server-cache.obj: cache.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-cache.obj -MD -MP -MF $(DEPDIR)/ss_server-cache.Tpo -c -o ss_server-cache.obj `if test -f 'cache.c'; then $(CYGPATH_W) 'cache.c'; else $(CYGPATH_W) '$(srcdir)/cache.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-cache.Tpo $(DEPDIR)/ss_server-cache.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cache.c' object='ss_server-cache.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-cache.obj `if test -f 'cache.c'; then $(CYGPATH_W) 'cache.c'; else $(CYGPATH_W) '$(srcdir)/cache.c'; fi` + +ss_server-acl.o: acl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-acl.o -MD -MP -MF $(DEPDIR)/ss_server-acl.Tpo -c -o ss_server-acl.o `test -f 'acl.c' || echo '$(srcdir)/'`acl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-acl.Tpo $(DEPDIR)/ss_server-acl.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='acl.c' object='ss_server-acl.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-acl.o `test -f 'acl.c' || echo '$(srcdir)/'`acl.c + +ss_server-acl.obj: acl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-acl.obj -MD -MP -MF $(DEPDIR)/ss_server-acl.Tpo -c -o ss_server-acl.obj `if test -f 'acl.c'; then $(CYGPATH_W) 'acl.c'; else $(CYGPATH_W) '$(srcdir)/acl.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-acl.Tpo $(DEPDIR)/ss_server-acl.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='acl.c' object='ss_server-acl.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-acl.obj `if test -f 'acl.c'; then $(CYGPATH_W) 'acl.c'; else $(CYGPATH_W) '$(srcdir)/acl.c'; fi` + +ss_server-resolv.o: resolv.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-resolv.o -MD -MP -MF $(DEPDIR)/ss_server-resolv.Tpo -c -o ss_server-resolv.o `test -f 'resolv.c' || echo '$(srcdir)/'`resolv.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-resolv.Tpo $(DEPDIR)/ss_server-resolv.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='resolv.c' object='ss_server-resolv.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-resolv.o `test -f 'resolv.c' || echo '$(srcdir)/'`resolv.c + +ss_server-resolv.obj: resolv.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-resolv.obj -MD -MP -MF $(DEPDIR)/ss_server-resolv.Tpo -c -o ss_server-resolv.obj `if test -f 'resolv.c'; then $(CYGPATH_W) 'resolv.c'; else $(CYGPATH_W) '$(srcdir)/resolv.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-resolv.Tpo $(DEPDIR)/ss_server-resolv.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='resolv.c' object='ss_server-resolv.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-resolv.obj `if test -f 'resolv.c'; then $(CYGPATH_W) 'resolv.c'; else $(CYGPATH_W) '$(srcdir)/resolv.c'; fi` + +ss_server-server.o: server.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-server.o -MD -MP -MF $(DEPDIR)/ss_server-server.Tpo -c -o ss_server-server.o `test -f 'server.c' || echo '$(srcdir)/'`server.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-server.Tpo $(DEPDIR)/ss_server-server.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server.c' object='ss_server-server.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-server.o `test -f 'server.c' || echo '$(srcdir)/'`server.c + +ss_server-server.obj: server.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-server.obj -MD -MP -MF $(DEPDIR)/ss_server-server.Tpo -c -o ss_server-server.obj `if test -f 'server.c'; then $(CYGPATH_W) 'server.c'; else $(CYGPATH_W) '$(srcdir)/server.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-server.Tpo $(DEPDIR)/ss_server-server.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server.c' object='ss_server-server.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-server.obj `if test -f 'server.c'; then $(CYGPATH_W) 'server.c'; else $(CYGPATH_W) '$(srcdir)/server.c'; fi` + +ss_server-http.o: http.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-http.o -MD -MP -MF $(DEPDIR)/ss_server-http.Tpo -c -o ss_server-http.o `test -f 'http.c' || echo '$(srcdir)/'`http.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-http.Tpo $(DEPDIR)/ss_server-http.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='http.c' object='ss_server-http.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-http.o `test -f 'http.c' || echo '$(srcdir)/'`http.c + +ss_server-http.obj: http.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-http.obj -MD -MP -MF $(DEPDIR)/ss_server-http.Tpo -c -o ss_server-http.obj `if test -f 'http.c'; then $(CYGPATH_W) 'http.c'; else $(CYGPATH_W) '$(srcdir)/http.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-http.Tpo $(DEPDIR)/ss_server-http.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='http.c' object='ss_server-http.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-http.obj `if test -f 'http.c'; then $(CYGPATH_W) 'http.c'; else $(CYGPATH_W) '$(srcdir)/http.c'; fi` + +ss_server-tls.o: tls.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-tls.o -MD -MP -MF $(DEPDIR)/ss_server-tls.Tpo -c -o ss_server-tls.o `test -f 'tls.c' || echo '$(srcdir)/'`tls.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-tls.Tpo $(DEPDIR)/ss_server-tls.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tls.c' object='ss_server-tls.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-tls.o `test -f 'tls.c' || echo '$(srcdir)/'`tls.c + +ss_server-tls.obj: tls.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-tls.obj -MD -MP -MF $(DEPDIR)/ss_server-tls.Tpo -c -o ss_server-tls.obj `if test -f 'tls.c'; then $(CYGPATH_W) 'tls.c'; else $(CYGPATH_W) '$(srcdir)/tls.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-tls.Tpo $(DEPDIR)/ss_server-tls.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tls.c' object='ss_server-tls.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-tls.obj `if test -f 'tls.c'; then $(CYGPATH_W) 'tls.c'; else $(CYGPATH_W) '$(srcdir)/tls.c'; fi` + +ss_server-rule.o: rule.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-rule.o -MD -MP -MF $(DEPDIR)/ss_server-rule.Tpo -c -o ss_server-rule.o `test -f 'rule.c' || echo '$(srcdir)/'`rule.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-rule.Tpo $(DEPDIR)/ss_server-rule.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rule.c' object='ss_server-rule.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-rule.o `test -f 'rule.c' || echo '$(srcdir)/'`rule.c + +ss_server-rule.obj: rule.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-rule.obj -MD -MP -MF $(DEPDIR)/ss_server-rule.Tpo -c -o ss_server-rule.obj `if test -f 'rule.c'; then $(CYGPATH_W) 'rule.c'; else $(CYGPATH_W) '$(srcdir)/rule.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-rule.Tpo $(DEPDIR)/ss_server-rule.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rule.c' object='ss_server-rule.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-rule.obj `if test -f 'rule.c'; then $(CYGPATH_W) 'rule.c'; else $(CYGPATH_W) '$(srcdir)/rule.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ + clean-binPROGRAMS clean-generic clean-libtool cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-binPROGRAMS + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/shadowsocksr-libev/src/server/README.md b/shadowsocksr-libev/src/server/README.md new file mode 100644 index 0000000..ef6a20e --- /dev/null +++ b/shadowsocksr-libev/src/server/README.md @@ -0,0 +1,3 @@ +# server + +`ss-server` and `ss-check` from https://github.com/ywb94/shadowsocks-libev diff --git a/shadowsocksr-libev/src/server/acl.c b/shadowsocksr-libev/src/server/acl.c new file mode 100644 index 0000000..60d4b72 --- /dev/null +++ b/shadowsocksr-libev/src/server/acl.c @@ -0,0 +1,597 @@ +/* + * acl.c - Manage the ACL (Access Control List) + * + * Copyright (C) 2013 - 2016, Max Lv + * + * This file is part of the shadowsocks-libev. + * + * shadowsocks-libev is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * shadowsocks-libev 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with shadowsocks-libev; see the file COPYING. If not, see + * . + */ + +#include +#include + +#include "rule.h" +#include "utils.h" +#include "cache.h" +#include "acl.h" + +static struct ip_set white_list_ipv4; +static struct ip_set white_list_ipv6; + +static struct ip_set black_list_ipv4; +static struct ip_set black_list_ipv6; + +static struct cork_dllist black_list_rules; +static struct cork_dllist white_list_rules; + +static int acl_mode = BLACK_LIST; + +static struct cache *block_list; + +static struct ip_set outbound_block_list_ipv4; +static struct ip_set outbound_block_list_ipv6; +static struct cork_dllist outbound_block_list_rules; + +#ifdef __linux__ + +#include +#include + +#define NO_FIREWALL_MODE 0 +#define IPTABLES_MODE 1 +#define FIREWALLD_MODE 2 + +static FILE *shell_stdin; +static int mode = NO_FIREWALL_MODE; + +static char chain_name[64]; +static char *iptables_init_chain = + "iptables -N %s; iptables -F %s; iptables -A OUTPUT -p tcp --tcp-flags RST RST -j %s"; +static char *iptables_remove_chain = + "iptables -D OUTPUT -p tcp --tcp-flags RST RST -j %s; iptables -F %s; iptables -X %s"; +static char *iptables_add_rule = "iptables -A %s -d %s -j DROP"; +static char *iptables_remove_rule = "iptables -D %s -d %s -j DROP"; + +static char *ip6tables_init_chain = + "ip6tables -N %s; ip6tables -F %s; ip6tables -A OUTPUT -p tcp --tcp-flags RST RST -j %s"; +static char *ip6tables_remove_chain = + "ip6tables -D OUTPUT -p tcp --tcp-flags RST RST -j %s; ip6tables -F %s; ip6tables -X %s"; +static char *ip6tables_add_rule = "ip6tables -A %s -d %s -j DROP"; +static char *ip6tables_remove_rule = "ip6tables -D %s -d %s -j DROP"; + +static char *firewalld_init_chain = + "firewall-cmd --direct --add-chain ipv4 filter %s; \ + firewall-cmd --direct --passthrough ipv4 -F %s; \ + firewall-cmd --direct --passthrough ipv4 -A OUTPUT -p tcp --tcp-flags RST RST -j %s"; +static char *firewalld_remove_chain = + "firewall-cmd --direct --passthrough ipv4 -D OUTPUT -p tcp --tcp-flags RST RST -j %s; \ + firewall-cmd --direct --passthrough ipv4 -F %s; \ + firewall-cmd --direct --remove-chain ipv4 filter %s"; +static char *firewalld_add_rule = "firewall-cmd --direct --passthrough ipv4 -A %s -d %s -j DROP"; +static char *firewalld_remove_rule = "firewall-cmd --direct --passthrough ipv4 -D %s -d %s -j DROP"; + +static char *firewalld6_init_chain = + "firewall-cmd --direct --add-chain ipv6 filter %s; \ + firewall-cmd --direct --passthrough ipv6 -F %s; \ + firewall-cmd --direct --passthrough ipv6 -A OUTPUT -p tcp --tcp-flags RST RST -j %s"; +static char *firewalld6_remove_chain = + "firewall-cmd --direct --passthrough ipv6 -D OUTPUT -p tcp --tcp-flags RST RST -j %s; \ + firewall-cmd --direct --passthrough ipv6 -F %s; \ + firewall-cmd --direct --remove-chain ipv6 filter %s"; +static char *firewalld6_add_rule = "firewall-cmd --direct --passthrough ipv6 -A %s -d %s -j DROP"; +static char *firewalld6_remove_rule = "firewall-cmd --direct --passthrough ipv6 -D %s -d %s -j DROP"; + +static int +run_cmd(const char *cmd) +{ + int ret = 0; + char cmdstring[256]; + + sprintf(cmdstring, "%s\n", cmd); + size_t len = strlen(cmdstring); + + if (shell_stdin != NULL) { + ret = fwrite(cmdstring, 1, len, shell_stdin); + fflush(shell_stdin); + } + + return ret == len; +} + +static int +init_firewall() +{ + int ret = 0; + char cli[256]; + FILE *fp; + + if (getuid() != 0) + return -1; + + sprintf(cli, "firewall-cmd --version 2>&1"); + fp = popen(cli, "r"); + + if (fp == NULL) + return -1; + + if (pclose(fp) == 0) { + mode = FIREWALLD_MODE; + } else { + /* Check whether we have permission to operate iptables. + * Note that checking `iptables --version` is insufficient: + * eg, running within a child user namespace. + */ + sprintf(cli, "iptables -L 2>&1"); + fp = popen(cli, "r"); + if (fp == NULL) + return -1; + if (pclose(fp) == 0) + mode = IPTABLES_MODE; + } + + sprintf(chain_name, "SHADOWSOCKS_LIBEV_%d", getpid()); + + if (mode == FIREWALLD_MODE) { + sprintf(cli, firewalld6_init_chain, chain_name, chain_name, chain_name); + ret |= system(cli); + sprintf(cli, firewalld_init_chain, chain_name, chain_name, chain_name); + ret |= system(cli); + } else if (mode == IPTABLES_MODE) { + sprintf(cli, ip6tables_init_chain, chain_name, chain_name, chain_name); + ret |= system(cli); + sprintf(cli, iptables_init_chain, chain_name, chain_name, chain_name); + ret |= system(cli); + } + + shell_stdin = popen("/bin/sh", "w"); + + return ret; +} + +static int +reset_firewall() +{ + int ret = 0; + char cli[256]; + + if (getuid() != 0) + return -1; + + if (mode == IPTABLES_MODE) { + sprintf(cli, ip6tables_remove_chain, chain_name, chain_name, chain_name); + ret |= system(cli); + sprintf(cli, iptables_remove_chain, chain_name, chain_name, chain_name); + ret |= system(cli); + } else if (mode == FIREWALLD_MODE) { + sprintf(cli, firewalld6_remove_chain, chain_name, chain_name, chain_name); + ret |= system(cli); + sprintf(cli, firewalld_remove_chain, chain_name, chain_name, chain_name); + ret |= system(cli); + } + + if (shell_stdin != NULL) { + run_cmd("exit 0"); + pclose(shell_stdin); + } + + return ret; +} + +static int +set_firewall_rule(char *addr, int add) +{ + char cli[256]; + struct cork_ip ip; + + if (getuid() != 0) + return -1; + + if (cork_ip_init(&ip, addr)) + return -1; + + if (add) { + if (mode == IPTABLES_MODE) + sprintf(cli, ip.version == 4 ? iptables_add_rule : ip6tables_add_rule, + chain_name, addr); + else if (mode == FIREWALLD_MODE) + sprintf(cli, ip.version == 4 ? firewalld_add_rule : firewalld6_add_rule, + chain_name, addr); + return run_cmd(cli); + } else { + if (mode == IPTABLES_MODE) + sprintf(cli, ip.version == 4 ? iptables_remove_rule : ip6tables_remove_rule, + chain_name, addr); + else if (mode == FIREWALLD_MODE) + sprintf(cli, ip.version == 4 ? firewalld_remove_rule : firewalld6_remove_rule, + chain_name, addr); + return run_cmd(cli); + } + + return 0; +} + +static void +free_firewall_rule(void *key, void *element) +{ + if (key == NULL) + return; + char *addr = (char *)key; + set_firewall_rule(addr, 0); + ss_free(element); +} + +#endif + +void +init_block_list(int firewall) +{ + // Initialize cache +#ifdef __linux__ + if (firewall) + init_firewall(); + else + mode = NO_FIREWALL_MODE; + cache_create(&block_list, 256, free_firewall_rule); +#else + cache_create(&block_list, 256, NULL); +#endif +} + +void +free_block_list() +{ +#ifdef __linux__ + if (mode != NO_FIREWALL_MODE) + reset_firewall(); +#endif + cache_clear(block_list, 0); // Remove all items +} + +int +remove_from_block_list(char *addr) +{ + size_t addr_len = strlen(addr); + return cache_remove(block_list, addr, addr_len); +} + +void +clear_block_list() +{ + cache_clear(block_list, 3600); // Clear items older than 1 hour +} + +int +check_block_list(char *addr) +{ + size_t addr_len = strlen(addr); + + if (cache_key_exist(block_list, addr, addr_len)) { + int *count = NULL; + cache_lookup(block_list, addr, addr_len, &count); + + if (count != NULL && *count > MAX_TRIES) + return 1; + } + + return 0; +} + +int +update_block_list(char *addr, int err_level) +{ + size_t addr_len = strlen(addr); + + if (cache_key_exist(block_list, addr, addr_len)) { + int *count = NULL; + cache_lookup(block_list, addr, addr_len, &count); + if (count != NULL) { + if (*count > MAX_TRIES) + return 1; + (*count) += err_level; + } + } else if (err_level > 0) { + int *count = (int *)ss_malloc(sizeof(int)); + *count = 1; + cache_insert(block_list, addr, addr_len, count); +#ifdef __linux__ + if (mode != NO_FIREWALL_MODE) + set_firewall_rule(addr, 1); +#endif + } + + return 0; +} + +static void +parse_addr_cidr(const char *str, char *host, int *cidr) +{ + int ret = -1, n = 0; + char *pch; + + pch = strchr(str, '/'); + while (pch != NULL) { + n++; + ret = pch - str; + pch = strchr(pch + 1, '/'); + } + if (ret == -1) { + strcpy(host, str); + *cidr = -1; + } else { + memcpy(host, str, ret); + host[ret] = '\0'; + *cidr = atoi(str + ret + 1); + } +} + +char * +trimwhitespace(char *str) +{ + char *end; + + // Trim leading space + while (isspace(*str)) + str++; + + if (*str == 0) // All spaces? + return str; + + // Trim trailing space + end = str + strlen(str) - 1; + while (end > str && isspace(*end)) + end--; + + // Write new null terminator + *(end + 1) = 0; + + return str; +} + +int +init_acl(const char *path) +{ + // initialize ipset + ipset_init_library(); + + ipset_init(&white_list_ipv4); + ipset_init(&white_list_ipv6); + ipset_init(&black_list_ipv4); + ipset_init(&black_list_ipv6); + ipset_init(&outbound_block_list_ipv4); + ipset_init(&outbound_block_list_ipv6); + + cork_dllist_init(&black_list_rules); + cork_dllist_init(&white_list_rules); + cork_dllist_init(&outbound_block_list_rules); + + struct ip_set *list_ipv4 = &black_list_ipv4; + struct ip_set *list_ipv6 = &black_list_ipv6; + struct cork_dllist *rules = &black_list_rules; + + FILE *f = fopen(path, "r"); + if (f == NULL) { + LOGE("Invalid acl path."); + return -1; + } + + char buf[257]; + while (!feof(f)) + if (fgets(buf, 256, f)) { + // Trim the newline + int len = strlen(buf); + if (len > 0 && buf[len - 1] == '\n') { + buf[len - 1] = '\0'; + } + + char *line = trimwhitespace(buf); + + // Skip comments + if (line[0] == '#') { + continue; + } + + if (strlen(line) == 0) { + continue; + } + + if (strcmp(line, "[outbound_block_list]") == 0) { + list_ipv4 = &outbound_block_list_ipv4; + list_ipv6 = &outbound_block_list_ipv6; + rules = &outbound_block_list_rules; + continue; + } else if (strcmp(line, "[black_list]") == 0 + || strcmp(line, "[bypass_list]") == 0) { + list_ipv4 = &black_list_ipv4; + list_ipv6 = &black_list_ipv6; + rules = &black_list_rules; + continue; + } else if (strcmp(line, "[white_list]") == 0 + || strcmp(line, "[proxy_list]") == 0) { + list_ipv4 = &white_list_ipv4; + list_ipv6 = &white_list_ipv6; + rules = &white_list_rules; + continue; + } else if (strcmp(line, "[reject_all]") == 0 + || strcmp(line, "[bypass_all]") == 0) { + acl_mode = WHITE_LIST; + continue; + } else if (strcmp(line, "[accept_all]") == 0 + || strcmp(line, "[proxy_all]") == 0) { + acl_mode = BLACK_LIST; + continue; + } + + char host[257]; + int cidr; + parse_addr_cidr(line, host, &cidr); + + struct cork_ip addr; + int err = cork_ip_init(&addr, host); + if (!err) { + if (addr.version == 4) { + if (cidr >= 0) { + ipset_ipv4_add_network(list_ipv4, &(addr.ip.v4), cidr); + } else { + ipset_ipv4_add(list_ipv4, &(addr.ip.v4)); + } + } else if (addr.version == 6) { + if (cidr >= 0) { + ipset_ipv6_add_network(list_ipv6, &(addr.ip.v6), cidr); + } else { + ipset_ipv6_add(list_ipv6, &(addr.ip.v6)); + } + } + } else { + rule_t *rule = new_rule(); + accept_rule_arg(rule, line); + init_rule(rule); + add_rule(rules, rule); + } + } + + fclose(f); + + return 0; +} + +void +free_rules(struct cork_dllist *rules) +{ + struct cork_dllist_item *iter; + while ((iter = cork_dllist_head(rules)) != NULL) { + rule_t *rule = cork_container_of(iter, rule_t, entries); + remove_rule(rule); + } +} + +void +free_acl(void) +{ + ipset_done(&black_list_ipv4); + ipset_done(&black_list_ipv6); + ipset_done(&white_list_ipv4); + ipset_done(&white_list_ipv6); + + free_rules(&black_list_rules); + free_rules(&white_list_rules); +} + +int +get_acl_mode(void) +{ + return acl_mode; +} + +/* + * Return 0, if not match. + * Return 1, if match black list. + * Return -1, if match white list. + */ +int +acl_match_host(const char *host) +{ + struct cork_ip addr; + int ret = 0; + int err = cork_ip_init(&addr, host); + + if (err) { + int host_len = strlen(host); + if (lookup_rule(&black_list_rules, host, host_len) != NULL) + ret = 1; + else if (lookup_rule(&white_list_rules, host, host_len) != NULL) + ret = -1; + return ret; + } + + if (addr.version == 4) { + if (ipset_contains_ipv4(&black_list_ipv4, &(addr.ip.v4))) + ret = 1; + else if (ipset_contains_ipv4(&white_list_ipv4, &(addr.ip.v4))) + ret = -1; + } else if (addr.version == 6) { + if (ipset_contains_ipv6(&black_list_ipv6, &(addr.ip.v6))) + ret = 1; + else if (ipset_contains_ipv6(&white_list_ipv6, &(addr.ip.v6))) + ret = -1; + } + + return ret; +} + +int +acl_add_ip(const char *ip) +{ + struct cork_ip addr; + int err = cork_ip_init(&addr, ip); + if (err) { + return -1; + } + + if (addr.version == 4) { + ipset_ipv4_add(&black_list_ipv4, &(addr.ip.v4)); + } else if (addr.version == 6) { + ipset_ipv6_add(&black_list_ipv6, &(addr.ip.v6)); + } + + return 0; +} + +int +acl_remove_ip(const char *ip) +{ + struct cork_ip addr; + int err = cork_ip_init(&addr, ip); + if (err) { + return -1; + } + + if (addr.version == 4) { + ipset_ipv4_remove(&black_list_ipv4, &(addr.ip.v4)); + } else if (addr.version == 6) { + ipset_ipv6_remove(&black_list_ipv6, &(addr.ip.v6)); + } + + return 0; +} + +/* + * Return 0, if not match. + * Return 1, if match black list. + */ +int +outbound_block_match_host(const char *host) +{ + struct cork_ip addr; + int ret = 0; + int err = cork_ip_init(&addr, host); + + if (err) { + int host_len = strlen(host); + if (lookup_rule(&outbound_block_list_rules, host, host_len) != NULL) + ret = 1; + return ret; + } + + if (addr.version == 4) { + if (ipset_contains_ipv4(&outbound_block_list_ipv4, &(addr.ip.v4))) + ret = 1; + } else if (addr.version == 6) { + if (ipset_contains_ipv6(&outbound_block_list_ipv6, &(addr.ip.v6))) + ret = 1; + } + + return ret; +} diff --git a/shadowsocksr-libev/src/server/acl.h b/shadowsocksr-libev/src/server/acl.h new file mode 100644 index 0000000..d6f18b8 --- /dev/null +++ b/shadowsocksr-libev/src/server/acl.h @@ -0,0 +1,53 @@ +/* + * acl.h - Define the ACL interface + * + * Copyright (C) 2013 - 2016, Max Lv + * + * This file is part of the shadowsocks-libev. + * + * shadowsocks-libev is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * shadowsocks-libev 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with shadowsocks-libev; see the file COPYING. If not, see + * . + */ + +#ifndef _ACL_H +#define _ACL_H + +#define BLACK_LIST 0 +#define WHITE_LIST 1 + +#define MAX_TRIES 64 +#define MALICIOUS 8 +#define SUSPICIOUS 4 +#define BAD 2 +#define MALFORMED 1 + +int init_acl(const char *path); +void free_acl(void); +void clear_block_list(void); + +int acl_match_host(const char *ip); +int acl_add_ip(const char *ip); +int acl_remove_ip(const char *ip); + +int get_acl_mode(void); + +void init_block_list(int firewall); +void free_block_list(); +int check_block_list(char *addr); +int update_block_list(char *addr, int err_level); +int remove_from_block_list(char *addr); + +int outbound_block_match_host(const char *host); + +#endif // _ACL_H diff --git a/shadowsocksr-libev/src/server/auth.c b/shadowsocksr-libev/src/server/auth.c new file mode 100644 index 0000000..a36257a --- /dev/null +++ b/shadowsocksr-libev/src/server/auth.c @@ -0,0 +1,993 @@ + +#include "auth.h" + +static int auth_simple_pack_unit_size = 2000; +typedef int (*hmac_with_key_func)(char *auth, char *msg, int msg_len, uint8_t *auth_key, int key_len); +typedef int (*hash_func)(char *auth, char *msg, int msg_len); + +typedef struct auth_simple_global_data { + uint8_t local_client_id[8]; + uint32_t connection_id; +}auth_simple_global_data; + +typedef struct auth_simple_local_data { + int has_sent_header; + char * recv_buffer; + int recv_buffer_size; + uint32_t recv_id; + uint32_t pack_id; + char * salt; + uint8_t * user_key; + char uid[4]; + int user_key_len; + hmac_with_key_func hmac; + hash_func hash; + int hash_len; +}auth_simple_local_data; + +void auth_simple_local_data_init(auth_simple_local_data* local) { + local->has_sent_header = 0; + local->recv_buffer = (char*)malloc(16384); + local->recv_buffer_size = 0; + local->recv_id = 1; + local->pack_id = 1; + local->salt = ""; + local->user_key = 0; + local->user_key_len = 0; + local->hmac = 0; + local->hash = 0; + local->hash_len = 0; + local->salt = ""; +} + +void * auth_simple_init_data() { + auth_simple_global_data *global = (auth_simple_global_data*)malloc(sizeof(auth_simple_global_data)); + rand_bytes(global->local_client_id, 8); + rand_bytes((uint8_t*)&global->connection_id, 4); + global->connection_id &= 0xFFFFFF; + return global; +} + +obfs * auth_simple_new_obfs() { + obfs * self = new_obfs(); + self->l_data = malloc(sizeof(auth_simple_local_data)); + auth_simple_local_data_init((auth_simple_local_data*)self->l_data); + return self; +} + +obfs * auth_aes128_md5_new_obfs() { + obfs * self = new_obfs(); + self->l_data = malloc(sizeof(auth_simple_local_data)); + auth_simple_local_data_init((auth_simple_local_data*)self->l_data); + ((auth_simple_local_data*)self->l_data)->hmac = ss_md5_hmac_with_key; + ((auth_simple_local_data*)self->l_data)->hash = ss_md5_hash_func; + ((auth_simple_local_data*)self->l_data)->hash_len = 16; + ((auth_simple_local_data*)self->l_data)->salt = "auth_aes128_md5"; + return self; +} + +obfs * auth_aes128_sha1_new_obfs() { + obfs * self = new_obfs(); + self->l_data = malloc(sizeof(auth_simple_local_data)); + auth_simple_local_data_init((auth_simple_local_data*)self->l_data); + ((auth_simple_local_data*)self->l_data)->hmac = ss_sha1_hmac_with_key; + ((auth_simple_local_data*)self->l_data)->hash = ss_sha1_hash_func; + ((auth_simple_local_data*)self->l_data)->hash_len = 20; + ((auth_simple_local_data*)self->l_data)->salt = "auth_aes128_sha1"; + return self; +} + +void auth_simple_dispose(obfs *self) { + auth_simple_local_data *local = (auth_simple_local_data*)self->l_data; + if (local->recv_buffer != NULL) { + free(local->recv_buffer); + local->recv_buffer = NULL; + } + if (local->user_key != NULL) { + free(local->user_key); + local->user_key = NULL; + } + free(local); + self->l_data = NULL; + dispose_obfs(self); +} + +int auth_simple_pack_data(char *data, int datalength, char *outdata) { + unsigned char rand_len = (xorshift128plus() & 0xF) + 1; + int out_size = rand_len + datalength + 6; + outdata[0] = out_size >> 8; + outdata[1] = out_size; + outdata[2] = rand_len; + memmove(outdata + rand_len + 2, data, datalength); + fillcrc32((unsigned char *)outdata, out_size); + return out_size; +} + +void memintcopy_lt(void *mem, uint32_t val) { + ((uint8_t *)mem)[0] = val; + ((uint8_t *)mem)[1] = val >> 8; + ((uint8_t *)mem)[2] = val >> 16; + ((uint8_t *)mem)[3] = val >> 24; +} + +int auth_simple_pack_auth_data(auth_simple_global_data *global, char *data, int datalength, char *outdata) { + unsigned char rand_len = (xorshift128plus() & 0xF) + 1; + int out_size = rand_len + datalength + 6 + 12; + outdata[0] = out_size >> 8; + outdata[1] = out_size; + outdata[2] = rand_len; + ++global->connection_id; + if (global->connection_id > 0xFF000000) { + rand_bytes(global->local_client_id, 8); + rand_bytes((uint8_t*)&global->connection_id, 4); + global->connection_id &= 0xFFFFFF; + } + time_t t = time(NULL); + memintcopy_lt(outdata + rand_len + 2, t); + memmove(outdata + rand_len + 2 + 4, global->local_client_id, 4); + memintcopy_lt(outdata + rand_len + 2 + 8, global->connection_id); + memmove(outdata + rand_len + 2 + 12, data, datalength); + fillcrc32((unsigned char *)outdata, out_size); + return out_size; +} + +int auth_simple_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) { + char *plaindata = *pplaindata; + auth_simple_local_data *local = (auth_simple_local_data*)self->l_data; + char * out_buffer = (char*)malloc(datalength * 2 + 64); + char * buffer = out_buffer; + char * data = plaindata; + int len = datalength; + int pack_len; + if (len > 0 && local->has_sent_header == 0) { + int head_size = get_head_size(plaindata, datalength, 30); + if (head_size > datalength) + head_size = datalength; + pack_len = auth_simple_pack_auth_data((auth_simple_global_data *)self->server.g_data, data, head_size, buffer); + buffer += pack_len; + data += head_size; + len -= head_size; + local->has_sent_header = 1; + } + while ( len > auth_simple_pack_unit_size ) { + pack_len = auth_simple_pack_data(data, auth_simple_pack_unit_size, buffer); + buffer += pack_len; + data += auth_simple_pack_unit_size; + len -= auth_simple_pack_unit_size; + } + if (len > 0) { + pack_len = auth_simple_pack_data(data, len, buffer); + buffer += pack_len; + } + len = buffer - out_buffer; + if (*capacity < len) { + *pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2); + plaindata = *pplaindata; + } + memmove(plaindata, out_buffer, len); + free(out_buffer); + return len; +} + +int auth_simple_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) { + char *plaindata = *pplaindata; + auth_simple_local_data *local = (auth_simple_local_data*)self->l_data; + uint8_t * recv_buffer = (uint8_t *)local->recv_buffer; + if (local->recv_buffer_size + datalength > 16384) + return -1; + memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength); + local->recv_buffer_size += datalength; + + char * out_buffer = (char*)malloc(local->recv_buffer_size); + char * buffer = out_buffer; + while (local->recv_buffer_size > 2) { + int length = ((int)recv_buffer[0] << 8) | recv_buffer[1]; + if (length >= 8192 || length < 7) { + free(out_buffer); + local->recv_buffer_size = 0; + return -1; + } + if (length > local->recv_buffer_size) + break; + + int crc = crc32((unsigned char*)recv_buffer, length); + if (crc != -1) { + free(out_buffer); + local->recv_buffer_size = 0; + return -1; + } + int data_size = length - recv_buffer[2] - 6; + memmove(buffer, recv_buffer + 2 + recv_buffer[2], data_size); + buffer += data_size; + memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length); + } + int len = buffer - out_buffer; + if (*capacity < len) { + *pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2); + plaindata = *pplaindata; + } + memmove(plaindata, out_buffer, len); + free(out_buffer); + return len; +} + + +int auth_sha1_pack_data(char *data, int datalength, char *outdata) { + unsigned char rand_len = (xorshift128plus() & 0xF) + 1; + int out_size = rand_len + datalength + 6; + outdata[0] = out_size >> 8; + outdata[1] = out_size; + outdata[2] = rand_len; + memmove(outdata + rand_len + 2, data, datalength); + filladler32((unsigned char *)outdata, out_size); + return out_size; +} + +int auth_sha1_pack_auth_data(auth_simple_global_data *global, server_info *server, char *data, int datalength, char *outdata) { + unsigned char rand_len = (xorshift128plus() & 0x7F) + 1; + int data_offset = rand_len + 4 + 2; + int out_size = data_offset + datalength + 12 + OBFS_HMAC_SHA1_LEN; + fillcrc32to((unsigned char *)server->key, server->key_len, (unsigned char *)outdata); + outdata[4] = out_size >> 8; + outdata[5] = out_size; + outdata[6] = rand_len; + ++global->connection_id; + if (global->connection_id > 0xFF000000) { + rand_bytes(global->local_client_id, 8); + rand_bytes((uint8_t*)&global->connection_id, 4); + global->connection_id &= 0xFFFFFF; + } + time_t t = time(NULL); + memintcopy_lt(outdata + data_offset, t); + memmove(outdata + data_offset + 4, global->local_client_id, 4); + memintcopy_lt(outdata + data_offset + 8, global->connection_id); + memmove(outdata + data_offset + 12, data, datalength); + char hash[ONETIMEAUTH_BYTES * 2]; + ss_sha1_hmac(hash, outdata, out_size - OBFS_HMAC_SHA1_LEN, server->iv); + memcpy(outdata + out_size - OBFS_HMAC_SHA1_LEN, hash, OBFS_HMAC_SHA1_LEN); + return out_size; +} + +int auth_sha1_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) { + char *plaindata = *pplaindata; + auth_simple_local_data *local = (auth_simple_local_data*)self->l_data; + char * out_buffer = (char*)malloc(datalength * 2 + 256); + char * buffer = out_buffer; + char * data = plaindata; + int len = datalength; + int pack_len; + if (len > 0 && local->has_sent_header == 0) { + int head_size = get_head_size(plaindata, datalength, 30); + if (head_size > datalength) + head_size = datalength; + pack_len = auth_sha1_pack_auth_data((auth_simple_global_data *)self->server.g_data, &self->server, data, head_size, buffer); + buffer += pack_len; + data += head_size; + len -= head_size; + local->has_sent_header = 1; + } + while ( len > auth_simple_pack_unit_size ) { + pack_len = auth_sha1_pack_data(data, auth_simple_pack_unit_size, buffer); + buffer += pack_len; + data += auth_simple_pack_unit_size; + len -= auth_simple_pack_unit_size; + } + if (len > 0) { + pack_len = auth_sha1_pack_data(data, len, buffer); + buffer += pack_len; + } + len = buffer - out_buffer; + if (*capacity < len) { + *pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2); + plaindata = *pplaindata; + } + memmove(plaindata, out_buffer, len); + free(out_buffer); + return len; +} + +int auth_sha1_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) { + char *plaindata = *pplaindata; + auth_simple_local_data *local = (auth_simple_local_data*)self->l_data; + uint8_t * recv_buffer = (uint8_t *)local->recv_buffer; + if (local->recv_buffer_size + datalength > 16384) + return -1; + memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength); + local->recv_buffer_size += datalength; + + char * out_buffer = (char*)malloc(local->recv_buffer_size); + char * buffer = out_buffer; + while (local->recv_buffer_size > 2) { + int length = ((int)recv_buffer[0] << 8) | recv_buffer[1]; + if (length >= 8192 || length < 7) { + free(out_buffer); + local->recv_buffer_size = 0; + return -1; + } + if (length > local->recv_buffer_size) + break; + + if (checkadler32((unsigned char*)recv_buffer, length) == 0) { + free(out_buffer); + local->recv_buffer_size = 0; + return -1; + } + int pos = recv_buffer[2] + 2; + int data_size = length - pos - 4; + memmove(buffer, recv_buffer + pos, data_size); + buffer += data_size; + memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length); + } + int len = buffer - out_buffer; + if (*capacity < len) { + *pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2); + plaindata = *pplaindata; + } + memmove(plaindata, out_buffer, len); + free(out_buffer); + return len; +} + +int auth_sha1_v2_pack_data(char *data, int datalength, char *outdata) { + unsigned int rand_len = (datalength > 1300 ? 0 : datalength > 400 ? (xorshift128plus() & 0x7F) : (xorshift128plus() & 0x3FF)) + 1; + int out_size = rand_len + datalength + 6; + outdata[0] = out_size >> 8; + outdata[1] = out_size; + if (rand_len < 128) + { + outdata[2] = rand_len; + } + else + { + outdata[2] = 0xFF; + outdata[3] = rand_len >> 8; + outdata[4] = rand_len; + } + memmove(outdata + rand_len + 2, data, datalength); + filladler32((unsigned char *)outdata, out_size); + return out_size; +} + +int auth_sha1_v2_pack_auth_data(auth_simple_global_data *global, server_info *server, char *data, int datalength, char *outdata) { + unsigned int rand_len = (datalength > 1300 ? 0 : datalength > 400 ? (xorshift128plus() & 0x7F) : (xorshift128plus() & 0x3FF)) + 1; + int data_offset = rand_len + 4 + 2; + int out_size = data_offset + datalength + 12 + OBFS_HMAC_SHA1_LEN; + const char* salt = "auth_sha1_v2"; + int salt_len = strlen(salt); + unsigned char *crc_salt = (unsigned char*)malloc(salt_len + server->key_len); + memcpy(crc_salt, salt, salt_len); + memcpy(crc_salt + salt_len, server->key, server->key_len); + fillcrc32to(crc_salt, salt_len + server->key_len, (unsigned char *)outdata); + free(crc_salt); + outdata[4] = out_size >> 8; + outdata[5] = out_size; + if (rand_len < 128) + { + outdata[6] = rand_len; + } + else + { + outdata[6] = 0xFF; + outdata[7] = rand_len >> 8; + outdata[8] = rand_len; + } + ++global->connection_id; + if (global->connection_id > 0xFF000000) { + rand_bytes(global->local_client_id, 8); + rand_bytes((uint8_t*)&global->connection_id, 4); + global->connection_id &= 0xFFFFFF; + } + memmove(outdata + data_offset, global->local_client_id, 8); + memintcopy_lt(outdata + data_offset + 8, global->connection_id); + memmove(outdata + data_offset + 12, data, datalength); + char hash[ONETIMEAUTH_BYTES * 2]; + ss_sha1_hmac(hash, outdata, out_size - OBFS_HMAC_SHA1_LEN, server->iv); + memcpy(outdata + out_size - OBFS_HMAC_SHA1_LEN, hash, OBFS_HMAC_SHA1_LEN); + return out_size; +} + +int auth_sha1_v2_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) { + char *plaindata = *pplaindata; + auth_simple_local_data *local = (auth_simple_local_data*)self->l_data; + char * out_buffer = (char*)malloc(datalength * 2 + 4096); + char * buffer = out_buffer; + char * data = plaindata; + int len = datalength; + int pack_len; + if (len > 0 && local->has_sent_header == 0) { + int head_size = get_head_size(plaindata, datalength, 30); + if (head_size > datalength) + head_size = datalength; + pack_len = auth_sha1_v2_pack_auth_data((auth_simple_global_data *)self->server.g_data, &self->server, data, head_size, buffer); + buffer += pack_len; + data += head_size; + len -= head_size; + local->has_sent_header = 1; + } + while ( len > auth_simple_pack_unit_size ) { + pack_len = auth_sha1_v2_pack_data(data, auth_simple_pack_unit_size, buffer); + buffer += pack_len; + data += auth_simple_pack_unit_size; + len -= auth_simple_pack_unit_size; + } + if (len > 0) { + pack_len = auth_sha1_v2_pack_data(data, len, buffer); + buffer += pack_len; + } + len = buffer - out_buffer; + if (*capacity < len) { + *pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2); + plaindata = *pplaindata; + } + memmove(plaindata, out_buffer, len); + free(out_buffer); + return len; +} + +int auth_sha1_v2_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) { + char *plaindata = *pplaindata; + auth_simple_local_data *local = (auth_simple_local_data*)self->l_data; + uint8_t * recv_buffer = (uint8_t *)local->recv_buffer; + if (local->recv_buffer_size + datalength > 16384) + return -1; + memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength); + local->recv_buffer_size += datalength; + + char * out_buffer = (char*)malloc(local->recv_buffer_size); + char * buffer = out_buffer; + char error = 0; + while (local->recv_buffer_size > 2) { + int length = ((int)recv_buffer[0] << 8) | recv_buffer[1]; + if (length >= 8192 || length < 7) { + local->recv_buffer_size = 0; + error = 1; + break; + } + if (length > local->recv_buffer_size) + break; + + if (checkadler32((unsigned char*)recv_buffer, length) == 0) { + local->recv_buffer_size = 0; + error = 1; + break; + } + int pos = recv_buffer[2]; + if (pos < 255) + { + pos += 2; + } + else + { + pos = ((recv_buffer[3] << 8) | recv_buffer[4]) + 2; + } + int data_size = length - pos - 4; + memmove(buffer, recv_buffer + pos, data_size); + buffer += data_size; + memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length); + } + int len; + if (error == 0) { + len = buffer - out_buffer; + if (*capacity < len) { + *pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2); + plaindata = *pplaindata; + } + memmove(plaindata, out_buffer, len); + } else { + len = -1; + } + free(out_buffer); + return len; +} + +int auth_sha1_v4_pack_data(char *data, int datalength, char *outdata) { + unsigned int rand_len = (datalength > 1300 ? 0 : datalength > 400 ? (xorshift128plus() & 0x7F) : (xorshift128plus() & 0x3FF)) + 1; + int out_size = rand_len + datalength + 8; + outdata[0] = out_size >> 8; + outdata[1] = out_size; + uint32_t crc_val = crc32((unsigned char*)outdata, 2); + outdata[2] = crc_val; + outdata[3] = crc_val >> 8; + if (rand_len < 128) + { + outdata[4] = rand_len; + } + else + { + outdata[4] = 0xFF; + outdata[5] = rand_len >> 8; + outdata[6] = rand_len; + } + memmove(outdata + rand_len + 4, data, datalength); + filladler32((unsigned char *)outdata, out_size); + return out_size; +} + +int auth_sha1_v4_pack_auth_data(auth_simple_global_data *global, server_info *server, char *data, int datalength, char *outdata) { + unsigned int rand_len = (datalength > 1300 ? 0 : datalength > 400 ? (xorshift128plus() & 0x7F) : (xorshift128plus() & 0x3FF)) + 1; + int data_offset = rand_len + 4 + 2; + int out_size = data_offset + datalength + 12 + OBFS_HMAC_SHA1_LEN; + const char* salt = "auth_sha1_v4"; + int salt_len = strlen(salt); + unsigned char *crc_salt = (unsigned char*)malloc(salt_len + server->key_len + 2); + crc_salt[0] = outdata[0] = out_size >> 8; + crc_salt[1] = outdata[1] = out_size; + + memcpy(crc_salt + 2, salt, salt_len); + memcpy(crc_salt + salt_len + 2, server->key, server->key_len); + fillcrc32to(crc_salt, salt_len + server->key_len + 2, (unsigned char *)outdata + 2); + free(crc_salt); + if (rand_len < 128) + { + outdata[6] = rand_len; + } + else + { + outdata[6] = 0xFF; + outdata[7] = rand_len >> 8; + outdata[8] = rand_len; + } + ++global->connection_id; + if (global->connection_id > 0xFF000000) { + rand_bytes(global->local_client_id, 8); + rand_bytes((uint8_t*)&global->connection_id, 4); + global->connection_id &= 0xFFFFFF; + } + time_t t = time(NULL); + memintcopy_lt(outdata + data_offset, t); + memmove(outdata + data_offset + 4, global->local_client_id, 4); + memintcopy_lt(outdata + data_offset + 8, global->connection_id); + memmove(outdata + data_offset + 12, data, datalength); + char hash[ONETIMEAUTH_BYTES * 2]; + ss_sha1_hmac(hash, outdata, out_size - OBFS_HMAC_SHA1_LEN, server->iv); + memcpy(outdata + out_size - OBFS_HMAC_SHA1_LEN, hash, OBFS_HMAC_SHA1_LEN); + return out_size; +} + +int auth_sha1_v4_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) { + char *plaindata = *pplaindata; + auth_simple_local_data *local = (auth_simple_local_data*)self->l_data; + char * out_buffer = (char*)malloc(datalength * 2 + 4096); + char * buffer = out_buffer; + char * data = plaindata; + int len = datalength; + int pack_len; + if (len > 0 && local->has_sent_header == 0) { + int head_size = get_head_size(plaindata, datalength, 30); + if (head_size > datalength) + head_size = datalength; + pack_len = auth_sha1_v4_pack_auth_data((auth_simple_global_data *)self->server.g_data, &self->server, data, head_size, buffer); + buffer += pack_len; + data += head_size; + len -= head_size; + local->has_sent_header = 1; + } + while ( len > auth_simple_pack_unit_size ) { + pack_len = auth_sha1_v4_pack_data(data, auth_simple_pack_unit_size, buffer); + buffer += pack_len; + data += auth_simple_pack_unit_size; + len -= auth_simple_pack_unit_size; + } + if (len > 0) { + pack_len = auth_sha1_v4_pack_data(data, len, buffer); + buffer += pack_len; + } + len = buffer - out_buffer; + if (*capacity < len) { + *pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2); + plaindata = *pplaindata; + } + memmove(plaindata, out_buffer, len); + free(out_buffer); + return len; +} + +int auth_sha1_v4_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) { + char *plaindata = *pplaindata; + auth_simple_local_data *local = (auth_simple_local_data*)self->l_data; + uint8_t * recv_buffer = (uint8_t *)local->recv_buffer; + if (local->recv_buffer_size + datalength > 16384) + return -1; + memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength); + local->recv_buffer_size += datalength; + + char * out_buffer = (char*)malloc(local->recv_buffer_size); + char * buffer = out_buffer; + char error = 0; + while (local->recv_buffer_size > 4) { + uint32_t crc_val = crc32((unsigned char*)recv_buffer, 2); + if ((((uint32_t)recv_buffer[3] << 8) | recv_buffer[2]) != (crc_val & 0xffff)) { + local->recv_buffer_size = 0; + error = 1; + break; + } + int length = ((int)recv_buffer[0] << 8) | recv_buffer[1]; + if (length >= 8192 || length < 7) { + local->recv_buffer_size = 0; + error = 1; + break; + } + if (length > local->recv_buffer_size) + break; + + if (checkadler32((unsigned char*)recv_buffer, length) == 0) { + local->recv_buffer_size = 0; + error = 1; + break; + } + int pos = recv_buffer[4]; + if (pos < 255) + { + pos += 4; + } + else + { + pos = (((int)recv_buffer[5] << 8) | recv_buffer[6]) + 4; + } + int data_size = length - pos - 4; + memmove(buffer, recv_buffer + pos, data_size); + buffer += data_size; + memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length); + } + int len; + if (error == 0) { + len = buffer - out_buffer; + if (*capacity < len) { + *pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2); + plaindata = *pplaindata; + } + memmove(plaindata, out_buffer, len); + } else { + len = -1; + } + free(out_buffer); + return len; +} + + +int auth_aes128_sha1_pack_data(char *data, int datalength, char *outdata, auth_simple_local_data *local, server_info *server) { + unsigned int rand_len = (datalength > 1200 ? 0 : local->pack_id > 4 ? (xorshift128plus() & 0x20) : datalength > 900 ? (xorshift128plus() & 0x80) : (xorshift128plus() & 0x200)) + 1; + int out_size = rand_len + datalength + 8; + memcpy(outdata + rand_len + 4, data, datalength); + outdata[0] = out_size; + outdata[1] = out_size >> 8; + uint8_t key_len = local->user_key_len + 4; + uint8_t *key = (uint8_t*)malloc(key_len); + memcpy(key, local->user_key, local->user_key_len); + memintcopy_lt(key + key_len - 4, local->pack_id); + + { + uint8_t rnd_data[rand_len]; + rand_bytes(rnd_data, rand_len); + memcpy(outdata + 4, rnd_data, rand_len); + } + + { + char hash[20]; + local->hmac(hash, outdata, 2, key, key_len); + memcpy(outdata + 2, hash, 2); + } + + if (rand_len < 128) + { + outdata[4] = rand_len; + } + else + { + outdata[4] = 0xFF; + outdata[5] = rand_len; + outdata[6] = rand_len >> 8; + } + ++local->pack_id; + + { + char hash[20]; + local->hmac(hash, outdata, out_size - 4, key, key_len); + memcpy(outdata + out_size - 4, hash, 4); + } + free(key); + + return out_size; +} + +int auth_aes128_sha1_pack_auth_data(auth_simple_global_data *global, server_info *server, auth_simple_local_data *local, char *data, int datalength, char *outdata) { + unsigned int rand_len = (datalength > 400 ? (xorshift128plus() & 0x200) : (xorshift128plus() & 0x400)); + int data_offset = rand_len + 16 + 4 + 4 + 7; + int out_size = data_offset + datalength + 4; + + char encrypt[24]; + char encrypt_data[16]; + + uint8_t *key = (uint8_t*)malloc(server->iv_len + server->key_len); + uint8_t key_len = server->iv_len + server->key_len; + memcpy(key, server->iv, server->iv_len); + memcpy(key + server->iv_len, server->key, server->key_len); + + { + uint8_t rnd_data[rand_len]; + rand_bytes(rnd_data, rand_len); + memcpy(outdata + data_offset - rand_len, rnd_data, rand_len); + } + + ++global->connection_id; + if (global->connection_id > 0xFF000000) { + rand_bytes(global->local_client_id, 8); + rand_bytes((uint8_t*)&global->connection_id, 4); + global->connection_id &= 0xFFFFFF; + } + time_t t = time(NULL); + memintcopy_lt(encrypt, t); + memcpy(encrypt + 4, global->local_client_id, 4); + memintcopy_lt(encrypt + 8, global->connection_id); + encrypt[12] = out_size; + encrypt[13] = out_size >> 8; + encrypt[14] = rand_len; + encrypt[15] = rand_len >> 8; + + { + + if (local->user_key == NULL) { + if(server->param != NULL && server->param[0] != 0) { + char *param = server->param; + char *delim = strchr(param, ':'); + if(delim != NULL) { + char uid_str[16] = {}; + strncpy(uid_str, param, delim - param); + char key_str[128]; + strcpy(key_str, delim + 1); + long uid_long = strtol(uid_str, NULL, 10); + memintcopy_lt(local->uid, uid_long); + + char hash[21] = {0}; + local->hash(hash, key_str, strlen(key_str)); + + local->user_key_len = local->hash_len; + local->user_key = (uint8_t*)malloc(local->user_key_len); + memcpy(local->user_key, hash, local->hash_len); + } + } + if (local->user_key == NULL) { + rand_bytes((uint8_t *)local->uid, 4); + + local->user_key_len = server->key_len; + local->user_key = (uint8_t*)malloc(local->user_key_len); + memcpy(local->user_key, server->key, local->user_key_len); + } + } + + char encrypt_key_base64[256] = {0}; + unsigned char encrypt_key[local->user_key_len]; + memcpy(encrypt_key, local->user_key, local->user_key_len); + base64_encode(encrypt_key, local->user_key_len, encrypt_key_base64); + + int base64_len; + base64_len = (local->user_key_len + 2) / 3 * 4; + memcpy(encrypt_key_base64 + base64_len, local->salt, strlen(local->salt)); + + char enc_key[16]; + int enc_key_len = base64_len + strlen(local->salt); + bytes_to_key_with_size(encrypt_key_base64, enc_key_len, (uint8_t*)enc_key, 16); + ss_aes_128_cbc(encrypt, encrypt_data, enc_key); + memcpy(encrypt + 4, encrypt_data, 16); + memcpy(encrypt, local->uid, 4); + } + + { + char hash[20]; + local->hmac(hash, encrypt, 20, key, key_len); + memcpy(encrypt + 20, hash, 4); + } + + { + uint8_t rnd[1]; + rand_bytes(rnd, 1); + memcpy(outdata, rnd, 1); + char hash[20]; + local->hmac(hash, (char *)rnd, 1, key, key_len); + memcpy(outdata + 1, hash, 6); + } + + memcpy(outdata + 7, encrypt, 24); + memcpy(outdata + data_offset, data, datalength); + + { + char hash[20]; + local->hmac(hash, outdata, out_size - 4, local->user_key, local->user_key_len); + memmove(outdata + out_size - 4, hash, 4); + } + free(key); + + return out_size; +} + +int auth_aes128_sha1_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) { + char *plaindata = *pplaindata; + auth_simple_local_data *local = (auth_simple_local_data*)self->l_data; + char * out_buffer = (char*)malloc(datalength * 2 + 4096); + char * buffer = out_buffer; + char * data = plaindata; + int len = datalength; + int pack_len; + if (len > 0 && local->has_sent_header == 0) { + int head_size = 1200; + if (head_size > datalength) + head_size = datalength; + pack_len = auth_aes128_sha1_pack_auth_data((auth_simple_global_data *)self->server.g_data, &self->server, local, data, head_size, buffer); + buffer += pack_len; + data += head_size; + len -= head_size; + local->has_sent_header = 1; + } + while ( len > auth_simple_pack_unit_size ) { + pack_len = auth_aes128_sha1_pack_data(data, auth_simple_pack_unit_size, buffer, local, &self->server); + buffer += pack_len; + data += auth_simple_pack_unit_size; + len -= auth_simple_pack_unit_size; + } + if (len > 0) { + pack_len = auth_aes128_sha1_pack_data(data, len, buffer, local, &self->server); + buffer += pack_len; + } + len = buffer - out_buffer; + if (*capacity < len) { + *pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2); + plaindata = *pplaindata; + } + memmove(plaindata, out_buffer, len); + free(out_buffer); + return len; +} + +int auth_aes128_sha1_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) { + char *plaindata = *pplaindata; + auth_simple_local_data *local = (auth_simple_local_data*)self->l_data; + //server_info *server = (server_info*)&self->server; + uint8_t * recv_buffer = (uint8_t *)local->recv_buffer; + if (local->recv_buffer_size + datalength > 16384) + return -1; + memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength); + local->recv_buffer_size += datalength; + + int key_len = local->user_key_len + 4; + uint8_t *key = (uint8_t*)malloc(key_len); + memcpy(key, local->user_key, local->user_key_len); + + char * out_buffer = (char*)malloc(local->recv_buffer_size); + char * buffer = out_buffer; + char error = 0; + while (local->recv_buffer_size > 4) { + memintcopy_lt(key + key_len - 4, local->recv_id); + + { + char hash[20]; + local->hmac(hash, (char*)recv_buffer, 2, key, key_len); + + if (memcmp(hash, recv_buffer + 2, 2)) { + local->recv_buffer_size = 0; + error = 1; + break; + } + } + + int length = ((int)recv_buffer[1] << 8) + recv_buffer[0]; + if (length >= 8192 || length < 8) { + local->recv_buffer_size = 0; + error = 1; + break; + } + if (length > local->recv_buffer_size) + break; + + { + char hash[20]; + local->hmac(hash, (char *)recv_buffer, length - 4, key, key_len); + if (memcmp(hash, recv_buffer + length - 4, 4)) + { + local->recv_buffer_size = 0; + error = 1; + break; + } + } + + ++local->recv_id; + int pos = recv_buffer[4]; + if (pos < 255) + { + pos += 4; + } + else + { + pos = (((int)recv_buffer[6] << 8) | recv_buffer[5]) + 4; + } + int data_size = length - pos - 4; + memmove(buffer, recv_buffer + pos, data_size); + buffer += data_size; + memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length); + } + int len; + if (error == 0) { + len = buffer - out_buffer; + if (*capacity < len) { + *pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2); + plaindata = *pplaindata; + } + memmove(plaindata, out_buffer, len); + } else { + len = -1; + } + free(out_buffer); + free(key); + return len; +} + +int auth_aes128_sha1_client_udp_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) { + char *plaindata = *pplaindata; + auth_simple_local_data *local = (auth_simple_local_data*)self->l_data; + char * out_buffer = (char*)malloc(datalength + 8); + + if (local->user_key == NULL) { + if(self->server.param != NULL && self->server.param[0] != 0) { + char *param = self->server.param; + char *delim = strchr(param, ':'); + if(delim != NULL) { + char uid_str[16] = {}; + strncpy(uid_str, param, delim - param); + char key_str[128]; + strcpy(key_str, delim + 1); + long uid_long = strtol(uid_str, NULL, 10); + memintcopy_lt(local->uid, uid_long); + + char hash[21] = {0}; + local->hash(hash, key_str, strlen(key_str)); + + local->user_key_len = local->hash_len; + local->user_key = (uint8_t*)malloc(local->user_key_len); + memcpy(local->user_key, hash, local->hash_len); + } + } + if (local->user_key == NULL) { + rand_bytes((uint8_t *)local->uid, 4); + + local->user_key_len = self->server.key_len; + local->user_key = (uint8_t*)malloc(local->user_key_len); + memcpy(local->user_key, self->server.key, local->user_key_len); + } + } + + int outlength = datalength + 8; + memmove(out_buffer, plaindata, datalength); + memmove(out_buffer + datalength, local->uid, 4); + + { + char hash[20]; + local->hmac(hash, out_buffer, outlength - 4, local->user_key, local->user_key_len); + memmove(out_buffer + outlength - 4, hash, 4); + } + + if (*capacity < outlength) { + *pplaindata = (char*)realloc(*pplaindata, *capacity = outlength * 2); + plaindata = *pplaindata; + } + memmove(plaindata, out_buffer, outlength); + + free(out_buffer); + return outlength; +} + +int auth_aes128_sha1_client_udp_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) { + if (datalength <= 4) + return 0; + + char *plaindata = *pplaindata; + auth_simple_local_data *local = (auth_simple_local_data*)self->l_data; + + char hash[20]; + local->hmac(hash, plaindata, datalength - 4, self->server.key, self->server.key_len); + + if (memcmp(hash, plaindata + datalength - 4, 4)) + { + return 0; + } + + return datalength - 4; +} diff --git a/shadowsocksr-libev/src/server/auth.h b/shadowsocksr-libev/src/server/auth.h new file mode 100644 index 0000000..f7730df --- /dev/null +++ b/shadowsocksr-libev/src/server/auth.h @@ -0,0 +1,30 @@ +/* + * auth.h - Define shadowsocksR server's buffers and callbacks + * + * Copyright (C) 2015 - 2016, Break Wa11 + */ + +#ifndef _AUTH_H +#define _AUTH_H + +void * auth_simple_init_data(); +obfs * auth_simple_new_obfs(); +void auth_simple_dispose(obfs *self); + +int auth_simple_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); +int auth_simple_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); + + +int auth_sha1_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); +int auth_sha1_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); + +int auth_sha1_v2_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); +int auth_sha1_v2_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); + +int auth_sha1_v4_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); +int auth_sha1_v4_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); + +int auth_aes128_sha1_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); +int auth_aes128_sha1_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); + +#endif // _AUTH_H diff --git a/shadowsocksr-libev/src/server/base64.c b/shadowsocksr-libev/src/server/base64.c new file mode 100644 index 0000000..7cf9552 --- /dev/null +++ b/shadowsocksr-libev/src/server/base64.c @@ -0,0 +1,119 @@ +#include "base64.h" + +/* BASE 64 encode table */ +static const char base64en[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +#define BASE64_PAD '=' + +#define BASE64DE_FIRST '+' +#define BASE64DE_LAST 'z' + +/* ASCII order for BASE 64 decode, -1 in unused character */ +static const signed char base64de[] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + /* '+', ',', '-', '.', '/', */ + -1, -1, -1, 62, -1, -1, -1, 63, + /* '0', '1', '2', '3', '4', '5', '6', '7', */ + 52, 53, 54, 55, 56, 57, 58, 59, + /* '8', '9', ':', ';', '<', '=', '>', '?', */ + 60, 61, -1, -1, -1, -1, -1, -1, + /* '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', */ + -1, 0, 1, 2, 3, 4, 5, 6, + /* 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', */ + 7, 8, 9, 10, 11, 12, 13, 14, + /* 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', */ + 15, 16, 17, 18, 19, 20, 21, 22, + /* 'X', 'Y', 'Z', '[', '\', ']', '^', '_', */ + 23, 24, 25, -1, -1, -1, -1, -1, + /* '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', */ + -1, 26, 27, 28, 29, 30, 31, 32, + /* 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', */ + 33, 34, 35, 36, 37, 38, 39, 40, + /* 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', */ + 41, 42, 43, 44, 45, 46, 47, 48, + /* 'x', 'y', 'z', */ + 49, 50, 51, +}; + +int +base64_encode(const unsigned char *in, unsigned int inlen, char *out) +{ + unsigned int i, j; + + for (i = j = 0; i < inlen; i++) { + int s = i % 3; /* from 6/gcd(6, 8) */ + + switch (s) { + case 0: + out[j++] = base64en[(in[i] >> 2) & 0x3F]; + continue; + case 1: + out[j++] = base64en[((in[i-1] & 0x3) << 4) + ((in[i] >> 4) & 0xF)]; + continue; + case 2: + out[j++] = base64en[((in[i-1] & 0xF) << 2) + ((in[i] >> 6) & 0x3)]; + out[j++] = base64en[in[i] & 0x3F]; + } + } + + /* move back */ + i -= 1; + + /* check the last and add padding */ + if ((i % 3) == 0) { + out[j++] = base64en[(in[i] & 0x3) << 4]; + out[j++] = BASE64_PAD; + out[j++] = BASE64_PAD; + } else if ((i % 3) == 1) { + out[j++] = base64en[(in[i] & 0xF) << 2]; + out[j++] = BASE64_PAD; + } + + return BASE64_OK; +} + +int +base64_decode(const char *in, unsigned int inlen, unsigned char *out) +{ + unsigned int i, j; + + for (i = j = 0; i < inlen; i++) { + int c; + int s = i % 4; /* from 8/gcd(6, 8) */ + + if (in[i] == '=') + return BASE64_OK; + + if (in[i] < BASE64DE_FIRST || in[i] > BASE64DE_LAST || + (c = base64de[(int)in[i]]) == -1) + return BASE64_INVALID; + + switch (s) { + case 0: + out[j] = ((unsigned int)c << 2) & 0xFF; + continue; + case 1: + out[j++] += ((unsigned int)c >> 4) & 0x3; + + /* if not last char with padding */ + if (i < (inlen - 3) || in[inlen - 2] != '=') + out[j] = ((unsigned int)c & 0xF) << 4; + continue; + case 2: + out[j++] += ((unsigned int)c >> 2) & 0xF; + + /* if not last char with padding */ + if (i < (inlen - 2) || in[inlen - 1] != '=') + out[j] = ((unsigned int)c & 0x3) << 6; + continue; + case 3: + out[j++] += (unsigned char)c; + } + } + + return BASE64_OK; +} diff --git a/shadowsocksr-libev/src/server/base64.h b/shadowsocksr-libev/src/server/base64.h new file mode 100644 index 0000000..6432ba3 --- /dev/null +++ b/shadowsocksr-libev/src/server/base64.h @@ -0,0 +1,16 @@ +#ifndef __BASE64_H__ +#define __BASE64_H__ + +enum {BASE64_OK = 0, BASE64_INVALID}; + +#define BASE64_ENCODE_OUT_SIZE(s) (((s) + 2) / 3 * 4) +#define BASE64_DECODE_OUT_SIZE(s) (((s)) / 4 * 3) + +int +base64_encode(const unsigned char *in, unsigned int inlen, char *out); + +int +base64_decode(const char *in, unsigned int inlen, unsigned char *out); + + +#endif /* __BASE64_H__ */ diff --git a/shadowsocksr-libev/src/server/cache.c b/shadowsocksr-libev/src/server/cache.c new file mode 100644 index 0000000..c1a2995 --- /dev/null +++ b/shadowsocksr-libev/src/server/cache.c @@ -0,0 +1,308 @@ +/* + * cache.c - Manage the connection cache for UDPRELAY + * + * Copyright (C) 2013 - 2016, Max Lv + * + * This file is part of the shadowsocks-libev. + * + * shadowsocks-libev is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * shadowsocks-libev 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with shadowsocks-libev; see the file COPYING. If not, see + * . + */ + +/* + * Original Author: Oliver Lorenz (ol), olli@olorenz.org, https://olorenz.org + * License: This is licensed under the same terms as uthash itself + */ + +#include +#include + +#include "cache.h" +#include "utils.h" + +#ifdef __MINGW32__ +#include "win32.h" +#endif + +/** Creates a new cache object + * + * @param dst + * Where the newly allocated cache object will be stored in + * + * @param capacity + * The maximum number of elements this cache object can hold + * + * @return EINVAL if dst is NULL, ENOMEM if malloc fails, 0 otherwise + */ +int +cache_create(struct cache **dst, const size_t capacity, + void (*free_cb)(void *key, void *element)) +{ + struct cache *new = NULL; + + if (!dst) { + return EINVAL; + } + + if ((new = malloc(sizeof(*new))) == NULL) { + return ENOMEM; + } + + new->max_entries = capacity; + new->entries = NULL; + new->free_cb = free_cb; + *dst = new; + return 0; +} + +/** Frees an allocated cache object + * + * @param cache + * The cache object to free + * + * @param keep_data + * Whether to free contained data or just delete references to it + * + * @return EINVAL if cache is NULL, 0 otherwise + */ +int +cache_delete(struct cache *cache, int keep_data) +{ + struct cache_entry *entry, *tmp; + + if (!cache) { + return EINVAL; + } + + if (keep_data) { + HASH_CLEAR(hh, cache->entries); + } else { + HASH_ITER(hh, cache->entries, entry, tmp){ + HASH_DEL(cache->entries, entry); + if (entry->data != NULL) { + if (cache->free_cb) { + cache->free_cb(entry->key, entry->data); + } else { + ss_free(entry->data); + } + } + ss_free(entry->key); + ss_free(entry); + } + } + + ss_free(cache); + return 0; +} + +/** Clear old cache object + * + * @param cache + * The cache object to clear + * + * @param age + * Clear only objects older than the age (sec) + * + * @return EINVAL if cache is NULL, 0 otherwise + */ +int +cache_clear(struct cache *cache, ev_tstamp age) +{ + struct cache_entry *entry, *tmp; + + if (!cache) { + return EINVAL; + } + + ev_tstamp now = ev_time(); + + HASH_ITER(hh, cache->entries, entry, tmp){ + if (now - entry->ts > age) { + HASH_DEL(cache->entries, entry); + if (entry->data != NULL) { + if (cache->free_cb) { + cache->free_cb(entry->key, entry->data); + } else { + ss_free(entry->data); + } + } + ss_free(entry->key); + ss_free(entry); + } + } + + return 0; +} + +/** Removes a cache entry + * + * @param cache + * The cache object + * + * @param key + * The key of the entry to remove + * + * @param key_len + * The length of key + * + * @return EINVAL if cache is NULL, 0 otherwise + */ +int +cache_remove(struct cache *cache, char *key, size_t key_len) +{ + struct cache_entry *tmp; + + if (!cache || !key) { + return EINVAL; + } + + HASH_FIND(hh, cache->entries, key, key_len, tmp); + + if (tmp) { + HASH_DEL(cache->entries, tmp); + if (tmp->data != NULL) { + if (cache->free_cb) { + cache->free_cb(tmp->key, tmp->data); + } else { + ss_free(tmp->data); + } + } + ss_free(tmp->key); + ss_free(tmp); + } + + return 0; +} + +/** Checks if a given key is in the cache + * + * @param cache + * The cache object + * + * @param key + * The key to look-up + * + * @param key_len + * The length of key + * + * @param result + * Where to store the result if key is found. + * + * A warning: Even though result is just a pointer, + * you have to call this function with a **ptr, + * otherwise this will blow up in your face. + * + * @return EINVAL if cache is NULL, 0 otherwise + */ +int +cache_lookup(struct cache *cache, char *key, size_t key_len, void *result) +{ + struct cache_entry *tmp = NULL; + char **dirty_hack = result; + + if (!cache || !key || !result) { + return EINVAL; + } + + HASH_FIND(hh, cache->entries, key, key_len, tmp); + if (tmp) { + HASH_DELETE(hh, cache->entries, tmp); + tmp->ts = ev_time(); + HASH_ADD_KEYPTR(hh, cache->entries, tmp->key, key_len, tmp); + *dirty_hack = tmp->data; + } else { + *dirty_hack = result = NULL; + } + + return 0; +} + +int +cache_key_exist(struct cache *cache, char *key, size_t key_len) +{ + struct cache_entry *tmp = NULL; + + if (!cache || !key) { + return 0; + } + + HASH_FIND(hh, cache->entries, key, key_len, tmp); + if (tmp) { + HASH_DELETE(hh, cache->entries, tmp); + tmp->ts = ev_time(); + HASH_ADD_KEYPTR(hh, cache->entries, tmp->key, key_len, tmp); + return 1; + } else { + return 0; + } + + return 0; +} + +/** Inserts a given pair into the cache + * + * @param cache + * The cache object + * + * @param key + * The key that identifies + * + * @param key_len + * The length of key + * + * @param data + * Data associated with + * + * @return EINVAL if cache is NULL, ENOMEM if malloc fails, 0 otherwise + */ +int +cache_insert(struct cache *cache, char *key, size_t key_len, void *data) +{ + struct cache_entry *entry = NULL; + struct cache_entry *tmp_entry = NULL; + + if (!cache) { + return EINVAL; + } + + if ((entry = malloc(sizeof(*entry))) == NULL) { + return ENOMEM; + } + + entry->key = ss_malloc(key_len + 1); + memcpy(entry->key, key, key_len); + entry->key[key_len] = 0; + + entry->data = data; + entry->ts = ev_time(); + HASH_ADD_KEYPTR(hh, cache->entries, entry->key, key_len, entry); + + if (HASH_COUNT(cache->entries) >= cache->max_entries) { + HASH_ITER(hh, cache->entries, entry, tmp_entry){ + HASH_DELETE(hh, cache->entries, entry); + if (entry->data != NULL) { + if (cache->free_cb) { + cache->free_cb(entry->key, entry->data); + } else { + ss_free(entry->data); + } + } + ss_free(entry->key); + ss_free(entry); + break; + } + } + + return 0; +} diff --git a/shadowsocksr-libev/src/server/cache.h b/shadowsocksr-libev/src/server/cache.h new file mode 100644 index 0000000..0ec98f5 --- /dev/null +++ b/shadowsocksr-libev/src/server/cache.h @@ -0,0 +1,62 @@ +/* + * cache.h - Define the cache manager interface + * + * Copyright (C) 2013 - 2016, Max Lv + * + * This file is part of the shadowsocks-libev. + * + * shadowsocks-libev is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * shadowsocks-libev 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with shadowsocks-libev; see the file COPYING. If not, see + * . + */ + +/* + * Original Author: Oliver Lorenz (ol), olli@olorenz.org, https://olorenz.org + * License: This is licensed under the same terms as uthash itself + */ + +#ifndef _CACHE_ +#define _CACHE_ + +#include "uthash.h" +#include "ev.h" + +/** + * A cache entry + */ +struct cache_entry { + char *key; /** +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#define __DEBUG__ +#ifdef __DEBUG__ +#define DEBUG(format,...) printf("File: "__FILE__", Line: %05d: "format"/n", __LINE__, ##__VA_ARGS__) +#else +#define DEBUG(format,...) +#endif + +static sigjmp_buf jmpbuf; +static void alarm_func() +{ + siglongjmp(jmpbuf, 1); +} + +static struct hostent *timeGethostbyname(const char *domain, int timeout) +{ + struct hostent *ipHostent = NULL; + signal(SIGALRM, alarm_func); + if(sigsetjmp(jmpbuf, 1) != 0) + { + alarm(0);//timout + signal(SIGALRM, SIG_IGN); + return NULL; + } + alarm(timeout);//setting alarm + ipHostent = gethostbyname(domain); + signal(SIGALRM, SIG_IGN); + return ipHostent; +} + + +#define MY_HTTP_DEFAULT_PORT 80 +#define BUFFER_SIZE 1024 +#define HTTP_POST "POST /%s HTTP/1.1\r\nHOST: %s:%d\r\nAccept: */*\r\n"\ + "Content-Type:application/x-www-form-urlencoded\r\nContent-Length: %d\r\n\r\n%s" +#define HTTP_GET "GET /%s HTTP/1.1\r\nHOST: %s:%d\r\nAccept: */*\r\n\r\n" + +static int http_parse_url(const char *url,char *host,char *file,int *port) +{ + char *ptr1,*ptr2; + int len = 0; + if(!url || !host || !file || !port){ + return 1; + } + + ptr1 = (char *)url; + + if(!strncmp(ptr1,"http://",strlen("http://"))){ + ptr1 += strlen("http://"); + }else{ + return 1; + } + + ptr2 = strchr(ptr1,'/'); + if(ptr2){ + len = strlen(ptr1) - strlen(ptr2); + memcpy(host,ptr1,len); + host[len] = '\0'; + if(*(ptr2 + 1)){ + memcpy(file,ptr2 + 1,strlen(ptr2) - 1 ); + file[strlen(ptr2) - 1] = '\0'; + } + }else{ + memcpy(host,ptr1,strlen(ptr1)); + host[strlen(ptr1)] = '\0'; + } + //get host and ip + ptr1 = strchr(host,':'); + if(ptr1){ + *ptr1++ = '\0'; + *port = atoi(ptr1); + }else{ + *port = MY_HTTP_DEFAULT_PORT; + } + + return 0; +} + + +static int http_tcpclient_recv(int socket,char *lpbuff){ + int recvnum = 0; + + recvnum = recv(socket, lpbuff,BUFFER_SIZE*4,0); + + return recvnum; +} + +static int http_tcpclient_send(int socket,char *buff,int size){ + int sent=0,tmpres=0; + + while(sent < size){ + tmpres = send(socket,buff+sent,size-sent,0); + if(tmpres == -1){ + return 1; + } + sent += tmpres; + } + return sent; +} + + + + + +int http_get(const char *url,int socket_fd) +{ + char lpbuf[BUFFER_SIZE*4] = {'\0'}; + + char host_addr[BUFFER_SIZE] = {'\0'}; + char file[BUFFER_SIZE] = {'\0'}; + int port = 0; + + + if(!url){ + DEBUG(" failed!\n"); + return 1; + } + + if(http_parse_url(url,host_addr,file,&port)){ + DEBUG("http_parse_url failed!\n"); + return 1; + } + DEBUG("url: %s\thost_addr : %s\tfile:%s\t,%d\n",url,host_addr,file,port); + + + if(socket_fd < 0){ + DEBUG("http_tcpclient_create failed\n"); + return 1; + } + + sprintf(lpbuf,HTTP_GET,file,host_addr,port); + + if(http_tcpclient_send(socket_fd,lpbuf,strlen(lpbuf)) < 0){ + DEBUG("http_tcpclient_send failed..\n"); + return 1; + } + DEBUG("request:\n%s\n",lpbuf); + + if(http_tcpclient_recv(socket_fd,lpbuf) <= 0){ + DEBUG("http_tcpclient_recv failed\n"); + close(socket_fd); + return 1; + } + DEBUG("rec:\n%s\n",lpbuf); + close(socket_fd); + + //return http_parse_result(lpbuf); +return 0; +} + + + +int main(int argc, char *argv[]) +{ + int fd,http_flag=0,http_ret=1; + struct sockaddr_in addr; + struct hostent *host; + struct timeval timeo = {3, 0}; + socklen_t len = sizeof(timeo); + + char http_url[100]="http://"; + + + + fd = socket(AF_INET, SOCK_STREAM, 0); + if (argc >= 4) + timeo.tv_sec = atoi(argv[3]); + if (argc>=5) + http_flag=1; + + if((host=timeGethostbyname(argv[1],timeo.tv_sec)) == NULL) { + DEBUG("gethostbyname err\n"); + return 1; + } + if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeo, len) == -1) + { + + DEBUG("setsockopt send err\n"); + return 1; + } + + if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeo, len) == -1) + { + + DEBUG("setsockopt recv err\n"); + return 1; + } + + addr.sin_family = AF_INET; + addr.sin_addr = *((struct in_addr *)host->h_addr); + //addr.sin_addr.s_addr = inet_addr(argv[1]); + addr.sin_port = htons(atoi(argv[2])); +if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) + { + if (errno == EINPROGRESS) + { + DEBUG("timeout err\n"); + return 1; + } + DEBUG("connect err\n"); + return 1; + } +if(http_flag==0) +{ + close(fd); + return 0; +} +strcat(http_url,argv[1]); +http_ret=http_get(http_url,fd); +if(http_ret==1) +{ +DEBUG("recv err"); + return 1; +} +else +{ +DEBUG("recv ok"); + + return 0; +} + +} \ No newline at end of file diff --git a/shadowsocksr-libev/src/server/common.h b/shadowsocksr-libev/src/server/common.h new file mode 100644 index 0000000..000f084 --- /dev/null +++ b/shadowsocksr-libev/src/server/common.h @@ -0,0 +1,58 @@ +/* + * common.h - Provide global definitions + * + * Copyright (C) 2013 - 2016, Max Lv + * + * This file is part of the shadowsocks-libev. + * shadowsocks-libev is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * shadowsocks-libev 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with shadowsocks-libev; see the file COPYING. If not, see + * . + */ + +#ifndef _COMMON_H +#define _COMMON_H + +#define DEFAULT_CONF_PATH "/etc/shadowsocks-libev/config.json" + +#ifndef SOL_TCP +#define SOL_TCP IPPROTO_TCP +#endif + +#if defined(MODULE_TUNNEL) || defined(MODULE_REDIR) +#define MODULE_LOCAL +#endif + +int init_udprelay(const char *server_host, const char *server_port, +#ifdef MODULE_LOCAL + const struct sockaddr *remote_addr, const int remote_addr_len, +#ifdef MODULE_TUNNEL + const ss_addr_t tunnel_addr, +#endif +#endif + int mtu, int method, int auth, int timeout, const char *iface, const char *protocol, const char *protocol_param); + +void free_udprelay(void); + +#ifdef ANDROID +int protect_socket(int fd); +int send_traffic_stat(uint64_t tx, uint64_t rx); +#endif + +#define STAGE_ERROR -1 /* Error detected */ +#define STAGE_INIT 0 /* Initial stage */ +#define STAGE_HANDSHAKE 1 /* Handshake with client */ +#define STAGE_PARSE 2 /* Parse the header */ +#define STAGE_RESOLVE 4 /* Resolve the hostname */ +#define STAGE_STREAM 5 /* Stream between client and server */ + +#endif // _COMMON_H diff --git a/shadowsocksr-libev/src/server/crc32.c b/shadowsocksr-libev/src/server/crc32.c new file mode 100644 index 0000000..6d328d2 --- /dev/null +++ b/shadowsocksr-libev/src/server/crc32.c @@ -0,0 +1,97 @@ +static uint32_t crc32_table[256] = {0}; + +void init_crc32_table(void) { + uint32_t c, i, j; + if (crc32_table[0] == 0) { + for (i = 0; i < 256; i++) { + c = i; + for (j = 0; j < 8; j++) { + if (c & 1) + c = 0xedb88320L ^ (c >> 1); + else + c = c >> 1; + } + crc32_table[i] = c; + } + } +} + +uint32_t crc32(unsigned char *buffer, unsigned int size) { + uint32_t crc = 0xFFFFFFFF; + unsigned int i; + for (i = 0; i < size; i++) { + crc = crc32_table[(crc ^ buffer[i]) & 0xFF] ^ (crc >> 8); + } + return crc ^ 0xFFFFFFFF; +} + +void fillcrc32to(unsigned char *buffer, unsigned int size, unsigned char *outbuffer) { + uint32_t crc = 0xFFFFFFFF; + unsigned int i; + for (i = 0; i < size; i++) { + crc = crc32_table[(crc ^ buffer[i]) & 0xff] ^ (crc >> 8); + } + crc ^= 0xFFFFFFFF; + outbuffer[0] = crc; + outbuffer[1] = crc >> 8; + outbuffer[2] = crc >> 16; + outbuffer[3] = crc >> 24; +} + +void fillcrc32(unsigned char *buffer, unsigned int size) { + uint32_t crc = 0xFFFFFFFF; + unsigned int i; + size -= 4; + for (i = 0; i < size; i++) { + crc = crc32_table[(crc ^ buffer[i]) & 0xff] ^ (crc >> 8); + } + buffer += size; + buffer[0] = crc; + buffer[1] = crc >> 8; + buffer[2] = crc >> 16; + buffer[3] = crc >> 24; +} + +void adler32_short(unsigned char *buffer, unsigned int size, uint32_t *a, uint32_t *b) { + for (int i = 0; i < size; i++) { + *a += buffer[i]; + *b += *a; + } + *a %= 65521; + *b %= 65521; +} + +#define NMAX 5552 +uint32_t adler32(unsigned char *buffer, unsigned int size) { + uint32_t a = 1; + uint32_t b = 0; + while ( size >= NMAX ) { + adler32_short(buffer, NMAX, &a, &b); + buffer += NMAX; + size -= NMAX; + } + adler32_short(buffer, size, &a, &b); + return (b << 16) + a; +} +#undef NMAX + +void filladler32(unsigned char *buffer, unsigned int size) { + size -= 4; + uint32_t checksum = adler32(buffer, size); + buffer += size; + buffer[0] = checksum; + buffer[1] = checksum >> 8; + buffer[2] = checksum >> 16; + buffer[3] = checksum >> 24; +} + +int checkadler32(unsigned char *buffer, unsigned int size) { + size -= 4; + uint32_t checksum = adler32(buffer, size); + buffer += size; + return checksum == (((uint32_t)buffer[3] << 24) + | ((uint32_t)buffer[2] << 16) + | ((uint32_t)buffer[1] << 8) + | (uint32_t)buffer[0]); +} + diff --git a/shadowsocksr-libev/src/server/encrypt.c b/shadowsocksr-libev/src/server/encrypt.c new file mode 100644 index 0000000..37dd5cd --- /dev/null +++ b/shadowsocksr-libev/src/server/encrypt.c @@ -0,0 +1,1645 @@ +/* + * encrypt.c - Manage the global encryptor + * + * Copyright (C) 2013 - 2016, Max Lv + * + * This file is part of the shadowsocks-libev. + * + * shadowsocks-libev is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * shadowsocks-libev 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with shadowsocks-libev; see the file COPYING. If not, see + * . + */ + +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#if defined(USE_CRYPTO_OPENSSL) + +#include +#include +#include +#include + +#elif defined(USE_CRYPTO_POLARSSL) + +#include +#include +#include +#include +#include +#include +#define CIPHER_UNSUPPORTED "unsupported" + +#include +#ifdef _WIN32 +#include +#include +#else +#include +#endif + +#elif defined(USE_CRYPTO_MBEDTLS) + +#include +#include +#include +#include +#include +#define CIPHER_UNSUPPORTED "unsupported" + +#include +#ifdef _WIN32 +#include +#include +#else +#include +#endif + +#endif + +#include + +#ifndef __MINGW32__ +#include +#endif + +#include "cache.h" +#include "encrypt.h" +#include "utils.h" + +#define OFFSET_ROL(p, o) ((uint64_t)(*(p + o)) << (8 * o)) + +static uint8_t *enc_table; +static uint8_t *dec_table; +static uint8_t enc_key[MAX_KEY_LENGTH]; +static int enc_key_len; +static int enc_iv_len; +static int enc_method; + +static struct cache *iv_cache; + +#ifdef DEBUG +static void +dump(char *tag, char *text, int len) +{ + int i; + printf("%s: ", tag); + for (i = 0; i < len; i++) + printf("0x%02x ", (uint8_t)text[i]); + printf("\n"); +} + +#endif + +static const char *supported_ciphers[CIPHER_NUM] = { + "table", + "rc4", + "rc4-md5-6", + "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" +}; + +#ifdef USE_CRYPTO_POLARSSL +static const char *supported_ciphers_polarssl[CIPHER_NUM] = { + "table", + "ARC4-128", + "ARC4-128", + "ARC4-128", + "AES-128-CFB128", + "AES-192-CFB128", + "AES-256-CFB128", + "AES-128-CTR", + "AES-192-CTR", + "AES-256-CTR", + "BLOWFISH-CFB64", + "CAMELLIA-128-CFB128", + "CAMELLIA-192-CFB128", + "CAMELLIA-256-CFB128", + CIPHER_UNSUPPORTED, + CIPHER_UNSUPPORTED, + CIPHER_UNSUPPORTED, + CIPHER_UNSUPPORTED, + CIPHER_UNSUPPORTED, + "salsa20", + "chacha20", + "chacha20-ietf" +}; +#endif + +#ifdef USE_CRYPTO_MBEDTLS +static const char *supported_ciphers_mbedtls[CIPHER_NUM] = { + "table", + "ARC4-128", + "ARC4-128", + "ARC4-128", + "AES-128-CFB128", + "AES-192-CFB128", + "AES-256-CFB128", + "AES-128-CTR", + "AES-192-CTR", + "AES-256-CTR", + "BLOWFISH-CFB64", + "CAMELLIA-128-CFB128", + "CAMELLIA-192-CFB128", + "CAMELLIA-256-CFB128", + CIPHER_UNSUPPORTED, + CIPHER_UNSUPPORTED, + CIPHER_UNSUPPORTED, + CIPHER_UNSUPPORTED, + CIPHER_UNSUPPORTED, + "salsa20", + "chacha20", + "chacha20-ietf" +}; +#endif + +#ifdef USE_CRYPTO_APPLECC +static const CCAlgorithm supported_ciphers_applecc[CIPHER_NUM] = { + kCCAlgorithmInvalid, + kCCAlgorithmRC4, + kCCAlgorithmRC4, + kCCAlgorithmRC4, + kCCAlgorithmAES, + kCCAlgorithmAES, + kCCAlgorithmAES, + kCCAlgorithmAES, + kCCAlgorithmAES, + kCCAlgorithmAES, + kCCAlgorithmBlowfish, + kCCAlgorithmInvalid, + kCCAlgorithmInvalid, + kCCAlgorithmInvalid, + kCCAlgorithmCAST, + kCCAlgorithmDES, + kCCAlgorithmInvalid, + kCCAlgorithmRC2, + kCCAlgorithmInvalid, + kCCAlgorithmInvalid, + kCCAlgorithmInvalid, + kCCAlgorithmInvalid +}; + +static const CCMode supported_modes_applecc[CIPHER_NUM] = { + kCCAlgorithmInvalid, + kCCAlgorithmInvalid, + kCCModeRC4, + kCCModeRC4, + kCCModeCFB, + kCCModeCFB, + kCCModeCFB, + kCCModeCTR, + kCCModeCTR, + kCCModeCTR, + kCCModeCFB, + kCCAlgorithmInvalid, + kCCAlgorithmInvalid, + kCCAlgorithmInvalid, + kCCModeCFB, + kCCModeCFB, + kCCModeCFB, + kCCModeCFB, + kCCAlgorithmInvalid, + kCCAlgorithmInvalid, + kCCAlgorithmInvalid, + kCCAlgorithmInvalid +}; +#endif + +static const int supported_ciphers_iv_size[CIPHER_NUM] = { + 0, 0, 6, 16, 16, 16, 16, 16, 16, 16, 8, 16, 16, 16, 8, 8, 8, 8, 16, 8, 8, 12 +}; + +static const int supported_ciphers_key_size[CIPHER_NUM] = { + 0, 16, 16, 16, 16, 24, 32, 16, 24, 32, 16, 16, 24, 32, 16, 8, 16, 16, 16, 32, 32, 32 +}; + +static int +safe_memcmp(const void *s1, const void *s2, size_t n) +{ + const unsigned char *_s1 = (const unsigned char *)s1; + const unsigned char *_s2 = (const unsigned char *)s2; + int ret = 0; + size_t i; + for (i = 0; i < n; i++) + ret |= _s1[i] ^ _s2[i]; + return !!ret; +} + +int +balloc(buffer_t *ptr, size_t capacity) +{ + sodium_memzero(ptr, sizeof(buffer_t)); + ptr->array = ss_malloc(capacity); + ptr->capacity = capacity; + return capacity; +} + +int +brealloc(buffer_t *ptr, size_t len, size_t capacity) +{ + if (ptr == NULL) + return -1; + size_t real_capacity = max(len, capacity); + if (ptr->capacity < real_capacity) { + ptr->array = ss_realloc(ptr->array, real_capacity); + ptr->capacity = real_capacity; + } + return real_capacity; +} + +void +bfree(buffer_t *ptr) +{ + if (ptr == NULL) + return; + ptr->idx = 0; + ptr->len = 0; + ptr->capacity = 0; + if (ptr->array != NULL) { + ss_free(ptr->array); + } +} + +static int +crypto_stream_xor_ic(uint8_t *c, const uint8_t *m, uint64_t mlen, + const uint8_t *n, uint64_t ic, const uint8_t *k, + int method) +{ + switch (method) { + case SALSA20: + return crypto_stream_salsa20_xor_ic(c, m, mlen, n, ic, k); + case CHACHA20: + return crypto_stream_chacha20_xor_ic(c, m, mlen, n, ic, k); + case CHACHA20IETF: + return crypto_stream_chacha20_ietf_xor_ic(c, m, mlen, n, (uint32_t)ic, k); + } + // always return 0 + return 0; +} + +static int +random_compare(const void *_x, const void *_y, uint32_t i, + uint64_t a) +{ + uint8_t x = *((uint8_t *)_x); + uint8_t y = *((uint8_t *)_y); + return a % (x + i) - a % (y + i); +} + +static void +merge(uint8_t *left, int llength, uint8_t *right, + int rlength, uint32_t salt, uint64_t key) +{ + uint8_t *ltmp = (uint8_t *)malloc(llength * sizeof(uint8_t)); + uint8_t *rtmp = (uint8_t *)malloc(rlength * sizeof(uint8_t)); + + uint8_t *ll = ltmp; + uint8_t *rr = rtmp; + + uint8_t *result = left; + + memcpy(ltmp, left, llength * sizeof(uint8_t)); + memcpy(rtmp, right, rlength * sizeof(uint8_t)); + + while (llength > 0 && rlength > 0) { + if (random_compare(ll, rr, salt, key) <= 0) { + *result = *ll; + ++ll; + --llength; + } else { + *result = *rr; + ++rr; + --rlength; + } + ++result; + } + + if (llength > 0) { + while (llength > 0) { + *result = *ll; + ++result; + ++ll; + --llength; + } + } else { + while (rlength > 0) { + *result = *rr; + ++result; + ++rr; + --rlength; + } + } + + ss_free(ltmp); + ss_free(rtmp); +} + +static void +merge_sort(uint8_t array[], int length, + uint32_t salt, uint64_t key) +{ + uint8_t middle; + uint8_t *left, *right; + int llength; + + if (length <= 1) { + return; + } + + middle = length / 2; + + llength = length - middle; + + left = array; + right = array + llength; + + merge_sort(left, llength, salt, key); + merge_sort(right, middle, salt, key); + merge(left, llength, right, middle, salt, key); +} + +int +enc_get_iv_len() +{ + return enc_iv_len; +} + +uint8_t* enc_get_key() +{ + return enc_key; +} + +int enc_get_key_len() +{ + return enc_key_len; +} + +unsigned char *enc_md5(const unsigned char *d, size_t n, unsigned char *md) +{ +#if defined(USE_CRYPTO_OPENSSL) + return MD5(d, n, md); +#elif defined(USE_CRYPTO_POLARSSL) + static unsigned char m[16]; + if (md == NULL) { + md = m; + } + md5(d, n, md); + return md; +#elif defined(USE_CRYPTO_MBEDTLS) + static unsigned char m[16]; + if (md == NULL) { + md = m; + } + mbedtls_md5(d, n, md); + return md; +#endif +} + +void +enc_table_init(const char *pass) +{ + uint32_t i; + uint64_t key = 0; + uint8_t *digest; + + enc_table = ss_malloc(256); + dec_table = ss_malloc(256); + + digest = enc_md5((const uint8_t *)pass, strlen(pass), NULL); + + for (i = 0; i < 8; i++) + key += OFFSET_ROL(digest, i); + + for (i = 0; i < 256; ++i) + enc_table[i] = i; + for (i = 1; i < 1024; ++i) + merge_sort(enc_table, 256, i, key); + for (i = 0; i < 256; ++i) + // gen decrypt table from encrypt table + dec_table[enc_table[i]] = i; +} + +int +cipher_iv_size(const cipher_t *cipher) +{ +#if defined(USE_CRYPTO_OPENSSL) + if (cipher->info == NULL) + return cipher->iv_len; + else + return EVP_CIPHER_iv_length(cipher->info); +#elif defined(USE_CRYPTO_POLARSSL) || defined(USE_CRYPTO_MBEDTLS) + if (cipher == NULL) { + return 0; + } + return cipher->info->iv_size; +#endif +} + +int +cipher_key_size(const cipher_t *cipher) +{ +#if defined(USE_CRYPTO_OPENSSL) + if (cipher->info == NULL) + return cipher->key_len; + else + return EVP_CIPHER_key_length(cipher->info); +#elif defined(USE_CRYPTO_POLARSSL) + if (cipher == NULL) { + return 0; + } + /* Override PolarSSL 32 bit default key size with sane 128 bit default */ + if (cipher->info->base != NULL && POLARSSL_CIPHER_ID_BLOWFISH == + cipher->info->base->cipher) { + return 128 / 8; + } + return cipher->info->key_length / 8; +#elif defined(USE_CRYPTO_MBEDTLS) + /* + * Semi-API changes (technically public, morally private) + * Renamed a few headers to include _internal in the name. Those headers are + * not supposed to be included by users. + * Changed md_info_t into an opaque structure (use md_get_xxx() accessors). + * Changed pk_info_t into an opaque structure. + * Changed cipher_base_t into an opaque structure. + */ + if (cipher == NULL) { + return 0; + } + /* From Version 1.2.7 released 2013-04-13 Default Blowfish keysize is now 128-bits */ + return cipher->info->key_bitlen / 8; +#endif +} + +void +bytes_to_key_with_size(const char *pass, size_t len, uint8_t *md, size_t md_size) +{ + uint8_t result[128]; + enc_md5((const unsigned char *)pass, len, result); + memcpy(md, result, 16); + int i = 16; + for (; i < md_size; i += 16) { + memcpy(result + 16, pass, len); + enc_md5(result, 16 + len, result); + memcpy(md + i, result, 16); + } +} + +int +bytes_to_key(const cipher_t *cipher, const digest_type_t *md, + const uint8_t *pass, uint8_t *key) +{ + size_t datal; + datal = strlen((const char *)pass); + +#if defined(USE_CRYPTO_OPENSSL) + + MD5_CTX c; + unsigned char md_buf[MAX_MD_SIZE]; + int nkey; + int addmd; + unsigned int i, j, mds; + + mds = 16; + nkey = cipher_key_size(cipher); + if (pass == NULL) + return nkey; + memset(&c, 0, sizeof(MD5_CTX)); + + for (j = 0, addmd = 0; j < nkey; addmd++) { + MD5_Init(&c); + if (addmd) { + MD5_Update(&c, md_buf, mds); + } + MD5_Update(&c, pass, datal); + MD5_Final(md_buf, &c); + + for (i = 0; i < mds; i++, j++) { + if (j >= nkey) + break; + key[j] = md_buf[i]; + } + } + + return nkey; + +#elif defined(USE_CRYPTO_POLARSSL) + md_context_t c; + unsigned char md_buf[MAX_MD_SIZE]; + int nkey; + int addmd; + unsigned int i, j, mds; + + nkey = cipher_key_size(cipher); + mds = md_get_size(md); + memset(&c, 0, sizeof(md_context_t)); + + if (pass == NULL) + return nkey; + if (md_init_ctx(&c, md)) + return 0; + + for (j = 0, addmd = 0; j < nkey; addmd++) { + md_starts(&c); + if (addmd) { + md_update(&c, md_buf, mds); + } + md_update(&c, pass, datal); + md_finish(&c, md_buf); + + for (i = 0; i < mds; i++, j++) { + if (j >= nkey) + break; + key[j] = md_buf[i]; + } + } + + md_free_ctx(&c); + return nkey; + +#elif defined(USE_CRYPTO_MBEDTLS) + + mbedtls_md_context_t c; + unsigned char md_buf[MAX_MD_SIZE]; + int nkey; + int addmd; + unsigned int i, j, mds; + + nkey = cipher_key_size(cipher); + mds = mbedtls_md_get_size(md); + memset(&c, 0, sizeof(mbedtls_md_context_t)); + + if (pass == NULL) + return nkey; + if (mbedtls_md_setup(&c, md, 1)) + return 0; + + for (j = 0, addmd = 0; j < nkey; addmd++) { + mbedtls_md_starts(&c); + if (addmd) { + mbedtls_md_update(&c, md_buf, mds); + } + mbedtls_md_update(&c, pass, datal); + mbedtls_md_finish(&c, &(md_buf[0])); + + for (i = 0; i < mds; i++, j++) { + if (j >= nkey) + break; + key[j] = md_buf[i]; + } + } + + mbedtls_md_free(&c); + return nkey; +#endif +} + +int +rand_bytes(uint8_t *output, int len) +{ + randombytes_buf(output, len); + // always return success + return 0; +} + +const cipher_kt_t * +get_cipher_type(int method) +{ + if (method <= TABLE || method >= CIPHER_NUM) { + LOGE("get_cipher_type(): Illegal method"); + return NULL; + } + + if (method == RC4_MD5 || method == RC4_MD5_6) { + method = RC4; + } + + if (method >= SALSA20) { + return NULL; + } + + const char *ciphername = supported_ciphers[method]; +#if defined(USE_CRYPTO_OPENSSL) + return EVP_get_cipherbyname(ciphername); +#elif defined(USE_CRYPTO_POLARSSL) + const char *polarname = supported_ciphers_polarssl[method]; + if (strcmp(polarname, CIPHER_UNSUPPORTED) == 0) { + LOGE("Cipher %s currently is not supported by PolarSSL library", + ciphername); + return NULL; + } + return cipher_info_from_string(polarname); +#elif defined(USE_CRYPTO_MBEDTLS) + const char *mbedtlsname = supported_ciphers_mbedtls[method]; + if (strcmp(mbedtlsname, CIPHER_UNSUPPORTED) == 0) { + LOGE("Cipher %s currently is not supported by mbed TLS library", + ciphername); + return NULL; + } + return mbedtls_cipher_info_from_string(mbedtlsname); +#endif +} + +const digest_type_t * +get_digest_type(const char *digest) +{ + if (digest == NULL) { + LOGE("get_digest_type(): Digest name is null"); + return NULL; + } + +#if defined(USE_CRYPTO_OPENSSL) + return EVP_get_digestbyname(digest); +#elif defined(USE_CRYPTO_POLARSSL) + return md_info_from_string(digest); +#elif defined(USE_CRYPTO_MBEDTLS) + return mbedtls_md_info_from_string(digest); +#endif +} + +void +cipher_context_init(cipher_ctx_t *ctx, int method, int enc) +{ + if (method <= TABLE || method >= CIPHER_NUM) { + LOGE("cipher_context_init(): Illegal method"); + return; + } + + if (method >= SALSA20) { + enc_iv_len = supported_ciphers_iv_size[method]; + return; + } + + const char *ciphername = supported_ciphers[method]; +#if defined(USE_CRYPTO_APPLECC) + cipher_cc_t *cc = &ctx->cc; + cc->cryptor = NULL; + cc->cipher = supported_ciphers_applecc[method]; + if (cc->cipher == kCCAlgorithmInvalid) { + cc->valid = kCCContextInvalid; + } else { + cc->valid = kCCContextValid; + if (cc->cipher == kCCAlgorithmRC4) { + cc->mode = supported_modes_applecc[method]; + cc->padding = ccNoPadding; + } else { + cc->mode = supported_modes_applecc[method]; + if (cc->mode == kCCModeCTR) { + cc->padding = ccNoPadding; + } else { + cc->padding = ccPKCS7Padding; + } + } + return; + } +#endif + + const cipher_kt_t *cipher = get_cipher_type(method); + +#if defined(USE_CRYPTO_OPENSSL) + ctx->evp = EVP_CIPHER_CTX_new(); + cipher_evp_t *evp = ctx->evp; + + if (cipher == NULL) { + LOGE("Cipher %s not found in OpenSSL library", ciphername); + FATAL("Cannot initialize cipher"); + } + if (!EVP_CipherInit_ex(evp, cipher, NULL, NULL, NULL, enc)) { + LOGE("Cannot initialize cipher %s", ciphername); + exit(EXIT_FAILURE); + } + if (!EVP_CIPHER_CTX_set_key_length(evp, enc_key_len)) { + EVP_CIPHER_CTX_cleanup(evp); + LOGE("Invalid key length: %d", enc_key_len); + exit(EXIT_FAILURE); + } + if (method > RC4_MD5) { + EVP_CIPHER_CTX_set_padding(evp, 1); + } +#elif defined(USE_CRYPTO_POLARSSL) + ctx->evp = (cipher_evp_t *)ss_malloc(sizeof(cipher_evp_t)); + cipher_evp_t *evp = ctx->evp; + + if (cipher == NULL) { + LOGE("Cipher %s not found in PolarSSL library", ciphername); + FATAL("Cannot initialize PolarSSL cipher"); + } + if (cipher_init_ctx(evp, cipher) != 0) { + FATAL("Cannot initialize PolarSSL cipher context"); + } +#elif defined(USE_CRYPTO_MBEDTLS) + ctx->evp = (cipher_evp_t *)ss_malloc(sizeof(cipher_evp_t)); + cipher_evp_t *evp = ctx->evp; + + if (cipher == NULL) { + LOGE("Cipher %s not found in mbed TLS library", ciphername); + FATAL("Cannot initialize mbed TLS cipher"); + } + mbedtls_cipher_init(evp); + if (mbedtls_cipher_setup(evp, cipher) != 0) { + FATAL("Cannot initialize mbed TLS cipher context"); + } +#endif +} + +void +cipher_context_set_iv(cipher_ctx_t *ctx, uint8_t *iv, size_t iv_len, + int enc) +{ + const unsigned char *true_key; + + if (iv == NULL) { + LOGE("cipher_context_set_iv(): IV is null"); + return; + } + + if (!enc) { + memcpy(ctx->iv, iv, iv_len); + } + + if (enc_method >= SALSA20) { + return; + } + + if (enc_method == RC4_MD5 || enc_method == RC4_MD5_6) { + unsigned char key_iv[32]; + memcpy(key_iv, enc_key, 16); + memcpy(key_iv + 16, iv, iv_len); + true_key = enc_md5(key_iv, 16 + iv_len, NULL); + iv_len = 0; + } else { + true_key = enc_key; + } + +#ifdef USE_CRYPTO_APPLECC + cipher_cc_t *cc = &ctx->cc; + if (cc->valid == kCCContextValid) { + memcpy(cc->iv, iv, iv_len); + memcpy(cc->key, true_key, enc_key_len); + cc->iv_len = iv_len; + cc->key_len = enc_key_len; + cc->encrypt = enc ? kCCEncrypt : kCCDecrypt; + if (cc->cryptor != NULL) { + CCCryptorRelease(cc->cryptor); + cc->cryptor = NULL; + } + + CCCryptorStatus ret; + ret = CCCryptorCreateWithMode( + cc->encrypt, + cc->mode, + cc->cipher, + cc->padding, + cc->iv, cc->key, cc->key_len, + NULL, 0, 0, kCCModeOptionCTR_BE, + &cc->cryptor); + if (ret != kCCSuccess) { + if (cc->cryptor != NULL) { + CCCryptorRelease(cc->cryptor); + cc->cryptor = NULL; + } + FATAL("Cannot set CommonCrypto key and IV"); + } + return; + } +#endif + + cipher_evp_t *evp = ctx->evp; + if (evp == NULL) { + LOGE("cipher_context_set_iv(): Cipher context is null"); + return; + } +#if defined(USE_CRYPTO_OPENSSL) + if (!EVP_CipherInit_ex(evp, NULL, NULL, true_key, iv, enc)) { + EVP_CIPHER_CTX_cleanup(evp); + FATAL("Cannot set key and IV"); + } +#elif defined(USE_CRYPTO_POLARSSL) + // XXX: PolarSSL 1.3.11: cipher_free_ctx deprecated, Use cipher_free() instead. + if (cipher_setkey(evp, true_key, enc_key_len * 8, enc) != 0) { + cipher_free_ctx(evp); + FATAL("Cannot set PolarSSL cipher key"); + } +#if POLARSSL_VERSION_NUMBER >= 0x01030000 + if (cipher_set_iv(evp, iv, iv_len) != 0) { + cipher_free_ctx(evp); + FATAL("Cannot set PolarSSL cipher IV"); + } + if (cipher_reset(evp) != 0) { + cipher_free_ctx(evp); + FATAL("Cannot finalize PolarSSL cipher context"); + } +#else + if (cipher_reset(evp, iv) != 0) { + cipher_free_ctx(evp); + FATAL("Cannot set PolarSSL cipher IV"); + } +#endif +#elif defined(USE_CRYPTO_MBEDTLS) + if (mbedtls_cipher_setkey(evp, true_key, enc_key_len * 8, enc) != 0) { + mbedtls_cipher_free(evp); + FATAL("Cannot set mbed TLS cipher key"); + } + + if (mbedtls_cipher_set_iv(evp, iv, iv_len) != 0) { + mbedtls_cipher_free(evp); + FATAL("Cannot set mbed TLS cipher IV"); + } + if (mbedtls_cipher_reset(evp) != 0) { + mbedtls_cipher_free(evp); + FATAL("Cannot finalize mbed TLS cipher context"); + } +#endif + +#ifdef DEBUG + dump("IV", (char *)iv, iv_len); +#endif +} + +void +cipher_context_release(cipher_ctx_t *ctx) +{ + if (enc_method >= SALSA20) { + return; + } + +#ifdef USE_CRYPTO_APPLECC + cipher_cc_t *cc = &ctx->cc; + if (cc->cryptor != NULL) { + CCCryptorRelease(cc->cryptor); + cc->cryptor = NULL; + } + if (cc->valid == kCCContextValid) { + return; + } +#endif + +#if defined(USE_CRYPTO_OPENSSL) + EVP_CIPHER_CTX_free(ctx->evp); +#elif defined(USE_CRYPTO_POLARSSL) +// NOTE: cipher_free_ctx deprecated in PolarSSL 1.3.11 + cipher_free_ctx(ctx->evp); + ss_free(ctx->evp); +#elif defined(USE_CRYPTO_MBEDTLS) +// NOTE: cipher_free_ctx deprecated + mbedtls_cipher_free(ctx->evp); + ss_free(ctx->evp); +#endif +} + +static int +cipher_context_update(cipher_ctx_t *ctx, uint8_t *output, size_t *olen, + const uint8_t *input, size_t ilen) +{ +#ifdef USE_CRYPTO_APPLECC + cipher_cc_t *cc = &ctx->cc; + if (cc->valid == kCCContextValid) { + CCCryptorStatus ret; + ret = CCCryptorUpdate(cc->cryptor, input, ilen, output, + ilen, olen); + return (ret == kCCSuccess) ? 1 : 0; + } +#endif + cipher_evp_t *evp = ctx->evp; +#if defined(USE_CRYPTO_OPENSSL) + int err = 0, tlen = *olen; + err = EVP_CipherUpdate(evp, (uint8_t *)output, &tlen, + (const uint8_t *)input, ilen); + *olen = tlen; + return err; +#elif defined(USE_CRYPTO_POLARSSL) + return !cipher_update(evp, (const uint8_t *)input, ilen, + (uint8_t *)output, olen); +#elif defined(USE_CRYPTO_MBEDTLS) + return !mbedtls_cipher_update(evp, (const uint8_t *)input, ilen, + (uint8_t *)output, olen); +#endif +} +int ss_md5_hmac(char *auth, char *msg, int msg_len, uint8_t *iv) +{ + uint8_t hash[MD5_BYTES]; + uint8_t auth_key[MAX_IV_LENGTH + MAX_KEY_LENGTH]; + memcpy(auth_key, iv, enc_iv_len); + memcpy(auth_key + enc_iv_len, enc_key, enc_key_len); + +#if defined(USE_CRYPTO_OPENSSL) + HMAC(EVP_md5(), auth_key, enc_iv_len + enc_key_len, (uint8_t *)msg, msg_len, (uint8_t *)hash, NULL); +#elif defined(USE_CRYPTO_MBEDTLS) + mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_MD5), auth_key, enc_iv_len + enc_key_len, (uint8_t *)msg, msg_len, (uint8_t *)hash); +#else + md5_hmac(auth_key, enc_iv_len + enc_key_len, (uint8_t *)msg, msg_len, (uint8_t *)hash); +#endif + + memcpy(auth, hash, MD5_BYTES); + + return 0; +} + +int ss_md5_hmac_with_key(char *auth, char *msg, int msg_len, uint8_t *auth_key, int key_len) +{ + uint8_t hash[MD5_BYTES]; + +#if defined(USE_CRYPTO_OPENSSL) + HMAC(EVP_md5(), auth_key, key_len, (uint8_t *)msg, msg_len, (uint8_t *)hash, NULL); +#elif defined(USE_CRYPTO_MBEDTLS) + mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_MD5), auth_key, key_len, (uint8_t *)msg, msg_len, (uint8_t *)hash); +#else + md5_hmac(auth_key, key_len, (uint8_t *)msg, msg_len, (uint8_t *)hash); +#endif + + memcpy(auth, hash, MD5_BYTES); + + return 0; +} + +int ss_md5_hash_func(char *auth, char *msg, int msg_len) +{ + uint8_t hash[MD5_BYTES]; + +#if defined(USE_CRYPTO_OPENSSL) + MD5((uint8_t *)msg, msg_len, (uint8_t *)hash); +#elif defined(USE_CRYPTO_MBEDTLS) + mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_MD5), (uint8_t *)msg, msg_len, (uint8_t *)hash); +#else + md5((uint8_t *)msg, msg_len, (uint8_t *)hash); +#endif + + memcpy(auth, hash, MD5_BYTES); + + return 0; +} + +int ss_sha1_hmac(char *auth, char *msg, int msg_len, uint8_t *iv) +{ + uint8_t hash[SHA1_BYTES]; + uint8_t auth_key[MAX_IV_LENGTH + MAX_KEY_LENGTH]; + memcpy(auth_key, iv, enc_iv_len); + memcpy(auth_key + enc_iv_len, enc_key, enc_key_len); + +#if defined(USE_CRYPTO_OPENSSL) + HMAC(EVP_sha1(), auth_key, enc_iv_len + enc_key_len, (uint8_t *)msg, msg_len, (uint8_t *)hash, NULL); +#elif defined(USE_CRYPTO_MBEDTLS) + mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), auth_key, enc_iv_len + enc_key_len, (uint8_t *)msg, msg_len, (uint8_t *)hash); +#else + sha1_hmac(auth_key, enc_iv_len + enc_key_len, (uint8_t *)msg, msg_len, (uint8_t *)hash); +#endif + + memcpy(auth, hash, SHA1_BYTES); + + return 0; +} + +int ss_sha1_hmac_with_key(char *auth, char *msg, int msg_len, uint8_t *auth_key, int key_len) +{ + uint8_t hash[SHA1_BYTES]; + +#if defined(USE_CRYPTO_OPENSSL) + HMAC(EVP_sha1(), auth_key, key_len, (uint8_t *)msg, msg_len, (uint8_t *)hash, NULL); +#elif defined(USE_CRYPTO_MBEDTLS) + mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), auth_key, key_len, (uint8_t *)msg, msg_len, (uint8_t *)hash); +#else + sha1_hmac(auth_key, key_len, (uint8_t *)msg, msg_len, (uint8_t *)hash); +#endif + + memcpy(auth, hash, SHA1_BYTES); + + return 0; +} + +int ss_sha1_hash_func(char *auth, char *msg, int msg_len) +{ + uint8_t hash[SHA1_BYTES]; +#if defined(USE_CRYPTO_OPENSSL) + SHA1((uint8_t *)msg, msg_len, (uint8_t *)hash); +#elif defined(USE_CRYPTO_MBEDTLS) + mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), (uint8_t *)msg, msg_len, (uint8_t *)hash); +#else + sha1((uint8_t *)msg, msg_len, (uint8_t *)hash); +#endif + + memcpy(auth, hash, SHA1_BYTES); + + return 0; +} + +int ss_aes_128_cbc(char *encrypt, char *out_data, char *key) +{ + unsigned char iv[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + +#if defined(USE_CRYPTO_OPENSSL) + AES_KEY aes; + AES_set_encrypt_key((unsigned char*)key, 128, &aes); + AES_cbc_encrypt((const unsigned char *)encrypt, (unsigned char *)out_data, 16, &aes, iv, AES_ENCRYPT); + +#elif defined(USE_CRYPTO_MBEDTLS) + mbedtls_aes_context aes; + + unsigned char output[16]; + + mbedtls_aes_setkey_enc( &aes, (unsigned char *)key, 128 ); + mbedtls_aes_crypt_cbc( &aes, MBEDTLS_AES_ENCRYPT, 16, iv, (unsigned char *)encrypt, output ); + + memcpy(out_data, output, 16); +#else + + aes_context aes; + + unsigned char output[16]; + + aes_setkey_enc( &aes, (unsigned char *)key, 128 ); + aes_crypt_cbc( &aes, AES_ENCRYPT, 16, iv, (unsigned char *)encrypt, output ); + + memcpy(out_data, output, 16); +#endif + + return 0; +} + +int ss_onetimeauth(buffer_t *buf, uint8_t *iv, size_t capacity) +{ + uint8_t hash[ONETIMEAUTH_BYTES * 2]; + uint8_t auth_key[MAX_IV_LENGTH + MAX_KEY_LENGTH]; + memcpy(auth_key, iv, enc_iv_len); + memcpy(auth_key + enc_iv_len, enc_key, enc_key_len); + + brealloc(buf, ONETIMEAUTH_BYTES + buf->len, capacity); + +#if defined(USE_CRYPTO_OPENSSL) + HMAC(EVP_sha1(), auth_key, enc_iv_len + enc_key_len, (uint8_t *)buf->array, buf->len, (uint8_t *)hash, NULL); +#elif defined(USE_CRYPTO_MBEDTLS) + mbedtls_md_hmac(mbedtls_md_info_from_type( + MBEDTLS_MD_SHA1), auth_key, enc_iv_len + enc_key_len, (uint8_t *)buf->array, buf->len, + (uint8_t *)hash); +#else + sha1_hmac(auth_key, enc_iv_len + enc_key_len, (uint8_t *)buf->array, buf->len, (uint8_t *)hash); +#endif + + memcpy(buf->array + buf->len, hash, ONETIMEAUTH_BYTES); + buf->len += ONETIMEAUTH_BYTES; + + return 0; +} + +int +ss_onetimeauth_verify(buffer_t *buf, uint8_t *iv) +{ + uint8_t hash[ONETIMEAUTH_BYTES * 2]; + uint8_t auth_key[MAX_IV_LENGTH + MAX_KEY_LENGTH]; + memcpy(auth_key, iv, enc_iv_len); + memcpy(auth_key + enc_iv_len, enc_key, enc_key_len); + size_t len = buf->len - ONETIMEAUTH_BYTES; + +#if defined(USE_CRYPTO_OPENSSL) + HMAC(EVP_sha1(), auth_key, enc_iv_len + enc_key_len, (uint8_t *)buf->array, len, hash, NULL); +#elif defined(USE_CRYPTO_MBEDTLS) + mbedtls_md_hmac(mbedtls_md_info_from_type( + MBEDTLS_MD_SHA1), auth_key, enc_iv_len + enc_key_len, (uint8_t *)buf->array, len, hash); +#else + sha1_hmac(auth_key, enc_iv_len + enc_key_len, (uint8_t *)buf->array, len, hash); +#endif + + return safe_memcmp(buf->array + len, hash, ONETIMEAUTH_BYTES); +} + +int +ss_encrypt_all(buffer_t *plain, int method, int auth, size_t capacity) +{ + if (method > TABLE) { + cipher_ctx_t evp; + cipher_context_init(&evp, method, 1); + + size_t iv_len = enc_iv_len; + int err = 1; + + static buffer_t tmp = { 0, 0, 0, NULL }; + brealloc(&tmp, iv_len + plain->len, capacity); + buffer_t *cipher = &tmp; + cipher->len = plain->len; + + uint8_t iv[MAX_IV_LENGTH]; + + rand_bytes(iv, iv_len); + cipher_context_set_iv(&evp, iv, iv_len, 1); + memcpy(cipher->array, iv, iv_len); + + if (auth) { + ss_onetimeauth(plain, iv, capacity); + cipher->len = plain->len; + } + + if (method >= SALSA20) { + crypto_stream_xor_ic((uint8_t *)(cipher->array + iv_len), + (const uint8_t *)plain->array, (uint64_t)(plain->len), + (const uint8_t *)iv, + 0, enc_key, method); + } else { + err = cipher_context_update(&evp, (uint8_t *)(cipher->array + iv_len), + &cipher->len, (const uint8_t *)plain->array, + plain->len); + } + + if (!err) { + bfree(plain); + cipher_context_release(&evp); + return -1; + } + +#ifdef DEBUG + dump("PLAIN", plain->array, plain->len); + dump("CIPHER", cipher->array + iv_len, cipher->len); +#endif + + cipher_context_release(&evp); + + brealloc(plain, iv_len + cipher->len, capacity); + memcpy(plain->array, cipher->array, iv_len + cipher->len); + plain->len = iv_len + cipher->len; + + return 0; + } else { + char *begin = plain->array; + char *ptr = plain->array; + while (ptr < begin + plain->len) { + *ptr = (char)enc_table[(uint8_t)*ptr]; + ptr++; + } + return 0; + } +} + +int +ss_encrypt(buffer_t *plain, enc_ctx_t *ctx, size_t capacity) +{ + if (ctx != NULL) { + static buffer_t tmp = { 0, 0, 0, NULL }; + + int err = 1; + size_t iv_len = 0; + if (!ctx->init) { + iv_len = enc_iv_len; + } + + brealloc(&tmp, iv_len + plain->len, capacity); + buffer_t *cipher = &tmp; + cipher->len = plain->len; + + if (!ctx->init) { + cipher_context_set_iv(&ctx->evp, ctx->evp.iv, iv_len, 1); + memcpy(cipher->array, ctx->evp.iv, iv_len); + ctx->counter = 0; + ctx->init = 1; + } + + if (enc_method >= SALSA20) { + int padding = ctx->counter % SODIUM_BLOCK_SIZE; + brealloc(cipher, iv_len + (padding + cipher->len) * 2, capacity); + if (padding) { + brealloc(plain, plain->len + padding, capacity); + memmove(plain->array + padding, plain->array, plain->len); + sodium_memzero(plain->array, padding); + } + crypto_stream_xor_ic((uint8_t *)(cipher->array + iv_len), + (const uint8_t *)plain->array, + (uint64_t)(plain->len + padding), + (const uint8_t *)ctx->evp.iv, + ctx->counter / SODIUM_BLOCK_SIZE, enc_key, + enc_method); + ctx->counter += plain->len; + if (padding) { + memmove(cipher->array + iv_len, + cipher->array + iv_len + padding, cipher->len); + } + } else { + err = + cipher_context_update(&ctx->evp, + (uint8_t *)(cipher->array + iv_len), + &cipher->len, (const uint8_t *)plain->array, + plain->len); + if (!err) { + return -1; + } + } + +#ifdef DEBUG + dump("PLAIN", plain->array, plain->len); + dump("CIPHER", cipher->array + iv_len, cipher->len); +#endif + + brealloc(plain, iv_len + cipher->len, capacity); + memcpy(plain->array, cipher->array, iv_len + cipher->len); + plain->len = iv_len + cipher->len; + + return 0; + } else { + char *begin = plain->array; + char *ptr = plain->array; + while (ptr < begin + plain->len) { + *ptr = (char)enc_table[(uint8_t)*ptr]; + ptr++; + } + return 0; + } +} + +int +ss_decrypt_all(buffer_t *cipher, int method, int auth, size_t capacity) +{ + if (method > TABLE) { + size_t iv_len = enc_iv_len; + int ret = 1; + + if (cipher->len <= iv_len) { + return -1; + } + + cipher_ctx_t evp; + cipher_context_init(&evp, method, 0); + + static buffer_t tmp = { 0, 0, 0, NULL }; + brealloc(&tmp, cipher->len, capacity); + buffer_t *plain = &tmp; + plain->len = cipher->len - iv_len; + + uint8_t iv[MAX_IV_LENGTH]; + memcpy(iv, cipher->array, iv_len); + cipher_context_set_iv(&evp, iv, iv_len, 0); + + if (method >= SALSA20) { + crypto_stream_xor_ic((uint8_t *)plain->array, + (const uint8_t *)(cipher->array + iv_len), + (uint64_t)(cipher->len - iv_len), + (const uint8_t *)iv, 0, enc_key, method); + } else { + ret = cipher_context_update(&evp, (uint8_t *)plain->array, &plain->len, + (const uint8_t *)(cipher->array + iv_len), + cipher->len - iv_len); + } + + if (auth || (plain->array[0] & ONETIMEAUTH_FLAG)) { + if (plain->len > ONETIMEAUTH_BYTES) { + ret = !ss_onetimeauth_verify(plain, iv); + if (ret) { + plain->len -= ONETIMEAUTH_BYTES; + } + } else { + ret = 0; + } + } + + if (!ret) { + bfree(cipher); + cipher_context_release(&evp); + return -1; + } + +#ifdef DEBUG + dump("PLAIN", plain->array, plain->len); + dump("CIPHER", cipher->array + iv_len, cipher->len - iv_len); +#endif + + cipher_context_release(&evp); + + brealloc(cipher, plain->len, capacity); + memcpy(cipher->array, plain->array, plain->len); + cipher->len = plain->len; + + return 0; + } else { + char *begin = cipher->array; + char *ptr = cipher->array; + while (ptr < begin + cipher->len) { + *ptr = (char)dec_table[(uint8_t)*ptr]; + ptr++; + } + return 0; + } +} + +int +ss_decrypt(buffer_t *cipher, enc_ctx_t *ctx, size_t capacity) +{ + if (ctx != NULL) { + static buffer_t tmp = { 0, 0, 0, NULL }; + + size_t iv_len = 0; + int err = 1; + + brealloc(&tmp, cipher->len, capacity); + buffer_t *plain = &tmp; + plain->len = cipher->len; + + if (!ctx->init) { + uint8_t iv[MAX_IV_LENGTH]; + iv_len = enc_iv_len; + plain->len -= iv_len; + + memcpy(iv, cipher->array, iv_len); + cipher_context_set_iv(&ctx->evp, iv, iv_len, 0); + ctx->counter = 0; + ctx->init = 1; + + if (enc_method > RC4) { + if (cache_key_exist(iv_cache, (char *)iv, iv_len)) { + bfree(cipher); + return -1; + } else { + cache_insert(iv_cache, (char *)iv, iv_len, NULL); + } + } + } + + if (enc_method >= SALSA20) { + int padding = ctx->counter % SODIUM_BLOCK_SIZE; + brealloc(plain, (plain->len + padding) * 2, capacity); + + if (padding) { + brealloc(cipher, cipher->len + padding, capacity); + memmove(cipher->array + iv_len + padding, cipher->array + iv_len, + cipher->len - iv_len); + sodium_memzero(cipher->array + iv_len, padding); + } + crypto_stream_xor_ic((uint8_t *)plain->array, + (const uint8_t *)(cipher->array + iv_len), + (uint64_t)(cipher->len - iv_len + padding), + (const uint8_t *)ctx->evp.iv, + ctx->counter / SODIUM_BLOCK_SIZE, enc_key, + enc_method); + ctx->counter += cipher->len - iv_len; + if (padding) { + memmove(plain->array, plain->array + padding, plain->len); + } + } else { + err = cipher_context_update(&ctx->evp, (uint8_t *)plain->array, &plain->len, + (const uint8_t *)(cipher->array + iv_len), + cipher->len - iv_len); + } + + if (!err) { + bfree(cipher); + return -1; + } + +#ifdef DEBUG + dump("PLAIN", plain->array, plain->len); + dump("CIPHER", cipher->array + iv_len, cipher->len - iv_len); +#endif + + brealloc(cipher, plain->len, capacity); + memcpy(cipher->array, plain->array, plain->len); + cipher->len = plain->len; + + return 0; + } else { + char *begin = cipher->array; + char *ptr = cipher->array; + while (ptr < begin + cipher->len) { + *ptr = (char)dec_table[(uint8_t)*ptr]; + ptr++; + } + return 0; + } +} + +void +enc_ctx_init(int method, enc_ctx_t *ctx, int enc) +{ + sodium_memzero(ctx, sizeof(enc_ctx_t)); + cipher_context_init(&ctx->evp, method, enc); + + if (enc) { + rand_bytes(ctx->evp.iv, enc_iv_len); + } +} + +void +enc_key_init(int method, const char *pass) +{ + if (method <= TABLE || method >= CIPHER_NUM) { + LOGE("enc_key_init(): Illegal method"); + return; + } + + // Initialize cache + cache_create(&iv_cache, 256, NULL); + +#if defined(USE_CRYPTO_OPENSSL) + OpenSSL_add_all_algorithms(); +#else + cipher_kt_t cipher_info; +#endif + + cipher_t cipher; + memset(&cipher, 0, sizeof(cipher_t)); + + // Initialize sodium for random generator + if (sodium_init() == -1) { + FATAL("Failed to initialize sodium"); + } + + if (method == SALSA20 || method == CHACHA20 || method == CHACHA20IETF) { +#if defined(USE_CRYPTO_OPENSSL) + cipher.info = NULL; + cipher.key_len = supported_ciphers_key_size[method]; + cipher.iv_len = supported_ciphers_iv_size[method]; +#endif +#if defined(USE_CRYPTO_POLARSSL) + cipher.info = &cipher_info; + cipher.info->base = NULL; + cipher.info->key_length = supported_ciphers_key_size[method] * 8; + cipher.info->iv_size = supported_ciphers_iv_size[method]; +#endif +#if defined(USE_CRYPTO_MBEDTLS) + // XXX: key_length changed to key_bitlen in mbed TLS 2.0.0 + cipher.info = &cipher_info; + cipher.info->base = NULL; + cipher.info->key_bitlen = supported_ciphers_key_size[method] * 8; + cipher.info->iv_size = supported_ciphers_iv_size[method]; +#endif + } else { + cipher.info = (cipher_kt_t *)get_cipher_type(method); + } + + if (cipher.info == NULL && cipher.key_len == 0) { + do { +#if defined(USE_CRYPTO_POLARSSL) && defined(USE_CRYPTO_APPLECC) + if (supported_ciphers_applecc[method] != kCCAlgorithmInvalid) { + cipher_info.base = NULL; + cipher_info.key_length = supported_ciphers_key_size[method] * 8; + cipher_info.iv_size = supported_ciphers_iv_size[method]; + cipher.info = (cipher_kt_t *)&cipher_info; + break; + } +#endif +#if defined(USE_CRYPTO_MBEDTLS) && defined(USE_CRYPTO_APPLECC) + // XXX: key_length changed to key_bitlen in mbed TLS 2.0.0 + if (supported_ciphers_applecc[method] != kCCAlgorithmInvalid) { + cipher_info.base = NULL; + cipher_info.key_bitlen = supported_ciphers_key_size[method] * 8; + cipher_info.iv_size = supported_ciphers_iv_size[method]; + cipher.info = (cipher_kt_t *)&cipher_info; + break; + } +#endif + LOGE("Cipher %s not found in crypto library", supported_ciphers[method]); + FATAL("Cannot initialize cipher"); + } while (0); + } + + const digest_type_t *md = get_digest_type("MD5"); + if (md == NULL) { + FATAL("MD5 Digest not found in crypto library"); + } + + enc_key_len = bytes_to_key(&cipher, md, (const uint8_t *)pass, enc_key); + + if (enc_key_len == 0) { + FATAL("Cannot generate key and IV"); + } + if (method == RC4_MD5 || method == RC4_MD5_6) { + enc_iv_len = supported_ciphers_iv_size[method]; + } else { + enc_iv_len = cipher_iv_size(&cipher); + } + enc_method = method; +} + +int +enc_init(const char *pass, const char *method) +{ + int m = TABLE; + if (method != NULL) { + for (m = TABLE; m < CIPHER_NUM; m++) + if (strcmp(method, supported_ciphers[m]) == 0) { + break; + } + if (m >= CIPHER_NUM) { + LOGE("Invalid cipher name: %s, use rc4-md5 instead", method); + m = RC4_MD5; + } + } + if (m == TABLE) { + enc_table_init(pass); + } else { + enc_key_init(m, pass); + } + return m; +} + +int +ss_check_hash(buffer_t *buf, chunk_t *chunk, enc_ctx_t *ctx, size_t capacity) +{ + int i, j, k; + ssize_t blen = buf->len; + uint32_t cidx = chunk->idx; + + brealloc(chunk->buf, chunk->len + blen, capacity); + brealloc(buf, chunk->len + blen, capacity); + + for (i = 0, j = 0, k = 0; i < blen; i++) { + chunk->buf->array[cidx++] = buf->array[k++]; + + if (cidx == CLEN_BYTES) { + uint16_t clen = ntohs(*((uint16_t *)chunk->buf->array)); + brealloc(chunk->buf, clen + AUTH_BYTES, capacity); + chunk->len = clen; + } + + if (cidx == chunk->len + AUTH_BYTES) { + // Compare hash + uint8_t hash[ONETIMEAUTH_BYTES * 2]; + uint8_t key[MAX_IV_LENGTH + sizeof(uint32_t)]; + + uint32_t c = htonl(chunk->counter); + memcpy(key, ctx->evp.iv, enc_iv_len); + memcpy(key + enc_iv_len, &c, sizeof(uint32_t)); +#if defined(USE_CRYPTO_OPENSSL) + HMAC(EVP_sha1(), key, enc_iv_len + sizeof(uint32_t), + (uint8_t *)chunk->buf->array + AUTH_BYTES, chunk->len, hash, NULL); +#elif defined(USE_CRYPTO_MBEDTLS) + mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), key, enc_iv_len + sizeof(uint32_t), + (uint8_t *)chunk->buf->array + AUTH_BYTES, chunk->len, hash); +#else + sha1_hmac(key, enc_iv_len + sizeof(uint32_t), + (uint8_t *)chunk->buf->array + AUTH_BYTES, chunk->len, hash); +#endif + + if (safe_memcmp(hash, chunk->buf->array + CLEN_BYTES, ONETIMEAUTH_BYTES) != 0) { + return 0; + } + + // Copy chunk back to buffer + memmove(buf->array + j + chunk->len, buf->array + k, blen - i - 1); + memcpy(buf->array + j, chunk->buf->array + AUTH_BYTES, chunk->len); + + // Reset the base offset + j += chunk->len; + k = j; + cidx = 0; + chunk->counter++; + } + } + + buf->len = j; + chunk->idx = cidx; + return 1; +} + +int +ss_gen_hash(buffer_t *buf, uint32_t *counter, enc_ctx_t *ctx, size_t capacity) +{ + ssize_t blen = buf->len; + uint16_t chunk_len = htons((uint16_t)blen); + uint8_t hash[ONETIMEAUTH_BYTES * 2]; + uint8_t key[MAX_IV_LENGTH + sizeof(uint32_t)]; + uint32_t c = htonl(*counter); + + brealloc(buf, AUTH_BYTES + blen, capacity); + memcpy(key, ctx->evp.iv, enc_iv_len); + memcpy(key + enc_iv_len, &c, sizeof(uint32_t)); +#if defined(USE_CRYPTO_OPENSSL) + HMAC(EVP_sha1(), key, enc_iv_len + sizeof(uint32_t), (uint8_t *)buf->array, blen, hash, NULL); +#elif defined(USE_CRYPTO_MBEDTLS) + mbedtls_md_hmac(mbedtls_md_info_from_type( + MBEDTLS_MD_SHA1), key, enc_iv_len + sizeof(uint32_t), (uint8_t *)buf->array, blen, hash); +#else + sha1_hmac(key, enc_iv_len + sizeof(uint32_t), (uint8_t *)buf->array, blen, hash); +#endif + + memmove(buf->array + AUTH_BYTES, buf->array, blen); + memcpy(buf->array + CLEN_BYTES, hash, ONETIMEAUTH_BYTES); + memcpy(buf->array, &chunk_len, CLEN_BYTES); + + *counter = *counter + 1; + buf->len = blen + AUTH_BYTES; + + return 0; +} diff --git a/shadowsocksr-libev/src/server/encrypt.h b/shadowsocksr-libev/src/server/encrypt.h new file mode 100644 index 0000000..3bb7940 --- /dev/null +++ b/shadowsocksr-libev/src/server/encrypt.h @@ -0,0 +1,222 @@ +/* + * encrypt.h - Define the enryptor's interface + * + * Copyright (C) 2013 - 2016, Max Lv + * + * This file is part of the shadowsocks-libev. + * + * shadowsocks-libev is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * shadowsocks-libev 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with shadowsocks-libev; see the file COPYING. If not, see + * . + */ + +#ifndef _ENCRYPT_H +#define _ENCRYPT_H + +#ifndef __MINGW32__ +#include +#else + +#ifdef max +#undef max +#endif + +#ifdef min +#undef min +#endif + +#endif + +#include +#include +#include +#include + +#if defined(USE_CRYPTO_OPENSSL) + +#include +#include +#include +typedef EVP_CIPHER cipher_kt_t; +typedef EVP_CIPHER_CTX cipher_evp_t; +typedef EVP_MD digest_type_t; +#define MAX_KEY_LENGTH EVP_MAX_KEY_LENGTH +#define MAX_IV_LENGTH EVP_MAX_IV_LENGTH +#define MAX_MD_SIZE EVP_MAX_MD_SIZE + +#elif defined(USE_CRYPTO_POLARSSL) + +#include +#include +typedef cipher_info_t cipher_kt_t; +typedef cipher_context_t cipher_evp_t; +typedef md_info_t digest_type_t; +#define MAX_KEY_LENGTH 64 +#define MAX_IV_LENGTH POLARSSL_MAX_IV_LENGTH +#define MAX_MD_SIZE POLARSSL_MD_MAX_SIZE + +#elif defined(USE_CRYPTO_MBEDTLS) + +#include +#include +typedef mbedtls_cipher_info_t cipher_kt_t; +typedef mbedtls_cipher_context_t cipher_evp_t; +typedef mbedtls_md_info_t digest_type_t; +#define MAX_KEY_LENGTH 64 +#define MAX_IV_LENGTH MBEDTLS_MAX_IV_LENGTH +#define MAX_MD_SIZE MBEDTLS_MD_MAX_SIZE + +/* we must have MBEDTLS_CIPHER_MODE_CFB defined */ +#if !defined(MBEDTLS_CIPHER_MODE_CFB) +#error Cipher Feedback mode a.k.a CFB not supported by your mbed TLS. +#endif + +#endif + +#ifdef USE_CRYPTO_APPLECC + +#include + +#define kCCAlgorithmInvalid UINT32_MAX +#define kCCContextValid 0 +#define kCCContextInvalid -1 + +typedef struct { + CCCryptorRef cryptor; + int valid; + CCOperation encrypt; + CCAlgorithm cipher; + CCMode mode; + CCPadding padding; + uint8_t iv[MAX_IV_LENGTH]; + uint8_t key[MAX_KEY_LENGTH]; + size_t iv_len; + size_t key_len; +} cipher_cc_t; + +#endif + +typedef struct { + cipher_evp_t *evp; +#ifdef USE_CRYPTO_APPLECC + cipher_cc_t cc; +#endif + uint8_t iv[MAX_IV_LENGTH]; +} cipher_ctx_t; + +typedef struct { + cipher_kt_t *info; + size_t iv_len; + size_t key_len; +} cipher_t; + +#ifdef HAVE_STDINT_H +#include +#elif HAVE_INTTYPES_H +#include +#endif + +#define SODIUM_BLOCK_SIZE 64 + +enum crpher_index { + NONE = -1, + TABLE = 0, + RC4, + RC4_MD5_6, + 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, + CHACHA20IETF, + CIPHER_NUM, +}; + +#define ONETIMEAUTH_FLAG 0x10 +#define ADDRTYPE_MASK 0xEF + +#define ONETIMEAUTH_BYTES 10U +#define MD5_BYTES 16U +#define SHA1_BYTES 20U +#define CLEN_BYTES 2U +#define AUTH_BYTES (ONETIMEAUTH_BYTES + CLEN_BYTES) + +#define min(a, b) (((a) < (b)) ? (a) : (b)) +#define max(a, b) (((a) > (b)) ? (a) : (b)) + +typedef struct buffer { + size_t idx; + size_t len; + size_t capacity; + char *array; +} buffer_t; + +typedef struct chunk { + uint32_t idx; + uint32_t len; + uint32_t counter; + buffer_t *buf; +} chunk_t; + +typedef struct enc_ctx { + uint8_t init; + uint64_t counter; + cipher_ctx_t evp; +} enc_ctx_t; + +void bytes_to_key_with_size(const char *pass, size_t len, uint8_t *md, size_t md_size); + +int ss_encrypt_all(buffer_t *plaintext, int method, int auth, size_t capacity); +int ss_decrypt_all(buffer_t *ciphertext, int method, int auth, size_t capacity); +int ss_encrypt(buffer_t *plaintext, enc_ctx_t *ctx, size_t capacity); +int ss_decrypt(buffer_t *ciphertext, enc_ctx_t *ctx, size_t capacity); + +void enc_ctx_init(int method, enc_ctx_t *ctx, int enc); +int enc_init(const char *pass, const char *method); +int enc_get_iv_len(void); +uint8_t* enc_get_key(void); +int enc_get_key_len(void); +void cipher_context_release(cipher_ctx_t *evp); +unsigned char *enc_md5(const unsigned char *d, size_t n, unsigned char *md); + +int ss_md5_hmac(char *auth, char *msg, int msg_len, uint8_t *iv); +int ss_md5_hmac_with_key(char *auth, char *msg, int msg_len, uint8_t *auth_key, int key_len); +int ss_md5_hash_func(char *auth, char *msg, int msg_len); +int ss_sha1_hmac(char *auth, char *msg, int msg_len, uint8_t *iv); +int ss_sha1_hmac_with_key(char *auth, char *msg, int msg_len, uint8_t *auth_key, int key_len); +int ss_sha1_hash_func(char *auth, char *msg, int msg_len); +int ss_aes_128_cbc(char *encrypt, char *out_data, char *key); +int ss_onetimeauth(buffer_t *buf, uint8_t *iv, size_t capacity); +int ss_onetimeauth_verify(buffer_t *buf, uint8_t *iv); + +int ss_check_hash(buffer_t *buf, chunk_t *chunk, enc_ctx_t *ctx, size_t capacity); +int ss_gen_hash(buffer_t *buf, uint32_t *counter, enc_ctx_t *ctx, size_t capacity); + +int balloc(buffer_t *ptr, size_t capacity); +int brealloc(buffer_t *ptr, size_t len, size_t capacity); +void bfree(buffer_t *ptr); + +#endif // _ENCRYPT_H diff --git a/shadowsocksr-libev/src/server/http.c b/shadowsocksr-libev/src/server/http.c new file mode 100644 index 0000000..3bd4a32 --- /dev/null +++ b/shadowsocksr-libev/src/server/http.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2011 and 2012, Dustin Lundquist + * 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 HOLDER 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include /* malloc() */ +#include /* strncpy() */ +#include /* strncasecmp() */ +#include /* isblank() */ + +#include "http.h" +#include "protocol.h" + +#define SERVER_NAME_LEN 256 + +static int parse_http_header(const char *, size_t, char **); +static int get_header(const char *, const char *, int, char **); +static int next_header(const char **, int *); + +static const protocol_t http_protocol_st = { + .default_port = 80, + .parse_packet = &parse_http_header, +}; +const protocol_t *const http_protocol = &http_protocol_st; + +/* + * Parses a HTTP request for the Host: header + * + * Returns: + * >=0 - length of the hostname and updates *hostname + * caller is responsible for freeing *hostname + * -1 - Incomplete request + * -2 - No Host header included in this request + * -3 - Invalid hostname pointer + * -4 - malloc failure + * < -4 - Invalid HTTP request + * + */ +static int +parse_http_header(const char *data, size_t data_len, char **hostname) +{ + int result, i; + + if (hostname == NULL) + return -3; + + if (data_len == 0) + return -1; + + result = get_header("Host:", data, data_len, hostname); + if (result < 0) + return result; + + /* + * if the user specifies the port in the request, it is included here. + * Host: example.com:80 + * so we trim off port portion + */ + for (i = result - 1; i >= 0; i--) + if ((*hostname)[i] == ':') { + (*hostname)[i] = '\0'; + result = i; + break; + } + + return result; +} + +static int +get_header(const char *header, const char *data, int data_len, char **value) +{ + int len, header_len; + + header_len = strlen(header); + + /* loop through headers stopping at first blank line */ + while ((len = next_header(&data, &data_len)) != 0) + if (len > header_len && strncasecmp(header, data, header_len) == 0) { + /* Eat leading whitespace */ + while (header_len < len && isblank(data[header_len])) + header_len++; + + *value = malloc(len - header_len + 1); + if (*value == NULL) + return -4; + + strncpy(*value, data + header_len, len - header_len); + (*value)[len - header_len] = '\0'; + + return len - header_len; + } + + /* If there is no data left after reading all the headers then we do not + * have a complete HTTP request, there must be a blank line */ + if (data_len == 0) + return -1; + + return -2; +} + +static int +next_header(const char **data, int *len) +{ + int header_len; + + /* perhaps we can optimize this to reuse the value of header_len, rather + * than scanning twice. + * Walk our data stream until the end of the header */ + while (*len > 2 && (*data)[0] != '\r' && (*data)[1] != '\n') { + (*len)--; + (*data)++; + } + + /* advanced past the pair */ + *data += 2; + *len -= 2; + + /* Find the length of the next header */ + header_len = 0; + while (*len > header_len + 1 + && (*data)[header_len] != '\r' + && (*data)[header_len + 1] != '\n') + header_len++; + + return header_len; +} diff --git a/shadowsocksr-libev/src/server/http.h b/shadowsocksr-libev/src/server/http.h new file mode 100644 index 0000000..914815a --- /dev/null +++ b/shadowsocksr-libev/src/server/http.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2011 and 2012, Dustin Lundquist + * 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 HOLDER 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. + */ +#ifndef HTTP_H +#define HTTP_H + +#include +#include "protocol.h" + +const protocol_t *const http_protocol; + +#endif diff --git a/shadowsocksr-libev/src/server/http_simple.c b/shadowsocksr-libev/src/server/http_simple.c new file mode 100644 index 0000000..c1e34ee --- /dev/null +++ b/shadowsocksr-libev/src/server/http_simple.c @@ -0,0 +1,625 @@ + +#include "http_simple.h" + +static char* g_useragent[] = { + "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0", + "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:40.0) Gecko/20100101 Firefox/44.0", + "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36", + "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", + "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:35.0) Gecko/20100101 Firefox/35.0", + "Mozilla/5.0 (compatible; WOW64; MSIE 10.0; Windows NT 6.2)", + "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", + "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.3; Trident/7.0; .NET4.0E; .NET4.0C)", + "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko", + "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", + "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", + "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", +}; + +static int g_useragent_index = -1; + +typedef struct http_simple_local_data { + int has_sent_header; + int has_recv_header; + char *encode_buffer; + int host_matched; + char *recv_buffer; + int recv_buffer_size; +}http_simple_local_data; + +void http_simple_local_data_init(http_simple_local_data* local) { + local->has_sent_header = 0; + local->has_recv_header = 0; + local->encode_buffer = NULL; + + local->recv_buffer = malloc(0); + local->recv_buffer_size = 0; + + local->host_matched = 0; + + if (g_useragent_index == -1) { + g_useragent_index = xorshift128plus() % (sizeof(g_useragent) / sizeof(*g_useragent)); + } +} + +obfs * http_simple_new_obfs() { + obfs * self = new_obfs(); + self->l_data = malloc(sizeof(http_simple_local_data)); + http_simple_local_data_init((http_simple_local_data*)self->l_data); + return self; +} + +void http_simple_dispose(obfs *self) { + http_simple_local_data *local = (http_simple_local_data*)self->l_data; + if (local->encode_buffer != NULL) { + free(local->encode_buffer); + local->encode_buffer = NULL; + } + free(local); + dispose_obfs(self); +} + +char http_simple_hex(char c) { + if (c < 10) return c + '0'; + return c - 10 + 'a'; +} + +int get_data_from_http_header(char *data, char **outdata) { + char *delim = "\r\n"; + char *delim_hex = "%"; + int outlength = 0; + + char *buf = *outdata; + char *p_line; + p_line = strtok(data, delim); + + //while(p_line) + { + char *p_hex; + + p_hex = strtok(p_line, delim_hex); + + while((p_hex = strtok(NULL, delim_hex))) + { + char hex = 0; + + if(strlen(p_hex) <= 0) + { + continue; + } + + if(strlen(p_hex) > 2) + { + char *c_hex = (char*)malloc(2); + memcpy(c_hex, p_hex, 2); + hex = (char)strtol(c_hex, NULL, 16); + free(c_hex); + } + else + { + hex = (char)strtol(p_hex, NULL, 16); + } + + outlength += 1; + buf = (char*)realloc(buf, outlength); + buf[outlength - 1] = hex; + } + + //p_line = strtok(p_line, delim); + } + return outlength; +} + +void get_host_from_http_header(char *data, char **host) { + char* data_begin = strstr(data, "Host: "); + + if(data_begin == NULL) + { + return; + } + + data_begin += 6; + char* data_end = strstr(data_begin, "\r\n"); + char* data_end_port = strstr(data_begin, ":"); + + int host_length = 0; + + if(data_end_port != NULL) + { + host_length = data_end_port - data_begin; + } + else + { + host_length = data_end - data_begin; + } + + if(host_length <= 0) + { + return; + } + + memset(*host, 0x00, 1024); + memcpy(*host, data_begin, host_length); +} + +void http_simple_encode_head(http_simple_local_data *local, char *data, int datalength) { + if (local->encode_buffer == NULL) { + local->encode_buffer = (char*)malloc(datalength * 3 + 1); + } + int pos = 0; + for (; pos < datalength; ++pos) { + local->encode_buffer[pos * 3] = '%'; + local->encode_buffer[pos * 3 + 1] = http_simple_hex(((unsigned char)data[pos] >> 4)); + local->encode_buffer[pos * 3 + 2] = http_simple_hex(data[pos] & 0xF); + } + local->encode_buffer[pos * 3] = 0; +} + +int http_simple_client_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity) { + char *encryptdata = *pencryptdata; + http_simple_local_data *local = (http_simple_local_data*)self->l_data; + if (local->has_sent_header) { + return datalength; + } + char hosts[1024]; + char * phost[128]; + int host_num = 0; + int pos; + char hostport[128]; + int head_size = self->server.head_len + (xorshift128plus() & 0x3F); + int outlength; + char * out_buffer = (char*)malloc(datalength + 2048); + char * body_buffer = NULL; + if (head_size > datalength) + head_size = datalength; + http_simple_encode_head(local, encryptdata, head_size); + if (self->server.param && strlen(self->server.param) == 0) + self->server.param = NULL; + strncpy(hosts, self->server.param ? self->server.param : self->server.host, sizeof hosts); + phost[host_num++] = hosts; + for (pos = 0; hosts[pos]; ++pos) { + if (hosts[pos] == ',') { + phost[host_num++] = &hosts[pos + 1]; + hosts[pos] = 0; + } else if (hosts[pos] == '#') { + char * body_pointer = &hosts[pos + 1]; + char * p; + int trans_char = 0; + p = body_buffer = (char*)malloc(2048); + for ( ; *body_pointer; ++body_pointer) { + if (*body_pointer == '\\') { + trans_char = 1; + continue; + } else if (*body_pointer == '\n') { + *p = '\r'; + *++p = '\n'; + continue; + } + if (trans_char) { + if (*body_pointer == '\\' ) { + *p = '\\'; + } else if (*body_pointer == 'n' ) { + *p = '\r'; + *++p = '\n'; + } else { + *p = '\\'; + *p = *body_pointer; + } + trans_char = 0; + } else { + *p = *body_pointer; + } + ++p; + } + *p = 0; + hosts[pos] = 0; + break; + } + } + host_num = xorshift128plus() % host_num; + if (self->server.port == 80) + sprintf(hostport, "%s", phost[host_num]); + else + sprintf(hostport, "%s:%d", phost[host_num], self->server.port); + if (body_buffer) { + sprintf(out_buffer, + "GET /%s HTTP/1.1\r\n" + "Host: %s\r\n" + "%s\r\n\r\n", + local->encode_buffer, + hostport, + body_buffer); + } else { + sprintf(out_buffer, + "GET /%s HTTP/1.1\r\n" + "Host: %s\r\n" + "User-Agent: %s\r\n" + "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" + "Accept-Language: en-US,en;q=0.8\r\n" + "Accept-Encoding: gzip, deflate\r\n" + "DNT: 1\r\n" + "Connection: keep-alive\r\n" + "\r\n", + local->encode_buffer, + hostport, + g_useragent[g_useragent_index] + ); + } + //LOGI("http header: %s", out_buffer); + outlength = strlen(out_buffer); + memmove(out_buffer + outlength, encryptdata + head_size, datalength - head_size); + outlength += datalength - head_size; + local->has_sent_header = 1; + if (*capacity < outlength) { + *pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2); + encryptdata = *pencryptdata; + } + memmove(encryptdata, out_buffer, outlength); + free(out_buffer); + if (body_buffer != NULL) + free(body_buffer); + if (local->encode_buffer != NULL) { + free(local->encode_buffer); + local->encode_buffer = NULL; + } + return outlength; +} + +int http_simple_server_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity) { + char *encryptdata = *pencryptdata; + http_simple_local_data *local = (http_simple_local_data*)self->l_data; + if (local->has_sent_header) { + return datalength; + } + int outlength; + char * out_buffer = (char*)malloc(datalength + 2048); + + time_t now; + struct tm *tm_now; + char datetime[200]; + + time(&now); + tm_now = localtime(&now); + strftime(datetime, 200, "%a, %d %b %Y %H:%M:%S GMT", tm_now); + + sprintf(out_buffer, + "HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nContent-Encoding: gzip\r\nContent-Type: text/html\r\nDate: " + "%s" + "\r\nServer: nginx\r\nVary: Accept-Encoding\r\n\r\n", + datetime); + + outlength = strlen(out_buffer); + memmove(out_buffer + outlength, encryptdata, datalength); + outlength += datalength; + + local->has_sent_header = 1; + if (*capacity < outlength) { + *pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2); + encryptdata = *pencryptdata; + } + memmove(encryptdata, out_buffer, outlength); + free(out_buffer); + return outlength; +} + +int http_simple_client_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback) { + char *encryptdata = *pencryptdata; + http_simple_local_data *local = (http_simple_local_data*)self->l_data; + *needsendback = 0; + if (local->has_recv_header) { + return datalength; + } + char* data_begin = strstr(encryptdata, "\r\n\r\n"); + if (data_begin) { + int outlength; + data_begin += 4; + local->has_recv_header = 1; + outlength = datalength - (data_begin - encryptdata); + memmove(encryptdata, data_begin, outlength); + return outlength; + } else { + return 0; + } +} + +int http_simple_server_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback) { + char *encryptdata = *pencryptdata; + http_simple_local_data *local = (http_simple_local_data*)self->l_data; + *needsendback = 0; + if (local->has_recv_header) { + return datalength; + } + + if(datalength != 0) + { + local->recv_buffer = (char*)realloc(local->recv_buffer, local->recv_buffer_size + datalength); + memmove(local->recv_buffer + local->recv_buffer_size, encryptdata, datalength); + local->recv_buffer_size += datalength; + + int outlength = local->recv_buffer_size; + if (*capacity < outlength) { + *pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2); + encryptdata = *pencryptdata; + } + memcpy(encryptdata, local->recv_buffer, local->recv_buffer_size); + } + + if(local->recv_buffer_size > 10) + { + if(strstr(local->recv_buffer, "GET /") == local->recv_buffer || strstr(local->recv_buffer, "POST /") == local->recv_buffer) + { + if(local->recv_buffer_size > 65536) + { + free(local->recv_buffer); + local->recv_buffer = malloc(0); + local->recv_buffer_size = 0; + local->has_sent_header = 1; + local->has_recv_header = 1; + LOGE("http_simple: over size"); + return -1; + } + } + else + { + free(local->recv_buffer); + local->recv_buffer = malloc(0); + local->recv_buffer_size = 0; + local->has_sent_header = 1; + local->has_recv_header = 1; + LOGE("http_simple: not match begin"); + return -1; + } + } + else + { + LOGE("http_simple: too short"); + local->has_sent_header = 1; + local->has_recv_header = 1; + return -1; + } + + char* data_begin = strstr(encryptdata, "\r\n\r\n"); + if (data_begin) { + int outlength; + char *ret_buf = (char*)malloc(*capacity); + memset(ret_buf, 0x00, *capacity); + int ret_buf_len = 0; + ret_buf_len = get_data_from_http_header(encryptdata, &ret_buf); + + if (self->server.param && strlen(self->server.param) == 0) + { + self->server.param = NULL; + } + else + { + if(local->host_matched == 0) + { + char *host = (char*)malloc(1024); + get_host_from_http_header(local->recv_buffer, &host); + char hosts[1024]; + char * phost[128]; + int host_num = 0; + int pos = 0; + int is_match = 0; + char * body_buffer = NULL; + strncpy(hosts, self->server.param, sizeof hosts); + phost[host_num++] = hosts; + + for (pos = 0; hosts[pos]; ++pos) { + if (hosts[pos] == ',') { + phost[host_num++] = &hosts[pos + 1]; + hosts[pos] = 0; + } else if (hosts[pos] == '#') { + char * body_pointer = &hosts[pos + 1]; + char * p; + int trans_char = 0; + p = body_buffer = (char*)malloc(2048); + for ( ; *body_pointer; ++body_pointer) { + if (*body_pointer == '\\') { + trans_char = 1; + continue; + } else if (*body_pointer == '\n') { + *p = '\r'; + *++p = '\n'; + continue; + } + if (trans_char) { + if (*body_pointer == '\\' ) { + *p = '\\'; + } else if (*body_pointer == 'n' ) { + *p = '\r'; + *++p = '\n'; + } else { + *p = '\\'; + *p = *body_pointer; + } + trans_char = 0; + } else { + *p = *body_pointer; + } + ++p; + } + *p = 0; + hosts[pos] = 0; + break; + } + } + + + for(pos = 0; pos < host_num; pos++) + { + if(strcmp(phost[pos], host) == 0) + { + is_match = 1; + local->host_matched = 1; + } + } + + if(is_match == 0) + { + free(local->recv_buffer); + local->recv_buffer = malloc(0); + local->recv_buffer_size = 0; + local->has_sent_header = 1; + local->has_recv_header = 1; + LOGE("http_simple: not match host, host: %s", host); + return -1; + } + + free(host); + } + } + + if(ret_buf_len <= 0) + { + return -1; + } + + data_begin += 4; + local->has_recv_header = 1; + + ret_buf = (char*)realloc(ret_buf, ret_buf_len + datalength - (data_begin - encryptdata)); + outlength = ret_buf_len + datalength - (data_begin - encryptdata); + + memcpy(ret_buf + ret_buf_len, data_begin, datalength - (data_begin - encryptdata)); + + if (*capacity < outlength) { + *pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2); + encryptdata = *pencryptdata; + } + + memcpy(encryptdata, ret_buf, outlength); + free(ret_buf); + return outlength; + } else { + return 0; + } +} + +void boundary(char result[]) +{ + char *str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + int i,lstr; + char ss[3] = {0}; + lstr = strlen(str); + srand((unsigned int)time((time_t *)NULL)); + for(i = 0; i < 32; ++i) + { + sprintf(ss, "%c", str[(rand()%lstr)]); + strcat(result, ss); + } +} + +int http_post_client_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity) { + char *encryptdata = *pencryptdata; + http_simple_local_data *local = (http_simple_local_data*)self->l_data; + if (local->has_sent_header) { + return datalength; + } + char hosts[1024]; + char * phost[128]; + int host_num = 0; + int pos; + char hostport[128]; + int head_size = self->server.head_len + (xorshift128plus() & 0x3F); + int outlength; + char * out_buffer = (char*)malloc(datalength + 2048); + char * body_buffer = NULL; + if (head_size > datalength) + head_size = datalength; + http_simple_encode_head(local, encryptdata, head_size); + if (self->server.param && strlen(self->server.param) == 0) + self->server.param = NULL; + strncpy(hosts, self->server.param ? self->server.param : self->server.host, sizeof hosts); + phost[host_num++] = hosts; + for (pos = 0; hosts[pos]; ++pos) { + if (hosts[pos] == ',') { + phost[host_num++] = &hosts[pos + 1]; + hosts[pos] = 0; + } else if (hosts[pos] == '#') { + char * body_pointer = &hosts[pos + 1]; + char * p; + int trans_char = 0; + p = body_buffer = (char*)malloc(2048); + for ( ; *body_pointer; ++body_pointer) { + if (*body_pointer == '\\') { + trans_char = 1; + continue; + } else if (*body_pointer == '\n') { + *p = '\r'; + *++p = '\n'; + continue; + } + if (trans_char) { + if (*body_pointer == '\\' ) { + *p = '\\'; + } else if (*body_pointer == 'n' ) { + *p = '\r'; + *++p = '\n'; + } else { + *p = '\\'; + *p = *body_pointer; + } + trans_char = 0; + } else { + *p = *body_pointer; + } + ++p; + } + *p = 0; + hosts[pos] = 0; + break; + } + } + host_num = xorshift128plus() % host_num; + if (self->server.port == 80) + sprintf(hostport, "%s", phost[host_num]); + else + sprintf(hostport, "%s:%d", phost[host_num], self->server.port); + if (body_buffer) { + sprintf(out_buffer, + "POST /%s HTTP/1.1\r\n" + "Host: %s\r\n" + "%s\r\n\r\n", + local->encode_buffer, + hostport, + body_buffer); + } else { + char result[33] = {0}; + boundary(result); + sprintf(out_buffer, + "POST /%s HTTP/1.1\r\n" + "Host: %s\r\n" + "User-Agent: %s\r\n" + "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" + "Accept-Language: en-US,en;q=0.8\r\n" + "Accept-Encoding: gzip, deflate\r\n" + "Content-Type: multipart/form-data; boundary=%s\r\n" + "DNT: 1\r\n" + "Connection: keep-alive\r\n" + "\r\n", + local->encode_buffer, + hostport, + g_useragent[g_useragent_index], + result + ); + } + //LOGI("http header: %s", out_buffer); + outlength = strlen(out_buffer); + memmove(out_buffer + outlength, encryptdata + head_size, datalength - head_size); + outlength += datalength - head_size; + local->has_sent_header = 1; + if (*capacity < outlength) { + *pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2); + encryptdata = *pencryptdata; + } + memmove(encryptdata, out_buffer, outlength); + free(out_buffer); + if (body_buffer != NULL) + free(body_buffer); + if (local->encode_buffer != NULL) { + free(local->encode_buffer); + local->encode_buffer = NULL; + } + return outlength; +} diff --git a/shadowsocksr-libev/src/server/http_simple.h b/shadowsocksr-libev/src/server/http_simple.h new file mode 100644 index 0000000..cce24cc --- /dev/null +++ b/shadowsocksr-libev/src/server/http_simple.h @@ -0,0 +1,21 @@ +/* + * http_simple.h - Define shadowsocksR server's buffers and callbacks + * + * Copyright (C) 2015 - 2016, Break Wa11 + */ + +#ifndef _HTTP_SIMPLE_H +#define _HTTP_SIMPLE_H + +obfs * http_simple_new_obfs(); +void http_simple_dispose(obfs *self); + +int http_simple_client_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity); +int http_simple_client_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback); + +int http_post_client_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity); + +int http_simple_server_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity); +int http_simple_server_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback); + +#endif // _HTTP_SIMPLE_H diff --git a/shadowsocksr-libev/src/server/jconf.c b/shadowsocksr-libev/src/server/jconf.c new file mode 100644 index 0000000..494aa5f --- /dev/null +++ b/shadowsocksr-libev/src/server/jconf.c @@ -0,0 +1,260 @@ +/* + * jconf.c - Parse the JSON format config file + * + * Copyright (C) 2013 - 2016, Max Lv + * + * This file is part of the shadowsocks-libev. + * shadowsocks-libev is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * shadowsocks-libev 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with shadowsocks-libev; see the file COPYING. If not, see + * . + */ + +#include +#include +#include +#include +#include + +#include "utils.h" +#include "jconf.h" +#include "json.h" +#include "string.h" + +#include + +#define check_json_value_type(value, expected_type, message) \ + do { \ + if ((value)->type != (expected_type)) \ + FATAL((message)); \ + } while(0) + +static char * +to_string(const json_value *value) +{ + if (value->type == json_string) { + return ss_strndup(value->u.string.ptr, value->u.string.length); + } else if (value->type == json_integer) { + return strdup(ss_itoa(value->u.integer)); + } else if (value->type == json_null) { + return "null"; + } else { + LOGE("%d", value->type); + FATAL("Invalid config format."); + } + return 0; +} + +void +free_addr(ss_addr_t *addr) +{ + ss_free(addr->host); + ss_free(addr->port); +} + +void +parse_addr(const char *str, ss_addr_t *addr) +{ + int ipv6 = 0, ret = -1, n = 0; + char *pch; + + struct cork_ip ip; + if (cork_ip_init(&ip, str) != -1) { + addr->host = strdup(str); + addr->port = NULL; + return; + } + + pch = strchr(str, ':'); + while (pch != NULL) { + n++; + ret = pch - str; + pch = strchr(pch + 1, ':'); + } + if (n > 1) { + ipv6 = 1; + if (str[ret - 1] != ']') { + ret = -1; + } + } + + if (ret == -1) { + if (ipv6) { + addr->host = ss_strndup(str + 1, strlen(str) - 2); + } else { + addr->host = strdup(str); + } + addr->port = NULL; + } else { + if (ipv6) { + addr->host = ss_strndup(str + 1, ret - 2); + } else { + addr->host = ss_strndup(str, ret); + } + addr->port = strdup(str + ret + 1); + } +} + +jconf_t * +read_jconf(const char *file) +{ + static jconf_t conf; + + memset(&conf, 0, sizeof(jconf_t)); + + char *buf; + json_value *obj; + + FILE *f = fopen(file, "rb"); + if (f == NULL) { + FATAL("Invalid config path."); + } + + fseek(f, 0, SEEK_END); + long pos = ftell(f); + fseek(f, 0, SEEK_SET); + + if (pos >= MAX_CONF_SIZE) { + FATAL("Too large config file."); + } + + buf = ss_malloc(pos + 1); + if (buf == NULL) { + FATAL("No enough memory."); + } + + int nread = fread(buf, pos, 1, f); + if (!nread) { + FATAL("Failed to read the config file."); + } + fclose(f); + + buf[pos] = '\0'; // end of string + + json_settings settings = { 0UL, 0, NULL, NULL, NULL }; + char error_buf[512]; + obj = json_parse_ex(&settings, buf, pos, error_buf); + + if (obj == NULL) { + FATAL(error_buf); + } + + if (obj->type == json_object) { + unsigned int i, j; + for (i = 0; i < obj->u.object.length; i++) { + char *name = obj->u.object.values[i].name; + json_value *value = obj->u.object.values[i].value; + if (strcmp(name, "server") == 0) { + if (value->type == json_array) { + for (j = 0; j < value->u.array.length; j++) { + if (j >= MAX_REMOTE_NUM) { + break; + } + json_value *v = value->u.array.values[j]; + char *addr_str = to_string(v); + parse_addr(addr_str, conf.remote_addr + j); + ss_free(addr_str); + conf.remote_num = j + 1; + } + } else if (value->type == json_string) { + conf.remote_addr[0].host = to_string(value); + conf.remote_addr[0].port = NULL; + conf.remote_num = 1; + } + } else if (strcmp(name, "port_password") == 0) { + if (value->type == json_object) { + for (j = 0; j < value->u.object.length; j++) { + if (j >= MAX_PORT_NUM) { + break; + } + json_value *v = value->u.object.values[j].value; + if (v->type == json_string) { + conf.port_password[j].port = ss_strndup(value->u.object.values[j].name, + value->u.object.values[j].name_length); + conf.port_password[j].password = to_string(v); + conf.port_password_num = j + 1; + } + } + } + } else if (strcmp(name, "server_port") == 0) { + conf.remote_port = to_string(value); + } else if (strcmp(name, "local_address") == 0) { + conf.local_addr = to_string(value); + } else if (strcmp(name, "local_port") == 0) { + conf.local_port = to_string(value); + } else if (strcmp(name, "password") == 0) { + conf.password = to_string(value); + } else if (strcmp(name, "protocol") == 0) { // SSR + conf.protocol = to_string(value); + } else if (strcmp(name, "protocol_param") == 0) { // SSR + conf.protocol_param = to_string(value); + } else if (strcmp(name, "method") == 0) { + conf.method = to_string(value); + } else if (strcmp(name, "obfs") == 0) { // SSR + conf.obfs = to_string(value); + } else if (strcmp(name, "obfs_param") == 0) { // SSR + conf.obfs_param = to_string(value); + } else if (strcmp(name, "timeout") == 0) { + conf.timeout = to_string(value); + } else if (strcmp(name, "user") == 0) { + conf.user = to_string(value); + } else if (strcmp(name, "fast_open") == 0) { + check_json_value_type(value, json_boolean, + "invalid config file: option 'fast_open' must be a boolean"); + conf.fast_open = value->u.boolean; + } else if (strcmp(name, "auth") == 0) { + check_json_value_type(value, json_boolean, + "invalid config file: option 'auth' must be a boolean"); + conf.auth = value->u.boolean; + } else if (strcmp(name, "nofile") == 0) { + check_json_value_type(value, json_integer, + "invalid config file: option 'nofile' must be an integer"); + conf.nofile = value->u.integer; + } else if (strcmp(name, "nameserver") == 0) { + conf.nameserver = to_string(value); + } else if (strcmp(name, "tunnel_address") == 0) { + conf.tunnel_address = to_string(value); + } else if (strcmp(name, "mode") == 0) { + char *mode_str = to_string(value); + + if (strcmp(mode_str, "tcp_only") == 0) + conf.mode = TCP_ONLY; + else if (strcmp(mode_str, "tcp_and_udp") == 0) + conf.mode = TCP_AND_UDP; + else if (strcmp(mode_str, "udp_only") == 0) + conf.mode = UDP_ONLY; + else + LOGI("ignore unknown mode: %s, use tcp_only as fallback", + mode_str); + ss_free(mode_str); + } else if (strcmp(name, "mtu") == 0) { + check_json_value_type(value, json_integer, + "invalid config file: option 'mtu' must be an integer"); + conf.mtu = value->u.integer; + } else if (strcmp(name, "mptcp") == 0) { + check_json_value_type(value, json_boolean, + "invalid config file: option 'mptcp' must be a boolean"); + conf.mptcp = value->u.boolean; + } else if (strcmp(name, "ipv6_first") == 0) { + check_json_value_type(value, json_boolean, + "invalid config file: option 'ipv6_first' must be a boolean"); + conf.ipv6_first = value->u.boolean; + } + } + } else { + FATAL("Invalid config file"); + } + + ss_free(buf); + json_value_free(obj); + return &conf; +} diff --git a/shadowsocksr-libev/src/server/jconf.h b/shadowsocksr-libev/src/server/jconf.h new file mode 100644 index 0000000..9a7e5e3 --- /dev/null +++ b/shadowsocksr-libev/src/server/jconf.h @@ -0,0 +1,78 @@ +/* + * jconf.h - Define the config data structure + * + * Copyright (C) 2013 - 2016, Max Lv + * + * This file is part of the shadowsocks-libev. + * shadowsocks-libev is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * shadowsocks-libev 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with shadowsocks-libev; see the file COPYING. If not, see + * . + */ + +#ifndef _JCONF_H +#define _JCONF_H + +#define MAX_PORT_NUM 1024 +#define MAX_REMOTE_NUM 10 +#define MAX_CONF_SIZE 128 * 1024 +#define MAX_DNS_NUM 4 +#define MAX_CONNECT_TIMEOUT 10 +#define MAX_REQUEST_TIMEOUT 60 +#define MIN_UDP_TIMEOUT 10 + +#define TCP_ONLY 0 +#define TCP_AND_UDP 1 +#define UDP_ONLY 3 + +typedef struct { + char *host; + char *port; +} ss_addr_t; + +typedef struct { + char *port; + char *password; +} ss_port_password_t; + +typedef struct { + int remote_num; + ss_addr_t remote_addr[MAX_REMOTE_NUM]; + int port_password_num; + ss_port_password_t port_password[MAX_PORT_NUM]; + char *remote_port; + char *local_addr; + char *local_port; + char *password; + char *protocol; // SSR + char *protocol_param; // SSR + char *method; + char *obfs; // SSR + char *obfs_param; // SSR + char *timeout; + char *user; + int auth; + int fast_open; + int nofile; + char *nameserver; + char *tunnel_address; + int mode; + int mtu; + int mptcp; + int ipv6_first; +} jconf_t; + +jconf_t *read_jconf(const char *file); +void parse_addr(const char *str, ss_addr_t *addr); +void free_addr(ss_addr_t *addr); + +#endif // _JCONF_H diff --git a/shadowsocksr-libev/src/server/json.c b/shadowsocksr-libev/src/server/json.c new file mode 100644 index 0000000..18e95ef --- /dev/null +++ b/shadowsocksr-libev/src/server/json.c @@ -0,0 +1,1002 @@ +/* vim: set et ts=3 sw=3 sts=3 ft=c: + * + * Copyright (C) 2012, 2013, 2014 James McLaughlin et al. All rights reserved. + * https://github.com/udp/json-parser + * + * 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. + */ + +#include "json.h" +#include "utils.h" + +#ifdef _MSC_VER +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS +#endif +#endif + +#ifdef __cplusplus +const struct _json_value json_value_none; /* zero-d by ctor */ +#else +const struct _json_value json_value_none = { NULL, 0, { 0 }, { NULL } }; +#endif + +#include +#include +#include +#include + +typedef unsigned short json_uchar; + +static unsigned char +hex_value(json_char c) +{ + if (isdigit((uint8_t)c)) { + return c - '0'; + } + + switch (c) { + case 'a': + case 'A': + return 0x0A; + case 'b': + case 'B': + return 0x0B; + case 'c': + case 'C': + return 0x0C; + case 'd': + case 'D': + return 0x0D; + case 'e': + case 'E': + return 0x0E; + case 'f': + case 'F': + return 0x0F; + default: + return 0xFF; + } +} + +typedef struct { + unsigned long used_memory; + + unsigned int uint_max; + unsigned long ulong_max; + + json_settings settings; + int first_pass; +} json_state; + +static void * +default_alloc(size_t size, int zero, void *user_data) +{ + return zero ? calloc(1, size) : ss_malloc(size); +} + +static void +default_free(void *ptr, void *user_data) +{ + ss_free(ptr); +} + +static void * +json_alloc(json_state *state, unsigned long size, int zero) +{ + if ((state->ulong_max - state->used_memory) < size) { + return 0; + } + + if (state->settings.max_memory + && (state->used_memory += size) > state->settings.max_memory) { + return 0; + } + + return state->settings.mem_alloc(size, zero, state->settings.user_data); +} + +static int +new_value(json_state *state, json_value **top, json_value **root, + json_value **alloc, json_type type) +{ + json_value *value; + int values_size; + + if (!state->first_pass) { + value = *top = *alloc; + *alloc = (*alloc)->_reserved.next_alloc; + + if (!*root) { + *root = value; + } + + switch (value->type) { + case json_array: + + if (!(value->u.array.values = (json_value **)json_alloc + (state, value->u.array.length * + sizeof(json_value *), 0))) { + return 0; + } + + value->u.array.length = 0; + break; + + case json_object: + + values_size = sizeof(*value->u.object.values) * + value->u.object.length; + + if (!((*(void **)&value->u.object.values) = json_alloc + (state, + values_size + + ((size_t)value->u. + object.values), + 0))) { + return 0; + } + + value->_reserved.object_mem = (*(char **)&value->u.object.values) + + values_size; + + value->u.object.length = 0; + break; + + case json_string: + + if (!(value->u.string.ptr = (json_char *)json_alloc + (state, + (value->u.string.length + + 1) * sizeof(json_char), 0))) { + return 0; + } + + value->u.string.length = 0; + break; + + default: + break; + } + + return 1; + } + + value = (json_value *)json_alloc(state, sizeof(json_value), 1); + + if (!value) { + return 0; + } + + if (!*root) { + *root = value; + } + + value->type = type; + value->parent = *top; + + if (*alloc) { + (*alloc)->_reserved.next_alloc = value; + } + + *alloc = *top = value; + + return 1; +} + +#define e_off \ + ((int)(i - cur_line_begin)) + +#define whitespace \ +case '\n': \ + ++cur_line; cur_line_begin = i; \ +case ' ': \ +case '\t': \ +case '\r' + +#define string_add(b) \ + do { if (!state.first_pass) { string[string_length] = b; \ + } ++string_length; } while (0) + +static const long + flag_next = 1 << 0, + flag_reproc = 1 << 1, + flag_need_comma = 1 << 2, + flag_seek_value = 1 << 3, + flag_escaped = 1 << 4, + flag_string = 1 << 5, + flag_need_colon = 1 << 6, + flag_done = 1 << 7, + flag_num_negative = 1 << 8, + flag_num_zero = 1 << 9, + flag_num_e = 1 << 10, + flag_num_e_got_sign = 1 << 11, + flag_num_e_negative = 1 << 12, + flag_line_comment = 1 << 13, + flag_block_comment = 1 << 14; + +json_value * +json_parse_ex(json_settings *settings, + const json_char *json, + size_t length, + char *error_buf) +{ + json_char error[json_error_max]; + int cur_line; + const json_char *cur_line_begin, *i, *end; + json_value *top, *root, *alloc = 0; + json_state state = { 0UL, 0U, 0UL, { 0UL, 0, NULL, NULL, NULL }, 0 }; + long flags; + long num_digits = 0, num_e = 0; + json_int_t num_fraction = 0; + + /* Skip UTF-8 BOM + */ + if (length >= 3 && ((unsigned char)json[0]) == 0xEF + && ((unsigned char)json[1]) == 0xBB + && ((unsigned char)json[2]) == 0xBF) { + json += 3; + length -= 3; + } + + error[0] = '\0'; + end = (json + length); + + memcpy(&state.settings, settings, sizeof(json_settings)); + + if (!state.settings.mem_alloc) { + state.settings.mem_alloc = default_alloc; + } + + if (!state.settings.mem_free) { + state.settings.mem_free = default_free; + } + + memset(&state.uint_max, 0xFF, sizeof(state.uint_max)); + memset(&state.ulong_max, 0xFF, sizeof(state.ulong_max)); + + state.uint_max -= 8; /* limit of how much can be added before next check */ + state.ulong_max -= 8; + + for (state.first_pass = 1; state.first_pass >= 0; --state.first_pass) { + json_uchar uchar; + unsigned char uc_b1, uc_b2, uc_b3, uc_b4; + json_char *string = 0; + unsigned int string_length = 0; + + top = root = 0; + flags = flag_seek_value; + + cur_line = 1; + cur_line_begin = json; + + for (i = json;; ++i) { + json_char b = (i == end ? 0 : *i); + + if (flags & flag_string) { + if (!b) { + sprintf(error, "Unexpected EOF in string (at %d:%d)", + cur_line, e_off); + goto e_failed; + } + + if (string_length > state.uint_max) { + goto e_overflow; + } + + if (flags & flag_escaped) { + flags &= ~flag_escaped; + + switch (b) { + case 'b': + string_add('\b'); + break; + case 'f': + string_add('\f'); + break; + case 'n': + string_add('\n'); + break; + case 'r': + string_add('\r'); + break; + case 't': + string_add('\t'); + break; + case 'u': + + if (end - i < 4 || + (uc_b1 = hex_value(*++i)) == 0xFF || + (uc_b2 = hex_value(*++i)) == 0xFF + || (uc_b3 = hex_value(*++i)) == 0xFF || + (uc_b4 = hex_value(*++i)) == 0xFF) { + sprintf(error, + "Invalid character value `%c` (at %d:%d)", + b, cur_line, e_off); + goto e_failed; + } + + uc_b1 = uc_b1 * 16 + uc_b2; + uc_b2 = uc_b3 * 16 + uc_b4; + + uchar = ((json_char)uc_b1) * 256 + uc_b2; + + if (sizeof(json_char) >= sizeof(json_uchar) || + (uc_b1 == 0 && uc_b2 <= 0x7F)) { + string_add((json_char)uchar); + break; + } + + if (uchar <= 0x7FF) { + if (state.first_pass) { + string_length += 2; + } else { + string[string_length++] = 0xC0 | + ((uc_b2 & + 0xC0) >> + 6) | + ((uc_b1 & 0x7) << 2); + string[string_length++] = 0x80 | + (uc_b2 & 0x3F); + } + + break; + } + + if (state.first_pass) { + string_length += 3; + } else { + string[string_length++] = 0xE0 | + ((uc_b1 & 0xF0) >> 4); + string[string_length++] = 0x80 | + ((uc_b1 & + 0xF) << + 2) | + ((uc_b2 & 0xC0) >> 6); + string[string_length++] = 0x80 | (uc_b2 & 0x3F); + } + + break; + + default: + string_add(b); + } + + continue; + } + + if (b == '\\') { + flags |= flag_escaped; + continue; + } + + if (b == '"') { + if (!state.first_pass) { + string[string_length] = 0; + } + + flags &= ~flag_string; + string = 0; + + switch (top->type) { + case json_string: + + top->u.string.length = string_length; + flags |= flag_next; + + break; + + case json_object: + + if (state.first_pass) { + (*(json_char **)&top->u.object.values) += + string_length + 1; + } else { + top->u.object.values[top->u.object.length].name + = (json_char *)top->_reserved.object_mem; + + top->u.object.values[top->u.object.length]. + name_length + = string_length; + + (*(json_char **)&top->_reserved.object_mem) += + string_length + 1; + } + + flags |= flag_seek_value | flag_need_colon; + continue; + + default: + break; + } + } else { + string_add(b); + continue; + } + } + + if (state.settings.settings & json_enable_comments) { + if (flags & (flag_line_comment | flag_block_comment)) { + if (flags & flag_line_comment) { + if (b == '\r' || b == '\n' || !b) { + flags &= ~flag_line_comment; + --i; /* so null can be reproc'd */ + } + + continue; + } + + if (flags & flag_block_comment) { + if (!b) { + sprintf(error, + "%d:%d: Unexpected EOF in block comment", + cur_line, e_off); + goto e_failed; + } + + if (b == '*' && i < (end - 1) && i[1] == '/') { + flags &= ~flag_block_comment; + ++i; /* skip closing sequence */ + } + + continue; + } + } else if (b == '/') { + if (!(flags & (flag_seek_value | flag_done)) && top->type != + json_object) { + sprintf(error, "%d:%d: Comment not allowed here", + cur_line, e_off); + goto e_failed; + } + + if (++i == end) { + sprintf(error, "%d:%d: EOF unexpected", cur_line, + e_off); + goto e_failed; + } + + switch (b = *i) { + case '/': + flags |= flag_line_comment; + continue; + + case '*': + flags |= flag_block_comment; + continue; + + default: + sprintf(error, + "%d:%d: Unexpected `%c` in comment opening sequence", cur_line, e_off, + b); + goto e_failed; + } + } + } + + if (flags & flag_done) { + if (!b) { + break; + } + + switch (b) { +whitespace: + continue; + + default: + sprintf(error, "%d:%d: Trailing garbage: `%c`", cur_line, + e_off, b); + goto e_failed; + } + } + + if (flags & flag_seek_value) { + switch (b) { +whitespace: + continue; + + case ']': + + if (top->type == json_array) { + flags = + (flags & + ~(flag_need_comma | flag_seek_value)) | flag_next; + } else { + sprintf(error, "%d:%d: Unexpected ]", cur_line, e_off); + goto e_failed; + } + + break; + + default: + + if (flags & flag_need_comma) { + if (b == ',') { + flags &= ~flag_need_comma; + continue; + } else { + sprintf(error, "%d:%d: Expected , before %c", + cur_line, e_off, b); + goto e_failed; + } + } + + if (flags & flag_need_colon) { + if (b == ':') { + flags &= ~flag_need_colon; + continue; + } else { + sprintf(error, "%d:%d: Expected : before %c", + cur_line, e_off, b); + goto e_failed; + } + } + + flags &= ~flag_seek_value; + + switch (b) { + case '{': + + if (!new_value(&state, &top, &root, &alloc, + json_object)) { + goto e_alloc_failure; + } + + continue; + + case '[': + + if (!new_value(&state, &top, &root, &alloc, + json_array)) { + goto e_alloc_failure; + } + + flags |= flag_seek_value; + continue; + + case '"': + + if (!new_value(&state, &top, &root, &alloc, + json_string)) { + goto e_alloc_failure; + } + + flags |= flag_string; + + string = top->u.string.ptr; + string_length = 0; + + continue; + + case 't': + + if ((end - i) < 3 || *(++i) != 'r' || *(++i) != 'u' || + *(++i) != 'e') { + goto e_unknown_value; + } + + if (!new_value(&state, &top, &root, &alloc, + json_boolean)) { + goto e_alloc_failure; + } + + top->u.boolean = 1; + + flags |= flag_next; + break; + + case 'f': + + if ((end - i) < 4 || *(++i) != 'a' || *(++i) != 'l' || + *(++i) != 's' || *(++i) != 'e') { + goto e_unknown_value; + } + + if (!new_value(&state, &top, &root, &alloc, + json_boolean)) { + goto e_alloc_failure; + } + + flags |= flag_next; + break; + + case 'n': + + if ((end - i) < 3 || *(++i) != 'u' || *(++i) != 'l' || + *(++i) != 'l') { + goto e_unknown_value; + } + + if (!new_value(&state, &top, &root, &alloc, + json_null)) { + goto e_alloc_failure; + } + + flags |= flag_next; + break; + + default: + + if (isdigit((uint8_t)b) || b == '-') { + if (!new_value(&state, &top, &root, &alloc, + json_integer)) { + goto e_alloc_failure; + } + + if (!state.first_pass) { + while (isdigit((uint8_t)b) || b == '+' || b == + '-' + || b == 'e' || b == 'E' || b == '.') { + if ((++i) == end) { + b = 0; + break; + } + + b = *i; + } + + flags |= flag_next | flag_reproc; + break; + } + + flags &= ~(flag_num_negative | flag_num_e | + flag_num_e_got_sign | + flag_num_e_negative | + flag_num_zero); + + num_digits = 0; + num_fraction = 0; + num_e = 0; + + if (b != '-') { + flags |= flag_reproc; + break; + } + + flags |= flag_num_negative; + continue; + } else { + sprintf(error, + "%d:%d: Unexpected %c when seeking value", + cur_line, e_off, b); + goto e_failed; + } + } + } + } else { + switch (top->type) { + case json_object: + + switch (b) { +whitespace: + continue; + + case '"': + + if (flags & flag_need_comma) { + sprintf(error, "%d:%d: Expected , before \"", + cur_line, e_off); + goto e_failed; + } + + flags |= flag_string; + + string = (json_char *)top->_reserved.object_mem; + string_length = 0; + + break; + + case '}': + + flags = (flags & ~flag_need_comma) | flag_next; + break; + + case ',': + + if (flags & flag_need_comma) { + flags &= ~flag_need_comma; + break; + } + + default: + + sprintf(error, "%d:%d: Unexpected `%c` in object", + cur_line, e_off, b); + goto e_failed; + } + + break; + + case json_integer: + case json_double: + + if (isdigit((uint8_t)b)) { + ++num_digits; + + if (top->type == json_integer || flags & flag_num_e) { + if (!(flags & flag_num_e)) { + if (flags & flag_num_zero) { + sprintf(error, + "%d:%d: Unexpected `0` before `%c`", + cur_line, e_off, b); + goto e_failed; + } + + if (num_digits == 1 && b == '0') { + flags |= flag_num_zero; + } + } else { + flags |= flag_num_e_got_sign; + num_e = (num_e * 10) + (b - '0'); + continue; + } + + top->u.integer = (top->u.integer * 10) + (b - '0'); + continue; + } + + num_fraction = (num_fraction * 10) + (b - '0'); + continue; + } + + if (b == '+' || b == '-') { + if ((flags & flag_num_e) && + !(flags & flag_num_e_got_sign)) { + flags |= flag_num_e_got_sign; + + if (b == '-') { + flags |= flag_num_e_negative; + } + + continue; + } + } else if (b == '.' && top->type == json_integer) { + if (!num_digits) { + sprintf(error, "%d:%d: Expected digit before `.`", + cur_line, e_off); + goto e_failed; + } + + top->type = json_double; + top->u.dbl = (double)top->u.integer; + + num_digits = 0; + continue; + } + + if (!(flags & flag_num_e)) { + if (top->type == json_double) { + if (!num_digits) { + sprintf(error, + "%d:%d: Expected digit after `.`", + cur_line, e_off); + goto e_failed; + } + + top->u.dbl += ((double)num_fraction) / + (pow(10, (double)num_digits)); + } + + if (b == 'e' || b == 'E') { + flags |= flag_num_e; + + if (top->type == json_integer) { + top->type = json_double; + top->u.dbl = (double)top->u.integer; + } + + num_digits = 0; + flags &= ~flag_num_zero; + + continue; + } + } else { + if (!num_digits) { + sprintf(error, "%d:%d: Expected digit after `e`", + cur_line, e_off); + goto e_failed; + } + + top->u.dbl *= + pow(10, + (double)((flags & + flag_num_e_negative) ? -num_e : num_e)); + } + + if (flags & flag_num_negative) { + if (top->type == json_integer) { + top->u.integer = -top->u.integer; + } else { + top->u.dbl = -top->u.dbl; + } + } + + flags |= flag_next | flag_reproc; + break; + + default: + break; + } + } + + if (flags & flag_reproc) { + flags &= ~flag_reproc; + --i; + } + + if (flags & flag_next) { + flags = (flags & ~flag_next) | flag_need_comma; + + if (!top->parent) { + /* root value done */ + + flags |= flag_done; + continue; + } + + if (top->parent->type == json_array) { + flags |= flag_seek_value; + } + + if (!state.first_pass) { + json_value *parent = top->parent; + + switch (parent->type) { + case json_object: + + parent->u.object.values + [parent->u.object.length].value = top; + + break; + + case json_array: + + parent->u.array.values + [parent->u.array.length] = top; + + break; + + default: + break; + } + } + + if ((++top->parent->u.array.length) > state.uint_max) { + goto e_overflow; + } + + top = top->parent; + + continue; + } + } + + alloc = root; + } + + return root; + +e_unknown_value: + + sprintf(error, "%d:%d: Unknown value", cur_line, e_off); + goto e_failed; + +e_alloc_failure: + + strcpy(error, "Memory allocation failure"); + goto e_failed; + +e_overflow: + + sprintf(error, "%d:%d: Too long (caught overflow)", cur_line, e_off); + goto e_failed; + +e_failed: + + if (error_buf) { + if (*error) { + strcpy(error_buf, error); + } else { + strcpy(error_buf, "Unknown error"); + } + } + + if (state.first_pass) { + alloc = root; + } + + while (alloc) { + top = alloc->_reserved.next_alloc; + state.settings.mem_free(alloc, state.settings.user_data); + alloc = top; + } + + if (!state.first_pass) { + json_value_free_ex(&state.settings, root); + } + + return 0; +} + +json_value * +json_parse(const json_char *json, size_t length) +{ + json_settings settings = { 0UL, 0, NULL, NULL, NULL }; + return json_parse_ex(&settings, json, length, 0); +} + +void +json_value_free_ex(json_settings *settings, json_value *value) +{ + json_value *cur_value; + + if (!value) { + return; + } + + value->parent = 0; + + while (value) { + switch (value->type) { + case json_array: + + if (!value->u.array.length) { + settings->mem_free(value->u.array.values, settings->user_data); + break; + } + + value = value->u.array.values[--value->u.array.length]; + continue; + + case json_object: + + if (!value->u.object.length) { + settings->mem_free(value->u.object.values, settings->user_data); + break; + } + + value = value->u.object.values[--value->u.object.length].value; + continue; + + case json_string: + + settings->mem_free(value->u.string.ptr, settings->user_data); + break; + + default: + break; + } + + cur_value = value; + value = value->parent; + settings->mem_free(cur_value, settings->user_data); + } +} + +void +json_value_free(json_value *value) +{ + json_settings settings = { 0UL, 0, NULL, NULL, NULL }; + settings.mem_free = default_free; + json_value_free_ex(&settings, value); +} diff --git a/shadowsocksr-libev/src/server/json.h b/shadowsocksr-libev/src/server/json.h new file mode 100644 index 0000000..016fc5a --- /dev/null +++ b/shadowsocksr-libev/src/server/json.h @@ -0,0 +1,249 @@ +/* vim: set et ts=3 sw=3 sts=3 ft=c: + * + * Copyright (C) 2012, 2013, 2014 James McLaughlin et al. All rights reserved. + * https://github.com/udp/json-parser + * + * 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. + */ + +#ifndef _JSON_H +#define _JSON_H + +#ifndef json_char +#define json_char char +#endif + +#ifndef json_int_t +#ifndef _MSC_VER +#include +#define json_int_t int64_t +#else +#define json_int_t __int64 +#endif +#endif + +#include + +#ifdef __cplusplus + +#include + +extern "C" +{ +#endif + +typedef struct { + unsigned long max_memory; + int settings; + + /* Custom allocator support (leave null to use malloc/free) + */ + + void * (*mem_alloc)(size_t, int zero, void *user_data); + void (*mem_free)(void *, void *user_data); + + void *user_data; /* will be passed to mem_alloc and mem_free */ +} json_settings; + +#define json_enable_comments 0x01 + +typedef enum { + json_none, + json_object, + json_array, + json_integer, + json_double, + json_string, + json_boolean, + json_null +} json_type; + +extern const struct _json_value json_value_none; + +typedef struct _json_value { + struct _json_value *parent; + + json_type type; + + union { + int boolean; + json_int_t integer; + double dbl; + + struct { + unsigned int length; + json_char *ptr; /* null terminated */ + } string; + + struct { + unsigned int length; + + struct { + json_char *name; + unsigned int name_length; + + struct _json_value *value; + } *values; + +#if defined(__cplusplus) && __cplusplus >= 201103L + decltype(values) begin() const + { + return values; + } + decltype(values) end() const + { + return values + length; + } +#endif + } object; + + struct { + unsigned int length; + struct _json_value **values; + +#if defined(__cplusplus) && __cplusplus >= 201103L + decltype(values) begin() const + { + return values; + } + decltype(values) end() const + { + return values + length; + } +#endif + } array; + } u; + + union { + struct _json_value *next_alloc; + void *object_mem; + } _reserved; + + /* Some C++ operator sugar */ + +#ifdef __cplusplus + +public: + + inline _json_value(){ + memset(this, 0, sizeof(_json_value)); + } + + inline const struct _json_value &operator [] (int index) const { + if (type != json_array || index < 0 + || ((unsigned int)index) >= u.array.length) { + return json_value_none; + } + + return *u.array.values[index]; + } + + inline const struct _json_value &operator [] (const char *index) const { + if (type != json_object) { + return json_value_none; + } + + for (unsigned int i = 0; i < u.object.length; ++i) + if (!strcmp(u.object.values[i].name, index)) { + return *u.object.values[i].value; + } + + return json_value_none; + } + + inline operator const char * () const + { + switch (type) { + case json_string: + return u.string.ptr; + + default: + return ""; + } + } + + inline operator + json_int_t() const + { + switch (type) { + case json_integer: + return u.integer; + + case json_double: + return (json_int_t)u.dbl; + + default: + return 0; + } + } + + inline operator + bool() const + { + if (type != json_boolean) { + return false; + } + + return u.boolean != 0; + } + + inline operator double () const + { + switch (type) { + case json_integer: + return (double)u.integer; + + case json_double: + return u.dbl; + + default: + return 0; + } + } + +#endif +} json_value; + +json_value *json_parse(const json_char *json, + size_t length); + +#define json_error_max 128 +json_value *json_parse_ex(json_settings *settings, + const json_char *json, + size_t length, + char *error); + +void json_value_free(json_value *); + +/* Not usually necessary, unless you used a custom mem_alloc and now want to + * use a custom mem_free. + */ +void json_value_free_ex(json_settings *settings, + json_value *); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/shadowsocksr-libev/src/server/list.c b/shadowsocksr-libev/src/server/list.c new file mode 100644 index 0000000..dde085d --- /dev/null +++ b/shadowsocksr-libev/src/server/list.c @@ -0,0 +1,370 @@ +#include "list.h" + +/// 文件:list_impl.c +/// 功能:实现链表的基本操作 +/// 作者:bluewind +/// 完成时间:2011.5.29 +/// 修改时间:2011.5.31, 2011.7.2 +/// 修改备注:在头节点处添加一个空节点,可以优化添加、删除节点代码 +/// 再次修改,链表增加节点数据data_size,限制数据大小,修改了 +/// 添加复制数据代码,修正重复添加节点后释放节点的Bug,添加了前 +/// 插、排序和遍历功能,7.3 添加tail尾指针,改进后插法性能,并改名 +/// -------------------------------------------------------------- + +void swap_data(Node n1, Node n2); + +/// -------------------------------------------------------------- +// 函数名:list_init +// 功能: 链表初始化 +// 参数: 无 +// 返回值:已初始化链表指针 +// 备注: 链表本身动态分配,由list_destroy函数管理释放 +/// -------------------------------------------------------------- +List list_init(unsigned int data_size) +{ + List list = (List) malloc(sizeof(struct clist)); + if(list != NULL) //内存分配成功 + { + list->head = (Node) malloc(sizeof(node)); //为头节点分配内存 + if(list->head) //内存分配成功 + { + list->head->data = NULL; //初始化头节点 + list->head->next = NULL; + list->data_size = data_size; + list->tail = list->head; + list->size = 0; + + list->add_back = list_add_back; //初始化成员函数 + list->add_front = list_add_front; + list->delete_node = list_delete_node; + list->delete_at = list_delete_at; + list->modify_at = list_modify_at; + list->have_same = list_have_same; + list->have_same_cmp = list_have_same_cmp; + list->foreach = list_foreach; + list->clear = list_clear; + list->sort = list_sort; + list->destroy = list_destroy; + } + } + return list; +} + +/// -------------------------------------------------------------- +// 函数名:list_add_back +// 功能: 添加链表结点 (后插法) +// 参数: l--链表指针,data--链表数据指针,可为任意类型 +// 返回值:int型,为1表示添加成功,为0表示添加失败 +// 备注: 如果链表本身为空或是分配节点内存失败,将返回0 +/// -------------------------------------------------------------- +int list_add_back(List l, void *data) +{ + Node new_node = (Node) malloc(sizeof(node)); + + if(l != NULL && new_node != NULL) //链表本身不为空,且内存申请成功 + { + new_node->data = malloc(l->data_size); + memcpy(new_node->data, data, l->data_size); + new_node->next = NULL; + + l->tail->next = new_node; //添加节点 + l->tail = new_node; //记录尾节点位置 + l->size ++; //链表元素总数加1 + + return 1; + } + + return 0; +} + +/// -------------------------------------------------------------- +// 函数名:list_add_front +// 功能: 添加链表结点 (前插法) +// 参数: l--链表指针,data--链表数据指针,可为任意类型 +// 返回值:int型,为1表示添加成功,为0表示添加失败 +// 备注: 如果链表本身为空或是分配节点内存失败,将返回0 +/// -------------------------------------------------------------- +int list_add_front(List l, void *data) +{ + Node new_node = (Node) malloc(sizeof(node)); + + if(l != NULL && new_node != NULL) + { + new_node->data = malloc(l->data_size); + memcpy(new_node->data, data, l->data_size); + new_node->next = l->head->next; + + l->head->next = new_node; + if(!l->size) //记录尾指针位置 + l->tail = new_node; + l->size ++; + + return 1; + } + + return 0; +} + +/// -------------------------------------------------------------- +// 函数名:list_delete_node +// 功能:删除链表结点 +// 参数:l--链表指针,data--链表数据指针,可为任意类型 +// *pfunc为指向一个数据类型比较的函数指针 +// 返回值:int型,为1表示删除成功,为0表示没有找到匹配数据 +// 备注:*pfunc函数接口参数ndata为节点数据,data为比较数据,返回为真表示匹配数据 +/// -------------------------------------------------------------- +int list_delete_node(List l, void *data, int (*pfunc)(void *ndata, void *data)) +{ + if(l != NULL) + { + Node prev = l->head; //前一个节点 + Node curr = l->head->next; //当前节点 + + while(curr != NULL) + { + if(pfunc(curr->data, data)) //如果找到匹配数据 + { + if(curr == l->tail) //如果是删除尾节点 + l->tail = prev; + + prev->next = prev->next->next; //修改前节点next指针指向下下个节点 + + free(curr->data); //释放节点数据 + free(curr); //释放节点 + + l->size--; //链表元素总数减1 + return 1; //返回真值 + } + prev = prev->next; //没有找到匹配时移动前节点和当前节点 + curr = curr->next; + } + } + + return 0; //没有找到匹配数据 +} + +/// -------------------------------------------------------------- +// 函数名:list_delete_at +// 功能: 修改链表节点元素值 +// 参数: l--链表指针,index--索引值, 范围(0 -- size-1) +// 返回值:int型,为1表示删除成功,为0表示删除失败 +// 备注: 如果链表本身为空或是index为非法值,将返回0 +/// -------------------------------------------------------------- +int list_delete_at(List l, unsigned int index) +{ + unsigned int cindex = 0; + + if(l != NULL && index >= 0 && index < l->size) + { + Node prev = l->head; //前一个节点 + Node curr = l->head->next; //当前节点 + + while(cindex != index) + { + prev = prev->next; + curr = curr->next; + cindex ++; + } + + if(index == (l->size) - 1) + l->tail = prev; + + prev->next = prev->next->next; + free(curr->data); + free(curr); + l->size --; + + return 1; + } + + return 0; +} + +/// -------------------------------------------------------------- +// 函数名:list_modify_at +// 功能: 修改链表节点元素值 +// 参数: l--链表指针,index--索引值, 范围(0 -- size-1) +// data--链表数据指针 +// 返回值:int型,为1表示修改成功,为0表示修改失败 +// 备注: 如果链表本身为空或是index为非法值,将返回0 +/// -------------------------------------------------------------- +int list_modify_at(List l, unsigned int index, void *new_data) +{ + unsigned int cindex = 0; + + if(l != NULL && index >= 0 && index < l->size ) //非空链表,并且index值合法 + { + Node curr = l->head->next; + while(cindex != index) + { + curr = curr->next; + cindex ++; + } + memcpy(curr->data, new_data, l->data_size); + return 1; + } + + return 0; +} + +/// -------------------------------------------------------------- +// 函数名:list_sort +// 功能: 链表排序 +// 参数: l--链表指针,*pfunc为指向一个数据类型比较的函数指针 +// 返回值:无 +// 备注: 使用简单选择排序法,相比冒泡法每次交换,效率高一点 +/// -------------------------------------------------------------- +void list_sort(List l, compare pfunc) +{ + if(l != NULL) + { + Node min, icurr, jcurr; + + icurr = l->head->next; + while(icurr) + { + min = icurr; //记录最小值 + jcurr = icurr->next; //内循环指向下一个节点 + while(jcurr) + { + if(pfunc(min->data, jcurr->data)) //如果找到n+1到最后一个元素最小值 + min = jcurr; //记录下最小值的位置 + + jcurr = jcurr->next; + } + + if(min != icurr) //当最小值位置和n+1元素位置不相同时 + { + swap_data(min, icurr); //才进行交换,减少交换次数 + } + + icurr = icurr->next; + } + } +} + +void swap_data(Node n1, Node n2) +{ + void *temp; + + temp = n2->data; + n2->data = n1->data; + n1->data = temp; +} + + +int list_have_same(List l, void *data, int (*pfunc)(void *ndata, void *data)) +{ + if(l != NULL) + { + Node curr; + + for(curr = l->head->next; curr != NULL; curr = curr->next) + { + if(pfunc(curr->data, data)) + { + return 1; + } + } + } + + return 0; +} + +int list_have_same_cmp(List l, void *data) +{ + if(l != NULL) + { + Node curr; + + for(curr = l->head->next; curr != NULL; curr = curr->next) + { + if(memcmp(curr->data, data, l->data_size)) + { + return 1; + } + } + } + + return 0; +} + +/// -------------------------------------------------------------- +// 函数名:list_foreach +// 功能: 遍历链表元素 +// 参数: l--链表指针,doit为指向一个处理数据的函数指针 +// 返回值:无 +// 备注: doit申明为void (*dofunc)(void *ndata)原型 +/// -------------------------------------------------------------- +void list_foreach(List l, dofunc doit) +{ + if(l != NULL) + { + Node curr; + + for(curr = l->head->next; curr != NULL; curr = curr->next) + { + doit(curr->data); + } + } +} + +/// -------------------------------------------------------------- +// 函数名:list_clear +// 功能: 清空链表元素 +// 参数: l--链表指针 +// 返回值:无 +// 备注: 没有使用先Destroy再Init链表的办法,直接实现 +/// -------------------------------------------------------------- +void list_clear(List l) +{ + if(l != NULL) + { + Node temp; + Node curr = l->head->next; + + while(curr != NULL) + { + temp = curr->next; + + free(curr->data); //释放节点和数据 + free(curr); + + curr = temp; + } + + l->size = 0; //重置链表数据 + l->head->next = NULL; + l->tail = l->head; + } +} + +/// -------------------------------------------------------------- +// 函数名:list_destroy +// 功能: 释放链表 +// 参数: l--链表指针 +// 返回值:空链表指针 +/// -------------------------------------------------------------- +List list_destroy(List l) +{ + if(l != NULL) + { + Node temp; + + while(l->head) + { + temp = l->head->next; + + if(l->head->data != NULL) //如果是头节点就不释放数据空间 + free(l->head->data); //先释放节点数据(但是节点数据里也有指针?) + free(l->head); //再释放节点 + + l->head = temp; + } + + free(l); //释放链表本身占用空间 + l = NULL; + } + + return l; +} diff --git a/shadowsocksr-libev/src/server/list.h b/shadowsocksr-libev/src/server/list.h new file mode 100644 index 0000000..ab49720 --- /dev/null +++ b/shadowsocksr-libev/src/server/list.h @@ -0,0 +1,61 @@ +#ifndef LIST_H_H +#define LIST_H_H + +#include +#include +#include + +typedef struct clist *List; + +typedef int (*compare)(void *ndata, void *data); +typedef void (*dofunc)(void *ndata); + +typedef int (*lpf0)(List l, void *data); +typedef int (*lpf1)(List l, void *data, compare pfunc); +typedef List (*lpf2)(List l); +typedef void (*lpf3)(List l); +typedef void (*lpf4)(List l, dofunc pfunc); +typedef int (*lpf5)(List l, unsigned int index, void *new_data); +typedef void (*lpf6)(List l, compare pfunc); +typedef int (*lpf7)(List l, unsigned int index); + +typedef struct cnode +{ + void *data; + struct cnode *next; +}node, *Node; + +typedef struct clist +{ + Node head; + Node tail; + unsigned int size; + unsigned int data_size; + lpf0 add_back; + lpf0 add_front; + lpf1 delete_node; + lpf1 have_same; + lpf0 have_same_cmp; + lpf4 foreach; + lpf3 clear; + lpf2 destroy; + lpf5 modify_at; + lpf6 sort; + lpf7 delete_at; +}list; + +//初始化链表 +List list_init(unsigned int data_size); +int list_add_back(List l, void *data); +int list_add_front(List l, void *data); +int list_delete_node(List l, void *data, compare pfunc); +int list_delete_at(List l, unsigned int index); +int list_modify_at(List l, unsigned int index, void *new_data); +int list_have_same(List l, void *data, compare pfunc); +int list_have_same_cmp(List l, void *data); +void list_foreach(List l, dofunc doit); +void list_sort(List l, compare pfunc); +void list_clear(List l); +//释放链表 +List list_destroy(List l); +#endif diff --git a/shadowsocksr-libev/src/server/netutils.c b/shadowsocksr-libev/src/server/netutils.c new file mode 100644 index 0000000..3a32b4d --- /dev/null +++ b/shadowsocksr-libev/src/server/netutils.c @@ -0,0 +1,297 @@ +/* + * netutils.c - Network utilities + * + * Copyright (C) 2013 - 2016, Max Lv + * + * This file is part of the shadowsocks-libev. + * + * shadowsocks-libev is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * shadowsocks-libev 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with shadowsocks-libev; see the file COPYING. If not, see + * . + */ + +#include + +#include +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef __MINGW32__ +#include "win32.h" +#define sleep(n) Sleep(1000 * (n)) +#else +#include +#include +#include +#include +#endif + +#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_NET_IF_H) && defined(__linux__) +#include +#include +#define SET_INTERFACE +#endif + +#include "netutils.h" +#include "utils.h" + +#ifndef SO_REUSEPORT +#define SO_REUSEPORT 15 +#endif + +extern int verbose; + +static const char valid_label_bytes[] = + "-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"; + +#if defined(MODULE_LOCAL) +extern int keep_resolving; +#endif + +int +set_reuseport(int socket) +{ + int opt = 1; + return setsockopt(socket, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)); +} + +size_t +get_sockaddr_len(struct sockaddr *addr) +{ + if (addr->sa_family == AF_INET) { + return sizeof(struct sockaddr_in); + } else if (addr->sa_family == AF_INET6) { + return sizeof(struct sockaddr_in6); + } + return 0; +} + +#ifdef SET_INTERFACE +int +setinterface(int socket_fd, const char *interface_name) +{ + struct ifreq interface; + memset(&interface, 0, sizeof(struct ifreq)); + strncpy(interface.ifr_name, interface_name, IFNAMSIZ); + int res = setsockopt(socket_fd, SOL_SOCKET, SO_BINDTODEVICE, &interface, + sizeof(struct ifreq)); + return res; +} + +#endif + +int +bind_to_address(int socket_fd, const char *host) +{ + if (host != NULL) { + struct cork_ip ip; + struct sockaddr_storage storage; + memset(&storage, 0, sizeof(struct sockaddr_storage)); + if (cork_ip_init(&ip, host) != -1) { + if (ip.version == 4) { + struct sockaddr_in *addr = (struct sockaddr_in *)&storage; + dns_pton(AF_INET, host, &addr->sin_addr); + addr->sin_family = AF_INET; + return bind(socket_fd, (struct sockaddr *)addr, sizeof(struct sockaddr_in)); + } else if (ip.version == 6) { + struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&storage; + dns_pton(AF_INET6, host, &addr->sin6_addr); + addr->sin6_family = AF_INET6; + return bind(socket_fd, (struct sockaddr *)addr, sizeof(struct sockaddr_in6)); + } + } + } + return -1; +} + +ssize_t +get_sockaddr(char *host, char *port, + struct sockaddr_storage *storage, int block, + int ipv6first) +{ + struct cork_ip ip; + if (cork_ip_init(&ip, host) != -1) { + if (ip.version == 4) { + struct sockaddr_in *addr = (struct sockaddr_in *)storage; + addr->sin_family = AF_INET; + dns_pton(AF_INET, host, &(addr->sin_addr)); + if (port != NULL) { + addr->sin_port = htons(atoi(port)); + } + } else if (ip.version == 6) { + struct sockaddr_in6 *addr = (struct sockaddr_in6 *)storage; + addr->sin6_family = AF_INET6; + dns_pton(AF_INET6, host, &(addr->sin6_addr)); + if (port != NULL) { + addr->sin6_port = htons(atoi(port)); + } + } + return 0; + } else { + struct addrinfo hints; + struct addrinfo *result, *rp; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; /* Return IPv4 and IPv6 choices */ + hints.ai_socktype = SOCK_STREAM; /* We want a TCP socket */ + + int err, i; + + for (i = 1; i < 8; i++) { + err = getaddrinfo(host, port, &hints, &result); +#if defined(MODULE_LOCAL) + if (!keep_resolving) + break; +#endif + if ((!block || !err)) { + break; + } else { + sleep(pow(2, i)); + LOGE("failed to resolve server name, wait %.0f seconds", pow(2, i)); + } + } + + if (err != 0) { + LOGE("getaddrinfo: %s", gai_strerror(err)); + return -1; + } + + int prefer_af = ipv6first ? AF_INET6 : AF_INET; + for (rp = result; rp != NULL; rp = rp->ai_next) + if (rp->ai_family == prefer_af) { + if (rp->ai_family == AF_INET) + memcpy(storage, rp->ai_addr, sizeof(struct sockaddr_in)); + else if (rp->ai_family == AF_INET6) + memcpy(storage, rp->ai_addr, sizeof(struct sockaddr_in6)); + break; + } + + if (rp == NULL) { + for (rp = result; rp != NULL; rp = rp->ai_next) { + if (rp->ai_family == AF_INET) + memcpy(storage, rp->ai_addr, sizeof(struct sockaddr_in)); + else if (rp->ai_family == AF_INET6) + memcpy(storage, rp->ai_addr, sizeof(struct sockaddr_in6)); + break; + } + } + + if (rp == NULL) { + LOGE("failed to resolve remote addr"); + return -1; + } + + freeaddrinfo(result); + return 0; + } + + return -1; +} + +int +sockaddr_cmp(struct sockaddr_storage *addr1, + struct sockaddr_storage *addr2, socklen_t len) +{ + struct sockaddr_in *p1_in = (struct sockaddr_in *)addr1; + struct sockaddr_in *p2_in = (struct sockaddr_in *)addr2; + struct sockaddr_in6 *p1_in6 = (struct sockaddr_in6 *)addr1; + struct sockaddr_in6 *p2_in6 = (struct sockaddr_in6 *)addr2; + if (p1_in->sin_family < p2_in->sin_family) + return -1; + if (p1_in->sin_family > p2_in->sin_family) + return 1; + /* compare ip4 */ + if (p1_in->sin_family == AF_INET) { + /* just order it, ntohs not required */ + if (p1_in->sin_port < p2_in->sin_port) + return -1; + if (p1_in->sin_port > p2_in->sin_port) + return 1; + return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE); + } else if (p1_in6->sin6_family == AF_INET6) { + /* just order it, ntohs not required */ + if (p1_in6->sin6_port < p2_in6->sin6_port) + return -1; + if (p1_in6->sin6_port > p2_in6->sin6_port) + return 1; + return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr, + INET6_SIZE); + } else { + /* eek unknown type, perform this comparison for sanity. */ + return memcmp(addr1, addr2, len); + } +} + +int +sockaddr_cmp_addr(struct sockaddr_storage *addr1, + struct sockaddr_storage *addr2, socklen_t len) +{ + struct sockaddr_in *p1_in = (struct sockaddr_in *)addr1; + struct sockaddr_in *p2_in = (struct sockaddr_in *)addr2; + struct sockaddr_in6 *p1_in6 = (struct sockaddr_in6 *)addr1; + struct sockaddr_in6 *p2_in6 = (struct sockaddr_in6 *)addr2; + if (p1_in->sin_family < p2_in->sin_family) + return -1; + if (p1_in->sin_family > p2_in->sin_family) + return 1; + /* compare ip4 */ + if (p1_in->sin_family == AF_INET) { + return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE); + } else if (p1_in6->sin6_family == AF_INET6) { + return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr, + INET6_SIZE); + } else { + /* eek unknown type, perform this comparison for sanity. */ + return memcmp(addr1, addr2, len); + } +} + +int +validate_hostname(const char *hostname, const int hostname_len) +{ + if (hostname == NULL) + return 0; + + if (hostname_len < 1 || hostname_len > 255) + return 0; + + if (hostname[0] == '.') + return 0; + + const char *label = hostname; + while (label < hostname + hostname_len) { + size_t label_len = hostname_len - (label - hostname); + char *next_dot = strchr(label, '.'); + if (next_dot != NULL) + label_len = next_dot - label; + + if (label + label_len > hostname + hostname_len) + return 0; + + if (label_len > 63 || label_len < 1) + return 0; + + if (label[0] == '-' || label[label_len - 1] == '-') + return 0; + + if (strspn(label, valid_label_bytes) < label_len) + return 0; + + label += label_len + 1; + } + + return 1; +} diff --git a/shadowsocksr-libev/src/server/netutils.h b/shadowsocksr-libev/src/server/netutils.h new file mode 100644 index 0000000..0725592 --- /dev/null +++ b/shadowsocksr-libev/src/server/netutils.h @@ -0,0 +1,98 @@ +/* + * netutils.h - Network utilities + * + * Copyright (C) 2013 - 2016, Max Lv + * + * This file is part of the shadowsocks-libev. + * + * shadowsocks-libev is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * shadowsocks-libev 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with shadowsocks-libev; see the file COPYING. If not, see + * . + */ + +#ifndef _NETUTILS_H +#define _NETUTILS_H + +#if defined(__linux__) +#include +#elif !defined(__MINGW32__) +#include +#endif + +// only enable TCP_FASTOPEN on linux +#if defined(__linux__) +#include +/* conditional define for TCP_FASTOPEN */ +#ifndef TCP_FASTOPEN +#define TCP_FASTOPEN 23 +#endif +/* conditional define for MSG_FASTOPEN */ +#ifndef MSG_FASTOPEN +#define MSG_FASTOPEN 0x20000000 +#endif +#elif !defined(__APPLE__) +#ifdef TCP_FASTOPEN +#undef TCP_FASTOPEN +#endif +#endif + +/* Backward compatibility for MPTCP_ENABLED between kernel 3 & 4 */ +#ifndef MPTCP_ENABLED +#ifdef TCP_CC_INFO +#define MPTCP_ENABLED 42 +#else +#define MPTCP_ENABLED 26 +#endif +#endif + +/** byte size of ip4 address */ +#define INET_SIZE 4 +/** byte size of ip6 address */ +#define INET6_SIZE 16 + +size_t get_sockaddr_len(struct sockaddr *addr); +ssize_t get_sockaddr(char *host, char *port, + struct sockaddr_storage *storage, int block, + int ipv6first); +int set_reuseport(int socket); + +#ifdef SET_INTERFACE +int setinterface(int socket_fd, const char *interface_name); +#endif + +int bind_to_address(int socket_fd, const char *address); + +/** + * Compare two sockaddrs. Imposes an ordering on the addresses. + * Compares address and port. + * @param addr1: address 1. + * @param addr2: address 2. + * @param len: lengths of addr. + * @return: 0 if addr1 == addr2. -1 if addr1 is smaller, +1 if larger. + */ +int sockaddr_cmp(struct sockaddr_storage *addr1, + struct sockaddr_storage *addr2, socklen_t len); + +/** + * Compare two sockaddrs. Compares address, not the port. + * @param addr1: address 1. + * @param addr2: address 2. + * @param len: lengths of addr. + * @return: 0 if addr1 == addr2. -1 if addr1 is smaller, +1 if larger. + */ +int sockaddr_cmp_addr(struct sockaddr_storage *addr1, + struct sockaddr_storage *addr2, socklen_t len); + +int validate_hostname(const char *hostname, const int hostname_len); + +#endif diff --git a/shadowsocksr-libev/src/server/obfs.c b/shadowsocksr-libev/src/server/obfs.c new file mode 100644 index 0000000..5c885bf --- /dev/null +++ b/shadowsocksr-libev/src/server/obfs.c @@ -0,0 +1,205 @@ +#include +#include + +#include "utils.h" +#include "obfs.h" + +int rand_bytes(uint8_t *output, int len); +#define OBFS_HMAC_SHA1_LEN 10 + +#include "obfsutil.c" +#include "crc32.c" +#include "base64.c" +#include "http_simple.c" +#include "tls1.2_ticket.c" +#include "verify.c" +#include "auth.c" + +void * init_data() { + return malloc(1); +} + +obfs * new_obfs() { + obfs * self = (obfs*)malloc(sizeof(obfs)); + self->l_data = NULL; + return self; +} + +void set_server_info(obfs *self, server_info *server) { + memmove(&self->server, server, sizeof(server_info)); +} + +void get_server_info(obfs *self, server_info *server) { + memmove(server, &self->server, sizeof(server_info)); +} + +void dispose_obfs(obfs *self) { + free(self); +} + +obfs_class * new_obfs_class(char *plugin_name) +{ + if (plugin_name == NULL) + return NULL; + if (strcmp(plugin_name, "origin") == 0) + return NULL; + if (strcmp(plugin_name, "plain") == 0) + return NULL; + init_crc32_table(); + init_shift128plus(); + if (strcmp(plugin_name, "http_simple") == 0) { + obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs)); + plugin->init_data = init_data; + plugin->new_obfs = http_simple_new_obfs; + plugin->get_server_info = get_server_info; + plugin->set_server_info = set_server_info; + plugin->dispose = http_simple_dispose; + + plugin->client_encode = http_simple_client_encode; + plugin->client_decode = http_simple_client_decode; + + plugin->server_encode = http_simple_server_encode; + plugin->server_decode = http_simple_server_decode; + + return plugin; + } else if (strcmp(plugin_name, "http_post") == 0) { + obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs)); + plugin->init_data = init_data; + plugin->new_obfs = http_simple_new_obfs; + plugin->get_server_info = get_server_info; + plugin->set_server_info = set_server_info; + plugin->dispose = http_simple_dispose; + + plugin->client_encode = http_post_client_encode; + plugin->client_decode = http_simple_client_decode; + + plugin->server_encode = http_simple_server_encode; + plugin->server_decode = http_simple_server_decode; + + return plugin; + } else if (strcmp(plugin_name, "tls1.2_ticket_auth") == 0) { + obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs)); + plugin->init_data = tls12_ticket_auth_init_data; + plugin->new_obfs = tls12_ticket_auth_new_obfs; + plugin->get_server_info = get_server_info; + plugin->set_server_info = set_server_info; + plugin->dispose = tls12_ticket_auth_dispose; + + plugin->client_encode = tls12_ticket_auth_client_encode; + plugin->client_decode = tls12_ticket_auth_client_decode; + + plugin->server_encode = tls12_ticket_auth_server_encode; + plugin->server_decode = tls12_ticket_auth_server_decode; + + return plugin; + } else if (strcmp(plugin_name, "verify_simple") == 0) { + obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs)); + plugin->init_data = init_data; + plugin->new_obfs = verify_simple_new_obfs; + plugin->get_server_info = get_server_info; + plugin->set_server_info = set_server_info; + plugin->dispose = verify_simple_dispose; + + plugin->client_pre_encrypt = verify_simple_client_pre_encrypt; + plugin->client_post_decrypt = verify_simple_client_post_decrypt; + plugin->client_udp_pre_encrypt = NULL; + plugin->client_udp_post_decrypt = NULL; + + plugin->server_pre_encrypt = verify_simple_server_pre_encrypt; + plugin->server_post_decrypt = verify_simple_server_post_decrypt; + plugin->server_udp_pre_encrypt = NULL; + plugin->server_udp_post_decrypt = NULL; + + return plugin; + } else if (strcmp(plugin_name, "auth_simple") == 0) { + obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs)); + plugin->init_data = auth_simple_init_data; + plugin->new_obfs = auth_simple_new_obfs; + plugin->get_server_info = get_server_info; + plugin->set_server_info = set_server_info; + plugin->dispose = auth_simple_dispose; + + plugin->client_pre_encrypt = auth_simple_client_pre_encrypt; + plugin->client_post_decrypt = auth_simple_client_post_decrypt; + plugin->client_udp_pre_encrypt = NULL; + plugin->client_udp_post_decrypt = NULL; + + return plugin; + } else if (strcmp(plugin_name, "auth_sha1") == 0) { + obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs)); + plugin->init_data = auth_simple_init_data; + plugin->new_obfs = auth_simple_new_obfs; + plugin->get_server_info = get_server_info; + plugin->set_server_info = set_server_info; + plugin->dispose = auth_simple_dispose; + + plugin->client_pre_encrypt = auth_sha1_client_pre_encrypt; + plugin->client_post_decrypt = auth_sha1_client_post_decrypt; + plugin->client_udp_pre_encrypt = NULL; + plugin->client_udp_post_decrypt = NULL; + + return plugin; + } else if (strcmp(plugin_name, "auth_sha1_v2") == 0) { + obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs)); + plugin->init_data = auth_simple_init_data; + plugin->new_obfs = auth_simple_new_obfs; + plugin->get_server_info = get_server_info; + plugin->set_server_info = set_server_info; + plugin->dispose = auth_simple_dispose; + + plugin->client_pre_encrypt = auth_sha1_v2_client_pre_encrypt; + plugin->client_post_decrypt = auth_sha1_v2_client_post_decrypt; + plugin->client_udp_pre_encrypt = NULL; + plugin->client_udp_post_decrypt = NULL; + + return plugin; + } else if (strcmp(plugin_name, "auth_sha1_v4") == 0) { + obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs)); + plugin->init_data = auth_simple_init_data; + plugin->new_obfs = auth_simple_new_obfs; + plugin->get_server_info = get_server_info; + plugin->set_server_info = set_server_info; + plugin->dispose = auth_simple_dispose; + + plugin->client_pre_encrypt = auth_sha1_v4_client_pre_encrypt; + plugin->client_post_decrypt = auth_sha1_v4_client_post_decrypt; + plugin->client_udp_pre_encrypt = NULL; + plugin->client_udp_post_decrypt = NULL; + + return plugin; + } else if (strcmp(plugin_name, "auth_aes128_md5") == 0) { + obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs)); + plugin->init_data = auth_simple_init_data; + plugin->new_obfs = auth_aes128_md5_new_obfs; + plugin->get_server_info = get_server_info; + plugin->set_server_info = set_server_info; + plugin->dispose = auth_simple_dispose; + + plugin->client_pre_encrypt = auth_aes128_sha1_client_pre_encrypt; + plugin->client_post_decrypt = auth_aes128_sha1_client_post_decrypt; + plugin->client_udp_pre_encrypt = auth_aes128_sha1_client_udp_pre_encrypt; + plugin->client_udp_post_decrypt = auth_aes128_sha1_client_udp_post_decrypt; + + return plugin; + } else if (strcmp(plugin_name, "auth_aes128_sha1") == 0) { + obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs)); + plugin->init_data = auth_simple_init_data; + plugin->new_obfs = auth_aes128_sha1_new_obfs; + plugin->get_server_info = get_server_info; + plugin->set_server_info = set_server_info; + plugin->dispose = auth_simple_dispose; + + plugin->client_pre_encrypt = auth_aes128_sha1_client_pre_encrypt; + plugin->client_post_decrypt = auth_aes128_sha1_client_post_decrypt; + plugin->client_udp_pre_encrypt = auth_aes128_sha1_client_udp_pre_encrypt; + plugin->client_udp_post_decrypt = auth_aes128_sha1_client_udp_post_decrypt; + + return plugin; + } + LOGE("Load obfs '%s' failed", plugin_name); + return NULL; +} + +void free_obfs_class(obfs_class *plugin) { + free(plugin); +} diff --git a/shadowsocksr-libev/src/server/obfs.h b/shadowsocksr-libev/src/server/obfs.h new file mode 100644 index 0000000..74c60c9 --- /dev/null +++ b/shadowsocksr-libev/src/server/obfs.h @@ -0,0 +1,100 @@ +/* + * obfs.h - Define shadowsocksR server's buffers and callbacks + * + * Copyright (C) 2015 - 2016, Break Wa11 + */ + +#ifndef _OBFS_H +#define _OBFS_H + +#include +#include + +typedef struct server_info { + char host[64]; + uint16_t port; + char *param; + void *g_data; + uint8_t *iv; + size_t iv_len; + uint8_t *recv_iv; + size_t recv_iv_len; + uint8_t *key; + size_t key_len; + int head_len; + size_t tcp_mss; +}server_info; + +typedef struct obfs { + server_info server; + void *l_data; +}obfs; + +typedef struct obfs_class { + void * (*init_data)(); + obfs * (*new_obfs)(); + void (*get_server_info)(obfs *self, server_info *server); + void (*set_server_info)(obfs *self, server_info *server); + void (*dispose)(obfs *self); + + int (*client_pre_encrypt)(obfs *self, + char **pplaindata, + int datalength, + size_t* capacity); + int (*client_encode)(obfs *self, + char **pencryptdata, + int datalength, + size_t* capacity); + int (*client_decode)(obfs *self, + char **pencryptdata, + int datalength, + size_t* capacity, + int *needsendback); + int (*client_post_decrypt)(obfs *self, + char **pplaindata, + int datalength, + size_t* capacity); + int (*client_udp_pre_encrypt)(obfs *self, + char **pplaindata, + int datalength, + size_t* capacity); + int (*client_udp_post_decrypt)(obfs *self, + char **pplaindata, + int datalength, + size_t* capacity); + int (*server_pre_encrypt)(obfs *self, + char **pplaindata, + int datalength, + size_t* capacity); + int (*server_post_decrypt)(obfs *self, + char **pplaindata, + int datalength, + size_t* capacity); + int (*server_udp_pre_encrypt)(obfs *self, + char **pplaindata, + int datalength, + size_t* capacity); + int (*server_udp_post_decrypt)(obfs *self, + char **pplaindata, + int datalength, + size_t* capacity); + int (*server_encode)(obfs *self, + char **pencryptdata, + int datalength, + size_t* capacity); + int (*server_decode)(obfs *self, + char **pencryptdata, + int datalength, + size_t* capacity, + int *needsendback); +}obfs_class; + +obfs_class * new_obfs_class(char *plugin_name); +void free_obfs_class(obfs_class *plugin); + +void set_server_info(obfs *self, server_info *server); +void get_server_info(obfs *self, server_info *server); +obfs * new_obfs(); +void dispose_obfs(obfs *self); + +#endif // _OBFS_H diff --git a/shadowsocksr-libev/src/server/obfsutil.c b/shadowsocksr-libev/src/server/obfsutil.c new file mode 100644 index 0000000..d00959b --- /dev/null +++ b/shadowsocksr-libev/src/server/obfsutil.c @@ -0,0 +1,36 @@ +int get_head_size(char *plaindata, int size, int def_size) { + if (plaindata == NULL || size < 2) + return def_size; + int head_type = plaindata[0] & 0x7; + if (head_type == 1) + return 7; + if (head_type == 4) + return 19; + if (head_type == 3) + return 4 + plaindata[1]; + return def_size; +} + +static int shift128plus_init_flag = 0; +static uint64_t shift128plus_s[2] = {0x10000000, 0xFFFFFFFF}; + +void init_shift128plus(void) { + if (shift128plus_init_flag == 0) { + shift128plus_init_flag = 1; + uint32_t seed = time(NULL); + shift128plus_s[0] = seed | 0x100000000L; + shift128plus_s[1] = ((uint64_t)seed << 32) | 0x1; + } +} + +uint64_t xorshift128plus(void) { + uint64_t x = shift128plus_s[0]; + uint64_t const y = shift128plus_s[1]; + shift128plus_s[0] = y; + x ^= x << 23; // a + x ^= x >> 17; // b + x ^= y ^ (y >> 26); // c + shift128plus_s[1] = x; + return x + y; +} + diff --git a/shadowsocksr-libev/src/server/protocol.h b/shadowsocksr-libev/src/server/protocol.h new file mode 100644 index 0000000..eaa866e --- /dev/null +++ b/shadowsocksr-libev/src/server/protocol.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2014, Dustin Lundquist + * 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 HOLDER 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. + */ +#ifndef PROTOCOL_H +#define PROTOCOL_H + +typedef struct protocol { + const int default_port; + int(*const parse_packet)(const char *, size_t, char **); +} protocol_t; + +#endif diff --git a/shadowsocksr-libev/src/server/resolv.c b/shadowsocksr-libev/src/server/resolv.c new file mode 100644 index 0000000..f580d06 --- /dev/null +++ b/shadowsocksr-libev/src/server/resolv.c @@ -0,0 +1,444 @@ +/* + * Copyright (c) 2014, Dustin Lundquist + * 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 HOLDER 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include + +#ifdef __MINGW32__ +#include "win32.h" +#else +#include +#include +#include +#include +#endif + +#include "resolv.h" +#include "utils.h" +#include "netutils.h" + +/* + * Implement DNS resolution interface using libudns + */ + +struct ResolvQuery { + void (*client_cb)(struct sockaddr *, void *); + void (*client_free_cb)(void *); + void *client_cb_data; + struct dns_query *queries[2]; + size_t response_count; + struct sockaddr **responses; + uint16_t port; +}; + +extern int verbose; + +static struct ev_io resolv_io_watcher; +static struct ev_timer resolv_timeout_watcher; +static const int MODE_IPV4_ONLY = 0; +static const int MODE_IPV6_ONLY = 1; +static const int MODE_IPV4_FIRST = 2; +static const int MODE_IPV6_FIRST = 3; +static int resolv_mode = 0; + +static void resolv_sock_cb(struct ev_loop *, struct ev_io *, int); +static void resolv_timeout_cb(struct ev_loop *, struct ev_timer *, int); +static void dns_query_v4_cb(struct dns_ctx *, struct dns_rr_a4 *, void *); +static void dns_query_v6_cb(struct dns_ctx *, struct dns_rr_a6 *, void *); +static void dns_timer_setup_cb(struct dns_ctx *, int, void *); +static void process_client_callback(struct ResolvQuery *); +static inline int all_queries_are_null(struct ResolvQuery *); +static struct sockaddr *choose_ipv4_first(struct ResolvQuery *); +static struct sockaddr *choose_ipv6_first(struct ResolvQuery *); +static struct sockaddr *choose_any(struct ResolvQuery *); + +int +resolv_init(struct ev_loop *loop, char **nameservers, int nameserver_num, int ipv6first) +{ + if (ipv6first) + resolv_mode = MODE_IPV6_FIRST; + else + resolv_mode = MODE_IPV4_FIRST; + + struct dns_ctx *ctx = &dns_defctx; + if (nameservers == NULL) { + /* Nameservers not specified, use system resolver config */ + dns_init(ctx, 0); + } else { + dns_reset(ctx); + + for (int i = 0; i < nameserver_num; i++) { + char *server = nameservers[i]; + dns_add_serv(ctx, server); + } + } + + int sockfd = dns_open(ctx); + if (sockfd < 0) { + FATAL("Failed to open DNS resolver socket"); + } + + if (nameserver_num == 1 && nameservers != NULL) { + if (strncmp("127.0.0.1", nameservers[0], 9) == 0 + || strncmp("::1", nameservers[0], 3) == 0) { + if (verbose) { + LOGI("bind UDP resolver to %s", nameservers[0]); + } + if (bind_to_address(sockfd, nameservers[0]) == -1) + ERROR("bind_to_address"); + } + } + +#ifdef __MINGW32__ + setnonblocking(sockfd); +#else + int flags = fcntl(sockfd, F_GETFL, 0); + fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); +#endif + + ev_io_init(&resolv_io_watcher, resolv_sock_cb, sockfd, EV_READ); + resolv_io_watcher.data = ctx; + + ev_io_start(loop, &resolv_io_watcher); + + ev_timer_init(&resolv_timeout_watcher, resolv_timeout_cb, 0.0, 0.0); + resolv_timeout_watcher.data = ctx; + + dns_set_tmcbck(ctx, dns_timer_setup_cb, loop); + + return sockfd; +} + +void +resolv_shutdown(struct ev_loop *loop) +{ + struct dns_ctx *ctx = (struct dns_ctx *)resolv_io_watcher.data; + + ev_io_stop(loop, &resolv_io_watcher); + + if (ev_is_active(&resolv_timeout_watcher)) { + ev_timer_stop(loop, &resolv_timeout_watcher); + } + + dns_close(ctx); +} + +struct ResolvQuery * +resolv_query(const char *hostname, void (*client_cb)(struct sockaddr *, void *), + void (*client_free_cb)(void *), void *client_cb_data, + uint16_t port) +{ + struct dns_ctx *ctx = (struct dns_ctx *)resolv_io_watcher.data; + + /* + * Wrap udns's call back in our own + */ + struct ResolvQuery *cb_data = ss_malloc(sizeof(struct ResolvQuery)); + if (cb_data == NULL) { + LOGE("Failed to allocate memory for DNS query callback data."); + return NULL; + } + memset(cb_data, 0, sizeof(struct ResolvQuery)); + + cb_data->client_cb = client_cb; + cb_data->client_free_cb = client_free_cb; + cb_data->client_cb_data = client_cb_data; + memset(cb_data->queries, 0, sizeof(cb_data->queries)); + cb_data->response_count = 0; + cb_data->responses = NULL; + cb_data->port = port; + + /* Submit A and AAAA queries */ + if (resolv_mode != MODE_IPV6_ONLY) { + cb_data->queries[0] = dns_submit_a4(ctx, + hostname, 0, + dns_query_v4_cb, cb_data); + if (cb_data->queries[0] == NULL) { + LOGE("Failed to submit DNS query: %s", + dns_strerror(dns_status(ctx))); + } + } + + if (resolv_mode != MODE_IPV4_ONLY) { + cb_data->queries[1] = dns_submit_a6(ctx, + hostname, 0, + dns_query_v6_cb, cb_data); + if (cb_data->queries[1] == NULL) { + LOGE("Failed to submit DNS query: %s", + dns_strerror(dns_status(ctx))); + } + } + + if (all_queries_are_null(cb_data)) { + if (cb_data->client_free_cb != NULL) { + cb_data->client_free_cb(cb_data->client_cb_data); + } + ss_free(cb_data); + } + + return cb_data; +} + +void +resolv_cancel(struct ResolvQuery *query_handle) +{ + struct ResolvQuery *cb_data = (struct ResolvQuery *)query_handle; + struct dns_ctx *ctx = (struct dns_ctx *)resolv_io_watcher.data; + + for (int i = 0; i < sizeof(cb_data->queries) / sizeof(cb_data->queries[0]); + i++) + if (cb_data->queries[i] != NULL) { + dns_cancel(ctx, cb_data->queries[i]); + ss_free(cb_data->queries[i]); + } + + if (cb_data->client_free_cb != NULL) { + cb_data->client_free_cb(cb_data->client_cb_data); + } + + ss_free(cb_data); +} + +/* + * DNS UDP socket activity callback + */ +static void +resolv_sock_cb(struct ev_loop *loop, struct ev_io *w, int revents) +{ + struct dns_ctx *ctx = (struct dns_ctx *)w->data; + + if (revents & EV_READ) { + dns_ioevent(ctx, ev_now(loop)); + } +} + +/* + * Wrapper for client callback we provide to udns + */ +static void +dns_query_v4_cb(struct dns_ctx *ctx, struct dns_rr_a4 *result, void *data) +{ + struct ResolvQuery *cb_data = (struct ResolvQuery *)data; + + if (result == NULL) { + if (verbose) { + LOGI("IPv4 resolv: %s", dns_strerror(dns_status(ctx))); + } + } else if (result->dnsa4_nrr > 0) { + struct sockaddr **new_responses = ss_realloc(cb_data->responses, + (cb_data->response_count + + result->dnsa4_nrr) * + sizeof(struct sockaddr *)); + if (new_responses == NULL) { + LOGE("Failed to allocate memory for additional DNS responses"); + } else { + cb_data->responses = new_responses; + + for (int i = 0; i < result->dnsa4_nrr; i++) { + struct sockaddr_in *sa = + (struct sockaddr_in *)ss_malloc(sizeof(struct sockaddr_in)); + sa->sin_family = AF_INET; + sa->sin_port = cb_data->port; + sa->sin_addr = result->dnsa4_addr[i]; + + cb_data->responses[cb_data->response_count] = + (struct sockaddr *)sa; + if (cb_data->responses[cb_data->response_count] == NULL) { + LOGE( + "Failed to allocate memory for DNS query result address"); + } else { + cb_data->response_count++; + } + } + } + } + + ss_free(result); + cb_data->queries[0] = NULL; /* mark A query as being completed */ + + /* Once all queries have completed, call client callback */ + if (all_queries_are_null(cb_data)) { + return process_client_callback(cb_data); + } +} + +static void +dns_query_v6_cb(struct dns_ctx *ctx, struct dns_rr_a6 *result, void *data) +{ + struct ResolvQuery *cb_data = (struct ResolvQuery *)data; + + if (result == NULL) { + if (verbose) { + LOGI("IPv6 resolv: %s", dns_strerror(dns_status(ctx))); + } + } else if (result->dnsa6_nrr > 0) { + struct sockaddr **new_responses = ss_realloc(cb_data->responses, + (cb_data->response_count + + result->dnsa6_nrr) * + sizeof(struct sockaddr *)); + if (new_responses == NULL) { + LOGE("Failed to allocate memory for additional DNS responses"); + } else { + cb_data->responses = new_responses; + + for (int i = 0; i < result->dnsa6_nrr; i++) { + struct sockaddr_in6 *sa = + (struct sockaddr_in6 *)ss_malloc(sizeof(struct sockaddr_in6)); + sa->sin6_family = AF_INET6; + sa->sin6_port = cb_data->port; + sa->sin6_addr = result->dnsa6_addr[i]; + + cb_data->responses[cb_data->response_count] = + (struct sockaddr *)sa; + if (cb_data->responses[cb_data->response_count] == NULL) { + LOGE( + "Failed to allocate memory for DNS query result address"); + } else { + cb_data->response_count++; + } + } + } + } + + ss_free(result); + cb_data->queries[1] = NULL; /* mark AAAA query as being completed */ + + /* Once all queries have completed, call client callback */ + if (all_queries_are_null(cb_data)) { + return process_client_callback(cb_data); + } +} + +/* + * Called once all queries have been completed + */ +static void +process_client_callback(struct ResolvQuery *cb_data) +{ + struct sockaddr *best_address = NULL; + + if (resolv_mode == MODE_IPV4_FIRST) { + best_address = choose_ipv4_first(cb_data); + } else if (resolv_mode == MODE_IPV6_FIRST) { + best_address = choose_ipv6_first(cb_data); + } else { + best_address = choose_any(cb_data); + } + + cb_data->client_cb(best_address, cb_data->client_cb_data); + + for (int i = 0; i < cb_data->response_count; i++) + ss_free(cb_data->responses[i]); + + ss_free(cb_data->responses); + if (cb_data->client_free_cb != NULL) { + cb_data->client_free_cb(cb_data->client_cb_data); + } + ss_free(cb_data); +} + +static struct sockaddr * +choose_ipv4_first(struct ResolvQuery *cb_data) +{ + for (int i = 0; i < cb_data->response_count; i++) + if (cb_data->responses[i]->sa_family == AF_INET) { + return cb_data->responses[i]; + } + + return choose_any(cb_data); +} + +static struct sockaddr * +choose_ipv6_first(struct ResolvQuery *cb_data) +{ + for (int i = 0; i < cb_data->response_count; i++) + if (cb_data->responses[i]->sa_family == AF_INET6) { + return cb_data->responses[i]; + } + + return choose_any(cb_data); +} + +static struct sockaddr * +choose_any(struct ResolvQuery *cb_data) +{ + if (cb_data->response_count >= 1) { + return cb_data->responses[0]; + } + + return NULL; +} + +/* + * DNS timeout callback + */ +static void +resolv_timeout_cb(struct ev_loop *loop, struct ev_timer *w, int revents) +{ + struct dns_ctx *ctx = (struct dns_ctx *)w->data; + + if (revents & EV_TIMER) { + dns_timeouts(ctx, 30, ev_now(loop)); + } +} + +/* + * Callback to setup DNS timeout callback + */ +static void +dns_timer_setup_cb(struct dns_ctx *ctx, int timeout, void *data) +{ + struct ev_loop *loop = (struct ev_loop *)data; + + if (ev_is_active(&resolv_timeout_watcher)) { + ev_timer_stop(loop, &resolv_timeout_watcher); + } + + if (ctx != NULL && timeout >= 0) { + ev_timer_set(&resolv_timeout_watcher, timeout, 0.0); + ev_timer_start(loop, &resolv_timeout_watcher); + } +} + +static inline int +all_queries_are_null(struct ResolvQuery *cb_data) +{ + int result = 1; + + for (int i = 0; i < sizeof(cb_data->queries) / sizeof(cb_data->queries[0]); + i++) + result = result && cb_data->queries[i] == NULL; + + return result; +} diff --git a/shadowsocksr-libev/src/server/resolv.h b/shadowsocksr-libev/src/server/resolv.h new file mode 100644 index 0000000..0552922 --- /dev/null +++ b/shadowsocksr-libev/src/server/resolv.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014, Dustin Lundquist + * 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 HOLDER 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. + */ +#ifndef RESOLV_H +#define RESOLV_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#ifdef __MINGW32__ +#include "win32.h" +#else +#include +#endif + +struct ResolvQuery; + +int resolv_init(struct ev_loop *, char **, int, int); +struct ResolvQuery *resolv_query(const char *, void (*)(struct sockaddr *, + void *), void (*)( + void *), void *, uint16_t); +void resolv_cancel(struct ResolvQuery *); +void resolv_shutdown(struct ev_loop *); + +#endif diff --git a/shadowsocksr-libev/src/server/rule.c b/shadowsocksr-libev/src/server/rule.c new file mode 100644 index 0000000..8aae04e --- /dev/null +++ b/shadowsocksr-libev/src/server/rule.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2011 and 2012, Dustin Lundquist + * Copyright (c) 2011 Manuel Kasper + * 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 HOLDER 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#ifdef __MINGW32__ +extern void ss_error(const char *s); +#endif + +#include "rule.h" +#include "utils.h" + +static void free_rule(rule_t *); + +rule_t * +new_rule() +{ + rule_t *rule; + + rule = calloc(1, sizeof(rule_t)); + if (rule == NULL) { + ERROR("malloc"); + return NULL; + } + + return rule; +} + +int +accept_rule_arg(rule_t *rule, const char *arg) +{ + if (rule->pattern == NULL) { + rule->pattern = strdup(arg); + if (rule->pattern == NULL) { + ERROR("strdup failed"); + return -1; + } + } else { + LOGE("Unexpected table rule argument: %s", arg); + return -1; + } + + return 1; +} + +void +add_rule(struct cork_dllist *rules, rule_t *rule) +{ + cork_dllist_add(rules, &rule->entries); +} + +int +init_rule(rule_t *rule) +{ + if (rule->pattern_re == NULL) { + const char *reerr; + int reerroffset; + + rule->pattern_re = + pcre_compile(rule->pattern, 0, &reerr, &reerroffset, NULL); + if (rule->pattern_re == NULL) { + LOGE("Regex compilation of \"%s\" failed: %s, offset %d", + rule->pattern, reerr, reerroffset); + return 0; + } + } + + return 1; +} + +rule_t * +lookup_rule(const struct cork_dllist *rules, const char *name, size_t name_len) +{ + struct cork_dllist_item *curr, *next; + + if (name == NULL) { + name = ""; + name_len = 0; + } + + cork_dllist_foreach_void(rules, curr, next) { + rule_t *rule = cork_container_of(curr, rule_t, entries); + if (pcre_exec(rule->pattern_re, NULL, + name, name_len, 0, 0, NULL, 0) >= 0) + return rule; + } + + return NULL; +} + +void +remove_rule(rule_t *rule) +{ + cork_dllist_remove(&rule->entries); + free_rule(rule); +} + +static void +free_rule(rule_t *rule) +{ + if (rule == NULL) + return; + + ss_free(rule->pattern); + if (rule->pattern_re != NULL) + pcre_free(rule->pattern_re); + ss_free(rule); +} diff --git a/shadowsocksr-libev/src/server/rule.h b/shadowsocksr-libev/src/server/rule.h new file mode 100644 index 0000000..015bc42 --- /dev/null +++ b/shadowsocksr-libev/src/server/rule.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2011 and 2012, Dustin Lundquist + * Copyright (c) 2011 Manuel Kasper + * 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 HOLDER 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. + */ +#ifndef RULE_H +#define RULE_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#ifdef HAVE_PCRE_H +#include +#elif HAVE_PCRE_PCRE_H +#include +#endif + +typedef struct rule { + char *pattern; + + /* Runtime fields */ + pcre *pattern_re; + + struct cork_dllist_item entries; +} rule_t; + +void add_rule(struct cork_dllist *, rule_t *); +int init_rule(rule_t *); +rule_t *lookup_rule(const struct cork_dllist *, const char *, size_t); +void remove_rule(rule_t *); +rule_t *new_rule(); +int accept_rule_arg(rule_t *, const char *); + +#endif diff --git a/shadowsocksr-libev/src/server/server.c b/shadowsocksr-libev/src/server/server.c new file mode 100644 index 0000000..65b0e42 --- /dev/null +++ b/shadowsocksr-libev/src/server/server.c @@ -0,0 +1,2209 @@ +/* + * server.c - Provide shadowsocks service + * + * Copyright (C) 2013 - 2016, Max Lv + * + * This file is part of the shadowsocks-libev. + * + * shadowsocks-libev is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * shadowsocks-libev 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with shadowsocks-libev; see the file COPYING. If not, see + * . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef __MINGW32__ +#include +#include +#include +#include +#include +#include +#endif + +#include +#include + +#ifdef __MINGW32__ +#include "win32.h" +#endif + +#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_NET_IF_H) && defined(__linux__) +#include +#include +#define SET_INTERFACE +#endif + +#include "netutils.h" +#include "utils.h" +#include "acl.h" +#include "server.h" + +#include "obfs.c" // I don't want to modify makefile + +#ifndef EAGAIN +#define EAGAIN EWOULDBLOCK +#endif + +#ifndef EWOULDBLOCK +#define EWOULDBLOCK EAGAIN +#endif + +#ifndef BUF_SIZE +#define BUF_SIZE 2048 +#endif + +#ifndef SSMAXCONN +#define SSMAXCONN 1024 +#endif + +#ifndef UPDATE_INTERVAL +#define UPDATE_INTERVAL 30 +#endif + +static void signal_cb(EV_P_ ev_signal *w, int revents); +static void accept_cb(EV_P_ ev_io *w, int revents); +static void server_send_cb(EV_P_ ev_io *w, int revents); +static void server_recv_cb(EV_P_ ev_io *w, int revents); +static void remote_recv_cb(EV_P_ ev_io *w, int revents); +static void remote_send_cb(EV_P_ ev_io *w, int revents); +static void server_timeout_cb(EV_P_ ev_timer *watcher, int revents); +static void block_list_clear_cb(EV_P_ ev_timer *watcher, int revents); + +static remote_t *new_remote(int fd); +static server_t *new_server(int fd, listen_ctx_t *listener); +static remote_t *connect_to_remote(EV_P_ struct addrinfo *res, + server_t *server); + +static void free_remote(remote_t *remote); +static void close_and_free_remote(EV_P_ remote_t *remote); +static void free_server(server_t *server); +static void close_and_free_server(EV_P_ server_t *server); +static void server_resolve_cb(struct sockaddr *addr, void *data); +static void query_free_cb(void *data); + +static size_t parse_header_len(const char atyp, const char *data, size_t offset); +static int is_header_complete(const buffer_t *buf); + +int verbose = 0; + +static int acl = 0; +static int mode = TCP_ONLY; +static int auth = 0; +static int ipv6first = 0; + +static int protocol_compatible = 0;//SSR +static int obfs_compatible = 0;//SSR + +static int fast_open = 0; +#ifdef HAVE_SETRLIMIT +static int nofile = 0; +#endif +static int remote_conn = 0; +static int server_conn = 0; + +static char *bind_address = NULL; +static char *server_port = NULL; +static char *manager_address = NULL; +uint64_t tx = 0; +uint64_t rx = 0; +ev_timer stat_update_watcher; +ev_timer block_list_watcher; + +static struct cork_dllist connections; + +static void +stat_update_cb(EV_P_ ev_timer *watcher, int revents) +{ + struct sockaddr_un svaddr, claddr; + int sfd = -1; + size_t msgLen; + char resp[BUF_SIZE]; + + if (verbose) { + LOGI("update traffic stat: tx: %" PRIu64 " rx: %" PRIu64 "", tx, rx); + } + + snprintf(resp, BUF_SIZE, "stat: {\"%s\":%" PRIu64 "}", server_port, tx + rx); + msgLen = strlen(resp) + 1; + + ss_addr_t ip_addr = { .host = NULL, .port = NULL }; + parse_addr(manager_address, &ip_addr); + + if (ip_addr.host == NULL || ip_addr.port == NULL) { + sfd = socket(AF_UNIX, SOCK_DGRAM, 0); + if (sfd == -1) { + ERROR("stat_socket"); + return; + } + + memset(&claddr, 0, sizeof(struct sockaddr_un)); + claddr.sun_family = AF_UNIX; + snprintf(claddr.sun_path, sizeof(claddr.sun_path), "/tmp/shadowsocks.%s", server_port); + + unlink(claddr.sun_path); + + if (bind(sfd, (struct sockaddr *)&claddr, sizeof(struct sockaddr_un)) == -1) { + ERROR("stat_bind"); + close(sfd); + return; + } + + memset(&svaddr, 0, sizeof(struct sockaddr_un)); + svaddr.sun_family = AF_UNIX; + strncpy(svaddr.sun_path, manager_address, sizeof(svaddr.sun_path) - 1); + + if (sendto(sfd, resp, strlen(resp) + 1, 0, (struct sockaddr *)&svaddr, + sizeof(struct sockaddr_un)) != msgLen) { + ERROR("stat_sendto"); + close(sfd); + return; + } + + unlink(claddr.sun_path); + } else { + struct sockaddr_storage storage; + memset(&storage, 0, sizeof(struct sockaddr_storage)); + if (get_sockaddr(ip_addr.host, ip_addr.port, &storage, 0, ipv6first) == -1) { + ERROR("failed to parse the manager addr"); + return; + } + + sfd = socket(storage.ss_family, SOCK_DGRAM, 0); + + if (sfd == -1) { + ERROR("stat_socket"); + return; + } + + size_t addr_len = get_sockaddr_len((struct sockaddr *)&storage); + if (sendto(sfd, resp, strlen(resp) + 1, 0, (struct sockaddr *)&storage, + addr_len) != msgLen) { + ERROR("stat_sendto"); + close(sfd); + return; + } + } + + close(sfd); +} + +static void +free_connections(struct ev_loop *loop) +{ + struct cork_dllist_item *curr, *next; + cork_dllist_foreach_void(&connections, curr, next) { + server_t *server = cork_container_of(curr, server_t, entries); + remote_t *remote = server->remote; + close_and_free_server(loop, server); + close_and_free_remote(loop, remote); + } +} + +static size_t +parse_header_len(const char atyp, const char *data, size_t offset) +{ + size_t len = 0; + if ((atyp & ADDRTYPE_MASK) == 1) { + // IP V4 + len += sizeof(struct in_addr); + } else if ((atyp & ADDRTYPE_MASK) == 3) { + // Domain name + uint8_t name_len = *(uint8_t *)(data + offset); + len += name_len + 1; + } else if ((atyp & ADDRTYPE_MASK) == 4) { + // IP V6 + len += sizeof(struct in6_addr); + } else { + return 0; + } + len += 2; + return len; +} + +static int +is_header_complete(const buffer_t *buf) +{ + size_t header_len = 0; + size_t buf_len = buf->len; + + char atyp = buf->array[header_len]; + + // 1 byte for atyp + header_len++; + + if ((atyp & ADDRTYPE_MASK) == 1) { + // IP V4 + header_len += sizeof(struct in_addr); + } else if ((atyp & ADDRTYPE_MASK) == 3) { + // Domain name + // domain len + len of domain + if (buf_len < header_len + 1) + return 0; + uint8_t name_len = *(uint8_t *)(buf->array + header_len); + header_len += name_len + 1; + } else if ((atyp & ADDRTYPE_MASK) == 4) { + // IP V6 + header_len += sizeof(struct in6_addr); + } else { + return -1; + } + + // len of port + header_len += 2; + + // size of ONETIMEAUTH_BYTES + if (auth || (atyp & ONETIMEAUTH_FLAG)) { + header_len += ONETIMEAUTH_BYTES; + } + + return buf_len >= header_len ? 1 : 0; +} + +static char * +get_peer_name(int fd) +{ + static char peer_name[INET6_ADDRSTRLEN] = { 0 }; + struct sockaddr_storage addr; + socklen_t len = sizeof(struct sockaddr_storage); + memset(&addr, 0, len); + memset(peer_name, 0, INET6_ADDRSTRLEN); + int err = getpeername(fd, (struct sockaddr *)&addr, &len); + if (err == 0) { + if (addr.ss_family == AF_INET) { + struct sockaddr_in *s = (struct sockaddr_in *)&addr; + dns_ntop(AF_INET, &s->sin_addr, peer_name, INET_ADDRSTRLEN); + } else if (addr.ss_family == AF_INET6) { + struct sockaddr_in6 *s = (struct sockaddr_in6 *)&addr; + dns_ntop(AF_INET6, &s->sin6_addr, peer_name, INET6_ADDRSTRLEN); + } + } else { + return NULL; + } + return peer_name; +} + +#ifdef __linux__ +static void +set_linger(int fd) +{ + struct linger so_linger; + memset(&so_linger, 0, sizeof(struct linger)); + so_linger.l_onoff = 1; + so_linger.l_linger = 0; + setsockopt(fd, SOL_SOCKET, SO_LINGER, &so_linger, sizeof so_linger); +} +#endif + +static void +reset_addr(int fd) +{ + char *peer_name; + peer_name = get_peer_name(fd); + if (peer_name != NULL) { + remove_from_block_list(peer_name); + } +} + +static void +report_addr(int fd, int err_level) +{ +#ifdef __linux__ + set_linger(fd); +#endif + + char *peer_name; + peer_name = get_peer_name(fd); + if (peer_name != NULL) { + LOGE("failed to handshake with %s", peer_name); + update_block_list(peer_name, err_level); + } +} + +int +setfastopen(int fd) +{ + int s = 0; +#ifdef TCP_FASTOPEN + if (fast_open) { +#ifdef __APPLE__ + int opt = 1; +#else + int opt = 5; +#endif + s = setsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN, &opt, sizeof(opt)); + + if (s == -1) { + if (errno == EPROTONOSUPPORT || errno == ENOPROTOOPT) { + LOGE("fast open is not supported on this platform"); + fast_open = 0; + } else { + ERROR("setsockopt"); + } + } + } +#endif + return s; +} + +#ifndef __MINGW32__ +int +setnonblocking(int fd) +{ + int flags; + if (-1 == (flags = fcntl(fd, F_GETFL, 0))) { + flags = 0; + } + return fcntl(fd, F_SETFL, flags | O_NONBLOCK); +} + +#endif + +int +create_and_bind(const char *host, const char *port, int mptcp) +{ + struct addrinfo hints; + struct addrinfo *result, *rp, *ipv4v6bindall; + int s, listen_sock; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; /* Return IPv4 and IPv6 choices */ + hints.ai_socktype = SOCK_STREAM; /* We want a TCP socket */ + hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; /* For wildcard IP address */ + hints.ai_protocol = IPPROTO_TCP; + + for (int i = 1; i < 8; i++) { + s = getaddrinfo(host, port, &hints, &result); + if (s == 0) { + break; + } else { + sleep(pow(2, i)); + LOGE("failed to resolve server name, wait %.0f seconds", pow(2, i)); + } + } + + if (s != 0) { + LOGE("getaddrinfo: %s", gai_strerror(s)); + return -1; + } + + rp = result; + + /* + * On Linux, with net.ipv6.bindv6only = 0 (the default), getaddrinfo(NULL) with + * AI_PASSIVE returns 0.0.0.0 and :: (in this order). AI_PASSIVE was meant to + * return a list of addresses to listen on, but it is impossible to listen on + * 0.0.0.0 and :: at the same time, if :: implies dualstack mode. + */ + if (!host) { + ipv4v6bindall = result; + + /* Loop over all address infos found until a IPV6 address is found. */ + while (ipv4v6bindall) { + if (ipv4v6bindall->ai_family == AF_INET6) { + rp = ipv4v6bindall; /* Take first IPV6 address available */ + break; + } + ipv4v6bindall = ipv4v6bindall->ai_next; /* Get next address info, if any */ + } + } + + for (/*rp = result*/; rp != NULL; rp = rp->ai_next) { + listen_sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if (listen_sock == -1) { + continue; + } + + if (rp->ai_family == AF_INET6) { + int ipv6only = host ? 1 : 0; + setsockopt(listen_sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, sizeof(ipv6only)); + } + + int opt = 1; + setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); +#ifdef SO_NOSIGPIPE + setsockopt(listen_sock, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); +#endif + int err = set_reuseport(listen_sock); + if (err == 0) { + LOGI("tcp port reuse enabled"); + } + + if (mptcp == 1) { + int err = setsockopt(listen_sock, SOL_TCP, MPTCP_ENABLED, &opt, sizeof(opt)); + if (err == -1) { + ERROR("failed to enable multipath TCP"); + } + } + + s = bind(listen_sock, rp->ai_addr, rp->ai_addrlen); + if (s == 0) { + /* We managed to bind successfully! */ + break; + } else { + ERROR("bind"); + } + + close(listen_sock); + } + + if (rp == NULL) { + LOGE("Could not bind"); + return -1; + } + + freeaddrinfo(result); + + return listen_sock; +} + +static remote_t * +connect_to_remote(EV_P_ struct addrinfo *res, + server_t *server) +{ + int sockfd; +#ifdef SET_INTERFACE + const char *iface = server->listen_ctx->iface; +#endif + + if (acl) { + char ipstr[INET6_ADDRSTRLEN]; + memset(ipstr, 0, INET6_ADDRSTRLEN); + + if (res->ai_addr->sa_family == AF_INET) { + struct sockaddr_in *s = (struct sockaddr_in *)res->ai_addr; + dns_ntop(AF_INET, &s->sin_addr, ipstr, INET_ADDRSTRLEN); + } else if (res->ai_addr->sa_family == AF_INET6) { + struct sockaddr_in6 *s = (struct sockaddr_in6 *)res->ai_addr; + dns_ntop(AF_INET6, &s->sin6_addr, ipstr, INET6_ADDRSTRLEN); + } + + if (outbound_block_match_host(ipstr) == 1) { + if (verbose) + LOGI("outbound blocked %s", ipstr); + return NULL; + } + } + + // initialize remote socks + sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (sockfd == -1) { + ERROR("socket"); + close(sockfd); + return NULL; + } + + int opt = 1; + setsockopt(sockfd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt)); +#ifdef SO_NOSIGPIPE + setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); +#endif + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); + + // setup remote socks + + if (setnonblocking(sockfd) == -1) + ERROR("setnonblocking"); + + if (bind_address != NULL) + if (bind_to_address(sockfd, bind_address) == -1) { + ERROR("bind_to_address"); + close(sockfd); + return NULL; + } + +#ifdef SET_INTERFACE + if (iface) { + if (setinterface(sockfd, iface) == -1) { + ERROR("setinterface"); + close(sockfd); + return NULL; + } + } +#endif + + remote_t *remote = new_remote(sockfd); + +#ifdef TCP_FASTOPEN + if (fast_open) { +#ifdef __APPLE__ + ((struct sockaddr_in *)(res->ai_addr))->sin_len = sizeof(struct sockaddr_in); + sa_endpoints_t endpoints; + memset((char *)&endpoints, 0, sizeof(endpoints)); + endpoints.sae_dstaddr = res->ai_addr; + endpoints.sae_dstaddrlen = res->ai_addrlen; + + struct iovec iov; + iov.iov_base = server->buf->array + server->buf->idx; + iov.iov_len = server->buf->len; + size_t len; + int s = connectx(sockfd, &endpoints, SAE_ASSOCID_ANY, CONNECT_DATA_IDEMPOTENT, + &iov, 1, &len, NULL); + if (s == 0) { + s = len; + } +#else + ssize_t s = sendto(sockfd, server->buf->array + server->buf->idx, + server->buf->len, MSG_FASTOPEN, res->ai_addr, + res->ai_addrlen); +#endif + if (s == -1) { + if (errno == CONNECT_IN_PROGRESS || errno == EAGAIN + || errno == EWOULDBLOCK) { + // The remote server doesn't support tfo or it's the first connection to the server. + // It will automatically fall back to conventional TCP. + } else if (errno == EOPNOTSUPP || errno == EPROTONOSUPPORT || + errno == ENOPROTOOPT) { + // Disable fast open as it's not supported + fast_open = 0; + LOGE("fast open is not supported on this platform"); + } else { + ERROR("sendto"); + } + } else if (s <= server->buf->len) { + server->buf->idx += s; + server->buf->len -= s; + } else { + server->buf->idx = 0; + server->buf->len = 0; + } + } +#endif + + if (!fast_open) { + int r = connect(sockfd, res->ai_addr, res->ai_addrlen); + + if (r == -1 && errno != CONNECT_IN_PROGRESS) { + ERROR("connect"); + close_and_free_remote(EV_A_ remote); + return NULL; + } + } + + return remote; +} + +static void +server_recv_cb(EV_P_ ev_io *w, int revents) +{ + server_ctx_t *server_recv_ctx = (server_ctx_t *)w; + server_t *server = server_recv_ctx->server; + remote_t *remote = NULL; + + int len = server->buf->len; + buffer_t *buf = server->buf; + + if (server->stage > STAGE_PARSE) { + remote = server->remote; + buf = remote->buf; + len = 0; + + ev_timer_again(EV_A_ & server->recv_ctx->watcher); + } + + if (len > BUF_SIZE) { + ERROR("out of recv buffer"); + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + return; + } + + ssize_t r = recv(server->fd, buf->array + len, BUF_SIZE - len, 0); + + if (r == 0) { + // connection closed + if (verbose) { + LOGI("server_recv close the connection"); + } + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + return; + } else if (r == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { + // no data + // continue to wait for recv + return; + } else { + ERROR("server recv"); + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + return; + } + } + + tx += r; + + if (server->stage == STAGE_ERROR) { + server->buf->len = 0; + server->buf->idx = 0; + return; + } + + // handle incomplete header part 1 + if (server->stage == STAGE_INIT) { + buf->len += r; + if (buf->len <= enc_get_iv_len() + 1) { + // wait for more + return; + } + } else { + buf->len = r; + } + + // SSR beg + + if (server->obfs_plugin) { + obfs_class *obfs_plugin = server->obfs_plugin; + if (obfs_plugin->server_decode) { + int needsendback = 0; + + if(obfs_compatible == 1) + { + char *back_buf = (char*)malloc(sizeof(buffer_t)); + memcpy(back_buf, buf, sizeof(buffer_t)); + buf->len = obfs_plugin->server_decode(server->obfs, &buf->array, buf->len, &buf->capacity, &needsendback); + + if ((int)buf->len < 0) + { + LOGE("obfs_compatible"); + memcpy(buf, back_buf, sizeof(buffer_t)); + free(back_buf); + server->obfs_compatible_state = 1; + } + } + else + { + buf->len = obfs_plugin->server_decode(server->obfs, &buf->array, buf->len, &buf->capacity, &needsendback); + if ((int)buf->len < 0) { + LOGE("server_decode"); + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + return; + } + } + + if (needsendback) { + size_t capacity = BUF_SIZE; + char *sendback_buf = (char*)malloc(capacity); + obfs_class *obfs_plugin = server->obfs_plugin; + if (obfs_plugin->server_encode) { + int len = obfs_plugin->server_encode(server->obfs, &sendback_buf, 0, &capacity); + send(server->fd, sendback_buf, len, 0); + } + free(sendback_buf); + return; + } + } + } + + int err = ss_decrypt(buf, server->d_ctx, BUF_SIZE); + + if (err) { + report_addr(server->fd, MALICIOUS); + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + return; + } + + if (server->protocol_plugin) { + obfs_class *protocol_plugin = server->protocol_plugin; + if (protocol_plugin->server_post_decrypt) { + + if(protocol_compatible == 1) + { + char *back_buf = (char*)malloc(sizeof(buffer_t)); + memcpy(back_buf, buf, sizeof(buffer_t)); + buf->len = protocol_plugin->server_post_decrypt(server->protocol, &buf->array, buf->len, &buf->capacity); + + if ((int)buf->len < 0) { + LOGE("protocol_compatible"); + memcpy(buf, back_buf, sizeof(buffer_t)); + free(back_buf); + server->protocol_compatible_state = 1; + } + if ( buf->len == 0 ) + { + LOGE("protocol_compatible"); + memcpy(buf, back_buf, sizeof(buffer_t)); + free(back_buf); + server->protocol_compatible_state = 1; + } + } + else + { + buf->len = protocol_plugin->server_post_decrypt(server->protocol, &buf->array, buf->len, &buf->capacity); + if ((int)buf->len < 0) { + LOGE("server_post_decrypt"); + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + return; + } + if ( buf->len == 0 ) + { + LOGE("server_post_decrypt"); + return; + } + } + } + } + // SSR end + + // handle incomplete header part 2 + if (server->stage == STAGE_INIT) { + int ret = is_header_complete(server->buf); + if (ret == 1) { + bfree(server->header_buf); + ss_free(server->header_buf); + server->stage = STAGE_PARSE; + } else if (ret == -1) { + server->stage = STAGE_ERROR; + report_addr(server->fd, MALFORMED); + server->buf->len = 0; + server->buf->idx = 0; + return; + } else { + server->stage = STAGE_HANDSHAKE; + } + } + + if (server->stage == STAGE_HANDSHAKE) { + size_t header_len = server->header_buf->len; + brealloc(server->header_buf, server->buf->len + header_len, BUF_SIZE); + memcpy(server->header_buf->array + header_len, + server->buf->array, server->buf->len); + server->header_buf->len = server->buf->len + header_len; + + int ret = is_header_complete(server->buf); + + if (ret == 1) { + brealloc(server->buf, server->header_buf->len, BUF_SIZE); + memcpy(server->buf->array, server->header_buf->array, server->header_buf->len); + server->buf->len = server->header_buf->len; + bfree(server->header_buf); + ss_free(server->header_buf); + server->stage = STAGE_PARSE; + } else { + if (ret == -1) + server->stage = STAGE_ERROR; + server->buf->len = 0; + server->buf->idx = 0; + return; + } + } + + // handshake and transmit data + if (server->stage == STAGE_STREAM) { + if (server->auth && !ss_check_hash(remote->buf, server->chunk, server->d_ctx, BUF_SIZE)) { + LOGE("hash error"); + report_addr(server->fd, BAD); + close_and_free_server(EV_A_ server); + close_and_free_remote(EV_A_ remote); + return; + } + + int s = send(remote->fd, remote->buf->array, remote->buf->len, 0); + if (s == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { + // no data, wait for send + remote->buf->idx = 0; + ev_io_stop(EV_A_ & server_recv_ctx->io); + ev_io_start(EV_A_ & remote->send_ctx->io); + } else { + ERROR("server_recv_send"); + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + } + } else if (s < remote->buf->len) { + remote->buf->len -= s; + remote->buf->idx = s; + ev_io_stop(EV_A_ & server_recv_ctx->io); + ev_io_start(EV_A_ & remote->send_ctx->io); + } + return; + } else if (server->stage == STAGE_PARSE) { + /* + * Shadowsocks TCP Relay Header: + * + * +------+----------+----------+----------------+ + * | ATYP | DST.ADDR | DST.PORT | HMAC-SHA1 | + * +------+----------+----------+----------------+ + * | 1 | Variable | 2 | 10 | + * +------+----------+----------+----------------+ + * + * If ATYP & ONETIMEAUTH_FLAG(0x10) != 0, Authentication (HMAC-SHA1) is enabled. + * + * The key of HMAC-SHA1 is (IV + KEY) and the input is the whole header. + * The output of HMAC-SHA is truncated to 10 bytes (leftmost bits). + */ + + /* + * Shadowsocks Request's Chunk Authentication for TCP Relay's payload + * (No chunk authentication for response's payload): + * + * +------+-----------+-------------+------+ + * | LEN | HMAC-SHA1 | DATA | ... + * +------+-----------+-------------+------+ + * | 2 | 10 | Variable | ... + * +------+-----------+-------------+------+ + * + * The key of HMAC-SHA1 is (IV + CHUNK ID) + * The output of HMAC-SHA is truncated to 10 bytes (leftmost bits). + */ + + int offset = 0; + int need_query = 0; + char atyp = server->buf->array[offset++]; + char host[257] = { 0 }; + uint16_t port = 0; + struct addrinfo info; + struct sockaddr_storage storage; + memset(&info, 0, sizeof(struct addrinfo)); + memset(&storage, 0, sizeof(struct sockaddr_storage)); + + if (auth || (atyp & ONETIMEAUTH_FLAG)) { + size_t header_len = parse_header_len(atyp, server->buf->array, offset); + size_t len = server->buf->len; + + if (header_len == 0 || len < offset + header_len + ONETIMEAUTH_BYTES) { + report_addr(server->fd, MALFORMED); + close_and_free_server(EV_A_ server); + return; + } + + server->buf->len = offset + header_len + ONETIMEAUTH_BYTES; + if (ss_onetimeauth_verify(server->buf, server->d_ctx->evp.iv)) { + report_addr(server->fd, BAD); + close_and_free_server(EV_A_ server); + return; + } + + server->buf->len = len; + server->auth = 1; + } + + // get remote addr and port + if ((atyp & ADDRTYPE_MASK) == 1) { + // IP V4 + struct sockaddr_in *addr = (struct sockaddr_in *)&storage; + size_t in_addr_len = sizeof(struct in_addr); + addr->sin_family = AF_INET; + if (server->buf->len >= in_addr_len + 3) { + addr->sin_addr = *(struct in_addr *)(server->buf->array + offset); + dns_ntop(AF_INET, (const void *)(server->buf->array + offset), + host, INET_ADDRSTRLEN); + offset += in_addr_len; + } else { + LOGE("invalid header with addr type %d", atyp); + report_addr(server->fd, MALFORMED); + close_and_free_server(EV_A_ server); + return; + } + addr->sin_port = *(uint16_t *)(server->buf->array + offset); + info.ai_family = AF_INET; + info.ai_socktype = SOCK_STREAM; + info.ai_protocol = IPPROTO_TCP; + info.ai_addrlen = sizeof(struct sockaddr_in); + info.ai_addr = (struct sockaddr *)addr; + } else if ((atyp & ADDRTYPE_MASK) == 3) { + // Domain name + uint8_t name_len = *(uint8_t *)(server->buf->array + offset); + if (name_len + 4 <= server->buf->len) { + memcpy(host, server->buf->array + offset + 1, name_len); + offset += name_len + 1; + } else { + LOGE("invalid name length: %d", name_len); + report_addr(server->fd, MALFORMED); + close_and_free_server(EV_A_ server); + return; + } + if (acl && outbound_block_match_host(host) == 1) { + if (verbose) + LOGI("outbound blocked %s", host); + close_and_free_server(EV_A_ server); + return; + } + struct cork_ip ip; + if (cork_ip_init(&ip, host) != -1) { + info.ai_socktype = SOCK_STREAM; + info.ai_protocol = IPPROTO_TCP; + if (ip.version == 4) { + struct sockaddr_in *addr = (struct sockaddr_in *)&storage; + dns_pton(AF_INET, host, &(addr->sin_addr)); + addr->sin_port = *(uint16_t *)(server->buf->array + offset); + addr->sin_family = AF_INET; + info.ai_family = AF_INET; + info.ai_addrlen = sizeof(struct sockaddr_in); + info.ai_addr = (struct sockaddr *)addr; + } else if (ip.version == 6) { + struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&storage; + dns_pton(AF_INET6, host, &(addr->sin6_addr)); + addr->sin6_port = *(uint16_t *)(server->buf->array + offset); + addr->sin6_family = AF_INET6; + info.ai_family = AF_INET6; + info.ai_addrlen = sizeof(struct sockaddr_in6); + info.ai_addr = (struct sockaddr *)addr; + } + } else { + if (!validate_hostname(host, name_len)) { + LOGE("invalid host name"); + report_addr(server->fd, MALFORMED); + close_and_free_server(EV_A_ server); + return; + } + need_query = 1; + } + } else if ((atyp & ADDRTYPE_MASK) == 4) { + // IP V6 + struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&storage; + size_t in6_addr_len = sizeof(struct in6_addr); + addr->sin6_family = AF_INET6; + if (server->buf->len >= in6_addr_len + 3) { + addr->sin6_addr = *(struct in6_addr *)(server->buf->array + offset); + dns_ntop(AF_INET6, (const void *)(server->buf->array + offset), + host, INET6_ADDRSTRLEN); + offset += in6_addr_len; + } else { + LOGE("invalid header with addr type %d", atyp); + report_addr(server->fd, MALFORMED); + close_and_free_server(EV_A_ server); + return; + } + addr->sin6_port = *(uint16_t *)(server->buf->array + offset); + info.ai_family = AF_INET6; + info.ai_socktype = SOCK_STREAM; + info.ai_protocol = IPPROTO_TCP; + info.ai_addrlen = sizeof(struct sockaddr_in6); + info.ai_addr = (struct sockaddr *)addr; + } + + if (offset == 1) { + LOGE("invalid header with addr type %d", atyp); + report_addr(server->fd, MALFORMED); + close_and_free_server(EV_A_ server); + return; + } + + port = (*(uint16_t *)(server->buf->array + offset)); + + offset += 2; + + if (server->auth) { + offset += ONETIMEAUTH_BYTES; + } + + if (server->buf->len < offset) { + report_addr(server->fd, MALFORMED); + close_and_free_server(EV_A_ server); + return; + } else { + server->buf->len -= offset; + memmove(server->buf->array, server->buf->array + offset, server->buf->len); + } + + if (verbose) { + if ((atyp & ADDRTYPE_MASK) == 4) + LOGI("connect to [%s]:%d", host, ntohs(port)); + else + LOGI("connect to %s:%d", host, ntohs(port)); + } + + if (server->auth && !ss_check_hash(server->buf, server->chunk, server->d_ctx, BUF_SIZE)) { + LOGE("hash error"); + report_addr(server->fd, BAD); + close_and_free_server(EV_A_ server); + return; + } + + + if (!need_query) { + remote_t *remote = connect_to_remote(EV_A_ &info, server); + + if (remote == NULL) { + LOGE("connect error"); + close_and_free_server(EV_A_ server); + return; + } else { + server->remote = remote; + remote->server = server; + + // XXX: should handle buffer carefully + if (server->buf->len > 0) { + memcpy(remote->buf->array, server->buf->array, server->buf->len); + remote->buf->len = server->buf->len; + remote->buf->idx = 0; + server->buf->len = 0; + server->buf->idx = 0; + } + + // waiting on remote connected event + ev_io_stop(EV_A_ & server_recv_ctx->io); + ev_io_start(EV_A_ & remote->send_ctx->io); + } + } else { + query_t *query = (query_t *)ss_malloc(sizeof(query_t)); + query->server = server; + snprintf(query->hostname, 256, "%s", host); + + server->stage = STAGE_RESOLVE; + server->query = resolv_query(host, server_resolve_cb, + query_free_cb, query, port); + + ev_io_stop(EV_A_ & server_recv_ctx->io); + } + + return; + } + // should not reach here + FATAL("server context error"); +} + +static void +server_send_cb(EV_P_ ev_io *w, int revents) +{ + server_ctx_t *server_send_ctx = (server_ctx_t *)w; + server_t *server = server_send_ctx->server; + remote_t *remote = server->remote; + + if (remote == NULL) { + LOGE("invalid server"); + close_and_free_server(EV_A_ server); + return; + } + + if (server->buf->len == 0) { + // close and free + if (verbose) { + LOGI("server_send close the connection"); + } + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + return; + } else { + // has data to send + ssize_t s = send(server->fd, server->buf->array + server->buf->idx, + server->buf->len, 0); + if (s == -1) { + if (errno != EAGAIN && errno != EWOULDBLOCK) { + ERROR("server_send_send"); + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + } + return; + } else if (s < server->buf->len) { + // partly sent, move memory, wait for the next time to send + server->buf->len -= s; + server->buf->idx += s; + return; + } else { + // all sent out, wait for reading + server->buf->len = 0; + server->buf->idx = 0; + ev_io_stop(EV_A_ & server_send_ctx->io); + if (remote != NULL) { + ev_io_start(EV_A_ & remote->recv_ctx->io); + return; + } else { + LOGE("invalid remote"); + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + return; + } + } + } +} + +static void +block_list_clear_cb(EV_P_ ev_timer *watcher, int revents) +{ + clear_block_list(); +} + +static void +server_timeout_cb(EV_P_ ev_timer *watcher, int revents) +{ + server_ctx_t *server_ctx + = cork_container_of(watcher, server_ctx_t, watcher); + server_t *server = server_ctx->server; + remote_t *remote = server->remote; + + if (verbose) { + LOGI("TCP connection timeout"); + } + + if (server->stage < STAGE_PARSE) { + if (verbose) { + size_t len = server->stage ? + server->header_buf->len : server->buf->len; +#ifdef __MINGW32__ + LOGI("incomplete header: %u", len); +#else + LOGI("incomplete header: %zu", len); +#endif + } + report_addr(server->fd, SUSPICIOUS); + } + + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); +} + +static void +query_free_cb(void *data) +{ + if (data != NULL) { + ss_free(data); + } +} + +static void +server_resolve_cb(struct sockaddr *addr, void *data) +{ + query_t *query = (query_t *)data; + server_t *server = query->server; + struct ev_loop *loop = server->listen_ctx->loop; + + server->query = NULL; + + if (addr == NULL) { + LOGE("unable to resolve %s", query->hostname); + close_and_free_server(EV_A_ server); + } else { + if (verbose) { + LOGI("successfully resolved %s", query->hostname); + } + + struct addrinfo info; + memset(&info, 0, sizeof(struct addrinfo)); + info.ai_socktype = SOCK_STREAM; + info.ai_protocol = IPPROTO_TCP; + info.ai_addr = addr; + + if (addr->sa_family == AF_INET) { + info.ai_family = AF_INET; + info.ai_addrlen = sizeof(struct sockaddr_in); + } else if (addr->sa_family == AF_INET6) { + info.ai_family = AF_INET6; + info.ai_addrlen = sizeof(struct sockaddr_in6); + } + + remote_t *remote = connect_to_remote(EV_A_ &info, server); + + if (remote == NULL) { + close_and_free_server(EV_A_ server); + } else { + server->remote = remote; + remote->server = server; + + // XXX: should handle buffer carefully + if (server->buf->len > 0) { + memcpy(remote->buf->array, server->buf->array + server->buf->idx, + server->buf->len); + remote->buf->len = server->buf->len; + remote->buf->idx = 0; + server->buf->len = 0; + server->buf->idx = 0; + } + + // listen to remote connected event + ev_io_start(EV_A_ & remote->send_ctx->io); + } + } +} + +static void +remote_recv_cb(EV_P_ ev_io *w, int revents) +{ + remote_ctx_t *remote_recv_ctx = (remote_ctx_t *)w; + remote_t *remote = remote_recv_ctx->remote; + server_t *server = remote->server; + + if (server == NULL) { + LOGE("invalid server"); + close_and_free_remote(EV_A_ remote); + return; + } + + ev_timer_again(EV_A_ & server->recv_ctx->watcher); + + ssize_t r = recv(remote->fd, server->buf->array, BUF_SIZE, 0); + + if (r == 0) { + // connection closed + if (verbose) { + LOGI("remote_recv close the connection"); + } + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + return; + } else if (r == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { + // no data + // continue to wait for recv + return; + } else { + ERROR("remote recv"); + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + return; + } + } + + rx += r; + + server->buf->len = r; + + // SSR beg + server_info _server_info; + if (server->obfs_plugin) { + server->obfs_plugin->get_server_info(server->obfs, &_server_info); + _server_info.head_len = get_head_size(server->buf->array, server->buf->len, 30); + server->obfs_plugin->set_server_info(server->obfs, &_server_info); + } + + if (server->protocol_plugin && server->obfs_compatible_state == 0) { + obfs_class *protocol_plugin = server->protocol_plugin; + if (protocol_plugin->server_pre_encrypt) { + server->buf->len = protocol_plugin->server_pre_encrypt(server->protocol, &server->buf->array, server->buf->len, &server->buf->capacity); + } + } + + int err = ss_encrypt(server->buf, server->e_ctx, BUF_SIZE); + + if (err) { + LOGE("invalid password or cipher"); + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + return; + } + + if (server->obfs_plugin && server->obfs_compatible_state == 0) { + obfs_class *obfs_plugin = server->obfs_plugin; + if (obfs_plugin->server_encode) { + server->buf->len = obfs_plugin->server_encode(server->obfs, &server->buf->array, server->buf->len, &server->buf->capacity); + } + } + // SSR end + + int s = send(server->fd, server->buf->array, server->buf->len, 0); + + if (s == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { + // no data, wait for send + server->buf->idx = 0; + ev_io_stop(EV_A_ & remote_recv_ctx->io); + ev_io_start(EV_A_ & server->send_ctx->io); + } else { + ERROR("remote_recv_send"); + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + return; + } + } else if (s < server->buf->len) { + server->buf->len -= s; + server->buf->idx = s; + ev_io_stop(EV_A_ & remote_recv_ctx->io); + ev_io_start(EV_A_ & server->send_ctx->io); + } + + // Disable TCP_NODELAY after the first response are sent + if (!remote->recv_ctx->connected) { + int opt = 0; + setsockopt(server->fd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt)); + setsockopt(remote->fd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt)); + remote->recv_ctx->connected = 1; + } +} + +static void +remote_send_cb(EV_P_ ev_io *w, int revents) +{ + remote_ctx_t *remote_send_ctx = (remote_ctx_t *)w; + remote_t *remote = remote_send_ctx->remote; + server_t *server = remote->server; + + if (server == NULL) { + LOGE("invalid server"); + close_and_free_remote(EV_A_ remote); + return; + } + + if (!remote_send_ctx->connected) { + struct sockaddr_storage addr; + socklen_t len = sizeof(struct sockaddr_storage); + memset(&addr, 0, len); + int r = getpeername(remote->fd, (struct sockaddr *)&addr, &len); + if (r == 0) { + if (verbose) { + LOGI("remote connected"); + } + remote_send_ctx->connected = 1; + + // Clear the state of this address in the block list + reset_addr(server->fd); + + if (remote->buf->len == 0) { + server->stage = STAGE_STREAM; + ev_io_stop(EV_A_ & remote_send_ctx->io); + ev_io_start(EV_A_ & server->recv_ctx->io); + ev_io_start(EV_A_ & remote->recv_ctx->io); + return; + } + } else { + ERROR("getpeername"); + // not connected + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + return; + } + } + + if (remote->buf->len == 0) { + // close and free + if (verbose) { + LOGI("remote_send close the connection"); + } + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + return; + } else { + // has data to send + ssize_t s = send(remote->fd, remote->buf->array + remote->buf->idx, + remote->buf->len, 0); + if (s == -1) { + if (errno != EAGAIN && errno != EWOULDBLOCK) { + ERROR("remote_send_send"); + // close and free + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + } + return; + } else if (s < remote->buf->len) { + // partly sent, move memory, wait for the next time to send + remote->buf->len -= s; + remote->buf->idx += s; + return; + } else { + // all sent out, wait for reading + remote->buf->len = 0; + remote->buf->idx = 0; + ev_io_stop(EV_A_ & remote_send_ctx->io); + if (server != NULL) { + ev_io_start(EV_A_ & server->recv_ctx->io); + if (server->stage != STAGE_STREAM) { + server->stage = STAGE_STREAM; + ev_io_start(EV_A_ & remote->recv_ctx->io); + } + } else { + LOGE("invalid server"); + close_and_free_remote(EV_A_ remote); + close_and_free_server(EV_A_ server); + } + return; + } + } +} + +static remote_t * +new_remote(int fd) +{ + if (verbose) { + remote_conn++; + } + + remote_t *remote; + + remote = ss_malloc(sizeof(remote_t)); + remote->recv_ctx = ss_malloc(sizeof(remote_ctx_t)); + remote->send_ctx = ss_malloc(sizeof(remote_ctx_t)); + remote->buf = ss_malloc(sizeof(buffer_t)); + remote->fd = fd; + remote->recv_ctx->remote = remote; + remote->recv_ctx->connected = 0; + remote->send_ctx->remote = remote; + remote->send_ctx->connected = 0; + remote->server = NULL; + + ev_io_init(&remote->recv_ctx->io, remote_recv_cb, fd, EV_READ); + ev_io_init(&remote->send_ctx->io, remote_send_cb, fd, EV_WRITE); + + balloc(remote->buf, BUF_SIZE); + + return remote; +} + +static void +free_remote(remote_t *remote) +{ + if (remote->server != NULL) { + remote->server->remote = NULL; + } + if (remote->buf != NULL) { + bfree(remote->buf); + ss_free(remote->buf); + } + ss_free(remote->recv_ctx); + ss_free(remote->send_ctx); + ss_free(remote); +} + +static void +close_and_free_remote(EV_P_ remote_t *remote) +{ + if (remote != NULL) { + ev_io_stop(EV_A_ & remote->send_ctx->io); + ev_io_stop(EV_A_ & remote->recv_ctx->io); + close(remote->fd); + free_remote(remote); + if (verbose) { + remote_conn--; + LOGI("current remote connection: %d", remote_conn); + } + } +} + +static server_t * +new_server(int fd, listen_ctx_t *listener) +{ + if (verbose) { + server_conn++; + } + + server_t *server; + server = ss_malloc(sizeof(server_t)); + + memset(server, 0, sizeof(server_t)); + + server->recv_ctx = ss_malloc(sizeof(server_ctx_t)); + server->send_ctx = ss_malloc(sizeof(server_ctx_t)); + server->buf = ss_malloc(sizeof(buffer_t)); + server->header_buf = ss_malloc(sizeof(buffer_t)); + server->fd = fd; + server->recv_ctx->server = server; + server->recv_ctx->connected = 0; + server->send_ctx->server = server; + server->send_ctx->connected = 0; + server->stage = STAGE_INIT; + server->query = NULL; + server->listen_ctx = listener; + server->remote = NULL; + + if (listener->method) { + server->e_ctx = ss_malloc(sizeof(enc_ctx_t)); + server->d_ctx = ss_malloc(sizeof(enc_ctx_t)); + enc_ctx_init(listener->method, server->e_ctx, 1); + enc_ctx_init(listener->method, server->d_ctx, 0); + } else { + server->e_ctx = NULL; + server->d_ctx = NULL; + } + + int request_timeout = min(MAX_REQUEST_TIMEOUT, listener->timeout) + + rand() % MAX_REQUEST_TIMEOUT; + + ev_io_init(&server->recv_ctx->io, server_recv_cb, fd, EV_READ); + ev_io_init(&server->send_ctx->io, server_send_cb, fd, EV_WRITE); + ev_timer_init(&server->recv_ctx->watcher, server_timeout_cb, + request_timeout, listener->timeout); + + balloc(server->buf, BUF_SIZE); + balloc(server->header_buf, BUF_SIZE); + + server->chunk = (chunk_t *)malloc(sizeof(chunk_t)); + memset(server->chunk, 0, sizeof(chunk_t)); + server->chunk->buf = ss_malloc(sizeof(buffer_t)); + memset(server->chunk->buf, 0, sizeof(buffer_t)); + + cork_dllist_add(&connections, &server->entries); + + return server; +} + +static void +free_server(server_t *server) +{ + cork_dllist_remove(&server->entries); + + if (server->chunk != NULL) { + if (server->chunk->buf != NULL) { + bfree(server->chunk->buf); + ss_free(server->chunk->buf); + } + ss_free(server->chunk); + } + if (server->remote != NULL) { + server->remote->server = NULL; + } + if (server->e_ctx != NULL) { + cipher_context_release(&server->e_ctx->evp); + ss_free(server->e_ctx); + } + if (server->d_ctx != NULL) { + cipher_context_release(&server->d_ctx->evp); + ss_free(server->d_ctx); + } + if (server->buf != NULL) { + bfree(server->buf); + ss_free(server->buf); + } + if (server->header_buf != NULL) { + bfree(server->header_buf); + ss_free(server->header_buf); + } + + ss_free(server->recv_ctx); + ss_free(server->send_ctx); + ss_free(server); +} + +static void +close_and_free_server(EV_P_ server_t *server) +{ + if (server != NULL) { + if (server->query != NULL) { + resolv_cancel(server->query); + server->query = NULL; + } + ev_io_stop(EV_A_ & server->send_ctx->io); + ev_io_stop(EV_A_ & server->recv_ctx->io); + ev_timer_stop(EV_A_ & server->recv_ctx->watcher); + close(server->fd); + free_server(server); + if (verbose) { + server_conn--; + LOGI("current server connection: %d", server_conn); + } + } +} + +static void +signal_cb(EV_P_ ev_signal *w, int revents) +{ + if (revents & EV_SIGNAL) { + switch (w->signum) { + case SIGINT: + case SIGTERM: + ev_unloop(EV_A_ EVUNLOOP_ALL); + } + } +} + +static void +accept_cb(EV_P_ ev_io *w, int revents) +{ + listen_ctx_t *listener = (listen_ctx_t *)w; + int serverfd = accept(listener->fd, NULL, NULL); + if (serverfd == -1) { + ERROR("accept"); + return; + } + + char *peer_name = get_peer_name(serverfd); + if (peer_name != NULL) { + int in_white_list = 0; + if (acl) { + if ((get_acl_mode() == BLACK_LIST && acl_match_host(peer_name) == 1) + || (get_acl_mode() == WHITE_LIST && acl_match_host(peer_name) >= 0)) { + LOGE("Access denied from %s", peer_name); + close(serverfd); + return; + } else if (acl_match_host(peer_name) == -1) { + in_white_list = 1; + } + } + if (!in_white_list && check_block_list(peer_name)) { + LOGE("block all requests from %s", peer_name); +#ifdef __linux__ + set_linger(serverfd); +#endif + close(serverfd); + return; + } + } + + int opt = 1; + setsockopt(serverfd, SOL_TCP, TCP_NODELAY, &opt, sizeof(opt)); +#ifdef SO_NOSIGPIPE + setsockopt(serverfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); +#endif + setnonblocking(serverfd); + + if (verbose) { + LOGI("accept a connection"); + } + + server_t *server = new_server(serverfd, listener); + + // SSR beg + server->obfs_plugin = new_obfs_class(server->listen_ctx->obfs_name); + if (server->obfs_plugin) { + server->obfs = server->obfs_plugin->new_obfs(); + server->obfs_compatible_state = 0; + } + server->protocol_plugin = new_obfs_class(server->listen_ctx->protocol_name); + if (server->protocol_plugin) { + server->protocol = server->protocol_plugin->new_obfs(); + server->protocol_compatible_state = 0; + } + server_info _server_info; + memset(&_server_info, 0, sizeof(server_info)); + _server_info.param = server->listen_ctx->obfs_param; + if(server->obfs_plugin) + _server_info.g_data = server->obfs_plugin->init_data(); + _server_info.head_len = 7; + _server_info.iv = server->e_ctx->evp.iv; + _server_info.iv_len = enc_get_iv_len(); + _server_info.key = enc_get_key(); + _server_info.key_len = enc_get_key_len(); + _server_info.tcp_mss = 1460; + + if (server->obfs_plugin) + server->obfs_plugin->set_server_info(server->obfs, &_server_info); + + _server_info.param = server->listen_ctx->protocol_param; + if (server->protocol_plugin) + _server_info.g_data = server->protocol_plugin->init_data(); + + if (server->protocol_plugin) + server->protocol_plugin->set_server_info(server->protocol, &_server_info); + // SSR end + + ev_io_start(EV_A_ & server->recv_ctx->io); + ev_timer_start(EV_A_ & server->recv_ctx->watcher); +} + +int +main(int argc, char **argv) +{ + int i, c; + int pid_flags = 0; + int mptcp = 0; + int firewall = 0; + int mtu = 0; + char *user = NULL; + char *password = NULL; + char *timeout = NULL; + char *protocol = NULL; // SSR + char *protocol_param = NULL; // SSR + char *method = NULL; + char *obfs = NULL; // SSR + char *obfs_param = NULL; // SSR + char *pid_path = NULL; + char *conf_path = NULL; + char *iface = NULL; + + int server_num = 0; + const char *server_host[MAX_REMOTE_NUM]; + + char *nameservers[MAX_DNS_NUM + 1]; + int nameserver_num = 0; + + int option_index = 0; + static struct option long_options[] = { + { "fast-open", no_argument, 0, 0 }, + { "acl", required_argument, 0, 0 }, + { "manager-address", required_argument, 0, 0 }, + { "mtu", required_argument, 0, 0 }, + { "help", no_argument, 0, 0 }, +#ifdef __linux__ + { "mptcp", no_argument, 0, 0 }, + { "firewall", no_argument, 0, 0 }, +#endif + { 0, 0, 0, 0 } + }; + + opterr = 0; + + USE_TTY(); + + while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:b:c:i:d:a:n:O:o:G:g:huUvA6", + long_options, &option_index)) != -1) { + switch (c) { + case 0: + if (option_index == 0) { + fast_open = 1; + } else if (option_index == 1) { + LOGI("initializing acl..."); + acl = !init_acl(optarg); + } else if (option_index == 2) { + manager_address = optarg; + } else if (option_index == 3) { + mtu = atoi(optarg); + LOGI("set MTU to %d", mtu); + } else if (option_index == 4) { + usage(); + exit(EXIT_SUCCESS); + } else if (option_index == 5) { + mptcp = 1; + LOGI("enable multipath TCP"); + } else if (option_index == 6) { + firewall = 1; + LOGI("enable firewall rules"); + } + break; + case 's': + if (server_num < MAX_REMOTE_NUM) { + server_host[server_num++] = optarg; + } + break; + case 'b': + bind_address = optarg; + break; + case 'p': + server_port = optarg; + break; + case 'k': + password = optarg; + break; + case 'f': + pid_flags = 1; + pid_path = optarg; + break; + case 't': + timeout = optarg; + break; + // SSR beg + case 'O': + protocol = optarg; + break; + case 'm': + method = optarg; + break; + case 'o': + obfs = optarg; + break; + case 'G': + protocol_param = optarg; + break; + case 'g': + obfs_param = optarg; + break; + // SSR end + case 'c': + conf_path = optarg; + break; + case 'i': + iface = optarg; + break; + case 'd': + if (nameserver_num < MAX_DNS_NUM) { + nameservers[nameserver_num++] = optarg; + } + break; + case 'a': + user = optarg; + break; +#ifdef HAVE_SETRLIMIT + case 'n': + nofile = atoi(optarg); + break; +#endif + case 'u': + mode = TCP_AND_UDP; + break; + case 'U': + mode = UDP_ONLY; + break; + case 'v': + verbose = 1; + break; + case 'h': + usage(); + exit(EXIT_SUCCESS); + case 'A': + auth = 1; + break; + case '6': + ipv6first = 1; + break; + case '?': + // The option character is not recognized. + LOGE("Unrecognized option: %s", optarg); + opterr = 1; + break; + } + } + + if (opterr) { + usage(); + exit(EXIT_FAILURE); + } + + if (argc == 1) { + if (conf_path == NULL) { + conf_path = DEFAULT_CONF_PATH; + } + } + + if (conf_path != NULL) { + jconf_t *conf = read_jconf(conf_path); + if (server_num == 0) { + server_num = conf->remote_num; + for (i = 0; i < server_num; i++) + server_host[i] = conf->remote_addr[i].host; + } + if (server_port == NULL) { + server_port = conf->remote_port; + } + if (password == NULL) { + password = conf->password; + } + // SSR beg + if (protocol == NULL) { + protocol = conf->protocol; + LOGI("protocol %s", protocol); + } + if (protocol_param == NULL) { + protocol_param = conf->protocol_param; + LOGI("protocol_param %s", obfs_param); + } + if (method == NULL) { + method = conf->method; + LOGI("method %s", method); + } + if (obfs == NULL) { + obfs = conf->obfs; + LOGI("obfs %s", obfs); + } + if (obfs_param == NULL) { + obfs_param = conf->obfs_param; + LOGI("obfs_param %s", obfs_param); + } + // SSR end + if (timeout == NULL) { + timeout = conf->timeout; + } + if (user == NULL) { + user = conf->user; + } + if (auth == 0) { + auth = conf->auth; + } + if (mode == TCP_ONLY) { + mode = conf->mode; + } + if (mtu == 0) { + mtu = conf->mtu; + } + if (mptcp == 0) { + mptcp = conf->mptcp; + } +#ifdef TCP_FASTOPEN + if (fast_open == 0) { + fast_open = conf->fast_open; + } +#endif +#ifdef HAVE_SETRLIMIT + if (nofile == 0) { + nofile = conf->nofile; + } +#endif + if (conf->nameserver != NULL) { + nameservers[nameserver_num++] = conf->nameserver; + } + if (ipv6first == 0) { + ipv6first = conf->ipv6_first; + } + } + + //_compatible + if(strlen(protocol)>11) + { + char *text; + text = (char*)malloc(12); + memcpy(text, protocol + strlen(protocol) - 11, 12); + + if(strcmp(text, "_compatible") == 0) + { + free(text); + text = (char*)malloc(strlen(protocol) - 11); + memcpy(text, protocol, strlen(protocol) - 11); + int length = strlen(protocol) - 11; + free(protocol); + obfs = (char*)malloc(length); + memset(protocol, 0x00, length); + memcpy(protocol, text, length); + LOGI("protocol compatible enable, %s", protocol); + free(text); + protocol_compatible = 1; + } + } + + if(strlen(obfs)>11) + { + char *text; + text = (char*)malloc(12); + memcpy(text, obfs + strlen(obfs) - 11, 12); + + if(strcmp(text, "_compatible") == 0) + { + free(text); + text = (char*)malloc(strlen(obfs) - 11); + memcpy(text, obfs, strlen(obfs) - 11); + int length = strlen(obfs) - 11; + free(obfs); + obfs = (char*)malloc(length); + memset(obfs, 0x00, length); + memcpy(obfs, text, length); + LOGI("obfs compatible enable, %s", obfs); + free(text); + obfs_compatible = 1; + } + } + + + if (server_num == 0) { + server_host[server_num++] = NULL; + } + + if (server_num == 0 || server_port == NULL || password == NULL) { + usage(); + exit(EXIT_FAILURE); + } + + if (protocol && strcmp(protocol, "verify_sha1") == 0) { + auth = 1; + protocol = NULL; + } + + if (method == NULL) { + method = "rc4-md5"; + } + + if (timeout == NULL) { + timeout = "60"; + } + +#ifdef HAVE_SETRLIMIT + /* + * no need to check the return value here since we will show + * the user an error message if setrlimit(2) fails + */ + if (nofile > 1024) { + if (verbose) { + LOGI("setting NOFILE to %d", nofile); + } + set_nofile(nofile); + } +#endif + + if (pid_flags) { + USE_SYSLOG(argv[0]); + daemonize(pid_path); + } + + if (ipv6first) { + LOGI("resolving hostname to IPv6 address first"); + } + + if (fast_open == 1) { +#ifdef TCP_FASTOPEN + LOGI("using tcp fast open"); +#else + LOGE("tcp fast open is not supported by this environment"); + fast_open = 0; +#endif + } + + if (auth) { + LOGI("onetime authentication enabled"); + } + + if (mode != TCP_ONLY) { + LOGI("UDP relay enabled"); + } + + if (mode == UDP_ONLY) { + LOGI("TCP relay disabled"); + } + +#ifdef __MINGW32__ + winsock_init(); +#else + // ignore SIGPIPE + signal(SIGPIPE, SIG_IGN); + signal(SIGCHLD, SIG_IGN); + signal(SIGABRT, SIG_IGN); +#endif + + struct ev_signal sigint_watcher; + struct ev_signal sigterm_watcher; + ev_signal_init(&sigint_watcher, signal_cb, SIGINT); + ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM); + ev_signal_start(EV_DEFAULT, &sigint_watcher); + ev_signal_start(EV_DEFAULT, &sigterm_watcher); + + // setup keys + LOGI("initializing ciphers... %s", method); + int m = enc_init(password, method); + + // initialize ev loop + struct ev_loop *loop = EV_DEFAULT; + + // setup udns + if (nameserver_num == 0) { +#ifdef __MINGW32__ + nameservers[nameserver_num++] = "8.8.8.8"; + resolv_init(loop, nameservers, nameserver_num, ipv6first); +#else + resolv_init(loop, NULL, 0, ipv6first); +#endif + } else { + resolv_init(loop, nameservers, nameserver_num, ipv6first); + } + + for (int i = 0; i < nameserver_num; i++) + LOGI("using nameserver: %s", nameservers[i]); + + // initialize listen context + listen_ctx_t listen_ctx_list[server_num]; + + // bind to each interface + while (server_num > 0) { + int index = --server_num; + const char *host = server_host[index]; + + if (mode != UDP_ONLY) { + // Bind to port + int listenfd; + listenfd = create_and_bind(host, server_port, mptcp); + if (listenfd == -1) { + FATAL("bind() error"); + } + if (listen(listenfd, SSMAXCONN) == -1) { + FATAL("listen() error"); + } + setfastopen(listenfd); + setnonblocking(listenfd); + listen_ctx_t *listen_ctx = &listen_ctx_list[index]; + + // Setup proxy context + listen_ctx->timeout = atoi(timeout); + listen_ctx->fd = listenfd; + listen_ctx->method = m; + listen_ctx->iface = iface; + + // SSR beg + listen_ctx->protocol_name = protocol; + listen_ctx->protocol_param = protocol_param; + listen_ctx->method = m; + listen_ctx->obfs_name = obfs; + listen_ctx->obfs_param = obfs_param; + listen_ctx->list_protocol_global = malloc(sizeof(void *)); + listen_ctx->list_obfs_global = malloc(sizeof(void *)); + memset(listen_ctx->list_protocol_global, 0, sizeof(void *)); + memset(listen_ctx->list_obfs_global, 0, sizeof(void *)); + // SSR end + + listen_ctx->loop = loop; + + ev_io_init(&listen_ctx->io, accept_cb, listenfd, EV_READ); + ev_io_start(loop, &listen_ctx->io); + } + + // Setup UDP + if (mode != TCP_ONLY) { + init_udprelay(server_host[index], server_port, mtu, m, + auth, atoi(timeout), iface, protocol, protocol_param); + } + + if (host && strcmp(host, ":") > 0) + LOGI("listening at [%s]:%s", host, server_port); + else + LOGI("listening at %s:%s", host ? host : "*", server_port); + } + + if (manager_address != NULL) { + ev_timer_init(&stat_update_watcher, stat_update_cb, UPDATE_INTERVAL, UPDATE_INTERVAL); + ev_timer_start(EV_DEFAULT, &stat_update_watcher); + } + + ev_timer_init(&block_list_watcher, block_list_clear_cb, UPDATE_INTERVAL, UPDATE_INTERVAL); + ev_timer_start(EV_DEFAULT, &block_list_watcher); + + // setuid + if (user != NULL && ! run_as(user)) { + FATAL("failed to switch user"); + } + +#ifndef __MINGW32__ + if (geteuid() == 0){ + LOGI("running from root user"); + } else if (firewall) { + LOGE("firewall setup requires running from root user"); + exit(-1); + } +#endif + + // init block list + init_block_list(firewall); + + // Init connections + cork_dllist_init(&connections); + + // start ev loop + ev_run(loop, 0); + + if (verbose) { + LOGI("closed gracefully"); + } + + // Free block list + free_block_list(); + + if (manager_address != NULL) { + ev_timer_stop(EV_DEFAULT, &stat_update_watcher); + } + ev_timer_stop(EV_DEFAULT, &block_list_watcher); + + // Clean up + for (int i = 0; i <= server_num; i++) { + listen_ctx_t *listen_ctx = &listen_ctx_list[i]; + if (mode != UDP_ONLY) { + ev_io_stop(loop, &listen_ctx->io); + close(listen_ctx->fd); + } + } + + if (mode != UDP_ONLY) { + free_connections(loop); + } + + if (mode != TCP_ONLY) { + free_udprelay(); + } + + resolv_shutdown(loop); + +#ifdef __MINGW32__ + winsock_cleanup(); +#endif + + ev_signal_stop(EV_DEFAULT, &sigint_watcher); + ev_signal_stop(EV_DEFAULT, &sigterm_watcher); + + return 0; +} diff --git a/shadowsocksr-libev/src/server/server.h b/shadowsocksr-libev/src/server/server.h new file mode 100644 index 0000000..4cd3cf6 --- /dev/null +++ b/shadowsocksr-libev/src/server/server.h @@ -0,0 +1,115 @@ +/* + * server.h - Define shadowsocks server's buffers and callbacks + * + * Copyright (C) 2013 - 2016, Max Lv + * + * This file is part of the shadowsocks-libev. + * + * shadowsocks-libev is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * shadowsocks-libev 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with shadowsocks-libev; see the file COPYING. If not, see + * . + */ + +#ifndef _SERVER_H +#define _SERVER_H + +#include +#include +#include + +#include "encrypt.h" +#include "jconf.h" +#include "resolv.h" +#include "obfs.h" +#include "protocol.h" + +#include "common.h" + +typedef struct listen_ctx { + ev_io io; + int fd; + int timeout; + int method; + char *iface; + struct ev_loop *loop; + + // SSR + char *protocol_name; + char *protocol_param; + char *obfs_name; + char *obfs_param; + void **list_protocol_global; + void **list_obfs_global; +} listen_ctx_t; + +typedef struct server_ctx { + ev_io io; + ev_timer watcher; + int connected; + struct server *server; +} server_ctx_t; + +typedef struct server { + int fd; + int stage; + buffer_t *buf; + ssize_t buf_capacity; + buffer_t *header_buf; + + int auth; + struct chunk *chunk; + + struct enc_ctx *e_ctx; + struct enc_ctx *d_ctx; + struct server_ctx *recv_ctx; + struct server_ctx *send_ctx; + struct listen_ctx *listen_ctx; + struct remote *remote; + + struct ResolvQuery *query; + + struct cork_dllist_item entries; + + // SSR + obfs *protocol; + obfs *obfs; + obfs_class *protocol_plugin; + obfs_class *obfs_plugin; + int obfs_compatible_state; + int protocol_compatible_state; +} server_t; + +typedef struct query { + server_t *server; + char hostname[257]; +} query_t; + +typedef struct remote_ctx { + ev_io io; + int connected; + struct remote *remote; +} remote_ctx_t; + +typedef struct remote { + int fd; + buffer_t *buf; + ssize_t buf_capacity; + struct remote_ctx *recv_ctx; + struct remote_ctx *send_ctx; + struct server *server; + + // SSR + int remote_index; +} remote_t; + +#endif // _SERVER_H diff --git a/shadowsocksr-libev/src/server/tls.c b/shadowsocksr-libev/src/server/tls.c new file mode 100644 index 0000000..5c42216 --- /dev/null +++ b/shadowsocksr-libev/src/server/tls.c @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2011 and 2012, Dustin Lundquist + * 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 HOLDER 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. + */ +/* + * This is a minimal TLS implementation intended only to parse the server name + * extension. This was created based primarily on Wireshark dissection of a + * TLS handshake and RFC4366. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include /* malloc() */ +#include /* strncpy() */ + +#ifndef __MINGW32__ +#include +#else +#include +#endif + +#include "tls.h" +#include "protocol.h" +#include "utils.h" + +#define SERVER_NAME_LEN 256 +#define TLS_HEADER_LEN 5 +#define TLS_HANDSHAKE_CONTENT_TYPE 0x16 +#define TLS_HANDSHAKE_TYPE_CLIENT_HELLO 0x01 + +#ifndef MIN +#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) +#endif + +extern int verbose; + +static int parse_tls_header(const char *, size_t, char **); +static int parse_extensions(const char *, size_t, char **); +static int parse_server_name_extension(const char *, size_t, char **); + +static const protocol_t tls_protocol_st = { + .default_port = 443, + .parse_packet = &parse_tls_header, +}; +const protocol_t *const tls_protocol = &tls_protocol_st; + +/* Parse a TLS packet for the Server Name Indication extension in the client + * hello handshake, returning the first servername found (pointer to static + * array) + * + * Returns: + * >=0 - length of the hostname and updates *hostname + * caller is responsible for freeing *hostname + * -1 - Incomplete request + * -2 - No Host header included in this request + * -3 - Invalid hostname pointer + * -4 - malloc failure + * < -4 - Invalid TLS client hello + */ +static int +parse_tls_header(const char *data, size_t data_len, char **hostname) +{ + char tls_content_type; + char tls_version_major; + char tls_version_minor; + size_t pos = TLS_HEADER_LEN; + size_t len; + + if (hostname == NULL) + return -3; + + /* Check that our TCP payload is at least large enough for a TLS header */ + if (data_len < TLS_HEADER_LEN) + return -1; + + /* SSL 2.0 compatible Client Hello + * + * High bit of first byte (length) and content type is Client Hello + * + * See RFC5246 Appendix E.2 + */ + if (data[0] & 0x80 && data[2] == 1) { + if (verbose) + LOGI("Received SSL 2.0 Client Hello which can not support SNI."); + return -2; + } + + tls_content_type = data[0]; + if (tls_content_type != TLS_HANDSHAKE_CONTENT_TYPE) { + if (verbose) + LOGI("Request did not begin with TLS handshake."); + return -5; + } + + tls_version_major = data[1]; + tls_version_minor = data[2]; + if (tls_version_major < 3) { + if (verbose) + LOGI("Received SSL %d.%d handshake which can not support SNI.", + tls_version_major, tls_version_minor); + + return -2; + } + + /* TLS record length */ + len = ((unsigned char)data[3] << 8) + + (unsigned char)data[4] + TLS_HEADER_LEN; + data_len = MIN(data_len, len); + + /* Check we received entire TLS record length */ + if (data_len < len) + return -1; + + /* + * Handshake + */ + if (pos + 1 > data_len) { + return -5; + } + if (data[pos] != TLS_HANDSHAKE_TYPE_CLIENT_HELLO) { + if (verbose) + LOGI("Not a client hello"); + + return -5; + } + + /* Skip past fixed length records: + * 1 Handshake Type + * 3 Length + * 2 Version (again) + * 32 Random + * to Session ID Length + */ + pos += 38; + + /* Session ID */ + if (pos + 1 > data_len) + return -5; + len = (unsigned char)data[pos]; + pos += 1 + len; + + /* Cipher Suites */ + if (pos + 2 > data_len) + return -5; + len = ((unsigned char)data[pos] << 8) + (unsigned char)data[pos + 1]; + pos += 2 + len; + + /* Compression Methods */ + if (pos + 1 > data_len) + return -5; + len = (unsigned char)data[pos]; + pos += 1 + len; + + if (pos == data_len && tls_version_major == 3 && tls_version_minor == 0) { + if (verbose) + LOGI("Received SSL 3.0 handshake without extensions"); + return -2; + } + + /* Extensions */ + if (pos + 2 > data_len) + return -5; + len = ((unsigned char)data[pos] << 8) + (unsigned char)data[pos + 1]; + pos += 2; + + if (pos + len > data_len) + return -5; + return parse_extensions(data + pos, len, hostname); +} + +static int +parse_extensions(const char *data, size_t data_len, char **hostname) +{ + size_t pos = 0; + size_t len; + + /* Parse each 4 bytes for the extension header */ + while (pos + 4 <= data_len) { + /* Extension Length */ + len = ((unsigned char)data[pos + 2] << 8) + + (unsigned char)data[pos + 3]; + + /* Check if it's a server name extension */ + if (data[pos] == 0x00 && data[pos + 1] == 0x00) { + /* There can be only one extension of each type, so we break + * our state and move p to beinnging of the extension here */ + if (pos + 4 + len > data_len) + return -5; + return parse_server_name_extension(data + pos + 4, len, hostname); + } + pos += 4 + len; /* Advance to the next extension header */ + } + /* Check we ended where we expected to */ + if (pos != data_len) + return -5; + + return -2; +} + +static int +parse_server_name_extension(const char *data, size_t data_len, + char **hostname) +{ + size_t pos = 2; /* skip server name list length */ + size_t len; + + while (pos + 3 < data_len) { + len = ((unsigned char)data[pos + 1] << 8) + + (unsigned char)data[pos + 2]; + + if (pos + 3 + len > data_len) + return -5; + + switch (data[pos]) { /* name type */ + case 0x00: /* host_name */ + *hostname = malloc(len + 1); + if (*hostname == NULL) { + ERROR("malloc() failure"); + return -4; + } + + strncpy(*hostname, data + pos + 3, len); + + (*hostname)[len] = '\0'; + + return len; + default: + if (verbose) + LOGI("Unknown server name extension name type: %d", + data[pos]); + } + pos += 3 + len; + } + /* Check we ended where we expected to */ + if (pos != data_len) + return -5; + + return -2; +} diff --git a/shadowsocksr-libev/src/server/tls.h b/shadowsocksr-libev/src/server/tls.h new file mode 100644 index 0000000..3998913 --- /dev/null +++ b/shadowsocksr-libev/src/server/tls.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2011 and 2012, Dustin Lundquist + * 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 HOLDER 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. + */ +#ifndef TLS_H +#define TLS_H + +#include "protocol.h" + +const protocol_t *const tls_protocol; + +#endif diff --git a/shadowsocksr-libev/src/server/tls1.2_ticket.c b/shadowsocksr-libev/src/server/tls1.2_ticket.c new file mode 100644 index 0000000..88970c0 --- /dev/null +++ b/shadowsocksr-libev/src/server/tls1.2_ticket.c @@ -0,0 +1,609 @@ + +#include "tls1.2_ticket.h" +#include "list.c" + +typedef struct tls12_ticket_auth_global_data { + uint8_t local_client_id[32]; + List client_data; + time_t startup_time; +}tls12_ticket_auth_global_data; + +typedef struct tls12_ticket_auth_local_data { + int handshake_status; + char *send_buffer; + int send_buffer_size; + char *recv_buffer; + int recv_buffer_size; +}tls12_ticket_auth_local_data; + +void tls12_ticket_auth_local_data_init(tls12_ticket_auth_local_data* local) { + local->handshake_status = 0; + local->send_buffer = malloc(0); + local->send_buffer_size = 0; + local->recv_buffer = malloc(0); + local->recv_buffer_size = 0; +} + +void * tls12_ticket_auth_init_data() { + tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)malloc(sizeof(tls12_ticket_auth_global_data)); + rand_bytes(global->local_client_id, 32); + global->client_data = list_init(22); + global->startup_time = time(NULL); + return global; +} + +obfs * tls12_ticket_auth_new_obfs() { + obfs * self = new_obfs(); + self->l_data = malloc(sizeof(tls12_ticket_auth_local_data)); + tls12_ticket_auth_local_data_init((tls12_ticket_auth_local_data*)self->l_data); + return self; +} + +void tls12_ticket_auth_dispose(obfs *self) { + tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data; + if (local->send_buffer != NULL) { + free(local->send_buffer); + local->send_buffer = NULL; + } + if (local->recv_buffer != NULL) { + free(local->recv_buffer); + local->recv_buffer = NULL; + } + free(local); + dispose_obfs(self); +} + +int tls12_ticket_pack_auth_data(tls12_ticket_auth_global_data *global, server_info *server, char *outdata) { + int out_size = 32; + time_t t = time(NULL); + outdata[0] = t >> 24; + outdata[1] = t >> 16; + outdata[2] = t >> 8; + outdata[3] = t; + rand_bytes((uint8_t*)outdata + 4, 18); + + uint8_t *key = (uint8_t*)malloc(server->key_len + 32); + char hash[ONETIMEAUTH_BYTES * 2]; + memcpy(key, server->key, server->key_len); + memcpy(key + server->key_len, global->local_client_id, 32); + ss_sha1_hmac_with_key(hash, outdata, out_size - OBFS_HMAC_SHA1_LEN, key, server->key_len + 32); + free(key); + memcpy(outdata + out_size - OBFS_HMAC_SHA1_LEN, hash, OBFS_HMAC_SHA1_LEN); + return out_size; +} + +void tls12_ticket_auth_pack_data(char *encryptdata, int datalength, int start, int len, char *out_buffer, int outlength) { + out_buffer[outlength] = 0x17; + out_buffer[outlength + 1] = 0x3; + out_buffer[outlength + 2] = 0x3; + out_buffer[outlength + 3] = len >> 8; + out_buffer[outlength + 4] = len; + memcpy(out_buffer + outlength + 5, encryptdata + start, len); +} + +int tls12_ticket_auth_client_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity) { + char *encryptdata = *pencryptdata; + tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data; + tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)self->server.g_data; + char * out_buffer = NULL; + + if (local->handshake_status == 8) { + if (datalength < 1024) { + if (*capacity < datalength + 5) { + *pencryptdata = (char*)realloc(*pencryptdata, *capacity = (datalength + 5) * 2); + encryptdata = *pencryptdata; + } + memmove(encryptdata + 5, encryptdata, datalength); + encryptdata[0] = 0x17; + encryptdata[1] = 0x3; + encryptdata[2] = 0x3; + encryptdata[3] = datalength >> 8; + encryptdata[4] = datalength; + return datalength + 5; + } else { + out_buffer = (char*)malloc(datalength + 2048); + int start = 0; + int outlength = 0; + int len; + while (datalength - start > 2048) { + len = xorshift128plus() % 4096 + 100; + if (len > datalength - start) + len = datalength - start; + tls12_ticket_auth_pack_data(encryptdata, datalength, start, len, out_buffer, outlength); + outlength += len + 5; + start += len; + } + if (datalength - start > 0) { + len = datalength - start; + tls12_ticket_auth_pack_data(encryptdata, datalength, start, len, out_buffer, outlength); + outlength += len + 5; + } + if (*capacity < outlength) { + *pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2); + encryptdata = *pencryptdata; + } + memcpy(encryptdata, out_buffer, outlength); + free(out_buffer); + return outlength; + } + } + local->send_buffer = (char*)realloc(local->send_buffer, local->send_buffer_size + datalength + 5); + memcpy(local->send_buffer + local->send_buffer_size + 5, encryptdata, datalength); + local->send_buffer[local->send_buffer_size] = 0x17; + local->send_buffer[local->send_buffer_size + 1] = 0x3; + local->send_buffer[local->send_buffer_size + 2] = 0x3; + local->send_buffer[local->send_buffer_size + 3] = datalength >> 8; + local->send_buffer[local->send_buffer_size + 4] = datalength; + local->send_buffer_size += datalength + 5; + + if (local->handshake_status == 0) { +#define CSTR_DECL(name, len, str) const char* name = str; const int len = sizeof(str) - 1; + CSTR_DECL(tls_data0, tls_data0_len, "\x00\x1c\xc0\x2b\xc0\x2f\xcc\xa9\xcc\xa8\xcc\x14\xcc\x13\xc0\x0a\xc0\x14\xc0\x09\xc0\x13\x00\x9c\x00\x35\x00\x2f\x00\x0a\x01\x00" + ); + CSTR_DECL(tls_data1, tls_data1_len, "\xff\x01\x00\x01\x00" + ); + CSTR_DECL(tls_data2, tls_data2_len, "\x00\x17\x00\x00\x00\x23\x00\xd0"); + CSTR_DECL(tls_data3, tls_data3_len, "\x00\x0d\x00\x16\x00\x14\x06\x01\x06\x03\x05\x01\x05\x03\x04\x01\x04\x03\x03\x01\x03\x03\x02\x01\x02\x03\x00\x05\x00\x05\x01\x00\x00\x00\x00\x00\x12\x00\x00\x75\x50\x00\x00\x00\x0b\x00\x02\x01\x00\x00\x0a\x00\x06\x00\x04\x00\x17\x00\x18" + //"00150066000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" // padding + ); + uint8_t tls_data[2048]; + int tls_data_len = 0; + memcpy(tls_data, tls_data1, tls_data1_len); + tls_data_len += tls_data1_len; + + char hosts[1024]; + char * phost[128]; + int host_num = 0; + int pos; + + char sni[256] = {0}; + if (self->server.param && strlen(self->server.param) == 0) + self->server.param = NULL; + strncpy(hosts, self->server.param ? self->server.param : self->server.host, sizeof hosts); + phost[host_num++] = hosts; + for (pos = 0; hosts[pos]; ++pos) { + if (hosts[pos] == ',') { + phost[host_num++] = &hosts[pos + 1]; + } + } + host_num = xorshift128plus() % host_num; + + sprintf(sni, "%s", phost[host_num]); + int sni_len = strlen(sni); + if (sni_len > 0 && sni[sni_len - 1] >= '0' && sni[sni_len - 1] <= '9') + sni_len = 0; + tls_data[tls_data_len] = '\0'; + tls_data[tls_data_len + 1] = '\0'; + tls_data[tls_data_len + 2] = (sni_len + 5) >> 8; + tls_data[tls_data_len + 3] = (sni_len + 5); + tls_data[tls_data_len + 4] = (sni_len + 3) >> 8; + tls_data[tls_data_len + 5] = (sni_len + 3); + tls_data[tls_data_len + 6] = '\0'; + tls_data[tls_data_len + 7] = sni_len >> 8; + tls_data[tls_data_len + 8] = sni_len; + memcpy(tls_data + tls_data_len + 9, sni, sni_len); + tls_data_len += 9 + sni_len; + memcpy(tls_data + tls_data_len, tls_data2, tls_data2_len); + tls_data_len += tls_data2_len; + rand_bytes(tls_data + tls_data_len, 208); + tls_data_len += 208; + memcpy(tls_data + tls_data_len, tls_data3, tls_data3_len); + tls_data_len += tls_data3_len; + + datalength = 11 + 32 + 1 + 32 + tls_data0_len + 2 + tls_data_len; + out_buffer = (char*)malloc(datalength); + char *pdata = out_buffer + datalength - tls_data_len; + int len = tls_data_len; + memcpy(pdata, tls_data, tls_data_len); + pdata[-1] = tls_data_len; + pdata[-2] = tls_data_len >> 8; + pdata -= 2; len += 2; + memcpy(pdata - tls_data0_len, tls_data0, tls_data0_len); + pdata -= tls_data0_len; len += tls_data0_len; + memcpy(pdata - 32, global->local_client_id, 32); + pdata -= 32; len += 32; + pdata[-1] = 0x20; + pdata -= 1; len += 1; + tls12_ticket_pack_auth_data(global, &self->server, pdata - 32); + pdata -= 32; len += 32; + pdata[-1] = 0x3; + pdata[-2] = 0x3; // tls version + pdata -= 2; len += 2; + pdata[-1] = len; + pdata[-2] = len >> 8; + pdata[-3] = 0; + pdata[-4] = 1; + pdata -= 4; len += 4; + + pdata[-1] = len; + pdata[-2] = len >> 8; + pdata -= 2; len += 2; + pdata[-1] = 0x1; + pdata[-2] = 0x3; // tls version + pdata -= 2; len += 2; + pdata[-1] = 0x16; // tls handshake + pdata -= 1; len += 1; + + local->handshake_status = 1; + } else if (datalength == 0) { + datalength = local->send_buffer_size + 43; + out_buffer = (char*)malloc(datalength); + char *pdata = out_buffer; + memcpy(pdata, "\x14\x03\x03\x00\x01\x01", 6); + pdata += 6; + memcpy(pdata, "\x16\x03\x03\x00\x20", 5); + pdata += 5; + rand_bytes((uint8_t*)pdata, 22); + pdata += 22; + + uint8_t *key = (uint8_t*)malloc(self->server.key_len + 32); + char hash[ONETIMEAUTH_BYTES * 2]; + memcpy(key, self->server.key, self->server.key_len); + memcpy(key + self->server.key_len, global->local_client_id, 32); + ss_sha1_hmac_with_key(hash, out_buffer, pdata - out_buffer, key, self->server.key_len + 32); + free(key); + memcpy(pdata, hash, OBFS_HMAC_SHA1_LEN); + + pdata += OBFS_HMAC_SHA1_LEN; + memcpy(pdata, local->send_buffer, local->send_buffer_size); + free(local->send_buffer); + local->send_buffer = NULL; + + local->handshake_status = 8; + } else { + return 0; + } + if (*capacity < datalength) { + *pencryptdata = (char*)realloc(*pencryptdata, *capacity = datalength * 2); + encryptdata = *pencryptdata; + } + memmove(encryptdata, out_buffer, datalength); + free(out_buffer); + return datalength; +} + +int tls12_ticket_auth_server_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity) { + char *encryptdata = *pencryptdata; + tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data; + tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)self->server.g_data; + char * out_buffer = NULL; + + if (local->handshake_status == 8) { + if (datalength < 1024) { + if (*capacity < datalength + 5) { + *pencryptdata = (char*)realloc(*pencryptdata, *capacity = (datalength + 5) * 2); + encryptdata = *pencryptdata; + } + memmove(encryptdata + 5, encryptdata, datalength); + encryptdata[0] = 0x17; + encryptdata[1] = 0x3; + encryptdata[2] = 0x3; + encryptdata[3] = datalength >> 8; + encryptdata[4] = datalength; + return datalength + 5; + } else { + out_buffer = (char*)malloc(datalength + 2048); + int start = 0; + int outlength = 0; + int len; + while (datalength - start > 2048) { + len = xorshift128plus() % 4096 + 100; + if (len > datalength - start) + len = datalength - start; + tls12_ticket_auth_pack_data(encryptdata, datalength, start, len, out_buffer, outlength); + outlength += len + 5; + start += len; + } + if (datalength - start > 0) { + len = datalength - start; + tls12_ticket_auth_pack_data(encryptdata, datalength, start, len, out_buffer, outlength); + outlength += len + 5; + } + if (*capacity < outlength) { + *pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2); + encryptdata = *pencryptdata; + } + memcpy(encryptdata, out_buffer, outlength); + free(out_buffer); + return outlength; + } + } + + local->handshake_status = 3; + + out_buffer = (char*)malloc(43 + 86); + int data_len = 0; + char *p_data = out_buffer + 86; + + memcpy(p_data - 10, "\xc0\x2f\x00\x00\x05\xff\x01\x00\x01\x00", 10); + p_data -= 10;data_len += 10; + + memcpy(p_data - 32, global->local_client_id, 32); + p_data -= 32;data_len += 32; + + p_data[-1] = 0x20; + p_data -= 1;data_len += 1; + + tls12_ticket_pack_auth_data(global, &self->server, p_data - 32); + p_data -= 32;data_len += 32; + + p_data[-1] = 0x3; + p_data[-2] = 0x3; // tls version + p_data -= 2;data_len += 2; + + p_data[-1] = data_len; + p_data[-2] = data_len >> 8; + p_data[-3] = 0x00; + p_data[-4] = 0x02; + p_data -= 4; data_len += 4; + + p_data[-1] = data_len; + p_data[-2] = data_len >> 8; + p_data[-3] = 0x03; + p_data[-4] = 0x03; + p_data[-5] = 0x16; + p_data -= 5; data_len += 5; + + memcpy(out_buffer, p_data, data_len); + char *pdata = out_buffer + 86; + + memcpy(pdata, "\x14\x03\x03\x00\x01\x01", 6); + pdata += 6; + memcpy(pdata, "\x16\x03\x03\x00\x20", 5); + pdata += 5; + rand_bytes((uint8_t*)pdata, 22); + pdata += 22; + + uint8_t *key = (uint8_t*)malloc(self->server.key_len + 32); + char hash[ONETIMEAUTH_BYTES * 2]; + memcpy(key, self->server.key, self->server.key_len); + memcpy(key + self->server.key_len, global->local_client_id, 32); + ss_sha1_hmac_with_key(hash, out_buffer, 43 + 86, key, self->server.key_len + 32); + free(key); + memcpy(pdata, hash, OBFS_HMAC_SHA1_LEN); + + memmove(encryptdata, out_buffer, 43 + 86); + free(out_buffer); + return 43 + 86; +} + +int tls12_ticket_auth_client_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback) { + char *encryptdata = *pencryptdata; + tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data; + tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)self->server.g_data; + + *needsendback = 0; + + if (local->handshake_status == 8) { + local->recv_buffer_size += datalength; + local->recv_buffer = (char*)realloc(local->recv_buffer, local->recv_buffer_size); + memcpy(local->recv_buffer + local->recv_buffer_size - datalength, encryptdata, datalength); + datalength = 0; + while (local->recv_buffer_size > 5) { + if (local->recv_buffer[0] != 0x17) + return -1; + int size = ((int)(unsigned char)local->recv_buffer[3] << 8) + (unsigned char)local->recv_buffer[4]; + if (size + 5 > local->recv_buffer_size) + break; + if (*capacity < datalength + size) { + *pencryptdata = (char*)realloc(*pencryptdata, *capacity = (datalength + size) * 2); + encryptdata = *pencryptdata; + } + memcpy(encryptdata + datalength, local->recv_buffer + 5, size); + datalength += size; + local->recv_buffer_size -= 5 + size; + memmove(local->recv_buffer, local->recv_buffer + 5 + size, local->recv_buffer_size); + } + return datalength; + } + if (datalength < 11 + 32 + 1 + 32) { + return -1; + } + + uint8_t *key = (uint8_t*)malloc(self->server.key_len + 32); + char hash[ONETIMEAUTH_BYTES * 2]; + memcpy(key, self->server.key, self->server.key_len); + memcpy(key + self->server.key_len, global->local_client_id, 32); + ss_sha1_hmac_with_key(hash, encryptdata + 11, 22, key, self->server.key_len + 32); + free(key); + + if (memcmp(encryptdata + 33, hash, OBFS_HMAC_SHA1_LEN)) { + return -1; + } + + *needsendback = 1; + return 0; +} + +int tls12_ticket_auth_server_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback) { + char *encryptdata = *pencryptdata; + tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data; + tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)self->server.g_data; + + *needsendback = 0; + + if (local->handshake_status == 8) { + if(datalength != 0) + { + local->recv_buffer = (char*)realloc(local->recv_buffer, local->recv_buffer_size + datalength); + memmove(local->recv_buffer + local->recv_buffer_size, encryptdata, datalength); + local->recv_buffer_size += datalength; + } + datalength = 0; + + while (local->recv_buffer_size > 5) { + if (local->recv_buffer[0] != 0x17 || local->recv_buffer[1] != 0x03 || local->recv_buffer[2] != 0x03) + { + LOGE("server_decode data error, wrong tls version 3"); + return -1; + } + int size = ((int)(unsigned char)local->recv_buffer[3] << 8) + (unsigned char)local->recv_buffer[4]; + if (size + 5 > local->recv_buffer_size) + break; + if (*capacity < local->recv_buffer_size + size) { + *pencryptdata = (char*)realloc(*pencryptdata, *capacity = (local->recv_buffer_size + size) * 2); + encryptdata = *pencryptdata; + } + memcpy(encryptdata + datalength, local->recv_buffer + 5, size); + datalength += size; + local->recv_buffer_size -= 5 + size; + memmove(local->recv_buffer, local->recv_buffer + 5 + size, local->recv_buffer_size); + } + return datalength; + } + + if (local->handshake_status == 3) { + + char *verify = encryptdata; + + if(datalength < 43) + { + LOGE("server_decode data error, too short:%d", (int)datalength); + return -1; + } + + if(encryptdata[0] != 0x14 || encryptdata[1] != 0x03 || encryptdata[2] != 0x03 || encryptdata[3] != 0x00 || encryptdata[4] != 0x01 || encryptdata[5] != 0x01) + { + LOGE("server_decode data error, wrong tls version"); + return -1; + } + + encryptdata += 6; + + if(encryptdata[0] != 0x16 || encryptdata[1] != 0x03 || encryptdata[2] != 0x03 || encryptdata[3] != 0x00 || encryptdata[4] != 0x20) + { + LOGE("server_decode data error, wrong tls version 2"); + return -1; + } + + uint8_t *key = (uint8_t*)malloc(self->server.key_len + 32); + char hash[ONETIMEAUTH_BYTES * 2]; + memcpy(key, self->server.key, self->server.key_len); + memcpy(key + self->server.key_len, global->local_client_id, 32); + ss_sha1_hmac_with_key(hash, verify, 33, key, self->server.key_len + 32); + free(key); + + if (memcmp(verify + 33, hash, OBFS_HMAC_SHA1_LEN) != 0) { + LOGE("server_decode data error, hash Mismatch %d",(int)memcmp(verify + 33, hash, OBFS_HMAC_SHA1_LEN)); + return -1; + } + + local->recv_buffer_size = datalength - 43; + local->recv_buffer = (char*)realloc(local->recv_buffer, local->recv_buffer_size); + memmove(local->recv_buffer, encryptdata + 37, datalength - 43); + + local->handshake_status = 8; + return tls12_ticket_auth_server_decode(self, pencryptdata, 0, capacity, needsendback); + } + + local->handshake_status = 2; + if(encryptdata[0] != 0x16 || encryptdata[1] != 0x03 || encryptdata[2] != 0x01) + { + return -1; + } + + encryptdata += 3; + + { + int size = ((int)(unsigned char)encryptdata[0] << 8) + (unsigned char)encryptdata[1]; + if(size != datalength - 5) + { + LOGE("tls_auth wrong tls head size"); + return -1; + } + } + + encryptdata += 2; + + if(encryptdata[0] != 0x01 || encryptdata[1] != 0x00) + { + LOGE("tls_auth not client hello message"); + return -1; + } + + encryptdata += 2; + + { + int size = ((int)(unsigned char)encryptdata[0] << 8) + (unsigned char)encryptdata[1]; + if(size != datalength - 9) + { + LOGE("tls_auth wrong message size"); + return -1; + } + } + + encryptdata += 2; + + if(encryptdata[0] != 0x03 || encryptdata[1] != 0x03) + { + LOGE("tls_auth wrong tls version"); + return -1; + } + + encryptdata += 2; + + char *verifyid = encryptdata; + + encryptdata += 32; + + int sessionid_len = encryptdata[0]; + if(sessionid_len < 32) + { + LOGE("tls_auth wrong sessionid_len"); + return -1; + } + + char *sessionid = encryptdata + 1; + memcpy(global->local_client_id , sessionid, sessionid_len); + + uint8_t *key = (uint8_t*)malloc(self->server.key_len + sessionid_len); + char hash[ONETIMEAUTH_BYTES * 2]; + memcpy(key, self->server.key, self->server.key_len); + memcpy(key + self->server.key_len, global->local_client_id, sessionid_len); + ss_sha1_hmac_with_key(hash, verifyid, 22, key, self->server.key_len + sessionid_len); + free(key); + + encryptdata += (sessionid_len + 1); + + long utc_time = ((int)(unsigned char)verifyid[0] << 24) + ((int)(unsigned char)verifyid[1] << 16) + ((int)(unsigned char)verifyid[2] << 8) + (unsigned char)verifyid[3]; + time_t t = time(NULL); + + + if (self->server.param && strlen(self->server.param) == 0) + { + self->server.param = NULL; + } + + int max_time_dif = 0; + int time_dif = utc_time - t; + if(self->server.param) + { + max_time_dif = atoi(self->server.param); + } + + if(max_time_dif > 0 && (time_dif < -max_time_dif || time_dif > max_time_dif || utc_time - global->startup_time < -max_time_dif / 2)) + { + LOGE("tls_auth wrong time"); + return -1; + } + + if (memcmp(verifyid + 22, hash, OBFS_HMAC_SHA1_LEN)) { + LOGE("tls_auth wrong sha1"); + return -1; + } + + int search_result = global->client_data->have_same_cmp(global->client_data, verifyid); + if(search_result != 0) + { + LOGE("replay attack detect!"); + return -1; + } + + global->client_data->add_back(global->client_data, verifyid); + + encryptdata += 48; + + *needsendback = 1; + + return 0; +} diff --git a/shadowsocksr-libev/src/server/tls1.2_ticket.h b/shadowsocksr-libev/src/server/tls1.2_ticket.h new file mode 100644 index 0000000..10a57c9 --- /dev/null +++ b/shadowsocksr-libev/src/server/tls1.2_ticket.h @@ -0,0 +1,20 @@ +/* + * http_simple.h - Define shadowsocksR server's buffers and callbacks + * + * Copyright (C) 2015 - 2016, Break Wa11 + */ + +#ifndef _TLS1_2_TICKET_H +#define _TLS1_2_TICKET_H + +void * tls12_ticket_auth_init_data(); +obfs * tls12_ticket_auth_new_obfs(); +void tls12_ticket_auth_dispose(obfs *self); + +int tls12_ticket_auth_client_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity); +int tls12_ticket_auth_client_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback); + +int tls12_ticket_auth_server_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity); +int tls12_ticket_auth_server_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback); + +#endif // _TLS1_2_TICKET_H diff --git a/shadowsocksr-libev/src/server/udprelay.c b/shadowsocksr-libev/src/server/udprelay.c new file mode 100644 index 0000000..d9251ee --- /dev/null +++ b/shadowsocksr-libev/src/server/udprelay.c @@ -0,0 +1,1452 @@ +/* + * udprelay.c - Setup UDP relay for both client and server + * + * Copyright (C) 2013 - 2016, Max Lv + * + * This file is part of the shadowsocks-libev. + * + * shadowsocks-libev is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * shadowsocks-libev 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with shadowsocks-libev; see the file COPYING. If not, see + * . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef __MINGW32__ +#include +#include +#include +#include +#include +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_NET_IF_H) && defined(__linux__) +#include +#include +#define SET_INTERFACE +#endif + +#ifdef __MINGW32__ +#include "win32.h" +#endif + +#include +#include + +#include "utils.h" +#include "netutils.h" +#include "cache.h" +#include "udprelay.h" + +#ifdef MODULE_REMOTE +#define MAX_UDP_CONN_NUM 512 +#else +#define MAX_UDP_CONN_NUM 256 +#endif + +#ifdef MODULE_REMOTE +#ifdef MODULE_ +#error "MODULE_REMOTE and MODULE_LOCAL should not be both defined" +#endif +#endif + +#ifndef EAGAIN +#define EAGAIN EWOULDBLOCK +#endif + +#ifndef EWOULDBLOCK +#define EWOULDBLOCK EAGAIN +#endif + +static void server_recv_cb(EV_P_ ev_io *w, int revents); +static void remote_recv_cb(EV_P_ ev_io *w, int revents); +static void remote_timeout_cb(EV_P_ ev_timer *watcher, int revents); + +static char *hash_key(const int af, const struct sockaddr_storage *addr); +#ifdef MODULE_REMOTE +static void query_resolve_cb(struct sockaddr *addr, void *data); +#endif +static void close_and_free_remote(EV_P_ remote_ctx_t *ctx); +static remote_ctx_t *new_remote(int fd, server_ctx_t *server_ctx); + +#ifdef ANDROID +extern uint64_t tx; +extern uint64_t rx; +extern int vpn; +#endif + +extern int verbose; +#ifdef MODULE_REMOTE +extern uint64_t tx; +extern uint64_t rx; +#endif + +static int packet_size = DEFAULT_PACKET_SIZE; +static int buf_size = DEFAULT_PACKET_SIZE * 2; +static int server_num = 0; +static server_ctx_t *server_ctx_list[MAX_REMOTE_NUM] = { NULL }; + +#ifndef __MINGW32__ +static int +setnonblocking(int fd) +{ + int flags; + if (-1 == (flags = fcntl(fd, F_GETFL, 0))) { + flags = 0; + } + return fcntl(fd, F_SETFL, flags | O_NONBLOCK); +} + +#endif + +#if defined(MODULE_REMOTE) && defined(SO_BROADCAST) +static int +set_broadcast(int socket_fd) +{ + int opt = 1; + return setsockopt(socket_fd, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt)); +} + +#endif + +#ifdef SO_NOSIGPIPE +static int +set_nosigpipe(int socket_fd) +{ + int opt = 1; + return setsockopt(socket_fd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); +} + +#endif + +#ifdef MODULE_REDIR + +#ifndef IP_TRANSPARENT +#define IP_TRANSPARENT 19 +#endif + +#ifndef IP_RECVORIGDSTADDR +#define IP_RECVORIGDSTADDR 20 +#endif + +static int +get_dstaddr(struct msghdr *msg, struct sockaddr_storage *dstaddr) +{ + struct cmsghdr *cmsg; + + for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { + if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVORIGDSTADDR) { + memcpy(dstaddr, CMSG_DATA(cmsg), sizeof(struct sockaddr_in)); + dstaddr->ss_family = AF_INET; + return 0; + } else if (cmsg->cmsg_level == SOL_IPV6 && cmsg->cmsg_type == IP_RECVORIGDSTADDR) { + memcpy(dstaddr, CMSG_DATA(cmsg), sizeof(struct sockaddr_in6)); + dstaddr->ss_family = AF_INET6; + return 0; + } + } + + return 1; +} + +#endif + +#define HASH_KEY_LEN sizeof(struct sockaddr_storage) + sizeof(int) +static char * +hash_key(const int af, const struct sockaddr_storage *addr) +{ + size_t addr_len = sizeof(struct sockaddr_storage); + static char key[HASH_KEY_LEN]; + + memset(key, 0, HASH_KEY_LEN); + memcpy(key, &af, sizeof(int)); + memcpy(key + sizeof(int), (const uint8_t *)addr, addr_len); + + return key; +} + +#if defined(MODULE_REDIR) || defined(MODULE_REMOTE) +static int +construct_udprealy_header(const struct sockaddr_storage *in_addr, + char *addr_header) +{ + int addr_header_len = 0; + if (in_addr->ss_family == AF_INET) { + struct sockaddr_in *addr = (struct sockaddr_in *)in_addr; + size_t addr_len = sizeof(struct in_addr); + addr_header[addr_header_len++] = 1; + memcpy(addr_header + addr_header_len, &addr->sin_addr, addr_len); + addr_header_len += addr_len; + memcpy(addr_header + addr_header_len, &addr->sin_port, 2); + addr_header_len += 2; + } else if (in_addr->ss_family == AF_INET6) { + struct sockaddr_in6 *addr = (struct sockaddr_in6 *)in_addr; + size_t addr_len = sizeof(struct in6_addr); + addr_header[addr_header_len++] = 4; + memcpy(addr_header + addr_header_len, &addr->sin6_addr, addr_len); + addr_header_len += addr_len; + memcpy(addr_header + addr_header_len, &addr->sin6_port, 2); + addr_header_len += 2; + } else { + return 0; + } + return addr_header_len; +} + +#endif + +static int +parse_udprealy_header(const char *buf, const size_t buf_len, + char *host, char *port, struct sockaddr_storage *storage) +{ + const uint8_t atyp = *(uint8_t *)buf; + int offset = 1; + + // get remote addr and port + if ((atyp & ADDRTYPE_MASK) == 1) { + // IP V4 + size_t in_addr_len = sizeof(struct in_addr); + if (buf_len >= in_addr_len + 3) { + if (storage != NULL) { + struct sockaddr_in *addr = (struct sockaddr_in *)storage; + addr->sin_family = AF_INET; + addr->sin_addr = *(struct in_addr *)(buf + offset); + addr->sin_port = *(uint16_t *)(buf + offset + in_addr_len); + } + if (host != NULL) { + dns_ntop(AF_INET, (const void *)(buf + offset), + host, INET_ADDRSTRLEN); + } + offset += in_addr_len; + } + } else if ((atyp & ADDRTYPE_MASK) == 3) { + // Domain name + uint8_t name_len = *(uint8_t *)(buf + offset); + if (name_len + 4 <= buf_len) { + if (storage != NULL) { + char tmp[257] = { 0 }; + struct cork_ip ip; + memcpy(tmp, buf + offset + 1, name_len); + if (cork_ip_init(&ip, tmp) != -1) { + if (ip.version == 4) { + struct sockaddr_in *addr = (struct sockaddr_in *)storage; + dns_pton(AF_INET, tmp, &(addr->sin_addr)); + addr->sin_port = *(uint16_t *)(buf + offset + 1 + name_len); + addr->sin_family = AF_INET; + } else if (ip.version == 6) { + struct sockaddr_in6 *addr = (struct sockaddr_in6 *)storage; + dns_pton(AF_INET, tmp, &(addr->sin6_addr)); + addr->sin6_port = *(uint16_t *)(buf + offset + 1 + name_len); + addr->sin6_family = AF_INET6; + } + } + } + if (host != NULL) { + memcpy(host, buf + offset + 1, name_len); + } + offset += 1 + name_len; + } + } else if ((atyp & ADDRTYPE_MASK) == 4) { + // IP V6 + size_t in6_addr_len = sizeof(struct in6_addr); + if (buf_len >= in6_addr_len + 3) { + if (storage != NULL) { + struct sockaddr_in6 *addr = (struct sockaddr_in6 *)storage; + addr->sin6_family = AF_INET6; + addr->sin6_addr = *(struct in6_addr *)(buf + offset); + addr->sin6_port = *(uint16_t *)(buf + offset + in6_addr_len); + } + if (host != NULL) { + dns_ntop(AF_INET6, (const void *)(buf + offset), + host, INET6_ADDRSTRLEN); + } + offset += in6_addr_len; + } + } + + if (offset == 1) { + LOGE("[udp] invalid header with addr type %d", atyp); + return 0; + } + + if (port != NULL) { + sprintf(port, "%d", ntohs(*(uint16_t *)(buf + offset))); + } + offset += 2; + + return offset; +} + +static char * +get_addr_str(const struct sockaddr *sa) +{ + static char s[SS_ADDRSTRLEN]; + memset(s, 0, SS_ADDRSTRLEN); + char addr[INET6_ADDRSTRLEN] = { 0 }; + char port[PORTSTRLEN] = { 0 }; + uint16_t p; + + switch (sa->sa_family) { + case AF_INET: + dns_ntop(AF_INET, &(((struct sockaddr_in *)sa)->sin_addr), + addr, INET_ADDRSTRLEN); + p = ntohs(((struct sockaddr_in *)sa)->sin_port); + sprintf(port, "%d", p); + break; + + case AF_INET6: + dns_ntop(AF_INET6, &(((struct sockaddr_in6 *)sa)->sin6_addr), + addr, INET6_ADDRSTRLEN); + p = ntohs(((struct sockaddr_in *)sa)->sin_port); + sprintf(port, "%d", p); + break; + + default: + strncpy(s, "Unknown AF", SS_ADDRSTRLEN); + } + + int addr_len = strlen(addr); + int port_len = strlen(port); + memcpy(s, addr, addr_len); + memcpy(s + addr_len + 1, port, port_len); + s[addr_len] = ':'; + + return s; +} + +int +create_remote_socket(int ipv6) +{ + int remote_sock; + + if (ipv6) { + // Try to bind IPv6 first + struct sockaddr_in6 addr; + memset(&addr, 0, sizeof(struct sockaddr_in6)); + addr.sin6_family = AF_INET6; + addr.sin6_addr = in6addr_any; + addr.sin6_port = 0; + remote_sock = socket(AF_INET6, SOCK_DGRAM, 0); + if (remote_sock == -1) { + ERROR("[udp] cannot create socket"); + return -1; + } + if (bind(remote_sock, (struct sockaddr *)&addr, sizeof(addr)) != 0) { + FATAL("[udp] cannot bind remote"); + return -1; + } + } else { + // Or else bind to IPv4 + struct sockaddr_in addr; + memset(&addr, 0, sizeof(struct sockaddr_in)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = 0; + remote_sock = socket(AF_INET, SOCK_DGRAM, 0); + if (remote_sock == -1) { + ERROR("[udp] cannot create socket"); + return -1; + } + + if (bind(remote_sock, (struct sockaddr *)&addr, sizeof(addr)) != 0) { + FATAL("[udp] cannot bind remote"); + return -1; + } + } + return remote_sock; +} + +int +create_server_socket(const char *host, const char *port) +{ + struct addrinfo hints; + struct addrinfo *result, *rp, *ipv4v6bindall; + int s, server_sock; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; /* Return IPv4 and IPv6 choices */ + hints.ai_socktype = SOCK_DGRAM; /* We want a UDP socket */ + hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; /* For wildcard IP address */ + hints.ai_protocol = IPPROTO_UDP; + + s = getaddrinfo(host, port, &hints, &result); + if (s != 0) { + LOGE("[udp] getaddrinfo: %s", gai_strerror(s)); + return -1; + } + + rp = result; + + /* + * On Linux, with net.ipv6.bindv6only = 0 (the default), getaddrinfo(NULL) with + * AI_PASSIVE returns 0.0.0.0 and :: (in this order). AI_PASSIVE was meant to + * return a list of addresses to listen on, but it is impossible to listen on + * 0.0.0.0 and :: at the same time, if :: implies dualstack mode. + */ + if (!host) { + ipv4v6bindall = result; + + /* Loop over all address infos found until a IPV6 address is found. */ + while (ipv4v6bindall) { + if (ipv4v6bindall->ai_family == AF_INET6) { + rp = ipv4v6bindall; /* Take first IPV6 address available */ + break; + } + ipv4v6bindall = ipv4v6bindall->ai_next; /* Get next address info, if any */ + } + } + + for (/*rp = result*/; rp != NULL; rp = rp->ai_next) { + server_sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if (server_sock == -1) { + continue; + } + + if (rp->ai_family == AF_INET6) { + int ipv6only = host ? 1 : 0; + setsockopt(server_sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, sizeof(ipv6only)); + } + + int opt = 1; + setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); +#ifdef SO_NOSIGPIPE + set_nosigpipe(server_sock); +#endif + int err = set_reuseport(server_sock); + if (err == 0) { + LOGI("udp port reuse enabled"); + } +#ifdef IP_TOS + // Set QoS flag + int tos = 46; + setsockopt(server_sock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); +#endif + +#ifdef MODULE_REDIR + if (setsockopt(server_sock, SOL_IP, IP_TRANSPARENT, &opt, sizeof(opt))) { + ERROR("[udp] setsockopt IP_TRANSPARENT"); + exit(EXIT_FAILURE); + } + if (setsockopt(server_sock, IPPROTO_IP, IP_RECVORIGDSTADDR, &opt, sizeof(opt))) { + FATAL("[udp] setsockopt IP_RECVORIGDSTADDR"); + } +#endif + + s = bind(server_sock, rp->ai_addr, rp->ai_addrlen); + if (s == 0) { + /* We managed to bind successfully! */ + break; + } else { + ERROR("[udp] bind"); + } + + close(server_sock); + } + + if (rp == NULL) { + LOGE("[udp] cannot bind"); + return -1; + } + + freeaddrinfo(result); + + return server_sock; +} + +remote_ctx_t * +new_remote(int fd, server_ctx_t *server_ctx) +{ + remote_ctx_t *ctx = ss_malloc(sizeof(remote_ctx_t)); + memset(ctx, 0, sizeof(remote_ctx_t)); + + ctx->fd = fd; + ctx->server_ctx = server_ctx; + + ev_io_init(&ctx->io, remote_recv_cb, fd, EV_READ); + ev_timer_init(&ctx->watcher, remote_timeout_cb, server_ctx->timeout, + server_ctx->timeout); + + return ctx; +} + +server_ctx_t * +new_server_ctx(int fd) +{ + server_ctx_t *ctx = ss_malloc(sizeof(server_ctx_t)); + memset(ctx, 0, sizeof(server_ctx_t)); + + ctx->fd = fd; + + ev_io_init(&ctx->io, server_recv_cb, fd, EV_READ); + + return ctx; +} + +#ifdef MODULE_REMOTE +struct query_ctx * +new_query_ctx(char *buf, size_t len) +{ + struct query_ctx *ctx = ss_malloc(sizeof(struct query_ctx)); + memset(ctx, 0, sizeof(struct query_ctx)); + ctx->buf = ss_malloc(sizeof(buffer_t)); + balloc(ctx->buf, len); + memcpy(ctx->buf->array, buf, len); + ctx->buf->len = len; + return ctx; +} + +void +close_and_free_query(EV_P_ struct query_ctx *ctx) +{ + if (ctx != NULL) { + if (ctx->query != NULL) { + resolv_cancel(ctx->query); + ctx->query = NULL; + } + if (ctx->buf != NULL) { + bfree(ctx->buf); + ss_free(ctx->buf); + } + ss_free(ctx); + } +} + +#endif + +void +close_and_free_remote(EV_P_ remote_ctx_t *ctx) +{ + if (ctx != NULL) { + ev_timer_stop(EV_A_ & ctx->watcher); + ev_io_stop(EV_A_ & ctx->io); + close(ctx->fd); + ss_free(ctx); + } +} + +static void +remote_timeout_cb(EV_P_ ev_timer *watcher, int revents) +{ + remote_ctx_t *remote_ctx + = cork_container_of(watcher, remote_ctx_t, watcher); + + if (verbose) { + LOGI("[udp] connection timeout"); + } + + char *key = hash_key(remote_ctx->af, &remote_ctx->src_addr); + cache_remove(remote_ctx->server_ctx->conn_cache, key, HASH_KEY_LEN); +} + +#ifdef MODULE_REMOTE +static void +query_resolve_cb(struct sockaddr *addr, void *data) +{ + struct query_ctx *query_ctx = (struct query_ctx *)data; + struct ev_loop *loop = query_ctx->server_ctx->loop; + + if (verbose) { + LOGI("[udp] udns resolved"); + } + + query_ctx->query = NULL; + + if (addr == NULL) { + LOGE("[udp] udns returned an error"); + } else { + remote_ctx_t *remote_ctx = query_ctx->remote_ctx; + int cache_hit = 0; + + // Lookup in the conn cache + if (remote_ctx == NULL) { + char *key = hash_key(AF_UNSPEC, &query_ctx->src_addr); + cache_lookup(query_ctx->server_ctx->conn_cache, key, HASH_KEY_LEN, (void *)&remote_ctx); + } + + if (remote_ctx == NULL) { + int remotefd = create_remote_socket(addr->sa_family == AF_INET6); + if (remotefd != -1) { + setnonblocking(remotefd); +#ifdef SO_BROADCAST + set_broadcast(remotefd); +#endif +#ifdef SO_NOSIGPIPE + set_nosigpipe(remotefd); +#endif +#ifdef IP_TOS + // Set QoS flag + int tos = 46; + setsockopt(remotefd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); +#endif +#ifdef SET_INTERFACE + if (query_ctx->server_ctx->iface) { + if (setinterface(remotefd, query_ctx->server_ctx->iface) == -1) + ERROR("setinterface"); + } +#endif + remote_ctx = new_remote(remotefd, query_ctx->server_ctx); + remote_ctx->src_addr = query_ctx->src_addr; + remote_ctx->server_ctx = query_ctx->server_ctx; + remote_ctx->addr_header_len = query_ctx->addr_header_len; + memcpy(remote_ctx->addr_header, query_ctx->addr_header, + query_ctx->addr_header_len); + } else { + ERROR("[udp] bind() error"); + } + } else { + cache_hit = 1; + } + + if (remote_ctx != NULL) { + memcpy(&remote_ctx->dst_addr, addr, sizeof(struct sockaddr_storage)); + + size_t addr_len = get_sockaddr_len(addr); + int s = sendto(remote_ctx->fd, query_ctx->buf->array, query_ctx->buf->len, + 0, addr, addr_len); + + if (s == -1) { + ERROR("[udp] sendto_remote"); + if (!cache_hit) { + close_and_free_remote(EV_A_ remote_ctx); + } + } else { + if (!cache_hit) { + // Add to conn cache + char *key = hash_key(AF_UNSPEC, &remote_ctx->src_addr); + cache_insert(query_ctx->server_ctx->conn_cache, key, HASH_KEY_LEN, (void *)remote_ctx); + ev_io_start(EV_A_ & remote_ctx->io); + ev_timer_start(EV_A_ & remote_ctx->watcher); + } + } + } + } + + // clean up + close_and_free_query(EV_A_ query_ctx); +} + +#endif + +static void +remote_recv_cb(EV_P_ ev_io *w, int revents) +{ + ssize_t r; + remote_ctx_t *remote_ctx = (remote_ctx_t *)w; + server_ctx_t *server_ctx = remote_ctx->server_ctx; + + // server has been closed + if (server_ctx == NULL) { + LOGE("[udp] invalid server"); + close_and_free_remote(EV_A_ remote_ctx); + return; + } + + struct sockaddr_storage src_addr; + socklen_t src_addr_len = sizeof(struct sockaddr_storage); + memset(&src_addr, 0, src_addr_len); + + buffer_t *buf = ss_malloc(sizeof(buffer_t)); + balloc(buf, buf_size); + + // recv + r = recvfrom(remote_ctx->fd, buf->array, buf_size, 0, (struct sockaddr *)&src_addr, &src_addr_len); + + if (r == -1) { + // error on recv + // simply drop that packet + ERROR("[udp] remote_recv_recvfrom"); + goto CLEAN_UP; + } else if (r > packet_size) { + LOGE("[udp] remote_recv_recvfrom fragmentation"); + goto CLEAN_UP; + } + + buf->len = r; + +#ifdef MODULE_LOCAL + int err = ss_decrypt_all(buf, server_ctx->method, 0, buf_size); + if (err) { + // drop the packet silently + goto CLEAN_UP; + } + + //SSR beg + if (server_ctx->protocol_plugin) { + obfs_class *protocol_plugin = server_ctx->protocol_plugin; + if (protocol_plugin->client_udp_post_decrypt) { + buf->len = protocol_plugin->client_udp_post_decrypt(server_ctx->protocol, &buf->array, buf->len, &buf->capacity); + if ((int)buf->len < 0) { + LOGE("client_udp_post_decrypt"); + close_and_free_remote(EV_A_ remote_ctx); + return; + } + if ( buf->len == 0 ) + return; + } + } + // SSR end + +#ifdef MODULE_REDIR + struct sockaddr_storage dst_addr; + memset(&dst_addr, 0, sizeof(struct sockaddr_storage)); + int len = parse_udprealy_header(buf->array, buf->len, NULL, NULL, &dst_addr); + + if (dst_addr.ss_family != AF_INET && dst_addr.ss_family != AF_INET6) { + LOGI("[udp] ss-redir does not support domain name"); + goto CLEAN_UP; + } + + if (verbose) { + char src[SS_ADDRSTRLEN]; + char dst[SS_ADDRSTRLEN]; + strcpy(src, get_addr_str((struct sockaddr *)&src_addr)); + strcpy(dst, get_addr_str((struct sockaddr *)&dst_addr)); + LOGI("[udp] recv %s via %s", dst, src); + } +#else + int len = parse_udprealy_header(buf->array, buf->len, NULL, NULL, NULL); +#endif + + if (len == 0) { + LOGI("[udp] error in parse header"); + // error in parse header + goto CLEAN_UP; + } + + // server may return using a different address type other than the type we + // have used during sending +#if defined(MODULE_TUNNEL) || defined(MODULE_REDIR) + // Construct packet + buf->len -= len; + memmove(buf->array, buf->array + len, buf->len); +#else +#ifdef ANDROID + rx += buf->len; +#endif + // Construct packet + brealloc(buf, buf->len + 3, buf_size); + memmove(buf->array + 3, buf->array, buf->len); + memset(buf->array, 0, 3); + buf->len += 3; +#endif + +#endif + +#ifdef MODULE_REMOTE + + rx += buf->len; + + char addr_header_buf[512]; + char *addr_header = remote_ctx->addr_header; + int addr_header_len = remote_ctx->addr_header_len; + + if (remote_ctx->af == AF_INET || remote_ctx->af == AF_INET6) { + addr_header_len = construct_udprealy_header(&src_addr, addr_header_buf); + addr_header = addr_header_buf; + } + + // Construct packet + brealloc(buf, buf->len + addr_header_len, buf_size); + memmove(buf->array + addr_header_len, buf->array, buf->len); + memcpy(buf->array, addr_header, addr_header_len); + buf->len += addr_header_len; + + int err = ss_encrypt_all(buf, server_ctx->method, 0, buf_size); + if (err) { + // drop the packet silently + goto CLEAN_UP; + } + +#endif + + if (buf->len > packet_size) { + LOGE("[udp] remote_recv_sendto fragmentation"); + goto CLEAN_UP; + } + + size_t remote_src_addr_len = get_sockaddr_len((struct sockaddr *)&remote_ctx->src_addr); + +#ifdef MODULE_REDIR + + size_t remote_dst_addr_len = get_sockaddr_len((struct sockaddr *)&dst_addr); + + int src_fd = socket(remote_ctx->src_addr.ss_family, SOCK_DGRAM, 0); + if (src_fd < 0) { + ERROR("[udp] remote_recv_socket"); + goto CLEAN_UP; + } + int opt = 1; + if (setsockopt(src_fd, SOL_IP, IP_TRANSPARENT, &opt, sizeof(opt))) { + ERROR("[udp] remote_recv_setsockopt"); + close(src_fd); + goto CLEAN_UP; + } + if (setsockopt(src_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) { + ERROR("[udp] remote_recv_setsockopt"); + close(src_fd); + goto CLEAN_UP; + } +#ifdef IP_TOS + // Set QoS flag + int tos = 46; + setsockopt(src_fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); +#endif + if (bind(src_fd, (struct sockaddr *)&dst_addr, remote_dst_addr_len) != 0) { + ERROR("[udp] remote_recv_bind"); + close(src_fd); + goto CLEAN_UP; + } + + int s = sendto(src_fd, buf->array, buf->len, 0, + (struct sockaddr *)&remote_ctx->src_addr, remote_src_addr_len); + if (s == -1) { + ERROR("[udp] remote_recv_sendto"); + close(src_fd); + goto CLEAN_UP; + } + close(src_fd); + +#else + + int s = sendto(server_ctx->fd, buf->array, buf->len, 0, + (struct sockaddr *)&remote_ctx->src_addr, remote_src_addr_len); + if (s == -1) { + ERROR("[udp] remote_recv_sendto"); + goto CLEAN_UP; + } + +#endif + + // handle the UDP packet successfully, + // triger the timer + ev_timer_again(EV_A_ & remote_ctx->watcher); + +CLEAN_UP: + + bfree(buf); + ss_free(buf); +} + +static void +server_recv_cb(EV_P_ ev_io *w, int revents) +{ + server_ctx_t *server_ctx = (server_ctx_t *)w; + struct sockaddr_storage src_addr; + memset(&src_addr, 0, sizeof(struct sockaddr_storage)); + + buffer_t *buf = ss_malloc(sizeof(buffer_t)); + balloc(buf, buf_size); + + socklen_t src_addr_len = sizeof(struct sockaddr_storage); + unsigned int offset = 0; + +#ifdef MODULE_REDIR + char control_buffer[64] = { 0 }; + struct msghdr msg; + memset(&msg, 0, sizeof(struct msghdr)); + struct iovec iov[1]; + struct sockaddr_storage dst_addr; + memset(&dst_addr, 0, sizeof(struct sockaddr_storage)); + + msg.msg_name = &src_addr; + msg.msg_namelen = src_addr_len; + msg.msg_control = control_buffer; + msg.msg_controllen = sizeof(control_buffer); + + iov[0].iov_base = buf->array; + iov[0].iov_len = buf_size; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + + buf->len = recvmsg(server_ctx->fd, &msg, 0); + if (buf->len == -1) { + ERROR("[udp] server_recvmsg"); + goto CLEAN_UP; + } else if (buf->len > packet_size) { + ERROR("[udp] UDP server_recv_recvmsg fragmentation"); + goto CLEAN_UP; + } + + if (get_dstaddr(&msg, &dst_addr)) { + LOGE("[udp] unable to get dest addr"); + goto CLEAN_UP; + } + + src_addr_len = msg.msg_namelen; +#else + ssize_t r; + r = recvfrom(server_ctx->fd, buf->array, buf_size, + 0, (struct sockaddr *)&src_addr, &src_addr_len); + + if (r == -1) { + // error on recv + // simply drop that packet + ERROR("[udp] server_recv_recvfrom"); + goto CLEAN_UP; + } else if (r > packet_size) { + ERROR("[udp] server_recv_recvfrom fragmentation"); + goto CLEAN_UP; + } + + buf->len = r; +#endif + +#ifdef MODULE_REMOTE + tx += buf->len; + + int err = ss_decrypt_all(buf, server_ctx->method, server_ctx->auth, buf_size); + if (err) { + // drop the packet silently + goto CLEAN_UP; + } +#endif + +#ifdef MODULE_LOCAL +#if !defined(MODULE_TUNNEL) && !defined(MODULE_REDIR) +#ifdef ANDROID + tx += buf->len; +#endif + uint8_t frag = *(uint8_t *)(buf->array + 2); + offset += 3; +#endif +#endif + + /* + * + * 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 | HMAC-SHA1 | + * +------+----------+----------+----------+-------------+ + * | 1 | Variable | 2 | Variable | 10 | + * +------+----------+----------+----------+-------------+ + * + * If ATYP & ONETIMEAUTH_FLAG(0x10) != 0, Authentication (HMAC-SHA1) is enabled. + * + * The key of HMAC-SHA1 is (IV + KEY) and the input is the whole packet. + * The output of HMAC-SHA is truncated to 10 bytes (leftmost bits). + * + * 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 | + * +-------+--------------+ + * + */ + +#ifdef MODULE_REDIR + if (verbose) { + char src[SS_ADDRSTRLEN]; + char dst[SS_ADDRSTRLEN]; + strcpy(src, get_addr_str((struct sockaddr *)&src_addr)); + strcpy(dst, get_addr_str((struct sockaddr *)&dst_addr)); + LOGI("[udp] redir to %s from %s", dst, src); + } + + char addr_header[512] = { 0 }; + int addr_header_len = construct_udprealy_header(&dst_addr, addr_header); + + if (addr_header_len == 0) { + LOGE("[udp] failed to parse tproxy addr"); + goto CLEAN_UP; + } + + // reconstruct the buffer + brealloc(buf, buf->len + addr_header_len, buf_size); + memmove(buf->array + addr_header_len, buf->array, buf->len); + memcpy(buf->array, addr_header, addr_header_len); + buf->len += addr_header_len; + +#elif MODULE_TUNNEL + + char addr_header[512] = { 0 }; + char *host = server_ctx->tunnel_addr.host; + char *port = server_ctx->tunnel_addr.port; + uint16_t port_num = (uint16_t)atoi(port); + uint16_t port_net_num = htons(port_num); + int addr_header_len = 0; + + struct cork_ip ip; + if (cork_ip_init(&ip, host) != -1) { + if (ip.version == 4) { + // send as IPv4 + struct in_addr host_addr; + memset(&host_addr, 0, sizeof(struct in_addr)); + int host_len = sizeof(struct in_addr); + + if (dns_pton(AF_INET, host, &host_addr) == -1) { + FATAL("IP parser error"); + } + addr_header[addr_header_len++] = 1; + memcpy(addr_header + addr_header_len, &host_addr, host_len); + addr_header_len += host_len; + } else if (ip.version == 6) { + // send as IPv6 + struct in6_addr host_addr; + memset(&host_addr, 0, sizeof(struct in6_addr)); + int host_len = sizeof(struct in6_addr); + + if (dns_pton(AF_INET6, host, &host_addr) == -1) { + FATAL("IP parser error"); + } + addr_header[addr_header_len++] = 4; + memcpy(addr_header + addr_header_len, &host_addr, host_len); + addr_header_len += host_len; + } else { + FATAL("IP parser error"); + } + } else { + // send as domain + int host_len = strlen(host); + + addr_header[addr_header_len++] = 3; + addr_header[addr_header_len++] = host_len; + memcpy(addr_header + addr_header_len, host, host_len); + addr_header_len += host_len; + } + memcpy(addr_header + addr_header_len, &port_net_num, 2); + addr_header_len += 2; + + // reconstruct the buffer + brealloc(buf, buf->len + addr_header_len, buf_size); + memmove(buf->array + addr_header_len, buf->array, buf->len); + memcpy(buf->array, addr_header, addr_header_len); + buf->len += addr_header_len; + +#else + + char host[257] = { 0 }; + char port[64] = { 0 }; + struct sockaddr_storage dst_addr; + memset(&dst_addr, 0, sizeof(struct sockaddr_storage)); + + int addr_header_len = parse_udprealy_header(buf->array + offset, buf->len - offset, + host, port, &dst_addr); + if (addr_header_len == 0) { + // error in parse header + goto CLEAN_UP; + } + + char *addr_header = buf->array + offset; +#endif + +#ifdef MODULE_LOCAL + char *key = hash_key(server_ctx->remote_addr->sa_family, &src_addr); +#else + char *key = hash_key(dst_addr.ss_family, &src_addr); +#endif + + struct cache *conn_cache = server_ctx->conn_cache; + + remote_ctx_t *remote_ctx = NULL; + cache_lookup(conn_cache, key, HASH_KEY_LEN, (void *)&remote_ctx); + + if (remote_ctx != NULL) { + if (sockaddr_cmp(&src_addr, &remote_ctx->src_addr, sizeof(src_addr))) { + remote_ctx = NULL; + } + } + + // reset the timer + if (remote_ctx != NULL) { + ev_timer_again(EV_A_ & remote_ctx->watcher); + } + + if (remote_ctx == NULL) { + if (verbose) { +#ifdef MODULE_REDIR + char src[SS_ADDRSTRLEN]; + char dst[SS_ADDRSTRLEN]; + strcpy(src, get_addr_str((struct sockaddr *)&src_addr)); + strcpy(dst, get_addr_str((struct sockaddr *)&dst_addr)); + LOGI("[udp] cache miss: %s <-> %s", dst, src); +#else + LOGI("[udp] cache miss: %s:%s <-> %s", host, port, + get_addr_str((struct sockaddr *)&src_addr)); +#endif + } + } else { + if (verbose) { +#ifdef MODULE_REDIR + char src[SS_ADDRSTRLEN]; + char dst[SS_ADDRSTRLEN]; + strcpy(src, get_addr_str((struct sockaddr *)&src_addr)); + strcpy(dst, get_addr_str((struct sockaddr *)&dst_addr)); + LOGI("[udp] cache hit: %s <-> %s", dst, src); +#else + LOGI("[udp] cache hit: %s:%s <-> %s", host, port, + get_addr_str((struct sockaddr *)&src_addr)); +#endif + } + } + +#ifdef MODULE_LOCAL + +#if !defined(MODULE_TUNNEL) && !defined(MODULE_REDIR) + if (frag) { + LOGE("[udp] drop a message since frag is not 0, but %d", frag); + goto CLEAN_UP; + } +#endif + + const struct sockaddr *remote_addr = server_ctx->remote_addr; + const int remote_addr_len = server_ctx->remote_addr_len; + + if (remote_ctx == NULL) { + // Bind to any port + int remotefd = create_remote_socket(remote_addr->sa_family == AF_INET6); + if (remotefd < 0) { + ERROR("[udp] udprelay bind() error"); + goto CLEAN_UP; + } + setnonblocking(remotefd); + +#ifdef SO_NOSIGPIPE + set_nosigpipe(remotefd); +#endif +#ifdef IP_TOS + // Set QoS flag + int tos = 46; + setsockopt(remotefd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); +#endif +#ifdef SET_INTERFACE + if (server_ctx->iface) { + if (setinterface(remotefd, server_ctx->iface) == -1) + ERROR("setinterface"); + } +#endif + +#ifdef ANDROID + if (vpn) { + if (protect_socket(remotefd) == -1) { + ERROR("protect_socket"); + close(remotefd); + goto CLEAN_UP; + } + } +#endif + + // Init remote_ctx + remote_ctx = new_remote(remotefd, server_ctx); + remote_ctx->src_addr = src_addr; + remote_ctx->af = remote_addr->sa_family; + remote_ctx->addr_header_len = addr_header_len; + memcpy(remote_ctx->addr_header, addr_header, addr_header_len); + + // Add to conn cache + cache_insert(conn_cache, key, HASH_KEY_LEN, (void *)remote_ctx); + + // Start remote io + ev_io_start(EV_A_ & remote_ctx->io); + ev_timer_start(EV_A_ & remote_ctx->watcher); + } + + if (offset > 0) { + buf->len -= offset; + memmove(buf->array, buf->array + offset, buf->len); + } + + if (server_ctx->auth) { + buf->array[0] |= ONETIMEAUTH_FLAG; + } + + // SSR beg + if (server_ctx->protocol_plugin) { + obfs_class *protocol_plugin = server_ctx->protocol_plugin; + if (protocol_plugin->client_udp_pre_encrypt) { + buf->len = protocol_plugin->client_udp_pre_encrypt(server_ctx->protocol, &buf->array, buf->len, &buf->capacity); + } + } + //SSR end + + int err = ss_encrypt_all(buf, server_ctx->method, server_ctx->auth, buf->len); + + if (err) { + // drop the packet silently + goto CLEAN_UP; + } + + if (buf->len > packet_size) { + LOGE("[udp] server_recv_sendto fragmentation"); + goto CLEAN_UP; + } + + int s = sendto(remote_ctx->fd, buf->array, buf->len, 0, remote_addr, remote_addr_len); + + if (s == -1) { + ERROR("[udp] server_recv_sendto"); + } + +#else + + int cache_hit = 0; + int need_query = 0; + + if (buf->len - addr_header_len > packet_size) { + LOGE("[udp] server_recv_sendto fragmentation"); + goto CLEAN_UP; + } + + if (remote_ctx != NULL) { + cache_hit = 1; + // detect destination mismatch + if (remote_ctx->addr_header_len != addr_header_len + || memcmp(addr_header, remote_ctx->addr_header, addr_header_len) != 0) { + if (dst_addr.ss_family != AF_INET && dst_addr.ss_family != AF_INET6) { + need_query = 1; + } + } else { + memcpy(&dst_addr, &remote_ctx->dst_addr, sizeof(struct sockaddr_storage)); + } + } else { + if (dst_addr.ss_family == AF_INET || dst_addr.ss_family == AF_INET6) { + int remotefd = create_remote_socket(dst_addr.ss_family == AF_INET6); + if (remotefd != -1) { + setnonblocking(remotefd); +#ifdef SO_BROADCAST + set_broadcast(remotefd); +#endif +#ifdef SO_NOSIGPIPE + set_nosigpipe(remotefd); +#endif +#ifdef IP_TOS + // Set QoS flag + int tos = 46; + setsockopt(remotefd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)); +#endif +#ifdef SET_INTERFACE + if (server_ctx->iface) { + if (setinterface(remotefd, server_ctx->iface) == -1) + ERROR("setinterface"); + } +#endif + remote_ctx = new_remote(remotefd, server_ctx); + remote_ctx->src_addr = src_addr; + remote_ctx->server_ctx = server_ctx; + remote_ctx->addr_header_len = addr_header_len; + memcpy(remote_ctx->addr_header, addr_header, addr_header_len); + memcpy(&remote_ctx->dst_addr, &dst_addr, sizeof(struct sockaddr_storage)); + } else { + ERROR("[udp] bind() error"); + goto CLEAN_UP; + } + } + } + + if (remote_ctx != NULL && !need_query) { + size_t addr_len = get_sockaddr_len((struct sockaddr *)&dst_addr); + int s = sendto(remote_ctx->fd, buf->array + addr_header_len, + buf->len - addr_header_len, 0, + (struct sockaddr *)&dst_addr, addr_len); + + if (s == -1) { + ERROR("[udp] sendto_remote"); + if (!cache_hit) { + close_and_free_remote(EV_A_ remote_ctx); + } + } else { + if (!cache_hit) { + // Add to conn cache + remote_ctx->af = dst_addr.ss_family; + char *key = hash_key(remote_ctx->af, &remote_ctx->src_addr); + cache_insert(server_ctx->conn_cache, key, HASH_KEY_LEN, (void *)remote_ctx); + + ev_io_start(EV_A_ & remote_ctx->io); + ev_timer_start(EV_A_ & remote_ctx->watcher); + } + } + } else { + struct addrinfo hints; + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + + struct query_ctx *query_ctx = new_query_ctx(buf->array + addr_header_len, + buf->len - addr_header_len); + query_ctx->server_ctx = server_ctx; + query_ctx->addr_header_len = addr_header_len; + query_ctx->src_addr = src_addr; + memcpy(query_ctx->addr_header, addr_header, addr_header_len); + + if (need_query) { + query_ctx->remote_ctx = remote_ctx; + } + + struct ResolvQuery *query = resolv_query(host, query_resolve_cb, + NULL, query_ctx, htons(atoi(port))); + if (query == NULL) { + ERROR("[udp] unable to create DNS query"); + close_and_free_query(EV_A_ query_ctx); + goto CLEAN_UP; + } + query_ctx->query = query; + } +#endif + +CLEAN_UP: + bfree(buf); + ss_free(buf); +} + +void +free_cb(void *key, void *element) +{ + remote_ctx_t *remote_ctx = (remote_ctx_t *)element; + + if (verbose) { + LOGI("[udp] one connection freed"); + } + + close_and_free_remote(EV_DEFAULT, remote_ctx); +} + +int +init_udprelay(const char *server_host, const char *server_port, +#ifdef MODULE_LOCAL + const struct sockaddr *remote_addr, const int remote_addr_len, +#ifdef MODULE_TUNNEL + const ss_addr_t tunnel_addr, +#endif +#endif + int mtu, int method, int auth, int timeout, const char *iface, const char *protocol, const char *protocol_param) +{ + // Initialize ev loop + struct ev_loop *loop = EV_DEFAULT; + + // Initialize MTU + if (mtu > 0) { + packet_size = mtu - 1 - 28 - 2 - 64; + buf_size = packet_size * 2; + } + + // Initialize cache + struct cache *conn_cache; + cache_create(&conn_cache, MAX_UDP_CONN_NUM, free_cb); + + // //////////////////////////////////////////////// + // Setup server context + + // Bind to port + int serverfd = create_server_socket(server_host, server_port); + if (serverfd < 0) { + FATAL("[udp] bind() error"); + } + setnonblocking(serverfd); + if (protocol != NULL && strcmp(protocol, "verify_sha1") == 0) { + auth = 1; + protocol = NULL; + } + + server_ctx_t *server_ctx = new_server_ctx(serverfd); +#ifdef MODULE_REMOTE + server_ctx->loop = loop; +#endif + server_ctx->auth = auth; + server_ctx->timeout = max(timeout, MIN_UDP_TIMEOUT); + server_ctx->method = method; + server_ctx->iface = iface; + server_ctx->conn_cache = conn_cache; +#ifdef MODULE_LOCAL + server_ctx->remote_addr = remote_addr; + server_ctx->remote_addr_len = remote_addr_len; + //SSR beg + server_ctx->protocol_plugin = new_obfs_class((char *)protocol); + if (server_ctx->protocol_plugin) { + server_ctx->protocol = server_ctx->protocol_plugin->new_obfs(); + server_ctx->protocol_global = server_ctx->protocol_plugin->init_data(); + } + + server_info _server_info; + memset(&_server_info, 0, sizeof(server_info)); + strcpy(_server_info.host, inet_ntoa(((struct sockaddr_in*)remote_addr)->sin_addr)); + _server_info.port = ((struct sockaddr_in*)remote_addr)->sin_port; + _server_info.port = _server_info.port >> 8 | _server_info.port << 8; + _server_info.g_data = server_ctx->protocol_global; + _server_info.param = (char *)protocol_param; + _server_info.key = enc_get_key(); + _server_info.key_len = enc_get_key_len(); + + if (server_ctx->protocol_plugin) + server_ctx->protocol_plugin->set_server_info(server_ctx->protocol, &_server_info); + //SSR end +#ifdef MODULE_TUNNEL + server_ctx->tunnel_addr = tunnel_addr; +#endif +#endif + + ev_io_start(loop, &server_ctx->io); + + server_ctx_list[server_num++] = server_ctx; + + return 0; +} + +void +free_udprelay() +{ + struct ev_loop *loop = EV_DEFAULT; + while (server_num-- > 0) { + server_ctx_t *server_ctx = server_ctx_list[server_num]; + +#ifdef MODULE_LOCAL + //SSR beg + if (server_ctx->protocol_plugin) { + server_ctx->protocol_plugin->dispose(server_ctx->protocol); + server_ctx->protocol = NULL; + free_obfs_class(server_ctx->protocol_plugin); + server_ctx->protocol_plugin = NULL; + } + //SSR end +#endif + + ev_io_stop(loop, &server_ctx->io); + close(server_ctx->fd); + cache_delete(server_ctx->conn_cache, 0); + ss_free(server_ctx); + server_ctx_list[server_num] = NULL; + } +} diff --git a/shadowsocksr-libev/src/server/udprelay.h b/shadowsocksr-libev/src/server/udprelay.h new file mode 100644 index 0000000..89876d4 --- /dev/null +++ b/shadowsocksr-libev/src/server/udprelay.h @@ -0,0 +1,95 @@ +/* + * udprelay.h - Define UDP relay's buffers and callbacks + * + * Copyright (C) 2013 - 2016, Max Lv + * + * This file is part of the shadowsocks-libev. + * + * shadowsocks-libev is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * shadowsocks-libev 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with shadowsocks-libev; see the file COPYING. If not, see + * . + */ + +#ifndef _UDPRELAY_H +#define _UDPRELAY_H + +#include +#include + +#include "encrypt.h" +#include "jconf.h" +#include "obfs.h" + +#ifdef MODULE_REMOTE +#include "resolv.h" +#endif + +#include "cache.h" + +#include "common.h" + +#define MAX_UDP_PACKET_SIZE (65507) + +#define DEFAULT_PACKET_SIZE 1397 // 1492 - 1 - 28 - 2 - 64 = 1397, the default MTU for UDP relay + +typedef struct server_ctx { + ev_io io; + int fd; + int method; + int auth; + int timeout; + const char *iface; + struct cache *conn_cache; +#ifdef MODULE_LOCAL + const struct sockaddr *remote_addr; + int remote_addr_len; +#ifdef MODULE_TUNNEL + ss_addr_t tunnel_addr; +#endif +#endif +#ifdef MODULE_REMOTE + struct ev_loop *loop; +#endif + // SSR + obfs *protocol; + obfs_class *protocol_plugin; + void *protocol_global; +} server_ctx_t; + +#ifdef MODULE_REMOTE +typedef struct query_ctx { + struct ResolvQuery *query; + struct sockaddr_storage src_addr; + buffer_t *buf; + int addr_header_len; + char addr_header[384]; + struct server_ctx *server_ctx; + struct remote_ctx *remote_ctx; +} query_ctx_t; +#endif + +typedef struct remote_ctx { + ev_io io; + ev_timer watcher; + int af; + int fd; + int addr_header_len; + char addr_header[384]; + struct sockaddr_storage src_addr; +#ifdef MODULE_REMOTE + struct sockaddr_storage dst_addr; +#endif + struct server_ctx *server_ctx; +} remote_ctx_t; + +#endif // _UDPRELAY_H diff --git a/shadowsocksr-libev/src/server/uthash.h b/shadowsocksr-libev/src/server/uthash.h new file mode 100644 index 0000000..45d1f9f --- /dev/null +++ b/shadowsocksr-libev/src/server/uthash.h @@ -0,0 +1,1074 @@ +/* +Copyright (c) 2003-2016, Troy D. Hanson http://troydhanson.github.com/uthash/ +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +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. +*/ + +#ifndef UTHASH_H +#define UTHASH_H + +#define UTHASH_VERSION 2.0.1 + +#include /* memcmp,strlen */ +#include /* ptrdiff_t */ +#include /* exit() */ + +/* These macros use decltype or the earlier __typeof GNU extension. + As decltype is only available in newer compilers (VS2010 or gcc 4.3+ + when compiling c++ source) this code uses whatever method is needed + or, for VS2008 where neither is available, uses casting workarounds. */ +#if defined(_MSC_VER) /* MS compiler */ +#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ +#define DECLTYPE(x) (decltype(x)) +#else /* VS2008 or older (or VS2010 in C mode) */ +#define NO_DECLTYPE +#define DECLTYPE(x) +#endif +#elif defined(__BORLANDC__) || defined(__LCC__) || defined(__WATCOMC__) +#define NO_DECLTYPE +#define DECLTYPE(x) +#else /* GNU, Sun and other compilers */ +#define DECLTYPE(x) (__typeof(x)) +#endif + +#ifdef NO_DECLTYPE +#define DECLTYPE_ASSIGN(dst,src) \ +do { \ + char **_da_dst = (char**)(&(dst)); \ + *_da_dst = (char*)(src); \ +} while (0) +#else +#define DECLTYPE_ASSIGN(dst,src) \ +do { \ + (dst) = DECLTYPE(dst)(src); \ +} while (0) +#endif + +/* a number of the hash function use uint32_t which isn't defined on Pre VS2010 */ +#if defined(_WIN32) +#if defined(_MSC_VER) && _MSC_VER >= 1600 +#include +#elif defined(__WATCOMC__) || defined(__MINGW32__) || defined(__CYGWIN__) +#include +#else +typedef unsigned int uint32_t; +typedef unsigned char uint8_t; +#endif +#elif defined(__GNUC__) && !defined(__VXWORKS__) +#include +#else +typedef unsigned int uint32_t; +typedef unsigned char uint8_t; +#endif + +#ifndef uthash_fatal +#define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */ +#endif +#ifndef uthash_malloc +#define uthash_malloc(sz) malloc(sz) /* malloc fcn */ +#endif +#ifndef uthash_free +#define uthash_free(ptr,sz) free(ptr) /* free fcn */ +#endif +#ifndef uthash_strlen +#define uthash_strlen(s) strlen(s) +#endif +#ifndef uthash_memcmp +#define uthash_memcmp(a,b,n) memcmp(a,b,n) +#endif + +#ifndef uthash_noexpand_fyi +#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */ +#endif +#ifndef uthash_expand_fyi +#define uthash_expand_fyi(tbl) /* can be defined to log expands */ +#endif + +/* initial number of buckets */ +#define HASH_INITIAL_NUM_BUCKETS 32U /* initial number of buckets */ +#define HASH_INITIAL_NUM_BUCKETS_LOG2 5U /* lg2 of initial number of buckets */ +#define HASH_BKT_CAPACITY_THRESH 10U /* expand when bucket count reaches */ + +/* calculate the element whose hash handle address is hhp */ +#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho))) +/* calculate the hash handle from element address elp */ +#define HH_FROM_ELMT(tbl,elp) ((UT_hash_handle *)(((char*)(elp)) + ((tbl)->hho))) + +#define HASH_VALUE(keyptr,keylen,hashv) \ +do { \ + HASH_FCN(keyptr, keylen, hashv); \ +} while (0) + +#define HASH_FIND_BYHASHVALUE(hh,head,keyptr,keylen,hashval,out) \ +do { \ + (out) = NULL; \ + if (head) { \ + unsigned _hf_bkt; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _hf_bkt); \ + if (HASH_BLOOM_TEST((head)->hh.tbl, hashval) != 0) { \ + HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], keyptr, keylen, hashval, out); \ + } \ + } \ +} while (0) + +#define HASH_FIND(hh,head,keyptr,keylen,out) \ +do { \ + unsigned _hf_hashv; \ + HASH_VALUE(keyptr, keylen, _hf_hashv); \ + HASH_FIND_BYHASHVALUE(hh, head, keyptr, keylen, _hf_hashv, out); \ +} while (0) + +#ifdef HASH_BLOOM +#define HASH_BLOOM_BITLEN (1UL << HASH_BLOOM) +#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8UL) + (((HASH_BLOOM_BITLEN%8UL)!=0UL) ? 1UL : 0UL) +#define HASH_BLOOM_MAKE(tbl) \ +do { \ + (tbl)->bloom_nbits = HASH_BLOOM; \ + (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \ + if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \ + memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \ + (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \ +} while (0) + +#define HASH_BLOOM_FREE(tbl) \ +do { \ + uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ +} while (0) + +#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8U] |= (1U << ((idx)%8U))) +#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8U] & (1U << ((idx)%8U))) + +#define HASH_BLOOM_ADD(tbl,hashv) \ + HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1U))) + +#define HASH_BLOOM_TEST(tbl,hashv) \ + HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1U))) + +#else +#define HASH_BLOOM_MAKE(tbl) +#define HASH_BLOOM_FREE(tbl) +#define HASH_BLOOM_ADD(tbl,hashv) +#define HASH_BLOOM_TEST(tbl,hashv) (1) +#define HASH_BLOOM_BYTELEN 0U +#endif + +#define HASH_MAKE_TABLE(hh,head) \ +do { \ + (head)->hh.tbl = (UT_hash_table*)uthash_malloc( \ + sizeof(UT_hash_table)); \ + if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \ + memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \ + (head)->hh.tbl->tail = &((head)->hh); \ + (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \ + (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \ + (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \ + (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \ + HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ + if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \ + memset((head)->hh.tbl->buckets, 0, \ + HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ + HASH_BLOOM_MAKE((head)->hh.tbl); \ + (head)->hh.tbl->signature = HASH_SIGNATURE; \ +} while (0) + +#define HASH_REPLACE_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,replaced,cmpfcn) \ +do { \ + (replaced) = NULL; \ + HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ + if (replaced) { \ + HASH_DELETE(hh, head, replaced); \ + } \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn); \ +} while (0) + +#define HASH_REPLACE_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add,replaced) \ +do { \ + (replaced) = NULL; \ + HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ + if (replaced) { \ + HASH_DELETE(hh, head, replaced); \ + } \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add); \ +} while (0) + +#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced) \ +do { \ + unsigned _hr_hashv; \ + HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ + HASH_REPLACE_BYHASHVALUE(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced); \ +} while (0) + +#define HASH_REPLACE_INORDER(hh,head,fieldname,keylen_in,add,replaced,cmpfcn) \ +do { \ + unsigned _hr_hashv; \ + HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ + HASH_REPLACE_BYHASHVALUE_INORDER(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced, cmpfcn); \ +} while (0) + +#define HASH_APPEND_LIST(hh, head, add) \ +do { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \ + (head)->hh.tbl->tail->next = (add); \ + (head)->hh.tbl->tail = &((add)->hh); \ +} while (0) + +#define HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh,head,keyptr,keylen_in,hashval,add,cmpfcn) \ +do { \ + unsigned _ha_bkt; \ + (add)->hh.hashv = (hashval); \ + (add)->hh.key = (char*) (keyptr); \ + (add)->hh.keylen = (unsigned) (keylen_in); \ + if (!(head)) { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = NULL; \ + (head) = (add); \ + HASH_MAKE_TABLE(hh, head); \ + } else { \ + struct UT_hash_handle *_hs_iter = &(head)->hh; \ + (add)->hh.tbl = (head)->hh.tbl; \ + do { \ + if (cmpfcn(DECLTYPE(head) ELMT_FROM_HH((head)->hh.tbl, _hs_iter), add) > 0) \ + break; \ + } while ((_hs_iter = _hs_iter->next)); \ + if (_hs_iter) { \ + (add)->hh.next = _hs_iter; \ + if (((add)->hh.prev = _hs_iter->prev)) { \ + HH_FROM_ELMT((head)->hh.tbl, _hs_iter->prev)->next = (add); \ + } else { \ + (head) = (add); \ + } \ + _hs_iter->prev = (add); \ + } else { \ + HASH_APPEND_LIST(hh, head, add); \ + } \ + } \ + (head)->hh.tbl->num_items++; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ + HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], &(add)->hh); \ + HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ + HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ + HASH_FSCK(hh, head); \ +} while (0) + +#define HASH_ADD_KEYPTR_INORDER(hh,head,keyptr,keylen_in,add,cmpfcn) \ +do { \ + unsigned _hs_hashv; \ + HASH_VALUE(keyptr, keylen_in, _hs_hashv); \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, keyptr, keylen_in, _hs_hashv, add, cmpfcn); \ +} while (0) + +#define HASH_ADD_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,cmpfcn) \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn) + +#define HASH_ADD_INORDER(hh,head,fieldname,keylen_in,add,cmpfcn) \ + HASH_ADD_KEYPTR_INORDER(hh, head, &((add)->fieldname), keylen_in, add, cmpfcn) + +#define HASH_ADD_KEYPTR_BYHASHVALUE(hh,head,keyptr,keylen_in,hashval,add) \ +do { \ + unsigned _ha_bkt; \ + (add)->hh.hashv = (hashval); \ + (add)->hh.key = (char*) (keyptr); \ + (add)->hh.keylen = (unsigned) (keylen_in); \ + if (!(head)) { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = NULL; \ + (head) = (add); \ + HASH_MAKE_TABLE(hh, head); \ + } else { \ + (add)->hh.tbl = (head)->hh.tbl; \ + HASH_APPEND_LIST(hh, head, add); \ + } \ + (head)->hh.tbl->num_items++; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ + HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], &(add)->hh); \ + HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ + HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ + HASH_FSCK(hh, head); \ +} while (0) + +#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \ +do { \ + unsigned _ha_hashv; \ + HASH_VALUE(keyptr, keylen_in, _ha_hashv); \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, keyptr, keylen_in, _ha_hashv, add); \ +} while (0) + +#define HASH_ADD_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add) \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add) + +#define HASH_ADD(hh,head,fieldname,keylen_in,add) \ + HASH_ADD_KEYPTR(hh, head, &((add)->fieldname), keylen_in, add) + +#define HASH_TO_BKT(hashv,num_bkts,bkt) \ +do { \ + bkt = ((hashv) & ((num_bkts) - 1U)); \ +} while (0) + +/* delete "delptr" from the hash table. + * "the usual" patch-up process for the app-order doubly-linked-list. + * The use of _hd_hh_del below deserves special explanation. + * These used to be expressed using (delptr) but that led to a bug + * if someone used the same symbol for the head and deletee, like + * HASH_DELETE(hh,users,users); + * We want that to work, but by changing the head (users) below + * we were forfeiting our ability to further refer to the deletee (users) + * in the patch-up process. Solution: use scratch space to + * copy the deletee pointer, then the latter references are via that + * scratch pointer rather than through the repointed (users) symbol. + */ +#define HASH_DELETE(hh,head,delptr) \ +do { \ + struct UT_hash_handle *_hd_hh_del; \ + if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \ + uthash_free((head)->hh.tbl->buckets, \ + (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \ + HASH_BLOOM_FREE((head)->hh.tbl); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + head = NULL; \ + } else { \ + unsigned _hd_bkt; \ + _hd_hh_del = &((delptr)->hh); \ + if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \ + (head)->hh.tbl->tail = \ + (UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \ + (head)->hh.tbl->hho); \ + } \ + if ((delptr)->hh.prev != NULL) { \ + ((UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \ + (head)->hh.tbl->hho))->next = (delptr)->hh.next; \ + } else { \ + DECLTYPE_ASSIGN(head,(delptr)->hh.next); \ + } \ + if (_hd_hh_del->next != NULL) { \ + ((UT_hash_handle*)((ptrdiff_t)_hd_hh_del->next + \ + (head)->hh.tbl->hho))->prev = \ + _hd_hh_del->prev; \ + } \ + HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ + HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \ + (head)->hh.tbl->num_items--; \ + } \ + HASH_FSCK(hh,head); \ +} while (0) + + +/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */ +#define HASH_FIND_STR(head,findstr,out) \ + HASH_FIND(hh,head,findstr,(unsigned)uthash_strlen(findstr),out) +#define HASH_ADD_STR(head,strfield,add) \ + HASH_ADD(hh,head,strfield[0],(unsigned)uthash_strlen(add->strfield),add) +#define HASH_REPLACE_STR(head,strfield,add,replaced) \ + HASH_REPLACE(hh,head,strfield[0],(unsigned)uthash_strlen(add->strfield),add,replaced) +#define HASH_FIND_INT(head,findint,out) \ + HASH_FIND(hh,head,findint,sizeof(int),out) +#define HASH_ADD_INT(head,intfield,add) \ + HASH_ADD(hh,head,intfield,sizeof(int),add) +#define HASH_REPLACE_INT(head,intfield,add,replaced) \ + HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced) +#define HASH_FIND_PTR(head,findptr,out) \ + HASH_FIND(hh,head,findptr,sizeof(void *),out) +#define HASH_ADD_PTR(head,ptrfield,add) \ + HASH_ADD(hh,head,ptrfield,sizeof(void *),add) +#define HASH_REPLACE_PTR(head,ptrfield,add,replaced) \ + HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced) +#define HASH_DEL(head,delptr) \ + HASH_DELETE(hh,head,delptr) + +/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined. + * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined. + */ +#ifdef HASH_DEBUG +#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0) +#define HASH_FSCK(hh,head) \ +do { \ + struct UT_hash_handle *_thh; \ + if (head) { \ + unsigned _bkt_i; \ + unsigned _count; \ + char *_prev; \ + _count = 0; \ + for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \ + unsigned _bkt_count = 0; \ + _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \ + _prev = NULL; \ + while (_thh) { \ + if (_prev != (char*)(_thh->hh_prev)) { \ + HASH_OOPS("invalid hh_prev %p, actual %p\n", \ + _thh->hh_prev, _prev ); \ + } \ + _bkt_count++; \ + _prev = (char*)(_thh); \ + _thh = _thh->hh_next; \ + } \ + _count += _bkt_count; \ + if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \ + HASH_OOPS("invalid bucket count %u, actual %u\n", \ + (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \ + } \ + } \ + if (_count != (head)->hh.tbl->num_items) { \ + HASH_OOPS("invalid hh item count %u, actual %u\n", \ + (head)->hh.tbl->num_items, _count ); \ + } \ + /* traverse hh in app order; check next/prev integrity, count */ \ + _count = 0; \ + _prev = NULL; \ + _thh = &(head)->hh; \ + while (_thh) { \ + _count++; \ + if (_prev !=(char*)(_thh->prev)) { \ + HASH_OOPS("invalid prev %p, actual %p\n", \ + _thh->prev, _prev ); \ + } \ + _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \ + _thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \ + (head)->hh.tbl->hho) : NULL ); \ + } \ + if (_count != (head)->hh.tbl->num_items) { \ + HASH_OOPS("invalid app item count %u, actual %u\n", \ + (head)->hh.tbl->num_items, _count ); \ + } \ + } \ +} while (0) +#else +#define HASH_FSCK(hh,head) +#endif + +/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to + * the descriptor to which this macro is defined for tuning the hash function. + * The app can #include to get the prototype for write(2). */ +#ifdef HASH_EMIT_KEYS +#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \ +do { \ + unsigned _klen = fieldlen; \ + write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \ + write(HASH_EMIT_KEYS, keyptr, (unsigned long)fieldlen); \ +} while (0) +#else +#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) +#endif + +/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */ +#ifdef HASH_FUNCTION +#define HASH_FCN HASH_FUNCTION +#else +#define HASH_FCN HASH_JEN +#endif + +/* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */ +#define HASH_BER(key,keylen,hashv) \ +do { \ + unsigned _hb_keylen=(unsigned)keylen; \ + const unsigned char *_hb_key=(const unsigned char*)(key); \ + (hashv) = 0; \ + while (_hb_keylen-- != 0U) { \ + (hashv) = (((hashv) << 5) + (hashv)) + *_hb_key++; \ + } \ +} while (0) + + +/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at + * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */ +#define HASH_SAX(key,keylen,hashv) \ +do { \ + unsigned _sx_i; \ + const unsigned char *_hs_key=(const unsigned char*)(key); \ + hashv = 0; \ + for(_sx_i=0; _sx_i < keylen; _sx_i++) { \ + hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \ + } \ +} while (0) +/* FNV-1a variation */ +#define HASH_FNV(key,keylen,hashv) \ +do { \ + unsigned _fn_i; \ + const unsigned char *_hf_key=(const unsigned char*)(key); \ + hashv = 2166136261U; \ + for(_fn_i=0; _fn_i < keylen; _fn_i++) { \ + hashv = hashv ^ _hf_key[_fn_i]; \ + hashv = hashv * 16777619U; \ + } \ +} while (0) + +#define HASH_OAT(key,keylen,hashv) \ +do { \ + unsigned _ho_i; \ + const unsigned char *_ho_key=(const unsigned char*)(key); \ + hashv = 0; \ + for(_ho_i=0; _ho_i < keylen; _ho_i++) { \ + hashv += _ho_key[_ho_i]; \ + hashv += (hashv << 10); \ + hashv ^= (hashv >> 6); \ + } \ + hashv += (hashv << 3); \ + hashv ^= (hashv >> 11); \ + hashv += (hashv << 15); \ +} while (0) + +#define HASH_JEN_MIX(a,b,c) \ +do { \ + a -= b; a -= c; a ^= ( c >> 13 ); \ + b -= c; b -= a; b ^= ( a << 8 ); \ + c -= a; c -= b; c ^= ( b >> 13 ); \ + a -= b; a -= c; a ^= ( c >> 12 ); \ + b -= c; b -= a; b ^= ( a << 16 ); \ + c -= a; c -= b; c ^= ( b >> 5 ); \ + a -= b; a -= c; a ^= ( c >> 3 ); \ + b -= c; b -= a; b ^= ( a << 10 ); \ + c -= a; c -= b; c ^= ( b >> 15 ); \ +} while (0) + +#define HASH_JEN(key,keylen,hashv) \ +do { \ + unsigned _hj_i,_hj_j,_hj_k; \ + unsigned const char *_hj_key=(unsigned const char*)(key); \ + hashv = 0xfeedbeefu; \ + _hj_i = _hj_j = 0x9e3779b9u; \ + _hj_k = (unsigned)(keylen); \ + while (_hj_k >= 12U) { \ + _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \ + + ( (unsigned)_hj_key[2] << 16 ) \ + + ( (unsigned)_hj_key[3] << 24 ) ); \ + _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \ + + ( (unsigned)_hj_key[6] << 16 ) \ + + ( (unsigned)_hj_key[7] << 24 ) ); \ + hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \ + + ( (unsigned)_hj_key[10] << 16 ) \ + + ( (unsigned)_hj_key[11] << 24 ) ); \ + \ + HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ + \ + _hj_key += 12; \ + _hj_k -= 12U; \ + } \ + hashv += (unsigned)(keylen); \ + switch ( _hj_k ) { \ + case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); /* FALLTHROUGH */ \ + case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); /* FALLTHROUGH */ \ + case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); /* FALLTHROUGH */ \ + case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); /* FALLTHROUGH */ \ + case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); /* FALLTHROUGH */ \ + case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); /* FALLTHROUGH */ \ + case 5: _hj_j += _hj_key[4]; /* FALLTHROUGH */ \ + case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); /* FALLTHROUGH */ \ + case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); /* FALLTHROUGH */ \ + case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); /* FALLTHROUGH */ \ + case 1: _hj_i += _hj_key[0]; \ + } \ + HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ +} while (0) + +/* The Paul Hsieh hash function */ +#undef get16bits +#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ + || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) +#define get16bits(d) (*((const uint16_t *) (d))) +#endif + +#if !defined (get16bits) +#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \ + +(uint32_t)(((const uint8_t *)(d))[0]) ) +#endif +#define HASH_SFH(key,keylen,hashv) \ +do { \ + unsigned const char *_sfh_key=(unsigned const char*)(key); \ + uint32_t _sfh_tmp, _sfh_len = (uint32_t)keylen; \ + \ + unsigned _sfh_rem = _sfh_len & 3U; \ + _sfh_len >>= 2; \ + hashv = 0xcafebabeu; \ + \ + /* Main loop */ \ + for (;_sfh_len > 0U; _sfh_len--) { \ + hashv += get16bits (_sfh_key); \ + _sfh_tmp = ((uint32_t)(get16bits (_sfh_key+2)) << 11) ^ hashv; \ + hashv = (hashv << 16) ^ _sfh_tmp; \ + _sfh_key += 2U*sizeof (uint16_t); \ + hashv += hashv >> 11; \ + } \ + \ + /* Handle end cases */ \ + switch (_sfh_rem) { \ + case 3: hashv += get16bits (_sfh_key); \ + hashv ^= hashv << 16; \ + hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)]) << 18; \ + hashv += hashv >> 11; \ + break; \ + case 2: hashv += get16bits (_sfh_key); \ + hashv ^= hashv << 11; \ + hashv += hashv >> 17; \ + break; \ + case 1: hashv += *_sfh_key; \ + hashv ^= hashv << 10; \ + hashv += hashv >> 1; \ + } \ + \ + /* Force "avalanching" of final 127 bits */ \ + hashv ^= hashv << 3; \ + hashv += hashv >> 5; \ + hashv ^= hashv << 4; \ + hashv += hashv >> 17; \ + hashv ^= hashv << 25; \ + hashv += hashv >> 6; \ +} while (0) + +#ifdef HASH_USING_NO_STRICT_ALIASING +/* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads. + * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error. + * MurmurHash uses the faster approach only on CPU's where we know it's safe. + * + * Note the preprocessor built-in defines can be emitted using: + * + * gcc -m64 -dM -E - < /dev/null (on gcc) + * cc -## a.c (where a.c is a simple test file) (Sun Studio) + */ +#if (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86)) +#define MUR_GETBLOCK(p,i) p[i] +#else /* non intel */ +#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 3UL) == 0UL) +#define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 3UL) == 1UL) +#define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 3UL) == 2UL) +#define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 3UL) == 3UL) +#define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL)) +#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__)) +#define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24)) +#define MUR_TWO_TWO(p) ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16)) +#define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >> 8)) +#else /* assume little endian non-intel */ +#define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24)) +#define MUR_TWO_TWO(p) ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16)) +#define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) << 8)) +#endif +#define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) : \ + (MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \ + (MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) : \ + MUR_ONE_THREE(p)))) +#endif +#define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r)))) +#define MUR_FMIX(_h) \ +do { \ + _h ^= _h >> 16; \ + _h *= 0x85ebca6bu; \ + _h ^= _h >> 13; \ + _h *= 0xc2b2ae35u; \ + _h ^= _h >> 16; \ +} while (0) + +#define HASH_MUR(key,keylen,hashv) \ +do { \ + const uint8_t *_mur_data = (const uint8_t*)(key); \ + const int _mur_nblocks = (int)(keylen) / 4; \ + uint32_t _mur_h1 = 0xf88D5353u; \ + uint32_t _mur_c1 = 0xcc9e2d51u; \ + uint32_t _mur_c2 = 0x1b873593u; \ + uint32_t _mur_k1 = 0; \ + const uint8_t *_mur_tail; \ + const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+(_mur_nblocks*4)); \ + int _mur_i; \ + for(_mur_i = -_mur_nblocks; _mur_i!=0; _mur_i++) { \ + _mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i); \ + _mur_k1 *= _mur_c1; \ + _mur_k1 = MUR_ROTL32(_mur_k1,15); \ + _mur_k1 *= _mur_c2; \ + \ + _mur_h1 ^= _mur_k1; \ + _mur_h1 = MUR_ROTL32(_mur_h1,13); \ + _mur_h1 = (_mur_h1*5U) + 0xe6546b64u; \ + } \ + _mur_tail = (const uint8_t*)(_mur_data + (_mur_nblocks*4)); \ + _mur_k1=0; \ + switch((keylen) & 3U) { \ + case 3: _mur_k1 ^= (uint32_t)_mur_tail[2] << 16; /* FALLTHROUGH */ \ + case 2: _mur_k1 ^= (uint32_t)_mur_tail[1] << 8; /* FALLTHROUGH */ \ + case 1: _mur_k1 ^= (uint32_t)_mur_tail[0]; \ + _mur_k1 *= _mur_c1; \ + _mur_k1 = MUR_ROTL32(_mur_k1,15); \ + _mur_k1 *= _mur_c2; \ + _mur_h1 ^= _mur_k1; \ + } \ + _mur_h1 ^= (uint32_t)(keylen); \ + MUR_FMIX(_mur_h1); \ + hashv = _mur_h1; \ +} while (0) +#endif /* HASH_USING_NO_STRICT_ALIASING */ + +/* iterate over items in a known bucket to find desired item */ +#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,hashval,out) \ +do { \ + if ((head).hh_head != NULL) { \ + DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (head).hh_head)); \ + } else { \ + (out) = NULL; \ + } \ + while ((out) != NULL) { \ + if ((out)->hh.hashv == (hashval) && (out)->hh.keylen == (keylen_in)) { \ + if (uthash_memcmp((out)->hh.key, keyptr, keylen_in) == 0) { \ + break; \ + } \ + } \ + if ((out)->hh.hh_next != NULL) { \ + DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (out)->hh.hh_next)); \ + } else { \ + (out) = NULL; \ + } \ + } \ +} while (0) + +/* add an item to a bucket */ +#define HASH_ADD_TO_BKT(head,addhh) \ +do { \ + head.count++; \ + (addhh)->hh_next = head.hh_head; \ + (addhh)->hh_prev = NULL; \ + if (head.hh_head != NULL) { (head).hh_head->hh_prev = (addhh); } \ + (head).hh_head=addhh; \ + if ((head.count >= ((head.expand_mult+1U) * HASH_BKT_CAPACITY_THRESH)) \ + && ((addhh)->tbl->noexpand != 1U)) { \ + HASH_EXPAND_BUCKETS((addhh)->tbl); \ + } \ +} while (0) + +/* remove an item from a given bucket */ +#define HASH_DEL_IN_BKT(hh,head,hh_del) \ + (head).count--; \ + if ((head).hh_head == hh_del) { \ + (head).hh_head = hh_del->hh_next; \ + } \ + if (hh_del->hh_prev) { \ + hh_del->hh_prev->hh_next = hh_del->hh_next; \ + } \ + if (hh_del->hh_next) { \ + hh_del->hh_next->hh_prev = hh_del->hh_prev; \ + } + +/* Bucket expansion has the effect of doubling the number of buckets + * and redistributing the items into the new buckets. Ideally the + * items will distribute more or less evenly into the new buckets + * (the extent to which this is true is a measure of the quality of + * the hash function as it applies to the key domain). + * + * With the items distributed into more buckets, the chain length + * (item count) in each bucket is reduced. Thus by expanding buckets + * the hash keeps a bound on the chain length. This bounded chain + * length is the essence of how a hash provides constant time lookup. + * + * The calculation of tbl->ideal_chain_maxlen below deserves some + * explanation. First, keep in mind that we're calculating the ideal + * maximum chain length based on the *new* (doubled) bucket count. + * In fractions this is just n/b (n=number of items,b=new num buckets). + * Since the ideal chain length is an integer, we want to calculate + * ceil(n/b). We don't depend on floating point arithmetic in this + * hash, so to calculate ceil(n/b) with integers we could write + * + * ceil(n/b) = (n/b) + ((n%b)?1:0) + * + * and in fact a previous version of this hash did just that. + * But now we have improved things a bit by recognizing that b is + * always a power of two. We keep its base 2 log handy (call it lb), + * so now we can write this with a bit shift and logical AND: + * + * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0) + * + */ +#define HASH_EXPAND_BUCKETS(tbl) \ +do { \ + unsigned _he_bkt; \ + unsigned _he_bkt_i; \ + struct UT_hash_handle *_he_thh, *_he_hh_nxt; \ + UT_hash_bucket *_he_new_buckets, *_he_newbkt; \ + _he_new_buckets = (UT_hash_bucket*)uthash_malloc( \ + 2UL * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ + if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \ + memset(_he_new_buckets, 0, \ + 2UL * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ + tbl->ideal_chain_maxlen = \ + (tbl->num_items >> (tbl->log2_num_buckets+1U)) + \ + (((tbl->num_items & ((tbl->num_buckets*2U)-1U)) != 0U) ? 1U : 0U); \ + tbl->nonideal_items = 0; \ + for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \ + { \ + _he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \ + while (_he_thh != NULL) { \ + _he_hh_nxt = _he_thh->hh_next; \ + HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2U, _he_bkt); \ + _he_newbkt = &(_he_new_buckets[ _he_bkt ]); \ + if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \ + tbl->nonideal_items++; \ + _he_newbkt->expand_mult = _he_newbkt->count / \ + tbl->ideal_chain_maxlen; \ + } \ + _he_thh->hh_prev = NULL; \ + _he_thh->hh_next = _he_newbkt->hh_head; \ + if (_he_newbkt->hh_head != NULL) { _he_newbkt->hh_head->hh_prev = \ + _he_thh; } \ + _he_newbkt->hh_head = _he_thh; \ + _he_thh = _he_hh_nxt; \ + } \ + } \ + uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \ + tbl->num_buckets *= 2U; \ + tbl->log2_num_buckets++; \ + tbl->buckets = _he_new_buckets; \ + tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \ + (tbl->ineff_expands+1U) : 0U; \ + if (tbl->ineff_expands > 1U) { \ + tbl->noexpand=1; \ + uthash_noexpand_fyi(tbl); \ + } \ + uthash_expand_fyi(tbl); \ +} while (0) + + +/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */ +/* Note that HASH_SORT assumes the hash handle name to be hh. + * HASH_SRT was added to allow the hash handle name to be passed in. */ +#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn) +#define HASH_SRT(hh,head,cmpfcn) \ +do { \ + unsigned _hs_i; \ + unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \ + struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \ + if (head != NULL) { \ + _hs_insize = 1; \ + _hs_looping = 1; \ + _hs_list = &((head)->hh); \ + while (_hs_looping != 0U) { \ + _hs_p = _hs_list; \ + _hs_list = NULL; \ + _hs_tail = NULL; \ + _hs_nmerges = 0; \ + while (_hs_p != NULL) { \ + _hs_nmerges++; \ + _hs_q = _hs_p; \ + _hs_psize = 0; \ + for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \ + _hs_psize++; \ + _hs_q = (UT_hash_handle*)((_hs_q->next != NULL) ? \ + ((void*)((char*)(_hs_q->next) + \ + (head)->hh.tbl->hho)) : NULL); \ + if (! (_hs_q) ) { break; } \ + } \ + _hs_qsize = _hs_insize; \ + while ((_hs_psize > 0U) || ((_hs_qsize > 0U) && (_hs_q != NULL))) {\ + if (_hs_psize == 0U) { \ + _hs_e = _hs_q; \ + _hs_q = (UT_hash_handle*)((_hs_q->next != NULL) ? \ + ((void*)((char*)(_hs_q->next) + \ + (head)->hh.tbl->hho)) : NULL); \ + _hs_qsize--; \ + } else if ( (_hs_qsize == 0U) || (_hs_q == NULL) ) { \ + _hs_e = _hs_p; \ + if (_hs_p != NULL){ \ + _hs_p = (UT_hash_handle*)((_hs_p->next != NULL) ? \ + ((void*)((char*)(_hs_p->next) + \ + (head)->hh.tbl->hho)) : NULL); \ + } \ + _hs_psize--; \ + } else if (( \ + cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \ + DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \ + ) <= 0) { \ + _hs_e = _hs_p; \ + if (_hs_p != NULL){ \ + _hs_p = (UT_hash_handle*)((_hs_p->next != NULL) ? \ + ((void*)((char*)(_hs_p->next) + \ + (head)->hh.tbl->hho)) : NULL); \ + } \ + _hs_psize--; \ + } else { \ + _hs_e = _hs_q; \ + _hs_q = (UT_hash_handle*)((_hs_q->next != NULL) ? \ + ((void*)((char*)(_hs_q->next) + \ + (head)->hh.tbl->hho)) : NULL); \ + _hs_qsize--; \ + } \ + if ( _hs_tail != NULL ) { \ + _hs_tail->next = ((_hs_e != NULL) ? \ + ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \ + } else { \ + _hs_list = _hs_e; \ + } \ + if (_hs_e != NULL) { \ + _hs_e->prev = ((_hs_tail != NULL) ? \ + ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \ + } \ + _hs_tail = _hs_e; \ + } \ + _hs_p = _hs_q; \ + } \ + if (_hs_tail != NULL){ \ + _hs_tail->next = NULL; \ + } \ + if ( _hs_nmerges <= 1U ) { \ + _hs_looping=0; \ + (head)->hh.tbl->tail = _hs_tail; \ + DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \ + } \ + _hs_insize *= 2U; \ + } \ + HASH_FSCK(hh,head); \ + } \ +} while (0) + +/* This function selects items from one hash into another hash. + * The end result is that the selected items have dual presence + * in both hashes. There is no copy of the items made; rather + * they are added into the new hash through a secondary hash + * hash handle that must be present in the structure. */ +#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \ +do { \ + unsigned _src_bkt, _dst_bkt; \ + void *_last_elt=NULL, *_elt; \ + UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \ + ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \ + if (src != NULL) { \ + for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \ + for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \ + _src_hh != NULL; \ + _src_hh = _src_hh->hh_next) { \ + _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \ + if (cond(_elt)) { \ + _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \ + _dst_hh->key = _src_hh->key; \ + _dst_hh->keylen = _src_hh->keylen; \ + _dst_hh->hashv = _src_hh->hashv; \ + _dst_hh->prev = _last_elt; \ + _dst_hh->next = NULL; \ + if (_last_elt_hh != NULL) { _last_elt_hh->next = _elt; } \ + if (dst == NULL) { \ + DECLTYPE_ASSIGN(dst,_elt); \ + HASH_MAKE_TABLE(hh_dst,dst); \ + } else { \ + _dst_hh->tbl = (dst)->hh_dst.tbl; \ + } \ + HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \ + HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \ + (dst)->hh_dst.tbl->num_items++; \ + _last_elt = _elt; \ + _last_elt_hh = _dst_hh; \ + } \ + } \ + } \ + } \ + HASH_FSCK(hh_dst,dst); \ +} while (0) + +#define HASH_CLEAR(hh,head) \ +do { \ + if (head != NULL) { \ + uthash_free((head)->hh.tbl->buckets, \ + (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \ + HASH_BLOOM_FREE((head)->hh.tbl); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + (head)=NULL; \ + } \ +} while (0) + +#define HASH_OVERHEAD(hh,head) \ + ((head != NULL) ? ( \ + (size_t)(((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \ + ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \ + sizeof(UT_hash_table) + \ + (HASH_BLOOM_BYTELEN))) : 0U) + +#ifdef NO_DECLTYPE +#define HASH_ITER(hh,head,el,tmp) \ +for(((el)=(head)), ((*(char**)(&(tmp)))=(char*)((head!=NULL)?(head)->hh.next:NULL)); \ + (el) != NULL; ((el)=(tmp)), ((*(char**)(&(tmp)))=(char*)((tmp!=NULL)?(tmp)->hh.next:NULL))) +#else +#define HASH_ITER(hh,head,el,tmp) \ +for(((el)=(head)), ((tmp)=DECLTYPE(el)((head!=NULL)?(head)->hh.next:NULL)); \ + (el) != NULL; ((el)=(tmp)), ((tmp)=DECLTYPE(el)((tmp!=NULL)?(tmp)->hh.next:NULL))) +#endif + +/* obtain a count of items in the hash */ +#define HASH_COUNT(head) HASH_CNT(hh,head) +#define HASH_CNT(hh,head) ((head != NULL)?((head)->hh.tbl->num_items):0U) + +typedef struct UT_hash_bucket { + struct UT_hash_handle *hh_head; + unsigned count; + + /* expand_mult is normally set to 0. In this situation, the max chain length + * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If + * the bucket's chain exceeds this length, bucket expansion is triggered). + * However, setting expand_mult to a non-zero value delays bucket expansion + * (that would be triggered by additions to this particular bucket) + * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH. + * (The multiplier is simply expand_mult+1). The whole idea of this + * multiplier is to reduce bucket expansions, since they are expensive, in + * situations where we know that a particular bucket tends to be overused. + * It is better to let its chain length grow to a longer yet-still-bounded + * value, than to do an O(n) bucket expansion too often. + */ + unsigned expand_mult; + +} UT_hash_bucket; + +/* random signature used only to find hash tables in external analysis */ +#define HASH_SIGNATURE 0xa0111fe1u +#define HASH_BLOOM_SIGNATURE 0xb12220f2u + +typedef struct UT_hash_table { + UT_hash_bucket *buckets; + unsigned num_buckets, log2_num_buckets; + unsigned num_items; + struct UT_hash_handle *tail; /* tail hh in app order, for fast append */ + ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */ + + /* in an ideal situation (all buckets used equally), no bucket would have + * more than ceil(#items/#buckets) items. that's the ideal chain length. */ + unsigned ideal_chain_maxlen; + + /* nonideal_items is the number of items in the hash whose chain position + * exceeds the ideal chain maxlen. these items pay the penalty for an uneven + * hash distribution; reaching them in a chain traversal takes >ideal steps */ + unsigned nonideal_items; + + /* ineffective expands occur when a bucket doubling was performed, but + * afterward, more than half the items in the hash had nonideal chain + * positions. If this happens on two consecutive expansions we inhibit any + * further expansion, as it's not helping; this happens when the hash + * function isn't a good fit for the key domain. When expansion is inhibited + * the hash will still work, albeit no longer in constant time. */ + unsigned ineff_expands, noexpand; + + uint32_t signature; /* used only to find hash tables in external analysis */ +#ifdef HASH_BLOOM + uint32_t bloom_sig; /* used only to test bloom exists in external analysis */ + uint8_t *bloom_bv; + uint8_t bloom_nbits; +#endif + +} UT_hash_table; + +typedef struct UT_hash_handle { + struct UT_hash_table *tbl; + void *prev; /* prev element in app order */ + void *next; /* next element in app order */ + struct UT_hash_handle *hh_prev; /* previous hh in bucket order */ + struct UT_hash_handle *hh_next; /* next hh in bucket order */ + void *key; /* ptr to enclosing struct's key */ + unsigned keylen; /* enclosing struct's key len */ + unsigned hashv; /* result of hash-fcn(key) */ +} UT_hash_handle; + +#endif /* UTHASH_H */ diff --git a/shadowsocksr-libev/src/server/utils.c b/shadowsocksr-libev/src/server/utils.c new file mode 100644 index 0000000..14a60c7 --- /dev/null +++ b/shadowsocksr-libev/src/server/utils.c @@ -0,0 +1,448 @@ +/* + * utils.c - Misc utilities + * + * Copyright (C) 2013 - 2016, Max Lv + * + * This file is part of the shadowsocks-libev. + * + * shadowsocks-libev is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * shadowsocks-libev 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with shadowsocks-libev; see the file COPYING. If not, see + * . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#ifndef __MINGW32__ +#include +#include +#endif + +#include +#include + +#include "utils.h" + +#ifdef HAVE_SETRLIMIT +#include +#include +#endif + +#define INT_DIGITS 19 /* enough for 64 bit integer */ + +#ifdef LIB_ONLY +FILE *logfile; +#endif + +#ifdef HAS_SYSLOG +int use_syslog = 0; +#endif + +#ifndef __MINGW32__ +void +ERROR(const char *s) +{ + char *msg = strerror(errno); + LOGE("%s: %s", s, msg); +} + +#endif + +int use_tty = 1; + +char * +ss_itoa(int i) +{ + /* Room for INT_DIGITS digits, - and '\0' */ + static char buf[INT_DIGITS + 2]; + char *p = buf + INT_DIGITS + 1; /* points to terminating '\0' */ + if (i >= 0) { + do { + *--p = '0' + (i % 10); + i /= 10; + } while (i != 0); + return p; + } else { /* i < 0 */ + do { + *--p = '0' - (i % 10); + i /= 10; + } while (i != 0); + *--p = '-'; + } + return p; +} + +int +ss_isnumeric(const char *s) { + if (!s || !*s) + return 0; + while (isdigit(*s)) + ++s; + return *s == '\0'; +} + +/* + * setuid() and setgid() for a specified user. + */ +int +run_as(const char *user) +{ +#ifndef __MINGW32__ + if (user[0]) { + /* Convert user to a long integer if it is a non-negative number. + * -1 means it is a user name. */ + long uid = -1; + if (ss_isnumeric(user)) { + errno = 0; + char *endptr; + uid = strtol(user, &endptr, 10); + if (errno || endptr == user) + uid = -1; + } + +#ifdef HAVE_GETPWNAM_R + struct passwd pwdbuf, *pwd; + memset(&pwdbuf, 0, sizeof(struct passwd)); + size_t buflen; + int err; + + for (buflen = 128;; buflen *= 2) { + char buf[buflen]; /* variable length array */ + + /* Note that we use getpwnam_r() instead of getpwnam(), + * which returns its result in a statically allocated buffer and + * cannot be considered thread safe. */ + err = uid >= 0 ? getpwuid_r((uid_t)uid, &pwdbuf, buf, buflen, &pwd) + : getpwnam_r(user, &pwdbuf, buf, buflen, &pwd); + + if (err == 0 && pwd) { + /* setgid first, because we may not be allowed to do it anymore after setuid */ + if (setgid(pwd->pw_gid) != 0) { + LOGE( + "Could not change group id to that of run_as user '%s': %s", + pwd->pw_name, strerror(errno)); + return 0; + } + + if (initgroups(pwd->pw_name, pwd->pw_gid) == -1) { + LOGE("Could not change supplementary groups for user '%s'.", pwd->pw_name); + return 0; + } + + if (setuid(pwd->pw_uid) != 0) { + LOGE( + "Could not change user id to that of run_as user '%s': %s", + pwd->pw_name, strerror(errno)); + return 0; + } + break; + } else if (err != ERANGE) { + if (err) { + LOGE("run_as user '%s' could not be found: %s", user, + strerror(err)); + } else { + LOGE("run_as user '%s' could not be found.", user); + } + return 0; + } else if (buflen >= 16 * 1024) { + /* If getpwnam_r() seems defective, call it quits rather than + * keep on allocating ever larger buffers until we crash. */ + LOGE( + "getpwnam_r() requires more than %u bytes of buffer space.", + (unsigned)buflen); + return 0; + } + /* Else try again with larger buffer. */ + } +#else + /* No getpwnam_r() :-( We'll use getpwnam() and hope for the best. */ + struct passwd *pwd; + + if (!(pwd = uid >=0 ? getpwuid((uid_t)uid) : getpwnam(user))) { + LOGE("run_as user %s could not be found.", user); + return 0; + } + /* setgid first, because we may not allowed to do it anymore after setuid */ + if (setgid(pwd->pw_gid) != 0) { + LOGE("Could not change group id to that of run_as user '%s': %s", + pwd->pw_name, strerror(errno)); + return 0; + } + if (initgroups(pwd->pw_name, pwd->pw_gid) == -1) { + LOGE("Could not change supplementary groups for user '%s'.", pwd->pw_name); + return 0; + } + if (setuid(pwd->pw_uid) != 0) { + LOGE("Could not change user id to that of run_as user '%s': %s", + pwd->pw_name, strerror(errno)); + return 0; + } +#endif + } + +#endif // __MINGW32__ + return 1; +} + +char * +ss_strndup(const char *s, size_t n) +{ + size_t len = strlen(s); + char *ret; + + if (len <= n) { + return strdup(s); + } + + ret = ss_malloc(n + 1); + strncpy(ret, s, n); + ret[n] = '\0'; + return ret; +} + +void +FATAL(const char *msg) +{ + LOGE("%s", msg); + exit(-1); +} + +void * +ss_malloc(size_t size) +{ + void *tmp = malloc(size); + if (tmp == NULL) + exit(EXIT_FAILURE); + return tmp; +} + +void * +ss_realloc(void *ptr, size_t new_size) +{ + void *new = realloc(ptr, new_size); + if (new == NULL) { + free(ptr); + ptr = NULL; + exit(EXIT_FAILURE); + } + return new; +} + +void +usage() +{ + printf("\n"); + printf("shadowsocks-libev %s with %s\n\n", VERSION, USING_CRYPTO); + printf( + " maintained by Max Lv and Linus Yang \n\n"); + printf(" usage:\n\n"); +#ifdef MODULE_LOCAL + printf(" ss-local\n"); +#elif MODULE_REMOTE + printf(" ss-server\n"); +#elif MODULE_TUNNEL + printf(" ss-tunnel\n"); +#elif MODULE_REDIR + printf(" ss-redir\n"); +#elif MODULE_MANAGER + printf(" ss-manager\n"); +#endif + printf("\n"); + printf( + " -s Host name or IP address of your remote server.\n"); + printf( + " -p Port number of your remote server.\n"); + printf( + " -l Port number of your local server.\n"); + printf( + " -k Password of your remote server.\n"); + printf( + " -m Encrypt method: table, rc4, rc4-md5,\n"); + printf( + " aes-128-cfb, aes-192-cfb, aes-256-cfb,\n"); + printf( + " aes-128-ctr, aes-192-ctr, aes-256-ctr,\n"); + printf( + " bf-cfb, camellia-128-cfb, camellia-192-cfb,\n"); + printf( + " camellia-256-cfb, cast5-cfb, des-cfb,\n"); + printf( + " idea-cfb, rc2-cfb, seed-cfb, salsa20,\n"); + printf( + " chacha20 and chacha20-ietf.\n"); + printf( + " The default cipher is rc4-md5.\n"); + printf("\n"); + printf( + " [-a ] Run as another user.\n"); + printf( + " [-f ] The file path to store pid.\n"); + printf( + " [-t ] Socket timeout in seconds.\n"); + printf( + " [-c ] The path to config file.\n"); +#ifdef HAVE_SETRLIMIT + printf( + " [-n ] Max number of open files.\n"); +#endif +#ifndef MODULE_REDIR + printf( + " [-i ] Network interface to bind.\n"); +#endif + printf( + " [-b ] Local address to bind.\n"); + printf("\n"); + printf( + " [-u] Enable UDP relay.\n"); +#ifdef MODULE_REDIR + printf( + " TPROXY is required in redir mode.\n"); +#endif + printf( + " [-U] Enable UDP relay and disable TCP relay.\n"); + printf( + " [-A] Enable onetime authentication.\n"); +#ifdef MODULE_REMOTE + printf( + " [-6] Resovle hostname to IPv6 address first.\n"); +#endif + printf("\n"); +#ifdef MODULE_TUNNEL + printf( + " [-L :] Destination server address and port\n"); + printf( + " for local port forwarding.\n"); +#endif +#ifdef MODULE_REMOTE + printf( + " [-d ] Name servers for internal DNS resolver.\n"); +#endif +#if defined(MODULE_REMOTE) || defined(MODULE_LOCAL) + printf( + " [--fast-open] Enable TCP fast open.\n"); + printf( + " with Linux kernel > 3.7.0.\n"); + printf( + " [--acl ] Path to ACL (Access Control List).\n"); +#endif +#if defined(MODULE_REMOTE) || defined(MODULE_MANAGER) + printf( + " [--manager-address ] UNIX domain socket address.\n"); +#endif +#ifdef MODULE_MANAGER + printf( + " [--executable ] Path to the executable of ss-server.\n"); +#endif + printf( + " [--mtu ] MTU of your network interface.\n"); +#ifdef __linux__ + printf( + " [--mptcp] Enable Multipath TCP on MPTCP Kernel.\n"); +#ifdef MODULE_REMOTE + printf( + " [--firewall] Setup firewall rules for auto blocking.\n"); +#endif +#endif + printf("\n"); + printf( + " [-v] Verbose mode.\n"); + printf( + " [-h, --help] Print this message.\n"); + printf("\n"); +} + +void +daemonize(const char *path) +{ +#ifndef __MINGW32__ + /* Our process ID and Session ID */ + pid_t pid, sid; + + /* Fork off the parent process */ + pid = fork(); + if (pid < 0) { + exit(EXIT_FAILURE); + } + + /* If we got a good PID, then + * we can exit the parent process. */ + if (pid > 0) { + FILE *file = fopen(path, "w"); + if (file == NULL) { + FATAL("Invalid pid file\n"); + } + + fprintf(file, "%d", (int)pid); + fclose(file); + exit(EXIT_SUCCESS); + } + + /* Change the file mode mask */ + umask(0); + + /* Open any logs here */ + + /* Create a new SID for the child process */ + sid = setsid(); + if (sid < 0) { + /* Log the failure */ + exit(EXIT_FAILURE); + } + + /* Change the current working directory */ + if ((chdir("/")) < 0) { + /* Log the failure */ + exit(EXIT_FAILURE); + } + + /* Close out the standard file descriptors */ + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); +#endif +} + +#ifdef HAVE_SETRLIMIT +int +set_nofile(int nofile) +{ + struct rlimit limit = { nofile, nofile }; /* set both soft and hard limit */ + + if (nofile <= 0) { + FATAL("nofile must be greater than 0\n"); + } + + if (setrlimit(RLIMIT_NOFILE, &limit) < 0) { + if (errno == EPERM) { + LOGE( + "insufficient permission to change NOFILE, not starting as root?"); + return -1; + } else if (errno == EINVAL) { + LOGE("invalid nofile, decrease nofile and try again"); + return -1; + } else { + LOGE("setrlimit failed: %s", strerror(errno)); + return -1; + } + } + + return 0; +} + +#endif diff --git a/shadowsocksr-libev/src/server/utils.h b/shadowsocksr-libev/src/server/utils.h new file mode 100644 index 0000000..0fb7f5a --- /dev/null +++ b/shadowsocksr-libev/src/server/utils.h @@ -0,0 +1,232 @@ +/* + * utils.h - Misc utilities + * + * Copyright (C) 2013 - 2016, Max Lv + * + * This file is part of the shadowsocks-libev. + * + * shadowsocks-libev is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * shadowsocks-libev 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with shadowsocks-libev; see the file COPYING. If not, see + * . + */ + +#if defined(USE_CRYPTO_OPENSSL) + +#include +#define USING_CRYPTO OPENSSL_VERSION_TEXT + +#elif defined(USE_CRYPTO_POLARSSL) +#include +#define USING_CRYPTO POLARSSL_VERSION_STRING_FULL + +#elif defined(USE_CRYPTO_MBEDTLS) +#include +#define USING_CRYPTO MBEDTLS_VERSION_STRING_FULL + +#endif + +#ifndef _UTILS_H +#define _UTILS_H + +#include +#include +#include +#include + +#define PORTSTRLEN 16 +#define SS_ADDRSTRLEN (INET6_ADDRSTRLEN + PORTSTRLEN + 1) + +#ifdef ANDROID + +#include + +#define USE_TTY() +#define USE_SYSLOG(ident) +#define LOGI(...) \ + ((void)__android_log_print(ANDROID_LOG_DEBUG, "shadowsocks", \ + __VA_ARGS__)) +#define LOGE(...) \ + ((void)__android_log_print(ANDROID_LOG_ERROR, "shadowsocks", \ + __VA_ARGS__)) + +#else + +#define STR(x) # x +#define TOSTR(x) STR(x) + +#ifdef LIB_ONLY + +extern FILE *logfile; + +#define TIME_FORMAT "%Y-%m-%d %H:%M:%S" + +#define USE_TTY() + +#define USE_SYSLOG(ident) + +#define USE_LOGFILE(ident) \ + do { \ + if (ident != NULL) { logfile = fopen(ident, "w+"); } } \ + while (0) + +#define CLOSE_LOGFILE \ + do { \ + if (logfile != NULL) { fclose(logfile); } } \ + while (0) + +#define LOGI(format, ...) \ + do { \ + if (logfile != NULL) { \ + time_t now = time(NULL); \ + char timestr[20]; \ + strftime(timestr, 20, TIME_FORMAT, localtime(&now)); \ + fprintf(logfile, " %s INFO: " format "\n", timestr, ## __VA_ARGS__); \ + fflush(logfile); } \ + } \ + while (0) + +#define LOGE(format, ...) \ + do { \ + if (logfile != NULL) { \ + time_t now = time(NULL); \ + char timestr[20]; \ + strftime(timestr, 20, TIME_FORMAT, localtime(&now)); \ + fprintf(logfile, " %s ERROR: " format "\n", timestr, \ + ## __VA_ARGS__); \ + fflush(logfile); } \ + } \ + while (0) + +#elif defined(_WIN32) + +#define TIME_FORMAT "%Y-%m-%d %H:%M:%S" + +#define USE_TTY() + +#define USE_SYSLOG(ident) + +#define LOGI(format, ...) \ + do { \ + time_t now = time(NULL); \ + char timestr[20]; \ + strftime(timestr, 20, TIME_FORMAT, localtime(&now)); \ + fprintf(stderr, " %s INFO: " format "\n", timestr, ## __VA_ARGS__); \ + fflush(stderr); } \ + while (0) + +#define LOGE(format, ...) \ + do { \ + time_t now = time(NULL); \ + char timestr[20]; \ + strftime(timestr, 20, TIME_FORMAT, localtime(&now)); \ + fprintf(stderr, " %s ERROR: " format "\n", timestr, ## __VA_ARGS__); \ + fflush(stderr); } \ + while (0) + +#else + +#include + +extern int use_tty; +#define USE_TTY() \ + do { \ + use_tty = isatty(STDERR_FILENO); \ + } while (0) \ + +#define HAS_SYSLOG +extern int use_syslog; + +#define TIME_FORMAT "%F %T" + +#define USE_SYSLOG(ident) \ + do { \ + use_syslog = 1; \ + openlog((ident), LOG_CONS | LOG_PID, 0); } \ + while (0) + +#define LOGI(format, ...) \ + do { \ + if (use_syslog) { \ + syslog(LOG_INFO, format, ## __VA_ARGS__); \ + } else { \ + time_t now = time(NULL); \ + char timestr[20]; \ + strftime(timestr, 20, TIME_FORMAT, localtime(&now)); \ + if (use_tty) { \ + fprintf(stderr, "\e[01;32m %s INFO: \e[0m" format "\n", timestr, \ + ## __VA_ARGS__); \ + } else { \ + fprintf(stderr, " %s INFO: " format "\n", timestr, \ + ## __VA_ARGS__); \ + } \ + } \ + } \ + while (0) + +#define LOGE(format, ...) \ + do { \ + if (use_syslog) { \ + syslog(LOG_ERR, format, ## __VA_ARGS__); \ + } else { \ + time_t now = time(NULL); \ + char timestr[20]; \ + strftime(timestr, 20, TIME_FORMAT, localtime(&now)); \ + if (use_tty) { \ + fprintf(stderr, "\e[01;35m %s ERROR: \e[0m" format "\n", timestr, \ + ## __VA_ARGS__); \ + } else { \ + fprintf(stderr, " %s ERROR: " format "\n", timestr, \ + ## __VA_ARGS__); \ + } \ + } } \ + while (0) + +#endif +/* _WIN32 */ + +#endif + +#ifdef __MINGW32__ + +#ifdef ERROR +#undef ERROR +#endif +#define ERROR(s) ss_error(s) + +#else + +void ERROR(const char *s); + +#endif + +char *ss_itoa(int i); +int ss_isnumeric(const char *s); +int run_as(const char *user); +void FATAL(const char *msg); +void usage(void); +void daemonize(const char *path); +char *ss_strndup(const char *s, size_t n); +#ifdef HAVE_SETRLIMIT +int set_nofile(int nofile); +#endif + +void *ss_malloc(size_t size); +void *ss_realloc(void *ptr, size_t new_size); + +#define ss_free(ptr) \ + do { \ + free(ptr); \ + ptr = NULL; \ + } while (0) + +#endif // _UTILS_H diff --git a/shadowsocksr-libev/src/server/verify.c b/shadowsocksr-libev/src/server/verify.c new file mode 100644 index 0000000..9e7393d --- /dev/null +++ b/shadowsocksr-libev/src/server/verify.c @@ -0,0 +1,188 @@ + +#include "verify.h" + +static int verify_simple_pack_unit_size = 2000; + +typedef struct verify_simple_local_data { + char * recv_buffer; + int recv_buffer_size; +}verify_simple_local_data; + +void verify_simple_local_data_init(verify_simple_local_data* local) { + local->recv_buffer = (char*)malloc(16384); + local->recv_buffer_size = 0; +} + +obfs * verify_simple_new_obfs() { + obfs * self = new_obfs(); + self->l_data = malloc(sizeof(verify_simple_local_data)); + verify_simple_local_data_init((verify_simple_local_data*)self->l_data); + return self; +} + +void verify_simple_dispose(obfs *self) { + verify_simple_local_data *local = (verify_simple_local_data*)self->l_data; + if (local->recv_buffer != NULL) { + free(local->recv_buffer); + local->recv_buffer = NULL; + } + free(local); + self->l_data = NULL; + dispose_obfs(self); +} + +int verify_simple_pack_data(char *data, int datalength, char *outdata) { + unsigned char rand_len = (xorshift128plus() & 0xF) + 1; + int out_size = rand_len + datalength + 6; + outdata[0] = out_size >> 8; + outdata[1] = out_size; + outdata[2] = rand_len; + memmove(outdata + rand_len + 2, data, datalength); + fillcrc32((unsigned char *)outdata, out_size); + return out_size; +} + +int verify_simple_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t *capacity) { + char *plaindata = *pplaindata; + //verify_simple_local_data *local = (verify_simple_local_data*)self->l_data; + char * out_buffer = (char*)malloc(datalength * 2 + 32); + char * buffer = out_buffer; + char * data = plaindata; + int len = datalength; + int pack_len; + while ( len > verify_simple_pack_unit_size ) { + pack_len = verify_simple_pack_data(data, verify_simple_pack_unit_size, buffer); + buffer += pack_len; + data += verify_simple_pack_unit_size; + len -= verify_simple_pack_unit_size; + } + if (len > 0) { + pack_len = verify_simple_pack_data(data, len, buffer); + buffer += pack_len; + } + len = buffer - out_buffer; + if (*capacity < len) { + *pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2); + plaindata = *pplaindata; + } + memmove(plaindata, out_buffer, len); + free(out_buffer); + return len; +} + +int verify_simple_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t *capacity) { + char *plaindata = *pplaindata; + verify_simple_local_data *local = (verify_simple_local_data*)self->l_data; + uint8_t * recv_buffer = (uint8_t *)local->recv_buffer; + if (local->recv_buffer_size + datalength > 16384) + return -1; + memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength); + local->recv_buffer_size += datalength; + + char * out_buffer = (char*)malloc(local->recv_buffer_size); + char * buffer = out_buffer; + while (local->recv_buffer_size > 2) { + int length = ((int)recv_buffer[0] << 8) | recv_buffer[1]; + if (length >= 8192 || length < 7) { + free(out_buffer); + local->recv_buffer_size = 0; + return -1; + } + if (length > local->recv_buffer_size) + break; + + int crc = crc32((unsigned char*)recv_buffer, length); + if (crc != -1) { + free(out_buffer); + local->recv_buffer_size = 0; + return -1; + } + int data_size = length - recv_buffer[2] - 6; + memmove(buffer, recv_buffer + 2 + recv_buffer[2], data_size); + buffer += data_size; + memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length); + } + int len = buffer - out_buffer; + if (*capacity < len) { + *pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2); + plaindata = *pplaindata; + } + memmove(plaindata, out_buffer, len); + free(out_buffer); + return len; +} + +int verify_simple_server_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t *capacity) { + char *plaindata = *pplaindata; + //verify_simple_local_data *local = (verify_simple_local_data*)self->l_data; + char * out_buffer = (char*)malloc(datalength * 2 + 32); + char * buffer = out_buffer; + char * data = plaindata; + int len = datalength; + int pack_len; + while ( len > verify_simple_pack_unit_size ) { + pack_len = verify_simple_pack_data(data, verify_simple_pack_unit_size, buffer); + buffer += pack_len; + data += verify_simple_pack_unit_size; + len -= verify_simple_pack_unit_size; + } + if (len > 0) { + pack_len = verify_simple_pack_data(data, len, buffer); + buffer += pack_len; + } + len = buffer - out_buffer; + if (*capacity < len) { + *pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2); + plaindata = *pplaindata; + } + memmove(plaindata, out_buffer, len); + free(out_buffer); + return len; +} + +int verify_simple_server_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t *capacity) { + char *plaindata = *pplaindata; + verify_simple_local_data *local = (verify_simple_local_data*)self->l_data; + uint8_t * recv_buffer = (uint8_t *)local->recv_buffer; + if (local->recv_buffer_size + datalength > 16384) + { + LOGE("verify_simple: wrong buf length %d", local->recv_buffer_size + datalength); + return -1; + } + memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength); + local->recv_buffer_size += datalength; + + char * out_buffer = (char*)malloc(local->recv_buffer_size); + char * buffer = out_buffer; + while (local->recv_buffer_size > 2) { + int length = ((int)recv_buffer[0] << 8) | recv_buffer[1]; + if (length >= 8192 || length < 7) { + free(out_buffer); + local->recv_buffer_size = 0; + LOGE("verify_simple: wrong length %d", length); + return -1; + } + if (length > local->recv_buffer_size) + break; + + int crc = crc32((unsigned char*)recv_buffer, length); + if (crc != -1) { + free(out_buffer); + local->recv_buffer_size = 0; + LOGE("verify_simple: wrong crc"); + return -1; + } + int data_size = length - recv_buffer[2] - 6; + memmove(buffer, recv_buffer + 2 + recv_buffer[2], data_size); + buffer += data_size; + memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length); + } + int len = buffer - out_buffer; + if (*capacity < len) { + *pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2); + plaindata = *pplaindata; + } + memmove(plaindata, out_buffer, len); + free(out_buffer); + return len; +} diff --git a/shadowsocksr-libev/src/server/verify.h b/shadowsocksr-libev/src/server/verify.h new file mode 100644 index 0000000..57c6ff9 --- /dev/null +++ b/shadowsocksr-libev/src/server/verify.h @@ -0,0 +1,19 @@ +/* + * verify.h - Define shadowsocksR server's buffers and callbacks + * + * Copyright (C) 2015 - 2016, Break Wa11 + */ + +#ifndef _VERIFY_H +#define _VERIFY_H + +obfs * verify_simple_new_obfs(); +void verify_simple_dispose(obfs *self); + +int verify_simple_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); +int verify_simple_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); + +int verify_simple_server_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); +int verify_simple_server_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity); + +#endif // _VERIFY_H diff --git a/package/simple-obfs/Makefile b/simple-obfs/Makefile similarity index 92% rename from package/simple-obfs/Makefile rename to simple-obfs/Makefile index bc5f28a..d682beb 100644 --- a/package/simple-obfs/Makefile +++ b/simple-obfs/Makefile @@ -9,16 +9,17 @@ include $(TOPDIR)/rules.mk PKG_NAME:=simple-obfs PKG_VERSION:=0.0.5 -PKG_RELEASE:=4 +PKG_RELEASE:=$(AUTORELEASE) PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/shadowsocks/simple-obfs.git +PKG_MIRROR_HASH:=ea8f2b9825bbb87d5d860524e29bade265141687338db2dbf7ecd32690cf02fc PKG_SOURCE_VERSION:=486bebd9208539058e57e23a12f23103016e09b4 PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION) PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz -PKG_LICENSE:=GPLv3 -PKG_LICENSE_FILES:=LICENSE +PKG_LICENSE:=GPL-3.0-or-later +PKG_LICENSE_FILES:=COPYING LICENSE PKG_MAINTAINER:=Jian Chang PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)/$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION) diff --git a/ssocks/Makefile b/ssocks/Makefile new file mode 100644 index 0000000..2de3b0b --- /dev/null +++ b/ssocks/Makefile @@ -0,0 +1,77 @@ +# +# Copyright (C) 2017-2018 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:=ssocks +PKG_VERSION:=0.0.14 +PKG_RELEASE:=3 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=https://github.com/tostercx/ssocks.git +PKG_SOURCE_DATE:=2020-07-09 +PKG_SOURCE_VERSION:=c2024789c1ee076d171fd6061d7c133302216ea7 +PKG_MIRROR_HASH:=3654e9f1fb54646e1e89c19e7aa3e105b84b2e20b5b634662c21c66691d1d22e + +PKG_LICENSE:=MIT +PKG_LICENSE_FILES:=LICENSE +PKG_MAINTAINER:=Tianling Shen + +PKG_BUILD_PARALLEL:=1 + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/cmake.mk + +define Package/ssocks/template + SECTION:=net + CATEGORY:=Network + TITLE:=sSocks + URL:=https://github.com/tostercx/ssocks + DEPENDS:=+libopenssl +endef + +define Package/ssocks + $(call Package/ssocks/template) + TITLE+= Relay +endef + +define Package/ssocksd + $(call Package/ssocks/template) + TITLE+= Server +endef + +define Package/ssocks/description/template + sSocks is a package which contains: a socks5 server implements RFC 1928 (SOCKS V5) and + RFC 1929 (Authentication for SOCKS V5), a reverse socks server and client, a netcat like tool + and a socks5 relay. +endef + +Package/ssocks/description = $(Package/ssocks/description/template) +Package/ssocksd/description = $(Package/ssocks/description/template) + +define Build/Install + true +endef + +define Package/ssocks/install/template + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/$(2) $(1)/usr/bin/ +endef + +define Package/ssocks/install + $(call Package/ssocks/install/template,$(1),ssocks) +endef + +define Package/ssocksd/install + $(call Package/ssocks/install/template,$(1),ssocksd) +endef + +$(eval $(call BuildPackage,ssocks)) +$(eval $(call BuildPackage,ssocksd)) diff --git a/package/ssocks/patches/001-fix.patch b/ssocks/patches/001-fix.patch similarity index 100% rename from package/ssocks/patches/001-fix.patch rename to ssocks/patches/001-fix.patch diff --git a/package/ssocks/patches/002-gcc10.patch b/ssocks/patches/002-gcc10.patch similarity index 100% rename from package/ssocks/patches/002-gcc10.patch rename to ssocks/patches/002-gcc10.patch diff --git a/package/tcping/Makefile b/tcping/Makefile old mode 100755 new mode 100644 similarity index 87% rename from package/tcping/Makefile rename to tcping/Makefile index 90d8979..9d69985 --- a/package/tcping/Makefile +++ b/tcping/Makefile @@ -12,8 +12,12 @@ PKG_NAME:=tcping PKG_VERSION:=0.3 PKG_RELEASE:=1 +PKG_LICENSE:=GPL-2.0-only +PKG_LICENSE_FILES:=license.txt + PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/Lienol/tcping +PKG_MIRROR_HASH:=79414cd8e1d124422a36b8fe36a1f296b7d9bde99807b2c90ad81bbd65e200e0 PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) PKG_SOURCE_VERSION:=db9101834732dac9aaa59dbb7fb9c74612dbf723 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz diff --git a/trojan-go/Makefile b/trojan-go/Makefile new file mode 100644 index 0000000..248dd91 --- /dev/null +++ b/trojan-go/Makefile @@ -0,0 +1,77 @@ +# SPDX-License-Identifier: GPL-3.0-only +# +# Copyright (C) 2021 ImmortalWrt.org + +include $(TOPDIR)/rules.mk + +PKG_NAME:=trojan-go +PKG_VERSION:=0.10.6 +PKG_RELEASE:=$(AUTORELEASE) + +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:=925f02647dda944813f1eab0b71eac98b83eb5964ef5a6f63e89bc7eb4486c1f + +PKG_LICENSE:=GPL-3.0-only +PKG_LICENSE_FILES:=LICENSE +PKG_MAINTAINER:=Tianling Shen + +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_LDFLAGS:=-s -w +GO_PKG_LDFLAGS_X:= \ + $(GO_PKG)/constant.Version=$(PKG_VERSION) \ + $(GO_PKG)/constant.Commit=v$(PKG_VERSION) +GO_PKG_TAGS:=full + +include $(INCLUDE_DIR)/package.mk +include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk + +define Package/trojan-go + SECTION:=net + CATEGORY:=Network + SUBMENU:=Web Servers/Proxies + TITLE:=A Trojan proxy written in Go + DEPENDS:=$(GO_ARCH_DEPENDS) +ca-bundle + URL:=https://p4gefau1t.github.io/trojan-go/ +endef + +define Package/trojan-go/description + Trojan features multiple protocols over TLS to avoid both + active/passive detections and ISP QoS limitations. +endef + +define Package/trojan-go/config +config TROJAN_GO_COMPRESS_GOPROXY + bool "Compiling with GOPROXY proxy" + default n + +config TROJAN_GO_COMPRESS_UPX + bool "Compress executable files with UPX" + depends on !mips64 + default n +endef + +ifeq ($(CONFIG_TROJAN_GO_COMPRESS_GOPROXY),y) + export GO111MODULE=on + export GOPROXY=https://goproxy.baidu.com +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)/trojan-go +endif +endef + +$(eval $(call GoBinPackage,trojan-go)) +$(eval $(call BuildPackage,trojan-go)) diff --git a/package/trojan-plus/Makefile b/trojan-plus/Makefile similarity index 81% rename from package/trojan-plus/Makefile rename to trojan-plus/Makefile index aa64efb..5120ab7 100644 --- a/package/trojan-plus/Makefile +++ b/trojan-plus/Makefile @@ -8,19 +8,19 @@ include $(TOPDIR)/rules.mk PKG_NAME:=trojan-plus PKG_VERSION:=10.0.3 -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/peter-tank/trojan-plus.git -PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE_DATE:=2020-09-06 PKG_SOURCE_VERSION:=a6394cdd718669b0c7491493a78e61f6f0f899b3 -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz +PKG_MIRROR_HASH:=2d37d09fe6d39d7981116ad387706f58f2b30b74a34e27fc5608f267dacc9208 -CMAKE_INSTALL:=1 -PKG_BUILD_PARALLEL:=0 +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 @@ -51,18 +51,19 @@ CMAKE_OPTIONS += \ -DBoost_DEBUG=ON \ -DBoost_NO_BOOST_CMAKE=ON -define Package/$(PKG_NAME) +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 \ + DEPENDS:= \ + +libpthread +libstdcpp +libopenssl \ +boost +boost-system +boost-program_options endef -define Package/$(PKG_NAME)/install +define Package/trojan-plus/install $(INSTALL_DIR) $(1)/usr/sbin - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/trojan $(1)/usr/sbin/$(PKG_NAME) + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/trojan $(1)/usr/sbin/trojan-plus endef -$(eval $(call BuildPackage,$(PKG_NAME))) +$(eval $(call BuildPackage,trojan-plus)) diff --git a/package/trojan/Makefile b/trojan/Makefile similarity index 79% rename from package/trojan/Makefile rename to trojan/Makefile index c86941d..d16dd51 100644 --- a/package/trojan/Makefile +++ b/trojan/Makefile @@ -8,19 +8,17 @@ include $(TOPDIR)/rules.mk PKG_NAME:=trojan PKG_VERSION:=1.16.0 -PKG_RELEASE:=1 +PKG_RELEASE:=2 -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://github.com/trojan-gfw/trojan.git -PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) -PKG_SOURCE_VERSION:=8606b7110fe79f8ab02d60c897f87ffb0a9b23f0 -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz +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 -CMAKE_INSTALL:=1 -PKG_BUILD_PARALLEL:=0 +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 @@ -56,7 +54,8 @@ define Package/trojan CATEGORY:=Network TITLE:=An unidentifiable mechanism that helps you bypass GFW URL:=https://github.com/trojan-gfw/trojan - DEPENDS:=+libpthread +libstdcpp +libopenssl \ + DEPENDS:= \ + +libpthread +libstdcpp +libopenssl \ +boost +boost-system +boost-program_options +boost-date_time endef diff --git a/package/trojan/patches/001-force-openssl-version.patch b/trojan/patches/001-force-openssl-version.patch similarity index 100% rename from package/trojan/patches/001-force-openssl-version.patch rename to trojan/patches/001-force-openssl-version.patch diff --git a/v2ray-core/Makefile b/v2ray-core/Makefile new file mode 100644 index 0000000..25efe6b --- /dev/null +++ b/v2ray-core/Makefile @@ -0,0 +1,189 @@ +# SPDX-License-Identifier: GPL-3.0-only +# +# Copyright (C) 2021 ImmortalWrt.org + +include $(TOPDIR)/rules.mk + +PKG_NAME:=v2ray-core +PKG_VERSION:=4.44.0 +PKG_RELEASE:=$(AUTORELEASE) + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=https://codeload.github.com/v2fly/v2ray-core/tar.gz/v$(PKG_VERSION)? +PKG_HASH:=d9973bafd3020f60a51fa3495b24ab417b08b3c8f9539a3748d00da6c68d0103 + +PKG_LICENSE:=MIT +PKG_LICENSE_FILES:=LICENSE +PKG_MAINTAINER:=Tianling Shen + +PKG_CONFIG_DEPENDS:= \ + CONFIG_V2RAY_CORE_COMPRESS_GOPROXY \ + CONFIG_V2RAY_CORE_COMPRESS_UPX \ + CONFIG_V2RAY_CTL_COMPRESS_GOPROXY \ + CONFIG_V2RAY_CTL_COMPRESS_UPX + +PKG_BUILD_DEPENDS:=golang/host +PKG_BUILD_PARALLEL:=1 +PKG_USE_MIPS16:=0 + +GO_PKG:=github.com/v2fly/v2ray-core/v4 +GO_PKG_BUILD_PKG:=github.com/v2fly/v2ray-core/v4/main +GO_PKG_LDFLAGS:=-s -w +GO_PKG_LDFLAGS_X:= \ + $(GO_PKG).build=OpenWrt \ + $(GO_PKG).version=$(PKG_VERSION) + +include $(INCLUDE_DIR)/package.mk +include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk + +define Package/v2ray/template + TITLE:=A platform for building proxies to bypass network restrictions + SECTION:=net + CATEGORY:=Network + URL:=https://www.v2fly.org +endef + +define Package/v2ray-core + $(call Package/v2ray/template) + DEPENDS:=$(GO_ARCH_DEPENDS) +ca-bundle +endef + +define Package/v2ray-ctl + $(call Package/v2ray/template) + DEPENDS:=v2ray-core +endef + +define Package/v2ray-example + $(call Package/v2ray/template) + TITLE+= (example configs) + DEPENDS:=v2ray-core + PKGARCH:=all +endef + +define Package/v2ray-extra + $(call Package/v2ray/template) + TITLE+= (extra resources) + DEPENDS:=v2ray-core + PKGARCH:=all +endef + +define Package/v2ray/description + Project V is a set of network tools that help you to build your own computer network. + It secures your network connections and thus protects your privacy. +endef + +define Package/v2ray-core/description + $(call Package/v2ray/description) +endef + +define Package/v2ray-ctl/description + $(call Package/v2ray/description) + + This includes configuration tool for v2ray-core. +endef + +define Package/v2ray-example/description + $(call Package/v2ray/description) + + This includes example configuration files for v2ray-core. +endef + +define Package/v2ray-extra/description + $(call Package/v2ray/description) + + This includes extra resources for v2ray-core. +endef + +define Package/v2ray-core/config +menu "v2ray-core Configuration" + depends on PACKAGE_v2ray-core + +config V2RAY_CORE_COMPRESS_GOPROXY + bool "Compiling with GOPROXY proxy" + default n + +config V2RAY_CORE_COMPRESS_UPX + bool "Compress executable files with UPX" + depends on !mips64 + default n +endmenu +endef + +define Package/v2ray-ctl/config +menu "v2ray-ctl Configuration" + depends on PACKAGE_v2ray-ctl + +config V2RAY_CTL_COMPRESS_GOPROXY + bool "Compiling with GOPROXY proxy" + default n + +config V2RAY_CTL_COMPRESS_UPX + bool "Compress executable files with UPX" + depends on !mips64 + default n +endmenu +endef + +define Package/v2ray-core/conffiles +/etc/config/v2ray +/etc/v2ray/ +endef + +ifneq ($(CONFIG_V2RAY_CORE_COMPRESS_GOPROXY)$(CONFIG_V2RAY_CTL_COMPRESS_GOPROXY),) + export GO111MODULE=on + export GOPROXY=https://goproxy.baidu.com +endif + +define Build/Compile + $(call GoPackage/Build/Compile) + mv $(GO_PKG_BUILD_BIN_DIR)/main $(GO_PKG_BUILD_BIN_DIR)/v2ray +ifneq ($(CONFIG_V2RAY_CORE_COMPRESS_UPX),) + $(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DIR)/v2ray +endif + +ifneq ($(CONFIG_PACKAGE_v2ray-ctl),) + $(eval GO_PKG_BUILD_PKG:=$(GO_PKG)/infra/control/main) + $(call GoPackage/Build/Compile) + mv $(GO_PKG_BUILD_BIN_DIR)/main $(GO_PKG_BUILD_BIN_DIR)/v2ctl +ifneq ($(CONFIG_V2RAY_CTL_COMPRESS_UPX),) + $(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DIR)/v2ctl +endif +endif +endef + +define Package/v2ray-core/install + $(call GoPackage/Package/Install/Bin,$(PKG_INSTALL_DIR)) + $(INSTALL_DIR) $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/v2ray $(1)/usr/bin/ + + $(INSTALL_DIR) $(1)/etc/v2ray/ + $(INSTALL_DATA) $(PKG_BUILD_DIR)/release/config/config.json $(1)/etc/v2ray/ + + $(INSTALL_DIR) $(1)/etc/config/ + $(INSTALL_CONF) $(CURDIR)/files/v2ray.conf $(1)/etc/config/v2ray + $(INSTALL_DIR) $(1)/etc/init.d/ + $(INSTALL_BIN) $(CURDIR)/files/v2ray.init $(1)/etc/init.d/v2ray +endef + +define Package/v2ray-ctl/install + $(call GoPackage/Package/Install/Bin,$(PKG_INSTALL_DIR)) + + $(INSTALL_DIR) $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/v2ctl $(1)/usr/bin/ +endef + +define Package/v2ray-example/install + $(INSTALL_DIR) $(1)/etc/v2ray/ + $(INSTALL_DATA) $(PKG_BUILD_DIR)/release/config/vpoint_socks_vmess.json $(1)/etc/v2ray/ + $(INSTALL_DATA) $(PKG_BUILD_DIR)/release/config/vpoint_vmess_freedom.json $(1)/etc/v2ray/ +endef + +define Package/v2ray-extra/install + $(INSTALL_DIR) $(1)/usr/share/v2ray/ + $(CP) $(PKG_BUILD_DIR)/release/extra/* $(1)/usr/share/v2ray/ +endef + +$(eval $(call BuildPackage,v2ray-core)) +$(eval $(call BuildPackage,v2ray-ctl)) +$(eval $(call BuildPackage,v2ray-example)) +$(eval $(call BuildPackage,v2ray-extra)) diff --git a/v2ray-core/files/v2ray.conf b/v2ray-core/files/v2ray.conf new file mode 100644 index 0000000..6df1e10 --- /dev/null +++ b/v2ray-core/files/v2ray.conf @@ -0,0 +1,11 @@ + +config v2ray 'enabled' + option enabled '0' + +config v2ray 'config' + option confdir '/etc/v2ray' + list conffiles '/etc/v2ray/config.json' + option datadir '/usr/share/v2ray' + option format 'json' + option memconservative '1' + diff --git a/v2ray-core/files/v2ray.init b/v2ray-core/files/v2ray.init new file mode 100755 index 0000000..4370c7f --- /dev/null +++ b/v2ray-core/files/v2ray.init @@ -0,0 +1,56 @@ +#!/bin/sh /etc/rc.common + +USE_PROCD=1 +START=99 + +CONF="v2ray" +PROG="/usr/bin/v2ray" +CAPA_FILE="/etc/capabilities/v2ray.json" + +start_service() { + config_load "$CONF" + + local enabled + config_get_bool enabled "enabled" "enabled" "0" + [ "$enabled" -eq "0" ] && exit 1 + + local confdir + local conffiles + local datadir + local format + + config_get confdir "config" "confdir" + config_get conffiles "config" "conffiles" + config_get datadir "config" "datadir" "/usr/share/v2ray" + config_get format "config" "format" "json" + config_get_bool memconservative "config" "memconservative" "1" + + procd_open_instance "$CONF" + procd_set_param command "$PROG" run + [ -n "$confdir" ] && procd_append_param command -confdir "$confdir" + [ -n "$conffiles" ] && { + for i in $conffiles + do + procd_append_param command -config "$i" + done + } + [ -n "$format" ] && procd_append_param command -format "$format" + procd_set_param env v2ray.local.asset="$datadir" + [ "$memconservative" -eq "1" ] && procd_append_param env V2RAY_CONF_GEOLOADER="memconservative" + procd_set_param file $conffiles + + procd_set_param stdout 1 + procd_set_param stderr 1 + procd_set_param respawn + + procd_close_instance +} + +reload_service() { + stop + start +} + +service_triggers() { + procd_add_reload_trigger "$CONF" +} diff --git a/v2ray-geodata/Makefile b/v2ray-geodata/Makefile new file mode 100644 index 0000000..9a127f6 --- /dev/null +++ b/v2ray-geodata/Makefile @@ -0,0 +1,79 @@ +# SPDX-License-Identifier: GPL-3.0-only +# +# Copyright (C) 2021 ImmortalWrt.org + +include $(TOPDIR)/rules.mk + +PKG_NAME:=v2ray-geodata +PKG_RELEASE:=$(AUTORELEASE) + +PKG_LICENSE_FILES:=LICENSE +PKG_MAINTAINER:=Tianling Shen + +include $(INCLUDE_DIR)/package.mk + +GEOIP_VER:=202112090029 +GEOIP_FILE:=geoip.dat.$(GEOIP_VER) +define Download/geoip + URL:=https://github.com/v2fly/geoip/releases/download/$(GEOIP_VER)/ + URL_FILE:=geoip.dat + FILE:=$(GEOIP_FILE) + HASH:=704c53a30531b74a2c4c51b5ee958340717fc81906335c4342fb7d6ef4243ba9 +endef + +GEOSITE_VER:=20211209100918 +GEOSITE_FILE:=dlc.dat.$(GEOSITE_VER) +define Download/geosite + URL:=https://github.com/v2fly/domain-list-community/releases/download/$(GEOSITE_VER)/ + URL_FILE:=dlc.dat + FILE:=$(GEOSITE_FILE) + HASH:=a39901df0d0f7477d874cda50b045057610837dd0d80f7ff4c51b7ab87d88b18 +endef + +define Package/v2ray-geodata/template + SECTION:=net + CATEGORY:=Network + SUBMENU:=IP Addresses and Names + URL:=https://www.v2fly.org + PKGARCH:=all +endef + +define Package/v2ray-geoip + $(call Package/v2ray-geodata/template) + TITLE:=GeoIP List for V2Ray + VERSION:=$(GEOIP_VER)-$(PKG_RELEASE) + LICENSE:=CC-BY-SA-4.0 +endef + +define Package/v2ray-geosite + $(call Package/v2ray-geodata/template) + TITLE:=Geosite List for V2Ray + VERSION:=$(GEOSITE_VER)-$(PKG_RELEASE) + LICENSE:=MIT +endef + +define Build/Prepare + $(call Build/Prepare/Default) +ifneq ($(CONFIG_PACKAGE_v2ray-geoip),) + $(call Download,geoip) +endif +ifneq ($(CONFIG_PACKAGE_v2ray-geosite),) + $(call Download,geosite) +endif +endef + +define Build/Compile +endef + +define Package/v2ray-geoip/install + $(INSTALL_DIR) $(1)/usr/share/v2ray + $(INSTALL_DATA) $(DL_DIR)/$(GEOIP_FILE) $(1)/usr/share/v2ray/geoip.dat +endef + +define Package/v2ray-geosite/install + $(INSTALL_DIR) $(1)/usr/share/v2ray + $(INSTALL_DATA) $(DL_DIR)/$(GEOSITE_FILE) $(1)/usr/share/v2ray/geosite.dat +endef + +$(eval $(call BuildPackage,v2ray-geoip)) +$(eval $(call BuildPackage,v2ray-geosite)) diff --git a/v2ray-plugin/Makefile b/v2ray-plugin/Makefile new file mode 100644 index 0000000..6a1f888 --- /dev/null +++ b/v2ray-plugin/Makefile @@ -0,0 +1,74 @@ +# SPDX-License-Identifier: GPL-3.0-only +# +# Copyright (C) 2020 SharerMax +# Copyright (C) 2021 ImmortalWrt.org + +include $(TOPDIR)/rules.mk + +PKG_NAME:=v2ray-plugin +PKG_VERSION:=4.44.0 +PKG_RELEASE:=$(AUTORELEASE) + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=https://codeload.github.com/teddysun/v2ray-plugin/tar.gz/v$(PKG_VERSION)? +PKG_HASH:=f94e8efe879a5300871dd01faec7d6635baaef4dbd39d83f4362802f716d386e + +PKG_LICENSE:=MIT +PKG_LICENSE_FILES:=LICENSE +PKG_MAINTAINER:=madeye + +PKG_BUILD_DEPENDS:=golang/host +PKG_BUILD_PARALLEL:=1 +PKG_USE_MIPS16:=0 + +GO_PKG:=github.com/shadowsocks/v2ray-plugin +GO_PKG_LDFLAGS:=-s -w +GO_PKG_LDFLAGS_X:=main.VERSION=v$(PKG_VERSION) + +PKG_CONFIG_DEPENDS := \ + CONFIG_V2RAY_PLUGIN_INCLUDE_GOPROXY \ + CONFIG_V2RAY_PLUGIN_COMPRESS_UPX + +include $(INCLUDE_DIR)/package.mk +include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk + +define Package/v2ray-plugin/config +config V2RAY_PLUGIN_INCLUDE_GOPROXY + bool "Compiling with GOPROXY proxy" + default n + +config V2RAY_PLUGIN_COMPRESS_UPX + bool "Compress executable files with UPX" + depends on !mips64 + default n +endef + +ifeq ($(CONFIG_V2RAY_PLUGIN_INCLUDE_GOPROXY),y) +export GO111MODULE=on +export GOPROXY=https://goproxy.io +#export GOPROXY=https://mirrors.aliyun.com/goproxy/ +endif + +define Package/v2ray-plugin + SECTION:=net + CATEGORY:=Network + SUBMENU:=Web Servers/Proxies + TITLE:=SIP003 plugin for shadowsocks, based on v2ray + URL:=https://github.com/teddysun/v2ray-plugin + DEPENDS:=$(GO_ARCH_DEPENDS) +ca-bundle +endef + +define Build/Compile + $(call GoPackage/Build/Compile) +ifneq ($(CONFIG_V2RAY_PLUGIN_COMPRESS_UPX),) + $(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DIR)/v2ray-plugin +endif +endef + +define Package/v2ray-plugin/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(GO_PKG_BUILD_BIN_DIR)/v2ray-plugin $(1)/usr/bin/v2ray-plugin +endef + +$(eval $(call GoBinPackage,v2ray-plugin)) +$(eval $(call BuildPackage,v2ray-plugin)) diff --git a/xray-core/Makefile b/xray-core/Makefile new file mode 100644 index 0000000..254b1fd --- /dev/null +++ b/xray-core/Makefile @@ -0,0 +1,126 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=Xray-core +PKG_VERSION:=1.5.3 +PKG_RELEASE:=$(AUTORELEASE) + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=https://codeload.github.com/XTLS/Xray-core/tar.gz/v$(PKG_VERSION)? +PKG_HASH:=4b8d78cc20bdf2e8936c02b05d22f0a3231075155ffdc67508d8448ab8858252 + +#PKG_SOURCE_PROTO:=git +#PKG_SOURCE_URL:=https://github.com/XTLS/xray-core.git +#PKG_MIRROR_HASH:=19f3017d8279acc28d242d18689b95a39ca00a286e72329552d114f04a861ecb +#PKG_SOURCE_VERSION:=c345d4818efa763b07961d6c132afe1cf91845de +#PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz + +PKG_MAINTAINER:=Tianling Shen +PKG_LICENSE:=MPL-2.0 +PKG_LICENSE_FILES:=LICENSE + +PKG_CONFIG_DEPENDS:= \ + CONFIG_XRAY_CORE_COMPRESS_GOPROXY \ + CONFIG_XRAY_CORE_COMPRESS_UPX \ + +PKG_BUILD_DEPENDS:=golang/host +PKG_BUILD_PARALLEL:=1 +PKG_USE_MIPS16:=0 + +GO_PKG:=github.com/xtls/xray-core +GO_PKG_BUILD_PKG:=github.com/xtls/xray-core/main +GO_PKG_LDFLAGS:=-s -w +GO_PKG_LDFLAGS_X:= \ + $(GO_PKG)/core.build=OpenWrt \ + $(GO_PKG)/core.version=$(PKG_VERSION) + +include $(INCLUDE_DIR)/package.mk +include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk + +define Package/xray/template + TITLE:=A platform for building proxies to bypass network restrictions + SECTION:=net + CATEGORY:=Network + URL:=https://xtls.github.io +endef + +define Package/xray-core + $(call Package/xray/template) + DEPENDS:=$(GO_ARCH_DEPENDS) +ca-bundle +endef + +define Package/xray-example + $(call Package/xray/template) + TITLE+= (example configs) + DEPENDS:=xray-core + PKGARCH:=all +endef + +define Package/xray/description + Xray, Penetrates Everything. It helps you to build your own computer network. + It secures your network connections and thus protects your privacy. +endef + +define Package/xray-core/description + $(call Package/xray/description) +endef + +define Package/xray-example/description + $(call Package/xray/description) + + This includes example configuration files for xray-core. +endef + +define Package/xray-core/config +menu "Xray-core Configuration" + depends on PACKAGE_xray-core + +config XRAY_CORE_COMPRESS_GOPROXY + bool "Compiling with GOPROXY proxy" + default n + +config XRAY_CORE_COMPRESS_UPX + bool "Compress executable files with UPX" + depends on !mips64 + default n +endmenu +endef + +define Package/xray-core/conffiles +/etc/xray/ +/etc/config/xray +endef + +ifneq ($(CONFIG_XRAY_CORE_COMPRESS_GOPROXY),) + export GO111MODULE=on + export GOPROXY=https://goproxy.baidu.com +endif + +define Build/Compile + $(call GoPackage/Build/Compile) +ifneq ($(CONFIG_XRAY_CORE_COMPRESS_UPX),) + $(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DIR)/main +endif +endef + +define Package/xray-core/install + $(call GoPackage/Package/Install/Bin,$(PKG_INSTALL_DIR)) + $(INSTALL_DIR) $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/main $(1)/usr/bin/xray + + $(INSTALL_DIR) $(1)/etc/xray/ + $(INSTALL_DATA) $(CURDIR)/files/config.json.example $(1)/etc/xray/ + + $(INSTALL_DIR) $(1)/etc/config/ + $(INSTALL_CONF) $(CURDIR)/files/xray.conf $(1)/etc/config/xray + $(INSTALL_DIR) $(1)/etc/init.d/ + $(INSTALL_BIN) $(CURDIR)/files/xray.init $(1)/etc/init.d/xray +endef + +define Package/xray-example/install + $(INSTALL_DIR) $(1)/etc/xray/ + $(INSTALL_DATA) $(CURDIR)/files/vpoint_socks_vmess.json $(1)/etc/xray/ + $(INSTALL_DATA) $(CURDIR)/files/vpoint_vmess_freedom.json $(1)/etc/xray/ +endef + +$(eval $(call BuildPackage,xray-core)) +$(eval $(call BuildPackage,xray-example)) diff --git a/xray-core/files/config.json.example b/xray-core/files/config.json.example new file mode 100644 index 0000000..710bb1b --- /dev/null +++ b/xray-core/files/config.json.example @@ -0,0 +1,144 @@ +// Config file of Xray. This file follows standard JSON format, with comments support. +// Uncomment entries below to satisfy your needs. Also read our manual for more detail at +// https://xtls.github.io/en/config/ +{ + "log": { + // By default, Xray writes access log to stdout. + // "access": "/path/to/access/log/file", + + // By default, Xray write error log to stdout. + // "error": "/path/to/error/log/file", + + // Log level, one of "debug", "info", "warning", "error", "none" + "loglevel": "warning" + }, + // List of inbound proxy configurations. + "inbounds": [{ + // Port to listen on. You may need root access if the value is less than 1024. + "port": 1080, + + // IP address to listen on. Change to "0.0.0.0" to listen on all network interfaces. + "listen": "127.0.0.1", + + // Tag of the inbound proxy. May be used for routing. + "tag": "socks-inbound", + + // Protocol name of inbound proxy. + "protocol": "socks", + + // Settings of the protocol. Varies based on protocol. + "settings": { + "auth": "noauth", + "udp": false, + "ip": "127.0.0.1" + }, + + // Enable sniffing on TCP connection. + "sniffing": { + "enabled": true, + // Target domain will be overriden to the one carried by the connection, if the connection is HTTP or HTTPS. + "destOverride": ["http", "tls"] + } + }], + // List of outbound proxy configurations. + "outbounds": [{ + // Protocol name of the outbound proxy. + "protocol": "freedom", + + // Settings of the protocol. Varies based on protocol. + "settings": {}, + + // Tag of the outbound. May be used for routing. + "tag": "direct" + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }], + + // Transport is for global transport settings. If you have multiple transports with same settings + // (say mKCP), you may put it here, instead of in each individual inbound/outbounds. + //"transport": {}, + + // Routing controls how traffic from inbounds are sent to outbounds. + "routing": { + "domainStrategy": "IPOnDemand", + "rules":[ + { + // Blocks access to private IPs. Remove this if you want to access your router. + "type": "field", + "ip": ["geoip:private"], + "outboundTag": "blocked" + }, + { + // Blocks major ads. + "type": "field", + "domain": ["geosite:category-ads"], + "outboundTag": "blocked" + } + ] + }, + + // Dns settings for domain resolution. + "dns": { + // Static hosts, similar to hosts file. + "hosts": { + // Match v2ray.com to another domain on CloudFlare. This domain will be used when querying IPs for v2ray.com. + "domain:v2ray.com": "www.vicemc.net", + + // The following settings help to eliminate DNS poisoning in mainland China. + // It is safe to comment these out if this is not the case for you. + "domain:github.io": "pages.github.com", + "domain:wikipedia.org": "www.wikimedia.org", + "domain:shadowsocks.org": "electronicsrealm.com" + }, + "servers": [ + "1.1.1.1", + { + "address": "114.114.114.114", + "port": 53, + // List of domains that use this DNS first. + "domains": [ + "geosite:cn" + ] + }, + "8.8.8.8", + "localhost" + ] + }, + + // Policy controls some internal behavior of how Xray handles connections. + // It may be on connection level by user levels in 'levels', or global settings in 'system.' + "policy": { + // Connection policys by user levels + "levels": { + "0": { + "uplinkOnly": 0, + "downlinkOnly": 0 + } + }, + "system": { + "statsInboundUplink": false, + "statsInboundDownlink": false, + "statsOutboundUplink": false, + "statsOutboundDownlink": false + } + }, + + // Stats enables internal stats counter. + // This setting can be used together with Policy and Api. + //"stats":{}, + + // Api enables gRPC APIs for external programs to communicate with Xray instance. + //"api": { + //"tag": "api", + //"services": [ + // "HandlerService", + // "LoggerService", + // "StatsService" + //] + //}, + + // You may add other entries to the configuration, but they will not be recognized by Xray. + "other": {} +} diff --git a/xray-core/files/vpoint_socks_vmess.json b/xray-core/files/vpoint_socks_vmess.json new file mode 100644 index 0000000..789cd27 --- /dev/null +++ b/xray-core/files/vpoint_socks_vmess.json @@ -0,0 +1,25 @@ +{ + "log": { + "loglevel": "warning" + }, + "inbounds": [{ + "port": 1080, + "listen": "127.0.0.1", + "protocol": "socks", + "settings": { + "auth": "noauth", + "udp": false, + "ip": "127.0.0.1" + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {}, + "tag": "direct" + }], + "policy": { + "levels": { + "0": {"uplinkOnly": 0} + } + } +} diff --git a/xray-core/files/vpoint_vmess_freedom.json b/xray-core/files/vpoint_vmess_freedom.json new file mode 100644 index 0000000..41c7e30 --- /dev/null +++ b/xray-core/files/vpoint_vmess_freedom.json @@ -0,0 +1,31 @@ +{ + "inbounds": [{ + "port": 10086, + "protocol": "vmess", + "settings": { + "clients": [ + { + "id": "23ad6b10-8d1a-40f7-8ad0-e3e35cd38297", + "level": 1 + } + ] + } + }], + "outbounds": [{ + "protocol": "freedom", + "settings": {} + },{ + "protocol": "blackhole", + "settings": {}, + "tag": "blocked" + }], + "routing": { + "rules": [ + { + "type": "field", + "ip": ["geoip:private"], + "outboundTag": "blocked" + } + ] + } +} diff --git a/xray-core/files/xray.conf b/xray-core/files/xray.conf new file mode 100644 index 0000000..362fbac --- /dev/null +++ b/xray-core/files/xray.conf @@ -0,0 +1,11 @@ + +config xray 'enabled' + option enabled '0' + +config xray 'config' + option confdir '/etc/xray' + list conffiles '/etc/xray/config.json' + option datadir '/usr/share/v2ray' + option dialer '' + option format 'json' + diff --git a/xray-core/files/xray.init b/xray-core/files/xray.init new file mode 100755 index 0000000..1197255 --- /dev/null +++ b/xray-core/files/xray.init @@ -0,0 +1,56 @@ +#!/bin/sh /etc/rc.common + +USE_PROCD=1 +START=99 + +CONF="xray" +PROG="/usr/bin/xray" + +start_service() { + config_load "$CONF" + + local enabled + config_get enabled "enabled" "enabled" "0" + [ "$enabled" -eq "0" ] && exit 1 + + local confdir + local conffiles + local datadir + local dialer + local format + + config_get confdir "config" "confdir" + config_get conffiles "config" "conffiles" + config_get datadir "config" "datadir" "/usr/share/v2ray" + config_get dialer "config" "dialer" + config_get format "config" "format" "json" + + procd_open_instance "$CONF" + procd_set_param command "$PROG" run + [ -n "$confdir" ] && procd_append_param command -confdir "$confdir" + [ -n "$conffiles" ] && { + for i in $conffiles + do + procd_append_param command -config "$i" + done + } + [ -n "$format" ] && procd_append_param command -format "$format" + [ -n "$dialer" ] && procd_set_param env XRAY_BROWSER_DIALER="$dialer" + procd_set_param env XRAY_LOCATION_ASSET="$datadir" + procd_set_param file $conffiles + + procd_set_param stdout 1 + procd_set_param stderr 1 + procd_set_param respawn + + procd_close_instance +} + +reload_service() { + stop + start +} + +service_triggers() { + procd_add_reload_trigger "$CONF" +} diff --git a/xray-plugin/Makefile b/xray-plugin/Makefile new file mode 100644 index 0000000..e1a1bf0 --- /dev/null +++ b/xray-plugin/Makefile @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: GPL-3.0-only +# +# Copyright (C) 2021 ImmortalWrt.org + +include $(TOPDIR)/rules.mk + +PKG_NAME:=xray-plugin +PKG_VERSION:=1.5.3 +PKG_RELEASE:=$(AUTORELEASE) + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=https://codeload.github.com/teddysun/xray-plugin/tar.gz/v$(PKG_VERSION)? +PKG_HASH:=0280e1c7c9c87db13a456be098e42065374066df4108b87c2e1d781337740a73 + +PKG_LICENSE:=MIT +PKG_LICENSE_FILES:=LICENSE +PKG_MAINTAINER:=Tianling Shen + +PKG_CONFIG_DEPENDS:= \ + CONFIG_XRAY_PLUGIN_COMPRESS_GOPROXY \ + CONFIG_XRAY_PLUGIN_COMPRESS_UPX + +PKG_BUILD_DEPENDS:=golang/host +PKG_BUILD_PARALLEL:=1 +PKG_USE_MIPS16:=0 + +GO_PKG:=github.com/teddysun/xray-plugin +GO_PKG_LDFLAGS:=-s -w + +include $(INCLUDE_DIR)/package.mk +include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk + +define Package/xray-plugin/config +config XRAY_PLUGIN_COMPRESS_GOPROXY + bool "Compiling with GOPROXY proxy" + default n + +config XRAY_PLUGIN_COMPRESS_UPX + bool "Compress executable files with UPX" + depends on !mips64 + default n +endef + +ifneq ($(CONFIG_XRAY_PLUGIN_COMPRESS_GOPROXY),) + export GO111MODULE=on + export GOPROXY=https://goproxy.io +endif + +define Package/xray-plugin + SECTION:=net + CATEGORY:=Network + SUBMENU:=Web Servers/Proxies + TITLE:=SIP003 plugin for Shadowsocks, based on Xray + URL:=https://github.com/teddysun/xray-plugin + DEPENDS:=$(GO_ARCH_DEPENDS) +ca-bundle +endef + +define Build/Compile + $(call GoPackage/Build/Compile) +ifneq ($(CONFIG_XRAY_PLUGIN_COMPRESS_UPX),) + $(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DIR)/xray-plugin +endif +endef + +define Package/xray-plugin/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(GO_PKG_BUILD_BIN_DIR)/xray-plugin $(1)/usr/bin/xray-plugin +endef + +$(eval $(call GoBinPackage,xray-plugin)) +$(eval $(call BuildPackage,xray-plugin))