public static Exception VmUserDefinedPrimitiveError(Shovel.Vm.Vm vm) { return(vm.UserDefinedPrimitiveError); }
public static void Client() { Console.WriteLine("***"); var program = @" // Setting up the call on the client. var sourceAccountNo = @getSourceAccountNo() var destinationAccountNo = @getDestinationAccountNo() var amount = @getAmount() // Go to the server. @goToServer() // Run the code on the server (the code on the server will wrap // the code between 'goToServer' and 'goToClient' in a transaction) . @subtractFromAccount(sourceAccountNo, amount) @addToAccount(destinationAccountNo, amount) var transactionDeadline = @getTransactionDeadline() // Go back to the client. @goToClient() // Handle the results on the client. @setTransactionDeadline(transactionDeadline) "; var sources = Shovel.Api.MakeSources("request.sho", program); var bytecode = Shovel.Api.GetBytecode(sources); // Run on the client to fill in request data. Shovel.Vm.Vm vm = null; TimeIt("client - initialization", () => { vm = Shovel.Api.RunVm(bytecode, sources, Udps()); } ); var serializedBytecode = Shovel.Api.SerializeBytecode(bytecode); var serializedState = Shovel.Api.SerializeVmState(vm); byte[] requestBytes = null; using (var ms = new MemoryStream()) { byte[] bytes = new byte[4]; bytes = BitConverter.GetBytes(serializedBytecode.Length); ms.Write(bytes, 0, bytes.Length); var sourceBytes = Encoding.UTF8.GetBytes(program); bytes = BitConverter.GetBytes(sourceBytes.Length); ms.Write(bytes, 0, bytes.Length); bytes = BitConverter.GetBytes(serializedState.Length); ms.Write(bytes, 0, bytes.Length); ms.Write(serializedBytecode, 0, serializedBytecode.Length); ms.Write(sourceBytes, 0, sourceBytes.Length); ms.Write(serializedState, 0, serializedState.Length); requestBytes = ms.ToArray(); } byte[] responseBytes = null; // Send the Shovel process to the server. TimeIt("server", () => { using (var wc = new WebClient()) { responseBytes = wc.UploadData("http://localhost:8080/", requestBytes); } } ); // Extract the new state of the Shovel process from the HTTP response. byte[] serializedServerState = null; using (var ms = new MemoryStream(responseBytes)) { byte[] bytes = new byte[4]; ms.Read(bytes, 0, 4); int serverStateLength = BitConverter.ToInt32(bytes, 0); serializedServerState = new byte[serverStateLength]; ms.Read(serializedServerState, 0, serializedServerState.Length); } // Run again on the client to extract the data from the program. TimeIt("client - postprocess", () => { Shovel.Api.RunVm(bytecode, sources, Udps(), serializedServerState); } ); }
public static ShovelException VmProgrammingError(Shovel.Vm.Vm vm) { return(vm.ProgrammingError); }
public static void Main(string[] args) { if (!HttpListener.IsSupported) { Console.WriteLine("HttpListener not available."); Environment.Exit(-1); } HttpListener hl = new HttpListener(); hl.Prefixes.Add("http://localhost:8080/"); hl.Start(); while (hl.IsListening) { var ctx = hl.GetContext(); Console.WriteLine("Serving a request ({0}).", ctx.Request.Url.AbsolutePath); if (ctx.Request.Url.AbsolutePath == "/") { byte[] bytes = new byte[4]; byte[] state = null; string program = null; byte[] bytecode = null; TimeIt("read request", () => { ctx.Request.InputStream.Read(bytes, 0, bytes.Length); int bytecodeLength = BitConverter.ToInt32(bytes, 0); ctx.Request.InputStream.Read(bytes, 0, bytes.Length); int sourcesLength = BitConverter.ToInt32(bytes, 0); ctx.Request.InputStream.Read(bytes, 0, bytes.Length); int stateLength = BitConverter.ToInt32(bytes, 0); bytecode = new byte[bytecodeLength]; ctx.Request.InputStream.Read(bytecode, 0, bytecode.Length); byte[] sourceBytes = new byte[sourcesLength]; ctx.Request.InputStream.Read(sourceBytes, 0, sourceBytes.Length); program = Encoding.UTF8.GetString(sourceBytes); state = new byte[stateLength]; ctx.Request.InputStream.Read(state, 0, state.Length); } ); // To execute the ShovelScript code between // @goToServer and @goToClient in a DB transaction, // just wrap this call in a DB transaction. Shovel.Vm.Vm vm = null; TimeIt("server", () => { vm = Shovel.Api.RunVm( Shovel.Api.DeserializeBytecode(bytecode), Shovel.Api.MakeSources("request.sho", program), Udps(), state); } ); // In a real application, we should check the values returned by // Shovel.Api.VmProgrammingError and Shovel.Api.VmUserDefinedPrimitiveError // and return something else based on the presence/absence of errors. // In a normal context, you must set quotas for RAM and CPU when calling RunVm (so a single // broken/malicious request doesn't bring down the whole server). This is not // done here to keep things simple. // This is accomplished using the RunVm 'totalTicksQuota' and 'usedCellsQuota' parameters. // Using 'ticksUntilNextNapQuota' should also be used to protect against infinite loops. byte[] stateAfter = null; TimeIt("serialize state", () => { stateAfter = Shovel.Api.SerializeVmState(vm); } ); TimeIt("write response", () => { bytes = BitConverter.GetBytes(stateAfter.Length); ctx.Response.OutputStream.Write(bytes, 0, bytes.Length); ctx.Response.OutputStream.Write(stateAfter, 0, stateAfter.Length); } ); } ctx.Response.OutputStream.Close(); Console.WriteLine("Finished serving request."); } }