conn.go 2.19 KB
Newer Older
1
package conn
2 3

import (
4
	"fmt"
5

6 7
	msgio "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-msgio"
	ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
8
	manet "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net"
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
9 10

	spipe "github.com/jbenet/go-ipfs/crypto/spipe"
11 12
	peer "github.com/jbenet/go-ipfs/peer"
	u "github.com/jbenet/go-ipfs/util"
13 14
)

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
15 16
var log = u.Logger("conn")

Juan Batiz-Benet's avatar
go lint  
Juan Batiz-Benet committed
17
// ChanBuffer is the size of the buffer in the Conn Chan
18 19
const ChanBuffer = 10

20 21
// 1 MB
const MaxMessageSize = 1 << 20
22

Juan Batiz-Benet's avatar
go lint  
Juan Batiz-Benet committed
23
// Conn represents a connection to another Peer (IPFS Node).
24
type Conn struct {
25
	Peer *peer.Peer
26
	Addr ma.Multiaddr
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
27
	Conn manet.Conn
28

29 30 31
	Closed   chan bool
	Outgoing *msgio.Chan
	Incoming *msgio.Chan
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
32
	Secure   *spipe.SecurePipe
33 34
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
35 36
// Map maps Keys (Peer.IDs) to Connections.
type Map map[u.Key]*Conn
37

38
// NewConn constructs a new connection
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
39
func NewConn(peer *peer.Peer, addr ma.Multiaddr, mconn manet.Conn) (*Conn, error) {
40 41 42
	conn := &Conn{
		Peer: peer,
		Addr: addr,
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
43
		Conn: mconn,
44 45 46 47 48 49 50 51 52
	}

	if err := conn.newChans(); err != nil {
		return nil, err
	}

	return conn, nil
}

Juan Batiz-Benet's avatar
go lint  
Juan Batiz-Benet committed
53 54
// Dial connects to a particular peer, over a given network
// Example: Dial("udp", peer)
55
func Dial(network string, peer *peer.Peer) (*Conn, error) {
56 57 58 59
	addr := peer.NetAddress(network)
	if addr == nil {
		return nil, fmt.Errorf("No address for network %s", network)
	}
60

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
61
	nconn, err := manet.Dial(addr)
62 63 64
	if err != nil {
		return nil, err
	}
65

66
	return NewConn(peer, addr, nconn)
67 68 69
}

// Construct new channels for given Conn.
70
func (c *Conn) newChans() error {
71 72
	if c.Outgoing != nil || c.Incoming != nil {
		return fmt.Errorf("Conn already initialized")
73
	}
74

75 76 77
	c.Outgoing = msgio.NewChan(10)
	c.Incoming = msgio.NewChan(10)
	c.Closed = make(chan bool, 1)
78

79
	go c.Outgoing.WriteTo(c.Conn)
80
	go c.Incoming.ReadFrom(c.Conn, MaxMessageSize)
81 82

	return nil
83 84
}

Juan Batiz-Benet's avatar
go lint  
Juan Batiz-Benet committed
85
// Close closes the connection, and associated channels.
86
func (c *Conn) Close() error {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
87
	log.Debug("Closing Conn with %v", c.Peer)
88
	if c.Conn == nil {
89
		return fmt.Errorf("Already closed") // already closed
90
	}
91

92
	// closing net connection
93 94
	err := c.Conn.Close()
	c.Conn = nil
95
	// closing channels
96 97 98
	c.Incoming.Close()
	c.Outgoing.Close()
	c.Closed <- true
99
	return err
100
}