//
// Copyright (c) 2002
// Ronald Kevin Burton
//
// Z poniższym kodem nie jest związana żadna gwarancja poprawności działania.
// Program został dołączony do książki ".NET CLR. Księga eksperta" w celu
// ilustracji koncepcji i zasad przedstawionych w tej książce. Program może być 
// używany na własne ryzyko.
//
// Przyznaje się prawo do użycia lub kopiowania tego oprogramowania do dowolnego celu
// bez konieczności ponoszenia żadnych opłat pod warunkiem, że powyższe uwagi zostaną 
// zachowane we wszystkich kopiach. Przyznaje się także prawo do modyfikacji kodu
// i dystrybucji zmodyfikowanego kodu pod warunkiem zachowania powyższych uwag
// oraz dołączenia informacji mówiącej o modyfikacji kodu.
//
// 
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Security.Permissions;

class Listener
{
	private static void AssertAndGo()
	{
		Console.WriteLine("Włączenie wszystkich aż do portu 5000...");
		SocketPermission sp = new SocketPermission(PermissionState.None);
		sp.AddPermission(NetworkAccess.Connect,
			TransportType.Tcp,
			"gilgamesh",
			SocketPermission.AllPorts);
		sp.AddPermission(NetworkAccess.Accept,
			TransportType.Tcp,
			"*.*.*.*",
			5000);
		sp.Assert();

		TcpListener client = new TcpListener(5000);
		client.Start();
		Socket s = client.AcceptSocket();

		ProcessRequests(s);

		s.Close();

		client.Stop();
	}

	private static void DenyThenAssertThenGo()
	{
		Console.WriteLine("Wyłączenie wszystkich...");
		SocketPermission sp = new SocketPermission(PermissionState.Unrestricted);
		sp.Deny();
		AssertAndGo();
	}

	private static void ProcessRequests(Socket s)
	{
		byte[] responseData = new byte[128];
		bool continueProcessing = true;

		try
		{
			IPEndPoint remoteEndPoint = (IPEndPoint)s.RemoteEndPoint;
			IPAddress remoteAddress = remoteEndPoint.Address;
			IPHostEntry remoteHostEntry = Dns.GetHostByAddress(remoteAddress);
			Console.WriteLine("Zaakceptowano połączenie ze zdalnego komputera ({0})...", remoteHostEntry.HostName);
			SocketPermission sp = new SocketPermission(NetworkAccess.Connect,
				TransportType.Tcp,
				remoteHostEntry.HostName,
				remoteEndPoint.Port);
			sp.Demand();
		}
		catch(Exception e)
		{
			Console.WriteLine("Błąd uprawnienia: {0}", e.ToString());
			return;
		}

		Console.WriteLine("Próba odczytu/zapisu...");

		while(continueProcessing)
		{	
			try
			{
				int bytesRead = s.Receive(responseData);
				// string message = Encoding.ASCII.GetString(responseData, 0, bytesRead);
				string message = Encoding.Unicode.GetString(responseData, 0, bytesRead);
				if(message == "quit")
				{
					continueProcessing = false;
					break;
				}
				else
				{
					Console.WriteLine("Otrzymana wiadomość to " + message);
				}
			}
			catch(Exception ex)
			{
				Console.WriteLine(ex.ToString());
			}
		}
	}

	public static void Main()
	{
		Console.WriteLine("Gotowy do przetwarzania żądań...");
		DenyThenAssertThenGo();
	}
}
