public void Can_enter_Game_status_after_initial_sequence()
        {
            var inputStream = new TestPullStream(new List <byte[]>
            {
                FakePackets.InitialLoginSeed_Pre6060,
                FakePackets.InitialLoginRequest,
                FakePackets.ClientSpy,
                FakePackets.SelectServerRequest,
                FakePackets.LoginSeed,
                FakePackets.GameServerLoginRequest
            });

            var connection = new UltimaClientConnection(UltimaClientConnectionStatus.Initial);

            connection.ReceiveBatch(inputStream, inputStream.Length);
            inputStream.NextBatch();
            connection.ReceiveBatch(inputStream, inputStream.Length);
            inputStream.NextBatch();
            connection.ReceiveBatch(inputStream, inputStream.Length);
            inputStream.NextBatch();
            connection.ReceiveBatch(inputStream, inputStream.Length);
            inputStream.NextBatch();
            connection.ReceiveBatch(inputStream, inputStream.Length);
            inputStream.NextBatch();
            connection.ReceiveBatch(inputStream, inputStream.Length);

            connection.Status.Should().Be(UltimaClientConnectionStatus.Game);
        }
        Given_connection_in_Initial_status_When_receives_2_part_login_seed_second_part_appended_to_LoginRequest_Then_connection_enters_ServerLogin_status()
        {
            var inputStream = new TestPullStream(new List <byte[]> {
                new byte[] { 0xef },
                new byte[] { 0x01, 0x38, 0xa8, 0xc0 },
                new byte[]
                {
                    0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x01,

                    0x80, 0x42, 0x75, 0x74, 0x68, 0x72, 0x6F, 0x6D, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4A,
                    0x46, 0x6B, 0x72, 0x34, 0x33, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF
                },
            });

            int packetsReceived = 0;

            var connection = new UltimaClientConnection(UltimaClientConnectionStatus.Initial);

            connection.PacketReceived += (sender, packet) => packetsReceived++;

            connection.ReceiveBatch(inputStream, 1);
            inputStream.NextBatch();

            connection.ReceiveBatch(inputStream, 4);
            inputStream.NextBatch();

            connection.ReceiveBatch(inputStream, 78);
            inputStream.NextBatch();

            connection.Status.Should().Be(UltimaClientConnectionStatus.ServerLogin);
            packetsReceived.Should().Be(2);
        }
