Beispiel #1
0
        /// <summary>
        /// Buffer processed data and send to the receive callback.
        /// </summary>
        private void ProcessReceivedData()
        {
            // get a buffer to dequeue into
            var buffer = BufferCache.Get();

            try {
                // dequeue a buffer from the pending received data
                int count = _receivedBuffer.TakeItem().Dequeue(buffer, 0, Global.BufferSizeLocal);
                _receivedBuffer.Release();
                if (count == 0)
                {
                    // allocate the buffer cache once more
                    BufferCache.Set(buffer);
                }
                else
                {
                    // remove
                    //Log.Debug(new string(System.Text.Encoding.UTF8.GetChars(buffer, 0, count)));

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

                    if (count == Global.BufferSizeLocal)
                    {
                        ManagerUpdate.Control.AddSingle(ProcessReceivedData);
                        return;
                    }
                }

                // no bytes to receive
                CompleteReceive();
            } catch (SocketException ex) {
                _readLock.Release();
                BufferCache.Set(buffer);
                if (ex.SocketErrorCode == SocketError.ConnectionReset)
                {
                    return;
                }
                ProcessError(ex);
            } catch (Exception ex) {
                _readLock.Release();
                BufferCache.Set(buffer);
                ProcessError(ex);
            }
        }
Beispiel #2
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;
            }
        }
Beispiel #3
0
 /// <summary>
 /// Internal addition of a metadata task when the task is ready to run.
 /// </summary>
 internal void Add(IAction metaTask)
 {
     _sequencer.AddRun(metaTask);
 }