Example #1
0
        /// <summary>
        /// Write the specified byte buffer.
        /// </summary>
        public override void Write(byte[] buffer, int offset, int count)
        {
            if (_initialize)
            {
                Initialize(false);
            }

            _updated |= count > 0;

            // iterate while there are more bytes to write
            while (count > 0)
            {
                if (_section == null)
                {
                    SetSection(_sectionIndex);
                }

                // will the section be filled by the section?
                if (count > _sectionSize - _sectionPosition)
                {
                    // yes, fill the current section
                    var bytes = _sectionSize - _sectionPosition;
                    Micron.CopyMemory(buffer, offset, _section.Bytes, _sectionPosition, bytes);

                    offset += bytes;
                    count  -= bytes;

                    _section.Updated = true;
                    _section.Length += bytes;

                    // increment the section
                    NextSection();

                    // add the bytes count
                    AddByteCount(bytes);
                }
                else
                {
                    // no, copy the buffer bytes
                    Micron.CopyMemory(buffer, offset, _section.Bytes, _sectionPosition, count);

                    // increment the section position
                    _sectionPosition += count;
                    _section.Length  += count;
                    _section.Updated  = true;

                    AddByteCount(count);
                    count = 0;
                }
            }

            if (_position + _sectionPosition > _length)
            {
                _length = _position + _sectionPosition;
            }
        }
Example #2
0
 /// <summary>
 /// Save the section.
 /// </summary>
 protected void SaveSection(BlobSection section, int sectionIndex)
 {
     section.Updated = false;
     if (section.Length != _sectionSize)
     {
         byte[] bytes = new byte[section.Length];
         Micron.CopyMemory(section.Bytes, bytes, section.Length);
         _blobs.BlobData.Set(Id, sectionIndex, bytes);
     }
     else
     {
         _blobs.BlobData.Set(Id, sectionIndex, section.Bytes);
     }
 }
Example #3
0
        /// <summary>
        /// Append the specified bytes to the next read.
        /// </summary>
        protected void Buffer(byte[] bytes, int offset, int length)
        {
            _buffer = true;

            // does the buffer have room for the specified bytes?
            if (length > _bufferTarget - _bufferIndex)
            {
                // no, resize the prepared byte array
                _bufferBytes = BufferCache.Get(_bufferTarget + length);
            }

            // copy the byte buffer into the prepared collection
            Micron.CopyMemory(bytes, offset, _bufferBytes, _bufferIndex, length);
            // increment the index
            _bufferIndex += length;
        }
Example #4
0
        /// <summary>
        /// On socket data being received.
        /// </summary>
        private unsafe void OnReceiveSocketData(IAsyncResult ar)
        {
            int count = 0;

            try {
                // end the receive
                count = Socket.EndReceiveFrom(ar, ref _receiveEndPoint);
            } catch (Exception ex) {
                // release the read lock
                _syncLock.ReleaseRead();

                ProcessError(ex);
                return;
            }

            if (count > 0)
            {
                // is the received buffer chunked?
                byte flag = _receiveBuffer[0];
                if (flag < 60 || flag >= 188)
                {
                    count -= ChunkHeaderSize;

                    int chunkId;
                    int chunkIndex;
                    int chunkCount;

                    // sanity check for correct number of bytes received
                    if (count < 0)
                    {
                        _syncLock.ReleaseRead();
                        ProcessError("Socket didn't receive enough data for chunked information.");
                        return;
                    }

                    // yes, read the chunk details
                    fixed(byte *intP = &_receiveBuffer[1])
                    {
                        chunkId = *(int *)intP;
                    }

                    fixed(byte *intP = &_receiveBuffer[5])
                    {
                        chunkIndex = *(int *)intP;
                    }

                    fixed(byte *intP = &_receiveBuffer[9])
                    {
                        chunkCount = *(int *)intP;
                    }

                    // sanity check for the chunk data being valid
                    if (chunkIndex >= chunkCount)
                    {
                        _syncLock.ReleaseRead();
                        ProcessError("Socket received invalid chunk index and count information.");
                        return;
                    }

                    // write
                    ChunkedGram chunkedGram;
                    if (_receivedChunks.TryGetValue(chunkId, out chunkedGram))
                    {
                        chunkedGram.Length += count;
                        chunkedGram.Chunks.Insert(Teple.New(count, _receiveBuffer), chunkIndex);

                        // have all chunks been added?
                        if (chunkedGram.Chunks.Count == chunkCount)
                        {
                            // yes, remove from the collection
                            _receivedChunks.Remove(chunkId);

                            // create a byte buffer for the entire message
                            byte[] result = new byte[chunkedGram.Length];
                            int    index  = 0;
                            foreach (var chunk in chunkedGram.Chunks)
                            {
                                int length = chunk.ArgA;
                                Micron.CopyMemory(chunk.ArgB, ChunkHeaderSize, result, index, length);
                                index += length;
                            }

                            // reference the endpoint from which the data was received
                            IPEndPoint endpoint = (IPEndPoint)_receiveEndPoint;

                            // run the callback
                            _onReceive.AddRun(ActionSet.New(OnReceive,
                                                            endpoint,
                                                            result,
                                                            chunkedGram.Length));
                        }
                        else
                        {
                            // no, create a new receive buffer
                            _receiveBuffer = BufferCache.Get();
                        }
                    }
                    else
                    {
                        chunkedGram = new ChunkedGram {
                            Chunks    = new ArrayRig <Teple <int, byte[]> >(chunkCount),
                            Timestamp = Time.Timestamp
                        };

                        _receivedChunks.Add(chunkId, chunkedGram);

                        chunkedGram.Chunks.Add(Teple.New(count, _receiveBuffer));
                        chunkedGram.Length += count;

                        // create a new receive buffer
                        _receiveBuffer = BufferCache.Get();
                    }
                }
                else
                {
                    // no, copy the received buffer
                    --count;
                    byte[] buffer = BufferCache.Get(count);
                    Micron.CopyMemory(_receiveBuffer, 1, buffer, 0, count);

                    // reference the endpoint from which the data was received
                    IPEndPoint endpoint = (IPEndPoint)_receiveEndPoint;

                    // run the callback
                    _onReceive.AddRun(ActionSet.New(OnReceive,
                                                    endpoint,
                                                    buffer,
                                                    count));
                }
            }

            if (_receivedChunks.Count > 0)
            {
                // check for any chunked data timeouts
                ArrayRig <int> toRemove = null;
                foreach (var chunkedGram in _receivedChunks)
                {
                    if (Time.Timestamp - chunkedGram.Value.Timestamp > ChunkedGramTimeout)
                    {
                        if (toRemove == null)
                        {
                            toRemove = new ArrayRig <int>();
                        }
                        toRemove.Add(chunkedGram.Key);
                    }
                }
                if (toRemove != null)
                {
                    foreach (var chunkId in toRemove)
                    {
                        ChunkedGram chunked;
                        if (_receivedChunks.TryGetValue(chunkId, out chunked))
                        {
                            _receivedChunks.Remove(chunkId);
                            chunked.Chunks.Dispose();
                        }
                    }
                }
            }

            // release the read lock
            _syncLock.ReleaseRead();

            // create the endpoint for receiving data
            _receiveEndPoint = new IPEndPoint(RemoteEndPoint.Address, RemoteEndPoint.Port);

            try {
                // start receiving again
                Socket.BeginReceiveFrom(_receiveBuffer, 0, Global.BufferSizeLocal, SocketFlags.None,
                                        ref _receiveEndPoint, OnReceiveSocketData, null);
            } catch (Exception ex) {
                ProcessError(ex);
                return;
            }
        }
Example #5
0
        /// <summary>
        /// Read and fill the byte buffer from the stream.
        /// </summary>
        public override int Read(byte[] buffer, int offset, int count)
        {
            if (_initialize)
            {
                Initialize(true);
            }

            int start = offset;

            // get the required sections
            while (count > 0)
            {
                if (_section == null)
                {
                    if (_sectionIndex == _sectionCount)
                    {
                        Log.Error(Position + "- Read Last " + (offset - start) + " bytes. Was hoping for " + count);
                        return(offset - start);
                    }

                    // load the required section
                    SetSection(_sectionIndex);

                    if (count >= _section.Length - _sectionPosition)
                    {
                        var copySize = _section.Length - _sectionPosition;
                        Micron.CopyMemory(_section.Bytes, _sectionPosition, buffer, offset, copySize);
                        count  -= copySize;
                        offset += copySize;

                        NextSection();
                    }
                    else
                    {
                        Micron.CopyMemory(_section.Bytes, _sectionPosition, buffer, offset, count);
                        offset           += count;
                        _sectionPosition += count;
                        count             = 0;
                    }
                }
                else
                {
                    // will the buffer be filled with the current section?
                    if (count >= _section.Length - _sectionPosition)
                    {
                        // no, copy bytes from the current section
                        int bufferSize = _section.Length - _sectionPosition;

                        Micron.CopyMemory(_section.Bytes, _sectionPosition, buffer, offset, bufferSize);

                        offset += bufferSize;
                        count  -= bufferSize;

                        // increment the section
                        NextSection();
                    }
                    else
                    {
                        // yes, copy bytes from the current section
                        Micron.CopyMemory(_section.Bytes, _sectionPosition, buffer, offset, count);

                        // increment the section position
                        _sectionPosition += count;
                        offset           += count;
                        count             = 0;
                        if (_sectionPosition > _length)
                        {
                            _length = _sectionPosition;
                        }
                    }
                }
            }

            // all required bytes were read
            return(offset - start);
        }
Example #6
0
        /// <summary>
        /// Read a single block of data, interpreting the bytes as a meaningful type.
        /// </summary>
        public virtual bool Read(byte[] bytes, int offset, int length)
        {
            // reset local buffers
            Reset();

            // are some required bytes being prepared?
            if (_buffer)
            {
                bool result = false;

                // iterate while the buffer requirement is filled by the new bytes
                while (_bufferIndex + length - offset >= _bufferTarget)
                {
                    // iterate while the prepared buffer contains enough bytes
                    while (_bufferCount - _bufferIndex > _bufferTarget)
                    {
                        // send the prepared bytes
                        int target = _bufferTarget;
                        result       |= Next(_bufferBytes, _bufferIndex, target);
                        _bufferIndex += target;
                    }

                    // any prepared bytes remaining?
                    if (_bufferCount > _bufferIndex)
                    {
                        // yes, copy the bytes to the start of the prepared array
                        Micron.CopyMemory(_bufferBytes, _bufferIndex, _bufferBytes, 0, _bufferCount - _bufferIndex);
                        // update the prepared count
                        _bufferCount -= _bufferIndex;
                        _bufferIndex  = 0;
                    }
                    else
                    {
                        // no, copy any new bytes to the start of the buffer
                        Micron.CopyMemory(bytes, offset, _bufferBytes, 0, length - offset);
                        // reset the buffer parameters
                        _bufferIndex = _bufferCount = 0;

                        break;
                    }

                    // append new bytes to the buffer
                    Micron.CopyMemory(bytes, offset, _bufferBytes, _bufferIndex, _bufferCapacity - _bufferIndex);
                    offset += _bufferCount - _bufferIndex;
                }

                // iterate new buffer
                while (length - offset > _bufferTarget)
                {
                    result |= Next(bytes, offset, _bufferTarget);
                    offset += _bufferTarget;
                }

                // copy the remaining new bytes to the buffer
                Micron.CopyMemory(bytes, offset, _bufferBytes, _bufferIndex, length);

                return(result);
            }

            // any bytes in the buffer?
            if (_bufferIndex < _bufferCount)
            {
                // yes, will the new bytes fit in the buffer?
                if (length > _bufferCapacity - _bufferCount)
                {
                    // no, resize the buffer
                    Array.Resize(ref _bufferBytes, _bufferCapacity + length);
                }

                // copy the new bytes into the buffer
                Micron.CopyMemory(bytes, offset, _bufferBytes, _bufferIndex, length);

                int index = _bufferIndex;
                _bufferIndex += _bufferCount;

                // read the buffer bytes
                return(Next(_bufferBytes, index, _bufferCount));
            }

            // read all bytes passed
            return(Next(bytes, offset, length));
        }