/**
 * Send an MQTT unsubscribe packet down a socket.
 * @param topics list of topics
 * @param msgid the MQTT message id to use
 * @param dup boolean - whether to set the MQTT DUP flag
 * @param socket the open socket to send the data to
 * @param clientID the string client identifier, only used for tracing
 * @return the completion code (e.g. TCPSOCKET_COMPLETE)
 */
int MQTTPacket_send_unsubscribe(List* topics, int msgid, int dup, networkHandles* net, const char* clientID)
{
	Header header;
	char *data, *ptr;
	int rc = -1;
	ListElement *elem = NULL;
	int datalen;

	FUNC_ENTRY;
	header.bits.type = UNSUBSCRIBE;
	header.bits.dup = dup;
	header.bits.qos = 1;
	header.bits.retain = 0;

	datalen = 2 + topics->count * 2; /* utf length == 2 */
	while (ListNextElement(topics, &elem))
		datalen += (int)strlen((char*)(elem->content));
	ptr = data = malloc(datalen);

	writeInt(&ptr, msgid);
	elem = NULL;
	while (ListNextElement(topics, &elem))
		writeUTF(&ptr, (char*)(elem->content));
	rc = MQTTPacket_send(net, header, data, datalen, 1);
	Log(LOG_PROTOCOL, 25, NULL, net->socket, clientID, msgid, rc);
	if (rc != TCPSOCKET_INTERRUPTED)
		free(data);
	FUNC_EXIT_RC(rc);
	return rc;
}
Exemple #2
0
/**
 *  Continue any outstanding writes for a socket set
 *  @param pwset the set of sockets
 *  @return completion code
 */
int Socket_continueWrites(fd_set* pwset)
{
	int rc1 = 0;
	ListElement* curpending = s.write_pending->first;

	FUNC_ENTRY;
	while (curpending)
	{
		int socket = *(int*)(curpending->content);
		if (FD_ISSET(socket, pwset) && Socket_continueWrite(socket))
		{
			if (!SocketBuffer_writeComplete(socket))
				Log(LOG_SEVERE, -1, "Failed to remove pending write from socket buffer list");
			FD_CLR(socket, &(s.pending_wset));
			if (!ListRemove(s.write_pending, curpending->content))
			{
				Log(LOG_SEVERE, -1, "Failed to remove pending write from list");
				ListNextElement(s.write_pending, &curpending);
			}
			curpending = s.write_pending->current;
						
			if (writecomplete)
				(*writecomplete)(socket);
		}
		else
			ListNextElement(s.write_pending, &curpending);
	}
	FUNC_EXIT_RC(rc1);
	return rc1;
}
/**
 * MQTT retry protocol and socket pending writes processing.
 * @param now current time
 * @param doRetry boolean - retries as well as pending writes?
 * @param regardless boolean - retry packets regardless of retry interval (used on reconnect)
 */
void MQTTProtocol_retry(time_t now, int doRetry, int regardless)
{
	ListElement* current = NULL;

	FUNC_ENTRY;
	ListNextElement(bstate->clients, &current);
	/* look through the outbound message list of each client, checking to see if a retry is necessary */
	while (current)
	{
		Clients* client = (Clients*)(current->content);
		ListNextElement(bstate->clients, &current);
		if (client->connected == 0)
			continue;
		if (client->good == 0)
		{
			MQTTProtocol_closeSession(client, 1);
			continue;
		}
		if (Socket_noPendingWrites(client->net.socket) == 0)
			continue;
		if (doRetry)
			MQTTProtocol_retries(now, client, regardless);
	}
	FUNC_EXIT;
}
Exemple #4
0
/**
 * Send an MQTT unsubscribe packet down a socket.
 * @param topics list of topics
 * @param msgid the MQTT message id to use
 * @param dup boolean - whether to set the MQTT DUP flag
 * @param socket the open socket to send the data to
 * @param clientID the string client identifier, only used for tracing
 * @return the completion code (e.g. TCPSOCKET_COMPLETE)
 */
