初次提交
This commit is contained in:
@@ -0,0 +1,325 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash/crc32"
|
||||
"net"
|
||||
"rakshasa/common"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/luyu6056/ishell"
|
||||
)
|
||||
|
||||
var (
|
||||
// clientListenMap = make(map[uint32]*remoteListen)
|
||||
// connectMap = make(map[uint32]*rawConnect)
|
||||
)
|
||||
|
||||
type clientListen struct {
|
||||
id uint32
|
||||
localAddr string
|
||||
remoteAddr string
|
||||
server *node
|
||||
typ string
|
||||
openOption byte
|
||||
openMsg []byte //掉线重连会用到
|
||||
connMap sync.Map //clientListen关闭的时候关掉这里的id
|
||||
listen net.Listener
|
||||
result chan interface{}
|
||||
}
|
||||
|
||||
func StartRawBind(str string, dst []string) error {
|
||||
n, err := GetNodeFromAddrs(dst)
|
||||
if err != nil {
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
addrs, err := common.ResolveTCPAddr(str)
|
||||
if err != nil {
|
||||
|
||||
return err
|
||||
}
|
||||
if len(addrs) != 2 {
|
||||
return errors.New("参数错误,格式为ip:port,remote_ip:remote_port")
|
||||
}
|
||||
|
||||
l := &clientListen{
|
||||
id: common.GetID(),
|
||||
localAddr: addrs[0],
|
||||
remoteAddr: addrs[1],
|
||||
server: n,
|
||||
typ: "bind",
|
||||
result: make(chan interface{}),
|
||||
openOption: common.CMD_LISTEN,
|
||||
}
|
||||
l.openMsg = []byte(addrs[1])
|
||||
currentNode.listenMap.Store(l.id, l)
|
||||
n.Write(l.openOption, l.id, l.openMsg)
|
||||
select {
|
||||
case res := <-l.result:
|
||||
|
||||
if err, ok := res.(error); ok {
|
||||
l.Close(remoteClose)
|
||||
currentNode.listenMap.Delete(l.id)
|
||||
return err
|
||||
}
|
||||
case <-time.After(common.CMD_TIMEOUT):
|
||||
l.Close(remoteClose)
|
||||
currentNode.listenMap.Delete(l.id)
|
||||
return fmt.Errorf("listen %s fail time out", addrs[1])
|
||||
|
||||
}
|
||||
fmt.Println("bind 启动成功")
|
||||
//l := clientLock.Lock()
|
||||
|
||||
//clientListenMap[b.id] = b
|
||||
//l.Unlock()
|
||||
return nil
|
||||
}
|
||||
func StartRawConnect(str string, n *node) error {
|
||||
addrs, err := common.ResolveTCPAddr(str)
|
||||
if len(addrs) != 2 || err != nil {
|
||||
return errors.New("-connect参数错误,格式为ip:port,remote_ip:remote_port")
|
||||
}
|
||||
|
||||
addr1, _ := net.ResolveTCPAddr("tcp", addrs[1])
|
||||
listen, err := net.Listen("tcp", addrs[0])
|
||||
if err != nil {
|
||||
return errors.New("监听本地端口" + addrs[0] + "失败 " + err.Error())
|
||||
}
|
||||
|
||||
l := &clientListen{
|
||||
id: common.GetID(),
|
||||
localAddr: addrs[0],
|
||||
remoteAddr: addrs[1],
|
||||
listen: listen,
|
||||
server: n,
|
||||
typ: "connect",
|
||||
}
|
||||
currentNode.listenMap.Store(l.id, l)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
conn, err := listen.Accept()
|
||||
if err != nil {
|
||||
if err.(*net.OpError).Err == net.ErrClosed {
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
s := &clientConnect{
|
||||
conn: conn,
|
||||
server: n,
|
||||
}
|
||||
s.OnOpened()
|
||||
s.connect(common.RAW_TCP, addr1.IP.String(), uint16(addr1.Port))
|
||||
go rawHandleLocal(s)
|
||||
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
func (l *clientListen) Close(reason string) {
|
||||
l.connMap.Range(func(key, value interface{}) bool {
|
||||
value.(*clientConnect).Close(reason)
|
||||
l.connMap.Delete(key)
|
||||
return true
|
||||
})
|
||||
l.server.listenMap.Delete(l.id)
|
||||
if l.listen != nil {
|
||||
l.listen.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func rawHandleLocal(s *clientConnect) {
|
||||
buf := make([]byte, common.MAX_PLAINTEXT)
|
||||
|
||||
for {
|
||||
n, err := s.conn.Read(buf[8:])
|
||||
if err != nil {
|
||||
|
||||
s.Close(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var new_size int64
|
||||
if new_size = int64(common.INIT_WINDOWS_SIZE) - s.windowsSize; new_size > 0 { //扩大窗口
|
||||
atomic.AddInt64(&s.windowsSize, new_size)
|
||||
|
||||
} else {
|
||||
new_size = 0
|
||||
}
|
||||
buf[0] = byte(new_size)
|
||||
buf[1] = byte(new_size >> 8)
|
||||
buf[2] = byte(new_size >> 16)
|
||||
buf[3] = byte(new_size >> 24)
|
||||
buf[4] = byte(new_size >> 32)
|
||||
buf[5] = byte(new_size >> 40)
|
||||
buf[6] = byte(new_size >> 48)
|
||||
buf[7] = byte(new_size >> 56)
|
||||
if common.Debug {
|
||||
fmt.Println("发送", crc32.ChecksumIEEE(buf[8:8+n]), n)
|
||||
}
|
||||
data := make([]byte, 8+n)
|
||||
copy(data, buf)
|
||||
s.server.Write(common.CMD_CONN_MSG, s.id, buf)
|
||||
}
|
||||
}
|
||||
func init() {
|
||||
bindshell := cliInit()
|
||||
bindshell.SetPrompt("rakshasa\\bind>")
|
||||
bindshell.AddCmd(&ishell.Cmd{
|
||||
Name: "list",
|
||||
Help: "列出当前连接的ID和其他信息",
|
||||
Func: func(c *ishell.Context) {
|
||||
var list []*clientListen
|
||||
currentNode.listenMap.Range(func(key, value interface{}) bool {
|
||||
if v, ok := value.(*clientListen); ok {
|
||||
if v.typ == "bind" {
|
||||
list = append(list, v)
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
orderClientListen(list)
|
||||
fmt.Println("当前连接数量:", len(list))
|
||||
for _, v := range list {
|
||||
fmt.Println("ID", v.id, "本地端口", v.localAddr, "远程端口", v.remoteAddr, "服务器uuid", v.server.uuid)
|
||||
}
|
||||
},
|
||||
})
|
||||
bindshell.AddCmd(&ishell.Cmd{
|
||||
Name: "new-bind",
|
||||
Help: "新建一个本地bind,使用方法 new-bind ip:port,remote_ip:remote_port 目标服务器 如 new-bind 192.168.1.180:8808,0.0.0.0:8808 192.168.1.2:1081",
|
||||
Func: func(c *ishell.Context) {
|
||||
if len(c.Args) != 2 {
|
||||
c.Println("参数错误")
|
||||
return
|
||||
}
|
||||
|
||||
if err := StartRawBind(c.Args[0], strings.Split(c.Args[1], ",")); err != nil {
|
||||
c.Println("启动bind失败", err)
|
||||
|
||||
}
|
||||
},
|
||||
})
|
||||
bindshell.AddCmd(&ishell.Cmd{
|
||||
Name: "close",
|
||||
Help: "关闭一个bind连接,使用方法 close ID",
|
||||
Func: func(c *ishell.Context) {
|
||||
if len(c.Args) != 1 {
|
||||
c.Println("参数错误,例子 close 1")
|
||||
return
|
||||
}
|
||||
id, _ := strconv.Atoi(c.Args[0])
|
||||
var l *clientListen
|
||||
if value, ok := currentNode.listenMap.Load(uint32(id)); ok {
|
||||
if v, ok := value.(*clientListen); ok && v.typ == "bind" {
|
||||
l = v
|
||||
}
|
||||
|
||||
}
|
||||
if l == nil {
|
||||
c.Println("没有找到ID为", id, "的连接")
|
||||
} else {
|
||||
l.Close("命令行关闭")
|
||||
l.server.Write(common.CMD_DELETE_LISTEN, l.id, nil)
|
||||
currentNode.listenMap.Delete(uint32(id))
|
||||
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
rootCli.AddCmd(&ishell.Cmd{
|
||||
Name: "bind",
|
||||
Help: "进入bind功能",
|
||||
Func: func(c *ishell.Context) {
|
||||
bindshell.Run()
|
||||
},
|
||||
})
|
||||
connectshell := ishell.New()
|
||||
connectshell.SetPrompt("rakshasa\\connect>")
|
||||
connectshell.AddCmd(&ishell.Cmd{
|
||||
Name: "list",
|
||||
Help: "列出当前连接的ID和其他信息",
|
||||
Func: func(c *ishell.Context) {
|
||||
var list []*clientListen
|
||||
currentNode.listenMap.Range(func(key, value interface{}) bool {
|
||||
if v, ok := value.(*clientListen); ok {
|
||||
if v.typ == "connect" {
|
||||
list = append(list, v)
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
orderClientListen(list)
|
||||
fmt.Println("当前连接数量:", len(list))
|
||||
for _, v := range list {
|
||||
fmt.Println("ID", v.id, "本地端口", v.localAddr, "远程端口", v.remoteAddr, "服务器uuid", v.server.uuid)
|
||||
}
|
||||
|
||||
},
|
||||
})
|
||||
connectshell.AddCmd(&ishell.Cmd{
|
||||
Name: "new-connect",
|
||||
Help: "新建一个本地connect,使用方法 new-connect ip:port,remote_ip:remote_port 目标服务器 如 new-connect 0.0.0.0:88,192.168.1.180:8808 192.168.1.2:1081",
|
||||
Func: func(c *ishell.Context) {
|
||||
if len(c.Args) != 2 {
|
||||
c.Println("参数错误")
|
||||
return
|
||||
}
|
||||
|
||||
n, err := GetNodeFromAddrs(strings.Split(c.Args[1], ","))
|
||||
if err != nil {
|
||||
c.Println("connect连接", c.Args[1], "失败", err)
|
||||
return
|
||||
}
|
||||
if err = StartRawConnect(c.Args[0], n); err != nil {
|
||||
c.Println(err)
|
||||
return
|
||||
}
|
||||
c.Println("connect连接", c.Args[1], "成功")
|
||||
},
|
||||
})
|
||||
connectshell.AddCmd(&ishell.Cmd{
|
||||
Name: "close",
|
||||
Help: "关闭一个connect连接,使用方法 close ID",
|
||||
Func: func(c *ishell.Context) {
|
||||
if len(c.Args) != 1 {
|
||||
c.Println("参数错误,例子 close 1")
|
||||
return
|
||||
}
|
||||
|
||||
id, _ := strconv.Atoi(c.Args[0])
|
||||
var l *clientListen
|
||||
if value, ok := currentNode.listenMap.Load(uint32(id)); ok {
|
||||
if v, ok := value.(*clientListen); ok && v.typ == "connect" {
|
||||
l = v
|
||||
}
|
||||
}
|
||||
if l == nil {
|
||||
c.Println("没有找到ID为", id, "的连接")
|
||||
} else {
|
||||
l.Close("命令行关闭")
|
||||
l.server.Write(common.CMD_DELETE_LISTEN, l.id, nil)
|
||||
currentNode.listenMap.Delete(uint32(id))
|
||||
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
rootCli.AddCmd(&ishell.Cmd{
|
||||
Name: "connect",
|
||||
Help: "进入connect功能",
|
||||
Func: func(c *ishell.Context) {
|
||||
connectshell.Run()
|
||||
},
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user