/// <summary>
        /// Reads the next block of data from the socket.
        /// </summary>
        private void ReadNextBlock()
        {
            Socket socket = null;

            // check if already closed.
            lock (m_socketLock)
            {
                if (m_socket == null)
                {
                    if (m_receiveBuffer != null)
                    {
                        m_bufferManager.ReturnBuffer(m_receiveBuffer, "ReadNextBlock");
                        m_receiveBuffer = null;
                    }

                    return;
                }

                socket = m_socket;

                // avoid stale ServiceException when socket is disconnected
                if (!socket.Connected)
                {
                    return;
                }
            }

            BufferManager.LockBuffer(m_receiveBuffer);

            ServiceResult        error = ServiceResult.Good;
            SocketAsyncEventArgs args  = new SocketAsyncEventArgs();

            try
            {
                args.SetBuffer(m_receiveBuffer, m_bytesReceived, m_bytesToReceive - m_bytesReceived);
                args.Completed += m_ReadComplete;
                if (!socket.ReceiveAsync(args))
                {
                    // I/O completed synchronously
                    if ((args.SocketError != SocketError.Success) || (args.BytesTransferred < (m_bytesToReceive - m_bytesReceived)))
                    {
                        throw ServiceResultException.Create(StatusCodes.BadTcpInternalError, args.SocketError.ToString());
                    }

                    args.Dispose();
                }
            }
            catch (ServiceResultException sre)
            {
                args.Dispose();
                BufferManager.UnlockBuffer(m_receiveBuffer);
                throw sre;
            }
            catch (Exception ex)
            {
                args.Dispose();
                BufferManager.UnlockBuffer(m_receiveBuffer);
                throw ServiceResultException.Create(StatusCodes.BadTcpInternalError, ex, "BeginReceive failed.");
            }
        }
Пример #2
0
        /// <summary>
        /// Reads the next block of data from the socket.
        /// </summary>
        private void ReadNextBlock()
        {
            Socket socket = null;

            // check if already closed.
            lock (m_socketLock) {
                if (m_socket == null)
                {
                    if (m_receiveBuffer != null)
                    {
                        m_bufferManager.ReturnBuffer(m_receiveBuffer, "ReadNextBlock");
                        m_receiveBuffer = null;
                    }

                    return;
                }

                socket = m_socket;
            }

            BufferManager.LockBuffer(m_receiveBuffer);

            try {
                socket.BeginReceive(
                    m_receiveBuffer,
                    m_bytesReceived,
                    m_bytesToReceive - m_bytesReceived,
                    SocketFlags.None,
                    m_ReadComplete,
                    null);
            } catch (Exception e) {
                BufferManager.UnlockBuffer(m_receiveBuffer);
                throw ServiceResultException.Create(StatusCodes.BadTcpInternalError, e, "BeginReceive failed.");
            }
        }
Пример #3
0
        /// <summary>
        /// Cancels all outstanding I/O operations.
        /// </summary>
        private void CancelOperations()
        {
            // cancel any outstanding write operations.
            WriteOperation operation = null;

            do
            {
                operation = null;

                lock (m_writeQueue) {
                    if (m_writeQueue.Count > 0)
                    {
                        operation = m_writeQueue.First.Value;
                        m_writeQueue.RemoveFirst();
                    }
                }

                if (operation != null)
                {
                    operation.Fault(StatusCodes.BadConnectionClosed);
                }
            } while (operation != null);

            // cancel any outstanding read operations.
            byte[] buffer = null;

            do
            {
                buffer = null;

                lock (m_readQueue) {
                    if (m_readQueue.Count > 0)
                    {
                        buffer = m_readQueue.First.Value.Array;
                        m_readQueue.RemoveFirst();

                        // check for graceful shutdown.
                        if (buffer != null)
                        {
                            BufferManager.UnlockBuffer(buffer);

#if TRACK_MEMORY
                            int cookie = BitConverter.ToInt32(buffer, 0);

                            if (cookie < 0)
                            {
                                Utils.Trace("BufferCookieError (CancelOperations): Cookie={0:X8}", cookie);
                            }
#endif
                        }
                    }
                }

                if (buffer != null)
                {
                    m_bufferManager.ReturnBuffer(buffer, "CancelOperations");
                }
            } while (buffer != null);
        }
