/** * Allocates a block of memory. A direct replacement for malloc, but keeps track of items * allocated in a list, so that free can check that a item is being freed correctly and that * we can check that all memory is freed at shutdown. * @param file use the __FILE__ macro to indicate which file this item was allocated in * @param line use the __LINE__ macro to indicate which line this item was allocated at * @param size the size of the item to be allocated * @return pointer to the allocated item, or NULL if there was an error */ void* mymalloc(char* file, int line, size_t size) { storageElement* s = NULL; size_t space = sizeof(storageElement); size_t filenamelen = strlen(file)+1; Thread_lock_mutex(heap_mutex); size = Heap_roundup(size); if ((s = malloc(sizeof(storageElement))) == NULL) { Log(LOG_ERROR, 13, errmsg); return NULL; } s->size = size; /* size without eyecatchers */ if ((s->file = malloc(filenamelen)) == NULL) { Log(LOG_ERROR, 13, errmsg); free(s); return NULL; } space += filenamelen; strcpy(s->file, file); s->line = line; /* Add space for eyecatcher at each end */ if ((s->ptr = malloc(size + 2*sizeof(int))) == NULL) { Log(LOG_ERROR, 13, errmsg); free(s->file); free(s); return NULL; } space += size + 2*sizeof(int); *(int*)(s->ptr) = eyecatcher; /* start eyecatcher */ *(int*)(((char*)(s->ptr)) + (sizeof(int) + size)) = eyecatcher; /* end eyecatcher */ Log(TRACE_MAX, -1, "Allocating %d bytes in heap at file %s line %d ptr %p\n", size, file, line, s->ptr); TreeAdd(&heap, s, space); state.current_size += size; if (state.current_size > state.max_size) state.max_size = state.current_size; Thread_unlock_mutex(heap_mutex); return ((int*)(s->ptr)) + 1; /* skip start eyecatcher */ }
void ItemRecord::TreeAdd(ItemRecord *r, int c) { // dodanie rekordu do drzewa - ustalenie w której ga³êzi // zapisaæ w (iFlags) ile znaków jest zgodnych z nadrzêdnym, ¿eby nie sprawdzaæ wszystkich od // zera if ((cName[c] && r->cName[c]) ? cName[c] == r->cName[c] : false) TreeAdd(r, c + 1); // ustawiæ wg kolejnego znaku, chyba ¿e zero else if ((unsigned char)(cName[c]) < (unsigned char)(r->cName[c])) { // zero jest najmniejsze - doczepiamy jako (rNext) if (!rNext) rNext = r; else rNext->TreeAdd(r, 0); // doczepiæ do tej ga³êzi } else { if (!rPrev) rPrev = r; else rPrev->TreeAdd(r, 0); // doczepiæ do tej ga³êzi } };
/** * Reallocates a block of memory. A direct replacement for realloc, but keeps track of items * allocated in a list, so that free can check that a item is being freed correctly and that * we can check that all memory is freed at shutdown. * We have to remove the item from the tree, as the memory is in order and so it needs to * be reinserted in the correct place. * @param file use the __FILE__ macro to indicate which file this item was reallocated in * @param line use the __LINE__ macro to indicate which line this item was reallocated at * @param p pointer to the item to be reallocated * @param size the new size of the item * @return pointer to the allocated item, or NULL if there was an error */ void *myrealloc(char* file, int line, void* p, size_t size) { void* rc = NULL; storageElement* s = NULL; Thread_lock_mutex(heap_mutex); s = TreeRemoveKey(&heap, ((int*)p)-1); if (s == NULL) Log(LOG_ERROR, 13, "Failed to reallocate heap item at file %s line %d", file, line); else { size_t space = sizeof(storageElement); size_t filenamelen = strlen(file)+1; checkEyecatchers(file, line, p, s->size); size = Heap_roundup(size); state.current_size += size - s->size; if (state.current_size > state.max_size) state.max_size = state.current_size; if ((s->ptr = realloc(s->ptr, size + 2*sizeof(int))) == NULL) { Log(LOG_ERROR, 13, errmsg); return NULL; } space += size + 2*sizeof(int) - s->size; *(int*)(s->ptr) = eyecatcher; /* start eyecatcher */ *(int*)(((char*)(s->ptr)) + (sizeof(int) + size)) = eyecatcher; /* end eyecatcher */ s->size = size; space -= strlen(s->file); s->file = realloc(s->file, filenamelen); space += filenamelen; strcpy(s->file, file); s->line = line; rc = s->ptr; TreeAdd(&heap, s, space); } Thread_unlock_mutex(heap_mutex); return (rc == NULL) ? NULL : ((int*)(rc)) + 1; /* skip start eyecatcher */ }
void MQTTSProtocol_reconnect(char* ip_address, Clients* client) { int port, rc; char *address = NULL; Clients* oldc = NULL; FUNC_ENTRY; oldc = TreeRemoveKeyIndex(bstate->disconnected_clients, client->clientID, 1); if (oldc == NULL) oldc = TreeRemoveKeyIndex(bstate->clients, client->clientID, 1); client->good = 1; client->ping_outstanding = 0; client->connect_state = 0; client->connected = 0; if (client->cleansession) client->msgID = 0; if (client->addr) free(client->addr); client->addr = malloc(strlen(ip_address)); strcpy(client->addr, ip_address); address = MQTTProtocol_addressPort(ip_address, &port); rc = Socket_new_type(address, port, &(client->socket), SOCK_DGRAM); if (rc == EINPROGRESS || rc == EWOULDBLOCK) client->connect_state = 1; /* UDP connect called - improbable, but possible on obscure platforms */ else if (rc == 0) { client->connect_state = 2; // TCP connect completed, in which case send the MQTT connect packet MQTTSPacket_send_connect(client); time(&(client->lastContact)); } TreeAdd(bstate->clients, client, sizeof(Clients) + strlen(client->clientID)+1 + 3*sizeof(List)); FUNC_EXIT; }
int test(int limit) { int i, *ip, *todelete; Node* current = NULL; Tree* t = TreeInitialize(TreeIntCompare); int rc = 0; printf("Tree initialized\n"); srand(time(NULL)); ip = malloc(sizeof(int)); *ip = 2; TreeAdd(t, (void*)ip, sizeof(int)); check(t); i = 2; void* result = TreeRemove(t, (void*)&i); if (result) free(result); int actual[limit]; for (i = 0; i < limit; i++) { void* replaced = NULL; ip = malloc(sizeof(int)); *ip = rand(); replaced = TreeAdd(t, (void*)ip, sizeof(int)); if (replaced) /* duplicate */ { free(replaced); actual[i] = -1; } else actual[i] = *ip; if (i==5) todelete = ip; printf("Tree element added %d\n", *ip); if (1 % 1000 == 0) { rc = check(t); printf("%d elements, check result %d\n", i+1, rc); if (rc != 0) return 88; } } check(t); for (i = 0; i < limit; i++) { int parm = actual[i]; if (parm == -1) continue; Node* found = TreeFind(t, (void*)&parm); if (found) printf("Tree find %d %d\n", parm, *(int*)(found->content)); else { printf("%d not found\n", parm); traverse(t, parm); return -2; } } check(t); for (i = limit -1; i >= 0; i--) { int parm = actual[i]; void *found; if (parm == -1) /* skip duplicate */ continue; found = TreeRemove(t, (void*)&parm); if (found) { printf("%d Tree remove %d %d\n", i, parm, *(int*)(found)); free(found); } else { int count = 0; printf("%d %d not found\n", i, parm); traverse(t, parm); for (i = 0; i < limit; i++) if (actual[i] == parm) ++count; printf("%d occurs %d times\n", parm, count); return -2; } if (i % 1000 == 0) { rc = check(t); printf("%d elements, check result %d\n", i+1, rc); if (rc != 0) return 88; } } printf("finished\n"); return 0; }
int MQTTSProtocol_handleConnects(void* pack, int sock, char* clientAddr, Clients* client, uint8_t* wirelessNodeId , uint8_t wirelessNodeIdLen) { MQTTS_Connect* connect = (MQTTS_Connect*)pack; Listener* list = NULL; int terminate = 0; Node* elem = NULL; int rc = 0; int existingClient = 0; FUNC_ENTRY; Log(LOG_PROTOCOL, 39, NULL, sock, clientAddr, client ? client->clientID : "", connect->flags.cleanSession); if (bstate->clientid_prefixes->count > 0 && !ListFindItem(bstate->clientid_prefixes, connect->clientID, clientPrefixCompare)) { Log(LOG_WARNING, 31, NULL, connect->clientID); terminate = 1; } else { list = Socket_getParentListener(sock); if (list->max_connections > -1 && list->connections->count > list->max_connections) { /* TODO: why is this commented out? delete if not needed //MQTTPacket_send_connack(3, sock); */ Log(LOG_WARNING, 141, NULL, connect->clientID, list->max_connections, list->port); terminate = 1; } else if (connect->protocolID != 1) { Log(LOG_WARNING, 32, NULL, "MQTT-S", connect->protocolID); /* TODO: why is this commented out? delete if not needed //MQTTPacket_send_connack(1, sock); */ terminate = 1; } } if (terminate) { /*TODO: process the terminate*/ MQTTSPacket_free_packet(pack); goto exit; } if (client != NULL && !strcmp(client->clientID, connect->clientID)) { /* Connect for a new client id on a used addr * TODO: clean out 'old' Client (that may be 'connected') */ } elem = TreeFindIndex(bstate->mqtts_clients, connect->clientID, 1); if (elem == NULL) { client = TreeRemoveKey(bstate->disconnected_mqtts_clients, connect->clientID); if (client == NULL) /* this is a totally new connection */ { /* Brand new client connection */ int i; client = malloc(sizeof(Clients)); memset(client, '\0', sizeof(Clients)); client->protocol = PROTOCOL_MQTTS; client->outboundMsgs = ListInitialize(); client->inboundMsgs = ListInitialize(); for (i = 0; i < PRIORITY_MAX; ++i) client->queuedMsgs[i] = ListInitialize(); client->registrations = ListInitialize(); client->noLocal = 0; /* (connect->version == PRIVATE_PROTOCOL_VERSION) ? 1 : 0; */ client->clientID = connect->clientID; connect->clientID = NULL; /* don't want to free this space as it is being used in the clients tree below */ // Set Wireless Node ID if exists if ( wirelessNodeId == NULL) { client->wirelessNodeId = NULL ; client->wirelessNodeIdLen = 0 ; } else { client->wirelessNodeId = malloc((sizeof(uint8_t) * wirelessNodeIdLen)) ; memcpy( client->wirelessNodeId , wirelessNodeId , sizeof(uint8_t) * wirelessNodeIdLen) ; client->wirelessNodeIdLen = wirelessNodeIdLen ; } } // // client == NULL else /* there is an existing disconnected client */ { /* Reconnect of a disconnected client */ free(client->addr); client->connect_state = 0; client->connected = 0; /* Do not connect until we know the connack has been sent */ // Delete Wireless Node ID if exists in existing client if ( wirelessNodeId == NULL) { if ( client->wirelessNodeId != NULL) free( client->wirelessNodeId ) ; client->wirelessNodeId = NULL ; client->wirelessNodeIdLen = 0 ; } else // Replace existing Wireless Node ID with value from current connect packet { if ( client->wirelessNodeId != NULL) free ( client->wirelessNodeId ) ; client->wirelessNodeId = malloc((sizeof(uint8_t) * wirelessNodeIdLen)) ; memcpy( client->wirelessNodeId , wirelessNodeId , sizeof(uint8_t) * wirelessNodeIdLen) ; client->wirelessNodeIdLen = wirelessNodeIdLen ; } } // client != NULL client->good = 1; /* good is set to 0 in disconnect, so we need to reset it here */ client->keepAliveInterval = connect->keepAlive; client->cleansession = connect->flags.cleanSession; client->socket = sock; client->addr = malloc(strlen(clientAddr)+1); strcpy(client->addr, clientAddr); TreeAdd(bstate->mqtts_clients, client, sizeof(Clients) + strlen(client->clientID)+1 + 3*sizeof(List)); if (client->cleansession) MQTTProtocol_removeAllSubscriptions(client->clientID); /* clear any persistent subscriptions */ if (connect->flags.will) { client->connect_state = 1; rc = MQTTSPacket_send_willTopicReq(client); } else { client->connected = 1; rc = MQTTSPacket_send_connack(client, 0); /* send response */ } } else { /* Reconnect of a connected client */ client = (Clients*)(elem->content); if (client->connected) { Log(LOG_INFO, 34, NULL, connect->clientID, clientAddr); if (client->socket != sock) Socket_close(client->socket); } client->socket = sock; client->connected = 0; /* Do not connect until we know the connack has been sent */ client->connect_state = 0; // Delete Wireless Node ID if exists in existing client if ( wirelessNodeId == NULL) { if ( client->wirelessNodeId != NULL) free( client->wirelessNodeId ) ; client->wirelessNodeId = NULL ; client->wirelessNodeIdLen = 0 ; } else // Replace existing Wireless Node ID with value from current connect packet { if ( client->wirelessNodeId != NULL) free ( client->wirelessNodeId ) ; client->wirelessNodeId = malloc((sizeof(uint8_t) * wirelessNodeIdLen)) ; memcpy( client->wirelessNodeId , wirelessNodeId , sizeof(uint8_t) * wirelessNodeIdLen) ; client->wirelessNodeIdLen = wirelessNodeIdLen ; } client->good = 1; if (client->addr != NULL) free(client->addr); client->addr = malloc(strlen(clientAddr)+1); strcpy(client->addr, clientAddr); client->cleansession = connect->flags.cleanSession; if (client->cleansession) { int i; MQTTProtocol_removeAllSubscriptions(client->clientID); /* empty pending message lists */ MQTTProtocol_emptyMessageList(client->outboundMsgs); MQTTProtocol_emptyMessageList(client->inboundMsgs); for (i = 0; i < PRIORITY_MAX; ++i) MQTTProtocol_emptyMessageList(client->queuedMsgs[i]); MQTTProtocol_clearWill(client); } /* registrations are always cleared */ MQTTSProtocol_emptyRegistrationList(client->registrations); /* have to remove and re-add client so it is in the right order for new socket */ if (client->socket != sock) { TreeRemoveNodeIndex(bstate->mqtts_clients, elem, 1); TreeRemoveKeyIndex(bstate->mqtts_clients, &client->socket, 0); client->socket = sock; TreeAdd(bstate->mqtts_clients, client, sizeof(Clients) + strlen(client->clientID)+1 + 3*sizeof(List)); } client->keepAliveInterval = connect->keepAlive; client->pendingRegistration = NULL; #if !defined(NO_BRIDGE) client->pendingSubscription = NULL; #endif if (connect->flags.will) { client->connect_state = 1; rc = MQTTSPacket_send_willTopicReq(client); } else { client->connected = 1; rc = MQTTSPacket_send_connack(client,0); /* send response */ } } if (existingClient) MQTTProtocol_processQueued(client); Log(LOG_INFO, 0, "Client connected to udp port %d from %s (%s)", list->port, client->clientID, clientAddr); MQTTSPacket_free_packet(pack); time( &(client->lastContact) ); exit: FUNC_EXIT_RC(rc); return rc; }
/** * Create the server socket in multi-listener mode. * @param list pointer to a listener structure * @return completion code */ int Socket_addServerSocket(Listener* list) { int flag = 1; int rc = SOCKET_ERROR; int ipv4 = 1; /* yes we can drop down to ipv4 */ FUNC_ENTRY; if (!list->address || strcmp(list->address, "INADDR_ANY") == 0) { struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; list->addr.sin_addr.s_addr = htonl(INADDR_ANY); list->addr6.sin6_addr = in6addr_any; } else { if (list->address[0] == '[') { int changed = ipv6_format(list->address); #if defined(WIN32) /*wchar_t buf[(INET6_ADDRSTRLEN+1)*2]; int buflen = sizeof(list->addr6); mbstowcs(buf, &list->address[1], sizeof(buf)); rc = WSAStringToAddress(buf, AF_INET6, NULL, (struct sockaddr*)&list->addr6, &buflen);*/ rc = win_inet_pton(AF_INET6, &list->address[1], &(list->addr6.sin6_addr)); #else rc = inet_pton(AF_INET6, &list->address[1], &(list->addr6.sin6_addr)); #endif ipv4 = 0; if (changed) (list->address)[changed] = ']'; } else { #if defined(WIN32) /*wchar_t buf[(INET6_ADDRSTRLEN+1)*2]; int buflen = sizeof(list->addr); mbstowcs(buf, list->address, sizeof(buf)); rc = WSAStringToAddress(buf, AF_INET, NULL, (struct sockaddr*)&list->addr, &buflen);*/ rc = win_inet_pton(AF_INET, list->address, &(list->addr.sin_addr.s_addr)); #else rc = inet_pton(AF_INET, list->address, &(list->addr.sin_addr.s_addr)); #endif list->ipv6 = 0; } #if defined(WIN32) if (rc != 0) #else if (rc != 1) #endif { Log(LOG_WARNING, 67, NULL, list->address); rc = -1; goto exit; } } list->socket = -1; if (list->protocol == PROTOCOL_MQTT) { if (list->ipv6) list->socket = socket(AF_INET6, SOCK_STREAM, 0); if (list->socket < 0 && ipv4) { list->socket = socket(AF_INET, SOCK_STREAM, 0); list->ipv6 = 0; } } #if defined(MQTTS) else if (list->protocol == PROTOCOL_MQTTS) { if (list->ipv6) list->socket = socket(AF_INET6, SOCK_DGRAM, 0); if (list->socket < 0 && ipv4) { list->socket = socket(AF_INET, SOCK_DGRAM, 0); list->ipv6 = 0; } } #endif Log(TRACE_MAX, 6, NULL, FD_SETSIZE); if (list->socket < 0) { Socket_error("socket", list->socket); Log(LOG_WARNING, 77, NULL); rc = list->socket; goto exit; } #if !defined(WIN32) if (setsockopt(list->socket, SOL_SOCKET, SO_REUSEADDR, (const char*)&flag, sizeof(int)) != 0) Log(LOG_WARNING, 109, NULL, list->port); #endif if (list->ipv6) { list->addr6.sin6_family = AF_INET6; list->addr6.sin6_port = htons(list->port); rc = bind(list->socket, (struct sockaddr *)&(list->addr6), sizeof(list->addr6)); } else { list->addr.sin_family = AF_INET; list->addr.sin_port = htons(list->port); memset(list->addr.sin_zero, 0, sizeof(list->addr.sin_zero)); rc = bind(list->socket, (struct sockaddr *)&(list->addr), sizeof(list->addr)); } if (rc == SOCKET_ERROR) { Socket_error("bind", list->socket); Log(LOG_WARNING, 78, NULL, list->port); goto exit; } /* Only listen if this is mqtt/tcp */ if (list->protocol == PROTOCOL_MQTT && listen(list->socket, SOMAXCONN) == SOCKET_ERROR) /* second parm is max no of connections */ { Socket_error("listen", list->socket); Log(LOG_WARNING, 79, NULL, list->port); goto exit; } if (Socket_setnonblocking(list->socket) == SOCKET_ERROR) { Socket_error("setnonblocking", list->socket); goto exit; } #if defined(MQTTS) /* If mqtts/udp, add to the list of clientsds to test for reading */ if (list->protocol == PROTOCOL_MQTTS) { ListElement* current = NULL; int loopback = list->loopback; #if !defined(USE_POLL) int* pnewSd = (int*)malloc(sizeof(list->socket)); *pnewSd = list->socket; ListAppend(s.clientsds, pnewSd, sizeof(list->socket)); #endif Log(LOG_INFO, 300, NULL, list->port); if (setsockopt(list->socket, IPPROTO_IP, IP_MULTICAST_LOOP, (const char*)&loopback, sizeof(loopback)) == SOCKET_ERROR) Socket_error("set listener IP_MULTICAST_LOOP", list->socket); /* join any multicast groups */ while (ListNextElement(list->multicast_groups, ¤t)) Socket_joinMulticastGroup(list->socket, list->ipv6, (char*)(current->content)); } else #endif Log(LOG_INFO, 14, NULL, list->port); #if defined(USE_POLL) /* add new socket to the epoll descriptor with epoll_ctl */ struct socket_info* si = malloc(sizeof(struct socket_info)); si->listener = list; si->fd = list->socket; si->connect_pending = 0; si->event.events = EPOLLIN; si->event.data.ptr = si; TreeAdd(s.fds_tree, si, sizeof(struct socket_info)); if (epoll_ctl(s.epoll_fds, EPOLL_CTL_ADD, list->socket, &si->event) != 0) Socket_error("epoll_ctl add", list->socket); #else FD_SET((u_int)list->socket, &(s.rset)); /* Add the current socket descriptor */ s.maxfdp1 = max(s.maxfdp1+1, list->socket+1); memcpy((void*)&(s.rset_saved), (void*)&(s.rset), sizeof(s.rset_saved)); #endif rc = 0; exit: FUNC_EXIT_RC(rc); return rc; }
bool FolderAdd(MessageTreeItem *pItem) { return TreeAdd(g_pFolderTree, g_pFolderList, pItem, &g_lFolderMaxID); }
/* * Process Response files on the command line * Returns true if it allocated a new argv array that must be freed later */ void ConsoleArgs::ProcessResponseArgs() { HRESULT hr; b_tree *response_files = NULL; WCHAR szFilename[MAX_PATH]; WCAllocBuffer textBuffer; for (WStrList * listCurArg = m_listArgs; listCurArg != NULL && !m_output->HadFatalError(); listCurArg = listCurArg->next) { WCHAR * szArg = listCurArg->arg; // Skip everything except Response files if (szArg == NULL || szArg[0] != '@') continue; if (wcslen(szArg) == 1) { m_output->ShowErrorIdString( ERR_NoFileSpec, ERROR_ERROR, szArg); goto CONTINUE; } // Check for duplicates if (!GetFullFileName( RemoveQuotes(WCBuffer::CreateFrom(&szArg[1])), szFilename, false)) continue; hr = TreeAdd(&response_files, szFilename); if (hr == E_OUTOFMEMORY) { m_output->ShowErrorId(FTL_NoMemory, ERROR_FATAL); goto CONTINUE; } else if (hr == S_FALSE) { m_output->ShowErrorIdString(ERR_DuplicateResponseFile, ERROR_ERROR, szFilename); goto CONTINUE; } FileType fileType; textBuffer.Clear(); if (FAILED(hr = ReadTextFile(szFilename, NULL, textBuffer, &fileType)) || hr == S_FALSE) { if (hr == E_OUTOFMEMORY) { m_output->ShowErrorId(FTL_NoMemory, ERROR_FATAL); } else if (FAILED(hr)) { if (fileType == ftBinary) m_output->ShowErrorIdString(ERR_BinaryFile, ERROR_ERROR, szFilename); else m_output->ShowErrorIdString(ERR_OpenResponseFile, ERROR_ERROR, szFilename, m_output->ErrorHR(hr)); } goto CONTINUE; } TextToArgs( textBuffer, &listCurArg->next); CONTINUE: // remove the response file argument, and continue to the next. listCurArg->arg = NULL; VSFree(szArg); } CleanupTree(response_files); }
/** * Process an incoming connect packet for a socket * @param pack pointer to the connect packet * @param sock the socket on which the packet was received * @return completion code */ int MQTTProtocol_handleConnects(void* pack, int sock, Clients* client) { Connect* connect = (Connect*)pack; Node* elem = NULL; int terminate = 0; int rc = TCPSOCKET_COMPLETE; #if !defined(SINGLE_LISTENER) Listener* listener = Socket_getParentListener(sock); #endif FUNC_ENTRY; Log(LOG_PROTOCOL, 26, NULL, sock, connect->clientID);/* connect->Protocol, connect->flags.bits.cleanstart, connect->keepAliveTimer, connect->version, connect->username, connect->password);*/ Socket_removeNew(sock); if (bstate->state != BROKER_RUNNING) terminate = 1; /* don't accept new connection requests when we are shutting down */ /* Now check the version. If we don't recognize it we will not have parsed the packet, * so nothing else in the packet structure will have been filled in. */ else if (!MQTTPacket_checkVersion(pack)) { Log(LOG_WARNING, 32, NULL, connect->Protocol, connect->version); rc = MQTTPacket_send_connack(CONNACK_UNACCEPTABLE_PROTOCOL_VERSION, sock, Socket_getpeer(sock)); /* send response */ terminate = 1; } else if (connect->clientID[0] == '\0' || (connect->version == 3 && strlen(connect->clientID) > 23)) { rc = MQTTPacket_send_connack(CONNACK_IDENTIFIER_REJECTED, sock, Socket_getpeer(sock)); /* send response */ terminate = 1; } else if (bstate->password_file != NULL) { if (connect->flags.bits.username && connect->flags.bits.password && (Users_authenticate(connect->username, connect->password) == false)) { Log(LOG_WARNING, 31, NULL, connect->clientID); rc = MQTTPacket_send_connack(CONNACK_BAD_USERNAME_OR_PASSWORD, sock, connect->clientID); /* send bad user/pass response */ terminate = 1; } else if ((!connect->flags.bits.username || !connect->flags.bits.password) && !bstate->allow_anonymous) { Log(LOG_WARNING, 31, NULL, connect->clientID); rc = MQTTPacket_send_connack(CONNACK_BROKER_UNAVAILABLE, sock, connect->clientID); /* send broker unavailable response */ terminate = 1; } } if (terminate) ; else if (bstate->clientid_prefixes->count > 0 && !ListFindItem(bstate->clientid_prefixes, connect->clientID, clientPrefixCompare)) { Log(LOG_WARNING, 31, NULL, connect->clientID); terminate = 1; } else { #if !defined(SINGLE_LISTENER) if (listener->max_connections > -1 && listener->connections->count > listener->max_connections) { Log(LOG_WARNING, 141, NULL, connect->clientID, listener->max_connections, listener->port); #else if (bstate->max_connections > -1 && MQTTProtocol_getNoConnectedClients() >= bstate->max_connections) { Log(LOG_WARNING, 141, NULL, connect->clientID, bstate->max_connections, bstate->port); #endif rc = MQTTPacket_send_connack(CONNACK_BROKER_UNAVAILABLE, sock, connect->clientID); /* send response */ terminate = 1; } } if (terminate) { MQTTPacket_freeConnect(connect); Socket_close(sock); rc = TCPSOCKET_COMPLETE; goto exit; } if (bstate->connection_messages) Log(LOG_INFO, #if !defined(SINGLE_LISTENER) 33, NULL, listener->port, connect->clientID, Socket_getpeer(sock)); #else 33, NULL, bstate->port, connect->clientID, Socket_getpeer(sock)); #endif elem = TreeFindIndex(bstate->clients, connect->clientID, 1); if (elem == NULL) { client = TreeRemoveKey(bstate->disconnected_clients, connect->clientID); if (client == NULL) { int i; char* tmpAddr = NULL; client = malloc(sizeof(Clients)); memset(client, '\0', sizeof(Clients)); tmpAddr = Socket_getpeer(sock); client->addr = malloc(strlen(tmpAddr)+1); strcpy(client->addr, tmpAddr); #if defined(MQTTS) client->protocol = PROTOCOL_MQTT; #endif client->clientID = connect->clientID; client->outboundMsgs = ListInitialize(); client->inboundMsgs = ListInitialize(); for (i = 0; i < PRIORITY_MAX; ++i) client->queuedMsgs[i] = ListInitialize(); connect->clientID = NULL; /* don't want to free this space as it is being used in the client structure */ } client->socket = sock; TreeAdd(bstate->clients, client, sizeof(Clients) + strlen(client->clientID)+1 + 3*sizeof(List)); } else { client = (Clients*)(elem->content); if (client->connected) { Log(LOG_INFO, 34, NULL, connect->clientID, Socket_getpeer(sock)); if (client->socket != sock) Socket_close(client->socket); } if (connect->flags.bits.cleanstart) { int i; /* empty pending message lists */ MQTTProtocol_emptyMessageList(client->outboundMsgs); MQTTProtocol_emptyMessageList(client->inboundMsgs); for (i = 0; i < PRIORITY_MAX; ++i) MQTTProtocol_emptyMessageList(client->queuedMsgs[i]); client->msgID = client->outbound = client->ping_outstanding = 0; } /* have to remove and re-add client so it is in the right order for new socket */ if (client->socket != sock) { TreeRemoveNodeIndex(bstate->clients, elem, 1); TreeRemoveKeyIndex(bstate->clients, &client->socket, 0); client->socket = sock; TreeAdd(bstate->clients, client, sizeof(Clients) + strlen(client->clientID)+1 + 3*sizeof(List)); } } client->good = client->connected = 1; client->cleansession = connect->flags.bits.cleanstart; client->keepAliveInterval = connect->keepAliveTimer; client->noLocal = (connect->version == PRIVATE_PROTOCOL_VERSION) ? 1 : 0; if (client->cleansession) MQTTProtocol_removeAllSubscriptions(client->clientID); /* clear any persistent subscriptions */ #if !defined(SINGLE_LISTENER) if (listener && listener->mount_point && connect->flags.bits.will) { char* temp = malloc(strlen(connect->willTopic) + strlen(listener->mount_point) + 1); strcpy(temp, listener->mount_point); strcat(temp, connect->willTopic); free(connect->willTopic); connect->willTopic = temp; } #endif #if defined(MQTTS) if (connect->flags.bits.will) { MQTTProtocol_setWillTopic(client, connect->willTopic, connect->flags.bits.willRetain, connect->flags.bits.willQoS); MQTTProtocol_setWillMsg(client, connect->willMsg); connect->willTopic = NULL; connect->willMsg = NULL; } #else MQTTProtocol_setWill(connect, client); #endif if (connect->flags.bits.username) { client->user = Users_get_user(connect->username); } rc = MQTTPacket_send_connack(CONNACK_CONNECTION_ACCEPTED, sock, client->clientID); /* send response */ if (client->cleansession == 0) { ListElement* outcurrent = NULL; time_t now = 0; /* ensure that inflight messages are retried now by setting the last touched time * to very old (0) before calling the retry function */ time(&(now)); while (ListNextElement(client->outboundMsgs, &outcurrent)) { Messages* m = (Messages*)(outcurrent->content); m->lastTouch = 0; } MQTTProtocol_retries(now, client); MQTTProtocol_processQueued(client); } time(&(client->lastContact)); MQTTPacket_freeConnect(connect); exit: FUNC_EXIT_RC(rc); return rc; } /** * Process an incoming ping request 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_handlePingreqs(void* pack, int sock, Clients* client) { int rc = TCPSOCKET_COMPLETE; FUNC_ENTRY; Log(LOG_PROTOCOL, 3, NULL, sock, client->clientID); rc = MQTTPacket_send_pingresp(sock, client->clientID); 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; }
Clients* MQTTSProtocol_create_multicast(char* ip_address, char* clientID, int loopback) { /* outgoing connection */ int i, port, rc; char* addr; Clients* newc = NULL; char* intface = NULL; int ipv6 = 0; FUNC_ENTRY; newc = malloc(sizeof(Clients)); memset(newc, '\0', sizeof(Clients)); newc->clientID = clientID; newc->outbound = 1; newc->good = 1; newc->connected = 1; newc->outboundMsgs = ListInitialize(); newc->inboundMsgs = ListInitialize(); for (i = 0; i < PRIORITY_MAX; ++i) newc->queuedMsgs[i] = ListInitialize(); newc->registrations = ListInitialize(); newc->protocol = PROTOCOL_MQTTS_MULTICAST; /* if there is a space in the ip_address string, it means we have address plus interface specified */ if ((intface = strchr(ip_address, ' ')) != NULL) { *intface = '\0'; ++intface; } addr = MQTTProtocol_addressPort(ip_address, &port); newc->addr = malloc(strlen(ip_address) + 1); strcpy(newc->addr, ip_address); ipv6 = (newc->addr[0] == '['); rc = Socket_new_udp(&(newc->socket), ipv6); if (setsockopt(newc->socket, IPPROTO_IP, IP_MULTICAST_LOOP, (const char*)&loopback, sizeof(loopback)) == SOCKET_ERROR) Socket_error("set bridge IP_MULTICAST_LOOP", newc->socket); if (intface) { if (ipv6) { int index = 0; if ((index = if_nametoindex(intface)) == 0) Socket_error("get interface index", newc->socket); else if (setsockopt(newc->socket, IPPROTO_IPV6, IPV6_MULTICAST_IF, (const char*)&index, sizeof(index)) == SOCKET_ERROR) Socket_error("set bridge IP_MULTICAST_IF", newc->socket); } else { struct in_addr interface_addr; #if defined(WIN32) if ((rc = win_inet_pton(AF_INET, intface, &interface_addr)) == SOCKET_ERROR) Socket_error("WSAStringToAddress interface", newc->socket); else { #else /* get address of the interface */ struct ifreq ifreq; strncpy(ifreq.ifr_name, intface, IFNAMSIZ); if (ioctl(newc->socket, SIOCGIFADDR, &ifreq) == SOCKET_ERROR) Socket_error("get interface address", newc->socket); else { memcpy(&interface_addr, &((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr, sizeof(struct in_addr)); #endif if (setsockopt(newc->socket, IPPROTO_IP, IP_MULTICAST_IF, &interface_addr, sizeof(interface_addr)) == SOCKET_ERROR) Socket_error("set bridge IP_MULTICAST_IF", newc->socket); } } } TreeAdd(bstate->disconnected_mqtts_clients, newc, sizeof(Clients) + strlen(newc->clientID)+1 + 3*sizeof(List)); FUNC_EXIT; return newc; } Clients* MQTTSProtocol_connect(char* ip_address, char* clientID, int cleansession, int try_private, int keepalive, willMessages* willMessage) { /* outgoing connection */ int rc, port; char* addr; Clients* newc = NULL; FUNC_ENTRY; newc = TreeRemoveKeyIndex(bstate->disconnected_clients, clientID, 1); /* must be a dummy client */ if (newc == NULL) newc = TreeRemoveKeyIndex(bstate->clients, clientID, 1); if (newc) { free(clientID); newc->connected = newc->ping_outstanding = newc->connect_state = newc->msgID = newc->discardedMsgs = 0; } else { int i; newc = malloc(sizeof(Clients)); memset(newc, '\0', sizeof(Clients)); newc->outboundMsgs = ListInitialize(); newc->inboundMsgs = ListInitialize(); for (i = 0; i < PRIORITY_MAX; ++i) newc->queuedMsgs[i] = ListInitialize(); newc->clientID = clientID; } newc->cleansession = cleansession; newc->outbound = newc->good = 1; newc->keepAliveInterval = keepalive; newc->registrations = ListInitialize(); newc->will = willMessage; newc->noLocal = try_private; /* try private connection first */ time(&(newc->lastContact)); newc->pendingRegistration = NULL; newc->protocol = PROTOCOL_MQTTS; addr = MQTTProtocol_addressPort(ip_address, &port); newc->addr = malloc(strlen(ip_address)); strcpy(newc->addr, ip_address); rc = Socket_new_type(addr, port, &(newc->socket), SOCK_DGRAM); if (rc == EINPROGRESS || rc == EWOULDBLOCK) newc->connect_state = 1; /* UDP connect called - improbable, but possible on obscure platforms */ else if (rc == 0) { newc->connect_state = 2; rc = MQTTSPacket_send_connect(newc); } TreeAdd(bstate->clients, newc, sizeof(Clients) + strlen(newc->clientID)+1 + 3*sizeof(List)); FUNC_EXIT; return newc; }