Implement dynamic plugins support (by RPC)

This commit is contained in:
ChronosX88 2020-02-12 20:39:57 +04:00
parent 7e534680c7
commit 1584f9e58a
23 changed files with 435 additions and 121 deletions

View File

@ -1,16 +1,22 @@
package main
import (
"errors"
"flag"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"github.com/ChronosX88/zirconium/internal"
core "github.com/ChronosX88/zirconium/core"
"github.com/google/logger"
"github.com/gorilla/mux"
"github.com/gorilla/websocket"
"github.com/pelletier/go-toml"
)
var connectionHandler = internal.NewConnectionHandler()
var connectionHandler = core.NewConnectionHandler()
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
@ -18,7 +24,44 @@ var upgrader = websocket.Upgrader{
}
func main() {
internal.InitializeContext("localhost")
var cfg core.ServerConfig
var configPath string
var generateConfig bool
flag.StringVar(&configPath, "config", "", "Path to config")
flag.BoolVar(&generateConfig, "gen_config", false, "Generate the config")
flag.Parse()
if generateConfig == true {
sampleConfig := &core.ServerConfig{}
val, err := toml.Marshal(sampleConfig)
if err != nil {
logger.Errorf("Failed to generate config: %s", err.Error())
os.Exit(1)
}
fmt.Println(string(val))
os.Exit(0)
}
if configPath == "" {
logger.Error("Path to config isn't specified!")
os.Exit(1)
}
cfgData, err := ioutil.ReadFile(configPath)
if err != nil {
logger.Error("Failed to read config!")
os.Exit(1)
}
err = toml.Unmarshal(cfgData, &cfg)
if err != nil {
logger.Errorf("Failed to read config! (yaml error: %s)", err.Error())
os.Exit(1)
}
err = validateConfig(&cfg)
if err != nil {
logger.Errorf("Config validation failed: %s", err.Error())
os.Exit(1)
}
core.InitializeContext(cfg.ServerDomain, cfg.PluginsDirPath, cfg.EnabledPlugins)
router := mux.NewRouter()
router.HandleFunc("/", func(response http.ResponseWriter, request *http.Request) {
response.Write([]byte("Zirconium server is up and running!"))
@ -36,3 +79,12 @@ func wsHandler(w http.ResponseWriter, r *http.Request) {
}
connectionHandler.HandleNewConnection(ws)
}
func validateConfig(config *core.ServerConfig) error {
if config.ServerDomain == "" {
return errors.New("server domain isn't specified")
} else if config.PluginsDirPath == "" {
return errors.New("plugin directory path isn't specified")
}
return nil
}

View File

@ -1,4 +1,4 @@
package internal
package core
import (
"encoding/base64"

4
core/builtin_plugins.go Normal file
View File

@ -0,0 +1,4 @@
package core
// BuiltinPlugins is a list of builtin plugins
var BuiltinPlugins = map[string]Module{}

12
core/config.go Normal file
View File

@ -0,0 +1,12 @@
package core
type ServerConfig struct {
// A list of enabled plugins (or extensions) in server
EnabledPlugins []string `toml:"enabledPlugins" comment:"A list of enabled plugins (or extensions) in server"`
// Server domain name (e.g. example.com)
ServerDomain string `toml:"serverDomain" comment:"Server domain name (e.g. example.com)"`
// Path to directory with plugin executables
PluginsDirPath string `toml:"pluginsDirPath" comment:"Path to directory with plugin executables"`
}

View File

@ -1,7 +1,7 @@
package internal
package core
import (
"github.com/ChronosX88/zirconium/internal/models"
"github.com/ChronosX88/zirconium/core/models"
"github.com/google/logger"
"github.com/google/uuid"
"github.com/gorilla/websocket"

41
core/globals.go Normal file
View File

@ -0,0 +1,41 @@
package core
import (
"github.com/google/logger"
)
var (
moduleMgr *ModuleManager
router *Router
authManager *AuthManager
serverDomain string
pluginManager *PluginManager
)
func InitializeContext(sDomain string, pluginsDirPath string, enabledPlugins []string) {
var err error
moduleMgr, err = NewModuleManager()
if err != nil {
logger.Fatalf("Unable to initialize module manager: %s", err.Error())
}
router, err = NewRouter()
if err != nil {
logger.Fatalf("Unable to initialize router: %s", err.Error())
}
authManager, err = NewAuthManager()
if err != nil {
logger.Fatalf("Unable to initialize authentication manager: %s", err.Error())
}
serverDomain = sDomain
for _, v := range BuiltinPlugins {
go v.Initialize(moduleMgr) // Initialize builtin plugins
}
pluginManager = NewPluginManager()
for _, v := range enabledPlugins {
pluginManager.StartPlugin(pluginsDirPath, v, moduleMgr)
}
}

17
core/module.go Normal file
View File

@ -0,0 +1,17 @@
package core
const (
ModuleInterfaceName = "Module"
)
type Module interface {
Initialize(moduleAPI *ModuleManager)
Name() string
Version() string
}
type ModuleRef struct {
F func() Module
}
type ModuleFunc func() Module

View File

@ -1,11 +1,11 @@
package internal
package core
import (
"reflect"
"sync"
"time"
"github.com/ChronosX88/zirconium/internal/models"
"github.com/ChronosX88/zirconium/core/models"
)
type C2SMessageHandler struct {
@ -16,13 +16,13 @@ type C2SMessageHandler struct {
type ModuleManager struct {
moduleMutex sync.Mutex
c2sMessageHandlers map[string][]*C2SMessageHandler
internalEventHandlers map[string][]func(sourceModuleName string, event map[string]interface{})
coreEventHandlers map[string][]func(sourceModuleName string, event map[string]interface{})
}
func NewModuleManager() (*ModuleManager, error) {
var mm = &ModuleManager{
c2sMessageHandlers: make(map[string][]*C2SMessageHandler),
internalEventHandlers: make(map[string][]func(sourceModuleName string, event map[string]interface{})),
coreEventHandlers: make(map[string][]func(sourceModuleName string, event map[string]interface{})),
}
return mm, nil
}
@ -36,9 +36,9 @@ func (mm *ModuleManager) Hook(messageType string, anonymousAllowed bool, handler
mm.moduleMutex.Unlock()
}
func (mm *ModuleManager) HookInternalEvent(eventName string, handlerFunc func(sourceModuleName string, event map[string]interface{})) {
func (mm *ModuleManager) HookcoreEvent(eventName string, handlerFunc func(sourceModuleName string, event map[string]interface{})) {
mm.moduleMutex.Lock()
mm.internalEventHandlers[eventName] = append(mm.internalEventHandlers[eventName], handlerFunc)
mm.coreEventHandlers[eventName] = append(mm.coreEventHandlers[eventName], handlerFunc)
mm.moduleMutex.Unlock()
}
@ -59,17 +59,17 @@ func (mm *ModuleManager) Unhook(messageType string, handlerFunc func(origin *Ori
}
}
func (mm *ModuleManager) UnhookInternalEvent(eventName string, handlerFunc func(sourceModuleName string, event map[string]interface{})) {
func (mm *ModuleManager) UnhookcoreEvent(eventName string, handlerFunc func(sourceModuleName string, event map[string]interface{})) {
mm.moduleMutex.Lock()
defer mm.moduleMutex.Unlock()
var handlers = mm.internalEventHandlers[eventName]
var handlers = mm.coreEventHandlers[eventName]
if handlers != nil {
for i, v := range handlers {
if reflect.ValueOf(v).Pointer() == reflect.ValueOf(handlerFunc).Pointer() {
handlers[i] = handlers[len(handlers)-1]
handlers[len(handlers)-1] = nil
handlers = handlers[:len(handlers)-1]
mm.internalEventHandlers[eventName] = handlers
mm.coreEventHandlers[eventName] = handlers
break
}
}
@ -77,7 +77,7 @@ func (mm *ModuleManager) UnhookInternalEvent(eventName string, handlerFunc func(
}
func (mm *ModuleManager) FireEvent(sourceModuleName string, eventName string, eventPayload map[string]interface{}) {
router.RouteInternalEvent(sourceModuleName, eventName, eventPayload)
router.RoutecoreEvent(sourceModuleName, eventName, eventPayload)
}
func (mm *ModuleManager) GenerateToken(entityID, deviceID string, tokenExpireTimeDuration time.Duration) (string, error) {

View File

@ -0,0 +1,38 @@
package core
import (
"errors"
"github.com/hashicorp/go-plugin"
)
type greeterServer struct {
Broker *plugin.MuxBroker
Module Module
}
// Server implmentation of go-plugin.plugin.Plugin.Server
func (p *ModuleRef) Server(b *plugin.MuxBroker) (interface{}, error) {
if p.F == nil {
return nil, errors.New("Greeter interface not implemeted")
}
return &greeterServer{Broker: b, Module: p.F()}, nil
}
// Name calls the plugin implementation to get the name of the plugin
func (p *greeterServer) Name(nothing interface{}, result *string) error {
*result = p.Module.Name()
return nil
}
// Version calls the plugin implementation to get the version of the plugin
func (p *greeterServer) Version(nothing interface{}, result *string) error {
*result = p.Module.Version()
return nil
}
// StartTime calls the plugin implementation to initialize plugin
func (p *greeterServer) Initialize(moduleAPI *ModuleManager, emptyResult interface{}) error {
p.Module.Initialize(moduleAPI)
return nil
}

48
core/module_rpc_sender.go Normal file
View File

@ -0,0 +1,48 @@
package core
import (
"log"
"net/rpc"
"github.com/hashicorp/go-plugin"
)
type moduleClient struct {
Broker *plugin.MuxBroker
Client *rpc.Client
}
// Client implmentation of go-plugin.plugin.Plugin.Client
func (p *ModuleRef) Client(b *plugin.MuxBroker, c *rpc.Client) (interface{}, error) {
return &moduleClient{Broker: b, Client: c}, nil
}
// Name initiates an RPC call to the plugin name
func (p *moduleClient) Name() string {
var resp string
err := p.Client.Call("Plugin.Name", new(interface{}), &resp)
if err != nil {
log.Fatal(err) // FIXME
}
return resp
}
// Version initiates an RPC call to the plugin version
func (p *moduleClient) Version() string {
var resp string
err := p.Client.Call("Plugin.Version", new(interface{}), &resp)
if err != nil {
log.Fatal(err) // FIXME
}
return resp
}
// StartTime initiates an RPC call to the plugin for initializing
func (p *moduleClient) Initialize(moduleAPI *ModuleManager) {
err := p.Client.Call("Plugin.Initialize", map[string]interface{}{
"moduleAPI": moduleAPI,
}, nil)
if err != nil {
log.Fatal(err) // FIXME
}
}

View File

@ -1,7 +1,7 @@
package internal
package core
import (
"github.com/ChronosX88/zirconium/internal/models"
"github.com/ChronosX88/zirconium/core/models"
"github.com/gorilla/websocket"
)

56
core/plugin_manager.go Normal file
View File

@ -0,0 +1,56 @@
package core
import (
"os"
"os/exec"
"path/filepath"
"github.com/google/logger"
"github.com/hashicorp/go-plugin"
)
type PluginManager struct{}
func NewPluginManager() *PluginManager {
return &PluginManager{}
}
func (p *PluginManager) StartPlugin(pluginsDirPath, pluginFile string, moduleManager *ModuleManager) error {
pluginsDirectory, _ := filepath.Abs(filepath.Dir(pluginsDirPath))
pluginFile = filepath.Join(pluginsDirectory, pluginFile)
logger.Info("Starting plugin: %s", pluginFile)
client := plugin.NewClient(&plugin.ClientConfig{
Cmd: exec.Command(pluginFile),
Managed: true,
SyncStdout: os.Stdout,
SyncStderr: os.Stderr,
HandshakeConfig: HandshakeConfig,
Plugins: GetPluginMap(nil),
})
rpcclient, err := client.Client()
if err != nil {
logger.Errorf("Failed to get RPC Client: %s", err)
client.Kill()
return err
}
// get the interface
raw, err := rpcclient.Dispense(ModuleInterfaceName)
if err != nil {
logger.Errorf("Failed to get interface: %s error: %s", ModuleInterfaceName, err)
return err
}
moduleObj := raw.(Module)
go func() {
moduleObj.Initialize(moduleManager)
}()
return nil
}

View File

@ -1,7 +1,7 @@
package internal
package core
import (
"github.com/ChronosX88/zirconium/internal/models"
"github.com/ChronosX88/zirconium/core/models"
"github.com/google/logger"
)
@ -64,8 +64,8 @@ func (r *Router) RouteMessage(origin *OriginC2S, message models.BaseMessage) {
}
}
func (r *Router) RouteInternalEvent(sourceModuleName string, eventName string, eventPayload map[string]interface{}) {
handlers := r.moduleManager.internalEventHandlers[eventName]
func (r *Router) RoutecoreEvent(sourceModuleName string, eventName string, eventPayload map[string]interface{}) {
handlers := r.moduleManager.coreEventHandlers[eventName]
if handlers != nil {
for _, v := range handlers {
go v(sourceModuleName, eventPayload)

99
core/utils.go Normal file
View File

@ -0,0 +1,99 @@
package core
import (
"crypto/rand"
"log"
"reflect"
"github.com/ChronosX88/zirconium/core/models"
"github.com/google/logger"
"github.com/hashicorp/go-plugin"
)
func GenRandomBytes(size int) (blk []byte, err error) {
blk = make([]byte, size)
_, err = rand.Read(blk)
return
}
func StructToMap(item interface{}) map[string]interface{} {
res := map[string]interface{}{}
if item == nil {
return res
}
v := reflect.TypeOf(item)
reflectValue := reflect.ValueOf(item)
reflectValue = reflect.Indirect(reflectValue)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
for i := 0; i < v.NumField(); i++ {
tag := v.Field(i).Tag.Get("json")
field := reflectValue.Field(i).Interface()
if tag != "" && tag != "-" {
if v.Field(i).Type.Kind() == reflect.Struct {
res[tag] = StructToMap(field)
} else {
res[tag] = field
}
}
}
return res
}
func PrepareMessageUnauthorized(msg models.BaseMessage) models.BaseMessage {
protocolError := models.ProtocolError{
ErrCode: "unauthorized",
ErrText: "Unauthorized access",
ErrPayload: make(map[string]interface{}),
}
errMsg := models.NewBaseMessage(msg.ID, msg.MessageType, serverDomain, msg.From, false, StructToMap(protocolError))
return errMsg
}
var HandshakeConfig = plugin.HandshakeConfig{
ProtocolVersion: 1,
MagicCookieKey: "TEST_TEST",
MagicCookieValue: "qwerty",
}
type PluginOpts struct {
Module ModuleFunc
RunAsPlugin bool
}
// GetPluginMap returns the plugin map defined Hashicorp go-plugin.
// The reserved parameter should only be used by the RPC receiver (the plugin).
// Otherwise, reserved should be nil for the RPC sender (the mainapp).
func GetPluginMap(reserved *PluginOpts) map[string]plugin.Plugin {
var moduleObj ModuleRef
if reserved != nil {
moduleObj.F = reserved.Module
}
return map[string]plugin.Plugin{
ModuleInterfaceName: &moduleObj,
}
}
func StartPlugin(opts *PluginOpts, quit chan bool) {
if opts.RunAsPlugin {
go func() {
logger.Info("Starting plugin communication...")
plugin.Serve(&plugin.ServeConfig{
HandshakeConfig: HandshakeConfig,
Plugins: GetPluginMap(opts),
})
logger.Info("Exiting plugin communication...")
quit <- true
logger.Info("Exiting plugin...")
}()
} else {
log.Println("Starting in standalone mode...")
}
}

2
go.mod
View File

@ -8,4 +8,6 @@ require (
github.com/google/uuid v1.1.1
github.com/gorilla/mux v1.7.3
github.com/gorilla/websocket v1.4.1
github.com/hashicorp/go-plugin v1.0.1
github.com/pelletier/go-toml v1.6.0
)

41
go.sum
View File

@ -1,5 +1,14 @@
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/logger v1.0.1 h1:Jtq7/44yDwUXMaLTYgXFC31zpm6Oku7OI/k4//yVANQ=
github.com/google/logger v1.0.1/go.mod h1:w7O8nrRr0xufejBlQMI83MXqRusvREoJdaAxV+CoAB4=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
@ -8,5 +17,37 @@ github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd h1:rNuUHR+CvK1IS89MMtcF0EpcVMZtjKfPRp4MEmt/aTs=
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
github.com/hashicorp/go-plugin v1.0.1 h1:4OtAfUGbnKC6yS48p0CtMX2oFYtzFZVv6rok3cRWgnE=
github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY=
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M=
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77 h1:7GoSOOW2jpsfkntVKaS2rAr1TJqfcxotyaUcuxoZSzg=
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/pelletier/go-toml v1.6.0 h1:aetoXYr0Tv7xRU/V4B4IZJ2QcbtMUFoNb3ORp7TzIK4=
github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d h1:g9qWBGx4puODJTMVyoPrpoxPFgVGd+z1DZwjfRu4d0I=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/grpc v1.14.0 h1:ArxJuB1NWfPY6r9Gp9gqwplT0Ge7nqv9msgu03lHLmo=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@ -1,36 +0,0 @@
package internal
import (
"github.com/ChronosX88/zirconium/shared"
"github.com/google/logger"
)
var (
ModuleMgr *ModuleManager
router *Router
authManager *AuthManager
serverDomain string
)
func InitializeContext(sDomain string) {
var err error
ModuleMgr, err = NewModuleManager()
if err != nil {
logger.Fatalf("Unable to initialize module manager: %s", err.Error())
}
router, err = NewRouter()
if err != nil {
logger.Fatalf("Unable to initialize router: %s", err.Error())
}
authManager, err = NewAuthManager()
if err != nil {
logger.Fatalf("Unable to initialize authentication manager: %s", err.Error())
}
serverDomain = sDomain
for _, v := range shared.Plugins {
go v.Initialize() // Initialize provided plugins
}
}

View File

@ -1,50 +0,0 @@
package internal
import (
"crypto/rand"
"reflect"
"github.com/ChronosX88/zirconium/internal/models"
)
func GenRandomBytes(size int) (blk []byte, err error) {
blk = make([]byte, size)
_, err = rand.Read(blk)
return
}
func StructToMap(item interface{}) map[string]interface{} {
res := map[string]interface{}{}
if item == nil {
return res
}
v := reflect.TypeOf(item)
reflectValue := reflect.ValueOf(item)
reflectValue = reflect.Indirect(reflectValue)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
for i := 0; i < v.NumField(); i++ {
tag := v.Field(i).Tag.Get("json")
field := reflectValue.Field(i).Interface()
if tag != "" && tag != "-" {
if v.Field(i).Type.Kind() == reflect.Struct {
res[tag] = StructToMap(field)
} else {
res[tag] = field
}
}
}
return res
}
func PrepareMessageUnauthorized(msg models.BaseMessage) models.BaseMessage {
protocolError := models.ProtocolError{
ErrCode: "unauthorized",
ErrText: "Unauthorized access",
ErrPayload: make(map[string]interface{}),
}
errMsg := models.NewBaseMessage(msg.ID, msg.MessageType, serverDomain, msg.From, false, StructToMap(protocolError))
return errMsg
}

View File

@ -1,5 +0,0 @@
package shared
type Module interface {
Initialize()
}

View File

@ -1,5 +0,0 @@
package shared
var Plugins = map[string]Module{
// Add plugins here
}