Пример #4
0
        /// <summary>
        /// Removes the next message from the queue.
        /// </summary>
        private bool GetNextMessage(out ArraySegment <byte> messageChunk)
        {
            lock (m_readQueue)
            {
                // check if queue has been cleared.
                if (m_readQueue.Count == 0)
                {
                    messageChunk       = new ArraySegment <byte>();
                    m_readThreadActive = false;
                    return(false);
                }

                messageChunk = m_readQueue.First.Value;
                m_readQueue.RemoveFirst();

                // return message.
                if (messageChunk.Array != null)
                {
                    BufferManager.UnlockBuffer(messageChunk.Array);
                    m_readThreadActive = true;

                    #if TRACK_MEMORY
                    int cookie = BitConverter.ToInt32(messageChunk.Array, 0);

                    if (cookie < 0)
                    {
                        Utils.Trace("BufferCookieError (ReadQueuedMessages1): Cookie={0:X8}", cookie);
                    }
                    #endif

                    return(true);
                }

                m_readThreadActive = false;
            }

            // handle graceful shutdown.
            if (m_sink != null)
            {
                try
                {
                    m_sink.OnReceiveError(this, StatusCodes.BadSecureChannelClosed);
                }
                catch (Exception e)
                {
                    Utils.Trace(e, "Unexpected error invoking OnReceiveError callback.");
                }
            }

            return(false);
        }
Пример #5
0
        /// <summary>
        /// Handles a read complete event.
        /// </summary>
        private ServiceResult DoReadComplete(SocketAsyncEventArgs e)
        {
            // complete operation.
            int bytesRead = e.BytesTransferred;

            lock (m_socketLock)
            {
                BufferManager.UnlockBuffer(m_receiveBuffer);
            }

            Utils.TraceDebug("Bytes read: {0}", bytesRead);

            if (bytesRead == 0)
            {
                // Remote end has closed the connection

                // free the empty receive buffer.
                if (m_receiveBuffer != null)
                {
                    m_bufferManager.ReturnBuffer(m_receiveBuffer, "DoReadComplete");
                    m_receiveBuffer = null;
                }

                return(ServiceResult.Create(StatusCodes.BadConnectionClosed, "Remote side closed connection"));
            }

            m_bytesReceived += bytesRead;

            // check if more data left to read.
            if (m_bytesReceived < m_bytesToReceive)
            {
                ReadNextBlock();

                return(ServiceResult.Good);
            }

            // start reading the message body.
            if (m_incomingMessageSize < 0)
            {
                m_incomingMessageSize = BitConverter.ToInt32(m_receiveBuffer, 4);

                if (m_incomingMessageSize <= 0 || m_incomingMessageSize > m_receiveBufferSize)
                {
                    Utils.Trace(
                        "BadTcpMessageTooLarge: BufferSize={0}; MessageSize={1}",
                        m_receiveBufferSize,
                        m_incomingMessageSize);

                    return(ServiceResult.Create(
                               StatusCodes.BadTcpMessageTooLarge,
                               "Messages size {1} bytes is too large for buffer of size {0}.",
                               m_receiveBufferSize,
                               m_incomingMessageSize));
                }

                // set up buffer for reading the message body.
                m_bytesToReceive = m_incomingMessageSize;

                ReadNextBlock();

                return(ServiceResult.Good);
            }

            // notify the sink.
            if (m_sink != null)
            {
                try
                {
                    // send notification (implementor responsible for freeing buffer) on success.
                    ArraySegment <byte> messageChunk = new ArraySegment <byte>(m_receiveBuffer, 0, m_incomingMessageSize);

                    // must allocate a new buffer for the next message.
                    m_receiveBuffer = null;

                    m_sink.OnMessageReceived(this, messageChunk);
                }
                catch (Exception ex)
                {
                    Utils.Trace(ex, "Unexpected error invoking OnMessageReceived callback.");
                }
            }

            // free the receive buffer.
            if (m_receiveBuffer != null)
            {
                m_bufferManager.ReturnBuffer(m_receiveBuffer, "DoReadComplete");
                m_receiveBuffer = null;
            }

            // start receiving next message.
            ReadNextMessage();

            return(ServiceResult.Good);
        }
Пример #6
0
        /// <summary>
        /// Reads the next block of data from the socket.
        /// </summary>
        private void ReadNextBlock()
        {
            Socket socket = null;

            // check if already closed.
            lock (m_socketLock)
            {
                if (m_socket == null)
                {
                    if (m_receiveBuffer != null)
                    {
                        m_bufferManager.ReturnBuffer(m_receiveBuffer, "ReadNextBlock");
                        m_receiveBuffer = null;
                    }
                    m_readState = ReadState.NotConnected;
                    return;
                }

                socket = m_socket;

                // avoid stale ServiceException when socket is disconnected
                if (!socket.Connected)
                {
                    m_readState = ReadState.NotConnected;
                    return;
                }
            }

            BufferManager.LockBuffer(m_receiveBuffer);

            var args = new SocketAsyncEventArgs();

            try
            {
                m_readState = ReadState.Receive;
                args.SetBuffer(m_receiveBuffer, m_bytesReceived, m_bytesToReceive - m_bytesReceived);
                args.Completed += m_readComplete;
                if (!socket.ReceiveAsync(args))
                {
                    // I/O completed synchronously
                    if (args.SocketError != SocketError.Success)
                    {
                        throw ServiceResultException.Create(StatusCodes.BadTcpInternalError, args.SocketError.ToString());
                    }
                    // set state to inner complete
                    m_readState = ReadState.ReadComplete;
                    m_readComplete(null, args);
                }
            }
            catch (ServiceResultException)
            {
                args?.Dispose();
                BufferManager.UnlockBuffer(m_receiveBuffer);
                throw;
            }
            catch (Exception ex)
            {
                args?.Dispose();
                BufferManager.UnlockBuffer(m_receiveBuffer);
                throw ServiceResultException.Create(StatusCodes.BadTcpInternalError, ex, "BeginReceive failed.");
            }
        }
