Exemplo n.º 1
0
void FifoPlayer::WriteFramePart(u32 dataStart, u32 dataEnd, u32 &nextMemUpdate, const FifoFrameInfo &frame, const AnalyzedFrameInfo &info)
{
	u8 *data = frame.fifoData;

	while (nextMemUpdate < frame.memoryUpdates.size() && dataStart < dataEnd)
	{
		const MemoryUpdate &memUpdate = info.memoryUpdates[nextMemUpdate];

		if (memUpdate.fifoPosition < dataEnd)
		{
			if (dataStart < memUpdate.fifoPosition)
			{
				WriteFifo(data, dataStart, memUpdate.fifoPosition);
				dataStart = memUpdate.fifoPosition;
			}

			WriteMemory(memUpdate);

			++nextMemUpdate;
		}
		else
		{
			WriteFifo(data, dataStart, dataEnd);
			dataStart = dataEnd;
		}
	}

	if (dataStart < dataEnd)
		WriteFifo(data, dataStart, dataEnd);
}
Exemplo 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;
}