char* MQTTSProtocol_getPreDefinedTopicName(Clients* client, int topicId) { Node* node; char* rc = NULL; FUNC_ENTRY; // Read client specific mappings first if ( (node = TreeFind(bstate->client_predefined_topics, client->clientID)) != NULL){ Tree *topic = ((Client_Predefined_Topics*)(node->content))->topics ; if ( (node = TreeFind( topic , &topicId)) != NULL){ rc = ((Predefined_Topic*)(node->content))->topicName; } } // If client specific pre-defined topic not found, read broker wide mapping if ( rc == NULL ) { if ( (node = TreeFind(bstate->default_predefined_topics, &topicId)) == NULL) { goto exit; } rc = ((Predefined_Topic*)(node->content))->topicName; } exit: FUNC_EXIT; return rc; }
DBDAT* DbaseSet( TAG* list, DBDAT* dbdat ) { FOLDER* folder ; if( !dbdat ) { IOerror( IO_WARN, "DbaseFind", "setting null value" ) ; return (DBDAT*) 0 ; } if( !*list ) { IOerror( IO_WARN, "DbaseFind", "null taglist" ) ; return (DBDAT*) 0 ; } for( folder = &DbaseRoot ; *(list + 1) ; list++ ) { FOLDER* son = (FOLDER*) TreeFind( folder->kids, kid_cmp, *list ) ; if( !son ) { DbaseAddFolder( folder, *list ) ; son = (FOLDER*) TreeFind( folder->kids, kid_cmp, *list ) ; } folder = son ; } return folder->EntryOverwrite( *list, dbdat ) ; }
/** * Process an incoming pubrel packet for a socket * @param pack pointer to the publish packet * @param sock the socket on which the packet was received * @return completion code */ int MQTTProtocol_handlePubrels(void* pack, int sock, Clients* client) { Pubrel* pubrel = (Pubrel*)pack; //Clients* client = (Clients*)(TreeFind(bstate->clients, &sock)->content); int rc = TCPSOCKET_COMPLETE; FUNC_ENTRY; Log(LOG_PROTOCOL, 17, NULL, sock, client->clientID, pubrel->msgId); /* look for the message by message id in the records of inbound messages for this client */ if (ListFindItem(client->inboundMsgs, &(pubrel->msgId), messageIDCompare) == NULL) { if (pubrel->header.bits.dup == 0) Log(LOG_WARNING, 50, NULL, "PUBREL", client->clientID, pubrel->msgId); /* Apparently this is "normal" behaviour, so we don't need to issue a warning */ rc = MQTTPacket_send_pubcomp(pubrel->msgId, sock, client->clientID); } 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; char* saved_clientid = malloc(strlen(client->clientID) + 1); strcpy(saved_clientid, client->clientID); /* send pubcomp before processing the publications because a lot of return publications could fill up the socket buffer */ rc = MQTTPacket_send_pubcomp(pubrel->msgId, sock, client->clientID); 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; ++(bstate->msgs_received); bstate->bytes_received += m->publish->payloadlen; Protocol_processPublication(&publish, client->clientID); /* The client structure might have been removed in processPublication, on error */ if (TreeFind(bstate->clients, &sock) || TreeFind(bstate->disconnected_clients, saved_clientid)) { ListRemove(client->inboundMsgs, m); MQTTProtocol_removePublication(m->publish); } free(saved_clientid); } } free(pack); FUNC_EXIT_RC(rc); return rc; }
DBDAT* DbaseLookup( char* opath, TAG keytag ) { static char path[1000] ; DBDAT* dbdat = (DBDAT*) 0 ; FOLDER* folder = &DbaseRoot ; (void) strcpy( path, DataBasePath ) ; dbdat = folder->EntryFind( keytag ) ; for( TAG* list = DbasePathtoList( opath ) ; *list ; list++ ) { (void) strcat( path, "/" ) ; (void) strcat( path, TagString( *list ) ) ; FOLDER* son = (FOLDER*) TreeFind( folder->kids, kid_cmp, *list ) ; if( !son ) { IOerror( IO_WARN, "DbaseLookup", "no such directory %s\n", path ) ; return dbdat ; } if( !son->loaded ) DbaseLoadDir( path, son ) ; folder = son ; if( DBDAT* new_dbdat = folder->EntryFind( keytag ) ) dbdat = new_dbdat ; } return dbdat ; }
/** * Utility to find an item in the heap. Lets you know if the heap already contains * the memory location in question. * @param p pointer to a memory location * @return pointer to the storage element if found, or NULL */ void* Heap_findItem(void* p) { Node* e = NULL; Thread_lock_mutex(heap_mutex); e = TreeFind(&heap, ((int*)p)-1); Thread_unlock_mutex(heap_mutex); return (e == NULL) ? NULL : e->content; }
Clients* Protocol_getoutboundclient(int sock) { Node* node = NULL; Clients* client = NULL; FUNC_ENTRY; if ((node = TreeFind(bstate->clients, &sock)) != NULL) client = (Clients*)(node->content); FUNC_EXIT; return client; }
Clients* Protocol_getclientbyaddr(char* addr) { Node* node = NULL; Clients* client = NULL; FUNC_ENTRY; if ((node = TreeFind(bstate->mqtts_clients, addr)) != NULL) client = (Clients*)(node->content); FUNC_EXIT; return client; }
DBDAT* DbaseFind( TAG* list ) { FOLDER* folder ; if( !*list ) { IOerror( IO_WARN, "DbaseFind", "null taglist" ) ; return (DBDAT*) 0 ; } for( folder = &DbaseRoot ; *(list + 1) ; list++ ) { FOLDER* son = (FOLDER*) TreeFind( folder->kids, kid_cmp, *list ) ; if( !son ) { DbaseAddFolder( folder, *list ) ; son = (FOLDER*) TreeFind( folder->kids, kid_cmp, *list ) ; } folder = son ; } return folder->EntryFind( *list ) ; }
Bool ChunkOfAddr(Chunk *chunkReturn, Arena arena, Addr addr) { Tree tree; AVER_CRITICAL(chunkReturn != NULL); AVERT_CRITICAL(Arena, arena); /* addr is arbitrary */ if (TreeFind(&tree, ArenaChunkTree(arena), TreeKeyOfAddrVar(addr), ChunkCompare) == CompareEQUAL) { Chunk chunk = ChunkOfTree(tree); AVER_CRITICAL(chunk->base <= addr); AVER_CRITICAL(addr < chunk->limit); *chunkReturn = chunk; return TRUE; } return FALSE; }
/** * Remove an item from the recorded heap without actually freeing it. * Use sparingly! * @param file use the __FILE__ macro to indicate which file this item was allocated in * @param line use the __LINE__ macro to indicate which line this item was allocated at * @param p pointer to the item to be removed */ static int Internal_heap_unlink(char* file, int line, void* p) { Node* e = NULL; int rc = 0; e = TreeFind(&heap, ((int*)p)-1); if (e == NULL) Log(LOG_ERROR, 13, "Failed to remove heap item at file %s line %d", file, line); else { storageElement* s = (storageElement*)(e->content); Log(TRACE_MAX, -1, "Freeing %d bytes in heap at file %s line %d, heap use now %d bytes\n", s->size, file, line, state.current_size); checkEyecatchers(file, line, p, s->size); /* free(s->ptr); */ free(s->file); state.current_size -= s->size; TreeRemoveNodeIndex(&heap, e, 0); free(s); rc = 1; } return rc; }
Bool TreeInsert(Tree *treeReturn, Tree root, Tree node, TreeKey key, TreeCompare compare) { Tree parent; Compare cmp; AVER(treeReturn != NULL); AVER(Tree, root); AVER(TreeCheckLeaf(node)); AVER(FUNCHECK(compare)); /* key is arbitrary */ cmp = TreeFind(&parent, root, key, compare); switch (cmp) { case CompareLESS: parent->left = node; break; case CompareEQUAL: if (parent != NULL) { *treeReturn = parent; return FALSE; } AVER(root == TreeEMPTY); root = node; break; case CompareGREATER: parent->right = node; break; default: NOTREACHED; *treeReturn = NULL; return FALSE; } *treeReturn = root; return TRUE; }
/** * Originates a new publication - sends it to all clients subscribed. * @param publish pointer to a stucture which contains all the publication information * @param originator the originating client */ void Protocol_processPublication(Publish* publish, char* originator) { Messages* stored = NULL; /* to avoid duplication of data where possible */ List* clients; ListElement* current = NULL; int savedMsgId = publish->msgId; int clean_needed = 0; FUNC_ENTRY; if (Topics_hasWildcards(publish->topic)) { Log(LOG_INFO, 12, NULL, publish->topic, originator); goto exit; } if ((strcmp(INTERNAL_CLIENTID, originator) != 0) && bstate->password_file && bstate->acl_file) { Clients* client = (Clients*)(TreeFindIndex(bstate->clients, originator, 1)->content); if (Users_authorise(client->user, publish->topic, ACL_WRITE) == false) { Log(LOG_AUDIT, 149, NULL, originator, publish->topic); goto exit; } } if (publish->header.bits.retain) { SubscriptionEngines_setRetained(bstate->se, publish->topic, publish->header.bits.qos, publish->payload, publish->payloadlen); if (bstate->persistence == 1 && bstate->autosave_on_changes == 1 && bstate->autosave_interval > 0 && bstate->se->retained_changes >= bstate->autosave_interval) { Log(LOG_INFO, 100, NULL, bstate->autosave_interval); SubscriptionEngines_save(bstate->se); } } clients = SubscriptionEngines_getSubscribers(bstate->se, publish->topic, originator); if (strncmp(publish->topic, "$SYS/client/", 12) == 0) { /* default subscription for a client */ Node* node = TreeFindIndex(bstate->clients, &publish->topic[12], 1); if (node == NULL) node = TreeFind(bstate->disconnected_clients, &publish->topic[12]); if (node && node->content) { Subscriptions* rcs = malloc(sizeof(Subscriptions)); rcs->clientName = &publish->topic[12]; rcs->qos = 2; rcs->priority = PRIORITY_NORMAL; rcs->topicName = publish->topic; ListAppend(clients, rcs, sizeof(Subscriptions)); } } current = NULL; while (ListNextElement(clients, ¤t)) { Node* curnode = NULL; unsigned int qos = ((Subscriptions*)(current->content))->qos; int priority = ((Subscriptions*)(current->content))->priority; char* clientName = ((Subscriptions*)(current->content))->clientName; if (publish->header.bits.qos < qos) /* reduce qos if > subscribed qos */ qos = publish->header.bits.qos; if ((curnode = TreeFindIndex(bstate->clients, clientName, 1)) == NULL) curnode = TreeFind(bstate->disconnected_clients, clientName); #if defined(MQTTS) if (curnode == NULL && ((curnode = TreeFindIndex(bstate->mqtts_clients, clientName, 1)) == NULL)) curnode = TreeFind(bstate->disconnected_mqtts_clients, clientName); #endif if (curnode) { Clients* pubclient = (Clients*)(curnode->content); int retained = 0; Messages* saved = NULL; char* original_topic = publish->topic; #if !defined(NO_BRIDGE) if (pubclient->outbound || pubclient->noLocal) { retained = publish->header.bits.retain; /* outbound and noLocal mean outward/inward bridge client, so keep retained flag */ if (pubclient->outbound) { Bridge_handleOutbound(pubclient, publish); if (publish->topic != original_topic) { /* handleOutbound has changed the topic, so we musn't used the stored pub which contains the original topic */ saved = stored; stored = NULL; } } } #endif if (Protocol_startOrQueuePublish(pubclient, publish, qos, retained, priority, &stored) == SOCKET_ERROR) { pubclient->good = pubclient->connected = 0; /* flag this client as needing to be cleaned up */ clean_needed = 1; } if (publish->topic != original_topic) { stored = saved; /* restore the stored pointer for the next loop iteration */ free(publish->topic); publish->topic = original_topic; } } } publish->msgId = savedMsgId; /* INTERNAL_CLIENTID means that we are publishing data to the log, and we don't want to interfere with other close processing */ if (clean_needed && strcmp(originator, INTERNAL_CLIENTID) != 0) MQTTProtocol_clean_clients(bstate->clients); ListFree(clients); exit: FUNC_EXIT; }
/** * Timeslice function to run protocol exchanges */ void Protocol_timeslice() { int sock; int bridge_connection = 0; static int more_work = 0; FUNC_ENTRY; if ((sock = Socket_getReadySocket(more_work, NULL)) == SOCKET_ERROR) { #if defined(WIN32) int errno; errno = WSAGetLastError(); #endif if (errno != EINTR && errno != EAGAIN && errno != EINPROGRESS && errno != EWOULDBLOCK) { Log(LOG_SEVERE, 0, "Restarting MQTT protocol to resolve socket problems"); MQTTProtocol_shutdown(0); SubscriptionEngines_save(bstate->se); MQTTProtocol_reinitialize(); goto exit; } } MQTTProtocol_checkPendingWrites(); if (sock > 0) { Clients* client = NULL; Node* curnode = TreeFind(bstate->clients, &sock); if (curnode) { client = (Clients*)(curnode->content); #if !defined(NO_BRIDGE) if (client->outbound && client->connect_state == 1) { Bridge_handleConnection(client); bridge_connection = 1; } #endif } if (bridge_connection == 0) #if defined(MQTTS) { int protocol = PROTOCOL_MQTT; if (client == NULL) protocol = Socket_getParentListener(sock)->protocol; else protocol = client->protocol; if (protocol == PROTOCOL_MQTT) #endif MQTTProtocol_timeslice(sock, client); #if defined(MQTTS) else if (protocol == PROTOCOL_MQTTS) MQTTSProtocol_timeslice(sock); } #endif } if (bstate->state != BROKER_STOPPING) #if !defined(NO_ADMIN_COMMANDS) Persistence_read_command(bstate); #else ; #endif else
ubi_btNodePtr ubi_btLocate( ubi_btRootPtr RootPtr, ubi_btItemPtr FindMe, ubi_trCompOps CompOp ) /* ------------------------------------------------------------------------ ** * The purpose of ubi_btLocate() is to find a node or set of nodes given * a target value and a "comparison operator". The Locate() function is * more flexible and (in the case of trees that may contain dupicate keys) * more precise than the ubi_btFind() function. The latter is faster, * but it only searches for exact matches and, if the tree contains * duplicates, Find() may return a pointer to any one of the duplicate- * keyed records. * * Input: * RootPtr - A pointer to the header of the tree to be searched. * FindMe - An ubi_btItemPtr that indicates the key for which to * search. * CompOp - One of the following: * CompOp Return a pointer to the node with * ------ --------------------------------- * ubi_trLT - the last key value that is less * than FindMe. * ubi_trLE - the first key matching FindMe, or * the last key that is less than * FindMe. * ubi_trEQ - the first key matching FindMe. * ubi_trGE - the first key matching FindMe, or the * first key greater than FindMe. * ubi_trGT - the first key greater than FindMe. * Output: * A pointer to the node matching the criteria listed above under * CompOp, or NULL if no node matched the criteria. * * Notes: * In the case of trees with duplicate keys, Locate() will behave as * follows: * * Find: 3 Find: 3 * Keys: 1 2 2 2 3 3 3 3 3 4 4 Keys: 1 1 2 2 2 4 4 5 5 5 6 * ^ ^ ^ ^ ^ * LT EQ GT LE GE * * That is, when returning a pointer to a node with a key that is LESS * THAN the target key (FindMe), Locate() will return a pointer to the * LAST matching node. * When returning a pointer to a node with a key that is GREATER * THAN the target key (FindMe), Locate() will return a pointer to the * FIRST matching node. * * See Also: ubi_btFind(), ubi_btFirstOf(), ubi_btLastOf(). * ------------------------------------------------------------------------ ** */ { register ubi_btNodePtr p; ubi_btNodePtr parent; char whichkid; /* Start by searching for a matching node. */ p = TreeFind( FindMe, RootPtr->root, &parent, &whichkid, RootPtr->cmp ); if( NULL != p ) /* If we have found a match, we can resolve as follows: */ { switch( CompOp ) { case ubi_trLT: /* It's just a jump to the left... */ p = Border( RootPtr, FindMe, p, ubi_trLEFT ); return( Neighbor( p, ubi_trLEFT ) ); case ubi_trGT: /* ...and then a jump to the right. */ p = Border( RootPtr, FindMe, p, ubi_trRIGHT ); return( Neighbor( p, ubi_trRIGHT ) ); default: p = Border( RootPtr, FindMe, p, ubi_trLEFT ); return( p ); } } /* Else, no match. */ if( ubi_trEQ == CompOp ) /* If we were looking for an exact match... */ return( NULL ); /* ...forget it. */ /* We can still return a valid result for GT, GE, LE, and LT. * <parent> points to a node with a value that is either just before or * just after the target value. * Remaining possibilities are LT and GT (including LE & GE). */ if( (ubi_trLT == CompOp) || (ubi_trLE == CompOp) ) return( (ubi_trLEFT == whichkid) ? Neighbor( parent, whichkid ) : parent ); else return( (ubi_trRIGHT == whichkid) ? Neighbor( parent, whichkid ) : parent ); } /* ubi_btLocate */
ubi_trBool ubi_btInsert( ubi_btRootPtr RootPtr, ubi_btNodePtr NewNode, ubi_btItemPtr ItemPtr, ubi_btNodePtr *OldNode ) /* ------------------------------------------------------------------------ ** * This function uses a non-recursive algorithm to add a new element to the * tree. * * Input: RootPtr - a pointer to the ubi_btRoot structure that indicates * the root of the tree to which NewNode is to be added. * NewNode - a pointer to an ubi_btNode structure that is NOT * part of any tree. * ItemPtr - A pointer to the sort key that is stored within * *NewNode. ItemPtr MUST point to information stored * in *NewNode or an EXACT DUPLICATE. The key data * indicated by ItemPtr is used to place the new node * into the tree. * OldNode - a pointer to an ubi_btNodePtr. When searching * the tree, a duplicate node may be found. If * duplicates are allowed, then the new node will * be simply placed into the tree. If duplicates * are not allowed, however, then one of two things * may happen. * 1) if overwritting *is not* allowed, this * function will return FALSE (indicating that * the new node could not be inserted), and * *OldNode will point to the duplicate that is * still in the tree. * 2) if overwritting *is* allowed, then this * function will swap **OldNode for *NewNode. * In this case, *OldNode will point to the node * that was removed (thus allowing you to free * the node). * ** If you are using overwrite mode, ALWAYS ** * ** check the return value of this parameter! ** * Note: You may pass NULL in this parameter, the * function knows how to cope. If you do this, * however, there will be no way to return a * pointer to an old (ie. replaced) node (which is * a problem if you are using overwrite mode). * * Output: a boolean value indicating success or failure. The function * will return FALSE if the node could not be added to the tree. * Such failure will only occur if duplicates are not allowed, * nodes cannot be overwritten, AND a duplicate key was found * within the tree. * ------------------------------------------------------------------------ ** */ { ubi_btNodePtr OtherP, parent = NULL; char tmp; if( NULL == OldNode ) /* If they didn't give us a pointer, supply our own. */ OldNode = &OtherP; (void)ubi_btInitNode( NewNode ); /* Init the new node's BinTree fields. */ /* Find a place for the new node. */ *OldNode = TreeFind(ItemPtr, (RootPtr->root), &parent, &tmp, (RootPtr->cmp)); /* Now add the node to the tree... */ if( NULL == (*OldNode) ) /* The easy one: we have a space for a new node! */ { if( NULL == parent ) RootPtr->root = NewNode; else { parent->Link[(int)tmp] = NewNode; NewNode->Link[ubi_trPARENT] = parent; NewNode->gender = tmp; } (RootPtr->count)++; return( ubi_trTRUE ); } /* If we reach this point, we know that a duplicate node exists. This * section adds the node to the tree if duplicate keys are allowed. */ if( ubi_trDups_OK(RootPtr) ) /* Key exists, add duplicate */ { ubi_btNodePtr q; tmp = ubi_trRIGHT; q = (*OldNode); *OldNode = NULL; while( NULL != q ) { parent = q; if( tmp == ubi_trEQUAL ) tmp = ubi_trRIGHT; q = q->Link[(int)tmp]; if ( q ) tmp = ubi_trAbNormal( (*(RootPtr->cmp))(ItemPtr, q) ); } parent->Link[(int)tmp] = NewNode; NewNode->Link[ubi_trPARENT] = parent; NewNode->gender = tmp; (RootPtr->count)++; return( ubi_trTRUE ); } /* If we get to *this* point, we know that we are not allowed to have * duplicate nodes, but our node keys match, so... may we replace the * old one? */ if( ubi_trOvwt_OK(RootPtr) ) /* Key exists, we replace */ { if( NULL == parent ) ReplaceNode( &(RootPtr->root), *OldNode, NewNode ); else ReplaceNode( &(parent->Link[(int)((*OldNode)->gender)]), *OldNode, NewNode ); return( ubi_trTRUE ); } return( ubi_trFALSE ); /* Failure: could not replace an existing node. */ } /* ubi_btInsert */
int test(int limit) { int i, *ip, *todelete; Node* current = NULL; Tree* t = TreeInitialize(TreeIntCompare); int rc = 0; printf("Tree initialized\n"); srand(time(NULL)); ip = malloc(sizeof(int)); *ip = 2; TreeAdd(t, (void*)ip, sizeof(int)); check(t); i = 2; void* result = TreeRemove(t, (void*)&i); if (result) free(result); int actual[limit]; for (i = 0; i < limit; i++) { void* replaced = NULL; ip = malloc(sizeof(int)); *ip = rand(); replaced = TreeAdd(t, (void*)ip, sizeof(int)); if (replaced) /* duplicate */ { free(replaced); actual[i] = -1; } else actual[i] = *ip; if (i==5) todelete = ip; printf("Tree element added %d\n", *ip); if (1 % 1000 == 0) { rc = check(t); printf("%d elements, check result %d\n", i+1, rc); if (rc != 0) return 88; } } check(t); for (i = 0; i < limit; i++) { int parm = actual[i]; if (parm == -1) continue; Node* found = TreeFind(t, (void*)&parm); if (found) printf("Tree find %d %d\n", parm, *(int*)(found->content)); else { printf("%d not found\n", parm); traverse(t, parm); return -2; } } check(t); for (i = limit -1; i >= 0; i--) { int parm = actual[i]; void *found; if (parm == -1) /* skip duplicate */ continue; found = TreeRemove(t, (void*)&parm); if (found) { printf("%d Tree remove %d %d\n", i, parm, *(int*)(found)); free(found); } else { int count = 0; printf("%d %d not found\n", i, parm); traverse(t, parm); for (i = 0; i < limit; i++) if (actual[i] == parm) ++count; printf("%d occurs %d times\n", parm, count); return -2; } if (i % 1000 == 0) { rc = check(t); printf("%d elements, check result %d\n", i+1, rc); if (rc != 0) return 88; } } printf("finished\n"); return 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; }