Пример #7
0
        /// <summary>
        /// Handles a read complete event.
        /// </summary>
        private ServiceResult DoReadComplete(IAsyncResult result)
        {
            // complete operation.
            int bytesRead = 0;

            lock (m_socketLock) {
                try {
                    if (m_socket != null)
                    {
                        bytesRead = m_socket.EndReceive(result);
                        // Utils.Trace("EndReceive {0} bytes", bytesRead);
                    }

#if TRACK_MEMORY
                    int cookie = BitConverter.ToInt32(m_receiveBuffer, 0);

                    if (cookie < 0)
                    {
                        Utils.Trace("BufferCookieError (EndReceive): Cookie={0:X8}", cookie);
                    }
#endif
                } finally {
                    BufferManager.UnlockBuffer(m_receiveBuffer);
                }
            }

            if (bytesRead == 0)
            {
                // free the empty receive buffer.
                if (m_receiveBuffer != null)
                {
                    m_bufferManager.ReturnBuffer(m_receiveBuffer, "DoReadComplete");
                    m_receiveBuffer = null;
                }

                // put a null buffer to ensure that all queued messages are processed before close.
                lock (m_readQueue) {
                    m_readQueue.AddLast(new ArraySegment <byte>());

                    if (m_readQueue.Count == 1 && !m_readThreadActive)
                    {
                        ThreadPool.QueueUserWorkItem(ReadQueuedMessages, null);
                    }
                }

                return(ServiceResult.Good);
            }

            // Utils.Trace("Bytes read: {0}", bytesRead);

            m_bytesReceived += bytesRead;

            // check if more data left to read.
            if (m_bytesReceived < m_bytesToReceive)
            {
                ReadNextBlock();

#if TRACK_MEMORY
                int cookie = BitConverter.ToInt32(m_receiveBuffer, 0);

                if (cookie < 0)
                {
                    Utils.Trace("BufferCookieError (ReadNextBlock): Cookie={0:X8}", cookie);
                }
#endif

                return(ServiceResult.Good);
            }

            // start reading the message body.
            if (m_incomingMessageSize < 0)
            {
                m_incomingMessageSize = BitConverter.ToInt32(m_receiveBuffer, 4);

                if (m_incomingMessageSize <= 0 || m_incomingMessageSize > m_receiveBufferSize)
                {
                    Utils.Trace(
                        "BadTcpMessageTooLarge: BufferSize={0}; MessageSize={1}",
                        m_receiveBufferSize,
                        m_incomingMessageSize);

                    return(ServiceResult.Create(
                               StatusCodes.BadTcpMessageTooLarge,
                               "Messages size {1} bytes is too large for buffer of size {0}.",
                               m_receiveBufferSize,
                               m_incomingMessageSize));
                }

                // set up buffer for reading the message body.
                m_bytesToReceive = m_incomingMessageSize;

                ReadNextBlock();
                return(ServiceResult.Good);
            }

            // add message to queue.
            ArraySegment <byte> messageChunk = new ArraySegment <byte>(m_receiveBuffer, 0, m_incomingMessageSize);

            // must allocate a new buffer for the next message.
            m_receiveBuffer = null;

            lock (m_readQueue) {
#if TRACK_MEMORY
                int cookie = BitConverter.ToInt32(messageChunk.Array, 0);

                if (cookie < 0)
                {
                    Utils.Trace("BufferCookieError (DoReadComplete): Cookie={0:X8}", cookie);
                }
#endif

                BufferManager.LockBuffer(messageChunk.Array);
                m_readQueue.AddLast(messageChunk);

                if (m_readQueue.Count == 1 && !m_readThreadActive)
                {
                    ThreadPool.QueueUserWorkItem(ReadQueuedMessages, null);
                }
            }

            // start receiving next message.
            ReadNextMessage();
            return(ServiceResult.Good);
        }