Exemplo n.º 3
0
        private static void ClientLoop(ILogger packetLogger)
        {
            var diagnosticProvider = new InfusionDiagnosticPushStreamProvider(Configuration, Console);

            serverDiagnosticPushStream =
                new CompositeDiagnosticPushStream(new ConsoleDiagnosticPushStream(packetLogger, "proxy -> server"),
                                                  new InfusionBinaryDiagnosticPushStream(DiagnosticStreamDirection.ClientToServer, diagnosticProvider.GetStream));
            serverDiagnosticPullStream = new ConsoleDiagnosticPullStream(packetLogger, "server -> proxy");

            serverConnection = new ServerConnection(ServerConnectionStatus.Initial, serverDiagnosticPullStream,
                                                    serverDiagnosticPushStream);
            serverConnection.PacketReceived += ServerConnectionOnPacketReceived;

            clientConnection = new UltimaClientConnection(UltimaClientConnectionStatus.Initial,
                                                          new ConsoleDiagnosticPullStream(packetLogger, "client -> proxy"),
                                                          new CompositeDiagnosticPushStream(new ConsoleDiagnosticPushStream(packetLogger, "proxy -> client"),
                                                                                            new InfusionBinaryDiagnosticPushStream(DiagnosticStreamDirection.ServerToClient, diagnosticProvider.GetStream)));
            clientConnection.PacketReceived += ClientConnectionOnPacketReceived;

            diagnosticProvider.ClientConnection = clientConnection;
            diagnosticProvider.ServerConnection = serverConnection;

            Task.Run(() => ServerLoop());

            try
            {
                while (true)
                {
                    var client = listener.AcceptTcpClient();
                    ClientStream = client.GetStream();

                    int receivedLength;
                    var receiveBuffer = new byte[65535];

                    while ((receivedLength = ClientStream.Read(receiveBuffer, 0, receiveBuffer.Length)) > 0)
                    {
                        var memoryStream = new MemoryStream(receiveBuffer, 0, receivedLength, false);

                        clientConnection.ReceiveBatch(new MemoryStreamToPullStreamAdapter(memoryStream));
                    }

                    Thread.Yield();
                }
            }
            catch (IOException ioex) when(ioex.InnerException is SocketException socex && socex.SocketErrorCode == SocketError.ConnectionReset)
            {
                Console.Error("Connection to client lost.");
                throw;
            }
            catch (Exception ex)
            {
                Console.Error(serverDiagnosticPullStream.Flush());
                Console.Error(ex.ToString());
                throw;
            }
            finally
            {
                diagnosticProvider.Dispose();
            }
        }
        public void Can_send_game_packet()
        {
            var packet            = FakePackets.Instantiate(FakePackets.EnableLockedClientFeatures);
            var expectedSentBytes = new byte[] { 0xB3, 0x32, 0x98, 0xDA };
            var connection        = new UltimaClientConnection(UltimaClientConnectionStatus.Game);
            var outputStream      = new TestMemoryStream();

            connection.Send(packet, outputStream);

            outputStream.ActualBytes.Should().BeEquivalentTo(expectedSentBytes);
        }
        public void Can_send_prelogin_packet()
        {
            var packet            = FakePackets.Instantiate(FakePackets.GameServerList);
            var expectedSentBytes = FakePackets.GameServerList;
            var connection        = new UltimaClientConnection(UltimaClientConnectionStatus.ServerLogin);
            var outputStream      = new TestMemoryStream();

            connection.Send(packet, outputStream);

            outputStream.ActualBytes.Should().BeEquivalentTo(expectedSentBytes);
        }
        public void Given_connection_in_GameLoign_status_When_receives_GameServerLoginRequest_Then_enters_Game_status()
        {
            var inputStream = new TestPullStream(new List <byte[]> {
                FakePackets.GameServerLoginRequest
            });

            var connection = new UltimaClientConnection(UltimaClientConnectionStatus.GameLogin);

            connection.ReceiveBatch(inputStream, inputStream.Length);

            connection.Status.Should().Be(UltimaClientConnectionStatus.Game);
        }
        Given_connection_in_PreGameLogin_status_When_receives_login_seed_Then_connection_enters_GameLogin_status()
        {
            var inpuStream = new TestPullStream(new List <byte[]> {
                FakePackets.LoginSeed
            });

            var connection = new UltimaClientConnection(UltimaClientConnectionStatus.PreGameLogin);

            connection.ReceiveBatch(inpuStream, inpuStream.Length);

            connection.Status.Should().Be(UltimaClientConnectionStatus.GameLogin);
        }
Exemplo n.º 8
0
        Given_connection_in_Initial_status_When_receives_login_seed_Then_connection_enters_ServerLogin_status()
        {
            var inputStream = new TestPullStream(new List <byte[]> {
                FakePackets.InitialLoginSeed_Pre6060
            });

            var connection = new UltimaClientConnection(UltimaClientConnectionStatus.Initial);

            connection.ReceiveBatch(inputStream, inputStream.Length);

            connection.Status.Should().Be(UltimaClientConnectionStatus.AfterInitialSeed);
        }
        Given_connection_in_ServerLogin_status_When_receives_SelectServerRequest_Then_enters_PreGameLogin_status()
        {
            var inputStream = new TestPullStream(new List <byte[]> {
                FakePackets.SelectServerRequest
            });

            var connection = new UltimaClientConnection(UltimaClientConnectionStatus.ServerLogin);

            connection.ReceiveBatch(inputStream);

            connection.Status.Should().Be(UltimaClientConnectionStatus.PreGameLogin);
        }
Exemplo n.º 10
0
        public void Can_write_diagnostic_info_about_sent_PreGameLogin_packet()
        {
            var packet           = FakePackets.Instantiate(FakePackets.ConnectToGameServer);
            var diagnosticStream = new TextDiagnosticPushStream();
            var connection       = new UltimaClientConnection(UltimaClientConnectionStatus.PreGameLogin, NullDiagnosticPullStream.Instance, diagnosticStream);
            var outputStream     = new TestMemoryStream();

            connection.Send(packet, outputStream);

            var output = diagnosticStream.Flush();

            output.Should().Contain("0x8C, 0x7F, 0x00, 0x00, 0x01, 0x0A, 0x21, 0x7F, 0x00, 0x00, 0x01");
        }
