diff --git a/src/context/lex/lex.go b/src/context/lex/lex.go deleted file mode 100644 index 3b1ee784..00000000 --- a/src/context/lex/lex.go +++ /dev/null @@ -1,375 +0,0 @@ -package lex // {{{ -// }}} -import ( // {{{ - "context" - "fmt" -) - -// }}} - -type State struct { - star bool - next int - hash int -} - -type Seed struct { - page int - hash int - word string -} - -type LEX struct { - seed []*Seed - page map[string]int - hash map[string]int - - state map[State]*State - mat []map[byte]*State - - *ctx.Message - *ctx.Context -} - -func (lex *LEX) train(seed []byte, arg ...string) { // {{{ - cell, page, hash := 128, 1, 1 // {{{ - if len(arg) > 0 { - if x, ok := lex.hash[arg[0]]; ok { - hash = x - } else { - hash = lex.Capi("nhash", 1) - lex.hash[arg[0]] = hash - } - } - if len(arg) > 1 { - if x, ok := lex.page[arg[1]]; ok { - page = x - } else { - lex.mat = append(lex.mat, make(map[byte]*State)) - page = lex.Capi("nline", 1) - lex.page[arg[1]] = page - lex.Capi("npage", 1) - } - } - lex.Log("debug", nil, "%d %d %v", page, hash, seed) - lex.seed = append(lex.seed, &Seed{page, hash, string(seed)}) - lex.Capi("nseed", 1) - lex.Cap("stream", fmt.Sprintf("%s,%s,%s", lex.Cap("nseed"), lex.Cap("npage"), lex.Cap("nhash"))) - // }}} - - s := []int{page} - c := make([]byte, 0, cell) - sn := make([]bool, len(lex.mat)) - cn := make([]bool, cell) - - ends := make([]*State, 0, len(seed)) - - for p := 0; p < len(seed); p++ { - switch seed[p] { - case '[': - p++ - set := true - if seed[p] == '^' { - set = false - p++ - } - - for ; seed[p] != ']'; p++ { - if seed[p] == '\\' { - p++ - cn[seed[p]] = true - continue - } - - if seed[p+1] == '-' { - begin, end := seed[p], seed[p+2] - if begin > end { - begin, end = end, begin - } - for i := begin; i <= end; i++ { - cn[i] = true - } - p += 2 - } - - cn[seed[p]] = true - } - - for i := 0; i < len(cn); i++ { - if (set && cn[i]) || (!set && !cn[i]) { - c = append(c, byte(i)) - } - cn[i] = false - } - - case '.': - for i := 0; i < cell; i++ { - c = append(c, byte(i)) - } - case '\\': - p++ - fallthrough - default: - c = append(c, seed[p]) - } - - lex.Log("debug", nil, "page: \033[31m%v\033[0m", s) - lex.Log("debug", nil, "cell: \033[32m%v\033[0m", c) - - flag := '\000' - if p+1 < len(seed) { - flag = rune(seed[p+1]) - switch flag { - case '+', '*', '?': - p++ - } - } - - for i := 0; i < len(s); i++ { - for line, j := 0, byte(0); int(j) < len(c); j++ { - state := lex.mat[s[i]][c[j]] - if state == nil { - state = new(State) - lex.Capi("nnode", 1) - } - lex.Log("debug", nil, "GET(%d,%d): %v", s[i], c[j], state) - - switch flag { - case '+': - state.star = true - case '*': - state.star = true - fallthrough - case '?': - if sn[s[i]] = true; p == len(seed)-1 { - for _, n := range ends { - if n.next == s[i] && n.hash == 0 { - lex.Log("debug", nil, "GET() state:%v", n) - n.hash = hash - lex.Log("debug", nil, "END() state:%v", n) - } - } - } - } - - if p == len(seed)-1 { - state.hash = hash - } else { - if state.next == 0 { - if line == 0 { - line = len(lex.mat) - sn = append(sn, false) - lex.mat = append(lex.mat, make(map[byte]*State)) - lex.Capi("nline", 1) - } - state.next = line - } - sn[state.next] = true - } - - if s, ok := lex.state[*state]; ok { - state = s - } - - lex.state[*state] = state - lex.mat[s[i]][c[j]] = state - - lex.Log("debug", nil, "SET(%d,%d): %v", s[i], c[j], state) - ends = append(ends, state) - } - } - - c, s = c[:0], s[:0] - for i := 0; i < len(sn); i++ { - if sn[i] { - s = append(s, i) - } - sn[i] = false - } - } -} - -// }}} -func (lex *LEX) parse(line []byte, arg ...string) (word []byte, hash int, rest []byte) { // {{{ - page, begin, end := 1, 0, 0 // {{{ - if len(arg) > 0 { - if x, ok := lex.page[arg[0]]; ok { - page = x - } else { - return line, 0, nil - } - } - // }}} - - for star, s, i := 0, page, 0; s != 0 && i < len(line); i++ { - - c := line[i] - if c == '\\' && i < len(line)-1 { - c = 'a' - end++ - i++ - } - - state := lex.mat[s][c] - lex.Log("debug", nil, "(%d,%d): %v", s, c, state) - if state == nil && star != 0 { - s, star = star, 0 - state = lex.mat[s][c] - lex.Log("debug", nil, "(%d,%d): %v", s, c, state) - } - if state == nil { - break - } - - if state, ok := lex.mat[star][c]; star == 0 || !ok || state == nil || !state.star { - star = 0 - } - - if end++; state.star { - star = s - } - - if s, hash = state.next, state.hash; s == 0 { - s, star = star, 0 - } - } - - if hash == 0 { - begin, end = 0, 0 - } - - word, rest = line[begin:end], line[end:] - lex.Log("debug", nil, "\033[31m[%v]\033[0m %d [%v]", string(word), hash, string(rest)) - return -} - -// }}} - -func (lex *LEX) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { // {{{ - c.Caches = map[string]*ctx.Cache{} - c.Configs = map[string]*ctx.Config{} - - s := new(LEX) - s.Context = c - return s -} - -// }}} -func (lex *LEX) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{ - lex.Message = m - lex.Caches["nseed"] = &ctx.Cache{Name: "种子数量", Value: "0", Help: "种子数量"} - lex.Caches["npage"] = &ctx.Cache{Name: "集合数量", Value: "1", Help: "集合数量"} - lex.Caches["nhash"] = &ctx.Cache{Name: "类型数量", Value: "1", Help: "类型数量"} - - lex.Caches["nline"] = &ctx.Cache{Name: "状态数量", Value: "1", Help: "状态数量"} - lex.Caches["nnode"] = &ctx.Cache{Name: "节点数量", Value: "0", Help: "节点数量"} - lex.Caches["npush"] = &ctx.Cache{Name: "节点数量", Value: "0", Help: "节点数量", Hand: func(m *ctx.Message, x *ctx.Cache, arg ...string) string { - lex := m.Target.Server.(*LEX) // {{{ - return fmt.Sprintf("%d", len(lex.state)) - // }}} - }} - - return lex -} - -// }}} -func (lex *LEX) Start(m *ctx.Message, arg ...string) bool { // {{{ - lex.seed = make([]*Seed, 0, 10) - lex.page = map[string]int{"nil": 0} - lex.hash = map[string]int{"nil": 0} - - lex.state = make(map[State]*State) - lex.mat = make([]map[byte]*State, 2, 10) - for i := 0; i < len(lex.mat); i++ { - lex.mat[i] = make(map[byte]*State) - } - - lex.Message = m - return false -} - -// }}} -func (lex *LEX) Close(m *ctx.Message, arg ...string) bool { // {{{ - return false -} - -// }}} - -var Index = &ctx.Context{Name: "lex", Help: "词法解析", - Caches: map[string]*ctx.Cache{}, - Configs: map[string]*ctx.Config{}, - Commands: map[string]*ctx.Command{ - "train": &ctx.Command{Name: "train seed [hash [page]", Help: "添加词法规则", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) string { - lex, ok := m.Target.Server.(*LEX) // {{{ - m.Assert(ok, "模块类型错误") - m.Assert(len(arg) > 0, "参数错误") - - lex.train([]byte(arg[0]), arg[1:]...) - return "" - // }}} - }}, - "parse": &ctx.Command{Name: "parse line [page]", Help: "解析单词", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) string { - lex, ok := m.Target.Server.(*LEX) // {{{ - m.Assert(ok, "模块类型错误") - m.Assert(len(arg) > 0, "参数错误") - - word, hash, rest := lex.parse([]byte(arg[0]), arg[1:]...) - m.Add("result", string(word), fmt.Sprintf("%d", hash), string(rest)) - return "" - // }}} - }}, - "split": &ctx.Command{Name: "split line page1 [page2]", Help: "分割语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) string { - lex, ok := m.Target.Server.(*LEX) // {{{ - m.Assert(ok, "模块类型错误") - m.Assert(len(arg) > 1, "参数错误") - - for line := arg[0]; len(line) > 0; { - word, hash, rest := lex.parse([]byte(line), arg[1:]...) - line = string(rest) - word, hash, rest = lex.parse([]byte(line), arg[2:]...) - line = string(rest) - - if hash == 0 { - break - } - m.Echo(string(word)) - } - return "" - // }}} - }}, - "cache": &ctx.Command{Name: "cache", Help: "显示缓存", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) string { - lex, ok := m.Target.Server.(*LEX) // {{{ - m.Assert(ok, "模块类型错误") - for i, v := range lex.seed { - m.Echo("seed: %d %v\n", i, v) - } - for i, v := range lex.page { - m.Echo("page: %s %d\n", i, v) - } - for i, v := range lex.hash { - m.Echo("hash: %s %d\n", i, v) - } - for i, v := range lex.state { - m.Echo("node: %v %v\n", i, v) - } - for i, v := range lex.mat { - for k, v := range v { - m.Echo("node: %v %v %v\n", i, k, v) - } - } - return "" - // }}} - }}, - }, - Index: map[string]*ctx.Context{ - "void": &ctx.Context{Name: "void", - Commands: map[string]*ctx.Command{"split": &ctx.Command{}}, - }, - }, -} - -func init() { - lex := &LEX{} - lex.Context = Index - ctx.Index.Register(Index, lex) -} diff --git a/src/context/lex/lex_test.go b/src/context/lex/lex_test.go deleted file mode 100644 index 70aca707..00000000 --- a/src/context/lex/lex_test.go +++ /dev/null @@ -1,152 +0,0 @@ -package lex - -import ( - "context" - "testing" -) - -func TestLEX(t *testing.T) { - - m := ctx.Pulse.Spawn(Index) - seed := map[string]map[string]string{ - // "shy?": map[string]string{ - // "s": "", - // "sh": "sh", - // "she": "sh", - // "shy": "shy", - // "shyyy": "shy", - // }, - // "shy*": map[string]string{ - // "s": "", - // "sh": "sh", - // "she": "sh", - // "shy": "shy", - // "shyyy": "shyyy", - // }, - // "shy+": map[string]string{ - // "s": "", - // "sh": "", - // "she": "", - // "shy": "shy", - // "shyyy": "shyyy", - // }, - // "s?hy": map[string]string{ - // "s": "", - // "sh": "", - // "she": "", - // "shy": "shy", - // "hy": "hy", - // }, - // "s*hy": map[string]string{ - // "s": "", - // "sh": "", - // "she": "", - // "shy": "shy", - // "ssshy": "ssshy", - // "hy": "hy", - // }, - // "s+hy": map[string]string{ - // "s": "", - // "sh": "", - // "she": "", - // "shy": "shy", - // "ssshy": "ssshy", - // "hy": "", - // }, - // "sh[xyz]?": map[string]string{ - // "s": "", - // "sh": "sh", - // "she": "sh", - // "shy": "shy", - // "shyyy": "shy", - // }, - // "sh[xyz]*": map[string]string{ - // "s": "", - // "sh": "sh", - // "she": "sh", - // "shy": "shy", - // "shyyy": "shyyy", - // "shyxz": "shyxz", - // }, - // "sh[xyz]+": map[string]string{ - // "s": "", - // "sh": "", - // "she": "", - // "shy": "shy", - // "shyyy": "shyyy", - // "shyxzy": "shyxzy", - // }, - // "[xyz]?sh": map[string]string{ - // "s": "", - // "sh": "sh", - // "zsh": "zsh", - // "zxyshy": "", - // }, - // "[xyz]*sh": map[string]string{ - // "s": "", - // "sh": "sh", - // "zsh": "zsh", - // "zxyshy": "zxysh", - // }, - // "[xyz]+sh": map[string]string{ - // "s": "", - // "sh": "", - // "zsh": "zsh", - // "zxyshy": "zxysh", - // }, - // "[0-9]+": map[string]string{ - // "hello": "", - // "hi123": "", - // "123": "123", - // "123hi": "123", - // }, - // "0x[0-9a-fA-F]+": map[string]string{ - // "hello": "", - // "0xhi123": "", - // "0x123": "0x123", - // "0xab123ab": "0xab123ab", - // "0x123ab": "0x123ab", - // }, - "[a-zA-Z][a-zA-Z0-9]*": map[string]string{ - "hello": "hello", - "hi123": "hi123", - "123": "", - }, - "\"[^\"]*\"": map[string]string{ - "hello": "", - "0xhi123": "", - "\"hi\"": "\"hi\"", - "\"\\\"hi\"": "\"\\\"hi\"", - }, - } - m.Conf("debug", "on") - Index.Begin(m) - for k, s := range seed { - Index.Start(m) - m.Cmd("train", k) - for i, v := range s { - if m.Cmd("parse", i) != v { - t.Error("train&parse error:", k, i, v) - } - } - } - - Index.Start(m) - m.Cmd("train", "[ \n\t]+", "1") - m.Cmd("train", "[a-zA-Z][a-zA-Z0-9]*", "2", "2") - m.Cmd("train", "0x[0-9]+", "3", "2") - m.Cmd("train", "[0-9]+", "3", "2") - m.Cmd("train", "\"[^\"]*\"", "4", "2") - m.Cmd("train", "'[^']*'", "4", "2") - - lex := Index.Server.(*LEX) - for _, v := range lex.seed { - t.Log(v.page, v.hash, v.word) - } - - m.Cmd("split", "hello 0x2134 \"hi he\" meet\\ you") - // m.Cmd("parse", "0x54 nice to meet") - // m.Cmd("parse", "737 nice to meet") - // m.Cmd("parse", "\"73 u\" nice to meet") - // m.Cmd("parse", "'hh h' nice to meet") -} diff --git a/src/context/mdb/mdb.go b/src/context/mdb/mdb.go deleted file mode 100644 index be0de87d..00000000 --- a/src/context/mdb/mdb.go +++ /dev/null @@ -1,175 +0,0 @@ -package mdb // {{{ -// }}} -import ( // {{{ - "context" - - "database/sql" - _ "github.com/go-sql-driver/mysql" - - "fmt" -) - -// }}} - -type MDB struct { - *sql.DB - *ctx.Context -} - -func (mdb *MDB) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { // {{{ - c.Caches = map[string]*ctx.Cache{ - "source": &ctx.Cache{Name: "数据库参数", Value: "", Help: "数据库参数"}, - "driver": &ctx.Cache{Name: "数据库驱动", Value: "", Help: "数据库驱动"}, - } - c.Configs = map[string]*ctx.Config{} - - s := new(MDB) - s.Context = c - return s -} - -// }}} -func (mdb *MDB) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{ - return mdb -} - -// }}} -func (mdb *MDB) Start(m *ctx.Message, arg ...string) bool { // {{{ - if len(arg) > 0 { - m.Cap("source", arg[0]) - } - if len(arg) > 1 { - m.Cap("driver", arg[1]) - } else { - m.Cap("driver", m.Conf("driver")) - } - - if m.Cap("source") == "" || m.Cap("driver") == "" { - return false - } - - m.Cap("stream", m.Cap("source")) - db, e := sql.Open(m.Cap("driver"), m.Cap("source")) - m.Assert(e) - mdb.DB = db - - m.Log("info", nil, "%d open %s %s", m.Capi("nsource", 1), m.Cap("driver"), m.Cap("source")) - return false -} - -// }}} -func (mdb *MDB) Close(m *ctx.Message, arg ...string) bool { // {{{ - if mdb.Context == Index { - return false - } - - switch mdb.Context { - case m.Target: - case m.Source: - } - - if mdb.DB != nil { - m.Log("info", nil, "%d close %s %s", m.Capi("nsource", -1)+1, m.Cap("driver"), m.Cap("source")) - mdb.DB.Close() - mdb.DB = nil - } - - return true -} - -// }}} - -var Index = &ctx.Context{Name: "mdb", Help: "数据中心", - Caches: map[string]*ctx.Cache{ - "nsource": &ctx.Cache{Name: "数据源数量", Value: "0", Help: "已打开数据库的数量"}, - }, - Configs: map[string]*ctx.Config{ - "driver": &ctx.Config{Name: "数据库驱动(mysql)", Value: "mysql", Help: "数据库驱动"}, - }, - Commands: map[string]*ctx.Command{ - "open": &ctx.Command{Name: "open name help source [driver]", Help: "打开数据库", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) string { - m.Assert(len(arg) > 2, "缺少参数") // {{{ - m.Master, m.Target = c, c - m.Cap("stream", m.Cap("nsource")) - m.Start(arg[0], "数据存储", arg[2:]...) - return "" - // }}} - }}, - "exec": &ctx.Command{Name: "exec sql [arg]", Help: "操作数据库", - Appends: map[string]string{"LastInsertId": "最后插入元组的标识", "RowsAffected": "修改元组的数量"}, - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) string { - mdb, ok := m.Target.Server.(*MDB) // {{{ - m.Assert(ok, "目标模块类型错误") - m.Assert(len(arg) > 0, "缺少参数") - m.Assert(mdb.DB != nil, "数据库未打开") - - which := make([]interface{}, 0, len(arg)) - for _, v := range arg[1:] { - which = append(which, v) - } - - ret, e := mdb.Exec(arg[0], which...) - m.Assert(e) - id, e := ret.LastInsertId() - m.Assert(e) - n, e := ret.RowsAffected() - m.Assert(e) - - m.Echo("%d", id).Echo("%d", n) - m.Add("append", "LastInsertId", fmt.Sprintf("%d", id)) - m.Add("append", "RowsAffected", fmt.Sprintf("%d", n)) - m.Log("info", nil, "last(%d) rows(%d)", id, n) - return "" - // }}} - }}, - "query": &ctx.Command{Name: "query sql [arg]", Help: "执行查询语句", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) string { - mdb, ok := m.Target.Server.(*MDB) // {{{ - m.Assert(ok, "目标模块类型错误") - m.Assert(len(arg) > 0, "缺少参数") - m.Assert(mdb.DB != nil, "数据库未打开") - - which := make([]interface{}, 0, len(arg)) - for _, v := range arg[1:] { - which = append(which, v) - } - - rows, e := mdb.Query(arg[0], which...) - m.Assert(e) - defer rows.Close() - - cols, e := rows.Columns() - m.Assert(e) - num := len(cols) - - for rows.Next() { - vals := make([]interface{}, num) - ptrs := make([]interface{}, num) - for i := range vals { - ptrs[i] = &vals[i] - } - rows.Scan(ptrs...) - - for i, k := range cols { - switch b := vals[i].(type) { - case []byte: - m.Add("append", k, string(b)) - case int64: - m.Add("append", k, fmt.Sprintf("%d", b)) - default: - m.Add("append", k, "") - } - } - } - - m.Log("info", nil, "rows(%d) cols(%d)", len(m.Meta[m.Meta["append"][0]]), len(m.Meta["append"])) - return "" - // }}} - }}, - }, -} - -func init() { - mdb := &MDB{} - mdb.Context = Index - ctx.Index.Register(Index, mdb) -} diff --git a/src/context/mdb/mdb_test.go b/src/context/mdb/mdb_test.go deleted file mode 100644 index 4029ff2f..00000000 --- a/src/context/mdb/mdb_test.go +++ /dev/null @@ -1,61 +0,0 @@ -package mdb - -import ( - "context" - "flag" - "log" - "os" - "testing" -) - -func TestOpen(t *testing.T) { - flag.Parse() - args := flag.Args() - if len(args) < 2 { - t.Fatal("usages: -args source driver [table]") - } - - source := "user:word@/book" - driver := "mysql" - source = args[0] - driver = args[1] - - //mysql -u root -p; - //create database book; - //grant all on book.* to user identified by 'word' - - ctx.Start() - ctx.Index.Conf("debug", "off") - log.SetOutput(os.Stdout) - m := ctx.Pulse.Spawn(Index) - - m.Meta = nil - m.Cmd("open", source, driver) - - m.Meta = nil - m.Cmd("exec", "insert into program(time, hash, name) values(?, ?, ?)", "1", "2", "3") - - m.Meta = nil - m.Cmd("exec", "insert into program(time, hash, name) values(?, ?, ?)", "1", "2", "3") - - m.Meta = nil - m.Cmd("exec", "insert into program(time, hash, name) values(?, ?, ?)", "2", "3", "4") - - m.Meta = nil - m.Cmd("query", "select time, hash, name from program") - - t.Log() - for i, rows := 0, len(m.Meta[m.Meta["append"][0]]); i < rows; i++ { - for _, k := range m.Meta["append"] { - t.Log(k, m.Meta[k][i]) - } - t.Log() - } - - if len(m.Meta["append"]) != 3 || len(m.Meta[m.Meta["append"][0]]) != 2 { - t.Error() - } - - m.Meta = nil - // Index.Exit(m) -} diff --git a/src/context/tcp/tcp.go b/src/context/tcp/tcp.go deleted file mode 100644 index 8f0912b6..00000000 --- a/src/context/tcp/tcp.go +++ /dev/null @@ -1,202 +0,0 @@ -package tcp // {{{ -// }}} -import ( // {{{ - "context" - - "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: "protocol(tcp/tcp4/tcp6)", Value: m.Conf("protocol"), Help: "监听地址"}, - "security": &ctx.Cache{Name: "security(true/false)", Value: m.Conf("security"), Help: "加密通信"}, - "address": &ctx.Cache{Name: "address", 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 { // {{{ - if m.Target == 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]) - } - - switch arg[0] { - case "dial": - c, e := net.Dial(m.Cap("protocol"), m.Cap("address")) - m.Assert(e) - tcp.Conn = c - m.Log("info", nil, "dial(%d) %v->%v", m.Capi("nclient", 1), tcp.LocalAddr(), tcp.RemoteAddr()) - m.Cap("stream", fmt.Sprintf("%s->%s", tcp.LocalAddr(), tcp.RemoteAddr())) - - // m.Reply(c.LocalAddr().String()).Put("option", "io", c).Cmd("open") - return false - case "accept": - c, e := m.Data["io"].(net.Conn) - m.Assert(e) - tcp.Conn = c - m.Log("info", nil, "accept(%d) %v<-%v", m.Capi("nclient", 1), tcp.LocalAddr(), tcp.RemoteAddr()) - m.Cap("stream", fmt.Sprintf("%s<-%s", tcp.LocalAddr(), tcp.RemoteAddr())) - - s, e := m.Data["source"].(*ctx.Context) - m.Assert(e) - msg := m.Spawn(s).Put("option", "io", c) - msg.Cmd("open") - msg.Cap("stream", tcp.RemoteAddr().String()) - - if tcp.Sessions == nil { - tcp.Sessions = make(map[string]*ctx.Message) - } - tcp.Sessions["open"] = msg - msg.Name = "open" - - // m.Reply(c.RemoteAddr().String()) - return false - } - - l, e := net.Listen(m.Cap("protocol"), m.Cap("address")) - m.Assert(e) - tcp.Listener = l - m.Log("info", nil, "listen(%d) %v", m.Capi("nlisten", 1), l.Addr()) - m.Cap("stream", fmt.Sprintf("%s", l.Addr())) - - for { - c, e := l.Accept() - m.Assert(e) - m.Spawn(Index).Put("option", "io", c).Put("option", "source", m.Source).Start(fmt.Sprintf("com%d", m.Capi("nclient", 1)), "网络连接", "accept", c.RemoteAddr().String()) - } - - return true -} - -// }}} -func (tcp *TCP) Close(m *ctx.Message, arg ...string) bool { // {{{ - if tcp.Context == Index { - return false - } - - switch tcp.Context { - case m.Target: - case m.Source: - if tcp.Listener != nil { - return false - } - - } - - if tcp.Listener != nil { - m.Log("info", nil, "close(%d) %v", Pulse.Capi("nlisten", -1)+1, tcp.Listener.Addr()) - tcp.Listener.Close() - } - if tcp.Conn != nil { - m.Log("info", nil, "close %v", tcp.Conn.LocalAddr()) - tcp.Conn.Close() - } - return true -} - -// }}} - -var Index = &ctx.Context{Name: "tcp", Help: "网络中心", - Caches: map[string]*ctx.Cache{ - "nlisten": &ctx.Cache{Name: "nlisten", Value: "0", Help: "监听数量"}, - "nclient": &ctx.Cache{Name: "nclient", Value: "0", Help: "连接数量"}, - }, - Configs: map[string]*ctx.Config{ - "protocol": &ctx.Config{Name: "protocol(tcp/tcp4/tcp6)", Value: "tcp4", Help: "连接协议"}, - "security": &ctx.Config{Name: "security(true/false)", Value: "false", Help: "加密通信"}, - }, - Commands: map[string]*ctx.Command{ - "listen": &ctx.Command{Name: "listen [address [security]]", Help: "监听连接", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) string { - switch len(arg) { // {{{ - case 0: - m.Travel(nil, func(m *ctx.Message) bool { - if tcp, ok := m.Target.Server.(*TCP); ok && tcp.Listener != nil { - m.Echo("%s %v\n", m.Target.Name, tcp.Addr()) - } - return true - }) - default: - m.Start(fmt.Sprintf("pub%d", m.Capi("nlisten")+1), "网络监听", m.Meta["detail"]...) - } - return "" - // }}} - }}, - "dial": &ctx.Command{Name: "dial [address [security]]", Help: "建立连接", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) string { - switch len(arg) { // {{{ - case 0: - m.Travel(nil, func(m *ctx.Message) bool { - if tcp, ok := m.Target.Server.(*TCP); ok && tcp.Conn != nil { - m.Echo("%s %v<->%v\n", m.Target.Name, tcp.LocalAddr(), tcp.RemoteAddr()) - } - return true - }) - default: - m.Start(fmt.Sprintf("com%d", m.Capi("nclient")+1), "网络连接", m.Meta["detail"]...) - } - return "" - // }}} - }}, - "send": &ctx.Command{Name: "send message", Help: "发送消息", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) string { - if tcp, ok := m.Target.Server.(*TCP); ok && tcp.Conn != nil { // {{{ - tcp.Conn.Write([]byte(arg[0])) - } - return "" - // }}} - }}, - "recv": &ctx.Command{Name: "recv size", Help: "接收消息", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) string { - size, e := strconv.Atoi(arg[0]) - m.Assert(e) - if tcp, ok := m.Target.Server.(*TCP); ok && tcp.Conn != nil { // {{{ - buf := make([]byte, size) - tcp.Conn.Read(buf) - return string(buf) - } - return "" - // }}} - }}, - }, - Index: map[string]*ctx.Context{ - "void": &ctx.Context{ - Commands: map[string]*ctx.Command{ - "listen": &ctx.Command{}, - "dial": &ctx.Command{}, - }, - }, - }, -} - -var Pulse *ctx.Message - -func init() { - tcp := &TCP{} - tcp.Context = Index - ctx.Index.Register(Index, tcp) -} diff --git a/src/context/tcp/tcp_test.go b/src/context/tcp/tcp_test.go deleted file mode 100644 index 3695d9e3..00000000 --- a/src/context/tcp/tcp_test.go +++ /dev/null @@ -1,29 +0,0 @@ -package tcp - -import ( - "context" - "flag" - "testing" - "time" -) - -func TestOpen(t *testing.T) { - flag.Parse() - args := flag.Args() - if len(args) < 1 { - t.Fatal("usages: -args address") - } - - address := ":9393" - address = args[0] - - //mysql -u root -p; - //create database book; - //grant all on book.* to user identified by 'word' - - ctx.Start() - m := ctx.Pulse.Spawn(Index) - - m.Meta = nil - Index.Cmd(m, "listen", address) -} diff --git a/src/context/web/web.go b/src/context/web/web.go deleted file mode 100644 index 21de3270..00000000 --- a/src/context/web/web.go +++ /dev/null @@ -1,278 +0,0 @@ -package web // {{{ -// }}} -import ( // {{{ - "context" - - "html/template" - "net/http" - - "bufio" - "log" - "os" - "path" - "strings" -) - -// }}} - -type MUX interface { - Handle(string, http.Handler) - HandleFunc(string, func(http.ResponseWriter, *http.Request)) - Trans(*ctx.Message, string, func(*ctx.Message, *ctx.Context, string, ...string) string) -} - -type WEB struct { - *http.ServeMux - *http.Server - - *ctx.Message - *ctx.Context -} - -func (web *WEB) Trans(m *ctx.Message, key string, hand func(*ctx.Message, *ctx.Context, string, ...string) string) { // {{{ - web.HandleFunc(key, func(w http.ResponseWriter, r *http.Request) { - msg := m.Spawn(m.Target) - msg.Set("detail", key) - for k, v := range r.Form { - msg.Add("option", k) - msg.Meta[k] = v - } - for _, v := range r.Cookies() { - msg.Add("option", v.Name, v.Value) - } - - msg.Log("cmd", nil, "%s %v", key, msg.Meta["option"]) - msg.Put("option", "request", r) - msg.Put("option", "response", w) - - ret := hand(msg, msg.Target, key) - if ret != "" { - msg.Echo(ret) - } - - header := w.Header() - for _, k := range msg.Meta["append"] { - ce := &http.Cookie{Name: k, Value: msg.Get(k)} - header.Add("Set-Cookie", ce.String()) - } - for _, v := range msg.Meta["result"] { - w.Write([]byte(v)) - } - }) -} - -// }}} -func (web *WEB) ServeHTTP(w http.ResponseWriter, r *http.Request) { // {{{ - if web.Message != nil { - log.Println() - web.Log("cmd", nil, "%v %s %s", r.RemoteAddr, r.Method, r.URL) - defer log.Println() - - if web.Cap("logheaders") == "yes" { - for k, v := range r.Header { - log.Println(k+":", v[0]) - } - log.Println() - } - - r.ParseForm() - if len(r.PostForm) > 0 { - for k, v := range r.PostForm { - log.Printf("%s: %s", k, v[0]) - } - log.Println() - } - } - - web.ServeMux.ServeHTTP(w, r) - - if web.Message != nil { - if web.Cap("logheaders") == "yes" { - for k, v := range w.Header() { - log.Println(k+":", v[0]) - } - } - } -} - -// }}} - -func (web *WEB) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { // {{{ - c.Caches = map[string]*ctx.Cache{ - "directory": &ctx.Cache{Name: "directory", Value: "usr", Help: "服务目录"}, - } - c.Configs = map[string]*ctx.Config{} - - s := new(WEB) - s.Context = c - return s -} - -// }}} -func (web *WEB) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{ - if len(arg) > 0 { - m.Cap("directory", arg[0]) - } - - web.Caches["route"] = &ctx.Cache{Name: "route", Value: "/" + web.Context.Name + "/", Help: "请求路径"} - web.Caches["register"] = &ctx.Cache{Name: "已初始化(yes/no)", Value: "no", Help: "模块是否已注册"} - web.Caches["master"] = &ctx.Cache{Name: "master(yes/no)", Value: "no", Help: "日志输出请求头"} - - web.ServeMux = http.NewServeMux() - if mux, ok := m.Target.Server.(MUX); ok { - for k, x := range web.Commands { - if k[0] == '/' { - mux.Trans(m, k, x.Hand) - } - } - } - - return web -} - -// }}} -func (web *WEB) Start(m *ctx.Message, arg ...string) bool { // {{{ - if len(arg) > 0 { - m.Cap("directory", arg[0]) - } - - web.Message = m - m.Cap("master", "yes") - - m.Travel(m.Target, func(m *ctx.Message) bool { - if h, ok := m.Target.Server.(http.Handler); ok && m.Cap("register") == "no" { - m.Cap("register", "yes") - - p, i := m.Target, 0 - m.BackTrace(func(m *ctx.Message) bool { - p = m.Target - if i++; i == 2 { - return false - } - return true - }) - - if s, ok := p.Server.(MUX); ok { - m.Log("info", p, "route %s -> %s", m.Cap("route"), m.Target.Name) - s.Handle(m.Cap("route"), http.StripPrefix(path.Dir(m.Cap("route")), h)) - } - - if s, ok := m.Target.Server.(MUX); ok && m.Cap("directory") != "" { - m.Log("info", nil, "dir / -> [%s]", m.Cap("directory")) - s.Handle("/", http.FileServer(http.Dir(m.Cap("directory")))) - } - } - return true - }) - - web.Caches["address"] = &ctx.Cache{Name: "address", Value: ":9191", Help: "监听地址"} - web.Caches["protocol"] = &ctx.Cache{Name: "protocol", Value: "http", Help: "服务协议"} - if len(arg) > 1 { - m.Cap("address", arg[1]) - } - if len(arg) > 2 { - m.Cap("protocol", arg[2]) - } - - m.Cap("stream", m.Cap("address")) - m.Log("info", nil, "address [%s]", m.Cap("address")) - m.Log("info", nil, "protocol [%s]", m.Cap("protocol")) - web.Server = &http.Server{Addr: m.Cap("address"), Handler: web} - - web.Caches["logheaders"] = &ctx.Cache{Name: "日志输出报文头(yes/no)", Value: "yes", Help: "日志输出请求头"} - - if m.Cap("protocol") == "https" { - m.Log("info", nil, "key [%s]", m.Cap("key")) - m.Log("info", nil, "cert [%s]", m.Cap("cert")) - web.Server.ListenAndServeTLS(m.Cap("cert"), m.Cap("key")) - } else { - web.Server.ListenAndServe() - } - - return true -} - -// }}} -func (web *WEB) Close(m *ctx.Message, arg ...string) bool { // {{{ - return false -} - -// }}} - -var Index = &ctx.Context{Name: "web", Help: "网页服务", - Caches: map[string]*ctx.Cache{ - "directory": &ctx.Cache{Name: "directory", Value: "usr", Help: "服务目录"}, - }, - Configs: map[string]*ctx.Config{}, - Commands: map[string]*ctx.Command{ - "listen": &ctx.Command{Name: "listen [directory [address [protocol]]]", Help: "开启网页服务", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) string { - m.Meta["detail"] = arg // {{{ - m.Target.Start(m) - return "" - // }}} - }}, - "route": &ctx.Command{Name: "route [directory|template|script] route string", Help: "添加响应", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) string { - mux, ok := m.Target.Server.(MUX) // {{{ - m.Assert(ok, "模块类型错误") - m.Assert(len(arg) == 3, "缺少参数") - - switch arg[0] { - case "directory": - mux.Handle(arg[1], http.FileServer(http.Dir(arg[2]))) - case "template": - mux.Trans(m, arg[1], func(m *ctx.Message, c *ctx.Context, key string, a ...string) string { // {{{ - w := m.Data["response"].(http.ResponseWriter) - - if _, e := os.Stat(arg[2]); e == nil { - template.Must(template.ParseGlob(arg[2])).Execute(w, m) - } else { - template.Must(template.New("temp").Parse(arg[2])).Execute(w, m) - } - - return "" - }) - // }}} - case "script": - cli := m.Find("cli", true) // {{{ - lex := m.Find("lex", true) - mux.Trans(m, arg[1], func(m *ctx.Message, c *ctx.Context, key string, a ...string) string { - f, e := os.Open(arg[2]) - line, bio := "", bufio.NewReader(f) - - if e != nil { - line = arg[2] - } - - for { - if line = strings.TrimSpace(line); line != "" { - lex.Cmd("split", line, "void") - cli.Wait = make(chan bool) - cli.Cmd(lex.Meta["result"]...) - m.Meta["result"] = cli.Meta["result"] - } - - if line, e = bio.ReadString('\n'); e != nil { - break - } - } - - return "" - }) - // }}} - } - - return "" - // }}} - }}, - "/hi": &ctx.Command{Name: "/hi", Help: "添加响应", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) string { - m.Add("append", "hi", "hello") - return "hello" - }}, - }, -} - -func init() { - web := &WEB{} - web.Context = Index - ctx.Index.Register(Index, web) -}