int MQTTPacket_send_unsubscribe(List* topics, int msgid, int dup, int socket, char* clientID)
{
	Header header;
	char *data, *ptr;
	int rc = -1;
	ListElement *elem = NULL;
	int datalen;

	FUNC_ENTRY;
	header.bits.type = UNSUBSCRIBE;
	header.bits.dup = dup;
	header.bits.qos = 1;
	header.bits.retain = 0;

	datalen = 2 + topics->count * 2; // utf length == 2
	while (ListNextElement(topics, &elem))
		datalen += strlen((char*)(elem->content));
	ptr = data = malloc(datalen);

	writeInt(&ptr, msgid);
	elem = NULL;
	while (ListNextElement(topics, &elem))
		writeUTF(&ptr, (char*)(elem->content));
	rc = MQTTPacket_send(socket, header, data, datalen);
	Log(LOG_PROTOCOL, 25, NULL, socket, clientID, msgid, rc);
	free(data);
	FUNC_EXIT_RC(rc);
	return rc;
}
Exemple #5
0
/**
 * Write the contents of the stored trace to a stream
 * @param dest string which contains a file name or the special strings stdout or stderr
 */
int Log_dumpTrace(char* dest)
{
	FILE* file = NULL;
	ListElement* cur_trace_entry = NULL;
	const int msgstart = 7;
	int rc = -1;
	int trace_queue_index = 0;

	if ((file = Log_destToFile(dest)) == NULL)
	{
		Log(LOG_ERROR, 9, NULL, "trace", dest, "trace entries");
		goto exit;
	}

	fprintf(file, "=========== Start of trace dump ==========\n");
	/* Interleave the log and trace entries together appropriately */
	ListNextElement(trace_buffer, &cur_trace_entry);
	trace_queue_index = start_index;
	if (trace_queue_index == -1)
		trace_queue_index = next_index;
	else
	{
		Log_formatTraceEntry(&trace_queue[trace_queue_index++]);
		if (trace_queue_index == trace_settings.max_trace_entries)
			trace_queue_index = 0;
	}
	while (cur_trace_entry || trace_queue_index != next_index)
	{
		if (cur_trace_entry && trace_queue_index != -1)
		{	/* compare these timestamps */
			if (Log_compareEntries((char*)cur_trace_entry->content, msg_buf) > 0)
				cur_trace_entry = NULL;
		}

		if (cur_trace_entry)
		{
			fprintf(file, "%s\n", &((char*)(cur_trace_entry->content))[msgstart]);
			ListNextElement(trace_buffer, &cur_trace_entry);
		}
		else
		{
			fprintf(file, "%s\n", &msg_buf[7]);
			if (trace_queue_index != next_index)
			{
				Log_formatTraceEntry(&trace_queue[trace_queue_index++]);
				if (trace_queue_index == trace_settings.max_trace_entries)
					trace_queue_index = 0;
			}
		}
	}
	fprintf(file, "========== End of trace dump ==========\n\n");
	if (file != stdout && file != stderr && file != NULL)
		fclose(file);
	rc = 0;
exit:
	return rc;
}
/**
 * MQTT protocol keepAlive processing.  Sends PINGREQ packets as required.
 * @param now current time
 */
void MQTTProtocol_keepalive(time_t now)
{
	ListElement* current = NULL;

	FUNC_ENTRY;
	ListNextElement(bstate->clients, &current);
	while (current)
	{
		Clients* client =	(Clients*)(current->content);
		ListNextElement(bstate->clients, &current);
#if !defined(NO_BRIDGE)
		if (client->outbound)
		{
			if (client->connected && client->keepAliveInterval > 0
					&& (difftime(now, client->lastContact) >= client->keepAliveInterval))
			{
				if (client->ping_outstanding)
				{
					Log(LOG_INFO, 143, NULL, client->keepAliveInterval, client->clientID);
					MQTTProtocol_closeSession(client, 1);
				}
				else
				{
#if defined(MQTTS)
					if (client->protocol == PROTOCOL_MQTTS)
					{
						int rc = MQTTSPacket_send_pingReq(client);
						if (rc == SOCKET_ERROR)
							MQTTProtocol_closeSession(client, 1);
					}
					else
#endif
						MQTTPacket_send_pingreq(client->socket, client->clientID);
					client->lastContact = now;
					client->ping_outstanding = 1;
				}
			}
		}
		else
#endif
		if (client->connected && client->keepAliveInterval > 0)
		{ /* zero keepalive interval means never disconnect */
			int threshold = client->keepAliveInterval + min((client->keepAliveInterval / 2), 60);
					
			if (difftime(now, client->lastContact) > threshold)
			{
				Log(LOG_INFO, 24, NULL, client->keepAliveInterval, client->clientID);
#if defined(MQTTMP)
				if (client->protocol == PROTOCOL_MQTT_MP)
					MQTTMPProtocol_closeSession(client,1);
#endif
				MQTTProtocol_closeSession(client, 1);
			}
		}
	}
	FUNC_EXIT;
}
Exemple #7
0
/**
 * See if any pending writes have been completed, and cleanup if so.
 * Cleaning up means removing any publication data that was stored because the write did
 * not originally complete.
 */
