2020-04-16 08:39:20 -07:00
|
|
|
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
|
|
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
|
|
|
|
package ghttp
|
|
|
|
|
|
|
|
import (
|
|
|
|
"net/http"
|
|
|
|
|
2020-04-16 23:03:17 -07:00
|
|
|
"google.golang.org/grpc"
|
|
|
|
|
|
|
|
"github.com/hashicorp/go-plugin"
|
|
|
|
|
2020-04-17 06:47:19 -07:00
|
|
|
"github.com/ava-labs/gecko/vms/rpcchainvm/ghttp/ghttpproto"
|
2020-04-16 23:03:17 -07:00
|
|
|
"github.com/ava-labs/gecko/vms/rpcchainvm/ghttp/greadcloser"
|
2020-04-17 06:47:19 -07:00
|
|
|
"github.com/ava-labs/gecko/vms/rpcchainvm/ghttp/greadcloser/greadcloserproto"
|
2020-04-16 23:03:17 -07:00
|
|
|
"github.com/ava-labs/gecko/vms/rpcchainvm/ghttp/gresponsewriter"
|
2020-04-17 06:47:19 -07:00
|
|
|
"github.com/ava-labs/gecko/vms/rpcchainvm/ghttp/gresponsewriter/gresponsewriterproto"
|
2020-04-16 08:39:20 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
// Client is an implementation of a messenger channel that talks over RPC.
|
2020-04-16 23:03:17 -07:00
|
|
|
type Client struct {
|
2020-04-17 06:47:19 -07:00
|
|
|
client ghttpproto.HTTPClient
|
2020-04-16 23:03:17 -07:00
|
|
|
broker *plugin.GRPCBroker
|
|
|
|
}
|
2020-04-16 08:39:20 -07:00
|
|
|
|
|
|
|
// NewClient returns a database instance connected to a remote database instance
|
2020-04-17 06:47:19 -07:00
|
|
|
func NewClient(client ghttpproto.HTTPClient, broker *plugin.GRPCBroker) *Client {
|
2020-04-16 23:03:17 -07:00
|
|
|
return &Client{
|
|
|
|
client: client,
|
|
|
|
broker: broker,
|
|
|
|
}
|
2020-04-16 08:39:20 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Handle ...
|
|
|
|
func (c *Client) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
2020-04-16 23:03:17 -07:00
|
|
|
var reader *grpc.Server
|
|
|
|
var writer *grpc.Server
|
|
|
|
|
|
|
|
readerID := c.broker.NextId()
|
|
|
|
go c.broker.AcceptAndServe(readerID, func(opts []grpc.ServerOption) *grpc.Server {
|
|
|
|
reader = grpc.NewServer(opts...)
|
2020-04-17 06:47:19 -07:00
|
|
|
greadcloserproto.RegisterReaderServer(reader, greadcloser.NewServer(r.Body))
|
2020-04-16 23:03:17 -07:00
|
|
|
|
|
|
|
return reader
|
|
|
|
})
|
|
|
|
writerID := c.broker.NextId()
|
|
|
|
go c.broker.AcceptAndServe(writerID, func(opts []grpc.ServerOption) *grpc.Server {
|
|
|
|
writer = grpc.NewServer(opts...)
|
2020-04-17 06:47:19 -07:00
|
|
|
gresponsewriterproto.RegisterWriterServer(writer, gresponsewriter.NewServer(w, c.broker))
|
2020-04-16 23:03:17 -07:00
|
|
|
|
|
|
|
return writer
|
|
|
|
})
|
|
|
|
|
2020-04-17 06:47:19 -07:00
|
|
|
req := &ghttpproto.HTTPRequest{
|
2020-04-16 23:03:17 -07:00
|
|
|
ResponseWriter: writerID,
|
2020-04-17 06:47:19 -07:00
|
|
|
Request: &ghttpproto.Request{
|
2020-04-16 23:03:17 -07:00
|
|
|
Method: r.Method,
|
|
|
|
Proto: r.Proto,
|
|
|
|
ProtoMajor: int32(r.ProtoMajor),
|
|
|
|
ProtoMinor: int32(r.ProtoMinor),
|
|
|
|
Body: readerID,
|
|
|
|
ContentLength: r.ContentLength,
|
|
|
|
TransferEncoding: r.TransferEncoding,
|
|
|
|
Host: r.Host,
|
|
|
|
RemoteAddr: r.RemoteAddr,
|
|
|
|
RequestURI: r.RequestURI,
|
|
|
|
},
|
|
|
|
}
|
2020-04-17 06:47:19 -07:00
|
|
|
req.Request.Header = make([]*ghttpproto.Element, 0, len(r.Header))
|
2020-04-16 08:39:20 -07:00
|
|
|
for key, values := range r.Header {
|
2020-04-17 06:47:19 -07:00
|
|
|
req.Request.Header = append(req.Request.Header, &ghttpproto.Element{
|
2020-04-16 08:39:20 -07:00
|
|
|
Key: key,
|
|
|
|
Values: values,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-04-17 06:47:19 -07:00
|
|
|
req.Request.Form = make([]*ghttpproto.Element, 0, len(r.Form))
|
2020-04-16 23:03:17 -07:00
|
|
|
for key, values := range r.Form {
|
2020-04-17 06:47:19 -07:00
|
|
|
req.Request.Form = append(req.Request.Form, &ghttpproto.Element{
|
2020-04-16 23:03:17 -07:00
|
|
|
Key: key,
|
|
|
|
Values: values,
|
|
|
|
})
|
2020-04-16 08:39:20 -07:00
|
|
|
}
|
|
|
|
|
2020-04-17 06:47:19 -07:00
|
|
|
req.Request.PostForm = make([]*ghttpproto.Element, 0, len(r.PostForm))
|
2020-04-16 23:03:17 -07:00
|
|
|
for key, values := range r.PostForm {
|
2020-04-17 06:47:19 -07:00
|
|
|
req.Request.PostForm = append(req.Request.PostForm, &ghttpproto.Element{
|
2020-04-16 23:03:17 -07:00
|
|
|
Key: key,
|
|
|
|
Values: values,
|
|
|
|
})
|
2020-04-16 08:39:20 -07:00
|
|
|
}
|
|
|
|
|
2020-04-16 23:03:17 -07:00
|
|
|
if r.URL != nil {
|
2020-04-17 06:47:19 -07:00
|
|
|
req.Request.Url = &ghttpproto.URL{
|
2020-04-16 23:03:17 -07:00
|
|
|
Scheme: r.URL.Scheme,
|
|
|
|
Opaque: r.URL.Opaque,
|
|
|
|
Host: r.URL.Host,
|
|
|
|
Path: r.URL.Path,
|
|
|
|
RawPath: r.URL.RawPath,
|
|
|
|
ForceQuery: r.URL.ForceQuery,
|
|
|
|
RawQuery: r.URL.RawQuery,
|
|
|
|
Fragment: r.URL.Fragment,
|
|
|
|
}
|
2020-04-16 08:39:20 -07:00
|
|
|
|
2020-04-16 23:03:17 -07:00
|
|
|
if r.URL.User != nil {
|
2020-04-17 06:47:19 -07:00
|
|
|
req.Request.Url.User = &ghttpproto.Userinfo{
|
2020-04-16 23:03:17 -07:00
|
|
|
Username: r.URL.User.Username(),
|
|
|
|
}
|
|
|
|
pwd, set := r.URL.User.Password()
|
|
|
|
req.Request.Url.User.Password = pwd
|
|
|
|
req.Request.Url.User.PasswordSet = set
|
|
|
|
}
|
2020-04-16 08:39:20 -07:00
|
|
|
}
|
|
|
|
|
2020-04-16 23:03:17 -07:00
|
|
|
if r.TLS != nil {
|
2020-04-17 06:47:19 -07:00
|
|
|
req.Request.Tls = &ghttpproto.ConnectionState{
|
2020-04-16 23:03:17 -07:00
|
|
|
Version: uint32(r.TLS.Version),
|
|
|
|
HandshakeComplete: r.TLS.HandshakeComplete,
|
|
|
|
DidResume: r.TLS.DidResume,
|
|
|
|
CipherSuite: uint32(r.TLS.CipherSuite),
|
|
|
|
NegotiatedProtocol: r.TLS.NegotiatedProtocol,
|
|
|
|
NegotiatedProtocolIsMutual: r.TLS.NegotiatedProtocolIsMutual,
|
|
|
|
ServerName: r.TLS.ServerName,
|
|
|
|
SignedCertificateTimestamps: r.TLS.SignedCertificateTimestamps,
|
|
|
|
OcspResponse: r.TLS.OCSPResponse,
|
|
|
|
TlsUnique: r.TLS.TLSUnique,
|
|
|
|
}
|
|
|
|
|
2020-04-17 06:47:19 -07:00
|
|
|
req.Request.Tls.PeerCertificates = &ghttpproto.Certificates{
|
2020-04-16 23:03:17 -07:00
|
|
|
Cert: make([][]byte, len(r.TLS.PeerCertificates)),
|
|
|
|
}
|
|
|
|
for i, cert := range r.TLS.PeerCertificates {
|
|
|
|
req.Request.Tls.PeerCertificates.Cert[i] = cert.Raw
|
|
|
|
}
|
|
|
|
|
2020-04-17 06:47:19 -07:00
|
|
|
req.Request.Tls.VerifiedChains = make([]*ghttpproto.Certificates, len(r.TLS.VerifiedChains))
|
2020-04-16 23:03:17 -07:00
|
|
|
for i, chain := range r.TLS.VerifiedChains {
|
2020-04-17 06:47:19 -07:00
|
|
|
req.Request.Tls.VerifiedChains[i] = &ghttpproto.Certificates{
|
2020-04-16 23:03:17 -07:00
|
|
|
Cert: make([][]byte, len(chain)),
|
|
|
|
}
|
|
|
|
for j, cert := range chain {
|
|
|
|
req.Request.Tls.VerifiedChains[i].Cert[j] = cert.Raw
|
|
|
|
}
|
|
|
|
}
|
2020-04-16 08:39:20 -07:00
|
|
|
}
|
2020-04-16 23:03:17 -07:00
|
|
|
|
|
|
|
c.client.Handle(r.Context(), req)
|
|
|
|
|
|
|
|
reader.Stop()
|
|
|
|
writer.Stop()
|
2020-04-16 08:39:20 -07:00
|
|
|
}
|