Пример #1
0
        /// <summary>
        /// Callback for the queued write.
        /// </summary>
        /// <param name="value"></param>
        /// <param name="error"></param>
        /// <param name="promise"></param>
        private void QueueWriteCallback(ChunkedBuffer buffer, Exception error, Promise <ChunkedBuffer> promise)
        {
            SendQueueState state = (SendQueueState)promise.State;

            try
            {
                SockNetLogger.Log(SockNetLogger.LogLevel.DEBUG, this, (stream is SslStream ? "[SSL] " : "") + "Sent data to [{0}].", RemoteEndpoint);

                // if the receive buffer was being sent don't close it
                if (buffer != chunkedBuffer)
                {
                    buffer.Close();
                }
            }
            catch (Exception e)
            {
                SockNetLogger.Log(SockNetLogger.LogLevel.ERROR, this, "Unable to close the given buffer", e);
            }
            finally
            {
                Interlocked.CompareExchange(ref sendState, 0, 1);

                try
                {
                    state.promise.CreateFulfiller().Fulfill(this);
                }
                finally
                {
                    NotifySendQueue();
                }
            }
        }
Пример #2
0
        /// <summary>
        /// A callback the gets invoked after SSL auth completes.
        /// </summary>
        /// <param name="result"></param>
        private void EnableServerSslCallback(IAsyncResult result)
        {
            canRead = true;

            SslStream sslStream = (SslStream)result.AsyncState;

            sslStream.EndAuthenticateAsServer(result);

            SockNetLogger.Log(SockNetLogger.LogLevel.INFO, this, "Authenticated SSL with [{0}].", RemoteEndpoint);
            SockNetLogger.Log(SockNetLogger.LogLevel.DEBUG, this, "[SSL] Reading data from [{0}]...", RemoteEndpoint);

            this.stream = sslStream;

            PooledObject <byte[]> buffer = bufferPool.Borrow();

            buffer.RefCount.Increment();

            receiveState = new ReceiveState()
            {
                buffer = buffer, offset = 0, length = buffer.Value.Length
            };

            currentReadResult = stream.BeginRead(buffer.Value, 0, buffer.Value.Length, new AsyncCallback(ReceiveCallback), null);

            attachPromiseFulfiller.Fulfill(this);
        }
Пример #3
0
        /// <summary>
        /// Notifies the send queue to process more data.
        /// </summary>
        private void NotifySendQueue()
        {
            if (Interlocked.CompareExchange(ref sendState, 1, 0) == 0)
            {
                SendQueueState nextState;

                if (sendQueue.Dequeue(out nextState))
                {
                    try
                    {
                        Promise <ChunkedBuffer> promise = nextState.buffer.DrainToStream(stream);
                        promise.State       = nextState;
                        promise.OnFulfilled = QueueWriteCallback;
                    }
                    catch (Exception e)
                    {
                        SockNetLogger.Log(SockNetLogger.LogLevel.ERROR, this, "Send data to the socket stream failed.", e);
                    }
                }
                else
                {
                    Interlocked.CompareExchange(ref sendState, 0, 1);
                }
            }
        }
Пример #4
0
        /// <summary>
        /// Enables SSL on this connection.
        /// </summary>
        /// <param name="certificateValidationCallback"></param>
        public void EnableServerSsl(RemoteCertificateValidationCallback certificateValidationCallback, X509Certificate serverCert)
        {
            canRead = false;

            SockNetLogger.Log(SockNetLogger.LogLevel.INFO, this, "Authenticating SSL with [{0}]...", RemoteEndpoint);

            if (currentReadResult != null)
            {
                stream.EndRead(currentReadResult);
            }

            SslStream sslStream = new SslStream(stream, false, certificateValidationCallback);

            sslStream.BeginAuthenticateAsServer(serverCert, new AsyncCallback(EnableServerSslCallback), sslStream);
        }
