bool UDPThread::Listen(const int &iAddressFamily) { sock = socket(iAddressFamily, SOCK_DGRAM, IPPROTO_UDP); #ifdef _WIN32 if(sock == INVALID_SOCKET) { #else if(sock == -1) { #endif AppendLog("[ERR] UDP Socket creation error."); return false; } #ifndef _WIN32 int on = 1; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); #endif sockaddr_storage sas; memset(&sas, 0, sizeof(sockaddr_storage)); socklen_t sas_len; if(iAddressFamily == AF_INET6) { ((struct sockaddr_in6 *)&sas)->sin6_family = AF_INET6; ((struct sockaddr_in6 *)&sas)->sin6_port = htons((unsigned short)atoi(clsSettingManager::mPtr->sTexts[SETTXT_UDP_PORT])); sas_len = sizeof(struct sockaddr_in6); if(clsSettingManager::mPtr->bBools[SETBOOL_BIND_ONLY_SINGLE_IP] == true && clsServerManager::sHubIP6[0] != '\0') { #if defined(_WIN32) && !defined(_WIN64) && !defined(_WIN_IOT) win_inet_pton(clsServerManager::sHubIP6, &((struct sockaddr_in6 *)&sas)->sin6_addr); #else inet_pton(AF_INET6, clsServerManager::sHubIP6, &((struct sockaddr_in6 *)&sas)->sin6_addr); #endif } else { ((struct sockaddr_in6 *)&sas)->sin6_addr = in6addr_any; if(iAddressFamily == AF_INET6 && clsServerManager::bIPv6DualStack == true) { #ifdef _WIN32 DWORD dwIPv6 = 0; setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&dwIPv6, sizeof(dwIPv6)); #else int iIPv6 = 0; setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &iIPv6, sizeof(iIPv6)); #endif } } } else { ((struct sockaddr_in *)&sas)->sin_family = AF_INET; ((struct sockaddr_in *)&sas)->sin_port = htons((unsigned short)atoi(clsSettingManager::mPtr->sTexts[SETTXT_UDP_PORT])); sas_len = sizeof(struct sockaddr_in); if(clsSettingManager::mPtr->bBools[SETBOOL_BIND_ONLY_SINGLE_IP] == true && clsServerManager::sHubIP[0] != '\0') { ((struct sockaddr_in *)&sas)->sin_addr.s_addr = inet_addr(clsServerManager::sHubIP); } else { ((struct sockaddr_in *)&sas)->sin_addr.s_addr = INADDR_ANY; } } #ifdef _WIN32 if(bind(sock, (struct sockaddr *)&sas, sas_len) == SOCKET_ERROR) { AppendLog("[ERR] UDP Socket bind error: "+string(WSAGetLastError())); #else if(bind(sock, (struct sockaddr *)&sas, sas_len) == -1) { AppendLog("[ERR] UDP Socket bind error: "+string(ErrnoStr(errno))+" ("+string(errno)+")"); #endif return false; } return true; } //--------------------------------------------------------------------------- UDPThread::~UDPThread() { #ifdef _WIN32 if(sock != INVALID_SOCKET) { closesocket(sock); sock = INVALID_SOCKET; } if(hThreadHandle != INVALID_HANDLE_VALUE) { CloseHandle(hThreadHandle); #else if(threadId != 0) { Close(); WaitFor(); #endif } } //--------------------------------------------------------------------------- #ifdef _WIN32 unsigned __stdcall ExecuteUDP(void* UDPThrd) { #else static void* ExecuteUDP(void* UDPThrd) { #endif ((UDPThread *)UDPThrd)->Run(); return 0; } //--------------------------------------------------------------------------- void UDPThread::Resume() { #ifdef _WIN32 hThreadHandle = (HANDLE)_beginthreadex(NULL, 0, ExecuteUDP, this, 0, &threadId); if(hThreadHandle == 0) { #else int iRet = pthread_create(&threadId, NULL, ExecuteUDP, this); if(iRet != 0) { #endif AppendDebugLog("%s - [ERR] Failed to create new UDPThread\n"); } } //--------------------------------------------------------------------------- void UDPThread::Run() { sockaddr_storage sas; socklen_t sas_len = sizeof(sockaddr_storage); int len = 0; while(bTerminated == false) { len = recvfrom(sock, rcvbuf, 4095, 0, (struct sockaddr *)&sas, &sas_len); if(len < 5 || strncmp(rcvbuf, "$SR ", 4) != 0) { continue; } rcvbuf[len] = '\0'; // added ip check, we don't want fake $SR causing kick of innocent user... clsEventQueue::mPtr->AddThread(clsEventQueue::EVENT_UDP_SR, rcvbuf, &sas); } } //--------------------------------------------------------------------------- void UDPThread::Close() { bTerminated = true; #ifdef _WIN32 closesocket(sock); #else shutdown(sock, SHUT_RDWR); close(sock); #endif } //--------------------------------------------------------------------------- void UDPThread::WaitFor() { #ifdef _WIN32 WaitForSingleObject(hThreadHandle, INFINITE); #else if(threadId != 0) { pthread_join(threadId, NULL); threadId = 0; } #endif }
void clsIpP2Country::LoadIPv6() { if(clsServerManager::bUseIPv6 == false) { return; } #ifdef _WIN32 FILE * ip2country = fopen((clsServerManager::sPath + "\\cfg\\IpToCountry.6R.csv").c_str(), "r"); #else FILE * ip2country = fopen((clsServerManager::sPath + "/cfg/IpToCountry.6R.csv").c_str(), "r"); #endif if(ip2country == NULL) { return; } if(ui32IPv6Size == 0) { ui32IPv6Size = 16384; if(ui128IPv6RangeFrom == NULL) { #ifdef _WIN32 ui128IPv6RangeFrom = (uint8_t *)HeapAlloc(clsServerManager::hLibHeap, HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY, ui32IPv6Size * (sizeof(uint8_t)*16)); #else ui128IPv6RangeFrom = (uint8_t *)calloc(ui32IPv6Size, sizeof(uint8_t) * 16); #endif if(ui128IPv6RangeFrom == NULL) { AppendDebugLog("%s - [MEM] Cannot create clsIpP2Country::ui128IPv6RangeFrom\n", 0); fclose(ip2country); ui32IPv6Size = 0; return; } } if(ui128IPv6RangeTo == NULL) { #ifdef _WIN32 ui128IPv6RangeTo = (uint8_t *)HeapAlloc(clsServerManager::hLibHeap, HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY, ui32IPv6Size * (sizeof(uint8_t)*16)); #else ui128IPv6RangeTo = (uint8_t *)calloc(ui32IPv6Size, sizeof(uint8_t) * 16); #endif if(ui128IPv6RangeTo == NULL) { AppendDebugLog("%s - [MEM] Cannot create clsIpP2Country::ui128IPv6RangeTo\n", 0); fclose(ip2country); ui32IPv6Size = 0; return; } } if(ui8IPv6RangeCI == NULL) { #ifdef _WIN32 ui8IPv6RangeCI = (uint8_t *)HeapAlloc(clsServerManager::hLibHeap, HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY, ui32IPv6Size * sizeof(uint8_t)); #else ui8IPv6RangeCI = (uint8_t *)calloc(ui32IPv6Size, sizeof(uint8_t)); #endif if(ui8IPv6RangeCI == NULL) { AppendDebugLog("%s - [MEM] Cannot create clsIpP2Country::ui8IPv6RangeCI\n", 0); fclose(ip2country); ui32IPv6Size = 0; return; } } } char sLine[1024]; while(fgets(sLine, 1024, ip2country) != NULL) { if(sLine[0] == '#' || sLine[0] < 32) { continue; } if(ui32IPv6Count == ui32IPv6Size) { ui32IPv6Size += 512; void * oldbuf = ui128IPv6RangeFrom; #ifdef _WIN32 ui128IPv6RangeFrom = (uint8_t *)HeapReAlloc(clsServerManager::hLibHeap, HEAP_NO_SERIALIZE, (void *)oldbuf, ui32IPv6Size * (sizeof(uint8_t)*16)); #else ui128IPv6RangeFrom = (uint8_t *)realloc(oldbuf, ui32IPv6Size * (sizeof(uint8_t)*16)); #endif if(ui128IPv6RangeFrom == NULL) { AppendDebugLog("%s - [MEM] Cannot reallocate %" PRIu64 " bytes in clsIpP2Country::clsIpP2Country for ui128IPv6RangeFrom\n", (uint64_t)ui32IPv6Size); ui128IPv6RangeFrom = (uint8_t *)oldbuf; fclose(ip2country); return; } oldbuf = ui128IPv6RangeTo; #ifdef _WIN32 ui128IPv6RangeTo = (uint8_t *)HeapReAlloc(clsServerManager::hLibHeap, HEAP_NO_SERIALIZE, (void *)oldbuf, ui32IPv6Size * (sizeof(uint8_t)*16)); #else ui128IPv6RangeTo = (uint8_t *)realloc(oldbuf, ui32IPv6Size * (sizeof(uint8_t)*16)); #endif if(ui128IPv6RangeTo == NULL) { AppendDebugLog("%s - [MEM] Cannot reallocate %" PRIu64 " bytes in clsIpP2Country::clsIpP2Country for ui128IPv6RangeTo\n", (uint64_t)ui32IPv6Size); ui128IPv6RangeTo = (uint8_t *)oldbuf; fclose(ip2country); return; } oldbuf = ui8IPv6RangeCI; #ifdef _WIN32 ui8IPv6RangeCI = (uint8_t *)HeapReAlloc(clsServerManager::hLibHeap, HEAP_NO_SERIALIZE, (void *)oldbuf, ui32IPv6Size * sizeof(uint8_t)); #else ui8IPv6RangeCI = (uint8_t *)realloc(oldbuf, ui32IPv6Size * sizeof(uint8_t)); #endif if(ui8IPv6RangeCI == NULL) { AppendDebugLog("%s - [MEM] Cannot reallocate %" PRIu64 " bytes in clsIpP2Country::clsIpP2Country for ui8IPv6RangeCI\n", (uint64_t)ui32IPv6Size); ui8IPv6RangeCI = (uint8_t *)oldbuf; fclose(ip2country); return; } } char * sStart = sLine; uint8_t ui8d = 0; size_t szLineLen = strlen(sLine); for(size_t szi = 0; szi < szLineLen; szi++) { if(ui8d == 0 && sLine[szi] == '-') { sLine[szi] = '\0'; #ifdef _WIN32 win_inet_pton(sStart, ui128IPv6RangeFrom + (ui32IPv6Count*16)); #else inet_pton(AF_INET6, sStart, ui128IPv6RangeFrom + (ui32IPv6Count*16)); #endif } else if(sLine[szi] == ',') { sLine[szi] = '\0'; if(ui8d == 1) { #ifdef _WIN32 win_inet_pton(sStart, ui128IPv6RangeTo + (ui32IPv6Count*16)); #else inet_pton(AF_INET6, sStart, ui128IPv6RangeTo + (ui32IPv6Count*16)); #endif } else { for(uint8_t ui8i = 0; ui8i < 252; ui8i++) { if(*((uint16_t *)CountryCodes[ui8i]) == *((uint16_t *)sStart)) { ui8IPv6RangeCI[ui32IPv6Count] = ui8i; ui32IPv6Count++; break; } } break; } } else { continue; } ui8d++; sStart = sLine+szi+1; } } fclose(ip2country); if(ui32IPv6Count < ui32IPv6Size) { ui32IPv6Size = ui32IPv6Count; void * oldbuf = ui128IPv6RangeFrom; #ifdef _WIN32 ui128IPv6RangeFrom = (uint8_t *)HeapReAlloc(clsServerManager::hLibHeap, HEAP_NO_SERIALIZE, (void *)oldbuf, ui32IPv6Size * (sizeof(uint8_t)*16)); #else ui128IPv6RangeFrom = (uint8_t *)realloc(oldbuf, ui32IPv6Size * (sizeof(uint8_t)*16)); #endif if(ui128IPv6RangeFrom == NULL) { AppendDebugLog("%s - [MEM] Cannot reallocate %" PRIu64 " bytes in clsIpP2Country::clsIpP2Country for ui128IPv6RangeFrom\n", (uint64_t)ui32IPv6Size); ui128IPv6RangeFrom = (uint8_t *)oldbuf; } oldbuf = ui128IPv6RangeTo; #ifdef _WIN32 ui128IPv6RangeTo = (uint8_t *)HeapReAlloc(clsServerManager::hLibHeap, HEAP_NO_SERIALIZE, (void *)oldbuf, ui32IPv6Size * (sizeof(uint8_t)*16)); #else ui128IPv6RangeTo = (uint8_t *)realloc(oldbuf, ui32IPv6Size * (sizeof(uint8_t)*16)); #endif if(ui128IPv6RangeTo == NULL) { AppendDebugLog("%s - [MEM] Cannot reallocate %" PRIu64 " bytes in clsIpP2Country::clsIpP2Country for ui128IPv6RangeTo\n", (uint64_t)ui32IPv6Size); ui128IPv6RangeTo = (uint8_t *)oldbuf; } oldbuf = ui8IPv6RangeCI; #ifdef _WIN32 ui8IPv6RangeCI = (uint8_t *)HeapReAlloc(clsServerManager::hLibHeap, HEAP_NO_SERIALIZE, (void *)oldbuf, ui32IPv6Size * sizeof(uint8_t)); #else ui8IPv6RangeCI = (uint8_t *)realloc(oldbuf, ui32IPv6Size * sizeof(uint8_t)); #endif if(ui8IPv6RangeCI == NULL) { AppendDebugLog("%s - [MEM] Cannot reallocate %" PRIu64 " bytes in clsIpP2Country::clsIpP2Country for ui8IPv6RangeCI\n", (uint64_t)ui32IPv6Size); ui8IPv6RangeCI = (uint8_t *)oldbuf; } } }
int Socket_joinMulticastGroup(int sock, int ipv6, char* mcast) { int rc = 0; char* mcast_addr = mcast; char* mcast_interface = NULL; /* if there is a space in the mcast string, it means we have address plus interface specified */ if ((mcast_interface = strchr(mcast, ' ')) != NULL) { *mcast_interface = '\0'; ++mcast_interface; } else mcast_interface = "INADDR_ANY"; if (ipv6) { struct ipv6_mreq mreq6; #if defined(WIN32) if ((rc = win_inet_pton(AF_INET6, mcast_addr, &mreq6.ipv6mr_multiaddr.s6_addr)) == SOCKET_ERROR) Socket_error("WSAStringToAddress", sock); #else if ((rc = inet_pton(AF_INET6, mcast_addr, &mreq6.ipv6mr_multiaddr.s6_addr)) != 1) { if (rc == 0) Log(LOG_WARNING, 67, NULL, mcast_addr); else if (rc == SOCKET_ERROR) Socket_error("inet_pton", sock); } #endif if (strcmp(mcast_interface, "INADDR_ANY") == 0) mreq6.ipv6mr_interface = 0; else { #if defined(WIN32) /* on Windows, the if_nametoindex function requires Vista, i.e. will not work on XP */ /* Alternative functions are not short running. So for now, we can take an interface number */ mreq6.ipv6mr_interface = atoi(mcast_interface); #else mreq6.ipv6mr_interface = if_nametoindex(mcast_interface); #endif if (mreq6.ipv6mr_interface == 0) Log(LOG_WARNING, 302, NULL, mcast_interface); } rc = setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (const char*)&mreq6, sizeof(mreq6)); } else { struct ip_mreq mreq; #if defined(WIN32) if ((rc = win_inet_pton(AF_INET, mcast_addr, &mreq.imr_multiaddr.s_addr)) == SOCKET_ERROR) Socket_error("WSAStringToAddress", sock); #else if ((rc = inet_pton(AF_INET, mcast_addr, &mreq.imr_multiaddr.s_addr)) != 1) { if (rc == 0) Log(LOG_WARNING, 67, NULL, mcast_addr); else if (rc == -1) Socket_error("inet_pton", sock); } #endif if (strcmp(mcast_interface, "INADDR_ANY") == 0) mreq.imr_interface.s_addr = htonl(INADDR_ANY); else { /* find an address corresponding to the named interface */ #if defined(WIN32) /* on Windows, the GetAdaptersAddresses is suggested as a method for getting an address for an adapter. However that function is not short running. So for now, we can just take an address */ if ((rc = win_inet_pton(AF_INET, mcast_interface, &mreq.imr_interface.s_addr)) == SOCKET_ERROR) Socket_error("WSAStringToAddress interface", sock); //mreq.imr_interface.s_addr = inet_addr(mcast_interface); /* can use inet_addr as this code is IPv4 specific */ #else struct ifreq ifreq; strncpy(ifreq.ifr_name, mcast_interface, IFNAMSIZ); if (ioctl(sock, SIOCGIFADDR, &ifreq) >= 0) memcpy(&mreq.imr_interface, &((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr, sizeof(struct in_addr)); else Socket_error("ioctl SIOCGIFADDR", sock); #endif } rc = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*)&mreq, sizeof(mreq)); } Log(LOG_INFO, 303, NULL, mcast_addr, mcast_interface); if (rc != 0) Socket_error("add to multicast group", sock); 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; }
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; }