net.go 4.12 KB
Newer Older
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
1
// Package net provides an interface for ipfs to interact with the network through
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
2 3 4
package net

import (
5
	swarm "github.com/jbenet/go-ipfs/net/swarm2"
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
6
	peer "github.com/jbenet/go-ipfs/peer"
7
	util "github.com/jbenet/go-ipfs/util"
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
8

9
	context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
10
	ctxgroup "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-ctxgroup"
11
	ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
12 13
)

14
type stream swarm.Stream
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
15

16 17 18
func (s *stream) SwarmStream() *swarm.Stream {
	return (*swarm.Stream)(s)
}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
19

20 21 22 23 24
// Conn returns the connection this stream is part of.
func (s *stream) Conn() Conn {
	c := s.SwarmStream().Conn()
	return (*conn_)(c)
}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
25

26 27 28 29
// Conn returns the connection this stream is part of.
func (s *stream) Close() error {
	return s.SwarmStream().Close()
}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
30

31 32 33
// Read reads bytes from a stream.
func (s *stream) Read(p []byte) (n int, err error) {
	return s.SwarmStream().Read(p)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
34 35
}

36 37 38 39
// Write writes bytes to a stream, flushing for each call.
func (s *stream) Write(p []byte) (n int, err error) {
	return s.SwarmStream().Write(p)
}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
40

41
type conn_ swarm.Conn
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
42

43 44 45 46 47 48
func (c *conn_) SwarmConn() *swarm.Conn {
	return (*swarm.Conn)(c)
}

func (c *conn_) NewStream(p peer.Peer) (Stream, error) {
	s, err := (*swarm.Conn)(c).NewStream()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
49 50 51
	if err != nil {
		return nil, err
	}
52 53
	return (*stream)(s), nil
}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
54

55 56 57 58
// LocalMultiaddr is the Multiaddr on this side
func (c *conn_) LocalMultiaddr() ma.Multiaddr {
	return c.SwarmConn().LocalMultiaddr()
}
59

60 61 62 63
// LocalPeer is the Peer on our side of the connection
func (c *conn_) LocalPeer() peer.Peer {
	return c.SwarmConn().LocalPeer()
}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
64

65 66 67
// RemoteMultiaddr is the Multiaddr on the remote side
func (c *conn_) RemoteMultiaddr() ma.Multiaddr {
	return c.SwarmConn().RemoteMultiaddr()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
68 69
}

70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
// RemotePeer is the Peer on the remote side
func (c *conn_) RemotePeer() peer.Peer {
	return c.SwarmConn().RemotePeer()
}

// network implements the Network interface,
type network struct {
	local peer.Peer    // local peer
	mux   Mux          // protocol multiplexing
	swarm *swarm.Swarm // peer connection multiplexing

	cg ctxgroup.ContextGroup // for Context closing
}

// NewConn is the structure that implements the network interface
func NewConn(ctx context.Context, listen []ma.Multiaddr, local peer.Peer,
	peers peer.Peerstore, m Mux) (*network, error) {

	s, err := swarm.NewSwarm(ctx, listen, local, peers)
	if err != nil {
		return nil, err
	}

	n := &network{
		local: local,
		swarm: s,
		mux:   m,
		cg:    ctxgroup.WithContext(ctx),
	}

	s.SetStreamHandler(func(s *swarm.Stream) {
		m.Handle((*stream)(s))
	})

	n.cg.AddChildGroup(s.CtxGroup())
	return n, nil
}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
107

108 109
// DialPeer attempts to establish a connection to a given peer.
// Respects the context.
110
func (n *network) DialPeer(ctx context.Context, p peer.Peer) error {
111
	err := util.ContextDo(ctx, func() error {
112 113 114
		_, err := n.swarm.Dial(p)
		return err
	})
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
115 116 117
	return err
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
118
// LocalPeer the network's LocalPeer
119
func (n *network) LocalPeer() peer.Peer {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
120 121 122
	return n.swarm.LocalPeer()
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
123
// ClosePeer connection to peer
124
func (n *network) ClosePeer(p peer.Peer) error {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
125 126 127
	return n.swarm.CloseConnection(p)
}

128 129 130 131 132
// BandwidthTotals returns the total amount of bandwidth transferred
func (n *network) BandwidthTotals() (in uint64, out uint64) {
	// need to implement this. probably best to do it in swarm this time.
	// need a "metrics" object
	return 0, 0
Jeromy's avatar
Jeromy committed
133 134
}

135
// ListenAddresses returns a list of addresses at which this network listens.
136
func (n *network) ListenAddresses() []ma.Multiaddr {
137 138 139 140 141 142
	return n.swarm.ListenAddresses()
}

// InterfaceListenAddresses returns a list of addresses at which this network
// listens. It expands "any interface" addresses (/ip4/0.0.0.0, /ip6/::) to
// use the known local interfaces.
143 144
func (n *network) InterfaceListenAddresses() ([]ma.Multiaddr, error) {
	return swarm.InterfaceListenAddresses(n.swarm)
145
}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
146 147

// Connectedness returns a state signaling connection capabilities
Brian Tiger Chow's avatar
Brian Tiger Chow committed
148
// For now only returns Connected || NotConnected. Expand into more later.
149 150 151
func (n *network) Connectedness(p peer.Peer) Connectedness {
	c := n.swarm.ConnectionsToPeer(p)
	if c != nil && len(c) < 1 {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
152 153 154 155
		return Connected
	}
	return NotConnected
}