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 dbd50c5..7f14877 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,16 @@ # NPS -![](https://img.shields.io/github/stars/cnlh/nps.svg) ![](https://img.shields.io/github/forks/cnlh/nps.svg) +![](https://img.shields.io/github/stars/ehang-io/nps.svg) ![](https://img.shields.io/github/forks/ehang-io/nps.svg) [![Gitter](https://badges.gitter.im/cnlh-nps/community.svg)](https://gitter.im/cnlh-nps/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) -[![Build Status](https://travis-ci.org/cnlh/nps.svg?branch=master)](https://travis-ci.org/cnlh/nps) -![GitHub All Releases](https://img.shields.io/github/downloads/cnlh/nps/total) +[![Build Status](https://travis-ci.org/ehang-io/nps.svg?branch=master)](https://travis-ci.org/ehang-io/nps) +![GitHub All Releases](https://img.shields.io/github/downloads/ehang-io/nps/total) -[README](https://github.com/cnlh/nps/blob/master/README.md)|[中文文档](https://github.com/cnlh/nps/README_zh.md) +[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. -![image](https://github.com/cnlh/nps/blob/master/image/web.png?raw=true) +![image](https://github.com/ehang-io/nps/blob/master/image/web.png?raw=true) ## Feature @@ -24,13 +24,13 @@ NPS is a lightweight, high-performance, powerful **intranet penetration** proxy - 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. -**Didn't find the feature you want? It doesn't matter, click [Enter the document](https://cnlh.github.io/nps/) to find it!** +**Didn't find the feature you want? It doesn't matter, click [Enter the document](https://ehang-io.github.io/nps/) to find it!** ## Quick start ### Installation -> [releases](https://github.com/cnlh/nps/releases) +> [releases](https://github.com/ehang-io/nps/releases) Download the corresponding system version, the server and client are separate. @@ -62,11 +62,12 @@ For windows, run cmd as administrator and enter the program directory ```nps.exe - 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. -If you need to register to the system service, you can check [Register to the system service](https://cnlh.github.io/nps/#/use?id=注册到系统服务) + +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://cnlh.github.io/nps/) +- 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. diff --git a/README_zh.md b/README_zh.md index 64a1c47..008d469 100644 --- a/README_zh.md +++ b/README_zh.md @@ -1,17 +1,17 @@ # nps -![](https://img.shields.io/github/stars/cnlh/nps.svg) ![](https://img.shields.io/github/forks/cnlh/nps.svg) +![](https://img.shields.io/github/stars/ehang-io/nps.svg) ![](https://img.shields.io/github/forks/ehang-io/nps.svg) [![Gitter](https://badges.gitter.im/cnlh-nps/community.svg)](https://gitter.im/cnlh-nps/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) -[![Build Status](https://travis-ci.org/cnlh/nps.svg?branch=master)](https://travis-ci.org/cnlh/nps) -![GitHub All Releases](https://img.shields.io/github/downloads/cnlh/nps/total) +[![Build Status](https://travis-ci.org/ehang-io/nps.svg?branch=master)](https://travis-ci.org/ehang-io/nps) +![GitHub All Releases](https://img.shields.io/github/downloads/ehang-io/nps/total) -[README](https://github.com/cnlh/nps/blob/master/README.md)|[中文文档](https://github.com/cnlh/nps/README_zh.md) +[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管理端。 ## 背景 -![image](https://github.com/cnlh/nps/blob/master/image/web.png?raw=true) +![image](https://github.com/ehang-io/nps/blob/master/image/web.png?raw=true) 1. 做微信公众号开发、小程序开发等----> 域名代理模式 @@ -33,11 +33,11 @@ nps是一款轻量级、高性能、功能强大的**内网穿透**代理服务 - 域名解析具备自定义header、404页面配置、host修改、站点保护、URL路由、泛解析等功能 - 服务端支持多用户和用户注册功能 -**没找到你想要的功能?不要紧,点击[进入文档](https://cnlh.github.io/nps/)查找吧** +**没找到你想要的功能?不要紧,点击[进入文档](https://ehang-io.github.io/nps)查找吧** ## 快速开始 ### 安装 -> [releases](https://github.com/cnlh/nps/releases) +> [releases](https://github.com/ehang-io/nps/releases) 下载对应的系统版本即可,服务端和客户端是单独的 @@ -67,11 +67,11 @@ nps是一款轻量级、高性能、功能强大的**内网穿透**代理服务 - 点击web管理中客户端前的+号,复制启动命令 - 执行启动命令,linux直接执行即可,windows将./npc换成npc.exe用cmd执行 -如果需要注册到系统服务可查看[注册到系统服务](https://cnlh.github.io/nps/#/use?id=注册到系统服务) +如果需要注册到系统服务可查看[注册到系统服务](https://ehang-io.github.io/nps/#/use?id=注册到系统服务) ### 配置 - 客户端连接后,在web中配置对应穿透服务即可 -- 更多高级用法见[完整文档](https://cnlh.github.io/nps/) +- 更多高级用法见[完整文档](https://ehang-io.github.io/nps/) ## 贡献 - 如果遇到bug可以直接提交至dev分支 diff --git a/bridge/bridge.go b/bridge/bridge.go index 7894b66..8ee385e 100755 --- a/bridge/bridge.go +++ b/bridge/bridge.go @@ -1,6 +1,7 @@ package bridge import ( + "ehang.io/nps-mux" "encoding/binary" "errors" "fmt" @@ -11,27 +12,26 @@ 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/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 { - tunnel *mux.Mux + tunnel *nps_mux.Mux signal *conn.Conn - file *mux.Mux + file *nps_mux.Mux Version string retryTime int // it will be add 1 when ping not ok until to 3 will close the client } -func NewClient(t, f *mux.Mux, s *conn.Conn, vs string) *Client { +func NewClient(t, f *nps_mux.Mux, s *conn.Conn, vs string) *Client { return &Client{ signal: s, tunnel: t, @@ -242,7 +242,7 @@ func (s *Bridge) typeDeal(typeVal string, c *conn.Conn, id int, vs string) { go s.GetHealthFromClient(id, c) logs.Info("clientId %d connection succeeded, address:%s ", id, c.Conn.RemoteAddr()) case common.WORK_CHAN: - muxConn := mux.NewMux(c.Conn, s.tunnelType) + muxConn := nps_mux.NewMux(c.Conn, s.tunnelType) if v, ok := s.Client.LoadOrStore(id, NewClient(muxConn, nil, nil, vs)); ok { v.(*Client).tunnel = muxConn } @@ -263,7 +263,7 @@ func (s *Bridge) typeDeal(typeVal string, c *conn.Conn, id int, vs string) { logs.Error("secret error, failed to match the key successfully") } case common.WORK_FILE: - muxConn := mux.NewMux(c.Conn, s.tunnelType) + muxConn := nps_mux.NewMux(c.Conn, s.tunnelType) if v, ok := s.Client.LoadOrStore(id, NewClient(nil, muxConn, nil, vs)); ok { v.(*Client).file = muxConn } @@ -321,7 +321,7 @@ func (s *Bridge) SendLinkInfo(clientId int, link *conn.Link, t *file.Tunnel) (ta } } } - var tunnel *mux.Mux + var tunnel *nps_mux.Mux if t != nil && t.Mode == "file" { tunnel = v.(*Client).file } else { 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/client/client.go b/client/client.go index 7a6f1da..99801f2 100755 --- a/client/client.go +++ b/client/client.go @@ -3,6 +3,7 @@ package client import ( "bufio" "bytes" + "ehang.io/nps-mux" "net" "net/http" "strconv" @@ -11,11 +12,10 @@ 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" ) type TRPClient struct { @@ -24,7 +24,7 @@ type TRPClient struct { proxyUrl string vKey string p2pAddr map[string]string - tunnel *mux.Mux + tunnel *nps_mux.Mux signal *conn.Conn ticker *time.Ticker cnf *config.Config @@ -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 @@ -137,7 +138,7 @@ func (s *TRPClient) newUdpConn(localAddr, rAddr string, md5Password string) { conn.SetUdpSession(udpTunnel) logs.Trace("successful connection with client ,address %s", udpTunnel.RemoteAddr().String()) //read link info from remote - conn.Accept(mux.NewMux(udpTunnel, s.bridgeConnType), func(c net.Conn) { + conn.Accept(nps_mux.NewMux(udpTunnel, s.bridgeConnType), func(c net.Conn) { go s.handleChan(c) }) break @@ -145,14 +146,14 @@ func (s *TRPClient) newUdpConn(localAddr, rAddr string, md5Password string) { } } -//mux tunnel +//pmux tunnel func (s *TRPClient) newChan() { tunnel, err := NewConn(s.bridgeConnType, s.vKey, s.svrAddr, common.WORK_CHAN, s.proxyUrl) if err != nil { logs.Error("connect to ", s.svrAddr, "error:", err) return } - s.tunnel = mux.NewMux(tunnel.Conn, s.bridgeConnType) + s.tunnel = nps_mux.NewMux(tunnel.Conn, s.bridgeConnType) for { src, err := s.tunnel.Accept() if err != nil { 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..b5b1319 100644 --- a/client/local.go +++ b/client/local.go @@ -1,6 +1,7 @@ package client import ( + "ehang.io/nps-mux" "errors" "net" "net/http" @@ -8,21 +9,20 @@ 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/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" ) var ( LocalServer []*net.TCPListener udpConn net.Conn - muxSession *mux.Mux + muxSession *nps_mux.Mux fileServer []*http.Server p2pNetBridge *p2pBridge lock sync.RWMutex @@ -73,7 +73,7 @@ func startLocalFileServer(config *config.CommonConfig, t *file.Tunnel, vkey stri } logs.Info("start local file system, local path %s, strip prefix %s ,remote port %s ", t.LocalPath, t.StripPre, t.Ports) fileServer = append(fileServer, srv) - listener := mux.NewMux(remoteConn.Conn, common.CONN_TCP) + listener := nps_mux.NewMux(remoteConn.Conn, common.CONN_TCP) logs.Error(srv.Serve(listener)) } @@ -214,6 +214,6 @@ func newUdpConn(localAddr string, config *config.CommonConfig, l *config.LocalSe logs.Trace("successful create a connection with server", remoteAddress) conn.SetUdpSession(udpTunnel) udpConn = udpTunnel - muxSession = mux.NewMux(udpConn, "kcp") + muxSession = nps_mux.NewMux(udpConn, "kcp") p2pNetBridge = &p2pBridge{} } 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/conf/nps.conf b/conf/nps.conf index 01f3e27..cee576f 100755 --- a/conf/nps.conf +++ b/conf/nps.conf @@ -49,7 +49,8 @@ web_key_file=conf/server.key #web_base_url=/nps #Web API unauthenticated IP address(the len of auth_crypt_key must be 16) -auth_key=test +#Remove comments if needed +#auth_key=test auth_crypt_key =1234567812345678 #allow_ports=9001-9009,10001,11000-12000 @@ -73,4 +74,5 @@ system_info_display=false http_cache=false http_cache_length=100 - +#get origin ip +http_add_origin_header=false 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是一款轻量级、高性能、功能强大的**内网穿透**代理服务 ## 背景 -![image](https://github.com/cnlh/nps/blob/master/image/web.png?raw=true) +![image](https://github.com/ehang-io/nps/blob/master/image/web.png?raw=true) 1. 做微信公众号开发、小程序开发等----> 域名代理模式 diff --git a/docs/_coverpage.md b/docs/_coverpage.md index 652591b..9bcc15a 100644 --- a/docs/_coverpage.md +++ b/docs/_coverpage.md @@ -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..f4c6b9a 100644 --- a/docs/api.md +++ b/docs/api.md @@ -1,4 +1,6 @@ # web api + +需要开启请先去掉`nps.conf`中`auth_key`的注释并配置一个合适的密钥 ## webAPI验证说明 - 采用auth_key的验证方式 - 在提交的每个请求后面附带两个参数,`auth_key` 和`timestamp` @@ -43,4 +45,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/description.md b/docs/description.md index 72e69b3..bdc0257 100644 --- a/docs/description.md +++ b/docs/description.md @@ -1,5 +1,6 @@ # 说明 ## 获取用户真实ip +如需使用需要在`nps.conf`中设置`http_add_origin_header=true` 在域名代理模式中,可以通过request请求 header 中的 X-Forwarded-For 和 X-Real-IP 来获取用户真实 IP。 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更好的发展。 ## 支付宝 -![image](https://github.com/cnlh/nps/blob/master/image/donation_zfb.png?raw=true) +![image](https://github.com/ehang-io/nps/blob/master/image/donation_zfb.png?raw=true) ## 微信 -![image](https://github.com/cnlh/nps/blob/master/image/donation_wx.png?raw=true) +![image](https://github.com/ehang-io/nps/blob/master/image/donation_wx.png?raw=true) 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 @@ -![image](https://github.com/cnlh/nps/blob/master/image/web2.png?raw=true) +![image](https://github.com/ehang-io/nps/blob/master/image/web2.png?raw=true) # 介绍 可在网页上配置和管理各个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..5bb6634 100644 --- a/go.mod +++ b/go.mod @@ -1,33 +1,26 @@ -module github.com/cnlh/nps +module ehang.io/nps go 1.13 require ( + ehang.io/nps-mux v0.0.0-20200109142326-674a17784f79 fyne.io/fyne v1.2.0 - github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect github.com/astaxie/beego v1.12.0 - github.com/bradfitz/iter v0.0.0-20190303215204-33e6a9893b0c // indirect github.com/c4milo/unpackit v0.0.0-20170704181138-4ed373e9ef1c github.com/ccding/go-stun v0.0.0-20180726100737-be486d185f3d - github.com/dsnet/compress v0.0.1 // indirect - github.com/go-ole/go-ole v1.2.4 // indirect github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db - github.com/hooklift/assert v0.0.0-20170704181755-9d1defd6d214 // indirect github.com/kardianos/service v1.0.0 - github.com/klauspost/cpuid v1.2.1 // indirect - github.com/klauspost/pgzip v1.2.1 // indirect - github.com/klauspost/reedsolomon v1.9.2 // indirect + github.com/klauspost/cpuid v1.2.2 // indirect + github.com/klauspost/reedsolomon v1.9.3 // indirect github.com/panjf2000/ants/v2 v2.2.2 github.com/pkg/errors v0.8.1 - github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 // indirect github.com/shirou/gopsutil v2.19.11+incompatible - github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 // indirect - github.com/templexxx/xor v0.0.0-20181023030647-4e92f724b73b // indirect - github.com/tjfoc/gmsm v1.0.1 // indirect - github.com/xtaci/kcp-go v5.4.4+incompatible - github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae // indirect - golang.org/x/net v0.0.0-20181220203305-927f97764cc3 - golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa // indirect + github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b // indirect + github.com/tjfoc/gmsm v1.2.0 // indirect + github.com/xtaci/kcp-go v5.4.20+incompatible + golang.org/x/crypto v0.0.0-20200108215511-5d647ca15757 // indirect + golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 + golang.org/x/sys v0.0.0-20200107162124-548cf772de50 // indirect ) replace github.com/astaxie/beego => github.com/exfly/beego v1.12.0-export-init diff --git a/go.sum b/go.sum index a1c8f67..49b9e98 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +ehang.io/nps-mux v0.0.0-20200109142326-674a17784f79 h1:pvraJv3v71ETX0y3GZpCLeY5R4dxGh5sAU2zWu4F22s= +ehang.io/nps-mux v0.0.0-20200109142326-674a17784f79/go.mod h1:wcLC4LlVaSnuwxT2tdsxWii75vZMYWDx3cL6WVN6COE= fyne.io/fyne v1.2.0 h1:mdp7Cs7QmSJTeazYxEDa9wWeJNig7paBcjm0dooFtLE= fyne.io/fyne v1.2.0/go.mod h1:Ab+3DIB/FVteW0y4DXfmZv4N3JdnCBh2lHkINI02BOU= github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= @@ -17,6 +19,7 @@ github.com/casbin/casbin v1.7.0/go.mod h1:c67qKN6Oum3UF5Q1+BByfFxkwKvhwW57ITjqwt github.com/ccding/go-stun v0.0.0-20180726100737-be486d185f3d h1:As4937T5NVbJ/DmZT9z33pyLEprMd6CUSfhbmMY57Io= github.com/ccding/go-stun v0.0.0-20180726100737-be486d185f3d/go.mod h1:3FK1bMar37f7jqVY7q/63k3OMX1c47pGCufzt3X0sYE= github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80= +github.com/cnlh/nps v0.26.0/go.mod h1:ra/6/iO2zNYg12P7oxQtTu/yNVUsa4JdJplPZ2lkvM8= github.com/couchbase/go-couchbase v0.0.0-20181122212707-3e9b6e1258bb/go.mod h1:TWI8EKQMs5u5jLKW/tsb9VwauIrMIxQG1r5fMsswK5U= github.com/couchbase/gomemcached v0.0.0-20181122193126-5125a94a666c/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c= github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs= @@ -58,10 +61,14 @@ github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0 github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid v1.2.1 h1:vJi+O/nMdFt0vqm8NZBI6wzALWdA2X+egi0ogNyrC/w= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid v1.2.2 h1:1xAgYebNnsb9LKCdLOvFWtAxGU/33mjJtyOVbmUa0Us= +github.com/klauspost/cpuid v1.2.2/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/pgzip v1.2.1 h1:oIPZROsWuPHpOdMVWLuJZXwgjhrW8r1yEX8UqMyeNHM= github.com/klauspost/pgzip v1.2.1/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/klauspost/reedsolomon v1.9.2 h1:E9CMS2Pqbv+C7tsrYad4YC9MfhnMVWhMRsTi7U0UB18= github.com/klauspost/reedsolomon v1.9.2/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4= +github.com/klauspost/reedsolomon v1.9.3 h1:N/VzgeMfHmLc+KHMD1UL/tNkfXAt8FnUqlgXGIduwAY= +github.com/klauspost/reedsolomon v1.9.3/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= @@ -97,17 +104,27 @@ github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 h1:89CEmDvlq/F7S github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU= github.com/templexxx/xor v0.0.0-20181023030647-4e92f724b73b h1:mnG1fcsIB1d/3vbkBak2MM0u+vhGhlQwpeimUi7QncM= github.com/templexxx/xor v0.0.0-20181023030647-4e92f724b73b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4= +github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b h1:fj5tQ8acgNUr6O8LEplsxDhUIe2573iLkJc+PqnzZTI= +github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4= github.com/tjfoc/gmsm v1.0.1 h1:R11HlqhXkDospckjZEihx9SW/2VW0RgdwrykyWMFOQU= github.com/tjfoc/gmsm v1.0.1/go.mod h1:XxO4hdhhrzAd+G4CjDqaOkd0hUzmtPR/d3EiBBMn/wc= +github.com/tjfoc/gmsm v1.2.0 h1:oTXUFetR8GphwGmUUxWFxrRZJTaDcZo1Lt2mRxlVzEI= +github.com/tjfoc/gmsm v1.2.0/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w= github.com/ulikunitz/xz v0.5.6 h1:jGHAfXawEGZQ3blwU5wnWKQJvAraT7Ftq9EXjnXYgt8= github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc= github.com/xtaci/kcp-go v5.4.4+incompatible h1:QIJ0a0Q0N1G20yLHL2+fpdzyy2v/Cb3PI+xiwx/KK9c= github.com/xtaci/kcp-go v5.4.4+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE= +github.com/xtaci/kcp-go v5.4.20+incompatible h1:TN1uey3Raw0sTz0Fg8GkfM0uH3YwzhnZWQ1bABv5xAg= +github.com/xtaci/kcp-go v5.4.20+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE= github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae h1:J0GxkO96kL4WF+AIT3M4mfUVinOCPgf2uUWYFUzN0sM= github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE= golang.org/x/crypto v0.0.0-20181127143415-eb0de9b17e85 h1:et7+NAX3lLIk5qUCTA9QelBjGE/NkhzYw/mhnr0s7nI= golang.org/x/crypto v0.0.0-20181127143415-eb0de9b17e85/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200108215511-5d647ca15757 h1:pJ9H8lzdBh301qPX4VpwJ8TRpLt1IhNK1PxVOICyP54= +golang.org/x/crypto v0.0.0-20200108215511-5d647ca15757/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8 h1:idBdZTd9UioThJp8KpM/rTSinK/ChZFBE43/WtIy8zg= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= @@ -119,11 +136,18 @@ golang.org/x/net v0.0.0-20181114220301-adae6a3d119a h1:gOpx8G595UYyvj8UK4+OFyY4r golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3 h1:eH6Eip3UpmR+yM/qI9Ijluzb1bNv/cAU/n+6l8tRSis= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa h1:KIDDMLT1O0Nr7TSxp8xM5tJcdn8tgyAONntO829og1M= golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200107162124-548cf772de50 h1:YvQ10rzcqWXLlJZ3XCUoO25savxmscf4+SC+ZqiCHhA= +golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + 页-1 + + + + + + + + + + + + + + + + + + + + + + + + 防火墙 + NAT + + 工作表.2 + + + + 工作表.3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NAT + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 服务器 + Application2 10.0.0.4:PORT + + 工作表.5 + + + + 工作表.6 + + + + 工作表.7 + + + + + + + + + + Application210.0.0.4:PORT + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 服务器.8 + Application1 10.0.0.3:PORT + + 工作表.9 + + + + 工作表.10 + + + + 工作表.11 + + + + + + + + + + Application110.0.0.3:PORT + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 服务器.12 + Application3 10.0.0.5:PORT + + 工作表.13 + + + + 工作表.14 + + + + 工作表.15 + + + + + + + + + + Application310.0.0.5:PORT + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 主机 + NPC Client 10.0.0.2 Dial To: ->10.0.0.3:PORT ->10.0.0.4:PORT ... + + 工作表.17 + + + + + + 工作表.18 + + + + + + + + 工作表.19 + + + + + + NPCClient10.0.0.2Dial To:->10.0.0.3:PORT->10.0.0.4:PORT->10.0.0.5:PORT + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 主机.20 + NPS Server 1.1.1.1 Listen On: 8003->10.0.0.3:PORT 8004->10.0.... + + 工作表.21 + + + + + + 工作表.22 + + + + + + + + 工作表.23 + + + + + + NPSServer1.1.1.1Listen On:8003->10.0.0.3:PORT8004->10.0.0.4:PORT8005->10.0.0.5:PORT + + + + + + + + + + + + + + + + + + 用户 + User1 Wants:APP1 + + 工作表.25 + + + + + + User1Wants:APP1 + + + + + + + + + + + + + + + + + + 用户.26 + User2 Wants:APP2 + + 工作表.27 + + + + + + User2Wants:APP2 + + + + + + + + + + + + + + + + + + 用户.28 + User3 Wants:APP3 + + 工作表.29 + + + + + + User3Wants:APP3 + + + 动态连接线.1003 + ->8003 Multi Conn + + + + + + + + ->8003Multi Conn + + 动态连接线.1004 + ->8004 Multi Conn + + + + + + + + ->8004Multi Conn + + 动态连接线.1005 + ->8005 Multi Conn + + + + + + + + ->8005Multi Conn + + 动态连接线.1006 + NPS & NPC Multiplexing Connection TCP or KCP Only One Conn Pe... + + + + + + + + NPS & NPCMultiplexingConnectionTCP or KCPOnly OneConn PeerNPC + + 动态连接线.1007 + ->PORT Multi Conn + + + + + + + + ->PORTMulti Conn + + 动态连接线.1008 + ->PORT Multi Conn + + + + + + + + ->PORTMulti Conn + + 动态连接线.1009 + ->PORT Multi Conn + + + + + + + + ->PORTMulti Conn + + 动态连接线.1010 + NPS & NPC + + + + + + + + NPS&NPC + + 工作表.1011 + + + + 工作表.1012 + + + + 工作表.1013 + Internet + + + + Internet + + 工作表.1014 + Intranet + + + + Intranet + + diff --git a/lib/common/const.go b/lib/common/const.go index 2f195f3..ffb2fa6 100644 --- a/lib/common/const.go +++ b/lib/common/const.go @@ -36,19 +36,3 @@ WWW-Authenticate: Basic realm="easyProxy" ` ) - -const ( - MUX_PING_FLAG uint8 = iota - MUX_NEW_CONN_OK - MUX_NEW_CONN_Fail - MUX_NEW_MSG - MUX_NEW_MSG_PART - MUX_MSG_SEND_OK - MUX_NEW_CONN - MUX_CONN_CLOSE - MUX_PING_RETURN - MUX_PING int32 = -1 - MAXIMUM_SEGMENT_SIZE = PoolSizeWindow - 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 45456c5..b54121f 100644 --- a/lib/common/netpackager.go +++ b/lib/common/netpackager.go @@ -3,13 +3,11 @@ package common import ( "bytes" "encoding/binary" - "encoding/json" "errors" "io" "io/ioutil" "net" "strconv" - "strings" ) type NetPackager interface { @@ -17,222 +15,6 @@ type NetPackager interface { UnPack(reader io.Reader) (err error) } -type BasePackager struct { - Length uint16 - Content []byte -} - -func (Self *BasePackager) NewPac(contents ...interface{}) (err error) { - Self.clean() - for _, content := range contents { - switch content.(type) { - case nil: - Self.Content = Self.Content[:0] - case []byte: - err = Self.appendByte(content.([]byte)) - case string: - err = Self.appendByte([]byte(content.(string))) - if err != nil { - return - } - err = Self.appendByte([]byte(CONN_DATA_SEQ)) - default: - err = Self.marshal(content) - } - } - Self.setLength() - if Self.Length > MAXIMUM_SEGMENT_SIZE { - err = errors.New("mux:packer: newpack content segment too large") - } - return -} - -func (Self *BasePackager) appendByte(data []byte) (err error) { - m := len(Self.Content) - n := m + len(data) - if n <= cap(Self.Content) { - Self.Content = Self.Content[0:n] // grow the length for copy - copy(Self.Content[m:n], data) - return nil - } else { - return errors.New("pack content too large") - } -} - -//似乎这里涉及到父类作用域问题,当子类调用父类的方法时,其struct仅仅为父类的 -func (Self *BasePackager) Pack(writer io.Writer) (err error) { - err = binary.Write(writer, binary.LittleEndian, Self.Length) - if err != nil { - return - } - err = binary.Write(writer, binary.LittleEndian, Self.Content) - return -} - -//Unpack 会导致传入的数字类型转化成float64!! -//主要原因是json unmarshal并未传入正确的数据类型 -func (Self *BasePackager) UnPack(reader io.Reader) (n uint16, err error) { - Self.clean() - n += 2 // uint16 - err = binary.Read(reader, binary.LittleEndian, &Self.Length) - if err != nil { - return - } - if int(Self.Length) > cap(Self.Content) { - err = errors.New("unpack err, content length too large") - return - } - if Self.Length > MAXIMUM_SEGMENT_SIZE { - err = errors.New("mux:packer: unpack content segment too large") - return - } - Self.Content = Self.Content[:int(Self.Length)] - //n, err := io.ReadFull(reader, Self.Content) - //if n != int(Self.Length) { - // err = io.ErrUnexpectedEOF - //} - err = binary.Read(reader, binary.LittleEndian, Self.Content) - n += Self.Length - return -} - -func (Self *BasePackager) marshal(content interface{}) (err error) { - tmp, err := json.Marshal(content) - if err != nil { - return err - } - err = Self.appendByte(tmp) - return -} - -func (Self *BasePackager) Unmarshal(content interface{}) (err error) { - err = json.Unmarshal(Self.Content, content) - if err != nil { - return err - } - return -} - -func (Self *BasePackager) setLength() { - Self.Length = uint16(len(Self.Content)) - return -} - -func (Self *BasePackager) clean() { - Self.Length = 0 - Self.Content = Self.Content[:0] // reset length -} - -func (Self *BasePackager) Split() (strList []string) { - n := bytes.IndexByte(Self.Content, 0) - strList = strings.Split(string(Self.Content[:n]), CONN_DATA_SEQ) - strList = strList[0 : len(strList)-1] - return -} - -type ConnPackager struct { - // Todo - ConnType uint8 - BasePackager -} - -func (Self *ConnPackager) NewPac(connType uint8, content ...interface{}) (err error) { - Self.ConnType = connType - err = Self.BasePackager.NewPac(content...) - return -} - -func (Self *ConnPackager) Pack(writer io.Writer) (err error) { - err = binary.Write(writer, binary.LittleEndian, Self.ConnType) - if err != nil { - return - } - err = Self.BasePackager.Pack(writer) - return -} - -func (Self *ConnPackager) UnPack(reader io.Reader) (n uint16, err error) { - err = binary.Read(reader, binary.LittleEndian, &Self.ConnType) - if err != nil && err != io.EOF { - return - } - n, err = Self.BasePackager.UnPack(reader) - n += 2 - return -} - -type MuxPackager struct { - Flag uint8 - Id int32 - Window uint64 - BasePackager -} - -func (Self *MuxPackager) NewPac(flag uint8, id int32, content ...interface{}) (err error) { - Self.Flag = flag - Self.Id = id - switch flag { - case MUX_PING_FLAG, MUX_PING_RETURN, MUX_NEW_MSG, MUX_NEW_MSG_PART: - Self.Content = WindowBuff.Get() - err = Self.BasePackager.NewPac(content...) - //logs.Warn(Self.Length, string(Self.Content)) - case MUX_MSG_SEND_OK: - // MUX_MSG_SEND_OK contains one data - Self.Window = content[0].(uint64) - } - return -} - -func (Self *MuxPackager) Pack(writer io.Writer) (err error) { - err = binary.Write(writer, binary.LittleEndian, Self.Flag) - if err != nil { - return - } - err = binary.Write(writer, binary.LittleEndian, Self.Id) - if err != nil { - return - } - switch Self.Flag { - case MUX_NEW_MSG, MUX_NEW_MSG_PART, MUX_PING_FLAG, MUX_PING_RETURN: - err = Self.BasePackager.Pack(writer) - WindowBuff.Put(Self.Content) - case MUX_MSG_SEND_OK: - err = binary.Write(writer, binary.LittleEndian, Self.Window) - } - return -} - -func (Self *MuxPackager) UnPack(reader io.Reader) (n uint16, err error) { - err = binary.Read(reader, binary.LittleEndian, &Self.Flag) - if err != nil { - return - } - err = binary.Read(reader, binary.LittleEndian, &Self.Id) - if err != nil { - return - } - switch Self.Flag { - case MUX_NEW_MSG, MUX_NEW_MSG_PART, MUX_PING_FLAG, MUX_PING_RETURN: - Self.Content = WindowBuff.Get() // need get a window buf from pool - Self.BasePackager.clean() // also clean the content - n, err = Self.BasePackager.UnPack(reader) - //logs.Warn("unpack", Self.Length, string(Self.Content)) - case MUX_MSG_SEND_OK: - err = binary.Read(reader, binary.LittleEndian, &Self.Window) - n += 8 // uint64 - } - n += 5 //uint8 int32 - return -} - -func (Self *MuxPackager) reset() { - Self.Id = 0 - Self.Flag = 0 - Self.Length = 0 - Self.Content = nil - Self.Window = 0 -} - const ( ipV4 = 1 domainName = 3 diff --git a/lib/common/pool.go b/lib/common/pool.go index 31931f9..8a487aa 100644 --- a/lib/common/pool.go +++ b/lib/common/pool.go @@ -1,7 +1,6 @@ package common import ( - "bytes" "sync" ) @@ -9,8 +8,6 @@ const PoolSize = 64 * 1024 const PoolSizeSmall = 100 const PoolSizeUdp = 1472 + 200 const PoolSizeCopy = 32 << 10 -const PoolSizeBuffer = 4096 -const PoolSizeWindow = PoolSizeBuffer - 2 - 4 - 4 - 1 var BufPool = sync.Pool{ New: func() interface{} { @@ -86,115 +83,11 @@ func (Self *copyBufferPool) Put(x []byte) { } } -type windowBufferPool struct { - pool sync.Pool -} - -func (Self *windowBufferPool) New() { - Self.pool = sync.Pool{ - New: func() interface{} { - return make([]byte, PoolSizeWindow) - }, - } -} - -func (Self *windowBufferPool) Get() (buf []byte) { - buf = Self.pool.Get().([]byte) - buf = buf[:PoolSizeWindow] - return buf -} - -func (Self *windowBufferPool) Put(x []byte) { - x = x[:0] // clean buf - Self.pool.Put(x) -} - -type bufferPool struct { - pool sync.Pool -} - -func (Self *bufferPool) New() { - Self.pool = sync.Pool{ - New: func() interface{} { - return bytes.NewBuffer(make([]byte, 0, PoolSizeBuffer)) - }, - } -} - -func (Self *bufferPool) Get() *bytes.Buffer { - return Self.pool.Get().(*bytes.Buffer) -} - -func (Self *bufferPool) Put(x *bytes.Buffer) { - x.Reset() - Self.pool.Put(x) -} - -type muxPackagerPool struct { - pool sync.Pool -} - -func (Self *muxPackagerPool) New() { - Self.pool = sync.Pool{ - New: func() interface{} { - pack := MuxPackager{} - return &pack - }, - } -} - -func (Self *muxPackagerPool) Get() *MuxPackager { - return Self.pool.Get().(*MuxPackager) -} - -func (Self *muxPackagerPool) Put(pack *MuxPackager) { - pack.reset() - Self.pool.Put(pack) -} - -type ListElement struct { - Buf []byte - L uint16 - Part bool -} - -type listElementPool struct { - pool sync.Pool -} - -func (Self *listElementPool) New() { - Self.pool = sync.Pool{ - New: func() interface{} { - element := ListElement{} - return &element - }, - } -} - -func (Self *listElementPool) Get() *ListElement { - return Self.pool.Get().(*ListElement) -} - -func (Self *listElementPool) Put(element *ListElement) { - element.L = 0 - element.Buf = nil - element.Part = false - Self.pool.Put(element) -} - var once = sync.Once{} -var BuffPool = bufferPool{} var CopyBuff = copyBufferPool{} -var MuxPack = muxPackagerPool{} -var WindowBuff = windowBufferPool{} -var ListElementPool = listElementPool{} func newPool() { - BuffPool.New() CopyBuff.New() - MuxPack.New() - WindowBuff.New() - ListElementPool.New() } func init() { diff --git a/lib/common/util.go b/lib/common/util.go index 1db0d27..dce3c8b 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 @@ -98,7 +98,7 @@ func Getverifyval(vkey string) string { } //Change headers and host of request -func ChangeHostAndHeader(r *http.Request, host string, header string, addr string) { +func ChangeHostAndHeader(r *http.Request, host string, header string, addr string,addOrigin bool) { if host != "" { r.Host = host } @@ -115,8 +115,10 @@ func ChangeHostAndHeader(r *http.Request, host string, header string, addr strin if prior, ok := r.Header["X-Forwarded-For"]; ok { addr = strings.Join(prior, ", ") + ", " + addr } - r.Header.Set("X-Forwarded-For", addr) - r.Header.Set("X-Real-IP", addr) + if addOrigin { + r.Header.Set("X-Forwarded-For", addr) + r.Header.Set("X-Real-IP", addr) + } } //Read file content by file path 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..cf29acb 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/pmux" + "ehang.io/nps/lib/rate" "github.com/xtaci/kcp-go" ) @@ -126,8 +126,8 @@ func (s *Conn) SetAlive(tp string) { conn.SetReadDeadline(time.Time{}) //conn.SetKeepAlive(false) //conn.SetKeepAlivePeriod(time.Duration(2 * time.Second)) - case *mux.PortConn: - s.Conn.(*mux.PortConn).SetReadDeadline(time.Time{}) + case *pmux.PortConn: + s.Conn.(*pmux.PortConn).SetReadDeadline(time.Time{}) } } @@ -138,8 +138,8 @@ func (s *Conn) SetReadDeadlineBySecond(t time.Duration) { s.Conn.(*kcp.UDPSession).SetReadDeadline(time.Now().Add(time.Duration(t) * time.Second)) case *net.TCPConn: s.Conn.(*net.TCPConn).SetReadDeadline(time.Now().Add(time.Duration(t) * time.Second)) - case *mux.PortConn: - s.Conn.(*mux.PortConn).SetReadDeadline(time.Now().Add(time.Duration(t) * time.Second)) + case *pmux.PortConn: + s.Conn.(*pmux.PortConn).SetReadDeadline(time.Now().Add(time.Duration(t) * time.Second)) } } 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/bytes.go b/lib/mux/bytes.go deleted file mode 100644 index c44bad4..0000000 --- a/lib/mux/bytes.go +++ /dev/null @@ -1,32 +0,0 @@ -package mux - -import ( - "bytes" - "encoding/binary" - "io" -) - -//write bytes with int32 length -func WriteLenBytes(buf []byte, w io.Writer) (int, error) { - raw := bytes.NewBuffer([]byte{}) - if err := binary.Write(raw, binary.LittleEndian, int32(len(buf))); err != nil { - return 0, err - } - if err := binary.Write(raw, binary.LittleEndian, buf); err != nil { - return 0, err - } - return w.Write(raw.Bytes()) -} - -//read bytes by length -func ReadLenBytes(buf []byte, r io.Reader) (int, error) { - var l uint32 - var err error - if binary.Read(r, binary.LittleEndian, &l) != nil { - return 0, err - } - if _, err = io.ReadFull(r, buf[:l]); err != nil { - return 0, err - } - return int(l), nil -} diff --git a/lib/mux/conn.go b/lib/mux/conn.go deleted file mode 100644 index 6d65f7c..0000000 --- a/lib/mux/conn.go +++ /dev/null @@ -1,666 +0,0 @@ -package mux - -import ( - "errors" - "github.com/astaxie/beego/logs" - "github.com/cnlh/nps/lib/common" - "io" - "math" - "net" - "runtime" - "sync" - "sync/atomic" - "time" -) - -type conn struct { - net.Conn - getStatusCh chan struct{} - connStatusOkCh chan struct{} - connStatusFailCh chan struct{} - connId int32 - isClose bool - closeFlag bool // close conn flag - receiveWindow *ReceiveWindow - sendWindow *SendWindow - once sync.Once - //label string -} - -func NewConn(connId int32, mux *Mux, label ...string) *conn { - c := &conn{ - getStatusCh: make(chan struct{}), - connStatusOkCh: make(chan struct{}), - connStatusFailCh: make(chan struct{}), - connId: connId, - receiveWindow: new(ReceiveWindow), - sendWindow: new(SendWindow), - once: sync.Once{}, - } - //if len(label) > 0 { - // c.label = label[0] - //} - c.receiveWindow.New(mux) - c.sendWindow.New(mux) - //logm := &connLog{ - // startTime: time.Now(), - // isClose: false, - // logs: []string{c.label + "new conn success"}, - //} - //setM(label[0], int(connId), logm) - return c -} - -func (s *conn) Read(buf []byte) (n int, err error) { - if s.isClose || buf == nil { - return 0, errors.New("the conn has closed") - } - if len(buf) == 0 { - return 0, nil - } - // waiting for takeout from receive window finish or timeout - //now := time.Now() - n, err = s.receiveWindow.Read(buf, s.connId) - //t := time.Now().Sub(now) - //if t.Seconds() > 0.5 { - //logs.Warn("conn read long", n, t.Seconds()) - //} - //var errstr string - //if err == nil { - // errstr = "err:nil" - //} else { - // errstr = err.Error() - //} - //d := getM(s.label, int(s.connId)) - //d.logs = append(d.logs, s.label+"read "+strconv.Itoa(n)+" "+errstr+" "+string(buf[:100])) - //setM(s.label, int(s.connId), d) - return -} - -func (s *conn) Write(buf []byte) (n int, err error) { - if s.isClose { - return 0, errors.New("the conn has closed") - } - if s.closeFlag { - //s.Close() - return 0, errors.New("io: write on closed conn") - } - if len(buf) == 0 { - return 0, nil - } - //logs.Warn("write buf", len(buf)) - //now := time.Now() - n, err = s.sendWindow.WriteFull(buf, s.connId) - //t := time.Now().Sub(now) - //if t.Seconds() > 0.5 { - // logs.Warn("conn write long", n, t.Seconds()) - //} - return -} - -func (s *conn) Close() (err error) { - s.once.Do(s.closeProcess) - return -} - -func (s *conn) closeProcess() { - s.isClose = true - s.receiveWindow.mux.connMap.Delete(s.connId) - if !s.receiveWindow.mux.IsClose { - // if server or user close the conn while reading, will get a io.EOF - // and this Close method will be invoke, send this signal to close other side - s.receiveWindow.mux.sendInfo(common.MUX_CONN_CLOSE, s.connId, nil) - } - s.sendWindow.CloseWindow() - s.receiveWindow.CloseWindow() - //d := getM(s.label, int(s.connId)) - //d.isClose = true - //d.logs = append(d.logs, s.label+"close "+time.Now().String()) - //setM(s.label, int(s.connId), d) - return -} - -func (s *conn) LocalAddr() net.Addr { - return s.receiveWindow.mux.conn.LocalAddr() -} - -func (s *conn) RemoteAddr() net.Addr { - return s.receiveWindow.mux.conn.RemoteAddr() -} - -func (s *conn) SetDeadline(t time.Time) error { - _ = s.SetReadDeadline(t) - _ = s.SetWriteDeadline(t) - return nil -} - -func (s *conn) SetReadDeadline(t time.Time) error { - s.receiveWindow.SetTimeOut(t) - return nil -} - -func (s *conn) SetWriteDeadline(t time.Time) error { - s.sendWindow.SetTimeOut(t) - return nil -} - -type window struct { - 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 -} - -const windowBits = 31 -const waitBits = dequeueBits + windowBits -const mask1 = 1 -const mask31 = 1<> dequeueBits) & mask31) - done = uint32(ptrs & mask31) - //logs.Warn("unpack", maxSize, done) - if ((ptrs >> waitBits) & mask1) == 1 { - wait = true - return - } - return -} - -func (Self *window) pack(maxSize, done uint32, wait bool) uint64 { - //logs.Warn("pack", maxSize, done, wait) - if wait { - return (uint64(1)< 0 { - n = uint32(l) - } - return -} - -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() + Self.bw.Get())) - //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 - } - 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 n > (common.MAXIMUM_WINDOW_SIZE / uint32(conns)) { - logs.Warn("window too large, calculated:", n, "limit:", common.MAXIMUM_WINDOW_SIZE/uint32(conns)) - n = common.MAXIMUM_WINDOW_SIZE / uint32(conns) - } - // set the maximum size - //logs.Warn("n", n) - if atomic.CompareAndSwapUint64(&Self.maxSizeDone, ptrs, Self.pack(n, read, wait)) { - // only change the maxSize - break - } - } - Self.count = -10 - } - Self.count += 1 - return -} - -func (Self *ReceiveWindow) Write(buf []byte, l uint16, part bool, id int32) (err error) { - if Self.closeOp { - 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) - if err != nil { - return - } - Self.calcSize() // calculate the max window size - var wait bool - var maxSize, read uint32 -start: - 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 remain == 0 && !wait { - //logs.Warn("window full true", remaining) - 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 { - Self.mux.sendInfo(common.MUX_MSG_SEND_OK, id, Self.pack(maxSize, read, false)) - // send the current status to send window - } - return nil -} - -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) -copyData: - if Self.off == uint32(Self.element.L) { - // on the first Read method invoked, Self.off and Self.element.l - // both zero value - common.ListElementPool.Put(Self.element) - if Self.closeOp { - return 0, io.EOF - } - 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 - 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) - } - l = copy(p[pOff:], Self.element.Buf[Self.off:Self.element.L]) - pOff += l - Self.off += uint32(l) - //logs.Warn("window read length buf len", Self.readLength, Self.bufQueue.Len()) - n += l - l = 0 - if Self.off == uint32(Self.element.L) { - //logs.Warn("put the element end ", string(Self.element.buf[:15])) - common.WindowBuff.Put(Self.element.Buf) - Self.sendStatus(id, Self.element.L) - // check the window full status - } - if pOff < len(p) && Self.element.Part { - // element is a part of the segments, trying to fill up buf p - goto copyData - } - return // buf p is full or all of segments in buf, return -} - -func (Self *ReceiveWindow) sendStatus(id int32, l uint16) { - var maxSize, read uint32 - var wait bool - for { - 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 - } - return -} - -func (Self *ReceiveWindow) SetTimeOut(t time.Time) { - // waiting for FIFO queue Pop method - Self.bufQueue.SetTimeOut(t) -} - -func (Self *ReceiveWindow) Stop() { - // queue has no more data to push, so unblock pop method - Self.once.Do(Self.bufQueue.Stop) -} - -func (Self *ReceiveWindow) CloseWindow() { - Self.window.CloseWindow() - Self.Stop() - Self.release() -} - -func (Self *ReceiveWindow) release() { - //if Self.element != nil { - // if Self.element.Buf != nil { - // common.WindowBuff.Put(Self.element.Buf) - // } - // common.ListElementPool.Put(Self.element) - //} - for { - ele := Self.bufQueue.TryPop() - if ele == nil { - return - } - if ele.Buf != nil { - common.WindowBuff.Put(ele.Buf) - } - common.ListElementPool.Put(ele) - } // release resource -} - -type SendWindow struct { - window - 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.maxSizeDone = Self.pack(common.MAXIMUM_SEGMENT_SIZE*30, 0, false) - Self.mux = mux - Self.window.New() -} - -func (Self *SendWindow) SetSendBuf(buf []byte) { - // send window buff from conn write method, set it to send window - Self.buf = buf - Self.off = 0 -} - -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 { - closed = true - } - }() - if Self.closeOp { - close(Self.setSizeCh) - return true - } - //logs.Warn("set send window size to ", windowSize, newRemaining) - var maxsize, send uint32 - var wait, newWait bool - currentMaxSize, read, _ := Self.unpack(currentMaxSizeDone) - for { - 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 read == 0 && currentMaxSize == maxsize { - return - } - 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 && !newWait { - // send window into the wait status, need notice the channel - //logs.Warn("send window allow") - Self.allow() - } - // send window not into the wait status, so just do slide - return false -} - -func (Self *SendWindow) allow() { - select { - case Self.setSizeCh <- struct{}{}: - //logs.Warn("send window remaining size is 0 finish") - return - case <-Self.closeOpCh: - close(Self.setSizeCh) - return - } -} - -func (Self *SendWindow) sent(sentSize uint32) { - var maxSie, send uint32 - var wait bool - for { - 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 - } - } -} - -func (Self *SendWindow) WriteTo() (p []byte, sendSize uint32, part bool, err error) { - // returns buf segments, return only one segments, need a loop outside - // until err = io.EOF - if Self.closeOp { - return nil, 0, false, errors.New("conn.writeWindow: window closed") - } - if Self.off == uint32(len(Self.buf)) { - return nil, 0, false, io.EOF - // send window buff is drain, return eof and get another one - } - var maxSize, send uint32 -start: - 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 - //logs.Warn("send window into wait status") - err = Self.waitReceiveWindow() - if err != nil { - return nil, 0, false, err - } - //logs.Warn("rem into wait finish") - goto start - } - // there are still remaining window - //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 remain < sendSize { - // usable window size is small than - // window MAXIMUM_SEGMENT_SIZE or send buf left - sendSize = remain - //logs.Warn("cut buf by remainingsize", sendSize, len(Self.buf[Self.off:])) - } - //logs.Warn("send size", sendSize) - if sendSize < uint32(len(Self.buf[Self.off:])) { - part = true - } - p = Self.buf[Self.off : sendSize+Self.off] - Self.off += sendSize - Self.sent(sendSize) - return -} - -func (Self *SendWindow) waitReceiveWindow() (err error) { - t := Self.timeout.Sub(time.Now()) - if t < 0 { // not set the timeout, wait for it as long as connection close - select { - case _, ok := <-Self.setSizeCh: - if !ok { - return errors.New("conn.writeWindow: window closed") - } - return nil - case <-Self.closeOpCh: - return errors.New("conn.writeWindow: window closed") - } - } - timer := time.NewTimer(t) - defer timer.Stop() - // waiting for receive usable window size, or timeout - select { - case _, ok := <-Self.setSizeCh: - if !ok { - return errors.New("conn.writeWindow: window closed") - } - return nil - case <-timer.C: - return errors.New("conn.writeWindow: write to time out") - case <-Self.closeOpCh: - return errors.New("conn.writeWindow: window closed") - } -} - -func (Self *SendWindow) WriteFull(buf []byte, id int32) (n int, err error) { - Self.SetSendBuf(buf) // set the buf to send window - //logs.Warn("set the buf to send window") - var bufSeg []byte - var part bool - var l uint32 - for { - bufSeg, l, part, err = Self.WriteTo() - //logs.Warn("buf seg", len(bufSeg), part, err) - // get the buf segments from send window - if bufSeg == nil && part == false && err == io.EOF { - // send window is drain, break the loop - err = nil - break - } - if err != nil { - break - } - n += int(l) - l = 0 - if part { - Self.mux.sendInfo(common.MUX_NEW_MSG_PART, id, bufSeg) - } else { - Self.mux.sendInfo(common.MUX_NEW_MSG, id, bufSeg) - //logs.Warn("buf seg sent", len(bufSeg), part, err) - } - // send to other side, not send nil data to other side - } - //logs.Warn("buf seg write success") - return -} - -func (Self *SendWindow) SetTimeOut(t time.Time) { - // waiting for receive a receive window size - Self.timeout = t -} diff --git a/lib/mux/map.go b/lib/mux/map.go deleted file mode 100644 index 86d09b5..0000000 --- a/lib/mux/map.go +++ /dev/null @@ -1,75 +0,0 @@ -package mux - -import ( - "sync" -) - -type connMap struct { - connMap map[int32]*conn - //closeCh chan struct{} - sync.RWMutex -} - -func NewConnMap() *connMap { - connMap := &connMap{ - connMap: make(map[int32]*conn), - //closeCh: make(chan struct{}), - } - //go connMap.clean() - return connMap -} - -func (s *connMap) Size() (n int) { - s.Lock() - n = len(s.connMap) - s.Unlock() - return -} - -func (s *connMap) Get(id int32) (*conn, bool) { - s.Lock() - v, ok := s.connMap[id] - s.Unlock() - if ok && v != nil { - return v, true - } - return nil, false -} - -func (s *connMap) Set(id int32, v *conn) { - s.Lock() - s.connMap[id] = v - s.Unlock() -} - -func (s *connMap) Close() { - //s.closeCh <- struct{}{} // stop the clean goroutine first - for _, v := range s.connMap { - v.Close() // close all the connections in the mux - } -} - -func (s *connMap) Delete(id int32) { - s.Lock() - delete(s.connMap, id) - s.Unlock() -} - -//func (s *connMap) clean() { -// ticker := time.NewTimer(time.Minute * 1) -// for { -// select { -// case <-ticker.C: -// s.Lock() -// for _, v := range s.connMap { -// if v.isClose { -// delete(s.connMap, v.connId) -// } -// } -// s.Unlock() -// case <-s.closeCh: -// ticker.Stop() -// return -// } -// } -//} diff --git a/lib/mux/mux.go b/lib/mux/mux.go deleted file mode 100644 index f89bbc4..0000000 --- a/lib/mux/mux.go +++ /dev/null @@ -1,535 +0,0 @@ -package mux - -import ( - "errors" - "io" - "math" - "net" - "os" - "sync/atomic" - "time" - - "github.com/astaxie/beego/logs" - "github.com/cnlh/nps/lib/common" -) - -type Mux struct { - latency uint64 // we store latency in bits, but it's float64 - net.Listener - conn net.Conn - connMap *connMap - newConnCh chan *conn - id int32 - closeChan chan struct{} - IsClose bool - pingOk uint32 - counter *latencyCounter - bw *bandwidth - pingCh chan []byte - pingCheckTime uint32 - connType string - writeQueue PriorityQueue - newConnQueue ConnQueue -} - -func NewMux(c net.Conn, connType string) *Mux { - //c.(*net.TCPConn).SetReadBuffer(0) - //c.(*net.TCPConn).SetWriteBuffer(0) - _ = c.SetDeadline(time.Time{}) - fd, err := getConnFd(c) - if err != nil { - logs.Warn(err) - } - m := &Mux{ - conn: c, - connMap: NewConnMap(), - id: 0, - closeChan: make(chan struct{}, 1), - newConnCh: make(chan *conn), - bw: NewBandwidth(fd), - IsClose: false, - connType: connType, - pingCh: make(chan []byte), - counter: newLatencyCounter(), - } - m.writeQueue.New() - m.newConnQueue.New() - //read session by flag - m.readSession() - //ping - m.ping() - m.pingReturn() - m.writeSession() - return m -} - -func (s *Mux) NewConn() (*conn, error) { - if s.IsClose { - return nil, errors.New("the mux has closed") - } - conn := NewConn(s.getId(), s, "nps ") - //it must be set before send - s.connMap.Set(conn.connId, conn) - s.sendInfo(common.MUX_NEW_CONN, conn.connId, nil) - //set a timer timeout 30 second - timer := time.NewTimer(time.Minute * 2) - defer timer.Stop() - select { - case <-conn.connStatusOkCh: - return conn, nil - case <-conn.connStatusFailCh: - case <-timer.C: - } - return nil, errors.New("create connection fail,the server refused the connection") -} - -func (s *Mux) Accept() (net.Conn, error) { - if s.IsClose { - return nil, errors.New("accpet error,the mux has closed") - } - conn := <-s.newConnCh - if conn == nil { - return nil, errors.New("accpet error,the conn has closed") - } - return conn, nil -} - -func (s *Mux) Addr() net.Addr { - return s.conn.LocalAddr() -} - -func (s *Mux) sendInfo(flag uint8, id int32, data ...interface{}) { - if s.IsClose { - return - } - var err error - pack := common.MuxPack.Get() - err = pack.NewPac(flag, id, data...) - if err != nil { - common.MuxPack.Put(pack) - logs.Error("mux: new pack err", err) - s.Close() - return - } - s.writeQueue.Push(pack) - return -} - -func (s *Mux) writeSession() { - go s.packBuf() - //go s.writeBuf() -} - -func (s *Mux) packBuf() { - //buffer := common.BuffPool.Get() - for { - if s.IsClose { - break - } - //buffer.Reset() - pack := s.writeQueue.Pop() - if s.IsClose { - break - } - //buffer := common.BuffPool.Get() - err := pack.Pack(s.conn) - common.MuxPack.Put(pack) - if err != nil { - logs.Error("mux: pack err", err) - //common.BuffPool.Put(buffer) - s.Close() - break - } - //logs.Warn(buffer.String()) - //s.bufQueue.Push(buffer) - //l := buffer.Len() - //n, err := buffer.WriteTo(s.conn) - //common.BuffPool.Put(buffer) - //if err != nil || int(n) != l { - // logs.Error("mux: close from write session fail ", err, n, l) - // s.Close() - // break - //} - } -} - -//func (s *Mux) writeBuf() { -// for { -// if s.IsClose { -// break -// } -// buffer, err := s.bufQueue.Pop() -// if err != nil { -// break -// } -// l := buffer.Len() -// n, err := buffer.WriteTo(s.conn) -// common.BuffPool.Put(buffer) -// if err != nil || int(n) != l { -// logs.Warn("close from write session fail ", err, n, l) -// s.Close() -// break -// } -// } -//} - -func (s *Mux) ping() { - go func() { - now, _ := time.Now().UTC().MarshalText() - s.sendInfo(common.MUX_PING_FLAG, common.MUX_PING, now) - // send the ping flag and get the latency first - ticker := time.NewTicker(time.Second * 5) - defer ticker.Stop() - for { - if s.IsClose { - break - } - select { - case <-ticker.C: - } - if atomic.LoadUint32(&s.pingCheckTime) >= 60 { - logs.Error("mux: ping time out") - s.Close() - // more than 5 minutes not receive the ping return package, - // mux conn is damaged, maybe a packet drop, close it - break - } - now, _ := time.Now().UTC().MarshalText() - s.sendInfo(common.MUX_PING_FLAG, common.MUX_PING, now) - atomic.AddUint32(&s.pingCheckTime, 1) - if atomic.LoadUint32(&s.pingOk) > 10 && s.connType == "kcp" { - logs.Error("mux: kcp ping err") - s.Close() - break - } - atomic.AddUint32(&s.pingOk, 1) - } - return - }() -} - -func (s *Mux) pingReturn() { - go func() { - var now time.Time - var data []byte - for { - if s.IsClose { - break - } - select { - case data = <-s.pingCh: - atomic.StoreUint32(&s.pingCheckTime, 0) - case <-s.closeChan: - return - } - _ = now.UnmarshalText(data) - latency := time.Now().UTC().Sub(now).Seconds() / 2 - if latency > 0 { - atomic.StoreUint64(&s.latency, math.Float64bits(s.counter.Latency(latency))) - // convert float64 to bits, store it atomic - } - //logs.Warn("latency", math.Float64frombits(atomic.LoadUint64(&s.latency))) - if cap(data) > 0 { - common.WindowBuff.Put(data) - } - } - }() -} - -func (s *Mux) readSession() { - go func() { - var connection *conn - for { - if s.IsClose { - break - } - connection = s.newConnQueue.Pop() - if s.IsClose { - break // make sure that is closed - } - s.connMap.Set(connection.connId, connection) //it has been set before send ok - s.newConnCh <- connection - s.sendInfo(common.MUX_NEW_CONN_OK, connection.connId, nil) - } - }() - go func() { - pack := common.MuxPack.Get() - var l uint16 - var err error - for { - if s.IsClose { - break - } - pack = common.MuxPack.Get() - s.bw.StartRead() - if l, err = pack.UnPack(s.conn); err != nil { - logs.Error("mux: read session unpack from connection err", err) - s.Close() - break - } - s.bw.SetCopySize(l) - atomic.StoreUint32(&s.pingOk, 0) - switch pack.Flag { - case common.MUX_NEW_CONN: //new connection - connection := NewConn(pack.Id, s) - s.newConnQueue.Push(connection) - continue - case common.MUX_PING_FLAG: //ping - s.sendInfo(common.MUX_PING_RETURN, common.MUX_PING, pack.Content) - common.WindowBuff.Put(pack.Content) - continue - case common.MUX_PING_RETURN: - //go func(content []byte) { - s.pingCh <- pack.Content - //}(pack.Content) - continue - } - if connection, ok := s.connMap.Get(pack.Id); ok && !connection.isClose { - switch pack.Flag { - case common.MUX_NEW_MSG, common.MUX_NEW_MSG_PART: //new msg from remote connection - err = s.newMsg(connection, pack) - if err != nil { - logs.Error("mux: read session connection new msg err", err) - connection.Close() - } - continue - case common.MUX_NEW_CONN_OK: //connection ok - connection.connStatusOkCh <- struct{}{} - continue - case common.MUX_NEW_CONN_Fail: - connection.connStatusFailCh <- struct{}{} - continue - case common.MUX_MSG_SEND_OK: - if connection.isClose { - continue - } - connection.sendWindow.SetSize(pack.Window) - continue - case common.MUX_CONN_CLOSE: //close the connection - connection.closeFlag = true - //s.connMap.Delete(pack.Id) - //go func(connection *conn) { - connection.receiveWindow.Stop() // close signal to receive window - //}(connection) - continue - } - } else if pack.Flag == common.MUX_CONN_CLOSE { - continue - } - common.MuxPack.Put(pack) - } - common.MuxPack.Put(pack) - s.Close() - }() -} - -func (s *Mux) newMsg(connection *conn, pack *common.MuxPackager) (err error) { - if connection.isClose { - err = io.ErrClosedPipe - return - } - //logs.Warn("read session receive new msg", pack.Length) - //go func(connection *conn, pack *common.MuxPackager) { // do not block read session - //insert into queue - if pack.Flag == common.MUX_NEW_MSG_PART { - err = connection.receiveWindow.Write(pack.Content, pack.Length, true, pack.Id) - } - if pack.Flag == common.MUX_NEW_MSG { - err = connection.receiveWindow.Write(pack.Content, pack.Length, false, pack.Id) - } - //logs.Warn("read session write success", pack.Length) - return -} - -func (s *Mux) Close() (err error) { - logs.Warn("close mux") - if s.IsClose { - return errors.New("the mux has closed") - } - s.IsClose = true - s.connMap.Close() - s.connMap = nil - //s.bufQueue.Stop() - s.closeChan <- struct{}{} - close(s.newConnCh) - err = s.conn.Close() - s.release() - return -} - -func (s *Mux) release() { - for { - pack := s.writeQueue.TryPop() - if pack == nil { - break - } - if pack.BasePackager.Content != nil { - common.WindowBuff.Put(pack.BasePackager.Content) - } - common.MuxPack.Put(pack) - } - for { - connection := s.newConnQueue.TryPop() - if connection == nil { - break - } - connection = nil - } - s.writeQueue.Stop() - s.newConnQueue.Stop() -} - -//get new connId as unique flag -func (s *Mux) getId() (id int32) { - //Avoid going beyond the scope - if (math.MaxInt32 - s.id) < 10000 { - atomic.StoreInt32(&s.id, 0) - } - id = atomic.AddInt32(&s.id, 1) - if _, ok := s.connMap.Get(id); ok { - return s.getId() - } - return -} - -type bandwidth struct { - readBandwidth uint64 // store in bits, but it's float64 - readStart time.Time - lastReadStart time.Time - bufLength uint32 - fd *os.File - calcThreshold uint32 -} - -func NewBandwidth(fd *os.File) *bandwidth { - return &bandwidth{fd: fd} -} - -func (Self *bandwidth) StartRead() { - if Self.readStart.IsZero() { - Self.readStart = time.Now() - } - if Self.bufLength >= Self.calcThreshold { - Self.lastReadStart, Self.readStart = Self.readStart, time.Now() - Self.calcBandWidth() - } -} - -func (Self *bandwidth) SetCopySize(n uint16) { - Self.bufLength += uint32(n) -} - -func (Self *bandwidth) calcBandWidth() { - t := Self.readStart.Sub(Self.lastReadStart) - bufferSize, err := sysGetSock(Self.fd) - //logs.Warn(bufferSize) - if err != nil { - logs.Warn(err) - Self.bufLength = 0 - return - } - if Self.bufLength >= uint32(bufferSize) { - atomic.StoreUint64(&Self.readBandwidth, math.Float64bits(float64(Self.bufLength)/t.Seconds())) - // calculate the whole socket buffer, the time meaning to fill the buffer - //logs.Warn(Self.Get()) - } else { - Self.calcThreshold = uint32(bufferSize) - } - // socket buffer size is bigger than bufLength, so we don't calculate it - Self.bufLength = 0 -} - -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 - } - //logs.Warn(bw) - return -} - -const counterBits = 4 -const counterMask = 1<> counterBits) & counterMask) - // we set head is 4 bits - min = uint8(idxs & counterMask) - return -} - -func (Self *latencyCounter) pack(head, min uint8) uint8 { - return uint8(head< value { - min = head - } - head++ - Self.headMin = Self.pack(head, min) -} - -func (Self *latencyCounter) minimal() (min uint8) { - var val float64 - var i uint8 - for i = 0; i < counterMask; i++ { - if Self.buf[i] > 0 { - if val > Self.buf[i] { - val = Self.buf[i] - min = i - } - } - } - return -} - -func (Self *latencyCounter) Latency(value float64) (latency float64) { - Self.add(value) - _, min := Self.unpack(Self.headMin) - latency = Self.buf[min] * Self.countSuccess() - return -} - -const lossRatio = 1.6 - -func (Self *latencyCounter) countSuccess() (successRate float64) { - var success, loss, i uint8 - _, min := Self.unpack(Self.headMin) - for i = 0; i < counterMask; i++ { - if Self.buf[i] > lossRatio*Self.buf[min] && Self.buf[i] > 0 { - loss++ - } - if Self.buf[i] <= lossRatio*Self.buf[min] && Self.buf[i] > 0 { - success++ - } - } - // counting all the data in the ring buf, except zero - successRate = float64(success) / float64(loss+success) - return -} diff --git a/lib/mux/mux_test.go b/lib/mux/mux_test.go deleted file mode 100644 index 0d71ee4..0000000 --- a/lib/mux/mux_test.go +++ /dev/null @@ -1,453 +0,0 @@ -package mux - -import ( - "bufio" - "fmt" - "github.com/cnlh/nps/lib/common" - "github.com/cnlh/nps/lib/goroutine" - "io" - "log" - "net" - "net/http" - "net/http/httputil" - _ "net/http/pprof" - "strconv" - "testing" - "time" - "unsafe" - - "github.com/astaxie/beego/logs" -) - -var conn1 net.Conn -var conn2 net.Conn - -func TestNewMux(t *testing.T) { - go func() { - http.ListenAndServe("0.0.0.0:8889", nil) - }() - logs.EnableFuncCallDepth(true) - logs.SetLogFuncCallDepth(3) - server() - client() - //poolConnCopy, _ := ants.NewPoolWithFunc(200000, common.copyConn, ants.WithNonblocking(false)) - time.Sleep(time.Second * 3) - go func() { - m2 := NewMux(conn2, "tcp") - //m2 := NewMux(conn2, "kcp") - for { - //logs.Warn("npc starting accept") - c, err := m2.Accept() - if err != nil { - logs.Warn(err) - continue - } - //logs.Warn("npc accept success ") - c2, err := net.Dial("tcp", "127.0.0.1:80") - if err != nil { - logs.Warn(err) - c.Close() - continue - } - //c2.(*net.TCPConn).SetReadBuffer(0) - //c2.(*net.TCPConn).SetReadBuffer(0) - _ = goroutine.CopyConnsPool.Invoke(goroutine.NewConns(c, c2, nil)) - //go func(c2 net.Conn, c *conn) { - // wg := new(sync.WaitGroup) - // wg.Add(2) - // _ = poolConnCopy.Invoke(common.newConnGroup(c2, c, wg)) - // //go func() { - // // _, err = common.CopyBuffer(c2, c) - // // if err != nil { - // // c2.Close() - // // c.Close() - // // //logs.Warn("close npc by copy from nps", err, c.connId) - // // } - // // wg.Done() - // //}() - // //wg.Add(1) - // _ = poolConnCopy.Invoke(common.newConnGroup(c, c2, wg)) - // //go func() { - // // _, err = common.CopyBuffer(c, c2) - // // if err != nil { - // // c2.Close() - // // c.Close() - // // //logs.Warn("close npc by copy from server", err, c.connId) - // // } - // // wg.Done() - // //}() - // //logs.Warn("npc wait") - // wg.Wait() - //}(c2, c.(*conn)) - } - }() - - go func() { - m1 := NewMux(conn1, "tcp") - //m1 := NewMux(conn1, "kcp") - l, err := net.Listen("tcp", "127.0.0.1:7777") - if err != nil { - logs.Warn(err) - } - for { - //logs.Warn("nps starting accept") - conns, err := l.Accept() - if err != nil { - logs.Warn(err) - continue - } - //conns.(*net.TCPConn).SetReadBuffer(0) - //conns.(*net.TCPConn).SetReadBuffer(0) - //logs.Warn("nps accept success starting new conn") - tmpCpnn, err := m1.NewConn() - if err != nil { - logs.Warn("nps new conn err ", err) - continue - } - //logs.Warn("nps new conn success ", tmpCpnn.connId) - _ = goroutine.CopyConnsPool.Invoke(goroutine.NewConns(tmpCpnn, conns, nil)) - //go func(tmpCpnn *conn, conns net.Conn) { - // wg := new(sync.WaitGroup) - // wg.Add(2) - // _ = poolConnCopy.Invoke(common.newConnGroup(tmpCpnn, conns, wg)) - // //go func() { - // // _, err := common.CopyBuffer(tmpCpnn, conns) - // // if err != nil { - // // conns.Close() - // // tmpCpnn.Close() - // // //logs.Warn("close nps by copy from user", tmpCpnn.connId, err) - // // } - // //}() - // //wg.Add(1) - // _ = poolConnCopy.Invoke(common.newConnGroup(conns, tmpCpnn, wg)) - // //time.Sleep(time.Second) - // //_, err = common.CopyBuffer(conns, tmpCpnn) - // //if err != nil { - // // conns.Close() - // // tmpCpnn.Close() - // // //logs.Warn("close nps by copy from npc ", tmpCpnn.connId, err) - // //} - // wg.Wait() - //}(tmpCpnn, conns) - } - }() - - //go NewLogServer() - time.Sleep(time.Second * 5) - //for i := 0; i < 1; i++ { - // go test_raw(i) - //} - //test_request() - - for { - time.Sleep(time.Second * 5) - } -} - -func server() { - var err error - 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) - if err != nil { - logs.Warn(err) - } - }() - return -} - -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") - if err != nil { - logs.Warn(err) - } -} - -func test_request() { - conn, _ := net.Dial("tcp", "127.0.0.1:7777") - for i := 0; i < 1000; i++ { - conn.Write([]byte(`GET / HTTP/1.1 -Host: 127.0.0.1:7777 -Connection: keep-alive - - -`)) - r, err := http.ReadResponse(bufio.NewReader(conn), nil) - if err != nil { - logs.Warn("close by read response err", err) - break - } - logs.Warn("read response success", r) - b, err := httputil.DumpResponse(r, true) - if err != nil { - logs.Warn("close by dump response err", err) - break - } - fmt.Println(string(b[:20]), err) - //time.Sleep(time.Second) - } - logs.Warn("finish") -} - -func test_raw(k int) { - for i := 0; i < 1000; i++ { - ti := time.Now() - conn, err := net.Dial("tcp", "127.0.0.1:7777") - if err != nil { - logs.Warn("conn dial err", err) - } - tid := time.Now() - conn.Write([]byte(`GET /videojs5/video.js HTTP/1.1 -Host: 127.0.0.1:7777 - - -`)) - tiw := time.Now() - buf := make([]byte, 3572) - n, err := io.ReadFull(conn, buf) - //n, err := conn.Read(buf) - if err != nil { - logs.Warn("close by read response err", err) - break - } - logs.Warn(n, string(buf[:50]), "\n--------------\n", string(buf[n-50:n])) - //time.Sleep(time.Second) - err = conn.Close() - if err != nil { - logs.Warn("close conn err ", err) - } - now := time.Now() - du := now.Sub(ti).Seconds() - dud := now.Sub(tid).Seconds() - duw := now.Sub(tiw).Seconds() - if du > 1 { - logs.Warn("duration long", du, dud, duw, k, i) - } - if n != 3572 { - logs.Warn("n loss", n, string(buf)) - } - } - logs.Warn("finish") -} - -func TestNewConn(t *testing.T) { - buf := common.GetBufPoolCopy() - logs.Warn(len(buf), cap(buf)) - //b := pool.GetBufPoolCopy() - //b[0] = 1 - //b[1] = 2 - //b[2] = 3 - b := []byte{1, 2, 3} - logs.Warn(copy(buf[:3], b), len(buf), cap(buf)) - logs.Warn(len(buf), buf[0]) -} - -func TestDQueue(t *testing.T) { - logs.EnableFuncCallDepth(true) - logs.SetLogFuncCallDepth(3) - d := new(bufDequeue) - d.vals = make([]unsafe.Pointer, 8) - go func() { - time.Sleep(time.Second) - for i := 0; i < 10; i++ { - logs.Warn(i) - logs.Warn(d.popTail()) - } - }() - go func() { - time.Sleep(time.Second) - for i := 0; i < 10; i++ { - data := "test" - go logs.Warn(i, unsafe.Pointer(&data), d.pushHead(unsafe.Pointer(&data))) - } - }() - time.Sleep(time.Second * 3) -} - -func TestChain(t *testing.T) { - go func() { - log.Println(http.ListenAndServe("0.0.0.0:8889", nil)) - }() - logs.EnableFuncCallDepth(true) - logs.SetLogFuncCallDepth(3) - time.Sleep(time.Second * 5) - d := new(bufChain) - d.new(256) - go func() { - time.Sleep(time.Second) - for i := 0; i < 30000; i++ { - unsa, ok := d.popTail() - str := (*string)(unsa) - if ok { - fmt.Println(i, str, *str, ok) - //logs.Warn(i, str, *str, ok) - } else { - fmt.Println("nil", i, ok) - //logs.Warn("nil", i, ok) - } - } - }() - go func() { - time.Sleep(time.Second) - for i := 0; i < 3000; i++ { - go func(i int) { - for n := 0; n < 10; n++ { - data := "test " + strconv.Itoa(i) + strconv.Itoa(n) - fmt.Println(data, unsafe.Pointer(&data)) - //logs.Warn(data, unsafe.Pointer(&data)) - d.pushHead(unsafe.Pointer(&data)) - } - }(i) - } - }() - time.Sleep(time.Second * 100000) -} - -func TestFIFO(t *testing.T) { - go func() { - log.Println(http.ListenAndServe("0.0.0.0:8889", nil)) - }() - logs.EnableFuncCallDepth(true) - logs.SetLogFuncCallDepth(3) - time.Sleep(time.Second * 5) - d := new(ReceiveWindowQueue) - d.New() - go func() { - time.Sleep(time.Second) - for i := 0; i < 1001; i++ { - data, err := d.Pop() - if err == nil { - //fmt.Println(i, string(data.buf), err) - logs.Warn(i, string(data.Buf), err) - common.ListElementPool.Put(data) - } else { - //fmt.Println("err", err) - logs.Warn("err", err) - } - //logs.Warn(d.Len()) - } - logs.Warn("pop finish") - }() - go func() { - time.Sleep(time.Second * 10) - for i := 0; i < 1000; i++ { - by := []byte("test " + strconv.Itoa(i) + " ") // - data, _ := NewListElement(by, uint16(len(by)), true) - //fmt.Println(string((*data).buf), data) - //logs.Warn(string((*data).buf), data) - d.Push(data) - } - }() - time.Sleep(time.Second * 100000) -} - -func TestPriority(t *testing.T) { - go func() { - log.Println(http.ListenAndServe("0.0.0.0:8889", nil)) - }() - logs.EnableFuncCallDepth(true) - logs.SetLogFuncCallDepth(3) - time.Sleep(time.Second * 5) - d := new(PriorityQueue) - d.New() - go func() { - time.Sleep(time.Second) - for i := 0; i < 360050; i++ { - data := d.Pop() - //fmt.Println(i, string(data.buf), err) - logs.Warn(i, string(data.Content), data) - } - logs.Warn("pop finish") - }() - go func() { - time.Sleep(time.Second * 10) - for i := 0; i < 30000; i++ { - go func(i int) { - for n := 0; n < 10; n++ { - data := new(common.MuxPackager) - by := []byte("test " + strconv.Itoa(i) + strconv.Itoa(n)) - _ = data.NewPac(common.MUX_NEW_MSG_PART, int32(i), by) - //fmt.Println(string((*data).buf), data) - logs.Warn(string((*data).Content), data) - d.Push(data) - } - }(i) - go func(i int) { - data := new(common.MuxPackager) - _ = data.NewPac(common.MUX_NEW_CONN, int32(i), nil) - //fmt.Println(string((*data).buf), data) - logs.Warn(data) - d.Push(data) - }(i) - go func(i int) { - data := new(common.MuxPackager) - _ = data.NewPac(common.MUX_NEW_CONN_OK, int32(i), nil) - //fmt.Println(string((*data).buf), data) - logs.Warn(data) - d.Push(data) - }(i) - } - }() - time.Sleep(time.Second * 100000) -} - -//func TestReceive(t *testing.T) { -// go func() { -// log.Println(http.ListenAndServe("0.0.0.0:8889", nil)) -// }() -// logs.EnableFuncCallDepth(true) -// logs.SetLogFuncCallDepth(3) -// time.Sleep(time.Second * 5) -// mux := new(Mux) -// mux.bw.readBandwidth = float64(1*1024*1024) -// mux.latency = float64(1/1000) -// wind := new(ReceiveWindow) -// wind.New(mux) -// wind. -// go func() { -// time.Sleep(time.Second) -// for i := 0; i < 36000; i++ { -// data := d.Pop() -// //fmt.Println(i, string(data.buf), err) -// logs.Warn(i, string(data.Content), data) -// } -// }() -// go func() { -// time.Sleep(time.Second*10) -// for i := 0; i < 3000; i++ { -// go func(i int) { -// for n := 0; n < 10; n++{ -// data := new(common.MuxPackager) -// by := []byte("test " + strconv.Itoa(i) + strconv.Itoa(n)) -// _ = data.NewPac(common.MUX_NEW_MSG_PART, int32(i), by) -// //fmt.Println(string((*data).buf), data) -// logs.Warn(string((*data).Content), data) -// d.Push(data) -// } -// }(i) -// go func(i int) { -// data := new(common.MuxPackager) -// _ = data.NewPac(common.MUX_NEW_CONN, int32(i), nil) -// //fmt.Println(string((*data).buf), data) -// logs.Warn(data) -// d.Push(data) -// }(i) -// go func(i int) { -// data := new(common.MuxPackager) -// _ = data.NewPac(common.MUX_NEW_CONN_OK, int32(i), nil) -// //fmt.Println(string((*data).buf), data) -// logs.Warn(data) -// d.Push(data) -// }(i) -// } -// }() -// time.Sleep(time.Second * 100000) -//} diff --git a/lib/mux/queue.go b/lib/mux/queue.go deleted file mode 100644 index 9a62fa2..0000000 --- a/lib/mux/queue.go +++ /dev/null @@ -1,589 +0,0 @@ -package mux - -import ( - "errors" - "github.com/cnlh/nps/lib/common" - "io" - "math" - "runtime" - "sync" - "sync/atomic" - "time" - "unsafe" -) - -type PriorityQueue struct { - highestChain *bufChain - middleChain *bufChain - lowestChain *bufChain - starving uint8 - stop bool - cond *sync.Cond -} - -func (Self *PriorityQueue) New() { - Self.highestChain = new(bufChain) - Self.highestChain.new(4) - Self.middleChain = new(bufChain) - Self.middleChain.new(32) - Self.lowestChain = new(bufChain) - Self.lowestChain.new(256) - locker := new(sync.Mutex) - Self.cond = sync.NewCond(locker) -} - -func (Self *PriorityQueue) Push(packager *common.MuxPackager) { - //logs.Warn("push start") - Self.push(packager) - Self.cond.Broadcast() - //logs.Warn("push finish") - return -} - -func (Self *PriorityQueue) push(packager *common.MuxPackager) { - switch packager.Flag { - case common.MUX_PING_FLAG, common.MUX_PING_RETURN: - Self.highestChain.pushHead(unsafe.Pointer(packager)) - // the ping package need highest priority - // prevent ping calculation error - case common.MUX_NEW_CONN, common.MUX_NEW_CONN_OK, common.MUX_NEW_CONN_Fail: - // the new conn package need some priority too - Self.middleChain.pushHead(unsafe.Pointer(packager)) - default: - Self.lowestChain.pushHead(unsafe.Pointer(packager)) - } -} - -const maxStarving uint8 = 8 - -func (Self *PriorityQueue) Pop() (packager *common.MuxPackager) { - var iter bool - for { - packager = Self.TryPop() - if packager != nil { - return - } - if Self.stop { - return - } - if iter { - break - // trying to pop twice - } - iter = true - runtime.Gosched() - } - Self.cond.L.Lock() - defer Self.cond.L.Unlock() - for packager = Self.TryPop(); packager == nil; { - if Self.stop { - return - } - //logs.Warn("queue into wait") - Self.cond.Wait() - // wait for it with no more iter - packager = Self.TryPop() - //logs.Warn("queue wait finish", packager) - } - return -} - -func (Self *PriorityQueue) TryPop() (packager *common.MuxPackager) { - ptr, ok := Self.highestChain.popTail() - if ok { - packager = (*common.MuxPackager)(ptr) - return - } - if Self.starving < maxStarving { - // not pop too much, lowestChain will wait too long - ptr, ok = Self.middleChain.popTail() - if ok { - packager = (*common.MuxPackager)(ptr) - Self.starving++ - return - } - } - ptr, ok = Self.lowestChain.popTail() - if ok { - packager = (*common.MuxPackager)(ptr) - if Self.starving > 0 { - Self.starving = uint8(Self.starving / 2) - } - return - } - if Self.starving > 0 { - ptr, ok = Self.middleChain.popTail() - if ok { - packager = (*common.MuxPackager)(ptr) - Self.starving++ - return - } - } - return -} - -func (Self *PriorityQueue) Stop() { - Self.stop = true - Self.cond.Broadcast() -} - -type ConnQueue struct { - chain *bufChain - starving uint8 - stop bool - cond *sync.Cond -} - -func (Self *ConnQueue) New() { - Self.chain = new(bufChain) - Self.chain.new(32) - locker := new(sync.Mutex) - Self.cond = sync.NewCond(locker) -} - -func (Self *ConnQueue) Push(connection *conn) { - Self.chain.pushHead(unsafe.Pointer(connection)) - Self.cond.Broadcast() - return -} - -func (Self *ConnQueue) Pop() (connection *conn) { - var iter bool - for { - connection = Self.TryPop() - if connection != nil { - return - } - if Self.stop { - return - } - if iter { - break - // trying to pop twice - } - iter = true - runtime.Gosched() - } - Self.cond.L.Lock() - defer Self.cond.L.Unlock() - for connection = Self.TryPop(); connection == nil; { - if Self.stop { - return - } - //logs.Warn("queue into wait") - Self.cond.Wait() - // wait for it with no more iter - connection = Self.TryPop() - //logs.Warn("queue wait finish", packager) - } - return -} - -func (Self *ConnQueue) TryPop() (connection *conn) { - ptr, ok := Self.chain.popTail() - if ok { - connection = (*conn)(ptr) - return - } - return -} - -func (Self *ConnQueue) Stop() { - Self.stop = true - Self.cond.Broadcast() -} - -func NewListElement(buf []byte, l uint16, part bool) (element *common.ListElement, err error) { - if uint16(len(buf)) != l { - err = errors.New("ListElement: buf length not match") - return - } - //if l == 0 { - // logs.Warn("push zero") - //} - element = common.ListElementPool.Get() - element.Buf = buf - element.L = l - element.Part = part - return -} - -type ReceiveWindowQueue struct { - chain *bufChain - stopOp chan struct{} - readOp chan struct{} - lengthWait uint64 // really strange ???? need put here - // https://golang.org/pkg/sync/atomic/#pkg-note-BUG - // On non-Linux ARM, the 64-bit functions use instructions unavailable before the ARMv6k core. - // On ARM, x86-32, and 32-bit MIPS, it is the caller's responsibility - // to arrange for 64-bit alignment of 64-bit words accessed atomically. - // The first word in a variable or in an allocated struct, array, or slice can be relied upon to be 64-bit aligned. - timeout time.Time -} - -func (Self *ReceiveWindowQueue) New() { - Self.readOp = make(chan struct{}) - Self.chain = new(bufChain) - Self.chain.new(64) - Self.stopOp = make(chan struct{}, 2) -} - -func (Self *ReceiveWindowQueue) Push(element *common.ListElement) { - var length, wait uint32 - for { - ptrs := atomic.LoadUint64(&Self.lengthWait) - length, wait = Self.chain.head.unpack(ptrs) - length += uint32(element.L) - if atomic.CompareAndSwapUint64(&Self.lengthWait, ptrs, Self.chain.head.pack(length, 0)) { - break - } - // another goroutine change the length or into wait, make sure - } - //logs.Warn("window push before", Self.Len(), uint32(element.l), len(element.buf)) - Self.chain.pushHead(unsafe.Pointer(element)) - //logs.Warn("window push", Self.Len()) - if wait == 1 { - Self.allowPop() - } - return -} - -func (Self *ReceiveWindowQueue) Pop() (element *common.ListElement, err error) { - var length uint32 -startPop: - ptrs := atomic.LoadUint64(&Self.lengthWait) - length, _ = Self.chain.head.unpack(ptrs) - if length == 0 { - if !atomic.CompareAndSwapUint64(&Self.lengthWait, ptrs, Self.chain.head.pack(0, 1)) { - goto startPop // another goroutine is pushing - } - err = Self.waitPush() - // there is no more data in queue, wait for it - if err != nil { - return - } - goto startPop // wait finish, trying to get the new status - } - // length is not zero, so try to pop - for { - element = Self.TryPop() - if element != nil { - return - } - runtime.Gosched() // another goroutine is still pushing - } -} - -func (Self *ReceiveWindowQueue) TryPop() (element *common.ListElement) { - ptr, ok := Self.chain.popTail() - if ok { - //logs.Warn("window pop before", Self.Len()) - element = (*common.ListElement)(ptr) - atomic.AddUint64(&Self.lengthWait, ^(uint64(element.L)<> dequeueBits) & mask) - tail = uint32(ptrs & mask) - return -} - -func (d *bufDequeue) pack(head, tail uint32) uint64 { - const mask = 1< 0 { - runtime.Gosched() - } - for { - ptrs := atomic.LoadUint64(&d.headTail) - head, tail := d.unpack(ptrs) - if (tail+uint32(len(d.vals)))&(1<= 3 && atomic.LoadUint32(&d.starving) > 0 { - atomic.StoreUint32(&d.starving, 0) - } - break - } - starve++ - if starve >= 3 { - atomic.StoreUint32(&d.starving, 1) - } - } - // The head slot is free, so we own it. - *slot = val - return true -} - -// popTail removes and returns the element at the tail of the queue. -// It returns false if the queue is empty. It may be called by any -// number of consumers. -func (d *bufDequeue) popTail() (unsafe.Pointer, bool) { - ptrs := atomic.LoadUint64(&d.headTail) - head, tail := d.unpack(ptrs) - if tail == head { - // Queue is empty. - return nil, false - } - slot := &d.vals[tail&uint32(len(d.vals)-1)] - var val unsafe.Pointer - for { - val = atomic.LoadPointer(slot) - if val != nil { - // We now own slot. - break - } - // Another goroutine is still pushing data on the tail. - } - - // Tell pushHead that we're done with this slot. Zeroing the - // slot is also important so we don't leave behind references - // that could keep this object live longer than necessary. - // - // We write to val first and then publish that we're done with - atomic.StorePointer(slot, nil) - // At this point pushHead owns the slot. - if tail < math.MaxUint32 { - atomic.AddUint64(&d.headTail, 1) - } else { - atomic.AddUint64(&d.headTail, ^uint64(math.MaxUint32-1)) - } - return val, true -} - -// bufChain is a dynamically-sized version of bufDequeue. -// -// This is implemented as a doubly-linked list queue of poolDequeues -// where each dequeue is double the size of the previous one. Once a -// dequeue fills up, this allocates a new one and only ever pushes to -// the latest dequeue. Pops happen from the other end of the list and -// once a dequeue is exhausted, it gets removed from the list. -type bufChain struct { - // head is the bufDequeue to push to. This is only accessed - // by the producer, so doesn't need to be synchronized. - head *bufChainElt - - // tail is the bufDequeue to popTail from. This is accessed - // by consumers, so reads and writes must be atomic. - tail *bufChainElt - newChain uint32 -} - -type bufChainElt struct { - bufDequeue - - // next and prev link to the adjacent poolChainElts in this - // bufChain. - // - // next is written atomically by the producer and read - // atomically by the consumer. It only transitions from nil to - // non-nil. - // - // prev is written atomically by the consumer and read - // atomically by the producer. It only transitions from - // non-nil to nil. - next, prev *bufChainElt -} - -func storePoolChainElt(pp **bufChainElt, v *bufChainElt) { - atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(pp)), unsafe.Pointer(v)) -} - -func loadPoolChainElt(pp **bufChainElt) *bufChainElt { - return (*bufChainElt)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(pp)))) -} - -func (c *bufChain) new(initSize int) { - // Initialize the chain. - // initSize must be a power of 2 - d := new(bufChainElt) - d.vals = make([]unsafe.Pointer, initSize) - storePoolChainElt(&c.head, d) - storePoolChainElt(&c.tail, d) -} - -func (c *bufChain) pushHead(val unsafe.Pointer) { -startPush: - for { - if atomic.LoadUint32(&c.newChain) > 0 { - runtime.Gosched() - } else { - break - } - } - - d := loadPoolChainElt(&c.head) - - if d.pushHead(val) { - return - } - - // The current dequeue is full. Allocate a new one of twice - // the size. - if atomic.CompareAndSwapUint32(&c.newChain, 0, 1) { - newSize := len(d.vals) * 2 - if newSize >= dequeueLimit { - // Can't make it any bigger. - newSize = dequeueLimit - } - - d2 := &bufChainElt{prev: d} - d2.vals = make([]unsafe.Pointer, newSize) - d2.pushHead(val) - storePoolChainElt(&c.head, d2) - storePoolChainElt(&d.next, d2) - atomic.StoreUint32(&c.newChain, 0) - return - } - goto startPush -} - -func (c *bufChain) popTail() (unsafe.Pointer, bool) { - d := loadPoolChainElt(&c.tail) - if d == nil { - return nil, false - } - - for { - // It's important that we load the next pointer - // *before* popping the tail. In general, d may be - // transiently empty, but if next is non-nil before - // the TryPop and the TryPop fails, then d is permanently - // empty, which is the only condition under which it's - // safe to drop d from the chain. - d2 := loadPoolChainElt(&d.next) - - if val, ok := d.popTail(); ok { - return val, ok - } - - if d2 == nil { - // This is the only dequeue. It's empty right - // now, but could be pushed to in the future. - return nil, false - } - - // The tail of the chain has been drained, so move on - // to the next dequeue. Try to drop it from the chain - // so the next TryPop doesn't have to look at the empty - // dequeue again. - if atomic.CompareAndSwapPointer((*unsafe.Pointer)(unsafe.Pointer(&c.tail)), unsafe.Pointer(d), unsafe.Pointer(d2)) { - // We won the race. Clear the prev pointer so - // the garbage collector can collect the empty - // dequeue and so popHead doesn't back up - // further than necessary. - storePoolChainElt(&d2.prev, nil) - } - d = d2 - } -} diff --git a/lib/mux/sysGetsock_nowindows.go b/lib/mux/sysGetsock_nowindows.go deleted file mode 100644 index 85d2197..0000000 --- a/lib/mux/sysGetsock_nowindows.go +++ /dev/null @@ -1,46 +0,0 @@ -// +build !windows - -package mux - -import ( - "errors" - "github.com/xtaci/kcp-go" - "net" - "os" - "syscall" -) - -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 5 * 1024 * 1024, nil - } -} - -func getConnFd(c net.Conn) (fd *os.File, err error) { - switch c.(type) { - case *net.TCPConn: - fd, err = c.(*net.TCPConn).File() - if err != nil { - return - } - return - case *net.UDPConn: - fd, err = c.(*net.UDPConn).File() - if err != nil { - return - } - return - case *kcp.UDPSession: - //fd, err = (*net.UDPConn)(unsafe.Pointer(c.(*kcp.UDPSession))).File() - //if err != nil { - // return - //} - // Todo - return - default: - err = errors.New("mux:unknown conn type, only tcp or kcp") - return - } -} diff --git a/lib/mux/sysGetsock_windows.go b/lib/mux/sysGetsock_windows.go deleted file mode 100644 index 579d620..0000000 --- a/lib/mux/sysGetsock_windows.go +++ /dev/null @@ -1,46 +0,0 @@ -// +build windows - -package mux - -import ( - "errors" - "github.com/xtaci/kcp-go" - "net" - "os" -) - -func sysGetSock(fd *os.File) (bufferSize int, err error) { - // https://github.com/golang/sys/blob/master/windows/syscall_windows.go#L1184 - // not support, WTF??? - // Todo - // return syscall.GetsockoptInt((syscall.Handle)(unsafe.Pointer(fd.Fd())), syscall.SOL_SOCKET, syscall.SO_RCVBUF) - bufferSize = 5 * 1024 * 1024 - return -} - -func getConnFd(c net.Conn) (fd *os.File, err error) { - switch c.(type) { - case *net.TCPConn: - //fd, err = c.(*net.TCPConn).File() - //if err != nil { - // return - //} - return - case *net.UDPConn: - //fd, err = c.(*net.UDPConn).File() - //if err != nil { - // return - //} - return - case *kcp.UDPSession: - //fd, err = (*net.UDPConn)(unsafe.Pointer(c.(*kcp.UDPSession))).File() - //if err != nil { - // return - //} - // Todo - return - default: - err = errors.New("mux:unknown conn type, only tcp or kcp") - return - } -} diff --git a/lib/mux/web.go b/lib/mux/web.go deleted file mode 100644 index 36b2017..0000000 --- a/lib/mux/web.go +++ /dev/null @@ -1,154 +0,0 @@ -package mux - -import ( - "fmt" - "github.com/astaxie/beego/logs" - "net/http" - "sort" - "strconv" - "strings" - "sync" - "time" -) - -type connLog struct { - startTime time.Time - isClose bool - logs []string -} - -var logms map[int]*connLog -var logmc map[int]*connLog - -var copyMaps map[int]*connLog -var copyMapc map[int]*connLog -var stashTimeNow time.Time -var mutex sync.Mutex - -func deepCopyMaps() { - copyMaps = make(map[int]*connLog) - for k, v := range logms { - copyMaps[k] = &connLog{ - startTime: v.startTime, - isClose: v.isClose, - logs: v.logs, - } - } -} - -func deepCopyMapc() { - copyMapc = make(map[int]*connLog) - for k, v := range logmc { - copyMapc[k] = &connLog{ - startTime: v.startTime, - isClose: v.isClose, - logs: v.logs, - } - } -} - -func init() { - logms = make(map[int]*connLog) - logmc = make(map[int]*connLog) -} - -type IntSlice []int - -func (s IntSlice) Len() int { return len(s) } - -func (s IntSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } - -func (s IntSlice) Less(i, j int) bool { return s[i] < s[j] } - -func NewLogServer() { - http.HandleFunc("/", index) - http.HandleFunc("/detail", detail) - http.HandleFunc("/stash", stash) - fmt.Println(http.ListenAndServe(":8899", nil)) -} - -func stash(w http.ResponseWriter, r *http.Request) { - stashTimeNow = time.Now() - deepCopyMaps() - deepCopyMapc() - w.Write([]byte("ok")) -} - -func getM(label string, id int) (cL *connLog) { - label = strings.TrimSpace(label) - mutex.Lock() - defer mutex.Unlock() - if label == "nps" { - cL = logms[id] - } - if label == "npc" { - cL = logmc[id] - } - return -} - -func setM(label string, id int, cL *connLog) { - label = strings.TrimSpace(label) - mutex.Lock() - defer mutex.Unlock() - if label == "nps" { - logms[id] = cL - } - if label == "npc" { - logmc[id] = cL - } -} - -func index(w http.ResponseWriter, r *http.Request) { - var keys []int - for k := range copyMaps { - keys = append(keys, k) - } - sort.Sort(IntSlice(keys)) - var s string - s += "

