2019-06-05 15:08:55 +00:00
|
|
|
package tunnelhostnamemapper
|
|
|
|
|
|
|
|
import (
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
"github.com/cloudflare/cloudflared/h2mux"
|
|
|
|
"github.com/cloudflare/cloudflared/originservice"
|
2019-08-28 15:41:39 +00:00
|
|
|
"github.com/cloudflare/cloudflared/tunnelrpc/pogs"
|
2019-06-05 15:08:55 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// TunnelHostnameMapper maps TunnelHostname to an OriginService
|
|
|
|
type TunnelHostnameMapper struct {
|
|
|
|
sync.RWMutex
|
|
|
|
tunnelHostnameToOrigin map[h2mux.TunnelHostname]originservice.OriginService
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewTunnelHostnameMapper() *TunnelHostnameMapper {
|
|
|
|
return &TunnelHostnameMapper{
|
|
|
|
tunnelHostnameToOrigin: make(map[h2mux.TunnelHostname]originservice.OriginService),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get an OriginService given a TunnelHostname
|
|
|
|
func (om *TunnelHostnameMapper) Get(key h2mux.TunnelHostname) (originservice.OriginService, bool) {
|
|
|
|
om.RLock()
|
|
|
|
defer om.RUnlock()
|
|
|
|
originService, ok := om.tunnelHostnameToOrigin[key]
|
|
|
|
return originService, ok
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add a mapping. If there is already an OriginService with this key, shutdown the old origin service and replace it
|
|
|
|
// with the new one
|
|
|
|
func (om *TunnelHostnameMapper) Add(key h2mux.TunnelHostname, os originservice.OriginService) {
|
|
|
|
om.Lock()
|
|
|
|
defer om.Unlock()
|
|
|
|
if oldOS, ok := om.tunnelHostnameToOrigin[key]; ok {
|
|
|
|
oldOS.Shutdown()
|
|
|
|
}
|
|
|
|
om.tunnelHostnameToOrigin[key] = os
|
|
|
|
}
|
|
|
|
|
2019-08-28 15:41:39 +00:00
|
|
|
// Delete a mapping, and shutdown its OriginService
|
|
|
|
func (om *TunnelHostnameMapper) Delete(key h2mux.TunnelHostname) (keyFound bool) {
|
2019-06-05 15:08:55 +00:00
|
|
|
om.Lock()
|
|
|
|
defer om.Unlock()
|
2019-08-28 15:41:39 +00:00
|
|
|
if os, ok := om.tunnelHostnameToOrigin[key]; ok {
|
2019-06-05 15:08:55 +00:00
|
|
|
os.Shutdown()
|
|
|
|
delete(om.tunnelHostnameToOrigin, key)
|
2019-08-28 15:41:39 +00:00
|
|
|
return true
|
2019-06-05 15:08:55 +00:00
|
|
|
}
|
2019-08-28 15:41:39 +00:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// ToRemove finds all keys that should be removed from the TunnelHostnameMapper.
|
|
|
|
func (om *TunnelHostnameMapper) ToRemove(newConfigs []*pogs.ReverseProxyConfig) (toRemove []h2mux.TunnelHostname) {
|
|
|
|
om.Lock()
|
|
|
|
defer om.Unlock()
|
|
|
|
|
|
|
|
// Convert into a set, for O(1) lookups instead of O(n)
|
|
|
|
newConfigSet := toSet(newConfigs)
|
|
|
|
|
|
|
|
// If a config in `om` isn't in `newConfigs`, it must be removed.
|
|
|
|
for hostname := range om.tunnelHostnameToOrigin {
|
|
|
|
if _, ok := newConfigSet[hostname]; !ok {
|
|
|
|
toRemove = append(toRemove, hostname)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// ToAdd filters the given configs, keeping those that should be added to the TunnelHostnameMapper.
|
|
|
|
func (om *TunnelHostnameMapper) ToAdd(newConfigs []*pogs.ReverseProxyConfig) (toAdd []*pogs.ReverseProxyConfig) {
|
|
|
|
om.Lock()
|
|
|
|
defer om.Unlock()
|
|
|
|
|
|
|
|
// If a config in `newConfigs` isn't in `om`, it must be added.
|
|
|
|
for _, config := range newConfigs {
|
|
|
|
if _, ok := om.tunnelHostnameToOrigin[config.TunnelHostname]; !ok {
|
|
|
|
toAdd = append(toAdd, config)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func toSet(configs []*pogs.ReverseProxyConfig) map[h2mux.TunnelHostname]*pogs.ReverseProxyConfig {
|
|
|
|
m := make(map[h2mux.TunnelHostname]*pogs.ReverseProxyConfig)
|
|
|
|
for _, config := range configs {
|
|
|
|
m[config.TunnelHostname] = config
|
|
|
|
}
|
|
|
|
return m
|
2019-06-05 15:08:55 +00:00
|
|
|
}
|