code: func (c *Client) PublishMessage(msg *packet.Message) (GenericFuture, error) {
  	c.mutex.Lock()
  	defer c.mutex.Unlock()
  
  	// check if connected
  	if atomic.LoadUint32(&c.state) != clientConnected {
  		return nil, ErrClientNotConnected
  	}
  
  	// allocate publish packet
  	publish := packet.NewPublish()
  	publish.Message = *msg
  
  	// set packet id
  	if msg.QOS > 0 {
  		publish.ID = c.Session.NextID()
  	}
  
  	// create future
  	publishFuture := future.New()
  
  	// store future
  	c.futureStore.Put(publish.ID, publishFuture)
  
  	// store packet if at least qos 1
  	if msg.QOS > 0 {
  		err := c.Session.SavePacket(session.Outgoing, publish)
  		if err != nil {
  			return nil, c.cleanup(err, true, false)
  		}
  	}
  
  	// send packet
  	err := c.send(publish, true)
  	if err != nil {
  		return nil, c.cleanup(err, false, false)
  	}
  
  	// complete and remove qos 0 future
  	if msg.QOS == 0 {
  		publishFuture.Complete()
  		c.futureStore.Delete(publish.ID)
  	}
  
  	return publishFuture, nil
  }
docs: // PublishMessage will send a Publish containing the passed message. It will
  // return a PublishFuture that gets completed once the quality of service flow
  // has been completed.