public void ServerResponds() { using (var container = SetupMefContainer()) { using (var server = container.GetExport<IServerProcessProxy>().Value) { var waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset); var request = new IpcRequest { RequestId = 5, Protocol = IpcProtocols.Echo, Data = new IpcStringData { Text = "sdfsdsd" } }; IpcResponse response = null; server.RunAsync(request, x => { response = x; waitHandle.Set(); }); Assert.IsTrue(waitHandle.WaitOne(TimeSpan.FromSeconds(5.0)), "Server did not respond within 5 seconds."); Assert.AreEqual(5, response.RequestId); Assert.AreEqual(IpcProtocols.Echo, response.Protocol); Assert.IsNotNull(request.Data); Assert.IsNotNull(response.Data); Assert.AreEqual(request.Data.GetType(), typeof(IpcStringData)); Assert.AreEqual(response.Data.GetType(), typeof(IpcStringData)); Assert.AreEqual((request.Data as IpcStringData).Text, (response.Data as IpcStringData).Text); } } }
public void RunAsync(IpcRequest request, Action <IpcResponse> callback) { CreateServerProcessAsync().ContinueWith(t => { // Register callback so that we can reply with error if needed _callbacks.Add(request, callback); if (t.Exception != null) { // Skip the "AggregateException" var error = t.Exception.InnerExceptions.Count == 1 ? t.Exception.InnerExceptions[0] : t.Exception; // Reply error to callback (this will also fire general "server is down" event) HandleSendRequestError(request, error); } else { // The queue is guaranteed to be started at this point, so enqueue the request // so it is sent to the server _requestQueue.Enqueue(request); } }, new CancellationToken(), TaskContinuationOptions.ExecuteSynchronously, // Make sure to run on thread pool even if called from a UI thread TaskScheduler.Default); }
public override IpcResponse Process(IpcRequest request) { return new IpcResponse { RequestId = request.RequestId, Protocol = request.Protocol, Data = request.Data }; }
public void Enqueue(IpcRequest request) { lock (_lock) { _requests.Enqueue(request); } _waitHandle.Set(); }
public static IpcResponse CreateIpcErrorResponse(IpcRequest request, Exception error) { return new IpcResponse { RequestId = request.RequestId, Protocol = IpcProtocols.Exception, Data = CreateErrorResponse(error) }; }
public async Task GenericMethod(decimal input, decimal expected) { _serviceMock .Setup(x => x.GenericMethod <decimal>(input)) .Returns(expected); #if !DISABLE_DYNAMIC_CODE_GENERATION decimal actual = await _client .InvokeAsync(x => x.GenericMethod <decimal>(input)); Assert.Equal(expected, actual); #endif // TestHelpers.CreateIpcRequest() does not support generic methods, so build the IpcRequests manually var request = new IpcRequest() { MethodName = "GenericMethod", Parameters = new object[1] { input }, ParameterTypesByName = new IpcRequestParameterType[1] { new IpcRequestParameterType(input.GetType()) }, GenericArgumentsByName = new IpcRequestParameterType[1] { new IpcRequestParameterType(input.GetType()) } }; var actual2 = await _client.InvokeAsync <decimal>(request); Assert.Equal(expected, actual2); }
public void ServerResponds() { using (var container = SetupMefContainer()) { using (var server = container.GetExport <IServerProcessProxy>().Value) { var waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset); var request = new IpcRequest { RequestId = 5, Protocol = IpcProtocols.Echo, Data = new IpcStringData { Text = "sdfsdsd" } }; IpcResponse response = null; server.RunAsync(request, x => { response = x; waitHandle.Set(); }); Assert.IsTrue(waitHandle.WaitOne(TimeSpan.FromSeconds(5.0)), "Server did not respond within 5 seconds."); Assert.AreEqual(5, response.RequestId); Assert.AreEqual(IpcProtocols.Echo, response.Protocol); Assert.IsNotNull(request.Data); Assert.IsNotNull(response.Data); Assert.AreEqual(request.Data.GetType(), typeof(IpcStringData)); Assert.AreEqual(response.Data.GetType(), typeof(IpcStringData)); Assert.AreEqual((request.Data as IpcStringData).Text, (response.Data as IpcStringData).Text); } } }
private IpcResponse ProcessOneRequest(IpcRequest request) { try { var processor = _protocolHandlers.FirstOrDefault(x => x.CanProcess(request)); if (processor == null) { throw new Exception(string.Format("Request protocol {0} is not recognized by any request processor!", request.Protocol)); } return(processor.Process(request)); } catch (OperationCanceledException e) { Logger.LogInfo("Request {0} of type \"{1}\" has been canceled.", request.RequestId, request.Data.GetType().Name); return(ErrorResponseHelper.CreateIpcErrorResponse(request.RequestId, e)); } catch (RecoverableErrorException e) { Logger.LogInfo("Request {0} of type \"{1}\" generated a recoverable error: {2}.", request.RequestId, request.Data.GetType().Name, e.Message); return(ErrorResponseHelper.CreateIpcErrorResponse(request.RequestId, e)); } catch (Exception e) { var message = string.Format("Error executing request {0} of type \"{1}\".", request.RequestId, request.Data.GetType().Name); Logger.LogError(e, "{0}", message); var outer = new Exception(message, e); return(ErrorResponseHelper.CreateIpcErrorResponse(request.RequestId, outer)); } }
public void RunAsync(IpcRequest request, Action<IpcResponse> callback) { CreateServerProcess(); // Order is important below to avoid race conditions! _callbacks.Add(request, callback); _requestQueue.Enqueue(request); }
public void RunAsync(TypedRequest request, Action <TypedResponse> callback, Action <ErrorResponse> errorCallback) { var sw = Stopwatch.StartNew(); var ipcRequest = new IpcRequest { RequestId = _ipcRequestIdFactory.GetNextId(), Protocol = IpcProtocols.TypedMessage, Data = request }; // Note: We capture the value outside the RunAsync callback. var localSequenceNumber = Interlocked.Increment(ref _currentSequenceNumber); _serverProcessProxy.RunAsync(ipcRequest, ipcResponse => { lock (_lock) { _bufferedResponses.Add(new BufferedResponse { SequenceNumber = localSequenceNumber, IpcRequest = ipcRequest, IpcResponse = ipcResponse, SuccessCallback = callback, ErrorCallback = errorCallback, Elapsed = sw.Elapsed }); } OnResponseReceived(); }); }
private void OnRequestError(IpcRequest request, Exception error) { var callback = _callbacks.Remove(request.RequestId); var response = ErrorResponseHelper.CreateIpcErrorResponse(request, error); callback(response); }
private IpcResponse ProcessOneRequest(IpcRequest request) { try { var processor = _protocolHandlers.FirstOrDefault(x => x.CanProcess(request)); if (processor == null) { throw new Exception(string.Format("Request protocol {0} is not recognized by any request processor!", request.Protocol)); } return processor.Process(request); } catch (OperationCanceledException e) { Logger.LogInfo("Request {0} of type \"{1}\" has been canceled.", request.RequestId, request.Data.GetType().Name); return ErrorResponseHelper.CreateIpcErrorResponse(request, e); } catch (RecoverableErrorException e) { Logger.LogInfo("Request {0} of type \"{1}\" generated a recoverable error: {2}.", request.RequestId, request.Data.GetType().Name, e.Message); return ErrorResponseHelper.CreateIpcErrorResponse(request, e); } catch (Exception e) { var message = string.Format("Error executing request {0} of type \"{1}\".", request.RequestId, request.Data.GetType().Name); Logger.LogError(e, "{0}", message); var outer = new Exception(message, e); return ErrorResponseHelper.CreateIpcErrorResponse(request, outer); } }
public override IpcResponse Process(IpcRequest request) { return(new IpcResponse { RequestId = request.RequestId, Protocol = request.Protocol, Data = request.Data }); }
private void SendRequest(IpcRequest request) { try { _ipcStream.WriteRequest(request); } catch (Exception e) { throw new IpcRequestException(request, e); } }
public void RunAsync(IpcRequest request, Action <IpcResponse> callback) { CreateServerProcess(); // Order is important below to avoid race conditions! _callbacks.Add(request, callback); _requestQueue.Enqueue(request); }
private void ProcessRequestTask(IpcRequest request) { var sw = Stopwatch.StartNew(); var response = ProcessOneRequest(request); _ipcResponseQueue.Enqueue(response); sw.Stop(); Logger.LogInfo("Request {0} of type \"{1}\" took {2:n0} msec to handle.", request.RequestId, request.Data.GetType().Name, sw.ElapsedMilliseconds); }
private static MethodInfo GetUnambiguousMethod(IpcRequest request, object service) { if (request is null) { throw new ArgumentNullException(nameof(request)); } if (service is null) { throw new ArgumentNullException(nameof(service)); } MethodInfo method = null; // disambiguate - can't just call as before with generics - MethodInfo method = service.GetType().GetMethod(request.MethodName); Type[] types = service.GetType().GetInterfaces(); IEnumerable <MethodInfo> allMethods = types.SelectMany(t => t.GetMethods()); var serviceMethods = allMethods.Where(t => t.Name == request.MethodName).ToList(); object[] requestParameters = request.Parameters?.ToArray() ?? Array.Empty <object>(); Type[] requestGenericArguments = request.GenericArguments?.ToArray() ?? Array.Empty <Type>(); Type[] requestParameterTypes = request.ParameterTypes?.ToArray() ?? Array.Empty <Type>(); foreach (MethodInfo serviceMethod in serviceMethods) { ParameterInfo[] serviceMethodParameters = serviceMethod.GetParameters(); int parameterTypeMatches = 0; if (serviceMethodParameters.Length == requestParameters.Length && serviceMethod.GetGenericArguments().Length == requestGenericArguments.Length) { for (int parameterIndex = 0; parameterIndex < serviceMethodParameters.Length; parameterIndex++) { Type serviceParameterType = serviceMethodParameters[parameterIndex].ParameterType.IsGenericParameter ? requestGenericArguments[serviceMethodParameters[parameterIndex].ParameterType.GenericParameterPosition] : serviceMethodParameters[parameterIndex].ParameterType; if (serviceParameterType == requestParameterTypes[parameterIndex]) { parameterTypeMatches++; } else { break; } } if (parameterTypeMatches == serviceMethodParameters.Length) { method = serviceMethod; // signatures match so assign break; } } } return(method); }
protected void SendRequest(IpcRequest request) { lock (baseLock) { _formatter.Serialize(_pipeClientStream, request); _pipeClientStream.WaitForPipeDrain(); } }
public async Task InvokeAsync(IpcRequest request, CancellationToken cancellationToken = default) { var response = await GetResponseAsync(request, cancellationToken).ConfigureAwait(false); if (!response.Succeed()) { throw response.CreateFaultException(); } }
private static string GetRequestDescription(IpcRequest request) { try { return(request.ToString()); } catch (Exception) { return(request.Data.GetType().Name); } }
protected virtual void OnRequestError(IpcRequest request, Exception error) { var handler = RequestError; if (handler != null) { handler(request, error); } }
/// <summary> /// Creates an IPC request for the given method in the given interface. Does not support generic methods. /// </summary> /// <param name="interfaceType">The Type of the interface containing the method.</param> /// <param name="methodName">Name of the method.</param> /// <param name="args">The arguments to the method.</param> /// <returns>IpcRequest object</returns> public static IpcRequest CreateIpcRequest(Type interfaceType, string methodName, bool useIpcRequestParameterType, params object[] args) { MethodInfo method = null; // Try to find the matching method based on name and args if (args.All(x => x != null)) { method = interfaceType.GetMethod(methodName, args.Select(x => x.GetType()).ToArray()); } if (method == null) { method = interfaceType.GetMethod(methodName); } if (method == null) { throw new ArgumentException($"Could not find a valid method in {interfaceType}!"); } if (method.IsGenericMethod) { throw new ArgumentException("Generic methods are not supported!", nameof(methodName)); } var methodParams = method.GetParameters(); var request = new IpcRequest() { MethodName = methodName, Parameters = args }; if (useIpcRequestParameterType) { var parameterTypesByName = new IpcRequestParameterType[methodParams.Length]; for (int i = 0; i < methodParams.Length; i++) { parameterTypesByName[i] = new IpcRequestParameterType(methodParams[i].ParameterType); } request.ParameterTypesByName = parameterTypesByName; } else { var parameterTypes = new Type[methodParams.Length]; for (int i = 0; i < args.Length; i++) { parameterTypes[i] = methodParams[i].ParameterType; } request.ParameterTypes = parameterTypes; } return(request); }
/// <summary> /// Creates the IPC request. /// </summary> /// <param name="methodName">Name of the method.</param> /// <param name="args">The arguments to the method.</param> /// <returns>IpcRequest object</returns> protected static IpcRequest CreateIpcRequest(string methodName, params object[] args) { MethodBase method = null; // Try to find the matching method based on name and args try { if (args.All(x => x != null)) { method = typeof(FactoryOrchestratorClient).GetMethod(methodName, args.Select(x => x.GetType()).ToArray()); } if (method == null) { method = typeof(FactoryOrchestratorClient).GetMethod(methodName); } } catch (Exception) { method = null; } if (method == null) { // Multiple methods with the same name were found or no method was found, try to find the unique method via stack trace var frame = new StackTrace().GetFrames().Where(x => x.GetMethod()?.Name == methodName); if (!frame.Any()) { throw new Exception(string.Format(CultureInfo.CurrentCulture, Resources.NoMethodFound, methodName)); } if (frame.Count() > 1) { throw new Exception(string.Format(CultureInfo.CurrentCulture, Resources.TooManyMethodsFound, methodName)); } method = frame.First().GetMethod(); } var methodParams = method.GetParameters(); var parameterTypes = new IpcRequestParameterType[methodParams.Length]; for (int i = 0; i < methodParams.Length; i++) { parameterTypes[i] = new IpcRequestParameterType(methodParams[i].ParameterType); } var request = new IpcRequest() { MethodName = methodName, Parameters = args, ParameterTypesByName = parameterTypes }; return(request); }
protected bool ProcessRequest(IpcRequest request) { switch (request.RequestType) { case IpcRequestType.Exit: CloseConnection(true); return(false); case IpcRequestType.Init: OpenConnection(request.ConnectionString); break; case IpcRequestType.GetDocumentText: GetDocumentText(request.DocumentID, request.NoteColumnName); break; case IpcRequestType.Navigate: Navigate(request.NavigationContextID, request.NavigationMode, request.RegExp, request.TotalDocumentsCount, request.DocumentsBlock.ToList(), request.Position); break; case IpcRequestType.SortByCategory: SortByCategory(request.SortAscending); break; case IpcRequestType.GetDocumentColumnCount: GetDocumentColumnCount(); break; case IpcRequestType.GetDynamicColumnID: GetDynamicColumnID(request.DynamicColumnName); break; case IpcRequestType.GetDocumentColumnSettings: GetDocumentColumnSettings(); break; case IpcRequestType.GetDynamicColumnDisplayName: GetDynamicColumnDisplayName(request.DynamicColumnName); break; case IpcRequestType.SetDocumentColumnSettings: SetDocumentColumnSettings(request.DocumentColumnSettings); break; case IpcRequestType.DeleteAllExtraDocumentColumns: DeleteAllExtraDocumentColumns(); break; default: SendErrorResponse("Invalid request code"); break; } return(true); }
/// <exception cref="IpcSerializationException">If unable to serialize request</exception> /// <exception cref="IpcCommunicationException">If communication is broken</exception> /// <exception cref="IpcFaultException">If error occurred in server</exception> public async Task InvokeAsync(Expression <Func <TInterface, Task> > exp, CancellationToken cancellationToken = default) { IpcRequest request = GetRequest(exp, new MyInterceptor <Task>()); IpcResponse response = await GetResponseAsync(request, cancellationToken).ConfigureAwait(false); if (!response.Succeed()) { throw response.CreateFaultException(); } }
/// <summary> /// Process one request synchronously (on a background thread) and sends the response back /// to the response queue (i.e. communication pipe) /// </summary> private void ProcessRequestWorker(IpcRequest request) { var sw = Stopwatch.StartNew(); var response = ProcessOneRequest(request); sw.Stop(); _ipcResponseQueue.Enqueue(response); Logger.LogInfo("Request {0} of type \"{1}\" took {2:n0} msec to execute.", request.RequestId, request.Data.GetType().Name, sw.ElapsedMilliseconds); }
/// <exception cref="IpcSerializationException">If unable to serialize request</exception> /// <exception cref="IpcCommunicationException">If communication is broken</exception> /// <exception cref="IpcFaultException">If error occurred in server</exception> public async Task InvokeAsync(Expression <Action <TInterface> > exp, CancellationToken cancellationToken = default) { IpcRequest request = GetRequest(exp, DispatchProxy.Create <TInterface, IpcProxy>()); IpcResponse response = await GetResponseAsync(request, cancellationToken).ConfigureAwait(false); if (!response.Succeed()) { throw response.CreateFaultException(); } }
public void ProcessRequestAsync(IpcRequest request) { if (request.RunOnSequentialQueue) { // Run on queue, with a unique ID since each request is unique _sequentialTaskQueue.Enqueue(new TaskId(String.Format("RequestId={0}", request.RequestId)), t => ProcessRequestWorker(request)); } else { _customThreadPool.RunAsync(() => ProcessRequestWorker(request)); } }
private void HandleSendRequestError(IpcRequest request, Exception error) { var callback = _callbacks.Remove(request.RequestId); var response = ErrorResponseHelper.CreateIpcErrorResponse(request.RequestId, error); callback(response); // We assume the server is down as soon as there is an error // sending a request. _isServerRunning = false; OnProcessFatalError(new ErrorEventArgs(error)); }
private async Task <IpcResponse> GetResponseAsync(IpcRequest request, CancellationToken cancellationToken) { using (Stream client = await ConnectToServerAsync(cancellationToken).ConfigureAwait(false)) using (Stream client2 = _options.StreamTranslator == null ? client : _options.StreamTranslator(client)) using (var writer = new IpcWriter(client2, _options.Serializer, leaveOpen: true)) using (var reader = new IpcReader(client2, _options.Serializer, leaveOpen: true)) { // send request await writer.WriteAsync(request, cancellationToken).ConfigureAwait(false); // receive response return(await reader.ReadIpcResponseAsync(cancellationToken).ConfigureAwait(false)); } }
public void ProtoBufSerializationWorksForRegisterFileRequest() { using (var container = SetupMefContainer()) { var serializer = container.GetExport <IProtoBufSerializer>().Value; var req = new IpcRequest { RequestId = 7, Protocol = IpcProtocols.TypedMessage, Data = new RegisterFileRequest { FileName = "c:\\hhhh" } }; AssertRoundTrip(serializer, req); } }
public void ProtoBufSerializationWorksForStringData() { using (var container = SetupMefContainer()) { var serializer = container.GetExport <IProtoBufSerializer>().Value; var req = new IpcRequest { RequestId = 6, Protocol = IpcProtocols.TypedMessage, Data = new IpcStringData { Text = "c:\\hhhh" } }; AssertRoundTrip(serializer, req); } }
public override IpcResponse Process(IpcRequest request) { var typedRequest = (TypedRequest)request.Data; var handler = _handlers.FirstOrDefault(x => x.CanProcess(typedRequest)); if (handler == null) { throw new InvalidOperationException(string.Format("No TypedMessage handler for request of type {0}", request.GetType().Name)); } var typedResponse = handler.Process(typedRequest); return new IpcResponse { RequestId = request.RequestId, Protocol = request.Protocol, Data = typedResponse }; }
protected override object Invoke(MethodInfo targetMethod, object[] args) { var actualReturnType = GetAndCheckActualReturnType(targetMethod.ReturnType); var parameters = targetMethod.GetParameters(); var parameterTypes = parameters.Select(p => new IpcRequestParameterType(p.ParameterType)).ToArray(); var parameterList = new List <IpcRequestParameter>(parameterTypes.Length); for (var i = 0; i < parameterTypes.Length; i++) { var ipcRequestParameter = new IpcRequestParameter() { ParameterType = parameterTypes[i], Value = args[i] }; parameterList.Add(ipcRequestParameter); } var genericTypes = targetMethod.GetGenericArguments(); var genericArgumentList = genericTypes.Select(type => new IpcRequestParameterType(type)).Cast <IpcSerializableType>().ToList(); var ipcRequest = new IpcRequest() { MethodName = targetMethod.Name, ParameterList = parameterList, GenericArgumentList = genericArgumentList, ReturnType = new IpcSerializableType(actualReturnType), ObjectType = new IpcSerializableType(typeof(T)), ObjectId = ObjectId, }; //IpcResponse response = await GetResponseAsync(ipcRequest); ////Task<T> //TaskCompletionSource<int> t = new TaskCompletionSource<int>(); //int n = await foo.FooAsync(); //var re = IpcObjectSerializer.Serialize(ipcRequest); // 此方法还没完成,等待下一次实现,有技术实现问题 throw new NotImplementedException(); }
public void ProtoBufSerializationWorksForBigRequest() { Logger.LogMemoryStats(); using (var container = SetupMefContainer()) { var serializer = container.GetExport <IProtoBufSerializer>().Value; var req = new IpcRequest { RequestId = 6, Protocol = IpcProtocols.TypedMessage, Data = new GetFileSystemResponse { Tree = CreateBigFileSystemTree() } }; Logger.LogMemoryStats(); AssertRoundTrip(serializer, req); } Logger.LogMemoryStats(); }
public async Task <TResult> InvokeAsync <TResult>(IpcRequest request, CancellationToken cancellationToken = default) { var response = await GetResponseAsync(request, cancellationToken).ConfigureAwait(false); if (!response.Succeed()) { throw response.CreateFaultException(); } if (_options.ValueConverter.TryConvert(response.Data, typeof(TResult), out object @return)) { return((TResult)@return); } else { throw new IpcSerializationException($"Unable to convert returned value to '{typeof(TResult).Name}'."); } }
/// <exception cref="IpcSerializationException">If unable to serialize request</exception> /// <exception cref="IpcCommunicationException">If communication is broken</exception> /// <exception cref="IpcFaultException">If error occurred in server</exception> public async Task <TResult> InvokeAsync <TResult>(Expression <Func <TInterface, TResult> > exp, CancellationToken cancellationToken = default) { IpcRequest request = GetRequest(exp, new MyInterceptor <TResult>()); IpcResponse response = await GetResponseAsync(request, cancellationToken).ConfigureAwait(false); if (!response.Succeed()) { throw response.CreateFaultException(); } if (!_options.ValueConverter.TryConvert(response.Data, typeof(TResult), out object @return)) { throw new IpcSerializationException($"Unable to convert returned value to '{typeof(TResult).Name}'."); } return((TResult)@return); }
public void ProcessRequestAsync(IpcRequest request) { _customThreadPool.RunAsync(() => ProcessRequestTask(request)); }
public override IpcResponse Process(IpcRequest request) { return HelloWorldProtocol.Response; }
public abstract IpcResponse Process(IpcRequest request);
public IpcRequestException(IpcRequest request, Exception inner) : base(string.Format("Error sending request {0} of type {1} to server", request.RequestId, request.Data.GetType().FullName), inner) { _request = request; }
public bool CanProcess(IpcRequest request) { return request.Protocol == _protocol; }
public void Add(IpcRequest request, Action<IpcResponse> callback) { lock (_lock) { _callbacks.Add(request.RequestId, callback); } }
protected virtual void OnRequestError(IpcRequest request, Exception error) { var handler = RequestError; if (handler != null) handler(request, error); }