diff --git a/sw/ground_segment/tmtc/server.ml b/sw/ground_segment/tmtc/server.ml index 6203cdfa9f..374a191c43 100644 --- a/sw/ground_segment/tmtc/server.ml +++ b/sw/ground_segment/tmtc/server.ml @@ -26,6 +26,7 @@ let my_id = "ground" let gps_mode_3D = 3 +let no_md5_check = ref false open Printf open Latlong @@ -36,6 +37,7 @@ module LL = Latlong module Ground = struct let name = "ground" end module Ground_Pprz = Pprz.Messages(Ground) +module Tm_Pprz = Pprz.Messages (struct let name = "telemetry" end) module Alerts_Pprz = Pprz.Messages(struct let name = "alert" end) module Dl_Pprz = Pprz.Messages (struct let name = "datalink" end) @@ -413,16 +415,44 @@ let get_conf = fun real_id id conf_xml -> Hashtbl.add unknown_aircrafts real_id (); failwith (sprintf "Error: A/C '%s' not found" id) +let check_md5sum = fun ac_name alive_md5sum aircraft_conf_dir -> + (* Read the digest generated by sw/tools/gen_aircraft *) + let f = open_in (aircraft_conf_dir // "aircraft.md5") in + let md5sum = input_line f in + close_in f; + + try + match alive_md5sum with + Pprz.Array array -> + let n = Array.length array in + assert(n = String.length md5sum / 2); + for i = 0 to n - 1 do + let x = int_of_string (sprintf "0x%c%c" md5sum.[2*i] md5sum.[2*i+1]) in + assert (x = Pprz.int_of_value array.(i)) + done + | _ -> failwith "Array expected here" + with _ -> + let error_message = sprintf "WARNING: live md5 signature for %s does not match current configuration, please reload your code (disable check with -no_md5_check option)" ac_name in + if !no_md5_check then + fprintf stderr "%s; continuing anyway as requested\n%!" error_message + else + failwith error_message + -let new_aircraft = fun real_id -> +let new_aircraft = fun alive_md5sum real_id -> let id, root_dir, conf_xml = replayed real_id in let conf = get_conf real_id id conf_xml in let ac_name = ExtXml.attrib conf "name" in - let fp_file = Env.paparazzi_home // root_dir // "var" // ac_name // "flight_plan.xml" in + let var_aircraft_dir = Env.paparazzi_home // root_dir // "var" // ac_name in + + let fp_file = var_aircraft_dir // "flight_plan.xml" in let xml_fp = ExtXml.child (Xml.parse_file fp_file) "flight_plan" in - let airframe_file = Env.paparazzi_home // root_dir // "conf" // ExtXml.attrib conf "airframe" in + let aircraft_conf_dir = var_aircraft_dir // "conf" in + let airframe_file = aircraft_conf_dir // ExtXml.attrib conf "airframe" in let airframe_xml = Xml.parse_file airframe_file in + + check_md5sum real_id alive_md5sum aircraft_conf_dir; let ac = Aircraft.new_aircraft real_id ac_name xml_fp airframe_xml in let update = fun () -> @@ -507,11 +537,12 @@ let register_aircraft = fun name a -> (** Identifying message from an A/C *) -let ident_msg = fun log name -> +let ident_msg = fun log name vs -> try if not (Hashtbl.mem aircrafts name) && not (Hashtbl.mem unknown_aircrafts name) then - let ac, messages_xml = new_aircraft name in + let md5sum = Pprz.assoc "md5sum" vs in + let ac, messages_xml = new_aircraft md5sum name in let ac_msg_closure = ac_msg messages_xml log name ac in let _b = Ivy.bind (fun _ args -> ac_msg_closure args.(0)) (sprintf "^%s +(.*)" name) in register_aircraft name ac; @@ -525,8 +556,7 @@ let new_color = fun () -> (* Waits for new aircrafts *) let listen_acs = fun log -> (** Wait for any message (they all are identified with the A/C) *) - ignore (Ivy.bind (fun _ args -> ident_msg log args.(0)) "^(.*) ALIVE"); - ignore (Ivy.bind (fun _ args -> ident_msg log args.(0)) "^(.*) PPRZ_MODE") + ignore (Tm_Pprz.message_bind "ALIVE" (ident_msg log)) let send_config = fun http _asker args -> @@ -559,7 +589,7 @@ let send_config = fun http _asker args -> "ac_name", Pprz.String ac_name ] with Not_found -> - failwith (sprintf "ground UNKNOWN %s" ac_id') + failwith (sprintf "ground UNKNOWN %s" ac_id') let ivy_server = fun http -> ignore (Ground_Pprz.message_answerer my_id "AIRCRAFTS" send_aircrafts_msg); @@ -629,11 +659,12 @@ let _ = let options = [ "-b", Arg.String (fun x -> ivy_bus := x), (sprintf "Bus\tDefault is %s" !ivy_bus); - "-n", Arg.Clear logging, "Disable log"; + "-hostname", Arg.Set_string hostname, " Set the address for the http server"; + "-http", Arg.Set http, "Send http: URLs (default is file:)"; "-kml", Arg.Set Kml.enabled, "Enable KML file updating"; "-kml_port", Arg.Set_int Kml.port, (sprintf "Port for KML files (default is %d)" !Kml.port); - "-hostname", Arg.Set_string hostname, " Set the address for the http server"; - "-http", Arg.Set http, "Send http: URLs (default is file:)"] in + "-n", Arg.Clear logging, "Disable log"; + "-no_md5_check", Arg.Set no_md5_check, "Disable safety matching of live and current configurations"] in Arg.parse (options) (fun x -> Printf.fprintf stderr "%s: Warning: Don't do anything with '%s' argument\n" Sys.argv.(0) x) "Usage: "; diff --git a/sw/tools/gen_aircraft.ml b/sw/tools/gen_aircraft.ml index 337aaab74d..2c0e011c87 100644 --- a/sw/tools/gen_aircraft.ml +++ b/sw/tools/gen_aircraft.ml @@ -92,6 +92,10 @@ let _ = close_out f; let md5sum = Digest.to_hex (Digest.file conf_aircraft_file) in + let md5sum_file = aircraft_conf_dir // "aircraft.md5" in + let f = open_out md5sum_file in + Printf.fprintf f "%s\n" md5sum; + close_out f; let c = sprintf "make -f Makefile.ac AIRCRAFT=%s AC_ID=%s AIRFRAME_XML=%s RADIO=%s FLIGHT_PLAN=%s TELEMETRY=%s SETTINGS=\"%s\" MD5SUM=\"%s\" all_ac_h" aircraft (value "ac_id") (value "airframe") (value "radio") (value "flight_plan") (value "telemetry") settings md5sum in begin (** Quiet is speficied in the Makefile *)