You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

server.go 2.8 kB

11 months ago
11 months ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. package rpc
  2. import (
  3. "crypto/tls"
  4. "crypto/x509"
  5. "fmt"
  6. "net"
  7. "os"
  8. "gitlink.org.cn/cloudream/common/pkgs/async"
  9. "gitlink.org.cn/cloudream/common/pkgs/logger"
  10. "google.golang.org/grpc"
  11. "google.golang.org/grpc/credentials"
  12. )
  13. type ServerEventChan = async.UnboundChannel[RPCServerEvent]
  14. type RPCServerEvent interface {
  15. IsRPCServerEvent()
  16. }
  17. type ExitEvent struct {
  18. RPCServerEvent
  19. Err error
  20. }
  21. type Config struct {
  22. Listen string `json:"listen"`
  23. RootCA string `json:"rootCA"`
  24. ServerCert string `json:"serverCert"`
  25. ServerKey string `json:"serverKey"`
  26. }
  27. type ServerBase struct {
  28. cfg Config
  29. grpcSvr *grpc.Server
  30. srvImpl any
  31. svcDesc *grpc.ServiceDesc
  32. rootCA *x509.CertPool
  33. serverCert tls.Certificate
  34. accessTokenAuthAPIs map[string]bool
  35. tokenVerifier AccessTokenVerifier
  36. noAuthAPIs map[string]bool
  37. }
  38. func NewServerBase(cfg Config, srvImpl any, svcDesc *grpc.ServiceDesc, accessTokenAuthAPIs []string, tokenVerifier AccessTokenVerifier, noAuthAPIs []string) *ServerBase {
  39. tokenAuthAPIs := make(map[string]bool)
  40. for _, api := range accessTokenAuthAPIs {
  41. tokenAuthAPIs[api] = true
  42. }
  43. noAuths := make(map[string]bool)
  44. for _, api := range noAuthAPIs {
  45. noAuths[api] = true
  46. }
  47. return &ServerBase{
  48. cfg: cfg,
  49. srvImpl: srvImpl,
  50. svcDesc: svcDesc,
  51. accessTokenAuthAPIs: tokenAuthAPIs,
  52. tokenVerifier: tokenVerifier,
  53. noAuthAPIs: noAuths,
  54. }
  55. }
  56. func (s *ServerBase) Start() *ServerEventChan {
  57. ch := async.NewUnboundChannel[RPCServerEvent]()
  58. go func() {
  59. svrCert, err := tls.LoadX509KeyPair(s.cfg.ServerCert, s.cfg.ServerKey)
  60. if err != nil {
  61. logger.Warnf("load server cert: %v", err)
  62. ch.Send(&ExitEvent{Err: err})
  63. return
  64. }
  65. s.serverCert = svrCert
  66. rootCA, err := os.ReadFile(s.cfg.RootCA)
  67. if err != nil {
  68. logger.Warnf("load root ca: %v", err)
  69. ch.Send(&ExitEvent{Err: err})
  70. return
  71. }
  72. s.rootCA = x509.NewCertPool()
  73. if !s.rootCA.AppendCertsFromPEM(rootCA) {
  74. logger.Warnf("load root ca: failed to parse root ca")
  75. ch.Send(&ExitEvent{Err: fmt.Errorf("failed to parse root ca")})
  76. return
  77. }
  78. logger.Infof("start serving rpc at: %v", s.cfg.Listen)
  79. lis, err := net.Listen("tcp", s.cfg.Listen)
  80. if err != nil {
  81. ch.Send(&ExitEvent{Err: err})
  82. return
  83. }
  84. s.grpcSvr = grpc.NewServer(
  85. grpc.Creds(credentials.NewTLS(&tls.Config{
  86. GetConfigForClient: s.tlsConfigSelector,
  87. })),
  88. grpc.UnaryInterceptor(s.authUnary),
  89. grpc.StreamInterceptor(s.authStream),
  90. )
  91. s.grpcSvr.RegisterService(s.svcDesc, s.srvImpl)
  92. err = s.grpcSvr.Serve(lis)
  93. ch.Send(&ExitEvent{Err: err})
  94. }()
  95. return ch
  96. }
  97. func (s *ServerBase) Stop() {
  98. if s.grpcSvr != nil {
  99. s.grpcSvr.Stop()
  100. }
  101. }

本项目旨在将云际存储公共基础设施化,使个人及企业可低门槛使用高效的云际存储服务(安装开箱即用云际存储客户端即可,无需关注其他组件的部署),同时支持用户灵活便捷定制云际存储的功能细节。