Example #1
0
        public static async Task Main(string[] args)
        {
            // Get the IP address to bind to as a command line arguement or default
            // to 127.0.0.1.
            var userSuppliedIp = args.Length < 1 ? "127.0.0.1" : args[0];

            // Require the IP address be supplied as a command line argument.
            var localIp       = IPAddress.Parse(userSuppliedIp);
            var localEndPoint = new IPEndPoint(localIp, BspConstants.DefaultPort);

            // Begin listening for clients attempting to discover the server IP
            _ = StartUdpListing(localEndPoint);

            // Create objects used for every connection.
            var generalLogger = new Logger(Console.Out);
            var unparser      = new MessageUnparser();
            var listener      = new BspListener(generalLogger);
            var gameTypeRepo  = CreateGameTypeRepository();
            var userRepo      = CreateUserRepository();
            var matchMaker    = new MatchMaker();

            // The body of this foreach loop is a callback. This body will run for
            // connection our listener accepts. Here we create objects specific for
            // each connection.
            await foreach (var socket in listener.StartListeningAsync(localEndPoint))
            {
                // Create a logger that will log with the client's EndPoint.
                var logger = new EndPointLogger(Console.Out, socket.RemoteEndPoint);

                // Create a disconnecter that can clean up a connection.
                var disconnecter = new ServerDisconnecter(logger, socket, userRepo, matchMaker);

                // Create a sender for sending messages to the client.
                var senderHandler = new MultiMessageHandler();
                var sender        = new BspSender(socket, logger, unparser, senderHandler);

                // Create a container for this connections state.
                var container = new ServerNetworkStateContainer(sender, disconnecter, gameTypeRepo,
                                                                userRepo, matchMaker);

                // Create a context for our state machine.
                var context = new NetworkStateContext(container, disconnecter);

                // Register incoming messages with this context.
                senderHandler.AddHandler(LoggingMessageHandler.ForSending(logger));
                senderHandler.AddHandler(new SentMessageHandler(context));

                // Register outgoing messages with this context.
                var receiverHandler = new MultiMessageHandler();
                receiverHandler.AddHandler(LoggingMessageHandler.ForReceiving(logger));
                receiverHandler.AddHandler(new ReceiveMessageHandler(context));

                // Create a parser for this connection
                var parser = new MessageParser(receiverHandler, gameTypeRepo);

                // Begin asynchronously receiving messages
                var receiver = new BspReceiver(socket, disconnecter, parser, logger);
                _ = receiver.StartReceivingAsync();
            }
        }
Example #2
0
        public static async Task Main(string[] args)
        {
            // Create a logger
            var logger = new Logger(Console.Out);

            // If the user did not supply an IP or hostname, attempt to
            // discover a server on the same subnet.
            IPEndPoint endPoint;

            if (args.Length > 0)
            {
                if (IPAddress.TryParse(args[0], out var ip))
                {
                    endPoint = new IPEndPoint(ip, BspConstants.DefaultPort);
                }
                else
                {
                    // Maybe the user supplied a hostname not an IP
                    var addresses = Dns.GetHostAddresses(args[0]);

                    if (addresses.Length < 1)
                    {
                        Console.WriteLine("Could not find hostname.");
                        return;
                    }

                    endPoint = new IPEndPoint(addresses.Last(), BspConstants.DefaultPort);
                }
            }
            else
            {
                logger.LogInfo("Attempting to discover server end point...");
                endPoint = await DiscoverServerEndPoint(BspConstants.DefaultPort);
            }

            // Attempt to connect to the server.
            var unparser = new MessageUnparser();
            var socket   = new Socket(SocketType.Stream, ProtocolType.Tcp);

            try
            {
                logger.LogInfo($"Attempting to connect to {endPoint}");
                socket.Connect(endPoint);
            }
            catch (SocketException)
            {
                logger.LogError($"Failed to connect to {endPoint}");
            }

            // Create a disconnecter that can clean up a connection.
            var disconnecter = new ClientDisconnecter(logger, socket);

            // Create a sender for sending to the server.
            var senderHandler = new MultiMessageHandler();
            var sender        = new BspSender(socket, logger, unparser, senderHandler);

            // Create a prompter to handle user interaction.
            var prompter = new Prompter(sender);

            // Create a state machine
            var container = new ClientNetworkStateContainer(prompter);
            var context   = new NetworkStateContext(container, disconnecter);

            // Register sending messages with our state machine.
            senderHandler.AddHandler(LoggingMessageHandler.ForSending(logger));
            senderHandler.AddHandler(new SentMessageHandler(context));

            // Register receiving messages with our state machine.
            var receiverHandler = new MultiMessageHandler();

            receiverHandler.AddHandler(LoggingMessageHandler.ForReceiving(logger));
            receiverHandler.AddHandler(new ReceiveMessageHandler(context));

            // Create a parser for our connection with the server
            var parser   = new MessageParser(receiverHandler, new GameTypeRepository());
            var receiver = new BspReceiver(socket, disconnecter, parser, logger);

            // Begin receive messages and start the prompt.
            var receivingTask = receiver.StartReceivingAsync();

            prompter.PromptLogOn();
            await receivingTask;
        }