/** * Internal publication to a system topic. * @param topic the topic to publish on * @param string the data to publish */ void MQTTProtocol_sys_publish(char* topic, char* string) { List* rpl = NULL; int doPublish = 1; FUNC_ENTRY; rpl = SubscriptionEngines_getRetained(bstate->se, topic); if (rpl->count > 0) /* this should be at most 1, as we must use a non-wildcard topic (for publishing) */ { RetainedPublications* rp = (RetainedPublications*)(rpl->first->content); if (strlen(string) == rp->payloadlen && memcmp(rp->payload, string, rp->payloadlen) == 0) doPublish = 0; } ListFreeNoContent(rpl); if (doPublish) { Publish publish; publish.header.byte = 0; publish.header.bits.retain = 1; publish.payload = string; publish.payloadlen = strlen(string); publish.topic = topic; MQTTProtocol_handlePublishes(&publish, 0, NULL); } FUNC_EXIT; }
/** * 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; }
int MQTTClient_unsubscribeMany(MQTTClient handle, int count, char* const* topic) { MQTTClients* m = handle; List* topics = ListInitialize(); int i = 0; int rc = SOCKET_ERROR; int msgid = 0; FUNC_ENTRY; Thread_lock_mutex(mqttclient_mutex); if (m == NULL || m->c == NULL) { rc = MQTTCLIENT_FAILURE; goto exit; } if (m->c->connected == 0) { rc = MQTTCLIENT_DISCONNECTED; goto exit; } for (i = 0; i < count; i++) { if (!UTF8_validateString(topic[i])) { rc = MQTTCLIENT_BAD_UTF8_STRING; goto exit; } } if ((msgid = MQTTProtocol_assignMsgId(m->c)) == 0) { rc = MQTTCLIENT_MAX_MESSAGES_INFLIGHT; goto exit; } for (i = 0; i < count; i++) ListAppend(topics, topic[i], strlen(topic[i])); rc = MQTTProtocol_unsubscribe(m->c, topics, msgid); ListFreeNoContent(topics); if (rc == TCPSOCKET_COMPLETE) { MQTTPacket* pack = NULL; Thread_unlock_mutex(mqttclient_mutex); pack = MQTTClient_waitfor(handle, UNSUBACK, &rc, 10000L); Thread_lock_mutex(mqttclient_mutex); if (pack != NULL) { rc = MQTTProtocol_handleUnsubacks(pack, m->c->net.socket); m->pack = NULL; } else rc = SOCKET_ERROR; } if (rc == SOCKET_ERROR) { Thread_unlock_mutex(mqttclient_mutex); MQTTClient_disconnect_internal(handle, 0); Thread_lock_mutex(mqttclient_mutex); } exit: Thread_unlock_mutex(mqttclient_mutex); FUNC_EXIT_RC(rc); return rc; }
int MQTTClient_subscribeMany(MQTTClient handle, int count, char* const* topic, int* qos) { MQTTClients* m = handle; List* topics = ListInitialize(); List* qoss = ListInitialize(); int i = 0; int rc = MQTTCLIENT_FAILURE; int msgid = 0; FUNC_ENTRY; Thread_lock_mutex(mqttclient_mutex); if (m == NULL || m->c == NULL) { rc = MQTTCLIENT_FAILURE; goto exit; } if (m->c->connected == 0) { rc = MQTTCLIENT_DISCONNECTED; goto exit; } for (i = 0; i < count; i++) { if (!UTF8_validateString(topic[i])) { rc = MQTTCLIENT_BAD_UTF8_STRING; goto exit; } if(qos[i] < 0 || qos[i] > 2) { rc = MQTTCLIENT_BAD_QOS; goto exit; } } if ((msgid = MQTTProtocol_assignMsgId(m->c)) == 0) { rc = MQTTCLIENT_MAX_MESSAGES_INFLIGHT; goto exit; } for (i = 0; i < count; i++) { ListAppend(topics, topic[i], strlen(topic[i])); ListAppend(qoss, &qos[i], sizeof(int)); } rc = MQTTProtocol_subscribe(m->c, topics, qoss, msgid); ListFreeNoContent(topics); ListFreeNoContent(qoss); if (rc == TCPSOCKET_COMPLETE) { MQTTPacket* pack = NULL; Thread_unlock_mutex(mqttclient_mutex); pack = MQTTClient_waitfor(handle, SUBACK, &rc, 10000L); Thread_lock_mutex(mqttclient_mutex); if (pack != NULL) { Suback* sub = (Suback*)pack; ListElement* current = NULL; i = 0; while (ListNextElement(sub->qoss, ¤t)) { int* reqqos = (int*)(current->content); qos[i++] = *reqqos; } rc = MQTTProtocol_handleSubacks(pack, m->c->net.socket); m->pack = NULL; } else rc = SOCKET_ERROR; } if (rc == SOCKET_ERROR) { Thread_unlock_mutex(mqttclient_mutex); MQTTClient_disconnect_internal(handle, 0); Thread_lock_mutex(mqttclient_mutex); } else if (rc == TCPSOCKET_COMPLETE) rc = MQTTCLIENT_SUCCESS; exit: Thread_unlock_mutex(mqttclient_mutex); FUNC_EXIT_RC(rc); return rc; }
int MQTTClient_subscribeMany(MQTTClient handle, int count, char** topic, int* qos) { MQTTClients* m = handle; List* topics = ListInitialize(); List* qoss = ListInitialize(); int i = 0; int rc = MQTTCLIENT_FAILURE; FUNC_ENTRY; Thread_lock_mutex(mqttclient_mutex); if (m == NULL || m->c == NULL) { rc = MQTTCLIENT_FAILURE; goto exit; } if (m->c->connected == 0) { rc = MQTTCLIENT_DISCONNECTED; goto exit; } for (i = 0; i < count; i++) { if (!UTF8_validateString(topic[i])) { rc = MQTTCLIENT_BAD_UTF8_STRING; goto exit; } } for (i = 0; i < count; i++) { ListAppend(topics, topic[i], strlen(topic[i])); ListAppend(qoss, &qos[i], sizeof(int)); } rc = MQTTProtocol_subscribe(m->c, topics, qoss); ListFreeNoContent(topics); ListFreeNoContent(qoss); if (rc == TCPSOCKET_COMPLETE) { MQTTPacket* pack = NULL; Thread_unlock_mutex(mqttclient_mutex); pack = MQTTClient_waitfor(handle, SUBACK, &rc, 10000L); Thread_lock_mutex(mqttclient_mutex); if (pack != NULL) { rc = MQTTProtocol_handleSubacks(pack, m->c->socket); m->pack = NULL; } else rc = SOCKET_ERROR; } if (rc == SOCKET_ERROR) { Thread_unlock_mutex(mqttclient_mutex); MQTTClient_disconnect_internal(handle, 0); Thread_lock_mutex(mqttclient_mutex); } else if (rc == TCPSOCKET_COMPLETE) rc = MQTTCLIENT_SUCCESS; exit: Thread_unlock_mutex(mqttclient_mutex); FUNC_EXIT_RC(rc); return rc; }