1
0
mirror of https://shylinux.com/x/icebergs synced 2025-04-25 17:18:05 +08:00

add web.HandleWSS

This commit is contained in:
shaoying 2019-12-14 20:18:08 +08:00
parent fe6226481e
commit 47bb65632d
23 changed files with 1130 additions and 63 deletions

2
Makefile Normal file
View File

@ -0,0 +1,2 @@
all:
cd demo && go build main.go

97
core.go Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1,2 @@
all:
go build main.go

13
demo/go.mod Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@ -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...))
}