internal static bool HandleTransportExceptionHelper(Exception exception) { //if (exception == null) // throw ExceptionHandler exceptionHandler = ExceptionHandler.TransportExceptionHandler; if (exceptionHandler == null) { return(false); } try { if (!exceptionHandler.HandleException(exception)) { return(false); } } catch (Exception ex) { //if (IsFatal(ex)) { // throw; } //else { //if (ShouldTraceError) RpcTrace.Error(ex); return(false); } } // if (ShouldTraceError) // TraceHandledException(exception, TraceEventType.Error); return(true); }
private Message invokeContract(IRpcCallInfo call, MessageRequest request, Type contractType) { OperationDispatchBase operation; bool operationExists = _operations.IdToOperation.TryGetValue(request.Operation, out operation); if (!operationExists) { var error = new ActionNotSupportedException(string.Format("Server endpoint {0} with contract {1} does not supports operation with id = {2}. Check that client and server use the same version of contract and binding. ", _endpoint._address, contractType, request.Operation)); var faultMessage = new Message(); faultMessage = makeFault(error, faultMessage); return(faultMessage); } OperationContext operationContext = SetupOperationConext(call, request, contractType); Func <Message> invokeAction = () => { OperationContext.Current = operationContext; if (_concurrency == ConcurrencyMode.Single) { lock (this) { return(invokeContract(operation, request)); } } return(invokeContract(operation, request)); }; if (operation.Operation.IsOneWay) { Task task = Tasks.Factory.StartNew(invokeAction); task.ContinueWith(x => RpcTrace.Error(x.Exception), TaskContinuationOptions.OnlyOnFaulted); return(new Message()); } else { return(invokeAction()); } }
public override IMessage Invoke(IMessage msg) { var input = (IMethodCallMessage)msg; //TODO: move to RpcCallbackProxy if (_router._context != null) { _router._context.Initialize(_router._typeOfService, _router._address, _router._binding, _router._session, _router._syncContext); } Debug.Assert(input.MethodBase != null); Debug.Assert(input.MethodBase.DeclaringType != null); var iid = input.MethodBase.DeclaringType; if (iid == typeof(ICommunicationObject)) { //TODO: use something faster than string comparison if (input.MethodName == "get_State") { return(new ReturnMessage(State, null, 0, input.LogicalCallContext, input)); } } else if (iid == typeof(IContextChannel)) { if (input.MethodName == "set_OperationTimeout") { OperationTimeout = (TimeSpan)input.InArgs[0]; return(new ReturnMessage(null, null, 0, input.LogicalCallContext, input)); } if (input.MethodName == "get_OperationTimeout") { return(new ReturnMessage(OperationTimeout, null, 0, input.LogicalCallContext, input)); } } MethodResponse methodReturn; OperationDispatchBase op; if (_router._operations.TokenToOperation.TryGetValue(input.MethodBase.MetadataToken, out op)) { var r = new MessageRequest(); if (_router._session != null) { r.Session = _router._session; } r.Operation = op.Identifier; var ps = new List <RpcParamData>(); for (int i = 0; i < op.Params.Count; i++) { var paramIdentifier = i;//TODO: try to make this connection with more inderect way var stream = new MemoryStream(); _router._serializer.WriteObject(stream, input.GetInArg(i)); ps.Add(new RpcParamData { Identifier = paramIdentifier, Data = stream.ToArray() }); } r.Data.AddRange(ps.ToArray()); var rData = new MemoryStream(); _router._serializer.WriteObject(rData, r); if (op is AsyncOperationDispatch) { object asyncState = input.GetInArg(op.Params.Count + 1); var asyncCallback = (AsyncCallback)input.GetInArg(op.Params.Count); Task task = Tasks.Factory.StartNew((x) => { try { _router._operationPending.Reset(); byte[] result = null; result = ExecuteRequest(rData); var reply = (Message) _encoder.ReadObject(new MemoryStream(result), typeof(Message)); applyReplyProcessing(reply); } catch (ExternalException ex) { throw HandleCommunicationError(ex); } catch (Exception ex) { throw; } finally { _router._operationPending.Set(); } return(new ReturnMessage(null, null, 0, null, input)); }, asyncState); task.ContinueWith(x => { //TODO: do exception handling like in WCF RpcTrace.Error(x.Exception); if (asyncCallback != null) { asyncCallback(x); } }, TaskContinuationOptions.OnlyOnFaulted); task.ContinueWith(x => { if (asyncCallback != null) { asyncCallback(x); } }, TaskContinuationOptions.OnlyOnRanToCompletion); return(new ReturnMessage(task, null, 0, null, input)); } else if (op.Operation.IsOneWay) { Debug.Assert(op.MethodInfo.ReturnType == typeof(void)); try { _router._operationPending.Reset(); byte[] result = null; result = ExecuteRequest(rData); var reply = (Message)_encoder.ReadObject(new MemoryStream(result), typeof(Message)); try { applyReplyProcessing(reply); } catch (Exception ex) { return(new ReturnMessage(ex, input)); } } catch (ExternalException ex) { throw HandleCommunicationError(ex); } catch (Exception ex) { throw; } finally { _router._operationPending.Set(); } return(new ReturnMessage(null, null, 0, null, input)); } try { _router._operationPending.Reset(); byte[] result = null; //BUG: using tasks adds 30% to simple local calls with bytes, and 10% longer then WCF... //TODO: use native MS-RPC timeouts //Task operation = Task.Factory.StartNew(() => // { result = ExecuteRequest(rData); // }); //var ended = operation.Wait(_operationTimeout); //if (!ended) //{ // var timeourError = // new TimeoutException( // string.Format("The request channel timed out attempting to send after {0}", // _operationTimeout)); // return new ReturnMessage(timeourError,input); //} var reply = (Message)_encoder.ReadObject(new MemoryStream(result), typeof(Message)); applyReplyProcessing(reply); if (op.MethodInfo.ReturnType != typeof(void)) { var retVal = _router._serializer.ReadObject(new MemoryStream(reply.Data), op.MethodInfo.ReturnType); var ret = new ReturnMessage(retVal, null, 0, null, input); return(ret); } } catch (ExternalException ex) { var wrappedException = HandleCommunicationError(ex); return(new ReturnMessage(wrappedException, input)); } catch (Exception ex) { return(new ReturnMessage(ex, input)); } finally { _router._operationPending.Set(); } return(new ReturnMessage(null, null, 0, null, input)); } //var error = new ActionNotSupportedException(); //RpcTrace.Error(); throw new InvalidOperationException(string.Format("Cannot find operation {0} on service {1}", input.MethodName, _service)); }