This commit is contained in:
MQjehovah 2024-01-22 09:52:50 +08:00
parent 8abb8c1f2f
commit 3b95cf5645
4 changed files with 88 additions and 15 deletions

16
README.md Normal file
View File

@ -0,0 +1,16 @@
```mermaid
sequenceDiagram
participant Device
participant Broker
participant Web
Device->>Broker: 建立TCP连接
Broker->>Broker: 5s未注册主动断开
Device->>Broker: 注册报文
Broker->>Device: 注册回复
Device->>Broker: 心跳报文
Broker->>Device: 心跳报文
Web->>Broker: 创建Session
Broker->>Device: 创建Session
```

View File

@ -19,8 +19,13 @@ import (
// 帧类型 1字节 // 帧类型 1字节
// 帧长度 4字节 // 帧长度 4字节
// 帧数据 帧长度大小的数据
// 心跳包 02 00 00 00 00
// 注册包 01 00 00 00 00 device_id 00 token 00 desc
// 创建SESSION 03 00 00 00
type Config struct { type Config struct {
DeviceId string
AddrServer string AddrServer string
} }
@ -28,8 +33,8 @@ const HEART_BEAT_INTERVAL = time.Second * 5 // 心跳超时时间
const ( const (
MSG_TYPE_UNKOWNM = iota MSG_TYPE_UNKOWNM = iota
MSG_TYPE_HEARTBEAT
MSG_TYPE_REGISTER MSG_TYPE_REGISTER
MSG_TYPE_HEARTBEAT
MSG_TYPE_SESSION_CREATE MSG_TYPE_SESSION_CREATE
MSG_TYPE_SESSION_DATA MSG_TYPE_SESSION_DATA
MSG_TYPE_SESSION_DESTORY MSG_TYPE_SESSION_DESTORY
@ -37,6 +42,12 @@ const (
MSG_TYPE_MAX MSG_TYPE_MAX
) )
type Session struct {
sessionId string
inBound *os.File
dev *Device
}
type Device struct { type Device struct {
id string id string
category string category string
@ -47,6 +58,7 @@ type Device struct {
registered bool registered bool
closed uint32 closed uint32
send chan []byte // Buffered channel of outbound messages. send chan []byte // Buffered channel of outbound messages.
sessions map[string]*Session
} }
func main() { func main() {
@ -108,7 +120,8 @@ func main() {
func runClient(c *cli.Context) { func runClient(c *cli.Context) {
cfg := &Config{ cfg := &Config{
AddrServer: "localhost:9011", DeviceId: "jmq",
AddrServer: "dev.xzrobot.com:9011",
} }
tcpConn, err := createTcpConn(cfg.AddrServer) tcpConn, err := createTcpConn(cfg.AddrServer)
@ -119,7 +132,7 @@ func runClient(c *cli.Context) {
fmt.Println(tcpConn.LocalAddr().String() + " : Client Connected") fmt.Println(tcpConn.LocalAddr().String() + " : Client Connected")
dev := &Device{ dev := &Device{
id: "1234567890", id: cfg.DeviceId,
category: "device", category: "device",
conn: tcpConn, conn: tcpConn,
create_time: time.Now().Unix(), create_time: time.Now().Unix(),
@ -127,35 +140,35 @@ func runClient(c *cli.Context) {
registered: false, registered: false,
closed: 0, closed: 0,
send: make(chan []byte, 100), send: make(chan []byte, 100),
sessions: make(map[string]*Session),
} }
go dev.readLoop() go dev.readLoop()
go dev.writeLoop()
//registe //registe
s := make([][]byte, 3) s := make([][]byte, 3)
s[0] = []byte("deviceid") //id s[0] = []byte("jmq") //id
s[1] = []byte(dev.id) //desc s[1] = []byte("desc") //desc
s[2] = []byte(dev.id) //token s[2] = []byte("token") //token
dev.WriteMsg(MSG_TYPE_REGISTER, bytes.Join(s, []byte{0})) dev.WriteMsg(MSG_TYPE_REGISTER, bytes.Join(s, []byte{0}))
go dev.writeLoop()
select {} select {}
} }
func (dev *Device) WriteMsg(typ int, data []byte) { func (dev *Device) WriteMsg(typ int, data []byte) {
b := []byte{byte(typ), 0, 0, 0, 0} b := []byte{byte(typ), 0, 0, 0, 0}
binary.BigEndian.PutUint32(b[1:], uint32(len(data))) binary.BigEndian.PutUint32(b[1:], uint32(len(data)))
dev.send <- append(b, data...) dev.send <- append(b, data...)
} }
func (dev *Device) readLoop() { func (dev *Device) readLoop() {
defer dev.conn.Close() defer dev.conn.Close()
defer log.Debug().Msgf("dev readLoop finished")
reader := bufio.NewReader(dev.conn) reader := bufio.NewReader(dev.conn)
for { for {
b, err := reader.Peek(5) b, err := reader.Peek(3)
if err != nil { if err != nil {
if err != io.EOF && !strings.Contains(err.Error(), "use of closed network connection") { if err != io.EOF && !strings.Contains(err.Error(), "use of closed network connection") {
log.Error().Msg(err.Error()) log.Error().Msg(err.Error())
@ -163,7 +176,7 @@ func (dev *Device) readLoop() {
return return
} }
reader.Discard(5) reader.Discard(3)
msg_type := b[0] msg_type := b[0]
@ -172,7 +185,7 @@ func (dev *Device) readLoop() {
return return
} }
msg_length := binary.BigEndian.Uint32(b[1:]) msg_length := binary.BigEndian.Uint16(b[1:])
data := make([]byte, msg_length) data := make([]byte, msg_length)
_, err = io.ReadFull(reader, data) _, err = io.ReadFull(reader, data)
if err != nil { if err != nil {
@ -184,11 +197,50 @@ func (dev *Device) readLoop() {
switch msg_type { switch msg_type {
case MSG_TYPE_HEARTBEAT: case MSG_TYPE_HEARTBEAT:
// log.Info().Msgf("Receive Heartbeat Time: %d", time.Now().Unix()) log.Info().Msgf("Receive Heartbeat Time: %d", time.Now().Unix())
case MSG_TYPE_REGISTER: case MSG_TYPE_REGISTER:
dev.registered = true dev.registered = true
log.Info().Msgf("Device Registry Success") log.Info().Msgf("Device Registry Success")
case MSG_TYPE_SESSION_CREATE:
sessionId := string(data[:32])
cmd := exec.Command("bash")
ff, err := pty.Start(cmd)
if err != nil {
fmt.Println("Create Pty Error! " + err.Error())
return
}
s := &Session{
sessionId: sessionId,
inBound: nil,
dev: dev,
}
dev.sessions[sessionId] = s
go func(s *Session) {
defer ff.Close()
reader := bufio.NewReader(ff)
for {
buffer := []byte{}
len, err := reader.Read(buffer)
if err != nil {
log.Error().Msg(err.Error())
return
}
dev.WriteMsg(MSG_TYPE_SESSION_DATA, append([]byte(s.sessionId), buffer[:len]...))
}
}(s)
case MSG_TYPE_SESSION_DATA:
sessionId := string(data[:32])
if session, ok := dev.sessions[sessionId]; ok {
session.dev.WriteMsg(MSG_TYPE_SESSION_DATA, data)
// session.inBound.Write(data[32:])
return
}
case MSG_TYPE_TUNNEL_CREATE: case MSG_TYPE_TUNNEL_CREATE:
log.Info().Msgf("Receive Tunnel Create") log.Info().Msgf("Receive Tunnel Create")
cmd := exec.Command("bash") cmd := exec.Command("bash")
@ -228,6 +280,7 @@ func (dev *Device) readLoop() {
log.Error().Msgf("invalid msg type: %d", msg_type) log.Error().Msgf("invalid msg type: %d", msg_type)
} }
} }
} }
func (dev *Device) writeLoop() { func (dev *Device) writeLoop() {

View File

@ -5,6 +5,9 @@
}, },
{ {
"path": "./server" "path": "./server"
},
{
"path": "."
} }
] ]
} }

View File

@ -25,8 +25,8 @@ const HEART_BEAT_INTERVAL = time.Second * 5 // 心跳超时时间
const ( const (
MSG_TYPE_UNKOWNM = iota MSG_TYPE_UNKOWNM = iota
MSG_TYPE_HEARTBEAT
MSG_TYPE_REGISTER MSG_TYPE_REGISTER
MSG_TYPE_HEARTBEAT
MSG_TYPE_SESSION_CREATE MSG_TYPE_SESSION_CREATE
MSG_TYPE_SESSION_DATA MSG_TYPE_SESSION_DATA
MSG_TYPE_SESSION_DESTORY MSG_TYPE_SESSION_DESTORY
@ -149,9 +149,10 @@ func (dev *Device) readLoop() {
return return
} }
if !parseDeviceInfo(dev, data) { if !parseDeviceInfo(dev, data) {
log.Error().Msg("parseDeviceInfo Failed")
return return
} }
dev.WriteMsg(MSG_TYPE_TUNNEL_CREATE, []byte{}) // dev.WriteMsg(MSG_TYPE_TUNNEL_CREATE, []byte{})
dev.br.register <- dev dev.br.register <- dev
case MSG_TYPE_SESSION_CREATE: case MSG_TYPE_SESSION_CREATE: