Skip to content

Commit bd59ee3

Browse files
v1 shim
Signed-off-by: eternal-flame-AD <yume@yumechi.jp>
1 parent 4493373 commit bd59ee3

1 file changed

Lines changed: 57 additions & 23 deletions

File tree

v2/shim_v1.go

Lines changed: 57 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,13 @@ import (
77
"errors"
88
"log"
99
"math"
10-
"net"
1110
"net/http"
1211
"net/url"
12+
"plugin"
1313
"strings"
1414
"sync"
1515

1616
"google.golang.org/grpc"
17-
"google.golang.org/grpc/credentials"
1817
"google.golang.org/protobuf/types/known/emptypb"
1918
"gopkg.in/yaml.v2"
2019

@@ -32,19 +31,54 @@ type CompatV1 struct {
3231
GetInstance func(user *papiv1.UserContext) (papiv1.Plugin, error)
3332
}
3433

35-
type PluginShim struct {
34+
// NewCompatV1FromPlugin creates a new CompatV1 from a native Go plugin.
35+
func NewCompatV1FromPlugin(plugin *plugin.Plugin) (*CompatV1, error) {
36+
getPluginInfo, err := plugin.Lookup("GetGotifyPluginInfo")
37+
if err != nil {
38+
return nil, err
39+
}
40+
getInstance, err := plugin.Lookup("NewGotifyPlugin")
41+
if err != nil {
42+
return nil, err
43+
}
44+
45+
getPluginInfoChecked, ok := getPluginInfo.(func() *papiv1.Info)
46+
if !ok {
47+
return nil, errors.New("GetGotifyPluginInfo is not a function")
48+
}
49+
getInstanceCheckedWithErr, ok := getInstance.(func(user *papiv1.UserContext) (papiv1.Plugin, error))
50+
if !ok {
51+
if getInstanceCheckedWithoutErr, ok := getInstance.(func(user *papiv1.UserContext) papiv1.Plugin); ok {
52+
getInstanceCheckedWithErr = func(user *papiv1.UserContext) (papiv1.Plugin, error) {
53+
return getInstanceCheckedWithoutErr(user), nil
54+
}
55+
} else {
56+
return nil, errors.New("NewGotifyPlugin is not a function")
57+
}
58+
}
59+
60+
return &CompatV1{
61+
GetPluginInfo: getPluginInfoChecked,
62+
GetInstance: getInstanceCheckedWithErr,
63+
}, nil
64+
}
65+
66+
// CompatV1Shim is a shim that acts like a plugin server and delegates request to
67+
// something that implements a V1-style API interface.
68+
type CompatV1Shim struct {
3669
mu *sync.RWMutex
3770
compatV1 *CompatV1
3871
gin *gin.Engine
3972
instances map[uint64]papiv1.Plugin
4073
pluginServer *grpc.Server
4174
pluginInfo *papiv1.Info
75+
http.Server
4276
protobuf.UnimplementedPluginServer
4377
protobuf.UnimplementedDisplayerServer
4478
protobuf.UnimplementedConfigurerServer
4579
}
4680

47-
func (s *PluginShim) GetPluginInfo(ctx context.Context, req *emptypb.Empty) (*protobuf.Info, error) {
81+
func (s *CompatV1Shim) GetPluginInfo(ctx context.Context, req *emptypb.Empty) (*protobuf.Info, error) {
4882
return &protobuf.Info{
4983
Version: s.pluginInfo.Version,
5084
Author: s.pluginInfo.Author,
@@ -88,7 +122,7 @@ func (h *shimV1StorageHandler) Load() (b []byte, err error) {
88122
return
89123
}
90124

91-
func (s *PluginShim) SetEnable(ctx context.Context, req *protobuf.SetEnableRequest) (*emptypb.Empty, error) {
125+
func (s *CompatV1Shim) SetEnable(ctx context.Context, req *protobuf.SetEnableRequest) (*emptypb.Empty, error) {
92126
if req.User.Id > math.MaxUint {
93127
return nil, errors.New("user id is too large")
94128
}
@@ -105,7 +139,7 @@ func (s *PluginShim) SetEnable(ctx context.Context, req *protobuf.SetEnableReque
105139
}
106140
}
107141

108-
func (s *PluginShim) Display(ctx context.Context, req *protobuf.DisplayRequest) (*protobuf.DisplayResponse, error) {
142+
func (s *CompatV1Shim) Display(ctx context.Context, req *protobuf.DisplayRequest) (*protobuf.DisplayResponse, error) {
109143
if req.User.Id > math.MaxUint {
110144
return nil, errors.New("user id is too large")
111145
}
@@ -127,7 +161,7 @@ func (s *PluginShim) Display(ctx context.Context, req *protobuf.DisplayRequest)
127161
return nil, errors.New("instance does not implement displayer")
128162
}
129163

130-
func (s *PluginShim) DefaultConfig(ctx context.Context, req *protobuf.DefaultConfigRequest) (*protobuf.Config, error) {
164+
func (s *CompatV1Shim) DefaultConfig(ctx context.Context, req *protobuf.DefaultConfigRequest) (*protobuf.Config, error) {
131165
if req.User.Id > math.MaxUint {
132166
return nil, errors.New("user id is too large")
133167
}
@@ -150,7 +184,7 @@ func (s *PluginShim) DefaultConfig(ctx context.Context, req *protobuf.DefaultCon
150184
return nil, errors.New("instance does not implement configurer")
151185
}
152186

153-
func (s *PluginShim) ValidateAndSetConfig(ctx context.Context, req *protobuf.ValidateAndSetConfigRequest) (*protobuf.ValidateAndSetConfigResponse, error) {
187+
func (s *CompatV1Shim) ValidateAndSetConfig(ctx context.Context, req *protobuf.ValidateAndSetConfigRequest) (*protobuf.ValidateAndSetConfigResponse, error) {
154188
if req.User.Id > math.MaxUint {
155189
return nil, errors.New("user id is too large")
156190
}
@@ -183,7 +217,7 @@ func (s *PluginShim) ValidateAndSetConfig(ctx context.Context, req *protobuf.Val
183217
return nil, errors.New("instance does not implement configurer")
184218
}
185219

186-
func (s *PluginShim) RunUserInstance(req *protobuf.UserInstanceRequest, stream protobuf.Plugin_RunUserInstanceServer) error {
220+
func (s *CompatV1Shim) RunUserInstance(req *protobuf.UserInstanceRequest, stream protobuf.Plugin_RunUserInstanceServer) error {
187221
if req.User.Id > math.MaxUint {
188222
return errors.New("user id is too large")
189223
}
@@ -262,7 +296,7 @@ func (s *PluginShim) RunUserInstance(req *protobuf.UserInstanceRequest, stream p
262296
return nil
263297
}
264298

265-
func NewPluginRpc(compatV1 *CompatV1, cliArgs []string) (*PluginShim, error) {
299+
func NewPluginRpc(compatV1 *CompatV1, cliArgs []string) (*CompatV1Shim, error) {
266300
pluginInfo := compatV1.GetPluginInfo()
267301
tlsName := BuildPluginTLSName(purposePluginRPC, pluginInfo.Name)
268302

@@ -296,19 +330,14 @@ func NewPluginRpc(compatV1 *CompatV1, cliArgs []string) (*PluginShim, error) {
296330
RootCAs: rootCAs,
297331
ServerName: tlsName,
298332
ClientAuth: tls.RequireAndVerifyClientCert,
299-
VerifyConnection: func(state tls.ConnectionState) error {
300-
if state.ServerName != ServerTLSName {
301-
return errors.New("not implemented: client must be the gotify server itself for now")
302-
}
303-
return nil
304-
},
333+
ClientCAs: rootCAs,
305334
}
306335

307-
rpcServer := grpc.NewServer(grpc.Creds(credentials.NewTLS(tlsConfig)))
336+
rpcServer := grpc.NewServer()
308337

309338
gin := gin.Default()
310339

311-
self := &PluginShim{
340+
self := &CompatV1Shim{
312341
mu: &sync.RWMutex{},
313342
instances: make(map[uint64]papiv1.Plugin),
314343
compatV1: compatV1,
@@ -321,10 +350,19 @@ func NewPluginRpc(compatV1 *CompatV1, cliArgs []string) (*PluginShim, error) {
321350
protobuf.RegisterDisplayerServer(rpcServer, self)
322351
protobuf.RegisterConfigurerServer(rpcServer, self)
323352

353+
protocols := new(http.Protocols)
354+
protocols.SetHTTP1(true)
355+
protocols.SetHTTP2(true)
356+
self.Server = http.Server{
357+
Handler: self,
358+
TLSConfig: tlsConfig,
359+
Protocols: protocols,
360+
}
361+
324362
return self, nil
325363
}
326364

327-
func (h *PluginShim) ServeHTTP(w http.ResponseWriter, r *http.Request) {
365+
func (h *CompatV1Shim) ServeHTTP(w http.ResponseWriter, r *http.Request) {
328366
if r.TLS == nil {
329367
http.Error(w, "Must use TLS", http.StatusUpgradeRequired)
330368
return
@@ -354,7 +392,3 @@ func (h *PluginShim) ServeHTTP(w http.ResponseWriter, r *http.Request) {
354392

355393
http.Error(w, "Virtual host not found", http.StatusNotFound)
356394
}
357-
358-
func (h *PluginShim) Serve(listener net.Listener) error {
359-
return h.pluginServer.Serve(listener)
360-
}

0 commit comments

Comments
 (0)