void MQTTProtocol_checkPendingWrites()
{
	FUNC_ENTRY;
	if (state.pending_writes.count > 0)
	{
		ListElement* le = state.pending_writes.first;
		while (le)
		{
			pending_write* pw = (pending_write*)(le->content);
			if (Socket_noPendingWrites(pw->socket))
			{
				Clients* client = pw->client;

				MQTTProtocol_removePublication(pw->p);
				state.pending_writes.current = le;
				ListRemove(&(state.pending_writes), le->content); /* does NextElement itself */
				le = state.pending_writes.current;
				/* now we might be able to write the next message in the queue */
				MQTTProtocol_processQueued(client);
			}
			else
				ListNextElement(&(state.pending_writes), &le);
		}
	}
	FUNC_EXIT;
}
Exemple #8
0
/**
 *  Close a socket and remove it from the select list.
 *  @param socket the socket to close
 *  @return completion code
 */
void Socket_close(int socket)
{
	FUNC_ENTRY;
	Socket_close_only(socket);
	FD_CLR(socket, &(s.rset_saved));
	if (FD_ISSET(socket, &(s.pending_wset)))
		FD_CLR(socket, &(s.pending_wset));
	if (s.cur_clientsds != NULL && *(int*)(s.cur_clientsds->content) == socket)
		s.cur_clientsds = s.cur_clientsds->next;
	ListRemoveItem(s.connect_pending, &socket, intcompare);
	ListRemoveItem(s.write_pending, &socket, intcompare);
	SocketBuffer_cleanup(socket);

	if (ListRemoveItem(s.clientsds, &socket, intcompare))
		Log(TRACE_MIN, -1, "Removed socket %d", socket);
	else
		Log(TRACE_MIN, -1, "Failed to remove socket %d", socket);
	if (socket + 1 >= s.maxfdp1)
	{
		/* now we have to reset s.maxfdp1 */
		ListElement* cur_clientsds = NULL;

		s.maxfdp1 = 0;
		while (ListNextElement(s.clientsds, &cur_clientsds))
			s.maxfdp1 = max(*((int*)(cur_clientsds->content)), s.maxfdp1);
		++(s.maxfdp1);
		Log(TRACE_MAX, -1, "Reset max fdp1 to %d", s.maxfdp1);
	}
	FUNC_EXIT;
}
Exemple #9
0
/**
 * MQTTs protocol advertise processing.
 */
