conn.go 2.39 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
go lint  
Juan Batiz-Benet committed
15
// ChanBuffer is the size of the buffer in the Conn Chan
16 17
const ChanBuffer = 10

18 19
// 1 MB
const MaxMessageSize = 1 << 20
20

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

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

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

36
// NewConn constructs a new connection
37
func NewConn(peer *peer.Peer, addr ma.Multiaddr, nconn net.Conn) (*Conn, error) {
38 39 40 41 42 43 44 45 46 47 48 49 50
	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
51 52
// Dial connects to a particular peer, over a given network
// Example: Dial("udp", peer)
53
func Dial(network string, peer *peer.Peer) (*Conn, error) {
54 55 56 57
	addr := peer.NetAddress(network)
	if addr == nil {
		return nil, fmt.Errorf("No address for network %s", network)
	}
58

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

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

69
	return NewConn(peer, addr, nconn)
70 71 72
}

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

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

82
	go c.Outgoing.WriteTo(c.Conn)
83
	go c.Incoming.ReadFrom(c.Conn, MaxMessageSize)
84 85

	return nil
86 87
}

Juan Batiz-Benet's avatar
go lint  
Juan Batiz-Benet committed
88
// Close closes the connection, and associated channels.
89
func (c *Conn) Close() error {
90
	u.DOut("Closing Conn.\n")
91
	if c.Conn == nil {
92
		return fmt.Errorf("Already closed") // already closed
93
	}
94

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

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