mirror of
https://gitee.com/IrisVega/frp.git
synced 2024-11-01 22:31:29 +08:00
all: add "--reload" command for frps, reload ini file without kill old program
This commit is contained in:
parent
ee8786a6b3
commit
5febee6201
@ -10,4 +10,4 @@ godep:
|
|||||||
GOPATH=$(OLDGOPATH) go get github.com/mitchellh/gox
|
GOPATH=$(OLDGOPATH) go get github.com/mitchellh/gox
|
||||||
|
|
||||||
app:
|
app:
|
||||||
gox -osarch "darwin/386 darwin/amd64 linux/386 linux/amd64 linux/arm windows/386 windows/amd64" ./...
|
gox -osarch "darwin/386 darwin/amd64 linux/386 linux/amd64 linux/arm windows/386 windows/amd64" ./src/...
|
||||||
|
@ -4,7 +4,7 @@ bind_addr = 0.0.0.0
|
|||||||
bind_port = 7000
|
bind_port = 7000
|
||||||
# if you want to support virtual host, you must set the http port for listening (optional)
|
# if you want to support virtual host, you must set the http port for listening (optional)
|
||||||
vhost_http_port = 80
|
vhost_http_port = 80
|
||||||
# if you want to configure or reload frps by dashboard, dashboard_port is needed
|
# if you want to configure or reload frps by dashboard, dashboard_port must be set
|
||||||
dashboard_port = 7500
|
dashboard_port = 7500
|
||||||
# console or real logFile path like ./frps.log
|
# console or real logFile path like ./frps.log
|
||||||
log_file = ./frps.log
|
log_file = ./frps.log
|
||||||
|
@ -67,7 +67,7 @@ func controlWorker(c *conn.Conn) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// do login when type is NewCtlConn or NewWorkConn
|
// login when type is NewCtlConn or NewWorkConn
|
||||||
ret, info := doLogin(cliReq, c)
|
ret, info := doLogin(cliReq, c)
|
||||||
s, ok := server.ProxyServers[cliReq.ProxyName]
|
s, ok := server.ProxyServers[cliReq.ProxyName]
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -134,7 +134,6 @@ func msgReader(s *server.ProxyServer, c *conn.Conn, msgSendChan chan interface{}
|
|||||||
timer := time.AfterFunc(time.Duration(server.HeartBeatTimeout)*time.Second, func() {
|
timer := time.AfterFunc(time.Duration(server.HeartBeatTimeout)*time.Second, func() {
|
||||||
heartbeatTimeout = true
|
heartbeatTimeout = true
|
||||||
s.Close()
|
s.Close()
|
||||||
c.Close()
|
|
||||||
log.Error("ProxyName [%s], client heartbeat timeout", s.Name)
|
log.Error("ProxyName [%s], client heartbeat timeout", s.Name)
|
||||||
})
|
})
|
||||||
defer timer.Stop()
|
defer timer.Stop()
|
||||||
@ -229,7 +228,7 @@ func doLogin(req *msg.ControlReq, c *conn.Conn) (ret int64, info string) {
|
|||||||
s.UseEncryption = req.UseEncryption
|
s.UseEncryption = req.UseEncryption
|
||||||
|
|
||||||
// start proxy and listen for user connections, no block
|
// start proxy and listen for user connections, no block
|
||||||
err := s.Start()
|
err := s.Start(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
info = fmt.Sprintf("ProxyName [%s], start proxy error: %v", req.ProxyName, err)
|
info = fmt.Sprintf("ProxyName [%s], start proxy error: %v", req.ProxyName, err)
|
||||||
log.Warn(info)
|
log.Warn(info)
|
||||||
|
@ -15,7 +15,10 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -30,15 +33,13 @@ import (
|
|||||||
"frp/utils/vhost"
|
"frp/utils/vhost"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
configFile string = "./frps.ini"
|
|
||||||
)
|
|
||||||
|
|
||||||
var usage string = `frps is the server of frp
|
var usage string = `frps is the server of frp
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
frps [-c config_file] [-L log_file] [--log-level=<log_level>] [--addr=<bind_addr>]
|
frps [-c config_file] [-L log_file] [--log-level=<log_level>] [--addr=<bind_addr>]
|
||||||
frps -h | --help | --version
|
frps --reload
|
||||||
|
frps -h | --help
|
||||||
|
frps -v | --version
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
-c config_file set config file
|
-c config_file set config file
|
||||||
@ -46,7 +47,7 @@ Options:
|
|||||||
--log-level=<log_level> set log level: debug, info, warn, error
|
--log-level=<log_level> set log level: debug, info, warn, error
|
||||||
--addr=<bind_addr> listen addr for client, example: 0.0.0.0:7000
|
--addr=<bind_addr> listen addr for client, example: 0.0.0.0:7000
|
||||||
-h --help show this screen
|
-h --help show this screen
|
||||||
--version show version
|
-v --version show version
|
||||||
`
|
`
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -54,14 +55,43 @@ func main() {
|
|||||||
args, err := docopt.Parse(usage, nil, true, version.Full(), false)
|
args, err := docopt.Parse(usage, nil, true, version.Full(), false)
|
||||||
|
|
||||||
if args["-c"] != nil {
|
if args["-c"] != nil {
|
||||||
configFile = args["-c"].(string)
|
server.ConfigFile = args["-c"].(string)
|
||||||
}
|
}
|
||||||
err = server.LoadConf(configFile)
|
err = server.LoadConf(server.ConfigFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
os.Exit(-1)
|
os.Exit(-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reload check
|
||||||
|
if args["--reload"] != nil {
|
||||||
|
if args["--reload"].(bool) {
|
||||||
|
resp, err := http.Get("http://" + server.BindAddr + ":" + fmt.Sprintf("%d", server.DashboardPort) + "/api/reload")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("frps reload error: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
} else {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("frps reload error: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
res := &server.GeneralResponse{}
|
||||||
|
err = json.Unmarshal(body, &res)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("http response error: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
} else if res.Code != 0 {
|
||||||
|
fmt.Printf("reload error: %s\n", res.Msg)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
fmt.Printf("reload success\n")
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if args["-L"] != nil {
|
if args["-L"] != nil {
|
||||||
if args["-L"].(string) == "console" {
|
if args["-L"].(string) == "console" {
|
||||||
server.LogWay = "console"
|
server.LogWay = "console"
|
||||||
@ -90,6 +120,13 @@ func main() {
|
|||||||
server.BindPort = bindPort
|
server.BindPort = bindPort
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if args["-v"] != nil {
|
||||||
|
if args["-v"].(bool) {
|
||||||
|
fmt.Println(version.Full())
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
log.InitLog(server.LogWay, server.LogFile, server.LogLevel, server.LogMaxDays)
|
log.InitLog(server.LogWay, server.LogFile, server.LogLevel, server.LogMaxDays)
|
||||||
|
|
||||||
l, err := conn.Listen(server.BindAddr, server.BindPort)
|
l, err := conn.Listen(server.BindAddr, server.BindPort)
|
||||||
@ -111,7 +148,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// create dashboard web server if DashboardPort != 0
|
// create dashboard web server if DashboardPort is set, so it won't be 0
|
||||||
if server.DashboardPort != 0 {
|
if server.DashboardPort != 0 {
|
||||||
err := server.RunDashboardServer(server.BindAddr, server.DashboardPort)
|
err := server.RunDashboardServer(server.BindAddr, server.DashboardPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -18,14 +18,17 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
ini "github.com/vaughan0/go-ini"
|
ini "github.com/vaughan0/go-ini"
|
||||||
|
|
||||||
|
"frp/utils/log"
|
||||||
"frp/utils/vhost"
|
"frp/utils/vhost"
|
||||||
)
|
)
|
||||||
|
|
||||||
// common config
|
// common config
|
||||||
var (
|
var (
|
||||||
|
ConfigFile string = "./frps.ini"
|
||||||
BindAddr string = "0.0.0.0"
|
BindAddr string = "0.0.0.0"
|
||||||
BindPort int64 = 7000
|
BindPort int64 = 7000
|
||||||
VhostHttpPort int64 = 0 // if VhostHttpPort equals 0, don't listen a public port for http
|
VhostHttpPort int64 = 0 // if VhostHttpPort equals 0, don't listen a public port for http
|
||||||
@ -38,19 +41,38 @@ var (
|
|||||||
UserConnTimeout int64 = 10
|
UserConnTimeout int64 = 10
|
||||||
|
|
||||||
VhostMuxer *vhost.HttpMuxer
|
VhostMuxer *vhost.HttpMuxer
|
||||||
|
ProxyServers map[string]*ProxyServer = make(map[string]*ProxyServer) // all proxy servers info and resources
|
||||||
|
ProxyServersMutex sync.RWMutex
|
||||||
)
|
)
|
||||||
|
|
||||||
var ProxyServers map[string]*ProxyServer = make(map[string]*ProxyServer)
|
|
||||||
|
|
||||||
func LoadConf(confFile string) (err error) {
|
func LoadConf(confFile string) (err error) {
|
||||||
var tmpStr string
|
err = loadCommonConf(confFile)
|
||||||
var ok bool
|
|
||||||
|
|
||||||
conf, err := ini.LoadFile(confFile)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// load all proxy server's configure and initialize
|
||||||
|
// and set ProxyServers map
|
||||||
|
newProxyServers, err := loadProxyConf(confFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, proxyServer := range newProxyServers {
|
||||||
|
proxyServer.Init()
|
||||||
|
}
|
||||||
|
ProxyServersMutex.Lock()
|
||||||
|
ProxyServers = newProxyServers
|
||||||
|
ProxyServersMutex.Unlock()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadCommonConf(confFile string) error {
|
||||||
|
var tmpStr string
|
||||||
|
var ok bool
|
||||||
|
conf, err := ini.LoadFile(confFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
// common
|
// common
|
||||||
tmpStr, ok = conf.Get("common", "bind_addr")
|
tmpStr, ok = conf.Get("common", "bind_addr")
|
||||||
if ok {
|
if ok {
|
||||||
@ -95,18 +117,26 @@ func LoadConf(confFile string) (err error) {
|
|||||||
if ok {
|
if ok {
|
||||||
LogMaxDays, _ = strconv.ParseInt(tmpStr, 10, 64)
|
LogMaxDays, _ = strconv.ParseInt(tmpStr, 10, 64)
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadProxyConf(confFile string) (proxyServers map[string]*ProxyServer, err error) {
|
||||||
|
var ok bool
|
||||||
|
proxyServers = make(map[string]*ProxyServer)
|
||||||
|
conf, err := ini.LoadFile(confFile)
|
||||||
|
if err != nil {
|
||||||
|
return proxyServers, err
|
||||||
|
}
|
||||||
// servers
|
// servers
|
||||||
for name, section := range conf {
|
for name, section := range conf {
|
||||||
if name != "common" {
|
if name != "common" {
|
||||||
proxyServer := &ProxyServer{}
|
proxyServer := NewProxyServer()
|
||||||
proxyServer.CustomDomains = make([]string, 0)
|
|
||||||
proxyServer.Name = name
|
proxyServer.Name = name
|
||||||
|
|
||||||
proxyServer.Type, ok = section["type"]
|
proxyServer.Type, ok = section["type"]
|
||||||
if ok {
|
if ok {
|
||||||
if proxyServer.Type != "tcp" && proxyServer.Type != "http" {
|
if proxyServer.Type != "tcp" && proxyServer.Type != "http" {
|
||||||
return fmt.Errorf("Parse ini file error: proxy [%s] type error", proxyServer.Name)
|
return proxyServers, fmt.Errorf("Parse conf error: proxy [%s] type error", proxyServer.Name)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
proxyServer.Type = "tcp"
|
proxyServer.Type = "tcp"
|
||||||
@ -114,7 +144,7 @@ func LoadConf(confFile string) (err error) {
|
|||||||
|
|
||||||
proxyServer.AuthToken, ok = section["auth_token"]
|
proxyServer.AuthToken, ok = section["auth_token"]
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("Parse ini file error: proxy [%s] no auth_token found", proxyServer.Name)
|
return proxyServers, fmt.Errorf("Parse conf error: proxy [%s] no auth_token found", proxyServer.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// for tcp
|
// for tcp
|
||||||
@ -128,10 +158,10 @@ func LoadConf(confFile string) (err error) {
|
|||||||
if ok {
|
if ok {
|
||||||
proxyServer.ListenPort, err = strconv.ParseInt(portStr, 10, 64)
|
proxyServer.ListenPort, err = strconv.ParseInt(portStr, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Parse ini file error: proxy [%s] listen_port error", proxyServer.Name)
|
return proxyServers, fmt.Errorf("Parse conf error: proxy [%s] listen_port error", proxyServer.Name)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("Parse ini file error: proxy [%s] listen_port not found", proxyServer.Name)
|
return proxyServers, fmt.Errorf("Parse conf error: proxy [%s] listen_port not found", proxyServer.Name)
|
||||||
}
|
}
|
||||||
} else if proxyServer.Type == "http" {
|
} else if proxyServer.Type == "http" {
|
||||||
// for http
|
// for http
|
||||||
@ -142,20 +172,53 @@ func LoadConf(confFile string) (err error) {
|
|||||||
suffix = fmt.Sprintf(":%d", VhostHttpPort)
|
suffix = fmt.Sprintf(":%d", VhostHttpPort)
|
||||||
}
|
}
|
||||||
proxyServer.CustomDomains = strings.Split(domainStr, ",")
|
proxyServer.CustomDomains = strings.Split(domainStr, ",")
|
||||||
|
if len(proxyServer.CustomDomains) == 0 {
|
||||||
|
return proxyServers, fmt.Errorf("Parse conf error: proxy [%s] custom_domains must be set when type equals http", proxyServer.Name)
|
||||||
|
}
|
||||||
for i, domain := range proxyServer.CustomDomains {
|
for i, domain := range proxyServer.CustomDomains {
|
||||||
proxyServer.CustomDomains[i] = strings.ToLower(strings.TrimSpace(domain)) + suffix
|
proxyServer.CustomDomains[i] = strings.ToLower(strings.TrimSpace(domain)) + suffix
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
proxyServers[proxyServer.Name] = proxyServer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return proxyServers, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// the function can only reload proxy configures
|
||||||
|
// common section won't be changed
|
||||||
|
func ReloadConf(confFile string) (err error) {
|
||||||
|
loadProxyServers, err := loadProxyConf(confFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ProxyServersMutex.Lock()
|
||||||
|
for name, proxyServer := range loadProxyServers {
|
||||||
|
oldProxyServer, ok := ProxyServers[name]
|
||||||
|
if ok {
|
||||||
|
if !oldProxyServer.Compare(proxyServer) {
|
||||||
|
oldProxyServer.Close()
|
||||||
proxyServer.Init()
|
proxyServer.Init()
|
||||||
ProxyServers[proxyServer.Name] = proxyServer
|
ProxyServers[name] = proxyServer
|
||||||
|
log.Info("ProxyName [%s] configure change, restart", name)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
proxyServer.Init()
|
||||||
|
ProxyServers[name] = proxyServer
|
||||||
|
log.Info("ProxyName [%s] is new, init it", name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(ProxyServers) == 0 {
|
for name, oldProxyServer := range ProxyServers {
|
||||||
return fmt.Errorf("Parse ini file error: no proxy config found")
|
_, ok := loadProxyServers[name]
|
||||||
|
if !ok {
|
||||||
|
oldProxyServer.Close()
|
||||||
|
delete(ProxyServers, name)
|
||||||
|
log.Info("ProxyName [%s] deleted, close it", name)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
ProxyServersMutex.Unlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ func RunDashboardServer(addr string, port int64) (err error) {
|
|||||||
}()
|
}()
|
||||||
gin.SetMode(gin.ReleaseMode)
|
gin.SetMode(gin.ReleaseMode)
|
||||||
router := gin.New()
|
router := gin.New()
|
||||||
router.LoadHTMLGlob("assets/*")
|
//router.LoadHTMLGlob("assets/*")
|
||||||
router.GET("/api/reload", apiReload)
|
router.GET("/api/reload", apiReload)
|
||||||
go router.Run(fmt.Sprintf("%s:%d", addr, port))
|
go router.Run(fmt.Sprintf("%s:%d", addr, port))
|
||||||
return
|
return
|
||||||
|
@ -15,12 +15,32 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
|
"frp/utils/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func apiReload(c *gin.Context) {
|
type GeneralResponse struct {
|
||||||
c.JSON(200, gin.H{
|
Code int64 `json:"code"`
|
||||||
"code": 0,
|
Msg string `json:"msg"`
|
||||||
"msg": "ok",
|
}
|
||||||
})
|
|
||||||
|
func apiReload(c *gin.Context) {
|
||||||
|
res := &GeneralResponse{}
|
||||||
|
defer func() {
|
||||||
|
buf, _ := json.Marshal(res)
|
||||||
|
log.Info("Http response [/api/reload]: %s", string(buf))
|
||||||
|
}()
|
||||||
|
|
||||||
|
log.Info("Http request: [/api/reload]")
|
||||||
|
err := ReloadConf(ConfigFile)
|
||||||
|
if err != nil {
|
||||||
|
res.Code = 2
|
||||||
|
res.Msg = fmt.Sprintf("%v", err)
|
||||||
|
log.Error("frps reload error: %v", err)
|
||||||
|
}
|
||||||
|
c.JSON(200, res)
|
||||||
}
|
}
|
||||||
|
@ -35,21 +35,49 @@ type ProxyServer struct {
|
|||||||
Type string
|
Type string
|
||||||
BindAddr string
|
BindAddr string
|
||||||
ListenPort int64
|
ListenPort int64
|
||||||
UseEncryption bool
|
|
||||||
CustomDomains []string
|
CustomDomains []string
|
||||||
|
|
||||||
|
// configure in frpc.ini
|
||||||
|
UseEncryption bool
|
||||||
|
|
||||||
Status int64
|
Status int64
|
||||||
|
CtlConn *conn.Conn // control connection with frpc
|
||||||
listeners []Listener // accept new connection from remote users
|
listeners []Listener // accept new connection from remote users
|
||||||
ctlMsgChan chan int64 // every time accept a new user conn, put "1" to the channel
|
ctlMsgChan chan int64 // every time accept a new user conn, put "1" to the channel
|
||||||
workConnChan chan *conn.Conn // get new work conns from control goroutine
|
workConnChan chan *conn.Conn // get new work conns from control goroutine
|
||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewProxyServer() (p *ProxyServer) {
|
||||||
|
p = &ProxyServer{
|
||||||
|
CustomDomains: make([]string, 0),
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
func (p *ProxyServer) Init() {
|
func (p *ProxyServer) Init() {
|
||||||
|
p.Lock()
|
||||||
p.Status = consts.Idle
|
p.Status = consts.Idle
|
||||||
p.workConnChan = make(chan *conn.Conn, 100)
|
p.workConnChan = make(chan *conn.Conn, 100)
|
||||||
p.ctlMsgChan = make(chan int64)
|
p.ctlMsgChan = make(chan int64)
|
||||||
p.listeners = make([]Listener, 0)
|
p.listeners = make([]Listener, 0)
|
||||||
|
p.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ProxyServer) Compare(p2 *ProxyServer) bool {
|
||||||
|
if p.Name != p2.Name || p.AuthToken != p2.AuthToken || p.Type != p2.Type ||
|
||||||
|
p.BindAddr != p2.BindAddr || p.ListenPort != p2.ListenPort {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if len(p.CustomDomains) != len(p2.CustomDomains) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i, _ := range p.CustomDomains {
|
||||||
|
if p.CustomDomains[i] != p2.CustomDomains[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ProxyServer) Lock() {
|
func (p *ProxyServer) Lock() {
|
||||||
@ -61,7 +89,8 @@ func (p *ProxyServer) Unlock() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// start listening for user conns
|
// start listening for user conns
|
||||||
func (p *ProxyServer) Start() (err error) {
|
func (p *ProxyServer) Start(c *conn.Conn) (err error) {
|
||||||
|
p.CtlConn = c
|
||||||
p.Init()
|
p.Init()
|
||||||
if p.Type == "tcp" {
|
if p.Type == "tcp" {
|
||||||
l, err := conn.Listen(p.BindAddr, p.ListenPort)
|
l, err := conn.Listen(p.BindAddr, p.ListenPort)
|
||||||
@ -79,9 +108,11 @@ func (p *ProxyServer) Start() (err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p.Lock()
|
||||||
p.Status = consts.Working
|
p.Status = consts.Working
|
||||||
|
p.Unlock()
|
||||||
|
|
||||||
// start a goroutine for listener to accept user connection
|
// start a goroutine for every listener to accept user connection
|
||||||
for _, listener := range p.listeners {
|
for _, listener := range p.listeners {
|
||||||
go func(l Listener) {
|
go func(l Listener) {
|
||||||
for {
|
for {
|
||||||
@ -138,6 +169,9 @@ func (p *ProxyServer) Close() {
|
|||||||
}
|
}
|
||||||
close(p.ctlMsgChan)
|
close(p.ctlMsgChan)
|
||||||
close(p.workConnChan)
|
close(p.workConnChan)
|
||||||
|
if p.CtlConn != nil {
|
||||||
|
p.CtlConn.Close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
p.Unlock()
|
p.Unlock()
|
||||||
}
|
}
|
||||||
|
@ -92,6 +92,7 @@ type Conn struct {
|
|||||||
TcpConn net.Conn
|
TcpConn net.Conn
|
||||||
Reader *bufio.Reader
|
Reader *bufio.Reader
|
||||||
closeFlag bool
|
closeFlag bool
|
||||||
|
mutex sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConn(conn net.Conn) (c *Conn) {
|
func NewConn(conn net.Conn) (c *Conn) {
|
||||||
@ -129,7 +130,9 @@ func (c *Conn) GetLocalAddr() (addr string) {
|
|||||||
func (c *Conn) ReadLine() (buff string, err error) {
|
func (c *Conn) ReadLine() (buff string, err error) {
|
||||||
buff, err = c.Reader.ReadString('\n')
|
buff, err = c.Reader.ReadString('\n')
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
|
c.mutex.Lock()
|
||||||
c.closeFlag = true
|
c.closeFlag = true
|
||||||
|
c.mutex.Unlock()
|
||||||
}
|
}
|
||||||
return buff, err
|
return buff, err
|
||||||
}
|
}
|
||||||
@ -146,14 +149,19 @@ func (c *Conn) SetDeadline(t time.Time) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) Close() {
|
func (c *Conn) Close() {
|
||||||
|
c.mutex.Lock()
|
||||||
if c.TcpConn != nil && c.closeFlag == false {
|
if c.TcpConn != nil && c.closeFlag == false {
|
||||||
c.closeFlag = true
|
c.closeFlag = true
|
||||||
c.TcpConn.Close()
|
c.TcpConn.Close()
|
||||||
}
|
}
|
||||||
|
c.mutex.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Conn) IsClosed() bool {
|
func (c *Conn) IsClosed() (closeFlag bool) {
|
||||||
return c.closeFlag
|
c.mutex.RLock()
|
||||||
|
closeFlag = c.closeFlag
|
||||||
|
c.mutex.RUnlock()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// will block until connection close
|
// will block until connection close
|
||||||
|
Loading…
Reference in New Issue
Block a user