pipe.go 1.48 KB
Newer Older
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
package spipe

import (
	"errors"

	context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
	peer "github.com/jbenet/go-ipfs/peer"
)

// Duplex is a simple duplex channel
type Duplex struct {
	In  chan []byte
	Out chan []byte
}

// SecurePipe objects represent a bi-directional message channel.
type SecurePipe struct {
	Duplex
	insecure Duplex

	local  *peer.Peer
	remote *peer.Peer
23
	peers  peer.Peerstore
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
24 25 26 27 28 29 30 31 32 33 34 35

	params params

	ctx    context.Context
	cancel context.CancelFunc
}

// options in a secure pipe
type params struct {
}

// NewSecurePipe constructs a pipe with channels of a given buffer size.
36
func NewSecurePipe(ctx context.Context, bufsize int, local *peer.Peer,
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
37 38 39
	peers peer.Peerstore, insecure Duplex) (*SecurePipe, error) {

	ctx, cancel := context.WithCancel(ctx)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
40 41 42 43 44 45

	sp := &SecurePipe{
		Duplex: Duplex{
			In:  make(chan []byte, bufsize),
			Out: make(chan []byte, bufsize),
		},
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
46 47 48
		local:    local,
		peers:    peers,
		insecure: insecure,
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
49

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
50 51
		ctx:    ctx,
		cancel: cancel,
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
52 53
	}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
54 55 56
	if err := sp.handshake(); err != nil {
		sp.Close()
		return nil, err
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
57 58
	}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
59
	return sp, nil
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
60 61
}

62 63 64 65 66 67 68 69 70 71
// LocalPeer retrieves the local peer.
func (s *SecurePipe) LocalPeer() *peer.Peer {
	return s.local
}

// RemotePeer retrieves the local peer.
func (s *SecurePipe) RemotePeer() *peer.Peer {
	return s.remote
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
72 73
// Close closes the secure pipe
func (s *SecurePipe) Close() error {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
74 75 76 77
	select {
	case <-s.ctx.Done():
		return errors.New("already closed")
	default:
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
78 79 80 81 82
	}

	s.cancel()
	return nil
}