Ejemplo n.º 1
0
// DDNS client thread
void DCThread(THREAD *thread, void *param)
{
	DDNS_CLIENT *c;
	INTERRUPT_MANAGER *interrput;
	UINT last_ip_hash = 0;
	void *route_change_poller = NULL;
	bool last_time_ip_changed = false;
	UINT last_azure_ddns_trigger_int = 0;
	UINT last_vgs_ddns_trigger_int = 0;
	UINT n;
	INTERNET_SETTING last_t;
	// Validate arguments
	if (thread == NULL || param == NULL)
	{
		return;
	}

	c = (DDNS_CLIENT *)param;

	interrput = NewInterruptManager();

	route_change_poller = NewRouteChange();
	IsRouteChanged(route_change_poller);

	Zero(&last_t, sizeof(last_t));

	n = 0;

	while (c->Halt == false)
	{
		UINT ip_hash = GetHostIPAddressHash32();
		UINT interval;
		UINT64 now = Tick64();
		bool ip_changed = false;
		bool azure_client_triggered = false;
		bool internet_setting_changed = false;
		bool vgs_server_triggered = false;


		if (c->Cedar->Server != NULL && c->Cedar->Server->AzureClient != NULL)
		{
			if (c->Cedar->Server->AzureClient->DDnsTriggerInt != last_azure_ddns_trigger_int)
			{
				azure_client_triggered = true;
				last_azure_ddns_trigger_int = c->Cedar->Server->AzureClient->DDnsTriggerInt;
				last_time_ip_changed = false;
				Debug("DDNS Thread Triggered by AzureClient.\n");
			}
		}

		if (Cmp(&last_t, &c->InternetSetting, sizeof(INTERNET_SETTING)) != 0)
		{
			Copy(&last_t, &c->InternetSetting, sizeof(INTERNET_SETTING));
			internet_setting_changed = true;
			last_time_ip_changed = false;
		}

		if (ip_hash != last_ip_hash)
		{
			last_time_ip_changed = false;
			Debug("DDNS Thread Triggered by IP Hash Changed.\n");
		}

		if ((ip_hash != last_ip_hash) || (IsRouteChanged(route_change_poller)) || azure_client_triggered || internet_setting_changed || vgs_server_triggered)
		{
			if (last_time_ip_changed == false)
			{
				// Call all getting functions from the beginning if the routing
				//  table or the IP address of this host has changed
				c->NextRegisterTick_IPv4 = 0;
				c->NextRegisterTick_IPv6 = 0;
				c->NextGetMyIpTick_IPv4 = 0;
				c->NextGetMyIpTick_IPv6 = 0;

				last_ip_hash = ip_hash;

				last_time_ip_changed = true;

				ip_changed = true;

				Debug("DDNS Internet Condition Changed.\n");
			}
		}
		else
		{
			last_time_ip_changed = false;
		}

		if ((n++) >= 1)
		{
			// Self IPv4 address acquisition
			if (c->NextGetMyIpTick_IPv4 == 0 || now >= c->NextGetMyIpTick_IPv4)
			{
				UINT next_interval;
				char ip[MAX_SIZE];

				Zero(ip, sizeof(ip));
				c->Err_IPv4_GetMyIp = DCGetMyIp(c, false, ip, sizeof(ip), NULL);

				if (c->Err_IPv4_GetMyIp == ERR_NO_ERROR)
				{
					if (StrCmpi(c->LastMyIPv4, ip) != 0)
					{
						ip_changed = true;
						StrCpy(c->LastMyIPv4, sizeof(c->LastMyIPv4), ip);
					}

					next_interval = GenRandInterval(DDNS_GETMYIP_INTERVAL_OK_MIN, DDNS_GETMYIP_INTERVAL_OK_MAX);
				}
				else
				{
					if (IsEmptyStr(c->LastMyIPv4) == false)
					{
						ip_changed = true;
					}

					Zero(c->LastMyIPv4, sizeof(c->LastMyIPv4));
					next_interval = GenRandInterval(DDNS_GETMYIP_INTERVAL_NG_MIN, DDNS_GETMYIP_INTERVAL_NG_MAX);
				}

				c->NextGetMyIpTick_IPv4 = Tick64() + (UINT64)next_interval;

				AddInterrupt(interrput, c->NextGetMyIpTick_IPv4);
			}

			// Self IPv6 address acquisition
			if (c->NextGetMyIpTick_IPv6 == 0 || now >= c->NextGetMyIpTick_IPv6)
			{
				UINT next_interval;
				char ip[MAX_SIZE];

				Zero(ip, sizeof(ip));
				c->Err_IPv6_GetMyIp = DCGetMyIp(c, true, ip, sizeof(ip), NULL);

				if (c->Err_IPv6_GetMyIp == ERR_NO_ERROR)
				{
					if (StrCmpi(c->LastMyIPv6, ip) != 0)
					{
						ip_changed = true;
						StrCpy(c->LastMyIPv6, sizeof(c->LastMyIPv6), ip);
					}

					next_interval = GenRandInterval(DDNS_GETMYIP_INTERVAL_OK_MIN, DDNS_GETMYIP_INTERVAL_OK_MAX);
				}
				else
				{
					if (IsEmptyStr(c->LastMyIPv6) == false)
					{
						ip_changed = true;
					}

					Zero(c->LastMyIPv6, sizeof(c->LastMyIPv6));
					next_interval = GenRandInterval(DDNS_GETMYIP_INTERVAL_NG_MIN, DDNS_GETMYIP_INTERVAL_NG_MAX);
				}

				c->NextGetMyIpTick_IPv6 = Tick64() + (UINT64)next_interval;

				AddInterrupt(interrput, c->NextGetMyIpTick_IPv6);
			}
		}

		if (ip_changed)
		{
			c->NextRegisterTick_IPv4 = 0;
			c->NextRegisterTick_IPv6 = 0;
		}

		// IPv4 host registration
		if (c->NextRegisterTick_IPv4 == 0 || now >= c->NextRegisterTick_IPv4)
		{
			UINT next_interval;

			c->Err_IPv4 = DCRegister(c, false, NULL, NULL);

			if (c->Err_IPv4 == ERR_NO_ERROR)
			{
				next_interval = GenRandInterval(DDNS_REGISTER_INTERVAL_OK_MIN, DDNS_REGISTER_INTERVAL_OK_MAX);
			}
			else
			{
				next_interval = GenRandInterval(DDNS_REGISTER_INTERVAL_NG_MIN, DDNS_REGISTER_INTERVAL_NG_MAX);
			}
			//next_interval = 0;

			c->NextRegisterTick_IPv4 = Tick64() + (UINT64)next_interval;

			if (true)
			{
				DDNS_CLIENT_STATUS st;

				DCGetStatus(c, &st);

				SiApplyAzureConfig(c->Cedar->Server, &st);
			}

			AddInterrupt(interrput, c->NextRegisterTick_IPv4);
		}

		if (c->Halt)
		{
			break;
		}

		// IPv6 host registration
		if (c->NextRegisterTick_IPv6 == 0 || now >= c->NextRegisterTick_IPv6)
		{
			UINT next_interval;

			c->Err_IPv6 = DCRegister(c, true, NULL, NULL);

			if (c->Err_IPv6 == ERR_NO_ERROR)
			{
				next_interval = GenRandInterval(DDNS_REGISTER_INTERVAL_OK_MIN, DDNS_REGISTER_INTERVAL_OK_MAX);
			}
			else
			{
				next_interval = GenRandInterval(DDNS_REGISTER_INTERVAL_NG_MIN, DDNS_REGISTER_INTERVAL_NG_MAX);
			}

			c->NextRegisterTick_IPv6 = Tick64() + (UINT64)next_interval;

			if (true)
			{
				DDNS_CLIENT_STATUS st;

				DCGetStatus(c, &st);

				SiApplyAzureConfig(c->Cedar->Server, &st);
			}

			AddInterrupt(interrput, c->NextRegisterTick_IPv6);
		}

		interval = GetNextIntervalForInterrupt(interrput);
		interval = MIN(interval, 1234);

		if (n == 1)
		{
			interval = MIN(interval, 0);
		}

		if (c->Halt)
		{
			break;
		}

		if (c->KeyChanged)
		{
			c->KeyChanged = false;
			c->NextRegisterTick_IPv4 = c->NextRegisterTick_IPv6 = 0;

			interval = 0;
		}

		if (last_time_ip_changed)
		{
			if (c->Cedar->Server != NULL && c->Cedar->Server->AzureClient != NULL)
			{
				c->Cedar->Server->AzureClient->IpStatusRevision++;
			}
		}

		Wait(c->Event, interval);
	}

	FreeRouteChange(route_change_poller);
	FreeInterruptManager(interrput);
}
Ejemplo n.º 2
0
// Handle the communication of SSTP protocol
bool ProcessSstpHttps(CEDAR *cedar, SOCK *s, SOCK_EVENT *se)
{
	UINT tmp_size = 65536;
	UCHAR *tmp_buf;
	FIFO *recv_fifo;
	FIFO *send_fifo;
	SSTP_SERVER *sstp;
	bool ret = false;
	// Validate arguments
	if (cedar == NULL || s == NULL || se == NULL)
	{
		return false;
	}

	tmp_buf = Malloc(tmp_size);
	recv_fifo = NewFifo();
	send_fifo = NewFifo();

	sstp = NewSstpServer(cedar, &s->RemoteIP, s->RemotePort, &s->LocalIP, s->LocalPort, se,
		s->RemoteHostname, s->CipherName);

	while (true)
	{
		UINT r;
		bool is_disconnected = false;
		bool state_changed = false;

		// Receive data over SSL
		while (true)
		{
			r = Recv(s, tmp_buf, tmp_size, true);
			if (r == 0)
			{
				// SSL is disconnected
				is_disconnected = true;
				break;
			}
			else if (r == SOCK_LATER)
			{
				// Data is not received any more
				break;
			}
			else
			{
				// Queue the received data
				WriteFifo(recv_fifo, tmp_buf, r);
				state_changed = true;
			}
		}

		while (recv_fifo->size >= 4)
		{
			UCHAR *first4;
			UINT read_size = 0;
			bool ok = false;
			// Read 4 bytes from the beginning of the receive queue
			first4 = ((UCHAR *)recv_fifo->p) + recv_fifo->pos;
			if (first4[0] == SSTP_VERSION_1)
			{
				USHORT len = READ_USHORT(first4 + 2) & 0xFFF;
				if (len >= 4)
				{
					ok = true;

					if (recv_fifo->size >= len)
					{
						UCHAR *data;
						BLOCK *b;

						read_size = len;
						data = Malloc(read_size);

						ReadFifo(recv_fifo, data, read_size);

						b = NewBlock(data, read_size, 0);

						InsertQueue(sstp->RecvQueue, b);
					}
				}
			}

			if (read_size == 0)
			{
				break;
			}

			if (ok == false)
			{
				// Disconnect the connection since a bad packet received
				is_disconnected = true;
				break;
			}
		}

		// Process the timer interrupt
		SstpProcessInterrupt(sstp);

		if (sstp->Disconnected)
		{
			is_disconnected = true;
		}

		// Put the transmission data that SSTP module has generated into the transmission queue
		while (true)
		{
			BLOCK *b = GetNext(sstp->SendQueue);

			if (b == NULL)
			{
				break;
			}

			// When transmit a data packet, If there are packets of more than about
			// 2.5 MB in the transmission queue of the TCP, discard without transmission
			if (b->PriorityQoS || (send_fifo->size <= MAX_BUFFERING_PACKET_SIZE))
			{
				WriteFifo(send_fifo, b->Buf, b->Size);
			}

			FreeBlock(b);
		}

		// Data is transmitted over SSL
		while (send_fifo->size != 0)
		{
			r = Send(s, ((UCHAR *)send_fifo->p) + send_fifo->pos, send_fifo->size, true);
			if (r == 0)
			{
				// SSL is disconnected
				is_disconnected = true;
				break;
			}
			else if (r == SOCK_LATER)
			{
				// Can not send any more
				break;
			}
			else
			{
				// Advance the transmission queue by the amount of the transmitted
				ReadFifo(send_fifo, NULL, r);
				state_changed = true;
			}
		}

		if (is_disconnected)
		{
			// Disconnected
			break;
		}

		// Wait for the next state change
		if (state_changed == false)
		{
			UINT select_time = SELECT_TIME;
			UINT r = GetNextIntervalForInterrupt(sstp->Interrupt);
			WaitSockEvent(se, MIN(r, select_time));
		}
	}

	if (sstp != NULL && sstp->EstablishedCount >= 1)
	{
		ret = true;
	}

	FreeSstpServer(sstp);

	ReleaseFifo(recv_fifo);
	ReleaseFifo(send_fifo);
	Free(tmp_buf);

	YieldCpu();
	Disconnect(s);

	return ret;
}