Exemple #1
0
/**
 * Utility function to start a new publish exchange.
 * @param pubclient the client to send the publication to
 * @param publish the publication data
 * @param qos the MQTT QoS to use
 * @param retained boolean - whether to set the MQTT retained flag
 * @return the completion code
 */
int MQTTProtocol_startPublishCommon(Clients* pubclient, Publish* publish, int qos, int retained)
{
	int rc = TCPSOCKET_COMPLETE;

	FUNC_ENTRY;
	if (qos == 0 && (strlen(publish->topic) < 5 || strncmp(publish->topic, sysprefix, strlen(sysprefix)) != 0))
	{
		++(bstate->msgs_sent);
		bstate->bytes_sent += publish->payloadlen;
	}
#if defined(MQTTS)
	if (pubclient->protocol == PROTOCOL_MQTTS)
	{
		rc = MQTTSProtocol_startPublishCommon(pubclient,publish,0,qos,retained);
	}
	else
	{
#endif
	rc = MQTTPacket_send_publish(publish, 0, qos, retained, pubclient->socket, pubclient->clientID);
	if (qos == 0 && rc == TCPSOCKET_INTERRUPTED)
		MQTTProtocol_storeQoS0(pubclient, publish);
#if defined(MQTTS)
	}
#endif
	FUNC_EXIT_RC(rc);
	return rc;
}
/**
 * Utility function to start a new publish exchange.
 * @param pubclient the client to send the publication to
 * @param publish the publication data
 * @param qos the MQTT QoS to use
 * @param retained boolean - whether to set the MQTT retained flag
 * @return the completion code
 */
static int MQTTProtocol_startPublishCommon(Clients* pubclient, Publish* publish, int qos, int retained)
{
	int rc = TCPSOCKET_COMPLETE;

	FUNC_ENTRY;
	rc = MQTTPacket_send_publish(publish, 0, qos, retained, &pubclient->net, pubclient->clientID);
	if (qos == 0 && rc == TCPSOCKET_INTERRUPTED)
		MQTTProtocol_storeQoS0(pubclient, publish);
	FUNC_EXIT_RC(rc);
	return rc;
}
Exemple #3
0
/**
 * MQTT retry processing per client
 * @param now current time
 * @param client - the client to which to apply the retry processing
 */
void MQTTProtocol_retries(time_t now, Clients* client)
{
	ListElement* outcurrent = NULL;
	FUNC_ENTRY;
#if defined(MQTTS)
	if (client->protocol == PROTOCOL_MQTTS)
	{
		if (client->pendingRegistration != NULL &&
				difftime(now, client->pendingRegistration->sent) > bstate->retry_interval)
		{
			Registration* reg = client->pendingRegistration->registration;
			time(&client->pendingRegistration->sent);
			/* NB: no dup bit for these packets */
			if (MQTTSPacket_send_register(client, reg->id, reg->topicName, client->pendingRegistration->msgId) == SOCKET_ERROR)
			{
				client->good = 0;
				//TODO: update message
				Log(LOG_WARNING, 29, NULL, client->clientID, client->socket);
				MQTTProtocol_closeSession(client, 1);
				client = NULL;
			}
		}
#if !defined(NO_BRIDGE)
		if (client->pendingSubscription != NULL &&
				difftime(now, client->pendingSubscription->sent) > bstate->retry_interval)
		{
			time(&client->pendingSubscription->sent);
			if (MQTTSPacket_send_subscribe(client, client->pendingSubscription->topicName,client->pendingSubscription->qos, client->pendingSubscription->msgId) == SOCKET_ERROR)
			{
				client->good = 0;
				//TODO: update message
				Log(LOG_WARNING, 29, NULL, client->clientID, client->socket);
				MQTTProtocol_closeSession(client, 1);
				client = NULL;
			}
		}
#endif
	}
#endif
	while (client && ListNextElement(client->outboundMsgs, &outcurrent) &&
		   client->connected && client->good &&           /* client is connected and has no errors */
			Socket_noPendingWrites(client->socket))  /* there aren't any previous packets still stacked up on the socket */
	{
		Messages* m = (Messages*)(outcurrent->content);


		if (difftime(now, m->lastTouch) > bstate->retry_interval)
		{
			if (m->qos == 1 || (m->qos == 2 && m->nextMessageType == PUBREC))
			{
				Publish publish;
				int rc;
				Log(LOG_INFO, 28, NULL, client->clientID, client->socket, m->msgid);
				publish.msgId = m->msgid;
				publish.topic = m->publish->topic;
				publish.payload = m->publish->payload;
				publish.payloadlen = m->publish->payloadlen;
#if defined(MQTTS)
				if (client->protocol == PROTOCOL_MQTTS)
				{
					if (MQTTSProtocol_startPublishCommon(client, &publish, 1, m->qos, m->retain) == SOCKET_ERROR)
					{
						client->good = 0;
						Log(LOG_WARNING, 29, NULL, client->clientID, client->socket);
						MQTTProtocol_closeSession(client, 1);
						client = NULL;
					}
					else
						time(&(m->lastTouch));
				}
				else
				{
#endif
					rc = MQTTPacket_send_publish(&publish, 1, m->qos, m->retain, client->socket, client->clientID);
					if (rc == SOCKET_ERROR)
					{
						client->good = 0;
						Log(LOG_WARNING, 29, NULL, client->clientID, client->socket);
						MQTTProtocol_closeSession(client, 1);
						client = NULL;
					}
					else
					{
						if (m->qos == 0 && rc == TCPSOCKET_INTERRUPTED)
							MQTTProtocol_storeQoS0(client, &publish);
						time(&(m->lastTouch));
					}
#if defined(MQTTS)
				}
#endif
			}
			else if (m->qos && m->nextMessageType == PUBCOMP)
			{
				Log(LOG_WARNING, 30, NULL, client->clientID, m->msgid);
#if defined(MQTTS)
				if (client->protocol == PROTOCOL_MQTTS)
				{
					/* NB: no dup bit for PUBREL */
					if (MQTTSPacket_send_pubrel(client, m->msgid) == SOCKET_ERROR)
					{
						client->good = 0;
						Log(LOG_WARNING, 18, NULL, client->clientID, client->socket,
								Socket_getpeer(client->socket));
						MQTTProtocol_closeSession(client, 1);
						client = NULL;
					}
					else
						time(&(m->lastTouch));
				}
				else
#endif
					if (MQTTPacket_send_pubrel(m->msgid, 1, client->socket, client->clientID) != TCPSOCKET_COMPLETE)
					{
						client->good = 0;
						Log(LOG_WARNING, 18, NULL, client->clientID, client->socket,
								Socket_getpeer(client->socket));
						MQTTProtocol_closeSession(client, 1);
						client = NULL;
					}
					else
						time(&(m->lastTouch));
			}
			/* break; why not do all retries at once? */
		}
	}
	FUNC_EXIT;
}
/**
 * MQTT retry processing per client
 * @param now current time
 * @param client - the client to which to apply the retry processing
 * @param regardless boolean - retry packets regardless of retry interval (used on reconnect)
 */
