Exemplo n.º 1
0
        /// <summary>Used internally by the netcode to send unconnected messages.</summary>
        private async Task <int> SendAsync(PacketType type, IPEndPoint remote, IWritable message)
        {
            // Buffers allocated by the allocator
            byte[] compress = null;
            Writer writer   = null;

            try {
                // Write message
                writer = new Writer(Allocator, 5);
                message?.Write(writer);
                ArraySegment <byte> packet = new ArraySegment <byte>(writer.Buffer, 5, writer.Position - 5);

                // Create flags
                PacketFlags flags = PacketFlags.None;

                // Compress
                if (Config.Compression)
                {
                    int max = Compressor.MaxCompressedLength(packet.Count) + packet.Offset;
                    compress = Allocator.CreateMessage(max);
                    int len = Compressor.Compress(packet, compress, packet.Offset);
                    if (len <= 0)
                    {
                        throw new InvalidOperationException(string.Format(
                                                                "Compressing {0} bytes returned {1} bytes", packet.Count, len
                                                                ));
                    }
                    else if (len < packet.Count)
                    {
                        packet = new ArraySegment <byte>(compress, packet.Offset, len);
                        flags |= PacketFlags.Compressed;
                    }
                }

                // Write CRC32
                if (Config.CRC32)
                {
                    uint crc32 = CRC32.Compute(packet.Array, packet.Offset, packet.Count);
                    Serializer.Write32(packet.Array, packet.Offset - 4, crc32);
                    packet = new ArraySegment <byte>(packet.Array, packet.Offset - 4, packet.Count + 4);
                    flags |= PacketFlags.Verified;
                }

                // Write header
                packet.Array[packet.Offset - 1] = (byte)(((byte)type) | ((byte)flags));
                packet = new ArraySegment <byte>(packet.Array, packet.Offset - 1, packet.Count + 1);

                // Send
                return(await SendSocketAsync(remote, packet.Array, packet.Offset, packet.Count));
            } catch (Exception exception) {
                // Notify listener about the exception
                Listener.OnHostException(remote, exception);
                throw;
            } finally {
                // Return the allocated buffers back to the allocator
                writer?.Dispose();
                Allocator.ReturnMessage(ref compress);
            }
        }