void MQTTSProtocol_housekeeping()
{
	ListElement* current = NULL;
	time_t now = 0;

	FUNC_ENTRY;
	/* for each listener, if the advertise parameter is set and the interval has expired,
	 * call send_advertise
	 */
	while (ListNextElement(bstate->listeners, &current))
	{
		Listener *listener = (Listener*)current->content;
		if (listener->advertise)
		{
			if (now == 0)
				time(&(now));
			if (difftime(now, listener->advertise->last) > listener->advertise->interval)
			{
				int rc = 0;
				rc = MQTTSPacket_send_advertise(listener->socket,
						listener->advertise->address, listener->advertise->gateway_id,
						listener->advertise->interval);
				listener->advertise->last = now;
			}
		}
	}
	FUNC_EXIT;
}
Exemple #10
0
int MQTTClient_getPendingDeliveryTokens(MQTTClient handle, MQTTClient_deliveryToken **tokens)
{
	int rc = MQTTCLIENT_SUCCESS;
	MQTTClients* m = handle;
	*tokens = NULL;

	FUNC_ENTRY;
	Thread_lock_mutex(mqttclient_mutex);

	if (m == NULL)
	{
		rc = MQTTCLIENT_FAILURE;
		goto exit;
	}

	if (m->c && m->c->outboundMsgs->count > 0)
	{
		ListElement* current = NULL;
		int count = 0;

		*tokens = malloc(sizeof(MQTTClient_deliveryToken) * (m->c->outboundMsgs->count + 1));
		/*Heap_unlink(__FILE__, __LINE__, *tokens);*/
		while (ListNextElement(m->c->outboundMsgs, &current))
		{
			Messages* m = (Messages*)(current->content);
			(*tokens)[count++] = m->msgid;
		}
		(*tokens)[count] = -1;
	}

exit:
	Thread_unlock_mutex(mqttclient_mutex);
	FUNC_EXIT_RC(rc);
	return rc;
}
Exemple #11
0
/**
 * Terminate the socket module for both in an outbound communications
 */
void Socket_terminate()
{
#if !defined(SINGLE_LISTENER)
	ListElement* current = NULL;
#if defined(USE_POLL)
	struct socket_info* si = NULL;
#endif

	FUNC_ENTRY;
	while (ListNextElement(s.listeners, &current))
	{
		Listener* listener = (Listener*)(current->content);
		Socket_close_only(listener->socket);
#if defined(USE_POLL)
		if ((si = TreeRemoveKey(s.fds_tree, &listener->socket)) == NULL)
			Log(LOG_WARNING, 13, "Failed to remove socket %d", listener->socket);
		else
			free(si);
#endif
	}
#else
	FUNC_ENTRY;
	Socket_close_only(s.mySocket);
#endif
	Socket_outTerminate();
	FUNC_EXIT;
}
Exemple #12
0
/**
 * Dump the state of the heap
 * @param file file handle to dump the heap contents to
 * @return completion code, success == 0
 */
int HeapDump(FILE* file)
{
	int rc = 0;

	if (file != NULL)
	{
		ListElement* current = NULL;
		while (ListNextElement(&heap, &current))
		{
			storageElement* s = (storageElement*)(current->content);
			int* i = s->ptr;
			unsigned int j;

			if (fwrite(&(s->ptr), sizeof(int), 1, file) != 1)
				rc = -1;
			if (fwrite(&(s->size), sizeof(int), 1, file) != 1)
				rc = -1;
			for (j = 0; j < s->size; j++)
			{
				if (fwrite(i, sizeof(int), 1, file) != -1)
					rc = -1;
				i++;
			}
		}
	}
	return rc;
}
Exemple #13
0
/**
 * Send an MQTT subscribe packet down a socket.
 * @param topics list of topics
 * @param qoss list of corresponding QoSs
 * @param msgid the MQTT message id to use
 * @param dup boolean - whether to set the MQTT DUP flag
 * @param socket the open socket to send the data to
 * @param clientID the string client identifier, only used for tracing
 * @return the completion code (e.g. TCPSOCKET_COMPLETE)
 */
