conn.go 2.43 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"
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
27
	Conn net.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
39
func NewConn(peer *peer.Peer, addr ma.Multiaddr, nconn net.Conn) (*Conn, error) {
40 41 42 43 44 45 46 47 48 49 50 51 52
	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
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

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

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

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

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

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

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

	return nil
88 89
}

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

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

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