Esempio n. 1
0
        internal void SendPartialPacket(PartialPacket p)
        {
            byte[] type       = { (byte)p.Type };
            byte[] hasId      = { p.HasId ? (byte)1 : (byte)0 };
            byte[] isbuffered = { 1 };
            byte[] length     = BitConverter.GetBytes(p.Data.Length);

            byte[] posBytes         = BitConverter.GetBytes(p.Position);
            byte[] isEndBytes       = p.IsEnd ? new byte[] { 1 } : new byte[] { 0 };
            byte[] totalLengthBytes = BitConverter.GetBytes(p.TotalDataSize);

            byte[] arrData = p.Data;

            byte[] b;
            if (p.HasId)
            {
                b = ByteArrayHelpers.Combine(type, hasId, p.Id, isbuffered, length, posBytes, isEndBytes, totalLengthBytes, arrData);
            }
            else
            {
                b = ByteArrayHelpers.Combine(type, hasId, isbuffered, length, posBytes, isEndBytes, totalLengthBytes, arrData);
            }

            _stream.Write(b, 0, b.Length);
        }
Esempio n. 2
0
        internal List <PartialPacket> PayloadToPartials(int msgType, byte[] arrayToSplit, int chunckSize)
        {
            List <PartialPacket> splitted = new List <PartialPacket>();

            int sourceArrayLength = arrayToSplit.Length;
            int wholePacketCount  = sourceArrayLength / chunckSize;
            int lastPacketSize    = sourceArrayLength % chunckSize;

            if (wholePacketCount == 0 && lastPacketSize <= 0)
            {
                return(null);
            }

            for (int i = 0; i < wholePacketCount; i++)
            {
                byte[] slice = new byte[chunckSize];
                Array.Copy(arrayToSplit, i * chunckSize, slice, 0, MaxOutboundPacketSize);

                var partial = new PartialPacket {
                    Type = msgType, Position = i, TotalDataSize = sourceArrayLength, Data = slice
                };

                splitted.Add(partial);
            }

            if (lastPacketSize != 0)
            {
                byte[] slice = new byte[lastPacketSize];
                Array.Copy(arrayToSplit, wholePacketCount * chunckSize, slice, 0, lastPacketSize);

                var partial = new PartialPacket {
                    Type = msgType, Position = wholePacketCount, TotalDataSize = sourceArrayLength, Data = slice
                };

                // Set last packet flag to this packet
                partial.IsEnd = true;

                splitted.Add(partial);
            }
            else
            {
                splitted.Last().IsEnd = true;
            }

            return(splitted);
        }
Esempio n. 3
0
        private async Task <PartialPacket> ReadPartialPacket(int dataLength)
        {
            PartialPacket partialPacket = new PartialPacket();

            partialPacket.Position = await ReadInt();

            partialPacket.IsEnd = await ReadBoolean();

            partialPacket.TotalDataSize = await ReadInt();

            // Read the data
            byte[] packetData = await ReadBytesAsync(dataLength);

            partialPacket.Data = packetData;

            return(partialPacket);
        }
Esempio n. 4
0
        /// <summary>
        /// Reads the bytes from the stream.
        /// </summary>
        private async Task Read()
        {
            try
            {
                while (true)
                {
                    // Read type
                    int type = await ReadByte();

                    // Read if the message is associated with an id
                    bool hasId = await ReadBoolean();

                    byte[] id = null;
                    if (hasId)
                    {
                        // The Id is a 128-bit guid
                        id = await ReadBytesAsync(IdLength);
                    }

                    // Is this a partial reception ?
                    bool isBuffered = await ReadBoolean();

                    // Read the size of the data
                    int length = await ReadInt();

                    if (isBuffered)
                    {
                        // If it's a partial packet read the packet info
                        PartialPacket partialPacket = await ReadPartialPacket(length);

                        // todo property control

                        if (!partialPacket.IsEnd)
                        {
                            _partialPacketBuffer.Add(partialPacket);

                            if (_partialPacketBuffer.Count == 0)
                            {
                                _logger.Trace($"Received first packet: {partialPacket.Type}, total size: {partialPacket.TotalDataSize}.");
                            }
                        }
                        else
                        {
                            // This is the last packet
                            // Concat all data

                            _partialPacketBuffer.Add(partialPacket);

                            byte[] allData =
                                ByteArrayHelpers.Combine(_partialPacketBuffer.Select(pp => pp.Data).ToArray());

                            _logger.Trace($"Received last packet: {_partialPacketBuffer.Count}, total length: {allData.Length}.");

                            // Clear the buffer for the next partial to receive
                            _partialPacketBuffer.Clear();

                            Message message;
                            if (hasId)
                            {
                                message = new Message {
                                    Type = type, HasId = true, Id = id, Length = allData.Length, Payload = allData
                                };
                            }
                            else
                            {
                                message = new Message {
                                    Type = type, HasId = false, Length = allData.Length, Payload = allData
                                };
                            }

                            FireMessageReceivedEvent(message);
                        }
                    }
                    else
                    {
                        // If it's not a partial packet the next "length" bytes should be
                        // the entire data

                        byte[] packetData = await ReadBytesAsync(length);

                        Message message;
                        if (hasId)
                        {
                            message = new Message {
                                Type = type, HasId = true, Id = id, Length = length, Payload = packetData
                            };
                        }
                        else
                        {
                            message = new Message {
                                Type = type, HasId = false, Length = length, Payload = packetData
                            };
                        }

                        FireMessageReceivedEvent(message);
                    }
                }
            }
            catch (PeerDisconnectedException)
            {
                StreamClosed?.Invoke(this, EventArgs.Empty);
                Close();
            }
            catch (Exception e)
            {
                if (!IsConnected && e is IOException)
                {
                    // If the stream fails while the connection is logically closed (call to Close())
                    // we simply return - the StreamClosed event will no be closed.
                    return;
                }

                Close();
                StreamClosed?.Invoke(this, EventArgs.Empty);
            }
        }