/*

	Chat program proof-of-concept using UDP.
	Needs Bridged Mode working on two VMs under the same router.

*/

U8				*dest_ip_string		= StrGet("Destination IPV4: "),
				*port_string		= StrGet("RX & TX UDP Port: ");
CIPV4Address	*dest_address		= CAlloc(sizeof(CIPV4Address));

I64				 port				= Str2I64(port_string);
CTask			*chat_display_task	= NULL;
CTask			*chat_message_task	= NULL;

U0 ChatDisplayTask(I64)
{ // display received messages.
	DocTermNew;
	DocCursor;
	DocPrint(, "$$WW,1$$");

	while (TaskValidate(chat_message_task))
	{
		Refresh;
	}
}

U0 ChatMessageTask(I64)
{ // take in text.
	U8	*message;
	I64  de_index;
	U8	*payload;

	DocTermNew;
	DocPrint(, "$$WW,1$$");

	while (message = StrGet("> ",, SGF_SHIFT_ESC_EXIT))
	{
		DocBottom(chat_display_task->put_doc);
		DocPrint(chat_display_task->put_doc, "$$BG,BLUE$$$$BLACK$$<local>$$FG$$$$BG$$ %s\n", message);

		de_index = UDPPacketAllocate(&payload, ipv4_globals.local_ip, port, dest_address->address, port, StrLen(message));
		MemCopy(payload, message, StrLen(message));
		UDPPacketFinish(de_index);

		DocClear;
		DocPrint(, "$$WW,1$$");

	}
}

U0 ChatInit()
{
	chat_message_task = Spawn(&ChatMessageTask, NULL, "UDP Chat Message");
	chat_display_task = Spawn(&ChatDisplayTask, NULL, "UDP Chat");
	chat_message_task->win_inhibit = WIG_USER_TASK_DEFAULT;
	chat_display_task->win_inhibit = WIG_USER_TASK_DEFAULT;
	LBts(&chat_message_task->display_flags, DISPLAYf_SHOW);
	LBts(&chat_display_task->display_flags, DISPLAYf_SHOW);

	WinFocus(chat_display_task);
	WinFocus(chat_message_task);

	chat_display_task->win_top		= 2;
	chat_display_task->win_bottom	= TEXT_ROWS / 3;
	chat_display_task->win_left		= TEXT_COLS / 3;
	chat_display_task->win_right	= TEXT_COLS / 3 * 2;

	chat_message_task->win_top		= chat_display_task->win_bottom + 2;
	chat_message_task->win_bottom	= chat_message_task->win_top + 3;
	chat_message_task->win_left		= chat_display_task->win_left;
	chat_message_task->win_right	= chat_display_task->win_right;

}

U0 Chat()
{
	CUDPSocket			*udp_socket = UDPSocket(AF_INET);
	CSocketAddressIPV4	*sock_addr = CAlloc(sizeof(CSocketAddressIPV4));
	U8					*buffer[ETHERNET_FRAME_SIZE];

//	MemSet(buffer, 0, ETHERNET_FRAME_SIZE);

	"\nIP entered: %s\n", dest_ip_string;

	while (PresentationToNetwork(AF_INET, dest_ip_string, dest_address) == -1)
	{
		"ERROR: Bad IP entered. Retry.\n";
		dest_ip_string = StrGet("Destination IPV4: ");
	}

	ChatInit;

	sock_addr->port				= EndianU16(port);
	sock_addr->family			= AF_INET;
	sock_addr->address.address	= dest_address->address;
	UDPSocketBind(udp_socket, sock_addr);

	"\nIP entered: %s\n", dest_ip_string;

	while (TaskValidate(chat_message_task))
	{
		if (UDPSocketReceiveFrom(udp_socket, buffer, ETHERNET_FRAME_SIZE, NULL) != -1)
		{
			DocBottom(chat_display_task->put_doc);
			DocPrint(chat_display_task->put_doc, "$$BG,PURPLE$$$$BLACK$$<%s>$$FG$$$$BG$$  %s\n", dest_ip_string, buffer);//NetworkToPresentation(AF_INET, dest_address));
			MemSet(buffer, 0, ETHERNET_FRAME_SIZE);
		}

		Refresh;

	}

}

Chat;