@@ -27,15 +27,16 @@ type Conn struct {
27
27
conn net.Conn
28
28
isClient bool
29
29
30
+ // handshakeStatus is 1 if the connection is currently transferring
31
+ // application data (i.e. is not currently processing a handshake).
32
+ // This field is only to be accessed with sync/atomic.
33
+ handshakeStatus uint32
30
34
// constant after handshake; protected by handshakeMutex
31
35
handshakeMutex sync.Mutex
32
36
handshakeErr error // error resulting from handshake
33
37
vers uint16 // TLS version
34
38
haveVers bool // version has been negotiated
35
39
config * Config // configuration passed to constructor
36
- // handshakeComplete is true if the connection is currently transferring
37
- // application data (i.e. is not currently processing a handshake).
38
- handshakeComplete bool
39
40
// handshakes counts the number of handshakes performed on the
40
41
// connection so far. If renegotiation is disabled then this is either
41
42
// zero or one.
@@ -571,12 +572,12 @@ func (c *Conn) readRecord(want recordType) error {
571
572
c .sendAlert (alertInternalError )
572
573
return c .in .setErrorLocked (errors .New ("tls: unknown record type requested" ))
573
574
case recordTypeHandshake , recordTypeChangeCipherSpec :
574
- if c .handshakeComplete {
575
+ if c .handshakeComplete () {
575
576
c .sendAlert (alertInternalError )
576
577
return c .in .setErrorLocked (errors .New ("tls: handshake or ChangeCipherSpec requested while not in handshake" ))
577
578
}
578
579
case recordTypeApplicationData :
579
- if ! c .handshakeComplete {
580
+ if ! c .handshakeComplete () {
580
581
c .sendAlert (alertInternalError )
581
582
return c .in .setErrorLocked (errors .New ("tls: application data record requested while in handshake" ))
582
583
}
@@ -1048,7 +1049,7 @@ func (c *Conn) Write(b []byte) (int, error) {
1048
1049
return 0 , err
1049
1050
}
1050
1051
1051
- if ! c .handshakeComplete {
1052
+ if ! c .handshakeComplete () {
1052
1053
return 0 , alertInternalError
1053
1054
}
1054
1055
@@ -1114,7 +1115,7 @@ func (c *Conn) handleRenegotiation() error {
1114
1115
c .handshakeMutex .Lock ()
1115
1116
defer c .handshakeMutex .Unlock ()
1116
1117
1117
- c . handshakeComplete = false
1118
+ atomic . StoreUint32 ( & c . handshakeStatus , 0 )
1118
1119
if c .handshakeErr = c .clientHandshake (); c .handshakeErr == nil {
1119
1120
c .handshakes ++
1120
1121
}
@@ -1215,11 +1216,9 @@ func (c *Conn) Close() error {
1215
1216
1216
1217
var alertErr error
1217
1218
1218
- c .handshakeMutex .Lock ()
1219
- if c .handshakeComplete {
1219
+ if c .handshakeComplete () {
1220
1220
alertErr = c .closeNotify ()
1221
1221
}
1222
- c .handshakeMutex .Unlock ()
1223
1222
1224
1223
if err := c .conn .Close (); err != nil {
1225
1224
return err
@@ -1233,9 +1232,7 @@ var errEarlyCloseWrite = errors.New("tls: CloseWrite called before handshake com
1233
1232
// called once the handshake has completed and does not call CloseWrite on the
1234
1233
// underlying connection. Most callers should just use Close.
1235
1234
func (c * Conn ) CloseWrite () error {
1236
- c .handshakeMutex .Lock ()
1237
- defer c .handshakeMutex .Unlock ()
1238
- if ! c .handshakeComplete {
1235
+ if ! c .handshakeComplete () {
1239
1236
return errEarlyCloseWrite
1240
1237
}
1241
1238
@@ -1264,7 +1261,7 @@ func (c *Conn) Handshake() error {
1264
1261
if err := c .handshakeErr ; err != nil {
1265
1262
return err
1266
1263
}
1267
- if c .handshakeComplete {
1264
+ if c .handshakeComplete () {
1268
1265
return nil
1269
1266
}
1270
1267
@@ -1284,7 +1281,7 @@ func (c *Conn) Handshake() error {
1284
1281
c .flush ()
1285
1282
}
1286
1283
1287
- if c .handshakeErr == nil && ! c .handshakeComplete {
1284
+ if c .handshakeErr == nil && ! c .handshakeComplete () {
1288
1285
panic ("handshake should have had a result." )
1289
1286
}
1290
1287
@@ -1297,10 +1294,10 @@ func (c *Conn) ConnectionState() ConnectionState {
1297
1294
defer c .handshakeMutex .Unlock ()
1298
1295
1299
1296
var state ConnectionState
1300
- state .HandshakeComplete = c .handshakeComplete
1297
+ state .HandshakeComplete = c .handshakeComplete ()
1301
1298
state .ServerName = c .serverName
1302
1299
1303
- if c . handshakeComplete {
1300
+ if state . HandshakeComplete {
1304
1301
state .Version = c .vers
1305
1302
state .NegotiatedProtocol = c .clientProtocol
1306
1303
state .DidResume = c .didResume
@@ -1345,11 +1342,15 @@ func (c *Conn) VerifyHostname(host string) error {
1345
1342
if ! c .isClient {
1346
1343
return errors .New ("tls: VerifyHostname called on TLS server connection" )
1347
1344
}
1348
- if ! c .handshakeComplete {
1345
+ if ! c .handshakeComplete () {
1349
1346
return errors .New ("tls: handshake has not yet been performed" )
1350
1347
}
1351
1348
if len (c .verifiedChains ) == 0 {
1352
1349
return errors .New ("tls: handshake did not verify certificate chain" )
1353
1350
}
1354
1351
return c .peerCertificates [0 ].VerifyHostname (host )
1355
1352
}
1353
+
1354
+ func (c * Conn ) handshakeComplete () bool {
1355
+ return atomic .LoadUint32 (& c .handshakeStatus ) == 1
1356
+ }
0 commit comments