maeqtt/session/connection.go

112 lines
2.5 KiB
Go

package session
import (
"bufio"
"errors"
"io"
"log"
"time"
"badat.dev/maeqtt/v2/mqtt/packets"
)
type Connection struct {
MaxPacketSize *uint32
RecvMax uint16
TopicAliasMax uint16
WantsRespInf bool
WantsProblemInf bool
Will packets.Will
KeepAliveInterval time.Duration
keepAliveTicker time.Ticker
PacketChannel chan packets.ClientPacket
ClientDisconnectedChan chan bool
rw io.ReadWriteCloser
}
func (c *Connection) resetKeepAlive() {
if c.KeepAliveInterval != 0 {
panic("TODO")
// TODO IMPLEMENT THIS
//s.keepAliveTicker.Reset(s.KeepAliveInterval)
}
}
func (c *Connection) readPacket() (*packets.ClientPacket, error) {
return packets.ReadPacket(bufio.NewReader(c.rw))
}
func (c *Connection) sendPacket(p packets.ServerPacket) error {
c.resetKeepAlive()
return p.Write(c.rw)
}
func (c *Connection) close() error {
close(c.PacketChannel)
return c.rw.Close()
}
func (c *Connection) PacketReadLoop() {
for {
pack, err := c.readPacket()
if err != nil {
c.ClientDisconnectedChan <- true
c.close()
} else {
c.PacketChannel <- *pack
}
}
}
var FirstPackNotConnect error = errors.New("Failed to connect, first packet is not connect")
func NewConnection(rw io.ReadWriteCloser) (ConnectionRequest, error) {
connReq := ConnectionRequest{}
conn := Connection{}
connReq.Connection = &conn
conn.rw = rw
packet, err := conn.readPacket()
conPack, isConn := (*packet).(packets.ConnectPacket)
if !isConn {
log.Println("Didn't receive a connect packet")
err := packets.DisconnectPacket{
ReasonCode: packets.DisconnectReasonCodeProtocolError,
}.Write(rw)
if err != nil {
log.Println("Failed to disconnect after not receiving a connect packet", err)
}
return connReq, FirstPackNotConnect
}
connReq.ConnectPakcet = conPack
if conPack.Properties.ReceiveMaximum.Value != nil {
conn.RecvMax = *conPack.Properties.ReceiveMaximum.Value
} else {
conn.RecvMax = 65535
}
conn.MaxPacketSize = conPack.Properties.MaximumPacketSize.Value
if conPack.Properties.TopicAliasMaximum.Value != nil {
conn.TopicAliasMax = *conPack.Properties.TopicAliasMaximum.Value
} else {
conn.TopicAliasMax = 0
}
if conPack.Properties.RequestProblemInformation.Value != nil {
conn.WantsRespInf = *conPack.Properties.RequestProblemInformation.Value != 0
} else {
conn.WantsRespInf = false
}
conn.KeepAliveInterval = time.Duration(conPack.KeepAliveInterval) * time.Second
conn.PacketChannel = make(chan packets.ClientPacket, 1)
return connReq, err
}