int MQTTPacket_send_subscribe(List* topics, List* qoss, uint64_t msgid, int dup, networkHandles* net, const char* clientID)
{
	Header header;
	char *data, *ptr;
	int rc = -1;
	ListElement *elem = NULL, *qosElem = NULL;
	int datalen;
    int mqtt_version = get_client_mqtt_version_from_network_handler(net);

	FUNC_ENTRY;
	header.bits.type = SUBSCRIBE;
	header.bits.dup = dup;
	header.bits.qos = 1;
	header.bits.retain = 0;

    //8 -> 64 bit msg id. if the msgid is 2 Byte, datalen will be decresed
	datalen = 8 + topics->count * 3; // utf length + char qos == 3
	while (ListNextElement(topics, &elem))
		datalen += strlen((char*)(elem->content));

	ptr = data = malloc(datalen);

    if(mqtt_version == MQTTVERSION_YUNBA_3_1)
    {
        writeInt64(&ptr, msgid);
    }else{
        msgid = (int)msgid;
        writeInt(&ptr, msgid);
        //make sure the datalen is adjusted
        datalen -= 6;
    }
	elem = NULL;
	while (ListNextElement(topics, &elem))
	{
		ListNextElement(qoss, &qosElem);
		writeUTF(&ptr, (char*)(elem->content));
		writeChar(&ptr, *(int*)(qosElem->content));
	}
	rc = MQTTPacket_send(net, header, data, datalen, 1);
	Log(LOG_PROTOCOL, 22, NULL, net->socket, clientID, msgid, rc);
	if (rc != TCPSOCKET_INTERRUPTED)
		free(data);
	FUNC_EXIT_RC(rc);
	return rc;
}
Exemple #14
0
int main(int argc, char *argv[])
{
	int i, *ip, *todelete;
	ListElement* current = NULL;
	List* l = ListInitialize();
	printf("List initialized\n");

	for (i = 0; i < 10; i++)
	{
		ip = malloc(sizeof(int));
		*ip = i;
		ListAppend(l, (void*)ip, sizeof(int));
		if (i==5)
			todelete = ip;
		printf("List element appended %d\n",  *((int*)(l->last->content)));
	}

	printf("List contents:\n");
	current = NULL;
	while (ListNextElement(l, &current) != NULL)
		printf("List element: %d\n", *((int*)(current->content)));

	printf("List contents in reverse order:\n");
	current = NULL;
	while (ListPrevElement(l, &current) != NULL)
		printf("List element: %d\n", *((int*)(current->content)));

	//if ListFindItem(l, *ip, intcompare)->content

	printf("List contents having deleted element %d:\n", *todelete);
	ListRemove(l, todelete);
	current = NULL;
	while (ListNextElement(l, &current) != NULL)
		printf("List element: %d\n", *((int*)(current->content)));

	i = 9;
	ListRemoveItem(l, &i, intcompare);
	printf("List contents having deleted another element, %d, size now %d:\n", i, l->size);
	current = NULL;
	while (ListNextElement(l, &current) != NULL)
		printf("List element: %d\n", *((int*)(current->content)));

	ListFree(l);
	printf("List freed\n");
}
Exemple #15
0
void SocketBuffer_terminate(void)
{
    ListElement* cur = NULL;
    ListEmpty(&writes);
    
    FUNC_ENTRY;
    while (ListNextElement(queues, &cur)) { free(((socket_queue*)(cur->content))->buf); }
    ListFree(queues);
    SocketBuffer_freeDefQ();
    FUNC_EXIT;
}
Exemple #16
0
/**
 * Remove any QoS 0 messages from a message list.
 * This is used to clean up a session for a client which is non-cleansession.  QoS 0 messages
 * are non-persistent, so they are removed from the queue.
 * @param msgList the message list to empty
 */
void MQTTProtocol_removeQoS0Messages(List* msgList)
{
	ListElement* current = NULL;

	FUNC_ENTRY;
	ListNextElement(msgList, &current);
	while (current)
	{
		Messages* m = (Messages*)(current->content);
		if (m->qos == 0)
		{
			MQTTProtocol_removePublication(m->publish);
			msgList->current = current;
			ListRemove(msgList, current->content);
			current = msgList->current;
		}
		else
			ListNextElement(msgList, &current);
	}
	FUNC_EXIT;
}
Exemple #17
0
void HeapScan()
{
	ListElement* current = NULL;
	Log(LOG_INFO, Messages_get(101), state.current_size);
	while (ListNextElement(&heap, &current))
	{
		storageElement* s = (storageElement*)(current->content);
		Log(LOG_INFO, Messages_get(102), s->size, s->line, s->file, s->ptr);
		Log(LOG_INFO, Messages_get(103), (10 > s->size) ? s->size : 10, s->ptr);
	}
	Log(LOG_INFO, Messages_get(104));
}
Exemple #18
0
void MQTTSProtocol_emptyRegistrationList(List* regList)
{
	ListElement* current = NULL;

	FUNC_ENTRY;
	while (ListNextElement(regList, &current))
	{
		Registration* m = (Registration*)(current->content);
		free(m->topicName);
	}
	ListEmpty(regList);
	FUNC_EXIT;
}
/**
 * MQTT protocol keepAlive processing.  Sends PINGREQ packets as required.
 * @param now current time
 */
