github.com/ooni/psiphon/tunnel-core@v0.0.0-20230105123940-fe12a24c96ee/psiphon/common/quic/gquic-go/streams_map_incoming_uni.go (about)

     1  // This file was automatically generated by genny.
     2  // Any changes will be lost if this file is regenerated.
     3  // see https://github.com/cheekybits/genny
     4  
     5  package gquic
     6  
     7  import (
     8  	"fmt"
     9  	"sync"
    10  
    11  	"github.com/ooni/psiphon/tunnel-core/psiphon/common/quic/gquic-go/internal/protocol"
    12  	"github.com/ooni/psiphon/tunnel-core/psiphon/common/quic/gquic-go/internal/wire"
    13  )
    14  
    15  type incomingUniStreamsMap struct {
    16  	mutex sync.RWMutex
    17  	cond  sync.Cond
    18  
    19  	streams map[protocol.StreamID]receiveStreamI
    20  
    21  	nextStream    protocol.StreamID // the next stream that will be returned by AcceptStream()
    22  	highestStream protocol.StreamID // the highest stream that the peer openend
    23  	maxStream     protocol.StreamID // the highest stream that the peer is allowed to open
    24  	maxNumStreams int               // maximum number of streams
    25  
    26  	newStream        func(protocol.StreamID) receiveStreamI
    27  	queueMaxStreamID func(*wire.MaxStreamIDFrame)
    28  
    29  	closeErr error
    30  }
    31  
    32  func newIncomingUniStreamsMap(
    33  	nextStream protocol.StreamID,
    34  	initialMaxStreamID protocol.StreamID,
    35  	maxNumStreams int,
    36  	queueControlFrame func(wire.Frame),
    37  	newStream func(protocol.StreamID) receiveStreamI,
    38  ) *incomingUniStreamsMap {
    39  	m := &incomingUniStreamsMap{
    40  		streams:          make(map[protocol.StreamID]receiveStreamI),
    41  		nextStream:       nextStream,
    42  		maxStream:        initialMaxStreamID,
    43  		maxNumStreams:    maxNumStreams,
    44  		newStream:        newStream,
    45  		queueMaxStreamID: func(f *wire.MaxStreamIDFrame) { queueControlFrame(f) },
    46  	}
    47  	m.cond.L = &m.mutex
    48  	return m
    49  }
    50  
    51  func (m *incomingUniStreamsMap) AcceptStream() (receiveStreamI, error) {
    52  	m.mutex.Lock()
    53  	defer m.mutex.Unlock()
    54  
    55  	var str receiveStreamI
    56  	for {
    57  		var ok bool
    58  		if m.closeErr != nil {
    59  			return nil, m.closeErr
    60  		}
    61  		str, ok = m.streams[m.nextStream]
    62  		if ok {
    63  			break
    64  		}
    65  		m.cond.Wait()
    66  	}
    67  	m.nextStream += 4
    68  	return str, nil
    69  }
    70  
    71  func (m *incomingUniStreamsMap) GetOrOpenStream(id protocol.StreamID) (receiveStreamI, error) {
    72  	m.mutex.RLock()
    73  	if id > m.maxStream {
    74  		m.mutex.RUnlock()
    75  		return nil, fmt.Errorf("peer tried to open stream %d (current limit: %d)", id, m.maxStream)
    76  	}
    77  	// if the id is smaller than the highest we accepted
    78  	// * this stream exists in the map, and we can return it, or
    79  	// * this stream was already closed, then we can return the nil
    80  	if id <= m.highestStream {
    81  		s := m.streams[id]
    82  		m.mutex.RUnlock()
    83  		return s, nil
    84  	}
    85  	m.mutex.RUnlock()
    86  
    87  	m.mutex.Lock()
    88  	// no need to check the two error conditions from above again
    89  	// * maxStream can only increase, so if the id was valid before, it definitely is valid now
    90  	// * highestStream is only modified by this function
    91  	var start protocol.StreamID
    92  	if m.highestStream == 0 {
    93  		start = m.nextStream
    94  	} else {
    95  		start = m.highestStream + 4
    96  	}
    97  	for newID := start; newID <= id; newID += 4 {
    98  		m.streams[newID] = m.newStream(newID)
    99  		m.cond.Signal()
   100  	}
   101  	m.highestStream = id
   102  	s := m.streams[id]
   103  	m.mutex.Unlock()
   104  	return s, nil
   105  }
   106  
   107  func (m *incomingUniStreamsMap) DeleteStream(id protocol.StreamID) error {
   108  	m.mutex.Lock()
   109  	defer m.mutex.Unlock()
   110  
   111  	if _, ok := m.streams[id]; !ok {
   112  		return fmt.Errorf("Tried to delete unknown stream %d", id)
   113  	}
   114  	delete(m.streams, id)
   115  	// queue a MAX_STREAM_ID frame, giving the peer the option to open a new stream
   116  	if numNewStreams := m.maxNumStreams - len(m.streams); numNewStreams > 0 {
   117  		m.maxStream = m.highestStream + protocol.StreamID(numNewStreams*4)
   118  		m.queueMaxStreamID(&wire.MaxStreamIDFrame{StreamID: m.maxStream})
   119  	}
   120  	return nil
   121  }
   122  
   123  func (m *incomingUniStreamsMap) CloseWithError(err error) {
   124  	m.mutex.Lock()
   125  	m.closeErr = err
   126  	for _, str := range m.streams {
   127  		str.closeForShutdown(err)
   128  	}
   129  	m.mutex.Unlock()
   130  	m.cond.Broadcast()
   131  }