forked from quic-go/quic-go
privatize the client, only expose Dial functions
This commit is contained in:
@@ -20,23 +20,19 @@ import (
|
||||
"github.com/lucas-clemente/quic-go/utils"
|
||||
)
|
||||
|
||||
type quicClient interface {
|
||||
OpenStream() (quic.Stream, error)
|
||||
Close(error) error
|
||||
Listen() error
|
||||
}
|
||||
|
||||
// Client is a HTTP2 client doing QUIC requests
|
||||
type Client struct {
|
||||
mutex sync.RWMutex
|
||||
cryptoChangedCond sync.Cond
|
||||
|
||||
config *quic.Config
|
||||
|
||||
t *QuicRoundTripper
|
||||
|
||||
hostname string
|
||||
encryptionLevel protocol.EncryptionLevel
|
||||
|
||||
client quicClient
|
||||
session quic.Session
|
||||
headerStream quic.Stream
|
||||
headerErr *qerr.QuicError
|
||||
requestWriter *requestWriter
|
||||
@@ -47,42 +43,50 @@ type Client struct {
|
||||
var _ h2quicClient = &Client{}
|
||||
|
||||
// NewClient creates a new client
|
||||
func NewClient(t *QuicRoundTripper, tlsConfig *tls.Config, hostname string) (*Client, error) {
|
||||
func NewClient(t *QuicRoundTripper, tlsConfig *tls.Config, hostname string) *Client {
|
||||
c := &Client{
|
||||
t: t,
|
||||
hostname: authorityAddr("https", hostname),
|
||||
responses: make(map[protocol.StreamID]chan *http.Response),
|
||||
}
|
||||
c.cryptoChangedCond = sync.Cond{L: &c.mutex}
|
||||
|
||||
var err error
|
||||
c.client, err = quic.NewClient(c.hostname, tlsConfig, c.cryptoChangeCallback, c.versionNegotiateCallback)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
c.config = &quic.Config{
|
||||
ConnState: c.connStateCallback,
|
||||
}
|
||||
|
||||
go c.client.Listen()
|
||||
return c, nil
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Client) cryptoChangeCallback(isForwardSecure bool) {
|
||||
c.cryptoChangedCond.L.Lock()
|
||||
defer c.cryptoChangedCond.L.Unlock()
|
||||
// Dial dials the connection
|
||||
func (c *Client) Dial() error {
|
||||
_, err := quic.DialAddr(c.hostname, c.config)
|
||||
return err
|
||||
}
|
||||
|
||||
if isForwardSecure {
|
||||
c.encryptionLevel = protocol.EncryptionForwardSecure
|
||||
utils.Debugf("is forward secure")
|
||||
} else {
|
||||
func (c *Client) connStateCallback(sess quic.Session, state quic.ConnState) {
|
||||
c.mutex.Lock()
|
||||
if c.session == nil {
|
||||
c.session = sess
|
||||
}
|
||||
switch state {
|
||||
case quic.ConnStateVersionNegotiated:
|
||||
// TODO: handle errors
|
||||
c.versionNegotiateCallback()
|
||||
case quic.ConnStateSecure:
|
||||
c.encryptionLevel = protocol.EncryptionSecure
|
||||
utils.Debugf("is secure")
|
||||
c.cryptoChangedCond.Broadcast()
|
||||
case quic.ConnStateForwardSecure:
|
||||
c.encryptionLevel = protocol.EncryptionForwardSecure
|
||||
utils.Debugf("is forward secure")
|
||||
c.cryptoChangedCond.Broadcast()
|
||||
}
|
||||
c.cryptoChangedCond.Broadcast()
|
||||
c.mutex.Unlock()
|
||||
}
|
||||
|
||||
func (c *Client) versionNegotiateCallback() error {
|
||||
var err error
|
||||
// once the version has been negotiated, open the header stream
|
||||
c.headerStream, err = c.client.OpenStream()
|
||||
c.headerStream, err = c.session.OpenStream()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -162,7 +166,7 @@ func (c *Client) Do(req *http.Request) (*http.Response, error) {
|
||||
}
|
||||
hdrChan := make(chan *http.Response)
|
||||
// TODO: think about what to do with a TooManyOpenStreams error. Wait and retry?
|
||||
dataStream, err := c.client.OpenStream()
|
||||
dataStream, err := c.session.OpenStream()
|
||||
if err != nil {
|
||||
c.Close(err)
|
||||
return nil, err
|
||||
@@ -260,7 +264,7 @@ func (c *Client) writeRequestBody(dataStream quic.Stream, body io.ReadCloser) (e
|
||||
|
||||
// Close closes the client
|
||||
func (c *Client) Close(e error) {
|
||||
_ = c.client.Close(e)
|
||||
_ = c.session.Close(e)
|
||||
}
|
||||
|
||||
// copied from net/transport.go
|
||||
|
||||
Reference in New Issue
Block a user