コード例 #1
0
ファイル: MQTTSProtocol.c プロジェクト: Pumpwell/rsmb
int MQTTSProtocol_handleSubscribes(void* pack, int sock, char* clientAddr, Clients* client)
{
	int rc = 0;
	MQTTS_Subscribe* sub = (MQTTS_Subscribe*)pack;
	int isnew;
	int topicId = 0;
	char* topicName = NULL , *preDefinedTopicName = NULL;

	FUNC_ENTRY;
	Log(LOG_PROTOCOL, 67, NULL, sock, clientAddr, client ? client->clientID : "",
		sub->msgId,
		(sub->flags.QoS == 3) ? -1: sub->flags.QoS,
		sub->flags.topicIdType);

	// NORMAL (topic name is in subscribe packet) or SHORT topic name
	if (sub->flags.topicIdType == MQTTS_TOPIC_TYPE_NORMAL || sub->flags.topicIdType == MQTTS_TOPIC_TYPE_SHORT)
	{
		topicName = sub->topicName;
		sub->topicName = NULL;
	}
	// Pre-defined topic
	else if (sub->flags.topicIdType == MQTTS_TOPIC_TYPE_PREDEFINED && client != NULL && sub->topicId != 0)
	{
		char *name = MQTTSProtocol_getPreRegisteredTopicName(client, sub->topicId) ;
		if (name) {
			preDefinedTopicName = MQTTSProtocol_replaceTopicNamePlaceholders(client , name ) ;
		}
		topicName = preDefinedTopicName ;
		topicId = sub->topicId;
	}

	// If topic name not found send SubAck with Rejected - Invalid topic ID
	if (topicName == NULL)
		rc = MQTTSPacket_send_subAck(client, sub, 0, sub->flags.QoS, MQTTS_RC_REJECTED_INVALID_TOPIC_ID);
	else
	{
		if (sub->flags.topicIdType == MQTTS_TOPIC_TYPE_NORMAL && !Topics_hasWildcards(topicName))
		{
			char* regTopicName = malloc(strlen(topicName)+1);
			strcpy(regTopicName, topicName);
			topicId = (MQTTSProtocol_registerTopic(client, regTopicName))->id;
		}

		isnew = SubscriptionEngines_subscribe(bstate->se, client->clientID,
				topicName, sub->flags.QoS, client->noLocal, (client->cleansession == 0), PRIORITY_NORMAL);

		if ( (rc = MQTTSPacket_send_subAck(client, sub, topicId, sub->flags.QoS, MQTTS_RC_ACCEPTED)) == 0)
			if ((client->noLocal == 0) || isnew)
				MQTTProtocol_processRetaineds(client, topicName,sub->flags.QoS, PRIORITY_NORMAL);
	}
	time( &(client->lastContact) );
	MQTTSPacket_free_packet(pack);
	if (preDefinedTopicName)
		free (preDefinedTopicName);
	FUNC_EXIT_RC(rc);
	return rc;
}
コード例 #2
0
ファイル: MQTTProtocol.c プロジェクト: Frank-KunLi/DTLS_RSMB
/**
 * Process an incoming ping subscribe packet for a socket
 * @param pack pointer to the subscribe packet
 * @param sock the socket on which the packet was received
 * @return completion code
 */
int MQTTProtocol_handleSubscribes(void* pack, int sock, Clients* client)
{
	int i, *aq, *isnew, *authorized;
	Subscribe* subscribe = (Subscribe*)pack;
	ListElement *curtopic = NULL, *curqos = NULL;
	int rc = TCPSOCKET_COMPLETE;
#if !defined(SINGLE_LISTENER)
	Listener* listener = Socket_getParentListener(sock);
#endif

	FUNC_ENTRY;
	if (Protocol_isClientQuiescing(client))
		goto exit; /* don't accept new work */

	Log(LOG_PROTOCOL, 6, NULL, sock, client->clientID, subscribe->msgId);
	aq = malloc(sizeof(int)*(subscribe->noTopics));
	isnew = malloc(sizeof(int)*(subscribe->noTopics));
	authorized = malloc(sizeof(int)*(subscribe->noTopics));
	for (i = 0; i < subscribe->noTopics; ++i)
	{
		int j;
		ListElement *duptopic = NULL;

		ListNextElement(subscribe->topics, &curtopic);
		aq[i] = *(int*)(ListNextElement(subscribe->qoss, &curqos)->content);

		/* The mount_point topic transformation must be done before the topic syntax validity check
		 * otherwise badly formed topics can get into the subscription engine.
		 */
#if !defined(SINGLE_LISTENER)
		if (listener && listener->mount_point)
		{
			char* temp = malloc(strlen((char*)(curtopic->content)) + strlen(listener->mount_point) + 1);
			strcpy(temp, listener->mount_point);
			strcat(temp, (char*)(curtopic->content));
			free((char*)(curtopic->content));
			curtopic->content = temp;
			subscribe->topics->size += strlen(listener->mount_point);
		}
#endif

		if (!Topics_isValidName((char*)curtopic->content))
		{
			Log(LOG_WARNING, 153, NULL, (char*)curtopic->content, client->clientID, client->addr);
			free(curtopic->content);
			continue;
		}

		authorized[i] = true;
		if (bstate->password_file && bstate->acl_file)
		{
			authorized[i] = Users_authorise(client->user,(char*)(curtopic->content),ACL_READ);
			if (!authorized[i])
				Log(LOG_AUDIT, 150, NULL, client->clientID, (char*)(curtopic->content));
		}

		for (j = 0; j < i; ++j)
		{
			char* prevtopic = (char*)(ListNextElement(subscribe->topics, &duptopic)->content);
			if (strcmp(prevtopic, (char*)(curtopic->content)) == 0)
				duptopic->content = curtopic->content;
		}
		isnew[i] = SubscriptionEngines_subscribe(bstate->se, client->clientID,
			(char*)(curtopic->content), aq[i], client->noLocal, (client->cleansession == 0), PRIORITY_NORMAL);
	}
	/* send suback before sending the retained publications because a lot of retained publications could fill up the socket buffer */
	if ((rc = MQTTPacket_send_suback(subscribe->msgId, subscribe->noTopics, aq, sock, client->clientID)) != SOCKET_ERROR)
	{
		curtopic = curqos = NULL;
		for (i = 0; i < subscribe->noTopics; ++i)
		{
			/* careful if you get >1 subscriptions using the same topic name in the same packet! */
			/* The next line changes the semantics of subscribe for bridge connections,
			 * so that retained messages are only sent for new subscriptions.  This is to help
			 * avoid "retained message storms" when a connection drops and is re-established.
			 * This change could be applied to all subscriptions by removing the "noLocal" check. */
			if (authorized[i] && ((client->noLocal == 0) || isnew[i]))
				MQTTProtocol_processRetaineds(client, (char*)(ListNextElement(subscribe->topics, &curtopic)->content),
					*(int*)(ListNextElement(subscribe->qoss, &curqos)->content), PRIORITY_NORMAL);
		}
	}
	free(aq);
	free(isnew);
	free(authorized);
exit:
	MQTTPacket_freeSubscribe(subscribe, 0);
	FUNC_EXIT_RC(rc);
	return rc;
}