/// <summary>
        /// Network action for processing client direction commands.
        /// </summary>
        private void HandleClientCommands(SocketState state)
        {
            if (state.HasError)
            {
                HandleNetworkError(state);
                return;
            }

            // enumerate the complete received messages.
            IEnumerable <string> messages = GetTokens(state.GetStringBuilder());

            lock (world)
            {
                // process all of the commands now,
                //may have recieved more than one before refreshing screen
                foreach (string command in messages)
                {
                    world.UpdateShipCommands(command, state.GetID());
                    state.GetStringBuilder().Remove(0, command.Length);
                }
            }

            // ask client for data (continue loop)
            Network.GetData(state);
        }
        /// <summary>
        /// Takes a SocketState object, state, extracts the player ID and world
        /// size, updates the network action and waits for more data.
        /// </summary>
        private void ReceiveStartup(SocketState state)
        {
            if (state.HasError)
            {
                // report the error to the user
                // show error message
                string errorMessage = "An error occured trying to contact the server";
                errorMessage += "\nPlease try to connect again";
                ReportNetworkError(errorMessage);
                // get out of the call loop
                return;
            }

            // get the player ID and world size out of state.sb
            IEnumerable <string> tokens         = GetTokens(state.GetStringBuilder());
            List <string>        IDAndWorldSize = new List <string>();

            foreach (string token in tokens)
            {
                IDAndWorldSize.Add(token);

                // we only want two tokens
                if (IDAndWorldSize.Count >= 2)
                {
                    break;
                }
            }

            // see if we actually got out two tokens, should be world size and
            // player id, if we did, process them and change network action
            if (IDAndWorldSize.Count == 2)
            {
                // remove tokens from StringBuilder should be size of tokens
                int sizeOfTokensAndNewLines = IDAndWorldSize[0].Length + IDAndWorldSize[1].Length;
                state.GetStringBuilder().Remove(0, sizeOfTokensAndNewLines);

                // Update the action to take when network events happen
                state.SetNetworkAction(ProcessMessage);

                // create new world
                theWorld = new World();
                window.SetWorld(theWorld);


                // parse the id and worldsize and set them in our client
                GetWorldSizeAndID(IDAndWorldSize, out int ID, out int worldSize);
                //SetPlayerID(ID);
                SetWorldSize(worldSize);

                // now that we have a connection, we can start sending controls
                StartSendingControls(state.GetSocket());
            }

            // Start waiting for data
            Network.GetData(state);
        }
Example #3
0
        /// <summary>
        /// This method parses the HTTP request sent by the broswer, and serves the appropriate web page.
        /// </summary>
        /// <param name="state">The socket state representing the connection with the client</param>
        private static void ServeHttpRequest(SocketState state)
        {
            string request = state.GetStringBuilder().ToString();

            // Print it for debugging/examining
            Console.WriteLine("received http request: " + request);


            // If the browser requested the server stats
            if (request.Contains("GET /scores HTTP/1.1"))
            {
                string html = MakeHTMLforStats();
                Console.WriteLine(html);
                Network.SendAndClose(state.GetSocket(), httpOkHeader + MakeHTMLforStats());
            }


            // If the browser requested a player
            else if (request.StartsWith(@"GET /games?player="))
            {
                // maybe split?
                string playerName = GetRequestParameter(request);
                string html       = MakeHTMLforPlayer(playerName);
                if (html.Length == 0)
                {
                    Network.SendAndClose(state.GetSocket(), httpBadHeader + "<h2>the passed in player does not exist</h2>");
                }
                else
                {
                    Network.SendAndClose(state.GetSocket(), httpOkHeader + html);
                }
            }

            // If the browser requested a game
            else if (request.StartsWith(@"GET /games?player="))
            {
                string html = MakeHTMLforGame(GetRequestParameter(request));
                if (html.Length == 0)
                {
                    Network.SendAndClose(state.GetSocket(), httpBadHeader + "<h2>the passed in game ID does not exist</h2>");
                }
                else
                {
                    Network.SendAndClose(state.GetSocket(), httpOkHeader + html);
                }
            }

            // Otherwise, our very simple web server doesn't recognize any other URL
            else
            {
                Network.SendAndClose(state.GetSocket(), httpBadHeader + "<h2>page not found</h2>");
            }
        }
Example #4
0
        public void SocketState_ConstructorTest()
        {
            // create a socket using to pass to a SocketState object
            Network.MakeSocket("localhost", out Socket sock, out IPAddress address);

            try
            {
                SocketState state = new SocketState(sock, -1);

                //the state should not be reporting an error
                Assert.IsFalse(state.HasError);

                // there error messgae should be an empty string
                Assert.IsTrue(state.ErrorMessage == "");

                //the size of the buffer should be 1024
                byte[] buffer = state.GetMessageBuffer();

                Assert.AreEqual(1024, buffer.Length);

                // the message buffer should be filled with 0's
                byte zeroByte = 0x0;
                for (int i = 0; i < buffer.Length; i++)
                {
                    Assert.IsTrue(buffer[i] == zeroByte);
                }

                // growable string builder which represents the message sent by server
                // should not contain anything.
                StringBuilder sb = state.GetStringBuilder();
                Assert.IsTrue(sb.ToString() == "");
                Assert.AreEqual(0, sb.Length);

                // the socket returned by GetSocket should be the same instance as
                // passed to the constructor
                Assert.AreEqual(sock, state.GetSocket());

                // We have not set a network action, but it should still not be null
                // trying to invoke this action would be bad if it was null and cause
                // test to fail
                state.InvokeNetworkAction(state);

                // ID should be same as what it was set
                Assert.AreEqual(-1, state.GetID());
            }
            // make sure we close the socket when we are done testing our state
            finally
            {
                sock.Dispose();
            }
        }
