private void UpdateMtuLogic(int deltaTime) { if (_finishMtu) { return; } _mtuCheckTimer += deltaTime; if (_mtuCheckTimer < MtuCheckDelay) { return; } _mtuCheckTimer = 0; _mtuCheckAttempts++; if (_mtuCheckAttempts >= MaxMtuCheckAttempts) { _finishMtu = true; return; } lock (_mtuMutex) { if (_mtuIdx >= NetConstants.PossibleMtu.Length - 1) { return; } //Send increased packet int newMtu = NetConstants.PossibleMtu[_mtuIdx + 1]; var p = _packetPool.GetPacket(newMtu); p.Property = PacketProperty.MtuCheck; FastBitConverter.GetBytes(p.RawData, 1, newMtu); //place into start FastBitConverter.GetBytes(p.RawData, p.Size - 4, newMtu); //and end of packet //Must check result for MTU fix if (NetManager.SendRawAndRecycle(p, EndPoint) <= 0) { _finishMtu = true; } } }
internal void SendRawData(NetPacket packet) { //2 - merge byte + minimal packet size + datalen(ushort) if (_netManager.MergeEnabled && _mergePos + packet.Size + NetConstants.HeaderSize * 2 + 2 < _mtu) { FastBitConverter.GetBytes(_mergeData.RawData, _mergePos + NetConstants.HeaderSize, (ushort)packet.Size); Buffer.BlockCopy(packet.RawData, 0, _mergeData.RawData, _mergePos + NetConstants.HeaderSize + 2, packet.Size); _mergePos += packet.Size + 2; _mergeCount++; //DebugWriteForce("Merged: " + _mergePos + "/" + (_mtu - 2) + ", count: " + _mergeCount); return; } NetUtils.DebugWrite(ConsoleColor.DarkYellow, "[P]SendingPacket: " + packet.Property); _netManager.SendRaw(packet, _remoteEndPoint); #if STATS_ENABLED Statistics.PacketsSent++; Statistics.BytesSent += (ulong)packet.Size; #endif }
/// <summary> /// Force closes connection and stop all threads. /// </summary> public void Stop() { //Send disconnect packets lock (_peers) foreach (NetPeer netPeer in _peers.Values) { var disconnectPacket = NetPacket.CreateRawPacket(PacketProperty.Disconnect, 8); FastBitConverter.GetBytes(disconnectPacket, 1, netPeer.ConnectId); SendRaw(disconnectPacket, netPeer.EndPoint); } //Clear ClearPeers(); //Stop if (IsRunning) { _logicThread.Stop(); _socket.Close(); } }
public void TestDeterministicOutput() { var bitConverter = new FastBitConverter(); var keyGenerator = new KeyGenerator(bitConverter); var blockManipulator = new BlockManipulator(); var tea = new BlackTeaCryptoServiceProvider(blockManipulator, keyGenerator, bitConverter); var passwordBytes = new byte[16]; var dataBytes = new byte[16]; for (var i = 0; i < 10000; i++) { Guid.NewGuid().TryWriteBytes(passwordBytes); Guid.NewGuid().TryWriteBytes(dataBytes); var cipher = tea.EncryptRaw(dataBytes, passwordBytes); var plain = tea.DecryptRaw(cipher, passwordBytes); Assert.IsTrue(plain.SequenceEqual(dataBytes)); } }
internal bool Shutdown(byte[] data, int start, int length, bool force) { lock (_shutdownLock) { //trying to shutdown already disconnected if (_connectionState == ConnectionState.Disconnected || _connectionState == ConnectionState.ShutdownRequested) { return(false); } //don't send anything if (force) { _connectionState = ConnectionState.Disconnected; return(true); } //reset time for reconnect protection _timeSinceLastPacket = 0; //send shutdown packet _shutdownPacket = new NetPacket(PacketProperty.Disconnect, length); _shutdownPacket.ConnectionNumber = _connectNum; FastBitConverter.GetBytes(_shutdownPacket.RawData, 1, _connectTime); if (_shutdownPacket.Size >= _mtu) { //Drop additional data NetDebug.WriteError("[Peer] Disconnect additional data size more than MTU - 8!"); } else if (data != null && length > 0) { Buffer.BlockCopy(data, start, _shutdownPacket.RawData, 9, length); } _connectionState = ConnectionState.ShutdownRequested; NetDebug.Write("[Peer] Send disconnect"); NetManager.SendRaw(_shutdownPacket, EndPoint); return(true); } }
internal async Task RunAsync() { // 첫 접속 패킷을 보내자 NetPacket sendPacket = NetPool.PacketPool.Alloc(PacketProperty.ResponseConnection, 8); sendPacket.SessionIdForConnection = SessionId; FastBitConverter.GetBytes(sendPacket.RawData, 5, _connectId); SendRawAsync(sendPacket, DeliveryMethod.Tcp); _isPossibleUpdate = true; try { await ProcessPacketAsync(); } finally { _isPossibleUpdate = false; Close(); } }
private void DisconnectPeer( NetPeer peer, DisconnectReason reason, int socketErrorCode, bool sendDisconnectPacket, byte[] data, int start, int count) { if (sendDisconnectPacket) { if (count + 8 >= peer.Mtu) { //Drop additional data data = null; count = 0; NetUtils.DebugWriteError("Disconnect additional data size more than MTU - 8!"); } var disconnectPacket = NetPacket.CreateRawPacket(PacketProperty.Disconnect, 8 + count); FastBitConverter.GetBytes(disconnectPacket, 1, peer.ConnectId); if (data != null) { Buffer.BlockCopy(data, start, disconnectPacket, 9, count); } SendRaw(disconnectPacket, peer.EndPoint); } var netEvent = CreateEvent(NetEventType.Disconnect); netEvent.Peer = peer; netEvent.AdditionalData = socketErrorCode; netEvent.DisconnectReason = reason; EnqueueEvent(netEvent); lock (_peersToRemove) { _peersToRemove.Enqueue(peer.EndPoint); } }
/// <summary> /// Force closes connection and stop all threads. /// </summary> public void Stop() { //Send disconnect packets lock (_peers) { for (int i = 0; i < _peers.Count; i++) { var disconnectPacket = _netPacketPool.Get(PacketProperty.Disconnect, 8); FastBitConverter.GetBytes(disconnectPacket.RawData, 1, _peers[i].ConnectId); SendRawAndRecycle(disconnectPacket, _peers[i].EndPoint); } } //Clear ClearPeers(); //Stop if (IsRunning) { _logicThread.Stop(); _socket.Close(); } }
private void CloseConnection(bool force, DisconnectReason reason, int socketErrorCode) { lock (_connectionCloseLock) { //Nothing to do if (!IsRunning) { return; } //Send goodbye if (_peer != null && !force && _connected) { //Send disconnect data var disconnectPacket = NetPacket.CreateRawPacket(PacketProperty.Disconnect, 8); FastBitConverter.GetBytes(disconnectPacket, 1, _connectId); SendRaw(disconnectPacket, _peer.EndPoint); } //Close threads and socket close base.Stop(); //Clear data _peer = null; _connected = false; _connectTimer = 0; _connectAttempts = 0; SocketClearPeers(); //Send event to Listener var netEvent = CreateEvent(NetEventType.Disconnect); netEvent.DisconnectReason = reason; netEvent.AdditionalData = socketErrorCode; EnqueueEvent(netEvent); } }
//Process incoming packet internal void ProcessPacket(NetPacket packet) { //not initialized if (_connectionState == ConnectionState.Outgoing) { _packetPool.Recycle(packet); return; } if (packet.ConnectionNumber != _connectNum && packet.Property != PacketProperty.ShutdownOk) //without connectionNum { NetDebug.Write(NetLogLevel.Trace, "[RR]Old packet"); _packetPool.Recycle(packet); return; } _timeSinceLastPacket = 0; NetDebug.Write("[RR]PacketProperty: {0}", packet.Property); switch (packet.Property) { case PacketProperty.Merged: int pos = NetConstants.HeaderSize; while (pos < packet.Size) { ushort size = BitConverter.ToUInt16(packet.RawData, pos); pos += 2; NetPacket mergedPacket = _packetPool.GetPacket(size, false); if (!mergedPacket.FromBytes(packet.RawData, pos, size)) { _packetPool.Recycle(packet); break; } pos += size; ProcessPacket(mergedPacket); } break; //If we get ping, send pong case PacketProperty.Ping: if (NetUtils.RelativeSequenceNumber(packet.Sequence, _pongPacket.Sequence) > 0) { NetDebug.Write("[PP]Ping receive, send pong"); FastBitConverter.GetBytes(_pongPacket.RawData, 3, DateTime.UtcNow.Ticks); _pongPacket.Sequence = packet.Sequence; NetManager.SendRaw(_pongPacket, EndPoint); } _packetPool.Recycle(packet); break; //If we get pong, calculate ping time and rtt case PacketProperty.Pong: if (packet.Sequence == _pingPacket.Sequence) { _pingTimer.Stop(); int elapsedMs = (int)_pingTimer.ElapsedMilliseconds; _remoteDelta = BitConverter.ToInt64(packet.RawData, 3) + (elapsedMs * TimeSpan.TicksPerMillisecond) / 2 - DateTime.UtcNow.Ticks; UpdateRoundTripTime(elapsedMs); NetManager.ConnectionLatencyUpdated(this, elapsedMs / 2); NetDebug.Write("[PP]Ping: {0} - {1} - {2}", packet.Sequence, elapsedMs, _remoteDelta); } _packetPool.Recycle(packet); break; case PacketProperty.Ack: case PacketProperty.Channeled: if (packet.ChannelId > _channels.Length) { _packetPool.Recycle(packet); break; } var channel = _channels[packet.ChannelId] ?? (packet.Property == PacketProperty.Ack ? null : CreateChannel(packet.ChannelId)); if (channel != null) { if (!channel.ProcessPacket(packet)) { _packetPool.Recycle(packet); } } break; //Simple packet without acks case PacketProperty.Unreliable: AddIncomingPacket(packet); return; case PacketProperty.MtuCheck: case PacketProperty.MtuOk: ProcessMtuPacket(packet); break; case PacketProperty.ShutdownOk: if (_connectionState == ConnectionState.ShutdownRequested) { _connectionState = ConnectionState.Disconnected; } _packetPool.Recycle(packet); break; default: NetDebug.WriteError("Error! Unexpected packet type: " + packet.Property); break; } }
public void ProcessOutBoundPacket(IPEndPoint remoteEndPoint, ref byte[] data, ref int offset, ref int length) { int num = offset; Array.Copy(data, offset, data, offset + 5 + 16, length); offset += 21; bool flag = this.MatchesFilter(data, offset, length); PacketEncryptionLayer.EncryptionState encryptionState; bool flag2; if (!flag && this.TryGetEncryptionState(remoteEndPoint, out encryptionState, out flag2)) { object sendMutex = encryptionState.sendMutex; lock (sendMutex) { uint nextSentSequenceNum = encryptionState.GetNextSentSequenceNum(); FastBitConverter.GetBytes(data, offset + length, nextSentSequenceNum); PacketEncryptionLayer._tempHash = encryptionState.sendMac.ComputeHash(data, offset, length + 4); PacketEncryptionLayer.FastCopyMac(PacketEncryptionLayer._tempHash, 0, data, offset + length); length += 10; if (PacketEncryptionLayer._tempIV == null) { PacketEncryptionLayer._tempIV = new byte[16]; } PacketEncryptionLayer._random.GetBytes(PacketEncryptionLayer._tempIV); int num2 = (int)(PacketEncryptionLayer.GetRandomByte() % 64); int num3 = (length + num2 + 1) % 16; num2 -= num3; if (num2 < 0) { num2 += 16; } if (offset + length + num2 >= data.Length) { num2 -= 16; } for (int i = 0; i <= num2; i++) { data[offset + length + i] = (byte)num2; } length += num2 + 1; using (ICryptoTransform cryptoTransform = this._aes.CreateEncryptor(encryptionState.sendKey, PacketEncryptionLayer._tempIV)) { int num4 = num + 5 + 16; int num5; for (int j = length; j >= cryptoTransform.InputBlockSize; j -= num5) { int inputCount = cryptoTransform.CanTransformMultipleBlocks ? (j / cryptoTransform.InputBlockSize * cryptoTransform.InputBlockSize) : cryptoTransform.InputBlockSize; num5 = cryptoTransform.TransformBlock(data, offset, inputCount, data, num4); offset += num5; num4 += num5; } offset = num; length = num4 - num; } data[offset] = 1; FastBitConverter.GetBytes(data, offset + 1, nextSentSequenceNum); PacketEncryptionLayer.FastCopyBlock(PacketEncryptionLayer._tempIV, 0, data, offset + 5); } return; } if (this._filterUnencryptedTraffic && !flag) { length = 0; return; } offset--; length++; data[offset] = 0; }
public override void ProcessOutBoundPacket(ref IPEndPoint endPoint, ref byte[] data, ref int offset, ref int length) { FastBitConverter.GetBytes(data, length, CRC32C.Compute(data, offset, length)); length += CRC32C.ChecksumSize; }
/// <summary> /// Parses a compressed resource data file /// </summary> /// <param name="filename">resource data file name</param> /// <returns>a Dictionary indexed by the resource filename's hashcode</returns> public static Dictionary <ulong, ResourceDataEntry> Parse(string filename) { Dictionary <ulong, ResourceDataEntry> resourceData; // The data should be compressed, read the whole file into memory first and decompress it // Compressed with Oodle Kraken, level 4 var resourceDataFileBytes = File.ReadAllBytes(filename); var compressedData = new byte[resourceDataFileBytes.Length - 8]; Buffer.BlockCopy(resourceDataFileBytes, 8, compressedData, 0, compressedData.Length); long decompressedSize = FastBitConverter.ToInt64(resourceDataFileBytes, 0); var decompressedData = OodleWrapper.Decompress(compressedData, decompressedSize); // Parse the binary data now using (var memoryStream = new MemoryStream(decompressedData)) { using (var binaryReader = new BinaryReader(memoryStream, Encoding.Default, true)) { // Amount of entries ulong amount = binaryReader.ReadUInt64(); resourceData = new Dictionary <ulong, ResourceDataEntry>((int)amount); // Read each entry for (ulong i = 0; i < amount; i++) { ulong fileNameHash = binaryReader.ReadUInt64(); ulong streamDbHash = binaryReader.ReadUInt64(); byte version = binaryReader.ReadByte(); byte specialByte1 = binaryReader.ReadByte(); byte specialByte2 = binaryReader.ReadByte(); byte specialByte3 = binaryReader.ReadByte(); ushort typeNameLength = binaryReader.ReadUInt16(); string typeName = Encoding.Default.GetString(binaryReader.ReadBytes(typeNameLength)); ushort assetTypeLength = binaryReader.ReadUInt16(); string assetType = typeName; string assetName = string.Empty; if (assetTypeLength > 0) { assetType = Encoding.Default.GetString(binaryReader.ReadBytes(assetTypeLength)); ushort assetNameLength = binaryReader.ReadUInt16(); assetName = Encoding.Default.GetString(binaryReader.ReadBytes(assetNameLength)); } resourceData.Add(fileNameHash, new ResourceDataEntry() { StreamDbHash = streamDbHash, Version = version, SpecialByte1 = specialByte1, SpecialByte2 = specialByte2, SpecialByte3 = specialByte3, ResourceType = typeName, MapResourceName = assetName, MapResourceType = assetType }); } } } return(resourceData); }
private void SetUInt64BE(int offset, ulong value) { FastBitConverter.GetBytes(Bytes, offset, SwapEndianness(value)); }
private bool TryDecryptData(byte[] data, PacketEncryptionLayer.EncryptionState state, int startingOffset, ref int offset, ref int length) { object receiveMutex = state.receiveMutex; bool result; lock (receiveMutex) { uint num = BitConverter.ToUInt32(data, offset); offset += 4; length -= 4; if (!state.IsValidSequenceNum(num)) { result = false; } else { if (PacketEncryptionLayer._tempIV == null) { PacketEncryptionLayer._tempIV = new byte[16]; } if (PacketEncryptionLayer._tempHash == null) { PacketEncryptionLayer._tempHash = new byte[10]; } PacketEncryptionLayer.FastCopyBlock(data, offset, PacketEncryptionLayer._tempIV, 0); offset += PacketEncryptionLayer._tempIV.Length; length -= PacketEncryptionLayer._tempIV.Length; using (ICryptoTransform cryptoTransform = this._aes.CreateDecryptor(state.receiveKey, PacketEncryptionLayer._tempIV)) { int num2 = startingOffset; int num3; for (int i = length; i >= cryptoTransform.InputBlockSize; i -= num3) { int inputCount = cryptoTransform.CanTransformMultipleBlocks ? (i / cryptoTransform.InputBlockSize * cryptoTransform.InputBlockSize) : cryptoTransform.InputBlockSize; num3 = cryptoTransform.TransformBlock(data, offset, inputCount, data, num2); offset += num3; num2 += num3; } offset = startingOffset; length = num2 - offset; } int num4 = (int)data[offset + length - 1]; bool flag2 = true; if (num4 + 10 + 1 > length) { num4 = 0; flag2 = false; } length -= num4 + 10 + 1; PacketEncryptionLayer.FastCopyMac(data, offset + length, PacketEncryptionLayer._tempHash, 0); FastBitConverter.GetBytes(data, offset + length, num); byte[] array = state.receiveMac.ComputeHash(data, offset, length + 4); if (!flag2) { result = false; } else { for (int j = 0; j < 10; j++) { if (PacketEncryptionLayer._tempHash[j] != array[j]) { return(false); } } if (!state.PutSequenceNum(num)) { result = false; } else { result = true; } } } } return(result); }
/// <summary> /// Converts the map resources object to a byte array /// </summary> /// <returns>the map resources object as a byte array</returns> public byte[] ToByteArray() { using (var memoryStream = new MemoryStream()) { // Write magic memoryStream.Write(FastBitConverter.GetBytes(Magic), 0, 4); // Write layer count (big-endian) var layerCountBytes = FastBitConverter.GetBytes(Layers.Count, true); memoryStream.Write(layerCountBytes, 0, 4); // Write layers foreach (var layer in Layers) { var layerNameBytes = Encoding.UTF8.GetBytes(layer); memoryStream.Write(FastBitConverter.GetBytes(layerNameBytes.Length), 0, 4); memoryStream.Write(layerNameBytes, 0, layerNameBytes.Length); } // Write asset type count (big-endian) var assetTypeCountBytes = FastBitConverter.GetBytes((long)AssetTypes.Count, true); memoryStream.Write(assetTypeCountBytes, 0, 8); // Write asset types foreach (var assetType in AssetTypes) { var assetTypeBytes = Encoding.UTF8.GetBytes(assetType); memoryStream.Write(FastBitConverter.GetBytes(assetTypeBytes.Length), 0, 4); memoryStream.Write(assetTypeBytes, 0, assetTypeBytes.Length); } // Write asset count (big-endian) var assetCountBytes = FastBitConverter.GetBytes(Assets.Count, true); memoryStream.Write(assetCountBytes, 0, 4); // Write assets foreach (var asset in Assets) { var assetNameBytes = Encoding.UTF8.GetBytes(asset.Name); // Write asset type index (big-endian) var assetTypeIndexBytes = FastBitConverter.GetBytes(asset.AssetTypeIndex, true); memoryStream.Write(assetTypeIndexBytes, 0, 4); memoryStream.Write(FastBitConverter.GetBytes(assetNameBytes.Length), 0, 4); memoryStream.Write(assetNameBytes, 0, assetNameBytes.Length); // Write unknown data 1 memoryStream.Write(FastBitConverter.GetBytes(asset.UnknownData1), 0, 4); // Write the remaining unknown data (big-endian) var unknownData2Bytes = FastBitConverter.GetBytes(asset.UnknownData2, true); memoryStream.Write(unknownData2Bytes, 0, 4); var unknownData3Bytes = FastBitConverter.GetBytes(asset.UnknownData3, true); memoryStream.Write(unknownData3Bytes, 0, 8); var unknownData4Bytes = FastBitConverter.GetBytes(asset.UnknownData4, true); memoryStream.Write(unknownData4Bytes, 0, 8); } // Write map count (big-endian) var mapCountBytes = FastBitConverter.GetBytes(Maps.Count, true); memoryStream.Write(mapCountBytes, 0, 4); // Write maps foreach (var map in Maps) { var mapBytes = Encoding.UTF8.GetBytes(map); memoryStream.Write(FastBitConverter.GetBytes(mapBytes.Length), 0, 4); memoryStream.Write(mapBytes, 0, mapBytes.Length); } return(memoryStream.ToArray()); } }
/// <summary> /// Creates a MapResources object from a byte array /// </summary> /// <param name="rawData">raw map resources file data</param> /// <returns>the parsed MapResources object</returns> public static MapResourcesFile Parse(byte[] rawData) { MapResourcesFile mapResourcesFile = new MapResourcesFile(); using (var memoryStream = new MemoryStream(rawData)) { using (var binaryReader = new BinaryReader(memoryStream, Encoding.Default, true)) { // Read the magic mapResourcesFile.Magic = binaryReader.ReadInt32(); // Read layer count (big-endian) var layerCountBytes = binaryReader.ReadBytes(4); int layerCount = FastBitConverter.ToInt32(layerCountBytes, 0, true); // Read layers for (int i = 0; i < layerCount; i++) { int stringLength = binaryReader.ReadInt32(); mapResourcesFile.Layers.Add(Encoding.UTF8.GetString(binaryReader.ReadBytes(stringLength))); } // Read asset type count (big-endian) var assetTypeCountBytes = binaryReader.ReadBytes(8); long assetTypeCount = FastBitConverter.ToInt64(assetTypeCountBytes, 0, true); // Read asset types for (int i = 0; i < assetTypeCount; i++) { int stringLength = binaryReader.ReadInt32(); mapResourcesFile.AssetTypes.Add(Encoding.UTF8.GetString(binaryReader.ReadBytes(stringLength))); } // Read assets count (big-endian) var assetCountBytes = binaryReader.ReadBytes(4); int assetCount = FastBitConverter.ToInt32(assetCountBytes, 0, true); // Read assets for (int i = 0; i < assetCount; i++) { var mapAsset = new MapAsset(); var assetTypeIndexBytes = binaryReader.ReadBytes(4); mapAsset.AssetTypeIndex = FastBitConverter.ToInt32(assetTypeIndexBytes, 0, true); int stringLength = binaryReader.ReadInt32(); mapAsset.Name = Encoding.UTF8.GetString(binaryReader.ReadBytes(stringLength)); // Read unknown data mapAsset.UnknownData1 = binaryReader.ReadInt32(); // Read the remaining unknown data (big-endian) var unknownData2Bytes = binaryReader.ReadBytes(4); mapAsset.UnknownData2 = FastBitConverter.ToInt32(unknownData2Bytes, 0, true); var unknownData3Bytes = binaryReader.ReadBytes(8); mapAsset.UnknownData3 = FastBitConverter.ToInt64(unknownData3Bytes, 0, true); var unknownData4Bytes = binaryReader.ReadBytes(8); mapAsset.UnknownData4 = FastBitConverter.ToInt64(unknownData4Bytes, 0, true); mapResourcesFile.Assets.Add(mapAsset); } // Read map count (big-endian) var mapCountBytes = binaryReader.ReadBytes(4); int mapCount = FastBitConverter.ToInt32(mapCountBytes, 0, true); // Read asset types for (int i = 0; i < mapCount; i++) { int stringLength = binaryReader.ReadInt32(); mapResourcesFile.Maps.Add(Encoding.UTF8.GetString(binaryReader.ReadBytes(stringLength))); } } } return(mapResourcesFile); }