Skip to content
Snippets Groups Projects
Commit 385a2069 authored by Ophestra's avatar Ophestra
Browse files

initial implementation of plugin loading

parents
Branches master
No related tags found
No related merge requests found
.idea/
host
\ No newline at end of file
go.mod 0 → 100644
main.go 0 → 100644
package main
import (
"log"
"os"
"os/signal"
"syscall"
)
func main() {
if err := pluginLoad(); err != nil {
log.Fatalf("Error loading plugins, %s", err)
}
// Signal handling
sig := make(chan os.Signal)
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)
}
package partial
// Partial represents a part of the server inserted by a plugin.
type Partial struct {
Route []*WebRoute
Database *DatabaseProvider
}
// WebRoute represents a route.
type WebRoute struct {
Method int
Path string
Handler func()
}
// DatabaseProvider provides a database.
type DatabaseProvider interface {
// DBType returns the type of database in string.
DBType() string
// Open opens the database.
Open(path string) error
// Close closes the database.
Close() error
// Size returns the size of the database.
Size() int64
// Set adds a key-value pair to the database.
Set(key, value string) error
// Get gets the value of a key from the database.
Get(key string) (string, error)
// Del deletes a key from the database.
Del(keys []string) error
// HSet adds a key-value pair to a hashmap.
HSet(hashmap, key, value string) error
// HGet gets the value of a key from a hashmap.
HGet(hashmap, key string) (string, error)
// HDel deletes a key from a hashmap.
HDel(hashmap string, keys []string) error
// HGetAll gets all key-value pairs of a hashmap.
HGetAll(hashmap string) (map[string]string, error)
// HKeys gets all keys of a hashmap.
HKeys(hashmap string) ([]string, error)
// HLen gets the length of a hashmap.
HLen(hashmap string) (int, error)
// Iter iterates through stuff in the database.
Iter(prefetch, includeOffset bool, offset, prefix string, handler func(key, value string) bool) error
}
package partial
import (
"errors"
"plugin"
"strings"
)
var (
ErrOpened = errors.New("plugin already opened")
ErrIncompatible = errors.New("plugin incompatible")
ErrBadSetup = errors.New("plugin has invalid setup")
)
var plugins map[string]*Plugin
// NewPlugin returns pointer to a new Plugin.
func NewPlugin(name string) *Plugin {
return &Plugin{Name: name}
}
// Plugins return a slice of registered plugin names.
func Plugins() []string {
pls := make([]string, len(plugins))
var i int
for name := range plugins {
pls[i] = name
i++
}
return pls
}
// GetPlugin gets plugin with specific name.
func GetPlugin(name string) *Plugin {
return plugins[name]
}
// Plugin holds information on a plugin.
type Plugin struct {
Name string `json:"name"`
Valid bool `json:"valid"`
Partial *Partial `json:"-"`
plugin *plugin.Plugin
}
// Register registers the plugin.
func (p *Plugin) Register() bool {
if _, ok := plugins[p.Name]; !ok {
plugins[p.Name] = p
return true
} else {
return false
}
}
// Open opens the plugin.
func (p *Plugin) Open() error {
if p.plugin == nil {
return ErrOpened
}
if pl, err := plugin.Open("plugins/" + p.Name); err != nil {
if strings.Contains(err.Error(), "plugin was built with a different version of package") {
return ErrIncompatible
} else {
return err
}
} else {
p.plugin = pl
}
if sym, err := p.plugin.Lookup("Setup"); err != nil {
return err
} else {
if setup, ok := sym.(func() (*Partial, error)); !ok {
return ErrBadSetup
} else {
if p.Partial, err = setup(); err != nil {
return err
} else {
p.Valid = true
}
}
}
return nil
}
package main
import (
"git.randomchars.net/leva/hub/host/partial"
"log"
"os"
"strings"
)
func pluginLoad() error {
if entries, err := os.ReadDir("plugins"); err != nil {
if os.IsNotExist(err) {
if err = os.Mkdir("plugins", 0755); err != nil {
return err
} else {
return nil
}
}
log.Fatalf("Error reading plugins directory, %s", err)
return nil
} else {
for _, entry := range entries {
if !entry.IsDir() && strings.HasSuffix(entry.Name(), ".so") {
if !partial.NewPlugin(entry.Name()).Register() {
log.Printf("Plugin %s did not register.", entry.Name())
}
}
}
}
for _, name := range partial.Plugins() {
pl := partial.GetPlugin(name)
if err := pl.Open(); err != nil {
log.Printf("Error loading %s, %s", pl.Name, err)
}
}
return nil
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment