Exemplo n.º 1
0
        public void Send(ICopyable data)
        {
            //We always use the fragmenting header to signal
            //to the receiving end that we support (and want)
            //fragmentation.
            MemBlock rest = data as MemBlock;

            if (null == rest)
            {
                rest = MemBlock.Copy(data);
            }
            int len = rest.Length;

            if (len > MAX_SEND_SIZE)
            {
                throw new SendException(true,
                                        System.String.Format("Packet too large: {0}, MaxSize = {1}", len,
                                                             MAX_SEND_SIZE));
            }
            uint crc32 = rest.Read <uint>(Crc32.ComputeChecksum);
            //Avoid a RNG operation for now, might need to reconsider
            //If we use RNG, we have to touch state, that has thread-safety issues
            int id = _wrapped_sender.GetHashCode() ^ rest.GetHashCode();

            byte[] header = new byte[HEADER_SIZE - 2];
            int    off    = FragPType.CopyTo(header, 0);

            NumberSerializer.WriteInt((int)crc32, header, off);
            NumberSerializer.WriteInt(id, header, off + 4);
            MemBlock header_mb = MemBlock.Reference(header);

            ushort block     = 0;
            int    blocksize = ComputeBlockSize(len);

            while (rest.Length > 0)
            {
                int      this_size  = System.Math.Min(blocksize, rest.Length);
                MemBlock this_block = rest.Slice(0, this_size);
                rest = rest.Slice(this_size);
                //Check to see if this is the last block:
                if (rest.Length == 0)
                {
                    block = (ushort)(block ^ (0x8000)); //Set the highest bit, this is last
                }
                byte[] block_b = new byte[2];
                NumberSerializer.WriteShort((short)block, block_b, 0);
                MemBlock block_mb = MemBlock.Reference(block_b);

                _wrapped_sender.Send(new CopyList(header_mb, block_mb, this_block));
                block += 1;
            }
        }