From 745efb4991c7d6b4071847e82cfb3070cdc73bc0 Mon Sep 17 00:00:00 2001 From: XueBing Date: Sun, 18 Dec 2016 12:55:16 +0800 Subject: [PATCH] router by name --- cross_compiles_package.sh | 8 ---- src/cmd/frps/main.go | 6 +-- src/models/server/config.go | 6 --- src/models/server/server.go | 12 ++--- src/utils/vhost/http.go | 6 --- src/utils/vhost/router.go | 74 ++++++++++++++++++++---------- src/utils/vhost/vhost.go | 89 ++++++++++++++++++++++--------------- 7 files changed, 109 insertions(+), 92 deletions(-) diff --git a/cross_compiles_package.sh b/cross_compiles_package.sh index 3d1aa3d0..5cbe6a67 100755 --- a/cross_compiles_package.sh +++ b/cross_compiles_package.sh @@ -17,14 +17,6 @@ mkdir ./packages os_all='linux windows darwin' arch_all='386 amd64 arm' -if [ $1 ];then - os_all=$1 -fi - -if [ $2 ];then - arch_all=$2 -fi - for os in $os_all; do for arch in $arch_all; do frp_dir_name="frp_${frp_version}_${os}_${arch}" diff --git a/src/cmd/frps/main.go b/src/cmd/frps/main.go index af6a7161..a68947a3 100644 --- a/src/cmd/frps/main.go +++ b/src/cmd/frps/main.go @@ -152,11 +152,7 @@ func main() { os.Exit(1) } - if server.VhostHttpRouters == nil { - server.VhostHttpMuxer, err = vhost.NewHttpMuxer(vhostListener, 30*time.Second) - } else { - server.VhostHttpMuxer, err = vhost.NewHttpMuxerWithRouter(vhostListener, 30*time.Second, server.VhostHttpRouters) - } + server.VhostHttpMuxer, err = vhost.NewHttpMuxer(vhostListener, 30*time.Second) if err != nil { log.Error("Create vhost httpMuxer error, %v", err) } diff --git a/src/models/server/config.go b/src/models/server/config.go index 7b0c8da1..91d4009e 100644 --- a/src/models/server/config.go +++ b/src/models/server/config.go @@ -54,8 +54,6 @@ var ( VhostHttpsMuxer *vhost.HttpsMuxer ProxyServers map[string]*ProxyServer = make(map[string]*ProxyServer) // all proxy servers info and resources ProxyServersMutex sync.RWMutex - - VhostHttpRouters *vhost.VhostRouters ) func LoadConf(confFile string) (err error) { @@ -278,11 +276,7 @@ func loadProxyConf(confFile string) (proxyServers map[string]*ProxyServer, err e //location locStr, loc_ok := section["custom_location"] if loc_ok { - if VhostHttpRouters == nil { - VhostHttpRouters = vhost.NewVhostRouters() - } proxyServer.Locations = strings.Split(locStr, ",") - VhostHttpRouters.Add(proxyServer.Name, proxyServer.CustomDomains, proxyServer.Locations) } } else if proxyServer.Type == "https" { // for https diff --git a/src/models/server/server.go b/src/models/server/server.go index a5e3aa70..993bd816 100644 --- a/src/models/server/server.go +++ b/src/models/server/server.go @@ -130,19 +130,13 @@ func (p *ProxyServer) Start(c *conn.Conn) (err error) { } p.listeners = append(p.listeners, l) } else if p.Type == "http" { - for _, domain := range p.CustomDomains { - l, err := VhostHttpMuxer.Listen(domain, p.HostHeaderRewrite) - if err != nil { - return err - } + ls := VhostHttpMuxer.ListenByRouter(p.Name, p.CustomDomains, p.Locations, p.HostHeaderRewrite) + for _, l := range ls { p.listeners = append(p.listeners, l) } } else if p.Type == "https" { for _, domain := range p.CustomDomains { - l, err := VhostHttpsMuxer.Listen(domain, p.HostHeaderRewrite) - if err != nil { - return err - } + l := VhostHttpsMuxer.Listen(p.Name, domain, p.HostHeaderRewrite) p.listeners = append(p.listeners, l) } } diff --git a/src/utils/vhost/http.go b/src/utils/vhost/http.go index 2ac5da1a..2a282f06 100644 --- a/src/utils/vhost/http.go +++ b/src/utils/vhost/http.go @@ -52,12 +52,6 @@ func NewHttpMuxer(listener *conn.Listener, timeout time.Duration) (*HttpMuxer, e return &HttpMuxer{mux}, err } -func NewHttpMuxerWithRouter(listener *conn.Listener, timeout time.Duration, r *VhostRouters) (*HttpMuxer, error) { - mux, err := NewVhostMuxer(listener, GetHttpHostname, HttpHostNameRewrite, timeout) - mux.routers = r - return &HttpMuxer{mux}, err -} - func HttpHostNameRewrite(c *conn.Conn, rewriteHost string) (_ net.Conn, err error) { sc, rd := newShareConn(c.TcpConn) var buff []byte diff --git a/src/utils/vhost/router.go b/src/utils/vhost/router.go index a81d6eb8..d4735df1 100644 --- a/src/utils/vhost/router.go +++ b/src/utils/vhost/router.go @@ -12,9 +12,10 @@ type VhostRouters struct { } type VhostRouter struct { - Name string - Domain string - Location string + name string + domain string + location string + listener *Listener } func NewVhostRouters() *VhostRouters { @@ -33,45 +34,72 @@ func (a ByLocation) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func (a ByLocation) Less(i, j int) bool { - return strings.Compare(a[i].Location, a[j].Location) < 0 + return strings.Compare(a[i].location, a[j].location) < 0 } -func (r *VhostRouters) Add(name string, domains, locations []string) { +func (r *VhostRouters) add(name, domain string, locations []string, l *Listener) { r.mutex.Lock() defer r.mutex.Unlock() - for _, domain := range domains { - vrs, found := r.RouterByDomain[name] - if !found { - vrs = make([]*VhostRouter, 0) - } + vrs, found := r.RouterByDomain[domain] + if !found { + vrs = make([]*VhostRouter, 0) + } - for _, loc := range locations { - vr := &VhostRouter{ - Name: name, - Domain: domain, - Location: loc, + for _, loc := range locations { + vr := &VhostRouter{ + name: name, + domain: domain, + location: loc, + listener: l, + } + vrs = append(vrs, vr) + } + + sort.Reverse(ByLocation(vrs)) + r.RouterByDomain[domain] = vrs +} + +func (r *VhostRouters) del(l *Listener) { + r.mutex.Lock() + defer r.mutex.Unlock() + + vrs, found := r.RouterByDomain[l.domain] + if !found { + return + } + + for i, vr := range vrs { + if vr.listener == l { + if len(vrs) > i+1 { + r.RouterByDomain[l.domain] = append(vrs[:i], vrs[i+1:]...) + } else { + r.RouterByDomain[l.domain] = vrs[:i] } - vrs = append(vrs, vr) } - - sort_vrs := sort.Reverse(ByLocation(vrs)) - r.RouterByDomain[name] = sort_vrs.(ByLocation) } } -func (r *VhostRouters) getName(domain, url string) (name string, exist bool) { +func (r *VhostRouters) get(rname string) (vr *VhostRouter, exist bool) { r.mutex.RLock() defer r.mutex.RUnlock() + var domain, url string + tmparray := strings.SplitN(rname, ":", 2) + if len(tmparray) == 2 { + domain = tmparray[0] + url = tmparray[1] + } + vrs, exist := r.RouterByDomain[domain] if !exist { return } - for _, vr := range vrs { - if strings.HasPrefix(url, vr.Location+"/") { - return vr.Name, true + //can't support load balance,will to do + for _, vr = range vrs { + if strings.HasPrefix(url, vr.location) { + return vr, true } } diff --git a/src/utils/vhost/vhost.go b/src/utils/vhost/vhost.go index f7849ac1..ff253f16 100644 --- a/src/utils/vhost/vhost.go +++ b/src/utils/vhost/vhost.go @@ -24,72 +24,89 @@ import ( "time" "github.com/fatedier/frp/src/utils/conn" + "github.com/fatedier/frp/src/utils/log" ) type muxFunc func(*conn.Conn) (net.Conn, string, error) type hostRewriteFunc func(*conn.Conn, string) (net.Conn, error) type VhostMuxer struct { - listener *conn.Listener - timeout time.Duration - vhostFunc muxFunc - rewriteFunc hostRewriteFunc - registryMap map[string]*Listener - routers *VhostRouters - mutex sync.RWMutex + listener *conn.Listener + timeout time.Duration + vhostFunc muxFunc + rewriteFunc hostRewriteFunc + registryRouter *VhostRouters + mutex sync.RWMutex } func NewVhostMuxer(listener *conn.Listener, vhostFunc muxFunc, rewriteFunc hostRewriteFunc, timeout time.Duration) (mux *VhostMuxer, err error) { mux = &VhostMuxer{ - listener: listener, - timeout: timeout, - vhostFunc: vhostFunc, - rewriteFunc: rewriteFunc, - registryMap: make(map[string]*Listener), + listener: listener, + timeout: timeout, + vhostFunc: vhostFunc, + rewriteFunc: rewriteFunc, + registryRouter: NewVhostRouters(), } go mux.run() return mux, nil } // listen for a new domain name, if rewriteHost is not empty and rewriteFunc is not nil, then rewrite the host header to rewriteHost -func (v *VhostMuxer) Listen(name string, rewriteHost string) (l *Listener, err error) { +func (v *VhostMuxer) Listen(name, domain string, rewriteHost string) (l *Listener) { v.mutex.Lock() defer v.mutex.Unlock() - if _, exist := v.registryMap[name]; exist { - return nil, fmt.Errorf("domain name %s is already bound", name) - } + + locations := []string{""} l = &Listener{ name: name, + domain: domain, + locations: locations, rewriteHost: rewriteHost, mux: v, accept: make(chan *conn.Conn), } - v.registryMap[name] = l - return l, nil + + v.registryRouter.add(name, domain, locations, l) + return l } -func (v *VhostMuxer) getListener(name string) (l *Listener, exist bool) { +func (v *VhostMuxer) ListenByRouter(name string, domains []string, locations []string, rewriteHost string) (ls []*Listener) { + v.mutex.Lock() + defer v.mutex.Unlock() + + ls = make([]*Listener, 0) + for _, domain := range domains { + l := &Listener{ + name: name, + domain: domain, + locations: locations, + rewriteHost: rewriteHost, + mux: v, + accept: make(chan *conn.Conn), + } + v.registryRouter.add(name, domain, locations, l) + ls = append(ls) + } + + return ls +} + +func (v *VhostMuxer) getListener(rname string) (l *Listener, exist bool) { v.mutex.RLock() defer v.mutex.RUnlock() - if v.routers != nil { - tmparray := strings.SplitN(name, ":", 2) - if len(tmparray) == 2 { - newname, found := v.routers.getName(tmparray[0], tmparray[1]) - if found { - name = newname - } - } + var frcname string + vr, found := v.registryRouter.get(rname) + if found { + frcname = vr.name + } else { + log.Warn("can't found the router for %s", rname) + return } - l, exist = v.registryMap[name] - return l, exist -} -func (v *VhostMuxer) unRegister(name string) { - v.mutex.Lock() - defer v.mutex.Unlock() - delete(v.registryMap, name) + log.Debug("get frcname %s for %s", frcname, rname) + return vr.listener, true } func (v *VhostMuxer) run() { @@ -128,6 +145,8 @@ func (v *VhostMuxer) handle(c *conn.Conn) { type Listener struct { name string + domain string + locations []string rewriteHost string mux *VhostMuxer // for closing VhostMuxer accept chan *conn.Conn @@ -152,7 +171,7 @@ func (l *Listener) Accept() (*conn.Conn, error) { } func (l *Listener) Close() error { - l.mux.unRegister(l.name) + l.mux.registryRouter.del(l) close(l.accept) return nil }