Skip to content

Commit 8777171

Browse files
committed
Merge branch 'sxprz-fork/rerun-with-different-params' of https://github.com/sxprz/gobview into sxprz-fork/rerun-with-different-params
2 parents c3dcfab + 6cdcfc9 commit 8777171

23 files changed

+808
-127
lines changed

dune-project

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
(name gobview)
2424
(synopsis "Web frontend for Goblint")
2525
(depends
26+
cohttp
27+
cohttp-lwt
28+
cohttp-lwt-jsoo
2629
dune
2730
(ocaml (>= 4.10.0))
2831
batteries
@@ -37,6 +40,8 @@
3740
ppx_yojson_conv ; TODO: switch to ppx_deriving_yojson like Goblint itself
3841
conduit-lwt-unix
3942
jsoo-react
43+
lwt
44+
uri
4045
(goblint-cil (>= 2.0.0))
4146
ctypes_stubs_js
4247
integers_stubs_js

goblint-http-server/goblint.ml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,7 @@ let config_raw goblint name value =
5757
| Ok _ -> Lwt.return_unit
5858
| Error err -> invalid_arg err.message
5959

60-
let option_whitelist = [] |> Set.of_list
61-
6260
let config goblint name value =
63-
if not (Set.mem name option_whitelist) then
64-
invalid_arg (Printf.sprintf "Option '%s' is not in the whitelist" name);
6561
with_lock goblint (fun () -> config_raw goblint name value)
6662

6763
let temp_dir () = Utils.temp_dir "goblint-http-server." ""

goblint-http-server/goblint_http.ml

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ open Cohttp_lwt
33
open Cohttp_lwt_unix
44
open Lwt.Infix
55

6+
module Header = Cohttp.Header
67
module Yojson_conv = Ppx_yojson_conv_lib.Yojson_conv
78

89
let docroot = ref "run"
910
let index = ref "index.html"
1011
let addr = ref "127.0.0.1"
11-
let port = ref 8080
12+
let port = ref 8000
1213
let goblint = ref "goblint"
1314
let rest = ref []
1415

@@ -24,31 +25,38 @@ let specs =
2425

2526
let paths = ref []
2627

28+
let cors_headers =
29+
[
30+
("Access-Control-Allow-Origin", "*");
31+
("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Allow-Headers");
32+
("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
33+
] |> Header.of_list
34+
2735
let process state name body =
2836
match Hashtbl.find_option Api.registry name with
2937
| None -> Server.respond_not_found ()
3038
| Some (module R) ->
3139
let%lwt body = Body.to_string body in
3240
let body = if body = "" then "null" else body in
3341
match Yojson.Safe.from_string body with
34-
| exception Yojson.Json_error err -> Server.respond_error ~status:`Bad_request ~body:err ()
42+
| exception Yojson.Json_error err -> Server.respond_error ~headers:cors_headers ~status:`Bad_request ~body:err ()
3543
| json ->
3644
match R.body_of_yojson json with
3745
| exception Yojson_conv.Of_yojson_error (exn, _) ->
38-
Server.respond_error ~status:`Bad_request ~body:(Printexc.to_string exn) ()
46+
Server.respond_error ~headers:cors_headers ~status:`Bad_request ~body:(Printexc.to_string exn) ()
3947
| body ->
4048
Lwt.catch
4149
(fun () ->
4250
R.process state body
4351
>|= R.yojson_of_response
4452
>|= Yojson.Safe.to_string
45-
>>= fun body -> Server.respond_string ~status:`OK ~body ())
46-
(fun exn -> Server.respond_error ~status:`Bad_request ~body:(Printexc.to_string exn) ())
53+
>>= fun body -> Server.respond_string ~headers:cors_headers ~status:`OK ~body ())
54+
(fun exn -> Server.respond_error ~headers:cors_headers ~status:`Bad_request ~body:(Printexc.to_string exn) ())
4755

4856
(* The serving of files is implemented similar as in the binary https://github.com/mirage/ocaml-cohttp/blob/master/cohttp-lwt-unix/bin/cohttp_server_lwt.ml *)
4957
let serve_file ~docroot ~uri =
5058
let fname = Cohttp.Path.resolve_local_file ~docroot ~uri in
51-
Server.respond_file ~fname ()
59+
Server.respond_file ~headers:cors_headers ~fname ()
5260

5361
let sort lst =
5462
let compare_kind = function
@@ -102,7 +110,7 @@ let serve uri path =
102110
| Unix.S_DIR -> (
103111
let path_len = String.length path in
104112
if path_len <> 0 && path.[path_len - 1] <> '/' then (
105-
Server.respond_redirect ~uri:(Uri.with_path uri (path ^ "/")) ())
113+
Server.respond_redirect ~headers:cors_headers ~uri:(Uri.with_path uri (path ^ "/")) ())
106114
else (
107115
match Sys.file_exists (Filename.concat file_name !index) with
108116
| true -> (
@@ -122,12 +130,12 @@ let serve uri path =
122130
f ))
123131
(fun _exn -> Lwt.return (None, f))) files in
124132
let body = html_of_listing uri path (sort listing) in
125-
Server.respond_string ~status:`OK ~body ()))
133+
Server.respond_string ~headers:cors_headers ~status:`OK ~body ()))
126134
| Unix.S_REG -> serve_file ~docroot:!docroot ~uri
127135
| _ -> (
128136
let body = Printf.sprintf "<html><body><h2>Forbidden</h2><p><b>%s</b> is not a normal file or \
129137
directory</p><hr/></body></html>" path in
130-
Server.respond_string ~status:`OK ~body ()))
138+
Server.respond_string ~headers:cors_headers ~status:`OK ~body ()))
131139
(function
132140
| Unix.Unix_error (Unix.ENOENT, "stat", p) as e ->
133141
if p = file_name then (
@@ -143,6 +151,7 @@ let callback state _ req body =
143151
match meth, parts with
144152
| `POST, ["api"; name] -> process state name body
145153
| `GET, _ -> serve uri path
154+
| `OPTIONS, _ -> Server.respond ~headers:cors_headers ~status:`OK ~body:`Empty () (* Used for preflight and CORS requests *)
146155
| _ -> Server.respond_not_found ()
147156

148157
let main () =

gobview.opam

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ license: "MIT"
1212
homepage: "https://github.com/goblint/gobview"
1313
bug-reports: "https://github.com/goblint/gobview/issues"
1414
depends: [
15+
"cohttp"
16+
"cohttp-lwt"
17+
"cohttp-lwt-jsoo"
1518
"dune" {>= "2.7"}
1619
"ocaml" {>= "4.10.0"}
1720
"batteries"
@@ -26,6 +29,8 @@ depends: [
2629
"ppx_yojson_conv"
2730
"conduit-lwt-unix"
2831
"jsoo-react"
32+
"lwt"
33+
"uri"
2934
"goblint-cil" {>= "2.0.0"}
3035
"ctypes_stubs_js"
3136
"integers_stubs_js"

package-lock.json

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/App.re

Lines changed: 3 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,100 +1,12 @@
1-
open Goblint_lib;
2-
open Batteries;
3-
open Js_of_ocaml;
41
open Lwt.Infix;
5-
module Cabs2cil = GoblintCil.Cabs2cil;
6-
7-
exception InitFailed(string);
8-
9-
let init_cil = environment => {
10-
// Restore the environment hash table, which
11-
// syntacticsearch uses to map temporary variables created
12-
// by CIL to their original counterparts.
13-
Hashtbl.clear(Cabs2cil.environment);
14-
environment
15-
|> Hashtbl.enum
16-
|> Enum.iter(((k, v)) => Hashtbl.add(Cabs2cil.environment, k, v));
17-
};
18-
19-
// Each Goblint analysis module is assigned an ID, and this
20-
// ID depends on the module registration order, which might
21-
// differ from build to build. This function reorders the
22-
// analysis list to match the native version of Goblint.
23-
let renumber_goblint_analyses = registered_name => {
24-
let old_registered = Hashtbl.copy(MCP.registered);
25-
let old_registered_name = Hashtbl.copy(MCP.registered_name);
26-
Hashtbl.clear(MCP.registered);
27-
Hashtbl.clear(MCP.registered_name);
28-
Hashtbl.iter((name, id) => {
29-
let old_id = Hashtbl.find(old_registered_name, name);
30-
let spec = Hashtbl.find(old_registered, old_id);
31-
Hashtbl.replace(MCP.registered, id, spec);
32-
Hashtbl.replace(MCP.registered_name, name, id);
33-
}, registered_name);
34-
};
35-
36-
let init_goblint = (solver, spec, registered_name, config, cil) => {
37-
AfterConfig.run(); // This registers the "base" analysis
38-
39-
try(renumber_goblint_analyses(registered_name)) {
40-
| Not_found =>
41-
raise(InitFailed("Failed to renumber Goblint analyses"))
42-
};
43-
44-
Sys.chdir("/"); // Don't remove this
45-
46-
Sys_js.create_file(~name="/goblint/solver.marshalled", ~content=solver);
47-
Sys_js.create_file(~name="/goblint/config.json", ~content=config);
48-
Sys_js.create_file(~name="/goblint/spec_marshal", ~content=spec);
49-
50-
GobConfig.merge_file(Fpath.v("/goblint/config.json"));
51-
52-
GobConfig.set_bool("dbg.verbose", true);
53-
// TODO: Uncomment this to improve performance in future
54-
// GobConfig.set_bool("verify", false);
55-
56-
// For some reason, the standard Batteries output channels
57-
// appear to be closed by default and writing to them
58-
// raises [BatInnerIO.Output_closed]. This fixes it.
59-
let out = IO.output_channel(Stdlib.stdout);
60-
Messages.formatter := Format.formatter_of_output(out);
61-
62-
GobConfig.set_string("load_run", "goblint");
63-
64-
// These two will be set by config.json. Reset them.
65-
GobConfig.set_string("save_run", "");
66-
GobConfig.set_bool("gobview", false);
67-
68-
GobConfig.set_auto("trans.activated[+]", "'expeval'");
69-
70-
Cilfacade.init();
71-
Maingoblint.handle_extraspecials();
72-
Maingoblint.handle_flags();
73-
74-
// NOTE: Commenting this out since it breaks the node view. Semantic search
75-
// may depend on this code but it is currently broken because of unrelated
76-
// (and uknown) reasons anyway.
77-
// Cil.iterGlobals(cil, glob =>
78-
// switch (glob) {
79-
// | GFun(fd, _) =>
80-
// Cil.prepareCFG(fd);
81-
// Cil.computeCFGInfo(fd, true);
82-
// | _ => ()
83-
// }
84-
// );
85-
Cilfacade.current_file := cil;
86-
87-
let goblint = GvGoblint.unmarshal(spec, cil);
88-
89-
(goblint, cil);
90-
};
2+
open Init;
913

924
let init = (solver, spec, config, meta, cil, analyses, warnings, stats, file_loc) => {
935
let cil =
946
switch (cil) {
957
| Ok(s) =>
968
let (c, e) = Marshal.from_string(s, 0);
97-
init_cil(e);
9+
Init.init_cil(e);
9810
c;
9911
| _ => raise(InitFailed("Failed to load CIL state"))
10012
};
@@ -172,6 +84,6 @@ let handle_error = exc => {
17284
| exc => handle_error(exc)
17385
}
17486
| _ => ()
175-
},
87+
}
17688
)
17789
);

0 commit comments

Comments
 (0)