// NewStream opens a new stream to given peer p, and writes a p2p/protocol // header with given protocol.ID. If there is no connection to p, attempts // to create one. If ProtocolID is "", writes no header. // (Threadsafe) func (h *BasicHost) NewStream(ctx context.Context, p peer.ID, pids ...protocol.ID) (inet.Stream, error) { pref, err := h.preferredProtocol(p, pids) if err != nil { return nil, err } if pref != "" { return h.newStream(ctx, p, pref) } var protoStrs []string for _, pid := range pids { protoStrs = append(protoStrs, string(pid)) } s, err := h.Network().NewStream(ctx, p) if err != nil { return nil, err } selected, err := msmux.SelectOneOf(protoStrs, s) if err != nil { s.Close() return nil, err } selpid := protocol.ID(selected) s.SetProtocol(selpid) h.Peerstore().AddProtocols(p, selected) return mstream.WrapStream(s, h.bwc), nil }
// newStreamHandler is the remote-opened stream handler for inet.Network // TODO: this feels a bit wonky func (h *BasicHost) newStreamHandler(s inet.Stream) { before := time.Now() protoID, handle, err := h.Mux().Negotiate(s) took := time.Now().Sub(before) if err != nil { if err == io.EOF { logf := log.Debugf if took > time.Second*10 { logf = log.Warningf } logf("protocol EOF: %s (took %s)", s.Conn().RemotePeer(), took) } else { log.Warning("protocol mux failed: %s (took %s)", err, took) } return } s.SetProtocol(protocol.ID(protoID)) if h.bwc != nil { s = mstream.WrapStream(s, h.bwc) } log.Debugf("protocol negotiation took %s", took) go handle(protoID, s) }
func (ids *IDService) RequestHandler(s inet.Stream) { defer s.Close() c := s.Conn() bwc := ids.Host.GetBandwidthReporter() s = mstream.WrapStream(s, bwc) w := ggio.NewDelimitedWriter(s) mes := pb.Identify{} ids.populateMessage(&mes, s.Conn()) w.WriteMsg(&mes) log.Debugf("%s sent message to %s %s", ID, c.RemotePeer(), c.RemoteMultiaddr()) }
func (ids *IDService) IdentifyConn(c inet.Conn) { ids.currmu.Lock() if wait, found := ids.currid[c]; found { ids.currmu.Unlock() log.Debugf("IdentifyConn called twice on: %s", c) <-wait // already identifying it. wait for it. return } ch := make(chan struct{}) ids.currid[c] = ch ids.currmu.Unlock() defer close(ch) s, err := c.NewStream() if err != nil { log.Debugf("error opening initial stream for %s: %s", ID, err) log.Event(context.TODO(), "IdentifyOpenFailed", c.RemotePeer()) c.Close() return } defer s.Close() s.SetProtocol(ID) if ids.Reporter != nil { s = mstream.WrapStream(s, ids.Reporter) } // ok give the response to our handler. if err := msmux.SelectProtoOrFail(ID, s); err != nil { log.Debugf("error writing stream header for %s", ID) log.Event(context.TODO(), "IdentifyOpenFailed", c.RemotePeer()) return } ids.ResponseHandler(s) ids.currmu.Lock() _, found := ids.currid[c] delete(ids.currid, c) ids.currmu.Unlock() if !found { log.Debugf("IdentifyConn failed to find channel (programmer error) for %s", c) return } }
func (h *BasicHost) newStream(ctx context.Context, p peer.ID, pid protocol.ID) (inet.Stream, error) { s, err := h.Network().NewStream(ctx, p) if err != nil { return nil, err } s.SetProtocol(pid) logStream := mstream.WrapStream(s, h.bwc) lzcon := msmux.NewMSSelect(logStream, string(pid)) return &streamWrapper{ Stream: logStream, rw: lzcon, }, nil }
// newStreamHandler is the remote-opened stream handler for inet.Network // TODO: this feels a bit wonky func (h *BasicHost) newStreamHandler(s inet.Stream) { before := time.Now() if h.NegotiateTimeout != 0 { if err := s.SetDeadline(time.Now().Add(h.NegotiateTimeout)); err != nil { log.Error("setting stream deadline: ", err) s.Close() return } } protoID, handle, err := h.Mux().Negotiate(s) took := time.Now().Sub(before) if err != nil { if err == io.EOF { logf := log.Debugf if took > time.Second*10 { logf = log.Warningf } logf("protocol EOF: %s (took %s)", s.Conn().RemotePeer(), took) } else { log.Warning("protocol mux failed: %s (took %s)", err, took) } s.Close() return } if h.NegotiateTimeout != 0 { if err := s.SetDeadline(time.Time{}); err != nil { log.Error("resetting stream deadline: ", err) s.Close() return } } s.SetProtocol(protocol.ID(protoID)) if h.bwc != nil { s = mstream.WrapStream(s, h.bwc) } log.Debugf("protocol negotiation took %s", took) go handle(protoID, s) }