/// <summary> /// Start a web socket server on a different thread, modifying /// the given interpreter to use it. /// </summary> /// <param name="current">Current interpreter</param> public static Thread WSServeThread(Interpreter current) { var ws = new Grace.Execution.WebSocketServer(); var wss = ws.Start(); var runningThread = Thread.CurrentThread; var runningSink = new WSOutputSink(wss); current.RPCSink = runningSink; wss.JsonReceived += (o, e) => { var je = (JsonWSEvent)e; var root = je.Root; var md = root.XPathSelectElement("//mode"); var mode = md.Value; if (mode == "stop") { Console.WriteLine("Program stopped on remote end."); runningSink.Stop(); runningSink.HardStop(); wss.Stop(); WebSocketEndpoint.Stop(); return; } else if (mode == "response") { processResponse(root); return; } else if (mode == "callback") { if (runningThread != null) { processCallback(root, runningSink); } return; } else if (mode == "ack") { return; } else { Console.WriteLine("unknown mode " + mode); } }; var thread = new Thread(() => { wss.Run(); }); thread.Start(); return(thread); }
private static int replyParseTree(ParseNode module, string modname, WSOutputSink sink) { Action <XmlDocument, XmlElement> handler = (doc, parent) => { var mod = doc.CreateElement("module"); var vis = new ParseTreeJSONVisitor(doc, mod); parent.AppendChild(module.Visit(vis)); }; sink.SendData("parse-tree", modname, handler); return(0); }
private static void processCallback(XElement root, WSOutputSink sink) { var blockEl = root.XPathSelectElement("//block"); if (blockEl == null) { return; } int blockID; int.TryParse(blockEl.Value, out blockID); var argsEl = root.XPathSelectElement("//args"); var argsEnum = argsEl.XPathSelectElements("//item"); var args = new object[argsEnum.Count()]; int i = 0; foreach (var arg in argsEnum) { args[i] = objectFromElement(arg); } sink.ReceiveCallback(blockID, args); }
private static int runModule(string code, string modname, string mode, WSOutputSink sink) { var interp = new Interpreter(sink); ErrorReporting.SetSink(new OutputSinkWrapper(Console.Error)); interp.RPCSink = sink; interp.AddModuleRoot(Path.GetFullPath(".")); interp.FailedImportHook = loadCachedModule; interp.LoadPrelude(); Parser parser = new Parser(modname, code); ParseNode module; try { module = parser.Parse(); ExecutionTreeTranslator ett = new ExecutionTreeTranslator(); Node eModule = ett.Translate(module as ObjectParseNode); sink.SendEvent("build-succeeded", modname); if (mode == "build") { return(0); } interp.EnterModule(modname); try { eModule.Evaluate(interp); } catch (GraceExceptionPacketException ex) { sink.SendRuntimeError(ex.ExceptionPacket.Description, ex.ExceptionPacket.StackTrace); } } catch (StaticErrorException ex) { sink.SendStaticError(ex.Code, ex.Module, ex.Line, ex.Message); } catch (ThreadAbortException) { throw; } catch (WebSocketClosedException) { return(0); } catch (Exception ex) { System.Console.Error.WriteLine( "An internal error occurred. " + "Debugging information follows."); System.Console.Error.WriteLine("Runtime version: " + Interpreter.GetRuntimeVersion()); System.Console.Error.WriteLine(ex); System.Console.Error.WriteLine(ex.StackTrace); System.Console.Error.WriteLine( "\nAn internal error occurred. " + "This is a bug in the implementation."); } sink.SendEvent("execution-complete", modname); return(0); }
/// <summary> /// Start a WebSocket server. /// </summary> public static int WSServe() { var ws = new Grace.Execution.WebSocketServer(); var wss = ws.Start(); Thread runningThread = null; WSOutputSink runningSink = null; while (true) { wss.JsonReceived += (o, e) => { var je = (JsonWSEvent)e; var root = je.Root; var md = root.XPathSelectElement("//mode"); var mode = md.Value; if (mode == "stop") { if (runningThread != null) { runningSink.Stop(); runningThread.Abort(); runningThread = null; runningSink = null; } return; } else if (mode == "response") { processResponse(root); return; } else if (mode == "callback") { if (runningThread != null) { processCallback(root, runningSink); } return; } else if (mode == "ack") { return; } else if (mode != "build" && mode != "run") { return; } var cn = root.XPathSelectElement("//code"); var mn = root.XPathSelectElement("//modulename"); var code = cn.Value; var modname = mn.Value; moduleCode[modname] = code; var sink = new WSOutputSink(wss); runningSink = sink; var thread = new Thread(() => { var startSent = wss.SentFrames; var startReceived = wss.ReceivedFrames; var startTime = DateTime.Now; try { runModule(code, modname, mode, sink); log("Module " + modname + " completed " + mode + "."); runningThread = null; summarise(wss, startSent, startReceived, DateTime.Now - startTime); } catch (WebSocketClosedException) { log("Lost WebSocket connection " + "while running module " + modname + "."); runningThread = null; summarise(wss, startSent, startReceived, DateTime.Now - startTime); } catch (ThreadAbortException) { log("Execution of " + modname + " aborted."); Thread.ResetAbort(); summarise(wss, startSent, startReceived, DateTime.Now - startTime); } }); runningThread = thread; log("Spawning thread to " + mode + " " + modname + "..."); thread.Start(); }; wss.Run(); wss = ws.Next(); } }