void MQTTProtocol_keepalive(time_t now)
{
	ListElement* current = NULL;

	FUNC_ENTRY;
	ListNextElement(bstate->clients, &current);
	while (current)
	{
		Clients* client =	(Clients*)(current->content);
		ListNextElement(bstate->clients, &current); 
		if (client->connected && client->keepAliveInterval > 0 &&
			(difftime(now, client->net.lastSent) >= client->keepAliveInterval ||
					difftime(now, client->net.lastReceived) >= client->keepAliveInterval))
		{
			if (client->ping_outstanding == 0)
			{
				if (Socket_noPendingWrites(client->net.socket))
				{
					if (MQTTPacket_send_pingreq(&client->net, client->clientID) != TCPSOCKET_COMPLETE)
					{
						Log(TRACE_PROTOCOL, -1, "Error sending PINGREQ for client %s on socket %d, disconnecting", client->clientID, client->net.socket);
						MQTTProtocol_closeSession(client, 1);
					}
					else
					{
						client->net.lastSent = now;
						client->ping_outstanding = 1;
					}
				}
			}
			else
			{
				Log(TRACE_PROTOCOL, -1, "PINGRESP not received in keepalive interval for client %s on socket %d, disconnecting", client->clientID, client->net.socket);
				MQTTProtocol_closeSession(client, 1);
			}
		}
	}
	FUNC_EXIT;
}
/**
 * Empty a message list, leaving it able to accept new messages
 * @param msgList the message list to empty
 */
void MQTTProtocol_emptyMessageList(List* msgList)
{
	ListElement* current = NULL;

	FUNC_ENTRY;
	while (ListNextElement(msgList, &current))
	{
		Messages* m = (Messages*)(current->content);
		MQTTProtocol_removePublication(m->publish);
	}
	ListEmpty(msgList);
	FUNC_EXIT;
}
Exemple #21
0
/**
 * Checks whether the message IDs wrapped by looking for the largest gap between two consecutive
 * message IDs in the outboundMsgs queue.
 * @param client the client as ::Clients.
 */
void MQTTPersistence_wrapMsgID(Clients *client)
{
	ListElement* wrapel = NULL;
	ListElement* current = NULL;

	FUNC_ENTRY;
	if ( client->outboundMsgs->count > 0 )
	{
		int firstMsgID = ((Messages*)client->outboundMsgs->first->content)->msgid;
		int lastMsgID = ((Messages*)client->outboundMsgs->last->content)->msgid;
		int gap = MAX_MSG_ID - lastMsgID + firstMsgID;
		current = ListNextElement(client->outboundMsgs, &current);

		while(ListNextElement(client->outboundMsgs, &current) != NULL)
		{
			int curMsgID = ((Messages*)current->content)->msgid;
			int curPrevMsgID = ((Messages*)current->prev->content)->msgid;
			int curgap = curMsgID - curPrevMsgID;
			if ( curgap > gap )
			{
				gap = curgap;
				wrapel = current;
			}
		}
	}

	if ( wrapel != NULL )
	{
		/* put wrapel at the beginning of the queue */
		client->outboundMsgs->first->prev = client->outboundMsgs->last;
		client->outboundMsgs->last->next = client->outboundMsgs->first;
		client->outboundMsgs->first = wrapel;
		client->outboundMsgs->last = wrapel->prev;
		client->outboundMsgs->first->prev = NULL;
		client->outboundMsgs->last->next = NULL;
	}
	FUNC_EXIT;
}
Exemple #22
0
void MQTTPersistence_insertInSeqOrder(List* list, MQTTPersistence_qEntry* qEntry, size_t size)
{
	ListElement* index = NULL;
	ListElement* current = NULL;

	FUNC_ENTRY;
	while (ListNextElement(list, &current) != NULL && index == NULL)
	{
		if (qEntry->seqno < ((MQTTPersistence_qEntry*)current->content)->seqno)
			index = current;
	}
	ListInsert(list, qEntry, size, index);
	FUNC_EXIT;
}
Exemple #23
0
/**
 * Scans the heap and reports any items currently allocated.
 * To be used at shutdown if any heap items have not been freed.
 */
