code sync 代码同步

This commit is contained in:
tavenli
2020-12-01 21:19:37 +08:00
parent 11f762ce6e
commit 5f3a8d50e8
237 changed files with 7659 additions and 2106 deletions
+2
View File
@@ -0,0 +1,2 @@
logs
*.log
+26
View File
@@ -0,0 +1,26 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "forward-server",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}/forward-server",
"env": {},
"args": []
},
{
"name": "forward-agent",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}/forward-agent",
"env": {},
"args": []
}
]
}
+32
View File
@@ -0,0 +1,32 @@
{
"go.formatTool": "goimports",
"go.alternateTools": {
},
"[go]": {
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": true,
},
// Optional: Disable snippets, as they conflict with completion ranking.
"editor.snippetSuggestions": "none",
},
"[go.mod]": {
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": true,
},
},
"go.gotoSymbol.includeImports": true,
"go.gotoSymbol.includeGoroot": true,
"go.languageServerExperimentalFeatures": {
"diagnostics": true,
"documentLink": true
},
"go.trace.server": "verbose",
"go.overwriteGoplsMiddleware": {
},
"go.useLanguageServer": true
}
+127
View File
@@ -0,0 +1,127 @@
木兰宽松许可证, 第2版
木兰宽松许可证, 第2版
2020年1月 http://license.coscl.org.cn/MulanPSL2
您对“软件”的复制、使用、修改及分发受木兰宽松许可证,第2版(“本许可证”)的如下条款的约束:
0. 定义
“软件”是指由“贡献”构成的许可在“本许可证”下的程序和相关文档的集合。
“贡献”是指由任一“贡献者”许可在“本许可证”下的受版权法保护的作品。
“贡献者”是指将受版权法保护的作品许可在“本许可证”下的自然人或“法人实体”。
“法人实体”是指提交贡献的机构及其“关联实体”。
“关联实体”是指,对“本许可证”下的行为方而言,控制、受控制或与其共同受控制的机构,此处的控制是指有受控方或共同受控方至少50%直接或间接的投票权、资金或其他有价证券。
1. 授予版权许可
每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的版权许可,您可以复制、使用、修改、分发其“贡献”,不论修改与否。
2. 授予专利许可
每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的(根据本条规定撤销除外)专利许可,供您制造、委托制造、使用、许诺销售、销售、进口其“贡献”或以其他方式转移其“贡献”。前述专利许可仅限于“贡献者”现在或将来拥有或控制的其“贡献”本身或其“贡献”与许可“贡献”时的“软件”结合而将必然会侵犯的专利权利要求,不包括对“贡献”的修改或包含“贡献”的其他结合。如果您或您的“关联实体”直接或间接地,就“软件”或其中的“贡献”对任何人发起专利侵权诉讼(包括反诉或交叉诉讼)或其他专利维权行动,指控其侵犯专利权,则“本许可证”授予您对“软件”的专利许可自您提起诉讼或发起维权行动之日终止。
3. 无商标许可
“本许可证”不提供对“贡献者”的商品名称、商标、服务标志或产品名称的商标许可,但您为满足第4条规定的声明义务而必须使用除外。
4. 分发限制
您可以在任何媒介中将“软件”以源程序形式或可执行形式重新分发,不论修改与否,但您必须向接收者提供“本许可证”的副本,并保留“软件”中的版权、商标、专利及免责声明。
5. 免责声明与责任限制
“软件”及其中的“贡献”在提供时不带任何明示或默示的担保。在任何情况下,“贡献者”或版权所有者不对任何人因使用“软件”或其中的“贡献”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于何种法律理论,即使其曾被建议有此种损失的可能性。
6. 语言
“本许可证”以中英文双语表述,中英文版本具有同等法律效力。如果中英文版本存在任何冲突不一致,以中文版为准。
条款结束
如何将木兰宽松许可证,第2版,应用到您的软件
如果您希望将木兰宽松许可证,第2版,应用到您的新软件,为了方便接收者查阅,建议您完成如下三步:
1, 请您补充如下声明中的空白,包括软件名、软件的首次发表年份以及您作为版权人的名字;
2, 请您在软件包的一级目录下创建以“LICENSE”为名的文件,将整个许可证文本放入该文件中;
3, 请将如下声明文本放入每个源文件的头部注释中。
Copyright (c) [Year] [name of copyright holder]
[Software Name] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
Mulan Permissive Software LicenseVersion 2
Mulan Permissive Software LicenseVersion 2 (Mulan PSL v2)
January 2020 http://license.coscl.org.cn/MulanPSL2
Your reproduction, use, modification and distribution of the Software shall be subject to Mulan PSL v2 (this License) with the following terms and conditions:
0. Definition
Software means the program and related documents which are licensed under this License and comprise all Contribution(s).
Contribution means the copyrightable work licensed by a particular Contributor under this License.
Contributor means the Individual or Legal Entity who licenses its copyrightable work under this License.
Legal Entity means the entity making a Contribution and all its Affiliates.
Affiliates means entities that control, are controlled by, or are under common control with the acting entity under this License, control means direct or indirect ownership of at least fifty percent (50%) of the voting power, capital or other securities of controlled or commonly controlled entity.
1. Grant of Copyright License
Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable copyright license to reproduce, use, modify, or distribute its Contribution, with modification or not.
2. Grant of Patent License
Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable (except for revocation under this Section) patent license to make, have made, use, offer for sale, sell, import or otherwise transfer its Contribution, where such patent license is only limited to the patent claims owned or controlled by such Contributor now or in future which will be necessarily infringed by its Contribution alone, or by combination of the Contribution with the Software to which the Contribution was contributed. The patent license shall not apply to any modification of the Contribution, and any other combination which includes the Contribution. If you or your Affiliates directly or indirectly institute patent litigation (including a cross claim or counterclaim in a litigation) or other patent enforcement activities against any individual or entity by alleging that the Software or any Contribution in it infringes patents, then any patent license granted to you under this License for the Software shall terminate as of the date such litigation or activity is filed or taken.
3. No Trademark License
No trademark license is granted to use the trade names, trademarks, service marks, or product names of Contributor, except as required to fulfill notice requirements in Section 4.
4. Distribution Restriction
You may distribute the Software in any medium with or without modification, whether in source or executable forms, provided that you provide recipients with a copy of this License and retain copyright, patent, trademark and disclaimer statements in the Software.
5. Disclaimer of Warranty and Limitation of Liability
THE SOFTWARE AND CONTRIBUTION IN IT ARE PROVIDED WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED. IN NO EVENT SHALL ANY CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO ANY DIRECT, OR INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING FROM YOUR USE OR INABILITY TO USE THE SOFTWARE OR THE CONTRIBUTION IN IT, NO MATTER HOW ITS CAUSED OR BASED ON WHICH LEGAL THEORY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
6. Language
THIS LICENSE IS WRITTEN IN BOTH CHINESE AND ENGLISH, AND THE CHINESE VERSION AND ENGLISH VERSION SHALL HAVE THE SAME LEGAL EFFECT. IN THE CASE OF DIVERGENCE BETWEEN THE CHINESE AND ENGLISH VERSIONS, THE CHINESE VERSION SHALL PREVAIL.
END OF THE TERMS AND CONDITIONS
How to Apply the Mulan Permissive Software LicenseVersion 2 (Mulan PSL v2) to Your Software
To apply the Mulan PSL v2 to your work, for easy identification by recipients, you are suggested to complete following three steps:
i Fill in the blanks in following statement, including insert your software name, the year of the first publication of your software, and your name identified as the copyright owner;
ii Create a file named “LICENSE” which contains the whole context of this License in the first directory of your software package;
iii Attach the statement to the appropriate annotated syntax at the beginning of each source file.
Copyright (c) [Year] [name of copyright holder]
[Software Name] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
+14 -5
View File
@@ -8,6 +8,19 @@ Go语言开发的端口转发工具 for port data forward
数据库:sqlite3
```
# 最近更新
```
v1.3.3 发布,增加 一键开启所有转发 和 一键关闭所有转发
v1.3.2 发布,服务稳定性已经过长时间的验证
v1.3.1 发布,增加程序启动自动开启转发
v1.2.9_beta 发布,完善点对点转发的稳定性,支持TCP和UDP协议转发
```
# 最新编译好的版本下载:
[http://git.oschina.net/tavenli/port-forward/releases](http://git.oschina.net/tavenli/port-forward/releases)
# 功能介绍
> 支持Web控制台添加端口映射
@@ -18,10 +31,6 @@ Go语言开发的端口转发工具 for port data forward
> 支持每条端口转发的同时,再分发给多个端口,满足某些测试场景
# 已编译好的程序包
[http://git.oschina.net/tavenli/port-forward/releases](http://git.oschina.net/tavenli/port-forward/releases)
# 使用交流群
@@ -30,7 +39,7 @@ Go语言开发的端口转发工具 for port data forward
# 快速安装说明
1. 下载编译好的程序包,并解压程序包
2. 执行 start.sh Linux)或 start.bat Win)命令
3. 打开浏览器,进入控制台,打开 http://127.0.0.1:8000/login
3. 打开浏览器,进入控制台,打开 http://127.0.0.1:8080/login
4. 输入用户 admin 密码 123456 进入控制台
+12
View File
@@ -0,0 +1,12 @@
package main
import "net"
type AgentClient struct {
cid string
encode, decode func([]byte) []byte
authed bool
conn net.Conn
}
+5
View File
@@ -0,0 +1,5 @@
package main
type AgentService struct {
}
+144
View File
@@ -0,0 +1,144 @@
package main
import (
"bufio"
"forward-core/Constant"
"forward-core/NetUtils"
"github.com/astaxie/beego/logs"
"io"
"net"
"strconv"
"time"
)
type AgentServiceV1 struct {
localConnMap map[int]net.Conn
MagicServerAddr string
AgentOnline bool
}
func (_self *AgentServiceV1) ConnToMagicServer() {
serviceConn, err := net.DialTimeout("tcp", _self.MagicServerAddr, 30*time.Second)
if err != nil {
logs.Error("try dial err", err)
_self.AgentOnline = false
return
}
callback := func(conn net.Conn, sessionId int, cmd byte, payload []byte) {
//payload 收到的消息内容
_self.OnTunnelRecv(conn, sessionId, cmd, payload)
}
logs.Debug("开始接收服务端返回指令或数据...")
_self.AgentOnline = true
go NetUtils.ReadConn(serviceConn, callback)
}
func (_self *AgentServiceV1) OnTunnelRecv(conn net.Conn, sessionId int, cmd byte, payload []byte) {
logs.Debug("收到一条给 sessionId", sessionId, " 客户端的数据,指令是:", cmd)
switch cmd {
case Constant.MagicCmd_AgentListenerOpen:
targetAddr := string(payload)
go _self.ListenForClient(targetAddr, _self.MagicServerAddr)
case Constant.MagicCmd_AgentConnOpen:
targetAddr := string(payload)
logs.Debug("sessionId", sessionId, " 收到 AgentConnOpen 指令是,打开本地连接:", targetAddr)
//AgentConnOpen 让连接进来的客户端,在它的本地创建一个连接,并关联好sessionId
localConn, err := net.DialTimeout("tcp", targetAddr, 30*time.Second)
if err != nil {
logs.Error("try dial err", err)
return
}
_self.localConnMap[sessionId] = localConn
//接收 localConn 返回数据,并将返回的数据,写回给 conn,带上 sessionId
go _self.ReadRawConn(localConn, conn, sessionId, Constant.MagicCmd_DataToMagic)
case Constant.MagicCmd_DataToAgent:
logs.Debug("sessionId", sessionId, " 收到 MsgToAgent 指令")
localConn := _self.localConnMap[sessionId]
localConn.Write(payload)
logs.Debug("sessionId", sessionId, " 数据已写入本地目标连接")
case Constant.MagicCmd_Refused:
//client := string(payload)
logs.Debug("Magic服务端拒绝本次连接")
}
}
func (_self *AgentServiceV1) ReadRawConn(from net.Conn, magic_client_Conn net.Conn, sessionId int, cmd byte) {
arr := make([]byte, 5000)
reader := bufio.NewReader(from)
for {
size, err := reader.Read(arr)
if err != nil {
break
}
err = NetUtils.WriteConn(magic_client_Conn, sessionId, cmd, arr[0:size])
if err != nil {
//有异常
logs.Error(err)
break
}
}
}
func (_self *AgentServiceV1) ListenForClient(localListenAddr, toAddr string) {
client_listener, err := net.Listen("tcp", localListenAddr)
if err != nil {
logs.Error("ListenForClient err:", err)
return
}
for {
logs.Debug("ListenForClient Ready to Accept ...")
client_Conn, err := client_listener.Accept()
if err != nil {
logs.Error("Accept err:", err)
break
}
//连接到远程服务
serviceConn, err := net.DialTimeout("tcp", toAddr, 30*time.Second)
if err != nil {
logs.Error("try dial err", err)
return
}
go func() {
_, err = io.Copy(serviceConn, client_Conn)
if err != nil {
logs.Error("to magic_client 网络连接异常:", err)
}
}()
go func() {
_, err = io.Copy(client_Conn, serviceConn)
if err != nil {
logs.Error("to magic_client 网络连接异常2", err)
}
}()
}
}
func (_self *AgentServiceV1) ConnectToMagicLoop() {
//客户端与服务端建立连接
if !_self.AgentOnline {
_self.ConnToMagicServer()
delay := 3
time.AfterFunc(time.Second*time.Duration(delay), func() {
_self.ConnectToMagicLoop()
})
logs.Debug("reConnect after " + strconv.Itoa(delay) + " seconds")
}
}
+13
View File
@@ -0,0 +1,13 @@
echo "Build For windows..."
set GOOS=windows
set GOARCH=amd64
go build -o forward-agent.exe
echo "--------- Build For windows Success!"
pause
+3
View File
@@ -0,0 +1,3 @@
magic.server = "127.0.0.1:7000"
+10
View File
@@ -0,0 +1,10 @@
module forward-agent
go 1.14
require (
forward-core v0.0.0-00010101000000-000000000000
github.com/astaxie/beego v1.12.2
)
replace forward-core => ../forward-core
+214
View File
@@ -0,0 +1,214 @@
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk=
github.com/astaxie/beego v1.12.2 h1:CajUexhSX5ONWDiSCpeQBNVfTzOtPb9e9d+3vuU5FuU=
github.com/astaxie/beego v1.12.2/go.mod h1:TMcqhsbhN3UFpN+RCfysaxPAbrhox6QSS3NIAEp/uzE=
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 h1:OYA+5W64v3OgClL+IrOD63t4i/RW7RqrAVl9LTZ9UqQ=
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394/go.mod h1:Q8n74mJTIgjX4RBBcHnJ05h//6/k6foqmgE45jTQtxg=
github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd/go.mod h1:1b+Y/CofkYwXMUU0OhQqGvsY2Bvgr4j6jfT699wyZKQ=
github.com/beego/x2j v0.0.0-20131220205130-a0352aadc542/go.mod h1:kSeGC/p1AbBiEp5kat81+DSQrZenVBZXklMLaELspWU=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60=
github.com/casbin/casbin v1.7.0/go.mod h1:c67qKN6Oum3UF5Q1+BByfFxkwKvhwW57ITjqwtzR1KE=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80=
github.com/couchbase/go-couchbase v0.0.0-20200519150804-63f3cdb75e0d/go.mod h1:TWI8EKQMs5u5jLKW/tsb9VwauIrMIxQG1r5fMsswK5U=
github.com/couchbase/gomemcached v0.0.0-20200526233749-ec430f949808/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c=
github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/elastic/go-elasticsearch/v6 v6.8.5/go.mod h1:UwaDJsD3rWLM5rKNFzv9hgox93HoX8utj1kxD9aFUcI=
github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk=
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/glendc/gopher-json v0.0.0-20170414221815-dc4743023d0c/go.mod h1:Gja1A+xZ9BoviGJNA2E9vFkPjjsl+CoJxSXiQM1UXtw=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-redis/redis v6.14.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/klauspost/cpuid v1.2.4 h1:EBfaK0SWSwk+fgk6efYFWdzl8MwRWoOO1gkmiaTXPW4=
github.com/klauspost/cpuid v1.2.4/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/reedsolomon v1.9.9 h1:qCL7LZlv17xMixl55nq2/Oa1Y86nfO8EqDfv2GHND54=
github.com/klauspost/reedsolomon v1.9.9/go.mod h1:O7yFFHiQwDR6b2t63KPUpccPtNdp5ADgh1gg4fd12wo=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/ledisdb/ledisdb v0.0.0-20200510135210-d35789ec47e6/go.mod h1:n931TsDuKuq+uX4v1fulaMbA/7ZLLhjc85h7chZGBCQ=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mmcloughlin/avo v0.0.0-20200803215136-443f81d77104 h1:ULR/QWMgcgRiZLUjSSJMU+fW+RDMstRdmnDWj9Q+AsA=
github.com/mmcloughlin/avo v0.0.0-20200803215136-443f81d77104/go.mod h1:wqKykBG2QzQDJEzvRkcS8x6MiSJkF52hXZsXcjaB3ls=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/pelletier/go-toml v1.0.1/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/peterh/liner v1.0.1-0.20171122030339-3681c2a91233/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.7.0 h1:wCi7urQOGBsYcQROHqpUUX4ct84xp40t9R9JX0FuA/U=
github.com/prometheus/client_golang v1.7.0/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 h1:X+yvsM2yrEktyI+b2qND5gpH8YhURn0k8OCaeRnkINo=
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
github.com/siddontang/go v0.0.0-20170517070808-cb568a3e5cc0/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
github.com/siddontang/goredis v0.0.0-20150324035039-760763f78400/go.mod h1:DDcKzU3qCuvj/tPnimWSsZZzvk9qvkvrIL5naVBPh5s=
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec/go.mod h1:QBvMkMya+gXctz3kmljlUCu/yB3GZ6oee+dUozsezQE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/syndtr/goleveldb v0.0.0-20160425020131-cfa635847112/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
github.com/ugorji/go v0.0.0-20171122102828-84cb69a8af83/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
github.com/ugorji/go v1.1.13 h1:nB3O5kBSQGjEQAcfe1aLUYuxmXdFKmYgBZhY32rQb6Q=
github.com/ugorji/go v1.1.13/go.mod h1:jxau1n+/wyTGLQoCkjok9r5zFa/FxT6eI5HiHKQszjc=
github.com/ugorji/go/codec v1.1.13 h1:013LbFhocBoIqgHeIHKlV4JWYhqogATYWZhIcH0WHn4=
github.com/ugorji/go/codec v1.1.13/go.mod h1:oNVt3Dq+FO91WNQ/9JnHKQP2QJxTzoN7wCBFCq1OeuU=
github.com/vzex/internal v0.0.0-20171013154326-dfb733a0d236 h1:3trmo370DZOjjLG1dNmndVAUCfDD1f4jvu2xDDqrOs8=
github.com/vzex/internal v0.0.0-20171013154326-dfb733a0d236/go.mod h1:sHzPrs6FKhwLPhAS8dd78TXJ8oW08cHYUkMBhBJd2Yg=
github.com/vzex/mathutil v0.0.0-20170925121414-53c70789c7ff h1:FNV7atNSgquZ9j5esAroK2qdMPNtHxzGpyUO1L465b4=
github.com/vzex/mathutil v0.0.0-20170925121414-53c70789c7ff/go.mod h1:3+1ZBsJJLlEmRwraBhPTTMvgo+UFpm8nOVp2Eh0byM0=
github.com/vzex/zappy v0.0.0-20171014114341-f5f547bd8793 h1:Z+hNZ8IKayfetfivugi98jReDRvvh1jJmUpduzhxQqY=
github.com/vzex/zappy v0.0.0-20171014114341-f5f547bd8793/go.mod h1:foiOFrN9lntdJ5ekyxoLfolphrq3gi0vWRsjJvsWG+A=
github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/gopher-lua v0.0.0-20171031051903-609c9cd26973/go.mod h1:aEV29XrmTYFr3CiRxZeGHpkvbwq+prZduBqMaascyCU=
golang.org/x/arch v0.0.0-20190909030613-46d78d1859ac/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/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-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/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-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/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=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200117065230-39095c1d176c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200425043458-8463f397d07c h1:iHhCR0b26amDCiiO+kBguKZom9aMF+NrFxh9zeKR/XU=
golang.org/x/tools v0.0.0-20200425043458-8463f397d07c/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
+49
View File
@@ -0,0 +1,49 @@
package main
import (
"forward-core/Utils"
"github.com/astaxie/beego"
"github.com/astaxie/beego/logs"
)
func main() {
logs.SetLogger(logs.AdapterConsole, `{"level":7}`)
logs.SetLogger(logs.AdapterFile, `{"filename":"app.log","level":7,"maxlines":0,"maxsize":0,"daily":true,"maxdays":10}`)
//输出文件名和行号
logs.EnableFuncCallDepth(true)
logs.SetLogFuncCallDepth(3)
//为了让日志输出不影响性能,开启异步日志
logs.Async()
//远端外网服务
magicServerAddr := beego.AppConfig.String("magic.server")
logs.Debug("★★★★★★★★★★★★★★★★★★★★")
logs.Debug(" tcp-forward 启动")
logs.Debug("")
logs.Debug("项目地址:https://github.com/tavenli/port-forward")
logs.Debug("")
logs.Debug("请求远端控制服务器:", magicServerAddr)
logs.Debug("")
logs.Debug("★★★★★★★★★★★★★★★★★★★★")
if Utils.IsEmpty(magicServerAddr){
magicServerAddr = "forward.apiclub.top:7000"
}
agentService := new(AgentServiceV1)
agentService.MagicServerAddr = magicServerAddr
agentService.AgentOnline = false
go agentService.ConnToMagicServer()
go agentService.ConnectToMagicLoop()
select {
}
}
+12
View File
@@ -0,0 +1,12 @@
package Constant
const (
MagicCmd_AuthFail =byte(iota)
MagicCmd_ReqAuth
MagicCmd_Refused
MagicCmd_AgentListenerOpen
MagicCmd_AgentConnOpen
MagicCmd_AgentConnClose
MagicCmd_DataToMagic
MagicCmd_DataToAgent
)
+6
View File
@@ -0,0 +1,6 @@
package Constant
const (
RunStatus_Stoped =byte(iota)
RunStatus_Running
)
+14
View File
@@ -0,0 +1,14 @@
package Models
type ForwardConfig struct {
RuleId int
Name string
Status int
SrcAddr string
SrcPort int
Protocol string
DestAddr string
DestPort int
}
+15
View File
@@ -0,0 +1,15 @@
package Models
type ForwardInfo struct {
Name string
Status byte
SrcAddr string
SrcPort int
Protocol string
DestAddr string
DestPort int
OnlineCount int
Clients []string
}
@@ -1,6 +1,6 @@
package models
package Models
type ResultData struct {
type FuncResult struct {
Code int32
Msg string
Data interface{}
@@ -1,4 +1,4 @@
package models
package Models
type LoginUser struct {
UserId int
@@ -1,4 +1,4 @@
package models
package Models
type PageData struct {
PIndex int64
@@ -1,6 +1,8 @@
package models
package Models
import "port-forward/utils"
import (
"forward-core/Utils"
)
type PageParam struct {
PIndex int64
@@ -19,8 +21,8 @@ func (this *PageParam) PageSize() int {
// 分页, 排序处理
func (this *PageParam) SkipRows() int {
this.PIndex = utils.If(this.PIndex < 1, 1, this.PIndex).(int64)
this.PSize = utils.If(this.PSize < 1, 5, this.PSize).(int64)
this.PIndex = Utils.If(this.PIndex < 1, 1, this.PIndex).(int64)
this.PSize = Utils.If(this.PSize < 1, 5, this.PSize).(int64)
skipRows := (this.PIndex - 1) * this.PSize
return int(skipRows)
@@ -28,8 +30,8 @@ func (this *PageParam) SkipRows() int {
func (this *PageParam) SortField() string {
var sortField string
if !utils.IsEmpty(this.Sort) {
if !utils.IsEmpty(this.Direction) && this.Direction == "DESC" {
if !Utils.IsEmpty(this.Sort) {
if !Utils.IsEmpty(this.Direction) && this.Direction == "DESC" {
//降序
sortField = "-" + this.Sort
} else {
@@ -1,4 +1,4 @@
package models
package Models
import (
"time"
+7
View File
@@ -0,0 +1,7 @@
package Models
type PortInfo struct {
Addr string
Port int
}
@@ -1,4 +1,4 @@
package models
package Models
import (
"time"
+110
View File
@@ -0,0 +1,110 @@
package NetUtils
import (
"bytes"
"encoding/binary"
"github.com/axgle/mahonia"
)
func WriteBYTE(data *bytes.Buffer, val uint8) {
//BYTE 长度:1
buf := make([]byte, 1)
buf[0] = byte(val)
data.Write(buf)
}
func WriteWORD(data *bytes.Buffer, val uint16) {
//WORD 长度:2
buf := make([]byte, 2)
buf[0] = byte(val)
buf[1] = byte(val >> 8)
data.Write(buf)
}
func WriteDWORD(data *bytes.Buffer, val uint32) {
//DWORD 长度:4
buf := make([]byte, 4)
buf[0] = byte(val)
buf[1] = byte(val >> 8)
buf[2] = byte(val >> 16)
buf[3] = byte(val >> 24)
data.Write(buf)
}
func WriteTCHAR(data *bytes.Buffer, size int, val string) {
//TCHAR 长度:由size指定
buf := []byte(val)
data.Write(buf)
//
for i := 0; i < size-len(buf); i++ {
//剩余的补0
data.WriteByte(0)
}
}
func WriteUnicodeTCHAR(data *bytes.Buffer, size int, val string) {
//Unicode TCHAR 长度:size*2
realSize := size * 2
buf := []byte(val)
dataBuffer := make([]byte, realSize)
k := 0
for j := 0; j < len(buf); j++ {
dataBuffer[k] = buf[j]
dataBuffer[k+1] = byte(0)
k = k + 2
}
data.Write(dataBuffer)
//
}
func WriteInt(data *bytes.Buffer, val int) {
//Byte 长度:4
buf := make([]byte, 4)
buf[0] = byte(val)
buf[1] = byte(val >> 8)
buf[2] = byte(val >> 16)
buf[3] = byte(val >> 24)
data.Write(buf)
}
func _ReadInt_(data *bytes.Buffer, val []byte) (int, error) {
return data.Read(val)
}
func ReadWord(val []byte) uint16 {
//binary.LittleEndian.Uint16(rData[4:6])
return binary.LittleEndian.Uint16(val)
}
func ReadDWord(val []byte) uint32 {
return binary.LittleEndian.Uint32(val)
}
func ReadTCHAR(val []byte) string {
return string(val)
}
func UTF8_To_GBK(input string) string {
enc := mahonia.NewEncoder("GBK")
return enc.ConvertString(input)
}
func GBK_To_UTF8(input string) string {
dec := mahonia.NewDecoder("UTF-8")
return dec.ConvertString(input)
}
func U2W(input string) string {
//网狐荣耀版本的服务端TCHAR编码需要这样转换
dec := mahonia.NewDecoder("UTF-16LE")
return dec.ConvertString(input)
}
+128
View File
@@ -0,0 +1,128 @@
package NetUtils
import (
"errors"
"forward-core/Utils"
"io/ioutil"
"net/http"
"net/url"
"strings"
"bytes"
"github.com/astaxie/beego"
"github.com/astaxie/beego/logs"
)
func GetIP(c *beego.Controller) string {
//utils.GetIP(&c.Controller)
//也可以直接用 c.Ctx.Input.IP() 取真实IP
ip := c.Ctx.Request.Header.Get("X-Real-IP")
if ip != "" {
return ip
}
ip = c.Ctx.Request.Header.Get("Remote_addr")
if ip == "" {
ip = c.Ctx.Request.RemoteAddr
}
return ip
}
func HttpGet(url string) (string, error) {
resp, err := http.Get(url)
if err != nil {
logs.Error("HttpGet error: ", err)
return "", err
}
if resp == nil {
return "", errors.New("返回对象为空")
}
defer resp.Body.Close()
result := ""
body, err := ioutil.ReadAll(resp.Body)
if err == nil {
result = string(body)
//logs.Debug("HttpGet result: ", result)
} else {
logs.Error("HttpGet error: ", err)
}
return result, nil
}
func HttpPostJsonReturnByte(url string, json string) ([]byte, error) {
resp, err := http.Post(url, "application/json", strings.NewReader(json))
if err != nil {
logs.Error("HttpPostJson error: ", err)
return nil, err
}
if resp == nil {
return nil, errors.New("返回对象为空")
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err == nil {
return body, err
//logs.Debug("HttpPostJson result: ", result)
} else {
logs.Error("HttpPostJson error: ", err)
return nil, err
}
}
func HttpPost(url string, param map[string]string) (string, error) {
var paramBuf bytes.Buffer
paramBuf.WriteString("curTime=" + Utils.GetCurrentTime())
for k, v := range param {
paramBuf.WriteString("&" + k + "=" + v)
}
resp, err := http.Post(url, "application/x-www-form-urlencoded", strings.NewReader(paramBuf.String()))
if err != nil {
logs.Error("HttpPost error: ", err)
return "", err
}
if resp == nil {
return "", errors.New("返回对象为空")
}
defer resp.Body.Close()
result := ""
body, err := ioutil.ReadAll(resp.Body)
if err == nil {
result = string(body)
logs.Debug("HttpPost result: ", result)
} else {
logs.Error("HttpPost error: ", err)
}
return result, nil
}
func UrlEncode(input string) string {
if Utils.IsEmpty(input) {
return ""
}
return url.QueryEscape(input)
}
func UrlDecode(input string) string {
if Utils.IsEmpty(input) {
return ""
}
result, err := url.QueryUnescape(input)
if err != nil {
return input
} else {
return result
}
}
@@ -1,34 +1,60 @@
package common
package NetUtils
import (
"bufio"
"encoding/binary"
"errors"
"net"
"github.com/astaxie/beego/logs"
"io"
"net"
"forward-core/Common"
)
type NetCommon struct {
func NewTCP(addr string) (net.Listener, error) {
tcpSocket, err := net.Listen("tcp", addr)
if err != nil {
return nil, err
}
return tcpSocket,nil
}
func NewUDP(addr string) (*net.UDPConn, error) {
udpAddr, err := net.ResolveUDPAddr("udp", addr)
if err != nil {
return nil, err
}
udpSocket, _err := net.ListenUDP("udp", udpAddr)
if _err != nil {
return nil, _err
}
return udpSocket,nil
}
func NewKCP(addr string, setting *Common.KcpSetting) (*Common.UDPListener, error) {
return Common.NewKCP(addr, setting)
}
func DataCopy(dst io.Writer, src io.Reader) (written int64, err error) {
return io.Copy(dst, src)
}
func MultiDataCopy(src io.Reader, dispatchConns []io.Writer) (written int64, err error) {
mWriter := io.MultiWriter(dispatchConns...)
return io.Copy(mWriter, src)
}
type ReadCallBack func(conn net.Conn, id int, cmd byte, arg []byte)
const (
MagicAuthFail = byte(iota)
DoAuth
MagicRefused
AgentListenerOpen
AgentConnOpen
AgentConnClose
MsgToMagic
MsgToAgent
)
func (_self *NetCommon) ReadConn(conn net.Conn, callback ReadCallBack) {
func ReadConn(conn net.Conn, callback ReadCallBack) {
scanner := bufio.NewScanner(conn)
scanner.Split(func(data []byte, atEOF bool) (adv int, token []byte, err error) {
return _self.Split(data, atEOF, conn, callback)
return NetSplitV1(data, atEOF, conn, callback)
})
for scanner.Scan() {
}
@@ -37,11 +63,12 @@ func (_self *NetCommon) ReadConn(conn net.Conn, callback ReadCallBack) {
}
}
func (_self *NetCommon) Split(data []byte, atEOF bool, conn net.Conn, callback ReadCallBack) (adv int, token []byte, err error) {
func NetSplitV1(data []byte, atEOF bool, conn net.Conn, callback ReadCallBack) (adv int, token []byte, err error) {
l := len(data)
if l < 6 {
return 0, nil, nil
}
if l > 100000 {
conn.Close()
return 0, nil, errors.New("max data")
@@ -73,7 +100,7 @@ func (_self *NetCommon) Split(data []byte, atEOF bool, conn net.Conn, callback R
return offset, []byte{}, nil
}
func (_self *NetCommon) WriteConn(conn net.Conn, id int, cmd byte, payload []byte) error {
func WriteConn(conn net.Conn, id int, cmd byte, payload []byte) error {
if conn == nil {
return nil
}
-2
View File
@@ -1,2 +0,0 @@
# 公共类库
+46
View File
@@ -0,0 +1,46 @@
package Utils
func IntArrayFind(slice []int, value int) int {
for p, v := range slice {
if v == value {
return p
}
}
return -1
}
func IntArrayContain(slice []int, value int) bool {
for _, v := range slice {
if v == value {
return true
}
}
return false
}
func Int64ArrayFind(slice []int64, value int64) int {
for p, v := range slice {
if v == value {
return p
}
}
return -1
}
func Int64ArrayContain(slice []int64, value int64) bool {
for _, v := range slice {
if v == value {
return true
}
}
return false
}
func StrArrayContain(slice []string, value string) bool {
for _, v := range slice {
if v == value {
return true
}
}
return false
}
@@ -1,4 +1,4 @@
package utils
package Utils
import (
"crypto/md5"
@@ -1,6 +1,7 @@
package utils
package Utils
import (
"fmt"
"math"
"time"
)
@@ -149,3 +150,33 @@ func AddDays(_time time.Time, days int) time.Time {
func AddMonths(_time time.Time, months int) time.Time {
return _time.AddDate(0, months, 0)
}
func GetBeginTime(_time time.Time) time.Time {
//2017-06-28 00:00:00 +0800 CST
return GetBeginTimeByLoc(_time, time.Local)
//return GetBeginTimeByLoc(_time, time.UTC)
}
func GetEndTime(_time time.Time) time.Time {
//2017-06-28 23:59:59.999999999 +0800 CST
return GetEndTimeByLoc(_time, time.Local)
}
func GetBeginTimeByLoc(_time time.Time, loc *time.Location) time.Time {
year, month, day := _time.Date()
return time.Date(year, month, day, 0, 0, 0, 0, loc)
}
func GetEndTimeByLoc(_time time.Time, loc *time.Location) time.Time {
year, month, day := _time.Date()
return time.Date(year, month, day, 23, 59, 59, 999999999, loc)
}
// 一行代码计算代码执行时间
// defer utils.TimeCost(time.Now())
func TimeCost(start time.Time) {
terminal := time.Since(start)
fmt.Println("TimeCost", terminal)
}
@@ -1,16 +1,19 @@
package utils
package Utils
import (
"bytes"
"encoding/gob"
"encoding/json"
"fmt"
"github.com/json-iterator/go"
"reflect"
"github.com/astaxie/beego/logs"
"github.com/ugorji/go/codec"
)
var jsonIter = jsoniter.ConfigCompatibleWithStandardLibrary
func ToJson(obj interface{}) ([]byte, error) {
return json.Marshal(obj)
}
@@ -19,6 +22,14 @@ func FromJson(data []byte, t interface{}) error {
return json.Unmarshal(data, t)
}
func ToJsonIterator(obj interface{}) ([]byte, error) {
return jsonIter.Marshal(obj)
}
func FromJsonIterator(data []byte, t interface{}) error {
return jsonIter.Unmarshal(data, t)
}
func MsgpEncode(obj interface{}) []byte {
var mh codec.MsgpackHandle
mh.MapType = reflect.TypeOf(obj)
+60
View File
@@ -0,0 +1,60 @@
package Utils
import (
"math"
)
func AbsInt(num float64) int {
//result := math.Abs(float64(num))
result := math.Abs(num)
return int(result)
}
func AbsInt64(num float64) int64 {
result := math.Abs(num)
return int64(result)
}
func CeilInt(num float64) int {
result := math.Ceil(num)
return int(result)
}
func CeilInt64(num float64) int64 {
//CeilInt64(5.9) = 6
//CeilInt64(5.3) = 6
//CeilInt64(5) = 5
result := math.Ceil(num)
return int64(result)
}
func Float64ToInt64(num float64) int64 {
return int64(num)
}
func Float64TryToInt64(num interface{}) int64 {
return int64(num.(float64))
}
// 返回最大值
func MaxInt(a, b int) int {
if a > b {
return a
}
return b
}
// 返回最小值
func MinInt(a, b int) int {
if a < b {
return a
}
return b
}
func Pages(total, psize int64) int64 {
pages := float64(total) / float64(psize)
result := math.Ceil(pages)
return int64(result)
}
@@ -1,4 +1,4 @@
package utils
package Utils
import (
"bytes"
@@ -1,4 +1,4 @@
package utils
package Utils
import (
"fmt"
File diff suppressed because it is too large Load Diff
+15
View File
@@ -0,0 +1,15 @@
module forward-core
go 1.14
require (
github.com/astaxie/beego v1.12.2
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394
github.com/json-iterator/go v1.1.10
github.com/klauspost/reedsolomon v1.9.9
github.com/mmcloughlin/avo v0.0.0-20200803215136-443f81d77104 // indirect
github.com/ugorji/go/codec v1.1.13
github.com/vzex/internal v0.0.0-20171013154326-dfb733a0d236 // indirect
github.com/vzex/mathutil v0.0.0-20170925121414-53c70789c7ff // indirect
github.com/vzex/zappy v0.0.0-20171014114341-f5f547bd8793
)
+217
View File
@@ -0,0 +1,217 @@
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk=
github.com/astaxie/beego v1.12.2 h1:CajUexhSX5ONWDiSCpeQBNVfTzOtPb9e9d+3vuU5FuU=
github.com/astaxie/beego v1.12.2/go.mod h1:TMcqhsbhN3UFpN+RCfysaxPAbrhox6QSS3NIAEp/uzE=
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 h1:OYA+5W64v3OgClL+IrOD63t4i/RW7RqrAVl9LTZ9UqQ=
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394/go.mod h1:Q8n74mJTIgjX4RBBcHnJ05h//6/k6foqmgE45jTQtxg=
github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd/go.mod h1:1b+Y/CofkYwXMUU0OhQqGvsY2Bvgr4j6jfT699wyZKQ=
github.com/beego/x2j v0.0.0-20131220205130-a0352aadc542/go.mod h1:kSeGC/p1AbBiEp5kat81+DSQrZenVBZXklMLaELspWU=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60=
github.com/casbin/casbin v1.7.0/go.mod h1:c67qKN6Oum3UF5Q1+BByfFxkwKvhwW57ITjqwtzR1KE=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80=
github.com/couchbase/go-couchbase v0.0.0-20200519150804-63f3cdb75e0d/go.mod h1:TWI8EKQMs5u5jLKW/tsb9VwauIrMIxQG1r5fMsswK5U=
github.com/couchbase/gomemcached v0.0.0-20200526233749-ec430f949808/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c=
github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/elastic/go-elasticsearch/v6 v6.8.5/go.mod h1:UwaDJsD3rWLM5rKNFzv9hgox93HoX8utj1kxD9aFUcI=
github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk=
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/glendc/gopher-json v0.0.0-20170414221815-dc4743023d0c/go.mod h1:Gja1A+xZ9BoviGJNA2E9vFkPjjsl+CoJxSXiQM1UXtw=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-redis/redis v6.14.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/klauspost/cpuid v1.2.4 h1:EBfaK0SWSwk+fgk6efYFWdzl8MwRWoOO1gkmiaTXPW4=
github.com/klauspost/cpuid v1.2.4/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/reedsolomon v1.9.9 h1:qCL7LZlv17xMixl55nq2/Oa1Y86nfO8EqDfv2GHND54=
github.com/klauspost/reedsolomon v1.9.9/go.mod h1:O7yFFHiQwDR6b2t63KPUpccPtNdp5ADgh1gg4fd12wo=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/ledisdb/ledisdb v0.0.0-20200510135210-d35789ec47e6/go.mod h1:n931TsDuKuq+uX4v1fulaMbA/7ZLLhjc85h7chZGBCQ=
github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mmcloughlin/avo v0.0.0-20200803215136-443f81d77104 h1:ULR/QWMgcgRiZLUjSSJMU+fW+RDMstRdmnDWj9Q+AsA=
github.com/mmcloughlin/avo v0.0.0-20200803215136-443f81d77104/go.mod h1:wqKykBG2QzQDJEzvRkcS8x6MiSJkF52hXZsXcjaB3ls=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/pelletier/go-toml v1.0.1/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/peterh/liner v1.0.1-0.20171122030339-3681c2a91233/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.7.0 h1:wCi7urQOGBsYcQROHqpUUX4ct84xp40t9R9JX0FuA/U=
github.com/prometheus/client_golang v1.7.0/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 h1:X+yvsM2yrEktyI+b2qND5gpH8YhURn0k8OCaeRnkINo=
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
github.com/siddontang/go v0.0.0-20170517070808-cb568a3e5cc0/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
github.com/siddontang/goredis v0.0.0-20150324035039-760763f78400/go.mod h1:DDcKzU3qCuvj/tPnimWSsZZzvk9qvkvrIL5naVBPh5s=
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec/go.mod h1:QBvMkMya+gXctz3kmljlUCu/yB3GZ6oee+dUozsezQE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/syndtr/goleveldb v0.0.0-20160425020131-cfa635847112/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
github.com/ugorji/go v0.0.0-20171122102828-84cb69a8af83/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
github.com/ugorji/go v1.1.13 h1:nB3O5kBSQGjEQAcfe1aLUYuxmXdFKmYgBZhY32rQb6Q=
github.com/ugorji/go v1.1.13/go.mod h1:jxau1n+/wyTGLQoCkjok9r5zFa/FxT6eI5HiHKQszjc=
github.com/ugorji/go/codec v1.1.13 h1:013LbFhocBoIqgHeIHKlV4JWYhqogATYWZhIcH0WHn4=
github.com/ugorji/go/codec v1.1.13/go.mod h1:oNVt3Dq+FO91WNQ/9JnHKQP2QJxTzoN7wCBFCq1OeuU=
github.com/vzex/internal v0.0.0-20171013154326-dfb733a0d236 h1:3trmo370DZOjjLG1dNmndVAUCfDD1f4jvu2xDDqrOs8=
github.com/vzex/internal v0.0.0-20171013154326-dfb733a0d236/go.mod h1:sHzPrs6FKhwLPhAS8dd78TXJ8oW08cHYUkMBhBJd2Yg=
github.com/vzex/mathutil v0.0.0-20170925121414-53c70789c7ff h1:FNV7atNSgquZ9j5esAroK2qdMPNtHxzGpyUO1L465b4=
github.com/vzex/mathutil v0.0.0-20170925121414-53c70789c7ff/go.mod h1:3+1ZBsJJLlEmRwraBhPTTMvgo+UFpm8nOVp2Eh0byM0=
github.com/vzex/zappy v0.0.0-20171014114341-f5f547bd8793 h1:Z+hNZ8IKayfetfivugi98jReDRvvh1jJmUpduzhxQqY=
github.com/vzex/zappy v0.0.0-20171014114341-f5f547bd8793/go.mod h1:foiOFrN9lntdJ5ekyxoLfolphrq3gi0vWRsjJvsWG+A=
github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/gopher-lua v0.0.0-20171031051903-609c9cd26973/go.mod h1:aEV29XrmTYFr3CiRxZeGHpkvbwq+prZduBqMaascyCU=
golang.org/x/arch v0.0.0-20190909030613-46d78d1859ac/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/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-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/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-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/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=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200117065230-39095c1d176c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200425043458-8463f397d07c h1:iHhCR0b26amDCiiO+kBguKZom9aMF+NrFxh9zeKR/XU=
golang.org/x/tools v0.0.0-20200425043458-8463f397d07c/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
File diff suppressed because it is too large Load Diff
+57
View File
@@ -0,0 +1,57 @@
package ikcp
import "container/list"
//=====================================================================
//
// KCP - A Better ARQ Protocol Implementation
// skywind3000 (at) gmail.com, 2010-2011
//
// Features:
// + Average RTT reduce 30% - 40% vs traditional ARQ like tcp.
// + Maximum RTT reduce three times vs tcp.
// + Lightweight, distributed as a single source file.
//
//=====================================================================
//---------------------------------------------------------------------
// IKCPCB
//---------------------------------------------------------------------
type IKCPCB struct {
conv, mtu, mss, state uint32
snd_una, snd_nxt, rcv_nxt uint32
ts_recent, ts_lastack, ssthresh uint32
rx_rttval, rx_srtt, rx_rto, rx_minrto uint32
snd_wnd, rcv_wnd, rmt_wnd, cwnd, probe uint32
current, interval, ts_flush, xmit uint32
nrcv_buf, nsnd_buf uint32
nrcv_que, nsnd_que uint32
nodelay, updated uint32
ts_probe, probe_wait uint32
dead_link, incr uint32
snd_queue, rcv_queue, snd_buf, rcv_buf *list.List
acklist []uint32
ackcount uint32
ackblock uint32
user interface{}
buffer []byte
fastresend int32
nocwnd int32
logmask int32
writelog func (log []byte, kcp *Ikcpcb, user []byte)
Output func (buf []byte, _len int32, kcp *Ikcpcb, user interface{}) (int32)
}
type Ikcpcb struct {IKCPCB}
const IKCP_LOG_OUTPUT = 1
const IKCP_LOG_INPUT = 2
const IKCP_LOG_SEND = 4
const IKCP_LOG_RECV = 8
const IKCP_LOG_IN_DATA = 16
const IKCP_LOG_IN_ACK = 32
const IKCP_LOG_IN_PROBE = 64
const IKCP_LOG_IN_WIN = 128
const IKCP_LOG_OUT_DATA =256
const IKCP_LOG_OUT_ACK = 512
const IKCP_LOG_OUT_PROBE = 1024
const IKCP_LOG_OUT_WINS = 2048
+181
View File
@@ -0,0 +1,181 @@
package ikcp
import "encoding/binary"
import "bytes"
import "time"
import "fmt"
import "testing"
//=====================================================================
//=====================================================================
// 模拟网络
var vnet *LatencySimulator
// 模拟网络:模拟发送一个 udp包
func udp_output(buf []byte, _len int32, kcp *Ikcpcb, user interface{}) int32 {
arr := (user).([]byte)
var id uint32 = uint32(arr[0])
//println("send!!!!", id, _len)
if vnet.send(int(id), buf, int(_len)) != 1 {
//println("wocao !!!", id, _len)
}
return 0
}
// 测试用例
func test(mode int) {
// 创建模拟网络:丢包率10%Rtt 60ms~125ms
vnet = &LatencySimulator{}
vnet.Init(10, 60, 125, 1000)
// 创建两个端点的 kcp对象,第一个参数 conv是会话编号,同一个会话需要相同
// 最后一个是 user参数,用来传递标识
a := []byte {0}
b := []byte {1}
kcp1 := Ikcp_create(0x11223344, a)
kcp2 := Ikcp_create(0x11223344, b)
// 设置kcp的下层输出,这里为 udp_output,模拟udp网络输出函数
kcp1.Output = udp_output
kcp2.Output = udp_output
current := uint32(iclock())
slap := current + 20
index := 0
next := 0
var sumrtt uint32 = 0
count := 0
maxrtt := 0
// 配置窗口大小:平均延迟200ms,每20ms发送一个包,
// 而考虑到丢包重发,设置最大收发窗口为128
Ikcp_wndsize(kcp1, 128, 128)
Ikcp_wndsize(kcp2, 128, 128)
// 判断测试用例的模式
if (mode == 0) {
// 默认模式
Ikcp_nodelay(kcp1, 0, 10, 0, 0)
Ikcp_nodelay(kcp2, 0, 10, 0, 0)
} else if (mode == 1) {
// 普通模式,关闭流控等
Ikcp_nodelay(kcp1, 0, 10, 0, 1)
Ikcp_nodelay(kcp2, 0, 10, 0, 1)
} else {
// 启动快速模式
// 第二个参数 nodelay-启用以后若干常规加速将启动
// 第三个参数 interval为内部处理时钟,默认设置为 10ms
// 第四个参数 resend为快速重传指标,设置为2
// 第五个参数 为是否禁用常规流控,这里禁止
Ikcp_nodelay(kcp1, 1, 10, 2, 1)
Ikcp_nodelay(kcp2, 1, 10, 2, 1)
}
var buffer []byte = make([]byte, 2000)
var hr int32
ts1 := iclock()
for {
time.Sleep(10* time.Millisecond)
current = uint32(iclock())
Ikcp_update(kcp1,uint32(iclock()))
Ikcp_update(kcp2, uint32(iclock()))
// 每隔 20mskcp1发送数据
for ; current >= slap; slap += 20 {
buf := new(bytes.Buffer)
binary.Write(buf, binary.LittleEndian, uint32(index))
index++
binary.Write(buf, binary.LittleEndian, uint64(current))
// 发送上层协议包
Ikcp_send(kcp1, buf.Bytes(), 8)
//println("now", iclock())
}
// 处理虚拟网络:检测是否有udp包从p1->p2
for {
hr = vnet.recv(1, buffer, 2000)
if (hr < 0) {
break
}
// 如果 p2收到udp,则作为下层协议输入到kcp2
Ikcp_input(kcp2, buffer, int(hr))
}
// 处理虚拟网络:检测是否有udp包从p2->p1
for {
hr = vnet.recv(0, buffer, 2000)
if (hr < 0) { break }
// 如果 p1收到udp,则作为下层协议输入到kcp1
Ikcp_input(kcp1, buffer, int(hr))
//println("@@@@", hr, r)
}
// kcp2接收到任何包都返回回去
for {
hr = Ikcp_recv(kcp2, buffer, 10)
// 没有收到包就退出
if (hr < 0) { break }
// 如果收到包就回射
buf := bytes.NewReader(buffer)
var sn uint32
binary.Read(buf, binary.LittleEndian, &sn)
Ikcp_send(kcp2, buffer, int(hr))
}
// kcp1收到kcp2的回射数据
for {
hr = Ikcp_recv(kcp1, buffer, 10)
buf := bytes.NewReader(buffer)
// 没有收到包就退出
if (hr < 0) { break }
var sn uint32
var ts, rtt uint32
binary.Read(buf, binary.LittleEndian, &sn)
binary.Read(buf, binary.LittleEndian, &ts)
rtt = uint32(current) - ts
if (sn != uint32(next)) {
// 如果收到的包不连续
//for i:=0;i<8 ;i++ {
//println("---", i, buffer[i])
//}
println("ERROR sn ", count, "<->", next, sn)
return
}
next++
sumrtt += rtt
count++
if (rtt > uint32(maxrtt)) { maxrtt = int(rtt) }
println("[RECV] mode=", mode, " sn=",sn, " rtt=", rtt)
}
if (next > 100) { break }
}
ts1 = iclock() - ts1
names := []string{ "default", "normal", "fast" }
fmt.Printf("%s mode result (%dms):\n", names[mode], ts1)
fmt.Printf("avgrtt=%d maxrtt=%d\n", int(sumrtt / uint32(count)), maxrtt)
}
func TestNetwork(t *testing.T) {
test(0); // 默认模式,类似 TCP:正常模式,无快速重传,常规流控
test(1); // 普通模式,关闭流控等
test(2); // 快速模式,所有开关都打开,且关闭流控
}
/*
default mode result (20917ms):
avgrtt=740 maxrtt=1507
normal mode result (20131ms):
avgrtt=156 maxrtt=571
fast mode result (20207ms):
avgrtt=138 maxrtt=392
*/
+101
View File
@@ -0,0 +1,101 @@
package ikcp
import "container/list"
import "math/rand"
import "time"
func iclock() int32 {
return int32((time.Now().UnixNano()/1000000) & 0xffffffff)
}
type DelayPacket struct {
_ptr []byte
_size int
_ts int32
}
func (p *DelayPacket) Init(size int, src []byte) {
p._ptr = make([]byte, size)
p._size = size
copy(p._ptr, src[:size])
}
func (p *DelayPacket) ptr() []byte { return p._ptr }
func (p *DelayPacket) size() int { return p._size }
func (p *DelayPacket) ts() int32 { return p._ts }
func (p *DelayPacket) setts(ts int32) { p._ts = ts}
type DelayTunnel struct {*list.List}
type Random *rand.Rand
type LatencySimulator struct {
current int32
lostrate, rttmin, rttmax, nmax int
p12 DelayTunnel
p21 DelayTunnel
r12 *rand.Rand
r21 *rand.Rand
}
// lostrate: 往返一周丢包率的百分比,默认 10%
// rttminrtt最小值,默认 60
// rttmaxrtt最大值,默认 125
//func (p *LatencySimulator)Init(int lostrate = 10, int rttmin = 60, int rttmax = 125, int nmax = 1000):
func (p *LatencySimulator)Init(lostrate, rttmin ,rttmax, nmax int) {
p.r12 = rand.New(rand.NewSource(9))
p.r21 = rand.New(rand.NewSource(99))
p.p12 = DelayTunnel{list.New()}
p.p21 = DelayTunnel{list.New()}
p.current = iclock()
p.lostrate = lostrate / 2; // 上面数据是往返丢包率,单程除以2
p.rttmin = rttmin / 2
p.rttmax = rttmax / 2
p.nmax = nmax
}
// 发送数据
// peer - 端点0/1,从0发送,从1接收;从1发送从0接收
func (p *LatencySimulator) send(peer int, data []byte, size int) int {
rnd := 0
if (peer == 0) {
rnd = p.r12.Intn(100)
} else {
rnd = p.r21.Intn(100)
}
//println("!!!!!!!!!!!!!!!!!!!!", rnd, p.lostrate, peer)
if (rnd < p.lostrate) { return 0}
pkt := &DelayPacket{}
pkt.Init(size, data)
p.current = iclock()
delay := p.rttmin
if (p.rttmax > p.rttmin) {
delay += rand.Int() % (p.rttmax - p.rttmin)
}
pkt.setts(p.current + int32(delay))
if (peer == 0) {
p.p12.PushBack(pkt)
} else {
p.p21.PushBack(pkt)
}
return 1
}
// 接收数据
func (p *LatencySimulator)recv(peer int, data []byte, maxsize int) int32 {
var it *list.Element
if (peer == 0) {
it = p.p21.Front()
if (p.p21.Len() == 0){ return -1}
} else {
it = p.p12.Front()
if (p.p12.Len() == 0){ return -1}
}
pkt := it.Value.(*DelayPacket)
p.current = iclock()
if (p.current < pkt.ts()) { return -2 }
if (maxsize < pkt.size()) { return -3 }
if (peer == 0) {
p.p21.Remove(it)
} else {
p.p12.Remove(it)
}
maxsize = pkt.size()
copy(data, pkt.ptr()[:maxsize])
return int32(maxsize)
}
@@ -1,29 +1,29 @@
package BaseController
package BaseCtrl
import (
"port-forward/utils"
"forward-core/NetUtils"
"github.com/astaxie/beego"
"github.com/astaxie/beego/logs"
)
type ApiController struct {
type ApiCtrl struct {
beego.Controller
}
var apiAuth = beego.AppConfig.String("api.auth")
func (c *ApiController) Prepare() {
func (c *ApiCtrl) Prepare() {
reqUrl := c.Ctx.Request.RequestURI
userIp := utils.GetIP(&c.Controller)
userIp := NetUtils.GetIP(&c.Controller)
logs.Debug("执行Prepare,当前reqUrl", reqUrl, " userIp:", userIp)
//校验鉴权参数
auth := c.GetString("auth")
if auth != apiAuth {
logs.Error("apiAuth验证失败:", auth)
c.Ctx.Redirect(302, "/apiAuthFail")
//logs.Error("apiAuth验证失败:", auth)
//c.Ctx.Redirect(302, "/apiAuthFail")
}
}
}
@@ -1,21 +1,21 @@
package BaseController
package BaseCtrl
import (
"port-forward/models"
"forward-core/Models"
"github.com/astaxie/beego"
"github.com/astaxie/beego/logs"
)
type ConsoleController struct {
beego.Controller
}
var (
ConsoleLoginUrl string = "/login"
)
func (c *ConsoleController) Prepare() {
type ConsoleCtrl struct {
beego.Controller
LoginUser *Models.LoginUser
}
func (c *ConsoleCtrl) Prepare() {
reqUrl := c.Ctx.Request.RequestURI
logs.Debug("执行Prepare,当前reqUrl", reqUrl)
@@ -26,29 +26,38 @@ func (c *ConsoleController) Prepare() {
//开始访问每个action前,执行登录和权限检查
userInfo := c.GetUserInfo()
if userInfo == nil {
//未登录
c.Ctx.Redirect(302, ConsoleLoginUrl)
}
c.LoginUser = userInfo
}
func (c *ConsoleController) StoreUserInfo(loginUser *models.LoginUser) {
//判断用户是否登录.
func (c *ConsoleCtrl) isUserLoggedIn() bool {
return c.LoginUser != nil && c.LoginUser.UserId > 0
}
func (c *ConsoleCtrl) StoreUserInfo(loginUser *Models.LoginUser) {
c.SetSession("userInfo", loginUser)
}
func (c *ConsoleController) GetUserInfo() *models.LoginUser {
func (c *ConsoleCtrl) GetUserInfo() *Models.LoginUser {
userInfo := c.GetSession("userInfo")
if userInfo == nil {
return nil
}
return userInfo.(*models.LoginUser)
return userInfo.(*Models.LoginUser)
}
func (c *ConsoleController) ClearUserInfo() {
func (c *ConsoleCtrl) ClearUserInfo() {
c.DelSession("userInfo")
c.LoginUser = nil
}
}
@@ -1,15 +1,15 @@
package BaseController
package BaseCtrl
import (
"github.com/astaxie/beego"
"github.com/astaxie/beego/logs"
)
type WebController struct {
type WebCtrl struct {
beego.Controller
}
func (c *WebController) Prepare() {
func (c *WebCtrl) Prepare() {
reqUrl := c.Ctx.Request.RequestURI
logs.Debug("执行Prepare,当前reqUrl", reqUrl)
@@ -1,15 +1,15 @@
package controllers
package Controllers
import (
"port-forward/models"
"github.com/astaxie/beego"
"forward-core/Models"
"forward-server/Controllers/BaseCtrl"
)
type DefaultCtrl struct {
beego.Controller
BaseCtrl.WebCtrl
}
// @router / [get]
func (c *DefaultCtrl) Default() {
@@ -22,8 +22,8 @@ func (c *DefaultCtrl) Default() {
// @router /apiAuthFail [get]
func (c *DefaultCtrl) ApiAuthFail() {
c.Data["json"] = models.ResultData{Code: 1, Msg: "ApiAuth鉴权失败"}
c.Data["json"] = Models.FuncResult{Code: 1, Msg: "ApiAuth鉴权失败"}
c.ServeJSON()
}
}
+411
View File
@@ -0,0 +1,411 @@
package Controllers
import (
"fmt"
"forward-core/Constant"
"forward-core/Models"
"forward-core/Utils"
"forward-server/Controllers/BaseCtrl"
"forward-server/Service"
"github.com/astaxie/beego"
"github.com/astaxie/beego/logs"
)
type ForwardCtrl struct {
BaseCtrl.ConsoleCtrl
}
// @router /u/ForwardList [get]
func (c *ForwardCtrl) ForwardList() {
c.TplName = "ucenter/forwardList.html"
}
// @router /u/ForwardList/json [post]
func (c *ForwardCtrl) ForwardListJson() {
pageParam := new(Models.PageParam)
pageParam.PIndex, _ = c.GetInt64("pIndex")
pageParam.PSize, _ = c.GetInt64("pSize")
port, _ := c.GetInt("port")
targetAddr := c.GetString("targetAddr", "")
targetPort, _ := c.GetInt("targetPort")
query := &Models.PortForward{}
query.Port = port
query.TargetAddr = targetAddr
query.TargetPort = targetPort
query.FType = -1
pageData := Service.SysDataS.GetPortForwardList(query, pageParam.PIndex, pageParam.PSize)
for _, entity := range pageData.Data.([]*Models.PortForward) {
forwardJob := Service.SysDataS.GetForwardJob(entity)
//entity.Status = Utils.If(forwardJob!=nil, int(forwardJob.Status), 0).(int)
if forwardJob != nil {
entity.Status = int(forwardJob.Status)
} else {
entity.Status = 0
}
}
c.Data["json"] = Models.FuncResult{Code: 0, Msg: "success", Data: pageData}
c.ServeJSON()
}
// @router /u/AddForward [get,post]
func (c *ForwardCtrl) AddForward() {
entity := Models.PortForward{}
entity.Status = 1
c.Data["entity"] = entity
c.TplName = "ucenter/forwardForm.html"
}
// @router /u/EditForward [get,post]
func (c *ForwardCtrl) EditForward() {
id, _ := c.GetInt("id")
entity := Service.SysDataS.GetPortForwardById(id)
c.Data["entity"] = entity
c.TplName = "ucenter/forwardForm.html"
}
// @router /u/DelForward [post]
func (c *ForwardCtrl) DelForward() {
ids := c.GetString("ids")
var idArray []int
for _, id := range Utils.Split(ids, ",") {
_id := Utils.ToInt(id)
//检查是否正在转发中
entity := Service.SysDataS.GetPortForwardById(_id)
forwardJob := Service.SysDataS.GetForwardJob(entity)
if forwardJob != nil && forwardJob.Status == Constant.RunStatus_Running {
c.Data["json"] = Models.FuncResult{Code: 1, Msg: fmt.Sprint("[", entity.Name, "] 正在转发中,不能删除")}
c.ServeJSON()
return
} else {
idArray = append(idArray, _id)
}
}
err := Service.SysDataS.DelPortForwards(idArray)
if err == nil {
//
c.Data["json"] = Models.FuncResult{Code: 0, Msg: "success"}
} else {
c.Data["json"] = Models.FuncResult{Code: 1, Msg: err.Error()}
logs.Error("DelForward err", err)
}
c.ServeJSON()
}
// @router /u/SaveForward [post]
func (c *ForwardCtrl) SaveForward() {
id, _ := c.GetInt("id")
name := c.GetString("name", "")
addr := c.GetString("addr", "")
port, _ := c.GetInt("port")
protocol := c.GetString("protocol", "TCP")
targetAddr := c.GetString("targetAddr", "")
targetPort, _ := c.GetInt("targetPort")
others := c.GetString("others", "")
fType, _ := c.GetInt("fType")
status, _ := c.GetInt("status")
if Utils.IsEmpty(name) {
//
//c.Data["json"] = Models.FuncResult{Code: 1, Msg: "名称 不能为空"}
//c.ServeJSON()
//return
name = "-"
}
if port < 0 || port > 65535 {
//
c.Data["json"] = Models.FuncResult{Code: 1, Msg: "监听端口 不在允许的范围"}
c.ServeJSON()
return
}
if Utils.IsEmpty(targetAddr) {
//
c.Data["json"] = Models.FuncResult{Code: 1, Msg: "目标地址 不能为空"}
c.ServeJSON()
return
}
if targetPort < 0 || targetPort > 65535 {
//
c.Data["json"] = Models.FuncResult{Code: 1, Msg: "目标端口 不在允许的范围"}
c.ServeJSON()
return
}
if status != 0 && status != 1 {
//
c.Data["json"] = Models.FuncResult{Code: 1, Msg: "输入的 启用/禁用 值不正确"}
c.ServeJSON()
return
}
// if Utils.IsNotEmpty(others) {
// //如果有others信息,则检查
// }
if fType > 0 {
//内网穿透模式,暂不支持多端口分发
others = ""
}
if id > 0 {
entity := Service.SysDataS.GetPortForwardById(id)
forwardJob := Service.SysDataS.GetForwardJob(entity)
if forwardJob != nil && forwardJob.Status == Constant.RunStatus_Running {
//正在转发中,修改前先关闭
c.Data["json"] = Models.FuncResult{Code: 1, Msg: fmt.Sprint("[", entity.Name, "] 正在转发中,不能修改")}
c.ServeJSON()
return
}
}
name = Utils.FilterHtml(name)
entity := &Models.PortForward{}
entity.Id = id
entity.Name = name
entity.Addr = addr
entity.Port = port
entity.Protocol = protocol
entity.TargetAddr = targetAddr
entity.TargetPort = targetPort
entity.Others = others
entity.FType = fType
entity.Status = status
err := Service.SysDataS.SavePortForward(entity)
if err == nil {
c.Data["json"] = Models.FuncResult{Code: 0, Msg: ""}
} else {
logs.Error("SaveForward ", err.Error())
c.Data["json"] = Models.FuncResult{Code: 1, Msg: err.Error()}
}
c.ServeJSON()
}
// @router /u/OpenForward [get,post]
func (c *ForwardCtrl) OpenForward() {
id, _ := c.GetInt("id")
entity := Service.SysDataS.GetPortForwardById(id)
resultChan := make(chan Models.FuncResult)
config := Service.SysDataS.ToForwardConfig(entity)
go Service.ForWardServ.OpenForward(config, resultChan)
c.Data["json"] = <-resultChan
c.ServeJSON()
}
// @router /u/CloseForward [get,post]
func (c *ForwardCtrl) CloseForward() {
id, _ := c.GetInt("id")
entity := Service.SysDataS.GetPortForwardById(id)
config := Service.SysDataS.ToForwardConfig(entity)
Service.ForWardServ.CloseForward(config)
c.Data["json"] = Models.FuncResult{Code: 0, Msg: ""}
c.ServeJSON()
}
// @router /u/OpenAllForward [get,post]
func (c *ForwardCtrl) OpenAllForward() {
forwards := Service.SysDataS.GetAllPortForwardList(1)
for _, entity := range forwards {
resultChan := make(chan Models.FuncResult)
config := Service.SysDataS.ToForwardConfig(entity)
go Service.ForWardServ.OpenForward(config, resultChan)
fmt.Println(<-resultChan)
}
c.Data["json"] = Models.FuncResult{Code: 0, Msg: ""}
c.ServeJSON()
}
// @router /u/CloseAllForward [get,post]
func (c *ForwardCtrl) CloseAllForward() {
//forwards := Service.SysDataS.GetAllPortForwardList(1)
//for _, entity := range forwards {
// config := Service.SysDataS.ToForwardConfig(entity)
// Service.ForWardServ.CloseForward(config)
//}
Service.ForWardServ.CloseAllForward()
c.Data["json"] = Models.FuncResult{Code: 0, Msg: ""}
c.ServeJSON()
}
// @router /u/ApiDoc [get]
func (c *ForwardCtrl) ApiDoc() {
c.TplName = "ucenter/apiDoc.html"
}
// @router /u/NetAgent [get]
func (c *ForwardCtrl) NetAgent() {
magicAddr := beego.AppConfig.DefaultString("magic.service", ":7000")
c.Data["magicAddr"] = magicAddr
agentForward := Service.MagicServ.ForwardInfo
if agentForward == nil {
agentForward = new(Models.PortForward)
agentForward.Addr = ""
agentForward.Port = 3307
agentForward.Protocol = "TCP"
agentForward.TargetAddr = "127.0.0.1"
agentForward.TargetPort = 3306
agentForward.FType = 2
}
c.Data["agentForward"] = agentForward
c.TplName = "ucenter/netAgent.html"
}
// @router /u/OpenMagicService [post]
func (c *ForwardCtrl) OpenMagicService() {
addr := beego.AppConfig.DefaultString("magic.service", ":7000")
resultChan := make(chan Models.FuncResult)
go Service.MagicServ.StartMagicService(addr, resultChan)
c.Data["json"] = <-resultChan
//c.Data["json"] = Models.FuncResult{Code: 0, Msg: ""}
c.ServeJSON()
}
// @router /u/CloseMagicService [post]
func (c *ForwardCtrl) CloseMagicService() {
resultChan := make(chan Models.FuncResult)
go Service.MagicServ.StopMagicService(resultChan)
c.Data["json"] = <-resultChan
c.ServeJSON()
}
// @router /u/GetMagicStatus [post]
func (c *ForwardCtrl) GetMagicStatus() {
magicListener := Service.MagicServ.GetMagicListener()
if magicListener == nil {
c.Data["json"] = Models.FuncResult{Code: 1, Msg: "未运行"}
} else {
c.Data["json"] = Models.FuncResult{Code: 0, Msg: "正在运行中..."}
}
c.ServeJSON()
}
// @router /u/GetNetAgentStatus [post]
func (c *ForwardCtrl) GetNetAgentStatus() {
agentMap := Service.MagicServ.GetMagicClient()
if len(agentMap) > 0 {
count := len(agentMap)
for k, _ := range agentMap {
c.Data["json"] = Models.FuncResult{Code: 0, Msg: k, Data: count}
//只取1个先
break
}
} else {
c.Data["json"] = Models.FuncResult{Code: 1, Msg: "未检测到Agent连接"}
}
c.ServeJSON()
}
// @router /u/ClearNetAgentStatus [post]
func (c *ForwardCtrl) ClearNetAgentStatus() {
agentMap := Service.MagicServ.GetMagicClient()
if len(agentMap) > 0 {
for k, v := range agentMap {
if v != nil {
v.Close()
Service.MagicServ.UnRegistryMagicClient(k)
logs.Debug("关闭Agent", k)
}
}
}
c.Data["json"] = Models.FuncResult{Code: 0, Msg: ""}
c.ServeJSON()
}
// @router /u/StartAgentJob [post]
func (c *ForwardCtrl) StartAgentJob() {
lAddr := c.GetString("lAddr", "")
protocol := c.GetString("protocol", "TCP")
targetAddr := c.GetString("targetAddr", "")
fType, _ := c.GetInt("fType")
portForward := new(Models.PortForward)
portForward.Addr = Utils.Split(lAddr, ":")[0]
portForward.Port = Utils.ToInt(Utils.Split(lAddr, ":")[1])
portForward.Protocol = protocol
portForward.TargetAddr = Utils.Split(targetAddr, ":")[0]
portForward.TargetPort = Utils.ToInt(Utils.Split(targetAddr, ":")[1])
portForward.FType = fType
resultChan := make(chan Models.FuncResult)
go Service.MagicServ.StartMagicForward(portForward, resultChan)
c.Data["json"] = <-resultChan
c.ServeJSON()
}
// @router /u/StopAgentJob [post]
func (c *ForwardCtrl) StopAgentJob() {
c.Data["json"] = Models.FuncResult{Code: 0, Msg: ""}
c.ServeJSON()
}
@@ -1,17 +1,16 @@
package controllers
package Controllers
import (
"port-forward/controllers/base"
"port-forward/models"
"port-forward/utils"
"port-forward/services"
"forward-core/Models"
"forward-core/NetUtils"
"forward-core/Utils"
"forward-server/Controllers/BaseCtrl"
"forward-server/Service"
"github.com/astaxie/beego/logs"
)
type LoginCtrl struct {
BaseController.ConsoleController
BaseCtrl.ConsoleCtrl
}
// @router /logout
@@ -33,17 +32,18 @@ func (c *LoginCtrl) DoLogin() {
userName := c.GetString("userName")
passWord := c.GetString("passWord")
sysUser := services.SysDataS.GetSysUserByName(userName)
sysUser := Service.SysDataS.GetSysUserByName(userName)
if sysUser == nil {
logs.Debug("用户不存在")
c.Ctx.Redirect(302, "/login")
return
}
descryptPwd := utils.GetMd5(passWord)
descryptPwd := Utils.GetMd5(passWord)
logs.Debug("存储的密码:", sysUser.PassWord, " 输入的密码:", descryptPwd)
if sysUser.PassWord == descryptPwd {
logs.Info("用户登录:", userName, " IP", utils.GetIP(&c.Controller))
loginUser := new(models.LoginUser)
logs.Info("用户登录:", userName, " IP", NetUtils.GetIP(&c.Controller))
loginUser := new(Models.LoginUser)
loginUser.UserId = 1
loginUser.UserName = userName
@@ -53,4 +53,5 @@ func (c *LoginCtrl) DoLogin() {
logs.Debug("用户登录失败")
c.Ctx.Redirect(302, "/login")
}
}
+86
View File
@@ -0,0 +1,86 @@
package Controllers
import (
"forward-core/Models"
"forward-core/Utils"
"forward-server/Controllers/BaseCtrl"
"forward-server/Service"
"runtime"
"strings"
"time"
)
type RestApiCtrl struct {
BaseCtrl.ApiCtrl
}
// @router /ServerSummary [get,post]
func (c *RestApiCtrl) ServerSummary() {
obj := make(map[string]interface{})
obj["runtime_NumGoroutine"] = runtime.NumGoroutine()
obj["runtime_GOOS"] = runtime.GOOS
obj["runtime_GOARCH"] = runtime.GOARCH
obj["server_Time"] = time.Now()
obj["forwardList"] = Service.ForWardServ.FindAllForward()
c.Data["json"] = obj
c.ServeJSON()
}
// @router /OpenForward [get,post]
func (c *RestApiCtrl) OpenForward() {
fromAddr := c.GetString("fromAddr")
toAddr := c.GetString("toAddr")
protocol := c.GetString("protocol", "TCP")
entity := Service.SysDataS.ChkPortForwardByApi(fromAddr, protocol, toAddr)
if entity == nil {
_, err := Service.SysDataS.SavePortForwardByApi(fromAddr, protocol, toAddr)
if err != nil {
c.Data["json"] = Models.FuncResult{Code: 1, Msg: "保存端口配置失败"}
c.ServeJSON()
return
}
}
//测试
//http://127.0.0.1:8000/api/v1/OpenForward?auth=26CCD056107481F45D1AC805A24A9E59&fromAddr=:8010&toAddr=127.0.0.1:3306
resultChan := make(chan Models.FuncResult)
config := Service.SysDataS.ToForwardConfig(entity)
go Service.ForWardServ.OpenForward(config, resultChan)
c.Data["json"] = <-resultChan
c.ServeJSON()
}
// @router /CloseForward [get,post]
func (c *RestApiCtrl) CloseForward() {
fromAddr := c.GetString("fromAddr")
toAddr := c.GetString("toAddr")
protocol := c.GetString("protocol", "TCP")
//fType, _ := c.GetInt("fType", 0)
//测试
//http://127.0.0.1:8000/api/v1/CloseForward?auth=26CCD056107481F45D1AC805A24A9E59&fromAddr=:8010&toAddr=127.0.0.1:3306
config := new(Models.ForwardConfig)
config.RuleId = 0
config.Name = ""
config.Protocol = protocol
config.SrcAddr = strings.Split(fromAddr, ":")[0]
config.SrcPort = Utils.ToInt(strings.Split(fromAddr, ":")[1])
config.DestAddr = strings.Split(toAddr, ":")[0]
config.DestPort = Utils.ToInt(strings.Split(toAddr, ":")[1])
config.Status = 0
Service.ForWardServ.CloseForward(config)
c.Data["json"] = Models.FuncResult{Code: 0, Msg: ""}
c.ServeJSON()
}
@@ -1,16 +1,16 @@
package controllers
package Controllers
import (
"port-forward/controllers/base"
"port-forward/models"
"port-forward/services"
"port-forward/utils"
"forward-core/Models"
"forward-core/Utils"
"forward-server/Controllers/BaseCtrl"
"forward-server/Service"
"runtime"
"time"
)
type UCenterCtrl struct {
BaseController.ConsoleController
BaseCtrl.ConsoleCtrl
}
// @router /u/main [get]
@@ -34,9 +34,9 @@ func (c *UCenterCtrl) Index() {
}
// @router /u/getServerTime [post]
func (c *UCenterCtrl) GetServerTime() {
func (c *UCenterCtrl) GetServerTime(){
c.Data["json"] = utils.GetCurrentTime()
c.Data["json"] = Utils.GetCurrentTime()
c.ServeJSON()
@@ -55,23 +55,23 @@ func (c *UCenterCtrl) DoChangePwd() {
passWord := c.GetString("passWord")
passWord2 := c.GetString("passWord2")
if utils.IsEmpty(passWord) {
c.Data["json"] = models.ResultData{Code: 1, Msg: "密码不能为空"}
if Utils.IsEmpty(passWord) {
c.Data["json"] = Models.FuncResult{Code: 1, Msg: "密码不能为空"}
c.ServeJSON()
return
}
if passWord != passWord2 {
c.Data["json"] = models.ResultData{Code: 1, Msg: "两次输入的密码不一致"}
c.Data["json"] = Models.FuncResult{Code: 1, Msg: "两次输入的密码不一致"}
c.ServeJSON()
return
}
err := services.SysDataS.ChangeUserPwd(userInfo.UserId, passWord)
err := Service.SysDataS.ChangeUserPwd(userInfo.UserId, passWord)
if err == nil {
c.Data["json"] = models.ResultData{Code: 0, Msg: "密码修改成功"}
c.Data["json"] = Models.FuncResult{Code: 0, Msg: "密码修改成功"}
} else {
c.Data["json"] = models.ResultData{Code: 1, Msg: err.Error()}
c.Data["json"] = Models.FuncResult{Code: 1, Msg: err.Error()}
}
c.ServeJSON()
+33
View File
@@ -0,0 +1,33 @@
package Service
import (
"encoding/gob"
"forward-core/Models"
"github.com/astaxie/beego"
"github.com/astaxie/beego/logs"
)
type ConsoleServer struct {
}
func (_self *ConsoleServer) StartHttpServer() {
//开启seesion支持,默认使用的存储引擎为:memory
beego.BConfig.WebConfig.Session.SessionOn = true
beego.BConfig.WebConfig.Session.SessionName = "sessionID"
beego.BConfig.WebConfig.Session.SessionGCMaxLifetime = 3600
//默认static目录是可以直接访问的,其它目录需要单独指定
beego.SetStaticPath("/theme", "theme")
//
gob.Register(&Models.LoginUser{})
logs.Debug("Http 服务启动...")
//启动应用
beego.Run()
}
+170
View File
@@ -0,0 +1,170 @@
package Service
import (
"fmt"
"forward-core/Constant"
"forward-core/Models"
"forward-core/NetUtils"
"forward-core/Utils"
"net"
"sync"
"time"
"github.com/astaxie/beego/logs"
)
type ForWardJob struct {
Config *Models.ForwardConfig
ClientMap map[string]*ForWardClient
ClientMapLock sync.Mutex
Status byte
PortListener net.Listener
UdpForwardJob *UdpForward
}
func (_self *ForWardJob) StartJob(result chan Models.FuncResult) {
sourceAddr := fmt.Sprint(_self.Config.SrcAddr, ":", _self.Config.SrcPort)
destAddr := fmt.Sprint(_self.Config.DestAddr, ":", _self.Config.DestPort)
resultData := &Models.FuncResult{Code: 0, Msg: ""}
var err error
if _self.IsUdpJob() {
//_self.PortListener, err = NetUtils.NewKCP(sourceAddr, Common.DefaultKcpSetting())
//_self.UdpForwardJob.UdpListenerConn, err = NetUtils.NewUDP(sourceAddr)
err = _self.UdpForwardJob.DoUdpForward(sourceAddr, destAddr)
if err != nil {
logs.Error("启动UDP监听 ", sourceAddr, " 出错:", err)
resultData.Code = 1
resultData.Msg = fmt.Sprint("启动UDP监听 ", sourceAddr, " 出错:", err)
result <- *resultData
return
}
_self.Status = Constant.RunStatus_Running
logs.Debug("启动UDP端口转发,从 ", sourceAddr, " 到 ", destAddr)
result <- *resultData
} else {
_self.PortListener, err = NetUtils.NewTCP(sourceAddr)
if err != nil {
logs.Error("启动监听 ", sourceAddr, " 出错:", err)
resultData.Code = 1
resultData.Msg = fmt.Sprint("启动监听 ", sourceAddr, " 出错:", err)
result <- *resultData
return
}
_self.Status = Constant.RunStatus_Running
logs.Debug("启动端口转发,从 ", sourceAddr, " 到 ", destAddr)
result <- *resultData
_self.doTcpForward(destAddr)
}
}
func (_self *ForWardJob) doTcpForward(destAddr string) {
for {
realClientConn, err := _self.PortListener.Accept()
if err != nil {
logs.Error("Forward Accept err:", err.Error())
logs.Error(fmt.Sprint("转发出现异常:", _self.Config.SrcAddr, ":", _self.Config.SrcPort, "->", destAddr))
_self.StopJob()
break
}
logs.Info("新用户 ", realClientConn.RemoteAddr().String(), " 数据转发规则:", fmt.Sprint(_self.Config.SrcAddr, ":", _self.Config.SrcPort), "->", destAddr)
var destConn net.Conn
if _self.Config.Protocol == "UDP" {
//destConn, err = Common.DialKcpTimeout(destAddr, 100)
destConn, err = net.DialTimeout("UDP", destAddr, 30*time.Second)
} else {
destConn, err = net.DialTimeout("tcp", destAddr, 30*time.Second)
}
if err != nil {
logs.Error("转发出现异常 Forward to Dest Addr err:", err.Error())
//break
continue
}
forwardClient := &ForWardClient{realClientConn, destConn, _self.ClosedCallBack}
go forwardClient.StartForward()
_self.RegistryClient(_self.GetClientId(realClientConn), forwardClient)
//_self.RegistryClient(fmt.Sprint(sourceAddr, "_", "TCP", "_", id), forwardClient)
}
}
func (_self *ForWardJob) ClosedCallBack(srcConn net.Conn, destConn net.Conn) {
_self.UnRegistryClient(_self.GetClientId(srcConn))
}
func (_self *ForWardJob) GetClientId(conn net.Conn) string {
return conn.RemoteAddr().String()
}
func (_self *ForWardJob) RegistryClient(srcAddr string, forwardClient *ForWardClient) {
_self.ClientMapLock.Lock()
defer _self.ClientMapLock.Unlock()
_self.ClientMap[srcAddr] = forwardClient
}
func (_self *ForWardJob) UnRegistryClient(srcAddr string) {
_self.ClientMapLock.Lock()
defer _self.ClientMapLock.Unlock()
delete(_self.ClientMap, srcAddr)
logs.Debug("UnRegistryClient srcAddr: ", srcAddr)
}
func (_self *ForWardJob) IsJobRunning() bool {
return _self.Status == Constant.RunStatus_Running
}
func (_self *ForWardJob) IsUdpJob() bool {
return Utils.ToUpper(_self.Config.Protocol) == "UDP"
}
func (_self *ForWardJob) StopJob() {
if _self.IsUdpJob() {
_self.stopUdpJob()
} else {
_self.stopTcpJob()
}
_self.Status = Constant.RunStatus_Stoped
}
func (_self *ForWardJob) stopTcpJob() {
_self.PortListener.Close()
for srcAddr, client := range _self.ClientMap {
logs.Debug("停止真实用户连接:", srcAddr)
client.StopForward()
}
_self.ClientMap = nil
}
func (_self *ForWardJob) stopUdpJob() {
_self.UdpForwardJob.Close()
}
+54
View File
@@ -0,0 +1,54 @@
package Service
import (
"io"
"net"
"github.com/astaxie/beego/logs"
)
type ForWardClient struct {
SrcConn net.Conn
DestConn net.Conn
ClosedCallBack func(srcConn net.Conn, destConn net.Conn)
}
func (_self *ForWardClient) StartForward() {
//io.Copy(dst, src)
go func() {
_, err := io.Copy(_self.DestConn, _self.SrcConn)
if err != nil {
//logs.Error("客户端来源数据转发到目标端口异常:", err)
_self.StopForward()
}
}()
go func() {
_, err := io.Copy(_self.SrcConn, _self.DestConn)
if err != nil {
//logs.Error("目标端口返回响应数据异常:", err)
_self.StopForward()
}
}()
}
func (_self *ForWardClient) DispatchData(dispatchConns []io.Writer) {
//将数据克隆给其它端口
go func() {
mWriter := io.MultiWriter(dispatchConns...)
_, err := io.Copy(mWriter, _self.SrcConn)
if err != nil {
logs.Error("Dispatch网络连接异常:", err)
}
}()
}
func (_self *ForWardClient) StopForward() {
//logs.Debug("关闭一个连接:", _self.SrcConn.RemoteAddr()," on ", _self.SrcConn.LocalAddr())
_self.SrcConn.Close()
_self.DestConn.Close()
_self.ClosedCallBack(_self.SrcConn, _self.DestConn)
}
+162
View File
@@ -0,0 +1,162 @@
package Service
import (
"fmt"
"forward-core/Models"
"github.com/astaxie/beego/logs"
"net"
"sync"
)
type ForWardServer struct {
JobMap map[string]*ForWardJob
JobMapLock sync.Mutex
}
func NewForWardServer() *ForWardServer {
return &ForWardServer{
JobMap:make(map[string]*ForWardJob,200),
}
}
func (_self *ForWardServer) FindAllForward() []*Models.ForwardInfo {
var forwardList []*Models.ForwardInfo
for _,forWardJob := range _self.JobMap {
forwardInfo := new(Models.ForwardInfo)
forwardInfo.Name = forWardJob.Config.Name
forwardInfo.Status = forWardJob.Status
forwardInfo.Protocol = forWardJob.Config.Protocol
forwardInfo.SrcAddr = forWardJob.Config.SrcAddr
forwardInfo.SrcPort = forWardJob.Config.SrcPort
forwardInfo.DestAddr = forWardJob.Config.DestAddr
forwardInfo.DestPort = forWardJob.Config.DestPort
if forWardJob.IsUdpJob() {
for key, _ := range forWardJob.UdpForwardJob.UdpConns {
forwardInfo.Clients = append(forwardInfo.Clients, key)
}
}else{
for _,client := range forWardJob.ClientMap {
forwardInfo.Clients = append(forwardInfo.Clients, client.SrcConn.RemoteAddr().String())
}
}
forwardInfo.OnlineCount = len(forwardInfo.Clients)
forwardList = append(forwardList, forwardInfo)
}
return forwardList
}
func (_self *ForWardServer) GetForwardInfo(config *Models.ForwardConfig) *Models.ForwardInfo {
forwardInfo := new(Models.ForwardInfo)
forWardJob :=_self.GetRegistryJob(config)
if forWardJob != nil {
forwardInfo.Name = forWardJob.Config.Name
forwardInfo.Status = forWardJob.Status
forwardInfo.Protocol = forWardJob.Config.Protocol
forwardInfo.SrcAddr = forWardJob.Config.SrcAddr
forwardInfo.SrcPort = forWardJob.Config.SrcPort
forwardInfo.DestAddr = forWardJob.Config.DestAddr
forwardInfo.DestPort = forWardJob.Config.DestPort
for _,client := range forWardJob.ClientMap{
forwardInfo.Clients = append(forwardInfo.Clients, client.SrcConn.RemoteAddr().String())
}
forwardInfo.OnlineCount = len(forwardInfo.Clients)
}
return forwardInfo
}
func (_self *ForWardServer) GetForwardJob(config *Models.ForwardConfig) *ForWardJob {
return _self.GetRegistryJob(config)
}
func (_self *ForWardServer) OpenForward(config *Models.ForwardConfig, result chan Models.FuncResult) {
forWardJob := new(ForWardJob)
forWardJob.ClientMap = make(map[string]*ForWardClient,500)
forWardJob.Config = config
forWardJob.UdpForwardJob = NewUdpForward()
go forWardJob.StartJob(result)
_self.RegistryJob(config, forWardJob)
}
func (_self *ForWardServer) GetJobKey(config *Models.ForwardConfig) string {
srcAddr := fmt.Sprint(config.SrcAddr, ":", config.SrcPort)
destAddr := fmt.Sprint(config.DestAddr, ":", config.DestPort)
return fmt.Sprint(srcAddr, "_", config.Protocol, "_", destAddr)
}
func (_self *ForWardServer) GetClientId(conn net.Conn) string {
return conn.RemoteAddr().String()
}
func (_self *ForWardServer) RegistryJob(config *Models.ForwardConfig, forWardJob *ForWardJob) {
_self.JobMapLock.Lock()
defer _self.JobMapLock.Unlock()
_self.JobMap[_self.GetJobKey(config)] = forWardJob
}
func (_self *ForWardServer) UnRegistryJob(config *Models.ForwardConfig) {
_self.JobMapLock.Lock()
defer _self.JobMapLock.Unlock()
key := _self.GetJobKey(config)
delete(_self.JobMap, key)
logs.Debug("UnRegistryClient key: ", key)
}
func (_self *ForWardServer) GetRegistryJob(config *Models.ForwardConfig) *ForWardJob {
if forWardJob, ok := _self.JobMap[_self.GetJobKey(config)]; ok {
return forWardJob
}
return nil
}
func (_self *ForWardServer) CloseForward(config *Models.ForwardConfig) {
forWardJob := _self.GetRegistryJob(config)
if forWardJob != nil {
logs.Debug("停止转发,找到执行者:", _self.GetJobKey(config))
forWardJob.StopJob()
_self.UnRegistryJob(config)
}
}
func (_self *ForWardServer) CloseAllForward() {
for _, forWardJob := range _self.JobMap {
forWardJob.StopJob()
//delete(_self.JobMap, key)
_self.UnRegistryJob(forWardJob.Config)
}
//_self.JobMap = nil
_self.JobMap = make(map[string]*ForWardJob,200)
}
+48
View File
@@ -0,0 +1,48 @@
package Service
import (
"fmt"
"forward-core/Models"
"github.com/astaxie/beego"
"github.com/astaxie/beego/orm"
_ "github.com/mattn/go-sqlite3"
)
var (
OrmerS orm.Ormer
//ForWardServ = new(ForWardServer)
ForWardServ = NewForWardServer()
MagicServ = NewMagicServiceV1()
//MagicServ = new(MagicServer)
ConsoleServ = new(ConsoleServer)
SysDataS = new(SysDataService)
)
func init() {
//开启DEBUG模式,输出SQL信息
orm.Debug = true
//_ "github.com/mattn/go-sqlite3"
orm.RegisterDriver("sqlite3", orm.DRSqlite)
orm.RegisterDataBase("default", "sqlite3", "file:data/data.db?cache=shared&loc=auto")
OrmerS = orm.NewOrm()
OrmerS.Using("default")
onstartForward := beego.AppConfig.String("onstart.forward")
if onstartForward == "true" {
onStartForward()
}
}
func onStartForward() {
forwards := SysDataS.GetAllPortForwardList(1)
for _, entity := range forwards {
resultChan := make(chan Models.FuncResult)
config := SysDataS.ToForwardConfig(entity)
go ForWardServ.OpenForward(config, resultChan)
fmt.Println(<-resultChan)
}
}
+12
View File
@@ -0,0 +1,12 @@
package Service
import "net"
type MagicClient struct {
cid string
encode, decode func([]byte) []byte
authed bool
conn net.Conn
}
+11
View File
@@ -0,0 +1,11 @@
package Service
import "forward-core/Models"
type MagicServer struct {
UseUDP bool
}
func (_self *MagicServer) StartMagicService(netAddr string, result chan Models.FuncResult) {
}
+328
View File
@@ -0,0 +1,328 @@
package Service
import (
"bufio"
"fmt"
"forward-core/Constant"
"forward-core/Models"
"forward-core/NetUtils"
"github.com/astaxie/beego/logs"
"io"
"net"
"sync"
"time"
)
type MagicServiceV1 struct {
MagicClientMap map[string]net.Conn
MagicClientMapLock sync.Mutex
MagicListener net.Listener
agentRunType int
MagicTargetAddr string
sessionId int
idLock sync.Mutex
sessionConnMap map[int]net.Conn
ForwardInfo *Models.PortForward
}
func NewMagicServiceV1() *MagicServiceV1 {
return &MagicServiceV1{
MagicClientMap:make(map[string]net.Conn,200),
sessionConnMap:make(map[int]net.Conn,200),
}
}
func (_self *MagicServiceV1) GetNewSessionId() int {
_self.idLock.Lock()
defer _self.idLock.Unlock()
_self.sessionId++
return _self.sessionId
}
func (_self *MagicServiceV1) GetKeyByEntity(entity *Models.PortForward) string {
fromAddr := fmt.Sprint(entity.Addr, ":", entity.Port)
toAddr := fmt.Sprint(entity.TargetAddr, ":", entity.TargetPort)
key := _self.GetKey(fromAddr, toAddr, entity.FType)
return key
}
func (_self *MagicServiceV1) GetKey(sourcePort, targetPort string, fType int) string {
return fmt.Sprint(sourcePort, "_", fType, "_TCP_", targetPort)
}
func (_self *MagicServiceV1) RegistryMagicClient(key string, conn net.Conn) {
_self.MagicClientMapLock.Lock()
defer _self.MagicClientMapLock.Unlock()
_self.MagicClientMap[key] = conn
}
func (_self *MagicServiceV1) GetTopMagicClient() net.Conn {
_self.MagicClientMapLock.Lock()
defer _self.MagicClientMapLock.Unlock()
for _, v := range _self.MagicClientMap {
return v
}
return nil
}
func (_self *MagicServiceV1) GetMagicListener() net.Listener {
return _self.MagicListener
}
func (_self *MagicServiceV1) UnRegistryMagicClient(key string) {
_self.MagicClientMapLock.Lock()
defer _self.MagicClientMapLock.Unlock()
delete(_self.MagicClientMap, key)
logs.Debug("UnRegistryMagicClient key: ", key)
}
func (_self *MagicServiceV1) CountMagicClient() int {
_self.MagicClientMapLock.Lock()
defer _self.MagicClientMapLock.Unlock()
return len(_self.MagicClientMap)
}
func (_self *MagicServiceV1) GetMagicClient() map[string]net.Conn {
return _self.MagicClientMap
}
func (_self *MagicServiceV1) StartMagicService(addr string, result chan Models.FuncResult) {
//启动穿透服务端
resultData := &Models.FuncResult{Code: 0, Msg: ""}
var err error
_self.MagicListener, err = net.Listen("tcp", addr)
if err != nil {
logs.Error("Magic Listen err:", err)
resultData.Code = 1
resultData.Msg = err.Error()
result <- *resultData
return
}
result <- *resultData
for {
logs.Debug("Magic Ready to Accept ...")
magic_client_Conn, err := _self.MagicListener.Accept()
if err != nil {
logs.Error("Accept err:", err)
break
}
if _self.CountMagicClient() > 0 && _self.CurrentAgentRunType() != 1 {
logs.Debug("目前版本只支持一个Agent连接,后续会增加多个的支持")
NetUtils.WriteConn(magic_client_Conn, -1, Constant.MagicCmd_Refused, []byte(""))
magic_client_Conn.Close()
continue
}
if _self.CountMagicClient() == 0 {
magicId := magic_client_Conn.RemoteAddr().String()
_self.RegistryMagicClient(magicId, magic_client_Conn)
} else {
if _self.CurrentAgentRunType() == 1 {
_self.MagicJustCopy(magic_client_Conn, _self.MagicTargetAddr)
}
}
}
}
func (_self *MagicServiceV1) StopMagicService(result chan Models.FuncResult) {
resultData := &Models.FuncResult{Code: 0, Msg: ""}
for k, conn := range _self.MagicClientMap {
conn.Close()
_self.UnRegistryMagicClient(k)
}
_self.MagicListener.Close()
_self.MagicListener = nil
result <- *resultData
}
func (_self *MagicServiceV1) StartMagicForward(portForward *Models.PortForward, result chan Models.FuncResult) {
resultData := &Models.FuncResult{Code: 0, Msg: ""}
agentConn := _self.GetTopMagicClient()
if agentConn == nil {
resultData.Code = 1
resultData.Msg = "未检测到Agent连接"
result <- *resultData
return
}
if _self.CurrentAgentRunType() != 0 {
resultData.Code = 1
resultData.Msg = "有正在执行的Agent连接,开启转发失败"
result <- *resultData
return
}
if portForward.FType == 2 {
//执行反向映射
go _self.ReverseListenForClient(portForward, agentConn, result)
callback := func(conn net.Conn, sessionId int, cmd byte, payload []byte) {
//payload 收到的消息内容
_self.OnTunnelRecv(_self.sessionConnMap[sessionId], sessionId, cmd, payload)
}
logs.Debug("从 magic_client_Conn 读,写入到 client_Conn")
go NetUtils.ReadConn(agentConn, callback)
} else {
//发送指令
localListenAddr := fmt.Sprint(portForward.Addr, ":", portForward.Port)
NetUtils.WriteConn(agentConn, -1, Constant.MagicCmd_AgentListenerOpen, []byte(localListenAddr))
result <- *resultData
_self.agentRunType = 1
_self.MagicTargetAddr = fmt.Sprint(portForward.TargetAddr, ":", portForward.TargetPort)
//key := _self.GetKeyByEntity(portForward)
//_self.RegistryPort(key, nil)
}
_self.ForwardInfo = portForward
}
func (_self *MagicServiceV1) StopMagicForward() error {
return nil
}
func (_self *MagicServiceV1) MagicJustCopy(toConn net.Conn, targetAddr string) {
localConn, err := net.DialTimeout("tcp", targetAddr, 30*time.Second)
if err != nil {
logs.Error("try dial err", err)
return
}
go func() {
_, err = io.Copy(localConn, toConn)
if err != nil {
logs.Error("JustCopy to local 网络连接异常:", err)
localConn.Close()
}
}()
go func() {
_, err = io.Copy(toConn, localConn)
if err != nil {
logs.Error("JustCopy to local 网络连接异常2", err)
toConn.Close()
}
}()
}
func (_self *MagicServiceV1) ReverseListenForClient(portForward *Models.PortForward, magic_client_Conn net.Conn, result chan Models.FuncResult) {
resultData := &Models.FuncResult{Code: 0, Msg: ""}
localListenAddr := fmt.Sprint(portForward.Addr, ":", portForward.Port)
//让客户端在本地建立连接与目标端口的连接
remote := fmt.Sprint(portForward.TargetAddr, ":", portForward.TargetPort)
//fType := portForward.FType
client_listener, err := net.Listen("tcp", localListenAddr)
if err != nil {
logs.Error("ListenForClient err:", err)
resultData.Code = 1
resultData.Msg = err.Error()
result <- *resultData
return
}
result <- *resultData
_self.agentRunType = 2
//key := _self.GetKeyByEntity(portForward)
//_self.RegistryPort(key, client_listener)
//从 client_Conn 读,写入到 magic_client_Conn
//从 magic_client_Conn 读,写入到 client_Conn
for {
logs.Debug("ListenForClient Ready to Accept ...")
client_Conn, err := client_listener.Accept()
if err != nil {
logs.Error("Accept err:", err)
break
}
//id := client_Conn.RemoteAddr().String()
//_self.RegistryClient(fmt.Sprint(localListenAddr, "_", fType, "_", id), client_Conn)
//有连接进来了,就创建一个sessionId
sessionId := _self.GetNewSessionId()
_self.sessionConnMap[sessionId] = client_Conn
logs.Debug("进来了一个连接,sessionId", sessionId)
NetUtils.WriteConn(magic_client_Conn, sessionId, Constant.MagicCmd_AgentConnOpen, []byte(remote))
logs.Debug("向 sessionId", sessionId, " 发送 AgentConnOpen 指令")
logs.Debug("从 client_Conn 读,写入到 magic_client_Conn sessionId", sessionId)
go _self.ReadRawConn(client_Conn, magic_client_Conn, sessionId, Constant.MagicCmd_DataToAgent)
}
}
func (_self *MagicServiceV1) OnTunnelRecv(client_Conn net.Conn, sessionId int, cmd byte, payload []byte) {
logs.Debug("收到一条给 sessionId", sessionId, " 客户端的数据,指令是:", cmd)
switch cmd {
case Constant.MagicCmd_DataToMagic:
client_Conn.Write(payload)
}
}
func (_self *MagicServiceV1) ReadRawConn(from net.Conn, magic_client_Conn net.Conn, sessionId int, cmd byte) {
arr := make([]byte, 5000)
reader := bufio.NewReader(from)
for {
size, err := reader.Read(arr)
if err != nil {
break
}
err = NetUtils.WriteConn(magic_client_Conn, sessionId, cmd, arr[0:size])
if err != nil {
//有异常
logs.Error(err)
break
}
}
}
func (_self *MagicServiceV1) CurrentAgentRunType() int {
// 0:空闲,1:服务端映射到内网中,2:内网映射到服务端中
return _self.agentRunType
}
@@ -1,10 +1,10 @@
package services
package Service
import (
"errors"
"forward-core/Models"
"forward-core/Utils"
"math"
"port-forward/models"
"port-forward/utils"
"time"
"github.com/astaxie/beego/logs"
@@ -13,9 +13,9 @@ import (
type SysDataService struct {
}
func (_self *SysDataService) GetSysUserById(userId int) *models.SysUser {
func (_self *SysDataService) GetSysUserById(userId int) *Models.SysUser {
entity := new(models.SysUser)
entity := new(Models.SysUser)
qs := OrmerS.QueryTable(entity)
qs = qs.Filter("Id", userId)
@@ -31,9 +31,9 @@ func (_self *SysDataService) GetSysUserById(userId int) *models.SysUser {
}
func (_self *SysDataService) GetSysUserByName(userName string) *models.SysUser {
func (_self *SysDataService) GetSysUserByName(userName string) *Models.SysUser {
entity := new(models.SysUser)
entity := new(Models.SysUser)
qs := OrmerS.QueryTable(entity)
qs = qs.Filter("UserName", userName)
@@ -50,7 +50,7 @@ func (_self *SysDataService) GetSysUserByName(userName string) *models.SysUser {
}
func (_self *SysDataService) ChangeUserPwd(id int, password string) error {
pwd := utils.GetMd5(password)
pwd := Utils.GetMd5(password)
res, err := OrmerS.Raw("update t_sys_user SET passWord = ? where id = ?",
pwd, id).Exec()
if err == nil {
@@ -64,7 +64,7 @@ func (_self *SysDataService) ChangeUserPwd(id int, password string) error {
return err
}
func (_self *SysDataService) UpdateSysUser(entity *models.SysUser) error {
func (_self *SysDataService) UpdateSysUser(entity *Models.SysUser) error {
_, err := OrmerS.Update(entity)
return err
@@ -73,7 +73,7 @@ func (_self *SysDataService) UpdateSysUser(entity *models.SysUser) error {
func (_self *SysDataService) DelSysUsers(ids []int) error {
//批量删除
del_num, err := OrmerS.QueryTable(new(models.SysUser)).Filter("Id__in", ids).Delete()
del_num, err := OrmerS.QueryTable(new(Models.SysUser)).Filter("Id__in", ids).Delete()
if err != nil {
logs.Error("DelSysUsers err", err)
return err
@@ -85,9 +85,9 @@ func (_self *SysDataService) DelSysUsers(ids []int) error {
}
func (_self *SysDataService) GetPortForwardById(id int) *models.PortForward {
func (_self *SysDataService) GetPortForwardById(id int) *Models.PortForward {
entity := new(models.PortForward)
entity := new(Models.PortForward)
qs := OrmerS.QueryTable(entity)
qs = qs.Filter("Id", id)
@@ -103,22 +103,22 @@ func (_self *SysDataService) GetPortForwardById(id int) *models.PortForward {
}
func (_self *SysDataService) ChkPortForwardByApi(sourcePort, protocol, targetPort string) *models.PortForward {
sourceArray := utils.Split(sourcePort, ":")
targetArray := utils.Split(targetPort, ":")
func (_self *SysDataService) ChkPortForwardByApi(sourcePort, protocol, targetPort string) *Models.PortForward {
sourceArray := Utils.Split(sourcePort, ":")
targetArray := Utils.Split(targetPort, ":")
addr := sourceArray[0]
port := utils.ToInt(sourceArray[1])
port := Utils.ToInt(sourceArray[1])
toAddr := targetArray[0]
toPort := utils.ToInt(targetArray[1])
toPort := Utils.ToInt(targetArray[1])
return _self.GetPortForwardByApi(addr, port, protocol, toAddr, toPort)
}
func (_self *SysDataService) GetPortForwardByApi(addr string, port int, protocol string, targetAddr string, targetPort int) *models.PortForward {
func (_self *SysDataService) GetPortForwardByApi(addr string, port int, protocol string, targetAddr string, targetPort int) *Models.PortForward {
entity := new(models.PortForward)
entity := new(Models.PortForward)
qs := OrmerS.QueryTable(entity)
qs = qs.Filter("Addr", addr)
@@ -138,41 +138,70 @@ func (_self *SysDataService) GetPortForwardByApi(addr string, port int, protocol
}
func (_self *SysDataService) SavePortForwardByApi(sourcePort, protocol, targetPort string) (*models.PortForward, error) {
if utils.IsEmpty(sourcePort) {
func (_self *SysDataService) SavePortForwardByApi(sourcePort, protocol, targetPort string) (*Models.PortForward, error) {
if Utils.IsEmpty(sourcePort) {
return nil, errors.New("本地监听端口信息不能为空")
}
if utils.IsEmpty(targetPort) {
if Utils.IsEmpty(targetPort) {
return nil, errors.New("目标端口信息不能为空")
}
sourceArray := utils.Split(sourcePort, ":")
targetArray := utils.Split(targetPort, ":")
sourceArray := Utils.Split(sourcePort, ":")
targetArray := Utils.Split(targetPort, ":")
entity := &models.PortForward{}
entity := &Models.PortForward{}
entity.Name = "API_Forward_" + sourcePort
entity.Addr = sourceArray[0]
entity.Port = utils.ToInt(sourceArray[1])
entity.Port = Utils.ToInt(sourceArray[1])
entity.Protocol = protocol
entity.TargetAddr = targetArray[0]
entity.TargetPort = utils.ToInt(targetArray[1])
entity.TargetPort = Utils.ToInt(targetArray[1])
entity.CreateTime = time.Now()
_, err := OrmerS.Insert(entity)
return entity, err
}
func (_self *SysDataService) GetPortForwardList(query *models.PortForward, pageIndex int64, pageSize int64) models.PageData {
func (_self *SysDataService) GetAllPortForwardList(status int) []*Models.PortForward {
var entites []*models.PortForward
entity := new(models.PortForward)
var entites []*Models.PortForward
entity := new(Models.PortForward)
qs := OrmerS.QueryTable(entity)
if status > -1 {
qs = qs.Filter("Status", status)
}
num, err := qs.All(&entites)
if err != nil {
logs.Error("GetAllPortForwardList ", err)
} else {
logs.Debug("GetAllPortForwardList rows ", num)
}
return entites
}
func (_self *SysDataService) GetPortForwardList(query *Models.PortForward, pageIndex int64, pageSize int64) Models.PageData {
var entites []*Models.PortForward
entity := new(Models.PortForward)
qs := OrmerS.QueryTable(entity)
if query.Port > 0 {
qs = qs.Filter("Port", query.Port)
}
if len(query.TargetAddr) > 0 {
qs = qs.Filter("TargetAddr__icontains", query.TargetAddr)
}
if query.TargetPort > 0 {
qs = qs.Filter("TargetPort", query.TargetPort)
}
if query.FType > -1 {
qs = qs.Filter("FType", query.FType)
}
@@ -191,16 +220,16 @@ func (_self *SysDataService) GetPortForwardList(query *models.PortForward, pageI
logs.Debug("GetPortForwardList rows ", num)
}
return models.PageData{PIndex: pageIndex, PSize: pageSize, TotalRows: totals, Pages: int64(pages), Data: entites}
return Models.PageData{PIndex: pageIndex, PSize: pageSize, TotalRows: totals, Pages: int64(pages), Data: entites}
}
func (_self *SysDataService) SavePortForward(entity *models.PortForward) error {
func (_self *SysDataService) SavePortForward(entity *Models.PortForward) error {
if entity.Id > 0 {
update := &models.PortForward{}
update := &Models.PortForward{}
qs := OrmerS.QueryTable(new(models.PortForward))
qs := OrmerS.QueryTable(new(Models.PortForward))
qs = qs.Filter("Id", entity.Id)
err := qs.One(update)
if err != nil {
@@ -216,6 +245,7 @@ func (_self *SysDataService) SavePortForward(entity *models.PortForward) error {
update.TargetPort = entity.TargetPort
update.Others = entity.Others
update.FType = entity.FType
update.Status = entity.Status
_, err1 := OrmerS.Update(update)
return err1
@@ -240,7 +270,7 @@ func (_self *SysDataService) SavePortForward(entity *models.PortForward) error {
func (_self *SysDataService) DelPortForwards(ids []int) error {
//sqlite3在debug模式中,每次操作后会卡住,release环境中没有问题
//批量删除
del_num, err := OrmerS.QueryTable(new(models.PortForward)).Filter("Id__in", ids).Delete()
del_num, err := OrmerS.QueryTable(new(Models.PortForward)).Filter("Id__in", ids).Delete()
if err != nil {
logs.Error("DelPortForwards err", err)
return err
@@ -252,3 +282,24 @@ func (_self *SysDataService) DelPortForwards(ids []int) error {
return nil
}
func (_self *SysDataService) ToForwardConfig(entity *Models.PortForward) *Models.ForwardConfig {
config := new(Models.ForwardConfig)
config.RuleId = entity.Id
config.Name = entity.Name
config.Protocol = entity.Protocol
config.SrcAddr = entity.Addr
config.SrcPort = entity.Port
config.DestAddr = entity.TargetAddr
config.DestPort = entity.TargetPort
config.Status = entity.Status
return config
}
func (_self *SysDataService) GetForwardJob(entity *Models.PortForward) *ForWardJob {
return ForWardServ.GetForwardJob(_self.ToForwardConfig(entity))
}
+207
View File
@@ -0,0 +1,207 @@
package Service
import (
"github.com/astaxie/beego/logs"
"net"
"sync"
"time"
)
type UdpForward struct {
SrcAddr *net.UDPAddr
DestAddr *net.UDPAddr
LClientAddr *net.UDPAddr
UdpListenerConn *net.UDPConn
UdpConns map[string]UdpConn
UdpConnsMutex *sync.RWMutex
ChkActTime time.Duration
Closed bool
ConnectedEvent func(addr string)
DisConnectedEvent func(addr string)
}
type UdpConn struct {
udp *net.UDPConn
lastActive time.Time
}
const bufferSize = 4096
var chkActTime = time.Minute * 1
func NewUdpForward() *UdpForward {
return &UdpForward{
UdpConns:make(map[string]UdpConn),
UdpConnsMutex:new(sync.RWMutex),
ChkActTime:chkActTime,
ConnectedEvent:func(addr string) {},
DisConnectedEvent:func(addr string){},
}
}
func (_self *UdpForward) DoUdpForward (srcAddr string, destAddr string) error {
var err error
_self.SrcAddr, err = net.ResolveUDPAddr("udp", srcAddr)
if err != nil {
logs.Error("ResolveUDPAddr ", srcAddr, " 出错:", err)
return err
}
_self.DestAddr, err = net.ResolveUDPAddr("udp", destAddr)
if err != nil {
logs.Error("ResolveUDPAddr ", destAddr, " 出错:", err)
return err
}
_self.LClientAddr = &net.UDPAddr{
IP: _self.SrcAddr.IP,
Port: 0,
Zone: _self.SrcAddr.Zone,
}
_self.UdpListenerConn, err = net.ListenUDP("udp", _self.SrcAddr)
if err != nil {
logs.Error("启动UDP监听 ", srcAddr, " 出错:", err)
return err
}
go _self.checkAlive()
go _self.runForward()
return nil
}
func (_self *UdpForward) runForward() {
for {
buf := make([]byte, bufferSize)
n, addr, err := _self.UdpListenerConn.ReadFromUDP(buf)
if err != nil {
return
}
go _self.forwardHandler(buf[:n], addr)
}
}
func (_self *UdpForward) forwardHandler(data []byte, addr *net.UDPAddr) {
_self.UdpConnsMutex.RLock()
udpConn, found := _self.UdpConns[addr.String()]
_self.UdpConnsMutex.RUnlock()
if found {
udpConn.udp.WriteTo(data, _self.DestAddr)
}else{
conn, err := net.ListenUDP("udp", _self.LClientAddr)
if err != nil {
logs.Error("udp-forwader: failed to dial:", err)
return
}
_self.UdpConnsMutex.Lock()
_self.UdpConns[addr.String()] = UdpConn{
udp: conn,
lastActive: time.Now(),
}
_self.UdpConnsMutex.Unlock()
_self.ConnectedEvent(addr.String())
conn.WriteTo(data, _self.DestAddr)
for {
buf := make([]byte, bufferSize)
n, _, err := conn.ReadFromUDP(buf)
if err != nil {
_self.UdpConnsMutex.Lock()
conn.Close()
delete(_self.UdpConns, addr.String())
_self.UdpConnsMutex.Unlock()
return
}
go func(data []byte, conn *net.UDPConn, addr *net.UDPAddr) {
_self.UdpListenerConn.WriteTo(data, addr)
}(buf[:n], conn, addr)
}
}
_self.updateActiveTime(addr)
}
func (_self *UdpForward) updateActiveTime(addr *net.UDPAddr) {
needUpdateTime := false
_self.UdpConnsMutex.RLock()
if _, found := _self.UdpConns[addr.String()]; found {
if _self.UdpConns[addr.String()].lastActive.Before(
time.Now().Add(_self.ChkActTime / 4)) {
needUpdateTime = true
//logs.Debug("needUpdateTime")
}
}
_self.UdpConnsMutex.RUnlock()
if needUpdateTime {
_self.UdpConnsMutex.Lock()
//
if _, found := _self.UdpConns[addr.String()]; found {
connWrapper := _self.UdpConns[addr.String()]
connWrapper.lastActive = time.Now()
_self.UdpConns[addr.String()] = connWrapper
}
_self.UdpConnsMutex.Unlock()
}
}
func (_self *UdpForward) checkAlive() {
for !_self.Closed {
time.Sleep(_self.ChkActTime)
var keysToDelete []string
_self.UdpConnsMutex.RLock()
for k, conn := range _self.UdpConns {
if conn.lastActive.Before(time.Now().Add(-_self.ChkActTime)) {
keysToDelete = append(keysToDelete, k)
//logs.Debug("need delete udp conn")
}
}
_self.UdpConnsMutex.RUnlock()
_self.UdpConnsMutex.Lock()
for _, k := range keysToDelete {
_self.UdpConns[k].udp.Close()
delete(_self.UdpConns, k)
}
_self.UdpConnsMutex.Unlock()
for _, k := range keysToDelete {
_self.DisConnectedEvent(k)
}
}
}
func (_self *UdpForward) Close() {
_self.UdpConnsMutex.Lock()
_self.Closed = true
for _, conn := range _self.UdpConns {
conn.udp.Close()
}
_self.UdpListenerConn.Close()
_self.UdpConnsMutex.Unlock()
}
func (_self *UdpForward) GetConnsInfo() []string {
_self.UdpConnsMutex.Lock()
defer _self.UdpConnsMutex.Unlock()
results := make([]string, 0, len(_self.UdpConns))
for key := range _self.UdpConns {
results = append(results, key)
}
return results
}
+23
View File
@@ -0,0 +1,23 @@
::Build For Linux
echo "Clean for build..."
go clean
echo "Build For Linux..."
::set CGO_ENABLED=0
set GOOS=linux
set GOARCH=amd64
go build -o forward-server
::go build -ldflags "-s -w" -o forward-server
::-s 去掉符号表
::-w 去掉DWARF调试信息,得到的程序不能用gdb调试
echo "--------- Build For Linux Success!"
pause
+13
View File
@@ -0,0 +1,13 @@
#!/bin/sh
export GoDevWork=/Users/tavenli/Desktop/Work/port-forward-v2
echo "Build For Linux..."
export GOOS=linux
export GOARCH=amd64
export GOPATH=${GoDevWork}:${GOPATH}
go build -o forward-server
echo "--------- Build For Linux Success!"
+13
View File
@@ -0,0 +1,13 @@
echo "Build For Mac..."
set GOOS=darwin
set GOARCH=amd64
go build -o forward-server
echo "--------- Build For Mac Success!"
pause
+18
View File
@@ -0,0 +1,18 @@
::set GoDevWork="D:\CodeWork\port-forward\"
echo "Clean for build..."
go clean
echo "Build For windows..."
set GOOS=windows
set GOARCH=amd64
::set GOPATH=%GoDevWork%;%GOPATH%
go build -o forward-server.exe
echo "--------- Build For windows Success!"
pause
@@ -2,20 +2,18 @@
app.name = "PortForward"
app.cname = "端口转发系统"
servername = "PortForward-Server"
httpport = 8000
runmode ="dev"
#runmode ="prod"
viewspath = "views"
#logfile.config = "close"
[dev]
httpaddr = "0.0.0.0"
httpport = 8000
httpport = 8080
recoverpanic = false
app.store = "mysql"
mysql.url = "root:grant@tcp(127.0.0.1:3306)/PortForwardDb?charset=utf8&loc=Asia%2FShanghai"
[prod]
httpaddr = "0.0.0.0"
httpport = 8000
httpport = 8080
recoverpanic = true
graceful = true
@@ -3,3 +3,4 @@ api.auth = "26CCD056107481F45D1AC805A24A9E59"
agent.auth = "722ED8F8D9900CC1AB17243DC7B51A2D"
onstart.forward = "false"
+13
View File
@@ -0,0 +1,13 @@
module forward-server
go 1.14
require (
forward-core v0.0.0-00010101000000-000000000000
github.com/astaxie/beego v1.12.2
github.com/mattn/go-sqlite3 v2.0.3+incompatible
github.com/vmihailenco/msgpack v4.0.4+incompatible
google.golang.org/appengine v1.6.7 // indirect
)
replace forward-core => ../forward-core
+225
View File
@@ -0,0 +1,225 @@
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk=
github.com/astaxie/beego v1.12.2 h1:CajUexhSX5ONWDiSCpeQBNVfTzOtPb9e9d+3vuU5FuU=
github.com/astaxie/beego v1.12.2/go.mod h1:TMcqhsbhN3UFpN+RCfysaxPAbrhox6QSS3NIAEp/uzE=
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 h1:OYA+5W64v3OgClL+IrOD63t4i/RW7RqrAVl9LTZ9UqQ=
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394/go.mod h1:Q8n74mJTIgjX4RBBcHnJ05h//6/k6foqmgE45jTQtxg=
github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd/go.mod h1:1b+Y/CofkYwXMUU0OhQqGvsY2Bvgr4j6jfT699wyZKQ=
github.com/beego/x2j v0.0.0-20131220205130-a0352aadc542/go.mod h1:kSeGC/p1AbBiEp5kat81+DSQrZenVBZXklMLaELspWU=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60=
github.com/casbin/casbin v1.7.0/go.mod h1:c67qKN6Oum3UF5Q1+BByfFxkwKvhwW57ITjqwtzR1KE=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80=
github.com/couchbase/go-couchbase v0.0.0-20200519150804-63f3cdb75e0d/go.mod h1:TWI8EKQMs5u5jLKW/tsb9VwauIrMIxQG1r5fMsswK5U=
github.com/couchbase/gomemcached v0.0.0-20200526233749-ec430f949808/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c=
github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/elastic/go-elasticsearch/v6 v6.8.5/go.mod h1:UwaDJsD3rWLM5rKNFzv9hgox93HoX8utj1kxD9aFUcI=
github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk=
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/glendc/gopher-json v0.0.0-20170414221815-dc4743023d0c/go.mod h1:Gja1A+xZ9BoviGJNA2E9vFkPjjsl+CoJxSXiQM1UXtw=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-redis/redis v6.14.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/klauspost/cpuid v1.2.4 h1:EBfaK0SWSwk+fgk6efYFWdzl8MwRWoOO1gkmiaTXPW4=
github.com/klauspost/cpuid v1.2.4/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/reedsolomon v1.9.9 h1:qCL7LZlv17xMixl55nq2/Oa1Y86nfO8EqDfv2GHND54=
github.com/klauspost/reedsolomon v1.9.9/go.mod h1:O7yFFHiQwDR6b2t63KPUpccPtNdp5ADgh1gg4fd12wo=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/ledisdb/ledisdb v0.0.0-20200510135210-d35789ec47e6/go.mod h1:n931TsDuKuq+uX4v1fulaMbA/7ZLLhjc85h7chZGBCQ=
github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mmcloughlin/avo v0.0.0-20200803215136-443f81d77104 h1:ULR/QWMgcgRiZLUjSSJMU+fW+RDMstRdmnDWj9Q+AsA=
github.com/mmcloughlin/avo v0.0.0-20200803215136-443f81d77104/go.mod h1:wqKykBG2QzQDJEzvRkcS8x6MiSJkF52hXZsXcjaB3ls=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/pelletier/go-toml v1.0.1/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/peterh/liner v1.0.1-0.20171122030339-3681c2a91233/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.7.0 h1:wCi7urQOGBsYcQROHqpUUX4ct84xp40t9R9JX0FuA/U=
github.com/prometheus/client_golang v1.7.0/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 h1:X+yvsM2yrEktyI+b2qND5gpH8YhURn0k8OCaeRnkINo=
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
github.com/siddontang/go v0.0.0-20170517070808-cb568a3e5cc0/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
github.com/siddontang/goredis v0.0.0-20150324035039-760763f78400/go.mod h1:DDcKzU3qCuvj/tPnimWSsZZzvk9qvkvrIL5naVBPh5s=
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec/go.mod h1:QBvMkMya+gXctz3kmljlUCu/yB3GZ6oee+dUozsezQE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/syndtr/goleveldb v0.0.0-20160425020131-cfa635847112/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
github.com/ugorji/go v0.0.0-20171122102828-84cb69a8af83/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
github.com/ugorji/go v1.1.13 h1:nB3O5kBSQGjEQAcfe1aLUYuxmXdFKmYgBZhY32rQb6Q=
github.com/ugorji/go v1.1.13/go.mod h1:jxau1n+/wyTGLQoCkjok9r5zFa/FxT6eI5HiHKQszjc=
github.com/ugorji/go/codec v1.1.13 h1:013LbFhocBoIqgHeIHKlV4JWYhqogATYWZhIcH0WHn4=
github.com/ugorji/go/codec v1.1.13/go.mod h1:oNVt3Dq+FO91WNQ/9JnHKQP2QJxTzoN7wCBFCq1OeuU=
github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI=
github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
github.com/vzex/internal v0.0.0-20171013154326-dfb733a0d236 h1:3trmo370DZOjjLG1dNmndVAUCfDD1f4jvu2xDDqrOs8=
github.com/vzex/internal v0.0.0-20171013154326-dfb733a0d236/go.mod h1:sHzPrs6FKhwLPhAS8dd78TXJ8oW08cHYUkMBhBJd2Yg=
github.com/vzex/mathutil v0.0.0-20170925121414-53c70789c7ff h1:FNV7atNSgquZ9j5esAroK2qdMPNtHxzGpyUO1L465b4=
github.com/vzex/mathutil v0.0.0-20170925121414-53c70789c7ff/go.mod h1:3+1ZBsJJLlEmRwraBhPTTMvgo+UFpm8nOVp2Eh0byM0=
github.com/vzex/zappy v0.0.0-20171014114341-f5f547bd8793 h1:Z+hNZ8IKayfetfivugi98jReDRvvh1jJmUpduzhxQqY=
github.com/vzex/zappy v0.0.0-20171014114341-f5f547bd8793/go.mod h1:foiOFrN9lntdJ5ekyxoLfolphrq3gi0vWRsjJvsWG+A=
github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/gopher-lua v0.0.0-20171031051903-609c9cd26973/go.mod h1:aEV29XrmTYFr3CiRxZeGHpkvbwq+prZduBqMaascyCU=
golang.org/x/arch v0.0.0-20190909030613-46d78d1859ac/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/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-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/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-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/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=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200117065230-39095c1d176c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200425043458-8463f397d07c h1:iHhCR0b26amDCiiO+kBguKZom9aMF+NrFxh9zeKR/XU=
golang.org/x/tools v0.0.0-20200425043458-8463f397d07c/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
+97
View File
@@ -0,0 +1,97 @@
package main
import (
"fmt"
"forward-server/Service"
_ "forward-server/routers"
"forward-core/Models"
"github.com/astaxie/beego"
"github.com/astaxie/beego/logs"
_ "github.com/mattn/go-sqlite3"
"github.com/vmihailenco/msgpack"
)
func main() {
logFileConfig := beego.AppConfig.String("logfile.config")
//日志级别:"emergency", "alert", "critical", "error", "warning", "notice", "info", "debug"
logs.SetLogger(logs.AdapterConsole, `{"level":7}`)
if len(logFileConfig) == 0 {
logFileConfig = `{"filename":"app.log","level":7,"maxlines":0,"maxsize":0,"daily":true,"maxdays":10}`
}
if logFileConfig != "close" {
//logs.SetLogger(logs.AdapterFile, `{"filename":"app.log","level":7,"maxlines":0,"maxsize":0,"daily":true,"maxdays":10}`)
logs.SetLogger(logs.AdapterFile, logFileConfig)
}
//输出文件名和行号
logs.EnableFuncCallDepth(true)
logs.SetLogFuncCallDepth(3)
//为了让日志输出不影响性能,开启异步日志
logs.Async()
logs.Debug("★★★★★★★★★★★★★★★★★★★★")
logs.Debug(" tcp-forward 启动")
logs.Debug("")
logs.Debug("项目地址:https://github.com/tavenli/port-forward")
logs.Debug("")
logs.Debug("★★★★★★★★★★★★★★★★★★★★")
//test1()
//启动Web控制台和接口
Service.ConsoleServ.StartHttpServer()
//select {}
//endRunning := make(chan bool, 1)
//time.Sleep(1* time.Second)
//endRunning <- true
//<-endRunning
}
func test1() {
//github.com/gogf/gf/g/os/glog
//glog.Debug("This is Debug")
//glog.Info("This is Info")
b, err := msgpack.Marshal(&Models.PortInfo{Addr: "bar"})
if err != nil {
panic(err)
}
var item Models.PortInfo
err = msgpack.Unmarshal(b, &item)
if err != nil {
panic(err)
}
logs.Debug(item.Addr)
//
config := new(Models.ForwardConfig)
//config.Protocol = "TCP"
config.Protocol = "UDP"
config.SrcAddr = ""
config.SrcPort = 8888
//106.14.184.192:9999
//config.DestAddr = "106.14.184.192"
//config.DestPort = 9999
config.DestAddr = "svn.apiclub.top"
config.DestPort = 9900
config.Status = 0
config.Name = "测试1"
config.RuleId = 1
resultChan := make(chan Models.FuncResult)
Service.ForWardServ.OpenForward(config, resultChan)
fmt.Println(<-resultChan)
}
@@ -0,0 +1,298 @@
package routers
import (
"github.com/astaxie/beego"
"github.com/astaxie/beego/context/param"
)
func init() {
beego.GlobalControllerRouter["forward-server/Controllers:DefaultCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:DefaultCtrl"],
beego.ControllerComments{
Method: "Default",
Router: `/`,
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["forward-server/Controllers:DefaultCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:DefaultCtrl"],
beego.ControllerComments{
Method: "ApiAuthFail",
Router: `/apiAuthFail`,
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"],
beego.ControllerComments{
Method: "AddForward",
Router: `/u/AddForward`,
AllowHTTPMethods: []string{"get", "post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"],
beego.ControllerComments{
Method: "ApiDoc",
Router: `/u/ApiDoc`,
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"],
beego.ControllerComments{
Method: "ClearNetAgentStatus",
Router: `/u/ClearNetAgentStatus`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"],
beego.ControllerComments{
Method: "CloseForward",
Router: `/u/CloseForward`,
AllowHTTPMethods: []string{"get", "post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"],
beego.ControllerComments{
Method: "OpenAllForward",
Router: `/u/OpenAllForward`,
AllowHTTPMethods: []string{"get", "post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"],
beego.ControllerComments{
Method: "CloseAllForward",
Router: `/u/CloseAllForward`,
AllowHTTPMethods: []string{"get", "post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"],
beego.ControllerComments{
Method: "CloseMagicService",
Router: `/u/CloseMagicService`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"],
beego.ControllerComments{
Method: "DelForward",
Router: `/u/DelForward`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"],
beego.ControllerComments{
Method: "EditForward",
Router: `/u/EditForward`,
AllowHTTPMethods: []string{"get", "post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"],
beego.ControllerComments{
Method: "ForwardList",
Router: `/u/ForwardList`,
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"],
beego.ControllerComments{
Method: "ForwardListJson",
Router: `/u/ForwardList/json`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"],
beego.ControllerComments{
Method: "GetMagicStatus",
Router: `/u/GetMagicStatus`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"],
beego.ControllerComments{
Method: "GetNetAgentStatus",
Router: `/u/GetNetAgentStatus`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"],
beego.ControllerComments{
Method: "NetAgent",
Router: `/u/NetAgent`,
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"],
beego.ControllerComments{
Method: "OpenForward",
Router: `/u/OpenForward`,
AllowHTTPMethods: []string{"get", "post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"],
beego.ControllerComments{
Method: "OpenMagicService",
Router: `/u/OpenMagicService`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"],
beego.ControllerComments{
Method: "SaveForward",
Router: `/u/SaveForward`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"],
beego.ControllerComments{
Method: "StartAgentJob",
Router: `/u/StartAgentJob`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:ForwardCtrl"],
beego.ControllerComments{
Method: "StopAgentJob",
Router: `/u/StopAgentJob`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["forward-server/Controllers:LoginCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:LoginCtrl"],
beego.ControllerComments{
Method: "Login",
Router: `/login`,
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["forward-server/Controllers:LoginCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:LoginCtrl"],
beego.ControllerComments{
Method: "DoLogin",
Router: `/login`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["forward-server/Controllers:LoginCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:LoginCtrl"],
beego.ControllerComments{
Method: "Logout",
Router: `/logout`,
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["forward-server/Controllers:RestApiCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:RestApiCtrl"],
beego.ControllerComments{
Method: "CloseForward",
Router: `/CloseForward`,
AllowHTTPMethods: []string{"get", "post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["forward-server/Controllers:RestApiCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:RestApiCtrl"],
beego.ControllerComments{
Method: "OpenForward",
Router: `/OpenForward`,
AllowHTTPMethods: []string{"get", "post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["forward-server/Controllers:RestApiCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:RestApiCtrl"],
beego.ControllerComments{
Method: "ServerSummary",
Router: `/ServerSummary`,
AllowHTTPMethods: []string{"get", "post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["forward-server/Controllers:UCenterCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:UCenterCtrl"],
beego.ControllerComments{
Method: "ChangePwd",
Router: `/u/changePwd`,
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["forward-server/Controllers:UCenterCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:UCenterCtrl"],
beego.ControllerComments{
Method: "DoChangePwd",
Router: `/u/doChangePwd`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["forward-server/Controllers:UCenterCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:UCenterCtrl"],
beego.ControllerComments{
Method: "GetServerTime",
Router: `/u/getServerTime`,
AllowHTTPMethods: []string{"post"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["forward-server/Controllers:UCenterCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:UCenterCtrl"],
beego.ControllerComments{
Method: "Index",
Router: `/u/index`,
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
beego.GlobalControllerRouter["forward-server/Controllers:UCenterCtrl"] = append(beego.GlobalControllerRouter["forward-server/Controllers:UCenterCtrl"],
beego.ControllerComments{
Method: "Main",
Router: `/u/main`,
AllowHTTPMethods: []string{"get"},
MethodParams: param.Make(),
Filters: nil,
Params: nil})
}
+26
View File
@@ -0,0 +1,26 @@
package routers
import (
"forward-server/Controllers"
"github.com/astaxie/beego"
)
func init() {
//
beego.Include(&Controllers.DefaultCtrl{})
beego.Include(&Controllers.LoginCtrl{})
beego.Include(&Controllers.UCenterCtrl{})
beego.Include(&Controllers.ForwardCtrl{})
api_ns := beego.NewNamespace("/api",
beego.NSNamespace("/v1",
beego.NSInclude(
&Controllers.RestApiCtrl{},
),
),
)
beego.AddNamespace(api_ns)
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
/** layui-v2.5.6 MIT License By https://www.layui.com */
html #layuicss-skincodecss{display:none;position:absolute;width:1989px}.layui-code-h3,.layui-code-view{position:relative;font-size:12px}.layui-code-view{display:block;margin:10px 0;padding:0;border:1px solid #e2e2e2;border-left-width:6px;background-color:#F2F2F2;color:#333;font-family:Courier New}.layui-code-h3{padding:0 10px;height:32px;line-height:32px;border-bottom:1px solid #e2e2e2}.layui-code-h3 a{position:absolute;right:10px;top:0;color:#999}.layui-code-view .layui-code-ol{position:relative;overflow:auto}.layui-code-view .layui-code-ol li{position:relative;margin-left:45px;line-height:20px;padding:0 5px;border-left:1px solid #e2e2e2;list-style-type:decimal-leading-zero;*list-style-type:decimal;background-color:#fff}.layui-code-view pre{margin:0}.layui-code-notepad{border:1px solid #0C0C0C;border-left-color:#3F3F3F;background-color:#0C0C0C;color:#C2BE9E}.layui-code-notepad .layui-code-h3{border-bottom:none}.layui-code-notepad .layui-code-ol li{background-color:#3F3F3F;border-left:none}
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 314 B

After

Width:  |  Height:  |  Size: 314 B

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Before

Width:  |  Height:  |  Size: 701 B

After

Width:  |  Height:  |  Size: 701 B

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 299 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Some files were not shown because too many files have changed in this diff Show More