micro-server-grpc/quic/quic_transport.go
Vasiliy Tolstov a793983ed2 add quic connection transport support
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2023-06-10 17:05:34 +03:00

118 lines
3.5 KiB
Go

// grpc over quic mostly based on https://github.com/sssgun/grpc-quic
// copyright sssgun with MIT license
package grpcquic
import (
"context"
"crypto/tls"
"net"
"google.golang.org/grpc/credentials"
)
var _ credentials.AuthInfo = (*Info)(nil)
// Info contains the auth information
type Info struct {
conn *Conn
}
func NewInfo(c *Conn) *Info {
return &Info{c}
}
// AuthType returns the type of Info as a string.
func (i *Info) AuthType() string {
return "quic-tls"
}
func (i *Info) Conn() net.Conn {
return i.conn
}
var _ credentials.TransportCredentials = (*Credentials)(nil)
type Credentials struct {
tlsConfig *tls.Config
isQuicConnection bool
serverName string
grpcCreds credentials.TransportCredentials
}
func NewCredentials(tlsConfig *tls.Config) credentials.TransportCredentials {
grpcCreds := credentials.NewTLS(tlsConfig)
return &Credentials{
grpcCreds: grpcCreds,
tlsConfig: tlsConfig,
}
}
// ClientHandshake does the authentication handshake specified by the corresponding
// authentication protocol on rawConn for clients. It returns the authenticated
// connection and the corresponding auth information about the connection.
// Implementations must use the provided context to implement timely cancellation.
// gRPC will try to reconnect if the error returned is a temporary error
// (io.EOF, context.DeadlineExceeded or err.Temporary() == true).
// If the returned error is a wrapper error, implementations should make sure that
// the error implements Temporary() to have the correct retry behaviors.
//
// If the returned net.Conn is closed, it MUST close the net.Conn provided.
func (pt *Credentials) ClientHandshake(ctx context.Context, authority string, conn net.Conn) (net.Conn, credentials.AuthInfo, error) {
if c, ok := conn.(*Conn); ok {
pt.isQuicConnection = true
return conn, NewInfo(c), nil
}
return pt.grpcCreds.ClientHandshake(ctx, authority, conn)
}
// ServerHandshake does the authentication handshake for servers. It returns
// the authenticated connection and the corresponding auth information about
// the connection.
//
// If the returned net.Conn is closed, it MUST close the net.Conn provided.
func (pt *Credentials) ServerHandshake(conn net.Conn) (net.Conn, credentials.AuthInfo, error) {
if c, ok := conn.(*Conn); ok {
pt.isQuicConnection = true
ainfo := NewInfo(c)
return conn, ainfo, nil
}
return pt.grpcCreds.ServerHandshake(conn)
}
// Info provides the ProtocolInfo of this Credentials.
func (pt *Credentials) Info() credentials.ProtocolInfo {
if pt.isQuicConnection {
return credentials.ProtocolInfo{
// ProtocolVersion is the gRPC wire protocol version.
ProtocolVersion: "/quic/1.0.0",
// SecurityProtocol is the security protocol in use.
SecurityProtocol: "quic-tls",
// SecurityVersion is the security protocol version.
// SecurityVersion: "1.2.0",
// ServerName is the user-configured server name.
ServerName: pt.serverName,
}
}
return pt.grpcCreds.Info()
}
// Clone makes a copy of this Credentials.
func (pt *Credentials) Clone() credentials.TransportCredentials {
return &Credentials{
tlsConfig: pt.tlsConfig.Clone(),
grpcCreds: pt.grpcCreds.Clone(),
}
}
// OverrideServerName overrides the server name used to verify the hostname on the returned certificates from the server.
// gRPC internals also use it to override the virtual hosting name if it is set.
// It must be called before dialing. Currently, this is only used by grpclb.
func (pt *Credentials) OverrideServerName(name string) error {
pt.serverName = name
return pt.grpcCreds.OverrideServerName(name)
}