github.com/psiphon-labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/common/quic/gquic-go/stream.go (about) 1 package gquic 2 3 import ( 4 "net" 5 "sync" 6 "time" 7 8 "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/quic/gquic-go/internal/flowcontrol" 9 "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/quic/gquic-go/internal/protocol" 10 "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/quic/gquic-go/internal/wire" 11 ) 12 13 const ( 14 errorCodeStopping protocol.ApplicationErrorCode = 0 15 errorCodeStoppingGQUIC protocol.ApplicationErrorCode = 7 16 ) 17 18 // The streamSender is notified by the stream about various events. 19 type streamSender interface { 20 queueControlFrame(wire.Frame) 21 onHasStreamData(protocol.StreamID) 22 // must be called without holding the mutex that is acquired by closeForShutdown 23 onStreamCompleted(protocol.StreamID) 24 } 25 26 // Each of the both stream halves gets its own uniStreamSender. 27 // This is necessary in order to keep track when both halves have been completed. 28 type uniStreamSender struct { 29 streamSender 30 onStreamCompletedImpl func() 31 } 32 33 func (s *uniStreamSender) queueControlFrame(f wire.Frame) { 34 s.streamSender.queueControlFrame(f) 35 } 36 37 func (s *uniStreamSender) onHasStreamData(id protocol.StreamID) { 38 s.streamSender.onHasStreamData(id) 39 } 40 41 func (s *uniStreamSender) onStreamCompleted(protocol.StreamID) { 42 s.onStreamCompletedImpl() 43 } 44 45 var _ streamSender = &uniStreamSender{} 46 47 type streamI interface { 48 Stream 49 closeForShutdown(error) 50 // for receiving 51 handleStreamFrame(*wire.StreamFrame) error 52 handleRstStreamFrame(*wire.RstStreamFrame) error 53 getWindowUpdate() protocol.ByteCount 54 // for sending 55 hasData() bool 56 handleStopSendingFrame(*wire.StopSendingFrame) 57 popStreamFrame(maxBytes protocol.ByteCount) (*wire.StreamFrame, bool) 58 handleMaxStreamDataFrame(*wire.MaxStreamDataFrame) 59 } 60 61 var _ receiveStreamI = (streamI)(nil) 62 var _ sendStreamI = (streamI)(nil) 63 64 // A Stream assembles the data from StreamFrames and provides a super-convenient Read-Interface 65 // 66 // Read() and Write() may be called concurrently, but multiple calls to Read() or Write() individually must be synchronized manually. 67 type stream struct { 68 receiveStream 69 sendStream 70 71 completedMutex sync.Mutex 72 sender streamSender 73 receiveStreamCompleted bool 74 sendStreamCompleted bool 75 76 version protocol.VersionNumber 77 } 78 79 var _ Stream = &stream{} 80 81 type deadlineError struct{} 82 83 func (deadlineError) Error() string { return "deadline exceeded" } 84 func (deadlineError) Temporary() bool { return true } 85 func (deadlineError) Timeout() bool { return true } 86 87 var errDeadline net.Error = &deadlineError{} 88 89 type streamCanceledError struct { 90 error 91 errorCode protocol.ApplicationErrorCode 92 } 93 94 func (streamCanceledError) Canceled() bool { return true } 95 func (e streamCanceledError) ErrorCode() protocol.ApplicationErrorCode { return e.errorCode } 96 97 var _ StreamError = &streamCanceledError{} 98 99 // newStream creates a new Stream 100 func newStream(streamID protocol.StreamID, 101 sender streamSender, 102 flowController flowcontrol.StreamFlowController, 103 version protocol.VersionNumber, 104 ) *stream { 105 s := &stream{sender: sender, version: version} 106 senderForSendStream := &uniStreamSender{ 107 streamSender: sender, 108 onStreamCompletedImpl: func() { 109 s.completedMutex.Lock() 110 s.sendStreamCompleted = true 111 s.checkIfCompleted() 112 s.completedMutex.Unlock() 113 }, 114 } 115 s.sendStream = *newSendStream(streamID, senderForSendStream, flowController, version) 116 senderForReceiveStream := &uniStreamSender{ 117 streamSender: sender, 118 onStreamCompletedImpl: func() { 119 s.completedMutex.Lock() 120 s.receiveStreamCompleted = true 121 s.checkIfCompleted() 122 s.completedMutex.Unlock() 123 }, 124 } 125 s.receiveStream = *newReceiveStream(streamID, senderForReceiveStream, flowController, version) 126 return s 127 } 128 129 // need to define StreamID() here, since both receiveStream and readStream have a StreamID() 130 func (s *stream) StreamID() protocol.StreamID { 131 // the result is same for receiveStream and sendStream 132 return s.sendStream.StreamID() 133 } 134 135 func (s *stream) Close() error { 136 if err := s.sendStream.Close(); err != nil { 137 return err 138 } 139 // in gQUIC, we need to send a RST_STREAM with the final offset if CancelRead() was called 140 s.receiveStream.onClose(s.sendStream.getWriteOffset()) 141 return nil 142 } 143 144 func (s *stream) SetDeadline(t time.Time) error { 145 _ = s.SetReadDeadline(t) // SetReadDeadline never errors 146 _ = s.SetWriteDeadline(t) // SetWriteDeadline never errors 147 return nil 148 } 149 150 // CloseForShutdown closes a stream abruptly. 151 // It makes Read and Write unblock (and return the error) immediately. 152 // The peer will NOT be informed about this: the stream is closed without sending a FIN or RST. 153 func (s *stream) closeForShutdown(err error) { 154 s.sendStream.closeForShutdown(err) 155 s.receiveStream.closeForShutdown(err) 156 } 157 158 func (s *stream) handleRstStreamFrame(frame *wire.RstStreamFrame) error { 159 if err := s.receiveStream.handleRstStreamFrame(frame); err != nil { 160 return err 161 } 162 if !s.version.UsesIETFFrameFormat() { 163 s.handleStopSendingFrame(&wire.StopSendingFrame{ 164 StreamID: s.StreamID(), 165 ErrorCode: frame.ErrorCode, 166 }) 167 } 168 return nil 169 } 170 171 // checkIfCompleted is called from the uniStreamSender, when one of the stream halves is completed. 172 // It makes sure that the onStreamCompleted callback is only called if both receive and send side have completed. 173 func (s *stream) checkIfCompleted() { 174 if s.sendStreamCompleted && s.receiveStreamCompleted { 175 s.sender.onStreamCompleted(s.StreamID()) 176 } 177 }