/** * 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; }
/** * Publish a message to the system log topic * @param topic topic to publish on * @param string the message to publish */ void Log_Publish(char* topic, char* string) { Publish publish; publish.header.byte = 0; /* Qos 0, not retained */ publish.payload = string; publish.payloadlen = strlen(string); publish.topic = topic; MQTTProtocol_handlePublishes(&publish, 0, NULL); }
MQTTPacket* MQTTClient_cycle(int* sock, unsigned long timeout, int* rc) { struct timeval tp = {0L, 0L}; static Ack ack; MQTTPacket* pack = NULL; FUNC_ENTRY; if (timeout > 0L) { tp.tv_sec = timeout / 1000; tp.tv_usec = (timeout % 1000) * 1000; /* this field is microseconds! */ } #if defined(OPENSSL) if ((*sock = SSLSocket_getPendingRead()) == -1) { /* 0 from getReadySocket indicates no work to do, -1 == error, but can happen normally */ #endif Thread_lock_mutex(socket_mutex); *sock = Socket_getReadySocket(0, &tp); Thread_unlock_mutex(socket_mutex); #if defined(OPENSSL) } #endif Thread_lock_mutex(mqttclient_mutex); if (*sock > 0) { MQTTClients* m = NULL; if (ListFindItem(handles, sock, clientSockCompare) != NULL) m = (MQTTClient)(handles->current->content); if (m != NULL) { if (m->c->connect_state == 1 || m->c->connect_state == 2) *rc = 0; /* waiting for connect state to clear */ else { pack = MQTTPacket_Factory(&m->c->net, rc); if (*rc == TCPSOCKET_INTERRUPTED) *rc = 0; } } if (pack) { int freed = 1; /* Note that these handle... functions free the packet structure that they are dealing with */ if (pack->header.bits.type == PUBLISH) *rc = MQTTProtocol_handlePublishes(pack, *sock); else if (pack->header.bits.type == PUBACK || pack->header.bits.type == PUBCOMP) { int msgid; ack = (pack->header.bits.type == PUBCOMP) ? *(Pubcomp*)pack : *(Puback*)pack; msgid = ack.msgId; *rc = (pack->header.bits.type == PUBCOMP) ? MQTTProtocol_handlePubcomps(pack, *sock) : MQTTProtocol_handlePubacks(pack, *sock); if (m && m->dc) { Log(TRACE_MIN, -1, "Calling deliveryComplete for client %s, msgid %d", m->c->clientID, msgid); (*(m->dc))(m->context, msgid); } } else if (pack->header.bits.type == PUBREC) *rc = MQTTProtocol_handlePubrecs(pack, *sock); else if (pack->header.bits.type == PUBREL) *rc = MQTTProtocol_handlePubrels(pack, *sock); else if (pack->header.bits.type == PINGRESP) *rc = MQTTProtocol_handlePingresps(pack, *sock); else freed = 0; if (freed) pack = NULL; } } MQTTClient_retry(); Thread_unlock_mutex(mqttclient_mutex); FUNC_EXIT_RC(*rc); return pack; }