Example #5
0
        public void SocketState_GetStringBuilder()
        {
            // create a socket using to pass to a SocketState object
            Network.MakeSocket("localhost", out Socket sock, out IPAddress address);

            try
            {
                SocketState state = new SocketState(sock, -1);

                // growable string builder which represents the message sent by server
                // should not contain anything.
                StringBuilder sb = state.GetStringBuilder();
                Assert.IsTrue(sb.ToString() == "");
                Assert.AreEqual(0, sb.Length);
            }
            // make sure we close the socket when we are done testing our state
            finally
            {
                sock.Dispose();
            }
        }
        /// <summary>
        /// This method acts as a NetworkAction delegate (see Networking.cs)
        /// When used as a NetworkAction, this method will be called whenever the Networking code
        /// has an event (ConnectedCallback or ReceiveCallback)
        /// </summary>
        private void ProcessMessage(SocketState state)
        {
            if (state.HasError)
            {
                // report the error to the user
                // show error message
                string errorMessage = "An error occured trying to contact the server";
                errorMessage += "\nPlease try to connect again";
                ReportNetworkError(errorMessage);

                // reset frame timer, so if reconnecting to server can cancel send events
                window.ResetFrameTimer();

                // get out of the call loop
                return;
            }

            IEnumerable <string> messages = GetTokens(state.GetStringBuilder());

            // Loop until we have processed all messages.
            // We may have received more than one.

            foreach (string message in messages)
            {
                JObject obj  = JObject.Parse(message);
                JToken  ship = obj["ship"];
                JToken  proj = obj["proj"];
                JToken  star = obj["star"];

                Ship       theShip = null;
                Projectile theProj = null;
                Star       theStar = null;

                if (ship != null)
                {
                    theShip = JsonConvert.DeserializeObject <Ship>(message);
                }
                if (proj != null)
                {
                    theProj = JsonConvert.DeserializeObject <Projectile>(message);
                }
                if (star != null)
                {
                    theStar = JsonConvert.DeserializeObject <Star>(message);
                }

                // lock the following code so that only one thread changes the world at a time
                lock (theWorld)
                {
                    theWorld.AddStar(theStar);
                    theWorld.AddShip(theShip);
                    theWorld.AddProjectile(theProj);
                }

                // Then remove the processed message from the SocketState's growable buffer
                state.GetStringBuilder().Remove(0, message.Length);
            }

            // Now ask for more data. This will start an event loop.
            Network.GetData(state);
        }
        /// <summary>
        /// NetworkAction delegate which implements the server's part of the
        /// initial handshake.
        ///
        /// Creates a new Ship with the given name and a new unique ID and sets
        /// the SocketState's ID.
        ///
        /// Changes the state's callback method to one that handles command
        /// requests from the client then asks the clients for data.
        /// </summary>
        private void ReceivePlayerName(SocketState state)
        {
            // enumerate the complete received messages.
            IEnumerable <string> messages = GetTokens(state.GetStringBuilder());
            // find the name in the complete messages
            string playerName = "";

            if (messages.Any())
            {
                playerName = messages.First();
                state.GetStringBuilder().Clear();
            }
            // if there wasn't a complete message continue the event loop
            else
            {
                Network.GetData(state);
                return;
            }

            // the id and world are being changed by callback methods (different threads)
            int playerID = 0;

            lock (world)
            {
                playerID = IDCounter++;
                // make a ship with a the name and give it a unique id
                // add ship to world
                world.MakeNewShip(playerName.TrimEnd(), playerID);
                // set the socket state ID
                state.SetID(playerID);
            }

            if (state.HasError)
            {
                HandleNetworkError(state);
                return;
            }


            // change the callback to handle incoming commands from the client
            state.SetNetworkAction(HandleClientCommands);

            // send the startup info to the client (ID and world size)
            string startupInfo = playerID + "\n" + world.GetSize() + "\n";

            Network.Send(state.GetSocket(), startupInfo);

            // set FirstPlayerHasJoined to true if this is the first player and
            // get the start time
            if (!FirstPlayerHasJoined)
            {
                FirstPlayerHasJoined = true;
                // set the start time to now (current value will be server start time)
                startTime = DateTime.UtcNow;
            }

            // handshake is done print line that someone has connected
            Console.Out.WriteLine("A new Client has contacted the Server.");

            // add the client's socket to a set of all clients
            lock (clients)
            {
                clients.Add(state);
            }

            // ask the client for data (continue loop)
            Network.GetData(state);
        }