static void MQTTProtocol_retries(time_t now, Clients* client, int regardless)
{
	ListElement* outcurrent = NULL;

	FUNC_ENTRY;

	if (!regardless && client->retryInterval <= 0) /* 0 or -ive retryInterval turns off retry except on reconnect */
		goto exit;

	while (client && ListNextElement(client->outboundMsgs, &outcurrent) &&
		   client->connected && client->good &&        /* client is connected and has no errors */
		   Socket_noPendingWrites(client->net.socket)) /* there aren't any previous packets still stacked up on the socket */
	{
		Messages* m = (Messages*)(outcurrent->content);
		if (regardless || difftime(now, m->lastTouch) > max(client->retryInterval, 10))
		{
			if (m->qos == 1 || (m->qos == 2 && m->nextMessageType == PUBREC))
			{
				Publish publish;
				int rc;

				Log(TRACE_MIN, 7, NULL, "PUBLISH", client->clientID, client->net.socket, m->msgid);
				publish.msgId = m->msgid;
				publish.topic = m->publish->topic;
				publish.payload = m->publish->payload;
				publish.payloadlen = m->publish->payloadlen;
				rc = MQTTPacket_send_publish(&publish, 1, m->qos, m->retain, &client->net, client->clientID);
				if (rc == SOCKET_ERROR)
				{
					client->good = 0;
					Log(TRACE_PROTOCOL, 29, NULL, client->clientID, client->net.socket,
												Socket_getpeer(client->net.socket));
					MQTTProtocol_closeSession(client, 1);
					client = NULL;
				}
				else
				{
					if (m->qos == 0 && rc == TCPSOCKET_INTERRUPTED)
						MQTTProtocol_storeQoS0(client, &publish);
					time(&(m->lastTouch));
				}
			}
			else if (m->qos && m->nextMessageType == PUBCOMP)
			{
				Log(TRACE_MIN, 7, NULL, "PUBREL", client->clientID, client->net.socket, m->msgid);
				if (MQTTPacket_send_pubrel(m->msgid, 0, &client->net, client->clientID) != TCPSOCKET_COMPLETE)
				{
					client->good = 0;
					Log(TRACE_PROTOCOL, 29, NULL, client->clientID, client->net.socket,
							Socket_getpeer(client->net.socket));
					MQTTProtocol_closeSession(client, 1);
					client = NULL;
				}
				else
					time(&(m->lastTouch));
			}
			/* break; why not do all retries at once? */
		}
	}
exit:
	FUNC_EXIT;
}