예제 #1
0
int MQTTSProtocol_handleAdvertises(void* pack, int sock, char* clientAddr, Clients* client)
{
	MQTTS_Advertise* advertisePack = (MQTTS_Advertise*)pack;
	Listener* listener = NULL;
	char* topic = NULL;
	char* data = NULL;
	int offset = 0;
	struct timeb ts;
	struct tm *timeinfo;

	FUNC_ENTRY;
	Log(LOG_PROTOCOL, 31, NULL, sock, "", clientAddr, advertisePack->gwId, advertisePack->duration);

	ftime(&ts);
	timeinfo = localtime(&ts.time);

	listener = Socket_getParentListener(sock);

	topic = malloc(40);
	sprintf(topic, "$SYS/broker/mqtts/listener/%d", listener->port);

	data = malloc(80);
	offset = strftime(data, 60, "%Y%m%d %H%M%S ", timeinfo);
	sprintf(&data[offset], "advertise from %s gateway id: %d duration: %d",
			clientAddr, advertisePack->gwId, advertisePack->duration);

	MQTTSPacket_free_packet(pack);
	MQTTProtocol_sys_publish(topic, data);

	free(topic);
	free(data);
	FUNC_EXIT;
	return 0;
}
예제 #2
0
int MQTTSProtocol_handlePubacks(void* pack, int sock, char* clientAddr, Clients* client)
{
	int rc = 0;
	MQTTS_PubAck* puback = (MQTTS_PubAck*)pack;

	FUNC_ENTRY;
	Log(LOG_PROTOCOL, 57, NULL, sock, clientAddr, client ? client->clientID : "", puback->msgId);

	/* look for the message by message id in the records of outbound messages for this client */
	if (ListFindItem(client->outboundMsgs, &(puback->msgId), messageIDCompare) == NULL)
		Log(LOG_WARNING, 50, NULL, "PUBACK", client->clientID, puback->msgId);
	else
	{
		Messages* m = (Messages*)(client->outboundMsgs->current->content);
		if (m->qos != 1)
			Log(LOG_WARNING, 51, NULL, "PUBACK", client->clientID, puback->msgId, m->qos);
		else
		{
			Log(TRACE_MAX, 4, NULL, client->clientID, puback->msgId);
			MQTTProtocol_removePublication(m->publish);
			ListRemove(client->outboundMsgs, m);
			/* TODO: msgs counts */
			/* (++state.msgs_sent);*/
		}
	}
	MQTTSPacket_free_packet(pack);
	FUNC_EXIT_RC(rc);
	return rc;
}
예제 #3
0
int MQTTSProtocol_handlePingresps(void* pack, int sock, char* clientAddr, Clients* client)
{
	FUNC_ENTRY;
	client->ping_outstanding = 0;
	time( &(client->lastContact) );
	MQTTSPacket_free_packet(pack);
	FUNC_EXIT;
	return 0;
}
예제 #4
0
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;
}
예제 #5
0
int MQTTSProtocol_handlePingreqs(void* pack, int sock, char* clientAddr, Clients* client)
{
	int rc = 0;

	FUNC_ENTRY;
	rc = MQTTSPacket_send_pingResp(client);
	time( &(client->lastContact) );
	MQTTSPacket_free_packet(pack);
	FUNC_EXIT_RC(rc);
	return rc;
}
예제 #6
0
int MQTTSProtocol_handleRegacks(void* pack, int sock, char* clientAddr, Clients* client)
{
	int rc = 0;
	MQTTS_RegAck* regack = (MQTTS_RegAck*)pack;

	FUNC_ENTRY;
	if (client->pendingRegistration == NULL ||
			regack->msgId != client->pendingRegistration->msgId)
	{
		/* unexpected regack*/
	}
	else if (!client->outbound)
	{
		if (regack->topicId != client->pendingRegistration->registration->id)
		{
			/* unexpected regack*/
		}
		else if (regack->returnCode != MQTTS_RC_ACCEPTED)
		{
			/* rejected ack... what do we do now? */
		}
		else
		{
			free(client->pendingRegistration);
			client->pendingRegistration = NULL;
			rc = MQTTProtocol_processQueued(client);
		}
	}
	else /* outbound client */
	{
		if (regack->returnCode != MQTTS_RC_ACCEPTED)
		{
			/* rejected ack... what do we do now? */
		}
		else
		{
			Registration* reg = client->pendingRegistration->registration;
			free(client->pendingRegistration);
			client->pendingRegistration = NULL;
			reg->id = regack->topicId;
			ListAppend(client->registrations, reg, sizeof(reg) + strlen(reg->topicName)+1);
			rc = MQTTProtocol_processQueued(client);
		}

	}

	time( &(client->lastContact) );
	MQTTSPacket_free_packet(pack);
	FUNC_EXIT_RC(rc);
	return rc;
}
예제 #7
0
int MQTTSProtocol_handleWillMsgUpds(void* pack, int sock, char* clientAddr, Clients* client)
{
	int rc = 0;
	MQTTS_WillMsgUpd* willMsg = (MQTTS_WillMsgUpd*)pack;

	FUNC_ENTRY;
	MQTTProtocol_setWillMsg(client, willMsg->willMsg);
	willMsg->willMsg = NULL;
	rc = MQTTSPacket_send_willMsgResp(client);
	time( &(client->lastContact) );
	MQTTSPacket_free_packet(pack);
	FUNC_EXIT_RC(rc);
	return rc;
}
예제 #8
0
int MQTTSProtocol_handlePubrels(void* pack, int sock, char* clientAddr, Clients* client)
{
	int rc = 0;
	MQTTS_PubRel* pubrel = (MQTTS_PubRel*)pack;

	FUNC_ENTRY;
	/* look for the message by message id in the records of inbound messages for this client */
	if (ListFindItem(client->inboundMsgs, &(pubrel->msgId), messageIDCompare) == NULL)
	{
		/* TODO: no dup flag in mqtts... not sure this is right
		if (pubrel->header.dup == 0)
			Log(LOG_WARNING, 50, "PUBREL", client->clientID, pubrel->msgId);
		else
		*/
			/* Apparently this is "normal" behavior, so we don't need to issue a warning */
			rc = MQTTSPacket_send_pubcomp(client,pubrel->msgId);
	}
	else
	{
		Messages* m = (Messages*)(client->inboundMsgs->current->content);
		if (m->qos != 2)
			Log(LOG_WARNING, 51, NULL, "PUBREL", client->clientID, pubrel->msgId, m->qos);
		else if (m->nextMessageType != PUBREL)
			Log(LOG_WARNING, 52, NULL, "PUBREL", client->clientID, pubrel->msgId);
		else
		{
			Publish publish;

			/* send pubcomp before processing the publications because a lot of return publications could fill up the socket buffer */
			rc = MQTTSPacket_send_pubcomp(client, pubrel->msgId);
			publish.header.bits.qos = m->qos;
			publish.header.bits.retain = m->retain;
			publish.msgId = m->msgid;
			publish.topic = m->publish->topic;
			publish.payload = m->publish->payload;
			publish.payloadlen = m->publish->payloadlen;
			Protocol_processPublication(&publish, client->clientID);
			MQTTProtocol_removePublication(m->publish);
			ListRemove(client->inboundMsgs, m);
			/* TODO: msgs counts */
			/* ++(state.msgs_received); */
		}
	}
	time( &(client->lastContact) );
	MQTTSPacket_free_packet(pack);
	FUNC_EXIT_RC(rc);
	return rc;
}
예제 #9
0
int MQTTSProtocol_handleWillMsgReqs(void* pack, int sock, char* clientAddr)
{
	Clients* client = Bridge_getClient(sock);

	FUNC_ENTRY;
	if (client == NULL)
	{
		//TODO: what now?
	}
	else
		MQTTSPacket_send_willMsg(client);

	MQTTSPacket_free_packet(pack);
  	FUNC_EXIT;
  	return 0;
}
예제 #10
0
int MQTTSProtocol_handleWillMsgReqs(void* pack, int sock, char* clientAddr, Clients* client)
{
	FUNC_ENTRY;
	//client = Bridge_getClient(sock);
	Log(LOG_PROTOCOL, 47, NULL, client->socket, client->addr, client->clientID);
	if (client == NULL)
	{
		//TODO: what now?
	}
	else
		MQTTSPacket_send_willMsg(client);

	MQTTSPacket_free_packet(pack);
  	FUNC_EXIT;
  	return 0;
}
예제 #11
0
int MQTTSProtocol_handlePubrecs(void* pack, int sock, char* clientAddr, Clients* client)
{
	int rc = 0;
	MQTTS_PubRec* pubrec = (MQTTS_PubRec*)pack;

	FUNC_ENTRY;
	Log(LOG_PROTOCOL, 15, NULL, pubrec->msgId, client->clientID);

	/* look for the message by message id in the records of outbound messages for this client */
	client->outboundMsgs->current = NULL;
	if (ListFindItem(client->outboundMsgs, &(pubrec->msgId), messageIDCompare) == NULL)
	{
		/* No Dupe flag in MQTTs
		if (pubrec->header.dup == 0)
		*/
		Log(LOG_WARNING, 50, NULL, "PUBREC", client->clientID, pubrec->msgId);
	}
	else
	{
		Messages* m = (Messages*)(client->outboundMsgs->current->content);
		if (m->qos != 2)
		{
			/* No Dupe flag in MQTTs
			if (pubrec->header.dup == 0)
			*/
			Log(LOG_WARNING, 51, NULL, "PUBREC", client->clientID, pubrec->msgId, m->qos);
		}
		else if (m->nextMessageType != PUBREC)
		{
			/* No Dupe flag in MQTTs
			if (pubrec->header.dup == 0)
			*/
			Log(LOG_WARNING, 52, NULL, "PUBREC", client->clientID, pubrec->msgId);
		}
		else
		{
			rc = MQTTSPacket_send_pubrel(client, pubrec->msgId);
			m->nextMessageType = PUBCOMP;
			time(&(m->lastTouch));
		}
	}
	MQTTSPacket_free_packet(pack);
	FUNC_EXIT_RC(rc);
	return rc;
}
예제 #12
0
int MQTTSProtocol_handleWillTopicUpds(void* pack, int sock, char* clientAddr, Clients* client)
{
	int rc = 0;
	MQTTS_WillTopicUpd* willTopic = (MQTTS_WillTopicUpd*)pack;

	FUNC_ENTRY;
	if (willTopic->willTopic != NULL)
	{
		MQTTProtocol_setWillTopic(client, willTopic->willTopic, willTopic->flags.retain, willTopic->flags.QoS);
		willTopic->willTopic = NULL;
	}
	else
		MQTTProtocol_clearWill(client);
	rc = MQTTSPacket_send_willTopicResp(client);
	time( &(client->lastContact) );
	MQTTSPacket_free_packet(pack);
	FUNC_EXIT_RC(rc);
	return rc;
}
예제 #13
0
int MQTTSProtocol_handleWillTopics(void* pack, int sock, char* clientAddr, Clients* client)
{
	MQTTS_WillTopic* willTopic = (MQTTS_WillTopic*)pack;
	int rc = 0;

	FUNC_ENTRY;
	Log(LOG_PROTOCOL, 45, NULL, sock, clientAddr, client->clientID,
				willTopic->flags.QoS, willTopic->flags.retain, willTopic->willTopic);
	if (client->connect_state == 1)
	{
		MQTTProtocol_setWillTopic(client, willTopic->willTopic, willTopic->flags.retain, willTopic->flags.QoS);
		willTopic->willTopic = NULL;
		client->connect_state = 2;
		rc = MQTTSPacket_send_willMsgReq(client);
	}
	MQTTSPacket_free_packet(pack);
	time( &(client->lastContact) );
	FUNC_EXIT_RC(rc);
	return rc;
}
예제 #14
0
int MQTTSProtocol_handleDisconnects(void* pack, int sock, char* clientAddr, Clients* client)
{
	MQTTS_Disconnect* disc = (MQTTS_Disconnect*)pack;

	FUNC_ENTRY;
	Log(LOG_PROTOCOL, 79, NULL, socket, client->addr, client->clientID, disc->duration);
	client->good = 0; /* don't try and send log message to this client if it is subscribed to $SYS/broker/log */
	Log((bstate->connection_messages) ? LOG_INFO : LOG_PROTOCOL, 38, NULL, client->clientID);

	// Remove all registrations if duration is zero.
	// Otherwise keep it. It is a sleeping client
	if ( disc->duration == 0 ) {
		MQTTSProtocol_emptyRegistrationList(client->registrations);
	}

	MQTTProtocol_closeSession(client, 0);
	MQTTSPacket_free_packet(pack);
	FUNC_EXIT;
	return 0;
}
예제 #15
0
int MQTTSProtocol_handleWillMsgs(void* pack, int sock, char* clientAddr, Clients* client)
{
	int rc = 0;
	MQTTS_WillMsg* willMsg = (MQTTS_WillMsg*)pack;

	FUNC_ENTRY;
	Log(LOG_PROTOCOL, 49, NULL, sock, clientAddr, client->clientID, willMsg->willMsg);
	if (client->connect_state == 2)
	{
		MQTTProtocol_setWillMsg(client, willMsg->willMsg);
		willMsg->willMsg = NULL;
		client->connect_state = 0;
		client->connected = 1;
		rc = MQTTSPacket_send_connack(client, 0); /* send response */
	}
	MQTTSPacket_free_packet(pack);
	time( &(client->lastContact) );
	FUNC_EXIT_RC(rc);
	return rc;
}
예제 #16
0
int MQTTSProtocol_handleUnsubscribes(void* pack, int sock, char* clientAddr, Clients* client)
{
	int rc = 0;
	MQTTS_Unsubscribe* unsub = (MQTTS_Unsubscribe*)pack;
	char* topicName = NULL;

	FUNC_ENTRY;
	if (unsub->flags.topicIdType == 0x01)
		topicName=MQTTSProtocol_getRegisteredTopicName(client, unsub->topicId);
	else
		topicName = unsub->topicName;

	if (topicName != NULL)
		SubscriptionEngines_unsubscribe(bstate->se, client->clientID, topicName);

	rc = MQTTSPacket_send_unsubAck(client, unsub->msgId);
	time( &(client->lastContact) );
	MQTTSPacket_free_packet(pack);
	FUNC_EXIT_RC(rc);
	return rc;
}
예제 #17
0
int main(int argc, char *argv[]) {
	HeapScan();

	MQTTS_Publish* pack = malloc(sizeof(MQTTS_Publish));
	pack->header.type = MQTTS_PUBLISH;
	pack->data = malloc(10);
	MQTTSPacket_free_packet((MQTTS_Header*)pack);

	Clients* client = malloc(sizeof(Clients));
	client->cleansession = 1;
	client->clientID = "a";
	client->keepAliveInterval = 15;
	/* MQTTSPacket_send_connect(client); */
	/*  7:4:4:1:0:15:97 */
	free(client);



	Heap_terminate();
	return 0;
}
예제 #18
0
int MQTTSProtocol_handlePubcomps(void* pack, int sock, char* clientAddr, Clients* client)
{
	int rc = 0;
	MQTTS_PubComp* pubcomp = (MQTTS_PubComp*)pack;

	FUNC_ENTRY;
	Log(LOG_PROTOCOL, 59, NULL, sock, clientAddr, client ? client->clientID : "", pubcomp->msgId);

	/* look for the message by message id in the records of outbound messages for this client */
	if (ListFindItem(client->outboundMsgs, &(pubcomp->msgId), messageIDCompare) == NULL)
	{
		/* No Dupe flag in MQTTs
		if (pubcomp->header.dup == 0)
		*/
		Log(LOG_WARNING, 50, NULL, "PUBCOMP", client->clientID, pubcomp->msgId);
	}
	else
	{
		Messages* m = (Messages*)(client->outboundMsgs->current->content);
		if (m->qos != 2)
			Log(LOG_WARNING, 51, NULL, "PUBCOMP", client->clientID, pubcomp->msgId, m->qos);
		else
		{
			if (m->nextMessageType != PUBCOMP)
				Log(LOG_WARNING, 52, NULL, "PUBCOMP", client->clientID, pubcomp->msgId);
			else
			{
				Log(TRACE_MAX, 5, NULL, client->clientID, pubcomp->msgId);
				MQTTProtocol_removePublication(m->publish);
				ListRemove(client->outboundMsgs, m);
				/* TODO: msgs counts */
				/*(++state.msgs_sent); */
			}
		}
	}
	MQTTSPacket_free_packet(pack);
	FUNC_EXIT_RC(rc);
	return rc;
}
예제 #19
0
int MQTTSProtocol_handleSubacks(void* pack, int sock, char* clientAddr, Clients* client)
{
	int rc = 0;
	MQTTS_SubAck* suback = (MQTTS_SubAck*)pack;

	FUNC_ENTRY;
	Log(LOG_PROTOCOL, 69, NULL, client->socket, client->addr, client->clientID, suback->msgId, suback->topicId,
			suback->returnCode);
	if (client->pendingSubscription == NULL ||
			suback->msgId != client->pendingSubscription->msgId)
	{
		/* TODO: unexpected suback*/
	}
	else if (suback->returnCode != MQTTS_RC_ACCEPTED)
	{
		/* TODO: rejected ack... what do we do now? */
	}
	else
	{
		if (suback->topicId > 0)
		{
			Registration* reg = malloc(sizeof(Registration));
			reg->topicName = client->pendingSubscription->topicName;
			reg->id = suback->topicId;
			ListAppend(client->registrations, reg, sizeof(reg) + strlen(reg->topicName)+1);
		}
		else
			free(client->pendingSubscription->topicName);
		free(client->pendingSubscription);
		client->pendingSubscription = NULL;
		/* TODO: could proactively call Bridge_subscribe() */
	}

	time( &(client->lastContact) );
	MQTTSPacket_free_packet(pack);
	FUNC_EXIT_RC(rc);
	return rc;
}
예제 #20
0
int MQTTSProtocol_handleRegisters(void* pack, int sock, char* clientAddr, Clients* client)
{
	int rc = 0;
	MQTTS_Register* registerPack = (MQTTS_Register*)pack;
	ListElement* elem = NULL;
	int topicId = 0;

	FUNC_ENTRY;
	Log(LOG_PROTOCOL, 51, NULL, sock, clientAddr, client ? client->clientID : "",
			registerPack->msgId, registerPack->topicId, registerPack->topicName);
	if ((elem = ListFindItem(client->registrations, registerPack->topicName, registeredTopicNameCompare)) == NULL)
	{
		topicId = (MQTTSProtocol_registerTopic(client, registerPack->topicName))->id;
		registerPack->topicName = NULL;
	}
	else
		topicId = ((Registration*)(elem->content))->id;

	rc = MQTTSPacket_send_regAck(client, registerPack->msgId, topicId, MQTTS_RC_ACCEPTED);
	time( &(client->lastContact) );
	MQTTSPacket_free_packet(pack);
	FUNC_EXIT_RC(rc);
	return rc;
}
예제 #21
0
void MQTTSProtocol_timeslice(int sock)
{
	int error;
	MQTTS_Header* pack = NULL;
	char *clientAddr = NULL ;
	Clients* client = NULL;
	struct sockaddr_in6 from;
	uint8_t *wirelessNodeId = NULL ;
	uint8_t wirelessNodeIdLen = 0 ;

	FUNC_ENTRY;
	pack = MQTTSPacket_Factory(sock, &clientAddr, (struct sockaddr *)&from, &wirelessNodeId , &wirelessNodeIdLen , &error);

	if (clientAddr)
	{
		// IF FRWDENCAP, append ":[WirelessNodeId in HEX]" to clientAddr
		if (wirelessNodeId && wirelessNodeIdLen > 0)
		{
			char* ptr = &clientAddr[strlen(clientAddr)] ;
			*(ptr++) = ':' ;
			*(ptr++) = '[' ;
			int i ;
			for (i = 0 ; i < wirelessNodeIdLen ; i++)
			{
				ptr += sprintf(ptr, "%02X", wirelessNodeId[i]);
			}
			*(ptr++) = ']' ;
			*ptr = '\0';
		}
		client = Protocol_getclientbyaddr(clientAddr);
	}

#if !defined(NO_BRIDGE)
	if (client == NULL)
		client = Protocol_getoutboundclient(sock);
#endif

	if (pack == NULL)
	{
		if (error == SOCKET_ERROR || error == UDPSOCKET_INCOMPLETE)
		{
			if (client != NULL)
			{
				client->good = 0; /* make sure we don't try and send messages to ourselves */
				//client->connected = 0;
				if (error == SOCKET_ERROR)
					Log(LOG_WARNING, 18, NULL, client->clientID, client->socket,
							Socket_getpeer(client->socket));
				else
					Log(LOG_WARNING, 19, NULL, client->clientID, client->socket,
							Socket_getpeer(client->socket));
				MQTTProtocol_closeSession(client, 0);
			}
			else
			{
				if (error == SOCKET_ERROR)
					Log(LOG_WARNING, 20, NULL, sock, Socket_getpeer(sock));
				else
					Log(LOG_WARNING, 21, NULL, sock, Socket_getpeer(sock));
				/*Socket_close(sock);*/
			}
		}
	}
	else if (pack->header.type != MQTTS_CONNECT && handle_packets[(int)pack->header.type] == NULL)
	{
			Log(LOG_WARNING, 22, NULL, pack->header.type, handle_packets[(int)pack->header.type]);
			MQTTSPacket_free_packet(pack);
	}
	else if (client == NULL &&  pack->header.type != MQTTS_CONNECT &&
			pack->header.type != MQTTS_ADVERTISE && pack->header.type != MQTTS_SEARCHGW &&
			(pack->header.type != MQTTS_PUBLISH || ((MQTTS_Publish*)pack)->flags.QoS != 3))
	{
			Log(LOG_WARNING, 23, NULL, sock, Socket_getpeer(sock), MQTTSPacket_name(pack->header.type));
			MQTTSPacket_free_packet(pack);
	}
	else if ( pack->header.type == MQTTS_CONNECT ) {
		MQTTSProtocol_handleConnects(pack, sock, clientAddr, client, wirelessNodeId , wirelessNodeIdLen) ;
	}
	else
	{
		(*handle_packets[(int)pack->header.type])(pack, sock, clientAddr, client);
		/* TODO:
		 *  - error handling
		 *  - centralise calls to time( &(c->lastContact) ); (currently in each _handle* function
		 */
	}
	FUNC_EXIT;
}
예제 #22
0
int MQTTSProtocol_handleConnacks(void* pack, int sock, char* clientAddr)
{
	MQTTS_Connack* connack = (MQTTS_Connack*)pack;
	int rc = 0;
	Clients* client = NULL;
	BridgeConnections* bc = Bridge_getBridgeConnection(sock);

	FUNC_ENTRY;
	if (bc == NULL)
	{
		rc = SOCKET_ERROR;
		goto exit;
	}

	if (bc->primary && bc->primary->socket == sock)
		client = bc->primary;
	else
		client = bc->backup;

	if (connack->returnCode != MQTTS_RC_ACCEPTED)
	{
		if (client)
		{
			if (client->noLocal == 1)
				client->noLocal = 0;
			else
				Log(LOG_WARNING, 132, NULL, connack->returnCode, client->clientID);
			MQTTProtocol_closeSession(client, 0);
		}
		else
			Socket_close(sock);
	}
	else if (client)
	{
		ListElement* addr = bc->cur_address;

		if (client == bc->primary && bc->round_robin == 0)
			addr = bc->addresses->first;
		Log(LOG_INFO, 133, NULL, bc->name, (char*)(addr->content));

		client->connect_state = 3;  //should have been 2 before
		bc->last_connect_result = connack->returnCode;
		(bc->no_successful_connections)++;
		client->connected = 1;
		client->good = 1;
		client->ping_outstanding = 0;
		time(&(client->lastContact));


		if (client->will)
		{
			Publish pub;
			Messages* m = NULL;
			MQTTProtocol_sys_publish(client->will->topic, "1");
			pub.payload = "1";
			pub.payloadlen = 1;
			pub.topic = client->will->topic;
			MQTTProtocol_startOrQueuePublish(client, &pub, 0, client->will->retained, &m);
		}


		if (client == bc->primary &&
			(bc->backup && (bc->backup->connected == 1 || bc->backup->connect_state != 0)))
		{
			Log(LOG_INFO, 134, NULL, (char*)(bc->cur_address->content));
			MQTTProtocol_closeSession(bc->backup, 0);
		}

		//if (bc->addresses->count > 1 || bc->no_successful_connections == 1)
		Bridge_subscribe(bc, client);
	}

	//Clients* client = Protocol_getclientbyaddr(clientAddr);

	MQTTSPacket_free_packet(pack);

exit:
	FUNC_EXIT_RC(rc);
	return rc;
}
예제 #23
0
int MQTTSProtocol_startPublishCommon(Clients* client, Publish* mqttPublish, int dup, int qos, int retained)
{
	int rc = 0;
	Registration* registration = NULL;
	MQTTS_Publish* pub = NULL;

	FUNC_ENTRY;
	pub = malloc(sizeof(MQTTS_Publish));
	memset(pub, '\0', sizeof(MQTTS_Publish));
	if (strlen(mqttPublish->topic) > 2 &&
			(registration = MQTTSProtocol_getRegisteredTopicId(client, mqttPublish->topic)) == 0 && (qos != 3))
	{
		/* TODO: Logic elsewhere _should_ mean this case never happens... */
		/*printf("I want to send a msg to %s on topic %s but it isn't registered\n",client->clientID,mqttPublish->topic); */
	}
	else
	{
		pub->header.type = MQTTS_PUBLISH;
		pub->flags.QoS = qos;
		pub->flags.retain = retained;
		pub->flags.dup = dup;
		pub->msgId = mqttPublish->msgId;
		pub->data = mqttPublish->payload;
		pub->shortTopic = NULL;

		if (strlen(mqttPublish->topic) > 2 && qos == 3)
		{
			pub->topicId = strlen(mqttPublish->topic);
			pub->dataLen = mqttPublish->payloadlen + strlen(mqttPublish->topic);

			pub->data = malloc(pub->dataLen);
			memcpy(pub->data, mqttPublish->topic, pub->topicId);
			memcpy(&pub->data[pub->topicId], mqttPublish->payload, mqttPublish->payloadlen);

			pub->flags.topicIdType = MQTTS_TOPIC_TYPE_NORMAL;
		}
		else if (mqttPublish->payloadlen > 65535)
		{
			/* TODO: add a message for truncated payload */
			/* printf("Truncating a %d byte message sent to %s on topic %s\n",mqttPublish->payloadlen, client->clientID, mqttPublish->topic);*/
			pub->dataLen = 65535;
		}
		else
			pub->dataLen = mqttPublish->payloadlen;

		pub->header.len = 7 + pub->dataLen;
		if (strlen(mqttPublish->topic) < 3)
		{
			pub->flags.topicIdType = MQTTS_TOPIC_TYPE_SHORT;
			pub->shortTopic = mqttPublish->topic;
		}
		else if (qos != 3)
		{
			pub->topicId = registration->id;
			pub->flags.topicIdType = registration->topicIdType;
		}

		rc = MQTTSPacket_send_publish(client, pub);

		if (pub->data == mqttPublish->payload)
			pub->data = NULL;
		pub->shortTopic = NULL;
	}
	MQTTSPacket_free_packet((MQTTS_Header*)pub);
	FUNC_EXIT_RC(rc);
	return rc;
}
예제 #24
0
int MQTTSProtocol_handlePublishes(void* pack, int sock, char* clientAddr, Clients* client)
{
	int rc = 0;
	char* topicName = NULL, *expandedPreDefinedTopicName = NULL;
	MQTTS_Publish* pub = NULL;

	FUNC_ENTRY;
	pub = (MQTTS_Publish*)pack;
	Log(LOG_PROTOCOL, 55, NULL, sock, clientAddr, client ? client->clientID : "",
			pub->msgId, pub->flags.QoS, pub->flags.retain);

	// Normal - registered topic
	if (pub->flags.topicIdType == MQTTS_TOPIC_TYPE_NORMAL && client != NULL && pub->topicId != 0)
	{
		/* copy the topic name as it will be freed later */
		char* name = MQTTSProtocol_getRegisteredTopicName(client, pub->topicId);
		if (name)
		{
			topicName = malloc(strlen(name) + 1);
			strcpy(topicName, name);
		}
	}
	// Pre-defined topics
	else if (pub->flags.topicIdType == MQTTS_TOPIC_TYPE_PREDEFINED && client != NULL && pub->topicId != 0)
	{
		/* copy the topic name as it will be freed later */
		char *origPreDefinedTopicName = MQTTSProtocol_getPreDefinedTopicName(client, pub->topicId) ;
		if (origPreDefinedTopicName)
		{
			expandedPreDefinedTopicName = MQTTSProtocol_replaceTopicNamePlaceholders(client, origPreDefinedTopicName) ;
		}

		// If original and expanded predef topic names are same, use expanded
		// while it is already a copy of orig name
		if (strcmp(origPreDefinedTopicName, expandedPreDefinedTopicName) == 0)
		{
			topicName = expandedPreDefinedTopicName ;
		} else {
			topicName = malloc(strlen(origPreDefinedTopicName)+1);
			strcpy(topicName, origPreDefinedTopicName);
		}
	}
	// Short topic names
	else if (pub->flags.topicIdType == MQTTS_TOPIC_TYPE_SHORT && pub->shortTopic != NULL)
	{
		topicName = pub->shortTopic;
		pub->shortTopic = NULL; /* will be freed in Protocol_handlePublishes */
	}

	// If topic name not found send PubAck with Rejected - Invalid topic ID
	if (topicName == NULL)
	{
		rc = MQTTSPacket_send_puback(client, pub->topicId , pub->msgId, MQTTS_RC_REJECTED_INVALID_TOPIC_ID);
	}
	else
	{
		Publish* publish = malloc(sizeof(Publish));
		publish->header.bits.type = PUBLISH;
		publish->header.bits.qos = pub->flags.QoS;
		publish->header.bits.retain = pub->flags.retain;
		publish->header.bits.dup = pub->flags.dup;
		publish->msgId = pub->msgId;
		publish->payload = pub->data;
		publish->payloadlen = pub->dataLen;
		publish->topic = topicName;
		rc = Protocol_handlePublishes(publish, sock, client, client ? client->clientID : clientAddr, pub->topicId);

		// If predefined topic Id and predefined topic name contains [ClientId]
		// publish message to expanded topic name too.
		if ( pub->flags.topicIdType == MQTTS_TOPIC_TYPE_PREDEFINED && topicName != expandedPreDefinedTopicName)
		{
			publish = malloc(sizeof(Publish));
			publish->header.bits.type = PUBLISH;
			publish->header.bits.qos = pub->flags.QoS;
			publish->header.bits.retain = pub->flags.retain;
			publish->header.bits.dup = pub->flags.dup;
			publish->msgId = pub->msgId;
			publish->payload = pub->data;
			publish->payloadlen = pub->dataLen;
			publish->topic = expandedPreDefinedTopicName;
			rc = Protocol_handlePublishes(publish, sock, client, client ? client->clientID : clientAddr, pub->topicId);
		}
	}

	if (client != NULL)
		time( &(client->lastContact) );

	MQTTSPacket_free_packet(pack);

	FUNC_EXIT_RC(rc);
	return rc;
}
예제 #25
0
int MQTTSProtocol_handleConnects(void* pack, int sock, char* clientAddr, Clients* client, uint8_t* wirelessNodeId , uint8_t wirelessNodeIdLen)
{
	MQTTS_Connect* connect = (MQTTS_Connect*)pack;
	Listener* list = NULL;
	int terminate = 0;
	Node* elem = NULL;
	int rc = 0;
	int existingClient = 0;

	FUNC_ENTRY;
	Log(LOG_PROTOCOL, 39, NULL, sock, clientAddr, client ? client->clientID : "", connect->flags.cleanSession);

	if (bstate->clientid_prefixes->count > 0 &&
		!ListFindItem(bstate->clientid_prefixes, connect->clientID, clientPrefixCompare))
	{
		Log(LOG_WARNING, 31, NULL, connect->clientID);
		terminate = 1;
	}
	else
	{
		list = Socket_getParentListener(sock);
		if (list->max_connections > -1 &&
				list->connections->count > list->max_connections)
		{
			/* TODO: why is this commented out? delete if not needed
			//MQTTPacket_send_connack(3, sock);
			*/
			Log(LOG_WARNING, 141, NULL, connect->clientID, list->max_connections, list->port);
			terminate = 1;

		}
		else if (connect->protocolID != 1)
		{
			Log(LOG_WARNING, 32, NULL, "MQTT-S", connect->protocolID);
			/* TODO: why is this commented out? delete if not needed
			//MQTTPacket_send_connack(1, sock);
			 */
			terminate = 1;
		}
	}

	if (terminate)
	{
		/*TODO: process the terminate*/
		MQTTSPacket_free_packet(pack);
		goto exit;
	}

	if (client != NULL && !strcmp(client->clientID, connect->clientID))
	{
		/* Connect for a new client id on a used addr
		 * TODO: clean out 'old' Client (that may be 'connected')
		 */
	}

	elem = TreeFindIndex(bstate->mqtts_clients, connect->clientID, 1);
	if (elem == NULL)
	{
		client = TreeRemoveKey(bstate->disconnected_mqtts_clients, connect->clientID);
		if (client == NULL) /* this is a totally new connection */
		{
			/* Brand new client connection */
			int i;
		
			client = malloc(sizeof(Clients));
			memset(client, '\0', sizeof(Clients));
			client->protocol = PROTOCOL_MQTTS;
			client->outboundMsgs = ListInitialize();
			client->inboundMsgs = ListInitialize();
			for (i = 0; i < PRIORITY_MAX; ++i)
				client->queuedMsgs[i] = ListInitialize();
			client->registrations = ListInitialize();
			client->noLocal = 0; /* (connect->version == PRIVATE_PROTOCOL_VERSION) ? 1 : 0; */
			client->clientID = connect->clientID;
			connect->clientID = NULL; /* don't want to free this space as it is being used in the clients tree below */
			// Set Wireless Node ID if exists
			if ( wirelessNodeId == NULL)
			{
				client->wirelessNodeId = NULL ;
				client->wirelessNodeIdLen = 0 ;
			}
			else
			{
				client->wirelessNodeId = malloc((sizeof(uint8_t) * wirelessNodeIdLen)) ;
				memcpy( client->wirelessNodeId , wirelessNodeId , sizeof(uint8_t) * wirelessNodeIdLen) ;
				client->wirelessNodeIdLen = wirelessNodeIdLen ;
			}
		} // // client == NULL
		else /* there is an existing disconnected client */
		{
			/* Reconnect of a disconnected client */
			free(client->addr);
			client->connect_state = 0;
			client->connected = 0; /* Do not connect until we know the connack has been sent */

			// Delete Wireless Node ID if exists in existing client
			if ( wirelessNodeId == NULL)
			{
				if ( client->wirelessNodeId != NULL)
					free( client->wirelessNodeId )  ;
				client->wirelessNodeId = NULL ;
				client->wirelessNodeIdLen = 0 ;
			}
			else
			// Replace existing Wireless Node ID with value from current connect packet
			{
				if ( client->wirelessNodeId != NULL)
					free ( client->wirelessNodeId )  ;
				client->wirelessNodeId = malloc((sizeof(uint8_t) * wirelessNodeIdLen)) ;
				memcpy( client->wirelessNodeId , wirelessNodeId , sizeof(uint8_t) * wirelessNodeIdLen) ;
				client->wirelessNodeIdLen = wirelessNodeIdLen ;
			}
		} // client != NULL
		client->good = 1; /* good is set to 0 in disconnect, so we need to reset it here */
		client->keepAliveInterval = connect->keepAlive;
		client->cleansession = connect->flags.cleanSession;
		client->socket = sock;
		client->addr = malloc(strlen(clientAddr)+1);
		strcpy(client->addr, clientAddr);
		TreeAdd(bstate->mqtts_clients, client, sizeof(Clients) + strlen(client->clientID)+1 + 3*sizeof(List));

		if (client->cleansession)
			MQTTProtocol_removeAllSubscriptions(client->clientID); /* clear any persistent subscriptions */

		if (connect->flags.will)
		{
			client->connect_state = 1;
			rc = MQTTSPacket_send_willTopicReq(client);
		}
		else
		{
			client->connected = 1;
			rc = MQTTSPacket_send_connack(client, 0); /* send response */
		}
	}
	else
	{
		/* Reconnect of a connected client */
		client = (Clients*)(elem->content);
		if (client->connected)
		{
			Log(LOG_INFO, 34, NULL, connect->clientID, clientAddr);
			if (client->socket != sock)
				Socket_close(client->socket);
		}
		client->socket = sock;
		client->connected = 0; /* Do not connect until we know the connack has been sent */
		client->connect_state = 0;

		// Delete Wireless Node ID if exists in existing client
		if ( wirelessNodeId == NULL)
		{
			if ( client->wirelessNodeId != NULL)
				free( client->wirelessNodeId )  ;
			client->wirelessNodeId = NULL ;
			client->wirelessNodeIdLen = 0 ;
		}
		else
		// Replace existing Wireless Node ID with value from current connect packet
		{
			if ( client->wirelessNodeId != NULL)
				free ( client->wirelessNodeId )  ;
			client->wirelessNodeId = malloc((sizeof(uint8_t) * wirelessNodeIdLen)) ;
			memcpy( client->wirelessNodeId , wirelessNodeId , sizeof(uint8_t) * wirelessNodeIdLen) ;
			client->wirelessNodeIdLen = wirelessNodeIdLen ;
		}

		client->good = 1;
		if (client->addr != NULL)
			free(client->addr);
		client->addr = malloc(strlen(clientAddr)+1);
		strcpy(client->addr, clientAddr);

		client->cleansession = connect->flags.cleanSession;
		if (client->cleansession)
		{
			int i;
			MQTTProtocol_removeAllSubscriptions(client->clientID);
			/* empty pending message lists */
			MQTTProtocol_emptyMessageList(client->outboundMsgs);
			MQTTProtocol_emptyMessageList(client->inboundMsgs);
			for (i = 0; i < PRIORITY_MAX; ++i)
				MQTTProtocol_emptyMessageList(client->queuedMsgs[i]);
			MQTTProtocol_clearWill(client);
		}
		/* registrations are always cleared */
		MQTTSProtocol_emptyRegistrationList(client->registrations);
		
		/* have to remove and re-add client so it is in the right order for new socket */
		if (client->socket != sock)
		{
			TreeRemoveNodeIndex(bstate->mqtts_clients, elem, 1);
			TreeRemoveKeyIndex(bstate->mqtts_clients, &client->socket, 0);
			client->socket = sock;
			TreeAdd(bstate->mqtts_clients, client, sizeof(Clients) + strlen(client->clientID)+1 + 3*sizeof(List));
		}

		client->keepAliveInterval = connect->keepAlive;
		client->pendingRegistration = NULL;
#if !defined(NO_BRIDGE)
		client->pendingSubscription = NULL;
#endif

		if (connect->flags.will)
		{
			client->connect_state = 1;
			rc = MQTTSPacket_send_willTopicReq(client);
		}
		else
		{
			client->connected = 1;
			rc = MQTTSPacket_send_connack(client,0); /* send response */
		}
	}
	
	if (existingClient)
		MQTTProtocol_processQueued(client);

	Log(LOG_INFO, 0, "Client connected to udp port %d from %s (%s)", list->port, client->clientID, clientAddr);

	MQTTSPacket_free_packet(pack);
	time( &(client->lastContact) );
exit:
	FUNC_EXIT_RC(rc);
	return rc;
}