/// <summary> /// Tries reading a single packet from this stream. To read multiple available /// packets, repeatedly call this method until it returns <c>null</c>. /// </summary> /// <returns> /// A read packet, if one was available. /// </returns> /// <exception cref="System.IO.IOException">If the underlying stream fails.</exception> public IReadablePacket Read() { using (var packet = _stream.Read()) { if (packet != null) { var compressed = packet.ReadBoolean(); var data = packet.ReadByteArray(); if (compressed) { data = SimpleCompression.Decompress(data); } return(new Packet(data, false)); } } return(null); }
/// <summary>Parse received data to check if it's a message we can handle, and parse it.</summary> /// <param name="message">the data to parse.</param> /// <returns> /// the data parsed from the message, or <c>null</c> on failure. /// </returns> private IReadablePacket ParseMessage(byte[] message) { // Check the header. if (IsHeaderValid(message)) { // Get message length plus compressed bit. var info = BitConverter.ToUInt32(message, _header.Length); var length = (int)(info & ~CompressedMask); var flag = (info & CompressedMask) > 0; // OK, get the decrypted packet. var data = Crypto.Decrypt(message, _header.Length + sizeof(uint), length); // Is this a compressed message? if (flag) { data = SimpleCompression.Decompress(data); } // Return result as a packet. return(new Packet(data, false)); } return(null); }
/// <summary> /// Loads this profile from disk. If loading fails this will default to a new profile with the fall-back character /// class. /// </summary> /// <exception cref="ArgumentException">Profile name is invalid.</exception> public void Load(string name) { if (InvalidCharPattern.IsMatch(name)) { throw new ArgumentException(@"Invalid profile name, contains invalid character.", "name"); } // Figure out the path, check if it's valid. Reset(); Name = name; var profilePath = GetFullProfilePath(); if (!File.Exists(profilePath)) { throw new ArgumentException(@"Invalid profile name, no such file.", "name"); } try { // Load the file contents, which are encrypted and compressed. var encrypted = File.ReadAllBytes(profilePath); var compressed = Crypto.Decrypt(encrypted); var plain = SimpleCompression.Decompress(compressed); // Now we have the plain data, handle it as a packet to read our // data from it. using (var packet = new Packet(plain, false)) { // Get file header. if (!CheckHeader(packet.ReadByteArray())) { Logger.Error("Failed loading profile, invalid header, using default."); return; } // Get the hash the data had when writing. var hash = packet.ReadInt32(); // Get the player class. var playerClass = (PlayerClassType)packet.ReadByte(); // And the actual data. var data = packet.ReadPacketizable <Packet>(); // Check if the hash matches. var hasher = new Hasher(); hasher.Write((byte)playerClass); if (data != null) { hasher.Write(data); } if (hasher.Value == hash) { // All is well, keep the data, drop our old data, if any. PlayerClass = playerClass; _data = data; } } } catch (Exception ex) { Logger.ErrorException("Failed loading profile, using default.", ex); } }