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 }