Пример #1
0
/**
 * MQTT retry protocol and socket pending writes processing.
 * @param now current time
 * @param doRetry boolean - retries as well as pending writes?
 */
void MQTTProtocol_retry(time_t now, int doRetry)
{
	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);
	}
	FUNC_EXIT;
}
Пример #2
0
int MQTTClient_disconnect1(MQTTClient handle, int timeout, int internal)
{
	MQTTClients* m = handle;
	START_TIME_TYPE start;
	int rc = MQTTCLIENT_SUCCESS;
	int was_connected = 0;

	FUNC_ENTRY;
	Thread_lock_mutex(mqttclient_mutex);

	if (m == NULL || m->c == NULL)
	{
		rc = MQTTCLIENT_FAILURE;
		goto exit;
	}
	if (m->c->connected == 0 && m->c->connect_state == 0)
	{
		rc = MQTTCLIENT_DISCONNECTED;
		goto exit;
	}
	was_connected = m->c->connected; /* should be 1 */
	if (m->c->connected != 0)
	{
		start = MQTTClient_start_clock();
		m->c->connect_state = -2; /* indicate disconnecting */
		while (m->c->inboundMsgs->count > 0 || m->c->outboundMsgs->count > 0)
		{ /* wait for all inflight message flows to finish, up to timeout */
			if (MQTTClient_elapsed(start) >= timeout)
				break;
			Thread_unlock_mutex(mqttclient_mutex);
			MQTTClient_yield();
			Thread_lock_mutex(mqttclient_mutex);
		}
	}

	MQTTProtocol_closeSession(m->c, 0);

	if (Thread_check_sem(m->connect_sem))
		Thread_post_sem(m->connect_sem);
	if (Thread_check_sem(m->connack_sem))
		Thread_post_sem(m->connack_sem);
	if (Thread_check_sem(m->suback_sem))
		Thread_post_sem(m->suback_sem);
	if (Thread_check_sem(m->unsuback_sem))
		Thread_post_sem(m->unsuback_sem);

exit:
	MQTTClient_stop();
	if (internal && m->cl && was_connected)
	{
		Log(TRACE_MIN, -1, "Calling connectionLost for client %s", m->c->clientID);
		Thread_start(connectionLost_call, m);
	}
	Thread_unlock_mutex(mqttclient_mutex);
	FUNC_EXIT_RC(rc);
	return rc;
}
Пример #3
0
/**
 * Process an incoming disconnect packet for a socket
 * @param pack pointer to the disconnect packet
 * @param sock the socket on which the packet was received
 * @return completion code
 */
int MQTTProtocol_handleDisconnects(void* pack, int sock, Clients* client)
{
	FUNC_ENTRY;
	client->good = 0; /* don't try and send log message to this client if it is subscribed to $SYS/broker/log */
	Log(LOG_PROTOCOL, 5, NULL, sock, client->clientID);
	if (bstate->connection_messages)
		Log(LOG_INFO, 38, NULL, client->clientID);
	MQTTProtocol_closeSession(client, 0);
	FUNC_EXIT;
	return TCPSOCKET_COMPLETE;
}
Пример #4
0
/**
 * 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;
}
Пример #5
0
void MQTTProtocol_shutdownclients(Tree* clients, int terminate)
{
	Node* current = NULL;

	FUNC_ENTRY;
	current = TreeNextElement(clients, current);
	while (current)
	{
		Clients* client = (Clients*)(current->content);
		current = TreeNextElement(clients, current);
		Log(LOG_INFO, 17, NULL, client->clientID);
		if (terminate)
			client->cleansession = 1; /* no persistence, so everything is clean */
		MQTTProtocol_closeSession(client, 0);
	}
	FUNC_EXIT;
}
Пример #6
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;
}
Пример #7
0
/**
 * Clean up a client list by closing any marked as "not good".
 * @param clients the list of clients
 */
void MQTTProtocol_clean_clients(Tree* clients)
{
	Node* current = NULL;

	FUNC_ENTRY;
	current = TreeNextElement(clients, current);
	while (current)
	{
		Clients* client =	(Clients*)(current->content);
		current = TreeNextElement(clients, current);

		if (client->good == 0)
		{
			Log(LOG_WARNING, 18, NULL, client->clientID, client->socket,
					Socket_getpeer(client->socket));
			MQTTProtocol_closeSession(client, 1);
		}
	}
	FUNC_EXIT;
}
Пример #8
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;
}
Пример #9
0
/**
 * 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;
}
Пример #10
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;
}
Пример #11
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;
}
Пример #12
0
/**
 * MQTT retry protocol and socket pending writes processing.
 * @param now current time
 * @param doRetry boolean - retries as well as pending writes?
 * @return not actually used
 */
