@@ -193,7 +193,11 @@ func (q *QUICConnection) runStream(quicStream quic.Stream) {
193193 // A call to close will simulate a close to the read-side, which will fail subsequent reads.
194194 noCloseStream := & nopCloserReadWriter {ReadWriteCloser : stream }
195195 if err := q .handleStream (ctx , noCloseStream ); err != nil {
196- q .logger .Err (err ).Msg ("Failed to handle QUIC stream" )
196+ q .logger .Debug ().Err (err ).Msg ("Failed to handle QUIC stream" )
197+
198+ // if we received an error at this level, then close write side of stream with an error, which will result in
199+ // RST_STREAM frame.
200+ quicStream .CancelWrite (0 )
197201 }
198202}
199203
@@ -226,43 +230,60 @@ func (q *QUICConnection) handleDataStream(ctx context.Context, stream *quicpogs.
226230 return err
227231 }
228232
229- if err := q .dispatchRequest (ctx , stream , err , request ); err != nil {
230- _ = stream .WriteConnectResponseData (err )
233+ if err , connectResponseSent := q .dispatchRequest (ctx , stream , err , request ); err != nil {
231234 q .logger .Err (err ).Str ("type" , request .Type .String ()).Str ("dest" , request .Dest ).Msg ("Request failed" )
235+
236+ // if the connectResponse was already sent and we had an error, we need to propagate it up, so that the stream is
237+ // closed with an RST_STREAM frame
238+ if connectResponseSent {
239+ return err
240+ }
241+
242+ if writeRespErr := stream .WriteConnectResponseData (err ); writeRespErr != nil {
243+ return writeRespErr
244+ }
232245 }
233246
234247 return nil
235248}
236249
237- func (q * QUICConnection ) dispatchRequest (ctx context.Context , stream * quicpogs.RequestServerStream , err error , request * quicpogs.ConnectRequest ) error {
250+ // dispatchRequest will dispatch the request depending on the type and returns an error if it occurs.
251+ // More importantly, it also tells if the during processing of the request the ConnectResponse metadata was sent downstream.
252+ // This is important since it informs
253+ func (q * QUICConnection ) dispatchRequest (ctx context.Context , stream * quicpogs.RequestServerStream , err error , request * quicpogs.ConnectRequest ) (error , bool ) {
238254 originProxy , err := q .orchestrator .GetOriginProxy ()
239255 if err != nil {
240- return err
256+ return err , false
241257 }
242258
243259 switch request .Type {
244260 case quicpogs .ConnectionTypeHTTP , quicpogs .ConnectionTypeWebsocket :
245261 tracedReq , err := buildHTTPRequest (ctx , request , stream , q .logger )
246262 if err != nil {
247- return err
263+ return err , false
248264 }
249265 w := newHTTPResponseAdapter (stream )
250- return originProxy .ProxyHTTP (w , tracedReq , request .Type == quicpogs .ConnectionTypeWebsocket )
266+ return originProxy .ProxyHTTP (& w , tracedReq , request .Type == quicpogs .ConnectionTypeWebsocket ), w . connectResponseSent
251267
252268 case quicpogs .ConnectionTypeTCP :
253- rwa := & streamReadWriteAcker {stream }
269+ rwa := & streamReadWriteAcker {RequestServerStream : stream }
254270 metadata := request .MetadataMap ()
255271 return originProxy .ProxyTCP (ctx , rwa , & TCPRequest {
256272 Dest : request .Dest ,
257273 FlowID : metadata [QUICMetadataFlowID ],
258274 CfTraceID : metadata [tracing .TracerContextName ],
259- })
275+ }), rwa .connectResponseSent
276+ default :
277+ return errors .Errorf ("unsupported error type: %s" , request .Type ), false
260278 }
261- return nil
262279}
263280
264281func (q * QUICConnection ) handleRPCStream (rpcStream * quicpogs.RPCServerStream ) error {
265- return rpcStream .Serve (q , q , q .logger )
282+ if err := rpcStream .Serve (q , q , q .logger ); err != nil {
283+ q .logger .Err (err ).Msg ("failed handling RPC stream" )
284+ }
285+
286+ return nil
266287}
267288
268289// RegisterUdpSession is the RPC method invoked by edge to register and run a session
@@ -357,6 +378,7 @@ func (q *QUICConnection) UpdateConfiguration(ctx context.Context, version int32,
357378// the client.
358379type streamReadWriteAcker struct {
359380 * quicpogs.RequestServerStream
381+ connectResponseSent bool
360382}
361383
362384// AckConnection acks response back to the proxy.
@@ -365,23 +387,25 @@ func (s *streamReadWriteAcker) AckConnection(tracePropagation string) error {
365387 Key : tracing .CanonicalCloudflaredTracingHeader ,
366388 Val : tracePropagation ,
367389 }
390+ s .connectResponseSent = true
368391 return s .WriteConnectResponseData (nil , metadata )
369392}
370393
371394// httpResponseAdapter translates responses written by the HTTP Proxy into ones that can be used in QUIC.
372395type httpResponseAdapter struct {
373396 * quicpogs.RequestServerStream
397+ connectResponseSent bool
374398}
375399
376400func newHTTPResponseAdapter (s * quicpogs.RequestServerStream ) httpResponseAdapter {
377- return httpResponseAdapter {s }
401+ return httpResponseAdapter {RequestServerStream : s }
378402}
379403
380- func (hrw httpResponseAdapter ) AddTrailer (trailerName , trailerValue string ) {
404+ func (hrw * httpResponseAdapter ) AddTrailer (trailerName , trailerValue string ) {
381405 // we do not support trailers over QUIC
382406}
383407
384- func (hrw httpResponseAdapter ) WriteRespHeaders (status int , header http.Header ) error {
408+ func (hrw * httpResponseAdapter ) WriteRespHeaders (status int , header http.Header ) error {
385409 metadata := make ([]quicpogs.Metadata , 0 )
386410 metadata = append (metadata , quicpogs.Metadata {Key : "HttpStatus" , Val : strconv .Itoa (status )})
387411 for k , vv := range header {
@@ -390,13 +414,19 @@ func (hrw httpResponseAdapter) WriteRespHeaders(status int, header http.Header)
390414 metadata = append (metadata , quicpogs.Metadata {Key : httpHeaderKey , Val : v })
391415 }
392416 }
417+
393418 return hrw .WriteConnectResponseData (nil , metadata ... )
394419}
395420
396- func (hrw httpResponseAdapter ) WriteErrorResponse (err error ) {
421+ func (hrw * httpResponseAdapter ) WriteErrorResponse (err error ) {
397422 hrw .WriteConnectResponseData (err , quicpogs.Metadata {Key : "HttpStatus" , Val : strconv .Itoa (http .StatusBadGateway )})
398423}
399424
425+ func (hrw * httpResponseAdapter ) WriteConnectResponseData (respErr error , metadata ... quicpogs.Metadata ) error {
426+ hrw .connectResponseSent = true
427+ return hrw .RequestServerStream .WriteConnectResponseData (respErr , metadata ... )
428+ }
429+
400430func buildHTTPRequest (
401431 ctx context.Context ,
402432 connectRequest * quicpogs.ConnectRequest ,
0 commit comments