type SingleConn struct {
conn net.Conn
ln *SingleListener
+ once sync.Once
}
func (conn *SingleConn) Read(b []byte) (int, error) { return conn.conn.Read(b) }
func (conn *SingleConn) Write(b []byte) (int, error) { return conn.conn.Write(b) }
func (conn *SingleConn) Close() error {
- conn.ln.Unlock()
+ conn.once.Do(conn.ln.Unlock)
return conn.conn.Close()
}
return nil, AlreadyAccepted{}
}
ln.accepted = true
- return &SingleConn{ln.conn, ln}, nil
+ return &SingleConn{conn: ln.conn, ln: ln}, nil
}
func (ln *SingleListener) Close() error { return nil }
@item TLS session resumption is also supported.
+@item And Go itself tries also to act as a
+@url{https://http2.github.io/, HTTP/2} client too.
+
@end itemize
@image{dialog,,,Example dialog,.webp}
caCert *x509.Certificate
caPrv crypto.PrivateKey
transport = http.Transport{
- ForceAttemptHTTP2: false,
- TLSNextProto: make(map[string]func(string, *tls.Conn) http.RoundTripper),
DialTLSContext: dialTLS,
+ ForceAttemptHTTP2: true,
}
sessionCache = tls.NewLRUClientSessionCache(1024)
return verifyCert(host, nil, rawCerts, verifiedChains)
},
ClientSessionCache: sessionCache,
+ NextProtos: []string{"h2", "http/1.1"},
}
conn, dialErr := tls.Dial(network, addr, &cfg)
if dialErr != nil {
}
}
connState := conn.ConnectionState()
- msg := fmt.Sprintf(
- "%s\t%s %s\t%s",
- strings.TrimSuffix(addr, ":443"),
- ucspi.TLSVersion(connState.Version),
- tls.CipherSuiteName(connState.CipherSuite),
- spkiHash(connState.PeerCertificates[0]),
- )
if connState.DidResume {
- msg += "\tresumed"
+ sinkTLS <- fmt.Sprintf(
+ "%s\t%s %s\t%s\t%s",
+ strings.TrimSuffix(addr, ":443"),
+ ucspi.TLSVersion(connState.Version),
+ tls.CipherSuiteName(connState.CipherSuite),
+ spkiHash(connState.PeerCertificates[0]),
+ connState.NegotiatedProtocol,
+ )
}
- sinkTLS <- msg
return conn, nil
}