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

import (
4
	"fmt"
5 6
	"net"

7 8
	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"
9
	manet "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net"
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
10 11

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

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

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

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

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

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

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

39
// NewConn constructs a new connection
40
func NewConn(peer *peer.Peer, addr ma.Multiaddr, nconn net.Conn) (*Conn, error) {
41 42 43 44 45 46 47 48 49 50 51 52 53
	conn := &Conn{
		Peer: peer,
		Addr: addr,
		Conn: nconn,
	}

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

	return conn, nil
}

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

62
	network, host, err := manet.DialArgs(addr)
63 64 65
	if err != nil {
		return nil, err
	}
66

67 68 69 70
	nconn, err := net.Dial(network, host)
	if err != nil {
		return nil, err
	}
71

72
	return NewConn(peer, addr, nconn)
73 74 75
}

// Construct new channels for given Conn.
76
func (c *Conn) newChans() error {
77 78
	if c.Outgoing != nil || c.Incoming != nil {
		return fmt.Errorf("Conn already initialized")
79
	}
80

81 82 83
	c.Outgoing = msgio.NewChan(10)
	c.Incoming = msgio.NewChan(10)
	c.Closed = make(chan bool, 1)
84

85
	go c.Outgoing.WriteTo(c.Conn)
86
	go c.Incoming.ReadFrom(c.Conn, MaxMessageSize)
87 88

	return nil
89 90
}

Juan Batiz-Benet's avatar
go lint  
Juan Batiz-Benet committed
91
// Close closes the connection, and associated channels.
92
func (c *Conn) Close() error {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
93
	log.Debug("Closing Conn with %v", c.Peer)
94
	if c.Conn == nil {
95
		return fmt.Errorf("Already closed") // already closed
96
	}
97

98
	// closing net connection
99 100
	err := c.Conn.Close()
	c.Conn = nil
101
	// closing channels
102 103 104
	c.Incoming.Close()
	c.Outgoing.Close()
	c.Closed <- true
105
	return err
106
}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
107 108 109

// NetConnMultiaddr returns the net.Conn's address, recast as a multiaddr.
// (consider moving this directly into the multiaddr package)
110
func NetConnMultiaddr(nconn net.Conn) (ma.Multiaddr, error) {
111
	return manet.FromNetAddr(nconn.RemoteAddr())
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
112
}