public static void RegisterReceivers(GameSocket socket) { #region Login socket.registerRequestReceiver(new HandshakeReceiver(socket)); socket.registerRequestReceiver(new LoginAccountReceiver(socket)); socket.registerRequestReceiver(new GenerateAccountReceiver()); socket.registerRequestReceiver(new FetchDataReceiver(socket)); #endregion #region Resource socket.registerRequestReceiver(new GetResourceStatusReceiver(socket)); #endregion }
protected override void TestInternal() { var printer = new Printer(); #region Make Connection var listener = new TcpListener(IPAddress.Loopback, 8039); listener.Start(); var serverTask = listener.AcceptTcpClientAsync(); var clientTcp = new TcpClient(); var clientTask = clientTcp.ConnectAsync(IPAddress.Loopback, 8039); Console.WriteLine("Waiting for Connect..."); Task.WaitAll(serverTask, clientTask); Console.WriteLine("Connected! Wrapping with GameSocket"); var server = new GameSocket(); server.AttachNetworkStream(serverTask.GetAwaiter().GetResult().GetStream()); var client = new GameSocket(); client.AttachNetworkStream(clientTcp.GetStream()); Receivers.RegisterReceivers(server); server.SendPingAsync(); client.SendPingAsync(); WaitForFlag(() => { return(server.LastPongTime == -1); }, "서버가 클라이언트의 핑을 기다리는중... {0}"); WaitForFlag(() => { return(client.LastPongTime == -1); }, "클라이언트가 서버의 핑을 기다리는중... {0}"); Console.WriteLine("서로 핑을 주고 받았습니다!"); #endregion #region Alive Checker - No Response at all (half-open tcp connection) Console.WriteLine("Alive Checker - No Response at all (half-open tcp connection)"); var aliveCheckServerTask = listener.AcceptTcpClientAsync(); var aliveCheckClient = new TcpClient(); var aliveCheckClientTask = aliveCheckClient.ConnectAsync(IPAddress.Loopback, 8039); Task.WaitAll(aliveCheckClientTask, aliveCheckServerTask); var isClosed = false; var aliveCheckServerSocket = new GameSocket(); aliveCheckServerSocket.printHelper = printer; aliveCheckServerSocket.AttachNetworkStream(aliveCheckServerTask.GetAwaiter().GetResult().GetStream(), () => { isClosed = true; }); aliveCheckServerSocket.LastReceiveTime = DateTimeOffset.Now.ToUnixTimeMilliseconds() - 30000; Thread.Sleep(2000); aliveCheckServerSocket.LastReceiveTime = DateTimeOffset.Now.ToUnixTimeMilliseconds() - 60000; Thread.Sleep(2000); Assert(isClosed, true); aliveCheckClient.Close(); Console.WriteLine("Alive Checker - No Response at all (half-open tcp connection) is PASS"); #endregion #region Alive Checker - Client Closed Connection Console.WriteLine("Alive Checker - Client Closed Connection"); aliveCheckServerTask = listener.AcceptTcpClientAsync(); aliveCheckClient = new TcpClient(); aliveCheckClientTask = aliveCheckClient.ConnectAsync(IPAddress.Loopback, 8039); Task.WaitAll(aliveCheckClientTask, aliveCheckServerTask); isClosed = false; aliveCheckServerSocket = new GameSocket(); aliveCheckServerSocket.printHelper = printer; aliveCheckServerSocket.AttachNetworkStream(aliveCheckServerTask.GetAwaiter().GetResult().GetStream(), () => { isClosed = true; }); aliveCheckClient.Close(); aliveCheckServerSocket.LastReceiveTime = DateTimeOffset.Now.ToUnixTimeMilliseconds() - 30000; Thread.Sleep(2000); aliveCheckServerSocket.LastReceiveTime = DateTimeOffset.Now.ToUnixTimeMilliseconds() - 60000; Thread.Sleep(2000); Assert(isClosed, true); Console.WriteLine("Alive Checker - Client Closed Connection is PASS"); #endregion #region Handshake Console.WriteLine("암호화를 활성화 합니다"); var handshake = new HandshakePacket(); handshake.SendPacketAsync(client, null); WaitForFlag(() => { return(client.encryptHelper.UseAES); }, "연결의 암호화를 기다리는중... {0}"); var random = new Random(); server.registerRequestReceiver(new MessageReceiver()); server.registerRequestReceiver(new DevReceiver()); var messageFlag = new FlagReceiver(); var devFlag = new FlagReceiver(); var messageBuffer = new byte[1024 * 16]; random.NextBytes(messageBuffer); client.SendRequestAsync("message", messageBuffer, messageFlag); client.SendRequestAsync("dev", new byte[] { 0x0 }, devFlag); WaitForFlag(() => { return(messageFlag.IsReceived); }, "클라이언트가 랜덤 바이트 테스트의 응답을 기다리는중... {0}"); WaitForFlag(() => { return(devFlag.IsReceived); }, "클라이언트가 고정 메시지 테스트의 응답을 기다리는중... {0}"); Console.WriteLine("클라이언트가 응답을 수신함"); Assert(messageFlag.ReceivedData, messageBuffer); Assert(devFlag.ReceivedData, needMoreTime); Console.WriteLine("요청을 검증했습니다. 정상입니다."); #endregion #region Login Packet var authToken = new byte[128]; var rnd = new RNGCryptoServiceProvider(); rnd.GetBytes(authToken); string failMessage = null; Action throwIfFail = new Action(() => { if (failMessage != null) { throw new Exception(failMessage); } }); Account generatedAccount = null; var generateAccountPacket = new GenerateAccountPacket(); generateAccountPacket.SendPacketAsync(client, authToken, new FinishListener <Account>((account) => { generatedAccount = account; }, (message) => { failMessage = message; })); WaitForFlag(() => { return(generatedAccount != null || failMessage != null); }, "클라이언트가 서버의 계정 생성을 기다리는중... {0}"); throwIfFail(); var loginAccount = new LoginAccountPacket(); var badLoginPass = false; //Bad Token Test loginAccount.SendPacketAsync(client, generatedAccount.Id, new byte[128], new FinishListener(() => { failMessage = "클라이언트가 틀린 토큰으로 로그인을 성공했습니다"; }, (message) => { badLoginPass = true; })); WaitForFlag(() => { return(badLoginPass || failMessage != null); }, "클라이언트가 틀린 토큰으로 로그인 시도중... {0}"); throwIfFail(); var goodLoginPass = false; loginAccount.SendPacketAsync(client, generatedAccount.Id, authToken, new FinishListener(() => { goodLoginPass = true; }, (message) => { failMessage = message; })); WaitForFlag(() => { return(goodLoginPass || failMessage != null); }, "클라이언트가 정상 토큰으로 로그인 시도중... {0}"); throwIfFail(); var fetchDataPacket = new FetchDataPacket(); FetchData data = null; fetchDataPacket.SendPacketAsync(client, new FinishListener <FetchData>((fetchData) => { data = fetchData; }, (message) => { failMessage = message; })); WaitForFlag(() => { return(data != null || failMessage != null); }, "클라이언트가 시작에 필요한 정보를 가져오는중... {0}"); throwIfFail(); #endregion #region Resource Packet var resourcePacket = new GetResourceStatusPacket(); bool resourceReceived = false; resourcePacket.SendPacketAsync(client, new FinishListener <Resource>((resource) => { Console.WriteLine($"자원정보 수신함(Mo/Fo/El/Ti): {resource.Money}/{resource.Food}/{resource.Electric}/{resource.Time}"); resourceReceived = true; }, (message) => { failMessage = message; })); WaitForFlag(() => { return(resourceReceived || failMessage != null); }, "자원 정보를 서버로부터 받는중... {0}"); throwIfFail(); listener.Stop(); #endregion }