1
0
forked from x/ContextOS

213 lines
5.9 KiB
Go

package tcp // {{{
// }}}
import ( // {{{
"contexts"
"crypto/tls"
"fmt"
"net"
"strconv"
)
// }}}
type TCP struct {
net.Conn
net.Listener
*ctx.Context
}
func (tcp *TCP) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { // {{{
c.Caches = map[string]*ctx.Cache{
"protocol": &ctx.Cache{Name: "网络协议(tcp/tcp4/tcp6)", Value: m.Conf("protocol"), Help: "网络协议"},
"security": &ctx.Cache{Name: "加密通信(true/false)", Value: m.Conf("security"), Help: "加密通信"},
"address": &ctx.Cache{Name: "网络地址", Value: "", Help: "网络地址"},
}
c.Configs = map[string]*ctx.Config{}
s := new(TCP)
s.Context = c
return s
}
// }}}
func (tcp *TCP) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{
tcp.Context.Master(nil)
if tcp.Context == Index {
Pulse = m
}
return tcp
}
// }}}
func (tcp *TCP) Start(m *ctx.Message, arg ...string) bool { // {{{
if len(arg) > 1 {
m.Cap("address", arg[1])
}
if len(arg) > 2 {
m.Cap("security", arg[2])
}
if len(arg) > 3 {
m.Cap("protocol", arg[3])
}
switch arg[0] {
case "dial":
if m.Caps("security") {
cert, e := tls.LoadX509KeyPair(m.Conf("cert"), m.Conf("key"))
m.Assert(e)
conf := &tls.Config{Certificates: []tls.Certificate{cert}}
c, e := tls.Dial(m.Cap("protocol"), m.Cap("address"), conf)
m.Assert(e)
tcp.Conn = c
} else {
c, e := net.Dial(m.Cap("protocol"), m.Cap("address"))
m.Assert(e)
tcp.Conn = c
}
m.Log("info", nil, "%s dial %s", Pulse.Cap("nclient"),
m.Append("stream", m.Cap("stream", fmt.Sprintf("%s->%s", tcp.LocalAddr(), tcp.RemoteAddr()))))
m.Put("append", "io", tcp.Conn).Back(true, m)
return false
case "accept":
c, e := m.Data["io"].(net.Conn)
m.Assert(e)
tcp.Conn = c
m.Log("info", nil, "%s accept %s", Pulse.Cap("nclient"),
m.Append("stream", m.Cap("stream", fmt.Sprintf("%s<-%s", tcp.LocalAddr(), tcp.RemoteAddr()))))
m.Put("append", "io", tcp.Conn).Back(true, m)
m.Log("fuck", nil, "accept")
return false
default:
if m.Cap("security") != "false" {
cert, e := tls.LoadX509KeyPair(m.Conf("cert"), m.Conf("key"))
m.Assert(e)
conf := &tls.Config{Certificates: []tls.Certificate{cert}}
l, e := tls.Listen(m.Cap("protocol"), m.Cap("address"), conf)
m.Assert(e)
tcp.Listener = l
} else {
l, e := net.Listen(m.Cap("protocol"), m.Cap("address"))
m.Assert(e)
tcp.Listener = l
}
m.Log("info", nil, "%d listen %v", Pulse.Capi("nlisten"), m.Cap("stream", fmt.Sprintf("%s", tcp.Addr())))
}
for {
c, e := tcp.Accept()
m.Assert(e)
msg := m.Spawn(Index).Put("option", "io", c).Put("option", "source", m.Source())
msg.Call(func(ok bool, com *ctx.Message) (bool, *ctx.Message) {
if ok {
m.Append("stream", msg.Append("stream"))
m.Put("append", "io", msg.Data["io"])
com.Log("fuck", nil, "listen")
}
return ok, com
}, false).Start(fmt.Sprintf("com%d", Pulse.Capi("nclient", 1)), "网络连接",
"accept", c.RemoteAddr().String(), m.Cap("security"), m.Cap("protocol"))
}
return true
}
// }}}
func (tcp *TCP) Close(m *ctx.Message, arg ...string) bool { // {{{
switch tcp.Context {
case m.Target():
if tcp.Listener != nil {
m.Log("info", nil, "%d close %v", Pulse.Capi("nlisten", -1)+1, m.Cap("stream"))
tcp.Listener.Close()
tcp.Listener = nil
}
if tcp.Conn != nil {
m.Log("info", nil, "%d close %v", Pulse.Capi("nclient", -1)+1, m.Cap("stream"))
tcp.Conn.Close()
tcp.Conn = nil
}
case m.Source():
if tcp.Conn != nil {
msg := m.Spawn(tcp.Context)
if msg.Master(tcp.Context); !tcp.Context.Close(msg, arg...) {
return false
}
}
}
return true
}
// }}}
var Pulse *ctx.Message
var Index = &ctx.Context{Name: "tcp", Help: "网络中心",
Caches: map[string]*ctx.Cache{
"nlisten": &ctx.Cache{Name: "监听数量", Value: "0", Help: "监听数量"},
"nclient": &ctx.Cache{Name: "连接数量", Value: "0", Help: "连接数量"},
},
Configs: map[string]*ctx.Config{
"security": &ctx.Config{Name: "加密通信(true/false)", Value: "false", Help: "加密通信"},
"protocol": &ctx.Config{Name: "网络协议(tcp/tcp4/tcp6)", Value: "tcp4", Help: "网络协议"},
},
Commands: map[string]*ctx.Command{
"listen": &ctx.Command{Name: "listen address [security [protocol]]", Help: "网络监听",
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
m.Start(fmt.Sprintf("pub%d", Pulse.Capi("nlisten", 1)), "网络监听", m.Meta["detail"]...)
}},
"dial": &ctx.Command{Name: "dial address [security [protocol]]", Help: "网络连接",
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
m.Start(fmt.Sprintf("com%d", Pulse.Capi("nclient", 1)), "网络连接", m.Meta["detail"]...)
}},
"send": &ctx.Command{Name: "send message", Help: "发送消息",
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
tcp, ok := m.Target().Server.(*TCP)
m.Assert(ok && tcp.Conn != nil)
tcp.Conn.Write([]byte(arg[0]))
}},
"recv": &ctx.Command{Name: "recv size", Help: "接收消息",
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
tcp, ok := m.Target().Server.(*TCP)
m.Assert(ok && tcp.Conn != nil)
size, e := strconv.Atoi(arg[0])
m.Assert(e)
buf := make([]byte, size)
tcp.Conn.Read(buf)
m.Echo(string(buf))
}},
"ifconfig": &ctx.Command{Name: "ifconfig", Help: "接收消息",
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
ifs, e := net.Interfaces()
m.Assert(e)
for _, v := range ifs {
ips, e := v.Addrs()
m.Assert(e)
for _, x := range ips {
m.Echo("%d %s %v %v\n", v.Index, v.Name, v.HardwareAddr, x.String())
}
}
}},
},
Index: map[string]*ctx.Context{
"void": &ctx.Context{
Commands: map[string]*ctx.Command{
"listen": &ctx.Command{},
"dial": &ctx.Command{},
},
},
},
}
func init() {
tcp := &TCP{}
tcp.Context = Index
ctx.Index.Register(Index, tcp)
}