From 12d88eac238f2f7601aba0bd916165a5892c8efe Mon Sep 17 00:00:00 2001 From: Alex Bligh Date: Thu, 9 Apr 2015 12:27:27 +0100 Subject: [PATCH] Add options to set ports on weaver command line This commit adds two command line options, intended to allow multiple instances of weave to run without container separation between them. * -port=PORT makes weave bind to port PORT (an integer). Without the option, the default value (6783) is used. * -httpaddr=ADDRESS makes weave bind its control interface to a different address. For instance "127.0.0.1:6784" can be used to bind to localhost only. An absent address element makes it bind to all interfaces. ":6784" is the default. An empty string can be used to disable the control interface. Signed-off-by: Alex Bligh --- router/connection_maker.go | 28 +++++++++++++++------------- router/gossip_test.go | 2 +- router/local_peer.go | 2 +- router/router.go | 24 ++++++++++++++++++------ router/udp_sender.go | 2 +- router/utils.go | 10 ---------- weaver/main.go | 21 +++++++++++++-------- 7 files changed, 49 insertions(+), 40 deletions(-) diff --git a/router/connection_maker.go b/router/connection_maker.go index 6a1e7bf2d6..7860a89d2e 100644 --- a/router/connection_maker.go +++ b/router/connection_maker.go @@ -15,11 +15,12 @@ const ( ) type ConnectionMaker struct { - ourself *LocalPeer - peers *Peers - targets map[string]*Target - cmdLineAddress map[string]struct{} - actionChan chan<- ConnectionMakerAction + ourself *LocalPeer + peers *Peers + normalisePeerAddr func(string) string + targets map[string]*Target + cmdLineAddress map[string]struct{} + actionChan chan<- ConnectionMakerAction } // Information about an address where we may find a peer @@ -31,12 +32,13 @@ type Target struct { type ConnectionMakerAction func() bool -func NewConnectionMaker(ourself *LocalPeer, peers *Peers) *ConnectionMaker { +func NewConnectionMaker(ourself *LocalPeer, peers *Peers, normalisePeerAddr func(string) string) *ConnectionMaker { return &ConnectionMaker{ - ourself: ourself, - peers: peers, - cmdLineAddress: make(map[string]struct{}), - targets: make(map[string]*Target)} + ourself: ourself, + peers: peers, + normalisePeerAddr: normalisePeerAddr, + cmdLineAddress: make(map[string]struct{}), + targets: make(map[string]*Target)} } func (cm *ConnectionMaker) Start() { @@ -47,7 +49,7 @@ func (cm *ConnectionMaker) Start() { func (cm *ConnectionMaker) InitiateConnection(address string) { cm.actionChan <- func() bool { - cm.cmdLineAddress[NormalisePeerAddr(address)] = void + cm.cmdLineAddress[cm.normalisePeerAddr(address)] = void if target, found := cm.targets[address]; found { target.tryAfter, target.tryInterval = tryImmediately() } @@ -57,7 +59,7 @@ func (cm *ConnectionMaker) InitiateConnection(address string) { func (cm *ConnectionMaker) ForgetConnection(address string) { cm.actionChan <- func() bool { - delete(cm.cmdLineAddress, NormalisePeerAddr(address)) + delete(cm.cmdLineAddress, cm.normalisePeerAddr(address)) return false } } @@ -150,7 +152,7 @@ func (cm *ConnectionMaker) checkStateAndAttemptConnections() time.Duration { addTarget(address) } if host, _, err := net.SplitHostPort(address); err == nil { - addTarget(NormalisePeerAddr(host)) + addTarget(cm.normalisePeerAddr(host)) } } }) diff --git a/router/gossip_test.go b/router/gossip_test.go index 6a3d6837a4..371c77c462 100644 --- a/router/gossip_test.go +++ b/router/gossip_test.go @@ -17,7 +17,7 @@ type mockChannelConnection struct { // Construct a "passive" Router, i.e. without any goroutines, except // for Routes and GossipSenders. func NewTestRouter(name PeerName) *Router { - router := NewRouter(nil, name, "", nil, 10, 1024, nil) + router := NewRouter(nil, name, "", nil, 10, 1024, nil, Port) // need to create a dummy channel otherwise tests hang on nil // channels when the Router invoked ConnectionMaker.Refresh router.ConnectionMaker.actionChan = make(chan ConnectionMakerAction, ChannelSize) diff --git a/router/local_peer.go b/router/local_peer.go index 7346c5943d..0f2f6f7893 100644 --- a/router/local_peer.go +++ b/router/local_peer.go @@ -94,7 +94,7 @@ func (peer *LocalPeer) CreateConnection(peerAddr string, acceptNewPeer bool) err return err } // We're dialing the remote so that means connections will come from random ports - addrStr := NormalisePeerAddr(peerAddr) + addrStr := peer.Router.NormalisePeerAddr(peerAddr) tcpAddr, tcpErr := net.ResolveTCPAddr("tcp4", addrStr) udpAddr, udpErr := net.ResolveUDPAddr("udp4", addrStr) if tcpErr != nil || udpErr != nil { diff --git a/router/router.go b/router/router.go index 2eb9af36df..289307a6c5 100644 --- a/router/router.go +++ b/router/router.go @@ -31,6 +31,7 @@ type Router struct { ConnLimit int BufSz int LogFrame func(string, []byte, *layers.Ethernet) + Port int } type PacketSource interface { @@ -46,14 +47,15 @@ type PacketSourceSink interface { PacketSink } -func NewRouter(iface *net.Interface, name PeerName, nickName string, password []byte, connLimit int, bufSz int, logFrame func(string, []byte, *layers.Ethernet)) *Router { +func NewRouter(iface *net.Interface, name PeerName, nickName string, password []byte, connLimit int, bufSz int, logFrame func(string, []byte, *layers.Ethernet), port int) *Router { router := &Router{ Iface: iface, GossipChannels: make(map[uint32]*GossipChannel), Password: password, ConnLimit: connLimit, BufSz: bufSz, - LogFrame: logFrame} + LogFrame: logFrame, + Port: port} onMacExpiry := func(mac net.HardwareAddr, peer *Peer) { log.Println("Expired MAC", mac, "at", peer.FullName()) } @@ -66,7 +68,7 @@ func NewRouter(iface *net.Interface, name PeerName, nickName string, password [] router.Peers = NewPeers(router.Ourself.Peer, onPeerGC) router.Peers.FetchWithDefault(router.Ourself.Peer) router.Routes = NewRoutes(router.Ourself.Peer, router.Peers) - router.ConnectionMaker = NewConnectionMaker(router.Ourself, router.Peers) + router.ConnectionMaker = NewConnectionMaker(router.Ourself, router.Peers, router.NormalisePeerAddr) router.TopologyGossip = router.NewGossip("topology", router) return router } @@ -86,8 +88,8 @@ func (router *Router) Start() { router.Macs.Start() router.Routes.Start() router.ConnectionMaker.Start() - router.UDPListener = router.listenUDP(Port, po) - router.listenTCP(Port) + router.UDPListener = router.listenUDP(router.Port, po) + router.listenTCP(router.Port) if pio != nil { router.sniff(pio) } @@ -198,7 +200,7 @@ func (router *Router) listenTCP(localPort int) { func (router *Router) acceptTCP(tcpConn *net.TCPConn) { // someone else is dialing us, so our udp sender is the conn - // on Port and we wait for them to send us something on UDP to + // on router.Port and we wait for them to send us something on UDP to // start. remoteAddrStr := tcpConn.RemoteAddr().String() log.Printf("->[%s] connection accepted\n", remoteAddrStr) @@ -416,3 +418,13 @@ func (router *Router) applyTopologyUpdate(update []byte) (PeerNameSet, PeerNameS } return origUpdate, newUpdate, nil } + +// given an address like '1.2.3.4:567', return the address if it has a port, +// otherwise return the address with the default port number for the router +func (router *Router) NormalisePeerAddr(peerAddr string) string { + _, _, err := net.SplitHostPort(peerAddr) + if err == nil { + return peerAddr + } + return fmt.Sprintf("%s:%d", peerAddr, router.Port) +} diff --git a/router/udp_sender.go b/router/udp_sender.go index 26928f3c09..9e91ee0b21 100644 --- a/router/udp_sender.go +++ b/router/udp_sender.go @@ -48,7 +48,7 @@ func NewRawUDPSender(conn *LocalConnection) (*RawUDPSender, error) { if err != nil { return nil, err } - udpHeader := &layers.UDP{SrcPort: layers.UDPPort(Port)} + udpHeader := &layers.UDP{SrcPort: layers.UDPPort(conn.Router.Port)} ipBuf := gopacket.NewSerializeBuffer() opts := gopacket.SerializeOptions{ FixLengths: true, diff --git a/router/utils.go b/router/utils.go index 1545b23d86..9cf4f1bd51 100644 --- a/router/utils.go +++ b/router/utils.go @@ -117,13 +117,3 @@ func (lop ListOfPeers) Swap(i, j int) { func (lop ListOfPeers) Less(i, j int) bool { return lop[i].Name < lop[j].Name } - -// given an address like '1.2.3.4:567', return the address if it has a port, -// otherwise return the address with weave's standard port number -func NormalisePeerAddr(peerAddr string) string { - _, _, err := net.SplitHostPort(peerAddr) - if err == nil { - return peerAddr - } - return fmt.Sprintf("%s:%d", peerAddr, Port) -} diff --git a/weaver/main.go b/weaver/main.go index 469b713cfd..eb8fc476b0 100644 --- a/weaver/main.go +++ b/weaver/main.go @@ -46,6 +46,8 @@ func main() { peers []string connLimit int bufSz int + port int + httpAddr string ) flag.BoolVar(&justVersion, "version", false, "print version and exit") @@ -58,6 +60,8 @@ func main() { flag.StringVar(&prof, "profile", "", "enable profiling and write profiles to given path") flag.IntVar(&connLimit, "connlimit", 30, "connection limit (defaults to 30, set to 0 for unlimited)") flag.IntVar(&bufSz, "bufsz", 8, "capture buffer size in MB (defaults to 8MB)") + flag.IntVar(&port, "port", weave.Port, fmt.Sprintf("router port (defaults to %d)", weave.Port)) + flag.StringVar(&httpAddr, "httpaddr", fmt.Sprintf(":%d", weave.HTTPPort), fmt.Sprintf("address to bind HTTP interface to (defaults to :%d, set to \"\" to disable)", weave.HTTPPort)) flag.Parse() peers = flag.Args() @@ -121,11 +125,13 @@ func main() { defer profile.Start(&p).Stop() } - router := weave.NewRouter(iface, ourName, nickName, pwSlice, connLimit, bufSz*1024*1024, logFrameFunc(debug)) + router := weave.NewRouter(iface, ourName, nickName, pwSlice, connLimit, bufSz*1024*1024, logFrameFunc(debug), port) log.Println("Our name is", router.Ourself.FullName()) router.Start() initiateConnections(router, peers) - go handleHTTP(router) + if httpAddr != "" { + go handleHTTP(router, httpAddr) + } handleSignals(router) } @@ -145,7 +151,7 @@ func logFrameFunc(debug bool) func(string, []byte, *layers.Ethernet) { func initiateConnections(router *weave.Router, peers []string) { for _, peer := range peers { - if addr, err := net.ResolveTCPAddr("tcp4", weave.NormalisePeerAddr(peer)); err == nil { + if addr, err := net.ResolveTCPAddr("tcp4", router.NormalisePeerAddr(peer)); err == nil { router.ConnectionMaker.InitiateConnection(addr.String()) } else { log.Fatal(err) @@ -153,7 +159,7 @@ func initiateConnections(router *weave.Router, peers []string) { } } -func handleHTTP(router *weave.Router) { +func handleHTTP(router *weave.Router, httpAddr string) { encryption := "off" if router.UsingPassword() { encryption = "on" @@ -174,7 +180,7 @@ func handleHTTP(router *weave.Router) { muxRouter.Methods("POST").Path("/connect").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { peer := r.FormValue("peer") - if addr, err := net.ResolveTCPAddr("tcp4", weave.NormalisePeerAddr(peer)); err == nil { + if addr, err := net.ResolveTCPAddr("tcp4", router.NormalisePeerAddr(peer)); err == nil { router.ConnectionMaker.InitiateConnection(addr.String()) } else { http.Error(w, fmt.Sprint("invalid peer address: ", err), http.StatusBadRequest) @@ -183,7 +189,7 @@ func handleHTTP(router *weave.Router) { muxRouter.Methods("POST").Path("/forget").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { peer := r.FormValue("peer") - if addr, err := net.ResolveTCPAddr("tcp4", weave.NormalisePeerAddr(peer)); err == nil { + if addr, err := net.ResolveTCPAddr("tcp4", router.NormalisePeerAddr(peer)); err == nil { router.ConnectionMaker.ForgetConnection(addr.String()) } else { http.Error(w, fmt.Sprint("invalid peer address: ", err), http.StatusBadRequest) @@ -192,8 +198,7 @@ func handleHTTP(router *weave.Router) { http.Handle("/", muxRouter) - address := fmt.Sprintf(":%d", weave.HTTPPort) - err := http.ListenAndServe(address, nil) + err := http.ListenAndServe(httpAddr, nil) if err != nil { log.Fatal("Unable to create http listener: ", err) }