예제 #1
0
        /// <summary>
        /// Sends a <see cref="Packet"/> through this channel.
        /// </summary>
        /// <param name="packet">The packet to send through the channel.</param>
        /// <returns>Whether the send was successful or not.</returns>
        public void Send(Packet packet)
        {
            // Check if we are processing
            if (!this.IsRunning || packet == null)
            {
                return;
            }

            // Get a context for this send
            using (var context = ProcessingContext.Acquire(this, this.Encoding))
            {
                try
                {
                    // Encode the packet, then queue the buffer
                    var buffer = context.OnSend(packet);
                    if (buffer != null)
                    {
                        if (buffer.Length <= 0)
                        {
                            // We have to release the buffer since we are not going to send it and
                            // the packet was already compiled.
                            buffer.TryRelease();
                            return;
                        }

                        // We don't need to await here, since WriteAsync() will actually copy the buffer
                        // segment into a tail, we can dispose the thing straight away.
                        this.WriteAsync(buffer.AsSegment(), default(CancellationToken)).Forget();

                        // Release the buffer once we sent the thing
                        buffer.TryRelease();
                    }
                }

                /*catch (CapacityExceededException)
                 * {
                 *  Service.Logger.Log(LogLevel.Info, String.Format("{0} disconnected. Too much data pending.", this));
                 *  OnDispose(false);
                 *  return;
                 * }*/
#if DEBUG
                catch (Exception ex) { ex.Log(); return; }
#else
                catch (Exception) { return; }
#endif
            }
        }
예제 #2
0
        /// <summary>
        /// Primary loop which consumes socket input, parses it for protocol framing, and invokes the
        /// application delegate for as long as the socket is intended to remain open. The resulting
        /// Task from this loop is preserved in a field which is used when the server needs to drain
        /// and close all currently active connections.
        /// </summary>
        public async Task OnReceive()
        {
            try
            {
                while (!this.ProcessingStopping)
                {
                    // Update the expires timer
                    this.Expires     = Timer.Now + Timeout;
                    this._abortedCts = null;

                    // If _requestAbort is set, the connection has already been closed.
                    if (Volatile.Read(ref _requestAborted) != 0)
                    {
                        return;
                    }

                    // If we're disconnecting, do not process
                    if (this.State == ConnectionState.Disconnecting || this.State == ConnectionState.SocketClosed || this.Decoding == null)
                    {
                        return;
                    }

                    // Book a buffer
                    var incoming = this.DecodingSettings.BufferProvider.Reserve(Constants.ReceiveBufferSize);

                    // Read from the socket
                    incoming.Length = await this.SocketInput.ReadAsync(incoming.Array, incoming.Offset, incoming.Length);

                    // Process whatever we just read
                    using (var context = ProcessingContext.Acquire(this, this.Decoding))
                    {
                        // Forward to the receive
                        await context.OnReceive(incoming);
                    }
                }
            }
            catch (Exception ex)
            {
                // Dig out the inner exception
                if (ex.InnerException != null)
                {
                    ex = ex.InnerException;
                }

                // If the task was canceled, do not log
                if (ex is TaskCanceledException)
                {
                    return;
                }

                // Log everything else
                Service.Logger.Log(ex);
                //Service.Logger.Log(LogLevel.Warning, "Connection processing ended abnormally. Reason: " + ex.Message);
            }
            finally
            {
                try
                {
                    // Reset the task source
                    this._abortedCts = null;

                    // If _requestAborted is set, the connection has already been closed.
                    if (Volatile.Read(ref _requestAborted) == 0)
                    {
                        this.Close(CloseType.SocketShutdown);
                    }

                    // Also dispose
                    this.OnDispose();
                }
                catch (Exception ex)
                {
                    Service.Logger.Log(ex);
                    //Service.Logger.Log(LogLevel.Warning,  "Connection shutdown abnormally. Reason: " + ex.Message));
                }
            }
        }