diff --git a/src/core/api.go b/src/core/api.go index 999acd4c..df39046c 100644 --- a/src/core/api.go +++ b/src/core/api.go @@ -103,17 +103,21 @@ func (c *Core) GetSessions() []Session { return sessions } +func (c *Core) Listen(u *url.URL, sintf string) (*TcpListener, error) { + return c.links.tcp.listenURL(u, sintf) +} + // ListenTCP starts a new TCP listener. The input URI should match that of the // "Listen" configuration item, e.g. // tcp://a.b.c.d:e -func (c *Core) ListenTCP(uri string, metric uint8) (*TcpListener, error) { +func (c *Core) xListenTCP(uri string, metric uint8) (*TcpListener, error) { return c.links.tcp.listen(uri, nil, metric) } // ListenTLS starts a new TLS listener. The input URI should match that of the // "Listen" configuration item, e.g. // tls://a.b.c.d:e -func (c *Core) ListenTLS(uri string, metric uint8) (*TcpListener, error) { +func (c *Core) xListenTLS(uri string, metric uint8) (*TcpListener, error) { return c.links.tcp.listen(uri, c.links.tcp.tls.forListener, metric) } @@ -226,10 +230,6 @@ func (c *Core) RemovePeer(addr string, sintf string) error { // socks://a.b.c.d:e/f.g.h.i:j // This does not add the peer to the peer list, so if the connection drops, the // peer will not be called again automatically. -func (c *Core) CallPeer(addr string, sintf string) error { - u, err := url.Parse(addr) - if err != nil { - return err - } +func (c *Core) CallPeer(u *url.URL, sintf string) error { return c.links.call(u, sintf) } diff --git a/src/core/core.go b/src/core/core.go index a30b2556..ba2b89b0 100644 --- a/src/core/core.go +++ b/src/core/core.go @@ -5,6 +5,7 @@ import ( "encoding/hex" "errors" "io/ioutil" + "net/url" "time" iw "github.com/Arceliar/ironwood/encrypted" @@ -69,7 +70,11 @@ func (c *Core) _addPeerLoop() { // Add peers from the Peers section for _, peer := range current.Peers { go func(peer string, intf string) { - if err := c.CallPeer(peer, intf); err != nil { + u, err := url.Parse(peer) + if err != nil { + c.log.Errorln("Failed to parse peer url:", peer, err) + } + if err := c.CallPeer(u, intf); err != nil { c.log.Errorln("Failed to add peer:", err) } }(peer, "") // TODO: this should be acted and not in a goroutine? @@ -79,7 +84,11 @@ func (c *Core) _addPeerLoop() { for intf, intfpeers := range current.InterfacePeers { for _, peer := range intfpeers { go func(peer string, intf string) { - if err := c.CallPeer(peer, intf); err != nil { + u, err := url.Parse(peer) + if err != nil { + c.log.Errorln("Failed to parse peer url:", peer, err) + } + if err := c.CallPeer(u, intf); err != nil { c.log.Errorln("Failed to add peer:", err) } }(peer, intf) // TODO: this should be acted and not in a goroutine? diff --git a/src/core/link.go b/src/core/link.go index 5993d767..f547c7ff 100644 --- a/src/core/link.go +++ b/src/core/link.go @@ -80,7 +80,6 @@ func (l *links) call(u *url.URL, sintf string) error { //if err != nil { // return fmt.Errorf("peer %s is not correctly formatted (%s)", uri, err) //} - pathtokens := strings.Split(strings.Trim(u.Path, "/"), "/") tcpOpts := tcpOptions{} if pubkeys, ok := u.Query()["ed25519"]; ok && len(pubkeys) > 0 { tcpOpts.pinnedEd25519Keys = make(map[keyArray]struct{}) @@ -106,6 +105,7 @@ func (l *links) call(u *url.URL, sintf string) error { tcpOpts.socksProxyAuth.User = u.User.Username() tcpOpts.socksProxyAuth.Password, _ = u.User.Password() } + pathtokens := strings.Split(strings.Trim(u.Path, "/"), "/") l.tcp.call(pathtokens[0], tcpOpts, sintf) case "tls": tcpOpts.upgrade = l.tcp.tls.forDialer diff --git a/src/core/tcp.go b/src/core/tcp.go index 588da698..66ac7af9 100644 --- a/src/core/tcp.go +++ b/src/core/tcp.go @@ -185,6 +185,32 @@ func (t *tcp) reconfigure() { */ } +func (t *tcp) listenURL(u *url.URL, sintf string) (*TcpListener, error) { + var metric uint8 + if ms := u.Query()["metric"]; len(ms) == 1 { + m64, _ := strconv.ParseUint(ms[0], 10, 8) + metric = uint8(m64) + } + var listener *TcpListener + var err error + hostport := u.Host // Used for tcp and tls + if len(sintf) != 0 { + host, port, err := net.SplitHostPort(hostport) + if err == nil { + hostport = fmt.Sprintf("[%s%%%s]:%s", host, sintf, port) + } + } + switch u.Scheme { + case "tcp": + listener, err = t.listen(hostport, nil, metric) + case "tls": + listener, err = t.listen(hostport, t.tls.forListener, metric) + default: + t.links.core.log.Errorln("Failed to add listener: listener", u.String(), "is not correctly formatted, ignoring") + } + return listener, err +} + func (t *tcp) listen(listenaddr string, upgrade *TcpUpgrade, metric uint8) (*TcpListener, error) { var err error diff --git a/src/multicast/multicast.go b/src/multicast/multicast.go index 56f46133..66edaa8e 100644 --- a/src/multicast/multicast.go +++ b/src/multicast/multicast.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "net" + "net/url" "regexp" "time" @@ -273,9 +274,13 @@ func (m *Multicast) _announce() { var info *listenerInfo if nfo, ok := m.listeners[iface.Name]; !ok || nfo.listener.Listener == nil { // No listener was found - let's create one - listenaddr := fmt.Sprintf("[%s%%%s]:%d", addrIP, iface.Name, m.listenPort) - var metric uint8 // TODO parse this from config - if li, err := m.core.ListenTCP(listenaddr, metric); err == nil { + var metric uint8 // TODO parse this from the config + urlString := fmt.Sprintf("tcp://[%s]:%d/?metric=%d", addrIP, m.listenPort, metric) + u, err := url.Parse(urlString) + if err != nil { + panic(err) + } + if li, err := m.core.Listen(u, iface.Name); err == nil { m.log.Debugln("Started multicasting on", iface.Name) // Store the listener so that we can stop it later if needed info = &listenerInfo{listener: li, time: time.Now()} @@ -353,7 +358,11 @@ func (m *Multicast) listen() { }) if _, ok := interfaces[from.Zone]; ok { addr.Zone = "" - if err := m.core.CallPeer("tcp://"+addr.String(), from.Zone); err != nil { + u, err := url.Parse("tcp://" + addr.String()) + if err != nil { + m.log.Debugln("Call from multicast failed, parse error:", addr.String(), err) + } + if err := m.core.CallPeer(u, from.Zone); err != nil { m.log.Debugln("Call from multicast failed:", err) } }