github.com/ethersphere/bee/v2@v2.2.0/pkg/p2p/libp2p/stream.go (about)

     1  // Copyright 2020 The Swarm Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package libp2p
     6  
     7  import (
     8  	"errors"
     9  	"io"
    10  	"time"
    11  
    12  	"github.com/ethersphere/bee/v2/pkg/p2p"
    13  	"github.com/libp2p/go-libp2p/core/network"
    14  )
    15  
    16  var (
    17  	closeDeadline  = 30 * time.Second
    18  	errExpectedEof = errors.New("read: expected eof")
    19  )
    20  var _ p2p.Stream = (*stream)(nil)
    21  
    22  type stream struct {
    23  	network.Stream
    24  	headers         map[string][]byte
    25  	responseHeaders map[string][]byte
    26  	metrics         metrics
    27  }
    28  
    29  func newStream(s network.Stream, metrics metrics) *stream {
    30  	return &stream{Stream: s, metrics: metrics}
    31  }
    32  func (s *stream) Headers() p2p.Headers {
    33  	return s.headers
    34  }
    35  
    36  func (s *stream) ResponseHeaders() p2p.Headers {
    37  	return s.responseHeaders
    38  }
    39  
    40  func (s *stream) Reset() error {
    41  	defer s.metrics.StreamResetCount.Inc()
    42  	return s.Stream.Reset()
    43  }
    44  
    45  func (s *stream) FullClose() error {
    46  	defer s.metrics.ClosedStreamCount.Inc()
    47  	// close the stream to make sure it is gc'd
    48  	defer s.Close()
    49  
    50  	if err := s.CloseWrite(); err != nil {
    51  		_ = s.Stream.Reset()
    52  		return err
    53  	}
    54  
    55  	// So we don't wait forever
    56  	_ = s.SetDeadline(time.Now().Add(closeDeadline))
    57  
    58  	// We *have* to observe the EOF. Otherwise, we leak the stream.
    59  	// Now, technically, we should do this *before*
    60  	// returning from SendMessage as the message
    61  	// hasn't really been sent yet until we see the
    62  	// EOF but we don't actually *know* what
    63  	// protocol the other side is speaking.
    64  	n, err := s.Read([]byte{0})
    65  	if n > 0 || err == nil {
    66  		_ = s.Stream.Reset()
    67  		return errExpectedEof
    68  	}
    69  	if !errors.Is(err, io.EOF) {
    70  		_ = s.Stream.Reset()
    71  		return err
    72  	}
    73  	return nil
    74  }