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 (
|
import (
|
||||||
"github.com/shylinux/toolkits"
|
"github.com/shylinux/toolkits"
|
||||||
|
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -36,9 +40,12 @@ type Context struct {
|
|||||||
contexts map[string]*Context
|
contexts map[string]*Context
|
||||||
context *Context
|
context *Context
|
||||||
root *Context
|
root *Context
|
||||||
|
begin *Message
|
||||||
|
start *Message
|
||||||
|
|
||||||
exit chan bool
|
exit chan bool
|
||||||
server Server
|
server Server
|
||||||
|
id int
|
||||||
}
|
}
|
||||||
type Server interface {
|
type Server interface {
|
||||||
Spawn(m *Message, c *Context, arg ...string) Server
|
Spawn(m *Message, c *Context, arg ...string) Server
|
||||||
@ -47,6 +54,46 @@ type Server interface {
|
|||||||
Close(m *Message, arg ...string) bool
|
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 {
|
type Message struct {
|
||||||
time time.Time
|
time time.Time
|
||||||
code int
|
code int
|
||||||
@ -61,8 +108,54 @@ type Message struct {
|
|||||||
source *Context
|
source *Context
|
||||||
target *Context
|
target *Context
|
||||||
Hand bool
|
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 {
|
func (m *Message) Spawn(arg ...interface{}) *Message {
|
||||||
msg := &Message{
|
msg := &Message{
|
||||||
time: time.Now(),
|
time: time.Now(),
|
||||||
@ -82,14 +175,277 @@ func (m *Message) Spawn(arg ...interface{}) *Message {
|
|||||||
switch val := arg[0].(type) {
|
switch val := arg[0].(type) {
|
||||||
case *Context:
|
case *Context:
|
||||||
msg.target = val
|
msg.target = val
|
||||||
|
case []byte:
|
||||||
|
json.Unmarshal(val, &msg.meta)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return msg
|
return msg
|
||||||
}
|
}
|
||||||
func (m *Message) Log(level string, str string, arg ...interface{}) {
|
func (m *Message) Spawns(arg ...interface{}) *Message {
|
||||||
fmt.Fprintf(os.Stderr, "%s %s %s\n", time.Now().Format("2006-01-02 15:04:05"), level, fmt.Sprintf(str, arg...))
|
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 := ""
|
key := ""
|
||||||
switch val := arg[0].(type) {
|
switch val := arg[0].(type) {
|
||||||
case string:
|
case string:
|
||||||
@ -98,69 +454,13 @@ func (m *Message) Confv(arg ...interface{}) interface{} {
|
|||||||
|
|
||||||
for _, s := range []*Context{m.target} {
|
for _, s := range []*Context{m.target} {
|
||||||
for c := s; c != nil; c = c.context {
|
for c := s; c != nil; c = c.context {
|
||||||
if conf, ok := c.Configs[key]; ok {
|
if caps, ok := c.Caches[key]; ok {
|
||||||
m.Log("conf", "%s.%s", c.Name, key)
|
return kit.Value(caps.Value, arg[0])
|
||||||
return kit.Value(conf.Value, key)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (m *Message) Conf(arg ...interface{}) string {
|
func (m *Message) Cap(arg ...interface{}) string {
|
||||||
return kit.Format(m.Confv(arg...))
|
return kit.Format(m.Capv(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
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user