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'
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}"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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