Exemple #1
0
static int mqttClient_processPublish(mqttClient_t* clientData)
{
  MQTTString topicName;
  mqttClient_msg_t msg;
  int len = 0;
  int32_t rc = LE_OK;

  LE_DEBUG("---> PUBLISH");
  LE_ASSERT(clientData);

  if (MQTTDeserialize_publish((unsigned char*)&msg.dup, (int*)&msg.qos, (unsigned char*)&msg.retained, (unsigned short*)&msg.id, &topicName,
          (unsigned char**)&msg.payload, (int*)&msg.payloadLen, clientData->session.rx.buf, sizeof(clientData->session.rx.buf)) != 1)
  {
    LE_ERROR("MQTTDeserialize_publish() failed");
    rc = LE_BAD_PARAMETER;
    goto cleanup;
  }

  if (msg.qos != MQTT_CLIENT_QOS0)
  {
    if (msg.qos == MQTT_CLIENT_QOS1)
      len = MQTTSerialize_ack(clientData->session.tx.buf, sizeof(clientData->session.tx.buf), PUBACK, 0, msg.id);
    else if (msg.qos == MQTT_CLIENT_QOS2)
      len = MQTTSerialize_ack(clientData->session.tx.buf, sizeof(clientData->session.tx.buf), PUBREC, 0, msg.id);

    if (len <= 0)
    {
      LE_ERROR("MQTTSerialize_ack() failed(%d)", len);
      rc = LE_BAD_PARAMETER;
      goto cleanup;
    }
        
    LE_DEBUG("<--- PUBACK");
    rc = mqttClient_write(clientData, len);
    if (rc)
    {
      LE_ERROR("mqttClient_write() failed(%d)", rc);
      goto cleanup;
    }
  }

  rc = mqttClient_deliverMsg(clientData, &topicName, &msg);
  if (rc)
  {
    LE_ERROR("mqttClient_deliverMsg() failed(%d)", rc);
    goto cleanup;
  }

cleanup:
  return rc;
}
Exemple #2
0
static int mqttClient_processPubRec(mqttClient_t* clientData)
{
  int32_t rc = LE_OK;
  uint16_t packetId;
  uint8_t dup;
  uint8_t type;

  LE_DEBUG("---> PUBREC");
  LE_ASSERT(clientData);

  if (MQTTDeserialize_ack(&type, &dup, &packetId, clientData->session.rx.buf, sizeof(clientData->session.rx.buf)) != 1)
  {
    LE_ERROR("MQTTDeserialize_ack() failed");
    rc = LE_BAD_PARAMETER;
    goto cleanup;
  }
  else if (clientData->session.nextPacketId != packetId)
  {
    LE_ERROR("invalid packet ID(%u != %u)", clientData->session.nextPacketId, packetId);
    rc = LE_BAD_PARAMETER;
    goto cleanup;
  }

  int len = MQTTSerialize_ack(clientData->session.tx.buf, sizeof(clientData->session.tx.buf), PUBREL, 0, packetId);
  if (len <= 0)
  {
    LE_ERROR("MQTTSerialize_ack() failed(%d)", len);
    rc = LE_BAD_PARAMETER;
    goto cleanup;
  }

  LE_DEBUG("<--- PUBREL");
  rc = mqttClient_write(clientData, len);
  if (rc) 
  {
    LE_ERROR("mqttClient_write() failed(%d)", rc);
    goto cleanup;
  }

cleanup:
  return rc;
}
/**
  * Serializes a pubrel packet into the supplied buffer.
  * @param buf the buffer into which the packet will be serialized
  * @param buflen the length in bytes of the supplied buffer
  * @param packetid integer - the MQTT packet identifier
  * @return serialized length, or error if 0
  */
