mirror of
https://github.com/refraction-networking/utls.git
synced 2025-04-02 03:27:35 +03:00
📦 build: WebAssembly Transport Module
Modify slightly to make uTLS compatible with TinyGo and WATER. Signed-off-by: Gaukas Wang <i@gaukas.wang>
This commit is contained in:
parent
925bfb39ab
commit
513679377a
7 changed files with 405 additions and 211 deletions
100
conn.go
100
conn.go
|
@ -1503,106 +1503,6 @@ func (c *Conn) HandshakeContext(ctx context.Context) error {
|
|||
return c.handshakeContext(ctx)
|
||||
}
|
||||
|
||||
func (c *Conn) handshakeContext(ctx context.Context) (ret error) {
|
||||
// Fast sync/atomic-based exit if there is no handshake in flight and the
|
||||
// last one succeeded without an error. Avoids the expensive context setup
|
||||
// and mutex for most Read and Write calls.
|
||||
if c.isHandshakeComplete.Load() {
|
||||
return nil
|
||||
}
|
||||
|
||||
handshakeCtx, cancel := context.WithCancel(ctx)
|
||||
// Note: defer this before starting the "interrupter" goroutine
|
||||
// so that we can tell the difference between the input being canceled and
|
||||
// this cancellation. In the former case, we need to close the connection.
|
||||
defer cancel()
|
||||
|
||||
if c.quic != nil {
|
||||
c.quic.cancelc = handshakeCtx.Done()
|
||||
c.quic.cancel = cancel
|
||||
} else if ctx.Done() != nil {
|
||||
// Start the "interrupter" goroutine, if this context might be canceled.
|
||||
// (The background context cannot).
|
||||
//
|
||||
// The interrupter goroutine waits for the input context to be done and
|
||||
// closes the connection if this happens before the function returns.
|
||||
done := make(chan struct{})
|
||||
interruptRes := make(chan error, 1)
|
||||
defer func() {
|
||||
close(done)
|
||||
if ctxErr := <-interruptRes; ctxErr != nil {
|
||||
// Return context error to user.
|
||||
ret = ctxErr
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
select {
|
||||
case <-handshakeCtx.Done():
|
||||
// Close the connection, discarding the error
|
||||
_ = c.conn.Close()
|
||||
interruptRes <- handshakeCtx.Err()
|
||||
case <-done:
|
||||
interruptRes <- nil
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
c.handshakeMutex.Lock()
|
||||
defer c.handshakeMutex.Unlock()
|
||||
|
||||
if err := c.handshakeErr; err != nil {
|
||||
return err
|
||||
}
|
||||
if c.isHandshakeComplete.Load() {
|
||||
return nil
|
||||
}
|
||||
|
||||
c.in.Lock()
|
||||
defer c.in.Unlock()
|
||||
|
||||
c.handshakeErr = c.handshakeFn(handshakeCtx)
|
||||
if c.handshakeErr == nil {
|
||||
c.handshakes++
|
||||
} else {
|
||||
// If an error occurred during the handshake try to flush the
|
||||
// alert that might be left in the buffer.
|
||||
c.flush()
|
||||
}
|
||||
|
||||
if c.handshakeErr == nil && !c.isHandshakeComplete.Load() {
|
||||
c.handshakeErr = errors.New("tls: internal error: handshake should have had a result")
|
||||
}
|
||||
if c.handshakeErr != nil && c.isHandshakeComplete.Load() {
|
||||
panic("tls: internal error: handshake returned an error but is marked successful")
|
||||
}
|
||||
|
||||
if c.quic != nil {
|
||||
if c.handshakeErr == nil {
|
||||
c.quicHandshakeComplete()
|
||||
// Provide the 1-RTT read secret now that the handshake is complete.
|
||||
// The QUIC layer MUST NOT decrypt 1-RTT packets prior to completing
|
||||
// the handshake (RFC 9001, Section 5.7).
|
||||
c.quicSetReadSecret(QUICEncryptionLevelApplication, c.cipherSuite, c.in.trafficSecret)
|
||||
} else {
|
||||
var a alert
|
||||
c.out.Lock()
|
||||
if !errors.As(c.out.err, &a) {
|
||||
a = alertInternalError
|
||||
}
|
||||
c.out.Unlock()
|
||||
// Return an error which wraps both the handshake error and
|
||||
// any alert error we may have sent, or alertInternalError
|
||||
// if we didn't send an alert.
|
||||
// Truncate the text of the alert to 0 characters.
|
||||
c.handshakeErr = fmt.Errorf("%w%.0w", c.handshakeErr, AlertError(a))
|
||||
}
|
||||
close(c.quic.blockedc)
|
||||
close(c.quic.signalc)
|
||||
}
|
||||
|
||||
return c.handshakeErr
|
||||
}
|
||||
|
||||
// ConnectionState returns basic TLS details about the connection.
|
||||
func (c *Conn) ConnectionState() ConnectionState {
|
||||
c.handshakeMutex.Lock()
|
||||
|
|
109
conn_nowasi.go
Normal file
109
conn_nowasi.go
Normal file
|
@ -0,0 +1,109 @@
|
|||
//go:build !wasm && !wasi && !wasip1 && !wasip2
|
||||
|
||||
package tls
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func (c *Conn) handshakeContext(ctx context.Context) (ret error) {
|
||||
// Fast sync/atomic-based exit if there is no handshake in flight and the
|
||||
// last one succeeded without an error. Avoids the expensive context setup
|
||||
// and mutex for most Read and Write calls.
|
||||
if c.isHandshakeComplete.Load() {
|
||||
return nil
|
||||
}
|
||||
|
||||
handshakeCtx, cancel := context.WithCancel(ctx)
|
||||
// Note: defer this before starting the "interrupter" goroutine
|
||||
// so that we can tell the difference between the input being canceled and
|
||||
// this cancellation. In the former case, we need to close the connection.
|
||||
defer cancel()
|
||||
|
||||
if c.quic != nil {
|
||||
c.quic.cancelc = handshakeCtx.Done()
|
||||
c.quic.cancel = cancel
|
||||
} else if ctx.Done() != nil {
|
||||
// Start the "interrupter" goroutine, if this context might be canceled.
|
||||
// (The background context cannot).
|
||||
//
|
||||
// The interrupter goroutine waits for the input context to be done and
|
||||
// closes the connection if this happens before the function returns.
|
||||
done := make(chan struct{})
|
||||
interruptRes := make(chan error, 1)
|
||||
defer func() {
|
||||
close(done)
|
||||
if ctxErr := <-interruptRes; ctxErr != nil {
|
||||
// Return context error to user.
|
||||
ret = ctxErr
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
select {
|
||||
case <-handshakeCtx.Done():
|
||||
// Close the connection, discarding the error
|
||||
_ = c.conn.Close()
|
||||
interruptRes <- handshakeCtx.Err()
|
||||
case <-done:
|
||||
interruptRes <- nil
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
c.handshakeMutex.Lock()
|
||||
defer c.handshakeMutex.Unlock()
|
||||
|
||||
if err := c.handshakeErr; err != nil {
|
||||
return err
|
||||
}
|
||||
if c.isHandshakeComplete.Load() {
|
||||
return nil
|
||||
}
|
||||
|
||||
c.in.Lock()
|
||||
defer c.in.Unlock()
|
||||
|
||||
c.handshakeErr = c.handshakeFn(handshakeCtx)
|
||||
if c.handshakeErr == nil {
|
||||
c.handshakes++
|
||||
} else {
|
||||
// If an error occurred during the handshake try to flush the
|
||||
// alert that might be left in the buffer.
|
||||
c.flush()
|
||||
}
|
||||
|
||||
if c.handshakeErr == nil && !c.isHandshakeComplete.Load() {
|
||||
c.handshakeErr = errors.New("tls: internal error: handshake should have had a result")
|
||||
}
|
||||
if c.handshakeErr != nil && c.isHandshakeComplete.Load() {
|
||||
panic("tls: internal error: handshake returned an error but is marked successful")
|
||||
}
|
||||
|
||||
if c.quic != nil {
|
||||
if c.handshakeErr == nil {
|
||||
c.quicHandshakeComplete()
|
||||
// Provide the 1-RTT read secret now that the handshake is complete.
|
||||
// The QUIC layer MUST NOT decrypt 1-RTT packets prior to completing
|
||||
// the handshake (RFC 9001, Section 5.7).
|
||||
c.quicSetReadSecret(QUICEncryptionLevelApplication, c.cipherSuite, c.in.trafficSecret)
|
||||
} else {
|
||||
var a alert
|
||||
c.out.Lock()
|
||||
if !errors.As(c.out.err, &a) {
|
||||
a = alertInternalError
|
||||
}
|
||||
c.out.Unlock()
|
||||
// Return an error which wraps both the handshake error and
|
||||
// any alert error we may have sent, or alertInternalError
|
||||
// if we didn't send an alert.
|
||||
// Truncate the text of the alert to 0 characters.
|
||||
c.handshakeErr = fmt.Errorf("%w%.0w", c.handshakeErr, AlertError(a))
|
||||
}
|
||||
close(c.quic.blockedc)
|
||||
close(c.quic.signalc)
|
||||
}
|
||||
|
||||
return c.handshakeErr
|
||||
}
|
83
conn_wasi.go
Normal file
83
conn_wasi.go
Normal file
|
@ -0,0 +1,83 @@
|
|||
//go:build wasm || wasi || wasip1 || wasip2
|
||||
|
||||
package tls
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func (c *Conn) handshakeContext(ctx context.Context) (ret error) {
|
||||
// Fast sync/atomic-based exit if there is no handshake in flight and the
|
||||
// last one succeeded without an error. Avoids the expensive context setup
|
||||
// and mutex for most Read and Write calls.
|
||||
if c.isHandshakeComplete.Load() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// check if ctx has expired ONLY ONCE, since we cannot use goroutines
|
||||
if ctxErr := ctx.Err(); ctxErr != nil {
|
||||
return ctxErr
|
||||
}
|
||||
|
||||
if c.quic != nil {
|
||||
// c.quic.cancelc = handshakeCtx.Done()
|
||||
// c.quic.cancel = cancel
|
||||
}
|
||||
|
||||
c.handshakeMutex.Lock()
|
||||
defer c.handshakeMutex.Unlock()
|
||||
|
||||
if err := c.handshakeErr; err != nil {
|
||||
return err
|
||||
}
|
||||
if c.isHandshakeComplete.Load() {
|
||||
return nil
|
||||
}
|
||||
|
||||
c.in.Lock()
|
||||
defer c.in.Unlock()
|
||||
|
||||
c.handshakeErr = c.handshakeFn(ctx)
|
||||
if c.handshakeErr == nil {
|
||||
c.handshakes++
|
||||
} else {
|
||||
// If an error occurred during the handshake try to flush the
|
||||
// alert that might be left in the buffer.
|
||||
c.flush()
|
||||
}
|
||||
|
||||
if c.handshakeErr == nil && !c.isHandshakeComplete.Load() {
|
||||
c.handshakeErr = errors.New("tls: internal error: handshake should have had a result")
|
||||
}
|
||||
if c.handshakeErr != nil && c.isHandshakeComplete.Load() {
|
||||
panic("tls: internal error: handshake returned an error but is marked successful")
|
||||
}
|
||||
|
||||
if c.quic != nil {
|
||||
if c.handshakeErr == nil {
|
||||
c.quicHandshakeComplete()
|
||||
// Provide the 1-RTT read secret now that the handshake is complete.
|
||||
// The QUIC layer MUST NOT decrypt 1-RTT packets prior to completing
|
||||
// the handshake (RFC 9001, Section 5.7).
|
||||
c.quicSetReadSecret(QUICEncryptionLevelApplication, c.cipherSuite, c.in.trafficSecret)
|
||||
} else {
|
||||
var a alert
|
||||
c.out.Lock()
|
||||
if !errors.As(c.out.err, &a) {
|
||||
a = alertInternalError
|
||||
}
|
||||
c.out.Unlock()
|
||||
// Return an error which wraps both the handshake error and
|
||||
// any alert error we may have sent, or alertInternalError
|
||||
// if we didn't send an alert.
|
||||
// Truncate the text of the alert to 0 characters.
|
||||
c.handshakeErr = fmt.Errorf("%w%.0w", c.handshakeErr, AlertError(a))
|
||||
}
|
||||
close(c.quic.blockedc)
|
||||
close(c.quic.signalc)
|
||||
}
|
||||
|
||||
return c.handshakeErr
|
||||
}
|
108
u_conn.go
108
u_conn.go
|
@ -313,114 +313,6 @@ func (c *UConn) HandshakeContext(ctx context.Context) error {
|
|||
return c.handshakeContext(ctx)
|
||||
}
|
||||
|
||||
func (c *UConn) handshakeContext(ctx context.Context) (ret error) {
|
||||
// Fast sync/atomic-based exit if there is no handshake in flight and the
|
||||
// last one succeeded without an error. Avoids the expensive context setup
|
||||
// and mutex for most Read and Write calls.
|
||||
if c.isHandshakeComplete.Load() {
|
||||
return nil
|
||||
}
|
||||
|
||||
handshakeCtx, cancel := context.WithCancel(ctx)
|
||||
// Note: defer this before starting the "interrupter" goroutine
|
||||
// so that we can tell the difference between the input being canceled and
|
||||
// this cancellation. In the former case, we need to close the connection.
|
||||
defer cancel()
|
||||
|
||||
// Start the "interrupter" goroutine, if this context might be canceled.
|
||||
// (The background context cannot).
|
||||
//
|
||||
// The interrupter goroutine waits for the input context to be done and
|
||||
// closes the connection if this happens before the function returns.
|
||||
if c.quic != nil {
|
||||
c.quic.cancelc = handshakeCtx.Done()
|
||||
c.quic.cancel = cancel
|
||||
} else if ctx.Done() != nil {
|
||||
done := make(chan struct{})
|
||||
interruptRes := make(chan error, 1)
|
||||
defer func() {
|
||||
close(done)
|
||||
if ctxErr := <-interruptRes; ctxErr != nil {
|
||||
// Return context error to user.
|
||||
ret = ctxErr
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
select {
|
||||
case <-handshakeCtx.Done():
|
||||
// Close the connection, discarding the error
|
||||
_ = c.conn.Close()
|
||||
interruptRes <- handshakeCtx.Err()
|
||||
case <-done:
|
||||
interruptRes <- nil
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
c.handshakeMutex.Lock()
|
||||
defer c.handshakeMutex.Unlock()
|
||||
|
||||
if err := c.handshakeErr; err != nil {
|
||||
return err
|
||||
}
|
||||
if c.isHandshakeComplete.Load() {
|
||||
return nil
|
||||
}
|
||||
|
||||
c.in.Lock()
|
||||
defer c.in.Unlock()
|
||||
|
||||
// [uTLS section begins]
|
||||
if c.isClient {
|
||||
err := c.BuildHandshakeState()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// [uTLS section ends]
|
||||
c.handshakeErr = c.handshakeFn(handshakeCtx)
|
||||
if c.handshakeErr == nil {
|
||||
c.handshakes++
|
||||
} else {
|
||||
// If an error occurred during the hadshake try to flush the
|
||||
// alert that might be left in the buffer.
|
||||
c.flush()
|
||||
}
|
||||
|
||||
if c.handshakeErr == nil && !c.isHandshakeComplete.Load() {
|
||||
c.handshakeErr = errors.New("tls: internal error: handshake should have had a result")
|
||||
}
|
||||
if c.handshakeErr != nil && c.isHandshakeComplete.Load() {
|
||||
panic("tls: internal error: handshake returned an error but is marked successful")
|
||||
}
|
||||
|
||||
if c.quic != nil {
|
||||
if c.handshakeErr == nil {
|
||||
c.quicHandshakeComplete()
|
||||
// Provide the 1-RTT read secret now that the handshake is complete.
|
||||
// The QUIC layer MUST NOT decrypt 1-RTT packets prior to completing
|
||||
// the handshake (RFC 9001, Section 5.7).
|
||||
c.quicSetReadSecret(QUICEncryptionLevelApplication, c.cipherSuite, c.in.trafficSecret)
|
||||
} else {
|
||||
var a alert
|
||||
c.out.Lock()
|
||||
if !errors.As(c.out.err, &a) {
|
||||
a = alertInternalError
|
||||
}
|
||||
c.out.Unlock()
|
||||
// Return an error which wraps both the handshake error and
|
||||
// any alert error we may have sent, or alertInternalError
|
||||
// if we didn't send an alert.
|
||||
// Truncate the text of the alert to 0 characters.
|
||||
c.handshakeErr = fmt.Errorf("%w%.0w", c.handshakeErr, AlertError(a))
|
||||
}
|
||||
close(c.quic.blockedc)
|
||||
close(c.quic.signalc)
|
||||
}
|
||||
|
||||
return c.handshakeErr
|
||||
}
|
||||
|
||||
// Copy-pasted from tls.Conn in its entirety. But c.Handshake() is now utls' one, not tls.
|
||||
// Write writes data to the connection.
|
||||
func (c *UConn) Write(b []byte) (int, error) {
|
||||
|
|
117
u_conn_nowasi.go
Normal file
117
u_conn_nowasi.go
Normal file
|
@ -0,0 +1,117 @@
|
|||
//go:build !wasm && !wasi && !wasip1 && !wasip2
|
||||
|
||||
package tls
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func (c *UConn) handshakeContext(ctx context.Context) (ret error) {
|
||||
// Fast sync/atomic-based exit if there is no handshake in flight and the
|
||||
// last one succeeded without an error. Avoids the expensive context setup
|
||||
// and mutex for most Read and Write calls.
|
||||
if c.isHandshakeComplete.Load() {
|
||||
return nil
|
||||
}
|
||||
|
||||
handshakeCtx, cancel := context.WithCancel(ctx)
|
||||
// Note: defer this before starting the "interrupter" goroutine
|
||||
// so that we can tell the difference between the input being canceled and
|
||||
// this cancellation. In the former case, we need to close the connection.
|
||||
defer cancel()
|
||||
|
||||
// Start the "interrupter" goroutine, if this context might be canceled.
|
||||
// (The background context cannot).
|
||||
//
|
||||
// The interrupter goroutine waits for the input context to be done and
|
||||
// closes the connection if this happens before the function returns.
|
||||
if c.quic != nil {
|
||||
c.quic.cancelc = handshakeCtx.Done()
|
||||
c.quic.cancel = cancel
|
||||
} else if ctx.Done() != nil {
|
||||
done := make(chan struct{})
|
||||
interruptRes := make(chan error, 1)
|
||||
defer func() {
|
||||
close(done)
|
||||
if ctxErr := <-interruptRes; ctxErr != nil {
|
||||
// Return context error to user.
|
||||
ret = ctxErr
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
select {
|
||||
case <-handshakeCtx.Done():
|
||||
// Close the connection, discarding the error
|
||||
_ = c.conn.Close()
|
||||
interruptRes <- handshakeCtx.Err()
|
||||
case <-done:
|
||||
interruptRes <- nil
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
c.handshakeMutex.Lock()
|
||||
defer c.handshakeMutex.Unlock()
|
||||
|
||||
if err := c.handshakeErr; err != nil {
|
||||
return err
|
||||
}
|
||||
if c.isHandshakeComplete.Load() {
|
||||
return nil
|
||||
}
|
||||
|
||||
c.in.Lock()
|
||||
defer c.in.Unlock()
|
||||
|
||||
// [uTLS section begins]
|
||||
if c.isClient {
|
||||
err := c.BuildHandshakeState()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// [uTLS section ends]
|
||||
c.handshakeErr = c.handshakeFn(handshakeCtx)
|
||||
if c.handshakeErr == nil {
|
||||
c.handshakes++
|
||||
} else {
|
||||
// If an error occurred during the hadshake try to flush the
|
||||
// alert that might be left in the buffer.
|
||||
c.flush()
|
||||
}
|
||||
|
||||
if c.handshakeErr == nil && !c.isHandshakeComplete.Load() {
|
||||
c.handshakeErr = errors.New("tls: internal error: handshake should have had a result")
|
||||
}
|
||||
if c.handshakeErr != nil && c.isHandshakeComplete.Load() {
|
||||
panic("tls: internal error: handshake returned an error but is marked successful")
|
||||
}
|
||||
|
||||
if c.quic != nil {
|
||||
if c.handshakeErr == nil {
|
||||
c.quicHandshakeComplete()
|
||||
// Provide the 1-RTT read secret now that the handshake is complete.
|
||||
// The QUIC layer MUST NOT decrypt 1-RTT packets prior to completing
|
||||
// the handshake (RFC 9001, Section 5.7).
|
||||
c.quicSetReadSecret(QUICEncryptionLevelApplication, c.cipherSuite, c.in.trafficSecret)
|
||||
} else {
|
||||
var a alert
|
||||
c.out.Lock()
|
||||
if !errors.As(c.out.err, &a) {
|
||||
a = alertInternalError
|
||||
}
|
||||
c.out.Unlock()
|
||||
// Return an error which wraps both the handshake error and
|
||||
// any alert error we may have sent, or alertInternalError
|
||||
// if we didn't send an alert.
|
||||
// Truncate the text of the alert to 0 characters.
|
||||
c.handshakeErr = fmt.Errorf("%w%.0w", c.handshakeErr, AlertError(a))
|
||||
}
|
||||
close(c.quic.blockedc)
|
||||
close(c.quic.signalc)
|
||||
}
|
||||
|
||||
return c.handshakeErr
|
||||
}
|
91
u_conn_wasi.go
Normal file
91
u_conn_wasi.go
Normal file
|
@ -0,0 +1,91 @@
|
|||
//go:build wasm || wasi || wasip1 || wasip2
|
||||
|
||||
package tls
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func (c *UConn) handshakeContext(ctx context.Context) (ret error) {
|
||||
// Fast sync/atomic-based exit if there is no handshake in flight and the
|
||||
// last one succeeded without an error. Avoids the expensive context setup
|
||||
// and mutex for most Read and Write calls.
|
||||
if c.isHandshakeComplete.Load() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// check if ctx has expired ONLY ONCE, since we cannot use goroutines
|
||||
if ctxErr := ctx.Err(); ctxErr != nil {
|
||||
return ctxErr
|
||||
}
|
||||
|
||||
if c.quic != nil {
|
||||
// c.quic.cancelc = handshakeCtx.Done()
|
||||
// c.quic.cancel = cancel
|
||||
}
|
||||
|
||||
c.handshakeMutex.Lock()
|
||||
defer c.handshakeMutex.Unlock()
|
||||
|
||||
if err := c.handshakeErr; err != nil {
|
||||
return err
|
||||
}
|
||||
if c.isHandshakeComplete.Load() {
|
||||
return nil
|
||||
}
|
||||
|
||||
c.in.Lock()
|
||||
defer c.in.Unlock()
|
||||
|
||||
// [uTLS section begins]
|
||||
if c.isClient {
|
||||
err := c.BuildHandshakeState()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// [uTLS section ends]
|
||||
c.handshakeErr = c.handshakeFn(ctx)
|
||||
if c.handshakeErr == nil {
|
||||
c.handshakes++
|
||||
} else {
|
||||
// If an error occurred during the hadshake try to flush the
|
||||
// alert that might be left in the buffer.
|
||||
c.flush()
|
||||
}
|
||||
|
||||
if c.handshakeErr == nil && !c.isHandshakeComplete.Load() {
|
||||
c.handshakeErr = errors.New("tls: internal error: handshake should have had a result")
|
||||
}
|
||||
if c.handshakeErr != nil && c.isHandshakeComplete.Load() {
|
||||
panic("tls: internal error: handshake returned an error but is marked successful")
|
||||
}
|
||||
|
||||
if c.quic != nil {
|
||||
if c.handshakeErr == nil {
|
||||
c.quicHandshakeComplete()
|
||||
// Provide the 1-RTT read secret now that the handshake is complete.
|
||||
// The QUIC layer MUST NOT decrypt 1-RTT packets prior to completing
|
||||
// the handshake (RFC 9001, Section 5.7).
|
||||
c.quicSetReadSecret(QUICEncryptionLevelApplication, c.cipherSuite, c.in.trafficSecret)
|
||||
} else {
|
||||
var a alert
|
||||
c.out.Lock()
|
||||
if !errors.As(c.out.err, &a) {
|
||||
a = alertInternalError
|
||||
}
|
||||
c.out.Unlock()
|
||||
// Return an error which wraps both the handshake error and
|
||||
// any alert error we may have sent, or alertInternalError
|
||||
// if we didn't send an alert.
|
||||
// Truncate the text of the alert to 0 characters.
|
||||
c.handshakeErr = fmt.Errorf("%w%.0w", c.handshakeErr, AlertError(a))
|
||||
}
|
||||
close(c.quic.blockedc)
|
||||
close(c.quic.signalc)
|
||||
}
|
||||
|
||||
return c.handshakeErr
|
||||
}
|
|
@ -47,8 +47,9 @@ func NewRoller() (*Roller, error) {
|
|||
// If tcp connection fails or all HelloIDs are tried, returns with last error.
|
||||
//
|
||||
// Usage examples:
|
||||
// Dial("tcp4", "google.com:443", "google.com")
|
||||
// Dial("tcp", "10.23.144.22:443", "mywebserver.org")
|
||||
//
|
||||
// Dial("tcp4", "google.com:443", "google.com")
|
||||
// Dial("tcp", "10.23.144.22:443", "mywebserver.org")
|
||||
func (c *Roller) Dial(network, addr, serverName string) (*UConn, error) {
|
||||
helloIDs := make([]ClientHelloID, len(c.HelloIDs))
|
||||
copy(helloIDs, c.HelloIDs)
|
||||
|
@ -77,7 +78,8 @@ func (c *Roller) Dial(network, addr, serverName string) (*UConn, error) {
|
|||
var tcpConn net.Conn
|
||||
var err error
|
||||
for _, helloID := range helloIDs {
|
||||
tcpConn, err = net.DialTimeout(network, addr, c.TcpDialTimeout)
|
||||
// tcpConn, err = net.DialTimeout(network, addr, c.TcpDialTimeout)
|
||||
tcpConn, err = net.Dial(network, addr)
|
||||
if err != nil {
|
||||
return nil, err // on tcp Dial failure return with error right away
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue