Exemple #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;
            }
        }
Exemple #2
0
        protected MemBlock DecodeAndClear(uint crc32, int id, ushort total)
        {
            ICopyable[] blocks        = new ICopyable[total];
            bool        missing_block = false;
            ushort      last_idx      = (ushort)(total - 1);

            for (ushort i = 0; i < last_idx; i++)
            {
                var key        = new Triple <uint, int, ushort>(crc32, id, i);
                var this_block = (MemBlock)_fragments.Remove(key);
                if (null != this_block)
                {
                    blocks[i] = this_block;
                }
                else
                {
                    //We are missing one:
                    missing_block = true;
                    break;
                }
            }
            //Get the last one:
            ushort last_id    = (ushort)(last_idx ^ FragmentingSender.LAST_BLOCK_FLAG);
            var    lastkey    = new Triple <uint, int, ushort>(crc32, id, last_id);
            var    last_block = (MemBlock)_fragments.Remove(lastkey);

            blocks[last_idx] = last_block;

            missing_block = missing_block || (null == last_block);

            MemBlock result = null;

            if (false == missing_block)
            {
                result = MemBlock.Concat(blocks);
                uint crc32_ck = result.Read <uint>(Crc32.ComputeChecksum);
                if (crc32_ck != crc32)
                {
                    //Something went wrong:
                    result = null;
                }
            }
            _frag_count.Remove(new Pair <uint, int>(crc32, id));
            return(result);
        }