func (c *Client) Connect() error { conn, err := net.DialTimeout(c.Broker.Type, string(c.Broker.Addr+":"+strconv.Itoa(c.Broker.Port)), c.Broker.TimeOut) if err != nil { log.Println("Error while TCP connection.") log.Println(err) return err } c.Con = conn //creating connect message : start. m := (Message.NewControlPacket(Message.Connect)).(*Message.ConnectPacket) m.ProtocolName = c.ProtocolName m.ProtocolVersion = byte(c.ProtocolVersion) m.ClientIdentifier = c.Id.(string) m.CleanSession = c.CleanSession m.WillFlag = c.WillFlag m.WillRetain = c.WillRetain if c.WillFlag { m.WillQos = c.WillQos m.WillTopic = c.WillTopic m.WillMessage = c.WillPayload } if c.UserName != "" { m.UsernameFlag = true m.Username = c.UserName //mustn't have password without user as well if c.Password != "" { m.PasswordFlag = true m.Password = []byte(c.Password) } } m.KeepaliveTimer = uint16(c.KeepAlive.Seconds()) // end. if err != m.Write(c.Con) { log.Println("Error while writing connect package.") log.Println(err) } //This is the response packet came from server. ca, err := Message.ReadPacket(c.Con) //read packet will validate packet and type. if err != nil { log.Println("Error in receiving.") log.Println(err.Error()) return err } if ca == nil { return errors.New("Received Nil Packet") } msg, ok := ca.(*Message.ConnackPacket) if !ok { return errors.New("Received wrong packet.") } if msg.ReturnCode != Message.Accepted { c.Con.Close() c.Con = nil return errors.New("Wrong Response code.") } log.Println("Connected...!") //connect is done. // INIT SETUP : START. c.WriteChan = make(chan *PacketAndToken, 100) c.ReadChan = make(chan *Message.ControlPacket, 100) c.InComingPubChan = make(chan *Message.PublishPacket, 100) c.stop = make(chan struct{}) c.setConnected(true) c.HeartBeat.update() // for keep alive. c.MessageRouter.matchAndDispatch(c.InComingPubChan, c.Order, c) //start contractors. go writeContractor(c) go readContractor(c) if c.KeepAlive > 0 { // if 0 then alive forever. else we need to do some work. go keepalive(c) } //INIT SETUP : DONE return nil }
func readContractor(c *Client) { c.Workers.Add(1) // tell client that i am working in your group. defer c.Workers.Done() // singnal client that i am done. var err error var msg Message.ControlPacket log.Println("Reader Ready..!") for { select { case <-c.stop: return default: if msg, err = Message.ReadPacket(c.Con); err != nil { log.Println("Error in read packet.") log.Fatalln(err.Error()) return } switch msg.(type) { case *Message.PingrespPacket: log.Println("Received PingResp") case *Message.SubackPacket: log.Println("Received SUBACKS") sa := msg.(*Message.SubackPacket) token := c.getToken(sa.MessageID).(*SubscribeToken) //these are the granted Qos From server. // for i, qos := range sa.GrantedQoss { // token.subResult[token.subs[i]] = qos // } token.flowComplete() // finish c.freeID(sa.MessageID) // free ID. case *Message.UnsubackPacket: ua := msg.(*Message.UnsubackPacket) token := c.getToken(ua.MessageID).(*UnsubscribeToken) token.flowComplete() c.freeID(ua.MessageID) case *Message.PublishPacket: // calls when server publish to this client. pp := msg.(*Message.PublishPacket) switch pp.Qos { case 2: c.InComingPubChan <- pp pr := Message.NewControlPacket(Message.Pubrec).(*Message.PubrecPacket) pr.MessageID = pp.MessageID c.WriteChan <- &PacketAndToken{p: pr, t: nil} case 1: c.InComingPubChan <- pp pa := Message.NewControlPacket(Message.Puback).(*Message.PubackPacket) pa.MessageID = pp.MessageID c.WriteChan <- &PacketAndToken{p: pa, t: nil} case 0: c.InComingPubChan <- pp } case *Message.PubackPacket: pa := msg.(*Message.PubackPacket) c.getToken(pa.MessageID).flowComplete() c.freeID(pa.MessageID) case *Message.PubrecPacket: prec := msg.(*Message.PubrecPacket) //log.Println("Received PUBREC") prel := Message.NewControlPacket(Message.Pubrel).(*Message.PubrelPacket) prel.MessageID = prec.MessageID select { case c.WriteChan <- &PacketAndToken{p: prel, t: nil}: case <-time.After(time.Second): } case *Message.PubrelPacket: pr := msg.(*Message.PubrelPacket) pc := Message.NewControlPacket(Message.Pubcomp).(*Message.PubcompPacket) pc.MessageID = pr.MessageID select { case c.WriteChan <- &PacketAndToken{p: pc, t: nil}: case <-time.After(time.Second): } case *Message.PubcompPacket: //log.Println("Received PUBCOMP") pc := msg.(*Message.PubcompPacket) c.getToken(pc.MessageID).flowComplete() c.freeID(pc.MessageID) } } } }