nps

" - for _, v := range keys { - connL := copyMaps[v] - s += "" + strconv.Itoa(v) + "----------" - s += strconv.Itoa(int(stashTimeNow.Sub(connL.startTime).Milliseconds())) + "ms----------" - s += strconv.FormatBool(connL.isClose) - s += "
" - } - - keys = keys[:0] - s += "

npc

" - for k := range copyMapc { - keys = append(keys, k) - } - sort.Sort(IntSlice(keys)) - - for _, v := range keys { - connL := copyMapc[v] - s += "" + strconv.Itoa(v) + "----------" - s += strconv.Itoa(int(stashTimeNow.Sub(connL.startTime).Milliseconds())) + "ms----------" - s += strconv.FormatBool(connL.isClose) - s += "
" - } - w.Write([]byte(s)) -} - -func detail(w http.ResponseWriter, r *http.Request) { - id := r.FormValue("id") - label := r.FormValue("label") - logs.Warn(label) - i, _ := strconv.Atoi(id) - var v *connLog - if label == "nps" { - v, _ = copyMaps[i] - } - if label == "npc" { - v, _ = copyMapc[i] - } - var s string - if v != nil { - for i, vv := range v.logs { - s += "

" + strconv.Itoa(i+1) + ":" + vv + "

" - } - } - w.Write([]byte(s)) -} diff --git a/lib/mux/web_test.go b/lib/mux/web_test.go deleted file mode 100644 index 91a0430..0000000 --- a/lib/mux/web_test.go +++ /dev/null @@ -1,7 +0,0 @@ -package mux - -import "testing" - -func TestWeb(t *testing.T) { - NewLogServer() -} diff --git a/lib/mux/pconn.go b/lib/pmux/pconn.go similarity index 99% rename from lib/mux/pconn.go rename to lib/pmux/pconn.go index 35af3cc..d4330ef 100644 --- a/lib/mux/pconn.go +++ b/lib/pmux/pconn.go @@ -1,4 +1,4 @@ -package mux +package pmux import ( "net" diff --git a/lib/mux/plistener.go b/lib/pmux/plistener.go similarity index 98% rename from lib/mux/plistener.go rename to lib/pmux/plistener.go index 9bdaabc..deef001 100644 --- a/lib/mux/plistener.go +++ b/lib/pmux/plistener.go @@ -1,4 +1,4 @@ -package mux +package pmux import ( "errors" diff --git a/lib/mux/pmux.go b/lib/pmux/pmux.go similarity index 97% rename from lib/mux/pmux.go rename to lib/pmux/pmux.go index f4e9d4a..0dffb3e 100644 --- a/lib/mux/pmux.go +++ b/lib/pmux/pmux.go @@ -1,6 +1,6 @@ // This module is used for port reuse // Distinguish client, web manager , HTTP and HTTPS according to the difference of protocol -package mux +package pmux import ( "bufio" @@ -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" ) @@ -139,7 +139,7 @@ func (pMux *PortMux) process(conn net.Conn) { func (pMux *PortMux) Close() error { if pMux.isClose { - return errors.New("the port mux has closed") + return errors.New("the port pmux has closed") } pMux.isClose = true close(pMux.clientConn) diff --git a/lib/mux/pmux_test.go b/lib/pmux/pmux_test.go similarity index 98% rename from lib/mux/pmux_test.go rename to lib/pmux/pmux_test.go index 4c8e44e..6a17ddd 100644 --- a/lib/mux/pmux_test.go +++ b/lib/pmux/pmux_test.go @@ -1,4 +1,4 @@ -package mux +package pmux import ( "testing" diff --git a/server/connection/connection.go b/server/connection/connection.go index dbd74ca..f614622 100644 --- a/server/connection/connection.go +++ b/server/connection/connection.go @@ -5,12 +5,12 @@ import ( "os" "strconv" + "ehang.io/nps/lib/pmux" "github.com/astaxie/beego" "github.com/astaxie/beego/logs" - "github.com/cnlh/nps/lib/mux" ) -var pMux *mux.PortMux +var pMux *pmux.PortMux var bridgePort string var httpsPort string var httpPort string @@ -28,7 +28,7 @@ func InitConnectionService() { logs.Error(err) os.Exit(0) } - pMux = mux.NewPortMux(port, beego.AppConfig.String("web_host")) + pMux = pmux.NewPortMux(port, beego.AppConfig.String("web_host")) } } 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..9cf0ce7 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 { @@ -30,11 +30,12 @@ type httpServer struct { httpsServer *http.Server httpsListener net.Listener useCache bool + addOrigin bool cache *cache.Cache cacheLen int } -func NewHttp(bridge *bridge.Bridge, c *file.Tunnel, httpPort, httpsPort int, useCache bool, cacheLen int) *httpServer { +func NewHttp(bridge *bridge.Bridge, c *file.Tunnel, httpPort, httpsPort int, useCache bool, cacheLen int, addOrigin bool) *httpServer { httpServer := &httpServer{ BaseServer: BaseServer{ task: c, @@ -45,6 +46,7 @@ func NewHttp(bridge *bridge.Bridge, c *file.Tunnel, httpPort, httpsPort int, use httpsPort: httpsPort, useCache: useCache, cacheLen: cacheLen, + addOrigin: addOrigin, } if useCache { httpServer.cache = cache.New(cacheLen) @@ -214,7 +216,7 @@ reset: } //change the host and header and set proxy setting - common.ChangeHostAndHeader(r, host.HostChange, host.HeaderChange, c.Conn.RemoteAddr().String()) + common.ChangeHostAndHeader(r, host.HostChange, host.HeaderChange, c.Conn.RemoteAddr().String(), s.addOrigin) logs.Trace("%s request, method %s, host %s, url %s, remote address %s, target %s", r.URL.Scheme, r.Method, r.Host, r.URL.Path, c.RemoteAddr().String(), lk.Host) //write lenConn = conn.NewLenConn(connClient) 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 ab780f7..37be87f 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..d5fa7ca 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" @@ -147,7 +147,8 @@ func NewMode(Bridge *bridge.Bridge, c *file.Tunnel) proxy.Service { httpsPort, _ := beego.AppConfig.Int("https_proxy_port") useCache, _ := beego.AppConfig.Bool("http_cache") cacheLen, _ := beego.AppConfig.Int("http_cache_length") - service = proxy.NewHttp(Bridge, c, httpPort, httpsPort, useCache, cacheLen) + addOrigin, _ := beego.AppConfig.Bool("http_add_origin_header") + service = proxy.NewHttp(Bridge, c, httpPort, httpsPort, useCache, cacheLen, addOrigin) } return service } 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..cf4da6a 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 { @@ -33,10 +33,13 @@ func (s *BaseController) Prepare() { timestamp := s.GetIntNoErr("timestamp") configKey := beego.AppConfig.String("auth_key") timeNowUnix := time.Now().Unix() - if !((math.Abs(float64(timeNowUnix-int64(timestamp))) <= 20) && (crypt.Md5(configKey+strconv.Itoa(timestamp)) == md5Key)) { + if !(md5Key!="" && (math.Abs(float64(timeNowUnix-int64(timestamp))) <= 20) && (crypt.Md5(configKey+strconv.Itoa(timestamp)) == md5Key)) { if s.GetSession("auth") != true { s.Redirect(beego.AppConfig.String("web_base_url")+"/login/index", 302) } + }else { + s.SetSession("isAdmin",true) + s.Data["isAdmin"] = true } if s.GetSession("isAdmin") != nil && !s.GetSession("isAdmin").(bool) { s.Ctx.Input.SetData("client_id", s.GetSession("clientId").(int)) 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 @@ nps error -404 not found,power by nps +404 not found,power by nps \ 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 @@

- goto nps + goto nps

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 @@