Beispiel #1
0
        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);
            }
        }
Beispiel #2
0
        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);
            }
        }
Beispiel #3
0
        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();
                    });
                }
            }
        }
Beispiel #4
0
        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);
            }
        }
Beispiel #5
0
            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;
		}
Beispiel #11
0
 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();
                }
            }
        }
Beispiel #14
0
        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);
			}
		}
Beispiel #17
0
 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);
			}
		}
Beispiel #19
0
        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);
        }
Beispiel #20
0
        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);
                }
            }
        }
Beispiel #21
0
        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);
        }
Beispiel #22
0
 public async Task <RT> SendMessage <RT> (BinaryMessage <RT> message) where RT : BinaryMessage
 {
     return((RT) await SendMessage((BinaryMessage)message));
 }
Beispiel #23
0
 public void DispatchMessage(BinaryMessage msg)
 {
     ThreadPool.QueueUserWorkItem((state) => { ExecuteMessage(msg); });
 }
Beispiel #24
0
 public void SendResponse(BinaryMessage response)
 {
     WriteMessage(0, response);
 }
Beispiel #25
0
 public void SendMessage(BinaryMessage msg)
 {
     WriteMessage(1, msg);
 }
Beispiel #26
0
        public void FlushMessages(string target)
        {
            var msg = new BinaryMessage("FlushMessages", target);

            SendMessage(msg);
        }