Пример #1
0
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
}
Пример #2
0
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;
    	}
    }
}
Пример #3
0
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;
}
Пример #4
0
/**
 * 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, &current))
			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;
}
Пример #5
0
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;
}