Пример #5
0
        /// <summary>
        /// Removes a module from this channel.
        /// </summary>
        /// <param name="module"></param>
        /// <returns></returns>
        public ISockNetChannel RemoveModule(ISockNetChannelModule module)
        {
            if (modules.Remove(module.GetType().Name))
            {
                SockNetLogger.Log(SockNetLogger.LogLevel.DEBUG, this, "Uninstalling module: [{0}]", module);

                module.Uninstall(this);
            }
            else
            {
                throw new Exception("Module [" + module + "] not installed.");
            }

            return(this);
        }
Пример #6
0
        /// <summary>
        /// Enables SSL on this connection.
        /// </summary>
        /// <param name="certificateValidationCallback"></param>
        public void EnableClientSsl(RemoteCertificateValidationCallback certificateValidationCallback)
        {
            canRead = false;

            SockNetLogger.Log(SockNetLogger.LogLevel.INFO, this, "Authenticating SSL with [{0}]...", RemoteEndpoint);

            if (currentReadResult != null)
            {
                stream.EndRead(currentReadResult);
            }

            SslStream sslStream = new SslStream(stream, false, certificateValidationCallback);

            X509Certificate2Collection certCollection = new X509Certificate2Collection();

            sslStream.BeginAuthenticateAsClient(RemoteEndpoint.Address.ToString(), certCollection, SslProtocols.Tls, false, new AsyncCallback(EnableClientSslCallback), sslStream);
        }
Пример #7
0
        /// <summary>
        /// Attaches as a non-ssl channel.
        /// </summary>
        protected Promise <ISockNetChannel> Attach()
        {
            stream = new NetworkStream(Socket, true);

            SockNetLogger.Log(SockNetLogger.LogLevel.DEBUG, this, "Reading data from [{0}]...", RemoteEndpoint);

            PooledObject <byte[]> buffer = bufferPool.Borrow();

            buffer.RefCount.Increment();

            receiveState = new ReceiveState()
            {
                buffer = buffer, offset = 0, length = buffer.Value.Length
            };

            canRead = true;

            currentReadResult = stream.BeginRead(buffer.Value, 0, buffer.Value.Length, new AsyncCallback(ReceiveCallback), null);

            return((attachPromiseFulfiller = new Promise <ISockNetChannel>(this).CreateFulfiller()).Promise);
        }
Пример #8
0
        /// <summary>
        /// Sets the given message to the IPEndpoint.
        /// </summary>
        /// <param name="data"></param>
        public Promise <ISockNetChannel> Send(object data)
        {
            Promise <ISockNetChannel> promise = new Promise <ISockNetChannel>();

            object obj = data;

            try
            {
                Pipe.HandleOutgoingData(ref obj);
            }
            catch (Exception ex)
            {
                SockNetLogger.Log(SockNetLogger.LogLevel.ERROR, this, ex.Message);
            }
            finally
            {
                if (obj is byte[])
                {
                    byte[] rawSendableData = (byte[])obj;

                    SockNetLogger.Log(SockNetLogger.LogLevel.DEBUG, this, (IsConnectionEncrypted ? "[SSL] " : "") + "Sending [{0}] bytes to [{1}]...", rawSendableData.Length, RemoteEndpoint);

                    EnqueueToSendQueueAndNotify(new ChunkedBuffer(bufferPool).OfferRaw(rawSendableData, 0, rawSendableData.Length), promise);
                }
                else if (obj is ChunkedBuffer)
                {
                    ChunkedBuffer sendableStream = ((ChunkedBuffer)obj);

                    SockNetLogger.Log(SockNetLogger.LogLevel.DEBUG, this, (IsConnectionEncrypted ? "[SSL] " : "") + "Sending [{0}] bytes to [{1}]...", sendableStream.AvailableBytesToRead, RemoteEndpoint);

                    EnqueueToSendQueueAndNotify(sendableStream, promise);
                }
                else
                {
                    SockNetLogger.Log(SockNetLogger.LogLevel.ERROR, this, "Unable to send object: {0}", obj);
                }
            }
            return(promise);
        }
