forked from x/icebergs
213 lines
5.9 KiB
Go
213 lines
5.9 KiB
Go
package tcp
|
|
|
|
import (
|
|
"os"
|
|
"path"
|
|
|
|
ice "github.com/shylinux/icebergs"
|
|
"github.com/shylinux/icebergs/base/aaa"
|
|
"github.com/shylinux/icebergs/base/cli"
|
|
kit "github.com/shylinux/toolkits"
|
|
|
|
"bufio"
|
|
"net"
|
|
"net/url"
|
|
"strings"
|
|
)
|
|
|
|
func _port_list(m *ice.Message) string {
|
|
return ""
|
|
}
|
|
func _port_get(m *ice.Message, begin string) string {
|
|
current := kit.Int(kit.Select(m.Conf(PORT, "meta.current"), begin))
|
|
end := kit.Int(m.Conf(PORT, "meta.end"))
|
|
if current >= end {
|
|
current = kit.Int(m.Conf(PORT, "meta.begin"))
|
|
}
|
|
for i := current; i < end; i++ {
|
|
if m.Cmd(cli.SYSTEM, "lsof", "-i", kit.Format(":%d", i)).Append(cli.CMD_CODE) != "0" {
|
|
m.Conf(PORT, "meta.current", i)
|
|
m.Log_SELECT(PORT, i)
|
|
return kit.Format("%d", i)
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func _ip_list(m *ice.Message, ifname string) {
|
|
if ifs, e := net.Interfaces(); m.Assert(e) {
|
|
for _, v := range ifs {
|
|
if ifname != "" && !strings.Contains(v.Name, ifname) {
|
|
continue
|
|
}
|
|
if ips, e := v.Addrs(); m.Assert(e) {
|
|
for _, x := range ips {
|
|
ip := strings.Split(x.String(), "/")
|
|
if strings.Contains(ip[0], ":") || len(ip) == 0 {
|
|
continue
|
|
}
|
|
if len(v.HardwareAddr.String()) == 0 {
|
|
continue
|
|
}
|
|
|
|
m.Push("index", v.Index)
|
|
m.Push("name", v.Name)
|
|
m.Push("ip", ip[0])
|
|
m.Push("mask", ip[1])
|
|
m.Push("hard", v.HardwareAddr.String())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
func _ip_islocal(m *ice.Message, ip string) (ok bool) {
|
|
if ip == "::1" || strings.HasPrefix(ip, "127.") {
|
|
return true
|
|
}
|
|
|
|
if m.Richs(IP, kit.Keys("meta.white"), ip, nil) == nil {
|
|
return false
|
|
}
|
|
m.Log_AUTH(aaa.White, ip)
|
|
return true
|
|
}
|
|
func IPIsLocal(m *ice.Message, ip string) bool {
|
|
return _ip_islocal(m, ip)
|
|
}
|
|
|
|
const (
|
|
IP = "ip"
|
|
PORT = "port"
|
|
)
|
|
|
|
var Index = &ice.Context{Name: "tcp", Help: "通信模块",
|
|
Configs: map[string]*ice.Config{
|
|
PORT: {Name: "port", Help: "端口", Value: kit.Data(
|
|
"begin", 10000, "current", 10000, "end", 20000,
|
|
)},
|
|
IP: {Name: "ip", Help: "地址", Value: kit.Data(
|
|
"black", kit.Dict(),
|
|
"white", kit.Data(kit.MDB_SHORT, kit.MDB_TEXT),
|
|
)},
|
|
},
|
|
Commands: map[string]*ice.Command{
|
|
ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
|
m.Load()
|
|
m.Cmd(IP).Table(func(index int, value map[string]string, head []string) {
|
|
m.Cmd(IP, aaa.White, value[IP])
|
|
})
|
|
|
|
}},
|
|
ice.CTX_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Save(PORT) }},
|
|
|
|
IP: {Name: "ip", Help: "地址", Action: map[string]*ice.Action{
|
|
aaa.White: {Name: "show ip", Help: "白名单", Hand: func(m *ice.Message, arg ...string) {
|
|
m.Rich(IP, kit.Keys("meta.white"), kit.Dict(
|
|
kit.MDB_NAME, "",
|
|
kit.MDB_TEXT, arg[0],
|
|
))
|
|
}},
|
|
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
|
_ip_list(m, "")
|
|
}},
|
|
PORT: {Name: "port", Help: "端口", Action: map[string]*ice.Action{
|
|
"get": {Name: "get", Help: "分配端口", Hand: func(m *ice.Message, arg ...string) {
|
|
m.Echo(_port_get(m, ""))
|
|
}},
|
|
"select": {Name: "select [begin]", Help: "分配端口", Hand: func(m *ice.Message, arg ...string) {
|
|
port, p := kit.Select("", arg, 0), ""
|
|
for i := 0; i < 10; i++ {
|
|
port = _port_get(m, port)
|
|
p = path.Join(m.Conf(cli.DAEMON, kit.META_PATH), port)
|
|
if _, e := os.Stat(p); e != nil && os.IsNotExist(e) {
|
|
break
|
|
}
|
|
port = kit.Format(kit.Int(port) + 1)
|
|
}
|
|
os.MkdirAll(p, ice.MOD_DIR)
|
|
m.Echo(port)
|
|
}},
|
|
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
|
_port_list(m)
|
|
}},
|
|
|
|
"server": {Name: "server [tcp4|tcp6|udp4|udp6] addr", Help: "server", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
|
proto := "tcp4"
|
|
switch arg[0] {
|
|
case "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6", "ip", "ip4", "ip6":
|
|
proto, arg = arg[0], arg[1:]
|
|
}
|
|
|
|
if l, e := net.Listen(proto, arg[0]); m.Assert(e) {
|
|
m.Gos(m, func(m *ice.Message) {
|
|
// 启动服务
|
|
m.Logs(ice.LOG_LISTEN, "addr", l.Addr())
|
|
for {
|
|
if c, e := l.Accept(); m.Assert(e) {
|
|
m.Gos(m.Spawns(), func(msg *ice.Message) {
|
|
// 建立连接
|
|
msg.Logs(ice.LOG_ACCEPT, "addr", c.RemoteAddr())
|
|
msg.Option(ice.MSG_USERADDR, c.RemoteAddr())
|
|
msg.Option(ice.MSG_USERNAME, "")
|
|
msg.Option(ice.MSG_USERROLE, "")
|
|
|
|
switch msg.Cmdx("check", c.RemoteAddr().String()) {
|
|
case "local":
|
|
// 本机用户
|
|
msg.Option(ice.MSG_USERNAME, msg.Conf(cli.RUNTIME, "boot.username"))
|
|
msg.Option(ice.MSG_USERROLE, msg.Cmdx(aaa.ROLE, "check", msg.Option(ice.MSG_USERNAME)))
|
|
msg.Logs(ice.LOG_AUTH, "name", msg.Option(ice.MSG_USERNAME), "role", msg.Option(ice.MSG_USERROLE))
|
|
}
|
|
|
|
cmds := []string{}
|
|
buf := bufio.NewWriter(c)
|
|
for bio := bufio.NewScanner(c); bio.Scan(); {
|
|
text := bio.Text()
|
|
msg.Logs("scan", "len", len(text), "text", text)
|
|
|
|
if len(text) == 0 {
|
|
if len(cmds) > 0 {
|
|
msg.Cmd(aaa.ROLE, "right")
|
|
// 执行命令
|
|
res := msg.Cmd(cmds)
|
|
|
|
// 返回结果
|
|
for _, str := range res.Resultv() {
|
|
buf.WriteString("result:")
|
|
buf.WriteString(url.QueryEscape(str))
|
|
buf.WriteString("\n")
|
|
}
|
|
buf.WriteString("\n")
|
|
buf.Flush()
|
|
|
|
cmds = cmds[:0]
|
|
}
|
|
continue
|
|
}
|
|
|
|
// 解析请求
|
|
line := strings.SplitN(bio.Text(), ":", 2)
|
|
line[0], e = url.QueryUnescape(line[0])
|
|
m.Assert(e)
|
|
line[1], e = url.QueryUnescape(line[1])
|
|
m.Assert(e)
|
|
switch line[0] {
|
|
case "cmds", ice.MSG_DETAIL:
|
|
cmds = append(cmds, line[1])
|
|
default:
|
|
msg.Option(line[0], line[1])
|
|
}
|
|
}
|
|
msg.Logs(ice.LOG_FINISH, "addr", c.RemoteAddr())
|
|
})
|
|
}
|
|
}
|
|
m.Logs(ice.LOG_FINISH, "addr", l.Addr())
|
|
})
|
|
}
|
|
}},
|
|
},
|
|
}
|
|
|
|
func init() { ice.Index.Register(Index, nil, IP, PORT) }
|