conn.go 1.78 KB
Newer Older
1 2 3
package swarm

import (
4
	"fmt"
5 6
	"net"

7 8 9 10
	peer "github.com/jbenet/go-ipfs/peer"
	u "github.com/jbenet/go-ipfs/util"
	msgio "github.com/jbenet/go-msgio"
	ma "github.com/jbenet/go-multiaddr"
11 12
)

Juan Batiz-Benet's avatar
go lint  
Juan Batiz-Benet committed
13
// ChanBuffer is the size of the buffer in the Conn Chan
14 15
const ChanBuffer = 10

16 17
const MaxMessageSize = 1 << 19

Juan Batiz-Benet's avatar
go lint  
Juan Batiz-Benet committed
18
// Conn represents a connection to another Peer (IPFS Node).
19
type Conn struct {
20 21 22
	Peer *peer.Peer
	Addr *ma.Multiaddr
	Conn net.Conn
23

24 25 26
	Closed   chan bool
	Outgoing *msgio.Chan
	Incoming *msgio.Chan
27 28
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
29
// ConnMap maps Keys (Peer.IDs) to Connections.
30
type ConnMap map[u.Key]*Conn
31

Juan Batiz-Benet's avatar
go lint  
Juan Batiz-Benet committed
32 33
// Dial connects to a particular peer, over a given network
// Example: Dial("udp", peer)
34
func Dial(network string, peer *peer.Peer) (*Conn, error) {
35 36 37 38
	addr := peer.NetAddress(network)
	if addr == nil {
		return nil, fmt.Errorf("No address for network %s", network)
	}
39

40 41 42 43
	network, host, err := addr.DialArgs()
	if err != nil {
		return nil, err
	}
44

45 46 47 48
	nconn, err := net.Dial(network, host)
	if err != nil {
		return nil, err
	}
49

50 51 52 53
	conn := &Conn{
		Peer: peer,
		Addr: addr,
		Conn: nconn,
54
	}
55

56 57 58 59 60 61 62 63
	newConnChans(conn)
	return conn, nil
}

// Construct new channels for given Conn.
func newConnChans(c *Conn) error {
	if c.Outgoing != nil || c.Incoming != nil {
		return fmt.Errorf("Conn already initialized")
64
	}
65

66 67 68
	c.Outgoing = msgio.NewChan(10)
	c.Incoming = msgio.NewChan(10)
	c.Closed = make(chan bool, 1)
69

70
	go c.Outgoing.WriteTo(c.Conn)
71
	go c.Incoming.ReadFrom(c.Conn, MaxMessageSize)
72 73

	return nil
74 75
}

Juan Batiz-Benet's avatar
go lint  
Juan Batiz-Benet committed
76
// Close closes the connection, and associated channels.
77
func (s *Conn) Close() error {
78
	u.DOut("Closing Conn.\n")
79
	if s.Conn == nil {
80
		return fmt.Errorf("Already closed") // already closed
81
	}
82

83 84 85 86 87 88 89 90
	// closing net connection
	err := s.Conn.Close()
	s.Conn = nil
	// closing channels
	s.Incoming.Close()
	s.Outgoing.Close()
	s.Closed <- true
	return err
91
}