int MQTTSerialize_pubcomp(unsigned char* buf, int buflen, uint64_t packetid)
{
	return MQTTSerialize_ack(buf, buflen, PUBCOMP, 0, packetid);
}
/**
  * Serializes a pubrel packet into the supplied buffer.
  * @param buf the buffer into which the packet will be serialized
  * @param buflen the length in bytes of the supplied buffer
  * @param dup integer - the MQTT dup flag
  * @param packetid integer - the MQTT packet identifier
  * @return serialized length, or error if 0
  */
int MQTTSerialize_pubrel(unsigned char* buf, int buflen, unsigned char dup, uint64_t packetid)
{
	return MQTTSerialize_ack(buf, buflen, PUBREL, dup, packetid);
}
int cycle(Client* c, Timer* timer)
{
    // read the socket, see what work is due
    unsigned short packet_type = readPacket(c, timer);
    
    int len = 0,
        rc = SUCCESS;

    switch (packet_type)
    {
        case CONNACK:
        case PUBACK:
        case SUBACK:
            break;
        case PUBLISH:
        {
            MQTTString topicName;
            MQTTMessage msg;
            if (MQTTDeserialize_publish((unsigned char*)&msg.dup, (int*)&msg.qos, (unsigned char*)&msg.retained, (unsigned short*)&msg.id, &topicName,
               (unsigned char**)&msg.payload, (int*)&msg.payloadlen, c->readbuf, c->readbuf_size) != 1)
                goto exit;
            deliverMessage(c, &topicName, &msg);
            if (msg.qos != QOS0)
            {
                if (msg.qos == QOS1)
                    len = MQTTSerialize_ack(c->buf, c->buf_size, PUBACK, 0, msg.id);
                else if (msg.qos == QOS2)
                    len = MQTTSerialize_ack(c->buf, c->buf_size, PUBREC, 0, msg.id);
                if (len <= 0)
                    rc = FAILURE;
                   else
                       rc = sendPacket(c, len, timer);
                if (rc == FAILURE)
                    goto exit; // there was a problem
            }
            break;
        }
        case PUBREC:
        {
            unsigned short mypacketid;
            unsigned char dup, type;
            if (MQTTDeserialize_ack(&type, &dup, &mypacketid, c->readbuf, c->readbuf_size) != 1)
                rc = FAILURE;
            else if ((len = MQTTSerialize_ack(c->buf, c->buf_size, PUBREL, 0, mypacketid)) <= 0)
                rc = FAILURE;
            else if ((rc = sendPacket(c, len, timer)) != SUCCESS) // send the PUBREL packet
                rc = FAILURE; // there was a problem
            if (rc == FAILURE)
                goto exit; // there was a problem
            break;
        }
        case PUBCOMP:
            break;
        case PINGRESP:
				{
						INFO("<--PINGRESP");
						c->ping_outstanding = 0;
						countdown(&c->ping_timer, c->keepAliveInterval);
            break;
				}
    }
    rc = keepalive(c);
exit:
    if (rc == SUCCESS)
        rc = packet_type;
    return rc;
}
/**
  * Serializes a puback packet into the supplied buffer.
  * @param buf the buffer into which the packet will be serialized
  * @param buflen the length in bytes of the supplied buffer
  * @param packetid integer - the MQTT packet identifier
  * @return serialized length, or error if 0
  */
int MQTTSerialize_puback(unsigned char* buf, int buflen, unsigned short packetid)
{
	return MQTTSerialize_ack(buf, buflen, PUBACK, 0, packetid);
}
/**
  * Serializes a pubrel packet into the supplied buffer.
  * @param buf the buffer into which the packet will be serialized
  * @param buflen the length in bytes of the supplied buffer
  * @param packetid integer - the MQTT packet identifier
  * @return serialized length, or error if 0
  */
