int MQTTProtocol_handleGets(void* pack, int sock) { Getack* getack = (Getack*)pack; Clients* client = NULL; char* clientid = NULL; int rc = TCPSOCKET_COMPLETE; FUNC_ENTRY; // printf("------>%s, %s, %d\n", __func__, getack->ack_payload.ret_string, getack->ack_payload.ext_cmd); client = (Clients*)(ListFindItem(bstate->clients, &sock, clientSocketCompare)->content); clientid = client->clientID; // Log(LOG_PROTOCOL, 11, NULL, sock, clientid, getack->msgId, get->header.bits.qos, // getack->header.bits.retain, min(20, getack->ext_payloadlen), get->ext_payload); /* here we needn't process some just like publish. only to parse ext ack, get one callback. */ #if 0 if (get->header.bits.qos == 0) Protocol_processPublication(get, client); else if (get->header.bits.qos == 1) { /* send puback before processing the publications because a lot of return publications could fill up the socket buffer */ rc = MQTTPacket_send_puback(publish->msgId, &client->net, client->clientID); /* if we get a socket error from sending the puback, should we ignore the publication? */ Protocol_processPublication(publish, client); } else if (publish->header.bits.qos == 2) { /* store publication in inbound list */ int len; ListElement* listElem = NULL; Messages* m = malloc(sizeof(Messages)); Publications* p = MQTTProtocol_storePublication(publish, &len); m->publish = p; m->msgid = publish->msgId; m->qos = publish->header.bits.qos; m->retain = publish->header.bits.retain; m->nextMessageType = PUBREL; if ( ( listElem = ListFindItem(client->inboundMsgs, &(m->msgid), messageIDCompare) ) != NULL ) { /* discard queued publication with same msgID that the current incoming message */ Messages* msg = (Messages*)(listElem->content); MQTTProtocol_removePublication(msg->publish); ListInsert(client->inboundMsgs, m, sizeof(Messages) + len, listElem); ListRemove(client->inboundMsgs, msg); } else ListAppend(client->inboundMsgs, m, sizeof(Messages) + len); rc = MQTTPacket_send_pubrec(publish->msgId, &client->net, client->clientID); publish->topic = NULL; } MQTTPacket_freePublish(publish); #endif MQTTPacket_freeGet(getack); FUNC_EXIT_RC(rc); return rc; }
/** * 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; }
/** * 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) { Pubrel* pubrel = (Pubrel*)pack; Clients* client = NULL; int rc = TCPSOCKET_COMPLETE; FUNC_ENTRY; client = (Clients*)(ListFindItem(bstate->clients, &sock, clientSocketCompare)->content); 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(TRACE_MIN, 3, NULL, "PUBREL", client->clientID, pubrel->msgId); else /* Apparently this is "normal" behaviour, so we don't need to issue a warning */ rc = MQTTPacket_send_pubcomp(pubrel->msgId, &client->net, client->clientID); } else { Messages* m = (Messages*)(client->inboundMsgs->current->content); if (m->qos != 2) Log(TRACE_MIN, 4, NULL, "PUBREL", client->clientID, pubrel->msgId, m->qos); else if (m->nextMessageType != PUBREL) Log(TRACE_MIN, 5, NULL, "PUBREL", client->clientID, pubrel->msgId); else { Publish publish; /* send pubcomp before processing the publications because a lot of return publications could fill up the socket buffer */ rc = MQTTPacket_send_pubcomp(pubrel->msgId, &client->net, client->clientID); publish.header.bits.qos = m->qos; publish.header.bits.retain = m->retain; publish.msgId = m->msgid; publish.topic = m->publish->topic; publish.topiclen = m->publish->topiclen; publish.payload = m->publish->payload; publish.payloadlen = m->publish->payloadlen; Protocol_processPublication(&publish, client); #if !defined(NO_PERSISTENCE) rc += MQTTPersistence_remove(client, PERSISTENCE_PUBLISH_RECEIVED, m->qos, pubrel->msgId); #endif ListRemove(&(state.publications), m->publish); ListRemove(client->inboundMsgs, m); ++(state.msgs_received); } } free(pack); FUNC_EXIT_RC(rc); return rc; }
int MQTTSProtocol_handlePubrels(void* pack, int sock, char* clientAddr, Clients* client) { int rc = 0; MQTTS_PubRel* pubrel = (MQTTS_PubRel*)pack; FUNC_ENTRY; /* look for the message by message id in the records of inbound messages for this client */ if (ListFindItem(client->inboundMsgs, &(pubrel->msgId), messageIDCompare) == NULL) { /* TODO: no dup flag in mqtts... not sure this is right if (pubrel->header.dup == 0) Log(LOG_WARNING, 50, "PUBREL", client->clientID, pubrel->msgId); else */ /* Apparently this is "normal" behavior, so we don't need to issue a warning */ rc = MQTTSPacket_send_pubcomp(client,pubrel->msgId); } 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; /* send pubcomp before processing the publications because a lot of return publications could fill up the socket buffer */ rc = MQTTSPacket_send_pubcomp(client, pubrel->msgId); 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; Protocol_processPublication(&publish, client->clientID); MQTTProtocol_removePublication(m->publish); ListRemove(client->inboundMsgs, m); /* TODO: msgs counts */ /* ++(state.msgs_received); */ } } time( &(client->lastContact) ); MQTTSPacket_free_packet(pack); FUNC_EXIT_RC(rc); return rc; }
int Protocol_handlePublishes(Publish* publish, int sock, Clients* client, char* clientid) { int rc = TCPSOCKET_COMPLETE; #if !defined(SINGLE_LISTENER) Listener* listener = NULL; #endif FUNC_ENTRY; if (Protocol_isClientQuiescing(client)) goto exit; /* don't accept new work */ #if !defined(SINGLE_LISTENER) listener = Socket_getParentListener(sock); if (listener && listener->mount_point) { char* temp = malloc(strlen(publish->topic) + strlen(listener->mount_point) + 1); strcpy(temp, listener->mount_point); strcat(temp, publish->topic); free(publish->topic); publish->topic = temp; } #endif #if !defined(NO_BRIDGE) if (client && client->outbound) Bridge_handleInbound(client, publish); #endif if (publish->header.bits.qos == 0) { if (strlen(publish->topic) < 5 || strncmp(publish->topic, sysprefix, strlen(sysprefix)) != 0) { ++(bstate->msgs_received); bstate->bytes_received += publish->payloadlen; } Protocol_processPublication(publish, clientid); } else if (publish->header.bits.qos == 1) { /* send puback before processing the publications because a lot of return publications could fill up the socket buffer */ #if defined(MQTTS) if (client->protocol == PROTOCOL_MQTTS) rc = MQTTSPacket_send_puback(client, publish->msgId, MQTTS_RC_ACCEPTED); else #endif rc = MQTTPacket_send_puback(publish->msgId, sock, clientid); /* if we get a socket error from sending the puback, should we ignore the publication? */ Protocol_processPublication(publish, clientid); ++(bstate->msgs_received); bstate->bytes_received += publish->payloadlen; } else if (publish->header.bits.qos == 2 && client->inboundMsgs->count < bstate->max_inflight_messages) { /* store publication in inbound list - if list is full, ignore and rely on client retry */ int len; ListElement* listElem = NULL; Messages* m = NULL; Publications* p = MQTTProtocol_storePublication(publish, &len); if ((listElem = ListFindItem(client->inboundMsgs, &publish->msgId, messageIDCompare)) != NULL) { m = (Messages*)(listElem->content); MQTTProtocol_removePublication(m->publish); /* remove old publication data - could be different */ } else m = malloc(sizeof(Messages)); m->publish = p; m->msgid = publish->msgId; m->qos = publish->header.bits.qos; m->retain = publish->header.bits.retain; m->nextMessageType = PUBREL; if (listElem == NULL) ListAppend(client->inboundMsgs, m, sizeof(Messages) + len); #if defined(MQTTS) if (client->protocol == PROTOCOL_MQTTS) rc = MQTTSPacket_send_pubrec(client, publish->msgId); else #endif rc = MQTTPacket_send_pubrec(publish->msgId, sock, clientid); } else if (publish->header.bits.qos == 3) /* only applies to MQTT-S */ { publish->header.bits.qos = 0; Protocol_processPublication(publish, clientid); } exit: if (sock > 0) MQTTPacket_freePublish(publish); FUNC_EXIT_RC(rc); return rc; }
/** * Process an incoming publish 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_handlePublishes(void* pack, int sock) { Publish* publish = (Publish*)pack; Clients* client = NULL; char* clientid = NULL; int rc = TCPSOCKET_COMPLETE; #if !defined(SINGLE_LISTENER) Listener* listener = Socket_getParentListener(sock); #endif FUNC_ENTRY; if (sock == 0) clientid = INTERNAL_CLIENTID; /* this is an internal client */ else { client = (Clients*)(ListFindItem(bstate->clients, &sock, clientSocketCompare)->content); clientid = client->clientID; Log(LOG_PROTOCOL, 11, NULL, sock, clientid, publish->msgId, publish->header.bits.qos, publish->header.bits.retain, min(20, publish->payloadlen), publish->payload); if (Protocol_isClientQuiescing(client)) goto exit; /* don't accept new work */ #if !defined(SINGLE_LISTENER) if (listener && listener->mount_point) { char* temp = malloc(strlen(publish->topic) + strlen(listener->mount_point) + 1); strcpy(temp, listener->mount_point); strcat(temp, publish->topic); free(publish->topic); publish->topic = temp; } #endif } #if !defined(NO_BRIDGE) if (client && client->outbound) Bridge_handleInbound(client, publish); #endif if (publish->header.bits.qos == 0) { if (strlen(publish->topic) < 5 || strncmp(publish->topic, sysprefix, strlen(sysprefix)) != 0) { ++(bstate->msgs_received); bstate->bytes_received += publish->payloadlen; } Protocol_processPublication(publish, clientid); } else if (publish->header.bits.qos == 1) { /* send puback before processing the publications because a lot of return publications could fill up the socket buffer */ rc = MQTTPacket_send_puback(publish->msgId, sock, clientid); /* if we get a socket error from sending the puback, should we ignore the publication? */ Protocol_processPublication(publish, clientid); ++(bstate->msgs_received); bstate->bytes_received += publish->payloadlen; } else if (publish->header.bits.qos == 2) { /* store publication in inbound list */ int len; ListElement* listElem = NULL; Messages* m = NULL; Publications* p = NULL; /*if list is full, disconnect the client with warning message */ if (client->inboundMsgs->count >= (bstate->max_inflight_messages*2)) { Log(LOG_WARNING, 69, NULL, clientid); rc = SOCKET_ERROR; /* will cause the client to be disconnected */ goto exit; } p = MQTTProtocol_storePublication(publish, &len); if ((listElem = ListFindItem(client->inboundMsgs, &publish->msgId, messageIDCompare)) != NULL) { m = (Messages*)(listElem->content); MQTTProtocol_removePublication(m->publish); /* remove old publication data - could be different */ } else m = malloc(sizeof(Messages)); m->publish = p; m->msgid = publish->msgId; m->qos = publish->header.bits.qos; m->priority = publish->priority; m->retain = publish->header.bits.retain; m->nextMessageType = PUBREL; if (listElem == NULL) ListAppend(client->inboundMsgs, m, sizeof(Messages) + len); rc = MQTTPacket_send_pubrec(publish->msgId, sock, clientid); } exit: if (sock < -1 || sock > 0) MQTTPacket_freePublish(publish); FUNC_EXIT_RC(rc); return rc; }
/** * Close any active session for a client and clean up. * @param client the client to clean up * @param send_will flag to indicate whether a will messsage should be sent if it has been set */ void MQTTProtocol_closeSession(Clients* client, int send_will) { FUNC_ENTRY; client->good = 0; if (in_MQTTPacket_Factory == client->socket || client->closing) goto exit; client->closing = 1; if (client->socket > 0) { if (client->connected) { if (client->outbound && client->will) { Publish pub; pub.payload = "0"; pub.payloadlen = 1; pub.topic = client->will->topic; #if defined(MQTTS) if (client->protocol == PROTOCOL_MQTTS) MQTTSProtocol_startPublishCommon(client, &pub, 0,0,1); if (client->protocol == PROTOCOL_MQTTS_DTLS) MQTTSProtocol_startPublishCommon(client, &pub, 0,0,1); //TODO LW else #endif MQTTPacket_send_publish(&pub, 0, 0, 1, client->socket, client->clientID); MQTTProtocol_sys_publish(client->will->topic, "0"); } #if defined(MQTTS) if (client->protocol == PROTOCOL_MQTTS_MULTICAST) ; else if (client->protocol == PROTOCOL_MQTTS) MQTTSPacket_send_disconnect(client, 0); else if (client->protocol == PROTOCOL_MQTTS_DTLS) MQTTSPacket_send_disconnect(client, 0); else #endif if (client->outbound) MQTTPacket_send_disconnect(client->socket, client->clientID); } if (ListFindItem(&(state.pending_writes), &(client->socket), intcompare)) { pending_write* pw = (pending_write*)(state.pending_writes.current->content); MQTTProtocol_removePublication(pw->p); ListRemove(&(state.pending_writes), pw); } #if defined(MQTTS) if (client->protocol == PROTOCOL_MQTT || client->outbound == 1) { if (client->protocol == PROTOCOL_MQTTS_MULTICAST) Socket_close_only(client->socket); else #endif Socket_close(client->socket); #if defined(MQTTS) } #endif } if (client->connected || client->connect_state) { client->connected = 0; client->connect_state = 0; } if (client->outbound == 0 && client->will != NULL && send_will) { Publish publish; publish.payload = client->will->msg; publish.payloadlen = strlen(client->will->msg); publish.topic = client->will->topic; publish.header.bits.qos = client->will->qos; publish.header.bits.retain = client->will->retained; Protocol_processPublication(&publish, client->clientID); } #if defined(MQTTS) if (client->protocol == PROTOCOL_MQTTS) MQTTSProtocol_emptyRegistrationList(client->registrations); else if (client->protocol == PROTOCOL_MQTTS_DTLS) MQTTSProtocol_emptyRegistrationList(client->registrations); #endif if (client->cleansession) { if (client->outbound && ((BridgeConnections*)(client->bridge_context))->state != CONNECTION_DELETE) { /* bridge outbound client structures are reused on reconnection */ int i; MQTTProtocol_removeAllSubscriptions(client->clientID); MQTTProtocol_emptyMessageList(client->inboundMsgs); MQTTProtocol_emptyMessageList(client->outboundMsgs); for (i = 0; i < PRIORITY_MAX; ++i) MQTTProtocol_emptyMessageList(client->queuedMsgs[i]); client->msgID = 0; } else { #if defined(MQTTS) if ((client->protocol == PROTOCOL_MQTTS && client->outbound == 0) || (client->protocol == PROTOCOL_MQTTS_DTLS && client->outbound == 0) || client->protocol == PROTOCOL_MQTTS_MULTICAST) { if (!TreeRemove(bstate->mqtts_clients, client) && !TreeRemove(bstate->disconnected_mqtts_clients, client)) Log(LOG_ERROR, 39, NULL); else Log(TRACE_MAX, 2, NULL, client->clientID, client->socket); } else { #endif if (!TreeRemove(bstate->clients, client) && !TreeRemove(bstate->disconnected_clients, client)) Log(LOG_ERROR, 39, NULL); else Log(TRACE_MAX, 2, NULL, client->clientID, client->socket); #if defined(MQTTS) } #endif MQTTProtocol_freeClient(client); } } else { int i; for (i = 0; i < PRIORITY_MAX; ++i) MQTTProtocol_removeQoS0Messages(client->queuedMsgs[i]); #if defined(MQTTS) if ((client->protocol == PROTOCOL_MQTTS && client->outbound == 0)||(client->protocol == PROTOCOL_MQTTS_DTLS && client->outbound == 0)) { if (TreeRemove(bstate->mqtts_clients, client)) { client->socket = 0; TreeAdd(bstate->disconnected_mqtts_clients, client, sizeof(Clients) + strlen(client->clientID)+1 + 3*sizeof(List)); } } else { #endif if (TreeRemove(bstate->clients, client)) { client->socket = 0; TreeAdd(bstate->disconnected_clients, client, sizeof(Clients) + strlen(client->clientID)+1 + 3*sizeof(List)); } #if defined(MQTTS) } #endif client->closing = 0; } exit: FUNC_EXIT; }