1
0
mirror of https://shylinux.com/x/ContextOS synced 2025-04-26 09:14:06 +08:00
2018-08-05 00:16:07 +08:00

412 lines
12 KiB
Go

package ssh // {{{
// }}}
import ( // {{{
"contexts"
"fmt"
"strings"
"time"
)
// }}}
type SSH struct {
nfs *ctx.Context
peer map[string]*ctx.Message
*ctx.Context
}
func (ssh *SSH) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { // {{{
c.Caches = map[string]*ctx.Cache{
"hostname": &ctx.Cache{Name: "hostname", Value: "com", Help: "主机数量"},
}
c.Configs = map[string]*ctx.Config{}
s := new(SSH)
s.Context = c
return s
}
// }}}
func (ssh *SSH) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{
ssh.Caches["hostname"] = &ctx.Cache{Name: "hostname", Value: "", Help: "主机数量"}
if ssh.Context == Index {
Pulse = m
}
return ssh
}
// }}}
func (ssh *SSH) Start(m *ctx.Message, arg ...string) bool { // {{{
ssh.nfs = m.Source()
m.Cap("stream", m.Source().Name)
return false
}
// }}}
func (ssh *SSH) Close(m *ctx.Message, arg ...string) bool { // {{{
return false
switch ssh.Context {
case m.Target():
case m.Source():
}
if m.Target() == Index {
go func() {
m.Target().Begin(m)
m.Sess("nfs", "nfs")
for !m.Caps("stream") {
time.Sleep(time.Second * time.Duration(m.Confi("interval")))
go ssh.Message().Spawn(m.Target()).Copy(ssh.Message(), "detail").Cmd()
time.Sleep(time.Second * time.Duration(m.Confi("interval")))
}
}()
return false
}
return true
}
// }}}
func Done(m *ctx.Message, lock chan bool) { // {{{
m.Log("lock", "done before %v", m.Meta["detail"])
if m.Options("stdio") {
lock <- true
}
m.Log("lock", "done after %v", m.Meta["detail"])
}
// }}}
func Wait(m *ctx.Message, lock chan bool) { // {{{
m.Log("lock", "wait before %v", m.Meta["detail"])
if m.Options("stdio") {
<-lock
}
m.Log("lock", "wait after %v", m.Meta["detail"])
}
// }}}
var Pulse *ctx.Message
var Index = &ctx.Context{Name: "ssh", Help: "集群中心",
Caches: map[string]*ctx.Cache{
"nhost": &ctx.Cache{Name: "主机数量", Value: "0", Help: "主机数量"},
"route": &ctx.Cache{Name: "route", Value: "com", Help: "主机数量"},
"count": &ctx.Cache{Name: "count", Value: "3", Help: "主机数量"},
"share": &ctx.Cache{Name: "share", Value: "root", Help: "主机数量"},
"level": &ctx.Cache{Name: "level", Value: "root", Help: "主机数量"},
"domain": &ctx.Cache{Name: "domain", Value: "com", Help: "主机数量"},
},
Configs: map[string]*ctx.Config{
"interval": &ctx.Config{Name: "interval", Value: "3", Help: "主机数量"},
"hostname": &ctx.Config{Name: "hostname", Value: "com", Help: "主机数量"},
"domain.json": &ctx.Config{Name: "domain.json", Value: "var/domain.json", Help: "主机数量"},
"domain.png": &ctx.Config{Name: "domain.png", Value: "var/domain.png", Help: "主机数量"},
"mdb": &ctx.Config{Name: "mdb", Value: "mdb.chat", Help: "主机数量"},
"uid": &ctx.Config{Name: "uid", Value: "", Help: "主机数量"},
"type": &ctx.Config{Name: "type", Value: "terminal", Help: "主机数量"},
"kind": &ctx.Config{Name: "kind", Value: "terminal", Help: "主机数量"},
"name": &ctx.Config{Name: "name", Value: "vps", Help: "主机数量"},
"mark": &ctx.Config{Name: "mark", Value: "com", Help: "主机数量"},
},
Commands: map[string]*ctx.Command{
"listen": &ctx.Command{Name: "listen address protocol", Help: "监听连接", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if _, ok := m.Target().Server.(*SSH); m.Assert(ok) { // {{{
m.Sess("nfs").Call(func(sub *ctx.Message) *ctx.Message {
sub.Start(fmt.Sprintf("host%d", Pulse.Capi("nhost", 1)), "远程主机")
return sub
}, m.Meta["detail"])
m.Spawn(m.Target()).Cmd("save")
}
// }}}
}},
"dial": &ctx.Command{Name: "dial address protocol", Help: "建立连接", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if _, ok := m.Target().Server.(*SSH); m.Assert(ok) { // {{{
m.Sess("nfs").CallBack(true, func(sub *ctx.Message) *ctx.Message {
sub.Target().Start(sub)
sub.Spawn().Cmd("pwd", m.Conf("hostname"))
return sub
}, m.Meta["detail"])
}
// }}}
}},
"send": &ctx.Command{Name: "send [domain str] cmd arg...", Help: "远程执行",
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if ssh, ok := m.Target().Server.(*SSH); m.Assert(ok) { // {{{
domain := ""
if len(arg) > 1 && arg[0] == "domain" {
domain, arg = arg[1], arg[2:]
domain = strings.TrimPrefix(strings.TrimPrefix(domain, m.Cap("domain")), ".")
}
if domain != "" {
domain_miss := true
host := strings.SplitN(domain, ".", 2)
m.Travel(func(m *ctx.Message, i int) bool {
if i > 0 {
if m.Cap("hostname") == host[0] {
ssh, ok := m.Target().Server.(*SSH)
m.Assert(ok)
msg := m.Spawn(ssh.Message().Source()).Copy(m, "option")
if len(host) > 1 {
msg.Options("downflow", true)
msg.Detail("send", "domain", host[1], arg)
} else {
msg.Detail(arg)
}
if ssh.Message().Back(msg); !msg.Appends("domain_miss") {
m.Copy(msg, "result").Copy(msg, "append")
domain_miss = false
return false
}
}
return false
}
return true
}, c)
if domain_miss && !m.Options("downflow") && m.Cap("domain") != m.Conf("domain") {
ssh, ok := c.Server.(*SSH)
m.Assert(ok)
msg := m.Spawn(ssh.Message().Source()).Copy(m, "option")
msg.Detail("send", "domain", domain, arg)
if ssh.Message().Back(msg); !msg.Appends("domain_miss") {
m.Copy(msg, "result").Copy(msg, "append")
domain_miss = false
}
}
m.Appends("domain_miss", domain_miss)
return
}
if m.Options("send_code") || m.Cap("status") != "start" {
msg := m.Spawn().Cmd(arg)
m.Copy(msg, "result").Copy(msg, "append")
} else {
msg := m.Spawn(ssh.Message().Source())
msg.Copy(m, "option").Detail(arg)
ssh.Message().Back(msg)
m.Copy(msg, "result").Copy(msg, "append")
}
return
} // }}}
}},
"pwd": &ctx.Command{Name: "pwd", Help: "远程执行", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if len(arg) == 0 { // {{{
if m.Target() == c {
m.Echo(m.Cap("domain"))
} else {
m.Echo("%s.%s", m.Cap("domain"), m.Cap("hostname"))
}
return
}
if m.Target() == c {
msg := m.Spawn().Cmd("send", "pwd", arg[0])
m.Copy(msg, "result").Copy(msg, "append")
m.Cap("domain", msg.Result(0))
} else if m.Options("send_code") {
hostname := arg[0]
m.Travel(func(m *ctx.Message, line int) bool {
if hostname == m.Cap("hostname") {
hostname += m.Cap("nhost")
return false
}
return true
}, c)
m.Echo("%s.%s", m.Cap("domain"), m.Cap("hostname", hostname))
} // }}}
}},
"hello": &ctx.Command{Name: "hello request", Help: "加密请求", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
aaa := m.Target().Message().Sess("aaa", false) // {{{
for _, k := range m.Meta["seal"] {
for i, v := range m.Meta[k] {
m.Meta[k][i] = m.Spawn(aaa).Cmd("deal", v).Result(0)
}
}
for _, k := range m.Meta["encrypt"] {
for i, v := range m.Meta[k] {
m.Meta[k][i] = m.Spawn(aaa).Cmd("decrypt", v).Result(0)
}
}
if len(arg) == 0 {
if !m.Has("mi") {
cert := aaa.Spawn().Cmd("certificate")
m.Echo(cert.Result(0))
} else {
msg := m.Sess("aaa").Cmd("login", m.Option("mi"), m.Option("mi"))
m.Echo(msg.Result(0))
msg.Sess("aaa").Cmd("newcipher", m.Option("mi"))
}
return
}
msg := m.Spawn().Copy(m, "option").Cmd(arg)
m.Copy(msg, "result").Copy(msg, "append")
// }}}
}},
"shake": &ctx.Command{
Name: "shake [domain host] cmd... [seal option...][encrypt option...]",
Help: "加密通信",
Form: map[string]int{"seal": -1, "encrypt": -1},
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if ssh, ok := m.Target().Server.(*SSH); m.Assert(ok) { // {{{
if len(arg) == 0 {
for k, v := range ssh.peer {
m.Echo("%s: %s\n", k, v.Cap("stream"))
}
return
}
peer := "peer"
args := []string{}
if len(arg) > 1 && arg[0] == "domain" {
args = append(args, "domain", arg[1])
peer, arg = arg[1], arg[2:]
}
if ssh.peer == nil {
ssh.peer = map[string]*ctx.Message{}
}
user, ok := ssh.peer[peer]
if !ok {
user = m.Sess("aaa").Cmd("login", "cert", m.Spawn().Cmd("send", args, "hello"), peer)
ssh.peer[peer] = user
mi := user.Cap("sessid")
remote := m.Spawn().Add("option", mi, m.Spawn(user).Cmd("seal", mi)).Add("option", "seal", mi).Cmd("send", args, "hello")
m.Spawn(user).Cmd("newcipher", mi)
user.Cap("remote", "remote", remote.Result(0), "远程会话")
user.Cap("remote_mi", "remote_mi", mi, "远程密钥")
}
msg := m.Spawn(ssh.Message().Source()).Copy(m, "option")
msg.Option("hello", "world")
msg.Option("world", "hello")
for _, k := range msg.Meta["seal"] {
for i, v := range msg.Meta[k] {
msg.Meta[k][i] = msg.Spawn(user).Cmd("seal", v).Result(0)
}
}
for _, k := range msg.Meta["encrypt"] {
for i, v := range msg.Meta[k] {
msg.Meta[k][i] = msg.Spawn(user).Cmd("encrypt", v).Result(0)
}
}
msg.Detail("send", args, "hello", arg)
ssh.Message().Back(msg)
m.Copy(msg, "result").Copy(msg, "append")
} // }}}
}},
"close": &ctx.Command{Name: "close", Help: "连接断开", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
m.Target().Close(m)
}},
"list": &ctx.Command{Name: "list", Help: "连接断开", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
domain := m.Cap("domain")
m.Travel(func(m *ctx.Message, i int) bool {
if m.Confs("domains") {
m.Echo("%s: %s.%s\n", m.Target().Name, domain, m.Conf("domains"))
}
return true
}, c)
}},
"save": &ctx.Command{Name: "save", Help: "远程执行", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
json := m.Sess("nfs") // {{{
json.Put("option", "data", map[string]string{"domain": m.Cap("domain")})
json.Cmd("json", m.Conf("domain.json"))
m.Sess("nfs").Cmd("genqr", m.Conf("domain.png"), json.Result(0))
// }}}
}},
"who": &ctx.Command{Name: "who", Help: "远程执行", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
aaa := m.Sess("aaa") // {{{
if aaa != nil {
m.Echo(aaa.Cap("group"))
}
// }}}
}},
"good": &ctx.Command{Name: "good context|command|config|cache args", Help: "设备注册", Hand: func(m *ctx.Message, c *ctx.Context, cmd string, arg ...string) {
if len(arg) == 0 { // {{{
m.Append("share", m.Cap("share"))
m.Append("level", m.Cap("level"))
m.Append("type", m.Conf("type"))
m.Append("value", m.Cap("domain"))
m.Append("kind", m.Conf("kind"))
m.Append("name", m.Cap("domain"))
m.Append("mark", m.Conf("mark"))
m.Append("count", m.Cap("count"))
m.Back(m)
return
}
cmds := m.Option("cmds")
if arg[0] == "context" {
if len(arg) > 1 {
cmds = arg[1]
}
m.Travel(func(msg *ctx.Message, i int) bool {
current := msg.Target()
if _, ok := current.Index[cmds]; ok {
} else if cmds != "" && cmds != "root" {
return true
}
m.Add("append", "name", current.Name)
m.Add("append", "help", current.Help)
return true
}, ctx.Index)
return
}
if len(arg) > 2 {
cmds = arg[2]
}
current := m.Sess(arg[1], arg[1], "search").Target()
if x, ok := current.Index[cmds]; ok {
current = x
} else if cmds != "" && cmds != "root" {
return
}
switch arg[0] {
case "command":
for k, x := range current.Commands {
m.Add("append", "key", k)
m.Add("append", "name", x.Name)
m.Add("append", "help", x.Help)
}
case "config":
for k, x := range current.Configs {
m.Add("append", "key", k)
m.Add("append", "name", x.Name)
m.Add("append", "value", x.Value)
m.Add("append", "help", x.Help)
}
case "cache":
for k, x := range current.Caches {
m.Add("append", "key", k)
m.Add("append", "name", x.Name)
m.Add("append", "value", x.Value)
m.Add("append", "help", x.Help)
}
} // }}}
}},
},
}
func init() {
ssh := &SSH{}
ssh.Context = Index
ctx.Index.Register(Index, ssh)
}