package localserver import ( "context" "log" "net/http" "path/filepath" "sync" "google.golang.org/grpc" "google.golang.org/grpc/credentials" ) var logger *log.Logger = new(log.Logger) var dbLogger *BadgerLogger = &BadgerLogger{ Logger: logger, } type BadgerLogger struct { *log.Logger } func (b *BadgerLogger) Debugf(message string, data ...interface{}) { b.Println(data...) } func (b *BadgerLogger) Errorf(message string, data ...interface{}) { b.Println(data...) } func (b *BadgerLogger) Infof(message string, data ...interface{}) { b.Println(data...) } func (b *BadgerLogger) Warningf(message string, data ...interface{}) { b.Println(data...) } type ( LocalServerHandlerMiddleware interface { Process(ctx context.Context, req *http.Request, w http.ResponseWriter) (err error) } GrpcClientManagerMiddleware interface { Process(ctx context.Context, req *Response, stream GrpcManager_LinkClient) (err error) } LocalServerHandler struct { middlewares []LocalServerHandlerMiddleware } LocalServer struct { ID string GrpcClientManager *GrpcClientManager } GrpcClientManager struct { GrpcConn grpc.ClientConnInterface GrpcManagerClient GrpcManagerClient GrpcLinkClient GrpcManager_LinkClient middlewares []GrpcClientManagerMiddleware } CustomMenuItem struct { //MenuItem *systray.MenuItem ID string State bool SubMenus []*CustomMenuItem CallBack func(bool) } ReqType string LocalServerRequest struct { ReqType ReqType Payload map[string]interface{} } ) func NewLocalServer(addr string, grpcAddr string, id string, token string) (localServer *LocalServer, err error) { webRTCCallManager, err := NewWebRTCCallManager(id, token, NewWebrtcCallSoundManager(), NewWebrtcCallChatManager(), NewWebrtcCallVideoManager(), NewWebrtcCallFileManager()) if err != nil { return } zoneManager, err := NewZoneManager(id, token) if err != nil { return } webrtcFsManager, err := NewWebrtcFsManager(NewP2PFSDatachannelManager()) if err != nil { return } webrtcGrpcMiddleware := NewWebRTCGrpcMiddleware(webRTCCallManager) ZoneGrpcMiddleware := NewZoneGrpcMiddleware(zoneManager) webrtcFsMiddleware := NewWebRTCFsMiddleware(webrtcFsManager) grpcClientManager, err := NewGrpcClientManager(grpcAddr, id, webrtcGrpcMiddleware, ZoneGrpcMiddleware) webrtcGrpcMiddleware.stream = grpcClientManager.GrpcLinkClient webRTCCallManager.stream = grpcClientManager.GrpcLinkClient zoneManager.stream = grpcClientManager.GrpcLinkClient webrtcFsMiddleware.stream = grpcClientManager.GrpcLinkClient webrtcFsManager.stream = grpcClientManager.GrpcLinkClient ZoneGrpcMiddleware.stream = grpcClientManager.GrpcLinkClient localServer = &LocalServer{ ID: id, GrpcClientManager: grpcClientManager, } return } func NewGrpcClientManager(addr string, id string, middleware ...GrpcClientManagerMiddleware) (grpcClientManager *GrpcClientManager, err error) { conn, grpcClient, grpcLinkClient, err := NewGrpcConn(addr, id) if err != nil { return } grpcClientManager = &GrpcClientManager{ GrpcConn: conn, GrpcManagerClient: grpcClient, GrpcLinkClient: grpcLinkClient, middlewares: middleware, } return } func NewGrpcConn(addr string, id string) (conn grpc.ClientConnInterface, grpcClient GrpcManagerClient, grpcLinkClient GrpcManager_LinkClient, err error) { var cert = filepath.Join("config", "cert.pem") creds, err := credentials.NewClientTLSFromFile(cert, "dev.zippytal.com") if err != nil { return } var opts []grpc.DialOption = []grpc.DialOption{grpc.WithTransportCredentials(creds)} conn, err = grpc.Dial(addr, opts...) if err != nil { return } grpcClient = NewGrpcManagerClient(conn) grpcLinkClient, err = grpcClient.Link(context.Background()) if err != nil { logger.Println(err) return } if err = grpcLinkClient.Send(&Request{ Type: "init", From: id, Payload: map[string]string{}, Token: "none", }); err != nil { return } return } func NewLocalServerHandler(middlewares ...LocalServerHandlerMiddleware) (localServerHandler *LocalServerHandler) { localServerHandler = &LocalServerHandler{ middlewares: middlewares, } return } func (lsh *LocalServerHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { wg, done, errCh := &sync.WaitGroup{}, make(chan struct{}), make(chan error) for _, middleware := range lsh.middlewares { wg.Add(1) go func(m LocalServerHandlerMiddleware) { err := m.Process(req.Context(), req, w) if err != nil { errCh <- err } wg.Done() }(middleware) } go func() { wg.Wait() done <- struct{}{} }() select { case <-req.Context().Done(): case <-done: case err := <-errCh: logger.Println(err) } } func (gcm *GrpcClientManager) Handle(ctx context.Context) (err error) { done, errCh := make(chan struct{}), make(chan error) go func() { wg := new(sync.WaitGroup) for { res, err := gcm.GrpcLinkClient.Recv() if err != nil { errCh <- err return } for _, middleware := range gcm.middlewares { wg.Add(1) go func(m GrpcClientManagerMiddleware) { if err := m.Process(ctx, res, gcm.GrpcLinkClient); err != nil { logger.Println(err) } wg.Done() }(middleware) } wg.Wait() } }() select { case <-gcm.GrpcLinkClient.Context().Done(): logger.Println("grpc context") err = gcm.GrpcLinkClient.Context().Err() return case <-ctx.Done(): logger.Println("app context") err = ctx.Err() return case <-done: return case err = <-errCh: if closeErr := gcm.GrpcLinkClient.CloseSend(); closeErr != nil { return closeErr } return } }