commit 34bf7aa21bcd519891eb590e0ec23fcf370bb0e6
Author: Eliška Mourycová <eliska.mourycova@seznam.cz>
Date:   Sun Apr 18 15:52:21 2021 +0200

    Refs #8620, #8619. Refactor + testing.

diff --git a/ClientConnectionTest/ClientTest/.vs/ClientTest/v16/.suo b/ClientConnectionTest/ClientTest/.vs/ClientTest/v16/.suo
index 85ef11a..40f5646 100644
Binary files a/ClientConnectionTest/ClientTest/.vs/ClientTest/v16/.suo and b/ClientConnectionTest/ClientTest/.vs/ClientTest/v16/.suo differ
diff --git a/ClientConnectionTest/ClientTest/ClientTest/Program.cs b/ClientConnectionTest/ClientTest/ClientTest/Program.cs
index 16f10d6..d7be656 100644
--- a/ClientConnectionTest/ClientTest/ClientTest/Program.cs
+++ b/ClientConnectionTest/ClientTest/ClientTest/Program.cs
@@ -203,13 +203,21 @@ using System.Text;
 
 class Program
 {
-    const int PORT_NO = 11000;
-    const string SERVER_IP = "127.0.0.1";
+    static int PORT_NO = 11000;
+    const string SERVER_IP = "127.0.0.1";//"192.168.1.5";
     static void Main(string[] args)
     {
         //---data to send to the server---
         string textToSend = "ahoj!";
 
+        Console.WriteLine("enter A if you are admin: ");
+        string ent = "B";
+        ent = Console.ReadLine();
+
+		if (ent.Equals("A"))
+		{
+            PORT_NO = 10000;
+		}
         //---create a TCPClient object at the IP and port no.---
         TcpClient client = new TcpClient(SERVER_IP, PORT_NO);
         NetworkStream nwStream = client.GetStream();
diff --git a/ClientConnectionTest/ClientTest/ClientTest/bin/Debug/net5.0/ClientTest.dll b/ClientConnectionTest/ClientTest/ClientTest/bin/Debug/net5.0/ClientTest.dll
index c4f34be..793e3bb 100644
Binary files a/ClientConnectionTest/ClientTest/ClientTest/bin/Debug/net5.0/ClientTest.dll and b/ClientConnectionTest/ClientTest/ClientTest/bin/Debug/net5.0/ClientTest.dll differ
diff --git a/ClientConnectionTest/ClientTest/ClientTest/bin/Debug/net5.0/ClientTest.pdb b/ClientConnectionTest/ClientTest/ClientTest/bin/Debug/net5.0/ClientTest.pdb
index 0388651..5c7c470 100644
Binary files a/ClientConnectionTest/ClientTest/ClientTest/bin/Debug/net5.0/ClientTest.pdb and b/ClientConnectionTest/ClientTest/ClientTest/bin/Debug/net5.0/ClientTest.pdb differ
diff --git a/ClientConnectionTest/ClientTest/ClientTest/obj/Debug/net5.0/ClientTest.csprojAssemblyReference.cache b/ClientConnectionTest/ClientTest/ClientTest/obj/Debug/net5.0/ClientTest.csprojAssemblyReference.cache
index b8faec7..8210100 100644
Binary files a/ClientConnectionTest/ClientTest/ClientTest/obj/Debug/net5.0/ClientTest.csprojAssemblyReference.cache and b/ClientConnectionTest/ClientTest/ClientTest/obj/Debug/net5.0/ClientTest.csprojAssemblyReference.cache differ
diff --git a/ClientConnectionTest/ClientTest/ClientTest/obj/Debug/net5.0/ClientTest.dll b/ClientConnectionTest/ClientTest/ClientTest/obj/Debug/net5.0/ClientTest.dll
index c4f34be..793e3bb 100644
Binary files a/ClientConnectionTest/ClientTest/ClientTest/obj/Debug/net5.0/ClientTest.dll and b/ClientConnectionTest/ClientTest/ClientTest/obj/Debug/net5.0/ClientTest.dll differ
diff --git a/ClientConnectionTest/ClientTest/ClientTest/obj/Debug/net5.0/ClientTest.pdb b/ClientConnectionTest/ClientTest/ClientTest/obj/Debug/net5.0/ClientTest.pdb
index 0388651..5c7c470 100644
Binary files a/ClientConnectionTest/ClientTest/ClientTest/obj/Debug/net5.0/ClientTest.pdb and b/ClientConnectionTest/ClientTest/ClientTest/obj/Debug/net5.0/ClientTest.pdb differ
diff --git a/Server/.vs/ServerApp/v16/.suo b/Server/.vs/ServerApp/v16/.suo
index 4b6da0c..851b08b 100644
Binary files a/Server/.vs/ServerApp/v16/.suo and b/Server/.vs/ServerApp/v16/.suo differ
diff --git a/Server/ServerApp/Connection/SocketListener.cs b/Server/ServerApp/Connection/SocketListener.cs
index c9fe8de..d5d6006 100644
--- a/Server/ServerApp/Connection/SocketListener.cs
+++ b/Server/ServerApp/Connection/SocketListener.cs
@@ -1,52 +1,63 @@
-﻿using System;
-using System.Collections.Generic;
-using System.Linq;
+﻿//
+// Author: Eliska Mourycova
+//
+
+using System;
 using System.Net;
 using System.Net.Sockets;
 using System.Text;
 using System.Threading;
-using System.Threading.Tasks;
 
 namespace Connection
 {
-    // State object for reading client data asynchronously
+    /// <summary>
+    /// State object for reading client data asynchronously
+    /// </summary>
     public class StateObject
     {
         // Client  socket.
-        public Socket workSocket = null;
+        public Socket WorkSocket = null;
         // Size of receive buffer.
-        public const int BufferSize = 1024;
+        public const int BUFFER_SIZE = 1024;
         // Receive buffer.
-        public byte[] buffer = new byte[BufferSize];
+        public byte[] Buffer = new byte[BUFFER_SIZE];
         // Received data string.
-        public StringBuilder sb = new StringBuilder();
+        public StringBuilder StrBuilder = new StringBuilder();
     }
 
+    /// <summary>
+    /// This class takes care of client connection. It serves clients asynchronously.
+    /// </summary>
     public class AsynchronousSocketListener
     {
-        // Thread signal.
-        public static ManualResetEvent allDone = new ManualResetEvent(false);
+        // port numbers:
+        private const int PORT_NO = 11000;
+        private const int ADMIN_PORT_NO = 10000;
 
-        public AsynchronousSocketListener()
-        {
-        }
 
+        // Thread signal
+        private ManualResetEvent allDone = new ManualResetEvent(false);
+
+        /// <summary>
+        /// Starts listening and accepting connections. It serves requests when they come.
+        /// </summary>
         public void StartListening()
         {
             // Data buffer for incoming data.
             byte[] bytes = new Byte[1024];
 
-            // Establish the local endpoint for the socket.
-            // The DNS name of the computer
-            // running the listener is "host.contoso.com".
+            // Establish the local endpoint for the socket:
             IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
+
+            // Get the IP of the machine - UNUSED ATM, USING LOOPBACK ON LOCALHOST
             IPAddress ipAddress = ipHostInfo.AddressList[1];
-            Console.WriteLine("ip: " + ipAddress.ToString());
-            IPEndPoint localEndPoint = new IPEndPoint(/*ipAddress*/IPAddress.Loopback, 11000);
+            Console.WriteLine("machine ip: " + ipAddress.ToString());
+            IPEndPoint localEndPoint = new IPEndPoint(/*ipAddress*/IPAddress.Loopback, PORT_NO);
+            IPEndPoint localEndPointAdmin = new IPEndPoint(/*ipAddress*/IPAddress.Loopback, ADMIN_PORT_NO);
 
             // Create a TCP/IP socket.
-            Socket listener = new Socket(AddressFamily.InterNetwork,
-                SocketType.Stream, ProtocolType.Tcp);
+            Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
+            Socket listenerAdmin = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
 
             // Bind the socket to the local endpoint and listen for incoming connections.
             try
@@ -54,6 +65,10 @@ namespace Connection
                 listener.Bind(localEndPoint);
                 listener.Listen(100);
 
+                listenerAdmin.Bind(localEndPointAdmin);
+                listenerAdmin.Listen(1);
+
+                // keep accepting
                 while (true)
                 {
                     // Set the event to nonsignaled state.
@@ -62,6 +77,7 @@ namespace Connection
                     // Start an asynchronous socket to listen for connections.
                     Console.WriteLine("Waiting for a connection...");
                     listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
+                    listenerAdmin.BeginAccept(new AsyncCallback(AcceptCallback), listenerAdmin);
 
                     // Wait until a connection is made before continuing.
                     allDone.WaitOne();
@@ -70,6 +86,7 @@ namespace Connection
             }
             catch (Exception e)
             {
+                // bind failed
                 Console.WriteLine(e.ToString());
             }
 
@@ -78,61 +95,77 @@ namespace Connection
 
         }
 
-        public void AcceptCallback(IAsyncResult ar)
+        // Routine for when BeginAccept on the given listener ended
+        private void AcceptCallback(IAsyncResult ar)
         {
             // Signal the main thread to continue.
             allDone.Set();
             Console.WriteLine("Accepted a connection.");
+            
 
             // Get the socket that handles the client request.
             Socket listener = (Socket)ar.AsyncState;
             Socket handler = listener.EndAccept(ar);
 
+            // debug
+            Console.WriteLine("handler: ");
+            Console.WriteLine("I am connected to " + IPAddress.Parse(((IPEndPoint)handler.RemoteEndPoint).Address.ToString()) + " on port number " + ((IPEndPoint)handler.RemoteEndPoint).Port.ToString());
+            Console.WriteLine("My local IpAddress is : " + IPAddress.Parse(((IPEndPoint)handler.LocalEndPoint).Address.ToString()) + ". I am connected on port number " + ((IPEndPoint)handler.LocalEndPoint).Port.ToString());
+
+
+
+
             // Create the state object.
             StateObject state = new StateObject();
-            state.workSocket = handler;
-            handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
+            state.WorkSocket = handler;
+            handler.BeginReceive(state.Buffer, 0, StateObject.BUFFER_SIZE, 0, new AsyncCallback(ReadCallback), state);
             
         }
 
-        public void ReadCallback(IAsyncResult ar)
+        // Routine for when BeginReceive on the given listener ended
+        private void ReadCallback(IAsyncResult ar)
         {
-
-            
-
-
+            // string for the received message
             String content = String.Empty;
 
             // Retrieve the state object and the handler socket
             // from the asynchronous state object.
             StateObject state = (StateObject)ar.AsyncState;
-            Socket handler = state.workSocket;
+            Socket handler = state.WorkSocket;
 
+            // check if we're still connected
             if (!SocketConnected(handler))
 			{
+                // if the client isn't connected anymore, take care of cleanup
                 Console.WriteLine("Closing connection - unexpected...");
                 CloseConnection(handler);
+
+                // return so that we don't attempt to read from a non-existent stream
                 return;
             }
 
-                // Read data from the client socket. 
+            // check if it is admin's request we're serving
+            bool admin = ((IPEndPoint)handler.LocalEndPoint).Port == ADMIN_PORT_NO;
+
+            // Read data from the client socket. 
             int bytesRead = handler.EndReceive(ar);
 
             if (bytesRead > 0)
             {
                 // There  might be more data, so store the data received so far.
-                state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
+                state.StrBuilder.Append(Encoding.ASCII.GetString(state.Buffer, 0, bytesRead));
 
-                // Check for end-of-file tag. If it is not there, read 
-                // more data.
-                content = state.sb.ToString();
+                // Check for end-of-file tag. If it is not there, read more data.
+                content = state.StrBuilder.ToString();
                 if (content.IndexOf("!") > -1)
                 {
-                    // All the data has been read from the 
-                    // client. Display it on the console.
+                    // All the data has been read from the client. Display it on the console.
                     Console.WriteLine("Read {0} bytes from socket. \n Data : {1}", content.Length, content);
 
-                    content = ParseMessageAndBuildAnswer(content);
+                    // parse the message and determine the response:
+                    content = ParseMessageAndBuildAnswer(content, admin);
+
+                    // check if the client wishes to close the connection:
                     if (content.Equals("bye!"))
                     {
                         Console.WriteLine("Closing connection - expected...");
@@ -142,21 +175,24 @@ namespace Connection
                         return;
                     }
 
-                    // Echo the data back to the client.
+                    // Send a response to the client
                     Send(handler, content);
 					
+                    // clear the string
+                    state.StrBuilder.Clear();
 
-                    state.sb.Clear();
-                    handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
+                    // begin receiving another message:
+                    handler.BeginReceive(state.Buffer, 0, StateObject.BUFFER_SIZE, 0, new AsyncCallback(ReadCallback), state);
                 }
                 else
                 {
                     // Not all data received. Get more.
-                    handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
+                    handler.BeginReceive(state.Buffer, 0, StateObject.BUFFER_SIZE, 0, new AsyncCallback(ReadCallback), state);
                 }
             }
         }
 
+        // Takes care of sending data to a connected client
         private void Send(Socket handler, String data)
         {
             // Convert the string data to byte data using ASCII encoding.
@@ -166,6 +202,7 @@ namespace Connection
             handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
         }
 
+        // Routine for when BeginSend on the given listener ended
         private void SendCallback(IAsyncResult ar)
         {
             try
@@ -184,18 +221,22 @@ namespace Connection
             }
             catch (Exception e)
             {
+                // close connection here?
+
                 Console.WriteLine(e.ToString());
             }
         }
 
 
-
-
-
-
-
-        private string ParseMessageAndBuildAnswer(string message)
+        /// <summary>
+        /// Parses the incoming request and determines the response.
+        /// </summary>
+        /// <param name="message">The incoming message from the client</param>
+        /// <param name="admin">A flag saying whether it is admin's request</param>
+        /// <returns></returns>
+        private string ParseMessageAndBuildAnswer(string message, bool admin)
 		{
+            Console.WriteLine("Parsing message from admin: " + admin);
             string ans = "";
 
 			if (message.Equals("hello!"))
@@ -220,13 +261,21 @@ namespace Connection
             return ans;
 		}
 
-
+        /// <summary>
+        /// Closes the connection on the passed Socket
+        /// </summary>
+        /// <param name="s">The socket to close the connection for</param>
         private void CloseConnection(Socket s)
 		{
             s.Shutdown(SocketShutdown.Both);
             s.Close();
         }
 
+        /// <summary>
+        /// Checks whether the connection on a given socket is active
+        /// </summary>
+        /// <param name="s">The socket to check for connection activity</param>
+        /// <returns>True if the connection is active, false otherwise</returns>
         private bool SocketConnected(Socket s)
         {
             bool part1 = s.Poll(1000, SelectMode.SelectRead);
diff --git a/Server/ServerApp/DataDownload/DataDownloader.cs b/Server/ServerApp/DataDownload/DataDownloader.cs
index e382ec4..e465d44 100644
--- a/Server/ServerApp/DataDownload/DataDownloader.cs
+++ b/Server/ServerApp/DataDownload/DataDownloader.cs
@@ -1,37 +1,64 @@
-﻿using System;
+﻿//
+// Author: Eliska Mourycova
+//
+
+using System;
 using System.Collections.Generic;
 using System.IO;
 using System.IO.Compression;
-using System.Linq;
 using System.Net;
-using System.Text;
-using System.Text.RegularExpressions;
-using System.Threading.Tasks;
-using static System.Net.Mime.MediaTypeNames;
 
 namespace DataDownload
 {
+	/// <summary>
+	/// Enum representing all of the available data types (not all will be used in this project)
+	/// They are in Czech for easier handling file names.
+	/// TBD: They might be translated to English later.
+	/// </summary>
 	public enum DataType
 	{
 		POCASI, ENERGO, STROJE, EMAIL, OBSAZENI_MISTNOSTI, JIS, KOLOBEZKY, WIFI
 	}
+
+	/// <summary>
+	/// Represent all available data formats.
+	/// </summary>
 	public enum DataFormat
 	{
 		XML, JSON, CSV
 	}
 
+	/// <summary>
+	/// This class takes care of downloading of data. Download happens from http://openstore.zcu.cz/.
+	/// </summary>
 	public class DataDownloader
 	{
+		/// <summary>
+		/// The root directory containing all downloaded data
+		/// </summary>
 		public string DataDirectory { get; }
+
+		/// <summary>
+		/// Flag stating whether files which already exist should be overwritten when downloaded again
+		/// </summary>
 		public bool OverwriteExisting { get; set; }
 
+		// the main site where the data can be downloaded from
 		private string site;
+
+		// the substring at the start of every file name
 		private string dataStr;
+
+		// WebClient instance used for the actual download
 		private WebClient webClient;
+
+		// a shortcut to writing Path.DirectorySeparatorChar
 		private char sep = Path.DirectorySeparatorChar;
 
 		public DataDownloader()
 		{
+			// initialize all needed variables:
+
 			Console.WriteLine(Directory.GetCurrentDirectory());
 			site = "http://openstore.zcu.cz/";
 			dataStr = "OD_ZCU_";
@@ -42,6 +69,14 @@ namespace DataDownload
 			webClient = new WebClient();
 		}
 
+		/// <summary>
+		/// Downloads a specific archive.
+		/// </summary>
+		/// <param name="type">The type of data</param>
+		/// <param name="format">The format of the data</param>
+		/// <param name="year">The year</param>
+		/// <param name="month">The month</param>
+		/// <returns>A list of all extracted file names (should be only one)</returns>
 		private List<string> DownloadData(DataType type, DataFormat format, int year, int month)
 		{
 			// the list of all files potentially relevant to the caller
diff --git a/Server/ServerApp/bin/Debug/ServerApp.exe b/Server/ServerApp/bin/Debug/ServerApp.exe
index 949dd33..914c1d8 100644
Binary files a/Server/ServerApp/bin/Debug/ServerApp.exe and b/Server/ServerApp/bin/Debug/ServerApp.exe differ
diff --git a/Server/ServerApp/bin/Debug/ServerApp.pdb b/Server/ServerApp/bin/Debug/ServerApp.pdb
index 148683d..08274df 100644
Binary files a/Server/ServerApp/bin/Debug/ServerApp.pdb and b/Server/ServerApp/bin/Debug/ServerApp.pdb differ
diff --git a/Server/ServerApp/obj/Debug/ServerApp.csprojAssemblyReference.cache b/Server/ServerApp/obj/Debug/ServerApp.csprojAssemblyReference.cache
index 31a4ac6..f5cfc18 100644
Binary files a/Server/ServerApp/obj/Debug/ServerApp.csprojAssemblyReference.cache and b/Server/ServerApp/obj/Debug/ServerApp.csprojAssemblyReference.cache differ
diff --git a/Server/ServerApp/obj/Debug/ServerApp.exe b/Server/ServerApp/obj/Debug/ServerApp.exe
index 949dd33..914c1d8 100644
Binary files a/Server/ServerApp/obj/Debug/ServerApp.exe and b/Server/ServerApp/obj/Debug/ServerApp.exe differ
diff --git a/Server/ServerApp/obj/Debug/ServerApp.pdb b/Server/ServerApp/obj/Debug/ServerApp.pdb
index 148683d..08274df 100644
Binary files a/Server/ServerApp/obj/Debug/ServerApp.pdb and b/Server/ServerApp/obj/Debug/ServerApp.pdb differ
