...

Source file src/golang.org/x/net/internal/quic/stream_limits_test.go

Documentation: golang.org/x/net/internal/quic

     1  // Copyright 2023 The Go 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  //go:build go1.21
     6  
     7  package quic
     8  
     9  import (
    10  	"context"
    11  	"crypto/tls"
    12  	"testing"
    13  )
    14  
    15  func TestStreamLimitNewStreamBlocked(t *testing.T) {
    16  	// "An endpoint that receives a frame with a stream ID exceeding the limit
    17  	// it has sent MUST treat this as a connection error of type STREAM_LIMIT_ERROR [...]"
    18  	// https://www.rfc-editor.org/rfc/rfc9000#section-4.6-3
    19  	testStreamTypes(t, "", func(t *testing.T, styp streamType) {
    20  		ctx := canceledContext()
    21  		tc := newTestConn(t, clientSide,
    22  			permissiveTransportParameters,
    23  			func(p *transportParameters) {
    24  				p.initialMaxStreamsBidi = 0
    25  				p.initialMaxStreamsUni = 0
    26  			})
    27  		tc.handshake()
    28  		tc.ignoreFrame(frameTypeAck)
    29  		opening := runAsync(tc, func(ctx context.Context) (*Stream, error) {
    30  			return tc.conn.newLocalStream(ctx, styp)
    31  		})
    32  		if _, err := opening.result(); err != errNotDone {
    33  			t.Fatalf("new stream blocked by limit: %v, want errNotDone", err)
    34  		}
    35  		tc.writeFrames(packetType1RTT, debugFrameMaxStreams{
    36  			streamType: styp,
    37  			max:        1,
    38  		})
    39  		if _, err := opening.result(); err != nil {
    40  			t.Fatalf("new stream not created after limit raised: %v", err)
    41  		}
    42  		if _, err := tc.conn.newLocalStream(ctx, styp); err == nil {
    43  			t.Fatalf("new stream blocked by raised limit: %v, want error", err)
    44  		}
    45  	})
    46  }
    47  
    48  func TestStreamLimitMaxStreamsDecreases(t *testing.T) {
    49  	// "MAX_STREAMS frames that do not increase the stream limit MUST be ignored."
    50  	// https://www.rfc-editor.org/rfc/rfc9000#section-4.6-4
    51  	testStreamTypes(t, "", func(t *testing.T, styp streamType) {
    52  		ctx := canceledContext()
    53  		tc := newTestConn(t, clientSide,
    54  			permissiveTransportParameters,
    55  			func(p *transportParameters) {
    56  				p.initialMaxStreamsBidi = 0
    57  				p.initialMaxStreamsUni = 0
    58  			})
    59  		tc.handshake()
    60  		tc.ignoreFrame(frameTypeAck)
    61  		tc.writeFrames(packetType1RTT, debugFrameMaxStreams{
    62  			streamType: styp,
    63  			max:        2,
    64  		})
    65  		tc.writeFrames(packetType1RTT, debugFrameMaxStreams{
    66  			streamType: styp,
    67  			max:        1,
    68  		})
    69  		if _, err := tc.conn.newLocalStream(ctx, styp); err != nil {
    70  			t.Fatalf("open stream 1, limit 2, got error: %v", err)
    71  		}
    72  		if _, err := tc.conn.newLocalStream(ctx, styp); err != nil {
    73  			t.Fatalf("open stream 2, limit 2, got error: %v", err)
    74  		}
    75  		if _, err := tc.conn.newLocalStream(ctx, styp); err == nil {
    76  			t.Fatalf("open stream 3, limit 2, got error: %v", err)
    77  		}
    78  	})
    79  }
    80  
    81  func TestStreamLimitViolated(t *testing.T) {
    82  	testStreamTypes(t, "", func(t *testing.T, styp streamType) {
    83  		tc := newTestConn(t, serverSide,
    84  			func(c *Config) {
    85  				if styp == bidiStream {
    86  					c.MaxBidiRemoteStreams = 10
    87  				} else {
    88  					c.MaxUniRemoteStreams = 10
    89  				}
    90  			})
    91  		tc.handshake()
    92  		tc.ignoreFrame(frameTypeAck)
    93  		tc.writeFrames(packetType1RTT, debugFrameStream{
    94  			id: newStreamID(clientSide, styp, 9),
    95  		})
    96  		tc.wantIdle("stream number 9 is within the limit")
    97  		tc.writeFrames(packetType1RTT, debugFrameStream{
    98  			id: newStreamID(clientSide, styp, 10),
    99  		})
   100  		tc.wantFrame("stream number 10 is beyond the limit",
   101  			packetType1RTT, debugFrameConnectionCloseTransport{
   102  				code: errStreamLimit,
   103  			},
   104  		)
   105  	})
   106  }
   107  
   108  func TestStreamLimitImplicitStreams(t *testing.T) {
   109  	testStreamTypes(t, "", func(t *testing.T, styp streamType) {
   110  		tc := newTestConn(t, serverSide,
   111  			func(c *Config) {
   112  				c.MaxBidiRemoteStreams = 1 << 60
   113  				c.MaxUniRemoteStreams = 1 << 60
   114  			})
   115  		tc.handshake()
   116  		tc.ignoreFrame(frameTypeAck)
   117  		if got, want := tc.sentTransportParameters.initialMaxStreamsBidi, int64(implicitStreamLimit); got != want {
   118  			t.Errorf("sent initial_max_streams_bidi = %v, want %v", got, want)
   119  		}
   120  		if got, want := tc.sentTransportParameters.initialMaxStreamsUni, int64(implicitStreamLimit); got != want {
   121  			t.Errorf("sent initial_max_streams_uni = %v, want %v", got, want)
   122  		}
   123  
   124  		// Create stream 0.
   125  		tc.writeFrames(packetType1RTT, debugFrameStream{
   126  			id: newStreamID(clientSide, styp, 0),
   127  		})
   128  		tc.wantIdle("max streams not increased enough to send a new frame")
   129  
   130  		// Create streams [0, implicitStreamLimit).
   131  		tc.writeFrames(packetType1RTT, debugFrameStream{
   132  			id: newStreamID(clientSide, styp, implicitStreamLimit-1),
   133  		})
   134  		tc.wantFrame("max streams increases to implicit stream limit",
   135  			packetType1RTT, debugFrameMaxStreams{
   136  				streamType: styp,
   137  				max:        2 * implicitStreamLimit,
   138  			})
   139  
   140  		// Create a stream past the limit.
   141  		tc.writeFrames(packetType1RTT, debugFrameStream{
   142  			id: newStreamID(clientSide, styp, 2*implicitStreamLimit),
   143  		})
   144  		tc.wantFrame("stream is past the limit",
   145  			packetType1RTT, debugFrameConnectionCloseTransport{
   146  				code: errStreamLimit,
   147  			},
   148  		)
   149  	})
   150  }
   151  
   152  func TestStreamLimitMaxStreamsTransportParameterTooLarge(t *testing.T) {
   153  	// "If a max_streams transport parameter [...] is received with
   154  	// a value greater than 2^60 [...] the connection MUST be closed
   155  	// immediately with a connection error of type TRANSPORT_PARAMETER_ERROR [...]"
   156  	// https://www.rfc-editor.org/rfc/rfc9000#section-4.6-2
   157  	testStreamTypes(t, "", func(t *testing.T, styp streamType) {
   158  		tc := newTestConn(t, serverSide,
   159  			func(p *transportParameters) {
   160  				if styp == bidiStream {
   161  					p.initialMaxStreamsBidi = 1<<60 + 1
   162  				} else {
   163  					p.initialMaxStreamsUni = 1<<60 + 1
   164  				}
   165  			})
   166  		tc.writeFrames(packetTypeInitial, debugFrameCrypto{
   167  			data: tc.cryptoDataIn[tls.QUICEncryptionLevelInitial],
   168  		})
   169  		tc.wantFrame("max streams transport parameter is too large",
   170  			packetTypeInitial, debugFrameConnectionCloseTransport{
   171  				code: errTransportParameter,
   172  			},
   173  		)
   174  	})
   175  }
   176  
   177  func TestStreamLimitMaxStreamsFrameTooLarge(t *testing.T) {
   178  	// "If [...] a MAX_STREAMS frame is received with a value
   179  	// greater than 2^60 [...] the connection MUST be closed immediately
   180  	// with a connection error [...] of type FRAME_ENCODING_ERROR [...]"
   181  	// https://www.rfc-editor.org/rfc/rfc9000#section-4.6-2
   182  	testStreamTypes(t, "", func(t *testing.T, styp streamType) {
   183  		tc := newTestConn(t, serverSide)
   184  		tc.handshake()
   185  		tc.writeFrames(packetTypeInitial,
   186  			debugFrameCrypto{
   187  				data: tc.cryptoDataIn[tls.QUICEncryptionLevelInitial],
   188  			})
   189  		tc.writeFrames(packetType1RTT, debugFrameMaxStreams{
   190  			streamType: styp,
   191  			max:        1<<60 + 1,
   192  		})
   193  		tc.wantFrame("MAX_STREAMS value is too large",
   194  			packetType1RTT, debugFrameConnectionCloseTransport{
   195  				code: errFrameEncoding,
   196  			},
   197  		)
   198  	})
   199  }
   200  
   201  func TestStreamLimitSendUpdatesMaxStreams(t *testing.T) {
   202  	testStreamTypes(t, "", func(t *testing.T, styp streamType) {
   203  		ctx := canceledContext()
   204  		tc := newTestConn(t, serverSide, func(c *Config) {
   205  			if styp == uniStream {
   206  				c.MaxUniRemoteStreams = 4
   207  				c.MaxBidiRemoteStreams = 0
   208  			} else {
   209  				c.MaxUniRemoteStreams = 0
   210  				c.MaxBidiRemoteStreams = 4
   211  			}
   212  		})
   213  		tc.handshake()
   214  		tc.ignoreFrame(frameTypeAck)
   215  		var streams []*Stream
   216  		for i := 0; i < 4; i++ {
   217  			tc.writeFrames(packetType1RTT, debugFrameStream{
   218  				id:  newStreamID(clientSide, styp, int64(i)),
   219  				fin: true,
   220  			})
   221  			s, err := tc.conn.AcceptStream(ctx)
   222  			if err != nil {
   223  				t.Fatalf("AcceptStream = %v", err)
   224  			}
   225  			streams = append(streams, s)
   226  		}
   227  		streams[3].CloseContext(ctx)
   228  		if styp == bidiStream {
   229  			tc.wantFrame("stream is closed",
   230  				packetType1RTT, debugFrameStream{
   231  					id:   streams[3].id,
   232  					fin:  true,
   233  					data: []byte{},
   234  				})
   235  			tc.writeAckForAll()
   236  		}
   237  		tc.wantFrame("closing a stream when peer is at limit immediately extends the limit",
   238  			packetType1RTT, debugFrameMaxStreams{
   239  				streamType: styp,
   240  				max:        5,
   241  			})
   242  	})
   243  }
   244  
   245  func TestStreamLimitStopSendingDoesNotUpdateMaxStreams(t *testing.T) {
   246  	tc, s := newTestConnAndRemoteStream(t, serverSide, bidiStream, func(c *Config) {
   247  		c.MaxBidiRemoteStreams = 1
   248  	})
   249  	tc.writeFrames(packetType1RTT, debugFrameStream{
   250  		id:  s.id,
   251  		fin: true,
   252  	})
   253  	s.CloseRead()
   254  	tc.writeFrames(packetType1RTT, debugFrameStopSending{
   255  		id: s.id,
   256  	})
   257  	tc.wantFrame("recieved STOP_SENDING, send RESET_STREAM",
   258  		packetType1RTT, debugFrameResetStream{
   259  			id: s.id,
   260  		})
   261  	tc.writeAckForAll()
   262  	tc.wantIdle("MAX_STREAMS is not extended until the user fully closes the stream")
   263  	s.CloseWrite()
   264  	tc.wantFrame("user closing the stream triggers MAX_STREAMS update",
   265  		packetType1RTT, debugFrameMaxStreams{
   266  			streamType: bidiStream,
   267  			max:        2,
   268  		})
   269  }
   270  

View as plain text