working commit
This commit is contained in:
@@ -0,0 +1,151 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"mbase/app/handler"
|
||||
"mbase/app/logic"
|
||||
"mbase/pkg/logger"
|
||||
"mbase/pkg/netacl"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/peer"
|
||||
)
|
||||
|
||||
type ServiceConfig struct {
|
||||
Handler *handler.Handler
|
||||
Logic *logic.Logic
|
||||
NetACL *netacl.NetACL
|
||||
Portnum uint32
|
||||
Address string
|
||||
Protocol string
|
||||
Hostname string
|
||||
X509Cert []byte
|
||||
X509Key []byte
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
gsrv *grpc.Server
|
||||
hand *handler.Handler
|
||||
lg *logic.Logic
|
||||
log *logger.Logger
|
||||
nacl *netacl.NetACL
|
||||
portnum uint32
|
||||
address string
|
||||
protocol string
|
||||
hostname string
|
||||
username string
|
||||
password string
|
||||
x509Cert []byte
|
||||
x509Key []byte
|
||||
}
|
||||
|
||||
func NewService(conf *ServiceConfig) *Service {
|
||||
svc := Service{
|
||||
hand: conf.Handler,
|
||||
lg: conf.Logic,
|
||||
nacl: conf.NetACL,
|
||||
portnum: conf.Portnum,
|
||||
address: conf.Address,
|
||||
protocol: conf.Protocol,
|
||||
hostname: conf.Hostname,
|
||||
x509Cert: conf.X509Cert,
|
||||
x509Key: conf.X509Key,
|
||||
}
|
||||
svc.log = logger.NewLogger("gservice")
|
||||
return &svc
|
||||
}
|
||||
|
||||
func (svc *Service) Run() error {
|
||||
var err error
|
||||
svc.log.Infof("Service run")
|
||||
|
||||
listenSpec := fmt.Sprintf("%s:%d", svc.address, svc.portnum)
|
||||
listener, err := net.Listen(svc.protocol, listenSpec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tlsCert, err := tls.X509KeyPair(svc.x509Cert, svc.x509Key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tlsConfig := tls.Config{
|
||||
Certificates: []tls.Certificate{tlsCert},
|
||||
ClientAuth: tls.NoClientCert,
|
||||
InsecureSkipVerify: true,
|
||||
}
|
||||
|
||||
tlsCredentials := credentials.NewTLS(&tlsConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
interceptors := []grpc.UnaryServerInterceptor{
|
||||
svc.accessInterceptor,
|
||||
svc.logInterceptor,
|
||||
}
|
||||
|
||||
gsrvOpts := []grpc.ServerOption{
|
||||
grpc.Creds(tlsCredentials),
|
||||
grpc.ChainUnaryInterceptor(interceptors...),
|
||||
}
|
||||
svc.gsrv = grpc.NewServer(gsrvOpts...)
|
||||
|
||||
svc.hand.Register(svc.gsrv)
|
||||
|
||||
svc.log.Infof("Service listening at %v", listener.Addr())
|
||||
err = svc.gsrv.Serve(listener)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (svc *Service) accessInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
|
||||
peerMeta, _ := peer.FromContext(ctx)
|
||||
host, _, err := net.SplitHostPort(peerMeta.Addr.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
addressEnabled, _ := svc.nacl.AddressIsEnabled(host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if addressEnabled {
|
||||
svc.log.Warningf("Enable access from %s", host)
|
||||
return handler(ctx, req)
|
||||
}
|
||||
svc.log.Warningf("Disable access from %s", host)
|
||||
return nil, fmt.Errorf("Access disabled by network ACL")
|
||||
}
|
||||
|
||||
func (svc *Service) logInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
|
||||
meta, _ := metadata.FromIncomingContext(ctx)
|
||||
peerMeta, _ := peer.FromContext(ctx)
|
||||
svc.log.Infof("User %v called %v from %s", meta["username"], info.FullMethod, peerMeta.Addr.String())
|
||||
return handler(ctx, req)
|
||||
}
|
||||
|
||||
func (svc *Service) debugInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
|
||||
var err error
|
||||
reqBinary, err := json.Marshal(req)
|
||||
requestString := ""
|
||||
if err == nil {
|
||||
requestString = string(reqBinary)
|
||||
}
|
||||
svc.log.Debugf("Called method: %v with params %v", info.FullMethod, requestString)
|
||||
return handler(ctx, req)
|
||||
}
|
||||
|
||||
func (svc *Service) Stop() {
|
||||
svc.log.Infof("Stopping service")
|
||||
svc.gsrv.GracefulStop()
|
||||
}
|
||||
Reference in New Issue
Block a user