async void HandleMessage(BinaryMessage msg, byte type) { var t = Task.Run(() => { msg = LoadMessageData(msg); if (type == 0) { ProcessResponse(msg); } else { ProcessRemoteMessage(msg); } }); try { lock (pendingMessageTasks) pendingMessageTasks.Add(t); await t.ConfigureAwait(false); } catch (Exception e) { LoggingService.LogError("RemoteProcessConnection.HandleMessage failed", e); } finally { lock (pendingMessageTasks) pendingMessageTasks.Remove(t); } }
async void ReadMessages() { byte[] buffer = new byte [1]; while (!disposed && connectionStream != null) { BinaryMessage msg; byte type; try { int nr = await connectionStream.ReadAsync(buffer, 0, 1, mainCancelSource.Token).ConfigureAwait(false); if (nr == 0) { // Connection closed. Remote process should die by itself. return; } type = buffer [0]; msg = BinaryMessage.Read(connectionStream); } catch (Exception ex) { if (disposed) { return; } LoggingService.LogError("ReadMessage failed", ex); StopRemoteProcess(isAsync: true); PostSetStatus(ConnectionStatus.ConnectionFailed, "Connection to remote process failed."); return; } HandleMessage(msg, type); } }
void PostMessage(BinaryMessage message, TaskCompletionSource <BinaryMessage> cs, bool checkInitialized) { if (checkInitialized && !initializationDone) { throw new RemoteProcessException("Not connected"); } if (cs != null) { lock (messageWaiters) { messageWaiters [message.Id] = new MessageRequest { Request = message, TaskSource = cs }; } } lock (messageQueue) { messageQueue.Add(message); if (!senderRunning) { senderRunning = true; ThreadPool.QueueUserWorkItem(delegate { SendMessages(); }); } } }
void ProcessRemoteMessage(BinaryMessage msg) { if (DebugMode) { LogMessage(MessageType.Message, msg); } if (msg.Name == "Connect") { processConnectedEvent.TrySetResult(true); return; } if (MessageReceived != null) { Runtime.RunInMainThread(delegate { MessageReceived?.Invoke(null, new MessageEventArgs() { Message = msg }); }); } try { foreach (var li in listeners) { li.ProcessMessage(msg); } } catch (Exception ex) { LoggingService.LogError("Exception in message invocation: " + msg, ex); } }
void ExecuteMessage(BinaryMessage msg) { BinaryMessage response = null; var sw = System.Diagnostics.Stopwatch.StartNew(); try { if (msg.Name == "FlushMessages") { response = msg.CreateResponse(); } else { response = listener.ProcessMessage(msg); } } catch (Exception ex) { if (ex is TargetInvocationException) { ex = ((TargetInvocationException)ex).InnerException; } server.LogError(ex); response = msg.CreateErrorResponse(ex.Message, !(ex is RemoteProcessException)); Console.WriteLine(ex); } if (response != null) { response.Id = msg.Id; response.ProcessingTime = sw.ElapsedMilliseconds; server.SendResponse(response); } else if (!msg.OneWay) { server.SendResponse(msg.CreateErrorResponse("Got no response from server", true)); } }
void ProcessResponse (BinaryMessage msg) { DateTime respTime = DateTime.Now; lock (messageWaiters) { MessageRequest req; if (messageWaiters.TryGetValue (msg.Id, out req)) { messageWaiters.Remove (msg.Id); try { var rt = req.Request.GetResponseType (); if (rt != typeof (BinaryMessage)) { var resp = (BinaryMessage)Activator.CreateInstance (rt); resp.CopyFrom (msg); msg = resp; } } catch (Exception ex) { msg = msg.CreateErrorResponse (ex.ToString ()); } if (DebugMode) { var time = (int)(respTime - req.Request.SentTime).TotalMilliseconds; LogMessage (MessageType.Response, msg, time); } if (!req.Request.OneWay) NotifyResponse (req, msg); } else if (DebugMode) LogMessage (MessageType.Response, msg, -1); } }
void PostMessageInternal (BinaryMessage message) { if ((status != ConnectionStatus.Connected || disposed) && !message.BypassConnection) { ProcessResponse (message.CreateErrorResponse ("Connection is closed")); return; } try { if (DebugMode) message.SentTime = DateTime.Now; // Now send the message. This one will need a response if (DebugMode) LogMessage (MessageType.Request, message); connectionStream.WriteByte ((byte)RequestType.QueueEnd); message.Write (connectionStream); connectionStream.Flush (); } catch (Exception ex){ if (connection == null || (!connection.Connected && status == ConnectionStatus.Connected)) { AbortConnection ("Disconnected from remote process due to a communication error", isAsync: true); } else ProcessResponse (message.CreateErrorResponse (ex.ToString ())); } }
public void PostMessage (BinaryMessage message) { message.ReadCustomData (); var interceptor = Interceptor; if (interceptor != null && !interceptor.PreProcessMessage (message)) return; PostMessage (message, null, true); }
BinaryMessage LoadMessageData (BinaryMessage msg) { Type type; if (messageTypes.TryGetValue (msg.Name, out type)) { var res = (BinaryMessage)Activator.CreateInstance (type); res.CopyFrom (msg); return res; } return msg; }
public Task<BinaryMessage> SendMessage (BinaryMessage message) { message.ReadCustomData (); var interceptor = Interceptor; if (interceptor != null && !interceptor.PreProcessMessage (message)) return Task.FromResult (message.CreateErrorResponse ("Message was refused by interceptor")); var cs = new TaskCompletionSource<BinaryMessage> (); PostMessage (message, cs, true); return cs.Task; }
public void CopyFrom(BinaryMessage msg) { Id = msg.Id; Name = msg.Name; Target = msg.Target; SentTime = msg.SentTime; OneWay = msg.OneWay; BypassConnection = msg.BypassConnection; ProcessingTime = msg.ProcessingTime; args = new List <BinaryMessageArgument> (msg.args); LoadCustomData(); }
async void ReadMessages() { byte[] buffer = new byte [1]; while (!disposed && connectionStream != null) { BinaryMessage msg; byte type; try { int nr = await connectionStream.ReadAsync(buffer, 0, 1, mainCancelSource.Token).ConfigureAwait(false); if (nr == 0) { // Connection closed. Remote process should die by itself. return; } type = buffer [0]; msg = BinaryMessage.Read(connectionStream); } catch (Exception ex) { if (disposed) { return; } LoggingService.LogError("ReadMessage failed", ex); StopRemoteProcess(isAsync: true); PostSetStatus(ConnectionStatus.ConnectionFailed, "Connection to remote process failed."); return; } lock (pendingMessageTasks) { var t = Task.Run(() => { msg = LoadMessageData(msg); if (type == 0) { ProcessResponse(msg); } else { ProcessRemoteMessage(msg); } }); t.ContinueWith(ta => { lock (pendingMessageTasks) { pendingMessageTasks.Remove(ta); } }).Ignore(); pendingMessageTasks.Add(t); } } }
public void Run() { List <BinaryMessage> messages = new List <BinaryMessage> (); while (true) { BinaryMessage msg; int type; try { type = inStream.ReadByte(); if (type == -1) { break; } msg = BinaryMessage.Read(inStream); msg = LoadMessageData(msg); if (DebugMode) { String mtype = type == MESSAGE_QUEUE_END ? "[M] " : "[Q] "; Console.WriteLine("[SERVER] XS >> RP " + mtype + msg); } } catch (Exception e) { Console.WriteLine(e); break; } if (msg.Name == "Stop" && msg.Target == "Process") { try { WriteMessage(0, msg.CreateResponse()); } catch { // Ignore } break; } if (msg.Name == "Ping" && msg.Target == "Process") { try { WriteMessage(0, msg.CreateResponse()); } catch { // Ignore } continue; } messages.Add(msg); if (type == MESSAGE_QUEUE_END) { ProcessMessages(messages); messages.Clear(); } } }
public void Connect(int port, object processListener, bool debugMode = false) { DebugMode = debugMode; socket = new TcpClient("127.0.0.1", port); outStream = socket.GetStream(); inStream = outStream; AddListener(processListener); Start(); BinaryMessage msg = new BinaryMessage("Connect"); WriteMessage(1, msg); }
void LogMessage (MessageType type, BinaryMessage msg, int time = -1) { Console.Write ("[" + (Environment.TickCount - tickBase) + "] "); if (type == MessageType.Request) Console.WriteLine ("[CLIENT] XS >> RP " + msg); else if (type == MessageType.Response) { if (time != -1) Console.WriteLine ("[CLIENT] XS << RP " + time + "ms " + msg); else Console.WriteLine ("[CLIENT] XS << RP " + msg); } else Console.WriteLine ("[CLIENT] XS <- RP " + msg); }
void NotifyResponse (MessageRequest req, BinaryMessage res) { if (disposed || res == null) { req.TaskSource.SetException (new Exception ("Connection closed")); } else if (res.Name == "Error") { string msg = res.GetArgument<string> ("Message"); if (res.GetArgument<bool> ("IsInternal") && !string.IsNullOrEmpty (msg)) { msg = "The operation failed due to an internal error: " + msg + "."; } req.TaskSource.SetException (new RemoteProcessException (msg) { ExtendedDetails = res.GetArgument<string> ("Log") }); } else { req.TaskSource.SetResult (res); } }
public void WriteMessage(byte type, BinaryMessage msg) { msg.ReadCustomData(); lock (listeners) { if (DebugMode) { Console.WriteLine("[SERVER] XS << RP " + type + " [" + msg.ProcessingTime + "ms] " + msg); } outStream.WriteByte(type); try { msg.Write(outStream); } catch (Exception ex) { msg.CreateErrorResponse(ex.ToString(), true).Write(outStream); } } }
void PingConnection (object state) { bool lockTaken = false; try { Monitor.TryEnter (pingerLock, ref lockTaken); if (!lockTaken) return; var msg = new BinaryMessage ("Ping", "Process"); SendMessage (msg); } catch (Exception ex) { LoggingService.LogError ("Connection ping failed", ex); } finally { if (lockTaken) Monitor.Exit (pingerLock); } }
internal BinaryMessage ProcessMessage(BinaryMessage msg) { MethodInfo m; if (handlers.TryGetValue(msg.Name, out m)) { var r = m.Invoke(target, new object [] { msg }); if (r is BinaryMessage) { return((BinaryMessage)r); } else { return(msg.CreateResponse()); } } return(null); }
void ProcessMessages(List <BinaryMessage> msgs) { foreach (BinaryMessage msg in msgs) { MessageListenerHandler l; lock (listeners) { listeners.TryGetValue(msg.Target ?? "", out l); } if (l != null) { l.DispatchMessage(msg); } else { BinaryMessage response = msg.CreateErrorResponse("No handler found for target: " + msg.Target, true); SendResponse(response); } } }
public static BinaryMessage Read(Stream s) { BinaryReader br = new BinaryReader(s); br.ReadInt32(); // length BinaryMessage msg = new BinaryMessage(); msg.Id = br.ReadInt32(); msg.Name = br.ReadString(); msg.Target = br.ReadString(); int ac = br.ReadInt32(); for (int n = 0; n < ac; n++) { BinaryMessageArgument arg = new BinaryMessageArgument(); arg.Name = br.ReadString(); arg.Value = ReadValue(br); msg.Args.Add(arg); } return(msg); }
public async Task <RT> SendMessage <RT> (BinaryMessage <RT> message) where RT : BinaryMessage { return((RT) await SendMessage((BinaryMessage)message)); }
public void DispatchMessage(BinaryMessage msg) { ThreadPool.QueueUserWorkItem((state) => { ExecuteMessage(msg); }); }
public void SendResponse(BinaryMessage response) { WriteMessage(0, response); }
public void SendMessage(BinaryMessage msg) { WriteMessage(1, msg); }
public void FlushMessages(string target) { var msg = new BinaryMessage("FlushMessages", target); SendMessage(msg); }