Exemplo n.º 1
0
        /// <summary>
        /// This method is invoked by the IoCompleted method to process the send completion.
        /// </summary>
        private void ProcessSend(long requestId, RequestContext context, int status, uint byteTransferred)
        {
            sendStatusQueue.Add(status);
            if (status != (int)SocketError.Success)
            {
                logger.LogError("Socket send operation failed with error {0}", status);
                context.Data.Release();
                return;
            }

            var data = context.Data;
            data.ReaderIndex += (int)byteTransferred;
            if (data.IsReadable())
            {
                // If some of the bytes in the message have NOT been sent,
                // then we need to post another send operation.
                context.Data = data;
                DoSend(requestId, context);
            }
            else
            {
                // All the bytes in the data have been sent,
                // release the buffer back to pool.
                data.Release();
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// This method is invoked by the IoCompleted method to process the receive completion.
        /// </summary>
        private void ProcessReceive(RequestContext context, int status, uint byteTransferred)
        {
            context.Data.Status = status;
            var data = context.Data;
            data.WriterIndex += (int)byteTransferred;
            receivedDataQueue.Add(data);

            if (status != (int) SocketError.Success)
            {
                logger.LogError("Socket receive operation failed with error {0}", status);
                context.Data.Release();
                return;
            }

            if (status == 0 && byteTransferred == 0)
            {
                // The remote has gracefully closed the connection
                logger.LogDebug("ProcessReceive() with status(0) and byteTransferred(0). The connection has been gracefully closed.");
                return;
            }

            // Posts another receive operation
            DoReceive();
        }
Exemplo n.º 3
0
        /// <summary>
        /// Posts a receive operation to this socket
        /// </summary>
        private unsafe void DoReceive()
        {
            // Make a room from Request Queue of this socket for operation.
            var errorStatus = AllocateRequest();
            if (errorStatus != 0)
            {
                logger.LogError("Cannot post receive operation due to no room in Request Queue.");
                receivedDataQueue.Add(ByteBuf.NewErrorStatusByteBuf(errorStatus));
                return;
            }

            // Allocate buffer to receive incoming network data.
            var dataBuffer = ByteBufPool.UnsafeDefault.Allocate();
            if (dataBuffer == null)
            {
                logger.LogError("Failed to allocate ByteBuf at DoReceive().");
                receivedDataQueue.Add(ByteBuf.NewErrorStatusByteBuf((int)SocketError.NoBufferSpaceAvailable));
                return;
            }
            var context = new RequestContext(SocketOperation.Receive, dataBuffer);
            var recvId = GenerateUniqueKey();

            // Add the operation context to request table for completion callback.
            while (!requestContexts.TryAdd(recvId, context))
            {
                // Generate another key, if the key is duplicated.
                recvId = GenerateUniqueKey();
            }

            // Post a receive operation via native method.
            var rioBuf = dataBuffer.GetInputRioBuf();
            if (RioNative.PostRIOReceive(rioRqHandle, &rioBuf, 1, 0, recvId)) return;

            requestContexts.TryRemove(recvId, out context);
            context.Data.Release();

            if (isCleanedUp)
            {
                logger.LogDebug("Socket is already disposed. DoReceive() do nothing.");
                receivedDataQueue.Add(ByteBuf.NewErrorStatusByteBuf((int)SocketError.NetworkDown));
                return;
            }

            // Log exception, if post receive operation failed.
            var socketException = new SocketException();
            logger.LogError("Failed to call DoReceive() with error code [{0}], error message: {1}",
                socketException.ErrorCode, socketException.Message);
            context.Data.Status = socketException.ErrorCode;
            receivedDataQueue.Add(context.Data);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Posts a send operation to this socket.
        /// </summary>
        private unsafe void DoSend(long sendId, RequestContext context)
        {
            // Make a room from Request Queue of this socket for operation.
            var errorStatus = AllocateRequest();
            if ( errorStatus != 0)
            {
                logger.LogError("Cannot post send operation due to no room in Request Queue.");
                sendStatusQueue.Add(errorStatus);
                return;
            }

            // Add the operation context to request table for completion callback.
            while (!requestContexts.TryAdd(sendId, context))
            {
                // Generate another key, if the key is duplicated.
                sendId = GenerateUniqueKey();
            }

            // Post a send operation via native method.
            var rioBuf = context.Data.GetOutputRioBuf();
            if (RioNative.PostRIOSend(rioRqHandle, &rioBuf, 1, 0, sendId)) return;

            requestContexts.TryRemove(sendId, out context);
            context.Data.Release();

            if (isCleanedUp)
            {
                logger.LogDebug("Socket is already disposed. PostSend() do nothing.");
                receivedDataQueue.Add(ByteBuf.NewErrorStatusByteBuf((int)SocketError.NetworkDown));
                return;
            }

            // Log exception, if post send operation failed.
            var socketException = new SocketException();
            logger.LogError("Failed to call PostRIOSend() with error code [{0}]. Error message: {1}",
                socketException.ErrorCode, socketException.Message);
            sendStatusQueue.Add(socketException.ErrorCode);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Sends data to this socket with a ByteBuf object that contains data to be sent.
        /// </summary>
        /// <param name="data">A ByteBuf object that contains data to be sent</param>
        public void Send(ByteBuf data)
        {
            EnsureAccessible();
            if (!isConnected)
            {
                throw new InvalidOperationException("The operation is not allowed on non-connected sockets.");
            }
            if (!data.IsReadable())
            {
                throw new ArgumentException("The parameter {0} must contain one or more elements.", "data");
            }

            var context = new RequestContext(SocketOperation.Send, data);
            DoSend(GenerateUniqueKey(), context);

            var status = sendStatusQueue.Take();
            if (status == (int)SocketError.Success) return;

            // throw a SocketException if theres is an error.
            Dispose(true);
            var socketException = new SocketException(status);
            throw socketException;
        }