router by name

This commit is contained in:
XueBing 2016-12-18 12:55:16 +08:00
parent a06dc1eafa
commit 745efb4991
7 changed files with 109 additions and 92 deletions

View File

@ -17,14 +17,6 @@ mkdir ./packages
os_all='linux windows darwin' os_all='linux windows darwin'
arch_all='386 amd64 arm' 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 os in $os_all; do
for arch in $arch_all; do for arch in $arch_all; do
frp_dir_name="frp_${frp_version}_${os}_${arch}" frp_dir_name="frp_${frp_version}_${os}_${arch}"

View File

@ -152,11 +152,7 @@ func main() {
os.Exit(1) os.Exit(1)
} }
if server.VhostHttpRouters == nil { server.VhostHttpMuxer, err = vhost.NewHttpMuxer(vhostListener, 30*time.Second)
server.VhostHttpMuxer, err = vhost.NewHttpMuxer(vhostListener, 30*time.Second)
} else {
server.VhostHttpMuxer, err = vhost.NewHttpMuxerWithRouter(vhostListener, 30*time.Second, server.VhostHttpRouters)
}
if err != nil { if err != nil {
log.Error("Create vhost httpMuxer error, %v", err) log.Error("Create vhost httpMuxer error, %v", err)
} }

View File

@ -54,8 +54,6 @@ var (
VhostHttpsMuxer *vhost.HttpsMuxer VhostHttpsMuxer *vhost.HttpsMuxer
ProxyServers map[string]*ProxyServer = make(map[string]*ProxyServer) // all proxy servers info and resources ProxyServers map[string]*ProxyServer = make(map[string]*ProxyServer) // all proxy servers info and resources
ProxyServersMutex sync.RWMutex ProxyServersMutex sync.RWMutex
VhostHttpRouters *vhost.VhostRouters
) )
func LoadConf(confFile string) (err error) { func LoadConf(confFile string) (err error) {
@ -278,11 +276,7 @@ func loadProxyConf(confFile string) (proxyServers map[string]*ProxyServer, err e
//location //location
locStr, loc_ok := section["custom_location"] locStr, loc_ok := section["custom_location"]
if loc_ok { if loc_ok {
if VhostHttpRouters == nil {
VhostHttpRouters = vhost.NewVhostRouters()
}
proxyServer.Locations = strings.Split(locStr, ",") proxyServer.Locations = strings.Split(locStr, ",")
VhostHttpRouters.Add(proxyServer.Name, proxyServer.CustomDomains, proxyServer.Locations)
} }
} else if proxyServer.Type == "https" { } else if proxyServer.Type == "https" {
// for https // for https

View File

@ -130,19 +130,13 @@ func (p *ProxyServer) Start(c *conn.Conn) (err error) {
} }
p.listeners = append(p.listeners, l) p.listeners = append(p.listeners, l)
} else if p.Type == "http" { } else if p.Type == "http" {
for _, domain := range p.CustomDomains { ls := VhostHttpMuxer.ListenByRouter(p.Name, p.CustomDomains, p.Locations, p.HostHeaderRewrite)
l, err := VhostHttpMuxer.Listen(domain, p.HostHeaderRewrite) for _, l := range ls {
if err != nil {
return err
}
p.listeners = append(p.listeners, l) p.listeners = append(p.listeners, l)
} }
} else if p.Type == "https" { } else if p.Type == "https" {
for _, domain := range p.CustomDomains { for _, domain := range p.CustomDomains {
l, err := VhostHttpsMuxer.Listen(domain, p.HostHeaderRewrite) l := VhostHttpsMuxer.Listen(p.Name, domain, p.HostHeaderRewrite)
if err != nil {
return err
}
p.listeners = append(p.listeners, l) p.listeners = append(p.listeners, l)
} }
} }

View File

