示例#1
0
func (c *Client) Subscribe(topic string, qos byte, callback MessageHandler) Token {

	token := newToken(Message.Subscribe).(*SubscribeToken)

	if !c.IsConnected() {
		token.err = errors.New("Not Connected.")
		token.flowComplete()
		return token
	}

	sub := Message.NewControlPacket(Message.Subscribe).(*Message.SubscribePacket)
	if err := validateTopicAndQos(topic, qos); err != nil {
		token.err = err
		token.flowComplete()
		return token
	}

	sub.Topics = append(sub.Topics, topic)
	sub.Qoss = append(sub.Qoss, qos)
	if sub.Qos != 0 {
		sub.MessageID = c.getID(token)
	}

	if callback != nil {
		c.MessageRouter.addRoute(topic, callback)
	}

	c.WriteChan <- &PacketAndToken{p: sub, t: token}
	return token

}
示例#2
0
// to publish message , we need topic to publish to ,
//QoS for this message , Is this message to be Retained OR not and message body.
func (c *Client) Publish(topic string, qos byte, retained bool, payload interface{}) Token {

	token := newToken(Message.Publish).(*PublishToken)

	if !c.IsConnected() {
		token.err = errors.New("Not Connected.")
		token.flowComplete()
		return token
	}

	pub := Message.NewControlPacket(Message.Publish).(*Message.PublishPacket)
	pub.Qos = qos
	pub.TopicName = topic
	pub.Retain = retained
	pub.Dup = false
	if pub.Qos != 0 {
		pub.MessageID = c.getID(token)
	}

	//check for the type of payload.
	switch payload.(type) {
	case string:
		pub.Payload = []byte(payload.(string))
	case []byte:
		pub.Payload = payload.([]byte)
	default:
		token.err = errors.New("Unknown payload type")
		token.flowComplete()
		return token
	}

	c.WriteChan <- &PacketAndToken{p: pub, t: token}
	return token
}
示例#3
0
func keepalive(c *Client) {
	c.Workers.Add(1)       // adding as worker.
	defer c.Workers.Done() // i am done client. you can do whatever you want.
	for {
		select {
		case <-c.stop:
			return
		default:
			last := uint(time.Since(c.HeartBeat.get()).Seconds())
			if last > uint(c.KeepAlive.Seconds()) {
				token := newToken(Message.Pingreq)
				ping := Message.NewControlPacket(Message.Pingreq).(*Message.PingreqPacket)
				c.WriteChan <- &PacketAndToken{p: ping, t: token}
				token.Wait()
			}
			time.Sleep(1 * time.Second)
		}
	}
}
示例#4
0
func (c *Client) Disconnect() {

	token := newToken(Message.Disconnect).(*DisconnectToken)

	if !c.IsConnected() {
		log.Println("Already Disconnected.")
	}

	disPacket := Message.NewControlPacket(Message.Disconnect).(*Message.DisconnectPacket)

	c.WriteChan <- &PacketAndToken{p: disPacket, t: token}
	token.Wait()

	c.setConnected(false)
	close(c.stop) // this will signal all the go routines to finish what they are doing.

	c.disconnect()

}
示例#5
0
func (c *Client) UnSubscribe(topics ...string) Token {

	token := newToken(Message.Unsubscribe).(*UnsubscribeToken)

	if !c.IsConnected() {
		token.err = errors.New("Not Connected.")
		token.flowComplete()
		return token
	}

	unsub := Message.NewControlPacket(Message.Unsubscribe).(*Message.UnsubscribePacket)
	unsub.Topics = make([]string, len(topics))
	if unsub.Qos != 0 {
		unsub.MessageID = c.getID(token)
	}
	copy(unsub.Topics, topics)

	c.WriteChan <- &PacketAndToken{p: unsub, t: token}

	for _, topic := range topics {
		c.MessageRouter.deleteRoute(topic)
	}
	return token
}
示例#6
0
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
}
示例#7
0
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)
			}
		}
	}
}