Tidy up address handling

This commit is contained in:
Matt Joiner 2014-11-16 13:16:26 -06:00
parent 1460e835c2
commit 86de81fba8
1 changed files with 49 additions and 59 deletions

View File

@ -133,18 +133,20 @@ type Client struct {
dataWaits map[*torrent][]dataWait dataWaits map[*torrent][]dataWait
} }
func (me *Client) ListenAddr() net.Addr { func (me *Client) ListenAddr() (addr net.Addr) {
return me.listener.Addr() for _, l := range me.listeners {
if addr != nil && l.Addr().String() != addr.String() {
panic("listeners exist on different addresses")
}
addr = l.Addr()
}
return
} }
func (cl *Client) WriteStatus(w io.Writer) { func (cl *Client) WriteStatus(w io.Writer) {
cl.mu.LevelLock(1) cl.mu.LevelLock(1)
defer cl.mu.Unlock() defer cl.mu.Unlock()
if cl.listener != nil { fmt.Fprintf(w, "Listening on %s\n", cl.ListenAddr())
fmt.Fprintf(w, "Listening on %s\n", cl.listener.Addr())
} else {
fmt.Fprintf(w, "No listening torrent port!\n")
}
fmt.Fprintf(w, "Peer ID: %q\n", cl.peerID) fmt.Fprintf(w, "Peer ID: %q\n", cl.peerID)
fmt.Fprintf(w, "Half open outgoing connections: %d\n", cl.halfOpen) fmt.Fprintf(w, "Half open outgoing connections: %d\n", cl.halfOpen)
fmt.Fprintf(w, "Handshaking: %d\n", cl.handshaking) fmt.Fprintf(w, "Handshaking: %d\n", cl.handshaking)
@ -386,36 +388,31 @@ func (me *Client) initiateConn(peer Peer, torrent *torrent) {
}() }()
} }
// The port number for incoming peer connections. 0 if the client isn't
// listening.
func (cl *Client) incomingPeerPort() int { func (cl *Client) incomingPeerPort() int {
if cl.listener == nil { listenAddr := cl.ListenAddr()
if listenAddr == nil {
return 0 return 0
} }
_, p, err := net.SplitHostPort(cl.listener.Addr().String()) return addrPort(listenAddr)
if err != nil {
panic(err)
}
var i int
_, err = fmt.Sscanf(p, "%d", &i)
if err != nil {
panic(err)
}
return i
} }
// Convert a net.Addr to its compact IP representation. Either 4 or 16 bytes per "yourip" field of http://www.bittorrent.org/beps/bep_0010.html. // Convert a net.Addr to its compact IP representation. Either 4 or 16 bytes
// per "yourip" field of http://www.bittorrent.org/beps/bep_0010.html.
func addrCompactIP(addr net.Addr) (string, error) { func addrCompactIP(addr net.Addr) (string, error) {
switch typed := addr.(type) { host, _, err := net.SplitHostPort(addr.String())
case *net.TCPAddr: if err != nil {
if v4 := typed.IP.To4(); v4 != nil { return "", err
}
ip := net.ParseIP(host)
if v4 := ip.To4(); v4 != nil {
if len(v4) != 4 { if len(v4) != 4 {
panic(v4) panic(v4)
} }
return string(v4), nil return string(v4), nil
} }
return string(typed.IP.To16()), nil return string(ip.To16()), nil
default:
return "", fmt.Errorf("unhandled type: %T", addr)
}
} }
func handshakeWriter(w io.WriteCloser, bb <-chan []byte, done chan<- error) { func handshakeWriter(w io.WriteCloser, bb <-chan []byte, done chan<- error) {
@ -757,6 +754,19 @@ type peerExchangeMessage struct {
Dropped []tracker.Peer `bencode:"dropped"` Dropped []tracker.Peer `bencode:"dropped"`
} }
// Extracts the port as an integer from an address string.
func addrPort(addr net.Addr) int {
_, port, err := net.SplitHostPort(addr.String())
if err != nil {
panic(err)
}
i64, err := strconv.ParseInt(port, 0, 0)
if err != nil {
panic(err)
}
return int(i64)
}
// Processes incoming bittorrent messages. The client lock is held upon entry // Processes incoming bittorrent messages. The client lock is held upon entry
// and exit. // and exit.
func (me *Client) connectionLoop(t *torrent, c *connection) error { func (me *Client) connectionLoop(t *torrent, c *connection) error {
@ -960,17 +970,14 @@ func (me *Client) connectionLoop(t *torrent, c *connection) error {
if me.dHT == nil { if me.dHT == nil {
break break
} }
addr, _ := c.Socket.RemoteAddr().(*net.TCPAddr) pingAddr, err := net.ResolveUDPAddr("", c.Socket.RemoteAddr().String())
_, err = me.dHT.Ping(&net.UDPAddr{ if err != nil {
IP: addr.IP, panic(err)
Zone: addr.Zone,
Port: func() int {
if msg.Port == 0 {
return addr.Port
} }
return int(msg.Port) if msg.Port != 0 {
}(), pingAddr.Port = int(msg.Port)
}) }
_, err = me.dHT.Ping(pingAddr)
default: default:
err = fmt.Errorf("received unknown message type: %#v", msg.Type) err = fmt.Errorf("received unknown message type: %#v", msg.Type)
} }
@ -1223,23 +1230,6 @@ func (me *Client) AddTorrentFromFile(name string) (err error) {
return me.AddTorrent(mi) return me.AddTorrent(mi)
} }
func (cl *Client) listenerAnnouncePort() (port int16) {
l := cl.listener
if l == nil {
return
}
addr := l.Addr()
switch data := addr.(type) {
case *net.TCPAddr:
return int16(data.Port)
case *net.UDPAddr:
return int16(data.Port)
default:
log.Printf("unknown listener addr type: %T", addr)
}
return
}
func (cl *Client) announceTorrentDHT(t *torrent) { func (cl *Client) announceTorrentDHT(t *torrent) {
for { for {
ps, err := cl.dHT.GetPeers(string(t.InfoHash[:])) ps, err := cl.dHT.GetPeers(string(t.InfoHash[:]))
@ -1285,7 +1275,7 @@ func (cl *Client) announceTorrent(t *torrent) {
req := tracker.AnnounceRequest{ req := tracker.AnnounceRequest{
Event: tracker.Started, Event: tracker.Started,
NumWant: -1, NumWant: -1,
Port: cl.listenerAnnouncePort(), Port: int16(cl.incomingPeerPort()),
PeerId: cl.peerID, PeerId: cl.peerID,
InfoHash: t.InfoHash, InfoHash: t.InfoHash,
} }