Пример #1
0
 /// <summary>
 ///		Performs protocol specific asynchronous 'Send' operation.
 /// </summary>
 /// <param name="context">Context information.</param>
 protected sealed override void SendCore(ClientRequestContext context)
 {
     if (!BoundSocket.SendToAsync(context.SocketContext))
     {
         context.SetCompletedSynchronously();
         OnSent(context);
     }
 }
Пример #2
0
        /// <summary>
        ///		Returns the request context to the pool.
        /// </summary>
        /// <param name="context">The context to the pool.</param>
        /// <exception cref="ArgumentNullException">
        ///		<paramref name="context"/> is  <c>null</c>.
        /// </exception>
        protected internal void ReturnRequestContext(ClientRequestContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            Contract.EndContractBlock();

            context.Clear();
            context.UnboundTransport();
            RequestContextPool.Return(context);
        }
Пример #3
0
        /// <summary>
        ///		Returns the specified context to the <see cref="Manager"/>.
        /// </summary>
        /// <param name="context">The <see cref="ClientRequestContext"/> to be returned.</param>
        /// <exception cref="ArgumentNullException">
        ///		<paramref name="context"/> is <c>null</c>.
        /// </exception>
        /// <exception cref="ArgumentException">
        ///		<paramref name="context"/> is not bound to this transport.
        /// </exception>
        public void ReturnContext(ClientRequestContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (!ReferenceEquals(context.BoundTransport, this))
            {
                throw new ArgumentException("Context is not bound to this transport.", nameof(context));
            }

            Contract.EndContractBlock();

            Manager.ReturnRequestContext(context);
        }
Пример #4
0
        /// <summary>
        ///		Called when asynchronous 'Send' operation is completed.
        /// </summary>
        /// <param name="context">Context information.</param>
        /// <returns>
        ///		<c>true</c>, if the subsequent request is already received;
        ///		<c>false</c>, otherwise.
        /// </returns>
        ///	<exception cref="InvalidOperationException">
        ///		This instance is not in 'Sending' state.
        ///	</exception>
        ///	<exception cref="ObjectDisposedException">
        ///		This instance is disposed.
        ///	</exception>
        protected virtual void OnSent(ClientRequestContext context)
        {
            if (MsgPackRpcClientProtocolsTrace.ShouldTrace(MsgPackRpcClientProtocolsTrace.SentOutboundData))
            {
                var socket = BoundSocket;
                MsgPackRpcClientProtocolsTrace.TraceEvent(
                    MsgPackRpcClientProtocolsTrace.SentOutboundData,
                    "Sent request/notification. {{ \"SessionID\" : {0}, \"Socket\" : 0x{1:X}, \"RemoteEndPoint\" : \"{2}\", \"LocalEndPoint\" : \"{3}\", \"Type\" : \"{4}\", \"MessageID\" : {5}, \"Method\" : \"{6}\", \"BytesTransferred\" : {7} }}",
                    context.SessionId,
                    GetHandle(socket),
                    GetRemoteEndPoint(socket, context),
                    GetLocalEndPoint(socket),
                    context.MessageType,
                    context.MessageId,
                    context.MethodName,
                    context.BytesTransferred
                    );
            }

            context.StopWatchTimeout();
            context.Timeout -= OnSendTimeout;

            context.ClearBuffers();

            if (context.MessageType == MessageType.Notification)
            {
                try {
                    Action <Exception, bool> handler = null;
                    try {
                        pendingNotificationTable.TryRemove(context.SessionId, out handler);
                    }
                    finally {
                        var rpcError = context.SocketError.ToClientRpcError();
                        handler?.Invoke(rpcError.IsSuccess ? null : rpcError.ToException(), context.CompletedSynchronously);
                    }
                }
                finally {
                    Manager.ReturnRequestContext(context);
                    OnProcessFinished();
                    Manager.ReturnTransport(this);
                }
            }
            else
            {
                if (Manager.Configuration.WaitTimeout != null &&
                    (Manager.Configuration.WaitTimeout.Value - context.ElapsedTime).TotalMilliseconds < 1.0)
                {
                    OnWaitTimeout(context);
                    Manager.ReturnRequestContext(context);
                    Manager.ReturnTransport(this);
                    return;
                }

                var responseContext = Manager.GetResponseContext(this, context.RemoteEndPoint);

                if (Manager.Configuration.WaitTimeout != null)
                {
                    responseContext.Timeout += OnReceiveTimeout;
                    responseContext.StartWatchTimeout(Manager.Configuration.WaitTimeout.Value - context.ElapsedTime);
                }

                Manager.ReturnRequestContext(context);
                Receive(responseContext);
            }
        }
