github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/p2p/net/conn/listen.go (about)

     1  package conn
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"net"
     7  
     8  	ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
     9  	manet "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net"
    10  	reuseport "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-reuseport"
    11  	tec "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-temp-err-catcher"
    12  	"github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess"
    13  	goprocessctx "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess/context"
    14  	context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
    15  
    16  	ic "github.com/ipfs/go-ipfs/p2p/crypto"
    17  	filter "github.com/ipfs/go-ipfs/p2p/net/filter"
    18  	peer "github.com/ipfs/go-ipfs/p2p/peer"
    19  )
    20  
    21  // ConnWrapper is any function that wraps a raw multiaddr connection
    22  type ConnWrapper func(manet.Conn) manet.Conn
    23  
    24  // listener is an object that can accept connections. It implements Listener
    25  type listener struct {
    26  	manet.Listener
    27  
    28  	local peer.ID    // LocalPeer is the identity of the local Peer
    29  	privk ic.PrivKey // private key to use to initialize secure conns
    30  
    31  	filters *filter.Filters
    32  
    33  	wrapper ConnWrapper
    34  
    35  	proc goprocess.Process
    36  }
    37  
    38  func (l *listener) teardown() error {
    39  	defer log.Debugf("listener closed: %s %s", l.local, l.Multiaddr())
    40  	return l.Listener.Close()
    41  }
    42  
    43  func (l *listener) Close() error {
    44  	log.Debugf("listener closing: %s %s", l.local, l.Multiaddr())
    45  	return l.proc.Close()
    46  }
    47  
    48  func (l *listener) String() string {
    49  	return fmt.Sprintf("<Listener %s %s>", l.local, l.Multiaddr())
    50  }
    51  
    52  func (l *listener) SetAddrFilters(fs *filter.Filters) {
    53  	l.filters = fs
    54  }
    55  
    56  // Accept waits for and returns the next connection to the listener.
    57  // Note that unfortunately this
    58  func (l *listener) Accept() (net.Conn, error) {
    59  
    60  	// listeners dont have contexts. given changes dont make sense here anymore
    61  	// note that the parent of listener will Close, which will interrupt all io.
    62  	// Contexts and io don't mix.
    63  	ctx := context.Background()
    64  
    65  	var catcher tec.TempErrCatcher
    66  
    67  	catcher.IsTemp = func(e error) bool {
    68  		// ignore connection breakages up to this point. but log them
    69  		if e == io.EOF {
    70  			log.Debugf("listener ignoring conn with EOF: %s", e)
    71  			return true
    72  		}
    73  
    74  		te, ok := e.(tec.Temporary)
    75  		if ok {
    76  			log.Debugf("listener ignoring conn with temporary err: %s", e)
    77  			return te.Temporary()
    78  		}
    79  		return false
    80  	}
    81  
    82  	for {
    83  		maconn, err := l.Listener.Accept()
    84  		if err != nil {
    85  			if catcher.IsTemporary(err) {
    86  				continue
    87  			}
    88  			return nil, err
    89  		}
    90  
    91  		log.Debugf("listener %s got connection: %s <---> %s", l, maconn.LocalMultiaddr(), maconn.RemoteMultiaddr())
    92  
    93  		if l.filters != nil && l.filters.AddrBlocked(maconn.RemoteMultiaddr()) {
    94  			log.Debugf("blocked connection from %s", maconn.RemoteMultiaddr())
    95  			maconn.Close()
    96  			continue
    97  		}
    98  		// If we have a wrapper func, wrap this conn
    99  		if l.wrapper != nil {
   100  			maconn = l.wrapper(maconn)
   101  		}
   102  
   103  		c, err := newSingleConn(ctx, l.local, "", maconn)
   104  		if err != nil {
   105  			if catcher.IsTemporary(err) {
   106  				continue
   107  			}
   108  			return nil, err
   109  		}
   110  
   111  		if l.privk == nil || EncryptConnections == false {
   112  			log.Warning("listener %s listening INSECURELY!", l)
   113  			return c, nil
   114  		}
   115  		sc, err := newSecureConn(ctx, l.privk, c)
   116  		if err != nil {
   117  			log.Infof("ignoring conn we failed to secure: %s %s", err, c)
   118  			continue
   119  		}
   120  		return sc, nil
   121  	}
   122  }
   123  
   124  func (l *listener) Addr() net.Addr {
   125  	return l.Listener.Addr()
   126  }
   127  
   128  // Multiaddr is the identity of the local Peer.
   129  // If there is an error converting from net.Addr to ma.Multiaddr,
   130  // the return value will be nil.
   131  func (l *listener) Multiaddr() ma.Multiaddr {
   132  	return l.Listener.Multiaddr()
   133  }
   134  
   135  // LocalPeer is the identity of the local Peer.
   136  func (l *listener) LocalPeer() peer.ID {
   137  	return l.local
   138  }
   139  
   140  func (l *listener) Loggable() map[string]interface{} {
   141  	return map[string]interface{}{
   142  		"listener": map[string]interface{}{
   143  			"peer":    l.LocalPeer(),
   144  			"address": l.Multiaddr(),
   145  			"secure":  (l.privk != nil),
   146  		},
   147  	}
   148  }
   149  
   150  // Listen listens on the particular multiaddr, with given peer and peerstore.
   151  func Listen(ctx context.Context, addr ma.Multiaddr, local peer.ID, sk ic.PrivKey) (Listener, error) {
   152  	ml, err := manetListen(addr)
   153  	if err != nil {
   154  		return nil, err
   155  	}
   156  
   157  	l := &listener{
   158  		Listener: ml,
   159  		local:    local,
   160  		privk:    sk,
   161  	}
   162  	l.proc = goprocessctx.WithContextAndTeardown(ctx, l.teardown)
   163  
   164  	log.Debugf("Conn Listener on %s", l.Multiaddr())
   165  	log.Event(ctx, "swarmListen", l)
   166  	return l, nil
   167  }
   168  
   169  type ListenerConnWrapper interface {
   170  	SetConnWrapper(ConnWrapper)
   171  }
   172  
   173  // SetConnWrapper assigns a maconn ConnWrapper to wrap all incoming
   174  // connections with. MUST be set _before_ calling `Accept()`
   175  func (l *listener) SetConnWrapper(cw ConnWrapper) {
   176  	l.wrapper = cw
   177  }
   178  
   179  func manetListen(addr ma.Multiaddr) (manet.Listener, error) {
   180  	network, naddr, err := manet.DialArgs(addr)
   181  	if err != nil {
   182  		return nil, err
   183  	}
   184  
   185  	if reuseportIsAvailable() {
   186  		nl, err := reuseport.Listen(network, naddr)
   187  		if err == nil {
   188  			// hey, it worked!
   189  			return manet.WrapNetListener(nl)
   190  		}
   191  		// reuseport is available, but we failed to listen. log debug, and retry normally.
   192  		log.Debugf("reuseport available, but failed to listen: %s %s, %s", network, naddr, err)
   193  	}
   194  
   195  	// either reuseport not available, or it failed. try normally.
   196  	return manet.Listen(addr)
   197  }