diff --git a/Dockerfile.npc b/Dockerfile.npc index ae6715a..2ef275e 100755 --- a/Dockerfile.npc +++ b/Dockerfile.npc @@ -1,10 +1,10 @@ FROM golang as builder -WORKDIR /go/src/github.com/cnlh/nps +WORKDIR /go/src/ehang.io/nps COPY . . RUN go get -d -v ./... RUN CGO_ENABLED=0 go build -ldflags="-w -s -extldflags -static" ./cmd/npc/npc.go FROM scratch -COPY --from=builder /go/src/github.com/cnlh/nps/npc / +COPY --from=builder /go/src/ehang.io/nps/npc / VOLUME /conf ENTRYPOINT ["/npc"] diff --git a/Dockerfile.nps b/Dockerfile.nps index 698ced9..faf02ba 100755 --- a/Dockerfile.nps +++ b/Dockerfile.nps @@ -1,11 +1,11 @@ FROM golang as builder -WORKDIR /go/src/github.com/cnlh/nps +WORKDIR /go/src/ehang.io/nps COPY . . RUN go get -d -v ./... RUN CGO_ENABLED=0 go build -ldflags="-w -s -extldflags -static" ./cmd/nps/nps.go FROM scratch -COPY --from=builder /go/src/github.com/cnlh/nps/nps / -COPY --from=builder /go/src/github.com/cnlh/nps/web /web +COPY --from=builder /go/src/ehang.io/nps/nps / +COPY --from=builder /go/src/ehang.io/nps/web /web VOLUME /conf CMD ["/nps"] diff --git a/README.md b/README.md index b7d39d9..7f14877 100644 --- a/README.md +++ b/README.md @@ -1,78 +1,76 @@ -# nps -  +# NPS +  [](https://gitter.im/cnlh-nps/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) -[](https://travis-ci.org/cnlh/nps) - +[](https://travis-ci.org/ehang-io/nps) + -nps是一款轻量级、高性能、功能强大的**内网穿透**代理服务器。目前支持**tcp、udp流量转发**,可支持任何**tcp、udp**上层协议(访问内网网站、本地支付接口调试、ssh访问、远程桌面,内网dns解析等等……),此外还**支持内网http代理、内网socks5代理**、**p2p等**,并带有功能强大的web管理端。 +[README](https://github.com/ehang-io/nps/blob/master/README.md)|[中文文档](https://github.com/ehang-io/nps/blob/master/README_zh.md) + +NPS is a lightweight, high-performance, powerful **intranet penetration** proxy server, with a powerful web management terminal. -## 背景 - + -1. 做微信公众号开发、小程序开发等----> 域名代理模式 +## Feature -2. 想在外网通过ssh连接内网的机器,做云服务器到内网服务器端口的映射,----> tcp代理模式 +- Comprehensive protocol support, compatible with almost all commonly used protocols, such as tcp, udp, http(s), socks5, p2p, http proxy ... +- Full platform compatibility (linux, windows, macos, Qunhui, etc.), support installation as a system service simply. +- Comprehensive control, both client and server control are allowed. +- Https integration, support to convert backend proxy and web services to https, and support multiple certificates. +- Just simple configuration on web ui can complete most requirements. +- Complete information display, such as traffic, system information, real-time bandwidth, client version, etc. +- Powerful extension functions, everything is available (cache, compression, encryption, traffic limit, bandwidth limit, port reuse, etc.) +- Domain name resolution has functions such as custom headers, 404 page configuration, host modification, site protection, URL routing, and pan-resolution. +- Multi-user and user registration support on server. -3. 在非内网环境下使用内网dns,或者需要通过udp访问内网机器等----> udp代理模式 +**Didn't find the feature you want? It doesn't matter, click [Enter the document](https://ehang-io.github.io/nps/) to find it!** -4. 在外网使用HTTP代理访问内网站点----> http代理模式 +## Quick start -5. 搭建一个内网穿透ss,在外网如同使用内网vpn一样访问内网资源或者设备----> socks5代理模式 -## 特点 -- 协议支持全面,兼容几乎所有常用协议,例如tcp、udp、http(s)、socks5、p2p、http代理... -- 全平台兼容(linux、windows、macos、群辉等),支持一键安装为系统服务 -- 控制全面,同时支持服务端和客户端控制 -- https集成,支持将后端代理和web服务转成https,同时支持多证书 -- 操作简单,只需简单的配置即可在web ui上完成其余操作 -- 展示信息全面,流量、系统信息、即时带宽、客户端版本等 -- 扩展功能强大,该有的都有了(缓存、压缩、加密、流量限制、带宽限制、端口复用等等) -- 域名解析具备自定义header、404页面配置、host修改、站点保护、URL路由、泛解析等功能 -- 服务端支持多用户和用户注册功能 +### Installation -**没找到你想要的功能?不要紧,点击[进入文档](https://ehang-io.github.io/nps)查找吧** -## 快速开始 +> [releases](https://github.com/ehang-io/nps/releases) -### 安装 -> [releases](https://github.com/cnlh/nps/releases) +Download the corresponding system version, the server and client are separate. -下载对应的系统版本即可,服务端和客户端是单独的 +### Server start -### 服务端启动 -下载完服务器压缩包后,解压,然后进入解压后的文件夹 +After downloading the server compressed package, unzip it, and then enter the unzipped folder. -- 执行安装命令 +- execute installation command -对于linux|darwin ```sudo ./nps install``` +For linux、darwin ```sudo ./nps install``` -对于windows,管理员身份运行cmd,进入安装目录 ```nps.exe install``` +For windows, run cmd as administrator and enter the installation directory ```nps.exe install``` -- 启动 +- start up -对于linux|darwin ```sudo nps start``` +For linux、darwin ```sudo nps start``` -对于windows,管理员身份运行cmd,进入程序目录 ```nps.exe start``` +For windows, run cmd as administrator and enter the program directory ```nps.exe start``` -```安装后windows配置文件位于 C:\Program Files\nps,linux和darwin位于/etc/nps``` +```After installation, the windows configuration file is located at C:\Program Files\nps, linux or darwin is located at /etc/nps``` -**如果发现没有启动成功,可以查看日志(Windows日志文件位于当前运行目录下,linux和darwin位于/var/log/nps.log)** -- 访问服务端ip:web服务端口(默认为8080) -- 使用用户名和密码登陆(默认admin/123,正式使用一定要更改) -- 创建客户端 +**If you don't find it started successfully, you can check the log (Windows log files are located in the current running directory, linux and darwin are located in /var/log/nps.log).** -### 客户端连接 -- 点击web管理中客户端前的+号,复制启动命令 -- 执行启动命令,linux直接执行即可,windows将./npc换成npc.exe用cmd执行 +- Access server IP:web service port (default is 8080). +- Login with username and password (default is admin/123, must be modified when officially used). +- Create a client. -如果需要注册到系统服务可查看[注册到系统服务](https://ehang-io.github.io/nps/#/use?id=注册到系统服务) +### Client connection +- Click the + sign in front of the client in web management and copy the startup command. +- Execute the startup command, Linux can be executed directly, Windows will replace ./npc with npc.exe and execute it with cmd. -### 配置 -- 客户端连接后,在web中配置对应穿透服务即可 -- 更多高级用法见[完整文档](https://ehang-io.github.io/nps) -## 贡献 -- 如果遇到bug可以直接提交至dev分支 -- 使用遇到问题可以通过issues反馈 -- 项目处于开发阶段,还有很多待完善的地方,如果可以贡献代码,请提交 PR 至 dev 分支 -- 如果有新的功能特性反馈,可以通过issues或者qq群反馈 +If you need to register to the system service, you can check [Register to the system service](https://ehang-io.github.io/nps/#/use?id=注册到系统服务) + +### Configuration +- After the client connects, configure the corresponding penetration service in the web. +- For more advanced usage, see [Complete Documentation](https://ehang-io.github.io/nps/) + +## Contribution +- If you encounter a bug, you can submit it to the dev branch directly. +- If you encounter a problem, you can feedback through the issue. +- The project is under development, and there is still a lot of room for improvement. If you can contribute code, please submit PR to the dev branch. +- If there is feedback on new features, you can feedback via issues or qq group. diff --git a/README_zh.md b/README_zh.md new file mode 100644 index 0000000..008d469 --- /dev/null +++ b/README_zh.md @@ -0,0 +1,80 @@ + +# nps +  +[](https://gitter.im/cnlh-nps/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) +[](https://travis-ci.org/ehang-io/nps) + + +[README](https://github.com/ehang-io/nps/blob/master/README.md)|[中文文档](https://github.com/ehang-io/nps/blob/master/README_zh.md) + +nps是一款轻量级、高性能、功能强大的**内网穿透**代理服务器。目前支持**tcp、udp流量转发**,可支持任何**tcp、udp**上层协议(访问内网网站、本地支付接口调试、ssh访问、远程桌面,内网dns解析等等……),此外还**支持内网http代理、内网socks5代理**、**p2p等**,并带有功能强大的web管理端。 + + +## 背景 + + +1. 做微信公众号开发、小程序开发等----> 域名代理模式 + +2. 想在外网通过ssh连接内网的机器,做云服务器到内网服务器端口的映射,----> tcp代理模式 + +3. 在非内网环境下使用内网dns,或者需要通过udp访问内网机器等----> udp代理模式 + +4. 在外网使用HTTP代理访问内网站点----> http代理模式 + +5. 搭建一个内网穿透ss,在外网如同使用内网vpn一样访问内网资源或者设备----> socks5代理模式 +## 特点 +- 协议支持全面,兼容几乎所有常用协议,例如tcp、udp、http(s)、socks5、p2p、http代理... +- 全平台兼容(linux、windows、macos、群辉等),支持一键安装为系统服务 +- 控制全面,同时支持服务端和客户端控制 +- https集成,支持将后端代理和web服务转成https,同时支持多证书 +- 操作简单,只需简单的配置即可在web ui上完成其余操作 +- 展示信息全面,流量、系统信息、即时带宽、客户端版本等 +- 扩展功能强大,该有的都有了(缓存、压缩、加密、流量限制、带宽限制、端口复用等等) +- 域名解析具备自定义header、404页面配置、host修改、站点保护、URL路由、泛解析等功能 +- 服务端支持多用户和用户注册功能 + +**没找到你想要的功能?不要紧,点击[进入文档](https://ehang-io.github.io/nps)查找吧** +## 快速开始 + +### 安装 +> [releases](https://github.com/ehang-io/nps/releases) + +下载对应的系统版本即可,服务端和客户端是单独的 + +### 服务端启动 +下载完服务器压缩包后,解压,然后进入解压后的文件夹 + +- 执行安装命令 + +对于linux|darwin ```sudo ./nps install``` + +对于windows,管理员身份运行cmd,进入安装目录 ```nps.exe install``` + +- 启动 + +对于linux|darwin ```sudo nps start``` + +对于windows,管理员身份运行cmd,进入程序目录 ```nps.exe start``` + +```安装后windows配置文件位于 C:\Program Files\nps,linux和darwin位于/etc/nps``` + +**如果发现没有启动成功,可以查看日志(Windows日志文件位于当前运行目录下,linux和darwin位于/var/log/nps.log)** +- 访问服务端ip:web服务端口(默认为8080) +- 使用用户名和密码登陆(默认admin/123,正式使用一定要更改) +- 创建客户端 + +### 客户端连接 +- 点击web管理中客户端前的+号,复制启动命令 +- 执行启动命令,linux直接执行即可,windows将./npc换成npc.exe用cmd执行 + +如果需要注册到系统服务可查看[注册到系统服务](https://ehang-io.github.io/nps/#/use?id=注册到系统服务) + +### 配置 +- 客户端连接后,在web中配置对应穿透服务即可 +- 更多高级用法见[完整文档](https://ehang-io.github.io/nps/) + +## 贡献 +- 如果遇到bug可以直接提交至dev分支 +- 使用遇到问题可以通过issues反馈 +- 项目处于开发阶段,还有很多待完善的地方,如果可以贡献代码,请提交 PR 至 dev 分支 +- 如果有新的功能特性反馈,可以通过issues或者qq群反馈 diff --git a/bridge/bridge.go b/bridge/bridge.go index 7894b66..0827260 100755 --- a/bridge/bridge.go +++ b/bridge/bridge.go @@ -11,16 +11,16 @@ import ( "sync" "time" + "ehang.io/nps/lib/common" + "ehang.io/nps/lib/conn" + "ehang.io/nps/lib/crypt" + "ehang.io/nps/lib/file" + "ehang.io/nps/lib/mux" + "ehang.io/nps/lib/version" + "ehang.io/nps/server/connection" + "ehang.io/nps/server/tool" "github.com/astaxie/beego" "github.com/astaxie/beego/logs" - "github.com/cnlh/nps/lib/common" - "github.com/cnlh/nps/lib/conn" - "github.com/cnlh/nps/lib/crypt" - "github.com/cnlh/nps/lib/file" - "github.com/cnlh/nps/lib/mux" - "github.com/cnlh/nps/lib/version" - "github.com/cnlh/nps/server/connection" - "github.com/cnlh/nps/server/tool" ) type Client struct { diff --git a/build.android.sh b/build.android.sh index d9f8141..918a66a 100644 --- a/build.android.sh +++ b/build.android.sh @@ -14,16 +14,16 @@ git checkout v1.2.0 go install -v ./cmd/fyne #fyne package -os android fyne.io/fyne/cmd/hello echo "fyne install success" -mkdir -p /go/src/github.com/cnlh/nps -cp -R /app/* /go/src/github.com/cnlh/nps -cd /go/src/github.com/cnlh/nps +mkdir -p /go/src/ehang.io/nps +cp -R /app/* /go/src/ehang.io/nps +cd /go/src/ehang.io/nps #go get -u fyne.io/fyne fyne.io/fyne/cmd/fyne rm cmd/npc/sdk.go #go get -u ./... #go mod tidy #rm -rf /go/src/golang.org/x/mobile echo "tidy success" -cd /go/src/github.com/cnlh/nps +cd /go/src/ehang.io/nps go mod vendor cd vendor cp -R * /go/src diff --git a/build.sh b/build.sh index 5059486..6b236c4 100755 --- a/build.sh +++ b/build.sh @@ -1,5 +1,5 @@ #/bash/sh -export VERSION=0.25.4 +export VERSION=0.26.0 sudo apt-get install gcc-mingw-w64-i686 env GOOS=windows GOARCH=386 CGO_ENABLED=1 CC=i686-w64-mingw32-gcc go build -ldflags "-s -w -extldflags -static -extldflags -static" -buildmode=c-shared -o npc_sdk.dll cmd/npc/sdk.go diff --git a/client/client.go b/client/client.go index 7a6f1da..98c918d 100755 --- a/client/client.go +++ b/client/client.go @@ -11,11 +11,11 @@ import ( "github.com/astaxie/beego/logs" "github.com/xtaci/kcp-go" - "github.com/cnlh/nps/lib/common" - "github.com/cnlh/nps/lib/config" - "github.com/cnlh/nps/lib/conn" - "github.com/cnlh/nps/lib/crypt" - "github.com/cnlh/nps/lib/mux" + "ehang.io/nps/lib/common" + "ehang.io/nps/lib/config" + "ehang.io/nps/lib/conn" + "ehang.io/nps/lib/crypt" + "ehang.io/nps/lib/mux" ) type TRPClient struct { @@ -44,6 +44,7 @@ func NewRPClient(svraddr string, vKey string, bridgeConnType string, proxyUrl st var NowStatus int var CloseClient bool + //start func (s *TRPClient) Start() { CloseClient = false diff --git a/client/control.go b/client/control.go index d8b98f3..63bf7ea 100644 --- a/client/control.go +++ b/client/control.go @@ -19,12 +19,12 @@ import ( "strings" "time" + "ehang.io/nps/lib/common" + "ehang.io/nps/lib/config" + "ehang.io/nps/lib/conn" + "ehang.io/nps/lib/crypt" + "ehang.io/nps/lib/version" "github.com/astaxie/beego/logs" - "github.com/cnlh/nps/lib/common" - "github.com/cnlh/nps/lib/config" - "github.com/cnlh/nps/lib/conn" - "github.com/cnlh/nps/lib/crypt" - "github.com/cnlh/nps/lib/version" "github.com/xtaci/kcp-go" "golang.org/x/net/proxy" ) diff --git a/client/health.go b/client/health.go index e804cf9..2726c5b 100644 --- a/client/health.go +++ b/client/health.go @@ -7,10 +7,10 @@ import ( "strings" "time" + "ehang.io/nps/lib/conn" + "ehang.io/nps/lib/file" + "ehang.io/nps/lib/sheap" "github.com/astaxie/beego/logs" - "github.com/cnlh/nps/lib/conn" - "github.com/cnlh/nps/lib/file" - "github.com/cnlh/nps/lib/sheap" "github.com/pkg/errors" ) diff --git a/client/local.go b/client/local.go index 9c903f6..13dfb60 100644 --- a/client/local.go +++ b/client/local.go @@ -8,14 +8,14 @@ import ( "sync" "time" + "ehang.io/nps/lib/common" + "ehang.io/nps/lib/config" + "ehang.io/nps/lib/conn" + "ehang.io/nps/lib/crypt" + "ehang.io/nps/lib/file" + "ehang.io/nps/lib/mux" + "ehang.io/nps/server/proxy" "github.com/astaxie/beego/logs" - "github.com/cnlh/nps/lib/common" - "github.com/cnlh/nps/lib/config" - "github.com/cnlh/nps/lib/conn" - "github.com/cnlh/nps/lib/crypt" - "github.com/cnlh/nps/lib/file" - "github.com/cnlh/nps/lib/mux" - "github.com/cnlh/nps/server/proxy" "github.com/xtaci/kcp-go" ) diff --git a/client/register.go b/client/register.go index c03fb3c..dda4445 100644 --- a/client/register.go +++ b/client/register.go @@ -5,7 +5,7 @@ import ( "log" "os" - "github.com/cnlh/nps/lib/common" + "ehang.io/nps/lib/common" ) func RegisterLocalIp(server string, vKey string, tp string, proxyUrl string, hour int) { diff --git a/cmd/npc/npc.go b/cmd/npc/npc.go index da29a05..cb2efba 100644 --- a/cmd/npc/npc.go +++ b/cmd/npc/npc.go @@ -1,16 +1,16 @@ package main import ( + "ehang.io/nps/client" + "ehang.io/nps/lib/common" + "ehang.io/nps/lib/config" + "ehang.io/nps/lib/file" + "ehang.io/nps/lib/install" + "ehang.io/nps/lib/version" "flag" "fmt" "github.com/astaxie/beego/logs" "github.com/ccding/go-stun/stun" - "github.com/cnlh/nps/client" - "github.com/cnlh/nps/lib/common" - "github.com/cnlh/nps/lib/config" - "github.com/cnlh/nps/lib/file" - "github.com/cnlh/nps/lib/install" - "github.com/cnlh/nps/lib/version" "github.com/kardianos/service" "os" "runtime" @@ -114,7 +114,7 @@ func main() { } err := service.Control(s, os.Args[1]) if err != nil { - logs.Error("Valid actions: %q\n", service.ControlAction, err.Error()) + logs.Error("Valid actions: %q\n%s", service.ControlAction, err.Error()) } return } diff --git a/cmd/npc/sdk.go b/cmd/npc/sdk.go index b8cc38f..5d199a2 100644 --- a/cmd/npc/sdk.go +++ b/cmd/npc/sdk.go @@ -2,10 +2,10 @@ package main import ( "C" + "ehang.io/nps/client" + "ehang.io/nps/lib/common" + "ehang.io/nps/lib/version" "github.com/astaxie/beego/logs" - "github.com/cnlh/nps/client" - "github.com/cnlh/nps/lib/common" - "github.com/cnlh/nps/lib/version" ) var cl *client.TRPClient diff --git a/cmd/nps/nps.go b/cmd/nps/nps.go index 306da88..18ea025 100644 --- a/cmd/nps/nps.go +++ b/cmd/nps/nps.go @@ -1,26 +1,26 @@ package main import ( + "ehang.io/nps/lib/install" "flag" - "github.com/cnlh/nps/lib/install" "log" "os" "path/filepath" "runtime" "strings" + "ehang.io/nps/lib/common" + "ehang.io/nps/lib/crypt" + "ehang.io/nps/lib/daemon" + "ehang.io/nps/lib/file" + "ehang.io/nps/lib/version" + "ehang.io/nps/server" + "ehang.io/nps/server/connection" + "ehang.io/nps/server/tool" "github.com/astaxie/beego" "github.com/astaxie/beego/logs" - "github.com/cnlh/nps/lib/common" - "github.com/cnlh/nps/lib/crypt" - "github.com/cnlh/nps/lib/daemon" - "github.com/cnlh/nps/lib/file" - "github.com/cnlh/nps/lib/version" - "github.com/cnlh/nps/server" - "github.com/cnlh/nps/server/connection" - "github.com/cnlh/nps/server/tool" - "github.com/cnlh/nps/web/routers" + "ehang.io/nps/web/routers" "github.com/kardianos/service" ) @@ -94,13 +94,13 @@ func main() { } err = service.Control(s, os.Args[1]) if err != nil { - logs.Error("Valid actions: %q\n", service.ControlAction, err.Error()) + logs.Error("Valid actions: %q\n%s", service.ControlAction, err.Error()) } return case "start", "restart", "stop", "uninstall": err := service.Control(s, os.Args[1]) if err != nil { - logs.Error("Valid actions: %q\n", service.ControlAction, err.Error()) + logs.Error("Valid actions: %q\n%s", service.ControlAction, err.Error()) } return case "update": diff --git a/docs/README.md b/docs/README.md index 8f94b02..0ca334e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -7,7 +7,7 @@ nps是一款轻量级、高性能、功能强大的**内网穿透**代理服务 ## 背景 - + 1. 做微信公众号开发、小程序开发等----> 域名代理模式 diff --git a/docs/_coverpage.md b/docs/_coverpage.md index 68e0cc3..9bcc15a 100644 --- a/docs/_coverpage.md +++ b/docs/_coverpage.md @@ -1,6 +1,6 @@  -# NPS <small>0.25.4</small> +# NPS <small>0.26.0</small> > 一款轻量级、高性能、功能强大的内网穿透代理服务器 @@ -12,5 +12,5 @@ - 全平台兼容,一键注册为服务 -[GitHub](https://github.com/cnlh/nps/) +[GitHub](https://github.com/ehang-io/nps/) [开始使用](#nps) diff --git a/docs/api.md b/docs/api.md index 2b11650..0357838 100644 --- a/docs/api.md +++ b/docs/api.md @@ -43,4 +43,4 @@ POST /auth/getauthkey - **此文档近期可能更新较慢,建议自行抓包** 为方便第三方扩展,在web模式下可利用webAPI进行相关操作,详情见 -[webAPI文档](https://github.com/cnlh/nps/wiki/webAPI%E6%96%87%E6%A1%A3) +[webAPI文档](https://github.com/ehang-io/nps/wiki/webAPI%E6%96%87%E6%A1%A3) diff --git a/docs/donate.md b/docs/donate.md index 551e1eb..5331e91 100644 --- a/docs/donate.md +++ b/docs/donate.md @@ -2,6 +2,6 @@ 如果您觉得nps对你有帮助,欢迎给予我们一定捐助,也是帮助nps更好的发展。 ## 支付宝 - + ## 微信 - + diff --git a/docs/index.html b/docs/index.html index caaab9b..4be6ab5 100644 --- a/docs/index.html +++ b/docs/index.html @@ -29,7 +29,7 @@ hideOtherSidebarContent: true, // whether or not to hide other sidebar content }, plugins: [ - EditOnGithubPlugin.create("https://github.com/cnlh/nps/tree/master/docs/", "", "在github上编辑"), + EditOnGithubPlugin.create("https://github.com/ehang-io/nps/tree/master/docs/", "", "在github上编辑"), ] } diff --git a/docs/install.md b/docs/install.md index 09313e6..a1d46c6 100644 --- a/docs/install.md +++ b/docs/install.md @@ -1,13 +1,12 @@ # 安装 ## 安装包安装 - [releases](https://github.com/cnlh/nps/releases) + [releases](https://github.com/ehang-io/nps/releases) 下载对应的系统版本即可,服务端和客户端是单独的 ## 源码安装 - 安装源码 -```go get -u github.com/cnlh/nps... -``` +```go get -u ehang.io/nps...``` - 编译 服务端```go build cmd/nps/nps.go``` diff --git a/docs/introduction.md b/docs/introduction.md index 0656246..dff49e1 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -1,4 +1,4 @@ - + # 介绍 可在网页上配置和管理各个tcp、udp隧道、内网站点代理,http、https解析等,功能强大,操作方便。 diff --git a/docs/use.md b/docs/use.md index 5f775ab..481e853 100644 --- a/docs/use.md +++ b/docs/use.md @@ -44,7 +44,7 @@ npc-update.exe update ./npc -config=npc配置文件路径 ``` ## 配置文件说明 -[示例配置文件](https://github.com/cnlh/nps/tree/master/conf/npc.conf) +[示例配置文件](https://github.com/ehang-io/nps/tree/master/conf/npc.conf) #### 全局配置 ```ini [common] diff --git a/docs/webapi.md b/docs/webapi.md new file mode 100644 index 0000000..836358b --- /dev/null +++ b/docs/webapi.md @@ -0,0 +1,233 @@ +获取客户端列表 + +``` +POST /client/list/ +``` + + +| 参数 | 含义 | +| --- | --- | +| search | 搜索 | +| order | 排序asc 正序 desc倒序 | +| offset | 分页(第几页) | +| limit | 条数(分页显示的条数) | + +*** +获取单个客户端 + +``` +POST /client/getclient/ +``` + + +| 参数 | 含义 | +| --- | --- | +| id | 客户端id | + +*** +添加客户端 + +``` +POST /client/add/ +``` + +| 参数 | 含义 | +| --- | --- | +| remark | 备注 | +| u | basic权限认证用户名 | +| p | basic权限认证密码 | +| limit | 条数(分页显示的条数) | +| vkey | 客户端验证密钥 | +| config\_conn\_allow | 是否允许客户端以配置文件模式连接 1允许 0不允许 | +| compress | 压缩1允许 0不允许 | +| crypt | 是否加密(1或者0)1允许 0不允许 | +| rate\_limit | 带宽限制 单位KB/S 空则为不限制 | +| flow\_limit | 流量限制 单位M 空则为不限制 | +| max\_conn | 客户端最大连接数量 空则为不限制 | +| max\_tunnel | 客户端最大隧道数量 空则为不限制 | + +*** +修改客户端(25.4版本有问题暂时不能用) + +``` +POST /client/edit/ +``` + +| 参数 | 含义 | +| --- | --- | +| remark | 备注 | +| u | basic权限认证用户名 | +| p | basic权限认证密码 | +| limit | 条数(分页显示的条数) | +| vkey | 客户端验证密钥 | +| config\_conn\_allow | 是否允许客户端以配置文件模式连接 1允许 0不允许 | +| compress | 压缩1允许 0不允许 | +| crypt | 是否加密(1或者0)1允许 0不允许 | +| rate\_limit | 带宽限制 单位KB/S 空则为不限制 | +| flow\_limit | 流量限制 单位M 空则为不限制 | +| max\_conn | 客户端最大连接数量 空则为不限制 | +| max\_tunnel | 客户端最大隧道数量 空则为不限制 | +| id | 要修改的客户端id | + +*** +删除客户端 + +``` +POST /client/del/ +``` + +| 参数 | 含义 | +| --- | --- | +| id | 要删除的客户端id | + +*** +获取域名解析列表 + +``` +POST /index/hostlist/ +``` + +| 参数 | 含义 | +| --- | --- | +| search | 搜索(可以搜域名/备注什么的) | +| offset | 分页(第几页) | +| limit | 条数(分页显示的条数) | + +*** +添加域名解析 + +``` +POST /index/addhost/ +``` + + +| 参数 | 含义 | +| --- | --- | +| remark | 备注 | +| host | 域名 | +| scheme | 协议类型(三种 all http https) | +| location | url路由 空则为不限制 | +| client\_id | 客户端id | +| target | 内网目标(ip:端口) | +| header | request header 请求头 | +| hostchange | request host 请求主机 | + +*** +修改域名解析 + +``` +POST /index/edithost/ +``` + +| 参数 | 含义 | +| --- | --- | +| remark | 备注 | +| host | 域名 | +| scheme | 协议类型(三种 all http https) | +| location | url路由 空则为不限制 | +| client\_id | 客户端id | +| target | 内网目标(ip:端口) | +| header | request header 请求头 | +| hostchange | request host 请求主机 | +| id | 需要修改的域名解析id | + +*** +删除域名解析 + +``` +POST /index/delhost/ +``` + +| 参数 | 含义 | +| --- | --- | +| id | 需要删除的域名解析id | + +*** +获取单条隧道信息 + +``` +POST /index/getonetunnel/ +``` + +| 参数 | 含义 | +| --- | --- | +| id | 隧道的id | + +*** +获取隧道列表 + +``` +POST /index/gettunnel/ +``` + +| 参数 | 含义 | +| --- | --- | +| client\_id | 穿透隧道的客户端id | +| type | 类型tcp udp httpProx socks5 secret p2p | +| search | 搜索 | +| offset | 分页(第几页) | +| limit | 条数(分页显示的条数) | + +*** +添加隧道 + +``` +POST /index/add/ +``` + +| 参数 | 含义 | +| --- | --- | +| type | 类型tcp udp httpProx socks5 secret p2p | +| remark | 备注 | +| port | 服务端端口 | +| target | 目标(ip:端口) | +| client\_id | 客户端id | + +*** +修改隧道 + +``` +POST /index/edit/ +``` + +| 参数 | 含义 | +| --- | --- | +| type | 类型tcp udp httpProx socks5 secret p2p | +| remark | 备注 | +| port | 服务端端口 | +| target | 目标(ip:端口) | +| client\_id | 客户端id | +| id | 隧道id | + +*** +删除隧道 + +``` +POST /index/del/ +``` + +| 参数 | 含义 | +| --- | --- | +| id | 隧道id | + +*** +隧道停止工作 + +``` +POST /index/stop/ +``` + +| 参数 | 含义 | +| --- | --- | +| id | 隧道id | + +*** +隧道开始工作 + +``` +POST /index/start/ +``` + +| 参数 | 含义 | +| --- | --- | +| id | 隧道id | diff --git a/go.mod b/go.mod index 141d73c..cad2acc 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/cnlh/nps +module ehang.io/nps go 1.13 diff --git a/gui/npc/AndroidManifest.xml b/gui/npc/AndroidManifest.xml index 901a508..6543fbd 100755 --- a/gui/npc/AndroidManifest.xml +++ b/gui/npc/AndroidManifest.xml @@ -2,7 +2,7 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" - android:versionName="0.25.4" + android:versionName="0.26.0" package="org.nps.client" platformBuildVersionCode="15" platformBuildVersionName="4.0.4-1406430"> diff --git a/gui/npc/npc.go b/gui/npc/npc.go index 0c55ed4..516a87a 100644 --- a/gui/npc/npc.go +++ b/gui/npc/npc.go @@ -1,16 +1,16 @@ package main import ( + "ehang.io/nps/client" + "ehang.io/nps/lib/common" + "ehang.io/nps/lib/daemon" + "ehang.io/nps/lib/version" "fmt" "fyne.io/fyne" "fyne.io/fyne/app" "fyne.io/fyne/layout" "fyne.io/fyne/widget" "github.com/astaxie/beego/logs" - "github.com/cnlh/nps/client" - "github.com/cnlh/nps/lib/common" - "github.com/cnlh/nps/lib/daemon" - "github.com/cnlh/nps/lib/version" "io/ioutil" "os" "path" diff --git a/image/work_flow.svg b/image/work_flow.svg new file mode 100644 index 0000000..5b3794b --- /dev/null +++ b/image/work_flow.svg @@ -0,0 +1,821 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<!-- 由 Microsoft Visio, SVG Export 生成 工作图.svg Page-1 --> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" + xmlns:v="http://schemas.microsoft.com/visio/2003/SVGExtensions/" width="11.6929in" height="8.26772in" + viewBox="0 0 841.89 595.276" xml:space="preserve" color-interpolation-filters="sRGB" class="st17"> + <v:documentProperties v:langID="2052" v:metric="true" v:viewMarkup="false"> + <v:userDefs> + <v:ud v:nameU="msvNoAutoConnect" v:prompt="" v:val="VT0(0):26"/> + </v:userDefs> + </v:documentProperties> + + <style type="text/css"> + <![CDATA[ + .st1 {fill:#5b9bd5;stroke:#ffffff;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.5} + .st2 {stroke:#ffffff;stroke-linecap:butt;stroke-width:0.5} + .st3 {fill:#1e4a73;font-family:Calibri;font-size:1.5em} + .st4 {fill:#aad288;stroke:#ffffff;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.5} + .st5 {fill:#ffffff} + .st6 {font-size:1em} + .st7 {fill:#5b9bd5} + .st8 {stroke:#ffffff;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.5} + .st9 {fill:#a5a5a5} + .st10 {marker-end:url(#mrkr4-135);marker-start:url(#mrkr4-133);stroke:#5592c9;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5} + .st11 {fill:#5592c9;fill-opacity:1;stroke:#5592c9;stroke-opacity:1;stroke-width:0.37313432835821} + .st12 {fill:#ffffff;stroke:none;stroke-linecap:butt;stroke-width:7.2} + .st13 {fill:#41729d;font-family:Calibri;font-size:1.5em} + .st14 {fill:none;stroke:#42829e;stroke-dasharray:45,27;stroke-linecap:round;stroke-linejoin:round;stroke-width:3} + .st15 {fill:none;stroke:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.5} + .st16 {fill:#5b9bd5;font-family:Calibri;font-size:1.99999em} + .st17 {fill:none;fill-rule:evenodd;font-size:12px;overflow:visible;stroke-linecap:square;stroke-miterlimit:3} + ]]> + </style> + + <defs id="Markers"> + <g id="lend4"> + <path d="M 2 1 L 0 0 L 2 -1 L 2 1 " style="stroke:none"/> + </g> + <marker id="mrkr4-133" class="st11" v:arrowType="4" v:arrowSize="2" v:setback="5.12" refX="5.12" orient="auto" + markerUnits="strokeWidth" overflow="visible"> + <use xlink:href="#lend4" transform="scale(2.68) "/> + </marker> + <marker id="mrkr4-135" class="st11" v:arrowType="4" v:arrowSize="2" v:setback="5.36" refX="-5.36" orient="auto" + markerUnits="strokeWidth" overflow="visible"> + <use xlink:href="#lend4" transform="scale(-2.68,-2.68) "/> + </marker> + </defs> + <g v:mID="0" v:index="1" v:groupContext="foregroundPage"> + <v:userDefs> + <v:ud v:nameU="msvThemeOrder" v:val="VT0(0):26"/> + </v:userDefs> + <title>页-1</title> + <v:pageProperties v:drawingScale="0.0393701" v:pageScale="0.0393701" v:drawingUnits="24" v:shadowOffsetX="8.50394" + v:shadowOffsetY="-8.50394"/> + <v:layer v:name="连接线" v:index="0"/> + <g id="group1-1" transform="translate(418.11,-311.811)" v:mID="1" v:groupContext="group"> + <v:custProps> + <v:cp v:nameU="AssetNumber" v:lbl="资产号" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="SerialNumber" v:lbl="序列号" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Location" v:lbl="位置" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Building" v:lbl="构建" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Room" v:lbl="空间" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" v:ask="false" + v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Manufacturer" v:lbl="制造商" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="ProductNumber" v:lbl="产品编号" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="PartNumber" v:lbl="部件号" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="ProductDescription" v:lbl="产品说明" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" + v:invis="false" v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="ShapeClass" v:lbl="ShapeClass" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="2052" v:cal="0" v:val="VT4(设备)"/> + <v:cp v:nameU="ShapeType" v:lbl="ShapeType" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="2052" v:cal="0" v:val="VT4(设备)"/> + <v:cp v:nameU="SubShapeType" v:lbl="SubShapeType" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="2052" v:cal="0" v:val="VT4(防火墙)"/> + </v:custProps> + <v:userDefs> + <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/> + <v:ud v:nameU="ShapeClass" v:prompt="" v:val="VT0(5):26"/> + <v:ud v:nameU="SolSH" v:prompt="" v:val="VT15({BF0433D9-CD73-4EB5-8390-8653BE590246}):41"/> + <v:ud v:nameU="visLegendShape" v:prompt="" v:val="VT0(2):26"/> + </v:userDefs> + <title>防火墙</title> + <desc>NAT</desc> + <g id="shape2-2" v:mID="2" v:groupContext="shape" transform="translate(0.545123,-7.63784)"> + <title>工作表.2</title> + <rect x="0" y="539.685" width="69.7759" height="55.5905" class="st1"/> + </g> + <g id="shape3-4" v:mID="3" v:groupContext="shape" transform="translate(0.795123,-7.88784)"> + <title>工作表.3</title> + <v:userDefs> + <v:ud v:nameU="SurroundingRegionColor" v:prompt="" v:val="VT5(1)"/> + <v:ud v:nameU="SurroundingRegionColor" v:prompt="" v:val="VT5(#5b9bd5)"/> + </v:userDefs> + <path d="M0 587.41 L69.28 587.41" class="st2"/> + <path d="M0 579.54 L69.28 579.54" class="st2"/> + <path d="M0 571.67 L69.28 571.67" class="st2"/> + <path d="M0 563.8 L69.28 563.8" class="st2"/> + <path d="M0 555.93 L69.28 555.93" class="st2"/> + <path d="M0 548.06 L69.28 548.06" class="st2"/> + <path d="M17.32 595.28 L17.32 587.41" class="st2"/> + <path d="M34.64 595.28 L34.64 587.41" class="st2"/> + <path d="M51.96 595.28 L51.96 587.41" class="st2"/> + <path d="M8.66 587.41 L8.66 579.54" class="st2"/> + <path d="M25.98 587.41 L25.98 579.54" class="st2"/> + <path d="M43.3 587.41 L43.3 579.54" class="st2"/> + <path d="M60.62 587.41 L60.62 579.54" class="st2"/> + <path d="M17.32 579.54 L17.32 571.67" class="st2"/> + <path d="M34.64 579.54 L34.64 571.67" class="st2"/> + <path d="M51.96 579.54 L51.96 571.67" class="st2"/> + <path d="M8.66 571.67 L8.66 563.8" class="st2"/> + <path d="M25.98 571.67 L25.98 563.8" class="st2"/> + <path d="M43.3 571.67 L43.3 563.8" class="st2"/> + <path d="M60.62 571.67 L60.62 563.8" class="st2"/> + <path d="M17.32 563.8 L17.32 555.93" class="st2"/> + <path d="M34.64 563.8 L34.64 555.93" class="st2"/> + <path d="M51.96 563.8 L51.96 555.93" class="st2"/> + <path d="M8.66 555.93 L8.66 548.06" class="st2"/> + <path d="M25.98 555.93 L25.98 548.06" class="st2"/> + <path d="M43.3 555.93 L43.3 548.06" class="st2"/> + <path d="M60.62 555.93 L60.62 548.06" class="st2"/> + <path d="M17.32 548.06 L17.32 540.19" class="st2"/> + <path d="M34.64 548.06 L34.64 540.19" class="st2"/> + <path d="M51.96 548.06 L51.96 540.19" class="st2"/> + </g> + <g id="shape1-36" v:mID="1" v:groupContext="groupContent"> + <v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/> + <v:textRect cx="35.4331" cy="610.077" width="42.88" height="29.6036"/> + <text x="20.03" y="615.48" class="st3" v:langID="2052"><v:paragraph v:horizAlign="1"/><v:tabList/>NAT</text> </g> + </g> + <g id="group4-38" transform="translate(701.575,-311.811)" v:mID="4" v:groupContext="group"> + <v:custProps> + <v:cp v:nameU="AssetNumber" v:lbl="资产号" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="SerialNumber" v:lbl="序列号" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Location" v:lbl="位置" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Building" v:lbl="构建" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Room" v:lbl="空间" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" v:ask="false" + v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Manufacturer" v:lbl="制造商" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="ProductNumber" v:lbl="产品编号" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="PartNumber" v:lbl="部件号" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="ProductDescription" v:lbl="产品说明" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" + v:invis="false" v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="NetworkName" v:lbl="网络名称" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="IPAddress" v:lbl="IP 地址" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="SubnetMask" v:lbl="子网掩码" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="AdminInterface" v:lbl="管理接口" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="NumberofPorts" v:lbl="端口数目" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="CommunityString" v:lbl="团体字符串" v:prompt="" v:type="0" v:format="" v:sortKey="Network" + v:invis="false" v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="NetworkDescription" v:lbl="网络说明" v:prompt="" v:type="0" v:format="" v:sortKey="Network" + v:invis="false" v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="MACAddress" v:lbl="MAC 地址" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="CPU" v:lbl="CPU" v:prompt="" v:type="0" v:format="" v:sortKey="Workstation" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Memory" v:lbl="内存" v:prompt="" v:type="0" v:format="" v:sortKey="Workstation" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="OperatingSystem" v:lbl="操作系统" v:prompt="" v:type="0" v:format="" v:sortKey="Workstation" + v:invis="false" v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="HardDriveSize" v:lbl="硬盘容量" v:prompt="" v:type="0" v:format="" v:sortKey="Workstation" + v:invis="false" v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Department" v:lbl="部门" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="false" v:ask="false" + v:langID="2052" v:cal="0"/> + <v:cp v:nameU="ShapeClass" v:lbl="ShapeClass" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="2052" v:cal="0" v:val="VT4(设备)"/> + <v:cp v:nameU="ShapeType" v:lbl="ShapeType" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="2052" v:cal="0" v:val="VT4(服务器)"/> + <v:cp v:nameU="BelongsTo" v:lbl="属于" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" v:ask="false" + v:langID="2052" v:cal="0"/> + </v:custProps> + <v:userDefs> + <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/> + <v:ud v:nameU="ShapeClass" v:prompt="" v:val="VT0(5):26"/> + <v:ud v:nameU="SolSH" v:prompt="" v:val="VT15({BF0433D9-CD73-4EB5-8390-8653BE590246}):41"/> + <v:ud v:nameU="visLegendShape" v:prompt="" v:val="VT0(2):26"/> + </v:userDefs> + <title>服务器</title> + <desc>Application2 10.0.0.4:PORT</desc> + <g id="shape5-39" v:mID="5" v:groupContext="shape" transform="translate(12.8133,0)"> + <title>工作表.5</title> + <rect x="0" y="524.409" width="45.2395" height="70.8661" class="st1"/> + </g> + <g id="shape6-41" v:mID="6" v:groupContext="shape" transform="translate(46.625,-30.2513)"> + <title>工作表.6</title> + <ellipse cx="2.73472" cy="592.541" rx="2.73472" ry="2.73472" class="st4"/> + </g> + <g id="shape7-43" v:mID="7" v:groupContext="shape" transform="translate(30.0295,-11.6164)"> + <title>工作表.7</title> + <v:userDefs> + <v:ud v:nameU="SurroundingRegionColor" v:prompt="" v:val="VT5(1)"/> + <v:ud v:nameU="SurroundingRegionColor" v:prompt="" v:val="VT5(#5b9bd5)"/> + </v:userDefs> + <path d="M-0 595.28 L22.06 595.28 L22.06 593.5 L-0 593.5 L-0 595.28 ZM-0 589.9 L22.06 589.9 L22.06 588.13 L-0 588.13 + L-0 589.9 ZM-0 584.53 L22.06 584.53 L22.06 582.76 L-0 582.76 L-0 584.53 Z" class="st5"/> + </g> + <g id="shape4-46" v:mID="4" v:groupContext="groupContent"> + <v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/> + <v:textRect cx="35.4331" cy="620.877" width="115.9" height="51.2036"/> + <text x="-10.6" y="615.48" class="st3" v:langID="2052"><v:paragraph v:horizAlign="1"/><v:tabList/>Application2<v:newlineChar/><tspan + x="-16.48" dy="1.2em" class="st6">10.0.0.4:PORT</tspan></text> </g> + </g> + <g id="group8-49" transform="translate(701.575,-496.063)" v:mID="8" v:groupContext="group"> + <v:custProps> + <v:cp v:nameU="AssetNumber" v:lbl="资产号" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="SerialNumber" v:lbl="序列号" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Location" v:lbl="位置" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Building" v:lbl="构建" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Room" v:lbl="空间" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" v:ask="false" + v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Manufacturer" v:lbl="制造商" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="ProductNumber" v:lbl="产品编号" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="PartNumber" v:lbl="部件号" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="ProductDescription" v:lbl="产品说明" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" + v:invis="false" v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="NetworkName" v:lbl="网络名称" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="IPAddress" v:lbl="IP 地址" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="SubnetMask" v:lbl="子网掩码" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="AdminInterface" v:lbl="管理接口" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="NumberofPorts" v:lbl="端口数目" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="CommunityString" v:lbl="团体字符串" v:prompt="" v:type="0" v:format="" v:sortKey="Network" + v:invis="false" v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="NetworkDescription" v:lbl="网络说明" v:prompt="" v:type="0" v:format="" v:sortKey="Network" + v:invis="false" v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="MACAddress" v:lbl="MAC 地址" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="CPU" v:lbl="CPU" v:prompt="" v:type="0" v:format="" v:sortKey="Workstation" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Memory" v:lbl="内存" v:prompt="" v:type="0" v:format="" v:sortKey="Workstation" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="OperatingSystem" v:lbl="操作系统" v:prompt="" v:type="0" v:format="" v:sortKey="Workstation" + v:invis="false" v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="HardDriveSize" v:lbl="硬盘容量" v:prompt="" v:type="0" v:format="" v:sortKey="Workstation" + v:invis="false" v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Department" v:lbl="部门" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="false" v:ask="false" + v:langID="2052" v:cal="0"/> + <v:cp v:nameU="ShapeClass" v:lbl="ShapeClass" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="2052" v:cal="0" v:val="VT4(设备)"/> + <v:cp v:nameU="ShapeType" v:lbl="ShapeType" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="2052" v:cal="0" v:val="VT4(服务器)"/> + <v:cp v:nameU="BelongsTo" v:lbl="属于" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" v:ask="false" + v:langID="2052" v:cal="0"/> + </v:custProps> + <v:userDefs> + <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/> + <v:ud v:nameU="ShapeClass" v:prompt="" v:val="VT0(5):26"/> + <v:ud v:nameU="SolSH" v:prompt="" v:val="VT15({BF0433D9-CD73-4EB5-8390-8653BE590246}):41"/> + <v:ud v:nameU="visLegendShape" v:prompt="" v:val="VT0(2):26"/> + </v:userDefs> + <title>服务器.8</title> + <desc>Application1 10.0.0.3:PORT</desc> + <g id="shape9-50" v:mID="9" v:groupContext="shape" transform="translate(12.8133,0)"> + <title>工作表.9</title> + <rect x="0" y="524.409" width="45.2395" height="70.8661" class="st1"/> + </g> + <g id="shape10-52" v:mID="10" v:groupContext="shape" transform="translate(46.625,-30.2513)"> + <title>工作表.10</title> + <ellipse cx="2.73472" cy="592.541" rx="2.73472" ry="2.73472" class="st4"/> + </g> + <g id="shape11-54" v:mID="11" v:groupContext="shape" transform="translate(30.0295,-11.6164)"> + <title>工作表.11</title> + <v:userDefs> + <v:ud v:nameU="SurroundingRegionColor" v:prompt="" v:val="VT5(1)"/> + <v:ud v:nameU="SurroundingRegionColor" v:prompt="" v:val="VT5(#5b9bd5)"/> + </v:userDefs> + <path d="M-0 595.28 L22.06 595.28 L22.06 593.5 L-0 593.5 L-0 595.28 ZM-0 589.9 L22.06 589.9 L22.06 588.13 L-0 588.13 + L-0 589.9 ZM-0 584.53 L22.06 584.53 L22.06 582.76 L-0 582.76 L-0 584.53 Z" class="st5"/> + </g> + <g id="shape8-57" v:mID="8" v:groupContext="groupContent"> + <v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/> + <v:textRect cx="35.4331" cy="620.877" width="115.9" height="51.2036"/> + <text x="-10.6" y="615.48" class="st3" v:langID="2052"><v:paragraph v:horizAlign="1"/><v:tabList/>Application1<v:newlineChar/><tspan + x="-16.48" dy="1.2em" class="st6">10.0.0.3:PORT</tspan></text> </g> + </g> + <g id="group12-60" transform="translate(701.575,-127.559)" v:mID="12" v:groupContext="group"> + <v:custProps> + <v:cp v:nameU="AssetNumber" v:lbl="资产号" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="SerialNumber" v:lbl="序列号" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Location" v:lbl="位置" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Building" v:lbl="构建" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Room" v:lbl="空间" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" v:ask="false" + v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Manufacturer" v:lbl="制造商" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="ProductNumber" v:lbl="产品编号" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="PartNumber" v:lbl="部件号" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="ProductDescription" v:lbl="产品说明" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" + v:invis="false" v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="NetworkName" v:lbl="网络名称" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="IPAddress" v:lbl="IP 地址" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="SubnetMask" v:lbl="子网掩码" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="AdminInterface" v:lbl="管理接口" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="NumberofPorts" v:lbl="端口数目" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="CommunityString" v:lbl="团体字符串" v:prompt="" v:type="0" v:format="" v:sortKey="Network" + v:invis="false" v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="NetworkDescription" v:lbl="网络说明" v:prompt="" v:type="0" v:format="" v:sortKey="Network" + v:invis="false" v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="MACAddress" v:lbl="MAC 地址" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="CPU" v:lbl="CPU" v:prompt="" v:type="0" v:format="" v:sortKey="Workstation" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Memory" v:lbl="内存" v:prompt="" v:type="0" v:format="" v:sortKey="Workstation" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="OperatingSystem" v:lbl="操作系统" v:prompt="" v:type="0" v:format="" v:sortKey="Workstation" + v:invis="false" v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="HardDriveSize" v:lbl="硬盘容量" v:prompt="" v:type="0" v:format="" v:sortKey="Workstation" + v:invis="false" v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Department" v:lbl="部门" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="false" v:ask="false" + v:langID="2052" v:cal="0"/> + <v:cp v:nameU="ShapeClass" v:lbl="ShapeClass" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="2052" v:cal="0" v:val="VT4(设备)"/> + <v:cp v:nameU="ShapeType" v:lbl="ShapeType" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="2052" v:cal="0" v:val="VT4(服务器)"/> + <v:cp v:nameU="BelongsTo" v:lbl="属于" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" v:ask="false" + v:langID="2052" v:cal="0"/> + </v:custProps> + <v:userDefs> + <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/> + <v:ud v:nameU="ShapeClass" v:prompt="" v:val="VT0(5):26"/> + <v:ud v:nameU="SolSH" v:prompt="" v:val="VT15({BF0433D9-CD73-4EB5-8390-8653BE590246}):41"/> + <v:ud v:nameU="visLegendShape" v:prompt="" v:val="VT0(2):26"/> + </v:userDefs> + <title>服务器.12</title> + <desc>Application3 10.0.0.5:PORT</desc> + <g id="shape13-61" v:mID="13" v:groupContext="shape" transform="translate(12.8133,0)"> + <title>工作表.13</title> + <rect x="0" y="524.409" width="45.2395" height="70.8661" class="st1"/> + </g> + <g id="shape14-63" v:mID="14" v:groupContext="shape" transform="translate(46.625,-30.2513)"> + <title>工作表.14</title> + <ellipse cx="2.73472" cy="592.541" rx="2.73472" ry="2.73472" class="st4"/> + </g> + <g id="shape15-65" v:mID="15" v:groupContext="shape" transform="translate(30.0295,-11.6164)"> + <title>工作表.15</title> + <v:userDefs> + <v:ud v:nameU="SurroundingRegionColor" v:prompt="" v:val="VT5(1)"/> + <v:ud v:nameU="SurroundingRegionColor" v:prompt="" v:val="VT5(#5b9bd5)"/> + </v:userDefs> + <path d="M-0 595.28 L22.06 595.28 L22.06 593.5 L-0 593.5 L-0 595.28 ZM-0 589.9 L22.06 589.9 L22.06 588.13 L-0 588.13 + L-0 589.9 ZM-0 584.53 L22.06 584.53 L22.06 582.76 L-0 582.76 L-0 584.53 Z" class="st5"/> + </g> + <g id="shape12-68" v:mID="12" v:groupContext="groupContent"> + <v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/> + <v:textRect cx="35.4331" cy="620.877" width="115.9" height="51.2036"/> + <text x="-10.6" y="615.48" class="st3" v:langID="2052"><v:paragraph v:horizAlign="1"/><v:tabList/>Application3<v:newlineChar/><tspan + x="-16.48" dy="1.2em" class="st6">10.0.0.5:PORT</tspan></text> </g> + </g> + <g id="group16-71" transform="translate(538.583,-311.811)" v:mID="16" v:groupContext="group"> + <v:custProps> + <v:cp v:nameU="AssetNumber" v:lbl="资产号" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="SerialNumber" v:lbl="序列号" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Location" v:lbl="位置" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Building" v:lbl="建筑物" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Room" v:lbl="空间" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" v:ask="false" + v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Manufacturer" v:lbl="制造商" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="ProductNumber" v:lbl="产品编号" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="PartNumber" v:lbl="部件号" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="ProductDescription" v:lbl="产品说明" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" + v:invis="false" v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="NetworkName" v:lbl="网络名称" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="IPAddress" v:lbl="IP 地址" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="SubnetMask" v:lbl="子网掩码" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="AdminInterface" v:lbl="管理接口" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="NumberofPorts" v:lbl="端口数目" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="CommunityString" v:lbl="团体字符串" v:prompt="" v:type="0" v:format="" v:sortKey="Network" + v:invis="false" v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="NetworkDescription" v:lbl="网络说明" v:prompt="" v:type="0" v:format="" v:sortKey="Network" + v:invis="false" v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="MACAddress" v:lbl="MAC 地址" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="ShapeClass" v:lbl="ShapeClass" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="2052" v:cal="0" v:val="VT4(设备)"/> + <v:cp v:nameU="ShapeType" v:lbl="ShapeType" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="2052" v:cal="0" v:val="VT4(计算机)"/> + <v:cp v:nameU="SubShapeType" v:lbl="SubShapeType" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="2052" v:cal="0" v:val="VT4(大型机)"/> + </v:custProps> + <v:userDefs> + <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/> + <v:ud v:nameU="ShapeClass" v:prompt="" v:val="VT0(5):26"/> + <v:ud v:nameU="SolSH" v:prompt="" v:val="VT15({BF0433D9-CD73-4EB5-8390-8653BE590246}):41"/> + <v:ud v:nameU="visLegendShape" v:prompt="" v:val="VT0(2):26"/> + </v:userDefs> + <title>主机</title> + <desc>NPC Client 10.0.0.2 Dial To: ->10.0.0.3:PORT ->10.0.0.4:PORT ...</desc> + <g id="shape17-72" v:mID="17" v:groupContext="shape" transform="translate(5.68158,0)"> + <title>工作表.17</title> + <path d="M0 595.28 L59.5 595.28 L59.5 524.41 L0 524.41 L0 595.28 Z" class="st7"/> + <path d="M0 595.28 L59.5 595.28 L59.5 524.41 L0 524.41 L0 595.28" class="st8"/> + <path d="M29.75 595.28 L29.75 524.41" class="st8"/> + </g> + <g id="shape18-76" v:mID="18" v:groupContext="shape" transform="translate(11.5726,-5.14536)"> + <title>工作表.18</title> + <v:userDefs> + <v:ud v:nameU="SurroundingRegionColor" v:prompt="" v:val="VT5(1)"/> + <v:ud v:nameU="SurroundingRegionColor" v:prompt="" v:val="VT5(#5b9bd5)"/> + </v:userDefs> + <path d="M36.09 551.42 L49.23 551.42 L49.23 536.38 L36.09 536.38 L36.09 551.42 ZM14.89 542.47 L16.68 542.47 L16.68 + 536.06 L14.89 536.06 L14.89 542.47 ZM14.89 551.71 L16.68 551.71 L16.68 545.3 L14.89 545.3 L14.89 551.71 + ZM10.63 542.47 L12.43 542.47 L12.43 536.06 L10.63 536.06 L10.63 542.47 ZM10.63 551.71 L12.43 551.71 + L12.43 545.3 L10.63 545.3 L10.63 551.71 ZM4.25 542.47 L6.05 542.47 L6.05 536.06 L4.25 536.06 L4.25 542.47 + ZM4.25 551.71 L6.05 551.71 L6.05 545.3 L4.25 545.3 L4.25 551.71 ZM0 542.47 L1.79 542.47 L1.79 536.06 + L0 536.06 L0 542.47 ZM0 551.71 L1.79 551.71 L1.79 545.3 L0 545.3 L0 551.71 ZM33.82 586.45 L33.82 587.7 + L49.39 587.69 L49.39 586.44 L33.82 586.45 ZM33.82 590.24 L33.82 591.49 L49.39 591.48 L49.39 590.24 L33.82 + 590.24 ZM33.82 594.03 L33.82 595.28 L49.39 595.27 L49.39 594.03 L33.82 594.03 ZM2.96 587.7 L18.52 587.7 + L18.52 586.45 L2.95 586.45 L2.96 587.7 ZM2.96 591.49 L18.52 591.49 L18.52 590.24 L2.95 590.24 L2.96 + 591.49 ZM2.96 595.28 L18.52 595.28 L18.52 594.03 L2.95 594.03 L2.96 595.28 Z" class="st5"/> + </g> + <g id="shape19-79" v:mID="19" v:groupContext="shape" transform="translate(49.0815,-50.4059)"> + <title>工作表.19</title> + <path d="M8.15 583.79 A1.11073 1.11073 -180 1 0 10.24 584.56 A1.11073 1.11073 -180 1 0 8.15 583.79 ZM8.17 587.08 + A1.11073 1.11073 -180 1 0 10.22 587.93 A1.11073 1.11073 -180 1 0 8.17 587.08 ZM8.18 590.39 A1.11073 + 1.11073 -180 1 0 10.21 591.28 A1.11073 1.11073 -180 1 0 8.18 590.39 ZM8.18 593.71 A1.11073 1.11073 -180 + 1 0 10.21 594.6 A1.11073 1.11073 -180 1 0 8.18 593.71 ZM4.1 583.84 A1.11073 1.11073 -180 1 0 6.21 584.51 + A1.11073 1.11073 -180 1 0 4.1 583.84 ZM4.11 587.14 A1.11073 1.11073 -180 1 0 6.2 587.87 A1.11073 1.11073 + -180 1 0 4.11 587.14 ZM4.11 590.44 A1.11073 1.11073 -180 1 0 6.19 591.22 A1.11073 1.11073 -180 1 0 4.11 + 590.44 ZM4.11 593.77 A1.11073 1.11073 -180 1 0 6.19 594.55 A1.11073 1.11073 -180 1 0 4.11 593.77 ZM0.04 + 583.9 A1.11144 1.11144 -180 1 0 2.19 584.46 A1.11144 1.11144 -180 1 0 0.04 583.9 ZM0.05 587.19 A1.11144 + 1.11144 -180 1 0 2.18 587.82 A1.11144 1.11144 -180 1 0 0.05 587.19 ZM0.05 590.5 A1.11144 1.11144 -180 + 1 0 2.17 591.16 A1.11144 1.11144 -180 1 0 0.05 590.5 ZM0.05 593.83 A1.11144 1.11144 -180 1 0 2.17 594.49 + A1.11144 1.11144 -180 1 0 0.05 593.83 Z" class="st9"/> + </g> + <g id="shape16-82" v:mID="16" v:groupContext="groupContent"> + <v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/> + <v:textRect cx="35.4331" cy="674.877" width="130.38" height="159.204"/> + <text x="20.18" y="615.48" class="st3" v:langID="2052"><v:paragraph v:horizAlign="1"/><v:tabList/>NPC<v:newlineChar/><tspan + x="14.28" dy="1.2em" class="st6">Client<v:newlineChar/></tspan><tspan x="5.81" dy="1.2em" class="st6">10.0.0.2<v:newlineChar/></tspan><tspan + x="7.88" dy="1.2em" class="st6">Dial To:<v:newlineChar/></tspan><tspan x="-23.72" dy="1.2em" + class="st6">-</tspan>>10.0.0.3:PORT<v:newlineChar/><tspan x="-23.72" dy="1.2em" class="st6">-</tspan>>10.0.0.4:PORT<v:newlineChar/><tspan + x="-23.72" dy="1.2em" class="st6">-</tspan>>10.0.0.5:PORT</text> </g> + </g> + <g id="group20-90" transform="translate(212.598,-311.811)" v:mID="20" v:groupContext="group"> + <v:custProps> + <v:cp v:nameU="AssetNumber" v:lbl="资产号" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="SerialNumber" v:lbl="序列号" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Location" v:lbl="位置" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Building" v:lbl="建筑物" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Room" v:lbl="空间" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" v:ask="false" + v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Manufacturer" v:lbl="制造商" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="ProductNumber" v:lbl="产品编号" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="PartNumber" v:lbl="部件号" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="ProductDescription" v:lbl="产品说明" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" + v:invis="false" v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="NetworkName" v:lbl="网络名称" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="IPAddress" v:lbl="IP 地址" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="SubnetMask" v:lbl="子网掩码" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="AdminInterface" v:lbl="管理接口" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="NumberofPorts" v:lbl="端口数目" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="CommunityString" v:lbl="团体字符串" v:prompt="" v:type="0" v:format="" v:sortKey="Network" + v:invis="false" v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="NetworkDescription" v:lbl="网络说明" v:prompt="" v:type="0" v:format="" v:sortKey="Network" + v:invis="false" v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="MACAddress" v:lbl="MAC 地址" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="2052" v:cal="0"/> + <v:cp v:nameU="ShapeClass" v:lbl="ShapeClass" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="2052" v:cal="0" v:val="VT4(设备)"/> + <v:cp v:nameU="ShapeType" v:lbl="ShapeType" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="2052" v:cal="0" v:val="VT4(计算机)"/> + <v:cp v:nameU="SubShapeType" v:lbl="SubShapeType" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="2052" v:cal="0" v:val="VT4(大型机)"/> + </v:custProps> + <v:userDefs> + <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/> + <v:ud v:nameU="ShapeClass" v:prompt="" v:val="VT0(5):26"/> + <v:ud v:nameU="SolSH" v:prompt="" v:val="VT15({BF0433D9-CD73-4EB5-8390-8653BE590246}):41"/> + <v:ud v:nameU="visLegendShape" v:prompt="" v:val="VT0(2):26"/> + </v:userDefs> + <title>主机.20</title> + <desc>NPS Server 1.1.1.1 Listen On: 8003->10.0.0.3:PORT 8004->10.0....</desc> + <g id="shape21-91" v:mID="21" v:groupContext="shape" transform="translate(5.68158,0)"> + <title>工作表.21</title> + <path d="M0 595.28 L59.5 595.28 L59.5 524.41 L0 524.41 L0 595.28 Z" class="st7"/> + <path d="M0 595.28 L59.5 595.28 L59.5 524.41 L0 524.41 L0 595.28" class="st8"/> + <path d="M29.75 595.28 L29.75 524.41" class="st8"/> + </g> + <g id="shape22-95" v:mID="22" v:groupContext="shape" transform="translate(11.5726,-5.14536)"> + <title>工作表.22</title> + <v:userDefs> + <v:ud v:nameU="SurroundingRegionColor" v:prompt="" v:val="VT5(1)"/> + <v:ud v:nameU="SurroundingRegionColor" v:prompt="" v:val="VT5(#5b9bd5)"/> + </v:userDefs> + <path d="M36.09 551.42 L49.23 551.42 L49.23 536.38 L36.09 536.38 L36.09 551.42 ZM14.89 542.47 L16.68 542.47 L16.68 + 536.06 L14.89 536.06 L14.89 542.47 ZM14.89 551.71 L16.68 551.71 L16.68 545.3 L14.89 545.3 L14.89 551.71 + ZM10.63 542.47 L12.43 542.47 L12.43 536.06 L10.63 536.06 L10.63 542.47 ZM10.63 551.71 L12.43 551.71 + L12.43 545.3 L10.63 545.3 L10.63 551.71 ZM4.25 542.47 L6.05 542.47 L6.05 536.06 L4.25 536.06 L4.25 542.47 + ZM4.25 551.71 L6.05 551.71 L6.05 545.3 L4.25 545.3 L4.25 551.71 ZM0 542.47 L1.79 542.47 L1.79 536.06 + L0 536.06 L0 542.47 ZM0 551.71 L1.79 551.71 L1.79 545.3 L0 545.3 L0 551.71 ZM33.82 586.45 L33.82 587.7 + L49.39 587.69 L49.39 586.44 L33.82 586.45 ZM33.82 590.24 L33.82 591.49 L49.39 591.48 L49.39 590.24 L33.82 + 590.24 ZM33.82 594.03 L33.82 595.28 L49.39 595.27 L49.39 594.03 L33.82 594.03 ZM2.96 587.7 L18.52 587.7 + L18.52 586.45 L2.95 586.45 L2.96 587.7 ZM2.96 591.49 L18.52 591.49 L18.52 590.24 L2.95 590.24 L2.96 + 591.49 ZM2.96 595.28 L18.52 595.28 L18.52 594.03 L2.95 594.03 L2.96 595.28 Z" class="st5"/> + </g> + <g id="shape23-98" v:mID="23" v:groupContext="shape" transform="translate(49.0815,-50.4059)"> + <title>工作表.23</title> + <path d="M8.15 583.79 A1.11073 1.11073 -180 1 0 10.24 584.56 A1.11073 1.11073 -180 1 0 8.15 583.79 ZM8.17 587.08 + A1.11073 1.11073 -180 1 0 10.22 587.93 A1.11073 1.11073 -180 1 0 8.17 587.08 ZM8.18 590.39 A1.11073 + 1.11073 -180 1 0 10.21 591.28 A1.11073 1.11073 -180 1 0 8.18 590.39 ZM8.18 593.71 A1.11073 1.11073 -180 + 1 0 10.21 594.6 A1.11073 1.11073 -180 1 0 8.18 593.71 ZM4.1 583.84 A1.11073 1.11073 -180 1 0 6.21 584.51 + A1.11073 1.11073 -180 1 0 4.1 583.84 ZM4.11 587.14 A1.11073 1.11073 -180 1 0 6.2 587.87 A1.11073 1.11073 + -180 1 0 4.11 587.14 ZM4.11 590.44 A1.11073 1.11073 -180 1 0 6.19 591.22 A1.11073 1.11073 -180 1 0 4.11 + 590.44 ZM4.11 593.77 A1.11073 1.11073 -180 1 0 6.19 594.55 A1.11073 1.11073 -180 1 0 4.11 593.77 ZM0.04 + 583.9 A1.11144 1.11144 -180 1 0 2.19 584.46 A1.11144 1.11144 -180 1 0 0.04 583.9 ZM0.05 587.19 A1.11144 + 1.11144 -180 1 0 2.18 587.82 A1.11144 1.11144 -180 1 0 0.05 587.19 ZM0.05 590.5 A1.11144 1.11144 -180 + 1 0 2.17 591.16 A1.11144 1.11144 -180 1 0 0.05 590.5 ZM0.05 593.83 A1.11144 1.11144 -180 1 0 2.17 594.49 + A1.11144 1.11144 -180 1 0 0.05 593.83 Z" class="st9"/> + </g> + <g id="shape20-101" v:mID="20" v:groupContext="groupContent"> + <v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/> + <v:textRect cx="35.4331" cy="674.877" width="166.87" height="159.204"/> + <text x="20.84" y="615.48" class="st3" v:langID="2052"><v:paragraph v:horizAlign="1"/><v:tabList/>NPS<v:newlineChar/><tspan + x="12" dy="1.2em" class="st6">Server<v:newlineChar/></tspan><tspan x="10.37" dy="1.2em" class="st6">1.1.1.1<v:newlineChar/></tspan><tspan + x="-1.29" dy="1.2em" class="st6">Listen On:<v:newlineChar/></tspan><tspan x="-41.96" dy="1.2em" + class="st6">8003</tspan>->10.0.0.3:PORT<v:newlineChar/><tspan x="-41.96" dy="1.2em" class="st6">8004</tspan>->10.0.0.4:PORT<v:newlineChar/><tspan + x="-41.96" dy="1.2em" class="st6">8005</tspan>->10.0.0.5:PORT</text> </g> + </g> + <g id="group24-109" transform="translate(49.6063,-496.063)" v:mID="24" v:groupContext="group"> + <v:custProps> + <v:cp v:nameU="Name" v:lbl="名称" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="false" v:ask="false" + v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Location" v:lbl="位置" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="false" v:ask="false" + v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Building" v:lbl="构建" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="false" v:ask="false" + v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Room" v:lbl="空间" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="false" v:ask="false" + v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Department" v:lbl="部门" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="false" v:ask="false" + v:langID="2052" v:cal="0"/> + <v:cp v:nameU="ShapeClass" v:lbl="ShapeClass" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="2052" v:cal="0" v:val="VT4(连接性)"/> + <v:cp v:nameU="ShapeType" v:lbl="ShapeType" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="2052" v:cal="0" v:val="VT4(用户)"/> + </v:custProps> + <v:userDefs> + <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/> + <v:ud v:nameU="ShapeClass" v:prompt="" v:val="VT0(5):26"/> + <v:ud v:nameU="SolSH" v:prompt="" v:val="VT15({BF0433D9-CD73-4EB5-8390-8653BE590246}):41"/> + <v:ud v:nameU="visLegendShape" v:prompt="" v:val="VT0(2):26"/> + </v:userDefs> + <title>用户</title> + <desc>User1 Wants:APP1</desc> + <g id="shape25-110" v:mID="25" v:groupContext="shape" transform="translate(18.0575,0)"> + <title>工作表.25</title> + <path d="M26.29 533.22 A8.81 8.81 -180 1 0 8.67 533.22 A8.81 8.81 -180 1 0 26.29 533.22 ZM27.58 544.41 L7.17 544.41 + C3.22 544.41 0 547.62 0 551.58 L0 576.58 L5.59 576.58 L5.59 562.03 L7.45 562.03 L7.45 595.28 L16.55 + 595.28 L16.55 580.42 C16.55 579.9 16.97 579.48 17.48 579.48 C18 579.48 18.42 579.9 18.42 580.42 L18.42 + 595.28 L28.04 595.28 L28.04 561.98 L29.91 561.98 L29.91 576.58 L34.75 576.58 L34.75 551.58 C34.75 547.62 + 31.54 544.41 27.58 544.41 Z" class="st1"/> + </g> + <g id="shape24-112" v:mID="24" v:groupContext="groupContent"> + <v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/> + <v:textRect cx="35.4331" cy="620.877" width="102.19" height="51.2036"/> + <text x="13.96" y="615.48" class="st3" v:langID="2052"><v:paragraph v:horizAlign="1"/><v:tabList/>User1<v:newlineChar/><tspan + x="-9.62" dy="1.2em" class="st6">Wants:APP1</tspan></text> </g> + </g> + <g id="group26-115" transform="translate(49.6063,-311.811)" v:mID="26" v:groupContext="group"> + <v:custProps> + <v:cp v:nameU="Name" v:lbl="名称" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="false" v:ask="false" + v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Location" v:lbl="位置" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="false" v:ask="false" + v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Building" v:lbl="构建" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="false" v:ask="false" + v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Room" v:lbl="空间" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="false" v:ask="false" + v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Department" v:lbl="部门" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="false" v:ask="false" + v:langID="2052" v:cal="0"/> + <v:cp v:nameU="ShapeClass" v:lbl="ShapeClass" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="2052" v:cal="0" v:val="VT4(连接性)"/> + <v:cp v:nameU="ShapeType" v:lbl="ShapeType" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="2052" v:cal="0" v:val="VT4(用户)"/> + </v:custProps> + <v:userDefs> + <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/> + <v:ud v:nameU="ShapeClass" v:prompt="" v:val="VT0(5):26"/> + <v:ud v:nameU="SolSH" v:prompt="" v:val="VT15({BF0433D9-CD73-4EB5-8390-8653BE590246}):41"/> + <v:ud v:nameU="visLegendShape" v:prompt="" v:val="VT0(2):26"/> + </v:userDefs> + <title>用户.26</title> + <desc>User2 Wants:APP2</desc> + <g id="shape27-116" v:mID="27" v:groupContext="shape" transform="translate(18.0575,0)"> + <title>工作表.27</title> + <path d="M26.29 533.22 A8.81 8.81 -180 1 0 8.67 533.22 A8.81 8.81 -180 1 0 26.29 533.22 ZM27.58 544.41 L7.17 544.41 + C3.22 544.41 0 547.62 0 551.58 L0 576.58 L5.59 576.58 L5.59 562.03 L7.45 562.03 L7.45 595.28 L16.55 + 595.28 L16.55 580.42 C16.55 579.9 16.97 579.48 17.48 579.48 C18 579.48 18.42 579.9 18.42 580.42 L18.42 + 595.28 L28.04 595.28 L28.04 561.98 L29.91 561.98 L29.91 576.58 L34.75 576.58 L34.75 551.58 C34.75 547.62 + 31.54 544.41 27.58 544.41 Z" class="st1"/> + </g> + <g id="shape26-118" v:mID="26" v:groupContext="groupContent"> + <v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/> + <v:textRect cx="35.4331" cy="620.877" width="102.19" height="51.2036"/> + <text x="13.96" y="615.48" class="st3" v:langID="2052"><v:paragraph v:horizAlign="1"/><v:tabList/>User2<v:newlineChar/><tspan + x="-9.62" dy="1.2em" class="st6">Wants:APP2</tspan></text> </g> + </g> + <g id="group28-121" transform="translate(49.6063,-127.559)" v:mID="28" v:groupContext="group"> + <v:custProps> + <v:cp v:nameU="Name" v:lbl="名称" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="false" v:ask="false" + v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Location" v:lbl="位置" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="false" v:ask="false" + v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Building" v:lbl="构建" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="false" v:ask="false" + v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Room" v:lbl="空间" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="false" v:ask="false" + v:langID="2052" v:cal="0"/> + <v:cp v:nameU="Department" v:lbl="部门" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="false" v:ask="false" + v:langID="2052" v:cal="0"/> + <v:cp v:nameU="ShapeClass" v:lbl="ShapeClass" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="2052" v:cal="0" v:val="VT4(连接性)"/> + <v:cp v:nameU="ShapeType" v:lbl="ShapeType" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="2052" v:cal="0" v:val="VT4(用户)"/> + </v:custProps> + <v:userDefs> + <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/> + <v:ud v:nameU="ShapeClass" v:prompt="" v:val="VT0(5):26"/> + <v:ud v:nameU="SolSH" v:prompt="" v:val="VT15({BF0433D9-CD73-4EB5-8390-8653BE590246}):41"/> + <v:ud v:nameU="visLegendShape" v:prompt="" v:val="VT0(2):26"/> + </v:userDefs> + <title>用户.28</title> + <desc>User3 Wants:APP3</desc> + <g id="shape29-122" v:mID="29" v:groupContext="shape" transform="translate(18.0575,0)"> + <title>工作表.29</title> + <path d="M26.29 533.22 A8.81 8.81 -180 1 0 8.67 533.22 A8.81 8.81 -180 1 0 26.29 533.22 ZM27.58 544.41 L7.17 544.41 + C3.22 544.41 0 547.62 0 551.58 L0 576.58 L5.59 576.58 L5.59 562.03 L7.45 562.03 L7.45 595.28 L16.55 + 595.28 L16.55 580.42 C16.55 579.9 16.97 579.48 17.48 579.48 C18 579.48 18.42 579.9 18.42 580.42 L18.42 + 595.28 L28.04 595.28 L28.04 561.98 L29.91 561.98 L29.91 576.58 L34.75 576.58 L34.75 551.58 C34.75 547.62 + 31.54 544.41 27.58 544.41 Z" class="st1"/> + </g> + <g id="shape28-124" v:mID="28" v:groupContext="groupContent"> + <v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/> + <v:textRect cx="35.4331" cy="620.877" width="102.19" height="51.2036"/> + <text x="13.96" y="615.48" class="st3" v:langID="2052"><v:paragraph v:horizAlign="1"/><v:tabList/>User3<v:newlineChar/><tspan + x="-9.62" dy="1.2em" class="st6">Wants:APP3</tspan></text> </g> + </g> + <g id="shape1003-127" v:mID="1003" v:groupContext="shape" v:layerMember="0" transform="translate(99.8466,-514.757)"> + <title>动态连接线.1003</title> + <desc>->8003 Multi Conn</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/> + <v:textRect cx="56.059" cy="684.836" width="93.29" height="51.2036"/> + <path d="M5.09 601.03 L5.33 601.3 L113.11 723.13" class="st10"/> + <rect v:rectContext="textBkgnd" x="15.4535" y="663.236" width="81.2109" height="43.1999" class="st12"/> + <text x="30.58" y="679.44" class="st13" v:langID="2052"><v:paragraph v:horizAlign="1"/><v:tabList/>->8003<v:newlineChar/><tspan + x="15.45" dy="1.2em" class="st6">Multi Conn</tspan></text> </g> + <g id="shape1004-139" v:mID="1004" v:groupContext="shape" v:layerMember="0" transform="translate(102.415,-340.157)"> + <title>动态连接线.1004</title> + <desc>->8004 Multi Conn</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/> + <v:textRect cx="57.9325" cy="588.189" width="93.29" height="51.2036"/> + <path d="M7.68 588.19 L8.04 588.19 L107.83 588.19" class="st10"/> + <rect v:rectContext="textBkgnd" x="17.327" y="566.589" width="81.2109" height="43.1999" class="st12"/> + <text x="32.45" y="582.79" class="st13" v:langID="2052"><v:paragraph v:horizAlign="1"/><v:tabList/>->8004<v:newlineChar/><tspan + x="17.33" dy="1.2em" class="st6">Multi Conn</tspan></text> </g> + <g id="shape1005-149" v:mID="1005" v:groupContext="shape" v:layerMember="0" transform="translate(98.1493,-177.812)"> + <title>动态连接线.1005</title> + <desc>->8005 Multi Conn</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/> + <v:textRect cx="60.0654" cy="527.376" width="93.29" height="51.2036"/> + <path d="M5.09 589.52 L5.33 589.25 L114.8 465.5" class="st10"/> + <rect v:rectContext="textBkgnd" x="19.4599" y="505.776" width="81.2109" height="43.1999" class="st12"/> + <text x="34.58" y="521.98" class="st13" v:langID="2052"><v:paragraph v:horizAlign="1"/><v:tabList/>->8005<v:newlineChar/><tspan + x="19.46" dy="1.2em" class="st6">Multi Conn</tspan></text> </g> + <g id="shape1006-159" v:mID="1006" v:groupContext="shape" v:layerMember="0" transform="translate(277.783,-354.331)"> + <title>动态连接线.1006</title> + <desc>NPS & NPC Multiplexing Connection TCP or KCP Only One Conn Pe...</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/> + <v:textRect cx="70.4362" cy="602.362" width="103.62" height="159.204"/> + <path d="M7.68 602.36 L8.04 602.36 L132.83 602.36" class="st10"/> + <rect v:rectContext="textBkgnd" x="24.6671" y="526.762" width="91.5381" height="151.2" class="st12"/> + <text x="30.38" y="542.96" class="st13" v:langID="2052"><v:paragraph v:horizAlign="1"/><v:tabList/>NPS & NPC<v:newlineChar/><tspan + x="24.67" dy="1.2em" class="st6">Multiplexing<v:newlineChar/></tspan><tspan x="28.6" dy="1.2em" class="st6">Connection<v:newlineChar/></tspan><tspan + x="30.53" dy="1.2em" class="st6">TCP or KCP<v:newlineChar/></tspan><tspan x="36.41" dy="1.2em" class="st6">Only One<v:newlineChar/></tspan><tspan + x="32.66" dy="1.2em" class="st6">Conn Peer<v:newlineChar/></tspan><tspan x="55.18" dy="1.2em" class="st6">NPC</tspan></text> </g> + <g id="shape1007-174" v:mID="1007" v:groupContext="shape" v:layerMember="0" transform="translate(603.767,-380.876)"> + <title>动态连接线.1007</title> + <desc>->PORT Multi Conn</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/> + <v:textRect cx="55.0044" cy="550.955" width="93.29" height="51.2036"/> + <path d="M5.09 589.52 L5.33 589.25 L105.29 476.25" class="st10"/> + <rect v:rectContext="textBkgnd" x="14.3989" y="529.355" width="81.2109" height="43.1999" class="st12"/> + <text x="27.89" y="545.56" class="st13" v:langID="2052"><v:paragraph v:horizAlign="1"/><v:tabList/>->PORT<v:newlineChar/><tspan + x="14.4" dy="1.2em" class="st6">Multi Conn</tspan></text> </g> + <g id="shape1008-184" v:mID="1008" v:groupContext="shape" v:layerMember="0" transform="translate(603.767,-340.157)"> + <title>动态连接线.1008</title> + <desc>->PORT Multi Conn</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/> + <v:textRect cx="55.3104" cy="588.189" width="93.29" height="51.2036"/> + <path d="M7.68 588.19 L8.04 588.19 L102.58 588.19" class="st10"/> + <rect v:rectContext="textBkgnd" x="14.7049" y="566.589" width="81.2109" height="43.1999" class="st12"/> + <text x="28.19" y="582.79" class="st13" v:langID="2052"><v:paragraph v:horizAlign="1"/><v:tabList/>->PORT<v:newlineChar/><tspan + x="14.7" dy="1.2em" class="st6">Multi Conn</tspan></text> </g> + <g id="shape1009-194" v:mID="1009" v:groupContext="shape" v:layerMember="0" transform="translate(603.767,-313.612)"> + <title>动态连接线.1009</title> + <desc>->PORT Multi Conn</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/> + <v:textRect cx="68.0438" cy="667.943" width="93.29" height="51.2036"/> + <path d="M5.09 601.03 L5.33 601.3 L105.29 714.3" class="st10"/> + <rect v:rectContext="textBkgnd" x="27.4383" y="646.343" width="81.2109" height="43.1999" class="st12"/> + <text x="40.93" y="662.54" class="st13" v:langID="2052"><v:paragraph v:horizAlign="1"/><v:tabList/>->PORT<v:newlineChar/><tspan + x="27.44" dy="1.2em" class="st6">Multi Conn</tspan></text> </g> + <g id="shape1010-204" v:mID="1010" v:groupContext="shape" v:layerMember="0" transform="translate(488.431,-340.157)"> + <title>动态连接线.1010</title> + <desc>NPS & NPC</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/> + <v:textRect cx="27.9165" cy="588.189" width="90" height="72.8036"/> + <path d="M7.68 588.19 L8.04 588.19 L47.79 588.19" class="st10"/> + <rect v:rectContext="textBkgnd" x="12.6587" y="555.789" width="30.5156" height="64.7998" class="st12"/> + <text x="13.32" y="571.99" class="st13" v:langID="2052"><v:paragraph v:horizAlign="1"/><v:tabList/>NPS<v:newlineChar/><tspan + x="21.78" dy="1.2em" class="st6">&<v:newlineChar/></tspan><tspan x="12.66" dy="1.2em" class="st6">NPC</tspan></text> </g> + <g id="shape1011-215" v:mID="1011" v:groupContext="shape" transform="translate(34.0157,-62.8844)"> + <title>工作表.1011</title> + <path d="M0 595.28 L398.27 595.28 L398.27 85.04 L0 85.04 L0 595.28 Z" class="st14"/> + </g> + <g id="shape1012-217" v:mID="1012" v:groupContext="shape" transform="translate(473.386,-62.8844)"> + <title>工作表.1012</title> + <path d="M0 595.28 L320.31 595.28 L320.31 85.04 L0 85.04 L0 595.28 Z" class="st14"/> + </g> + <g id="shape1013-219" v:mID="1013" v:groupContext="shape" transform="translate(255.118,-496.063)"> + <title>工作表.1013</title> + <desc>Internet</desc> + <v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/> + <v:textRect cx="63.7795" cy="559.843" width="127.56" height="70.8661"/> + <rect x="0" y="524.409" width="127.559" height="70.8661" class="st15"/> + <text x="23.98" y="567.04" class="st16" v:langID="2052"><v:paragraph v:horizAlign="1"/><v:tabList/>Internet</text> </g> + <g id="shape1014-222" v:mID="1014" v:groupContext="shape" transform="translate(517.323,-515.866)"> + <title>工作表.1014</title> + <desc>Intranet</desc> + <v:textBlock v:margins="rect(4,4,4,4)" v:tabSpace="42.5197"/> + <v:textRect cx="76" cy="579.646" width="152.01" height="31.2598"/> + <rect x="0" y="564.016" width="152" height="31.2598" class="st15"/> + <text x="36.43" y="586.85" class="st16" v:langID="2052"><v:paragraph v:horizAlign="1"/><v:tabList/>Intranet</text> </g> + </g> +</svg> diff --git a/lib/common/const.go b/lib/common/const.go index 2fd5bb6..2f195f3 100644 --- a/lib/common/const.go +++ b/lib/common/const.go @@ -49,6 +49,6 @@ const ( MUX_PING_RETURN MUX_PING int32 = -1 MAXIMUM_SEGMENT_SIZE = PoolSizeWindow - MAXIMUM_WINDOW_SIZE = 1 << 25 // 1<<31-1 TCP slide window size is very large, - // we use 32M, reduce memory usage + MAXIMUM_WINDOW_SIZE = 1 << 27 // 1<<31-1 TCP slide window size is very large, + // we use 128M, reduce memory usage ) diff --git a/lib/common/netpackager.go b/lib/common/netpackager.go index c6956f5..45456c5 100644 --- a/lib/common/netpackager.go +++ b/lib/common/netpackager.go @@ -162,10 +162,9 @@ func (Self *ConnPackager) UnPack(reader io.Reader) (n uint16, err error) { } type MuxPackager struct { - Flag uint8 - Id int32 - Window uint32 - ReadLength uint32 + Flag uint8 + Id int32 + Window uint64 BasePackager } @@ -178,19 +177,8 @@ func (Self *MuxPackager) NewPac(flag uint8, id int32, content ...interface{}) (e err = Self.BasePackager.NewPac(content...) //logs.Warn(Self.Length, string(Self.Content)) case MUX_MSG_SEND_OK: - // MUX_MSG_SEND_OK contains two data - switch content[0].(type) { - case int: - Self.Window = uint32(content[0].(int)) - case uint32: - Self.Window = content[0].(uint32) - } - switch content[1].(type) { - case int: - Self.ReadLength = uint32(content[1].(int)) - case uint32: - Self.ReadLength = content[1].(uint32) - } + // MUX_MSG_SEND_OK contains one data + Self.Window = content[0].(uint64) } return } @@ -210,10 +198,6 @@ func (Self *MuxPackager) Pack(writer io.Writer) (err error) { WindowBuff.Put(Self.Content) case MUX_MSG_SEND_OK: err = binary.Write(writer, binary.LittleEndian, Self.Window) - if err != nil { - return - } - err = binary.Write(writer, binary.LittleEndian, Self.ReadLength) } return } @@ -235,12 +219,7 @@ func (Self *MuxPackager) UnPack(reader io.Reader) (n uint16, err error) { //logs.Warn("unpack", Self.Length, string(Self.Content)) case MUX_MSG_SEND_OK: err = binary.Read(reader, binary.LittleEndian, &Self.Window) - if err != nil { - return - } - n += 4 // uint32 - err = binary.Read(reader, binary.LittleEndian, &Self.ReadLength) - n += 4 // uint32 + n += 8 // uint64 } n += 5 //uint8 int32 return @@ -251,7 +230,6 @@ func (Self *MuxPackager) reset() { Self.Flag = 0 Self.Length = 0 Self.Content = nil - Self.ReadLength = 0 Self.Window = 0 } diff --git a/lib/common/util.go b/lib/common/util.go index 1db0d27..71e604e 100755 --- a/lib/common/util.go +++ b/lib/common/util.go @@ -16,7 +16,7 @@ import ( "strings" "sync" - "github.com/cnlh/nps/lib/crypt" + "ehang.io/nps/lib/crypt" ) //Get the corresponding IP address through domain name diff --git a/lib/config/config.go b/lib/config/config.go index 96531e2..62e2d2b 100644 --- a/lib/config/config.go +++ b/lib/config/config.go @@ -6,8 +6,8 @@ import ( "regexp" "strings" - "github.com/cnlh/nps/lib/common" - "github.com/cnlh/nps/lib/file" + "ehang.io/nps/lib/common" + "ehang.io/nps/lib/file" ) type CommonConfig struct { @@ -241,7 +241,7 @@ func dealTunnel(s string) *file.Tunnel { t.StripPre = item[1] case "multi_account": t.MultiAccount = &file.MultiAccount{} - if common.FileExists(item[1]){ + if common.FileExists(item[1]) { if b, err := common.ReadAllFromFile(item[1]); err != nil { panic(err) } else { diff --git a/lib/conn/conn.go b/lib/conn/conn.go index db03c40..c1ca1b1 100755 --- a/lib/conn/conn.go +++ b/lib/conn/conn.go @@ -3,11 +3,11 @@ package conn import ( "bufio" "bytes" + "ehang.io/nps/lib/goroutine" "encoding/binary" "encoding/json" "errors" "github.com/astaxie/beego/logs" - "github.com/cnlh/nps/lib/goroutine" "io" "net" "net/http" @@ -16,11 +16,11 @@ import ( "strings" "time" - "github.com/cnlh/nps/lib/common" - "github.com/cnlh/nps/lib/crypt" - "github.com/cnlh/nps/lib/file" - "github.com/cnlh/nps/lib/mux" - "github.com/cnlh/nps/lib/rate" + "ehang.io/nps/lib/common" + "ehang.io/nps/lib/crypt" + "ehang.io/nps/lib/file" + "ehang.io/nps/lib/mux" + "ehang.io/nps/lib/rate" "github.com/xtaci/kcp-go" ) diff --git a/lib/daemon/daemon.go b/lib/daemon/daemon.go index 3c41086..521745c 100644 --- a/lib/daemon/daemon.go +++ b/lib/daemon/daemon.go @@ -9,7 +9,7 @@ import ( "strconv" "strings" - "github.com/cnlh/nps/lib/common" + "ehang.io/nps/lib/common" ) func InitDaemon(f string, runPath string, pidPath string) { diff --git a/lib/daemon/reload.go b/lib/daemon/reload.go index 2db00ac..5216eff 100644 --- a/lib/daemon/reload.go +++ b/lib/daemon/reload.go @@ -8,8 +8,8 @@ import ( "path/filepath" "syscall" + "ehang.io/nps/lib/common" "github.com/astaxie/beego" - "github.com/cnlh/nps/lib/common" ) func init() { diff --git a/lib/file/db.go b/lib/file/db.go index c48df2e..50be394 100644 --- a/lib/file/db.go +++ b/lib/file/db.go @@ -9,9 +9,9 @@ import ( "strings" "sync" - "github.com/cnlh/nps/lib/common" - "github.com/cnlh/nps/lib/crypt" - "github.com/cnlh/nps/lib/rate" + "ehang.io/nps/lib/common" + "ehang.io/nps/lib/crypt" + "ehang.io/nps/lib/rate" ) type DbUtils struct { diff --git a/lib/file/file.go b/lib/file/file.go index 63f3cb7..beab47f 100644 --- a/lib/file/file.go +++ b/lib/file/file.go @@ -9,8 +9,8 @@ import ( "sync" "sync/atomic" - "github.com/cnlh/nps/lib/common" - "github.com/cnlh/nps/lib/rate" + "ehang.io/nps/lib/common" + "ehang.io/nps/lib/rate" ) func NewJsonDb(runPath string) *JsonDb { diff --git a/lib/file/obj.go b/lib/file/obj.go index 36c783b..31f3e63 100644 --- a/lib/file/obj.go +++ b/lib/file/obj.go @@ -6,7 +6,7 @@ import ( "sync/atomic" "time" - "github.com/cnlh/nps/lib/rate" + "ehang.io/nps/lib/rate" "github.com/pkg/errors" ) diff --git a/lib/goroutine/pool.go b/lib/goroutine/pool.go index 287c711..ca91d6d 100644 --- a/lib/goroutine/pool.go +++ b/lib/goroutine/pool.go @@ -1,8 +1,8 @@ package goroutine import ( - "github.com/cnlh/nps/lib/common" - "github.com/cnlh/nps/lib/file" + "ehang.io/nps/lib/common" + "ehang.io/nps/lib/file" "github.com/panjf2000/ants/v2" "io" "net" diff --git a/lib/install/install.go b/lib/install/install.go index 6156e3f..8973d0d 100644 --- a/lib/install/install.go +++ b/lib/install/install.go @@ -1,11 +1,11 @@ package install import ( + "ehang.io/nps/lib/common" "encoding/json" "errors" "fmt" "github.com/c4milo/unpackit" - "github.com/cnlh/nps/lib/common" "io" "io/ioutil" "log" @@ -50,7 +50,7 @@ func downloadLatest(bin string) string { fmt.Println("the latest version is", version) filename := runtime.GOOS + "_" + runtime.GOARCH + "_" + bin + ".tar.gz" // download latest package - downloadUrl := fmt.Sprintf("https://github.com/cnlh/nps/releases/download/%s/%s", version, filename) + downloadUrl := fmt.Sprintf("https://ehang.io/nps/releases/download/%s/%s", version, filename) fmt.Println("download package from ", downloadUrl) resp, err := http.Get(downloadUrl) if err != nil { diff --git a/lib/mux/conn.go b/lib/mux/conn.go index 52fb642..c0a5b7a 100644 --- a/lib/mux/conn.go +++ b/lib/mux/conn.go @@ -1,6 +1,7 @@ package mux import ( + "ehang.io/nps/lib/common" "errors" "github.com/astaxie/beego/logs" "io" @@ -10,8 +11,6 @@ import ( "sync" "sync/atomic" "time" - - "github.com/cnlh/nps/lib/common" ) type conn struct { @@ -146,25 +145,44 @@ func (s *conn) SetWriteDeadline(t time.Time) error { } type window struct { - remainingWait uint64 // 64bit alignment - off uint32 - maxSize uint32 - closeOp bool - closeOpCh chan struct{} - mux *Mux + maxSizeDone uint64 + // 64bit alignment + // maxSizeDone contains 4 parts + // 1 31 1 31 + // wait maxSize useless done + // wait zero means false, one means true + off uint32 + closeOp bool + closeOpCh chan struct{} + mux *Mux } -func (Self *window) unpack(ptrs uint64) (remaining, wait uint32) { - const mask = 1<<dequeueBits - 1 - remaining = uint32((ptrs >> dequeueBits) & mask) - wait = uint32(ptrs & mask) +const windowBits = 31 +const waitBits = dequeueBits + windowBits +const mask1 = 1 +const mask31 = 1<<windowBits - 1 + +func (Self *window) unpack(ptrs uint64) (maxSize, done uint32, wait bool) { + maxSize = uint32((ptrs >> dequeueBits) & mask31) + done = uint32(ptrs & mask31) + //logs.Warn("unpack", maxSize, done) + if ((ptrs >> waitBits) & mask1) == 1 { + wait = true + return + } return } -func (Self *window) pack(remaining, wait uint32) uint64 { - const mask = 1<<dequeueBits - 1 - return (uint64(remaining) << dequeueBits) | - uint64(wait&mask) +func (Self *window) pack(maxSize, done uint32, wait bool) uint64 { + //logs.Warn("pack", maxSize, done, wait) + if wait { + return (uint64(1)<<waitBits | + uint64(maxSize&mask31)<<dequeueBits) | + uint64(done&mask31) + } + return (uint64(0)<<waitBits | + uint64(maxSize&mask31)<<dequeueBits) | + uint64(done&mask31) } func (Self *window) New() { @@ -184,21 +202,25 @@ type ReceiveWindow struct { bufQueue ReceiveWindowQueue element *common.ListElement count int8 + bw *writeBandwidth once sync.Once + // receive window send the current max size and read size to send window + // means done size actually store the size receive window has read } func (Self *ReceiveWindow) New(mux *Mux) { // initial a window for receive Self.bufQueue.New() Self.element = common.ListElementPool.Get() - Self.maxSize = common.MAXIMUM_SEGMENT_SIZE * 10 + Self.maxSizeDone = Self.pack(common.MAXIMUM_SEGMENT_SIZE*30, 0, false) Self.mux = mux Self.window.New() + Self.bw = NewWriteBandwidth() } -func (Self *ReceiveWindow) remainingSize(delta uint16) (n uint32) { +func (Self *ReceiveWindow) remainingSize(maxSize uint32, delta uint16) (n uint32) { // receive window remaining - l := int64(atomic.LoadUint32(&Self.maxSize)) - int64(Self.bufQueue.Len()) + l := int64(maxSize) - int64(Self.bufQueue.Len()) l -= int64(delta) if l > 0 { n = uint32(l) @@ -210,30 +232,46 @@ func (Self *ReceiveWindow) calcSize() { // calculating maximum receive window size if Self.count == 0 { //logs.Warn("ping, bw", Self.mux.latency, Self.bw.Get()) - conns := Self.mux.connMap.Size() - n := uint32(math.Float64frombits(atomic.LoadUint64(&Self.mux.latency)) * - Self.mux.bw.Get() / float64(conns)) - if n < common.MAXIMUM_SEGMENT_SIZE*10 { - n = common.MAXIMUM_SEGMENT_SIZE * 10 + //conns := Self.mux.connMap.Size() + muxBw := Self.mux.bw.Get() + connBw := Self.bw.Get() + //logs.Warn("muxbw connbw", muxBw, connBw) + var n uint32 + if connBw > 0 && muxBw > 0 { + n = uint32(math.Float64frombits(atomic.LoadUint64(&Self.mux.latency)) * + (muxBw + connBw)) } - //bufLen := Self.bufQueue.Len() - //if n < bufLen { - // n = bufLen - //} - if n < Self.maxSize/2 { - n = Self.maxSize / 2 + //logs.Warn(n) + if n < common.MAXIMUM_SEGMENT_SIZE*30 { + //logs.Warn("window small", n, Self.mux.bw.Get(), Self.bw.Get()) + n = common.MAXIMUM_SEGMENT_SIZE * 30 } - // set the minimal size - if n > 2*Self.maxSize { - n = 2 * Self.maxSize + for { + ptrs := atomic.LoadUint64(&Self.maxSizeDone) + size, read, wait := Self.unpack(ptrs) + if n < size/2 { + n = size / 2 + // half reduce + } + // set the minimal size + if n > 2*size { + n = 2 * size + // twice grow + } + if connBw > 0 && muxBw > 0 { + limit := uint32(common.MAXIMUM_WINDOW_SIZE * (connBw / (muxBw + connBw))) + if n > limit { + logs.Warn("window too large, calculated:", n, "limit:", limit, connBw, muxBw) + n = limit + } + } + // set the maximum size + //logs.Warn("n", n) + if atomic.CompareAndSwapUint64(&Self.maxSizeDone, ptrs, Self.pack(n, read, wait)) { + // only change the maxSize + break + } } - if n > (common.MAXIMUM_WINDOW_SIZE / uint32(conns)) { - logs.Warn("window too large", n) - n = common.MAXIMUM_WINDOW_SIZE / uint32(conns) - } - // set the maximum size - //logs.Warn("n", n) - atomic.StoreUint32(&Self.maxSize, n) Self.count = -10 } Self.count += 1 @@ -245,30 +283,40 @@ func (Self *ReceiveWindow) Write(buf []byte, l uint16, part bool, id int32) (err return errors.New("conn.receiveWindow: write on closed window") } element, err := NewListElement(buf, l, part) - //logs.Warn("push the buf", len(buf), l, (&element).l) + //logs.Warn("push the buf", len(buf), l, element.L) if err != nil { return } Self.calcSize() // calculate the max window size - var wait uint32 + var wait bool + var maxSize, read uint32 start: - ptrs := atomic.LoadUint64(&Self.remainingWait) - _, wait = Self.unpack(ptrs) - newRemaining := Self.remainingSize(l) + ptrs := atomic.LoadUint64(&Self.maxSizeDone) + maxSize, read, wait = Self.unpack(ptrs) + remain := Self.remainingSize(maxSize, l) // calculate the remaining window size now, plus the element we will push - if newRemaining == 0 { + if remain == 0 && !wait { //logs.Warn("window full true", remaining) - wait = 1 - } - if !atomic.CompareAndSwapUint64(&Self.remainingWait, ptrs, Self.pack(0, wait)) { - goto start - // another goroutine change the status, make sure shall we need wait - } + wait = true + if !atomic.CompareAndSwapUint64(&Self.maxSizeDone, ptrs, Self.pack(maxSize, read, wait)) { + // only change the wait status, not send the read size + goto start + // another goroutine change the status, make sure shall we need wait + } + //logs.Warn("receive window full") + } else if !wait { + if !atomic.CompareAndSwapUint64(&Self.maxSizeDone, ptrs, Self.pack(maxSize, 0, wait)) { + // reset read size here, and send the read size directly + goto start + // another goroutine change the status, make sure shall we need wait + } + } // maybe there are still some data received even if window is full, just keep the wait status + // and push into queue. when receive window read enough, send window will be acknowledged. Self.bufQueue.Push(element) // status check finish, now we can push the element into the queue - if wait == 0 { - Self.mux.sendInfo(common.MUX_MSG_SEND_OK, id, Self.maxSize, newRemaining) - // send the remaining window size, not including zero size + if !wait { + Self.mux.sendInfo(common.MUX_MSG_SEND_OK, id, Self.pack(maxSize, read, false)) + // send the current status to send window } return nil } @@ -277,9 +325,16 @@ func (Self *ReceiveWindow) Read(p []byte, id int32) (n int, err error) { if Self.closeOp { return 0, io.EOF // receive close signal, returns eof } + Self.bw.StartRead() + n, err = Self.readFromQueue(p, id) + Self.bw.SetCopySize(uint16(n)) + return +} + +func (Self *ReceiveWindow) readFromQueue(p []byte, id int32) (n int, err error) { pOff := 0 l := 0 - //logs.Warn("receive window read off, element.l", Self.off, Self.element.l) + //logs.Warn("receive window read off, element.l", Self.off, Self.element.L) copyData: if Self.off == uint32(Self.element.L) { // on the first Read method invoked, Self.off and Self.element.l @@ -291,14 +346,13 @@ copyData: Self.element, err = Self.bufQueue.Pop() // if the queue is empty, Pop method will wait until one element push // into the queue successful, or timeout. - // timer start on timeout parameter is set up , - // reset to 60s if timeout and data still available + // timer start on timeout parameter is set up Self.off = 0 if err != nil { Self.CloseWindow() // also close the window, to avoid read twice return // queue receive stop or time out, break the loop and return } - //logs.Warn("pop element", Self.element.l, Self.element.part) + //logs.Warn("pop element", Self.element.L, Self.element.Part) } l = copy(p[pOff:], Self.element.Buf[Self.off:Self.element.L]) pOff += l @@ -320,22 +374,41 @@ copyData: } func (Self *ReceiveWindow) sendStatus(id int32, l uint16) { - var remaining, wait uint32 + var maxSize, read uint32 + var wait bool for { - ptrs := atomic.LoadUint64(&Self.remainingWait) - remaining, wait = Self.unpack(ptrs) - remaining += uint32(l) - if atomic.CompareAndSwapUint64(&Self.remainingWait, ptrs, Self.pack(remaining, 0)) { - break + ptrs := atomic.LoadUint64(&Self.maxSizeDone) + maxSize, read, wait = Self.unpack(ptrs) + if read <= (read+uint32(l))&mask31 { + read += uint32(l) + remain := Self.remainingSize(maxSize, 0) + if wait && remain > 0 || read >= maxSize/2 || remain == maxSize { + if atomic.CompareAndSwapUint64(&Self.maxSizeDone, ptrs, Self.pack(maxSize, 0, false)) { + // now we get the current window status success + // receive window free up some space we need acknowledge send window, also reset the read size + // still having a condition that receive window is empty and not send the status to send window + // so send the status here + //logs.Warn("receive window free up some space", remain) + Self.mux.sendInfo(common.MUX_MSG_SEND_OK, id, Self.pack(maxSize, read, false)) + break + } + } else { + if atomic.CompareAndSwapUint64(&Self.maxSizeDone, ptrs, Self.pack(maxSize, read, wait)) { + // receive window not into the wait status, or still not having any space now, + // just change the read size + break + } + } + } else { + //overflow + if atomic.CompareAndSwapUint64(&Self.maxSizeDone, ptrs, Self.pack(maxSize, uint32(l), wait)) { + // reset to l + Self.mux.sendInfo(common.MUX_MSG_SEND_OK, id, Self.pack(maxSize, read, false)) + break + } } runtime.Gosched() // another goroutine change remaining or wait status, make sure - // we need acknowledge other side - } - // now we get the current window status success - if wait == 1 { - //logs.Warn("send the wait status", remaining) - Self.mux.sendInfo(common.MUX_MSG_SEND_OK, id, atomic.LoadUint32(&Self.maxSize), remaining) } return } @@ -380,12 +453,14 @@ type SendWindow struct { buf []byte setSizeCh chan struct{} timeout time.Time + // send window receive the receive window max size and read size + // done size store the size send window has send, send and read will be totally equal + // so send minus read, send window can get the current window size remaining } func (Self *SendWindow) New(mux *Mux) { Self.setSizeCh = make(chan struct{}) - Self.maxSize = common.MAXIMUM_SEGMENT_SIZE * 10 - atomic.AddUint64(&Self.remainingWait, uint64(common.MAXIMUM_SEGMENT_SIZE*10)<<dequeueBits) + Self.maxSizeDone = Self.pack(common.MAXIMUM_SEGMENT_SIZE*30, 0, false) Self.mux = mux Self.window.New() } @@ -396,7 +471,15 @@ func (Self *SendWindow) SetSendBuf(buf []byte) { Self.off = 0 } -func (Self *SendWindow) SetSize(windowSize, newRemaining uint32) (closed bool) { +func (Self *SendWindow) remainingSize(maxSize, send uint32) uint32 { + l := int64(maxSize&mask31) - int64(send&mask31) + if l > 0 { + return uint32(l) + } + return 0 +} + +func (Self *SendWindow) SetSize(currentMaxSizeDone uint64) (closed bool) { // set the window size from receive window defer func() { if recover() != nil { @@ -408,26 +491,34 @@ func (Self *SendWindow) SetSize(windowSize, newRemaining uint32) (closed bool) { return true } //logs.Warn("set send window size to ", windowSize, newRemaining) - var remaining, wait, newWait uint32 + var maxsize, send uint32 + var wait, newWait bool + currentMaxSize, read, _ := Self.unpack(currentMaxSizeDone) for { - ptrs := atomic.LoadUint64(&Self.remainingWait) - remaining, wait = Self.unpack(ptrs) - if remaining == newRemaining { - //logs.Warn("waiting for another window size") - return false // waiting for receive another usable window size + ptrs := atomic.LoadUint64(&Self.maxSizeDone) + maxsize, send, wait = Self.unpack(ptrs) + if read > send { + logs.Error("window read > send: max size:", currentMaxSize, "read:", read, "send", send) + return } - if newRemaining == 0 && wait == 1 { - newWait = 1 // keep the wait status, - // also if newRemaining is not zero, change wait to 0 + if read == 0 && currentMaxSize == maxsize { + return } - if atomic.CompareAndSwapUint64(&Self.remainingWait, ptrs, Self.pack(newRemaining, newWait)) { + send -= read + remain := Self.remainingSize(currentMaxSize, send) + if remain == 0 && wait { + // just keep the wait status + newWait = true + } + // remain > 0, change wait to false. or remain == 0, wait is false, just keep it + if atomic.CompareAndSwapUint64(&Self.maxSizeDone, ptrs, Self.pack(currentMaxSize, send, newWait)) { break } // anther goroutine change wait status or window size } - if wait == 1 { + if wait && !newWait { // send window into the wait status, need notice the channel - //logs.Warn("send window remaining size is 0") + //logs.Warn("send window allow") Self.allow() } // send window not into the wait status, so just do slide @@ -446,18 +537,20 @@ func (Self *SendWindow) allow() { } func (Self *SendWindow) sent(sentSize uint32) { - var remaining, wait uint32 + var maxSie, send uint32 + var wait bool for { - ptrs := atomic.LoadUint64(&Self.remainingWait) - remaining, wait = Self.unpack(ptrs) - if remaining >= sentSize { - atomic.AddUint64(&Self.remainingWait, ^(uint64(sentSize)<<dequeueBits - 1)) + ptrs := atomic.LoadUint64(&Self.maxSizeDone) + maxSie, send, wait = Self.unpack(ptrs) + if (send+sentSize)&mask31 < send { + // overflow + runtime.Gosched() + continue + } + if atomic.CompareAndSwapUint64(&Self.maxSizeDone, ptrs, Self.pack(maxSie, send+sentSize, wait)) { + // set the send size + //logs.Warn("sent", maxSie, send+sentSize, wait) break - } else { - if atomic.CompareAndSwapUint64(&Self.remainingWait, ptrs, Self.pack(0, wait)) { - // just keep the wait status, it will be wait in the next loop - break - } } } } @@ -472,12 +565,14 @@ func (Self *SendWindow) WriteTo() (p []byte, sendSize uint32, part bool, err err return nil, 0, false, io.EOF // send window buff is drain, return eof and get another one } - var remaining uint32 + var maxSize, send uint32 start: - ptrs := atomic.LoadUint64(&Self.remainingWait) - remaining, _ = Self.unpack(ptrs) - if remaining == 0 { - if !atomic.CompareAndSwapUint64(&Self.remainingWait, ptrs, Self.pack(0, 1)) { + ptrs := atomic.LoadUint64(&Self.maxSizeDone) + maxSize, send, _ = Self.unpack(ptrs) + remain := Self.remainingSize(maxSize, send) + if remain == 0 { + if !atomic.CompareAndSwapUint64(&Self.maxSizeDone, ptrs, Self.pack(maxSize, send, true)) { + // just change the status wait status goto start // another goroutine change the window, try again } // into the wait status @@ -490,17 +585,17 @@ start: goto start } // there are still remaining window - //logs.Warn("rem", remaining) + //logs.Warn("rem", remain, maxSize, send) if len(Self.buf[Self.off:]) > common.MAXIMUM_SEGMENT_SIZE { sendSize = common.MAXIMUM_SEGMENT_SIZE //logs.Warn("cut buf by mss") } else { sendSize = uint32(len(Self.buf[Self.off:])) } - if remaining < sendSize { + if remain < sendSize { // usable window size is small than // window MAXIMUM_SEGMENT_SIZE or send buf left - sendSize = remaining + sendSize = remain //logs.Warn("cut buf by remainingsize", sendSize, len(Self.buf[Self.off:])) } //logs.Warn("send size", sendSize) @@ -579,81 +674,49 @@ func (Self *SendWindow) SetTimeOut(t time.Time) { Self.timeout = t } -//type bandwidth struct { -// readStart time.Time -// lastReadStart time.Time -// readEnd time.Time -// lastReadEnd time.Time -// bufLength int -// lastBufLength int -// count int8 -// readBW float64 -// writeBW float64 -// readBandwidth float64 -//} -// -//func (Self *bandwidth) StartRead() { -// Self.lastReadStart, Self.readStart = Self.readStart, time.Now() -// if !Self.lastReadStart.IsZero() { -// if Self.count == -5 { -// Self.calcBandWidth() -// } -// } -//} -// -//func (Self *bandwidth) EndRead() { -// Self.lastReadEnd, Self.readEnd = Self.readEnd, time.Now() -// if Self.count == -5 { -// Self.calcWriteBandwidth() -// } -// if Self.count == 0 { -// Self.calcReadBandwidth() -// Self.count = -6 -// } -// Self.count += 1 -//} -// -//func (Self *bandwidth) SetCopySize(n int) { -// // must be invoke between StartRead and EndRead -// Self.lastBufLength, Self.bufLength = Self.bufLength, n -//} -//// calculating -//// start end start end -//// read read -//// write -// -//func (Self *bandwidth) calcBandWidth() { -// t := Self.readStart.Sub(Self.lastReadStart) -// if Self.lastBufLength >= 32768 { -// Self.readBandwidth = float64(Self.lastBufLength) / t.Seconds() -// } -//} -// -//func (Self *bandwidth) calcReadBandwidth() { -// // Bandwidth between nps and npc -// readTime := Self.readEnd.Sub(Self.readStart) -// Self.readBW = float64(Self.bufLength) / readTime.Seconds() -// //logs.Warn("calc read bw", Self.readBW, Self.bufLength, readTime.Seconds()) -//} -// -//func (Self *bandwidth) calcWriteBandwidth() { -// // Bandwidth between nps and user, npc and application -// writeTime := Self.readStart.Sub(Self.lastReadEnd) -// Self.writeBW = float64(Self.lastBufLength) / writeTime.Seconds() -// //logs.Warn("calc write bw", Self.writeBW, Self.bufLength, writeTime.Seconds()) -//} -// -//func (Self *bandwidth) Get() (bw float64) { -// // The zero value, 0 for numeric types -// if Self.writeBW == 0 && Self.readBW == 0 { -// //logs.Warn("bw both 0") -// return 100 -// } -// if Self.writeBW == 0 && Self.readBW != 0 { -// return Self.readBW -// } -// if Self.readBW == 0 && Self.writeBW != 0 { -// return Self.writeBW -// } -// return Self.readBandwidth -//} +type writeBandwidth struct { + writeBW uint64 // store in bits, but it's float64 + readEnd time.Time + duration float64 + bufLength uint32 +} + +const writeCalcThreshold uint32 = 5 * 1024 * 1024 + +func NewWriteBandwidth() *writeBandwidth { + return &writeBandwidth{} +} + +func (Self *writeBandwidth) StartRead() { + if Self.readEnd.IsZero() { + Self.readEnd = time.Now() + } + Self.duration += time.Now().Sub(Self.readEnd).Seconds() + if Self.bufLength >= writeCalcThreshold { + Self.calcBandWidth() + } +} + +func (Self *writeBandwidth) SetCopySize(n uint16) { + Self.bufLength += uint32(n) + Self.endRead() +} + +func (Self *writeBandwidth) endRead() { + Self.readEnd = time.Now() +} + +func (Self *writeBandwidth) calcBandWidth() { + atomic.StoreUint64(&Self.writeBW, math.Float64bits(float64(Self.bufLength)/Self.duration)) + Self.bufLength = 0 + Self.duration = 0 +} + +func (Self *writeBandwidth) Get() (bw float64) { + // The zero value, 0 for numeric types + bw = math.Float64frombits(atomic.LoadUint64(&Self.writeBW)) + if bw <= 0 { + bw = 0 + } + return +} diff --git a/lib/mux/mux.go b/lib/mux/mux.go index 254945e..5b591ed 100644 --- a/lib/mux/mux.go +++ b/lib/mux/mux.go @@ -9,8 +9,8 @@ import ( "sync/atomic" "time" + "ehang.io/nps/lib/common" "github.com/astaxie/beego/logs" - "github.com/cnlh/nps/lib/common" ) type Mux struct { @@ -220,7 +220,7 @@ func (s *Mux) pingReturn() { case data = <-s.pingCh: atomic.StoreUint32(&s.pingCheckTime, 0) case <-s.closeChan: - break + return } _ = now.UnmarshalText(data) latency := time.Now().UTC().Sub(now).Seconds() / 2 @@ -303,7 +303,7 @@ func (s *Mux) readSession() { if connection.isClose { continue } - connection.sendWindow.SetSize(pack.Window, pack.ReadLength) + connection.sendWindow.SetSize(pack.Window) continue case common.MUX_CONN_CLOSE: //close the connection connection.closeFlag = true @@ -443,7 +443,7 @@ func (Self *bandwidth) Get() (bw float64) { // The zero value, 0 for numeric types bw = math.Float64frombits(atomic.LoadUint64(&Self.readBandwidth)) if bw <= 0 { - bw = 100 + bw = 0 } //logs.Warn(bw) return diff --git a/lib/mux/mux_test.go b/lib/mux/mux_test.go index fb5adb2..a3ed3fc 100644 --- a/lib/mux/mux_test.go +++ b/lib/mux/mux_test.go @@ -2,10 +2,9 @@ package mux import ( "bufio" + "ehang.io/nps/lib/common" + "ehang.io/nps/lib/goroutine" "fmt" - "github.com/cnlh/nps/lib/common" - "github.com/cnlh/nps/lib/goroutine" - "github.com/xtaci/kcp-go" "io" "log" "net" @@ -34,8 +33,8 @@ func TestNewMux(t *testing.T) { //poolConnCopy, _ := ants.NewPoolWithFunc(200000, common.copyConn, ants.WithNonblocking(false)) time.Sleep(time.Second * 3) go func() { - //m2 := NewMux(conn2, "tcp") - m2 := NewMux(conn2, "kcp") + m2 := NewMux(conn2, "tcp") + //m2 := NewMux(conn2, "kcp") for { //logs.Warn("npc starting accept") c, err := m2.Accept() @@ -84,8 +83,8 @@ func TestNewMux(t *testing.T) { }() go func() { - //m1 := NewMux(conn1, "tcp") - m1 := NewMux(conn1, "kcp") + m1 := NewMux(conn1, "tcp") + //m1 := NewMux(conn1, "kcp") l, err := net.Listen("tcp", "127.0.0.1:7777") if err != nil { logs.Warn(err) @@ -147,14 +146,14 @@ func TestNewMux(t *testing.T) { func server() { var err error - //l, err := net.Listen("tcp", "127.0.0.1:9999") - l, err := kcp.Listen("127.0.0.1:9999") + l, err := net.Listen("tcp", "127.0.0.1:9999") + //l, err := kcp.Listen("127.0.0.1:9999") if err != nil { logs.Warn(err) } go func() { conn1, err = l.Accept() - logs.Info("accept", conn1) + //logs.Info("accept", conn1) if err != nil { logs.Warn(err) } @@ -164,9 +163,9 @@ func server() { func client() { var err error - //conn2, err = net.Dial("tcp", "127.0.0.1:9999") - logs.Warn("dial") - conn2, err = kcp.Dial("127.0.0.1:9999") + conn2, err = net.Dial("tcp", "127.0.0.1:9999") + //logs.Warn("dial") + //conn2, err = kcp.Dial("127.0.0.1:9999") if err != nil { logs.Warn(err) } diff --git a/lib/mux/pmux.go b/lib/mux/pmux.go index f4e9d4a..b8de236 100644 --- a/lib/mux/pmux.go +++ b/lib/mux/pmux.go @@ -12,8 +12,8 @@ import ( "strings" "time" + "ehang.io/nps/lib/common" "github.com/astaxie/beego/logs" - "github.com/cnlh/nps/lib/common" "github.com/pkg/errors" ) diff --git a/lib/mux/queue.go b/lib/mux/queue.go index 9a62fa2..cc80407 100644 --- a/lib/mux/queue.go +++ b/lib/mux/queue.go @@ -1,8 +1,8 @@ package mux import ( + "ehang.io/nps/lib/common" "errors" - "github.com/cnlh/nps/lib/common" "io" "math" "runtime" diff --git a/lib/mux/sysGetsock_nowindows.go b/lib/mux/sysGetsock_nowindows.go index 86c78ad..85d2197 100644 --- a/lib/mux/sysGetsock_nowindows.go +++ b/lib/mux/sysGetsock_nowindows.go @@ -14,7 +14,7 @@ func sysGetSock(fd *os.File) (bufferSize int, err error) { if fd != nil { return syscall.GetsockoptInt(int(fd.Fd()), syscall.SOL_SOCKET, syscall.SO_RCVBUF) } else { - return 1400 * 320, nil + return 5 * 1024 * 1024, nil } } diff --git a/lib/mux/sysGetsock_windows.go b/lib/mux/sysGetsock_windows.go index 5cf213f..579d620 100644 --- a/lib/mux/sysGetsock_windows.go +++ b/lib/mux/sysGetsock_windows.go @@ -14,7 +14,7 @@ func sysGetSock(fd *os.File) (bufferSize int, err error) { // not support, WTF??? // Todo // return syscall.GetsockoptInt((syscall.Handle)(unsafe.Pointer(fd.Fd())), syscall.SOL_SOCKET, syscall.SO_RCVBUF) - bufferSize = 10 * 1024 * 1024 + bufferSize = 5 * 1024 * 1024 return } diff --git a/lib/version/version.go b/lib/version/version.go index c2f1489..6a4c8ab 100644 --- a/lib/version/version.go +++ b/lib/version/version.go @@ -1,8 +1,8 @@ package version -const VERSION = "0.25.4" +const VERSION = "0.26.0" // Compulsory minimum version, Minimum downward compatibility to this version func GetVersion() string { - return "0.25.0" + return "0.26.0" } diff --git a/server/connection/connection.go b/server/connection/connection.go index dbd74ca..aac1c34 100644 --- a/server/connection/connection.go +++ b/server/connection/connection.go @@ -5,9 +5,9 @@ import ( "os" "strconv" + "ehang.io/nps/lib/mux" "github.com/astaxie/beego" "github.com/astaxie/beego/logs" - "github.com/cnlh/nps/lib/mux" ) var pMux *mux.PortMux diff --git a/server/proxy/base.go b/server/proxy/base.go index 93774f3..7df5921 100644 --- a/server/proxy/base.go +++ b/server/proxy/base.go @@ -6,11 +6,11 @@ import ( "net/http" "sync" + "ehang.io/nps/bridge" + "ehang.io/nps/lib/common" + "ehang.io/nps/lib/conn" + "ehang.io/nps/lib/file" "github.com/astaxie/beego/logs" - "github.com/cnlh/nps/bridge" - "github.com/cnlh/nps/lib/common" - "github.com/cnlh/nps/lib/conn" - "github.com/cnlh/nps/lib/file" ) type Service interface { diff --git a/server/proxy/http.go b/server/proxy/http.go index 936aae3..1470c3c 100644 --- a/server/proxy/http.go +++ b/server/proxy/http.go @@ -13,13 +13,13 @@ import ( "strings" "sync" + "ehang.io/nps/bridge" + "ehang.io/nps/lib/cache" + "ehang.io/nps/lib/common" + "ehang.io/nps/lib/conn" + "ehang.io/nps/lib/file" + "ehang.io/nps/server/connection" "github.com/astaxie/beego/logs" - "github.com/cnlh/nps/bridge" - "github.com/cnlh/nps/lib/cache" - "github.com/cnlh/nps/lib/common" - "github.com/cnlh/nps/lib/conn" - "github.com/cnlh/nps/lib/file" - "github.com/cnlh/nps/server/connection" ) type httpServer struct { diff --git a/server/proxy/https.go b/server/proxy/https.go index 303b92d..3f0be1d 100644 --- a/server/proxy/https.go +++ b/server/proxy/https.go @@ -6,13 +6,13 @@ import ( "net/url" "sync" + "ehang.io/nps/lib/cache" + "ehang.io/nps/lib/common" + "ehang.io/nps/lib/conn" + "ehang.io/nps/lib/crypt" + "ehang.io/nps/lib/file" "github.com/astaxie/beego" "github.com/astaxie/beego/logs" - "github.com/cnlh/nps/lib/cache" - "github.com/cnlh/nps/lib/common" - "github.com/cnlh/nps/lib/conn" - "github.com/cnlh/nps/lib/crypt" - "github.com/cnlh/nps/lib/file" "github.com/pkg/errors" ) diff --git a/server/proxy/p2p.go b/server/proxy/p2p.go index b789ced..7c9b70f 100644 --- a/server/proxy/p2p.go +++ b/server/proxy/p2p.go @@ -5,8 +5,8 @@ import ( "strings" "time" + "ehang.io/nps/lib/common" "github.com/astaxie/beego/logs" - "github.com/cnlh/nps/lib/common" ) type P2PServer struct { diff --git a/server/proxy/socks5.go b/server/proxy/socks5.go index dd27dfd..f2ee2d5 100755 --- a/server/proxy/socks5.go +++ b/server/proxy/socks5.go @@ -7,10 +7,10 @@ import ( "net" "strconv" + "ehang.io/nps/lib/common" + "ehang.io/nps/lib/conn" + "ehang.io/nps/lib/file" "github.com/astaxie/beego/logs" - "github.com/cnlh/nps/lib/common" - "github.com/cnlh/nps/lib/conn" - "github.com/cnlh/nps/lib/file" ) const ( diff --git a/server/proxy/tcp.go b/server/proxy/tcp.go index 1f593ba..58ce3e0 100755 --- a/server/proxy/tcp.go +++ b/server/proxy/tcp.go @@ -7,13 +7,13 @@ import ( "path/filepath" "strconv" + "ehang.io/nps/bridge" + "ehang.io/nps/lib/common" + "ehang.io/nps/lib/conn" + "ehang.io/nps/lib/file" + "ehang.io/nps/server/connection" "github.com/astaxie/beego" "github.com/astaxie/beego/logs" - "github.com/cnlh/nps/bridge" - "github.com/cnlh/nps/lib/common" - "github.com/cnlh/nps/lib/conn" - "github.com/cnlh/nps/lib/file" - "github.com/cnlh/nps/server/connection" ) type TunnelModeServer struct { diff --git a/server/proxy/transport.go b/server/proxy/transport.go index d622683..e08bfd0 100644 --- a/server/proxy/transport.go +++ b/server/proxy/transport.go @@ -7,8 +7,8 @@ import ( "strconv" "syscall" - "github.com/cnlh/nps/lib/common" - "github.com/cnlh/nps/lib/conn" + "ehang.io/nps/lib/common" + "ehang.io/nps/lib/conn" ) func HandleTrans(c *conn.Conn, s *TunnelModeServer) error { diff --git a/server/proxy/transport_windows.go b/server/proxy/transport_windows.go index cf4c22d..def673b 100644 --- a/server/proxy/transport_windows.go +++ b/server/proxy/transport_windows.go @@ -3,7 +3,7 @@ package proxy import ( - "github.com/cnlh/nps/lib/conn" + "ehang.io/nps/lib/conn" ) func HandleTrans(c *conn.Conn, s *TunnelModeServer) error { diff --git a/server/proxy/udp.go b/server/proxy/udp.go index 958e3c2..abe2c7f 100755 --- a/server/proxy/udp.go +++ b/server/proxy/udp.go @@ -4,11 +4,11 @@ import ( "net" "strings" + "ehang.io/nps/bridge" + "ehang.io/nps/lib/common" + "ehang.io/nps/lib/conn" + "ehang.io/nps/lib/file" "github.com/astaxie/beego/logs" - "github.com/cnlh/nps/bridge" - "github.com/cnlh/nps/lib/common" - "github.com/cnlh/nps/lib/conn" - "github.com/cnlh/nps/lib/file" ) type UdpModeServer struct { diff --git a/server/server.go b/server/server.go index 868a94d..b1de97e 100644 --- a/server/server.go +++ b/server/server.go @@ -1,21 +1,21 @@ package server import ( + "ehang.io/nps/lib/version" "errors" - "github.com/cnlh/nps/lib/version" "math" "os" "strconv" "strings" "time" + "ehang.io/nps/bridge" + "ehang.io/nps/lib/common" + "ehang.io/nps/lib/file" + "ehang.io/nps/server/proxy" + "ehang.io/nps/server/tool" "github.com/astaxie/beego" "github.com/astaxie/beego/logs" - "github.com/cnlh/nps/bridge" - "github.com/cnlh/nps/lib/common" - "github.com/cnlh/nps/lib/file" - "github.com/cnlh/nps/server/proxy" - "github.com/cnlh/nps/server/tool" "github.com/shirou/gopsutil/cpu" "github.com/shirou/gopsutil/load" "github.com/shirou/gopsutil/mem" diff --git a/server/test/test.go b/server/test/test.go index 0a8fbfd..a30d03d 100644 --- a/server/test/test.go +++ b/server/test/test.go @@ -5,9 +5,9 @@ import ( "path/filepath" "strconv" + "ehang.io/nps/lib/common" + "ehang.io/nps/lib/file" "github.com/astaxie/beego" - "github.com/cnlh/nps/lib/common" - "github.com/cnlh/nps/lib/file" ) func TestServerConfig() { diff --git a/server/tool/utils.go b/server/tool/utils.go index fb8fa55..09dfaf7 100644 --- a/server/tool/utils.go +++ b/server/tool/utils.go @@ -5,8 +5,8 @@ import ( "strconv" "time" + "ehang.io/nps/lib/common" "github.com/astaxie/beego" - "github.com/cnlh/nps/lib/common" "github.com/shirou/gopsutil/cpu" "github.com/shirou/gopsutil/load" "github.com/shirou/gopsutil/mem" diff --git a/web/controllers/auth.go b/web/controllers/auth.go index 3b6b4c5..9eb22ca 100644 --- a/web/controllers/auth.go +++ b/web/controllers/auth.go @@ -4,8 +4,8 @@ import ( "encoding/hex" "time" + "ehang.io/nps/lib/crypt" "github.com/astaxie/beego" - "github.com/cnlh/nps/lib/crypt" ) type AuthController struct { diff --git a/web/controllers/base.go b/web/controllers/base.go index 1ba5a07..426692f 100755 --- a/web/controllers/base.go +++ b/web/controllers/base.go @@ -7,11 +7,11 @@ import ( "strings" "time" + "ehang.io/nps/lib/common" + "ehang.io/nps/lib/crypt" + "ehang.io/nps/lib/file" + "ehang.io/nps/server" "github.com/astaxie/beego" - "github.com/cnlh/nps/lib/common" - "github.com/cnlh/nps/lib/crypt" - "github.com/cnlh/nps/lib/file" - "github.com/cnlh/nps/server" ) type BaseController struct { diff --git a/web/controllers/client.go b/web/controllers/client.go index 8a3ae31..52bcee8 100644 --- a/web/controllers/client.go +++ b/web/controllers/client.go @@ -1,11 +1,11 @@ package controllers import ( + "ehang.io/nps/lib/common" + "ehang.io/nps/lib/file" + "ehang.io/nps/lib/rate" + "ehang.io/nps/server" "github.com/astaxie/beego" - "github.com/cnlh/nps/lib/common" - "github.com/cnlh/nps/lib/file" - "github.com/cnlh/nps/lib/rate" - "github.com/cnlh/nps/server" ) type ClientController struct { diff --git a/web/controllers/index.go b/web/controllers/index.go index 5b60495..e28e49a 100755 --- a/web/controllers/index.go +++ b/web/controllers/index.go @@ -1,10 +1,10 @@ package controllers import ( - "github.com/cnlh/nps/lib/file" - "github.com/cnlh/nps/server" - "github.com/cnlh/nps/server/tool" - + "ehang.io/nps/lib/file" + "ehang.io/nps/server" + "ehang.io/nps/server/tool" + "github.com/astaxie/beego" ) diff --git a/web/controllers/login.go b/web/controllers/login.go index 39c5c55..5414325 100755 --- a/web/controllers/login.go +++ b/web/controllers/login.go @@ -6,10 +6,10 @@ import ( "sync" "time" + "ehang.io/nps/lib/common" + "ehang.io/nps/lib/file" + "ehang.io/nps/server" "github.com/astaxie/beego" - "github.com/cnlh/nps/lib/common" - "github.com/cnlh/nps/lib/file" - "github.com/cnlh/nps/server" ) type LoginController struct { diff --git a/web/routers/router.go b/web/routers/router.go index 31221eb..51ab97d 100755 --- a/web/routers/router.go +++ b/web/routers/router.go @@ -1,8 +1,8 @@ package routers import ( + "ehang.io/nps/web/controllers" "github.com/astaxie/beego" - "github.com/cnlh/nps/web/controllers" ) func Init() { diff --git a/web/static/page/error.html b/web/static/page/error.html index c063fc3..90f4cf4 100644 --- a/web/static/page/error.html +++ b/web/static/page/error.html @@ -5,6 +5,6 @@ <title>nps error</title> </head> <body> -404 not found,power by <a href="//github.com/cnlh/nps">nps</a> +404 not found,power by <a href="//ehang.io/nps">nps</a> </body> </html> \ No newline at end of file diff --git a/web/views/login/index.html b/web/views/login/index.html index ffe89d0..fbe6488 100755 --- a/web/views/login/index.html +++ b/web/views/login/index.html @@ -37,7 +37,7 @@ </p> <p> - goto <a href="//github.com/cnlh/nps">nps</a> + goto <a href="//ehang.io/nps">nps</a> </p> <div class="ibox-content"> <form class="m-t" onsubmit="return false"> diff --git a/web/views/public/layout.html b/web/views/public/layout.html index a19cc62..04534f5 100755 --- a/web/views/public/layout.html +++ b/web/views/public/layout.html @@ -105,7 +105,7 @@ <ul class="nav navbar-top-links navbar-right"> <li> <span class="m-r-sm text-muted welcome-message">Welcome to use <a - href="https://github.com/cnlh/nps">NPS</a></span> + href="https://ehang.io/nps">NPS</a></span> </li> <li> <a id="lang-en">English</a> @@ -128,7 +128,7 @@ {{.LayoutContent}} <div class="footer"> <div class="pull-right"> - read more <strong><a href="https://github.com/cnlh/nps">go</a></strong> + read more <strong><a href="https://ehang.io/nps">go</a></strong> </div> <div> <strong>Copyright</strong> nps © 2018-2019