Пример #9
0
        /// <summary>
        /// Adds a module into this channel.
        /// </summary>
        /// <param name="module"></param>
        /// <returns></returns>
        public ISockNetChannel AddModule(ISockNetChannelModule module)
        {
            ISockNetChannelModule tmp;

            if (modules.TryAdd(module.GetType().Name, module, out tmp, false))
            {
                SockNetLogger.Log(SockNetLogger.LogLevel.DEBUG, this, "Adding module: [{0}]", module);

                if (ShouldInstallModule(module))
                {
                    SockNetLogger.Log(SockNetLogger.LogLevel.DEBUG, this, "Installing module: [{0}]", module);

                    module.Install(this);
                }
            }
            else
            {
                throw new Exception("Module [" + module + "] already installed.");
            }

            return(this);
        }
Пример #10
0
        /// <summary>
        /// A callback that gets invoked when we have incoming data in the pipe.
        /// </summary>
        /// <param name="result"></param>
        private void ReceiveCallback(IAsyncResult result)
        {
            int count = 0;

            this.currentReadResult = null;

            try
            {
                count = stream.EndRead(result);
            }
            catch (Exception)
            {
                // this means that the connection closed...
                Close();
                return;
            }

            SockNetLogger.Log(SockNetLogger.LogLevel.DEBUG, this, (this.stream is SslStream ? "[SSL] " : "") + "Received [{0}] bytes from [{1}].", count, RemoteEndpoint);

            if (count > 0)
            {
                try
                {
                    chunkedBuffer.OfferChunk(receiveState.buffer, receiveState.offset, count);

                    while (true)
                    {
                        long startingPosition = chunkedBuffer.ReadPosition;

                        object obj = chunkedBuffer;

                        Pipe.HandleIncomingData(ref obj);

                        if (startingPosition == chunkedBuffer.ReadPosition)
                        {
                            break;
                        }
                    }

                    if (chunkedBuffer.IsClosed)
                    {
                        Close();

                        return;
                    }
                }
                catch (Exception ex)
                {
                    SockNetLogger.Log(SockNetLogger.LogLevel.ERROR, this, ex.Message, ex);
                }
                finally
                {
                    try
                    {
                        chunkedBuffer.Flush();

                        if (canRead)
                        {
                            if (receiveState.offset + count >= receiveState.length)
                            {
                                if (receiveState.buffer.RefCount.Decrement() < 1)
                                {
                                    if (receiveState.buffer.State == PooledObjectState.USED)
                                    {
                                        receiveState.buffer.Return();
                                    }
                                    else
                                    {
                                        SockNetLogger.Log(SockNetLogger.LogLevel.WARN, this, "Potential resource leak found.");
                                    }
                                }

                                PooledObject <byte[]> buffer = bufferPool.Borrow();
                                buffer.RefCount.Increment();

                                if (IsActive)
                                {
                                    SockNetLogger.Log(SockNetLogger.LogLevel.DEBUG, this, (this.stream is SslStream ? "[SSL] " : "") + "Reading data from [{0}]...", RemoteEndpoint);

                                    receiveState.buffer = buffer;
                                    receiveState.offset = 0;
                                    receiveState.length = buffer.Value.Length;

                                    currentReadResult = stream.BeginRead(buffer.Value, 0, buffer.Value.Length, new AsyncCallback(ReceiveCallback), null);
                                }
                                else
                                {
                                    Close();
                                }
                            }
                            else
                            {
                                if (IsActive)
                                {
                                    SockNetLogger.Log(SockNetLogger.LogLevel.DEBUG, this, (this.stream is SslStream ? "[SSL] " : "") + "Reading data from [{0}]...", RemoteEndpoint);

                                    receiveState.offset += count;

                                    currentReadResult = stream.BeginRead(receiveState.buffer.Value, receiveState.offset, receiveState.length - receiveState.offset, new AsyncCallback(ReceiveCallback), null);
                                }
                                else
                                {
                                    Close();
                                }
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        SockNetLogger.Log(SockNetLogger.LogLevel.ERROR, this, "Unable to begin reading.", e);

                        Close();
                    }
                }
            }
            else
            {
                Close();
            }
        }