mirror of
https://shylinux.com/x/icebergs
synced 2025-04-25 17:18:05 +08:00
add web.HandleWSS
This commit is contained in:
parent
fe6226481e
commit
47bb65632d
97
core.go
Normal file
97
core.go
Normal file
@ -0,0 +1,97 @@
|
||||
package ice
|
||||
|
||||
import (
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Frame struct {
|
||||
}
|
||||
|
||||
func (f *Frame) Spawn(m *Message, c *Context, arg ...string) Server {
|
||||
return &Frame{}
|
||||
}
|
||||
func (f *Frame) Begin(m *Message, arg ...string) Server {
|
||||
list := map[*Context]*Message{m.target: m}
|
||||
m.Travel(func(p *Context, s *Context) {
|
||||
if msg, ok := list[p]; ok && msg != nil {
|
||||
sub := msg.Spawns(s)
|
||||
s.Begin(sub, arg...)
|
||||
list[s] = sub
|
||||
}
|
||||
})
|
||||
return f
|
||||
}
|
||||
func (f *Frame) Start(m *Message, arg ...string) bool {
|
||||
// 加载配置
|
||||
m.Travel(func(p *Context, s *Context) {
|
||||
if cmd, ok := s.Commands["_init"]; ok {
|
||||
msg := m.Spawns(s)
|
||||
msg.Log("_init", s.Name)
|
||||
cmd.Hand(msg, s, "_init", arg...)
|
||||
}
|
||||
})
|
||||
|
||||
// 启动服务
|
||||
Index.begin.Cmd(arg)
|
||||
|
||||
m.Travel(func(p *Context, s *Context) {
|
||||
if cmd, ok := s.Commands["_exit"]; ok {
|
||||
msg := m.Spawns(s)
|
||||
msg.Log("_exit", "some")
|
||||
cmd.Hand(msg, s, "_exit", arg...)
|
||||
}
|
||||
})
|
||||
// 保存配置
|
||||
return true
|
||||
}
|
||||
func (f *Frame) Close(m *Message, arg ...string) bool {
|
||||
list := map[*Context]*Message{m.target: m}
|
||||
m.Travel(func(p *Context, s *Context) {
|
||||
if msg, ok := list[p]; ok && msg != nil {
|
||||
sub := msg.Spawns(s)
|
||||
s.Close(sub, arg...)
|
||||
list[s] = sub
|
||||
}
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
var Index = &Context{Name: "ice", Help: "冰山模块",
|
||||
Caches: map[string]*Cache{},
|
||||
Configs: map[string]*Config{},
|
||||
Commands: map[string]*Command{
|
||||
"_init": {Name: "_init", Help: "hello", Hand: func(m *Message, c *Context, cmd string, arg ...string) {
|
||||
m.Echo("hello %s world", c.Name)
|
||||
}},
|
||||
"hi": {Name: "hi", Help: "hello", Hand: func(m *Message, c *Context, cmd string, arg ...string) {
|
||||
m.Echo("hello %s world", c.Name)
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
var Pulse = &Message{
|
||||
time: time.Now(), code: 0,
|
||||
meta: map[string][]string{},
|
||||
data: map[string]interface{}{},
|
||||
|
||||
messages: []*Message{}, message: nil, root: nil,
|
||||
source: Index, target: Index, Hand: true,
|
||||
}
|
||||
|
||||
func init() {
|
||||
Index.root = Index
|
||||
Pulse.root = Pulse
|
||||
Index.server = &Frame{}
|
||||
}
|
||||
|
||||
func Run(arg ...string) string {
|
||||
if len(arg) == 0 {
|
||||
arg = os.Args[1:]
|
||||
}
|
||||
|
||||
if Index.Begin(Pulse.Spawns(), arg...).Start(Index.begin.Spawns(), arg...) {
|
||||
Index.Close(Index.start.Spawns(), arg...)
|
||||
}
|
||||
return Pulse.Result()
|
||||
}
|
17
core/aaa/aaa.go
Normal file
17
core/aaa/aaa.go
Normal file
@ -0,0 +1,17 @@
|
||||
package aaa
|
||||
|
||||
import (
|
||||
"github.com/shylinux/icebergs"
|
||||
)
|
||||
|
||||
var Index = &ice.Context{Name: "aaa", Help: "认证模块",
|
||||
Caches: map[string]*ice.Cache{},
|
||||
Configs: map[string]*ice.Config{},
|
||||
Commands: map[string]*ice.Command{
|
||||
"hi": {Name: "hi", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
m.Echo("hello %s world", c.Name)
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
func init() { ice.Index.Register(Index, nil) }
|
68
core/cli/cli.go
Normal file
68
core/cli/cli.go
Normal file
@ -0,0 +1,68 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/shylinux/icebergs"
|
||||
"github.com/shylinux/toolkits"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"path"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
var Index = &ice.Context{Name: "cli", Help: "命令模块",
|
||||
Caches: map[string]*ice.Cache{},
|
||||
Configs: map[string]*ice.Config{
|
||||
"runtime": {Name: "runtime", Value: map[string]interface{}{
|
||||
"host": map[string]interface{}{},
|
||||
"boot": map[string]interface{}{},
|
||||
"node": map[string]interface{}{},
|
||||
"user": map[string]interface{}{},
|
||||
"work": map[string]interface{}{},
|
||||
}},
|
||||
},
|
||||
Commands: map[string]*ice.Command{
|
||||
"_init": {Name: "_init", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
m.Conf("runtime", "host.GOARCH", runtime.GOARCH)
|
||||
m.Conf("runtime", "host.GOOS", runtime.GOOS)
|
||||
m.Conf("runtime", "host.pid", os.Getpid())
|
||||
|
||||
if name, e := os.Hostname(); e == nil {
|
||||
m.Conf("runtime", "boot.hostname", kit.Select(name, os.Getenv("HOSTNAME")))
|
||||
}
|
||||
if user, e := user.Current(); e == nil {
|
||||
m.Conf("runtime", "boot.username", path.Base(kit.Select(user.Name, os.Getenv("USER"))))
|
||||
}
|
||||
if name, e := os.Getwd(); e == nil {
|
||||
m.Conf("runtime", "boot.pathname", path.Base(kit.Select(name, os.Getenv("PWD"))))
|
||||
}
|
||||
|
||||
m.Conf("runtime", "node.type", "worker")
|
||||
m.Log("info", "runtime %v", kit.Formats(m.Confv("runtime")))
|
||||
}},
|
||||
"runtime": {Name: "runtime", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
}},
|
||||
"system": {Name: "system", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
out := bytes.NewBuffer(make([]byte, 0, 1024))
|
||||
err := bytes.NewBuffer(make([]byte, 0, 1024))
|
||||
|
||||
sys := exec.Command(arg[0], arg[1:]...)
|
||||
sys.Stdout = out
|
||||
sys.Stderr = err
|
||||
|
||||
if e := sys.Run(); e != nil {
|
||||
m.Echo("error: ").Echo(kit.Select(e.Error(), err.String()))
|
||||
return
|
||||
}
|
||||
m.Echo(out.String())
|
||||
}},
|
||||
"timer": {Name: "timer", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
}},
|
||||
"hi": {Name: "hi", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
m.Echo("hello %s world", c.Name)
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
func init() { ice.Index.Register(Index, nil) }
|
17
core/ctx/ctx.go
Normal file
17
core/ctx/ctx.go
Normal file
@ -0,0 +1,17 @@
|
||||
package ctx
|
||||
|
||||
import (
|
||||
"github.com/shylinux/icebergs"
|
||||
)
|
||||
|
||||
var Index = &ice.Context{Name: "ctx", Help: "元始模块",
|
||||
Caches: map[string]*ice.Cache{},
|
||||
Configs: map[string]*ice.Config{},
|
||||
Commands: map[string]*ice.Command{
|
||||
"hi": {Name: "hi", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
m.Echo("hello %s world", c.Name)
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
func init() { ice.Index.Register(Index, nil) }
|
17
core/gdb/gdb.go
Normal file
17
core/gdb/gdb.go
Normal file
@ -0,0 +1,17 @@
|
||||
package gdb
|
||||
|
||||
import (
|
||||
"github.com/shylinux/icebergs"
|
||||
)
|
||||
|
||||
var Index = &ice.Context{Name: "gdb", Help: "调试模块",
|
||||
Caches: map[string]*ice.Cache{},
|
||||
Configs: map[string]*ice.Config{},
|
||||
Commands: map[string]*ice.Command{
|
||||
"hi": {Name: "hi", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
m.Echo("hello %s world", c.Name)
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
func init() { ice.Index.Register(Index, nil) }
|
17
core/lex/lex.go
Normal file
17
core/lex/lex.go
Normal file
@ -0,0 +1,17 @@
|
||||
package lex
|
||||
|
||||
import (
|
||||
"github.com/shylinux/icebergs"
|
||||
)
|
||||
|
||||
var Index = &ice.Context{Name: "lex", Help: "词法模块",
|
||||
Caches: map[string]*ice.Cache{},
|
||||
Configs: map[string]*ice.Config{},
|
||||
Commands: map[string]*ice.Command{
|
||||
"hi": {Name: "hi", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
m.Echo("hello %s world", c.Name)
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
func init() { ice.Index.Register(Index, nil) }
|
17
core/log/log.go
Normal file
17
core/log/log.go
Normal file
@ -0,0 +1,17 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"github.com/shylinux/icebergs"
|
||||
)
|
||||
|
||||
var Index = &ice.Context{Name: "log", Help: "日志模块",
|
||||
Caches: map[string]*ice.Cache{},
|
||||
Configs: map[string]*ice.Config{},
|
||||
Commands: map[string]*ice.Command{
|
||||
"hi": {Name: "hi", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
m.Echo("hello %s world", c.Name)
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
func init() { ice.Index.Register(Index, nil) }
|
17
core/mdb/mdb.go
Normal file
17
core/mdb/mdb.go
Normal file
@ -0,0 +1,17 @@
|
||||
package mdb
|
||||
|
||||
import (
|
||||
"github.com/shylinux/icebergs"
|
||||
)
|
||||
|
||||
var Index = &ice.Context{Name: "mdb", Help: "数据模块",
|
||||
Caches: map[string]*ice.Cache{},
|
||||
Configs: map[string]*ice.Config{},
|
||||
Commands: map[string]*ice.Command{
|
||||
"hi": {Name: "hi", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
m.Echo("hello %s world", c.Name)
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
func init() { ice.Index.Register(Index, nil) }
|
17
core/nfs/nfs.go
Normal file
17
core/nfs/nfs.go
Normal file
@ -0,0 +1,17 @@
|
||||
package nfs
|
||||
|
||||
import (
|
||||
"github.com/shylinux/icebergs"
|
||||
)
|
||||
|
||||
var Index = &ice.Context{Name: "nfs", Help: "文件模块",
|
||||
Caches: map[string]*ice.Cache{},
|
||||
Configs: map[string]*ice.Config{},
|
||||
Commands: map[string]*ice.Command{
|
||||
"hi": {Name: "hi", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
m.Echo("hello %s world", c.Name)
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
func init() { ice.Index.Register(Index, nil) }
|
17
core/ssh/ssh.go
Normal file
17
core/ssh/ssh.go
Normal file
@ -0,0 +1,17 @@
|
||||
package ssh
|
||||
|
||||
import (
|
||||
"github.com/shylinux/icebergs"
|
||||
)
|
||||
|
||||
var Index = &ice.Context{Name: "ssh", Help: "远程模块",
|
||||
Caches: map[string]*ice.Cache{},
|
||||
Configs: map[string]*ice.Config{},
|
||||
Commands: map[string]*ice.Command{
|
||||
"hi": {Name: "hi", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
m.Echo("hello %s world", c.Name)
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
func init() { ice.Index.Register(Index, nil) }
|
19
core/tcp/tcp.go
Normal file
19
core/tcp/tcp.go
Normal file
@ -0,0 +1,19 @@
|
||||
package tcp
|
||||
|
||||
import (
|
||||
"github.com/shylinux/icebergs"
|
||||
)
|
||||
|
||||
var Index = &ice.Context{Name: "tcp", Help: "网络模块",
|
||||
Caches: map[string]*ice.Cache{},
|
||||
Configs: map[string]*ice.Config{},
|
||||
Commands: map[string]*ice.Command{
|
||||
"hi": {Name: "hi", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
m.Echo("hello %s world", c.Name)
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
ice.Index.Register(Index, nil)
|
||||
}
|
300
core/web/web.go
Normal file
300
core/web/web.go
Normal file
@ -0,0 +1,300 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/shylinux/icebergs"
|
||||
"github.com/shylinux/toolkits"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
MSG_MAPS = 1
|
||||
)
|
||||
|
||||
type WEB struct {
|
||||
*http.Client
|
||||
*http.Server
|
||||
*http.ServeMux
|
||||
m *ice.Message
|
||||
send map[string]*ice.Message
|
||||
}
|
||||
|
||||
func (web *WEB) HandleWSS(m *ice.Message, safe bool, c *websocket.Conn) {
|
||||
for {
|
||||
if t, b, e := c.ReadMessage(); e != nil {
|
||||
m.Log("warn", "space recv %d msg %v", t, e)
|
||||
break
|
||||
} else {
|
||||
switch t {
|
||||
case MSG_MAPS:
|
||||
socket, msg := c, m.Spawn(b)
|
||||
source := kit.Simple(msg.Optionv("_source"))
|
||||
target := kit.Simple(msg.Optionv("_target"))
|
||||
msg.Log("space", "recv %v %v->%v %v", t, source, target, msg.Formats("meta"))
|
||||
|
||||
if len(target) > 0 {
|
||||
if s, ok := msg.Confv("web.space", "hash."+target[0]+".socket").(*websocket.Conn); ok {
|
||||
msg.Log("space", "route")
|
||||
// 转发报文
|
||||
socket, source, target = s, append(source, target[0]), target[1:]
|
||||
} else if call, ok := web.send[msg.Option("_target")]; len(target) == 1 && ok {
|
||||
msg.Log("space", "done")
|
||||
// 接收响应
|
||||
delete(web.send, msg.Option("_target"))
|
||||
call.Back(msg)
|
||||
break
|
||||
} else if msg.Option("_handle") == "true" {
|
||||
msg.Log("space", "miss")
|
||||
// 丢弃报文
|
||||
break
|
||||
} else {
|
||||
// 失败报文
|
||||
msg.Log("space", "error")
|
||||
msg.Echo("error")
|
||||
source, target = []string{source[len(source)-1]}, kit.Revert(source)[1:]
|
||||
}
|
||||
} else {
|
||||
msg.Log("space", "run")
|
||||
// 本地执行
|
||||
msg = msg.Cmd()
|
||||
msg.Optionv("_handle", "true")
|
||||
kit.Revert(source)
|
||||
source, target = []string{source[0]}, source[1:]
|
||||
}
|
||||
|
||||
// 发送报文
|
||||
msg.Optionv("_source", source)
|
||||
msg.Optionv("_target", target)
|
||||
msg.Log("space", "send %v %v->%v %v", t, source, target, msg.Formats("meta"))
|
||||
socket.WriteMessage(t, []byte(msg.Format("meta")))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
func (web *WEB) HandleCmd(m *ice.Message, key string, cmd *ice.Command) {
|
||||
web.HandleFunc(key, func(w http.ResponseWriter, r *http.Request) {
|
||||
m.TryCatch(m.Spawns(), true, func(msg *ice.Message) {
|
||||
msg.Optionv("request", r)
|
||||
msg.Optionv("response", w)
|
||||
msg.Option("agent", r.Header.Get("User-Agent"))
|
||||
msg.Option("referer", r.Header.Get("Referer"))
|
||||
msg.Option("accept", r.Header.Get("Accept"))
|
||||
msg.Option("method", r.Method)
|
||||
msg.Option("path", r.URL.Path)
|
||||
msg.Option("sessid", "")
|
||||
|
||||
// 请求环境
|
||||
for _, v := range r.Cookies() {
|
||||
if v.Value != "" {
|
||||
msg.Option(v.Name, v.Value)
|
||||
}
|
||||
}
|
||||
|
||||
// 请求参数
|
||||
r.ParseMultipartForm(4096)
|
||||
if r.ParseForm(); len(r.PostForm) > 0 {
|
||||
for k, v := range r.PostForm {
|
||||
msg.Log("info", "%s: %v", k, v)
|
||||
}
|
||||
msg.Log("info", "")
|
||||
}
|
||||
for k, v := range r.Form {
|
||||
for _, v := range v {
|
||||
msg.Add("option", k, v)
|
||||
}
|
||||
}
|
||||
|
||||
// 请求数据
|
||||
switch r.Header.Get("Content-Type") {
|
||||
case "application/json":
|
||||
var data interface{}
|
||||
if e := json.NewDecoder(r.Body).Decode(&data); e != nil {
|
||||
msg.Log("warn", "%v", e)
|
||||
}
|
||||
msg.Optionv("content_data", data)
|
||||
msg.Log("info", "%v", kit.Formats(data))
|
||||
|
||||
switch d := data.(type) {
|
||||
case map[string]interface{}:
|
||||
for k, v := range d {
|
||||
for _, v := range kit.Simple(v) {
|
||||
msg.Add("option", k, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
msg.Log("cmd", "%s %s", msg.Target().Name, key)
|
||||
cmd.Hand(msg, msg.Target(), msg.Option("path"))
|
||||
msg.Set("option")
|
||||
if msg.Optionv("append") == nil {
|
||||
msg.Result()
|
||||
}
|
||||
w.Write([]byte(msg.Formats("meta")))
|
||||
msg.Log("cost", msg.Format("cost"))
|
||||
})
|
||||
})
|
||||
}
|
||||
func (web *WEB) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
m := web.m
|
||||
|
||||
index := r.Header.Get("index.module") == ""
|
||||
if index {
|
||||
if ip := r.Header.Get("X-Forwarded-For"); ip != "" {
|
||||
r.Header.Set("remote_ip", ip)
|
||||
} else if ip := r.Header.Get("X-Real-Ip"); ip != "" {
|
||||
r.Header.Set("remote_ip", ip)
|
||||
} else if strings.HasPrefix(r.RemoteAddr, "[") {
|
||||
r.Header.Set("remote_ip", strings.Split(r.RemoteAddr, "]")[0][1:])
|
||||
} else {
|
||||
r.Header.Set("remote_ip", strings.Split(r.RemoteAddr, ":")[0])
|
||||
}
|
||||
m.Log("info", "").Log("info", "%v %s %s", r.Header.Get("remote_ip"), r.Method, r.URL)
|
||||
r.Header.Set("index.module", "some")
|
||||
r.Header.Set("index.url", r.URL.String())
|
||||
r.Header.Set("index.path", r.URL.Path)
|
||||
}
|
||||
|
||||
web.ServeMux.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
func (web *WEB) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server {
|
||||
return &WEB{}
|
||||
}
|
||||
func (web *WEB) Begin(m *ice.Message, arg ...string) ice.Server {
|
||||
web.send = map[string]*ice.Message{}
|
||||
return web
|
||||
}
|
||||
func (web *WEB) Start(m *ice.Message, arg ...string) bool {
|
||||
m.Travel(func(p *ice.Context, s *ice.Context) {
|
||||
if w, ok := s.Server().(*WEB); ok {
|
||||
if w.ServeMux != nil {
|
||||
return
|
||||
}
|
||||
|
||||
msg := m.Spawns(s)
|
||||
w.ServeMux = http.NewServeMux()
|
||||
|
||||
route := "/" + s.Name + "/"
|
||||
if n, ok := p.Server().(*WEB); ok && n.ServeMux != nil {
|
||||
msg.Log("route", "%s <- %s", p.Name, route)
|
||||
n.Handle(route, http.StripPrefix(path.Dir(route), w))
|
||||
}
|
||||
|
||||
for k, x := range s.Commands {
|
||||
if k[0] == '/' {
|
||||
msg.Log("route", "%s <- %s", s.Name, k)
|
||||
w.HandleCmd(msg, k, x)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
port := kit.Select(m.Conf("spide", "self.port"), arg, 0)
|
||||
web.m = m
|
||||
web.Server = &http.Server{Addr: port, Handler: web}
|
||||
m.Log("serve", "listen %s", port)
|
||||
m.Log("serve", "listen %s", web.Server.ListenAndServe())
|
||||
return true
|
||||
}
|
||||
func (web *WEB) Close(m *ice.Message, arg ...string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
var Index = &ice.Context{Name: "web", Help: "网页模块",
|
||||
Caches: map[string]*ice.Cache{},
|
||||
Configs: map[string]*ice.Config{
|
||||
"spide": {Name: "客户端", Value: map[string]interface{}{
|
||||
"self": map[string]interface{}{"port": ":9020"},
|
||||
}},
|
||||
"serve": {Name: "服务端", Value: map[string]interface{}{}},
|
||||
"space": {Name: "空间端", Value: map[string]interface{}{
|
||||
"meta": map[string]interface{}{"buffer": 4096},
|
||||
"hash": map[string]interface{}{},
|
||||
"list": map[string]interface{}{},
|
||||
}},
|
||||
},
|
||||
Commands: map[string]*ice.Command{
|
||||
"_init": {Name: "_init", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
m.Echo("hello %s world", c.Name)
|
||||
}},
|
||||
"serve": {Name: "hi", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
m.Conf("cli.runtime", "node.type", "server")
|
||||
m.Run(arg...)
|
||||
}},
|
||||
"/space": &ice.Command{Name: "/space", Help: "", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
r := m.Optionv("request").(*http.Request)
|
||||
w := m.Optionv("response").(http.ResponseWriter)
|
||||
if s, e := websocket.Upgrade(w, r, nil, m.Confi("web.space", "meta.buffer"), m.Confi("web.space", "meta.buffer")); m.Assert(e) {
|
||||
h := m.Option("name")
|
||||
|
||||
meta := map[string]interface{}{
|
||||
"create_time": m.Time(),
|
||||
"socket": s,
|
||||
"type": m.Option("node"),
|
||||
"name": m.Option("name"),
|
||||
}
|
||||
m.Confv("space", []string{"hash", h}, meta)
|
||||
m.Log("space", "conn %v %v", h, kit.Formats(m.Confv("space")))
|
||||
|
||||
web := m.Target().Server().(*WEB)
|
||||
m.Gos(m, func(m *ice.Message) {
|
||||
web.HandleWSS(m, false, s)
|
||||
})
|
||||
}
|
||||
}},
|
||||
"space": &ice.Command{Name: "space", Help: "", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
web := m.Target().Server().(*WEB)
|
||||
switch arg[0] {
|
||||
case "connect":
|
||||
node, name := m.Conf("cli.runtime", "node.type"), m.Conf("cli.runtime", "boot.hostname")
|
||||
if node == "worker" {
|
||||
name = m.Conf("cli.runtime", "boot.pathname")
|
||||
}
|
||||
host := kit.Select(m.Conf("web.spide", "self.port"), arg, 1)
|
||||
p := "ws://" + host + kit.Select("/space", arg, 2) + "?node=" + node + "&name=" + name
|
||||
|
||||
if s, e := net.Dial("tcp", host); m.Assert(e) {
|
||||
if u, e := url.Parse(p); m.Assert(e) {
|
||||
if s, _, e := websocket.NewClient(s, u, nil, m.Confi("web.space", "meta.buffer"), m.Confi("web.space", "meta.buffer")); m.Assert(e) {
|
||||
|
||||
id := m.Option("_source", []string{kit.Format(c.ID()), "some"})
|
||||
web.send[id] = m
|
||||
s.WriteMessage(MSG_MAPS, []byte(m.Format("meta")))
|
||||
web.HandleWSS(m, true, s)
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
if arg[0] == "" {
|
||||
m.Cmdy(arg[1:])
|
||||
break
|
||||
}
|
||||
target := strings.Split(arg[0], ".")
|
||||
if socket, ok := m.Confv("space", "hash."+target[0]+".socket").(*websocket.Conn); !ok {
|
||||
m.Echo("error").Echo("not found")
|
||||
} else {
|
||||
id := kit.Format(c.ID())
|
||||
m.Optionv("_source", []string{id, target[0]})
|
||||
m.Optionv("_target", target[1:])
|
||||
|
||||
web := m.Target().Server().(*WEB)
|
||||
web.send[id] = m
|
||||
m.Add("detail", arg[1:]...)
|
||||
socket.WriteMessage(MSG_MAPS, []byte(m.Format("meta")))
|
||||
m.Call(true, func(msg *ice.Message) *ice.Message {
|
||||
m.Copy(msg)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
}
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
func init() { ice.Index.Register(Index, &WEB{}) }
|
17
core/yac/yac.go
Normal file
17
core/yac/yac.go
Normal file
@ -0,0 +1,17 @@
|
||||
package yac
|
||||
|
||||
import (
|
||||
"github.com/shylinux/icebergs"
|
||||
)
|
||||
|
||||
var Index = &ice.Context{Name: "yac", Help: "语法模块",
|
||||
Caches: map[string]*ice.Cache{},
|
||||
Configs: map[string]*ice.Config{},
|
||||
Commands: map[string]*ice.Command{
|
||||
"hi": {Name: "hi", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
m.Echo("hello %s world", c.Name)
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
func init() { ice.Index.Register(Index, nil) }
|
2
demo/Makefile
Normal file
2
demo/Makefile
Normal file
@ -0,0 +1,2 @@
|
||||
all:
|
||||
go build main.go
|
13
demo/go.mod
Normal file
13
demo/go.mod
Normal file
@ -0,0 +1,13 @@
|
||||
module github.com/shylinux/icebergs/demo
|
||||
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/shylinux/icebergs v0.0.0-20191212145348-fe6226481eaa
|
||||
github.com/shylinux/toolkits v0.0.0-20191212145555-d32eaba90a9e
|
||||
)
|
||||
|
||||
replace (
|
||||
github.com/shylinux/icebergs => ../
|
||||
github.com/shylinux/toolkits => ../../toolkits
|
||||
)
|
10
demo/go.sum
Normal file
10
demo/go.sum
Normal file
@ -0,0 +1,10 @@
|
||||
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/shylinux/icebergs v0.0.0-20191209060320-9f0b85bae35a h1:0RgyhBEPMnRwECFoDPYsz/FgB9yVA9/nJ+tJacwSAig=
|
||||
github.com/shylinux/icebergs v0.0.0-20191209060320-9f0b85bae35a/go.mod h1:FowoSa6syu4hP1QWT9UNoQICuIwfP2PGQ/ao1fSeoOc=
|
||||
github.com/shylinux/icebergs v0.0.0-20191212145348-fe6226481eaa h1:DcLg8BUz5a0ON2UICK7b61LPFJ2+HVC7E8vV5ItYABo=
|
||||
github.com/shylinux/icebergs v0.0.0-20191212145348-fe6226481eaa/go.mod h1:FowoSa6syu4hP1QWT9UNoQICuIwfP2PGQ/ao1fSeoOc=
|
||||
github.com/shylinux/toolkits v0.0.0-20191205193931-8b65f7e78477 h1:xwu6cGDBy/ZCrVklmCqSgx9O7Hr1v+hkzsIh1yc0hxg=
|
||||
github.com/shylinux/toolkits v0.0.0-20191205193931-8b65f7e78477/go.mod h1:e1dV0lMyoKz4Luib6XyMNpfpn5Sn7POnq7XTT4wfN7k=
|
||||
github.com/shylinux/toolkits v0.0.0-20191212145555-d32eaba90a9e h1:eFZMsw0LuDeeVgwYwNJISebbMUZCVHEdQRaYBNWvC9s=
|
||||
github.com/shylinux/toolkits v0.0.0-20191212145555-d32eaba90a9e/go.mod h1:e1dV0lMyoKz4Luib6XyMNpfpn5Sn7POnq7XTT4wfN7k=
|
10
demo/main.go
Normal file
10
demo/main.go
Normal file
@ -0,0 +1,10 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/shylinux/icebergs"
|
||||
_ "github.com/shylinux/icebergs/misc/chat"
|
||||
)
|
||||
|
||||
func main() {
|
||||
println(ice.Run())
|
||||
}
|
8
go.mod
Normal file
8
go.mod
Normal file
@ -0,0 +1,8 @@
|
||||
module github.com/shylinux/icebergs
|
||||
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/gorilla/websocket v1.4.1
|
||||
github.com/shylinux/toolkits v0.0.0-20191205193931-8b65f7e78477
|
||||
)
|
4
go.sum
Normal file
4
go.sum
Normal file
@ -0,0 +1,4 @@
|
||||
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/shylinux/toolkits v0.0.0-20191205193931-8b65f7e78477 h1:xwu6cGDBy/ZCrVklmCqSgx9O7Hr1v+hkzsIh1yc0hxg=
|
||||
github.com/shylinux/toolkits v0.0.0-20191205193931-8b65f7e78477/go.mod h1:e1dV0lMyoKz4Luib6XyMNpfpn5Sn7POnq7XTT4wfN7k=
|
65
misc/chat/chat.go
Normal file
65
misc/chat/chat.go
Normal file
@ -0,0 +1,65 @@
|
||||
package chat
|
||||
|
||||
import (
|
||||
"github.com/shylinux/icebergs"
|
||||
"github.com/shylinux/icebergs/core/web"
|
||||
_ "github.com/shylinux/icebergs/misc"
|
||||
"github.com/shylinux/toolkits"
|
||||
)
|
||||
|
||||
var Index = &ice.Context{Name: "chat", Help: "聊天模块",
|
||||
Caches: map[string]*ice.Cache{},
|
||||
Configs: map[string]*ice.Config{
|
||||
"group": {Name: "group", Value: map[string]interface{}{
|
||||
"meta": map[string]interface{}{},
|
||||
"list": map[string]interface{}{},
|
||||
"hash": map[string]interface{}{},
|
||||
}},
|
||||
},
|
||||
Commands: map[string]*ice.Command{
|
||||
"_init": {Name: "_init", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
}},
|
||||
"/ocean": {Name: "/ocean", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
}},
|
||||
"/river": {Name: "/river", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
if len(arg) == 0 {
|
||||
arg = kit.Simple(m.Optionv("cmds"))
|
||||
}
|
||||
|
||||
if len(arg) == 0 {
|
||||
m.Confm("group", "hash", func(key string, value map[string]interface{}) {
|
||||
m.Push("key", key)
|
||||
m.Push("create_time", value["create_time"])
|
||||
m.Push("name", value["name"])
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
switch arg[0] {
|
||||
case "create":
|
||||
// h := kit.Hashs("uniq")
|
||||
h := kit.ShortKey(m.Confm("group", "hash"), 6)
|
||||
m.Conf("group", "hash."+h, map[string]interface{}{
|
||||
"create_time": m.Time(),
|
||||
"create_name": arg[1],
|
||||
})
|
||||
m.Log("info", "river create %v %v", h, kit.Formats(m.Confv("group", "hash."+h)))
|
||||
m.Echo(h)
|
||||
}
|
||||
}},
|
||||
"/action": {Name: "/action", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
if cmds, ok := m.Optionv("cmds").([]string); ok {
|
||||
m.Cmdy("web.space", cmds)
|
||||
return
|
||||
}
|
||||
}},
|
||||
"/storm": {Name: "/storm", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
}},
|
||||
"/steam": {Name: "/steam", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
}},
|
||||
"_exit": {Name: "_init", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
func init() { web.Index.Register(Index, &web.WEB{}) }
|
16
misc/shy.go
Normal file
16
misc/shy.go
Normal file
@ -0,0 +1,16 @@
|
||||
package shy
|
||||
|
||||
import (
|
||||
_ "github.com/shylinux/icebergs/core/aaa"
|
||||
_ "github.com/shylinux/icebergs/core/cli"
|
||||
_ "github.com/shylinux/icebergs/core/ctx"
|
||||
_ "github.com/shylinux/icebergs/core/gdb"
|
||||
_ "github.com/shylinux/icebergs/core/lex"
|
||||
_ "github.com/shylinux/icebergs/core/log"
|
||||
_ "github.com/shylinux/icebergs/core/mdb"
|
||||
_ "github.com/shylinux/icebergs/core/nfs"
|
||||
_ "github.com/shylinux/icebergs/core/ssh"
|
||||
_ "github.com/shylinux/icebergs/core/tcp"
|
||||
_ "github.com/shylinux/icebergs/core/web"
|
||||
_ "github.com/shylinux/icebergs/core/yac"
|
||||
)
|
426
type.go
426
type.go
@ -3,8 +3,12 @@ package ice
|
||||
import (
|
||||
"github.com/shylinux/toolkits"
|
||||
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@ -36,9 +40,12 @@ type Context struct {
|
||||
contexts map[string]*Context
|
||||
context *Context
|
||||
root *Context
|
||||
begin *Message
|
||||
start *Message
|
||||
|
||||
exit chan bool
|
||||
server Server
|
||||
id int
|
||||
}
|
||||
type Server interface {
|
||||
Spawn(m *Message, c *Context, arg ...string) Server
|
||||
@ -47,6 +54,46 @@ type Server interface {
|
||||
Close(m *Message, arg ...string) bool
|
||||
}
|
||||
|
||||
func (c *Context) ID() int {
|
||||
c.id++
|
||||
return c.id
|
||||
}
|
||||
func (c *Context) Server() Server {
|
||||
return c.server
|
||||
}
|
||||
func (c *Context) Register(s *Context, x Server) *Context {
|
||||
Pulse.Log("register", "%s <- %s", c.Name, s.Name)
|
||||
if c.contexts == nil {
|
||||
c.contexts = map[string]*Context{}
|
||||
}
|
||||
c.contexts[s.Name] = s
|
||||
s.root = c.root
|
||||
s.context = c
|
||||
s.server = x
|
||||
return s
|
||||
}
|
||||
|
||||
func (c *Context) Begin(m *Message, arg ...string) *Context {
|
||||
c.begin = m
|
||||
m.Log("begin", "%s", c.Name)
|
||||
if c.server != nil {
|
||||
c.server.Begin(m, arg...)
|
||||
}
|
||||
return c
|
||||
}
|
||||
func (c *Context) Start(m *Message, arg ...string) bool {
|
||||
c.start = m
|
||||
m.Log("start", "%s", c.Name)
|
||||
return c.server.Start(m, arg...)
|
||||
}
|
||||
func (c *Context) Close(m *Message, arg ...string) bool {
|
||||
m.Log("close", "%s", c.Name)
|
||||
if c.server != nil {
|
||||
return c.server.Close(m, arg...)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
type Message struct {
|
||||
time time.Time
|
||||
code int
|
||||
@ -61,8 +108,54 @@ type Message struct {
|
||||
source *Context
|
||||
target *Context
|
||||
Hand bool
|
||||
cb func(*Message) *Message
|
||||
}
|
||||
|
||||
func (m *Message) Time() string {
|
||||
return m.time.Format("2006-01-02 15:04:05")
|
||||
}
|
||||
func (m *Message) Target() *Context {
|
||||
return m.target
|
||||
}
|
||||
func (m *Message) Format(key interface{}) string {
|
||||
switch key := key.(type) {
|
||||
case string:
|
||||
switch key {
|
||||
case "cost":
|
||||
return time.Now().Sub(m.time).String()
|
||||
case "meta":
|
||||
return kit.Format(m.meta)
|
||||
case "stack":
|
||||
pc := make([]uintptr, 100)
|
||||
pc = pc[:runtime.Callers(5, pc)]
|
||||
frames := runtime.CallersFrames(pc)
|
||||
|
||||
meta := []string{}
|
||||
for {
|
||||
frame, more := frames.Next()
|
||||
file := strings.Split(frame.File, "/")
|
||||
name := strings.Split(frame.Function, "/")
|
||||
meta = append(meta, fmt.Sprintf("\n%s:%d\t%s", file[len(file)-1], frame.Line, name[len(name)-1]))
|
||||
if !more {
|
||||
break
|
||||
}
|
||||
}
|
||||
return strings.Join(meta, "")
|
||||
}
|
||||
case []byte:
|
||||
json.Unmarshal(key, &m.meta)
|
||||
}
|
||||
return m.time.Format("2006-01-02 15:04:05")
|
||||
}
|
||||
func (m *Message) Formats(key string) string {
|
||||
switch key {
|
||||
case "meta":
|
||||
return kit.Formats(m.meta)
|
||||
default:
|
||||
return m.Format(key)
|
||||
}
|
||||
return m.time.Format("2006-01-02 15:04:05")
|
||||
}
|
||||
func (m *Message) Spawn(arg ...interface{}) *Message {
|
||||
msg := &Message{
|
||||
time: time.Now(),
|
||||
@ -82,14 +175,277 @@ func (m *Message) Spawn(arg ...interface{}) *Message {
|
||||
switch val := arg[0].(type) {
|
||||
case *Context:
|
||||
msg.target = val
|
||||
case []byte:
|
||||
json.Unmarshal(val, &msg.meta)
|
||||
}
|
||||
}
|
||||
return msg
|
||||
}
|
||||
func (m *Message) Log(level string, str string, arg ...interface{}) {
|
||||
fmt.Fprintf(os.Stderr, "%s %s %s\n", time.Now().Format("2006-01-02 15:04:05"), level, fmt.Sprintf(str, arg...))
|
||||
func (m *Message) Spawns(arg ...interface{}) *Message {
|
||||
msg := m.Spawn(arg...)
|
||||
msg.code = Index.ID()
|
||||
m.messages = append(m.messages, msg)
|
||||
return msg
|
||||
}
|
||||
func (m *Message) Confv(arg ...interface{}) interface{} {
|
||||
|
||||
func (m *Message) Add(key string, arg ...string) *Message {
|
||||
switch key {
|
||||
case "detail", "result":
|
||||
m.meta[key] = append(m.meta[key], arg...)
|
||||
|
||||
case "option", "append":
|
||||
if len(arg) > 0 {
|
||||
if kit.IndexOf(m.meta[key], arg[0]) == -1 {
|
||||
m.meta[key] = append(m.meta[key], arg[0])
|
||||
}
|
||||
m.meta[arg[0]] = append(m.meta[arg[0]], arg[1:]...)
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
||||
func (m *Message) Set(key string, arg ...string) *Message {
|
||||
switch key {
|
||||
case "detail", "result":
|
||||
delete(m.meta, key)
|
||||
case "option", "append":
|
||||
if len(arg) > 0 {
|
||||
delete(m.meta, arg[0])
|
||||
} else {
|
||||
for _, k := range m.meta[key] {
|
||||
delete(m.meta, k)
|
||||
}
|
||||
delete(m.meta, key)
|
||||
return m
|
||||
}
|
||||
}
|
||||
return m.Add(key, arg...)
|
||||
}
|
||||
func (m *Message) Copy(msg *Message) *Message {
|
||||
for _, k := range msg.meta["append"] {
|
||||
if kit.IndexOf(m.meta["append"], k) == -1 {
|
||||
m.meta["append"] = append(m.meta["append"], k)
|
||||
}
|
||||
for _, v := range msg.meta[k] {
|
||||
m.meta[k] = append(m.meta[k], v)
|
||||
}
|
||||
}
|
||||
for _, v := range msg.meta["result"] {
|
||||
m.meta["result"] = append(m.meta["result"], v)
|
||||
}
|
||||
return m
|
||||
}
|
||||
func (m *Message) Push(key string, value interface{}) *Message {
|
||||
return m.Add("append", key, kit.Format(value))
|
||||
}
|
||||
func (m *Message) Echo(str string, arg ...interface{}) *Message {
|
||||
m.meta["result"] = append(m.meta["result"], fmt.Sprintf(str, arg...))
|
||||
return m
|
||||
}
|
||||
func (m *Message) Option(key string, arg ...interface{}) string {
|
||||
return kit.Select("", kit.Simple(m.Optionv(key, arg...)), 0)
|
||||
}
|
||||
func (m *Message) Optionv(key string, arg ...interface{}) interface{} {
|
||||
if len(arg) > 0 {
|
||||
if kit.IndexOf(m.meta["option"], key) == -1 {
|
||||
m.meta["option"] = append(m.meta["option"], key)
|
||||
}
|
||||
|
||||
switch arg := arg[0].(type) {
|
||||
case string:
|
||||
m.meta[key] = []string{arg}
|
||||
case []string:
|
||||
m.meta[key] = arg
|
||||
default:
|
||||
m.data[key] = arg
|
||||
}
|
||||
}
|
||||
|
||||
for msg := m; msg != nil; msg = msg.message {
|
||||
if list, ok := m.meta[key]; ok {
|
||||
return list
|
||||
}
|
||||
if list, ok := m.data[key]; ok {
|
||||
return list
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *Message) Resultv(arg ...interface{}) []string {
|
||||
return m.meta["result"]
|
||||
}
|
||||
func (m *Message) Result(arg ...interface{}) string {
|
||||
return strings.Join(m.Resultv(), "")
|
||||
}
|
||||
|
||||
func (m *Message) Log(level string, str string, arg ...interface{}) *Message {
|
||||
fmt.Fprintf(os.Stderr, "%s %d %s->%s %s %s\n", time.Now().Format("2006-01-02 15:04:05"), m.code, m.source.Name, m.target.Name, level, fmt.Sprintf(str, arg...))
|
||||
return m
|
||||
}
|
||||
func (m *Message) Assert(arg interface{}) bool {
|
||||
switch arg := arg.(type) {
|
||||
case nil:
|
||||
return true
|
||||
case bool:
|
||||
if arg == true {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
panic(errors.New(fmt.Sprintf("error %v", arg)))
|
||||
}
|
||||
func (m *Message) TryCatch(msg *Message, safe bool, hand ...func(msg *Message)) *Message {
|
||||
defer func() {
|
||||
switch e := recover(); e {
|
||||
case io.EOF:
|
||||
case nil:
|
||||
default:
|
||||
m.Log("bench", "chain: %s", msg.Format("chain"))
|
||||
m.Log("bench", "catch: %s", e)
|
||||
m.Log("bench", "stack: %s", msg.Format("stack"))
|
||||
|
||||
if m.Log("error", "catch: %s", e); len(hand) > 1 {
|
||||
m.TryCatch(msg, safe, hand[1:]...)
|
||||
} else if !safe {
|
||||
m.Assert(e)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
if len(hand) > 0 {
|
||||
hand[0](msg)
|
||||
}
|
||||
return m
|
||||
}
|
||||
func (m *Message) Travel(cb func(p *Context, s *Context)) *Message {
|
||||
list := []*Context{m.target}
|
||||
for i := 0; i < len(list); i++ {
|
||||
cb(list[i].context, list[i])
|
||||
for _, v := range list[i].contexts {
|
||||
list = append(list, v)
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
||||
func (m *Message) Search(key interface{}, cb func(p *Context, s *Context, key string)) *Message {
|
||||
switch key := key.(type) {
|
||||
case string:
|
||||
if strings.Contains(key, ":") {
|
||||
|
||||
} else if strings.Contains(key, ".") {
|
||||
list := strings.Split(key, ".")
|
||||
|
||||
p := m.target.root
|
||||
for _, v := range list[:len(list)-1] {
|
||||
if s, ok := p.contexts[v]; ok {
|
||||
p = s
|
||||
} else {
|
||||
p = nil
|
||||
break
|
||||
}
|
||||
}
|
||||
if p != nil {
|
||||
cb(p.context, p, list[len(list)-1])
|
||||
}
|
||||
} else {
|
||||
cb(m.target.context, m.target, key)
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
||||
func (m *Message) Gos(msg *Message, cb func(*Message)) *Message {
|
||||
go func() { msg.TryCatch(msg, true, func(msg *Message) { cb(msg) }) }()
|
||||
return m
|
||||
}
|
||||
func (m *Message) Run(arg ...string) *Message {
|
||||
m.target.server.Start(m, arg...)
|
||||
return m
|
||||
}
|
||||
func (m *Message) Call(sync bool, cb func(*Message) *Message) *Message {
|
||||
if sync {
|
||||
wait := make(chan bool)
|
||||
m.cb = func(sub *Message) *Message {
|
||||
wait <- true
|
||||
return cb(sub)
|
||||
}
|
||||
<-wait
|
||||
}
|
||||
return m
|
||||
}
|
||||
func (m *Message) Back(sub *Message) *Message {
|
||||
if m.cb != nil {
|
||||
m.cb(sub)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *Message) Cmdy(arg ...interface{}) *Message {
|
||||
msg := m.Cmd(arg...)
|
||||
m.Copy(msg)
|
||||
return m
|
||||
}
|
||||
func (m *Message) Cmd(arg ...interface{}) *Message {
|
||||
list := kit.Simple(arg...)
|
||||
if len(list) == 0 {
|
||||
list = m.meta["detail"]
|
||||
}
|
||||
if len(list) == 0 {
|
||||
return m
|
||||
}
|
||||
|
||||
msg := m
|
||||
m.Search(list[0], func(p *Context, s *Context, key string) {
|
||||
for c := s; c != nil; c = c.context {
|
||||
if cmd, ok := c.Commands[key]; ok {
|
||||
msg = m.Spawns(s).Log("cmd", "%s.%s %v", c.Name, key, list[1:])
|
||||
msg.TryCatch(msg, true, func(msg *Message) {
|
||||
cmd.Hand(msg, c, key, list[1:]...)
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
return msg
|
||||
}
|
||||
func (m *Message) Confv(arg ...interface{}) (val interface{}) {
|
||||
m.Search(arg[0], func(p *Context, s *Context, key string) {
|
||||
for c := s; c != nil; c = c.context {
|
||||
if conf, ok := c.Configs[key]; ok {
|
||||
if len(arg) > 0 {
|
||||
val = kit.Value(conf.Value, arg[1:]...)
|
||||
} else {
|
||||
val = conf.Value
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
func (m *Message) Confm(key string, chain interface{}, cbs ...interface{}) map[string]interface{} {
|
||||
val := m.Confv(key, chain)
|
||||
if len(cbs) > 0 {
|
||||
switch val := val.(type) {
|
||||
case map[string]interface{}:
|
||||
switch cb := cbs[0].(type) {
|
||||
case func(string, map[string]interface{}):
|
||||
for k, v := range val {
|
||||
cb(k, v.(map[string]interface{}))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
value, _ := val.(map[string]interface{})
|
||||
return value
|
||||
}
|
||||
func (m *Message) Confs(arg ...interface{}) bool {
|
||||
return kit.Format(m.Confv(arg...)) != ""
|
||||
}
|
||||
func (m *Message) Confi(arg ...interface{}) int {
|
||||
return kit.Int(m.Confv(arg...))
|
||||
}
|
||||
func (m *Message) Conf(arg ...interface{}) string {
|
||||
return kit.Format(m.Confv(arg...))
|
||||
}
|
||||
func (m *Message) Capv(arg ...interface{}) interface{} {
|
||||
key := ""
|
||||
switch val := arg[0].(type) {
|
||||
case string:
|
||||
@ -98,69 +454,13 @@ func (m *Message) Confv(arg ...interface{}) interface{} {
|
||||
|
||||
for _, s := range []*Context{m.target} {
|
||||
for c := s; c != nil; c = c.context {
|
||||
if conf, ok := c.Configs[key]; ok {
|
||||
m.Log("conf", "%s.%s", c.Name, key)
|
||||
return kit.Value(conf.Value, key)
|
||||
if caps, ok := c.Caches[key]; ok {
|
||||
return kit.Value(caps.Value, arg[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *Message) Conf(arg ...interface{}) string {
|
||||
return kit.Format(m.Confv(arg...))
|
||||
}
|
||||
func (m *Message) Cmd(arg ...interface{}) *Message {
|
||||
list := kit.Trans(arg...)
|
||||
if len(list) == 0 {
|
||||
return m
|
||||
}
|
||||
for _, s := range []*Context{m.target} {
|
||||
for c := s; c != nil; c = c.context {
|
||||
if cmd, ok := c.Commands[list[0]]; ok {
|
||||
m.Log("cmd", "%s.%s", c.Name, list[0])
|
||||
cmd.Hand(m, c, list[0], list[1:]...)
|
||||
}
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
||||
func (m *Message) Echo(str string, arg ...interface{}) *Message {
|
||||
m.meta["result"] = append(m.meta["result"], fmt.Sprintf(str, arg...))
|
||||
return m
|
||||
}
|
||||
func (m *Message) Result(arg ...interface{}) string {
|
||||
return strings.Join(m.meta["result"], "")
|
||||
}
|
||||
|
||||
var Pulse = &Message{
|
||||
time: time.Now(), code: 0,
|
||||
meta: map[string][]string{},
|
||||
data: map[string]interface{}{},
|
||||
|
||||
messages: []*Message{}, message: nil, root: nil,
|
||||
source: Index, target: Index, Hand: true,
|
||||
}
|
||||
var Index = &Context{Name: "root", Help: "元始模块",
|
||||
Caches: map[string]*Cache{},
|
||||
Configs: map[string]*Config{},
|
||||
Commands: map[string]*Command{
|
||||
"hi": {Name: "hi", Help: "hello", Hand: func(m *Message, c *Context, cmd string, arg ...string) {
|
||||
m.Echo("hello world")
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
func (c *Context) Register(s *Context, x Server) *Context {
|
||||
if c.contexts == nil {
|
||||
c.contexts = map[string]*Context{}
|
||||
}
|
||||
c.contexts[s.Name] = s
|
||||
s.root = c.root
|
||||
s.context = c
|
||||
s.server = x
|
||||
return s
|
||||
}
|
||||
func init() {
|
||||
Index.root = Index
|
||||
Pulse.root = Pulse
|
||||
func (m *Message) Cap(arg ...interface{}) string {
|
||||
return kit.Format(m.Capv(arg...))
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user