conn.go 1.59 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 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 62 63 64 65 66 67 68 69
package swarm

import (
	"errors"
	"fmt"
	"net"

	ident "github.com/jbenet/go-ipfs/identify"
	conn "github.com/jbenet/go-ipfs/net/conn"

	u "github.com/jbenet/go-ipfs/util"
)

// Handle getting ID from this peer, handshake, and adding it into the map
func (s *Swarm) handleIncomingConn(nconn net.Conn) {

	c, err := conn.NewNetConn(nconn)
	if err != nil {
		s.errChan <- err
		return
	}

	//TODO(jbenet) the peer might potentially already be in the global PeerBook.
	// maybe use the handshake to populate peer.
	c.Peer.AddAddress(c.Addr)

	// Setup the new connection
	err = s.connSetup(c)
	if err != nil && err != ErrAlreadyOpen {
		s.errChan <- err
		c.Close()
	}
}

// connSetup adds the passed in connection to its peerMap and starts
// the fanIn routine for that connection
func (s *Swarm) connSetup(c *conn.Conn) error {
	if c == nil {
		return errors.New("Tried to start nil connection.")
	}

	u.DOut("Starting connection: %s\n", c.Peer.Key().Pretty())

	// handshake
	if err := s.connHandshake(c); err != nil {
		return fmt.Errorf("Conn handshake error: %v", err)
	}

	// add to conns
	s.connsLock.Lock()
	if _, ok := s.conns[c.Peer.Key()]; ok {
		s.connsLock.Unlock()
		return ErrAlreadyOpen
	}
	s.conns[c.Peer.Key()] = c
	s.connsLock.Unlock()

	// kick off reader goroutine
	go s.fanIn(c)
	return nil
}

// connHandshake runs the handshake with the remote connection.
func (s *Swarm) connHandshake(c *conn.Conn) error {

	//TODO(jbenet) this Handshake stuff should be moved elsewhere.
	// needs cleanup. needs context. use msg.Pipe.
	return ident.Handshake(s.local, c.Peer, c.Incoming.MsgChan, c.Outgoing.MsgChan)
}