/** * 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; }
/** * 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, ¤t); /* 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, ¤t); 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; }
/** * 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; }
/** * 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, ¤t); while (current) { Clients* client = (Clients*)(current->content); ListNextElement(bstate->clients, ¤t); #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; }
/** * 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; }
/** * 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; }
/** * 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, ¤t)) { 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; }
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, ¤t)) { Messages* m = (Messages*)(current->content); (*tokens)[count++] = m->msgid; } (*tokens)[count] = -1; } exit: Thread_unlock_mutex(mqttclient_mutex); FUNC_EXIT_RC(rc); return rc; }
/** * 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, ¤t)) { 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; }
/** * 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, ¤t)) { 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; }
/** * 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; }
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, ¤t) != NULL) printf("List element: %d\n", *((int*)(current->content))); printf("List contents in reverse order:\n"); current = NULL; while (ListPrevElement(l, ¤t) != 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, ¤t) != 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, ¤t) != NULL) printf("List element: %d\n", *((int*)(current->content))); ListFree(l); printf("List freed\n"); }
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; }
/** * 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, ¤t); 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, ¤t); } FUNC_EXIT; }
void HeapScan() { ListElement* current = NULL; Log(LOG_INFO, Messages_get(101), state.current_size); while (ListNextElement(&heap, ¤t)) { 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)); }
void MQTTSProtocol_emptyRegistrationList(List* regList) { ListElement* current = NULL; FUNC_ENTRY; while (ListNextElement(regList, ¤t)) { 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, ¤t); while (current) { Clients* client = (Clients*)(current->content); ListNextElement(bstate->clients, ¤t); 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, ¤t)) { Messages* m = (Messages*)(current->content); MQTTProtocol_removePublication(m->publish); } ListEmpty(msgList); FUNC_EXIT; }
/** * 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, ¤t); while(ListNextElement(client->outboundMsgs, ¤t) != 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; }
void MQTTPersistence_insertInSeqOrder(List* list, MQTTPersistence_qEntry* qEntry, size_t size) { ListElement* index = NULL; ListElement* current = NULL; FUNC_ENTRY; while (ListNextElement(list, ¤t) != NULL && index == NULL) { if (qEntry->seqno < ((MQTTPersistence_qEntry*)current->content)->seqno) index = current; } ListInsert(list, qEntry, size, index); FUNC_EXIT; }
/** * 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, ¤t)) { 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"); }
/** * 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; }
/** * 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, ¤t) != NULL && index == NULL) { if ( ((Messages*)content)->msgid < ((Messages*)current->content)->msgid ) index = current; } ListInsert(list, content, size, index); FUNC_EXIT; }
void MQTTClient_emptyMessageQueue(Clients* client) { FUNC_ENTRY; /* empty message queue */ if (client->messageQueue->count > 0) { ListElement* current = NULL; while (ListNextElement(client->messageQueue, ¤t)) { qEntry* qe = (qEntry*)(current->content); free(qe->topicName); free(qe->msg->payload); free(qe->msg); } ListEmpty(client->messageQueue); } FUNC_EXIT; }
/** * 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, ¤t)) { 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; }
/** * 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; }
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, ¤t)) { 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); }
/** * 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; }