public void UpdateGameConnections(Process process) { var update = _connections.Count < 2; var currentConnections = GetConnections(process); foreach (var connection in _connections) { if (!currentConnections.Contains(connection)) { // 기존 연결 끊겨 있음, 새로 해야함 update = true; MsgLog.Error("l-network-detected-connection-closing"); break; } } if (update) { var lobbyEndPoint = GetLobbyEndPoint(process); _connections = currentConnections.Where(x => !x.RemoteEndPoint.Equals(lobbyEndPoint)).ToList(); foreach (var connection in _connections) { MsgLog.Info("l-network-detected-connection", connection); } } }
public void StartCapture(Process process) { _pid = process.Id; Task.Factory.StartNew(() => { try { MsgLog.Info("l-network-starting"); if (IsRunning) { MsgLog.Error("l-network-error-already-started"); return; } UpdateGameConnections(process); if (_connections.Count < 2) { MsgLog.Error("l-network-error-no-connection"); return; } var localAddress = _connections[0].LocalEndPoint.Address; RegisterToFirewall(); _socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP); _socket.Bind(new IPEndPoint(localAddress, 0)); _socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.HeaderIncluded, true); _socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AcceptConnection, true); _socket.IOControl(IOControlCode.ReceiveAll, RcvAllIpLevel, null); _socket.ReceiveBufferSize = _recvBuffer.Length * 4; _socket.BeginReceive(_recvBuffer, 0, _recvBuffer.Length, 0, OnReceive, null); IsRunning = true; MsgLog.Success("l-network-started"); } catch (Exception ex) { MsgLog.Exception(ex, "l-network-error-starting"); } }); }
public void StopCapture() { try { if (!IsRunning) { MsgLog.Error("l-network-error-already-stopped"); return; } _socket.Close(); _connections.Clear(); MsgLog.Info("l-network-stopping"); } catch (Exception ex) { MsgLog.Exception(ex, "l-network-error-stopping"); } }
public static void Analyze(int pid, byte[] payload, ref MatchStatus state) { try { while (true) { if (payload.Length < 4) { break; } var type = BitConverter.ToUInt16(payload, 0); if (type == 0x0000 || type == 0x5252) { if (payload.Length < 28) { break; } var length = BitConverter.ToInt32(payload, 24); if (length <= 0 || payload.Length < length) { break; } using (var messages = new MemoryStream(payload.Length)) { using (var stream = new MemoryStream(payload, 0, length)) { stream.Seek(40, SeekOrigin.Begin); if (payload[33] == 0x00) { stream.CopyTo(messages); } else { stream.Seek(2, SeekOrigin.Current); // 닷넷 DeflateStream 버그 (앞 2바이트 넘겨야함) using (var z = new DeflateStream(stream, CompressionMode.Decompress)) z.CopyTo(messages); } } messages.Seek(0, SeekOrigin.Begin); var messageCount = BitConverter.ToUInt16(payload, 30); for (var i = 0; i < messageCount; i++) { try { var buffer = new byte[4]; var read = messages.Read(buffer, 0, 4); if (read < 4) { MsgLog.Error("l-analyze-error-length", read, i, messageCount); break; } var messageLength = BitConverter.ToInt32(buffer, 0); var message = new byte[messageLength]; messages.Seek(-4, SeekOrigin.Current); messages.Read(message, 0, messageLength); HandleMessage(pid, message, ref state); } catch (Exception ex) { MsgLog.Exception(ex, "l-analyze-error-general"); } } } if (length < payload.Length) { // 더 처리해야 할 패킷이 남아 있음 payload = payload.Skip(length).ToArray(); continue; } } else { // 앞쪽이 잘려서 오는 패킷 workaround // 잘린 패킷 1개는 버리고 바로 다음 패킷부터 찾기... // TODO: 버리는 패킷 없게 제대로 수정하기 for (var offset = 0; offset < payload.Length - 2; offset++) { var possibleType = BitConverter.ToUInt16(payload, offset); if (possibleType == 0x5252) { payload = payload.Skip(offset).ToArray(); Analyze(pid, payload, ref state); break; } } } break; } } catch (Exception ex) { MsgLog.Exception(ex, "l-analyze-error"); } }