Exemplo n.º 11
0
        public void Can_write_diagnostic_info_about_send_Game_packet()
        {
            var packet           = FakePackets.Instantiate(FakePackets.EnableLockedClientFeatures);
            var diagnosticStream = new TextDiagnosticPushStream();
            var connection       = new UltimaClientConnection(UltimaClientConnectionStatus.Game, NullDiagnosticPullStream.Instance, diagnosticStream);
            var outputStream     = new TestMemoryStream();

            connection.Send(packet, outputStream);

            string output = diagnosticStream.Flush();

            output.Should().Contain("0xB9, 0x80, 0x1F")
            .And.Contain("0xB3, 0x32, 0x98, 0xDA");
        }
Exemplo n.º 12
0
        private void ClientLoop()
        {
            var listener = new TcpListener(new IPEndPoint(IPAddress.Any, 30000));

            listener.Start();

            while (true)
            {
                try
                {
                    transmitClientPackets = false;
                    clientConnection      = new UltimaClientConnection(UltimaClientConnectionStatus.Initial,
                                                                       new ConsoleDiagnosticPullStream(packetLogger, "client -> proxy", packetRegistry),
                                                                       new CompositeDiagnosticPushStream(new ConsoleDiagnosticPushStream(packetLogger, "proxy -> client", packetRegistry),
                                                                                                         new InfusionBinaryDiagnosticPushStream(DiagnosticStreamDirection.ServerToClient, diagnosticProvider.GetStream)), packetRegistry,
                                                                       EncryptionSetup.Autodetect, null);
                    clientConnection.PacketReceived += ClientConnectionOnPacketReceived;

                    console.Important("Listening for remote clients on port 30000");
                    PreGameClientLoop(listener);

                    console.Important("Remote client entered game");
                    GameClientLoop(listener);
                }
                catch (OperationCanceledException)
                {
                    throw;
                }
                catch (SocketException sex) when(sex.NativeErrorCode == 0x00002746)
                {
                    console.Important("Remote client disconnected");
                }
                catch (IOException ioex) when(ioex.InnerException is SocketException sex && sex.NativeErrorCode == 0x00002746)
                {
                    console.Important("Remote client disconnected");
                }
                catch (Exception ex)
                {
                    console.Error(ex.ToString());
                }
            }
        }
        public void Can_receive_two_consecutive_batches()
        {
            var inputStream = new TestPullStream(new List <byte[]>
            {
                FakePackets.InitialLoginSeed_Pre6060,
                FakePackets.InitialLoginRequest
            });

            var expectedPackets = new[]
            {
                new Packet(PacketDefinitions.LoginSeed.Id, FakePackets.InitialLoginSeed_Pre6060),
                new Packet(0x80, FakePackets.InitialLoginRequest)
            };

            var connection      = new UltimaClientConnection();
            var receivedPackets = new List <Packet>();

            connection.PacketReceived += (sender, packet) => receivedPackets.Add(packet);
            connection.ReceiveBatch(inputStream, inputStream.Length);
            inputStream.NextBatch();
            connection.ReceiveBatch(inputStream, inputStream.Length);

            expectedPackets.AreEqual(receivedPackets);
        }
        public void Can_receive_three_packets_in_one_batch()
        {
            var inputStream = new TestPullStream(new List <byte[]>
            {
                FakePackets.InitialLoginSeed_Pre6060
                .Concat(FakePackets.InitialLoginRequest)
                .Concat(FakePackets.SelectServerRequest).ToArray()
            });

            var expectedPackets = new[]
            {
                new Packet(PacketDefinitions.LoginSeed.Id, FakePackets.InitialLoginSeed_Pre6060),
                new Packet(0x80, FakePackets.InitialLoginRequest),
                new Packet(0xA0, FakePackets.SelectServerRequest)
            };

            var connection      = new UltimaClientConnection();
            var receivedPackets = new List <Packet>();

            connection.PacketReceived += (sender, packet) => receivedPackets.Add(packet);
            connection.ReceiveBatch(inputStream, inputStream.Length);

            expectedPackets.AreEqual(receivedPackets);
        }
        Given_connection_in_Initial_status_When_receives_3_part_login_seed_Then_connection_enters_ServerLogin_status()
        {
            var inputStream = new TestPullStream(new List <byte[]> {
                new byte[] { 0xef },
                new byte[] { 0x01, 0x38, 0xa8, 0xc0 },
                new byte[]
                {
                    0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x21, 0x00, 0x00, 0x00, 0x01,
                },
            });

            var connection = new UltimaClientConnection(UltimaClientConnectionStatus.Initial);

            connection.ReceiveBatch(inputStream, 1);
            inputStream.NextBatch();

            connection.ReceiveBatch(inputStream, 4);
            inputStream.NextBatch();

            connection.ReceiveBatch(inputStream, 16);

            connection.Status.Should().Be(UltimaClientConnectionStatus.AfterInitialSeed);
        }
