github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/routing/dht/dht_net.go (about)

     1  package dht
     2  
     3  import (
     4  	"errors"
     5  	"time"
     6  
     7  	ggio "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/gogo/protobuf/io"
     8  	ctxio "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-context/io"
     9  	context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
    10  	inet "github.com/ipfs/go-ipfs/p2p/net"
    11  	peer "github.com/ipfs/go-ipfs/p2p/peer"
    12  	pb "github.com/ipfs/go-ipfs/routing/dht/pb"
    13  )
    14  
    15  // handleNewStream implements the inet.StreamHandler
    16  func (dht *IpfsDHT) handleNewStream(s inet.Stream) {
    17  	go dht.handleNewMessage(s)
    18  }
    19  
    20  func (dht *IpfsDHT) handleNewMessage(s inet.Stream) {
    21  	defer s.Close()
    22  
    23  	ctx := dht.Context()
    24  	cr := ctxio.NewReader(ctx, s) // ok to use. we defer close stream in this func
    25  	cw := ctxio.NewWriter(ctx, s) // ok to use. we defer close stream in this func
    26  	r := ggio.NewDelimitedReader(cr, inet.MessageSizeMax)
    27  	w := ggio.NewDelimitedWriter(cw)
    28  	mPeer := s.Conn().RemotePeer()
    29  
    30  	// receive msg
    31  	pmes := new(pb.Message)
    32  	if err := r.ReadMsg(pmes); err != nil {
    33  		log.Debugf("Error unmarshaling data: %s", err)
    34  		return
    35  	}
    36  
    37  	// update the peer (on valid msgs only)
    38  	dht.updateFromMessage(ctx, mPeer, pmes)
    39  
    40  	// get handler for this msg type.
    41  	handler := dht.handlerForMsgType(pmes.GetType())
    42  	if handler == nil {
    43  		log.Debug("got back nil handler from handlerForMsgType")
    44  		return
    45  	}
    46  
    47  	// dispatch handler.
    48  	rpmes, err := handler(ctx, mPeer, pmes)
    49  	if err != nil {
    50  		log.Debugf("handle message error: %s", err)
    51  		return
    52  	}
    53  
    54  	// if nil response, return it before serializing
    55  	if rpmes == nil {
    56  		log.Debug("Got back nil response from request.")
    57  		return
    58  	}
    59  
    60  	// send out response msg
    61  	if err := w.WriteMsg(rpmes); err != nil {
    62  		log.Debugf("send response error: %s", err)
    63  		return
    64  	}
    65  
    66  	return
    67  }
    68  
    69  // sendRequest sends out a request, but also makes sure to
    70  // measure the RTT for latency measurements.
    71  func (dht *IpfsDHT) sendRequest(ctx context.Context, p peer.ID, pmes *pb.Message) (*pb.Message, error) {
    72  
    73  	log.Debugf("%s dht starting stream", dht.self)
    74  	s, err := dht.host.NewStream(ProtocolDHT, p)
    75  	if err != nil {
    76  		return nil, err
    77  	}
    78  	defer s.Close()
    79  
    80  	cr := ctxio.NewReader(ctx, s) // ok to use. we defer close stream in this func
    81  	cw := ctxio.NewWriter(ctx, s) // ok to use. we defer close stream in this func
    82  	r := ggio.NewDelimitedReader(cr, inet.MessageSizeMax)
    83  	w := ggio.NewDelimitedWriter(cw)
    84  
    85  	start := time.Now()
    86  
    87  	if err := w.WriteMsg(pmes); err != nil {
    88  		return nil, err
    89  	}
    90  	log.Event(ctx, "dhtSentMessage", dht.self, p, pmes)
    91  
    92  	rpmes := new(pb.Message)
    93  	if err := r.ReadMsg(rpmes); err != nil {
    94  		return nil, err
    95  	}
    96  	if rpmes == nil {
    97  		return nil, errors.New("no response to request")
    98  	}
    99  
   100  	// update the peer (on valid msgs only)
   101  	dht.updateFromMessage(ctx, p, rpmes)
   102  
   103  	dht.peerstore.RecordLatency(p, time.Since(start))
   104  	log.Event(ctx, "dhtReceivedMessage", dht.self, p, rpmes)
   105  	return rpmes, nil
   106  }
   107  
   108  // sendMessage sends out a message
   109  func (dht *IpfsDHT) sendMessage(ctx context.Context, p peer.ID, pmes *pb.Message) error {
   110  
   111  	log.Debugf("%s dht starting stream", dht.self)
   112  	s, err := dht.host.NewStream(ProtocolDHT, p)
   113  	if err != nil {
   114  		return err
   115  	}
   116  	defer s.Close()
   117  
   118  	cw := ctxio.NewWriter(ctx, s) // ok to use. we defer close stream in this func
   119  	w := ggio.NewDelimitedWriter(cw)
   120  
   121  	if err := w.WriteMsg(pmes); err != nil {
   122  		return err
   123  	}
   124  	log.Event(ctx, "dhtSentMessage", dht.self, p, pmes)
   125  	return nil
   126  }
   127  
   128  func (dht *IpfsDHT) updateFromMessage(ctx context.Context, p peer.ID, mes *pb.Message) error {
   129  	dht.Update(ctx, p)
   130  	return nil
   131  }