int ListMutableIteratorAppend(ListMutableIterator *iterator, void *payload) { if (!iterator) return -1; if (IsMutableIteratorValid(iterator)) return -1; ListNode *node = NULL; node = (ListNode *)malloc(sizeof(ListNode)); if (!node) { // This is unlikely in Linux but other Unixes actually return NULL return -1; } ListDetach(iterator->origin); node->next = NULL; node->payload = payload; if (iterator->current->next) { node->next = iterator->current->next; node->previous = iterator->current; iterator->current->next->previous = node; iterator->current->next = node; } else { // Last element node->next = NULL; node->previous = iterator->current; iterator->current->next = node; iterator->origin->last = node; } iterator->origin->node_count++; return 0; }
int ListAppend(List *list, void *payload) { ListNode *node = NULL; if (!list) { return -1; } ListDetach(list); node = (ListNode *)malloc(sizeof(ListNode)); if (!node) { // This is unlikely in Linux but other Unixes actually return NULL return -1; } node->next = NULL; node->payload = payload; if (list->last) { // We have elements node->previous = list->last; list->last->next = node; } else { // First element node->previous = NULL; list->list = node; list->first = node; } list->last = node; list->node_count++; return 0; }
int ListMutableIteratorPrepend(ListMutableIterator *iterator, void *payload) { if (!iterator) return -1; if (IsMutableIteratorValid(iterator)) return -1; ListNode *node = NULL; node = (ListNode *)malloc(sizeof(ListNode)); if (!node) { return -1; } ListDetach(iterator->origin); node->payload = payload; if (iterator->current->previous) { node->previous = iterator->current->previous; node->next = iterator->current; iterator->current->previous->next = node; iterator->current->previous = node; } else { // First element node->previous = NULL; node->next = iterator->current; iterator->current->previous = node; iterator->origin->first = node; iterator->origin->list = node; } iterator->origin->node_count++; return 0; }
int ListPrepend(List *list, void *payload) { ListNode *node = NULL; if (!list) { return -1; } ListDetach(list); node = (ListNode *)malloc(sizeof(ListNode)); node->payload = payload; node->previous = NULL; if (list->list) { // We have elements node->next = list->list; list->list->previous = node; } else { // First element node->next = NULL; list->last = node; } list->list = node; list->first = node; list->node_count++; return 0; }
int ListRemove(List *list, void *payload) { if (!list || !payload) return -1; ListNode *node = NULL; /* * This is a complicated matter. We could detach the list before * we know that we have a new node, but that will mean that we * might have copied the whole list without real reasons. On the * other hand, it saves us a whole traversal of the list if we * just do it. */ int found = ListFindNode(list, payload); if (!found) return -1; ListDetach(list); node = NULL; /* * We need to find the node again since we have a new list. * In theory we don't have to worry about the existence of the node, * since the list has not changed, it might have been copied but * it is still the same as before. */ for (node = list->list; node; node = node->next) { if (list->compare) { if (!list->compare(node->payload, payload)) { found = 1; break; } } else { if (node->payload == payload) { found = 1; break; } } } /* * Before deleting the node we have to update the mutable iterator. * We might need to advance it! */ ListUpdateMutableIterator(list, node); ListRemoveNode(list, node); if (list->destroy && node->payload) { list->destroy(node->payload); } free(node); ListUpdateListState(list); return 0; }
char* SocketBuffer_complete(int socket) { FUNC_ENTRY; if (ListFindItem(queues, &socket, socketcompare)) { socket_queue* queue = (socket_queue*)(queues->current->content); SocketBuffer_freeDefQ(); def_queue = queue; ListDetach(queues, queue); } def_queue->socket = def_queue->index = def_queue->headerlen = def_queue->datalen = 0; FUNC_EXIT; return def_queue->buf; }
static PyObject* mqttv3_setcallbacks(PyObject* self, PyObject *args) { MQTTClient c; CallbackEntry* e = NULL; int rc; e = malloc(sizeof(CallbackEntry)); if (!PyArg_ParseTuple(args, "kOOOO", &c, (PyObject**) &e->context, &e->cl, &e->ma, &e->dc)) return NULL; e->c = c; printf("setCallbacks MQTTClient pointer %p\n", c); if ((e->cl != Py_None && !PyCallable_Check(e->cl)) || (e->ma != Py_None && !PyCallable_Check(e->ma)) || (e->dc != Py_None && !PyCallable_Check(e->dc))) { PyErr_SetString(PyExc_TypeError, "3rd, 4th and 5th parameters must be callable or None"); return NULL; } Py_BEGIN_ALLOW_THREADS rc = MQTTClient_setCallbacks(c, e, connectionLost, messageArrived, deliveryComplete); Py_END_ALLOW_THREADS if (rc == MQTTCLIENT_SUCCESS) { ListElement* temp = NULL; if ((temp = ListFindItem(callbacks, c, clientCompare)) != NULL) { ListDetach(callbacks, temp->content); free(temp->content); } ListAppend(callbacks, e, sizeof(e)); Py_XINCREF(e->cl); Py_XINCREF(e->ma); Py_XINCREF(e->dc); Py_XINCREF(e->context); } return Py_BuildValue("i", rc); }
static PyObject* mqttv3_destroy(PyObject* self, PyObject *args) { MQTTClient c; ListElement* temp = NULL; if (!PyArg_ParseTuple(args, "k", &c)) return NULL; if ((temp = ListFindItem(callbacks, c, clientCompare)) != NULL) { ListDetach(callbacks, temp->content); free(temp->content); } MQTTClient_destroy(&c); Py_INCREF(Py_None); return Py_None; }
int ListMutableIteratorRemove(ListMutableIterator *iterator) { if (!iterator) return -1; if (IsMutableIteratorValid(iterator)) return -1; ListDetach(iterator->origin); /* * Removing an element is not as simple as it sounds. We need to inform the list * and make sure we move out of the way. */ ListNode *node = NULL; if (iterator->current->next) { /* * We are not the last element, therefore we proceed as normal. */ node = iterator->current->next; } else { /* * We might be the last element or the only element on the list. * If we are the only element we do not destroy the element otherwise the iterator * would become invalid. */ if (iterator->current->previous) { /* * last element */ node = iterator->current->previous; } else return -1; } ListRemoveNode(iterator->origin, iterator->current); if (iterator->origin->destroy) iterator->origin->destroy(iterator->current->payload); free (iterator->current); iterator->current = node; ListUpdateListState(iterator->origin); return 0; }
/** * Start the publish exchange for any queued messages, if possible. * When the inflight message queue is not at maximum capacity we can start a new * publication. * @param client the client to process queued messages for */ int MQTTProtocol_processQueued(Clients* client) { int rc = 0; #if defined(QOS0_SEND_LIMIT) int qos0count = 0; #endif int threshold_log_message_issued = 0; FUNC_ENTRY; if (Protocol_isClientQuiescing(client)) goto exit; /* don't create new work - just finish in-flight stuff */ Log(TRACE_MAXIMUM, 0, NULL, client->clientID); while (client->good && Socket_noPendingWrites(client->socket) && /* no point in starting a publish if a write is still pending */ client->outboundMsgs->count < bstate->max_inflight_messages && queuedMsgsCount(client) > 0 #if defined(QOS0_SEND_LIMIT) && qos0count < bstate->max_inflight_messages /* an arbitrary criterion - but when would we restart? */ #endif #if defined(MQTTS) && (client->protocol == PROTOCOL_MQTT || client->outboundMsgs->count == 0) #endif ) { int pubrc = TCPSOCKET_COMPLETE; Messages* m = NULL; int threshold = (THRESHOLD * bstate->max_queued_messages) / 100; List* queue = NULL; int i; for (i = PRIORITY_MAX-1; i >= 0; --i) { if (client->queuedMsgs[i]->count > 0) { queue = client->queuedMsgs[i]; break; } } m = (Messages*)(queue->first->content); Log(TRACE_MAXIMUM, 1, NULL, client->clientID); #if defined(MQTTS) if (client->protocol == PROTOCOL_MQTTS && strlen(m->publish->topic) > 2 && MQTTSProtocol_getRegisteredTopicId(client, m->publish->topic) == 0) { if (client->pendingRegistration == NULL) rc = MQTTSProtocol_startRegistration(client, m->publish->topic); goto exit; } #endif #if defined(QOS0_SEND_LIMIT) if (m->qos == 0) ++qos0count; #endif pubrc = MQTTProtocol_startQueuedPublish(client, m); /* regardless of whether the publish packet was sent on the wire (pubrc is good), the * message has been put onto the outbound queue, so it must be removed from * the queuedMsgs queue */ if (pubrc != TCPSOCKET_COMPLETE && pubrc != TCPSOCKET_INTERRUPTED) client->good = 0; if (m->qos == 0) { /* This is done primarily for MQTT-S. * A qos-0 message will be on this queue if its topic * has to be registered first. Now that the message * has been sent, it needs to be cleaned up as there * won't be an ack to trigger it. * * For MQTT, there is a scenario in which qos-0 messages * could be on this list for which the same applies. * * Note (IGC): this is also a bug fix I just implemented - applies equally to MQTTs and MQTT! */ MQTTProtocol_removePublication(m->publish); if (!ListRemove(queue, m)) Log(LOG_ERROR, 38, NULL); } else if (!ListDetach(queue, m)) Log(LOG_ERROR, 38, NULL); if (queuedMsgsCount(client) == threshold - 1 && !threshold_log_message_issued) { Log(LOG_INFO, 146, NULL, client->clientID, THRESHOLD); threshold_log_message_issued = 1; } } #if defined(QOS0_SEND_LIMIT) if (qos0count >= bstate->max_inflight_messages) rc = 1; #endif exit: FUNC_EXIT_RC(rc); return rc; }
int ListRemove(List *list, void *payload) { if (!list || !payload) return -1; ListNode *node = NULL; /* * This is a complicated matter. We could detach the list before * we know that we have a new node, but that will mean that we * might have copied the whole list without real reasons. On the * other hand, it saves us a whole traversal of the list if we * just do it. */ int found = ListFindNode(list, payload); if (!found) return -1; found = 0; ListDetach(list); node = NULL; /* * We need to find the node again since we have a new list. * In theory we don't have to worry about the existence of the node, * since the list has not changed, it might have been copied but * it is still the same as before. */ for (node = list->list; node; node = node->next) { if (list->compare) { if (!list->compare(node->payload, payload)) { found = 1; break; } } else { if (node->payload == payload) { found = 1; break; } } } /* * This is nearly impossible, so we will only assert it. */ assert(found == 1); /* * Before deleting the node we have to update the mutable iterator. * We might need to advance it! */ if (list->iterator) { if (list->iterator->current == node) { /* * So lucky, it is the same node! * Move the iterator so it is not dangling. * Rules for moving: * 1. Move forward. * 2. if not possible, move backward. * 3. If not possible, then invalidate the iterator. */ if (list->iterator->current->next) { list->iterator->current = list->iterator->current->next; } else if (list->iterator->current->previous) { list->iterator->current = list->iterator->current->previous; } else { list->iterator->valid = 0; } } } /* * Now, remove the node from the list and delete it. */ if (node->next && node->previous) { // Middle of the list node->next->previous = node->previous; node->previous->next = node->next; } else if (node->next) { // First element of the list list->list = node->next; list->first = node->next; node->next->previous = NULL; } else if (node->previous) { // Last element node->previous->next = NULL; list->last = node->previous; } else { // Single element list->list = NULL; list->first = NULL; list->last = NULL; } if (list->destroy && node->payload) { list->destroy(node->payload); } else { free (node->payload); } free(node); ListUpdateListState(list); return 0; }