@@ -889,3 +889,134 @@ type utlsConnExtraFields struct {
889889
890890 sessionController * sessionController
891891}
892+
893+ // Read reads data from the connection.
894+ //
895+ // As Read calls [Conn.Handshake], in order to prevent indefinite blocking a deadline
896+ // must be set for both Read and [Conn.Write] before Read is called when the handshake
897+ // has not yet completed. See [Conn.SetDeadline], [Conn.SetReadDeadline], and
898+ // [Conn.SetWriteDeadline].
899+ func (c * UConn ) Read (b []byte ) (int , error ) {
900+ if err := c .Handshake (); err != nil {
901+ return 0 , err
902+ }
903+ if len (b ) == 0 {
904+ // Put this after Handshake, in case people were calling
905+ // Read(nil) for the side effect of the Handshake.
906+ return 0 , nil
907+ }
908+
909+ c .in .Lock ()
910+ defer c .in .Unlock ()
911+
912+ for c .input .Len () == 0 {
913+ if err := c .readRecord (); err != nil {
914+ return 0 , err
915+ }
916+ for c .hand .Len () > 0 {
917+ if err := c .handlePostHandshakeMessage (); err != nil {
918+ return 0 , err
919+ }
920+ }
921+ }
922+
923+ n , _ := c .input .Read (b )
924+
925+ // If a close-notify alert is waiting, read it so that we can return (n,
926+ // EOF) instead of (n, nil), to signal to the HTTP response reading
927+ // goroutine that the connection is now closed. This eliminates a race
928+ // where the HTTP response reading goroutine would otherwise not observe
929+ // the EOF until its next read, by which time a client goroutine might
930+ // have already tried to reuse the HTTP connection for a new request.
931+ // See https://golang.org/cl/76400046 and https://golang.org/issue/3514
932+ if n != 0 && c .input .Len () == 0 && c .rawInput .Len () > 0 &&
933+ recordType (c .rawInput .Bytes ()[0 ]) == recordTypeAlert {
934+ if err := c .readRecord (); err != nil {
935+ return n , err // will be io.EOF on closeNotify
936+ }
937+ }
938+
939+ return n , nil
940+ }
941+
942+ // handleRenegotiation processes a HelloRequest handshake message.
943+ func (c * UConn ) handleRenegotiation () error {
944+ if c .vers == VersionTLS13 {
945+ return errors .New ("tls: internal error: unexpected renegotiation" )
946+ }
947+
948+ msg , err := c .readHandshake (nil )
949+ if err != nil {
950+ return err
951+ }
952+
953+ helloReq , ok := msg .(* helloRequestMsg )
954+ if ! ok {
955+ c .sendAlert (alertUnexpectedMessage )
956+ return unexpectedMessageError (helloReq , msg )
957+ }
958+
959+ if ! c .isClient {
960+ return c .sendAlert (alertNoRenegotiation )
961+ }
962+
963+ switch c .config .Renegotiation {
964+ case RenegotiateNever :
965+ return c .sendAlert (alertNoRenegotiation )
966+ case RenegotiateOnceAsClient :
967+ if c .handshakes > 1 {
968+ return c .sendAlert (alertNoRenegotiation )
969+ }
970+ case RenegotiateFreelyAsClient :
971+ // Ok.
972+ default :
973+ c .sendAlert (alertInternalError )
974+ return errors .New ("tls: unknown Renegotiation value" )
975+ }
976+
977+ c .handshakeMutex .Lock ()
978+ defer c .handshakeMutex .Unlock ()
979+
980+ c .isHandshakeComplete .Store (false )
981+
982+ // [uTLS section begins]
983+ if err = c .BuildHandshakeState (); err != nil {
984+ return err
985+ }
986+ // [uTLS section ends]
987+ if c .handshakeErr = c .clientHandshake (context .Background ()); c .handshakeErr == nil {
988+ c .handshakes ++
989+ }
990+ return c .handshakeErr
991+ }
992+
993+ // handlePostHandshakeMessage processes a handshake message arrived after the
994+ // handshake is complete. Up to TLS 1.2, it indicates the start of a renegotiation.
995+ func (c * UConn ) handlePostHandshakeMessage () error {
996+ if c .vers != VersionTLS13 {
997+ return c .handleRenegotiation ()
998+ }
999+
1000+ msg , err := c .readHandshake (nil )
1001+ if err != nil {
1002+ return err
1003+ }
1004+ c .retryCount ++
1005+ if c .retryCount > maxUselessRecords {
1006+ c .sendAlert (alertUnexpectedMessage )
1007+ return c .in .setErrorLocked (errors .New ("tls: too many non-advancing records" ))
1008+ }
1009+
1010+ switch msg := msg .(type ) {
1011+ case * newSessionTicketMsgTLS13 :
1012+ return c .handleNewSessionTicket (msg )
1013+ case * keyUpdateMsg :
1014+ return c .handleKeyUpdate (msg )
1015+ }
1016+ // The QUIC layer is supposed to treat an unexpected post-handshake CertificateRequest
1017+ // as a QUIC-level PROTOCOL_VIOLATION error (RFC 9001, Section 4.4). Returning an
1018+ // unexpected_message alert here doesn't provide it with enough information to distinguish
1019+ // this condition from other unexpected messages. This is probably fine.
1020+ c .sendAlert (alertUnexpectedMessage )
1021+ return fmt .Errorf ("tls: received unexpected handshake message of type %T" , msg )
1022+ }
0 commit comments