int MQTTProtocol_retry(time_t now, int doRetry)
{
	Node* current = NULL;
	int rc = 0;

	FUNC_ENTRY;
	current = TreeNextElement(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);
		current = TreeNextElement(bstate->clients, current);
		if (client->connected == 0)
		{
#if defined(MQTTS)
			if (client->protocol == PROTOCOL_MQTTS)
			{
				if (difftime(now,client->lastContact) > bstate->retry_interval)
				{
					int rc2 = 0;
					/* NB: no dup bit for these packets */
					if (client->connect_state == 1) /* TODO: handle err */
						rc2 = MQTTSPacket_send_willTopicReq(client);
					else if (client->connect_state == 2) /* TODO: handle err */
						rc2 = MQTTSPacket_send_willMsgReq(client);
					if (rc2 == SOCKET_ERROR)
					{
						client->good = 0;
						Log(LOG_WARNING, 29, NULL, client->clientID, client->socket);
						MQTTProtocol_closeSession(client, 1);
						client = NULL;
					}
				}
			}
			else if (client->protocol == PROTOCOL_MQTTS_DTLS)
			{
				if (difftime(now,client->lastContact) > bstate->retry_interval)
				{
					int rc2 = 0;
					/* NB: no dup bit for these packets */
					if (client->connect_state == 1) /* TODO: handle err */
						rc2 = MQTTSPacket_send_willTopicReq(client);
					else if (client->connect_state == 2) /* TODO: handle err */
						rc2 = MQTTSPacket_send_willMsgReq(client);
					if (rc2 == SOCKET_ERROR)
					{
						client->good = 0;
						Log(LOG_WARNING, 29, NULL, client->clientID, client->socket);
						MQTTProtocol_closeSession(client, 1);
						client = NULL;
					}
				}
			}
#endif
			continue;
		}
		if (client->good == 0)
		{
			MQTTProtocol_closeSession(client, 1);
			continue;
		}
		if (Socket_noPendingWrites(client->socket) == 0)
			continue;
		if (doRetry)
			MQTTProtocol_retries(now, client);
		if (client)
		{
			if (MQTTProtocol_processQueued(client))
				rc = 1;
		}
	}
	FUNC_EXIT_RC(rc);
	return rc;
}
Пример #13
0
/**
 * MQTT protocol timeslice for one packet and client - must not take too long!
 * @param sock the socket which is ready for the packet to be read from
 * @param client the client structure which corresponds to the socket
 */
void MQTTProtocol_timeslice(int sock, Clients* client)
{
	int error;
	MQTTPacket* pack;

	FUNC_ENTRY;

	Log(TRACE_MIN, -1, "%d %s About to read packet for peer address %s",
			sock, (client == NULL) ? "unknown" : client->clientID, Socket_getpeer(sock));
	in_MQTTPacket_Factory = sock;
	pack = MQTTPacket_Factory(sock, &error);
	in_MQTTPacket_Factory = -1;
	if (pack == NULL)
	{ /* there was an error on the socket, so clean it up */
		if (error == SOCKET_ERROR || error == BAD_MQTT_PACKET)
		{
			if (client != NULL)
			{
				client->good = 0; /* make sure we don't try and send messages to ourselves */
				if (error == SOCKET_ERROR)
					Log(LOG_WARNING, 18, NULL, client->clientID, sock, Socket_getpeer(sock));
				else
					Log(LOG_WARNING, 19, NULL, client->clientID, sock, Socket_getpeer(sock));
				MQTTProtocol_closeSession(client, 1);
			}
			else
			{
				if (error == SOCKET_ERROR)
					/* Don't do a Socket_getpeer in the case of SOCKET_ERROR -
					 * otherwise another SOCKET_ERROR will be hit  */
					Log(LOG_WARNING, 20, NULL, sock, "unknown");
				else
					Log(LOG_WARNING, 21, NULL, sock, Socket_getpeer(sock));
				Socket_close(sock);
			}
		}
	}
	else if (handle_packets[pack->header.bits.type] == NULL)
		Log(LOG_WARNING, 22, NULL, pack->header.bits.type, sock);
	else
	{
		if (client == NULL && pack->header.bits.type != CONNECT)
		{
			Log(LOG_WARNING, 23, NULL, sock, Socket_getpeer(sock), MQTTPacket_name(pack->header.bits.type));
			MQTTPacket_free_packet(pack);
			Socket_close(sock);
		}
		else
		{
			Node* elem = NULL;
			/* incoming publish at QoS 0 does not result in outgoing communication, so we don't want to count it as contact,
			   for PING processing on outbound connections */
			int update_time = (pack->header.bits.type == PUBLISH && pack->header.bits.qos == 0) ? 0 : 1;
			if (client && (update_time || (client->outbound == 0)))
				time(&(client->lastContact));
			if ((*handle_packets[pack->header.bits.type])(pack, sock, client) == SOCKET_ERROR)
			{
				/* the client could have been closed during handle_packet, so check to see if it's still in the client list */
				elem = TreeFind(bstate->clients, &sock);
				if (elem == NULL && client && client->clientID)
					elem = TreeFind(bstate->disconnected_clients, client->clientID);
				if (elem != NULL)
				{
					client = (Clients*)(elem->content);
					client->good = 0; /* make sure we don't try and send messages to ourselves */
					Log(LOG_WARNING, 18, NULL, client->clientID, sock, Socket_getpeer(sock));
					MQTTProtocol_closeSession(client, 1);
				}
				else
				{
					Log(LOG_WARNING, 20, NULL, sock, Socket_getpeer(sock));
					Socket_close(sock);
				}
			}
		}
	}
	/*MQTTProtocol_housekeeping(); move to Protocol_timeslice*/
	FUNC_EXIT;
}