From ac2abffa89f3438abc9f24c2d6853f73e6282408 Mon Sep 17 00:00:00 2001
From: sili98 <sili98@sch.bme.hu>
Date: Sat, 16 Nov 2019 02:47:31 +0100
Subject: [PATCH] Some networking. More backend stuff.

---
 zsirozas/Form1.cs      |   3 +-
 zsirozas/Game.cs       |   5 +-
 zsirozas/GameClient.cs | 164 +++++++++++++++++++++++++--
 zsirozas/Server.cs     | 246 ++++++++++++++++++++++++++++++-----------
 4 files changed, 346 insertions(+), 72 deletions(-)

diff --git a/zsirozas/Form1.cs b/zsirozas/Form1.cs
index 091438b..0a73a6d 100644
--- a/zsirozas/Form1.cs
+++ b/zsirozas/Form1.cs
@@ -16,6 +16,7 @@ namespace zsirozas
         {
             InitializeComponent();
             CardButtons = new Button[] { buttonCard0, buttonCard1, buttonCard2, buttonCard3 };
+            client = new GameClient();
         }
 
         private void buttonEndTurn_Click(object sender, EventArgs e)
@@ -52,7 +53,7 @@ namespace zsirozas
             int port_num;
             if (int.TryParse(textBoxServerPort.Text, out port_num))
             {
-                if (GameClient.pingServer(textBoxServerAddr.Text,port_num))
+                if (client.pingServer(textBoxServerAddr.Text,port_num))
                 {
                     buttonServerTest.BackColor = Color.Green;
                 }
diff --git a/zsirozas/Game.cs b/zsirozas/Game.cs
index 1bfce69..5b8e746 100644
--- a/zsirozas/Game.cs
+++ b/zsirozas/Game.cs
@@ -15,7 +15,8 @@ namespace zsirozas
 
         public void NotifyPlayers(GameEvent @event)
         {
-            string message = @event.ToString();
+            string prefix = ServerAction.GameAction.ToString() + "\n";
+            string message = prefix + @event.ToString();
             switch (@event)
             {
                 case GameEvent.CardAction:
@@ -172,6 +173,8 @@ namespace zsirozas
                     Complain("Objection! It's not a valid request!");
                     break;
             }
+            //TODO: ezt majd vagyük ki...
+            return null;
         }
         public void Complain(string message)
         {
diff --git a/zsirozas/GameClient.cs b/zsirozas/GameClient.cs
index cd3adc8..d91baf7 100644
--- a/zsirozas/GameClient.cs
+++ b/zsirozas/GameClient.cs
@@ -1,4 +1,8 @@
 using System;
+using System.IO;
+using System.Net;
+using System.Net.Sockets;
+using System.Threading;
 using System.Web.Script.Serialization;
 
 namespace zsirozas
@@ -13,19 +17,53 @@ namespace zsirozas
         //connectivity stuff
         //
 
-        public static bool pingServer(string IP, int port)
+        public bool pingServer(string IP, int port)
         {
-            throw new NotImplementedException();
+            try
+            {
+                var tempConn = new TcpClient();
+                tempConn.Connect(IPAddress.Parse(IP), port);
+                using (var sw = new StreamWriter(tempConn.GetStream()))
+                using (var sr = new StreamReader(tempConn.GetStream()))
+                {
+                    sw.WriteLine(ServerAction.Ping);
+                    if (sr.ReadLine() != "OK")
+                    {
+                        return false;
+                    }
+                }
+                return true;
+            }
+            catch (Exception ex)
+            {
+                return false;
+            }
         }
 
-        public static string[] searchLAN()
+        public IPEndPoint[] searchLAN()
         {
+            //this is an extendned feature not yet available
             throw new NotSupportedException();
         }
 
         public bool Connect(string server_ip, int server_port)
         {
-            //TODO: connect
+            if (pingServer(server_ip, server_port))
+            {
+                server = new IPEndPoint(IPAddress.Parse(server_ip), server_port);
+                try
+                {
+                    incomingListener.Start();
+                    if (SendRequest(ServerAction.Login, 6501 + ""))
+                    {
+                        messageStream = incomingListener.AcceptTcpClient().GetStream();
+                        new Thread(ListenForServer).Start();
+                        return true;
+                    }
+                }
+                catch (Exception ex) { }
+            }
+
             return false;
         }
 
@@ -35,6 +73,119 @@ namespace zsirozas
 
         public event EventHandler<string> handleServerError;
 
+        public IPEndPoint server;
+        public string userID;
+        public string roomID;
+        public string gameID;
+        public int playerIDX;
+
+        TcpListener incomingListener = new TcpListener(IPAddress.Any, 6501);
+        Stream messageStream = null;
+
+        public bool SendRequest(ServerAction action, string @params = null) 
+        {
+            var tempConn = new TcpClient();
+            tempConn.Connect(server);
+            using (var sw = new StreamWriter(tempConn.GetStream()))
+            using (var sr = new StreamReader(tempConn.GetStream())) 
+            {
+                sw.WriteLine();
+                string status = null;
+                sw.WriteLine(action);
+                switch (action)
+                {
+                    case ServerAction.CreateRoom:
+                        sw.WriteLine(userID);
+                        if ((status = sr.ReadLine()) != "OK")
+                        {
+                            handleServerError(this, status);
+                            return false;
+                        }
+                        else
+                        {
+                            roomID = sr.ReadLine();
+                        }
+                        break;
+                    case ServerAction.JoinRoom:
+                        sw.WriteLine(userID);
+                        sw.WriteLine(@params);
+                        if ((status = sr.ReadLine()) != "OK")
+                        {
+                            handleServerError(this, status);
+                            return false;
+                        }
+                        else
+                        {
+                            roomID = @params;
+                        }
+                        break;
+                    case ServerAction.LeaveRoom:
+                        sw.WriteLine(userID);
+                        if ((status = sr.ReadLine()) != "OK")
+                        {
+                            handleServerError(this, status);
+                            return false;
+                        }
+                        break;
+                    case ServerAction.InviteUser:
+                        break;
+                    case ServerAction.GameAction:
+                        sw.WriteLine(gameID);
+                        sw.WriteLine(userID);
+                        sw.WriteLine(@params);
+                        //TODO: ez a getCards idegesítően fura...
+                        if ((status = sr.ReadLine()) != "OK")
+                        {
+                            handleServerError(this, status);
+                            return false;
+                        }
+                        else if (@params.Contains(PlayerAction.GetCards.ToString()))
+                        {
+                            Cards = new JavaScriptSerializer().Deserialize<Card[]>(sr.ReadLine());
+                        }
+                        break;
+                    case ServerAction.Logout:
+                        sw.WriteLine(userID);
+
+                        break;
+                    case ServerAction.Ping:
+                    case ServerAction.Login:
+                    case ServerAction.ListRooms:
+                    default:
+                        break;
+                }
+            }
+            tempConn.Close();
+            return true;
+        }
+
+        void ListenForServer() 
+        {
+
+            //var utruzr = new TcpClient();
+            ////-------stolen code-----------
+            //// Create a TCP/IP socket.  
+            //Socket listener = new Socket(SocketType.Stream, ProtocolType.Tcp);
+
+            //// Bind the socket to the local endpoint and   
+            //// listen for incoming connections.  
+            //IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 1221);
+            //listener.Bind(localEndPoint);
+            //listener.Listen(10);
+
+            //// Start listening for connections.  
+
+            //Console.WriteLine("Waiting for a connection...");
+            //// Program is suspended while waiting for an incoming connection.  
+            //Socket handler = listener.Accept();
+            ////-----stuff happens
+            //handler.Shutdown(SocketShutdown.Both);
+            //handler.Close();
+
+            ////------end stolen code-----------
+            //ParseNextMessage(utruzr.GetStream());
+
+        }
 
 
         //
@@ -56,13 +207,12 @@ namespace zsirozas
 
         public bool UseCard(int card_num)
         {
-            throw new NotImplementedException();
-
+            return SendRequest(ServerAction.GameAction, PlayerAction.Card + "\n" + Cards[card_num].ID);
         }
 
         public bool EndTurn()
         {
-            throw new NotImplementedException();
+            return SendRequest(ServerAction.GameAction, PlayerAction.EndTurn.ToString());
         }
 
         public Game.MidGameState gameState;
diff --git a/zsirozas/Server.cs b/zsirozas/Server.cs
index 8832f58..fc02a39 100644
--- a/zsirozas/Server.cs
+++ b/zsirozas/Server.cs
@@ -10,6 +10,12 @@ namespace zsirozas
     {
         public Server()
         {
+            Users = new List<string>();
+            Rooms = new List<string>();
+            Games = new List<string>();
+            UsersByID = new Dictionary<string, User>();
+            RoomsByID = new Dictionary<string, Room>();
+            GamesByID = new Dictionary<string, Game>();
         }
         public List<string> Users;
         public Dictionary<string, User> UsersByID;
@@ -17,72 +23,115 @@ namespace zsirozas
         public List<string> Games;
         public Dictionary<string, Game> GamesByID;
 
+        public List<string> Rooms;
         public Dictionary<string, Room> RoomsByID;
 
+        public int ListenPort = 6500;
         public void Loop()
         {
-            var utruzr = new TcpClient();
-            //-------stolen code-----------
-            // Create a TCP/IP socket.  
-            Socket listener = new Socket(SocketType.Stream, ProtocolType.Tcp);
-
-            // Bind the socket to the local endpoint and   
-            // listen for incoming connections.  
-            IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 1221);
-            listener.Bind(localEndPoint);
-            listener.Listen(10);
-
-            // Start listening for connections.  
-
-            Console.WriteLine("Waiting for a connection...");
-            // Program is suspended while waiting for an incoming connection.  
-            Socket handler = listener.Accept();
-            //-----stuff happens
-            handler.Shutdown(SocketShutdown.Both);
-            handler.Close();
-
-            //------end stolen code-----------
-                    ParseNextMessage(utruzr.GetStream());
+            if (bigRoom)
+            {
+                string Room0 = "RoomZero";
+                Rooms.Add(Room0);
+                RoomsByID.Add(
+                                Room0,
+                                new Room()
+                                {
+                                    roomID = Room0,
+                                    userList = new List<string>()
+                                }
+                             );
+            }
+            var requestQueue = new TcpListener(IPAddress.Any, ListenPort);
+            while (true)
+            {
+                var clientRequest = requestQueue.AcceptTcpClient();
+                ParseNextMessage(clientRequest.GetStream(), ((IPEndPoint)clientRequest.Client.RemoteEndPoint).Address);
+                clientRequest.Close();
+            }
         }
 
-        public void ParseNextMessage(Stream s)
+        public void ParseNextMessage(Stream s, object param)
         {
             //TODO: eztet rendesen
 
-            var sr = new StreamReader(s);
-
-            string line = "";
-            while (line == "")
+            using (var sr = new StreamReader(s))
+            using (var sw = new StreamWriter(s))
             {
-                line = sr.ReadLine();
-            }
 
-            var action = (ServerAction)Enum.Parse(typeof(ServerAction), line);
-            
-            switch (action)
-            {
-                case ServerAction.GameAction:
-                    //a k9vetkező sor a gameID
+                string line = "";
+                while (line == "")
+                {
                     line = sr.ReadLine();
-                    if (Games.Contains(line))
-                    {
-                        //TODO: GamesByID[line].Action(...
-                    }
-                    break;
-                case ServerAction.Ping:
-                case ServerAction.ListRooms:
-                case ServerAction.Login:
-                case ServerAction.Logout:
-                case ServerAction.CreateRoom:
-                case ServerAction.LeaveRoom:
-                case ServerAction.JoinRoom:
-                case ServerAction.InviteUser:
-                default:
-                    break;
+                }
+
+                var action = (ServerAction)Enum.Parse(typeof(ServerAction), line);
+
+                switch (action)
+                {
+                    case ServerAction.GameAction:
+                        //a következő sor a gameID
+                        line = sr.ReadLine();
+                        if (Games.Contains(line))
+                        {
+                            //TODO: validálni? vagy kivételt elkapni?
+                            GamesByID[line].Action(
+                                //playerID
+                                sr.ReadLine(),
+                                //action
+                                (PlayerAction)Enum.Parse(typeof(PlayerAction), sr.ReadLine()),
+                                //cardID, nem hagyható el (de nem mindig értelmes)
+                                int.Parse(sr.ReadLine())
+                                );
+                        }
+                        break;
+                    case ServerAction.Ping:
+                        //TODO: egyéb ellenőrzés ping során?
+                        sw.WriteLine("OK");
+                        break;
+                    case ServerAction.ListRooms:
+                        //TODO: szobákat kilistázni
+                        throw new NotImplementedException();
+                    case ServerAction.Login:
+                        line = sr.ReadLine();
+                        //TODO: validálni!
+                        string ID = CreateUser(line, (IPAddress)param, int.Parse(sr.ReadLine()));
+                        sw.WriteLine("OK");
+                        sw.WriteLine(ID);
+                        break;
+                    case ServerAction.Logout:
+                        line = sr.ReadLine();
+                        RemoveUser(line);
+                        sw.WriteLine("OK");
+                        break;
+                    case ServerAction.CreateRoom:
+                        line = sr.ReadLine();
+                        string newroom = CreateRoom(line);
+                        sw.WriteLine("OK");
+                        sw.WriteLine(newroom);
+                        break;
+                    case ServerAction.LeaveRoom:
+                        line = sr.ReadLine();
+                        LeaveRoom(line);
+                        sw.WriteLine("OK");
+                        break;
+                    case ServerAction.JoinRoom:
+                        line = sr.ReadLine();
+                        JoinRoom(line, sr.ReadLine());
+                        sw.WriteLine("OK");
+                        break;
+                    case ServerAction.InviteUser:
+                        //nem része az alapnak
+                        throw new NotSupportedException();
+                    default:
+                        break;
+                }
             }
+
+
         }
 
-        public void MessageUser(string userID, ServerAction action, string message) { }
+        // public void MessageUser(string userID, ServerAction action, string message) { }
 
         //different kinds of actions
         /// <summary>
@@ -90,35 +139,106 @@ namespace zsirozas
         /// </summary>
         public string CreateRoom(string userID)
         {
+            //TODO: validálni!
             var r = new Room();
             r.roomID = userID + "~" + (DateTime.Now.TimeOfDay.TotalSeconds).ToString();
             r.userList = new List<string>() { userID };
             RoomsByID.Add(r.roomID, r);
-            //TODO: egyéb teendők
+            Rooms.Add(r.roomID);
+            UsersByID[userID].roomID = r.roomID;
             return r.roomID;
         }
 
+        //TODO: ezt majd vissza hamisra
+        /// <summary>
+        /// If this is set, everyone on the server will belong to the same big room.
+        /// If you cant start a game with that many players, you might need some of them to log out.
+        /// </summary>
+        public bool bigRoom = true;
+
+        public string CreateUser(string nickname, IPAddress IP, int port)
+        {
+            var U = new User();
+
+            //making sure the userID is unique
+            U.userID = nickname + (DateTime.Now.TimeOfDay.Milliseconds).ToString();
+
+            //filling in the data
+            U.nickname = nickname;
+            UsersByID.Add(U.userID, U);
+            Users.Add(U.userID);
+            if (bigRoom)
+            {
+                JoinRoom(U.userID, Rooms[0]);
+            }
+
+            //estabilishing server-to-client link
+            U.msgConn = new TcpClient();
+            U.msgConn.Connect(IP, port);
+            U.messageStreamW = new StreamWriter(U.msgConn.GetStream());
 
+            return U.userID;
+        }
+
+        public void RemoveUser(string userID)
+        {
+            LeaveRoom(userID);
+            UsersByID[userID].SendMessage("Logout");
+            UsersByID[userID].messageStreamW.Close();
+            UsersByID[userID].msgConn.Close();
+            UsersByID.Remove(userID);
+            Users.Remove(userID);
+        }
+        public void LeaveRoom(string userID)
+        {
+            if (UsersByID[userID].roomID != null)
+            {
+                //TODO: validálni ezt a mindent
+                RoomsByID[UsersByID[userID].roomID].userList.Remove(userID);
+            }
+        }
+        public void JoinRoom(string userID, string roomID)
+        {
+            if (UsersByID[userID].roomID == null)
+            {
+                if (Rooms.Contains(roomID))
+                {
+                    UsersByID[userID].roomID = roomID;
+                    RoomsByID[roomID].userList.Add(userID);
+                    //TODO: akarok-e erről üzenni?
+                }
+                else throw new NotImplementedException();
+            }
+            else throw new NotImplementedException();
+        }
+        public string NewGame(string roomID)
+        {
+            var G = new Game(this, RoomsByID[roomID].userList);
+            string gameID = "G~" + roomID;
+            GamesByID.Add(gameID, G);
+            Games.Add(gameID);
+            return gameID;
+            //TODO: üzenetsorrend hogy történik?
+        }
     }
 
     enum ServerAction
     {
-        GameAction, Ping, ListRooms, Login, Logout, CreateRoom, LeaveRoom, JoinRoom, InviteUser
+        GameAction, StartGame, Ping, ListRooms, Login, Logout, CreateRoom, LeaveRoom, JoinRoom, InviteUser
     }
 
-    struct User
+    class User
     {
-        public string userID;
         public string nickname;
-        public bool occupied;
-        public int failedPings;
-        public System.Net.Sockets.Socket socket;
-        public IPEndPoint endPoint;
-        public void SendMessage(string message) 
+        public string userID;
+        public string roomID;
+        public bool occupied = false;
+
+        public TcpClient msgConn;
+        public StreamWriter messageStreamW;
+        public void SendMessage(string message)
         {
-            var client = new TcpClient();
-            client.Connect(endPoint);
-            new StreamWriter(client.GetStream()).WriteLine(message);
+            messageStreamW.WriteLine(message);
         }
     }
 
-- 
GitLab