Пример #5
0
 /// <summary>
 ///		Performs protocol specific asynchronous 'Send' operation.
 /// </summary>
 /// <param name="context">Context information.</param>
 protected abstract void SendCore(ClientRequestContext context);
Пример #6
0
        /// <summary>
        ///		Sends a request or notification message with the specified context.
        /// </summary>
        /// <param name="context">The context information.</param>
        /// <exception cref="ArgumentNullException">
        ///		<paramref name="context"/> is <c>null</c>.
        /// </exception>
        /// <exception cref="ArgumentException">
        ///		<paramref name="context"/> is not bound to this transport.
        /// </exception>
        /// <exception cref="ObjectDisposedException">
        ///		This instance has been disposed.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        ///		This instance is in shutdown.
        ///		Or the message ID or session ID is duplicated.
        /// </exception>
        /// <exception cref="RpcException">
        ///		Failed to send request or notification to the server.
        /// </exception>
        public void Send(ClientRequestContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (!ReferenceEquals(context.BoundTransport, this))
            {
                throw new ArgumentException("Context is not bound to this object.", nameof(context));
            }

            VerifyIsNotDisposed();

            if (IsClientShutdown)
            {
                throw new InvalidOperationException("This transport is in shutdown.");
            }

            Contract.EndContractBlock();

            if (IsServerShutdown)
            {
                throw new RpcErrorMessage(RpcError.TransportError, "Server did shutdown socket.", null).ToException();
            }

            context.Prepare();

            if (context.MessageType == MessageType.Request)
            {
                if (!pendingRequestTable.TryAdd(context.MessageId.Value, context.RequestCompletionCallback))
                {
                    throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Message ID '{0}' is already used.", context.MessageId));
                }
            }
            else
            {
                if (!pendingNotificationTable.TryAdd(context.SessionId, context.NotificationCompletionCallback))
                {
                    throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Session ID '{0}' is already used.", context.MessageId));
                }
            }

            if (MsgPackRpcClientProtocolsTrace.ShouldTrace(MsgPackRpcClientProtocolsTrace.SendOutboundData))
            {
                var socket = BoundSocket;
                MsgPackRpcClientProtocolsTrace.TraceEvent(
                    MsgPackRpcClientProtocolsTrace.SendOutboundData,
                    "Send request/notification. {{ \"SessionID\" : {0}, \"Socket\" : 0x{1:X}, \"RemoteEndPoint\" : \"{2}\", \"LocalEndPoint\" : \"{3}\", \"Type\" : \"{4}\", \"MessageID\" : {5}, \"Method\" : \"{6}\", \"BytesTransferring\" : {7} }}",
                    context.SessionId,
                    GetHandle(socket),
                    GetRemoteEndPoint(socket, context),
                    GetLocalEndPoint(socket),
                    context.MessageType,
                    context.MessageId,
                    context.MethodName,
                    context.sendingBuffer.Sum(segment => (long)segment.Count)
                    );
            }

            // Because exceptions here means client error, it should be handled like other client error.
            // Therefore, no catch clauses here.
            ApplyFilters(AfterSerializationFilters, context);

            if (Manager.Configuration.WaitTimeout != null)
            {
                context.Timeout += OnSendTimeout;
                context.StartWatchTimeout(Manager.Configuration.WaitTimeout.Value);
            }

            SendCore(context);
        }