Exemplo n.º 16
0
        private void ClientLoop(ILogger packetLogger)
        {
            var diagnosticProvider = new InfusionDiagnosticPushStreamProvider(LogConfig, Console);

            serverDiagnosticPushStream =
                new CompositeDiagnosticPushStream(new ConsoleDiagnosticPushStream(packetLogger, "proxy -> server", packetRegistry),
                                                  new InfusionBinaryDiagnosticPushStream(DiagnosticStreamDirection.ClientToServer, diagnosticProvider.GetStream));
            serverDiagnosticPullStream = new ConsoleDiagnosticPullStream(packetLogger, "server -> proxy", packetRegistry);

            serverConnection = new ServerConnection(ServerConnectionStatus.Initial, serverDiagnosticPullStream,
                                                    serverDiagnosticPushStream, packetRegistry, proxyStartConfig.Encryption);
            serverConnection.PacketReceived += ServerConnectionOnPacketReceived;

            clientConnection = new UltimaClientConnection(UltimaClientConnectionStatus.Initial,
                                                          new ConsoleDiagnosticPullStream(packetLogger, "client -> proxy", packetRegistry),
                                                          new CompositeDiagnosticPushStream(new ConsoleDiagnosticPushStream(packetLogger, "proxy -> client", packetRegistry),
                                                                                            new InfusionBinaryDiagnosticPushStream(DiagnosticStreamDirection.ServerToClient, diagnosticProvider.GetStream)), packetRegistry,
                                                          proxyStartConfig.Encryption, proxyStartConfig.LoginEncryptionKey);
            clientConnection.PacketReceived           += ClientConnectionOnPacketReceived;
            clientConnection.NewGameEncryptionStarted += ClientConnectionOnNewGameEncryptionStarted;
            clientConnection.LoginEncryptionStarted   += ClientConnectionOnLoginEncryptionStarted;

            diagnosticProvider.ClientConnection = clientConnection;
            diagnosticProvider.ServerConnection = serverConnection;
            bool serverLoopStarted = false;

            try
            {
                while (true)
                {
                    var client = listener.AcceptTcpClient();
                    ClientStream = client.GetStream();

                    lock (serverStreamLock)
                    {
                        if (ServerStream == null)
                        {
                            ServerStream = ConnectToServer();
                        }
                    }

                    if (!serverLoopStarted)
                    {
                        Task.Run(() => ServerLoop());
                        serverLoopStarted = true;
                    }

                    int receivedLength;
                    var receiveBuffer = new byte[65535];

                    while ((receivedLength = ClientStream.Read(receiveBuffer, 0, receiveBuffer.Length)) > 0)
                    {
#if DUMP_RAW
                        Console.Info("client -> proxy");
                        Console.Info(receiveBuffer.Take(receivedLength).Select(x => x.ToString("X2")).Aggregate((l, r) => l + " " + r));
#endif

                        var memoryStream = new MemoryStream(receiveBuffer, 0, receivedLength, false);
                        clientConnection.ReceiveBatch(new MemoryStreamToPullStreamAdapter(memoryStream), receivedLength);
                    }

                    lock (serverStreamLock)
                    {
                        DisconnectFromServer();
                        ServerStream = ConnectToServer();
                    }

                    Thread.Yield();
                }
            }
            catch (IOException ioex) when(ioex.InnerException is SocketException socex && socex.SocketErrorCode == SocketError.ConnectionReset)
            {
                Console.Error("Connection to client lost. Please restart infusion.");
                Console.Debug(socex.ToString());
            }
            catch (Exception ex)
            {
                Console.Error("Connection to client lost. Please restart infusion.");
                Console.Debug(serverDiagnosticPullStream.Flush());
                Console.Debug(ex.ToString());
                throw;
            }
            finally
            {
                diagnosticProvider.Dispose();
            }
        }