Esempio n. 1
0
// Stack main thread
void NsMainThread(THREAD *thread, void *param)
{
	NATIVE_STACK *a = (NATIVE_STACK *)param;
	// Validate arguments
	if (thread == NULL || param == NULL)
	{
		return;
	}

	while (true)
	{
		SOCKSET set;
		bool err = false;
		bool flush_tube;
		LIST *recv_packets;
		bool state_changed = false;

		InitSockSet(&set);
		AddSockSet(&set, a->Sock1);

		if (a->Halt)
		{
			break;
		}

		// Pass to the IPC by receiving from the bridge
LABEL_RESTART:
		state_changed = false;
		flush_tube = false;
		while (true)
		{
			void *data;
			UINT size;

			size = EthGetPacket(a->Eth, &data);

			if (size == INFINITE)
			{
				// Device error
				err = true;
				break;
			}
			else if (size == 0)
			{
				// Can not get any more
				break;
			}
			else
			{
				// Pass the IPC socket
				TubeSendEx(a->Sock1->SendTube, data, size, NULL, true);
				Free(data);
				flush_tube = true;
				state_changed = true;
			}
		}

		if (flush_tube)
		{
			TubeFlush(a->Sock1->SendTube);
		}

		// Pass to the bridge by receiving from IPC
		recv_packets = NULL;
		while (true)
		{
			TUBEDATA *d = TubeRecvAsync(a->Sock1->RecvTube);

			if (d == NULL)
			{
				break;
			}

			if (recv_packets == NULL)
			{
				recv_packets = NewListFast(NULL);
			}

			Add(recv_packets, d);

			state_changed = true;
		}
		if (recv_packets != NULL)
		{
			UINT i;
			UINT num = LIST_NUM(recv_packets);
			void **data_array;
			UINT *size_array;

			data_array = Malloc(sizeof(void *) * num);
			size_array = Malloc(sizeof(UINT) * num);

			for (i = 0;i < num;i++)
			{
				TUBEDATA *d = LIST_DATA(recv_packets, i);

				data_array[i] = d->Data;
				size_array[i] = d->DataSize;
			}

			EthPutPackets(a->Eth, num, data_array, size_array);

			for (i = 0;i < num;i++)
			{
				TUBEDATA *d = LIST_DATA(recv_packets, i);

				// Because the data buffer has been already released, not to release twice
				d->Data = NULL;

				FreeTubeData(d);
			}

			Free(data_array);
			Free(size_array);

			ReleaseList(recv_packets);
		}

		if (IsTubeConnected(a->Sock1->SendTube) == false || IsTubeConnected(a->Sock1->RecvTube) == false)
		{
			err = true;
		}

		if (err)
		{
			// An error has occured
			Debug("Native Stack: Error !\n");
			a->Halt = true;
			continue;
		}

		if (state_changed)
		{
			goto LABEL_RESTART;
		}

		Select(&set, 1234, a->Cancel, NULL);
	}

	Disconnect(a->Sock1);
	Disconnect(a->Sock2);
}
Esempio n. 2
0
// Process the timer interrupt
void SstpProcessInterrupt(SSTP_SERVER *s)
{
	// Validate arguments
	if (s == NULL)
	{
		return;
	}

	s->Now = Tick64();

	s->FlushRecvTube = false;

	// Process the received packet
	while (true)
	{
		BLOCK *b = GetNext(s->RecvQueue);
		SSTP_PACKET *p;

		if (b == NULL)
		{
			break;
		}

		p = SstpParsePacket(b->Buf, b->Size);
		if (p == NULL)
		{
			// Disconnect the SSTP since a bad packet received
			SstpAbort(s);
		}
		else
		{
			// Process the received packet
			SstpProcessPacket(s, p);

			SstpFreePacket(p);
		}

		FreeBlock(b);
	}

	if (s->FlushRecvTube)
	{
		TubeFlush(s->TubeRecv);
	}

	// Transmit a packet that the PPP module is trying to send via the SSTP
	while (true)
	{
		TUBEDATA *d = TubeRecvAsync(s->TubeSend);
		SSTP_PACKET *p;
		if (d == NULL)
		{
			break;
		}

		p = SstpNewDataPacket(d->Data, d->DataSize);

		SstpSendPacket(s, p);

		SstpFreePacket(p);

		FreeTubeData(d);
	}

	if (s->Status == SSTP_SERVER_STATUS_ESTABLISHED)
	{
		if (s->Disconnecting == false && s->Aborting == false)
		{
			// Periodic transmission of Echo Request
			if (s->NextSendEchoRequestTick == 0 || s->NextSendEchoRequestTick <= s->Now)
			{
				UINT64 next_interval = (UINT64)(SSTP_ECHO_SEND_INTERVAL_MIN + Rand32() % (SSTP_ECHO_SEND_INTERVAL_MAX - SSTP_ECHO_SEND_INTERVAL_MIN));
				SSTP_PACKET *p;

				s->NextSendEchoRequestTick = s->Now + next_interval;
				AddInterrupt(s->Interrupt, s->NextSendEchoRequestTick);

				p = SstpNewControlPacket(SSTP_MSG_ECHO_REQUEST);

				SstpSendPacket(s, p);

				SstpFreePacket(p);
			}
		}
	}

	if ((s->LastRecvTick + (UINT64)SSTP_TIMEOUT) <= s->Now)
	{
		// Disconnect the SSTP because a timeout occurred
		SstpAbort(s);
		s->Disconnected = true;
	}

	if (IsTubeConnected(s->TubeRecv) == false || IsTubeConnected(s->TubeSend) == false)
	{
		// Disconnect the SSTP since the PPP module is disconnected
		SstpDisconnect(s);
	}

	if (s->Disconnecting)
	{
		// Normal disconnection process
		if (s->DisconnectSent == false)
		{
			// Send a Disconnect
			SSTP_PACKET *ret = SstpNewControlPacket(s->DisconnectRecved ? SSTP_MSG_CALL_DISCONNECT_ACK : SSTP_MSG_CALL_DISCONNECT);

			SstpSendPacket(s, ret);

			SstpFreePacket(ret);

			s->DisconnectSent = true;
		}
	}

	if (s->Aborting)
	{
		// Abnormal disconnection processing
		if (s->AbortSent == false)
		{
			// Send the Abort
			SSTP_PACKET *ret = SstpNewControlPacket(SSTP_MSG_CALL_ABORT);

			SstpSendPacket(s, ret);

			SstpFreePacket(ret);

			s->AbortSent = true;
		}
	}

	if (s->DisconnectSent && s->DisconnectRecved)
	{
		// Disconnect after exchanging the Disconnect each other
		s->Disconnected = true;
	}

	if (s->AbortSent && s->AbortReceived)
	{
		// Disconnect after exchanging the Abort each other
		s->Disconnected = true;
	}
}