Source file src/net/http/internal/http3/conn_test.go

     1  // Copyright 2024 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  package http3
     6  
     7  import (
     8  	"errors"
     9  	"testing"
    10  	"testing/synctest"
    11  
    12  	"golang.org/x/net/quic"
    13  )
    14  
    15  // Tests which apply to both client and server connections.
    16  
    17  func TestConnCreatesControlStream(t *testing.T) {
    18  	runConnTest(t, func(t testing.TB, tc *testQUICConn) {
    19  		controlStream := tc.wantStream(streamTypeControl)
    20  		controlStream.wantFrameHeader(
    21  			"server sends SETTINGS frame on control stream",
    22  			frameTypeSettings)
    23  		controlStream.discardFrame()
    24  	})
    25  }
    26  
    27  func TestConnUnknownUnidirectionalStream(t *testing.T) {
    28  	// "Recipients of unknown stream types MUST either abort reading of the stream
    29  	// or discard incoming data without further processing."
    30  	// https://www.rfc-editor.org/rfc/rfc9114.html#section-6.2-7
    31  	runConnTest(t, func(t testing.TB, tc *testQUICConn) {
    32  		st := tc.newStream(0x21) // reserved stream type
    33  
    34  		// The endpoint should send a STOP_SENDING for this stream,
    35  		// but it should not close the connection.
    36  		synctest.Wait()
    37  		wantErr := quic.StreamError(errH3StreamCreationError)
    38  		if _, err := st.Write([]byte("hello")); !errors.Is(err, wantErr) {
    39  			t.Fatalf("write to send-only stream with an unknown type returned error %v; want %v", err, wantErr)
    40  		}
    41  		tc.wantNotClosed("after receiving unknown unidirectional stream type")
    42  	})
    43  }
    44  
    45  func TestConnUnknownSettings(t *testing.T) {
    46  	// "An implementation MUST ignore any [settings] parameter with
    47  	// an identifier it does not understand."
    48  	// https://www.rfc-editor.org/rfc/rfc9114.html#section-7.2.4-9
    49  	runConnTest(t, func(t testing.TB, tc *testQUICConn) {
    50  		controlStream := tc.newStream(streamTypeControl)
    51  		controlStream.writeSettings(0x1f+0x21, 0) // reserved settings type
    52  		controlStream.Flush()
    53  		tc.wantNotClosed("after receiving unknown settings")
    54  	})
    55  }
    56  
    57  func TestConnInvalidSettings(t *testing.T) {
    58  	// "These reserved settings MUST NOT be sent, and their receipt MUST
    59  	// be treated as a connection error of type H3_SETTINGS_ERROR."
    60  	// https://www.rfc-editor.org/rfc/rfc9114.html#section-7.2.4.1-5
    61  	runConnTest(t, func(t testing.TB, tc *testQUICConn) {
    62  		controlStream := tc.newStream(streamTypeControl)
    63  		controlStream.writeSettings(0x02, 0) // HTTP/2 SETTINGS_ENABLE_PUSH
    64  		controlStream.Flush()
    65  		tc.wantClosed("invalid setting", errH3SettingsError)
    66  	})
    67  }
    68  
    69  func TestConnDuplicateStream(t *testing.T) {
    70  	for _, stype := range []streamType{
    71  		streamTypeControl,
    72  		streamTypeEncoder,
    73  		streamTypeDecoder,
    74  	} {
    75  		t.Run(stype.String(), func(t *testing.T) {
    76  			runConnTest(t, func(t testing.TB, tc *testQUICConn) {
    77  				_ = tc.newStream(stype)
    78  				tc.wantNotClosed("after creating one " + stype.String() + " stream")
    79  
    80  				// Opening a second control, encoder, or decoder stream
    81  				// is a protocol violation.
    82  				_ = tc.newStream(stype)
    83  				tc.wantClosed("duplicate stream", errH3StreamCreationError)
    84  			})
    85  		})
    86  	}
    87  }
    88  
    89  func TestConnUnknownFrames(t *testing.T) {
    90  	for _, stype := range []streamType{
    91  		streamTypeControl,
    92  	} {
    93  		t.Run(stype.String(), func(t *testing.T) {
    94  			runConnTest(t, func(t testing.TB, tc *testQUICConn) {
    95  				st := tc.newStream(stype)
    96  
    97  				if stype == streamTypeControl {
    98  					// First frame on the control stream must be settings.
    99  					st.writeVarint(int64(frameTypeSettings))
   100  					st.writeVarint(0) // size
   101  				}
   102  
   103  				data := "frame content"
   104  				st.writeVarint(0x1f + 0x21)      // reserved frame type
   105  				st.writeVarint(int64(len(data))) // size
   106  				st.Write([]byte(data))
   107  				st.Flush()
   108  
   109  				tc.wantNotClosed("after writing unknown frame")
   110  			})
   111  		})
   112  	}
   113  }
   114  
   115  func TestConnInvalidFrames(t *testing.T) {
   116  	runConnTest(t, func(t testing.TB, tc *testQUICConn) {
   117  		control := tc.newStream(streamTypeControl)
   118  
   119  		// SETTINGS frame.
   120  		control.writeVarint(int64(frameTypeSettings))
   121  		control.writeVarint(0) // size
   122  
   123  		// DATA frame (invalid on the control stream).
   124  		control.writeVarint(int64(frameTypeData))
   125  		control.writeVarint(0) // size
   126  		control.Flush()
   127  		tc.wantClosed("after writing DATA frame to control stream", errH3FrameUnexpected)
   128  	})
   129  }
   130  
   131  func TestConnPeerCreatesBadUnidirectionalStream(t *testing.T) {
   132  	runConnTest(t, func(t testing.TB, tc *testQUICConn) {
   133  		// Create and close a stream without sending the unidirectional stream header.
   134  		qs, err := tc.qconn.NewSendOnlyStream(canceledCtx)
   135  		if err != nil {
   136  			t.Fatal(err)
   137  		}
   138  		st := newTestQUICStream(tc.t, newStream(qs))
   139  		st.Close()
   140  
   141  		tc.wantClosed("after peer creates and closes uni stream", errH3StreamCreationError)
   142  	})
   143  }
   144  
   145  func runConnTest(t *testing.T, f func(testing.TB, *testQUICConn)) {
   146  	t.Helper()
   147  	synctestSubtest(t, "client", func(t *testing.T) {
   148  		tc := newTestClientConn(t)
   149  		f(t, tc.testQUICConn)
   150  	})
   151  	synctestSubtest(t, "server", func(t *testing.T) {
   152  		ts := newTestServer(t, nil)
   153  		tc := ts.connect()
   154  		f(t, tc.testQUICConn)
   155  	})
   156  }
   157  

View as plain text