Merge pull request #186 from iamqizhao/master

Allow some handshaking between client and server before rpc happens.
This commit is contained in:
Qi Zhao 2015-05-01 19:17:42 -07:00
Родитель d84520d5f9 54b06c32f6
Коммит 5ea2bfc402
4 изменённых файлов: 43 добавлений и 2 удалений

Просмотреть файл

@ -104,6 +104,15 @@ func WithDialer(f func(addr string, timeout time.Duration) (net.Conn, error)) Di
}
}
// WithHandshaker returns a DialOption that specifies a function to perform some handshaking
// with the server. It is typically used to negotiate the wire protocol version and security
// protocol with the server.
func WithHandshaker(h func(conn net.Conn) (credentials.TransportAuthenticator, error)) DialOption {
return func(o *dialOptions) {
o.copts.Handshaker = h
}
}
// Dial creates a client connection the given target.
// TODO(zhaoq): Have an option to make Dial return immediately without waiting
// for connection to complete.

Просмотреть файл

@ -70,8 +70,19 @@ type Credentials interface {
GetRequestMetadata(ctx context.Context) (map[string]string, error)
}
// TransportAuthenticator defines the common interface all supported transport
// authentication protocols (e.g., TLS, SSL) must implement.
// ProtocolInfo provides information regarding the gRPC wire protocol version,
// security protocol, security protocol version in use, etc.
type ProtocolInfo struct {
// ProtocolVersion is the gRPC wire protocol version.
ProtocolVersion string
// SecurityProtocol is the security protocol in use.
SecurityProtocol string
// SecurityVersion is the security protocol version.
SecurityVersion string
}
// TransportAuthenticator defines the common interface for all the live gRPC wire
// protocols and supported transport security protocols (e.g., TLS, SSL).
type TransportAuthenticator interface {
// Handshake does the authentication handshake specified by the corresponding
// authentication protocol on rawConn.
@ -79,6 +90,8 @@ type TransportAuthenticator interface {
// NewListener creates a listener which accepts connections with requested
// authentication handshake.
NewListener(lis net.Listener) net.Listener
// Info provides the ProtocolInfo of this TransportAuthenticator.
Info() ProtocolInfo
Credentials
}
@ -88,6 +101,13 @@ type tlsCreds struct {
config tls.Config
}
func (c *tlsCreds) Info() ProtocolInfo {
return ProtocolInfo{
SecurityProtocol: "tls",
SecurityVersion: "1.2",
}
}
// GetRequestMetadata returns nil, nil since TLS credentials does not have
// metadata.
func (c *tlsCreds) GetRequestMetadata(ctx context.Context) (map[string]string, error) {

Просмотреть файл

@ -111,6 +111,17 @@ func newHTTP2Client(addr string, opts *ConnectOptions) (_ ClientTransport, err e
if connErr != nil {
return nil, ConnectionErrorf("transport: %v", connErr)
}
// Perform handshake if opts.Handshaker is set.
if opts.Handshaker != nil {
auth, err := opts.Handshaker(conn)
if err != nil {
return nil, ConnectionErrorf("transport: handshaking failed %v", err)
}
// Prepend the resulting authenticator to opts.AuthOptions.
if auth != nil {
opts.AuthOptions = append([]credentials.Credentials{auth}, opts.AuthOptions...)
}
}
for _, c := range opts.AuthOptions {
if ccreds, ok := c.(credentials.TransportAuthenticator); ok {
scheme = "https"

Просмотреть файл

@ -316,6 +316,7 @@ func NewServerTransport(protocol string, conn net.Conn, maxStreams uint32) (Serv
// ConnectOptions covers all relevant options for dialing a server.
type ConnectOptions struct {
Dialer func(string, time.Duration) (net.Conn, error)
Handshaker func(conn net.Conn) (credentials.TransportAuthenticator, error)
AuthOptions []credentials.Credentials
Timeout time.Duration
}