void HeapScan()
{
	ListElement* current = NULL;
	Log(TRACE_MIN, -1, "Heap scan start, total %d bytes", state.current_size);
	while (ListNextElement(&heap, &current))
	{
		storageElement* s = (storageElement*)(current->content);
		Log(TRACE_MIN, -1, "Heap element size %d, line %d, file %s, ptr %p", s->size, s->line, s->file, s->ptr);
		Log(TRACE_MIN, -1, "  Content %*.s", (10 > s->size) ? s->size : 10, (char*)s->ptr);
		if (s->stack)
			Log(TRACE_MIN, -1, "  Stack trace: %s", s->stack);
	}
	Log(TRACE_MIN, -1, "Heap scan end");
}
Exemple #24
0
/**
 * Send an MQTT unsubscribe packet down a socket.
 * @param topics list of topics
 * @param msgid the MQTT message id to use
 * @param dup boolean - whether to set the MQTT DUP flag
 * @param socket the open socket to send the data to
 * @param clientID the string client identifier, only used for tracing
 * @return the completion code (e.g. TCPSOCKET_COMPLETE)
 */
int MQTTPacket_send_unsubscribe(List* topics, uint64_t msgid, int dup, networkHandles* net, const char* clientID)
{
	Header header;
	char *data, *ptr;
	int rc = -1;
	ListElement *elem = NULL;
	int datalen;
    int mqtt_version = get_client_mqtt_version_from_network_handler(net);

	FUNC_ENTRY;
	header.bits.type = UNSUBSCRIBE;
	header.bits.dup = dup;
	header.bits.qos = 1;
	header.bits.retain = 0;

	datalen = 8 + topics->count * 2; // utf length == 2
	while (ListNextElement(topics, &elem))
		datalen += strlen((char*)(elem->content));
	ptr = data = malloc(datalen);

    if(MQTTVERSION_YUNBA_3_1 == mqtt_version)
    {
        writeInt64(&ptr, msgid);
    }else{
        writeInt(&ptr, msgid);
        datalen -= 6;
    }
	elem = NULL;
	while (ListNextElement(topics, &elem))
		writeUTF(&ptr, (char*)(elem->content));
	rc = MQTTPacket_send(net, header, data, datalen, 1);
	Log(LOG_PROTOCOL, 25, NULL, net->socket, clientID, msgid, rc);
	if (rc != TCPSOCKET_INTERRUPTED)
		free(data);
	FUNC_EXIT_RC(rc);
	return rc;
}
Exemple #25
0
/**
 * Inserts the specified message into the list, maintaining message ID order.
 * @param list the list to insert the message into.
 * @param content the message to add.
 * @param size size of the message.
 */
void MQTTPersistence_insertInOrder(List* list, void* content, size_t size)
{
	ListElement* index = NULL;
	ListElement* current = NULL;

	FUNC_ENTRY;
	while(ListNextElement(list, &current) != NULL && index == NULL)
	{
		if ( ((Messages*)content)->msgid < ((Messages*)current->content)->msgid )
			index = current;
	}

	ListInsert(list, content, size, index);
	FUNC_EXIT;
}
Exemple #26
0
void MQTTClient_emptyMessageQueue(Clients* client)
{
	FUNC_ENTRY;
	/* empty message queue */
	if (client->messageQueue->count > 0)
	{
		ListElement* current = NULL;
		while (ListNextElement(client->messageQueue, &current))
		{
			qEntry* qe = (qEntry*)(current->content);
			free(qe->topicName);
			free(qe->msg->payload);
			free(qe->msg);
		}
		ListEmpty(client->messageQueue);
	}
	FUNC_EXIT;
}
Exemple #27
0
/**
 * Fully initialize the socket module for in and outbound communications.
 * In multi-listener mode.
 * @param myListeners list of listeners
 * @return completion code
 */
