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 24 25
	Peer *peer.Peer
	Addr *ma.Multiaddr
	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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
// NewConn constructs a new connection
func NewConn(peer *peer.Peer, addr *ma.Multiaddr, nconn net.Conn) (*Conn, error) {
	conn := &Conn{
		Peer: peer,
		Addr: addr,
		Conn: nconn,
	}

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

	return conn, nil
}

// NewNetConn constructs a new connection with given net.Conn
func NewNetConn(nconn net.Conn) (*Conn, error) {

	addr, err := ma.FromNetAddr(nconn.RemoteAddr())
	if err != nil {
		return nil, err
	}

	return NewConn(new(peer.Peer), addr, nconn)
}

Juan Batiz-Benet's avatar
go lint  
Juan Batiz-Benet committed
62 63
// Dial connects to a particular peer, over a given network
// Example: Dial("udp", peer)
64
func Dial(network string, peer *peer.Peer) (*Conn, error) {
65 66 67 68
	addr := peer.NetAddress(network)
	if addr == nil {
		return nil, fmt.Errorf("No address for network %s", network)
	}
69

70 71 72 73
	network, host, err := addr.DialArgs()
	if err != nil {
		return nil, err
	}
74

75 76 77 78
	nconn, err := net.Dial(network, host)
	if err != nil {
		return nil, err
	}
79

80
	return NewConn(peer, addr, nconn)
81 82 83
}

// Construct new channels for given Conn.
84
func (c *Conn) newChans() error {
85 86
	if c.Outgoing != nil || c.Incoming != nil {
		return fmt.Errorf("Conn already initialized")
87
	}
88

89 90 91
	c.Outgoing = msgio.NewChan(10)
	c.Incoming = msgio.NewChan(10)
	c.Closed = make(chan bool, 1)
92

93
	go c.Outgoing.WriteTo(c.Conn)
94
	go c.Incoming.ReadFrom(c.Conn, MaxMessageSize)
95 96

	return nil
97 98
}

Juan Batiz-Benet's avatar
go lint  
Juan Batiz-Benet committed
99
// Close closes the connection, and associated channels.
100
func (c *Conn) Close() error {
101
	u.DOut("Closing Conn.\n")
102
	if c.Conn == nil {
103
		return fmt.Errorf("Already closed") // already closed
104
	}
105

106
	// closing net connection
107 108
	err := c.Conn.Close()
	c.Conn = nil
109
	// closing channels
110 111 112
	c.Incoming.Close()
	c.Outgoing.Close()
	c.Closed <- true
113
	return err
114
}