@ -52,12 +52,6 @@ func NewHttpMuxer(listener *conn.Listener, timeout time.Duration) (*HttpMuxer, e
return &HttpMuxer{mux}, err 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) { func HttpHostNameRewrite(c *conn.Conn, rewriteHost string) (_ net.Conn, err error) {
sc, rd := newShareConn(c.TcpConn) sc, rd := newShareConn(c.TcpConn)
var buff []byte var buff []byte

View File

@ -12,9 +12,10 @@ type VhostRouters struct {
} }
type VhostRouter struct { type VhostRouter struct {
Name string name string
Domain string domain string
Location string location string
listener *Listener
} }
func NewVhostRouters() *VhostRouters { func NewVhostRouters() *VhostRouters {
@ -33,45 +34,72 @@ func (a ByLocation) Swap(i, j int) {
a[i], a[j] = a[j], a[i] a[i], a[j] = a[j], a[i]
} }
func (a ByLocation) Less(i, j int) bool { 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() r.mutex.Lock()
defer r.mutex.Unlock() defer r.mutex.Unlock()
for _, domain := range domains { vrs, found := r.RouterByDomain[domain]
vrs, found := r.RouterByDomain[name] if !found {
if !found { vrs = make([]*VhostRouter, 0)
vrs = make([]*VhostRouter, 0) }
}
for _, loc := range locations { for _, loc := range locations {
vr := &VhostRouter{ vr := &VhostRouter{
Name: name, name: name,
Domain: domain, domain: domain,
Location: loc, 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() r.mutex.RLock()
defer r.mutex.RUnlock() 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] vrs, exist := r.RouterByDomain[domain]
if !exist { if !exist {
return return
} }
for _, vr := range vrs { //can't support load balance,will to do
if strings.HasPrefix(url, vr.Location+"/") { for _, vr = range vrs {
return vr.Name, true if strings.HasPrefix(url, vr.location) {
return vr, true
} }
} }

View File

@ -24,72 +24,89 @@ import (
"time" "time"
"github.com/fatedier/frp/src/utils/conn" "github.com/fatedier/frp/src/utils/conn"
"github.com/fatedier/frp/src/utils/log"
) )
type muxFunc func(*conn.Conn) (net.Conn, string, error) type muxFunc func(*conn.Conn) (net.Conn, string, error)
type hostRewriteFunc func(*conn.Conn, string) (net.Conn, error) type hostRewriteFunc func(*conn.Conn, string) (net.Conn, error)
type VhostMuxer struct { type VhostMuxer struct {
listener *conn.Listener listener *conn.Listener
timeout time.Duration timeout time.Duration
vhostFunc muxFunc vhostFunc muxFunc
rewriteFunc hostRewriteFunc rewriteFunc hostRewriteFunc
registryMap map[string]*Listener registryRouter *VhostRouters
routers *VhostRouters mutex sync.RWMutex
mutex sync.RWMutex
} }
func NewVhostMuxer(listener *conn.Listener, vhostFunc muxFunc, rewriteFunc hostRewriteFunc, timeout time.Duration) (mux *VhostMuxer, err error) { func NewVhostMuxer(listener *conn.Listener, vhostFunc muxFunc, rewriteFunc hostRewriteFunc, timeout time.Duration) (mux *VhostMuxer, err error) {
mux = &VhostMuxer{ mux = &VhostMuxer{
listener: listener, listener: listener,
timeout: timeout, timeout: timeout,
vhostFunc: vhostFunc, vhostFunc: vhostFunc,
rewriteFunc: rewriteFunc, rewriteFunc: rewriteFunc,
registryMap: make(map[string]*Listener), registryRouter: NewVhostRouters(),
} }
go mux.run() go mux.run()
return mux, nil 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 // 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() v.mutex.Lock()
defer v.mutex.Unlock() 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{ l = &Listener{
name: name, name: name,
domain: domain,
locations: locations,
rewriteHost: rewriteHost, rewriteHost: rewriteHost,
mux: v, mux: v,
accept: make(chan *conn.Conn), 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() v.mutex.RLock()
defer v.mutex.RUnlock() defer v.mutex.RUnlock()
if v.routers != nil { var frcname string
tmparray := strings.SplitN(name, ":", 2) vr, found := v.registryRouter.get(rname)
if len(tmparray) == 2 { if found {
newname, found := v.routers.getName(tmparray[0], tmparray[1]) frcname = vr.name
if found { } else {
name = newname 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) { log.Debug("get frcname %s for %s", frcname, rname)
v.mutex.Lock() return vr.listener, true
defer v.mutex.Unlock()
delete(v.registryMap, name)
} }
func (v *VhostMuxer) run() { func (v *VhostMuxer) run() {
@ -128,6 +145,8 @@ func (v *VhostMuxer) handle(c *conn.Conn) {
type Listener struct { type Listener struct {
name string name string
domain string
locations []string
rewriteHost string rewriteHost string
mux *VhostMuxer // for closing VhostMuxer mux *VhostMuxer // for closing VhostMuxer
accept chan *conn.Conn accept chan *conn.Conn
@ -152,7 +171,7 @@ func (l *Listener) Accept() (*conn.Conn, error) {
} }
func (l *Listener) Close() error { func (l *Listener) Close() error {
l.mux.unRegister(l.name) l.mux.registryRouter.del(l)
close(l.accept) close(l.accept)
return nil return nil
} }