int MQTTSerialize_pubcomp(unsigned char* buf, int buflen, unsigned short packetid)
{
	return MQTTSerialize_ack(buf, buflen, PUBCOMP, packetid, 0);
}
int cycle(MQTTClient *c, Timer *timer)
{
    int len = 0,
        rc = SUCCESS;

    int packet_type = readPacket(c, timer);     /* read the socket, see what work is due */

    switch (packet_type) {
    default:
        /* no more data to read, unrecoverable. Or read packet fails due to unexpected network error */
        rc = packet_type;
        goto exit;

    case 0: /* timed out reading packet */
        break;

    case CONNACK:
    case PUBACK:
    case SUBACK:
    case UNSUBACK:
        break;

    case PUBLISH: {
        MQTTString topicName;
        MQTTMessage msg;
        int intQoS;
        msg.payloadlen = 0; /* this is a size_t, but deserialize publish sets this as int */

        if (MQTTDeserialize_publish(&msg.dup, &intQoS, &msg.retained, &msg.id, &topicName,
                                    (unsigned char **)&msg.payload, (int *)&msg.payloadlen, c->readbuf, c->readbuf_size) != 1) {
            goto exit;
        }

        msg.qos = (enum QoS)intQoS;
        deliverMessage(c, &topicName, &msg);

        if (msg.qos != QOS0) {
            if (msg.qos == QOS1) {
                len = MQTTSerialize_ack(c->buf, c->buf_size, PUBACK, 0, msg.id);
            } else if (msg.qos == QOS2) {
                len = MQTTSerialize_ack(c->buf, c->buf_size, PUBREC, 0, msg.id);
            }

            if (len <= 0) {
                rc = FAILURE;
            } else {
                rc = sendPacket(c, len, timer);
            }

            if (rc == FAILURE) {
                goto exit;    // there was a problem
            }
        }

        break;
    }

    case PUBREC:
    case PUBREL: {
        unsigned short mypacketid;
        unsigned char dup, type;

        if (MQTTDeserialize_ack(&type, &dup, &mypacketid, c->readbuf, c->readbuf_size) != 1) {
            rc = FAILURE;
        } else if ((len = MQTTSerialize_ack(c->buf, c->buf_size,
                                            (packet_type == PUBREC) ? PUBREL : PUBCOMP, 0, mypacketid)) <= 0) {
            rc = FAILURE;
        } else if ((rc = sendPacket(c, len, timer)) != SUCCESS) { // send the PUBREL packet
            rc = FAILURE;    // there was a problem
        }

        if (rc == FAILURE) {
            goto exit;    // there was a problem
        }

        break;
    }

    case PUBCOMP:
        break;

    case PINGRESP:
        c->ping_outstanding = 0;
        break;
    }

    if (keepalive(c) != SUCCESS) {
        //check only keepalive FAILURE status so that previous FAILURE status can be considered as FAULT
        rc = FAILURE;
    }

exit:

    if (rc == SUCCESS) {
        rc = packet_type;
    } else if (c->isconnected) {
        MQTTCloseSession(c);
    }

    return rc;
}
Exemple #9
0
int cycle( Client* c, Timer* timer )
{
    // read the socket, see what work is due
    unsigned short packet_type = readPacket( c, timer );
    int len = 0;
    int rc = MQTT_SUCCESS;

    WPRINT_APP_INFO( ("Packet Type %d\n", packet_type) );

    switch ( packet_type )
    {
        case CONNACK:
        case PUBACK:
        case SUBACK:
            break;
        case PUBLISH:
        {
            MQTTString topicName;
            MQTTMessage msg;

            if ( MQTTDeserialize_publish( (unsigned char*) &msg.dup, (int*) &msg.qos, (unsigned char*) &msg.retained, (unsigned short*) &msg.id, &topicName, (unsigned char**) &msg.payload, (int*) &msg.payloadlen, c->readbuf, c->readbuf_size ) != 1 )
            {
                goto exit;
            }

            deliverMessage( c, &topicName, &msg );
            if ( msg.qos != QOS0 )
            {
                if ( msg.qos == QOS1 )
                {
                    len = MQTTSerialize_ack( c->buf, c->buf_size, PUBACK, 0, msg.id );
                }
                else if ( msg.qos == QOS2 )
                {
                    len = MQTTSerialize_ack( c->buf, c->buf_size, PUBREC, 0, msg.id );
                }
                if ( len <= 0 )
                {
                    rc = MQTT_FAILURE;
                }
                else
                {
                    rc = sendPacket( c, len, timer );
                }

                if ( rc == MQTT_FAILURE )
                {
                    goto exit;
                    // there was a problem
                }
            }
            break;
        }
        case PUBREC:
        {
            unsigned short mypacketid;
            unsigned char dup, type;
            if ( MQTTDeserialize_ack( &type, &dup, &mypacketid, c->readbuf, c->readbuf_size ) != 1 )
            {
                rc = MQTT_FAILURE;
            }
            else if ( ( len = MQTTSerialize_ack( c->buf, c->buf_size, PUBREL, 0, mypacketid ) ) <= 0 )
            {
                rc = MQTT_FAILURE;
            }
            else if ( ( rc = sendPacket( c, len, timer ) ) != MQTT_SUCCESS ) // send the PUBREL packet
            {
                rc = MQTT_FAILURE; // there was a problem
            }

            if ( rc == MQTT_FAILURE )
            {
                goto exit;
                // there was a problem
            }

            break;
        }
        case PUBCOMP:
            break;
        case PINGRESP:
            c->ping_outstanding = 0;
            break;
    }

    keepalive( c );

    exit: if ( rc == MQTT_SUCCESS )
    {
        rc = packet_type;
    }

    return rc;
}
int cycle(Client* c, Timer* timer)
{
    // read the socket, see what work is due
    int read_status;
    unsigned short packet_type;
    read_status = readPacket(c, timer);
    packet_type = (unsigned short )read_status;

    if(read_status == SOCKET_CLOSED)
    {
    	MQTTReConnect(c);
    	goto exit;
    }
    int len = 0,
        rc = SUCCESS;
    switch (packet_type)
    {
        case CONNACK:
        {
			{
				unsigned char connack_rc = 255;
				char sessionPresent = 0;
				if (MQTTDeserialize_connack((unsigned char*)&sessionPresent, &connack_rc, c->readbuf, c->readbuf_size) == 1)
				{
					c->isconnected = 1;
					//开cloud灯
					system(SET_LIGHT_CLOUD);

					log_printf(LOG_NOTICE, "[MqttConnected]: recv connack\n");
					//subtopics and pubtopics init
					sprintf(&subtopics[0][0], "%s%s", SUBTOPIC_PRE1, gateway_info.did);
					sprintf(&subtopics[1][0], "%s%s", SUBTOPIC_PRE2, gateway_info.productkey);
					sprintf(&subtopics[2][0], "%s%s/#", SUBTOPIC_PRE3, gateway_info.did);

					sprintf(&pubtopics[0][0], "%s%s", PUBTOPIC_PRE1, gateway_info.did);
					sprintf(&pubtopics[1][0], "%s%s", PUBTOPIC_PRE2, gateway_info.did);
					sprintf(&pubtopics[2][0], "%s%s/#", PUBTOPIC_PRE3, gateway_info.did);

					rc = MQTTSubscribe(c, subtopics[c->suborder], 0, mh[c->suborder]); //for test
					log_printf(LOG_NOTICE, "Subscribing to %s\n", subtopics[c->suborder]);
					c->suborder++;
				}
			}
        }
        	break;
        case PUBACK:
        	break;
        case SUBACK:
        {
			int count = 0, grantedQoS = -1;
			unsigned short mypacketid;
			if (MQTTDeserialize_suback(&mypacketid, 1, &count, &grantedQoS, c->readbuf, c->readbuf_size) == 1)
				rc = grantedQoS; // 0, 1, 2 or 0x80
			if (rc != 0x80)
			{
				if(c->suborder <subscribe_over)
				{
					rc = MQTTSubscribe(c, subtopics[c->suborder], 0, mh[c->suborder]);
					log_printf(LOG_NOTICE, "Subscribing to %s\n",subtopics[c->suborder]);
					c->suborder++;
				}

//				int i;
//				for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
//				{
//					if (c->messageHandlers[i].topicFilter == 0)
//					{
//						c->messageHandlers[i].topicFilter = mytopics[i];
//						c->messageHandlers[i].fp = mh[i];
//						rc = 0;
//						break;
//					}
//				}
			}
			else
			{
				log_printf(LOG_ERROR, "SUCACK FAILED\n");
				//TODO: error handle
			}
        }
        	break;
        case PUBLISH:
        {
            if(c->suborder != subscribe_over)
            {
            	log_printf(LOG_ERROR, "[REC_MSG] rece publish msg but subcribe not over\n");
            	//TODO: error
            }
            MQTTString topicName = MQTTString_initializer;
            MQTTMessage msg;
            if (MQTTDeserialize_publish((unsigned char*)&msg.dup, (int*)&msg.qos, (unsigned char*)&msg.retained, (unsigned short*)&msg.id, &topicName,
               (unsigned char**)&msg.payload, (int*)&msg.payloadlen, c->readbuf, c->readbuf_size) != 1)
                goto exit;
            deliverMessage(c, &topicName, &msg);
//            MQTTPublish(c, "applerespond", &msg); //add by yaly for test
            if (msg.qos != QOS0)
            {
                if (msg.qos == QOS1)
                    len = MQTTSerialize_ack(c->buf, c->buf_size, PUBACK, 0, msg.id);
                else if (msg.qos == QOS2)
                    len = MQTTSerialize_ack(c->buf, c->buf_size, PUBREC, 0, msg.id);
                if (len <= 0)
                    rc = FAILURE;
                   else
                       rc = sendPacket_ev(c, len);
                if (rc == FAILURE)
                    goto exit;
            }
        }
        	break;
        case PUBREC:
        {
            unsigned short mypacketid;
            unsigned char dup, type;
            if (MQTTDeserialize_ack(&type, &dup, &mypacketid, c->readbuf, c->readbuf_size) != 1)
                rc = FAILURE;
            else if ((len = MQTTSerialize_ack(c->buf, c->buf_size, PUBREL, 0, mypacketid)) <= 0)
                rc = FAILURE;
            else if ((rc = sendPacket_ev(c, len)) != SUCCESS) // send the PUBREL packet
                rc = FAILURE;
            if (rc == FAILURE)
                goto exit;
            break;
        }
        break;
        case PUBCOMP:
            break;
        case PINGRESP:
        	log_printf(LOG_NOTICE, "[MqttPingResp]\n");
            c->ping_outstanding = 0;
            break;
    }
//    keepalive(c); //modify by yanly
exit:
    if (rc == SUCCESS)
        rc = packet_type;
    return rc;
}
static void *mqtt_sub_thread(void *param)
{
    MQTTPacket_connectData condata = MQTTPacket_connectData_initializer;
    int pktype, rc, len;
    int failcnt = 0;
    unsigned char wbuf[64];
    unsigned char rbuf[64];

    DEBUG("sub thread start\n");

    _csub.wbuf = wbuf;
    _csub.wbuflen = sizeof(wbuf);
    _csub.rbuf = rbuf;
    _csub.rbuflen = sizeof(rbuf);
    _csub.getfn = sub_read;

    if ((_csub.sockfd = mqtt_netconnect(HOSTNAME, HOSTPORT)) < 0)
    {
        DEBUG("sub netconnect fail\n");

        return 0;
    }

    DEBUG("sub connect to: %s %d\n", HOSTNAME, HOSTPORT);

    condata.clientID.cstring = "mqttsub";
    condata.keepAliveInterval = KEEPALIVE_INTERVAL;
    condata.cleansession = 1;
    condata.username.cstring = USERNAME;
    condata.password.cstring = PASSWORD;

    rc = mqtt_connect(&_csub, &condata);
    if (rc < 0)
        goto exit;

    DEBUG("sub connect ok\n");

    rc = mqtt_subscribe(&_csub, TOPIC, 0);
    if (rc < 0)
        goto exit;

    DEBUG("sub topic: %s\n", TOPIC);

    mqtt_ping_start(&_csub.sockfd);

    while (1)
    {
        pktype = MQTTPacket_read(_csub.rbuf, _csub.rbuflen, sub_read);

        switch (pktype)
        {
        case CONNACK:
        case PUBACK:
        case SUBACK:
            break;
        case PUBLISH:
        {
            MQTTString topic;
            mqtt_msg_t msg;

            if (MQTTDeserialize_publish(&msg.dup, &msg.qos, &msg.retained, &msg.id, &topic,
                                                         &msg.payload, &msg.payloadlen, _csub.rbuf, _csub.rbuflen) != 1)
                goto exit;

            msgprocess(&topic, &msg);

            if (msg.qos != 0)
            {
                if (msg.qos == 1)
                    len = MQTTSerialize_ack(_csub.wbuf, _csub.wbuflen, PUBACK, 0, msg.id);
                else if (msg.qos == 2)
                    len = MQTTSerialize_ack(_csub.wbuf, _csub.wbuflen, PUBREC, 0, msg.id);

                if (len <= 0)
                    rc = -1;
                else
                    rc = mqtt_write(_csub.sockfd, _csub.wbuf, len);

                if (rc == -1)
                    goto exit;
            }
        }
        break;
        case PUBCOMP:
            break;
        case PINGRESP:
            failcnt = 0;
            break;
        case -1:
            if (++failcnt > KEEPALIVE_INTERVAL)
            {
                /*  */
                goto exit;
            }
            break;
        }
    }
    /*  */
    mqtt_disconnect(&_csub);

exit:
    mqtt_netdisconnect(&_csub.sockfd);
    DEBUG("sub thread exit\n");

    return 0;
}
/*


	success -> 
  		return packet type
  	fail->
		return FAIL

*/
int cycle(MQTTClient* c, Timer* timer)
{
	int packet_type = readPacket(c, timer);
	int len = 0;
	int rc = SUCCESS;

	if (FAILURE == packet_type) {
		packet_type = NOPACKET;
		goto exit;
	}
	printf("received %s\n", MQTTPacket_names[packet_type]);

	switch (packet_type)
	{
		case CONNACK:
		case PUBACK:
		case SUBACK:
			break;
		case PUBLISH:
		{
			MQTTString topicName;
			MQTTMessage msg;
			int intQoS;
			if (MQTTDeserialize_publish(&msg.dup, &intQoS, &msg.retained, &msg.id, &topicName,
					(unsigned char**)&msg.payload, (int*)&msg.payloadlen, c->readbuf, c->readbuf_size) != 1)
				goto exit;

			msg.qos = (enum QoS)intQoS;
			//deliverMessage(c, &topicName, &msg);

			if (msg.qos != QOS0) {
				if (msg.qos == QOS1)
					len = MQTTSerialize_ack(c->buf, c->buf_size, PUBACK, 0, msg.id);
				else if (msg.qos == QOS2)
					len = MQTTSerialize_ack(c->buf, c->buf_size, PUBREC, 0, msg.id);

				if (len <= 0)
					rc = FAILURE;
				else
					rc = sendPacket(c, len, timer);

				if (rc == FAILURE)
					goto exit; // there was a problem
			}
			deliverMessage(c, &topicName, &msg);

			break;
		}
		case PUBREC:
		{
			unsigned short mypacketid;
			unsigned char dup, type;
			if (MQTTDeserialize_ack(&type, &dup, &mypacketid, c->readbuf, c->readbuf_size) != 1)
				rc = FAILURE;
			else if ((len = MQTTSerialize_ack(c->buf, c->buf_size, PUBREL, 0, mypacketid)) <= 0)
				rc = FAILURE;
			else if ((rc = sendPacket(c, len, timer)) != SUCCESS) // send the PUBREL packet
				rc = FAILURE; // there was a problem
			if (rc == FAILURE)
				goto exit; // there was a problem
			break;
		}
		case PUBCOMP:
			break;
		case PINGRESP:
			c->ping_outstanding = 0;
			//c->keepAliveFailCount = 0;
			break;
		case PUBREL:
		{
			unsigned short mypacketid;
			unsigned char dup, type;
			if (MQTTDeserialize_ack(&type, &dup, &mypacketid, c->readbuf, c->readbuf_size) != 1)
				rc = FAILURE;
			else if ((len = MQTTSerialize_ack(c->buf, c->buf_size, PUBCOMP, 0, mypacketid)) <= 0)
				rc = FAILURE;
			else if ((rc = sendPacket(c, len, timer)) != SUCCESS) // send the PUBCOMP packet
				rc = FAILURE; // there was a problem
			if (rc == FAILURE)
				goto exit; // there was a problem
			break;
		}
	}

exit:

	if (FAILURE == keepalive(c)) {
		rc = FAILURE;
	}

	if (rc == SUCCESS)
		rc = packet_type;

	return rc;
}
int cycle(MQTTClient* c, Timer* timer)
{
    Timer t;
    platform_timer_init(&t);

    int len = 0, packet_type, rc = MQTT_SUCCESS;

    // read the socket, see what work is due
    if ((packet_type = readPacket(c, timer)) == MQTT_CONNECTION_LOST)
	{
		rc = MQTT_CONNECTION_LOST;
		goto exit;
	}
    
    switch (packet_type)
    {
        case CONNACK:
        case PUBACK:
        case SUBACK:
            break;
        case PUBLISH:
        {
            MQTTString topicName;
            MQTTMessage msg = {0};
            int intQoS;
            if (MQTTDeserialize_publish(&msg.dup, &intQoS, &msg.retained, &msg.id, &topicName,
               (unsigned char**)&msg.payload, &msg.payloadlen, c->readbuf, c->readbuf_size) != 1)
                goto exit;
            msg.qos = (enum QoS)intQoS;
            deliverMessage(c, &topicName, &msg);
            if (msg.qos != QOS0)
            {
                if (msg.qos == QOS1)
                    len = MQTTSerialize_ack(c->buf, c->buf_size, PUBACK, 0, msg.id);
                else if (msg.qos == QOS2)
                    len = MQTTSerialize_ack(c->buf, c->buf_size, PUBREC, 0, msg.id);
                if (len <= 0)
                    rc = MQTT_FAILURE;
                else
                {
                    platform_timer_countdown(&t, c->command_timeout_ms);
                    rc = sendPacket(c, len, &t);
                }
                if (rc == MQTT_FAILURE)
                    goto exit; // there was a problem
            }
            break;
        }
        case PUBREC:
        {
            unsigned short mypacketid;
            unsigned char dup, type;
            platform_timer_countdown(&t, c->command_timeout_ms);
            if (MQTTDeserialize_ack(&type, &dup, &mypacketid, c->readbuf, c->readbuf_size) != 1)
                rc = MQTT_FAILURE;
            else if ((len = MQTTSerialize_ack(c->buf, c->buf_size, PUBREL, 0, mypacketid)) <= 0)
                rc = MQTT_FAILURE;
            else if ((rc = sendPacket(c, len, &t)) != MQTT_SUCCESS) // send the PUBREL packet
                rc = MQTT_FAILURE; // there was a problem
            if (rc == MQTT_FAILURE)
                goto exit; // there was a problem
            break;
        }
        case PUBCOMP:
            break;
        case PINGRESP:
            c->ping_outstanding = 0;
            platform_printf("received ping response\n");
            break;
    }

    keepalive(c);

    if (c->ping_outstanding && platform_timer_isexpired(&c->pingresp_timer))
    {
        c->ping_outstanding = 0;
		platform_printf("ping response was not received within keepalive timeout of %d\n", 
                c->keepAliveInterval);
        rc = MQTT_CONNECTION_LOST;
    }

exit:
	if (rc == MQTT_SUCCESS)
		rc = packet_type;

	return rc;
}