int Socket_initialize(List* myListeners)
{
	ListElement* current = NULL;
	int rc = 0;

	FUNC_ENTRY;
	s.listeners = myListeners;
	Socket_outInitialize();
	while (ListNextElement(s.listeners, &current))
	{
		Listener* list = (Listener*)(current->content);
		if ((rc = Socket_addServerSocket(list)) != 0)
		{
			Log(LOG_WARNING, 15, NULL, list->port);
			break;
		}
	}
	FUNC_EXIT_RC(rc);
	return rc;
}
Exemple #28
0
/**
 * Process retained messages (when a client subscribes)
 * @param client the client to send the messages to
 * @param topic the topic to match
 * @param qos the QoS of the subscription
 */
void MQTTProtocol_processRetaineds(Clients* client, char* topic, int qos, int priority)
{
	List* rpl = NULL;
	ListElement* currp = NULL;
#if defined(QOS0_SEND_LIMIT)
	int qos0count = 0;
#endif

	FUNC_ENTRY;
	rpl = SubscriptionEngines_getRetained(bstate->se, topic);
	while (ListNextElement(rpl, &currp))
	{
		int curqos;
		Publish publish;
		Messages* p = NULL;
		RetainedPublications* rp = (RetainedPublications*)(currp->content);

		publish.payload = rp->payload;
		publish.payloadlen = rp->payloadlen;
		publish.topic = rp->topicName;
		curqos = (rp->qos < qos) ? rp->qos : qos;
#if defined(QOS0_SEND_LIMIT)
		if (curqos == 0)
			++qos0count;
		if (qos0count > bstate->max_inflight_messages) /* a somewhat arbitrary criterion */
		{
			if (MQTTProtocol_queuePublish(client, &publish, curqos, 1, priority, &p) == SOCKET_ERROR)
				break;
		}
		else
		{
#endif
			if (Protocol_startOrQueuePublish(client, &publish, curqos, 1, priority, &p) == SOCKET_ERROR)
				break;
#if defined(QOS0_SEND_LIMIT)
		}
#endif
	}
	ListFreeNoContent(rpl);
	FUNC_EXIT;
}
Exemple #29
0
void MQTTClient_stop()
{
	int rc = 0;

	FUNC_ENTRY;
	if (running == 1 && tostop == 0)
	{
		int conn_count = 0;
		ListElement* current = NULL;

		if (handles != NULL)
		{
			/* find out how many handles are still connected */
			while (ListNextElement(handles, &current))
			{
				if (((MQTTClients*)(current->content))->c->connect_state > 0 ||
						((MQTTClients*)(current->content))->c->connected)
					++conn_count;
			}
		}
		Log(TRACE_MIN, -1, "Conn_count is %d", conn_count);
		/* stop the background thread, if we are the last one to be using it */
		if (conn_count == 0)
		{
			int count = 0;
			tostop = 1;
			if (Thread_getid() != run_id)
			{
				while (running && ++count < 100)
				{
					Thread_unlock_mutex(mqttclient_mutex);
					Log(TRACE_MIN, -1, "sleeping");
					MQTTClient_sleep(100L);
					Thread_lock_mutex(mqttclient_mutex);
				}
			}
			rc = 1;
		}
	}
	FUNC_EXIT_RC(rc);
}
Exemple #30
0
/**
 * See if any pending writes have been completed, and cleanup if so.
 * Cleaning up means removing any publication data that was stored because the write did
 * not originally complete.
 */
void MQTTProtocol_checkPendingWrites()
{
	FUNC_ENTRY;
	if (state.pending_writes.count > 0)
	{
		ListElement* le = state.pending_writes.first;
		while (le)
		{
			if (Socket_noPendingWrites(((pending_write*)(le->content))->socket))
			{
				MQTTProtocol_removePublication(((pending_write*)(le->content))->p);
				state.pending_writes.current = le;
				ListRemove(&(state.pending_writes), le->content); /* does NextElement itself */
				le = state.pending_writes.current;
			}
			else
				ListNextElement(&(state.pending_writes), &le);
		}
	}
	FUNC_EXIT;
}